Skip to content

fix(models): list providers that extensions register at session_start - #1071

Open
SoulKyu wants to merge 1 commit into
agegr:mainfrom
SoulKyu:fix/deferred-extension-providers
Open

SoulKyu wants to merge 1 commit into
agegr:mainfrom
SoulKyu:fix/deferred-extension-providers

Conversation

@SoulKyu

@SoulKyu SoulKyu commented Oct 5, 2026

Copy link
Copy Markdown

Summary

Models of pi-claude-bridge showed in the picker only on the first listing after Pi Web started. They vanished as soon as the user switched folders, and a session could not start on them.

pi-web builds a fresh ModelRuntime for every model listing (createAgentSessionServices() in /api/models, /api/models/default, /api/models/enabled) and never starts a session in it. The bridge registers its provider eagerly only in the first runtime of a process. Later instances defer to session_start, so that a subagent sharing its parent's registry does not overwrite the parent's stream function. In pi-web, every runtime after the first therefore lacked the provider:

runtime 1: zai,claude-bridge
runtime 2: zai
runtime 3: zai

The same deferral breaks other hosts; it is tracked upstream in elidickinson/pi-claude-bridge#149. This PR makes Pi Web tolerate any extension that registers its provider at session_start.

Listings

  • lib/deferred-provider-models.ts remembers the available models of every runtime Pi Web builds: listings, createModelRuntimeWithExtensions(), and sessions once their extensions are bound.
  • withDeferredProviderModels() adds back the models of providers a runtime does not register at all. A provider it registered but cannot use (signed out, no key) is never added back, so auth state stays truthful.
  • When a new provider is remembered, the models cache is invalidated. Otherwise a listing cached before it would hide it for the cache lifetime.

Sessions

  • startRpcSession() builds a session whose requested model (new chat) or restored model (resumed chat) belongs to such a deferred provider on the default model. Once the extensions are bound and session_start has run, it switches to that model with set_model. Before, a new chat on a bridge model failed the scope check, and a resumed one silently fell back to the default.

Known limit: a project-only extension that defers its provider would also appear in other folders' listings. Picking it there leaves the session on its default model.

docs/agents/models.md gets a section on this, and the AGENTS.md file map is updated.

Test plan

  • tsc --noEmit, npm run lint, npm run build
  • npm test: 2286/2286. The new lib/deferred-provider-models.test.mjs covers:
    • a later runtime lists the remembered models, with and without a provider filter;
    • a registered but signed-out provider is not added back;
    • a deferred model is found only while the runtime lacks its provider.
  • Against a production build on a loopback port, with pi-claude-bridge 0.9.1 installed globally:
    • /api/models for folders A, B, C, then A again: every listing has claude-bridge (13 models) and zai (7). Before, only the first did;
    • POST /api/agent/new with claude-bridge/claude-haiku-4-5 in a folder that was not listed first: the session starts on Haiku and the reply comes from the bridge;
    • server restart, then reopening that session: get_state reports claude-bridge/claude-haiku-4-5, not the default model.

pi-web builds a fresh ModelRuntime for every model listing and never starts
a session in it. Extensions that register their provider only in the first
runtime of a process and defer later ones to session_start (pi-claude-bridge)
disappeared from the picker after the first listing, and a session could not
start on their models.

Remember the available models of every runtime pi-web builds and add back
providers a runtime does not register at all. A session whose requested or
restored model is deferred starts on the default and switches once its
extensions are bound.

This branch has not been deployed

No deployments
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