Task 系统是 Claude Code 的后台工作管理核心,负责管理所有异步执行单元:Shell 命令、本地 Agent、远程 Agent、进程内 Teammate 和 Dream 内存整合。Coordinator 模式则在此之上提供多 Worker 编排能力,将 Claude Code 从单线程对话转变为并行任务调度器。
核心源码分布:
| 模块 | 路径 | 职责 |
|---|---|---|
| 基础类型 | src/Task.ts |
TaskType、TaskStatus、TaskStateBase 定义 |
| 任务注册表 | src/tasks.ts |
getAllTasks()、getTaskByType() |
| 联合类型 | src/tasks/types.ts |
TaskState 联合类型、isBackgroundTask 判定 |
| 框架工具 | src/utils/task/framework.ts |
registerTask、updateTaskState、pollTasks |
| 磁盘输出 | src/utils/task/diskOutput.ts |
任务输出文件管理 |
| Coordinator | src/coordinator/coordinatorMode.ts |
协调者模式系统提示与配置 |
+-----------------------------+
| AppState.tasks |
| Record<string, TaskState> |
+-------------+---------------+
|
+----------+---------+---+---+-----------+---------+
| | | | | |
LocalShell LocalAgent Remote InProcess Dream Workflow
(bash) (subagent) (cloud) (teammate) (memory) (scripts)
| | | | |
v v v v v
ShellCmd query() poll runAgent forkAgent
(local) (API) (in-proc) (consolidate)
// src/Task.ts
export type TaskType =
| 'local_bash' // Shell 命令执行
| 'local_agent' // 本地 Agent 子进程
| 'remote_agent' // 云端远程 Agent
| 'in_process_teammate' // 进程内 Teammate (Swarm)
| 'local_workflow' // 工作流脚本 (feature-gated)
| 'monitor_mcp' // MCP 监控 (feature-gated)
| 'dream' // 内存整合 (auto-dream)export type TaskStatus =
| 'pending' // 已注册,尚未启动
| 'running' // 正在执行
| 'completed' // 成功完成
| 'failed' // 执行失败
| 'killed' // 被用户/系统终止状态转换图:
pending ──> running ──> completed
├──> failed
└──> killed
isTerminalTaskStatus() 判定终态 (completed/failed/killed),终态任务不会再发生状态转换。
所有任务类型共享的基础字段:
export type TaskStateBase = {
id: string // 任务唯一 ID (前缀编码: b=bash, a=agent, r=remote, t=teammate, d=dream)
type: TaskType // 任务类型
status: TaskStatus // 当前状态
description: string // 人类可读描述
toolUseId?: string // 关联的 tool_use block ID
startTime: number // 创建时间戳
endTime?: number // 结束时间戳
totalPausedMs?: number // 总暂停时间
outputFile: string // 磁盘输出文件路径
outputOffset: number // 已上报的输出偏移量
notified: boolean // 是否已发送完成通知
}每个任务类型有独立的前缀,后跟 8 位随机字符 (36^8 约 2.8 万亿组合):
const TASK_ID_PREFIXES: Record<string, string> = {
local_bash: 'b',
local_agent: 'a',
remote_agent: 'r',
in_process_teammate: 't',
local_workflow: 'w',
monitor_mcp: 'm',
dream: 'd',
}示例: a7k2m9x3f 表示一个 local_agent 任务。
export type Task = {
name: string
type: TaskType
kill(taskId: string, setAppState: SetAppState): Promise<void>
}kill 是唯一的多态方法。spawn 和 render 各任务类型独立实现,不走统一调度。
Shell 命令后台执行,由 BashTool 的 run_in_background 参数触发。
export type LocalShellTaskState = TaskStateBase & {
type: 'local_bash'
command: string // 执行的命令
result?: { code: number; interrupted: boolean }
shellCommand: ShellCommand | null // 底层进程句柄
isBackgrounded: boolean // 是否已后台化
agentId?: AgentId // 所属 Agent (用于孤儿清理)
kind?: 'bash' | 'monitor' // UI 显示变体
lastReportedTotalLines: number // 输出增量追踪
completionStatusSentInAttachment: boolean
}关键机制:
- Stall Watchdog: 每 5 秒检查输出增长。若 45 秒无新输出且末行匹配交互式提示模式 (
(y/n),Press Enter等),自动发送<task-notification>通知模型 - 孤儿清理: Agent 退出时,
killShellTasksForAgent()终止该 Agent 名下所有 Shell 任务 - 前台/后台切换:
isBackgrounded标志控制是否显示在状态栏 pill 中
本地 Agent 子进程,是最常用的并发任务类型。
export type LocalAgentTaskState = TaskStateBase & {
type: 'local_agent'
agentId: string // Agent 唯一标识
prompt: string // 初始提示
selectedAgent?: AgentDefinition // Agent 定义
agentType: string // Agent 类型名
model?: string // 模型覆盖
abortController?: AbortController // 终止控制器
error?: string
result?: AgentToolResult // 最终结果
progress?: AgentProgress // 实时进度
isBackgrounded: boolean // 后台标志
pendingMessages: string[] // SendMessage 队列
retain: boolean // UI 持有标志 (阻止回收)
diskLoaded: boolean // 侧链加载状态
evictAfter?: number // 面板宽限期截止时间
messages?: Message[] // UI 显示用消息
}进度追踪系统:
export type AgentProgress = {
toolUseCount: number // 工具调用计数
tokenCount: number // Token 消耗
lastActivity?: ToolActivity // 最近活动
recentActivities?: ToolActivity[] // 最近 5 条活动
summary?: string // 进度摘要
}
export type ProgressTracker = {
toolUseCount: number
latestInputTokens: number // 最新输入 token (API 累计值)
cumulativeOutputTokens: number // 累计输出 token
recentActivities: ToolActivity[]
}消息队列机制: pendingMessages 数组在 tool-round 边界被 drainPendingMessages() 排空,实现 SendMessage 对运行中 Agent 的消息注入。
面板宽限期: 终态任务设置 evictAfter = Date.now() + 30_000 (PANEL_GRACE_MS),30 秒后才允许从 AppState 回收。
云端远程 Agent,通过 Teleport API 执行,支持多种远程任务类型:
export type RemoteAgentTaskState = TaskStateBase & {
type: 'remote_agent'
remoteTaskType: RemoteTaskType // 远程任务类型
remoteTaskMetadata?: RemoteTaskMetadata
sessionId: string // 远程会话 ID
command: string
title: string
todoList: TodoList // 关联的待办列表
log: SDKMessage[] // 消息日志
isLongRunning?: boolean // 长运行标志
pollStartedAt: number // 轮询起始时间
isRemoteReview?: boolean // 远程代码审查
reviewProgress?: { ... } // 审查进度
isUltraplan?: boolean // Ultraplan 标志
ultraplanPhase?: UltraplanPhase // Ultraplan 阶段
}
type RemoteTaskType = 'remote-agent' | 'ultraplan' | 'ultrareview' | 'autofix-pr' | 'background-pr'关键机制:
- 资格检查: 创建前通过
checkRemoteAgentEligibility()验证: 已登录、有远程环境、在 Git 仓库中、有 GitHub remote、已安装 Claude GitHub App - 轮询恢复:
pollStartedAt记录轮询起始,--resume恢复时从当前时刻重新计时,避免立即超时 - 完成检查器:
registerCompletionChecker()注册按 RemoteTaskType 分发的回调,每个轮询周期执行 - 元数据持久化: 通过 sidecar 文件持久化/删除远程 Agent 元数据,使会话恢复不会复活已完成任务
- Ultraplan 阶段: pill 徽标根据
ultraplanPhase显示不同状态 (running/needs_input/plan_ready)
进程内 Teammate,是 Swarm 系统的核心执行单元。与 LocalAgentTask 的关键区别:
export type InProcessTeammateTaskState = TaskStateBase & {
type: 'in_process_teammate'
identity: TeammateIdentity // 团队身份
prompt: string
model?: string
abortController?: AbortController // 终止整个 Teammate
currentWorkAbortController?: AbortController // 仅终止当前回合
awaitingPlanApproval: boolean // Plan 模式审批中
permissionMode: PermissionMode // 独立权限模式
progress?: AgentProgress
messages?: Message[] // UI 显示用 (上限 50 条)
pendingUserMessages: string[] // 用户消息注入队列
isIdle: boolean // 空闲状态 (等待工作)
shutdownRequested: boolean // 关闭请求标志
onIdleCallbacks?: Array<() => void> // 空闲回调 (避免轮询)
}
export type TeammateIdentity = {
agentId: string // "researcher@my-team"
agentName: string // "researcher"
teamName: string
color?: string
planModeRequired: boolean
parentSessionId: string
}内存管理:
// 消息 UI 缓冲上限 50 条 -- 鲸鱼会话 9a990de8 在 2 分钟内启动 292 个 agent 达到 36.8GB
export const TEAMMATE_MESSAGES_UI_CAP = 50生命周期特点:
- 双层 AbortController:
abortController杀死整个 Teammate,currentWorkAbortController仅终止当前回合 - 空闲/活跃切换:
isIdle标志配合onIdleCallbacks实现高效等待,无需轮询 - Plan 模式:
awaitingPlanApproval+planModeRequired实现写代码前的审批流程
内存整合任务,对应 auto-dream 功能。纯 UI 展示层,让隐形的 fork agent 在状态栏可见。
export type DreamTaskState = TaskStateBase & {
type: 'dream'
phase: 'starting' | 'updating' // 简单两阶段
sessionsReviewing: number // 审查的会话数
filesTouched: string[] // 已触及的文件路径
turns: DreamTurn[] // 最近 30 个回合
abortController?: AbortController
priorMtime: number // 整合锁回滚用
}
export type DreamTurn = {
text: string
toolUseCount: number
}杀死 DreamTask 时,通过 rollbackConsolidationLock(priorMtime) 回滚锁的 mtime,使下次会话可以重试。
主会话后台化任务,复用 LocalAgentTaskState 结构,以 agentType: 'main-session' 标记区分。
当用户按 Ctrl+B 两次时,当前会话被后台化:
- 查询继续在后台运行
- UI 清空为新提示符
- 完成时发送
<task-notification>
export type LocalMainSessionTaskState = LocalAgentTaskState & {
agentType: 'main-session'
}isPanelAgentTask() 过滤器排除 main-session 任务,使其不出现在 Coordinator 面板中。
// src/utils/task/framework.ts
// 注册新任务到 AppState
function registerTask(task: TaskState, setAppState: SetAppState): void
// 类型安全的状态更新
function updateTaskState<T extends TaskState>(
taskId: string,
setAppState: SetAppState,
updater: (task: T) => T, // 返回同一引用则跳过更新
): voidregisterTask 的智能合并: 若任务已存在 (resume 场景),保留 retain、startTime、messages、diskLoaded、pendingMessages 等 UI 状态。
// 主轮询循环,由框架每秒调用
async function pollTasks(
getAppState: () => AppState,
setAppState: SetAppState,
): Promise<void>
// 生成任务附件 (增量输出 + 终态回收)
async function generateTaskAttachments(state: AppState): Promise<{
attachments: TaskAttachment[]
updatedTaskOffsets: Record<string, number>
evictedTaskIds: string[]
}>回收策略:
- 延迟回收: 终态 + notified 的任务在下一轮
generateTaskAttachments时被标记为可回收 - 主动回收:
evictTerminalTask()允许立即回收,但受面板宽限期约束 - TOCTOU 防护:
applyTaskOffsetsAndEvictions()在 FRESH prev.tasks 上操作,避免并发状态转换被覆盖
任务完成通知通过 XML 格式的 <task-notification> 发送:
<task-notification>
<task-id>{taskId}</task-id>
<tool-use-id>{toolUseId}</tool-use-id>
<task-type>{taskType}</task-type>
<output-file>{outputPath}</output-file>
<status>completed|failed|killed</status>
<summary>Task "description" completed successfully</summary>
</task-notification>每个任务类型自行管理通知发送,通过 enqueuePendingNotification() 入队。notified 标志的原子性 check-and-set 防止重复通知。
// src/tasks/stopTask.ts
async function stopTask(
taskId: string,
context: { getAppState, setAppState },
): Promise<{ taskId: string; taskType: string; command: string | undefined }>流程: 查找任务 -> 验证运行中 -> 调用 taskImpl.kill() -> 标记已通知 (Shell 特殊处理: 抑制 exit code 137 噪音通知)
任务输出文件存储在会话隔离的临时目录中:
{projectTempDir}/{sessionId}/tasks/{taskId}
安全措施: 使用 O_NOFOLLOW 防止 symlink 攻击。输出上限 5GB (MAX_TASK_OUTPUT_BYTES)。
Agent 可用工具通过多层过滤:
function filterToolsForAgent({
tools,
isBuiltIn, // 内置 Agent 有更宽松的工具限制
isAsync, // 异步 Agent 仅允许 ASYNC_AGENT_ALLOWED_TOOLS
permissionMode, // plan 模式允许 ExitPlanMode
}): Tools过滤层级:
- MCP 工具 (
mcp__前缀) 始终允许 ALL_AGENT_DISALLOWED_TOOLS全局黑名单CUSTOM_AGENT_DISALLOWED_TOOLS自定义 Agent 额外黑名单ASYNC_AGENT_ALLOWED_TOOLS异步 Agent 白名单- Swarm Teammate 特殊例外: 允许 AgentTool (同步子 Agent) 和
IN_PROCESS_TEAMMATE_ALLOWED_TOOLS
当 FORK_SUBAGENT feature flag 启用时,省略 subagent_type 会触发 fork:
export const FORK_AGENT = {
agentType: 'fork',
tools: ['*'], // 继承父级全部工具
model: 'inherit', // 继承父级模型 (保持 cache)
permissionMode: 'bubble', // 权限冒泡到父终端
source: 'built-in',
}Fork 与 Coordinator 互斥: isForkSubagentEnabled() 在 Coordinator 模式下返回 false。
防递归: isInForkChild() 检测对话历史中的 fork boilerplate tag,阻止 fork 子进程再次 fork。
AgentTool.call()
|
+--> resolveAgentTools() # 解析工具集
+--> runAgent() # 创建子 Agent 上下文
|
+--> createSubagentContext() # 隔离上下文
+--> registerTask() # 注册到 AppState
+--> query() # 执行 API 调用循环
| |
| +--> (stream events) --> updateProgressFromMessage()
| +--> recordSidechainTranscript() # 侧链持久化
|
+--> enqueueAgentNotification() # 完成通知
+--> evictTaskOutput() # 清理输出文件
通过 SendMessageTool,可以向运行中的 Agent 发送后续消息:
// SendMessageTool 对 local_agent 的处理:
// 1. 通过 queuePendingMessage() 入队
// 2. 在 tool-round 边界由 drainPendingMessages() 排空
// 3. Agent 将排空的消息作为新用户消息处理
// 也可通过 resumeAgentBackground() 恢复已完成的 Agent// src/coordinator/coordinatorMode.ts
export function isCoordinatorMode(): boolean {
// 需要 COORDINATOR_MODE build feature + 环境变量
return feature('COORDINATOR_MODE') &&
isEnvTruthy(process.env.CLAUDE_CODE_COORDINATOR_MODE)
}会话恢复时通过 matchSessionMode() 自动切换:
function matchSessionMode(
sessionMode: 'coordinator' | 'normal' | undefined,
): string | undefined
// 若当前模式与存储模式不匹配,翻转环境变量Coordinator 模式完全替换标准系统提示,定义了一套独立的交互模型:
角色定位: 编排器,不是执行器。直接回答简单问题,复杂任务交给 Worker。
可用工具:
| 工具 | 用途 |
|---|---|
| Agent | 创建新 Worker |
| SendMessage | 续接现有 Worker |
| TaskStop | 终止运行中的 Worker |
| subscribe/unsubscribe_pr_activity | GitHub PR 事件订阅 |
Worker 工具集上下文:
function getCoordinatorUserContext(
mcpClients: ReadonlyArray<{ name: string }>,
scratchpadDir?: string,
): { [k: string]: string }注入内容包括:
- Worker 可用工具列表 (普通模式: ASYNC_AGENT_ALLOWED_TOOLS; simple 模式: Bash+Read+Edit)
- MCP 服务器列表
- Scratchpad 目录路径 (跨 Worker 持久化知识)
Coordinator 系统提示定义了标准四阶段工作流:
+-------------------+ +-------------------+ +-------------------+ +-------------------+
| Research | --> | Synthesis | --> | Implementation | --> | Verification |
| (Workers 并行) | | (Coordinator) | | (Workers) | | (Workers) |
| | | 读取发现,理解问题, | | 按规格执行变更 | | 运行测试,检查类型 |
| 调查代码库 | | 编写实施规格 | | | | |
+-------------------+ +-------------------+ +-------------------+ +-------------------+
并发规则:
- 只读任务 (研究): 自由并行
- 写入任务 (实现): 每组文件同时只有一个 Worker
- 验证任务: 可与不同文件区域的实现并行
Worker 结果以 <task-notification> XML 作为 user-role 消息交付:
<task-notification>
<task-id>{agentId}</task-id>
<status>completed|failed|killed</status>
<summary>{human-readable status summary}</summary>
<result>{agent's final text response}</result>
<usage>
<total_tokens>N</total_tokens>
<tool_uses>N</tool_uses>
<duration_ms>N</duration_ms>
</usage>
</task-notification>Coordinator 必须区分用户消息和 task-notification (通过 <task-notification> 开头标签判定)。
const INTERNAL_WORKER_TOOLS = new Set([
'TeamCreate',
'TeamDelete',
'SendMessage',
'SyntheticOutput',
])
// 这些工具从 Worker 可见工具列表中过滤掉Coordinator 系统提示强调最重要的设计原则: 永远不要委托理解。
反模式:
"Based on your findings, fix the auth bug" // 把理解推给 Worker
正确模式:
"Fix the null pointer in src/auth/validate.ts:42. The user field
on Session is undefined when sessions expire but the token remains
cached. Add a null check before user.id access." // 具体到文件、行号、原因
续接 vs 新建的决策矩阵:
| 场景 | 机制 | 原因 |
|---|---|---|
| 研究刚好覆盖需编辑的文件 | SendMessage 续接 | Worker 已有文件上下文 |
| 研究范围广但实现范围窄 | 新建 Agent | 避免探索噪音 |
| 修正失败或扩展近期工作 | 续接 | Worker 有错误上下文 |
| 验证其他 Worker 的代码 | 新建 Agent | 独立审视 |
| 首次实现方向完全错误 | 新建 Agent | 错误上下文会锚定重试 |
// src/utils/swarm/teamHelpers.ts
export type TeamFile = {
name: string
description?: string
createdAt: number
leadAgentId: string
leadSessionId?: string // Leader 的真实 session UUID
teamAllowedPaths?: TeamAllowedPath[]
members: Array<{
agentId: string // "researcher@my-team"
name: string
agentType?: string
model?: string
prompt?: string
color?: string
planModeRequired?: boolean
joinedAt: number
tmuxPaneId: string
cwd: string
subscriptions: string[]
isActive?: boolean
}>
}团队文件存储在磁盘,通过 readTeamFile() / writeTeamFileAsync() 读写。会话清理时由 registerTeamForSessionCleanup() 注册的钩子自动删除。
三种执行后端,通过 TeammateExecutor 接口抽象:
// src/utils/swarm/backends/types.ts
export type BackendType = 'tmux' | 'iterm2' | 'in-process'| 后端 | 隔离方式 | 通信方式 | 适用场景 |
|---|---|---|---|
| tmux | 独立 tmux pane | 文件邮箱 | 终端环境,可视化多 Agent |
| iterm2 | iTerm2 split pane | 文件邮箱 | macOS iTerm2 用户 |
| in-process | AsyncLocalStorage | 文件邮箱 + AppState | 无外部依赖,资源共享 |
后端检测与降级:
iTerm2 检测 -> iTerm2 可用? -> 使用 iTerm2 Backend
|
v (否)
tmux 检测 -> tmux 可用? -> 使用 tmux Backend
|
v (否)
in-process Fallback
spawnInProcessTeammate()
|
+--> createTeammateContext() # AsyncLocalStorage 隔离
+--> generateTaskId('t') # t 前缀 ID
+--> registerTask() # 注册到 AppState
+--> startInProcessTeammate() # 启动执行循环
|
+--> inProcessRunner.ts # 主循环
|
+-- 读取 pending messages / mailbox
+-- 调用 query() API
+-- 更新 progress
+-- 检查 shutdownRequested
+-- 转 idle 等待新消息
Swarm 中的消息类型:
// SendMessageTool 的消息格式
const StructuredMessage = z.discriminatedUnion('type', [
z.object({ type: z.literal('shutdown_request'), reason: z.string().optional() }),
z.object({ type: z.literal('shutdown_response'), request_id, approve, reason }),
z.object({ type: z.literal('plan_approval_response'), request_id, approve, feedback }),
])消息路由:
- 定向消息:
to: "researcher"-> 发送到指定 Teammate - 广播消息:
to: "*"-> 发送到所有 Teammate - Agent 续接:
to: "{agentId}"-> 如果 target 是 local_agent,用resumeAgentBackground()恢复 - UDS 对等:
to: "uds:<socket-path>"-> 本地 Unix socket 对等通信 - Bridge 对等:
to: "bridge:<session-id>"-> Remote Control 对等通信
// TeamCreateTool 创建流程:
// 1. 检查是否已在团队中 (一个 leader 只能管理一个团队)
// 2. 生成唯一团队名 (冲突时用 word slug)
// 3. 创建 team-lead agent ID: "team-lead@{teamName}"
// 4. 写入 TeamFile 到磁盘
// 5. 注册清理钩子
// 6. 重置任务列表 (Team = Project = TaskList)
// 7. 更新 AppState.teamContext
// TeamDeleteTool 清理流程:
// 1. 检查是否有活跃非 leader 成员
// 2. 如有活跃成员,拒绝删除 (需先 requestShutdown)
// 3. 清理团队目录和 worktree
// 4. 清除颜色分配
// 5. 清除 AppState.teamContext创建结构化任务项 (非后台任务,而是任务列表中的项目):
// 输入
{ subject: string, description: string, activeForm?: string, metadata?: Record }
// 输出
{ task: { id: string, subject: string } }与 TodoWrite 是不同系统: TaskCreate 管理的是 Swarm 团队共享的任务列表 (tasks/ 目录),TodoWrite 管理的是 Claude 自身的待办列表。
统一的任务终止工具:
// 输入 (兼容旧版 KillShell)
{ task_id?: string, shell_id?: string }
// 流程: validateInput -> stopTask() -> kill + markNotified这些工具用于 Swarm 团队内部的任务协调:
- TaskOutput: 读取任务输出 (大文件,65KB)
- TaskGet: 获取单个任务详情
- TaskList: 列出所有任务
- TaskUpdate: 更新任务状态 (status, notes 等)
// src/tasks/pillLabel.ts
function getPillLabel(tasks: BackgroundTaskState[]): stringPill 文本根据任务类型和数量动态生成:
| 类型 | 单个 | 多个 |
|---|---|---|
| local_bash | "1 shell" | "3 shells" |
| local_bash (monitor) | "1 monitor" | "2 monitors" |
| local_agent | "1 local agent" | "3 local agents" |
| remote_agent | "diamond 1 cloud session" | "diamond 3 cloud sessions" |
| remote_agent (ultraplan) | "diamond ultraplan" / "diamond ultraplan ready" / "diamond ultraplan needs your input" | - |
| in_process_teammate | "1 team" (按团队计数) | "2 teams" |
| dream | "dreaming" | - |
| 混合 | "N background tasks" | - |
底部状态栏组件,显示 Teammate 圆点和任务状态:
- 过滤
isBackgroundTask()为 true 的任务 - 排除
isPanelAgentTask()为 true 的 Coordinator 面板任务 - Teammate 入口按
startTime排序 - 支持水平滚动 (终端宽度不够时)
每种任务类型有独立的详情对话框:
| 文件 | 对应任务 |
|---|---|
ShellDetailDialog.tsx |
LocalShellTask |
AsyncAgentDetailDialog.tsx |
LocalAgentTask |
RemoteSessionDetailDialog.tsx |
RemoteAgentTask |
InProcessTeammateDetailDialog.tsx |
InProcessTeammateTask |
DreamDetailDialog.tsx |
DreamTask |
BackgroundTasksDialog.tsx |
总览对话框 (Shift+Down) |
// src/components/tasks/taskStatusUtils.tsx
function getTaskStatusIcon(status, options?): string
// running: play, completed: tick, failed/killed: cross
// idle: ellipsis, awaitingApproval: questionMark, shutdownRequested: warning
function getTaskStatusColor(status, options?): 'success'|'error'|'warning'|'background'
function describeTeammateActivity(t): string
// shutdownRequested -> 'stopping'
// awaitingPlanApproval -> 'awaiting approval'
// isIdle -> 'idle'
// 否则 -> 最近活动摘要 / 'working'// isBackgroundTask 判定条件:
// 1. status === 'running' || status === 'pending'
// 2. isBackgrounded !== false (默认视为后台)
function isBackgroundTask(task: TaskState): task is BackgroundTaskState主会话通过 foregroundMainSessionTask() 实现前台化: 将目标任务的 isBackgrounded 设为 false,之前的前台任务恢复为 true。
所有任务通过 registerCleanup() 注册进程退出清理回调。Agent 任务额外注册 perfetto tracing 代理。
任务系统通过 enqueueSdkEvent() 发射结构化事件给 SDK 消费者:
// 任务启动
{ type: 'system', subtype: 'task_started', task_id, tool_use_id, description, task_type }
// 任务终止 (通过 emitTaskTerminatedSdk)
{ type: 'system', subtype: 'task_terminated', task_id, status, summary }Coordinator 模式可选启用 Scratchpad 目录:
// Worker 可以在此目录无需权限提示地读写
// 用于跨 Worker 的持久化知识共享
`Scratchpad directory: ${scratchpadDir}`+----------------------------------------------------------+
| 用户交互层 |
| BackgroundTaskStatus | DetailDialogs | PillLabel |
+------+---------------------+-----------------------------+
| |
v v
+------+--------+ +--------+--------+
| AppState | | Coordinator |
| .tasks{} | | System Prompt |
| .teamContext | | Worker dispatch |
+------+--------+ | Synthesis |
| +--------+--------+
| |
+------+---------------------+-----------------------------+
| Task Framework Layer |
| registerTask | updateTaskState | pollTasks | evict |
+------+-----+-----+-----+-----+-----+-----+--------------+
| | | | | | |
v v v v v v v
Shell Agent Remote Teammate Dream Workflow Monitor
| | | | |
v v v v v
Process query API In-proc forkAgent
spawn loop poll runner consolidate
核心设计特点:
- 不可变状态更新: 所有
updateTaskState返回新对象,===相等时跳过更新 - 原子通知:
notified标志的 check-and-set 防止重复通知 - TOCTOU 防护: offset/eviction 在 fresh state 上操作
- 内存安全: Teammate 消息上限 50 条,面板宽限期 30 秒后回收
- 安全隔离: 输出文件 O_NOFOLLOW 防 symlink 攻击,session ID 隔离目录