fix(gui): harden multimodal image attachments

This commit is contained in:
Yichen Jiang
2026-07-23 19:38:37 +08:00
parent eea595fcb4
commit 580e05b794
61 changed files with 1700 additions and 214 deletions
@@ -1,5 +1,6 @@
import { describe, expect, it, vi } from 'vitest'
import { Context } from 'cordis'
import { AttachmentId } from '@deepseek-ai/dsh-attachment'
import BasicCompactService from '@deepseek-ai/dsh-compact-basic'
import type { BasicCompactConfig } from '@deepseek-ai/dsh-compact-basic'
import { selectCompactableRange } from '@deepseek-ai/dsh-compact-basic/src/region.ts'
@@ -1103,7 +1104,22 @@ describe('default one-shot summarizer', () => {
it('replays the conversation prefix and appends the instruction as the final message', async () => {
const { adapter, compact } = await summarizerHarness([{ type: 'text', text: 'summary' }])
const tools = [{ name: 'do_thing', description: 'd', parameters: { type: 'object' } }]
const prefix: Message = { role: 'user', content: [{ type: 'text', text: 'earlier turn' }] }
const prefix: Message = {
role: 'user',
content: [
{ type: 'text', text: 'earlier turn' },
{
type: 'image',
attachment: {
attachmentId: AttachmentId(`sha256:${'a'.repeat(64)}`),
mediaType: 'image/png',
bytes: 1,
width: 1,
height: 1,
},
},
],
}
await compact.runSummarize({
system: 'REPLAYED SYSTEM',
tools,
@@ -1256,6 +1272,43 @@ describe('default one-shot summarizer', () => {
await expect(compact.runSummarize(promptInput('history'), agent(conversation(1), MODEL)))
.rejects.toThrow(/no text summary content/)
})
it('rejects image summary output instead of silently dropping it', async () => {
const { compact } = await summarizerHarness([
{
type: 'image',
attachment: {
attachmentId: AttachmentId(`sha256:${'b'.repeat(64)}`),
mediaType: 'image/png',
bytes: 1,
width: 1,
height: 1,
},
},
{ type: 'text', text: 'partial summary' },
])
await expect(compact.runSummarize(promptInput('history'), agent(conversation(1), MODEL)))
.rejects.toMatchObject({ code: 'UNSUPPORTED_CONTENT' })
})
it('rejects image summary output nested in a tool result', async () => {
const { compact } = await summarizerHarness([{
type: 'tool-result',
toolCallId: CallId('summary-tool'),
content: [{
type: 'image',
attachment: {
attachmentId: AttachmentId(`sha256:${'c'.repeat(64)}`),
mediaType: 'image/png',
bytes: 1,
width: 1,
height: 1,
},
}],
}])
await expect(compact.runSummarize(promptInput('history'), agent(conversation(1), MODEL)))
.rejects.toMatchObject({ code: 'UNSUPPORTED_CONTENT' })
})
})
describe('automatic listener and loader composition', () => {