import { describe, expect, it } from 'vitest' import type { AgentExecutionRequest, AgentRuntime } from '../agent/runtime' import type { MagicNoteEntry, MagicTodoItem } from '../../shared/magic-notes-contracts' import { analyzeMagicNoteEntry, analyzeMagicTodo } from './magic-note-analyzer' const entry: MagicNoteEntry = { id: '00000000-0000-4000-8000-000000000501', noteId: '00000000-0000-4000-8000-000000000502', content: { version: 1, ops: [{ insert: '周五前整理发布清单\n' }] }, plainText: '周五前整理发布清单', comments: [], revision: 0, createdAt: '2026-08-01T00:00:00.000Z', updatedAt: '2026-08-01T00:00:00.000Z' } describe('magic note analyzer', () => { it('uses ask mode and converts bounded JSON into comments only', async () => { let request: AgentExecutionRequest | undefined const runtime = { requiresToolApproval: false, supportsToolExecution: false, async getStatus() { return { id: 'model', label: 'Test model', available: true, detail: 'Ready', supportsToolExecution: false } as const }, async *run(input: AgentExecutionRequest) { request = input yield { requestId: input.requestId, type: 'text', delta: '```json\n{"comments":[{"kind":"suggestion","content":"先列出发布检查项。"}]}\n```' } as const yield { requestId: input.requestId, type: 'done' } as const }, async dispose() {} } as AgentRuntime const result = await analyzeMagicNoteEntry( runtime, entry, { requestId: '00000000-0000-4000-8000-000000000506', direction: 'general', format: 'structured' } ) expect(request).toMatchObject({ workMode: 'ask', knowledgeLibraryIds: [] }) expect(request?.trustedInstructions).toContain('禁止工具调用') expect(result).toEqual([ expect.objectContaining({ kind: 'suggestion', content: '先列出发布检查项。' }) ]) expect(request?.prompt).toContain('不创建待办') }) it('does not analyze image-only records', async () => { const runtime = {} as AgentRuntime await expect( analyzeMagicNoteEntry( runtime, { ...entry, plainText: '' }, { requestId: '00000000-0000-4000-8000-000000000507', direction: 'general', format: 'structured' } ) ).rejects.toThrow('没有可供 AI 分析的文字') }) it('analyzes a magic todo as comments without tool access', async () => { let request: AgentExecutionRequest | undefined const runtime = { requiresToolApproval: false, supportsToolExecution: false, async getStatus() { return { id: 'model', label: 'Test model', available: true, detail: 'Ready', supportsToolExecution: false } as const }, async *run(input: AgentExecutionRequest) { request = input yield { requestId: input.requestId, type: 'text', delta: '{"comments":[{"kind":"warning","content":"验收条件还不够明确。"}]}' } as const yield { requestId: input.requestId, type: 'done' } as const }, async dispose() {} } as AgentRuntime const todo: MagicTodoItem = { id: '00000000-0000-4000-8000-000000000601', noteId: '00000000-0000-4000-8000-000000000602', entryId: '00000000-0000-4000-8000-000000000603', noteTitle: '发布笔记', sourceIndex: 0, source: 'note', title: '整理发布清单', instructions: '核对版本、说明和构建产物。', completed: false, comments: [], revision: 0, createdAt: '2026-08-01T00:00:00.000Z', updatedAt: '2026-08-01T00:00:00.000Z' } await expect( analyzeMagicTodo( runtime, todo, { requestId: '00000000-0000-4000-8000-000000000604', direction: 'general', format: 'structured' } ) ).resolves.toEqual([ expect.objectContaining({ kind: 'warning', content: '验收条件还不够明确。' }) ]) expect(request?.workMode).toBe('ask') expect(request?.trustedInstructions).toContain('禁止工具调用') }) it('streams the narrative and snapshots combined comment options', async () => { const runtime = { requiresToolApproval: false, supportsToolExecution: false, async getStatus() { return { id: 'model', label: 'Test model', available: true, detail: 'Ready', supportsToolExecution: false } as const }, async *run(input: AgentExecutionRequest) { yield { requestId: input.requestId, type: 'text', delta: '可以先扩展目标读者,' } as const yield { requestId: input.requestId, type: 'text', delta: '再补充一个实际例子。\n<<>>\n' } as const yield { requestId: input.requestId, type: 'text', delta: '{"comments":[{"kind":"suggestion","content":"补充一个读者场景。"}]}' } as const yield { requestId: input.requestId, type: 'done' } as const }, async dispose() {} } as AgentRuntime const deltas: string[] = [] const result = await analyzeMagicNoteEntry( runtime, entry, { requestId: '00000000-0000-4000-8000-000000000508', direction: 'expand', format: 'combined' }, (delta) => deltas.push(delta) ) expect(deltas.join('')).toBe( '可以先扩展目标读者,再补充一个实际例子。\n' ) expect(result).toEqual([ expect.objectContaining({ kind: 'narrative', direction: 'expand', format: 'combined' }), expect.objectContaining({ kind: 'suggestion', content: '补充一个读者场景。', direction: 'expand', format: 'combined' }) ]) }) })