feat(chat): 优化分析过程与结果展示
Generic Container CI/CD / test-build-publish (push) Successful in 2m25s
Frontend CI/CD v2 / build-test-publish-and-deploy (push) Successful in 2m25s

This commit is contained in:
2026-08-26 18:05:03 +08:00
parent fee4fc6ce1
commit 0dad61ff1f
13 changed files with 1049 additions and 292 deletions
+58
View File
@@ -100,6 +100,27 @@ describe("streamAgentChat", () => {
]);
});
it("parses one complete final answer event", async () => {
mockNewSessionStream({
ok: true,
body: makeStream([
'event: final_answer\ndata: {"session_id":"s1","content":"完整分析结果"}\n\n',
'event: done\ndata: {"session_id":"s1"}\n\n',
]),
});
const events: StreamEvent[] = [];
await streamAgentChat({
message: "分析",
onEvent: (event) => events.push(event),
});
expect(events).toEqual([
{ type: "final_answer", sessionId: "s1", content: "完整分析结果" },
{ type: "done", sessionId: "s1" },
]);
});
it("parses state events from a resumed stream", async () => {
apiFetch.mockResolvedValue({
ok: true,
@@ -172,6 +193,41 @@ describe("streamAgentChat", () => {
});
});
it("parses grouped activities and inherited permission reasons", async () => {
mockNewSessionStream({
ok: true,
body: makeStream([
'event: activity_update\ndata: {"session_id":"s1","activity":{"id":"a1","title":"准备分析数据","reason":"需要先确认输入数据完整。","status":"running","started_at":100,"elapsed_ms":25,"actions":[{"id":"x1","tool":"tjwater_cli","title":"查询后端数据","status":"running","target":"data list","started_at":110,"elapsed_ms":15}]},"todos":[{"id":"t1","content":"准备分析数据","status":"completed","priority":"high"},{"id":"t2","content":"生成分析结果","status":"in_progress","priority":"medium"}],"todos_created_at":125}\n\n',
'event: permission_request\ndata: {"session_id":"s1","request_id":"p1","permission":"bash","patterns":["python3 analysis.py"],"target":"python3 analysis.py","always":[],"activity_id":"a1","reason":"需要先确认输入数据完整。","created_at":123}\n\n',
]),
});
const events: StreamEvent[] = [];
await streamAgentChat({ message: "分析", onEvent: (event) => events.push(event) });
expect(events[0]).toMatchObject({
type: "activity_update",
sessionId: "s1",
activity: {
id: "a1",
title: "准备分析数据",
reason: "需要先确认输入数据完整。",
status: "running",
actions: [expect.objectContaining({ id: "x1", target: "data list" })],
},
todos: [
expect.objectContaining({ id: "t1", status: "completed" }),
expect.objectContaining({ id: "t2", status: "in_progress" }),
],
todosCreatedAt: 125,
});
expect(events[1]).toMatchObject({
type: "permission_request",
activityId: "a1",
reason: "需要先确认输入数据完整。",
});
});
it("parses credential refresh lifecycle events", async () => {
mockNewSessionStream({
ok: true,
@@ -246,6 +302,8 @@ describe("streamAgentChat", () => {
permission: "bash",
patterns: ["rm *"],
target: "rm tmp.txt",
activityId: undefined,
reason: undefined,
always: ["rm *"],
tool: undefined,
createdAt: 123,