/** * TodoWrite tool — visible task planning (audit D5-5). * * The tool itself is a no-op acknowledgement: its value is the bot:tool event * the session already emits for every tool_use — on the dashboard that commits * the streamed text as its own bubble (the plan "rhythm" claude users see), * and on WhatsApp/Telegram it flushes the pending chunk as an intermediate * progress message. Claude's TodoWrite works the same way from the harness's * point of view. Deliberately NOT in FILE_TOOL_NAMES — updating a plan must * never trigger a backend restart. */ import type { PiTool } from './types.js'; export const todoWriteTool: PiTool = { name: 'TodoWrite', description: 'Maintain a visible todo list for multi-step tasks. Call it when you start a task (all items pending, ' + 'first in_progress) and again after each step completes. Exactly one item should be in_progress at a time.', inputSchema: { type: 'object', properties: { todos: { type: 'array', description: 'The complete, updated todo list (replaces the previous one).', items: { type: 'object', properties: { content: { type: 'string', description: 'Imperative description, e.g. "Add the API route".' }, status: { type: 'string', enum: ['pending', 'in_progress', 'completed'] }, activeForm: { type: 'string', description: 'Present-continuous label shown while in_progress.' }, }, required: ['content', 'status'], }, }, }, required: ['todos'], }, async run(input) { const todos = Array.isArray(input?.todos) ? input.todos : []; if (todos.length === 0) return { output: 'Todo list cleared.' }; const done = todos.filter((t: any) => t?.status === 'completed').length; return { output: `Todo list updated (${done}/${todos.length} completed).` }; }, };