mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-05 14:52:09 +03:00
Merge pull request #696 from benjaminkitt/fix/input-stream-invalid-boolean
Reviewed and approved via consolidated analysis. Fix is surgical (1 line removed) with 122 lines of regression tests covering stream=true, stream=false and guard scenarios. Resolves #677.
This commit is contained in:
@@ -462,7 +462,6 @@ export async function handleChatCore({
|
||||
FORMATS.CLAUDE,
|
||||
model,
|
||||
{ ...translatedBody, _disableToolPrefix: true },
|
||||
translatedBody,
|
||||
stream,
|
||||
credentials,
|
||||
provider,
|
||||
|
||||
122
tests/unit/claude-passthrough-stream-boolean.test.mjs
Normal file
122
tests/unit/claude-passthrough-stream-boolean.test.mjs
Normal file
@@ -0,0 +1,122 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
const { translateRequest } = await import("../../open-sse/translator/index.ts");
|
||||
const { FORMATS } = await import("../../open-sse/translator/formats.ts");
|
||||
|
||||
/**
|
||||
* Regression: claude-to-claude passthrough translateRequest was called with
|
||||
* an extra argument (the previous translatedBody object) before the stream
|
||||
* parameter, causing stream to receive an object instead of a boolean.
|
||||
* Upstream Anthropic rejected with: "stream: Input should be a valid boolean"
|
||||
*
|
||||
* Fix: open-sse/handlers/chatCore.ts — removed stray translatedBody arg.
|
||||
*/
|
||||
|
||||
test("Claude passthrough: stream field must be a boolean (stream=true)", () => {
|
||||
const body = {
|
||||
model: "claude-sonnet-4-6",
|
||||
max_tokens: 1024,
|
||||
stream: true,
|
||||
messages: [{ role: "user", content: [{ type: "text", text: "Hello" }] }],
|
||||
};
|
||||
|
||||
// Simulate the claude->openai->claude round-trip from chatCore passthrough
|
||||
const openaiBody = translateRequest(
|
||||
FORMATS.CLAUDE,
|
||||
FORMATS.OPENAI,
|
||||
body.model,
|
||||
structuredClone(body),
|
||||
true,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
const result = translateRequest(
|
||||
FORMATS.OPENAI,
|
||||
FORMATS.CLAUDE,
|
||||
body.model,
|
||||
{ ...openaiBody, _disableToolPrefix: true },
|
||||
true,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
assert.equal(typeof result.stream, "boolean", "stream must be a boolean, not an object");
|
||||
assert.equal(result.stream, true);
|
||||
});
|
||||
|
||||
test("Claude passthrough: stream field must be a boolean (stream=false)", () => {
|
||||
const body = {
|
||||
model: "claude-sonnet-4-6",
|
||||
max_tokens: 1024,
|
||||
stream: false,
|
||||
messages: [{ role: "user", content: [{ type: "text", text: "Hello" }] }],
|
||||
};
|
||||
|
||||
const openaiBody = translateRequest(
|
||||
FORMATS.CLAUDE,
|
||||
FORMATS.OPENAI,
|
||||
body.model,
|
||||
structuredClone(body),
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
const result = translateRequest(
|
||||
FORMATS.OPENAI,
|
||||
FORMATS.CLAUDE,
|
||||
body.model,
|
||||
{ ...openaiBody, _disableToolPrefix: true },
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
assert.equal(typeof result.stream, "boolean", "stream must be a boolean, not an object");
|
||||
assert.equal(result.stream, false);
|
||||
});
|
||||
|
||||
test("Claude passthrough: passing an object as stream propagates invalid type (guard)", () => {
|
||||
const body = {
|
||||
model: "claude-sonnet-4-6",
|
||||
max_tokens: 1024,
|
||||
messages: [{ role: "user", content: [{ type: "text", text: "Hello" }] }],
|
||||
};
|
||||
|
||||
const openaiBody = translateRequest(
|
||||
FORMATS.CLAUDE,
|
||||
FORMATS.OPENAI,
|
||||
body.model,
|
||||
structuredClone(body),
|
||||
true,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
// Simulate the old bug: passing openaiBody (an object) where stream should be
|
||||
const result = translateRequest(
|
||||
FORMATS.OPENAI,
|
||||
FORMATS.CLAUDE,
|
||||
body.model,
|
||||
{ ...openaiBody, _disableToolPrefix: true },
|
||||
openaiBody, // BUG: object instead of boolean
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
// This test documents the bug: if an object is passed as stream, it ends up
|
||||
// in the translated body as a non-boolean, which Anthropic rejects.
|
||||
assert.notEqual(
|
||||
typeof result.stream,
|
||||
"boolean",
|
||||
"passing an object as stream should produce a non-boolean (documents the bug)"
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user