mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-31 04:12:10 +03:00
fix(sse): preserve Responses combo payloads (#8310)
This commit is contained in:
1
changelog.d/fixes/8310-combo-responses-payload.md
Normal file
1
changelog.d/fixes/8310-combo-responses-payload.md
Normal file
@@ -0,0 +1 @@
|
||||
- **fix(sse):** Combo middleware preserves OpenAI Responses request bodies and maps combo system overrides to `instructions`, preventing Responses-native fallbacks from receiving an unsupported `messages` parameter. ([#8310](https://github.com/diegosouzapw/OmniRoute/pull/8310)) — thanks @ridho9
|
||||
@@ -180,16 +180,24 @@ export function applyComboAgentMiddleware(
|
||||
): { body: Record<string, unknown>; pinnedModel: string | null } {
|
||||
if (!comboConfig) return { body, pinnedModel: null };
|
||||
|
||||
let messages: Message[] = Array.isArray(body.messages) ? [...body.messages] : [];
|
||||
const hasMessages = Array.isArray(body.messages);
|
||||
const isResponsesRequest =
|
||||
Object.prototype.hasOwnProperty.call(body, "input") ||
|
||||
Object.prototype.hasOwnProperty.call(body, "instructions");
|
||||
const systemMessage =
|
||||
typeof comboConfig.system_message === "string" && comboConfig.system_message.trim()
|
||||
? comboConfig.system_message
|
||||
: null;
|
||||
let messages: Message[] = hasMessages ? [...(body.messages as Message[])] : [];
|
||||
let pinnedModel: string | null = null;
|
||||
|
||||
// Context cache pinning is handled server-side in combo.ts via
|
||||
// session_model_history. No client-side <omniModel> tag extraction needed.
|
||||
pinnedModel = null;
|
||||
|
||||
// 2. System message override
|
||||
if (comboConfig.system_message && comboConfig.system_message.trim()) {
|
||||
messages = applySystemMessageOverride(messages, comboConfig.system_message);
|
||||
// 2. System message override. Responses API uses top-level instructions instead of messages.
|
||||
if (systemMessage && !isResponsesRequest) {
|
||||
messages = applySystemMessageOverride(messages, systemMessage);
|
||||
}
|
||||
|
||||
// 3. Tool filter
|
||||
@@ -206,7 +214,8 @@ export function applyComboAgentMiddleware(
|
||||
return {
|
||||
body: {
|
||||
...body,
|
||||
messages,
|
||||
...(isResponsesRequest && systemMessage ? { instructions: systemMessage } : {}),
|
||||
...(hasMessages ? { messages } : {}),
|
||||
...(filteredTools !== body.tools && { tools: filteredTools }),
|
||||
},
|
||||
pinnedModel,
|
||||
|
||||
@@ -184,6 +184,32 @@ test("combo agent middleware covers system override, tool filtering, tag strippi
|
||||
assert.equal(passthrough.body, body);
|
||||
});
|
||||
|
||||
test("combo agent middleware preserves Responses API input and instructions", () => {
|
||||
const body = {
|
||||
model: "combo/default",
|
||||
input: "Reply with exactly: pong",
|
||||
};
|
||||
|
||||
const unchanged = comboAgentMiddleware.applyComboAgentMiddleware(
|
||||
body,
|
||||
{ context_cache_protection: true },
|
||||
"openai/gpt-4o"
|
||||
);
|
||||
assert.deepEqual(unchanged.body, body);
|
||||
assert.equal(Object.hasOwn(unchanged.body, "messages"), false);
|
||||
|
||||
const overridden = comboAgentMiddleware.applyComboAgentMiddleware(
|
||||
{ ...body, instructions: "client instruction" },
|
||||
{ system_message: "combo instruction" },
|
||||
"openai/gpt-4o"
|
||||
);
|
||||
assert.deepEqual(overridden.body, {
|
||||
...body,
|
||||
instructions: "combo instruction",
|
||||
});
|
||||
assert.equal(Object.hasOwn(overridden.body, "messages"), false);
|
||||
});
|
||||
|
||||
test("rate limit semaphore covers immediate acquire, timeout, cooldown drain and reset", async () => {
|
||||
const release = await rateLimitSemaphore.acquire("model-a", { maxConcurrency: 1 });
|
||||
assert.deepEqual(rateLimitSemaphore.getStats()["model-a"], {
|
||||
|
||||
Reference in New Issue
Block a user