第一章:Coding Agent 概述 -- 从 Agent 到编码助手产品

对应源文件:packages/coding-agent/src/

回顾

到目前为止我们学了:

  • ai 包:统一 LLM API,发请求收响应
  • agent 包:tool-call loop 和状态管理

这两个包加起来不到 3000 行代码,提供了"通用 AI Agent"的能力。但要变成一个可用的编码助手产品,还需要大量"产品化"的工作。

coding-agent 做了什么

coding-agent 是整个项目中最大最复杂的包agent-session.ts 一个文件就有 103KB)。它在 agent 包之上增加了:

功能说明
内置工具read、write、edit、bash、grep、find、ls -- 操作文件系统的完整工具集
系统提示精心构建的 system prompt,告诉 AI 如何使用这些工具
扩展系统通过 TypeScript 扩展添加自定义工具、命令、快捷键、UI 组件
会话管理JSONL 树形结构持久化对话历史,支持分支、恢复、fork
上下文压缩当对话超出 context window 时自动摘要和压缩
多模型支持运行中切换模型,model scope 循环切换
CLI完整的命令行界面:参数解析、四种运行模式
设置系统全局 + 项目级设置,支持热加载
认证存储API key 和 OAuth token 管理
Skills可复用的 prompt 指令文件

架构总览

用户输入
    ↓
CLI (cli.ts + args.ts)
    ↓ 解析参数
main.ts
    ↓ 加载配置、创建 session
AgentSession (agent-session.ts)     ← 核心!
    ├── Agent 实例(来自 agent 包)
    ├── 内置工具(tools/)
    ├── 系统提示(system-prompt.ts)
    ├── 扩展系统(extensions/)
    ├── 会话管理(session-manager.ts)
    ├── 上下文压缩(compaction/)
    ├── 模型管理(model-registry.ts + model-resolver.ts)
    └── 设置管理(settings-manager.ts)
    ↓
运行模式
    ├── Interactive(TUI 交互界面)
    ├── Print(非交互输出)
    ├── RPC(stdin/stdout JSON-RPC)
    └── JSON(事件流输出)

四种运行模式

模式触发方式使用场景
Interactive默认(终端直接运行 pi主要使用方式,TUI 交互界面
Printpi -p "问题" 或管道输入非交互,输出结果后退出
RPCpi --rpcstdin/stdout JSONL 协议,供其他程序集成
JSONpi --json "问题"输出全部事件为 JSON lines

启动流程

main.ts 是一个 732 行的启动编排器,按顺序完成以下步骤:

1. 解析 CLI 参数(parseArgs)
2. 运行数据迁移(runMigrations)
3. 创建会话管理器(createSessionManager)
   - 根据 --session/--resume/--continue/--fork 参数选择
4. 创建运行时服务(createAgentSessionServices)
   - 加载设置(SettingsManager)
   - 加载扩展、skills、themes(ResourceLoader)
   - 构建模型注册表(ModelRegistry)
5. 创建 AgentSession
   - 装配 Agent + tools + extensions
   - 恢复历史对话
6. 读取 stdin 内容(管道输入)
7. 根据模式启动
   - Interactive → new InteractiveMode(runtime).run()
   - Print → runPrintMode(runtime)
   - RPC → runRpcMode(runtime)

关键子系统预览

AgentSession(agent-session.ts)

这是整个 coding-agent 的核心。它:

  • 创建并配置 Agent 实例
  • 注册所有内置工具和扩展工具
  • 实现 convertToLlm(把自定义消息类型转为 LLM 消息)
  • 实现 transformContext(上下文压缩的集成点)
  • 管理模型切换
  • 协调扩展系统

内置工具(tools/)

7 个核心工具覆盖了文件操作的所有方面:

工具功能代码量
read读取文件/图片,支持行范围和截断274 行
write创建/覆写文件~250 行
edit基于 search/replace 的精准编辑~400 行
bash执行 shell 命令~400 行
grep搜索文件内容(ripgrep 风格)~350 行
find查找文件(尊重 .gitignore)~320 行
ls列出目录内容~200 行

扩展系统(extensions/)

扩展是 pi 最重要的设计决策之一。几乎所有"高级功能"都通过扩展实现:

  • Sub-agent(子代理)→ 扩展
  • Plan mode(计划模式)→ 扩展
  • 权限弹窗 → 扩展(通过 beforeToolCall 钩子)
  • 自定义工具 → 扩展
  • 自定义快捷键和命令 → 扩展

扩展 API 类型定义有 53KB(1546 行),覆盖了:工具注册、命令注册、快捷键绑定、UI 组件、事件监听、会话控制等几乎所有方面。

会话管理(session-manager.ts)

对话历史以 JSONL(每行一条 JSON 记录)格式存储在 ~/.pi/agent/sessions/ 目录下。

关键设计:树形结构。每条记录有 idparentId,形成一棵树而非线性列表。这支持:

  • 分支(从历史某点创建新分支)
  • Fork(从任意位置创建新会话文件)
  • 导航(在不同分支间切换)

上下文压缩(compaction/)

当对话超出模型的 context window 时,自动触发压缩:

  1. 估算当前上下文的 token 数
  2. 找到合适的切割点
  3. 用 LLM 对旧消息生成摘要
  4. 用摘要替代旧消息
  5. 记录为 CompactionEntry 保存到 session 文件

下一步

下面几章会深入每个子系统。建议的阅读顺序:

  1. 内置工具(read + edit)→ 理解工具如何实现
  2. 系统提示 → 理解 AI 的"行为规范"
  3. 扩展系统 → 理解可扩展性设计
  4. 会话管理 → 理解持久化和分支
  5. 上下文压缩 → 理解 context overflow 的解决方案