forked from bai/curriculum-project-hub
fix(hub): ship checklist via cph_hub todo_write MCP tool
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.
This commit is contained in:
@@ -19,6 +19,7 @@ export const CPH_HUB_MCP_TOOL_IDS = [
|
||||
"pbank_search_problems",
|
||||
"pbank_get_problem",
|
||||
"pbank_get_many_problems",
|
||||
"todo_write",
|
||||
] as const;
|
||||
|
||||
export type CphHubMcpToolId = (typeof CPH_HUB_MCP_TOOL_IDS)[number];
|
||||
@@ -62,6 +63,9 @@ const ROLE_TOOL_TO_CPH_HUB_MCP_TOOLS: Readonly<Record<string, readonly CphHubMcp
|
||||
pbank_search_problems: ["pbank_search_problems"],
|
||||
pbank_get_problem: ["pbank_get_problem"],
|
||||
pbank_get_many_problems: ["pbank_get_many_problems"],
|
||||
todo: ["todo_write"],
|
||||
TodoWrite: ["todo_write"],
|
||||
todo_write: ["todo_write"],
|
||||
"mcp__cph_hub__send_file": ["send_file"],
|
||||
"mcp__cph_hub__feishu_read_context": ["feishu_read_context"],
|
||||
"mcp__cph_hub__feishu_download_resource": ["feishu_download_resource"],
|
||||
@@ -70,6 +74,7 @@ const ROLE_TOOL_TO_CPH_HUB_MCP_TOOLS: Readonly<Record<string, readonly CphHubMcp
|
||||
"mcp__cph_hub__pbank_search_problems": ["pbank_search_problems"],
|
||||
"mcp__cph_hub__pbank_get_problem": ["pbank_get_problem"],
|
||||
"mcp__cph_hub__pbank_get_many_problems": ["pbank_get_many_problems"],
|
||||
"mcp__cph_hub__todo_write": ["todo_write"],
|
||||
};
|
||||
|
||||
const SUPPORTED_ROLE_TOOLS = new Set([
|
||||
@@ -109,9 +114,13 @@ export function claudeSdkToolConfigForRole(
|
||||
export function cphHubMcpToolsForRole(
|
||||
roleTools: readonly string[] | null | undefined,
|
||||
): readonly CphHubMcpToolId[] {
|
||||
if (roleTools === undefined || roleTools === null) return [...CPH_HUB_MCP_TOOL_IDS];
|
||||
// Always expose hub-side todo_write so progress cards work even when the
|
||||
// native Claude TodoWrite tool is not registered in headless agent mode.
|
||||
if (roleTools === undefined || roleTools === null) {
|
||||
return [...CPH_HUB_MCP_TOOL_IDS];
|
||||
}
|
||||
|
||||
const tools: CphHubMcpToolId[] = [];
|
||||
const tools: CphHubMcpToolId[] = ["todo_write"];
|
||||
for (const roleTool of roleTools) {
|
||||
assertSupportedRoleTool(roleTool);
|
||||
for (const mcpTool of ROLE_TOOL_TO_CPH_HUB_MCP_TOOLS[roleTool] ?? []) {
|
||||
|
||||
@@ -169,6 +169,7 @@ export async function runAgent(req: RunRequest): Promise<RunResult> {
|
||||
const allowedToolsOption = uniqueTools([
|
||||
...toolConfig.allowedTools,
|
||||
"TodoWrite",
|
||||
"mcp__cph_hub__todo_write",
|
||||
...skillExtras,
|
||||
]);
|
||||
|
||||
|
||||
@@ -14,9 +14,15 @@ export interface AgentTodoItem {
|
||||
|
||||
const STATUSES = new Set<AgentTodoStatus>(["pending", "in_progress", "completed"]);
|
||||
|
||||
/** True when the tool name is the SDK TodoWrite dispatcher. */
|
||||
/** True when the tool name is SDK TodoWrite or hub mcp todo_write. */
|
||||
export function isTodoWriteTool(toolName: string): boolean {
|
||||
return toolName === "TodoWrite" || toolName.endsWith("__TodoWrite");
|
||||
const lower = toolName.toLowerCase();
|
||||
return (
|
||||
toolName === "TodoWrite" ||
|
||||
toolName.endsWith("__TodoWrite") ||
|
||||
lower === "todo_write" ||
|
||||
lower.endsWith("__todo_write")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user