# DOX — packages/image-fit-extension/src

Files in this directory. One row per source file.

| File | Purpose |
|------|---------|
| `cache.ts` | SHA-256 temp-file cache under `os.tmpdir()/pi-image-fit/<session>/`. Exports `ROOT_DIR`, `cacheKey({absPath,mtimeMs,maxEdge,maxBytes,quality})`, `scopeFor(sessionScope)` (sanitizes `[^A-Za-z0-9_-]` → `_`, collapses runs, trims, falls back to `default`), `ensureDir`, `hasCached`, `cleanupSession`, `cleanupOrphans` (24 h sweep, injectable clock). Also exports the context-seam in-memory content cache: `ContentCache` (bounded LRU, `keyFor(base64,mimeType,{maxEdge,maxBytes,quality})` SHA-256, `get`/`set`/`has`, byte-budget eviction, `bytes`/`size` observability) + `DEFAULT_CONTENT_CACHE_BUDGET` (64 MiB); never touches disk. See change: image-fit-tool-result-images. |
| `extension.ts` | Pi extension entry. Seam 1 `pi.on("tool_call")` gated on `toolName === "read"` + `isImagePath(input.path)`; try/catch fall-through, `session_shutdown` → `cleanupSession`, `cleanupOrphans()` once on load, one telemetry `console.log` per resize. Seam 2 `pi.on("context")` (guarded by `!config.disabled`) → `fitContextMessages(messages, config, ContentCache)` (exported): role-agnostic block walk, `Array.isArray(content)` guard, cheap header-probe gate → hash → cache → `resizeBuffer` on miss, mutates block `data`/`mimeType` in place, returns `{messages}` only on change else `undefined`; per-block try/catch fail-open (one WARN per bad block). `PI_IMAGE_FIT_DISABLE=1` skips BOTH seams. See change: image-fit-tool-result-images. |
| `policy.ts` | Exports `readConfigFromEnv(): { disabled, maxEdge, maxBytes, quality }`. Env vars `PI_IMAGE_FIT_DISABLE` / `PI_IMAGE_FIT_MAX_EDGE` / `PI_IMAGE_FIT_MAX_BYTES` / `PI_IMAGE_FIT_QUALITY`. Defaults 1568 / 4194304 / 85. Invalid values fall back to default + emit one `[pi-image-fit] WARN ` line naming the variable. See change: pi-image-fit-extension. |
| `resize.ts` | File-path helpers: `needsResize({bytes,maxBytes,dims,maxEdge})` predicate (long edge OR bytes), `outputFormatFor(srcPath)` (PNG-in → PNG-out, else JPEG), `isImagePath` regex `.png/.jpe?g/.webp/.gif`, `probeDims` (jimp lazy load), `resizeToFile` (long-edge `scaleToFit({w:maxEdge,h:maxEdge})`, `getBuffer(JimpMime.png|jpeg,{quality})`). Buffer helpers (context seam): `estimateBytesFromBase64` (no decode), `probeDimsFromHeader(buf)` (PNG IHDR / JPEG SOF / WEBP VP8X·VP8·VP8L / GIF logical-screen, null on unparseable), `probeDimsFromBuffer(buf)` (jimp fallback), `outputFormatForMime(mime)` (`image/png`→png else jpeg), `resizeBuffer(buf,opts,"png"|"jpeg")` → `{data:Buffer,dims}` (no temp file). jimp only, no native deps. See change: image-fit-tool-result-images. |
