mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-26 09:52:11 +03:00
feat(responses): degrade background mode to synchronous execution (#2164)
Integrated into release/v3.8.0 — degrades background:true to synchronous execution instead of 400, enabling Capy and similar clients that set background:true by default to work seamlessly.
This commit is contained in:
@@ -77,13 +77,28 @@ export function openaiResponsesToOpenAIRequest(
|
||||
}
|
||||
}
|
||||
|
||||
if (root.background) {
|
||||
throw unsupportedFeature(
|
||||
"Unsupported Responses API feature: background mode is not supported by omniroute"
|
||||
const result: JsonRecord = { ...root };
|
||||
|
||||
// background: true requests a deferred Responses API run (the upstream
|
||||
// returns 202 with response_id and the client polls GET /responses/<id>).
|
||||
// OmniRoute is a forward proxy that streams responses synchronously —
|
||||
// implementing the queue/poll contract would require persistence and a
|
||||
// separate retrieval surface. Degrade: log a marker when true was
|
||||
// actually requested (operators can observe clients that should be
|
||||
// reconfigured) and strip the flag. Clients that set background=true
|
||||
// opportunistically (Capy Captain Pro, Codex agents) work unchanged.
|
||||
// Clients that strictly require the async contract still observe a
|
||||
// completed response on the first poll and can adapt.
|
||||
if (result.background === true) {
|
||||
const providerStr = toString(credentialRecord.provider);
|
||||
const modelStr = toString(model);
|
||||
console.warn(
|
||||
`BACKGROUND_DEGRADE provider=${providerStr || "unknown"} model=${modelStr || "unknown"}`
|
||||
);
|
||||
}
|
||||
|
||||
const result: JsonRecord = { ...root };
|
||||
if (result.background !== undefined) {
|
||||
delete result.background;
|
||||
}
|
||||
const messages: JsonRecord[] = [];
|
||||
result.messages = messages;
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ test("Responses -> Chat filters orphan tool outputs and supports role-based mess
|
||||
});
|
||||
});
|
||||
|
||||
test("Responses -> Chat rejects unsupported built-in tools and background mode", () => {
|
||||
test("Responses -> Chat rejects unsupported built-in tools", () => {
|
||||
assert.throws(
|
||||
() =>
|
||||
openaiResponsesToOpenAIRequest(
|
||||
@@ -124,20 +124,77 @@ test("Responses -> Chat rejects unsupported built-in tools and background mode",
|
||||
),
|
||||
(error: any) => error.statusCode === 400 && error.errorType === "unsupported_feature"
|
||||
);
|
||||
});
|
||||
|
||||
assert.throws(
|
||||
() =>
|
||||
openaiResponsesToOpenAIRequest(
|
||||
"gpt-4o",
|
||||
{
|
||||
input: [],
|
||||
background: true,
|
||||
},
|
||||
false,
|
||||
null
|
||||
),
|
||||
(error: any) => error.statusCode === 400 && error.errorType === "unsupported_feature"
|
||||
);
|
||||
test("Responses -> Chat strips background flag and degrades to synchronous execution", () => {
|
||||
// Previously this threw 400 unsupported_feature. OmniRoute is a forward proxy
|
||||
// and cannot host the deferred run + poll contract, so background=true is
|
||||
// silently dropped and the request runs synchronously. Clients that set the
|
||||
// flag opportunistically (Capy Captain Pro, Codex agents) work unchanged.
|
||||
const warnLog: string[] = [];
|
||||
const originalWarn = console.warn;
|
||||
console.warn = (msg: unknown) => warnLog.push(String(msg));
|
||||
try {
|
||||
const result = openaiResponsesToOpenAIRequest(
|
||||
"gpt-5.5",
|
||||
{
|
||||
input: [{ role: "user", content: [{ type: "input_text", text: "hi" }] }],
|
||||
background: true,
|
||||
},
|
||||
true,
|
||||
{ provider: "codex" }
|
||||
);
|
||||
const r = result as Record<string, unknown>;
|
||||
assert.equal(r.background, undefined, "background flag must be stripped from output");
|
||||
assert.ok(Array.isArray(r.messages), "translation must complete and produce messages");
|
||||
assert.equal((r.messages as unknown[]).length, 1, "user message must be preserved");
|
||||
assert.ok(
|
||||
warnLog.some((m) => m.startsWith("BACKGROUND_DEGRADE provider=codex model=gpt-5.5")),
|
||||
"BACKGROUND_DEGRADE warning log must be emitted when background=true"
|
||||
);
|
||||
} finally {
|
||||
console.warn = originalWarn;
|
||||
}
|
||||
});
|
||||
|
||||
test("Responses -> Chat passes through when background flag is unset or false (no degrade log)", () => {
|
||||
// Verifies the inverse of the degradation case: when background is absent or
|
||||
// explicitly false, no warning should be emitted and the request body should
|
||||
// not carry a residual background field. Guards against accidental log spam
|
||||
// and confirms the degradation logic is conditional on background === true.
|
||||
const warnLog: string[] = [];
|
||||
const originalWarn = console.warn;
|
||||
console.warn = (msg: unknown) => warnLog.push(String(msg));
|
||||
try {
|
||||
// Case 1: background unset
|
||||
const r1 = openaiResponsesToOpenAIRequest(
|
||||
"gpt-5.5",
|
||||
{ input: [{ role: "user", content: [{ type: "input_text", text: "hi" }] }] },
|
||||
true,
|
||||
{ provider: "codex" }
|
||||
) as Record<string, unknown>;
|
||||
assert.equal(r1.background, undefined, "background must be absent on output (unset case)");
|
||||
|
||||
// Case 2: background explicitly false
|
||||
const r2 = openaiResponsesToOpenAIRequest(
|
||||
"gpt-5.5",
|
||||
{
|
||||
input: [{ role: "user", content: [{ type: "input_text", text: "hi" }] }],
|
||||
background: false,
|
||||
},
|
||||
true,
|
||||
{ provider: "codex" }
|
||||
) as Record<string, unknown>;
|
||||
assert.equal(r2.background, undefined, "background must be stripped on output (false case)");
|
||||
|
||||
assert.equal(
|
||||
warnLog.filter((m) => m.startsWith("BACKGROUND_DEGRADE")).length,
|
||||
0,
|
||||
"BACKGROUND_DEGRADE must NOT be emitted for unset or false values"
|
||||
);
|
||||
} finally {
|
||||
console.warn = originalWarn;
|
||||
}
|
||||
});
|
||||
|
||||
test("Chat -> Responses converts messages, tool calls, tool outputs, tools and pass-through params", () => {
|
||||
|
||||
Reference in New Issue
Block a user