dsh-custom-mode 1.11.4 → 1.11.6

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.i18n.yaml CHANGED
@@ -1,5 +1,5 @@
1
1
  # 双语配对一致性记录:两侧在「上次确认一致」时的 git blob 哈希。
2
2
  # 两份文档权威相同——改完任意一侧,请把另一侧也改掉,然后重新记录:
3
3
  # node tools/verify-translation-pairing.mjs --write
4
- README.md: d8f40717eedc2d2270be9f6982b4f6d6f0ddd0ff
5
- README.zh.md: a63ba3cef3b184b4c8d7cbb083aa4607d4dd8cdb
4
+ README.md: b432cc8ec19134c8a09d73e7642f9986363d188a
5
+ README.zh.md: 95e765c6ee1eae02c3ee1db344e31b3b00cbfad1
package/README.md CHANGED
@@ -59,7 +59,7 @@ One command installs everything — the settings-page plugin, and the preset it
59
59
  activation:
60
60
 
61
61
  ```sh
62
- dsh plugin --profile web add dsh-custom-mode@1.11.4 # pin the version to get this one for sure
62
+ dsh plugin --profile web add dsh-custom-mode@1.11.6 # pin the version to get this one for sure
63
63
  # A bare `add dsh-custom-mode` is subject to pnpm's release cooldown (`minimumReleaseAge`, 1 day by
64
64
  # default): for hours after a release it can silently install an OLDER version — measured: a bare
65
65
  # install 38 minutes after 1.3.0 shipped landed on 1.0.3. Check what you got with `npm ls
@@ -118,7 +118,7 @@ Electron shell**, so this plugin's page renders there unchanged. One install pat
118
118
  too and points you at the app, so the two agree instead of one silently working around the other.
119
119
  (A lab simulation of the profile shape can override it with `DSH_ALLOW_DESKTOP_PROFILE=1`.)
120
120
  **The app's own bundled CLI is the exception** — `<install>\resources\runtime\cli\bin\dsh.cmd` is allowed
121
- to operate on that profile (measured on 1.11.1: `add dsh-custom-mode@1.11.4` → `+ dsh-custom-mode 1.11.1`).
121
+ to operate on that profile (measured on 1.11.1: `add dsh-custom-mode@1.11.6` → `+ dsh-custom-mode 1.11.1`).
122
122
  It is a launcher, not a dsh feature: it starts Electron with `ELECTRON_RUN_AS_NODE=1` and runs the
123
123
  desktop-host CLI, so it is the app talking to its own profile rather than something driving from outside.
124
124
  - **Nothing else to do on the preset side**: `$DSH_HOME/.agent-presets/` is product data shared by the
@@ -430,7 +430,7 @@ installing again — your data is not touched:
430
430
 
431
431
  ```sh
432
432
  # the pinned form: what you ask for is what you get
433
- dsh plugin --profile web add dsh-custom-mode@1.11.4
433
+ dsh plugin --profile web add dsh-custom-mode@1.11.6
434
434
  # then restart the DSH process that serves the web profile
435
435
  ```
436
436
 
package/README.zh.md CHANGED
@@ -48,7 +48,7 @@ base mode / plugin switches / multi-assistant / multi-persona。
48
48
  一条命令装完——设置页插件,以及它在首次激活时自动播种的 preset:
49
49
 
50
50
  ```sh
51
- dsh plugin --profile web add dsh-custom-mode@1.11.4 # 钉版本才能确定拿到这一版
51
+ dsh plugin --profile web add dsh-custom-mode@1.11.6 # 钉版本才能确定拿到这一版
52
52
  # 不带版本号会受 pnpm 的发布冷却期影响(`minimumReleaseAge`,默认一天):发布后数小时内按名安装
53
53
  # 可能**静默装到旧版** —— 实测 1.3.0 发布 38 分钟后按名安装装到了 1.0.3。用 profile 里的
54
54
  # `npm ls dsh-custom-mode` 核对实际装到的版本,或像上面那样钉版本。
@@ -98,7 +98,7 @@ dsh `0.1.6-alpha.2` 起有插件管理页:**侧边栏 → 插件 → 添加插
98
98
  `cordis.patch.yml`。所以 `install.sh` 也**拒绝** `--profile desktop` 并指向应用内安装 —— 两边一致,
99
99
  而不是某一方偷偷绕过去。(只想在本机模拟 profile 形状时可设 `DSH_ALLOW_DESKTOP_PROFILE=1`。)
100
100
  **应用自带的捆绑 CLI 是例外**:`<安装目录>\resources\runtime\cli\bin\dsh.cmd` 可以操作那个 profile
101
- (1.11.1 实测:`add dsh-custom-mode@1.11.4` → `+ dsh-custom-mode 1.11.1`)。它是启动器而不是 dsh 的
101
+ (1.11.1 实测:`add dsh-custom-mode@1.11.6` → `+ dsh-custom-mode 1.11.1`)。它是启动器而不是 dsh 的
102
102
  新功能 —— 它用 `ELECTRON_RUN_AS_NODE=1` 起 Electron 去跑 desktop-host 的 CLI,所以那是**应用在跟自己的
103
103
  profile 说话**,不是从外面驱动它。
104
104
  - **预设那一侧不用做任何事**:`$DSH_HOME/.agent-presets/` 是桌面端与 CLI 共享的产品数据,
@@ -330,7 +330,7 @@ MIT
330
330
 
331
331
  ```sh
332
332
  # 钉版本的写法:要哪版就是哪版
333
- dsh plugin --profile web add dsh-custom-mode@1.11.4
333
+ dsh plugin --profile web add dsh-custom-mode@1.11.6
334
334
  # 然后重启为该 profile 提供服务的 DSH 进程
335
335
  ```
336
336
 
package/client.js CHANGED
@@ -61,11 +61,10 @@ try {
61
61
  const ZH = {
62
62
  "nav": "自定义模式",
63
63
  "assistant.heading": "助手",
64
- "assistant.hint": "每个助手即一个独立模式:独立的系统提示词、基础模式与插件开关。新建会话时在模式选择器中选择。",
64
+ "assistant.hint": "每个助手即一个独立模式:独立的系统提示词、基础模式与插件开关。新建会话时在模式选择器中选用。",
65
65
  "assistant.empty": "还没有助手,用下面的输入框新建一个。",
66
66
  "assistant.loadingList": "正在读取助手列表…",
67
67
  "assistant.newPlaceholder": "新助手的名字(例如:写作助手)",
68
- "assistant.meta": "标识",
69
68
  "assistant.copyName": "「{name}」副本",
70
69
  "assistant.broken": "本机无法启动",
71
70
  "assistant.brokenRows": "{count} 行在本机不可用",
@@ -83,7 +82,7 @@ try {
83
82
  "btn.delete": "删除这个助手",
84
83
  "btn.cancel": "取消",
85
84
  "msg.created": "已创建。现在可以为它写系统提示词。",
86
- "msg.duplicated": "已复制。两份从此各改各的。",
85
+ "msg.duplicated": "已复制。两份配置彼此独立。",
87
86
  "msg.deleted": "已删除。",
88
87
  "msg.createFailed": "创建失败",
89
88
  "msg.deleteFailed": "删除失败",
@@ -99,16 +98,9 @@ try {
99
98
  "api.alreadyLast": "「{name}」已经在最后面。",
100
99
  "api.badVariableName": "变量引用的写法不合法:{variable} 里的名字只能用小写字母、数字、下划线,且以字母开头。要写字面量花括号,请用单个左花括号,或不闭合的双左花括号。",
101
100
  "api.unknownVariable": "{variable} 不是已注册的变量,渲染会报错并让本模式每个请求都失败。可用:{known}。",
102
- "assistant.short": "每个助手是一个独立模式:自己的系统提示词、基础模式与插件开关。",
103
- "name.short": "改名只影响显示,内部标识与已有会话不受影响。",
104
- "mode.short": "底子决定「行集合」与工具能力;persona 行始终由本模式替换。",
105
101
  "mode.unavailable": "本机这条 DSH 线没有可读的出厂组成,基础模式暂时不能切换。",
106
102
  "rows.unavailable": "出厂组成取不到,插件开关暂时不能编辑;磁盘上原有的行状态仍然生效。",
107
- "mode.pendingRows": "底子已改为「{mode}」:保存后,下面的行列表会按新底子重算。",
108
- "rows.short": "逐行控制挂载哪些插件;没拨过的行保持官方默认。",
109
- "prompt.short": "这段文本就是本模式的系统提示词,保存后下一步生效。",
110
- "aria.expandHint": "展开完整说明",
111
- "aria.collapseHint": "收起完整说明",
103
+ "mode.pendingRows": "基础模式已改为「{mode}」:保存后,下面的行列表会按新的基础模式重算。",
112
104
  "aria.expand": "展开详情",
113
105
  "aria.collapse": "收起详情",
114
106
  "detail.id": "行 id",
@@ -129,7 +121,7 @@ try {
129
121
  "api.saved": "已保存({name},基础模式 {mode})。新建会话即生效,当前会话保持原配置。",
130
122
  "api.savedWithExclusiveRows": "已保存({name},基础模式 {mode})。两套壳注册同名工具、不能同时启用 —— 已自动关掉:{rows}。新建会话即生效,当前会话保持原配置。",
131
123
  "api.created": "已创建「{name}」。现在可以为它写系统提示词。",
132
- "api.duplicated": "已复制自「{from}」。两份从此各改各的。",
124
+ "api.duplicated": "已复制自「{from}」。两份配置彼此独立。",
133
125
  "api.deleted": "已删除「{name}」。正在使用它的会话不受影响;新建会话时它不再出现。",
134
126
  "api.reordered": "顺序已保存:新建会话时的模式选择器按这个顺序排列。",
135
127
  "api.nameRequired": "请先给新助手起个名字。",
@@ -163,9 +155,7 @@ try {
163
155
  "warn.presetBroken": "平台判这个模式为 broken,它会从新会话的选择器里消失 —— 而上面的「无法解析」检查解释不了原因(多半是某一行依赖的服务没起来)。点下方「按本线修复」把那几行关掉;平台自己给的原因见下面那行。",
164
156
  "warn.exclusiveRowsActive": "两条互斥的壳同时开着(它们注册同名工具),平台会判整个模式为 broken 并从新会话的选择器里丢掉。关掉其中一条即可;在设置页保存一次也会自动避让。",
165
157
  "warn.baseCompositionUnavailable": "取不到本机这条 DSH 线的出厂组成:基础模式与插件开关暂时不能改(系统提示词不受影响,照常可保存)。已尝试的途径写在宿主日志里。",
166
- "warn.approvalGateMissing.label": "审批闸门未启用",
167
- "warn.approvalGateMissing.hint": "这个 DSH 版本没有 tools/pre-execute 事件,会话内改写系统提示词不会弹审批。设置页不受影响;要恢复保护请升级 DSH,或把「custom_prompt 工具」那一行关掉。",
168
- "warn.personaOffWithPrompt": "「身份(系统提示词)」这一行是关的,所以 prompt.md 不会被注入 —— 你写的提示词现在不起作用。要么打开这一行,要么清空提示词。",
158
+ "warn.personaOffWithPrompt": "「身份(系统提示词)」这一行是关的,所以 prompt.md 不会被注入 —— 所写的提示词不会生效。打开这一行,或清空提示词。",
169
159
  "warn.toolOff": "「custom_prompt 工具」这一行是关的:会话里无法让 agent 改提示词,只能在本页改。",
170
160
  "warn.noDescription": "没有描述:新建会话的模式选择器里会显示成「暂无描述」。",
171
161
  "warn.noName": "没有名字:模式选择器里会显示成目录 id(例如 custom)。",
@@ -191,9 +181,9 @@ try {
191
181
  "name.placeholder": "自定义模式",
192
182
  "name.descriptionPlaceholder": "模式描述(显示在模式选择器里,可留空)",
193
183
  "mode.heading": "基础模式",
194
- "mode.hint": "底子只决定「行集合」与工具能力:本模式的身份行始终替换底子那一行(提示词由你编辑,complete: false),底子的提示语语义不继承。保存后新建会话即生效,无需重启。",
184
+ "mode.hint": "基础模式只决定行集合与工具能力:本模式的身份行始终替换基础模式的那一行(提示词由本页编辑,complete: false),不继承其提示语语义。保存后新建会话即生效,无需重启。",
195
185
  "rows.heading": "插件开关",
196
- "rows.hint": "逐行控制本模式挂载的插件。未拨动的行保持官方默认(含平台判断);手动拨动后以你的为准。",
186
+ "rows.hint": "逐行控制本模式挂载的插件。未改动的行保持官方默认(含平台判断);手动设置后以手动值为准。",
197
187
  "prompt.heading": "系统提示词",
198
188
  "prompt.hint": "每次模型调用前重新读取:保存后下一步生效,仅影响使用本助手的会话。「导入」读文件进编辑器(保存前不写入);「导出」存为 .md;「恢复出厂提示词」填回出厂模板(同样需保存)。",
199
189
  "status.enabled": "已启用",
@@ -206,9 +196,6 @@ try {
206
196
  "btn.reload": "重新读取",
207
197
  "btn.reloadDiscard": "放弃修改并重新读取",
208
198
  "msg.unsaved": "有未保存的修改",
209
- "msg.loading": "正在读取…",
210
- "msg.notLoaded": "(尚未读取)",
211
- "msg.reread": "已重新读取",
212
199
  "msg.readFailed": "读取失败",
213
200
  "msg.saveFailed": "保存失败",
214
201
  "msg.saved": "已保存。新建会话即生效,当前会话保持原配置。",
@@ -274,7 +261,13 @@ try {
274
261
  "base.ptc.note": "在标准模式基础上启用 PTC 工具呈现(tool-presentation)",
275
262
  "base.minimal.label": "极简模式",
276
263
  "base.minimal.note": "只有 Shell 与终端,共 7 行;没有文件、检索、技能、子代理。系统提示词不是极简那一套(persona 行被本模式替换)",
277
- "base.cordis.label": "Cordis 模式",
264
+ // ★ 与官方对齐:cordis 这个模式在官方界面里叫「创造模式」(英文 Creator mode),
265
+ // 不是「Cordis 模式」—— 实测 `dsh-client-ui-agent-preset` 的词典:
266
+ // `presetCordisName: "创造模式"` / `"Creator mode"`(0.1.7-rc.2 与 0.2.0-rc.2 同名)。
267
+ // 「Cordis」在官方用语里是**技术名**(Cordis 插件 / Cordis 运行时),不是模式名。
268
+ // 此前这里写「Cordis 模式」、而同一份词典的 `base.all.note` 又写「创造模式」,
269
+ // 同一个模式在一页里有两个名字:用户点了「Cordis 模式」药丸,读到的说明却说「创造模式」。
270
+ "base.cordis.label": "创造模式",
278
271
  "base.cordis.note": "标准模式 + 读写运行时的 Cordis 工具集,可让 agent 自己改 harness",
279
272
  "base.all.label": "自定义模式",
280
273
  "base.all.note": "不继承任何单一原生模式:以标准模式的全套行为底,补上只有 PTC / 极简 / 创造模式才有的行,全部都能逐行开关"
@@ -287,7 +280,6 @@ try {
287
280
  "assistant.empty": "No assistants yet — create one with the field below.",
288
281
  "assistant.loadingList": "Loading assistants…",
289
282
  "assistant.newPlaceholder": "Name of the new assistant (e.g. Writing assistant)",
290
- "assistant.meta": "ID",
291
283
  "assistant.copyName": "{name} (copy)",
292
284
  "assistant.broken": "Will not start here",
293
285
  "assistant.brokenRows": "{count} row(s) unusable here",
@@ -321,16 +313,9 @@ try {
321
313
  "api.alreadyLast": "{name} is already last.",
322
314
  "api.badVariableName": "{variable} is not a valid variable reference: names may use lower-case letters, digits and underscores, and must start with a letter. For a literal brace, use a single opening brace or an unclosed double brace.",
323
315
  "api.unknownVariable": "{variable} is not a registered variable — rendering would fail every request in this mode. Available: {known}.",
324
- "assistant.short": "Each assistant is its own mode: its own system prompt, base mode and plugin switches.",
325
- "name.short": "Renaming only changes what is displayed — not the internal id or existing sessions.",
326
- "mode.short": "The base decides the row set and tool abilities; the persona row is always replaced by this mode.",
327
316
  "mode.unavailable": "This DSH line exposes no readable shipped composition, so the base mode cannot be switched right now.",
328
317
  "rows.unavailable": "No shipped composition is available, so the plugin switches cannot be edited right now; the row states already on disk still apply.",
329
- "mode.pendingRows": "Base changed to {mode}: the row list below is recomputed from the new base when you save.",
330
- "rows.short": "Control which plugins this mode mounts, row by row; untouched rows keep the shipped default.",
331
- "prompt.short": "Saving this text makes it the system prompt of this mode, and it takes effect on the next step.",
332
- "aria.expandHint": "Show the full explanation",
333
- "aria.collapseHint": "Hide the full explanation",
318
+ "mode.pendingRows": "Base mode changed to {mode}: the row list below is recomputed from it when you save.",
334
319
  "aria.expand": "Show details",
335
320
  "aria.collapse": "Hide details",
336
321
  "detail.id": "Row id",
@@ -380,15 +365,13 @@ try {
380
365
  "api.badJson": "The request body is not valid JSON",
381
366
  "api.savedPromptOnly": "System prompt saved (this machine exposes no shipped composition, so the plugin switches and the base mode were left untouched).",
382
367
  "api.baseCompositionUnavailable": "No shipped composition for base mode \"{mode}\" on this machine, so its plugin switches and base mode cannot be changed (the system prompt can still be saved on its own).",
383
- "warn.personaOffWithPrompt": "The \"Identity (system prompt)\" row is off, so prompt.md is never injected — the prompt you wrote has no effect. Turn the row on, or clear the prompt.",
368
+ "warn.personaOffWithPrompt": "The \"Identity (system prompt)\" row is off, so prompt.md is never injected — the prompt being edited has no effect. Turn the row on, or clear the prompt.",
384
369
  "warn.toolOff": "The \"custom_prompt tool\" row is off: the agent cannot change the prompt from inside a session, only this page can.",
385
370
  "warn.noDescription": "No description: the new-session mode picker will show it as \"no description yet\".",
386
371
  "warn.approvalGateMissing": "The approval gate is off: this DSH build has no tools/pre-execute event, so in-session prompt rewrites do not ask for approval. See the details.",
387
372
  "warn.unresolvableRows": "Some rows cannot be resolved on this DSH line: the platform marks the whole mode broken and silently drops it from the new-session picker. Click Fix for this line — it only turns those rows off and leaves your other choices alone.",
388
373
  "warn.presetBroken": "The platform marks this mode broken, so it disappears from the new-session picker — and the \"unresolvable\" check above cannot explain why (usually a row whose service or engine never started). Click Fix for this line to turn those rows off. The host's own reason is in Details.",
389
374
  "warn.exclusiveRowsActive": "Both shells are on, and they register the same tool names: the platform marks the whole mode broken and silently drops it from the new-session picker. Turn one of them off — saving from the settings page also resolves it automatically.",
390
- "warn.approvalGateMissing.label": "Approval gate is off",
391
- "warn.approvalGateMissing.hint": "This DSH build has no tools/pre-execute event, so in-session prompt rewrites do NOT ask for approval. The settings page is unaffected; upgrade DSH or turn the custom_prompt tool row off to restore the gate.",
392
375
  "warn.noName": "No name: the mode picker will show the directory id (e.g. custom).",
393
376
  "warn.baseCompositionUnavailable": "This DSH line exposes no shipped composition: the base mode and the plugin switches cannot be changed right now (the system prompt is unaffected and still saves). The routes that were tried are in the host log.",
394
377
  "history.label": "Change history",
@@ -415,22 +398,19 @@ try {
415
398
  "mode.heading": "Base mode",
416
399
  "mode.hint": "The base decides the row set and the tool abilities: this mode always replaces the base's persona row with its own reader (complete: false), so the base's prompt semantics are not inherited. A save applies to the next new session; no restart needed.",
417
400
  "rows.heading": "Plugin switches",
418
- "rows.hint": "Control row by row which plugins this mode mounts, laid out like the official plugin list. Untouched rows keep the official default (platform conditions included); your manual choice wins.",
401
+ "rows.hint": "Control row by row which plugins this mode mounts. Untouched rows keep the official default (platform conditions included); an explicit choice wins.",
419
402
  "prompt.heading": "System prompt",
420
403
  "prompt.hint": "This text is re-read before every model call, so a save applies on the next step and only affects sessions on this assistant. \"Import\" reads a file into the editor (nothing is written until you save); \"Export\" saves the current text as a .md file; \"Reset to factory prompt\" puts the shipped template back into the editor (also saved only when you save).",
421
404
  "status.enabled": "Enabled",
422
405
  "status.disabled": "Disabled",
423
406
  "status.changed": "changed",
424
- "tag.essential": "core",
407
+ "tag.essential": "Core",
425
408
  "tag.followPlatform": "follows platform",
426
409
  "btn.save": "Save",
427
410
  "btn.saving": "Working…",
428
411
  "btn.reload": "Reload",
429
412
  "btn.reloadDiscard": "Discard edits and reload",
430
413
  "msg.unsaved": "Unsaved changes",
431
- "msg.loading": "Loading…",
432
- "msg.notLoaded": "(not loaded)",
433
- "msg.reread": "Reloaded",
434
414
  "msg.readFailed": "Load failed",
435
415
  "msg.saveFailed": "Save failed",
436
416
  "msg.saved": "Saved. A new session picks it up; the current one keeps its configuration.",
@@ -490,16 +470,20 @@ try {
490
470
  "row.persistent-bash.label": "Persistent bash",
491
471
  "row.terminal-pwsh.label": "Terminal (pwsh)",
492
472
  "row.persistent-pwsh.label": "Persistent pwsh",
493
- "base.standard.label": "Standard",
473
+ // ★ 与官方选择器逐字一致(实测 `dsh-client-ui-agent-preset` 的英文字典,两版 DSH 同名):
474
+ // 官方英文名都带 " mode" 后缀 —— "Standard mode" / "PTC mode" / "Minimal mode" /
475
+ // "Creator mode"。本仓此前写成 "Standard" / "PTC" / "Minimal" / "Cordis",
476
+ // 与用户在官方模式选择器里看到的同一个模式名对不上。
477
+ "base.standard.label": "Standard mode",
494
478
  "base.standard.note": "Full coding agent: shell, files, search, skills, planning, goals, subagents, workflows",
495
- "base.ptc.label": "PTC",
479
+ "base.ptc.label": "PTC mode",
496
480
  "base.ptc.note": "Standard plus PTC tool presentation (tool-presentation)",
497
- "base.minimal.label": "Minimal",
481
+ "base.minimal.label": "Minimal mode",
498
482
  "base.minimal.note": "Shell and terminal only, 7 rows; no files, search, skills or subagents. The system prompt is not minimal's either (this mode replaces the persona row)",
499
- "base.cordis.label": "Cordis",
483
+ "base.cordis.label": "Creator mode",
500
484
  "base.cordis.note": "Standard plus the Cordis toolset, letting the agent modify its own harness",
501
- "base.all.label": "Custom",
502
- "base.all.note": "Inherits no single shipped mode: standard's full row list plus the rows only PTC / Minimal / Cordis declare, every one of them switchable"
485
+ "base.all.label": "Custom mode",
486
+ "base.all.note": "Inherits no single shipped mode: standard's full row list plus the rows only PTC / Minimal / Creator declare, every one of them switchable"
503
487
  }
504
488
 
505
489
  const TRANSLATIONS = { zh: ZH, en: EN }
@@ -651,12 +635,14 @@ try {
651
635
  IconChevronDownOutline14: "IconChevronDownOutlineRegular",
652
636
  IconChevronUpOutline14: "IconChevronUpOutlineRegular",
653
637
  IconChevronLeftOutline14: "IconChevronLeftOutlineRegular",
638
+ IconChevronRightOutline14: "IconChevronRightOutlineRegular",
654
639
  IconPlusOutline16: "IconPlusOutlineRegular",
655
640
  IconCheckOutline14: "IconCheckOutlineRegular",
656
641
  IconCopyOutline16: "IconCopyOutlineRegular",
657
642
  IconDownloadOutline16: "IconDownloadOutlineRegular",
658
643
  IconRefreshOutline16: "IconRefreshOutlineRegular",
659
644
  IconTrashOutline16: "IconTrashOutlineRegular",
645
+ IconWarningOutline14: "IconWarningOutlineRegular",
660
646
  }
661
647
 
662
648
  function withIconAliases(atoms) {
@@ -700,16 +686,20 @@ try {
700
686
  */
701
687
  const CSS = [
702
688
  ".cpfe{--g:8px;display:flex;flex-direction:column;gap:24px;width:100%;max-width:900px;box-sizing:border-box;padding-bottom:16px}",
703
- // ★ 区块标题对齐官方设置页的度量(实测 0.1.7-rc.2:区块标题 14px/22px w500,引言 12px/18px
704
- // tertiary)。原来是 15px w700 —— 在官方页面里那看起来就是"另一个产品"。
705
- ".cpfe-h{margin:0 0 2px;font-size:14px;line-height:22px;font-weight:500;color:var(--dsw-alias-label-primary)}",
689
+ // 分节标题:度量抄官方设置面板里的同类文本。
690
+ // 实测(**0.1.7-rc.2 与 0.2.0-rc.2 各量一次,结论相同**):官方 `_title`(设置行标题)
691
+ // 与 `groupTitle`(插件页分组标题)都是 14px/22px **w400**;官方唯一的 14px w500 是插件
692
+ // 卡片标题(`cardTitle`,行高 20px,形态不同),页级标题则是 16px/24px w500。
693
+ // 本页是设置面板里的分节,取 w400。
694
+ // ⚠️ 本仓长期记作「官方区块标题 14px/22px w500」—— 那一条在 2026-10-02 的复量中被证伪。
695
+ ".cpfe-h{margin:0 0 2px;font-size:14px;line-height:22px;font-weight:400;color:var(--dsw-alias-label-primary)}",
706
696
  ".cpfe-sub{margin:0 0 8px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary)}",
707
697
  // 区块引言:官方是标题下的一行 12px 灰字 —— 没有折叠按钮,也没有那个蓝色圆点。
708
698
  ".cpfe-hint{display:flex;flex-direction:column;gap:2px;margin:0 0 6px}",
709
699
  ".cpfe-hint-line{font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary)}",
710
700
  ".cpfe-hint-detail{margin:0;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary)}",
711
701
  // 描述:多行、自适应高度(没有多行输入组件,所以用 textarea + 同一批语义变量)
712
- ".cpfe-desc{box-sizing:border-box;min-height:56px;max-height:200px;resize:vertical;padding:8px 12px;border-radius:10px;border:.5px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;line-height:20px;margin-bottom:8px}",
702
+ ".cpfe-desc{box-sizing:border-box;min-height:56px;max-height:200px;resize:vertical;padding:8px 12px;border-radius:var(--dsw-radius-md);border:.5px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;line-height:20px;margin-bottom:8px}",
713
703
  ".cpfe-base-pending{color:var(--dsw-alias-state-warn-primary)}",
714
704
  ".cpfe-note{display:block;margin:8px 0 0;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary)}",
715
705
  ".cpfe-mono{display:block;margin:0;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere}",
@@ -725,11 +715,11 @@ try {
725
715
  ".cpfe-actions{display:flex;flex-wrap:wrap;gap:var(--g);align-items:center;margin-top:4px}",
726
716
  ".cpfe-newrow{display:flex;gap:var(--g);align-items:center;flex-wrap:wrap;margin-top:10px}",
727
717
  ".cpfe-field{display:flex;width:100%;margin-bottom:8px}",
728
- ".cpfe-row-head{font-size:14px;line-height:20px;color:var(--dsw-alias-label-primary)}",
718
+ ".cpfe-row-head{font-size:14px;line-height:22px;color:var(--dsw-alias-label-primary)}",
729
719
  ".cpfe-row-switch{flex:0 0 auto}",
730
720
  ".cpfe-row-line{display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-width:0}",
731
721
  ".cpfe-row-note{min-height:18px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}",
732
- ".cpfe-row-toggle{flex:0 0 auto;width:22px;height:22px;padding:0;border:0;border-radius:6px;background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer;font-size:12px;line-height:1}",
722
+ ".cpfe-row-toggle{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;border:0;border-radius:var(--dsw-radius-sm);background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer}",
733
723
  ".cpfe-row-toggle:hover{background:var(--dsw-alias-bg-layer-2)}",
734
724
  ".cpfe-row-open{border-color:var(--dsw-alias-border-l2)}",
735
725
  ".cpfe-row-detail{display:flex;flex-direction:column;gap:4px;margin:0 0 12px;padding:0 0 0 16px;border:0;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary)}",
@@ -746,10 +736,10 @@ try {
746
736
  ".cpfe-line:last-child{border-bottom:0}",
747
737
  ".cpfe-group{display:flex;flex-direction:column;min-width:0}",
748
738
  ".cpfe-kids{display:flex;flex-direction:column;margin-left:0;padding-left:16px}",
749
- ".cpfe-row{display:flex;gap:12px;align-items:center;box-sizing:border-box;min-height:0;padding:12px 0;border:0;border-radius:0;background:none}",
739
+ ".cpfe-row{display:flex;gap:12px;align-items:center;box-sizing:border-box;min-height:0;padding:16px 0;border:0;border-radius:0;background:none}",
750
740
  ".cpfe-row-meta{display:flex;flex-direction:column;gap:4px;min-width:0;flex:1}",
751
741
  ".cpfe-row-badges{display:flex;align-items:center;gap:6px;flex-wrap:wrap;height:18px}",
752
- ".cpfe-editor{box-sizing:border-box;width:100%;min-height:240px;resize:vertical;padding:12px;border-radius:10px;border:.5px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13px;line-height:20px}",
742
+ ".cpfe-editor{box-sizing:border-box;width:100%;min-height:240px;resize:vertical;padding:12px;border-radius:var(--dsw-radius-md);border:.5px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13px;line-height:20px}",
753
743
  ".cpfe-bar{display:flex;align-items:center;gap:var(--g);flex-wrap:wrap}",
754
744
  ".cpfe-status{font-size:13px;line-height:20px}",
755
745
  ".cpfe-ok{color:var(--dsw-alias-label-secondary)}",
@@ -760,12 +750,12 @@ try {
760
750
  ".cpfe-version{font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary);white-space:nowrap}",
761
751
  ".cpfe-path{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere}",
762
752
  // ── fallback-path controls (unused when the shell provides the atoms) ──
763
- ".cpfe-btn{appearance:none;cursor:pointer;padding:0 14px;height:32px;border-radius:8px;border:.5px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px}",
764
- ".cpfe-btn:disabled{opacity:.5;cursor:default}",
765
- ".cpfe-btn-sm{height:28px;padding:0 10px;font-size:12px}",
753
+ ".cpfe-btn{appearance:none;cursor:pointer;padding:0 14px;height:36px;border-radius:var(--dsw-radius-md);border:.5px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary);font:inherit;font-size:14px}",
754
+ ".cpfe-btn:disabled{opacity:.4;cursor:not-allowed}",
755
+ ".cpfe-btn-sm{height:28px;padding:0 10px;font-size:12px;line-height:18px;border-radius:var(--dsw-radius-sm)}",
766
756
  ".cpfe-btn-primary{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-base);border-color:transparent;font-weight:500}",
767
757
  ".cpfe-btn-ghost{border-color:transparent;background:transparent}",
768
- ".cpfe-input{box-sizing:border-box;width:100%;height:34px;padding:0 12px;border-radius:8px;border:.5px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px}",
758
+ ".cpfe-input{box-sizing:border-box;width:100%;height:36px;padding:0 12px;border-radius:var(--dsw-radius-md);border:.5px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px}",
769
759
  ".cpfe-switch{display:inline-flex;align-items:center;gap:8px;cursor:pointer;font-size:13px;line-height:19px;color:var(--dsw-alias-label-primary)}",
770
760
  // 忙碌期间禁掉草稿类控件的交互(issue #6)。
771
761
  // 状态层已经拦住了改动(`update()` 在 busy 时直接返回),但对**受控组件**来说,
@@ -780,6 +770,26 @@ try {
780
770
  ".cpfe-tag-danger{color:var(--dsw-alias-state-error-primary)}",
781
771
  ".cpfe-pill{appearance:none;cursor:pointer;height:28px;padding:0 12px;border-radius:999px;border:.5px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-secondary);font:inherit;font-size:13px}",
782
772
  ".cpfe-pill-on{border-color:var(--dsw-alias-label-primary);color:var(--dsw-alias-label-primary)}",
773
+ // ── 官方的「设置项下拉」形态 ────────────────────────────────────────────
774
+ // 实测(**0.1.7-rc.2 与 0.2.0-rc.2 各量一次,结论相同**):官方的 `_selector` 是
775
+ // height 36px · border-radius var(--dsw-radius-md) · background var(--dsw-alias-bg-module-platform)
776
+ // · padding 0 14px · font-size 14px/line-height 22px · gap 12px,hover 换
777
+ // var(--dsw-alias-interactive-bg-hover)。
778
+ // 壳的 Button 只有 primary / ghost / outline / toolbar 四种变体,没有"灰底选择器"这一种 ——
779
+ // 官方各设置页也是**各自定义** `_selector`(oY77xG / hVGvvW / _2XZxNq / T1PP_q 各一份、
780
+ // 度量完全一致),所以这里照同一套度量自绘,做法与官方一致。
781
+ // 双类选择器(`.cpfe .cpfe-selector`)用来压过壳 Button 的单类变体规则,
782
+ // 免得 `_ghost_` / `_sm_` 把灰底和高度覆盖掉。
783
+ ".cpfe .cpfe-selector{height:36px;padding:0 14px;gap:12px;border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-primary);font-size:14px;line-height:22px;font-weight:400}",
784
+ ".cpfe .cpfe-selector:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}",
785
+ // ── 告警区 ──────────────────────────────────────────────────────────────
786
+ // 这一段此前**一条 CSS 都没有**(2026-10-02 逐表核对:样式表里 `cpfe-warn` 零规则),
787
+ // 于是出现告警时它是一串没有排版的裸 `<p>`:没有行距、图标与文字不对齐、
788
+ // 与页面其余部分(12px/18px)的字号也对不上。度量沿用页面其余部分。
789
+ ".cpfe-warns{display:flex;flex-direction:column;gap:12px}",
790
+ ".cpfe-warn-row{display:flex;flex-direction:column;gap:6px;align-items:flex-start}",
791
+ ".cpfe-warn{display:flex;gap:6px;align-items:flex-start;margin:0;font-size:12px;line-height:18px;color:var(--dsw-alias-state-warn-primary)}",
792
+ ".cpfe-warn svg{flex:0 0 auto;margin-top:2px}",
783
793
  ].join("")
784
794
 
785
795
  /** Apply the page stylesheet once, keyed so a re-mount never duplicates it. */
@@ -890,21 +900,21 @@ try {
890
900
  }
891
901
 
892
902
  /**
893
- * A section's one-line hint, with the full explanation behind a disclosure.
903
+ * A section's one-line introduction, sitting under its heading.
894
904
  *
895
- * The sections used to open with a paragraph each. On a real screen that is a wall of text above the
896
- * controls the user came for, and the same "compact line + open on demand" language as the row list keeps
897
- * the page scannable without dropping a word of the explanation.
905
+ * It takes ONE string and renders it as one line — the shape the official settings pages use:
906
+ * a single 12px/18px tertiary line under the title, with no disclosure control and no bullet.
907
+ *
908
+ * It used to take `hint` + `detail` and pick `detail` when present, for a collapsible
909
+ * introduction that no longer exists. Every caller passed both, so the short form was
910
+ * **never rendered** — five dictionary entries (`assistant.short`, `name.short`, `mode.short`,
911
+ * `rows.short`, `prompt.short`) that looked alive in a grep but reached no pixel. Both are gone.
898
912
  */
899
913
  function SectionHint(props) {
900
- const { hint, detail } = props
901
- // 官方设置页的区块引言就是标题下的一段 12px 灰字:没有圆点、没有折叠按钮,也**不重复**。
902
- // 有完整说明就用完整说明(它是短句的超集),否则用短句 —— 两个都印会在屏幕上出现两遍。
903
- const text = typeof detail === "string" && detail !== "" ? detail : hint
904
914
  return react.createElement(
905
915
  "div",
906
916
  { className: "cpfe-hint" },
907
- react.createElement("span", { className: "cpfe-hint-line" }, text),
917
+ react.createElement("span", { className: "cpfe-hint-line" }, props.text),
908
918
  )
909
919
  }
910
920
 
@@ -971,7 +981,12 @@ try {
971
981
  "aria-label": t(open ? "aria.collapse" : "aria.expand"),
972
982
  onClick: () => onToggleExpand(row.id),
973
983
  },
974
- open ? "▾" : "▸",
984
+ // 用壳自己的图标,不再手绘 "▸"/"▾" 字符:字符的字形、基线与粗细都随字体走,
985
+ // 与官方那一排 14px 线性图标放在一起就是两种东西。壳没提供时退回原字符。
986
+ (() => {
987
+ const Icon = open ? A.IconChevronDownOutline14 : A.IconChevronRightOutline14
988
+ return renderable(Icon) ? react.createElement(Icon, { size: 14 }) : open ? "▾" : "▸"
989
+ })(),
975
990
  ),
976
991
  react.createElement(A.Switch, {
977
992
  checked: effective,
@@ -1595,14 +1610,7 @@ try {
1595
1610
  "section",
1596
1611
  null,
1597
1612
  react.createElement("h2", { className: "cpfe-h" }, t("assistant.heading")),
1598
- react.createElement(SectionHint, {
1599
- id: "hint:assistant",
1600
- hint: t("assistant.short", t("assistant.hint")),
1601
- detail: t("assistant.hint"),
1602
- expanded: expandedRows,
1603
- onToggleExpand: toggleRowExpanded,
1604
- t: t,
1605
- }),
1613
+ react.createElement(SectionHint, { text: t("assistant.hint") }),
1606
1614
  list === null
1607
1615
  ? react.createElement("p", { className: "cpfe-sub" }, t("assistant.loadingList"))
1608
1616
  : assistants.length === 0
@@ -1627,14 +1635,17 @@ try {
1627
1635
  A.Button,
1628
1636
  {
1629
1637
  variant: "ghost",
1630
- size: "sm",
1638
+ className: "cpfe-selector",
1631
1639
  disabled: busy,
1632
- icon: renderable(A.IconChevronDownOutline14)
1633
- ? react.createElement(A.IconChevronDownOutline14, { size: 14 })
1634
- : null,
1635
1640
  onClick: () => setAssistantOpen((open) => open !== true),
1636
1641
  },
1637
1642
  (assistants.find((item) => item.id === selected) || {}).name || selected || t("assistant.heading"),
1643
+ // 官方设置项的下拉是「文字在左、chevron 在右」(实测「通用设置」页的
1644
+ // 「工作区内修改 / 中文 / 详细」都是这个形态)⇒ 图标放在 children 末尾,
1645
+ // 不走 `icon` prop —— 那个会渲染到文字**前面**,成为页面上唯一一个反向的下拉。
1646
+ renderable(A.IconChevronDownOutline14)
1647
+ ? react.createElement(A.IconChevronDownOutline14, { size: 14 })
1648
+ : null,
1638
1649
  ),
1639
1650
  items: assistants.map((item) => ({
1640
1651
  id: item.id,
@@ -1651,7 +1662,7 @@ try {
1651
1662
  })
1652
1663
  : react.createElement(
1653
1664
  "div",
1654
- { className: "cpfe-pills cpfe-assistants" },
1665
+ { className: "cpfe-pills" },
1655
1666
  assistants.map((item) =>
1656
1667
  react.createElement(
1657
1668
  "span",
@@ -1725,14 +1736,7 @@ try {
1725
1736
  "section",
1726
1737
  { key: "name" },
1727
1738
  react.createElement("h2", { className: "cpfe-h" }, t("name.heading")),
1728
- react.createElement(SectionHint, {
1729
- id: "hint:name",
1730
- hint: t("name.short", t("name.hint")),
1731
- detail: t("name.hint"),
1732
- expanded: expandedRows,
1733
- onToggleExpand: toggleRowExpanded,
1734
- t: t,
1735
- }),
1739
+ react.createElement(SectionHint, { text: t("name.hint") }),
1736
1740
  react.createElement(A.Input, {
1737
1741
  className: "cpfe-field",
1738
1742
  value: draft.name,
@@ -1808,14 +1812,7 @@ try {
1808
1812
  "section",
1809
1813
  { key: "mode" },
1810
1814
  react.createElement("h2", { className: "cpfe-h" }, t("mode.heading")),
1811
- react.createElement(SectionHint, {
1812
- id: "hint:mode",
1813
- hint: t("mode.short", t("mode.hint")),
1814
- detail: t("mode.hint"),
1815
- expanded: expandedRows,
1816
- onToggleExpand: toggleRowExpanded,
1817
- t: t,
1818
- }),
1815
+ react.createElement(SectionHint, { text: t("mode.hint") }),
1819
1816
  // 降级态(本机这条线没有可读的出厂组成):不给可点的模式药丸,改说一句为什么 ——
1820
1817
  // 点了也只会拿到一个服务端错误,那比置灰更糟。
1821
1818
  draft.baseUnavailable !== null
@@ -1851,14 +1848,7 @@ try {
1851
1848
  "section",
1852
1849
  { key: "rows" },
1853
1850
  react.createElement("h2", { className: "cpfe-h" }, t("rows.heading")),
1854
- react.createElement(SectionHint, {
1855
- id: "hint:rows",
1856
- hint: t("rows.short", t("rows.hint")),
1857
- detail: t("rows.hint"),
1858
- expanded: expandedRows,
1859
- onToggleExpand: toggleRowExpanded,
1860
- t: t,
1861
- }),
1851
+ react.createElement(SectionHint, { text: t("rows.hint") }),
1862
1852
  draft.baseUnavailable !== null
1863
1853
  ? react.createElement("p", { className: "cpfe-note" }, t("rows.unavailable"))
1864
1854
  : react.createElement(RowList, {
@@ -1934,14 +1924,7 @@ try {
1934
1924
  }),
1935
1925
  ),
1936
1926
  ),
1937
- react.createElement(SectionHint, {
1938
- id: "hint:prompt",
1939
- hint: t("prompt.short", t("prompt.hint")),
1940
- detail: t("prompt.hint"),
1941
- expanded: expandedRows,
1942
- onToggleExpand: toggleRowExpanded,
1943
- t: t,
1944
- }),
1927
+ react.createElement(SectionHint, { text: t("prompt.hint") }),
1945
1928
  react.createElement("textarea", {
1946
1929
  className: "cpfe-editor",
1947
1930
  value: draft.prompt,
@@ -1976,11 +1959,8 @@ try {
1976
1959
  A.Button,
1977
1960
  {
1978
1961
  variant: "ghost",
1979
- size: "sm",
1962
+ className: "cpfe-selector",
1980
1963
  disabled: busy,
1981
- icon: renderable(A.IconChevronDownOutline14)
1982
- ? react.createElement(A.IconChevronDownOutline14, { size: 14 })
1983
- : null,
1984
1964
  onClick: () => setHistoryOpen((open) => open !== true),
1985
1965
  },
1986
1966
  draft.historyPick === ""
@@ -1991,6 +1971,9 @@ try {
1991
1971
  ? t("history.pick")
1992
1972
  : formatWhen(entry.at) + " · " + t("history.by." + entry.by)
1993
1973
  })(),
1974
+ renderable(A.IconChevronDownOutline14)
1975
+ ? react.createElement(A.IconChevronDownOutline14, { size: 14 })
1976
+ : null,
1994
1977
  ),
1995
1978
  items: draft.history.map((entry) => ({
1996
1979
  id: String(entry.n),
@@ -2053,7 +2036,17 @@ try {
2053
2036
  react.createElement(
2054
2037
  "div",
2055
2038
  { key: code, className: "cpfe-warn-row" },
2056
- react.createElement("p", { className: "cpfe-warn" }, "⚠ " + t("warn." + code)),
2039
+ react.createElement(
2040
+ "p",
2041
+ { className: "cpfe-warn" },
2042
+ // 图标与文本分成两个节点:文本单独包一层 span,`align-items:flex-start`
2043
+ // 才能把图标钉在**第一行**,而不是让它在一段多行告警里垂直居中。
2044
+ // 壳没提供图标时退回原来的 "⚠" 字符。
2045
+ renderable(A.IconWarningOutline14)
2046
+ ? react.createElement(A.IconWarningOutline14, { size: 14 })
2047
+ : "⚠",
2048
+ react.createElement("span", null, t("warn." + code)),
2049
+ ),
2057
2050
  // 平台自己给的那句话(`state.broken`,形如
2058
2051
  // `tool-workflow (@deepseek-ai/dsh-tool-workflow): waiting for workflowEngine`)。
2059
2052
  //
package/locales.mjs CHANGED
@@ -21,11 +21,10 @@ export const zh = {
21
21
  // ── 助手管理 ──────────────────────────────────────────────────────────────
22
22
  'assistant.heading': '助手',
23
23
  'assistant.hint':
24
- '每个助手即一个独立模式:独立的系统提示词、基础模式与插件开关。新建会话时在模式选择器中选择。',
24
+ '每个助手即一个独立模式:独立的系统提示词、基础模式与插件开关。新建会话时在模式选择器中选用。',
25
25
  'assistant.empty': '还没有助手,用下面的输入框新建一个。',
26
26
  'assistant.loadingList': '正在读取助手列表…',
27
27
  'assistant.newPlaceholder': '新助手的名字(例如:写作助手)',
28
- 'assistant.meta': '标识',
29
28
  'assistant.copyName': '「{name}」副本',
30
29
  'assistant.broken': '本机无法启动',
31
30
  // 带上具体行数:只说「有问题」用户不知道有多严重,也不知道修完会怎样。
@@ -45,7 +44,7 @@ export const zh = {
45
44
  'btn.delete': '删除这个助手',
46
45
  'btn.cancel': '取消',
47
46
  'msg.created': '已创建。现在可以为它写系统提示词。',
48
- 'msg.duplicated': '已复制。两份从此各改各的。',
47
+ 'msg.duplicated': '已复制。两份配置彼此独立。',
49
48
  'msg.deleted': '已删除。',
50
49
  'msg.createFailed': '创建失败',
51
50
  'msg.deleteFailed': '删除失败',
@@ -61,16 +60,9 @@ export const zh = {
61
60
  'api.alreadyLast': '「{name}」已经在最后面。',
62
61
  'api.badVariableName': '变量引用的写法不合法:{variable} 里的名字只能用小写字母、数字、下划线,且以字母开头。要写字面量花括号,请用单个左花括号,或不闭合的双左花括号。',
63
62
  'api.unknownVariable': '{variable} 不是已注册的变量,渲染会报错并让本模式每个请求都失败。可用:{known}。',
64
- 'assistant.short': '每个助手是一个独立模式:自己的系统提示词、基础模式与插件开关。',
65
- 'name.short': '改名只影响显示,内部标识与已有会话不受影响。',
66
- 'mode.short': '底子决定「行集合」与工具能力;persona 行始终由本模式替换。',
67
63
  'mode.unavailable': '本机这条 DSH 线没有可读的出厂组成,基础模式暂时不能切换。',
68
64
  'rows.unavailable': '出厂组成取不到,插件开关暂时不能编辑;磁盘上原有的行状态仍然生效。',
69
- 'mode.pendingRows': '底子已改为「{mode}」:保存后,下面的行列表会按新底子重算。',
70
- 'rows.short': '逐行控制挂载哪些插件;没拨过的行保持官方默认。',
71
- 'prompt.short': '这段文本就是本模式的系统提示词,保存后下一步生效。',
72
- 'aria.expandHint': '展开完整说明',
73
- 'aria.collapseHint': '收起完整说明',
65
+ 'mode.pendingRows': '基础模式已改为「{mode}」:保存后,下面的行列表会按新的基础模式重算。',
74
66
  'aria.expand': '展开详情',
75
67
  'aria.collapse': '收起详情',
76
68
  'detail.id': '行 id',
@@ -91,7 +83,7 @@ export const zh = {
91
83
  'api.saved': '已保存({name},基础模式 {mode})。新建会话即生效,当前会话保持原配置。',
92
84
  'api.savedWithExclusiveRows': '已保存({name},基础模式 {mode})。两套壳注册同名工具、不能同时启用 —— 已自动关掉:{rows}。新建会话即生效,当前会话保持原配置。',
93
85
  'api.created': '已创建「{name}」。现在可以为它写系统提示词。',
94
- 'api.duplicated': '已复制自「{from}」。两份从此各改各的。',
86
+ 'api.duplicated': '已复制自「{from}」。两份配置彼此独立。',
95
87
  'api.deleted': '已删除「{name}」。正在使用它的会话不受影响;新建会话时它不再出现。',
96
88
  'api.reordered': '顺序已保存:新建会话时的模式选择器按这个顺序排列。',
97
89
  'api.nameRequired': '请先给新助手起个名字。',
@@ -125,9 +117,7 @@ export const zh = {
125
117
  'warn.presetBroken': '平台判这个模式为 broken,它会从新会话的选择器里消失 —— 而上面的「无法解析」检查解释不了原因(多半是某一行依赖的服务没起来)。点下方「按本线修复」把那几行关掉;平台自己给的原因见下面那行。',
126
118
  'warn.exclusiveRowsActive': '两条互斥的壳同时开着(它们注册同名工具),平台会判整个模式为 broken 并从新会话的选择器里丢掉。关掉其中一条即可;在设置页保存一次也会自动避让。',
127
119
  'warn.baseCompositionUnavailable': '取不到本机这条 DSH 线的出厂组成:基础模式与插件开关暂时不能改(系统提示词不受影响,照常可保存)。已尝试的途径写在宿主日志里。',
128
- 'warn.approvalGateMissing.label': '审批闸门未启用',
129
- 'warn.approvalGateMissing.hint': '这个 DSH 版本没有 tools/pre-execute 事件,会话内改写系统提示词不会弹审批。设置页不受影响;要恢复保护请升级 DSH,或把「custom_prompt 工具」那一行关掉。',
130
- 'warn.personaOffWithPrompt': '「身份(系统提示词)」这一行是关的,所以 prompt.md 不会被注入 —— 你写的提示词现在不起作用。要么打开这一行,要么清空提示词。',
120
+ 'warn.personaOffWithPrompt': '「身份(系统提示词)」这一行是关的,所以 prompt.md 不会被注入 —— 所写的提示词不会生效。打开这一行,或清空提示词。',
131
121
  'warn.toolOff': '「custom_prompt 工具」这一行是关的:会话里无法让 agent 改提示词,只能在本页改。',
132
122
  'warn.noDescription': '没有描述:新建会话的模式选择器里会显示成「暂无描述」。',
133
123
  'warn.noName': '没有名字:模式选择器里会显示成目录 id(例如 custom)。',
@@ -155,10 +145,10 @@ export const zh = {
155
145
  'name.descriptionPlaceholder': '模式描述(显示在模式选择器里,可留空)',
156
146
 
157
147
  'mode.heading': '基础模式',
158
- 'mode.hint': '底子只决定「行集合」与工具能力:本模式的身份行始终替换底子那一行(提示词由你编辑,complete: false),底子的提示语语义不继承。保存后新建会话即生效,无需重启。',
148
+ 'mode.hint': '基础模式只决定行集合与工具能力:本模式的身份行始终替换基础模式的那一行(提示词由本页编辑,complete: false),不继承其提示语语义。保存后新建会话即生效,无需重启。',
159
149
 
160
150
  'rows.heading': '插件开关',
161
- 'rows.hint': '逐行控制本模式挂载的插件。未拨动的行保持官方默认(含平台判断);手动拨动后以你的为准。',
151
+ 'rows.hint': '逐行控制本模式挂载的插件。未改动的行保持官方默认(含平台判断);手动设置后以手动值为准。',
162
152
 
163
153
  'prompt.heading': '系统提示词',
164
154
  'prompt.hint':
@@ -176,9 +166,6 @@ export const zh = {
176
166
  'btn.reloadDiscard': '放弃修改并重新读取',
177
167
 
178
168
  'msg.unsaved': '有未保存的修改',
179
- 'msg.loading': '正在读取…',
180
- 'msg.notLoaded': '(尚未读取)',
181
- 'msg.reread': '已重新读取',
182
169
  'msg.readFailed': '读取失败',
183
170
  'msg.saveFailed': '保存失败',
184
171
  'msg.saved': '已保存。新建会话即生效,当前会话保持原配置。',
@@ -244,13 +231,19 @@ export const zh = {
244
231
  'row.persistent-pwsh.label': '持久 pwsh',
245
232
 
246
233
  // ── base mode labels ──────────────────────────────────────────────────────
234
+ // ★ 名字与官方界面逐字一致。实测 `dsh-client-ui-agent-preset` 的词典
235
+ // (0.1.7-rc.2 与 0.2.0-rc.2 同名):standard「标准模式」/ ptc「PTC 模式」/
236
+ // minimal「极简模式」/ cordis「**创造模式**」(英文 `Creator mode`)。
237
+ // 「Cordis」在官方用语里是技术名(Cordis 插件 / Cordis 运行时),不是模式名;
238
+ // 本仓此前把 cordis 写「Cordis 模式」,而同一份词典的 `base.all.note` 又写「创造模式」——
239
+ // 同一个模式在一页里有两个名字。英文侧四个名字此前都缺官方的 " mode" 后缀。
247
240
  'base.standard.label': '标准模式',
248
241
  'base.standard.note': '完整编码能力:Shell、文件、检索、技能、计划、目标、子代理、工作流',
249
242
  'base.ptc.label': 'PTC 模式',
250
243
  'base.ptc.note': '在标准模式基础上启用 PTC 工具呈现(tool-presentation)',
251
244
  'base.minimal.label': '极简模式',
252
245
  'base.minimal.note': '只有 Shell 与终端,共 7 行;没有文件、检索、技能、子代理。系统提示词不是极简那一套(persona 行被本模式替换)',
253
- 'base.cordis.label': 'Cordis 模式',
246
+ 'base.cordis.label': '创造模式',
254
247
  'base.cordis.note': '标准模式 + 读写运行时的 Cordis 工具集,可让 agent 自己改 harness',
255
248
  'base.all.label': '自定义模式',
256
249
  'base.all.note': '不继承任何单一原生模式:以标准模式的全套行为底,补上只有 PTC / 极简 / 创造模式才有的行,全部都能逐行开关',
@@ -267,7 +260,6 @@ export const en = {
267
260
  'assistant.empty': 'No assistants yet — create one with the field below.',
268
261
  'assistant.loadingList': 'Loading assistants…',
269
262
  'assistant.newPlaceholder': 'Name of the new assistant (e.g. Writing assistant)',
270
- 'assistant.meta': 'ID',
271
263
  'assistant.copyName': '{name} (copy)',
272
264
  'assistant.broken': 'Will not start here',
273
265
  'assistant.brokenRows': '{count} row(s) unusable here',
@@ -301,16 +293,9 @@ export const en = {
301
293
  'api.alreadyLast': '{name} is already last.',
302
294
  'api.badVariableName': '{variable} is not a valid variable reference: names may use lower-case letters, digits and underscores, and must start with a letter. For a literal brace, use a single opening brace or an unclosed double brace.',
303
295
  'api.unknownVariable': '{variable} is not a registered variable — rendering would fail every request in this mode. Available: {known}.',
304
- 'assistant.short': 'Each assistant is its own mode: its own system prompt, base mode and plugin switches.',
305
- 'name.short': 'Renaming only changes what is displayed — not the internal id or existing sessions.',
306
- 'mode.short': 'The base decides the row set and tool abilities; the persona row is always replaced by this mode.',
307
296
  'mode.unavailable': 'This DSH line exposes no readable shipped composition, so the base mode cannot be switched right now.',
308
297
  'rows.unavailable': 'No shipped composition is available, so the plugin switches cannot be edited right now; the row states already on disk still apply.',
309
- 'mode.pendingRows': 'Base changed to {mode}: the row list below is recomputed from the new base when you save.',
310
- 'rows.short': 'Control which plugins this mode mounts, row by row; untouched rows keep the shipped default.',
311
- 'prompt.short': 'Saving this text makes it the system prompt of this mode, and it takes effect on the next step.',
312
- 'aria.expandHint': 'Show the full explanation',
313
- 'aria.collapseHint': 'Hide the full explanation',
298
+ 'mode.pendingRows': 'Base mode changed to {mode}: the row list below is recomputed from it when you save.',
314
299
  'aria.expand': 'Show details',
315
300
  'aria.collapse': 'Hide details',
316
301
  'detail.id': 'Row id',
@@ -360,15 +345,13 @@ export const en = {
360
345
  'api.badJson': 'The request body is not valid JSON',
361
346
  'api.savedPromptOnly': 'System prompt saved (this machine exposes no shipped composition, so the plugin switches and the base mode were left untouched).',
362
347
  'api.baseCompositionUnavailable': 'No shipped composition for base mode "{mode}" on this machine, so its plugin switches and base mode cannot be changed (the system prompt can still be saved on its own).',
363
- 'warn.personaOffWithPrompt': 'The "Identity (system prompt)" row is off, so prompt.md is never injected — the prompt you wrote has no effect. Turn the row on, or clear the prompt.',
348
+ 'warn.personaOffWithPrompt': 'The "Identity (system prompt)" row is off, so prompt.md is never injected — the prompt being edited has no effect. Turn the row on, or clear the prompt.',
364
349
  'warn.toolOff': 'The "custom_prompt tool" row is off: the agent cannot change the prompt from inside a session, only this page can.',
365
350
  'warn.noDescription': 'No description: the new-session mode picker will show it as "no description yet".',
366
351
  'warn.approvalGateMissing': 'The approval gate is off: this DSH build has no tools/pre-execute event, so in-session prompt rewrites do not ask for approval. See the details.',
367
352
  'warn.unresolvableRows': 'Some rows cannot be resolved on this DSH line: the platform marks the whole mode broken and silently drops it from the new-session picker. Click Fix for this line — it only turns those rows off and leaves your other choices alone.',
368
353
  'warn.presetBroken': 'The platform marks this mode broken, so it disappears from the new-session picker — and the "unresolvable" check above cannot explain why (usually a row whose service or engine never started). Click Fix for this line to turn those rows off. The host\'s own reason is in Details.',
369
354
  'warn.exclusiveRowsActive': 'Both shells are on, and they register the same tool names: the platform marks the whole mode broken and silently drops it from the new-session picker. Turn one of them off — saving from the settings page also resolves it automatically.',
370
- 'warn.approvalGateMissing.label': 'Approval gate is off',
371
- 'warn.approvalGateMissing.hint': 'This DSH build has no tools/pre-execute event, so in-session prompt rewrites do NOT ask for approval. The settings page is unaffected; upgrade DSH or turn the custom_prompt tool row off to restore the gate.',
372
355
  'warn.noName': 'No name: the mode picker will show the directory id (e.g. custom).',
373
356
  'warn.baseCompositionUnavailable': 'This DSH line exposes no shipped composition: the base mode and the plugin switches cannot be changed right now (the system prompt is unaffected and still saves). The routes that were tried are in the host log.',
374
357
  'history.label': 'Change history',
@@ -401,7 +384,7 @@ export const en = {
401
384
 
402
385
  'rows.heading': 'Plugin switches',
403
386
  'rows.hint':
404
- 'Control row by row which plugins this mode mounts, laid out like the official plugin list. Untouched rows keep the official default (platform conditions included); your manual choice wins.',
387
+ 'Control row by row which plugins this mode mounts. Untouched rows keep the official default (platform conditions included); an explicit choice wins.',
405
388
 
406
389
  'prompt.heading': 'System prompt',
407
390
  'prompt.hint':
@@ -410,7 +393,7 @@ export const en = {
410
393
  'status.enabled': 'Enabled',
411
394
  'status.disabled': 'Disabled',
412
395
  'status.changed': 'changed',
413
- 'tag.essential': 'core',
396
+ 'tag.essential': 'Core',
414
397
  'tag.followPlatform': 'follows platform',
415
398
 
416
399
  'btn.save': 'Save',
@@ -419,9 +402,6 @@ export const en = {
419
402
  'btn.reloadDiscard': 'Discard edits and reload',
420
403
 
421
404
  'msg.unsaved': 'Unsaved changes',
422
- 'msg.loading': 'Loading…',
423
- 'msg.notLoaded': '(not loaded)',
424
- 'msg.reread': 'Reloaded',
425
405
  'msg.readFailed': 'Load failed',
426
406
  'msg.saveFailed': 'Save failed',
427
407
  'msg.saved': 'Saved. A new session picks it up; the current one keeps its configuration.',
@@ -485,14 +465,14 @@ export const en = {
485
465
  'row.persistent-pwsh.label': 'Persistent pwsh',
486
466
 
487
467
  // ── base mode labels ──────────────────────────────────────────────────────
488
- 'base.standard.label': 'Standard',
468
+ 'base.standard.label': 'Standard mode',
489
469
  'base.standard.note': 'Full coding agent: shell, files, search, skills, planning, goals, subagents, workflows',
490
- 'base.ptc.label': 'PTC',
470
+ 'base.ptc.label': 'PTC mode',
491
471
  'base.ptc.note': 'Standard plus PTC tool presentation (tool-presentation)',
492
- 'base.minimal.label': 'Minimal',
472
+ 'base.minimal.label': 'Minimal mode',
493
473
  'base.minimal.note': 'Shell and terminal only, 7 rows; no files, search, skills or subagents. The system prompt is not minimal\'s either (this mode replaces the persona row)',
494
- 'base.cordis.label': 'Cordis',
474
+ 'base.cordis.label': 'Creator mode',
495
475
  'base.cordis.note': 'Standard plus the Cordis toolset, letting the agent modify its own harness',
496
- 'base.all.label': 'Custom',
497
- 'base.all.note': "Inherits no single shipped mode: standard's full row list plus the rows only PTC / Minimal / Cordis declare, every one of them switchable",
476
+ 'base.all.label': 'Custom mode',
477
+ 'base.all.note': "Inherits no single shipped mode: standard's full row list plus the rows only PTC / Minimal / Creator declare, every one of them switchable",
498
478
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-custom-mode",
3
- "version": "1.11.4",
3
+ "version": "1.11.6",
4
4
  "description": "Custom modes and custom prompts for DeepSeek Harness (dsh): edit a mode's system prompt on the settings page (it takes effect on the next model step), pick its base mode, switch plugin rows one by one, and keep several assistants side by side — coding, chat or roleplay (RP) personas (multi-mode / multi-agent).",
5
5
  "license": "MIT",
6
6
  "type": "module",