Skip to content

feat(chat): choose the model that names a session - #1391

Closed
escapeWu wants to merge 1 commit into
agegr:mainfrom
escapeWu:feat/title-model-menu
Closed

escapeWu wants to merge 1 commit into
agegr:mainfrom
escapeWu:feat/title-model-menu

Conversation

@escapeWu

@escapeWu escapeWu commented Oct 22, 2026 •

Copy link
Copy Markdown

What

Right-clicking Generate title (press and hold on a phone, which has no right-click) opens a menu of the enabled models and, below them, the reasoning levels the chosen model supports. Picking a model names the current session with it right away. Picking a level only stores it, so a model and its level are set in one visit.

With nothing chosen, nothing changes: the session is named with its own model at the cheapest level it supports, as on main.

Related: #671 asked for a dedicated model and thinking level for title generation. #807 bounded the transcript the title is made from; this adds the choice of model and level.

How it works

  • The rows come from /api/models?cwd= (modelList and thinkingLevels), read on every open, so a model enabled since the last open is in the list. The row rules are pure and live in lib/title-menu.ts: a level survives clearing the model, a model survives clearing the level, and a chosen model only offers the levels it supports.
  • The choice is one value for the whole instance, kept in pi-web-title-model.json beside pi's own files (lib/title-model-preference.ts, GET/PUT /api/title-model), so every browser and device names sessions the same way. No file is the default and needs no write. It follows the pattern of pi-web-session-state.json. It is not a pi setting, and pi's settings.json is untouched, so the pi CLI is unaffected.
  • POST /api/sessions/[id]/auto-name reads the choice on every naming and resolves the model on the wrapper's modelRuntime, with one refresh({ allowNetwork: false }) first for a provider an extension registers at session_start. A model that no longer resolves logs a warning and names with the session's own model instead of failing the button.
  • A level stored on its own applies to whichever model names, and only when that model supports it (resolveTitleThinkingLevel()), so a level picked for one model is never sent to another.
  • The menu is the existing SidebarMenu (a bottom sheet on phones). There is no new toolbar control. New strings are in en, zh-CN and zh-TW, and docs/agents/sessions.md has the note.

Scope

This adds one instance-wide file for one value. I kept it there rather than per browser because the choice has to be the same on every device that reaches the instance, as the sidebar state is. If you would rather it live somewhere else, or not be stored at all, I am happy to rework it.

Verification

  • node_modules/.bin/tsc --noEmit — clean. npm run lint — clean.
  • npm test — 2881 tests, 2878 pass, 0 fail, 1 skipped. Two tests in lib/session-membership.integration.test.mjs timed out at 15 s in a run where two suites were going at once. That file passes on its own (2/2, 6 s) and this change does not touch session listing.
  • New coverage:
    • the menu's rows and the model/level rules (lib/title-menu.test.mjs),
    • reading, parsing and writing the preference file (lib/title-model-preference.test.mjs),
    • GET/PUT /api/title-model (app/api/title-model/route.test.mjs),
    • the override reaching the title request, and a level the model does not support (lib/session-title.test.mjs).

Not run: a browser pass of the right-click and long-press paths on this branch, and next build (per AGENTS.md).

Generate title can now name a session with a model of its own: a right-click
on the button, or a press and hold on a phone, opens a menu of the enabled
models with the levels each supports. The choice is one for the whole pi-web
instance (pi-web-title-model.json beside pi's own files, GET/PUT
/api/title-model), with the session's own model at its cheapest level when
nothing is chosen, and a thinking level stored on its own still applies to
the session's model. A model row names the session right away; a level row
keeps the menu open, so both are set in one visit.
@escapeWu
escapeWu force-pushed the feat/title-model-menu branch from 80a394d to ae18371 Compare October 22, 2026 07:45
@escapeWu escapeWu closed this Oct 26, 2026
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