mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-22 06:42:19 +03:00
Compare commits
3 Commits
fix/13380-
...
fix/12968-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e0555a989 | ||
|
|
512ffb6a49 | ||
|
|
1603f4f5c2 |
@@ -0,0 +1 @@
|
||||
- **fix(sse):** stop misclassifying a truncated Anthropic-compatible `max_tokens` probe response (`content:[{type:"text",text:""}]`) as an empty upstream response (#12968) — thanks @pranay-gpt
|
||||
@@ -255,7 +255,9 @@ export function detectMalformedNonStream(resp: unknown): MalformedReason | null
|
||||
// 1) A block IS present but invalid (e.g. text:"", a lone "(empty response)"
|
||||
// sentinel, or only null entries) — the model genuinely produced no
|
||||
// usable output. That is a MALFORMED-200 empty_choices regardless of
|
||||
// stop_reason (parity with the OpenAI content:"" path).
|
||||
// stop_reason (parity with the OpenAI content:"" path) — UNLESS the
|
||||
// terminal stop_reason is one of the legitimate truncated-completion
|
||||
// exemptions below (#12968).
|
||||
// 2) `content: []` — no block at all. #9971: a truncated / non-terminal
|
||||
// body (no stop_reason) must not become empty_choices. A terminal
|
||||
// stop_reason with no output usually is empty_choices — except the
|
||||
@@ -265,12 +267,16 @@ export function detectMalformedNonStream(resp: unknown): MalformedReason | null
|
||||
// return content:[] + stop_reason max_tokens. Treating that as
|
||||
// empty_choices turns a valid 200 into MALFORMED-200 → 502 even
|
||||
// though errorClassifier would have let it through.
|
||||
if (content.length === 0) {
|
||||
const stopReason = typeof body.stop_reason === "string" ? body.stop_reason : "";
|
||||
if (stopReason.length === 0) return null;
|
||||
if (stopReason === "max_tokens" || stopReason === "tool_use") return null;
|
||||
return "empty_choices";
|
||||
}
|
||||
const stopReason = typeof body.stop_reason === "string" ? body.stop_reason : "";
|
||||
// #12968: the #9971 exemption above only fired when `content` was a
|
||||
// completely empty array. A tiny `max_tokens` probe against an
|
||||
// Anthropic-compatible shim can instead return content:[{type:"text",
|
||||
// text:""}] — one block, just with no visible text — which is the exact
|
||||
// same legitimate truncated-completion shape, so the exemption must apply
|
||||
// whenever there is no visible output, not only when content is [].
|
||||
if (stopReason === "max_tokens" || stopReason === "tool_use") return null;
|
||||
// content:[] with no stop_reason at all is non-terminal, not empty (#9971).
|
||||
if (content.length === 0 && stopReason.length === 0) return null;
|
||||
return "empty_choices";
|
||||
}
|
||||
|
||||
@@ -323,7 +329,8 @@ export function describeMalformedNonStream(
|
||||
): { message: string; code: string; type: string } {
|
||||
const body = resp && typeof resp === "object" ? (resp as Record<string, unknown>) : null;
|
||||
if (body?.object === "response" && body.status === "failed") {
|
||||
const err = body.error && typeof body.error === "object" ? (body.error as Record<string, unknown>) : null;
|
||||
const err =
|
||||
body.error && typeof body.error === "object" ? (body.error as Record<string, unknown>) : null;
|
||||
const rawMessage =
|
||||
typeof err?.message === "string" && err.message.trim().length > 0 ? err.message.trim() : null;
|
||||
return {
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { detectMalformedNonStream } from "../../open-sse/utils/diagnostics.ts";
|
||||
|
||||
// Exact upstream body captured in the issue (freeaiapikey.com probe response).
|
||||
const upstreamBody = {
|
||||
content: [{ text: "", type: "text" }],
|
||||
id: "msg_4d5e123dda0d4eda8055cd21",
|
||||
model: "anthropic/claude-sonnet-5",
|
||||
role: "assistant",
|
||||
stop_reason: "max_tokens",
|
||||
stop_sequence: null,
|
||||
type: "message",
|
||||
usage: {
|
||||
cache_creation_input_tokens: 2623,
|
||||
cache_read_input_tokens: 0,
|
||||
input_tokens: 2234,
|
||||
output_tokens: 1,
|
||||
},
|
||||
};
|
||||
|
||||
test("#12968 max_tokens probe with content:[{text:''}] must NOT be flagged empty_choices", () => {
|
||||
const reason = detectMalformedNonStream(upstreamBody);
|
||||
assert.equal(
|
||||
reason,
|
||||
null,
|
||||
`expected legitimate truncated-probe response to pass through, got reason=${reason}`
|
||||
);
|
||||
});
|
||||
|
||||
test("#12968 control — content:[] + max_tokens already exempted (#9971)", () => {
|
||||
const reason = detectMalformedNonStream({ ...upstreamBody, content: [] });
|
||||
assert.equal(reason, null);
|
||||
});
|
||||
|
||||
test("#12968 control — empty text block with end_turn stop_reason stays flagged", () => {
|
||||
const reason = detectMalformedNonStream({ ...upstreamBody, stop_reason: "end_turn" });
|
||||
assert.equal(reason, "empty_choices");
|
||||
});
|
||||
Reference in New Issue
Block a user