@michengai/dsh-codex-ui 1.1.22 → 1.1.23

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 CHANGED
@@ -4,6 +4,29 @@
4
4
 
5
5
  This changelog records recent releases of DSH Codex UI and its one-click installer. Earlier changes remain available in the [Git history](https://github.com/MichengAI/dsh-codex-ui/commits/main).
6
6
 
7
+ ## 1.1.23 - 2026-09-29
8
+
9
+ - Installing or updating other plugins from the About page in official DeepSeek Harness Desktop no longer crashes the desktop host.
10
+ - Those installs are written to the current desktop profile. Restart the app once afterward so the new plugin can load.
11
+
12
+ ## suite-installer-v1.0.29 - 2026-09-29
13
+
14
+ Install or maintain 11 first-party plugins in one step. Included plugins and versions:
15
+
16
+ - `@michengai/dsh-archive-manager@1.0.7`
17
+ - `@michengai/dsh-codex-ui@1.1.21`
18
+ - `@michengai/dsh-skills-manager@1.1.5`
19
+ - `@michengai/dsh-agency-agents@1.0.6`
20
+ - `@michengai/dsh-im-connect@0.1.57`
21
+ - `@michengai/dsh-automation@0.1.52`
22
+ - `@michengai/dsh-btw@0.1.14`
23
+ - `@michengai/dsh-simplify@0.1.11`
24
+ - `@michengai/dsh-pua@0.3.19`
25
+ - `@michengai/dsh-code-review@0.1.8`
26
+ - `@michengai/dsh-codex-pet@0.1.11`
27
+
28
+ The installer uses these exact versions for reproducible installation.
29
+
7
30
  ## 1.1.22 - 2026-09-29
8
31
 
9
32
  - Host support now starts at DSH `0.1.2-rc.1` and lists every release candidate through `0.2.0-rc.1`: `0.1.2-rc.1`, `0.1.5-rc.1`, `0.1.5-rc.2`, `0.1.5-rc.3`, `0.1.7-rc.1`, `0.1.7-rc.2`, and `0.2.0-rc.1`. This adds the previously missing `0.1.5-rc.3` and matches the other first-party plugins; `0.1.0-rc.8` and `0.1.1-rc.2` are no longer declared.
@@ -4,6 +4,29 @@
4
4
 
5
5
  本日志记录 DSH Codex UI 及其一键安装器的最近发布;更早的变更可查看 [Git 提交历史](https://github.com/MichengAI/dsh-codex-ui/commits/main)。
6
6
 
7
+ ## 1.1.23 - 2026-09-29
8
+
9
+ - 在官方 DeepSeek Harness 桌面端的关于页安装或更新其他插件时,不再把桌面宿主打崩。
10
+ - 安装会写入当前桌面 profile。装完后需要手动重启一次,新插件才会加载。
11
+
12
+ ## suite-installer-v1.0.29 - 2026-09-29
13
+
14
+ 一键维护安装 11 个自研插件。包含以下插件及版本:
15
+
16
+ - `@michengai/dsh-archive-manager@1.0.7`
17
+ - `@michengai/dsh-codex-ui@1.1.21`
18
+ - `@michengai/dsh-skills-manager@1.1.5`
19
+ - `@michengai/dsh-agency-agents@1.0.6`
20
+ - `@michengai/dsh-im-connect@0.1.57`
21
+ - `@michengai/dsh-automation@0.1.52`
22
+ - `@michengai/dsh-btw@0.1.14`
23
+ - `@michengai/dsh-simplify@0.1.11`
24
+ - `@michengai/dsh-pua@0.3.19`
25
+ - `@michengai/dsh-code-review@0.1.8`
26
+ - `@michengai/dsh-codex-pet@0.1.11`
27
+
28
+ 安装器使用这些精确版本执行安装,确保可复现。
29
+
7
30
  ## 1.1.22 - 2026-09-29
8
31
 
9
32
  - 宿主兼容范围从 DSH `0.1.2-rc.1` 起,逐个列出直到 `0.2.0-rc.1` 的全部候选版:`0.1.2-rc.1`、`0.1.5-rc.1`、`0.1.5-rc.2`、`0.1.5-rc.3`、`0.1.7-rc.1`、`0.1.7-rc.2` 与 `0.2.0-rc.1`。这补上了此前漏掉的 `0.1.5-rc.3`,并与其余自研插件保持一致;`0.1.0-rc.8` 与 `0.1.1-rc.2` 不再声明支持。
package/lib/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { apply as apply$1 } from "@deepseek-ai/dsh-client-ui-settings-general";
2
2
  import { spawn } from "node:child_process";
3
- import { existsSync } from "node:fs";
3
+ import { existsSync, readFileSync } from "node:fs";
4
4
  import { lstat, mkdir, open, readFile, readdir, realpath, rename, rm, unlink, writeFile } from "node:fs/promises";
5
5
  import { homedir } from "node:os";
6
6
  import { basename, dirname, isAbsolute, join, relative, resolve, sep, win32 } from "node:path";
@@ -205,17 +205,62 @@ function resolveDependencyRuntime(ctx, options = {}) {
205
205
  desktopPnpm
206
206
  };
207
207
  }
208
- const profileDir = resolve(env.DSH_PROFILE_DIR ?? resolve(home, ".dsh", "profiles", "web"));
208
+ const launched = optionalService(ctx, "profileContext");
209
+ const launchedDir = typeof launched?.dir === "string" && isAbsolute(launched.dir) ? resolve(launched.dir) : void 0;
210
+ const launchedName = validProfileName(launched?.name) ? launched.name : void 0;
211
+ const hostProfileDir = isOfficialDesktopHostEntry(argv[1]) && existsSync(resolve(cwd, "package.json")) ? resolve(cwd) : void 0;
212
+ const profileDir = launchedDir ?? hostProfileDir ?? resolve(env.DSH_PROFILE_DIR ?? resolve(home, ".dsh", "profiles", "web"));
209
213
  const selected = profileNameFromArgv(argv);
210
- const profileName = validProfileName(selected) ? selected : validProfileName(basename(profileDir)) ? basename(profileDir) : "web";
214
+ const profileName = launchedName ?? (validProfileName(selected) ? selected : validProfileName(basename(profileDir)) ? basename(profileDir) : "web");
215
+ const cliEntry = resolveCliFromInstallAnchor(launched?.installAnchor) ?? resolveCliBesideDesktopHost(argv[1]);
211
216
  const cliRuntimeRoot = argv[1] === void 0 ? void 0 : resolveDshRuntimeRoot(argv[1], cwd);
217
+ const anchorRoot = cliEntry === void 0 ? void 0 : resolveDshRuntimeRoot(cliEntry);
218
+ const runtimeRoots = [
219
+ env.DSH_RUNTIME_DIR,
220
+ anchorRoot,
221
+ cliRuntimeRoot
222
+ ].filter((root) => root !== void 0 && root !== "");
223
+ const pluginEnv = stringEnvironment(launched?.packageManager?.env);
212
224
  return {
213
225
  environmentKind: "cli",
214
226
  profileName,
215
227
  profileDir,
216
- runtimeRoots: [env.DSH_RUNTIME_DIR, cliRuntimeRoot].filter((root) => root !== void 0 && root !== "")
228
+ runtimeRoots,
229
+ ...cliEntry === void 0 ? {} : { cliEntry },
230
+ ...pluginEnv === void 0 ? {} : { pluginEnv }
217
231
  };
218
232
  }
233
+ function stringEnvironment(value) {
234
+ if (value === null || typeof value !== "object") return void 0;
235
+ const env = {};
236
+ for (const [key, item] of Object.entries(value)) if (typeof item === "string") env[key] = item;
237
+ return Object.keys(env).length === 0 ? void 0 : env;
238
+ }
239
+ /** 从公开 profileContext.installAnchor 读出 dsh bin,不把 Desktop Host 入口当成 CLI。 */
240
+ function resolveCliFromInstallAnchor(anchor) {
241
+ if (typeof anchor !== "string" || anchor === "" || !isAbsolute(anchor)) return void 0;
242
+ try {
243
+ const bin = JSON.parse(readFileSync(anchor, "utf8")).bin;
244
+ const relative = typeof bin === "string" ? bin : bin !== null && typeof bin === "object" && typeof bin.dsh === "string" ? bin.dsh : void 0;
245
+ if (relative === void 0 || relative === "") return void 0;
246
+ const entry = resolve(dirname(anchor), relative);
247
+ return existsSync(entry) ? entry : void 0;
248
+ } catch {
249
+ return;
250
+ }
251
+ }
252
+ /** 官方 Desktop Host 是 Electron 的 IPC 子进程;父进程只接受带 type 的事件。 */
253
+ function isOfficialDesktopHostEntry(entry = process.argv[1]) {
254
+ if (entry === void 0 || entry === "") return false;
255
+ return entry.replaceAll("\\", "/").includes("/dsh-desktop-host/");
256
+ }
257
+ /** 从公开包布局定位同一次安装里的 dsh CLI,不读取 launcher 私有 service。 */
258
+ function resolveCliBesideDesktopHost(entry = process.argv[1]) {
259
+ if (!isOfficialDesktopHostEntry(entry)) return void 0;
260
+ const index = entry.replaceAll("\\", "/").toLowerCase().lastIndexOf("/node_modules/@deepseek-ai/dsh-desktop-host/");
261
+ if (index < 0) return void 0;
262
+ return resolveCliFromInstallAnchor(resolve(entry.slice(0, index), "node_modules", "@deepseek-ai", "dsh", "package.json"));
263
+ }
219
264
  function profileDirectory(runtime) {
220
265
  return runtime.profileDir;
221
266
  }
@@ -452,12 +497,27 @@ function resolveDshCliEntry(entry = process.argv[1], cwd = process.cwd()) {
452
497
  }
453
498
  function requestDesktopHotUpdate(send = process.send) {
454
499
  if (typeof send !== "function") return false;
455
- send(APPLY_PLUGIN_UPDATES_IPC);
456
- return true;
500
+ try {
501
+ if (send === process.send) {
502
+ if (process.connected !== true) return false;
503
+ process.send?.(APPLY_PLUGIN_UPDATES_IPC);
504
+ } else send(APPLY_PLUGIN_UPDATES_IPC);
505
+ return true;
506
+ } catch {
507
+ return false;
508
+ }
509
+ }
510
+ /** Desktop 的包管理服务会自行安排重载;只有父进程能识别该消息的独立 Web 子进程才通知。 */
511
+ function canRequestParentReload(runtime, send = process.send, entry = process.argv[1]) {
512
+ return runtime.environmentKind === "cli" && !isOfficialDesktopHostEntry(entry) && typeof send === "function" && (send !== process.send || process.connected === true);
457
513
  }
458
- /** Desktop 的包管理服务会自行安排重载;只有独立 Web 子进程需要通知父进程。 */
459
- function canRequestParentReload(runtime, send = process.send) {
460
- return runtime.environmentKind === "cli" && typeof send === "function";
514
+ /** 响应已经发出后再通知父进程;通知失败不能变成未捕获异常。 */
515
+ function scheduleParentPluginReload(delayMs = 150) {
516
+ setTimeout(() => {
517
+ try {
518
+ requestDesktopHotUpdate();
519
+ } catch {}
520
+ }, delayMs).unref?.();
461
521
  }
462
522
  async function recordPendingUpdate(packageName, version, runtime) {
463
523
  const pendingPath = resolve(profileDirectory(runtime), PROFILE_PENDING_UPDATES_FILE);
@@ -786,7 +846,8 @@ function monitorDesktopPlugin(handle, timeoutMs = PLUGIN_INSTALL_TIMEOUT_MS) {
786
846
  function runDshPlugin(args, runtime = resolveDependencyRuntime(), timeoutMs = PLUGIN_INSTALL_TIMEOUT_MS) {
787
847
  const desktopPnpm = runtime.desktopPnpm;
788
848
  if (desktopPnpm !== void 0) return monitorDesktopPlugin(withPnpmEntry(() => desktopPnpm.runPlugin(args, runtime.profileDir)), timeoutMs);
789
- const entry = resolveDshCliEntry();
849
+ const entry = runtime.cliEntry ?? resolveDshCliEntry();
850
+ if (isOfficialDesktopHostEntry(entry)) throw new Error("无法定位 DSH CLI。请从 DSH 命令启动 Web 服务后重试。");
790
851
  return monitorPluginChild(spawn(process.execPath, [
791
852
  ...pluginExecArgv(),
792
853
  entry,
@@ -796,7 +857,10 @@ function runDshPlugin(args, runtime = resolveDependencyRuntime(), timeoutMs = PL
796
857
  ...args
797
858
  ], {
798
859
  cwd: process.cwd(),
799
- env: pluginSpawnEnv(),
860
+ env: {
861
+ ...pluginSpawnEnv(),
862
+ ...runtime.pluginEnv
863
+ },
800
864
  windowsHide: true,
801
865
  stdio: [
802
866
  "ignore",
@@ -2082,9 +2146,7 @@ function apply(ctx) {
2082
2146
  restartRequired: updatedCount > 0,
2083
2147
  autoReload
2084
2148
  }));
2085
- if (restartAfterResponse) setTimeout(() => {
2086
- requestDesktopHotUpdate();
2087
- }, 150).unref?.();
2149
+ if (restartAfterResponse) scheduleParentPluginReload();
2088
2150
  return;
2089
2151
  }
2090
2152
  const runtime = resolveDependencyRuntime(ctx);
@@ -2104,9 +2166,7 @@ function apply(ctx) {
2104
2166
  restartRequired: true,
2105
2167
  autoReload
2106
2168
  }));
2107
- if (restartAfterResponse) setTimeout(() => {
2108
- requestDesktopHotUpdate();
2109
- }, 150).unref?.();
2169
+ if (restartAfterResponse) scheduleParentPluginReload();
2110
2170
  return;
2111
2171
  }
2112
2172
  response.writeHead(405);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@michengai/dsh-codex-ui",
3
- "version": "1.1.22",
3
+ "version": "1.1.23",
4
4
  "description": "DSH Codex UI — 为 DeepSeek Harness Web 提供 Codex 风格侧栏、工作区会话树、全局搜索和轮次导航 · A Codex-style sidebar, workspace session tree, global search, and turn navigation for DSH Web",
5
5
  "license": "Apache-2.0",
6
6
  "publishConfig": {