@michengai/dsh-codex-ui 0.2.92 → 0.2.93

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,20 @@
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
+ ## 0.2.93 — 2026-08-30
8
+
9
+ ### Compatibility
10
+
11
+ - Resolved the active DSH Desktop profile through the public `desktopProfiles` service and delegated installs and updates to the public `desktopPnpm` package manager instead of hard-coding the `web` profile.
12
+ - Preserved the ordinary Web/CLI profile fallback while recognizing Desktop-provided runtime and companion-package state across restarts.
13
+ - Routed new-session actions through Archive Manager's optional `uiWorkspace.startSession()` service, with the standard workspace service retained as the fallback.
14
+
15
+ ### Safety
16
+
17
+ - Removed the dependency on the launcher-private `desktopPnpmBootstrap` implementation detail.
18
+ - Failed safely when a Desktop generation exposes incomplete public services instead of falling back to an ambient CLI that could mutate another profile.
19
+ - Reported the running Desktop DSH runtime as installed without fabricating a version or update when the Host exposes no supported runtime path.
20
+
7
21
  ## 0.2.92 — 2026-08-28
8
22
 
9
23
  Companion release: `@michengai/dsh-codex-suite-installer@0.1.9`.
@@ -4,6 +4,20 @@
4
4
 
5
5
  本日志记录 DSH Codex UI 及其一键安装器的最近发布;更早的变更可查看 [Git 提交历史](https://github.com/MichengAI/dsh-codex-ui/commits/main)。
6
6
 
7
+ ## 0.2.93 — 2026-08-30
8
+
9
+ ### 兼容性
10
+
11
+ - 通过公开的 `desktopProfiles` service 读取 DSH Desktop 当前 Profile,并把安装与更新交给公开的 `desktopPnpm` 包管理服务,不再硬编码 `web` Profile。
12
+ - 保留普通 Web/CLI 的 Profile 回退,同时在 Desktop 重启前后正确识别宿主 Runtime 与配套插件状态。
13
+ - 新建会话优先调用 Archive Manager 可选提供的 `uiWorkspace.startSession()` service,缺失时继续使用标准工作区服务。
14
+
15
+ ### 安全性
16
+
17
+ - 移除对 Launcher 私有实现细节 `desktopPnpmBootstrap` 的依赖。
18
+ - Desktop generation 的公开服务不完整时安全失败,不再回退到可能修改其他 Profile 的环境 CLI。
19
+ - 宿主没有通过受支持路径暴露 Runtime 目录时,只确认正在运行的 Desktop DSH Runtime 已安装,不伪造版本或升级状态。
20
+
7
21
  ## 0.2.92 — 2026-08-28
8
22
 
9
23
  配套版本:`@michengai/dsh-codex-suite-installer@0.1.9`。
package/dist/client.js CHANGED
@@ -5445,6 +5445,18 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
5445
5445
  function hasDeleteSession(value) {
5446
5446
  return value !== null && typeof value === "object" && "deleteSession" in value && typeof value.deleteSession === "function";
5447
5447
  }
5448
+ function hasStartSession(value) {
5449
+ return value !== null && typeof value === "object" && "startSession" in value && typeof value.startSession === "function";
5450
+ }
5451
+ /** Archive Manager replaces the official ui-workspace row with this optional service. */
5452
+ function startWorkspaceSession(ctx, workspaceId) {
5453
+ const uiWorkspace = ctx.get("uiWorkspace");
5454
+ if (hasStartSession(uiWorkspace)) {
5455
+ uiWorkspace.startSession(workspaceId);
5456
+ return;
5457
+ }
5458
+ ctx.workspaces.startSession(workspaceId);
5459
+ }
5448
5460
  /** 替换 DSH 的官方 sidebar 插槽,不修改 DSH 源码或会话数据。 */
5449
5461
  function apply(ctx) {
5450
5462
  ctx.effect(() => ctx.locale.register(NS, {
@@ -5490,7 +5502,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
5490
5502
  ctx.sessions.open(sessionId);
5491
5503
  },
5492
5504
  startSession: (workspaceId) => {
5493
- ctx.workspaces.startSession(workspaceId);
5505
+ startWorkspaceSession(ctx, workspaceId);
5494
5506
  },
5495
5507
  toggleSidebar: () => {
5496
5508
  ctx.layout.toggleSidebar();
@@ -5561,7 +5573,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
5561
5573
  insertWorkspaceBefore: (workspaceId, beforeWorkspaceId) => ctx.workspaces.insertBefore(workspaceId, beforeWorkspaceId),
5562
5574
  insertSessionBefore: (workspaceId, sessionId, beforeSessionId) => ctx.workspaces.insertSessionBefore(workspaceId, sessionId, beforeSessionId),
5563
5575
  startSession: (workspaceId) => {
5564
- ctx.workspaces.startSession(workspaceId);
5576
+ startWorkspaceSession(ctx, workspaceId);
5565
5577
  }
5566
5578
  })
5567
5579
  }, CodexWorkspaceBrowser));
@@ -5601,6 +5613,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
5601
5613
  //#endregion
5602
5614
  exports.apply = apply;
5603
5615
  exports.inject = inject;
5616
+ exports.startWorkspaceSession = startWorkspaceSession;
5604
5617
  return module.exports;
5605
5618
  }
5606
5619
  });
package/dist/index.mjs CHANGED
@@ -56,13 +56,63 @@ function managedDependency(id) {
56
56
  const PROFILE_PENDING_UPDATES_FILE = ".dsh-pending-updates.json";
57
57
  const APPLY_PLUGIN_UPDATES_IPC = "apply-plugin-updates";
58
58
  const PLUGIN_INSTALL_TIMEOUT_MS = 6e5;
59
- function profileDirectory() {
60
- if (process.env.DSH_PROFILE_DIR !== void 0) return process.env.DSH_PROFILE_DIR;
61
- return resolve(homedir(), ".dsh", "profiles", "web");
59
+ function optionalService(ctx, name) {
60
+ if (ctx === void 0) return void 0;
61
+ return typeof ctx.get === "function" ? ctx.get(name) : ctx[name];
62
62
  }
63
- async function declaredPluginNames() {
63
+ function validProfileName(value) {
64
+ return typeof value === "string" && value !== "" && value !== "." && value !== ".." && value !== "node_modules" && !value.includes("/") && !value.includes("\\") && !/[\0-\x1f\x7f]/.test(value);
65
+ }
66
+ function profileNameFromArgv(argv) {
67
+ for (let index = 2; index < argv.length; index += 1) {
68
+ const argument = argv[index];
69
+ if (argument === "--profile") return argv[index + 1];
70
+ if (argument?.startsWith("--profile=")) return argument.slice(10);
71
+ }
72
+ return argv[2] === "web" ? "web" : void 0;
73
+ }
74
+ /**
75
+ * Desktop 通过可选 Host service 暴露当前 profile;普通 Web/CLI 继续使用
76
+ * DSH_PROFILE_DIR、命令行 profile 与默认 web profile。
77
+ */
78
+ function resolveDependencyRuntime(ctx, options = {}) {
79
+ const env = options.env ?? process.env;
80
+ const argv = options.argv ?? process.argv;
81
+ const cwd = options.cwd ?? process.cwd();
82
+ const home = options.homeDir ?? homedir();
83
+ const profiles = optionalService(ctx, "desktopProfiles");
84
+ const desktopPnpm = optionalService(ctx, "desktopPnpm");
85
+ if (profiles !== void 0) {
86
+ const current = profiles.current;
87
+ if (!validProfileName(current?.name) || typeof current.dir !== "string" || !isAbsolute(current.dir)) throw new Error("DSH Desktop 当前 Profile 信息无效,请重启 Desktop 后重试。");
88
+ if (typeof desktopPnpm?.runPlugin !== "function") throw new Error("DSH Desktop 包管理服务尚未就绪,请重启 Desktop 后重试。");
89
+ const profileDir = resolve(current.dir);
90
+ const runtimeRoots = typeof env.DSH_RUNTIME_DIR === "string" && isAbsolute(env.DSH_RUNTIME_DIR) ? [resolve(env.DSH_RUNTIME_DIR)] : [];
91
+ return {
92
+ environmentKind: "desktop",
93
+ profileName: current.name,
94
+ profileDir,
95
+ runtimeRoots,
96
+ desktopPnpm
97
+ };
98
+ }
99
+ const profileDir = resolve(env.DSH_PROFILE_DIR ?? resolve(home, ".dsh", "profiles", "web"));
100
+ const selected = profileNameFromArgv(argv);
101
+ const profileName = validProfileName(selected) ? selected : validProfileName(basename(profileDir)) ? basename(profileDir) : "web";
102
+ const cliRuntimeRoot = argv[1] === void 0 ? void 0 : resolveDshRuntimeRoot(argv[1], cwd);
103
+ return {
104
+ environmentKind: "cli",
105
+ profileName,
106
+ profileDir,
107
+ runtimeRoots: [env.DSH_RUNTIME_DIR, cliRuntimeRoot].filter((root) => root !== void 0 && root !== "")
108
+ };
109
+ }
110
+ function profileDirectory(runtime) {
111
+ return runtime.profileDir;
112
+ }
113
+ async function declaredPluginNames(runtime) {
64
114
  try {
65
- const manifest = JSON.parse(await readFile(resolve(profileDirectory(), "package.json"), "utf8"));
115
+ const manifest = JSON.parse(await readFile(resolve(profileDirectory(runtime), "package.json"), "utf8"));
66
116
  return [.../* @__PURE__ */ new Set([...Object.keys({
67
117
  ...manifest.devDependencies,
68
118
  ...manifest.dependencies
@@ -101,17 +151,12 @@ function resolveDshRuntimeRoot(entry = process.argv[1], cwd = process.cwd()) {
101
151
  const root = cliEntry.slice(0, index);
102
152
  return root.endsWith(sep) ? root.slice(0, -1) : root;
103
153
  }
104
- function packageLookupRoots(packageName) {
105
- if (!isOfficialRuntimePackage(packageName)) return [profileDirectory()];
106
- const runtimeDir = process.env.DSH_RUNTIME_DIR;
107
- return [...new Set([
108
- runtimeDir,
109
- resolveDshRuntimeRoot(),
110
- profileDirectory()
111
- ].filter((root) => root !== void 0 && root !== ""))];
154
+ function packageLookupRoots(packageName, runtime) {
155
+ if (!isOfficialRuntimePackage(packageName)) return [profileDirectory(runtime)];
156
+ return [.../* @__PURE__ */ new Set([...runtime.runtimeRoots, profileDirectory(runtime)])];
112
157
  }
113
- async function installedPackageVersion(packageName) {
114
- for (const root of packageLookupRoots(packageName)) try {
158
+ async function installedPackageVersion(packageName, runtime) {
159
+ for (const root of packageLookupRoots(packageName, runtime)) try {
115
160
  const manifest = JSON.parse(await readFile(resolve(root, "node_modules", ...packageName.split("/"), "package.json"), "utf8"));
116
161
  if (typeof manifest.version === "string" && manifest.version !== "") return manifest.version;
117
162
  } catch (error) {
@@ -183,9 +228,9 @@ function applyReleaseExclude(source, packageName, version) {
183
228
  return `${source}${source === "" || source.endsWith("\n") ? "" : eol}minimumReleaseAgeExclude:${eol}${entry}${eol}`;
184
229
  }
185
230
  /** 将用户本次确认的精确版本加入 Profile 的 pnpm 发布时间保护例外。 */
186
- async function ensureLatestReleaseAllowed(packageName, version) {
231
+ async function ensureLatestReleaseAllowed(packageName, version, runtime) {
187
232
  if (parseSemver(version) === void 0) throw new Error("npm 返回了无法识别的最新版本。");
188
- const path = resolve(profileDirectory(), "pnpm-workspace.yaml");
233
+ const path = resolve(profileDirectory(runtime), "pnpm-workspace.yaml");
189
234
  let source;
190
235
  try {
191
236
  source = await readFile(path, "utf8");
@@ -231,11 +276,16 @@ function newerVersion(installed, latest) {
231
276
  for (let index = 0; index < current.core.length; index += 1) if (candidate.core[index] !== current.core[index]) return candidate.core[index] > current.core[index];
232
277
  return comparePrerelease(candidate.prerelease, current.prerelease) > 0;
233
278
  }
234
- /** 返回 Web profile 中固定管理插件的实际安装版本与 npm latest 状态。 */
235
- async function dependencyStatuses() {
236
- const declaredNames = await declaredPluginNames();
279
+ /** 返回当前 profile 中固定管理插件的实际安装版本与 npm latest 状态。 */
280
+ async function dependencyStatuses(runtime = resolveDependencyRuntime()) {
281
+ const declaredNames = await declaredPluginNames(runtime);
237
282
  return Promise.all(MANAGED_DEPENDENCIES.map(async (dependency) => {
238
- const version = await installedPackageVersion(dependency.packageName);
283
+ const version = await installedPackageVersion(dependency.packageName, runtime);
284
+ if (version === void 0 && runtime.environmentKind === "desktop" && isOfficialRuntimePackage(dependency.packageName)) return {
285
+ ...dependency,
286
+ installed: true,
287
+ updateAvailable: false
288
+ };
239
289
  const declared = isOfficialRuntimePackage(dependency.packageName) || isManagedPackageDeclared(dependency.packageName, declaredNames);
240
290
  if (version === void 0 || !isManagedPackageInstalled({
241
291
  installedVersion: version,
@@ -273,8 +323,8 @@ function isRestartableInstallError(error) {
273
323
  const message = error instanceof Error ? error.message : String(error);
274
324
  return /完全退出桌面端|正在运行的插件|pnpm 仓库不一致/.test(message);
275
325
  }
276
- async function recordPendingUpdate(packageName, version) {
277
- const pendingPath = resolve(profileDirectory(), PROFILE_PENDING_UPDATES_FILE);
326
+ async function recordPendingUpdate(packageName, version, runtime) {
327
+ const pendingPath = resolve(profileDirectory(runtime), PROFILE_PENDING_UPDATES_FILE);
278
328
  let packages = [];
279
329
  try {
280
330
  const parsed = JSON.parse(await readFile(pendingPath, "utf8"));
@@ -297,8 +347,8 @@ async function recordPendingUpdate(packageName, version) {
297
347
  });
298
348
  await writeFile(pendingPath, `${JSON.stringify({ packages }, void 0, 2)}\n`, "utf8");
299
349
  }
300
- async function removePendingUpdate(packageName) {
301
- const pendingPath = resolve(profileDirectory(), PROFILE_PENDING_UPDATES_FILE);
350
+ async function removePendingUpdate(packageName, runtime) {
351
+ const pendingPath = resolve(profileDirectory(runtime), PROFILE_PENDING_UPDATES_FILE);
302
352
  try {
303
353
  const parsed = JSON.parse(await readFile(pendingPath, "utf8"));
304
354
  if (!Array.isArray(parsed.packages)) return;
@@ -313,8 +363,8 @@ async function removePendingUpdate(packageName) {
313
363
  if (error.code !== "ENOENT") throw error;
314
364
  }
315
365
  }
316
- async function recordDeclaredVersion(packageName, version) {
317
- const manifestPath = resolve(profileDirectory(), "package.json");
366
+ async function recordDeclaredVersion(packageName, version, runtime) {
367
+ const manifestPath = resolve(profileDirectory(runtime), "package.json");
318
368
  let manifest;
319
369
  try {
320
370
  manifest = JSON.parse(await readFile(manifestPath, "utf8"));
@@ -344,6 +394,7 @@ function pluginExecArgv(args = process.execArgv) {
344
394
  return args.filter((arg) => !/^--(?:inspect|inspect-brk|debug|debug-brk)(?:=|$)/.test(arg));
345
395
  }
346
396
  const activePluginChildren = /* @__PURE__ */ new Set();
397
+ const activeDesktopPluginHandles = /* @__PURE__ */ new Set();
347
398
  function terminatePluginChild(child) {
348
399
  if (child.exitCode !== null || child.killed) return;
349
400
  if (process.platform === "win32" && child.pid !== void 0) {
@@ -367,6 +418,7 @@ function terminatePluginChild(child) {
367
418
  /** 插件停用时终止仍在运行的安装进程,避免热更新后遗留 pnpm。 */
368
419
  function disposeDependencyInstaller() {
369
420
  for (const child of activePluginChildren) terminatePluginChild(child);
421
+ for (const handle of activeDesktopPluginHandles) handle.cancel();
370
422
  }
371
423
  function monitorPluginChild(child, timeoutMs = PLUGIN_INSTALL_TIMEOUT_MS) {
372
424
  return new Promise((resolvePromise, reject) => {
@@ -398,14 +450,52 @@ function monitorPluginChild(child, timeoutMs = PLUGIN_INSTALL_TIMEOUT_MS) {
398
450
  timeout.unref?.();
399
451
  });
400
452
  }
401
- function runDshPlugin(args, timeoutMs = PLUGIN_INSTALL_TIMEOUT_MS) {
453
+ function monitorDesktopPlugin(handle, timeoutMs = PLUGIN_INSTALL_TIMEOUT_MS) {
454
+ return new Promise((resolvePromise, reject) => {
455
+ activeDesktopPluginHandles.add(handle);
456
+ let output = "";
457
+ let settled = false;
458
+ const collect = (chunk) => {
459
+ output = `${output}${String(chunk)}`.slice(-65536);
460
+ };
461
+ const finish = (error) => {
462
+ if (settled) return;
463
+ settled = true;
464
+ clearTimeout(timeout);
465
+ activeDesktopPluginHandles.delete(handle);
466
+ error === void 0 ? resolvePromise() : reject(error);
467
+ };
468
+ handle.stdout?.on("data", collect);
469
+ handle.stderr?.on("data", collect);
470
+ handle.stdout?.once("error", () => {
471
+ handle.cancel();
472
+ finish(/* @__PURE__ */ new Error("无法读取 DSH Desktop 插件安装输出。"));
473
+ });
474
+ handle.stderr?.once("error", () => {
475
+ handle.cancel();
476
+ finish(/* @__PURE__ */ new Error("无法读取 DSH Desktop 插件安装输出。"));
477
+ });
478
+ handle.done.then((outcome) => {
479
+ finish(outcome.exitCode === 0 && outcome.signal === null ? void 0 : pluginCommandError(output));
480
+ }, () => {
481
+ finish(pluginCommandError(output));
482
+ });
483
+ const timeout = setTimeout(() => {
484
+ handle.cancel();
485
+ finish(/* @__PURE__ */ new Error("插件安装超时,已终止安装进程。请检查网络后重试。"));
486
+ }, timeoutMs);
487
+ timeout.unref?.();
488
+ });
489
+ }
490
+ function runDshPlugin(args, runtime = resolveDependencyRuntime(), timeoutMs = PLUGIN_INSTALL_TIMEOUT_MS) {
491
+ if (runtime.desktopPnpm !== void 0) return monitorDesktopPlugin(runtime.desktopPnpm.runPlugin(args, runtime.profileDir), timeoutMs);
402
492
  const entry = resolveDshCliEntry();
403
493
  return monitorPluginChild(spawn(process.execPath, [
404
494
  ...pluginExecArgv(),
405
495
  entry,
406
496
  "plugin",
407
497
  "--profile",
408
- "web",
498
+ runtime.profileName,
409
499
  ...args
410
500
  ], {
411
501
  cwd: process.cwd(),
@@ -424,11 +514,11 @@ function runDshPlugin(args, timeoutMs = PLUGIN_INSTALL_TIMEOUT_MS) {
424
514
  /** 并发安装互斥:pnpm 锁文件竞争会触发 EPERM/EBUSY,同一时间只允许一个安装进程。 */
425
515
  let installing = false;
426
516
  /** 仅允许安装固定依赖,避免把浏览器输入转成任意命令。 */
427
- async function installDependency(id, requestHotUpdate = requestDesktopHotUpdate) {
517
+ async function installDependency(id, requestHotUpdate = requestDesktopHotUpdate, runtime = resolveDependencyRuntime()) {
428
518
  if (installing) throw new Error("已有依赖安装正在进行,请等待完成后再试。");
429
519
  installing = true;
430
520
  try {
431
- return await installDependenciesLocked([id], requestHotUpdate);
521
+ return await installDependenciesLocked([id], requestHotUpdate, runtime);
432
522
  } finally {
433
523
  installing = false;
434
524
  }
@@ -438,31 +528,31 @@ function updatableDependencyIds(statuses) {
438
528
  return statuses.filter((status) => status.installed && status.updateAvailable).map((status) => status.id);
439
529
  }
440
530
  /** 把所有待更新版本一次写入清单,最后只请求一次桌面热更新。 */
441
- async function updateAllDependencies(requestHotUpdate = requestDesktopHotUpdate) {
531
+ async function updateAllDependencies(requestHotUpdate = requestDesktopHotUpdate, runtime = resolveDependencyRuntime()) {
442
532
  if (installing) throw new Error("已有依赖安装正在进行,请等待完成后再试。");
443
533
  installing = true;
444
534
  try {
445
- const current = await dependencyStatuses();
535
+ const current = await dependencyStatuses(runtime);
446
536
  const ids = updatableDependencyIds(current);
447
537
  if (ids.length === 0) return {
448
538
  dependencies: current,
449
539
  updatedCount: 0
450
540
  };
451
541
  return {
452
- dependencies: await installDependenciesLocked(ids, requestHotUpdate),
542
+ dependencies: await installDependenciesLocked(ids, requestHotUpdate, runtime),
453
543
  updatedCount: ids.length
454
544
  };
455
545
  } finally {
456
546
  installing = false;
457
547
  }
458
548
  }
459
- async function installDependenciesLocked(ids, requestHotUpdate) {
549
+ async function installDependenciesLocked(ids, requestHotUpdate, runtime) {
460
550
  const dependencies = [...new Set(ids)].map((id) => {
461
551
  const dependency = managedDependency(id);
462
552
  if (dependency === void 0) throw new Error("不支持安装该依赖。");
463
553
  return dependency;
464
554
  });
465
- const declared = await declaredPluginNames();
555
+ const declared = await declaredPluginNames(runtime);
466
556
  const requestedTargets = await Promise.all(dependencies.map(async (dependency) => {
467
557
  const latestVersion = await npmLatestVersion(dependency.packageName);
468
558
  if (latestVersion === void 0) throw new Error("无法获取 npm 最新版本,请检查网络或 npm registry 后重试。");
@@ -482,7 +572,7 @@ async function installDependenciesLocked(ids, requestHotUpdate) {
482
572
  packageName,
483
573
  version: requestedVersion
484
574
  };
485
- const version = await installedPackageVersion(packageName) ?? await npmLatestVersion(packageName);
575
+ const version = await installedPackageVersion(packageName, runtime) ?? await npmLatestVersion(packageName);
486
576
  if (version === void 0) throw new Error("无法读取 Suite 成员版本,请检查 npm 安装后重试。");
487
577
  return {
488
578
  packageName,
@@ -491,27 +581,27 @@ async function installDependenciesLocked(ids, requestHotUpdate) {
491
581
  }));
492
582
  const remove = [...new Set(targets.flatMap((target) => pluginsToRemoveBeforeInstall(declared, target.packageName)))];
493
583
  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);
584
+ await ensureLatestReleaseAllowed(target.packageName, target.version, runtime);
585
+ if (!isOfficialRuntimePackage(target.packageName)) await recordDeclaredVersion(target.packageName, target.version, runtime);
586
+ await recordPendingUpdate(target.packageName, target.version, runtime);
497
587
  }
498
- if (remove.length > 0) await runDshPlugin(["remove", ...remove]);
499
- if (requestHotUpdate()) return dependencyStatuses();
588
+ if (remove.length > 0) await runDshPlugin(["remove", ...remove], runtime);
589
+ if (runtime.desktopPnpm === void 0 && requestHotUpdate()) return dependencyStatuses(runtime);
500
590
  for (const target of targets) {
501
591
  try {
502
592
  await runDshPlugin([
503
593
  "add",
504
594
  `${target.packageName}@${target.version}`,
505
595
  "--registry=https://registry.npmjs.org/"
506
- ]);
596
+ ], runtime);
507
597
  } catch (error) {
508
- if (isRestartableInstallError(error)) return dependencyStatuses();
598
+ if (isRestartableInstallError(error)) return dependencyStatuses(runtime);
509
599
  throw error;
510
600
  }
511
- if (await installedPackageVersion(target.packageName) !== target.version) return dependencyStatuses();
512
- await removePendingUpdate(target.packageName);
601
+ if (await installedPackageVersion(target.packageName, runtime) !== target.version) return dependencyStatuses(runtime);
602
+ await removePendingUpdate(target.packageName, runtime);
513
603
  }
514
- return dependencyStatuses();
604
+ return dependencyStatuses(runtime);
515
605
  }
516
606
  //#endregion
517
607
  //#region src/explorer-path-policy.ts
@@ -950,7 +1040,7 @@ function apply(ctx) {
950
1040
  const url = new URL(request.url ?? "/", "http://localhost");
951
1041
  try {
952
1042
  if (request.method === "GET") {
953
- const dependencies = await dependencyStatuses();
1043
+ const dependencies = await dependencyStatuses(resolveDependencyRuntime(ctx));
954
1044
  response.writeHead(200, {
955
1045
  "content-type": "application/json; charset=utf-8",
956
1046
  "cache-control": "no-store"
@@ -972,7 +1062,7 @@ function apply(ctx) {
972
1062
  const { dependencies, updatedCount } = await updateAllDependencies(() => {
973
1063
  restartAfterResponse = typeof process.send === "function";
974
1064
  return restartAfterResponse;
975
- });
1065
+ }, resolveDependencyRuntime(ctx));
976
1066
  response.writeHead(200, {
977
1067
  "content-type": "application/json; charset=utf-8",
978
1068
  "cache-control": "no-store"
@@ -990,7 +1080,7 @@ function apply(ctx) {
990
1080
  const dependencies = await installDependency(url.searchParams.get("dependency"), () => {
991
1081
  restartAfterResponse = typeof process.send === "function";
992
1082
  return restartAfterResponse;
993
- });
1083
+ }, resolveDependencyRuntime(ctx));
994
1084
  response.writeHead(200, {
995
1085
  "content-type": "application/json; charset=utf-8",
996
1086
  "cache-control": "no-store"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@michengai/dsh-codex-ui",
3
- "version": "0.2.92",
3
+ "version": "0.2.93",
4
4
  "description": "以 Codex 风格重构 DSH Web 侧栏的独立客户端插件",
5
5
  "license": "Apache-2.0",
6
6
  "publishConfig": {