@michengai/dsh-codex-ui 0.2.80 → 0.2.82
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/CHANGELOG.md +38 -10
- package/CHANGELOG.zh-CN.md +38 -10
- package/README.md +15 -8
- package/README.zh-CN.md +15 -8
- package/dist/client.js +54 -4
- package/dist/index.mjs +106 -27
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,44 @@
|
|
|
4
4
|
|
|
5
5
|
This changelog records the five most recent published releases of DSH Codex UI and its one-click Suite. Earlier changes remain available in the [Git history](https://github.com/MichengAI/dsh-codex-ui/commits/main).
|
|
6
6
|
|
|
7
|
+
## 0.2.82 — 2026-08-24
|
|
8
|
+
|
|
9
|
+
Companion release: `@michengai/dsh-codex-suite@0.1.14`.
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Replaced the Suite's recommended aggregate install with an installer that records all six members as direct profile dependencies, allowing **Settings → About** to detect and update each plugin independently.
|
|
14
|
+
- Made clean custom Web profiles reuse the same `DSH_HOME` while placing DSH's built-in `dsh-web-app` before the member bundles.
|
|
15
|
+
- When About encounters a legacy aggregate Suite, it now promotes all six members before removing the aggregate package instead of retaining only the clicked plugin.
|
|
16
|
+
|
|
17
|
+
### Suite 0.1.14
|
|
18
|
+
|
|
19
|
+
- Added the cross-platform `dsh-codex-suite` command, legacy migration, config-dump validation, and dry-run support.
|
|
20
|
+
- Preserved exact member version coordination without modifying upstream DSH or creating a separate DSH Home.
|
|
21
|
+
|
|
22
|
+
Published packages: [`@michengai/dsh-codex-ui@0.2.82`](https://www.npmjs.com/package/@michengai/dsh-codex-ui/v/0.2.82) and [`@michengai/dsh-codex-suite@0.1.14`](https://www.npmjs.com/package/@michengai/dsh-codex-suite/v/0.1.14).
|
|
23
|
+
|
|
24
|
+
## 0.2.81 — 2026-08-24
|
|
25
|
+
|
|
26
|
+
Companion release: `@michengai/dsh-codex-suite@0.1.13`.
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- Added an **Update all** action beside Companion management plugins whenever installed plugins have updates available.
|
|
31
|
+
- Kept missing plugins on their existing per-row install path instead of installing them implicitly during a bulk update.
|
|
32
|
+
|
|
33
|
+
### Reliability and accessibility
|
|
34
|
+
|
|
35
|
+
- Staged every selected package in one Host request and sent a single Desktop hot-update signal after the complete batch, so updating several plugins now reloads the window only once.
|
|
36
|
+
- Preserved individual install and update actions while preventing overlapping requests.
|
|
37
|
+
- Added visible loading feedback, keyboard focus treatment, accessible busy/status announcements, bilingual copy, and regression coverage for the batch selection and endpoint contract.
|
|
38
|
+
|
|
39
|
+
### Suite 0.1.13
|
|
40
|
+
|
|
41
|
+
- Pinned `@michengai/dsh-codex-ui` to `0.2.81`; all other Suite member pins remain on their currently verified releases.
|
|
42
|
+
|
|
43
|
+
Published packages: [`@michengai/dsh-codex-ui@0.2.81`](https://www.npmjs.com/package/@michengai/dsh-codex-ui/v/0.2.81) and [`@michengai/dsh-codex-suite@0.1.13`](https://www.npmjs.com/package/@michengai/dsh-codex-suite/v/0.1.13).
|
|
44
|
+
|
|
7
45
|
## 0.2.80 — 2026-08-23
|
|
8
46
|
|
|
9
47
|
Companion release: `@michengai/dsh-codex-suite@0.1.12`.
|
|
@@ -77,13 +115,3 @@ Companion release: `@michengai/dsh-codex-suite@0.1.8`.
|
|
|
77
115
|
- Kept the workspace slot mounted across compact and expanded sidebar modes.
|
|
78
116
|
|
|
79
117
|
Release commit: [`b96d5a8`](https://github.com/MichengAI/dsh-codex-ui/commit/b96d5a8).
|
|
80
|
-
|
|
81
|
-
## 0.2.76 — 2026-08-23
|
|
82
|
-
|
|
83
|
-
Companion release: `@michengai/dsh-codex-suite@0.1.7`.
|
|
84
|
-
|
|
85
|
-
### Fixed
|
|
86
|
-
|
|
87
|
-
- Removed the duplicate drop indicator that could appear while reordering pinned workspaces.
|
|
88
|
-
|
|
89
|
-
Release commit: [`e2a38d1`](https://github.com/MichengAI/dsh-codex-ui/commit/e2a38d1).
|
package/CHANGELOG.zh-CN.md
CHANGED
|
@@ -4,6 +4,44 @@
|
|
|
4
4
|
|
|
5
5
|
本日志记录 DSH Codex UI 及其一键 Suite 最近发布的五个版本;更早的变更可查看 [Git 提交历史](https://github.com/MichengAI/dsh-codex-ui/commits/main)。
|
|
6
6
|
|
|
7
|
+
## 0.2.82 — 2026-08-24
|
|
8
|
+
|
|
9
|
+
配套版本:`@michengai/dsh-codex-suite@0.1.14`。
|
|
10
|
+
|
|
11
|
+
### 修复
|
|
12
|
+
|
|
13
|
+
- Suite 一键入口改为安装器,将六个成员写成 profile 的直接依赖,使「设置 → 关于」可以分别检测和升级每个插件。
|
|
14
|
+
- 新建自定义 Web profile 时自动复用同一 `DSH_HOME`,并把 DSH 内置 `dsh-web-app` 放在成员 bundle 之前。
|
|
15
|
+
- “关于”页遇到旧版聚合 Suite 时,先把全部六个成员提升为直接依赖,再移除聚合包,避免只保留本次点击的一个插件。
|
|
16
|
+
|
|
17
|
+
### Suite 0.1.14
|
|
18
|
+
|
|
19
|
+
- 新增跨平台 `dsh-codex-suite` 命令、旧 Suite 自动迁移、配置 dump 验证和 dry-run。
|
|
20
|
+
- 保留精确成员版本组合,不修改上游 DSH,也不创建独立 DSH Home。
|
|
21
|
+
|
|
22
|
+
发布包:[`@michengai/dsh-codex-ui@0.2.82`](https://www.npmjs.com/package/@michengai/dsh-codex-ui/v/0.2.82) 与 [`@michengai/dsh-codex-suite@0.1.14`](https://www.npmjs.com/package/@michengai/dsh-codex-suite/v/0.1.14)。
|
|
23
|
+
|
|
24
|
+
## 0.2.81 — 2026-08-24
|
|
25
|
+
|
|
26
|
+
配套版本:`@michengai/dsh-codex-suite@0.1.13`。
|
|
27
|
+
|
|
28
|
+
### 新增
|
|
29
|
+
|
|
30
|
+
- 当已安装插件存在新版本时,在“配套管理插件”标题右侧显示 **全部更新** 操作。
|
|
31
|
+
- 缺失插件继续使用各自的行内安装入口,不会被批量更新隐式安装。
|
|
32
|
+
|
|
33
|
+
### 可靠性与无障碍
|
|
34
|
+
|
|
35
|
+
- 通过一次 Host 请求登记全部选中版本,并在批次完整写入后只发送一次 Desktop 热更新信号;多个插件更新现在只会重载一次窗口。
|
|
36
|
+
- 保留单插件安装和更新入口,同时阻止重叠请求。
|
|
37
|
+
- 增加可见加载反馈、键盘焦点样式、可访问的忙碌/状态提示、中英文文案,以及批量筛选和接口约束的回归测试。
|
|
38
|
+
|
|
39
|
+
### Suite 0.1.13
|
|
40
|
+
|
|
41
|
+
- 将 `@michengai/dsh-codex-ui` 固定为 `0.2.81`;其他 Suite 成员继续使用当前已验证版本。
|
|
42
|
+
|
|
43
|
+
发布包:[`@michengai/dsh-codex-ui@0.2.81`](https://www.npmjs.com/package/@michengai/dsh-codex-ui/v/0.2.81) 与 [`@michengai/dsh-codex-suite@0.1.13`](https://www.npmjs.com/package/@michengai/dsh-codex-suite/v/0.1.13)。
|
|
44
|
+
|
|
7
45
|
## 0.2.80 — 2026-08-23
|
|
8
46
|
|
|
9
47
|
配套版本:`@michengai/dsh-codex-suite@0.1.12`。
|
|
@@ -77,13 +115,3 @@
|
|
|
77
115
|
- 在窄轨态和展开态之间切换时保持工作区插槽挂载。
|
|
78
116
|
|
|
79
117
|
发布提交:[`b96d5a8`](https://github.com/MichengAI/dsh-codex-ui/commit/b96d5a8)。
|
|
80
|
-
|
|
81
|
-
## 0.2.76 — 2026-08-23
|
|
82
|
-
|
|
83
|
-
配套版本:`@michengai/dsh-codex-suite@0.1.7`。
|
|
84
|
-
|
|
85
|
-
### 修复
|
|
86
|
-
|
|
87
|
-
- 移除置顶工作区排序时可能重复出现的落点指示线。
|
|
88
|
-
|
|
89
|
-
发布提交:[`e2a38d1`](https://github.com/MichengAI/dsh-codex-ui/commit/e2a38d1)。
|
package/README.md
CHANGED
|
@@ -55,7 +55,7 @@ Conversation menu: rename, pin, unread, archive, fork, copy, and delete.
|
|
|
55
55
|
|
|
56
56
|
## Plugin combo
|
|
57
57
|
|
|
58
|
-
`@michengai/dsh-codex-suite`
|
|
58
|
+
`@michengai/dsh-codex-suite` provides a one-click installer that adds these six plugins to the same profile as **direct dependencies**:
|
|
59
59
|
|
|
60
60
|
| Plugin | npm package | Role |
|
|
61
61
|
| --- | --- | --- |
|
|
@@ -68,7 +68,7 @@ Conversation menu: rename, pin, unread, archive, fork, copy, and delete.
|
|
|
68
68
|
|
|
69
69
|
`dshmarket` stays optional. When it is installed, **Plugins** opens the market first.
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
Direct dependencies let **Settings → About** detect and update every plugin independently. The installer also migrates the legacy aggregate Suite without leaving duplicate patches behind.
|
|
72
72
|
|
|
73
73
|
## DSH product ecosystem
|
|
74
74
|
|
|
@@ -92,7 +92,7 @@ Copy one of the sentences below into DSH, Codex, or WorkBuddy and let that agent
|
|
|
92
92
|
From npm:
|
|
93
93
|
|
|
94
94
|
```text
|
|
95
|
-
|
|
95
|
+
Use the one-click installer to add all six DSH Codex Suite members as direct dependencies of my local web profile: npx --yes @michengai/dsh-codex-suite@latest --profile web. Confirm its configuration check succeeds, then remind me to restart DSH Web and hard-refresh the browser.
|
|
96
96
|
```
|
|
97
97
|
|
|
98
98
|
UI only:
|
|
@@ -107,7 +107,7 @@ Install the latest DSH plugin @michengai/dsh-codex-ui into my local web profile
|
|
|
107
107
|
| Codex | Send one of the sentences above to Codex and let it install locally. |
|
|
108
108
|
| WorkBuddy | Send one of the sentences above to WorkBuddy. |
|
|
109
109
|
|
|
110
|
-
|
|
110
|
+
The installer needs the current `dsh` on PATH. Set `DSH_BIN` when the executable lives elsewhere.
|
|
111
111
|
|
|
112
112
|
### Install the complete suite
|
|
113
113
|
|
|
@@ -116,13 +116,20 @@ This is the one-click combo. Run it from any PowerShell directory:
|
|
|
116
116
|
```powershell
|
|
117
117
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
|
118
118
|
$OutputEncoding = [System.Text.Encoding]::UTF8
|
|
119
|
-
|
|
120
|
-
dsh --profile web --dump-config
|
|
119
|
+
npx --yes @michengai/dsh-codex-suite@latest --profile web
|
|
121
120
|
```
|
|
122
121
|
|
|
123
|
-
|
|
122
|
+
The installer reads the exact member versions verified by that Suite release, adds all six members as direct profile dependencies in one `dsh plugin add`, and finishes with `dsh --profile web --dump-config`. Replace `@latest` with a Suite version to pin the whole set.
|
|
123
|
+
|
|
124
|
+
Restart DSH Web and hard-refresh the browser. Existing members are aligned in place; a legacy `@michengai/dsh-codex-suite` aggregate dependency is removed only after all six direct members have been staged.
|
|
125
|
+
|
|
126
|
+
Use the same command with another profile name for a clean custom Web profile:
|
|
127
|
+
|
|
128
|
+
```powershell
|
|
129
|
+
npx --yes @michengai/dsh-codex-suite@latest --profile codex
|
|
130
|
+
```
|
|
124
131
|
|
|
125
|
-
|
|
132
|
+
The installer stays in the current `DSH_HOME` and places DSH's built-in `@deepseek-ai/dsh-web-app` before the member bundles. It neither creates a separate Home nor reinstalls the official Web package.
|
|
126
133
|
|
|
127
134
|
### Install Codex UI only
|
|
128
135
|
|
package/README.zh-CN.md
CHANGED
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
|
|
56
56
|
## 插件组合
|
|
57
57
|
|
|
58
|
-
`@michengai/dsh-codex-suite`
|
|
58
|
+
`@michengai/dsh-codex-suite` 提供一键安装器,会把下面 6 个插件作为**直接依赖**装进同一个 profile:
|
|
59
59
|
|
|
60
60
|
| 插件 | npm 包 | 作用 |
|
|
61
61
|
| --- | --- | --- |
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
|
|
69
69
|
`dshmarket` 仍是可选项。已安装时,「插件」入口会优先进入市场。
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
直接依赖让「设置 → 关于」能够分别检测和升级每个插件。安装器也会自动迁移旧版聚合 Suite,避免聚合 patch 与独立 patch 冲突。
|
|
72
72
|
|
|
73
73
|
## DSH 产品生态
|
|
74
74
|
|
|
@@ -92,7 +92,7 @@ Codex UI 既可以独立安装,也可以随桌面端或 Web 套件一起使用
|
|
|
92
92
|
从 npm 安装完整套件:
|
|
93
93
|
|
|
94
94
|
```text
|
|
95
|
-
|
|
95
|
+
请用一键安装器把 DSH Codex Suite 的六个成员作为直接依赖装进本机 web profile,执行:npx --yes @michengai/dsh-codex-suite@latest --profile web。确认安装器完成配置检查,并提醒我重启 DSH Web 后硬刷新浏览器。
|
|
96
96
|
```
|
|
97
97
|
|
|
98
98
|
只安装 Codex UI:
|
|
@@ -107,7 +107,7 @@ Codex UI 既可以独立安装,也可以随桌面端或 Web 套件一起使用
|
|
|
107
107
|
| Codex | 把上面其中一句发给 Codex,让它在本机执行安装。 |
|
|
108
108
|
| WorkBuddy | 把上面其中一句发给 WorkBuddy。 |
|
|
109
109
|
|
|
110
|
-
|
|
110
|
+
一键安装器需要能从 PATH 找到当前 DSH;也可以用 `DSH_BIN` 指定 `dsh` 可执行文件。
|
|
111
111
|
|
|
112
112
|
### 安装完整套件
|
|
113
113
|
|
|
@@ -116,13 +116,20 @@ Codex UI 既可以独立安装,也可以随桌面端或 Web 套件一起使用
|
|
|
116
116
|
```powershell
|
|
117
117
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
|
118
118
|
$OutputEncoding = [System.Text.Encoding]::UTF8
|
|
119
|
-
|
|
120
|
-
dsh --profile web --dump-config
|
|
119
|
+
npx --yes @michengai/dsh-codex-suite@latest --profile web
|
|
121
120
|
```
|
|
122
121
|
|
|
123
|
-
|
|
122
|
+
安装器会读取该 Suite 版本验证过的精确成员版本,用一次 `dsh plugin add` 将六个成员写成 profile 的直接依赖,并在最后运行 `dsh --profile web --dump-config`。需要钉死一组版本时,把 `@latest` 换成具体 Suite 版本。
|
|
123
|
+
|
|
124
|
+
安装后重启 DSH Web 并硬刷新浏览器。已有成员会原地对齐版本;旧版 `@michengai/dsh-codex-suite` 聚合依赖会在六个成员提升完成后自动移除。
|
|
125
|
+
|
|
126
|
+
新建自定义 Web profile 也使用同一命令,只需改 profile 名:
|
|
127
|
+
|
|
128
|
+
```powershell
|
|
129
|
+
npx --yes @michengai/dsh-codex-suite@latest --profile codex
|
|
130
|
+
```
|
|
124
131
|
|
|
125
|
-
|
|
132
|
+
安装器会复用当前 `DSH_HOME`,并把 DSH 自带的 `@deepseek-ai/dsh-web-app` 放到成员 bundle 之前;不会创建独立 Home,也不会重新安装官方 Web 包。
|
|
126
133
|
|
|
127
134
|
### 只安装 Codex UI
|
|
128
135
|
|
package/dist/client.js
CHANGED
|
@@ -3932,7 +3932,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3932
3932
|
//#region src/client/AboutSection.tsx
|
|
3933
3933
|
const endpoint = "/api/michengai/codex-ui/dependencies";
|
|
3934
3934
|
const stylesheet$2 = `
|
|
3935
|
-
.dcu-about{color:var(--dsw-alias-label-primary)}.dcu-about h2{margin:0;font-size:20px;line-height:28px}.dcu-about-intro{margin:6px 0 22px;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:20px}.dcu-about h3{margin:24px 0 8px;font-size:14px;line-height:20px}.dcu-about-features{margin:0;padding-left:20px;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:24px}.dcu-about-dependencies{overflow:hidden;border:1px solid var(--dsw-alias-border-l2);border-radius:10px}.dcu-about-dependency{display:flex;align-items:center;gap:12px;min-height:64px;padding:12px;border-bottom:1px solid var(--dsw-alias-border-l2)}.dcu-about-dependency:last-child{border-bottom:0}.dcu-about-copy{min-width:0;flex:1}.dcu-about-name{font-size:13px;font-weight:600}.dcu-about-package{overflow:hidden;margin-top:2px;color:var(--dsw-alias-label-tertiary);font-size:12px;text-overflow:ellipsis;white-space:nowrap}.dcu-about-status{display:flex;align-items:center;gap:5px;font-size:12px}.dcu-about-status[data-installed=true]{color:var(--dsw-alias-state-success-primary)}.dcu-about-status[data-installed=false]{color:var(--dsw-alias-state-error-primary)}.dcu-about-status[data-update=true]{color:var(--dsw-alias-state-warning-primary)}.dcu-about-install{display:inline-flex;align-items:center;gap:5px;border:1px solid var(--dsw-alias-border-l2);border-radius:7px;padding:6px 9px;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:12px;cursor:pointer}.dcu-about-install:hover:not(:disabled){background:var(--dsw-specific-menu-item-hover)}.dcu-about-install:disabled{cursor:wait;opacity:.65}.dcu-about-message{margin:10px 0 0;border-radius:8px;padding:9px 10px;background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 12%,transparent);color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}.dcu-about-message[data-error=true]{background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 12%,transparent);color:var(--dsw-alias-state-error-primary)}
|
|
3935
|
+
.dcu-about{color:var(--dsw-alias-label-primary)}.dcu-about h2{margin:0;font-size:20px;line-height:28px}.dcu-about-intro{margin:6px 0 22px;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:20px}.dcu-about h3{margin:24px 0 8px;font-size:14px;line-height:20px}.dcu-about-features{margin:0;padding-left:20px;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:24px}.dcu-about-dependencies-heading{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:24px}.dcu-about-dependencies-heading h3{margin:0}.dcu-about-dependencies-heading+.dcu-about-intro{margin-bottom:14px}.dcu-about-dependencies{overflow:hidden;border:1px solid var(--dsw-alias-border-l2);border-radius:10px}.dcu-about-dependency{display:flex;align-items:center;gap:12px;min-height:64px;padding:12px;border-bottom:1px solid var(--dsw-alias-border-l2)}.dcu-about-dependency:last-child{border-bottom:0}.dcu-about-copy{min-width:0;flex:1}.dcu-about-name{font-size:13px;font-weight:600}.dcu-about-package{overflow:hidden;margin-top:2px;color:var(--dsw-alias-label-tertiary);font-size:12px;text-overflow:ellipsis;white-space:nowrap}.dcu-about-status{display:flex;align-items:center;gap:5px;font-size:12px}.dcu-about-status[data-installed=true]{color:var(--dsw-alias-state-success-primary)}.dcu-about-status[data-installed=false]{color:var(--dsw-alias-state-error-primary)}.dcu-about-status[data-update=true]{color:var(--dsw-alias-state-warning-primary)}.dcu-about-install{display:inline-flex;align-items:center;justify-content:center;gap:5px;min-height:32px;border:1px solid var(--dsw-alias-border-l2);border-radius:7px;padding:6px 9px;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:12px;cursor:pointer}.dcu-about-install:hover:not(:disabled){background:var(--dsw-specific-menu-item-hover)}.dcu-about-install:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}.dcu-about-install:disabled{cursor:wait;opacity:.65}.dcu-about-update-all{min-width:92px}.dcu-about-message{margin:10px 0 0;border-radius:8px;padding:9px 10px;background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 12%,transparent);color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}.dcu-about-message[data-error=true]{background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 12%,transparent);color:var(--dsw-alias-state-error-primary)}
|
|
3936
3936
|
`;
|
|
3937
3937
|
function isDependencyStatus(value) {
|
|
3938
3938
|
if (value === null || typeof value !== "object") return false;
|
|
@@ -4030,6 +4030,34 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
4030
4030
|
if (alive.current) setInstalling(void 0);
|
|
4031
4031
|
}
|
|
4032
4032
|
};
|
|
4033
|
+
const updateAll = async () => {
|
|
4034
|
+
if (installingRef.current !== void 0) return;
|
|
4035
|
+
installingRef.current = "all";
|
|
4036
|
+
setInstalling("all");
|
|
4037
|
+
setMessage(void 0);
|
|
4038
|
+
try {
|
|
4039
|
+
const response = await fetch(`${endpoint}?action=update-all`, { method: "POST" });
|
|
4040
|
+
const payload = await response.json();
|
|
4041
|
+
if (!response.ok || !Array.isArray(payload.dependencies) || !payload.dependencies.every(isDependencyStatus)) throw new Error(typeof payload.error === "string" ? payload.error : t("about.installFailed"));
|
|
4042
|
+
if (!alive.current) return;
|
|
4043
|
+
setDependencies(payload.dependencies);
|
|
4044
|
+
setState("ready");
|
|
4045
|
+
setMessage({
|
|
4046
|
+
error: false,
|
|
4047
|
+
text: payload.restartRequired === false ? t("about.upToDate") : t("about.restartRequired")
|
|
4048
|
+
});
|
|
4049
|
+
} catch (error) {
|
|
4050
|
+
if (!alive.current) return;
|
|
4051
|
+
setMessage({
|
|
4052
|
+
error: true,
|
|
4053
|
+
text: error instanceof Error ? error.message : t("about.installFailed")
|
|
4054
|
+
});
|
|
4055
|
+
} finally {
|
|
4056
|
+
installingRef.current = void 0;
|
|
4057
|
+
if (alive.current) setInstalling(void 0);
|
|
4058
|
+
}
|
|
4059
|
+
};
|
|
4060
|
+
const updateCount = dependencies.filter((dependency) => dependency.installed && dependency.updateAvailable).length;
|
|
4033
4061
|
const title = (id) => t(`about.dependency.${id}`);
|
|
4034
4062
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
4035
4063
|
ref: root,
|
|
@@ -4054,20 +4082,35 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
4054
4082
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: t("about.feature.navigator") })
|
|
4055
4083
|
]
|
|
4056
4084
|
}),
|
|
4057
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
4085
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4086
|
+
className: "dcu-about-dependencies-heading",
|
|
4087
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("about.dependencies") }), state === "ready" && updateCount > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
4088
|
+
className: "dcu-about-install dcu-about-update-all",
|
|
4089
|
+
type: "button",
|
|
4090
|
+
"aria-busy": installing === "all",
|
|
4091
|
+
disabled: installing !== void 0,
|
|
4092
|
+
onClick: () => {
|
|
4093
|
+
updateAll();
|
|
4094
|
+
},
|
|
4095
|
+
children: [installing === "all" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconLoadingOutline16, { size: 14 }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconDownloadOutline16, { size: 14 }), installing === "all" ? t("about.updatingAll") : t("about.updateAll")]
|
|
4096
|
+
})]
|
|
4097
|
+
}),
|
|
4058
4098
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4059
4099
|
className: "dcu-about-intro",
|
|
4060
4100
|
children: t("about.dependenciesDescription")
|
|
4061
4101
|
}),
|
|
4062
4102
|
state === "loading" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4063
4103
|
className: "dcu-about-message",
|
|
4104
|
+
role: "status",
|
|
4064
4105
|
children: t("about.loading")
|
|
4065
4106
|
}) : state === "failed" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4066
4107
|
className: "dcu-about-message",
|
|
4067
4108
|
"data-error": "true",
|
|
4109
|
+
role: "alert",
|
|
4068
4110
|
children: t("about.statusFailed")
|
|
4069
4111
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4070
4112
|
className: "dcu-about-dependencies",
|
|
4113
|
+
"aria-busy": installing !== void 0,
|
|
4071
4114
|
children: dependencies.map((dependency) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
|
|
4072
4115
|
className: "dcu-about-dependency",
|
|
4073
4116
|
children: [
|
|
@@ -4106,6 +4149,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
4106
4149
|
message !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4107
4150
|
className: "dcu-about-message",
|
|
4108
4151
|
"data-error": message.error,
|
|
4152
|
+
role: message.error ? "alert" : "status",
|
|
4109
4153
|
children: message.text
|
|
4110
4154
|
})
|
|
4111
4155
|
]
|
|
@@ -4289,7 +4333,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
4289
4333
|
"about.feature.conversation": "保留原生消息、工具调用、输入、权限和模型选择,仅调整容器视觉",
|
|
4290
4334
|
"about.feature.navigator": "当前会话提供轮次缩略导航,可快速跳转至每一次用户提问",
|
|
4291
4335
|
"about.dependencies": "配套管理插件",
|
|
4292
|
-
"about.dependenciesDescription": "
|
|
4336
|
+
"about.dependenciesDescription": "每个配套插件都可单独安装和更新,也可一键更新所有可更新项。可分别检查 Codex UI、专家、技能、归档、IM、定时任务和第三方插件市场。",
|
|
4293
4337
|
"about.loading": "正在读取依赖安装状态…",
|
|
4294
4338
|
"about.statusFailed": "暂时无法读取依赖安装状态。",
|
|
4295
4339
|
"about.installed": "已安装",
|
|
@@ -4298,6 +4342,9 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
4298
4342
|
"about.install": "安装",
|
|
4299
4343
|
"about.update": "更新",
|
|
4300
4344
|
"about.installing": "安装中",
|
|
4345
|
+
"about.updateAll": "全部更新",
|
|
4346
|
+
"about.updatingAll": "更新中",
|
|
4347
|
+
"about.upToDate": "所有已安装插件均为最新版本。",
|
|
4301
4348
|
"about.installFailed": "依赖安装失败,请稍后重试。",
|
|
4302
4349
|
"about.restartRequired": "正在热更新插件,窗口会自动刷新。",
|
|
4303
4350
|
"about.dependency.dsh": "DeepSeek Harness",
|
|
@@ -4408,7 +4455,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
4408
4455
|
"about.feature.conversation": "Keeps native messages, tool calls, composer, permissions, and model selection while refining the container visuals",
|
|
4409
4456
|
"about.feature.navigator": "Navigate directly to each user prompt with the current conversation turn navigator",
|
|
4410
4457
|
"about.dependencies": "Companion management plugins",
|
|
4411
|
-
"about.dependenciesDescription": "
|
|
4458
|
+
"about.dependenciesDescription": "Install or update each companion plugin separately, or update every available plugin at once. Check Codex UI, expert, skill, archive, IM, scheduled-task, and marketplace plugins on their own.",
|
|
4412
4459
|
"about.loading": "Loading dependency status…",
|
|
4413
4460
|
"about.statusFailed": "Dependency status is temporarily unavailable.",
|
|
4414
4461
|
"about.installed": "Installed",
|
|
@@ -4417,6 +4464,9 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
4417
4464
|
"about.install": "Install",
|
|
4418
4465
|
"about.update": "Update",
|
|
4419
4466
|
"about.installing": "Installing",
|
|
4467
|
+
"about.updateAll": "Update all",
|
|
4468
|
+
"about.updatingAll": "Updating",
|
|
4469
|
+
"about.upToDate": "All installed plugins are up to date.",
|
|
4420
4470
|
"about.installFailed": "Dependency installation failed. Try again later.",
|
|
4421
4471
|
"about.restartRequired": "Updating plugins now. The window will refresh automatically.",
|
|
4422
4472
|
"about.dependency.dsh": "DeepSeek Harness",
|
package/dist/index.mjs
CHANGED
|
@@ -7,10 +7,10 @@ import { randomUUID } from "node:crypto";
|
|
|
7
7
|
//#region src/dependencies.ts
|
|
8
8
|
const SUITE_PACKAGE = "@michengai/dsh-codex-suite";
|
|
9
9
|
const SUITE_MEMBER_PACKAGES = [
|
|
10
|
+
"@michengai/dsh-archive-manager",
|
|
10
11
|
"@michengai/dsh-codex-ui",
|
|
11
|
-
"@michengai/dsh-agency-agents",
|
|
12
12
|
"@michengai/dsh-skills-manager",
|
|
13
|
-
"@michengai/dsh-
|
|
13
|
+
"@michengai/dsh-agency-agents",
|
|
14
14
|
"@michengai/dsh-im-connect",
|
|
15
15
|
"@michengai/dsh-automation"
|
|
16
16
|
];
|
|
@@ -122,6 +122,15 @@ async function installedPackageVersion(packageName) {
|
|
|
122
122
|
function isManagedPackageInstalled(input) {
|
|
123
123
|
return input.declared && input.installedVersion !== void 0 && input.installedVersion !== "";
|
|
124
124
|
}
|
|
125
|
+
/** 旧 Suite 对其六个成员拥有声明权;迁移成直接依赖前也应显示真实安装版本。 */
|
|
126
|
+
function isManagedPackageDeclared(packageName, declared) {
|
|
127
|
+
return declared.includes(packageName) || declared.includes("@michengai/dsh-codex-suite") && SUITE_MEMBER_PACKAGES.includes(packageName);
|
|
128
|
+
}
|
|
129
|
+
/** 更新旧 Suite 中任一成员时,必须一次提升全部成员,避免移除 Suite 后只剩一个插件。 */
|
|
130
|
+
function directPackagesForInstall(requested, declared) {
|
|
131
|
+
const migrateSuite = declared.includes("@michengai/dsh-codex-suite") && requested.some((packageName) => SUITE_MEMBER_PACKAGES.includes(packageName));
|
|
132
|
+
return [...new Set(migrateSuite ? [...SUITE_MEMBER_PACKAGES, ...requested] : requested)];
|
|
133
|
+
}
|
|
125
134
|
/** npm latest 查询缓存有效期:避免每次打开“关于”页都打 7 个 registry 请求。 */
|
|
126
135
|
const LATEST_CACHE_TTL_MS = 3e5;
|
|
127
136
|
const latestCache = /* @__PURE__ */ new Map();
|
|
@@ -227,7 +236,7 @@ async function dependencyStatuses() {
|
|
|
227
236
|
const declaredNames = await declaredPluginNames();
|
|
228
237
|
return Promise.all(MANAGED_DEPENDENCIES.map(async (dependency) => {
|
|
229
238
|
const version = await installedPackageVersion(dependency.packageName);
|
|
230
|
-
const declared = isOfficialRuntimePackage(dependency.packageName) ||
|
|
239
|
+
const declared = isOfficialRuntimePackage(dependency.packageName) || isManagedPackageDeclared(dependency.packageName, declaredNames);
|
|
231
240
|
if (version === void 0 || !isManagedPackageInstalled({
|
|
232
241
|
installedVersion: version,
|
|
233
242
|
declared
|
|
@@ -419,38 +428,89 @@ async function installDependency(id, requestHotUpdate = requestDesktopHotUpdate)
|
|
|
419
428
|
if (installing) throw new Error("已有依赖安装正在进行,请等待完成后再试。");
|
|
420
429
|
installing = true;
|
|
421
430
|
try {
|
|
422
|
-
return await
|
|
431
|
+
return await installDependenciesLocked([id], requestHotUpdate);
|
|
423
432
|
} finally {
|
|
424
433
|
installing = false;
|
|
425
434
|
}
|
|
426
435
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
436
|
+
/** 只挑选已安装且确有新版本的插件,缺失插件仍交给各行的“安装”按钮。 */
|
|
437
|
+
function updatableDependencyIds(statuses) {
|
|
438
|
+
return statuses.filter((status) => status.installed && status.updateAvailable).map((status) => status.id);
|
|
439
|
+
}
|
|
440
|
+
/** 把所有待更新版本一次写入清单,最后只请求一次桌面热更新。 */
|
|
441
|
+
async function updateAllDependencies(requestHotUpdate = requestDesktopHotUpdate) {
|
|
442
|
+
if (installing) throw new Error("已有依赖安装正在进行,请等待完成后再试。");
|
|
443
|
+
installing = true;
|
|
444
|
+
try {
|
|
445
|
+
const current = await dependencyStatuses();
|
|
446
|
+
const ids = updatableDependencyIds(current);
|
|
447
|
+
if (ids.length === 0) return {
|
|
448
|
+
dependencies: current,
|
|
449
|
+
updatedCount: 0
|
|
450
|
+
};
|
|
451
|
+
return {
|
|
452
|
+
dependencies: await installDependenciesLocked(ids, requestHotUpdate),
|
|
453
|
+
updatedCount: ids.length
|
|
454
|
+
};
|
|
455
|
+
} finally {
|
|
456
|
+
installing = false;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
async function installDependenciesLocked(ids, requestHotUpdate) {
|
|
460
|
+
const dependencies = [...new Set(ids)].map((id) => {
|
|
461
|
+
const dependency = managedDependency(id);
|
|
462
|
+
if (dependency === void 0) throw new Error("不支持安装该依赖。");
|
|
463
|
+
return dependency;
|
|
464
|
+
});
|
|
432
465
|
const declared = await declaredPluginNames();
|
|
433
|
-
const
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
466
|
+
const requestedTargets = await Promise.all(dependencies.map(async (dependency) => {
|
|
467
|
+
const latestVersion = await npmLatestVersion(dependency.packageName);
|
|
468
|
+
if (latestVersion === void 0) throw new Error("无法获取 npm 最新版本,请检查网络或 npm registry 后重试。");
|
|
469
|
+
const packageName = resolveDshPluginTarget(dependency.packageName, declared);
|
|
470
|
+
const version = packageName === dependency.packageName ? latestVersion : await npmLatestVersion(packageName);
|
|
471
|
+
if (version === void 0) throw new Error("无法获取 npm 最新版本,请检查网络或 npm registry 后重试。");
|
|
472
|
+
return {
|
|
473
|
+
packageName,
|
|
474
|
+
version
|
|
475
|
+
};
|
|
476
|
+
}));
|
|
477
|
+
const requestedVersions = new Map(requestedTargets.map((target) => [target.packageName, target.version]));
|
|
478
|
+
const targetPackages = directPackagesForInstall(requestedTargets.map((target) => target.packageName), declared);
|
|
479
|
+
const targets = await Promise.all(targetPackages.map(async (packageName) => {
|
|
480
|
+
const requestedVersion = requestedVersions.get(packageName);
|
|
481
|
+
if (requestedVersion !== void 0) return {
|
|
482
|
+
packageName,
|
|
483
|
+
version: requestedVersion
|
|
484
|
+
};
|
|
485
|
+
const version = await installedPackageVersion(packageName) ?? await npmLatestVersion(packageName);
|
|
486
|
+
if (version === void 0) throw new Error("无法读取 Suite 成员版本,请检查 npm 安装后重试。");
|
|
487
|
+
return {
|
|
488
|
+
packageName,
|
|
489
|
+
version
|
|
490
|
+
};
|
|
491
|
+
}));
|
|
492
|
+
const remove = [...new Set(targets.flatMap((target) => pluginsToRemoveBeforeInstall(declared, target.packageName)))];
|
|
493
|
+
for (const target of targets) {
|
|
494
|
+
await ensureLatestReleaseAllowed(target.packageName, target.version);
|
|
495
|
+
if (!isOfficialRuntimePackage(target.packageName)) await recordDeclaredVersion(target.packageName, target.version);
|
|
496
|
+
await recordPendingUpdate(target.packageName, target.version);
|
|
497
|
+
}
|
|
440
498
|
if (remove.length > 0) await runDshPlugin(["remove", ...remove]);
|
|
441
499
|
if (requestHotUpdate()) return dependencyStatuses();
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
500
|
+
for (const target of targets) {
|
|
501
|
+
try {
|
|
502
|
+
await runDshPlugin([
|
|
503
|
+
"add",
|
|
504
|
+
`${target.packageName}@${target.version}`,
|
|
505
|
+
"--registry=https://registry.npmjs.org/"
|
|
506
|
+
]);
|
|
507
|
+
} catch (error) {
|
|
508
|
+
if (isRestartableInstallError(error)) return dependencyStatuses();
|
|
509
|
+
throw error;
|
|
510
|
+
}
|
|
511
|
+
if (await installedPackageVersion(target.packageName) !== target.version) return dependencyStatuses();
|
|
512
|
+
await removePendingUpdate(target.packageName);
|
|
451
513
|
}
|
|
452
|
-
if (await installedPackageVersion(target) !== targetVersion) return dependencyStatuses();
|
|
453
|
-
await removePendingUpdate(target);
|
|
454
514
|
return dependencyStatuses();
|
|
455
515
|
}
|
|
456
516
|
//#endregion
|
|
@@ -662,6 +722,25 @@ function apply(ctx) {
|
|
|
662
722
|
response.end(JSON.stringify({ error: "已拒绝跨站请求。" }));
|
|
663
723
|
return;
|
|
664
724
|
}
|
|
725
|
+
if (url.searchParams.get("action") === "update-all") {
|
|
726
|
+
let restartAfterResponse = false;
|
|
727
|
+
const { dependencies, updatedCount } = await updateAllDependencies(() => {
|
|
728
|
+
restartAfterResponse = typeof process.send === "function";
|
|
729
|
+
return restartAfterResponse;
|
|
730
|
+
});
|
|
731
|
+
response.writeHead(200, {
|
|
732
|
+
"content-type": "application/json; charset=utf-8",
|
|
733
|
+
"cache-control": "no-store"
|
|
734
|
+
});
|
|
735
|
+
response.end(JSON.stringify({
|
|
736
|
+
dependencies,
|
|
737
|
+
restartRequired: updatedCount > 0
|
|
738
|
+
}));
|
|
739
|
+
if (restartAfterResponse) setTimeout(() => {
|
|
740
|
+
requestDesktopHotUpdate();
|
|
741
|
+
}, 150).unref?.();
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
665
744
|
let restartAfterResponse = false;
|
|
666
745
|
const dependencies = await installDependency(url.searchParams.get("dependency"), () => {
|
|
667
746
|
restartAfterResponse = typeof process.send === "function";
|