mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-05 14:52:09 +03:00
feat(api): aceitar aliases explícitos para resposta sem stream (#1036)
Adds support for non-standard stream aliases (non_stream, disable_stream, disable_streaming, streaming=false). Includes unit tests. Integrated into release/v3.5.4.
This commit is contained in:
committed by
GitHub
parent
47d188541b
commit
58c5f7e373
@@ -106,7 +106,11 @@ import {
|
||||
isFallbackDecision,
|
||||
EMERGENCY_FALLBACK_CONFIG,
|
||||
} from "../services/emergencyFallback.ts";
|
||||
import { resolveStreamFlag, stripMarkdownCodeFence } from "../utils/aiSdkCompat.ts";
|
||||
import {
|
||||
resolveExplicitStreamAlias,
|
||||
resolveStreamFlag,
|
||||
stripMarkdownCodeFence,
|
||||
} from "../utils/aiSdkCompat.ts";
|
||||
import { generateRequestId } from "@/shared/utils/requestId";
|
||||
import { normalizePayloadForLog } from "@/lib/logPayloads";
|
||||
import { extractFacts } from "@/lib/memory/extraction";
|
||||
@@ -782,6 +786,22 @@ export async function handleChatCore({
|
||||
? clientRawRequest.headers.get("accept") || clientRawRequest.headers.get("Accept")
|
||||
: (clientRawRequest?.headers || {})["accept"] || (clientRawRequest?.headers || {})["Accept"];
|
||||
|
||||
const explicitStreamAlias = resolveExplicitStreamAlias(body);
|
||||
|
||||
// Remove non-standard non-stream aliases before provider translation/execution.
|
||||
// They are accepted for compatibility at the OmniRoute API boundary only.
|
||||
if (body && typeof body === "object") {
|
||||
const b = body as Record<string, unknown>;
|
||||
if (explicitStreamAlias !== undefined) {
|
||||
b.stream = explicitStreamAlias;
|
||||
}
|
||||
|
||||
delete b.non_stream;
|
||||
delete b.disable_stream;
|
||||
delete b.disable_streaming;
|
||||
delete b.streaming;
|
||||
}
|
||||
|
||||
const stream = resolveStreamFlag(body?.stream, acceptHeader);
|
||||
|
||||
// ── Phase 9.1: Semantic cache check (non-streaming, temp=0 only) ──
|
||||
|
||||
@@ -26,6 +26,33 @@ export function resolveStreamFlag(bodyStream: unknown, acceptHeader: unknown): b
|
||||
return !clientWantsJsonResponse(acceptHeader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves explicit stream aliases used by non-standard clients.
|
||||
* Returns:
|
||||
* - `true` -> explicit streaming intent
|
||||
* - `false` -> explicit non-stream intent
|
||||
* - `undefined` -> no explicit alias present
|
||||
*/
|
||||
export function resolveExplicitStreamAlias(body: unknown): boolean | undefined {
|
||||
if (!body || typeof body !== "object") return undefined;
|
||||
const b = body as Record<string, unknown>;
|
||||
|
||||
if (b.streaming === true) return true;
|
||||
if (b.streaming === false) return false;
|
||||
if (b.non_stream === true) return false;
|
||||
if (b.disable_stream === true) return false;
|
||||
if (b.disable_streaming === true) return false;
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Backward-compatible helper used by tests/legacy call sites.
|
||||
*/
|
||||
export function hasExplicitNoStreamParam(body: unknown): boolean {
|
||||
return resolveExplicitStreamAlias(body) === false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes surrounding markdown code fences when Claude wraps JSON payloads.
|
||||
* Example: ```json\n{"ok":true}\n``` -> {"ok":true}
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
const { clientWantsJsonResponse, resolveStreamFlag, stripMarkdownCodeFence } =
|
||||
await import("../../open-sse/utils/aiSdkCompat.ts");
|
||||
const {
|
||||
clientWantsJsonResponse,
|
||||
resolveStreamFlag,
|
||||
resolveExplicitStreamAlias,
|
||||
hasExplicitNoStreamParam,
|
||||
stripMarkdownCodeFence,
|
||||
} = await import("../../open-sse/utils/aiSdkCompat.ts");
|
||||
|
||||
test("T26: explicit stream:true takes priority over Accept application/json (#656)", () => {
|
||||
assert.equal(clientWantsJsonResponse("application/json"), true);
|
||||
@@ -42,3 +47,20 @@ test("T26: explicit stream:false always prevents streaming", () => {
|
||||
assert.equal(resolveStreamFlag(false, "text/event-stream"), false);
|
||||
assert.equal(resolveStreamFlag(false, undefined), false);
|
||||
});
|
||||
|
||||
test("T26: explicit non-stream aliases are detected", () => {
|
||||
assert.equal(hasExplicitNoStreamParam({ non_stream: true }), true);
|
||||
assert.equal(hasExplicitNoStreamParam({ disable_stream: true }), true);
|
||||
assert.equal(hasExplicitNoStreamParam({ disable_streaming: true }), true);
|
||||
assert.equal(hasExplicitNoStreamParam({ streaming: false }), true);
|
||||
assert.equal(hasExplicitNoStreamParam({ streaming: true }), false);
|
||||
assert.equal(hasExplicitNoStreamParam({ stream: false }), false);
|
||||
assert.equal(hasExplicitNoStreamParam({}), false);
|
||||
});
|
||||
|
||||
test("T26: explicit stream aliases resolve true/false correctly", () => {
|
||||
assert.equal(resolveExplicitStreamAlias({ streaming: true }), true);
|
||||
assert.equal(resolveExplicitStreamAlias({ streaming: false }), false);
|
||||
assert.equal(resolveExplicitStreamAlias({ disable_streaming: true }), false);
|
||||
assert.equal(resolveExplicitStreamAlias({}), undefined);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user