@marsapi/cli 0.0.147 → 0.0.151

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.
Files changed (44) hide show
  1. package/client-config.snapshot.json +12 -12
  2. package/components.json +157 -0
  3. package/dist/client-config.snapshot.json +12 -12
  4. package/dist/commands/components.js +1 -0
  5. package/dist/commands/config.js +1 -1
  6. package/dist/commands/doctor.js +1 -1
  7. package/dist/commands/setup.js +1 -1
  8. package/dist/commands/upgrade.js +1 -1
  9. package/dist/components.json +157 -0
  10. package/dist/lib/app-update.js +1 -1
  11. package/dist/lib/brand.js +1 -1
  12. package/dist/lib/claude-code-manager.js +1 -1
  13. package/dist/lib/codex-sessions.js +1 -1
  14. package/dist/lib/command.js +1 -1
  15. package/dist/lib/components.js +1 -0
  16. package/dist/lib/config.js +1 -1
  17. package/dist/lib/dry-run.js +1 -1
  18. package/dist/lib/env-cleanup.js +1 -1
  19. package/dist/lib/gateway-addresses.js +1 -1
  20. package/dist/lib/i18n.js +1 -1
  21. package/dist/lib/model-registry.js +1 -1
  22. package/dist/lib/post-apply.js +1 -1
  23. package/dist/lib/powershell-env.js +1 -0
  24. package/dist/lib/program.js +1 -1
  25. package/dist/lib/runtime-options.js +1 -1
  26. package/dist/lib/tool-manager.js +1 -1
  27. package/dist/lib/tool-upgrade.js +1 -1
  28. package/dist/lib/tools/chatgpt-desktop.js +1 -0
  29. package/dist/lib/tools/claude-code.js +1 -1
  30. package/dist/lib/tools/claude-desktop-app.js +1 -1
  31. package/dist/lib/tools/claude-desktop-cli.js +1 -1
  32. package/dist/lib/tools/claude-desktop.js +1 -1
  33. package/dist/lib/tools/codex.js +1 -1
  34. package/dist/lib/tools/desktop-app-installer.js +1 -0
  35. package/dist/lib/tools/desktop-process.js +1 -1
  36. package/dist/lib/tools/elevated-reg.js +1 -1
  37. package/dist/lib/tools/tool-installs.js +1 -1
  38. package/dist/lib/windows-env.js +1 -1
  39. package/dist/lib/wizard.js +1 -1
  40. package/dist/lib/write-plan.js +1 -1
  41. package/dist/lib/written-values.js +1 -0
  42. package/dist/locales/en_US.json +175 -12
  43. package/dist/locales/zh_CN.json +175 -12
  44. package/package.json +2 -1
@@ -28,7 +28,7 @@
28
28
  },
29
29
  {
30
30
  "description": "轻量档 | 低延迟 | 高频短任务",
31
- "group": "grp_6eg2dq9ywgrg",
31
+ "group": "grp_irydsgijuckh",
32
32
  "group_name": "",
33
33
  "hidden": false,
34
34
  "id": "claude-haiku-4-5-20251001",
@@ -37,7 +37,7 @@
37
37
  },
38
38
  {
39
39
  "description": "100 万上下文 | 12.8 万输出 | 低延迟 | 高频轻量任务",
40
- "group": "grp_6eg2dq9ywgrg",
40
+ "group": "grp_6co8aqwefsoh",
41
41
  "group_name": "",
42
42
  "hidden": false,
43
43
  "id": "claude-haiku-5-5",
@@ -46,7 +46,7 @@
46
46
  },
47
47
  {
48
48
  "description": "100 万上下文 | 推理 | 编程 | 长上下文不加价",
49
- "group": "grp_rld6af0zorqd",
49
+ "group": "grp_6eg2dq9ywgrg",
50
50
  "group_name": "",
51
51
  "hidden": false,
52
52
  "id": "claude-opus-4-6",
@@ -55,7 +55,7 @@
55
55
  },
56
56
  {
57
57
  "description": "100 万上下文 | 推理 | 编程 | 长上下文不加价",
58
- "group": "grp_6lyxfgbs440g",
58
+ "group": "grp_irydsgijuckh",
59
59
  "group_name": "",
60
60
  "hidden": false,
61
61
  "id": "claude-opus-4-7",
@@ -64,7 +64,7 @@
64
64
  },
65
65
  {
66
66
  "description": "100 万上下文 | 推理 | 编程 | 长上下文不加价",
67
- "group": "grp_6eg2dq9ywgrg",
67
+ "group": "grp_rld6af0zorqd",
68
68
  "group_name": "",
69
69
  "hidden": false,
70
70
  "id": "claude-opus-4-8",
@@ -82,7 +82,7 @@
82
82
  },
83
83
  {
84
84
  "description": "100 万上下文 | 长时 Agent 编程 | 知识工作",
85
- "group": "grp_irydsgijuckh",
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_6lyxfgbs440g",
95
95
  "group_name": "",
96
96
  "hidden": false,
97
97
  "id": "claude-sonnet-4-6",
@@ -129,7 +129,7 @@
129
129
  },
130
130
  {
131
131
  "description": "105 万上下文 | 12.8 万输出 | 前沿档",
132
- "group": "grp_bsbtt432saoq",
132
+ "group": "grp_irydsgijuckh",
133
133
  "group_name": "",
134
134
  "hidden": false,
135
135
  "id": "gpt-5.6-sol",
@@ -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_bsbtt432saoq",
169
169
  "group_name": "",
170
170
  "hidden": false,
171
171
  "id": "gpt-6-sol",
@@ -221,7 +221,7 @@
221
221
  },
222
222
  {
223
223
  "description": "约 100 万上下文 | 深度推理 | 密集长文档",
224
- "group": "grp_3pi5kyqkp51b",
224
+ "group": "grp_z5khwusxuh2j",
225
225
  "group_name": "",
226
226
  "hidden": false,
227
227
  "id": "gemini-3.1-pro",
@@ -239,7 +239,7 @@
239
239
  },
240
240
  {
241
241
  "description": "高吞吐 | 低成本 | 大批量常规任务",
242
- "group": "grp_z5khwusxuh2j",
242
+ "group": "grp_3pi5kyqkp51b",
243
243
  "group_name": "",
244
244
  "hidden": false,
245
245
  "id": "gemini-3.5-flash",
@@ -0,0 +1,157 @@
1
+ {
2
+ "schema": 1,
3
+ "about": "Components the CLI installs and upgrades (its list / install / upgrade commands). Read by src/lib/components.ts and by scripts/gen-components-doc.mjs (docs, the install scripts' README). {scripts} = the brand's installMirror.scripts, {agy} = installMirror.agy, {devtools} = the neutral CNB mirror of fnm / uv / Git for Windows.",
4
+ "devtools": "https://cnb.cool/lib/devtools/-/releases/latest/download",
5
+ "components": [
6
+ {
7
+ "id": "node",
8
+ "name": "Node.js",
9
+ "category": "runtime",
10
+ "aliases": ["nodejs"],
11
+ "platforms": ["darwin", "linux", "win32"],
12
+ "detect": { "command": "node", "pattern": "v(\\d+\\.\\d+\\.\\d+)" },
13
+ "latest": { "type": "node-lts", "url": "https://registry.npmmirror.com/-/binary/node/index.json" },
14
+ "sources": {
15
+ "all": "fnm({devtools})+ Node 镜像 https://npmmirror.com/mirrors/node"
16
+ },
17
+ "verify": { "checksum": "fnm:SHA256SUMS;Node:fnm 下载时核对官方 SHASUMS256.txt", "signature": "—" },
18
+ "install": { "type": "script", "script": "node", "forceEnv": { "NODE_INSTALL_FORCE": "1" } },
19
+ "upgrade": { "managedBy": "fnm", "migrateGlobalPackages": true },
20
+ "check": ["node", "--version"],
21
+ "requires": []
22
+ },
23
+ {
24
+ "id": "git",
25
+ "name": "Git",
26
+ "category": "runtime",
27
+ "platforms": ["darwin", "linux", "win32"],
28
+ "detect": { "command": "git", "pattern": "git version (\\d+\\.\\d+\\.\\d+)" },
29
+ "latest": { "type": "devtools", "key": "git", "platforms": ["win32"] },
30
+ "sources": {
31
+ "darwin": "苹果命令行工具(xcode-select)",
32
+ "linux": "系统包管理器(apt、dnf、yum、zypper、pacman、apk)",
33
+ "win32": "Git for Windows({devtools})"
34
+ },
35
+ "verify": {
36
+ "checksum": "Windows:SHA256SUMS(取自 GitHub 公布的 digest)",
37
+ "signature": "macOS / Linux:系统包管理器自己的签名"
38
+ },
39
+ "install": { "type": "script", "script": "git", "forceEnv": { "GIT_INSTALL_FORCE": "1" } },
40
+ "upgrade": { "managedBy": "git-for-windows-user" },
41
+ "check": ["git", "--version"],
42
+ "requires": []
43
+ },
44
+ {
45
+ "id": "uv",
46
+ "name": "uv",
47
+ "category": "runtime",
48
+ "aliases": ["python-uv"],
49
+ "platforms": ["darwin", "linux", "win32"],
50
+ "detect": { "command": "uv", "pattern": "uv (\\d+\\.\\d+\\.\\d+)" },
51
+ "latest": { "type": "devtools", "key": "uv" },
52
+ "sources": {
53
+ "all": "uv 官方程序({devtools});Python 从 npmmirror 的 python-build-standalone 镜像、包从阿里云 PyPI 镜像"
54
+ },
55
+ "verify": { "checksum": "SHA256SUMS", "signature": "—" },
56
+ "install": { "type": "script", "script": "uv", "forceEnv": { "UV_INSTALL_FORCE": "1" } },
57
+ "upgrade": { "managedBy": "uv-standalone" },
58
+ "check": ["uv", "--version"],
59
+ "requires": []
60
+ },
61
+ {
62
+ "id": "claude-code",
63
+ "name": "Claude Code",
64
+ "category": "cli",
65
+ "aliases": ["claude"],
66
+ "platforms": ["darwin", "linux", "win32"],
67
+ "adapter": "claude-code",
68
+ "latest": { "type": "npm", "package": "@anthropic-ai/claude-code" },
69
+ "sources": {
70
+ "all": "npmmirror 的 @anthropic-ai/claude-code-<平台>(与 downloads.claude.ai 同一文件),按官方原生布局安装({scripts}/claude-code.sh / .ps1)"
71
+ },
72
+ "verify": { "checksum": "npm sha512;连得上时再核对 Anthropic 发布清单的 sha256", "signature": "—" },
73
+ "install": { "type": "adapter" },
74
+ "check": ["claude", "--version"],
75
+ "requires": []
76
+ },
77
+ {
78
+ "id": "codex",
79
+ "name": "Codex",
80
+ "category": "cli",
81
+ "platforms": ["darwin", "linux", "win32"],
82
+ "adapter": "codex",
83
+ "latest": { "type": "npm", "package": "@openai/codex" },
84
+ "sources": {
85
+ "all": "npmmirror 的 @openai/codex(vendor 目录与官方 codex-package 逐文件相同),按官方原生布局安装({scripts}/codex.sh / .ps1)"
86
+ },
87
+ "verify": { "checksum": "npm sha512", "signature": "—" },
88
+ "install": { "type": "adapter" },
89
+ "check": ["codex", "--version"],
90
+ "requires": []
91
+ },
92
+ {
93
+ "id": "grok",
94
+ "name": "Grok Build",
95
+ "category": "cli",
96
+ "platforms": ["darwin", "linux", "win32"],
97
+ "adapter": "grok",
98
+ "latest": { "type": "npm", "package": "@xai-official/grok", "staleTag": true },
99
+ "sources": { "all": "npmmirror 的 @xai-official/grok-<平台>({scripts}/grok.sh / .ps1)" },
100
+ "verify": { "checksum": "npm sha512", "signature": "—" },
101
+ "install": { "type": "adapter" },
102
+ "check": ["grok", "--version"],
103
+ "requires": []
104
+ },
105
+ {
106
+ "id": "agy",
107
+ "name": "Antigravity CLI",
108
+ "category": "cli",
109
+ "aliases": ["antigravity"],
110
+ "platforms": ["darwin", "linux", "win32"],
111
+ "adapter": "agy",
112
+ "latest": { "type": "version-file", "url": "{agy}/version.txt" },
113
+ "sources": { "all": "高速下载站 {agy}(每小时同步官方)" },
114
+ "verify": { "checksum": "官方清单的 sha512", "signature": "—" },
115
+ "install": { "type": "adapter" },
116
+ "check": ["agy", "--version"],
117
+ "requires": []
118
+ },
119
+ {
120
+ "id": "claude-desktop",
121
+ "name": "Claude Desktop",
122
+ "category": "app",
123
+ "platforms": ["darwin", "win32"],
124
+ "app": "claude-desktop",
125
+ "latest": { "type": "app" },
126
+ "sources": {
127
+ "darwin": "高速下载站 lib/claude-desktop(官方 dmg)",
128
+ "win32": "高速下载站 lib/claude-desktop(官方 MSIX)"
129
+ },
130
+ "verify": {
131
+ "checksum": "SHA256SUMS",
132
+ "signature": "macOS:Team ID Q6L2SF6YDW + 公证;Windows:Authenticode O=Anthropic, PBC"
133
+ },
134
+ "install": { "type": "app" },
135
+ "requires": []
136
+ },
137
+ {
138
+ "id": "chatgpt",
139
+ "name": "ChatGPT",
140
+ "category": "app",
141
+ "aliases": ["chatgpt-desktop", "codex-desktop", "codex-app"],
142
+ "platforms": ["darwin", "win32"],
143
+ "app": "chatgpt",
144
+ "latest": { "type": "app" },
145
+ "sources": {
146
+ "darwin": "高速下载站 lib/chatgpt-desktop(官方 dmg,只有 Apple 芯片版)",
147
+ "win32": "高速下载站 lib/chatgpt-desktop(Microsoft Store 同一个 MSIX)"
148
+ },
149
+ "verify": {
150
+ "checksum": "SHA256SUMS",
151
+ "signature": "macOS:Team ID 2DC432GLL2 + 公证;Windows:Microsoft Store 签名(OpenAI 发布者)"
152
+ },
153
+ "install": { "type": "app" },
154
+ "requires": []
155
+ }
156
+ ]
157
+ }
@@ -28,7 +28,7 @@
28
28
  },
29
29
  {
30
30
  "description": "轻量档 | 低延迟 | 高频短任务",
31
- "group": "grp_6eg2dq9ywgrg",
31
+ "group": "grp_irydsgijuckh",
32
32
  "group_name": "",
33
33
  "hidden": false,
34
34
  "id": "claude-haiku-4-5-20251001",
@@ -37,7 +37,7 @@
37
37
  },
38
38
  {
39
39
  "description": "100 万上下文 | 12.8 万输出 | 低延迟 | 高频轻量任务",
40
- "group": "grp_6eg2dq9ywgrg",
40
+ "group": "grp_6co8aqwefsoh",
41
41
  "group_name": "",
42
42
  "hidden": false,
43
43
  "id": "claude-haiku-5-5",
@@ -46,7 +46,7 @@
46
46
  },
47
47
  {
48
48
  "description": "100 万上下文 | 推理 | 编程 | 长上下文不加价",
49
- "group": "grp_rld6af0zorqd",
49
+ "group": "grp_6eg2dq9ywgrg",
50
50
  "group_name": "",
51
51
  "hidden": false,
52
52
  "id": "claude-opus-4-6",
@@ -55,7 +55,7 @@
55
55
  },
56
56
  {
57
57
  "description": "100 万上下文 | 推理 | 编程 | 长上下文不加价",
58
- "group": "grp_6lyxfgbs440g",
58
+ "group": "grp_irydsgijuckh",
59
59
  "group_name": "",
60
60
  "hidden": false,
61
61
  "id": "claude-opus-4-7",
@@ -64,7 +64,7 @@
64
64
  },
65
65
  {
66
66
  "description": "100 万上下文 | 推理 | 编程 | 长上下文不加价",
67
- "group": "grp_6eg2dq9ywgrg",
67
+ "group": "grp_rld6af0zorqd",
68
68
  "group_name": "",
69
69
  "hidden": false,
70
70
  "id": "claude-opus-4-8",
@@ -82,7 +82,7 @@
82
82
  },
83
83
  {
84
84
  "description": "100 万上下文 | 长时 Agent 编程 | 知识工作",
85
- "group": "grp_irydsgijuckh",
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_6lyxfgbs440g",
95
95
  "group_name": "",
96
96
  "hidden": false,
97
97
  "id": "claude-sonnet-4-6",
@@ -129,7 +129,7 @@
129
129
  },
130
130
  {
131
131
  "description": "105 万上下文 | 12.8 万输出 | 前沿档",
132
- "group": "grp_bsbtt432saoq",
132
+ "group": "grp_irydsgijuckh",
133
133
  "group_name": "",
134
134
  "hidden": false,
135
135
  "id": "gpt-5.6-sol",
@@ -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_bsbtt432saoq",
169
169
  "group_name": "",
170
170
  "hidden": false,
171
171
  "id": "gpt-6-sol",
@@ -221,7 +221,7 @@
221
221
  },
222
222
  {
223
223
  "description": "约 100 万上下文 | 深度推理 | 密集长文档",
224
- "group": "grp_3pi5kyqkp51b",
224
+ "group": "grp_z5khwusxuh2j",
225
225
  "group_name": "",
226
226
  "hidden": false,
227
227
  "id": "gemini-3.1-pro",
@@ -239,7 +239,7 @@
239
239
  },
240
240
  {
241
241
  "description": "高吞吐 | 低成本 | 大批量常规任务",
242
- "group": "grp_z5khwusxuh2j",
242
+ "group": "grp_3pi5kyqkp51b",
243
243
  "group_name": "",
244
244
  "hidden": false,
245
245
  "id": "gemini-3.5-flash",
@@ -0,0 +1 @@
1
+ import t from"chalk";import{appUpgradeCommand as e,upgradeApp as n}from"../lib/app-update.js";import{CLI_NAME as o}from"../lib/brand.js";import{componentStatus as r,listComponents as a,prefetchLatest as l,resolveComponent as s,runRuntime as i,upgradeAdvice as c}from"../lib/components.js";import{i18n as u}from"../lib/i18n.js";import{emitJson as d,isJsonMode as p,progressToStderr as m}from"../lib/runtime-options.js";import{mirrorInstall as f,upgradeTool as g}from"../lib/tool-upgrade.js";import{getAdapter as _}from"../lib/tools/registry.js";import{findInstallsIncludingNative as y,forgetInstalls as b}from"../lib/tools/tool-installs.js";function h(t){p()?process.stderr.write(t+"\n"):console.log(t)}function w(t){let e=0;for(const n of t)e+=/[ᄀ-ᅟ⺀-꓏가-힣豈-﫿︰-﹏＀-⦆¢-₩]/.test(n)?2:1;return e}function k(t,e){return t+" ".repeat(Math.max(0,e-w(t)))}export function resolveTargets(t){const e=[],n=[],o=(t,e)=>{if(!n.includes(t)&&!e.includes(t.id)){for(const n of t.requires){const r=s(n);r&&o(r,[...e,t.id])}n.push(t)}};for(const n of t){const t=s(n);t?o(t,[]):e.push(n)}return{specs:n,unknown:e}}function v(e){return e.supported?!e.installed&&e.blocker?t.gray(function(t){for(const e of[`components.reason_${t}`,`app_update.reason_${t}`]){const t=u.t(e);if(t!==e)return t}return t}(e.blocker)):e.installed?e.outdated?t.yellow(e.auto_upgrade?u.t("components.state.outdated_auto",{command:`${o} upgrade ${e.id}`}):u.t("components.state.outdated_manual",{how:e.hint??u.t(`components.how_${e.managed_by??"other"}`,{tool:e.name})})):e.latest?t.green(u.t("components.state.latest")):t.gray(u.t("components.state.unknown_latest")):t.gray(u.t("components.state.missing",{command:`${o} install ${e.id}`})):t.gray(u.t("components.state.unsupported"))}export async function listCommand(e={}){const n=a(),o=await l(n,{refresh:e.refresh}),s=[];for(const t of n)s.push(await r(t,{latest:o.get(t.id)}));if(p())return void d({components:s});const i=s.map(t=>({s:t,cells:[t.name,t.installed?t.current??"?":"—",t.latest??"—",t.installed?u.t(`components.by.${t.managed_by??"other"}`):"—"]})),c=[u.t("components.col.name"),u.t("components.col.current"),u.t("components.col.latest"),u.t("components.col.managed")],m=c.map((t,e)=>Math.max(w(t),...i.map(t=>w(t.cells[e])))+2);for(const e of["runtime","cli","app"]){const n=i.filter(t=>t.s.category===e);if(n.length){console.log(t.bold(`\n${u.t(`components.category.${e}`)}`)),console.log(t.gray(" "+c.map((t,e)=>k(t,m[e])).join("")+u.t("components.col.state")));for(const{s:e,cells:o}of n)console.log(" "+o.map((t,e)=>k(t,m[e])).join("")+v(e)),e.source&&e.supported&&console.log(t.gray(" "+u.t("components.source",{source:e.source})))}}const f=s.filter(t=>t.error&&!t.latest);f.length&&console.log(t.yellow("\n ! "+u.t("components.latest_unknown",{tools:f.map(t=>t.name).join("、")})))}export async function installComponent(o,a){return p()||console.log(t.bold(`\n${o.name}`)),"runtime"===o.category?i(o,"install",{force:a}):"cli"===o.category?async function(e,n){const o=_(e.adapter),a=await r(e,{refresh:!0}),l={tool:e.id,category:"cli",current:a.current,latest:a.latest,version_after:null};if(!o?.installSpec)return{...l,result:"unavailable",ok:!1,reason:"no_install_spec"};if(a.blocker)return h(t.yellow(" ! "+u.t(`components.blocked_${a.blocker}`,{tool:e.name}))),{...l,result:"unavailable",ok:!1,reason:a.blocker};if(a.installed&&!n){const n=t.gray(`(${a.path})`);return a.outdated?(h(t.green(" √ "+u.t("components.already_installed",{tool:e.name,current:a.current??"?"}))+n),h(t.yellow(" ! "+c(a))),{...l,result:"already_installed",ok:!0,hint:c(a)}):(h(t.green(" √ "+u.t(a.latest?"components.up_to_date":"components.already_installed",{tool:e.name,current:a.current??"?"}))+n),{...l,result:"already_installed",ok:!0})}let s;a.installed?(h(t.yellow(" ! "+u.t("components.reinstalling",{tool:e.name,current:a.current??"?"}))),s=await f(o.installSpec)):s=await g(o.name),b();const i=y(o.installSpec)[0];a.installed&&s&&h(t.green(" √ "+u.t("components.reinstalled",{tool:e.name,version:i?.version??"?"})));const d=s&&i?a.installed?"reinstalled":"installed":"failed";return{...l,result:d,ok:"failed"!==d,version_after:i?.version??null}}(o,a):async function(o,a){const l=await r(o,{refresh:!0});if(l.installed&&!a){const n={tool:o.id,category:"app",current:l.current,latest:l.latest,version_after:null};if(l.outdated){h(t.green(" √ "+u.t("components.already_installed",{tool:o.name,current:l.current??"?"})));const r=u.t("app_update.upgrade_hint",{tool:o.name,current:l.current??"?",latest:l.latest??"?",command:e(o.app)});return h(t.yellow(" ! "+r)),{...n,result:"already_installed",ok:!0,hint:r}}return h(t.green(" √ "+u.t(l.latest?"components.up_to_date":"components.already_installed",{tool:o.name,current:l.current??"?"}))),{...n,result:"already_installed",ok:!0}}return function(t,e){const n={installed:"installed",upgraded:e.current&&e.latest&&e.current===e.version_after?"reinstalled":"upgraded",up_to_date:"up_to_date",declined:"manual",offered:"already_installed",left_running:"manual",not_installed:"unavailable",unavailable:"unavailable",failed:"failed"}[e.result]??"failed";return{tool:t.id,category:"app",current:e.current,latest:e.latest,result:n,version_after:e.version_after,ok:["installed","upgraded","reinstalled","up_to_date","already_installed"].includes(n),...e.reason?{reason:e.reason}:{}}}(o,await n(o.app,{install:!0,force:a}))}(o,a)}export async function installCommand(e,n={}){const{specs:o,unknown:r}=resolveTargets(e);if(r.length||!o.length)return console.error(t.red(u.t("components.unknown",{names:r.join(", ")||"—"}))),console.error(u.t("components.known",{ids:a().map(t=>t.id).join(" / ")})),void(process.exitCode=1);const l=[];for(const t of o)l.push(await m(()=>installComponent(t,Boolean(n.force))));p()&&d({components:l}),l.some(t=>!t.ok)&&(process.exitCode=1)}export async function outdatedRuntimeHints(){const t=a().filter(t=>"runtime"===t.category);return(await Promise.all(t.map(t=>r(t,{offline:!0})))).filter(t=>t.installed&&t.outdated).map(t=>c(t))}
@@ -1 +1 @@
1
- import o from"inquirer";import e from"chalk";import{wizard as t}from"../lib/wizard.js";import{toolManager as n,SUPPORTED_TOOLS as l}from"../lib/tool-manager.js";import{i18n as i}from"../lib/i18n.js";import{configManager as r,DEFAULT_PROFILE_NAME as a}from"../lib/config.js";import{confirmAction as s,applyOrDryRun as c,requireTerminal as d}from"../lib/confirm.js";import{canPrompt as f,isDryRun as g,isNonInteractive as p,shouldAutoConfirm as m}from"../lib/runtime-options.js";const _=/^[a-zA-Z0-9._-]+$/;function u(o,e){const t=(o||"").trim();if(!t||!_.test(t))throw new Error(i.t(`config.${e}_invalid_name`,{name:t||"<empty>"}));return t}function y(o,t){console.log("\n"+e.bold(o)),0!==t.length?t.forEach(o=>console.log(" "+o)):console.log(e.gray(" ("+i.t("config.empty_list")+")"))}function v(o,t){if("backups"===t){const t=n.listToolBackups(o).flatMap(o=>{const t=o.file.replace(/^.*[/\\]/,"");return o.backups.length?o.backups.map(o=>`${e.cyan(t)} ${e.gray(o.name.split(".bak-")[1]||o.name)}`):[`${e.cyan(t)} ${e.gray("("+i.t("config.empty_list")+")")}`]});return void y(i.t("config.tool_backups_title",{tool:l[o].displayName}),t)}const r=n.restorePrivateConfig(o).filter(o=>o.result.restored);0!==r.length?(console.log(e.green(i.t("config.config_restored",{tool:l[o].displayName}))),r.forEach(o=>console.log(e.gray(` ${o.file} ← ${o.result.from}`))),console.log(e.yellow(" ! "+i.t("config.reopen_hint",{tool:l[o].displayName})))):console.log(e.yellow(i.t("config.restore_no_backup",{tool:l[o].displayName})))}async function w(a,p,m){if(!l[a])return void console.log(e.red(i.t("config.unknown_tool",{tool:a})));const _=(p[0]||"").toLowerCase();if("backups"!==_&&"list-backups"!==_)if("restore"!==_){if("remove"===_||"unload"===_){const o=l[a].displayName;return void await c({description:i.t("config.remove_dry_run",{tool:o}),json:{action:"remove",tool:a},apply:async()=>{if(!await s({message:i.t("config.confirm_remove",{tool:o,name:a}),defaultValue:!0}))return;const t=n.holdsOurConfig(a),l=n.unloadPrivateConfig(a);t?(console.log(e.green(i.t("config.remove_done",{tool:o}))),l.forEach(o=>console.log(e.yellow(" ! "+o.text)))):console.log(e.gray(i.t("config.remove_nothing",{tool:o})))}})}if("clear-model"===_||"clear-models"===_){const o=l[a].displayName;return n.supportsClearPinnedModels(a)?void await c({description:i.t("config.clear_model_dry_run",{tool:o}),json:{action:"clear_model",tool:a},apply:async()=>{const t=await n.clearPinnedModels(a);0!==t.length?(console.log(e.green(i.t("config.clear_model_done",{tool:o}))),t.forEach(o=>console.log(e.gray(` - ${o}`))),console.log(e.gray(i.t("config.clear_model_restart_hint",{tool:o})))):console.log(e.yellow(i.t("config.clear_model_none",{tool:o})))}}):void console.log(e.yellow(i.t("config.clear_model_unsupported",{tool:o})))}if(g())await c({description:i.t("config.tool_apply_dry_run",{tool:l[a].displayName}),json:{action:"apply",tool:a,force:Boolean(m.force)},apply:()=>{}});else{if(!n.isToolInstalled(a)){if(m.nonInteractive)return void console.log(e.yellow(i.t("wizard.tool_not_installed",{tool:l[a].displayName})));if(console.log(e.yellow(i.t("wizard.tool_not_installed",{tool:l[a].displayName}))),!f())return;const{shouldInstall:t}=await o.prompt([{type:"confirm",name:"shouldInstall",message:i.t("wizard.install_tool_confirm"),default:!0}]);if(!t)return void console.log(e.yellow(i.t("wizard.install_skipped")));try{await n.installTool(a)}catch(o){return console.error(e.red(i.t("install.install_failed_detail"))),void(o instanceof Error&&o.message&&console.error(e.gray(o.message)))}}if(m.nonInteractive||m.force){const o=r.getApiKeyForTool(a);if(!o)return void console.log(e.red(i.t("auth.reload_missing_config")));if(m.force&&!m.nonInteractive&&!await s({message:i.t("config.confirm_force",{tool:l[a].displayName}),defaultValue:!1}))return;return await n.applyPrivateConfig(a,o,r.getModelsForTool(a),{force:m.force}),m.force&&console.log(e.yellow(i.t("config.force_done",{tool:l[a].displayName,name:a}))),void n.printApplied(a)}d(),await t.showToolMenu(a)}}else await c({description:i.t("config.tool_restore_dry_run",{tool:l[a].displayName}),json:{action:"tool_restore",tool:a},apply:async()=>{await s({message:i.t("config.confirm_restore",{tool:l[a].displayName}),defaultValue:!1})&&v(a,"restore")}});else v(a,"backups")}export async function configCommand(t){const{positional:n,options:d}=function(o){const e=[],t={};(p()||m())&&(t.nonInteractive=!0);for(const n of o)"--non-interactive"===n||"-y"===n?t.nonInteractive=!0:"--force"===n||"-f"===n?t.force=!0:e.push(n);return{positional:e,options:t}}(t),g=n[0],v=n.slice(1);if(g){switch(g){case"profile":return void await async function(o){const t=o[0],n=o[1];if(!t||"list"===t){const o=r.getActiveProfileName(),t=r.listProfiles().map(t=>{const n=t===o;return`${n?e.green("●"):e.gray("○")} ${t}${n?e.gray(" ("+i.t("config.profile_active_label")+")"):""}`});return void y(i.t("config.profile_list_title"),t)}if("create"===t){const o=u(n,"profile");return r.listProfiles().includes(o)?void console.log(e.yellow(i.t("config.profile_exists",{name:o}))):void await c({description:i.t("config.profile_create_dry_run",{name:o}),json:{action:"profile_create",name:o},apply:()=>{r.createProfile(o),console.log(e.green(i.t("config.profile_created",{name:o})))}})}if("use"===t){const o=u(n,"profile");return void await c({description:i.t("config.profile_use_dry_run",{name:o}),json:{action:"profile_use",name:o},apply:()=>{r.setActiveProfile(o),console.log(e.green(i.t("config.profile_activated",{name:o})))}})}if("delete"===t||"remove"===t){const o=u(n,"profile");return o===a&&1===r.listProfiles().length?void console.log(e.yellow(i.t("config.profile_cannot_delete_last"))):void await c({description:i.t("config.profile_delete_dry_run",{name:o}),json:{action:"profile_delete",name:o},apply:async()=>{await s({message:i.t("config.profile_delete_confirm",{name:o}),defaultValue:!1})?(r.deleteProfile(o),console.log(e.green(i.t("config.profile_deleted",{name:o})))):console.log(e.yellow(i.t("config.profile_delete_aborted")))}})}console.log(e.red(i.t("config.unknown_action",{action:t})))}(v);case"preset":return void await async function(o){const t=o[0],n=o[1];if(!t||"list"===t){const o=Object.entries(r.getCustomPresets()).map(([o,t])=>`${e.cyan(o)} ${e.gray(`H:${t.models.haiku} S:${t.models.sonnet} O:${t.models.opus}`)}`);return void y(i.t("config.preset_list_title"),o)}if("save"===t){const o=u(n,"preset");return void await c({description:i.t("config.preset_save_dry_run",{name:o}),json:{action:"preset_save",name:o},apply:()=>{r.saveCustomPreset(o,r.getModels()),console.log(e.green(i.t("config.preset_saved",{name:o})))}})}if("use"===t||"apply"===t){const o=u(n,"preset"),t=r.getCustomPresets()[o];return t?void await c({description:i.t("config.preset_use_dry_run",{name:o}),json:{action:"preset_use",name:o},apply:()=>{r.setModels(t.models),console.log(e.green(i.t("config.preset_applied",{name:o})))}}):void console.log(e.red(i.t("config.preset_not_found",{name:o})))}if("delete"===t||"remove"===t){const o=u(n,"preset");return void await c({description:i.t("config.preset_delete_dry_run",{name:o}),json:{action:"preset_delete",name:o},apply:()=>{r.deleteCustomPreset(o),console.log(e.green(i.t("config.preset_deleted",{name:o})))}})}console.log(e.red(i.t("config.unknown_action",{action:t})))}(v);case"tool-model":return void await async function(o){const t=o[0];if(!t||"list"===t){const o=r.getProfile().tool_models||{},t=Object.entries(o).map(([o,t])=>{const n=Object.entries(t).map(([o,e])=>`${o}=${e}`).join(" ");return`${e.cyan(o)} ${e.gray(n)}`});return void y(i.t("config.tool_model_list_title"),t)}if("set"===t){const t=(o[1]||"").trim(),n=o.length>=4?(o[2]||"").trim():"opus",a=(o.length>=4?o[3]:o[2]||"").trim();return l[t]?a&&_.test(n)?void await c({description:i.t("config.tool_model_set_dry_run",{tool:t,slot:n,model:a}),json:{action:"tool_model_set",tool:t,slot:n,model:a},apply:()=>{r.setToolModel(t,{[n]:a}),console.log(e.green(i.t("config.tool_model_set",{tool:t,slot:n,model:a})))}}):void console.log(e.red(i.t("config.tool_model_usage"))):void console.log(e.red(t?i.t("config.unknown_tool",{tool:t}):i.t("config.tool_model_usage")))}if("clear"===t||"remove"===t){const t=(o[1]||"").trim();return l[t]?void await c({description:i.t("config.tool_model_clear_dry_run",{tool:t}),json:{action:"tool_model_clear",tool:t},apply:()=>{r.setToolModel(t,null),console.log(e.green(i.t("config.tool_model_cleared",{tool:t})))}}):void console.log(e.red(t?i.t("config.unknown_tool",{tool:t}):i.t("config.tool_model_usage")))}console.log(e.red(i.t("config.unknown_action",{action:t})))}(v);case"backup":return void await function(o){return async function(o){const t=o[0],n=o[1];if(!t||"list"===t){const o=r.listBackups().map(o=>{const t=new Date(o.mtimeMs).toISOString();return`${e.cyan(o.name)} ${e.gray(t)}`});return void y(i.t("config.backup_list_title"),o)}if("create"!==t&&"snapshot"!==t)return"restore"===t?n?void await c({description:i.t("config.backup_restore_dry_run",{name:n}),json:{action:"backup_restore",name:n},apply:async()=>{await s({message:i.t("config.backup_restore_confirm",{name:n}),defaultValue:!1})?(r.restoreBackup(n),console.log(e.green(i.t("config.backup_restored",{name:n})))):console.log(e.yellow(i.t("config.backup_restore_aborted")))}}):void console.log(e.red(i.t("config.backup_restore_missing_name"))):void console.log(e.red(i.t("config.unknown_action",{action:t})));await c({description:i.t("config.backup_create_dry_run"),json:{action:"backup_create",name:n??null},apply:()=>{const o=r.createBackup(n);console.log(e.green(i.t("config.backup_created",{path:o})))}})}(o)}(v)}"claude-code"!==g&&"claude-code"!==v[0]?l[g]?await w(g,v,d):(console.error(e.red(i.t("config.unknown_command",{command:g}))),console.log(e.gray(i.t("config.usage_hint"))),Object.values(l).filter(o=>!o.hidden).forEach(o=>{console.log(e.gray(` - ${o.name}: ${o.displayName}`))})):await w("claude-code",v,d)}else await async function(t){if(t.nonInteractive||!f())return void console.log(e.red(i.t("config.requires_argument")));const{selectedTool:n}=await o.prompt([{type:"list",name:"selectedTool",message:i.t("wizard.select_tool"),choices:Object.values(l).filter(o=>!o.hidden).map(o=>({name:`${o.displayName} (${o.name})`,value:o.name}))}]);await w(n,[],t)}(d)}
1
+ import o from"inquirer";import e from"chalk";import{wizard as t}from"../lib/wizard.js";import{runFollowUps as n}from"../lib/post-apply.js";import{toolManager as l,SUPPORTED_TOOLS as i}from"../lib/tool-manager.js";import{i18n as r}from"../lib/i18n.js";import{configManager as a,DEFAULT_PROFILE_NAME as s}from"../lib/config.js";import{confirmAction as c,applyOrDryRun as d,requireTerminal as f}from"../lib/confirm.js";import{canPrompt as g,isDryRun as p,isNonInteractive as m,shouldAutoConfirm as _}from"../lib/runtime-options.js";const u=/^[a-zA-Z0-9._-]+$/;function y(o,e){const t=(o||"").trim();if(!t||!u.test(t))throw new Error(r.t(`config.${e}_invalid_name`,{name:t||"<empty>"}));return t}function v(o,t){console.log("\n"+e.bold(o)),0!==t.length?t.forEach(o=>console.log(" "+o)):console.log(e.gray(" ("+r.t("config.empty_list")+")"))}function w(o,t){if("backups"===t){const t=l.listToolBackups(o).flatMap(o=>{const t=o.file.replace(/^.*[/\\]/,"");return o.backups.length?o.backups.map(o=>`${e.cyan(t)} ${e.gray(o.name.split(".bak-")[1]||o.name)}`):[`${e.cyan(t)} ${e.gray("("+r.t("config.empty_list")+")")}`]});return void v(r.t("config.tool_backups_title",{tool:i[o].displayName}),t)}const n=l.restorePrivateConfig(o).filter(o=>o.result.restored);0!==n.length?(console.log(e.green(r.t("config.config_restored",{tool:i[o].displayName}))),n.forEach(o=>console.log(e.gray(` ${o.file} ← ${o.result.from}`))),console.log(e.yellow(" ! "+r.t("config.reopen_hint",{tool:i[o].displayName})))):console.log(e.yellow(r.t("config.restore_no_backup",{tool:i[o].displayName})))}async function b(s,m,_){if(!i[s])return void console.log(e.red(r.t("config.unknown_tool",{tool:s})));const u=(m[0]||"").toLowerCase();if("backups"!==u&&"list-backups"!==u)if("restore"!==u){if("remove"===u||"unload"===u){const o=i[s].displayName;return void await d({description:r.t("config.remove_dry_run",{tool:o}),json:{action:"remove",tool:s},apply:async()=>{if(!await c({message:r.t("config.confirm_remove",{tool:o,name:s}),defaultValue:!0}))return;const t=l.holdsOurConfig(s),n=l.unloadPrivateConfig(s);t?(console.log(e.green(r.t("config.remove_done",{tool:o}))),n.forEach(o=>console.log(e.yellow(" ! "+o.text)))):console.log(e.gray(r.t("config.remove_nothing",{tool:o})))}})}if("clear-model"===u||"clear-models"===u){const o=i[s].displayName;return l.supportsClearPinnedModels(s)?void await d({description:r.t("config.clear_model_dry_run",{tool:o}),json:{action:"clear_model",tool:s},apply:async()=>{const t=await l.clearPinnedModels(s);0!==t.length?(console.log(e.green(r.t("config.clear_model_done",{tool:o}))),t.forEach(o=>console.log(e.gray(` - ${o}`))),console.log(e.gray(r.t("config.clear_model_restart_hint",{tool:o})))):console.log(e.yellow(r.t("config.clear_model_none",{tool:o})))}}):void console.log(e.yellow(r.t("config.clear_model_unsupported",{tool:o})))}if(p())await d({description:r.t("config.tool_apply_dry_run",{tool:i[s].displayName}),json:{action:"apply",tool:s,force:Boolean(_.force)},apply:()=>{}});else{if(!l.isToolInstalled(s)){if(_.nonInteractive)return void console.log(e.yellow(r.t("wizard.tool_not_installed",{tool:i[s].displayName})));if(console.log(e.yellow(r.t("wizard.tool_not_installed",{tool:i[s].displayName}))),!g())return;const{shouldInstall:t}=await o.prompt([{type:"confirm",name:"shouldInstall",message:r.t("wizard.install_tool_confirm"),default:!0}]);if(!t)return void console.log(e.yellow(r.t("wizard.install_skipped")));try{await l.installTool(s)}catch(o){return console.error(e.red(r.t("install.install_failed_detail"))),void(o instanceof Error&&o.message&&console.error(e.gray(o.message)))}}if(_.nonInteractive||_.force){const o=a.getApiKeyForTool(s);if(!o)return void console.log(e.red(r.t("auth.reload_missing_config")));if(_.force&&!_.nonInteractive&&!await c({message:r.t("config.confirm_force",{tool:i[s].displayName}),defaultValue:!1}))return;return await l.applyPrivateConfig(s,o,a.getModelsForTool(s),{force:_.force,takeOver:!0}),_.force&&console.log(e.yellow(r.t("config.force_done",{tool:i[s].displayName,name:s}))),l.printApplied(s),void await n([s])}f(),await t.showToolMenu(s)}}else await d({description:r.t("config.tool_restore_dry_run",{tool:i[s].displayName}),json:{action:"tool_restore",tool:s},apply:async()=>{await c({message:r.t("config.confirm_restore",{tool:i[s].displayName}),defaultValue:!1})&&w(s,"restore")}});else w(s,"backups")}export async function configCommand(t){const{positional:n,options:l}=function(o){const e=[],t={};(m()||_())&&(t.nonInteractive=!0);for(const n of o)"--non-interactive"===n||"-y"===n?t.nonInteractive=!0:"--force"===n||"-f"===n?t.force=!0:e.push(n);return{positional:e,options:t}}(t),f=n[0],p=n.slice(1);if(f){switch(f){case"profile":return void await async function(o){const t=o[0],n=o[1];if(!t||"list"===t){const o=a.getActiveProfileName(),t=a.listProfiles().map(t=>{const n=t===o;return`${n?e.green("●"):e.gray("○")} ${t}${n?e.gray(" ("+r.t("config.profile_active_label")+")"):""}`});return void v(r.t("config.profile_list_title"),t)}if("create"===t){const o=y(n,"profile");return a.listProfiles().includes(o)?void console.log(e.yellow(r.t("config.profile_exists",{name:o}))):void await d({description:r.t("config.profile_create_dry_run",{name:o}),json:{action:"profile_create",name:o},apply:()=>{a.createProfile(o),console.log(e.green(r.t("config.profile_created",{name:o})))}})}if("use"===t){const o=y(n,"profile");return void await d({description:r.t("config.profile_use_dry_run",{name:o}),json:{action:"profile_use",name:o},apply:()=>{a.setActiveProfile(o),console.log(e.green(r.t("config.profile_activated",{name:o})))}})}if("delete"===t||"remove"===t){const o=y(n,"profile");return o===s&&1===a.listProfiles().length?void console.log(e.yellow(r.t("config.profile_cannot_delete_last"))):void await d({description:r.t("config.profile_delete_dry_run",{name:o}),json:{action:"profile_delete",name:o},apply:async()=>{await c({message:r.t("config.profile_delete_confirm",{name:o}),defaultValue:!1})?(a.deleteProfile(o),console.log(e.green(r.t("config.profile_deleted",{name:o})))):console.log(e.yellow(r.t("config.profile_delete_aborted")))}})}console.log(e.red(r.t("config.unknown_action",{action:t})))}(p);case"preset":return void await async function(o){const t=o[0],n=o[1];if(!t||"list"===t){const o=Object.entries(a.getCustomPresets()).map(([o,t])=>`${e.cyan(o)} ${e.gray(`H:${t.models.haiku} S:${t.models.sonnet} O:${t.models.opus}`)}`);return void v(r.t("config.preset_list_title"),o)}if("save"===t){const o=y(n,"preset");return void await d({description:r.t("config.preset_save_dry_run",{name:o}),json:{action:"preset_save",name:o},apply:()=>{a.saveCustomPreset(o,a.getModels()),console.log(e.green(r.t("config.preset_saved",{name:o})))}})}if("use"===t||"apply"===t){const o=y(n,"preset"),t=a.getCustomPresets()[o];return t?void await d({description:r.t("config.preset_use_dry_run",{name:o}),json:{action:"preset_use",name:o},apply:()=>{a.setModels(t.models),console.log(e.green(r.t("config.preset_applied",{name:o})))}}):void console.log(e.red(r.t("config.preset_not_found",{name:o})))}if("delete"===t||"remove"===t){const o=y(n,"preset");return void await d({description:r.t("config.preset_delete_dry_run",{name:o}),json:{action:"preset_delete",name:o},apply:()=>{a.deleteCustomPreset(o),console.log(e.green(r.t("config.preset_deleted",{name:o})))}})}console.log(e.red(r.t("config.unknown_action",{action:t})))}(p);case"tool-model":return void await async function(o){const t=o[0];if(!t||"list"===t){const o=a.getProfile().tool_models||{},t=Object.entries(o).map(([o,t])=>{const n=Object.entries(t).map(([o,e])=>`${o}=${e}`).join(" ");return`${e.cyan(o)} ${e.gray(n)}`});return void v(r.t("config.tool_model_list_title"),t)}if("set"===t){const t=(o[1]||"").trim(),n=o.length>=4?(o[2]||"").trim():"opus",l=(o.length>=4?o[3]:o[2]||"").trim();return i[t]?l&&u.test(n)?void await d({description:r.t("config.tool_model_set_dry_run",{tool:t,slot:n,model:l}),json:{action:"tool_model_set",tool:t,slot:n,model:l},apply:()=>{a.setToolModel(t,{[n]:l}),console.log(e.green(r.t("config.tool_model_set",{tool:t,slot:n,model:l})))}}):void console.log(e.red(r.t("config.tool_model_usage"))):void console.log(e.red(t?r.t("config.unknown_tool",{tool:t}):r.t("config.tool_model_usage")))}if("clear"===t||"remove"===t){const t=(o[1]||"").trim();return i[t]?void await d({description:r.t("config.tool_model_clear_dry_run",{tool:t}),json:{action:"tool_model_clear",tool:t},apply:()=>{a.setToolModel(t,null),console.log(e.green(r.t("config.tool_model_cleared",{tool:t})))}}):void console.log(e.red(t?r.t("config.unknown_tool",{tool:t}):r.t("config.tool_model_usage")))}console.log(e.red(r.t("config.unknown_action",{action:t})))}(p);case"backup":return void await function(o){return async function(o){const t=o[0],n=o[1];if(!t||"list"===t){const o=a.listBackups().map(o=>{const t=new Date(o.mtimeMs).toISOString();return`${e.cyan(o.name)} ${e.gray(t)}`});return void v(r.t("config.backup_list_title"),o)}if("create"!==t&&"snapshot"!==t)return"restore"===t?n?void await d({description:r.t("config.backup_restore_dry_run",{name:n}),json:{action:"backup_restore",name:n},apply:async()=>{await c({message:r.t("config.backup_restore_confirm",{name:n}),defaultValue:!1})?(a.restoreBackup(n),console.log(e.green(r.t("config.backup_restored",{name:n})))):console.log(e.yellow(r.t("config.backup_restore_aborted")))}}):void console.log(e.red(r.t("config.backup_restore_missing_name"))):void console.log(e.red(r.t("config.unknown_action",{action:t})));await d({description:r.t("config.backup_create_dry_run"),json:{action:"backup_create",name:n??null},apply:()=>{const o=a.createBackup(n);console.log(e.green(r.t("config.backup_created",{path:o})))}})}(o)}(p)}"claude-code"!==f&&"claude-code"!==p[0]?i[f]?await b(f,p,l):(console.error(e.red(r.t("config.unknown_command",{command:f}))),console.log(e.gray(r.t("config.usage_hint"))),Object.values(i).filter(o=>!o.hidden).forEach(o=>{console.log(e.gray(` - ${o.name}: ${o.displayName}`))})):await b("claude-code",p,l)}else await async function(t){if(t.nonInteractive||!g())return void console.log(e.red(r.t("config.requires_argument")));const{selectedTool:n}=await o.prompt([{type:"list",name:"selectedTool",message:r.t("wizard.select_tool"),choices:Object.values(i).filter(o=>!o.hidden).map(o=>({name:`${o.displayName} (${o.name})`,value:o.name}))}]);await b(n,[],t)}(l)}
@@ -1 +1 @@
1
- import{refreshClientConfig as o}from"../lib/client-config-sync.js";import t from"chalk";import e from"ora";import{spawnSync as s}from"child_process";import{existsSync as r,readdirSync as n,readFileSync as a}from"fs";import{connect as c}from"net";import{join as i}from"path";import{configManager as l}from"../lib/config.js";import{savedApiKey as d}from"./base.js";import{toolManager as p}from"../lib/tool-manager.js";import{i18n as u}from"../lib/i18n.js";import{validateApiKey as m}from"../lib/api-validator.js";import{getAdapter as f}from"../lib/tools/registry.js";import{findInstalls as _,installLabel as g}from"../lib/tools/tool-installs.js";import{detectManagedOverrides as h}from"../lib/tools/claude-managed.js";import{codexAuthProblem as y,codexCatalogRejection as k,codexConfigPath as b,codexWorkModeOn as w}from"../lib/tools/codex.js";import{claudeAccountLoginPresent as v}from"../lib/tools/claude-code.js";import{toolHome as j}from"../lib/tools/types.js";import{gatewayAddresses as x,probeGatewayAddress as $}from"../lib/gateway-addresses.js";import{listAdapters as T}from"../lib/tools/registry.js";import{logger as A}from"../utils/logger.js";import{maskHome as P,maskSecrets as R,uploadReport as N}from"../lib/telemetry.js";import{CLI_NAME as O}from"../lib/brand.js";import{appStatus as C,appStatusText as I,appTools as H,appUpgradeCommand as L}from"../lib/app-update.js";import{balanceLookupEnabled as S,balanceNeedsAttention as U,balanceText as E,fetchKeyBalances as K}from"../lib/key-balance.js";const B=["HTTPS_PROXY","https_proxy","HTTP_PROXY","http_proxy","ALL_PROXY","all_proxy"];function G(o,t,e=3e3){return new Promise(s=>{const r=c({host:o,port:t}),n=o=>{r.destroy(),s(o)};r.setTimeout(e,()=>n(!1)),r.once("connect",()=>n(!0)),r.once("error",()=>n(!1))})}function D(){const o=A.getLogDir();if(!r(o))return"";const t=n(o).filter(o=>/^\d{4}-\d{2}-\d{2}\.log$/.test(o)).sort().slice(-2).map(t=>`== ${t}\n`+a(i(o,t),"utf-8")).join("\n");return R(t.slice(-15e4))}function q(){const o={};for(const t of B){const e=process.env[t]?.trim();if(e)try{const s=new URL(e.includes("://")?e:`http://${e}`);o[t]=`${s.protocol}//${s.host}`}catch{o[t]="(unparsable)"}}return o}export async function doctorCommand(r={}){const n=e(u.t("doctor.checking")).start(),c=[],A=Number(process.versions.node.split(".")[0]);c.push({name:"Node.js",status:A>=20?"pass":"fail",message:`v${process.versions.node}`}),n.text=u.t("doctor.check_proxy"),c.push(await async function(){const o=u.t("doctor.proxy"),t=new Map;for(const o of B){const e=process.env[o]?.trim();e&&!t.has(e)&&t.set(e,o)}if(0===t.size)return{name:o,status:"pass",message:u.t("doctor.proxy_none")};const e=[];for(const[o,s]of t){let t;try{t=new URL(o.includes("://")?o:`http://${o}`)}catch{e.push(`${s}=${o}`);continue}const r=Number(t.port)||("https:"===t.protocol?443:t.protocol.startsWith("socks")?1080:80);await G(t.hostname,r)||e.push(`${s}=${o}`)}return 0===e.length?{name:o,status:"pass",message:[...t.keys()].join(", ")}:{name:o,status:"fail",message:u.t("doctor.proxy_dead",{proxies:e.join(", ")})}}()),n.text=u.t("doctor.check_api_key_network");const R=d(),F=u.t("doctor.api_key_network");if(R){const o=await m(R);o.valid?(c.push({name:F,status:"pass"}),n.text=u.t("doctor.check_balance"),c.push(...await async function(o){if(!S())return[];const t=l.listToolApiKeys().map(o=>({tool:o,key:l.getApiKeyForTool(o)})).filter(t=>Boolean(t.key)&&t.key!==o),e=await K([o,...t.map(o=>o.key)]),s=[{name:u.t("doctor.balance"),key:o},...t.map(o=>({name:u.t("doctor.balance_tool",{tool:f(o.tool)?.displayName??o.tool}),key:o.key}))],r=[];for(const o of s){const t=e.get(o.key);t&&r.push({name:o.name,status:U(t)?"warn":"pass",message:E(t)})}return r}(R))):"invalid_api_key"===o.error?c.push({name:F,status:"fail",message:u.t("doctor.api_key_invalid")}):(c.push({name:F,status:"fail",message:`${u.t("doctor.network_error")}: ${o.message??o.error}`}),n.text=u.t("doctor.check_other_addresses"),c.push(await async function(){const o=u.t("doctor.other_addresses"),t=l.getBaseUrl(),e=x().filter(o=>o.url!==t),s=d(),r=await Promise.all(e.map(o=>$(o.url,{apiKey:s}))),n=e.filter((o,t)=>r[t].ok).map(o=>o.url);return 0===n.length?{name:o,status:"fail",message:u.t("doctor.other_addresses_none")}:{name:o,status:"warn",message:u.t("doctor.other_addresses_found",{urls:n.join(", ")})}}()))}else c.push({name:F,status:"fail",message:u.t("doctor.api_key_missing")});n.text=u.t("doctor.check_client_config");const M=await o();c.push({name:u.t("doctor.client_config"),status:"cloud"===M.source||"cache"===M.source&&!M.problem?"pass":"warn",message:[M.source?u.t(`refresh.source.${M.source}`):u.t("refresh.source.none"),M.revision?u.t("doctor.client_config_revision",{revision:M.revision}):"",M.problem??""].filter(Boolean).join(" · ")}),n.text=u.t("doctor.check_tools");const X=p.getInstalledTools();c.push({name:u.t("doctor.installed_tools"),status:X.length>0?"pass":"warn",message:X.length>0?X.map(o=>f(o)?.displayName??o).join(u.t("setup.list_separator")):u.t("doctor.no_tools_installed")}),c.push(...function(){const o=[];for(const t of p.getInstalledTools()){const e=f(t);if(!e?.installSpec)continue;const s=_(e.installSpec);if(0===s.length)continue;const r=[],n=p.outdatedVersion(t);n&&r.push(u.t("doctor.tool_outdated",{min:n.min})),s.length>1&&r.push(u.t("doctor.tool_duplicates",{others:s.slice(1).map(g).join("、")})),o.push({name:e.displayName,status:r.length>0?"warn":"pass",message:[g(s[0]),...r,...r.length>0?[u.t("doctor.run_upgrade",{tool:t})]:[]].join("\n ")})}return o}()),c.push(...await async function(){const o=[];for(const t of H()){const e=await C(t,{refresh:!0});if(!e.installed||!e.current)continue;const s=u.t("doctor.app_version",{tool:e.name});if(e.outdated){const r=e.blocker?u.t(`app_update.blocked_${e.blocker}`,{tool:e.name}):u.t("doctor.run_app_upgrade",{command:L(t)});o.push({name:s,status:"warn",message:`${I(e)}\n ${r}`})}else o.push({name:s,status:"pass",message:I(e)})}return o}());const Y=function(){if(!p.isToolInstalled("claude-code"))return null;const o=u.t("doctor.claude_config"),t=h();if(t.length>0){const e=t.map(o=>`${o.source}: ${o.keys.join(", ")}`).join("; ");return{name:o,status:"fail",message:u.t("doctor.claude_managed",{detail:e})}}let e={};try{e=JSON.parse(a(i(process.env.CLAUDE_CONFIG_DIR?.trim()||i(j(),".claude"),"settings.json"),"utf-8")).env??{}}catch{}const s=l.getApiKeyForTool("claude-code");return e.ANTHROPIC_AUTH_TOKEN&&e.ANTHROPIC_BASE_URL?e.ANTHROPIC_BASE_URL!==l.getBaseUrl()||s&&e.ANTHROPIC_AUTH_TOKEN!==s?{name:o,status:"warn",message:u.t("doctor.claude_config_changed")}:{name:o,status:"pass"}:{name:o,status:"warn",message:u.t("doctor.claude_not_configured")}}();Y&&c.push(Y),X.includes("claude-code")&&v()&&c.push({name:u.t("doctor.claude_login"),status:"pass",message:u.t("tools.claude_code.account_login_overridden")});const V=X.includes("codex")?y():null;if(X.includes("codex")&&c.push({name:u.t("doctor.codex_auth"),status:V?"fail":"pass",message:V?u.t(`doctor.codex_${V}`,{path:P(b())}):void 0}),X.includes("codex")){const o=k();c.push({name:u.t("doctor.codex_catalog"),status:o?"fail":"pass",message:o?u.t("doctor.codex_catalog_rejected",{path:o.bin,version:o.version??"?",error:o.error}):void 0})}X.includes("codex")&&w()&&c.push({name:u.t("doctor.codex_work_mode"),status:"warn",message:u.t("tools.codex.work_mode_on")}),"win32"===process.platform&&X.includes("claude-code")&&!process.env.CLAUDE_CODE_GIT_BASH_PATH&&c.push({name:"Git for Windows",status:p.isGitInstalled()?"pass":"warn",message:p.isGitInstalled()?void 0:u.t("tools.claude_code.no_git_bash")}),r.deep&&X.includes("claude-code")&&(n.text=u.t("doctor.check_claude_request"),c.push(function(){const o=u.t("doctor.claude_request"),t=_(f("claude-code").installSpec)[0];if(!t)return{name:o,status:"warn",message:u.t("doctor.claude_request_skipped")};const e={encoding:"utf-8",timeout:12e4,windowsHide:!0,stdio:["ignore","pipe","pipe"]},r=["-p","Reply with the single word OK."],n=/\.cmd$/i.test(t.path)?s(`"${t.path}" ${r.map(o=>`"${o}"`).join(" ")}`,{...e,shell:!0}):s(t.path,r,e),a=`${n.stdout??""}`.trim();if(0===n.status&&a)return{name:o,status:"pass",message:a.slice(0,80)};const c=(`${n.stderr??""}`.trim()||a||n.error?.message||`exit ${n.status}`).slice(0,300);return{name:o,status:"fail",message:u.t("doctor.claude_request_failed",{reason:c})}}())),n.stop(),console.log("\n"+t.bold(u.t("doctor.results_title"))+"\n");const W={pass:t.green("√"),warn:t.yellow("!"),fail:t.red("×")};for(const o of c)console.log(`${W[o.status]} ${o.name}`),o.message&&console.log(t.gray(` ${o.message}`));if(c.every(o=>"pass"===o.status)&&console.log("\n"+t.green.bold(u.t("doctor.all_good"))),!r.deep&&X.includes("claude-code")&&console.log(t.gray("\n"+u.t("doctor.deep_hint"))),r.report){const o=e(u.t("doctor.report_uploading")).start(),t=await N(function(o,t){const e={};for(const o of T()){if(o.hidden)continue;let t=null;try{t=p.detectCurrentConfig(o.name).apiKey?"has_key":"no_key"}catch{t="unreadable"}e[o.name]={installed:p.isToolInstalled(o.name),version:p.installedVersion(o.name),copies:o.installSpec?_(o.installSpec).map(o=>({kind:o.kind,version:o.version,path:o.path})):void 0,config:t}}const s=l.getProfile();return{checks:o,tools:e,settings:{base_url:l.getBaseUrl(),profile:l.getActiveProfileName(),profiles:l.listProfiles().length,key_fingerprint:l.getApiKeyFingerprint()||null,tool_keys:Object.keys(s.tool_api_keys??{}),models:s.models,tool_models:s.tool_models??{},tool_settings:s.tool_settings??{},lang:l.getLang()},client_config:t,env:{shell:process.env.SHELL??process.env.ComSpec??null,term:process.env.TERM_PROGRAM??null,proxies:q()},log:D()}}(c,{source:M.source??void 0,revision:M.revision,problem:M.problem}));t?o.succeed(u.t("doctor.report_done",{code:t})):o.fail(u.t("doctor.report_failed",{cli:O}))}else c.some(o=>"fail"===o.status)&&console.log(t.gray("\n"+u.t("doctor.report_hint",{cli:O})));c.some(o=>"fail"===o.status)&&(process.exitCode=1)}
1
+ import{refreshClientConfig as o}from"../lib/client-config-sync.js";import t from"chalk";import e from"ora";import{spawnSync as s}from"child_process";import{existsSync as r,readdirSync as n,readFileSync as a}from"fs";import{connect as c}from"net";import{join as i}from"path";import{configManager as l}from"../lib/config.js";import{savedApiKey as d}from"./base.js";import{toolManager as p}from"../lib/tool-manager.js";import{i18n as u}from"../lib/i18n.js";import{validateApiKey as m}from"../lib/api-validator.js";import{getAdapter as f}from"../lib/tools/registry.js";import{findInstalls as _,installLabel as g}from"../lib/tools/tool-installs.js";import{detectManagedOverrides as h}from"../lib/tools/claude-managed.js";import{codexAuthProblem as y,codexCatalogRejection as k,codexConfigPath as w,codexWorkModeOn as b}from"../lib/tools/codex.js";import{claudeAccountLoginPresent as v}from"../lib/tools/claude-code.js";import{toolHome as j}from"../lib/tools/types.js";import{gatewayAddresses as x,probeGatewayAddress as $}from"../lib/gateway-addresses.js";import{listAdapters as T}from"../lib/tools/registry.js";import{logger as A}from"../utils/logger.js";import{maskHome as P,maskSecrets as R,uploadReport as N}from"../lib/telemetry.js";import{CLI_NAME as O}from"../lib/brand.js";import{appStatus as I,appStatusText as C,appTools as H,appUpgradeCommand as L,getApp as S}from"../lib/app-update.js";import{balanceLookupEnabled as U,balanceNeedsAttention as E,balanceText as K,fetchKeyBalances as B}from"../lib/key-balance.js";const G=["HTTPS_PROXY","https_proxy","HTTP_PROXY","http_proxy","ALL_PROXY","all_proxy"];function D(o,t,e=3e3){return new Promise(s=>{const r=c({host:o,port:t}),n=o=>{r.destroy(),s(o)};r.setTimeout(e,()=>n(!1)),r.once("connect",()=>n(!0)),r.once("error",()=>n(!1))})}function q(){const o=A.getLogDir();if(!r(o))return"";const t=n(o).filter(o=>/^\d{4}-\d{2}-\d{2}\.log$/.test(o)).sort().slice(-2).map(t=>`== ${t}\n`+a(i(o,t),"utf-8")).join("\n");return R(t.slice(-15e4))}function F(){const o={};for(const t of G){const e=process.env[t]?.trim();if(e)try{const s=new URL(e.includes("://")?e:`http://${e}`);o[t]=`${s.protocol}//${s.host}`}catch{o[t]="(unparsable)"}}return o}export async function doctorCommand(r={}){const n=e(u.t("doctor.checking")).start(),c=[],A=Number(process.versions.node.split(".")[0]);c.push({name:"Node.js",status:A>=20?"pass":"fail",message:`v${process.versions.node}`}),n.text=u.t("doctor.check_proxy"),c.push(await async function(){const o=u.t("doctor.proxy"),t=new Map;for(const o of G){const e=process.env[o]?.trim();e&&!t.has(e)&&t.set(e,o)}if(0===t.size)return{name:o,status:"pass",message:u.t("doctor.proxy_none")};const e=[];for(const[o,s]of t){let t;try{t=new URL(o.includes("://")?o:`http://${o}`)}catch{e.push(`${s}=${o}`);continue}const r=Number(t.port)||("https:"===t.protocol?443:t.protocol.startsWith("socks")?1080:80);await D(t.hostname,r)||e.push(`${s}=${o}`)}return 0===e.length?{name:o,status:"pass",message:[...t.keys()].join(", ")}:{name:o,status:"fail",message:u.t("doctor.proxy_dead",{proxies:e.join(", ")})}}()),n.text=u.t("doctor.check_api_key_network");const R=d(),M=u.t("doctor.api_key_network");if(R){const o=await m(R);o.valid?(c.push({name:M,status:"pass"}),n.text=u.t("doctor.check_balance"),c.push(...await async function(o){if(!U())return[];const t=l.listToolApiKeys().map(o=>({tool:o,key:l.getApiKeyForTool(o)})).filter(t=>Boolean(t.key)&&t.key!==o),e=await B([o,...t.map(o=>o.key)]),s=[{name:u.t("doctor.balance"),key:o},...t.map(o=>({name:u.t("doctor.balance_tool",{tool:f(o.tool)?.displayName??o.tool}),key:o.key}))],r=[];for(const o of s){const t=e.get(o.key);t&&r.push({name:o.name,status:E(t)?"warn":"pass",message:K(t)})}return r}(R))):"invalid_api_key"===o.error?c.push({name:M,status:"fail",message:u.t("doctor.api_key_invalid")}):(c.push({name:M,status:"fail",message:`${u.t("doctor.network_error")}: ${o.message??o.error}`}),n.text=u.t("doctor.check_other_addresses"),c.push(await async function(){const o=u.t("doctor.other_addresses"),t=l.getBaseUrl(),e=x().filter(o=>o.url!==t),s=d(),r=await Promise.all(e.map(o=>$(o.url,{apiKey:s}))),n=e.filter((o,t)=>r[t].ok).map(o=>o.url);return 0===n.length?{name:o,status:"fail",message:u.t("doctor.other_addresses_none")}:{name:o,status:"warn",message:u.t("doctor.other_addresses_found",{urls:n.join(", ")})}}()))}else c.push({name:M,status:"fail",message:u.t("doctor.api_key_missing")});n.text=u.t("doctor.check_client_config");const X=await o();c.push({name:u.t("doctor.client_config"),status:"cloud"===X.source||"cache"===X.source&&!X.problem?"pass":"warn",message:[X.source?u.t(`refresh.source.${X.source}`):u.t("refresh.source.none"),X.revision?u.t("doctor.client_config_revision",{revision:X.revision}):"",X.problem??""].filter(Boolean).join(" · ")}),n.text=u.t("doctor.check_tools");const Y=p.getInstalledTools();c.push({name:u.t("doctor.installed_tools"),status:Y.length>0?"pass":"warn",message:Y.length>0?Y.map(o=>f(o)?.displayName??o).join(u.t("setup.list_separator")):u.t("doctor.no_tools_installed")}),c.push(...function(){const o=[];for(const t of p.getInstalledTools()){const e=f(t);if(!e?.installSpec)continue;const s=_(e.installSpec);if(0===s.length)continue;const r=[],n=p.outdatedVersion(t);n&&r.push(u.t("doctor.tool_outdated",{min:n.min})),s.length>1&&r.push(u.t("doctor.tool_duplicates",{others:s.slice(1).map(g).join("、")})),o.push({name:e.displayName,status:r.length>0?"warn":"pass",message:[g(s[0]),...r,...r.length>0?[u.t("doctor.run_upgrade",{tool:t})]:[]].join("\n ")})}return o}()),c.push(...await async function(){const o=[];for(const t of H()){const e=await I(t,{refresh:!0});if(!e.installed||!e.current)continue;const s=u.t("doctor.app_version",{tool:e.name});if(e.outdated){const r=e.blocker?u.t(`app_update.blocked_${e.blocker}`,{tool:e.name,url:S(t)?.appInstaller.downloadPage??"",command:L(t)}):u.t("doctor.run_app_upgrade",{command:L(t)});o.push({name:s,status:"warn",message:`${C(e)}\n ${r}`})}else o.push({name:s,status:"pass",message:C(e)})}return o}());const V=function(){if(!p.isToolInstalled("claude-code"))return null;const o=u.t("doctor.claude_config"),t=h();if(t.length>0){const e=t.map(o=>`${o.source}: ${o.keys.join(", ")}`).join("; ");return{name:o,status:"fail",message:u.t("doctor.claude_managed",{detail:e})}}let e={};try{e=JSON.parse(a(i(process.env.CLAUDE_CONFIG_DIR?.trim()||i(j(),".claude"),"settings.json"),"utf-8")).env??{}}catch{}const s=l.getApiKeyForTool("claude-code");return e.ANTHROPIC_AUTH_TOKEN&&e.ANTHROPIC_BASE_URL?e.ANTHROPIC_BASE_URL!==l.getBaseUrl()||s&&e.ANTHROPIC_AUTH_TOKEN!==s?{name:o,status:"warn",message:u.t("doctor.claude_config_changed")}:{name:o,status:"pass"}:{name:o,status:"warn",message:u.t("doctor.claude_not_configured")}}();V&&c.push(V),Y.includes("claude-code")&&v()&&c.push({name:u.t("doctor.claude_login"),status:"pass",message:u.t("tools.claude_code.account_login_overridden")});const W=Y.includes("codex")?y():null;if(Y.includes("codex")&&c.push({name:u.t("doctor.codex_auth"),status:W?"fail":"pass",message:W?u.t(`doctor.codex_${W}`,{path:P(w())}):void 0}),Y.includes("codex")){const o=k();c.push({name:u.t("doctor.codex_catalog"),status:o?"fail":"pass",message:o?u.t("doctor.codex_catalog_rejected",{path:o.bin,version:o.version??"?",error:o.error}):void 0})}Y.includes("codex")&&b()&&c.push({name:u.t("doctor.codex_work_mode"),status:"warn",message:u.t("tools.codex.work_mode_on")}),"win32"===process.platform&&Y.includes("claude-code")&&!process.env.CLAUDE_CODE_GIT_BASH_PATH&&c.push({name:"Git for Windows",status:p.isGitInstalled()?"pass":"warn",message:p.isGitInstalled()?void 0:u.t("tools.claude_code.no_git_bash")}),r.deep&&Y.includes("claude-code")&&(n.text=u.t("doctor.check_claude_request"),c.push(function(){const o=u.t("doctor.claude_request"),t=_(f("claude-code").installSpec)[0];if(!t)return{name:o,status:"warn",message:u.t("doctor.claude_request_skipped")};const e={encoding:"utf-8",timeout:12e4,windowsHide:!0,stdio:["ignore","pipe","pipe"]},r=["-p","Reply with the single word OK."],n=/\.cmd$/i.test(t.path)?s(`"${t.path}" ${r.map(o=>`"${o}"`).join(" ")}`,{...e,shell:!0}):s(t.path,r,e),a=`${n.stdout??""}`.trim();if(0===n.status&&a)return{name:o,status:"pass",message:a.slice(0,80)};const c=(`${n.stderr??""}`.trim()||a||n.error?.message||`exit ${n.status}`).slice(0,300);return{name:o,status:"fail",message:u.t("doctor.claude_request_failed",{reason:c})}}())),n.stop(),console.log("\n"+t.bold(u.t("doctor.results_title"))+"\n");const z={pass:t.green("√"),warn:t.yellow("!"),fail:t.red("×")};for(const o of c)console.log(`${z[o.status]} ${o.name}`),o.message&&console.log(t.gray(` ${o.message}`));if(c.every(o=>"pass"===o.status)&&console.log("\n"+t.green.bold(u.t("doctor.all_good"))),!r.deep&&Y.includes("claude-code")&&console.log(t.gray("\n"+u.t("doctor.deep_hint"))),r.report){const o=e(u.t("doctor.report_uploading")).start(),t=await N(function(o,t){const e={};for(const o of T()){if(o.hidden)continue;let t=null;try{t=p.detectCurrentConfig(o.name).apiKey?"has_key":"no_key"}catch{t="unreadable"}e[o.name]={installed:p.isToolInstalled(o.name),version:p.installedVersion(o.name),copies:o.installSpec?_(o.installSpec).map(o=>({kind:o.kind,version:o.version,path:o.path})):void 0,config:t}}const s=l.getProfile();return{checks:o,tools:e,settings:{base_url:l.getBaseUrl(),profile:l.getActiveProfileName(),profiles:l.listProfiles().length,key_fingerprint:l.getApiKeyFingerprint()||null,tool_keys:Object.keys(s.tool_api_keys??{}),models:s.models,tool_models:s.tool_models??{},tool_settings:s.tool_settings??{},lang:l.getLang()},client_config:t,env:{shell:process.env.SHELL??process.env.ComSpec??null,term:process.env.TERM_PROGRAM??null,proxies:F()},log:q()}}(c,{source:X.source??void 0,revision:X.revision,problem:X.problem}));t?o.succeed(u.t("doctor.report_done",{code:t})):o.fail(u.t("doctor.report_failed",{cli:O}))}else c.some(o=>"fail"===o.status)&&console.log(t.gray("\n"+u.t("doctor.report_hint",{cli:O})));c.some(o=>"fail"===o.status)&&(process.exitCode=1)}
@@ -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 w,isDryRun as v,isJsonMode as x,isNonInteractive as C,shouldAutoConfirm as j}from"../lib/runtime-options.js";import{appUpgradeCommand as K}from"../lib/app-update.js";import{join as $}from"path";import{confirmWritePlan as T,printWritePlan as G,toolWritePlan as M}from"../lib/write-plan.js";import N from"inquirer";import{logger as S}from"../utils/logger.js";import{forgetInstalls as E}from"../lib/tools/tool-installs.js";import{CLI_NAME as I,brandEnv as A}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 O(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 B(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 D(e){console.log(o.green(e))}function F(e){console.log(o.yellow(e))}function L(e){console.error(o.red(e))}let R=null;function P(o){const e={operation:1,authentication:2,network:3};(!R||e[o]>e[R])&&(R=o)}async function Y(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?`${I} setup --key ${a}`:`${I} setup ${e} ${a}`;let p;if("network_error"===i.error?(P("network"),p=_(l.t("setup.unreachable",{url:s.getBaseUrl(),reason:i.message||"network error"}),`${I} base auto`,"network_error")):"invalid_api_key"===i.error?(P("authentication"),p=y(l.t("setup.invalid_key",{label:e,reason:i.message||"invalid"}),n,"invalid_api_key")):(P("operation"),p=g(l.t("setup.validate_failed",{label:e,reason:i.message||i.error||"unknown"}),n,i.error)),x())throw p;return L(p.message),console.log(o.gray(l.t("errors.next_step",{command:p.hint}))),!1}async function q(t,i,r={}){const{oneMillion:p,officialLogin:c,desktopRegistry:u,force:y}=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})}catch(o){if(x())throw g(o instanceof Error?o.message:String(o),`${I} setup --key ${l.t("errors.key_placeholder")}`,"config_write_failed");const e=(o instanceof Error?o.message:String(o)).replace(/\s+/g," ").trim();return L("× "+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 H(o){return!e(o)?.isInstalled&&!a.isToolInstalled(o)}export async function installMissingApps(t,i){const s=t.filter(o=>{const t=e(o)?.appInstaller;try{return Boolean(t&&!t.blocker()&&!t.installedPath())}catch(e){return S.logError(`setup: app installed? ${o}`,e),!1}});if(0===s.length)return!1;let a=i;if(void 0===a&&h()&&!j()){const o=s.map(o=>n[o].displayName).join(l.t("setup.list_separator"));console.log(""),a=(await N.prompt([{type:"confirm",name:"go",message:l.t("setup.install_app_confirm",{tools:o}),default:!1}])).go}if(!a&&!x())for(const e of s)console.log(o.gray(l.t("setup.install_app_hint",{tool:n[e].displayName,command:K(e)})));return Boolean(a)}function W(o){F(l.t("setup.still_missing",{tools:o.map(o=>n[o].displayName).join(l.t("setup.list_separator")),commands:o.map(o=>`${I} config ${o} --yes`).join(l.t("setup.list_separator"))}))}function U(e,t,i=[]){const a=M(e),n=$(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")}`)}G(a,{label:l.t("runtime.dry_run_label"),keyFile:t?n:void 0,installFirst:i})}}function z(){return"darwin"===process.platform||"win32"===process.platform||a.isToolInstalled("claude-desktop")}export async function setupCommand(r){R=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 L(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 L(l.t("setup.desktop_registry_invalid",{value:String(r.desktopRegistry)})),void(process.exitCode=1);const b=g||_,w=Boolean(p||f.length>0),K={oneMillion:r.oneMillion,officialLogin:y,desktopRegistry:h,force:r.force};if(!w&&(m||b)&&v())return void U([...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),D(l.t(e?"setup.codex_1m_enabled":"setup.codex_1m_disabled"))}catch(o){L(l.t("setup.apply_failed",{tool:n.codex.displayName,reason:o instanceof Error?o.message:String(o)})),process.exitCode=1}else L(l.t("setup.codex_1m_missing_key")),process.exitCode=1}if(b){const o=s.getApiKeyForTool("claude-desktop");o?await q("claude-desktop",o,{...K,oneMillion:void 0})?await t(["claude-desktop"],{apps:{install:!1}}):process.exitCode=1:(L(l.t("setup.desktop_official_login_missing_key")),process.exitCode=1)}return}if(!w)return L(l.t("setup.usage")),void(process.exitCode=1);const G=v();G||await i(p||f[0].apiKey);const M=[],P=[];let J,Q=0,V=0;const X=new Set,Z=f.map(o=>({tool:o.tool,label:`--${o.option}`,apiKey:o.apiKey,need:o.need}));for(const o of Z){if(!await Y(o.label,o.apiKey)){V+=1;continue}const e=await O(o.apiKey);!e.probed||B(e,o.need)?(e.probed||F(l.t("setup.probe_failed",{label:o.label})),M.push({tool:o.tool,apiKey:o.apiKey,dedicated:!0}),X.add(o.tool)):(L(l.t(`setup.key_no_${o.need}`,{label:o.label,tool:n[o.tool].displayName})),V+=1)}const oo=!!p&&await Y("--key",p);p&&!oo&&(J=k[R??"operation"]);const eo=p&&oo?await O(p):void 0;if(p&&eo&&!eo.probed&&F(l.t("setup.probe_failed",{label:"--key"})),!(p&&eo&&eo.probed)||eo.hasClaude||eo.hasGpt||eo.hasGrok||eo.hasGemini||(L(l.t("setup.key_no_family")),J=1),p&&eo&&void 0===J){const o=[{tool:"claude-code",capable:eo.hasClaude,skipMsg:l.t(z()?"setup.skip_no_claude_desktop":"setup.skip_no_claude")},{tool:"codex",capable:eo.hasGpt,skipMsg:l.t("setup.skip_no_gpt")},{tool:"grok",capable:eo.hasGrok,skipMsg:l.t("setup.skip_no_grok")},{tool:"claude-desktop",capable:eo.hasClaude&&z(),skipMsg:"",quiet:!0},{tool:"agy",capable:eo.hasGemini,skipMsg:l.t("setup.skip_no_gemini")}];for(const e of o)X.has(e.tool)||(e.capable?(M.push({tool:e.tool,apiKey:p,dedicated:!1}),X.add(e.tool)):e.quiet||F(e.skipMsg))}const to=Boolean(p&&oo&&void 0===J);if(G)return U(M.filter(o=>!H(o.tool)).map(o=>o.tool),M.length>0,M.filter(o=>H(o.tool)).map(o=>o.tool)),void((V>0||void 0!==J)&&(process.exitCode=J??k[R??"operation"]));const io=M.filter(o=>!H(o.tool)),lo=to||M.some(o=>o.dedicated);if((M.length>0||lo)&&!r.fromInstaller&&!await T(io.map(o=>o.tool),{keyFile:lo?$(s.getConfigDir(),"config.yaml"):void 0,installFirst:M.filter(o=>H(o.tool)).map(o=>o.tool)}))return void(process.exitCode=k.cancelled);to&&p&&s.setApiKey(p);for(const o of M)o.dedicated&&s.setToolApiKey(o.tool,o.apiKey),H(o.tool)?P.push({tool:o.tool,apiKey:o.apiKey}):await q(o.tool,o.apiKey,K)?Q+=1:(V+=1,X.delete(o.tool));if(void 0!==J)return P.length>0&&W(P.map(o=>o.tool)),void(process.exitCode=J);let so=[];if(P.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:I}))),{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){S.logError(`setup: install ${e}`,o)}E(),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 q(o,t,i)?u.push(o):f.push(o);return{still:d,applied:u,failed:f}}(P,r.install,K);so=e.still,Q+=e.applied.length,V+=e.failed.length;for(const o of[...so,...e.failed])X.delete(o)}if(Q>0){const t=[...X].filter(o=>!e(o)?.isInstalled&&!so.includes(o)),i=t.map(o=>n[o]?.command).filter(Boolean).join(" / "),s=l.t("setup.done",{count:String(Q)});D("\n"+(i?`${s}${l.t("setup.done_commands",{commands:i})}`:s)),so.length>0&&W(so);for(const o of t){const e=a.ensureNativeOnPath(o);e&&D(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"!==A("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===Q&&so.length>0&&W(so),V>0&&(L(l.t("setup.failed_summary",{count:String(V)})),x()||console.error(`${I} setup --key ${l.t("errors.key_placeholder")}`)),await t([...X],{apps:{install:await installMissingApps([...X],r.install)}}),(V>0||0===Q&&0===so.length)&&(process.exitCode=k[R??"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 _,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 +1 @@
1
- import o from"chalk";import{appTools as t,upgradeApp as e}from"../lib/app-update.js";import{i18n as l}from"../lib/i18n.js";import{emitJson as r,isJsonMode as n}from"../lib/runtime-options.js";import{toolManager as i}from"../lib/tool-manager.js";import{getAdapter as s,listAdapters as a}from"../lib/tools/registry.js";import{upgradeTool as p}from"../lib/tool-upgrade.js";export async function upgradeCommand(d){const c=t(),u=[...a().filter(o=>o.installSpec).map(o=>o.name),...c],m=d.length>0?d:u.filter(o=>c.includes(o)?(o=>{const t=s(o)?.appInstaller;return Boolean(t&&!t.blocker()&&t.installedPath())})(o):i.isToolInstalled(o)),f=m.filter(o=>!u.includes(o));if(f.length>0)return console.error(o.red(l.t("upgrade.unsupported",{tool:f.join(", ")}))),console.error(l.t("upgrade.supported",{tools:u.join(" / ")})),void(process.exitCode=1);if(0===m.length)return void(n()?r({tools:[]}):console.log(l.t("upgrade.nothing_installed",{tools:u.join(" / ")})));let g=0;const j=[];for(const t of m){if(c.includes(t)){const l=s(t)?.displayName??t;n()||console.log(o.bold(`\n${l}`));const r=await e(t,{install:!0}),i=["installed","upgraded","up_to_date","declined"].includes(r.result);i||(g+=1),j.push({...r,ok:i});continue}const l=await p(t);l||(g+=1),j.push({tool:t,ok:l})}n()&&r({tools:j}),g>0&&(process.exitCode=1)}
1
+ import o from"chalk";import{appTools as t,getApp as e,upgradeApp as n}from"../lib/app-update.js";import{i18n as l}from"../lib/i18n.js";import{emitJson as r,isJsonMode as i,progressToStderr as s}from"../lib/runtime-options.js";import{toolManager as a}from"../lib/tool-manager.js";import{listAdapters as p}from"../lib/tools/registry.js";import{upgradeTool as c}from"../lib/tool-upgrade.js";import{listComponents as d,resolveComponent as m,runRuntime as u}from"../lib/components.js";import{outdatedRuntimeHints as f}from"./components.js";export async function upgradeCommand(g,h={}){const j=t(),b=new Set;g=g.map(o=>{const t=m(o);return t?("runtime"===t.category&&b.add(t.id),t.adapter??t.app??t.id):o});const w=[...p().filter(o=>o.installSpec).map(o=>o.name),...j,...b],y=g.length>0?g:w.filter(o=>j.includes(o)?(o=>{const t=e(o)?.appInstaller;return Boolean(t&&!t.blocker()&&t.installedPath())})(o):a.isToolInstalled(o)),k=y.filter(o=>!w.includes(o));if(k.length>0){console.error(o.red(l.t("upgrade.unsupported",{tool:k.join(", ")})));const t=d().filter(o=>"runtime"===o.category).map(o=>o.id);return console.error(l.t("upgrade.supported",{tools:[...new Set([...w,...t])].join(" / ")})),void(process.exitCode=1)}if(0===y.length)return void(i()?r({tools:[]}):console.log(l.t("upgrade.nothing_installed",{tools:w.join(" / ")})));let x=0;const C=[];for(const t of y){if(b.has(t)){const e=m(t);i()||console.log(o.bold(`\n${e.name}`));const n=await s(()=>u(e,"upgrade",{force:h.force}));n.ok||(x+=1),C.push(n);continue}if(j.includes(t)){const l=e(t)?.displayName??t;i()||console.log(o.bold(`\n${l}`));const r=await s(()=>n(t,{install:!0,force:h.force})),a=["installed","upgraded","up_to_date","declined"].includes(r.result);a||(x+=1),C.push({...r,ok:a});continue}const l=await s(()=>c(t));l||(x+=1),C.push({tool:t,ok:l})}if(i())r({tools:C});else if(0===g.length){const t=await f();t.length&&console.log("\n"+t.map(t=>o.yellow(" ! "+t)).join("\n"))}x>0&&(process.exitCode=1)}