forked from EduCraft/curriculum-project-hub
feat(hub): live TodoWrite checklist on Feishu agent cards
Always expose Claude Agent SDK TodoWrite (todoFeatureEnabled) so multi-step runs can plan in the open. Parse TodoWrite payloads into a progress panel on the streaming Feishu card (completed/in_progress/pending) and filter raw TodoWrite noise out of the tool-use list.
This commit is contained in:
+20
-3
@@ -160,8 +160,14 @@ export async function runAgent(req: RunRequest): Promise<RunResult> {
|
||||
cwd: security.cwd,
|
||||
// `skills` controls discovery/allowlisting, but an explicit `tools`
|
||||
// list still has to expose the Skill dispatcher itself.
|
||||
tools: [...toolConfig.tools, ...(hasSkills ? ["Skill"] : [])],
|
||||
allowedTools: [...toolConfig.allowedTools],
|
||||
// TodoWrite is always available so multi-step runs can surface a live checklist
|
||||
// on the Feishu card (Manus-style progress), even when a role whitelists tools.
|
||||
tools: uniqueTools([
|
||||
...toolConfig.tools,
|
||||
"TodoWrite",
|
||||
...(hasSkills ? ["Skill"] : []),
|
||||
]),
|
||||
allowedTools: uniqueTools([...toolConfig.allowedTools, "TodoWrite"]),
|
||||
maxTurns: cap,
|
||||
includePartialMessages: true,
|
||||
// ADR-0018: bypass interactive prompts (headless server); the sandbox
|
||||
@@ -178,7 +184,10 @@ export async function runAgent(req: RunRequest): Promise<RunResult> {
|
||||
// The project workspace is untrusted input. Do not load user/project
|
||||
// settings that could widen tools, hooks, MCP servers, or sandbox paths.
|
||||
settingSources: [],
|
||||
settings: { disableBundledSkills: true },
|
||||
settings: {
|
||||
disableBundledSkills: true,
|
||||
todoFeatureEnabled: true,
|
||||
},
|
||||
...(hasSkills && security.skillPluginRoot !== undefined
|
||||
? { plugins: [{ type: "local" as const, path: security.skillPluginRoot, skipMcpDiscovery: true }] }
|
||||
: {}),
|
||||
@@ -405,3 +414,11 @@ function extractToolResultText(content: unknown): string {
|
||||
}
|
||||
return parts.join("\n");
|
||||
}
|
||||
|
||||
function uniqueTools(tools: readonly string[]): string[] {
|
||||
const out: string[] = [];
|
||||
for (const tool of tools) {
|
||||
if (!out.includes(tool)) out.push(tool);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user