dsh-plugin-prompt-tool 0.3.1 → 0.4.1
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 +97 -16
- package/lib/client.js +119 -10
- package/lib/client.js.map +1 -1
- package/lib/index.d.mts +9 -2
- package/lib/index.mjs +302 -71
- package/lib/preset-core.d.mts +5 -1
- package/lib/preset-core.mjs +130 -31
- package/package.json +24 -21
- package/plan.md +19 -3
- package/preset/agent.cordis.yml +443 -0
- package/preset/compaction-epoch.mjs +81 -0
- package/preset/context-gate.mjs +165 -0
- package/preset/custom-bash.mjs +243 -0
- package/preset/instruction-hint.mjs +217 -0
- package/preset/near-anchor.mjs +6 -19
- package/preset/prompt-injector.mjs +111 -126
- package/preset/router-first-turn.mjs +73 -70
- package/preset/router-guide.mjs +14 -20
- package/preset/shared.mjs +83 -0
- package/preset/skill-search.mjs +142 -0
- package/preset/tool-bootstrap.mjs +282 -0
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# 提示词工具(dsh-plugin-prompt-tool)
|
|
2
2
|
|
|
3
|
-
把「Anchored Standard + dsh-router-standard 最优组合」做成 DSH 全家桶里的一键安装插件:插件启动时生成并维护 `~/.dsh/.agent-presets/prompt-tool/` 预设,首轮模型请求只看到官方 Minimal 精确双工具——持久 `bash` 与 `str_replace_editor`——和正确的 persona,没有运行时上下文与指令注入;锚定建立后进入 resident 目录,恢复常规注入,并在确认轨迹后注入 `preset.md`。同时提供 Web 界面在线编辑 `preset.md` / `AGENTS.md`、切换全部开关,以及可开关的 skills
|
|
3
|
+
把「Anchored Standard + dsh-router-standard 最优组合」做成 DSH 全家桶里的一键安装插件:插件启动时生成并维护 `~/.dsh/.agent-presets/prompt-tool/` 预设,首轮模型请求只看到官方 Minimal 精确双工具——持久 `bash` 与 `str_replace_editor`——和正确的 persona,没有运行时上下文与指令注入;锚定建立后进入 resident 目录,恢复常规注入,并在确认轨迹后注入 `preset.md`。同时提供 Web 界面在线编辑 `preset.md` / `AGENTS.md`、切换全部开关,以及可开关的 skills 技能层(含一键打开技能目录、设置自定义技能目录)。全部通过官方插件接口实现,不修改 DSH 源码。
|
|
4
4
|
|
|
5
5
|
## 原理
|
|
6
6
|
|
|
7
7
|
DeepSeek V4 会强烈依赖 API 中可见的**首轮工具目录与 persona** 选择执行轨迹。完整 Standard 目录与自动注入在场会破坏 Minimal 轨迹,而全程 Minimal 又会失去重型工具。本项目把「首次轨迹选择」与「后续完整工具能力」拆开:
|
|
8
8
|
|
|
9
9
|
1. **干净首轮**:`context-gate` 清空首轮 runtime-context 并剥离自动注入;`tool-bootstrap` 只暴露 Minimal 双工具;`router-first-turn` 按主会话模型替换 persona——Pro 使用训练原句,Flash 自动采用 dsh-router-standard 的 Flash 弱路由人设(build/fix 分类 + 回顾锚 + 反跑题锚 + 先深想再产出)。
|
|
10
|
-
2. **晋升**:首次持久 `tool/call` 或 `assistant/message
|
|
10
|
+
2. **晋升**:首次持久 `tool/call` 或 `assistant/message`(先到者为准)落地后,按 `usePtcMode` 开关选择 wire 形态——默认开启时切换为 Code Mode(PTC,单一 `run_code`),完整插件工具经生成 SDK 调用;关闭时恢复原生完整工具目录。
|
|
11
11
|
3. **任务引导**:可选 `near-anchor` 在首条真实用户消息后追加一次近距离首句引导(we/let 按任务自动选择);Flash 主会话晋升后 `router-guide` 按任务复杂度追加每轮深度引导。
|
|
12
12
|
4. **提示词注入**:we 锚定确认后把 `preset.md` 作为用户消息注入一次;we 未确认最多等一轮兜底,绝不卡死。
|
|
13
13
|
5. **子代理**:目录直接全量放行(仍受调用方工具白名单过滤);可选 `subagentFlash` 固定 Flash 路由 + 任务分类人设 + 三锚。
|
|
@@ -21,37 +21,117 @@ DeepSeek V4 会强烈依赖 API 中可见的**首轮工具目录与 persona**
|
|
|
21
21
|
- `bootstrapMaxTokens`:首轮输出封顶。`0` = 本项目默认不设封顶(Web 界面显示 256000,即不设上限);正整数 = 请求 #1 的 `maxTokens`,晋升后自动剥离,不会焊进后续请求。不锁定 1024,任意正整数均可。
|
|
22
22
|
- `context-gate`:未晋升期间关闭两条统一注入路径,pre-step 只保留 claimed 批次 + `allowKinds`(放行用户技能手势与 `near-anchor` / `router-guide`);晋升后差分恢复一条 runtime-context 消息。
|
|
23
23
|
- `tool-bootstrap`:`promoteOn: either` 避免纯文字首答永久困在双工具;compaction 后回到 bootstrap + `compactionTools` 受控阶段。
|
|
24
|
+
- `usePtcMode`(默认开启):晋升后把 wire 切换为 Code Mode(PTC,单一 `run_code`),完整插件工具经生成 SDK 调用;关闭时恢复原生完整工具目录。两种模式都不再依赖 `dev_tool_search`,生成 preset 时直接移除该行且不复制 `dev-tool-search.mjs`。
|
|
24
25
|
- `router-first-turn`:只替换 persona 段,保留 plan-mode 段与第三方 section;首轮隐藏 `mnemon:*` 自动注入段,晋升后恢复。
|
|
25
26
|
- `near-anchor`:行为引导放在真实用户消息之后(近距离零衰减),只要求首句一次;复杂规划任务放行 Let 深度路径,日常任务锚 We。
|
|
26
27
|
- `router-guide`:简单任务快速收敛,复杂任务深度引导;子代理不注入,首轮不注入。
|
|
27
28
|
- `prompt-injector`:注入状态以持久事件为准,跨进程重启 / 插件热重载不重复注入。
|
|
28
|
-
- `injectAgentsPrompt`:开启时用 `AGENTS.md`
|
|
29
|
+
- `injectAgentsPrompt`:开启时用 `AGENTS.md` 内容替换本地 instruction-hint 的默认提示文本;关闭时使用本地默认 hint(列出参考文件、按需读取)。
|
|
29
30
|
- `skillSwitches`:扫描 `skills/*/SKILL.md` 注册可开关技能,未列出的技能默认开启。
|
|
30
31
|
- `subagentFlash`:检测不到 DeepSeek 模型路由时 Web/TUI 禁用并强制降级为关闭。
|
|
31
32
|
|
|
32
33
|
## 安装
|
|
33
34
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
dsh
|
|
37
|
-
|
|
35
|
+
依据官方[《打包与安装插件》](https://deepseek-harness.github.io/deepseek-harness/develop/basic/publish)准则:
|
|
36
|
+
`dsh plugin add` 只把**声明了 `dsh.bundle` 的直接依赖**追加进
|
|
37
|
+
`dsh.profile.bundles`;`@deepseek-ai/dsh-web-app` 是随 DSH 安装自带的 in-box
|
|
38
|
+
bundle(从 dsh 安装目录解析,不需要也不应写进 `dependencies`)。
|
|
39
|
+
|
|
40
|
+
### npm 安装与源码安装
|
|
41
|
+
|
|
42
|
+
两种安装源等价,后续初始化流程相同:
|
|
38
43
|
|
|
39
|
-
|
|
44
|
+
```sh
|
|
45
|
+
# 方式 A:npm / registry 安装
|
|
40
46
|
dsh plugin --profile prompt-tool add dsh-plugin-prompt-tool
|
|
41
47
|
|
|
42
|
-
#
|
|
48
|
+
# 方式 B:本地源码安装(link 会覆盖 registry 依赖)
|
|
43
49
|
dsh plugin --profile prompt-tool add link:<本仓库绝对路径>
|
|
50
|
+
```
|
|
44
51
|
|
|
45
|
-
|
|
52
|
+
### 初始化:启动一次即可
|
|
53
|
+
|
|
54
|
+
```sh
|
|
46
55
|
dsh --profile prompt-tool
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
第一次启动只负责完成初始化。首次进程尚未挂载 Web 表面,这是预期行为;
|
|
59
|
+
自愈完成后**插件会自动退出(exit 0)**,无需手动停止:
|
|
60
|
+
|
|
61
|
+
```text
|
|
62
|
+
prompt-tool: auto-added @deepseek-ai/dsh-web-app to dsh.profile.bundles for profile "prompt-tool"; next launch will mount the Web surface ...
|
|
63
|
+
prompt-tool: initialization complete — exiting so the repaired profile can be launched
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
这一次启动会自动完成:
|
|
67
|
+
|
|
68
|
+
1. **prompt-tool profile**:把 `@deepseek-ai/dsh-web-app` 补进
|
|
69
|
+
`dsh.profile.bundles`,最终为
|
|
70
|
+
`base → web-app → dsh-plugin-prompt-tool`;
|
|
71
|
+
2. **web profile**:若存在,把 `dsh-plugin-prompt-tool` 写进它的
|
|
72
|
+
`dependencies` + `bundles`(dependency 写法复用当前 profile 的安装
|
|
73
|
+
spec)。**只写 package.json,不手工创建 node_modules 链接**;
|
|
74
|
+
3. **dsh-tui profile**:若存在且确实装有
|
|
75
|
+
`@deepseek-harness-tui/dsh-tui`,同样写进 `dsh-plugin-prompt-tool`;
|
|
76
|
+
**没有 dsh-tui 则整体跳过,不写入本插件**。dsh-tui 不需要
|
|
77
|
+
`@deepseek-ai/dsh-web-app`,因此不会给它补 web-app。
|
|
78
|
+
|
|
79
|
+
所有写入幂等:文件已正确时不做任何改动。
|
|
80
|
+
|
|
81
|
+
### 初始化之后直接使用
|
|
82
|
+
|
|
83
|
+
```sh
|
|
84
|
+
# Web:官方内置 profile,本插件已自动写入
|
|
47
85
|
dsh web
|
|
86
|
+
|
|
87
|
+
# TUI:dsh-tui 的安装流程已经物化过其 profile 依赖
|
|
48
88
|
dsh-tui
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
`dsh web` 随 dsh 安装必然存在;`dsh-tui` 则在其自身安装说明中已经执行过
|
|
92
|
+
profile 依赖物化。因此初始化只需写入 package.json,不需要额外 `install`。
|
|
93
|
+
|
|
94
|
+
如果还想直接使用 `prompt-tool` 这个 profile 本身,再运行一次即可
|
|
95
|
+
(第二次启动时 web-app 已由官方装配路径加载):
|
|
96
|
+
|
|
97
|
+
```sh
|
|
98
|
+
dsh --profile prompt-tool
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
> TUI 前提:先安装/初始化过 `@deepseek-harness-tui/dsh-tui` 并已生成
|
|
102
|
+
> `dsh-tui` profile,再执行上面的初始化启动;否则按设计会跳过 dsh-tui
|
|
103
|
+
> profile。之后补装 dsh-tui 时,重新执行一次
|
|
104
|
+
> `dsh --profile prompt-tool` 即可把本插件补进 dsh-tui profile。
|
|
49
105
|
|
|
50
|
-
|
|
106
|
+
### 备选:直接把本插件装进官方 `web` 模板 profile
|
|
107
|
+
|
|
108
|
+
`web` 是官方内置模板,初始 bundles 已含
|
|
109
|
+
`@deepseek-ai/dsh-base` + `@deepseek-ai/dsh-web-app`:
|
|
110
|
+
|
|
111
|
+
```sh
|
|
112
|
+
# registry 安装
|
|
113
|
+
dsh plugin --profile web add dsh-plugin-prompt-tool
|
|
114
|
+
# 本地开发安装
|
|
115
|
+
dsh plugin --profile web add link:<本仓库绝对路径>
|
|
116
|
+
|
|
117
|
+
# 启动
|
|
118
|
+
dsh --profile web
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
完成初始化后,用 `dsh web`、`dsh-tui` 或 `dsh --profile prompt-tool` 启动,
|
|
122
|
+
新建空 session,预设选择 **prompt-tool**。插件会在启动时生成并刷新
|
|
123
|
+
`~/.dsh/.agent-presets/prompt-tool/`(升级插件后重启即自动更新)。
|
|
124
|
+
|
|
125
|
+
### 卸载
|
|
126
|
+
|
|
127
|
+
```sh
|
|
51
128
|
dsh plugin --profile prompt-tool remove dsh-plugin-prompt-tool
|
|
52
129
|
```
|
|
53
130
|
|
|
54
|
-
|
|
131
|
+
首次启动还会把包内 `skills/` 增量复制到当前 profile 目录下的
|
|
132
|
+
`$DSH_HOME/profiles/<profile>/skills`,并优先使用这份副本:已有同名文件不覆盖,
|
|
133
|
+
用户对副本的编辑会保留;包内新增技能文件会在下次启动补齐。想改回包内原始
|
|
134
|
+
skills,删除该 `skills` 目录后重启即可(或在配置里显式设置 `skillsDir`)。
|
|
55
135
|
|
|
56
136
|
## 验证
|
|
57
137
|
|
|
@@ -80,7 +160,7 @@ pnpm lint # oxlint
|
|
|
80
160
|
- preset 与 shell 访问具有相同信任等级,安装前可自行审阅 `upstream/` 与生成目录。
|
|
81
161
|
- 插件只监听本机回环设置桥,不发起网络请求,也不增加遥测。
|
|
82
162
|
- 不要在已经产生内容的会话中途切换 preset。
|
|
83
|
-
- 需要 DSH 0.1.0-rc.
|
|
163
|
+
- 需要 DSH 0.1.0-rc.7+(preset 机制、`system-prompt/assemble` 钩子与 keyed `settings.plugin.item` 插槽)。
|
|
84
164
|
|
|
85
165
|
## 构建与上游管理
|
|
86
166
|
|
|
@@ -91,11 +171,11 @@ pnpm prepare # npm publish / git install 前自动触发
|
|
|
91
171
|
pnpm sync:anchored # 从上游 main 刷新内联快照(可加 ref 参数)
|
|
92
172
|
```
|
|
93
173
|
|
|
94
|
-
上游 `dsh-anchored-standard` 以内联快照形式固化在 `upstream/dsh-anchored-standard/`(含 `LICENSE`、`NOTICE`、`REVISION`),对应提交见 `REVISION
|
|
174
|
+
上游 `dsh-anchored-standard` 以内联快照形式固化在 `upstream/dsh-anchored-standard/`(含 `LICENSE`、`NOTICE`、`REVISION`),对应提交见 `REVISION`。本项目运行时不直读上游任何文件:`preset/` 已自有化全部 `agent.cordis.yml` 与预设 JS 脚本(shared / context-gate / compaction-epoch / custom-bash / instruction-hint / skill-search / tool-bootstrap),生成时只注入 `usePtcMode` / `bootstrapMaxTokens` / `subagentFlash` 动态项;`upstream/` 仅用于溯源与 sync 对照。上游已转入维护期(2026-08-17);其 Project2 的 98/99/99 成绩来自当前实现之前的旧配置(issue #60),轨迹锚定有独立复现(#65),能力增益在小样本下未决(#51)。
|
|
95
175
|
|
|
96
176
|
## 许可
|
|
97
177
|
|
|
98
|
-
插件本体 MIT(Czerror)。首轮锚定机制源自 [xiaobright/dsh-anchored-standard](https://github.com/xiaobright/dsh-anchored-standard)(MIT),任务引导与 Flash 方案参考 [yjh051108/dsh-router-standard](https://github.com/yjh051108/dsh-router-standard)(MIT),缓存与工具面成本原则参考 [yjh051108/dsh-super-injector](https://github.com/yjh051108/dsh-super-injector)(MIT
|
|
178
|
+
插件本体 MIT(Czerror)。首轮锚定机制源自 [xiaobright/dsh-anchored-standard](https://github.com/xiaobright/dsh-anchored-standard)(MIT),任务引导与 Flash 方案参考 [yjh051108/dsh-router-standard](https://github.com/yjh051108/dsh-router-standard)(MIT),缓存与工具面成本原则参考 [yjh051108/dsh-super-injector](https://github.com/yjh051108/dsh-super-injector)(MIT)。本地 `preset/` 下的 cordis 模板与 JS 脚本基于 DeepSeek Harness Standard 预设与上游 anchored-standard 修改,原始 DeepSeek 版权与 MIT 声明保留在 `upstream/dsh-anchored-standard/NOTICE` 与 `LICENSE`。
|
|
99
179
|
|
|
100
180
|
## 配置参考
|
|
101
181
|
|
|
@@ -122,7 +202,8 @@ pnpm sync:anchored # 从上游 main 刷新内联快照(可加 ref 参数)
|
|
|
122
202
|
subagentFlashProvider: 'deepseek-official'
|
|
123
203
|
subagentFlashModel: 'deepseek-v4-flash'
|
|
124
204
|
bootstrapMaxTokens: 0 # 首轮输出封顶:0=关闭;正整数=请求 #1 maxTokens
|
|
125
|
-
|
|
205
|
+
usePtcMode: true # 使用 PTC 模式:true=晋升后切换为 Code Mode(run_code);false=恢复原生完整目录
|
|
206
|
+
skillsDir: '' # 用户自定义技能目录;空 = 自动使用 profile 下 skills/ 副本
|
|
126
207
|
skillRankBase: 250 # 技能候选排序基数
|
|
127
208
|
residentAgentsPath: '' # 默认 ~/.dsh/AGENTS.md
|
|
128
209
|
presetDir: '' # 默认 ~/.dsh/.agent-presets/prompt-tool/
|
package/lib/client.js
CHANGED
|
@@ -23,7 +23,7 @@ window.__ModuleLoader__.load({
|
|
|
23
23
|
}
|
|
24
24
|
//#endregion
|
|
25
25
|
//#region \0dsh-css:E:\Documents\GitHub\dsh-plugin-prompt-tool\src\client\PromptEditor.module.css.mjs
|
|
26
|
-
const css = ".Ru2OGG_card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}.Ru2OGG_card:hover{border-color:var(--dsw-alias-label-dimmed)}.Ru2OGG_cardOpen{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}.Ru2OGG_header{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}.Ru2OGG_header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.Ru2OGG_headText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.Ru2OGG_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.Ru2OGG_description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.Ru2OGG_chevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.Ru2OGG_chevronOpen{transform:rotate(180deg)}.Ru2OGG_pending{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.Ru2OGG_body{border-top:1px solid var(--dsw-alias-border-l2);flex-direction:column;gap:14px;margin:0 16px;padding:14px 0 16px;display:flex}.Ru2OGG_loading{color:var(--dsw-alias-label-tertiary);font-size:12px;display:inline-block}.Ru2OGG_group{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;flex-direction:column;gap:8px;padding:12px 14px;display:flex}.Ru2OGG_groupTitle{color:var(--dsw-alias-label-secondary);font-size:13px;font-weight:600}.Ru2OGG_subSection{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;flex-direction:column;display:flex;overflow:hidden}.Ru2OGG_subHeader{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;align-items:center;gap:12px;padding:12px 14px;display:flex}.Ru2OGG_subHeader:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.Ru2OGG_subTitle{color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:600;line-height:1.5}.Ru2OGG_subCount{color:var(--dsw-alias-label-tertiary);flex:none;font-size:12px}.Ru2OGG_subBody{flex-direction:column;gap:8px;padding:2px 14px 12px;display:flex}.Ru2OGG_subEmpty{color:var(--dsw-alias-label-tertiary);padding:4px 0 8px;font-size:12px}.Ru2OGG_row{cursor:pointer;align-items:flex-start;gap:10px;padding:6px 0;display:flex}.Ru2OGG_rowStack{flex-direction:column;align-items:stretch;gap:8px;padding:6px 0;display:flex}.Ru2OGG_row input{flex:none;margin-top:3px}.Ru2OGG_rowText{flex-direction:column;gap:2px;display:flex}.Ru2OGG_rowName{color:var(--dsw-alias-label-primary);font-size:13px;line-height:1.5}.Ru2OGG_rowDesc{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}.Ru2OGG_rowDisabled{opacity:.55}.Ru2OGG_anchorInput{box-sizing:border-box;width:100%;min-height:64px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);resize:vertical;border-radius:8px;padding:8px 10px;font-family:ui-monospace,monospace;font-size:12px;line-height:1.6}.Ru2OGG_textarea{box-sizing:border-box;width:100%;min-height:420px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);resize:vertical;border-radius:8px;padding:10px;font-family:ui-monospace,monospace;font-size:13px;line-height:1.6}.Ru2OGG_actions{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.Ru2OGG_primary,.Ru2OGG_secondary{appearance:none;font:inherit;cursor:pointer;border:1px solid #0000;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5}.Ru2OGG_primary{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3)}.Ru2OGG_secondary{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:0 0}.Ru2OGG_primary:disabled,.Ru2OGG_secondary:disabled{opacity:.55;cursor:default}.Ru2OGG_primary:focus-visible,.Ru2OGG_secondary:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.Ru2OGG_notice{color:var(--dsw-alias-state-success-primary);font-size:12px}.Ru2OGG_noticeError{color:var(--dsw-alias-state-error-primary,#d5484d)}.Ru2OGG_bootstrapTokensInput{box-sizing:border-box;width:96px;min-height:36px;max-height:48px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);text-align:right;border-radius:8px;flex:none;align-self:stretch;margin:0 0 0 auto;padding:4px 8px;font-size:12px;line-height:1.4}.Ru2OGG_bootstrapTokensInput:disabled{opacity:.55;cursor:default}";
|
|
26
|
+
const css = ".Ru2OGG_card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}.Ru2OGG_card:hover{border-color:var(--dsw-alias-label-dimmed)}.Ru2OGG_cardOpen{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}.Ru2OGG_header{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}.Ru2OGG_header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.Ru2OGG_headText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.Ru2OGG_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.Ru2OGG_description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.Ru2OGG_chevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.Ru2OGG_chevronOpen{transform:rotate(180deg)}.Ru2OGG_pending{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.Ru2OGG_body{border-top:1px solid var(--dsw-alias-border-l2);flex-direction:column;gap:14px;margin:0 16px;padding:14px 0 16px;display:flex}.Ru2OGG_loading{color:var(--dsw-alias-label-tertiary);font-size:12px;display:inline-block}.Ru2OGG_group{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;flex-direction:column;gap:8px;padding:12px 14px;display:flex}.Ru2OGG_groupTitle{color:var(--dsw-alias-label-secondary);font-size:13px;font-weight:600}.Ru2OGG_subSection{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;flex-direction:column;display:flex;overflow:hidden}.Ru2OGG_subHeader{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;align-items:center;gap:12px;padding:12px 14px;display:flex}.Ru2OGG_subHeader:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.Ru2OGG_subTitle{color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:600;line-height:1.5}.Ru2OGG_subCount{color:var(--dsw-alias-label-tertiary);flex:none;font-size:12px}.Ru2OGG_subBody{flex-direction:column;gap:8px;padding:2px 14px 12px;display:flex}.Ru2OGG_subEmpty{color:var(--dsw-alias-label-tertiary);padding:4px 0 8px;font-size:12px}.Ru2OGG_row{cursor:pointer;align-items:flex-start;gap:10px;padding:6px 0;display:flex}.Ru2OGG_rowStack{flex-direction:column;align-items:stretch;gap:8px;padding:6px 0;display:flex}.Ru2OGG_row input{flex:none;margin-top:3px}.Ru2OGG_rowText{flex-direction:column;gap:2px;display:flex}.Ru2OGG_rowName{color:var(--dsw-alias-label-primary);font-size:13px;line-height:1.5}.Ru2OGG_rowDesc{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}.Ru2OGG_rowDisabled{opacity:.55}.Ru2OGG_anchorInput{box-sizing:border-box;width:100%;min-height:64px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);resize:vertical;border-radius:8px;padding:8px 10px;font-family:ui-monospace,monospace;font-size:12px;line-height:1.6}.Ru2OGG_textarea{box-sizing:border-box;width:100%;min-height:420px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);resize:vertical;border-radius:8px;padding:10px;font-family:ui-monospace,monospace;font-size:13px;line-height:1.6}.Ru2OGG_actions{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.Ru2OGG_primary,.Ru2OGG_secondary{appearance:none;font:inherit;cursor:pointer;border:1px solid #0000;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5}.Ru2OGG_primary{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3)}.Ru2OGG_secondary{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:0 0}.Ru2OGG_primary:disabled,.Ru2OGG_secondary:disabled{opacity:.55;cursor:default}.Ru2OGG_primary:focus-visible,.Ru2OGG_secondary:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.Ru2OGG_notice{color:var(--dsw-alias-state-success-primary);font-size:12px}.Ru2OGG_noticeError{color:var(--dsw-alias-state-error-primary,#d5484d)}.Ru2OGG_skillsBar{flex-direction:column;gap:8px;padding:2px 0 8px;display:flex}.Ru2OGG_skillsDirRow{align-items:center;gap:8px;min-width:0;display:flex}.Ru2OGG_skillsDirRow .Ru2OGG_secondary{flex:none}.Ru2OGG_skillsDirInput{box-sizing:border-box;min-width:0;min-height:34px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:8px;flex:1;padding:6px 10px;font-size:12px;line-height:1.4}.Ru2OGG_skillsDirInput:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.Ru2OGG_skillsPath{min-width:0;color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;flex:1;font-size:12px;line-height:1.5}.Ru2OGG_bootstrapTokensInput{box-sizing:border-box;width:96px;min-height:36px;max-height:48px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);text-align:right;border-radius:8px;flex:none;align-self:stretch;margin:0 0 0 auto;padding:4px 8px;font-size:12px;line-height:1.4}.Ru2OGG_bootstrapTokensInput:disabled{opacity:.55;cursor:default}";
|
|
27
27
|
const tagId = "dsh-plugin-prompt-tool/PromptEditor.module.css";
|
|
28
28
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
29
29
|
const tag = document.createElement("style");
|
|
@@ -59,6 +59,10 @@ window.__ModuleLoader__.load({
|
|
|
59
59
|
"rowStack": "Ru2OGG_rowStack",
|
|
60
60
|
"rowText": "Ru2OGG_rowText",
|
|
61
61
|
"secondary": "Ru2OGG_secondary",
|
|
62
|
+
"skillsBar": "Ru2OGG_skillsBar",
|
|
63
|
+
"skillsDirInput": "Ru2OGG_skillsDirInput",
|
|
64
|
+
"skillsDirRow": "Ru2OGG_skillsDirRow",
|
|
65
|
+
"skillsPath": "Ru2OGG_skillsPath",
|
|
62
66
|
"subBody": "Ru2OGG_subBody",
|
|
63
67
|
"subCount": "Ru2OGG_subCount",
|
|
64
68
|
"subEmpty": "Ru2OGG_subEmpty",
|
|
@@ -102,9 +106,12 @@ window.__ModuleLoader__.load({
|
|
|
102
106
|
guideCustom: false,
|
|
103
107
|
subagentFlash: false,
|
|
104
108
|
bootstrapMaxTokens: 0,
|
|
109
|
+
usePtcMode: true,
|
|
105
110
|
injectPrompt: true,
|
|
106
111
|
skillSwitches: {},
|
|
107
112
|
skillCatalog: [],
|
|
113
|
+
skillsDir: "",
|
|
114
|
+
activeSkillsDir: "",
|
|
108
115
|
writeAgents: true,
|
|
109
116
|
writePreset: true
|
|
110
117
|
};
|
|
@@ -117,8 +124,10 @@ window.__ModuleLoader__.load({
|
|
|
117
124
|
guideCustom: false,
|
|
118
125
|
subagentFlash: false,
|
|
119
126
|
bootstrapMaxTokens: 0,
|
|
127
|
+
usePtcMode: true,
|
|
120
128
|
injectPrompt: true,
|
|
121
129
|
skillSwitches: {},
|
|
130
|
+
skillsDir: "",
|
|
122
131
|
writeAgents: true,
|
|
123
132
|
writePreset: true
|
|
124
133
|
};
|
|
@@ -133,12 +142,14 @@ window.__ModuleLoader__.load({
|
|
|
133
142
|
guideCustom: fields.guideCustom,
|
|
134
143
|
subagentFlash: fields.subagentFlash,
|
|
135
144
|
bootstrapMaxTokens: fields.bootstrapMaxTokens,
|
|
145
|
+
usePtcMode: fields.usePtcMode,
|
|
136
146
|
injectPrompt: fields.injectPrompt,
|
|
137
147
|
skillSwitches: { ...fields.skillSwitches },
|
|
148
|
+
skillsDir: fields.skillsDir,
|
|
138
149
|
writeAgents: fields.writeAgents,
|
|
139
150
|
writePreset: fields.writePreset
|
|
140
151
|
});
|
|
141
|
-
const switchesEqual = (a, b) => a.injectAgentsPrompt === b.injectAgentsPrompt && a.anchorFirstTurn === b.anchorFirstTurn && a.anchorText === b.anchorText && a.anchorCustom === b.anchorCustom && a.guideText === b.guideText && a.guideCustom === b.guideCustom && a.subagentFlash === b.subagentFlash && a.bootstrapMaxTokens === b.bootstrapMaxTokens && a.injectPrompt === b.injectPrompt && JSON.stringify(a.skillSwitches) === JSON.stringify(b.skillSwitches) && a.writeAgents === b.writeAgents && a.writePreset === b.writePreset;
|
|
152
|
+
const switchesEqual = (a, b) => a.injectAgentsPrompt === b.injectAgentsPrompt && a.anchorFirstTurn === b.anchorFirstTurn && a.anchorText === b.anchorText && a.anchorCustom === b.anchorCustom && a.guideText === b.guideText && a.guideCustom === b.guideCustom && a.subagentFlash === b.subagentFlash && a.bootstrapMaxTokens === b.bootstrapMaxTokens && a.usePtcMode === b.usePtcMode && a.injectPrompt === b.injectPrompt && JSON.stringify(a.skillSwitches) === JSON.stringify(b.skillSwitches) && a.skillsDir === b.skillsDir && a.writeAgents === b.writeAgents && a.writePreset === b.writePreset;
|
|
142
153
|
const asRecord = (value) => value !== null && typeof value === "object" ? value : {};
|
|
143
154
|
const readString = (source, key) => {
|
|
144
155
|
const value = source[key];
|
|
@@ -215,12 +226,14 @@ window.__ModuleLoader__.load({
|
|
|
215
226
|
const [loaded, setLoaded] = (0, react.useState)(false);
|
|
216
227
|
const [fields, setFields] = (0, react.useState)(EMPTY);
|
|
217
228
|
const [bootstrapTokensDraft, setBootstrapTokensDraft] = (0, react.useState)(DEFAULT_BOOTSTRAP_DISPLAY);
|
|
229
|
+
const [skillsDirDraft, setSkillsDirDraft] = (0, react.useState)("");
|
|
218
230
|
const [savedPromptText, setSavedPromptText] = (0, react.useState)("");
|
|
219
231
|
const [savedAgentsText, setSavedAgentsText] = (0, react.useState)("");
|
|
220
232
|
const [savedSwitches, setSavedSwitches] = (0, react.useState)(EMPTY_SWITCHES);
|
|
221
233
|
const [loading, setLoading] = (0, react.useState)(false);
|
|
222
234
|
const [savingPrompt, setSavingPrompt] = (0, react.useState)(false);
|
|
223
235
|
const [savingAgents, setSavingAgents] = (0, react.useState)(false);
|
|
236
|
+
const [savingSkillsDir, setSavingSkillsDir] = (0, react.useState)(false);
|
|
224
237
|
const [restoringPrompt, setRestoringPrompt] = (0, react.useState)(false);
|
|
225
238
|
const [restoringAgents, setRestoringAgents] = (0, react.useState)(false);
|
|
226
239
|
const [notice, setNotice] = (0, react.useState)("");
|
|
@@ -259,18 +272,22 @@ window.__ModuleLoader__.load({
|
|
|
259
272
|
guideCustom: readBoolean(value, "guideCustom", readBoolean(base, "guideCustom", false)),
|
|
260
273
|
subagentFlash: readBoolean(value, "subagentFlash", readBoolean(base, "subagentFlash", false)),
|
|
261
274
|
bootstrapMaxTokens: readNumber(value, "bootstrapMaxTokens", readNumber(base, "bootstrapMaxTokens", 0)),
|
|
275
|
+
usePtcMode: readBoolean(value, "usePtcMode", readBoolean(base, "usePtcMode", true)),
|
|
262
276
|
injectPrompt: readBoolean(value, "injectPrompt", readBoolean(base, "injectPrompt", true)),
|
|
263
277
|
skillSwitches: value.skillSwitches !== void 0 || base.skillSwitches !== void 0 ? {
|
|
264
278
|
...readSkillSwitches(base, "skillSwitches"),
|
|
265
279
|
...readSkillSwitches(value, "skillSwitches")
|
|
266
280
|
} : {},
|
|
267
|
-
skillCatalog: readSkillCatalog(value, "skillCatalog").length > 0 ? readSkillCatalog(value, "skillCatalog") : readSkillCatalog(base, "skillCatalog"),
|
|
281
|
+
skillCatalog: res.skillCatalog ?? (readSkillCatalog(value, "skillCatalog").length > 0 ? readSkillCatalog(value, "skillCatalog") : readSkillCatalog(base, "skillCatalog")),
|
|
282
|
+
skillsDir: readString(value, "skillsDir") ?? readString(base, "skillsDir") ?? "",
|
|
283
|
+
activeSkillsDir: res.activeSkillsDir ?? readString(value, "activeSkillsDir") ?? readString(base, "activeSkillsDir") ?? "",
|
|
268
284
|
writeAgents: readBoolean(value, "writeAgents", readBoolean(base, "writeAgents", true)),
|
|
269
285
|
writePreset: readBoolean(value, "writePreset", readBoolean(base, "writePreset", true))
|
|
270
286
|
};
|
|
271
287
|
fieldsRef.current = next;
|
|
272
288
|
setFields(next);
|
|
273
289
|
setBootstrapTokensDraft(next.bootstrapMaxTokens > 0 ? String(next.bootstrapMaxTokens) : DEFAULT_BOOTSTRAP_DISPLAY);
|
|
290
|
+
setSkillsDirDraft(next.skillsDir);
|
|
274
291
|
setSavedPromptText(next.promptText);
|
|
275
292
|
setSavedAgentsText(next.agentsText);
|
|
276
293
|
setSavedSwitches(snapshotSwitches(next));
|
|
@@ -359,6 +376,20 @@ window.__ModuleLoader__.load({
|
|
|
359
376
|
showNotice("error", "打开失败:" + errorMessage(error) + ";可直接在下方编辑框保存");
|
|
360
377
|
}
|
|
361
378
|
};
|
|
379
|
+
const openSkillsDir = async () => {
|
|
380
|
+
const path = fields.activeSkillsDir || fields.skillsDir;
|
|
381
|
+
if (!path) {
|
|
382
|
+
showNotice("error", "技能目录路径未知,请先重新展开面板读取配置");
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
try {
|
|
386
|
+
const res = await api.host.openPath({ path });
|
|
387
|
+
if (res.result.ok) showNotice("ok", "已打开技能目录:" + path);
|
|
388
|
+
else showNotice("error", "打开失败:" + (res.result.error?.message ?? ""));
|
|
389
|
+
} catch (error) {
|
|
390
|
+
showNotice("error", "打开失败:" + errorMessage(error));
|
|
391
|
+
}
|
|
392
|
+
};
|
|
362
393
|
const enqueueSave = (0, react.useCallback)((ops, okMessage, onSaved, setBusy) => {
|
|
363
394
|
setBusy?.(true);
|
|
364
395
|
saveQueueRef.current = saveQueueRef.current.then(async () => {
|
|
@@ -434,6 +465,11 @@ window.__ModuleLoader__.load({
|
|
|
434
465
|
path: ["bootstrapMaxTokens"],
|
|
435
466
|
value: fieldsRef.current.bootstrapMaxTokens
|
|
436
467
|
},
|
|
468
|
+
{
|
|
469
|
+
op: "set",
|
|
470
|
+
path: ["usePtcMode"],
|
|
471
|
+
value: fieldsRef.current.usePtcMode
|
|
472
|
+
},
|
|
437
473
|
{
|
|
438
474
|
op: "set",
|
|
439
475
|
path: ["injectPrompt"],
|
|
@@ -444,6 +480,11 @@ window.__ModuleLoader__.load({
|
|
|
444
480
|
path: ["skillSwitches"],
|
|
445
481
|
value: fieldsRef.current.skillSwitches
|
|
446
482
|
},
|
|
483
|
+
{
|
|
484
|
+
op: "set",
|
|
485
|
+
path: ["skillsDir"],
|
|
486
|
+
value: fieldsRef.current.skillsDir
|
|
487
|
+
},
|
|
447
488
|
{
|
|
448
489
|
op: "set",
|
|
449
490
|
path: ["writeAgents"],
|
|
@@ -477,6 +518,18 @@ window.__ModuleLoader__.load({
|
|
|
477
518
|
} else patch({ bootstrapMaxTokens: parsed });
|
|
478
519
|
persistSwitches();
|
|
479
520
|
};
|
|
521
|
+
const applySkillsDir = () => {
|
|
522
|
+
const next = skillsDirDraft.trim();
|
|
523
|
+
patch({ skillsDir: next });
|
|
524
|
+
enqueueSave([{
|
|
525
|
+
op: "set",
|
|
526
|
+
path: ["skillsDir"],
|
|
527
|
+
value: next
|
|
528
|
+
}], next.length > 0 ? `自定义技能目录已保存并生效:${next}` : "已切回自动技能目录(当前 profile 下 skills/)", () => {
|
|
529
|
+
setSavedSwitches(snapshotSwitches(fieldsRef.current));
|
|
530
|
+
load();
|
|
531
|
+
}, setSavingSkillsDir);
|
|
532
|
+
};
|
|
480
533
|
const skillEnabled = (folder) => fields.skillSwitches[folder] !== false;
|
|
481
534
|
const toggleSkill = (folder) => {
|
|
482
535
|
const enabled = fieldsRef.current.skillSwitches[folder] !== false;
|
|
@@ -494,7 +547,8 @@ window.__ModuleLoader__.load({
|
|
|
494
547
|
const promptSwitchDirty = fields.injectPrompt !== savedSwitches.injectPrompt;
|
|
495
548
|
const agentsSwitchDirty = fields.injectAgentsPrompt !== savedSwitches.injectAgentsPrompt || fields.writeAgents !== savedSwitches.writeAgents;
|
|
496
549
|
const skillsSwitchDirty = JSON.stringify(fields.skillSwitches) !== JSON.stringify(savedSwitches.skillSwitches);
|
|
497
|
-
const
|
|
550
|
+
const skillsDirDirty = fields.skillsDir !== savedSwitches.skillsDir || skillsDirDraft.trim() !== fields.skillsDir;
|
|
551
|
+
const presetSwitchDirty = fields.writePreset !== savedSwitches.writePreset || fields.anchorFirstTurn !== savedSwitches.anchorFirstTurn || fields.anchorText !== savedSwitches.anchorText || fields.bootstrapMaxTokens !== savedSwitches.bootstrapMaxTokens || fields.usePtcMode !== savedSwitches.usePtcMode;
|
|
498
552
|
const discardPrompt = () => patch({ promptText: savedPromptText });
|
|
499
553
|
const discardAgents = () => patch({ agentsText: savedAgentsText });
|
|
500
554
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
@@ -675,12 +729,50 @@ window.__ModuleLoader__.load({
|
|
|
675
729
|
})
|
|
676
730
|
]
|
|
677
731
|
}),
|
|
678
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
732
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(CollapsibleSection, {
|
|
679
733
|
title: "Skills设置",
|
|
680
|
-
hint: `${fields.skillCatalog.length} 个${skillsSwitchDirty ? " · 未保存" : ""}`,
|
|
734
|
+
hint: `${fields.skillCatalog.length} 个${skillsSwitchDirty || skillsDirDirty ? " · 未保存" : ""}`,
|
|
681
735
|
open: skillsOpen,
|
|
682
736
|
onToggle: () => setSkillsOpen(!skillsOpen),
|
|
683
|
-
children:
|
|
737
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
738
|
+
className: PromptEditor_module_css_default.skillsBar,
|
|
739
|
+
children: [
|
|
740
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
741
|
+
className: PromptEditor_module_css_default.skillsDirRow,
|
|
742
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
743
|
+
type: "button",
|
|
744
|
+
className: PromptEditor_module_css_default.secondary,
|
|
745
|
+
disabled: !fields.activeSkillsDir && !fields.skillsDir,
|
|
746
|
+
onClick: () => void openSkillsDir(),
|
|
747
|
+
children: "打开技能目录"
|
|
748
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
749
|
+
className: PromptEditor_module_css_default.skillsPath,
|
|
750
|
+
children: fields.activeSkillsDir || fields.skillsDir || "(技能目录路径未知,请重新展开面板)"
|
|
751
|
+
})]
|
|
752
|
+
}),
|
|
753
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
754
|
+
className: PromptEditor_module_css_default.skillsDirRow,
|
|
755
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
756
|
+
className: PromptEditor_module_css_default.skillsDirInput,
|
|
757
|
+
"aria-label": "用户自定义技能目录",
|
|
758
|
+
value: skillsDirDraft,
|
|
759
|
+
placeholder: fields.activeSkillsDir || "留空 = 自动使用当前 profile 下的 skills/ 副本",
|
|
760
|
+
spellCheck: false,
|
|
761
|
+
onChange: (e) => setSkillsDirDraft(e.target.value)
|
|
762
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
763
|
+
type: "button",
|
|
764
|
+
className: PromptEditor_module_css_default.primary,
|
|
765
|
+
disabled: savingSkillsDir || skillsDirDraft.trim() === fields.skillsDir,
|
|
766
|
+
onClick: applySkillsDir,
|
|
767
|
+
children: savingSkillsDir ? "设置中…" : "设置自定义目录"
|
|
768
|
+
})]
|
|
769
|
+
}),
|
|
770
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
771
|
+
className: PromptEditor_module_css_default.rowDesc,
|
|
772
|
+
children: "留空并点“设置自定义目录”会切回自动目录(当前 profile 下的 skills/ 副本)。修改后技能目录立即重新扫描。"
|
|
773
|
+
})
|
|
774
|
+
]
|
|
775
|
+
}), fields.skillCatalog.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
684
776
|
className: PromptEditor_module_css_default.subEmpty,
|
|
685
777
|
children: "skills 目录下没有技能"
|
|
686
778
|
}) : fields.skillCatalog.map((skill) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
@@ -703,7 +795,7 @@ window.__ModuleLoader__.load({
|
|
|
703
795
|
]
|
|
704
796
|
})]
|
|
705
797
|
})]
|
|
706
|
-
}, skill.folder))
|
|
798
|
+
}, skill.folder))]
|
|
707
799
|
}),
|
|
708
800
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(CollapsibleSection, {
|
|
709
801
|
title: "锚定与 preset",
|
|
@@ -728,6 +820,24 @@ window.__ModuleLoader__.load({
|
|
|
728
820
|
})]
|
|
729
821
|
})]
|
|
730
822
|
}),
|
|
823
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
824
|
+
className: PromptEditor_module_css_default.row,
|
|
825
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
826
|
+
type: "checkbox",
|
|
827
|
+
checked: fields.usePtcMode,
|
|
828
|
+
disabled: !fields.writePreset,
|
|
829
|
+
onChange: () => toggle("usePtcMode")
|
|
830
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
831
|
+
className: PromptEditor_module_css_default.rowText,
|
|
832
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
833
|
+
className: PromptEditor_module_css_default.rowName,
|
|
834
|
+
children: "使用 PTC 模式"
|
|
835
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
836
|
+
className: PromptEditor_module_css_default.rowDesc,
|
|
837
|
+
children: "默认开启:晋升后把 wire 切换为 Code Mode(PTC,单一 run_code),完整插件工具通过生成 SDK 调用。关闭后恢复原生完整工具目录"
|
|
838
|
+
})]
|
|
839
|
+
})]
|
|
840
|
+
}),
|
|
731
841
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
732
842
|
className: PromptEditor_module_css_default.row,
|
|
733
843
|
children: [
|
|
@@ -891,8 +1001,7 @@ window.__ModuleLoader__.load({
|
|
|
891
1001
|
const injected = () => ({ api: connection.api });
|
|
892
1002
|
ctx.slots.inject("settings.plugin.item", () => ctx.slots.register({
|
|
893
1003
|
name: "settings.plugin.item",
|
|
894
|
-
|
|
895
|
-
order: 30,
|
|
1004
|
+
key: "prompt-tool",
|
|
896
1005
|
inject: injected
|
|
897
1006
|
}, PromptEditor));
|
|
898
1007
|
}
|