[Bug]: Pi text generation fails for models that a Pi extension adds, even though the model picker offers them#19053

opened15d agobySSpyrosPsarras

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/server

Steps to reproduce

  1. Create a Pi extension that adds a provider, for example ~/.pi/agent/extensions/demo-provider.ts:

    ts
    1import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
    2
    3export default function (pi: ExtensionAPI) {
    4 pi.registerProvider("demo", {
    5 baseUrl: "http://127.0.0.1:9/v1",
    6 apiKey: "unused",
    7 api: "openai-completions",
    8 models: [{
    9 id: "demo-model", name: "Demo Model", reasoning: false, input: ["text"],
    10 cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
    11 contextWindow: 128000, maxTokens: 4096,
    12 }],
    13 });
    14}

    Real setups do the same through provider packages listed in settings.json packages.

  2. In T3 Code, open Settings and set the text generation model to Pi → demo/demo-model. The picker lists it because model discovery runs Pi with extensions loaded.

  3. Start a new Pi thread and send a message.

The Pi step alone reproduces it, outside T3:

sh
1cd "$(mktemp -d)"
2echo '{"id":"1","type":"set_model","provider":"demo","modelId":"demo-model"}' \
3 | pi --mode rpc --no-session # success: true
4echo '{"id":"1","type":"set_model","provider":"demo","modelId":"demo-model"}' \
5 | pi --mode rpc --no-session --no-extensions --no-tools # Model not found: demo/demo-model

Expected behavior

The text generation model setting and the Pi process that text generation launches agree on which models exist. Either text generation can use a model the picker offers, or the picker does not offer models that text generation cannot load and says why.

Actual behavior

Every Pi text generation request fails at set_model. That includes thread titles, commit messages, PR content and branch names. The thread keeps its truncated first-message title.

Cause, on main @ 6524a8d:

  • Model discovery, packages/provider-pi/src/server/status.ts makePiDiscoveryConnection, calls buildPiRpcLaunch without disableExtensions. Extension-registered providers load and their models are listed.
  • Text generation, packages/provider-pi/src/server/textGeneration.ts, passes disableExtensions: true, so Pi starts with --no-extensions --no-tools. --no-extensions also skips the provider packages in Pi's settings.json, so the provider does not exist and set_model fails. The comment there says "User model config and auth still apply", which holds for models.json providers but not for extension-registered ones.

The disableExtensions: true choice itself makes sense, because no user is present to answer an extension dialog. The two launches just disagree about the model catalog.

Verified: the Pi RPC repro above on Pi 1.1.0, and the matching server log line on the nightly. Not verified: the full T3 UI flow with the demo extension; I observed it with a real extension-registered provider.

Impact

Major degradation or frequent failure

Version or commit

t3 0.0.46-nightly.20261012.3010; code paths unchanged on main @ 6524a8d

Environment

Linux x64, t3 server mode, Pi 1.1.0, text generation provider: Pi with an extension-registered provider

Logs or stack traces

shell
1Thread title generation failed
2 TextGenerationError generateThreadTitle: Pi text generation failed.
3 PiRpcError set_model: Model not found: <provider>/<model>

Screenshots, recordings, or supporting files

No response

Workaround

No response

Note

Grok responding on behalf of Julius.

Thanks. I checked both code paths on main, and they match your description.

  • makePiDiscoveryConnection (packages/provider-pi/src/server/status.ts) calls buildPiRpcLaunch without disableExtensions, so models from extension-registered providers show up in the catalog.
  • textGeneration.ts passes disableExtensions: true and disableTools: true.

Disabling extensions is intentional, because no user is around to answer an extension dialog during background generation, and we're keeping it. The bug is that the picker offers text-generation models that this launch can't load. The comment there ("User model config and auth still apply") only holds for models.json providers.

Workaround: under Settings → text generation model, pick a built-in Pi model, a provider defined in ~/.pi/agent/models.json, or a different provider (Codex or Claude).

Likely fix: don't offer extension-registered models for Pi text generation. That means tagging the discovered models by where they came from, or running a second discovery with --no-extensions, and then showing a clear error explaining why. We wouldn't re-enable extensions here.

This is separate from #17895 (extension dialogs) and #15529 (discovery timeout).

Note

🤖 Claude Opus 5.5 responding on behalf of Theo

Thanks for the report. One part of this is fixed on main in #19070. Please test on the nightly built from main on 2026-10-21, or on the next stable release. One part is still open: the picker still offers extension-only models and generation still fails. If that part still matters to you, please open a new issue for that part only.