@ljwei-stak/dsh-model-router 0.14.0-beta.2 → 0.14.0-beta.4
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 +74 -47
- package/.dsh-plugin/index.mjs +14 -8
- package/.dsh-plugin/shared/harness-plan.mjs +1 -1
- package/.dsh-plugin/shared/latest-versions.mjs +200 -0
- package/.dsh-plugin/shared/npm-attestation.mjs +315 -0
- package/.dsh-plugin/shared/official-tool-executor.mjs +37 -20
- package/.dsh-plugin/shared/official-tool-registry.mjs +14 -19
- package/.dsh-plugin/shared/official-tools-runtime.mjs +53 -54
- package/.dsh-plugin/shared/tool-health.mjs +25 -8
- package/.dsh-plugin/shared/vendor-mimo-grok-adapter.mjs +55 -37
- package/.dsh-plugin/shared/zcode-bundle.mjs +95 -32
- package/.dsh-plugin/shared/zcode-installer.mjs +33 -32
- package/CHANGELOG.md +29 -0
- package/README.md +17 -8
- package/README.zh.md +32 -21
- package/package.json +4 -2
package/.dsh-plugin/client.js
CHANGED
|
@@ -53,9 +53,8 @@ var OFFICIAL_TOOLS = Object.freeze([
|
|
|
53
53
|
vendor: "Moonshot AI",
|
|
54
54
|
purpose: "Kimi \u5B98\u65B9\u7F16\u7A0B CLI\uFF0C\u63D0\u4F9B kimi \u547D\u4EE4\u4E0E ACP \u4F1A\u8BDD\u3002",
|
|
55
55
|
package: "@moonshot-ai/kimi-code",
|
|
56
|
-
version: "2.1.1",
|
|
57
56
|
manager: "npm",
|
|
58
|
-
installArgs: ["install", "-g", "@moonshot-ai/kimi-code@
|
|
57
|
+
installArgs: ["install", "-g", "@moonshot-ai/kimi-code@latest", "--registry=https://registry.npmjs.org/"],
|
|
59
58
|
probeExecutables: ["kimi"],
|
|
60
59
|
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",
|
|
61
60
|
providerHints: ["moonshot", "kimi"]
|
|
@@ -66,9 +65,8 @@ var OFFICIAL_TOOLS = Object.freeze([
|
|
|
66
65
|
vendor: "Anthropic",
|
|
67
66
|
purpose: "Anthropic \u5B98\u65B9\u7F16\u7A0B CLI\uFF0C\u63D0\u4F9B claude \u547D\u4EE4\u3002",
|
|
68
67
|
package: "@anthropic-ai/claude-code",
|
|
69
|
-
version: "2.1.283",
|
|
70
68
|
manager: "npm",
|
|
71
|
-
installArgs: ["install", "-g", "@anthropic-ai/claude-code@
|
|
69
|
+
installArgs: ["install", "-g", "@anthropic-ai/claude-code@latest", "--registry=https://registry.npmjs.org/"],
|
|
72
70
|
probeExecutables: ["claude"],
|
|
73
71
|
providerHints: ["anthropic", "claude"]
|
|
74
72
|
}),
|
|
@@ -78,11 +76,10 @@ var OFFICIAL_TOOLS = Object.freeze([
|
|
|
78
76
|
vendor: "OpenAI",
|
|
79
77
|
purpose: "OpenAI \u5B98\u65B9\u7F16\u7A0B CLI\uFF0C\u63D0\u4F9B codex \u547D\u4EE4\u3002",
|
|
80
78
|
package: "@openai/codex",
|
|
81
|
-
|
|
82
|
-
installArgs: ["install", "-g", "@openai/codex@0.157.1", "--registry=https://registry.npmjs.org/"],
|
|
79
|
+
installArgs: ["install", "-g", "@openai/codex@latest", "--registry=https://registry.npmjs.org/"],
|
|
83
80
|
manager: "npm",
|
|
84
81
|
probeExecutables: ["codex"],
|
|
85
|
-
probeNote: "Codex \u7248\u672C\u6A2A\u5E45\u7531\u9002\u914D\u5C42\u5BBD\u5339\u914D\uFF1B\u5B89\u88C5\u65F6\
|
|
82
|
+
probeNote: "Codex \u7248\u672C\u6A2A\u5E45\u7531\u9002\u914D\u5C42\u5BBD\u5339\u914D\uFF1B\u5B89\u88C5\u65F6\u53D6 npm \u6700\u65B0\u7248\u3002",
|
|
86
83
|
providerHints: ["openai", "gpt", "codex"]
|
|
87
84
|
}),
|
|
88
85
|
Object.freeze({
|
|
@@ -91,9 +88,8 @@ var OFFICIAL_TOOLS = Object.freeze([
|
|
|
91
88
|
vendor: "MiniMax",
|
|
92
89
|
purpose: "MiniMax \u5B98\u65B9\u7F16\u7A0B CLI\uFF0C\u63D0\u4F9B mcode \u547D\u4EE4\u3002",
|
|
93
90
|
package: "@minimax-ai/code",
|
|
94
|
-
version: "0.5.5",
|
|
95
91
|
manager: "npm",
|
|
96
|
-
installArgs: ["install", "-g", "@minimax-ai/code@
|
|
92
|
+
installArgs: ["install", "-g", "@minimax-ai/code@latest", "--registry=https://registry.npmjs.org/", "--ignore-scripts=false", "--include=optional", "--allow-scripts=@minimax-ai/code,better-sqlite3"],
|
|
97
93
|
probeExecutables: ["mcode"],
|
|
98
94
|
providerHints: ["minimax"]
|
|
99
95
|
}),
|
|
@@ -103,9 +99,8 @@ var OFFICIAL_TOOLS = Object.freeze([
|
|
|
103
99
|
vendor: "XiaoMi",
|
|
104
100
|
purpose: "\u5C0F\u7C73 MiMo \u5B98\u65B9\u7F16\u7A0B CLI\uFF0C\u63D0\u4F9B mimo \u547D\u4EE4\u3002",
|
|
105
101
|
package: "@mimo-ai/cli",
|
|
106
|
-
version: "0.1.15",
|
|
107
102
|
manager: "npm",
|
|
108
|
-
installArgs: ["install", "-g", "@mimo-ai/cli@
|
|
103
|
+
installArgs: ["install", "-g", "@mimo-ai/cli@latest", "--registry=https://registry.npmjs.org/"],
|
|
109
104
|
probeExecutables: ["mimo"],
|
|
110
105
|
providerHints: ["mimo", "xiaomi"]
|
|
111
106
|
}),
|
|
@@ -115,9 +110,8 @@ var OFFICIAL_TOOLS = Object.freeze([
|
|
|
115
110
|
vendor: "xAI",
|
|
116
111
|
purpose: "xAI \u5B98\u65B9\u7F16\u7A0B CLI\uFF0C\u63D0\u4F9B grok \u547D\u4EE4\u4E0E ACP \u4F1A\u8BDD\u3002",
|
|
117
112
|
package: "@xai-official/grok",
|
|
118
|
-
version: "1.0.41",
|
|
119
113
|
manager: "npm",
|
|
120
|
-
installArgs: ["install", "-g", "@xai-official/grok@
|
|
114
|
+
installArgs: ["install", "-g", "@xai-official/grok@latest", "--registry=https://registry.npmjs.org/"],
|
|
121
115
|
probeExecutables: ["grok"],
|
|
122
116
|
providerHints: ["xai", "grok"]
|
|
123
117
|
}),
|
|
@@ -127,9 +121,8 @@ var OFFICIAL_TOOLS = Object.freeze([
|
|
|
127
121
|
vendor: "Google",
|
|
128
122
|
purpose: "Google \u5B98\u65B9 Gemini CLI\uFF0C\u65E0\u754C\u9762\u6A21\u5F0F\u4F7F\u7528 gemini -p\u3002",
|
|
129
123
|
package: "@google/gemini-cli",
|
|
130
|
-
version: "0.62.0",
|
|
131
124
|
manager: "npm",
|
|
132
|
-
installArgs: ["install", "-g", "@google/gemini-cli@
|
|
125
|
+
installArgs: ["install", "-g", "@google/gemini-cli@latest", "--registry=https://registry.npmjs.org/"],
|
|
133
126
|
probeExecutables: ["gemini"],
|
|
134
127
|
providerHints: ["gemini", "google"],
|
|
135
128
|
// Headless runs go through the task adapter. The signed sandbox runner does
|
|
@@ -141,7 +134,6 @@ var OFFICIAL_TOOLS = Object.freeze([
|
|
|
141
134
|
label: "ZCode",
|
|
142
135
|
vendor: "Z.ai",
|
|
143
136
|
purpose: "\u667A\u8C31\u5B98\u65B9 ZCode \u684C\u9762\u7248\uFF0C\u5185\u542B GLM \u7F16\u7A0B\u4EE3\u7406\u3002Windows \u5B89\u88C5\u5668\u53EF\u9009\u62E9 D \u76D8\u76EE\u5F55\u3002",
|
|
144
|
-
version: "3.14.3",
|
|
145
137
|
manager: "signed-windows-installer",
|
|
146
138
|
installArgs: [],
|
|
147
139
|
probeExecutables: [],
|
|
@@ -1359,7 +1351,7 @@ function channelForProvider(provider, installedToolIds = [], runnableToolIds = [
|
|
|
1359
1351
|
preference,
|
|
1360
1352
|
tool: tool.id,
|
|
1361
1353
|
label: tool.label,
|
|
1362
|
-
detail: tool.id === "zcode" ? "ZCode \u5DF2\u5B89\u88C5\uFF0C\u63D2\u4EF6\u53EF\u8C03\u7528\u5176\u5B98\u65B9\u7F16\u7A0B\u4EE3\u7406\
|
|
1354
|
+
detail: tool.id === "zcode" ? "ZCode \u5DF2\u5B89\u88C5\uFF0C\u63D2\u4EF6\u53EF\u8C03\u7528\u5176\u5B98\u65B9\u7F16\u7A0B\u4EE3\u7406\uFF1B\u5176 CLI \u4F7F\u7528\u81EA\u8EAB\u914D\u7F6E\u7684\u9ED8\u8BA4\u6A21\u578B\uFF0C\u4E0D\u80FD\u4FDD\u8BC1\u4E0E Harness \u5EFA\u8BAE\u6A21\u578B\u4E00\u81F4\u3002" : headless && !runnable ? `${tool.label} \u5DF2\u5B89\u88C5\u3002\u5206\u914D\u5230\u8BE5\u6A21\u578B\u7684\u4EFB\u52A1\u4F1A\u5148\u8D70\u5B98\u65B9\u65E0\u754C\u9762\u547D\u4EE4\uFF1B\u547D\u4EE4\u7F3A\u5931\u6216\u5931\u8D25\u65F6\u56DE\u9000\u6A21\u578B\u76EE\u5F55 API\u3002` : `${tool.label} \u5DF2\u5B89\u88C5\uFF0C\u63D2\u4EF6\u53EF\u6258\u7BA1\u8C03\u7528\u5176\u5B98\u65B9 CLI\uFF1BHarness \u6A21\u578B\u76EE\u5F55\u4E0E\u5382\u5546 CLI \u540D\u79F0\u53EF\u80FD\u4E0D\u540C\uFF0C\u56E2\u961F\u65E0\u6CD5\u786E\u8BA4\u6620\u5C04\u65F6\u4F7F\u7528 CLI \u9ED8\u8BA4\u6A21\u578B\uFF0C\u5B9E\u9645\u6A21\u578B\u4ECD\u987B\u6838\u5BF9\u8FD0\u884C\u8BB0\u5F55\u3002`
|
|
1363
1355
|
};
|
|
1364
1356
|
}
|
|
1365
1357
|
return {
|
|
@@ -1729,16 +1721,19 @@ function stableVersionOrder(left, right) {
|
|
|
1729
1721
|
}
|
|
1730
1722
|
return 0;
|
|
1731
1723
|
}
|
|
1732
|
-
function toolInstallAction({ tool, probe, readiness, job, probeStatus }) {
|
|
1724
|
+
function toolInstallAction({ tool, probe, readiness, job, probeStatus, latestVersion = null }) {
|
|
1733
1725
|
const running = job?.status === "running";
|
|
1734
|
-
const
|
|
1735
|
-
const
|
|
1736
|
-
const
|
|
1737
|
-
const
|
|
1738
|
-
const
|
|
1726
|
+
const installed = probe?.installed === true;
|
|
1727
|
+
const order = installed && latestVersion ? stableVersionOrder(probe.version, latestVersion) : null;
|
|
1728
|
+
const ready = readiness?.ready === true;
|
|
1729
|
+
const desktop = tool.manager === "signed-windows-installer";
|
|
1730
|
+
const noRunner = desktop || tool.headlessAdapter === true;
|
|
1731
|
+
const repair = installed && !noRunner && readiness?.ready === false;
|
|
1732
|
+
const label = running ? "\u5B89\u88C5\u4E2D\u2026" : !installed ? job?.status === "failed" ? "\u91CD\u8BD5\u5B89\u88C5" : desktop ? "\u4E0B\u8F7D\u6700\u65B0\u5B89\u88C5\u5668" : "\u4E00\u952E\u5B89\u88C5\u6700\u65B0\u7248" : order === -1 ? `\u66F4\u65B0\u5230\u6700\u65B0\u7248 ${latestVersion}` : order === 1 ? "\u5DF2\u9AD8\u4E8E\u6700\u65B0\u6B63\u5F0F\u7248" : repair ? "\u4FEE\u590D\u5B98\u65B9\u6267\u884C\u5165\u53E3" : order === 0 ? "\u5DF2\u662F\u6700\u65B0\u7248\u672C" : "\u5B89\u88C5\u6700\u65B0\u7248";
|
|
1733
|
+
const current = order === 0 && (ready || noRunner);
|
|
1739
1734
|
return {
|
|
1740
1735
|
label,
|
|
1741
|
-
disabled: probeStatus !== "ready" || running ||
|
|
1736
|
+
disabled: probeStatus !== "ready" || running || installed && (order === 1 || current)
|
|
1742
1737
|
};
|
|
1743
1738
|
}
|
|
1744
1739
|
|
|
@@ -1782,7 +1777,14 @@ function dagLayers(packages) {
|
|
|
1782
1777
|
return layers.filter(Boolean);
|
|
1783
1778
|
}
|
|
1784
1779
|
var LOGIN_LABEL = Object.freeze({ "logged-in": "\u5DF2\u767B\u5F55", "logged-out": "\u672A\u767B\u5F55", unknown: "\u767B\u5F55\u72B6\u6001\u672A\u77E5" });
|
|
1785
|
-
var VERSION_LABEL = Object.freeze({
|
|
1780
|
+
var VERSION_LABEL = Object.freeze({ latest: "\u5DF2\u662F\u6700\u65B0\u7248", "update-available": "\u6709\u65B0\u7248\u672C", unknown: "\u6700\u65B0\u7248\u672C\u672A\u77E5" });
|
|
1781
|
+
var UNTESTED_VERSION_NOTE = "\u63D2\u4EF6\u4E0D\u518D\u56FA\u5B9A\u5B98\u65B9\u5DE5\u5177\u7248\u672C\uFF0C\u5B89\u88C5\u548C\u66F4\u65B0\u90FD\u53D6\u5404\u5382\u5546\u7684\u6700\u65B0\u7248\uFF1B\u65B0\u7248\u672C\u672A\u7ECF\u63D2\u4EF6\u6D4B\u8BD5\uFF0C\u8F93\u51FA\u683C\u5F0F\u53D8\u5316\u65F6\u63D2\u4EF6\u4F1A\u5C3D\u91CF\u517C\u5BB9\uFF0C\u9047\u5230\u95EE\u9898\u8BF7\u53CD\u9988\u3002";
|
|
1782
|
+
function versionLine(entry) {
|
|
1783
|
+
if (!entry?.installed) return "";
|
|
1784
|
+
const installed = entry.version ? `\u5DF2\u5B89\u88C5 ${entry.version}` : "\u5DF2\u5B89\u88C5\uFF08\u7248\u672C\u672A\u77E5\uFF09";
|
|
1785
|
+
if (!entry.latestVersion) return `${installed} \xB7 ${VERSION_LABEL.unknown}`;
|
|
1786
|
+
return entry.versionStatus === "update-available" ? `${installed} \xB7 \u6700\u65B0 ${entry.latestVersion}\uFF08\u6709\u65B0\u7248\u672C\uFF0C\u53EF\u5728\u4E0B\u65B9\u66F4\u65B0\uFF09` : `${installed} \xB7 ${VERSION_LABEL.latest}`;
|
|
1787
|
+
}
|
|
1786
1788
|
function healthSummary(tools) {
|
|
1787
1789
|
const list = Array.isArray(tools) ? tools : [];
|
|
1788
1790
|
const installed = list.filter((item) => item.installed);
|
|
@@ -1792,7 +1794,7 @@ function healthSummary(tools) {
|
|
|
1792
1794
|
ready: installed.filter((item) => item.login?.state === "logged-in").length,
|
|
1793
1795
|
loggedOut: installed.filter((item) => item.login?.state === "logged-out").length,
|
|
1794
1796
|
unknown: installed.filter((item) => item.login?.state === "unknown").length,
|
|
1795
|
-
|
|
1797
|
+
updates: installed.filter((item) => item.versionStatus === "update-available").length
|
|
1796
1798
|
};
|
|
1797
1799
|
}
|
|
1798
1800
|
var money = formatUsd;
|
|
@@ -1953,8 +1955,9 @@ var SUBSCRIPTION_FAILURE_OPTIONS = [["ask", "\u6682\u505C\u5E76\u8BE2\u95EE"], [
|
|
|
1953
1955
|
var SUBSCRIPTION_CHOICE_BUTTONS = [["api", "\u6539\u7528 API \u91CD\u8BD5", false], ["subscription", "\u91CD\u8BD5\u8BA2\u9605", true], ["cancel", "\u53D6\u6D88", true]];
|
|
1954
1956
|
function OnboardingBanner({ health, onDone, onRefresh, refreshing, error }) {
|
|
1955
1957
|
const summary = healthSummary(health?.tools);
|
|
1956
|
-
const problems = (health?.tools ?? []).filter((item) => item.installed &&
|
|
1957
|
-
|
|
1958
|
+
const problems = (health?.tools ?? []).filter((item) => item.installed && item.login?.state === "logged-out");
|
|
1959
|
+
const updates = (health?.tools ?? []).filter((item) => item.installed && item.versionStatus === "update-available");
|
|
1960
|
+
return /* @__PURE__ */ import_react2.default.createElement("section", { className: "mr-card mr-onboarding", "aria-label": "\u5F00\u7BB1\u4F53\u68C0" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-card-head" }, /* @__PURE__ */ import_react2.default.createElement("div", null, /* @__PURE__ */ import_react2.default.createElement("h2", { className: "mr-card-title" }, "\u5F00\u7BB1\u4F53\u68C0"), /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-card-copy" }, "\u9996\u6B21\u6253\u5F00\u65F6\u68C0\u6D4B\u6BCF\u4E2A\u5B98\u65B9\u5DE5\u5177\u662F\u5426\u5DF2\u5B89\u88C5\u3001\u5F53\u524D\u7248\u672C\uFF08\u4EE5\u53CA\u80FD\u67E5\u5230\u65F6\u7684\u6700\u65B0\u7248\u672C\uFF09\u3001\u662F\u5426\u5DF2\u767B\u5F55\u3002\u672A\u767B\u5F55\u7684\u5DE5\u5177\u4F1A\u88AB\u8DEF\u7531\u76F4\u63A5\u8DF3\u8FC7\uFF0C\u6539\u8D70\u6A21\u578B\u76EE\u5F55 API\uFF0C\u4E0D\u5FC5\u7B49\u5F85 CLI \u5931\u8D25\u3002")), /* @__PURE__ */ import_react2.default.createElement("button", { className: "mr-button mr-button-secondary", type: "button", disabled: refreshing, onClick: onRefresh }, refreshing ? "\u68C0\u6D4B\u4E2D\u2026" : "\u91CD\u65B0\u4F53\u68C0")), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-card-body" }, error && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-error", role: "alert" }, error), !health && !error && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-empty", role: "status" }, "\u6B63\u5728\u4F53\u68C0\u672C\u673A\u5B98\u65B9\u5DE5\u5177\u2026"), health && /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-result-grid" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric-label" }, "\u5DF2\u5B89\u88C5"), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric-value" }, summary.installed, " / ", summary.total)), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric-label" }, "\u5DF2\u767B\u5F55\u53EF\u7528"), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric-value" }, summary.ready)), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric-label" }, "\u672A\u767B\u5F55"), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric-value" }, summary.loggedOut)), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric-label" }, "\u767B\u5F55\u72B6\u6001\u672A\u77E5"), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-metric-value" }, summary.unknown))), problems.length > 0 ? /* @__PURE__ */ import_react2.default.createElement("ul", { className: "mr-checklist" }, problems.map((item) => /* @__PURE__ */ import_react2.default.createElement("li", { key: item.id }, /* @__PURE__ */ import_react2.default.createElement("strong", null, item.label), "\uFF1A\u672A\u767B\u5F55\uFF0C\u53EF\u5728\u4E0B\u65B9\u70B9\u201C\u53BB\u767B\u5F55\u201D\u67E5\u770B\u767B\u5F55\u65B9\u6CD5\uFF08", item.login.command ?? "\u89C1\u8BF4\u660E", "\uFF09\u3002"))) : /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-caption" }, "\u5DF2\u5B89\u88C5\u7684\u5DE5\u5177\u6CA1\u6709\u53D1\u73B0\u672A\u767B\u5F55\u7684\u95EE\u9898\u3002\u672A\u5B89\u88C5\u7684\u5DE5\u5177\u53EF\u5728\u4E0B\u65B9\u4E00\u952E\u5B89\u88C5\u3002"), updates.length > 0 && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-caption" }, "\u6709\u65B0\u7248\u672C\uFF1A", updates.map((item) => `${item.label} ${item.version ?? "?"} \u2192 ${item.latestVersion}`).join("\uFF1B"), "\u3002\u53EF\u5728\u4E0B\u65B9\u201C\u5B98\u65B9\u5DE5\u5177\u201D\u4E2D\u66F4\u65B0\uFF08\u53EF\u9009\uFF09\u3002"), /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-caption" }, UNTESTED_VERSION_NOTE), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-actions" }, /* @__PURE__ */ import_react2.default.createElement("button", { className: "mr-button", type: "button", onClick: onDone }, "\u5B8C\u6210\u4F53\u68C0"), /* @__PURE__ */ import_react2.default.createElement("span", { className: "mr-caption" }, "\u4E4B\u540E\u53EF\u968F\u65F6\u5728\u201C\u5B98\u65B9\u5DE5\u5177\u201D\u5361\u7247\u4E2D\u91CD\u65B0\u4F53\u68C0\u3002")))));
|
|
1958
1961
|
}
|
|
1959
1962
|
function ToolLoginLine({ entry }) {
|
|
1960
1963
|
const [open, setOpen] = import_react2.default.useState(false);
|
|
@@ -1969,7 +1972,7 @@ function ToolLoginLine({ entry }) {
|
|
|
1969
1972
|
setCopied(false);
|
|
1970
1973
|
}
|
|
1971
1974
|
};
|
|
1972
|
-
return /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-login" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-tool-status" }, /* @__PURE__ */ import_react2.default.createElement("span", { className: `mr-tool-dot ${state === "logged-in" ? "installed" : state === "logged-out" ? "missing-strong" : ""}` }), LOGIN_LABEL[state], " \xB7 ",
|
|
1975
|
+
return /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-login" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-tool-status" }, /* @__PURE__ */ import_react2.default.createElement("span", { className: `mr-tool-dot ${state === "logged-in" ? "installed" : state === "logged-out" ? "missing-strong" : ""}` }), LOGIN_LABEL[state], " \xB7 ", versionLine(entry)), entry.login?.detail && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-caption mr-tool-detail" }, entry.login.detail), state === "logged-in" && entry.login?.billing === "subscription" && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-caption mr-tool-detail" }, "\u8BA2\u9605\u8D26\u53F7\u767B\u5F55\uFF1A\u8D39\u7528\u53EA\u4F5C\u53C2\u8003\u663E\u793A\uFF0C\u4E0D\u8BA1\u5165\u9884\u7B97\u3002"), state === "logged-in" && entry.login?.billing === "api-key" && /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-caption mr-tool-detail" }, "API Key \u8BA1\u8D39\uFF1A\u8D39\u7528\u8BA1\u5165\u6BCF\u65E5/\u6BCF\u6708\u9884\u7B97\u3002"), state !== "logged-in" && /* @__PURE__ */ import_react2.default.createElement("button", { className: "mr-button mr-button-secondary mr-tool-button mr-login-button", type: "button", "aria-expanded": open, onClick: () => setOpen((value) => !value) }, "\u53BB\u767B\u5F55"), open && /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-login-guide" }, /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-caption" }, entry.login.steps), entry.login.command && /* @__PURE__ */ import_react2.default.createElement("div", { className: "mr-login-command" }, /* @__PURE__ */ import_react2.default.createElement("code", { className: "mr-tool-command" }, entry.login.command), /* @__PURE__ */ import_react2.default.createElement("button", { className: "mr-button mr-button-secondary", type: "button", onClick: () => {
|
|
1973
1976
|
void copy();
|
|
1974
1977
|
} }, copied ? "\u5DF2\u590D\u5236" : "\u590D\u5236\u547D\u4EE4")), /* @__PURE__ */ import_react2.default.createElement("p", { className: "mr-caption" }, "\u63D2\u4EF6\u4E0D\u4F1A\u66FF\u4F60\u542F\u52A8\u4EA4\u4E92\u5F0F\u767B\u5F55\u3002\u767B\u5F55\u5B8C\u6210\u540E\u70B9\u201C\u91CD\u65B0\u4F53\u68C0\u201D\u3002")));
|
|
1975
1978
|
}
|
|
@@ -11601,7 +11604,7 @@ var xterm_default = `/**
|
|
|
11601
11604
|
`;
|
|
11602
11605
|
|
|
11603
11606
|
// .dsh-plugin/client/host-version.mjs
|
|
11604
|
-
var ROUTER_CLIENT_VERSION = true ? "0.14.0-beta.
|
|
11607
|
+
var ROUTER_CLIENT_VERSION = true ? "0.14.0-beta.4" : "";
|
|
11605
11608
|
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";
|
|
11606
11609
|
function isMissingRemoteMethod(message) {
|
|
11607
11610
|
const value = String(message ?? "");
|
|
@@ -11723,6 +11726,7 @@ function parseTerminalStop(value) {
|
|
|
11723
11726
|
const request = plainObject(value, "terminal stop request");
|
|
11724
11727
|
return { sessionId: sessionIdOf(request.sessionId) };
|
|
11725
11728
|
}
|
|
11729
|
+
var isTerminalSessionId = (value) => typeof value === "string" && SESSION_ID.test(value);
|
|
11726
11730
|
|
|
11727
11731
|
// .dsh-plugin/client/cli-terminal-state.mjs
|
|
11728
11732
|
var text3 = (value) => typeof value === "string" ? value.trim() : "";
|
|
@@ -11779,10 +11783,26 @@ var formatDuration = (ms2) => {
|
|
|
11779
11783
|
const minutes = Math.floor(seconds / 60);
|
|
11780
11784
|
return minutes < 60 ? `${minutes} \u5206 ${seconds % 60} \u79D2` : `${Math.floor(minutes / 60)} \u5C0F\u65F6 ${minutes % 60} \u5206`;
|
|
11781
11785
|
};
|
|
11782
|
-
|
|
11783
|
-
if (response?.ok)
|
|
11784
|
-
|
|
11785
|
-
|
|
11786
|
+
function unwrapTerminal(response, fallback) {
|
|
11787
|
+
if (!response?.ok) throw new Error(remoteErrorText(text3(response?.error?.message) || text3(response?.error), fallback));
|
|
11788
|
+
const inner = response.value;
|
|
11789
|
+
if (inner && typeof inner === "object" && typeof inner.ok === "boolean") {
|
|
11790
|
+
if (!inner.ok) throw new Error(remoteErrorText(text3(inner.error?.message) || text3(inner.error), fallback));
|
|
11791
|
+
return inner.value;
|
|
11792
|
+
}
|
|
11793
|
+
return inner;
|
|
11794
|
+
}
|
|
11795
|
+
var unwrap = unwrapTerminal;
|
|
11796
|
+
async function loadTerminalInfo(api) {
|
|
11797
|
+
const info = unwrap(await api.terminalInfo(), "\u65E0\u6CD5\u8BFB\u53D6\u7EC8\u7AEF\u72B6\u6001\u3002");
|
|
11798
|
+
if (!info || typeof info !== "object" || !["pty", "pipe"].includes(info.backend)) throw new Error("\u7EC8\u7AEF\u72B6\u6001\u683C\u5F0F\u65E0\u6548\u3002");
|
|
11799
|
+
return info;
|
|
11800
|
+
}
|
|
11801
|
+
async function startTerminal(api, request) {
|
|
11802
|
+
const session = unwrap(await api.terminalStart({ ...request, confirmed: true }), "\u7EC8\u7AEF\u542F\u52A8\u5931\u8D25\u3002");
|
|
11803
|
+
if (!isTerminalSessionId(session?.sessionId)) throw new Error("\u7EC8\u7AEF\u542F\u52A8\u7ED3\u679C\u7F3A\u5C11\u6709\u6548\u7684\u4F1A\u8BDD ID\u3002");
|
|
11804
|
+
return session;
|
|
11805
|
+
}
|
|
11786
11806
|
var TerminalConnection = class {
|
|
11787
11807
|
constructor({ api, sessionId, onData, onExit, onError, waitMs = 800, retryMs = 1e3, resizeDelayMs = 120, setTimer = setTimeout, clearTimer = clearTimeout }) {
|
|
11788
11808
|
Object.assign(this, { api, sessionId, onData, onExit, onError, waitMs, retryMs, resizeDelayMs });
|
|
@@ -11796,6 +11816,13 @@ var TerminalConnection = class {
|
|
|
11796
11816
|
this.failures = 0;
|
|
11797
11817
|
}
|
|
11798
11818
|
start() {
|
|
11819
|
+
if (!isTerminalSessionId(this.sessionId)) {
|
|
11820
|
+
this.closed = true;
|
|
11821
|
+
this.onError?.(new Error("\u7EC8\u7AEF\u4F1A\u8BDD ID \u65E0\u6548\uFF0C\u65E0\u6CD5\u8BFB\u53D6\u8F93\u51FA\u3002"));
|
|
11822
|
+
this.onExit?.({ endReason: "lost", exitCode: null });
|
|
11823
|
+
this.loop = Promise.resolve();
|
|
11824
|
+
return this.loop;
|
|
11825
|
+
}
|
|
11799
11826
|
this.loop = this.readLoop();
|
|
11800
11827
|
return this.loop;
|
|
11801
11828
|
}
|
|
@@ -11849,7 +11876,9 @@ var TerminalConnection = class {
|
|
|
11849
11876
|
}
|
|
11850
11877
|
}
|
|
11851
11878
|
resize(cols, rows) {
|
|
11852
|
-
if (this.closed) return;
|
|
11879
|
+
if (this.closed || !Number.isFinite(cols) || !Number.isFinite(rows)) return;
|
|
11880
|
+
cols = Math.min(TERMINAL_LIMITS.maxCols, Math.max(TERMINAL_LIMITS.minCols, Math.round(cols)));
|
|
11881
|
+
rows = Math.min(TERMINAL_LIMITS.maxRows, Math.max(TERMINAL_LIMITS.minRows, Math.round(rows)));
|
|
11853
11882
|
if (this.resizeTimer) this.clearTimer(this.resizeTimer);
|
|
11854
11883
|
this.resizeTimer = this.setTimer(() => {
|
|
11855
11884
|
this.resizeTimer = null;
|
|
@@ -11975,10 +12004,9 @@ function CliTerminalCard({ api, health }) {
|
|
|
11975
12004
|
const mounted = import_react4.default.useRef(true);
|
|
11976
12005
|
const loadInfo = import_react4.default.useCallback(async () => {
|
|
11977
12006
|
try {
|
|
11978
|
-
const
|
|
12007
|
+
const value = await loadTerminalInfo(api);
|
|
11979
12008
|
if (!mounted.current) return;
|
|
11980
|
-
|
|
11981
|
-
setInfo({ status: "ready", value: response.value, error: "" });
|
|
12009
|
+
setInfo({ status: "ready", value, error: "" });
|
|
11982
12010
|
} catch (error) {
|
|
11983
12011
|
if (mounted.current) setInfo({ status: "error", value: null, error: errorText(error, "\u65E0\u6CD5\u8BFB\u53D6\u7EC8\u7AEF\u72B6\u6001\u3002") });
|
|
11984
12012
|
}
|
|
@@ -12007,15 +12035,14 @@ function CliTerminalCard({ api, health }) {
|
|
|
12007
12035
|
setStarting(true);
|
|
12008
12036
|
setStartError("");
|
|
12009
12037
|
try {
|
|
12010
|
-
const
|
|
12011
|
-
if (!response?.ok) throw new Error(remoteErrorText(response?.error?.message, "\u7EC8\u7AEF\u542F\u52A8\u5931\u8D25\u3002"));
|
|
12038
|
+
const session = await startTerminal(api, { target: selected.id, mode, cwd: text4(cwd), cols: 100, rows: 30 });
|
|
12012
12039
|
storeCwd(text4(cwd));
|
|
12013
12040
|
if (!mounted.current) {
|
|
12014
|
-
void api.terminalStop({ sessionId:
|
|
12041
|
+
void api.terminalStop({ sessionId: session.sessionId });
|
|
12015
12042
|
return;
|
|
12016
12043
|
}
|
|
12017
|
-
setSessions((previous) => [...previous, { ...
|
|
12018
|
-
setActiveId(
|
|
12044
|
+
setSessions((previous) => [...previous, { ...session, ended: null }]);
|
|
12045
|
+
setActiveId(session.sessionId);
|
|
12019
12046
|
setConfirming(false);
|
|
12020
12047
|
} catch (error) {
|
|
12021
12048
|
if (mounted.current) setStartError(errorText(error, "\u7EC8\u7AEF\u542F\u52A8\u5931\u8D25\u3002"));
|
|
@@ -12419,7 +12446,7 @@ function OfficialToolsCard({ listOfficialTools, installOfficialTool, cancelOffic
|
|
|
12419
12446
|
const byId = Object.fromEntries(probeState.probes.map((probe) => [probe.id, probe]));
|
|
12420
12447
|
const capabilitiesById = Object.fromEntries(probeState.capabilities.map((item) => [item.id, item]));
|
|
12421
12448
|
const readinessById = Object.fromEntries(probeState.readiness.map((item) => [item.id, item]));
|
|
12422
|
-
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\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: () => {
|
|
12449
|
+
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\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: () => {
|
|
12423
12450
|
void refresh();
|
|
12424
12451
|
} }, "\u91CD\u65B0\u4F53\u68C0")), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-card-body" }, 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.status === "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) => {
|
|
12425
12452
|
const command = installCommandLine(tool);
|
|
@@ -12428,10 +12455,10 @@ function OfficialToolsCard({ listOfficialTools, installOfficialTool, cancelOffic
|
|
|
12428
12455
|
const readiness = readinessById[tool.id];
|
|
12429
12456
|
const job = jobs[tool.id];
|
|
12430
12457
|
const running = job?.status === "running";
|
|
12431
|
-
const action = toolInstallAction({ tool, probe, readiness, job, probeStatus: probeState.status });
|
|
12458
|
+
const action = toolInstallAction({ tool, probe, readiness, job, probeStatus: probeState.status, latestVersion: healthById[tool.id]?.latestVersion ?? null });
|
|
12432
12459
|
const verified = job?.status === "succeeded" && job.postInstallProbe?.installed === true;
|
|
12433
12460
|
const status = running ? job.cancelRequested ? "\u6B63\u5728\u53D6\u6D88\u5B89\u88C5\u2026" : "\u5B89\u88C5\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" ? "\u5B89\u88C5\u5DF2\u53D6\u6D88\uFF0C\u8BF7\u91CD\u65B0\u68C0\u6D4B" : verified ? "\u5B89\u88C5\u6210\u529F\u5E76\u9A8C\u8BC1" : probeLabel(probe);
|
|
12434
|
-
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,
|
|
12461
|
+
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" } }, tool.unsupportedReason), 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("button", { className: "mr-button mr-tool-button", type: "button", disabled: action.disabled, onClick: () => {
|
|
12435
12462
|
void install(tool.id);
|
|
12436
12463
|
} }, action.label), running && /* @__PURE__ */ import_react5.default.createElement("button", { className: "mr-button mr-button-secondary mr-tool-button", type: "button", disabled: job.cancelRequested, onClick: () => {
|
|
12437
12464
|
void cancel(tool.id);
|
|
@@ -12730,7 +12757,7 @@ function RouterMainPage({ loadCatalog, settingsScope, listOfficialTools, install
|
|
|
12730
12757
|
}
|
|
12731
12758
|
), /* @__PURE__ */ import_react5.default.createElement(SecurityCard, { data: workbench.boundaries.value, error: workbench.boundaries.error, onRefresh: () => {
|
|
12732
12759
|
void workbench.refreshBoundaries();
|
|
12733
|
-
} }), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-notice" }, "\u53EA\u8BFB\u4EFB\u52A1\u53EF\u5728\u4E0A\u65B9\u201C\u5728\u5DE5\u4F5C\u53F0\u6267\u884C\u201D\u4E2D\u76F4\u63A5\u9884\u89C8\u5E76\u6267\u884C\uFF1B\u5728\u5B98\u65B9\u4F1A\u8BDD\u4E2D\u53EF\u4F7F\u7528 ", /* @__PURE__ */ import_react5.default.createElement("code", null, "model_router_execute"), "\uFF08\u6309\u8DEF\u7531\u6216\u6307\u5B9A\u6A21\u578B\u6267\u884C\uFF0C\u5B98\u65B9 CLI \u5931\u8D25\u5219\u56DE\u9000 API\uFF09\u3001", /* @__PURE__ */ import_react5.default.createElement("code", null, "model_router_consult"), "\u3001", /* @__PURE__ */ import_react5.default.createElement("code", null, "model_router_tool_run"), " \u6216 ", /* @__PURE__ */ import_react5.default.createElement("code", null, "model_router_team_execute"), "\u3002\u6307\u5B9A\u6A21\u578B\u4F1A\u8DF3\u8FC7\u8DEF\u7EBF\u6BD4\u8F83\u3002\u6258\u7BA1\u6267\u884C\u80FD\u529B\u548C\u5C31\u7EEA\u72B6\u6001\u89C1\u4E0A\u65B9\u5404\u5DE5\u5177\u5361\u7247\uFF1B\u5B9E\u9645\u4F7F\u7528\u7684\u6A21\u578B\u4EE5\u5382\u5546\u8BB0\u5F55\u4E3A\u51C6\u3002ZCode
|
|
12760
|
+
} }), /* @__PURE__ */ import_react5.default.createElement("div", { className: "mr-notice" }, "\u53EA\u8BFB\u4EFB\u52A1\u53EF\u5728\u4E0A\u65B9\u201C\u5728\u5DE5\u4F5C\u53F0\u6267\u884C\u201D\u4E2D\u76F4\u63A5\u9884\u89C8\u5E76\u6267\u884C\uFF1B\u5728\u5B98\u65B9\u4F1A\u8BDD\u4E2D\u53EF\u4F7F\u7528 ", /* @__PURE__ */ import_react5.default.createElement("code", null, "model_router_execute"), "\uFF08\u6309\u8DEF\u7531\u6216\u6307\u5B9A\u6A21\u578B\u6267\u884C\uFF0C\u5B98\u65B9 CLI \u5931\u8D25\u5219\u56DE\u9000 API\uFF09\u3001", /* @__PURE__ */ import_react5.default.createElement("code", null, "model_router_consult"), "\u3001", /* @__PURE__ */ import_react5.default.createElement("code", null, "model_router_tool_run"), " \u6216 ", /* @__PURE__ */ import_react5.default.createElement("code", null, "model_router_team_execute"), "\u3002\u6307\u5B9A\u6A21\u578B\u4F1A\u8DF3\u8FC7\u8DEF\u7EBF\u6BD4\u8F83\u3002\u6258\u7BA1\u6267\u884C\u80FD\u529B\u548C\u5C31\u7EEA\u72B6\u6001\u89C1\u4E0A\u65B9\u5404\u5DE5\u5177\u5361\u7247\uFF1B\u5B9E\u9645\u4F7F\u7528\u7684\u6A21\u578B\u4EE5\u5382\u5546\u8BB0\u5F55\u4E3A\u51C6\u3002ZCode \u4F7F\u7528\u5176\u81EA\u8EAB\u914D\u7F6E\u7684\u9ED8\u8BA4\u6A21\u578B\u3002\u53EF\u7F16\u8F91\u56E2\u961F\u4EFB\u52A1\u8981\u6C42\u5E72\u51C0\u7684 Git \u4ED3\u5E93\uFF0C\u5E76\u7ECF\u5B98\u65B9\u5DE5\u5177\u5BA1\u6279\u3002\u8BBE\u7F6E\u4F4D\u4E8E\u201C\u63D2\u4EF6 \u2192 \u5DF2\u5B89\u88C5 \u2192 @ljwei-stak/model-router-galgame\u201D\u3002")));
|
|
12734
12761
|
}
|
|
12735
12762
|
|
|
12736
12763
|
// .dsh-plugin/shared/official-tools-remote.mjs
|
package/.dsh-plugin/index.mjs
CHANGED
|
@@ -7,6 +7,7 @@ import { defineTool } from '@deepseek-ai/dsh-tools'
|
|
|
7
7
|
import { DEFAULT_ROUTER_SETTINGS, modelMetadata } from './shared/router.mjs'
|
|
8
8
|
import { DEFAULT_ROUTING_PRESET, normalizeRoutingPreset, routingPreset } from './shared/routing-presets.mjs'
|
|
9
9
|
import { HEALTH_CACHE_MS, apiKeyEnvPresent, healthCache, runHealthCheck, subscriptionLoginOf } from './shared/tool-health.mjs'
|
|
10
|
+
import { latestVersions } from './shared/latest-versions.mjs'
|
|
10
11
|
import {
|
|
11
12
|
DEFAULT_COOLDOWN_MINUTES, billingOverview, createQuotaTracker, detectQuotaExhaustion, parseQuotaPatterns, vendorKey,
|
|
12
13
|
} from './shared/subscription-billing.mjs'
|
|
@@ -28,6 +29,7 @@ import {
|
|
|
28
29
|
parseTerminalWrite,
|
|
29
30
|
} from './shared/cli-terminal-protocol.mjs'
|
|
30
31
|
import {
|
|
32
|
+
OFFICIAL_TOOLS,
|
|
31
33
|
getOfficialTool,
|
|
32
34
|
installCommandLine,
|
|
33
35
|
toolForProvider,
|
|
@@ -293,9 +295,13 @@ const readAuthState = async path => {
|
|
|
293
295
|
}
|
|
294
296
|
|
|
295
297
|
/** 开箱体检: install, version and login state for every registry tool. */
|
|
296
|
-
export async function toolHealthReport({ fresh = false, runner = defaultRunner } = {}) {
|
|
297
|
-
|
|
298
|
-
const
|
|
298
|
+
export async function toolHealthReport({ fresh = false, runner = defaultRunner, latest = latestVersions } = {}) {
|
|
299
|
+
// Latest-version lookups run alongside the probes; failures are non-fatal (offline-safe).
|
|
300
|
+
const [probes, latestById] = await Promise.all([
|
|
301
|
+
probeAllTools({ fresh }),
|
|
302
|
+
latest.lookupAll(OFFICIAL_TOOLS).catch(() => ({})),
|
|
303
|
+
])
|
|
304
|
+
const report = await runHealthCheck(probes, { runner, home: homedir(), exists: fileExists, readAuthState, latest: latestById })
|
|
299
305
|
healthCache.remember(report)
|
|
300
306
|
try { await routerStateStore().saveHealth(report) } catch { /* the cache still serves this process */ }
|
|
301
307
|
return report
|
|
@@ -957,7 +963,7 @@ export async function planToolRun(ctx, config, args = {}, { signal } = {}) {
|
|
|
957
963
|
}
|
|
958
964
|
if (text(args.cliModel)) {
|
|
959
965
|
if (!route) throw new Error('cliModel 需要同时提供已配置的 provider 和 model 路线')
|
|
960
|
-
if (toolId === 'zcode') throw new Error('ZCode
|
|
966
|
+
if (toolId === 'zcode') throw new Error('ZCode CLI 不支持在单次调用中指定模型')
|
|
961
967
|
modelId = text(args.cliModel)
|
|
962
968
|
}
|
|
963
969
|
const estimate = route ? createPlanFromRoutes(taskText, routes, { mode: 'direct', directProvider: route.provider, directModel: route.model }).estimatedCost : null
|
|
@@ -1503,7 +1509,7 @@ function registerOfficialToolModels(ctx, config) {
|
|
|
1503
1509
|
}))
|
|
1504
1510
|
ctx.tools.register(defineTool({
|
|
1505
1511
|
name: 'model_router_tool_install',
|
|
1506
|
-
description: 'Install one official model tool by registry id
|
|
1512
|
+
description: 'Install one official model tool by registry id from its fixed official source at the vendor latest release. ZCode opens the latest publisher-signed interactive desktop installer with a directory picker. Only registry ids are accepted; arbitrary packages or executables are refused.',
|
|
1507
1513
|
parameters: {
|
|
1508
1514
|
tool: { type: 'string', required: true, description: 'Registry tool id, e.g. kimi-code.' },
|
|
1509
1515
|
},
|
|
@@ -1532,7 +1538,7 @@ function registerOfficialToolModels(ctx, config) {
|
|
|
1532
1538
|
task: { type: 'string', required: true, description: 'Concrete task for the official CLI model.' },
|
|
1533
1539
|
provider: { type: 'string', description: 'Optional configured provider, paired with model.' },
|
|
1534
1540
|
model: { type: 'string', description: 'Optional model ID from the Harness directory, paired with provider. This ID is advisory for CLIs except Claude/Codex.' },
|
|
1535
|
-
cliModel: { type: 'string', description: 'Optional model name already configured in this vendor CLI; requires provider and model. MiniMax/MiMo require provider/model format. ZCode
|
|
1541
|
+
cliModel: { type: 'string', description: 'Optional model name already configured in this vendor CLI; requires provider and model. MiniMax/MiMo require provider/model format. ZCode cannot switch models per call.' },
|
|
1536
1542
|
mode: { type: 'string', enum: ['read-only', 'workspace-write'], description: 'Default is read-only. Kimi, MiniMax and ZCode require workspace-write. Write mode requires official approval and a clean Git repository.' },
|
|
1537
1543
|
confirmOverBudget: { type: 'boolean', description: 'Set only after the user agreed to exceed the daily/monthly budget. Triggers an approval prompt.' },
|
|
1538
1544
|
},
|
|
@@ -1597,7 +1603,7 @@ function registerOfficialToolModels(ctx, config) {
|
|
|
1597
1603
|
}))
|
|
1598
1604
|
ctx.tools.register(defineTool({
|
|
1599
1605
|
name: 'model_router_health',
|
|
1600
|
-
description: 'Onboarding health check: for each official CLI in the fixed registry, report installed, version
|
|
1606
|
+
description: 'Onboarding health check: for each official CLI in the fixed registry, report installed version, the latest published version when it can be looked up cheaply (update hint only), and login state (cheap status commands only; never starts a login), plus a per-provider billing table: billing mode (subscription-first by default), subscription state (logged in / coding-plan key route / exhausted until a time) and whether an API-key route is available for fallback. Logged-out tools are skipped by routing until re-checked.',
|
|
1601
1607
|
parameters: {
|
|
1602
1608
|
fresh: { type: 'boolean', description: 'Re-probe instead of using the 60s probe cache.' },
|
|
1603
1609
|
},
|
|
@@ -1658,7 +1664,7 @@ function registerOfficialToolModels(ctx, config) {
|
|
|
1658
1664
|
task: { type: 'string', required: true, description: 'Full task to plan, distribute and execute.' },
|
|
1659
1665
|
mode: { type: 'string', enum: ['read-only', 'workspace-write'], description: 'Default read-only; workspace-write needs a clean Git repository and approval.' },
|
|
1660
1666
|
budgetUsd: { type: 'number', description: 'Estimated planning ceiling only, not a vendor billing limit.' },
|
|
1661
|
-
cliModelsJson: { type: 'string', description: 'Optional JSON object mapping official tool IDs or work package IDs to exact model names configured in those CLIs. MiniMax/MiMo require provider/model; ZCode
|
|
1667
|
+
cliModelsJson: { type: 'string', description: 'Optional JSON object mapping official tool IDs or work package IDs to exact model names configured in those CLIs. MiniMax/MiMo require provider/model; ZCode cannot switch per call.' },
|
|
1662
1668
|
confirmOverBudget: { type: 'boolean', description: 'Set only after the user agreed to exceed the daily/monthly budget. Triggers an approval prompt.' },
|
|
1663
1669
|
},
|
|
1664
1670
|
output: JSON_OUTPUT,
|
|
@@ -38,7 +38,7 @@ export function channelForProvider(provider, installedToolIds = [], runnableTool
|
|
|
38
38
|
return {
|
|
39
39
|
kind: 'official-cli', preference, tool: tool.id, label: tool.label,
|
|
40
40
|
detail: tool.id === 'zcode'
|
|
41
|
-
? 'ZCode
|
|
41
|
+
? 'ZCode 已安装,插件可调用其官方编程代理;其 CLI 使用自身配置的默认模型,不能保证与 Harness 建议模型一致。'
|
|
42
42
|
: headless && !runnable
|
|
43
43
|
? `${tool.label} 已安装。分配到该模型的任务会先走官方无界面命令;命令缺失或失败时回退模型目录 API。`
|
|
44
44
|
: `${tool.label} 已安装,插件可托管调用其官方 CLI;Harness 模型目录与厂商 CLI 名称可能不同,团队无法确认映射时使用 CLI 默认模型,实际模型仍须核对运行记录。`,
|