最近在给团队内部做 omp 技术栈分享,被问到三个问题:
- oh-my-pi 用了哪些基础组件?
- “pi-coding-agent” 和 “pi-sdk” 是两个东西吗?
- 它和上游 pi 是什么关系?fork 了多少?自创了多少?
翻完 monorepo 之后发现这三个问题其实是同一件事的不同切面。这篇文章把它们合并回答。
TL;DR
- 依赖栈:Bun runtime + TypeScript + Rust(~55k 行)+ 自研 19 个 workspace 包 + 第三方覆盖 LLM/TUI/协议/前端/浏览器自动化/本地推理/文档解析。
- “pi-sdk” 不是独立包:它就是
pi-coding-agent自己的程序化 API 表面(./sdk、./session/*、./modes/*、./main),CLI 和 SDK 是同一个包。 - oh-my-pi 是 pi-mono 的 fork + selective backport:上游 7 个 npm 包里 fork 了 5 个(
pi-ai、pi-agent-core、pi-tui、pi-coding-agent、pi-utils),丢了 3 个(pi-mom、pi-web-ui、pi-pods),并自创了一整套独占层(pi-natives、pi-catalog、pi-mnemopi、pi-wire、hashline、omp-stats、snapcompact、swarm-extension+pi-shellRust 内核)。 - 三 scope 等价:
@oh-my-pi/*(canonical)、@mariozechner/*(上游原名)、@earendil-works/*(中间 fork)写哪个都解析到同一份宿主内置代码。
一、依赖栈全景
1.1 运行时 / 构建
| 组件 | 用途 | 证据 |
|---|---|---|
| Bun 1.3.14+ | 包管理 + 运行时 + 测试 + 打包 + 单文件编译 | packageManager: [email protected] |
| TypeScript 6 | 类型检查(用 bun check,不用 tsc) | @typescript/native-preview: 7.0.0-dev... |
| Vite 8 | collab-web 开发/构建 | catalog: vite ^8.0.16 |
| Biome 2.4 | Lint + 格式(取代 ESLint+Prettier) | @biomejs/biome: ^2.4.16 |
| ts-morph 28 | 代码生成 | ts-morph: ^28.0.0 |
| @babel/* | AST 解析/转换(parser/traverse/generator/types) | ^7.29.7 |
1.2 自研 monorepo 包(19 个,统一 v16.2.7)
packages/coding-agent/AGENTS.md 明确 coding-agent/ 是 primary focus。其余 18 个按职责:
| 包 | 职责 |
|---|---|
pi-coding-agent | 主 CLI(焦点) |
pi-ai | 多 provider LLM 客户端(流式) |
pi-agent-core | agent runtime + 工具调用 + 状态管理 |
pi-catalog | 模型目录(models.json + 解析器) |
pi-tui | TUI 库(差分渲染) |
pi-utils | logger / streams / 环境变量 / 临时文件 |
pi-natives | Node 端原生绑定 |
pi-wire | wire 协议(protobuf) |
pi-mnemopi | 记忆子系统(Hindsight) |
hashline / snapcompact / omp-stats | 工具包 |
swarm-extension | 多 agent 协作 |
collab-web | Solid+React Web 协作 UI |
terminal-bench | 基准测试 |
typescript-edit-benchmark | TS edit benchmark |
1.3 Rust 内核(~55k 行)
Cargo.toml workspace 包含 crates/pi-* + crates/vendor/*:
pi-natives—napi-rs原生绑定,JS 可调用的 grep / 文本 / 图像操作pi-shell—crates/vendor/brush-core+brush-builtins(POSIX shell,vendoreduutils/brush)- release profile 严格:
opt-level=3、lto=fat、panic=unwind(napi-rs 需要捕获 panic 转 JS error)
1.4 TUI / 终端
@xterm/headless6.0 — 终端模拟器ghostty-web0.4 — Web 终端chalk5.6 — 颜色winston3.19 +winston-daily-rotate-file5.0 — 日志(写到~/.omp/logs/)
1.5 协议 / Schema
@bufbuild/protobuf+protoc-gen-es2.12 — pi-wire 协议(.proto→ TS)zod4 +arktype2.2 — 运行时 schema 校验@agentclientprotocol/sdk0.25 — Agent Client Protocol(让 Zed 等编辑器驱动 omp)
1.6 本地模型 / AI
@huggingface/transformers4.2 — 本地 transformer 模型onnxruntime-node1.26 — ONNX 推理fastembed2.1 — 本地 embeddingsherpa-onnx1.13 + 平台包 — 本地 ASR(whisper)@opentelemetry/*2.x — 链路追踪(OTLP)
1.7 文档 / 内容解析
| 库 | 用途 |
|---|---|
mammoth 1.12 | .docx → HTML |
mupdf 1.27 | PDF 解析/渲染 |
marked 18 | Markdown 渲染 |
turndown 7.2 + turndown-plugin-gfm | HTML → MD |
@mozilla/readability 0.6 | 文章正文提取 |
fast-xml-parser 5.9 | XML |
linkedom 0.18 | DOM 解析 |
1.8 文件编辑 / 工具
@oh-my-pi/hashline— 基于 hashline 文件寻址的 edit(README 章节 “11 · Hashline: edit by content hash”)diff9.0 — diff 算法regexp-tree0.1.27 — 正则 ASThandlebars4.7 — prompt 模板(.md+ hbs,永不内联字符串)lru-cache11.5 — 缓存fflate0.8.3 — 压缩
1.9 浏览器自动化
puppeteer-core25.1(打了patches/[email protected])@puppeteer/browsers3.0.4
1.10 前端(collab-web)
- React 19.2.7 +
react-dom+react-chartjs-2 - Solid.js 1.9 +
vite-plugin-solid(部分页面) - Tailwind CSS 4.3(
@tailwindcss/vite+@tailwindcss/node) - chart.js 4.5 — 图表
lucide-react1.17 — 图标date-fns4.4
1.11 关键设计约定(来自 AGENTS.md)
这些不是依赖、但影响整个技术栈:
- 无
any;无 inline imports;ES#private字段 - prompts 走
.md+ Handlebars,永不内联字符串 - 日志用
logger,禁console.*(保护 TUI 渲染) - Worker 通过
cli.ts单入口(__omp_worker_*隐藏 argv 派发)— 无独立 worker entry,二进制不会断 - 所有依赖集中在
package.json的workspaces.catalog(Bun catalog)— 一处升级,全 workspace 同步
二、关于 “pi-sdk” 的误解
2.1 真相:没有 pi-sdk 这个包
grep pi-sdk 全仓库,结果是 packages/coding-agent/test/sdk-*.test.ts 文件名前缀,里面 “sdk” 是 “以 SDK 方式测试 pi-coding-agent” 的简称,不是包名。
真正的入口是 packages/coding-agent/src/index.ts —— pi-coding-agent 自己就是 SDK,SDK 和 CLI 是同一个包:
| |
2.2 你可能在想的是这三个
| 名字 | 实际是什么 | 在哪 |
|---|---|---|
@oh-my-pi/pi-coding-agent (16.2.7) | CLI + SDK 二合一。bin.omp 是 CLI;./sdk、./session/*、./modes/* 是程序化 API | packages/coding-agent/ |
@oh-my-pi/pi-agent-core | 纯 runtime SDK(无 CLI / 无 I/O)— pi-coding-agent 自己用它,也对外暴露 | packages/agent/ |
@agentclientprotocol/sdk (0.25.0) | 第三方 ACP 协议 SDK,不是 pi-* | npm 上游 |
2.3 pi-coding-agent 作为 SDK 的入口长这样
packages/coding-agent/examples/sdk/ 有 15 个示例:
| |
另外 examples/extensions/ 和 examples/hooks/ 是写 Extension / Hook 插件 的入口,用的是 CustomToolFactory、ExtensionAPI、HookAPI 类型。
结论:之前以为 “pi-sdk” 是和 pi-coding-agent 并列的另一个包,顺序反了。
pi-coding-agent包本身就是 SDK,只是顺带也提供了ompCLI 入口。
三、oh-my-pi 与 pi 的血缘
3.1 pi 是什么
pi-mono = badlogic/pi-mono,作者 @mariozechner(Mario Zechner)。一个 modular 的 LLM agent toolkit,最初发布 scope 是 @mariozechner/*,后来也有 @earendil-works/*。
上游 monorepo 公开 7 个 npm 包(来源:badlogic-pi-mono.mintlify.app/concepts/packages):
| 上游包 | 职责 |
|---|---|
@mariozechner/pi-ai | 多 provider LLM 统一 API(OpenAI/Anthropic/Google/Vertex/Bedrock + 50+ 模型) |
@mariozechner/pi-agent-core | 有状态 agent runtime + 工具调用 + 事件流 |
@mariozechner/pi-tui | 差分渲染的 TUI 框架(line-diff / box-diff / full) |
@mariozechner/pi-coding-agent | 交互式 coding agent CLI |
@mariozechner/pi-mom | Slack bot |
@mariozechner/pi-web-ui | Web chat 组件 |
@mariozechner/pi-pods | vLLM GPU pod 管理 |
3.2 Single Source of Truth:legacy-pi-compat.ts
packages/coding-agent/src/extensibility/plugins/legacy-pi-compat.ts:161-178 是事实源头:
| |
含义:
- 插件无论写
@mariozechner/pi-coding-agent还是@earendil-works/pi-coding-agent,都被 shim 重写到宿主内置的同一份@oh-my-pi/pi-coding-agent PI_PACKAGE_NAMES里 6 个包都是宿主内置(plugin 即使在node_modules里装了同名包,也不会真正用它的代码)
3.3 血缘分类
✅ 直接 fork 上游的 pi-* 包
| oh-my-pi 包 | 上游来源 |
|---|---|
@oh-my-pi/pi-ai | @mariozechner/pi-ai |
@oh-my-pi/pi-agent-core | @mariozechner/pi-agent-core |
@oh-my-pi/pi-tui | @mariozechner/pi-tui |
@oh-my-pi/pi-coding-agent | @mariozechner/pi-coding-agent(主包) |
@oh-my-pi/pi-utils | @mariozechner/pi-utils(上游文档没列在 7 个主包里但存在,porting-from-pi-mono.md:50 显式列入映射表) |
@oh-my-pi/pi-natives | omp 自创——Rust napi-rs 绑定(上游没有),但 shim 也把它放进 PI_PACKAGE_NAMES,兼容老插件的 import |
➕ omp 自创的 pi-* 命名包(shim 不重写)
| 包 | 作用 | 对应 README 章节 |
|---|---|---|
@oh-my-pi/pi-catalog | 模型目录扩展(40+ providers vs 上游 50 模型) | 隐含在 README “40+ providers” |
@oh-my-pi/pi-mnemopi | Hindsight 记忆子系统(retain / recall / 压缩会话) | “13 · Hindsight” |
@oh-my-pi/pi-wire | protobuf 协议层,collab relay 用 | 隐含在 “07 · /collab” |
➕ omp 自创的非 pi- 命名包
| 包 | 作用 |
|---|---|
@oh-my-pi/hashline | “11 · Hashline: edit by content hash” |
@oh-my-pi/omp-stats | 本地 omp stats 可观测性面板 |
@oh-my-pi/snapcompact | 上下文 snap-compact |
@oh-my-pi/swarm-extension | subagent 协作(05 · First-class subagents) |
❌ 上游有但 omp 没继承
| 上游包 | omp 的替代方案 |
|---|---|
pi-mom(Slack bot) | 无 —— omp 不做 Slack 集成 |
pi-web-ui(Web chat UI) | collab-web workspace 包替代(Solid+React,omp 自建,带 relay + QR) |
pi-pods(vLLM pod 管理) | 无 |
🦀 Rust 内核 —— omp 独有
Cargo.toml:1 workspace 包含 crates/pi-* + crates/vendor/*,不是 pi-mono 的一部分:
pi-natives(napi-rs 绑定,导出给 JS)pi-shell= vendoredbrush-core+brush-builtins(POSIX shell,替代 bash)—— 来自uutils/brush- ~55k 行 Rust(README 数字)
3.4 同步策略
omp 与上游是 fork + selective backport,不是完全 cherry-pick:
docs/porting-from-pi-mono.md是合并手册,带上次同步锚点 commitb21b42d0(2026-03-22)packages/*/CHANGELOG.md大量条目形如Switched from local @oh-my-pi/pi-ai to upstream @mariozechner/pi-ai或backported pi-mono changes (...),证明持续同步- 上游改 SDK → omp 同步并保留自己的扩展(session / extensions / hooks 体系)
四、一图概括依赖血缘
五、关键证据文件
| 文件 | 作用 |
|---|---|
packages/coding-agent/src/extensibility/plugins/legacy-pi-compat.ts:161-178 | scope + subpath 重写规则(single source of truth) |
packages/coding-agent/test/pi-scope-aliases.test.ts | 三 scope 等价的回归测试 |
packages/coding-agent/test/issue-973-legacy-pi-plugin.test.ts | 老 plugin 兼容的回归测试(issue #973) |
docs/porting-from-pi-mono.md:46-51 | 上游 → oh-my-pi 包映射表 + sync 锚点 commit |
README.md:21-22, 469, 485 | 显式声明 “fork of pi-mono by @mariozechner” |
package.json 的 workspaces.catalog | 所有第三方依赖集中点 |
总结
- oh-my-pi = pi-mono fork + 自创层 + Rust 内核。fork 占大头(5 个核心 pi-* 包),自创层集中在 “omp 独有功能”(hindsight / hashline / collab / swarm / natives)。
- “pi-sdk” 不存在,
pi-coding-agent同时是 CLI 和 SDK。 - 上游 7 个包里丢了 3 个(
pi-mom/pi-web-ui/pi-pods),替换了 1 个(pi-web-ui→collab-web)。 - 三 scope(
@mariozechner/@earendil-works/@oh-my-pi)通过 shim 等价,老 plugin 不用改一行代码就能跑在 omp 上。
如果想看具体的 “哪些 pi-mono PR/issue 被 backport 进来”,可以翻 packages/*/CHANGELOG.md 里那些 backported pi-mono changes (...) 条目,或者 git log --grep="backport"。
