内容
# AgentFactory
AgentFactory:一个单用户本地任务板,作为外部代理循环的持久状态存储和UI。
## 技术栈
TypeScript monorepo(npm工作区),包含五个包:
- **`core`** — node:sqlite + 生命周期规则(共享业务逻辑和数据库层)
- **`mcp`** — stdio MCP服务器(向代理循环公开任务板操作)
- **`web`** — Hono API + SSE + React/Vite UI(基于浏览器的任务板界面)
- **`dispatcher`** — 无头工作器监督器(为每个排队的任务生成一个全新的`claude -p`会话)
- **`reviewer`** — 无头审查监督器(为每个`in_review`任务生成一个codex/claude会话,以发布`ai-review/v1`裁决)
**需要 Node >= 26.**
## 快速入门
### 安装依赖项
```bash
npm install
```
### 运行网页UI(开发模式)
开发模式需要两个进程:API服务器和Vite客户端(它代理`/api`和`/events`到API服务器)。
```bash
# 终端 1 — Hono API + SSE on port 8787
npm run web:dev:server
# 终端 2 — Vite client on port 5173
npm run web:dev
```
服务器将其数据存储在`agentfactory.db`中(可以通过`AGENTFACTORY_DB`环境变量覆盖 — 路径相对于工作目录解析,因此将网页服务器和MCP服务器指向相同的绝对路径)。
### 运行MCP服务器(开发模式)
```bash
npm run mcp:dev
```
### 运行调度器(无人值守的工作器)
对于没有人工介入的持续工作器,调度器会轮询数据库中的排队任务,并为每个任务生成一个全新的无头`claude -p`会话 — 该会话通过`get_next_task`认领,通过`submit_result`工作,并退出,因此每次尝试都从当前的MCP构建和协议开始。崩溃或超时的会话会释放回队列,附带日志尾部;令牌/成本指标从CLI自己的JSON结果中解析。
```bash
npm run dispatcher -- path/to/dispatcher.config.json
```
参见`packages/dispatcher/README.md`了解配置参考(工作区、并发性、权限模式、尝试限制)。
### 运行审查器(无人值守的AI审查)
除了调度器外,**审查器**将`in_review`列转换为自动第一轮审查,无需人工介入。它会轮询仍需要审查的任务,并为每个任务生成一个全新的无头引擎会话 — 默认情况下为**codex**(对调度器的Claude工作的独立第二意见)或claude — 将差异(实现)或交付成果(描述/计划)通过STDIN输入,并发布`ai-review/v1`裁决回。它是建议性的:干净的文档阶段裁决会自动将任务推进到下一阶段;发现和实现阶段将保留给人工门户。
```bash
npm run reviewer -- path/to/reviewer.config.json
```
在调度器和网页服务器上运行,所有这些都在同一个数据库上。参见`packages/reviewer/README.md`了解配置参考(引擎、模型、并发性、差异上限、尝试限制)。
### 实时代理状态
当代理工作时,**实时**视图(标头切换)和每个正在进行的任务的抽屉显示当前正在运行的内容 — 当前阶段、滚动里程碑提要和到目前为止的令牌计数 — 由工作器在达到每个里程碑时调用的`report_progress` MCP工具提供。这是短暂的当前状态(当会话结束时消失),与持久的活动日志不同。
实时视图还包含一个**监督器健康条**: 每个调度器/审查器的绿色/红色圆点,带有其忙碌计数和最后一次看到的时间,您可以一眼看出循环是否正常运行,而无需阅读控制台。每个监督器每隔一段时间发送一次心跳;停止跳动的心跳会自行变成红色。`GET /health`端点(公共,无身份验证)是观察狗的活动探测。
### 故障分类
当工作器崩溃、超时、被拒绝权限或耗尽其尝试次数 — 或审查器无法运行时,监督器会发布一个结构化的`failure/v1`注释。任务板将其显示为卡片上的红色**故障芯片**和抽屉中的**故障横幅**(原因、尝试次数和单击即可展开日志尾部的功能),并且分析视图会将故障按原因细分(“为什么任务失败”)。成功的重试会自动清除故障。
### 通知(无人值守的警报)
对于您离开运行的循环,网页服务器可以推送Webhook警报,以便您在几分钟内而不是几小时内收到通知。设置`AF_NOTIFY_WEBHOOKS`为一个或多个与Slack兼容的Webhook URL(逗号分隔),它会发布`{ text }`到“需要人类”的事件:
```bash
AF_NOTIFY_WEBHOOKS="https://hooks.slack.com/services/…" npm run web:dev:server
```
- `AF_NOTIFY_EVENTS` — 要发送哪些事件(默认为`in_review,skip_listed,supervisor_down`;还包括`failed`、`queue_empty`)。
- `AF_NOTIFY_POLL_SEC` — 轮询间隔(默认为15)。
通知程序读取活动日志,因此它会捕获来自任何进程(MCP、调度器)的代理驱动的转换,并且仅在启动后对新的事件发出警报。
### 工作区(多仓库)
任务属于**工作区** — 命名的git仓库,工作在此处进行。新数据库有一个默认的工作区(`repoPath: "."` = 代理的工作目录),因此单仓库设置需要零配置,UI不会显示工作区选项卡。
要驱动多个仓库的代理:
1. 在网页UI中创建一个工作区(**工作区**按钮):一个slug加上绝对仓库路径。
2. 在其中创建任务 — 任务表单获得一个工作区选择器,任务板获得一个过滤器和徽章,一旦存在第二个工作区。
3. 将每个代理的MCP服务器固定到其工作区:
```json
"env": {
"AGENTFACTORY_DB": "c:\\Git\\AgentFactory\\agentfactory.db",
"AGENTFACTORY_WORKSPACE": "shopfloor"
}
```
固定的工作器仅认领其自己的工作区的任务。认领的有效载荷带有`repoPath`,代理在`<repoPath>/.worktrees/<key>`下创建其每个任务的工作树。参见`packages/mcp/README.md`了解详情,包括未固定的“漫游”模式。
### 搁置认领
每次认领记录了谁认领了它以及何时认领(工作器通过`AGENTFACTORY_WORKER`识别,默认为工作区固定),在进行中的卡片上显示。如果工作器在任务中途死亡,打开任务并点击**释放认领** — 它会将整个历史记录重新排队,以便下一个认领者可以从死亡工作器停止的地方继续。
### 审查更改(差异视图)
当工作器提交具有`branch`链接的结果(约定:`feature/<key>-<kebab-title>`),任务的详细面板显示一个**更改**部分 — 更改的文件和+/-计数 — 以及一个**查看差异**按钮,打开完整的每个文件、行级差异,直接在任务板上。差异是根据工作区仓库实时计算的(与默认分支的合并基准),因此在分支点之后合并到主分支的提交永远不会污染审查。批准或请求更改,无需离开任务板。
### AI第一轮审查(建议)
审查器可以检查每个`in_review`任务的差异(实现)或交付成果(描述/计划),并使用 **`ai-review/v1`标记约定** 将其发现作为注释发布回去(标记行 + 摘要 +封闭的JSON:`{ reviewer, verdict, findings }` — 参见`docs/superpowers/specs/2026-06-12-ai-review-tier.md`)。任务板将裁决显示为卡片上的芯片(**干净** / **N个发现** / **待定** 在重新提交后),在抽屉中渲染发现为检查清单,并且**请求更改** 将已检查的发现和您自己的注释组合成一个有属性的反馈正文。未经整理的发现永远不会到达实施代理 — MCP有效载荷会剥离AI审查注释;只有您的精选反馈随重新认领而传递。批准过去的开放发现距离一个确认很近,并且会记录为覆盖。
任务板本身永远不会运行引擎 — 监督器发布裁决,并且可以互换:存储库中的 **`reviewer`** 监督器(`npm run reviewer`,默认引擎 **codex** — 参见上面的[运行审查器](#运行审查器(无人值守的AI审查))),或在存储库外部,`Run-ReviewerLoop.ps1`(`-Reviewer claude|codex`)在 **ado-bridge** 存储库中(其循环中的第三个循环旁边是`Run-AdoBridgeLoop.ps1`生产者和`Run-AgentFactoryLoop.ps1`工作器)。干净的裁决会将任务自动推进到下一阶段;发现和实施阶段会升级到人工门户。
### PR循环(推送、清理、重新打开)
工作器通过在功能分支(`feature/<key>-<kebab-title>`)上创建工作树**基于最新的默认分支**来启动每个任务 — 服务器解析基准(`origin/main`,首先获取)以确保工作始终从当前主分支开始,而不是仓库碰巧检出的内容。他们通过将该分支推送到`origin`并在`submit_result`之前删除工作树来完成 — 分支是持久记录,不会在磁盘上累积。您在任务板上审查,批准,并从已经推送的分支(GitHub,Azure DevOps — 远程上的任何内容)手动打开PR。如果PR构建失败,请将失败作为注释粘贴到任务上并点击**重新打开**(完成 -> 排队):下一个认领者获得完整的线程,在同一个分支上继续,其推送更新相同的PR。提示:启用*删除合并后的分支*,以便合并后的功能分支自行清理。
### 规格中的图像
在编写或编辑待办任务时,将截图直接粘贴到任务表单中(Ctrl+V) — 它们会在客户端缩小(最大1568px长边,模型的实际分辨率),存储在共享的SQLite中,并在任务上显示为缩略图。当代理认领任务时,图像作为**图像内容块**出现在MCP有效载荷中,因此代理看到实际的像素与规格一起。附件在任务排队后被冻结(简报在飞行途中不会更改),并且在任务删除时被删除。
### 分析
标头切换中的第三个视图(**任务板 · 列表 · 分析**)回答“我的代理循环性能如何?” — 已完成的任务、任务的中位数周期/工作时间、首次批准率、重新打开率、AI覆盖率(审查发现后的批准)、每个阶段的时间分布(实际上:人工审查队列,而不是代理)、每日吞吐量、审查往返分布、按模型或工作区(切换)的令牌,以及按工作器的表格,带有搁置释放计数。所有时间/质量指标均来自活动日志,因此它适用于从创建以来每个任务;令牌和成本是**工作器报告的**(`submit_result`上的可选`metrics`,或来自循环包装器的`POST /api/tasks/<key>/metrics`,具有确切的使用情况),而未报告的任务显示* n/a* — 永远不会是零。每个任务的抽屉还获得一个**指标**条:阶段时间线加上圆形/令牌/成本芯片。按工作区和7d/30d/all过滤。
### 令牌遥测(OpenTelemetry)
令牌使用情况会针对每个任务进行捕获,甚至包括**交互式/流式**会话和**Codex** — 调度器的stdout解析无法看到的模式。网页服务器托管一个**OTLP/HTTP(JSON)日志接收器,位于`POST /v1/logs`**;将CLI的原生OpenTelemetry导出指向它,并设置任务键,接收器会将令牌汇总到分析读取的相同`task_metric`行中。调度器在其配置中启用此功能时,会自动连接此功能(然后跳过其stdout解析以避免重复计算)。参见[`docs/token-telemetry.md`](docs/token-telemetry.md)了解Claude环境变量、Codex `config.toml`和限制。
### 实时遥测馈送
除了持久的每个任务汇总外,OTLP接收器将**每个**事件推送到一个小的内存环中,**遥测**视图(标头切换)实时渲染 — 一个包含最近事件的表格(**时间 · 任务 · 工作区 · 工作器 · 代理 · 模型 · 输入/输出令牌 · 成本**)带有代理和模型的滚动总数。这是分析的实时伴侣:观察Claude/Codex导出令牌的方式,查看哪个工作器/模型正在花费,以及捕获**未归属**事件(遥测到达时没有任务键 — 显示在这里,即使它们从任务汇总中排除)。馈送是短暂的(最后~500个事件,重启后消失);持久的指标/分析数字不受影响。
### 删除任务
打开任务并在抽屉底部使用**删除任务**(它变成红色*确认删除?* — 第二次点击删除)。任务及其整个活动/链接历史记录永久消失;没有存档。进行中的任务受到保护:首先释放认领,然后删除。删除仅限人类 — 代理没有删除工具。
### 运行测试
```bash
npm test
```