dsh-tree-task-flow 0.3.13 → 0.3.15
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 +157 -91
- package/client.js +629 -512
- package/config.example.yml +13 -6
- package/cordis.patch.yml +5 -3
- package/lib/commands.js +91 -18
- package/lib/http.js +228 -47
- package/lib/index.js +24 -16
- package/lib/interrupt.js +18 -0
- package/lib/notes.js +173 -0
- package/lib/pause.js +84 -15
- package/lib/plan.js +48 -0
- package/lib/prompt.js +20 -4
- package/lib/region.js +375 -58
- package/lib/render.js +311 -0
- package/lib/requirement.js +914 -0
- package/lib/settings.js +53 -0
- package/lib/store.js +91 -7
- package/lib/tools.js +602 -111
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
# dsh-tree-task-flow · 树形任务流
|
|
2
2
|
|
|
3
|
-
给 DeepSeek Harness
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
给 DeepSeek Harness 的**上下文管理**插件:把用户在这个会话里提的要求记成**需求**,
|
|
4
|
+
需求下面挂**任务**与**步骤**;**完成[步骤/任务/需求]并折叠过程**——模型提交结果,
|
|
5
|
+
插件随即把这段执行过程从上下文里折叠掉,只留下那条结果。
|
|
6
|
+
|
|
7
|
+
**这不是项目管理。** 需求记录的是"用户在这个会话里要什么",不是"项目长什么样"——
|
|
8
|
+
一条需求可以对应毫无关联的目录,需求列表也不跨会话。模型定义见
|
|
9
|
+
[`docs/09-需求与任务模型.md`](docs/09-需求与任务模型.md)。
|
|
6
10
|
|
|
7
11
|
**安装即启用**:`dsh plugin add` 之后就生效,不需要再改任何配置。
|
|
8
12
|
不想用的时候,在 profile 里写一句 `enabled: false` 就能关掉,关掉后一个字节都不碰会话。
|
|
@@ -19,37 +23,41 @@
|
|
|
19
23
|
|
|
20
24
|
| | 内容 | 去向 |
|
|
21
25
|
|---|---|---|
|
|
22
|
-
| 过程 |
|
|
26
|
+
| 过程 | 读文件、试错、命令输出、以及**已经写进需求的用户输入** | 节点完成时**整段折叠掉** |
|
|
23
27
|
| 结果 | 模型在 `tree_task_done` 里提交的 `result` | 留下来,供后续节点引用 |
|
|
28
|
+
| 笔记 | 跟工作有关、但不属于任何一条需求的事实与偏好 | 跟会话走,折叠时随通告带出去 |
|
|
24
29
|
|
|
25
30
|
## 折叠按什么切
|
|
26
31
|
|
|
27
|
-
|
|
32
|
+
规则只看表层,与计划树无关(计划树只用来认出"这次完成的是不是一条需求"):
|
|
28
33
|
|
|
29
34
|
```
|
|
30
|
-
|
|
31
|
-
→
|
|
35
|
+
tree_task_start → 收「上一次折叠成功之后」到这次调用之前
|
|
36
|
+
tree_task_done → 收「上一个 done 或 start 之后」到这次调用之前(尚未 start 时退到 create)
|
|
37
|
+
done 完成的是需求 → 收「这条需求开工那次 create 之后」到这次调用之前(全部)
|
|
32
38
|
```
|
|
33
39
|
|
|
34
|
-
|
|
35
|
-
会话里还没有过 `tree_task_done` 时,就是表层第一条 `tree_task_create`;
|
|
36
|
-
区间里一次 `tree_task_create` 都没有时,回退到上一次 `tree_task_done` 之后。
|
|
40
|
+
边界只有三个**工具名**:`create` / `start` / `done`,按名字认、不看实参。
|
|
37
41
|
**`tree_task_plan` 不是边界**——它的调用与返回跟普通过程一样,随这一段一起收走。
|
|
38
|
-
|
|
39
|
-
同样留着(模型靠它们看"计划是什么、下一步干什么")。
|
|
42
|
+
边界调用本身留在上下文里;触发这一次的 `done` / `start` 的调用与返回同样留着。
|
|
40
43
|
折叠只收它们**之间**的过程,换成一条计数通告:
|
|
41
44
|
|
|
42
45
|
```
|
|
43
|
-
[tree_task_create 调用] [
|
|
44
|
-
[
|
|
45
|
-
[
|
|
46
|
+
[tree_task_create 调用] [返回:草稿编号]
|
|
47
|
+
[tree_task_start 调用] [返回:需求详情]
|
|
48
|
+
[tree_task消息:隐藏了 4 条过程上下文。读取:… 写入:…]
|
|
49
|
+
[tree_task_done 调用] [返回:接下来需要进行任务:「二」(t-4)。]
|
|
46
50
|
```
|
|
47
51
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
**为什么 `start` 认「上次折叠成功」而不是「上一个边界」**:折叠会被"用户的话还没写进
|
|
53
|
+
需求"挡住;挡掉的那一段如果只按边界算,下一条边界一出现它就永远落在区间外——挡一次
|
|
54
|
+
就永久丢一段上下文。插件给每个会话记一个"折到哪儿了"的游标,`start` 从那里补折。
|
|
55
|
+
`done` 反过来只认上一个边界:它收的就是前面这一小节,用游标会把早就收过的内容再卷一遍。
|
|
56
|
+
|
|
57
|
+
> **`tree_task_create` / `tree_task_start` / `tree_task_done` 不能合并成一个工具。**
|
|
58
|
+
> 边界是"上一次调用之后"这种位置判定,而 `plan` 每补一次步骤就调一次;并成一个工具之后,
|
|
59
|
+
> 每次补步骤都会把边界往后推,中间那段过程就永远收不走。靠"实参里有没有 `parentId`"
|
|
60
|
+
> 去区分,也只是把认错边界的机会交给模型——写漏一个字段,边界就悄悄挪走,还不报错。
|
|
53
61
|
|
|
54
62
|
两条硬约束:
|
|
55
63
|
|
|
@@ -59,7 +67,8 @@
|
|
|
59
67
|
不追加、不留空消息。
|
|
60
68
|
|
|
61
69
|
每一次 `tree_task_done` 的调用与它的返回都**留在上下文里**,一轮轮累积;
|
|
62
|
-
模型下一轮还看得到"我刚做完了什么、接下来干什么"
|
|
70
|
+
模型下一轮还看得到"我刚做完了什么、接下来干什么"。`tree_task_start` 的调用与返回
|
|
71
|
+
也留着——它的返回就是需求详情,是"这条需求要做什么"的最近一份摘要。
|
|
63
72
|
|
|
64
73
|
折叠发生在 `agent/pre-step`——上一轮已结束、下一个请求还没构造的那一刻。
|
|
65
74
|
工具执行中途不能折叠,那时 surface 还在增长,替换会把自己卷进去。
|
|
@@ -105,54 +114,59 @@ tree_task消息:接下来需要进行步骤:「步骤二」(s-4)。
|
|
|
105
114
|
但插件**不会拦住任何工具**——"这一层到底做完了没有"由模型判断,插件既不替它定死,
|
|
106
115
|
也不靠拒绝别的工具把它逼到墙角。
|
|
107
116
|
|
|
108
|
-
##
|
|
117
|
+
## 十个工具
|
|
109
118
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
`
|
|
119
|
+
**边界必须各有专门的名字,不是可以合并的重复。** `tree_task_create` / `tree_task_start` /
|
|
120
|
+
`tree_task_done` 是任务流的三个位置标记:`create` 是"记下这件事"(本身不折叠任何东西),
|
|
121
|
+
`start` 是"开工"(收走上一次 `done` 之后的过程),`done` 是"收工"(折叠就发生在这里)。
|
|
122
|
+
它们各自只在特定时刻调一次,`plan` 却在任务中途反复调用——并成一个工具,
|
|
123
|
+
折叠边界就只能靠实参去猜了(见上一节)。
|
|
113
124
|
|
|
114
125
|
| 工具 | 用途 |
|
|
115
126
|
|---|---|
|
|
116
|
-
| `tree_task_status` |
|
|
117
|
-
| `tree_task_create` |
|
|
118
|
-
| `
|
|
119
|
-
| `
|
|
120
|
-
| `
|
|
121
|
-
| `
|
|
122
|
-
|
|
123
|
-
|
|
127
|
+
| `tree_task_status` | **开工第一步先调它**:需求列表不常驻上下文。不填参数按「活跃 → 已归档 → 草稿」逐条列出,并展开当前那一条;填 `ids` 一次查多条全貌;`include` 选简介 / 版本历史 / 任务结果;`match` 按关键词找 |
|
|
128
|
+
| `tree_task_create` | 把用户提出的一件事记成**需求草稿**(标题 ≤50 字、简介 ≤200 字、详情不限长)。草稿不算真需求,不进活跃列表;草稿阶段用 `tree_task_requirement` 的 `update` 逐次补充正文,确认时用 `confirm` 生成版本 |
|
|
129
|
+
| `tree_task_requirement` | 需求的写操作:`confirm` 确认草稿并生成版本(第一次 v1,之后每次 +1,`title` 可不传)/ `update` 部分更新正文,只改给出的字段,更新后需求回到草稿,可多次调用 / `confirmChange` 确认用户提交的暂定版本 / `question` 有歧义退回 / `archive`、`unarchive`(可批量,给 `ids`)/ `prerequisites` 设前置(`id` 被设置者,`ids` 前置编号,整体替换) |
|
|
130
|
+
| `tree_task_start` | **开工**:把上一次折叠成功之后的过程收走,返回这条需求的详情。草稿要先确认;已完成的不能再开工。**调用前先读完所需的文件与文档** |
|
|
131
|
+
| `tree_task_plan` | 给一个节点追加子节点:给需求加任务,给任务加步骤。**建新需求不归它管**;**读资料不算任务**——那是开工前就该掌握的信息 |
|
|
132
|
+
| `tree_task_done` | **完成步骤、任务或需求,并折叠它的过程**:每完成一个步骤调用一次,多个节点完成时分别调用。`result` 必填,缺了直接拒;完成需求时它就是**总结**。这一次调用连同返回留在上下文里,被收走的是它前面那段执行过程 |
|
|
133
|
+
| `tree_task_update` | 改**任务或步骤**的标题与说明(改需求正文要走 `tree_task_requirement`,因为要留版本历史) |
|
|
134
|
+
| `tree_task_drop` | **放弃**:留个记号说「这件事不做了」,节点**留在树里**可查(划掉)。放弃需求会连同没做完的任务一起放弃,完成过的保持原样。可批量:给 `ids`,被父节点带走的子节点自动跳过 |
|
|
135
|
+
| `tree_task_delete` | **删除**:把它连同下面的东西**摘掉**、不留痕,**不看状态**。清理写错 / 建重 / 结果记错的内容用它。可批量:给 `ids` |
|
|
136
|
+
| `tree_task_note` | 笔记:给 `key` 与 `text` 就是写(当场返回,同名覆盖、修订号 +1);要查就只给 `query`,什么都不给就是全部 |
|
|
137
|
+
|
|
138
|
+
**放弃与删除是两件事**:放弃回答"这件事还要不要做"(历史留着),删除是"这条内容本身就是错的"
|
|
139
|
+
(凭空摘掉)。一个节点做完之后再想让它消失,只能用删除。
|
|
140
|
+
|
|
141
|
+
层级固定三级,步骤是最低一级,不能再往下拆。
|
|
124
142
|
|
|
125
143
|
**返回的三条规矩:**
|
|
126
144
|
|
|
127
|
-
-
|
|
128
|
-
-
|
|
129
|
-
复制出去能正常预览,不会被当成代码块;
|
|
145
|
+
- 写树类工具只返回**本次动到的那个需求**,不再每次倾倒整份列表;
|
|
146
|
+
- 列表与树用**规范的 Markdown** 渲染,复制出去能正常预览,不会被当成代码块;
|
|
130
147
|
- **结果全文给出,一个字都不截**。
|
|
131
148
|
|
|
132
149
|
```markdown
|
|
133
|
-
- [
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
- [
|
|
137
|
-
- **结果**:交付物 android\settings.gradle;`cd android; powershell -File tools\build.ps1` 冷构建成功。
|
|
138
|
-
- [ ] **子任务** `s-mv50h48v5` 写 build.gradle ← 当前
|
|
139
|
-
- [ ] **目标** `g-mv50h48v6` 安卓端来源 ← 当前
|
|
140
|
-
- [ ] **任务** `t-mv50h48v7` 采集层
|
|
150
|
+
- [ ] **R1** · 未完成 把菜单改成深色 ← 当前
|
|
151
|
+
菜单太亮,改成深色
|
|
152
|
+
- [x] 任务一
|
|
153
|
+
- [ ] 任务二
|
|
141
154
|
```
|
|
142
155
|
|
|
143
156
|
### 三层怎么分
|
|
144
157
|
|
|
145
158
|
| 层 | 是什么 | 怎么算分对了 |
|
|
146
159
|
|---|---|---|
|
|
147
|
-
|
|
|
148
|
-
|
|
|
149
|
-
|
|
|
160
|
+
| **需求** | 用户在这个会话里要什么 | 标题一句话(≤50 字)、简介一段(≤200 字)、详情不限长;由 AI 与用户沟通后确认 |
|
|
161
|
+
| **任务** | **交付节点** | 一件能独立验收的交付内容——一个文件、一条能跑的命令、一份结论,也可以是一个检查点 |
|
|
162
|
+
| **步骤** | 任务内部的一下 | 一两次工具调用能做完的事 |
|
|
150
163
|
|
|
151
|
-
**折叠次数跟着 `tree_task_done`
|
|
152
|
-
|
|
164
|
+
**折叠次数跟着 `tree_task_done` 的次数走**:每完成一个任务折一次;完成需求时把它整条收成一条。
|
|
165
|
+
所以任务别拆得太碎——够厚,done 的次数少,上下文前缀变动的次数也少。
|
|
153
166
|
|
|
154
167
|
`result` 分两层写:任务的 result 写**交付物 + 怎么验收**(文件在哪、怎么跑、验出什么、
|
|
155
|
-
|
|
168
|
+
已知限制),步骤的 result 一句话说清这步做了什么就够;**需求的 result 就是它的总结**,
|
|
169
|
+
别的需求靠它快速查阅。
|
|
156
170
|
|
|
157
171
|
## 安装
|
|
158
172
|
|
|
@@ -206,37 +220,40 @@ dsh --profile web --dump-config # 输出里应出现 task-tree 这一
|
|
|
206
220
|
外观照内置条目做——用的是同一套 UI 基座(`@deepseek-ai/dsh-client-ui-primitives`
|
|
207
221
|
的图标、Tooltip 与 CSS 变量),所以它看起来就是内置的一部分:
|
|
208
222
|
|
|
209
|
-
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
-
|
|
222
|
-
|
|
223
|
-
|
|
223
|
+
- **收起时**是一条 36px 的单行条:左边清单图标,中间「状态 + 当前需求标题 + 进度」,
|
|
224
|
+
右边两个按钮——**暂停 / 继续**与展开。状态三种:进行中 / 已暂停 / 待开始;
|
|
225
|
+
**没有进行中的需求时照最近的那一条显**(标题与它自己的状态,多半是「已完成」),
|
|
226
|
+
不拿「待开始」去描述一条已经做完的需求。
|
|
227
|
+
- **展开后**是需求面板,分三段:
|
|
228
|
+
- **活跃需求**:一行一条(状态、编号、标题、简介、进度),当前进行中的那条打「当前」;
|
|
229
|
+
- **待确认**:还没跟 AI 沟通确认的草稿,不占上下文;
|
|
230
|
+
- **已归档**:用户归档掉的需求,同样一行一条,可随时取消归档;
|
|
231
|
+
- 每行三个动作:**开始**(叫醒 AI 去做这条)、**归档 / 取消归档**、**展开看详情**。
|
|
232
|
+
- **点开一条**看只读详情:简介、详情全文、缺哪个前置、待确认变动、任务与步骤、总结。
|
|
233
|
+
点「改需求」进编辑态:标题、简介、详情三个输入框 + 「确认变更」。
|
|
234
|
+
**提交之后只是暂定版本**,AI 确认之前仍按旧版本走。
|
|
235
|
+
- **归档有一个刻意的延迟**:点了之后这一行**不动**,按钮变成「取消归档」,反悔点一下就回去了;
|
|
236
|
+
下次打开面板才按新状态重新分列表。防误点优先于即时一致。
|
|
237
|
+
- 数据每 4 秒自动拉一次,模型在后台改需求时界面会自己跟上。
|
|
238
|
+
|
|
239
|
+
**一条需求都没有的会话一个像素都不占**——面板直接返回 `null`,不会平白挤掉内置的
|
|
224
240
|
待办与目标条目。
|
|
225
241
|
|
|
226
|
-
开关不在界面上,在 profile 的 `cordis.patch.yml` 里(见上面的「关闭」一节)。
|
|
227
|
-
|
|
228
242
|
## 命令
|
|
229
243
|
|
|
230
244
|
`/task-tree` **不经过模型**,直接执行:
|
|
231
245
|
|
|
232
246
|
| 命令 | 作用 |
|
|
233
247
|
|---|---|
|
|
234
|
-
| `/task-tree` |
|
|
235
|
-
| `/task-tree done <id> <结果>` |
|
|
236
|
-
| `/task-tree drop <id>` |
|
|
248
|
+
| `/task-tree` | 查看本会话的需求列表与当前进度 |
|
|
249
|
+
| `/task-tree done <id> <结果>` | 提交某个节点(需求 / 任务 / 步骤)的结果并完成它 |
|
|
250
|
+
| `/task-tree drop <id>` | 放弃:留着可查,标记为不做了 |
|
|
251
|
+
| `/task-tree delete <id>` | 删除:连下面的一起摘掉,不看状态 |
|
|
237
252
|
| `/task-tree pause` | 暂停:正在跑的工具跑完就停住,不再往下推进 |
|
|
238
253
|
| `/task-tree resume` | 继续:从停住的地方接着跑,不往会话里插消息 |
|
|
239
|
-
| `/task-tree reset` |
|
|
254
|
+
| `/task-tree reset` | 清掉本会话的计划(需求、任务全没) |
|
|
255
|
+
|
|
256
|
+
开关不在界面上,在 profile 的 `cordis.patch.yml` 里(见上面的「关闭」一节)。
|
|
240
257
|
|
|
241
258
|
## 配置
|
|
242
259
|
|
|
@@ -245,13 +262,35 @@ dsh --profile web --dump-config # 输出里应出现 task-tree 这一
|
|
|
245
262
|
| 字段 | 默认 | 说明 |
|
|
246
263
|
|---|---|---|
|
|
247
264
|
| `enabled` | `true` | 总开关;**装上即启用**,写 `false` 关掉 |
|
|
248
|
-
| `autoContinue` | `
|
|
265
|
+
| `autoContinue` | `false` | 模型停下时是否自动续行(见下节;**在插件管理里本插件那一页能改**) |
|
|
249
266
|
| `maxAutoRounds` | `5` | 连续自动续行的轮次上限 |
|
|
250
|
-
| `interruptRecovery` | `true` |
|
|
267
|
+
| `interruptRecovery` | `true` | 意外中断后是否自动拉起(见下节;**在插件管理里本插件那一页能改**) |
|
|
251
268
|
| `interruptDelaysMs` | `null` | 网络类中断的拉起时刻,`null` = 1/5/10/30 分钟 |
|
|
252
269
|
| `promptOrder` | `1800` | 工具说明段落的排序 |
|
|
253
270
|
| `rootDir` | `null` | 状态目录,默认 `$DSH_HOME/dsh-task-tree` |
|
|
254
271
|
|
|
272
|
+
## 设置
|
|
273
|
+
|
|
274
|
+
设置**在插件管理里、这个插件自己的那一页**:打开侧边栏的「插件」页,在「已安装」里点
|
|
275
|
+
`dsh-tree-task-flow` 这张卡,页面上描述下面就是这两个开关。**改完立刻生效,不用重启。**
|
|
276
|
+
|
|
277
|
+
> 它不在 DSH 的设置面板里,也不在任务条上。设置属于这个插件,就该长在插件自己身上;
|
|
278
|
+
> 任务条只干两件事:看进度、按暂停 / 继续。
|
|
279
|
+
|
|
280
|
+
| 设置 | 默认 | 做什么 |
|
|
281
|
+
|---|---|---|
|
|
282
|
+
| 自动续行 | **关** | 模型自己停下、计划树还没跑完时,要不要推一条"接下来做 X"把它唤醒 |
|
|
283
|
+
| 工具出错自动拉起 | 开 | 这一轮不是正常结束(网络断了 / 模型输出坏了 / 工具结果没了)时,要不要自动重来 |
|
|
284
|
+
|
|
285
|
+
两项是**两件事**,别混:前者是"要不要往前推",后者是"要不要救"。默认这么定是因为
|
|
286
|
+
自动续行会在你没看着的时候自己往下跑,该由人来点;而中断拉起只在"这一轮根本不是正常
|
|
287
|
+
结束"时动手,正常停下它一步都不动。
|
|
288
|
+
|
|
289
|
+
设置写在状态目录的 `settings.json` 里(**不按会话分**,整个插件一份),重启后还在。
|
|
290
|
+
优先级是 **在插件页里改过的 > profile 里的 config > `DEFAULT_CONFIG`**:在页里点过就以
|
|
291
|
+
页为准,免得界面对不上 YAML。`enabled`、`maxAutoRounds`、`interruptDelaysMs` 这类
|
|
292
|
+
"装插件时就该定好"的项不在开关名单里,仍然只认 profile 配置。
|
|
293
|
+
|
|
255
294
|
## 意外中断自动拉起
|
|
256
295
|
|
|
257
296
|
上一节 `autoContinue` 管的是"模型自己正常停下"。这一节管的是**这一轮没能正常
|
|
@@ -287,6 +326,8 @@ dsh --profile web --dump-config # 输出里应出现 task-tree 这一
|
|
|
287
326
|
自己改道,本来也没中断这一轮。
|
|
288
327
|
- 只在**这个会话的计划树还没走完**时才动手。等待时刻写在状态目录的 `revive/` 下,
|
|
289
328
|
重启 `dsh web` 不会丢。
|
|
329
|
+
- **能在插件页里关掉。** 插件管理里本插件那一页的"工具出错自动拉起"就是
|
|
330
|
+
这个开关,改完立刻生效(关掉之后插件连 `revive/` 都不再写)。
|
|
290
331
|
|
|
291
332
|
## 暂停与继续
|
|
292
333
|
|
|
@@ -300,10 +341,23 @@ dsh --profile web --dump-config # 输出里应出现 task-tree 这一
|
|
|
300
341
|
接着请求,同样**零新增消息**。任务树的进度停在哪儿,就从哪儿接着跑。
|
|
301
342
|
|
|
302
343
|
**重启 `dsh web` 之后暂停依然有效。** "被按住"这件事写在状态目录的 `held/` 下,
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
344
|
+
重启后条目仍显示「已暂停」,点「继续」即可接着跑。
|
|
345
|
+
|
|
346
|
+
**点「继续」是无条件的。** 不管此刻闸门有没有挂在岔口上、会话是不是正忙,点一下,
|
|
347
|
+
"被按住"就当场解除——它是一句"接着跑",不是一次"此刻有没有闸门"的查询。区别只在
|
|
348
|
+
插件接下来能做什么:
|
|
349
|
+
|
|
350
|
+
- **闸门正挂在岔口上** → 直接放行那一步,**零新增消息**;
|
|
351
|
+
- **没有岔口可放**(进程重启过,或者你点的时候那个工具还在跑)→ 退一步给会话排一条
|
|
352
|
+
「恢复续行」的消息把它从 `idle` 推起来;会话正忙的话连推都不用推,它自己会在下一个
|
|
353
|
+
岔口接着跑;
|
|
354
|
+
- **那个会话还没被 DSH 加载成实时 agent** → 提示你先打开它或在其中发一条消息,
|
|
355
|
+
但"被按住"照样解除。
|
|
356
|
+
|
|
357
|
+
> 早先不是这样:"继续"只在闸门恰好挂着的那一瞬间才算数;没有闸门可放时又要求会话
|
|
358
|
+
> 正好停在 `idle`,忙就**直接拒绝、并且什么都不清**。于是"工具还在跑的时候点的那一下"
|
|
359
|
+
> 被静默吞掉,等闸门真挂上时已经没人在等它——会话就停在原地了。真回归见
|
|
360
|
+
> `verify-pause.mjs` 的场景 s-31。
|
|
307
361
|
|
|
308
362
|
闸门开在 agent 的 `agent/pre-step` 上——一个 step 走完、工具结果都已落盘、模型还没
|
|
309
363
|
发起下一次请求的那一刻。这是唯一同时满足"不打断工具"和"不留痕迹"的位置:再晚一点
|
|
@@ -320,8 +374,8 @@ dsh --profile web --dump-config # 输出里应出现 task-tree 这一
|
|
|
320
374
|
**模型自己停下、计划树却没跑完,插件就推一条"接下来要做 X"把它唤醒。** 这只是**兜底**:
|
|
321
375
|
`tree_task_done` 的返回文本里已经带了"请继续执行下一个子任务",模型通常会在同一轮里接着做。
|
|
322
376
|
|
|
323
|
-
`autoContinue`
|
|
324
|
-
|
|
377
|
+
`autoContinue` **默认关闭**——它会自己往下跑,所以默认由人来点。要开就在插件管理里
|
|
378
|
+
本插件那一页打开(**改完立刻生效**,不用重启),或者在 profile 里写 `autoContinue: true`。
|
|
325
379
|
|
|
326
380
|
开着也不会脱缰,有四道闸门:
|
|
327
381
|
|
|
@@ -344,16 +398,21 @@ dsh --profile web --dump-config # 输出里应出现 task-tree 这一
|
|
|
344
398
|
|
|
345
399
|
## 状态文件
|
|
346
400
|
|
|
347
|
-
全部在 `$DSH_HOME/dsh-task-tree/`
|
|
401
|
+
全部在 `$DSH_HOME/dsh-task-tree/` 下。除 `settings.json` 外都**以 `sessionId` 为键**:
|
|
348
402
|
|
|
349
403
|
| 文件 | 内容 |
|
|
350
404
|
|---|---|
|
|
351
|
-
| `plans/<sessionId>.json` |
|
|
405
|
+
| `plans/<sessionId>.json` | 需求与任务(每个会话一份,需求住在里面的 `goals` 键上——历史键名) |
|
|
406
|
+
| `notes/<sessionId>.json` | 笔记(跟会话走,不跨会话带) |
|
|
352
407
|
| `surfaces/<sessionId>.json` | 三层的进度游标 `{ key, cursor }`(只给界面看,不参与折叠) |
|
|
353
408
|
| `held/<sessionId>.json` | 暂停 / 停止状态(跨重启保留) |
|
|
354
409
|
| `revive/<sessionId>.json` | 意外中断的拉起时刻表(跨重启保留) |
|
|
410
|
+
| `settings.json` | 在插件页里改过的设置(**整个插件一份,不按会话分**) |
|
|
355
411
|
|
|
356
412
|
> 目录名沿用插件改名前的标识,为的是不让既有的计划文件失联;插件名与它无关。
|
|
413
|
+
>
|
|
414
|
+
> 旧版的文件里没有需求那一层的字段(`versions` / `archived` / `prerequisites` 等)。
|
|
415
|
+
> 读的时候**在内存里补齐**,不改写磁盘上的老文件——老会话照常能读。
|
|
357
416
|
|
|
358
417
|
计划属于建立它的那个会话。放到会话无关的位置,任何一个会话的计划都会被
|
|
359
418
|
所有会话读到——那等于把不相干的节点指派塞进别人的上下文。
|
|
@@ -367,29 +426,36 @@ dsh --profile web --dump-config # 输出里应出现 task-tree 这一
|
|
|
367
426
|
空 `result` 会被拒绝。所以要写清"产出了什么",写成能独立看懂的样子——
|
|
368
427
|
过程会丢,别把过程写进去。
|
|
369
428
|
|
|
370
|
-
2.
|
|
371
|
-
`
|
|
372
|
-
|
|
373
|
-
|
|
429
|
+
2. **每完成一个步骤就报一次完成,不要合并。** 折叠只发生在完成的那一刻:四个任务全部做完
|
|
430
|
+
再连续补四次 `done`,中间那两百多条过程会一直留在上下文里。实测过一轮对照——合并补报
|
|
431
|
+
的会话,每步平均输入 174.7k token,不用插件的对照组是 167.0k,插件反而更贵。
|
|
432
|
+
这条插件无法代替模型决定,所以写进了系统提示词与工具说明里。
|
|
433
|
+
|
|
434
|
+
3. **折叠只看表层。** `start` 从上次折叠成功的位置起折,`done` 从上一个
|
|
435
|
+
`done` 或 `start` 之后折(尚未 start 时退到 `create`),完成需求时折整条;`tree_task_plan` 不是边界,
|
|
436
|
+
它的调用与返回跟过程一样会被收走。区间里没有过程时什么都不注入,夹着你的消息时
|
|
437
|
+
整段不折——那一段原样留着(往前折丢需求、往后折丢回应),代价是上下文不收缩;
|
|
438
|
+
下一次 `start` 会把它补折回来。
|
|
374
439
|
|
|
375
|
-
|
|
440
|
+
4. **模型看到的工具说明不随计划变化,也不复述工具清单。** 那一段只讲什么时候用
|
|
376
441
|
这组工具、完成时守什么规矩;每个工具的用法由它自己的 `description` 承担。
|
|
377
442
|
要了解计划就让模型调 `tree_task_status`。
|
|
378
443
|
|
|
379
|
-
|
|
444
|
+
5. **折叠几次,界面就多几张「系统提示词」卡片,但上下文里的系统提示词始终只有一条。**
|
|
380
445
|
DSH 把"上下文被替换过"记成一次请求序列的边界(下一次请求带 `reason=series`),
|
|
381
446
|
界面在 `reason` 不是 `change` 的请求上都会画一张系统提示词卡片;锚点跟着那一轮 step 走,
|
|
382
447
|
卡片于是一张张堆起来。**上下文里 `system/message` 自始至终只有一条**,折叠没有伪造
|
|
383
448
|
任何系统消息。已实测:3 次折叠 → 3 次 `series` → 界面 3 张卡片。
|
|
384
449
|
|
|
385
|
-
|
|
450
|
+
6. **改需求用「丢弃 + 追加」,不要重建整棵树。** 丢掉的节点留在树里可查,
|
|
386
451
|
它和完成的节点会一起被那一段折叠收走(通告只报条数,不区分完成还是丢弃)。
|
|
452
|
+
**内容写错了才用删除**——删除是摘掉,摘掉的东西查不回来,也没有任何通告替它留痕。
|
|
387
453
|
|
|
388
|
-
|
|
454
|
+
7. **暂停不留痕迹。** 暂停后模型看到的是"没有下一条请求",看不到任何"你被暂停了"
|
|
389
455
|
之类的提示;继续之后也不会有"继续"消息进上下文。想让模型知道中间发生过什么,
|
|
390
456
|
得自己发消息说。
|
|
391
457
|
|
|
392
|
-
|
|
458
|
+
8. **内置压缩之后会有一条提醒。** DSH 自己的压缩把一大段历史收成一条检查点之后,
|
|
393
459
|
如果这个会话里有计划树,插件会注入一条
|
|
394
460
|
`tree_task消息:上下文刚被压缩过,计划树没有被压缩。用 tree_task_status 取回当前进度…`。
|
|
395
461
|
计划树本身不在压缩范围内——它存在磁盘上;但模型会忘掉它,所以补这一句。
|
|
@@ -400,7 +466,7 @@ dsh --profile web --dump-config # 输出里应出现 task-tree 这一
|
|
|
400
466
|
| 不做 | 原因 |
|
|
401
467
|
|---|---|
|
|
402
468
|
| 资料 / 文件快照 / 记忆 | 上下文里值得留下的只有结果,其余靠模型自己重读 |
|
|
403
|
-
| 文件回退 / 撤销 | 改需求用「丢弃 +
|
|
469
|
+
| 文件回退 / 撤销 | 改需求用「丢弃 + 追加」;内容本身写错了才用删除摘掉,摘掉就找不回来 |
|
|
404
470
|
| 并行推进多个目标 | 结构上支持一个会话有多个目标(目标层就是兄弟列表),但同一时刻只沿一条活动路径走 |
|
|
405
471
|
| 把计划内容注入提示词 | 计划状态由 `tree_task_status` 现取,提示词里只放不随计划变化的说明 |
|
|
406
472
|
|