@michengai/dsh-codex-ui 0.2.67 → 0.2.69

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/README.md CHANGED
@@ -12,6 +12,7 @@
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)
15
+ [![npm downloads](https://img.shields.io/npm/dt/%40michengai%2Fdsh-codex-ui.svg?label=npm%20downloads&v=2)](https://www.npmjs.com/package/@michengai/dsh-codex-ui)
15
16
  [![DSH Web Plugin](https://img.shields.io/badge/DSH%20Web-Plugin-0f766e.svg)](https://github.com/MichengAI/dsh-codex-ui)
16
17
  [![Node.js 22 or later](https://img.shields.io/badge/Node.js-22%20or%20later-339933.svg?logo=node.js&logoColor=white)](https://nodejs.org/)
17
18
 
package/README.zh-CN.md CHANGED
@@ -12,6 +12,7 @@
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)
15
+ [![npm 下载量](https://img.shields.io/npm/dt/%40michengai%2Fdsh-codex-ui.svg?label=npm%20%E4%B8%8B%E8%BD%BD%E9%87%8F&v=2)](https://www.npmjs.com/package/@michengai/dsh-codex-ui)
15
16
  [![DSH Web Plugin](https://img.shields.io/badge/DSH%20Web-Plugin-0f766e.svg)](https://github.com/MichengAI/dsh-codex-ui)
16
17
  [![Node.js 22 or later](https://img.shields.io/badge/Node.js-22%20or%20later-339933.svg?logo=node.js&logoColor=white)](https://nodejs.org/)
17
18
 
package/dist/client.js CHANGED
@@ -4061,18 +4061,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
4061
4061
  "workspace.actions": "{name} 的项目操作",
4062
4062
  "workspace.taskCount": "{count} 个任务",
4063
4063
  "workspace.edit": "编辑项目",
4064
- "permission.read-only.title": "请求批准",
4065
- "permission.read-only.description": "编辑外部文件和使用互联网时始终询问",
4066
- "permission.read-only.trigger": "请求批准",
4067
- "permission.workspace-write.title": "帮我批准",
4068
- "permission.workspace-write.description": "仅对检测到的风险操作请求批准",
4069
- "permission.workspace-write.trigger": "帮我批准",
4070
- "permission.danger-full-access.title": "完全访问权限",
4071
- "permission.danger-full-access.description": "可不受限制地访问互联网和您电脑上的任何文件",
4072
- "permission.danger-full-access.trigger": "完全访问",
4073
- "permission.custom.title": "自定义",
4074
- "permission.custom.description": "使用当前会话的自定义权限预设",
4075
- "permission.custom.trigger": "自定义",
4076
4064
  "sessions.close": "关闭",
4077
4065
  "sessions.cancel": "取消",
4078
4066
  "sessions.save": "保存",
@@ -4184,18 +4172,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
4184
4172
  "workspace.actions": "Project actions for {name}",
4185
4173
  "workspace.taskCount": "{count} tasks",
4186
4174
  "workspace.edit": "Edit project",
4187
- "permission.read-only.title": "Request approval",
4188
- "permission.read-only.description": "Always ask when editing external files or using the internet",
4189
- "permission.read-only.trigger": "Request approval",
4190
- "permission.workspace-write.title": "Help me approve",
4191
- "permission.workspace-write.description": "Only ask for detected risky operations",
4192
- "permission.workspace-write.trigger": "Help me approve",
4193
- "permission.danger-full-access.title": "Full access",
4194
- "permission.danger-full-access.description": "Unrestricted access to the internet and any files on your computer",
4195
- "permission.danger-full-access.trigger": "Full access",
4196
- "permission.custom.title": "Custom",
4197
- "permission.custom.description": "Use the current session custom permission preset",
4198
- "permission.custom.trigger": "Custom",
4199
4175
  "sessions.close": "Close",
4200
4176
  "sessions.cancel": "Cancel",
4201
4177
  "sessions.save": "Save",
@@ -4264,120 +4240,39 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
4264
4240
  };
4265
4241
  //#endregion
4266
4242
  //#region src/client/permission-i18n.ts
4267
- const PERMISSION_I18N_STYLE = "[data-dcu-perm-title]{display:block;font-size:14px;line-height:20px;font-weight:500}[data-dcu-perm-desc]{display:block;margin-top:2px;color:var(--dcu-sidebar-secondary,#9ca39f);font-size:12px;line-height:18px;font-weight:400}button[role=menuitem][data-dcu-perm]{align-items:flex-start;height:auto;min-height:44px;padding-top:8px;padding-bottom:8px}button[data-dcu-perm=\"danger-full-access\"],button[data-dcu-perm=\"danger-full-access\"] svg,button[data-dcu-perm=\"danger-full-access\"] [data-dcu-perm-title],button[data-dcu-perm=\"danger-full-access\"] [data-dcu-perm-desc]{color:var(--dsw-alias-state-warn-label,#e3942a)}";
4268
- const ENGLISH_ALIASES = [
4269
- ["Workspace Write", "workspace-write"],
4270
- ["workspace-write", "workspace-write"],
4271
- ["Read Only", "read-only"],
4272
- ["read-only", "read-only"],
4273
- ["Full access", "danger-full-access"],
4274
- ["Full Access", "danger-full-access"],
4275
- ["danger-full-access", "danger-full-access"],
4276
- ["Custom", "custom"],
4277
- ["custom", "custom"]
4278
- ];
4279
- const LOCAL_ALIASES = [
4280
- ["帮我批准", "workspace-write"],
4281
- ["Help me approve", "workspace-write"],
4282
- ["请求批准", "read-only"],
4283
- ["Request approval", "read-only"],
4284
- ["完全访问权限", "danger-full-access"],
4285
- ["完全访问", "danger-full-access"],
4286
- ["自定义", "custom"]
4243
+ /**
4244
+ * 官方已负责权限文案及布局;这里只给「完全访问权限」保留醒目的风险提示。
4245
+ */
4246
+ const PERMISSION_RISK_STYLE = "button[role=menuitem][data-dcu-perm=\"danger-full-access\"],button[role=menuitem][data-dcu-perm=\"danger-full-access\"] *{color:var(--dsw-alias-state-warn-label,#e3942a)}";
4247
+ const FULL_ACCESS_LABELS = [
4248
+ "Full access",
4249
+ "Full Access",
4250
+ "danger-full-access",
4251
+ "完全访问权限",
4252
+ "完全访问"
4287
4253
  ];
4288
- /** 把宿主刚写上的英文权限名解析成本插件标识;英文优先于旧中文。 */
4289
- function permissionIdFromLabel(text) {
4254
+ /** 不改动宿主文案,只识别完全访问权限选项以施加风险色。 */
4255
+ function isFullAccessPermission(text) {
4290
4256
  const normalized = text.trim().replace(/\s+/g, " ");
4291
- for (const [alias, id] of ENGLISH_ALIASES) if (normalized === alias || normalized.includes(alias)) return id;
4292
- for (const [alias, id] of LOCAL_ALIASES) if (normalized === alias || normalized.includes(alias)) return id;
4293
- }
4294
- /** 把夹在中文确认框里的 Full access 换成当前语言名称。 */
4295
- function replaceFullAccessLabel(text, localized) {
4296
- if (localized === "Full access") return text;
4297
- return text.replaceAll("Full access", ` ${localized} `).replaceAll("Full Access", ` ${localized} `).replace(/ {2,}/g, " ").replace(/ ([??。,,!!])/g, "$1").trim();
4298
- }
4299
- function replaceEmbeddedFullAccess(root, localized) {
4300
- if (typeof document === "undefined" || localized === "Full access") return 0;
4301
- const doc = root instanceof Document ? root : root.ownerDocument;
4302
- if (doc === null) return 0;
4303
- const walker = doc.createTreeWalker(root, NodeFilter.SHOW_TEXT);
4304
- let changed = 0;
4305
- let node = walker.nextNode();
4306
- while (node !== null) {
4307
- const value = node.nodeValue;
4308
- if (value !== null && (value.includes("Full access") || value.includes("Full Access"))) {
4309
- node.nodeValue = replaceFullAccessLabel(value, localized);
4310
- changed += 1;
4311
- }
4312
- node = walker.nextNode();
4313
- }
4314
- return changed;
4315
- }
4316
- function permissionCopy(id, t) {
4317
- return {
4318
- title: t(`permission.${id}.title`),
4319
- description: t(`permission.${id}.description`),
4320
- trigger: t(`permission.${id}.trigger`)
4321
- };
4322
- }
4323
- function leafTextSpans(root) {
4324
- return [...root.querySelectorAll("span")].filter((span) => span.childElementCount === 0 && (span.textContent ?? "").trim() !== "");
4325
- }
4326
- function visibleText(root) {
4327
- return (root.textContent ?? "").replace(/\s+/g, " ").trim();
4328
- }
4329
- function applyCopy(label, copy, asTrigger) {
4330
- const title = asTrigger ? copy.trigger : copy.title;
4331
- let titleNode = label.querySelector("[data-dcu-perm-title]");
4332
- let descNode = label.querySelector("[data-dcu-perm-desc]");
4333
- if (titleNode === null) {
4334
- label.textContent = "";
4335
- titleNode = label.ownerDocument.createElement("span");
4336
- titleNode.setAttribute("data-dcu-perm-title", "1");
4337
- label.append(titleNode);
4338
- }
4339
- if (titleNode.textContent !== title) titleNode.textContent = title;
4340
- if (asTrigger) {
4341
- descNode?.remove();
4342
- return;
4343
- }
4344
- if (descNode === null) {
4345
- descNode = label.ownerDocument.createElement("span");
4346
- descNode.setAttribute("data-dcu-perm-desc", "1");
4347
- label.append(descNode);
4348
- }
4349
- if (descNode.textContent !== copy.description) descNode.textContent = copy.description;
4257
+ return FULL_ACCESS_LABELS.some((label) => normalized === label || normalized.includes(label));
4350
4258
  }
4351
- /** 把当前文档里的权限选择器改成当前语言的 Codex 文案。 */
4352
- function localizePermissionMenus(root, t) {
4259
+ function markFullAccessPermissionMenus(root) {
4353
4260
  let changed = 0;
4354
- for (const button of root.querySelectorAll("button")) {
4355
- const menuitem = button.getAttribute("role") === "menuitem";
4356
- const marked = button.getAttribute("data-dcu-perm");
4357
- const spans = leafTextSpans(button);
4358
- const id = permissionIdFromLabel(visibleText(button)) ?? marked ?? void 0;
4359
- if (id === void 0) continue;
4360
- const label = button.querySelector("[data-dcu-perm-title]")?.parentElement ?? spans[0];
4361
- if (label === void 0) continue;
4362
- const copy = permissionCopy(id, t);
4363
- const nextTitle = menuitem ? copy.title : copy.trigger;
4364
- const titleNode = label.querySelector("[data-dcu-perm-title]");
4365
- const descNode = label.querySelector("[data-dcu-perm-desc]");
4366
- if (marked === id && titleNode?.textContent === nextTitle && (menuitem ? descNode?.textContent === copy.description : descNode === null)) continue;
4367
- button.setAttribute("data-dcu-perm", id);
4368
- applyCopy(label, copy, !menuitem);
4261
+ for (const button of root.querySelectorAll("button[role=\"menuitem\"]")) {
4262
+ if (!isFullAccessPermission((button.textContent ?? "").replace(/\s+/g, " "))) continue;
4263
+ if (button.getAttribute("data-dcu-perm") === "danger-full-access") continue;
4264
+ button.setAttribute("data-dcu-perm", "danger-full-access");
4369
4265
  changed += 1;
4370
4266
  }
4371
- changed += replaceEmbeddedFullAccess(root, t("permission.danger-full-access.trigger"));
4372
4267
  return changed;
4373
4268
  }
4374
- function observePermissionMenus(t) {
4269
+ function observePermissionMenus() {
4375
4270
  if (typeof document === "undefined") return () => {};
4376
- const styleId = "dcu-permission-i18n";
4271
+ const styleId = "dcu-permission-risk";
4377
4272
  if (document.getElementById(styleId) === null) {
4378
4273
  const style = document.createElement("style");
4379
4274
  style.id = styleId;
4380
- style.textContent = PERMISSION_I18N_STYLE;
4275
+ style.textContent = PERMISSION_RISK_STYLE;
4381
4276
  document.head.append(style);
4382
4277
  }
4383
4278
  let applying = false;
@@ -4386,7 +4281,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
4386
4281
  if (applying) return;
4387
4282
  applying = true;
4388
4283
  try {
4389
- localizePermissionMenus(document, t);
4284
+ markFullAccessPermissionMenus(document);
4390
4285
  } finally {
4391
4286
  applying = false;
4392
4287
  }
@@ -4796,7 +4691,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
4796
4691
  en
4797
4692
  }), "michengai-codex-ui: dictionaries");
4798
4693
  const t = ctx.locale.bind(NS);
4799
- ctx.effect(() => observePermissionMenus((key) => t(key)), "michengai-codex-ui: permission i18n");
4694
+ ctx.effect(() => observePermissionMenus(), "michengai-codex-ui: permission risk highlight");
4800
4695
  ctx.effect(() => observeSlimSidebar(), "michengai-codex-ui: slim sidebar");
4801
4696
  ctx.effect(() => observeSettingsNavIcons(), "michengai-codex-ui: settings nav icons");
4802
4697
  ctx.effect(() => observeConversationHeader(), "michengai-codex-ui: conversation header");
package/dist/index.mjs CHANGED
@@ -333,16 +333,16 @@ function runDshPlugin(args) {
333
333
  /** 并发安装互斥:pnpm 锁文件竞争会触发 EPERM/EBUSY,同一时间只允许一个安装进程。 */
334
334
  let installing = false;
335
335
  /** 仅允许安装固定依赖,避免把浏览器输入转成任意命令。 */
336
- async function installDependency(id) {
336
+ async function installDependency(id, requestHotUpdate = requestDesktopHotUpdate) {
337
337
  if (installing) throw new Error("已有依赖安装正在进行,请等待完成后再试。");
338
338
  installing = true;
339
339
  try {
340
- return await installDependencyLocked(id);
340
+ return await installDependencyLocked(id, requestHotUpdate);
341
341
  } finally {
342
342
  installing = false;
343
343
  }
344
344
  }
345
- async function installDependencyLocked(id) {
345
+ async function installDependencyLocked(id, requestHotUpdate) {
346
346
  const dependency = managedDependency(id);
347
347
  if (dependency === void 0) throw new Error("不支持安装该依赖。");
348
348
  const latestVersion = await npmLatestVersion(dependency.packageName);
@@ -356,7 +356,7 @@ async function installDependencyLocked(id) {
356
356
  await ensureLatestReleaseAllowed(target, targetVersion);
357
357
  if (!isOfficialRuntimePackage(target)) await recordDeclaredVersion(target, targetVersion);
358
358
  await recordPendingUpdate(target, targetVersion);
359
- if (requestDesktopHotUpdate()) return dependencyStatuses();
359
+ if (requestHotUpdate()) return dependencyStatuses();
360
360
  try {
361
361
  await runDshPlugin([
362
362
  "add",
@@ -497,7 +497,11 @@ function apply(ctx) {
497
497
  response.end(JSON.stringify({ error: "已拒绝跨站请求。" }));
498
498
  return;
499
499
  }
500
- const dependencies = await installDependency(url.searchParams.get("dependency"));
500
+ let restartAfterResponse = false;
501
+ const dependencies = await installDependency(url.searchParams.get("dependency"), () => {
502
+ restartAfterResponse = typeof process.send === "function";
503
+ return restartAfterResponse;
504
+ });
501
505
  response.writeHead(200, {
502
506
  "content-type": "application/json; charset=utf-8",
503
507
  "cache-control": "no-store"
@@ -506,6 +510,9 @@ function apply(ctx) {
506
510
  dependencies,
507
511
  restartRequired: true
508
512
  }));
513
+ if (restartAfterResponse) setTimeout(() => {
514
+ requestDesktopHotUpdate();
515
+ }, 150).unref?.();
509
516
  return;
510
517
  }
511
518
  response.writeHead(405);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@michengai/dsh-codex-ui",
3
- "version": "0.2.67",
3
+ "version": "0.2.69",
4
4
  "description": "以 Codex 风格重构 DSH Web 侧栏的独立客户端插件",
5
5
  "license": "Apache-2.0",
6
6
  "publishConfig": {