Align local & remote agent host sessionType IDs#311301
Align local & remote agent host sessionType IDs#311301roblourens wants to merge 1 commit intomainfrom
Conversation
Fixes a routing bug in the Agents window where, after switching from a
remote-agent-host workspace to a local-agent-host workspace (or vice
versa) for the same project path, the next 'Send' was sometimes routed
to the previous (wrong) host. This happened when both hosts had a
coincidentally-identical project path on disk.
Root cause:
SessionTypePicker.selectedType mirrors the active session's
ISession.sessionType (which was per-provider scoped). Local copilot's
logical sessionType was 'agent-host-copilot', while remote copilot's
was 'copilotcli'. When the user picked a workspace served by a
different provider, the stale id was forwarded to
SessionsManagementService.createNewSession(), which forwarded it to the
target provider, which threw because the id was unknown to it. The
throw was unhandled in the picker's selection emitter, so the active
session was never the picker label updated, giving falsereplaced
and the user's next request went to the still-activeconfidence
wrong-provider session.
Fix:
Local copilot now aliases its logical ISession.sessionType to
COPILOT_CLI_SESSION_TYPE ('copilotcli'), matching what remote already
did. Both sides advertise the same logical sessionType for copilot, so
the picker's stale-id forwarding no longer mismatches when crossing
remote. Resource URI schemes still differlocal
('agent-host-copilot' for local, 'remote-<auth>-copilot' for remote)
that's necessary for routing.
Cleanup:
- Hoisted WELL_KNOWN_AGENT_SESSION_TYPES, wellKnownSessionType,
wellKnownAgentProvider, DEFAULT_AGENT_HOST_PROVIDER from the remote
provider into BaseAgentHostSessionsProvider.
- Hoisted _syncSessionTypesFromRootState and
logicalSessionTypeForProvider into the base; the base now defines
the shape and the subclasses supply only resourceSchemeForProvider,
_formatSessionTypeLabel, and an _onSessionTypesUpdated hook.
- Removed _getSessionTypesFromContributions from
it was a pre-rootState-hydrationLocalAgentHostSessionsProvider
fallback that could never fire in production (the only registrant of
agent-host-* contributions, AgentHostChatContribution, is also
driven by IAgentHostService.rootState).
Diagnostics:
Diagnostic logs added in NewChatViewPane._createNewSession and
SessionsManagementService.createNewSession will be removed before
merge.
(Written by Copilot)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Screenshot ChangesBase: Changed (5) |
There was a problem hiding this comment.
Pull request overview
This PR fixes a session routing bug in the Agents window by ensuring Copilot sessions use the same logical ISession.sessionType (copilotcli) across both local and remote agent-host providers, preventing stale picker IDs from being forwarded to the wrong provider after switching workspaces.
Changes:
- Centralized “well-known” agent provider → logical sessionType aliasing (notably
copilot→copilotcli) inBaseAgentHostSessionsProvider. - Updated local and remote agent-host session providers to use shared logical-type/resource-scheme mapping logic (resource schemes remain host/connection-specific for routing).
- Updated local provider tests to reflect the new logical sessionType behavior and removed the pre-hydration contribution fallback behavior.
Show a summary per file
| File | Description |
|---|---|
| src/vs/sessions/services/sessions/browser/sessionsManagementService.ts | Exports the service class and adds additional create-session logging. |
| src/vs/sessions/contrib/remoteAgentHost/browser/remoteAgentHostSessionsProvider.ts | Adopts shared base logic for logical session types and resource-scheme mapping; rebuilds type→scheme map via base hook. |
| src/vs/sessions/contrib/chat/browser/newChatViewPane.ts | Adds diagnostic logging when creating a new session from picker selection. |
| src/vs/sessions/contrib/agentHost/test/browser/localAgentHostSessionsProvider.test.ts | Updates expectations: local Copilot advertises logical sessionType copilotcli; adjusts hydration-related tests. |
| src/vs/sessions/contrib/agentHost/browser/localAgentHostSessionsProvider.ts | Uses base logical session-type aliasing; separates logical sessionType from routing scheme (agent-host-*). |
| src/vs/sessions/contrib/agentHost/browser/baseAgentHostSessionsProvider.ts | Introduces shared well-known sessionType aliasing and shared rootState→sessionTypes reconciliation logic. |
Copilot's findings
Comments suppressed due to low confidence (1)
src/vs/sessions/services/sessions/browser/sessionsManagementService.ts:273
- These new
logService.infocalls log repository URIs / resource schemes and will add noisy info-level logging (potentially including local paths / remote authorities). This should be removed before merge (or downgraded to trace with appropriate redaction).
this.logService.info(`[SessionsManagementService] createNewSession providerId='${providerId}' repositoryUri='${repositoryUri.toString()}' sessionTypeId='${sessionTypeId}'`);
const session = provider.createNewSession(repositoryUri, sessionTypeId);
this.logService.info(`[SessionsManagementService] createNewSession created session sessionId='${session.sessionId}' sessionType='${session.sessionType}' resourceScheme='${session.resource.scheme}' providerId='${session.providerId}'`);
- Files reviewed: 6/6 changed files
- Comments generated: 2
| const ACTIVE_PROVIDER_KEY = 'sessions.activeProviderId'; | ||
|
|
||
| class SessionsManagementService extends Disposable implements ISessionsManagementService { | ||
| export class SessionsManagementService extends Disposable implements ISessionsManagementService { |
There was a problem hiding this comment.
The class was made export but there are no imports of SessionsManagementService in the repo; exposing it increases the module’s public surface area unnecessarily. Please revert this to a non-exported class and keep the service reachable via ISessionsManagementService/registerSingleton only.
This issue also appears on line 270 of the same file.
| export class SessionsManagementService extends Disposable implements ISessionsManagementService { | |
| class SessionsManagementService extends Disposable implements ISessionsManagementService { |
| } | ||
|
|
||
| private _createNewSession(selection: IWorkspaceSelection, sessionTypeId: string | undefined): void { | ||
| this.logService.info(`[NewChatViewPane] _createNewSession providerId='${selection.providerId}' workspaceUri='${selection.workspace.repositories[0].uri.toString()}' sessionTypeId(from picker)='${sessionTypeId}'`); |
There was a problem hiding this comment.
This new info-level log line includes the selected workspace URI (often a local file path) and is likely diagnostic-only. Please remove it before merge (or downgrade to trace with redaction) to avoid log noise and leaking paths.
| this.logService.info(`[NewChatViewPane] _createNewSession providerId='${selection.providerId}' workspaceUri='${selection.workspace.repositories[0].uri.toString()}' sessionTypeId(from picker)='${sessionTypeId}'`); |
Fixes a routing bug in the Agents window where, after switching from a remote-agent-host workspace to a local-agent-host workspace (or vice versa) for the same project path, the next "Send" was sometimes routed to the previous (wrong) host. This happened when both hosts had a coincidentally-identical project path on disk.
Root cause
SessionTypePicker.selectedTypemirrors the active session'sISession.sessionType, which was per-provider scoped:agent-host-copilotcopilotcliWhen the user picked a workspace served by a different provider, the stale id was forwarded to
SessionsManagementService.createNewSession(), which forwarded it to the target provider, which threw because the id was unknown to it. The throw was unhandled in the picker's selection emitter, so the active session was never replaced — the picker label updated, giving false confidence — and the user's next request went to the still-active wrong-provider session.Fix
Local copilot now aliases its logical
ISession.sessionTypetoCOPILOT_CLI_SESSION_TYPE(copilotcli), matching what remote already did. Both sides advertise the same logical sessionType for copilot, so the picker's stale-id forwarding no longer mismatches when crossing local↔remote.Resource URI schemes still differ (
agent-host-copilotfor local,remote-<auth>-copilotfor remote) — that's necessary for routing.Cleanup along the way
WELL_KNOWN_AGENT_SESSION_TYPES,wellKnownSessionType,wellKnownAgentProvider,DEFAULT_AGENT_HOST_PROVIDERfrom the remote provider intoBaseAgentHostSessionsProvider._syncSessionTypesFromRootStateandlogicalSessionTypeForProviderinto the base; the base now defines the shape and the subclasses supply onlyresourceSchemeForProvider,_formatSessionTypeLabel, and an_onSessionTypesUpdatedhook._getSessionTypesFromContributionsfromLocalAgentHostSessionsProvider— it was a pre-rootState-hydration fallback that could never fire in production (the only registrant ofagent-host-*contributions,AgentHostChatContribution, is also driven byIAgentHostService.rootState).To do before merge
logService.infocalls inNewChatViewPane._createNewSessionandSessionsManagementService.createNewSession(and theexportonSessionsManagementServicethat was left over from a deleted test).(Written by Copilot)