forked from EduCraft/curriculum-project-hub
e3b463d390
Native Claude TodoWrite is not registered in headless agent mode even with --tools default. Add mcp__cph_hub__todo_write (always enabled), mirror the TodoWrite schema, instruct multi-step runs to use it, and keep the Feishu progress panel parsing both native and hub tool names.
77 lines
2.5 KiB
TypeScript
77 lines
2.5 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
isTodoWriteTool,
|
|
parseTodoWriteInput,
|
|
todoProgressSummary,
|
|
} from "../../src/agent/todoList.js";
|
|
import { buildAgentCard } from "../../src/feishu/card/builder.js";
|
|
|
|
describe("todo list parse", () => {
|
|
it("accepts TodoWrite payloads", () => {
|
|
const todos = parseTodoWriteInput({
|
|
todos: [
|
|
{ content: "搜题", status: "completed", activeForm: "正在搜题" },
|
|
{ content: "写报告", status: "in_progress", activeForm: "正在写报告" },
|
|
{ content: "发卡片", status: "pending" },
|
|
],
|
|
});
|
|
expect(todos).toEqual([
|
|
{ content: "搜题", status: "completed", activeForm: "正在搜题" },
|
|
{ content: "写报告", status: "in_progress", activeForm: "正在写报告" },
|
|
{ content: "发卡片", status: "pending", activeForm: undefined },
|
|
]);
|
|
expect(todoProgressSummary(todos!)).toEqual({ completed: 1, total: 3, inProgress: 1 });
|
|
});
|
|
|
|
it("rejects empty or invalid bodies", () => {
|
|
expect(parseTodoWriteInput(null)).toBeNull();
|
|
expect(parseTodoWriteInput({ todos: [] })).toBeNull();
|
|
expect(parseTodoWriteInput({ todos: [{ status: "pending" }] })).toBeNull();
|
|
});
|
|
|
|
it("recognizes TodoWrite tool names", () => {
|
|
expect(isTodoWriteTool("TodoWrite")).toBe(true);
|
|
expect(isTodoWriteTool("mcp__cph_hub__todo_write")).toBe(true);
|
|
expect(isTodoWriteTool("Bash")).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("agent card todo panel", () => {
|
|
it("renders a progress checklist when todos are present", () => {
|
|
const card = buildAgentCard({
|
|
phase: "streaming",
|
|
text: "",
|
|
reasoningText: undefined,
|
|
todos: [
|
|
{ content: "A", status: "completed", activeForm: undefined },
|
|
{ content: "B", status: "in_progress", activeForm: "Doing B" },
|
|
{ content: "C", status: "pending", activeForm: undefined },
|
|
],
|
|
toolUseSteps: [
|
|
{
|
|
id: "1",
|
|
seq: 1,
|
|
toolName: "TodoWrite",
|
|
toolUseId: "t1",
|
|
input: {},
|
|
result: undefined,
|
|
error: undefined,
|
|
status: "success",
|
|
startedAt: 0,
|
|
finishedAt: 1,
|
|
durationMs: 1,
|
|
},
|
|
],
|
|
toolUseElapsedMs: 10,
|
|
isError: undefined,
|
|
interrupted: undefined,
|
|
runId: "run-1",
|
|
});
|
|
|
|
const json = JSON.stringify(card);
|
|
expect(json).toContain("任务进度 1/3");
|
|
expect(json).toContain("Doing B");
|
|
expect(json).toContain("collapsible_panel");
|
|
});
|
|
});
|