架构
Zed ──ACP (JSON-RPC over stdio)──▶ rpi --acp ──spawn──▶ rpi --mode rpc (每会话一个)
rpi-acp 是个 cdylib 扩展,做三件事:抢 stdio、说 ACP v1、给每个会话挂一个 rpi --mode rpc 子进程。桥接层自己不跑模型——tools、models、auth、skills 全在子进程里,所以行为跟终端里跑 rpi 完全一致。
关键机制:抢夺 stdio
宿主默认会 drain stdin,扩展就拿不到 stdio,ACP server 无从谈起。解法:带 --acp 时,扩展在注册阶段声明 {"ownsStdio": true},宿主随即停止 drain,改走 StdioLifecycle,把 stdin/stdout 交给扩展。
从终端直接跑 --acp 会快速失败(一条消息 + exit 2),而不是空转。要注册用 rpi --install-zed。
事件映射
| rpi RPC 事件 | ACP update |
|---|---|
text_delta / thinking_delta |
agent_message_chunk / agent_thought_chunk |
tool_execution_start |
tool_call(edit/write 带 diff) |
tool_execution_update / _end |
tool_call_update |
plan_mode_complete |
plan |
| outcome aborted / completed | stopReason: cancelled / end_turn |
流式文本用累积快照 + finalText 去重,不重发已发过的 chunk。
会话持久化
稳定 UUID,原生 JSONL 历史落在 ~/.rpi/agent/acp/sessions(可用 RPI_ACP_SESSION_DIR 覆盖),进程退出后仍在。session/load 恢复并重放,session/resume 恢复但不重放。未知会话返回错误,不静默开空对话。
权限与问题扩展
- 权限:插件弹窗(如 bash 确认)映射成标准
session/request_permission,用户选择回传插件。默认带--permission-gate。 - 问题:ACP v1 没有通用多选方法,于是双方在
initialize里用_meta: {"pi-rust/questions": 1}协商。只有广告了 v1 的客户端才收到_rpi/request_question;超时默认 300s,配套_rpi/dialog_closed通知回收 UI。
安装配置
rpi install rpi-acp # 或 task install
Zed settings.json:
{ "agent_servers": { "rpi": { "type": "custom", "command": "rpi", "args": ["--acp"] } } }
args 可透传普通 flag,如 ["--acp", "--model", "gateway/model"]。--acp 会自动注册到 Zed(幂等、原子写、保留 JSONC 注释);设 RPI_ACP_NO_AUTO_REGISTER_ZED=1 可关掉。
独立二进制 rpi-acp-bridge
同样的 server 也能编成独立二进制,原生拥有 stdin/stdout,不需要 ownsStdio,可直接对着 stock rpi 跑。找 agent 的顺序:RPI_BIN → 自身 → 兄弟文件 → PATH。
cargo build --release -p rpi-acp --bin rpi-acp-bridge
task pack-acp # 打包进 ACP Registry
相关链接
- 🏠 官网与文档:https://rpi.laofu.online/
- 📦 核心仓库:bigfish1913/pi-rust
- 🔌 扩展仓库:pi-rust/rpi-package
- 📚 软件包目录:https://rpi.laofu.online/packages.html
- ✍️ 个人博客:https://blog.laofu.online/
Ext Link: https://blog.laofu.online/
评论区
写评论还没有评论