Agents - generate titles for untitled external sessions - #331985
Merged
Benjamin Christopher Simmonds (benibenj) merged 8 commits intoAug 22, 2026
Merged
Conversation
External sessions whose provider surfaces them without a title showed up unnamed in the sessions list. Generate one from the user's first prompt, reusing the existing rename infrastructure. Adds a deferred-work lane on AgentService: `markStartupComplete()` is signalled by the process mains, and work queued through `_runWhenStartupSettled` runs once that and the first served session listing have both happened. Background maintenance therefore never competes with startup, and the service owns no ambient timer. The stale external-session prune moves onto the same lane, replacing its 60s timer. Discovery and legacy migration queue newly registered external sessions that have no provider title. The job keeps the 2 most recently updated candidates, reads the first user prompt from the default chat, and hands it to `AgentHostSessionTitleController.generateExternalSessionTitle`, which reuses the same utility-model prompt, cleaning, persistence, and cancellation as first-message titling. Sessions that already carry a persisted title are left alone, and a rename during generation cancels it. Since these sessions are surfaced but not live, `updateSurfacedSessionTitle` pushes the title onto the surfaced summary so clients update in place. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot started reviewing on behalf of
Benjamin Christopher Simmonds (benibenj)
August 21, 2026 15:22
View session
Copilot started work on behalf of
Benjamin Christopher Simmonds (benibenj)
August 21, 2026 15:28
View session
Copilot stopped work on behalf of
Benjamin Christopher Simmonds (benibenj) due to an error
August 21, 2026 15:29
Contributor
There was a problem hiding this comment.
Pull request overview
Adds deferred title generation for untitled external agent sessions after startup settles.
Changes:
- Introduces serialized post-startup maintenance for pruning and title generation.
- Generates and persists titles for the two newest untitled external sessions.
- Updates surfaced session summaries and protects concurrent user renames.
Show a summary per file
| File | Description |
|---|---|
agentService.ts |
Schedules maintenance and external-session titling. |
agentHostSessionTitleController.ts |
Generates, applies, and persists external titles. |
agentHostStateManager.ts |
Updates surfaced session titles. |
agentSideEffects.ts |
Exposes external title generation. |
agentHostMain.ts |
Signals desktop host startup completion. |
agentHostServerMain.ts |
Signals server startup completion. |
agentService.test.ts |
Tests deferred candidate selection. |
agentHostSessionTitleController.test.ts |
Tests persistence, updates, and rename protection. |
Review details
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
- Files reviewed: 8/8 changed files
- Comments generated: 3
- Review effort level: Balanced
Benjamin Christopher Simmonds (benibenj)
enabled auto-merge (squash)
August 21, 2026 15:57
Copilot started work on behalf of
Benjamin Christopher Simmonds (benibenj)
August 21, 2026 15:58
View session
Co-authored-by: benibenj <44439583+benibenj@users.noreply.github.com>
Co-authored-by: benibenj <44439583+benibenj@users.noreply.github.com>
roblourens
previously approved these changes
Aug 21, 2026
- `generateExternalSessionTitle` returned a promise that resolved before generation had run, because `_generateTitleSoon` starts the work fire-and-forget. The awaited loop in `_titleUntitledExternalSessions` therefore launched both model calls concurrently and `whenDeferredWorkSettled()` reported completion while generation and persistence were still in flight, breaking the lane's serialization contract. Split out `_startTitleGeneration`, which returns the tracked promise, and await it on the external-session path. - `listSessions` marked the first listing as served from its rejection handler too, so deferred maintenance could start after a failed listing and compete with the retry the gate exists to protect. Keep in-flight cleanup on both paths but only set the flag on fulfillment. - `agentHostMain` marked startup complete while the configured WebSocket server was still being created and wired, so deferred work could begin concurrently with that remaining startup. Mark completion once the optional startup promise settles, keeping its non-fatal error handling. Adds a regression test for the failed-listing gate, and tightens the existing titling tests to assert the awaited-generation contract without polling. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
roblourens
previously approved these changes
Aug 21, 2026
Resolves a conflict in `_registerDiscoveredChats`: main replaced the `existing` provenance map with a `registeredKeys` set, so take main's `registeredKeys.add(...)` while keeping the collection of untitled external sessions for deferred titling. Also repairs `new AgentService(...)` in agentService.test.ts, which main left calling the pre-`IAgentServiceCore` 5-argument signature; it now uses the file's `createTestAgentService` helper like every other case. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…nal-session-rename-logic
Bhavya U (bhavyaus)
previously approved these changes
Aug 21, 2026
Mohammad javad Dianat (dianatofficial)
left a comment
There was a problem hiding this comment.
LGTM! Code changes are clean and well-structured.
Resolves a conflict in `agentService.ts` against "Simplify AgentService composition (#332035)", which moved the `agents` / `onDidStartTurn` getters out of `AgentService` into the composition/runtime layer and left the region overlapping the deferred-work lane this branch added. Takes main's removal of both getters, drops main's timer-based `_scheduleExternalSessionPrune`, and keeps the startup-settled lane that replaced it — the prune now runs through `_runWhenStartupSettled` like the external-session titling job. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…nal-session-rename-logic # Conflicts: # src/vs/platform/agentHost/node/agentService.ts
Sandeep Somavarapu (sandy081)
approved these changes
Aug 22, 2026
Benjamin Christopher Simmonds (benibenj)
merged commit Aug 22, 2026
4fae990
into
main
27 checks passed
Benjamin Christopher Simmonds (benibenj)
deleted the
benibenj/agents/external-session-rename-logic
branch
August 22, 2026 09:55
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
External sessions whose provider surfaces them without a title showed up unnamed in the sessions list. This generates one from the user's first prompt, reusing the existing rename infrastructure.
Deferred work
Rather than an ad-hoc timer,
AgentServicegets a single lane for maintenance that is fine to run late:markStartupComplete()is the explicit signal, called by the process mains —agentHostMainonce every ingress is wired,agentHostServerMainwhen it reportsREADY._runWhenStartupSettled(name, work)runs once that signal and the first served session listing have both happened, so background work never competes with startup. Jobs are serialized, failures are logged per job, and a disposal guard keeps work off a torn-down service.markStartupComplete().Titling external sessions
AgentHostSessionTitleController.generateExternalSessionTitle— the same utility-model prompt, cleaning, persistence and cancellation used for first-message titling.AgentHostStateManager.updateSurfacedSessionTitlepushes the title onto the surfaced summary and clients update in place; live sessions still go through the reducer.Validation
npm run typecheck-clientclean.agentService,agentHostSessionTitleController,agentHostStateManagerandagentSideEffectssuites, including four new tests: deferred titling of the 2 most recent candidates, surfaced-summary retitling, not clobbering a concurrent rename, and keeping an existing persisted title.sessionPermissionsfailures visible in a wider run reproduce on a clean checkout of this branch, so they are pre-existing and unrelated.