/**
* Prompt text for the todo tool and the tracker's injected messages.
*
* Ported from Oh My Pi's `packages/coding-agent/src/prompts/tools/todo.md`,
* `src/prompts/system/eager-todo.md`, and
* `src/prompts/system/mid-run-todo-nudge.md` (Handlebars templates flattened
* to plain template functions — the extension cannot rely on omp's prompt
* renderer).
*/
export interface EagerTodoContext {
/** Wire name of the todo tool (normally "todo"). */
toolRef: string;
/** Whether the eager mode is "always" (MUST-call) vs "preferred". */
forced: boolean;
}
/** First-turn eager todo prelude (`todo.eager: "preferred" | "always"`). */
export function renderEagerTodoPrompt(context: EagerTodoContext): string {
const { toolRef, forced } = context;
if (forced) {
return (
`\n` +
`Before substantive work, create a phased todo.\n\n` +
`You MUST call \`${toolRef}\` first in this turn.\n` +
`You MUST initialize the todo list with a single \`init\` op.\n` +
`You MUST cover the entire request from investigation through implementation and verification — not just the next immediate step.\n` +
`Task descriptions MUST be concise, specific 5-10 word labels.\n` +
`The \`init\` op only accepts phase names and task-label strings; do not invent task metadata fields.\n\n` +
`After \`${toolRef}\` succeeds, continue the request in the same turn.\n` +
`NEVER call \`${toolRef}\` again unless task state has materially changed.\n` +
``
);
}
return (
`\n` +
`Consider calling \`${toolRef}\` first to lay out a phased plan with a single \`init\` op. A good list covers the whole request — investigation through implementation and verification — not just the next step, with specific task descriptions a future turn could execute without re-planning.\n` +
`A useful list keeps each task to a concise, specific 5-10 word label; the \`init\` op only accepts phase names and task-label strings, so don't invent extra task metadata fields.\n` +
`If you create the list, continue the request in the same turn and avoid re-calling \`${toolRef}\` unless task state materially changes.\n` +
``
);
}
export interface MidRunNudgeContext {
/** Wire name of the todo tool (normally "todo"). */
toolRef: string;
incompleteCount: number;
}
/** Hidden mid-run nudge injected after many mutating tool results. */
export function renderMidRunNudgePrompt(context: MidRunNudgeContext): string {
const { toolRef, incompleteCount } = context;
const plural = incompleteCount !== 1;
return (
`\n` +
`${incompleteCount} todo item${plural ? "s" : ""} still open. If you finished a task since last \`${toolRef}\` update, mark it done now so progress stays visible; otherwise keep working.\n` +
``
);
}
/** The todo tool's description (what the model sees in the tools section). */
export const TODO_TOOL_DESCRIPTION = `**Tasks: verbatim content strings, NEVER auto-generated IDs; no "task-1"/"task-N". Pass content in \`task\`.**
Auto-promote only fires when NOTHING is in progress: an existing in-progress task keeps its place; completing any task with none in progress promotes the earliest still-open task (phase order) to \`in_progress\`. Out-of-order completion may move the pointer back to an earlier phase—expected; completed tasks NEVER revert.
## Operations
|\`op\`|Fields|Effect|
|---|---|---|
|\`init\`|\`list: [{phase, items: string[]}]\`|Initialize full list; replaces existing|
|\`init\`|\`items: string[]\`|Flattened single-phase init|
|\`start\`|\`task\`|Mark in progress|
|\`done\`|\`task\` or \`phase\`|Mark completed|
|\`drop\`|\`task\` or \`phase\`|Mark abandoned|
|\`block\`|\`task\` or \`phase\`; optional \`reason\`|Mark blocked: open, awaiting external input; excluded from stop-time incomplete-todo reminder|
|\`unblock\`|\`task\` or \`phase\`|Blocked task → \`pending\`|
|\`rm\`|optional \`task\` or \`phase\`|Remove task/phase; omit both → clear|
|\`append\`|\`phase\`; \`items: string[]\`|Append tasks to phase; lazily creates phase|
|\`view\`|—|Read-only; echo list|
## Anatomy
- Task content: 5–10 words; what, not how; unique identifier.
- Phase name: short noun phrase (e.g. \`Foundation\`, \`Auth\`, \`Verification\`); unique identifier. NEVER prefix \`1.\`, \`A)\`, \`Phase 1:\`.
## Rules
- Mark tasks done immediately after finishing; complete phases in order.
- NEVER make a todo call the turn's only tool call. Batch with real work: \`init\` with first reads/edits; each \`done\`/\`start\` with next action. Solo todo turns waste a round trip.
- Waiting on something you can't act on—a user decision, another agent, external service: \`block\` task (optional \`reason\`); remains tracked but avoids stop reminder. \`unblock\` when actionable. If blocker agent-actionable, \`append\` an unblocking task instead.
- Keep introduced \`task\`/\`phase\` strings stable.
- Lost exact task text: \`view\` echoes list; NEVER guess from memory.
## Create a list
- Task requires 3+ distinct steps.
- User explicitly requests one.
- User provides a set of tasks.
- New instructions arrive mid-task: capture before proceeding.
User gives multi-step plan—phased todo, numbered/bulleted checklist, or "N bugs/items/tasks":
- MUST \`init\` every item as its own task before working.
- Enumerate all; NEVER summarize into fewer tasks, sample "the important ones", drop items, or track the rest from memory.
`;