Chương 3Phần 1: Bối cảnh
Bản đồ monorepo
Mười một package, đồ thị phụ thuộc giữa chúng, và nên đọc theo thứ tự nào.
Trong chương này7 mục
Repo earendil-works/pi là một monorepo dùng npm workspaces: mọi package nằm dưới packages/, cùng chung một package-lock.json và cùng số phiên bản (mọi package ở tag này đều là 1.4.0). Chương này vẽ bản đồ để bạn biết mỗi thư mục làm gì, package nào dựa trên package nào, và nên đọc theo thứ tự nào.
Mười một package#
Số dòng dưới đây đếm các file .ts/.tsx trong src/ của từng package ở v1.4.0 (không gồm test); số file test đếm trong test/. README gốc liệt kê bảy package công khai chính (README.md:72–84); bốn package còn lại là phụ trợ.
| Thư mục | Tên npm | Vai trò | Dòng src | File test | Chương |
|---|---|---|---|---|---|
ai | @earendil-works/pi-ai | API thống nhất cho mọi provider LLM, danh mục mô hình, OAuth | 27.854 | 184 | pi-ai, provider |
agent | @earendil-works/pi-agent-core | Vòng lặp agent: gọi mô hình, chạy tool, hàng đợi steer/follow-up | 2.539 | 7 | agent-core |
coding-agent | @earendil-works/pi-coding-agent | CLI pi: session, tool, extension, các chế độ chạy, SDK | 76.067 | 321 | từ AgentSession trở đi |
tui | @earendil-works/pi-tui | Thư viện giao diện terminal vẽ lại theo vi sai | 19.623 | 53 | pi-tui |
codemode | @earendil-works/pi-codemode | Sandbox JavaScript (QuickJS) mà khả năng duy nhất là gọi tool được tiêm vào | 3.037 | 8 | Codemode |
mcp | @earendil-works/pi-mcp | Client Model Context Protocol độc lập (stdio, HTTP, OAuth) | 3.277 | 6 | Codemode, MCP |
chord | @earendil-works/chord | Runtime có kiểu cho plugin, contract, state nhân bản và RPC qua JSON | 14.612 | 62 | Chord |
durable | @earendil-works/pi-durable | Harness bền: hội thoại, task và document lưu bằng commit nguyên tử | 27.259 | 121 | Pi Durable |
env | @earendil-works/pi-env | Môi trường thực thi từ xa cho Pi Durable: daemon nhỏ triển khai qua SSH | 2.346 | 8 | pi-env |
telemetry | @earendil-works/pi-telemetry | Hợp đồng telemetry trung lập nhà cung cấp: span, event, metric | 1.572 | 8 | telemetry |
evals | @earendil-works/pi-evals | Bộ đánh giá coding agent bằng vitest (không phát hành như thư viện) | 1.446 | 6 | evals |
Bài công bố Pi Durable nói harness này khoảng 15.000 dòng không tính test. Ở v1.4.0, thư mục src/ của nó đã khoảng 27.000 dòng, vì gồm cả các backend storage, bộ kiểm thử tuân thủ trong src/testing/, môi trường Node và code mode bền; phần lõi harness vẫn nhỏ hơn nhiều.
Đồ thị phụ thuộc: hai chồng tách biệt#
Điều quan trọng nhất cần nhận ra khi nhìn các file package.json: Pi không phải một khối, mà là hai chồng dùng chung tầng dưới.
Chồng coding agent (CLI pi) Chồng Pi Durable (thư viện, thử nghiệm)
pi-telemetry pi-telemetry
│ │ │
▼ ▼ ▼
pi-ai pi-ai chord pi-codemode
│ │ │ │
▼ └──────────┼────────────┘
pi-agent-core pi-tui pi-mcp pi-codemode ▼
│ │ │ │ pi-durable
└────────────┴─────────┴─────┬─────┘ │
▼ ▼
pi-coding-agent pi-env
pi-coding-agent không phụ thuộc pi-durable hay chord; pi-durable không phụ thuộc pi-agent-core. Hai chồng gặp nhau ở pi-ai, pi-codemode và pi-telemetry.Phụ thuộc nội bộ của coding agent nằm ngay đầu khối dependencies:
"dependencies": { "@earendil-works/pi-agent-core": "1.4.0", "@earendil-works/pi-ai": "1.4.0", "@earendil-works/pi-codemode": "1.4.0", "@earendil-works/pi-mcp": "1.4.0", "@earendil-works/pi-tui": "1.4.0",Còn Pi Durable dựa trên Chord, pi-ai, pi-codemode và pi-telemetry, không có pi-agent-core:
"dependencies": { "@earendil-works/chord": "1.4.0", "@earendil-works/pi-ai": "1.4.0", "@earendil-works/pi-codemode": "1.4.0", "@earendil-works/pi-telemetry": "1.4.0",Thứ tự build trong package.json gốc chính là một thứ tự topo của đồ thị trên: telemetry, chord, tui, codemode, mcp, ai, durable, env, agent, rồi coding-agent.
"workspaces": [ "packages/*", "apps/*", "packages/coding-agent/examples/extensions/with-deps", "packages/coding-agent/examples/extensions/custom-provider-anthropic", "packages/coding-agent/examples/extensions/custom-provider-gitlab-duo", "packages/coding-agent/examples/extensions/sandbox", "packages/coding-agent/examples/extensions/gondolin"],"scripts": { "clean": "npm run clean --workspaces", "build": "cd packages/telemetry && npm run build && cd ../chord && npm run build && cd ../tui && npm run build && cd ../codemode && npm run build && cd ../mcp && npm run build && cd ../ai && npm run build && cd ../durable && npm run build && cd ../env && npm run build && cd ../agent && npm run build && cd ../coding-agent && npm run build",Phụ thuộc bên ngoài đáng chú ý#
Danh sách phụ thuộc bên ngoài cho biết mỗi package tự làm gì và giao gì cho thư viện khác:
- pi-ai dùng SDK chính thức của từng provider (
@anthropic-ai/sdk,openai,@google/genai, AWS Bedrock),partial-jsonđể đọc đối số tool khi nó còn đang stream, vàtypeboxcho schema của tool (ai/package.json). - pi-coding-agent dùng
jitiđể nạp extension viết bằng TypeScript lúc chạy,quickjs-wasicho codemode,@silvia-odwyer/photon-nodeđể xử lý ảnh,diffcho tooledit,highlight.jsđể tô màu code trong terminal,undicicho HTTP,proper-lockfileđể khoá file cấu hình khi nhiều tiến trình cùng ghi (coding-agent/package.json). - pi-tui chỉ cần
marked(parse Markdown) vàget-east-asian-width(độ rộng ký tự CJK); phần còn lại, kể cả thuật toán vẽ, là tự viết. - pi-durable dùng
@silvia-odwyer/photon(bản WebAssembly, chạy được cả trên Cloudflare),diffvàtypebox; còn lại đều là code của chính nó và Chord.
Các package thư viện công khai nhiều điểm vào con (subpath exports) để ứng dụng chỉ nạp phần mình cần. Ví dụ pi-ai có ./models, ./providers/*, ./api/*, ./oauth (ai/package.json:13), còn pi-durable tách riêng từng backend storage (./storage/sqlite/node, ./storage/sqlite/cloudflare, ./storage/jsonl/node, ./storage/indexeddb), các tool (./tools), code mode (./codemode) và bộ kiểm thử tuân thủ (./testing) (durable/package.json:8). Nhờ vậy một Durable Object trên Cloudflare không phải kéo theo code chỉ dành cho Node.
Ngoài packages/#
| Đường dẫn | Nội dung |
|---|---|
AGENTS.md, CONTRIBUTING.md | Quy tắc cho người và agent đóng góp; quy trình duyệt issue/PR. |
.pi/ | Tài nguyên Pi của chính repo: prompt template (/cl kiểm changelog, /is phân tích issue, /pr review PR, /wr “wrap it”: changelog, commit, push), skill (release, add-llm-provider, interactive-testing, github-work) và vài extension nhỏ. Đây là cách maintainer dùng Pi để phát triển Pi. |
scripts/ | Kiểm tra (pin dependency, import, install lock), phát hành, đóng gói, sinh danh mục mô hình. |
test.sh, pi-test.sh | Chạy test trong môi trường cô lập (HOME, tmp, cache riêng); chạy Pi từ mã nguồn ở bất kỳ thư mục nào. |
flake.nix, nix/ | Build Pi bằng Nix (thêm ở 1.0.1), kèm bản ghim danh mục mô hình để build offline. |
.github/ | CI và các workflow tự động đóng issue/PR của người mới. |
Một prompt template của maintainer trông như sau: frontmatter có mô tả và gợi ý đối số, thân là chỉ dẫn, và $ARGUMENTS được thay bằng những gì gõ sau lệnh. Cơ chế này được giải thích trong chương Extensions.
---description: Analyze GitHub issues (bugs or feature requests)argument-hint: "<issue>"---Analyze GitHub issue(s): $ARGUMENTSQuy ước kỹ thuật#
- TypeScript chạy thẳng, không biên dịch khi phát triển
- Từ 0.99.0 repo dùng TypeScript 7.0 (target ES2024) để kiểm kiểu và build, còn khi chạy từ mã nguồn thì dùng chế độ bỏ kiểu có sẵn của Node thay cho
tsx(CHANGELOG:463). Hệ quả là quy tắc chỉ dùng cú pháp xoá được (AGENTS.md:24), và các import tương đối ghi rõ đuôi.ts. - Định dạng và lint bằng Biome
- Thụt lề bằng tab, dòng tối đa 120 ký tự; file
models.generated.tsđược loại khỏi kiểm tra (biome.json:19–36). Trang này hiển thị tab rộng 2 ký tự. - Danh mục mô hình được sinh ra
- Không ai sửa tay
packages/ai/src/models.generated.ts; nó được sinh bằng script, còn dữ liệu mô hình chi tiết trongproviders/data/bị gitignore (AGENTS.md:28). Vì vậy bản clone của bạn không có dữ liệu đó; chương pi-ai giải thích nó được nạp thế nào. - Tài nguyên của coding agent đi qua
src/config.ts - Code không dùng
__dirnametrực tiếp mà gọi helper trongconfig.ts, vì cùng một mã phải chạy từ checkout, từ gói npm và từ binary độc lập (AGENTS.md:22). - Test cô lập
test.shtạo HOME, thư mục tạm và cache npm riêng, chỉ cho qua các biến môi trường cần thiết, và bỏ qua test cần gọi LLM thật khi không có khoá API (test.sh:4–13). Phần lớn test dùng vitest; riêngpi-tuidùngnode:test.
Điểm vào của lệnh pi ngắn đúng sáu dòng; mọi thứ còn lại bắt đầu từ main(), được giải thích trong chương Các chế độ chạy:
#!/usr/bin/env nodeimport { setupCli } from "./cli/setup.ts";import { main } from "./main.ts";setupCli();main(process.argv.slice(2));Những package đã biến mất#
Nếu đọc issue cũ, changelog hay blog, bạn sẽ gặp các package không còn trong packages/. Lịch sử git cho biết chúng đi đâu:
| Package | Tồn tại | Số phận |
|---|---|---|
pods | 2025-08-09 → 2026-04-30 | Công cụ triển khai vLLM; gỡ cùng mom. |
mom | 2025-11-26 → 2026-04-30 | Bot Slack dựa trên Pi; mảng chat nay ở repo earendil-works/pi-chat (README.md:86). |
web-ui | 2025-10-05 → 2026-05-20 | Thành phần giao diện web cho chat; gỡ khỏi workspace. |
browser-extension | 2025-10-01 → 2025-10-06 | Chuyển sang repo riêng (sitegeist). |
proxy, agent-old | 2025-10 → 2025-11/12 | Thử nghiệm sớm, đã gỡ. |
server, protocol, client | 2026-07 → 2026-10-12 | Bộ client/server từ xa thử nghiệm của coding agent (giao thức CBOR); gỡ sau khi Pi Durable ra đời. |
session-backends/sqlite-node | 2026-08-05 → 2026-10-01 | Backend SQLite cho harness thử nghiệm trong agent-core; gỡ cùng harness đó. |
Nên đọc theo thứ tự nào#
Tài liệu này đi từ dưới lên, khớp với đồ thị phụ thuộc. Nếu bạn có mục tiêu cụ thể, có thể nhảy thẳng: