From 53c05adf928e473f7eaa8ff5fe4462e92bf60dfd Mon Sep 17 00:00:00 2001 From: milind-soni Date: Fri, 21 Aug 2026 16:46:15 +0530 Subject: [PATCH 1/2] fix(codex): preserve full shell commands --- server/drivers/codex.test.ts | 17 +++++++++++++++++ server/drivers/codex.ts | 4 ++-- server/testing/fake-codex-app-server.ts | 11 +++++++++-- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/server/drivers/codex.test.ts b/server/drivers/codex.test.ts index 5b79cdbd83..db95ab2a81 100644 --- a/server/drivers/codex.test.ts +++ b/server/drivers/codex.test.ts @@ -124,6 +124,23 @@ describe("CodexDriver turns (fake app-server)", () => { expect(threadStart.params).toMatchObject({ model: "gpt-5.6-sol", modelProvider: "openai" }); }); + it("keeps the full command when a Windows interpreter prefix is long", async () => { + await create({ mode: "windows-command" }); + await instance.adapter.sendTurn({ threadId: "t-windows-command", text: "read notes" }); + await recorder.until((event) => event.type === "turn.completed"); + + const command = [ + "\"C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\"", + "-Command", + "\"Get-Content -Raw -LiteralPath 'C:\\Users\\Ada\\workspaces\\research\\NOTES.md'\"", + ].join(" "); + expect(command.length).toBeGreaterThan(80); + expect(recorder.events.find((event) => event.type === "item.started")).toMatchObject({ + type: "item.started", + title: command, + }); + }); + it("uses the instance environment for the Codex process", async () => { const codexHome = join(scratch, "custom-codex-home"); await create({ environment: { CODEX_HOME: codexHome } }); diff --git a/server/drivers/codex.ts b/server/drivers/codex.ts index 3b604c749c..e186784cff 100644 --- a/server/drivers/codex.ts +++ b/server/drivers/codex.ts @@ -258,7 +258,7 @@ export const CodexDriver: ProviderDriver = { const requestId = newId(); const summary = typeof params.command === "string" - ? params.command.slice(0, 200) + ? params.command : Array.isArray(params.questions) ? params.questions.map((q: any) => q.question ?? q.header).filter(Boolean).join(" · ") : typeof params.reason === "string" @@ -325,7 +325,7 @@ export const CodexDriver: ProviderDriver = { const item = p.item ?? {}; const title = item.type === "commandExecution" - ? String(item.command ?? "shell").slice(0, 80) + ? String(item.command ?? "shell") : item.type === "fileChange" ? "edit" : item.type === "mcpToolCall" diff --git a/server/testing/fake-codex-app-server.ts b/server/testing/fake-codex-app-server.ts index 0251628193..bd3575293f 100755 --- a/server/testing/fake-codex-app-server.ts +++ b/server/testing/fake-codex-app-server.ts @@ -4,7 +4,7 @@ // initialize/thread/turn handshake, then plays a scripted turn. Like the // real app-server, it never exits on its own — the driver kills it. // -// FAKE_CODEX_MODE happy (default) | approval | resume | stream | +// FAKE_CODEX_MODE happy (default) | approval | resume | stream | windows-command | // logged-in-stdout | logged-out | unauthorized // FAKE_CODEX_DUMP path to write {argv, env, calls, decision} as JSON // @@ -134,7 +134,14 @@ process.stdin.on("data", (chunk) => { break; } out({ jsonrpc: "2.0", id: msg.id, result: { ok: true } }); - notify("item/started", { item: { id: "i1", type: "commandExecution", command: "ls -la" } }); + const command = mode === "windows-command" + ? [ + "\"C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\"", + "-Command", + "\"Get-Content -Raw -LiteralPath 'C:\\Users\\Ada\\workspaces\\research\\NOTES.md'\"", + ].join(" ") + : "ls -la"; + notify("item/started", { item: { id: "i1", type: "commandExecution", command } }); notify("item/started", { item: { id: "w1", type: "webSearch", query: "OpenMausBot" } }); if (mode === "approval") { out({ jsonrpc: "2.0", id: 100, method: "execCommandApproval", params: { command: "rm -rf scratch" } }); From 469d3d6921e24e06bb6284d3b7e31332350b552a Mon Sep 17 00:00:00 2001 From: milind-soni Date: Fri, 21 Aug 2026 16:50:35 +0530 Subject: [PATCH 2/2] test(codex): cover full approval commands --- server/drivers/codex.test.ts | 10 +++++++--- server/testing/fake-codex-app-server.ts | 10 ++++++---- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/server/drivers/codex.test.ts b/server/drivers/codex.test.ts index db95ab2a81..c658bd46e5 100644 --- a/server/drivers/codex.test.ts +++ b/server/drivers/codex.test.ts @@ -127,18 +127,22 @@ describe("CodexDriver turns (fake app-server)", () => { it("keeps the full command when a Windows interpreter prefix is long", async () => { await create({ mode: "windows-command" }); await instance.adapter.sendTurn({ threadId: "t-windows-command", text: "read notes" }); - await recorder.until((event) => event.type === "turn.completed"); const command = [ "\"C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\"", "-Command", - "\"Get-Content -Raw -LiteralPath 'C:\\Users\\Ada\\workspaces\\research\\NOTES.md'\"", + `\"Get-Content -Raw -LiteralPath 'C:\\Users\\Ada\\workspaces\\${"very-long-folder\\".repeat(8)}NOTES.md'\"`, ].join(" "); - expect(command.length).toBeGreaterThan(80); + expect(command.length).toBeGreaterThan(200); + const opened = await recorder.until((event) => event.type === "request.opened"); expect(recorder.events.find((event) => event.type === "item.started")).toMatchObject({ type: "item.started", title: command, }); + expect(opened).toMatchObject({ requestType: "permission", summary: command }); + + await instance.adapter.respondToRequest("t-windows-command", opened.requestId!, { behavior: "allow" }); + await recorder.until((event) => event.type === "turn.completed"); }); it("uses the instance environment for the Codex process", async () => { diff --git a/server/testing/fake-codex-app-server.ts b/server/testing/fake-codex-app-server.ts index bd3575293f..d1017c9284 100755 --- a/server/testing/fake-codex-app-server.ts +++ b/server/testing/fake-codex-app-server.ts @@ -121,7 +121,7 @@ process.stdin.on("data", (chunk) => { case "thread/start": out({ jsonrpc: "2.0", id: msg.id, result: { thread: { id: "codex-thread-1" }, model: "fake-codex-model" } }); break; - case "turn/start": + case "turn/start": { if (mode === "unauthorized") { out({ jsonrpc: "2.0", @@ -138,18 +138,20 @@ process.stdin.on("data", (chunk) => { ? [ "\"C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\"", "-Command", - "\"Get-Content -Raw -LiteralPath 'C:\\Users\\Ada\\workspaces\\research\\NOTES.md'\"", + `\"Get-Content -Raw -LiteralPath 'C:\\Users\\Ada\\workspaces\\${"very-long-folder\\".repeat(8)}NOTES.md'\"`, ].join(" ") : "ls -la"; notify("item/started", { item: { id: "i1", type: "commandExecution", command } }); notify("item/started", { item: { id: "w1", type: "webSearch", query: "OpenMausBot" } }); - if (mode === "approval") { - out({ jsonrpc: "2.0", id: 100, method: "execCommandApproval", params: { command: "rm -rf scratch" } }); + if (mode === "approval" || mode === "windows-command") { + const approvalCommand = mode === "windows-command" ? command : "rm -rf scratch"; + out({ jsonrpc: "2.0", id: 100, method: "execCommandApproval", params: { command: approvalCommand } }); // turn continues from the approval response handler above } else { finishTurn(); } break; + } default: if (msg.id !== undefined) out({ jsonrpc: "2.0", id: msg.id, result: {} }); }