feat(pi): 交互式 pi 会话接入邮件工具(send_mail/read_inbox 等 10 个)
问题(⑧):守护进程用 noExtensions:true 起会话,它的邮件工具只给模型在邮件
会话里用;人在 TUI 里敲的 pi 拿不到。结果是平台的建设者自己收不到邮件 ——
一个「邮件驱动」的平台,维护者只能绕到 curl + 密钥直连 Gateway 才能看收件箱。
新增 plugins/pi-mail-bridge/extension/index.ts:把同一套工具(createMailTools)
注册到交互式会话。两者是同一条 AgentMail 身份(agent pi)的两个入口,与 DSH 的
「TUI + 邮箱是同一个 Agent」一致。
密钥解析顺序(交互式 pi 的环境里没有 AGENTMAIL_*):
1. 进程环境
2. AGENTMAIL_ENV_FILE(默认 /etc/agentmail/pi.env)—— 与守护进程同一把密钥,
因此身份一致
3. AGENTMAIL_CONFIG_DIR/agent.key 或 ~/.agentmail/agent.key
(兼容 key 与 key_token 两种字段名;实测本机文件用的是 key_token,
只认 key 会静默读不到)
拿不到密钥时不注册任何工具并明确告知 —— 挂一组永远 401 的工具比没有更糟。
不注册 connect_to_server:它会重写 Gateway 坐标并重新登记密钥,而交互式会话与
守护进程共用同一身份,一次 TUI 对话不该改到守护进程的配置。
为什么不会重复注册(读 SDK 实现确认,并用探针实测):
resource-loader.js 里 noExtensions 为真时只用 cliEnabledExtensions,
settings.json 的 extensions 数组被排除 —— 即 noExtensions:true 只加载
命令行 -e 传入的扩展。
探针:noExtensions=true → 扩展数=0;false → 16 个且含 pi-mail-bridge。
deploy/install.sh 增加幂等的扩展注册步骤(写入 settings.json 的 extensions)。
验证:headless pi 实际调用 read_inbox 返回真实邮件主题;工具清单含
send_mail/read_inbox/read_mail/forward_mail/upload_attachment/download_attachment/
suggest_address/list_contacts/session_participants/read_thread(10 个),
connect_to_server 按设计排除。
This commit is contained in:
@ -60,6 +60,40 @@ else
|
||||
echo " 未找到 pi SDK($PI_SDK),跳过 pi 插件测试"
|
||||
fi
|
||||
|
||||
# pi 邮件工具扩展:给**交互式**会话装上 send_mail / read_inbox。
|
||||
#
|
||||
# 守护进程(pi-mail-bridge.service)用 noExtensions:true 起会话,它的邮件工具
|
||||
# 只给模型在邮件会话里用;人在 TUI 里敲的 pi 拿不到。结果是平台的建设者自己
|
||||
# 收不到邮件,只能绕到 curl + 密钥直连 Gateway。这个扩展补上那一侧 ——
|
||||
# TUI 与邮箱是同一条 AgentMail 身份(agent pi)的两个入口。
|
||||
#
|
||||
# 为什么不会重复注册:noExtensions:true 只加载 CLI `-e` 传的扩展,
|
||||
# settings.json 的 extensions 数组会被排除(见 SDK resource-loader.js),
|
||||
# 因此守护进程的 worker 里零扩展、本扩展只作用于交互式会话。
|
||||
if [[ -d "$PI_SDK" ]]; then
|
||||
PI_HOME="${SUDO_USER:+$(getent passwd "$SUDO_USER" | cut -d: -f6)}"
|
||||
PI_HOME="${PI_HOME:-$HOME}"
|
||||
PI_SETTINGS="$PI_HOME/.pi/agent/settings.json"
|
||||
EXT_PATH="$REPO/plugins/pi-mail-bridge/extension/index.ts"
|
||||
if [[ -d "$PI_HOME/.pi/agent" || -f "$PI_SETTINGS" ]]; then
|
||||
install -d "$(dirname "$PI_SETTINGS")"
|
||||
node -e '
|
||||
const fs = require("fs");
|
||||
const [path, target] = process.argv.slice(1);
|
||||
let cfg = {};
|
||||
try { cfg = JSON.parse(fs.readFileSync(path, "utf8")); } catch { /* 新建 */ }
|
||||
const list = Array.isArray(cfg.extensions) ? cfg.extensions : [];
|
||||
if (list.includes(target)) { console.log(" 已注册,幂等跳过"); process.exit(0); }
|
||||
list.push(target);
|
||||
cfg.extensions = list;
|
||||
fs.writeFileSync(path, JSON.stringify(cfg, null, 2) + "\n");
|
||||
console.log(" 已注册 " + target);
|
||||
' "$PI_SETTINGS" "$EXT_PATH"
|
||||
else
|
||||
echo " 未找到 $PI_HOME/.pi/agent,跳过(手动在 settings.json 加 extensions: [\"$EXT_PATH\"])"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "==> 前端产物嵌入 Gateway"
|
||||
# 只清构建产物,不能 rm -rf 整个目录:
|
||||
# placeholder.html 在版本库里(让 go:embed 在新克隆里能编译),
|
||||
|
||||
Reference in New Issue
Block a user