Skip to content

feat: auto-generate session title after the first completed run - #644

Open
looluo wants to merge 4 commits into
agegr:mainfrom
looluo:feature/auto-title-after-run
Open

feat: auto-generate session title after the first completed run#644
looluo wants to merge 4 commits into
agegr:mainfrom
looluo:feature/auto-title-after-run

Conversation

@looluo

@looluo looluo commented Aug 28, 2026

Copy link
Copy Markdown

Auto-generate session title after the first completed run

Today session titles are manual-only (top-bar "Generate title" button). This PR adds automatic titling: when a regular session's agent run settles and the session has no name, a title is generated with the session's own model and persisted.

Design

  • Server-side trigger. Wired into the existing onAgentRunComplete hook in AgentSessionWrapper, so background sessions, closed tabs, and multi-tab setups all behave identically — no browser needs to be watching. Subagent wrappers suppress this callback entirely.
  • Named sessions are never touched. The trigger condition is simply "session currently has no name": once any name exists (auto-generated, manual, or set in the pi TUI) it is never overwritten. A failed attempt retries naturally on the next completed run — no state, no queues.
  • Generation logic is reused as-is from lib/session-title.ts (shadow agent, session model, 90s timeout, no tool execution).
  • Concurrency. A globalThis-scoped in-flight guard is shared between the automatic hook and the manual /auto-name route; a manual click during automatic generation gets an explicit 409 instead of racing two shadow agents.
  • Browser propagation. A synthetic session_named event is emitted over the existing per-session SSE stream (typically still inside the 30s idle grace window) so open tabs refresh the sidebar immediately.
  • Setting. ~/.pi/agent/pi-web.jsonautoSessionTitle, default true; atomic writes preserve unknown fields. Missing file = enabled; malformed file fail-closes the hook; the field is read at run-completion time so toggling takes effect without reloading sessions. Toggle lives in Settings → General (GET/PUT /api/sessions/settings).

Commits

  1. feat: auto-generate session title after agent run completes — hook + shared guard
  2. feat: gate automatic session titles behind a pi-web setting — config module
  3. feat: broadcast automatic session titles over the event streamsession_named SSE event
  4. feat: add automatic session title toggle to general settings — API route + UI

Tests

Unit tests for the trigger condition (named/dead/disabled/generate-once/retry-after-failure), the lock's exclusivity, the settings module (defaults, fail-close, field-type fallback, unknown-field preservation, round-trips), the settings route validation, and source-inspection assertions for the hook wiring, lock sharing, and event pipeline — matching this repo's existing test conventions.

looluo added 4 commits August 28, 2026 11:36
Wire the existing title generation into the server-side
onAgentRunComplete hook: when a regular session's run settles and the
session has no name, generate and persist one. Named sessions are never
overwritten, so this succeeds at most once per session; failures retry
on the next completed run. A globalThis-scoped in-flight guard is
shared with the manual /auto-name route to prevent concurrent shadow
agents (manual requests now get a clear 409 instead of racing).
Add ~/.pi/agent/pi-web.json (atomic writes, unknown fields preserved)
holding autoSessionTitle, defaulting to enabled. A missing file means
enabled; a malformed file fail-closes the automatic hook; a wrong-typed
field falls back to the default. The setting is read at run-completion
time so toggling needs no session reload.
Emit a synthetic session_named event from the wrapper once a title is
persisted. useAgentSession handles it during the idle-stream grace
window and forwards to AppShell, which refreshes the sidebar and syncs
the selected session name without remounting the chat. Pure metadata:
the event never touches streaming state.
Expose the autoSessionTitle preference through GET/PUT
/api/auto-title-settings (same request guards as the other settings
routes) and a ConfigSwitch in the settings panel's general section.
The stored file is the single source of truth; no browser-side
preference that the server-side hook could not see.
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