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:
Diego Rodrigues de Sa e Souza
2026-08-04 10:06:31 -03:00
committed by GitHub
parent a8216c92fe
commit 2cb77bbca7
3 changed files with 38 additions and 3 deletions

View File

@@ -0,0 +1 @@
- **fix(translator):** harden Claude format detection for relative message endpoints and kebab-case version metadata. (thanks @ervareza)

View File

@@ -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";
}

View 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"
);
});