@jacobbd/relay-ai 0.11.1 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/{chunk-TRM2WGI6.js → chunk-3R25QO5X.js} +11 -1
- package/dist/chunk-3R25QO5X.js.map +1 -0
- package/dist/{chunk-VXQ7ZVTW.js → chunk-FD5EDSBM.js} +2 -2
- package/dist/{chunk-YD6A3ZB3.js → chunk-HL3EZ4OU.js} +171 -18
- package/dist/chunk-HL3EZ4OU.js.map +1 -0
- package/dist/{chunk-O2XZFXHG.js → chunk-Z5GL4ALA.js} +34 -6
- package/dist/chunk-Z5GL4ALA.js.map +1 -0
- package/dist/cli.js +241 -234
- package/dist/cli.js.map +1 -1
- package/dist/core/index.js +11 -1
- package/dist/core/index.js.map +1 -1
- package/dist/{manual-models-VEBTRQFK.js → manual-models-A6FSQV3S.js} +3 -3
- package/dist/{provider-templates-JY3NXZK7.js → provider-templates-WXVGL4XE.js} +2 -2
- package/dist/{ui-command-WKPJI2CU.js → ui-command-J7PTTCM5.js} +6 -6
- package/package.json +1 -1
- package/dist/chunk-O2XZFXHG.js.map +0 -1
- package/dist/chunk-TRM2WGI6.js.map +0 -1
- package/dist/chunk-YD6A3ZB3.js.map +0 -1
- /package/dist/{chunk-VXQ7ZVTW.js.map → chunk-FD5EDSBM.js.map} +0 -0
- /package/dist/{manual-models-VEBTRQFK.js.map → manual-models-A6FSQV3S.js.map} +0 -0
- /package/dist/{provider-templates-JY3NXZK7.js.map → provider-templates-WXVGL4XE.js.map} +0 -0
- /package/dist/{ui-command-WKPJI2CU.js.map → ui-command-J7PTTCM5.js.map} +0 -0
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
|
|
28
28
|
Pick your backend:
|
|
29
29
|
|
|
30
|
-
- **Your providers** — configure once with `relay-ai providers` (ClinePass, Groq, Mistral, Nvidia, DeepSeek, custom OpenAI/Anthropic endpoints, and more)
|
|
30
|
+
- **Your providers** — configure once with `relay-ai providers` (Command Code, ClinePass, Groq, Mistral, Nvidia, DeepSeek, custom OpenAI/Anthropic endpoints, and more)
|
|
31
31
|
- **OpenCode Zen / Go** — cloud models with your OpenCode API key (optional; add via `relay-ai providers`)
|
|
32
32
|
- **One-time OpenCode import** — bring existing OpenCode provider settings into the registry (`relay-ai providers import`)
|
|
33
33
|
- **Google Vertex AI** — Claude on Vertex via `relay-ai server --vertex` and local gcloud credentials (no OpenCode key required)
|
|
@@ -62,7 +62,7 @@ Pick your backend:
|
|
|
62
62
|
- **Docker Server + Admin UI:** `docker compose up` (see **[docs/DOCKER.md](docs/DOCKER.md)**) runs an always-on admin UI + gateway for LAN/home-lab use — providers, favorites, and Start Server without a desktop keychain. Host CLI still launches Claude / Codex / Antigravity.
|
|
63
63
|
- **Server tab in the UI:** Run the same API gateway as `relay-ai server` — favorites-only or specific providers, discovery id masking for Claude Desktop / Cowork, local or network listen mode — from a browser form instead of a terminal wizard. Shows live URLs, the API key, and the full model catalog once started, with a one-click Stop.
|
|
64
64
|
- **Native provider registry:** `relay-ai providers` stores config in `~/.relay-ai/providers.json` and secrets in the OS keychain — no OpenCode binary required at launch. See **[docs/PROVIDERS.md](docs/PROVIDERS.md)** for a full list of providers and known issues.
|
|
65
|
-
- **Provider templates:** Add ClinePass, Groq, Mistral, Together, OpenRouter, and 15+ SDK-backed providers, plus custom OpenAI/Anthropic-compatible endpoints
|
|
65
|
+
- **Provider templates:** Add Command Code, ClinePass, Groq, Mistral, Together, OpenRouter, and 15+ SDK-backed providers, plus custom OpenAI/Anthropic-compatible endpoints
|
|
66
66
|
- **OpenCode import:** One-time migration from OpenCode (`providers import`); validates API keys and skips placeholders like `anything`
|
|
67
67
|
- **OpenCode Zen / Go:** Optional cloud backends when you have an OpenCode API key
|
|
68
68
|
- **SDK adapter proxy:** Non-Anthropic providers route through the Vercel AI SDK (same packages OpenCode uses), so Claude Code still speaks Anthropic format. Labeled `(via proxy)` in the picker
|
|
@@ -60,6 +60,16 @@ var init_provider_templates = __esm({
|
|
|
60
60
|
supported: true,
|
|
61
61
|
subscriptionRisk: true
|
|
62
62
|
},
|
|
63
|
+
{
|
|
64
|
+
id: "commandcode",
|
|
65
|
+
name: "Command Code",
|
|
66
|
+
authType: "api",
|
|
67
|
+
npm: "@ai-sdk/openai-compatible",
|
|
68
|
+
defaultBaseUrl: "https://api.commandcode.ai/provider/v1",
|
|
69
|
+
signupUrl: "https://commandcode.ai/settings",
|
|
70
|
+
modelSource: "commandcode",
|
|
71
|
+
supported: true
|
|
72
|
+
},
|
|
63
73
|
{
|
|
64
74
|
id: "groq",
|
|
65
75
|
name: "Groq",
|
|
@@ -463,4 +473,4 @@ export {
|
|
|
463
473
|
provider_templates_exports,
|
|
464
474
|
init_provider_templates
|
|
465
475
|
};
|
|
466
|
-
//# sourceMappingURL=chunk-
|
|
476
|
+
//# sourceMappingURL=chunk-3R25QO5X.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/provider-templates.ts"],"sourcesContent":["// src/provider-templates.ts — builtin provider templates for relay-ai providers add\n\nexport type ProviderAuthType = 'api' | 'oauth' | 'none';\nexport type ProviderModelSource = 'api-list' | 'static-seed' | 'manual-only' | 'zen-go-api' | 'cline-recommended' | 'commandcode';\n\nexport interface ProviderTemplate {\n id: string;\n name: string;\n /** Compact label for constrained model lists. */\n shortName?: string;\n authType: ProviderAuthType;\n /** Supported setup methods; defaults to the template's authType. */\n authMethods?: ProviderAuthType[];\n npm: string;\n defaultBaseUrl?: string;\n modelsPath?: string;\n signupUrl?: string;\n urlPlaceholder?: string;\n urlPrompt?: string;\n accountIdPrompt?: string;\n apiKeyOptional?: boolean;\n anonymousFreeModels?: boolean;\n /** Static headers this provider requires on every request (model listing and runtime). */\n headers?: Record<string, string>;\n modelSource: ProviderModelSource;\n staticModels?: Array<{ id: string; name: string }>;\n supported: boolean;\n addable?: boolean;\n hidden?: boolean;\n unsupportedReason?: string;\n /** True for providers that extract subscription tokens — carries account risk. */\n subscriptionRisk?: boolean;\n}\n\n/** Templates aligned with SDK packages shipped in package.json (API-key providers first). */\nexport const PROVIDER_TEMPLATES: ProviderTemplate[] = [\n {\n id: 'cline-pass',\n name: 'ClinePass',\n authType: 'api',\n authMethods: ['api', 'oauth'],\n npm: '@ai-sdk/openai-compatible',\n defaultBaseUrl: 'https://api.cline.bot/api/v1',\n signupUrl: 'https://app.cline.bot',\n modelSource: 'cline-recommended',\n headers: { 'HTTP-Referer': 'https://cline.bot', 'X-Title': 'Cline' },\n supported: true,\n subscriptionRisk: true,\n },\n {\n id: 'commandcode',\n name: 'Command Code',\n authType: 'api',\n npm: '@ai-sdk/openai-compatible',\n defaultBaseUrl: 'https://api.commandcode.ai/provider/v1',\n signupUrl: 'https://commandcode.ai/settings',\n modelSource: 'commandcode',\n supported: true,\n },\n {\n id: 'groq',\n name: 'Groq',\n authType: 'api',\n npm: '@ai-sdk/groq',\n defaultBaseUrl: 'https://api.groq.com/openai/v1',\n signupUrl: 'https://console.groq.com/keys',\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'nvidia',\n name: 'Nvidia',\n authType: 'api',\n npm: '@ai-sdk/openai-compatible',\n defaultBaseUrl: 'https://integrate.api.nvidia.com/v1',\n signupUrl: 'https://build.nvidia.com',\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'mistral',\n name: 'Mistral',\n authType: 'api',\n npm: '@ai-sdk/mistral',\n defaultBaseUrl: 'https://api.mistral.ai/v1',\n signupUrl: 'https://console.mistral.ai/api-keys',\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'togetherai',\n name: 'Together AI',\n authType: 'api',\n npm: '@ai-sdk/togetherai',\n defaultBaseUrl: 'https://api.together.xyz/v1',\n signupUrl: 'https://api.together.xyz/settings/api-keys',\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'cerebras',\n name: 'Cerebras',\n authType: 'api',\n npm: '@ai-sdk/cerebras',\n defaultBaseUrl: 'https://api.cerebras.ai/v1',\n signupUrl: 'https://cloud.cerebras.ai',\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'deepinfra',\n name: 'DeepInfra',\n authType: 'api',\n npm: '@ai-sdk/deepinfra',\n defaultBaseUrl: 'https://api.deepinfra.com/v1/openai',\n signupUrl: 'https://deepinfra.com/dash/api_keys',\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'deepseek',\n name: 'DeepSeek',\n authType: 'api',\n npm: '@ai-sdk/openai-compatible',\n defaultBaseUrl: 'https://api.deepseek.com/v1',\n signupUrl: 'https://platform.deepseek.com',\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'zhipu',\n name: 'Zhipu AI (GLM)',\n authType: 'api',\n npm: '@ai-sdk/openai-compatible',\n defaultBaseUrl: 'https://open.bigmodel.cn/api/paas/v4',\n signupUrl: 'https://open.bigmodel.cn',\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'moonshot',\n name: 'Moonshot (Kimi)',\n authType: 'api',\n npm: '@ai-sdk/openai-compatible',\n defaultBaseUrl: 'https://api.moonshot.cn/v1',\n signupUrl: 'https://platform.moonshot.cn',\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'moonshot-global',\n name: 'Moonshot Global (kimi.ai)',\n authType: 'api',\n npm: '@ai-sdk/openai-compatible',\n defaultBaseUrl: 'https://api.moonshot.ai/v1',\n signupUrl: 'https://platform.kimi.ai',\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'kimi-code',\n name: 'Kimi Code (Subscription Required)',\n authType: 'api',\n npm: '@ai-sdk/openai-compatible',\n defaultBaseUrl: 'https://api.kimi.com/coding/v1',\n modelSource: 'static-seed',\n staticModels: [\n { id: 'kimi-for-coding', name: 'Kimi Code K2.7 (Unified)' }\n ],\n supported: true,\n },\n {\n id: 'xai',\n name: 'xAI',\n authType: 'api',\n npm: '@ai-sdk/xai',\n defaultBaseUrl: 'https://api.x.ai/v1',\n signupUrl: 'https://console.x.ai',\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'perplexity',\n name: 'Perplexity',\n authType: 'api',\n npm: '@ai-sdk/perplexity',\n defaultBaseUrl: 'https://api.perplexity.ai',\n signupUrl: 'https://www.perplexity.ai/settings/api',\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'cohere',\n name: 'Cohere',\n authType: 'api',\n npm: '@ai-sdk/cohere',\n defaultBaseUrl: 'https://api.cohere.com/compatibility/v1',\n signupUrl: 'https://dashboard.cohere.com/api-keys',\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'openai',\n name: 'OpenAI',\n authType: 'api',\n npm: '@ai-sdk/openai',\n defaultBaseUrl: 'https://api.openai.com/v1',\n signupUrl: 'https://platform.openai.com/api-keys',\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'google',\n name: 'Google Gemini',\n authType: 'api',\n npm: '@ai-sdk/google',\n defaultBaseUrl: 'https://generativelanguage.googleapis.com/v1beta/openai',\n signupUrl: 'https://aistudio.google.com/apikey',\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'alibaba',\n name: 'Alibaba DashScope (China)',\n authType: 'api',\n npm: '@ai-sdk/alibaba',\n defaultBaseUrl: 'https://dashscope.aliyuncs.com/compatible-mode/v1',\n signupUrl: 'https://dashscope.console.aliyun.com/apiKey',\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'qwen-cloud-token-plan',\n name: 'Qwen Cloud (Token Plan)',\n shortName: 'Qwen Cloud',\n authType: 'api',\n npm: '@ai-sdk/alibaba',\n defaultBaseUrl: 'https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1',\n signupUrl: 'https://home.qwencloud.com/api-keys',\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'qwen-cloud-payg',\n name: 'Qwen Cloud (Pay-As-You-Go)',\n shortName: 'Qwen Cloud',\n authType: 'api',\n npm: '@ai-sdk/alibaba',\n defaultBaseUrl: 'https://dashscope-intl.aliyuncs.com/compatible-mode/v1',\n signupUrl: 'https://home.qwencloud.com/api-keys',\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'openrouter',\n name: 'OpenRouter',\n authType: 'api',\n npm: '@openrouter/ai-sdk-provider',\n defaultBaseUrl: 'https://openrouter.ai/api/v1',\n signupUrl: 'https://openrouter.ai/keys',\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'kilo',\n name: 'Kilo Code',\n authType: 'api',\n npm: '@ai-sdk/openai-compatible',\n defaultBaseUrl: 'https://api.kilo.ai/api/gateway',\n modelsPath: '/models',\n signupUrl: 'https://app.kilo.ai',\n apiKeyOptional: true,\n anonymousFreeModels: true,\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'ollama',\n name: 'Ollama',\n authType: 'api',\n npm: '@ai-sdk/openai-compatible',\n defaultBaseUrl: 'http://127.0.0.1:11434/v1',\n urlPrompt: 'Ollama API Base URL:',\n apiKeyOptional: true,\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'lmstudio',\n name: 'LM Studio',\n authType: 'api',\n npm: '@ai-sdk/openai-compatible',\n defaultBaseUrl: 'http://127.0.0.1:1234/v1',\n urlPrompt: 'LM Studio API Base URL:',\n apiKeyOptional: true,\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'venice',\n name: 'Venice AI',\n authType: 'api',\n npm: '@ai-sdk/openai-compatible',\n defaultBaseUrl: 'https://api.venice.ai/api/v1',\n signupUrl: 'https://venice.ai/settings/api',\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'cloudflare',\n name: 'Cloudflare Workers AI',\n authType: 'api',\n npm: '@ai-sdk/openai-compatible',\n defaultBaseUrl: 'https://api.cloudflare.com/client/v4/accounts/{ACCOUNT_ID}/ai/v1',\n modelsPath: '/models/search?task=Text%20Generation',\n signupUrl: 'https://dash.cloudflare.com',\n accountIdPrompt: 'Cloudflare Account ID:',\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'anthropic',\n name: 'Anthropic',\n authType: 'api',\n npm: '@ai-sdk/anthropic',\n defaultBaseUrl: 'https://api.anthropic.com',\n signupUrl: 'https://console.anthropic.com/settings/keys',\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'bedrock',\n name: 'Amazon Bedrock',\n authType: 'api',\n npm: '@ai-sdk/amazon-bedrock',\n modelSource: 'manual-only',\n supported: false,\n unsupportedReason: 'Not supported yet (requires AWS credentials). Optional: relay-ai providers import if already set up in OpenCode CLI.',\n },\n {\n id: 'azure',\n name: 'Azure OpenAI',\n authType: 'api',\n npm: '@ai-sdk/azure',\n modelSource: 'manual-only',\n supported: false,\n unsupportedReason: 'Not supported yet (requires Azure deployment URLs). Optional: relay-ai providers import if already set up in OpenCode CLI.',\n },\n {\n id: 'vertex',\n name: 'Google Vertex AI',\n authType: 'none',\n npm: '@ai-sdk/google-vertex',\n modelSource: 'manual-only',\n supported: false,\n unsupportedReason: 'Uses gcloud Application Default Credentials — use relay-ai server --vertex, not an API key.',\n },\n {\n id: 'opencode-cloud',\n name: 'OpenCode Zen / Go',\n authType: 'api',\n npm: '@ai-sdk/openai-compatible',\n signupUrl: 'https://opencode.ai/auth',\n modelSource: 'zen-go-api',\n supported: true,\n },\n {\n id: 'zen',\n name: 'OpenCode Zen',\n authType: 'api',\n npm: '@ai-sdk/openai-compatible',\n signupUrl: 'https://opencode.ai/auth',\n modelSource: 'zen-go-api',\n supported: true,\n addable: false,\n },\n {\n id: 'go',\n name: 'OpenCode Go',\n authType: 'api',\n npm: '@ai-sdk/openai-compatible',\n signupUrl: 'https://opencode.ai/auth',\n modelSource: 'zen-go-api',\n supported: true,\n addable: false,\n },\n // Subscription OAuth providers — Authorization Code + PKCE (browser redirect)\n // ⚠️ These extract tokens from paid subscriptions. Account risk — see plan docs.\n {\n id: 'claude-code',\n name: 'Claude Code (Anthropic subscription)',\n shortName: 'Claude Code',\n authType: 'oauth',\n npm: '@ai-sdk/anthropic',\n defaultBaseUrl: 'https://api.anthropic.com',\n signupUrl: 'https://claude.ai',\n modelSource: 'api-list',\n supported: true,\n hidden: true,\n subscriptionRisk: true,\n },\n {\n id: 'antigravity',\n name: 'Cloud Code Assist OAuth (Google)',\n // Compact label users actually recognise: every surface that shows this\n // provider calls it Antigravity, and it is also the shortest of the two.\n shortName: 'Antigravity',\n authType: 'oauth',\n npm: '@ai-sdk/openai-compatible',\n signupUrl: 'https://antigravity.google',\n modelSource: 'api-list',\n supported: true,\n hidden: true,\n subscriptionRisk: true,\n },\n // OAuth-gated subscription providers — device code or broker sign-in\n {\n id: 'xai-oauth',\n name: 'xAI Grok (SuperGrok)',\n shortName: 'xAI Grok',\n authType: 'oauth',\n npm: '@ai-sdk/xai',\n signupUrl: 'https://x.ai',\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'openai-oauth',\n name: 'OpenAI (ChatGPT)',\n shortName: 'OpenAI',\n authType: 'oauth',\n npm: '@ai-sdk/openai',\n signupUrl: 'https://chatgpt.com',\n modelSource: 'api-list',\n supported: true,\n },\n {\n id: 'github-copilot',\n name: 'GitHub Copilot',\n authType: 'oauth',\n npm: '@ai-sdk/openai-compatible',\n defaultBaseUrl: 'https://api.githubcopilot.com',\n modelsPath: '/models',\n signupUrl: 'https://github.com/features/copilot',\n modelSource: 'api-list',\n headers: { 'Editor-Version': 'vscode/1.85.1' },\n supported: true,\n },\n];\n\nexport function listSupportedTemplates(): ProviderTemplate[] {\n return PROVIDER_TEMPLATES\n .filter(t => t.supported && (t.authMethods ?? [t.authType]).includes('api') && t.addable !== false && !t.hidden)\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\n/** Supported templates not yet present in the user's registry. */\nexport function listAddableTemplates(configuredIds: Iterable<string> = []): ProviderTemplate[] {\n const configured = new Set(configuredIds);\n return listSupportedTemplates().filter(t => {\n if (t.id === 'opencode-cloud') {\n return !configured.has('zen') && !configured.has('go');\n }\n return !configured.has(t.id);\n });\n}\n\nexport function listVisibleOAuthTemplates(configuredIds: Iterable<string> = []): ProviderTemplate[] {\n const configured = new Set(configuredIds);\n return PROVIDER_TEMPLATES\n .filter(t => {\n const methods = t.authMethods ?? [t.authType];\n return methods.includes('oauth')\n && !methods.includes('api')\n && t.supported\n && t.addable !== false\n && !t.hidden\n && !configured.has(t.id);\n })\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\nexport function getTemplateById(id: string): ProviderTemplate | undefined {\n return PROVIDER_TEMPLATES.find(t => t.id === id);\n}\n\nexport function filterTemplates(templates: ProviderTemplate[], query: string): ProviderTemplate[] {\n const q = query.trim().toLowerCase();\n if (!q) return templates;\n return templates.filter(\n t =>\n t.id.toLowerCase().includes(q) ||\n t.name.toLowerCase().includes(q) ||\n t.npm.toLowerCase().includes(q),\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
supportsManualModels,
|
|
11
11
|
translateRequest,
|
|
12
12
|
validateCustomEndpointUrl
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-Z5GL4ALA.js";
|
|
14
14
|
|
|
15
15
|
// src/registry/validate-manual-model.ts
|
|
16
16
|
import { randomUUID } from "crypto";
|
|
@@ -149,4 +149,4 @@ export {
|
|
|
149
149
|
addManualModel,
|
|
150
150
|
removeManualModel
|
|
151
151
|
};
|
|
152
|
-
//# sourceMappingURL=chunk-
|
|
152
|
+
//# sourceMappingURL=chunk-FD5EDSBM.js.map
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
getTemplateById,
|
|
4
4
|
init_provider_templates
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-3R25QO5X.js";
|
|
6
6
|
import {
|
|
7
7
|
ANTIGRAVITY_BASE_URLS,
|
|
8
8
|
BACKENDS,
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
classifyModelFormat,
|
|
25
25
|
claudeCodeClientModelId,
|
|
26
26
|
claudeModelFamily,
|
|
27
|
+
contextWindowFromHeuristics,
|
|
27
28
|
createLanguageModel,
|
|
28
29
|
customProviderId,
|
|
29
30
|
deleteProviderCredential,
|
|
@@ -49,7 +50,6 @@ import {
|
|
|
49
50
|
isOpencodeOAuth,
|
|
50
51
|
isSdkMigratedNpm,
|
|
51
52
|
isValidProviderId,
|
|
52
|
-
loadOpencodeCache,
|
|
53
53
|
loadRegistry,
|
|
54
54
|
maxToolsForNpm,
|
|
55
55
|
modelPrefersResponsesApi,
|
|
@@ -85,7 +85,7 @@ import {
|
|
|
85
85
|
translateRequest,
|
|
86
86
|
upstreamHttpStatus,
|
|
87
87
|
validateCustomEndpointUrl
|
|
88
|
-
} from "./chunk-
|
|
88
|
+
} from "./chunk-Z5GL4ALA.js";
|
|
89
89
|
|
|
90
90
|
// src/registry/google-model-id.ts
|
|
91
91
|
var GOOGLE_MODEL_PREFIX = "models/";
|
|
@@ -1285,6 +1285,8 @@ var memoryCache = null;
|
|
|
1285
1285
|
var memoryCachePath = null;
|
|
1286
1286
|
var memoryCacheMtime = 0;
|
|
1287
1287
|
var REGISTRY_TO_MODELS_DEV = {
|
|
1288
|
+
zen: "opencode",
|
|
1289
|
+
go: "opencode-go",
|
|
1288
1290
|
google: "google",
|
|
1289
1291
|
openai: "openai",
|
|
1290
1292
|
groq: "groq",
|
|
@@ -3583,27 +3585,26 @@ function deriveBrand(family) {
|
|
|
3583
3585
|
}
|
|
3584
3586
|
return "Other";
|
|
3585
3587
|
}
|
|
3586
|
-
function
|
|
3587
|
-
const
|
|
3588
|
-
if (!cache) return null;
|
|
3589
|
-
const providerKey = backendId === "zen" ? "opencode" : "opencode-go";
|
|
3588
|
+
function readModelsFromModelsDev(backendId, cache = loadModelsDevCache()) {
|
|
3589
|
+
const providerKey = resolveModelsDevSlug(backendId);
|
|
3590
3590
|
const providerData = cache[providerKey];
|
|
3591
3591
|
if (!providerData?.models) return null;
|
|
3592
3592
|
const result = /* @__PURE__ */ new Map();
|
|
3593
|
-
for (const entry of Object.
|
|
3594
|
-
|
|
3593
|
+
for (const [modelKey, entry] of Object.entries(providerData.models)) {
|
|
3594
|
+
const id = entry.id ?? modelKey;
|
|
3595
|
+
if (entry.status === "deprecated") continue;
|
|
3595
3596
|
const isFree = entry.cost !== void 0 && entry.cost.input === 0 && entry.cost.output === 0;
|
|
3596
|
-
const rawFormat = classifyModelFormat(
|
|
3597
|
+
const rawFormat = classifyModelFormat(id, entry.provider?.npm);
|
|
3597
3598
|
const modelFormat = backendId === "go" && rawFormat === "anthropic" ? "openai" : rawFormat;
|
|
3598
|
-
result.set(
|
|
3599
|
-
id
|
|
3600
|
-
name: entry.name ??
|
|
3599
|
+
result.set(id, {
|
|
3600
|
+
id,
|
|
3601
|
+
name: entry.name ?? id,
|
|
3601
3602
|
isFree,
|
|
3602
|
-
brand: deriveBrand(entry.family ??
|
|
3603
|
+
brand: deriveBrand(entry.family ?? id),
|
|
3603
3604
|
sourceBackend: backendId,
|
|
3604
3605
|
modelFormat,
|
|
3605
3606
|
cost: entry.cost,
|
|
3606
|
-
contextWindow:
|
|
3607
|
+
contextWindow: entry.limit?.context ?? contextWindowFromHeuristics(id),
|
|
3607
3608
|
reasoning: entry.reasoning,
|
|
3608
3609
|
interleavedReasoningField: entry.interleaved?.field
|
|
3609
3610
|
});
|
|
@@ -3641,12 +3642,12 @@ function mergeModels(apiIds, cache, backendId) {
|
|
|
3641
3642
|
brand: "Other",
|
|
3642
3643
|
sourceBackend: backendId,
|
|
3643
3644
|
modelFormat,
|
|
3644
|
-
contextWindow:
|
|
3645
|
+
contextWindow: contextWindowFromHeuristics(id)
|
|
3645
3646
|
};
|
|
3646
3647
|
});
|
|
3647
3648
|
}
|
|
3648
3649
|
async function getModels(backend, fallbackModels) {
|
|
3649
|
-
const cache =
|
|
3650
|
+
const cache = readModelsFromModelsDev(backend.id);
|
|
3650
3651
|
try {
|
|
3651
3652
|
const apiIds = await fetchModelsFromApi(backend);
|
|
3652
3653
|
return { models: mergeModels(apiIds, cache, backend.id), fromCache: false };
|
|
@@ -5714,6 +5715,132 @@ async function validateClinePassApiKey(apiKey) {
|
|
|
5714
5715
|
}
|
|
5715
5716
|
}
|
|
5716
5717
|
|
|
5718
|
+
// src/registry/fetch-commandcode-models.ts
|
|
5719
|
+
var COMMANDCODE_BASE_URL = "https://api.commandcode.ai/provider/v1";
|
|
5720
|
+
var REQUEST_TIMEOUT_MS2 = 1e4;
|
|
5721
|
+
var PROBE_TIMEOUT_MS = 25e3;
|
|
5722
|
+
var PROBE_CONCURRENCY = 6;
|
|
5723
|
+
function isAnthropicSchemaModel(id) {
|
|
5724
|
+
return id.startsWith("claude-");
|
|
5725
|
+
}
|
|
5726
|
+
function positiveNumber2(value) {
|
|
5727
|
+
const number = typeof value === "number" ? value : typeof value === "string" && value.trim() ? Number(value) : void 0;
|
|
5728
|
+
return typeof number === "number" && Number.isFinite(number) && number > 0 ? number : void 0;
|
|
5729
|
+
}
|
|
5730
|
+
function toCachedModel2(entry, baseUrl) {
|
|
5731
|
+
const id = typeof entry.id === "string" ? entry.id.trim() : "";
|
|
5732
|
+
if (!id) return null;
|
|
5733
|
+
const anthropicSchema = isAnthropicSchemaModel(id);
|
|
5734
|
+
const displayName = typeof entry.name === "string" && entry.name.trim() ? entry.name.trim() : id;
|
|
5735
|
+
const contextWindow2 = positiveNumber2(entry.context_length);
|
|
5736
|
+
const family = id.split("/").pop()?.split(/[-:]/)[0] ?? id;
|
|
5737
|
+
return {
|
|
5738
|
+
id,
|
|
5739
|
+
name: displayName,
|
|
5740
|
+
upstreamModelId: id,
|
|
5741
|
+
family,
|
|
5742
|
+
brand: deriveBrand(family),
|
|
5743
|
+
contextWindow: contextWindow2,
|
|
5744
|
+
contextWindowSource: contextWindow2 === void 0 ? void 0 : "provider",
|
|
5745
|
+
modelFormat: anthropicSchema ? "anthropic" : "openai",
|
|
5746
|
+
npm: anthropicSchema ? "@ai-sdk/anthropic" : "@ai-sdk/openai-compatible",
|
|
5747
|
+
apiUrl: baseUrl
|
|
5748
|
+
};
|
|
5749
|
+
}
|
|
5750
|
+
function parseCommandCodeModels(payload, baseUrl) {
|
|
5751
|
+
if (!payload || typeof payload !== "object") return [];
|
|
5752
|
+
const rows = payload.data;
|
|
5753
|
+
if (!Array.isArray(rows)) return [];
|
|
5754
|
+
const models = [];
|
|
5755
|
+
for (const row of rows) {
|
|
5756
|
+
if (!row || typeof row !== "object") continue;
|
|
5757
|
+
const model = toCachedModel2(row, baseUrl);
|
|
5758
|
+
if (model) models.push(model);
|
|
5759
|
+
}
|
|
5760
|
+
return models;
|
|
5761
|
+
}
|
|
5762
|
+
function classifyProbeResponse(status, body) {
|
|
5763
|
+
const message = typeof body === "object" && body !== null ? String(body.error?.message ?? "") : "";
|
|
5764
|
+
if (status === 403 && message.includes("MODEL_NOT_IN_PLAN")) return "not-in-plan";
|
|
5765
|
+
if (status >= 500) return "unknown";
|
|
5766
|
+
if (status === 429) return "unknown";
|
|
5767
|
+
if (status === 401 || status === 403) return "unknown";
|
|
5768
|
+
if (status >= 200 && status < 500) return "available";
|
|
5769
|
+
return "unknown";
|
|
5770
|
+
}
|
|
5771
|
+
async function probeModel(model, baseUrl, apiKey) {
|
|
5772
|
+
const anthropicSchema = model.modelFormat === "anthropic";
|
|
5773
|
+
const controller = new AbortController();
|
|
5774
|
+
const timer = setTimeout(() => controller.abort(), PROBE_TIMEOUT_MS);
|
|
5775
|
+
try {
|
|
5776
|
+
const response = await fetch(`${baseUrl}/${anthropicSchema ? "messages" : "chat/completions"}`, {
|
|
5777
|
+
method: "POST",
|
|
5778
|
+
headers: {
|
|
5779
|
+
"Content-Type": "application/json",
|
|
5780
|
+
...anthropicSchema ? { "x-api-key": apiKey, "anthropic-version": "2023-06-01" } : { Authorization: `Bearer ${apiKey}` }
|
|
5781
|
+
},
|
|
5782
|
+
body: JSON.stringify({
|
|
5783
|
+
model: model.upstreamModelId,
|
|
5784
|
+
max_tokens: 1,
|
|
5785
|
+
messages: [{ role: "user", content: "hi" }]
|
|
5786
|
+
}),
|
|
5787
|
+
signal: controller.signal
|
|
5788
|
+
});
|
|
5789
|
+
const payload = await response.json().catch(() => null);
|
|
5790
|
+
return classifyProbeResponse(response.status, payload);
|
|
5791
|
+
} catch {
|
|
5792
|
+
return "unknown";
|
|
5793
|
+
} finally {
|
|
5794
|
+
clearTimeout(timer);
|
|
5795
|
+
}
|
|
5796
|
+
}
|
|
5797
|
+
async function filterModelsByPlan(models, baseUrl, apiKey) {
|
|
5798
|
+
if (!apiKey.trim()) return models;
|
|
5799
|
+
const keep = [];
|
|
5800
|
+
let next = 0;
|
|
5801
|
+
await Promise.all(
|
|
5802
|
+
Array.from({ length: Math.min(PROBE_CONCURRENCY, models.length) }, async () => {
|
|
5803
|
+
for (let i = next++; i < models.length; i = next++) {
|
|
5804
|
+
const model = models[i];
|
|
5805
|
+
if (await probeModel(model, baseUrl, apiKey) !== "not-in-plan") keep.push(model);
|
|
5806
|
+
}
|
|
5807
|
+
})
|
|
5808
|
+
);
|
|
5809
|
+
const order = new Map(models.map((m, i) => [m.id, i]));
|
|
5810
|
+
return keep.sort((a, b) => (order.get(a.id) ?? 0) - (order.get(b.id) ?? 0));
|
|
5811
|
+
}
|
|
5812
|
+
async function fetchCommandCodeModels(baseUrl = COMMANDCODE_BASE_URL, apiKey) {
|
|
5813
|
+
const normalizedBaseUrl = baseUrl.replace(/\/$/, "");
|
|
5814
|
+
const controller = new AbortController();
|
|
5815
|
+
const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS2);
|
|
5816
|
+
let response;
|
|
5817
|
+
try {
|
|
5818
|
+
response = await fetch(`${normalizedBaseUrl}/models`, {
|
|
5819
|
+
method: "GET",
|
|
5820
|
+
headers: {
|
|
5821
|
+
Accept: "application/json",
|
|
5822
|
+
...apiKey?.trim() ? { Authorization: `Bearer ${apiKey.trim()}` } : {}
|
|
5823
|
+
},
|
|
5824
|
+
redirect: "manual",
|
|
5825
|
+
signal: controller.signal
|
|
5826
|
+
});
|
|
5827
|
+
} finally {
|
|
5828
|
+
clearTimeout(timer);
|
|
5829
|
+
}
|
|
5830
|
+
if (response.status === 401 || response.status === 403) {
|
|
5831
|
+
throw new Error("Command Code rejected the API key.");
|
|
5832
|
+
}
|
|
5833
|
+
if (!response.ok) {
|
|
5834
|
+
throw new Error(`Command Code model list returned HTTP ${response.status}.`);
|
|
5835
|
+
}
|
|
5836
|
+
const payload = await response.json().catch(() => null);
|
|
5837
|
+
const models = parseCommandCodeModels(payload, normalizedBaseUrl);
|
|
5838
|
+
if (models.length === 0) throw new Error("Command Code returned no usable models.");
|
|
5839
|
+
if (!apiKey?.trim()) return models;
|
|
5840
|
+
const available = await filterModelsByPlan(models, normalizedBaseUrl, apiKey);
|
|
5841
|
+
return available.length > 0 ? available : models;
|
|
5842
|
+
}
|
|
5843
|
+
|
|
5717
5844
|
// src/registry/model-source.ts
|
|
5718
5845
|
init_provider_templates();
|
|
5719
5846
|
|
|
@@ -5874,6 +6001,7 @@ function modelInfoToCached(m, npm, apiUrl) {
|
|
|
5874
6001
|
}
|
|
5875
6002
|
async function refreshZenGoProvider(provider) {
|
|
5876
6003
|
const backendId = provider.id === "go" || provider.templateId === "go" ? "go" : "zen";
|
|
6004
|
+
await fetchModelsDevCache();
|
|
5877
6005
|
const result = await getModels(BACKENDS[backendId]);
|
|
5878
6006
|
return result.models.filter((m) => m.modelFormat !== "unsupported").map((m) => {
|
|
5879
6007
|
const isAnthropic = m.modelFormat === "anthropic";
|
|
@@ -6225,6 +6353,20 @@ async function refreshProviderModels(providerId, apiKey, registry = loadRegistry
|
|
|
6225
6353
|
let oauthFallbackReason;
|
|
6226
6354
|
if (source === "zen-go-api") {
|
|
6227
6355
|
models = await refreshZenGoProvider(provider);
|
|
6356
|
+
} else if (source === "commandcode") {
|
|
6357
|
+
const ccBaseUrl = (provider.api.url ?? COMMANDCODE_BASE_URL).replace(/\/$/, "");
|
|
6358
|
+
try {
|
|
6359
|
+
models = await fetchCommandCodeModels(ccBaseUrl, apiKey ?? void 0);
|
|
6360
|
+
baseUrl = ccBaseUrl;
|
|
6361
|
+
} catch (err) {
|
|
6362
|
+
if (cachedModelCount(provider) > 0) {
|
|
6363
|
+
return skipWithCachedModels(
|
|
6364
|
+
provider,
|
|
6365
|
+
`Command Code catalog refresh failed: ${err instanceof Error ? err.message : String(err)} Kept the existing cached model list; try again later.`
|
|
6366
|
+
);
|
|
6367
|
+
}
|
|
6368
|
+
throw err;
|
|
6369
|
+
}
|
|
6228
6370
|
} else if (source === "cline-recommended") {
|
|
6229
6371
|
try {
|
|
6230
6372
|
models = await fetchClinePassModels();
|
|
@@ -8253,6 +8395,17 @@ async function addProviderFromTemplate(template, apiKey, opts) {
|
|
|
8253
8395
|
hint: template.signupUrl ? `Verify your key at ${template.signupUrl}` : void 0
|
|
8254
8396
|
};
|
|
8255
8397
|
}
|
|
8398
|
+
} else if (template.modelSource === "commandcode") {
|
|
8399
|
+
try {
|
|
8400
|
+
const baseUrl = (opts?.baseUrl?.trim() || template.defaultBaseUrl || COMMANDCODE_BASE_URL).replace(/\/$/, "");
|
|
8401
|
+
fetched = { models: await fetchCommandCodeModels(baseUrl, trimmedKey), baseUrl };
|
|
8402
|
+
} catch (err) {
|
|
8403
|
+
return {
|
|
8404
|
+
added: false,
|
|
8405
|
+
error: err instanceof Error ? err.message : String(err),
|
|
8406
|
+
hint: template.signupUrl ? `Verify your key at ${template.signupUrl}` : void 0
|
|
8407
|
+
};
|
|
8408
|
+
}
|
|
8256
8409
|
} else {
|
|
8257
8410
|
fetched = await fetchTemplateModels(template, trimmedKey, opts?.baseUrl);
|
|
8258
8411
|
}
|
|
@@ -9508,4 +9661,4 @@ export {
|
|
|
9508
9661
|
supportsClaudeTransparentMode,
|
|
9509
9662
|
buildHttpProxyRoutes
|
|
9510
9663
|
};
|
|
9511
|
-
//# sourceMappingURL=chunk-
|
|
9664
|
+
//# sourceMappingURL=chunk-HL3EZ4OU.js.map
|