feat: 全新智能体功能
- 基于先进智能体框架,增加智能体编排功能 - 增加智能体聊天,并对接持久化
This commit is contained in:
@@ -0,0 +1,213 @@
|
||||
import {beforeEach, describe, expect, it} from 'vitest';
|
||||
|
||||
import {useAgentTryoutRawRounds} from './useAgentTryoutRawRounds';
|
||||
|
||||
describe('useAgentTryoutRawRounds', () => {
|
||||
beforeEach(() => {
|
||||
sessionStorage.clear();
|
||||
});
|
||||
|
||||
it('按原始事件顺序生成 timeline', () => {
|
||||
const store = useAgentTryoutRawRounds({
|
||||
mode: 'draft',
|
||||
sessionId: 'session-raw-1',
|
||||
});
|
||||
const roundId = store.createRound('上一轮问题');
|
||||
|
||||
store.recordEvent(roundId, {
|
||||
domain: 'LLM',
|
||||
payload: { reasoning: '先思考' },
|
||||
type: 'THINKING',
|
||||
});
|
||||
store.recordEvent(roundId, {
|
||||
domain: 'LLM',
|
||||
payload: { delta: '上一轮回答' },
|
||||
type: 'MESSAGE',
|
||||
});
|
||||
store.completeRound(roundId);
|
||||
|
||||
expect(store.buildTimelineItems().map((item) => item.type)).toEqual([
|
||||
'message',
|
||||
'message',
|
||||
]);
|
||||
});
|
||||
|
||||
it('业务引用只用于展示', () => {
|
||||
const store = useAgentTryoutRawRounds({
|
||||
mode: 'draft',
|
||||
sessionId: 'session-raw-2',
|
||||
});
|
||||
const roundId = store.createRound('查知识库');
|
||||
|
||||
store.recordEvent(roundId, {
|
||||
domain: 'BUSINESS',
|
||||
payload: {
|
||||
items: [
|
||||
{
|
||||
chunkContent: '知识库原文',
|
||||
chunkId: 'chunk-1',
|
||||
documentId: 'doc-1',
|
||||
knowledgeId: 'kb-1',
|
||||
},
|
||||
],
|
||||
},
|
||||
type: 'CITATIONS',
|
||||
});
|
||||
store.recordEvent(roundId, {
|
||||
domain: 'LLM',
|
||||
payload: { delta: '引用后的回答' },
|
||||
type: 'MESSAGE',
|
||||
});
|
||||
store.completeRound(roundId);
|
||||
|
||||
expect(store.buildTimelineItems().map((item) => item.type)).toEqual([
|
||||
'message',
|
||||
'knowledge',
|
||||
'message',
|
||||
]);
|
||||
});
|
||||
|
||||
it('AgentScope fragment 工具事件不进入页面时间线', () => {
|
||||
const store = useAgentTryoutRawRounds({
|
||||
mode: 'draft',
|
||||
sessionId: 'session-raw-fragment',
|
||||
});
|
||||
const roundId = store.createRound('调用内部片段');
|
||||
|
||||
store.recordEvent(roundId, {
|
||||
domain: 'TOOL',
|
||||
payload: {
|
||||
input: { text: 'fragment' },
|
||||
toolCallId: 'fragment-1',
|
||||
toolName: '__fragment__',
|
||||
},
|
||||
type: 'TOOL_CALL',
|
||||
});
|
||||
store.recordEvent(roundId, {
|
||||
domain: 'TOOL',
|
||||
payload: {
|
||||
output: 'internal',
|
||||
toolCallId: 'fragment-1',
|
||||
toolName: '__fragment__',
|
||||
},
|
||||
type: 'TOOL_RESULT',
|
||||
});
|
||||
|
||||
expect(store.buildTimelineItems().map((item) => item.type)).toEqual([
|
||||
'message',
|
||||
]);
|
||||
});
|
||||
|
||||
it('刷新后能从 raw rounds 恢复 timeline', () => {
|
||||
const first = useAgentTryoutRawRounds({
|
||||
mode: 'draft',
|
||||
sessionId: 'session-raw-5',
|
||||
});
|
||||
const roundId = first.createRound('问题');
|
||||
first.recordEvent(roundId, {
|
||||
domain: 'LLM',
|
||||
payload: { delta: '回答' },
|
||||
type: 'MESSAGE',
|
||||
});
|
||||
first.completeRound(roundId);
|
||||
|
||||
const restored = useAgentTryoutRawRounds({
|
||||
mode: 'draft',
|
||||
sessionId: 'session-raw-5',
|
||||
});
|
||||
|
||||
expect(restored.buildTimelineItems().map((item) => item.type)).toEqual([
|
||||
'message',
|
||||
'message',
|
||||
]);
|
||||
});
|
||||
|
||||
it('错误轮次不会被 completeRound 覆盖为成功状态', () => {
|
||||
const store = useAgentTryoutRawRounds({
|
||||
mode: 'draft',
|
||||
sessionId: 'session-raw-error',
|
||||
});
|
||||
const roundId = store.createRound('会失败的问题');
|
||||
store.recordEvent(roundId, {
|
||||
domain: 'LLM',
|
||||
payload: { delta: '半截回答' },
|
||||
type: 'MESSAGE',
|
||||
});
|
||||
store.recordEvent(roundId, {
|
||||
domain: 'SYSTEM',
|
||||
payload: { message: '调用失败' },
|
||||
type: 'ERROR',
|
||||
});
|
||||
|
||||
store.completeRound(roundId);
|
||||
|
||||
const assistant = store
|
||||
.buildTimelineItems()
|
||||
.find((item) => item.type === 'message' && item.role === 'assistant');
|
||||
expect(assistant).toMatchObject({ status: 'error' });
|
||||
});
|
||||
|
||||
it('流式重建 timeline 时保持稳定 item id', () => {
|
||||
const store = useAgentTryoutRawRounds({
|
||||
mode: 'draft',
|
||||
sessionId: 'session-raw-stable-id',
|
||||
});
|
||||
const roundId = store.createRound('问题');
|
||||
store.recordEvent(roundId, {
|
||||
domain: 'LLM',
|
||||
payload: { delta: '你' },
|
||||
type: 'MESSAGE',
|
||||
});
|
||||
const firstIds = store.buildTimelineItems().map((item) => item.id);
|
||||
|
||||
store.recordEvent(roundId, {
|
||||
domain: 'LLM',
|
||||
payload: { delta: '好' },
|
||||
type: 'MESSAGE',
|
||||
});
|
||||
const secondIds = store.buildTimelineItems().map((item) => item.id);
|
||||
|
||||
expect(secondIds).toEqual(firstIds);
|
||||
});
|
||||
|
||||
it('审批状态作为展示事件缓存并可刷新恢复', () => {
|
||||
const first = useAgentTryoutRawRounds({
|
||||
mode: 'draft',
|
||||
sessionId: 'session-raw-approval',
|
||||
});
|
||||
const roundId = first.createRound('审批工具');
|
||||
first.recordEvent(roundId, {
|
||||
domain: 'TOOL',
|
||||
payload: {
|
||||
requestId: 'req-1',
|
||||
resumeToken: 'resume-1',
|
||||
toolCallId: 'call-approval',
|
||||
toolName: 'dangerous_tool',
|
||||
},
|
||||
type: 'FORM_REQUEST',
|
||||
});
|
||||
first.recordEvent(roundId, {
|
||||
domain: 'TOOL',
|
||||
payload: {
|
||||
requestId: 'req-1',
|
||||
resumeToken: 'resume-1',
|
||||
toolCallId: 'call-approval',
|
||||
},
|
||||
type: 'FORM_APPROVING',
|
||||
});
|
||||
first.flush();
|
||||
|
||||
const restored = useAgentTryoutRawRounds({
|
||||
mode: 'draft',
|
||||
sessionId: 'session-raw-approval',
|
||||
});
|
||||
const tool = restored
|
||||
.buildTimelineItems()
|
||||
.find((item) => item.type === 'tool');
|
||||
|
||||
expect(tool).toMatchObject({
|
||||
status: 'approving',
|
||||
toolCallId: 'call-approval',
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user