@ljwei-stak/dsh-model-router 0.17.0 → 0.17.1

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.
@@ -62,7 +62,16 @@ function packageManagerMethod(id2, label, manager, spec, { registryFlag = "--reg
62
62
  supportsRegistry: true
63
63
  });
64
64
  }
65
- function scriptMethod(id2, label, { shell, scriptUrl, verify, installArg = [], env = [], platforms, supportsInstallDir = false }) {
65
+ function scriptMethod(id2, label, {
66
+ shell,
67
+ scriptUrl,
68
+ verify,
69
+ installArg = [],
70
+ env = [],
71
+ platforms,
72
+ installDirEnv = "",
73
+ defaultInstallDir = ""
74
+ }) {
66
75
  return Object.freeze({
67
76
  id: id2,
68
77
  label,
@@ -74,9 +83,13 @@ function scriptMethod(id2, label, { shell, scriptUrl, verify, installArg = [], e
74
83
  installArgs: Object.freeze(installArg),
75
84
  /** Environment the vendor script itself documents for this install. */
76
85
  env: Object.freeze(env),
86
+ /** When set, the configured directory is this environment variable, not an argv flag. */
87
+ installDirEnv,
88
+ /** Home-relative directory the vendor uses when the user sets none. Slashes only. */
89
+ defaultInstallDir,
77
90
  platforms: Object.freeze(platforms),
78
91
  /** Whether the vendor script honours a caller-chosen directory at all. */
79
- supportsInstallDir,
92
+ supportsInstallDir: Boolean(installDirEnv) || installArg.length > 0,
80
93
  supportsRegistry: false
81
94
  });
82
95
  }
@@ -93,9 +106,36 @@ var OFFICIAL_TOOLS = Object.freeze([
93
106
  probeExecutables: ["kimi"],
94
107
  probeNote: "kimi \u4E0E\u65E7 Python \u7248 kimi-cli \u540C\u540D\uFF1B\u8BF7\u6838\u5BF9\u53EF\u6267\u884C\u6587\u4EF6\u6765\u6E90\u548C\u7248\u672C\u3002",
95
108
  providerHints: ["moonshot", "kimi"],
109
+ scriptBinaryNames: Object.freeze(["kimi", "kimi.exe"]),
110
+ scriptBinaryRelatives: Object.freeze(["bin/kimi", "bin/kimi.exe"]),
111
+ defaultScriptInstallDir: ".kimi-code",
96
112
  installMethods: Object.freeze([
97
113
  packageManagerMethod("npm", "npm", "npm", "@moonshot-ai/kimi-code@latest"),
98
- packageManagerMethod("pnpm", "pnpm", "pnpm", "@moonshot-ai/kimi-code@latest")
114
+ packageManagerMethod("pnpm", "pnpm", "pnpm", "@moonshot-ai/kimi-code@latest"),
115
+ scriptMethod("script-bash", "curl | bash", {
116
+ shell: "bash",
117
+ scriptUrl: "https://code.kimi.com/kimi-code/install.sh",
118
+ platforms: ["linux", "darwin"],
119
+ installDirEnv: "KIMI_INSTALL_DIR",
120
+ defaultInstallDir: ".kimi-code",
121
+ env: ["KIMI_INSTALL_DIR"],
122
+ verify: Object.freeze({
123
+ mustInclude: ["code.kimi.com/kimi-code", "KIMI_INSTALL_DIR"],
124
+ mustNotInclude: ["downloads.claude.ai/claude-code-releases", "@minimax-ai/code"]
125
+ })
126
+ }),
127
+ scriptMethod("script-powershell", "irm | iex", {
128
+ shell: "powershell",
129
+ scriptUrl: "https://code.kimi.com/kimi-code/install.ps1",
130
+ platforms: ["win32"],
131
+ installDirEnv: "KIMI_INSTALL_DIR",
132
+ defaultInstallDir: ".kimi-code",
133
+ env: ["KIMI_INSTALL_DIR"],
134
+ verify: Object.freeze({
135
+ mustInclude: ["code.kimi.com/kimi-code", "KIMI_INSTALL_DIR"],
136
+ mustNotInclude: ["downloads.claude.ai/claude-code-releases", "@minimax-ai/code"]
137
+ })
138
+ })
99
139
  ])
100
140
  }),
101
141
  Object.freeze({
@@ -109,9 +149,32 @@ var OFFICIAL_TOOLS = Object.freeze([
109
149
  uninstallArgs: ["uninstall", "-g", "@anthropic-ai/claude-code"],
110
150
  probeExecutables: ["claude"],
111
151
  providerHints: ["anthropic", "claude"],
152
+ // The native installer always lands in ~/.local/bin; it has no directory flag.
153
+ scriptBinaryNames: Object.freeze(["claude", "claude.exe"]),
154
+ defaultScriptInstallDir: ".local/bin",
112
155
  installMethods: Object.freeze([
113
156
  packageManagerMethod("npm", "npm", "npm", "@anthropic-ai/claude-code@latest"),
114
- packageManagerMethod("pnpm", "pnpm", "pnpm", "@anthropic-ai/claude-code@latest")
157
+ packageManagerMethod("pnpm", "pnpm", "pnpm", "@anthropic-ai/claude-code@latest"),
158
+ scriptMethod("script-bash", "curl | bash", {
159
+ shell: "bash",
160
+ scriptUrl: "https://claude.ai/install.sh",
161
+ platforms: ["linux", "darwin"],
162
+ defaultInstallDir: ".local/bin",
163
+ verify: Object.freeze({
164
+ mustInclude: ["downloads.claude.ai/claude-code-releases", "claude.ai/install.sh"],
165
+ mustNotInclude: ["@minimax-ai/code", "releases.openai.com/codex"]
166
+ })
167
+ }),
168
+ scriptMethod("script-powershell", "irm | iex", {
169
+ shell: "powershell",
170
+ scriptUrl: "https://claude.ai/install.ps1",
171
+ platforms: ["win32"],
172
+ defaultInstallDir: ".local/bin",
173
+ verify: Object.freeze({
174
+ mustInclude: ["downloads.claude.ai/claude-code-releases"],
175
+ mustNotInclude: ["@minimax-ai/code", "releases.openai.com/codex"]
176
+ })
177
+ })
115
178
  ])
116
179
  }),
117
180
  Object.freeze({
@@ -126,9 +189,35 @@ var OFFICIAL_TOOLS = Object.freeze([
126
189
  probeExecutables: ["codex"],
127
190
  probeNote: "Codex \u7248\u672C\u6A2A\u5E45\u7531\u9002\u914D\u5C42\u5BBD\u5339\u914D\uFF1B\u5B89\u88C5\u65F6\u53D6 npm \u6700\u65B0\u7248\u3002",
128
191
  providerHints: ["openai", "gpt", "codex"],
192
+ scriptBinaryNames: Object.freeze(["codex", "codex.exe"]),
129
193
  installMethods: Object.freeze([
130
194
  packageManagerMethod("npm", "npm", "npm", "@openai/codex@latest"),
131
- packageManagerMethod("pnpm", "pnpm", "pnpm", "@openai/codex@latest")
195
+ packageManagerMethod("pnpm", "pnpm", "pnpm", "@openai/codex@latest"),
196
+ scriptMethod("script-bash", "curl | bash", {
197
+ shell: "bash",
198
+ scriptUrl: "https://chatgpt.com/codex/install.sh",
199
+ platforms: ["linux", "darwin"],
200
+ installDirEnv: "CODEX_INSTALL_DIR",
201
+ defaultInstallDir: ".local/bin",
202
+ env: ["CODEX_INSTALL_DIR"],
203
+ verify: Object.freeze({
204
+ mustInclude: ["releases.openai.com/codex", "CODEX_INSTALL_DIR"],
205
+ mustNotInclude: ["downloads.claude.ai/claude-code-releases", "@minimax-ai/code"]
206
+ })
207
+ }),
208
+ scriptMethod("script-powershell", "irm | iex", {
209
+ shell: "powershell",
210
+ scriptUrl: "https://chatgpt.com/codex/install.ps1",
211
+ platforms: ["win32"],
212
+ installDirEnv: "CODEX_INSTALL_DIR",
213
+ // %LOCALAPPDATA%\Programs\OpenAI\Codex\bin under a normal user profile.
214
+ defaultInstallDir: "AppData/Local/Programs/OpenAI/Codex/bin",
215
+ env: ["CODEX_INSTALL_DIR"],
216
+ verify: Object.freeze({
217
+ mustInclude: ["releases.openai.com/codex", "CODEX_INSTALL_DIR"],
218
+ mustNotInclude: ["downloads.claude.ai/claude-code-releases", "@minimax-ai/code"]
219
+ })
220
+ })
132
221
  ])
133
222
  }),
134
223
  Object.freeze({
@@ -142,9 +231,51 @@ var OFFICIAL_TOOLS = Object.freeze([
142
231
  uninstallArgs: ["uninstall", "-g", "@minimax-ai/code"],
143
232
  probeExecutables: ["mcode"],
144
233
  providerHints: ["minimax"],
234
+ scriptBinaryNames: Object.freeze([
235
+ "mcode",
236
+ "mcode.exe",
237
+ "mcode.cmd",
238
+ "mcode.ps1",
239
+ "mcode-tools",
240
+ "mcode-tools.cmd",
241
+ "mcode-tools.ps1"
242
+ ]),
243
+ scriptBinaryRelatives: Object.freeze([
244
+ "mcode.cmd",
245
+ "mcode.ps1",
246
+ "mcode-tools.cmd",
247
+ "mcode-tools.ps1",
248
+ "bin/mcode",
249
+ "bin/mcode-tools"
250
+ ]),
251
+ defaultScriptInstallDir: ".minimax-code",
145
252
  installMethods: Object.freeze([
146
253
  packageManagerMethod("npm", "npm", "npm", "@minimax-ai/code@latest"),
147
- packageManagerMethod("pnpm", "pnpm", "pnpm", "@minimax-ai/code@latest")
254
+ packageManagerMethod("pnpm", "pnpm", "pnpm", "@minimax-ai/code@latest"),
255
+ scriptMethod("script-bash", "curl | bash", {
256
+ shell: "bash",
257
+ scriptUrl: "https://filecdn.minimax.chat/public/install.sh",
258
+ platforms: ["linux", "darwin"],
259
+ installDirEnv: "MCODE_INSTALL_DIR",
260
+ defaultInstallDir: ".minimax-code",
261
+ env: ["MCODE_INSTALL_DIR", "MCODE_NPM_REGISTRY"],
262
+ verify: Object.freeze({
263
+ mustInclude: ["@minimax-ai/code", "MCODE_INSTALL_DIR", "MiniMax Code"],
264
+ mustNotInclude: ["downloads.claude.ai/claude-code-releases", "releases.openai.com/codex"]
265
+ })
266
+ }),
267
+ scriptMethod("script-powershell", "irm | iex", {
268
+ shell: "powershell",
269
+ scriptUrl: "https://filecdn.minimax.chat/public/install.ps1",
270
+ platforms: ["win32"],
271
+ installDirEnv: "MCODE_INSTALL_DIR",
272
+ defaultInstallDir: ".minimax-code",
273
+ env: ["MCODE_INSTALL_DIR", "MCODE_NPM_REGISTRY"],
274
+ verify: Object.freeze({
275
+ mustInclude: ["@minimax-ai/code", "MCODE_INSTALL_DIR", "MiniMax Code"],
276
+ mustNotInclude: ["downloads.claude.ai/claude-code-releases", "releases.openai.com/codex"]
277
+ })
278
+ })
148
279
  ])
149
280
  }),
150
281
  Object.freeze({
@@ -158,9 +289,34 @@ var OFFICIAL_TOOLS = Object.freeze([
158
289
  uninstallArgs: ["uninstall", "-g", "@mimo-ai/cli"],
159
290
  probeExecutables: ["mimo"],
160
291
  providerHints: ["mimo", "xiaomi"],
292
+ scriptBinaryNames: Object.freeze(["mimo", "mimo.exe"]),
293
+ defaultScriptInstallDir: ".mimocode/bin",
161
294
  installMethods: Object.freeze([
162
295
  packageManagerMethod("npm", "npm", "npm", "@mimo-ai/cli@latest"),
163
- packageManagerMethod("pnpm", "pnpm", "pnpm", "@mimo-ai/cli@latest")
296
+ packageManagerMethod("pnpm", "pnpm", "pnpm", "@mimo-ai/cli@latest"),
297
+ // The Unix script hardcodes ~/.mimocode/bin and ignores MIMOCODE_INSTALL_DIR.
298
+ scriptMethod("script-bash", "curl | bash", {
299
+ shell: "bash",
300
+ scriptUrl: "https://mimo.xiaomi.com/install",
301
+ platforms: ["linux", "darwin"],
302
+ defaultInstallDir: ".mimocode/bin",
303
+ verify: Object.freeze({
304
+ mustInclude: ["MiMoCode", "mimo.xiaomi.com"],
305
+ mustNotInclude: ["@minimax-ai/code", "downloads.claude.ai/claude-code-releases"]
306
+ })
307
+ }),
308
+ scriptMethod("script-powershell", "irm | iex", {
309
+ shell: "powershell",
310
+ scriptUrl: "https://mimo.xiaomi.com/install.ps1",
311
+ platforms: ["win32"],
312
+ installDirEnv: "MIMOCODE_INSTALL_DIR",
313
+ defaultInstallDir: ".mimocode/bin",
314
+ env: ["MIMOCODE_INSTALL_DIR"],
315
+ verify: Object.freeze({
316
+ mustInclude: ["MiMoCode", "mimo.xiaomi.com", "MIMOCODE_INSTALL_DIR"],
317
+ mustNotInclude: ["@minimax-ai/code", "downloads.claude.ai/claude-code-releases"]
318
+ })
319
+ })
164
320
  ])
165
321
  }),
166
322
  Object.freeze({
@@ -174,9 +330,35 @@ var OFFICIAL_TOOLS = Object.freeze([
174
330
  uninstallArgs: ["uninstall", "-g", "@xai-official/grok"],
175
331
  probeExecutables: ["grok"],
176
332
  providerHints: ["xai", "grok"],
333
+ scriptBinaryNames: Object.freeze(["grok", "grok.exe", "agent", "agent.exe"]),
334
+ defaultScriptInstallDir: ".grok/bin",
177
335
  installMethods: Object.freeze([
178
336
  packageManagerMethod("npm", "npm", "npm", "@xai-official/grok@latest"),
179
- packageManagerMethod("pnpm", "pnpm", "pnpm", "@xai-official/grok@latest")
337
+ packageManagerMethod("pnpm", "pnpm", "pnpm", "@xai-official/grok@latest"),
338
+ scriptMethod("script-bash", "curl | bash", {
339
+ shell: "bash",
340
+ scriptUrl: "https://x.ai/cli/install.sh",
341
+ platforms: ["linux", "darwin"],
342
+ installDirEnv: "GROK_BIN_DIR",
343
+ defaultInstallDir: ".grok/bin",
344
+ env: ["GROK_BIN_DIR"],
345
+ verify: Object.freeze({
346
+ mustInclude: ["x.ai/cli", "GROK_BIN_DIR"],
347
+ mustNotInclude: ["@minimax-ai/code", "downloads.claude.ai/claude-code-releases"]
348
+ })
349
+ }),
350
+ scriptMethod("script-powershell", "irm | iex", {
351
+ shell: "powershell",
352
+ scriptUrl: "https://x.ai/cli/install.ps1",
353
+ platforms: ["win32"],
354
+ installDirEnv: "GROK_BIN_DIR",
355
+ defaultInstallDir: ".grok/bin",
356
+ env: ["GROK_BIN_DIR"],
357
+ verify: Object.freeze({
358
+ mustInclude: ["x.ai/cli", "GROK_BIN_DIR"],
359
+ mustNotInclude: ["@minimax-ai/code", "downloads.claude.ai/claude-code-releases"]
360
+ })
361
+ })
180
362
  ])
181
363
  }),
182
364
  Object.freeze({
@@ -223,9 +405,7 @@ var OFFICIAL_TOOLS = Object.freeze([
223
405
  shell: "bash",
224
406
  scriptUrl: "https://opencode.ai/install",
225
407
  platforms: ["linux", "darwin"],
226
- // The published script hardcodes $HOME/.opencode/bin, so it cannot honour
227
- // a custom install directory; the npm/pnpm methods above can.
228
- supportsInstallDir: false,
408
+ defaultInstallDir: ".opencode/bin",
229
409
  verify: Object.freeze({
230
410
  mustInclude: ["anomalyco/opencode", "opencode.ai"],
231
411
  mustNotInclude: ["static-openapi.stepfun.com"]
@@ -255,7 +435,7 @@ var OFFICIAL_TOOLS = Object.freeze([
255
435
  platforms: ["linux", "darwin"],
256
436
  installArg: ["--install-dir"],
257
437
  env: ["STEP_INSTALL_DIR", "STEP_RELEASE_BASE_URL"],
258
- supportsInstallDir: true,
438
+ defaultInstallDir: ".stepcode/bin",
259
439
  verify: Object.freeze({
260
440
  mustInclude: ["static-openapi.stepfun.com", "stepcode installer"],
261
441
  mustNotInclude: ["anomalyco/opencode"]
@@ -267,7 +447,7 @@ var OFFICIAL_TOOLS = Object.freeze([
267
447
  platforms: ["win32"],
268
448
  installArg: ["-InstallDir"],
269
449
  env: ["STEP_INSTALL_DIR", "STEP_RELEASE_BASE_URL"],
270
- supportsInstallDir: true,
450
+ defaultInstallDir: ".stepcode/bin",
271
451
  verify: Object.freeze({
272
452
  mustInclude: ["static-openapi.stepfun.com", "stepcode"],
273
453
  mustNotInclude: ["anomalyco/opencode"]
@@ -3024,7 +3204,7 @@ function LaunchPreview({ value, changed, running, confirmRef, onConfirm, onCance
3024
3204
  // .dsh-plugin/client/cli-terminal.jsx
3025
3205
  var import_react4 = __toESM(require("react"), 1);
3026
3206
 
3027
- // node_modules/.pnpm/@xterm+xterm@6.0.0/node_modules/@xterm/xterm/lib/xterm.mjs
3207
+ // node_modules/@xterm/xterm/lib/xterm.mjs
3028
3208
  var zs = Object.defineProperty;
3029
3209
  var Rl = Object.getOwnPropertyDescriptor;
3030
3210
  var Ll = (s15, t) => {
@@ -12138,7 +12318,7 @@ var Dl = class extends D {
12138
12318
  }
12139
12319
  };
12140
12320
 
12141
- // node_modules/.pnpm/@xterm+addon-fit@0.11.0/node_modules/@xterm/addon-fit/lib/addon-fit.mjs
12321
+ // node_modules/@xterm/addon-fit/lib/addon-fit.mjs
12142
12322
  var h = 2;
12143
12323
  var _ = 1;
12144
12324
  var o = class {
@@ -12162,7 +12342,7 @@ var o = class {
12162
12342
  }
12163
12343
  };
12164
12344
 
12165
- // node_modules/.pnpm/@xterm+xterm@6.0.0/node_modules/@xterm/xterm/css/xterm.css
12345
+ // node_modules/@xterm/xterm/css/xterm.css
12166
12346
  var xterm_default = `/**
12167
12347
  * Copyright (c) 2014 The xterm.js authors. All rights reserved.
12168
12348
  * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
@@ -12451,7 +12631,7 @@ var xterm_default = `/**
12451
12631
  `;
12452
12632
 
12453
12633
  // .dsh-plugin/client/host-version.mjs
12454
- var ROUTER_CLIENT_VERSION = true ? "0.17.0" : "";
12634
+ var ROUTER_CLIENT_VERSION = true ? "0.17.1" : "";
12455
12635
  var STALE_HOST_MESSAGE = "\u63D2\u4EF6\u540E\u53F0\u7248\u672C\u8F83\u65E7\uFF0C\u8BF7\u5B8C\u5168\u9000\u51FA\u5E76\u91CD\u542F Harness\uFF08\u5305\u62EC\u6258\u76D8\u56FE\u6807\uFF09\u540E\u518D\u4F7F\u7528\u3002";
12456
12636
  function isMissingRemoteMethod(message) {
12457
12637
  const value = String(message ?? "");
@@ -13285,7 +13465,7 @@ var INSTALL_SETTING_FIELDS = [
13285
13465
  label: "\u7EDF\u4E00\u5B89\u88C5\u76EE\u5F55",
13286
13466
  fallback: "",
13287
13467
  placeholder: "\u7559\u7A7A = \u5404\u5382\u5546\u9ED8\u8BA4\u76EE\u5F55",
13288
- hint: "npm / pnpm \u65B9\u5F0F\u4F1A\u52A0 --prefix\uFF1B\u811A\u672C\u65B9\u5F0F\u770B\u5382\u5546\u662F\u5426\u652F\u6301\u76EE\u5F55\u53C2\u6570\u3002",
13468
+ hint: "npm / pnpm \u4F1A\u52A0 --prefix\u3002\u652F\u6301\u76EE\u5F55\u7684\u5B98\u65B9\u811A\u672C\u628A\u8FD9\u4E2A\u8DEF\u5F84\u4F20\u7ED9\u5382\u5546\u81EA\u5DF1\u7684\u5B89\u88C5\u76EE\u5F55\u53D8\u91CF\uFF1B\u5199\u6B7B\u8DEF\u5F84\u7684\u811A\u672C\u4F1A\u6807\u660E\u5B9E\u9645\u843D\u70B9\u3002\u66F4\u65B0\u4E5F\u4F7F\u7528\u8FD9\u91CC\uFF0C\u4E0D\u4F1A\u6539\u53BB\u522B\u7684\u9ED8\u8BA4\u4F4D\u7F6E\u3002",
13289
13469
  validate: () => null
13290
13470
  },
13291
13471
  {
@@ -14495,7 +14675,7 @@ function RouterSettingsCard(props) {
14495
14675
  {
14496
14676
  id: "model-router-tool-install-dir",
14497
14677
  label: "\u7EDF\u4E00\u5B89\u88C5\u76EE\u5F55",
14498
- hint: "\u7559\u7A7A\u8868\u793A\u4F7F\u7528\u5404\u5382\u5546\u9ED8\u8BA4\u4F4D\u7F6E\uFF08npm \u5168\u5C40\u76EE\u5F55 / \u5382\u5546\u811A\u672C\u76EE\u5F55\uFF09\u3002npm \u4E0E pnpm \u65B9\u5F0F\u4F1A\u5E26\u4E0A --prefix\uFF1B\u5382\u5546\u5B89\u88C5\u811A\u672C\u662F\u5426\u652F\u6301\u76EE\u5F55\u53C2\u6570\u53D6\u51B3\u4E8E\u8BE5\u5382\u5546\u3002\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84\u3002",
14678
+ hint: "\u7559\u7A7A\u8868\u793A\u4F7F\u7528\u5404\u5382\u5546\u9ED8\u8BA4\u4F4D\u7F6E\u3002npm \u4E0E pnpm \u4F1A\u5E26\u4E0A --prefix\uFF1B\u652F\u6301\u76EE\u5F55\u7684\u5B98\u65B9\u811A\u672C\u4F1A\u628A\u8FD9\u4E2A\u8DEF\u5F84\u4F20\u7ED9\u5382\u5546\u81EA\u5DF1\u7684\u5B89\u88C5\u76EE\u5F55\u53D8\u91CF\uFF08\u4F8B\u5982 MCODE_INSTALL_DIR\uFF09\u3002\u5199\u6B7B\u8DEF\u5F84\u7684\u811A\u672C\u4F1A\u5728\u5DE5\u5177\u884C\u6807\u660E\u5B9E\u9645\u843D\u70B9\u3002\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84\u3002\u66F4\u65B0\u4F7F\u7528\u540C\u4E00\u8DEF\u5F84\u3002",
14499
14679
  disabled,
14500
14680
  ...state.toolInstallDir,
14501
14681
  overriddenLabel: FIELD_COPY.overridden,
@@ -40,8 +40,16 @@ function packageManagerMethod(id, label, manager, spec, { registryFlag = '--regi
40
40
  })
41
41
  }
42
42
 
43
- /** Vendor installer script run from a verified local copy. */
44
- function scriptMethod(id, label, { shell, scriptUrl, verify, installArg = [], env = [], platforms, supportsInstallDir = false }) {
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
+ */
49
+ function scriptMethod(id, label, {
50
+ shell, scriptUrl, verify, installArg = [], env = [], platforms,
51
+ installDirEnv = '', defaultInstallDir = '',
52
+ }) {
45
53
  return Object.freeze({
46
54
  id,
47
55
  label,
@@ -53,9 +61,13 @@ function scriptMethod(id, label, { shell, scriptUrl, verify, installArg = [], en
53
61
  installArgs: Object.freeze(installArg),
54
62
  /** Environment the vendor script itself documents for this install. */
55
63
  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,
56
68
  platforms: Object.freeze(platforms),
57
69
  /** Whether the vendor script honours a caller-chosen directory at all. */
58
- supportsInstallDir,
70
+ supportsInstallDir: Boolean(installDirEnv) || installArg.length > 0,
59
71
  supportsRegistry: false,
60
72
  })
61
73
  }
@@ -73,9 +85,36 @@ export const OFFICIAL_TOOLS = Object.freeze([
73
85
  probeExecutables: ['kimi'],
74
86
  probeNote: 'kimi 与旧 Python 版 kimi-cli 同名;请核对可执行文件来源和版本。',
75
87
  providerHints: ['moonshot', 'kimi'],
88
+ scriptBinaryNames: Object.freeze(['kimi', 'kimi.exe']),
89
+ scriptBinaryRelatives: Object.freeze(['bin/kimi', 'bin/kimi.exe']),
90
+ defaultScriptInstallDir: '.kimi-code',
76
91
  installMethods: Object.freeze([
77
92
  packageManagerMethod('npm', 'npm', 'npm', '@moonshot-ai/kimi-code@latest'),
78
93
  packageManagerMethod('pnpm', 'pnpm', 'pnpm', '@moonshot-ai/kimi-code@latest'),
94
+ scriptMethod('script-bash', 'curl | bash', {
95
+ shell: 'bash',
96
+ scriptUrl: 'https://code.kimi.com/kimi-code/install.sh',
97
+ platforms: ['linux', 'darwin'],
98
+ installDirEnv: 'KIMI_INSTALL_DIR',
99
+ defaultInstallDir: '.kimi-code',
100
+ env: ['KIMI_INSTALL_DIR'],
101
+ verify: Object.freeze({
102
+ mustInclude: ['code.kimi.com/kimi-code', 'KIMI_INSTALL_DIR'],
103
+ mustNotInclude: ['downloads.claude.ai/claude-code-releases', '@minimax-ai/code'],
104
+ }),
105
+ }),
106
+ scriptMethod('script-powershell', 'irm | iex', {
107
+ shell: 'powershell',
108
+ scriptUrl: 'https://code.kimi.com/kimi-code/install.ps1',
109
+ platforms: ['win32'],
110
+ installDirEnv: 'KIMI_INSTALL_DIR',
111
+ defaultInstallDir: '.kimi-code',
112
+ env: ['KIMI_INSTALL_DIR'],
113
+ verify: Object.freeze({
114
+ mustInclude: ['code.kimi.com/kimi-code', 'KIMI_INSTALL_DIR'],
115
+ mustNotInclude: ['downloads.claude.ai/claude-code-releases', '@minimax-ai/code'],
116
+ }),
117
+ }),
79
118
  ]),
80
119
  }),
81
120
  Object.freeze({
@@ -89,9 +128,32 @@ export const OFFICIAL_TOOLS = Object.freeze([
89
128
  uninstallArgs: ['uninstall', '-g', '@anthropic-ai/claude-code'],
90
129
  probeExecutables: ['claude'],
91
130
  providerHints: ['anthropic', 'claude'],
131
+ // The native installer always lands in ~/.local/bin; it has no directory flag.
132
+ scriptBinaryNames: Object.freeze(['claude', 'claude.exe']),
133
+ defaultScriptInstallDir: '.local/bin',
92
134
  installMethods: Object.freeze([
93
135
  packageManagerMethod('npm', 'npm', 'npm', '@anthropic-ai/claude-code@latest'),
94
136
  packageManagerMethod('pnpm', 'pnpm', 'pnpm', '@anthropic-ai/claude-code@latest'),
137
+ scriptMethod('script-bash', 'curl | bash', {
138
+ shell: 'bash',
139
+ scriptUrl: 'https://claude.ai/install.sh',
140
+ platforms: ['linux', 'darwin'],
141
+ defaultInstallDir: '.local/bin',
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
+ }),
146
+ }),
147
+ scriptMethod('script-powershell', 'irm | iex', {
148
+ shell: 'powershell',
149
+ scriptUrl: 'https://claude.ai/install.ps1',
150
+ platforms: ['win32'],
151
+ defaultInstallDir: '.local/bin',
152
+ verify: Object.freeze({
153
+ mustInclude: ['downloads.claude.ai/claude-code-releases'],
154
+ mustNotInclude: ['@minimax-ai/code', 'releases.openai.com/codex'],
155
+ }),
156
+ }),
95
157
  ]),
96
158
  }),
97
159
  Object.freeze({
@@ -106,9 +168,35 @@ export const OFFICIAL_TOOLS = Object.freeze([
106
168
  probeExecutables: ['codex'],
107
169
  probeNote: 'Codex 版本横幅由适配层宽匹配;安装时取 npm 最新版。',
108
170
  providerHints: ['openai', 'gpt', 'codex'],
171
+ scriptBinaryNames: Object.freeze(['codex', 'codex.exe']),
109
172
  installMethods: Object.freeze([
110
173
  packageManagerMethod('npm', 'npm', 'npm', '@openai/codex@latest'),
111
174
  packageManagerMethod('pnpm', 'pnpm', 'pnpm', '@openai/codex@latest'),
175
+ scriptMethod('script-bash', 'curl | bash', {
176
+ shell: 'bash',
177
+ scriptUrl: 'https://chatgpt.com/codex/install.sh',
178
+ platforms: ['linux', 'darwin'],
179
+ installDirEnv: 'CODEX_INSTALL_DIR',
180
+ defaultInstallDir: '.local/bin',
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
+ }),
186
+ }),
187
+ scriptMethod('script-powershell', 'irm | iex', {
188
+ shell: 'powershell',
189
+ scriptUrl: 'https://chatgpt.com/codex/install.ps1',
190
+ platforms: ['win32'],
191
+ installDirEnv: 'CODEX_INSTALL_DIR',
192
+ // %LOCALAPPDATA%\Programs\OpenAI\Codex\bin under a normal user profile.
193
+ defaultInstallDir: 'AppData/Local/Programs/OpenAI/Codex/bin',
194
+ env: ['CODEX_INSTALL_DIR'],
195
+ verify: Object.freeze({
196
+ mustInclude: ['releases.openai.com/codex', 'CODEX_INSTALL_DIR'],
197
+ mustNotInclude: ['downloads.claude.ai/claude-code-releases', '@minimax-ai/code'],
198
+ }),
199
+ }),
112
200
  ]),
113
201
  }),
114
202
  Object.freeze({
@@ -122,9 +210,42 @@ export const OFFICIAL_TOOLS = Object.freeze([
122
210
  uninstallArgs: ['uninstall', '-g', '@minimax-ai/code'],
123
211
  probeExecutables: ['mcode'],
124
212
  providerHints: ['minimax'],
213
+ scriptBinaryNames: Object.freeze([
214
+ 'mcode', 'mcode.exe', 'mcode.cmd', 'mcode.ps1',
215
+ 'mcode-tools', 'mcode-tools.cmd', 'mcode-tools.ps1',
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',
125
222
  installMethods: Object.freeze([
126
223
  packageManagerMethod('npm', 'npm', 'npm', '@minimax-ai/code@latest'),
127
224
  packageManagerMethod('pnpm', 'pnpm', 'pnpm', '@minimax-ai/code@latest'),
225
+ scriptMethod('script-bash', 'curl | bash', {
226
+ shell: 'bash',
227
+ scriptUrl: 'https://filecdn.minimax.chat/public/install.sh',
228
+ platforms: ['linux', 'darwin'],
229
+ installDirEnv: 'MCODE_INSTALL_DIR',
230
+ defaultInstallDir: '.minimax-code',
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
+ }),
236
+ }),
237
+ scriptMethod('script-powershell', 'irm | iex', {
238
+ shell: 'powershell',
239
+ scriptUrl: 'https://filecdn.minimax.chat/public/install.ps1',
240
+ platforms: ['win32'],
241
+ installDirEnv: 'MCODE_INSTALL_DIR',
242
+ defaultInstallDir: '.minimax-code',
243
+ env: ['MCODE_INSTALL_DIR', 'MCODE_NPM_REGISTRY'],
244
+ verify: Object.freeze({
245
+ mustInclude: ['@minimax-ai/code', 'MCODE_INSTALL_DIR', 'MiniMax Code'],
246
+ mustNotInclude: ['downloads.claude.ai/claude-code-releases', 'releases.openai.com/codex'],
247
+ }),
248
+ }),
128
249
  ]),
129
250
  }),
130
251
  Object.freeze({
@@ -138,9 +259,34 @@ export const OFFICIAL_TOOLS = Object.freeze([
138
259
  uninstallArgs: ['uninstall', '-g', '@mimo-ai/cli'],
139
260
  probeExecutables: ['mimo'],
140
261
  providerHints: ['mimo', 'xiaomi'],
262
+ scriptBinaryNames: Object.freeze(['mimo', 'mimo.exe']),
263
+ defaultScriptInstallDir: '.mimocode/bin',
141
264
  installMethods: Object.freeze([
142
265
  packageManagerMethod('npm', 'npm', 'npm', '@mimo-ai/cli@latest'),
143
266
  packageManagerMethod('pnpm', 'pnpm', 'pnpm', '@mimo-ai/cli@latest'),
267
+ // The Unix script hardcodes ~/.mimocode/bin and ignores MIMOCODE_INSTALL_DIR.
268
+ scriptMethod('script-bash', 'curl | bash', {
269
+ shell: 'bash',
270
+ scriptUrl: 'https://mimo.xiaomi.com/install',
271
+ platforms: ['linux', 'darwin'],
272
+ defaultInstallDir: '.mimocode/bin',
273
+ verify: Object.freeze({
274
+ mustInclude: ['MiMoCode', 'mimo.xiaomi.com'],
275
+ mustNotInclude: ['@minimax-ai/code', 'downloads.claude.ai/claude-code-releases'],
276
+ }),
277
+ }),
278
+ scriptMethod('script-powershell', 'irm | iex', {
279
+ shell: 'powershell',
280
+ scriptUrl: 'https://mimo.xiaomi.com/install.ps1',
281
+ platforms: ['win32'],
282
+ installDirEnv: 'MIMOCODE_INSTALL_DIR',
283
+ defaultInstallDir: '.mimocode/bin',
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
+ }),
289
+ }),
144
290
  ]),
145
291
  }),
146
292
  Object.freeze({
@@ -154,9 +300,35 @@ export const OFFICIAL_TOOLS = Object.freeze([
154
300
  uninstallArgs: ['uninstall', '-g', '@xai-official/grok'],
155
301
  probeExecutables: ['grok'],
156
302
  providerHints: ['xai', 'grok'],
303
+ scriptBinaryNames: Object.freeze(['grok', 'grok.exe', 'agent', 'agent.exe']),
304
+ defaultScriptInstallDir: '.grok/bin',
157
305
  installMethods: Object.freeze([
158
306
  packageManagerMethod('npm', 'npm', 'npm', '@xai-official/grok@latest'),
159
307
  packageManagerMethod('pnpm', 'pnpm', 'pnpm', '@xai-official/grok@latest'),
308
+ scriptMethod('script-bash', 'curl | bash', {
309
+ shell: 'bash',
310
+ scriptUrl: 'https://x.ai/cli/install.sh',
311
+ platforms: ['linux', 'darwin'],
312
+ installDirEnv: 'GROK_BIN_DIR',
313
+ defaultInstallDir: '.grok/bin',
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
+ }),
319
+ }),
320
+ scriptMethod('script-powershell', 'irm | iex', {
321
+ shell: 'powershell',
322
+ scriptUrl: 'https://x.ai/cli/install.ps1',
323
+ platforms: ['win32'],
324
+ installDirEnv: 'GROK_BIN_DIR',
325
+ defaultInstallDir: '.grok/bin',
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
+ }),
331
+ }),
160
332
  ]),
161
333
  }),
162
334
  Object.freeze({
@@ -203,9 +375,7 @@ export const OFFICIAL_TOOLS = Object.freeze([
203
375
  shell: 'bash',
204
376
  scriptUrl: 'https://opencode.ai/install',
205
377
  platforms: ['linux', 'darwin'],
206
- // The published script hardcodes $HOME/.opencode/bin, so it cannot honour
207
- // a custom install directory; the npm/pnpm methods above can.
208
- supportsInstallDir: false,
378
+ defaultInstallDir: '.opencode/bin',
209
379
  verify: Object.freeze({
210
380
  mustInclude: ['anomalyco/opencode', 'opencode.ai'],
211
381
  mustNotInclude: ['static-openapi.stepfun.com'],
@@ -235,7 +405,7 @@ export const OFFICIAL_TOOLS = Object.freeze([
235
405
  platforms: ['linux', 'darwin'],
236
406
  installArg: ['--install-dir'],
237
407
  env: ['STEP_INSTALL_DIR', 'STEP_RELEASE_BASE_URL'],
238
- supportsInstallDir: true,
408
+ defaultInstallDir: '.stepcode/bin',
239
409
  verify: Object.freeze({
240
410
  mustInclude: ['static-openapi.stepfun.com', 'stepcode installer'],
241
411
  mustNotInclude: ['anomalyco/opencode'],
@@ -247,7 +417,7 @@ export const OFFICIAL_TOOLS = Object.freeze([
247
417
  platforms: ['win32'],
248
418
  installArg: ['-InstallDir'],
249
419
  env: ['STEP_INSTALL_DIR', 'STEP_RELEASE_BASE_URL'],
250
- supportsInstallDir: true,
420
+ defaultInstallDir: '.stepcode/bin',
251
421
  verify: Object.freeze({
252
422
  mustInclude: ['static-openapi.stepfun.com', 'stepcode'],
253
423
  mustNotInclude: ['anomalyco/opencode'],