@michengai/dsh-codex-ui 0.2.79 → 0.2.81

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 ADDED
@@ -0,0 +1,100 @@
1
+ # Changelog
2
+
3
+ [简体中文](CHANGELOG.zh-CN.md)
4
+
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
+
7
+ ## 0.2.81 — 2026-08-24
8
+
9
+ Companion release: `@michengai/dsh-codex-suite@0.1.13`.
10
+
11
+ ### Added
12
+
13
+ - Added an **Update all** action beside Companion management plugins whenever installed plugins have updates available.
14
+ - Kept missing plugins on their existing per-row install path instead of installing them implicitly during a bulk update.
15
+
16
+ ### Reliability and accessibility
17
+
18
+ - 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.
19
+ - Preserved individual install and update actions while preventing overlapping requests.
20
+ - Added visible loading feedback, keyboard focus treatment, accessible busy/status announcements, bilingual copy, and regression coverage for the batch selection and endpoint contract.
21
+
22
+ ### Suite 0.1.13
23
+
24
+ - Pinned `@michengai/dsh-codex-ui` to `0.2.81`; all other Suite member pins remain on their currently verified releases.
25
+
26
+ 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).
27
+
28
+ ## 0.2.80 — 2026-08-23
29
+
30
+ Companion release: `@michengai/dsh-codex-suite@0.1.12`.
31
+
32
+ ### Documentation
33
+
34
+ - Added bilingual changelogs covering the five most recent UI releases.
35
+ - Linked the release history from both README editions and included it in the npm package.
36
+
37
+ ### Suite 0.1.12
38
+
39
+ - Refreshed every bundled plugin to the changelog release published on 2026-08-23.
40
+ - Pinned Agency Agents `0.1.21`, Archive Manager `0.1.13`, Automation `0.1.14`, IM Connect `0.1.23`, and Skills Manager `0.1.24`.
41
+
42
+ Published packages: [`@michengai/dsh-codex-ui@0.2.80`](https://www.npmjs.com/package/@michengai/dsh-codex-ui/v/0.2.80) and [`@michengai/dsh-codex-suite@0.1.12`](https://www.npmjs.com/package/@michengai/dsh-codex-suite/v/0.1.12).
43
+
44
+ ## 0.2.79 — 2026-08-23
45
+
46
+ Companion release: `@michengai/dsh-codex-suite@0.1.11`.
47
+
48
+ ### Fixed
49
+
50
+ - Removed the delayed expanded state that could stretch compact navigation icons across an already-wide sidebar.
51
+ - Made expansion reveal the fixed-width wide layout immediately while the host column clips it during motion.
52
+ - Made collapse fade the wide layout for 140 ms before switching to the compact rail.
53
+ - Anchored the 56 px compact rail to the left so its icons no longer drift while the host column changes width.
54
+
55
+ ### Performance and accessibility
56
+
57
+ - Kept the workspace tree at its target width during the host transition, avoiding per-frame list reflow or remounting.
58
+ - Preserved the reduced-motion path for users who disable interface motion.
59
+ - Added regression coverage for both collapse and re-expansion without workspace-tree rerenders.
60
+
61
+ ### Suite 0.1.11
62
+
63
+ - Pinned `@michengai/dsh-codex-ui` to `0.2.79`.
64
+ - Updated `@michengai/dsh-im-connect` to `0.1.22`.
65
+
66
+ Release commit: [`e8d2f4b`](https://github.com/MichengAI/dsh-codex-ui/commit/e8d2f4b).
67
+
68
+ ## 0.2.78 — 2026-08-23
69
+
70
+ Companion releases: `@michengai/dsh-codex-suite@0.1.9` and dependency-only refresh `0.1.10`.
71
+
72
+ ### Changed
73
+
74
+ - Restored the host sidebar-width transition after the performance hardening in `0.2.77`.
75
+ - Added compositor-only reveal motion for expanded and compact shells, search, and workspace sections.
76
+ - Kept the large workspace tree mounted while switching sidebar modes.
77
+
78
+ ### Suite 0.1.9–0.1.10
79
+
80
+ - Refreshed all Suite member pins.
81
+ - Suite `0.1.10` advanced Automation to `0.1.13` and IM Connect to `0.1.20` without changing the UI package version.
82
+
83
+ Release commits: [`b7980e3`](https://github.com/MichengAI/dsh-codex-ui/commit/b7980e3), [`cc71abf`](https://github.com/MichengAI/dsh-codex-ui/commit/cc71abf).
84
+
85
+ ## 0.2.77 — 2026-08-23
86
+
87
+ Companion release: `@michengai/dsh-codex-suite@0.1.8`.
88
+
89
+ ### Added
90
+
91
+ - Persisted pinned workspaces in the DSH Host profile so they survive Desktop tray reloads and dynamic-port changes.
92
+ - Added safe client hydration, legacy local-storage migration, serialized writes, and protection against clearing pins from incomplete startup data.
93
+
94
+ ### Fixed
95
+
96
+ - Improved workspace and session drag-and-drop reliability and drop-target handling.
97
+ - Isolated search state and deferred filtering so typing does not rerender the workspace tree.
98
+ - Kept the workspace slot mounted across compact and expanded sidebar modes.
99
+
100
+ Release commit: [`b96d5a8`](https://github.com/MichengAI/dsh-codex-ui/commit/b96d5a8).
@@ -0,0 +1,100 @@
1
+ # 更新日志
2
+
3
+ [English](CHANGELOG.md)
4
+
5
+ 本日志记录 DSH Codex UI 及其一键 Suite 最近发布的五个版本;更早的变更可查看 [Git 提交历史](https://github.com/MichengAI/dsh-codex-ui/commits/main)。
6
+
7
+ ## 0.2.81 — 2026-08-24
8
+
9
+ 配套版本:`@michengai/dsh-codex-suite@0.1.13`。
10
+
11
+ ### 新增
12
+
13
+ - 当已安装插件存在新版本时,在“配套管理插件”标题右侧显示 **全部更新** 操作。
14
+ - 缺失插件继续使用各自的行内安装入口,不会被批量更新隐式安装。
15
+
16
+ ### 可靠性与无障碍
17
+
18
+ - 通过一次 Host 请求登记全部选中版本,并在批次完整写入后只发送一次 Desktop 热更新信号;多个插件更新现在只会重载一次窗口。
19
+ - 保留单插件安装和更新入口,同时阻止重叠请求。
20
+ - 增加可见加载反馈、键盘焦点样式、可访问的忙碌/状态提示、中英文文案,以及批量筛选和接口约束的回归测试。
21
+
22
+ ### Suite 0.1.13
23
+
24
+ - 将 `@michengai/dsh-codex-ui` 固定为 `0.2.81`;其他 Suite 成员继续使用当前已验证版本。
25
+
26
+ 发布包:[`@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)。
27
+
28
+ ## 0.2.80 — 2026-08-23
29
+
30
+ 配套版本:`@michengai/dsh-codex-suite@0.1.12`。
31
+
32
+ ### 文档
33
+
34
+ - 新增中英文更新日志,展示最近五个 UI 发布版本。
35
+ - 在中英文 README 中加入更新日志入口,并将日志纳入 npm 包。
36
+
37
+ ### Suite 0.1.12
38
+
39
+ - 将全部聚合插件刷新到 2026-08-23 发布的更新日志版本。
40
+ - 固定 Agency Agents `0.1.21`、Archive Manager `0.1.13`、Automation `0.1.14`、IM Connect `0.1.23` 和 Skills Manager `0.1.24`。
41
+
42
+ 发布包:[`@michengai/dsh-codex-ui@0.2.80`](https://www.npmjs.com/package/@michengai/dsh-codex-ui/v/0.2.80) 与 [`@michengai/dsh-codex-suite@0.1.12`](https://www.npmjs.com/package/@michengai/dsh-codex-suite/v/0.1.12)。
43
+
44
+ ## 0.2.79 — 2026-08-23
45
+
46
+ 配套版本:`@michengai/dsh-codex-suite@0.1.11`。
47
+
48
+ ### 修复
49
+
50
+ - 移除展开阶段的额外等待,解决侧栏已经变宽、窄轨图标仍居中显示的问题。
51
+ - 展开时立即呈现固定宽度的宽态内容,由宿主侧栏列在动画过程中负责裁切。
52
+ - 收缩时先用 140ms 淡出宽态内容,再切换到窄轨。
53
+ - 将 56px 窄轨固定在左侧,避免图标跟随宿主列宽变化而横向漂移。
54
+
55
+ ### 性能与无障碍
56
+
57
+ - 宿主动画期间保持工作区树的目标宽度,避免长列表逐帧重排或重新挂载。
58
+ - 保留减少动态效果模式,尊重用户的 `prefers-reduced-motion` 设置。
59
+ - 增加收缩和重新展开的双向回归测试,并验证工作区树不会额外渲染。
60
+
61
+ ### Suite 0.1.11
62
+
63
+ - 将 `@michengai/dsh-codex-ui` 固定为 `0.2.79`。
64
+ - 将 `@michengai/dsh-im-connect` 更新为 `0.1.22`。
65
+
66
+ 发布提交:[`e8d2f4b`](https://github.com/MichengAI/dsh-codex-ui/commit/e8d2f4b)。
67
+
68
+ ## 0.2.78 — 2026-08-23
69
+
70
+ 配套版本:`@michengai/dsh-codex-suite@0.1.9`,以及仅刷新依赖的 `0.1.10`。
71
+
72
+ ### 调整
73
+
74
+ - 在 `0.2.77` 的性能优化基础上恢复宿主侧栏宽度动画。
75
+ - 为展开态、窄轨态、搜索弹窗和工作区分区增加仅使用合成层的轻量显现动画。
76
+ - 侧栏模式切换时继续保留大型工作区树实例。
77
+
78
+ ### Suite 0.1.9–0.1.10
79
+
80
+ - 刷新 Suite 全部成员的固定版本。
81
+ - Suite `0.1.10` 将 Automation 更新到 `0.1.13`、IM Connect 更新到 `0.1.20`,UI 包版本保持不变。
82
+
83
+ 发布提交:[`b7980e3`](https://github.com/MichengAI/dsh-codex-ui/commit/b7980e3)、[`cc71abf`](https://github.com/MichengAI/dsh-codex-ui/commit/cc71abf)。
84
+
85
+ ## 0.2.77 — 2026-08-23
86
+
87
+ 配套版本:`@michengai/dsh-codex-suite@0.1.8`。
88
+
89
+ ### 新增
90
+
91
+ - 将置顶工作区持久化到 DSH Host Profile,使其在 Desktop 托盘重载和动态端口变化后仍可恢复。
92
+ - 增加安全的客户端水合、旧 localStorage 数据迁移、串行写入,以及启动数据不完整时的误清理保护。
93
+
94
+ ### 修复
95
+
96
+ - 提升工作区和会话拖放的可靠性,修正落点判断。
97
+ - 隔离搜索状态并延迟过滤,避免输入搜索词时重新渲染工作区树。
98
+ - 在窄轨态和展开态之间切换时保持工作区插槽挂载。
99
+
100
+ 发布提交:[`b96d5a8`](https://github.com/MichengAI/dsh-codex-ui/commit/b96d5a8)。
package/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  **Rebuild the DeepSeek Harness Web sidebar, workspace tree, search, and turn navigation in a Codex-style layout**
10
10
 
11
- [简体中文](README.zh-CN.md) · [Apache-2.0](LICENSE)
11
+ [简体中文](README.zh-CN.md) · [Changelog](CHANGELOG.md) · [Apache-2.0](LICENSE)
12
12
 
13
13
  [![License: Apache-2.0](https://img.shields.io/badge/License-Apache--2.0-blue.svg)](LICENSE)
14
14
  [![npm package](https://img.shields.io/npm/v/%40michengai%2Fdsh-codex-ui.svg?label=npm%20package)](https://www.npmjs.com/package/@michengai/dsh-codex-ui)
package/README.zh-CN.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  **为 DeepSeek Harness Web 重构 Codex 风格侧栏、工作区会话树、全局搜索和轮次导航**
10
10
 
11
- [English](README.md) · [Apache-2.0](LICENSE)
11
+ [English](README.md) · [更新日志](CHANGELOG.zh-CN.md) · [Apache-2.0](LICENSE)
12
12
 
13
13
  [![许可证:Apache-2.0](https://img.shields.io/badge/许可证-Apache--2.0-blue.svg)](LICENSE)
14
14
  [![npm package](https://img.shields.io/npm/v/%40michengai%2Fdsh-codex-ui.svg?label=npm%20package)](https://www.npmjs.com/package/@michengai/dsh-codex-ui)
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.jsx)("h3", { children: t("about.dependencies") }),
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": "每个配套插件都单独安装和更新,互不影响。可分别检查 Codex UI、专家、技能、归档、IM、定时任务和第三方插件市场。",
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": "Each companion plugin is installed and updated separately. Check Codex UI, expert, skill, archive, IM, scheduled-task, and marketplace plugins on their own.",
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
@@ -419,38 +419,74 @@ async function installDependency(id, requestHotUpdate = requestDesktopHotUpdate)
419
419
  if (installing) throw new Error("已有依赖安装正在进行,请等待完成后再试。");
420
420
  installing = true;
421
421
  try {
422
- return await installDependencyLocked(id, requestHotUpdate);
422
+ return await installDependenciesLocked([id], requestHotUpdate);
423
423
  } finally {
424
424
  installing = false;
425
425
  }
426
426
  }
427
- async function installDependencyLocked(id, requestHotUpdate) {
428
- const dependency = managedDependency(id);
429
- if (dependency === void 0) throw new Error("不支持安装该依赖。");
430
- const latestVersion = await npmLatestVersion(dependency.packageName);
431
- if (latestVersion === void 0) throw new Error("无法获取 npm 最新版本,请检查网络或 npm registry 后重试。");
427
+ /** 只挑选已安装且确有新版本的插件,缺失插件仍交给各行的“安装”按钮。 */
428
+ function updatableDependencyIds(statuses) {
429
+ return statuses.filter((status) => status.installed && status.updateAvailable).map((status) => status.id);
430
+ }
431
+ /** 把所有待更新版本一次写入清单,最后只请求一次桌面热更新。 */
432
+ async function updateAllDependencies(requestHotUpdate = requestDesktopHotUpdate) {
433
+ if (installing) throw new Error("已有依赖安装正在进行,请等待完成后再试。");
434
+ installing = true;
435
+ try {
436
+ const current = await dependencyStatuses();
437
+ const ids = updatableDependencyIds(current);
438
+ if (ids.length === 0) return {
439
+ dependencies: current,
440
+ updatedCount: 0
441
+ };
442
+ return {
443
+ dependencies: await installDependenciesLocked(ids, requestHotUpdate),
444
+ updatedCount: ids.length
445
+ };
446
+ } finally {
447
+ installing = false;
448
+ }
449
+ }
450
+ async function installDependenciesLocked(ids, requestHotUpdate) {
451
+ const dependencies = [...new Set(ids)].map((id) => {
452
+ const dependency = managedDependency(id);
453
+ if (dependency === void 0) throw new Error("不支持安装该依赖。");
454
+ return dependency;
455
+ });
432
456
  const declared = await declaredPluginNames();
433
- const target = resolveDshPluginTarget(dependency.packageName, declared);
434
- const targetVersion = target === dependency.packageName ? latestVersion : await npmLatestVersion(target);
435
- if (targetVersion === void 0) throw new Error("无法获取 npm 最新版本,请检查网络或 npm registry 后重试。");
436
- const remove = pluginsToRemoveBeforeInstall(declared, target);
437
- await ensureLatestReleaseAllowed(target, targetVersion);
438
- if (!isOfficialRuntimePackage(target)) await recordDeclaredVersion(target, targetVersion);
439
- await recordPendingUpdate(target, targetVersion);
457
+ const targets = await Promise.all(dependencies.map(async (dependency) => {
458
+ const latestVersion = await npmLatestVersion(dependency.packageName);
459
+ if (latestVersion === void 0) throw new Error("无法获取 npm 最新版本,请检查网络或 npm registry 后重试。");
460
+ const packageName = resolveDshPluginTarget(dependency.packageName, declared);
461
+ const version = packageName === dependency.packageName ? latestVersion : await npmLatestVersion(packageName);
462
+ if (version === void 0) throw new Error("无法获取 npm 最新版本,请检查网络或 npm registry 后重试。");
463
+ return {
464
+ packageName,
465
+ version
466
+ };
467
+ }));
468
+ const remove = [...new Set(targets.flatMap((target) => pluginsToRemoveBeforeInstall(declared, target.packageName)))];
469
+ for (const target of targets) {
470
+ await ensureLatestReleaseAllowed(target.packageName, target.version);
471
+ if (!isOfficialRuntimePackage(target.packageName)) await recordDeclaredVersion(target.packageName, target.version);
472
+ await recordPendingUpdate(target.packageName, target.version);
473
+ }
440
474
  if (remove.length > 0) await runDshPlugin(["remove", ...remove]);
441
475
  if (requestHotUpdate()) return dependencyStatuses();
442
- try {
443
- await runDshPlugin([
444
- "add",
445
- `${target}@${targetVersion}`,
446
- "--registry=https://registry.npmjs.org/"
447
- ]);
448
- } catch (error) {
449
- if (isRestartableInstallError(error)) return dependencyStatuses();
450
- throw error;
476
+ for (const target of targets) {
477
+ try {
478
+ await runDshPlugin([
479
+ "add",
480
+ `${target.packageName}@${target.version}`,
481
+ "--registry=https://registry.npmjs.org/"
482
+ ]);
483
+ } catch (error) {
484
+ if (isRestartableInstallError(error)) return dependencyStatuses();
485
+ throw error;
486
+ }
487
+ if (await installedPackageVersion(target.packageName) !== target.version) return dependencyStatuses();
488
+ await removePendingUpdate(target.packageName);
451
489
  }
452
- if (await installedPackageVersion(target) !== targetVersion) return dependencyStatuses();
453
- await removePendingUpdate(target);
454
490
  return dependencyStatuses();
455
491
  }
456
492
  //#endregion
@@ -662,6 +698,25 @@ function apply(ctx) {
662
698
  response.end(JSON.stringify({ error: "已拒绝跨站请求。" }));
663
699
  return;
664
700
  }
701
+ if (url.searchParams.get("action") === "update-all") {
702
+ let restartAfterResponse = false;
703
+ const { dependencies, updatedCount } = await updateAllDependencies(() => {
704
+ restartAfterResponse = typeof process.send === "function";
705
+ return restartAfterResponse;
706
+ });
707
+ response.writeHead(200, {
708
+ "content-type": "application/json; charset=utf-8",
709
+ "cache-control": "no-store"
710
+ });
711
+ response.end(JSON.stringify({
712
+ dependencies,
713
+ restartRequired: updatedCount > 0
714
+ }));
715
+ if (restartAfterResponse) setTimeout(() => {
716
+ requestDesktopHotUpdate();
717
+ }, 150).unref?.();
718
+ return;
719
+ }
665
720
  let restartAfterResponse = false;
666
721
  const dependencies = await installDependency(url.searchParams.get("dependency"), () => {
667
722
  restartAfterResponse = typeof process.send === "function";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@michengai/dsh-codex-ui",
3
- "version": "0.2.79",
3
+ "version": "0.2.81",
4
4
  "description": "以 Codex 风格重构 DSH Web 侧栏的独立客户端插件",
5
5
  "license": "Apache-2.0",
6
6
  "publishConfig": {
@@ -32,6 +32,8 @@
32
32
  "dist",
33
33
  "assets",
34
34
  "cordis.patch.yml",
35
+ "CHANGELOG.md",
36
+ "CHANGELOG.zh-CN.md",
35
37
  "LICENSE",
36
38
  "README.md",
37
39
  "README.zh-CN.md"