@jacobbd/relay-ai 0.7.5 → 0.8.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 +8 -4
- package/dist/{chunk-HEMJFOXG.js → chunk-5DDQJSTU.js} +1029 -169
- package/dist/chunk-5DDQJSTU.js.map +1 -0
- package/dist/{chunk-HXGZ4CTV.js → chunk-Q2FTCICO.js} +19 -3
- package/dist/chunk-Q2FTCICO.js.map +1 -0
- package/dist/cli.js +206 -50
- package/dist/cli.js.map +1 -1
- package/dist/core/index.js +628 -7
- package/dist/core/index.js.map +1 -1
- package/dist/{provider-templates-4H3C4DRL.js → provider-templates-XKNRKAQU.js} +2 -2
- package/dist/ui/public/app.js +106 -0
- package/dist/{ui-command-26QQUWTQ.js → ui-command-RYWL36VR.js} +44 -7
- package/dist/ui-command-RYWL36VR.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-HEMJFOXG.js.map +0 -1
- package/dist/chunk-HXGZ4CTV.js.map +0 -1
- package/dist/ui-command-26QQUWTQ.js.map +0 -1
- /package/dist/{provider-templates-4H3C4DRL.js.map → provider-templates-XKNRKAQU.js.map} +0 -0
|
@@ -31,7 +31,7 @@ __export(provider_templates_exports, {
|
|
|
31
31
|
listVisibleOAuthTemplates: () => listVisibleOAuthTemplates
|
|
32
32
|
});
|
|
33
33
|
function listSupportedTemplates() {
|
|
34
|
-
return PROVIDER_TEMPLATES.filter((t) => t.supported && t.
|
|
34
|
+
return PROVIDER_TEMPLATES.filter((t) => t.supported && (t.authMethods ?? [t.authType]).includes("api") && t.addable !== false && !t.hidden).sort((a, b) => a.name.localeCompare(b.name));
|
|
35
35
|
}
|
|
36
36
|
function listAddableTemplates(configuredIds = []) {
|
|
37
37
|
const configured = new Set(configuredIds);
|
|
@@ -44,7 +44,10 @@ function listAddableTemplates(configuredIds = []) {
|
|
|
44
44
|
}
|
|
45
45
|
function listVisibleOAuthTemplates(configuredIds = []) {
|
|
46
46
|
const configured = new Set(configuredIds);
|
|
47
|
-
return PROVIDER_TEMPLATES.filter((t) =>
|
|
47
|
+
return PROVIDER_TEMPLATES.filter((t) => {
|
|
48
|
+
const methods = t.authMethods ?? [t.authType];
|
|
49
|
+
return methods.includes("oauth") && !methods.includes("api") && t.supported && t.addable !== false && !t.hidden && !configured.has(t.id);
|
|
50
|
+
}).sort((a, b) => a.name.localeCompare(b.name));
|
|
48
51
|
}
|
|
49
52
|
function getTemplateById(id) {
|
|
50
53
|
return PROVIDER_TEMPLATES.find((t) => t.id === id);
|
|
@@ -60,6 +63,19 @@ var PROVIDER_TEMPLATES;
|
|
|
60
63
|
var init_provider_templates = __esm({
|
|
61
64
|
"src/provider-templates.ts"() {
|
|
62
65
|
PROVIDER_TEMPLATES = [
|
|
66
|
+
{
|
|
67
|
+
id: "cline-pass",
|
|
68
|
+
name: "ClinePass",
|
|
69
|
+
authType: "api",
|
|
70
|
+
authMethods: ["api", "oauth"],
|
|
71
|
+
npm: "@ai-sdk/openai-compatible",
|
|
72
|
+
defaultBaseUrl: "https://api.cline.bot/api/v1",
|
|
73
|
+
signupUrl: "https://app.cline.bot",
|
|
74
|
+
modelSource: "cline-recommended",
|
|
75
|
+
headers: { "HTTP-Referer": "https://cline.bot", "X-Title": "Cline" },
|
|
76
|
+
supported: true,
|
|
77
|
+
subscriptionRisk: true
|
|
78
|
+
},
|
|
63
79
|
{
|
|
64
80
|
id: "groq",
|
|
65
81
|
name: "Groq",
|
|
@@ -456,4 +472,4 @@ export {
|
|
|
456
472
|
provider_templates_exports,
|
|
457
473
|
init_provider_templates
|
|
458
474
|
};
|
|
459
|
-
//# sourceMappingURL=chunk-
|
|
475
|
+
//# sourceMappingURL=chunk-Q2FTCICO.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';\n\nexport interface ProviderTemplate {\n id: string;\n name: 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: '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 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 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: 'venice-ai-sdk-provider',\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 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: 'Antigravity (Google Cloud Code Assist)',\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 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 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":[]}
|
package/dist/cli.js
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
GLOBAL_OPENCODE_KEYRING_ACCOUNT,
|
|
9
9
|
MAX_MODEL_CATALOG,
|
|
10
10
|
PREVIEW_PROXY_PORT,
|
|
11
|
+
UNSUPPORTED_VOICE_MESSAGE,
|
|
11
12
|
VERSION,
|
|
12
13
|
VERTEX_ANTHROPIC_NPM,
|
|
13
14
|
addCustomEndpointProvider,
|
|
@@ -115,6 +116,7 @@ import {
|
|
|
115
116
|
parseDsmlToolCalls,
|
|
116
117
|
parseToolArguments,
|
|
117
118
|
prepareClaudeTraceLog,
|
|
119
|
+
prepareProviderTraceLog,
|
|
118
120
|
printApiKeyPanel,
|
|
119
121
|
printCloudProviderPanel,
|
|
120
122
|
printDryRunPanel,
|
|
@@ -125,6 +127,7 @@ import {
|
|
|
125
127
|
printTraceLog,
|
|
126
128
|
printWelcomePanel,
|
|
127
129
|
providerAuthHelpText,
|
|
130
|
+
providerRefreshToken,
|
|
128
131
|
providerSelectOption,
|
|
129
132
|
providersForPicker,
|
|
130
133
|
providersForTarget,
|
|
@@ -154,6 +157,7 @@ import {
|
|
|
154
157
|
routableModelsForTarget,
|
|
155
158
|
routeLookupIds,
|
|
156
159
|
runServerCommand,
|
|
160
|
+
sanitizeUnsupportedInlineData,
|
|
157
161
|
savePreferences,
|
|
158
162
|
saveProviderCredential,
|
|
159
163
|
saveRegistry,
|
|
@@ -180,14 +184,15 @@ import {
|
|
|
180
184
|
validateCustomEndpointUrl,
|
|
181
185
|
writeSecureLogLine,
|
|
182
186
|
zenRegistryStub
|
|
183
|
-
} from "./chunk-
|
|
187
|
+
} from "./chunk-5DDQJSTU.js";
|
|
184
188
|
import {
|
|
185
189
|
filterTemplates,
|
|
190
|
+
getTemplateById,
|
|
186
191
|
init_provider_templates,
|
|
187
192
|
listAddableTemplates,
|
|
188
193
|
listSupportedTemplates,
|
|
189
194
|
listVisibleOAuthTemplates
|
|
190
|
-
} from "./chunk-
|
|
195
|
+
} from "./chunk-Q2FTCICO.js";
|
|
191
196
|
|
|
192
197
|
// src/cli.ts
|
|
193
198
|
import pc12 from "picocolors";
|
|
@@ -1286,7 +1291,7 @@ ${pc4.bold("Subcommands:")}
|
|
|
1286
1291
|
(none) Provider hub wizard ${pc4.dim("[Phase 1.1]")}
|
|
1287
1292
|
add Add a provider (Groq, Mistral, Together AI, \u2026) ${pc4.dim("[Phase 1.1]")}
|
|
1288
1293
|
import Optional one-time import from OpenCode CLI ${pc4.dim("[Phase 1.0]")}
|
|
1289
|
-
auth Sign in with OAuth (GitHub Copilot, xAI, OpenAI)
|
|
1294
|
+
auth Sign in with OAuth (GitHub Copilot, xAI, OpenAI, ClinePass)
|
|
1290
1295
|
list Show configured providers ${pc4.dim("[Phase 1.0]")}
|
|
1291
1296
|
remove Remove a provider by id ${pc4.dim("[Phase 1.1]")}
|
|
1292
1297
|
refresh-models Update cached model lists ${pc4.dim("[Phase 1.2]")}`;
|
|
@@ -1508,6 +1513,69 @@ async function pickTemplateFromCatalog() {
|
|
|
1508
1513
|
if (template) return template;
|
|
1509
1514
|
}
|
|
1510
1515
|
}
|
|
1516
|
+
function hasApiAndOAuth(template) {
|
|
1517
|
+
const methods = template.authMethods ?? [template.authType];
|
|
1518
|
+
return methods.includes("api") && methods.includes("oauth");
|
|
1519
|
+
}
|
|
1520
|
+
function showProviderAddFailure(error, hint, fallback) {
|
|
1521
|
+
printPanel(pc4.red("Provider was not added"), [
|
|
1522
|
+
pc4.white(error ?? fallback),
|
|
1523
|
+
pc4.dim("No changes were saved."),
|
|
1524
|
+
...hint ? [pc4.white(hint)] : []
|
|
1525
|
+
]);
|
|
1526
|
+
}
|
|
1527
|
+
async function runDualAuthTemplateFlow(template, existing) {
|
|
1528
|
+
const method = await p5.select({
|
|
1529
|
+
message: existing ? `Change ${template.name} authentication` : `How would you like to connect to ${template.name}?`,
|
|
1530
|
+
options: [
|
|
1531
|
+
{
|
|
1532
|
+
value: "api",
|
|
1533
|
+
label: "Use an API key",
|
|
1534
|
+
hint: existing?.authType === "api" ? "Replace the current API key" : "Use your ClinePass API key"
|
|
1535
|
+
},
|
|
1536
|
+
{
|
|
1537
|
+
value: "oauth",
|
|
1538
|
+
label: "Sign in with ClinePass",
|
|
1539
|
+
hint: "One-time device code; uses your ClinePass account"
|
|
1540
|
+
},
|
|
1541
|
+
{ value: "back", label: "Back", hint: "" }
|
|
1542
|
+
]
|
|
1543
|
+
});
|
|
1544
|
+
if (p5.isCancel(method) || method === "back") return 0;
|
|
1545
|
+
if (method === "oauth") {
|
|
1546
|
+
return runProvidersAuth(template.id);
|
|
1547
|
+
}
|
|
1548
|
+
if (template.signupUrl) {
|
|
1549
|
+
printPanel(fmtProvider(template.name), [
|
|
1550
|
+
`${pc4.white("Get an API key at:")} ${fmtUrl(template.signupUrl)}`
|
|
1551
|
+
]);
|
|
1552
|
+
}
|
|
1553
|
+
const apiKeyInput = await p5.password({
|
|
1554
|
+
message: `Paste your ${template.name} API key:`,
|
|
1555
|
+
validate: (value) => value.trim() ? void 0 : "Key cannot be empty"
|
|
1556
|
+
});
|
|
1557
|
+
if (p5.isCancel(apiKeyInput)) {
|
|
1558
|
+
p5.cancel("Cancelled.");
|
|
1559
|
+
return 0;
|
|
1560
|
+
}
|
|
1561
|
+
const apiKey = String(apiKeyInput).trim();
|
|
1562
|
+
if (!apiKey) {
|
|
1563
|
+
showProviderAddFailure("Key cannot be empty.", void 0, "Could not add provider.");
|
|
1564
|
+
return 1;
|
|
1565
|
+
}
|
|
1566
|
+
const spinner9 = p5.spinner();
|
|
1567
|
+
spinner9.start(`Testing connection to ${template.name}...`);
|
|
1568
|
+
const result = await addProviderFromTemplate(template, apiKey, {
|
|
1569
|
+
replaceExisting: Boolean(existing)
|
|
1570
|
+
});
|
|
1571
|
+
spinner9.stop("");
|
|
1572
|
+
if (!result.added) {
|
|
1573
|
+
showProviderAddFailure(result.error, result.hint, "Could not add provider.");
|
|
1574
|
+
return 1;
|
|
1575
|
+
}
|
|
1576
|
+
logConnected(template.name, result.modelCount ?? 0);
|
|
1577
|
+
return 0;
|
|
1578
|
+
}
|
|
1511
1579
|
async function runTemplateAddFlow() {
|
|
1512
1580
|
if (listAddableTemplates(loadRegistry().providers.map((p15) => p15.id)).length === 0) {
|
|
1513
1581
|
p5.log.info("All catalog providers are already configured.");
|
|
@@ -1515,6 +1583,9 @@ async function runTemplateAddFlow() {
|
|
|
1515
1583
|
}
|
|
1516
1584
|
const template = await pickTemplateFromCatalog();
|
|
1517
1585
|
if (!template) return 0;
|
|
1586
|
+
if (hasApiAndOAuth(template)) {
|
|
1587
|
+
return runDualAuthTemplateFlow(template);
|
|
1588
|
+
}
|
|
1518
1589
|
if (template.modelSource === "zen-go-api") {
|
|
1519
1590
|
const existingKey = await readGlobalOpencodeCredential();
|
|
1520
1591
|
let apiKey2 = existingKey;
|
|
@@ -1597,8 +1668,7 @@ async function runTemplateAddFlow() {
|
|
|
1597
1668
|
const result = await addProviderFromTemplate(template, apiKey, { baseUrl: baseUrlOverride });
|
|
1598
1669
|
spinner9.stop("");
|
|
1599
1670
|
if (!result.added) {
|
|
1600
|
-
|
|
1601
|
-
if (result.hint) p5.log.info(result.hint);
|
|
1671
|
+
showProviderAddFailure(result.error, result.hint, "Could not add provider.");
|
|
1602
1672
|
return 1;
|
|
1603
1673
|
}
|
|
1604
1674
|
logConnected(template.name, result.modelCount ?? 0);
|
|
@@ -1686,8 +1756,7 @@ async function runCustomEndpointAddFlow() {
|
|
|
1686
1756
|
});
|
|
1687
1757
|
spinner9.stop("");
|
|
1688
1758
|
if (!result.added) {
|
|
1689
|
-
|
|
1690
|
-
if (result.hint) p5.log.info(result.hint);
|
|
1759
|
+
showProviderAddFailure(result.error, result.hint, "Could not add custom provider.");
|
|
1691
1760
|
return 1;
|
|
1692
1761
|
}
|
|
1693
1762
|
logConnected(result.provider?.name ?? "Provider", result.modelCount ?? 0);
|
|
@@ -1790,6 +1859,8 @@ async function runProviderDetail(id) {
|
|
|
1790
1859
|
const modelCount = provider.modelsCache?.models.length ?? 0;
|
|
1791
1860
|
const authLabel = formatRegistryAuthLabel(provider);
|
|
1792
1861
|
printProviderDetailPanel(provider.name, modelCount, authLabel);
|
|
1862
|
+
const template = getTemplateById(provider.templateId) ?? getTemplateById(id);
|
|
1863
|
+
const hasDualAuth = template ? hasApiAndOAuth(template) : false;
|
|
1793
1864
|
const detailOptions = [];
|
|
1794
1865
|
if (modelCount > 0) {
|
|
1795
1866
|
detailOptions.push({
|
|
@@ -1803,7 +1874,13 @@ async function runProviderDetail(id) {
|
|
|
1803
1874
|
label: "Refresh model list",
|
|
1804
1875
|
hint: "Fetch latest models from the provider API"
|
|
1805
1876
|
});
|
|
1806
|
-
if (
|
|
1877
|
+
if (hasDualAuth && template) {
|
|
1878
|
+
detailOptions.push({
|
|
1879
|
+
value: "change-auth",
|
|
1880
|
+
label: "Change authentication (API/OAuth)",
|
|
1881
|
+
hint: "Switch between a ClinePass API key and account sign-in"
|
|
1882
|
+
});
|
|
1883
|
+
} else if (supportsNativeOAuth(id) || provider.authType === "oauth") {
|
|
1807
1884
|
detailOptions.push({
|
|
1808
1885
|
value: "auth",
|
|
1809
1886
|
label: "Sign in again (OAuth)",
|
|
@@ -1837,12 +1914,13 @@ async function runProviderDetail(id) {
|
|
|
1837
1914
|
return "back";
|
|
1838
1915
|
}
|
|
1839
1916
|
if (action === "refresh") {
|
|
1840
|
-
await runProvidersRefreshModels(id);
|
|
1841
|
-
|
|
1917
|
+
return await runProvidersRefreshModels(id) === 0 ? "back" : "failed";
|
|
1918
|
+
}
|
|
1919
|
+
if (action === "change-auth" && template) {
|
|
1920
|
+
return await runDualAuthTemplateFlow(template, provider) === 0 ? "back" : "failed";
|
|
1842
1921
|
}
|
|
1843
1922
|
if (action === "auth") {
|
|
1844
|
-
await runProvidersAuth(id);
|
|
1845
|
-
return "back";
|
|
1923
|
+
return await runProvidersAuth(id) === 0 ? "back" : "failed";
|
|
1846
1924
|
}
|
|
1847
1925
|
if (action === "toggle") {
|
|
1848
1926
|
const result = toggleProviderEnabled(id);
|
|
@@ -1852,10 +1930,11 @@ async function runProviderDetail(id) {
|
|
|
1852
1930
|
return "back";
|
|
1853
1931
|
}
|
|
1854
1932
|
const code = await runProvidersRemove(id, true);
|
|
1855
|
-
return code === 0 ? "removed" : "
|
|
1933
|
+
return code === 0 ? "removed" : "failed";
|
|
1856
1934
|
}
|
|
1857
1935
|
async function runProvidersHub() {
|
|
1858
1936
|
const hasOpencode = findOpencodeBinary() !== null;
|
|
1937
|
+
let lastOperationFailed = false;
|
|
1859
1938
|
while (true) {
|
|
1860
1939
|
const entries = await resolveProvidersForDisplay();
|
|
1861
1940
|
const options = [
|
|
@@ -1883,18 +1962,18 @@ async function runProvidersHub() {
|
|
|
1883
1962
|
options
|
|
1884
1963
|
});
|
|
1885
1964
|
if (p5.isCancel(choice) || choice === "done") {
|
|
1886
|
-
return 0;
|
|
1965
|
+
return lastOperationFailed ? 1 : 0;
|
|
1887
1966
|
}
|
|
1888
1967
|
if (choice === "add") {
|
|
1889
|
-
await runProvidersAdd();
|
|
1968
|
+
lastOperationFailed = await runProvidersAdd() !== 0;
|
|
1890
1969
|
continue;
|
|
1891
1970
|
}
|
|
1892
1971
|
if (choice === "import") {
|
|
1893
|
-
await runProvidersImport();
|
|
1972
|
+
lastOperationFailed = await runProvidersImport() !== 0;
|
|
1894
1973
|
continue;
|
|
1895
1974
|
}
|
|
1896
1975
|
if (choice === "refresh-all") {
|
|
1897
|
-
await runProvidersRefreshModels();
|
|
1976
|
+
lastOperationFailed = await runProvidersRefreshModels() !== 0;
|
|
1898
1977
|
continue;
|
|
1899
1978
|
}
|
|
1900
1979
|
if (choice === "auth-menu") {
|
|
@@ -1912,7 +1991,9 @@ async function runProvidersHub() {
|
|
|
1912
1991
|
hint: "device code"
|
|
1913
1992
|
}))
|
|
1914
1993
|
});
|
|
1915
|
-
if (!p5.isCancel(providerId))
|
|
1994
|
+
if (!p5.isCancel(providerId)) {
|
|
1995
|
+
lastOperationFailed = await runProvidersAuth(providerId) !== 0;
|
|
1996
|
+
}
|
|
1916
1997
|
continue;
|
|
1917
1998
|
}
|
|
1918
1999
|
if (typeof choice === "string" && choice.startsWith("cloud:")) {
|
|
@@ -1923,6 +2004,7 @@ async function runProvidersHub() {
|
|
|
1923
2004
|
if (typeof choice === "string" && choice.startsWith("provider:")) {
|
|
1924
2005
|
const id = choice.slice("provider:".length);
|
|
1925
2006
|
const outcome = await runProviderDetail(id);
|
|
2007
|
+
lastOperationFailed = outcome === "failed";
|
|
1926
2008
|
if (outcome === "removed") continue;
|
|
1927
2009
|
}
|
|
1928
2010
|
}
|
|
@@ -3197,7 +3279,11 @@ async function startCodexProxy(routes, options = {}) {
|
|
|
3197
3279
|
oauthAccountId: route.oauthAccountId,
|
|
3198
3280
|
providerData: route.providerData,
|
|
3199
3281
|
vertex: route.vertex,
|
|
3200
|
-
headers: route.headers
|
|
3282
|
+
headers: route.headers,
|
|
3283
|
+
refreshToken: route.refreshToken,
|
|
3284
|
+
onTokenRefreshed: (refreshed) => {
|
|
3285
|
+
route.apiKey = refreshed;
|
|
3286
|
+
}
|
|
3201
3287
|
}));
|
|
3202
3288
|
}
|
|
3203
3289
|
return new Promise((resolve2, reject2) => {
|
|
@@ -3742,7 +3828,8 @@ function resolveCodexRoute(provider, model, apiKey) {
|
|
|
3742
3828
|
supportedParameters: model.supportedParameters,
|
|
3743
3829
|
reasoning: model.reasoning,
|
|
3744
3830
|
interleavedReasoningField: model.interleavedReasoningField,
|
|
3745
|
-
headers: provider.headers
|
|
3831
|
+
headers: provider.headers,
|
|
3832
|
+
refreshToken: providerRefreshToken(provider.id, provider.authType, provider.authRef)
|
|
3746
3833
|
};
|
|
3747
3834
|
if (model.modelFormat === "cloud-code") {
|
|
3748
3835
|
return {
|
|
@@ -3760,7 +3847,8 @@ function resolveCodexRoute(provider, model, apiKey) {
|
|
|
3760
3847
|
supportedParameters: model.supportedParameters,
|
|
3761
3848
|
reasoning: model.reasoning,
|
|
3762
3849
|
interleavedReasoningField: model.interleavedReasoningField,
|
|
3763
|
-
headers: provider.headers
|
|
3850
|
+
headers: provider.headers,
|
|
3851
|
+
refreshToken: providerRefreshToken(provider.id, provider.authType, provider.authRef)
|
|
3764
3852
|
};
|
|
3765
3853
|
}
|
|
3766
3854
|
if (model.npm === "@ai-sdk/openai" && provider.authType !== "oauth" && model.modelFormat === "openai") {
|
|
@@ -4302,7 +4390,9 @@ async function resolveFavorite(fav, ctx) {
|
|
|
4302
4390
|
apiKey: await resolveLocalProviderApiKey(found.provider) ?? "",
|
|
4303
4391
|
authType: found.provider.authType,
|
|
4304
4392
|
oauthAccountId: found.provider.oauthAccountId,
|
|
4305
|
-
providerData: found.provider.providerData
|
|
4393
|
+
providerData: found.provider.providerData,
|
|
4394
|
+
headers: found.provider.headers,
|
|
4395
|
+
refreshToken: providerRefreshToken(found.provider.id, found.provider.authType, found.provider.authRef)
|
|
4306
4396
|
};
|
|
4307
4397
|
}
|
|
4308
4398
|
return void 0;
|
|
@@ -5204,7 +5294,8 @@ Error: ${launchPlan.error}
|
|
|
5204
5294
|
supportedParameters: route.supportedParameters,
|
|
5205
5295
|
reasoning: route.reasoning,
|
|
5206
5296
|
interleavedReasoningField: route.interleavedReasoningField,
|
|
5207
|
-
headers: route.headers
|
|
5297
|
+
headers: route.headers,
|
|
5298
|
+
refreshToken: route.refreshToken
|
|
5208
5299
|
}], { debug: trace });
|
|
5209
5300
|
proxyPort = proxyHandle.port;
|
|
5210
5301
|
}
|
|
@@ -5698,7 +5789,11 @@ async function startGeminiProxy(routes, debug = false) {
|
|
|
5698
5789
|
authType: route.authType,
|
|
5699
5790
|
oauthAccountId: route.oauthAccountId,
|
|
5700
5791
|
providerData: route.providerData,
|
|
5701
|
-
headers: route.headers
|
|
5792
|
+
headers: route.headers,
|
|
5793
|
+
refreshToken: route.refreshToken,
|
|
5794
|
+
onTokenRefreshed: (refreshed) => {
|
|
5795
|
+
route.apiKey = refreshed;
|
|
5796
|
+
}
|
|
5702
5797
|
});
|
|
5703
5798
|
models.set(route.aliasId, m);
|
|
5704
5799
|
}
|
|
@@ -7469,6 +7564,26 @@ var MAX_REASONING_ECHOES_PER_CONVERSATION = 20;
|
|
|
7469
7564
|
function isCloudCodeOAuthRoute(route) {
|
|
7470
7565
|
return route.providerId === "antigravity" && route.authType === "oauth" && route.modelFormat === "cloud-code";
|
|
7471
7566
|
}
|
|
7567
|
+
async function createRouteLanguageModel(route) {
|
|
7568
|
+
const spec = {
|
|
7569
|
+
npm: route.npm,
|
|
7570
|
+
modelId: route.upstreamModelId,
|
|
7571
|
+
apiKey: route.apiKey,
|
|
7572
|
+
baseURL: route.baseURL,
|
|
7573
|
+
providerId: route.providerId,
|
|
7574
|
+
authType: route.authType,
|
|
7575
|
+
oauthAccountId: route.oauthAccountId,
|
|
7576
|
+
providerData: route.providerData
|
|
7577
|
+
};
|
|
7578
|
+
if (route.headers !== void 0) spec.headers = route.headers;
|
|
7579
|
+
if (route.refreshToken) {
|
|
7580
|
+
spec.refreshToken = route.refreshToken;
|
|
7581
|
+
spec.onTokenRefreshed = (refreshed) => {
|
|
7582
|
+
route.apiKey = refreshed;
|
|
7583
|
+
};
|
|
7584
|
+
}
|
|
7585
|
+
return createLanguageModel(spec);
|
|
7586
|
+
}
|
|
7472
7587
|
function isUserTurnRequest(parsed) {
|
|
7473
7588
|
return typeof parsed?.requestId === "string" && parsed.requestId.startsWith("agent/");
|
|
7474
7589
|
}
|
|
@@ -7547,7 +7662,12 @@ async function startCloudCodeGateway(routes, opts = {}) {
|
|
|
7547
7662
|
} catch {
|
|
7548
7663
|
}
|
|
7549
7664
|
if (trace && parsed) {
|
|
7550
|
-
const preview = JSON.stringify(parsed
|
|
7665
|
+
const preview = JSON.stringify(parsed, function(key, value) {
|
|
7666
|
+
if (key === "data" && typeof value === "string" && this && typeof this === "object" && typeof this.mimeType === "string") {
|
|
7667
|
+
return `[${value.length} media chars]`;
|
|
7668
|
+
}
|
|
7669
|
+
return value;
|
|
7670
|
+
}).slice(0, 500);
|
|
7551
7671
|
log14(`[gateway] body-preview: ${preview}`);
|
|
7552
7672
|
}
|
|
7553
7673
|
if (lowerUrl.includes("loadcodeassist")) {
|
|
@@ -7575,6 +7695,13 @@ async function startCloudCodeGateway(routes, opts = {}) {
|
|
|
7575
7695
|
`[gateway] resolved route: ${route.catalogId} (${route.providerId}/${route.upstreamModelId} via ${model})`
|
|
7576
7696
|
);
|
|
7577
7697
|
}
|
|
7698
|
+
const media = sanitizeUnsupportedInlineData(parsed);
|
|
7699
|
+
parsed = media.request;
|
|
7700
|
+
if (media.latestUserTurnHasUnsupportedMedia) {
|
|
7701
|
+
if (trace) log14("[gateway] unsupported media in current user turn; provider call skipped");
|
|
7702
|
+
respondUnsupportedMedia(res, route, lowerUrl.includes("stream"));
|
|
7703
|
+
return;
|
|
7704
|
+
}
|
|
7578
7705
|
if (trackActiveRoute && selectedSlotIds.has(model ?? "") && isUserTurnRequest(parsed)) {
|
|
7579
7706
|
activeRoute = route;
|
|
7580
7707
|
if (trace) log14(`[gateway] active route: ${route.catalogId} via ${model}`);
|
|
@@ -7944,6 +8071,41 @@ function respondJson(res, status, data) {
|
|
|
7944
8071
|
});
|
|
7945
8072
|
res.end(body);
|
|
7946
8073
|
}
|
|
8074
|
+
function respondUnsupportedMedia(res, route, streaming) {
|
|
8075
|
+
const responseId = `relay-${Date.now()}`;
|
|
8076
|
+
if (streaming) {
|
|
8077
|
+
const chunk = formatCloudCodeChunk({
|
|
8078
|
+
text: UNSUPPORTED_VOICE_MESSAGE,
|
|
8079
|
+
modelVersion: route.catalogId,
|
|
8080
|
+
responseId,
|
|
8081
|
+
finishReason: "STOP"
|
|
8082
|
+
});
|
|
8083
|
+
res.writeHead(200, {
|
|
8084
|
+
"content-type": "text/event-stream",
|
|
8085
|
+
"cache-control": "no-cache",
|
|
8086
|
+
"grpc-status": "0"
|
|
8087
|
+
});
|
|
8088
|
+
res.end(`data: ${JSON.stringify(chunk)}
|
|
8089
|
+
|
|
8090
|
+
`);
|
|
8091
|
+
return;
|
|
8092
|
+
}
|
|
8093
|
+
respondJson(res, 200, {
|
|
8094
|
+
response: {
|
|
8095
|
+
candidates: [{
|
|
8096
|
+
content: {
|
|
8097
|
+
role: "model",
|
|
8098
|
+
parts: [{ text: UNSUPPORTED_VOICE_MESSAGE }]
|
|
8099
|
+
},
|
|
8100
|
+
finishReason: "STOP"
|
|
8101
|
+
}],
|
|
8102
|
+
modelVersion: route.catalogId,
|
|
8103
|
+
responseId
|
|
8104
|
+
},
|
|
8105
|
+
traceId: "relay-trace",
|
|
8106
|
+
metadata: {}
|
|
8107
|
+
});
|
|
8108
|
+
}
|
|
7947
8109
|
function parsePseudoToolCall(text4, knownToolNames) {
|
|
7948
8110
|
const trimmed = text4.trim();
|
|
7949
8111
|
if (!trimmed.startsWith("{") || !trimmed.endsWith("}")) return null;
|
|
@@ -7972,16 +8134,7 @@ async function handleStreamingRequest(res, route, providerOptions, parsed, log14
|
|
|
7972
8134
|
providerOptions,
|
|
7973
8135
|
sdkParams.providerOptions
|
|
7974
8136
|
);
|
|
7975
|
-
const langModel = await
|
|
7976
|
-
npm: route.npm,
|
|
7977
|
-
modelId: route.upstreamModelId,
|
|
7978
|
-
apiKey: route.apiKey,
|
|
7979
|
-
baseURL: route.baseURL,
|
|
7980
|
-
providerId: route.providerId,
|
|
7981
|
-
authType: route.authType,
|
|
7982
|
-
oauthAccountId: route.oauthAccountId,
|
|
7983
|
-
providerData: route.providerData
|
|
7984
|
-
});
|
|
8137
|
+
const langModel = await createRouteLanguageModel(route);
|
|
7985
8138
|
const responseId = `relay-${Date.now()}`;
|
|
7986
8139
|
const { fullStream } = streamText3({
|
|
7987
8140
|
model: langModel,
|
|
@@ -8158,16 +8311,7 @@ async function handleUnaryRequest(res, route, providerOptions, parsed, log14, op
|
|
|
8158
8311
|
providerOptions,
|
|
8159
8312
|
sdkParams.providerOptions
|
|
8160
8313
|
);
|
|
8161
|
-
const langModel = await
|
|
8162
|
-
npm: route.npm,
|
|
8163
|
-
modelId: route.upstreamModelId,
|
|
8164
|
-
apiKey: route.apiKey,
|
|
8165
|
-
baseURL: route.baseURL,
|
|
8166
|
-
providerId: route.providerId,
|
|
8167
|
-
authType: route.authType,
|
|
8168
|
-
oauthAccountId: route.oauthAccountId,
|
|
8169
|
-
providerData: route.providerData
|
|
8170
|
-
});
|
|
8314
|
+
const langModel = await createRouteLanguageModel(route);
|
|
8171
8315
|
const responseId = `relay-${Date.now()}`;
|
|
8172
8316
|
const result = await generateText3({
|
|
8173
8317
|
model: langModel,
|
|
@@ -8226,7 +8370,9 @@ async function resolveAntigravityLaunchRoutes(opts) {
|
|
|
8226
8370
|
apiKey,
|
|
8227
8371
|
authType: opts.provider.authType,
|
|
8228
8372
|
oauthAccountId: opts.provider.oauthAccountId,
|
|
8229
|
-
providerData: opts.provider.providerData
|
|
8373
|
+
providerData: opts.provider.providerData,
|
|
8374
|
+
headers: opts.provider.headers,
|
|
8375
|
+
refreshToken: providerRefreshToken(opts.provider.id, opts.provider.authType, opts.provider.authRef)
|
|
8230
8376
|
};
|
|
8231
8377
|
const ctx = {
|
|
8232
8378
|
agent: "antigravity",
|
|
@@ -9068,7 +9214,8 @@ function codexRouteToProxyRoute(provider, model, apiKey) {
|
|
|
9068
9214
|
supportedParameters: route.supportedParameters,
|
|
9069
9215
|
reasoning: route.reasoning,
|
|
9070
9216
|
interleavedReasoningField: route.interleavedReasoningField,
|
|
9071
|
-
headers: route.headers
|
|
9217
|
+
headers: route.headers,
|
|
9218
|
+
refreshToken: route.refreshToken
|
|
9072
9219
|
};
|
|
9073
9220
|
}
|
|
9074
9221
|
async function buildCodexAppProviderCatalogRoutes(provider, apiKey, selectedModelId, trace) {
|
|
@@ -9534,7 +9681,8 @@ function codexProxyRouteToCodexRoute(route, fallbackProviderId) {
|
|
|
9534
9681
|
supportedParameters: route.supportedParameters,
|
|
9535
9682
|
reasoning: route.reasoning,
|
|
9536
9683
|
interleavedReasoningField: route.interleavedReasoningField,
|
|
9537
|
-
headers: route.headers
|
|
9684
|
+
headers: route.headers,
|
|
9685
|
+
refreshToken: route.refreshToken
|
|
9538
9686
|
};
|
|
9539
9687
|
}
|
|
9540
9688
|
async function waitForShutdownWithConfirm() {
|
|
@@ -13335,7 +13483,9 @@ Error: ${launchPlan.error}
|
|
|
13335
13483
|
reasoning: selectedModel.reasoning,
|
|
13336
13484
|
interleavedReasoningField: selectedModel.interleavedReasoningField,
|
|
13337
13485
|
useResponsesLite: selectedModel.useResponsesLite,
|
|
13338
|
-
preferWebSockets: selectedModel.preferWebSockets
|
|
13486
|
+
preferWebSockets: selectedModel.preferWebSockets,
|
|
13487
|
+
refreshToken: providerRefreshToken(activeProvider.id, activeProvider.authType, activeProvider.authRef),
|
|
13488
|
+
headers: activeProvider.headers
|
|
13339
13489
|
},
|
|
13340
13490
|
launchApiKey
|
|
13341
13491
|
);
|
|
@@ -13443,7 +13593,7 @@ Options:
|
|
|
13443
13593
|
--trace Write debug logs under ~/.relay-ai/logs/`);
|
|
13444
13594
|
return 0;
|
|
13445
13595
|
}
|
|
13446
|
-
const { runUiCommand } = await import("./ui-command-
|
|
13596
|
+
const { runUiCommand } = await import("./ui-command-RYWL36VR.js");
|
|
13447
13597
|
return runUiCommand({ trace: parsed.trace, serverMode: parsed.uiServerMode });
|
|
13448
13598
|
}
|
|
13449
13599
|
if (parsed.command === "models") {
|
|
@@ -13468,6 +13618,12 @@ Options:
|
|
|
13468
13618
|
}
|
|
13469
13619
|
if (parsed.trace) {
|
|
13470
13620
|
process.env.RELAY_AI_TRACE = "1";
|
|
13621
|
+
const providerTraceLogPath = prepareProviderTraceLog();
|
|
13622
|
+
try {
|
|
13623
|
+
return await runProvidersCommand(parsed.claudeArgs);
|
|
13624
|
+
} finally {
|
|
13625
|
+
printTraceLog(providerTraceLogPath);
|
|
13626
|
+
}
|
|
13471
13627
|
}
|
|
13472
13628
|
return runProvidersCommand(parsed.claudeArgs);
|
|
13473
13629
|
}
|