Skip to content

Upgrade the Pi SDK and refresh its model catalog - #867

Open
amadad wants to merge 4 commits into
ymichael:mainfrom
amadad:fix/pi-082-model-catalog
Open

Upgrade the Pi SDK and refresh its model catalog#867
amadad wants to merge 4 commits into
ymichael:mainfrom
amadad:fix/pi-082-model-catalog

Conversation

@amadad

@amadad amadad commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Move BB's Pi bridge and server inference helpers from @mariozechner/pi-* 0.70.5 to @earendil-works/pi-* 0.82.0.
  • Use one shared ModelRuntime for model resolution, authentication, session creation, and catalog refresh. The picker now reflects each model's supported reasoning levels, including max.
  • Keep retryable Pi failures inside the active BB turn by honoring agent_end.willRetry.
  • Bundle Pi's jiti/static dependency and register Pi's static OAuth loaders so the standalone bridge can authenticate without filesystem-only dynamic imports.
  • Raise the supported Node.js floor to 22.19 and remove the Node 20 compatibility job and shim.

Why

BB was pinned to Pi 0.70.5 under the retired package namespace. Its static model APIs could not expose models added through Pi's current catalog. The new runtime API keeps session and catalog behavior under one owner while preserving BB's existing bridge protocol.

The server pins @opentelemetry/api to the workspace version so Pi AI and Drizzle resolve one shared type identity.

Compatibility

  • Supported Node.js versions are 22.19, 24, and 26.
  • Pi remains an SDK bundled with BB. This does not switch the provider to an independently installed Pi CLI.
  • The server-to-daemon wire contract is unchanged, so this does not require a host daemon protocol bump.

Verification

  • pnpm install --frozen-lockfile
  • pnpm exec turbo run build typecheck lint --concurrency=1 --force (68 tasks)
  • Agent runtime: 41 files, 803 tests
  • Server: 148 files, 1,255 tests
  • bb-app: 2 files, 47 tests
  • pnpm exec turbo run smoke:tarball --filter=bb-app --force
  • Bundled OAuth probe: stored openai-codex credentials resolve inside the single-file bridge
  • Packaged Pi bridge model discovery: 96 models, including six GPT-5.6 variants; eight models advertise max

@amadad

amadad commented Jul 24, 2026

Copy link
Copy Markdown
Contributor Author

Live testing exposed one bundle-only OAuth failure: Pi’s lazy OAuth loader resolved ./openai-codex.js relative to the generated single-file bridge. Commit 5e157ef7 registers Pi’s static OAuth loaders at bridge startup.

Proof: the regression test failed before the change and passes after it; all 803 agent-runtime tests pass; the tarball smoke passes; and a bundled openai-codex/gpt-5.6-luna turn completed successfully with stored OAuth credentials.

@amadad

amadad commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto main and added one commit.

fix: refresh the Pi model catalog once per bridge process — as originally filed this PR shipped a regression it introduced. listPiBridgeModels called modelRuntime.refresh({ allowNetwork: true }) on every invocation, so each model list fanned out one network request per configured provider to pi.dev. It runs on every picker render and on thread-detail bootstrap with nothing cached between the browser and the bridge, so a stalled provider endpoint burned the full 5s abort budget. Measured per call: ~8-9ms warm, 274-375ms cold, 5,010ms on 2 of 6 cold runs. The refresh is now attempted at most once per bridge process; later calls resolve from the persisted store plus the bundled static catalog and return the same model set. It also stops memoizing a rejected ModelRuntime.create(), which previously cached a single transient failure for the life of the process and left every model list and session start broken until the bridge restarted.

Two things that may make the Node floor less of a decision than it looks:

  • @mariozechner/pi-ai is deprecated on npm — npm view @mariozechner/pi-ai@0.73.1 deprecated returns "please use @earendil-works/pi-ai instead going forward". The current pin is on a retired namespace, and the newer releases under it carry the same notice.
  • Node 20 was already best-effort here before this PR: docs/platform-support.md said "Node.js 20 is best-effort only because it is end-of-life upstream", packages/bb-app/README.md says "Node 20.19.x is best-effort only", and the Node 20 CI job already ran with continue-on-error: true. This PR removes a non-blocking job and a support tier the docs had already marked EOL.

Happy to split this differently if you'd rather review the namespace migration and the runtime unification separately — say the word and I'll restructure.

amadad added 3 commits July 28, 2026 00:19
listPiBridgeModels called modelRuntime.refresh({ allowNetwork: true }) on
every invocation, so each model list fanned out one network request per
configured provider to pi.dev. It runs on every picker render and on
thread-detail bootstrap, and nothing caches the result between the browser
and the bridge. When a provider endpoint stalls the call burns the full 5s
abort budget before returning.

Measured cost of one listPiBridgeModels call: ~8-9ms warm, 274-375ms cold,
and 5,010ms on 2 of 6 cold runs.

Attempt the network refresh at most once per bridge process. The bridge is
long-lived, so later calls resolve from the persisted store plus the bundled
static catalog and return the same model set.

Also stop memoizing a rejected ModelRuntime.create(): a single transient
failure was otherwise cached for the life of the process, leaving every
model list and session start broken until the bridge restarted.
@amadad

amadad commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

CI caught a real defect in the previous push — fixed and force-pushed.

The Node 20 cleanup had removed the globalThis.navigator shim in packages/plugin-build/scripts/generate-runtime-export-manifest.mjs, which broke runtime-export-manifest.test.ts > runs when Node does not provide a global Navigator. That was wrong on my part: the test deletes globalThis.navigator explicitly to prove export introspection survives without it, so the shim guards a scenario the supported-Node floor has no bearing on — @pierre/diffs reads navigator.userAgent during module initialization regardless of Node version. The shim is restored verbatim, and this PR no longer touches packages/plugin-build at all.

Verified locally on the pushed commit, replicating the CI shard:

  • pnpm exec turbo run test --filter='!@bb/server' --filter='!@bb/app' --filter='!@bb/integration-tests' — 48/48 packages passing, including @bb/plugin-build 6/6
  • One further exclusion: @bb/host-daemon's command-dispatch.test.ts > reuses a busy runtime when thread.start carries a changed skill catalog fails on my machine with "Codex 0.101.0 is too old for this bb version". It reproduces identically on a clean origin/main checkout, so it is a local Codex version artifact and unrelated to this branch.

@amadad
amadad force-pushed the fix/pi-082-model-catalog branch from 9b352a3 to 9ce7023 Compare July 28, 2026 00:24
@amadad

amadad commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

Resolved the max reasoning blocker called out in #875.

The owning invariant is now consistent end to end: Pi's model catalog, server provider policy, and daemon bridge all accept max. The fix updates PI_SERVER_CAPABILITIES rather than adding a caller bypass, adds a server-boundary regression that failed with the prior HTTP 400, and bumps HOST_DAEMON_PROTOCOL_VERSION to 66 so an older Pi runtime cannot remain connected after the expanded server→daemon value set.

Proof on dc0a40a9:

  • focused server tests: 57/57
  • full server suite: 1,256/1,256
  • agent runtime: 803/803
  • agent providers: 9/9
  • host-daemon contract: 50/50
  • protocol self-update: 10/10
  • relevant package typechecks: clean
  • live packaged turn after deploying protocol 66: openai-codex/gpt-5.6-luna, reasoning maxPI_MAX_LIVE_OK

The full local host-daemon suite still has the previously documented environment-only failure because this machine's Codex 0.101.0 is below bb's 0.136.0 minimum; the protocol-focused host-daemon test passes and GitHub CI is running on the pushed commit.

@SawyerHood

Copy link
Copy Markdown
Collaborator

Hey @amadad I think how I'm going to solve this is:

  • Move pi to ACP so you are using the installed version on your machine
  • Remove the bundled pi dependency all together

Does that make sense to you?

@amadad

amadad commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

Yeah @SawyerHood. Unbundling deletes the class of problems this PR works around (static Auth loaders, jiti/static, per-call catalog refresh all exist because F ships inside bb).

FWIW, bb already works this way with Codex, and I hit Codex 0.101.0 is too old for this bb version twice on this branch, reproducing on a clean origin/main It surfaces late and reads like a bb bug rather than "update Codex" - worth getting the version handshake right for Pi from the start.

Happy to close this. The max reasoning fix (PI_SERVER_CAPABILITIES + protocol 66) is server-side and survives unbundling - it closes #875 - so I can send it standalone if useful.

@SawyerHood

Copy link
Copy Markdown
Collaborator

I think I will end up going with your approach for now since it more or less keeps the status quo. I just dug into the pi acp adapter and it has some issues.

I'll take a pass to do some deeper review and testing today

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants