From e6598d304135f6e2b42873921249e7b6c7c631c2 Mon Sep 17 00:00:00 2001 From: Siddharth Ganesan Date: Thu, 6 Aug 2026 17:29:45 -0700 Subject: [PATCH] fix(mship): fix image handling --- apps/sim/lib/copilot/chat/payload.test.ts | 51 +++++++++++++++++------ apps/sim/lib/copilot/chat/payload.ts | 12 ++++-- bun.lock | 1 - 3 files changed, 47 insertions(+), 17 deletions(-) diff --git a/apps/sim/lib/copilot/chat/payload.test.ts b/apps/sim/lib/copilot/chat/payload.test.ts index 92e77ffb63a..2f061cf8592 100644 --- a/apps/sim/lib/copilot/chat/payload.test.ts +++ b/apps/sim/lib/copilot/chat/payload.test.ts @@ -374,19 +374,46 @@ describe('buildCopilotRequestPayload', () => { ]) }) - it('fails the request when an authorized attachment cannot be prepared', async () => { + it('isolates a failed attachment and still prepares valid siblings', async () => { const cause = new Error('provenance sidecar unavailable') - mockTrackChatUpload.mockRejectedValueOnce(cause) - - await expect( - buildCopilotRequestPayload( - { ...attachmentParams, userPermission: 'write' }, - { selectedModel: 'claude-opus-4-8' } - ) - ).rejects.toMatchObject({ - message: 'Failed to prepare attached file "payroll.xlsx" for Copilot. Please try again.', - cause, - }) + mockTrackChatUpload + .mockRejectedValueOnce(cause) + .mockResolvedValueOnce({ displayName: 'photo.png' }) + + const payload = await buildCopilotRequestPayload( + { + ...attachmentParams, + userPermission: 'write', + fileAttachments: [ + ...attachmentParams.fileAttachments, + { + id: 'a2', + key: 'workspace/ws-1/1731000000001-ab12cd35-photo.png', + filename: 'photo.png', + media_type: 'image/png', + size: 10, + }, + ], + }, + { selectedModel: 'claude-opus-4-8' } + ) + + expect(mockTrackChatUpload).toHaveBeenCalledTimes(2) + expect(payload.context).toEqual([ + { + type: 'uploaded_file', + content: + 'File "payroll.xlsx" could not be prepared for Copilot and was omitted. Other attached files remain available.', + }, + { + type: 'uploaded_file', + content: [ + 'File "photo.png" (image/png, 10 bytes) uploaded.', + 'Read with: read("uploads/photo.png")', + 'To save permanently: materialize_file(fileName: "photo.png")', + ].join('\n'), + }, + ]) }) }) diff --git a/apps/sim/lib/copilot/chat/payload.ts b/apps/sim/lib/copilot/chat/payload.ts index 7c9988ddac4..ef1ea48d159 100644 --- a/apps/sim/lib/copilot/chat/payload.ts +++ b/apps/sim/lib/copilot/chat/payload.ts @@ -401,10 +401,14 @@ export async function buildCopilotRequestPayload( chatId, error: cause.message, }) - throw new Error( - `Failed to prepare attached file "${filename}" for Copilot. Please try again.`, - { cause } - ) + // Isolate failures by entry. Aborting here discarded every valid + // sibling attachment in the request, even ones already tracked. Give + // the model a local marker for this file and continue preparing the + // rest of the batch. + uploadContexts.push({ + type: 'uploaded_file', + content: `File "${filename}" could not be prepared for Copilot and was omitted. Other attached files remain available.`, + }) } } } diff --git a/bun.lock b/bun.lock index 0132ebcfa12..f3070e48480 100644 --- a/bun.lock +++ b/bun.lock @@ -1,6 +1,5 @@ { "lockfileVersion": 1, - "configVersion": 0, "workspaces": { "": { "name": "simstudio",