Claude agent — Phase 7: tool permission round-trip + interactive tools#315399
Merged
TylerLeonhardt merged 2 commits intomainfrom May 8, 2026
Merged
Claude agent — Phase 7: tool permission round-trip + interactive tools#315399TylerLeonhardt merged 2 commits intomainfrom
TylerLeonhardt merged 2 commits intomainfrom
Conversation
Wires the Claude SDK's canUseTool callback through to the host. ExitPlanMode = permission gate; AskUserQuestion = user-input prompt. Adds cross-message tool_use to tool_result correlation in ClaudeMapperState with defense-in-depth cleanup on result.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR advances the Claude agent integration (Phase 7) by wiring the Claude SDK’s tool permission callbacks through the agent host so tool invocations can be permission-gated, and by correctly routing the two interactive built-in tools (ExitPlanMode and AskUserQuestion) according to their semantics (permission vs structured user input). It also extends the Claude SDK message mapper to correlate tool_use → tool_result across multiple SDK envelopes and adds new helper modules plus broad unit/integration test coverage.
Changes:
- Implement host-side
canUseToolhandling with per-tool routing: standard tools viapending_confirmation,ExitPlanModevia custom confirmation buttons,AskUserQuestionviaSessionInputRequested. - Extend the Claude mapper with per-session state to emit tool-call lifecycle actions (
SessionToolCallStart/Delta/Complete) and correlatetool_usewith latertool_resultuser envelopes. - Add new Claude tool display + interactive-tool projection helpers and snapshot/unit/integration tests; update docs and smoke procedures accordingly.
Show a summary per file
| File | Description |
|---|---|
| src/vs/platform/agentHost/node/claude/claudeAgent.ts | Wires canUseTool/onElicitation, adds interactive-tool handling, and forwards permission-mode changes between turns. |
| src/vs/platform/agentHost/node/claude/claudeAgentSession.ts | Adds pending permission/user-input maps and threads per-session mapper state into the mapper. |
| src/vs/platform/agentHost/node/claude/claudeMapSessionEvents.ts | Adds stateful mapping for streamed tool_use and synthetic tool_result, and part-id disambiguation across SDK messages. |
| src/vs/platform/agentHost/node/claude/claudeToolDisplay.ts | New tool-name→permission/display helpers and confirmation titles. |
| src/vs/platform/agentHost/node/claude/claudeInteractiveTools.ts | New pure projections for ExitPlanMode confirmation UI and AskUserQuestion input/answer mapping. |
| src/vs/platform/agentHost/node/sessionPermissions.ts | Allows agents to supply custom confirmation options, falling back to standard options. |
| src/vs/platform/agentHost/test/node/claudeAgent.test.ts | Adds Phase 7 unit coverage for permission round-trips, interactive tools, and permissionMode propagation. |
| src/vs/platform/agentHost/test/node/claudeAgent.integrationTest.ts | Extends proxy-backed integration tests to validate callback wiring and a Read-tool round-trip. |
| src/vs/platform/agentHost/test/node/claudeMapSessionEvents.test.ts | Adds direct mapper tests for tool-use/result lifecycle, attribution, and cleanup. |
| src/vs/platform/agentHost/test/node/claudeMapSessionEventsTestUtils.ts | Adds test helpers for input_json_delta and synthetic user tool_result envelopes. |
| src/vs/platform/agentHost/test/node/claudeToolDisplay.test.ts | New snapshot tests for tool display/permission mapping and path extraction. |
| src/vs/platform/agentHost/test/node/claudeInteractiveTools.test.ts | New unit tests for interactive-tool projections and answer flattening. |
| src/vs/platform/agentHost/node/claude/smoke.md | Updates smoke guidance and artifacts for Phase 7 tool/permission/user-input flows. |
| src/vs/platform/agentHost/node/claude/roadmap.md | Updates roadmap notes around permission semantics and deferred enhancements. |
| src/vs/platform/agentHost/node/claude/phase7-plan.md | Updates Phase 7 plan with post-implementation corrections and detailed steps/notes. |
| src/vs/platform/agentHost/node/claude/phase6.1-plan.md | Updates Phase 6.1 notes to reflect ExitPlanMode routing correction. |
| src/vs/platform/agentHost/node/claude/CONTEXT.md | Updates canonical routing table and clarifies SDK-side auto-approval vs host UI bridge behavior. |
Copilot's findings
Comments suppressed due to low confidence (1)
src/vs/platform/agentHost/node/claude/claudeToolDisplay.ts:106
getClaudeToolDisplayNamereturns the MCP fallback string using a template literal (Run MCP tool ...) without localization. Since this is user-facing, it should belocalize(...)(with a{0}placeholder) like the confirmation titles are.
export function getClaudeToolDisplayName(toolName: string): string {
const entry = TOOL_DISPLAY[toolName];
if (entry) {
return entry.displayName;
}
if (toolName.startsWith(MCP_TOOL_PREFIX)) {
return `Run MCP tool ${toolName.slice(MCP_TOOL_PREFIX.length)}`;
}
return toolName;
- Files reviewed: 17/17 changed files
- Comments generated: 6
Contributor
blocks-ci screenshots changedReplace the contents of Updated blocks-ci-screenshots.md<!-- auto-generated by CI — do not edit manually -->
#### editor/codeEditor/CodeEditor/Dark

#### editor/codeEditor/CodeEditor/Light

#### editor/inlineChatZoneWidget/InlineChatZoneWidget/Dark

#### editor/inlineChatZoneWidget/InlineChatZoneWidget/Light

#### editor/inlineChatZoneWidget/InlineChatZoneWidgetTerminated/Dark

#### editor/inlineChatZoneWidget/InlineChatZoneWidgetTerminated/Light
 |
- Localize TOOL_DISPLAY display names + MCP fallback (claudeToolDisplay) - Symmetric id derivation in flattenAskUserAnswers / buildAskUserSessionInputQuestions for empty-header questions - Await Query.setPermissionMode in ClaudeAgentSession.setPermissionMode and at the sendMessage callsite so the SDK acks the mode change before the next prompt yields - Guard JSON.stringify trace serialization behind getLevel() <= LogLevel.Trace - Observe options.signal in _handleCanUseTool: deny on already-aborted, race the parked permission/user-input prompt with the abort listener - Add unit tests covering the empty-header round-trip and both abort paths
anthonykim1
approved these changes
May 8, 2026
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.
Phase 7: wires the Claude SDK's
canUseToolcallback through to the host so tool invocations can be permission-gated, and routes the two interactive built-in tools per their actual semantics.What's in
_handleCanUseToolinclaudeAgent.tsroutes per-tool: most tools auto-approve;ExitPlanModeis a permission gate (session.requestPermission→pending_confirmation);AskUserQuestionis a structured user-input prompt (session.requestUserInput→SessionInputRequested).ClaudeMapperStatenow trackstool_use→tool_resultcorrelation across messages (the SDK delivers them in separate envelopes), with defense-in-depth cleanup on everyresultenvelope so an unmatchedtool_usecannot leak across turns.claudeInteractiveTools.tsandclaudeToolDisplay.tsmodules for the interactive-tool registry and tool naming/display.Tests
SDK tool_use→pending_confirmation→respondToPermissionRequest(true)→tool_result→ continuation), and an orphan-tool_usecleanup test that proves the mapper's cross-message maps are drained even when notool_resultarrives.Docs
phase7-plan.md,CONTEXT.md,roadmap.md,smoke.mdupdated to reflect the per-tool routing split.ExitPlanMode= permission,AskUserQuestion= user input — these were initially conflated in the plan and have been corrected throughout.