feat: 集成 AI 对话与只读查询工具
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { parseSsePayload, reduceAiSseMessage } from './provider';
|
||||
|
||||
describe('AI chat SSE message reducer', () => {
|
||||
it('separates reasoning and answer deltas', () => {
|
||||
let message = reduceAiSseMessage(undefined, {
|
||||
event: 'reasoning.delta',
|
||||
data: JSON.stringify({ messageId: 8, delta: '分析' }),
|
||||
});
|
||||
message = reduceAiSseMessage(message, {
|
||||
event: 'content.delta',
|
||||
data: JSON.stringify({ delta: '**答案**' }),
|
||||
});
|
||||
|
||||
expect(message.reasoningContent).toBe('分析');
|
||||
expect(message.content).toBe('**答案**');
|
||||
});
|
||||
|
||||
it('tracks tool lifecycle without exposing raw payloads', () => {
|
||||
let message = reduceAiSseMessage(undefined, {
|
||||
event: 'tool.started',
|
||||
data: JSON.stringify({
|
||||
toolCallId: 'call-1',
|
||||
toolName: 'search_students',
|
||||
summary: '姓名条件',
|
||||
}),
|
||||
});
|
||||
message = reduceAiSseMessage(message, {
|
||||
event: 'tool.completed',
|
||||
data: JSON.stringify({
|
||||
toolCallId: 'call-1',
|
||||
toolName: 'search_students',
|
||||
status: 'success',
|
||||
summary: '找到 1 条记录',
|
||||
}),
|
||||
});
|
||||
|
||||
expect(message.toolRuns).toHaveLength(1);
|
||||
expect(message.toolRuns[0]).toMatchObject({ status: 'success', summary: '找到 1 条记录' });
|
||||
});
|
||||
|
||||
it('uses final content and records cancellation and errors', () => {
|
||||
let message = reduceAiSseMessage(undefined, {
|
||||
event: 'message.completed',
|
||||
data: JSON.stringify({
|
||||
message: {
|
||||
id: 12,
|
||||
content: '最终回答',
|
||||
reasoningContent: '完成',
|
||||
status: 'completed',
|
||||
toolRuns: [
|
||||
{
|
||||
toolCallId: 'nested-tool',
|
||||
toolName: 'search_rooms',
|
||||
status: 'success',
|
||||
resultSummary: '共 4 间',
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
});
|
||||
message = reduceAiSseMessage(message, {
|
||||
event: 'error',
|
||||
data: JSON.stringify({ message: '上游服务不可用' }),
|
||||
});
|
||||
message = reduceAiSseMessage(message, {
|
||||
event: 'message.cancelled',
|
||||
data: JSON.stringify({ messageId: 12 }),
|
||||
});
|
||||
|
||||
expect(message).toMatchObject({
|
||||
id: 12,
|
||||
content: '最终回答',
|
||||
reasoningContent: '完成',
|
||||
error: '上游服务不可用',
|
||||
cancelled: true,
|
||||
});
|
||||
expect(message.toolRuns[0]).toMatchObject({ toolCallId: 'nested-tool', status: 'success' });
|
||||
});
|
||||
|
||||
it('reads nested assistant message from message.created', () => {
|
||||
const message = reduceAiSseMessage(undefined, {
|
||||
event: 'message.created',
|
||||
data: JSON.stringify({
|
||||
message: { id: 9, content: '', reasoningContent: null, status: 'pending' },
|
||||
}),
|
||||
});
|
||||
|
||||
expect(message.id).toBe(9);
|
||||
});
|
||||
|
||||
it('tolerates non-JSON event data', () => {
|
||||
expect(parseSsePayload({ event: 'content.delta', data: 'plain text' })).toEqual({
|
||||
event: 'content.delta',
|
||||
payload: { delta: 'plain text' },
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user