Repository navigation
feat: edit managed-model context windows in Settings - #1221
Conversation
The context-window normalizer refused any value in models.json that was not a positive safe integer, on the client and in the route. pi itself accepts any positive number (400000.5 loads and resolves), so one hand-edited override blocked every later Save, even an edit to an unrelated custom provider. parseContextWindow() now keeps the field's rule for what the user types (text must be a whole token count) and only pi's own check for a number already in the file. A value pi refuses still stops the save, since pi drops the whole models.json on a schema error, and the message names the model's provider/id so the field can be found. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each managed model row carried a 180px block: a repeated "Context window (tokens)" label, an input, a Default button and a "Currently: N" line, which took rows from 43.5px to 78px (117.5px on a phone, where the block wrapped under the name) and nearly doubled OpenRouter's 393-row list. The row now holds one compact numeric text field between the name and the switch. Its placeholder is the window pi resolves for the model, so a blank field reads as "no override" without a Default button or a current-value line; clearing it removes the override as before. The model's name stays in its aria-label, a title says the unit, and the single note above the list says what the fields are and that loaded sessions need a restart. An invalid draft keeps its red border, and the refused Save names the model in the footer. Measured in headless Chrome, rows are 43.5px at 1280px and 390px, as on main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e loading An entry holding only modelOverrides is hidden from the custom providers once /api/auth/providers names its managed provider. Until that request answers both lists are empty, so the entry was listed as a custom provider (with its "+ Model" row) for as long as the request took, then vanished. The entry now waits for the lists to answer before it can be listed as custom; a failed request still lists it, as before this change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lib/model-context.ts and components/ModelContextWindow.tsx were missing from the File Map, and the models.md entry under Topic Notes did not list them, so a change to either would not lead to the note that explains the overrides. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e loading The previous commit kept an overrides-only entry out of the custom provider list until /api/auth/providers answers, but the detail pane still opened it. With no remembered selection the panel selects the first models.json key, and a user who only set an override has exactly that entry first: for as long as the provider lists took, the pane showed a custom-provider form for openai-codex (Delete, Provider name, Base URL) beside a list that did not show it, then jumped to the subscription. The pane now opens the custom form only for an entry the list shows as custom, so it stays on its empty state until the lists answer and the existing redirect moves it to the managed provider. A failed request still lists and opens the entry as custom, as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks @22zyfeng-collab! I checked this on a merge with main first: pi 1.2.0 really applies The one thing I wanted changed was the weight of each row: the field took every model row from 43.5 to 78 px (117.5 px on a phone), so OpenRouter's 393 rows grew from about 17.5k to 31k px. I pushed five commits on top of your branch so it can go in:
Checked on a merge with main: tsc, lint and the full unit suite pass, your e2e check passes in headless Chrome at 1280x800 and 390x844, and a real save round trip against next dev with a scratch agent dir writes, keeps and removes the override as expected. |
…ntexts serviceWorkers: "block" makes reading navigator.serviceWorker throw a SecurityError in production builds, so PwaRegistration's register call became a page error and the width check failed. The routes need no block: sw.js leaves every /api/ request to the network, where page.route sees it, as checkModelDiscovery's routes already do. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Summary
Add context-window inputs to Settings → Models for managed providers, including account/OAuth models such as ChatGPT Plus/Pro. Custom models already expose this setting; managed models currently require editing
models.jsonby hand.providers[provider].modelOverrides[modelId].contextWindow; no SDK patches or new dependencies.Application semantics
This changes Pi's context accounting, not the upstream provider's actual capacity. New session runtimes read the saved value. Loaded sessions need a Pi Web restart: an integration check confirmed that Pi 1.2's
/reloadretains their old model metadata, so the help text deliberately does not promise that/reloadapplies this edit.Verification
npm run lintpassed.checkModelContextagainst the packed production build at 1280px and 390px: edit, shared Save, reopen, invalid draft, server refusal/retry, Default, preservation of unrelated configuration, and no duplicate provider row.contextUsage.contextWindowchanged 272000 → 500000 → 272000, without changing auth.json or sending inference requests.Existing test limitations
The full suite was attempted on Windows/Node 24 and did not finish cleanly. Unrelated MCP component/transport failures also reproduce on an untouched v0.12.1 worktree (53 failures among 62 tests in
components/McpConfig.test.mjsandapp/api/mcp/test/route.test.mjs). These baseline issues are not changed by this PR; I am not claiming a green full suite.The E2E runner blocks service workers so its API route fixtures also intercept requests in production mode.