@vibeapi/api-helper 0.0.132 → 0.0.133
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 +113 -52
- package/client-config.snapshot.json +23 -2
- package/dist/brand.json +5 -5
- package/dist/cli.js +1 -1
- package/dist/client-config.snapshot.json +23 -2
- package/dist/commands/doctor.js +1 -1
- package/dist/commands/setup.js +1 -1
- package/dist/lib/api-validator.js +1 -1
- package/dist/lib/tools/antigravity.js +1 -1
- package/dist/lib/tools/atomcode.js +1 -1
- package/dist/lib/tools/claude-desktop.js +1 -1
- package/dist/lib/tools/codex.js +1 -1
- package/dist/lib/tools/grok.js +1 -1
- package/dist/lib/tools/hermes.js +1 -1
- package/dist/lib/tools/openclaw.js +1 -1
- package/dist/lib/tools/tool-installs.js +1 -1
- package/dist/locales/en_US.json +228 -222
- package/dist/locales/zh_CN.json +517 -511
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,137 +1,198 @@
|
|
|
1
1
|
# VibeCLI(@vibeapi/api-helper)
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> 一条命令,为 Claude Code、Claude Desktop、Codex、Grok Build、Antigravity CLI 配置 VibeAPI 的令牌和模型。
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@vibeapi/api-helper)
|
|
6
6
|
[](https://nodejs.org)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
命令名是 `vibecli`,也可以用 `api-helper`。需要 **Node.js 20 及以上**。令牌在 VibeAPI 控制台的「令牌」页新建。每个命令的用法、示例和适用场景见 `vibecli <命令> --help`,或在线文档 https://docs.vibeapi.cn/zh/docs/coding-tools/commands 。
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## 安装与运行
|
|
11
|
+
|
|
12
|
+
不安装、直接运行最新版:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npx @vibeapi/cli@latest
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
或者全局安装,之后用 `vibecli` 运行:
|
|
11
19
|
|
|
12
20
|
```bash
|
|
13
|
-
|
|
14
|
-
npm install -g @vibeapi/cli # 或全局安装后用 vibecli
|
|
21
|
+
npm install -g @vibeapi/cli
|
|
15
22
|
```
|
|
16
23
|
|
|
17
|
-
|
|
24
|
+
`@vibeapi/cli` 与 `@vibeapi/api-helper` 是同一个程序的两个包名,同版本内容相同,安装哪个都可以。
|
|
18
25
|
|
|
19
|
-
npmjs.com
|
|
26
|
+
npmjs.com 无法访问时,从 CNB 备用制品库启动:
|
|
20
27
|
|
|
21
28
|
```bash
|
|
22
29
|
npx --yes --registry https://npm.cnb.cool/vibeapi/npm/-/packages/ @vibeapi/cli@latest
|
|
23
30
|
```
|
|
24
31
|
|
|
25
|
-
全局安装的 `vibecli`
|
|
32
|
+
全局安装的 `vibecli` 每次启动先检查更新(结果缓存 6 小时),按 **CNB → npmjs → npmmirror → Yarn registry** 的顺序查询和安装;有新版时自动升级,再重新执行当前命令。网络或权限出错时照常执行原命令:每个安装源最多等 45 秒,安装失败后 1 小时内不再重试。设置 `VIBECLI_DISABLE_AUTO_UPDATE=1` 可关闭启动时的更新。`npx @vibeapi/cli@latest` 由 npm 在 VibeCLI 启动前下载,所以第一次就下载失败时,请改用上面的 CNB 命令。
|
|
26
33
|
|
|
27
|
-
|
|
34
|
+
### 还没有安装编码工具
|
|
35
|
+
|
|
36
|
+
每个工具一条命令,安装方式与官方安装器相同,程序从国内镜像下载;再运行一次即升级。Node.js(VibeCLI 需要 20 及以上)和 Git 的脚本会先查找机器上已有的版本,已有就不安装。
|
|
28
37
|
|
|
29
38
|
| 工具 | macOS / Linux | Windows PowerShell |
|
|
30
39
|
| --------------- | --------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
|
|
31
40
|
| Claude Code | `curl -fsSL https://cnb.cool/vibeapi/install/-/git/raw/main/claude-code.sh \| sh` | `irm https://cnb.cool/vibeapi/install/-/git/raw/main/claude-code.ps1 \| iex` |
|
|
32
41
|
| Codex | `curl -fsSL https://cnb.cool/vibeapi/install/-/git/raw/main/codex.sh \| sh` | `irm https://cnb.cool/vibeapi/install/-/git/raw/main/codex.ps1 \| iex` |
|
|
42
|
+
| Grok Build | `curl -fsSL https://cnb.cool/vibeapi/install/-/git/raw/main/grok.sh \| sh` | `irm https://cnb.cool/vibeapi/install/-/git/raw/main/grok.ps1 \| iex` |
|
|
33
43
|
| Antigravity CLI | `curl -fsSL https://cnb.cool/vibeapi/install/-/git/raw/main/agy.sh \| sh` | `irm https://cnb.cool/vibeapi/install/-/git/raw/main/agy.ps1 \| iex` |
|
|
34
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` |
|
|
35
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` |
|
|
36
46
|
|
|
37
47
|
## 快速开始
|
|
38
48
|
|
|
39
|
-
|
|
49
|
+
下面三种方式**任选一种**,完成任意一种就已经配置好了,不要依次全部执行。
|
|
40
50
|
|
|
41
|
-
### 方式 A
|
|
51
|
+
### 方式 A:一条命令配置(推荐)
|
|
42
52
|
|
|
43
|
-
|
|
53
|
+
不需要任何交互;换令牌时重新执行一次即可。
|
|
44
54
|
|
|
45
55
|
```bash
|
|
46
56
|
vibecli setup --key sk-xxx
|
|
47
57
|
```
|
|
48
58
|
|
|
49
|
-
`--key`
|
|
59
|
+
`--key` 按令牌能用的模型自动选择工具:
|
|
60
|
+
|
|
61
|
+
| 令牌能用的模型 | 配置的工具 |
|
|
62
|
+
| -------------- | --------------------------- |
|
|
63
|
+
| Claude | Claude Code、Claude Desktop |
|
|
64
|
+
| GPT | Codex |
|
|
65
|
+
| Grok | Grok Build |
|
|
66
|
+
| Gemini | Antigravity CLI(`agy`) |
|
|
67
|
+
|
|
68
|
+
Claude Desktop 在 macOS 和 Windows 上即使还没有安装也会先写好配置,安装后打开即可使用;Linux 上只配置已安装的官方版。
|
|
69
|
+
|
|
70
|
+
还没有安装的命令行工具,VibeCLI 会先问是否从国内镜像安装(加 `--install` 直接安装、不再询问),安装完成后才写它的配置。选择不安装时不改动它的配置目录,以后安装好再运行 `vibecli config <工具> --yes` 补上配置。
|
|
71
|
+
|
|
72
|
+
不同分组各有一个令牌时(例如 Claude 分组、GPT 分组、Grok 分组各一个),分别指定:
|
|
50
73
|
|
|
51
74
|
```bash
|
|
52
75
|
vibecli setup --claudekey sk-a --codexkey sk-b --grokkey sk-c --desktopkey sk-d
|
|
53
76
|
```
|
|
54
77
|
|
|
55
|
-
|
|
78
|
+
每个工具都可以单独指定令牌:`--claudekey`、`--codexkey`、`--grokkey`、`--desktopkey`、`--agykey`。
|
|
56
79
|
|
|
57
|
-
Codex
|
|
80
|
+
Codex 默认开启 1M 上下文。配置 Codex 时显式开启,在末尾加 `--1m`:
|
|
58
81
|
|
|
59
82
|
```bash
|
|
60
83
|
vibecli setup --codexkey sk-xxx --1m
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
已经配置过 Codex、只想开启 1M 上下文时,不需要再输入令牌。这条命令只重新生成模型目录里的上下文设置,不改写 Codex 的凭据:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
61
89
|
vibecli setup --1m
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
关闭 1M 上下文,同样不改写凭据:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
62
95
|
vibecli setup --no-1m
|
|
63
96
|
```
|
|
64
97
|
|
|
65
|
-
|
|
98
|
+
配置完成后直接运行 `claude`、`codex` 或 `grok` 即可;`agy` 要在新开的终端里运行。Claude Desktop 默认隐藏官方(Claude.ai 账号)登录入口、只用 VibeAPI,要保留官方登录入口时加 `--claude-official on`。
|
|
66
99
|
|
|
67
100
|
### 方式 B:交互式向导
|
|
68
101
|
|
|
69
|
-
|
|
102
|
+
想在菜单里选择工具和模型时使用。中文系统自动显示中文界面,其他系统先选择语言:
|
|
70
103
|
|
|
71
104
|
```bash
|
|
72
105
|
vibecli init
|
|
73
106
|
```
|
|
74
107
|
|
|
75
|
-
### 方式 C:CI
|
|
108
|
+
### 方式 C:CI 与脚本
|
|
109
|
+
|
|
110
|
+
先保存令牌:
|
|
76
111
|
|
|
77
112
|
```bash
|
|
78
113
|
vibecli auth sk-xxx --non-interactive
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
再把配置写入某个工具,例如 Claude Code:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
79
119
|
vibecli config claude-code --non-interactive
|
|
80
120
|
```
|
|
81
121
|
|
|
82
|
-
###
|
|
122
|
+
### 配置完成后
|
|
123
|
+
|
|
124
|
+
查看当前配置:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
vibecli status
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
模型设置被固定、想恢复成工具自带的默认模型时(保留令牌):
|
|
83
131
|
|
|
84
132
|
```bash
|
|
85
|
-
vibecli
|
|
86
|
-
vibecli config claude-code clear-model # 模型选择被钉住时,交还给工具自带默认(保留 API Key)
|
|
133
|
+
vibecli config claude-code clear-model
|
|
87
134
|
```
|
|
88
135
|
|
|
89
|
-
##
|
|
136
|
+
## 功能
|
|
90
137
|
|
|
91
|
-
-
|
|
92
|
-
-
|
|
93
|
-
- Claude Code
|
|
94
|
-
- Codex
|
|
95
|
-
-
|
|
96
|
-
-
|
|
97
|
-
-
|
|
98
|
-
-
|
|
99
|
-
-
|
|
138
|
+
- **一次配置多个工具**:把当前的令牌和模型写入 Claude Code、Claude Desktop(第三方推理模式,写入应用的本地配置库,不需要管理员权限或描述文件)、Codex、Grok Build、Antigravity CLI。OpenCode 暂时下架,`vibecli config opencode` 仍可使用。
|
|
139
|
+
- **每个工具单独选模型**:可以用默认模型、从 API 实时获取、选内置预设或手动输入,每个工具可以用不同的模型。
|
|
140
|
+
- Claude Code 使用默认模型时不写 `ANTHROPIC_*_MODEL` 环境变量,顶层 `model` 取 `settings-template.json` 的值(当前为 `opus[1m]`);显式选择其他模型时覆盖这个值。Codex 默认 `gpt-6-astra`,Grok Build 默认 `grok-4.6`,其余工具默认 `gpt-5.5`。
|
|
141
|
+
- Codex(命令行版与桌面版)的模型菜单除了自带的 GPT 模型,还列出网关的 Claude、Gemini、Grok 和国产模型;Claude Code 的 `/model` 菜单在内置档位之后列出 GPT、Gemini、Grok 和国产模型。两边都只列令牌能用的模型。每个模型按自己的上下文窗口设置,用到窗口的 80% 时自动压缩。Codex 默认开启 1M 上下文,交互配置时可以关闭(关闭后窗口不超过 272K)。需要 Codex 0.122 及以上;Codex 或 Claude Code 版本过旧时,配置完成后会给出升级命令。
|
|
142
|
+
- **保留你的其他配置**:只改本工具的服务商(provider)字段,你的 hooks、MCP、插件和权限设置原样保留。
|
|
143
|
+
- **配置损坏时重置**:`vibecli config <tool> --force`(或 `vibecli setup … --force`)先备份,再用推荐配置整份重写,已经不是合法 JSON / TOML 的文件也能恢复。不加 `--force` 时只做合并,遇到损坏的文件不改动。
|
|
144
|
+
- **写入前自动备份,可以还原**:覆盖配置文件前先备份(每个文件保留 10 份),`vibecli config <tool> restore` 随时还原,还原之后还可以再撤销。
|
|
145
|
+
- **多个 Profile,凭据可随机器迁移**:work、personal 等 Profile 互相独立。令牌保存在权限为 `0600` 的 `~/.vibecli/config.yaml`,与 Claude Code、Codex 自己保存凭据的方式一样是明文,换机器后不会因为加密绑定原机器而无法读取。
|
|
146
|
+
- **适合 CI**:全局选项 `--json`、`--non-interactive`、`--yes`、`--no-color` 适用于各个命令;`setup`、`config` 和只读命令支持 `--dry-run` 预演,其他会写入的命令遇到 `--dry-run` 直接拒绝执行。
|
|
100
147
|
|
|
101
148
|
## 常用命令
|
|
102
149
|
|
|
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 upgrade` | 升级 Claude Code、Codex、Grok Build、agy;官方下载地址无法访问时改用国内镜像 |
|
|
161
|
+
| `vibecli codex sessions` | 换过登录方式后 Codex 的旧会话不显示时,让它们重新出现(先退出 Codex) |
|
|
162
|
+
| `vibecli setup --desktop-registry on` | Windows 上 Claude Desktop 不读取本地配置时,改为写入注册表(会请求一次管理员确认) |
|
|
163
|
+
| `vibecli base` | 列出并测试全部接入地址 |
|
|
164
|
+
| `vibecli base auto` | 换到第一个能用的接入地址,已配置的工具一起换 |
|
|
165
|
+
|
|
166
|
+
### 主域名无法访问或证书报错
|
|
167
|
+
|
|
168
|
+
校园网、酒店网络有时会把 `www.vibeapi.cn` 解析到别的服务器,表现为浏览器提示「连接不是私密连接」、报 `Self-signed certificate`,或者一直超时。这时换一个接入地址即可,令牌不用改。
|
|
169
|
+
|
|
170
|
+
自动测试并换到第一个能用的地址:
|
|
171
|
+
|
|
103
172
|
```bash
|
|
104
|
-
vibecli
|
|
105
|
-
vibecli config <tool> restore # 还原该工具到上次更改前
|
|
106
|
-
vibecli config <tool> clear-model # 清掉钉死的模型设置,回到工具自带默认(保留 API Key)
|
|
107
|
-
vibecli config <tool> remove # 移除 VibeAPI 写入的配置(Codex 会退出 API Key 登录,可改用 ChatGPT 订阅)
|
|
108
|
-
vibecli config tool-model set codex gpt-6-astra # 单独给某工具指定模型
|
|
109
|
-
vibecli config profile use work # 切换 profile
|
|
110
|
-
vibecli doctor # 健康巡检(--deep 实发一条请求)
|
|
111
|
-
vibecli doctor --report # 巡检后上传诊断信息,得到诊断码发给客服
|
|
112
|
-
vibecli upgrade # 升级 Claude Code / Codex / agy,官方渠道连不上自动改走国内镜像
|
|
113
|
-
vibecli codex sessions # 换过登录方式后 Codex 旧会话不显示时,让它们重新出现(先退出 Codex)
|
|
114
|
-
vibecli setup --desktop-registry on # Windows:桌面端不认本地配置时,强制写注册表(会请求一次管理员确认)
|
|
115
|
-
vibecli base # 查看并测试所有接入地址
|
|
116
|
-
vibecli base auto # 换到第一个能用的接入地址,已配置的工具一起换
|
|
173
|
+
vibecli base auto
|
|
117
174
|
```
|
|
118
175
|
|
|
119
|
-
|
|
176
|
+
指定一个地址:
|
|
120
177
|
|
|
121
|
-
|
|
178
|
+
```bash
|
|
179
|
+
vibecli base https://www.vibeapi.si
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
网络恢复后回到主站:
|
|
122
183
|
|
|
123
184
|
```bash
|
|
124
|
-
vibecli base
|
|
125
|
-
vibecli base https://www.vibeapi.si # 或指定一个地址
|
|
126
|
-
vibecli base default # 网络恢复后回到主站
|
|
185
|
+
vibecli base default
|
|
127
186
|
```
|
|
128
187
|
|
|
129
|
-
`auto`
|
|
188
|
+
`vibecli base auto` 按下面的顺序尝试,取第一个能用的:`www.vibeapi.cn` → `www.vibeapi.si` → `hk.vibeapi.cn` → `us13-www.vibeapi.cn` → `cf.vibeapi.cn` → `token.nfeyre.top`。网关控制台以后新增的地址排在这些之后。保存了令牌时,VibeCLI 用它在每个地址获取一次模型列表,获取到才算能用;`vibecli base` 对每个地址测 3 次取中位数,并标出最快的一个。
|
|
189
|
+
|
|
190
|
+
第一次运行 `vibecli setup` 或 `vibecli init` 时如果主站无法访问,也会按同样的顺序自动换到能用的地址。切换后的地址保存在当前 Profile 里,已经用 VibeCLI 配置过的工具(Claude Code、Codex、Claude Desktop 等)会一起改用新地址,以后再运行 `vibecli setup` 也不会改回主站。首次配置时也可以直接指定地址:`vibecli setup --base https://www.vibeapi.si --key sk-xxx`。向导主菜单里也有「切换接入地址」。
|
|
130
191
|
|
|
131
192
|
## 支持
|
|
132
193
|
|
|
133
194
|
主页 <https://www.vibeapi.cn/> · 反馈 <https://www.vibeapi.cn/support> · [CNB 备用制品库](https://cnb.cool/vibeapi/npm/-/registries/@vibeapi/cli)
|
|
134
195
|
|
|
135
|
-
##
|
|
196
|
+
## 许可证
|
|
136
197
|
|
|
137
|
-
UNLICENSED
|
|
198
|
+
UNLICENSED:仅供 VibeAPI 用户使用,详见随包附带的 LICENSE。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": 1,
|
|
3
|
-
"revision": "2026-10-
|
|
3
|
+
"revision": "2026-10-25T16:32:50Z-9",
|
|
4
4
|
"min_client_version": "",
|
|
5
5
|
"upgrade_message": "",
|
|
6
6
|
"defaults": {
|
|
@@ -214,6 +214,16 @@
|
|
|
214
214
|
"hidden": true,
|
|
215
215
|
"context_window": 1000000
|
|
216
216
|
},
|
|
217
|
+
{
|
|
218
|
+
"id": "kimi-k3.1-pro",
|
|
219
|
+
"name": "Kimi K3.1 Pro",
|
|
220
|
+
"description": "105 万上下文 | Agent 编程",
|
|
221
|
+
"group": "",
|
|
222
|
+
"group_name": "",
|
|
223
|
+
"recommended": false,
|
|
224
|
+
"hidden": false,
|
|
225
|
+
"context_window": 1048576
|
|
226
|
+
},
|
|
217
227
|
{
|
|
218
228
|
"id": "kimi-k3",
|
|
219
229
|
"name": "Kimi K3",
|
|
@@ -433,6 +443,16 @@
|
|
|
433
443
|
"hidden": true,
|
|
434
444
|
"context_window": 1000000
|
|
435
445
|
},
|
|
446
|
+
{
|
|
447
|
+
"id": "kimi-k3.1-pro",
|
|
448
|
+
"name": "Kimi K3.1 Pro",
|
|
449
|
+
"description": "105 万上下文 | Agent 编程",
|
|
450
|
+
"group": "",
|
|
451
|
+
"group_name": "",
|
|
452
|
+
"recommended": false,
|
|
453
|
+
"hidden": false,
|
|
454
|
+
"context_window": 1048576
|
|
455
|
+
},
|
|
436
456
|
{
|
|
437
457
|
"id": "kimi-k3",
|
|
438
458
|
"name": "Kimi K3",
|
|
@@ -689,7 +709,8 @@
|
|
|
689
709
|
"hint": "可以使用高级模型 Fable,并且畅享满血提示词缓存",
|
|
690
710
|
"groups": [
|
|
691
711
|
"Claude 官方满血版"
|
|
692
|
-
]
|
|
712
|
+
],
|
|
713
|
+
"default": true
|
|
693
714
|
}
|
|
694
715
|
]
|
|
695
716
|
}
|
package/dist/brand.json
CHANGED
|
@@ -16,23 +16,23 @@
|
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
18
|
"url": "https://www.vibeapi.si",
|
|
19
|
-
"label": "
|
|
19
|
+
"label": "主站备用域名"
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
22
|
"url": "https://hk.vibeapi.cn",
|
|
23
|
-
"label": "
|
|
23
|
+
"label": "香港"
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
26
|
"url": "https://us13-www.vibeapi.cn",
|
|
27
|
-
"label": "
|
|
27
|
+
"label": "美国"
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
30
|
"url": "https://cf.vibeapi.cn",
|
|
31
|
-
"label": "Cloudflare
|
|
31
|
+
"label": "Cloudflare 加速"
|
|
32
32
|
},
|
|
33
33
|
{
|
|
34
34
|
"url": "https://token.nfeyre.top",
|
|
35
|
-
"label": "
|
|
35
|
+
"label": "全球加速"
|
|
36
36
|
}
|
|
37
37
|
],
|
|
38
38
|
"links": {
|
package/dist/cli.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
if(Number(process.versions.node.split(".")[0])<20){const{brand:e}=await import("./lib/brand.js"),r=e().productName;console.error(
|
|
2
|
+
if(Number(process.versions.node.split(".")[0])<20){const{brand:e}=await import("./lib/brand.js"),r=e().productName;console.error(`无法启动 ${r}:需要 Node.js 20 或更高版本,当前是 v${process.versions.node}。\n请安装 Node.js LTS 版(国内镜像:https://registry.npmmirror.com/binary.html?path=node/ ,也可以运行 nvm install --lts),安装后重新打开终端再运行。\n${r} needs Node.js 20 or later (found v${process.versions.node}); install the LTS release and open a new terminal.`),process.exit(1)}const{Command:e}=await import("./lib/command.js"),{logger:r}=await import("./utils/logger.js"),{reportCliError:o}=await import("./lib/errors.js"),{telemetryPending:s}=await import("./lib/telemetry.js");try{await(new e).execute(process.argv.slice(2))}catch(e){r.logError("CLI",e),o(e)}s()&&process.exit();export{};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": 1,
|
|
3
|
-
"revision": "2026-10-
|
|
3
|
+
"revision": "2026-10-25T16:32:50Z-9",
|
|
4
4
|
"min_client_version": "",
|
|
5
5
|
"upgrade_message": "",
|
|
6
6
|
"defaults": {
|
|
@@ -214,6 +214,16 @@
|
|
|
214
214
|
"hidden": true,
|
|
215
215
|
"context_window": 1000000
|
|
216
216
|
},
|
|
217
|
+
{
|
|
218
|
+
"id": "kimi-k3.1-pro",
|
|
219
|
+
"name": "Kimi K3.1 Pro",
|
|
220
|
+
"description": "105 万上下文 | Agent 编程",
|
|
221
|
+
"group": "",
|
|
222
|
+
"group_name": "",
|
|
223
|
+
"recommended": false,
|
|
224
|
+
"hidden": false,
|
|
225
|
+
"context_window": 1048576
|
|
226
|
+
},
|
|
217
227
|
{
|
|
218
228
|
"id": "kimi-k3",
|
|
219
229
|
"name": "Kimi K3",
|
|
@@ -433,6 +443,16 @@
|
|
|
433
443
|
"hidden": true,
|
|
434
444
|
"context_window": 1000000
|
|
435
445
|
},
|
|
446
|
+
{
|
|
447
|
+
"id": "kimi-k3.1-pro",
|
|
448
|
+
"name": "Kimi K3.1 Pro",
|
|
449
|
+
"description": "105 万上下文 | Agent 编程",
|
|
450
|
+
"group": "",
|
|
451
|
+
"group_name": "",
|
|
452
|
+
"recommended": false,
|
|
453
|
+
"hidden": false,
|
|
454
|
+
"context_window": 1048576
|
|
455
|
+
},
|
|
436
456
|
{
|
|
437
457
|
"id": "kimi-k3",
|
|
438
458
|
"name": "Kimi K3",
|
|
@@ -689,7 +709,8 @@
|
|
|
689
709
|
"hint": "可以使用高级模型 Fable,并且畅享满血提示词缓存",
|
|
690
710
|
"groups": [
|
|
691
711
|
"Claude 官方满血版"
|
|
692
|
-
]
|
|
712
|
+
],
|
|
713
|
+
"default": true
|
|
693
714
|
}
|
|
694
715
|
]
|
|
695
716
|
}
|
package/dist/commands/doctor.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{refreshClientConfig as o}from"../lib/client-config-sync.js";import
|
|
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 i}from"net";import{join as c}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{balanceLookupEnabled as C,balanceNeedsAttention as I,balanceText as H,fetchKeyBalances as L}from"../lib/key-balance.js";const S=["HTTPS_PROXY","https_proxy","HTTP_PROXY","http_proxy","ALL_PROXY","all_proxy"];function U(o,t,e=3e3){return new Promise(s=>{const r=i({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 E(){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(c(o,t),"utf-8")).join("\n");return R(t.slice(-15e4))}function K(){const o={};for(const t of S){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(),i=[],A=Number(process.versions.node.split(".")[0]);i.push({name:"Node.js",status:A>=20?"pass":"fail",message:`v${process.versions.node}`}),n.text=u.t("doctor.check_proxy"),i.push(await async function(){const o=u.t("doctor.proxy"),t=new Map;for(const o of S){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 U(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(),B=u.t("doctor.api_key_network");if(R){const o=await m(R);o.valid?(i.push({name:B,status:"pass"}),n.text=u.t("doctor.check_balance"),i.push(...await async function(o){if(!C())return[];const t=l.listToolApiKeys().map(o=>({tool:o,key:l.getApiKeyForTool(o)})).filter(t=>Boolean(t.key)&&t.key!==o),e=await L([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:I(t)?"warn":"pass",message:H(t)})}return r}(R))):"invalid_api_key"===o.error?i.push({name:B,status:"fail",message:u.t("doctor.api_key_invalid")}):(i.push({name:B,status:"fail",message:`${u.t("doctor.network_error")}: ${o.message??o.error}`}),n.text=u.t("doctor.check_other_addresses"),i.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 i.push({name:B,status:"fail",message:u.t("doctor.api_key_missing")});n.text=u.t("doctor.check_client_config");const G=await o();i.push({name:u.t("doctor.client_config"),status:"cloud"===G.source||"cache"===G.source&&!G.problem?"pass":"warn",message:[G.source?u.t(`refresh.source.${G.source}`):u.t("refresh.source.none"),G.revision?u.t("doctor.client_config_revision",{revision:G.revision}):"",G.problem??""].filter(Boolean).join(" · ")}),n.text=u.t("doctor.check_tools");const D=p.getInstalledTools();i.push({name:u.t("doctor.installed_tools"),status:D.length>0?"pass":"warn",message:D.length>0?D.map(o=>f(o)?.displayName??o).join(u.t("setup.list_separator")):u.t("doctor.no_tools_installed")}),i.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}());const q=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(c(process.env.CLAUDE_CONFIG_DIR?.trim()||c(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")}}();q&&i.push(q),D.includes("claude-code")&&v()&&i.push({name:u.t("doctor.claude_login"),status:"pass",message:u.t("tools.claude_code.account_login_overridden")});const F=D.includes("codex")?y():null;if(D.includes("codex")&&i.push({name:u.t("doctor.codex_auth"),status:F?"fail":"pass",message:F?u.t(`doctor.codex_${F}`,{path:P(w())}):void 0}),D.includes("codex")){const o=k();i.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})}D.includes("codex")&&b()&&i.push({name:u.t("doctor.codex_work_mode"),status:"warn",message:u.t("tools.codex.work_mode_on")}),"win32"===process.platform&&D.includes("claude-code")&&!process.env.CLAUDE_CODE_GIT_BASH_PATH&&i.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&&D.includes("claude-code")&&(n.text=u.t("doctor.check_claude_request"),i.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 i=(`${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:i})}}())),n.stop(),console.log("\n"+t.bold(u.t("doctor.results_title"))+"\n");const M={pass:t.green("√"),warn:t.yellow("!"),fail:t.red("×")};for(const o of i)console.log(`${M[o.status]} ${o.name}`),o.message&&console.log(t.gray(` ${o.message}`));if(i.every(o=>"pass"===o.status)&&console.log("\n"+t.green.bold(u.t("doctor.all_good"))),!r.deep&&D.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:K()},log:E()}}(i,{source:G.source??void 0,revision:G.revision,problem:G.problem}));t?o.succeed(u.t("doctor.report_done",{code:t})):o.fail(u.t("doctor.report_failed",{cli:O}))}else i.some(o=>"fail"===o.status)&&console.log(t.gray("\n"+u.t("doctor.report_hint",{cli:O})));i.some(o=>"fail"===o.status)&&(process.exitCode=1)}
|
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 d}from"../lib/api-validator.js";import{CODEX_ONE_MILLION_CONTEXT_SETTING as p,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{emitJson as h,isColorEnabled as b,isDryRun as w,isJsonMode as v,isNonInteractive as x,shouldAutoConfirm as C}from"../lib/runtime-options.js";import{join as K}from"path";import{confirmWritePlan as j,printWritePlan as $,toolWritePlan as T}from"../lib/write-plan.js";import G from"inquirer";import{logger as N}from"../utils/logger.js";import{forgetInstalls as S}from"../lib/tools/tool-installs.js";import{CLI_NAME as M,brandEnv as E}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 I(o){const e=await d(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 O(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 A(e){console.log(o.green(e))}function L(e){console.log(o.yellow(e))}function D(e){console.error(o.red(e))}let F=null;function B(o){const e={operation:1,authentication:2,network:3};(!F||e[o]>e[F])&&(F=o)}async function R(e,t){v()||console.log(o.gray(l.t("setup.validating",{label:e})));const i=await r(t);if(i.valid)return!0;const a="zh_CN"===l.getLocale()?"<你的 Key>":"<your key>",n="--key"===e?`${M} setup --key ${a}`:`${M} setup ${e} ${a}`;let d;if("network_error"===i.error?(B("network"),d=_(l.t("setup.unreachable",{url:s.getBaseUrl(),reason:i.message||"network error"}),`${M} base auto`,"network_error")):"invalid_api_key"===i.error?(B("authentication"),d=y(l.t("setup.invalid_key",{label:e,reason:i.message||"invalid"}),n,"invalid_api_key")):(B("operation"),d=g(l.t("setup.validate_failed",{label:e,reason:i.message||i.error||"unknown"}),n,i.error)),v())throw d;return D(d.message),console.log(o.gray(l.t("errors.next_step",{command:d.hint}))),!1}async function P(t,i,r={}){const{oneMillion:d,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!==d&&s.setToolSetting("codex",p,d),"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(v())throw g(o instanceof Error?o.message:String(o),`${M} setup --key ${"zh_CN"===l.getLocale()?"<你的 Key>":"<your key>"}`,"config_write_failed");const e=(o instanceof Error?o.message:String(o)).replace(/\s+/g," ").trim();return D("× "+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!==d&&console.log(o.gray(" "+l.t(d?"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 Y(o){return!e(o)?.isInstalled&&!a.isToolInstalled(o)}function q(o){L(l.t("setup.still_missing",{tools:o.map(o=>n[o].displayName).join(l.t("setup.list_separator")),commands:o.map(o=>`${M} config ${o} --yes`).join(l.t("setup.list_separator"))}))}function z(e,t,i=[]){const a=T(e),n=K(s.getConfigDir(),"config.yaml");if(v())h({dry_run:!0,tools:a,install_first:i,key_file:t?n:null});else{if(0===a.length&&0===i.length){const e=(b()?o.cyan:o=>o)(l.t("runtime.dry_run_label"));return void console.log(`${e} ${l.t("setup.dry_run_none")}`)}$(a,{label:l.t("runtime.dry_run_label"),keyFile:t?n:void 0,installFirst:i})}}function H(){return"darwin"===process.platform||"win32"===process.platform||a.isToolInstalled("claude-desktop")}export async function setupCommand(r){F=null;const d=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 D(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 D(l.t("setup.desktop_registry_invalid",{value:String(r.desktopRegistry)})),void(process.exitCode=1);const b=g||_,$=Boolean(d||f.length>0),T={oneMillion:r.oneMillion,officialLogin:y,desktopRegistry:h,force:r.force};if(!$&&(m||b)&&w())return void z([...m?["codex"]:[],...b?["claude-desktop"]:[]],!1);if(!$&&(m||b)){if(m){const o=s.getApiKeyForTool("codex");if(o)try{const e=!0===r.oneMillion;s.setToolSetting("codex",p,e);const t=await u(o);c(e,t??void 0),A(l.t(e?"setup.codex_1m_enabled":"setup.codex_1m_disabled"))}catch(o){D(l.t("setup.apply_failed",{tool:n.codex.displayName,reason:o instanceof Error?o.message:String(o)})),process.exitCode=1}else D(l.t("setup.codex_1m_missing_key")),process.exitCode=1}if(b){const o=s.getApiKeyForTool("claude-desktop");o?await P("claude-desktop",o,{...T,oneMillion:void 0})?await t(["claude-desktop"]):process.exitCode=1:(D(l.t("setup.desktop_official_login_missing_key")),process.exitCode=1)}return}if(!$)return D(l.t("setup.usage")),void(process.exitCode=1);const B=w();B||await i(d||f[0].apiKey);const W=[],U=[];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 R(o.label,o.apiKey)){V+=1;continue}const e=await I(o.apiKey);!e.probed||O(e,o.need)?(e.probed||L(l.t("setup.probe_failed",{label:o.label})),W.push({tool:o.tool,apiKey:o.apiKey,dedicated:!0}),X.add(o.tool)):(D(l.t(`setup.key_no_${o.need}`,{label:o.label,tool:n[o.tool].displayName})),V+=1)}const oo=!!d&&await R("--key",d);d&&!oo&&(J=k[F??"operation"]);const eo=d&&oo?await I(d):void 0;if(d&&eo&&!eo.probed&&L(l.t("setup.probe_failed",{label:"--key"})),!(d&&eo&&eo.probed)||eo.hasClaude||eo.hasGpt||eo.hasGrok||eo.hasGemini||(D(l.t("setup.key_no_family")),J=1),d&&eo&&void 0===J){const o=[{tool:"claude-code",capable:eo.hasClaude,skipMsg:l.t(H()?"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&&H(),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?(W.push({tool:e.tool,apiKey:d,dedicated:!1}),X.add(e.tool)):e.quiet||L(e.skipMsg))}const to=Boolean(d&&oo&&void 0===J);if(B)return z(W.filter(o=>!Y(o.tool)).map(o=>o.tool),W.length>0,W.filter(o=>Y(o.tool)).map(o=>o.tool)),void((V>0||void 0!==J)&&(process.exitCode=J??k[F??"operation"]));const io=W.filter(o=>!Y(o.tool)),lo=to||W.some(o=>o.dedicated);if((W.length>0||lo)&&!r.fromInstaller&&!await j(io.map(o=>o.tool),{keyFile:lo?K(s.getConfigDir(),"config.yaml"):void 0,installFirst:W.filter(o=>Y(o.tool)).map(o=>o.tool)}))return void(process.exitCode=k.cancelled);to&&d&&s.setApiKey(d);for(const o of W)o.dedicated&&s.setToolApiKey(o.tool,o.apiKey),Y(o.tool)?U.push({tool:o.tool,apiKey:o.apiKey}):await P(o.tool,o.apiKey,T)?Q+=1:(V+=1,X.delete(o.tool));if(void 0!==J)return U.length>0&&q(U.map(o=>o.tool)),void(process.exitCode=J);let so=[];if(U.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 d=t;if(void 0!==d||v()||(C()?d=!x():process.stdin.isTTY&&(console.log(""),d=(await G.prompt([{type:"confirm",name:"go",message:l.t("setup.install_confirm",{tools:r}),default:!0}])).go)),!d){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 v()||console.log(o.gray(l.t("setup.install_all_hint",{cli:M}))),{still:s,applied:[],failed:[]}}const p=[];for(const e of s){console.log(o.bold(`\n${n[e].displayName}`));try{await a.installTool(e)}catch(o){N.logError(`setup: install ${e}`,o)}S(),a.isToolInstalled(e)||p.push(e)}const c=s.filter(o=>!p.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 P(o,t,i)?u.push(o):f.push(o);return{still:p,applied:u,failed:f}}(U,r.install,T);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)});A("\n"+(i?`${s}${l.t("setup.done_commands",{commands:i})}`:s)),so.length>0&&q(so);for(const o of t){const e=a.ensureNativeOnPath(o);e&&A(l.t("setup.path_added",{tool:n[o].displayName,dir:e}))}const r=t.filter(o=>!a.isOnPath(o));if(r.length>0&&!v()&&"1"!==E("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&&q(so),V>0&&(D(l.t("setup.failed_summary",{count:String(V)})),v()||console.error(`${M} setup --key ${"zh_CN"===l.getLocale()?"<你的 Key>":"<your key>"}`)),await t([...X]),(V>0||0===Q&&0===so.length)&&(process.exitCode=k[F??"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 d}from"../lib/api-validator.js";import{CODEX_ONE_MILLION_CONTEXT_SETTING as p,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{emitJson as h,isColorEnabled as b,isDryRun as w,isJsonMode as v,isNonInteractive as x,shouldAutoConfirm as C}from"../lib/runtime-options.js";import{join as j}from"path";import{confirmWritePlan as K,printWritePlan as $,toolWritePlan as T}from"../lib/write-plan.js";import G from"inquirer";import{logger as S}from"../utils/logger.js";import{forgetInstalls as M}from"../lib/tools/tool-installs.js";import{CLI_NAME as N,brandEnv as E}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 I(o){const e=await d(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 O(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 A(e){console.log(o.green(e))}function D(e){console.log(o.yellow(e))}function F(e){console.error(o.red(e))}let B=null;function L(o){const e={operation:1,authentication:2,network:3};(!B||e[o]>e[B])&&(B=o)}async function R(e,t){v()||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?`${N} setup --key ${a}`:`${N} setup ${e} ${a}`;let d;if("network_error"===i.error?(L("network"),d=_(l.t("setup.unreachable",{url:s.getBaseUrl(),reason:i.message||"network error"}),`${N} base auto`,"network_error")):"invalid_api_key"===i.error?(L("authentication"),d=y(l.t("setup.invalid_key",{label:e,reason:i.message||"invalid"}),n,"invalid_api_key")):(L("operation"),d=g(l.t("setup.validate_failed",{label:e,reason:i.message||i.error||"unknown"}),n,i.error)),v())throw d;return F(d.message),console.log(o.gray(l.t("errors.next_step",{command:d.hint}))),!1}async function P(t,i,r={}){const{oneMillion:d,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!==d&&s.setToolSetting("codex",p,d),"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(v())throw g(o instanceof Error?o.message:String(o),`${N} setup --key ${l.t("errors.key_placeholder")}`,"config_write_failed");const e=(o instanceof Error?o.message:String(o)).replace(/\s+/g," ").trim();return F("× "+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!==d&&console.log(o.gray(" "+l.t(d?"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 Y(o){return!e(o)?.isInstalled&&!a.isToolInstalled(o)}function q(o){D(l.t("setup.still_missing",{tools:o.map(o=>n[o].displayName).join(l.t("setup.list_separator")),commands:o.map(o=>`${N} config ${o} --yes`).join(l.t("setup.list_separator"))}))}function H(e,t,i=[]){const a=T(e),n=j(s.getConfigDir(),"config.yaml");if(v())h({dry_run:!0,tools:a,install_first:i,key_file:t?n:null});else{if(0===a.length&&0===i.length){const e=(b()?o.cyan:o=>o)(l.t("runtime.dry_run_label"));return void console.log(`${e} ${l.t("setup.dry_run_none")}`)}$(a,{label:l.t("runtime.dry_run_label"),keyFile:t?n:void 0,installFirst:i})}}function W(){return"darwin"===process.platform||"win32"===process.platform||a.isToolInstalled("claude-desktop")}export async function setupCommand(r){B=null;const d=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 F(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 F(l.t("setup.desktop_registry_invalid",{value:String(r.desktopRegistry)})),void(process.exitCode=1);const b=g||_,$=Boolean(d||f.length>0),T={oneMillion:r.oneMillion,officialLogin:y,desktopRegistry:h,force:r.force};if(!$&&(m||b)&&w())return void H([...m?["codex"]:[],...b?["claude-desktop"]:[]],!1);if(!$&&(m||b)){if(m){const o=s.getApiKeyForTool("codex");if(o)try{const e=!0===r.oneMillion;s.setToolSetting("codex",p,e);const t=await u(o);c(e,t??void 0),A(l.t(e?"setup.codex_1m_enabled":"setup.codex_1m_disabled"))}catch(o){F(l.t("setup.apply_failed",{tool:n.codex.displayName,reason:o instanceof Error?o.message:String(o)})),process.exitCode=1}else F(l.t("setup.codex_1m_missing_key")),process.exitCode=1}if(b){const o=s.getApiKeyForTool("claude-desktop");o?await P("claude-desktop",o,{...T,oneMillion:void 0})?await t(["claude-desktop"]):process.exitCode=1:(F(l.t("setup.desktop_official_login_missing_key")),process.exitCode=1)}return}if(!$)return F(l.t("setup.usage")),void(process.exitCode=1);const L=w();L||await i(d||f[0].apiKey);const U=[],z=[];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 R(o.label,o.apiKey)){V+=1;continue}const e=await I(o.apiKey);!e.probed||O(e,o.need)?(e.probed||D(l.t("setup.probe_failed",{label:o.label})),U.push({tool:o.tool,apiKey:o.apiKey,dedicated:!0}),X.add(o.tool)):(F(l.t(`setup.key_no_${o.need}`,{label:o.label,tool:n[o.tool].displayName})),V+=1)}const oo=!!d&&await R("--key",d);d&&!oo&&(J=k[B??"operation"]);const eo=d&&oo?await I(d):void 0;if(d&&eo&&!eo.probed&&D(l.t("setup.probe_failed",{label:"--key"})),!(d&&eo&&eo.probed)||eo.hasClaude||eo.hasGpt||eo.hasGrok||eo.hasGemini||(F(l.t("setup.key_no_family")),J=1),d&&eo&&void 0===J){const o=[{tool:"claude-code",capable:eo.hasClaude,skipMsg:l.t(W()?"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&&W(),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?(U.push({tool:e.tool,apiKey:d,dedicated:!1}),X.add(e.tool)):e.quiet||D(e.skipMsg))}const to=Boolean(d&&oo&&void 0===J);if(L)return H(U.filter(o=>!Y(o.tool)).map(o=>o.tool),U.length>0,U.filter(o=>Y(o.tool)).map(o=>o.tool)),void((V>0||void 0!==J)&&(process.exitCode=J??k[B??"operation"]));const io=U.filter(o=>!Y(o.tool)),lo=to||U.some(o=>o.dedicated);if((U.length>0||lo)&&!r.fromInstaller&&!await K(io.map(o=>o.tool),{keyFile:lo?j(s.getConfigDir(),"config.yaml"):void 0,installFirst:U.filter(o=>Y(o.tool)).map(o=>o.tool)}))return void(process.exitCode=k.cancelled);to&&d&&s.setApiKey(d);for(const o of U)o.dedicated&&s.setToolApiKey(o.tool,o.apiKey),Y(o.tool)?z.push({tool:o.tool,apiKey:o.apiKey}):await P(o.tool,o.apiKey,T)?Q+=1:(V+=1,X.delete(o.tool));if(void 0!==J)return z.length>0&&q(z.map(o=>o.tool)),void(process.exitCode=J);let so=[];if(z.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 d=t;if(void 0!==d||v()||(C()?d=!x():process.stdin.isTTY&&(console.log(""),d=(await G.prompt([{type:"confirm",name:"go",message:l.t("setup.install_confirm",{tools:r}),default:!0}])).go)),!d){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 v()||console.log(o.gray(l.t("setup.install_all_hint",{cli:N}))),{still:s,applied:[],failed:[]}}const p=[];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)}M(),a.isToolInstalled(e)||p.push(e)}const c=s.filter(o=>!p.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 P(o,t,i)?u.push(o):f.push(o);return{still:p,applied:u,failed:f}}(z,r.install,T);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)});A("\n"+(i?`${s}${l.t("setup.done_commands",{commands:i})}`:s)),so.length>0&&q(so);for(const o of t){const e=a.ensureNativeOnPath(o);e&&A(l.t("setup.path_added",{tool:n[o].displayName,dir:e}))}const r=t.filter(o=>!a.isOnPath(o));if(r.length>0&&!v()&&"1"!==E("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&&q(so),V>0&&(F(l.t("setup.failed_summary",{count:String(V)})),v()||console.error(`${N} setup --key ${l.t("errors.key_placeholder")}`)),await t([...X]),(V>0||0===Q&&0===so.length)&&(process.exitCode=k[B??"operation"])}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{KEY_INFO_PATH as
|
|
1
|
+
import{KEY_INFO_PATH as r}from"./gateway-protocol.js";import{logger as e}from"../utils/logger.js";import{configManager as t}from"./config.js";import{i18n as o}from"./i18n.js";import{rememberPublishedAddresses as a}from"./gateway-addresses.js";import{eligibleLists as n}from"./client-config.js";import{track as s}from"./telemetry.js";import{refreshClientConfig as i}from"./client-config-sync.js";const l=r=>new Promise(e=>setTimeout(e,r));async function c(r,e,a){const n=`${t.getBaseUrl()}/v1/models`,s=new AbortController,i=setTimeout(()=>s.abort(),e);try{const e=await a(n,{method:"GET",headers:{Authorization:`Bearer ${r}`,"Content-Type":"application/json"},signal:s.signal});if(401===e.status)return{valid:!1,error:"invalid_api_key",message:o.t("validator.rejected")};if(e.ok){try{const r=await e.json();if(r&&"list"===r.object)return{valid:!0}}catch{return{valid:!0}}return{valid:!0}}return{valid:!1,error:"unknown_error",message:`HTTP ${e.status}: ${e.statusText}`}}catch(r){return r instanceof Error&&"AbortError"===r.name?{valid:!1,error:"network_error",message:o.t("validator.timeout")}:function(r){const e=r?.cause?.code;return"string"==typeof e&&u.has(e)}(r)?{valid:!1,error:"network_error",message:o.t("messages.certificate_intercepted",{url:n})}:{valid:!1,error:"network_error",message:r instanceof Error?r.message:o.t("validator.network")}}finally{clearTimeout(i)}}const u=new Set(["DEPTH_ZERO_SELF_SIGNED_CERT","SELF_SIGNED_CERT_IN_CHAIN","UNABLE_TO_VERIFY_LEAF_SIGNATURE","UNABLE_TO_GET_ISSUER_CERT_LOCALLY","CERT_UNTRUSTED","ERR_TLS_CERT_ALTNAME_INVALID"]);export async function fetchModels(r,o={}){const{timeoutMs:a=3e4,fetchFn:n=fetch}=o,s=`${t.getBaseUrl()}/v1/models`,i=new AbortController,l=setTimeout(()=>i.abort(),a);try{const e=await n(s,{method:"GET",headers:{Authorization:`Bearer ${r}`,"Content-Type":"application/json"},signal:i.signal});if(!e.ok)return{ok:!1,models:[],error:`HTTP ${e.status}`};const t=await e.json();return{ok:!0,models:(Array.isArray(t?.data)?t.data:[]).map(r=>"string"==typeof r?r:r?.id).filter(r=>"string"==typeof r&&r.trim().length>0).map(r=>r.trim())}}catch(r){return e.logError("fetchModels",r),{ok:!1,models:[],error:r instanceof Error?r.message:"network error"}}finally{clearTimeout(l)}}function f(r){return r.filter(r=>!!r&&"object"==typeof r&&"string"==typeof r.name).map(r=>({name:r.name.trim(),..."string"==typeof r.labelOverride?{labelOverride:r.labelOverride}:{},..."boolean"==typeof r.supports1m?{supports1m:r.supports1m}:{}})).filter(r=>r.name.length>0)}export async function fetchGatewayStatus(r={}){const{timeoutMs:o=15e3,fetchFn:n=fetch}=r,s=`${t.getBaseUrl()}/api/status`,i=new AbortController,l=setTimeout(()=>i.abort(),o);try{const r=await n(s,{method:"GET",signal:i.signal});if(!r.ok)return{ok:!1,claudeDesktopGroupModels:{},error:`HTTP ${r.status}`};const e=await r.json();a(e?.data,t.getBaseUrl());let o=e?.data?.claude_desktop_group_models;if("string"==typeof o)try{o=JSON.parse(o)}catch{o=void 0}const l={};if(o&&"object"==typeof o&&!Array.isArray(o))for(const[r,e]of Object.entries(o))Array.isArray(e)&&(l[r]=f(e));return{ok:!0,claudeDesktopGroupModels:l}}catch(r){return e.logError("fetchGatewayStatus",r),{ok:!1,claudeDesktopGroupModels:{},error:r instanceof Error?r.message:"network error"}}finally{clearTimeout(l)}}export async function fetchKeyGroupInfo(o,a={}){const{timeoutMs:n=1e4,fetchFn:s=fetch}=a,i=`${t.getBaseUrl()}${r}`,l=new AbortController,c=setTimeout(()=>l.abort(),n);try{const r=await s(i,{method:"GET",headers:{Authorization:`Bearer ${o}`},signal:l.signal});if(!r.ok)return null;const e=await r.json(),t=e?.data;if(!t||"string"!=typeof t.group||!Array.isArray(t.claude_desktop_models))return null;const a=Array.isArray(t.groups)?t.groups.filter(r=>"string"==typeof r&&!!r):[];return{group:t.group,groups:a.length>0?a:[t.group],claudeDesktopModels:f(t.claude_desktop_models)}}catch(r){return e.logError("fetchKeyGroupInfo",r),null}finally{clearTimeout(c)}}export async function fetchClientModelConfig(r={}){const e=await i(r);return e.config?n(e.config.models):null}export async function validateApiKey(r,t={}){const a=Date.now(),n=await async function(r,t){const{timeoutMs:a=3e4,retries:n=2,backoffMs:s=500,fetchFn:i=fetch,sleepFn:u=l}=t;let f={valid:!1,error:"network_error",message:o.t("validator.network")};for(let t=0;t<=n;t++){const o=await c(r,a,i);if(o.valid||"invalid_api_key"===o.error)return o.valid||e.logError("validateApiKey",new Error(o.message||"invalid_api_key")),o;f=o,t<n&&await u(s*Math.pow(2,t))}return e.logError("validateApiKey",new Error(f.message||"network_error")),f}(r,t);return s("validate-key",n.valid?"ok":"fail",{duration_ms:Date.now()-a,...n.valid?{}:{error:n.message??n.error,detail:{reason:n.error}}}),n}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{chmodSync as t,existsSync as r,readFileSync as e}from"fs";import{join as n}from"path";import{i18n as o}from"../i18n.js";import{prettyModelName as i}from"../gateway-models.js";import{getAgyRules as a}from"../model-registry.js";import{logger as l}from"../../utils/logger.js";import{readPersistentEnvFile as s,removePersistentEnv as c,writePersistentEnv as u}from"../persistent-env.js";import{backupBeforeWrite as p,atomicWriteFile as g}from"./backup.js";import{findInstalls as d,mirrorInstallCommand as m}from"./tool-installs.js";import{toolHome as y}from"./types.js";import{brand as f,PROVIDER_KEY as v}from"../brand.js";const A="agy",_="AGY_LLM_GATEWAY_MODELS",h=["GEMINI_API_KEY","GOOGLE_GEMINI_BASE_URL","AGY_LLM_GATEWAY_URL","AGY_LLM_GATEWAY_API_KEY"],E="gemini",j=()=>n(y(),".gemini","antigravity-cli"),b=()=>n(j(),"settings.json"),w=()=>n(j(),`${v}.env`),I=()=>n(y(),".antigravity","settings.json"),K=f().installMirror?.agy,P={command:"agy",native:{binDir:"win32"===process.platform?["AppData","Local","agy","bin"]:[".local","bin"],updateArgs:["update"],dataDirs:[]},...K?{mirrorScript:{sh:`${K}/install.sh`,ps1:`${K}/install.ps1`}}:{}};function M(t){return!!t&&"object"==typeof t&&!Array.isArray(t)}function G(t,n){if(!r(t))return{};const o=e(t,"utf-8");if(!o.trim())return{};try{const t=JSON.parse(o);if(!M(t))throw new Error(`${n} root must be an object`);return t}catch(t){throw new Error(`Existing ${n} cannot be parsed
|
|
1
|
+
import{chmodSync as t,existsSync as r,readFileSync as e}from"fs";import{join as n}from"path";import{i18n as o}from"../i18n.js";import{prettyModelName as i}from"../gateway-models.js";import{getAgyRules as a}from"../model-registry.js";import{logger as l}from"../../utils/logger.js";import{readPersistentEnvFile as s,removePersistentEnv as c,writePersistentEnv as u}from"../persistent-env.js";import{backupBeforeWrite as p,atomicWriteFile as g}from"./backup.js";import{findInstalls as d,mirrorInstallCommand as m}from"./tool-installs.js";import{toolHome as y}from"./types.js";import{brand as f,PROVIDER_KEY as v}from"../brand.js";const A="agy",_="AGY_LLM_GATEWAY_MODELS",h=["GEMINI_API_KEY","GOOGLE_GEMINI_BASE_URL","AGY_LLM_GATEWAY_URL","AGY_LLM_GATEWAY_API_KEY"],E="gemini",j=()=>n(y(),".gemini","antigravity-cli"),b=()=>n(j(),"settings.json"),w=()=>n(j(),`${v}.env`),I=()=>n(y(),".antigravity","settings.json"),K=f().installMirror?.agy,P={command:"agy",native:{binDir:"win32"===process.platform?["AppData","Local","agy","bin"]:[".local","bin"],updateArgs:["update"],dataDirs:[]},...K?{mirrorScript:{sh:`${K}/install.sh`,ps1:`${K}/install.ps1`}}:{}};function M(t){return!!t&&"object"==typeof t&&!Array.isArray(t)}function G(t,n){if(!r(t))return{};const o=e(t,"utf-8");if(!o.trim())return{};try{const t=JSON.parse(o);if(!M(t))throw new Error(`${n} root must be an object`);return t}catch(t){throw new Error(`Existing ${n} cannot be parsed; back it up and fix it first: ${t instanceof Error?t.message:String(t)}`)}}const L=()=>G(b(),"~/.gemini/antigravity-cli/settings.json"),C=()=>G(I(),"~/.antigravity/settings.json");function N(r,e,n){p(r),g(r,JSON.stringify(e,null,2)+"\n",n),void 0!==n&&t(r,n)}function S(t){return(t||"").replace(/\/+$/,"").replace(/\/v1(beta)?$/,"")}function Y(t){const r=a().gatewayModels,e=t?r.filter(r=>t.models.includes(r)):[];return e.length>0?e:r}const $=t=>i(t.replace(/-preview$/,""));function k(t){const r=t.gateway;return M(r)&&!0===r.enabled&&"string"==typeof r.apiKey&&r.apiKey.trim()&&"string"==typeof r.url?{url:r.url,apiKey:r.apiKey}:null}function O(t){const r=t.models;return M(r)&&Array.isArray(r.list)?r.list.map(t=>M(t)&&"string"==typeof t.modelId?t.modelId:"").filter(Boolean):[]}function x(){try{if(L().modelProvider!==E)return null}catch{return null}const t=s(w()),r=t.GEMINI_API_KEY;return r&&r.trim()?{apiKey:r,url:t.GOOGLE_GEMINI_BASE_URL??""}:null}function U(t,r,e){const n=L(),o=C();o.gateway={...M(o.gateway)?o.gateway:{},enabled:!0,url:r,apiKey:t,wireProtocol:"genai"},o.models={...M(o.models)?o.models:{},defaultModelId:e[0],list:e.map(t=>({modelId:t,displayName:$(t),supportsThinking:!0}))},N(I(),o,384),h.some(t=>void 0!==s(w())[t])&&c(A,w(),h);const i=u(A,w(),{[_]:e.join(",")}).rcFiles;for(const t of h)delete process.env[t];return n.modelProvider===E&&(delete n.modelProvider,N(b(),n)),i}let D=null,R=null;export const antigravityAdapter={name:"agy",displayName:"Antigravity CLI",command:"agy",installCommand:m(P),installSpec:P,configPath:I(),wantsModelCatalog:!0,loadPrivateConfig(t){L(),C();const r=Y(t.catalog);D=U(t.apiKey,S(t.baseUrl),r),R=r},unloadPrivateConfig(){try{const t=C();k(t)&&(delete t.gateway,delete t.models,N(I(),t,384))}catch(t){l.logError("antigravityAdapter.unloadPrivateConfig",t)}try{const t=L();t.modelProvider===E&&(delete t.modelProvider,N(b(),t))}catch(t){l.logError("antigravityAdapter.unloadPrivateConfig",t)}c(A,w(),[_,...h])},detectCurrentConfig(){try{const t=k(C());if(t)return{apiKey:t.apiKey}}catch{return{apiKey:null}}return{apiKey:x()?.apiKey??null}},listedModels(){try{const t=C();if(k(t))return O(t)}catch{return null}return x()?[]:null},refreshModelMenu(t){const r=C(),e=k(r)??x();if(!e)return;const n=Y(t.catalog),o=e.url||S(t.baseUrl);null!==k(r)&&O(r).join(",")===n.join(",")&&s(w())[_]===n.join(",")&&null===x()||U(e.apiKey,o,n)},getConfig(){try{return C()}catch(t){return l.logError("antigravityAdapter.getConfig",t),null}},applyNotes(){const t=[];if(R&&R.length>0){const r=R.map($);t.push({kind:"summary",text:o.t("tools.agy.menu_written",{count:String(r.length),list:r.join(o.t("tools.grok.list_separator")),default:r[0]})})}return null===D||0===d(P).length||t.push({kind:"action",text:o.t("tools.agy.effort_after_reopen")}),t},backupPaths:()=>[I(),b(),w()],forceResetPaths:()=>[w()]};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{existsSync as r,readFileSync as o}from"fs";import{join as t}from"path";import*as e from"@iarna/toml";import{logger as i}from"../../utils/logger.js";import{BRAND_NAME as n}from"../brand.js";import{backupBeforeWrite as a,atomicWriteFile as d}from"./backup.js";import{pickModel as m,toolHome as s,withV1 as p}from"./types.js";import{getToolDefaultModel as l}from"../model-registry.js";const c=()=>t(t(s(),".atomcode"),"config.toml"),f=n;function u(r){return!!r&&"object"==typeof r&&!Array.isArray(r)}function g(){if(!r(c()))return{};const t=o(c(),"utf-8");if(!t.trim())return{};try{const r=e.parse(t);if(!u(r))throw new Error("config.toml root must be a TOML table");return r}catch(r){throw new Error(`Existing ~/.atomcode/config.toml cannot be parsed
|
|
1
|
+
import{existsSync as r,readFileSync as o}from"fs";import{join as t}from"path";import*as e from"@iarna/toml";import{logger as i}from"../../utils/logger.js";import{BRAND_NAME as n}from"../brand.js";import{backupBeforeWrite as a,atomicWriteFile as d}from"./backup.js";import{pickModel as m,toolHome as s,withV1 as p}from"./types.js";import{getToolDefaultModel as l}from"../model-registry.js";const c=()=>t(t(s(),".atomcode"),"config.toml"),f=n;function u(r){return!!r&&"object"==typeof r&&!Array.isArray(r)}function g(){if(!r(c()))return{};const t=o(c(),"utf-8");if(!t.trim())return{};try{const r=e.parse(t);if(!u(r))throw new Error("config.toml root must be a TOML table");return r}catch(r){throw new Error(`Existing ~/.atomcode/config.toml cannot be parsed; back it up and fix it first: ${r instanceof Error?r.message:String(r)}`)}}export const atomcodeAdapter={name:"atomcode",displayName:"AtomCode",command:"atomcode",installCommand:"npm install -g atomcode",hidden:!0,configPath:c(),loadPrivateConfig(r){const o=g(),t=u(o.providers)?o.providers:o.providers={},i=u(t[f])?{...t[f]}:{};t[f]={...i,type:"openai",base_url:p(r.baseUrl),context_window:2e5,api_key:r.apiKey,model:m(r.models,l("atomcode"))},o.default_provider=f,a(c()),d(c(),e.stringify(o))},unloadPrivateConfig(){if(!r(c()))return;let o;try{o=g()}catch(r){return void i.logError("atomcodeAdapter.unloadPrivateConfig",r)}u(o.providers)&&(delete o.providers[f],0===Object.keys(o.providers).length&&delete o.providers),o.default_provider===f&&delete o.default_provider,a(c()),d(c(),e.stringify(o))},detectCurrentConfig(){try{const r=g(),o=u(r.providers)?r.providers[f]:null,t=u(o)?o.api_key:null;return{apiKey:"string"==typeof t&&t.trim()?t:null}}catch{return{apiKey:null}}},getConfig(){try{return g()}catch(r){return i.logError("atomcodeAdapter.getConfig",r),null}}};
|