@marsapi/cli 0.0.157 → 0.0.160

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.
@@ -10,7 +10,7 @@
10
10
  "claude": [
11
11
  {
12
12
  "description": "100 万上下文 | 高强度推理 | 长时 Agent | SWE-bench Verified 95%",
13
- "group": "grp_pzxnceygmqlp",
13
+ "group": "grp_6eg2dq9ywgrg",
14
14
  "group_name": "",
15
15
  "hidden": false,
16
16
  "id": "claude-fable-5",
@@ -46,7 +46,7 @@
46
46
  },
47
47
  {
48
48
  "description": "100 万上下文 | 推理 | 编程 | 长上下文不加价",
49
- "group": "grp_6eg2dq9ywgrg",
49
+ "group": "grp_6co8aqwefsoh",
50
50
  "group_name": "",
51
51
  "hidden": false,
52
52
  "id": "claude-opus-4-6",
@@ -82,7 +82,7 @@
82
82
  },
83
83
  {
84
84
  "description": "100 万上下文 | 长时 Agent 编程 | 知识工作",
85
- "group": "grp_6co8aqwefsoh",
85
+ "group": "grp_6lyxfgbs440g",
86
86
  "group_name": "",
87
87
  "hidden": false,
88
88
  "id": "claude-opus-5-5",
@@ -91,7 +91,7 @@
91
91
  },
92
92
  {
93
93
  "description": "100 万上下文 | Agent 编程 | 长上下文不加价",
94
- "group": "grp_rld6af0zorqd",
94
+ "group": "grp_pzxnceygmqlp",
95
95
  "group_name": "",
96
96
  "hidden": false,
97
97
  "id": "claude-sonnet-4-6",
@@ -100,7 +100,7 @@
100
100
  },
101
101
  {
102
102
  "description": "100 万上下文 | Agent 编程 | 工具调用 | 知识工作",
103
- "group": "grp_6eg2dq9ywgrg",
103
+ "group": "grp_6lyxfgbs440g",
104
104
  "group_name": "",
105
105
  "hidden": false,
106
106
  "id": "claude-sonnet-5",
@@ -109,7 +109,7 @@
109
109
  },
110
110
  {
111
111
  "description": "100 万上下文 | 12.8 万输出 | Agent 编程 | 知识工作",
112
- "group": "grp_irydsgijuckh",
112
+ "group": "grp_6eg2dq9ywgrg",
113
113
  "group_name": "",
114
114
  "hidden": false,
115
115
  "id": "claude-sonnet-5-5",
@@ -120,7 +120,7 @@
120
120
  "codex": [
121
121
  {
122
122
  "description": "105 万上下文 | 12.8 万输出 | 大批量低成本档",
123
- "group": "grp_irydsgijuckh",
123
+ "group": "grp_bsbtt432saoq",
124
124
  "group_name": "",
125
125
  "hidden": false,
126
126
  "id": "gpt-5.6-luna",
@@ -129,7 +129,7 @@
129
129
  },
130
130
  {
131
131
  "description": "105 万上下文 | 12.8 万输出 | 前沿档",
132
- "group": "grp_mb5v069lpnze",
132
+ "group": "grp_irydsgijuckh",
133
133
  "group_name": "",
134
134
  "hidden": false,
135
135
  "id": "gpt-5.6-sol",
@@ -138,7 +138,7 @@
138
138
  },
139
139
  {
140
140
  "description": "105 万上下文 | 12.8 万输出 | 均衡生产档",
141
- "group": "grp_squ2qzjnehps",
141
+ "group": "grp_irydsgijuckh",
142
142
  "group_name": "",
143
143
  "hidden": false,
144
144
  "id": "gpt-5.6-terra",
@@ -147,7 +147,7 @@
147
147
  },
148
148
  {
149
149
  "description": "105 万上下文 | 12.8 万输出 | 思考强度至 max | 计算机操作 / 编码 / 科学基准接近饱和",
150
- "group": "grp_irydsgijuckh",
150
+ "group": "grp_6co8aqwefsoh",
151
151
  "group_name": "",
152
152
  "hidden": false,
153
153
  "id": "gpt-6-astra",
@@ -156,7 +156,7 @@
156
156
  },
157
157
  {
158
158
  "description": "转发至 gpt-6-sol | 实际由 gpt-6-sol 响应 | 105 万上下文 | 12.8 万输出",
159
- "group": "grp_6co8aqwefsoh",
159
+ "group": "grp_irydsgijuckh",
160
160
  "group_name": "",
161
161
  "hidden": false,
162
162
  "id": "gpt-6-luna",
@@ -165,7 +165,7 @@
165
165
  },
166
166
  {
167
167
  "description": "105 万上下文 | 12.8 万输出 | 复杂编程与 Agent 工作流",
168
- "group": "grp_irydsgijuckh",
168
+ "group": "grp_mb5v069lpnze",
169
169
  "group_name": "",
170
170
  "hidden": false,
171
171
  "id": "gpt-6-sol",
@@ -174,7 +174,7 @@
174
174
  },
175
175
  {
176
176
  "description": "105 万上下文 | 12.8 万输出 | 文字与图像输入 | 工具调用、联网搜索、结构化输出 | 工具调用使用 Responses API",
177
- "group": "grp_6co8aqwefsoh",
177
+ "group": "grp_irydsgijuckh",
178
178
  "group_name": "",
179
179
  "hidden": false,
180
180
  "id": "gpt-6.1-sol",
@@ -183,7 +183,7 @@
183
183
  },
184
184
  {
185
185
  "description": "105 万上下文 | 12.8 万输出 | 计算机操作与日常 Agent 任务 | 均衡档",
186
- "group": "grp_irydsgijuckh",
186
+ "group": "grp_mb5v069lpnze",
187
187
  "group_name": "",
188
188
  "hidden": false,
189
189
  "id": "gpt-6.1-terra",
@@ -248,7 +248,7 @@
248
248
  },
249
249
  {
250
250
  "description": "约 208 token/秒 | 高吞吐 | 多语言 | 编码",
251
- "group": "grp_irydsgijuckh",
251
+ "group": "grp_3pi5kyqkp51b",
252
252
  "group_name": "",
253
253
  "hidden": false,
254
254
  "id": "gemini-3.6-flash",
@@ -257,7 +257,7 @@
257
257
  },
258
258
  {
259
259
  "description": "Agent 主力 | 软件工程 | 网页开发",
260
- "group": "grp_z5khwusxuh2j",
260
+ "group": "grp_3pi5kyqkp51b",
261
261
  "group_name": "",
262
262
  "hidden": false,
263
263
  "id": "gemini-3.7-flash",
@@ -266,7 +266,7 @@
266
266
  },
267
267
  {
268
268
  "description": "推理与编码 | HLE-Verified 54.9% | 长文档工作流",
269
- "group": "grp_z5khwusxuh2j",
269
+ "group": "grp_3pi5kyqkp51b",
270
270
  "group_name": "",
271
271
  "hidden": false,
272
272
  "id": "gemini-3.8-flash",
package/components.json CHANGED
@@ -116,6 +116,20 @@
116
116
  "check": ["agy", "--version"],
117
117
  "requires": []
118
118
  },
119
+ {
120
+ "id": "codebuddy",
121
+ "name": "CodeBuddy Code",
122
+ "category": "cli",
123
+ "aliases": ["codebuddy-code"],
124
+ "platforms": ["darwin", "linux", "win32"],
125
+ "adapter": "codebuddy",
126
+ "latest": { "type": "npm", "package": "@tencent-ai/codebuddy-code" },
127
+ "sources": { "all": "npmmirror 的 @tencent-ai/codebuddy-code(与 npmjs 同一份)" },
128
+ "verify": { "checksum": "npm sha512", "signature": "—" },
129
+ "install": { "type": "adapter" },
130
+ "check": ["codebuddy", "--version"],
131
+ "requires": ["node"]
132
+ },
119
133
  {
120
134
  "id": "claude-desktop",
121
135
  "name": "Claude Desktop",
@@ -10,7 +10,7 @@
10
10
  "claude": [
11
11
  {
12
12
  "description": "100 万上下文 | 高强度推理 | 长时 Agent | SWE-bench Verified 95%",
13
- "group": "grp_pzxnceygmqlp",
13
+ "group": "grp_6eg2dq9ywgrg",
14
14
  "group_name": "",
15
15
  "hidden": false,
16
16
  "id": "claude-fable-5",
@@ -46,7 +46,7 @@
46
46
  },
47
47
  {
48
48
  "description": "100 万上下文 | 推理 | 编程 | 长上下文不加价",
49
- "group": "grp_6eg2dq9ywgrg",
49
+ "group": "grp_6co8aqwefsoh",
50
50
  "group_name": "",
51
51
  "hidden": false,
52
52
  "id": "claude-opus-4-6",
@@ -82,7 +82,7 @@
82
82
  },
83
83
  {
84
84
  "description": "100 万上下文 | 长时 Agent 编程 | 知识工作",
85
- "group": "grp_6co8aqwefsoh",
85
+ "group": "grp_6lyxfgbs440g",
86
86
  "group_name": "",
87
87
  "hidden": false,
88
88
  "id": "claude-opus-5-5",
@@ -91,7 +91,7 @@
91
91
  },
92
92
  {
93
93
  "description": "100 万上下文 | Agent 编程 | 长上下文不加价",
94
- "group": "grp_rld6af0zorqd",
94
+ "group": "grp_pzxnceygmqlp",
95
95
  "group_name": "",
96
96
  "hidden": false,
97
97
  "id": "claude-sonnet-4-6",
@@ -100,7 +100,7 @@
100
100
  },
101
101
  {
102
102
  "description": "100 万上下文 | Agent 编程 | 工具调用 | 知识工作",
103
- "group": "grp_6eg2dq9ywgrg",
103
+ "group": "grp_6lyxfgbs440g",
104
104
  "group_name": "",
105
105
  "hidden": false,
106
106
  "id": "claude-sonnet-5",
@@ -109,7 +109,7 @@
109
109
  },
110
110
  {
111
111
  "description": "100 万上下文 | 12.8 万输出 | Agent 编程 | 知识工作",
112
- "group": "grp_irydsgijuckh",
112
+ "group": "grp_6eg2dq9ywgrg",
113
113
  "group_name": "",
114
114
  "hidden": false,
115
115
  "id": "claude-sonnet-5-5",
@@ -120,7 +120,7 @@
120
120
  "codex": [
121
121
  {
122
122
  "description": "105 万上下文 | 12.8 万输出 | 大批量低成本档",
123
- "group": "grp_irydsgijuckh",
123
+ "group": "grp_bsbtt432saoq",
124
124
  "group_name": "",
125
125
  "hidden": false,
126
126
  "id": "gpt-5.6-luna",
@@ -129,7 +129,7 @@
129
129
  },
130
130
  {
131
131
  "description": "105 万上下文 | 12.8 万输出 | 前沿档",
132
- "group": "grp_mb5v069lpnze",
132
+ "group": "grp_irydsgijuckh",
133
133
  "group_name": "",
134
134
  "hidden": false,
135
135
  "id": "gpt-5.6-sol",
@@ -138,7 +138,7 @@
138
138
  },
139
139
  {
140
140
  "description": "105 万上下文 | 12.8 万输出 | 均衡生产档",
141
- "group": "grp_squ2qzjnehps",
141
+ "group": "grp_irydsgijuckh",
142
142
  "group_name": "",
143
143
  "hidden": false,
144
144
  "id": "gpt-5.6-terra",
@@ -147,7 +147,7 @@
147
147
  },
148
148
  {
149
149
  "description": "105 万上下文 | 12.8 万输出 | 思考强度至 max | 计算机操作 / 编码 / 科学基准接近饱和",
150
- "group": "grp_irydsgijuckh",
150
+ "group": "grp_6co8aqwefsoh",
151
151
  "group_name": "",
152
152
  "hidden": false,
153
153
  "id": "gpt-6-astra",
@@ -156,7 +156,7 @@
156
156
  },
157
157
  {
158
158
  "description": "转发至 gpt-6-sol | 实际由 gpt-6-sol 响应 | 105 万上下文 | 12.8 万输出",
159
- "group": "grp_6co8aqwefsoh",
159
+ "group": "grp_irydsgijuckh",
160
160
  "group_name": "",
161
161
  "hidden": false,
162
162
  "id": "gpt-6-luna",
@@ -165,7 +165,7 @@
165
165
  },
166
166
  {
167
167
  "description": "105 万上下文 | 12.8 万输出 | 复杂编程与 Agent 工作流",
168
- "group": "grp_irydsgijuckh",
168
+ "group": "grp_mb5v069lpnze",
169
169
  "group_name": "",
170
170
  "hidden": false,
171
171
  "id": "gpt-6-sol",
@@ -174,7 +174,7 @@
174
174
  },
175
175
  {
176
176
  "description": "105 万上下文 | 12.8 万输出 | 文字与图像输入 | 工具调用、联网搜索、结构化输出 | 工具调用使用 Responses API",
177
- "group": "grp_6co8aqwefsoh",
177
+ "group": "grp_irydsgijuckh",
178
178
  "group_name": "",
179
179
  "hidden": false,
180
180
  "id": "gpt-6.1-sol",
@@ -183,7 +183,7 @@
183
183
  },
184
184
  {
185
185
  "description": "105 万上下文 | 12.8 万输出 | 计算机操作与日常 Agent 任务 | 均衡档",
186
- "group": "grp_irydsgijuckh",
186
+ "group": "grp_mb5v069lpnze",
187
187
  "group_name": "",
188
188
  "hidden": false,
189
189
  "id": "gpt-6.1-terra",
@@ -248,7 +248,7 @@
248
248
  },
249
249
  {
250
250
  "description": "约 208 token/秒 | 高吞吐 | 多语言 | 编码",
251
- "group": "grp_irydsgijuckh",
251
+ "group": "grp_3pi5kyqkp51b",
252
252
  "group_name": "",
253
253
  "hidden": false,
254
254
  "id": "gemini-3.6-flash",
@@ -257,7 +257,7 @@
257
257
  },
258
258
  {
259
259
  "description": "Agent 主力 | 软件工程 | 网页开发",
260
- "group": "grp_z5khwusxuh2j",
260
+ "group": "grp_3pi5kyqkp51b",
261
261
  "group_name": "",
262
262
  "hidden": false,
263
263
  "id": "gemini-3.7-flash",
@@ -266,7 +266,7 @@
266
266
  },
267
267
  {
268
268
  "description": "推理与编码 | HLE-Verified 54.9% | 长文档工作流",
269
- "group": "grp_z5khwusxuh2j",
269
+ "group": "grp_3pi5kyqkp51b",
270
270
  "group_name": "",
271
271
  "hidden": false,
272
272
  "id": "gemini-3.8-flash",
@@ -1 +1 @@
1
- import o from"chalk";import{getAdapter as e}from"../lib/tools/registry.js";import{postApplyPrompts as t}from"../lib/post-apply.js";import{ensureReachableGatewayAddress as i}from"./base.js";import{i18n as l}from"../lib/i18n.js";import{configManager as s}from"../lib/config.js";import{toolManager as a,SUPPORTED_TOOLS as n}from"../lib/tool-manager.js";import{validateApiKey as r,fetchModels as p}from"../lib/api-validator.js";import{CODEX_ONE_MILLION_CONTEXT_SETTING as d,setCodexOneMillionContext as c}from"../lib/tools/codex.js";import{resolveModelCatalog as u}from"../lib/model-catalog.js";import{CLAUDE_DESKTOP_FORCE_REGISTRY_SETTING as f,CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING as m}from"../lib/tools/claude-desktop.js";import{operationError as g,authenticationError as y,networkError as _,EXIT_CODES as k}from"../lib/errors.js";import{canPrompt as h,emitJson as b,isColorEnabled as v,isDryRun as w,isJsonMode as x,isNonInteractive as C,shouldAutoConfirm as j}from"../lib/runtime-options.js";import{appsForTools as K,appUpgradeCommand as $,getApp as T}from"../lib/app-update.js";import{join as M}from"path";import{asksBeforeWriting as G,confirmWritePlan as O,printWritePlan as S,toolWritePlan as I}from"../lib/write-plan.js";import N from"inquirer";import{logger as E}from"../utils/logger.js";import{forgetInstalls as A}from"../lib/tools/tool-installs.js";import{CLI_NAME as B,brandEnv as D}from"../lib/brand.js";export const DEDICATED_KEYS=[{option:"claudekey",tool:"claude-code",need:"claude"},{option:"codexkey",tool:"codex",need:"gpt"},{option:"grokkey",tool:"grok",need:"grok"},{option:"desktopkey",tool:"claude-desktop",need:"claude"},{option:"agykey",tool:"agy",need:"gemini"},{option:"openclawkey",tool:"openclaw",need:"any",hidden:!0},{option:"hermeskey",tool:"hermes",need:"any",hidden:!0},{option:"atomcodekey",tool:"atomcode",need:"any",hidden:!0}];async function F(o){const e=await p(o);if(!e.ok)return{hasClaude:!0,hasGpt:!0,hasGrok:!0,hasGemini:!0,probed:!1};const t=e.models.map(o=>o.toLowerCase());return{hasClaude:t.some(o=>o.includes("claude")),hasGpt:t.some(o=>o.startsWith("gpt")||o.includes("gpt-")||/^o\d/.test(o)),hasGrok:t.some(o=>o.includes("grok")),hasGemini:t.some(o=>o.startsWith("gemini")),probed:!0}}function L(o,e){switch(e){case"claude":return o.hasClaude;case"gpt":return o.hasGpt;case"grok":return o.hasGrok;case"gemini":return o.hasGemini;default:return!0}}export function parseOnOff(o){const e=(o??"").trim().toLowerCase();return!!["on","true","show","1","yes","y"].includes(e)||!["off","false","hide","0","no","n"].includes(e)&&void 0}function R(e){console.log(o.green(e))}function P(e){console.log(o.yellow(e))}function Y(e){console.error(o.red(e))}let q=null;function z(o){const e={operation:1,authentication:2,network:3};(!q||e[o]>e[q])&&(q=o)}async function H(e,t){x()||console.log(o.gray(l.t("setup.validating",{label:e})));const i=await r(t);if(i.valid)return!0;const a=l.t("errors.key_placeholder"),n="--key"===e?`${B} setup --key ${a}`:`${B} setup ${e} ${a}`;let p;if("network_error"===i.error?(z("network"),p=_(l.t("setup.unreachable",{url:s.getBaseUrl(),reason:i.message||"network error"}),`${B} base auto`,"network_error")):"invalid_api_key"===i.error?(z("authentication"),p=y(l.t("setup.invalid_key",{label:e,reason:i.message||"invalid"}),n,"invalid_api_key")):(z("operation"),p=g(l.t("setup.validate_failed",{label:e,reason:i.message||i.error||"unknown"}),n,i.error)),x())throw p;return Y(p.message),console.log(o.gray(l.t("errors.next_step",{command:p.hint}))),!1}async function W(t,i,r={}){const{oneMillion:p,officialLogin:c,desktopRegistry:u,force:y,takeOver:_}=r,k=n[t];try{"claude-desktop"===t&&void 0!==u&&s.setToolSetting("claude-desktop",f,u),"codex"===t&&void 0!==p&&s.setToolSetting("codex",d,p),"claude-desktop"===t&&void 0!==c&&s.setToolSetting("claude-desktop",m,!c),await a.applyPrivateConfig(t,i,s.getModelsForTool(t),{force:y,takeOver:_})}catch(o){if(x())throw g(o instanceof Error?o.message:String(o),`${B} setup --key ${l.t("errors.key_placeholder")}`,"config_write_failed");const e=(o instanceof Error?o.message:String(o)).replace(/\s+/g," ").trim();return Y("× "+l.t("setup.apply_failed",{tool:k.displayName,reason:e})),!1}return a.printApplied(t),y&&console.log(o.gray(" "+l.t("config.force_done",{tool:k.displayName,name:t}))),"codex"===t&&void 0!==p&&console.log(o.gray(" "+l.t(p?"setup.codex_1m_enabled":"setup.codex_1m_disabled"))),e(t)?.isInstalled&&!a.isToolInstalled(t)&&console.log(o.yellow(" ! "+l.t("setup.gui_preconfigured",{tool:k.displayName,install:k.installCommand}))),!0}function U(o){return!e(o)?.isInstalled&&!a.isToolInstalled(o)}export async function installMissingApps(e,t){const i=K(e).filter(o=>{const e=T(o)?.appInstaller;try{return Boolean(e&&!e.blocker()&&!e.installedPath())}catch(e){return E.logError(`setup: app installed? ${o}`,e),!1}});if(0===i.length)return!1;const s=o=>T(o)?.displayName??o;let a=t;if(void 0===a&&!x())if(j())a=!C();else if(h()){const o=i.map(s).join(l.t("setup.list_separator")),e=i.reduce((o,e)=>o+(T(e)?.appInstaller.sizeMb()??0),0);console.log(""),a=(await N.prompt([{type:"confirm",name:"go",message:l.t("setup.install_app_confirm",{tools:o,size:String(e)}),default:!0}])).go}if(!a&&!x())for(const e of i)console.log(o.gray(l.t("setup.install_app_hint",{tool:s(e),command:$(e)})));return Boolean(a)}function J(o){P(l.t("setup.still_missing",{tools:o.map(o=>n[o].displayName).join(l.t("setup.list_separator")),commands:o.map(o=>`${B} config ${o} --yes`).join(l.t("setup.list_separator"))}))}function Q(e,t,i=[]){const a=I(e),n=M(s.getConfigDir(),"config.yaml");if(x())b({dry_run:!0,tools:a,install_first:i,key_file:t?n:null});else{if(0===a.length&&0===i.length){const e=(v()?o.cyan:o=>o)(l.t("runtime.dry_run_label"));return void console.log(`${e} ${l.t("setup.dry_run_none")}`)}S(a,{label:l.t("runtime.dry_run_label"),keyFile:t?n:void 0,installFirst:i})}}function V(){return"darwin"===process.platform||"win32"===process.platform||a.isToolInstalled("claude-desktop")}export async function setupCommand(r){q=null;const p=r.key?.trim(),f=DEDICATED_KEYS.map(o=>({...o,apiKey:r[o.option]?.trim()})).filter(o=>Boolean(o.apiKey)),m=void 0!==r.oneMillion,g=void 0!==r.claudeOfficial;let y;if(g&&(y=parseOnOff(r.claudeOfficial),void 0===y))return Y(l.t("setup.claude_official_invalid",{value:String(r.claudeOfficial)})),void(process.exitCode=1);const _=void 0!==r.desktopRegistry;let h;if(_&&(h=parseOnOff(r.desktopRegistry),void 0===h))return Y(l.t("setup.desktop_registry_invalid",{value:String(r.desktopRegistry)})),void(process.exitCode=1);const b=g||_,v=Boolean(p||f.length>0),K={oneMillion:r.oneMillion,officialLogin:y,desktopRegistry:h,force:r.force};if(!v&&(m||b)&&w())return void Q([...m?["codex"]:[],...b?["claude-desktop"]:[]],!1);if(!v&&(m||b)){if(m){const o=s.getApiKeyForTool("codex");if(o)try{const e=!0===r.oneMillion;s.setToolSetting("codex",d,e);const t=await u(o);c(e,t??void 0),R(l.t(e?"setup.codex_1m_enabled":"setup.codex_1m_disabled"))}catch(o){Y(l.t("setup.apply_failed",{tool:n.codex.displayName,reason:o instanceof Error?o.message:String(o)})),process.exitCode=1}else Y(l.t("setup.codex_1m_missing_key")),process.exitCode=1}if(b){const o=s.getApiKeyForTool("claude-desktop");o?await W("claude-desktop",o,{...K,oneMillion:void 0,takeOver:!0})?await t(["claude-desktop"],{apps:{install:!1}}):process.exitCode=1:(Y(l.t("setup.desktop_official_login_missing_key")),process.exitCode=1)}return}if(!v)return Y(l.t("setup.usage")),void(process.exitCode=1);const $=w();$||await i(p||f[0].apiKey);const T=[],S=[];let I,z=0,X=0;const Z=new Set,oo=f.map(o=>({tool:o.tool,label:`--${o.option}`,apiKey:o.apiKey,need:o.need}));for(const o of oo){if(!await H(o.label,o.apiKey)){X+=1;continue}const e=await F(o.apiKey);!e.probed||L(e,o.need)?(e.probed||P(l.t("setup.probe_failed",{label:o.label})),T.push({tool:o.tool,apiKey:o.apiKey,dedicated:!0}),Z.add(o.tool)):(Y(l.t(`setup.key_no_${o.need}`,{label:o.label,tool:n[o.tool].displayName})),X+=1)}const eo=!!p&&await H("--key",p);p&&!eo&&(I=k[q??"operation"]);const to=p&&eo?await F(p):void 0;if(p&&to&&!to.probed&&P(l.t("setup.probe_failed",{label:"--key"})),!(p&&to&&to.probed)||to.hasClaude||to.hasGpt||to.hasGrok||to.hasGemini||(Y(l.t("setup.key_no_family")),I=1),p&&to&&void 0===I){const o=[{tool:"claude-code",capable:to.hasClaude,skipMsg:l.t(V()?"setup.skip_no_claude_desktop":"setup.skip_no_claude")},{tool:"codex",capable:to.hasGpt,skipMsg:l.t("setup.skip_no_gpt")},{tool:"grok",capable:to.hasGrok,skipMsg:l.t("setup.skip_no_grok")},{tool:"claude-desktop",capable:to.hasClaude&&V(),skipMsg:"",quiet:!0},{tool:"agy",capable:to.hasGemini,skipMsg:l.t("setup.skip_no_gemini")}];for(const e of o)Z.has(e.tool)||(e.capable?(T.push({tool:e.tool,apiKey:p,dedicated:!1}),Z.add(e.tool)):e.quiet||P(e.skipMsg))}const io=Boolean(p&&eo&&void 0===I);if($)return Q(T.filter(o=>!U(o.tool)).map(o=>o.tool),T.length>0,T.filter(o=>U(o.tool)).map(o=>o.tool)),void((X>0||void 0!==I)&&(process.exitCode=I??k[q??"operation"]));const lo=T.filter(o=>!U(o.tool)),so=io||T.some(o=>o.dedicated),ao=!r.fromInstaller&&G();if((T.length>0||so)&&!r.fromInstaller&&!await O(lo.map(o=>o.tool),{keyFile:so?M(s.getConfigDir(),"config.yaml"):void 0,installFirst:T.filter(o=>U(o.tool)).map(o=>o.tool)}))return void(process.exitCode=k.cancelled);io&&p&&s.setApiKey(p);for(const o of T)o.dedicated&&s.setToolApiKey(o.tool,o.apiKey),U(o.tool)?S.push({tool:o.tool,apiKey:o.apiKey}):await W(o.tool,o.apiKey,{...K,takeOver:o.dedicated||ao})?z+=1:(X+=1,Z.delete(o.tool));if(void 0!==I)return S.length>0&&J(S.map(o=>o.tool)),void(process.exitCode=I);let no=[];if(S.length>0){const e=await async function(e,t,i){const s=e.map(o=>o.tool);if(0===s.length)return{still:[],applied:[],failed:[]};const r=s.map(o=>n[o].displayName).join(l.t("setup.list_separator"));let p=t;if(void 0!==p||x()||(j()?p=!C():process.stdin.isTTY&&(console.log(""),p=(await N.prompt([{type:"confirm",name:"go",message:l.t("setup.install_confirm",{tools:r}),default:!0}])).go)),!p){console.log("");for(const e of s)console.log(o.yellow("! "+l.t("setup.install_hint",{tool:n[e].displayName,install:n[e].installCommand})));return x()||console.log(o.gray(l.t("setup.install_all_hint",{cli:B}))),{still:s,applied:[],failed:[]}}const d=[];for(const e of s){console.log(o.bold(`\n${n[e].displayName}`));try{await a.installTool(e)}catch(o){E.logError(`setup: install ${e}`,o)}A(),a.isToolInstalled(e)||d.push(e)}const c=s.filter(o=>!d.includes(o));c.length>0&&console.log("");const u=[],f=[];for(const{tool:o,apiKey:t}of e.filter(o=>c.includes(o.tool)))await W(o,t,i)?u.push(o):f.push(o);return{still:d,applied:u,failed:f}}(S,r.install,K);no=e.still,z+=e.applied.length,X+=e.failed.length;for(const o of[...no,...e.failed])Z.delete(o)}if(z>0){const t=[...Z].filter(o=>!e(o)?.isInstalled&&!no.includes(o)),i=t.map(o=>n[o]?.command).filter(Boolean).join(" / "),s=l.t("setup.done",{count:String(z)});R("\n"+(i?`${s}${l.t("setup.done_commands",{commands:i})}`:s)),no.length>0&&J(no);for(const o of t){const e=a.ensureNativeOnPath(o);e&&R(l.t("setup.path_added",{tool:n[o].displayName,dir:e}))}const r=t.filter(o=>!a.isOnPath(o));if(r.length>0&&!x()&&"1"!==D("PATH_HINT_BY_CALLER")){const e=r.map(o=>n[o].command).join(" / ");console.log(o.yellow(" ! "+l.t("win32"===process.platform?"setup.path_reload_windows":"setup.path_reload",{commands:e})))}}0===z&&no.length>0&&J(no),X>0&&(Y(l.t("setup.failed_summary",{count:String(X)})),x()||console.error(`${B} setup --key ${l.t("errors.key_placeholder")}`)),await t([...Z],{apps:{install:await installMissingApps([...Z],r.install)}}),(X>0||0===z&&0===no.length)&&(process.exitCode=k[q??"operation"])}
1
+ import o from"chalk";import{getAdapter as e}from"../lib/tools/registry.js";import{postApplyPrompts as t}from"../lib/post-apply.js";import{ensureReachableGatewayAddress as i}from"./base.js";import{i18n as l}from"../lib/i18n.js";import{configManager as s}from"../lib/config.js";import{toolManager as a,SUPPORTED_TOOLS as n}from"../lib/tool-manager.js";import{validateApiKey as r,fetchModels as p}from"../lib/api-validator.js";import{CODEX_ONE_MILLION_CONTEXT_SETTING as d,setCodexOneMillionContext as c}from"../lib/tools/codex.js";import{resolveModelCatalog as u}from"../lib/model-catalog.js";import{CLAUDE_DESKTOP_FORCE_REGISTRY_SETTING as f,CLAUDE_DESKTOP_HIDE_OFFICIAL_LOGIN_SETTING as m}from"../lib/tools/claude-desktop.js";import{operationError as g,authenticationError as y,networkError as k,EXIT_CODES as _}from"../lib/errors.js";import{canPrompt as h,emitJson as b,isColorEnabled as w,isDryRun as v,isJsonMode as x,isNonInteractive as C,shouldAutoConfirm as j}from"../lib/runtime-options.js";import{appsForTools as K,appUpgradeCommand as T,getApp as $}from"../lib/app-update.js";import{join as G}from"path";import{asksBeforeWriting as M,confirmWritePlan as I,printWritePlan as O,toolWritePlan as S}from"../lib/write-plan.js";import N from"inquirer";import{logger as E}from"../utils/logger.js";import{forgetInstalls as A}from"../lib/tools/tool-installs.js";import{CLI_NAME as B,brandEnv as D}from"../lib/brand.js";export const DEDICATED_KEYS=[{option:"claudekey",tool:"claude-code",need:"claude"},{option:"codexkey",tool:"codex",need:"gpt"},{option:"grokkey",tool:"grok",need:"grok"},{option:"desktopkey",tool:"claude-desktop",need:"claude"},{option:"agykey",tool:"agy",need:"gemini"},{option:"openclawkey",tool:"openclaw",need:"any",hidden:!0},{option:"hermeskey",tool:"hermes",need:"any",hidden:!0},{option:"atomcodekey",tool:"atomcode",need:"any",hidden:!0},{option:"codebuddykey",tool:"codebuddy",need:"any"},{option:"workbuddykey",tool:"workbuddy",need:"any"}];async function F(o){const e=await p(o);if(!e.ok)return{hasClaude:!0,hasGpt:!0,hasGrok:!0,hasGemini:!0,probed:!1};const t=e.models.map(o=>o.toLowerCase());return{hasClaude:t.some(o=>o.includes("claude")),hasGpt:t.some(o=>o.startsWith("gpt")||o.includes("gpt-")||/^o\d/.test(o)),hasGrok:t.some(o=>o.includes("grok")),hasGemini:t.some(o=>o.startsWith("gemini")),probed:!0}}function L(o,e){switch(e){case"claude":return o.hasClaude;case"gpt":return o.hasGpt;case"grok":return o.hasGrok;case"gemini":return o.hasGemini;default:return!0}}export function parseOnOff(o){const e=(o??"").trim().toLowerCase();return!!["on","true","show","1","yes","y"].includes(e)||!["off","false","hide","0","no","n"].includes(e)&&void 0}function R(e){console.log(o.green(e))}function q(e){console.log(o.yellow(e))}function P(e){console.error(o.red(e))}let Y=null;function z(o){const e={operation:1,authentication:2,network:3};(!Y||e[o]>e[Y])&&(Y=o)}async function H(e,t){x()||console.log(o.gray(l.t("setup.validating",{label:e})));const i=await r(t);if(i.valid)return!0;const a=l.t("errors.key_placeholder"),n="--key"===e?`${B} setup --key ${a}`:`${B} setup ${e} ${a}`;let p;if("network_error"===i.error?(z("network"),p=k(l.t("setup.unreachable",{url:s.getBaseUrl(),reason:i.message||"network error"}),`${B} base auto`,"network_error")):"invalid_api_key"===i.error?(z("authentication"),p=y(l.t("setup.invalid_key",{label:e,reason:i.message||"invalid"}),n,"invalid_api_key")):(z("operation"),p=g(l.t("setup.validate_failed",{label:e,reason:i.message||i.error||"unknown"}),n,i.error)),x())throw p;return P(p.message),console.log(o.gray(l.t("errors.next_step",{command:p.hint}))),!1}async function W(t,i,r={}){const{oneMillion:p,officialLogin:c,desktopRegistry:u,force:y,takeOver:k}=r,_=n[t];try{"claude-desktop"===t&&void 0!==u&&s.setToolSetting("claude-desktop",f,u),"codex"===t&&void 0!==p&&s.setToolSetting("codex",d,p),"claude-desktop"===t&&void 0!==c&&s.setToolSetting("claude-desktop",m,!c),await a.applyPrivateConfig(t,i,s.getModelsForTool(t),{force:y,takeOver:k})}catch(o){if(x())throw g(o instanceof Error?o.message:String(o),`${B} setup --key ${l.t("errors.key_placeholder")}`,"config_write_failed");const e=(o instanceof Error?o.message:String(o)).replace(/\s+/g," ").trim();return P("× "+l.t("setup.apply_failed",{tool:_.displayName,reason:e})),!1}return a.printApplied(t),y&&console.log(o.gray(" "+l.t("config.force_done",{tool:_.displayName,name:t}))),"codex"===t&&void 0!==p&&console.log(o.gray(" "+l.t(p?"setup.codex_1m_enabled":"setup.codex_1m_disabled"))),e(t)?.isInstalled&&!a.isToolInstalled(t)&&console.log(o.yellow(" ! "+l.t("setup.gui_preconfigured",{tool:_.displayName,install:_.installCommand}))),!0}function U(o){return!e(o)?.isInstalled&&!a.isToolInstalled(o)}export async function installMissingApps(e,t){const i=K(e).filter(o=>{const e=$(o)?.appInstaller;try{return Boolean(e&&!e.blocker()&&!e.installedPath())}catch(e){return E.logError(`setup: app installed? ${o}`,e),!1}});if(0===i.length)return!1;const s=o=>$(o)?.displayName??o;let a=t;if(void 0===a&&!x())if(j())a=!C();else if(h()){const o=i.map(s).join(l.t("setup.list_separator")),e=i.reduce((o,e)=>o+($(e)?.appInstaller.sizeMb()??0),0);console.log(""),a=(await N.prompt([{type:"confirm",name:"go",message:l.t("setup.install_app_confirm",{tools:o,size:String(e)}),default:!0}])).go}if(!a&&!x())for(const e of i)console.log(o.gray(l.t("setup.install_app_hint",{tool:s(e),command:T(e)})));return Boolean(a)}function J(o){q(l.t("setup.still_missing",{tools:o.map(o=>n[o].displayName).join(l.t("setup.list_separator")),commands:o.map(o=>`${B} config ${o} --yes`).join(l.t("setup.list_separator"))}))}function Q(e,t,i=[]){const a=S(e),n=G(s.getConfigDir(),"config.yaml");if(x())b({dry_run:!0,tools:a,install_first:i,key_file:t?n:null});else{if(0===a.length&&0===i.length){const e=(w()?o.cyan:o=>o)(l.t("runtime.dry_run_label"));return void console.log(`${e} ${l.t("setup.dry_run_none")}`)}O(a,{label:l.t("runtime.dry_run_label"),keyFile:t?n:void 0,installFirst:i})}}function V(){return"darwin"===process.platform||"win32"===process.platform||a.isToolInstalled("claude-desktop")}export async function setupCommand(r){Y=null;const p=r.key?.trim(),f=DEDICATED_KEYS.map(o=>({...o,apiKey:r[o.option]?.trim()})).filter(o=>Boolean(o.apiKey)),m=void 0!==r.oneMillion,g=void 0!==r.claudeOfficial;let y;if(g&&(y=parseOnOff(r.claudeOfficial),void 0===y))return P(l.t("setup.claude_official_invalid",{value:String(r.claudeOfficial)})),void(process.exitCode=1);const k=void 0!==r.desktopRegistry;let h;if(k&&(h=parseOnOff(r.desktopRegistry),void 0===h))return P(l.t("setup.desktop_registry_invalid",{value:String(r.desktopRegistry)})),void(process.exitCode=1);const b=g||k,w=Boolean(p||f.length>0),K={oneMillion:r.oneMillion,officialLogin:y,desktopRegistry:h,force:r.force};if(!w&&(m||b)&&v())return void Q([...m?["codex"]:[],...b?["claude-desktop"]:[]],!1);if(!w&&(m||b)){if(m){const o=s.getApiKeyForTool("codex");if(o)try{const e=!0===r.oneMillion;s.setToolSetting("codex",d,e);const t=await u(o);c(e,t??void 0),R(l.t(e?"setup.codex_1m_enabled":"setup.codex_1m_disabled"))}catch(o){P(l.t("setup.apply_failed",{tool:n.codex.displayName,reason:o instanceof Error?o.message:String(o)})),process.exitCode=1}else P(l.t("setup.codex_1m_missing_key")),process.exitCode=1}if(b){const o=s.getApiKeyForTool("claude-desktop");o?await W("claude-desktop",o,{...K,oneMillion:void 0,takeOver:!0})?await t(["claude-desktop"],{apps:{install:!1}}):process.exitCode=1:(P(l.t("setup.desktop_official_login_missing_key")),process.exitCode=1)}return}if(!w)return P(l.t("setup.usage")),void(process.exitCode=1);const T=v();T||await i(p||f[0].apiKey);const $=[],O=[];let S,z=0,X=0;const Z=new Set,oo=f.map(o=>({tool:o.tool,label:`--${o.option}`,apiKey:o.apiKey,need:o.need}));for(const o of oo){if(!await H(o.label,o.apiKey)){X+=1;continue}const e=await F(o.apiKey);!e.probed||L(e,o.need)?(e.probed||q(l.t("setup.probe_failed",{label:o.label})),$.push({tool:o.tool,apiKey:o.apiKey,dedicated:!0}),Z.add(o.tool)):(P(l.t(`setup.key_no_${o.need}`,{label:o.label,tool:n[o.tool].displayName})),X+=1)}const eo=!!p&&await H("--key",p);p&&!eo&&(S=_[Y??"operation"]);const to=p&&eo?await F(p):void 0;if(p&&to&&!to.probed&&q(l.t("setup.probe_failed",{label:"--key"})),!(p&&to&&to.probed)||to.hasClaude||to.hasGpt||to.hasGrok||to.hasGemini||(P(l.t("setup.key_no_family")),S=1),p&&to&&void 0===S){const o=to.hasClaude||to.hasGpt||to.hasGrok||to.hasGemini,e=[{tool:"claude-code",capable:to.hasClaude,skipMsg:l.t(V()?"setup.skip_no_claude_desktop":"setup.skip_no_claude")},{tool:"codex",capable:to.hasGpt,skipMsg:l.t("setup.skip_no_gpt")},{tool:"grok",capable:to.hasGrok,skipMsg:l.t("setup.skip_no_grok")},{tool:"claude-desktop",capable:to.hasClaude&&V(),skipMsg:"",quiet:!0},{tool:"agy",capable:to.hasGemini,skipMsg:l.t("setup.skip_no_gemini")},{tool:"codebuddy",capable:o&&a.isToolInstalled("codebuddy"),skipMsg:"",quiet:!0},{tool:"workbuddy",capable:o&&a.isToolInstalled("workbuddy"),skipMsg:"",quiet:!0}];for(const o of e)Z.has(o.tool)||(o.capable?($.push({tool:o.tool,apiKey:p,dedicated:!1}),Z.add(o.tool)):o.quiet||q(o.skipMsg))}const io=Boolean(p&&eo&&void 0===S);if(T)return Q($.filter(o=>!U(o.tool)).map(o=>o.tool),$.length>0,$.filter(o=>U(o.tool)).map(o=>o.tool)),void((X>0||void 0!==S)&&(process.exitCode=S??_[Y??"operation"]));const lo=$.filter(o=>!U(o.tool)),so=io||$.some(o=>o.dedicated),ao=!r.fromInstaller&&M();if(($.length>0||so)&&!r.fromInstaller&&!await I(lo.map(o=>o.tool),{keyFile:so?G(s.getConfigDir(),"config.yaml"):void 0,installFirst:$.filter(o=>U(o.tool)).map(o=>o.tool)}))return void(process.exitCode=_.cancelled);io&&p&&s.setApiKey(p);for(const o of $)o.dedicated&&s.setToolApiKey(o.tool,o.apiKey),U(o.tool)?O.push({tool:o.tool,apiKey:o.apiKey}):await W(o.tool,o.apiKey,{...K,takeOver:o.dedicated||ao})?z+=1:(X+=1,Z.delete(o.tool));if(void 0!==S)return O.length>0&&J(O.map(o=>o.tool)),void(process.exitCode=S);let no=[];if(O.length>0){const e=await async function(e,t,i){const s=e.map(o=>o.tool);if(0===s.length)return{still:[],applied:[],failed:[]};const r=s.map(o=>n[o].displayName).join(l.t("setup.list_separator"));let p=t;if(void 0!==p||x()||(j()?p=!C():process.stdin.isTTY&&(console.log(""),p=(await N.prompt([{type:"confirm",name:"go",message:l.t("setup.install_confirm",{tools:r}),default:!0}])).go)),!p){console.log("");for(const e of s)console.log(o.yellow("! "+l.t("setup.install_hint",{tool:n[e].displayName,install:n[e].installCommand})));return x()||console.log(o.gray(l.t("setup.install_all_hint",{cli:B}))),{still:s,applied:[],failed:[]}}const d=[];for(const e of s){console.log(o.bold(`\n${n[e].displayName}`));try{await a.installTool(e)}catch(o){E.logError(`setup: install ${e}`,o)}A(),a.isToolInstalled(e)||d.push(e)}const c=s.filter(o=>!d.includes(o));c.length>0&&console.log("");const u=[],f=[];for(const{tool:o,apiKey:t}of e.filter(o=>c.includes(o.tool)))await W(o,t,i)?u.push(o):f.push(o);return{still:d,applied:u,failed:f}}(O,r.install,K);no=e.still,z+=e.applied.length,X+=e.failed.length;for(const o of[...no,...e.failed])Z.delete(o)}if(z>0){const t=[...Z].filter(o=>!e(o)?.isInstalled&&!no.includes(o)),i=t.map(o=>n[o]?.command).filter(Boolean).join(" / "),s=l.t("setup.done",{count:String(z)});R("\n"+(i?`${s}${l.t("setup.done_commands",{commands:i})}`:s)),no.length>0&&J(no);for(const o of t){const e=a.ensureNativeOnPath(o);e&&R(l.t("setup.path_added",{tool:n[o].displayName,dir:e}))}const r=t.filter(o=>!a.isOnPath(o));if(r.length>0&&!x()&&"1"!==D("PATH_HINT_BY_CALLER")){const e=r.map(o=>n[o].command).join(" / ");console.log(o.yellow(" ! "+l.t("win32"===process.platform?"setup.path_reload_windows":"setup.path_reload",{commands:e})))}}0===z&&no.length>0&&J(no),X>0&&(P(l.t("setup.failed_summary",{count:String(X)})),x()||console.error(`${B} setup --key ${l.t("errors.key_placeholder")}`)),await t([...Z],{apps:{install:await installMissingApps([...Z],r.install)}}),(X>0||0===z&&0===no.length)&&(process.exitCode=_[Y??"operation"])}
@@ -116,6 +116,20 @@
116
116
  "check": ["agy", "--version"],
117
117
  "requires": []
118
118
  },
119
+ {
120
+ "id": "codebuddy",
121
+ "name": "CodeBuddy Code",
122
+ "category": "cli",
123
+ "aliases": ["codebuddy-code"],
124
+ "platforms": ["darwin", "linux", "win32"],
125
+ "adapter": "codebuddy",
126
+ "latest": { "type": "npm", "package": "@tencent-ai/codebuddy-code" },
127
+ "sources": { "all": "npmmirror 的 @tencent-ai/codebuddy-code(与 npmjs 同一份)" },
128
+ "verify": { "checksum": "npm sha512", "signature": "—" },
129
+ "install": { "type": "adapter" },
130
+ "check": ["codebuddy", "--version"],
131
+ "requires": ["node"]
132
+ },
119
133
  {
120
134
  "id": "claude-desktop",
121
135
  "name": "Claude Desktop",
@@ -1 +1 @@
1
- import{KEY_INFO_PATH as r}from"./gateway-protocol.js";import{logger as e}from"../utils/logger.js";import{configManager as t}from"./config.js";import{i18n as o}from"./i18n.js";import{rememberPublishedAddresses as a}from"./gateway-addresses.js";import{eligibleLists as n}from"./client-config.js";import{track as s}from"./telemetry.js";import{refreshClientConfig as i}from"./client-config-sync.js";const l=r=>new Promise(e=>setTimeout(e,r));async function c(r,e,a){const n=`${t.getBaseUrl()}/v1/models`,s=new AbortController,i=setTimeout(()=>s.abort(),e);try{const e=await a(n,{method:"GET",headers:{Authorization:`Bearer ${r}`,"Content-Type":"application/json"},signal:s.signal});if(401===e.status)return{valid:!1,error:"invalid_api_key",message:o.t("validator.rejected")};if(e.ok){try{const r=await e.json();if(r&&"list"===r.object)return{valid:!0}}catch{return{valid:!0}}return{valid:!0}}return{valid:!1,error:"unknown_error",message:`HTTP ${e.status}: ${e.statusText}`}}catch(r){return r instanceof Error&&"AbortError"===r.name?{valid:!1,error:"network_error",message:o.t("validator.timeout")}:function(r){const e=r?.cause?.code;return"string"==typeof e&&u.has(e)}(r)?{valid:!1,error:"network_error",message:o.t("messages.certificate_intercepted",{url:n})}:{valid:!1,error:"network_error",message:r instanceof Error?r.message:o.t("validator.network")}}finally{clearTimeout(i)}}const u=new Set(["DEPTH_ZERO_SELF_SIGNED_CERT","SELF_SIGNED_CERT_IN_CHAIN","UNABLE_TO_VERIFY_LEAF_SIGNATURE","UNABLE_TO_GET_ISSUER_CERT_LOCALLY","CERT_UNTRUSTED","ERR_TLS_CERT_ALTNAME_INVALID"]);export async function fetchModels(r,o={}){const{timeoutMs:a=3e4,fetchFn:n=fetch}=o,s=`${t.getBaseUrl()}/v1/models`,i=new AbortController,l=setTimeout(()=>i.abort(),a);try{const e=await n(s,{method:"GET",headers:{Authorization:`Bearer ${r}`,"Content-Type":"application/json"},signal:i.signal});if(!e.ok)return{ok:!1,models:[],error:`HTTP ${e.status}`};const t=await e.json();return{ok:!0,models:(Array.isArray(t?.data)?t.data:[]).map(r=>"string"==typeof r?r:r?.id).filter(r=>"string"==typeof r&&r.trim().length>0).map(r=>r.trim())}}catch(r){return e.logError("fetchModels",r),{ok:!1,models:[],error:r instanceof Error?r.message:"network error"}}finally{clearTimeout(l)}}function f(r){return r.filter(r=>!!r&&"object"==typeof r&&"string"==typeof r.name).map(r=>({name:r.name.trim(),..."string"==typeof r.labelOverride?{labelOverride:r.labelOverride}:{},..."boolean"==typeof r.supports1m?{supports1m:r.supports1m}:{}})).filter(r=>r.name.length>0)}export async function fetchGatewayStatus(r={}){const{timeoutMs:o=15e3,fetchFn:n=fetch}=r,s=`${t.getBaseUrl()}/api/status`,i=new AbortController,l=setTimeout(()=>i.abort(),o);try{const r=await n(s,{method:"GET",signal:i.signal});if(!r.ok)return{ok:!1,claudeDesktopGroupModels:{},error:`HTTP ${r.status}`};const e=await r.json();a(e?.data,t.getBaseUrl());let o=e?.data?.claude_desktop_group_models;if("string"==typeof o)try{o=JSON.parse(o)}catch{o=void 0}const l={};if(o&&"object"==typeof o&&!Array.isArray(o))for(const[r,e]of Object.entries(o))Array.isArray(e)&&(l[r]=f(e));return{ok:!0,claudeDesktopGroupModels:l}}catch(r){return e.logError("fetchGatewayStatus",r),{ok:!1,claudeDesktopGroupModels:{},error:r instanceof Error?r.message:"network error"}}finally{clearTimeout(l)}}export async function fetchKeyGroupInfo(o,a={}){const{timeoutMs:n=1e4,fetchFn:s=fetch}=a,i=`${t.getBaseUrl()}${r}`,l=new AbortController,c=setTimeout(()=>l.abort(),n);try{const r=await s(i,{method:"GET",headers:{Authorization:`Bearer ${o}`},signal:l.signal});if(!r.ok)return null;const e=await r.json(),t=e?.data;if(!t||"string"!=typeof t.group||!Array.isArray(t.claude_desktop_models))return null;const a=Array.isArray(t.groups)?t.groups.filter(r=>"string"==typeof r&&!!r):[];return{group:t.group,groups:a.length>0?a:[t.group],claudeDesktopModels:f(t.claude_desktop_models)}}catch(r){return e.logError("fetchKeyGroupInfo",r),null}finally{clearTimeout(c)}}export async function fetchClientModelConfig(r={}){const e=await i(r);return e.config?n(e.config.models):null}export async function validateApiKey(r,t={}){const a=Date.now(),n=await async function(r,t){const{timeoutMs:a=3e4,retries:n=2,backoffMs:s=500,fetchFn:i=fetch,sleepFn:u=l}=t;let f={valid:!1,error:"network_error",message:o.t("validator.network")};for(let t=0;t<=n;t++){const o=await c(r,a,i);if(o.valid||"invalid_api_key"===o.error)return o.valid||e.logError("validateApiKey",new Error(o.message||"invalid_api_key")),o;f=o,t<n&&await u(s*Math.pow(2,t))}return e.logError("validateApiKey",new Error(f.message||"network_error")),f}(r,t);return s("validate-key",n.valid?"ok":"fail",{duration_ms:Date.now()-a,...n.valid?{}:{error:n.message??n.error,detail:{reason:n.error}}}),n}
1
+ import{KEY_INFO_PATH as r}from"./gateway-protocol.js";import{logger as e}from"../utils/logger.js";import{configManager as t}from"./config.js";import{i18n as o}from"./i18n.js";import{rememberPublishedAddresses as a}from"./gateway-addresses.js";import{eligibleLists as n}from"./client-config.js";import{track as s}from"./telemetry.js";import{refreshClientConfig as i}from"./client-config-sync.js";const l=r=>new Promise(e=>setTimeout(e,r));async function c(r,e,a){const n=`${t.getBaseUrl()}/v1/models`,s=new AbortController,i=setTimeout(()=>s.abort(),e);try{const e=await a(n,{method:"GET",headers:{Authorization:`Bearer ${r}`,"Content-Type":"application/json"},signal:s.signal});if(401===e.status)return{valid:!1,error:"invalid_api_key",message:o.t("validator.rejected")};if(e.ok){try{const r=await e.json();if(r&&"list"===r.object)return{valid:!0}}catch{return{valid:!0}}return{valid:!0}}return{valid:!1,error:"unknown_error",message:`HTTP ${e.status}: ${e.statusText}`}}catch(r){return r instanceof Error&&"AbortError"===r.name?{valid:!1,error:"network_error",message:o.t("validator.timeout")}:function(r){const e=r?.cause?.code;return"string"==typeof e&&u.has(e)}(r)?{valid:!1,error:"network_error",message:o.t("messages.certificate_intercepted",{url:n})}:{valid:!1,error:"network_error",message:r instanceof Error?r.message:o.t("validator.network")}}finally{clearTimeout(i)}}const u=new Set(["DEPTH_ZERO_SELF_SIGNED_CERT","SELF_SIGNED_CERT_IN_CHAIN","UNABLE_TO_VERIFY_LEAF_SIGNATURE","UNABLE_TO_GET_ISSUER_CERT_LOCALLY","CERT_UNTRUSTED","ERR_TLS_CERT_ALTNAME_INVALID"]);export async function fetchModels(r,o={}){const{timeoutMs:a=3e4,fetchFn:n=fetch}=o,s=`${t.getBaseUrl()}/v1/models`,i=new AbortController,l=setTimeout(()=>i.abort(),a);try{const e=await n(s,{method:"GET",headers:{Authorization:`Bearer ${r}`,"Content-Type":"application/json"},signal:i.signal});if(!e.ok)return{ok:!1,models:[],error:`HTTP ${e.status}`};const t=await e.json();return{ok:!0,models:(Array.isArray(t?.data)?t.data:[]).map(r=>"string"==typeof r?r:r?.id).filter(r=>"string"==typeof r&&r.trim().length>0).map(r=>r.trim())}}catch(r){return e.logError("fetchModels",r),{ok:!1,models:[],error:r instanceof Error?r.message:"network error"}}finally{clearTimeout(l)}}function f(r){return r.filter(r=>!!r&&"object"==typeof r&&"string"==typeof r.name).map(r=>({name:r.name.trim(),..."string"==typeof r.labelOverride?{labelOverride:r.labelOverride}:{},..."boolean"==typeof r.supports1m?{supports1m:r.supports1m}:{}})).filter(r=>r.name.length>0)}export async function fetchGatewayStatus(r={}){const{timeoutMs:o=15e3,fetchFn:n=fetch}=r,s=`${t.getBaseUrl()}/api/status`,i=new AbortController,l=setTimeout(()=>i.abort(),o);try{const r=await n(s,{method:"GET",signal:i.signal});if(!r.ok)return{ok:!1,claudeDesktopGroupModels:{},error:`HTTP ${r.status}`};const e=await r.json();a(e?.data,t.getBaseUrl());let o=e?.data?.claude_desktop_group_models;if("string"==typeof o)try{o=JSON.parse(o)}catch{o=void 0}const l={};if(o&&"object"==typeof o&&!Array.isArray(o))for(const[r,e]of Object.entries(o))Array.isArray(e)&&(l[r]=f(e));return{ok:!0,claudeDesktopGroupModels:l}}catch(r){return e.logError("fetchGatewayStatus",r),{ok:!1,claudeDesktopGroupModels:{},error:r instanceof Error?r.message:"network error"}}finally{clearTimeout(l)}}export async function fetchKeyGroupInfo(o,a={}){const{timeoutMs:n=1e4,fetchFn:s=fetch}=a,i=`${t.getBaseUrl()}${r}`,l=new AbortController,c=setTimeout(()=>l.abort(),n);try{const r=await s(i,{method:"GET",headers:{Authorization:`Bearer ${o}`},signal:l.signal});if(!r.ok)return null;const e=await r.json(),t=e?.data;if(!t||"string"!=typeof t.group||!Array.isArray(t.claude_desktop_models))return null;const a=Array.isArray(t.groups)?t.groups.filter(r=>"string"==typeof r&&!!r):[];return{group:t.group,groups:a.length>0?a:[t.group],claudeDesktopModels:f(t.claude_desktop_models)}}catch(r){return e.logError("fetchKeyGroupInfo",r),null}finally{clearTimeout(c)}}export async function fetchClientModelConfig(r={}){const e=await i(r);if(!e.config)return null;const{personal:t}=e.config;return{models:n(e.config.models),...t?{personal:t}:{}}}export async function validateApiKey(r,t={}){const a=Date.now(),n=await async function(r,t){const{timeoutMs:a=3e4,retries:n=2,backoffMs:s=500,fetchFn:i=fetch,sleepFn:u=l}=t;let f={valid:!1,error:"network_error",message:o.t("validator.network")};for(let t=0;t<=n;t++){const o=await c(r,a,i);if(o.valid||"invalid_api_key"===o.error)return o.valid||e.logError("validateApiKey",new Error(o.message||"invalid_api_key")),o;f=o,t<n&&await u(s*Math.pow(2,t))}return e.logError("validateApiKey",new Error(f.message||"network_error")),f}(r,t);return s("validate-key",n.valid?"ok":"fail",{duration_ms:Date.now()-a,...n.valid?{}:{error:n.message??n.error,detail:{reason:n.error}}}),n}
@@ -1 +1 @@
1
- import{CLIENT_CONFIG_PATH as e}from"./gateway-protocol.js";import{logger as t}from"../utils/logger.js";import{bundledClientConfig as o,parseClientConfig as n,readCachedClientConfig as r,setClientConfigSiteResolver as i,writeCachedClientConfig as c}from"./client-config.js";import{configManager as f}from"./config.js";import{getBuiltinGatewayAddresses as s,reloadRegistry as l}from"./model-registry.js";import{brandEnv as g,brand as a}from"./brand.js";export const CLIENT_CONFIG_TTL_MS=3e5;function u(e){try{return new URL(e).origin}catch{return e.replace(/\/+$/,"")}}export function clientConfigSite(e=f.getBaseUrl()){const t=u(e);return s().some(e=>u(e.url)===t)?a().id:t}i(()=>clientConfigSite());let d=null;export function lastClientConfigStatus(){return d}function m(e){const t=r();if(t&&t.site===clientConfigSite())return{config:t.config,source:"cache",revision:t.config.revision,fetchedAt:t.fetchedAt,problem:e};const n=o();return n?{config:n,source:"bundled",revision:n.revision,problem:e}:{config:null,source:null,problem:e}}export async function refreshClientConfig(i={}){const{force:s=!1,timeoutMs:u=8e3,fetchFn:h=fetch,now:p=Date.now()}=i;if("1"===g("DISABLE_CLIENT_CONFIG_FETCH"))return d=m(),d;const C=clientConfigSite(),v=r(),w=v&&v.site===C?v:null;if(!s&&w&&p-w.fetchedAt<3e5)return d={config:w.config,source:"cache",revision:w.config.revision,fetchedAt:w.fetchedAt},d;const A=w?.config??(C===a().id?o():null),T=new AbortController,b=setTimeout(()=>T.abort(),u);try{const o={};w?.etag&&(o["If-None-Match"]=w.etag);const r=await h(`${f.getBaseUrl()}${e}`,{method:"GET",headers:o,signal:T.signal});if(304===r.status&&w)return c({...w,fetchedAt:p}),d={config:w.config,source:"cloud",revision:w.config.revision,fetchedAt:p},d;if(!r.ok)return d=m(`HTTP ${r.status}`),d;const i=await r.json(),{config:s,problem:g}=n(i?.data,A);if(!s)return t.warn(`Gateway client config refused: ${g}`),d=m(`refused: ${g}`),d;g&&t.warn(`Gateway client config: ${g}`);const a=r.headers.get("etag")??void 0;return c({site:C,fetchedAt:p,config:s,...a?{etag:a}:{}}),l(),d={config:s,source:"cloud",revision:s.revision,fetchedAt:p,...g?{problem:g}:{}},d}catch(e){return t.logError("refreshClientConfig",e),d=m(e instanceof Error?e.message:String(e)),d}finally{clearTimeout(b)}}
1
+ import{createHash as e}from"node:crypto";import{CLIENT_CONFIG_PATH as t}from"./gateway-protocol.js";import{logger as o}from"../utils/logger.js";import{bundledClientConfig as n,parseClientConfig as i,readCachedClientConfig as r,setClientConfigSiteResolver as c,writeCachedClientConfig as s}from"./client-config.js";import{configManager as f}from"./config.js";import{getBuiltinGatewayAddresses as a,reloadRegistry as l}from"./model-registry.js";import{brandEnv as u,brand as g}from"./brand.js";export const CLIENT_CONFIG_TTL_MS=3e5;function d(e){try{return new URL(e).origin}catch{return e.replace(/\/+$/,"")}}export function clientConfigSite(e=f.getBaseUrl()){const t=d(e);return a().some(e=>d(e.url)===t)?g().id:t}c(()=>clientConfigSite());let h=null;export function lastClientConfigStatus(){return h}function m(e){const t=r();if(t&&t.site===clientConfigSite())return{config:t.config,source:"cache",revision:t.config.revision,fetchedAt:t.fetchedAt,problem:e};const o=n();return o?{config:o,source:"bundled",revision:o.revision,problem:e}:{config:null,source:null,problem:e}}export async function refreshClientConfig(c={}){const{force:a=!1,timeoutMs:d=8e3,fetchFn:p=fetch,now:C=Date.now()}=c,y=c.apiKey??f.getApiKey(),A=function(t){return t?e("sha256").update(t).digest("hex").slice(0,16):void 0}(y);if("1"===u("DISABLE_CLIENT_CONFIG_FETCH"))return h=m(),h;const v=clientConfigSite(),w=r(),T=w&&w.site===v?w:null,b=T&&T.keyHash===A?T:null;if(!a&&b&&C-b.fetchedAt<3e5)return h={config:b.config,source:"cache",revision:b.config.revision,fetchedAt:b.fetchedAt},h;const S=T?.config??(v===g().id?n():null),$=new AbortController,j=setTimeout(()=>$.abort(),d);try{const e={};b?.etag&&(e["If-None-Match"]=b.etag),y&&(e.Authorization=`Bearer ${y}`);const n=await p(`${f.getBaseUrl()}${t}`,{method:"GET",headers:e,signal:$.signal});if(304===n.status&&b)return s({...b,fetchedAt:C}),h={config:b.config,source:"cloud",revision:b.config.revision,fetchedAt:C},h;if(!n.ok)return h=m(`HTTP ${n.status}`),h;const r=await n.json(),{config:c,problem:a}=i(r?.data,S);if(!c)return o.warn(`Gateway client config refused: ${a}`),h=m(`refused: ${a}`),h;a&&o.warn(`Gateway client config: ${a}`);const u=n.headers.get("etag")??void 0;return s({site:v,fetchedAt:C,config:c,...A?{keyHash:A}:{},...u?{etag:u}:{}}),l(),h={config:c,source:"cloud",revision:c.revision,fetchedAt:C,...a?{problem:a}:{}},h}catch(e){return o.logError("refreshClientConfig",e),h=m(e instanceof Error?e.message:String(e)),h}finally{clearTimeout(j)}}
@@ -1 +1 @@
1
- import{createHash as t,randomUUID as e}from"crypto";import{existsSync as n,mkdirSync as o,readFileSync as i,renameSync as r,writeFileSync as s}from"fs";import{homedir as l}from"os";import{dirname as c,join as f}from"path";import{fileURLToPath as a}from"url";import{CLIENT_SECTION as u,MIN_CLIENT_VERSION as d}from"./gateway-protocol.js";import{brand as m,brandEnv as p}from"./brand.js";export const CLIENT_CONFIG_SCHEMA=1;const h=new Set(["haiku","sonnet","opus","reasoning","fable"]),g=/^[A-Za-z0-9._:@/\-[\]]{1,200}$/,_=/^[a-z][a-z0-9-]{0,31}$/,b=/^\d+(\.\d+){0,3}$/,y=t=>!!t&&"object"==typeof t&&!Array.isArray(t),C=t=>"number"==typeof t&&Number.isFinite(t)&&t>0?Math.floor(t):void 0;function $(t){if(!y(t)||"string"!=typeof t.id||!t.id.trim())return null;const e={id:t.id.trim()};if(!0===t.hidden)return{...e,hidden:!0};"string"==typeof t.name&&t.name.trim()&&(e.name=t.name.trim()),"string"==typeof t.description&&t.description.trim()&&(e.description=t.description.trim());const n=C(t.context_window);n&&(e.contextWindow=n);const o=C(t.auto_compact_tokens);if(o&&(e.autoCompactTokens=o),y(t.clients)){const n={};for(const[e,o]of Object.entries(t.clients))_.test(e)&&"boolean"==typeof o&&(n[e]=o);Object.keys(n).length>0&&(e.clients=n)}const i=t[d];return"string"==typeof i&&b.test(i)&&(e.minClientVersion=i),"number"==typeof t.rollout_percent&&t.rollout_percent>=0&&t.rollout_percent<=100&&(e.rolloutPercent=t.rollout_percent),e}function k(t,e,n,o){if(void 0===t)return{};if(!y(t))throw new Error(`${u}.${o} must be an object`);const i={};for(const[r,s]of Object.entries(t)){if(!e.test(r)||"string"!=typeof s||!n(s))throw new Error(`${u}.${o}.${r} is invalid`);i[r]=s}return i}function v(t,e,{nonEmpty:n=!1}={}){if(void 0===t)return[];if(!Array.isArray(t)||t.some(t=>"string"!=typeof t||!g.test(t)))throw new Error(`${u}.${e} must be a list of model ids`);if(n&&0===t.length)throw new Error(`${u}.${e} must not be empty`);return[...t]}function w(t,e,n){if(void 0===t)return{};if(!y(t))throw new Error(`${u}.${e} must be an object`);const o={};for(const[i,r]of Object.entries(t)){if(!h.has(i))throw new Error(`${u}.${e}.${i} is not a tier slot`);o[i]=v(r,`${e}.${i}`,{nonEmpty:n})}return o}const j=t=>(t??[]).filter(t=>!t.hidden).length;export function parseClientConfig(t,e){if(!y(t))return{config:null,problem:"not an object"};if(1!==t.schema)return{config:null,problem:`unsupported schema ${String(t.schema)}`};if(!y(t.models))return{config:null,problem:"models is not an object"};const n={};for(const[e,o]of Object.entries(t.models)){if(!Array.isArray(o))return{config:null,problem:`models.${e} is not a list`};const t=o.map($);if(t.some(t=>null===t))return{config:null,problem:`models.${e} has a row without an id`};n[e]=t}let o,i;try{o=function(t){if(null==t)return;if(!y(t))throw new Error(`${u} must be an object`);const e={};if(void 0!==t.min_version){if("string"!=typeof t.min_version||t.min_version&&!b.test(t.min_version))throw new Error(`${u}.min_version is invalid`);t.min_version&&(e.minVersion=t.min_version)}const n=k(t.default_models,/^(haiku|sonnet|opus|reasoning|fable)$/,t=>g.test(t),"default_models");Object.keys(n).length&&(e.defaultModels=n);const o=w(t.retired_default_models,"retired_default_models",!1);Object.keys(o).length&&(e.retiredDefaultModels=o);const i=k(t.tool_defaults,_,t=>""===t||g.test(t),"tool_defaults");Object.keys(i).length&&(e.toolDefaults=i);const r=w(t.tier_chains,"tier_chains",!0);Object.keys(r).length&&(e.tierChains=r);const s=v(t.retired_models,"retired_models");s.length&&(e.retiredModels=s);const l=k(t.tool_min_versions,_,t=>""===t||b.test(t),"tool_min_versions");Object.keys(l).length&&(e.toolMinVersions=l);const c=v(t.agy_models,"agy_models");c.length&&(e.agyModels=c);const f=v(t.one_million_fallback,"one_million_fallback");return f.length&&(e.oneMillionFallback=f),!0===t.accept_shrink&&(e.acceptShrink=!0),e}(t[u])}catch(t){i=`${u} section dropped: ${t instanceof Error?t.message:String(t)}`}const r=t[u];if(e&&(!y(r)||!0!==r.accept_shrink))for(const[t,o]of Object.entries(e.models)){const e=j(o),i=j(n[t]);if(e>0&&0===i||e>=4&&2*i<e)return{config:null,problem:`models.${t} shrank from ${e} to ${i}`}}return{config:{schema:1,revision:"string"==typeof t.revision?t.revision:"",models:n,...o?{client:o}:{}},problem:i}}export function serializeClientConfig(t){const e=Object.fromEntries(Object.entries(t.models).map(([t,e])=>[t,e.map(t=>({id:t.id,...t.hidden?{hidden:!0}:{},...t.name?{name:t.name}:{},...t.description?{description:t.description}:{},...t.contextWindow?{context_window:t.contextWindow}:{},...t.autoCompactTokens?{auto_compact_tokens:t.autoCompactTokens}:{},...t.clients?{clients:t.clients}:{},...t.minClientVersion?{[d]:t.minClientVersion}:{},...void 0!==t.rolloutPercent?{rollout_percent:t.rolloutPercent}:{}}))])),n=t.client,o=n?{...n.minVersion?{min_version:n.minVersion}:{},...n.defaultModels?{default_models:n.defaultModels}:{},...n.retiredDefaultModels?{retired_default_models:n.retiredDefaultModels}:{},...n.toolDefaults?{tool_defaults:n.toolDefaults}:{},...n.tierChains?{tier_chains:n.tierChains}:{},...n.retiredModels?{retired_models:n.retiredModels}:{},...n.toolMinVersions?{tool_min_versions:n.toolMinVersions}:{},...n.agyModels?{agy_models:n.agyModels}:{},...n.oneMillionFallback?{one_million_fallback:n.oneMillionFallback}:{},...n.acceptShrink?{accept_shrink:!0}:{}}:void 0;return{schema:t.schema,revision:t.revision,models:e,...o?{[u]:o}:{}}}function O(){const t=p("CONFIG_DIR")?.trim();if(t)return t;const e=p("TEST_HOME")?.trim();return f(e||l(),m().configDirName)}export const cachePath=()=>f(O(),"client-config.json");function x(t,e){o(c(t),{recursive:!0});const n=`${t}.${process.pid}.tmp`;s(n,e,"utf-8"),r(n,t)}export function readCachedClientConfig(){try{if(!n(cachePath()))return null;const t=JSON.parse(i(cachePath(),"utf-8"));if("string"!=typeof t.site||"number"!=typeof t.fetchedAt)return null;const{config:e}=parseClientConfig(t.config);return e?{site:t.site,fetchedAt:t.fetchedAt,config:e,..."string"==typeof t.etag?{etag:t.etag}:{}}:null}catch{return null}}export function writeCachedClientConfig(t){x(cachePath(),JSON.stringify({site:t.site,etag:t.etag,fetchedAt:t.fetchedAt,config:serializeClientConfig(t.config)},null,2)+"\n")}let E;export function bundledClientConfig(){if("1"===p("NO_BUNDLED_CLIENT_CONFIG"))return null;if(void 0!==E)return E;E=null;const t=c(a(import.meta.url));for(const e of[f(t,"..","..","client-config.snapshot.json"),f(t,"..","client-config.snapshot.json")])try{if(!n(e))continue;E=parseClientConfig(JSON.parse(i(e,"utf-8"))).config;break}catch{}return E}let M=null;export function setClientConfigSiteResolver(t){M=t}export function currentClientConfig(){const t=readCachedClientConfig();let e=null;try{e=M?M():null}catch{e=null}if(t&&null!==e&&t.site===e)return{config:t.config,source:"cache",fetchedAt:t.fetchedAt};const n=bundledClientConfig();return n?{config:n,source:"bundled"}:null}let V=null,A=null;export function setClientIdentityForTests(t,e){V=t,A=e}export const clientVersion=()=>V??function(){try{const t=c(a(import.meta.url));for(const e of[f(t,"..","..","package.json"),f(t,"..","package.json")])if(n(e))return String(JSON.parse(i(e,"utf-8")).version??"0.0.0")}catch{}return"0.0.0"}();function S(t,e){const n=t.split(".").map(t=>parseInt(t,10)||0),o=e.split(".").map(t=>parseInt(t,10)||0);for(let t=0;t<Math.max(n.length,o.length);t++){const e=(n[t]??0)-(o[t]??0);if(e)return e}return 0}export function installId(){if(A)return A;const t=f(O(),"install-id");try{if(n(t)){const e=i(t,"utf-8").trim();if(e)return e}const o=e();return x(t,o+"\n"),o}catch{return"unknown"}}export function rolloutBucket(e){return t("sha256").update(`${installId()}:${e}`).digest().readUInt32BE(0)%100}export function isEligible(t){return!(t.minClientVersion&&S(clientVersion(),t.minClientVersion)<0||void 0!==t.rolloutPercent&&rolloutBucket(t.id)>=t.rolloutPercent)}export function eligibleLists(t){return Object.fromEntries(Object.entries(t).map(([t,e])=>[t,e.map(t=>t.hidden||isEligible(t)?t:{id:t.id,hidden:!0})]))}export function usableClientSection(t){const e=t?.client;if(e&&!(e.minVersion&&S(clientVersion(),e.minVersion)<0))return e}
1
+ import{createHash as t,randomUUID as e}from"crypto";import{existsSync as n,mkdirSync as o,readFileSync as i,renameSync as r,writeFileSync as s}from"fs";import{homedir as l}from"os";import{dirname as c,join as a}from"path";import{fileURLToPath as f}from"url";import{CLIENT_SECTION as u,MIN_CLIENT_VERSION as d}from"./gateway-protocol.js";import{brand as p,brandEnv as m}from"./brand.js";export const CLIENT_CONFIG_SCHEMA=1;const g=new Set(["haiku","sonnet","opus","reasoning","fable"]),h=/^[A-Za-z0-9._:@/\-[\]]{1,200}$/,y=/^[a-z][a-z0-9-]{0,31}$/,_=/^\d+(\.\d+){0,3}$/,b=t=>!!t&&"object"==typeof t&&!Array.isArray(t),C=t=>"number"==typeof t&&Number.isFinite(t)&&t>0?Math.floor(t):void 0,k=/^[A-Za-z0-9._-]{1,64}$/,v=t=>{if(!Array.isArray(t))return;const e=t.filter(t=>"string"==typeof t&&k.test(t));return e.length>0?e:void 0};function E(t){if(!b(t)||"string"!=typeof t.id||!t.id.trim())return null;const e={id:t.id.trim()};if(!0===t.hidden)return{...e,hidden:!0};"string"==typeof t.name&&t.name.trim()&&(e.name=t.name.trim()),"string"==typeof t.description&&t.description.trim()&&(e.description=t.description.trim()),!0===t.recommended&&(e.recommended=!0);const n=C(t.context_window);n&&(e.contextWindow=n);const o=C(t.max_output_tokens);o&&(e.maxOutputTokens=o);const i=C(t.auto_compact_tokens);i&&(e.autoCompactTokens=i);const r=function(t){if(!b(t))return;const e={};"boolean"==typeof t.functionCall&&(e.toolCall=t.functionCall),"boolean"==typeof t.vision&&(e.vision=t.vision),"boolean"==typeof t.reasoning&&(e.reasoning=t.reasoning);const n=C(t.contextWindowTokens);n&&(e.contextWindow=n);const o=C(t.maxOutput);o&&(e.maxOutput=o);const i=v(t.reasoningEfforts);i&&(e.reasoningEfforts=i),"string"==typeof t.defaultReasoningEffort&&k.test(t.defaultReasoningEffort)&&(e.defaultReasoningEffort=t.defaultReasoningEffort);const r=v(t.functionCallEndpoints);return r&&(e.toolCallEndpoints=r),Object.keys(e).length>0?e:void 0}(t.capabilities);r&&(e.capabilities=r);const s=v(t.endpoint_types);if(s&&(e.endpointTypes=s),b(t.clients)){const n={};for(const[e,o]of Object.entries(t.clients))y.test(e)&&"boolean"==typeof o&&(n[e]=o);Object.keys(n).length>0&&(e.clients=n)}const l=t[d];return"string"==typeof l&&_.test(l)&&(e.minClientVersion=l),"number"==typeof t.rollout_percent&&t.rollout_percent>=0&&t.rollout_percent<=100&&(e.rolloutPercent=t.rollout_percent),e}function x(t,e,n,o){if(void 0===t)return{};if(!b(t))throw new Error(`${u}.${o} must be an object`);const i={};for(const[r,s]of Object.entries(t)){if(!e.test(r)||"string"!=typeof s||!n(s))throw new Error(`${u}.${o}.${r} is invalid`);i[r]=s}return i}function $(t,e,{nonEmpty:n=!1}={}){if(void 0===t)return[];if(!Array.isArray(t)||t.some(t=>"string"!=typeof t||!h.test(t)))throw new Error(`${u}.${e} must be a list of model ids`);if(n&&0===t.length)throw new Error(`${u}.${e} must not be empty`);return[...t]}function w(t,e,n){if(void 0===t)return{};if(!b(t))throw new Error(`${u}.${e} must be an object`);const o={};for(const[i,r]of Object.entries(t)){if(!g.has(i))throw new Error(`${u}.${e}.${i} is not a tier slot`);o[i]=$(r,`${e}.${i}`,{nonEmpty:n})}return o}const O=t=>(t??[]).filter(t=>!t.hidden).length;export function parseClientConfig(t,e){if(!b(t))return{config:null,problem:"not an object"};if(1!==t.schema)return{config:null,problem:`unsupported schema ${String(t.schema)}`};if(!b(t.models))return{config:null,problem:"models is not an object"};const n={};for(const[e,o]of Object.entries(t.models)){if(!Array.isArray(o))return{config:null,problem:`models.${e} is not a list`};const t=o.map(E);if(t.some(t=>null===t))return{config:null,problem:`models.${e} has a row without an id`};n[e]=t}let o,i;try{o=function(t){if(null==t)return;if(!b(t))throw new Error(`${u} must be an object`);const e={};if(void 0!==t.min_version){if("string"!=typeof t.min_version||t.min_version&&!_.test(t.min_version))throw new Error(`${u}.min_version is invalid`);t.min_version&&(e.minVersion=t.min_version)}const n=x(t.default_models,/^(haiku|sonnet|opus|reasoning|fable)$/,t=>h.test(t),"default_models");Object.keys(n).length&&(e.defaultModels=n);const o=w(t.retired_default_models,"retired_default_models",!1);Object.keys(o).length&&(e.retiredDefaultModels=o);const i=x(t.tool_defaults,y,t=>""===t||h.test(t),"tool_defaults");Object.keys(i).length&&(e.toolDefaults=i);const r=w(t.tier_chains,"tier_chains",!0);Object.keys(r).length&&(e.tierChains=r);const s=$(t.retired_models,"retired_models");s.length&&(e.retiredModels=s);const l=x(t.tool_min_versions,y,t=>""===t||_.test(t),"tool_min_versions");Object.keys(l).length&&(e.toolMinVersions=l);const c=$(t.agy_models,"agy_models");c.length&&(e.agyModels=c);const a=$(t.one_million_fallback,"one_million_fallback");return a.length&&(e.oneMillionFallback=a),!0===t.accept_shrink&&(e.acceptShrink=!0),e}(t[u])}catch(t){i=`${u} section dropped: ${t instanceof Error?t.message:String(t)}`}const r=b(t.personal)&&Array.isArray(t.personal.lists)?t.personal.lists.filter(t=>"string"==typeof t&&Array.isArray(n[t])):[],s=t[u];if(e&&(!b(s)||!0!==s.accept_shrink))for(const[t,o]of Object.entries(e.models)){if(r.includes(t))continue;const e=O(o),i=O(n[t]);if(e>0&&0===i||e>=4&&2*i<e)return{config:null,problem:`models.${t} shrank from ${e} to ${i}`}}return{config:{schema:1,revision:"string"==typeof t.revision?t.revision:"",models:n,...o?{client:o}:{},...r.length?{personal:r}:{}},problem:i}}export function serializeClientConfig(t){const e=Object.fromEntries(Object.entries(t.models).map(([t,e])=>[t,e.map(t=>{return{id:t.id,...t.hidden?{hidden:!0}:{},...t.recommended?{recommended:!0}:{},...t.name?{name:t.name}:{},...t.description?{description:t.description}:{},...t.contextWindow?{context_window:t.contextWindow}:{},...t.maxOutputTokens?{max_output_tokens:t.maxOutputTokens}:{},...t.autoCompactTokens?{auto_compact_tokens:t.autoCompactTokens}:{},...t.capabilities?{capabilities:(e=t.capabilities,{...void 0!==e.toolCall?{functionCall:e.toolCall}:{},...void 0!==e.vision?{vision:e.vision}:{},...void 0!==e.reasoning?{reasoning:e.reasoning}:{},...e.contextWindow?{contextWindowTokens:e.contextWindow}:{},...e.maxOutput?{maxOutput:e.maxOutput}:{},...e.reasoningEfforts?{reasoningEfforts:e.reasoningEfforts}:{},...e.defaultReasoningEffort?{defaultReasoningEffort:e.defaultReasoningEffort}:{},...e.toolCallEndpoints?{functionCallEndpoints:e.toolCallEndpoints}:{}})}:{},...t.endpointTypes?{endpoint_types:t.endpointTypes}:{},...t.clients?{clients:t.clients}:{},...t.minClientVersion?{[d]:t.minClientVersion}:{},...void 0!==t.rolloutPercent?{rollout_percent:t.rolloutPercent}:{}};var e})])),n=t.client,o=n?{...n.minVersion?{min_version:n.minVersion}:{},...n.defaultModels?{default_models:n.defaultModels}:{},...n.retiredDefaultModels?{retired_default_models:n.retiredDefaultModels}:{},...n.toolDefaults?{tool_defaults:n.toolDefaults}:{},...n.tierChains?{tier_chains:n.tierChains}:{},...n.retiredModels?{retired_models:n.retiredModels}:{},...n.toolMinVersions?{tool_min_versions:n.toolMinVersions}:{},...n.agyModels?{agy_models:n.agyModels}:{},...n.oneMillionFallback?{one_million_fallback:n.oneMillionFallback}:{},...n.acceptShrink?{accept_shrink:!0}:{}}:void 0;return{schema:t.schema,revision:t.revision,models:e,...o?{[u]:o}:{},...t.personal?{personal:{lists:t.personal}}:{}}}function j(){const t=m("CONFIG_DIR")?.trim();if(t)return t;const e=m("TEST_HOME")?.trim();return a(e||l(),p().configDirName)}export const cachePath=()=>a(j(),"client-config.json");function A(t,e){o(c(t),{recursive:!0});const n=`${t}.${process.pid}.tmp`;s(n,e,"utf-8"),r(n,t)}export function readCachedClientConfig(){try{if(!n(cachePath()))return null;const t=JSON.parse(i(cachePath(),"utf-8"));if("string"!=typeof t.site||"number"!=typeof t.fetchedAt)return null;const{config:e}=parseClientConfig(t.config);return e?{site:t.site,fetchedAt:t.fetchedAt,config:e,..."string"==typeof t.keyHash?{keyHash:t.keyHash}:{},..."string"==typeof t.etag?{etag:t.etag}:{}}:null}catch{return null}}export function writeCachedClientConfig(t){A(cachePath(),JSON.stringify({site:t.site,keyHash:t.keyHash,etag:t.etag,fetchedAt:t.fetchedAt,config:serializeClientConfig(t.config)},null,2)+"\n")}let M;export function bundledClientConfig(){if("1"===m("NO_BUNDLED_CLIENT_CONFIG"))return null;if(void 0!==M)return M;M=null;const t=c(f(import.meta.url));for(const e of[a(t,"..","..","client-config.snapshot.json"),a(t,"..","client-config.snapshot.json")])try{if(!n(e))continue;M=parseClientConfig(JSON.parse(i(e,"utf-8"))).config;break}catch{}return M}let T=null;export function setClientConfigSiteResolver(t){T=t}export function currentClientConfig(){const t=readCachedClientConfig();let e=null;try{e=T?T():null}catch{e=null}if(t&&null!==e&&t.site===e)return{config:t.config,source:"cache",fetchedAt:t.fetchedAt};const n=bundledClientConfig();return n?{config:n,source:"bundled"}:null}let V=null,S=null;export function setClientIdentityForTests(t,e){V=t,S=e}export const clientVersion=()=>V??function(){try{const t=c(f(import.meta.url));for(const e of[a(t,"..","..","package.json"),a(t,"..","package.json")])if(n(e))return String(JSON.parse(i(e,"utf-8")).version??"0.0.0")}catch{}return"0.0.0"}();function N(t,e){const n=t.split(".").map(t=>parseInt(t,10)||0),o=e.split(".").map(t=>parseInt(t,10)||0);for(let t=0;t<Math.max(n.length,o.length);t++){const e=(n[t]??0)-(o[t]??0);if(e)return e}return 0}export function installId(){if(S)return S;const t=a(j(),"install-id");try{if(n(t)){const e=i(t,"utf-8").trim();if(e)return e}const o=e();return A(t,o+"\n"),o}catch{return"unknown"}}export function rolloutBucket(e){return t("sha256").update(`${installId()}:${e}`).digest().readUInt32BE(0)%100}export function isEligible(t){return!(t.minClientVersion&&N(clientVersion(),t.minClientVersion)<0||void 0!==t.rolloutPercent&&rolloutBucket(t.id)>=t.rolloutPercent)}export function eligibleLists(t){return Object.fromEntries(Object.entries(t).map(([t,e])=>[t,e.map(t=>t.hidden||isEligible(t)?t:{id:t.id,hidden:!0})]))}export function usableClientSection(t){const e=t?.client;if(e&&!(e.minVersion&&N(clientVersion(),e.minVersion)<0))return e}
@@ -1 +1 @@
1
- import{getGatewayModelRules as e}from"./model-registry.js";export function autoCompactTokens(t,i){return i&&i>0?Math.min(i,t):Math.floor(t*e().autoCompactRatio)}export function gatewayModelSpecs(t,i){const o=e().models,n=o.filter(e=>function(e,t){return"codex"===e?!1!==t.codex:"grok"===e?"grok"===modelFamily(t.id):!t.id.startsWith("claude-")&&!1!==t.claudeCode}(t,e));if(!i)return n;const d=new Set(Object.values(i).flat().filter(e=>e.hidden).map(e=>e.id)),r=Object.fromEntries(Object.entries(i).map(([e,t])=>[e,t.filter(e=>!e.hidden)])),s=new Map;for(const e of Object.values(r).flat()){const i=e.clients?.[t];void 0===i||s.has(e.id)||s.set(e.id,i)}for(const[e,t]of s)t||d.add(e);const l=new Map(("claude-code"===t?o:n).map(e=>[e.id,e])),c=(r.gemini??[]).filter(e=>s.get(e.id)??!1!==o.find(t=>t.id===e.id)?.codex),a=("grok"===t?r.grok??[]:"codex"===t?[...r.codex??[],...c,...(r.claude??[]).filter(e=>e.id.startsWith("claude-")&&(s.get(e.id)??l.has(e.id)))]:function(e,t){return[...(e.codex??[]).filter(e=>"gpt"===modelFamily(e.id)),...e.gemini??[],...e.grok??[],...(e.claude??[]).filter(e=>!e.id.startsWith("claude-"))].filter(e=>e.clients?.["claude-code"]??t.get(e.id)?.claudeCode??!0)}(r,l)).filter(e=>!(e=>!1===s.get(e.id))(e));if(0===a.length)return n.filter(e=>!d.has(e.id));const u=new Set,f=[];for(const e of a){if(u.has(e.id))continue;u.add(e.id);const{clients:t,minClientVersion:i,rolloutPercent:o,...n}=e,d={...l.get(e.id),...n};void 0!==t?.codex&&(d.codex=t.codex),void 0!==t?.["claude-code"]&&(d.claudeCode=t["claude-code"]),f.push(d)}return function(e,t,i){const o=[...e];return t.forEach((e,n)=>{if(i.has(e.id)||o.some(t=>t.id===e.id))return;const d=modelFamily(e.id),r=new Set(t.slice(n+1).filter(e=>modelFamily(e.id)===d).map(e=>e.id));let s=o.findIndex(e=>r.has(e.id));if(s<0){s=o.length;for(let e=o.length-1;e>=0;e--)if(modelFamily(o[e].id)===d){s=e+1;break}}o.splice(s,0,e)}),o}(f,n,d)}const t={gpt:"GPT",gemini:"Gemini",glm:"GLM",deepseek:"DeepSeek",minimax:"MiniMax",qwen:"Qwen"};export function modelBlurb(e,t={}){const i=[];for(const o of(e??"").split("|")){const e=o.trim();e&&(/\d\s*万?\s*输出|output\D*\d|\d\D*output/i.test(e)||(/[\d百千]\s*万?\s*上下文|context\D*\d|\d\D*context/i.test(e)?t.millionContext&&!i.includes("百万上下文")&&i.unshift("百万上下文"):i.push(e)))}return t.millionContext&&!i.includes("百万上下文")&&i.unshift("百万上下文"),i.length>0?i.join(" | "):void 0}export function prettyModelName(e){const i=e.replace(/^([a-z]+)(\d)/i,"$1 $2").split(/[-_\s]+/).filter(Boolean),o=[];for(const e of i){const i=o[o.length-1];if(/^\d+$/.test(e)&&i&&/^\d+$/.test(i)&&e.length<=2&&!/^\d{8}$/.test(e)){o[o.length-1]=`${i}.${e}`;continue}const n=e.toLowerCase();o.push(t[n]??(/^[a-z]\d/i.test(e)?e.toUpperCase():e[0].toUpperCase()+e.slice(1)))}return o.join(" ")}export function vendorNames(e){return[...new Set(e.map(e=>prettyModelName(e).split(" ")[0]))]}export function modelFamily(e){const t=e.toLowerCase();return t.startsWith("claude-")?"claude":t.startsWith("gemini")?"gemini":t.startsWith("grok")?"grok":/^(gpt|o\d|codex)/.test(t)?"gpt":"other"}
1
+ import{getGatewayModelRules as e}from"./model-registry.js";export function autoCompactTokens(t,o){return o&&o>0?Math.min(o,t):Math.floor(t*e().autoCompactRatio)}export function gatewayModelSpecs(o,i,d=[]){const n=e().models,c=n.filter(e=>function(e,t){return"codebuddy"===e||("codex"===e?!1!==t.codex:"grok"===e?"grok"===modelFamily(t.id):!t.id.startsWith("claude-")&&!1!==t.claudeCode)}(o,e));if(!i)return c;const r=new Set(Object.values(i).flat().filter(e=>e.hidden).map(e=>e.id)),l=Object.fromEntries(Object.entries(i).map(([e,t])=>[e,t.filter(e=>!e.hidden)])),s=new Map;for(const e of Object.values(l).flat()){const t=e.clients?.[o];void 0===t||s.has(e.id)||s.set(e.id,t)}for(const[e,t]of s)t||r.add(e);const a=new Map(("claude-code"===o?n:c).map(e=>[e.id,e])),u=(l.gemini??[]).filter(e=>s.get(e.id)??!1!==n.find(t=>t.id===e.id)?.codex),f=("codebuddy"===o?[...l.claude??[],...l.codex??[],...l.gemini??[],...l.grok??[]]:"grok"===o?l.grok??[]:"codex"===o?[...l.codex??[],...u,...(l.claude??[]).filter(e=>e.id.startsWith("claude-")&&(s.get(e.id)??a.has(e.id)))]:function(e,t){return[...(e.codex??[]).filter(e=>"gpt"===modelFamily(e.id)),...e.gemini??[],...e.grok??[],...(e.claude??[]).filter(e=>!e.id.startsWith("claude-"))].filter(e=>e.clients?.["claude-code"]??t.get(e.id)?.claudeCode??!0)}(l,a)).filter(e=>!(e=>!1===s.get(e.id))(e));if(0===f.length)return c.filter(e=>!r.has(e.id));const m=new Set,g=[];for(const e of f){if(m.has(e.id))continue;m.add(e.id);const{clients:t,minClientVersion:o,rolloutPercent:i,...d}=e,n={...a.get(e.id),...d};void 0!==t?.codex&&(n.codex=t.codex),void 0!==t?.["claude-code"]&&(n.claudeCode=t["claude-code"]),g.push(n)}return t[o].some(e=>d.includes(e))?g:function(e,t,o){const i=[...e];return t.forEach((e,d)=>{if(o.has(e.id)||i.some(t=>t.id===e.id))return;const n=modelFamily(e.id),c=new Set(t.slice(d+1).filter(e=>modelFamily(e.id)===n).map(e=>e.id));let r=i.findIndex(e=>c.has(e.id));if(r<0){r=i.length;for(let e=i.length-1;e>=0;e--)if(modelFamily(i[e].id)===n){r=e+1;break}}i.splice(r,0,e)}),i}(g,c,r)}const t={grok:["grok"],codex:["codex","gemini","claude"],"claude-code":["codex","gemini","grok","claude"],codebuddy:["claude","codex","gemini","grok"]},o={gpt:"GPT",gemini:"Gemini",glm:"GLM",deepseek:"DeepSeek",minimax:"MiniMax",qwen:"Qwen"};export function modelBlurb(e,t={}){const o=[];for(const i of(e??"").split("|")){const e=i.trim();e&&(/\d\s*万?\s*输出|output\D*\d|\d\D*output/i.test(e)||(/[\d百千]\s*万?\s*上下文|context\D*\d|\d\D*context/i.test(e)?t.millionContext&&!o.includes("百万上下文")&&o.unshift("百万上下文"):o.push(e)))}return t.millionContext&&!o.includes("百万上下文")&&o.unshift("百万上下文"),o.length>0?o.join(" | "):void 0}export function prettyModelName(e){const t=e.replace(/^([a-z]+)(\d)/i,"$1 $2").split(/[-_\s]+/).filter(Boolean),i=[];for(const e of t){const t=i[i.length-1];if(/^\d+$/.test(e)&&t&&/^\d+$/.test(t)&&e.length<=2&&!/^\d{8}$/.test(e)){i[i.length-1]=`${t}.${e}`;continue}const d=e.toLowerCase();i.push(o[d]??(/^[a-z]\d/i.test(e)?e.toUpperCase():e[0].toUpperCase()+e.slice(1)))}return i.join(" ")}export function vendorNames(e){return[...new Set(e.map(e=>prettyModelName(e).split(" ")[0]))]}export function modelFamily(e){const t=e.toLowerCase();return t.startsWith("claude-")?"claude":t.startsWith("gemini")?"gemini":t.startsWith("grok")?"grok":/^(gpt|o\d|codex)/.test(t)?"gpt":"other"}
@@ -1 +1 @@
1
- import{logger as e}from"../utils/logger.js";import{fetchClientModelConfig as o,fetchKeyGroupInfo as l,fetchModels as t,fetchGatewayStatus as n}from"./api-validator.js";import{getClaudeDesktopRules as r}from"./model-registry.js";export function baseModelId(e){return e.replace(/\[[^\]]*\]$/,"").trim()}export function isClaudeModel(e){return/claude/i.test(baseModelId(e))}export function matchGroups(e,o){const l=new Set(e.map(baseModelId));if(0===l.size)return[];const t=[],n=[];for(const[e,r]of Object.entries(o)){const o=new Set(r.map(e=>baseModelId(e.name)).filter(isClaudeModel));[...l].every(e=>o.has(e))&&(o.size===l.size?t:n).push(e)}return t.length>0?t:n}export function resolveOneMillion(e,o,l){const t=r(),n=[...new Set(e.map(baseModelId))],s=new Set(e.filter(e=>/\[1m\]/i.test(e)).map(baseModelId)),a={};let i,d="fallback",c=[];if(l&&l.claudeDesktopModels.length>0){d="gateway",c=o?l.groups.filter(e=>e in o):l.groups;const e=new Map(l.claudeDesktopModels.map(e=>[baseModelId(e.name),e])),r=new Set(t.oneMillionFallback);i=new Set(n.filter(o=>{const l=e.get(o);return l?.labelOverride&&(a[o]=l.labelOverride),l?!0===l.supports1m:r.has(o)}))}else if(o&&(c=matchGroups(n,o)).length>0){d="gateway",i=new Set(n);for(const e of c){const l=new Map(o[e].map(e=>[baseModelId(e.name),e]));for(const e of n){const o=l.get(e);o?.labelOverride&&!a[e]&&(a[e]=o.labelOverride),!0!==o?.supports1m&&i.delete(e)}}}else{const e=new Set(t.oneMillionFallback);i=new Set(n.filter(o=>e.has(o)))}for(const e of s)i.add(e);for(const e of t.oneMillionExclusions)if(n.some(o=>o.startsWith(e.whenPrefixPresent)))for(const o of e.models)i.delete(o);return{oneMillion:[...i],labels:a,oneMillionSource:d,matchedGroups:c}}export async function resolveModelCatalog(r){try{const[e,s,a,i]=await Promise.all([t(r),n(),o(),l(r)]);if(!e.ok||0===e.models.length)return null;const d=[...new Set(e.models.map(e=>e.trim()).filter(Boolean))],c=d.filter(isClaudeModel);return{models:d,...resolveOneMillion(c,s.ok?s.claudeDesktopGroupModels:null,i),...a?{clientModels:a}:{}}}catch(o){return e.logError("resolveModelCatalog",o),null}}
1
+ import{logger as e}from"../utils/logger.js";import{fetchClientModelConfig as o,fetchKeyGroupInfo as l,fetchModels as t,fetchGatewayStatus as n}from"./api-validator.js";import{getClaudeDesktopRules as r}from"./model-registry.js";export function baseModelId(e){return e.replace(/\[[^\]]*\]$/,"").trim()}export function isClaudeModel(e){return/claude/i.test(baseModelId(e))}export function matchGroups(e,o){const l=new Set(e.map(baseModelId));if(0===l.size)return[];const t=[],n=[];for(const[e,r]of Object.entries(o)){const o=new Set(r.map(e=>baseModelId(e.name)).filter(isClaudeModel));[...l].every(e=>o.has(e))&&(o.size===l.size?t:n).push(e)}return t.length>0?t:n}export function resolveOneMillion(e,o,l){const t=r(),n=[...new Set(e.map(baseModelId))],s=new Set(e.filter(e=>/\[1m\]/i.test(e)).map(baseModelId)),a={};let i,d="fallback",c=[];if(l&&l.claudeDesktopModels.length>0){d="gateway",c=o?l.groups.filter(e=>e in o):l.groups;const e=new Map(l.claudeDesktopModels.map(e=>[baseModelId(e.name),e])),r=new Set(t.oneMillionFallback);i=new Set(n.filter(o=>{const l=e.get(o);return l?.labelOverride&&(a[o]=l.labelOverride),l?!0===l.supports1m:r.has(o)}))}else if(o&&(c=matchGroups(n,o)).length>0){d="gateway",i=new Set(n);for(const e of c){const l=new Map(o[e].map(e=>[baseModelId(e.name),e]));for(const e of n){const o=l.get(e);o?.labelOverride&&!a[e]&&(a[e]=o.labelOverride),!0!==o?.supports1m&&i.delete(e)}}}else{const e=new Set(t.oneMillionFallback);i=new Set(n.filter(o=>e.has(o)))}for(const e of s)i.add(e);for(const e of t.oneMillionExclusions)if(n.some(o=>o.startsWith(e.whenPrefixPresent)))for(const o of e.models)i.delete(o);return{oneMillion:[...i],labels:a,oneMillionSource:d,matchedGroups:c}}export async function resolveModelCatalog(r){try{const[e,s,a,i]=await Promise.all([t(r),n(),o({apiKey:r}),l(r)]);if(!e.ok||0===e.models.length)return null;const d=[...new Set(e.models.map(e=>e.trim()).filter(Boolean))],c=d.filter(isClaudeModel);return{models:d,...resolveOneMillion(c,s.ok?s.claudeDesktopGroupModels:null,i),...a?{clientModels:a.models}:{},...a?.personal?{clientPersonal:a.personal}:{}}}catch(o){return e.logError("resolveModelCatalog",o),null}}
@@ -1 +1 @@
1
- import{Command as e,Option as o}from"commander";import{readFileSync as s}from"fs";import{join as t,dirname as n}from"path";import{fileURLToPath as a}from"url";import{i18n as i}from"./i18n.js";import{wizard as r}from"./wizard.js";import{SUPPORTED_TOOLS as c}from"./tool-manager.js";import{DEFAULT_BASE_URL as l}from"./config.js";import{attachCommandHelp as p,helpConfiguration as m}from"./cli-help.js";import{langCommand as u,authCommand as d,doctorCommand as f,configCommand as g,statusCommand as x,refreshCommand as h}from"../commands/index.js";import{logsCommand as $}from"../commands/logs.js";import{completionCommand as y}from"../commands/completion.js";import{benchCommand as b}from"../commands/bench.js";import{updateCommand as k}from"../commands/update.js";import{upgradeCommand as _}from"../commands/upgrade.js";import{installCommand as w,listCommand as v}from"../commands/components.js";import{codexSessionsCommand as j}from"../commands/codex-sessions.js";import{sessionsExportCommand as O,sessionsListCommand as S,sessionsResumeCommand as A,sessionsShowCommand as E}from"../commands/sessions.js";import{setupCommand as G,DEDICATED_KEYS as z}from"../commands/setup.js";import{baseCommand as C}from"../commands/base.js";import{usageError as R}from"./errors.js";import{requireTerminal as B}from"./confirm.js";import{brand as I,brandEnv as L,CLI_NAME as N}from"./brand.js";const P=(I().gatewayAddresses[1]??I().gatewayAddresses[0]).url,T=(I().gatewayAddresses[2]??I().gatewayAddresses[0]).url;function U(e,o){return i.t(`help.${e}`,o)}function H(e,o){return{command:e,note:U(o)}}function K(e){const o=U(e);return o===`help.${e}`?"":o}function M(e,o=[]){return{when:K(`${e}.when`),prerequisites:K(`${e}.needs`).split("\n").filter(Boolean),alternatives:o.map(([e,o])=>H(e,o))}}function q(e){return e.helpCommand("help [command]",U("help_command"))}export function buildProgram(){const I=new e;I.name(`${N}`).summary(U("root.summary")).description(U("root.description")).configureHelp(m()).allowExcessArguments(!0).optionsGroup(U("group.global_options")).helpOption("-h, --help",U("global.help")).version(function(){try{const e=n(a(import.meta.url));return JSON.parse(s(t(e,"../../package.json"),"utf-8")).version}catch{return"1.0.0"}}(),"-v, --version",U("global.version")).option("--base <url>",U("global.base")).option("--non-interactive",U("global.non_interactive")).option("--json",U("global.json")).option("-y, --yes",U("global.yes")).option("--dry-run",U("global.dry_run")).option("--no-color",U("global.no_color")),I.configureOutput({writeErr:()=>{},outputError:()=>{}}),I.showSuggestionAfterError(),I.exitOverride(e=>{throw e}),I.commandsGroup(U("group.configure"));const K=I.command("setup").summary(U("setup.summary")).description(U("setup.description")).option("--key <key>",U("setup.opt.key"));for(const e of z){const s=new o(`--${e.option} <key>`,U(`setup.opt.${e.option}`));e.hidden&&s.hideHelp(),K.addOption(s)}K.option("--1m",U("setup.opt.one_m")).option("--no-1m",U("setup.opt.no_one_m")).option("--claude-official <on|off>",U("setup.opt.claude_official")).option("--desktop-registry <on|off>",U("setup.opt.desktop_registry")).option("--force",U("setup.opt.force")).option("--install",U("setup.opt.install")).option("--no-install",U("setup.opt.no_install")).option("--all",U("setup.opt.all")).action(async e=>{e.key||z.some(o=>e[o.option])||(e.key=L("SETUP_KEY")?.trim()||void 0,e.fromInstaller=Boolean(e.key));const o=Boolean(e.key||z.some(o=>e[o.option])),s=void 0!==e["1m"]||void 0!==e.claudeOfficial||void 0!==e.desktopRegistry,t=i.t("errors.key_placeholder");if(!o&&!s)throw R(i.t("setup.usage"),`${N} setup --key ${t}`,"missing_key");if(void 0!==e.claudeOfficial&&!["on","off"].includes(String(e.claudeOfficial).toLowerCase()))throw R(i.t("setup.claude_official_invalid",{value:String(e.claudeOfficial)}),`${N} setup --claude-official on|off`,"invalid_value");if(void 0!==e.desktopRegistry&&!["on","off"].includes(String(e.desktopRegistry).toLowerCase()))throw R(i.t("setup.desktop_registry_invalid",{value:String(e.desktopRegistry)}),`${N} setup --desktop-registry on|off`,"invalid_value");await G({key:e.key,...Object.fromEntries(z.map(o=>[o.option,e[o.option]])),all:e.all,oneMillion:e["1m"],claudeOfficial:e.claudeOfficial,desktopRegistry:e.desktopRegistry,force:e.force,install:e.install,fromInstaller:e.fromInstaller})}),p(K,{...M("setup",[[`${N} init`,"setup.alt.init"],[`${N} config <tool>`,"setup.alt.config"],[`${N} auth <key>`,"setup.alt.auth"]]),sections:[{title:U("setup.autodetect_title"),rows:[["Claude",U("setup.autodetect.claude")],["GPT",U("setup.autodetect.gpt")],["Grok",U("setup.autodetect.grok")],["Gemini",U("setup.autodetect.gemini")]]}],examples:[H(`${N} setup --key sk-xxx`,"setup.ex.key"),H(`${N} setup --install --key sk-xxx`,"setup.ex.install"),H(`${N} setup --claudekey sk-a --codexkey sk-b --agykey sk-g`,"setup.ex.split"),H(`${N} setup --force --key sk-xxx`,"setup.ex.force"),H(`${N} setup --base ${P} --key sk-xxx`,"setup.ex.base")]});const D=I.command("init").summary(U("init.summary")).description(U("init.description")).action(async()=>{B(),await r.runFirstTimeSetup()});p(D,{...M("init",[[`${N} setup --key <key>`,"init.alt.setup"],[`${N}`,"init.alt.menu"]]),examples:[H(`${N} init`,"init.ex.run"),H(`${N} init --base ${P}`,"init.ex.base"),H(`${N}`,"init.ex.menu")]});const F=I.command("auth").summary(U("auth.summary")).description(U("auth.description")).argument("[token]",U("auth.arg.token")).action(async e=>{const o=[];e&&o.push(e),await d(o)});q(F);const J=F.command("revoke").description(U("auth.revoke")).action(async()=>{await d(["revoke"])});p(J,{examples:[H(`${N} auth revoke`,"auth.ex.revoke_ask"),H(`${N} auth revoke --yes`,"auth.ex.revoke")]});const Y=F.command("reload <tool>").description(U("auth.reload")).action(async e=>{await d(["reload",e])});p(Y,{examples:[H(`${N} auth reload claude-code`,"auth.ex.reload"),H(`${N} auth reload claude-code --json`,"auth.ex.reload_json")]}),p(F,{...M("auth",[[`${N} setup --key <key>`,"auth.alt.setup"]]),examples:[H(`${N} auth`,"auth.ex.prompt"),H(`${N} auth sk-xxx --non-interactive`,"auth.ex.save"),H(`${N} auth revoke --yes`,"auth.ex.revoke"),H(`${N} auth reload claude-code`,"auth.ex.reload")]});const Q=I.command("config").summary(U("config.summary")).description(U("config.description")).argument("[args...]",U("config.arg.args")).option("-f, --force",U("config.opt.force")).allowUnknownOption(!0).action(async(e=[],o={})=>{await g(o.force?[...e,"--force"]:e)});p(Q,{...M("config",[[`${N} setup --force --key <key>`,"config.alt.setup"],[`${N} status`,"config.alt.status"]]),sections:[{title:U("config.subcommands_title"),rows:[["<tool>",U("config.sub.tool")],["<tool> --force",U("config.sub.tool_force")],["<tool> --non-interactive",U("config.sub.tool_non_interactive")],["<tool> remove",U("config.sub.tool_remove")],["<tool> restore",U("config.sub.tool_restore")],["<tool> backups",U("config.sub.tool_backups")],["<tool> clear-model",U("config.sub.tool_clear_model")],["tool-model list",U("config.sub.tool_model_list")],["tool-model set <tool> [slot] <model>",U("config.sub.tool_model_set")],["tool-model clear <tool>",U("config.sub.tool_model_clear")],["profile list",U("config.sub.profile_list")],["profile create <name>",U("config.sub.profile_create")],["profile use <name>",U("config.sub.profile_use")],["profile delete <name>",U("config.sub.profile_delete")],["preset list",U("config.sub.preset_list")],["preset save <name>",U("config.sub.preset_save")],["preset use <name>",U("config.sub.preset_use")],["preset delete <name>",U("config.sub.preset_delete")],["backup list",U("config.sub.backup_list")],["backup create [label]",U("config.sub.backup_create")],["backup restore <name>",U("config.sub.backup_restore")]]},{title:U("config.tools_title"),rows:Object.values(c).filter(e=>!e.hidden).map(e=>[e.name,e.displayName])}],examples:[H(`${N} config codex`,"config.ex.menu"),H(`${N} config claude-code --force`,"config.ex.force"),H(`${N} config tool-model set codex gpt-6-astra`,"config.ex.tool_model"),H(`${N} config profile create work`,"config.ex.profile"),H(`${N} config codex remove`,"config.ex.remove")]});const V=I.command("base").summary(U("base.summary")).description(U("base.description")).argument("[target]",U("base.arg.target")).action(async e=>{await C(e)});p(V,{...M("base",[[`${N} doctor`,"base.alt.doctor"],[`${N} bench`,"base.alt.bench"]]),sections:[{title:U("base.targets_title"),rows:[[U("base.target.none_term"),U("base.target.none")],[U("base.target.index_term"),U("base.target.index")],[U("base.target.url_term"),U("base.target.url")],["auto",U("base.target.auto")],["default",U("base.target.default",{url:l})]]}],examples:[H(`${N} base`,"base.ex.list"),H(`${N} base auto`,"base.ex.auto"),H(`${N} base 2`,"base.ex.index"),H(`${N} base ${P}`,"base.ex.url"),H(`${N} base default`,"base.ex.default")]}),I.commandsGroup(U("group.diagnose"));const W=I.command("status").summary(U("status.summary")).description(U("status.description")).action(async()=>{await x()});p(W,{...M("status",[[`${N} doctor`,"status.alt.doctor"]]),examples:[H(`${N} status`,"status.ex.show"),H(`${N} status --json`,"status.ex.json")]});const X=I.command("doctor").summary(U("doctor.summary")).description(U("doctor.description")).option("--deep",U("doctor.opt.deep")).option("--report",U("doctor.opt.report")).action(async e=>{await f({deep:e.deep,report:e.report})});p(X,{...M("doctor",[[`${N} base auto`,"doctor.alt.base"],[`${N} logs tail`,"doctor.alt.logs"]]),examples:[H(`${N} doctor`,"doctor.ex.run"),H(`${N} doctor --deep`,"doctor.ex.deep"),H(`${N} doctor --report`,"doctor.ex.report")]});const Z=I.command("bench").summary(U("bench.summary")).description(U("bench.description")).option("--samples <n>",U("bench.opt.samples"),"5").option("--stream",U("bench.opt.stream")).option("--model <model>",U("bench.opt.model")).action(async e=>{const o=[];e.samples&&o.push("--samples",e.samples),e.stream&&o.push("--stream"),e.model&&o.push("--model",e.model),await b(o)});p(Z,{...M("bench",[[`${N} base`,"bench.alt.base"]]),examples:[H(`${N} bench`,"bench.ex.run"),H(`${N} bench --samples 3`,"bench.ex.samples"),H(`${N} bench --stream`,"bench.ex.stream"),H(`${N} bench --stream --model gpt-6-astra`,"bench.ex.stream_model"),H(`${N} bench --json`,"bench.ex.json")]});const ee=I.command("logs").summary(U("logs.summary")).description(U("logs.description")).argument("[action]",U("logs.arg.action")).argument("[file]",U("logs.arg.file")).action(async(e,o)=>{const s=[];e&&s.push(e),o&&s.push(o),await $(s)});p(ee,{...M("logs",[[`${N} doctor`,"logs.alt.doctor"]]),sections:[{title:U("logs.actions_title"),rows:[["list",U("logs.action.list")],["tail [file]",U("logs.action.tail")],["path",U("logs.action.path")]]}],examples:[H(`${N} logs`,"logs.ex.list"),H(`${N} logs tail`,"logs.ex.tail"),H(`${N} logs path`,"logs.ex.path")]}),I.commandsGroup(U("group.maintain"));const oe=I.command("list").summary(U("list.summary")).description(U("list.description")).option("--refresh",U("list.opt.refresh")).action(async(e={})=>{await v({refresh:e.refresh})});p(oe,{...M("list",[[`${N} doctor`,"list.alt.doctor"]]),examples:[H(`${N} list`,"list.ex.all"),H(`${N} list --refresh`,"list.ex.refresh"),H(`${N} list --json`,"list.ex.json")]});const se=I.command("install").summary(U("install.summary")).description(U("install.description")).argument("<components...>",U("install.arg.components")).option("--force",U("install.opt.force")).action(async(e,o={})=>{await w(e,{force:o.force})});p(se,{...M("install",[[`${N} upgrade`,"install.alt.upgrade"],[`${N} setup --key ${i.t("errors.key_placeholder")}`,"install.alt.setup"]]),examples:[H(`${N} install node uv`,"install.ex.runtimes"),H(`${N} install claude-code codex`,"install.ex.clis"),H(`${N} install chatgpt`,"install.ex.app"),H(`${N} install uv --force`,"install.ex.force"),H(`${N} install node uv --yes --json`,"install.ex.json")]});const te=I.command("upgrade").summary(U("upgrade.summary")).description(U("upgrade.description")).argument("[tools...]",U("upgrade.arg.tools")).option("--force",U("upgrade.opt.force")).action(async(e=[],o={})=>{await _(e,{force:o.force})});p(te,{...M("upgrade",[[`${N} update`,"upgrade.alt.update"]]),examples:[H(`${N} upgrade`,"upgrade.ex.all"),H(`${N} upgrade codex agy`,"upgrade.ex.many"),H(`${N} upgrade claude-desktop`,"upgrade.ex.desktop"),H(`${N} upgrade chatgpt --force`,"upgrade.ex.force"),H(`${N} upgrade node`,"upgrade.ex.runtime")]});const ne=I.command("refresh").summary(U("refresh.summary")).description(U("refresh.description")).action(async()=>{await h()});p(ne,{...M("refresh",[[`${N} setup --key ${i.t("errors.key_placeholder")}`,"refresh.alt.setup"]]),examples:[H(`${N} refresh`,"refresh.ex.run"),H(`${N} refresh --base ${T}`,"refresh.ex.base")]});const ae=I.command("update").summary(U("update.summary")).description(U("update.description")).action(async()=>{await k()});p(ae,{...M("update",[[`${N} upgrade`,"update.alt.upgrade"]]),examples:[H(`${N} update`,"update.ex.check"),H(`${N} update --json`,"update.ex.json")]});const ie=I.command("codex").summary(U("codex.summary")).description(U("codex.description"));q(ie);const re=ie.command("sessions").summary(U("codex_sessions.summary")).description(U("codex_sessions.description")).option("--to <provider>",U("codex_sessions.opt.to")).option("--undo <dir>",U("codex_sessions.opt.undo")).action(async e=>{await j(e)});p(ie,{...M("codex"),examples:[H(`${N} codex sessions`,"codex_sessions.ex.move"),H(`${N} codex sessions --undo <dir>`,"codex_sessions.ex.undo")]}),p(re,{...M("codex_sessions",[[`${N} codex sessions --undo <dir>`,"codex_sessions.alt.undo"]]),examples:[H(`${N} codex sessions`,"codex_sessions.ex.move"),H(`${N} codex sessions --to custom`,"codex_sessions.ex.to"),H(`${N} codex sessions --undo <dir>`,"codex_sessions.ex.undo")]});const ce=I.command("sessions").summary(U("sessions.summary")).description(U("sessions.description"));q(ce);const le=ce.command("list",{isDefault:!0}).description(U("sessions.list")).option("--tool <tool>",U("sessions.opt.tool")).option("--dir <path>",U("sessions.opt.dir")).option("--here",U("sessions.opt.here")).option("-n, --limit <count>",U("sessions.opt.limit")).option("--all",U("sessions.opt.all")).action(async e=>{await S(e)}),pe=ce.command("show <id>").description(U("sessions.show")).option("-m, --messages <count>",U("sessions.opt.messages")).action(async(e,o)=>{await E(e,o)}),me=ce.command("resume <id>").description(U("sessions.resume")).option("--run",U("sessions.opt.run")).action(async(e,o)=>{await A(e,o)}),ue=ce.command("export <ids...>").description(U("sessions.export")).option("-o, --output <dir>",U("sessions.opt.output")).option("--tools",U("sessions.opt.tools")).action(async(e,o)=>{await O(e,o)});p(le,{examples:[H(`${N} sessions list`,"sessions.ex.list"),H(`${N} sessions list --tool codex`,"sessions.ex.codex"),H(`${N} sessions list --here --all`,"sessions.ex.here"),H(`${N} sessions list --json`,"sessions.ex.json")]}),p(pe,{examples:[H(`${N} sessions show 01a0f5fe`,"sessions.ex.show"),H(`${N} sessions show 01a0f5fe -m 20`,"sessions.ex.show_more")]}),p(me,{examples:[H(`${N} sessions resume 01a0f5fe`,"sessions.ex.resume_print"),H(`${N} sessions resume 01a0f5fe --run`,"sessions.ex.resume")]}),p(ue,{examples:[H(`${N} sessions export 01a0f5fe 7c2e9d41 -o ./sessions`,"sessions.ex.export"),H(`${N} sessions export 01a0f5fe -o ./sessions --tools`,"sessions.ex.export_tools")]}),p(ce,{...M("sessions",[[`${N} codex sessions`,"sessions.alt.codex_sessions"]]),examples:[H(`${N} sessions`,"sessions.ex.list"),H(`${N} sessions --tool codex --here`,"sessions.ex.here"),H(`${N} sessions show 01a0f5fe`,"sessions.ex.show"),H(`${N} sessions resume 01a0f5fe --run`,"sessions.ex.resume"),H(`${N} sessions export 01a0f5fe 7c2e9d41 -o ./sessions`,"sessions.ex.export")]});const de=I.command("lang").summary(U("lang.summary")).description(U("lang.description"));q(de);const fe=de.command("show").description(U("lang.show")).action(async()=>{await u(["show"])}),ge=de.command("set <locale>").description(U("lang.set")).action(async e=>{await u(["set",e])}),xe=[H(`${N} lang show`,"lang.ex.show"),H(`${N} lang set en_US`,"lang.ex.set_en"),H(`${N} lang set zh_CN`,"lang.ex.set_zh")];p(de,{...M("lang",[[`${N} enter lang`,"lang.alt.enter"]]),examples:xe}),p(fe,{examples:[xe[0],H(`${N} lang show --json`,"lang.ex.show_json")]}),p(ge,{examples:xe.slice(1)});const he=I.command("completion").summary(U("completion.summary")).description(U("completion.description")).argument("<shell>",U("completion.arg.shell")).action(async e=>{await y([e])});p(he,{...M("completion"),examples:[H(`${N} completion bash > ~/.${N}-completion.bash`,"completion.ex.bash"),H(`${N} completion zsh > ~/.${N}-completion.zsh`,"completion.ex.zsh"),H(`${N} completion fish > ~/.config/fish/completions/${N}.fish`,"completion.ex.fish")]});const $e=I.command("enter").summary(U("enter.summary")).description(U("enter.description")).argument("[option]",U("enter.arg.option")).action(async e=>{if(e&&!["lang","language","apikey","api-key","models"].includes(e)||B(),e)switch(e){case"lang":case"language":await r.configLanguage();break;case"apikey":case"api-key":await r.configApiKey();break;case"models":await r.configModels();break;default:await g([e])}else await r.run()});p($e,{...M("enter",[[`${N}`,"enter.alt.menu"],[`${N} config <tool>`,"enter.alt.config"]]),sections:[{title:U("enter.options_title"),rows:[[U("enter.option.none_term"),U("enter.option.none")],["lang",U("enter.option.lang")],["apikey",U("enter.option.apikey")],["models",U("enter.option.models")],["<tool>",U("enter.option.tool")]]}],examples:[H(`${N} enter`,"enter.ex.menu"),H(`${N} enter models`,"enter.ex.models"),H(`${N} enter codex`,"enter.ex.tool")]}),q(I),I.action(async()=>{B(),await r.run()}),p(I,{examples:[H(`${N}`,"root.ex.menu"),H(`${N} setup --key sk-xxx`,"root.ex.setup"),H(`${N} doctor`,"root.ex.doctor"),H(`${N} base auto`,"root.ex.base"),H(`${N} config codex`,"root.ex.config")]});const ye=e=>{for(const o of e.commands)o.helpOption("-h, --help",U("global.help")),ye(o)};return ye(I),I}
1
+ import{Command as e,Option as o}from"commander";import{readFileSync as s}from"fs";import{join as t,dirname as n}from"path";import{fileURLToPath as a}from"url";import{i18n as i}from"./i18n.js";import{wizard as r}from"./wizard.js";import{SUPPORTED_TOOLS as c}from"./tool-manager.js";import{DEFAULT_BASE_URL as l}from"./config.js";import{attachCommandHelp as p,helpConfiguration as m}from"./cli-help.js";import{langCommand as u,authCommand as d,doctorCommand as f,configCommand as g,statusCommand as x,refreshCommand as h}from"../commands/index.js";import{logsCommand as y}from"../commands/logs.js";import{completionCommand as $}from"../commands/completion.js";import{benchCommand as b}from"../commands/bench.js";import{updateCommand as k}from"../commands/update.js";import{upgradeCommand as _}from"../commands/upgrade.js";import{installCommand as w,listCommand as v}from"../commands/components.js";import{codexSessionsCommand as j}from"../commands/codex-sessions.js";import{sessionsExportCommand as O,sessionsListCommand as S,sessionsResumeCommand as A,sessionsShowCommand as E}from"../commands/sessions.js";import{setupCommand as G,DEDICATED_KEYS as z}from"../commands/setup.js";import{baseCommand as C}from"../commands/base.js";import{usageError as R}from"./errors.js";import{requireTerminal as B}from"./confirm.js";import{brand as I,brandEnv as L,CLI_NAME as N}from"./brand.js";const P=(I().gatewayAddresses[1]??I().gatewayAddresses[0]).url,T=(I().gatewayAddresses[2]??I().gatewayAddresses[0]).url;function U(e,o){return i.t(`help.${e}`,o)}function H(e,o){return{command:e,note:U(o)}}function K(e){const o=U(e);return o===`help.${e}`?"":o}function M(e,o=[]){return{when:K(`${e}.when`),prerequisites:K(`${e}.needs`).split("\n").filter(Boolean),alternatives:o.map(([e,o])=>H(e,o))}}function q(e){return e.helpCommand("help [command]",U("help_command"))}export function buildProgram(){const I=new e;I.name(`${N}`).summary(U("root.summary")).description(U("root.description")).configureHelp(m()).allowExcessArguments(!0).optionsGroup(U("group.global_options")).helpOption("-h, --help",U("global.help")).version(function(){try{const e=n(a(import.meta.url));return JSON.parse(s(t(e,"../../package.json"),"utf-8")).version}catch{return"1.0.0"}}(),"-v, --version",U("global.version")).option("--base <url>",U("global.base")).option("--non-interactive",U("global.non_interactive")).option("--json",U("global.json")).option("-y, --yes",U("global.yes")).option("--dry-run",U("global.dry_run")).option("--no-color",U("global.no_color")),I.configureOutput({writeErr:()=>{},outputError:()=>{}}),I.showSuggestionAfterError(),I.exitOverride(e=>{throw e}),I.commandsGroup(U("group.configure"));const K=I.command("setup").summary(U("setup.summary")).description(U("setup.description")).option("--key <key>",U("setup.opt.key"));for(const e of z){const s=new o(`--${e.option} <key>`,U(`setup.opt.${e.option}`));e.hidden&&s.hideHelp(),K.addOption(s)}K.option("--1m",U("setup.opt.one_m")).option("--no-1m",U("setup.opt.no_one_m")).option("--claude-official <on|off>",U("setup.opt.claude_official")).option("--desktop-registry <on|off>",U("setup.opt.desktop_registry")).option("--force",U("setup.opt.force")).option("--install",U("setup.opt.install")).option("--no-install",U("setup.opt.no_install")).option("--all",U("setup.opt.all")).action(async e=>{e.key||z.some(o=>e[o.option])||(e.key=L("SETUP_KEY")?.trim()||void 0,e.fromInstaller=Boolean(e.key));const o=Boolean(e.key||z.some(o=>e[o.option])),s=void 0!==e["1m"]||void 0!==e.claudeOfficial||void 0!==e.desktopRegistry,t=i.t("errors.key_placeholder");if(!o&&!s)throw R(i.t("setup.usage"),`${N} setup --key ${t}`,"missing_key");if(void 0!==e.claudeOfficial&&!["on","off"].includes(String(e.claudeOfficial).toLowerCase()))throw R(i.t("setup.claude_official_invalid",{value:String(e.claudeOfficial)}),`${N} setup --claude-official on|off`,"invalid_value");if(void 0!==e.desktopRegistry&&!["on","off"].includes(String(e.desktopRegistry).toLowerCase()))throw R(i.t("setup.desktop_registry_invalid",{value:String(e.desktopRegistry)}),`${N} setup --desktop-registry on|off`,"invalid_value");await G({key:e.key,...Object.fromEntries(z.map(o=>[o.option,e[o.option]])),all:e.all,oneMillion:e["1m"],claudeOfficial:e.claudeOfficial,desktopRegistry:e.desktopRegistry,force:e.force,install:e.install,fromInstaller:e.fromInstaller})}),p(K,{...M("setup",[[`${N} init`,"setup.alt.init"],[`${N} config <tool>`,"setup.alt.config"],[`${N} auth <key>`,"setup.alt.auth"]]),sections:[{title:U("setup.autodetect_title"),rows:[["Claude",U("setup.autodetect.claude")],["GPT",U("setup.autodetect.gpt")],["Grok",U("setup.autodetect.grok")],["Gemini",U("setup.autodetect.gemini")],[U("setup.autodetect.any_label"),U("setup.autodetect.any")]]}],examples:[H(`${N} setup --key sk-xxx`,"setup.ex.key"),H(`${N} setup --install --key sk-xxx`,"setup.ex.install"),H(`${N} setup --claudekey sk-a --codexkey sk-b --agykey sk-g`,"setup.ex.split"),H(`${N} setup --force --key sk-xxx`,"setup.ex.force"),H(`${N} setup --base ${P} --key sk-xxx`,"setup.ex.base")]});const D=I.command("init").summary(U("init.summary")).description(U("init.description")).action(async()=>{B(),await r.runFirstTimeSetup()});p(D,{...M("init",[[`${N} setup --key <key>`,"init.alt.setup"],[`${N}`,"init.alt.menu"]]),examples:[H(`${N} init`,"init.ex.run"),H(`${N} init --base ${P}`,"init.ex.base"),H(`${N}`,"init.ex.menu")]});const F=I.command("auth").summary(U("auth.summary")).description(U("auth.description")).argument("[token]",U("auth.arg.token")).action(async e=>{const o=[];e&&o.push(e),await d(o)});q(F);const J=F.command("revoke").description(U("auth.revoke")).action(async()=>{await d(["revoke"])});p(J,{examples:[H(`${N} auth revoke`,"auth.ex.revoke_ask"),H(`${N} auth revoke --yes`,"auth.ex.revoke")]});const Y=F.command("reload <tool>").description(U("auth.reload")).action(async e=>{await d(["reload",e])});p(Y,{examples:[H(`${N} auth reload claude-code`,"auth.ex.reload"),H(`${N} auth reload claude-code --json`,"auth.ex.reload_json")]}),p(F,{...M("auth",[[`${N} setup --key <key>`,"auth.alt.setup"]]),examples:[H(`${N} auth`,"auth.ex.prompt"),H(`${N} auth sk-xxx --non-interactive`,"auth.ex.save"),H(`${N} auth revoke --yes`,"auth.ex.revoke"),H(`${N} auth reload claude-code`,"auth.ex.reload")]});const Q=I.command("config").summary(U("config.summary")).description(U("config.description")).argument("[args...]",U("config.arg.args")).option("-f, --force",U("config.opt.force")).allowUnknownOption(!0).action(async(e=[],o={})=>{await g(o.force?[...e,"--force"]:e)});p(Q,{...M("config",[[`${N} setup --force --key <key>`,"config.alt.setup"],[`${N} status`,"config.alt.status"]]),sections:[{title:U("config.subcommands_title"),rows:[["<tool>",U("config.sub.tool")],["<tool> --force",U("config.sub.tool_force")],["<tool> --non-interactive",U("config.sub.tool_non_interactive")],["<tool> remove",U("config.sub.tool_remove")],["<tool> restore",U("config.sub.tool_restore")],["<tool> backups",U("config.sub.tool_backups")],["<tool> clear-model",U("config.sub.tool_clear_model")],["tool-model list",U("config.sub.tool_model_list")],["tool-model set <tool> [slot] <model>",U("config.sub.tool_model_set")],["tool-model clear <tool>",U("config.sub.tool_model_clear")],["profile list",U("config.sub.profile_list")],["profile create <name>",U("config.sub.profile_create")],["profile use <name>",U("config.sub.profile_use")],["profile delete <name>",U("config.sub.profile_delete")],["preset list",U("config.sub.preset_list")],["preset save <name>",U("config.sub.preset_save")],["preset use <name>",U("config.sub.preset_use")],["preset delete <name>",U("config.sub.preset_delete")],["backup list",U("config.sub.backup_list")],["backup create [label]",U("config.sub.backup_create")],["backup restore <name>",U("config.sub.backup_restore")]]},{title:U("config.tools_title"),rows:Object.values(c).filter(e=>!e.hidden).map(e=>[e.name,e.displayName])}],examples:[H(`${N} config codex`,"config.ex.menu"),H(`${N} config claude-code --force`,"config.ex.force"),H(`${N} config tool-model set codex gpt-6-astra`,"config.ex.tool_model"),H(`${N} config profile create work`,"config.ex.profile"),H(`${N} config codex remove`,"config.ex.remove")]});const V=I.command("base").summary(U("base.summary")).description(U("base.description")).argument("[target]",U("base.arg.target")).action(async e=>{await C(e)});p(V,{...M("base",[[`${N} doctor`,"base.alt.doctor"],[`${N} bench`,"base.alt.bench"]]),sections:[{title:U("base.targets_title"),rows:[[U("base.target.none_term"),U("base.target.none")],[U("base.target.index_term"),U("base.target.index")],[U("base.target.url_term"),U("base.target.url")],["auto",U("base.target.auto")],["default",U("base.target.default",{url:l})]]}],examples:[H(`${N} base`,"base.ex.list"),H(`${N} base auto`,"base.ex.auto"),H(`${N} base 2`,"base.ex.index"),H(`${N} base ${P}`,"base.ex.url"),H(`${N} base default`,"base.ex.default")]}),I.commandsGroup(U("group.diagnose"));const W=I.command("status").summary(U("status.summary")).description(U("status.description")).action(async()=>{await x()});p(W,{...M("status",[[`${N} doctor`,"status.alt.doctor"]]),examples:[H(`${N} status`,"status.ex.show"),H(`${N} status --json`,"status.ex.json")]});const X=I.command("doctor").summary(U("doctor.summary")).description(U("doctor.description")).option("--deep",U("doctor.opt.deep")).option("--report",U("doctor.opt.report")).action(async e=>{await f({deep:e.deep,report:e.report})});p(X,{...M("doctor",[[`${N} base auto`,"doctor.alt.base"],[`${N} logs tail`,"doctor.alt.logs"]]),examples:[H(`${N} doctor`,"doctor.ex.run"),H(`${N} doctor --deep`,"doctor.ex.deep"),H(`${N} doctor --report`,"doctor.ex.report")]});const Z=I.command("bench").summary(U("bench.summary")).description(U("bench.description")).option("--samples <n>",U("bench.opt.samples"),"5").option("--stream",U("bench.opt.stream")).option("--model <model>",U("bench.opt.model")).action(async e=>{const o=[];e.samples&&o.push("--samples",e.samples),e.stream&&o.push("--stream"),e.model&&o.push("--model",e.model),await b(o)});p(Z,{...M("bench",[[`${N} base`,"bench.alt.base"]]),examples:[H(`${N} bench`,"bench.ex.run"),H(`${N} bench --samples 3`,"bench.ex.samples"),H(`${N} bench --stream`,"bench.ex.stream"),H(`${N} bench --stream --model gpt-6-astra`,"bench.ex.stream_model"),H(`${N} bench --json`,"bench.ex.json")]});const ee=I.command("logs").summary(U("logs.summary")).description(U("logs.description")).argument("[action]",U("logs.arg.action")).argument("[file]",U("logs.arg.file")).action(async(e,o)=>{const s=[];e&&s.push(e),o&&s.push(o),await y(s)});p(ee,{...M("logs",[[`${N} doctor`,"logs.alt.doctor"]]),sections:[{title:U("logs.actions_title"),rows:[["list",U("logs.action.list")],["tail [file]",U("logs.action.tail")],["path",U("logs.action.path")]]}],examples:[H(`${N} logs`,"logs.ex.list"),H(`${N} logs tail`,"logs.ex.tail"),H(`${N} logs path`,"logs.ex.path")]}),I.commandsGroup(U("group.maintain"));const oe=I.command("list").summary(U("list.summary")).description(U("list.description")).option("--refresh",U("list.opt.refresh")).action(async(e={})=>{await v({refresh:e.refresh})});p(oe,{...M("list",[[`${N} doctor`,"list.alt.doctor"]]),examples:[H(`${N} list`,"list.ex.all"),H(`${N} list --refresh`,"list.ex.refresh"),H(`${N} list --json`,"list.ex.json")]});const se=I.command("install").summary(U("install.summary")).description(U("install.description")).argument("<components...>",U("install.arg.components")).option("--force",U("install.opt.force")).action(async(e,o={})=>{await w(e,{force:o.force})});p(se,{...M("install",[[`${N} upgrade`,"install.alt.upgrade"],[`${N} setup --key ${i.t("errors.key_placeholder")}`,"install.alt.setup"]]),examples:[H(`${N} install node uv`,"install.ex.runtimes"),H(`${N} install claude-code codex`,"install.ex.clis"),H(`${N} install chatgpt`,"install.ex.app"),H(`${N} install uv --force`,"install.ex.force"),H(`${N} install node uv --yes --json`,"install.ex.json")]});const te=I.command("upgrade").summary(U("upgrade.summary")).description(U("upgrade.description")).argument("[tools...]",U("upgrade.arg.tools")).option("--force",U("upgrade.opt.force")).action(async(e=[],o={})=>{await _(e,{force:o.force})});p(te,{...M("upgrade",[[`${N} update`,"upgrade.alt.update"]]),examples:[H(`${N} upgrade`,"upgrade.ex.all"),H(`${N} upgrade codex agy`,"upgrade.ex.many"),H(`${N} upgrade claude-desktop`,"upgrade.ex.desktop"),H(`${N} upgrade chatgpt --force`,"upgrade.ex.force"),H(`${N} upgrade node`,"upgrade.ex.runtime")]});const ne=I.command("refresh").summary(U("refresh.summary")).description(U("refresh.description")).action(async()=>{await h()});p(ne,{...M("refresh",[[`${N} setup --key ${i.t("errors.key_placeholder")}`,"refresh.alt.setup"]]),examples:[H(`${N} refresh`,"refresh.ex.run"),H(`${N} refresh --base ${T}`,"refresh.ex.base")]});const ae=I.command("update").summary(U("update.summary")).description(U("update.description")).action(async()=>{await k()});p(ae,{...M("update",[[`${N} upgrade`,"update.alt.upgrade"]]),examples:[H(`${N} update`,"update.ex.check"),H(`${N} update --json`,"update.ex.json")]});const ie=I.command("codex").summary(U("codex.summary")).description(U("codex.description"));q(ie);const re=ie.command("sessions").summary(U("codex_sessions.summary")).description(U("codex_sessions.description")).option("--to <provider>",U("codex_sessions.opt.to")).option("--undo <dir>",U("codex_sessions.opt.undo")).action(async e=>{await j(e)});p(ie,{...M("codex"),examples:[H(`${N} codex sessions`,"codex_sessions.ex.move"),H(`${N} codex sessions --undo <dir>`,"codex_sessions.ex.undo")]}),p(re,{...M("codex_sessions",[[`${N} codex sessions --undo <dir>`,"codex_sessions.alt.undo"]]),examples:[H(`${N} codex sessions`,"codex_sessions.ex.move"),H(`${N} codex sessions --to custom`,"codex_sessions.ex.to"),H(`${N} codex sessions --undo <dir>`,"codex_sessions.ex.undo")]});const ce=I.command("sessions").summary(U("sessions.summary")).description(U("sessions.description"));q(ce);const le=ce.command("list",{isDefault:!0}).description(U("sessions.list")).option("--tool <tool>",U("sessions.opt.tool")).option("--dir <path>",U("sessions.opt.dir")).option("--here",U("sessions.opt.here")).option("-n, --limit <count>",U("sessions.opt.limit")).option("--all",U("sessions.opt.all")).action(async e=>{await S(e)}),pe=ce.command("show <id>").description(U("sessions.show")).option("-m, --messages <count>",U("sessions.opt.messages")).action(async(e,o)=>{await E(e,o)}),me=ce.command("resume <id>").description(U("sessions.resume")).option("--run",U("sessions.opt.run")).action(async(e,o)=>{await A(e,o)}),ue=ce.command("export <ids...>").description(U("sessions.export")).option("-o, --output <dir>",U("sessions.opt.output")).option("--tools",U("sessions.opt.tools")).action(async(e,o)=>{await O(e,o)});p(le,{examples:[H(`${N} sessions list`,"sessions.ex.list"),H(`${N} sessions list --tool codex`,"sessions.ex.codex"),H(`${N} sessions list --here --all`,"sessions.ex.here"),H(`${N} sessions list --json`,"sessions.ex.json")]}),p(pe,{examples:[H(`${N} sessions show 01a0f5fe`,"sessions.ex.show"),H(`${N} sessions show 01a0f5fe -m 20`,"sessions.ex.show_more")]}),p(me,{examples:[H(`${N} sessions resume 01a0f5fe`,"sessions.ex.resume_print"),H(`${N} sessions resume 01a0f5fe --run`,"sessions.ex.resume")]}),p(ue,{examples:[H(`${N} sessions export 01a0f5fe 7c2e9d41 -o ./sessions`,"sessions.ex.export"),H(`${N} sessions export 01a0f5fe -o ./sessions --tools`,"sessions.ex.export_tools")]}),p(ce,{...M("sessions",[[`${N} codex sessions`,"sessions.alt.codex_sessions"]]),examples:[H(`${N} sessions`,"sessions.ex.list"),H(`${N} sessions --tool codex --here`,"sessions.ex.here"),H(`${N} sessions show 01a0f5fe`,"sessions.ex.show"),H(`${N} sessions resume 01a0f5fe --run`,"sessions.ex.resume"),H(`${N} sessions export 01a0f5fe 7c2e9d41 -o ./sessions`,"sessions.ex.export")]});const de=I.command("lang").summary(U("lang.summary")).description(U("lang.description"));q(de);const fe=de.command("show").description(U("lang.show")).action(async()=>{await u(["show"])}),ge=de.command("set <locale>").description(U("lang.set")).action(async e=>{await u(["set",e])}),xe=[H(`${N} lang show`,"lang.ex.show"),H(`${N} lang set en_US`,"lang.ex.set_en"),H(`${N} lang set zh_CN`,"lang.ex.set_zh")];p(de,{...M("lang",[[`${N} enter lang`,"lang.alt.enter"]]),examples:xe}),p(fe,{examples:[xe[0],H(`${N} lang show --json`,"lang.ex.show_json")]}),p(ge,{examples:xe.slice(1)});const he=I.command("completion").summary(U("completion.summary")).description(U("completion.description")).argument("<shell>",U("completion.arg.shell")).action(async e=>{await $([e])});p(he,{...M("completion"),examples:[H(`${N} completion bash > ~/.${N}-completion.bash`,"completion.ex.bash"),H(`${N} completion zsh > ~/.${N}-completion.zsh`,"completion.ex.zsh"),H(`${N} completion fish > ~/.config/fish/completions/${N}.fish`,"completion.ex.fish")]});const ye=I.command("enter").summary(U("enter.summary")).description(U("enter.description")).argument("[option]",U("enter.arg.option")).action(async e=>{if(e&&!["lang","language","apikey","api-key","models"].includes(e)||B(),e)switch(e){case"lang":case"language":await r.configLanguage();break;case"apikey":case"api-key":await r.configApiKey();break;case"models":await r.configModels();break;default:await g([e])}else await r.run()});p(ye,{...M("enter",[[`${N}`,"enter.alt.menu"],[`${N} config <tool>`,"enter.alt.config"]]),sections:[{title:U("enter.options_title"),rows:[[U("enter.option.none_term"),U("enter.option.none")],["lang",U("enter.option.lang")],["apikey",U("enter.option.apikey")],["models",U("enter.option.models")],["<tool>",U("enter.option.tool")]]}],examples:[H(`${N} enter`,"enter.ex.menu"),H(`${N} enter models`,"enter.ex.models"),H(`${N} enter codex`,"enter.ex.tool")]}),q(I),I.action(async()=>{B(),await r.run()}),p(I,{examples:[H(`${N}`,"root.ex.menu"),H(`${N} setup --key sk-xxx`,"root.ex.setup"),H(`${N} doctor`,"root.ex.doctor"),H(`${N} base auto`,"root.ex.base"),H(`${N} config codex`,"root.ex.config")]});const $e=e=>{for(const o of e.commands)o.helpOption("-h, --help",U("global.help")),$e(o)};return $e(I),I}
@@ -1 +1 @@
1
- import{join as e}from"path";import{applyGatewayModels as t,claudeCodeManager as o}from"../claude-code-manager.js";import{backupBeforeWrite as n}from"./backup.js";import{i18n as s}from"../i18n.js";import{baseModelId as a}from"../model-catalog.js";import{gatewayModelSpecs as r,prettyModelName as i,vendorNames as l}from"../gateway-models.js";import{toolHome as c}from"./types.js";import{gatewayAddresses as d,normalizeBaseUrl as u}from"../gateway-addresses.js";import{configManager as m,savedApiKeys as p}from"../config.js";import{envCleanupPlan as f,lastEnvCleanup as g,removeEnvSources as _}from"../env-cleanup.js";import{canPrompt as h,hasExplicitYes as v}from"../runtime-options.js";import{maskHome as C}from"../telemetry.js";import{spawnSync as j}from"child_process";import{existsSync as y,readFileSync as k}from"fs";import{detectManagedOverrides as A}from"./claude-managed.js";import{installOfficialPlugins as O}from"./claude-plugins.js";import{findInstalls as S,mirrorInstallCommand as P,brandInstallScripts as x}from"./tool-installs.js";import{updateNativeFromMirror as b}from"./claude-native-mirror.js";import{brandEnv as T}from"../brand.js";import{claudeFormat as N,claudeProjectFiles as w}from"../sessions/formats.js";const H=e(c(),".claude","settings.json"),L=e(c(),".claude.json");let R,U=null,E=()=>0===j("security",["find-generic-password","-s","Claude Code-credentials"],{stdio:"ignore"}).status;export function setClaudeKeychainProbeForTests(e){E=e}export function claudeAccountLoginPresent(){const t=process.env.CLAUDE_CONFIG_DIR?.trim()||e(c(),".claude");if(y(e(t,".credentials.json")))return!0;if("darwin"!==process.platform||T("TEST_HOME"))return!1;try{return E()}catch{return!1}}function I(){try{const t=JSON.parse(k(e(c(),".claude","settings.json"),"utf-8"));return"string"==typeof t.autoUpdatesChannel?t.autoUpdatesChannel:"latest"}catch{return"latest"}}function M(e){if(!e)return;const t=new Set(e.models);return r("claude-code",e.clientModels).filter(e=>t.has(e.id))}function D(){const e=o.getSettings().env?.ANTHROPIC_BASE_URL;return"string"==typeof e&&e.trim()?claudeCodeAdapter.holdsOurConfig(p())?null:e.trim():null}let B=null;const K={command:"claude",npmPackage:"@anthropic-ai/claude-code",native:{binDir:[".local","bin"],updateArgs:["update"],dataDirs:[[".local","share","claude"]],mirrorUpdate:()=>b(I())},mirrorScript:x("claude-code"),brew:"claude-code"};function F(){return h()&&!v()}export const claudeCodeAdapter={name:"claude-code",displayName:"Claude Code",command:"claude",installCommand:P(K),upgradeCommand:"claude update",installSpec:K,upgradeHints:e=>"stable"===I()?[s.t("tools.claude_code.stable_channel",{min:e})]:[],configPath:H,sessions:{format:N,files:()=>w(e(process.env.CLAUDE_CONFIG_DIR?.trim()||e(c(),".claude"),"projects")),resumeCommand:e=>({command:"claude",args:["--resume",e]})},wantsModelCatalog:!0,loadPrivateConfig(t){B=D(),n(H),n(L),R=M(t.catalog),o.loadPrivateConfig(t.apiKey,t.models,t.catalog?.models,R);const s=e(c(),".local","bin","win32"===process.platform?"claude.exe":"claude"),a=S(claudeCodeAdapter.installSpec)[0]?.path??(y(s)?s:null);U=a?O(a):null},holdsOurConfig(e){const t=o.getSettings().env??{},n="string"==typeof t.ANTHROPIC_AUTH_TOKEN?t.ANTHROPIC_AUTH_TOKEN.trim():"",s="string"==typeof t.ANTHROPIC_BASE_URL?u(t.ANTHROPIC_BASE_URL):null;return!(!n||!e.includes(n))||null!==s&&(d().some(e=>e.url===s)||s===u(m.getBaseUrl()))},planNotes(){const e=[],t=D();t&&e.push(s.t("tools.claude_code.plan_replace_provider",{url:t}));for(const t of f())e.push(s.t("tools.claude_code.plan_env_remove",{location:C(t.location),vars:Object.keys(t.vars).join(", ")}));return e},unloadPrivateConfig(e){const t=o.getSettings().env??{};Boolean(t.ANTHROPIC_AUTH_TOKEN||t.ANTHROPIC_BASE_URL)&&!claudeCodeAdapter.holdsOurConfig(e?.savedKeys??[])||(n(H),o.unloadPrivateConfig())},detectCurrentConfig:()=>o.detectCurrentConfig(),getConfig:()=>({settings:o.getSettings(),mcp:o.getMCPConfig()}),updateConfig(e){const t=e||{};t.settings&&o.saveSettings(t.settings),t.mcp&&o.saveMCPConfig(t.mcp)},clearPinnedModels:e=>(n(H),o.clearPinnedModels(e?.models)),listedModels(){const e=o.getSettings().modelPicker;return Array.isArray(e?.options)?e.options.map(e=>a(String(e.model))):null},refreshModelMenu(e){const s=o.getSettings(),a=t(s,M(e.catalog));JSON.stringify(a)!==JSON.stringify(s)&&(n(H),o.saveSettings(a))},async followUp(){const e=g().foreign;if(0===e.length||!F())return null;const t=e.map(e=>`${C(e.location)}(${Object.keys(e.vars).join(", ")})`).join("、");return{prompt:s.t("tools.claude_code.env_foreign_offer",{where:t}),hint:s.t("tools.claude_code.env_foreign",{location:e.map(e=>C(e.location)).join("、"),vars:[...new Set(e.flatMap(e=>Object.keys(e.vars)))].join(", ")}),async run(){const t=_(e),o=t.removed.map(e=>({kind:"summary",text:s.t("tools.claude_code.env_removed_foreign",{location:C(e.location),vars:Object.keys(e.vars).join(", ")})}));return t.machineLeft.length>0&&o.push({kind:"action",text:s.t("messages.env_vars_machine_left",{vars:t.machineLeft.join(", ")})}),o},decline(){}}},applyNotes(){const e=[];U?.installed.length&&(e.push({kind:"summary",text:s.t("tools.claude_code.plugins_installed",{count:String(U.installed.length)})}),e.push({kind:"detail",text:U.installed.join(", ")})),"git"===U?.skipped?e.push({kind:"action",text:s.t("tools.claude_code.plugins_need_git")}):("marketplace"===U?.skipped||U?.failed.length)&&e.push({kind:"action",text:s.t("tools.claude_code.plugins_failed")}),R&&R.length>0&&(e.push({kind:"summary",text:s.t("tools.claude_code.gateway_models",{count:String(R.length),vendors:l(R.map(e=>e.id)).join(" / ")})}),e.push({kind:"detail",text:R.map(e=>e.name||i(e.id)).join(", ")})),B&&e.push({kind:"summary",text:s.t("tools.claude_code.provider_replaced",{url:B})});const t=g();for(const o of t.removed)e.push({kind:"summary",text:s.t("tools.claude_code.env_removed",{location:C(o.location),vars:Object.keys(o.vars).join(", ")})});for(const o of t.foreign){const t={location:C(o.location),vars:Object.keys(o.vars).join(", ")};e.push(F()?{kind:"detail",text:s.t("tools.claude_code.env_foreign_found",t)}:{kind:"action",text:s.t("tools.claude_code.env_foreign",t)})}t.machineLeft.length>0&&e.push({kind:"action",text:s.t("messages.env_vars_machine_left",{vars:t.machineLeft.join(", ")})});const n=o.getLastReplaced();n.length>0&&e.push({kind:"summary",text:s.t("tools.claude_code.replaced_user_models",{values:n.join(", ")})}),"win32"!==process.platform||process.env.CLAUDE_CODE_GIT_BASH_PATH||0===j("where",["git"],{windowsHide:!0,stdio:"ignore"}).status||e.push({kind:"action",text:s.t("tools.claude_code.no_git_bash")}),claudeAccountLoginPresent()&&e.push({kind:"detail",text:s.t("tools.claude_code.account_login_overridden")});for(const t of A())e.push({kind:"action",text:s.t("tools.claude_code.managed_override",{source:t.source,keys:t.keys.join(", ")})});for(const t of o.getLastTierFallbacks())e.push({kind:"detail",text:s.t("tools.claude_code.tier_fallback",{tier:t.tier,from:t.from,to:t.to})});return e},backupPaths:()=>[H,L],forceResetPaths:()=>[H]};
1
+ import{join as e}from"path";import{applyGatewayModels as t,claudeCodeManager as o}from"../claude-code-manager.js";import{backupBeforeWrite as n}from"./backup.js";import{i18n as s}from"../i18n.js";import{baseModelId as a}from"../model-catalog.js";import{gatewayModelSpecs as r,prettyModelName as i,vendorNames as l}from"../gateway-models.js";import{toolHome as c}from"./types.js";import{gatewayAddresses as d,normalizeBaseUrl as u}from"../gateway-addresses.js";import{configManager as m,savedApiKeys as p}from"../config.js";import{envCleanupPlan as f,lastEnvCleanup as g,removeEnvSources as _}from"../env-cleanup.js";import{canPrompt as h,hasExplicitYes as v}from"../runtime-options.js";import{maskHome as C}from"../telemetry.js";import{spawnSync as j}from"child_process";import{existsSync as y,readFileSync as k}from"fs";import{detectManagedOverrides as A}from"./claude-managed.js";import{installOfficialPlugins as O}from"./claude-plugins.js";import{findInstalls as P,mirrorInstallCommand as S,brandInstallScripts as x}from"./tool-installs.js";import{updateNativeFromMirror as b}from"./claude-native-mirror.js";import{brandEnv as T}from"../brand.js";import{claudeFormat as N,claudeProjectFiles as w}from"../sessions/formats.js";const H=e(c(),".claude","settings.json"),L=e(c(),".claude.json");let R,U=null,E=()=>0===j("security",["find-generic-password","-s","Claude Code-credentials"],{stdio:"ignore"}).status;export function setClaudeKeychainProbeForTests(e){E=e}export function claudeAccountLoginPresent(){const t=process.env.CLAUDE_CONFIG_DIR?.trim()||e(c(),".claude");if(y(e(t,".credentials.json")))return!0;if("darwin"!==process.platform||T("TEST_HOME"))return!1;try{return E()}catch{return!1}}function I(){try{const t=JSON.parse(k(e(c(),".claude","settings.json"),"utf-8"));return"string"==typeof t.autoUpdatesChannel?t.autoUpdatesChannel:"latest"}catch{return"latest"}}function M(e){if(!e)return;const t=new Set(e.models);return r("claude-code",e.clientModels,e.clientPersonal).filter(e=>t.has(e.id))}function D(){const e=o.getSettings().env?.ANTHROPIC_BASE_URL;return"string"==typeof e&&e.trim()?claudeCodeAdapter.holdsOurConfig(p())?null:e.trim():null}let B=null;const K={command:"claude",npmPackage:"@anthropic-ai/claude-code",native:{binDir:[".local","bin"],updateArgs:["update"],dataDirs:[[".local","share","claude"]],mirrorUpdate:()=>b(I())},mirrorScript:x("claude-code"),brew:"claude-code"};function F(){return h()&&!v()}export const claudeCodeAdapter={name:"claude-code",displayName:"Claude Code",command:"claude",installCommand:S(K),upgradeCommand:"claude update",installSpec:K,upgradeHints:e=>"stable"===I()?[s.t("tools.claude_code.stable_channel",{min:e})]:[],configPath:H,sessions:{format:N,files:()=>w(e(process.env.CLAUDE_CONFIG_DIR?.trim()||e(c(),".claude"),"projects")),resumeCommand:e=>({command:"claude",args:["--resume",e]})},wantsModelCatalog:!0,loadPrivateConfig(t){B=D(),n(H),n(L),R=M(t.catalog),o.loadPrivateConfig(t.apiKey,t.models,t.catalog?.models,R);const s=e(c(),".local","bin","win32"===process.platform?"claude.exe":"claude"),a=P(claudeCodeAdapter.installSpec)[0]?.path??(y(s)?s:null);U=a?O(a):null},holdsOurConfig(e){const t=o.getSettings().env??{},n="string"==typeof t.ANTHROPIC_AUTH_TOKEN?t.ANTHROPIC_AUTH_TOKEN.trim():"",s="string"==typeof t.ANTHROPIC_BASE_URL?u(t.ANTHROPIC_BASE_URL):null;return!(!n||!e.includes(n))||null!==s&&(d().some(e=>e.url===s)||s===u(m.getBaseUrl()))},planNotes(){const e=[],t=D();t&&e.push(s.t("tools.claude_code.plan_replace_provider",{url:t}));for(const t of f())e.push(s.t("tools.claude_code.plan_env_remove",{location:C(t.location),vars:Object.keys(t.vars).join(", ")}));return e},unloadPrivateConfig(e){const t=o.getSettings().env??{};Boolean(t.ANTHROPIC_AUTH_TOKEN||t.ANTHROPIC_BASE_URL)&&!claudeCodeAdapter.holdsOurConfig(e?.savedKeys??[])||(n(H),o.unloadPrivateConfig())},detectCurrentConfig:()=>o.detectCurrentConfig(),getConfig:()=>({settings:o.getSettings(),mcp:o.getMCPConfig()}),updateConfig(e){const t=e||{};t.settings&&o.saveSettings(t.settings),t.mcp&&o.saveMCPConfig(t.mcp)},clearPinnedModels:e=>(n(H),o.clearPinnedModels(e?.models)),listedModels(){const e=o.getSettings().modelPicker;return Array.isArray(e?.options)?e.options.map(e=>a(String(e.model))):null},refreshModelMenu(e){const s=o.getSettings(),a=t(s,M(e.catalog));JSON.stringify(a)!==JSON.stringify(s)&&(n(H),o.saveSettings(a))},async followUp(){const e=g().foreign;if(0===e.length||!F())return null;const t=e.map(e=>`${C(e.location)}(${Object.keys(e.vars).join(", ")})`).join("、");return{prompt:s.t("tools.claude_code.env_foreign_offer",{where:t}),hint:s.t("tools.claude_code.env_foreign",{location:e.map(e=>C(e.location)).join("、"),vars:[...new Set(e.flatMap(e=>Object.keys(e.vars)))].join(", ")}),async run(){const t=_(e),o=t.removed.map(e=>({kind:"summary",text:s.t("tools.claude_code.env_removed_foreign",{location:C(e.location),vars:Object.keys(e.vars).join(", ")})}));return t.machineLeft.length>0&&o.push({kind:"action",text:s.t("messages.env_vars_machine_left",{vars:t.machineLeft.join(", ")})}),o},decline(){}}},applyNotes(){const e=[];U?.installed.length&&(e.push({kind:"summary",text:s.t("tools.claude_code.plugins_installed",{count:String(U.installed.length)})}),e.push({kind:"detail",text:U.installed.join(", ")})),"git"===U?.skipped?e.push({kind:"action",text:s.t("tools.claude_code.plugins_need_git")}):("marketplace"===U?.skipped||U?.failed.length)&&e.push({kind:"action",text:s.t("tools.claude_code.plugins_failed")}),R&&R.length>0&&(e.push({kind:"summary",text:s.t("tools.claude_code.gateway_models",{count:String(R.length),vendors:l(R.map(e=>e.id)).join(" / ")})}),e.push({kind:"detail",text:R.map(e=>e.name||i(e.id)).join(", ")})),B&&e.push({kind:"summary",text:s.t("tools.claude_code.provider_replaced",{url:B})});const t=g();for(const o of t.removed)e.push({kind:"summary",text:s.t("tools.claude_code.env_removed",{location:C(o.location),vars:Object.keys(o.vars).join(", ")})});for(const o of t.foreign){const t={location:C(o.location),vars:Object.keys(o.vars).join(", ")};e.push(F()?{kind:"detail",text:s.t("tools.claude_code.env_foreign_found",t)}:{kind:"action",text:s.t("tools.claude_code.env_foreign",t)})}t.machineLeft.length>0&&e.push({kind:"action",text:s.t("messages.env_vars_machine_left",{vars:t.machineLeft.join(", ")})});const n=o.getLastReplaced();n.length>0&&e.push({kind:"summary",text:s.t("tools.claude_code.replaced_user_models",{values:n.join(", ")})}),"win32"!==process.platform||process.env.CLAUDE_CODE_GIT_BASH_PATH||0===j("where",["git"],{windowsHide:!0,stdio:"ignore"}).status||e.push({kind:"action",text:s.t("tools.claude_code.no_git_bash")}),claudeAccountLoginPresent()&&e.push({kind:"detail",text:s.t("tools.claude_code.account_login_overridden")});for(const t of A())e.push({kind:"action",text:s.t("tools.claude_code.managed_override",{source:t.source,keys:t.keys.join(", ")})});for(const t of o.getLastTierFallbacks())e.push({kind:"detail",text:s.t("tools.claude_code.tier_fallback",{tier:t.tier,from:t.from,to:t.to})});return e},backupPaths:()=>[H,L],forceResetPaths:()=>[H]};
@@ -0,0 +1 @@
1
+ import{existsSync as e,readFileSync as t}from"fs";import{BRAND_NAME as r}from"../brand.js";import{gatewayModelSpecs as n,modelFamily as o,prettyModelName as i,vendorNames as s}from"../gateway-models.js";import{backupBeforeWrite as a,atomicWriteFile as p}from"./backup.js";import{withV1 as d}from"./types.js";export const CUSTOM_MODEL_PREFIX="custom-local:";const u="openai",l="openai-response",c=e=>!!e&&"object"==typeof e&&!Array.isArray(e);export const isOurEntry=e=>c(e)&&e.vendor===r;export function readModelsFile(r){if(!e(r))return{entries:[],wrap:e=>({models:e})};const n=t(r,"utf-8");if(!n.trim())return{entries:[],wrap:e=>({models:e})};let o;try{o=JSON.parse(n)}catch(e){throw new Error(`Existing ${r} cannot be parsed; back it up and fix it first: ${e instanceof Error?e.message:String(e)}`)}if(Array.isArray(o))return{entries:o,wrap:e=>e};if(c(o))return{entries:Array.isArray(o.models)?o.models:[],wrap:e=>({...o,models:e})};throw new Error(`Existing ${r} must hold a JSON object or array`)}export function writeModelsFile(r,n,o){const i=`${JSON.stringify(n.wrap(o),null,2)}\n`;e(r)&&t(r,"utf-8")===i||(a(r),p(r,i,384))}export const bareModelId=e=>e.replace(/\[[^\]]*\]$/,"");export function usesResponses(e){const t=e.endpointTypes??[];return"gpt"===o(e.id)?0===t.length||t.includes(l):t.length>0&&!t.includes(u)&&t.includes(l)}function f(e){const t=e.endpointTypes;return!t||0===t.length||t.includes(u)||t.includes(l)}export function modelEntry(e,t,n,s=!1){const a=e.capabilities??{},p=usesResponses(e),u=o(e.id),l={id:e.id,name:s?e.id:e.name??i(e.id),vendor:r,url:p?d(t):`${d(t)}/chat/completions`,apiKey:n};p&&(l.api="openai-responses");const c=a.contextWindow??e.contextWindow;c&&(l.maxInputTokens=c);const f=a.maxOutput??e.maxOutputTokens;return f&&(l.maxOutputTokens=f),l.supportsToolCall=a.toolCall??!0,l.supportsImages=a.vision??"other"!==u,void 0!==a.reasoning&&(l.supportsReasoning=a.reasoning),a.reasoning&&a.reasoningEfforts&&(l.reasoning={...a.defaultReasoningEffort?{defaultEffort:a.defaultReasoningEffort}:{},supportedEfforts:a.reasoningEfforts}),l}export function menuSpecs(e,t){let r=n("codebuddy",e?.clientModels,e?.clientPersonal).filter(f);if(e){const n=new Set(e.models);r=r.filter(e=>n.has(e.id)),!r.some(e=>e.id===t)&&n.has(t)&&(r=[{id:t},...r])}else r.some(e=>e.id===t)||(r=[{id:t},...r]);const o=(e?.clientPersonal??[]).length>0,i=new Set,a=r.filter(e=>{if(o)return!0;const r=s([e.id])[0],n=!i.has(r);return i.add(r),e.id===t||!0===e.recommended||n}),p=a.findIndex(e=>e.id===t);return p>0?[a[p],...a.slice(0,p),...a.slice(p+1)]:a}export function mergeEntries(e,t,r,n,o=!1){const i=new Set(t.map(e=>e.id)),s=[],a=e.filter(e=>{if(isOurEntry(e))return!1;const t=c(e)&&"string"==typeof e.id?e.id:void 0;return!t||!i.has(t)||(s.push(t),!1)});return{entries:[...t.map(e=>modelEntry(e,r,n,o)),...a],replaced:s}}export function foreignIdsReplaced(e,t){const r=new Set(t.map(e=>e.id));return e.filter(e=>!isOurEntry(e)).filter(e=>c(e)&&"string"==typeof e.id&&r.has(e.id)).map(e=>String(e.id))}export function ourEntries(e){return e.filter(isOurEntry)}export function ourApiKey(e){const t=ourEntries(e)[0]?.apiKey;return"string"==typeof t&&t.trim()?t:null}
@@ -0,0 +1 @@
1
+ import{existsSync as e,readFileSync as t}from"fs";import{join as o}from"path";import{logger as r}from"../../utils/logger.js";import{i18n as d}from"../i18n.js";import{getToolDefaultModel as n}from"../model-registry.js";import{prettyModelName as i,vendorNames as s}from"../gateway-models.js";import{backupBeforeWrite as a,atomicWriteFile as l}from"./backup.js";import{CUSTOM_MODEL_PREFIX as c,bareModelId as u,foreignIdsReplaced as m,isOurEntry as p,menuSpecs as g,mergeEntries as f,ourApiKey as y,ourEntries as b,readModelsFile as h,writeModelsFile as j}from"./codebuddy-models.js";import{pickModel as C,toolHome as v}from"./types.js";const S=()=>process.env.CODEBUDDY_CONFIG_DIR?.trim()||o(v(),".codebuddy"),w=()=>o(S(),"models.json"),E=()=>o(S(),"settings.json"),N={command:"codebuddy",npmPackage:"@tencent-ai/codebuddy-code",brew:"codebuddy-code"};function P(){if(!e(E()))return{};const o=t(E(),"utf-8");if(!o.trim())return{};let r;try{r=JSON.parse(o)}catch(e){throw new Error(`Existing ${E()} cannot be parsed; back it up and fix it first: ${e instanceof Error?e.message:String(e)}`)}if(!(d=r)||"object"!=typeof d||Array.isArray(d))throw new Error(`Existing ${E()} must hold a JSON object`);var d;return r}function $(e){a(E()),l(E(),`${JSON.stringify(e,null,2)}\n`,384)}function _(e,t){return"string"==typeof e&&e.startsWith(c)&&t.has(e.slice(c.length))}const k=e=>u(C(e.models,n("codebuddy")));function x(e,t){return e.find(e=>e.id===t)??e[0]}let A=null;function O(e,t){const o=h(w()),{entries:r,replaced:d}=f(o.entries,t,e.baseUrl,e.apiKey);return j(w(),o,r),d}export const codebuddyAdapter={name:"codebuddy",displayName:"CodeBuddy Code",command:"codebuddy",installCommand:`npm install -g ${N.npmPackage}`,installSpec:N,get configPath(){return w()},wantsModelCatalog:!0,loadPrivateConfig(e){const t=k(e),o=g(e.catalog,t),r=P(),d=O(e,o),n=x(o,t);n&&(r.model=`${c}${n.id}`,$(r));const a=e=>e.name??i(e.id);A={names:o.map(a),vendors:s(o.map(e=>e.id)),defaultName:n?a(n):"",replaced:d}},unloadPrivateConfig(){let e;try{e=h(w())}catch(e){return void r.logError("codebuddyAdapter.unloadPrivateConfig",e)}const t=new Set(b(e.entries).map(e=>String(e.id)));t.size>0&&j(w(),e,e.entries.filter(e=>!p(e)));try{const e=P();_(e.model,t)&&(delete e.model,$(e))}catch(e){r.logError("codebuddyAdapter.unloadPrivateConfig",e)}},detectCurrentConfig(){try{return{apiKey:y(h(w()).entries)}}catch{return{apiKey:null}}},listedModels(){try{const e=b(h(w()).entries);return e.length>0?e.map(e=>String(e.id)):null}catch{return null}},refreshModelMenu(e){const t=h(w()),o=new Set(b(t.entries).map(e=>String(e.id))),r=P(),d=_(r.model,o)?String(r.model).slice(c.length):void 0,n=d&&e.catalog.models.includes(d)?d:k(e),i=g(e.catalog,n);O(e,i);const s=x(i,n);if(s&&(void 0===r.model||_(r.model,o))){const e=`${c}${s.id}`;r.model!==e&&(r.model=e,$(r))}},planNotes(){try{const e=h(w()),t=m(e.entries,g(void 0,n("codebuddy")));return t.length>0?[d.t("tools.codebuddy.replaces_models",{path:w(),list:t.join(d.t("tools.codebuddy.list_separator"))})]:[]}catch{return[]}},applyNotes(){if(!A)return[];const e=[{kind:"summary",text:d.t("tools.codebuddy.menu_written",{count:String(A.names.length),list:A.vendors.join(d.t("tools.codebuddy.list_separator")),default:A.defaultName})}];return A.replaced.length>0&&e.push({kind:"detail",text:d.t("tools.codebuddy.replaced_models",{tool:"codebuddy",list:A.replaced.join(d.t("tools.codebuddy.list_separator"))})}),e},backupPaths:()=>[w(),E()],forceResetPaths:()=>[w()],getConfig(){try{return{models:h(w()).entries,settings:P()}}catch(e){return r.logError("codebuddyAdapter.getConfig",e),null}}};
@@ -1 +1 @@
1
- import{spawnSync as t}from"child_process";import{existsSync as o,mkdtempSync as e,readFileSync as n,realpathSync as i,rmSync as r,statSync as s,writeFileSync as c}from"fs";import{tmpdir as l}from"os";import{delimiter as u,dirname as a,isAbsolute as d,join as p}from"path";import*as f from"@iarna/toml";import{fileURLToPath as m}from"url";import{logger as _}from"../../utils/logger.js";import{getCodexRules as x,compareVersions as g}from"../model-registry.js";import{autoCompactTokens as h,modelBlurb as w,prettyModelName as y}from"../gateway-models.js";import{codexHome as b,toolHome as v}from"./types.js";import{brandEnv as C,CLI_NAME as M,PROVIDER_KEY as j}from"../brand.js";const A=a(m(import.meta.url));export const CODEX_CATALOG_FILE=`${j}-model-catalog.json`;export const codexCatalogPath=()=>p(b(),CODEX_CATALOG_FILE);function O(){const t=C("CODEX_BIN");if(void 0!==t)return t.trim()?[t.trim()]:[];const o=["codex"];if("win32"===process.platform){const t=process.env.LOCALAPPDATA||p(v(),"AppData","Local");o.push(p(t,"Programs","OpenAI","Codex","bin","codex.exe"))}else o.push(p(v(),".local","bin","codex"));if("darwin"===process.platform)for(const t of["/Applications",p(v(),"Applications")])o.push(p(t,"ChatGPT.app/Contents/Resources/codex-cli/bin/codex")),o.push(p(t,"Codex.app/Contents/Resources/codex"));return o}function E(t){return!!t&&"object"==typeof t&&!Array.isArray(t)}function $(t){try{const o=JSON.parse(t),e=E(o)&&Array.isArray(o.models)?o.models.filter(E):[];return e.length>0?e:null}catch{return null}}function k(o,e,n){const i={encoding:"utf-8",timeout:2e4,maxBuffer:67108864,windowsHide:!0,stdio:["ignore","pipe","pipe"],...n?{env:n}:{}};return"win32"!==process.platform||"codex"!==o&&!/\.cmd$/i.test(o)?t(o,e,i):t(["codex"===o?"codex":`"${o}"`,...e].join(" "),{...i,shell:!0})}function P(t){const o=k(t,["debug","models","--bundled"]);if(0===o.status&&o.stdout){const t=$(o.stdout);if(t)return t}return(o.error||0!==o.status)&&_.logError("loadBundledCodexModels",o.error??new Error(`${t} exited ${o.status}`)),null}export function loadBundledCodexModels(t){if(t)return P(t);for(const t of O()){if("codex"!==t&&!o(t))continue;const e=P(t);if(e)return e}return null}function B(t){try{return s(t).isFile()}catch{return!1}}export function installedCodexBinaries(){const t=[],o=O();if(o.includes("codex")){const o="win32"===process.platform?["codex.exe","codex.cmd"]:["codex"];for(const e of(process.env.PATH??"").split(u))if(e&&d(e))for(const n of o)t.push(p(e,n))}t.push(...o.filter(t=>"codex"!==t));const e=new Set,n=[];for(const o of t){if(!B(o))continue;let t=o;try{t=i(o)}catch{}const r="win32"===process.platform?t.toLowerCase():t;e.has(r)||(e.add(r),n.push(o))}return n}export function codexBinaryVersion(t){const o=`${k(t,["--version"]).stdout??""}`.match(/(\d+)\.(\d+)\.(\d+)/);return o?o[0]:null}export function catalogRejections(t,o=installedCodexBinaries()){if(0===o.length)return[];const n=e(p(l(),`${M}-codex-`)),i=[];try{c(p(n,"config.toml"),f.stringify({model_catalog_json:t}));for(const t of o){const o=k(t,["debug","models"],{...process.env,CODEX_HOME:n});if(0===o.status)continue;const e=`${o.stderr??""}\n${o.stdout??""}`,r=e.split(/\r?\n/).find(t=>t.includes("model_catalog_json"));r?i.push({bin:t,version:codexBinaryVersion(t),error:r.trim()}):_.logError("catalogRejections",o.error??new Error(`${t} exited ${o.status}: ${e.trim().slice(0,500)}`))}}finally{r(n,{recursive:!0,force:!0})}return i}export function loadPreviousCodexModels(){const t=L()?.filter(t=>!S(t));return t&&t.length>0?t:null}export function previousGatewayModelIds(){return(L()??[]).filter(S).map(t=>String(t.slug))}function L(){return o(codexCatalogPath())?$(n(codexCatalogPath(),"utf-8")):null}function S(t){return"number"==typeof t.priority&&t.priority>=1e3}let T=null;function W(){if(null!==T)return T;const t=[p(A,"..","..","..","codex-base-instructions.md"),p(A,"..","..","codex-base-instructions.md"),p(A,"codex-base-instructions.md")],e=t.find(t=>o(t));if(!e)throw new Error(`codex-base-instructions.md not found, searched: ${t.join(", ")}`);return T=n(e,"utf-8"),T}function D(t){return"number"==typeof t&&Number.isFinite(t)&&t>0?t:void 0}function F(t,o,e,n){const i=e?t:Math.min(t,o);return{window:i,compact:h(i,n)}}function I(t,o,e,n){const{standardContextWindow:i}=x();let r=D(t.contextWindow)??i;n&&t.id.startsWith("claude-")&&(r=n.has(t.id)?Math.max(r,1e6):Math.min(r,2e5));const{window:s,compact:c}=F(r,i,e,D(t.autoCompactTokens));return{slug:t.id,display_name:t.name||y(t.id),description:w(t.description,{millionContext:s>=1e6})??null,supported_reasoning_levels:[],shell_type:"unified_exec",visibility:"list",supported_in_api:!0,priority:o,additional_speed_tiers:[],service_tiers:[],availability_nux:null,upgrade:null,model_messages:{instructions_template:W()},base_instructions:W(),supports_reasoning_summaries:!0,supports_parallel_tool_calls:!1,prefer_websockets:!1,include_skills_usage_instructions:!1,include_plugin_usage_instructions:!1,include_apps_usage_instructions:!1,default_reasoning_summary:"auto",support_verbosity:!1,default_verbosity:null,apply_patch_tool_type:null,web_search_tool_type:"text",truncation_policy:{mode:"bytes",limit:1e4},supports_image_detail_original:!1,context_window:s,max_context_window:s,auto_compact_token_limit:c,effective_context_window_percent:95,experimental_supported_tools:[],input_modalities:["text","image"],supports_search_tool:!1,supports_experimental_context:!1,use_responses_lite:!1,supports_reasoning_effort_updates:!1,node_repl_auto_review_required:!1,node_repl_disabled:!1}}const G={supports_parallel_tool_calls:!0,supports_reasoning_summaries:!0};export function fillFromOlderEntries(t,o){const e=new Map(o.map(t=>[t.slug,t])),n=new Map;for(const t of o)for(const[o,e]of Object.entries(t))n.has(o)||n.set(o,e);return t.map(t=>{const o=e.get(t.slug),i={...t};for(const[t,e]of n)t in i||(i[t]=o&&t in o?o[t]:e);return i})}function R(t,o,e){if("list"!==(t=function(t){const o=Object.keys(G).filter(o=>!(o in t));return 0===o.length?t:{...t,...Object.fromEntries(o.map(t=>[t,G[t]]))}}(t)).visibility)return t;const n=D(t.context_window);if(!n)return t;const i=D(t.max_context_window)??n,r=e?Math.min(D(o?.contextWindow)??i,i):n,{window:s,compact:c}=F(r,n,!0,D(o?.autoCompactTokens));return{...t,context_window:s,auto_compact_token_limit:c}}function X(t,o){if(!t.startsWith("gpt-"))return;let e,n=4;for(const i of o){const o="string"==typeof i.slug?i.slug:"";if(!o.startsWith("gpt-")||"list"!==i.visibility)continue;let r=0;for(;r<o.length&&o[r]===t[r];)r++;r>n&&(e=i,n=r)}return e}function H(t,o,e,n){return R({...t,...Object.fromEntries(["slug","display_name","description","priority"].map(t=>[t,o[t]])),upgrade:null,availability_nux:null},e,n)}export function buildCodexCatalog(t){const{bundled:o,specs:e,oneMillion:n,selectedModel:i}=t,r=t.claudeOneMillion?new Set(t.claudeOneMillion):void 0,s=t.keyModels?new Set(t.keyModels):null,c=new Set(t.gatewayAvailable),l=t=>!s||s.has(t)||t===i,u=t=>c.has(t)||t===i,a=new Map(e.map(t=>[t.id,t])),d=[],p=new Set;for(const t of o){const o="string"==typeof t.slug?t.slug:"";o&&!p.has(o)&&("list"!==t.visibility||l(o))&&(p.add(o),d.push(R(t,a.get(o),n)))}const f=[...e];i&&!a.has(i)&&f.push({id:i});const m=function(t){const o=new Map;for(const e of t){const t=/^claude-([a-z]+)-(.+)$/.exec(e);if(!t)continue;const n=t[2].split("-").filter(t=>/^\d{1,2}$/.test(t)).join("."),i=o.get(t[1]);(!i||g(n,i.version)>0)&&o.set(t[1],{id:e,version:n})}return new Set([...o.values()].map(t=>t.id))}(f.map(t=>t.id).filter(u));for(const t of f){if(p.has(t.id)||!u(t.id))continue;if(t.id.startsWith("claude-")&&!m.has(t.id)&&t.id!==i)continue;p.add(t.id);const e=I(t,1e3+d.length,n,r),s=X(t.id,o);d.push(s?H(s,e,t,n):e)}return{models:d}}
1
+ import{spawnSync as t}from"child_process";import{existsSync as o,mkdtempSync as e,readFileSync as n,realpathSync as i,rmSync as s,statSync as r,writeFileSync as c}from"fs";import{tmpdir as l}from"os";import{delimiter as u,dirname as a,isAbsolute as d,join as p}from"path";import*as f from"@iarna/toml";import{fileURLToPath as m}from"url";import{logger as _}from"../../utils/logger.js";import{getCodexRules as x,compareVersions as g}from"../model-registry.js";import{autoCompactTokens as h,modelBlurb as w,prettyModelName as y}from"../gateway-models.js";import{codexHome as b,toolHome as v}from"./types.js";import{brandEnv as C,CLI_NAME as M,PROVIDER_KEY as j}from"../brand.js";const A=a(m(import.meta.url));export const CODEX_CATALOG_FILE=`${j}-model-catalog.json`;export const codexCatalogPath=()=>p(b(),CODEX_CATALOG_FILE);function O(){const t=C("CODEX_BIN");if(void 0!==t)return t.trim()?[t.trim()]:[];const o=["codex"];if("win32"===process.platform){const t=process.env.LOCALAPPDATA||p(v(),"AppData","Local");o.push(p(t,"Programs","OpenAI","Codex","bin","codex.exe"))}else o.push(p(v(),".local","bin","codex"));if("darwin"===process.platform)for(const t of["/Applications",p(v(),"Applications")])o.push(p(t,"ChatGPT.app/Contents/Resources/codex-cli/bin/codex")),o.push(p(t,"Codex.app/Contents/Resources/codex"));return o}function E(t){return!!t&&"object"==typeof t&&!Array.isArray(t)}function $(t){try{const o=JSON.parse(t),e=E(o)&&Array.isArray(o.models)?o.models.filter(E):[];return e.length>0?e:null}catch{return null}}function k(o,e,n){const i={encoding:"utf-8",timeout:2e4,maxBuffer:67108864,windowsHide:!0,stdio:["ignore","pipe","pipe"],...n?{env:n}:{}};return"win32"!==process.platform||"codex"!==o&&!/\.cmd$/i.test(o)?t(o,e,i):t(["codex"===o?"codex":`"${o}"`,...e].join(" "),{...i,shell:!0})}function P(t){const o=k(t,["debug","models","--bundled"]);if(0===o.status&&o.stdout){const t=$(o.stdout);if(t)return t}return(o.error||0!==o.status)&&_.logError("loadBundledCodexModels",o.error??new Error(`${t} exited ${o.status}`)),null}export function loadBundledCodexModels(t){if(t)return P(t);for(const t of O()){if("codex"!==t&&!o(t))continue;const e=P(t);if(e)return e}return null}function S(t){try{return r(t).isFile()}catch{return!1}}export function installedCodexBinaries(){const t=[],o=O();if(o.includes("codex")){const o="win32"===process.platform?["codex.exe","codex.cmd"]:["codex"];for(const e of(process.env.PATH??"").split(u))if(e&&d(e))for(const n of o)t.push(p(e,n))}t.push(...o.filter(t=>"codex"!==t));const e=new Set,n=[];for(const o of t){if(!S(o))continue;let t=o;try{t=i(o)}catch{}const s="win32"===process.platform?t.toLowerCase():t;e.has(s)||(e.add(s),n.push(o))}return n}export function codexBinaryVersion(t){const o=`${k(t,["--version"]).stdout??""}`.match(/(\d+)\.(\d+)\.(\d+)/);return o?o[0]:null}export function catalogRejections(t,o=installedCodexBinaries()){if(0===o.length)return[];const n=e(p(l(),`${M}-codex-`)),i=[];try{c(p(n,"config.toml"),f.stringify({model_catalog_json:t}));for(const t of o){const o=k(t,["debug","models"],{...process.env,CODEX_HOME:n});if(0===o.status)continue;const e=`${o.stderr??""}\n${o.stdout??""}`,s=e.split(/\r?\n/).find(t=>t.includes("model_catalog_json"));s?i.push({bin:t,version:codexBinaryVersion(t),error:s.trim()}):_.logError("catalogRejections",o.error??new Error(`${t} exited ${o.status}: ${e.trim().slice(0,500)}`))}}finally{s(n,{recursive:!0,force:!0})}return i}export function loadPreviousCodexModels(){const t=B()?.filter(t=>!L(t));return t&&t.length>0?t:null}export function previousGatewayModelIds(){return(B()??[]).filter(L).map(t=>String(t.slug))}function B(){return o(codexCatalogPath())?$(n(codexCatalogPath(),"utf-8")):null}function L(t){return"number"==typeof t.priority&&t.priority>=1e3}let W=null;function T(){if(null!==W)return W;const t=[p(A,"..","..","..","codex-base-instructions.md"),p(A,"..","..","codex-base-instructions.md"),p(A,"codex-base-instructions.md")],e=t.find(t=>o(t));if(!e)throw new Error(`codex-base-instructions.md not found, searched: ${t.join(", ")}`);return W=n(e,"utf-8"),W}function D(t){return"number"==typeof t&&Number.isFinite(t)&&t>0?t:void 0}function G(t,o,e,n){const i=e?t:Math.min(t,o);return{window:i,compact:h(i,n)}}function F(t,o,e,n){const{standardContextWindow:i}=x();let s=D(t.contextWindow)??i;n&&t.id.startsWith("claude-")&&(s=n.has(t.id)?Math.max(s,1e6):Math.min(s,2e5));const{window:r,compact:c}=G(s,i,e,D(t.autoCompactTokens));return{slug:t.id,display_name:t.name||y(t.id),description:w(t.description,{millionContext:r>=1e6})??null,supported_reasoning_levels:[],shell_type:"unified_exec",visibility:"list",supported_in_api:!0,priority:o,additional_speed_tiers:[],service_tiers:[],availability_nux:null,upgrade:null,model_messages:{instructions_template:T()},base_instructions:T(),supports_reasoning_summaries:!0,supports_parallel_tool_calls:!1,prefer_websockets:!1,include_skills_usage_instructions:!1,include_plugin_usage_instructions:!1,include_apps_usage_instructions:!1,default_reasoning_summary:"auto",support_verbosity:!1,default_verbosity:null,apply_patch_tool_type:null,web_search_tool_type:"text",truncation_policy:{mode:"bytes",limit:1e4},supports_image_detail_original:!1,context_window:r,max_context_window:r,auto_compact_token_limit:c,effective_context_window_percent:95,experimental_supported_tools:[],input_modalities:["text","image"],supports_search_tool:!1,supports_experimental_context:!1,use_responses_lite:!1,supports_reasoning_effort_updates:!1,node_repl_auto_review_required:!1,node_repl_disabled:!1}}const I={supports_parallel_tool_calls:!0,supports_reasoning_summaries:!0};export function fillFromOlderEntries(t,o){const e=new Map(o.map(t=>[t.slug,t])),n=new Map;for(const t of o)for(const[o,e]of Object.entries(t))n.has(o)||n.set(o,e);return t.map(t=>{const o=e.get(t.slug),i={...t};for(const[t,e]of n)t in i||(i[t]=o&&t in o?o[t]:e);return i})}function R(t,o,e){if("list"!==(t=function(t){const o=Object.keys(I).filter(o=>!(o in t));return 0===o.length?t:{...t,...Object.fromEntries(o.map(t=>[t,I[t]]))}}(t)).visibility)return t;const n=D(t.context_window);if(!n)return t;const i=D(t.max_context_window)??n,s=e?Math.min(D(o?.contextWindow)??i,i):n,{window:r,compact:c}=G(s,n,!0,D(o?.autoCompactTokens));return{...t,context_window:r,auto_compact_token_limit:c}}function X(t,o){if(!t.startsWith("gpt-"))return;let e,n=4;for(const i of o){const o="string"==typeof i.slug?i.slug:"";if(!o.startsWith("gpt-")||"list"!==i.visibility)continue;let s=0;for(;s<o.length&&o[s]===t[s];)s++;s>n&&(e=i,n=s)}return e}function H(t,o,e,n){return R({...t,...Object.fromEntries(["slug","display_name","description","priority"].map(t=>[t,o[t]])),upgrade:null,availability_nux:null},e,n)}export function buildCodexCatalog(t){const{bundled:o,specs:e,oneMillion:n,selectedModel:i}=t,s=t.claudeOneMillion?new Set(t.claudeOneMillion):void 0,r=t.keyModels?new Set(t.keyModels):null,c=new Set(t.gatewayAvailable),l=t=>!r||r.has(t)||t===i,u=t=>c.has(t)||t===i,a=new Map(e.map(t=>[t.id,t])),d=t.chosenGpt?new Set(t.chosenGpt):null,p=t=>!!d&&t.startsWith("gpt-")&&!d.has(t)&&t!==i,f=[],m=new Set;for(const t of o){const o="string"==typeof t.slug?t.slug:"";o&&!m.has(o)&&("list"!==t.visibility||l(o)&&!p(o))&&(m.add(o),f.push(R(t,a.get(o),n)))}const _=[...e];i&&!a.has(i)&&_.push({id:i});const x=function(t){const o=new Map;for(const e of t){const t=/^claude-([a-z]+)-(.+)$/.exec(e);if(!t)continue;const n=t[2].split("-").filter(t=>/^\d{1,2}$/.test(t)).join("."),i=o.get(t[1]);(!i||g(n,i.version)>0)&&o.set(t[1],{id:e,version:n})}return new Set([...o.values()].map(t=>t.id))}(_.map(t=>t.id).filter(u));for(const t of _){if(m.has(t.id)||!u(t.id))continue;if(t.id.startsWith("claude-")&&!x.has(t.id)&&t.id!==i)continue;m.add(t.id);const e=F(t,1e3+f.length,n,s),r=X(t.id,o);f.push(r?H(r,e,t,n):e)}return{models:f}}
@@ -1 +1 @@
1
- import{createHash as e}from"crypto";import{existsSync as t,mkdirSync as o,readdirSync as r,readFileSync as n,rmSync as s,statSync as i,writeFileSync as l}from"fs";import{join as a}from"path";import*as d from"@iarna/toml";import{logger as c}from"../../utils/logger.js";import{i18n as u}from"../i18n.js";import{backupBeforeWrite as p,atomicWriteFile as m}from"./backup.js";import{codexHome as f,pickModel as _,toolHome as g,withV1 as x}from"./types.js";import{moveSessionsToProvider as h,NO_STATE_DB as y,runningCodexPids as k}from"../codex-sessions.js";import{codexFormat as b,codexRolloutFiles as v}from"../sessions/formats.js";import{getGatewayModelRules as w,getToolDefaultModel as j}from"../model-registry.js";import{ownsValue as S,takeField as C}from"../written-values.js";import{configManager as O}from"../config.js";import{maskHome as M,track as A}from"../telemetry.js";import{buildCodexCatalog as E,catalogRejections as N,codexCatalogPath as P,fillFromOlderEntries as T,installedCodexBinaries as D,loadBundledCodexModels as $,loadPreviousCodexModels as I,previousGatewayModelIds as L}from"./codex-catalog.js";import{gatewayModelSpecs as J,modelFamily as G}from"../gateway-models.js";import{isOurGatewayUrl as R,noteWrittenGatewayUrl as K}from"../gateway-addresses.js";import{findInstalls as X,mirrorInstallCommand as B,brandInstallScripts as U}from"./tool-installs.js";import{chatgptDesktopApp as W}from"./chatgpt-desktop.js";const q=()=>f(),z=()=>a(q(),"config.toml"),Y="sessions_move_declined",F=["browser_use","browser_use_external","computer_use"],H="desktop_features_restored";function Q(e){if(!0===O.getToolSetting("codex",H))return!1;const t=e.features,o=de(t)&&F.every(e=>!1===t[e]);if(O.setToolSetting("codex",H,!0),!o)return!1;for(const e of F)delete t[e];return!0}export function codexWorkModeOn(){try{const e=ue();return e.model_provider===te&&de(e.desktop)&&"STEPS_PROSE"===e.desktop.conversationDetailMode}catch{return!1}}function V(){try{if(de(ue().desktop))return!0}catch{}if("darwin"===process.platform)return["/Applications",a(g(),"Applications")].some(e=>["ChatGPT.app","Codex.app"].some(o=>t(a(e,o))));if("win32"===process.platform){const e=a(process.env.LOCALAPPDATA||a(g(),"AppData","Local"),"Packages");try{return r(e).some(e=>/^OpenAI\.(Codex|ChatGPT)/i.test(e))}catch{return!1}}return t("/usr/lib/chatgpt/ChatGPT")}export function codexConfigPath(){return z()}const Z=()=>a(q(),"auth.json"),ee="OPENAI_API_KEY",te="custom",oe="high",re=["gpt-5.5","gpt-5.6-sol","gpt-6-astra"],ne=["high","xhigh"],se={goals:!0,js_repl:!1};let ie=[];const le=1e6,ae=9e5;export const CODEX_ONE_MILLION_CONTEXT_SETTING="one_million_context";function de(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function ce(e,t){return de(e[t])||(e[t]={}),e[t]}function ue(){if(!t(z()))return{};const e=n(z(),"utf-8");if(!e.trim())return{};try{const t=d.parse(e);if(!de(t))throw new Error("config.toml root must be a TOML table");return t}catch(e){throw new Error(`Existing ~/.codex/config.toml cannot be parsed; back it up and fix it first: ${e instanceof Error?e.message:String(e)}`)}}function pe(){if(!t(Z()))return{};try{const e=JSON.parse(n(Z(),"utf-8"));return de(e)?e:{}}catch{return{}}}let me=null;function fe(e){const t=e.profiles;if(de(t)){for(const[e,o]of Object.entries(t))de(o)&&2===Object.keys(o).length&&o.model_provider===te&&o.model===e&&delete t[e];0===Object.keys(t).length&&delete e.profiles}}let _e=null;const ge=()=>a(O.getConfigDir(),"codex-catalog-check.json");function xe(e){const o=P();t(o)&&n(o,"utf-8")===e||(p(o),m(o,e))}function he(t,r){if(0===r.length)return[];const s=function(t,o){const r=e("sha256").update(t);for(const e of o)try{const t=i(e);r.update(`\0${e}\0${t.size}\0${t.mtimeMs}`)}catch{r.update(`\0${e}`)}return r.digest("hex")}(t,r);if(function(e){try{return JSON.parse(n(ge(),"utf-8")).signature===e}catch{return!1}}(s))return[];const a=N(P(),r);return 0===a.length&&function(e){try{o(O.getConfigDir(),{recursive:!0}),l(ge(),JSON.stringify({signature:e})+"\n")}catch(e){c.logError("codexAdapter.rememberAccepted",e)}}(s),a}function ye(e,t,o){const r=!1!==t.settings?.one_million_context;!function(e){e.model_context_window===le&&delete e.model_context_window,e.model_auto_compact_token_limit===ae&&delete e.model_auto_compact_token_limit}(e);const n=()=>{e.model_catalog_json===P()&&delete e.model_catalog_json,r&&(e.model_context_window=le,e.model_auto_compact_token_limit=ae)},i=$()??I();if(!i)return c.logError("codexAdapter.writeModelCatalog",new Error("no Codex binary found; model catalog skipped")),_e="skipped",void n();const l=t.catalog,a=e=>E({bundled:e,specs:J("codex",l?.clientModels),...l?{keyModels:l.models}:{},gatewayAvailable:l?.models??L(),oneMillion:r,selectedModel:o,..."gateway"===l?.oneMillionSource?{claudeOneMillion:l.oneMillion}:{}}),d=e=>JSON.stringify(e,null,2)+"\n";let u=a(i);xe(d(u));const p=D(),m=he(d(u),p);if(m.length>0){const e=Date.now();let t=!1;for(const e of m){const o=$(e.bin);if(o){for(const e of[{models:T(u.models,o)},{models:T(a(o).models,o)}])if(xe(d(e)),0===he(d(e),p).length){u=e,t=!0;break}if(t)break}}if(A("codex-catalog",t?"fallback":"fail",{duration_ms:Date.now()-e,error:m[0].error,detail:{rejected_by:m.map(e=>({version:e.version,path:M(e.bin)}))}}),!t)return _e={rejectedBy:m[0]},s(P(),{force:!0}),void n()}_e={listed:u.models.filter(e=>"list"===e.visibility).map(e=>({id:String(e.slug),name:String(e.display_name??e.slug)}))},e.model_catalog_json=P()}export function codexCatalogRejection(){let e;try{e=ue()}catch{return null}return e.model_catalog_json===P()&&t(P())?N(P())[0]??null:null}export function setCodexOneMillionContext(e,t){const o=ue(),r=d.stringify(o),n="string"==typeof o.model?o.model:j("codex");ye(o,{settings:{[CODEX_ONE_MILLION_CONTEXT_SETTING]:e},catalog:t},n);const s=d.stringify(o);s!==r&&(p(z()),m(z(),s))}const ke={command:"codex",npmPackage:"@openai/codex",native:{binDir:"win32"===process.platform?["AppData","Local","Programs","OpenAI","Codex","bin"]:[".local","bin"],updateArgs:["update"],updateTimeoutMs:12e4,dataDirs:[[".codex","packages","standalone"]]},mirrorScript:U("codex"),brew:"codex"};function be(e){const t=de(e.model_providers)?e.model_providers[te]:void 0;if(!de(t))return null;const o="string"==typeof t.base_url?t.base_url.trim():"";return o&&!R(o)?o:null}let ve=null;function we(){if("skipped"===_e)return 0===X(ke).length?[]:[{kind:"action",text:u.t("tools.codex.catalog_skipped")}];if(!_e)return[];if("rejectedBy"in _e){const{bin:e,version:t}=_e.rejectedBy;return[{kind:"action",text:u.t("tools.codex.catalog_rejected",{path:e,version:t??"?"})}]}const e=new Map;for(const t of _e.listed)e.set(G(t.id),(e.get(G(t.id))??0)+1);const t=["gpt","claude","gemini","other","grok"].filter(t=>e.has(t)).map(t=>`${u.t(`tools.model_family.${t}`)} ${e.get(t)}`).join(" · ");return[{kind:"summary",text:u.t("tools.codex.catalog_written",{count:String(_e.listed.length),breakdown:t})},{kind:"detail",text:_e.listed.map(e=>e.name).join(", ")},...codexWorkModeOn()||V()?[{kind:"action",text:u.t(codexWorkModeOn()?"tools.codex.work_mode_on":"tools.codex.work_mode_hint")}]:[]]}export const codexAdapter={name:"codex",companionApps:[W],displayName:"Codex",command:"codex",installCommand:B(ke),installSpec:ke,configPath:z(),sessions:{format:b,files:()=>[...v(a(f(),"sessions")),...v(a(f(),"archived_sessions"))],resumeCommand:e=>({command:"codex",args:["resume",e]})},wantsModelCatalog:!0,listedModels(){if(ue().model_catalog_json!==P())return null;try{return(JSON.parse(n(P(),"utf-8")).models??[]).filter(e=>"list"===e.visibility).map(e=>String(e.slug))}catch{return null}},refreshModelMenu(e){if(ue().model_catalog_json!==P())return;setCodexOneMillionContext(!1!==e.settings?.one_million_context,e.catalog);const t=ue(),o=function(e,t){const o=de(e.model_providers)?e.model_providers[te]:void 0;return!(!de(o)||o.base_url!==t||!0===o.supports_standalone_web_search||(o.supports_standalone_web_search=!0,0))}(t,x(e.baseUrl));(Q(t)||o)&&(p(z()),m(z(),d.stringify(t)))},async followUp(){if(ue().model_provider!==te)return null;const e=await h(te,{dryRun:!0}),t=Math.max(e.moved.length,e.dbRows);if(0===t)return null;const o=O.getToolSettings("codex")[Y];if("number"==typeof o&&t<=o)return null;const r={count:String(t)};return k().length>0?{hint:u.t("tools.codex.sessions_hidden_running",r)}:{prompt:u.t("tools.codex.sessions_offer",r),hint:u.t("tools.codex.sessions_hidden",r),async run(){const e=await h(te),t=[...new Set(e.moved.map(e=>e.from))].join("、")||"-",o=String(Math.max(e.moved.length,e.dbRows)),r=[{kind:"summary",text:u.t("codex_sessions.moved",{count:o,from:t,target:te})},{kind:"summary",text:u.t("codex_sessions.backup",{dir:e.backupDir??""})}];return e.dbSkipped&&e.dbSkipped!==y&&r.push({kind:"action",text:u.t("codex_sessions.db_skipped",{reason:e.dbSkipped})}),r},decline(){O.setToolSetting("codex",Y,t)}}},applyNotes(){const e=[];return ve&&e.push({kind:"summary",text:u.t("tools.codex.provider_replaced",{url:ve})}),ie.length>0&&e.push({kind:"summary",text:u.t("tools.codex.replaced_user_settings",{values:ie.join(", ")})}),[...e,...we()]},planNotes(){let e;try{e=ue()}catch{return[]}const t=[],o=be(e);return o?t.push(u.t("tools.codex.plan_replace_provider",{url:o})):"string"==typeof e.model_provider&&e.model_provider!==te&&t.push(u.t("tools.codex.plan_switch_provider",{provider:e.model_provider})),t},loadPrivateConfig(e){const t=j("codex"),o=_(e.models,t),r=function(e){return/(?:^|\/)claude(?:-|$)/i.test(e)}(o)?t:o,n=x(e.baseUrl),s=ue();ie=[];const i=w().retired,l=(e,t,o,r,n)=>{void 0===t||t===o||"string"==typeof t&&i.includes(t)||S(e,t,r)||ie.push(`${n} = ${String(t)}`),C(e,o)};l("codex.model",s.model,r,re,"model"),s.model=r,s.model_provider=te,l("codex.model_reasoning_effort",s.model_reasoning_effort,oe,ne,"model_reasoning_effort"),s.model_reasoning_effort=oe;const a="string"==typeof s.model?s.model:r;ye(s,e,a);const c=ce(s,"model_providers");ve=be(s),K(n);const u=de(c[te])?{...c[te]}:{};delete u.env_key;const{experimental_bearer_token:f,...g}=u;c[te]={...g,name:"custom",wire_api:"responses",requires_openai_auth:!0,supports_standalone_web_search:!0,base_url:n},fe(s),ce(ce(s,"tui"),"model_availability_nux")[a]=4;const h=ce(s,"features");for(const[e,t]of Object.entries(se))l(`codex.features.${e}`,void 0===h[e]?void 0:String(h[e]),String(t),[String(t)],`features.${e}`),h[e]=t;Q(s),p(z()),m(z(),d.stringify(s)),function(e){const t=e.trim();if(!t)return;const o={...pe(),auth_mode:"apikey",[ee]:t};p(Z()),m(Z(),JSON.stringify(o,null,2)+"\n",384)}(e.apiKey)},holdsOurConfig(e){const t=pe()[ee];return"string"==typeof t&&e.includes(t.trim())},unloadPrivateConfig(e){if(me=function(e){const t=pe(),o="string"==typeof t[ee]?t[ee].trim():"";if(!o)return de(t.tokens)?"chatgpt":null;if(!e.includes(o))return"other_key";const{[ee]:r,auth_mode:n,...i}=t;return p(Z()),de(i.tokens)?(m(Z(),JSON.stringify({...i,auth_mode:"chatgpt"},null,2)+"\n",384),"chatgpt"):(s(Z(),{force:!0}),"signed_out")}(e?.savedKeys??[]),!t(z()))return;let o;try{o=ue()}catch(e){return void c.logError("codexAdapter.unloadPrivateConfig",e)}const r=o.model_providers;de(r)&&de(r[te])&&R(r[te].base_url)&&de(r)&&(delete r[te],0===Object.keys(r).length&&delete o.model_providers,o.model_provider===te&&delete o.model_provider),o.model_catalog_json===P()&&delete o.model_catalog_json,Q(o),fe(o),p(z()),m(z(),d.stringify(o))},unloadNotes(){switch(me){case"chatgpt":return[{kind:"action",text:u.t("tools.codex.unload_chatgpt_restored")}];case"other_key":return[{kind:"action",text:u.t("tools.codex.unload_other_key")}];default:return[{kind:"action",text:u.t("tools.codex.unload_sign_in")}]}},detectCurrentConfig(){const e=pe()[ee];return{apiKey:"string"==typeof e&&e.trim()?e.trim():null}},getConfig(){try{return ue()}catch(e){return c.logError("codexAdapter.getConfig",e),null}},backupPaths:()=>[z(),Z(),P()]};export function codexAuthProblem(){try{const e=ue(),t=e.model_providers?.[te];if(e.model_provider!==te||!t)return null;if("string"==typeof t.experimental_bearer_token&&t.experimental_bearer_token)return"stale_bearer";const o=pe();return!0===t.requires_openai_auth&&"chatgpt"===o.auth_mode?"chatgpt_login":null}catch{return null}}
1
+ import{createHash as e}from"crypto";import{existsSync as t,mkdirSync as o,readdirSync as n,readFileSync as r,rmSync as i,statSync as s,writeFileSync as l}from"fs";import{join as d}from"path";import*as a from"@iarna/toml";import{logger as c}from"../../utils/logger.js";import{i18n as u}from"../i18n.js";import{backupBeforeWrite as p,atomicWriteFile as m}from"./backup.js";import{codexHome as f,pickModel as _,toolHome as g,withV1 as x}from"./types.js";import{moveSessionsToProvider as h,NO_STATE_DB as y,runningCodexPids as k}from"../codex-sessions.js";import{codexFormat as b,codexRolloutFiles as v}from"../sessions/formats.js";import{getGatewayModelRules as w,getToolDefaultModel as j}from"../model-registry.js";import{ownsValue as S,takeField as C}from"../written-values.js";import{configManager as O}from"../config.js";import{maskHome as M,track as A}from"../telemetry.js";import{buildCodexCatalog as E,catalogRejections as P,codexCatalogPath as N,fillFromOlderEntries as T,installedCodexBinaries as D,loadBundledCodexModels as $,loadPreviousCodexModels as I,previousGatewayModelIds as L}from"./codex-catalog.js";import{gatewayModelSpecs as J,modelFamily as G}from"../gateway-models.js";import{isOurGatewayUrl as R,noteWrittenGatewayUrl as K}from"../gateway-addresses.js";import{findInstalls as X,mirrorInstallCommand as B,brandInstallScripts as U}from"./tool-installs.js";import{chatgptDesktopApp as W}from"./chatgpt-desktop.js";const q=()=>f(),z=()=>d(q(),"config.toml"),Y="sessions_move_declined",F=["browser_use","browser_use_external","computer_use"],H="desktop_features_restored";function Q(e){if(!0===O.getToolSetting("codex",H))return!1;const t=e.features,o=ae(t)&&F.every(e=>!1===t[e]);if(O.setToolSetting("codex",H,!0),!o)return!1;for(const e of F)delete t[e];return!0}export function codexWorkModeOn(){try{const e=ue();return e.model_provider===te&&ae(e.desktop)&&"STEPS_PROSE"===e.desktop.conversationDetailMode}catch{return!1}}function V(){try{if(ae(ue().desktop))return!0}catch{}if("darwin"===process.platform)return["/Applications",d(g(),"Applications")].some(e=>["ChatGPT.app","Codex.app"].some(o=>t(d(e,o))));if("win32"===process.platform){const e=d(process.env.LOCALAPPDATA||d(g(),"AppData","Local"),"Packages");try{return n(e).some(e=>/^OpenAI\.(Codex|ChatGPT)/i.test(e))}catch{return!1}}return t("/usr/lib/chatgpt/ChatGPT")}export function codexConfigPath(){return z()}const Z=()=>d(q(),"auth.json"),ee="OPENAI_API_KEY",te="custom",oe="high",ne=["gpt-5.5","gpt-5.6-sol","gpt-6-astra"],re=["high","xhigh"],ie={goals:!0,js_repl:!1};let se=[];const le=1e6,de=9e5;export const CODEX_ONE_MILLION_CONTEXT_SETTING="one_million_context";function ae(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function ce(e,t){return ae(e[t])||(e[t]={}),e[t]}function ue(){if(!t(z()))return{};const e=r(z(),"utf-8");if(!e.trim())return{};try{const t=a.parse(e);if(!ae(t))throw new Error("config.toml root must be a TOML table");return t}catch(e){throw new Error(`Existing ~/.codex/config.toml cannot be parsed; back it up and fix it first: ${e instanceof Error?e.message:String(e)}`)}}function pe(){if(!t(Z()))return{};try{const e=JSON.parse(r(Z(),"utf-8"));return ae(e)?e:{}}catch{return{}}}let me=null;function fe(e){const t=e.profiles;if(ae(t)){for(const[e,o]of Object.entries(t))ae(o)&&2===Object.keys(o).length&&o.model_provider===te&&o.model===e&&delete t[e];0===Object.keys(t).length&&delete e.profiles}}let _e=null;const ge=()=>d(O.getConfigDir(),"codex-catalog-check.json");function xe(e){const o=N();t(o)&&r(o,"utf-8")===e||(p(o),m(o,e))}function he(t,n){if(0===n.length)return[];const i=function(t,o){const n=e("sha256").update(t);for(const e of o)try{const t=s(e);n.update(`\0${e}\0${t.size}\0${t.mtimeMs}`)}catch{n.update(`\0${e}`)}return n.digest("hex")}(t,n);if(function(e){try{return JSON.parse(r(ge(),"utf-8")).signature===e}catch{return!1}}(i))return[];const d=P(N(),n);return 0===d.length&&function(e){try{o(O.getConfigDir(),{recursive:!0}),l(ge(),JSON.stringify({signature:e})+"\n")}catch(e){c.logError("codexAdapter.rememberAccepted",e)}}(i),d}function ye(e,t,o){const n=!1!==t.settings?.one_million_context;!function(e){e.model_context_window===le&&delete e.model_context_window,e.model_auto_compact_token_limit===de&&delete e.model_auto_compact_token_limit}(e);const r=()=>{e.model_catalog_json===N()&&delete e.model_catalog_json,n&&(e.model_context_window=le,e.model_auto_compact_token_limit=de)},s=$()??I();if(!s)return c.logError("codexAdapter.writeModelCatalog",new Error("no Codex binary found; model catalog skipped")),_e="skipped",void r();const l=t.catalog,d=e=>E({bundled:e,specs:J("codex",l?.clientModels,l?.clientPersonal),...l?.clientPersonal?.includes("codex")?{chosenGpt:(l.clientModels?.codex??[]).filter(e=>!e.hidden).map(e=>e.id)}:{},...l?{keyModels:l.models}:{},gatewayAvailable:l?.models??L(),oneMillion:n,selectedModel:o,..."gateway"===l?.oneMillionSource?{claudeOneMillion:l.oneMillion}:{}}),a=e=>JSON.stringify(e,null,2)+"\n";let u=d(s);xe(a(u));const p=D(),m=he(a(u),p);if(m.length>0){const e=Date.now();let t=!1;for(const e of m){const o=$(e.bin);if(o){for(const e of[{models:T(u.models,o)},{models:T(d(o).models,o)}])if(xe(a(e)),0===he(a(e),p).length){u=e,t=!0;break}if(t)break}}if(A("codex-catalog",t?"fallback":"fail",{duration_ms:Date.now()-e,error:m[0].error,detail:{rejected_by:m.map(e=>({version:e.version,path:M(e.bin)}))}}),!t)return _e={rejectedBy:m[0]},i(N(),{force:!0}),void r()}_e={listed:u.models.filter(e=>"list"===e.visibility).map(e=>({id:String(e.slug),name:String(e.display_name??e.slug)}))},e.model_catalog_json=N()}export function codexCatalogRejection(){let e;try{e=ue()}catch{return null}return e.model_catalog_json===N()&&t(N())?P(N())[0]??null:null}export function setCodexOneMillionContext(e,t){const o=ue(),n=a.stringify(o),r="string"==typeof o.model?o.model:j("codex");ye(o,{settings:{[CODEX_ONE_MILLION_CONTEXT_SETTING]:e},catalog:t},r);const i=a.stringify(o);i!==n&&(p(z()),m(z(),i))}const ke={command:"codex",npmPackage:"@openai/codex",native:{binDir:"win32"===process.platform?["AppData","Local","Programs","OpenAI","Codex","bin"]:[".local","bin"],updateArgs:["update"],updateTimeoutMs:12e4,dataDirs:[[".codex","packages","standalone"]]},mirrorScript:U("codex"),brew:"codex"};function be(e){const t=ae(e.model_providers)?e.model_providers[te]:void 0;if(!ae(t))return null;const o="string"==typeof t.base_url?t.base_url.trim():"";return o&&!R(o)?o:null}let ve=null;function we(){if("skipped"===_e)return 0===X(ke).length?[]:[{kind:"action",text:u.t("tools.codex.catalog_skipped")}];if(!_e)return[];if("rejectedBy"in _e){const{bin:e,version:t}=_e.rejectedBy;return[{kind:"action",text:u.t("tools.codex.catalog_rejected",{path:e,version:t??"?"})}]}const e=new Map;for(const t of _e.listed)e.set(G(t.id),(e.get(G(t.id))??0)+1);const t=["gpt","claude","gemini","other","grok"].filter(t=>e.has(t)).map(t=>`${u.t(`tools.model_family.${t}`)} ${e.get(t)}`).join(" · ");return[{kind:"summary",text:u.t("tools.codex.catalog_written",{count:String(_e.listed.length),breakdown:t})},{kind:"detail",text:_e.listed.map(e=>e.name).join(", ")},...codexWorkModeOn()||V()?[{kind:"action",text:u.t(codexWorkModeOn()?"tools.codex.work_mode_on":"tools.codex.work_mode_hint")}]:[]]}export const codexAdapter={name:"codex",companionApps:[W],displayName:"Codex",command:"codex",installCommand:B(ke),installSpec:ke,configPath:z(),sessions:{format:b,files:()=>[...v(d(f(),"sessions")),...v(d(f(),"archived_sessions"))],resumeCommand:e=>({command:"codex",args:["resume",e]})},wantsModelCatalog:!0,listedModels(){if(ue().model_catalog_json!==N())return null;try{return(JSON.parse(r(N(),"utf-8")).models??[]).filter(e=>"list"===e.visibility).map(e=>String(e.slug))}catch{return null}},refreshModelMenu(e){if(ue().model_catalog_json!==N())return;setCodexOneMillionContext(!1!==e.settings?.one_million_context,e.catalog);const t=ue(),o=function(e,t){const o=ae(e.model_providers)?e.model_providers[te]:void 0;return!(!ae(o)||o.base_url!==t||!0===o.supports_standalone_web_search||(o.supports_standalone_web_search=!0,0))}(t,x(e.baseUrl));(Q(t)||o)&&(p(z()),m(z(),a.stringify(t)))},async followUp(){if(ue().model_provider!==te)return null;const e=await h(te,{dryRun:!0}),t=Math.max(e.moved.length,e.dbRows);if(0===t)return null;const o=O.getToolSettings("codex")[Y];if("number"==typeof o&&t<=o)return null;const n={count:String(t)};return k().length>0?{hint:u.t("tools.codex.sessions_hidden_running",n)}:{prompt:u.t("tools.codex.sessions_offer",n),hint:u.t("tools.codex.sessions_hidden",n),async run(){const e=await h(te),t=[...new Set(e.moved.map(e=>e.from))].join("、")||"-",o=String(Math.max(e.moved.length,e.dbRows)),n=[{kind:"summary",text:u.t("codex_sessions.moved",{count:o,from:t,target:te})},{kind:"summary",text:u.t("codex_sessions.backup",{dir:e.backupDir??""})}];return e.dbSkipped&&e.dbSkipped!==y&&n.push({kind:"action",text:u.t("codex_sessions.db_skipped",{reason:e.dbSkipped})}),n},decline(){O.setToolSetting("codex",Y,t)}}},applyNotes(){const e=[];return ve&&e.push({kind:"summary",text:u.t("tools.codex.provider_replaced",{url:ve})}),se.length>0&&e.push({kind:"summary",text:u.t("tools.codex.replaced_user_settings",{values:se.join(", ")})}),[...e,...we()]},planNotes(){let e;try{e=ue()}catch{return[]}const t=[],o=be(e);return o?t.push(u.t("tools.codex.plan_replace_provider",{url:o})):"string"==typeof e.model_provider&&e.model_provider!==te&&t.push(u.t("tools.codex.plan_switch_provider",{provider:e.model_provider})),t},loadPrivateConfig(e){const t=j("codex"),o=_(e.models,t),n=function(e){return/(?:^|\/)claude(?:-|$)/i.test(e)}(o)?t:o,r=x(e.baseUrl),i=ue();se=[];const s=w().retired,l=(e,t,o,n,r)=>{void 0===t||t===o||"string"==typeof t&&s.includes(t)||S(e,t,n)||se.push(`${r} = ${String(t)}`),C(e,o)};l("codex.model",i.model,n,ne,"model"),i.model=n,i.model_provider=te,l("codex.model_reasoning_effort",i.model_reasoning_effort,oe,re,"model_reasoning_effort"),i.model_reasoning_effort=oe;const d="string"==typeof i.model?i.model:n;ye(i,e,d);const c=ce(i,"model_providers");ve=be(i),K(r);const u=ae(c[te])?{...c[te]}:{};delete u.env_key;const{experimental_bearer_token:f,...g}=u;c[te]={...g,name:"custom",wire_api:"responses",requires_openai_auth:!0,supports_standalone_web_search:!0,base_url:r},fe(i),ce(ce(i,"tui"),"model_availability_nux")[d]=4;const h=ce(i,"features");for(const[e,t]of Object.entries(ie))l(`codex.features.${e}`,void 0===h[e]?void 0:String(h[e]),String(t),[String(t)],`features.${e}`),h[e]=t;Q(i),p(z()),m(z(),a.stringify(i)),function(e){const t=e.trim();if(!t)return;const o={...pe(),auth_mode:"apikey",[ee]:t};p(Z()),m(Z(),JSON.stringify(o,null,2)+"\n",384)}(e.apiKey)},holdsOurConfig(e){const t=pe()[ee];return"string"==typeof t&&e.includes(t.trim())},unloadPrivateConfig(e){if(me=function(e){const t=pe(),o="string"==typeof t[ee]?t[ee].trim():"";if(!o)return ae(t.tokens)?"chatgpt":null;if(!e.includes(o))return"other_key";const{[ee]:n,auth_mode:r,...s}=t;return p(Z()),ae(s.tokens)?(m(Z(),JSON.stringify({...s,auth_mode:"chatgpt"},null,2)+"\n",384),"chatgpt"):(i(Z(),{force:!0}),"signed_out")}(e?.savedKeys??[]),!t(z()))return;let o;try{o=ue()}catch(e){return void c.logError("codexAdapter.unloadPrivateConfig",e)}const n=o.model_providers;ae(n)&&ae(n[te])&&R(n[te].base_url)&&ae(n)&&(delete n[te],0===Object.keys(n).length&&delete o.model_providers,o.model_provider===te&&delete o.model_provider),o.model_catalog_json===N()&&delete o.model_catalog_json,Q(o),fe(o),p(z()),m(z(),a.stringify(o))},unloadNotes(){switch(me){case"chatgpt":return[{kind:"action",text:u.t("tools.codex.unload_chatgpt_restored")}];case"other_key":return[{kind:"action",text:u.t("tools.codex.unload_other_key")}];default:return[{kind:"action",text:u.t("tools.codex.unload_sign_in")}]}},detectCurrentConfig(){const e=pe()[ee];return{apiKey:"string"==typeof e&&e.trim()?e.trim():null}},getConfig(){try{return ue()}catch(e){return c.logError("codexAdapter.getConfig",e),null}},backupPaths:()=>[z(),Z(),N()]};export function codexAuthProblem(){try{const e=ue(),t=e.model_providers?.[te];if(e.model_provider!==te||!t)return null;if("string"==typeof t.experimental_bearer_token&&t.experimental_bearer_token)return"stale_bearer";const o=pe();return!0===t.requires_openai_auth&&"chatgpt"===o.auth_mode?"chatgpt_login":null}catch{return null}}
@@ -1 +1 @@
1
- import{existsSync as e,readFileSync as t}from"fs";import{join as o}from"path";import*as r from"@iarna/toml";import{logger as n}from"../../utils/logger.js";import{PROVIDER_KEY as i}from"../brand.js";import{backupBeforeWrite as s,atomicWriteFile as l}from"./backup.js";import{pickModel as a,toolHome as d,withV1 as m}from"./types.js";import{i18n as f}from"../i18n.js";import{getToolDefaultModel as g}from"../model-registry.js";import{gatewayModelSpecs as u,modelBlurb as c,modelFamily as p,prettyModelName as y}from"../gateway-models.js";import{brandInstallScripts as k,mirrorInstallCommand as b}from"./tool-installs.js";import{OFFICIAL_PLUGINS as h}from"./claude-plugins.js";const j=()=>o(o(d(),".grok"),"config.toml"),_=i,w=`${i}-`,A=["low","medium","high","xhigh"];let v=null;const C=e=>`${w}${e}`,M=e=>e===_||e.startsWith(w),x={command:"grok",npmPackage:"@xai-official/grok",npmMirrorTagStale:!0,mirrorScript:k("grok"),native:{binDir:[".grok","bin"],updateArgs:["update"],updateTimeoutMs:12e4,dataDirs:[[".grok","downloads"]]}};function S(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function E(e,t){return S(e[t])||(e[t]={}),e[t]}function O(){if(!e(j()))return{};const o=t(j(),"utf-8");if(!o.trim())return{};try{const e=r.parse(o);if(!S(e))throw new Error("config.toml root must be a TOML table");return e}catch(e){throw new Error(`Existing ~/.grok/config.toml cannot be parsed; back it up and fix it first: ${e instanceof Error?e.message:String(e)}`)}}function P(e){return S(e.model)?Object.entries(e.model).filter(e=>M(e[0])&&S(e[1])):[]}function N(e,t){let o=u("grok",e.catalog?.clientModels);if(e.catalog){const t=new Set(e.catalog.models);o=o.filter(e=>t.has(e.id))}return o.some(e=>e.id===t)?o:[{id:t},...o]}function $(e,t,o){E(e,"endpoints").models_base_url=m(t.baseUrl);const r=E(e,"model"),n=new Map(P(e));for(const e of n.keys())delete r[e];for(const e of o){const o=C(e.id),i={...n.get(o)??{},name:e.name??y(e.id),model:e.id,base_url:m(t.baseUrl),api_key:t.apiKey,context_window:e.contextWindow??5e5,api_backend:"responses",reasoning_summary:"concise"};"grok"===p(e.id)&&(i.supports_reasoning_effort=!0,i.reasoning_efforts=A);const s=c(e.description);s?i.description=s:delete i.description,r[o]=i}}export const grokAdapter={name:"grok",displayName:"Grok Build",command:"grok",installCommand:b(x),installSpec:x,configPath:j(),wantsModelCatalog:!0,loadPrivateConfig(e){const t=O(),o=a(e.models,g("grok")),n=N(e,o);$(t,e,n);const i=e=>e.name??y(e.id);v={names:n.map(i),defaultName:i(n.find(e=>e.id===o))},E(t,"models").default=C(o),function(e){const t=E(e,"plugins"),o=e=>Array.isArray(e)?e.map(String):[],r=o(t.enabled),n=o(t.disabled),i=h.filter(e=>!r.includes(e)&&!n.includes(e));i.length>0&&(t.disabled=[...n,...i])}(t),s(j()),l(j(),r.stringify(t))},unloadPrivateConfig(){if(!e(j()))return;let t;try{t=O()}catch(e){return void n.logError("grokAdapter.unloadPrivateConfig",e)}if(S(t.model)){for(const[e]of P(t))delete t.model[e];0===Object.keys(t.model).length&&delete t.model}S(t.models)&&"string"==typeof t.models.default&&M(t.models.default)&&(delete t.models.default,0===Object.keys(t.models).length&&delete t.models),S(t.endpoints)&&(delete t.endpoints.models_base_url,0===Object.keys(t.endpoints).length&&delete t.endpoints),function(e){if(!S(e.plugins)||!Array.isArray(e.plugins.disabled))return;const t=e.plugins.disabled.filter(e=>!h.includes(e));t.length>0?e.plugins.disabled=t:delete e.plugins.disabled,0===Object.keys(e.plugins).length&&delete e.plugins}(t),s(j()),l(j(),r.stringify(t))},detectCurrentConfig(){try{const e=O(),t=P(e),o=S(e.models)?e.models.default:void 0,r=t.find(([e])=>e===o)?.[1]??t[0]?.[1],n=r?r.api_key:null;return{apiKey:"string"==typeof n&&n.trim()?n:null}}catch{return{apiKey:null}}},listedModels(){try{const e=P(O());return e.length>0?e.map(([,e])=>String(e.model)):null}catch{return null}},refreshModelMenu(e){const t=O(),o=E(t,"models"),n="string"==typeof o.default?o.default:void 0,i=n?P(t).find(([e])=>e===n)?.[1].model:void 0,d="string"==typeof i&&n!==_&&e.catalog.models.includes(i)?i:a(e.models,g("grok")),m=r.stringify(t);$(t,e,N(e,d)),(void 0===n||M(n))&&(o.default=C(d)),r.stringify(t)!==m&&(s(j()),l(j(),r.stringify(t)))},applyNotes:()=>v?[{kind:"summary",text:f.t("tools.grok.menu_written",{count:String(v.names.length),list:v.names.join(f.t("tools.grok.list_separator")),default:v.defaultName})}]:[],getConfig(){try{return O()}catch(e){return n.logError("grokAdapter.getConfig",e),null}}};
1
+ import{existsSync as e,readFileSync as t}from"fs";import{join as o}from"path";import*as r from"@iarna/toml";import{logger as n}from"../../utils/logger.js";import{PROVIDER_KEY as i}from"../brand.js";import{backupBeforeWrite as l,atomicWriteFile as s}from"./backup.js";import{pickModel as a,toolHome as d,withV1 as m}from"./types.js";import{i18n as f}from"../i18n.js";import{getToolDefaultModel as g}from"../model-registry.js";import{gatewayModelSpecs as c,modelBlurb as u,modelFamily as p,prettyModelName as y}from"../gateway-models.js";import{brandInstallScripts as k,mirrorInstallCommand as b}from"./tool-installs.js";import{OFFICIAL_PLUGINS as h}from"./claude-plugins.js";const j=()=>o(o(d(),".grok"),"config.toml"),_=i,w=`${i}-`,A=["low","medium","high","xhigh"];let v=null;const C=e=>`${w}${e}`,M=e=>e===_||e.startsWith(w),x={command:"grok",npmPackage:"@xai-official/grok",npmMirrorTagStale:!0,mirrorScript:k("grok"),native:{binDir:[".grok","bin"],updateArgs:["update"],updateTimeoutMs:12e4,dataDirs:[[".grok","downloads"]]}};function S(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function E(e,t){return S(e[t])||(e[t]={}),e[t]}function O(){if(!e(j()))return{};const o=t(j(),"utf-8");if(!o.trim())return{};try{const e=r.parse(o);if(!S(e))throw new Error("config.toml root must be a TOML table");return e}catch(e){throw new Error(`Existing ~/.grok/config.toml cannot be parsed; back it up and fix it first: ${e instanceof Error?e.message:String(e)}`)}}function P(e){return S(e.model)?Object.entries(e.model).filter(e=>M(e[0])&&S(e[1])):[]}function N(e,t){let o=c("grok",e.catalog?.clientModels,e.catalog?.clientPersonal);if(e.catalog){const t=new Set(e.catalog.models);o=o.filter(e=>t.has(e.id))}return o.some(e=>e.id===t)?o:[{id:t},...o]}function $(e,t,o){E(e,"endpoints").models_base_url=m(t.baseUrl);const r=E(e,"model"),n=new Map(P(e));for(const e of n.keys())delete r[e];for(const e of o){const o=C(e.id),i={...n.get(o)??{},name:e.name??y(e.id),model:e.id,base_url:m(t.baseUrl),api_key:t.apiKey,context_window:e.contextWindow??5e5,api_backend:"responses",reasoning_summary:"concise"};"grok"===p(e.id)&&(i.supports_reasoning_effort=!0,i.reasoning_efforts=A);const l=u(e.description);l?i.description=l:delete i.description,r[o]=i}}export const grokAdapter={name:"grok",displayName:"Grok Build",command:"grok",installCommand:b(x),installSpec:x,configPath:j(),wantsModelCatalog:!0,loadPrivateConfig(e){const t=O(),o=a(e.models,g("grok")),n=N(e,o);$(t,e,n);const i=e=>e.name??y(e.id);v={names:n.map(i),defaultName:i(n.find(e=>e.id===o))},E(t,"models").default=C(o),function(e){const t=E(e,"plugins"),o=e=>Array.isArray(e)?e.map(String):[],r=o(t.enabled),n=o(t.disabled),i=h.filter(e=>!r.includes(e)&&!n.includes(e));i.length>0&&(t.disabled=[...n,...i])}(t),l(j()),s(j(),r.stringify(t))},unloadPrivateConfig(){if(!e(j()))return;let t;try{t=O()}catch(e){return void n.logError("grokAdapter.unloadPrivateConfig",e)}if(S(t.model)){for(const[e]of P(t))delete t.model[e];0===Object.keys(t.model).length&&delete t.model}S(t.models)&&"string"==typeof t.models.default&&M(t.models.default)&&(delete t.models.default,0===Object.keys(t.models).length&&delete t.models),S(t.endpoints)&&(delete t.endpoints.models_base_url,0===Object.keys(t.endpoints).length&&delete t.endpoints),function(e){if(!S(e.plugins)||!Array.isArray(e.plugins.disabled))return;const t=e.plugins.disabled.filter(e=>!h.includes(e));t.length>0?e.plugins.disabled=t:delete e.plugins.disabled,0===Object.keys(e.plugins).length&&delete e.plugins}(t),l(j()),s(j(),r.stringify(t))},detectCurrentConfig(){try{const e=O(),t=P(e),o=S(e.models)?e.models.default:void 0,r=t.find(([e])=>e===o)?.[1]??t[0]?.[1],n=r?r.api_key:null;return{apiKey:"string"==typeof n&&n.trim()?n:null}}catch{return{apiKey:null}}},listedModels(){try{const e=P(O());return e.length>0?e.map(([,e])=>String(e.model)):null}catch{return null}},refreshModelMenu(e){const t=O(),o=E(t,"models"),n="string"==typeof o.default?o.default:void 0,i=n?P(t).find(([e])=>e===n)?.[1].model:void 0,d="string"==typeof i&&n!==_&&e.catalog.models.includes(i)?i:a(e.models,g("grok")),m=r.stringify(t);$(t,e,N(e,d)),(void 0===n||M(n))&&(o.default=C(d)),r.stringify(t)!==m&&(l(j()),s(j(),r.stringify(t)))},applyNotes:()=>v?[{kind:"summary",text:f.t("tools.grok.menu_written",{count:String(v.names.length),list:v.names.join(f.t("tools.grok.list_separator")),default:v.defaultName})}]:[],getConfig(){try{return O()}catch(e){return n.logError("grokAdapter.getConfig",e),null}}};
@@ -1 +1 @@
1
- import{claudeCodeAdapter as o}from"./claude-code.js";import{opencodeAdapter as r}from"./opencode.js";import{codexAdapter as t}from"./codex.js";import{openclawAdapter as m}from"./openclaw.js";import{hermesAdapter as e}from"./hermes.js";import{atomcodeAdapter as p}from"./atomcode.js";import{grokAdapter as s}from"./grok.js";import{claudeDesktopAdapter as i}from"./claude-desktop.js";import{antigravityAdapter as n}from"./antigravity.js";const c=[o,r,t,m,e,p,s,i,n];export const TOOL_ADAPTERS=Object.fromEntries(c.map(o=>[o.name,o]));export function getAdapter(o){return TOOL_ADAPTERS[o]}export function listAdapters(){return[...c]}
1
+ import{claudeCodeAdapter as o}from"./claude-code.js";import{opencodeAdapter as r}from"./opencode.js";import{codexAdapter as t}from"./codex.js";import{openclawAdapter as m}from"./openclaw.js";import{hermesAdapter as e}from"./hermes.js";import{atomcodeAdapter as p}from"./atomcode.js";import{grokAdapter as s}from"./grok.js";import{claudeDesktopAdapter as i}from"./claude-desktop.js";import{antigravityAdapter as d}from"./antigravity.js";import{codebuddyAdapter as f}from"./codebuddy.js";import{workbuddyAdapter as c}from"./workbuddy.js";const n=[o,r,t,m,e,p,s,i,d,f,c];export const TOOL_ADAPTERS=Object.fromEntries(n.map(o=>[o.name,o]));export function getAdapter(o){return TOOL_ADAPTERS[o]}export function listAdapters(){return[...n]}
@@ -0,0 +1 @@
1
+ import{existsSync as t}from"fs";import{join as r}from"path";import{logger as o}from"../../utils/logger.js";import{i18n as e}from"../i18n.js";import{getToolDefaultModel as n}from"../model-registry.js";import{prettyModelName as d,vendorNames as s}from"../gateway-models.js";import{bareModelId as i,foreignIdsReplaced as a,isOurEntry as l,menuSpecs as p,mergeEntries as u,ourApiKey as c,ourEntries as m,readModelsFile as y,writeModelsFile as g}from"./codebuddy-models.js";import{pickModel as f,toolHome as b}from"./types.js";const k=()=>process.env.WORKBUDDY_CONFIG_DIR?.trim()||process.env.CODEBUDDY_CONFIG_DIR?.trim()||r(b(),".workbuddy"),w=()=>r(k(),"models.json"),h="https://www.codebuddy.cn/work/";let C=null;function _(t,r){const o=y(w()),{entries:e,replaced:n}=u(o.entries,r,t.baseUrl,t.apiKey,!0);return g(w(),o,e),n}const j=t=>i(f(t.models,n("workbuddy")));export const workbuddyAdapter={name:"workbuddy",displayName:"WorkBuddy",command:"workbuddy",installCommand:"darwin"===process.platform?`open ${h}`:h,get configPath(){return w()},wantsModelCatalog:!0,isInstalled:function(){return!!t(k())||"darwin"===process.platform&&["/Applications/WorkBuddy.app",r(b(),"Applications","WorkBuddy.app")].some(r=>t(r))},loadPrivateConfig(t){const r=p(t.catalog,j(t)),o=_(t,r);C={names:r.map(t=>t.name??d(t.id)),vendors:s(r.map(t=>t.id)),replaced:o}},unloadPrivateConfig(){try{const t=y(w());if(0===m(t.entries).length)return;g(w(),t,t.entries.filter(t=>!l(t)))}catch(t){o.logError("workbuddyAdapter.unloadPrivateConfig",t)}},detectCurrentConfig(){try{return{apiKey:c(y(w()).entries)}}catch{return{apiKey:null}}},listedModels(){try{const t=m(y(w()).entries);return t.length>0?t.map(t=>String(t.id)):null}catch{return null}},refreshModelMenu(t){_(t,p(t.catalog,j(t)))},planNotes(){try{const t=y(w()),r=a(t.entries,p(void 0,n("workbuddy")));return r.length>0?[e.t("tools.codebuddy.replaces_models",{path:w(),list:r.join(e.t("tools.codebuddy.list_separator"))})]:[]}catch{return[]}},applyNotes(){if(!C)return[];const t=[{kind:"summary",text:e.t("tools.workbuddy.menu_written",{count:String(C.names.length),list:C.vendors.join(e.t("tools.codebuddy.list_separator"))})},{kind:"action",text:e.t("tools.workbuddy.pick_in_app")}];return C.replaced.length>0&&t.push({kind:"detail",text:e.t("tools.codebuddy.replaced_models",{tool:"workbuddy",list:C.replaced.join(e.t("tools.codebuddy.list_separator"))})}),t},backupPaths:()=>[w()],getConfig(){try{return y(w()).entries}catch(t){return o.logError("workbuddyAdapter.getConfig",t),null}}};
@@ -450,6 +450,16 @@
450
450
  "gemini": "Gemini",
451
451
  "other": "Chinese",
452
452
  "grok": "Grok"
453
+ },
454
+ "codebuddy": {
455
+ "menu_written": "Wrote {{count}} models ({{list}}), default {{default}}",
456
+ "list_separator": ", ",
457
+ "replaces_models": "Models with the same id in {{path}} will be replaced: {{list}}",
458
+ "replaced_models": "Replaced models with the same id in models.json: {{list}} (undo with `{{cli}} config {{tool}} restore`)"
459
+ },
460
+ "workbuddy": {
461
+ "menu_written": "Wrote {{count}} models ({{list}})",
462
+ "pick_in_app": "Sign in to WorkBuddy, then pick a model from the Custom group of the chat model menu; an enterprise admin may have turned custom models off"
453
463
  }
454
464
  },
455
465
  "upgrade": {
@@ -735,14 +745,18 @@
735
745
  "force": "Back up, then rewrite each config with the recommended one (fixes broken configs)",
736
746
  "all": "Configure every tool the API key can serve (the default)",
737
747
  "install": "Install missing tools from the China mirrors without asking",
738
- "no_install": "Only print install commands for missing tools"
748
+ "no_install": "Only print install commands for missing tools",
749
+ "codebuddykey": "API key just for CodeBuddy Code",
750
+ "workbuddykey": "API key just for WorkBuddy"
739
751
  },
740
752
  "autodetect_title": "Models the --key can use and the tools configured:",
741
753
  "autodetect": {
742
754
  "claude": "Claude Code, Claude Desktop (macOS / Windows: written ahead even when not installed; Linux: when installed)",
743
755
  "gpt": "Codex",
744
756
  "grok": "Grok Build",
745
- "gemini": "Antigravity CLI"
757
+ "gemini": "Antigravity CLI",
758
+ "any_label": "Any",
759
+ "any": "CodeBuddy Code, WorkBuddy (only when installed)"
746
760
  },
747
761
  "ex": {
748
762
  "key": "Configure every tool one API key can serve",
@@ -450,6 +450,16 @@
450
450
  "gemini": "Gemini",
451
451
  "other": "国产",
452
452
  "grok": "Grok"
453
+ },
454
+ "codebuddy": {
455
+ "menu_written": "已写入 {{count}} 个模型({{list}}),默认 {{default}}",
456
+ "list_separator": "、",
457
+ "replaces_models": "{{path}} 里同名的模型会换成本站的:{{list}}",
458
+ "replaced_models": "已替换 models.json 里同名的模型:{{list}}(恢复运行 `{{cli}} config {{tool}} restore`)"
459
+ },
460
+ "workbuddy": {
461
+ "menu_written": "已写入 {{count}} 个模型({{list}})",
462
+ "pick_in_app": "在 WorkBuddy 登录后,到对话框的模型菜单「自定义模型」分组里选择;企业账号的管理员可能关闭了自定义模型"
453
463
  }
454
464
  },
455
465
  "upgrade": {
@@ -735,14 +745,18 @@
735
745
  "force": "先备份,再用推荐配置整份重写(用于修复改坏的配置)",
736
746
  "all": "配置令牌能用的全部工具(默认行为)",
737
747
  "install": "未安装的工具直接从国内镜像安装,不再询问",
738
- "no_install": "未安装的工具只给出安装命令,不安装"
748
+ "no_install": "未安装的工具只给出安装命令,不安装",
749
+ "codebuddykey": "CodeBuddy Code 专属令牌",
750
+ "workbuddykey": "WorkBuddy 专属令牌"
739
751
  },
740
752
  "autodetect_title": "--key 能用的模型和自动配置的工具:",
741
753
  "autodetect": {
742
754
  "claude": "Claude Code、Claude Desktop(macOS、Windows 上未安装也会提前写好;Linux 上已安装才配置)",
743
755
  "gpt": "Codex",
744
756
  "grok": "Grok Build",
745
- "gemini": "Antigravity CLI"
757
+ "gemini": "Antigravity CLI",
758
+ "any_label": "任意",
759
+ "any": "CodeBuddy Code、WorkBuddy(已安装才配置)"
746
760
  },
747
761
  "ex": {
748
762
  "key": "用一个令牌配置它能用的全部工具",
package/dist/models.json CHANGED
@@ -18,7 +18,9 @@
18
18
  "openclaw": "gpt-5.5",
19
19
  "hermes": "gpt-5.5",
20
20
  "atomcode": "gpt-5.5",
21
- "grok": "grok-4.6"
21
+ "grok": "grok-4.6",
22
+ "codebuddy": "gpt-6-astra",
23
+ "workbuddy": "gpt-6-astra"
22
24
  },
23
25
  "presets": [
24
26
  {
package/models.json CHANGED
@@ -18,7 +18,9 @@
18
18
  "openclaw": "gpt-5.5",
19
19
  "hermes": "gpt-5.5",
20
20
  "atomcode": "gpt-5.5",
21
- "grok": "grok-4.6"
21
+ "grok": "grok-4.6",
22
+ "codebuddy": "gpt-6-astra",
23
+ "workbuddy": "gpt-6-astra"
22
24
  },
23
25
  "presets": [
24
26
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marsapi/cli",
3
- "version": "0.0.157",
3
+ "version": "0.0.160",
4
4
  "description": "Configure Claude Code, Codex, Grok Build and other coding tools for Mars AI with one command",
5
5
  "main": "dist/index.js",
6
6
  "bin": {