s11
Pi Package
分发与综合打包你的工具、技能、模板,分享出去
38 LOC0 个工具Pi Package 分发
一个单元,一次安装。
机制定位
Pi Package(可安装、可分发)
用户输入组装上下文模型推理tool_call 闸门执行工具tool_result 回传会话 / 持久化
包在循环之外,把前面各章的机制打包分发。
"打包你的工具、技能、模板,分享出去" — 一个单元,一次安装。
Harness 层:分发 — 让 harness 可复用、可版本化。
问题
到 s10 为止,你攒了一堆东西:自定义工具(s02)、权限扩展(s03)、截断钩子(s04)、skill(s05)、prompt 模板(s06)、provider(s10)。它们散落在各个目录里,靠 settings.json 一条条手动指路。
给同事用、发到团队、开源出去,都需要一个打包单元:装一次,全都有,能版本化,能更新。
解决方案
一个 pi package 就是一个 npm 包,用 package.json 的 pi 字段声明贡献哪些资源:
{
"name": "pi-example-bundle",
"version": "0.1.0",
"keywords": ["pi-package"],
"pi": {
"extensions": ["./extensions"],
"skills": ["./skills"],
"prompts": ["./prompts"],
"themes": ["./themes"]
},
"peerDependencies": {
"@earendil-works/pi-coding-agent": "*",
"typebox": "*"
}
}
安装:
pi install ./pi-example-bundle # 本地目录
pi install git:github.com/you/pi-example-bundle@v1 # git(钉住 ref)
pi install npm:pi-example-bundle@0.1.0 # npm
pi install -l ... # 写进项目设置,团队共享
装完 pi 自动发现并加载,不需要在别处再配置。
工作原理
两种声明方式
pi清单(推荐):显式列出每类资源的路径,支持 glob 和!排除。- 约定目录:没有
pi字段时,pi 自动发现extensions/、skills/、prompts/、themes/。
pi-example-bundle/
├── package.json # pi 清单
├── extensions/
│ └── hello.ts # 默认导出 (pi) => {...}
├── skills/
│ └── pkg-guide/SKILL.md
└── prompts/
└── pkg-check.md
依赖规则
- pi 核心包是 peer:
@earendil-works/pi-coding-agent、pi-ai、pi-agent-core、pi-tui、typebox写进peerDependencies且"*",不要打包。pi 自带它们,打包会版本冲突。 - 第三方运行时依赖放
dependencies。从 npm/git 安装时 pi 会跑npm install --omit=dev,所以运行时用到的不能放devDependencies。 - 引用其他 pi package 的包要放进
dependencies+bundledDependencies。
安装源与去重
| 源 | 写法 | 落盘位置 |
|---|---|---|
| npm | npm:pkg@1.2.3 | ~/.pi/agent/npm/ 或 .pi/npm/ |
| git | git:host/user/repo@v1 | ~/.pi/agent/git/... |
| 本地 | /abs/path 或 ./rel | 不复制,直接引用 |
同一个包同时出现在全局和项目设置里,项目条目优先(除非它标了 autoload: false)。身份按「npm 包名 / git 仓库 URL / 本地绝对路径」判定。
精细控制加载内容
settings.json 里可以用对象形式过滤包内资源:
{
"packages": [
{
"source": "npm:my-package",
"extensions": ["extensions/*.ts", "!extensions/legacy.ts"],
"skills": [],
"prompts": ["prompts/review.md"]
}
]
}
[] 表示该类全不加载,!pattern 排除,+path 强制包含。
变更内容
| 组件 | s10 | s11 |
|---|---|---|
| 分发单位 | 散落的目录 | 一个 npm 包 |
| 声明方式 | settings.json 手动指路 | pi 清单 / 约定目录 |
| 安装 | 手动拷贝 | pi install |
| 依赖 | — | 核心包 peer,运行时依赖 deps |
| 循环 | 不变 | 不变 |
试一下
npm run s11
脚本用 additionalExtensionPaths / additionalSkillPaths / additionalPromptTemplatePaths 加载包内资源,打印出:1 个扩展、1 个 skill、1 个 prompt 模板,以及会话工具里确实出现了 pkg_time。
真实安装(会写 settings,建议在测试环境试):
pi install ./s11_pi_packages/pi-example-bundle
pi -p "现在几点?" # 模型可调用 pkg_time
/pkg-check # 展开包内模板
再试几个:
- 删掉
package.json里的pi清单,只留约定目录,再跑npm run s11—— 资源仍会被发现 - 在 settings 里用对象形式过滤:
"extensions": ["extensions/*.ts", "!extensions/legacy.ts"],观察加载数量变化
本章要点
- pi package = npm 包 +
pi清单(或约定目录)。 - 核心包写
peerDependencies,别打包;运行时依赖放dependencies。 - 三种安装源:npm / git / 本地;项目条目优先于全局。
- 用 settings 的对象形式可以按路径过滤包内资源。
下一章
每一章只讲一个机制。最后,把它们装回同一个会话。s12:完整 Harness。