|
|
@@ -1,6 +1,7 @@
|
|
|
import { describe, expect, it } from 'vitest'
|
|
|
import { chatMessagesToUi } from '@/components/workspace/viewModels'
|
|
|
import { normalizeChatMessage } from '@/utils/normalize'
|
|
|
+import { buildMessageTimelineRows } from '@/utils/turnTrace'
|
|
|
|
|
|
describe('ordinary chat tool timeline', () => {
|
|
|
it('folds persisted function calls and their result rows into one expandable tool', () => {
|
|
|
@@ -38,4 +39,32 @@ describe('ordinary chat tool timeline', () => {
|
|
|
timelineMetadata: { task_count: 2, completed_count: 2 },
|
|
|
})
|
|
|
})
|
|
|
+
|
|
|
+ it('groups one turn of reasoning and tools before its visible assistant reply', () => {
|
|
|
+ const rows = buildMessageTimelineRows([
|
|
|
+ { id: 'user', role: 'user', content: '检查一下' },
|
|
|
+ { id: 'thinking', role: 'assistant', content: '', reasoning: '先读取配置', tools: [{ id: 'read', name: 'read_file', status: 'success', input: { path: 'a' }, output: 'ok' }] },
|
|
|
+ { id: 'tool-two', role: 'assistant', content: '', reasoning: '再执行命令', tools: [{ id: 'run', name: 'terminal', status: 'running', input: { command: 'pwd' } }] },
|
|
|
+ { id: 'answer', role: 'assistant', content: '检查完成', reasoning: '组织答案' },
|
|
|
+ ])
|
|
|
+ expect(rows.map(row => [row.kind, row.id])).toEqual([
|
|
|
+ ['message', 'message:user'],
|
|
|
+ ['trace', 'trace:thinking'],
|
|
|
+ ['message', 'message:answer'],
|
|
|
+ ])
|
|
|
+ const trace = rows[1]
|
|
|
+ expect(trace?.kind === 'trace' ? trace.entries.map(entry => entry.type) : []).toEqual(['reasoning', 'tool', 'reasoning', 'tool', 'reasoning'])
|
|
|
+ expect(trace?.kind === 'trace' ? trace.status : '').toBe('running')
|
|
|
+ expect(rows[2]?.kind === 'message' ? rows[2].message : undefined).toMatchObject({ content: '检查完成', reasoning: undefined, tools: undefined })
|
|
|
+ })
|
|
|
+
|
|
|
+ it('does not merge assistant traces across agents or system events', () => {
|
|
|
+ const rows = buildMessageTimelineRows([
|
|
|
+ { id: 'a', role: 'assistant', author: '甲', content: '', reasoning: '甲思考' },
|
|
|
+ { id: 'b', role: 'assistant', author: '乙', content: '', reasoning: '乙思考' },
|
|
|
+ { id: 'system', role: 'system', content: '系统信息' },
|
|
|
+ { id: 'c', role: 'assistant', author: '乙', content: '', reasoning: '新回合' },
|
|
|
+ ])
|
|
|
+ expect(rows.map(row => row.id)).toEqual(['trace:a', 'trace:b', 'message:system', 'trace:c'])
|
|
|
+ })
|
|
|
})
|