返回课程首页

37

升级到 Pi 0.83:变化、迁移与验证

理解 0.83.0 的新能力、TypeBox 破坏性变化和升级检查路径。

源码基线:Pi v0.83.0 · commit 845d6ff

Pi 0.83.0 不是一次只改版本号的小更新。它增加了认证导出、扩展上下文和更准确的流式状态,同时升级了 TypeBox,并修复了 RPC、会话切换、资源重载等一批会直接影响桌面 Agent 的问题。

本章以官方 v0.83.0 tag(commit 845d6ff)为基线,回答三个问题:新功能怎么用、旧代码哪里会坏、升级后怎样证明系统仍然可靠。

1. 先看升级地图

区域 0.83 的变化 对桌面 Agent 的影响
认证 pi auth print-api-keyprint-bearer-token 外部进程可安全地临时取得当前凭证
扩展 API 新增 ctx.scopedModels 扩展可读取本次会话允许使用的模型范围
流式协议 新增 pending stop reason 未结束的部分消息不再被误判为正常完成
Provider 保留原始 stop reason;未知终止原因转成错误 UI 和日志能显示更真实的上游状态
TypeBox 升级到 1.3.7,删除一组弃用 API 使用旧 API 的扩展需要迁移后才能编译
OAuth 凭证不足 5 分钟时自动刷新 长任务更少在中途因 token 到期失败
RPC / Session bash、会话替换、树导航与持久化修复 可删除部分宿主侧绕行逻辑,并补回归测试

0.82.1 还补充了 Claude Opus 5、ANTHROPIC_AUTH_TOKEN、自定义消息渲染的 outputPad,以及模型目录缓存改进。从 0.82.0 直接升级时,也要把这些变化算进去。

2. 认证导出:让外部进程复用 Pi 的登录状态

新命令适合桌面主进程、脚本或插件宿主调用:

pi auth print-api-key anthropic
pi auth print-bearer-token openai

OAuth 凭证会在剩余有效期不足 5 分钟时刷新。调用方应把输出当作秘密,只放进子进程环境或内存,不要写入日志、埋点、错误报告或前端状态。

const token = (await runPi([
  "auth",
  "print-bearer-token",
  provider,
])).stdout.trim();

spawn(workerPath, [], {
  env: { ...safeBaseEnv, PROVIDER_TOKEN: token },
  stdio: ["ignore", "pipe", "pipe"],
});

如果在没有浏览器的服务器上登录 OpenRouter,0.83 允许粘贴重定向 URL 或授权码完成流程。

3. TypeBox 1.3.7:唯一明确的破坏性变化

0.83 删除了已经弃用的 TypeBox API:

Type.Base           Type.Awaited       Type.Promise
Type.AsyncIterator  Type.Iterator      Type.Options
Value.Mutate

升级前先扫描扩展代码:

rg 'Type\.(Base|Awaited|Promise|AsyncIterator|Iterator|Options)|Value\.Mutate' .

不要用类型断言掩盖错误。根据实际 schema 改用当前 TypeBox 构造器;如果过去依赖 Value.Mutate 原地修改对象,优先改成显式返回新值,让事件链更容易测试。

这次升级也修复了 nullable array 的编译校验。若某个工具参数是“数组或 null”,请同时测试解释执行与编译校验,避免旧行为被错误地写进测试快照。

4. 正确处理 pending 流式状态

部分流式消息现在可能带有 pending。它表示“当前快照尚未得到终止结论”,既不是成功,也不是错误。

switch (message.stopReason) {
  case "stop":
  case "length":
    markComplete(message);
    break;
  case "pending":
    keepStreaming(message);
    break;
  case "error":
    showFailure(message);
    break;
}

桌面 UI 不应在 pending 时点亮“完成”标记、启用重试按钮或持久化最终统计。等终止事件到达后再收口。0.83 还保留 Provider 的原始 stop reason;无法映射的终止原因会成为 Provider 错误,因此错误面板应保留原始原因和 Provider 名称。

5. 扩展可以读取 ctx.scopedModels

ctx.scopedModels 表示当前上下文中经过范围约束的模型集合。模型选择器、成本策略和审批扩展应优先使用它,而不是重新扫描全局模型目录。

pi.on("session_start", async (_event, ctx) => {
  const allowed = ctx.scopedModels;
  audit("models available in this session", allowed);
});

这能避免扩展向用户推荐一个全局存在、但当前工作区或会话不可用的模型。每次请求注入的 fetch 现在也会向下继承,自定义网络层应验证代理、追踪和测试替身仍被采用。

6. 重新检查旧的绕行逻辑

0.83 修复了几类集成边界:

  • 直接 RPC 的 bash 命令现在会经过 user_bash 事件;审批和审计扩展可以统一观察它。
  • 会话替换和树导航会先中止活动流,并正确持久化离开的 turn。
  • 扩展重载后会保留资源元数据。
  • 并发用户 bash 的取消、启动时切换会话导致的重复消息已修复。
  • llama.cpp 用量统计、失败 git package 留下半成品目录等问题已修复。

不要立即删除宿主侧保护。先写一个能复现旧问题的测试,在新版本通过后再移除绕行逻辑;权限校验、超时和进程隔离仍然是宿主的责任。

7. 一条可回滚的升级路径

npm install @earendil-works/pi-ai@0.83.0 \
  @earendil-works/pi-agent-core@0.83.0 \
  @earendil-works/pi-coding-agent@0.83.0
npm test
npm run build

按下面顺序验证:

  1. 锁定依赖并保存可工作的 lockfile 与构建产物。
  2. 扫描并迁移删除的 TypeBox API。
  3. 用最小会话测试文本流、thinking、tool call、取消和 pending
  4. 测试 API key 与 OAuth;确认敏感输出不进入日志。
  5. 通过 SDK 和 RPC 各运行一次 bash 审批测试。
  6. 在模型输出中途切换会话,再恢复并检查 session tree。
  7. 重载扩展,核对 Skill、Prompt 和资源元数据。
  8. 先灰度发布;监控 Provider 错误、取消率与恢复失败率。

8. 本章小结

Pi 0.83 的主线是让边界更明确:认证可以被受控地交给外部进程,模型范围进入扩展上下文,流式消息明确区分“等待”和“结束”,Provider 错误保留更多事实。代价是 TypeBox 旧 API 必须迁移。最可靠的升级方式,是把 changelog 中的每一项转成一个可复现的集成测试。

练习

  1. 在你的 UI 状态机里加入 pending,证明它不会触发完成态。
  2. 扫描一个 Extension 项目中的旧 TypeBox API,并写出迁移清单。
  3. 为直接 RPC bash 增加审批事件测试,确认 user_bash 一定出现。
  4. 模拟 OAuth token 只剩 4 分钟,验证获取凭证时发生刷新。
  5. 在流式输出中切换会话,验证离开的 turn 能恢复且不会出现重复消息。

官方依据