@oyasmi/pipiclaw 0.3.4 → 0.4.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/CHANGELOG.md +3 -0
- package/LICENSE +184 -0
- package/README.md +230 -231
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +2 -19
- package/dist/agent.js.map +1 -1
- package/dist/command-extension.d.ts.map +1 -1
- package/dist/command-extension.js.map +1 -1
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js.map +1 -1
- package/dist/config-loader.d.ts.map +1 -1
- package/dist/config-loader.js.map +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +0 -2
- package/dist/context.js.map +1 -1
- package/dist/delivery.d.ts.map +1 -1
- package/dist/delivery.js +11 -14
- package/dist/delivery.js.map +1 -1
- package/dist/dingtalk.d.ts.map +1 -1
- package/dist/dingtalk.js +26 -26
- package/dist/dingtalk.js.map +1 -1
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +5 -8
- package/dist/events.js.map +1 -1
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/log.d.ts.map +1 -1
- package/dist/log.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js.map +1 -1
- package/dist/memory-consolidation.d.ts.map +1 -1
- package/dist/memory-consolidation.js.map +1 -1
- package/dist/memory-files.d.ts.map +1 -1
- package/dist/memory-files.js.map +1 -1
- package/dist/memory-lifecycle.d.ts.map +1 -1
- package/dist/memory-lifecycle.js +1 -2
- package/dist/memory-lifecycle.js.map +1 -1
- package/dist/model-utils.d.ts.map +1 -1
- package/dist/model-utils.js.map +1 -1
- package/dist/paths.d.ts.map +1 -1
- package/dist/prompt-builder.d.ts.map +1 -1
- package/dist/prompt-builder.js.map +1 -1
- package/dist/sandbox.d.ts.map +1 -1
- package/dist/sandbox.js +0 -1
- package/dist/sandbox.js.map +1 -1
- package/dist/shell-escape.d.ts.map +1 -1
- package/dist/shell-escape.js.map +1 -1
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +2 -3
- package/dist/store.js.map +1 -1
- package/dist/sub-agents.d.ts.map +1 -1
- package/dist/sub-agents.js +42 -10
- package/dist/sub-agents.js.map +1 -1
- package/dist/tools/attach.d.ts.map +1 -1
- package/dist/tools/attach.js.map +1 -1
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/read.d.ts.map +1 -1
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/subagent.d.ts.map +1 -1
- package/dist/tools/subagent.js.map +1 -1
- package/dist/tools/truncate.d.ts.map +1 -1
- package/dist/tools/truncate.js.map +1 -1
- package/dist/tools/write-content.d.ts.map +1 -1
- package/dist/tools/write-content.js.map +1 -1
- package/dist/tools/write.d.ts.map +1 -1
- package/dist/tools/write.js.map +1 -1
- package/docs/memory-rfc.md +291 -0
- package/docs/subagent/pi-subagent-analyse.txt +190 -0
- package/docs/subagent/pi-subagent-design.txt +266 -0
- package/docs/subagent/pi-subagent-phase1-plan.txt +529 -0
- package/package.json +69 -53
|
@@ -0,0 +1,529 @@
|
|
|
1
|
+
Pipiclaw Sub-Agent Phase 1 修改方案
|
|
2
|
+
|
|
3
|
+
目标
|
|
4
|
+
|
|
5
|
+
在 pipiclaw 中引入可由主 Agent 自主决定是否调用的 sub-agent 能力,用来把重计算、重文件操作、
|
|
6
|
+
专项审查之类的子任务卸载到独立 context 中执行。
|
|
7
|
+
|
|
8
|
+
Phase 1 的目标不是做完整 multi-agent 编排,而是在现有工具体系里增加一个可靠、可控、可观测的
|
|
9
|
+
`subagent` tool。
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
一、范围收敛
|
|
14
|
+
|
|
15
|
+
Phase 1 只做这些事情:
|
|
16
|
+
|
|
17
|
+
1. 提供单个 `subagent` tool
|
|
18
|
+
- 只支持 single 模式
|
|
19
|
+
- schema 形态为 `{ label, agent, task }`
|
|
20
|
+
|
|
21
|
+
2. sub-agent 的调用时机由主 Agent 自主判断
|
|
22
|
+
- 不要求用户手工指定“现在用 subagent”
|
|
23
|
+
- 通过 system prompt 中的规则说明,让主 Agent 在合适时自行调用 `subagent`
|
|
24
|
+
|
|
25
|
+
3. 预定义 sub-agent 定义目录为:
|
|
26
|
+
- `workspaceDir/sub-agents/*.md`
|
|
27
|
+
- 对 pipiclaw 默认 workspace 来说,就是 `~/.pi/pipiclaw/workspace/sub-agents/*.md`
|
|
28
|
+
|
|
29
|
+
4. 主 Agent 在需要时也可以临时内联定义一个 sub-agent
|
|
30
|
+
- 不必预先写到 `sub-agents/` 目录里
|
|
31
|
+
- 只要给出足够的 system prompt、工具、模型和预算参数,就可以实例化一个临时 sub-agent
|
|
32
|
+
|
|
33
|
+
5. 每个 sub-agent 可以声明工具和模型
|
|
34
|
+
- 工具只允许从 pipiclaw 现有工具白名单中选
|
|
35
|
+
- 模型允许不填写;不填写时默认使用主 Agent 当前模型
|
|
36
|
+
- 若填写,则必须能被当前 `ModelRegistry` 精确解析
|
|
37
|
+
|
|
38
|
+
6. 增加运行预算
|
|
39
|
+
- 允许在 agent 定义中填写
|
|
40
|
+
- 不填写时使用默认值
|
|
41
|
+
|
|
42
|
+
7. sub-agent 的 usage 和阶段性进度要能回传到主流程
|
|
43
|
+
|
|
44
|
+
Phase 1 明确不做:
|
|
45
|
+
|
|
46
|
+
1. parallel 模式
|
|
47
|
+
2. chain 模式
|
|
48
|
+
3. 自动运行时拦截式触发
|
|
49
|
+
- 例如“修改了 3 个文件后强制自动 review”
|
|
50
|
+
- Phase 1 不做 runtime 侧硬编码触发器,只通过 prompt 让主 Agent 自主决定
|
|
51
|
+
4. project/channel 多级 sub-agent 覆盖目录
|
|
52
|
+
5. 从 `AGENTS.md` 解析 sub-agent 定义
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
二、目录与信任模型
|
|
57
|
+
|
|
58
|
+
预定义 sub-agent 的加载目录:
|
|
59
|
+
|
|
60
|
+
- `workspaceDir/sub-agents/`
|
|
61
|
+
|
|
62
|
+
这样做的原因:
|
|
63
|
+
|
|
64
|
+
1. 保持 sub-agent 定义和 workspace 级配置在同一套管理员视角下维护
|
|
65
|
+
2. 不把 sub-agent 定义放进 channel 运行时目录,避免 channel 内工作产物和能力定义混在一起
|
|
66
|
+
3. 不复用 `AGENTS.md`
|
|
67
|
+
- `AGENTS.md` 继续承担“主 Agent 行为规则”职责
|
|
68
|
+
- sub-agent registry 单独管理,职责清晰
|
|
69
|
+
|
|
70
|
+
文档口径:
|
|
71
|
+
|
|
72
|
+
- `workspaceDir/sub-agents/` 是管理员维护的预定义 sub-agent 目录
|
|
73
|
+
- 主 Agent 可以读取并调用其中定义的 sub-agent
|
|
74
|
+
- 主 Agent 也可以在一次具体任务里临时构造一个内联 sub-agent
|
|
75
|
+
- `sub-agents/` 不属于 channel runtime 数据
|
|
76
|
+
- sub-agent 只隔离 LLM 对话上下文,不隔离文件系统和 executor
|
|
77
|
+
- sub-agent 在 workspace 中写出的文件,主 Agent 后续可以读取到;这是 Phase 1 的有意设计
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
三、Sub-Agent 定义文件格式
|
|
82
|
+
|
|
83
|
+
预定义文件位置示例:
|
|
84
|
+
|
|
85
|
+
- `workspaceDir/sub-agents/reviewer.md`
|
|
86
|
+
- `workspaceDir/sub-agents/researcher.md`
|
|
87
|
+
|
|
88
|
+
frontmatter 结构:
|
|
89
|
+
|
|
90
|
+
```md
|
|
91
|
+
---
|
|
92
|
+
name: reviewer
|
|
93
|
+
description: Review code changes for correctness, regressions, and missing tests
|
|
94
|
+
model: claude-sonnet-4-20250514
|
|
95
|
+
tools: read,bash
|
|
96
|
+
maxTurns: 24
|
|
97
|
+
maxToolCalls: 48
|
|
98
|
+
maxWallTimeSec: 300
|
|
99
|
+
bashTimeoutSec: 120
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
You are a focused code reviewer.
|
|
103
|
+
Review only the task given to you.
|
|
104
|
+
Prefer concise findings ordered by severity.
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
字段说明:
|
|
108
|
+
|
|
109
|
+
- `name`: 必填,sub-agent 名称,唯一键
|
|
110
|
+
- `description`: 必填,供主 Agent 决策时参考
|
|
111
|
+
- `model`: 选填,sub-agent 使用的模型 ID;为空时回退主 Agent 当前模型
|
|
112
|
+
- `tools`: 选填,逗号分隔;为空时使用默认工具集
|
|
113
|
+
- `maxTurns`: 选填,最多 assistant turns
|
|
114
|
+
- `maxToolCalls`: 选填,本次 sub-agent 最多允许执行的 tool call 总数
|
|
115
|
+
- `maxWallTimeSec`: 选填,本次 sub-agent 最大总执行时长
|
|
116
|
+
- `bashTimeoutSec`: 选填,sub-agent 内 bash 默认超时
|
|
117
|
+
- body: system prompt
|
|
118
|
+
|
|
119
|
+
默认值:
|
|
120
|
+
|
|
121
|
+
- `tools`: `read,bash`
|
|
122
|
+
- `maxTurns`: `24`
|
|
123
|
+
- `maxToolCalls`: `48`
|
|
124
|
+
- `maxWallTimeSec`: `300`
|
|
125
|
+
- `bashTimeoutSec`: `120`
|
|
126
|
+
|
|
127
|
+
这些默认值的设计目标:
|
|
128
|
+
|
|
129
|
+
1. 让 sub-agent 默认偏短任务
|
|
130
|
+
2. 优先控制 DingTalk 场景下的成本、失控和卡死风险
|
|
131
|
+
3. 不要求每个定义都显式写预算
|
|
132
|
+
4. 当任务明显更重时,允许在定义文件或单次调用中显式调大预算
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
四、加载与校验规则
|
|
137
|
+
|
|
138
|
+
新增 `src/sub-agents.ts`,负责发现、解析、校验和格式化可用 sub-agent 列表。
|
|
139
|
+
|
|
140
|
+
建议类型:
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
interface SubAgentConfig {
|
|
144
|
+
name: string;
|
|
145
|
+
description: string;
|
|
146
|
+
systemPrompt: string;
|
|
147
|
+
model?: Model<Api>;
|
|
148
|
+
modelRef?: string;
|
|
149
|
+
tools: string[];
|
|
150
|
+
maxTurns: number;
|
|
151
|
+
maxToolCalls: number;
|
|
152
|
+
maxWallTimeSec: number;
|
|
153
|
+
bashTimeoutSec: number;
|
|
154
|
+
filePath: string;
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
加载逻辑:
|
|
159
|
+
|
|
160
|
+
1. 读取 `SUB_AGENTS_DIR`
|
|
161
|
+
2. 遍历 `*.md`
|
|
162
|
+
3. 用 `parseFrontmatter()` 解析
|
|
163
|
+
4. 校验必填字段 `name`、`description`
|
|
164
|
+
5. 解析 `tools`
|
|
165
|
+
6. 解析预算字段,缺省填默认值
|
|
166
|
+
7. 若填写 `model`,通过 `ModelRegistry` 精确解析为 `Model<Api>`
|
|
167
|
+
8. 生成 `SubAgentConfig[]`
|
|
168
|
+
|
|
169
|
+
校验策略:
|
|
170
|
+
|
|
171
|
+
1. 未知工具名:直接拒绝加载该文件,并记录 warning
|
|
172
|
+
2. 无法解析的模型:直接拒绝加载该文件,并记录 warning
|
|
173
|
+
3. 重名 agent:后加载覆盖前加载不再需要,因为 Phase 1 只有一个目录;直接按文件名顺序遇到重名时报 warning 并忽略后者更清晰
|
|
174
|
+
4. 非法预算值:
|
|
175
|
+
- 小于等于 0 视为非法
|
|
176
|
+
- 回退默认值并记录 warning
|
|
177
|
+
|
|
178
|
+
允许的工具白名单:
|
|
179
|
+
|
|
180
|
+
- `read`
|
|
181
|
+
- `bash`
|
|
182
|
+
- `edit`
|
|
183
|
+
- `write`
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
五、主 Agent 如何使用 Sub-Agent
|
|
188
|
+
|
|
189
|
+
Phase 1 中,sub-agent 的调用决策仍然由主 Agent 做出。
|
|
190
|
+
|
|
191
|
+
这里要明确两层含义:
|
|
192
|
+
|
|
193
|
+
1. 不要求用户手工说“请调用 reviewer sub-agent”
|
|
194
|
+
2. 也不做 runtime 层硬编码自动触发器
|
|
195
|
+
|
|
196
|
+
实际机制是:
|
|
197
|
+
|
|
198
|
+
- 主 Agent 在 system prompt 里知道有 `subagent` 工具
|
|
199
|
+
- 主 Agent 看到复杂任务、上下文过重、需要专项视角时,自主发起 tool call
|
|
200
|
+
|
|
201
|
+
所以,Phase 1 的“只支持 single 模式”并不意味着“只能用户显式手工选择”,
|
|
202
|
+
它只是指工具参数结构先只支持一次调用一个 sub-agent。
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
六、Prompt 设计
|
|
207
|
+
|
|
208
|
+
修改 `src/prompt-builder.ts`,新增 `## Sub-Agents` section。
|
|
209
|
+
|
|
210
|
+
需要写清楚:
|
|
211
|
+
|
|
212
|
+
1. 你有一个 `subagent` tool
|
|
213
|
+
2. sub-agent 定义来自 `workspace/sub-agents/*.md`
|
|
214
|
+
3. 何时适合使用:
|
|
215
|
+
- 当前任务可拆分成独立子问题
|
|
216
|
+
- 需要新 context 处理重任务
|
|
217
|
+
- 需要特定专长角色,例如 reviewer / researcher
|
|
218
|
+
- 主上下文已经变长,想把局部工作卸载出去
|
|
219
|
+
4. 何时不要使用:
|
|
220
|
+
- 简单问答
|
|
221
|
+
- 严重依赖当前对话细节的任务
|
|
222
|
+
- 需要频繁和用户确认的互动任务
|
|
223
|
+
5. sub-agent 看不到主对话历史
|
|
224
|
+
- 主 Agent 必须把足够上下文写进 `task`
|
|
225
|
+
6. 优先调用最匹配的 sub-agent
|
|
226
|
+
7. 不要把一个小任务拆成过多 sub-agent
|
|
227
|
+
|
|
228
|
+
如果当前存在可用 sub-agent,可在 prompt 中附上简表:
|
|
229
|
+
|
|
230
|
+
- `reviewer`: Reviews code changes for regressions and missing tests
|
|
231
|
+
- `researcher`: Gathers focused information from files and shell output
|
|
232
|
+
|
|
233
|
+
另外要明确告诉主 Agent:
|
|
234
|
+
|
|
235
|
+
- 如果现有预定义 sub-agent 不适合当前任务,可以临时创建一个内联 sub-agent
|
|
236
|
+
- 内联 sub-agent 只服务当前这次 tool call,不会持久化到 `sub-agents/`
|
|
237
|
+
- 只有当任务确实需要时才这样做,避免把简单任务复杂化
|
|
238
|
+
|
|
239
|
+
这样主 Agent 才能稳定做选择,同时保留足够灵活性。
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
七、Sub-Agent Tool 设计
|
|
244
|
+
|
|
245
|
+
新增 `src/tools/subagent.ts`。
|
|
246
|
+
|
|
247
|
+
建议参数:
|
|
248
|
+
|
|
249
|
+
```ts
|
|
250
|
+
const subagentSchema = Type.Object({
|
|
251
|
+
label: Type.String(),
|
|
252
|
+
agent: Type.Optional(Type.String()),
|
|
253
|
+
name: Type.Optional(Type.String()),
|
|
254
|
+
task: Type.String(),
|
|
255
|
+
systemPrompt: Type.Optional(Type.String()),
|
|
256
|
+
tools: Type.Optional(Type.Array(Type.String())),
|
|
257
|
+
model: Type.Optional(Type.String()),
|
|
258
|
+
maxTurns: Type.Optional(Type.Number()),
|
|
259
|
+
maxToolCalls: Type.Optional(Type.Number()),
|
|
260
|
+
maxWallTimeSec: Type.Optional(Type.Number()),
|
|
261
|
+
bashTimeoutSec: Type.Optional(Type.Number()),
|
|
262
|
+
});
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
参数语义:
|
|
266
|
+
|
|
267
|
+
1. 预定义模式
|
|
268
|
+
- 提供 `agent`
|
|
269
|
+
- 运行时从 `workspaceDir/sub-agents/*.md` 加载该定义
|
|
270
|
+
|
|
271
|
+
2. 内联模式
|
|
272
|
+
- 不提供 `agent`
|
|
273
|
+
- 提供 `systemPrompt`
|
|
274
|
+
- 允许同时提供 `name/tools/model/预算`
|
|
275
|
+
- `name` 为空时,runtime 可回退为 `dynamic-subagent`
|
|
276
|
+
|
|
277
|
+
约束:
|
|
278
|
+
|
|
279
|
+
- `agent` 和 `systemPrompt` 至少要提供一类
|
|
280
|
+
- 如果同时提供 `agent` 和内联字段:
|
|
281
|
+
- Phase 1 采取简单规则:以 `agent` 对应的预定义配置为基础
|
|
282
|
+
- 内联字段作为本次调用的覆盖项
|
|
283
|
+
|
|
284
|
+
建议返回 details 结构:
|
|
285
|
+
|
|
286
|
+
```ts
|
|
287
|
+
interface SubAgentToolDetails {
|
|
288
|
+
agent: string;
|
|
289
|
+
model: string;
|
|
290
|
+
tools: string[];
|
|
291
|
+
usage: {
|
|
292
|
+
input: number;
|
|
293
|
+
output: number;
|
|
294
|
+
cacheRead: number;
|
|
295
|
+
cacheWrite: number;
|
|
296
|
+
total: number;
|
|
297
|
+
cost: {
|
|
298
|
+
input: number;
|
|
299
|
+
output: number;
|
|
300
|
+
cacheRead: number;
|
|
301
|
+
cacheWrite: number;
|
|
302
|
+
total: number;
|
|
303
|
+
};
|
|
304
|
+
};
|
|
305
|
+
turns: number;
|
|
306
|
+
toolCalls: number;
|
|
307
|
+
durationMs: number;
|
|
308
|
+
truncated?: boolean;
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
执行流程:
|
|
313
|
+
|
|
314
|
+
1. 如果提供 `agent`,先按名称查找预定义 sub-agent
|
|
315
|
+
2. 若提供内联字段,则在预定义配置基础上或纯内联模式下生成最终执行配置
|
|
316
|
+
3. 按 `tools` 白名单从基础工具集中筛选子工具集
|
|
317
|
+
4. 对 bash 工具应用 sub-agent 级默认 timeout
|
|
318
|
+
5. 创建新的 `Agent`
|
|
319
|
+
6. 订阅事件,累计:
|
|
320
|
+
- assistant 文本
|
|
321
|
+
- usage
|
|
322
|
+
- turns
|
|
323
|
+
- toolCalls
|
|
324
|
+
7. 用父 signal 派生子 `AbortController`
|
|
325
|
+
8. 超过 `maxWallTimeSec` 时主动 abort
|
|
326
|
+
9. 触达 `maxTurns` / `maxToolCalls` 时通过 `beforeToolCall` 或事件计数终止执行
|
|
327
|
+
10. 返回最终文本和 details
|
|
328
|
+
|
|
329
|
+
执行结果原则:
|
|
330
|
+
|
|
331
|
+
1. 成功时返回最终文本
|
|
332
|
+
2. 完全失败时返回 tool error
|
|
333
|
+
3. 若 sub-agent 已产生可用文本但因预算耗尽或中途停止而未完整完成,则返回部分结果,不丢弃已产出文本
|
|
334
|
+
4. 返回文本要简洁,不把完整 event dump 暴露给主 Agent
|
|
335
|
+
5. 细节放到 `details`
|
|
336
|
+
6. sub-agent 运行摘要应持久化到 channel 目录,便于事后审查
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
八、运行预算实现方式
|
|
341
|
+
|
|
342
|
+
预算字段允许不填写,但 runtime 需要严格执行默认值。
|
|
343
|
+
|
|
344
|
+
预算控制建议:
|
|
345
|
+
|
|
346
|
+
1. `maxWallTimeSec`
|
|
347
|
+
- 用 `setTimeout` + 子 `AbortController` 实现
|
|
348
|
+
|
|
349
|
+
2. `maxToolCalls`
|
|
350
|
+
- 通过 `tool_execution_start` 计数
|
|
351
|
+
- 超过上限后调用 `abort()`
|
|
352
|
+
|
|
353
|
+
3. `maxTurns`
|
|
354
|
+
- 通过 `message_end` 中 assistant message 计数
|
|
355
|
+
- 到达上限后不再继续下一轮
|
|
356
|
+
|
|
357
|
+
4. `bashTimeoutSec`
|
|
358
|
+
- 让 sub-agent 使用一个带默认 timeout 的 `createBashTool` 变体
|
|
359
|
+
- 调用参数里显式传了 `timeout` 时,以调用参数为准
|
|
360
|
+
|
|
361
|
+
运行预算是 Phase 1 的硬约束,不是“先记文档、后面再做”的软约束。
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
九、工具集组装方式
|
|
366
|
+
|
|
367
|
+
修改 `src/tools/index.ts`。
|
|
368
|
+
|
|
369
|
+
建议结构:
|
|
370
|
+
|
|
371
|
+
1. `createPipiclawBaseTools(executor)`
|
|
372
|
+
- 返回 `read/bash/edit/write`
|
|
373
|
+
|
|
374
|
+
2. `filterToolsByName(allTools, names)`
|
|
375
|
+
- 供 sub-agent 选择工具子集
|
|
376
|
+
|
|
377
|
+
3. `createSubAgentTool(options, baseTools)`
|
|
378
|
+
- 创建 `subagent`
|
|
379
|
+
|
|
380
|
+
4. `createPipiclawTools(options)`
|
|
381
|
+
- 主 Agent 用:`[...baseTools, subagentTool]`
|
|
382
|
+
|
|
383
|
+
重要约束:
|
|
384
|
+
|
|
385
|
+
- sub-agent 内部不注入 `subagent` 本身
|
|
386
|
+
- Phase 1 禁止递归 sub-agent
|
|
387
|
+
- 也就是不允许子 agent 再创建孙 agent
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
十、主流程接线
|
|
392
|
+
|
|
393
|
+
修改 `src/agent.ts`。
|
|
394
|
+
|
|
395
|
+
需要做的事情:
|
|
396
|
+
|
|
397
|
+
1. 创建基础工具集
|
|
398
|
+
2. 创建 `subagent` tool
|
|
399
|
+
3. 把 `subagent` 加入主 Agent 的工具列表
|
|
400
|
+
4. 在 session event 处理中支持 `tool_execution_update`
|
|
401
|
+
5. 当 `tool_execution_end` 的 toolName 为 `subagent` 时,读取 result.details.usage 并合并到
|
|
402
|
+
`runState.totalUsage`
|
|
403
|
+
|
|
404
|
+
这样可以解决两个问题:
|
|
405
|
+
|
|
406
|
+
1. DingTalk 侧有中间进度,不会长时间“假死”
|
|
407
|
+
2. `/session` 和 usage summary 不会漏掉 sub-agent 成本
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
十一、进度与可观测性
|
|
412
|
+
|
|
413
|
+
需要同时做两层进度:
|
|
414
|
+
|
|
415
|
+
1. subagent tool 内部用 `onUpdate` 上报阶段信息
|
|
416
|
+
2. `ChannelRunner` 处理 `tool_execution_update`
|
|
417
|
+
|
|
418
|
+
建议 subagent 的 update 文本形式:
|
|
419
|
+
|
|
420
|
+
- `Subagent reviewer started`
|
|
421
|
+
- `Subagent reviewer: reading files`
|
|
422
|
+
- `Subagent reviewer: running tests`
|
|
423
|
+
- `Subagent reviewer: preparing final summary`
|
|
424
|
+
|
|
425
|
+
update 不需要追求逐 token streaming,Phase 1 只要做到“用户可见仍在推进”即可。
|
|
426
|
+
|
|
427
|
+
另外补充:
|
|
428
|
+
|
|
429
|
+
- runtime 会把 sub-agent 的执行摘要写入 `<channel>/subagent-runs.jsonl`
|
|
430
|
+
- 至少包括 agent 名称、预算停止原因、usage、输出摘要
|
|
431
|
+
|
|
432
|
+
---
|
|
433
|
+
|
|
434
|
+
十二、README 与初始化
|
|
435
|
+
|
|
436
|
+
修改 `src/paths.ts`:
|
|
437
|
+
|
|
438
|
+
- 新增 `SUB_AGENTS_DIR_NAME = "sub-agents"`
|
|
439
|
+
|
|
440
|
+
修改 `src/main.ts`:
|
|
441
|
+
|
|
442
|
+
- 首次启动时创建 `workspace/sub-agents/`
|
|
443
|
+
- 初始目录留空,不生成示例文件
|
|
444
|
+
|
|
445
|
+
修改 `README.md`:
|
|
446
|
+
|
|
447
|
+
1. 在首次运行生成目录中加入 `workspace/sub-agents/`
|
|
448
|
+
2. 在 Workspace Files 中加入 `sub-agents/`
|
|
449
|
+
3. 说明它的职责是管理员维护的预定义 sub-agent 目录
|
|
450
|
+
4. 说明主 Agent 也可以临时内联定义 sub-agent
|
|
451
|
+
5. 补充一个最小 agent 定义示例
|
|
452
|
+
|
|
453
|
+
---
|
|
454
|
+
|
|
455
|
+
十三、建议文件变更清单
|
|
456
|
+
|
|
457
|
+
新增:
|
|
458
|
+
|
|
459
|
+
- `src/sub-agents.ts`
|
|
460
|
+
- `src/tools/subagent.ts`
|
|
461
|
+
|
|
462
|
+
修改:
|
|
463
|
+
|
|
464
|
+
- `src/paths.ts`
|
|
465
|
+
- `src/main.ts`
|
|
466
|
+
- `src/tools/index.ts`
|
|
467
|
+
- `src/agent.ts`
|
|
468
|
+
- `src/prompt-builder.ts`
|
|
469
|
+
- `README.md`
|
|
470
|
+
|
|
471
|
+
---
|
|
472
|
+
|
|
473
|
+
十四、实现顺序
|
|
474
|
+
|
|
475
|
+
建议按这个顺序落地:
|
|
476
|
+
|
|
477
|
+
1. `paths.ts` + `main.ts`
|
|
478
|
+
- 先把目录约定固定下来
|
|
479
|
+
|
|
480
|
+
2. `sub-agents.ts`
|
|
481
|
+
- 先完成定义文件加载、解析和校验
|
|
482
|
+
|
|
483
|
+
3. `tools/index.ts` 重构
|
|
484
|
+
- 拆出 base tools 和过滤逻辑
|
|
485
|
+
|
|
486
|
+
4. `tools/subagent.ts`
|
|
487
|
+
- 实现单个 sub-agent 执行
|
|
488
|
+
|
|
489
|
+
5. `agent.ts`
|
|
490
|
+
- 接入工具
|
|
491
|
+
- 合并 usage
|
|
492
|
+
- 处理 `tool_execution_update`
|
|
493
|
+
|
|
494
|
+
6. `prompt-builder.ts`
|
|
495
|
+
- 让主 Agent 知道什么时候应调用 sub-agent
|
|
496
|
+
|
|
497
|
+
7. `README.md`
|
|
498
|
+
- 补充目录与格式说明
|
|
499
|
+
|
|
500
|
+
---
|
|
501
|
+
|
|
502
|
+
十五、Phase 1 验收标准
|
|
503
|
+
|
|
504
|
+
只要满足下面几条,就可以认为 Phase 1 可用:
|
|
505
|
+
|
|
506
|
+
1. 在 `workspaceDir/sub-agents/` 放一个 `reviewer.md` 后,主 Agent 能自主调用它
|
|
507
|
+
2. sub-agent 能使用声明的工具集执行任务
|
|
508
|
+
3. sub-agent 看不到主对话历史,只依赖主 Agent 传入的 task
|
|
509
|
+
4. sub-agent 的 usage 能计入本次运行总 usage
|
|
510
|
+
5. DingTalk 中能看到 sub-agent 的阶段性进度
|
|
511
|
+
6. 非法模型/非法工具的 agent 文件会被明确拒绝加载
|
|
512
|
+
7. 不填写预算字段时,默认预算仍生效
|
|
513
|
+
8. 主 Agent 也可以在单次调用里临时内联定义一个 sub-agent
|
|
514
|
+
9. sub-agent 不能递归再调用 sub-agent
|
|
515
|
+
|
|
516
|
+
---
|
|
517
|
+
|
|
518
|
+
十六、Phase 2 以后再考虑的内容
|
|
519
|
+
|
|
520
|
+
以下内容暂不进入 Phase 1:
|
|
521
|
+
|
|
522
|
+
1. parallel
|
|
523
|
+
2. chain
|
|
524
|
+
3. 更细的 UI 展示
|
|
525
|
+
4. 多目录覆盖和优先级
|
|
526
|
+
5. 更复杂的自动委派策略模板
|
|
527
|
+
6. sub-agent 运行历史持久化
|
|
528
|
+
|
|
529
|
+
先把 Phase 1 做成一个稳定、低歧义、低运维成本的工具,再扩展模式。
|
package/package.json
CHANGED
|
@@ -1,54 +1,70 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
2
|
+
"name": "@oyasmi/pipiclaw",
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "An AI assistant runtime for coding and team workflows, with DingTalk AI Cards, sub-agents, memory, and scheduled events.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"pipiclaw": "dist/main.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./package.json": "./package.json"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"docs",
|
|
21
|
+
"CHANGELOG.md",
|
|
22
|
+
"README.md",
|
|
23
|
+
"LICENSE"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"clean": "shx rm -rf dist coverage",
|
|
27
|
+
"build": "tsc -p tsconfig.build.json && shx chmod +x dist/main.js",
|
|
28
|
+
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput",
|
|
29
|
+
"lint": "biome check .",
|
|
30
|
+
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
31
|
+
"test": "vitest --run",
|
|
32
|
+
"check": "npm run lint && npm run typecheck && npm run test",
|
|
33
|
+
"prepublishOnly": "npm run clean && npm run build && npm run check"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@mariozechner/pi-agent-core": "^0.63.0",
|
|
37
|
+
"@mariozechner/pi-ai": "^0.63.0",
|
|
38
|
+
"@mariozechner/pi-coding-agent": "^0.63.0",
|
|
39
|
+
"@sinclair/typebox": "^0.34.0",
|
|
40
|
+
"axios": "^1.7.0",
|
|
41
|
+
"chalk": "^5.6.2",
|
|
42
|
+
"croner": "^9.1.0",
|
|
43
|
+
"diff": "^8.0.2",
|
|
44
|
+
"dingtalk-stream": "^2.1.4"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@biomejs/biome": "2.3.5",
|
|
48
|
+
"@types/diff": "^7.0.2",
|
|
49
|
+
"@types/node": "^24.3.0",
|
|
50
|
+
"shx": "^0.4.0",
|
|
51
|
+
"typescript": "^5.7.3",
|
|
52
|
+
"vitest": "^3.2.4"
|
|
53
|
+
},
|
|
54
|
+
"keywords": [
|
|
55
|
+
"dingtalk",
|
|
56
|
+
"bot",
|
|
57
|
+
"ai",
|
|
58
|
+
"agent",
|
|
59
|
+
"coding-agent",
|
|
60
|
+
"pi",
|
|
61
|
+
"harness-engineering"
|
|
62
|
+
],
|
|
63
|
+
"license": "Apache-2.0",
|
|
64
|
+
"publishConfig": {
|
|
65
|
+
"access": "public"
|
|
66
|
+
},
|
|
67
|
+
"engines": {
|
|
68
|
+
"node": ">=22.0.0"
|
|
69
|
+
}
|
|
70
|
+
}
|