问题
@tt-a1i/openpi 与 pi-intercom 同时启用时,任何 subagent_spawn(含不带 agent_type 的普通子代理)都在首个模型请求前预检必挂:
Child tool preflight failed: requested tool "intercom" is unavailable after
child extensions initialized. Check the Agent Type tools list and child
extension loading.
#128 确立的 child exclusion 规则本身存在且应保留;本 Issue 是它的补缺:包被正确排除,工具名却漏进继承 allowlist,把「子会话不可用 intercom」变成「整个委托通道不可用」。
复现
- 环境:
@tt-a1i/openpi 0.7.0(实测);0.8.0 与 main 当前状态同样存在(2026-09-08 复核);pi-intercom 经 settings.json 同装。
- 步骤:任意调用一次子代理即可,如
subagent_spawn({ name: "probe", prompt: "Reply OK" })
带或不带 agent_type 都失败;失败发生在扩展绑定后、模型收到提示词之前。
根因
extensions/shared/child-session.ts:
blockedPackageSources() 会把 pi-intercom 包整体从子会话的 settings/资源中剔除(其把会话身份存在 process.env,而 OpenPI children 是同进程并发 Session,加载它会串号——该排除属于真实运行时安全边界,#128 的「必须保留」项)。
- 但
CHILD_EXCLUDED_TOOL_NAMES 没有收录 "intercom"。
subagents/index.ts 用 inheritedChildToolAllowlist(pi.getActiveTools(), …) 构造子代理 allowlist:凡是父会话激活、又不在排除表的工具都会被继承。intercom 在父会话激活且不在表内,于是进了子代理的请求清单。
bindChildSessionExtensions() 在扩展初始化后做预检:子会话没有 pi-intercom 包,永远无法提供 intercom,预检报错、spawn 终止。
即:包按 parent-only 处理了,工具名没有;边界检查把一次有意的排除升级成了整条委托通道的硬失败。
用户影响
- pi-intercom 与 OpenPI 常见同装(一个管跨会话协调、一个管委托),同装即无法使用任何子代理;
#128 让 OpenPI 不再主动安装 pi-intercom,但用户自行同装仍会命中。
- 连带影响:OpenPI 的回归测试与 release 检查无法覆盖「顶层 Session 已装 intercom」的组合。
建议范围
最小修复——把 intercom 加进排除表:
// pi-intercom:包已被 blockedPackageSources 从子会话剔除,
// 继承 allowlist 不得泄漏其工具名
"intercom",
结构修复(更彻底)——给 pi.registerTool 增加 parent-only 声明能力,inheritedChildToolAllowlist 据此丢弃「所属包被从子会话剔除」的工具,替代手维护名单。
回归测试——在 drift guard / agent-types 测试中加一类用例:模拟某包被从 children 剔除、但其工具名在父会话激活,断言 spawn 不把该工具名带进 allowlist、且预检通过。
验收标准
证据
问题
@tt-a1i/openpi与pi-intercom同时启用时,任何subagent_spawn(含不带agent_type的普通子代理)都在首个模型请求前预检必挂:#128确立的 child exclusion 规则本身存在且应保留;本 Issue 是它的补缺:包被正确排除,工具名却漏进继承 allowlist,把「子会话不可用 intercom」变成「整个委托通道不可用」。复现
@tt-a1i/openpi0.7.0(实测);0.8.0 与main当前状态同样存在(2026-09-08 复核);pi-intercom经settings.json同装。带或不带
agent_type都失败;失败发生在扩展绑定后、模型收到提示词之前。根因
extensions/shared/child-session.ts:blockedPackageSources()会把pi-intercom包整体从子会话的 settings/资源中剔除(其把会话身份存在process.env,而 OpenPI children 是同进程并发 Session,加载它会串号——该排除属于真实运行时安全边界,#128的「必须保留」项)。CHILD_EXCLUDED_TOOL_NAMES没有收录"intercom"。subagents/index.ts用inheritedChildToolAllowlist(pi.getActiveTools(), …)构造子代理 allowlist:凡是父会话激活、又不在排除表的工具都会被继承。intercom在父会话激活且不在表内,于是进了子代理的请求清单。bindChildSessionExtensions()在扩展初始化后做预检:子会话没有 pi-intercom 包,永远无法提供intercom,预检报错、spawn 终止。即:包按 parent-only 处理了,工具名没有;边界检查把一次有意的排除升级成了整条委托通道的硬失败。
用户影响
#128让 OpenPI 不再主动安装 pi-intercom,但用户自行同装仍会命中。建议范围
最小修复——把
intercom加进排除表:结构修复(更彻底)——给
pi.registerTool增加 parent-only 声明能力,inheritedChildToolAllowlist据此丢弃「所属包被从子会话剔除」的工具,替代手维护名单。回归测试——在 drift guard / agent-types 测试中加一类用例:模拟某包被从 children 剔除、但其工具名在父会话激活,断言 spawn 不把该工具名带进 allowlist、且预检通过。
验收标准
subagent_spawn与带agent_type的 spawn 均通过预检、正常执行。intercom(#128的隔离边界不回退)。CHILD_EXCLUDED_TOOL_NAMES含intercom(或结构性方案令继承逻辑等价生效)。bun run check、bun run test通过。证据
~/.pi/agent/npm/node_modules/@tt-a1i/openpi(0.7.0);0.8.0 与main同名文件复核结论一致。blockedPackageSources()、CHILD_EXCLUDED_TOOL_NAMES、inheritedChildToolAllowlist()、bindChildSessionExtensions()的报错文案。