@ljwei-stak/dsh-model-router 0.17.1 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.dsh-plugin/client.js +244 -178
- package/.dsh-plugin/index.mjs +1 -1
- package/.dsh-plugin/official-tools-remote-service.mjs +46 -10
- package/.dsh-plugin/shared/official-tool-executor.mjs +135 -47
- package/.dsh-plugin/shared/official-tool-registry.mjs +113 -150
- package/.dsh-plugin/shared/official-tools-runtime.mjs +419 -222
- package/.dsh-plugin/shared/tool-install-preferences.mjs +77 -73
- package/.dsh-plugin/shared/vendor-mimo-grok-adapter.mjs +41 -16
- package/CHANGELOG.md +11 -1
- package/README.md +17 -8
- package/README.zh.md +17 -8
- package/docs/INSTALLATION_GUIDE.zh.md +14 -14
- package/docs/WORKBENCH_USER_GUIDE.zh.md +27 -5
- package/package.json +2 -2
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
export const DEFAULT_NPM_REGISTRY = 'https://registry.npmjs.org/'
|
|
25
25
|
|
|
26
26
|
/** Shared shape of a "package manager" method: argv only, no script staging. */
|
|
27
|
-
function packageManagerMethod(id, label, manager, spec, { registryFlag = '--registry=' } = {}) {
|
|
27
|
+
function packageManagerMethod(id, label, manager, spec, { registryFlag = '--registry=', command = 'install', extraArgs = [] } = {}) {
|
|
28
28
|
return Object.freeze({
|
|
29
29
|
id,
|
|
30
30
|
label,
|
|
@@ -32,23 +32,20 @@ function packageManagerMethod(id, label, manager, spec, { registryFlag = '--regi
|
|
|
32
32
|
manager,
|
|
33
33
|
spec,
|
|
34
34
|
registryFlag,
|
|
35
|
-
installArgs: Object.freeze([
|
|
35
|
+
installArgs: Object.freeze([command, '-g', spec, ...extraArgs]),
|
|
36
36
|
uninstallArgs: Object.freeze(['uninstall', '-g', spec.replace(/@latest$/, '')]),
|
|
37
|
-
/**
|
|
37
|
+
/** The resolver binds npm prefix or pnpm global-dir/global-bin-dir. */
|
|
38
38
|
supportsInstallDir: true,
|
|
39
39
|
supportsRegistry: true,
|
|
40
40
|
})
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
/**
|
|
44
|
-
* Vendor installer script run from a verified local copy.
|
|
45
|
-
* A directory is passed either as `installArg` (`--install-dir`) or as
|
|
46
|
-
* `installDirEnv` (`MCODE_INSTALL_DIR`, `CODEX_INSTALL_DIR`, …). Scripts that
|
|
47
|
-
* hardcode their own path set neither and `supportsInstallDir` stays false.
|
|
48
|
-
*/
|
|
43
|
+
/** Vendor installer script run from a verified local copy. */
|
|
49
44
|
function scriptMethod(id, label, {
|
|
50
45
|
shell, scriptUrl, verify, installArg = [], env = [], platforms,
|
|
51
|
-
installDirEnv = '',
|
|
46
|
+
supportsInstallDir = false, installDirEnv = '', installDirSuffix = '',
|
|
47
|
+
defaultScriptInstallDir, defaultScriptInstallDirEnv, scriptBinaryNames,
|
|
48
|
+
registryEnv, installDirSubdir, uninstallUnsupportedReason, scriptFallbackUrls,
|
|
52
49
|
}) {
|
|
53
50
|
return Object.freeze({
|
|
54
51
|
id,
|
|
@@ -61,14 +58,19 @@ function scriptMethod(id, label, {
|
|
|
61
58
|
installArgs: Object.freeze(installArg),
|
|
62
59
|
/** Environment the vendor script itself documents for this install. */
|
|
63
60
|
env: Object.freeze(env),
|
|
64
|
-
/** When set, the configured directory is this environment variable, not an argv flag. */
|
|
65
|
-
installDirEnv,
|
|
66
|
-
/** Home-relative directory the vendor uses when the user sets none. Slashes only. */
|
|
67
|
-
defaultInstallDir,
|
|
68
61
|
platforms: Object.freeze(platforms),
|
|
69
62
|
/** Whether the vendor script honours a caller-chosen directory at all. */
|
|
70
|
-
supportsInstallDir
|
|
71
|
-
|
|
63
|
+
supportsInstallDir,
|
|
64
|
+
installDirEnv,
|
|
65
|
+
installDirSuffix,
|
|
66
|
+
...(installDirSubdir ? { installDirSubdir } : {}),
|
|
67
|
+
...(uninstallUnsupportedReason ? { uninstallUnsupportedReason } : {}),
|
|
68
|
+
...(defaultScriptInstallDir ? { defaultScriptInstallDir } : {}),
|
|
69
|
+
...(defaultScriptInstallDirEnv ? { defaultScriptInstallDirEnv } : {}),
|
|
70
|
+
...(scriptBinaryNames ? { scriptBinaryNames: Object.freeze(scriptBinaryNames) } : {}),
|
|
71
|
+
...(scriptFallbackUrls ? { scriptFallbackUrls: Object.freeze(scriptFallbackUrls) } : {}),
|
|
72
|
+
...(registryEnv ? { registryEnv } : {}),
|
|
73
|
+
supportsRegistry: Boolean(registryEnv),
|
|
72
74
|
})
|
|
73
75
|
}
|
|
74
76
|
|
|
@@ -86,34 +88,25 @@ export const OFFICIAL_TOOLS = Object.freeze([
|
|
|
86
88
|
probeNote: 'kimi 与旧 Python 版 kimi-cli 同名;请核对可执行文件来源和版本。',
|
|
87
89
|
providerHints: ['moonshot', 'kimi'],
|
|
88
90
|
scriptBinaryNames: Object.freeze(['kimi', 'kimi.exe']),
|
|
89
|
-
|
|
90
|
-
defaultScriptInstallDir: '.kimi-code',
|
|
91
|
+
defaultScriptInstallDir: '.kimi-code/bin',
|
|
91
92
|
installMethods: Object.freeze([
|
|
92
93
|
packageManagerMethod('npm', 'npm', 'npm', '@moonshot-ai/kimi-code@latest'),
|
|
93
94
|
packageManagerMethod('pnpm', 'pnpm', 'pnpm', '@moonshot-ai/kimi-code@latest'),
|
|
94
95
|
scriptMethod('script-bash', 'curl | bash', {
|
|
95
|
-
shell: 'bash',
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
installDirEnv: 'KIMI_INSTALL_DIR',
|
|
99
|
-
defaultInstallDir: '.kimi-code',
|
|
96
|
+
shell: 'bash', scriptUrl: 'https://code.kimi.com/kimi-code/install.sh',
|
|
97
|
+
platforms: ['linux', 'darwin'], supportsInstallDir: true,
|
|
98
|
+
installDirEnv: 'KIMI_INSTALL_DIR', installDirSuffix: 'bin',
|
|
100
99
|
env: ['KIMI_INSTALL_DIR'],
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
mustNotInclude: ['downloads.claude.ai/claude-code-releases', '@minimax-ai/code'],
|
|
104
|
-
}),
|
|
100
|
+
scriptBinaryNames: ['kimi'],
|
|
101
|
+
verify: Object.freeze({ mustInclude: ['kimi-code', 'code.kimi.com/kimi-code'] }),
|
|
105
102
|
}),
|
|
106
103
|
scriptMethod('script-powershell', 'irm | iex', {
|
|
107
|
-
shell: 'powershell',
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
installDirEnv: 'KIMI_INSTALL_DIR',
|
|
111
|
-
defaultInstallDir: '.kimi-code',
|
|
104
|
+
shell: 'powershell', scriptUrl: 'https://code.kimi.com/kimi-code/install.ps1',
|
|
105
|
+
platforms: ['win32'], supportsInstallDir: true,
|
|
106
|
+
installDirEnv: 'KIMI_INSTALL_DIR', installDirSuffix: 'bin',
|
|
112
107
|
env: ['KIMI_INSTALL_DIR'],
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
mustNotInclude: ['downloads.claude.ai/claude-code-releases', '@minimax-ai/code'],
|
|
116
|
-
}),
|
|
108
|
+
scriptBinaryNames: ['kimi.exe'],
|
|
109
|
+
verify: Object.freeze({ mustInclude: ['kimi-code', 'code.kimi.com/kimi-code'] }),
|
|
117
110
|
}),
|
|
118
111
|
]),
|
|
119
112
|
}),
|
|
@@ -128,31 +121,28 @@ export const OFFICIAL_TOOLS = Object.freeze([
|
|
|
128
121
|
uninstallArgs: ['uninstall', '-g', '@anthropic-ai/claude-code'],
|
|
129
122
|
probeExecutables: ['claude'],
|
|
130
123
|
providerHints: ['anthropic', 'claude'],
|
|
131
|
-
// The native installer always lands in ~/.local/bin; it has no directory flag.
|
|
132
124
|
scriptBinaryNames: Object.freeze(['claude', 'claude.exe']),
|
|
133
125
|
defaultScriptInstallDir: '.local/bin',
|
|
134
126
|
installMethods: Object.freeze([
|
|
135
127
|
packageManagerMethod('npm', 'npm', 'npm', '@anthropic-ai/claude-code@latest'),
|
|
136
|
-
packageManagerMethod('pnpm', 'pnpm', 'pnpm', '@anthropic-ai/claude-code@latest'
|
|
128
|
+
packageManagerMethod('pnpm', 'pnpm', 'pnpm', '@anthropic-ai/claude-code@latest', {
|
|
129
|
+
command: 'add',
|
|
130
|
+
extraArgs: ['--ignore-scripts=false', '--allow-build=@anthropic-ai/claude-code'],
|
|
131
|
+
}),
|
|
132
|
+
// The native installer has no directory argument. npm/pnpm support a prefix.
|
|
137
133
|
scriptMethod('script-bash', 'curl | bash', {
|
|
138
|
-
shell: 'bash',
|
|
139
|
-
|
|
134
|
+
shell: 'bash', scriptUrl: 'https://claude.ai/install.sh',
|
|
135
|
+
scriptFallbackUrls: ['https://downloads.claude.ai/claude-code-releases/bootstrap.sh'],
|
|
140
136
|
platforms: ['linux', 'darwin'],
|
|
141
|
-
|
|
142
|
-
verify: Object.freeze({
|
|
143
|
-
mustInclude: ['downloads.claude.ai/claude-code-releases', 'claude.ai/install.sh'],
|
|
144
|
-
mustNotInclude: ['@minimax-ai/code', 'releases.openai.com/codex'],
|
|
145
|
-
}),
|
|
137
|
+
scriptBinaryNames: ['claude'],
|
|
138
|
+
verify: Object.freeze({ mustInclude: ['downloads.claude.ai/claude-code-releases', 'manifest.json'] }),
|
|
146
139
|
}),
|
|
147
140
|
scriptMethod('script-powershell', 'irm | iex', {
|
|
148
|
-
shell: 'powershell',
|
|
149
|
-
|
|
141
|
+
shell: 'powershell', scriptUrl: 'https://claude.ai/install.ps1',
|
|
142
|
+
scriptFallbackUrls: ['https://downloads.claude.ai/claude-code-releases/bootstrap.ps1'],
|
|
150
143
|
platforms: ['win32'],
|
|
151
|
-
|
|
152
|
-
verify: Object.freeze({
|
|
153
|
-
mustInclude: ['downloads.claude.ai/claude-code-releases'],
|
|
154
|
-
mustNotInclude: ['@minimax-ai/code', 'releases.openai.com/codex'],
|
|
155
|
-
}),
|
|
144
|
+
scriptBinaryNames: ['claude.exe'],
|
|
145
|
+
verify: Object.freeze({ mustInclude: ['downloads.claude.ai/claude-code-releases', 'manifest.json'] }),
|
|
156
146
|
}),
|
|
157
147
|
]),
|
|
158
148
|
}),
|
|
@@ -169,33 +159,28 @@ export const OFFICIAL_TOOLS = Object.freeze([
|
|
|
169
159
|
probeNote: 'Codex 版本横幅由适配层宽匹配;安装时取 npm 最新版。',
|
|
170
160
|
providerHints: ['openai', 'gpt', 'codex'],
|
|
171
161
|
scriptBinaryNames: Object.freeze(['codex', 'codex.exe']),
|
|
162
|
+
defaultScriptInstallDir: '.local/bin',
|
|
172
163
|
installMethods: Object.freeze([
|
|
173
164
|
packageManagerMethod('npm', 'npm', 'npm', '@openai/codex@latest'),
|
|
174
165
|
packageManagerMethod('pnpm', 'pnpm', 'pnpm', '@openai/codex@latest'),
|
|
175
|
-
scriptMethod('script-
|
|
176
|
-
shell: '
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
env: ['CODEX_INSTALL_DIR'],
|
|
182
|
-
verify: Object.freeze({
|
|
183
|
-
mustInclude: ['releases.openai.com/codex', 'CODEX_INSTALL_DIR'],
|
|
184
|
-
mustNotInclude: ['downloads.claude.ai/claude-code-releases', '@minimax-ai/code'],
|
|
185
|
-
}),
|
|
166
|
+
scriptMethod('script-sh', 'curl | sh', {
|
|
167
|
+
shell: 'sh', scriptUrl: 'https://chatgpt.com/codex/install.sh',
|
|
168
|
+
platforms: ['linux', 'darwin'], supportsInstallDir: true,
|
|
169
|
+
installDirEnv: 'CODEX_INSTALL_DIR', env: ['CODEX_INSTALL_DIR'],
|
|
170
|
+
scriptBinaryNames: ['codex'],
|
|
171
|
+
verify: Object.freeze({ mustInclude: ['releases.openai.com/codex', 'CODEX_INSTALL_DIR'] }),
|
|
186
172
|
}),
|
|
187
173
|
scriptMethod('script-powershell', 'irm | iex', {
|
|
188
|
-
shell: 'powershell',
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}),
|
|
174
|
+
shell: 'powershell', scriptUrl: 'https://chatgpt.com/codex/install.ps1',
|
|
175
|
+
platforms: ['win32'], supportsInstallDir: true,
|
|
176
|
+
installDirEnv: 'CODEX_INSTALL_DIR', env: ['CODEX_INSTALL_DIR'],
|
|
177
|
+
defaultScriptInstallDirEnv: 'LOCALAPPDATA',
|
|
178
|
+
defaultScriptInstallDir: 'Programs/OpenAI/Codex/bin',
|
|
179
|
+
installDirSubdir: 'codex/bin',
|
|
180
|
+
uninstallUnsupportedReason: 'Codex 官方 Windows 脚本使用目录联接和版本化资源;请按官方卸载说明移除,插件不会删除联接目标。',
|
|
181
|
+
// The Windows bin directory is a junction to the versioned payload.
|
|
182
|
+
scriptBinaryNames: ['codex.exe'],
|
|
183
|
+
verify: Object.freeze({ mustInclude: ['releases.openai.com/codex', 'CODEX_INSTALL_DIR'] }),
|
|
199
184
|
}),
|
|
200
185
|
]),
|
|
201
186
|
}),
|
|
@@ -210,41 +195,32 @@ export const OFFICIAL_TOOLS = Object.freeze([
|
|
|
210
195
|
uninstallArgs: ['uninstall', '-g', '@minimax-ai/code'],
|
|
211
196
|
probeExecutables: ['mcode'],
|
|
212
197
|
providerHints: ['minimax'],
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
]),
|
|
217
|
-
scriptBinaryRelatives: Object.freeze([
|
|
218
|
-
'mcode.cmd', 'mcode.ps1', 'mcode-tools.cmd', 'mcode-tools.ps1',
|
|
219
|
-
'bin/mcode', 'bin/mcode-tools',
|
|
220
|
-
]),
|
|
221
|
-
defaultScriptInstallDir: '.minimax-code',
|
|
198
|
+
defaultMethodsByPlatform: Object.freeze({ win32: 'script-powershell' }),
|
|
199
|
+
scriptBinaryNames: Object.freeze(['mcode', 'mcode-tools']),
|
|
200
|
+
defaultScriptInstallDir: '.minimax-code/bin',
|
|
222
201
|
installMethods: Object.freeze([
|
|
223
|
-
packageManagerMethod('npm', 'npm', 'npm', '@minimax-ai/code@latest'
|
|
224
|
-
|
|
202
|
+
packageManagerMethod('npm', 'npm', 'npm', '@minimax-ai/code@latest', {
|
|
203
|
+
extraArgs: ['--ignore-scripts=false', '--include=optional', '--allow-scripts=@minimax-ai/code,better-sqlite3'],
|
|
204
|
+
}),
|
|
205
|
+
packageManagerMethod('pnpm', 'pnpm', 'pnpm', '@minimax-ai/code@latest', {
|
|
206
|
+
command: 'add',
|
|
207
|
+
extraArgs: ['--ignore-scripts=false', '--allow-build=@minimax-ai/code', '--allow-build=better-sqlite3'],
|
|
208
|
+
}),
|
|
225
209
|
scriptMethod('script-bash', 'curl | bash', {
|
|
226
|
-
shell: 'bash',
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
env: ['MCODE_INSTALL_DIR', 'MCODE_NPM_REGISTRY'],
|
|
232
|
-
verify: Object.freeze({
|
|
233
|
-
mustInclude: ['@minimax-ai/code', 'MCODE_INSTALL_DIR', 'MiniMax Code'],
|
|
234
|
-
mustNotInclude: ['downloads.claude.ai/claude-code-releases', 'releases.openai.com/codex'],
|
|
235
|
-
}),
|
|
210
|
+
shell: 'bash', scriptUrl: 'https://filecdn.minimax.chat/public/install.sh',
|
|
211
|
+
platforms: ['linux', 'darwin'], supportsInstallDir: true,
|
|
212
|
+
installDirEnv: 'MCODE_INSTALL_DIR', installDirSuffix: 'bin',
|
|
213
|
+
registryEnv: 'MCODE_NPM_REGISTRY', env: ['MCODE_INSTALL_DIR', 'MCODE_NPM_REGISTRY'],
|
|
214
|
+
verify: Object.freeze({ mustInclude: ['MiniMax Code CLI', '@minimax-ai/code'] }),
|
|
236
215
|
}),
|
|
237
216
|
scriptMethod('script-powershell', 'irm | iex', {
|
|
238
|
-
shell: 'powershell',
|
|
239
|
-
|
|
240
|
-
platforms: ['win32'],
|
|
217
|
+
shell: 'powershell', scriptUrl: 'https://filecdn.minimax.chat/public/install.ps1',
|
|
218
|
+
platforms: ['win32'], supportsInstallDir: true,
|
|
241
219
|
installDirEnv: 'MCODE_INSTALL_DIR',
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
mustNotInclude: ['downloads.claude.ai/claude-code-releases', 'releases.openai.com/codex'],
|
|
247
|
-
}),
|
|
220
|
+
registryEnv: 'MCODE_NPM_REGISTRY', env: ['MCODE_INSTALL_DIR', 'MCODE_NPM_REGISTRY'],
|
|
221
|
+
defaultScriptInstallDir: '.minimax-code',
|
|
222
|
+
scriptBinaryNames: ['mcode.cmd', 'mcode.ps1', 'mcode-tools.cmd', 'mcode-tools.ps1'],
|
|
223
|
+
verify: Object.freeze({ mustInclude: ['MiniMax Code CLI', '@minimax-ai/code'] }),
|
|
248
224
|
}),
|
|
249
225
|
]),
|
|
250
226
|
}),
|
|
@@ -264,28 +240,18 @@ export const OFFICIAL_TOOLS = Object.freeze([
|
|
|
264
240
|
installMethods: Object.freeze([
|
|
265
241
|
packageManagerMethod('npm', 'npm', 'npm', '@mimo-ai/cli@latest'),
|
|
266
242
|
packageManagerMethod('pnpm', 'pnpm', 'pnpm', '@mimo-ai/cli@latest'),
|
|
267
|
-
// The Unix script hardcodes ~/.mimocode/bin and ignores MIMOCODE_INSTALL_DIR.
|
|
268
243
|
scriptMethod('script-bash', 'curl | bash', {
|
|
269
|
-
shell: 'bash',
|
|
270
|
-
scriptUrl: 'https://mimo.xiaomi.com/install',
|
|
244
|
+
shell: 'bash', scriptUrl: 'https://mimo.xiaomi.com/install',
|
|
271
245
|
platforms: ['linux', 'darwin'],
|
|
272
|
-
|
|
273
|
-
verify: Object.freeze({
|
|
274
|
-
mustInclude: ['MiMoCode', 'mimo.xiaomi.com'],
|
|
275
|
-
mustNotInclude: ['@minimax-ai/code', 'downloads.claude.ai/claude-code-releases'],
|
|
276
|
-
}),
|
|
246
|
+
scriptBinaryNames: ['mimo'],
|
|
247
|
+
verify: Object.freeze({ mustInclude: ['mimo.xiaomi.com', '.mimocode'] }),
|
|
277
248
|
}),
|
|
278
249
|
scriptMethod('script-powershell', 'irm | iex', {
|
|
279
|
-
shell: 'powershell',
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
env: ['MIMOCODE_INSTALL_DIR'],
|
|
285
|
-
verify: Object.freeze({
|
|
286
|
-
mustInclude: ['MiMoCode', 'mimo.xiaomi.com', 'MIMOCODE_INSTALL_DIR'],
|
|
287
|
-
mustNotInclude: ['@minimax-ai/code', 'downloads.claude.ai/claude-code-releases'],
|
|
288
|
-
}),
|
|
250
|
+
shell: 'powershell', scriptUrl: 'https://mimo.xiaomi.com/install.ps1',
|
|
251
|
+
platforms: ['win32'], supportsInstallDir: true,
|
|
252
|
+
installDirEnv: 'MIMOCODE_INSTALL_DIR', env: ['MIMOCODE_INSTALL_DIR'],
|
|
253
|
+
scriptBinaryNames: ['mimo.exe'],
|
|
254
|
+
verify: Object.freeze({ mustInclude: ['mimo.xiaomi.com', '.mimocode'] }),
|
|
289
255
|
}),
|
|
290
256
|
]),
|
|
291
257
|
}),
|
|
@@ -300,34 +266,25 @@ export const OFFICIAL_TOOLS = Object.freeze([
|
|
|
300
266
|
uninstallArgs: ['uninstall', '-g', '@xai-official/grok'],
|
|
301
267
|
probeExecutables: ['grok'],
|
|
302
268
|
providerHints: ['xai', 'grok'],
|
|
303
|
-
scriptBinaryNames: Object.freeze(['grok', 'grok.exe', 'agent', '
|
|
269
|
+
scriptBinaryNames: Object.freeze(['grok', 'agent', 'grok.exe', 'agent.exe', 'grove.exe', 'grove-fsmonitor.exe', 'grove-credential.exe']),
|
|
304
270
|
defaultScriptInstallDir: '.grok/bin',
|
|
271
|
+
pathProfileMarkers: Object.freeze(['# >>> grok installer >>>', '# <<< grok installer <<<']),
|
|
305
272
|
installMethods: Object.freeze([
|
|
306
273
|
packageManagerMethod('npm', 'npm', 'npm', '@xai-official/grok@latest'),
|
|
307
274
|
packageManagerMethod('pnpm', 'pnpm', 'pnpm', '@xai-official/grok@latest'),
|
|
308
275
|
scriptMethod('script-bash', 'curl | bash', {
|
|
309
|
-
shell: 'bash',
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
env: ['GROK_BIN_DIR'],
|
|
315
|
-
verify: Object.freeze({
|
|
316
|
-
mustInclude: ['x.ai/cli', 'GROK_BIN_DIR'],
|
|
317
|
-
mustNotInclude: ['@minimax-ai/code', 'downloads.claude.ai/claude-code-releases'],
|
|
318
|
-
}),
|
|
276
|
+
shell: 'bash', scriptUrl: 'https://x.ai/cli/install.sh',
|
|
277
|
+
platforms: ['linux', 'darwin'], supportsInstallDir: true,
|
|
278
|
+
installDirEnv: 'GROK_BIN_DIR', env: ['GROK_BIN_DIR'],
|
|
279
|
+
scriptBinaryNames: ['grok', 'agent'],
|
|
280
|
+
verify: Object.freeze({ mustInclude: ['Grok CLI installer', 'x.ai/cli'] }),
|
|
319
281
|
}),
|
|
320
282
|
scriptMethod('script-powershell', 'irm | iex', {
|
|
321
|
-
shell: 'powershell',
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
env: ['GROK_BIN_DIR'],
|
|
327
|
-
verify: Object.freeze({
|
|
328
|
-
mustInclude: ['x.ai/cli', 'GROK_BIN_DIR'],
|
|
329
|
-
mustNotInclude: ['@minimax-ai/code', 'downloads.claude.ai/claude-code-releases'],
|
|
330
|
-
}),
|
|
283
|
+
shell: 'powershell', scriptUrl: 'https://x.ai/cli/install.ps1',
|
|
284
|
+
platforms: ['win32'], supportsInstallDir: true,
|
|
285
|
+
installDirEnv: 'GROK_BIN_DIR', env: ['GROK_BIN_DIR'],
|
|
286
|
+
scriptBinaryNames: ['grok.exe', 'agent.exe', 'grove.exe', 'grove-fsmonitor.exe', 'grove-credential.exe'],
|
|
287
|
+
verify: Object.freeze({ mustInclude: ['Grok CLI installer', 'x.ai/cli'] }),
|
|
331
288
|
}),
|
|
332
289
|
]),
|
|
333
290
|
}),
|
|
@@ -375,7 +332,9 @@ export const OFFICIAL_TOOLS = Object.freeze([
|
|
|
375
332
|
shell: 'bash',
|
|
376
333
|
scriptUrl: 'https://opencode.ai/install',
|
|
377
334
|
platforms: ['linux', 'darwin'],
|
|
378
|
-
|
|
335
|
+
// The published script hardcodes $HOME/.opencode/bin, so it cannot honour
|
|
336
|
+
// a custom install directory; the npm/pnpm methods above can.
|
|
337
|
+
supportsInstallDir: false,
|
|
379
338
|
verify: Object.freeze({
|
|
380
339
|
mustInclude: ['anomalyco/opencode', 'opencode.ai'],
|
|
381
340
|
mustNotInclude: ['static-openapi.stepfun.com'],
|
|
@@ -405,7 +364,7 @@ export const OFFICIAL_TOOLS = Object.freeze([
|
|
|
405
364
|
platforms: ['linux', 'darwin'],
|
|
406
365
|
installArg: ['--install-dir'],
|
|
407
366
|
env: ['STEP_INSTALL_DIR', 'STEP_RELEASE_BASE_URL'],
|
|
408
|
-
|
|
367
|
+
supportsInstallDir: true,
|
|
409
368
|
verify: Object.freeze({
|
|
410
369
|
mustInclude: ['static-openapi.stepfun.com', 'stepcode installer'],
|
|
411
370
|
mustNotInclude: ['anomalyco/opencode'],
|
|
@@ -417,7 +376,7 @@ export const OFFICIAL_TOOLS = Object.freeze([
|
|
|
417
376
|
platforms: ['win32'],
|
|
418
377
|
installArg: ['-InstallDir'],
|
|
419
378
|
env: ['STEP_INSTALL_DIR', 'STEP_RELEASE_BASE_URL'],
|
|
420
|
-
|
|
379
|
+
supportsInstallDir: true,
|
|
421
380
|
verify: Object.freeze({
|
|
422
381
|
mustInclude: ['static-openapi.stepfun.com', 'stepcode'],
|
|
423
382
|
mustNotInclude: ['anomalyco/opencode'],
|
|
@@ -464,7 +423,10 @@ export function installMethodsFor(tool) {
|
|
|
464
423
|
export function installMethodFor(tool, methodId) {
|
|
465
424
|
const wanted = String(methodId ?? '').trim()
|
|
466
425
|
if (!wanted) return null
|
|
467
|
-
|
|
426
|
+
// 0.17.1 saved Codex's POSIX installer as script-bash. The vendor uses sh;
|
|
427
|
+
// preserve that saved choice while returning the current declared method.
|
|
428
|
+
const canonical = tool?.id === 'codex' && wanted === 'script-bash' ? 'script-sh' : wanted
|
|
429
|
+
return installMethodsFor(tool).find(method => method.id === canonical) ?? null
|
|
468
430
|
}
|
|
469
431
|
|
|
470
432
|
/** The tool's default method, kept identical to `manager` / `installArgs`. */
|
|
@@ -480,7 +442,7 @@ export function installMethodBlockReason(method, platform = 'linux') {
|
|
|
480
442
|
|
|
481
443
|
/**
|
|
482
444
|
* A method able to place the tool in the user's chosen directory. npm and pnpm
|
|
483
|
-
*
|
|
445
|
+
* bind their global directories; vendor scripts declare an argument or environment binding.
|
|
484
446
|
*/
|
|
485
447
|
export function methodHonoursInstallDir(method) {
|
|
486
448
|
return method?.supportsInstallDir === true
|
|
@@ -499,8 +461,8 @@ export function installCommandLineFor(tool, method) {
|
|
|
499
461
|
if (!tool || tool.unsupported) return null
|
|
500
462
|
if (!method) return null
|
|
501
463
|
if (method.kind === 'script') {
|
|
502
|
-
const piped = method.shell === 'powershell' ? `irm ${method.scriptUrl} | iex` : `curl -fsSL ${method.scriptUrl} |
|
|
503
|
-
return
|
|
464
|
+
const piped = method.shell === 'powershell' ? `irm ${method.scriptUrl} | iex` : `curl -fsSL ${method.scriptUrl} | ${method.shell}`
|
|
465
|
+
return piped
|
|
504
466
|
}
|
|
505
467
|
return `${method.manager} ${method.installArgs.join(' ')}`
|
|
506
468
|
}
|
|
@@ -509,6 +471,7 @@ export function installCommandLineFor(tool, method) {
|
|
|
509
471
|
export function uninstallCommandLineFor(tool, method) {
|
|
510
472
|
if (!tool || tool.unsupported || !method) return null
|
|
511
473
|
if (tool.manager === 'signed-windows-installer') return null
|
|
474
|
+
if (method.uninstallUnsupportedReason) return method.uninstallUnsupportedReason
|
|
512
475
|
if (method.kind === 'script') return '删除官方安装的可执行文件(保留配置与登录信息)'
|
|
513
476
|
return `${method.manager} ${method.uninstallArgs.join(' ')}`
|
|
514
477
|
}
|