import { expect, test } from 'vitest'; import type { CreativeAgentSessionSnapshot, CreativeAgentSseEvent, } from '../../../packages/shared/src/contracts/creativeAgent'; import { buildCreativeAgentProcessItems } from './creativeAgentViewModel'; function createSession( overrides: Partial = {}, ): CreativeAgentSessionSnapshot { return { sessionId: 'creative-session-1', stage: 'target_ready', inputSummary: { text: '做一个生日拼图', entryContext: 'creation_home', images: [], materialSummary: '做一个生日拼图', unsupportedCapabilities: [], }, messages: [], puzzleTemplateCatalog: [], puzzleTemplateSelection: null, puzzleImageGenerationPlan: null, targetBinding: { playType: 'puzzle', targetSessionId: 'puzzle-session-1', targetStage: 'puzzle-result', resultProfileId: 'puzzle-profile-1', }, updatedAt: '2026-05-05T10:00:00.000Z', ...overrides, }; } test('buildCreativeAgentProcessItems expands creative agent sse details', () => { const eventLog: CreativeAgentSseEvent[] = [ { event: 'stage', data: { sessionId: 'creative-session-1', stage: 'perceiving', }, }, { event: 'thought_summary_delta', data: { sessionId: 'creative-session-1', thoughtId: 'thought-1', textDelta: '正在理解生日素材,', }, }, { event: 'thought_summary_delta', data: { sessionId: 'creative-session-1', thoughtId: 'thought-1', textDelta: '并准备转成拼图关卡。', }, }, { event: 'tool_started', data: { sessionId: 'creative-session-1', toolCallId: 'tool-1', toolName: 'retrieve_puzzle_template_catalog', summary: '读取拼图模板', }, }, { event: 'tool_completed', data: { sessionId: 'creative-session-1', toolCallId: 'tool-1', toolName: 'retrieve_puzzle_template_catalog', summary: '已读取拼图模板', }, }, { event: 'puzzle_template_catalog', data: { sessionId: 'creative-session-1', templates: [ { templateId: 'puzzle.default-creative', title: '创意拼图', summary: '把图文灵感做成拼图。', previewImageSrc: null, supportedLevelMode: 'single_or_multi', minLevelCount: 1, maxLevelCount: 6, defaultLevelCount: 1, costRange: { minPoints: 2, maxPoints: 12, pricingUnit: 'point', reason: '按关卡数估算', }, requiredDraftFields: ['workTitle'], imagePolicy: { allowUploadedImageDirectly: true, allowGeneratedImages: true, allowPerLevelReferenceImage: true, defaultCandidateCountPerLevel: 1, }, }, ], }, }, { event: 'puzzle_template_selection', data: { sessionId: 'creative-session-1', selection: { templateId: 'puzzle.default-creative', title: '创意拼图', reason: '适合把生日素材做成拼图。', costRange: { minPoints: 2, maxPoints: 12, pricingUnit: 'point', reason: '按关卡数估算', }, supportedLevelMode: 'single_or_multi', selectedLevelMode: 'multi_level', plannedLevelCount: 3, requiresUserConfirmation: true, }, }, }, { event: 'puzzle_level_plan', data: { sessionId: 'creative-session-1', plan: { mode: 'multi_level', templateId: 'puzzle.default-creative', estimatedCostRange: { minPoints: 2, maxPoints: 12, pricingUnit: 'point', reason: '按关卡数估算', }, levels: [ { levelId: 'level-1', levelName: '生日开场', pictureDescription: '蛋糕和礼物', imagePrompt: '蛋糕和礼物', pictureReference: null, candidateCount: 1, }, ], }, }, }, { event: 'done', data: { sessionId: 'creative-session-1', }, }, ]; const items = buildCreativeAgentProcessItems(eventLog, createSession()); expect(items.map((item) => item.title)).toContain('素材已理解'); expect(items.map((item) => item.title)).toContain('思考摘要'); expect(items.find((item) => item.title === '思考摘要')?.detail).toBe( '正在理解生日素材,并准备转成拼图关卡。', ); expect(items.find((item) => item.title === '思考摘要')?.tone).toBe('done'); expect(items.map((item) => item.title)).toContain('开始:读取拼图模板'); expect(items.find((item) => item.title === '开始:读取拼图模板')?.tone).toBe( 'done', ); expect(items.map((item) => item.title)).toContain('读取 1 个模板'); expect(items.map((item) => item.title)).toContain('选择 创意拼图'); expect(items.map((item) => item.title)).toContain('规划 1 个关卡'); expect(items.at(-1)?.detailLines).toContain('目标会话:puzzle-session-1'); expect(items.some((item) => item.tone === 'active')).toBe(false); }); test('buildCreativeAgentProcessItems only keeps current running stage active', () => { const eventLog: CreativeAgentSseEvent[] = [ { event: 'stage', data: { sessionId: 'creative-session-1', stage: 'perceiving', }, }, { event: 'stage', data: { sessionId: 'creative-session-1', stage: 'thinking', }, }, ]; const items = buildCreativeAgentProcessItems( eventLog, createSession({ stage: 'thinking', targetBinding: null, }), ); expect(items.find((item) => item.title === '素材已理解')?.tone).toBe('done'); expect(items.find((item) => item.title === '正在构思')?.tone).toBe('active'); expect(items.filter((item) => item.tone === 'active')).toHaveLength(1); }); test('buildCreativeAgentProcessItems stops spinners after waiting confirmation', () => { const eventLog: CreativeAgentSseEvent[] = [ { event: 'stage', data: { sessionId: 'creative-session-1', stage: 'perceiving', }, }, { event: 'stage', data: { sessionId: 'creative-session-1', stage: 'selecting_puzzle_template', }, }, { event: 'thought_summary_delta', data: { sessionId: 'creative-session-1', thoughtId: 'thought-1', textDelta: '已经选择合适模板。', }, }, { event: 'tool_started', data: { sessionId: 'creative-session-1', toolCallId: 'tool-start', toolName: 'retrieve_puzzle_template_catalog', summary: '读取拼图模板', }, }, { event: 'tool_completed', data: { sessionId: 'creative-session-1', toolCallId: 'tool-done', toolName: 'retrieve_puzzle_template_catalog', summary: '已读取拼图模板', }, }, { event: 'stage', data: { sessionId: 'creative-session-1', stage: 'waiting_template_confirmation', }, }, ]; const items = buildCreativeAgentProcessItems( eventLog, createSession({ stage: 'waiting_template_confirmation', targetBinding: null, }), ); expect(items.find((item) => item.title === '思考摘要')?.tone).toBe('done'); expect(items.find((item) => item.title === '开始:读取拼图模板')?.tone).toBe( 'done', ); expect(items.find((item) => item.title === '等待确认')?.tone).toBe('warning'); expect(items.some((item) => item.tone === 'active')).toBe(false); }); test('buildCreativeAgentProcessItems falls back to session snapshots', () => { const session = createSession({ puzzleTemplateSelection: { templateId: 'puzzle.default-creative', title: '创意拼图', reason: '适合拼图创作。', costRange: { minPoints: 2, maxPoints: 12, pricingUnit: 'point', reason: '按关卡数估算', }, supportedLevelMode: 'single_or_multi', selectedLevelMode: 'single_level', plannedLevelCount: 1, requiresUserConfirmation: true, }, }); const items = buildCreativeAgentProcessItems([], session); expect(items.map((item) => item.title)).toContain('选择 创意拼图'); expect(items.map((item) => item.title)).toContain('拼图草稿已绑定'); }); test('buildCreativeAgentProcessItems renders waiting session fallback as static', () => { const items = buildCreativeAgentProcessItems( [], createSession({ stage: 'waiting_template_confirmation', targetBinding: null, }), ); expect(items.map((item) => item.title)).toContain('等待确认'); expect(items.find((item) => item.title === '等待确认')?.tone).toBe('warning'); expect(items.some((item) => item.tone === 'active')).toBe(false); });