codev / docs /coordinator /goals-auto-mode.md
chenbhao's picture
chore: docs v1.0
eeeb2b6
|
Raw
History Blame Contribute Delete
8.14 kB
# 目标系统与自动模式
## Goal 系统
Goal(目标)系统允许用户通过 `/goal <objective>` 命令设定一个长期目标,让 Agent 在多个对话轮次中持续追寻该目标,直至完成、受阻或暂停。
### 状态机
Goal 的生命周期由以下状态构成:
```
pursuing → paused → achieved / blocked
→ usage-limited / budget-limited
```
- **pursuing(追寻中)**:初始状态,Agent 正在积极地朝目标推进。
- **paused(已暂停)**:用户使用 `/goal pause` 暂停自动续跑,可用 `/goal resume` 恢复。
- **achieved(已完成)**:Agent 认定目标已完全达成。需经过严格的完成审计(Completion Audit)。
- **blocked(已阻塞)**:Agent 遇到无法继续的障碍,需要用户介入。
- **usage-limited / budget-limited**:因 token 预算或费用限制而停止。
### 核心文件
| 文件 | 路径 | 用途 |
|------|------|------|
| goal.tsx | `src/commands/goal/goal.tsx` | `/goal` 命令的 JSX 实现(React Ink 渲染) |
| index.ts | `src/commands/goal/index.ts` | 命令注册入口 |
| goal.ts | `src/utils/goal.ts` | 工具函数:构建续跑提示、状态格式化 |
| useGoalAutoContinue.ts | `src/hooks/useGoalAutoContinue.ts` | React Hook:在每轮对话结束后自动注入续跑提示 |
### 持续提示
`buildContinuationPrompt()`(定义于 `src/utils/goal.ts`)在每轮自动续跑时注入完整的上下文提示,包含:
- **目标描述**`<objective>` XML 标签包裹)
- **续跑行为指导**:保持目标完整性,不允许缩小范围
- **基于证据的工作原则**:依赖当前工作区状态而非对话记忆
- **完成审计要求**:必须逐项验证所有需求
- **阻塞审计规则**:连续 3 轮相同阻塞条件才允许标记 blocked
`useGoalAutoContinue` hook(`src/hooks/useGoalAutoContinue.ts`)监听 `QueryGuard` 状态:
- 当查询从活跃(running)转为空闲(idle)时触发
- 仅在 goal 状态为 `pursuing` 且非 plan 模式时注入
- 自动清理旧目标的排队续跑,防止冲突
- 每次续跑递增 `continuationCount`
### 完成审计(Completion Audit)
Agent 在决定标记目标为 `achieved` 前,必须执行严格的完成审计:
1. 从目标描述中推导具体的、可验证的需求
2. 不重新定义成功标准——保留原始范围
3. 对每个需求,检查当前状态中的权威证据
4. 确认证据足以证明完成,而非仅未发现未完成的工作
5. 只有在当前证据能够经受逐项审查时,才标记为已达成
### Blocked 审计
防止 Agent 过早放弃的机制(`src/utils/goal.ts``BLOCKED_AUDIT_TURNS = 3`):
- 阻塞条件必须连续出现 **至少 3 轮** 才能标记 blocked
- 用户恢复已阻塞的目标后,阻塞审计重置
- 仅在确实无法推进、需要用户输入或外部状态变更时才使用
- 不因任务困难、缓慢或需要澄清而标记 blocked
### 预算跟踪
`checkTokenBudget()`(定义于 `src/query/tokenBudget.ts`)根据 token 消耗决定是否继续自动续跑:
- 使用 `createBudgetTracker()` 跟踪每次续跑的 token 消耗
- `COMPLETION_THRESHOLD = 0.9`:token 消耗达到预算的 90% 时停止
- `DIMINISHING_THRESHOLD = 500`:连续 3 次续跑且每次增量 < 500 token 时视为收益递减
- 返回 `continue``stop` 决策
---
## Auto Mode(自动模式)
### 激活方式
- 用户通过 `/goal <objective>` 设置目标后自动进入自动模式
- Plan 模式下自动模式被禁用(`inPlanMode` 检查)
### 自动续跑机制
每次 Agent 响应完成后,`useGoalAutoContinue` hook 自动向命令队列注入 `[goal] Continue` 提示:
```typescript
const prompt = buildContinuationPrompt(goal, now)
enqueue({
mode: 'prompt',
value: prompt,
priority: 'later',
isMeta: true,
})
```
- 只在 `pursuing` 状态下触发
- 跳过 plan 模式
- 用户输入优先于自动续跑(有阻塞性用户输入时不注入)
- 避免为同一目标重复排队
### update_goal 工具
Agent 可通过 `update_goal` 工具报告进度:
- `status='complete'`:目标达成,停止续跑
- `status='blocked'`:受阻,需用户介入
- 调用时必须包含 `goal_id`(与目标 ID 匹配)
### 目标管理命令
| 命令 | 功能 |
|------|------|
| `/goal <objective>` | 设置新目标(若已有活跃目标则提示覆盖确认) |
| `/goal set <objective>` | 同上 |
| `/goal pause` | 暂停当前目标 |
| `/goal resume` | 恢复被暂停的目标(重置续跑计数和预算窗口) |
| `/goal edit <new objective>` | 编辑目标描述 |
| `/goal clear` | 清除当前目标 |
| `/goal`(无参数) | 查看当前目标状态 |
---
## 查询循环(query.ts)
### queryLoop() 主循环
`src/query.ts` 中的 `queryLoop()` 是 Agent 的核心执行循环,在 `QueryEngine.ts` 中被调用。每次迭代处理一个完整的模型调用周期:
```
模型调用 → 流式响应处理 → 工具执行 → stop hooks → 继续决策
```
1. **模型调用**`queryModelWithStreaming()` 发送消息到 API
2. **流处理**:处理 `content_block_start/delta` 事件
3. **工具执行**:检测 `tool_use` 并执行
4. **stop hooks**:执行 `handleStopHooks()`(记忆提取、自动 dream、prompt 建议等)
5. **继续决策**:检查是否需要继续循环(工具调用、max_output_tokens 恢复、goal 续跑)
### max_output_tokens 恢复
当模型响应被 `max_output_tokens` 截断时,queryLoop 提供最多 **3 次** 恢复尝试(`MAX_OUTPUT_TOKENS_RECOVERY_LIMIT`):
1. 注入恢复提示,指导模型从中断处继续
2. 若 8K 默认输出限制触发,自动升级到 64K(一次,`tengu_otk_slot_v1` 功能门控)
3. 恢复尝试耗尽后,将错误信息输出给用户
相关变量(`src/query.ts`):
- `maxOutputTokensRecoveryCount`:当前恢复尝试次数
- `MAX_OUTPUT_TOKENS_RECOVERY_LIMIT = 3`:最大恢复次数
- `ESCALATED_MAX_TOKENS`:升级后的输出 token 上限
### Reactive Compaction
当上下文超出 API 限制时自动触发压缩:
- `hasAttemptedReactiveCompact`:防止在同一轮迭代中重复压缩
- 上下文超时(prompt-too-long)触发的压缩流程
- 压缩后保持 stop hooks 的阻塞错误处理
- 保留反应式压缩保护(不因 stop hook 错误而重置,防止无限循环)
---
## Task 系统
Task(任务)系统管理 Agent 派发的异步子任务。
### Task 类型
定义于 `src/Task.ts`
| 类型 | 标识 | 用途 |
|------|------|------|
| `local_bash` | `b` | 本地 Shell 命令执行 |
| `local_agent` | `a` | 本地子 Agent |
| `remote_agent` | `r` | 远程 Agent |
| `in_process_teammate` | `t` | 进程内队友 |
| `local_workflow` | `w` | 本地工作流脚本 |
| `dream` | `d` | 记忆整理任务 |
| `monitor_mcp` | `m` | MCP 监控 |
### 状态
```
pending → running → completed / failed / killed
```
- `pending`:等待分配
- `running`:正在执行
- `completed`:正常完成
- `failed`:执行失败
- `killed`:被终止
### 后台/前台任务
任务系统区分前台任务(阻塞用户交互)和后台任务(在后台运行),但 Task 类型本身不区分配置字段;区分体现在调用上下文中。
### 任务 ID 生成
`generateTaskId()``src/Task.ts`)生成格式为 `{类型前缀}{8位随机字母数字}` 的 ID:
- 使用 `randomBytes(8)` 生成安全随机数
- 36 进制字母表(数字 + 小写字母)
- 36^8 ≈ 2.8 万亿种组合,抗暴力枚举
### stopTask(优雅终止)
Task 的 `kill()` 方法实现优雅终止,每个 Task 类型提供独立的 `kill` 实现(`src/tasks.ts`):
```typescript
export type Task = {
name: string
type: TaskType
kill(taskId: string, setAppState: SetAppState): Promise<void>
}
```
### 任务注册
`src/tasks.ts` 中的 `getAllTasks()` 收集所有可用 Task:
- 始终注册:`LocalShellTask`, `LocalAgentTask`, `RemoteAgentTask`, `DreamTask`
- 条件注册(通过 feature gate):`LocalWorkflowTask`, `MonitorMcpTask`