agentHost: route session state through chat channels#323223
Conversation
Move turn state and tool confirmations onto AHP chat channels so peer chats and subagents do not cross-talk. Persist draft/config metadata through side effects, harden malformed chat-channel handling, and keep subscription hydration from hanging on errors. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
📬 CODENOTIFYThe following users are being notified based on files changed in this PR: @benibenjMatched files:
@sandy081Matched files:
@lszomoruMatched files:
|
There was a problem hiding this comment.
Pull request overview
This PR migrates agent-host chat/session routing so turn state, tool confirmations, and subagent activity are dispatched and observed on the correct AHP chat channel URIs (instead of overloading the session URI), aligning the workbench, agent host, and tests with the multi-chat protocol split.
Changes:
- Workbench
AgentHostSessionHandlernow resolves and caches upstream chat channel URIs from hydrated session state and routes all chat-scoped actions through that mapped channel. - Agent host side-effects, permissions, and protocol handling are updated to treat chat channels as authoritative for chat actions, confirmations, and subagents (now modeled as chats).
- Adds
NKeyMapdeletion/query helpers and updates tests/docs to reflect the new chat-channel routing model.
Show a summary per file
| File | Description |
|---|---|
| src/vs/workbench/contrib/chat/browser/agentSessions/agentHost/agentHostSessionHandler.ts | Resolve/store chat URIs from hydrated state and route chat actions via chat channels. |
| src/vs/sessions/SESSIONS.md | Documents required producer behavior and subagent-as-chat model. |
| src/vs/sessions/services/sessions/common/sessionContextKeys.ts | Excludes tool-origin chats from “multiple chat” UI context keys. |
| src/vs/sessions/services/sessions/common/session.ts | Introduces chat origin concepts for sessions/chats. |
| src/vs/sessions/contrib/providers/agentHost/browser/baseAgentHostSessionsProvider.ts | Propagates backend chat origin into session chat objects. |
| src/vs/sessions/browser/parts/chatCompositeBar.ts | Hides tool-origin chats from the tab strip. |
| src/vs/platform/agentHost/test/node/mockAgent.ts | Updates mock progress signals to use chat channels (resource / chat). |
| src/vs/platform/agentHost/test/node/copilotAgentSession.test.ts | Provides default chat channel URI when constructing sessions. |
| src/vs/platform/agentHost/test/node/copilotAgent.test.ts | Updates action signals to use resource field. |
| src/vs/platform/agentHost/test/node/claudeSdkPipeline.test.ts | Passes chat channel URIs into Claude pipeline construction. |
| src/vs/platform/agentHost/test/node/claudeSdkMessageRouter.test.ts | Passes chat channel URIs into Claude message router construction. |
| src/vs/platform/agentHost/test/node/claudeMapSessionEvents.test.ts | Updates emitted signals to use resource field. |
| src/vs/platform/agentHost/test/node/claudeAgent.test.ts | Updates signal filtering and pending confirmation routing to chat channels. |
| src/vs/platform/agentHost/test/node/agentSideEffects.test.ts | Updates tests for chat-channel routing (but still contains critical misrouted signals). |
| src/vs/platform/agentHost/test/node/agentService.test.ts | Updates action signal envelope field naming (resource). |
| src/vs/platform/agentHost/test/node/agentHostTurnTelemetry.test.ts | Updates action signal envelope field naming (but still emits chat actions on session URI). |
| src/vs/platform/agentHost/test/common/agentSubscription.test.ts | Validates new subscription error event behavior. |
| src/vs/platform/agentHost/node/shared/agentFeedbackServerTools.ts | Treats input as chat URI and resolves back to owning session for annotations. |
| src/vs/platform/agentHost/node/sessionPermissions.ts | Requires confirmations to be handled on AHP chat channels. |
| src/vs/platform/agentHost/node/protocolServerHandler.ts | Uses strict session extraction from chat channel for orphan checks. |
| src/vs/platform/agentHost/node/copilot/copilotAgentSession.ts | Tracks chat channel URI; emits chat actions/confirmations on chat channel. |
| src/vs/platform/agentHost/node/copilot/copilotAgent.ts | Establishes default chat channel URI for sessions. |
| src/vs/platform/agentHost/node/codex/codexAgent.ts | Routes chat-scoped progress via default chat channel. |
| src/vs/platform/agentHost/node/claude/claudeSubagentSignals.ts | Emits subagent signals and chat actions on chat channel. |
| src/vs/platform/agentHost/node/claude/claudeSdkPipeline.ts | Accepts chat channel URI; emits chat actions on it. |
| src/vs/platform/agentHost/node/claude/claudeSdkMessageRouter.ts | Routes mapped signals to configured chat channel URI. |
| src/vs/platform/agentHost/node/claude/claudeMapSessionEvents.ts | Maps SDK events to agent signals using chat channel routing. |
| src/vs/platform/agentHost/node/claude/claudeAgentSession.ts | Establishes default chat channel URI; emits input/confirmations on it. |
| src/vs/platform/agentHost/node/claude/claudeAgent.ts | Updates customization action signal envelope field naming (resource). |
| src/vs/platform/agentHost/node/agentSideEffects.ts | Moves subagents to chats; routes confirmations/side effects on chat channels; uses NKeyMap. |
| src/vs/platform/agentHost/node/agentService.ts | Ensures confirmations are handled on chat channel; resolves session from chat channel strictly. |
| src/vs/platform/agentHost/node/agentHostStateManager.ts | Enforces chat actions must be dispatched on chat channels; adds chat origin support. |
| src/vs/platform/agentHost/common/state/sessionState.ts | Adds subagent chat URI builders/parsers and strict session extraction helper. |
| src/vs/platform/agentHost/common/state/agentSubscription.ts | Adds onDidError event for subscriptions. |
| src/vs/platform/agentHost/common/agentService.ts | Updates agent signal envelope fields for chat-channel routing. |
| src/vs/base/test/common/map.test.ts | Adds coverage for new NKeyMap APIs. |
| src/vs/base/common/map.ts | Implements NKeyMap.delete, deleteAll, and getAll with cleanup semantics. |
| .github/skills/sessions/SKILL.md | Documents the chat-channel routing requirements and subagent-as-chat design. |
Review details
Comments suppressed due to low confidence (2)
src/vs/platform/agentHost/test/node/agentSideEffects.test.ts:1560
- This ChatToolCallStart signal is still emitted on the session URI. With chat actions now required to target an
ahp-chat://...channel, this should use the default chat URI (or the relevant peer chat URI) so the state manager can apply it and follow-up tool confirmation routing works.
agent.fireProgress({
kind: 'action', resource: sessionUri,
action: {
type: ActionType.ChatToolCallStart, turnId: 'turn-1',
toolCallId: 'tc-perm-1', toolName: 'write', displayName: 'Write File', contributor: { kind: ToolCallContributorKind.Client, clientId: 'test-client' },
_meta: { toolKind: undefined, language: undefined },
},
});
src/vs/platform/agentHost/common/agentService.ts:746
- The doc comments still refer to routing inner
parentToolCallIdactions to a "subagent session" and say theresourcefor inner subagent events is the parent session. With this PR’s change to model subagents as chats and to require chat-scoped actions be emitted on the owningahp-chatchannel, this should describe the parent chat channel and routing to the subagent chat to avoid misguiding future producers.
/** Target session or chat channel URI. For inner subagent events this is the parent session — see {@link parentToolCallId}. */
readonly resource: URI;
/** Protocol action to dispatch. */
readonly action: SessionAction | ChatAction;
/** If set, route the action to the subagent session belonging to this tool call. */
readonly parentToolCallId?: string;
- Files reviewed: 38/38 changed files
- Comments generated: 3
- Review effort level: Low
Address PR feedback by requiring chat actions and tool confirmations to flow on their AHP chat channels. Fix disconnected-client cleanup to iterate chats explicitly, normalize telemetry ids, and unblock subscription hydration on errors. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Resolve upstream conflicts while preserving strict AHP chat-channel routing and the PR feedback fixes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Make agent sendMessage receive both the parent session URI and the owning chat URI explicitly. This keeps default-chat sends from being mistaken for base64 session IDs and preserves the strict chat-channel invariant. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fix client-tool completion routing to resolve providers by parent session while preserving the originating chat channel for provider callbacks. Update agent host unit and protocol fixtures to dispatch chat actions on explicit AHP chat channels and keep subagent chat state separated from parent sessions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| /** Timestamp of when the last agent turn ended, if any. */ | ||
| readonly lastTurnEnd: IObservable<Date | undefined>; | ||
| /** How the chat came into existence, if provided by the backend. */ | ||
| readonly origin?: IChatOrigin; |
There was a problem hiding this comment.
Later on I want to add an affordance like we have for terminals where the user can click a button to reveal a subagent chat in its own multi-chat tab. But for now, this just hides them (when origin is a tool call)
This cleans up our action routing. Previously with the multi-chat migration, we did some logic where we would still dispatch actions on the session but then route them to the default chat. This caused features in non-default chats (like subagent permission approvals, which is how I first went down this small rabbit hole) to not work.
In Copilot's words:
Summary
Validation