Pi 0.83.0 is more than a version-label update. It adds credential export, richer extension context, and more precise streaming state; upgrades TypeBox; and fixes integration issues around RPC, session switching, and resource reloads.
This chapter uses the official v0.83.0 tag (commit 845d6ff) as its baseline. It answers three practical questions: What can you use now? What can break? How do you prove the upgrade is safe?
1. The upgrade map
| Area | Change in 0.83 | Desktop-agent impact |
|---|---|---|
| Authentication | pi auth print-api-key and print-bearer-token |
External processes can obtain the current credential in a controlled way |
| Extension API | New ctx.scopedModels |
Extensions can see the models allowed in the current scope |
| Streaming | New pending stop reason |
A partial message is no longer mistaken for a completed response |
| Providers | Raw stop reasons are preserved; unknown terminal reasons become errors | Logs and UI expose the upstream outcome more faithfully |
| TypeBox | Upgraded to 1.3.7 and deprecated APIs removed | Extensions using old APIs must migrate before they compile |
| OAuth | Credentials refresh when less than five minutes remain | Long-running tasks are less likely to fail mid-turn |
| RPC and sessions | Fixes for bash events, session replacement, navigation, and persistence | Some host-side workarounds can be retired after regression tests pass |
If you jump directly from 0.82.0, include the 0.82.1 additions in your review: Claude Opus 5 support, ANTHROPIC_AUTH_TOKEN, outputPad for custom message renderers, and model-catalog cache improvements.
2. Export credentials for an external process
The new commands are useful when a desktop main process, script, or plugin host needs to reuse Pi's authenticated session:
pi auth print-api-key anthropic
pi auth print-bearer-token openai
OAuth credentials are refreshed when fewer than five minutes remain. Treat stdout as a secret: pass it through memory or a child-process environment, never through logs, analytics, crash reports, or renderer state.
const token = (await runPi([
"auth",
"print-bearer-token",
provider,
])).stdout.trim();
spawn(workerPath, [], {
env: { ...safeBaseEnv, PROVIDER_TOKEN: token },
stdio: ["ignore", "pipe", "pipe"],
});
OpenRouter login also supports headless environments by accepting a pasted redirect URL or authorization code.
3. TypeBox 1.3.7 is the explicit breaking change
Pi 0.83 removes these deprecated APIs:
Type.Base Type.Awaited Type.Promise
Type.AsyncIterator Type.Iterator Type.Options
Value.Mutate
Scan extension code before upgrading:
rg 'Type\.(Base|Awaited|Promise|AsyncIterator|Iterator|Options)|Value\.Mutate' .
Do not hide the errors with casts. Replace each use with current TypeBox schema constructors that describe the actual data. If code relied on Value.Mutate, prefer an explicit new value; event-chain behavior becomes easier to reason about and test.
The release also fixes compiled validation for nullable arrays. Test both interpreted and compiled validation when a tool argument accepts “array or null,” rather than preserving the old behavior in a snapshot.
4. Model pending as a real streaming state
A partial streaming message can now carry pending. It means that the snapshot has no terminal outcome yet—not success and not failure.
switch (message.stopReason) {
case "stop":
case "length":
markComplete(message);
break;
case "pending":
keepStreaming(message);
break;
case "error":
showFailure(message);
break;
}
Do not show a completion badge, enable retry, or persist final usage while the state is pending. Pi 0.83 also preserves raw provider stop reasons. An unmapped terminal reason becomes a provider error, so retain the provider name and original reason in diagnostics.
5. Use ctx.scopedModels in extensions
ctx.scopedModels describes the models available inside the current scope. Model pickers, cost policies, and approval extensions should use it instead of rebuilding a global catalog.
pi.on("session_start", async (_event, ctx) => {
audit("models available in this session", ctx.scopedModels);
});
This prevents an extension from recommending a globally known model that is unavailable in the current workspace or session. Per-request fetch injection is now inherited as well; verify that custom proxies, tracing, and test doubles still flow through nested calls.
6. Revisit old workarounds—with tests first
Pi 0.83 fixes several integration boundaries:
- Direct RPC bash commands now pass through the
user_bashevent, unifying approval and audit hooks. - Session replacement and tree navigation abort active streams first and persist the turn being left.
- Resource metadata survives extension reloads.
- Concurrent user-bash cancellation and duplicate startup messages after a session switch are fixed.
- llama.cpp usage accounting and partial directories from failed git packages are fixed.
Do not delete host-side protection immediately. First encode the old failure as a regression test, verify it against 0.83, then remove only the redundant workaround. Authorization, timeouts, and process isolation remain host responsibilities.
7. A reversible upgrade path
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
Verify in this order:
- Preserve a known-good lockfile and build artifact.
- Scan for and migrate removed TypeBox APIs.
- Test text streaming, thinking, tool calls, cancellation, and
pendingin a minimal session. - Test API-key and OAuth flows; prove secrets never enter logs.
- Run a bash approval test through both SDK and RPC integration.
- Switch sessions during output, restore, and inspect the session tree.
- Reload extensions and verify Skill, prompt, and resource metadata.
- Roll out gradually while monitoring provider errors, cancellation, and restore failures.
8. Summary
Pi 0.83 makes system boundaries more explicit: authentication can be handed to external processes under control, model scope is available to extensions, streaming distinguishes waiting from completion, and provider failures retain more evidence. The cost is a required migration away from deprecated TypeBox APIs. The safest upgrade turns every relevant changelog item into a reproducible integration test.
Exercises
- Add
pendingto your UI state machine and prove it cannot trigger completion. - Scan an Extension project for removed TypeBox APIs and write a migration checklist.
- Add an approval-event test for direct RPC bash and assert that
user_bashis emitted. - Simulate an OAuth token with four minutes remaining and verify refresh on credential export.
- Switch sessions during streaming and verify that the abandoned turn restores without duplicate messages.