@vibeapi/cli 0.0.148 → 0.0.150
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -17
- package/components.json +157 -0
- package/dist/commands/components.d.ts +26 -0
- package/dist/commands/components.js +1 -0
- package/dist/commands/config.js +1 -1
- package/dist/commands/setup.js +1 -1
- package/dist/commands/upgrade.d.ts +4 -2
- package/dist/commands/upgrade.js +1 -1
- package/dist/components.json +157 -0
- package/dist/lib/app-update.d.ts +20 -0
- package/dist/lib/app-update.js +1 -1
- package/dist/lib/brand.js +1 -1
- package/dist/lib/claude-code-manager.d.ts +4 -0
- package/dist/lib/claude-code-manager.js +1 -1
- package/dist/lib/command.d.ts +0 -5
- package/dist/lib/command.js +1 -1
- package/dist/lib/components.d.ts +204 -0
- package/dist/lib/components.js +1 -0
- package/dist/lib/config.d.ts +2 -0
- package/dist/lib/config.js +1 -1
- package/dist/lib/dry-run.js +1 -1
- package/dist/lib/env-cleanup.d.ts +32 -28
- package/dist/lib/env-cleanup.js +1 -1
- package/dist/lib/gateway-addresses.d.ts +4 -0
- package/dist/lib/gateway-addresses.js +1 -1
- package/dist/lib/model-registry.d.ts +2 -0
- package/dist/lib/model-registry.js +1 -1
- package/dist/lib/program.js +1 -1
- package/dist/lib/runtime-options.d.ts +5 -0
- package/dist/lib/runtime-options.js +1 -1
- package/dist/lib/tool-manager.d.ts +3 -0
- package/dist/lib/tool-manager.js +1 -1
- package/dist/lib/tool-upgrade.d.ts +2 -0
- package/dist/lib/tool-upgrade.js +1 -1
- package/dist/lib/tools/chatgpt-desktop.d.ts +14 -1
- package/dist/lib/tools/chatgpt-desktop.js +1 -1
- package/dist/lib/tools/claude-code.js +1 -1
- package/dist/lib/tools/claude-desktop.d.ts +1 -1
- package/dist/lib/tools/claude-desktop.js +1 -1
- package/dist/lib/tools/codex.js +1 -1
- package/dist/lib/tools/desktop-process.d.ts +4 -1
- package/dist/lib/tools/desktop-process.js +1 -1
- package/dist/lib/tools/tool-installs.d.ts +8 -0
- package/dist/lib/tools/tool-installs.js +1 -1
- package/dist/lib/tools/types.d.ts +26 -9
- package/dist/lib/wizard.js +1 -1
- package/dist/lib/write-plan.d.ts +2 -0
- package/dist/lib/write-plan.js +1 -1
- package/dist/lib/written-values.d.ts +21 -0
- package/dist/lib/written-values.js +1 -0
- package/dist/locales/en_US.json +140 -5
- package/dist/locales/zh_CN.json +140 -5
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# VibeCLI(@vibeapi/api-helper)
|
|
2
2
|
|
|
3
|
-
> 一条命令,为 Claude Code、Claude Desktop、Codex、Grok Build、Antigravity CLI 配置 VibeAPI
|
|
3
|
+
> 一条命令,为 Claude Code、Claude Desktop、Codex、Grok Build、Antigravity CLI 配置 VibeAPI 的令牌和模型;也能从国内镜像安装和升级这些工具,以及 Node.js、Git、uv、Claude Desktop、ChatGPT 桌面版(`vibecli list` / `install` / `upgrade`)。
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@vibeapi/api-helper)
|
|
6
6
|
[](https://nodejs.org)
|
|
@@ -44,6 +44,8 @@ npx --yes --registry https://npm.cnb.cool/vibeapi/npm/-/packages/ @vibeapi/cli@l
|
|
|
44
44
|
| Node.js | `curl -fsSL https://cnb.cool/vibeapi/install/-/git/raw/main/node.sh \| sh` | `irm https://cnb.cool/vibeapi/install/-/git/raw/main/node.ps1 \| iex` |
|
|
45
45
|
| Git | `curl -fsSL https://cnb.cool/vibeapi/install/-/git/raw/main/git.sh \| sh` | `irm https://cnb.cool/vibeapi/install/-/git/raw/main/git.ps1 \| iex` |
|
|
46
46
|
|
|
47
|
+
已经装好 VibeCLI(有 Node.js)时,上面这些工具以及 uv、Claude Desktop、ChatGPT 桌面版都可以用 `vibecli install <组件>` 装、`vibecli upgrade <组件>` 升级,`vibecli list` 查看本机状态,不用逐条记脚本地址。组件清单见 [`docs/components.md`](docs/components.md)。
|
|
48
|
+
|
|
47
49
|
## 快速开始
|
|
48
50
|
|
|
49
51
|
下面三种方式**任选一种**,完成任意一种就已经配置好了,不要依次全部执行。
|
|
@@ -137,31 +139,34 @@ vibecli config claude-code clear-model
|
|
|
137
139
|
|
|
138
140
|
- **一次配置多个工具**:把当前的令牌和模型写入 Claude Code、Claude Desktop(第三方推理模式,写入应用的本地配置库,不需要管理员权限或描述文件)、Codex、Grok Build、Antigravity CLI。OpenCode 暂时下架,`vibecli config opencode` 仍可使用。
|
|
139
141
|
- **每个工具单独选模型**:可以用默认模型、从 API 实时获取、选内置预设或手动输入,每个工具可以用不同的模型。
|
|
140
|
-
- Claude Code 使用默认模型时不写 `ANTHROPIC_*_MODEL` 环境变量,顶层 `model` 取 `settings-template.json` 的值(当前为 `opus[1m]
|
|
142
|
+
- Claude Code 使用默认模型时不写 `ANTHROPIC_*_MODEL` 环境变量,顶层 `model` 取 `settings-template.json` 的值(当前为 `opus[1m]`);显式选择其他模型时覆盖这个值。你在 Claude Code / Codex 里用 `/model` 换过的模型和思考强度,之后再运行 setup 也保留(VibeCLI 只更新它自己写过、你没改过的值)。Codex 默认 `gpt-6-astra`,Grok Build 默认 `grok-4.6`,其余工具默认 `gpt-5.5`。
|
|
141
143
|
- Codex(命令行版与桌面版)的模型菜单除了自带的 GPT 模型,还列出网关的 Claude、Gemini、Grok 和国产模型;Claude Code 的 `/model` 菜单在内置档位之后列出 GPT、Gemini、Grok 和国产模型。两边都只列令牌能用的模型。每个模型按自己的上下文窗口设置,用到窗口的 80% 时自动压缩。Codex 默认开启 1M 上下文,交互配置时可以关闭(关闭后窗口不超过 272K)。需要 Codex 0.122 及以上;Codex 或 Claude Code 版本过旧时,配置完成后会给出升级命令。
|
|
142
144
|
- **保留你的其他配置**:只改本工具的服务商(provider)字段,你的 hooks、MCP、插件和权限设置原样保留。
|
|
143
145
|
- **配置损坏时重置**:`vibecli config <tool> --force`(或 `vibecli setup … --force`)先备份,再用推荐配置整份重写,已经不是合法 JSON / TOML 的文件也能恢复。不加 `--force` 时只做合并,遇到损坏的文件不改动。
|
|
144
146
|
- **写入前自动备份,可以还原**:覆盖配置文件前先备份(每个文件保留 10 份),`vibecli config <tool> restore` 随时还原,还原之后还可以再撤销。
|
|
145
147
|
- **多个 Profile,凭据可随机器迁移**:work、personal 等 Profile 互相独立。令牌保存在权限为 `0600` 的 `~/.vibecli/config.yaml`,与 Claude Code、Codex 自己保存凭据的方式一样是明文,换机器后不会因为加密绑定原机器而无法读取。
|
|
148
|
+
- **安装和升级常用工具**:`vibecli list` 查看本机装了哪些、什么版本、能不能升级;`vibecli install <组件>` 从国内镜像安装 Node.js、Git、uv、Claude Code、Codex、Grok Build、Antigravity CLI、Claude Desktop、ChatGPT 桌面版(校验哈希与签名,已装只提示升级,`--force` 重装);`vibecli upgrade <组件>` 升级。可以一次填多个组件,别的应用的安装脚本也能调用它。各组件来源、校验和适用系统见 [`docs/components.md`](docs/components.md)。
|
|
146
149
|
- **适合 CI**:全局选项 `--json`、`--non-interactive`、`--yes`、`--no-color` 适用于各个命令;`setup`、`config` 和只读命令支持 `--dry-run` 预演,其他会写入的命令遇到 `--dry-run` 直接拒绝执行。
|
|
147
150
|
|
|
148
151
|
## 常用命令
|
|
149
152
|
|
|
150
|
-
| 命令 | 用途
|
|
151
|
-
| ------------------------------------------------- |
|
|
152
|
-
| `vibecli config <tool>` | 打开某个工具的菜单:选择模型后应用、移除或还原
|
|
153
|
-
| `vibecli config <tool> restore` | 把该工具的配置还原到上次修改前
|
|
154
|
-
| `vibecli config <tool> clear-model` | 去掉固定的模型设置,恢复工具自带的默认模型(保留令牌)
|
|
155
|
-
| `vibecli config <tool> remove` | 移除 VibeAPI 写入的配置(Codex 会退出令牌登录,可以改用 ChatGPT 订阅登录)
|
|
156
|
-
| `vibecli config tool-model set codex gpt-6-astra` | 单独给某个工具指定模型
|
|
157
|
-
| `vibecli config profile use work` | 切换 Profile
|
|
158
|
-
| `vibecli doctor` | 检查配置、网络和工具版本;加 `--deep` 时实际发一条请求
|
|
159
|
-
| `vibecli doctor --report` | 检查后上传诊断信息,得到一个诊断码,发给客服
|
|
160
|
-
| `vibecli
|
|
161
|
-
| `vibecli
|
|
162
|
-
| `vibecli
|
|
163
|
-
| `vibecli
|
|
164
|
-
| `vibecli
|
|
153
|
+
| 命令 | 用途 |
|
|
154
|
+
| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
155
|
+
| `vibecli config <tool>` | 打开某个工具的菜单:选择模型后应用、移除或还原 |
|
|
156
|
+
| `vibecli config <tool> restore` | 把该工具的配置还原到上次修改前 |
|
|
157
|
+
| `vibecli config <tool> clear-model` | 去掉固定的模型设置,恢复工具自带的默认模型(保留令牌) |
|
|
158
|
+
| `vibecli config <tool> remove` | 移除 VibeAPI 写入的配置(Codex 会退出令牌登录,可以改用 ChatGPT 订阅登录) |
|
|
159
|
+
| `vibecli config tool-model set codex gpt-6-astra` | 单独给某个工具指定模型 |
|
|
160
|
+
| `vibecli config profile use work` | 切换 Profile |
|
|
161
|
+
| `vibecli doctor` | 检查配置、网络和工具版本;加 `--deep` 时实际发一条请求 |
|
|
162
|
+
| `vibecli doctor --report` | 检查后上传诊断信息,得到一个诊断码,发给客服 |
|
|
163
|
+
| `vibecli list` | 列出本机各组件(Node.js、Git、uv、各编码工具、桌面应用)是否已装、版本、能否升级 |
|
|
164
|
+
| `vibecli install <组件>` | 从国内镜像安装一个或多个组件(node、git、uv、claude-code、codex、grok、agy、claude-desktop、chatgpt) |
|
|
165
|
+
| `vibecli upgrade` | 不填名字时升级已装的编码工具和桌面应用(Claude Code、Codex、Grok Build、agy、Claude Desktop、ChatGPT),并提示可升级的运行环境;填名字可单独升级,含 node、git、uv。官方下载地址无法访问时改用国内镜像 |
|
|
166
|
+
| `vibecli codex sessions` | 换过登录方式后 Codex 的旧会话不显示时,让它们重新出现(先退出 Codex) |
|
|
167
|
+
| `vibecli setup --desktop-registry on` | Windows 上 Claude Desktop 不读取本地配置时,改为写入注册表(会请求一次管理员确认) |
|
|
168
|
+
| `vibecli base` | 列出并测试全部接入地址 |
|
|
169
|
+
| `vibecli base auto` | 换到第一个能用的接入地址,已配置的工具一起换 |
|
|
165
170
|
|
|
166
171
|
### 主域名无法访问或证书报错
|
|
167
172
|
|
package/components.json
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": 1,
|
|
3
|
+
"about": "Components VibeCLI installs and upgrades (vibecli list / install / upgrade). 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
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type ComponentResult, type ComponentSpec } from '../lib/components.js';
|
|
2
|
+
/** Names → components (ids or aliases), with the components they require put first; unknown names are reported. */
|
|
3
|
+
export declare function resolveTargets(names: string[]): {
|
|
4
|
+
specs: ComponentSpec[];
|
|
5
|
+
unknown: string[];
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* `vibecli list`: every component, whether it is installed, which version, the newest one and where it comes
|
|
9
|
+
* from. Latest versions are cached an hour (`--refresh` reads them again). `--json`: `{ components: [...] }`.
|
|
10
|
+
*/
|
|
11
|
+
export declare function listCommand(options?: {
|
|
12
|
+
refresh?: boolean;
|
|
13
|
+
}): Promise<void>;
|
|
14
|
+
/** One component, the way `install` (missing → install, there → report) or `upgrade` treats it. */
|
|
15
|
+
export declare function installComponent(spec: ComponentSpec, force: boolean): Promise<ComponentResult>;
|
|
16
|
+
/**
|
|
17
|
+
* `vibecli install <component...>`: installs the missing ones from China-reachable mirrors (checksums and, for
|
|
18
|
+
* desktop apps, the vendor's signature checked). One that is already installed is only reported, with the
|
|
19
|
+
* upgrade command when it is behind (user, 11-01); `--force` reinstalls. Exit code 1 when any of them didn't
|
|
20
|
+
* end up installed. `--json`: `{ components: [{ tool, category, current, latest, result, version_after, ok }] }`.
|
|
21
|
+
*/
|
|
22
|
+
export declare function installCommand(names: string[], options?: {
|
|
23
|
+
force?: boolean;
|
|
24
|
+
}): Promise<void>;
|
|
25
|
+
/** Runtimes behind their latest (cached versions only, no network): one line each after a plain `vibecli upgrade`. */
|
|
26
|
+
export declare function outdatedRuntimeHints(): Promise<string[]>;
|
|
@@ -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))}
|
package/dist/commands/config.js
CHANGED
|
@@ -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{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,takeOver:!0}),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)}
|
package/dist/commands/setup.js
CHANGED
|
@@ -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{appsForTools as K,appUpgradeCommand as $,getApp as T}from"../lib/app-update.js";import{join as M}from"path";import{confirmWritePlan as G,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 O,brandEnv as B}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 D(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 F(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 L(e){console.log(o.green(e))}function R(e){console.log(o.yellow(e))}function P(e){console.error(o.red(e))}let Y=null;function q(o){const e={operation:1,authentication:2,network:3};(!Y||e[o]>e[Y])&&(Y=o)}async function z(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?`${O} setup --key ${a}`:`${O} setup ${e} ${a}`;let p;if("network_error"===i.error?(q("network"),p=_(l.t("setup.unreachable",{url:s.getBaseUrl(),reason:i.message||"network error"}),`${O} base auto`,"network_error")):"invalid_api_key"===i.error?(q("authentication"),p=y(l.t("setup.invalid_key",{label:e,reason:i.message||"invalid"}),n,"invalid_api_key")):(q("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 H(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),`${O} 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 W(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 U(o){R(l.t("setup.still_missing",{tools:o.map(o=>n[o].displayName).join(l.t("setup.list_separator")),commands:o.map(o=>`${O} config ${o} --yes`).join(l.t("setup.list_separator"))}))}function J(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=(w()?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 Q(){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 _=void 0!==r.desktopRegistry;let h;if(_&&(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||_,w=Boolean(p||f.length>0),K={oneMillion:r.oneMillion,officialLogin:y,desktopRegistry:h,force:r.force};if(!w&&(m||b)&&v())return void J([...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),L(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 H("claude-desktop",o,{...K,oneMillion:void 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 $=v();$||await i(p||f[0].apiKey);const T=[],S=[];let I,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 z(o.label,o.apiKey)){V+=1;continue}const e=await D(o.apiKey);!e.probed||F(e,o.need)?(e.probed||R(l.t("setup.probe_failed",{label:o.label})),T.push({tool:o.tool,apiKey:o.apiKey,dedicated:!0}),X.add(o.tool)):(P(l.t(`setup.key_no_${o.need}`,{label:o.label,tool:n[o.tool].displayName})),V+=1)}const oo=!!p&&await z("--key",p);p&&!oo&&(I=k[Y??"operation"]);const eo=p&&oo?await D(p):void 0;if(p&&eo&&!eo.probed&&R(l.t("setup.probe_failed",{label:"--key"})),!(p&&eo&&eo.probed)||eo.hasClaude||eo.hasGpt||eo.hasGrok||eo.hasGemini||(P(l.t("setup.key_no_family")),I=1),p&&eo&&void 0===I){const o=[{tool:"claude-code",capable:eo.hasClaude,skipMsg:l.t(Q()?"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&&Q(),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?(T.push({tool:e.tool,apiKey:p,dedicated:!1}),X.add(e.tool)):e.quiet||R(e.skipMsg))}const to=Boolean(p&&oo&&void 0===I);if($)return J(T.filter(o=>!W(o.tool)).map(o=>o.tool),T.length>0,T.filter(o=>W(o.tool)).map(o=>o.tool)),void((V>0||void 0!==I)&&(process.exitCode=I??k[Y??"operation"]));const io=T.filter(o=>!W(o.tool)),lo=to||T.some(o=>o.dedicated);if((T.length>0||lo)&&!r.fromInstaller&&!await G(io.map(o=>o.tool),{keyFile:lo?M(s.getConfigDir(),"config.yaml"):void 0,installFirst:T.filter(o=>W(o.tool)).map(o=>o.tool)}))return void(process.exitCode=k.cancelled);to&&p&&s.setApiKey(p);for(const o of T)o.dedicated&&s.setToolApiKey(o.tool,o.apiKey),W(o.tool)?S.push({tool:o.tool,apiKey:o.apiKey}):await H(o.tool,o.apiKey,K)?q+=1:(V+=1,X.delete(o.tool));if(void 0!==I)return S.length>0&&U(S.map(o=>o.tool)),void(process.exitCode=I);let so=[];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:O}))),{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 H(o,t,i)?u.push(o):f.push(o);return{still:d,applied:u,failed:f}}(S,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)});L("\n"+(i?`${s}${l.t("setup.done_commands",{commands:i})}`:s)),so.length>0&&U(so);for(const o of t){const e=a.ensureNativeOnPath(o);e&&L(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"!==B("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&&U(so),V>0&&(P(l.t("setup.failed_summary",{count:String(V)})),x()||console.error(`${O} 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[Y??"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,7 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `vibecli upgrade [tool...]`: no argument = every installed tool vibecli knows how to upgrade (CLIs with an
|
|
3
|
-
* `installSpec`, GUI apps with an `appInstaller` that this machine can serve)
|
|
4
|
-
*
|
|
3
|
+
* `installSpec`, GUI apps with an `appInstaller` that this machine can serve), then one line per runtime that is
|
|
4
|
+
* behind (`vibecli upgrade node`). Named: CLIs, apps and runtimes (node, git, uv; components.json, aliases too). A
|
|
5
|
+
* tool or app named explicitly is installed when missing; `--force` reinstalls an app or runtime that is already
|
|
6
|
+
* the latest. `--json` prints `{ tools: [...] }`: per entry its current / latest version and whether it was upgraded.
|
|
5
7
|
*/
|
|
6
8
|
export declare function upgradeCommand(tools: string[], options?: {
|
|
7
9
|
force?: boolean;
|
package/dist/commands/upgrade.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import o from"chalk";import{appTools as t,getApp as e,upgradeApp as
|
|
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)}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": 1,
|
|
3
|
+
"about": "Components VibeCLI installs and upgrades (vibecli list / install / upgrade). 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
|
+
}
|