Something went wrong. Try again.
source dump of claude code forked from oppi.li/claude-code
Something went wrong. Try again.
4.3 kB · 167 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168import { mkdir, open } from 'fs/promises'import { join } from 'path'import { getSessionId } from '../bootstrap/state.js'import type { PastedContent } from './config.js'import { logForDebugging } from './debug.js'import { getClaudeConfigHomeDir } from './envUtils.js'import { getFsImplementation } from './fsOperations.js'
const IMAGE_STORE_DIR = 'image-cache'const MAX_STORED_IMAGE_PATHS = 200
// In-memory cache of stored image pathsconst storedImagePaths = new Map<number, string>()
/** * Get the image store directory for the current session. */function getImageStoreDir(): string { return join(getClaudeConfigHomeDir(), IMAGE_STORE_DIR, getSessionId())}
/** * Ensure the image store directory exists. */async function ensureImageStoreDir(): Promise<void> { const dir = getImageStoreDir() await mkdir(dir, { recursive: true })}
/** * Get the file path for an image by ID. */function getImagePath(imageId: number, mediaType: string): string { const extension = mediaType.split('/')[1] || 'png' return join(getImageStoreDir(), `${imageId}.${extension}`)}
/** * Cache the image path immediately (fast, no file I/O). */export function cacheImagePath(content: PastedContent): string | null { if (content.type !== 'image') { return null } const imagePath = getImagePath(content.id, content.mediaType || 'image/png') evictOldestIfAtCap() storedImagePaths.set(content.id, imagePath) return imagePath}
/** * Store an image from pastedContents to disk. */export async function storeImage( content: PastedContent,): Promise<string | null> { if (content.type !== 'image') { return null }
try { await ensureImageStoreDir() const imagePath = getImagePath(content.id, content.mediaType || 'image/png') const fh = await open(imagePath, 'w', 0o600) try { await fh.writeFile(content.content, { encoding: 'base64' }) await fh.datasync() } finally { await fh.close() } evictOldestIfAtCap() storedImagePaths.set(content.id, imagePath) logForDebugging(`Stored image ${content.id} to ${imagePath}`) return imagePath } catch (error) { logForDebugging(`Failed to store image: ${error}`) return null }}
/** * Store all images from pastedContents to disk. */export async function storeImages( pastedContents: Record<number, PastedContent>,): Promise<Map<number, string>> { const pathMap = new Map<number, string>()
for (const [id, content] of Object.entries(pastedContents)) { if (content.type === 'image') { const path = await storeImage(content) if (path) { pathMap.set(Number(id), path) } } }
return pathMap}
/** * Get the file path for a stored image by ID. */export function getStoredImagePath(imageId: number): string | null { return storedImagePaths.get(imageId) ?? null}
/** * Clear the in-memory cache of stored image paths. */export function clearStoredImagePaths(): void { storedImagePaths.clear()}
function evictOldestIfAtCap(): void { while (storedImagePaths.size >= MAX_STORED_IMAGE_PATHS) { const oldest = storedImagePaths.keys().next().value if (oldest !== undefined) { storedImagePaths.delete(oldest) } else { break } }}
/** * Clean up old image cache directories from previous sessions. */export async function cleanupOldImageCaches(): Promise<void> { const fsImpl = getFsImplementation() const baseDir = join(getClaudeConfigHomeDir(), IMAGE_STORE_DIR) const currentSessionId = getSessionId()
try { let sessionDirs try { sessionDirs = await fsImpl.readdir(baseDir) } catch { return }
for (const sessionDir of sessionDirs) { if (sessionDir.name === currentSessionId) { continue }
const sessionPath = join(baseDir, sessionDir.name) try { await fsImpl.rm(sessionPath, { recursive: true, force: true }) logForDebugging(`Cleaned up old image cache: ${sessionPath}`) } catch { // Ignore errors for individual directories } }
try { const remaining = await fsImpl.readdir(baseDir) if (remaining.length === 0) { await fsImpl.rmdir(baseDir) } } catch { // Ignore } } catch { // Ignore errors reading base directory }}