dsh-plugin-prompt-tool 0.1.5 → 0.2.0
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 +75 -171
- package/lib/client.js +73 -9
- package/lib/client.js.map +1 -1
- package/lib/index.d.mts +16 -2
- package/lib/index.mjs +184 -24
- package/lib/preset-core.d.mts +12 -1
- package/lib/preset-core.mjs +94 -21
- package/package.json +5 -6
- package/plan.md +292 -265
- package/preset/near-anchor.mjs +117 -0
- package/preset/router-first-turn.mjs +59 -0
- package/{vendor → upstream}/dsh-anchored-standard/NOTICE +5 -0
- package/upstream/dsh-anchored-standard/REVISION +1 -0
- package/{vendor → upstream}/dsh-anchored-standard/preset/agent.cordis.yml +53 -24
- package/upstream/dsh-anchored-standard/preset/context-gate.mjs +202 -0
- package/{vendor → upstream}/dsh-anchored-standard/preset/dev-tool-search.mjs +10 -8
- package/{vendor → upstream}/dsh-anchored-standard/preset/instruction-hint.mjs +66 -13
- package/{vendor → upstream}/dsh-anchored-standard/preset/tool-bootstrap.mjs +41 -78
- package/preset/turn-anchor.mjs +0 -83
- /package/{vendor → upstream}/dsh-anchored-standard/LICENSE +0 -0
- /package/{vendor → upstream}/dsh-anchored-standard/preset/compaction-epoch.mjs +0 -0
- /package/{vendor → upstream}/dsh-anchored-standard/preset/custom-bash.mjs +0 -0
- /package/{vendor → upstream}/dsh-anchored-standard/preset/preset.yml +0 -0
- /package/{vendor → upstream}/dsh-anchored-standard/preset/skill-search.mjs +0 -0
package/README.md
CHANGED
|
@@ -1,211 +1,115 @@
|
|
|
1
1
|
# 提示词工具(dsh-plugin-prompt-tool)
|
|
2
2
|
|
|
3
|
-
DSH
|
|
3
|
+
DSH 插件:为 DeepSeek Harness 提供三层提示词规范注入,并通过 Web 界面在线编辑。核心是“最优组合”首轮锚定:保持官方 Minimal(极简)训练分布的首轮条件,在模型轨迹稳定后再恢复完整能力。
|
|
4
4
|
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
- **常驻层(user 层)**:`AGENTS.md` 规则写入 `~/.dsh/AGENTS.md`。上游现以 `instruction-hint` 取代 dsh-agent-instructions 的大块注入:晋升后只提示一次"这些指令文件存在,先读",模型经文件工具自行读取;开启 `injectAgentsPrompt` 时,该提示文本改为直接注入 `AGENTS.md` 内容,注入位置不变,每会话一次(`preset.md` 不混入,改由 preset 层在锚定确认后注入,避免重复)。
|
|
8
|
-
- **按需层(技能)**:扫描 `skills/*/SKILL.md` 注册全部技能;每个技能的开关以目录名为键、以 frontmatter 的 `name`(缺省用目录名)显示;加载时 content = `preset.md` 规范 + 技能正文,`resourceBase` 指向 `skills/<目录>`。
|
|
9
|
-
- **独立 agent preset 层**:插件加载时直引 anchored-standard 上游文件生成 preset 到 `~/.dsh/.agent-presets/prompt-tool/`(首轮 = 官方 Minimal 真实 schema:持久 `bash` + `str_replace_editor` + 剥离自动注入上下文,无输出 cap);首轮 reasoning 稳定 "we" 轨迹,we 锚定确认后注入 `preset.md`;晋升后不放全量目录,改为 resident 集(bootstrap 对 + `dev_tool_search` / `skill_search` / `skill_load` + 已解锁工具)。
|
|
10
|
-
|
|
11
|
-
> 提示词采用「we 锚定确认后注入」:首轮剥离自动注入(`agent-instructions` / `skill-catalog`),Minimal 真实工具 schema 下 reasoning 稳定走 "We need…" 轨迹;确认 we 锚定后(或不确认则最多等一轮兜底)把提示词规范作为 user 消息补进来(每会话一次)。工具目录晋升不依赖 we 确认(首个工具调用或助手回复即放开),锚定失败也不会卡死。
|
|
12
|
-
|
|
13
|
-
## 项目引用
|
|
14
|
-
|
|
15
|
-
本项目集成与参考的生态项目:
|
|
5
|
+
## 来源与参考
|
|
16
6
|
|
|
17
7
|
| 项目 | 关系 | 复用内容 |
|
|
18
8
|
|---|---|---|
|
|
19
|
-
| [dsh-anchored-standard](https://github.com/xiaobright/dsh-anchored-standard) |
|
|
20
|
-
| [dsh-router-standard](https://github.com/yjh051108/dsh-router-standard) | 参考 |
|
|
21
|
-
| [dsh-super-injector](https://github.com/yjh051108/dsh-super-injector) | 参考 |
|
|
22
|
-
| [dsh 破限者(1449690477/dsh)](https://github.com/1449690477/dsh) | 姊妹项目 | `skills/` 技能目录(sandboxmod/SKILL.md)与之同源,常驻层 AGENTS.md 机制一致 |
|
|
9
|
+
| [xiaobright/dsh-anchored-standard](https://github.com/xiaobright/dsh-anchored-standard) | 上游,内联快照 | 两阶段首轮锚定、tool-bootstrap、context-gate、resident 目录与按需解锁 |
|
|
10
|
+
| [yjh051108/dsh-router-standard](https://github.com/yjh051108/dsh-router-standard) | 参考 | 首轮结构、追加任务引导、Flash 弱路由人设与三锚、子代理方案 |
|
|
11
|
+
| [yjh051108/dsh-super-injector](https://github.com/yjh051108/dsh-super-injector) | 参考 | 缓存铁律、工具面成本原则 |
|
|
23
12
|
|
|
24
|
-
|
|
13
|
+
上游文件固化在 `upstream/dsh-anchored-standard/`(含 `LICENSE`、`NOTICE`、`REVISION`),
|
|
14
|
+
用 `pnpm sync:anchored` 更新。
|
|
25
15
|
|
|
26
|
-
|
|
27
|
-
直接读子模块 `vendor/dsh-anchored-standard/preset/` 里的 `agent.cordis.yml`(运行时注入
|
|
28
|
-
prompt-injector 块与 `preset.md`)以及全部上游 `*.mjs` 模块(tool-bootstrap /
|
|
29
|
-
compaction-epoch / custom-bash / dev-tool-search / instruction-hint / skill-search),
|
|
30
|
-
并把它们完整复制进生成的 preset。同步上游:
|
|
16
|
+
## 项目说明
|
|
31
17
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
18
|
+
- **常驻层**:把 `AGENTS.md` 作为受管块写入 `~/.dsh/AGENTS.md`;开启 `injectAgentsPrompt` 时,以 `instruction-hint` 的位置每会话注入一次。
|
|
19
|
+
- **按需层**:扫描 `skills/*/SKILL.md` 注册可开关技能,内容只来自技能自身。
|
|
20
|
+
- **锚定层**:生成独立的 `~/.dsh/.agent-presets/prompt-tool/` 预设,承载首轮工具引导、上下文闸门、任务引导注入与提示词注入。
|
|
21
|
+
- **Web 界面**:自建回环设置桥,在线编辑 `preset.md` 与 `AGENTS.md`,切换全部开关;不占用模型设置区。
|
|
22
|
+
- **TUI(终端界面)命令**:`/prompt-tool status` 查看状态,`/prompt-tool on|off|toggle <开关>` 切换。
|
|
23
|
+
- **上游管理**:上游 dsh-anchored-standard 以内联快照形式放在 `upstream/`,`pnpm sync:anchored` 刷新;不再使用 git 子模块。
|
|
37
24
|
|
|
38
|
-
|
|
39
|
-
- `preset.yml`、`prompt-injector.mjs`、`turn-anchor.mjs` 为本项目自有文件,固定走 `preset/`
|
|
40
|
-
- vendor 缺失(git 安装未初始化子模块)或上游结构变化 → 插件加载时报错(fail loud)
|
|
41
|
-
- npm 安装走发布包内置的 `vendor/dsh-anchored-standard/preset` 快照,无需子模块;
|
|
42
|
-
git clone / `link:` 安装则需 `git submodule update --init` 后再使用
|
|
43
|
-
|
|
44
|
-
## 修改记录
|
|
45
|
-
|
|
46
|
-
- **v2.3(2026-08-15)**:删除 `prompt/references` 档位参考目录(SKILL.md 已内联全部规则,不再需要);README 描述同步。
|
|
47
|
-
- **v2.4(2026-08-15)**:新增 `injectSkill` 开关(按需层 `prompt/SKILL.md` 技能注入);UI 开关描述按实际生效层级修正,`injectPrompt` 明确为锚定层注入。
|
|
48
|
-
- **v2.5(2026-08-15)**:技能目录更名 `prompt` → `skills`,`SKILL.md` 移至 `skills/sandboxmod/`;新增 AGENTS.md 在线编辑保存与 skills 子折叠栏逐个技能开关。
|
|
49
|
-
- **v2.6(2026-08-15)**:移除 `injectSkill` 总开关(全部技能关闭时技能列表自动为空);UI 改为 preset.md / AGENTS.md / skills / 锚定轮与 preset 四个分区,每个分区默认折叠。
|
|
50
|
-
- **v2.7(2026-08-15)**:`prompt.md` 文件更名为 `preset.md`;分区更名为 Preset预设 / AGENTS设置 / Skills设置 / 锚定轮与 preset。
|
|
51
|
-
- **v2.2(2026-08-15)**:子模块同步上游 main(`ffb845c`,PR #20/#21/#23/#27/#29)。晋升后由全量目录改为 resident 集(bootstrap 对 + dev_tool_search / skill_search / skill_load + 解锁工具);AGENTS.md 由每轮注入改为 instruction-hint 一次性提示 + 模型自读;新增 compaction 回落与 Windows custom-bash;`writePreset` 复制上游全部 `preset/*.mjs`;`.gitmodules` 声明 `branch = main`。
|
|
52
|
-
- **v2.1(2026-08-15)**:技能目录重命名 `dreammod` → `skill` → `prompt`;上游改为子模块直引,移除不再需要的同步脚本。
|
|
53
|
-
- **v2.0(2026-08-15)**:跟随 anchored-standard PR #14,首轮工具 schema 从 `pwsh/read + 1024 cap` 改为官方 Minimal 真实 schema(持久 `bash` + `str_replace_editor`,无 cap);删除 zero 变体与锚定消息机制,回归原版 tool-bootstrap(字节一致)+ `prompt-injector.mjs` 附加件(we 确认后注入一次 preset.md,未确认最多等一轮兜底)。实测:复杂英文任务 ×5 并行,we 锚定 5/5、首请求纯净、注入恰好一次。
|
|
54
|
-
- **v1(2026-08)**:初版——zero 工具锚定变体 + 固定锚定消息 + 三层注入(AGENTS.md 常驻层、skill 按需层、preset 层)。
|
|
55
|
-
|
|
56
|
-
## Web UI
|
|
57
|
-
|
|
58
|
-
在 Settings → 插件 → **插件配置**分区注册「提示词工具」可折叠卡片(`settings.plugin.item`,与其他插件卡片同款式),展开后提供:
|
|
59
|
-
|
|
60
|
-
- **分区折叠**:Preset预设区(编辑器 + `injectPrompt`)、AGENTS设置区(编辑器 + `injectAgentsPrompt` + `writeAgents`)、Skills设置区(每个技能独立开关 `skillSwitches`)、锚定轮与 preset 区(`writePreset`、`anchorFirstTurn`、`anchorText`);每个分区默认折叠,文件分区带独立保存/还原/打开按钮,开关点击即时生效
|
|
61
|
-
- **保存 / 还原草稿 / 项目还原 / 打开**:`preset.md` 与 `AGENTS.md` 各自独立保存、还原未保存草稿、从项目原文还原、用系统编辑器打开。UI 只读写 `settings.yaml` 中的插件配置;`保存` 只写 settings,`项目还原` 读取项目根目录里的原始 `preset.md` / `AGENTS.md` 并覆盖写回 settings。注入开关与技能开关点击后即时写入 settings 并生效,不需要保存按钮。Host 监听 settings 变化后刷新 `~/.dsh/AGENTS.md` 受管块与 preset、失效技能目录缓存,下一次请求即生效
|
|
62
|
-
- **打开编辑**:用系统编辑器分别打开 `preset.md` 或 `AGENTS.md`
|
|
63
|
-
- **在线编辑框**:直接编辑 `preset.md` 与 `AGENTS.md` 文本
|
|
64
|
-
|
|
65
|
-
## 工作原理
|
|
66
|
-
|
|
67
|
-
1. 首次安装时,Host 读取项目根目录的 `preset.md` 与 `AGENTS.md`,把内容写入 `settings.yaml` 的 `prompt-tool.promptText` / `prompt-tool.agentsText`;之后每次启动优先读取 settings,项目文件不再被设置回写。
|
|
68
|
-
2. 常驻层:`writeAgents` 开启时把当前 `AGENTS.md` 写入 `~/.dsh/AGENTS.md`;`injectAgentsPrompt` 开启时,`instruction-hint` 位置注入的是 `AGENTS.md` 内容本身,而不是提示模型自行读取。
|
|
69
|
-
3. 按需层:扫描 `skills/*/SKILL.md`;每个技能的 name/description/whenToUse/metadata 来自自身 frontmatter,并按 `skillSwitches` 决定是否注册;全部技能关闭时技能列表自动为空。加载内容为 `preset.md` 规范 + 技能正文。
|
|
70
|
-
4. preset 层:直引 `vendor/` 上游 `agent.cordis.yml` + 全部 `*.mjs` 生成 `~/.dsh/.agent-presets/prompt-tool/`,并把 `preset.md` 注入 `prompt-injector` 的 `promptText`(we 锚定确认后注入)。晋升后目录为 resident 集,其余工具经 `dev_tool_search` 按需解锁。
|
|
71
|
-
5. UI 保存通过 settings API 只写入 `settings.yaml` 的 `promptText`、`agentsText` 与全部开关;Host 的 watch 回调按最新设置刷新 `~/.dsh/AGENTS.md` 受管块与 preset(含 turn-anchor 行的增删)、失效技能目录缓存,下一次请求即生效,不再覆盖项目根文件。
|
|
72
|
-
|
|
73
|
-
## 文件结构
|
|
74
|
-
|
|
75
|
-
```text
|
|
76
|
-
dsh-plugin-prompt-tool/
|
|
77
|
-
├── package.json
|
|
78
|
-
├── LICENSE # MIT
|
|
79
|
-
├── preset.md # 项目原文:首次种子与「项目还原」按钮的数据来源
|
|
80
|
-
├── AGENTS.md # 项目原文:首次种子与「项目还原」按钮的数据来源
|
|
81
|
-
├── plan.md # 设计与测试计划(含上游更新对照、实测数据)
|
|
82
|
-
├── tsconfig.json # Host 类型检查 program(排除 src/client)
|
|
83
|
-
├── tsconfig.client.json # Client 类型检查 program(jsx: react-jsx)
|
|
84
|
-
├── tsdown.config.ts # 构建配置(host lib + client bundle,自包含)
|
|
85
|
-
├── cordis.patch.yml # 挂载配置
|
|
86
|
-
├── preset/ # 本项目自有 preset 文件(上游文件直引 vendor 子模块)
|
|
87
|
-
│ ├── preset.yml # preset 元数据
|
|
88
|
-
│ ├── prompt-injector.mjs # 附加件:we 锚定确认后注入一次 preset.md
|
|
89
|
-
│ └── turn-anchor.mjs # 可选附加件:首轮独立锚定轮(anchorFirstTurn 开关)
|
|
90
|
-
├── skills/ # 按需层技能目录
|
|
91
|
-
│ └── sandboxmod/
|
|
92
|
-
│ └── SKILL.md # 技能定义(frontmatter name: prompt,开关键 sandboxmod)
|
|
93
|
-
├── src/
|
|
94
|
-
│ ├── index.ts # Host 入口
|
|
95
|
-
│ ├── preset-core.ts # preset 生成纯函数(buildCordis / parseFrontmatter)
|
|
96
|
-
│ ├── css-modules.d.ts
|
|
97
|
-
│ └── client/
|
|
98
|
-
│ ├── index.ts # Client 入口(注册 settings.plugin.item 卡片)
|
|
99
|
-
│ ├── PromptEditor.tsx # 编辑框组件
|
|
100
|
-
│ └── PromptEditor.module.css
|
|
101
|
-
├── test/
|
|
102
|
-
│ └── preset-core.test.mjs # node:test 单元测试(buildCordis / parseFrontmatter)
|
|
103
|
-
├── vendor/ # git 子模块:dsh-anchored-standard(跟踪 main;agent.cordis.yml + 全部 preset/*.mjs 直引源)
|
|
104
|
-
└── lib/ # 构建产物(pnpm build 生成,不提交)
|
|
105
|
-
├── index.mjs # Host 运行时(ESM)
|
|
106
|
-
├── index.d.mts # Host 类型声明
|
|
107
|
-
├── preset-core.mjs # preset 生成核心(测试导入)
|
|
108
|
-
└── client.js # Client 运行时(浏览器模块加载器协议,经 exports["./client"] 扫描)
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
## 构建与检查
|
|
25
|
+
## 构建 / 装载
|
|
112
26
|
|
|
113
27
|
```sh
|
|
114
28
|
pnpm install
|
|
115
|
-
pnpm build
|
|
116
|
-
pnpm typecheck
|
|
117
|
-
pnpm lint
|
|
118
|
-
pnpm test
|
|
29
|
+
pnpm build # 生成 lib/
|
|
30
|
+
pnpm typecheck # Host 与 Client 两个 tsc program
|
|
31
|
+
pnpm lint # oxlint
|
|
32
|
+
pnpm test # pnpm build + node --test
|
|
33
|
+
pnpm prepare # npm publish / git install 前自动触发
|
|
34
|
+
pnpm sync:anchored # 从上游 main 刷新内联快照(可加 ref 参数)
|
|
119
35
|
```
|
|
120
36
|
|
|
121
|
-
|
|
37
|
+
本插件挂载在独立 profile(`prompt-tool`):
|
|
122
38
|
|
|
123
39
|
```sh
|
|
124
|
-
|
|
40
|
+
dsh plugin --profile prompt-tool add link:<本仓库绝对路径>
|
|
41
|
+
dsh --profile prompt-tool
|
|
42
|
+
dsh plugin --profile prompt-tool remove dsh-plugin-prompt-tool
|
|
125
43
|
```
|
|
126
44
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
本插件挂载在**独立 profile**(`prompt-tool`)。
|
|
45
|
+
临时调试可用官方 `--patch` 覆盖层(不落盘、不改 profile):
|
|
130
46
|
|
|
131
47
|
```sh
|
|
132
|
-
dsh
|
|
133
|
-
dsh plugin --profile prompt-tool remove dsh-plugin-prompt-tool # 卸载
|
|
48
|
+
dsh --profile prompt-tool --patch <cordis.yml>
|
|
134
49
|
```
|
|
135
50
|
|
|
136
|
-
|
|
137
|
-
bundles 列表,pnpm 不管理)+ `dsh-plugin-prompt-tool`。本地仓库 link 后:`lib/` 为已构建
|
|
138
|
-
产物(`pnpm build` 生成),`vendor/` 子模块随仓库 checkout,插件加载时直引上游最新文件
|
|
139
|
-
(`git submodule update --remote vendor/dsh-anchored-standard` 后重启 dsh 即生效)。
|
|
51
|
+
完全重启 dsh 后,新建会话并选择 prompt-tool 预设。
|
|
140
52
|
|
|
141
|
-
|
|
53
|
+
## 原理
|
|
142
54
|
|
|
143
|
-
|
|
144
|
-
dsh --profile prompt-tool
|
|
145
|
-
```
|
|
55
|
+
模型的首轮请求结构决定整条会话轨迹。上游实测:官方 Minimal 首轮(训练原句 + 持久 `bash` + `str_replace_editor`,无输出封顶)稳定锚定 we 轨迹;完整 Standard 目录与自动注入在场会破坏锚定。
|
|
146
56
|
|
|
147
|
-
|
|
148
|
-
`--patch` 覆盖层(不落盘、不改任何 profile):
|
|
57
|
+
本插件把“首轮轨迹选择”和“后续完整能力”拆开:
|
|
149
58
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
59
|
+
1. **干净首轮**:`context-gate` 清空首轮自动上下文并剥离自动注入;`tool-bootstrap` 只暴露 Minimal 两个工具;`router-first-turn` 把 persona 替换为训练原句。
|
|
60
|
+
2. **晋升**:首次工具调用或助手回复落地后,目录进入 resident(常驻)集,上下文与注入恢复;工具按需解锁。
|
|
61
|
+
3. **追加任务引导**:可选 `near-anchor`,在首条真实用户消息之后追加一次引导——默认按任务自动选择 we/let 首句,也可固定使用自定义文本。
|
|
62
|
+
4. **提示词注入**:we 锚定确认后,把 `preset.md` 作为用户消息注入一次;未确认最多等一轮兜底。
|
|
63
|
+
5. **子代理**:目录直接全量放行(实际仍受调用方工具白名单过滤);开启 `subagentFlash` 时,采用 dsh-router-standard 的 Flash 方案——固定 Flash 路由、任务分类人设与三锚。
|
|
64
|
+
|
|
65
|
+
主会话首轮始终只有两个工具;模型性能不受记忆、技能等自动注入影响,完整能力在轨迹稳定后恢复。
|
|
66
|
+
|
|
67
|
+
## 配置参考
|
|
153
68
|
|
|
154
|
-
|
|
69
|
+
挂载配置(cordis.patch.yml / profile patch):
|
|
155
70
|
|
|
156
71
|
```yaml
|
|
157
72
|
- insert:
|
|
158
73
|
- id: prompt-tool
|
|
159
74
|
name: dsh-plugin-prompt-tool
|
|
160
75
|
config:
|
|
161
|
-
text: '' #
|
|
162
|
-
agentsText: '' #
|
|
163
|
-
injectAgentsPrompt: false #
|
|
164
|
-
writeAgents: true #
|
|
165
|
-
writePreset: true #
|
|
166
|
-
injectPrompt: true #
|
|
167
|
-
skillSwitches: {} # 按 skills/*
|
|
168
|
-
anchorFirstTurn: false #
|
|
169
|
-
anchorText:
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
76
|
+
text: '' # 覆盖 preset.md 文本;默认读项目文件
|
|
77
|
+
agentsText: '' # 覆盖 AGENTS.md 文本;默认读项目文件
|
|
78
|
+
injectAgentsPrompt: false # 用 AGENTS.md 替换 instruction-hint 提示文本
|
|
79
|
+
writeAgents: true # 写 ~/.dsh/AGENTS.md 受管块(默认 true)
|
|
80
|
+
writePreset: true # 启用锚定预设(总开关,默认 true)
|
|
81
|
+
injectPrompt: true # we 确认后注入 preset.md(默认 true)
|
|
82
|
+
skillSwitches: {} # 按 skills/* 目录名开关,未列出默认开启
|
|
83
|
+
anchorFirstTurn: false # 追加任务引导(默认关闭)
|
|
84
|
+
anchorText: '' # 自定义引导文本
|
|
85
|
+
anchorCustom: false # 使用自定义引导(true=固定使用 anchorText;false=自动选择)
|
|
86
|
+
subagentFlash: false # 子代理固定 Flash 模型(默认关闭)
|
|
87
|
+
subagentFlashProvider: 'deepseek-official'
|
|
88
|
+
subagentFlashModel: 'deepseek-v4-flash'
|
|
89
|
+
customBashPath: 'bash.exe' # 自定义 bash 路径(默认 PATH 查找)
|
|
90
|
+
skillsDir: '' # 可选技能目录(默认包内 skills/)
|
|
91
|
+
skillRankBase: 250 # 技能候选排序基数
|
|
92
|
+
residentAgentsPath: '' # 默认 ~/.dsh/AGENTS.md
|
|
93
|
+
presetDir: '' # 默认 ~/.dsh/.agent-presets/prompt-tool/
|
|
94
|
+
presetOrder: 5 # preset 显示顺序
|
|
95
|
+
fallbackText: '' # preset.md 缺失或不可读时的回退文本
|
|
176
96
|
```
|
|
177
97
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
`anchorFirstTurn`(默认 false)开启后,preset 额外挂载 `turn-anchor.mjs`:会话首个真实用户消息先原样入 `agent.inbox` 的 `next-step`,首步只把 `anchorText` 作为独立输入发给模型;模型回应锚定句后,driver 在同一轮内自动消费任务继续执行。任务绝不丢失:inbox 入队失败时回退为原样直发。
|
|
181
|
-
|
|
182
|
-
锚定句实测(deepseek-v4-pro + reasoningEffort=max,简单任务):
|
|
183
|
-
|
|
184
|
-
- 默认句(含 "Begin every reasoning block with 'We need'."):**12/12** 首轮 reasoning 以 "We need" 开头,preset.md 全部走 we 确认注入;
|
|
185
|
-
- 裸句 "You are a helpful software assistant.":首词 "We need" 约 58-67%(12 会话 7-8 次),其余走兜底注入。
|
|
186
|
-
|
|
187
|
-
## 锚定机制实测
|
|
188
|
-
|
|
189
|
-
工具引导由 preset 层的 `tool-bootstrap.mjs`(anchored-standard 上游直引)承担(挂在 agent-plane 首行,`inject:[]` + `prepend: true`,保证 strip 是 waterfall 的最终 transform):首轮 = Minimal 真实 schema(持久 `bash` + `str_replace_editor`)+ 剥离自动注入 → reasoning 稳定 "we" 轨迹 → 首个工具调用/助手回复落库后进入 resident 目录(bootstrap 对 + `dev_tool_search` / `skill_search` / `skill_load` + 已解锁工具)→ we 确认后(`prompt-injector.mjs`,注册在 tool-bootstrap 之后)注入 `preset.md` 一次。prompt-tool 插件(host 层)只负责生成 preset,不直接注册工具引导事件,避免与 preset 层重复。
|
|
190
|
-
|
|
191
|
-
实测(deepseek-v4-pro + reasoningEffort=max,复杂英文任务 ×5 并行,dsh web HTTP API):
|
|
98
|
+
字段说明:
|
|
192
99
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
| preset.md 注入 | 恰好一次,we 确认后同 turn 注入(5/5) |
|
|
200
|
-
| 晋升后目录 | resident 集:bash + str_replace_editor + dev_tool_search / skill_search / skill_load + 已解锁工具(上游 v2.2 起) |
|
|
100
|
+
- **启用锚定预设**:总开关。开启时生成并刷新 `~/.dsh/.agent-presets/prompt-tool/`;关闭时移除已生成目录,锚定相关开关失效。
|
|
101
|
+
- **追加任务引导**:开启时挂载 `near-anchor`,在首条真实用户消息后追加一次任务引导。
|
|
102
|
+
- **使用自定义引导**:开启时固定使用 `anchorText`;关闭时按任务自动选择 we/let 引导,Flash 模型附加三锚。开启且文本为空时不注入。
|
|
103
|
+
- **子代理固定 Flash 模型**:开启时采用 dsh-router-standard 的 Flash 子代理方案——通用子代理行加固定 Flash 路由、任务分类人设与三锚;宿主直派子代理(含 dsh-mnemon)自动补 Flash 路由,调用方显式模型优先。检测不到 DeepSeek 模型路由时 Web/TUI 禁用,且运行时强制降级为关闭。
|
|
104
|
+
- **自定义 bash 路径**:上游若带作者机器固定路径,生成 preset 时归一化为该值,默认 PATH 查找 `bash.exe`。
|
|
105
|
+
- 其他字段语义见上方配置注释;设置文件优先级高于挂载配置,首次安装时用项目文件内容初始化设置。
|
|
201
106
|
|
|
202
|
-
|
|
107
|
+
## 版权
|
|
203
108
|
|
|
204
|
-
|
|
109
|
+
本项目采用 MIT 许可证。
|
|
205
110
|
|
|
206
|
-
-
|
|
207
|
-
-
|
|
208
|
-
-
|
|
209
|
-
-
|
|
210
|
-
-
|
|
211
|
-
- **上游跟随**:`writePreset` 动态复制上游 `preset/*.mjs` 全集;上游结构变化导致生成 YAML 非法或锚点缺失时 fail loud,同步命令见上文。
|
|
111
|
+
- 首轮锚定机制源自 [xiaobright/dsh-anchored-standard](https://github.com/xiaobright/dsh-anchored-standard)(MIT),其 `preset/` 快照内联于本仓库 `upstream/`,对应上游提交记录见 `REVISION`。
|
|
112
|
+
- 任务引导与 Flash 子代理方案参考 [yjh051108/dsh-router-standard](https://github.com/yjh051108/dsh-router-standard)(MIT)。
|
|
113
|
+
- 缓存与工具面成本原则参考 [yjh051108/dsh-super-injector](https://github.com/yjh051108/dsh-super-injector)(MIT)。
|
|
114
|
+
- 上游 `agent.cordis.yml` 基于 DeepSeek Harness Standard 预设修改;原始 DeepSeek 版权与 MIT 声明保留在 `upstream/dsh-anchored-standard/NOTICE` 与 `LICENSE`。
|
|
115
|
+
- 本项目 `LICENSE` 见仓库根目录;随上游快照发布的 `upstream/dsh-anchored-standard/LICENSE` 与 `NOTICE` 继续保留。
|
package/lib/client.js
CHANGED
|
@@ -96,6 +96,8 @@ window.__ModuleLoader__.load({
|
|
|
96
96
|
injectAgentsPrompt: false,
|
|
97
97
|
anchorFirstTurn: false,
|
|
98
98
|
anchorText: "",
|
|
99
|
+
anchorCustom: false,
|
|
100
|
+
subagentFlash: false,
|
|
99
101
|
injectPrompt: true,
|
|
100
102
|
skillSwitches: {},
|
|
101
103
|
skillCatalog: [],
|
|
@@ -106,6 +108,8 @@ window.__ModuleLoader__.load({
|
|
|
106
108
|
injectAgentsPrompt: false,
|
|
107
109
|
anchorFirstTurn: false,
|
|
108
110
|
anchorText: "",
|
|
111
|
+
anchorCustom: false,
|
|
112
|
+
subagentFlash: false,
|
|
109
113
|
injectPrompt: true,
|
|
110
114
|
skillSwitches: {},
|
|
111
115
|
writeAgents: true,
|
|
@@ -115,12 +119,14 @@ window.__ModuleLoader__.load({
|
|
|
115
119
|
injectAgentsPrompt: fields.injectAgentsPrompt,
|
|
116
120
|
anchorFirstTurn: fields.anchorFirstTurn,
|
|
117
121
|
anchorText: fields.anchorText,
|
|
122
|
+
anchorCustom: fields.anchorCustom,
|
|
123
|
+
subagentFlash: fields.subagentFlash,
|
|
118
124
|
injectPrompt: fields.injectPrompt,
|
|
119
125
|
skillSwitches: { ...fields.skillSwitches },
|
|
120
126
|
writeAgents: fields.writeAgents,
|
|
121
127
|
writePreset: fields.writePreset
|
|
122
128
|
});
|
|
123
|
-
const switchesEqual = (a, b) => a.injectAgentsPrompt === b.injectAgentsPrompt && a.anchorFirstTurn === b.anchorFirstTurn && a.anchorText === b.anchorText && a.injectPrompt === b.injectPrompt && JSON.stringify(a.skillSwitches) === JSON.stringify(b.skillSwitches) && a.writeAgents === b.writeAgents && a.writePreset === b.writePreset;
|
|
129
|
+
const switchesEqual = (a, b) => a.injectAgentsPrompt === b.injectAgentsPrompt && a.anchorFirstTurn === b.anchorFirstTurn && a.anchorText === b.anchorText && a.anchorCustom === b.anchorCustom && a.subagentFlash === b.subagentFlash && a.injectPrompt === b.injectPrompt && JSON.stringify(a.skillSwitches) === JSON.stringify(b.skillSwitches) && a.writeAgents === b.writeAgents && a.writePreset === b.writePreset;
|
|
124
130
|
const asRecord = (value) => value !== null && typeof value === "object" ? value : {};
|
|
125
131
|
const readString = (source, key) => {
|
|
126
132
|
const value = source[key];
|
|
@@ -187,6 +193,9 @@ window.__ModuleLoader__.load({
|
|
|
187
193
|
const [agentsOpen, setAgentsOpen] = (0, react.useState)(false);
|
|
188
194
|
const [skillsOpen, setSkillsOpen] = (0, react.useState)(false);
|
|
189
195
|
const [presetOpen, setPresetOpen] = (0, react.useState)(false);
|
|
196
|
+
const [deepseekAvailable, setDeepseekAvailable] = (0, react.useState)(false);
|
|
197
|
+
const [deepseekProviders, setDeepseekProviders] = (0, react.useState)([]);
|
|
198
|
+
const [deepseekError, setDeepseekError] = (0, react.useState)("");
|
|
190
199
|
const [loaded, setLoaded] = (0, react.useState)(false);
|
|
191
200
|
const [fields, setFields] = (0, react.useState)(EMPTY);
|
|
192
201
|
const [savedPromptText, setSavedPromptText] = (0, react.useState)("");
|
|
@@ -214,6 +223,9 @@ window.__ModuleLoader__.load({
|
|
|
214
223
|
showNotice("error", "读取配置失败:" + (res.message ?? ""));
|
|
215
224
|
return;
|
|
216
225
|
}
|
|
226
|
+
setDeepseekAvailable(res.deepseekAvailable === true);
|
|
227
|
+
setDeepseekProviders(res.deepseekProviders ?? []);
|
|
228
|
+
setDeepseekError(res.deepseekError ?? "");
|
|
217
229
|
const ns = res.value;
|
|
218
230
|
const value = asRecord(ns.value);
|
|
219
231
|
const base = asRecord(ns.base);
|
|
@@ -225,6 +237,8 @@ window.__ModuleLoader__.load({
|
|
|
225
237
|
injectAgentsPrompt: readBoolean(value, "injectAgentsPrompt", readBoolean(base, "injectAgentsPrompt", false)),
|
|
226
238
|
anchorFirstTurn: readBoolean(value, "anchorFirstTurn", readBoolean(base, "anchorFirstTurn", false)),
|
|
227
239
|
anchorText: readString(value, "anchorText") ?? readString(base, "anchorText") ?? "",
|
|
240
|
+
anchorCustom: readBoolean(value, "anchorCustom", readBoolean(base, "anchorCustom", false)),
|
|
241
|
+
subagentFlash: readBoolean(value, "subagentFlash", readBoolean(base, "subagentFlash", false)),
|
|
228
242
|
injectPrompt: readBoolean(value, "injectPrompt", readBoolean(base, "injectPrompt", true)),
|
|
229
243
|
skillSwitches: value.skillSwitches !== void 0 || base.skillSwitches !== void 0 ? {
|
|
230
244
|
...readSkillSwitches(base, "skillSwitches"),
|
|
@@ -374,6 +388,16 @@ window.__ModuleLoader__.load({
|
|
|
374
388
|
path: ["anchorText"],
|
|
375
389
|
value: fieldsRef.current.anchorText
|
|
376
390
|
},
|
|
391
|
+
{
|
|
392
|
+
op: "set",
|
|
393
|
+
path: ["anchorCustom"],
|
|
394
|
+
value: fieldsRef.current.anchorCustom
|
|
395
|
+
},
|
|
396
|
+
{
|
|
397
|
+
op: "set",
|
|
398
|
+
path: ["subagentFlash"],
|
|
399
|
+
value: fieldsRef.current.subagentFlash
|
|
400
|
+
},
|
|
377
401
|
{
|
|
378
402
|
op: "set",
|
|
379
403
|
path: ["injectPrompt"],
|
|
@@ -396,6 +420,10 @@ window.__ModuleLoader__.load({
|
|
|
396
420
|
}
|
|
397
421
|
], void 0, () => setSavedSwitches(snapshotSwitches(fieldsRef.current)));
|
|
398
422
|
const toggle = (key) => {
|
|
423
|
+
if (key === "subagentFlash" && !deepseekAvailable) {
|
|
424
|
+
showNotice("error", "未检测到 DeepSeek 模型配置,子代理 Flash 开关不可用");
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
399
427
|
patch({ [key]: !fieldsRef.current[key] });
|
|
400
428
|
persistSwitches();
|
|
401
429
|
};
|
|
@@ -628,7 +656,7 @@ window.__ModuleLoader__.load({
|
|
|
628
656
|
}, skill.folder))
|
|
629
657
|
}),
|
|
630
658
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(CollapsibleSection, {
|
|
631
|
-
title: "
|
|
659
|
+
title: "锚定与 preset",
|
|
632
660
|
hint: presetSwitchDirty ? "未保存" : void 0,
|
|
633
661
|
open: presetOpen,
|
|
634
662
|
onToggle: () => setPresetOpen(!presetOpen),
|
|
@@ -643,10 +671,28 @@ window.__ModuleLoader__.load({
|
|
|
643
671
|
className: PromptEditor_module_css_default.rowText,
|
|
644
672
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
645
673
|
className: PromptEditor_module_css_default.rowName,
|
|
646
|
-
children: "
|
|
674
|
+
children: "启用锚定预设"
|
|
675
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
676
|
+
className: PromptEditor_module_css_default.rowDesc,
|
|
677
|
+
children: "总开关:开启时生成并刷新 ~/.dsh/.agent-presets/prompt-tool/,整套锚定预设才有载体;关闭时移除已生成的目录,下面锚定开关随之失效"
|
|
678
|
+
})]
|
|
679
|
+
})]
|
|
680
|
+
}),
|
|
681
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
682
|
+
className: PromptEditor_module_css_default.row,
|
|
683
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
684
|
+
type: "checkbox",
|
|
685
|
+
checked: fields.subagentFlash,
|
|
686
|
+
disabled: !fields.writePreset || !deepseekAvailable,
|
|
687
|
+
onChange: () => toggle("subagentFlash")
|
|
688
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
689
|
+
className: PromptEditor_module_css_default.rowText,
|
|
690
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
691
|
+
className: PromptEditor_module_css_default.rowName,
|
|
692
|
+
children: "子代理固定 Flash 模型"
|
|
647
693
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
648
694
|
className: PromptEditor_module_css_default.rowDesc,
|
|
649
|
-
children: "
|
|
695
|
+
children: deepseekAvailable ? "开启时采用 dsh-router-standard 的 Flash 子代理方案:固定 Flash 路由 + 任务分类人设 + 三锚;宿主直派子代理(含 dsh-mnemon)也会自动补 Flash 路由。关闭时继承主会话模型,工具目录全量放行" : `未检测到 DeepSeek 模型配置,此开关不可用。providers=[${deepseekProviders.join(", ") || "空"}]${deepseekError ? " error=" + deepseekError : ""}`
|
|
650
696
|
})]
|
|
651
697
|
})]
|
|
652
698
|
}),
|
|
@@ -661,10 +707,28 @@ window.__ModuleLoader__.load({
|
|
|
661
707
|
className: PromptEditor_module_css_default.rowText,
|
|
662
708
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
663
709
|
className: PromptEditor_module_css_default.rowName,
|
|
664
|
-
children: "
|
|
710
|
+
children: "追加任务引导"
|
|
711
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
712
|
+
className: PromptEditor_module_css_default.rowDesc,
|
|
713
|
+
children: "开启后在首条真实用户消息之后追加一句任务引导,不拆轮、不挪任务;内容按下方“使用自定义引导”开关选择"
|
|
714
|
+
})]
|
|
715
|
+
})]
|
|
716
|
+
}),
|
|
717
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
718
|
+
className: PromptEditor_module_css_default.row,
|
|
719
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
720
|
+
type: "checkbox",
|
|
721
|
+
checked: fields.anchorCustom,
|
|
722
|
+
disabled: !fields.writePreset || !fields.anchorFirstTurn,
|
|
723
|
+
onChange: () => toggle("anchorCustom")
|
|
724
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
725
|
+
className: PromptEditor_module_css_default.rowText,
|
|
726
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
727
|
+
className: PromptEditor_module_css_default.rowName,
|
|
728
|
+
children: "使用自定义引导"
|
|
665
729
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
666
730
|
className: PromptEditor_module_css_default.rowDesc,
|
|
667
|
-
children: "
|
|
731
|
+
children: "开启时使用下方文本作为引导;关闭时忽略下方文本,按任务自动选择 we/let 引导"
|
|
668
732
|
})]
|
|
669
733
|
})]
|
|
670
734
|
}),
|
|
@@ -674,15 +738,15 @@ window.__ModuleLoader__.load({
|
|
|
674
738
|
className: PromptEditor_module_css_default.rowText,
|
|
675
739
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
676
740
|
className: PromptEditor_module_css_default.rowName,
|
|
677
|
-
children: "
|
|
741
|
+
children: "自定义引导文本"
|
|
678
742
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
679
743
|
className: PromptEditor_module_css_default.rowDesc,
|
|
680
|
-
children: "
|
|
744
|
+
children: "仅在上方“使用自定义引导”开启时生效;关闭时自动文本优先"
|
|
681
745
|
})]
|
|
682
746
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
683
747
|
className: PromptEditor_module_css_default.anchorInput,
|
|
684
748
|
value: fields.anchorText,
|
|
685
|
-
disabled: !fields.writePreset || !fields.anchorFirstTurn,
|
|
749
|
+
disabled: !fields.writePreset || !fields.anchorFirstTurn || !fields.anchorCustom,
|
|
686
750
|
onChange: (e) => patch({ anchorText: e.target.value }),
|
|
687
751
|
onBlur: () => persistSwitches(),
|
|
688
752
|
spellCheck: false
|