123 lines
3.4 KiB
TypeScript
123 lines
3.4 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
applyPermissionResponse,
|
|
applyQuestionResponse,
|
|
finalizeAssistantMessageAfterAbort,
|
|
toTodoUpdate,
|
|
upsertPermission,
|
|
upsertProgress,
|
|
upsertQuestion
|
|
} from "./session-state";
|
|
import type { AgentChatMessage } from "./types";
|
|
|
|
describe("agent session state", () => {
|
|
it("upserts progress events by id", () => {
|
|
const first = upsertProgress(undefined, {
|
|
id: "tool-1",
|
|
phase: "tool",
|
|
status: "running",
|
|
title: "调用工具",
|
|
elapsed_ms: 20
|
|
});
|
|
const next = upsertProgress(first, {
|
|
id: "tool-1",
|
|
phase: "tool",
|
|
status: "completed",
|
|
title: "工具完成",
|
|
duration_ms: 40
|
|
});
|
|
|
|
expect(next).toHaveLength(1);
|
|
expect(next[0]).toMatchObject({ id: "tool-1", status: "completed", title: "工具完成", durationMs: 40 });
|
|
});
|
|
|
|
it("normalizes todo updates", () => {
|
|
expect(
|
|
toTodoUpdate({
|
|
session_id: "session-1",
|
|
todos: [{ id: "todo-1", content: "分析压力", status: "in_progress", priority: "high" }],
|
|
created_at: 123
|
|
})
|
|
).toEqual({
|
|
sessionId: "session-1",
|
|
messageId: undefined,
|
|
todos: [{ id: "todo-1", content: "分析压力", status: "in_progress", priority: "high" }],
|
|
createdAt: 123
|
|
});
|
|
});
|
|
|
|
it("tracks permission request and response", () => {
|
|
const permissions = upsertPermission(undefined, {
|
|
session_id: "session-1",
|
|
request_id: "permission-1",
|
|
permission: "bash",
|
|
patterns: ["pnpm test"],
|
|
always: [],
|
|
created_at: 100
|
|
});
|
|
const next = applyPermissionResponse(permissions, {
|
|
request_id: "permission-1",
|
|
reply: "once"
|
|
});
|
|
|
|
expect(next?.[0]).toMatchObject({
|
|
requestId: "permission-1",
|
|
status: "approved_once"
|
|
});
|
|
});
|
|
|
|
it("dedupes question requests by tool call id", () => {
|
|
const questions = upsertQuestion(undefined, {
|
|
session_id: "session-1",
|
|
request_id: "call-1",
|
|
tool: { messageID: "message-1", callID: "call-1" },
|
|
questions: [{ header: "范围", question: "选择范围", options: [] }],
|
|
created_at: 100
|
|
});
|
|
const next = upsertQuestion(questions, {
|
|
session_id: "session-1",
|
|
request_id: "question-1",
|
|
tool: { messageID: "message-1", callID: "call-1" },
|
|
questions: [{ header: "范围", question: "选择范围", options: [] }],
|
|
created_at: 120
|
|
});
|
|
const answered = applyQuestionResponse(next, {
|
|
request_id: "question-1",
|
|
answers: [["东部"]]
|
|
});
|
|
|
|
expect(next).toHaveLength(1);
|
|
expect(answered?.[0]).toMatchObject({
|
|
requestId: "question-1",
|
|
status: "answered",
|
|
answers: [["东部"]]
|
|
});
|
|
});
|
|
|
|
it("finalizes open assistant state after abort", () => {
|
|
const message: AgentChatMessage = {
|
|
id: "assistant-1",
|
|
role: "assistant",
|
|
content: "",
|
|
progress: [{ id: "run", phase: "run", status: "running", title: "处理中", startedAt: Date.now() }],
|
|
permissions: [
|
|
{
|
|
requestId: "permission-1",
|
|
sessionId: "session-1",
|
|
permission: "bash",
|
|
patterns: [],
|
|
always: [],
|
|
createdAt: 100,
|
|
status: "pending"
|
|
}
|
|
]
|
|
};
|
|
|
|
const next = finalizeAssistantMessageAfterAbort(message);
|
|
|
|
expect(next.content).toBe("请求已中止。");
|
|
expect(next.progress?.[0].status).toBe("completed");
|
|
expect(next.permissions?.[0].status).toBe("aborted");
|
|
});
|
|
});
|