@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.
@@ -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.authType === "api" && t.addable !== false && !t.hidden).sort((a, b) => a.name.localeCompare(b.name));
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) => t.authType === "oauth" && t.supported && t.addable !== false && !t.hidden && !configured.has(t.id)).sort((a, b) => a.name.localeCompare(b.name));
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-HXGZ4CTV.js.map
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":";;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA8aO,SAAS,yBAA6C;AAC3D,SAAO,mBACJ,OAAO,OAAK,EAAE,cAAc,EAAE,eAAe,CAAC,EAAE,QAAQ,GAAG,SAAS,KAAK,KAAK,EAAE,YAAY,SAAS,CAAC,EAAE,MAAM,EAC9G,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAChD;AAGO,SAAS,qBAAqB,gBAAkC,CAAC,GAAuB;AAC7F,QAAM,aAAa,IAAI,IAAI,aAAa;AACxC,SAAO,uBAAuB,EAAE,OAAO,OAAK;AAC1C,QAAI,EAAE,OAAO,kBAAkB;AAC7B,aAAO,CAAC,WAAW,IAAI,KAAK,KAAK,CAAC,WAAW,IAAI,IAAI;AAAA,IACvD;AACA,WAAO,CAAC,WAAW,IAAI,EAAE,EAAE;AAAA,EAC7B,CAAC;AACH;AAEO,SAAS,0BAA0B,gBAAkC,CAAC,GAAuB;AAClG,QAAM,aAAa,IAAI,IAAI,aAAa;AACxC,SAAO,mBACJ,OAAO,OAAK;AACX,UAAM,UAAU,EAAE,eAAe,CAAC,EAAE,QAAQ;AAC5C,WAAO,QAAQ,SAAS,OAAO,KAC1B,CAAC,QAAQ,SAAS,KAAK,KACvB,EAAE,aACF,EAAE,YAAY,SACd,CAAC,EAAE,UACH,CAAC,WAAW,IAAI,EAAE,EAAE;AAAA,EAC3B,CAAC,EACA,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAChD;AAEO,SAAS,gBAAgB,IAA0C;AACxE,SAAO,mBAAmB,KAAK,OAAK,EAAE,OAAO,EAAE;AACjD;AAEO,SAAS,gBAAgB,WAA+B,OAAmC;AAChG,QAAM,IAAI,MAAM,KAAK,EAAE,YAAY;AACnC,MAAI,CAAC,EAAG,QAAO;AACf,SAAO,UAAU;AAAA,IACf,OACE,EAAE,GAAG,YAAY,EAAE,SAAS,CAAC,KAC7B,EAAE,KAAK,YAAY,EAAE,SAAS,CAAC,KAC/B,EAAE,IAAI,YAAY,EAAE,SAAS,CAAC;AAAA,EAClC;AACF;AA3dA,IAiCa;AAjCb;AAAA;AAiCO,IAAM,qBAAyC;AAAA,MACpD;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,aAAa,CAAC,OAAO,OAAO;AAAA,QAC5B,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,aAAa;AAAA,QACb,SAAS,EAAE,gBAAgB,qBAAqB,WAAW,QAAQ;AAAA,QACnE,WAAW;AAAA,QACX,kBAAkB;AAAA,MACpB;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,aAAa;AAAA,QACb,cAAc;AAAA,UACZ,EAAE,IAAI,mBAAmB,MAAM,2BAA2B;AAAA,QAC5D;AAAA,QACA,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,YAAY;AAAA,QACZ,WAAW;AAAA,QACX,gBAAgB;AAAA,QAChB,qBAAqB;AAAA,QACrB,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,gBAAgB;AAAA,QAChB,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,gBAAgB;AAAA,QAChB,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,YAAY;AAAA,QACZ,WAAW;AAAA,QACX,iBAAiB;AAAA,QACjB,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,aAAa;AAAA,QACb,WAAW;AAAA,QACX,mBAAmB;AAAA,MACrB;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,aAAa;AAAA,QACb,WAAW;AAAA,QACX,mBAAmB;AAAA,MACrB;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,aAAa;AAAA,QACb,WAAW;AAAA,QACX,mBAAmB;AAAA,MACrB;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,QACX,SAAS;AAAA,MACX;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,QACX,SAAS;AAAA,MACX;AAAA;AAAA;AAAA,MAGA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,QACX,QAAQ;AAAA,QACR,kBAAkB;AAAA,MACpB;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,QACX,QAAQ;AAAA,QACR,kBAAkB;AAAA,MACpB;AAAA;AAAA,MAEA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,gBAAgB;AAAA,QAChB,YAAY;AAAA,QACZ,WAAW;AAAA,QACX,aAAa;AAAA,QACb,SAAS,EAAE,kBAAkB,gBAAgB;AAAA,QAC7C,WAAW;AAAA,MACb;AAAA,IACF;AAAA;AAAA;","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-HEMJFOXG.js";
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-HXGZ4CTV.js";
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
- p5.log.error(result.error ?? "Could not add provider.");
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
- p5.log.error(result.error ?? "Could not add custom provider.");
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 (supportsNativeOAuth(id) || provider.authType === "oauth") {
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
- return "back";
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" : "back";
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)) await runProvidersAuth(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).slice(0, 500);
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 createLanguageModel({
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 createLanguageModel({
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-26QQUWTQ.js");
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
  }