feat: Add Anthropic Compatible provider support
- Added support for 'anthropic-compatible' provider nodes in backend. - Implemented isAnthropicCompatible logic in open-sse for /messages URL construction and headers. - Added UI for creating and managing Anthropic Compatible providers in the dashboard. - Updated validation logic for Anthropic-compatible endpoints. - Sanitize base URL input (strip trailing /messages) to prevent 404s and improve UX. - Improve validation: use GET /models (2xx success), and support x-api-key / Authorization Bearer hybrid proxies. - Enable model import via /models for Anthropic Compatible providers. - Ensure Authorization is omitted when x-api-key is present to avoid strict proxy conflicts. - Resolve Anthropic-compatible credentials by prefix during model resolution (e.g., acx/model). - Update default executor to match provider header/url behavior for Anthropic-compatible providers.
This commit is contained in:
1 parent
7881db81ec
commit
da5bdef4cb
13 files changed
+614
-154
No files matched your search
@@ -2,7 +2,7 @@ import { NextResponse } from "next/server";
|
||||
import { getProviderConnectionById, updateProviderConnection, isCloudEnabled } from "@/lib/localDb";
|
||||
import { getConsistentMachineId } from "@/shared/utils/machineId";
|
||||
import { syncToCloud } from "@/app/api/sync/cloud/route";
|
||||
import { isOpenAICompatibleProvider } from "@/shared/constants/providers";
|
||||
import { isOpenAICompatibleProvider, isAnthropicCompatibleProvider } from "@/shared/constants/providers";
|
||||
import {
|
||||
GEMINI_CONFIG,
|
||||
ANTIGRAVITY_CONFIG,
|
||||
@@ -322,6 +322,32 @@ async function testApiKeyConnection(connection) {
|
||||
}
|
||||
}
|
||||
|
||||
// Anthropic Compatible providers - test via /models endpoint
|
||||
if (isAnthropicCompatibleProvider(connection.provider)) {
|
||||
let modelsBase = connection.providerSpecificData?.baseUrl;
|
||||
if (!modelsBase) {
|
||||
return { valid: false, error: "Missing base URL" };
|
||||
}
|
||||
try {
|
||||
modelsBase = modelsBase.replace(/\/$/, "");
|
||||
if (modelsBase.endsWith("/messages")) {
|
||||
modelsBase = modelsBase.slice(0, -9);
|
||||
}
|
||||
|
||||
const modelsUrl = `${modelsBase}/models`;
|
||||
const res = await fetch(modelsUrl, {
|
||||
headers: {
|
||||
"x-api-key": connection.apiKey,
|
||||
"anthropic-version": "2023-06-01",
|
||||
"Authorization": `Bearer ${connection.apiKey}`
|
||||
},
|
||||
});
|
||||
return { valid: res.ok, error: res.ok ? null : "Invalid API key or base URL" };
|
||||
} catch (err) {
|
||||
return { valid: false, error: err.message };
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
switch (connection.provider) {
|
||||
case "openai": {
|
||||
|
||||
Reference in new issue
Block a user