<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Effect TS on AI博士 万戈</title>
        <link>https://www.yesmiracle.net/tags/effect-ts/</link>
        <description>AI博士万戈的技术博客，聚焦 Agentic AI、AI Infra 与 Agent Security，分享 AI 基础设施与工程落地实践。</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-cn</language>
        <managingEditor>admin@yesmiracle.net (万戈)</managingEditor>
        <webMaster>admin@yesmiracle.net (万戈)</webMaster>
        <lastBuildDate>Sun, 19 Jul 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://www.yesmiracle.net/tags/effect-ts/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>OpenCode 源码深度拆解：Effect TS 代数效应系统构建的智能编码 Agent</title>
        <link>https://www.yesmiracle.net/post/20260719-opencode-architecture/</link>
        <pubDate>Sun, 19 Jul 2026 00:00:00 +0000</pubDate>
        <author>admin@yesmiracle.net (万戈)</author>
        <guid>https://www.yesmiracle.net/post/20260719-opencode-architecture/</guid>
        <description>&lt;img src="https://www.yesmiracle.net/post/20260719-opencode-architecture/cover.svg" alt="Featured image of post OpenCode 源码深度拆解：Effect TS 代数效应系统构建的智能编码 Agent" /&gt;&lt;p&gt;在读完 Grok Build 的 Rust 巨构和 Pi Agent 的 Steering 双队列之后，今天来看第三个编码 Agent——&lt;strong&gt;OpenCode&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;OpenCode 由 SST/Anomaly 团队开发，是一个 TypeScript monorepo，2499 个 TS 源文件，20+ 个独立包。它的技术栈选择非常激进：&lt;strong&gt;Effect TS&lt;/strong&gt; 不是「用了一下」，而是深嵌在每一层代码的核心。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TL;DR：OpenCode 的「四轴 LLM 路由」和「Schema First 协议层」设计，是三者中最工程化的。如果你追求代码的可测试性和架构的可维护性，OpenCode 的代码最值得读。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一monorepo-全景&#34;&gt;一、Monorepo 全景&lt;/h2&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;packages/
├── opencode/    # 主 CLI Agent —— 双 Agent 系统 (build + plan)
├── core/        # 核心运行时 —— Session, Tool, Config, Permission
├── protocol/    # HTTP API 协议层 —— Effect HttpApi
├── server/      # 服务器实现
├── tui/         # 终端 UI
├── schema/      # 浏览器安全的序列化合约
├── plugin/      # 插件系统（V2 Effect 版 + V1 Promise 版）
├── llm/         # LLM 集成 —— 四轴路由体系
├── console/     # 桌面应用
└── web/         # Web 前端
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;对比前两篇的架构规模：&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;项目&lt;/th&gt;
          &lt;th&gt;源文件数&lt;/th&gt;
          &lt;th&gt;语言&lt;/th&gt;
          &lt;th&gt;包数&lt;/th&gt;
          &lt;th&gt;核心设计哲学&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;Grok Build&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;2804 .rs&lt;/td&gt;
          &lt;td&gt;Rust&lt;/td&gt;
          &lt;td&gt;50+ crate&lt;/td&gt;
          &lt;td&gt;编译期类型安全 + Actor 模型&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;OpenCode&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;2499 .ts&lt;/td&gt;
          &lt;td&gt;TypeScript&lt;/td&gt;
          &lt;td&gt;20+ 包&lt;/td&gt;
          &lt;td&gt;Effect TS 代数效应 + Schema First&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;Pi Agent&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;859 .ts&lt;/td&gt;
          &lt;td&gt;TypeScript&lt;/td&gt;
          &lt;td&gt;5 包&lt;/td&gt;
          &lt;td&gt;事件驱动 + 分层抽象&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&#34;二effect-ts不是用了是深嵌&#34;&gt;二、Effect TS：不是「用了」，是「深嵌」&lt;/h2&gt;
&lt;p&gt;OpenCode 对 Effect TS 的使用深度，是我见过的 TypeScript 项目中最彻底的。&lt;/p&gt;
&lt;h3 id=&#34;21-contextservice-依赖注入&#34;&gt;2.1 Context.Service 依赖注入&lt;/h3&gt;
&lt;p&gt;每一层都通过 &lt;code&gt;Context.Tag&lt;/code&gt; 声明服务接口：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// packages/opencode/src/session/llm.ts
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;LLM&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;extends&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Context&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Tag&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;session/LLM&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;LLM&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    { &lt;span style=&#34;color:#a6e22e&#34;&gt;stream&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;input&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;StreamInput&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Effect&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;StreamResult&lt;/span&gt;&amp;gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;() {}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;22-effectgen-代数效应&#34;&gt;2.2 Effect.gen 代数效应&lt;/h3&gt;
&lt;p&gt;核心逻辑用 &lt;code&gt;Effect.gen&lt;/code&gt; 编写，而不是 &lt;code&gt;async/await&lt;/code&gt;：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;program&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Effect&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;gen&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; () {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;llm&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;yield&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;LLM&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;session&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;yield&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Session&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;result&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;yield&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;llm&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;stream&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;input&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;yield&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;session&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;save&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;result&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;23-schema-优先验证&#34;&gt;2.3 Schema 优先验证&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;packages/schema/&lt;/code&gt; 定义了所有数据结构的 Schema，运行时验证 + 编译时类型推导：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;AgentInfo&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Schema&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Struct&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;Schema.String&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;mode&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;Schema.Literals&lt;/span&gt;([&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;subagent&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;primary&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;all&amp;#34;&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;permission&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;PermissionV1.Ruleset&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;24-为什么这很重要&#34;&gt;2.4 为什么这很重要？&lt;/h3&gt;
&lt;p&gt;对比 Grok Build 的 Rust 方案：Rust 的类型系统在&lt;strong&gt;编译期&lt;/strong&gt;保证正确性，Effect TS 的 Schema 在&lt;strong&gt;运行时&lt;/strong&gt;保证正确性。两者达到的最终效果类似——数据结构不会在管道中变形——但路径完全不同。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;三四轴-llm-路由体系&#34;&gt;三、四轴 LLM 路由体系&lt;/h2&gt;
&lt;p&gt;这是 OpenCode 最独特的架构设计。&lt;code&gt;packages/llm/&lt;/code&gt; 将 LLM 调用拆成四个正交维度：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Protocol  → 协议层（OpenAI Chat、Anthropic Messages、Google Gemini...）
Endpoint → 端点层（api.openai.com、api.anthropic.com、自定义代理...）
Auth     → 认证层（API Key、OAuth、Bearer Token...）
Framing  → 框架层（AI SDK、原生 HTTP、流式/非流式...）
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;31-protocol-复用&#34;&gt;3.1 Protocol 复用&lt;/h3&gt;
&lt;p&gt;多个 Provider 共享同一个 Protocol 实现：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 同一个 OpenAIChat.protocol 被多个 provider 复用
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;deepseek&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;OpenAIChat&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;protocol&lt;/span&gt;({ &lt;span style=&#34;color:#a6e22e&#34;&gt;baseURL&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://api.deepseek.com&amp;#34;&lt;/span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;together&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;OpenAIChat&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;protocol&lt;/span&gt;({ &lt;span style=&#34;color:#a6e22e&#34;&gt;baseURL&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://api.together.xyz&amp;#34;&lt;/span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;fireworks&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;OpenAIChat&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;protocol&lt;/span&gt;({ &lt;span style=&#34;color:#a6e22e&#34;&gt;baseURL&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://api.fireworks.ai&amp;#34;&lt;/span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;openai&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;OpenAIChat&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;protocol&lt;/span&gt;({ &lt;span style=&#34;color:#a6e22e&#34;&gt;baseURL&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://api.openai.com/v1&amp;#34;&lt;/span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;对比 Pi Agent 的 30+ Provider：Pi 为每个 provider 写一个适配文件，而 OpenCode 只需要写一个 &lt;code&gt;OpenAIChat.protocol&lt;/code&gt;，然后通过配置不同的 baseURL 复用。&lt;strong&gt;这是架构抽象层次的差异。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&#34;32-requestexecutor-重试逻辑&#34;&gt;3.2 RequestExecutor 重试逻辑&lt;/h3&gt;
&lt;p&gt;在 &lt;code&gt;packages/llm/src/&lt;/code&gt; 中，&lt;code&gt;RequestExecutor&lt;/code&gt; 封装了完整的重试策略：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;指数退避 + 抖动&lt;/li&gt;
&lt;li&gt;按错误类型分类（4xx 不重试，5xx 重试，429 限速重试）&lt;/li&gt;
&lt;li&gt;请求超时控制&lt;/li&gt;
&lt;li&gt;流式响应中断恢复&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对比 Grok Build 的 &lt;code&gt;xai-grok-sampler&lt;/code&gt;：Grok Build 的 samper 有三层架构（SamplingClient → stream → SamplerHandle），重试逻辑在 &lt;code&gt;retry.rs&lt;/code&gt; 中，支持 &lt;code&gt;doom_loop&lt;/code&gt; 检测。OpenCode 的 RequestExecutor 功能类似但更轻量。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;四双-agent-架构build-vs-plan&#34;&gt;四、双 Agent 架构：build vs plan&lt;/h2&gt;
&lt;p&gt;OpenCode 内置了两个 Agent，定义在 &lt;code&gt;packages/opencode/src/agent/agent.ts&lt;/code&gt; 中：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;AgentInfo&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Schema&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Struct&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;Schema.String&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;description&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;Schema.optional&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;Schema&lt;/span&gt;.String),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;mode&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;Schema.Literals&lt;/span&gt;([&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;subagent&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;primary&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;all&amp;#34;&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;permission&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;PermissionV1.Ruleset&lt;/span&gt;,  &lt;span style=&#34;color:#75715e&#34;&gt;// 权限系统
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Agent&lt;/th&gt;
          &lt;th&gt;模式&lt;/th&gt;
          &lt;th&gt;权限&lt;/th&gt;
          &lt;th&gt;用途&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;build&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;primary&lt;/td&gt;
          &lt;td&gt;完整文件读写&lt;/td&gt;
          &lt;td&gt;开发工作&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;plan&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;primary&lt;/td&gt;
          &lt;td&gt;只读&lt;/td&gt;
          &lt;td&gt;代码分析、探索&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;两者通过 &lt;code&gt;Tab&lt;/code&gt; 键在 TUI 中切换。核心差异只是 &lt;code&gt;permission&lt;/code&gt; 级别不同——&lt;strong&gt;同一个 Agent Loop，不同的权限配置&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;对比 Grok Build：Grok Build 的 &lt;code&gt;AgentDefinition&lt;/code&gt; 系统更复杂，除了 permission 还支持 &lt;code&gt;prompt_mode&lt;/code&gt;、&lt;code&gt;completion_requirement&lt;/code&gt;、&lt;code&gt;toolset&lt;/code&gt; 等配置，通过 &lt;code&gt;AgentBuilder&lt;/code&gt; 构建。&lt;/p&gt;
&lt;p&gt;对比 Pi Agent：Pi 没有内置的多 Agent 概念，但通过扩展系统可以实现。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;五session-架构v2-的持久化改革&#34;&gt;五、Session 架构：V2 的持久化改革&lt;/h2&gt;
&lt;p&gt;OpenCode 的 Session 系统在 &lt;code&gt;packages/opencode/src/session/&lt;/code&gt; 下，约 24 个文件。V2 版本引入了 &lt;strong&gt;Durable Prompt Admission&lt;/strong&gt; 模式：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;SessionV2.prompt(input)
  ├── durable admission: 将 prompt 持久化到 SQLite
  ├── schedule wake: 通知 SessionRunner 有新工作
  └── return sessionID
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;关键设计&lt;/strong&gt;：prompt 在发送给 LLM 之前先持久化。即使进程崩溃，prompt 不会丢失。&lt;/p&gt;
&lt;h3 id=&#34;51-session-处理循环processor&#34;&gt;5.1 Session 处理循环（Processor）&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;processor.ts&lt;/code&gt; 是实现 Agent 循环的核心——一个&lt;strong&gt;事件驱动的状态机&lt;/strong&gt;：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;create(input) → LLM.Service.stream(input) → handleEvent(event)
  ├── reasoning-start → 管理推理过程
  ├── tool-call-start → 执行工具调用
  ├── tool-result → 处理工具结果
  ├── text-delta → 文本增量更新
  └── error → 错误处理
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;52-双运行时策略&#34;&gt;5.2 双运行时策略&lt;/h3&gt;
&lt;p&gt;OpenCode 同时支持两种 LLM 运行时：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;AI SDK 路径&lt;/strong&gt;（默认）：通过 Vercel AI SDK 调用&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Native LLM 路径&lt;/strong&gt;（新）：通过 &lt;code&gt;native-runtime.ts&lt;/code&gt; 直接调用&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;双运行时通过 &lt;code&gt;session/llm.ts&lt;/code&gt; 中的 &lt;code&gt;LLM.Service&lt;/code&gt; 统一管理，根据配置自动选择。这种渐进式迁移策略——先通过成熟 SDK 上线，再逐步替换为原生实现——是工程化团队的典型做法。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;六插件系统v1--v2-双轨制&#34;&gt;六、插件系统：V1 + V2 双轨制&lt;/h2&gt;
&lt;p&gt;OpenCode 的插件系统在 &lt;code&gt;packages/plugin/&lt;/code&gt; 中，同时维护两套 API：&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;版本&lt;/th&gt;
          &lt;th&gt;架构&lt;/th&gt;
          &lt;th&gt;使用场景&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;V1 (Promise)&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;简单的 &lt;code&gt;() =&amp;gt; Promise&amp;lt;void&amp;gt;&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;快速原型、简单插件&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;V2 (Effect)&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;Effect 的 Context/Layer/Scope&lt;/td&gt;
          &lt;td&gt;复杂插件、生产环境&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;V2 插件支持 20+ 生命周期钩子：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;onSessionStart&lt;/code&gt; / &lt;code&gt;onSessionEnd&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;onToolCall&lt;/code&gt; / &lt;code&gt;onToolResult&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;onPromptBuild&lt;/code&gt; / &lt;code&gt;onPromptComplete&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;onError&lt;/code&gt; / &lt;code&gt;onConfigLoad&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对比 Pi Agent 的扩展系统：Pi 的扩展机制更丰富（注册工具、命令、UI 组件），但 OpenCode 的插件系统在&lt;strong&gt;类型安全&lt;/strong&gt;上更好——Effect 的 Context 保证了插件依赖在编译期可验证。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;七和-grok-build-的深层对比&#34;&gt;七、和 Grok Build 的深层对比&lt;/h2&gt;
&lt;h3 id=&#34;71-哲学差异&#34;&gt;7.1 哲学差异&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;维度&lt;/th&gt;
          &lt;th&gt;Grok Build (Rust)&lt;/th&gt;
          &lt;th&gt;OpenCode (Effect TS)&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;正确性保证&lt;/td&gt;
          &lt;td&gt;编译期类型系统&lt;/td&gt;
          &lt;td&gt;运行时 Schema 验证&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;并发模型&lt;/td&gt;
          &lt;td&gt;Tokio Actor + mpsc&lt;/td&gt;
          &lt;td&gt;Effect Fiber + Scope&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;错误处理&lt;/td&gt;
          &lt;td&gt;Result + thiserror&lt;/td&gt;
          &lt;td&gt;Effect.Either + Cause&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;依赖注入&lt;/td&gt;
          &lt;td&gt;手动 Resource 注入&lt;/td&gt;
          &lt;td&gt;Context.Service 自动&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;协议层&lt;/td&gt;
          &lt;td&gt;ACP (Gateway + Session)&lt;/td&gt;
          &lt;td&gt;Effect HttpApi&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;72-工具系统&#34;&gt;7.2 工具系统&lt;/h3&gt;
&lt;p&gt;Grok Build 的 &lt;code&gt;ToolBridge&lt;/code&gt; + &lt;code&gt;FinalizedToolset&lt;/code&gt; 通过类型安全的 Resource 注入管理工具依赖。OpenCode 的工具注册通过 &lt;code&gt;Tool.Registry&lt;/code&gt; 的 Effect Service 实现。两者都在做同一件事——&lt;strong&gt;让工具不依赖全局状态&lt;/strong&gt;——但 Grok Build 的 Rust 版本在编译期保证，而 OpenCode 在运行时保证。&lt;/p&gt;
&lt;h3 id=&#34;73-mcp-集成&#34;&gt;7.3 MCP 集成&lt;/h3&gt;
&lt;p&gt;Grok Build 有完整的 &lt;code&gt;xai-grok-mcp&lt;/code&gt; crate，支持 Streamable HTTP 和子进程两种传输，OAuth 认证，Managed MCP 自动刷新。OpenCode 的 MCP 支持在 &lt;code&gt;packages/plugin/src/v2/&lt;/code&gt; 中，通过插件系统实现。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;八三篇编码-agent-的横向对比&#34;&gt;八、三篇编码 Agent 的横向对比&lt;/h2&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;维度&lt;/th&gt;
          &lt;th&gt;Grok Build&lt;/th&gt;
          &lt;th&gt;OpenCode&lt;/th&gt;
          &lt;th&gt;Pi Agent&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;语言&lt;/td&gt;
          &lt;td&gt;Rust&lt;/td&gt;
          &lt;td&gt;TypeScript/Effect&lt;/td&gt;
          &lt;td&gt;TypeScript&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;包数&lt;/td&gt;
          &lt;td&gt;50+ crate&lt;/td&gt;
          &lt;td&gt;20+ 包&lt;/td&gt;
          &lt;td&gt;5 包&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;文件数&lt;/td&gt;
          &lt;td&gt;2804&lt;/td&gt;
          &lt;td&gt;2499&lt;/td&gt;
          &lt;td&gt;859&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;会话模式&lt;/td&gt;
          &lt;td&gt;5 状态 + ACP 协议&lt;/td&gt;
          &lt;td&gt;Durable SQLite&lt;/td&gt;
          &lt;td&gt;JSONL 树形 + 分支&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;工具系统&lt;/td&gt;
          &lt;td&gt;ToolBridge 资源注入&lt;/td&gt;
          &lt;td&gt;Effect Service 注册&lt;/td&gt;
          &lt;td&gt;定义优先双层注册&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Provider&lt;/td&gt;
          &lt;td&gt;少（委托 xAI）&lt;/td&gt;
          &lt;td&gt;四轴路由&lt;/td&gt;
          &lt;td&gt;30+ Provider&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;验证系统&lt;/td&gt;
          &lt;td&gt;✅ Skeptic + Goal&lt;/td&gt;
          &lt;td&gt;❌&lt;/td&gt;
          &lt;td&gt;❌&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;权限系统&lt;/td&gt;
          &lt;td&gt;✅ 完整&lt;/td&gt;
          &lt;td&gt;✅ Ruleset&lt;/td&gt;
          &lt;td&gt;❌ 容器化&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;子 Agent&lt;/td&gt;
          &lt;td&gt;进程内 1 层&lt;/td&gt;
          &lt;td&gt;❌ 未知&lt;/td&gt;
          &lt;td&gt;RPC 进程级&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;协议&lt;/td&gt;
          &lt;td&gt;ACP&lt;/td&gt;
          &lt;td&gt;Effect HttpApi&lt;/td&gt;
          &lt;td&gt;❌ CLI 原生&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;MCP&lt;/td&gt;
          &lt;td&gt;✅ 完整&lt;/td&gt;
          &lt;td&gt;✅ 插件化&lt;/td&gt;
          &lt;td&gt;❌&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&#34;写在最后&#34;&gt;写在最后&lt;/h2&gt;
&lt;p&gt;OpenCode 的代码质量是三者中最高的。Effect TS 的选择让它的架构非常干净——&lt;strong&gt;每一层都有明确的边界，每个依赖都有显式的声明&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;但代价也很明显：学习曲线陡峭。如果你不熟悉 Effect TS，读 OpenCode 的代码会非常吃力。而 Grok Build 的 Rust 代码虽然复杂，但 Rust 类型系统的表现力让代码「自文档化」程度更高。&lt;/p&gt;
&lt;p&gt;如果你对 Effect TS 的代数效应系统在工程中的落地感兴趣，OpenCode 是最值得读的参考实现。它的「四轴 LLM 路由」和「Schema First 协议层」设计，是面向未来的 Agent 架构方向。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;相关阅读：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.yesmiracle.net/20260719-grok-build-open-source/&#34; &gt;Grok Build 开源！万字拆解 40 万行 Rust 构建的 AI Coding Agent 内部架构&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.yesmiracle.net/20260719-pi-agent-architecture/&#34; &gt;Pi Agent 深度拆解：TypeScript 多包架构下的 Steering + Follow-up 双队列设计&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;GitHub: &lt;a class=&#34;link&#34; href=&#34;https://github.com/sst/opencode&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/sst/opencode&lt;/a&gt;&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
