@michengai/dsh-codex-ui 0.2.95 → 0.2.96

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,19 @@
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.96 — 2026-09-01
8
+
9
+ Companion release: `@michengai/dsh-codex-suite-installer@0.1.13`.
10
+
11
+ ### Fixed
12
+
13
+ - Opened About immediately when the IM companion is not installed instead of showing General settings while waiting for a missing section to time out; the installed IM settings route is unchanged.
14
+ - Predeclared the nonessential `protobufjs` and `koffi` install scripts as disabled before About-page plugin installs, preventing pnpm's ignored-build placeholder from blocking an otherwise safe install.
15
+
16
+ ### Dependencies
17
+
18
+ - Refreshed the Suite Installer against the latest exact member versions from the official npm registry at release time.
19
+
7
20
  ## 0.2.95 — 2026-09-01
8
21
 
9
22
  Companion release: `@michengai/dsh-codex-suite-installer@0.1.12`.
@@ -4,6 +4,19 @@
4
4
 
5
5
  本日志记录 DSH Codex UI 及其一键安装器的最近发布;更早的变更可查看 [Git 提交历史](https://github.com/MichengAI/dsh-codex-ui/commits/main)。
6
6
 
7
+ ## 0.2.96 — 2026-09-01
8
+
9
+ 配套版本:`@michengai/dsh-codex-suite-installer@0.1.13`。
10
+
11
+ ### 修复
12
+
13
+ - 未安装 IM 配套插件时,点击 IM 助理会立即进入“关于”,不再先显示通用设置并等待缺失分区超时;已安装时仍正常进入 IM 设置。
14
+ - “关于”页安装插件前会预先将非必要的 `protobufjs` 与 `koffi` 安装脚本声明为禁用,避免 pnpm 写入 ignored-build 占位配置并阻断安全安装。
15
+
16
+ ### 依赖
17
+
18
+ - 发布时通过官方 npm 源重新解析 Suite Installer 全部成员的最新精确版本。
19
+
7
20
  ## 0.2.95 — 2026-09-01
8
21
 
9
22
  配套版本:`@michengai/dsh-codex-suite-installer@0.1.12`。
package/dist/client.js CHANGED
@@ -18,6 +18,16 @@ window.__ModuleLoader__.load({
18
18
  if (match !== void 0) return match;
19
19
  }
20
20
  }
21
+ /**
22
+ * 可选插件未注册设置入口时,直接打开兜底页,避免先展示通用设置并等待导航超时。
23
+ */
24
+ function routeOptionalSettingsSection(available, openRequested, openFallback) {
25
+ if (available) {
26
+ openRequested();
27
+ return;
28
+ }
29
+ openFallback();
30
+ }
21
31
  let cancelPendingNavigation;
22
32
  const SETTINGS_NAVIGATION_TIMEOUT_MS = 4e3;
23
33
  function openSettingsSection(root, label, onMissing, onSelected) {
@@ -3583,7 +3593,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
3583
3593
  });
3584
3594
  }
3585
3595
  /** 搜索状态与大侧栏隔离:输入、悬停和开关弹窗都不能让工作区树跟着重渲染。 */
3586
- const SidebarSearch = (0, react.forwardRef)(function SidebarSearch({ openSession, startSession, t, useSessions, useWorkspaces, settingsSeat }, ref) {
3596
+ const SidebarSearch = (0, react.forwardRef)(function SidebarSearch({ imSettingsAvailable, openSession, startSession, t, useSessions, useWorkspaces, settingsSeat }, ref) {
3587
3597
  const [open, setOpen] = (0, react.useState)(false);
3588
3598
  const [query, setQuery] = (0, react.useState)("");
3589
3599
  const [activeIndex, setActiveIndex] = (0, react.useState)(0);
@@ -3613,6 +3623,18 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
3613
3623
  settingsSeat,
3614
3624
  t
3615
3625
  ]);
3626
+ const openImSettings = (0, react.useCallback)(() => {
3627
+ routeOptionalSettingsSection(imSettingsAvailable, () => {
3628
+ selectExternalSection([t("sidebar.imSettings"), "IM助理"]);
3629
+ }, () => {
3630
+ selectSection(t("about.nav"));
3631
+ });
3632
+ }, [
3633
+ imSettingsAvailable,
3634
+ selectExternalSection,
3635
+ selectSection,
3636
+ t
3637
+ ]);
3616
3638
  const openSettings = (0, react.useCallback)(() => {
3617
3639
  settingsSeat.current?.querySelector("[aria-haspopup=\"dialog\"]")?.click();
3618
3640
  }, [settingsSeat]);
@@ -3698,7 +3720,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
3698
3720
  keywords: t("search.settings"),
3699
3721
  run: () => {
3700
3722
  close();
3701
- selectExternalSection([t("sidebar.imSettings"), "IM助理"]);
3723
+ openImSettings();
3702
3724
  }
3703
3725
  },
3704
3726
  {
@@ -3728,6 +3750,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
3728
3750
  ];
3729
3751
  }, [
3730
3752
  close,
3753
+ openImSettings,
3731
3754
  openSession,
3732
3755
  openSettings,
3733
3756
  selectExternalSection,
@@ -3872,6 +3895,13 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
3872
3895
  selectSection(t("about.nav"));
3873
3896
  });
3874
3897
  };
3898
+ const openImSettings = () => {
3899
+ routeOptionalSettingsSection(showChannels, () => {
3900
+ selectExternalSection([t("sidebar.imSettings"), "IM助理"]);
3901
+ }, () => {
3902
+ selectSection(t("about.nav"));
3903
+ });
3904
+ };
3875
3905
  (0, react.useEffect)(() => {
3876
3906
  if (imTab === "channels" && !showChannels) setImTab("tasks");
3877
3907
  if (imTab === "schedule" && !showSchedule) setImTab("tasks");
@@ -4072,9 +4102,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
4072
4102
  }),
4073
4103
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
4074
4104
  type: "button",
4075
- onClick: () => {
4076
- selectExternalSection([t("sidebar.imSettings"), "IM助理"]);
4077
- },
4105
+ onClick: openImSettings,
4078
4106
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuIcon, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ImAssistantIcon, {}) }), t("sidebar.assistant")]
4079
4107
  })
4080
4108
  ]
@@ -4230,9 +4258,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
4230
4258
  type: "button",
4231
4259
  className: "dcu-icon",
4232
4260
  "aria-label": t("sidebar.assistant"),
4233
- onClick: () => {
4234
- selectExternalSection([t("sidebar.imSettings"), "IM助理"]);
4235
- },
4261
+ onClick: openImSettings,
4236
4262
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ImAssistantIcon, {})
4237
4263
  })
4238
4264
  ]
@@ -4251,6 +4277,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
4251
4277
  }),
4252
4278
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarSearch, {
4253
4279
  ref: search,
4280
+ imSettingsAvailable: showChannels,
4254
4281
  settingsSeat,
4255
4282
  openSession,
4256
4283
  startSession,
package/dist/index.mjs CHANGED
@@ -228,6 +228,34 @@ function applyReleaseExclude(source, packageName, version) {
228
228
  if (section.test(source)) return source.replace(section, (match) => `${match.endsWith("\n") ? match : `${match}${eol}`}${entry}${eol}`);
229
229
  return `${source}${source === "" || source.endsWith("\n") ? "" : eol}minimumReleaseAgeExclude:${eol}${entry}${eol}`;
230
230
  }
231
+ /**
232
+ * pnpm 11 会在首次解析带 install script 的传递依赖时中止并写入占位值。
233
+ * 这些依赖的运行时不需要 postinstall,因此在调用 DSH plugin add 之前显式
234
+ * 记录拒绝执行,保证“关于”页单独安装和 Suite Installer 行为一致。
235
+ */
236
+ function applyRequiredBuildPolicies(source) {
237
+ const eol = source.includes("\r\n") ? "\r\n" : "\n";
238
+ const lines = source.split(/\r?\n/);
239
+ const start = lines.findIndex((line) => line === "allowBuilds:");
240
+ if (start === -1) return `${source}${source === "" || source.endsWith("\n") ? "" : eol}allowBuilds:${eol} protobufjs: false${eol} koffi: false${eol}`;
241
+ let end = start + 1;
242
+ while (end < lines.length && (lines[end] === "" || /^\s/.test(lines[end]))) end += 1;
243
+ const body = lines.slice(start + 1, end).filter((line) => !/^\s{2}(?:protobufjs|koffi):/.test(line));
244
+ lines.splice(start + 1, end - start - 1, " protobufjs: false", " koffi: false", ...body);
245
+ return lines.join(eol);
246
+ }
247
+ async function ensureRequiredBuildPolicies(runtime) {
248
+ const path = resolve(profileDirectory(runtime), "pnpm-workspace.yaml");
249
+ let source;
250
+ try {
251
+ source = await readFile(path, "utf8");
252
+ } catch (error) {
253
+ if (error.code !== "ENOENT") throw error;
254
+ source = "";
255
+ }
256
+ const next = applyRequiredBuildPolicies(source);
257
+ if (next !== source) await writeFile(path, next, "utf8");
258
+ }
231
259
  /** 将用户本次确认的精确版本加入 Profile 的 pnpm 发布时间保护例外。 */
232
260
  async function ensureLatestReleaseAllowed(packageName, version, runtime) {
233
261
  if (parseSemver(version) === void 0) throw new Error("npm 返回了无法识别的最新版本。");
@@ -384,6 +412,7 @@ function pluginCommandError(stderr) {
384
412
  if (detail.includes("minimumReleaseAge") || detail.includes("Release age")) return /* @__PURE__ */ new Error("更新被 pnpm 发布时间保护拦截。请确认已写入当前版本白名单后重试。");
385
413
  if (/EPERM|EBUSY|EACCES|unable to unlink|ERR_PNPM_LOCKED|Lock/i.test(detail)) return /* @__PURE__ */ new Error("无法覆盖正在运行的插件文件。请先完全退出桌面端,再重新打开后更新。");
386
414
  if (/UNEXPECTED_STORE|Unexpected store location/i.test(detail)) return /* @__PURE__ */ new Error("插件目录和 pnpm 仓库不一致。请完全退出桌面端后再更新。");
415
+ if (/ERR_PNPM_IGNORED_BUILDS|Ignored build scripts/i.test(detail)) return /* @__PURE__ */ new Error("插件依赖的 pnpm 构建脚本策略尚未确认。请更新 Profile 的 allowBuilds 配置后重试。");
387
416
  if (/pnpm not found/i.test(detail)) return /* @__PURE__ */ new Error("当前环境找不到 pnpm。请从桌面端启动后再更新。");
388
417
  return /* @__PURE__ */ new Error("无法在应用运行时更新插件。请先完全退出桌面端,再重新打开后更新。");
389
418
  }
@@ -581,6 +610,7 @@ async function installDependenciesLocked(ids, requestHotUpdate, runtime) {
581
610
  };
582
611
  }));
583
612
  const remove = [...new Set(targets.flatMap((target) => pluginsToRemoveBeforeInstall(declared, target.packageName)))];
613
+ await ensureRequiredBuildPolicies(runtime);
584
614
  for (const target of targets) {
585
615
  await ensureLatestReleaseAllowed(target.packageName, target.version, runtime);
586
616
  if (!isOfficialRuntimePackage(target.packageName)) await recordDeclaredVersion(target.packageName, target.version, runtime);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@michengai/dsh-codex-ui",
3
- "version": "0.2.95",
3
+ "version": "0.2.96",
4
4
  "description": "以 Codex 风格重构 DSH Web 侧栏的独立客户端插件",
5
5
  "license": "Apache-2.0",
6
6
  "publishConfig": {