@dsh-workbench/core 0.2.6 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/bin/dsh-workbench +2 -0
- package/client.js +252 -36
- package/dist/client/client.body.js +252 -36
- package/dist/client/index.js +252 -36
- package/dist/host/index.js +1054 -737
- package/dist/types/app/client.d.ts +21 -15
- package/dist/types/app/layouts/rightbar/__tests__/market-order.test.d.ts +1 -0
- package/dist/types/app/layouts/rightbar/__tests__/market-running-display.test.d.ts +1 -0
- package/dist/types/app/layouts/rightbar/__tests__/market-workbench-act.test.d.ts +1 -0
- package/dist/types/app/layouts/rightbar/market-act.d.ts +2 -1
- package/dist/types/app/layouts/rightbar/market-rows.d.ts +3 -0
- package/dist/types/app/layouts/rightbar/market-settle-hold.d.ts +13 -0
- package/dist/types/app/layouts/rightbar/market-settle.d.ts +22 -0
- package/dist/types/app/layouts/rightbar/market-transient-state.d.ts +22 -0
- package/dist/types/app/layouts/rightbar/market-view-text.d.ts +26 -1
- package/dist/types/modules/panels/__tests__/market-tools-harness.d.ts +3 -0
- package/dist/types/modules/panels/model/market-workbench-update.d.ts +19 -0
- package/dist/types/modules/panels/model/market.d.ts +4 -0
- package/dist/types/shared/api/bundle-install.d.ts +1 -0
- package/dist/types/shared/api/config-sync.d.ts +0 -2
- package/dist/types/shared/api/host/__tests__/post-channels.test.d.ts +1 -0
- package/dist/types/shared/api/host/__tests__/self-update.test.d.ts +1 -0
- package/dist/types/shared/api/host/bundle-manager.d.ts +1 -0
- package/dist/types/shared/api/host/bundle-routes.d.ts +1 -1
- package/dist/types/shared/api/host/config-sync.d.ts +2 -2
- package/dist/types/shared/api/host/post-channels.d.ts +18 -0
- package/dist/types/shared/api/host/self-update.d.ts +45 -0
- package/docs/HANDOFF.md +3 -3
- package/docs/OPERATIONS.md +33 -3
- package/package.json +4 -4
- package/scripts/seed-profile.sh +9 -0
package/README.md
CHANGED
|
@@ -71,11 +71,11 @@ npx @dsh-workbench/core # ② 起工作台,默认 :3081
|
|
|
71
71
|
| --- | --- |
|
|
72
72
|
| 起工作台 | `npx @dsh-workbench/core` |
|
|
73
73
|
| 换端口 | `WORKBENCH_PORT=3091 npx @dsh-workbench/core` |
|
|
74
|
-
| 升级 | 重跑一次 `npx --yes @dsh-workbench/core@latest setup
|
|
74
|
+
| 升级 | 重跑一次 `npx --yes @dsh-workbench/core@latest setup`(幂等),刷新一次页面即可(`dsh-hmr` 会重组;它报 `restartReason` 时才重启进程) |
|
|
75
75
|
| 重建 profile | `mv ~/.dsh/profiles/workbench ~/.dsh/profiles/workbench.bak`,再跑一次 `setup` |
|
|
76
76
|
| 彻底不用了 | 删 `~/.dsh/profiles/workbench` 与 `~/.dsh/workbench` 两个目录(都不影响 `dsh web`) |
|
|
77
77
|
| 改设置 | 在 `:3081` 的 Settings 里改(模型供应商 / 搜索源 / MCP 也是这里) |
|
|
78
|
-
| 从 `dsh web` 搬设置过来 | 设置 → 「配置同步」→ 选来源 → 勾行 →
|
|
78
|
+
| 从 `dsh web` 搬设置过来 | 设置 → 「配置同步」→ 选来源 → 勾行 → 同步(即生效) |
|
|
79
79
|
|
|
80
80
|
## 和 `dsh web` 的关系
|
|
81
81
|
|
|
@@ -87,7 +87,7 @@ npx @dsh-workbench/core # ② 起工作台,默认 :3081
|
|
|
87
87
|
- **设置是工作台自己那份**:模型供应商 / 搜索源 / MCP 都在 `:3081` 的 Settings 里配,
|
|
88
88
|
落在 `profiles/workbench/cordis.patch.yml` —— 那是它唯一的一份设置文档,每一行都改得动。
|
|
89
89
|
想用 `dsh web` 那边已经配好的行:`:3081` → `Meta+,` → 「配置同步」→ 选来源 → 勾行 → 同步 →
|
|
90
|
-
|
|
90
|
+
**即生效**(只搬显式配过的行;同 id 内容不同默认不覆盖)。web 后来改的不会自动过来,
|
|
91
91
|
再打开这一页拉一次即可。见 [ADR-0044](../../docs/adr/0044-config-sync-replaces-the-web-patch-overlay.md)。
|
|
92
92
|
- ⚠️ **别在 Settings → 插件里把 `@dsh-workbench/core` 关掉**:关掉 = 它那份 bundle patch 整份不再应用
|
|
93
93
|
(包括里面的"禁用出厂左栏"),界面会**退化成原版 dsh web**(左栏回来、右侧面板消失)。
|
|
@@ -103,8 +103,8 @@ npx @dsh-workbench/core # ② 起工作台,默认 :3081
|
|
|
103
103
|
| 打开面板 / 按刷新要等 5–8 秒 | 正常:opencli 每次调用有**固定约 5 秒**开销(起浏览器会话)。**没有缓存**,数据一律实时 |
|
|
104
104
|
| 体检那屏说「检测浏览器通道 · 没连上」,可面板照样能用 | 本机全局 opencli 与隔离运行时版本不一致,daemon 被顶成对方那版;下一条浏览器命令会自动把它重启回来,体检复检后改回「已连接」 |
|
|
105
105
|
| 一切正常,但左栏是出厂样子、右边没有面板 | 工作台插件在 Settings 里被关了(见上一条 ⚠️) |
|
|
106
|
-
| 模型列表里只有出厂的几个、没有自己配的供应商 | 新装的 profile 不带设置(ADR-0044):设置 → 「配置同步」→ 选来源 → 勾 `llm-` 那几行 →
|
|
107
|
-
| 「配置同步」里某一行说 `@x 还没装` | 那一行点名的包不在这个 profile 的 `node_modules` 里:`dsh plugin --profile workbench add @x
|
|
106
|
+
| 模型列表里只有出厂的几个、没有自己配的供应商 | 新装的 profile 不带设置(ADR-0044):设置 → 「配置同步」→ 选来源 → 勾 `llm-` 那几行 → 同步(即生效)|
|
|
107
|
+
| 「配置同步」里某一行说 `@x 还没装` | 那一行点名的包不在这个 profile 的 `node_modules` 里:`dsh plugin --profile workbench add @x`(或在模块市场装),(装完 dsh 会自行重组;它报 `restartReason` 时才重启)|
|
|
108
108
|
|
|
109
109
|
排障全表在仓库的 [`docs/OPERATIONS.md`](https://github.com/code-farmer-i/dsh-workbench/blob/main/packages/workbench/docs/OPERATIONS.md);
|
|
110
110
|
把工作台装到别人机器上的前置清单见 [`docs/HANDOFF.md`](https://github.com/code-farmer-i/dsh-workbench/blob/main/packages/workbench/docs/HANDOFF.md)。
|
|
@@ -116,7 +116,7 @@ git clone git@github.com:code-farmer-i/dsh-workbench.git
|
|
|
116
116
|
cd dsh-workbench/packages/workbench
|
|
117
117
|
pnpm install
|
|
118
118
|
pnpm run dev # 监听 src/**(重建产物)+ 起工作台 :3081;改完不用重启、不用刷新页面
|
|
119
|
-
pnpm run check #
|
|
119
|
+
pnpm run check # 门禁:整仓那一套(类型 / lint / 覆盖率 / 架构 / 文档 / 运行时边界 / 接线 / 模块判据)
|
|
120
120
|
./bin/dsh-workbench # 只想起工作台、不需要监听改动时用它
|
|
121
121
|
```
|
|
122
122
|
|
|
@@ -124,7 +124,7 @@ pnpm run check # 门禁:类型 / 覆盖率 / 架构 / 运行时边界 / 接
|
|
|
124
124
|
`:3081` 已经有实例在跑时就只监听、不重复起第二个。改界面时开着它就够了:
|
|
125
125
|
浏览器半侧重建 `client.js` 后由 dsh 的 HMR 热换插件(不刷新页面),宿主半侧按模块路径热重载。
|
|
126
126
|
|
|
127
|
-
|
|
127
|
+
`cordis.patch.yml` 与 `package.json` 的 bundle 清单也**不用重启**(`dsh-hmr` 变了就重组);要重启的是改 `vite.config.ts`。
|
|
128
128
|
|
|
129
129
|
结构与边界(两个运行时、槽位接线、模块包的门禁)见仓库的
|
|
130
130
|
[`docs/ARCHITECTURE.md`](https://github.com/code-farmer-i/dsh-workbench/blob/main/docs/ARCHITECTURE.md) ·
|
package/bin/dsh-workbench
CHANGED
|
@@ -69,6 +69,8 @@ run_setup() {
|
|
|
69
69
|
else
|
|
70
70
|
SPEC="$PKG@^$(pkg_version)"
|
|
71
71
|
echo "→ 从内网源装 ${SPEC}(源在 package.json 的 publishConfig.registry)"
|
|
72
|
+
echo " 这一份启动器是装在哪就是哪一代:换 profile / 重建 profile 之前,先"
|
|
73
|
+
echo " npm i -g ${PKG}@latest。已经在跑的那个 profile 升级走市场里工作台那一行的「更新」。"
|
|
72
74
|
fi
|
|
73
75
|
|
|
74
76
|
dsh plugin --profile "$PROFILE" add "$SPEC"
|
package/client.js
CHANGED
|
@@ -1388,6 +1388,7 @@ window.__ModuleLoader__.load({
|
|
|
1388
1388
|
"panels.market.lead": "Installed on this machine, shared by every project.",
|
|
1389
1389
|
"panels.market.install": "Install",
|
|
1390
1390
|
"panels.market.update": "Update",
|
|
1391
|
+
"panels.market.swapSlow": "Not swapped yet — maybe a slow or failed download. Press Update again; if it stays like this, restart dsh.",
|
|
1391
1392
|
"panels.market.uninstall": "Uninstall",
|
|
1392
1393
|
"panels.market.uninstallLabel": "Uninstall {name}",
|
|
1393
1394
|
"panels.market.installing": "Installing…",
|
|
@@ -1639,7 +1640,7 @@ window.__ModuleLoader__.load({
|
|
|
1639
1640
|
"panel.conversation": "Conversation",
|
|
1640
1641
|
"panels.label": "Global panels",
|
|
1641
1642
|
"configSync.nav": "Config sync",
|
|
1642
|
-
"configSync.lead": "Bring over the rows another profile configures explicitly — pick any profile as the source.
|
|
1643
|
+
"configSync.lead": "Bring over the rows another profile configures explicitly — pick any profile as the source.",
|
|
1643
1644
|
"configSync.source": "Source",
|
|
1644
1645
|
"configSync.sourceBroken": "its config is unreadable",
|
|
1645
1646
|
"configSync.sourceRows": "{name}: {count} rows are new or different for the workbench",
|
|
@@ -1663,7 +1664,7 @@ window.__ModuleLoader__.load({
|
|
|
1663
1664
|
"configSync.apply": "Sync {count} selected",
|
|
1664
1665
|
"configSync.applyNone": "Pick some rows first",
|
|
1665
1666
|
"configSync.applying": "Writing…",
|
|
1666
|
-
"configSync.applied": "Written to the workbench config ·
|
|
1667
|
+
"configSync.applied": "Written to the workbench config · applied",
|
|
1667
1668
|
"configSync.appliedIds": "Written this time: {ids}",
|
|
1668
1669
|
"configSync.skippedIds": "Left alone (already here): {ids}",
|
|
1669
1670
|
"configSync.nothing": "Nothing to sync",
|
|
@@ -1782,6 +1783,7 @@ window.__ModuleLoader__.load({
|
|
|
1782
1783
|
"panels.market.lead": "装在这台机器上,所有项目共用。",
|
|
1783
1784
|
"panels.market.install": "安装",
|
|
1784
1785
|
"panels.market.update": "更新",
|
|
1786
|
+
"panels.market.swapSlow": "还没换上:可能网慢或没装上。再点一次「更新」;一直这样就把 dsh 重启一遍。",
|
|
1785
1787
|
"panels.market.uninstall": "卸载",
|
|
1786
1788
|
"panels.market.uninstallLabel": "卸载 {name}",
|
|
1787
1789
|
"panels.market.installing": "正在安装…",
|
|
@@ -2033,7 +2035,7 @@ window.__ModuleLoader__.load({
|
|
|
2033
2035
|
"panel.conversation": "对话",
|
|
2034
2036
|
"panels.label": "全局面板",
|
|
2035
2037
|
"configSync.nav": "配置同步",
|
|
2036
|
-
"configSync.lead": "把另一个 profile 里显式配过的行搬过来 ——
|
|
2038
|
+
"configSync.lead": "把另一个 profile 里显式配过的行搬过来 —— 来源随你选。",
|
|
2037
2039
|
"configSync.source": "来源",
|
|
2038
2040
|
"configSync.sourceBroken": "读不到它的配置",
|
|
2039
2041
|
"configSync.sourceRows": "{name} 这份里你有 {count} 行可搬",
|
|
@@ -2057,7 +2059,7 @@ window.__ModuleLoader__.load({
|
|
|
2057
2059
|
"configSync.apply": "同步选中的 {count} 行",
|
|
2058
2060
|
"configSync.applyNone": "先勾几行",
|
|
2059
2061
|
"configSync.applying": "正在写入…",
|
|
2060
|
-
"configSync.applied": "已写入工作台配置 ·
|
|
2062
|
+
"configSync.applied": "已写入工作台配置 · 已生效",
|
|
2061
2063
|
"configSync.appliedIds": "这次写进去:{ids}",
|
|
2062
2064
|
"configSync.skippedIds": "这几行工作台自己已有,没动:{ids}",
|
|
2063
2065
|
"configSync.nothing": "没有需要同步的内容",
|
|
@@ -2887,6 +2889,38 @@ window.__ModuleLoader__.load({
|
|
|
2887
2889
|
const fresh = previous === null ? [] : pending.filter((unit) => !previous.has(unit));
|
|
2888
2890
|
return pending.filter((unit) => active.has(unit) || fresh.includes(unit));
|
|
2889
2891
|
}
|
|
2892
|
+
var WORKBENCH_SWAP_MS = 18e4;
|
|
2893
|
+
function swapLanded(until, installed) {
|
|
2894
|
+
return until !== void 0 && installed === until;
|
|
2895
|
+
}
|
|
2896
|
+
function swapUntil(action, application, latest) {
|
|
2897
|
+
if (action !== "update-workbench" || application !== "restart-required") return void 0;
|
|
2898
|
+
return latest;
|
|
2899
|
+
}
|
|
2900
|
+
var READ_BACK_ACTIONS = /* @__PURE__ */ new Set(["update", "update-bundle"]);
|
|
2901
|
+
function awaitsReadBack(action, application, version) {
|
|
2902
|
+
return application === "applied" && version !== void 0 && READ_BACK_ACTIONS.has(action);
|
|
2903
|
+
}
|
|
2904
|
+
function readBackDone(input) {
|
|
2905
|
+
if (input.action === "update") return !input.outdated;
|
|
2906
|
+
if (input.entry === void 0 || input.entry.local === true || input.entry.latest === void 0) return true;
|
|
2907
|
+
if (input.entry.latest === input.entry.installed) return true;
|
|
2908
|
+
if (input.clicked === void 0) return true;
|
|
2909
|
+
return input.entry.installed !== input.clicked;
|
|
2910
|
+
}
|
|
2911
|
+
function settleLanded(input) {
|
|
2912
|
+
if (input.until !== void 0) return swapLanded(input.until, input.installed);
|
|
2913
|
+
if (input.readBack !== true) return true;
|
|
2914
|
+
return readBackDone({
|
|
2915
|
+
action: input.action,
|
|
2916
|
+
entry: input.entry,
|
|
2917
|
+
clicked: input.clicked,
|
|
2918
|
+
outdated: input.outdated
|
|
2919
|
+
});
|
|
2920
|
+
}
|
|
2921
|
+
function holdWindowMs(until) {
|
|
2922
|
+
return until === void 0 ? MODULE_SETTLE_MS : WORKBENCH_SWAP_MS;
|
|
2923
|
+
}
|
|
2890
2924
|
//#endregion
|
|
2891
2925
|
//#region src/app/layouts/rightbar/market-installed-mock.ts
|
|
2892
2926
|
function installedMocks(input) {
|
|
@@ -4019,6 +4053,7 @@ window.__ModuleLoader__.load({
|
|
|
4019
4053
|
key: "panels.market.workbenchLocal",
|
|
4020
4054
|
params: {}
|
|
4021
4055
|
} : void 0;
|
|
4056
|
+
const stale = !local && version.running !== void 0 && version.running !== version.installed;
|
|
4022
4057
|
return {
|
|
4023
4058
|
id: WORKBENCH_ROW_ID,
|
|
4024
4059
|
titleKey: WORKBENCH_TITLE_KEY,
|
|
@@ -4028,6 +4063,7 @@ window.__ModuleLoader__.load({
|
|
|
4028
4063
|
canUpdate: update !== void 0,
|
|
4029
4064
|
canUninstall: false,
|
|
4030
4065
|
...note === void 0 ? {} : { note },
|
|
4066
|
+
...stale ? { hint: "panels.market.moduleRestartHint" } : {},
|
|
4031
4067
|
version: {
|
|
4032
4068
|
installed: version.installed,
|
|
4033
4069
|
...latest === void 0 ? {} : { latest }
|
|
@@ -4090,6 +4126,10 @@ window.__ModuleLoader__.load({
|
|
|
4090
4126
|
}
|
|
4091
4127
|
return next ?? known;
|
|
4092
4128
|
}
|
|
4129
|
+
function installedIdSet(installed) {
|
|
4130
|
+
if (installed === void 0) return null;
|
|
4131
|
+
return new Set(installed.map((item) => item.unit));
|
|
4132
|
+
}
|
|
4093
4133
|
function installedRows(modules, manifests, listed, known, defaults = /* @__PURE__ */ new Set(), changed = {}) {
|
|
4094
4134
|
const titles = new Map(manifests.map((manifest) => [manifest.id, manifest.card?.titleKey]));
|
|
4095
4135
|
const rows = [];
|
|
@@ -4152,6 +4192,9 @@ window.__ModuleLoader__.load({
|
|
|
4152
4192
|
if (capability === void 0) return false;
|
|
4153
4193
|
return capability.status === "missing-commands";
|
|
4154
4194
|
}
|
|
4195
|
+
function capabilityOutdated(capabilities, unit) {
|
|
4196
|
+
return isOutdated(capabilities?.[unit]);
|
|
4197
|
+
}
|
|
4155
4198
|
function envNameOf(source) {
|
|
4156
4199
|
if (source === void 0) return "";
|
|
4157
4200
|
if (source.kind === "local") return source.env;
|
|
@@ -4213,6 +4256,12 @@ window.__ModuleLoader__.load({
|
|
|
4213
4256
|
const self = workbenchRow(workbench);
|
|
4214
4257
|
return marketHasUpdates([...marketRows(manifests, capabilities, marketUpdatesOf(modules)), ...self === void 0 ? [] : [self]], sharedRows(manifests, capabilities));
|
|
4215
4258
|
}
|
|
4259
|
+
function marketOrder(rows, titleOf) {
|
|
4260
|
+
return [...rows].sort((left, right) => {
|
|
4261
|
+
const byTitle = titleOf(left).localeCompare(titleOf(right), "zh-Hans-CN");
|
|
4262
|
+
return byTitle === 0 ? left.id.localeCompare(right.id) : byTitle;
|
|
4263
|
+
});
|
|
4264
|
+
}
|
|
4216
4265
|
function marketSections(rows) {
|
|
4217
4266
|
const installed = rows.filter((row) => isOnMachine(row.state));
|
|
4218
4267
|
const rest = rows.filter((row) => !isOnMachine(row.state));
|
|
@@ -4350,6 +4399,74 @@ window.__ModuleLoader__.load({
|
|
|
4350
4399
|
return busyView(active, visible);
|
|
4351
4400
|
}
|
|
4352
4401
|
//#endregion
|
|
4402
|
+
//#region src/app/layouts/rightbar/market-settle-hold.ts
|
|
4403
|
+
function useSettleHold(input) {
|
|
4404
|
+
const { pending, landed, t, onChanged, setPending, setFailed } = input;
|
|
4405
|
+
const until = pending?.until;
|
|
4406
|
+
const id = pending?.id ?? "";
|
|
4407
|
+
const watching = pending !== null && (pending.until !== void 0 || pending.readBack === true);
|
|
4408
|
+
const sinceRef = useRef(0);
|
|
4409
|
+
useEffect(() => {
|
|
4410
|
+
if (!watching || !landed) return;
|
|
4411
|
+
setPending(null);
|
|
4412
|
+
}, [
|
|
4413
|
+
watching,
|
|
4414
|
+
landed,
|
|
4415
|
+
setPending
|
|
4416
|
+
]);
|
|
4417
|
+
useEffect(() => {
|
|
4418
|
+
if (!watching) {
|
|
4419
|
+
sinceRef.current = 0;
|
|
4420
|
+
return;
|
|
4421
|
+
}
|
|
4422
|
+
if (sinceRef.current === 0) sinceRef.current = Date.now();
|
|
4423
|
+
const deadline = sinceRef.current + holdWindowMs(until);
|
|
4424
|
+
const tick = window.setInterval(() => {
|
|
4425
|
+
onChanged();
|
|
4426
|
+
if (Date.now() < deadline) return;
|
|
4427
|
+
window.clearInterval(tick);
|
|
4428
|
+
setPending(null);
|
|
4429
|
+
setFailed({
|
|
4430
|
+
id,
|
|
4431
|
+
message: t("panels.market.swapSlow")
|
|
4432
|
+
});
|
|
4433
|
+
}, 800);
|
|
4434
|
+
return () => window.clearInterval(tick);
|
|
4435
|
+
}, [
|
|
4436
|
+
watching,
|
|
4437
|
+
landed,
|
|
4438
|
+
until,
|
|
4439
|
+
id,
|
|
4440
|
+
onChanged,
|
|
4441
|
+
setPending,
|
|
4442
|
+
setFailed,
|
|
4443
|
+
t
|
|
4444
|
+
]);
|
|
4445
|
+
}
|
|
4446
|
+
//#endregion
|
|
4447
|
+
//#region src/app/layouts/rightbar/market-transient-state.ts
|
|
4448
|
+
function useMarketTransient(input) {
|
|
4449
|
+
const { mock, onPending } = input;
|
|
4450
|
+
const [pending, setPending] = useState(mock?.pending ?? null);
|
|
4451
|
+
const [confirming, setConfirming] = useState(mock?.confirming ?? null);
|
|
4452
|
+
const [failed, setFailed] = useState(mock?.failure ?? null);
|
|
4453
|
+
const [notice, setNotice] = useState(mock?.notice ?? null);
|
|
4454
|
+
useEffect(() => {
|
|
4455
|
+
onPending?.(pending !== null);
|
|
4456
|
+
return () => onPending?.(false);
|
|
4457
|
+
}, [pending, onPending]);
|
|
4458
|
+
return {
|
|
4459
|
+
pending,
|
|
4460
|
+
setPending,
|
|
4461
|
+
confirming,
|
|
4462
|
+
setConfirming,
|
|
4463
|
+
failed,
|
|
4464
|
+
setFailed,
|
|
4465
|
+
notice,
|
|
4466
|
+
setNotice
|
|
4467
|
+
};
|
|
4468
|
+
}
|
|
4469
|
+
//#endregion
|
|
4353
4470
|
//#region src/app/layouts/rightbar/market-plugin-rows.ts
|
|
4354
4471
|
function installedPluginKept(value) {
|
|
4355
4472
|
if (typeof value !== "object" || value === null) return void 0;
|
|
@@ -4512,6 +4629,80 @@ window.__ModuleLoader__.load({
|
|
|
4512
4629
|
"uninstall-plugin": "panels.market.uninstall",
|
|
4513
4630
|
"update-workbench": "panels.market.update"
|
|
4514
4631
|
};
|
|
4632
|
+
function holdOf(pending, application) {
|
|
4633
|
+
if (pending === null || pending.row === void 0) return void 0;
|
|
4634
|
+
if (application !== "applied") return void 0;
|
|
4635
|
+
return {
|
|
4636
|
+
id: pending.id,
|
|
4637
|
+
row: pending.row
|
|
4638
|
+
};
|
|
4639
|
+
}
|
|
4640
|
+
function pendingLanded(pending, updates, capabilities, installed) {
|
|
4641
|
+
if (pending === null) return true;
|
|
4642
|
+
return settleLanded({
|
|
4643
|
+
action: pending.action,
|
|
4644
|
+
until: pending.until,
|
|
4645
|
+
readBack: pending.readBack,
|
|
4646
|
+
installed,
|
|
4647
|
+
entry: updates[pending.id],
|
|
4648
|
+
clicked: pending.version,
|
|
4649
|
+
outdated: capabilityOutdated(capabilities, pending.id)
|
|
4650
|
+
});
|
|
4651
|
+
}
|
|
4652
|
+
function holdExpired(held, backInRoster, elapsedMs) {
|
|
4653
|
+
if (held === void 0) return true;
|
|
4654
|
+
return backInRoster || elapsedMs >= 15e3;
|
|
4655
|
+
}
|
|
4656
|
+
function heldIdOf(pending, held) {
|
|
4657
|
+
return pending?.id ?? held?.id ?? null;
|
|
4658
|
+
}
|
|
4659
|
+
function pinnedRowOf(pending, held) {
|
|
4660
|
+
return pending?.row ?? held?.row;
|
|
4661
|
+
}
|
|
4662
|
+
function withPinnedRow(rows, pinned) {
|
|
4663
|
+
if (pinned === void 0) return [...rows];
|
|
4664
|
+
if (!rows.some((row) => row.id === pinned.id)) return [...rows, pinned];
|
|
4665
|
+
return rows.map((row) => row.id === pinned.id ? pinned : row);
|
|
4666
|
+
}
|
|
4667
|
+
function marketFootVisible(shown, installed) {
|
|
4668
|
+
return shown.length > 0 || installed.length > 0;
|
|
4669
|
+
}
|
|
4670
|
+
function useMarketTitles(manifests, mocked) {
|
|
4671
|
+
const [titles, setTitles] = useState(/* @__PURE__ */ new Map());
|
|
4672
|
+
useEffect(() => {
|
|
4673
|
+
if (!mocked) setTitles((known) => mergeTitles(known, manifests));
|
|
4674
|
+
}, [manifests, mocked]);
|
|
4675
|
+
return titles;
|
|
4676
|
+
}
|
|
4677
|
+
function useHeldRow(pending, backInRoster) {
|
|
4678
|
+
const [held, setHeld] = useState(void 0);
|
|
4679
|
+
const heldAtRef = useRef(0);
|
|
4680
|
+
const hold = useCallback((next) => {
|
|
4681
|
+
if (next !== void 0) heldAtRef.current = Date.now();
|
|
4682
|
+
setHeld(next);
|
|
4683
|
+
}, []);
|
|
4684
|
+
const back = held === void 0 ? false : backInRoster(held.id);
|
|
4685
|
+
useEffect(() => {
|
|
4686
|
+
if (held === void 0) return;
|
|
4687
|
+
if (holdExpired(held, back, Date.now() - heldAtRef.current)) {
|
|
4688
|
+
setHeld(void 0);
|
|
4689
|
+
return;
|
|
4690
|
+
}
|
|
4691
|
+
const timer = setTimeout(() => setHeld(void 0), MODULE_SETTLE_MS);
|
|
4692
|
+
return () => clearTimeout(timer);
|
|
4693
|
+
}, [held, back]);
|
|
4694
|
+
useEffect(() => {
|
|
4695
|
+
if (pending !== null) setHeld(void 0);
|
|
4696
|
+
}, [pending]);
|
|
4697
|
+
return {
|
|
4698
|
+
held,
|
|
4699
|
+
hold
|
|
4700
|
+
};
|
|
4701
|
+
}
|
|
4702
|
+
function removingIdOf(pending, failed) {
|
|
4703
|
+
if (pending === null || pending.action !== "remove-bundle") return null;
|
|
4704
|
+
return failed?.id === pending.id ? null : pending.id;
|
|
4705
|
+
}
|
|
4515
4706
|
function pendingRowOf(input) {
|
|
4516
4707
|
const { pending, removing } = input;
|
|
4517
4708
|
if (removing === null || pending === null) return void 0;
|
|
@@ -4908,18 +5099,21 @@ window.__ModuleLoader__.load({
|
|
|
4908
5099
|
}
|
|
4909
5100
|
//#endregion
|
|
4910
5101
|
//#region src/app/layouts/rightbar/market-act.ts
|
|
5102
|
+
var STEADY_ACTIONS = /* @__PURE__ */ new Set(["update", "update-bundle"]);
|
|
4911
5103
|
function marketActOf(options) {
|
|
4912
5104
|
const { t, mocked, rowOf, seats, send, onChanged } = options;
|
|
4913
5105
|
return async (id, action) => {
|
|
4914
5106
|
if (mocked) return;
|
|
4915
5107
|
const row = rowOf(id);
|
|
4916
|
-
|
|
5108
|
+
const next = {
|
|
4917
5109
|
id,
|
|
4918
5110
|
action,
|
|
4919
5111
|
...row?.titleKey === void 0 ? {} : { titleKey: row.titleKey },
|
|
4920
5112
|
...row?.pkg === void 0 ? {} : { pkg: row.pkg },
|
|
4921
|
-
...row?.version?.installed === void 0 ? {} : { version: row.version.installed }
|
|
4922
|
-
|
|
5113
|
+
...row?.version?.installed === void 0 ? {} : { version: row.version.installed },
|
|
5114
|
+
...row === void 0 || !STEADY_ACTIONS.has(action) ? {} : { row }
|
|
5115
|
+
};
|
|
5116
|
+
seats.setPending(next);
|
|
4923
5117
|
seats.setConfirming(null);
|
|
4924
5118
|
seats.setFailed(null);
|
|
4925
5119
|
if (action !== "uninstall-plugin") seats.setNotice(null);
|
|
@@ -4933,8 +5127,9 @@ window.__ModuleLoader__.load({
|
|
|
4933
5127
|
action,
|
|
4934
5128
|
unit: id
|
|
4935
5129
|
});
|
|
4936
|
-
seats.setPending(null);
|
|
4937
5130
|
if (!outcome.ok) {
|
|
5131
|
+
seats.setPending(null);
|
|
5132
|
+
seats.setHeld(void 0);
|
|
4938
5133
|
onChanged();
|
|
4939
5134
|
seats.setFailed({
|
|
4940
5135
|
id,
|
|
@@ -4942,8 +5137,17 @@ window.__ModuleLoader__.load({
|
|
|
4942
5137
|
});
|
|
4943
5138
|
return;
|
|
4944
5139
|
}
|
|
5140
|
+
const change = changeOf(outcome.value);
|
|
5141
|
+
const until = swapUntil(action, change?.application, row?.version?.latest);
|
|
5142
|
+
const readBack = awaitsReadBack(action, change?.application, next.version);
|
|
5143
|
+
seats.setPending(until === void 0 && !readBack ? null : {
|
|
5144
|
+
...next,
|
|
5145
|
+
...until === void 0 ? {} : { until },
|
|
5146
|
+
...readBack ? { readBack: true } : {}
|
|
5147
|
+
});
|
|
5148
|
+
seats.setHeld(readBack ? void 0 : holdOf(next, change?.application));
|
|
4945
5149
|
if (action === "uninstall-plugin") seats.setNotice(installedPluginNotice(outcome.value, t));
|
|
4946
|
-
const reason = changeFailure(
|
|
5150
|
+
const reason = changeFailure(change, t);
|
|
4947
5151
|
onChanged();
|
|
4948
5152
|
if (reason !== void 0) seats.setFailed({
|
|
4949
5153
|
id,
|
|
@@ -4986,6 +5190,7 @@ window.__ModuleLoader__.load({
|
|
|
4986
5190
|
}
|
|
4987
5191
|
function MarketBody({ t, self, shown, pluginList, installedList, shared, pending, failed, notice, act, onConfirming, setDefault, boardBusy }) {
|
|
4988
5192
|
const failureOf = (id) => failed?.id === id ? failed.message : null;
|
|
5193
|
+
const foot = marketFootVisible(shown, installedList);
|
|
4989
5194
|
return /* @__PURE__ */ h(Fragment, null, notice === null ? null : /* @__PURE__ */ h("div", { className: MarketPage_module_default.marketNote }, notice), /* @__PURE__ */ h(MarketSection, {
|
|
4990
5195
|
t,
|
|
4991
5196
|
rows: self === void 0 ? [] : [self],
|
|
@@ -4999,7 +5204,7 @@ window.__ModuleLoader__.load({
|
|
|
4999
5204
|
}), self === void 0 ? null : /* @__PURE__ */ h("div", {
|
|
5000
5205
|
className: MarketPage_module_default.marketSelfDivider,
|
|
5001
5206
|
"aria-hidden": "true"
|
|
5002
|
-
}), marketSections([...shown, ...installedList]).map((section) => /* @__PURE__ */ h(MarketSection, {
|
|
5207
|
+
}), marketSections(marketOrder([...shown, ...installedList], (row) => marketRowTitle(row, t))).map((section) => /* @__PURE__ */ h(MarketSection, {
|
|
5003
5208
|
key: section.id,
|
|
5004
5209
|
t,
|
|
5005
5210
|
titleKey: section.titleKey,
|
|
@@ -5024,10 +5229,10 @@ window.__ModuleLoader__.load({
|
|
|
5024
5229
|
act,
|
|
5025
5230
|
confirmActions: CONFIRM_UNINSTALL,
|
|
5026
5231
|
onConfirming
|
|
5027
|
-
}), /* @__PURE__ */ h(PanelFoot, {
|
|
5232
|
+
}), foot ? /* @__PURE__ */ h(PanelFoot, {
|
|
5028
5233
|
size: "md",
|
|
5029
5234
|
text: t("panels.market.foot")
|
|
5030
|
-
}), /* @__PURE__ */ h(SharedSection, {
|
|
5235
|
+
}) : null, /* @__PURE__ */ h(SharedSection, {
|
|
5031
5236
|
t,
|
|
5032
5237
|
rows: shared,
|
|
5033
5238
|
pending,
|
|
@@ -5036,22 +5241,19 @@ window.__ModuleLoader__.load({
|
|
|
5036
5241
|
}));
|
|
5037
5242
|
}
|
|
5038
5243
|
function MarketView({ t, manifests, installable, capabilities, freshness, onChanged, onPending, updates, installed, installedRead, workbench, plugins, settling, mock, defaults = [], changed = {} }) {
|
|
5039
|
-
const
|
|
5040
|
-
useEffect(() => {
|
|
5041
|
-
if (mock === void 0) setTitles((known) => mergeTitles(known, manifests));
|
|
5042
|
-
}, [manifests, mock]);
|
|
5244
|
+
const titles = useMarketTitles(manifests, mock !== void 0);
|
|
5043
5245
|
const catalog = mock?.manifests ?? manifests;
|
|
5044
5246
|
const marketable = mock === void 0 ? marketCatalog(manifests, installable) : catalog;
|
|
5045
5247
|
const effective = mock === void 0 ? capabilities : mock.capabilities;
|
|
5046
|
-
const source = liveManifests(marketable, effective, mock === void 0
|
|
5248
|
+
const source = liveManifests(marketable, effective, installedIdSet(mock === void 0 ? installed : void 0));
|
|
5047
5249
|
const byDefault = new Set(defaults);
|
|
5048
|
-
const
|
|
5250
|
+
const updateMap = mock?.updates ?? updates ?? {};
|
|
5251
|
+
const rows = marketRows(source, effective, updateMap, byDefault, changed);
|
|
5049
5252
|
const shared = sharedRows(source, effective);
|
|
5050
|
-
const
|
|
5051
|
-
|
|
5052
|
-
onPending
|
|
5053
|
-
|
|
5054
|
-
}, [pending, onPending]);
|
|
5253
|
+
const { pending, setPending, confirming, setConfirming, failed, setFailed, notice, setNotice } = useMarketTransient({
|
|
5254
|
+
mock,
|
|
5255
|
+
onPending
|
|
5256
|
+
});
|
|
5055
5257
|
const provision = useHostWrite({
|
|
5056
5258
|
channel: "provision",
|
|
5057
5259
|
networkText: t("panels.failed")
|
|
@@ -5079,19 +5281,19 @@ window.__ModuleLoader__.load({
|
|
|
5079
5281
|
setNotice(t("panels.failed"));
|
|
5080
5282
|
}
|
|
5081
5283
|
};
|
|
5082
|
-
const
|
|
5083
|
-
const
|
|
5084
|
-
const
|
|
5085
|
-
const
|
|
5086
|
-
const installedList = installedRows((mock?.installed ?? installed ?? []).filter((module) => !(settling?.has(module.unit) ?? false) && module.unit !== removing), catalog, new Set(rows.map((row) => row.id)), titles, byDefault, changed);
|
|
5284
|
+
const removing = removingIdOf(pending, failed);
|
|
5285
|
+
const steady = useHeldRow(pending, (id) => catalog.some((manifest) => manifest.id === id));
|
|
5286
|
+
const pinned = pinnedRowOf(pending, steady.held);
|
|
5287
|
+
const installedList = installedRows((mock?.installed ?? installed ?? []).filter((module) => module.unit !== pinned?.id && (!(settling?.has(module.unit) ?? false) || module.unit === heldIdOf(pending, steady.held)) && module.unit !== removing), catalog, new Set(rows.map((row) => row.id)), titles, byDefault, changed);
|
|
5087
5288
|
const pendingRow = pendingRowOf({
|
|
5088
5289
|
pending,
|
|
5089
5290
|
removing,
|
|
5090
5291
|
rows,
|
|
5091
5292
|
titles
|
|
5092
5293
|
});
|
|
5093
|
-
const
|
|
5094
|
-
const
|
|
5294
|
+
const selfRow = workbenchRow(mock === void 0 ? workbench : mock.workbench);
|
|
5295
|
+
const shown = withPinnedRow(pendingRow === void 0 ? rows : [...rows, pendingRow], pinned);
|
|
5296
|
+
const self = selfRow;
|
|
5095
5297
|
const pluginList = installedPluginRows(mock?.plugins ?? plugins ?? [], byDefault, changed);
|
|
5096
5298
|
const rowById = new Map([
|
|
5097
5299
|
...shown,
|
|
@@ -5100,19 +5302,29 @@ window.__ModuleLoader__.load({
|
|
|
5100
5302
|
...pluginList
|
|
5101
5303
|
].map((row) => [row.id, row]));
|
|
5102
5304
|
const confirmingRow = confirming === null ? void 0 : rowById.get(confirming);
|
|
5305
|
+
const seats = {
|
|
5306
|
+
setPending,
|
|
5307
|
+
setHeld: steady.hold,
|
|
5308
|
+
setConfirming,
|
|
5309
|
+
setFailed,
|
|
5310
|
+
setNotice
|
|
5311
|
+
};
|
|
5103
5312
|
const act = marketActOf({
|
|
5104
5313
|
t,
|
|
5105
5314
|
mocked: mock !== void 0,
|
|
5106
5315
|
rowOf: (id) => rowById.get(id),
|
|
5107
|
-
seats
|
|
5108
|
-
setPending,
|
|
5109
|
-
setConfirming,
|
|
5110
|
-
setFailed,
|
|
5111
|
-
setNotice
|
|
5112
|
-
},
|
|
5316
|
+
seats,
|
|
5113
5317
|
send: (body) => provision.send(body),
|
|
5114
5318
|
onChanged
|
|
5115
5319
|
});
|
|
5320
|
+
useSettleHold({
|
|
5321
|
+
pending,
|
|
5322
|
+
landed: pendingLanded(pending, updateMap, effective, workbench?.installed),
|
|
5323
|
+
t,
|
|
5324
|
+
onChanged,
|
|
5325
|
+
setPending,
|
|
5326
|
+
setFailed
|
|
5327
|
+
});
|
|
5116
5328
|
const settled = marketSettled(freshness, installedRead);
|
|
5117
5329
|
const nothing = shown.length === 0 && self === void 0 && installedList.length === 0 && pluginList.length === 0;
|
|
5118
5330
|
if (!settled || (settling?.size ?? 0) > 0 && shown.length === 0 && installedList.length === 0) return /* @__PURE__ */ h(MarketChecking, { t });
|
|
@@ -6871,6 +7083,10 @@ window.__ModuleLoader__.load({
|
|
|
6871
7083
|
}) : null, rows.length > 0 ? /* @__PURE__ */ h("div", { className: ConfigSyncSection_module_default.foot }, /* @__PURE__ */ h(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
6872
7084
|
variant: "primary",
|
|
6873
7085
|
size: "md",
|
|
7086
|
+
icon: /* @__PURE__ */ h(_deepseek_ai_dsh_client_ui_primitives.IconRefreshOutlineRegular, {
|
|
7087
|
+
size: 16,
|
|
7088
|
+
"aria-hidden": "true"
|
|
7089
|
+
}),
|
|
6874
7090
|
disabled: chosen.length === 0 || busy.busy,
|
|
6875
7091
|
onClick: apply
|
|
6876
7092
|
}, chosen.length === 0 ? t("configSync.applyNone") : busy.busy ? t("configSync.applying") : t("configSync.apply", { count: chosen.length }))) : null) : null));
|