mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-05 14:52:09 +03:00
fix(translator): harden Claude format detection for model validation (#9253)
* fix(translator): harden Claude format detection for model validation Co-authored-by: Ervareza Naurian <rianskp644@gmail.com> Inspired-by: https://github.com/decolua/9router/pull/2949 * chore(changelog): fragment for #9253 --------- Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> Co-authored-by: Ervareza Naurian <rianskp644@gmail.com>
This commit is contained in:
committed by
GitHub
parent
a8216c92fe
commit
2cb77bbca7
@@ -0,0 +1 @@
|
||||
- **fix(translator):** harden Claude format detection for relative message endpoints and kebab-case version metadata. (thanks @ervareza)
|
||||
@@ -135,7 +135,17 @@ export function detectFormatFromEndpoint(body, endpointPath = "") {
|
||||
// Thin wrapper for call sites that only have the full request URL (not the bare endpoint
|
||||
// path chatCore already threads) — single source of truth stays detectFormatFromEndpoint.
|
||||
export function detectFormatFromUrl(body, requestUrl) {
|
||||
return detectFormatFromEndpoint(body, new URL(requestUrl).pathname);
|
||||
const rawUrl = typeof requestUrl === "string" ? requestUrl : "";
|
||||
let pathname = rawUrl;
|
||||
try {
|
||||
// Supplying a base URL keeps relative client endpoints (for example,
|
||||
// `/v1/messages`) valid while preserving pathname-only detection.
|
||||
pathname = new URL(rawUrl || "/", "http://omniroute.local").pathname;
|
||||
} catch {
|
||||
// Fall back to the raw value; detectFormatFromEndpoint is intentionally
|
||||
// safe for unknown or malformed paths.
|
||||
}
|
||||
return detectFormatFromEndpoint(body, pathname);
|
||||
}
|
||||
|
||||
// Detect request format from body structure
|
||||
@@ -193,7 +203,7 @@ export function detectFormat(body) {
|
||||
if (firstContent?.type === "text" && !body.model?.includes("/")) {
|
||||
// Could be Claude or OpenAI multimodal
|
||||
// Check for Claude-specific fields
|
||||
if (body.system || body.anthropic_version) {
|
||||
if (body.system || body.anthropic_version || body["anthropic-version"]) {
|
||||
return "claude";
|
||||
}
|
||||
// Check if image format is Claude (source.type) vs OpenAI (image_url.url)
|
||||
@@ -216,7 +226,7 @@ export function detectFormat(body) {
|
||||
|
||||
// If content is string, it's likely OpenAI (Claude also supports this)
|
||||
// Check for other Claude-specific indicators
|
||||
if (body.system !== undefined || body.anthropic_version) {
|
||||
if (body.system !== undefined || body.anthropic_version || body["anthropic-version"]) {
|
||||
return "claude";
|
||||
}
|
||||
|
||||
|
||||
24
tests/unit/translator-format-detection-2949.test.ts
Normal file
24
tests/unit/translator-format-detection-2949.test.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import { detectFormat, detectFormatFromUrl } from "../../open-sse/services/provider.ts";
|
||||
|
||||
test("detectFormatFromUrl accepts a relative /messages endpoint", () => {
|
||||
assert.equal(
|
||||
detectFormatFromUrl(
|
||||
{ messages: [{ role: "user", content: "validate this model" }] },
|
||||
"/v1/messages"
|
||||
),
|
||||
"claude"
|
||||
);
|
||||
});
|
||||
|
||||
test("detectFormat recognizes the kebab-case anthropic-version body field", () => {
|
||||
assert.equal(
|
||||
detectFormat({
|
||||
messages: [{ role: "user", content: "validate this model" }],
|
||||
"anthropic-version": "2023-06-01",
|
||||
}),
|
||||
"claude"
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user