@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
package/.dsh-plugin/client.js
CHANGED
|
@@ -47,7 +47,7 @@ var import_react6 = __toESM(require("react"), 1);
|
|
|
47
47
|
|
|
48
48
|
// .dsh-plugin/shared/official-tool-registry.mjs
|
|
49
49
|
var DEFAULT_NPM_REGISTRY = "https://registry.npmjs.org/";
|
|
50
|
-
function packageManagerMethod(id2, label, manager, spec, { registryFlag = "--registry=" } = {}) {
|
|
50
|
+
function packageManagerMethod(id2, label, manager, spec, { registryFlag = "--registry=", command = "install", extraArgs = [] } = {}) {
|
|
51
51
|
return Object.freeze({
|
|
52
52
|
id: id2,
|
|
53
53
|
label,
|
|
@@ -55,9 +55,9 @@ function packageManagerMethod(id2, label, manager, spec, { registryFlag = "--reg
|
|
|
55
55
|
manager,
|
|
56
56
|
spec,
|
|
57
57
|
registryFlag,
|
|
58
|
-
installArgs: Object.freeze([
|
|
58
|
+
installArgs: Object.freeze([command, "-g", spec, ...extraArgs]),
|
|
59
59
|
uninstallArgs: Object.freeze(["uninstall", "-g", spec.replace(/@latest$/, "")]),
|
|
60
|
-
/**
|
|
60
|
+
/** The resolver binds npm prefix or pnpm global-dir/global-bin-dir. */
|
|
61
61
|
supportsInstallDir: true,
|
|
62
62
|
supportsRegistry: true
|
|
63
63
|
});
|
|
@@ -69,8 +69,16 @@ function scriptMethod(id2, label, {
|
|
|
69
69
|
installArg = [],
|
|
70
70
|
env = [],
|
|
71
71
|
platforms,
|
|
72
|
+
supportsInstallDir = false,
|
|
72
73
|
installDirEnv = "",
|
|
73
|
-
|
|
74
|
+
installDirSuffix = "",
|
|
75
|
+
defaultScriptInstallDir,
|
|
76
|
+
defaultScriptInstallDirEnv,
|
|
77
|
+
scriptBinaryNames,
|
|
78
|
+
registryEnv,
|
|
79
|
+
installDirSubdir,
|
|
80
|
+
uninstallUnsupportedReason,
|
|
81
|
+
scriptFallbackUrls
|
|
74
82
|
}) {
|
|
75
83
|
return Object.freeze({
|
|
76
84
|
id: id2,
|
|
@@ -83,14 +91,19 @@ function scriptMethod(id2, label, {
|
|
|
83
91
|
installArgs: Object.freeze(installArg),
|
|
84
92
|
/** Environment the vendor script itself documents for this install. */
|
|
85
93
|
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,
|
|
90
94
|
platforms: Object.freeze(platforms),
|
|
91
95
|
/** Whether the vendor script honours a caller-chosen directory at all. */
|
|
92
|
-
supportsInstallDir
|
|
93
|
-
|
|
96
|
+
supportsInstallDir,
|
|
97
|
+
installDirEnv,
|
|
98
|
+
installDirSuffix,
|
|
99
|
+
...installDirSubdir ? { installDirSubdir } : {},
|
|
100
|
+
...uninstallUnsupportedReason ? { uninstallUnsupportedReason } : {},
|
|
101
|
+
...defaultScriptInstallDir ? { defaultScriptInstallDir } : {},
|
|
102
|
+
...defaultScriptInstallDirEnv ? { defaultScriptInstallDirEnv } : {},
|
|
103
|
+
...scriptBinaryNames ? { scriptBinaryNames: Object.freeze(scriptBinaryNames) } : {},
|
|
104
|
+
...scriptFallbackUrls ? { scriptFallbackUrls: Object.freeze(scriptFallbackUrls) } : {},
|
|
105
|
+
...registryEnv ? { registryEnv } : {},
|
|
106
|
+
supportsRegistry: Boolean(registryEnv)
|
|
94
107
|
});
|
|
95
108
|
}
|
|
96
109
|
var OFFICIAL_TOOLS = Object.freeze([
|
|
@@ -107,8 +120,7 @@ var OFFICIAL_TOOLS = Object.freeze([
|
|
|
107
120
|
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",
|
|
108
121
|
providerHints: ["moonshot", "kimi"],
|
|
109
122
|
scriptBinaryNames: Object.freeze(["kimi", "kimi.exe"]),
|
|
110
|
-
|
|
111
|
-
defaultScriptInstallDir: ".kimi-code",
|
|
123
|
+
defaultScriptInstallDir: ".kimi-code/bin",
|
|
112
124
|
installMethods: Object.freeze([
|
|
113
125
|
packageManagerMethod("npm", "npm", "npm", "@moonshot-ai/kimi-code@latest"),
|
|
114
126
|
packageManagerMethod("pnpm", "pnpm", "pnpm", "@moonshot-ai/kimi-code@latest"),
|
|
@@ -116,25 +128,23 @@ var OFFICIAL_TOOLS = Object.freeze([
|
|
|
116
128
|
shell: "bash",
|
|
117
129
|
scriptUrl: "https://code.kimi.com/kimi-code/install.sh",
|
|
118
130
|
platforms: ["linux", "darwin"],
|
|
131
|
+
supportsInstallDir: true,
|
|
119
132
|
installDirEnv: "KIMI_INSTALL_DIR",
|
|
120
|
-
|
|
133
|
+
installDirSuffix: "bin",
|
|
121
134
|
env: ["KIMI_INSTALL_DIR"],
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
mustNotInclude: ["downloads.claude.ai/claude-code-releases", "@minimax-ai/code"]
|
|
125
|
-
})
|
|
135
|
+
scriptBinaryNames: ["kimi"],
|
|
136
|
+
verify: Object.freeze({ mustInclude: ["kimi-code", "code.kimi.com/kimi-code"] })
|
|
126
137
|
}),
|
|
127
138
|
scriptMethod("script-powershell", "irm | iex", {
|
|
128
139
|
shell: "powershell",
|
|
129
140
|
scriptUrl: "https://code.kimi.com/kimi-code/install.ps1",
|
|
130
141
|
platforms: ["win32"],
|
|
142
|
+
supportsInstallDir: true,
|
|
131
143
|
installDirEnv: "KIMI_INSTALL_DIR",
|
|
132
|
-
|
|
144
|
+
installDirSuffix: "bin",
|
|
133
145
|
env: ["KIMI_INSTALL_DIR"],
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
mustNotInclude: ["downloads.claude.ai/claude-code-releases", "@minimax-ai/code"]
|
|
137
|
-
})
|
|
146
|
+
scriptBinaryNames: ["kimi.exe"],
|
|
147
|
+
verify: Object.freeze({ mustInclude: ["kimi-code", "code.kimi.com/kimi-code"] })
|
|
138
148
|
})
|
|
139
149
|
])
|
|
140
150
|
}),
|
|
@@ -149,31 +159,30 @@ var OFFICIAL_TOOLS = Object.freeze([
|
|
|
149
159
|
uninstallArgs: ["uninstall", "-g", "@anthropic-ai/claude-code"],
|
|
150
160
|
probeExecutables: ["claude"],
|
|
151
161
|
providerHints: ["anthropic", "claude"],
|
|
152
|
-
// The native installer always lands in ~/.local/bin; it has no directory flag.
|
|
153
162
|
scriptBinaryNames: Object.freeze(["claude", "claude.exe"]),
|
|
154
163
|
defaultScriptInstallDir: ".local/bin",
|
|
155
164
|
installMethods: Object.freeze([
|
|
156
165
|
packageManagerMethod("npm", "npm", "npm", "@anthropic-ai/claude-code@latest"),
|
|
157
|
-
packageManagerMethod("pnpm", "pnpm", "pnpm", "@anthropic-ai/claude-code@latest"
|
|
166
|
+
packageManagerMethod("pnpm", "pnpm", "pnpm", "@anthropic-ai/claude-code@latest", {
|
|
167
|
+
command: "add",
|
|
168
|
+
extraArgs: ["--ignore-scripts=false", "--allow-build=@anthropic-ai/claude-code"]
|
|
169
|
+
}),
|
|
170
|
+
// The native installer has no directory argument. npm/pnpm support a prefix.
|
|
158
171
|
scriptMethod("script-bash", "curl | bash", {
|
|
159
172
|
shell: "bash",
|
|
160
173
|
scriptUrl: "https://claude.ai/install.sh",
|
|
174
|
+
scriptFallbackUrls: ["https://downloads.claude.ai/claude-code-releases/bootstrap.sh"],
|
|
161
175
|
platforms: ["linux", "darwin"],
|
|
162
|
-
|
|
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
|
-
})
|
|
176
|
+
scriptBinaryNames: ["claude"],
|
|
177
|
+
verify: Object.freeze({ mustInclude: ["downloads.claude.ai/claude-code-releases", "manifest.json"] })
|
|
167
178
|
}),
|
|
168
179
|
scriptMethod("script-powershell", "irm | iex", {
|
|
169
180
|
shell: "powershell",
|
|
170
181
|
scriptUrl: "https://claude.ai/install.ps1",
|
|
182
|
+
scriptFallbackUrls: ["https://downloads.claude.ai/claude-code-releases/bootstrap.ps1"],
|
|
171
183
|
platforms: ["win32"],
|
|
172
|
-
|
|
173
|
-
verify: Object.freeze({
|
|
174
|
-
mustInclude: ["downloads.claude.ai/claude-code-releases"],
|
|
175
|
-
mustNotInclude: ["@minimax-ai/code", "releases.openai.com/codex"]
|
|
176
|
-
})
|
|
184
|
+
scriptBinaryNames: ["claude.exe"],
|
|
185
|
+
verify: Object.freeze({ mustInclude: ["downloads.claude.ai/claude-code-releases", "manifest.json"] })
|
|
177
186
|
})
|
|
178
187
|
])
|
|
179
188
|
}),
|
|
@@ -190,33 +199,34 @@ var OFFICIAL_TOOLS = Object.freeze([
|
|
|
190
199
|
probeNote: "Codex \u7248\u672C\u6A2A\u5E45\u7531\u9002\u914D\u5C42\u5BBD\u5339\u914D\uFF1B\u5B89\u88C5\u65F6\u53D6 npm \u6700\u65B0\u7248\u3002",
|
|
191
200
|
providerHints: ["openai", "gpt", "codex"],
|
|
192
201
|
scriptBinaryNames: Object.freeze(["codex", "codex.exe"]),
|
|
202
|
+
defaultScriptInstallDir: ".local/bin",
|
|
193
203
|
installMethods: Object.freeze([
|
|
194
204
|
packageManagerMethod("npm", "npm", "npm", "@openai/codex@latest"),
|
|
195
205
|
packageManagerMethod("pnpm", "pnpm", "pnpm", "@openai/codex@latest"),
|
|
196
|
-
scriptMethod("script-
|
|
197
|
-
shell: "
|
|
206
|
+
scriptMethod("script-sh", "curl | sh", {
|
|
207
|
+
shell: "sh",
|
|
198
208
|
scriptUrl: "https://chatgpt.com/codex/install.sh",
|
|
199
209
|
platforms: ["linux", "darwin"],
|
|
210
|
+
supportsInstallDir: true,
|
|
200
211
|
installDirEnv: "CODEX_INSTALL_DIR",
|
|
201
|
-
defaultInstallDir: ".local/bin",
|
|
202
212
|
env: ["CODEX_INSTALL_DIR"],
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
mustNotInclude: ["downloads.claude.ai/claude-code-releases", "@minimax-ai/code"]
|
|
206
|
-
})
|
|
213
|
+
scriptBinaryNames: ["codex"],
|
|
214
|
+
verify: Object.freeze({ mustInclude: ["releases.openai.com/codex", "CODEX_INSTALL_DIR"] })
|
|
207
215
|
}),
|
|
208
216
|
scriptMethod("script-powershell", "irm | iex", {
|
|
209
217
|
shell: "powershell",
|
|
210
218
|
scriptUrl: "https://chatgpt.com/codex/install.ps1",
|
|
211
219
|
platforms: ["win32"],
|
|
220
|
+
supportsInstallDir: true,
|
|
212
221
|
installDirEnv: "CODEX_INSTALL_DIR",
|
|
213
|
-
// %LOCALAPPDATA%\Programs\OpenAI\Codex\bin under a normal user profile.
|
|
214
|
-
defaultInstallDir: "AppData/Local/Programs/OpenAI/Codex/bin",
|
|
215
222
|
env: ["CODEX_INSTALL_DIR"],
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
223
|
+
defaultScriptInstallDirEnv: "LOCALAPPDATA",
|
|
224
|
+
defaultScriptInstallDir: "Programs/OpenAI/Codex/bin",
|
|
225
|
+
installDirSubdir: "codex/bin",
|
|
226
|
+
uninstallUnsupportedReason: "Codex \u5B98\u65B9 Windows \u811A\u672C\u4F7F\u7528\u76EE\u5F55\u8054\u63A5\u548C\u7248\u672C\u5316\u8D44\u6E90\uFF1B\u8BF7\u6309\u5B98\u65B9\u5378\u8F7D\u8BF4\u660E\u79FB\u9664\uFF0C\u63D2\u4EF6\u4E0D\u4F1A\u5220\u9664\u8054\u63A5\u76EE\u6807\u3002",
|
|
227
|
+
// The Windows bin directory is a junction to the versioned payload.
|
|
228
|
+
scriptBinaryNames: ["codex.exe"],
|
|
229
|
+
verify: Object.freeze({ mustInclude: ["releases.openai.com/codex", "CODEX_INSTALL_DIR"] })
|
|
220
230
|
})
|
|
221
231
|
])
|
|
222
232
|
}),
|
|
@@ -231,50 +241,39 @@ var OFFICIAL_TOOLS = Object.freeze([
|
|
|
231
241
|
uninstallArgs: ["uninstall", "-g", "@minimax-ai/code"],
|
|
232
242
|
probeExecutables: ["mcode"],
|
|
233
243
|
providerHints: ["minimax"],
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
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",
|
|
244
|
+
defaultMethodsByPlatform: Object.freeze({ win32: "script-powershell" }),
|
|
245
|
+
scriptBinaryNames: Object.freeze(["mcode", "mcode-tools"]),
|
|
246
|
+
defaultScriptInstallDir: ".minimax-code/bin",
|
|
252
247
|
installMethods: Object.freeze([
|
|
253
|
-
packageManagerMethod("npm", "npm", "npm", "@minimax-ai/code@latest"
|
|
254
|
-
|
|
248
|
+
packageManagerMethod("npm", "npm", "npm", "@minimax-ai/code@latest", {
|
|
249
|
+
extraArgs: ["--ignore-scripts=false", "--include=optional", "--allow-scripts=@minimax-ai/code,better-sqlite3"]
|
|
250
|
+
}),
|
|
251
|
+
packageManagerMethod("pnpm", "pnpm", "pnpm", "@minimax-ai/code@latest", {
|
|
252
|
+
command: "add",
|
|
253
|
+
extraArgs: ["--ignore-scripts=false", "--allow-build=@minimax-ai/code", "--allow-build=better-sqlite3"]
|
|
254
|
+
}),
|
|
255
255
|
scriptMethod("script-bash", "curl | bash", {
|
|
256
256
|
shell: "bash",
|
|
257
257
|
scriptUrl: "https://filecdn.minimax.chat/public/install.sh",
|
|
258
258
|
platforms: ["linux", "darwin"],
|
|
259
|
+
supportsInstallDir: true,
|
|
259
260
|
installDirEnv: "MCODE_INSTALL_DIR",
|
|
260
|
-
|
|
261
|
+
installDirSuffix: "bin",
|
|
262
|
+
registryEnv: "MCODE_NPM_REGISTRY",
|
|
261
263
|
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
|
-
})
|
|
264
|
+
verify: Object.freeze({ mustInclude: ["MiniMax Code CLI", "@minimax-ai/code"] })
|
|
266
265
|
}),
|
|
267
266
|
scriptMethod("script-powershell", "irm | iex", {
|
|
268
267
|
shell: "powershell",
|
|
269
268
|
scriptUrl: "https://filecdn.minimax.chat/public/install.ps1",
|
|
270
269
|
platforms: ["win32"],
|
|
270
|
+
supportsInstallDir: true,
|
|
271
271
|
installDirEnv: "MCODE_INSTALL_DIR",
|
|
272
|
-
|
|
272
|
+
registryEnv: "MCODE_NPM_REGISTRY",
|
|
273
273
|
env: ["MCODE_INSTALL_DIR", "MCODE_NPM_REGISTRY"],
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
})
|
|
274
|
+
defaultScriptInstallDir: ".minimax-code",
|
|
275
|
+
scriptBinaryNames: ["mcode.cmd", "mcode.ps1", "mcode-tools.cmd", "mcode-tools.ps1"],
|
|
276
|
+
verify: Object.freeze({ mustInclude: ["MiniMax Code CLI", "@minimax-ai/code"] })
|
|
278
277
|
})
|
|
279
278
|
])
|
|
280
279
|
}),
|
|
@@ -294,28 +293,22 @@ var OFFICIAL_TOOLS = Object.freeze([
|
|
|
294
293
|
installMethods: Object.freeze([
|
|
295
294
|
packageManagerMethod("npm", "npm", "npm", "@mimo-ai/cli@latest"),
|
|
296
295
|
packageManagerMethod("pnpm", "pnpm", "pnpm", "@mimo-ai/cli@latest"),
|
|
297
|
-
// The Unix script hardcodes ~/.mimocode/bin and ignores MIMOCODE_INSTALL_DIR.
|
|
298
296
|
scriptMethod("script-bash", "curl | bash", {
|
|
299
297
|
shell: "bash",
|
|
300
298
|
scriptUrl: "https://mimo.xiaomi.com/install",
|
|
301
299
|
platforms: ["linux", "darwin"],
|
|
302
|
-
|
|
303
|
-
verify: Object.freeze({
|
|
304
|
-
mustInclude: ["MiMoCode", "mimo.xiaomi.com"],
|
|
305
|
-
mustNotInclude: ["@minimax-ai/code", "downloads.claude.ai/claude-code-releases"]
|
|
306
|
-
})
|
|
300
|
+
scriptBinaryNames: ["mimo"],
|
|
301
|
+
verify: Object.freeze({ mustInclude: ["mimo.xiaomi.com", ".mimocode"] })
|
|
307
302
|
}),
|
|
308
303
|
scriptMethod("script-powershell", "irm | iex", {
|
|
309
304
|
shell: "powershell",
|
|
310
305
|
scriptUrl: "https://mimo.xiaomi.com/install.ps1",
|
|
311
306
|
platforms: ["win32"],
|
|
307
|
+
supportsInstallDir: true,
|
|
312
308
|
installDirEnv: "MIMOCODE_INSTALL_DIR",
|
|
313
|
-
defaultInstallDir: ".mimocode/bin",
|
|
314
309
|
env: ["MIMOCODE_INSTALL_DIR"],
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
mustNotInclude: ["@minimax-ai/code", "downloads.claude.ai/claude-code-releases"]
|
|
318
|
-
})
|
|
310
|
+
scriptBinaryNames: ["mimo.exe"],
|
|
311
|
+
verify: Object.freeze({ mustInclude: ["mimo.xiaomi.com", ".mimocode"] })
|
|
319
312
|
})
|
|
320
313
|
])
|
|
321
314
|
}),
|
|
@@ -330,8 +323,9 @@ var OFFICIAL_TOOLS = Object.freeze([
|
|
|
330
323
|
uninstallArgs: ["uninstall", "-g", "@xai-official/grok"],
|
|
331
324
|
probeExecutables: ["grok"],
|
|
332
325
|
providerHints: ["xai", "grok"],
|
|
333
|
-
scriptBinaryNames: Object.freeze(["grok", "grok.exe", "agent", "
|
|
326
|
+
scriptBinaryNames: Object.freeze(["grok", "agent", "grok.exe", "agent.exe", "grove.exe", "grove-fsmonitor.exe", "grove-credential.exe"]),
|
|
334
327
|
defaultScriptInstallDir: ".grok/bin",
|
|
328
|
+
pathProfileMarkers: Object.freeze(["# >>> grok installer >>>", "# <<< grok installer <<<"]),
|
|
335
329
|
installMethods: Object.freeze([
|
|
336
330
|
packageManagerMethod("npm", "npm", "npm", "@xai-official/grok@latest"),
|
|
337
331
|
packageManagerMethod("pnpm", "pnpm", "pnpm", "@xai-official/grok@latest"),
|
|
@@ -339,25 +333,21 @@ var OFFICIAL_TOOLS = Object.freeze([
|
|
|
339
333
|
shell: "bash",
|
|
340
334
|
scriptUrl: "https://x.ai/cli/install.sh",
|
|
341
335
|
platforms: ["linux", "darwin"],
|
|
336
|
+
supportsInstallDir: true,
|
|
342
337
|
installDirEnv: "GROK_BIN_DIR",
|
|
343
|
-
defaultInstallDir: ".grok/bin",
|
|
344
338
|
env: ["GROK_BIN_DIR"],
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
mustNotInclude: ["@minimax-ai/code", "downloads.claude.ai/claude-code-releases"]
|
|
348
|
-
})
|
|
339
|
+
scriptBinaryNames: ["grok", "agent"],
|
|
340
|
+
verify: Object.freeze({ mustInclude: ["Grok CLI installer", "x.ai/cli"] })
|
|
349
341
|
}),
|
|
350
342
|
scriptMethod("script-powershell", "irm | iex", {
|
|
351
343
|
shell: "powershell",
|
|
352
344
|
scriptUrl: "https://x.ai/cli/install.ps1",
|
|
353
345
|
platforms: ["win32"],
|
|
346
|
+
supportsInstallDir: true,
|
|
354
347
|
installDirEnv: "GROK_BIN_DIR",
|
|
355
|
-
defaultInstallDir: ".grok/bin",
|
|
356
348
|
env: ["GROK_BIN_DIR"],
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
mustNotInclude: ["@minimax-ai/code", "downloads.claude.ai/claude-code-releases"]
|
|
360
|
-
})
|
|
349
|
+
scriptBinaryNames: ["grok.exe", "agent.exe", "grove.exe", "grove-fsmonitor.exe", "grove-credential.exe"],
|
|
350
|
+
verify: Object.freeze({ mustInclude: ["Grok CLI installer", "x.ai/cli"] })
|
|
361
351
|
})
|
|
362
352
|
])
|
|
363
353
|
}),
|
|
@@ -405,7 +395,9 @@ var OFFICIAL_TOOLS = Object.freeze([
|
|
|
405
395
|
shell: "bash",
|
|
406
396
|
scriptUrl: "https://opencode.ai/install",
|
|
407
397
|
platforms: ["linux", "darwin"],
|
|
408
|
-
|
|
398
|
+
// The published script hardcodes $HOME/.opencode/bin, so it cannot honour
|
|
399
|
+
// a custom install directory; the npm/pnpm methods above can.
|
|
400
|
+
supportsInstallDir: false,
|
|
409
401
|
verify: Object.freeze({
|
|
410
402
|
mustInclude: ["anomalyco/opencode", "opencode.ai"],
|
|
411
403
|
mustNotInclude: ["static-openapi.stepfun.com"]
|
|
@@ -435,7 +427,7 @@ var OFFICIAL_TOOLS = Object.freeze([
|
|
|
435
427
|
platforms: ["linux", "darwin"],
|
|
436
428
|
installArg: ["--install-dir"],
|
|
437
429
|
env: ["STEP_INSTALL_DIR", "STEP_RELEASE_BASE_URL"],
|
|
438
|
-
|
|
430
|
+
supportsInstallDir: true,
|
|
439
431
|
verify: Object.freeze({
|
|
440
432
|
mustInclude: ["static-openapi.stepfun.com", "stepcode installer"],
|
|
441
433
|
mustNotInclude: ["anomalyco/opencode"]
|
|
@@ -447,7 +439,7 @@ var OFFICIAL_TOOLS = Object.freeze([
|
|
|
447
439
|
platforms: ["win32"],
|
|
448
440
|
installArg: ["-InstallDir"],
|
|
449
441
|
env: ["STEP_INSTALL_DIR", "STEP_RELEASE_BASE_URL"],
|
|
450
|
-
|
|
442
|
+
supportsInstallDir: true,
|
|
451
443
|
verify: Object.freeze({
|
|
452
444
|
mustInclude: ["static-openapi.stepfun.com", "stepcode"],
|
|
453
445
|
mustNotInclude: ["anomalyco/opencode"]
|
|
@@ -486,7 +478,8 @@ function installMethodsFor(tool) {
|
|
|
486
478
|
function installMethodFor(tool, methodId) {
|
|
487
479
|
const wanted = String(methodId ?? "").trim();
|
|
488
480
|
if (!wanted) return null;
|
|
489
|
-
|
|
481
|
+
const canonical = tool?.id === "codex" && wanted === "script-bash" ? "script-sh" : wanted;
|
|
482
|
+
return installMethodsFor(tool).find((method) => method.id === canonical) ?? null;
|
|
490
483
|
}
|
|
491
484
|
function defaultInstallMethod(tool) {
|
|
492
485
|
return installMethodsFor(tool)[0] ?? null;
|
|
@@ -500,8 +493,8 @@ function installCommandLineFor(tool, method) {
|
|
|
500
493
|
if (!tool || tool.unsupported) return null;
|
|
501
494
|
if (!method) return null;
|
|
502
495
|
if (method.kind === "script") {
|
|
503
|
-
const piped = method.shell === "powershell" ? `irm ${method.scriptUrl} | iex` : `curl -fsSL ${method.scriptUrl} |
|
|
504
|
-
return
|
|
496
|
+
const piped = method.shell === "powershell" ? `irm ${method.scriptUrl} | iex` : `curl -fsSL ${method.scriptUrl} | ${method.shell}`;
|
|
497
|
+
return piped;
|
|
505
498
|
}
|
|
506
499
|
return `${method.manager} ${method.installArgs.join(" ")}`;
|
|
507
500
|
}
|
|
@@ -831,9 +824,9 @@ function keepKnownToolIds(raw, known, subject) {
|
|
|
831
824
|
}
|
|
832
825
|
return raw;
|
|
833
826
|
}
|
|
834
|
-
function parseInstallPreferences(config = {}, { tools = [] } = {}) {
|
|
827
|
+
function parseInstallPreferences(config = {}, { tools = [], home = "", env = {} } = {}) {
|
|
835
828
|
const known = new Set(tools.map((tool) => tool.id));
|
|
836
|
-
const installDir = expandInstallDir(valueOf(config, "toolInstallDir", ""));
|
|
829
|
+
const installDir = expandInstallDir(valueOf(config, "toolInstallDir", ""), { home, env });
|
|
837
830
|
const registry = normalizeSourceUrl(valueOf(config, "toolNpmRegistry", DEFAULT_NPM_REGISTRY), "npm \u6E90") || DEFAULT_NPM_REGISTRY;
|
|
838
831
|
const methodRaw = keepKnownToolIds(
|
|
839
832
|
parseJsonObject(valueOf(config, "toolInstallMethodsJson", "{}"), "\u5B89\u88C5\u65B9\u5F0F\u8986\u76D6"),
|
|
@@ -850,9 +843,11 @@ function parseInstallPreferences(config = {}, { tools = [] } = {}) {
|
|
|
850
843
|
for (const [id2, methodId] of Object.entries(methodRaw)) methods[id2] = methodId.trim();
|
|
851
844
|
for (const [id2, url] of Object.entries(scriptRaw)) scriptUrls[id2] = normalizeSourceUrl(url, `${id2} \u5B89\u88C5\u811A\u672C\u6E90`);
|
|
852
845
|
for (const [id2, methodId] of Object.entries(methods)) {
|
|
853
|
-
|
|
846
|
+
const selected = installMethodFor({ id: id2, installMethods: tools.find((tool) => tool.id === id2)?.installMethods }, methodId);
|
|
847
|
+
if (!selected) {
|
|
854
848
|
throw new Error(`${id2} \u4E0D\u652F\u6301\u5B89\u88C5\u65B9\u5F0F ${methodId}\u3002`);
|
|
855
849
|
}
|
|
850
|
+
methods[id2] = selected.id;
|
|
856
851
|
}
|
|
857
852
|
return {
|
|
858
853
|
installDir,
|
|
@@ -2347,6 +2342,23 @@ function compareReleaseVersions(left, right) {
|
|
|
2347
2342
|
}
|
|
2348
2343
|
|
|
2349
2344
|
// .dsh-plugin/client/tool-install-state.mjs
|
|
2345
|
+
var INSTALL_DEFAULTS = Object.freeze({
|
|
2346
|
+
toolInstallDir: "",
|
|
2347
|
+
toolNpmRegistry: DEFAULT_NPM_REGISTRY,
|
|
2348
|
+
toolScriptUrlsJson: "{}",
|
|
2349
|
+
toolAllowScriptInstall: true
|
|
2350
|
+
});
|
|
2351
|
+
function validateToolInstallSetting(key, value) {
|
|
2352
|
+
try {
|
|
2353
|
+
parseInstallPreferences({ [key]: value }, { tools: OFFICIAL_TOOLS });
|
|
2354
|
+
return "";
|
|
2355
|
+
} catch (error) {
|
|
2356
|
+
return error?.message || "\u5B89\u88C5\u8BBE\u7F6E\u65E0\u6548\u3002";
|
|
2357
|
+
}
|
|
2358
|
+
}
|
|
2359
|
+
function retainToolInstallDrafts(drafts, values = {}) {
|
|
2360
|
+
return Object.fromEntries(Object.entries(drafts).filter(([key, value]) => value !== (values[key] ?? INSTALL_DEFAULTS[key])));
|
|
2361
|
+
}
|
|
2350
2362
|
function toolInstallAction({ tool, probe, readiness, job, probeStatus, latestVersion = null }) {
|
|
2351
2363
|
const running = job?.status === "running";
|
|
2352
2364
|
const installed = probe?.installed === true;
|
|
@@ -2381,7 +2393,7 @@ function toolMaintenanceActions({ tool, probe, job, probeStatus, summary }) {
|
|
|
2381
2393
|
}
|
|
2382
2394
|
};
|
|
2383
2395
|
}
|
|
2384
|
-
function installClickRefusal({ tool, submitting = false, running = false, operation = "install" } = {}) {
|
|
2396
|
+
function installClickRefusal({ tool, submitting = false, running = false, operation = "install", pendingSettings = false, installError = "" } = {}) {
|
|
2385
2397
|
if (!tool) return "\u672A\u77E5\u5B98\u65B9\u5DE5\u5177\uFF0C\u65E0\u6CD5\u5F00\u59CB\u5B89\u88C5\u3002";
|
|
2386
2398
|
if (tool.unsupported) return String(tool.unsupportedReason ?? "").trim() || "\u6B64\u5DE5\u5177\u6682\u4E0D\u652F\u6301\u4E00\u952E\u5B89\u88C5\u3002";
|
|
2387
2399
|
if (tool.manager === "signed-windows-installer" && operation !== "install") {
|
|
@@ -2390,6 +2402,8 @@ function installClickRefusal({ tool, submitting = false, running = false, operat
|
|
|
2390
2402
|
if (submitting || running) {
|
|
2391
2403
|
return operation === "uninstall" ? "\u8BE5\u5DE5\u5177\u6B63\u5728\u5378\u8F7D\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u4EFB\u52A1\u7ED3\u675F\u3002" : operation === "repair" ? "\u8BE5\u5DE5\u5177\u6B63\u5728\u4FEE\u590D\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u4EFB\u52A1\u7ED3\u675F\u3002" : "\u8BE5\u5DE5\u5177\u6B63\u5728\u5B89\u88C5\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u4EFB\u52A1\u7ED3\u675F\u3002";
|
|
2392
2404
|
}
|
|
2405
|
+
if (pendingSettings) return "\u8BF7\u5148\u4FDD\u5B58\u6216\u653E\u5F03\u5B89\u88C5\u8BBE\u7F6E\u66F4\u6539\uFF0C\u5E76\u7B49\u5F85\u5B89\u88C5\u547D\u4EE4\u5237\u65B0\u3002";
|
|
2406
|
+
if (installError) return installError;
|
|
2393
2407
|
return "";
|
|
2394
2408
|
}
|
|
2395
2409
|
function payloadError(payload, fallback) {
|
|
@@ -3204,7 +3218,7 @@ function LaunchPreview({ value, changed, running, confirmRef, onConfirm, onCance
|
|
|
3204
3218
|
// .dsh-plugin/client/cli-terminal.jsx
|
|
3205
3219
|
var import_react4 = __toESM(require("react"), 1);
|
|
3206
3220
|
|
|
3207
|
-
// node_modules/@xterm/xterm/lib/xterm.mjs
|
|
3221
|
+
// node_modules/.pnpm/@xterm+xterm@6.0.0/node_modules/@xterm/xterm/lib/xterm.mjs
|
|
3208
3222
|
var zs = Object.defineProperty;
|
|
3209
3223
|
var Rl = Object.getOwnPropertyDescriptor;
|
|
3210
3224
|
var Ll = (s15, t) => {
|
|
@@ -12318,7 +12332,7 @@ var Dl = class extends D {
|
|
|
12318
12332
|
}
|
|
12319
12333
|
};
|
|
12320
12334
|
|
|
12321
|
-
// node_modules/@xterm/addon-fit/lib/addon-fit.mjs
|
|
12335
|
+
// node_modules/.pnpm/@xterm+addon-fit@0.11.0/node_modules/@xterm/addon-fit/lib/addon-fit.mjs
|
|
12322
12336
|
var h = 2;
|
|
12323
12337
|
var _ = 1;
|
|
12324
12338
|
var o = class {
|
|
@@ -12342,7 +12356,7 @@ var o = class {
|
|
|
12342
12356
|
}
|
|
12343
12357
|
};
|
|
12344
12358
|
|
|
12345
|
-
// node_modules/@xterm/xterm/css/xterm.css
|
|
12359
|
+
// node_modules/.pnpm/@xterm+xterm@6.0.0/node_modules/@xterm/xterm/css/xterm.css
|
|
12346
12360
|
var xterm_default = `/**
|
|
12347
12361
|
* Copyright (c) 2014 The xterm.js authors. All rights reserved.
|
|
12348
12362
|
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
|
|
@@ -12631,7 +12645,7 @@ var xterm_default = `/**
|
|
|
12631
12645
|
`;
|
|
12632
12646
|
|
|
12633
12647
|
// .dsh-plugin/client/host-version.mjs
|
|
12634
|
-
var ROUTER_CLIENT_VERSION = true ? "0.
|
|
12648
|
+
var ROUTER_CLIENT_VERSION = true ? "0.18.0" : "";
|
|
12635
12649
|
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";
|
|
12636
12650
|
function isMissingRemoteMethod(message) {
|
|
12637
12651
|
const value = String(message ?? "");
|
|
@@ -13223,14 +13237,15 @@ var router_main_default = `.mr-workspace {
|
|
|
13223
13237
|
.mr-tool-dot.running { background: #e9a640; }
|
|
13224
13238
|
.mr-tool-command { display: block; margin-top: 6px; padding: 4px 8px; font-size: 12px; background: var(--dsw-alias-markdown-code-block); border-radius: 6px; overflow-wrap: anywhere; }
|
|
13225
13239
|
.mr-tool-button { flex-shrink: 0; }
|
|
13226
|
-
.mr-tool-actions { display: flex; align-items: center; justify-content: flex-end; gap: 8px; flex-wrap: wrap; }
|
|
13240
|
+
.mr-tool-actions { display: flex; align-items: center; justify-content: flex-end; gap: 8px; flex-wrap: wrap; flex: 0 1 420px; }
|
|
13227
13241
|
.mr-tool-detail { margin: 7px 0 0; }
|
|
13228
13242
|
.mr-tool-error { margin: 8px 0 0; padding: 9px 11px; }
|
|
13229
13243
|
.mr-tool-log { margin-top: 7px; color: var(--mr-muted); font-size: 11px; }
|
|
13230
13244
|
.mr-tool-log summary { cursor: pointer; }
|
|
13231
13245
|
.mr-tool-log pre { max-height: 140px; overflow: auto; padding: 8px; border-radius: 7px; background: var(--dsw-alias-markdown-code-block); font-size: 10px; white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
13232
|
-
.mr-tool-methods { display: flex; align-items: center; gap: 6px;
|
|
13233
|
-
.mr-tool-methods label { display: flex; align-items: center; gap: 6px; color: var(--mr-muted); font-size: 11px; }
|
|
13246
|
+
.mr-tool-methods { display: flex; align-items: center; gap: 6px; width: 100%; }
|
|
13247
|
+
.mr-tool-methods label { display: flex; align-items: center; justify-content: flex-end; gap: 6px; width: 100%; color: var(--mr-muted); font-size: 11px; }
|
|
13248
|
+
.mr-tool-methods .mr-mini-select { min-width: 0; max-width: calc(100% - 54px); }
|
|
13234
13249
|
.mr-install-settings { margin-bottom: 14px; padding: 13px 14px; border: 1px solid var(--mr-line); border-radius: 11px; background: var(--mr-card); }
|
|
13235
13250
|
.mr-install-settings-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
|
|
13236
13251
|
.mr-install-grid { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
|
|
@@ -13239,6 +13254,7 @@ var router_main_default = `.mr-workspace {
|
|
|
13239
13254
|
.mr-install-field small { font-size: 11px; line-height: 1.6; }
|
|
13240
13255
|
.mr-install-error { color: #d95360; }
|
|
13241
13256
|
.mr-install-toggle-row { display: flex; align-items: center; gap: 7px; }
|
|
13257
|
+
.mr-install-save-row { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
|
|
13242
13258
|
.mr-channel-line { display: flex; align-items: center; gap: 8px; margin: 8px 0; flex-wrap: wrap; }
|
|
13243
13259
|
.mr-pill-channel-ok { border-color: var(--dsw-alias-success, #2f9e63); color: var(--dsw-alias-success, #2f9e63); }
|
|
13244
13260
|
.mr-pill-warn { border-color: var(--dsw-alias-warning, #c27c0e); color: var(--dsw-alias-warning, #c27c0e); }
|
|
@@ -13251,7 +13267,7 @@ var router_main_default = `.mr-workspace {
|
|
|
13251
13267
|
.mr-profile-advanced summary { cursor: pointer; }
|
|
13252
13268
|
.mr-profile-success { padding: 10px 12px; border-radius: 10px; background: #e5f5eb; color: #175f3a; font-size: 12px; }
|
|
13253
13269
|
@media (prefers-color-scheme: dark) { .mr-profile-success { background: #193b2b; color: #b4f1cc; } }
|
|
13254
|
-
@media (max-width: 560px) { .mr-tool { align-items: stretch; flex-direction: column; gap: 10px; } .mr-tool-button { align-self: flex-start; } }
|
|
13270
|
+
@media (max-width: 560px) { .mr-tool { align-items: stretch; flex-direction: column; gap: 10px; } .mr-tool-actions { flex-basis: auto; justify-content: flex-start; } .mr-tool-methods label { justify-content: flex-start; } .mr-tool-button { align-self: flex-start; } }
|
|
13255
13271
|
|
|
13256
13272
|
/* \u5F00\u7BB1\u4F53\u68C0\u3001\u6210\u672C\u63A7\u5236\u3001\u6267\u884C\u8BB0\u5F55\u3001\u5B89\u5168\u8FB9\u754C */
|
|
13257
13273
|
.mr-onboarding, .mr-cost { margin-bottom: 18px; }
|
|
@@ -13465,41 +13481,24 @@ var INSTALL_SETTING_FIELDS = [
|
|
|
13465
13481
|
label: "\u7EDF\u4E00\u5B89\u88C5\u76EE\u5F55",
|
|
13466
13482
|
fallback: "",
|
|
13467
13483
|
placeholder: "\u7559\u7A7A = \u5404\u5382\u5546\u9ED8\u8BA4\u76EE\u5F55",
|
|
13468
|
-
hint: "
|
|
13469
|
-
validate: () => null
|
|
13484
|
+
hint: "\u586B\u5199\u7EDD\u5BF9\u8DEF\u5F84\uFF0C\u4F8B\u5982 D:/AI/tools\u3002\u5404\u65B9\u5F0F\u7684\u5B9E\u9645\u76EE\u5F55\u4F1A\u663E\u793A\u5728\u5DE5\u5177\u547D\u4EE4\u65C1\uFF1B\u4E0D\u652F\u6301\u7EDF\u4E00\u76EE\u5F55\u7684\u65B9\u5F0F\u4F1A\u8BF4\u660E\u539F\u56E0\u3002"
|
|
13470
13485
|
},
|
|
13471
13486
|
{
|
|
13472
13487
|
key: "toolNpmRegistry",
|
|
13473
13488
|
label: "npm \u6E90\u5730\u5740",
|
|
13474
13489
|
fallback: "https://registry.npmjs.org/",
|
|
13475
13490
|
placeholder: "https://registry.npmjs.org/",
|
|
13476
|
-
hint: "\u5FC5\u987B\u4EE5 https:// \u5F00\u5934\u3002\
|
|
13477
|
-
validate: (raw) => /^https:\/\/\S+$/i.test(raw.trim()) ? null : "\u9700\u8981 https \u5F00\u5934\u7684\u5B8C\u6574\u5730\u5740\uFF0C\u4F8B\u5982 https://registry.npmmirror.com/"
|
|
13491
|
+
hint: "\u5FC5\u987B\u4EE5 https:// \u5F00\u5934\u3002\u6240\u6709 npm / pnpm \u65B9\u5F0F\u5171\u7528\u6B64\u4E0B\u8F7D\u6E90\uFF0C\u4F8B\u5982 https://registry.npmmirror.com/\u3002"
|
|
13478
13492
|
},
|
|
13479
13493
|
{
|
|
13480
13494
|
key: "toolScriptUrlsJson",
|
|
13481
13495
|
label: "\u5B89\u88C5\u811A\u672C\u6E90\u8986\u76D6\uFF08JSON\uFF0C\u53EF\u9009\uFF09",
|
|
13482
13496
|
fallback: "{}",
|
|
13483
13497
|
placeholder: '{ "stepcode": "https://mirror/stepcode/install.ps1" }',
|
|
13484
|
-
hint: "\u6309\u5DE5\u5177 ID \u6307\u5B9A\
|
|
13485
|
-
validate: (raw) => {
|
|
13486
|
-
if (!raw.trim()) return null;
|
|
13487
|
-
let parsed;
|
|
13488
|
-
try {
|
|
13489
|
-
parsed = JSON.parse(raw);
|
|
13490
|
-
} catch {
|
|
13491
|
-
return "JSON \u683C\u5F0F\u65E0\u6548\u3002";
|
|
13492
|
-
}
|
|
13493
|
-
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return "\u9700\u8981 JSON \u5BF9\u8C61\u3002";
|
|
13494
|
-
for (const [id2, url] of Object.entries(parsed)) {
|
|
13495
|
-
if (!OFFICIAL_TOOLS.some((tool) => tool.id === id2)) return `${id2} \u4E0D\u662F\u5B98\u65B9\u5DE5\u5177 ID\u3002`;
|
|
13496
|
-
if (typeof url !== "string" || !/^https:\/\/\S+$/i.test(url.trim())) return `${id2} \u7684\u5730\u5740\u5FC5\u987B\u662F https \u94FE\u63A5\u3002`;
|
|
13497
|
-
}
|
|
13498
|
-
return null;
|
|
13499
|
-
}
|
|
13498
|
+
hint: "\u6309\u5DE5\u5177 ID \u6307\u5B9A https \u955C\u50CF\u5730\u5740\u3002\u811A\u672C\u4E0B\u8F7D\u540E\u4ECD\u4F1A\u6838\u5BF9\u5382\u5546\u6807\u8BB0\uFF0C\u518D\u6267\u884C\u672C\u5730\u526F\u672C\u3002"
|
|
13500
13499
|
}
|
|
13501
13500
|
];
|
|
13502
|
-
function InstallSettings({ settingsScope, install }) {
|
|
13501
|
+
function InstallSettings({ settingsScope, install, onPendingChange }) {
|
|
13503
13502
|
const [snapshot, setSnapshot] = import_react5.default.useState(() => settingsScope?.getSnapshot?.() ?? { value: {}, writable: false });
|
|
13504
13503
|
const [drafts, setDrafts] = import_react5.default.useState({});
|
|
13505
13504
|
const [saving, setSaving] = import_react5.default.useState(false);
|
|
@@ -13507,36 +13506,48 @@ function InstallSettings({ settingsScope, install }) {
|
|
|
13507
13506
|
import_react5.default.useEffect(() => {
|
|
13508
13507
|
if (typeof settingsScope?.subscribe !== "function") return void 0;
|
|
13509
13508
|
const unsubscribe = settingsScope.subscribe(() => {
|
|
13510
|
-
|
|
13511
|
-
|
|
13509
|
+
const next = settingsScope.getSnapshot();
|
|
13510
|
+
setSnapshot(next);
|
|
13511
|
+
setDrafts((previous) => retainToolInstallDrafts(previous, next.value));
|
|
13512
13512
|
});
|
|
13513
13513
|
setSnapshot(settingsScope.getSnapshot());
|
|
13514
13514
|
return unsubscribe;
|
|
13515
13515
|
}, [settingsScope]);
|
|
13516
|
+
const dirty = Object.keys(drafts).length > 0;
|
|
13517
|
+
import_react5.default.useEffect(() => {
|
|
13518
|
+
onPendingChange?.(saving || dirty);
|
|
13519
|
+
}, [saving, dirty, onPendingChange]);
|
|
13516
13520
|
if (!settingsScope) return null;
|
|
13517
13521
|
const writable = snapshot.writable === true && !saving;
|
|
13518
13522
|
const shown = (field2) => drafts[field2.key] ?? String(snapshot.value?.[field2.key] ?? field2.fallback);
|
|
13519
|
-
const errors = Object.fromEntries(INSTALL_SETTING_FIELDS.map((field2) => [field2.key, field2.
|
|
13520
|
-
const
|
|
13523
|
+
const errors = Object.fromEntries(INSTALL_SETTING_FIELDS.map((field2) => [field2.key, validateToolInstallSetting(field2.key, shown(field2))]));
|
|
13524
|
+
const invalid = Object.values(errors).some(Boolean);
|
|
13525
|
+
const edit = (key, value) => {
|
|
13526
|
+
const next = retainToolInstallDrafts({ ...drafts, [key]: value }, snapshot.value);
|
|
13527
|
+
onPendingChange?.(saving || Object.keys(next).length > 0);
|
|
13528
|
+
setNotice("");
|
|
13529
|
+
setDrafts(next);
|
|
13530
|
+
};
|
|
13531
|
+
const apply2 = async () => {
|
|
13532
|
+
if (!writable || !dirty || invalid) return;
|
|
13521
13533
|
setSaving(true);
|
|
13534
|
+
onPendingChange?.(true);
|
|
13522
13535
|
setNotice("");
|
|
13523
13536
|
try {
|
|
13537
|
+
const entries = Object.entries(drafts).map(([key, value]) => ({ op: "set", path: [key], value }));
|
|
13524
13538
|
const accepted = await settingsScope.mutate(entries, snapshot.revision);
|
|
13525
13539
|
if (!accepted) throw new Error("\u8BBE\u7F6E\u672A\u88AB\u4FDD\u5B58\uFF0C\u53EF\u80FD\u88AB\u5176\u4ED6\u9875\u9762\u4FEE\u6539\uFF1B\u8F93\u5165\u5DF2\u4FDD\u7559\uFF0C\u8BF7\u91CD\u65B0\u6838\u5BF9\u3002");
|
|
13526
|
-
|
|
13540
|
+
const next = settingsScope.getSnapshot();
|
|
13541
|
+
setSnapshot(next);
|
|
13542
|
+
setDrafts((previous) => retainToolInstallDrafts(previous, next.value));
|
|
13543
|
+
setNotice("\u5B89\u88C5\u8BBE\u7F6E\u5DF2\u4FDD\u5B58\u3002");
|
|
13527
13544
|
} catch (error) {
|
|
13528
13545
|
setNotice(text5(error?.message) || "\u5B89\u88C5\u8BBE\u7F6E\u4FDD\u5B58\u5931\u8D25\u3002");
|
|
13529
13546
|
} finally {
|
|
13530
13547
|
setSaving(false);
|
|
13531
13548
|
}
|
|
13532
13549
|
};
|
|
13533
|
-
|
|
13534
|
-
const saved = String(snapshot.value?.[field2.key] ?? field2.fallback);
|
|
13535
|
-
const raw = shown(field2);
|
|
13536
|
-
if (raw === saved || errors[field2.key]) return;
|
|
13537
|
-
return apply2([{ op: "set", path: [field2.key], value: raw }], `\u5DF2\u4FDD\u5B58${field2.label}\uFF0C\u4E0B\u4E00\u6B21\u5B89\u88C5\u8D77\u751F\u6548\u3002`);
|
|
13538
|
-
};
|
|
13539
|
-
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-install-settings", "aria-label": "\u7EDF\u4E00\u5B89\u88C5\u8BBE\u7F6E" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-install-settings-head" }, /* @__PURE__ */ import_react5.default.createElement("strong", null, "\u7EDF\u4E00\u5B89\u88C5\u8BBE\u7F6E"), /* @__PURE__ */ import_react5.default.createElement("span", { className: "mr-caption" }, "\u5BF9\u6240\u6709\u5B98\u65B9\u5DE5\u5177\u751F\u6548\uFF0C\u6539\u52A8\u540E\u4E0B\u4E00\u6B21\u4E00\u952E\u5B89\u88C5\u3001\u4FEE\u590D\u6216\u5378\u8F7D\u7ACB\u5373\u4F7F\u7528\u3002\u63D2\u4EF6\u8BBE\u7F6E\u9875\u91CC\u6709\u540C\u6837\u7684\u5B57\u6BB5\u3002")), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-install-grid" }, INSTALL_SETTING_FIELDS.map((field2) => /* @__PURE__ */ import_react5.default.createElement("label", { className: "mr-install-field", key: field2.key }, /* @__PURE__ */ import_react5.default.createElement("span", null, field2.label), /* @__PURE__ */ import_react5.default.createElement(
|
|
13550
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-install-settings", "aria-label": "\u7EDF\u4E00\u5B89\u88C5\u8BBE\u7F6E" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-install-settings-head" }, /* @__PURE__ */ import_react5.default.createElement("strong", null, "\u7EDF\u4E00\u5B89\u88C5\u8BBE\u7F6E"), /* @__PURE__ */ import_react5.default.createElement("span", { className: "mr-caption" }, "\u4FDD\u5B58\u540E\u7528\u4E8E\u540E\u7EED\u5B89\u88C5\u4E0E\u66F4\u65B0\u3002\u6BCF\u4E2A\u5DE5\u5177\u4E0B\u65B9\u663E\u793A\u5B9E\u9645\u65B9\u5F0F\u548C\u76EE\u5F55\uFF0C\u63D2\u4EF6\u8BBE\u7F6E\u9875\u91CC\u4E5F\u80FD\u4FEE\u6539\u3002")), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-install-grid" }, INSTALL_SETTING_FIELDS.map((field2) => /* @__PURE__ */ import_react5.default.createElement("label", { className: "mr-install-field", key: field2.key }, /* @__PURE__ */ import_react5.default.createElement("span", null, field2.label), /* @__PURE__ */ import_react5.default.createElement(
|
|
13540
13551
|
"input",
|
|
13541
13552
|
{
|
|
13542
13553
|
className: "mr-input",
|
|
@@ -13544,37 +13555,47 @@ function InstallSettings({ settingsScope, install }) {
|
|
|
13544
13555
|
placeholder: field2.placeholder,
|
|
13545
13556
|
disabled: !writable,
|
|
13546
13557
|
"aria-invalid": Boolean(errors[field2.key]),
|
|
13547
|
-
onChange: (event) =>
|
|
13548
|
-
onBlur: () => {
|
|
13549
|
-
void commit(field2);
|
|
13550
|
-
}
|
|
13558
|
+
onChange: (event) => edit(field2.key, event.target.value)
|
|
13551
13559
|
}
|
|
13552
13560
|
), errors[field2.key] ? /* @__PURE__ */ import_react5.default.createElement("small", { className: "mr-install-error", role: "alert" }, errors[field2.key]) : /* @__PURE__ */ import_react5.default.createElement("small", null, field2.hint))), /* @__PURE__ */ import_react5.default.createElement("label", { className: "mr-install-field" }, /* @__PURE__ */ import_react5.default.createElement("span", null, "\u5B89\u88C5\u811A\u672C\u65B9\u5F0F"), /* @__PURE__ */ import_react5.default.createElement("span", { className: "mr-install-toggle-row" }, /* @__PURE__ */ import_react5.default.createElement(
|
|
13553
13561
|
"input",
|
|
13554
13562
|
{
|
|
13555
13563
|
type: "checkbox",
|
|
13556
|
-
checked: snapshot.value?.toolAllowScriptInstall !== false,
|
|
13564
|
+
checked: (drafts.toolAllowScriptInstall ?? snapshot.value?.toolAllowScriptInstall) !== false,
|
|
13557
13565
|
disabled: !writable,
|
|
13558
13566
|
onChange: (event) => {
|
|
13559
|
-
|
|
13560
|
-
void apply2(
|
|
13561
|
-
[{ op: "set", path: ["toolAllowScriptInstall"], value: allowed }],
|
|
13562
|
-
allowed ? "\u5DF2\u5141\u8BB8\u811A\u672C\u5B89\u88C5\u65B9\u5F0F\uFF08curl / irm\uFF09\u3002" : "\u5DF2\u5173\u95ED\u811A\u672C\u5B89\u88C5\u65B9\u5F0F\uFF0C\u53EA\u80FD\u4F7F\u7528 npm / pnpm\u3002"
|
|
13563
|
-
);
|
|
13567
|
+
edit("toolAllowScriptInstall", event.target.checked);
|
|
13564
13568
|
}
|
|
13565
13569
|
}
|
|
13566
|
-
), /* @__PURE__ */ import_react5.default.createElement("span", null, "\u5141\u8BB8 curl / irm \u5B89\u88C5\u811A\u672C")), /* @__PURE__ */ import_react5.default.createElement("small", null, "\u5173\u95ED\u540E\u53EA\u80FD\u4F7F\u7528 npm / pnpm \u65B9\u5F0F\uFF1B\u811A\u672C\u65B9\u5F0F\u9700\u8981\u5148\u4E0B\u8F7D\u5E76\u6821\u9A8C\u5382\u5546\u6807\u8BB0\u518D\u6267\u884C\u3002"))), /* @__PURE__ */ import_react5.default.createElement("
|
|
13570
|
+
), /* @__PURE__ */ import_react5.default.createElement("span", null, "\u5141\u8BB8 curl / irm \u5B89\u88C5\u811A\u672C")), /* @__PURE__ */ import_react5.default.createElement("small", null, "\u5173\u95ED\u540E\u53EA\u80FD\u4F7F\u7528 npm / pnpm \u65B9\u5F0F\uFF1B\u811A\u672C\u65B9\u5F0F\u9700\u8981\u5148\u4E0B\u8F7D\u5E76\u6821\u9A8C\u5382\u5546\u6807\u8BB0\u518D\u6267\u884C\u3002"))), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-install-save-row" }, /* @__PURE__ */ import_react5.default.createElement("button", { className: "mr-button mr-button-secondary", type: "button", disabled: !writable || !dirty || invalid, onClick: () => {
|
|
13571
|
+
void apply2();
|
|
13572
|
+
} }, saving ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58\u5B89\u88C5\u8BBE\u7F6E"), dirty && /* @__PURE__ */ import_react5.default.createElement("button", { className: "mr-button mr-button-secondary", type: "button", disabled: saving, onClick: () => {
|
|
13573
|
+
setDrafts({});
|
|
13574
|
+
setNotice("");
|
|
13575
|
+
onPendingChange?.(false);
|
|
13576
|
+
} }, "\u653E\u5F03\u66F4\u6539"), dirty && /* @__PURE__ */ import_react5.default.createElement("span", { className: "mr-caption" }, invalid ? "\u8BF7\u4FEE\u6B63\u8F93\u5165\u540E\u4FDD\u5B58\u3002" : "\u66F4\u6539\u5C1A\u672A\u4FDD\u5B58\uFF0C\u5B89\u88C5\u4E0E\u66F4\u65B0\u6682\u4E0D\u53EF\u7528\u3002")), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption", style: { marginTop: 8 }, role: notice ? "status" : void 0 }, "\u5F53\u524D\u751F\u6548\uFF1A\u5B89\u88C5\u76EE\u5F55 ", install?.installDir || "\uFF08\u5404\u5382\u5546\u9ED8\u8BA4\uFF09", " \xB7 npm \u6E90 ", install?.registry || "\uFF08\u9ED8\u8BA4\uFF09", notice ? ` \xB7 ${notice}` : ""));
|
|
13567
13577
|
}
|
|
13568
13578
|
function OfficialToolsCard({ listOfficialTools, installOfficialTool, uninstallOfficialTool, repairOfficialTool, cancelOfficialToolInstall, officialToolInstallStatus, onProbes, health, onRefreshHealth, settingsScope }) {
|
|
13569
13579
|
const healthById = Object.fromEntries((health?.tools ?? []).map((item) => [item.id, item]));
|
|
13570
13580
|
const [probeState, setProbeState] = import_react5.default.useState({ status: "loading", probes: [], capabilities: [], readiness: [], install: null, error: "" });
|
|
13571
13581
|
const [jobs, setJobs] = import_react5.default.useState({});
|
|
13572
13582
|
const [rowErrors, setRowErrors] = import_react5.default.useState({});
|
|
13583
|
+
const [settingsPending, setSettingsPending] = import_react5.default.useState(false);
|
|
13584
|
+
const [methodSaving, setMethodSaving] = import_react5.default.useState(null);
|
|
13585
|
+
const [previewPending, setPreviewPending] = import_react5.default.useState(false);
|
|
13586
|
+
const [settingsWritable, setSettingsWritable] = import_react5.default.useState(() => settingsScope?.getSnapshot?.()?.writable === true);
|
|
13587
|
+
const settingsPendingRef = import_react5.default.useRef(false);
|
|
13588
|
+
const methodSavingRef = import_react5.default.useRef(null);
|
|
13589
|
+
const previewPendingRef = import_react5.default.useRef(false);
|
|
13573
13590
|
const mounted = import_react5.default.useRef(false);
|
|
13574
13591
|
const request = import_react5.default.useRef(0);
|
|
13575
13592
|
const submitting = import_react5.default.useRef(/* @__PURE__ */ new Set());
|
|
13576
13593
|
const polling = import_react5.default.useRef(/* @__PURE__ */ new Set());
|
|
13577
13594
|
const jobsRef = import_react5.default.useRef({});
|
|
13595
|
+
const handleSettingsPending = import_react5.default.useCallback((value) => {
|
|
13596
|
+
settingsPendingRef.current = value;
|
|
13597
|
+
setSettingsPending(value);
|
|
13598
|
+
}, []);
|
|
13578
13599
|
const rememberJobs = (updater) => {
|
|
13579
13600
|
setJobs((previous) => {
|
|
13580
13601
|
const next = typeof updater === "function" ? updater(previous) : updater;
|
|
@@ -13599,6 +13620,8 @@ function OfficialToolsCard({ listOfficialTools, installOfficialTool, uninstallOf
|
|
|
13599
13620
|
const capabilities = Array.isArray(response.value?.executionCapabilities) ? response.value.executionCapabilities : [];
|
|
13600
13621
|
const readiness = Array.isArray(response.value?.executionReadiness) ? response.value.executionReadiness : [];
|
|
13601
13622
|
setProbeState({ status: "ready", probes, capabilities, readiness, install: response.value?.install ?? null, error: "" });
|
|
13623
|
+
previewPendingRef.current = false;
|
|
13624
|
+
setPreviewPending(false);
|
|
13602
13625
|
onProbes({ probes, capabilities, readiness, hostVersion: typeof response.value?.hostVersion === "string" ? response.value.hostVersion : null });
|
|
13603
13626
|
} catch (error) {
|
|
13604
13627
|
if (!mounted.current || current !== request.current) return;
|
|
@@ -13643,6 +13666,29 @@ function OfficialToolsCard({ listOfficialTools, installOfficialTool, uninstallOf
|
|
|
13643
13666
|
request.current += 1;
|
|
13644
13667
|
};
|
|
13645
13668
|
}, []);
|
|
13669
|
+
const refreshRef = import_react5.default.useRef(refresh);
|
|
13670
|
+
refreshRef.current = refresh;
|
|
13671
|
+
import_react5.default.useEffect(() => {
|
|
13672
|
+
if (typeof settingsScope?.subscribe !== "function") return void 0;
|
|
13673
|
+
const signature2 = (snapshot) => JSON.stringify([
|
|
13674
|
+
snapshot?.value?.toolInstallDir,
|
|
13675
|
+
snapshot?.value?.toolNpmRegistry,
|
|
13676
|
+
snapshot?.value?.toolInstallMethodsJson,
|
|
13677
|
+
snapshot?.value?.toolScriptUrlsJson,
|
|
13678
|
+
snapshot?.value?.toolAllowScriptInstall
|
|
13679
|
+
]);
|
|
13680
|
+
let previous = signature2(settingsScope.getSnapshot());
|
|
13681
|
+
return settingsScope.subscribe(() => {
|
|
13682
|
+
const snapshot = settingsScope.getSnapshot();
|
|
13683
|
+
setSettingsWritable(snapshot.writable === true);
|
|
13684
|
+
const next = signature2(snapshot);
|
|
13685
|
+
if (next === previous) return;
|
|
13686
|
+
previous = next;
|
|
13687
|
+
previewPendingRef.current = true;
|
|
13688
|
+
setPreviewPending(true);
|
|
13689
|
+
void refreshRef.current();
|
|
13690
|
+
});
|
|
13691
|
+
}, [settingsScope]);
|
|
13646
13692
|
import_react5.default.useEffect(() => {
|
|
13647
13693
|
const active = Object.values(jobs).filter((job) => job?.status === "running").map((job) => job.tool);
|
|
13648
13694
|
if (active.length === 0 || typeof officialToolInstallStatus !== "function") return void 0;
|
|
@@ -13683,18 +13729,24 @@ function OfficialToolsCard({ listOfficialTools, installOfficialTool, uninstallOf
|
|
|
13683
13729
|
}, [jobs, officialToolInstallStatus]);
|
|
13684
13730
|
const run = async (id2, operation) => {
|
|
13685
13731
|
const tool = OFFICIAL_TOOLS.find((item) => item.id === id2);
|
|
13732
|
+
const summary = (probeState.install?.tools ?? []).find((item) => item.id === id2);
|
|
13686
13733
|
const bridge = { install: installOfficialTool, repair: repairOfficialTool, uninstall: uninstallOfficialTool }[operation];
|
|
13687
13734
|
const refusal = installClickRefusal({
|
|
13688
13735
|
tool,
|
|
13689
13736
|
submitting: submitting.current.has(id2),
|
|
13690
13737
|
running: jobsRef.current[id2]?.status === "running",
|
|
13691
|
-
operation
|
|
13738
|
+
operation,
|
|
13739
|
+
pendingSettings: settingsPendingRef.current || Boolean(methodSavingRef.current) || previewPendingRef.current,
|
|
13740
|
+
installError: operation === "uninstall" ? summary?.uninstallError ?? (summary?.uninstallCommand ? "" : summary?.error ?? "") : summary?.installError ?? summary?.error ?? ""
|
|
13692
13741
|
});
|
|
13693
13742
|
if (refusal) {
|
|
13694
13743
|
setRowErrors((previous) => ({ ...previous, [id2]: refusal }));
|
|
13695
13744
|
return;
|
|
13696
13745
|
}
|
|
13697
|
-
if (typeof bridge !== "function")
|
|
13746
|
+
if (typeof bridge !== "function") {
|
|
13747
|
+
setRowErrors((previous) => ({ ...previous, [id2]: "\u5B98\u65B9\u5DE5\u5177\u5B89\u88C5\u6865\u5C1A\u672A\u52A0\u8F7D\u3002" }));
|
|
13748
|
+
return;
|
|
13749
|
+
}
|
|
13698
13750
|
submitting.current.add(id2);
|
|
13699
13751
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
13700
13752
|
setRowErrors((previous) => ({ ...previous, [id2]: "" }));
|
|
@@ -13731,7 +13783,10 @@ function OfficialToolsCard({ listOfficialTools, installOfficialTool, uninstallOf
|
|
|
13731
13783
|
const uninstall = (id2) => run(id2, "uninstall");
|
|
13732
13784
|
const setInstallMethod = async (toolId, methodId) => {
|
|
13733
13785
|
const snapshot = settingsScope?.getSnapshot?.();
|
|
13734
|
-
if (!snapshot) return;
|
|
13786
|
+
if (!snapshot?.writable || methodSavingRef.current || settingsPendingRef.current) return;
|
|
13787
|
+
methodSavingRef.current = toolId;
|
|
13788
|
+
setMethodSaving(toolId);
|
|
13789
|
+
setRowErrors((previous) => ({ ...previous, [toolId]: "" }));
|
|
13735
13790
|
let map = {};
|
|
13736
13791
|
try {
|
|
13737
13792
|
map = JSON.parse(String(snapshot.value?.toolInstallMethodsJson ?? "{}")) || {};
|
|
@@ -13744,9 +13799,14 @@ function OfficialToolsCard({ listOfficialTools, installOfficialTool, uninstallOf
|
|
|
13744
13799
|
try {
|
|
13745
13800
|
const accepted = await settingsScope.mutate([{ op: "set", path: ["toolInstallMethodsJson"], value: JSON.stringify(map) }], snapshot.revision);
|
|
13746
13801
|
if (!accepted) throw new Error("\u5B89\u88C5\u65B9\u5F0F\u672A\u88AB\u4FDD\u5B58\uFF0C\u53EF\u80FD\u88AB\u5176\u4ED6\u9875\u9762\u4FEE\u6539\u3002");
|
|
13747
|
-
|
|
13802
|
+
previewPendingRef.current = true;
|
|
13803
|
+
setPreviewPending(true);
|
|
13804
|
+
await refresh();
|
|
13748
13805
|
} catch (error) {
|
|
13749
13806
|
if (mounted.current) setRowErrors((previous) => ({ ...previous, [toolId]: text5(error?.message) || "\u5B89\u88C5\u65B9\u5F0F\u4FDD\u5B58\u5931\u8D25\u3002" }));
|
|
13807
|
+
} finally {
|
|
13808
|
+
methodSavingRef.current = null;
|
|
13809
|
+
if (mounted.current) setMethodSaving(null);
|
|
13750
13810
|
}
|
|
13751
13811
|
};
|
|
13752
13812
|
const cancel = async (id2) => {
|
|
@@ -13768,10 +13828,12 @@ function OfficialToolsCard({ listOfficialTools, installOfficialTool, uninstallOf
|
|
|
13768
13828
|
const installById = Object.fromEntries((probeState.install?.tools ?? []).map((item) => [item.id, item]));
|
|
13769
13829
|
return /* @__PURE__ */ import_react5.default.createElement("section", { className: "mr-card", "aria-label": "\u5B98\u65B9\u5DE5\u5177" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-card-head" }, /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("h2", { className: "mr-card-title" }, "\u5B98\u65B9\u5DE5\u5177 \xB7 \u4F53\u68C0"), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-card-copy" }, "\u68C0\u6D4B\u672C\u673A\u5B98\u65B9\u5DE5\u5177\u7684\u5B89\u88C5\u3001\u7248\u672C\u548C\u767B\u5F55\u72B6\u6001\uFF0C\u5E76\u4ECE\u56FA\u5B9A\u6CE8\u518C\u8868\u4E00\u952E\u5B89\u88C5\u6216\u66F4\u65B0\u5230\u5404\u5382\u5546\u6700\u65B0\u7248\uFF08\u65B0\u7248\u672C\u672A\u7ECF\u63D2\u4EF6\u6D4B\u8BD5\uFF09\u3002\u53EF\u6309\u5DE5\u5177\u9009\u62E9 npm\u3001pnpm \u6216\u5382\u5546\u5B89\u88C5\u811A\u672C\u65B9\u5F0F\uFF0C\u5E76\u7EDF\u4E00\u8BBE\u7F6E\u5B89\u88C5\u76EE\u5F55\u4E0E\u4E0B\u8F7D\u6E90\uFF1B\u5378\u8F7D\u53EA\u5220\u9664\u7A0B\u5E8F\uFF0C\u914D\u7F6E\u4E0E\u767B\u5F55\u4FDD\u7559\u3002\u672A\u767B\u5F55\u7684\u5DE5\u5177\u70B9\u201C\u53BB\u767B\u5F55\u201D\u67E5\u770B\u767B\u5F55\u547D\u4EE4\u3002ZCode \u4F1A\u6253\u5F00\u5B98\u65B9\u5B89\u88C5\u7A97\u53E3\u4F9B\u4F60\u9009\u62E9\u76EE\u5F55\uFF1B\u5B8C\u6210\u540E\u91CD\u65B0\u4F53\u68C0\u3002")), /* @__PURE__ */ import_react5.default.createElement("button", { className: "mr-button mr-button-secondary", type: "button", disabled: probeState.status === "loading", onClick: () => {
|
|
13770
13830
|
void refresh();
|
|
13771
|
-
} }, "\u91CD\u65B0\u4F53\u68C0")), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-card-body" }, /* @__PURE__ */ import_react5.default.createElement(InstallSettings, { settingsScope, install: probeState.install }), probeState.status === "loading" && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-empty", role: "status" }, "\u6B63\u5728\u68C0\u6D4B\u672C\u673A\u5B98\u65B9\u5DE5\u5177\u2026"), probeState.error && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-error", role: "alert" }, probeState.error), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-tools", role: "list", "aria-label": "\u5B98\u65B9\u5DE5\u5177\u6CE8\u518C\u8868" }, OFFICIAL_TOOLS.map((tool) => {
|
|
13831
|
+
} }, "\u91CD\u65B0\u4F53\u68C0")), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-card-body" }, /* @__PURE__ */ import_react5.default.createElement(InstallSettings, { settingsScope, install: probeState.install, onPendingChange: handleSettingsPending }), previewPending && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption", role: "status" }, "\u5B89\u88C5\u8BBE\u7F6E\u5DF2\u53D8\u66F4\uFF0C\u6B63\u5728\u5237\u65B0\u5B9E\u9645\u5B89\u88C5\u547D\u4EE4\uFF1B\u5237\u65B0\u5B8C\u6210\u540E\u53EF\u7EE7\u7EED\u5B89\u88C5\u4E0E\u66F4\u65B0\u3002"), probeState.status === "loading" && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-empty", role: "status" }, "\u6B63\u5728\u68C0\u6D4B\u672C\u673A\u5B98\u65B9\u5DE5\u5177\u2026"), probeState.error && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-error", role: "alert" }, probeState.error), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-tools", role: "list", "aria-label": "\u5B98\u65B9\u5DE5\u5177\u6CE8\u518C\u8868" }, OFFICIAL_TOOLS.map((tool) => {
|
|
13772
13832
|
const summary = installById[tool.id];
|
|
13773
|
-
const command = summary
|
|
13833
|
+
const command = summary ? summary.command : installCommandLine(tool);
|
|
13834
|
+
const updateCommand = summary?.updateCommand ?? command;
|
|
13774
13835
|
const methods = summary?.methods ?? installMethodsFor(tool).map((method) => ({ id: method.id, label: method.label }));
|
|
13836
|
+
const settingsBusy = settingsPending || Boolean(methodSaving) || previewPending;
|
|
13775
13837
|
const probe = byId[tool.id];
|
|
13776
13838
|
const capability = capabilitiesById[tool.id];
|
|
13777
13839
|
const readiness = readinessById[tool.id];
|
|
@@ -13783,32 +13845,36 @@ function OfficialToolsCard({ listOfficialTools, installOfficialTool, uninstallOf
|
|
|
13783
13845
|
probe,
|
|
13784
13846
|
job,
|
|
13785
13847
|
probeStatus: probeState.status,
|
|
13786
|
-
summary: {
|
|
13848
|
+
summary: {
|
|
13849
|
+
installable: !(summary?.installError ?? summary?.error),
|
|
13850
|
+
removable: !(summary?.uninstallError ?? (summary?.uninstallCommand ? "" : summary?.error))
|
|
13851
|
+
}
|
|
13787
13852
|
});
|
|
13788
13853
|
const verified = job?.status === "succeeded" && (job.operation === "uninstall" ? job.postInstallProbe?.installed === false : job.postInstallProbe?.installed === true);
|
|
13789
13854
|
const operation = job?.operation === "uninstall" ? "\u5378\u8F7D" : job?.operation === "repair" ? "\u4FEE\u590D" : "\u5B89\u88C5";
|
|
13790
13855
|
const status = running ? job.cancelRequested ? `\u6B63\u5728\u53D6\u6D88${operation}\u2026` : `${operation}\u4E2D\u2026` : job?.status === "installer-opened" ? "\u5B98\u65B9\u5B89\u88C5\u5668\u5DF2\u6253\u5F00\uFF0C\u8BF7\u5B8C\u6210\u5B89\u88C5\u540E\u91CD\u65B0\u68C0\u6D4B" : job?.status === "cancelled" ? `${operation}\u5DF2\u53D6\u6D88\uFF0C\u8BF7\u91CD\u65B0\u68C0\u6D4B` : verified ? `${operation}\u6210\u529F\u5E76\u9A8C\u8BC1` : probeLabel(probe);
|
|
13791
|
-
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-tool", role: "listitem", key: tool.id }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-tool-info" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-route-name", title: tool.purpose }, tool.label), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-route-provider" }, tool.vendor, " \xB7 ", tool.id), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-tool-status", role: "status" }, /* @__PURE__ */ import_react5.default.createElement("span", { className: `mr-tool-dot ${running ? "running" : probe?.installed ? "installed" : "missing"}` }), status, probe?.installed && probe.version ? ` \xB7 ${probe.version}` : "", healthById[tool.id]?.latestVersion ? ` \xB7 \u6700\u65B0 ${healthById[tool.id].latestVersion}` : ""), /* @__PURE__ */ import_react5.default.createElement(ToolLoginLine, { entry: healthById[tool.id] }), probe?.installed && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption mr-tool-detail" }, tool.headlessAdapter ? "\u5DF2\u53EF\u7531 model_router_execute \u4EE5\u65E0\u754C\u9762\u65B9\u5F0F\u8C03\u7528\u3002\u547D\u4EE4\u7F3A\u5931\u6216\u5931\u8D25\u65F6\u56DE\u9000\u6A21\u578B\u76EE\u5F55 API\u3002\u7B7E\u540D\u6C99\u7BB1\u5165\u53E3\u4E0D\u542F\u52A8\u6B64 CLI\u3002" : readiness?.ready ? `\u5B98\u65B9\u6267\u884C\u5165\u53E3\u5DF2\u6838\u9A8C\uFF0C\u53EF\u5728\u4F1A\u8BDD\u4E2D\u8C03\u7528 model_router_tool_run\uFF1B${capability?.modes?.includes("read-only") ? "\u652F\u6301\u53EA\u8BFB\u548C\u7ECF\u5BA1\u6279\u7684\u53EF\u7F16\u8F91\u4EFB\u52A1" : "\u4EC5\u652F\u6301\u7ECF\u5BA1\u6279\u7684\u53EF\u7F16\u8F91\u9694\u79BB\u5DE5\u4F5C\u533A\u4EFB\u52A1"}\uFF0C\u8D26\u53F7\u53CA\u6A21\u578B\u4ECD\u9700\u5B9E\u6D4B\u3002` : `\u5DF2\u5B89\u88C5\uFF0C\u4F46\u5F53\u524D\u4E0D\u53EF\u6258\u7BA1\u6267\u884C\uFF1A${readiness?.reason || capability?.reason || "\u6267\u884C\u5165\u53E3\u5C1A\u672A\u6838\u9A8C\u3002"}`), command ? /* @__PURE__ */ import_react5.default.createElement("code", { className: "mr-tool-command" }, command) : /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption", style: { margin: "6px 0 0" } }, summary?.error ?? tool.unsupportedReason), (summary?.notices ?? []).map((notice) => /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption mr-tool-detail", key: notice }, notice)), probe?.detail && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption mr-tool-detail" }, probe.detail), (rowErrors[tool.id] || job?.error) && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-error mr-tool-error", role: "alert" }, rowErrors[tool.id] || job.error), Array.isArray(job?.outputTail) && job.outputTail.length > 0 && /* @__PURE__ */ import_react5.default.createElement("details", { className: "mr-tool-log" }, /* @__PURE__ */ import_react5.default.createElement("summary", null, "\u5B89\u88C5\u65E5\u5FD7"), /* @__PURE__ */ import_react5.default.createElement("pre", null, job.outputTail.slice(-6).join("\n")))), command && /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-tool-actions" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-tool-methods" }, /* @__PURE__ */ import_react5.default.createElement("label", null, /* @__PURE__ */ import_react5.default.createElement("span", null, "\u5B89\u88C5\u65B9\u5F0F"), /* @__PURE__ */ import_react5.default.createElement(
|
|
13856
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-tool", role: "listitem", key: tool.id }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-tool-info" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-route-name", title: tool.purpose }, tool.label), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-route-provider" }, tool.vendor, " \xB7 ", tool.id), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-tool-status", role: "status" }, /* @__PURE__ */ import_react5.default.createElement("span", { className: `mr-tool-dot ${running ? "running" : probe?.installed ? "installed" : "missing"}` }), status, probe?.installed && probe.version ? ` \xB7 ${probe.version}` : "", healthById[tool.id]?.latestVersion ? ` \xB7 \u6700\u65B0 ${healthById[tool.id].latestVersion}` : ""), /* @__PURE__ */ import_react5.default.createElement(ToolLoginLine, { entry: healthById[tool.id] }), probe?.installed && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption mr-tool-detail" }, tool.headlessAdapter ? "\u5DF2\u53EF\u7531 model_router_execute \u4EE5\u65E0\u754C\u9762\u65B9\u5F0F\u8C03\u7528\u3002\u547D\u4EE4\u7F3A\u5931\u6216\u5931\u8D25\u65F6\u56DE\u9000\u6A21\u578B\u76EE\u5F55 API\u3002\u7B7E\u540D\u6C99\u7BB1\u5165\u53E3\u4E0D\u542F\u52A8\u6B64 CLI\u3002" : readiness?.ready ? `\u5B98\u65B9\u6267\u884C\u5165\u53E3\u5DF2\u6838\u9A8C\uFF0C\u53EF\u5728\u4F1A\u8BDD\u4E2D\u8C03\u7528 model_router_tool_run\uFF1B${capability?.modes?.includes("read-only") ? "\u652F\u6301\u53EA\u8BFB\u548C\u7ECF\u5BA1\u6279\u7684\u53EF\u7F16\u8F91\u4EFB\u52A1" : "\u4EC5\u652F\u6301\u7ECF\u5BA1\u6279\u7684\u53EF\u7F16\u8F91\u9694\u79BB\u5DE5\u4F5C\u533A\u4EFB\u52A1"}\uFF0C\u8D26\u53F7\u53CA\u6A21\u578B\u4ECD\u9700\u5B9E\u6D4B\u3002` : `\u5DF2\u5B89\u88C5\uFF0C\u4F46\u5F53\u524D\u4E0D\u53EF\u6258\u7BA1\u6267\u884C\uFF1A${readiness?.reason || capability?.reason || "\u6267\u884C\u5165\u53E3\u5C1A\u672A\u6838\u9A8C\u3002"}`), command ? /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption mr-tool-detail" }, "\u5B89\u88C5\u65B9\u5F0F\uFF1A", methods.find((method) => method.id === summary?.methodId)?.label ?? tool.manager, " \xB7 \u5B9E\u9645\u5B89\u88C5\u76EE\u5F55\uFF1A", summary?.installDir || "\u5404\u5382\u5546\u9ED8\u8BA4\u76EE\u5F55"), /* @__PURE__ */ import_react5.default.createElement("code", { className: "mr-tool-command", "aria-label": `${tool.label} \u5B89\u88C5\u547D\u4EE4` }, command), updateCommand !== command && /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption mr-tool-detail" }, "\u66F4\u65B0\u6CBF\u7528\u539F\u5B89\u88C5\u4F4D\u7F6E\uFF1A", summary?.updateInstallDir || "\u5404\u5382\u5546\u9ED8\u8BA4\u76EE\u5F55"), /* @__PURE__ */ import_react5.default.createElement("code", { className: "mr-tool-command", "aria-label": `${tool.label} \u66F4\u65B0\u547D\u4EE4` }, updateCommand))) : /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption", style: { margin: "6px 0 0" } }, summary?.error ?? tool.unsupportedReason), (summary?.notices ?? []).map((notice) => /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption mr-tool-detail", key: notice }, notice)), probe?.detail && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption mr-tool-detail" }, probe.detail), (rowErrors[tool.id] || job?.error) && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-error mr-tool-error", role: "alert" }, rowErrors[tool.id] || job.error), Array.isArray(job?.outputTail) && job.outputTail.length > 0 && /* @__PURE__ */ import_react5.default.createElement("details", { className: "mr-tool-log" }, /* @__PURE__ */ import_react5.default.createElement("summary", null, "\u5B89\u88C5\u65E5\u5FD7"), /* @__PURE__ */ import_react5.default.createElement("pre", null, job.outputTail.slice(-6).join("\n")))), (command || methods.length > 0) && /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-tool-actions" }, methods.length > 0 && /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-tool-methods" }, /* @__PURE__ */ import_react5.default.createElement("label", null, /* @__PURE__ */ import_react5.default.createElement("span", null, "\u5B89\u88C5\u65B9\u5F0F"), /* @__PURE__ */ import_react5.default.createElement(
|
|
13792
13857
|
"select",
|
|
13793
13858
|
{
|
|
13794
13859
|
className: "mr-mini-select",
|
|
13795
|
-
value: summary?.savedMethodId ??
|
|
13796
|
-
disabled: running ||
|
|
13860
|
+
value: summary?.savedMethodId ?? "",
|
|
13861
|
+
disabled: running || settingsBusy || !settingsWritable,
|
|
13797
13862
|
onChange: (event) => {
|
|
13798
13863
|
void setInstallMethod(tool.id, event.target.value);
|
|
13799
13864
|
}
|
|
13800
13865
|
},
|
|
13866
|
+
/* @__PURE__ */ import_react5.default.createElement("option", { value: "" }, "\u81EA\u52A8\u9009\u62E9"),
|
|
13801
13867
|
methods.map((method) => /* @__PURE__ */ import_react5.default.createElement("option", { key: method.id, value: method.id, disabled: Boolean(method.blocked) }, method.label, method.blocked ? `\uFF08${method.blocked}\uFF09` : ""))
|
|
13802
|
-
))), /* @__PURE__ */ import_react5.default.createElement("button", { className: "mr-button mr-tool-button", type: "button", disabled: action.disabled, onClick: () => {
|
|
13868
|
+
))), /* @__PURE__ */ import_react5.default.createElement("button", { className: "mr-button mr-tool-button", type: "button", disabled: action.disabled || settingsBusy || !command || Boolean(summary?.error), title: summary?.error || (settingsBusy ? "\u8BF7\u5148\u4FDD\u5B58\u6216\u653E\u5F03\u5B89\u88C5\u8BBE\u7F6E\u66F4\u6539\uFF0C\u5E76\u7B49\u5F85\u547D\u4EE4\u5237\u65B0\u3002" : void 0), onClick: () => {
|
|
13803
13869
|
void install(tool.id);
|
|
13804
|
-
} }, action.label), /* @__PURE__ */ import_react5.default.createElement("button", { className: "mr-button mr-button-secondary mr-tool-button", type: "button", disabled: maintenance.repair.disabled, title: maintenance.repair.title, onClick: () => {
|
|
13870
|
+
} }, methodSaving === tool.id ? "\u4FDD\u5B58\u65B9\u5F0F\u4E2D\u2026" : action.label), /* @__PURE__ */ import_react5.default.createElement("button", { className: "mr-button mr-button-secondary mr-tool-button", type: "button", disabled: maintenance.repair.disabled || settingsBusy, title: maintenance.repair.title, onClick: () => {
|
|
13805
13871
|
void repair(tool.id);
|
|
13806
|
-
} }, maintenance.repair.label), /* @__PURE__ */ import_react5.default.createElement("button", { className: "mr-button mr-button-secondary mr-tool-button", type: "button", disabled: maintenance.uninstall.disabled, title: maintenance.uninstall.title, onClick: () => {
|
|
13872
|
+
} }, maintenance.repair.label), /* @__PURE__ */ import_react5.default.createElement("button", { className: "mr-button mr-button-secondary mr-tool-button", type: "button", disabled: maintenance.uninstall.disabled || settingsBusy, title: maintenance.uninstall.title, onClick: () => {
|
|
13807
13873
|
void uninstall(tool.id);
|
|
13808
13874
|
} }, maintenance.uninstall.label), running && /* @__PURE__ */ import_react5.default.createElement("button", { className: "mr-button mr-button-secondary mr-tool-button", type: "button", disabled: job.cancelRequested, onClick: () => {
|
|
13809
13875
|
void cancel(tool.id);
|
|
13810
13876
|
} }, job.cancelRequested ? "\u6B63\u5728\u53D6\u6D88\u2026" : `\u53D6\u6D88${operation}`)));
|
|
13811
|
-
})), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption", style: { marginTop: 12 } }, "\u5B89\u88C5\
|
|
13877
|
+
})), /* @__PURE__ */ import_react5.default.createElement("p", { className: "mr-caption", style: { marginTop: 12 } }, "\u5B89\u88C5\u76EE\u5F55\u4E0E\u4E0B\u8F7D\u6E90\u4F7F\u7528\u5DF2\u4FDD\u5B58\u8BBE\u7F6E\uFF0C\u547D\u4EE4\u4E0A\u65B9\u663E\u793A\u5B9E\u9645\u6267\u884C\u65B9\u5F0F\u3002\u53EF\u70B9\u201C\u53D6\u6D88\u201D\u7EC8\u6B62\u4E0B\u8F7D\u4EFB\u52A1\uFF0C\u968F\u540E\u91CD\u65B0\u68C0\u6D4B\u7248\u672C\u3002\u5378\u8F7D\u4FDD\u7559\u914D\u7F6E\u3001\u767B\u5F55\u4FE1\u606F\u548C\u5386\u53F2\u8BB0\u5F55\uFF1B\u811A\u672C\u65B9\u5F0F\u53EA\u79FB\u9664\u767B\u8BB0\u7684\u547D\u4EE4\u5165\u53E3\uFF0C\u53EF\u80FD\u4FDD\u7559\u5382\u5546\u7248\u672C\u76EE\u5F55\u3002\u4E0D\u652F\u6301\u5B89\u5168\u5378\u8F7D\u7684\u65B9\u5F0F\u4F1A\u8BF4\u660E\u539F\u56E0\u3002ZCode \u9700\u5728\u5B98\u65B9\u5B89\u88C5\u7A97\u53E3\u5B8C\u6210\u5B89\u88C5\u3002\u4F1A\u8BDD\u4E0E Agent \u4E5F\u53EF\u4F7F\u7528 ", /* @__PURE__ */ import_react5.default.createElement("code", null, "/tools"), "\u3001", /* @__PURE__ */ import_react5.default.createElement("code", null, "model_router_tool_install"), "\u3001", /* @__PURE__ */ import_react5.default.createElement("code", null, "model_router_tool_repair"), " \u548C ", /* @__PURE__ */ import_react5.default.createElement("code", null, "model_router_tool_uninstall"), "\u3002")));
|
|
13812
13878
|
}
|
|
13813
13879
|
var HEADLESS_TOOLS = /* @__PURE__ */ new Set(["claude-code", "codex", "gemini"]);
|
|
13814
13880
|
var WORKSPACE_VIEWS = [
|
|
@@ -14670,12 +14736,12 @@ function RouterSettingsCard(props) {
|
|
|
14670
14736
|
), state.quotaPatternsJson.invalid && /* @__PURE__ */ import_react6.default.createElement("p", { style: styles.profileError, role: "alert" }, "\u9700\u8981 JSON \u5BF9\u8C61\uFF0C\u4E14\u6BCF\u6761\u89C4\u5219\u90FD\u662F\u6709\u6548\u7684\u6B63\u5219\u8868\u8FBE\u5F0F\u3002"), /* @__PURE__ */ import_react6.default.createElement("details", { style: styles.profileExample }, /* @__PURE__ */ import_react6.default.createElement("summary", null, "\u67E5\u770B\u89C4\u5219\u683C\u5F0F"), /* @__PURE__ */ import_react6.default.createElement("pre", null, `{
|
|
14671
14737
|
"kimi-code": { "quota": ["\u989D\u5EA6\u5DF2\u7528\u5B8C"], "rateLimit": ["\u8BF7\u6C42\u8FC7\u4E8E\u9891\u7E41"] },
|
|
14672
14738
|
"my-glm-plan": { "quota": ["Usage limit reached for", "1308"] }
|
|
14673
|
-
}`)), /* @__PURE__ */ import_react6.default.createElement("button", { type: "button", disabled, onClick: () => props.resetField("quotaPatternsJson") }, "\u6062\u590D\u9ED8\u8BA4\u89C4\u5219")), /* @__PURE__ */ import_react6.default.createElement("div", { style: styles.profileEditor }, /* @__PURE__ */ import_react6.default.createElement("span", { style: styles.profileLabel }, "\u5B98\u65B9\u5DE5\u5177\u7EDF\u4E00\u5B89\u88C5\u8BBE\u7F6E"), /* @__PURE__ */ import_react6.default.createElement("p", { style: styles.noticeText }, "\
|
|
14739
|
+
}`)), /* @__PURE__ */ import_react6.default.createElement("button", { type: "button", disabled, onClick: () => props.resetField("quotaPatternsJson") }, "\u6062\u590D\u9ED8\u8BA4\u89C4\u5219")), /* @__PURE__ */ import_react6.default.createElement("div", { style: styles.profileEditor }, /* @__PURE__ */ import_react6.default.createElement("span", { style: styles.profileLabel }, "\u5B98\u65B9\u5DE5\u5177\u7EDF\u4E00\u5B89\u88C5\u8BBE\u7F6E"), /* @__PURE__ */ import_react6.default.createElement("p", { style: styles.noticeText }, "\u7528\u4E8E\u5B98\u65B9\u5DE5\u5177\u7684\u5B89\u88C5\u4E0E\u66F4\u65B0\u3002\u5DE5\u4F5C\u53F0\u7684\u201C\u5B98\u65B9\u5DE5\u5177\u201D\u9875\u4E5F\u80FD\u4FDD\u5B58\u540C\u6837\u7684\u5B57\u6BB5\uFF0C\u5E76\u4F1A\u663E\u793A\u6BCF\u4E2A\u5DE5\u5177\u7684\u5B9E\u9645\u5B89\u88C5\u65B9\u5F0F\u3001\u76EE\u5F55\u4E0E\u6267\u884C\u547D\u4EE4\u3002 \u5B89\u88C5\u547D\u4EE4\u59CB\u7EC8\u6765\u81EA\u56FA\u5B9A\u6CE8\u518C\u8868\uFF0C\u8FD9\u91CC\u53EA\u51B3\u5B9A\u76EE\u5F55\u4E0E\u4E0B\u8F7D\u6E90\uFF0C\u4E0D\u63A5\u53D7\u81EA\u5B9A\u4E49\u5305\u540D\u6216\u4EFB\u610F\u5730\u5740\u3002"), /* @__PURE__ */ import_react6.default.createElement(
|
|
14674
14740
|
import_dsh_client_ui_primitives.SettingsValueField,
|
|
14675
14741
|
{
|
|
14676
14742
|
id: "model-router-tool-install-dir",
|
|
14677
14743
|
label: "\u7EDF\u4E00\u5B89\u88C5\u76EE\u5F55",
|
|
14678
|
-
hint: "\u7559\u7A7A\
|
|
14744
|
+
hint: "\u586B\u5199\u7EDD\u5BF9\u8DEF\u5F84\uFF0C\u7559\u7A7A\u4F7F\u7528\u5382\u5546\u9ED8\u8BA4\u4F4D\u7F6E\u3002npm / pnpm \u4F7F\u7528\u8BE5\u76EE\u5F55\u5B89\u88C5\uFF1B\u5382\u5546\u811A\u672C\u4E0D\u652F\u6301\u81EA\u5B9A\u4E49\u76EE\u5F55\u65F6\uFF0C\u5B98\u65B9\u5DE5\u5177\u9875\u4F1A\u663E\u793A\u5B9E\u9645\u76EE\u5F55\u4E0E\u539F\u56E0\u3002\u66F4\u65B0\u4F7F\u7528\u540C\u4E00\u5B89\u88C5\u65B9\u5F0F\u3001\u76EE\u5F55\u4E0E\u4E0B\u8F7D\u6E90\u3002",
|
|
14679
14745
|
disabled,
|
|
14680
14746
|
...state.toolInstallDir,
|
|
14681
14747
|
overriddenLabel: FIELD_COPY.overridden,
|
|
@@ -14711,7 +14777,7 @@ function RouterSettingsCard(props) {
|
|
|
14711
14777
|
{
|
|
14712
14778
|
id: "model-router-tool-install-methods",
|
|
14713
14779
|
label: "\u9ED8\u8BA4\u5B89\u88C5\u65B9\u5F0F\uFF08JSON\uFF0C\u53EF\u9009\uFF09",
|
|
14714
|
-
hint: "\u6309\u5DE5\u5177 ID \u56FA\u5B9A\u4E00\u79CD\u5B89\u88C5\u65B9\u5F0F\uFF0C\u4F8B\u5982\u56FA\u5B9A Step Code \u5728 Windows \u4E0A\u7528 irm | iex\u3002\u7559\u7A7A\
|
|
14780
|
+
hint: "\u6309\u5DE5\u5177 ID \u56FA\u5B9A\u4E00\u79CD\u5B89\u88C5\u65B9\u5F0F\uFF0C\u4F8B\u5982\u56FA\u5B9A Step Code \u5728 Windows \u4E0A\u7528 irm | iex\u3002\u7559\u7A7A\u81EA\u52A8\u9009\u62E9\u9002\u5408\u672C\u673A\u7684\u65B9\u5F0F\u3002\u53EF\u9009\u503C\u4EE5\u5DE5\u5177\u4E0B\u62C9\u6846\u4E3A\u51C6\uFF1Anpm\u3001pnpm\u3001script-bash\uFF08curl | bash\uFF09\u3001script-sh\uFF08curl | sh\uFF09\u3001script-powershell\uFF08irm | iex\uFF09\u3002",
|
|
14715
14781
|
disabled,
|
|
14716
14782
|
...state.toolInstallMethodsJson,
|
|
14717
14783
|
overriddenLabel: FIELD_COPY.overridden,
|