Skip to content

Dependency sweep: pi 0.83 and the 5-series models - #396

Draft
dannon wants to merge 4 commits into
galaxyproject:mainfrom
dannon:dep/pi-083-sweep
Draft

Dependency sweep: pi 0.83 and the 5-series models#396
dannon wants to merge 4 commits into
galaxyproject:mainfrom
dannon:dep/pi-083-sweep

Conversation

@dannon

@dannon dannon commented Aug 3, 2026

Copy link
Copy Markdown
Member

Two batches from a dependency survey, split into four commits so the mechanical
churn stays separable from the real migration.

Lockfile refresh. Straight npm update on root and app, no range changes.
Notable movers: prettier 3.8.4 → 3.9.6, eslint 10.4.1 → 10.8.0, vitest 4.1.8 →
4.1.10, better-sqlite3 12.10.0 → 12.11.1, dompurify 3.4.9 → 3.4.12, electron
41.7.1 → 41.10.3. The prettier reformat it triggers is its own commit.

pi 0.78.1 → 0.83.0, plus pi-mcp-adapter → ^2.18.0 and pi-web-access →
^0.17.1. These have to move together: pi-web-access 0.17 declares peer deps on
all three pi packages, and pi-mcp-adapter needed the lockfile off 2.9.0 so dev
resolves what users actually install (the version #395 just taught us to
resolve). The @mozilla/readability override goes away -- pi-web-access depends
on ^0.6.0 itself now.

Four API breaks came with it:

  • pi 0.80 moved pi-ai's global API off the package root to /compat. The
    extension loader aliases the root back, so extensions/loom/teams was fine at
    runtime, but Orbit's main process gets no such alias -- ipc-handlers was
    headed for undefined getProviders/getModels at runtime rather than a
    compile error. That's the one that would have silently killed the model
    picker's dynamic population.
  • AuthStorage is no longer re-exported from the package root.
  • ModelRegistry now takes a ModelRuntime from an async factory instead of an
    AuthStorage plus a path. --list-models collapses to a single
    listModels() call, which takes a runtime directly; the custom-provider test
    uses a small CredentialStore stub rather than reaching into pi internals.
  • loginOpenAICodex looks removed -- /oauth has been a type-only entry point
    since 0.81 and the implementation sits behind an unexported path. It's
    actually a relocation: pi 0.81 folded per-service login helpers into the
    provider, so auth hangs off provider.auth.oauth as login/refresh/toAuth and
    the app drives it. signInOpenAICodex now asks a ModelRuntime for the
    provider, which keeps this on public API.

Model catalog refresh. The renderer's picker, pricing, and context windows
are fallbacks that populateDynamicModelData() overwrites from pi's registry,
but they'd drifted to actively misleading -- topping out at Opus 4.8, still
listing GPT-4o and o1. The o1/gpt-4-turbo entries were offering models loom's own
legacy denylist strips from the live list. Adds Opus 5, Sonnet 5, Fable 5, moves
OpenAI to gpt-5.x and Google to gemini-3.x, and fixes the Gemini 2.5 Flash label
($0.15/$0.60 claimed, $0.30/$2.50 actual). Numbers are read out of the 0.83
registry, not hand-copied. shortModelLabel learns the fable family so the
footer stops rendering a raw id.

exec-guard's tier classifier needed nothing, which surprised me: Opus 5 and
Sonnet 5 match the existing opus/sonnet markers, and Fable 5 and Gemini 3.x Pro
both clear the trusted price threshold on their own.

Verification

Root and app typecheck, 1364 tests, format:check, and lint (0 errors) all pass.
smoke:pack passes too -- that's the one that installs the packed tarball
without the lockfile, so it exercises the same fresh-install path that broke in
#395. loom --version and loom --list-models both run against 0.83.

Not live-eyeballed in Orbit: the model picker and the Codex OAuth sign-in button
are typecheck-and-reason verified, not clicked.

Follow-ups, deliberately not here

Now that auth rides on the provider, six providers expose an OAuth login in 0.83
-- anthropic, github-copilot, kimi-coding, openai-codex, openrouter,
xai -- all reachable through the same provider.auth.oauth.login() path this
PR uses for one of them. Orbit hardcodes openai-codex; a generic
signInOAuth(providerId) would unlock the rest. Kept separate because it touches
the prefs UI, the IPC surface, and per-provider status/sign-out, and because the
providers differ in interaction shape (device_code vs auth_url) in ways the
current handler doesn't render.

smoke:pack still isn't in .github/workflows/build.yml, so nothing in CI
covers the no-lockfile install path this PR leans on.

Also held back, each wanting its own PR: typescript 6→7, electron 41→43, vite
6→8, better-sqlite3 12→13 (native, needs an electron rebuild), tus-js-client 3→4
(would need the live upload re-verified), node-html-parser 7→9, and
@anthropic-ai/sandbox-runtime 0.0.52→0.0.67.

dannon added 4 commits August 3, 2026 09:41
Straight `npm update` on root and app -- no package.json ranges changed, just
the pins catching up. Notable movers are prettier 3.8.4 to 3.9.6, eslint 10.4.1
to 10.8.0, vitest 4.1.8 to 4.1.10, better-sqlite3 12.10.0 to 12.11.1, dompurify
3.4.9 to 3.4.12, and electron 41.7.1 to 41.10.3 on the app side. Root typecheck,
app typecheck, and the full test suite are all green on these.

The prettier bump wants to reformat some files; that's the next commit so this
one stays a pure dependency change.
Mechanical only -- prettier 3.9.6 lays out a few union types and long
expressions differently than 3.8.4 did. No behavior change anywhere, and the
whole tree passes format:check again. Kept out of the lockfile commit so a
future bisect doesn't have to read 21 files of noise to find a dependency move.
Bumps pi-coding-agent/pi-tui/pi-ai to 0.83.0, pi-mcp-adapter to ^2.18.0, and
pi-web-access to ^0.17.1. These go together: pi-web-access 0.17 declares peer
deps on all three pi packages, and pi-mcp-adapter needed the lockfile moved off
2.9.0 so dev finally resolves what users actually install. Also drops the
@mozilla/readability override -- pi-web-access depends on ^0.6.0 itself now, so
it was doing nothing.

Four things broke along the way. pi 0.80 moved pi-ai's global API off the
package root to /compat; the extension loader aliases the root back, which
covers extensions/loom/teams but not Orbit's main process, so ipc-handlers was
heading for undefined getProviders/getModels at runtime rather than a compile
error. pi 0.83 stopped re-exporting AuthStorage from the package root, and
reshaped ModelRegistry to take a ModelRuntime built by an async factory instead
of an AuthStorage plus a path -- that hit both --list-models and the
custom-provider test. The test now stands up a small CredentialStore stub rather
than reaching for pi internals, and --list-models drops to just listModels(),
which takes a ModelRuntime directly now.

The interesting one is OAuth. pi 0.81 folded the per-service loginOpenAICodex()
helper into the provider: auth hangs off provider.auth.oauth as a
login/refresh/toAuth triple, and driving login is the app's job now. That reads
like a removal from the outside -- /oauth is a type-only entry point since 0.81
and the implementation sits behind an unexported path -- but the supported route
is just to ask a ModelRuntime for the provider, which is what signInOpenAICodex
does now.

Verified with root and app typecheck, the full test suite, and smoke:pack, which
installs the packed tarball without the lockfile and boots the CLI.
The picker, pricing table, and context windows in the renderer are only
fallbacks -- populateDynamicModelData() overwrites them from pi's registry at
startup -- but they'd drifted far enough to be actively misleading, topping out
at Opus 4.8 and still listing GPT-4o and o1 on the OpenAI side. The o1 and
gpt-4-turbo entries were the worst of it: loom's own legacy denylist strips
those from the dynamic list, so the fallback was offering models the live path
deliberately hides.

Adds Opus 5, Sonnet 5, and Fable 5, refreshes OpenAI to the gpt-5.x line and
Google to gemini-3.x, and fixes the Gemini 2.5 Flash label, which claimed
$0.15/$0.60 against an actual $0.30/$2.50. Every number here is read out of the
0.83 registry rather than hand-copied. Sonnet 5's $2/$10 is introductory
pricing, so it gets a comment pointing at the registry as the real source.

Also teaches shortModelLabel about the fable family -- without it the footer
renders a raw "claude-fable-5" where every other model gets a friendly name.

No change needed in exec-guard's tier classifier, which I'd initially suspected:
Opus 5 and Sonnet 5 match the existing opus/sonnet markers, and Fable 5 and
Gemini 3.x Pro both clear the trusted price threshold on their own.
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.

1 participant