feat: add AI proxy routes to Workers and Vercel entry points

- Add /v1/chat/completions, /v1/messages, /v1/models routes to
  src/worker.ts (Cloudflare Workers) and api/relay.ts (Vercel)
- Import handleChatCompletion, handleAnthropicMessages handlers
- Using the same backend routing as the standalone server

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
MythEclipse
2026-06-10 23:45:38 +07:00
co-authored by Claude Fable 5
parent 4168a087a0
commit 38d7a83fe9
2 changed files with 92 additions and 0 deletions
+46
View File
@@ -26,6 +26,8 @@ import {
import { checkBodySize } from "./middleware/body-limiter";
import { createRateLimiter } from "./middleware/rate-limiter";
import { logRelayEvent } from "./middleware/logger";
import { handleChatCompletion, listModels } from "./lib/ai-proxy";
import { handleAnthropicMessages, listAnthropicModels } from "./lib/anthropic-proxy";
// ─── Types ───────────────────────────────────────────────────────────────────────
@@ -390,6 +392,50 @@ export default {
);
}
// AI proxy routes — OpenAI-compatible
if (url.pathname === "/v1/chat/completions") {
if (req.method === "OPTIONS") return createCorsPreflightResponse();
if (req.method !== "POST") return new Response("Method Not Allowed", { status: 405 });
try {
const body = await req.json();
return handleChatCompletion(body);
} catch {
return new Response(
JSON.stringify({ error: { message: "Invalid JSON body", type: "invalid_request_error" } }),
{ status: 400, headers: { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*" } },
);
}
}
// AI proxy routes — Anthropic-compatible
if (url.pathname === "/v1/messages") {
if (req.method === "OPTIONS") return createCorsPreflightResponse();
if (req.method !== "POST") return new Response("Method Not Allowed", { status: 405 });
try {
const body = await req.json();
return handleAnthropicMessages(body);
} catch {
return new Response(
JSON.stringify({ error: { message: "Invalid JSON body", type: "invalid_request_error" } }),
{ status: 400, headers: { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*" } },
);
}
}
// Models list
if (url.pathname === "/v1/models" && req.method === "GET") {
const models = [...listModels(), ...listAnthropicModels()].map((id) => ({
id,
object: "model",
created: Math.floor(Date.now() / 1000),
owned_by: "proxy",
}));
return new Response(
JSON.stringify({ object: "list", data: models }),
{ status: 200, headers: { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*" } },
);
}
// Generic HTTP relay
return handleRelay(req, env);
},