From bd04bb9cc6724458cfb7cfea1072d6a5c9ebab90 Mon Sep 17 00:00:00 2001 From: Diego Rodrigues de Sa e Souza Date: Sat, 29 Aug 2026 08:10:33 -0300 Subject: [PATCH] fix(sse): set X-OmniRoute-Selected-Connection-Id on successful combo dispatches (#11810) (#11986) Co-authored-by: Markus Hartung --- .../11810-combo-success-connection-header.md | 1 + src/sse/handlers/chat.ts | 8 +- ...s-selected-connection-header-11810.test.ts | 143 ++++++++++++++++++ 3 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 changelog.d/fixes/11810-combo-success-connection-header.md create mode 100644 tests/unit/combo-success-selected-connection-header-11810.test.ts diff --git a/changelog.d/fixes/11810-combo-success-connection-header.md b/changelog.d/fixes/11810-combo-success-connection-header.md new file mode 100644 index 0000000000..f79f29e324 --- /dev/null +++ b/changelog.d/fixes/11810-combo-success-connection-header.md @@ -0,0 +1 @@ +- fix(sse): set X-OmniRoute-Selected-Connection-Id on successful combo dispatches so downstream consumers stop falling back to an empty connection id (#11810) diff --git a/src/sse/handlers/chat.ts b/src/sse/handlers/chat.ts index 316227e962..d504d67086 100644 --- a/src/sse/handlers/chat.ts +++ b/src/sse/handlers/chat.ts @@ -1913,11 +1913,15 @@ async function handleSingleModelChat( } if (telemetry) telemetry.startPhase("finalize"); if (telemetry) telemetry.endPhase(); + const successResponse = withSelectedConnectionHeader( + result.response, + credentials?.connectionId + ); if (requestBody.stream === true) { - return wrapResponseWithOAuthSessionRelease(result.response, releaseOAuthSession); + return wrapResponseWithOAuthSessionRelease(successResponse, releaseOAuthSession); } releaseOAuthSession(); - return result.response; + return successResponse; } // A final hard-lease fence rejection is authoritative. It must never mutate diff --git a/tests/unit/combo-success-selected-connection-header-11810.test.ts b/tests/unit/combo-success-selected-connection-header-11810.test.ts new file mode 100644 index 0000000000..0d8b039a38 --- /dev/null +++ b/tests/unit/combo-success-selected-connection-header-11810.test.ts @@ -0,0 +1,143 @@ +/** + * Regression test for #11810. + * + * On a successful provider dispatch, `handleSingleModelChat()`'s + * `result.success` branch in `src/sse/handlers/chat.ts` used to return + * `result.response` (non-streaming) or + * `wrapResponseWithOAuthSessionRelease(result.response, releaseOAuthSession)` + * (streaming) directly, without first calling `withSelectedConnectionHeader()` + * — unlike every failure exit in the same function, which does call it. + * + * As a result `X-OmniRoute-Selected-Connection-Id` was absent on every + * successful response for a dynamically-selected (unpinned) connection, so + * combo.ts's consumers (success-decay, provider cooldown recovery, webhook + * attribution, session stickiness, LKGP) fell back to the target's static + * `connectionId`, which is empty for provider-level combo targets like + * `openai/o3-mini`. + */ + +import test from "node:test"; +import assert from "node:assert/strict"; + +import { createChatPipelineHarness } from "../integration/_chatPipelineHarness.ts"; + +const harness = await createChatPipelineHarness("combo-success-sel-conn-11810"); +const { buildOpenAIResponse, buildRequest, combosDb, handleChat, resetStorage, seedConnection } = + harness; + +const textEncoder = new TextEncoder(); + +function buildOpenAIStreamResponse(text = "hello streamed") { + return new Response( + new ReadableStream({ + start(controller) { + controller.enqueue( + textEncoder.encode( + `data: ${JSON.stringify({ + id: "chatcmpl_stream_11810", + object: "chat.completion.chunk", + created: 1, + model: "o3-mini", + choices: [{ index: 0, delta: { role: "assistant", content: text } }], + })}\n\n` + ) + ); + controller.enqueue(textEncoder.encode(`data: [DONE]\n\n`)); + controller.close(); + }, + }), + { + status: 200, + headers: { "Content-Type": "text/event-stream" }, + } + ); +} + +test.beforeEach(async () => { + await resetStorage(); +}); + +test.afterEach(async () => { + await resetStorage(); +}); + +test.after(async () => { + await harness.cleanup(); +}); + +test("#11810 combo success response carries X-OmniRoute-Selected-Connection-Id for a dynamically selected connection", async () => { + const connection = await seedConnection("openai", { + apiKey: "sk-openai-11810", + }); + + await combosDb.createCombo({ + name: "combo-11810-priority", + strategy: "priority", + config: { maxRetries: 0, retryDelayMs: 0 }, + // Provider-level target, no pinned connectionId — the connection is selected + // dynamically at dispatch time. + models: ["openai/o3-mini"], + }); + + globalThis.fetch = async () => buildOpenAIResponse("hello from o3-mini", "o3-mini"); + + const response = await handleChat( + buildRequest({ + body: { + model: "combo-11810-priority", + stream: false, + messages: [{ role: "user", content: "hi" }], + }, + }) + ); + + assert.equal(response.status, 200); + const body = (await response.json()) as { choices: Array<{ message: { content: string } }> }; + assert.equal(body.choices[0].message.content, "hello from o3-mini"); + + const selectedConnectionId = response.headers.get("X-OmniRoute-Selected-Connection-Id"); + assert.equal( + selectedConnectionId, + connection.id, + `expected the response to carry the dynamically selected connection id (${connection.id}), got ${selectedConnectionId}` + ); +}); + +test("#11810 combo streaming success response carries X-OmniRoute-Selected-Connection-Id for a dynamically selected connection", async () => { + const connection = await seedConnection("openai", { + apiKey: "sk-openai-11810-stream", + }); + + await combosDb.createCombo({ + name: "combo-11810-priority-stream", + strategy: "priority", + config: { maxRetries: 0, retryDelayMs: 0 }, + // Provider-level target, no pinned connectionId — the connection is selected + // dynamically at dispatch time. + models: ["openai/o3-mini"], + }); + + globalThis.fetch = async () => buildOpenAIStreamResponse("hello streamed from o3-mini"); + + const response = await handleChat( + buildRequest({ + body: { + model: "combo-11810-priority-stream", + stream: true, + messages: [{ role: "user", content: "hi" }], + }, + }) + ); + + assert.equal(response.status, 200); + + const selectedConnectionId = response.headers.get("X-OmniRoute-Selected-Connection-Id"); + assert.equal( + selectedConnectionId, + connection.id, + `expected the streaming response to carry the dynamically selected connection id (${connection.id}), got ${selectedConnectionId}` + ); + + // Drain the stream so the harness's fetch mock/db handles are released cleanly. + await response.text(); +});