Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

32 - tasks 模块源码分析

路径: src/tasks/ 文件数: 12 个 功能: 后台任务管理 — 7 种任务类型的完整生命周期管理


模块概述

tasks/ 实现了 Claude Code 的后台任务系统,使用 discriminated union 架构统一管理 7 种任务类型。每种任务类型有独立的状态接口、类型守卫、React 组件和生命周期函数。


架构总览

TaskState (discriminated union)
├── LocalShellTask      — 本地 Shell 命令 (type: 'local_bash')
├── LocalAgentTask      — 本地子 Agent (type: 'local_agent')
├── RemoteAgentTask     — 远程 Agent (type: 'remote_agent')
├── InProcessTeammate   — 进程内队友 (type: 'in_process_teammate')
├── LocalMainSession    — 本地主会话后台化 (type: 'local_main_session')
├── DreamTask           — 后台推理/记忆整合 (type: 'dream')
└── MonitorMcpTask      — MCP 监控 (type: 'monitor_mcp')

核心文件

1. types.ts — 类型统一

行数: 47 行

// 所有任务类型的 discriminated union
type TaskState =
  | LocalShellTaskState
  | LocalAgentTaskState
  | RemoteAgentTaskState
  | InProcessTeammateTaskState
  | LocalMainSessionTaskState
  | DreamTaskState
  | MonitorMcpTaskState

// 后台任务(运行中或待处理 + 已后台化)
type BackgroundTaskState = TaskState

function isBackgroundTask(task: TaskState): boolean {
  return (task.status === 'running' || task.status === 'pending')
    && task.isBackgrounded
}

2. stopTask.ts — 任务终止

行数: 101 行

导出

  • StopTaskError — 自定义错误类
  • stopTask(appState, taskId) — 通用任务终止函数

逻辑

async function stopTask(appState: AppState, taskId: string): Promise<void> {
  // 1. 验证任务存在且正在运行
  const task = findTask(appState, taskId)
  if (!task) throw new StopTaskError('Task not found')
  if (task.status !== 'running') throw new StopTaskError('Task not running')

  // 2. 调用任务特定的 kill 实现
  await task.kill()

  // 3. Shell 任务: 抑制 exit code 137 的噪音通知
  if (isLocalShellTask(task) && task.exitCode === 137) {
    suppressNotification(task)
  }

  // 4. 发送 SDK 事件
  emitTaskTerminatedSdk(task)
}

3. pillLabel.ts — 任务标签 UI

行数: 83 行

功能

为底部状态栏的后台任务药丸标签生成紧凑文本。

// 类型特定标签
"1 shell"       // 1 个 Shell 任务
"2 teams"       // 2 个队友任务
"◇ ultraplan"   // ultraplan 阶段(空心钻石 = 等待输入)
"◆ ultraplan"   // ultraplan 阶段(实心钻石 = 计划就绪)

任务类型详解

4. DreamTask — 后台推理/记忆整合

行数: 158 行

功能

在用户不活跃时,AI 在后台进行记忆整合和推理。

状态

interface DreamTaskState extends TaskStateBase {
  type: 'dream'
  phase: DreamPhase        // 'starting' | 'updating'
  turns: DreamTurn[]       // 最近 30 轮(用于实时显示)
  touchedFiles: string[]   // 通过 Edit/Write 触及的文件
}

生命周期

registerDreamTask()
    ↓
phase: 'starting'
    ↓ (首次工具调用)
phase: 'updating'
    ↓ (追踪 EdWrite 的文件)
addDreamTurn(turn)  // 保留最近 30 轮
    ↓
completeDreamTask() 或 failDreamTask()

清理

注册到 cleanup 系统,通过 AbortController 处理中止。


5. LocalMainSessionTask — 主会话后台化

行数: 480 行

功能

支持用户按 Ctrl+B 两次将当前主会话查询后台化,继续在前台进行新对话。

关键设计

// 任务 ID 使用 's' 前缀(vs Agent 的 'a' 前缀)
const taskId = 's' + generateId()

// 隔离的 transcript 文件,防止 /clear 后损坏
const transcriptFile = createIsolatedTranscript()

生命周期

用户按 Ctrl+B 两次
    ↓
registerMainSessionTask()
    ├── 创建隔离 transcript
    ├── 保存当前消息上下文
    └── 启动后台查询
    ↓
后台运行中...
    ↓
foregroundMainSessionTask()  // 用户选择前台化
    ├── 恢复消息到主对话
    └── 继续交互

6. InProcessTeammateTask — 进程内队友

行数: 122 行 (types) + 126 行 (component)

功能

支持多个 AI Agent 在同一进程内协作(Swarm 模式)。

身份系统

interface TeammateIdentity {
  agentId: AgentId
  agentName: string
  teamName: string
  color: string                // UI 区分颜色
  planModeRequired: boolean    // 是否需要计划模式审批
  parentSessionId: string
}

消息上限

const TEAMMATE_MESSAGES_UI_CAP = 50

// 防止 36.8GB 内存膨胀
function appendCappedMessage(messages: Message[], msg: Message): Message[] {
  if (messages.length >= TEAMMATE_MESSAGES_UI_CAP) {
    return [...messages.slice(1), msg]  // FIFO
  }
  return [...messages, msg]
}

隔离机制

  • 使用 AsyncLocalStorage 实现并发 Agent 隔离
  • 邮箱消息系统用于 Agent 间通信
  • 优雅关闭:处理待处理消息后再停止

7. LocalShellTask — Shell 命令执行

行数: 42 行 (guards) + 77 行 (kill) + 522 行 (component)

卡住检测

const STALL_THRESHOLD = 45_000  // 45 秒
const STALL_CHECK_INTERVAL = 5_000  // 每 5 秒检查

function isShellTaskStalled(task: LocalShellTaskState): boolean {
  // 检测交互式提示模式
  const interactivePatterns = [
    /\(y\/n\)/,
    /\[y\/n\]/,
    /Press any key|Enter password/,
  ]
  return task.lastOutputAge > STALL_THRESHOLD
    || interactivePatterns.some(p => p.test(task.lastOutput))
}

任务种类

type BashTaskKind = 'bash' | 'monitor'

// bash: 标准命令,有完成通知
// monitor: 流式输出,无完成通知(如 tail -f)

僵尸进程清理

// 防止 10 天僵尸进程
function killShellTasksForAgent(agentId: AgentId): void {
  // 终止该 Agent 的所有 Shell 任务
  // 清除排队的通知
  // 驱逐任务输出缓存
}

8. LocalAgentTask — 本地子 Agent

行数: 682 行

功能

管理本地子 Agent 执行,包括进度追踪、消息队列和磁盘输出。

进度追踪

interface ProgressTracker {
  inputTokens: number
  outputTokens: number
  cacheReadTokens: number
  toolActivities: ToolActivity[]  // 工具活动列表
  startTime: number
  lastActivityTime: number
}

interface ToolActivity {
  toolName: string
  description: string
  timestamp: number
}

消息队列

// 后台 Agent 的消息队列
function appendMessageToLocalAgent(taskId: string, message: Message): void
function drainPendingMessages(taskId: string): Message[]

磁盘输出

// 输出写入磁盘文件,带驱逐策略
// 防止内存膨胀
const outputFile = createTempFile(`agent-${taskId}.jsonl`)

9. RemoteAgentTask — 远程 Agent

行数: 855 行(最大的任务文件)

远程任务类型

type RemoteTaskType =
  | 'remote-agent'     // 通用远程 Agent
  | 'ultraplan'        // 超级计划
  | 'ultrareview'      // 超级审查
  | 'autofix-pr'       // 自动修复 PR
  | 'background-pr'    // 后台 PR

前置条件检查

registerRemoteAgentTask()
    ↓
前置条件验证:
  ├── 用户已登录?
  ├── 远程环境可用?
  ├── 在 Git 仓库中?
  ├── 有 GitHub 远程?
  └── GitHub App 已安装?
    ↓
全部通过 → 创建远程会话
任一失败 → 显示错误 + 修复指导

Ultraplan 阶段追踪

// Ultraplan 有特殊的阶段状态
type UltraplanPhase =
  | 'needs_input'   // 等待用户输入(◇ 空心钻石)
  | 'plan_ready'    // 计划就绪(◆ 实心钻石)
  | 'executing'     // 执行中

元数据持久化

// 元数据保存到会话 sidecar 文件
// 支持跨会话恢复远程任务状态
persistMetadata(taskId, { remoteSessionId, status, phase })

通用设计模式

1. TaskStateBase 基础接口

interface TaskStateBase {
  id: string
  type: string
  status: 'pending' | 'running' | 'completed' | 'failed' | 'killed'
  isBackgrounded: boolean
  startTime: number
  endTime?: number
  error?: string
}

2. 每种任务类型的标准导出

// 类型守卫
export function isXxxTask(task: TaskState): task is XxxTaskState

// 生命周期函数
export function registerXxxTask(params): void
export function backgroundXxxTask(taskId): void
export function foregroundXxxTask(taskId): void

// React 组件
export function XxxTask(props): JSX.Element

3. AbortController 取消机制

所有长时间运行的任务都使用 AbortController,支持优雅取消。

4. 清理注册

所有任务注册到 cleanup 系统,确保进程退出时资源被正确释放。


模块依赖关系

tasks/
├── types.ts ← 所有任务状态类型
├── stopTask.ts ← 通用终止逻辑
├── pillLabel.ts ← UI 标签
│
├── DreamTask/ ← 后台推理
├── LocalMainSessionTask/ ← 主会话后台化
├── InProcessTeammateTask/ ← 队友协作
│   ├── types.ts
│   └── InProcessTeammateTask.tsx
├── LocalShellTask/ ← Shell 命令
│   ├── guards.ts
│   ├── killShellTasks.ts
│   LocalShellTask.tsx
├── LocalAgentTask/ ← 本地 Agent
│   └── LocalAgentTask.tsx
└── RemoteAgentTask/ ← 远程 Agent
    └── RemoteAgentTask.tsx