a876f0fe9d
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
171 lines
12 KiB
Markdown
171 lines
12 KiB
Markdown
# 任务书 07:agents(角色会话)
|
||
|
||
写 agents 模块:把一个任务交给 Pi 里的一个模型去做,等它交上来。它是程序里唯一直接跟 Pi 打交道的模块。
|
||
|
||
本任务书已由用户和监督者在 2026-10-03 一起确定。下面说的"监督者",是在参考项目目录里和用户讨论设计的另一个会话。
|
||
|
||
## 开工前先读
|
||
|
||
- `CLAUDE.md`:全部,尤其是"罕见情况怎么办"(什么算边界)、"不设默认值"、"测试"、"Pi 与三个角色"。
|
||
- `docs/结构.md`:
|
||
- 第二部分:agents 一行,"给模型看什么只归 materials""收不收一份提交,只在 submissions 一处判"两条边界;
|
||
- 第三部分:账本记录第 3 种(提交、私人笔记)和第 10 种(用量);
|
||
- 第六部分:只有 agents 和 plugin 能用 Pi;
|
||
- 第八部分:vocab 的 `ROLES`、`SUBMISSION_KINDS`、`SUBMISSION_SCHEMAS`、`ModelUsage`。
|
||
- `docs/方法.md`:
|
||
- 第三部分:角色与工具、私人笔记;
|
||
- 第五部分开头:替换自己刚交的提交;
|
||
- 第七部分:用量只记录,拿不到记"未知"、不记 0。
|
||
- `WORK_LOG.md`。
|
||
- 本机 Pi 0.85.1 的包和类型定义:`/home/iomgaa/.npm-global/lib/node_modules/@earendil-works/pi-coding-agent/`。只照这个版本写,不照网上别的版本的示例。
|
||
- 参考项目(只读,不要改):
|
||
- `/home/iomgaa/Projects/RivalBits/src/agents/session.ts`:开会话、核对加载了什么、收用量;
|
||
- `/home/iomgaa/Projects/RivalBits/src/agents/tools.ts`:各角色的工具、提交工具的两处特殊处理、shell 环境变量;
|
||
- `/home/iomgaa/Projects/RivalBits/src/agents/contract.ts`。
|
||
|
||
## 一、这个模块做什么
|
||
|
||
用实验员实现候选 c1 举例:
|
||
|
||
1. flow 交给 agents:
|
||
- 用哪个模型(provider、模型名、思考档位);
|
||
- 角色提示词、第一条消息(都是拼好的文字,由 materials 写);
|
||
- 工作目录、会话文件存放的目录;
|
||
- 这次要交哪种提交;
|
||
- 几个回调:模型调某个工具时,要找谁办。
|
||
2. agents 在 Pi 里开一个子会话,按角色只发该给的工具,发出第一条消息。
|
||
3. 模型干活:
|
||
- 调"查询",agents 转给回调,materials 回答;
|
||
- 调"提交",agents 转给回调,flow 经 submissions 判定、写账本,把"收下 + 编号"或"退回 + 原因"交回,agents 再原样回给模型;
|
||
- 模型每回复一次,agents 把这次的 token 用量交给回调。
|
||
4. 会话结束,agents 交回结局和这次会话的墙钟时间。
|
||
|
||
agents 不碰账本,不决定给模型看什么,也不判断交上来的东西好不好。
|
||
|
||
## 二、对外提供什么
|
||
|
||
经 `src/agents/index.ts` 导出,函数名由你定。
|
||
|
||
**跑一次会话**:一个函数,输入下面这些,全部必填,可以没有的写 `null`。
|
||
|
||
- 角色、模型(provider、模型名、思考档位)。思考档位必须写明,不接受 `null`(WORK_LOG"给 agents")。
|
||
- 角色提示词、第一条消息。
|
||
- 工作目录、会话文件目录。
|
||
- 这次要交的提交种类(vocab `SubmissionKind`)。提交工具的参数形状直接用 vocab 的 `SUBMISSION_SCHEMAS`,不另写一份。
|
||
- 交上一份被收下以后,是否就结束会话:
|
||
- 实验员、核验员是"是";
|
||
- 研究者是"否":一个研究者可能要交几份提案,或者看了回执发现被截断,要替换。
|
||
- 回调:
|
||
- 查询:给一个编号,交回文字,或者"看不到";
|
||
- 提交:给内容和"替换哪一份"(可以没有),交回"收下 + 编号"或"退回 + 原因";
|
||
- 用量:每次回复交一份 vocab 的 `ModelUsage`;
|
||
- 研究者另有"写私人笔记":笔记是账本记录,由回调去写;
|
||
- 实验员另有"轻量检查":由 flow 用 tasks 和 runner 接好,交回结果文字。
|
||
- 研究者和核验员另给"能读的目录"清单。
|
||
- 一个"停下"信号:用户中途停下研究时用。
|
||
|
||
用联合类型按角色区分:研究者才有写笔记和能读的目录,实验员才有轻量检查。写不出"实验员带笔记"这种组合,就不用写检查。
|
||
|
||
**交回的结局**:
|
||
- 交了:至少有一份被收下;
|
||
- 没交:附原因,例如最后一条回复被输出上限截断;
|
||
- 出错:模型服务报错、子会话核对不通过等,附原因;
|
||
- 被停下。
|
||
|
||
每种结局都带这次会话的墙钟时间和会话文件路径。账本记录本身不带时间,flow 把墙钟时间写进"模型调用结束"那条记录(结构.md 第三部分第 10 种)。
|
||
|
||
## 三、各角色的工具
|
||
|
||
| 角色 | 工具 |
|
||
|---|---|
|
||
| 研究者 | 查询、读代码、提交、写私人笔记 |
|
||
| 核验员 | 查询、读代码、提交 |
|
||
| 实验员 | 查询、提交、轻量检查,加上 Pi 自带的 read、write、edit、bash、grep、find、ls |
|
||
|
||
工具名、说明文字照参考项目 `tools.ts`,按下面改:
|
||
|
||
- **提交**:
|
||
- 去掉参考项目的 `slot` 参数:一个会话只处理一个对象,交给谁由 flow 定,模型不用再写一遍。
|
||
- `replaces` 只给研究者的提交种类;实现、修复、核验、消融实现、消融核验不能替换(方法.md 第五部分),这几种的工具参数里就没有这个字段。
|
||
- 同一次回复里调两次提交时,按顺序执行,照参考项目声明 `executionMode: "sequential"`。
|
||
- **读代码**:只能读给定目录里的文件、列目录,读之前按真实路径判断在不在目录里。模型正常探索时就会去 `ls` 上一层目录,看到别人还没公开的东西。单次读多少照参考项目的上限。
|
||
- **实验员的 bash**:
|
||
- 环境变量只放 PATH、HOME、LANG、LC_ALL、TMPDIR。插件进程的环境里可能有模型密钥,不能漏进实验员的 shell。参考项目还额外设了 `OMP_NUM_THREADS` 这一类变量,那是为宿主上跑轻量检查准备的,现在轻量检查在容器里跑,不用设了。
|
||
- 不把 Pi 的会话信息放进环境变量(`exposeSessionEnvironment: false`)。
|
||
|
||
## 四、要保留的几处特殊处理(都有真实证据)
|
||
|
||
1. **提交参数不是合法 JSON 时退回**:Pi 0.85.1 遇到写坏的工具参数,会悄悄只取前半截。参考项目 15-real-1 里,一份收尾就这样被截成 214 个字收下了。照参考项目的做法:监听流式输出,拼出参数原文,严格解析;解析失败就退回,告诉模型最常见的原因是正文里有没转义的半角双引号。参考项目提交 bcc422e。
|
||
2. **必填文字字段交 null 时退回**:Pi 校验之前会把 null 变成字符串 `"null"`。参考项目 14-real-1 里有两条挑刺回应就这样被收下了。照参考项目的 `nullFieldPaths`,在 Pi 校验之前查出来,报出字段位置。参考项目提交 fd73b78。
|
||
3. **形状不合格也要让 flow 知道**:Pi 在调提交工具之前就会把形状错误回给模型,提交回调收不到,flow 就记不下"退回"。所以 1、2 和 Pi 自己的形状校验发现的问题,都交给提交回调记一条退回,再照常回给模型。参考项目用的是 `rejectShape`;新项目里怎么接你定,但只用提交这一个回调,不另加一个。
|
||
4. **核对子会话实际加载了什么**(CLAUDE.md"Pi 与三个角色"最后一条):
|
||
- 会话用的是不是指定的模型,Pi 有没有悄悄换模型;
|
||
- 有没有加载扩展、技能、提示模板、`AGENTS.md` 这类上下文文件;
|
||
- 系统提示词是不是我们给的那一份,有没有被追加内容;
|
||
- 工具表是不是正好这几个,工具实现是不是我们给的。
|
||
|
||
本机 `~/.pi/agent/` 下有 extensions 和 skills,这件事没人操作也会发生。核对不通过,一个请求都不发,交回"出错"。
|
||
|
||
另外几点:
|
||
- **用量**:模型服务没报用量(输入、缓存读、缓存写都是 0)时,这次记"测不到"并附原因,不记 0。价格记"测不到",原因照参考项目:"Pi 的价格表不是账单"。
|
||
- **截断**:最后一条回复是因为输出上限停下的、而且没交,结局"没交"的原因里写明。
|
||
- **单次回复的输出上限**:不设,用 Pi 模型配置里的值。
|
||
- **重试**:模型服务出错时用 Pi 自己的重试。用的是哪些设置,在代码里写明,不另写一层重试。
|
||
|
||
## 五、不搬的东西
|
||
|
||
| 处理 | 内容 |
|
||
|---|---|
|
||
| 删除 | `shell-review.ts` 整个文件:Jev 审实验员的命令,方法里已删除 |
|
||
| 不归 agents | `prompts.ts`:读提示词文件、拼第一条消息、收尾段,归 materials;agents 只收拼好的文字 |
|
||
| 删除 | `context-window.ts`:估算材料会不会撑爆上下文;以后真出问题再在 materials 里加 |
|
||
| 删除 | `check.ts`:轻量检查由 flow 接好作为回调传进来 |
|
||
| 删除 | `redact.ts`:没查到报错信息里真带出过密钥 |
|
||
| 删除 | `notesSection`:笔记怎么放进第一条消息归 materials |
|
||
| 删除 | 配置里的"单次回复输出上限"和"服务没照上限截断"的检查 |
|
||
| 删除 | 提交工具的 `slot` 参数和对它的检查 |
|
||
| 删除 | `deps.runtime ?? ModelRuntime.create()` 这类可选参数:不设默认值,也不为测试给产品代码加参数 |
|
||
|
||
实验员会话里的 shell 命令不测 CPU,用户 2026-10-03 定(方法.md 第七部分)。
|
||
|
||
## 六、测试
|
||
|
||
**不花钱的测试**,放进 `npm test`:
|
||
- 第四部分第 1 条:用一段半角双引号没转义的参数原文喂给监听逻辑,结果是退回,原因写明。参考项目的回归测试可以借,有 slot 在前和在后两种。
|
||
- 第四部分第 2 条:必填文字字段交 null,退回并报出字段位置。
|
||
- 读代码:目录外的路径读不到,包括用 `..` 和符号链接绕出去的。
|
||
- 实验员 bash 的环境变量:插件进程里设一个假的密钥变量,shell 里看不到。
|
||
- 工具表:三种角色各自拿到的工具名正好是第三部分那几个。
|
||
|
||
**真实模型的测试**:CLAUDE.md 说真实模型链路要用真实运行来证明。另起一个命令,例如 `npm run test:pi`,不放进 `npm test`,因为要花钱、要联网。
|
||
|
||
用配置里的 glm-5.3,至少跑这几个:
|
||
- 一个研究者会话交一份简单的提交,用你选的最简单的种类,第一次故意让回调退回,模型改了再交,收下;
|
||
- 一个实验员会话在工作目录里写一个文件、跑一条 shell 命令,再交;
|
||
- 每次回复都交出了用量,会话交回了墙钟时间;
|
||
- 核对子会话加载了什么:在本机真实的 `~/.pi/agent/` 下跑一次,确认核对通过,没加载扩展和技能。
|
||
|
||
报告里贴出这几次的实际结局和用量。
|
||
|
||
**审阅**:agents 不碰账本,按原型标准,不另派子 Agent 审阅。
|
||
|
||
## 七、规模与文档
|
||
|
||
- 预期 400–600 行,不含测试。超过 600 行就停下来检查。
|
||
- 完成后更新:
|
||
- `docs/结构.md` 第八部分:补 agents 对外的函数和类型,每项一句话;
|
||
- `docs/结构.md` 第七部分:agents 的预期行数改成 400–600;
|
||
- `WORK_LOG.md`:在"已完成"补一条,删掉"给 agents:模型的思考档位必须写明"那条。
|
||
- 不新建 md 文件。
|
||
|
||
## 八、验收与报告
|
||
|
||
做完后本地提交,然后在回复里交一份报告,监督者会对着实际文件逐项核对:
|
||
|
||
1. 提交号,新增和修改的文件列表,每个文件的行数,agents 的总行数。
|
||
2. `npm run check`、`npm test`、`npm run test:pi` 的完整输出。
|
||
3. 真实模型那几次会话的结局、每次回复的用量、墙钟时间。
|
||
4. Pi 自己的重试用了什么设置。
|
||
5. 你和这份任务书、结构.md、方法.md 不一致的地方,以及为什么。
|
||
6. **规则不清楚的地方**:读 CLAUDE.md、结构.md、方法.md 时,哪里让你犹豫、哪里两份文件说法不一致、哪里你是靠猜的。没有就写"没有"。没有真实证据的可能情况,在这里提一句就够,不写进 WORK_LOG。
|