mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-08 00:02:20 +03:00
The Codex Responses-over-WebSocket bridge bypassed the whole prompt-compression pipeline (and its analytics writes) that the HTTP/SSE path (chatCore.ts) runs on every request, via two gaps: 1. prepare() in codex-responses-ws/route.ts never called anything from open-sse/services/compression/* — it authenticated, injected memory, applied reasoning-routing, then went straight to executor.transformRequest(). 2. scripts/dev/responses-ws-proxy.mjs memoized the upstream connection in ensureUpstream() and only called the internal "prepare" action on the FIRST response.create of a WS session — every subsequent turn on a reused connection bypassed prepare() (and therefore compression) entirely. Fix: a new compression.ts module wires the core compression pipeline (settings resolution -> selectCompressionStrategy -> applyCompressionAsync -> compression_analytics/compression_engine_breakdown writes, reusing adaptBodyForCompression's existing Responses-API input[] adapter) into prepare(); responses-ws-proxy.mjs now re-runs prepare() (via a new shared runPrepare() helper) for every logical response.create turn on a reused connection, not just the first, without recreating the upstream socket. Regression test: tests/unit/responses-ws-proxy-compression-parity.test.ts proves the reused-connection bypass by execution (RED: 1 prepare call for 2 turns; GREEN after the fix: 2 prepare calls for 2 turns).
This commit is contained in:
committed by
GitHub
parent
b954a3a60f
commit
98b1aa34b5
@@ -579,6 +579,52 @@ class ResponsesWsSession {
|
||||
await this.forwardClientMessage(message);
|
||||
}
|
||||
|
||||
// #8052: shared by ensureUpstream() (first turn — also owns socket creation) and
|
||||
// forwardClientMessage() (subsequent turns on a reused connection). Calls the internal
|
||||
// "prepare" action — auth/policy/memory/reasoning-routing/compression — and refreshes
|
||||
// preparedContext, but never touches this.upstream/this.upstreamReady; the caller decides
|
||||
// whether a new upstream socket is needed.
|
||||
async runPrepare(message, responseBody) {
|
||||
const prepared = await callInternal(this.fetchImpl, this.baseUrl, this.bridgeSecret, "prepare", {
|
||||
requestUrl: this.requestUrl,
|
||||
headers: getAuthHeaders(this.requestUrl, this.requestHeaders),
|
||||
message,
|
||||
response: responseBody,
|
||||
});
|
||||
|
||||
if (!prepared.ok) {
|
||||
const message2 =
|
||||
prepared.json?.error?.message ||
|
||||
prepared.json?.message ||
|
||||
prepared.text ||
|
||||
"Codex WS prepare failed";
|
||||
const code = prepared.json?.error?.code || "codex_ws_prepare_failed";
|
||||
const error = new Error(message2);
|
||||
error.code = code;
|
||||
error.status = prepared.status;
|
||||
throw error;
|
||||
}
|
||||
|
||||
this.preparedContext = {
|
||||
upstreamUrl: toStringOrNull(prepared.json?.upstreamUrl),
|
||||
connectionId: toStringOrNull(prepared.json?.connectionId),
|
||||
account: toStringOrNull(prepared.json?.account),
|
||||
provider: toStringOrNull(prepared.json?.provider) || "codex",
|
||||
model: toStringOrNull(prepared.json?.model) || toStringOrNull(responseBody.model),
|
||||
requestedModel: toStringOrNull(responseBody.model),
|
||||
reasoningRouting:
|
||||
prepared.json?.reasoningRouting &&
|
||||
typeof prepared.json.reasoningRouting === "object" &&
|
||||
!Array.isArray(prepared.json.reasoningRouting)
|
||||
? prepared.json.reasoningRouting
|
||||
: null,
|
||||
serviceTier:
|
||||
toStringOrNull(responseBody.service_tier) || toStringOrNull(responseBody.serviceTier),
|
||||
};
|
||||
|
||||
return prepared;
|
||||
}
|
||||
|
||||
async ensureUpstream(firstMessage) {
|
||||
if (this.upstreamReady) return this.upstreamReady;
|
||||
|
||||
@@ -590,48 +636,7 @@ class ResponsesWsSession {
|
||||
this.firstResponseBody ||= responseBody;
|
||||
this.currentRequestBody = responseBody;
|
||||
|
||||
const prepared = await callInternal(
|
||||
this.fetchImpl,
|
||||
this.baseUrl,
|
||||
this.bridgeSecret,
|
||||
"prepare",
|
||||
{
|
||||
requestUrl: this.requestUrl,
|
||||
headers: getAuthHeaders(this.requestUrl, this.requestHeaders),
|
||||
message: firstMessage,
|
||||
response: responseBody,
|
||||
}
|
||||
);
|
||||
|
||||
if (!prepared.ok) {
|
||||
const message =
|
||||
prepared.json?.error?.message ||
|
||||
prepared.json?.message ||
|
||||
prepared.text ||
|
||||
"Codex WS prepare failed";
|
||||
const code = prepared.json?.error?.code || "codex_ws_prepare_failed";
|
||||
const error = new Error(message);
|
||||
error.code = code;
|
||||
error.status = prepared.status;
|
||||
throw error;
|
||||
}
|
||||
|
||||
this.preparedContext = {
|
||||
upstreamUrl: toStringOrNull(prepared.json?.upstreamUrl),
|
||||
connectionId: toStringOrNull(prepared.json?.connectionId),
|
||||
account: toStringOrNull(prepared.json?.account),
|
||||
provider: toStringOrNull(prepared.json?.provider) || "codex",
|
||||
model: toStringOrNull(prepared.json?.model) || toStringOrNull(responseBody.model),
|
||||
requestedModel: toStringOrNull(responseBody.model),
|
||||
reasoningRouting:
|
||||
prepared.json?.reasoningRouting &&
|
||||
typeof prepared.json.reasoningRouting === "object" &&
|
||||
!Array.isArray(prepared.json.reasoningRouting)
|
||||
? prepared.json.reasoningRouting
|
||||
: null,
|
||||
serviceTier:
|
||||
toStringOrNull(responseBody.service_tier) || toStringOrNull(responseBody.serviceTier),
|
||||
};
|
||||
const prepared = await this.runPrepare(firstMessage, responseBody);
|
||||
|
||||
const wsOptions = {
|
||||
// #5591: chrome_149 is not a wreq-js 2.3.1 profile (max chrome_147); the
|
||||
@@ -704,7 +709,16 @@ class ResponsesWsSession {
|
||||
// turn's own request body so persistHistory() attaches the right
|
||||
// clientRequest instead of always the first turn's.
|
||||
const nextTurnBody = getResponseCreatePayload(message);
|
||||
if (nextTurnBody !== null) this.currentRequestBody = nextTurnBody;
|
||||
if (nextTurnBody !== null) {
|
||||
this.currentRequestBody = nextTurnBody;
|
||||
// #8052: a reused connection must re-run "prepare" (auth/policy/memory/
|
||||
// reasoning-routing/compression) for every logical turn, not just the first —
|
||||
// otherwise every turn after the first bypasses the whole pipeline. This reuses
|
||||
// the already-established upstream transport; it must NOT recreate the socket.
|
||||
const prepared = await this.runPrepare(message, nextTurnBody);
|
||||
this.upstream.send(jsonStringifySafe(withPreparedResponseCreate(message, prepared.json.response)));
|
||||
return;
|
||||
}
|
||||
this.upstream.send(jsonStringifySafe(message));
|
||||
} catch (error) {
|
||||
const code = error?.code || "upstream_websocket_connect_failed";
|
||||
|
||||
Reference in New Issue
Block a user