Master's log-backed session-title capability already titles sessions durably (deterministic fallback in the spine, optional model providers). Remove the TUI's own autoTitle generation — the latch, prompt, cap, and llm stream call — and keep the terminal rename: the TUI folds the logged title on mount and sets '<session title> — <configured title>' on every accepted session/title event. The tui-agent example and the scripted PTY fixture mount session-title-first-message-llm so titles stay model-made; the scripted adapter's tool-less branch now answers that provider's auxiliary request. See .agents/notes/implemented/simplification/2026-07-22-tui-titles-from-session-title-service.md
5.0 KiB
Agent Note: Auto-title on by default, re-derived on resume
Status: implemented
English | 中文
Superseded by the session-title consolidation Agent Note: the TUI-local
autoTitlegeneration is removed; titles come from the log-backed session-title service, and the terminal rename consumessession/titleevents.
Problem
The auto-title Agent Note shipped autoTitle off by default and, on a resumed session, kept the static title because the first user/message was already logged. In use both choices defeated the feature's purpose. A per-session descriptive pane title is what makes one tmux pane or terminal tab distinguishable from the next; leaving it off by default means the product ships an inert feature that almost no user turns on, and skipping re-derivation on resume means a resumed session — exactly the long-lived session most worth labelling — falls back to the shared static string. The user asked for a descriptive per-session name to be the normal experience.
Decision
autoTitledefaults on (z.boolean().default(true), mirrored byresolveTuiConfig's?? true). A deployment with anllmservice and an agent provider/model gets a model-made pane title on every session without opting in; one without them keeps the static title, so default-on is inert where the call cannot run.- A resumed session re-derives the title on mount from its already-logged first
user/message:createTuiChatscansagent.session.eventsfor the first such event and feeds its text to the same one-shotgenerateTitle. The title is never persisted (the session header carries no title field), so it is always derived, never restored. - The one-shot latch is now simply
titleSettled = !resolved.autoTitle. The prior pre-settle-on-resume clause is gone: on resumegenerateTitleruns once from the stored first message and then latches, so a message that arrives after the resume does not re-title. A fresh session has no storeduser/messageat mount, so the resume scan is a no-op and the livesession/eventlistener titles the first message instead. - Everything else from the auto-title Agent Note stands unchanged: the OSC 0
runtime.terminal.setTitlepath, the model-summary shape (two-to-five lowercase words, first non-empty line, 40-char cap), the fire-and-forgetctx.llm.streamcall that never touches the session or transcript, the shutdownAbortController, and every failure fallback (empty reply, missingllm, missing provider/model, whitespace-only prompt).
Alternatives considered
Keep the feature off by default. Rejected: this is a direct reversal of the auto-title Agent Note's "default off" decision at the user's request. Off-by-default ships an inert feature; the descriptive name is only useful if it is the normal experience. The keyless-replay concern that motivated off-by-default is addressed by pinning autoTitle: false in the replay-backed snapshot scenarios rather than by suppressing it for every deployment.
Persist the derived title in the session header. Rejected: the header has no title field and adding one would make a terminal label into session metadata — the boundary the auto-title Agent Note already drew against the log-backed session-title work. Re-deriving from the stored first message costs one tool-less call on resume and keeps the label a pure function of the conversation.
Re-derive on resume from the latest message instead of the first. Rejected: the title summarises what the session is about, which its opening request captures; a mid-conversation message would make the pane label drift as the work moves on.
Consequences
- A fresh session with a working
llmnow spends one extra tool-less model call by default (previously only when opted in); a resumed session spends one on mount. Deployments without anllmor provider/model are unaffected. - The replay-backed
examples/tui-agent/tests/tui.snapshot.tsmust opt out: it pinsautoTitle: false, because a default-on title request is not among the recorded turns andinstallLlmReplayfails loud on an unrecorded request. The unitpackages/ui/tui/tests/tui.snapshot.tsneeds no opt-out — it mounts nollmservice, sogenerateTitleshort-circuits and the default flip is inert there. The interactiveexamples/tui-agent/cordis.ymland the scripted PTY fixture already setautoTitle: true, so the keyless smoke's OSC 0 assertion is unchanged. packages/ui/tui/tests/tui.spec.tspins the new defaults: the config-default test expectsautoTitle: true; the disabled-path test now setsautoTitle: falseexplicitly; and the former "resumed session never fires" test is rewritten to assert re-derivation from the stored first message and that a later live message does not re-title.docs/config-catalog.mdregenerates to "On by default".