Skip to content

Commit 4be6fa7

Browse files
Pandah97steipete
andauthored
fix(codex-supervisor): use truncateUtf16Safe for stderr tail truncation (#102590)
* fix(codex-supervisor): use truncateUtf16Safe for stderr tail truncation StdioCodexJsonRpcConnection includes stderr output in the transport-closed error message with a naive .slice(0, 1200) which can split surrogate pairs. Replace with truncateUtf16Safe(). * test(codex-supervisor): cover UTF-16-safe stderr tails --------- Co-authored-by: Peter Steinberger <[email protected]>
1 parent d27d7ba commit 4be6fa7

2 files changed

Lines changed: 27 additions & 1 deletion

File tree

extensions/codex-supervisor/src/json-rpc-client.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import * as net from "node:net";
88
import * as os from "node:os";
99
import * as path from "node:path";
1010
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
11+
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
1112
import WebSocket from "ws";
1213
import type { CodexJsonRpcConnection, CodexSupervisorEndpoint } from "./types.js";
1314

@@ -199,7 +200,7 @@ class StdioCodexJsonRpcConnection extends BaseCodexJsonRpcConnection {
199200
this.proc.once("close", () =>
200201
this.fail(
201202
new Error(
202-
`Codex app-server stdio transport closed. stderr_tail=${this.stderrTail.join("\n").slice(0, 1200)}`,
203+
`Codex app-server stdio transport closed. stderr_tail=${truncateUtf16Safe(this.stderrTail.join("\n"), 1200)}`,
203204
),
204205
),
205206
);

extensions/codex-supervisor/src/supervisor.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -909,6 +909,31 @@ describe("connectCodexAppServerEndpoint", () => {
909909
await expect(waitForFile(marker)).resolves.toBe("closed");
910910
});
911911

912+
it("keeps stdio close errors UTF-16 safe at the stderr tail boundary", async () => {
913+
const prefix = "x".repeat(1_199);
914+
const script = `
915+
process.stderr.write(${JSON.stringify(`${prefix}😀`)});
916+
process.exit(0);
917+
`;
918+
let closeError: unknown;
919+
920+
try {
921+
await connectCodexAppServerEndpoint({
922+
id: "exits",
923+
transport: "stdio-proxy",
924+
command: process.execPath,
925+
args: ["-e", script],
926+
});
927+
} catch (error) {
928+
closeError = error;
929+
}
930+
931+
expect(closeError).toBeInstanceOf(Error);
932+
expect((closeError as Error).message).toBe(
933+
`Codex app-server stdio transport closed. stderr_tail=${prefix}`,
934+
);
935+
});
936+
912937
it("fails a cached stdio connection cleanly after the child exits", async () => {
913938
const script = `
914939
const readline = require("node:readline");

0 commit comments

Comments
 (0)