diff --git a/src/app/api/chat/route.ts b/src/app/api/chat/route.ts index a557c88..0d65a35 100644 --- a/src/app/api/chat/route.ts +++ b/src/app/api/chat/route.ts @@ -149,7 +149,7 @@ export async function POST(request: NextRequest) { name: f.name, type: f.type, size: f.size, - data: meta?.filePath ? '' : f.data, // Skip base64 data if file is already saved to disk + data: (meta?.filePath && !f.type.startsWith('image/')) ? '' : f.data, // Keep base64 for images (needed for vision); clear for non-images (read from disk) filePath: meta?.filePath, }; }) @@ -189,6 +189,7 @@ export async function POST(request: NextRequest) { abortController, permissionMode, files: fileAttachments, + imageAgentMode: !!systemPromptAppend, toolTimeoutSeconds: toolTimeout || 300, provider: resolvedProvider, conversationHistory: historyMsgs, diff --git a/src/lib/claude-client.ts b/src/lib/claude-client.ts index 5ab38af..c623af2 100644 --- a/src/lib/claude-client.ts +++ b/src/lib/claude-client.ts @@ -279,6 +279,7 @@ export function streamClaude(options: ClaudeStreamOptions): ReadableStream({ @@ -612,14 +613,21 @@ export function streamClaude(options: ClaudeStreamOptions): ReadableStream 0) { - // Append image disk paths to the text prompt so Claude knows where - // the files are on disk (enables skills to reference them by path). - const workDir = workingDirectory || os.homedir(); - const imagePaths = getUploadedFilePaths(imageFiles, workDir); - const imageReferences = imagePaths - .map((p, i) => `[User attached image: ${p} (${imageFiles[i].name})]`) - .join('\n'); - const textWithImageRefs = `${imageReferences}\n\n${textPrompt}`; + // In imageAgentMode, skip file path references so Claude doesn't + // try to use built-in tools to analyze images from disk. It will + // see the images via vision (base64 content blocks) and follow the + // IMAGE_AGENT_SYSTEM_PROMPT to output image-gen-request blocks. + // In normal mode, append disk paths so skills can reference them. + const textWithImageRefs = imageAgentMode + ? textPrompt + : (() => { + const workDir = workingDirectory || os.homedir(); + const imagePaths = getUploadedFilePaths(imageFiles, workDir); + const imageReferences = imagePaths + .map((p, i) => `[User attached image: ${p} (${imageFiles[i].name})]`) + .join('\n'); + return `${imageReferences}\n\n${textPrompt}`; + })(); const contentBlocks: Array< | { type: 'image'; source: { type: 'base64'; media_type: string; data: string } } diff --git a/src/types/index.ts b/src/types/index.ts index 5634cd4..32ec413 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -644,6 +644,7 @@ export interface ClaudeStreamOptions { abortController?: AbortController; permissionMode?: string; files?: FileAttachment[]; + imageAgentMode?: boolean; toolTimeoutSeconds?: number; provider?: ApiProvider; /** Recent conversation history from DB — used as fallback context when SDK resume is unavailable or fails */