diff options
| author | Adam Malczewski <[email protected]> | 2026-06-27 20:06:47 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-06-27 20:06:47 +0900 |
| commit | 2e741d1c1ac309327aff4fed0e248bc5baa342d4 (patch) | |
| tree | fb84708f55e07572e4c69447884365d9b457755c /packages/session-orchestrator/src | |
| parent | 2c91dc63802a386b1612ea0ed8c1e96b6f4421db (diff) | |
| download | dispatch-2e741d1c1ac309327aff4fed0e248bc5baa342d4.tar.gz dispatch-2e741d1c1ac309327aff4fed0e248bc5baa342d4.zip | |
feat(vision): store images in tmp dir instead of SQLite — compact URLs + purge on compaction/close
Diffstat (limited to 'packages/session-orchestrator/src')
| -rw-r--r-- | packages/session-orchestrator/src/orchestrator.ts | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/packages/session-orchestrator/src/orchestrator.ts b/packages/session-orchestrator/src/orchestrator.ts index c0493f3..045b88d 100644 --- a/packages/session-orchestrator/src/orchestrator.ts +++ b/packages/session-orchestrator/src/orchestrator.ts @@ -49,6 +49,20 @@ import type { ToolAssembly } from "./tools-filter.js"; * call `consult_vision`) and the images are registered for tool access. */ export interface VisionHandoffService { + /** + * Store images to tmp files and return compact URLs. Each input image's data + * URL is saved to a tmp file and replaced with a compact HTTP path so the + * persisted conversation store holds a tiny string, not megabytes of base64. + * When `saveImageToTmp` is not configured, data URLs pass through unchanged. + */ + readonly storeImages: ( + conversationId: string, + images: readonly ImageInput[], + ) => Promise<readonly ImageInput[]>; + + /** Delete all tmp images for a conversation (on close). Best-effort. */ + readonly purgeConversationImages: (conversationId: string) => Promise<void>; + readonly prepareForProvider: ( messages: readonly ChatMessage[], currentModelName: string | undefined, @@ -625,7 +639,18 @@ export function createSessionOrchestrator( const effectiveModelName = resolveModelName(modelName, storedModel); const history = await deps.conversationStore.load(conversationId); - const userMsg = buildUserMessage(text, images); + + // Store images to tmp files (compact URLs) BEFORE building the user + // message so the persisted chunks hold tiny URL references, not + // megabytes of base64 data URLs. When the vision-handoff service isn't + // loaded, images pass through unchanged (backward compatible). + const visionHandoffForStore = deps.resolveVisionHandoff?.(); + const storedImages = + visionHandoffForStore !== undefined && images !== undefined + ? await visionHandoffForStore.storeImages(conversationId, images) + : images; + + const userMsg = buildUserMessage(text, storedImages); // Workspace assignment for new conversations happens BEFORE // effective-cwd resolution (see workspaceSetupPromise above) so @@ -988,6 +1013,9 @@ export function createSessionOrchestrator( }); }); void deps.conversationStore.setConversationStatus(conversationId, "closed"); + // Purge tmp images for this conversation (best-effort, fire-and-forget). + const vh = deps.resolveVisionHandoff?.(); + if (vh !== undefined) void vh.purgeConversationImages(conversationId); return { abortedTurn }; }, |
