@rogeecn/pi-fusion
v1.1.0
Published
Focused fork of @pi-unipi/fusion for Pi 1.2.x: lead + persistent sidekick over a CLIProxyAPI-backed custom provider, with per-role model, effort and Standard/Fast service tiers
Maintainers
Readme
pi-fusion
@pi-unipi/fusion 2.20.5 的聚焦 fork,适配 Pi 1.2.x:Lead + 持久 Sidekick 双模型工作流,经自定义 provider(CLIProxyAPI)运行,主副手各自独立的模型、effort 与 Standard/Fast 服务档位。
特性
- 零
@pi-unipi运行时依赖 — 上游用到的 4 个 core 符号与 1 个 subagents 函数已内联到src/compat.ts(MIT,© 2026 Neuron Mr White)。 - 命令使用
/pi-fusion:前缀 — 可与原插件共存,互不冲突。 - 能力导向的模型目录 — 列表运行时读取 Pi 模型注册表;图像/分类器/无文本能力的模型不可被选为主副手(按 type/模态判断,非名称黑名单)。模型增减无需改代码。
- 持久副手 — 同一 Lead 会话复用一个子进程与一份连续的副手会话记录;忙时新委派以 steering 插入,不开第二个副手。
- 故障自愈 — 副手子进程被外部杀死(OOM-kill、手工清理)后,下一次交接自动重建;交接中的死亡如实上报 error,绝不误报成功。
- Fast(priority)档位 — 主副手各自独立开关,注入 OpenAI Responses 的
service_tier: "priority";实际档位从上游流事件读取,不凭响应延迟推断,未生效就明说。 - 密钥零接触 — 认证由 Pi 的 provider 配置承载;本 fork 的配置、源码、日志、仓库均不出现任何密钥。
命令
| 命令 | 说明 |
| --- | --- |
| /pi-fusion:model | Devin 风格选择器:选单模型,或 Fusion 主副手组合(模型/effort/档位一次配齐) |
| /pi-fusion:preset | 管理预设:主/副手候选清单、默认组合 |
输入 /model 时自动补全会把 /pi-fusion:model 置顶。
配置与状态文件
| 文件 | 用途 |
| --- | --- |
| ~/.pi/agent/pi-fusion.json | 全局预设(候选清单、effort、当前 active 组合) |
| <project>/.pi/pi-fusion.json | 项目覆盖(深合并,项目层优先) |
| ~/.pi/agent/pi-fusion/sidekick/<leadSessionId>.jsonl | 副手持久会话记录 |
| ~/.pi/agent/pi-fusion/sidekick/<leadSessionId>.tier-evidence.jsonl | 脱敏档位证据(见 状态核查) |
安装
要求:Pi ≥ 1.2.0(pi --version 确认)。
pi install npm:@rogeecn/pi-fusion本地开发安装(仓库即安装源):pi install /path/to/pi-fusion——packages 记录的是活路径引用(不拷贝),git pull 后无需重装;但也意味着删掉仓库目录会直接破坏安装。
快速开始(配对)
/pi-fusion:preset— 两栏清单勾选可作 Lead 与 Sidekick 的模型(L/S列,space 切换,tab 换列)。/pi-fusion:model— 选中 Fusion 行(默认置顶):tab在 Lead/Sidekick 下拉间切换,↑↓选择;下拉即输即筛,覆盖完整模型目录(预设成员置顶,其余目录模型跟在其后);←→调整 Lead effort(与 effort 记忆独立);ctrl+f切换当前焦点角色的 Standard/Fast 档位(焦点在 Sidekick 下拉时切副手,否则切 Lead;字母键始终用于搜索);↵应用。Lead 随即设为会话模型,组合记为默认。
之后正常对话:需要委派时 Lead 会调用 sidekick 工具。
工作原理
- Lead 是当前会话模型;确认 Fusion 组合后由它主导任务。
- Sidekick 是按需启动的子
pi进程(--mode rpc,stdin/stdout 通信,--no-skills,模型/effort/档位独立于 Lead)。首个委派触发启动,之后跨委派复用——副手的上下文在会话内连续,越用越懂本项目。 - 忙时 steering:副手还在干上一个委派时又来新委派,新指令注入同一子进程,不双开、不丢话。
- 自动恢复:子进程死亡(含被外部杀死)后,下一次交接自动拉起全新子进程;交接中的死亡以
error状态上报,Lead 可重试。 - 干净退出:切换单模型、切换主副手配置、退出 pi,都会结束子进程,不留孤儿。
- 会话恢复:重启 pi 后自动恢复上次的选择——上次是 Fusion 就恢复主副手(含档位),上次是单模型就恢复单模型。
代理配置(CLIProxyAPI)
本 fork 不自带 provider,直接使用 Pi 已配置的自定义 provider(例如 cliproxyapi,指向自建 CLIProxyAPI)。前提:
- 在 Pi 侧完成 provider 配置(自定义 provider + 模型清单 + 认证头)。认证信息只存在于 Pi 自己的 provider 配置中。
/pi-fusion:model的候选列表 = Pi 模型注册表里的可文本对话模型,注册表变化无需改代码。
Fast(priority)档位
- Fast = 请求中注入 OpenAI Responses 的
service_tier: "priority"(CLIProxyAPI v7.x 删除fast但保留priority)。 - 默认关闭(standard)。effort 与档位是两个正交设置,互不混淆:effort 管思考深度,档位管服务优先级。
- 注入机制:Pi 1.2 扩展事件
before_provider_request,且只对 Responses 形态的 payload 生效(model+input、无messages);其他 adapter 原样放行,不做假定。 - 副手档位独立生效:tier=fast 时子进程加载同一扩展的注入器模式,对自己的请求注入
priority,与 Lead 档位互不串档(双向)。
状态核查
档位的"请求 priority"与"上游实际返回档位"区分记录在脱敏证据文件 ~/.pi/agent/pi-fusion/sidekick/<leadSessionId>.tier-evidence.jsonl(仅时间戳/角色/模型/档位字段,无 prompt 内容),排错时可直接查看:
returned priority ✓ confirmed— Fast 实际生效;returned default ⚠ Fast NOT effective— 请求了但上游未按 priority 服务,不宣称生效;returned tier unknown— 响应无可识别档位字段,同样不宣称生效。
判定一律来自 provider 流事件(response.created / response.completed 的 response.service_tier)。
故障排查
| 症状 | 排查 |
| --- | --- |
| 副手没被调用 | 确认当前是 Fusion 组合(/pi-fusion:model);Lead 会在合适任务上调用 sidekick 工具,简单问题可能不需要委派 |
| 委派瞬间报错后自动恢复 | 设计行为:子进程死亡 → error 如实上报 → 下一次交接自动重建新子进程 |
| Fast 显示 ⚠ NOT effective | 请求带了 priority 但上游返回 default/缺失档位——看证据文件确认出站参数;可能是代理或模型不支持 |
| 副手会话越用越大 | 正常:同一 Lead 会话内副手上下文连续积累;开新 pi 会话即开新副手 |
| 想看副手干了什么 | 直接打开 ~/.pi/agent/pi-fusion/sidekick/<leadSessionId>.jsonl(标准 pi 会话格式) |
| 疑似双重委派/双重状态 | 见下节"与原插件共存" |
回退 / 退出 Fusion
- 临时退出 Fusion:
/pi-fusion:model选任意单模型行(或 Pi 自带/model/ Ctrl+P)——切换单模型即停用 Fusion 并结束副手进程。 - 关闭 Fast:
/pi-fusion:model中对相应角色按ctrl+f切回 Std;或直接编辑 preset 把leadTier/sidekickTier改为"standard"/删除。 - 完全卸载:
pi remove pi-fusion(或对应安装源),删除~/.pi/agent/pi-fusion.json与~/.pi/agent/pi-fusion/。
与原 @pi-unipi/fusion 共存
两者可同时安装(命令前缀与状态目录均不同),但不要在同一会话里跑两套 Fusion。若出现双重交接、双重 nudge 或两个 Fusion 指示:
pi list查看是否同时装了@pi-unipi/fusion(或 unipi 包组)和pi-fusion。- 移除其一:
pi remove @pi-unipi/fusion,或本项目pi remove后禁用。 - 重启 pi,应只剩
/pi-fusion:*命令。
内置互防护:本 fork 生成的副手子进程同时带 PI_FUSION_CHILD=1 与 UNIPI_FUSION_CHILD=1 标记,双方插件在对方子进程内均保持静默。
环境变量
| 变量 | 用途 |
| --- | --- |
| PI_FUSION_PI_BINARY | 覆盖用于拉起副手的 pi 可执行文件(开发/测试用) |
| PI_FUSION_CHILD=1 | (内部)副手子进程标记,本扩展在子进程内保持静默 |
| PI_FUSION_CHILD_TIER / PI_FUSION_TIER_EVIDENCE | (内部)副手 fast 注入器开关与证据文件路径 |
开发
npm install
npm run typecheck # tsc --noEmit(0 错误)
npm test # 114 项单元测试
node scripts/smoke.mjs # 真实链路冒烟:文本/工具/交接/复用/恢复/Fast(经代理发少量小请求)
node scripts/prod-verify.mjs # 生产级验证:真实修 Bug 闭环、杀子进程自愈、双档 Fast、孤儿检查等两个真实链路脚本都会经你配置的 provider 发少量小请求,并临时改写 ~/.pi/agent/pi-fusion.json(结束时可清理)。
配置字段参考(无密钥)
~/.pi/agent/pi-fusion.json(项目覆盖放 <project>/.pi/pi-fusion.json,字段相同):
{
"lead": ["cliproxyapi/你的主模型"],
"sidekick": ["cliproxyapi/你的副手模型"],
"default": { "lead": "cliproxyapi/你的主模型", "sidekick": "cliproxyapi/你的副手模型" },
"effort": { "cliproxyapi/你的主模型": "high" },
"active": {
"kind": "fusion",
"lead": "cliproxyapi/你的主模型",
"sidekick": "cliproxyapi/你的副手模型",
"leadEffort": "high",
"sidekickEffort": "low",
"leadTier": "standard",
"sidekickTier": "standard"
}
}| 字段 | 类型 | 说明 |
| --- | --- | --- |
| lead / sidekick | ModelKey[] | 可选为主/副手的候选清单(/pi-fusion:preset 管理) |
| default | { lead, sidekick } | 默认组合 |
| effort | Record<ModelKey, EffortLevel> | 每模型默认思考档(low/medium/high) |
| active.kind | "fusion" \| "single" | 当前选择 |
| active(fusion) | — | lead/sidekick + 可选 leadEffort/sidekickEffort/leadTier/sidekickTier(standard/fast) |
| active(single) | — | { "kind": "single", "model": "provider/model" } |
验证记录
- 需求验收:docs/acceptance-2026-10-14.md — 需求文档第 7 节验收清单 12/12 逐项证据。
- 生产验证:
scripts/prod-verify.mjs(GLM-5.3 主 / glm-5.3-flash 副)P1–P9 全过——真实修 Bug 闭环、交接中杀子进程后如实报错并自愈、双角色 Fast 上游确认返回priority且互不串档、SIGTERM/SIGKILL 无孤儿进程、会话恢复、证据字段白名单。
License
MIT — 见 LICENSE。Fork 自 UniPi(© 2026 Neuron Mr White);src/compat.ts 内联的辅助代码保留上游出处说明。
