From 80cfc4737c66d74df022b8458be64687c045cce9 Mon Sep 17 00:00:00 2001 From: roboomp Date: Wed, 17 Jun 2026 03:30:40 +0000 Subject: [PATCH] fix(rpc): honored todo setting opt-outs Preserved project-level todo.enabled, todo.reminders, and todo.eager settings in protocol hosts instead of forcing host defaults.\n\nFixes #2824 --- packages/coding-agent/CHANGELOG.md | 2 + packages/coding-agent/src/main.ts | 6 +- .../test/acp-lazy-startup.test.ts | 75 +++++++++++++++++++ 3 files changed, 79 insertions(+), 4 deletions(-) diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 957bead69..efd13448f 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -43,6 +43,8 @@ - Fixed startup model fallback choosing the plain OpenAI `gpt-5.5` provider before the Codex OAuth provider when both shared the same default model id, which could surface a misleading OpenAI 401 despite valid Codex credentials ([#2807](https://github.com/can1357/oh-my-pi/issues/2807)). - Fixed local auto-thinking classification for reasoning-capable tiny models by giving them the same safe answer budget as online reasoning classifiers, with a larger local floor for non-reasoning tiny models ([#2808](https://github.com/can1357/oh-my-pi/issues/2808)). +- Fixed RPC/ACP startup forcing todo settings back to host defaults, so project-level `todo.enabled`, `todo.reminders`, and `todo.eager` opt-outs now suppress protocol-mode todo prompt injection ([#2824](https://github.com/can1357/oh-my-pi/issues/2824)). + ### Removed - Removed the built-in `render_mermaid` tool and its `renderMermaid.enabled` setting, so it can no longer be invoked directly diff --git a/packages/coding-agent/src/main.ts b/packages/coding-agent/src/main.ts index b730a9b46..20ece691c 100644 --- a/packages/coding-agent/src/main.ts +++ b/packages/coding-agent/src/main.ts @@ -124,11 +124,9 @@ async function checkForNewVersion(currentVersion: string): Promise { }); } }); + + it("honors explicit todo settings for protocol hosts", async () => { + const { runRootCommand } = await import("@oh-my-pi/pi-coding-agent/main"); + + type ObservedTodoSettings = { + enabled: boolean; + reminders: boolean; + eager: "default" | "preferred" | "always"; + }; + + const runProtocolStartup = async (mode: "rpc" | "rpc-ui" | "acp"): Promise => { + using tempDir = TempDir.createSync("@omp-protocol-todo-settings-"); + const cwd = tempDir.path(); + const authStorage = await AuthStorage.create(path.join(cwd, "auth.db")); + const settings = Settings.isolated({ + "todo.enabled": false, + "todo.reminders": false, + "todo.eager": "always", + }); + let observed: ObservedTodoSettings | undefined; + const stopMessage = "stop test protocol todo settings"; + const observe = () => { + observed = { + enabled: settings.get("todo.enabled"), + reminders: settings.get("todo.reminders"), + eager: settings.get("todo.eager"), + }; + throw new Error(stopMessage); + }; + + try { + await runRootCommand( + { + mode, + messages: [], + fileArgs: [], + unknownFlags: new Map(), + unrecognizedFlags: [], + noSkills: true, + noRules: true, + noTools: true, + noLsp: true, + noExtensions: true, + sessionDir: cwd, + }, + [], + { + discoverAuthStorage: async () => authStorage, + settings, + createAgentSession: async () => observe(), + runAcpMode: async () => observe(), + }, + ); + } catch (error) { + if (!(error instanceof Error) || error.message !== stopMessage) { + throw error; + } + } finally { + authStorage.close(); + } + + if (!observed) { + throw new Error("Expected protocol mode to start"); + } + return observed; + }; + + for (const mode of ["rpc", "rpc-ui", "acp"] as const) { + await expect(runProtocolStartup(mode)).resolves.toEqual({ + enabled: false, + reminders: false, + eager: "always", + }); + } + }); it("answers initialize before creating the first AgentSession", async () => { const clientToAgent = new TransformStream(); const agentToClient = new TransformStream();