Skip to content

3. 核心架构

3.1 一句话总结

Pi 是一个 六层同心圆 的 monorepo:telemetry / tui 在最外层;pi-ai 提供统一 provider 适配;agent-core 提供基于 streamFn 注入的 runtime;session-backends 提供持久化;protocol + client + server 提供远程能力;最后 coding-agent 拼出 CLI。

3.2 主链架构图(来自 cli.ts → main.ts → sdk.ts 静态阅读)

┌─────────────────────────────────────────────────────────────────────┐
│                          用户键入   pi <args>                       │
└─────────────────────────────────┬───────────────────────────────────┘
              ┌────────────────────────────────────────┐
              │ coding-agent/src/cli.ts (21 行)         │
              │   • process.title=APP_NAME              │
              │   • env PI_CODING_AGENT=true            │
              │   • env AI_AGENT=pi                     │
              │   • configureHttpDispatcher()           │
              │   • main(argv)                          │
              └────────────────────┬───────────────────┘
              ┌────────────────────────────────────────┐
              │ coding-agent/src/main.ts (972 行)       │
              │   1. parseArgs(cli/args.ts)            │
              │   2. runAuthCommand 短路                │
              │   3. createSessionManager (8 种入口)    │
              │   4. resolveCliModel                    │
              │   5. applyHttpProxySettings             │
              │   6. dispatch by AppMode:               │
              │      interactive → InteractiveMode       │
              │      print/json  → runPrintMode         │
              │      rpc         → runRpcMode           │
              └────────────────────┬───────────────────┘
              ┌────────────────────────────────────────┐
              │ coding-agent/src/core/sdk.ts            │
              │ createAgentSession() — 真正装配点        │
              │  • ModelRuntime · SettingsManager       │
              │  • SessionManager · DefaultResourceLoader│
              │  • convertToLlm (with block_images)     │
              │  • streamFn (注入 retry/timeout/headers) │
              │  • new Agent({...})                    │
              │  • new AgentSession({...})             │
              └────────────────────┬───────────────────┘
              ┌────────────────────────────────────────┐
              │ agent-core (pi-agent-core)              │
              │  Agent class · state · agent-loop       │
              │  harness/                                │
              │   • agent-harness.ts (主循环)           │
              │   • messages / system-prompt / tools    │
              │   • session (持久化抽象)                │
              │   • skills (技能加载)                   │
              │   • search (检索索引)                   │
              │  proxy.ts · node.ts · agent-loop.ts     │
              └────────────────────┬───────────────────┘
              ┌────────────────────────────────────────┐
              │ pi-ai  +  pi-ai/compat                  │
              │  Unified LLM API                         │
              │   api/                                   │
              │    • anthropic-messages                 │
              │    • openai-responses / -codex-responses│
              │    • openai-completions                 │
              │    • google-generative-ai / -vertex     │
              │    • bedrock-converse-stream            │
              │    • mistral-conversations              │
              │    • azure-openai / pi-messages / lazy  │
              │   auth/ · providers/ · models-store     │
              │   streamSimple() · getModel() · uuidv7  │
              └────────────────────┬───────────────────┘
              ┌────────────────────────────────────────┐
              │ 模型 API(外部 HTTP / WebSocket)        │
              │  anthropic / openai / google /          │
              │  azure-openai / bedrock / mistral /     │
              │  openai-codex / openai-compat 等         │
              └─────────────────────────────────────────┘

3.3 "它解决什么问题"——叙事性回答

Pi 关心三件事:

1. 把 "模型差异" 抽象掉

每个 LLM provider 有自己的协议 / streaming 行为 / 鉴权 / thinking 控制 / token 计算方式。pi-ai 通过 streamSimple(model, context, options) 统一这些差异——调用者只需考虑:Model + Message[] + options

2. 把 "工具调用" 标准化

内建七件套工具:read / bash / edit / write / grep / find / ls。这些工具在 pi-agent-coreharness/tools/ 中以统一 Tool 接口实现。Agent 通过 agent-loop 反复迭代:模型返回 tool_call → 执行 → 把结果回灌 → 模型再判断。每步都可以被 hook / extension 切入。

3. 把 "会话" 持久化、可恢复

SessionManager 用 JSONL 持久化整棵消息树 + 分支(fork/continue/resume)。Agent.state.messages 是真相之源;session 文件只是它的镜像。

三件事合在一起

用户说一句话"修这个 bug",pi 把这句话变成"和 LLM 的几次有结构的往返",把 LLM 的工具调用变成"对工作树的文件系统操作",把这一切变成"以后能 resmue 的一个 JSONL 文件"——全程对用户可观察、可审计、可扩展。

3.4 关键设计模式(可复用)

模式 体现位置 含义
Hexagonal / Ports & Adapters streamFn 注入到 Agent Agent 不绑定 provider,只调用可替换的 stream 函数
Dependency Injection by Options CreateAgentSessionOptions(40+ 字段) 全部依赖通过对象注入;可独立单测
Hooks / Event Bus before_provider_request, after_provider_response, before_provider_headers 扩展点不污染核心
Transport Abstraction transport setting + proxy.ts 切换 LLM transport(HTTP/SSE/WebSocket)
State Machine per Session agent.state.messages + JSONL session 不可变分支(fork)
Strict Module Boundaries tools/index.tswithFileMutationQueue 工具调用并发安全
Tool Registry 三维 tools? · noTools? · excludeTools? 三层工具开关
Pinned Deps + Offline-Build min-release-age=2, build:offline 供应链抗风险
Converters convertToLlm(messages) 屏蔽 AgentMessageMessage 差异
Telemetry Schema defineTelemetrySchema() 整库 0 依赖

3.5 几个有趣的"非显然"细节

  • setDefaultStreamFn(streamSimple)coding-agent/src/core/sdk.ts 第 36 行被调用。它是为扩展可使用低层 API 路径留的兼容性口子:扩展或第三方库即使不接入 agent-core 的 streamFn,也能拿到"今天我们希望它做什么"的全局行为。
  • providerRetrySettingshttpIdleTimeoutMs 都是 settings 注入——这意味着"用户改了重试策略"会被下一次 stream 调用立刻看到,不需要重启 session
  • thinkingLevel 先 settings 取,再 model.clamp——模型不支持多档思考时会被强制降到 off
  • sessionManager.appendThinkingLevelChange(thinkingLevel) 把 thinking level 作为一个 append-only 事件写进 JSONL——这让"上次会话的 thinking 状态"无须额外字段就能恢复。