diff --git a/open-sse/config/providers/registry/codex/index.ts b/open-sse/config/providers/registry/codex/index.ts index 6b67797fa3..a70549f7c1 100644 --- a/open-sse/config/providers/registry/codex/index.ts +++ b/open-sse/config/providers/registry/codex/index.ts @@ -11,6 +11,9 @@ export const codexProvider: RegistryEntry = { alias: "cx", format: "openai-responses", executor: "codex", + // Codex /responses is upstream-streaming even when the client requested stream:false. + // Mark it forceStream so chatCore drains terminal SSE into JSON instead of waiting for EOF. + forceStream: true, baseUrl: "https://chatgpt.com/backend-api/codex/responses", reasoningTransport: "opaque", authType: "oauth", diff --git a/tests/unit/cline-force-stream.test.ts b/tests/unit/cline-force-stream.test.ts index 2c8ea5caaf..e4035ec218 100644 --- a/tests/unit/cline-force-stream.test.ts +++ b/tests/unit/cline-force-stream.test.ts @@ -22,14 +22,20 @@ test("clinepass provider is flagged forceStream (streaming-only upstream)", () = assert.equal(REGISTRY.clinepass?.forceStream, true); }); +test("codex provider is flagged forceStream because /responses always streams upstream", () => { + assert.equal(REGISTRY.codex?.forceStream, true); +}); + test("upstreamStream is forced true for a forceStream provider even when the client sent stream:false", () => { // Mirror the chatCore wiring: providerRequiresStreaming derives from the // registry flag, and upstreamStream ORs it in so the upstream always streams. - const providerRequiresStreaming = REGISTRY.cline?.forceStream === true; - const isClaudeCodeCompatible = false; - const clientStream = false; // client asked for JSON - const upstreamStream = clientStream || isClaudeCodeCompatible || providerRequiresStreaming; - assert.equal(upstreamStream, true); + for (const provider of ["cline", "codex"] as const) { + const providerRequiresStreaming = REGISTRY[provider]?.forceStream === true; + const isClaudeCodeCompatible = false; + const clientStream = false; // client asked for JSON + const upstreamStream = clientStream || isClaudeCodeCompatible || providerRequiresStreaming; + assert.equal(upstreamStream, true, provider); + } }); test("client-facing stream stays false for a stream:false JSON caller (so SSE→JSON conversion runs)", () => {