diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 5f02c11c4..9e9a75c37 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## [Unreleased] + ### Added - Debug tool with DAP (Debug Adapter Protocol) support for launching and attaching debuggers, setting breakpoints, stepping through execution, inspecting threads/stack/variables, and evaluating expressions @@ -18,6 +19,7 @@ ### Changed +- Eager todo enforcement now skips prompts ending with question marks or exclamation marks, treating them as queries or commands rather than statements requiring task planning - Chunk read output now displays fully-qualified anchor paths (e.g., `[class_Worker.fn_run#CRC]`) instead of bare names, making targets unambiguous for edits - Chunk edit tool documentation clarified: `target` must be the fully-qualified path with `#CRC` suffix; added guidance to run `read(path="file", sel="?")` for canonical target listings when anchor style is unclear - Chunk read tool documentation updated: `sel` parameter now documents the `?` selector for canonical target listings, and clarifies that default output shows full paths diff --git a/packages/coding-agent/src/session/agent-session.ts b/packages/coding-agent/src/session/agent-session.ts index 054e24e58..1d903ae86 100644 --- a/packages/coding-agent/src/session/agent-session.ts +++ b/packages/coding-agent/src/session/agent-session.ts @@ -2319,7 +2319,7 @@ export class AgentSession { return; } - const eagerTodoPrelude = !options?.synthetic ? this.#createEagerTodoPrelude() : undefined; + const eagerTodoPrelude = !options?.synthetic ? this.#createEagerTodoPrelude(expandedText) : undefined; const userContent: (TextContent | ImageContent)[] = [{ type: "text", text: expandedText }]; if (options?.images) { @@ -4049,7 +4049,7 @@ export class AgentSession { }); } - #createEagerTodoPrelude(): { message: AgentMessage; toolChoice: ToolChoice } | undefined { + #createEagerTodoPrelude(promptText: string): { message: AgentMessage; toolChoice: ToolChoice } | undefined { const eagerTodosEnabled = this.settings.get("todo.eager"); const todosEnabled = this.settings.get("todo.enabled"); if (!eagerTodosEnabled || !todosEnabled) { @@ -4063,6 +4063,11 @@ export class AgentSession { return undefined; } + const trimmedPromptText = promptText.trimEnd(); + if (trimmedPromptText.endsWith("?") || trimmedPromptText.endsWith("!")) { + return undefined; + } + if (!this.#toolRegistry.has("todo_write")) { logger.warn("Eager todo enforcement skipped because todo_write is unavailable", { activeToolNames: this.agent.state.tools.map(tool => tool.name), diff --git a/packages/coding-agent/test/agent-session-eager-todo.test.ts b/packages/coding-agent/test/agent-session-eager-todo.test.ts index 155b0d630..5a472c508 100644 --- a/packages/coding-agent/test/agent-session-eager-todo.test.ts +++ b/packages/coding-agent/test/agent-session-eager-todo.test.ts @@ -264,4 +264,32 @@ describe("AgentSession eager todo enforcement", () => { expect(session.getTodoPhases()).toHaveLength(1); expect(session.getTodoPhases()[0]?.tasks[0]?.content).toBe("List all git worktrees in the current repository"); }); + + it("skips eager todo enforcement for prompts ending with a question mark", async () => { + await session.prompt("list all work trees?"); + + expect(observedCalls).toHaveLength(1); + expect(observedCalls[0]).toEqual({ + toolChoice: undefined, + toolNames: ["todo_write", "bash"], + messageRoles: ["user"], + messageTexts: ["list all work trees?"], + lastMessageRole: "user", + lastMessageText: "list all work trees?", + }); + }); + + it("skips eager todo enforcement for prompts ending with an exclamation mark", async () => { + await session.prompt("list all work trees!"); + + expect(observedCalls).toHaveLength(1); + expect(observedCalls[0]).toEqual({ + toolChoice: undefined, + toolNames: ["todo_write", "bash"], + messageRoles: ["user"], + messageTexts: ["list all work trees!"], + lastMessageRole: "user", + lastMessageText: "list all work trees!", + }); + }); });