dsh-custom-mode 2.2.1 → 2.2.3
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 +2 -2
- package/README.md +26 -11
- package/README.zh.md +26 -11
- package/client.js +129 -79
- package/defaults.mjs +7 -3
- package/locales.mjs +25 -11
- package/package.json +5 -2
- package/preset-backend/declarative.mjs +13 -1
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:
|
|
5
|
-
README.zh.md:
|
|
4
|
+
README.md: 00045c14e30c98d389fc658906146272bfd82c7f
|
|
5
|
+
README.zh.md: afac5524be240ba1c38a6ac9ba17be15e0acc4bd
|
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ Edit a DeepSeek Harness (`dsh`) custom mode: system prompt, base mode, and plugi
|
|
|
24
24
|
Pin the version. A bare name can install an older build during pnpm's release cooldown. Details: [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md).
|
|
25
25
|
|
|
26
26
|
```sh
|
|
27
|
-
dsh plugin --profile web add dsh-custom-mode@2.2.
|
|
27
|
+
dsh plugin --profile web add dsh-custom-mode@2.2.3
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
Restart the process that serves the profile. The version on the settings page is the one that is running.
|
|
@@ -37,17 +37,17 @@ On Windows, `install.sh` is bash and it needs a `dsh` executable on `PATH`. Othe
|
|
|
37
37
|
|
|
38
38
|
1. Open Settings → Custom mode.
|
|
39
39
|
2. Edit the system prompt. Save is directly under the editor.
|
|
40
|
-
3. A new session uses this assistant when `settings.yaml` has no `agent-presets.default` yet. An existing value is left as it is.
|
|
40
|
+
3. A new session uses this assistant when `settings.yaml` has no `agent-presets.default` yet. An existing value is left as it is. Flow-style, scalar, and alias `agent-presets` values are preserved without inserting YAML into them.
|
|
41
41
|
|
|
42
42
|
The prompt is `prompt.md`. The next time a model step is assembled, that file is read again. History can load an older draft into the editor; loading does not write. A save computed against an older copy is refused when the file changed underneath. The model can change the same file only through `custom_prompt`, which asks first.
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
The page is two branches. This assistant edits the one you have open, and all five base modes can be chosen. New assistant writes only when you click New assistant: Coding, Writing, and Chat stay selectable, and only the official Standard mode is lit. The other four official modes are dim and cannot be chosen there.
|
|
45
45
|
|
|
46
46
|
| Posture | After create |
|
|
47
47
|
| --- | --- |
|
|
48
|
-
| Develop |
|
|
49
|
-
| Write | Terminal off
|
|
50
|
-
| Chat | Files and terminal off. |
|
|
48
|
+
| Develop | Official Standard mode, tools as shipped. |
|
|
49
|
+
| Write | Official Standard mode. Terminal off, file tools on. |
|
|
50
|
+
| Chat | Official Standard mode. Files and terminal off. |
|
|
51
51
|
|
|
52
52
|
## Boundaries
|
|
53
53
|
|
|
@@ -59,13 +59,28 @@ New assistants start as one posture. That choice applies only to the assistant y
|
|
|
59
59
|
|
|
60
60
|
Declared range: `>=0.1.5-rc.2 <0.2.0-0 || >=0.1.6-alpha.1 <0.2.0-0 || >=0.1.7-alpha.1 <0.2.0-0 || >=0.2.0-0 <0.3.0-0 || >=0.2.1-alpha.1 <0.3.0-0`
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
On 2026-10-09, npm `latest` and `next` still name `0.2.0-rc.2`; `alpha` names `0.2.1-alpha.2`, published that day. Upstream has not published a final stable version yet.
|
|
63
|
+
|
|
64
|
+
| dsh | Channel | Checked for 2.2.3 |
|
|
63
65
|
| --- | --- | --- |
|
|
64
|
-
| `0.2.0-rc.2` |
|
|
65
|
-
| `0.2.1-alpha.
|
|
66
|
-
| `0.1.7-rc.2` | declared
|
|
66
|
+
| `0.2.0-rc.2` | npm `latest` / `next` | Exact npm host, packed plugin load, API lifecycle, settings and picker in Windows web profile |
|
|
67
|
+
| `0.2.1-alpha.2` | npm `alpha` | The same isolated checks, against this host's own preset declarations |
|
|
68
|
+
| `0.1.7-rc.2` | earlier declared line | Kept in the CI regression matrix |
|
|
69
|
+
|
|
70
|
+
Release waits for the unit, boot, and browser workflows. To reproduce against an already installed exact host:
|
|
71
|
+
|
|
72
|
+
```sh
|
|
73
|
+
node tools/compat-check.mjs --host-install /path/to/host --out /tmp/custom-mode-check
|
|
74
|
+
node tools/runtime-check.mjs --host-install /path/to/host --out /tmp/custom-mode-check --browser /path/to/chrome
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Both tools use a generated home and ordinary mock prompts. The runtime check exercises all five base modes, repeated saves, uninstall, reinstall, data preservation, and repeated installation. No model calls are needed. VMware and native Linux desktop results are not claimed.
|
|
78
|
+
|
|
79
|
+
## Plugin markets
|
|
80
|
+
|
|
81
|
+
`dshmarket`, DSH Plugin Hub (`dsh-plugin`), and DSH Plugin Store (`dshmarketplace-plugin`) use different catalogs but install the same profile bundle. The root npm manifest provides `dsh.bundle.patch`, the browser export, the public repository, and matching compatibility ranges; no extra runtime adapter or build script is needed.
|
|
67
82
|
|
|
68
|
-
|
|
83
|
+
Run `node tools/market-check.mjs --out /tmp/custom-mode-markets.json` to check their public discovery data. An inaccessible catalog or an unverified/stale listing is reported explicitly. The tool never runs catalog-provided shell commands or submits a listing. [Market interfaces and limits](docs/MARKETPLACES.md).
|
|
69
84
|
|
|
70
85
|
## Docs
|
|
71
86
|
|
package/README.zh.md
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
钉版本。只写包名时,pnpm 的发布冷却期可能装到旧版。细节见 [docs/TROUBLESHOOTING.zh.md](docs/TROUBLESHOOTING.zh.md)。
|
|
25
25
|
|
|
26
26
|
```sh
|
|
27
|
-
dsh plugin --profile web add dsh-custom-mode@2.2.
|
|
27
|
+
dsh plugin --profile web add dsh-custom-mode@2.2.3
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
重启为这个 profile 提供服务的进程。设置页上的版本号才是正在运行的版本。
|
|
@@ -37,17 +37,17 @@ dsh plugin --profile web add dsh-custom-mode@2.2.1
|
|
|
37
37
|
|
|
38
38
|
1. 打开设置 → 自定义模式。
|
|
39
39
|
2. 改系统提示词。保存按钮在编辑器下面。
|
|
40
|
-
3. `settings.yaml` 里还没有 `agent-presets.default`
|
|
40
|
+
3. `settings.yaml` 里还没有 `agent-presets.default` 时,新会话用这个助手。已经写过的值保持原样。`agent-presets` 使用行内对象、标量或别名时也原样保留,不向里面插入 YAML。
|
|
41
41
|
|
|
42
42
|
提示词是 `prompt.md`。下一步组装模型输入时会重读这个文件。历史可以把旧稿载入编辑器;载入不落盘。打开页面之后文件被改过时,这一次保存会被拒绝。模型要改同一份文件,只能走 `custom_prompt`,并且先问过你。
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
页面分成两支。当前助手改的是已经打开的这一位,基础模式五档都可以点。新建助手只在点「新增助手」时写入:开发、写作、聊天可以点,工具底只有官方标准模式是亮的。其余四档是暗的,在这一支里点不了。
|
|
45
45
|
|
|
46
46
|
| 姿态 | 新建之后 |
|
|
47
47
|
| --- | --- |
|
|
48
|
-
| 开发 |
|
|
49
|
-
| 写作 |
|
|
50
|
-
| 聊天 |
|
|
48
|
+
| 开发 | 官方标准模式,工具按出厂。 |
|
|
49
|
+
| 写作 | 官方标准模式。终端关,文件工具开。 |
|
|
50
|
+
| 聊天 | 官方标准模式。文件和终端关。 |
|
|
51
51
|
|
|
52
52
|
## 边界
|
|
53
53
|
|
|
@@ -59,13 +59,28 @@ dsh plugin --profile web add dsh-custom-mode@2.2.1
|
|
|
59
59
|
|
|
60
60
|
声明范围:`>=0.1.5-rc.2 <0.2.0-0 || >=0.1.6-alpha.1 <0.2.0-0 || >=0.1.7-alpha.1 <0.2.0-0 || >=0.2.0-0 <0.3.0-0 || >=0.2.1-alpha.1 <0.3.0-0`
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
2026-10-09 实时核对 npm:`latest` 和 `next` 仍是 `0.2.0-rc.2`,`alpha` 是当天发布的 `0.2.1-alpha.2`。上游尚未发布去掉预发布后缀的正式稳定版。
|
|
63
|
+
|
|
64
|
+
| dsh | 通道 | 2.2.3 核对 |
|
|
63
65
|
| --- | --- | --- |
|
|
64
|
-
| `0.2.0-rc.2` |
|
|
65
|
-
| `0.2.1-alpha.
|
|
66
|
-
| `0.1.7-rc.2` |
|
|
66
|
+
| `0.2.0-rc.2` | npm `latest` / `next` | 精确 npm 宿主、打包加载、API 生命周期、Windows web profile 设置页与选择器 |
|
|
67
|
+
| `0.2.1-alpha.2` | npm `alpha` | 同一套隔离检查,读取该宿主自己的预设声明 |
|
|
68
|
+
| `0.1.7-rc.2` | 先前声明支持的版本 | 保留在 CI 回归矩阵里 |
|
|
69
|
+
|
|
70
|
+
发布必须等待单元、启动和浏览器工作流通过。已有精确版本的宿主安装时,可以这样复现:
|
|
71
|
+
|
|
72
|
+
```sh
|
|
73
|
+
node tools/compat-check.mjs --host-install /path/to/host --out /tmp/custom-mode-check
|
|
74
|
+
node tools/runtime-check.mjs --host-install /path/to/host --out /tmp/custom-mode-check --browser /path/to/chrome
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
两项工具只使用新生成的 home 和普通 mock 提示词。运行检查覆盖全部五档基础模式、重复保存、卸载、重装、用户数据保留与重复安装,不需要调用模型。不宣称 VMware 或原生 Linux 桌面已通过验收。
|
|
78
|
+
|
|
79
|
+
## 插件市场
|
|
80
|
+
|
|
81
|
+
`dshmarket`、DSH Plugin Hub(`dsh-plugin`)和 DSH Plugin Store(`dshmarketplace-plugin`)使用不同目录,但安装的是同一个 profile bundle。根 npm 清单提供 `dsh.bundle.patch`、浏览器导出、公开仓库和一致的兼容范围,不需要额外的运行时适配器或构建脚本。
|
|
67
82
|
|
|
68
|
-
|
|
83
|
+
运行 `node tools/market-check.mjs --out /tmp/custom-mode-markets.json` 检查它们的公开发现数据。目录不可访问、条目未审核或数据过期都会明确报告。工具不执行目录提供的 shell 命令,也不提交收录。[市场接口与限制](docs/MARKETPLACES.zh.md)。
|
|
69
84
|
|
|
70
85
|
## 文档
|
|
71
86
|
|
package/client.js
CHANGED
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
* Browser half: 「自定义模式」settings page — the assistant manager.
|
|
3
3
|
*
|
|
4
4
|
* Blocks:
|
|
5
|
-
* 0. 助手 —
|
|
6
|
-
* 1.
|
|
7
|
-
* 2.
|
|
8
|
-
*
|
|
9
|
-
* 4. 插件开关 — collapsed until the user opens it.
|
|
5
|
+
* 0. 助手 — which assistant is selected.
|
|
6
|
+
* 1. 当前助手 — prompt, name, five live base modes, plugin switches.
|
|
7
|
+
* 2. 新建助手 — Coding / Writing / Chat stay selectable. The official
|
|
8
|
+
* modes are shown beside them, and only Standard is lit.
|
|
10
9
|
*
|
|
11
10
|
* Three decisions worth knowing before editing this file:
|
|
12
11
|
*
|
|
@@ -62,13 +61,20 @@ try {
|
|
|
62
61
|
"nav": "自定义模式",
|
|
63
62
|
"assistant.heading": "助手",
|
|
64
63
|
"assistant.hint": "每个助手单独保存系统提示词、基础模式和插件开关。",
|
|
65
|
-
"posture.hint": "
|
|
64
|
+
"posture.hint": "这一支只在点「新增助手」时写入。",
|
|
65
|
+
"tree.posture": "起步",
|
|
66
|
+
"tree.base": "工具底",
|
|
67
|
+
"tree.baseHold": "新建时固定用官方标准模式。",
|
|
68
|
+
"tree.baseSkip": "这一支点不了。建好后到「当前助手」里改。",
|
|
69
|
+
"tree.baseLocked": "只有官方标准模式是亮的。其余四档是暗的,新建时点不了。",
|
|
66
70
|
"posture.develop.label": "开发",
|
|
67
|
-
"posture.develop.note": "
|
|
71
|
+
"posture.develop.note": "官方标准模式,工具按出厂。",
|
|
68
72
|
"posture.write.label": "写作",
|
|
69
|
-
"posture.write.note": "
|
|
73
|
+
"posture.write.note": "官方标准模式。终端关闭,文件读写打开。",
|
|
70
74
|
"posture.chat.label": "聊天",
|
|
71
|
-
"posture.chat.note": "
|
|
75
|
+
"posture.chat.note": "官方标准模式。文件和终端关闭。",
|
|
76
|
+
"editor.heading": "当前助手",
|
|
77
|
+
"editor.hint": "这一支改上面选中的助手。基础模式五档都可以点。",
|
|
72
78
|
"assistant.empty": "还没有助手,用下面的输入框新建一个。",
|
|
73
79
|
"assistant.loadingList": "正在读取助手列表…",
|
|
74
80
|
"assistant.newPlaceholder": "新助手的名字(例如:写作助手)",
|
|
@@ -78,7 +84,7 @@ try {
|
|
|
78
84
|
"assistant.brokenHint": "此模式在本机无法启动,不会出现在新会话菜单里。点「按本线修复」只关闭那些行。",
|
|
79
85
|
"assistant.switchHint": "切换助手保留各自的未保存草稿;列表中的「未保存」标记即为此。",
|
|
80
86
|
"btn.create": "新增助手",
|
|
81
|
-
"create.heading": "
|
|
87
|
+
"create.heading": "新建助手",
|
|
82
88
|
"btn.creating": "创建中…",
|
|
83
89
|
"btn.duplicate": "复制",
|
|
84
90
|
"btn.moveUp": "上移",
|
|
@@ -196,7 +202,7 @@ try {
|
|
|
196
202
|
"name.placeholder": "自定义模式",
|
|
197
203
|
"name.descriptionPlaceholder": "描述,显示在模式菜单里,可留空",
|
|
198
204
|
"mode.heading": "基础模式",
|
|
199
|
-
"mode.hint": "
|
|
205
|
+
"mode.hint": "五档都可以点。改的是当前这位助手。提示词仍以本页为准。",
|
|
200
206
|
"rows.heading": "插件开关",
|
|
201
207
|
"rows.filterPlaceholder": "按名称或 id 筛选",
|
|
202
208
|
"cap.heading": "插件开关",
|
|
@@ -296,13 +302,20 @@ try {
|
|
|
296
302
|
"nav": "Custom mode",
|
|
297
303
|
"assistant.heading": "Assistants",
|
|
298
304
|
"assistant.hint": "Each assistant keeps its own system prompt, base mode and plugin switches.",
|
|
299
|
-
"posture.hint": "
|
|
305
|
+
"posture.hint": "This branch is written only when you click New assistant.",
|
|
306
|
+
"tree.posture": "Starter",
|
|
307
|
+
"tree.base": "Tool base",
|
|
308
|
+
"tree.baseHold": "A new assistant always starts on the official Standard mode.",
|
|
309
|
+
"tree.baseSkip": "Cannot be chosen on this branch. Change it later under This assistant.",
|
|
310
|
+
"tree.baseLocked": "Only the official Standard mode is lit. The other four are dim and cannot be chosen when creating.",
|
|
300
311
|
"posture.develop.label": "Coding",
|
|
301
|
-
"posture.develop.note": "
|
|
312
|
+
"posture.develop.note": "Official Standard mode, tools as shipped.",
|
|
302
313
|
"posture.write.label": "Writing",
|
|
303
|
-
"posture.write.note": "
|
|
314
|
+
"posture.write.note": "Official Standard mode. Terminal off, file access on.",
|
|
304
315
|
"posture.chat.label": "Chat",
|
|
305
|
-
"posture.chat.note": "
|
|
316
|
+
"posture.chat.note": "Official Standard mode. Files and terminal off.",
|
|
317
|
+
"editor.heading": "This assistant",
|
|
318
|
+
"editor.hint": "This branch edits the assistant selected above. All five base modes can be chosen.",
|
|
306
319
|
"assistant.empty": "No assistants yet — create one with the field below.",
|
|
307
320
|
"assistant.loadingList": "Loading assistants…",
|
|
308
321
|
"assistant.newPlaceholder": "Name of the new assistant (e.g. Writing assistant)",
|
|
@@ -430,7 +443,7 @@ try {
|
|
|
430
443
|
"name.placeholder": "Custom mode",
|
|
431
444
|
"name.descriptionPlaceholder": "Description, shown in the mode menu. Optional.",
|
|
432
445
|
"mode.heading": "Base mode",
|
|
433
|
-
"mode.hint": "
|
|
446
|
+
"mode.hint": "All five can be chosen. This edits the assistant selected above. The prompt on this page still applies.",
|
|
434
447
|
"rows.heading": "Plugin switches",
|
|
435
448
|
"rows.filterPlaceholder": "Filter by name or id",
|
|
436
449
|
"cap.heading": "Plugin switches",
|
|
@@ -748,18 +761,19 @@ try {
|
|
|
748
761
|
".cpfe-hint{display:flex;flex-direction:column;gap:2px;margin:0 0 6px}",
|
|
749
762
|
".cpfe-hint-line{font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary)}",
|
|
750
763
|
".cpfe-hint-detail{margin:0;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary)}",
|
|
751
|
-
//
|
|
752
|
-
|
|
764
|
+
// The native InlineEditor saves on Enter and autofocuses; document editing must keep
|
|
765
|
+
// Enter as a newline and manual Save. Use its exact surface/font tokens for these
|
|
766
|
+
// controlled textareas, with only document height and width as layout differences.
|
|
767
|
+
".cpfe-desc,.cpfe-editor{box-sizing:border-box;min-width:0;margin:0;padding:3px 8px;border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-sm);outline:none;background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary);font:var(--dsw-font-xs-13);font-family:Inter,var(--dsw-font-family);overflow-y:auto}",
|
|
768
|
+
".cpfe-desc:focus,.cpfe-editor:focus{border-color:var(--dsw-alias-state-business-primary)}",
|
|
769
|
+
".cpfe-desc{min-height:40px;max-height:120px;resize:vertical}",
|
|
753
770
|
".cpfe-base-pending{color:var(--dsw-alias-state-warn-primary)}",
|
|
754
771
|
".cpfe-note{display:block;margin:8px 0 0;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary)}",
|
|
755
|
-
".cpfe-mono{display:block;margin:0;font
|
|
772
|
+
".cpfe-mono{display:block;margin:0;font:inherit;color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere}",
|
|
756
773
|
".cpfe-pills{display:flex;flex-wrap:wrap;gap:6px;align-items:center}",
|
|
757
774
|
".cpfe-pills > *{flex:0 0 auto;white-space:nowrap}",
|
|
758
775
|
".cpfe-pills button{white-space:nowrap}",
|
|
759
776
|
".cpfe-picker{display:flex;align-items:center;gap:8px;margin:2px 0 4px}",
|
|
760
|
-
// 壳的菜单浮层靠一个独立的 backing 元素上色(实测在 0.1.7-rc.2 + headless 下那块是透明的,
|
|
761
|
-
// 文字会"压"在下面的输入框上)。用官方 token 显式补一层底色,真实浏览器与 headless 一致。
|
|
762
|
-
".cpfe-menu{background:var(--dsw-menu-surface-fill,var(--dsw-alias-bg-layer-3));border-radius:var(--dsw-radius-lg);box-shadow:var(--dsw-elevation-soft)}",
|
|
763
777
|
".cpfe-history{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:10px}",
|
|
764
778
|
".cpfe-history-label{font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary)}",
|
|
765
779
|
".cpfe-history-hint{font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary)}",
|
|
@@ -767,14 +781,16 @@ try {
|
|
|
767
781
|
".cpfe-actions{display:flex;flex-wrap:wrap;gap:var(--g);align-items:center;margin-top:4px}",
|
|
768
782
|
".cpfe-newrow{display:flex;gap:var(--g);align-items:center;flex-wrap:wrap;margin-top:10px}",
|
|
769
783
|
".cpfe-postures{display:flex;flex-direction:column;gap:6px}",
|
|
770
|
-
".cpfe-create{display:flex;flex-direction:column;gap:6px
|
|
784
|
+
".cpfe-create{display:flex;flex-direction:column;gap:6px}",
|
|
785
|
+
".cpfe-branch{display:flex;flex-direction:column;gap:16px;margin-top:8px;padding-left:12px;border-left:1px solid var(--dsw-alias-border-l1)}",
|
|
786
|
+
".cpfe-node{display:flex;flex-direction:column;gap:4px}",
|
|
787
|
+
".cpfe-node-label{font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary)}",
|
|
771
788
|
".cpfe-field{display:flex;width:100%;margin-bottom:8px}",
|
|
772
789
|
".cpfe-row-head{font-size:14px;line-height:22px;color:var(--dsw-alias-label-primary)}",
|
|
773
790
|
".cpfe-row-switch{flex:0 0 auto}",
|
|
774
791
|
".cpfe-row-line{display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-width:0}",
|
|
775
792
|
".cpfe-row-note{font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}",
|
|
776
|
-
".cpfe-row-toggle{flex:0 0 auto
|
|
777
|
-
".cpfe-row-toggle:hover{background:var(--dsw-alias-bg-layer-2)}",
|
|
793
|
+
".cpfe-row-toggle{flex:0 0 auto}",
|
|
778
794
|
".cpfe-row-open{border-color:var(--dsw-alias-border-l2)}",
|
|
779
795
|
".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)}",
|
|
780
796
|
".cpfe-detail-line{display:flex;gap:8px;min-width:0}",
|
|
@@ -794,19 +810,17 @@ try {
|
|
|
794
810
|
".cpfe-row-meta{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}",
|
|
795
811
|
".cpfe-row-badges{display:flex;align-items:center;gap:4px;flex:0 1 auto;min-width:0}",
|
|
796
812
|
".cpfe-row{display:flex;gap:12px;align-items:center;box-sizing:border-box;min-height:74px;padding:16px 0;border:0;border-radius:0;background:none}",
|
|
797
|
-
".cpfe-editor{
|
|
813
|
+
".cpfe-editor{width:100%;min-height:120px;resize:vertical}",
|
|
798
814
|
".cpfe-bar{display:flex;align-items:center;gap:var(--g);flex-wrap:wrap;margin-top:8px}",
|
|
799
|
-
".cpfe-disclosure{
|
|
800
|
-
".cpfe-filter{box-sizing:border-box;width:100%;height:36px;margin:0 0 8px;padding:0 12px;border-radius:var(--dsw-radius-md);border:.5px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px}",
|
|
815
|
+
".cpfe-disclosure{align-self:flex-start;margin-top:8px}",
|
|
801
816
|
".cpfe .cpfe-danger{margin-left:auto}",
|
|
802
817
|
".cpfe-status{font-size:13px;line-height:20px}",
|
|
803
818
|
".cpfe-ok{color:var(--dsw-alias-label-secondary)}",
|
|
804
819
|
".cpfe-err{color:var(--dsw-alias-state-error-primary)}",
|
|
805
820
|
".cpfe-dirty{color:var(--dsw-alias-state-warn-primary)}",
|
|
806
|
-
".cpfe-danger{color:var(--dsw-alias-state-error-primary)}",
|
|
807
821
|
".cpfe-meta-line{display:flex;flex-wrap:wrap;align-items:baseline;gap:8px;min-width:0}",
|
|
808
822
|
".cpfe-version{font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary);white-space:nowrap}",
|
|
809
|
-
".cpfe-path{font
|
|
823
|
+
".cpfe-path{font:inherit;color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere}",
|
|
810
824
|
// ── fallback-path controls (unused when the shell provides the atoms) ──
|
|
811
825
|
".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}",
|
|
812
826
|
".cpfe-btn:disabled{opacity:.4;cursor:not-allowed}",
|
|
@@ -820,7 +834,7 @@ try {
|
|
|
820
834
|
// 光拦状态还不够:DOM 会先显示用户敲进去的字/翻过去的开关,等下一次重渲染才被拉回来 ——
|
|
821
835
|
// 那就是"我明明改了,它自己弹回去了"。`pointer-events` 让点击根本到不了控件,
|
|
822
836
|
// 视觉上也给一个明确的"此刻不能动"。
|
|
823
|
-
".cpfe-busy .cpfe-switch,.cpfe-busy .cpfe-row-switch,.cpfe-busy .cpfe-row-toggle,.cpfe-busy .cpfe-input,.cpfe-busy .cpfe-field,.cpfe-busy .cpfe-
|
|
837
|
+
".cpfe-busy .cpfe-switch,.cpfe-busy .cpfe-row-switch,.cpfe-busy .cpfe-row-toggle,.cpfe-busy .cpfe-input,.cpfe-busy .cpfe-field,.cpfe-busy .cpfe-pill,.cpfe-busy .cpfe-selector{pointer-events:none}",
|
|
824
838
|
".cpfe-busy .cpfe-editor{cursor:progress}",
|
|
825
839
|
".cpfe-tag{font-size:12px;line-height:18px;padding:0 5px;border-radius:4px;border:.5px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-secondary)}",
|
|
826
840
|
".cpfe-tag-success,.cpfe-tag-info{color:var(--dsw-alias-state-success-primary)}",
|
|
@@ -828,18 +842,7 @@ try {
|
|
|
828
842
|
".cpfe-tag-danger{color:var(--dsw-alias-state-error-primary)}",
|
|
829
843
|
".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}",
|
|
830
844
|
".cpfe-pill-on{border-color:var(--dsw-alias-label-primary);color:var(--dsw-alias-label-primary)}",
|
|
831
|
-
//
|
|
832
|
-
// 实测(**0.1.7-rc.2 与 0.2.0-rc.2 各量一次,结论相同**):官方的 `_selector` 是
|
|
833
|
-
// height 36px · border-radius var(--dsw-radius-md) · background var(--dsw-alias-bg-module-platform)
|
|
834
|
-
// · padding 0 14px · font-size 14px/line-height 22px · gap 12px,hover 换
|
|
835
|
-
// var(--dsw-alias-interactive-bg-hover)。
|
|
836
|
-
// 壳的 Button 只有 primary / ghost / outline / toolbar 四种变体,没有"灰底选择器"这一种 ——
|
|
837
|
-
// 官方各设置页也是**各自定义** `_selector`(oY77xG / hVGvvW / _2XZxNq / T1PP_q 各一份、
|
|
838
|
-
// 度量完全一致),所以这里照同一套度量自绘,做法与官方一致。
|
|
839
|
-
// 双类选择器(`.cpfe .cpfe-selector`)用来压过壳 Button 的单类变体规则,
|
|
840
|
-
// 免得 `_ghost_` / `_sm_` 把灰底和高度覆盖掉。
|
|
841
|
-
".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}",
|
|
842
|
-
".cpfe .cpfe-selector:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}",
|
|
845
|
+
// Menu surfaces and trigger Buttons keep the native atoms' own styles.
|
|
843
846
|
// ── 告警区 ──────────────────────────────────────────────────────────────
|
|
844
847
|
// 这一段此前**一条 CSS 都没有**(2026-10-02 逐表核对:样式表里 `cpfe-warn` 零规则),
|
|
845
848
|
// 于是出现告警时它是一串没有排版的裸 `<p>`:没有行距、图标与文字不对齐、
|
|
@@ -1041,9 +1044,10 @@ try {
|
|
|
1041
1044
|
: null,
|
|
1042
1045
|
),
|
|
1043
1046
|
react.createElement(
|
|
1044
|
-
|
|
1047
|
+
A.Button,
|
|
1045
1048
|
{
|
|
1046
|
-
|
|
1049
|
+
variant: "ghost",
|
|
1050
|
+
size: "sm",
|
|
1047
1051
|
className: "cpfe-row-toggle",
|
|
1048
1052
|
"aria-expanded": open,
|
|
1049
1053
|
"aria-label": t(open ? "aria.collapse" : "aria.expand"),
|
|
@@ -1717,38 +1721,70 @@ try {
|
|
|
1717
1721
|
: "cpfe-status cpfe-ok"
|
|
1718
1722
|
const shown = dirty && status === "" ? t("msg.unsaved") : status
|
|
1719
1723
|
|
|
1724
|
+
const lockedModes =
|
|
1725
|
+
payload !== null && Array.isArray(payload.modes) && payload.modes.length > 0
|
|
1726
|
+
? payload.modes
|
|
1727
|
+
: [{ id: "standard" }, { id: "ptc" }, { id: "minimal" }, { id: "cordis" }, { id: "all" }]
|
|
1720
1728
|
const createGroup = react.createElement(
|
|
1721
1729
|
"section",
|
|
1722
1730
|
{ className: "cpfe-create" },
|
|
1723
1731
|
react.createElement("h2", { className: "cpfe-h" }, t("create.heading")),
|
|
1724
1732
|
react.createElement(SectionHint, { text: t("posture.hint") }),
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
:
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1733
|
+
react.createElement(
|
|
1734
|
+
"div",
|
|
1735
|
+
{ className: "cpfe-branch" },
|
|
1736
|
+
postureChoices.length === 0
|
|
1737
|
+
? null
|
|
1738
|
+
: react.createElement(
|
|
1731
1739
|
"div",
|
|
1732
|
-
{ className: "cpfe-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1740
|
+
{ className: "cpfe-node" },
|
|
1741
|
+
react.createElement("span", { className: "cpfe-node-label" }, t("tree.posture")),
|
|
1742
|
+
react.createElement(
|
|
1743
|
+
"div",
|
|
1744
|
+
{ className: "cpfe-pills", role: "radiogroup", "aria-label": t("tree.posture") },
|
|
1745
|
+
postureChoices.map((item) =>
|
|
1746
|
+
react.createElement(
|
|
1747
|
+
A.Pill,
|
|
1748
|
+
{
|
|
1749
|
+
key: item.id,
|
|
1750
|
+
active: item.id === posture,
|
|
1751
|
+
disabled: busy,
|
|
1752
|
+
"aria-pressed": item.id === posture,
|
|
1753
|
+
onClick: () => setPosture(item.id),
|
|
1754
|
+
},
|
|
1755
|
+
t("posture." + item.id + ".label", item.id),
|
|
1756
|
+
),
|
|
1744
1757
|
),
|
|
1745
1758
|
),
|
|
1759
|
+
react.createElement("p", { className: "cpfe-note" }, t("posture." + posture + ".note", "")),
|
|
1760
|
+
),
|
|
1761
|
+
react.createElement(
|
|
1762
|
+
"div",
|
|
1763
|
+
{ className: "cpfe-node" },
|
|
1764
|
+
react.createElement("span", { className: "cpfe-node-label" }, t("tree.base")),
|
|
1765
|
+
react.createElement(
|
|
1766
|
+
"div",
|
|
1767
|
+
{ className: "cpfe-pills cpfe-locked", role: "radiogroup", "aria-disabled": "true", "aria-label": t("tree.base") },
|
|
1768
|
+
lockedModes.map((mode) =>
|
|
1769
|
+
react.createElement(
|
|
1770
|
+
A.Pill,
|
|
1771
|
+
{
|
|
1772
|
+
key: mode.id,
|
|
1773
|
+
active: mode.id === "standard",
|
|
1774
|
+
disabled: true,
|
|
1775
|
+
"aria-pressed": mode.id === "standard",
|
|
1776
|
+
title: mode.id === "standard" ? t("tree.baseHold") : t("tree.baseSkip"),
|
|
1777
|
+
onClick: () => {},
|
|
1778
|
+
},
|
|
1779
|
+
t("base." + mode.id + ".label", mode.label),
|
|
1780
|
+
),
|
|
1746
1781
|
),
|
|
1747
|
-
react.createElement("p", { className: "cpfe-note" }, t("posture." + posture + ".note", "")),
|
|
1748
1782
|
),
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1783
|
+
react.createElement("p", { className: "cpfe-note" }, t("tree.baseLocked")),
|
|
1784
|
+
),
|
|
1785
|
+
react.createElement(
|
|
1786
|
+
"div",
|
|
1787
|
+
{ className: "cpfe-newrow" },
|
|
1752
1788
|
react.createElement(A.Input, {
|
|
1753
1789
|
className: "cpfe-newinput",
|
|
1754
1790
|
value: newName,
|
|
@@ -1772,6 +1808,7 @@ try {
|
|
|
1772
1808
|
},
|
|
1773
1809
|
busy ? t("btn.creating") : t("btn.create"),
|
|
1774
1810
|
),
|
|
1811
|
+
),
|
|
1775
1812
|
),
|
|
1776
1813
|
)
|
|
1777
1814
|
|
|
@@ -1804,14 +1841,13 @@ try {
|
|
|
1804
1841
|
// ★ portal:不把浮层渲染在我们的容器里。设置面板有裁剪与叠层,非 portal 的
|
|
1805
1842
|
// 菜单会被裁掉表面,只剩文字"压"在下面的输入框上(实测截图如此)。
|
|
1806
1843
|
portal: true,
|
|
1807
|
-
listClassName: "cpfe-menu",
|
|
1808
1844
|
align: "start",
|
|
1809
1845
|
side: "bottom",
|
|
1810
1846
|
selectedId: selected,
|
|
1811
1847
|
anchor: react.createElement(
|
|
1812
1848
|
A.Button,
|
|
1813
1849
|
{
|
|
1814
|
-
variant: "
|
|
1850
|
+
variant: "toolbar",
|
|
1815
1851
|
className: "cpfe-selector",
|
|
1816
1852
|
disabled: busy,
|
|
1817
1853
|
onClick: () => setAssistantOpen((open) => open !== true),
|
|
@@ -1927,7 +1963,6 @@ try {
|
|
|
1927
1963
|
),
|
|
1928
1964
|
)
|
|
1929
1965
|
: null,
|
|
1930
|
-
createGroup,
|
|
1931
1966
|
typeof (assistants.find((item) => item.id === selected) || {}).broken === "string"
|
|
1932
1967
|
? react.createElement("p", { className: "cpfe-note" }, t("assistant.brokenHint"))
|
|
1933
1968
|
: null,
|
|
@@ -1944,6 +1979,7 @@ try {
|
|
|
1944
1979
|
react.createElement(SectionHint, { text: t("name.hint") }),
|
|
1945
1980
|
react.createElement(A.Input, {
|
|
1946
1981
|
className: "cpfe-field",
|
|
1982
|
+
disabled: busy,
|
|
1947
1983
|
value: draft.name,
|
|
1948
1984
|
placeholder: t("name.placeholder"),
|
|
1949
1985
|
"aria-label": t("name.heading"),
|
|
@@ -1975,7 +2011,7 @@ try {
|
|
|
1975
2011
|
? react.createElement("p", { className: "cpfe-note" }, t("mode.unavailable"))
|
|
1976
2012
|
: react.createElement(
|
|
1977
2013
|
"div",
|
|
1978
|
-
{ className: "cpfe-pills" },
|
|
2014
|
+
{ className: "cpfe-pills", "data-live": "base" },
|
|
1979
2015
|
payload.modes.map((mode) =>
|
|
1980
2016
|
react.createElement(
|
|
1981
2017
|
A.Pill,
|
|
@@ -2014,8 +2050,9 @@ try {
|
|
|
2014
2050
|
: react.createElement(
|
|
2015
2051
|
"div",
|
|
2016
2052
|
null,
|
|
2017
|
-
react.createElement(
|
|
2018
|
-
className: "cpfe-filter",
|
|
2053
|
+
react.createElement(A.Input, {
|
|
2054
|
+
className: "cpfe-field cpfe-filter",
|
|
2055
|
+
disabled: busy,
|
|
2019
2056
|
value: rowQuery,
|
|
2020
2057
|
placeholder: t("rows.filterPlaceholder"),
|
|
2021
2058
|
"aria-label": t("rows.filterPlaceholder"),
|
|
@@ -2126,14 +2163,13 @@ try {
|
|
|
2126
2163
|
? react.createElement(A.Menu, {
|
|
2127
2164
|
open: historyOpen,
|
|
2128
2165
|
portal: true,
|
|
2129
|
-
listClassName: "cpfe-menu",
|
|
2130
2166
|
align: "start",
|
|
2131
2167
|
side: "bottom",
|
|
2132
2168
|
selectedId: draft.historyPick,
|
|
2133
2169
|
anchor: react.createElement(
|
|
2134
2170
|
A.Button,
|
|
2135
2171
|
{
|
|
2136
|
-
variant: "
|
|
2172
|
+
variant: "toolbar",
|
|
2137
2173
|
className: "cpfe-selector",
|
|
2138
2174
|
disabled: busy,
|
|
2139
2175
|
onClick: () => setHistoryOpen((open) => open !== true),
|
|
@@ -2251,8 +2287,17 @@ try {
|
|
|
2251
2287
|
),
|
|
2252
2288
|
),
|
|
2253
2289
|
),
|
|
2254
|
-
|
|
2255
|
-
|
|
2290
|
+
editorReady
|
|
2291
|
+
? react.createElement(
|
|
2292
|
+
"section",
|
|
2293
|
+
null,
|
|
2294
|
+
react.createElement("h2", { className: "cpfe-h" }, t("editor.heading")),
|
|
2295
|
+
react.createElement(SectionHint, { text: t("editor.hint") }),
|
|
2296
|
+
react.createElement(
|
|
2297
|
+
"div",
|
|
2298
|
+
{ className: "cpfe-branch" },
|
|
2299
|
+
editorSections.filter((section) => section.key === "prompt"),
|
|
2300
|
+
react.createElement(
|
|
2256
2301
|
"div",
|
|
2257
2302
|
{ className: "cpfe-bar" },
|
|
2258
2303
|
react.createElement(
|
|
@@ -2300,9 +2345,10 @@ try {
|
|
|
2300
2345
|
"section",
|
|
2301
2346
|
null,
|
|
2302
2347
|
react.createElement(
|
|
2303
|
-
|
|
2348
|
+
A.Button,
|
|
2304
2349
|
{
|
|
2305
|
-
|
|
2350
|
+
variant: "ghost",
|
|
2351
|
+
disabled: busy,
|
|
2306
2352
|
"data-cap": "toggle",
|
|
2307
2353
|
className: "cpfe-disclosure",
|
|
2308
2354
|
"aria-expanded": capOpen,
|
|
@@ -2326,6 +2372,10 @@ try {
|
|
|
2326
2372
|
: null,
|
|
2327
2373
|
)
|
|
2328
2374
|
: null,
|
|
2375
|
+
),
|
|
2376
|
+
)
|
|
2377
|
+
: null,
|
|
2378
|
+
createGroup,
|
|
2329
2379
|
// The confirmation is a portal: rendering it here keeps every piece of this page's
|
|
2330
2380
|
// state in one component.
|
|
2331
2381
|
renderable(A.RiskConfirmation) && editorReady
|
package/defaults.mjs
CHANGED
|
@@ -35,8 +35,12 @@ export function ensureUnsetDefaultPreset(home, presetId) {
|
|
|
35
35
|
for (let i = 0; i < lines.length; i += 1) {
|
|
36
36
|
const line = lines[i]
|
|
37
37
|
if (line.trim() === '' || /^\s*#/.test(line)) continue
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
const key = /^(?:agent-presets|'agent-presets'|"agent-presets")\s*:\s*(.*)$/.exec(line.replace(/^\uFEFF/, ''))
|
|
39
|
+
if (key !== null) {
|
|
40
|
+
// A flow mapping, alias or scalar cannot receive an indented child.
|
|
41
|
+
// Leave unsupported YAML forms byte-identical instead of breaking boot.
|
|
42
|
+
const value = key[1].trim()
|
|
43
|
+
if (value !== '' && !value.startsWith('#')) return { wrote: false, reason: 'inline' }
|
|
40
44
|
section = i
|
|
41
45
|
break
|
|
42
46
|
}
|
|
@@ -50,7 +54,7 @@ export function ensureUnsetDefaultPreset(home, presetId) {
|
|
|
50
54
|
const line = lines[i]
|
|
51
55
|
if (line.trim() === '' || /^\s*#/.test(line)) continue
|
|
52
56
|
if (/^\S/.test(line)) break
|
|
53
|
-
if (/^\s+default\s*:/.test(line)) return { wrote: false, reason: 'present' }
|
|
57
|
+
if (/^\s+(?:default|'default'|"default")\s*:/.test(line)) return { wrote: false, reason: 'present' }
|
|
54
58
|
}
|
|
55
59
|
lines.splice(section + 1, 0, ' default: ' + presetId)
|
|
56
60
|
const next = lines.join('\n')
|
package/locales.mjs
CHANGED
|
@@ -21,13 +21,20 @@ export const zh = {
|
|
|
21
21
|
// ── 助手管理 ──────────────────────────────────────────────────────────────
|
|
22
22
|
'assistant.heading': '助手',
|
|
23
23
|
'assistant.hint': '每个助手单独保存系统提示词、基础模式和插件开关。',
|
|
24
|
-
'posture.hint': '
|
|
24
|
+
'posture.hint': '这一支只在点「新增助手」时写入。',
|
|
25
|
+
'tree.posture': '起步',
|
|
26
|
+
'tree.base': '工具底',
|
|
27
|
+
'tree.baseHold': '新建时固定用官方标准模式。',
|
|
28
|
+
'tree.baseSkip': '这一支点不了。建好后到「当前助手」里改。',
|
|
29
|
+
'tree.baseLocked': '只有官方标准模式是亮的。其余四档是暗的,新建时点不了。',
|
|
25
30
|
'posture.develop.label': '开发',
|
|
26
|
-
'posture.develop.note': '
|
|
31
|
+
'posture.develop.note': '官方标准模式,工具按出厂。',
|
|
27
32
|
'posture.write.label': '写作',
|
|
28
|
-
'posture.write.note': '
|
|
33
|
+
'posture.write.note': '官方标准模式。终端关闭,文件读写打开。',
|
|
29
34
|
'posture.chat.label': '聊天',
|
|
30
|
-
'posture.chat.note': '
|
|
35
|
+
'posture.chat.note': '官方标准模式。文件和终端关闭。',
|
|
36
|
+
'editor.heading': '当前助手',
|
|
37
|
+
'editor.hint': '这一支改上面选中的助手。基础模式五档都可以点。',
|
|
31
38
|
'assistant.empty': '还没有助手,用下面的输入框新建一个。',
|
|
32
39
|
'assistant.loadingList': '正在读取助手列表…',
|
|
33
40
|
'assistant.newPlaceholder': '新助手的名字(例如:写作助手)',
|
|
@@ -39,7 +46,7 @@ export const zh = {
|
|
|
39
46
|
'assistant.brokenHint': '此模式在本机无法启动,不会出现在新会话菜单里。点「按本线修复」只关闭那些行。',
|
|
40
47
|
'assistant.switchHint': '切换助手保留各自的未保存草稿;列表中的「未保存」标记即为此。',
|
|
41
48
|
'btn.create': '新增助手',
|
|
42
|
-
'create.heading': '
|
|
49
|
+
'create.heading': '新建助手',
|
|
43
50
|
'btn.creating': '创建中…',
|
|
44
51
|
'btn.duplicate': '复制',
|
|
45
52
|
'btn.moveUp': '上移',
|
|
@@ -159,7 +166,7 @@ export const zh = {
|
|
|
159
166
|
'name.descriptionPlaceholder': '描述,显示在模式菜单里,可留空',
|
|
160
167
|
|
|
161
168
|
'mode.heading': '基础模式',
|
|
162
|
-
'mode.hint': '
|
|
169
|
+
'mode.hint': '五档都可以点。改的是当前这位助手。提示词仍以本页为准。',
|
|
163
170
|
|
|
164
171
|
'rows.heading': '插件开关',
|
|
165
172
|
'rows.filterPlaceholder': '按名称或 id 筛选',
|
|
@@ -279,13 +286,20 @@ export const en = {
|
|
|
279
286
|
// ── assistant management ──────────────────────────────────────────────────
|
|
280
287
|
'assistant.heading': 'Assistants',
|
|
281
288
|
'assistant.hint': 'Each assistant keeps its own system prompt, base mode and plugin switches.',
|
|
282
|
-
'posture.hint': '
|
|
289
|
+
'posture.hint': 'This branch is written only when you click New assistant.',
|
|
290
|
+
'tree.posture': 'Starter',
|
|
291
|
+
'tree.base': 'Tool base',
|
|
292
|
+
'tree.baseHold': 'A new assistant always starts on the official Standard mode.',
|
|
293
|
+
'tree.baseSkip': 'Cannot be chosen on this branch. Change it later under This assistant.',
|
|
294
|
+
'tree.baseLocked': 'Only the official Standard mode is lit. The other four are dim and cannot be chosen when creating.',
|
|
283
295
|
'posture.develop.label': 'Coding',
|
|
284
|
-
'posture.develop.note': '
|
|
296
|
+
'posture.develop.note': 'Official Standard mode, tools as shipped.',
|
|
285
297
|
'posture.write.label': 'Writing',
|
|
286
|
-
'posture.write.note': '
|
|
298
|
+
'posture.write.note': 'Official Standard mode. Terminal off, file access on.',
|
|
287
299
|
'posture.chat.label': 'Chat',
|
|
288
|
-
'posture.chat.note': '
|
|
300
|
+
'posture.chat.note': 'Official Standard mode. Files and terminal off.',
|
|
301
|
+
'editor.heading': 'This assistant',
|
|
302
|
+
'editor.hint': 'This branch edits the assistant selected above. All five base modes can be chosen.',
|
|
289
303
|
'assistant.empty': 'No assistants yet — create one with the field below.',
|
|
290
304
|
'assistant.loadingList': 'Loading assistants…',
|
|
291
305
|
'assistant.newPlaceholder': 'Name of the new assistant (e.g. Writing assistant)',
|
|
@@ -415,7 +429,7 @@ export const en = {
|
|
|
415
429
|
'name.descriptionPlaceholder': 'Description, shown in the mode menu. Optional.',
|
|
416
430
|
|
|
417
431
|
'mode.heading': 'Base mode',
|
|
418
|
-
'mode.hint': '
|
|
432
|
+
'mode.hint': 'All five can be chosen. This edits the assistant selected above. The prompt on this page still applies.',
|
|
419
433
|
|
|
420
434
|
'rows.heading': 'Plugin switches',
|
|
421
435
|
'rows.filterPlaceholder': 'Filter by name or id',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-custom-mode",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.3",
|
|
4
4
|
"description": "Edit a DeepSeek Harness (dsh) custom mode: system prompt, base mode, and plugin switches.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -74,7 +74,10 @@
|
|
|
74
74
|
"union-mount-check": "node tools/union-mount-check.mjs",
|
|
75
75
|
"session-trace": "node tools/session-trace.mjs",
|
|
76
76
|
"browser-verify": "node tools/browser-verify.mjs",
|
|
77
|
-
"upgrade-preflight": "node tools/upgrade-preflight.mjs"
|
|
77
|
+
"upgrade-preflight": "node tools/upgrade-preflight.mjs",
|
|
78
|
+
"compat-check": "node tools/compat-check.mjs",
|
|
79
|
+
"runtime-check": "node tools/runtime-check.mjs",
|
|
80
|
+
"market-check": "node tools/market-check.mjs"
|
|
78
81
|
},
|
|
79
82
|
"peerDependencies": {
|
|
80
83
|
"@deepseek-ai/dsh": ">=0.1.5-rc.2 <0.2.0-0 || >=0.1.6-alpha.1 <0.2.0-0 || >=0.1.7-alpha.1 <0.2.0-0 || >=0.2.0-0 <0.3.0-0 || >=0.2.1-alpha.1 <0.3.0-0"
|
|
@@ -50,6 +50,18 @@ export function absoluteSpecifier(specifier, presetDir) {
|
|
|
50
50
|
return pathToFileURL(join(presetDir, specifier)).href
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
/** Preserve config expressions in the host loader's native node representation.
|
|
54
|
+
* The local parser returns __js without executing it. The host recognizes
|
|
55
|
+
* __jsExpr and evaluates it with its own baseUrl/context. Passing __js through
|
|
56
|
+
* as ordinary config broke Creator's customSkillDirs.
|
|
57
|
+
*/
|
|
58
|
+
function loaderConfig(value) {
|
|
59
|
+
if (value === null || typeof value !== 'object') return value
|
|
60
|
+
if (typeof value.__js === 'string') return { __jsExpr: value.__js }
|
|
61
|
+
if (Array.isArray(value)) return value.map(loaderConfig)
|
|
62
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, loaderConfig(item)]))
|
|
63
|
+
}
|
|
64
|
+
|
|
53
65
|
/**
|
|
54
66
|
* Turn parsed composition rows into the row objects `register()` takes.
|
|
55
67
|
*
|
|
@@ -72,7 +84,7 @@ export function toPluginRows(rows, presetDir) {
|
|
|
72
84
|
if (row.isolate !== undefined && row.isolate !== null) plugin.isolate = row.isolate
|
|
73
85
|
plugin.config = toPluginRows(row.config, presetDir)
|
|
74
86
|
} else if (row.config !== undefined && row.config !== null) {
|
|
75
|
-
plugin.config = row.config
|
|
87
|
+
plugin.config = loaderConfig(row.config)
|
|
76
88
|
}
|
|
77
89
|
if (row.disabled !== undefined) plugin.disabled = resolveDisabled(row.disabled)
|
|
78
90
|
out.push(plugin)
|