fix: use MODEL_ROUTES directly for Anthropic proxy routing
Remove the ANTHROPIC_MODEL_MAP layer — /v1/messages now uses the same model names as /v1/chat/completions (deepseek-v4-flash-free, gpt-5.4-mini-no-login, deepseek/deepseek-v4-flash). This way users send the original model name and it routes to the correct backend. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
2fca9febe4
commit
2fead57d0f
+2
-2
@@ -28,7 +28,7 @@ import { checkBodySize } from "../src/middleware/body-limiter";
|
|||||||
import { createRateLimiter } from "../src/middleware/rate-limiter";
|
import { createRateLimiter } from "../src/middleware/rate-limiter";
|
||||||
import { logRelayEvent } from "../src/middleware/logger";
|
import { logRelayEvent } from "../src/middleware/logger";
|
||||||
import { handleChatCompletion, listModels } from "../src/lib/ai-proxy";
|
import { handleChatCompletion, listModels } from "../src/lib/ai-proxy";
|
||||||
import { handleAnthropicMessages, listAnthropicModels } from "../src/lib/anthropic-proxy";
|
import { handleAnthropicMessages } from "../src/lib/anthropic-proxy";
|
||||||
|
|
||||||
// ─── Configuration ──────────────────────────────────────────────────────────────
|
// ─── Configuration ──────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -428,7 +428,7 @@ export default {
|
|||||||
|
|
||||||
// Models list
|
// Models list
|
||||||
if (url.pathname === "/v1/models" && req.method === "GET") {
|
if (url.pathname === "/v1/models" && req.method === "GET") {
|
||||||
const models = [...listModels(), ...listAnthropicModels()].map((id) => ({
|
const models = listModels().map((id) => ({
|
||||||
id,
|
id,
|
||||||
object: "model",
|
object: "model",
|
||||||
created: Math.floor(Date.now() / 1000),
|
created: Math.floor(Date.now() / 1000),
|
||||||
|
|||||||
+1
-1
@@ -29,7 +29,7 @@ import { createRateLimiter } from "./middleware/rate-limiter";
|
|||||||
import { logRelayEvent } from "./middleware/logger";
|
import { logRelayEvent } from "./middleware/logger";
|
||||||
import { ProxyPool } from "./lib/proxy-pool";
|
import { ProxyPool } from "./lib/proxy-pool";
|
||||||
import { handleChatCompletion, listModels } from "./lib/ai-proxy";
|
import { handleChatCompletion, listModels } from "./lib/ai-proxy";
|
||||||
import { handleAnthropicMessages, listAnthropicModels } from "./lib/anthropic-proxy";
|
import { handleAnthropicMessages } from "./lib/anthropic-proxy";
|
||||||
|
|
||||||
import type { Server, ServerWebSocket } from "bun";
|
import type { Server, ServerWebSocket } from "bun";
|
||||||
|
|
||||||
|
|||||||
@@ -40,53 +40,20 @@ interface AnthropicResponse {
|
|||||||
usage: { input_tokens: number; output_tokens: number };
|
usage: { input_tokens: number; output_tokens: number };
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Anthropic model → backend model mapping ──────────────────────────────────
|
// ─── Model resolution ─────────────────────────────────────────────────────────
|
||||||
|
|
||||||
/** User-facing Anthropic model name → { backendModel, backendConfig }. */
|
/** Resolve a model name to a backend config (uses MODEL_ROUTES directly). */
|
||||||
const ANTHROPIC_MODEL_MAP: Record<
|
|
||||||
string,
|
|
||||||
{ backendModel: string; config: BackendConfig }
|
|
||||||
> = {
|
|
||||||
"claude-sonnet-4-20250514": {
|
|
||||||
backendModel: "deepseek-v4-flash-free",
|
|
||||||
config: MODEL_ROUTES["deepseek-v4-flash-free"]!,
|
|
||||||
},
|
|
||||||
"claude-sonnet-4": {
|
|
||||||
backendModel: "deepseek-v4-flash-free",
|
|
||||||
config: MODEL_ROUTES["deepseek-v4-flash-free"]!,
|
|
||||||
},
|
|
||||||
"claude-3-haiku-20240307": {
|
|
||||||
backendModel: "gpt-5.4-mini-no-login",
|
|
||||||
config: MODEL_ROUTES["gpt-5.4-mini-no-login"]!,
|
|
||||||
},
|
|
||||||
"claude-3-haiku": {
|
|
||||||
backendModel: "gpt-5.4-mini-no-login",
|
|
||||||
config: MODEL_ROUTES["gpt-5.4-mini-no-login"]!,
|
|
||||||
},
|
|
||||||
"claude-opus-4-20250514": {
|
|
||||||
backendModel: "deepseek/deepseek-v4-flash",
|
|
||||||
config: MODEL_ROUTES["deepseek/deepseek-v4-flash"]!,
|
|
||||||
},
|
|
||||||
"claude-opus-4": {
|
|
||||||
backendModel: "deepseek/deepseek-v4-flash",
|
|
||||||
config: MODEL_ROUTES["deepseek/deepseek-v4-flash"]!,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// Also allow using raw backend model names directly
|
|
||||||
function resolveAnthropicModel(
|
function resolveAnthropicModel(
|
||||||
model: string,
|
model: string,
|
||||||
): { backendModel: string; config: BackendConfig } | undefined {
|
): { backendModel: string; config: BackendConfig } | undefined {
|
||||||
if (ANTHROPIC_MODEL_MAP[model]) return ANTHROPIC_MODEL_MAP[model];
|
|
||||||
// Fallback — try using the model name directly as a backend route
|
|
||||||
const direct = MODEL_ROUTES[model];
|
const direct = MODEL_ROUTES[model];
|
||||||
if (direct) return { backendModel: model, config: direct };
|
if (direct) return { backendModel: model, config: direct };
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** List all available Anthropic model names. */
|
/** List all available model names (same as OpenAI endpoint). */
|
||||||
export function listAnthropicModels(): string[] {
|
export function listAnthropicModels(): string[] {
|
||||||
return Object.keys(ANTHROPIC_MODEL_MAP);
|
return Object.keys(MODEL_ROUTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Translation: Anthropic → Backend (OpenAI-format) ───────────────────────
|
// ─── Translation: Anthropic → Backend (OpenAI-format) ───────────────────────
|
||||||
@@ -126,7 +93,7 @@ function anthropicToBackend(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const base: BackendBody = {
|
const base: BackendBody = {
|
||||||
model: anthReq.model,
|
model: backendModel,
|
||||||
messages,
|
messages,
|
||||||
max_tokens: anthReq.max_tokens,
|
max_tokens: anthReq.max_tokens,
|
||||||
temperature: anthReq.temperature,
|
temperature: anthReq.temperature,
|
||||||
@@ -144,7 +111,7 @@ function anthropicToBackend(
|
|||||||
// If backend has a custom adaptRequest, use it
|
// If backend has a custom adaptRequest, use it
|
||||||
if (config.adaptRequest) {
|
if (config.adaptRequest) {
|
||||||
return config.adaptRequest({
|
return config.adaptRequest({
|
||||||
model: anthReq.model,
|
model: backendModel,
|
||||||
messages,
|
messages,
|
||||||
temperature: anthReq.temperature,
|
temperature: anthReq.temperature,
|
||||||
max_tokens: anthReq.max_tokens,
|
max_tokens: anthReq.max_tokens,
|
||||||
|
|||||||
+2
-2
@@ -27,7 +27,7 @@ import { checkBodySize } from "./middleware/body-limiter";
|
|||||||
import { createRateLimiter } from "./middleware/rate-limiter";
|
import { createRateLimiter } from "./middleware/rate-limiter";
|
||||||
import { logRelayEvent } from "./middleware/logger";
|
import { logRelayEvent } from "./middleware/logger";
|
||||||
import { handleChatCompletion, listModels } from "./lib/ai-proxy";
|
import { handleChatCompletion, listModels } from "./lib/ai-proxy";
|
||||||
import { handleAnthropicMessages, listAnthropicModels } from "./lib/anthropic-proxy";
|
import { handleAnthropicMessages } from "./lib/anthropic-proxy";
|
||||||
|
|
||||||
// ─── Types ───────────────────────────────────────────────────────────────────────
|
// ─── Types ───────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -424,7 +424,7 @@ export default {
|
|||||||
|
|
||||||
// Models list
|
// Models list
|
||||||
if (url.pathname === "/v1/models" && req.method === "GET") {
|
if (url.pathname === "/v1/models" && req.method === "GET") {
|
||||||
const models = [...listModels(), ...listAnthropicModels()].map((id) => ({
|
const models = listModels().map((id) => ({
|
||||||
id,
|
id,
|
||||||
object: "model",
|
object: "model",
|
||||||
created: Math.floor(Date.now() / 1000),
|
created: Math.floor(Date.now() / 1000),
|
||||||
|
|||||||
Reference in New Issue
Block a user