From a876f0fe9d7280fe9b6b2b833facd4e2b48933a8 Mon Sep 17 00:00:00 2001 From: iomgaa Date: Sat, 3 Oct 2026 00:17:54 -0400 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=96=B0=E5=A2=9E=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E4=B9=A6=2007-agents?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- WORK_LOG.md | 3 +- 任务书/07-agents.md | 170 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 任务书/07-agents.md diff --git a/WORK_LOG.md b/WORK_LOG.md index 7a692f3..9f56b41 100644 --- a/WORK_LOG.md +++ b/WORK_LOG.md @@ -41,6 +41,7 @@ - tasks 与 runner(任务书 05):依赖跟着任务走,一份研究不能自己改依赖,镜像在研究开始时建一次、编号冻结进账本;runner、tasks 行数按结构.md 第七部分;两个模块合成一份任务书。用户原话:"都同意,写任务书 05 吧"。监督者另定并告知用户:凡是执行任务代码的事(正式运行、判分、轻量检查)都在任务镜像里跑;资源用量在容器里读,不建要 root 清理的 cgroup 分组;容器断网;同一份研究所有运行用同一个种子;不做"取消"函数;`VERDICTS` 删掉"判不了"。 - workspace(任务书 06)用 git:一份研究一个裸仓库,版本号是目录树编号;存版本时自己列文件、用 hash-object 存,不用 `git add`(实测 `.gitignore` 会让它悄悄漏存);git 子进程不读用户配置;实验员目录里除了 task.json 的"不存"清单都算候选,符号链接等特殊文件退回实验员;预期 200–300 行。先派全新上下文子 Agent 独立分析过。用户原话:"都同意,写任务书 06 吧"。 - 实验员会话里的 shell 命令不测 CPU,只记每次模型调用的墙钟时间;正式运行的资源用量照记。用户原话:"那要不就不测了?本来cpu就不重要,现在又可能测不准"。 +- agents(任务书 07):只收拼好的提示词和第一条消息(读提示词归 materials),不碰账本;提交工具去掉 slot;保留参考项目两处有真实证据的提交特殊处理(非法 JSON 被截半、null 变 "null")和子会话加载核对;删 Jev 审命令、上下文估算、输出上限配置;预期 400–600 行。用户原话:"同意,写任务书 07 吧"。 ## 未完成 @@ -87,4 +88,4 @@ ## 下一步 -任务书 06 已核对通过(6850c0a)。下一个模块待和用户商量。 +任务书 07(agents,`任务书/07-agents.md`)已写好,等用户另开新 Agent 执行;完成后监督者核对。 diff --git a/任务书/07-agents.md b/任务书/07-agents.md new file mode 100644 index 0000000..91f17e8 --- /dev/null +++ b/任务书/07-agents.md @@ -0,0 +1,170 @@ +# 任务书 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。