03.3 任务系统
关注源码
src/Task.tssrc/tasks/*src/utils/task/framework.tssrc/utils/task/diskOutput.ts
为什么要有任务层
一旦工具调用不再是瞬时完成,就需要统一表示:
- 谁在后台运行
- 输出落在哪里
- 何时通知主会话
- 何时可以中止或回收
任务层就是为此存在的统一 substrate。
Task.ts 定义了最小公共协议
公共字段包括:
idtypestatusdescriptionoutputFileoutputOffsetnotifiedstartTime/endTime
同时定义了统一的 TaskType,当前覆盖:
local_bashlocal_agentremote_agentin_process_teammatelocal_workflowmonitor_mcpdream
主要任务实现
LocalShellTask
负责本地 shell 命令的长时执行、输出持久化和 kill。
LocalAgentTask
负责后台 agent:
- 记录 transcript
- 聚合 tool use/token 进度
- 维护 foreground/background 状态
- 支持
SendMessage追加消息
RemoteAgentTask
负责远端 agent 会话和本地可见状态的衔接。
InProcessTeammateTask
负责 swarms/teammates 这种协作执行单元。
framework.ts 提供的统一能力
utils/task/framework.ts 负责:
registerTaskupdateTaskStatepollTasks- 输出 offset 维护
- terminal task eviction
- task notification 入队
最关键的是它把“任务输出来自磁盘、状态来自内存”这两个通道统一起来了。
为什么输出要落盘
任务不是普通消息,因为它们可能:
- 持续很久
- 输出很多
- 暂时不在前台视图里
- 需要被 resume / 远端查看
因此每个任务都有 outputFile,而不是只把输出塞进 AppState 数组里。
任务与主消息流怎么连接
任务不会直接强耦合到对话框,而是通过:
- XML 风格 task notification attachment
messageQueueManagerTaskOutputTool
重新回到主消息流。这让模型和 UI 都可以“看见后台结果”。
设计上的关键点
1. 任务是第一类对象
系统并不假设一切都在前台串行完成。后台 agent、shell、remote 都有正式建模。
2. 任务输出和任务状态分离
状态在内存里快速更新,输出在磁盘上持续累积,这能兼顾性能和持久化。
3. framework 处理通用生命周期,具体任务只负责业务差异
这样新增任务类型时,不需要重写一套通知、轮询、offset、回收逻辑。