Strip redundant cd <workingDirectory> && prefix from agent host shell tool calls#312019
Merged
roblourens merged 5 commits intomainfrom Apr 22, 2026
Merged
Strip redundant cd <workingDirectory> && prefix from agent host shell tool calls#312019roblourens merged 5 commits intomainfrom
cd <workingDirectory> && prefix from agent host shell tool calls#312019roblourens merged 5 commits intomainfrom
Conversation
…ll tool calls The Copilot CLI sometimes emits shell commands prefixed with a redundant `cd <` even though the agent already runs in thatworkingDirectory> && directory. The extension-host CLI strips this for display; this change brings the same cleanup to the agent host so all clients see the simplified command. Three live paths needed patching: - mapSessionEvents.ts (history replay via getMessages()) - copilotAgentSession.ts onToolStart (live tool execution) - copilotToolDisplay.ts getPermissionDisplay (shell permission requests) All three share a new helper, stripRedundantCdPrefix, in src/vs/platform/agentHost/common/commandLineHelpers.ts. Tests: 32 new unit tests across commandLineHelpers, copilotToolDisplay, mapSessionEvents, and copilotAgentSession (109 passing total in the agentHost module). Also added an opt-in real-SDK integration test in toolApprovalRealSdk.integrationTest.ts that exercises the full toolCallReady path with a live model (mock-agent integration tests can't reach this code because the mock IAgent bypasses CopilotAgentSession entirely). (Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
Contributor
There was a problem hiding this comment.
Pull request overview
This PR standardizes the “redundant cd <workingDirectory> && prefix” cleanup inside the agent host so that shell tool invocations shown to AHP clients match the already-stripped display in the extension-host CLI.
Changes:
- Added
extractCdPrefix/stripRedundantCdPrefixhelper incommandLineHelpers.tsand applied it across history replay, live tool events, and permission display. - Threaded
workingDirectorythroughCopilotAgent→CopilotAgentSessionand intomapSessionEvents/getPermissionDisplayso stripping can be conditional on the session CWD. - Added unit tests across the helper + affected call sites, plus a gated real-SDK integration test.
Show a summary per file
| File | Description |
|---|---|
| src/vs/platform/agentHost/common/commandLineHelpers.ts | New helper for detecting/stripping redundant cd prefixes from shell commands. |
| src/vs/platform/agentHost/node/copilot/mapSessionEvents.ts | Strips redundant cd prefixes during history replay when workingDirectory is known. |
| src/vs/platform/agentHost/node/copilot/copilotToolDisplay.ts | Strips redundant cd prefixes for shell/custom-tool permission request display. |
| src/vs/platform/agentHost/node/copilot/copilotAgentSession.ts | Strips redundant cd prefixes for live tool_start events and threads workingDirectory through. |
| src/vs/platform/agentHost/node/copilot/copilotAgent.ts | Passes resolved workingDirectory into CopilotAgentSession creation. |
| src/vs/platform/agentHost/test/common/commandLineHelpers.test.ts | New unit tests for extractCdPrefix and stripRedundantCdPrefix. |
| src/vs/platform/agentHost/test/node/mapSessionEvents.test.ts | New tests validating history-replay rewriting behavior. |
| src/vs/platform/agentHost/test/node/copilotToolDisplay.test.ts | New tests validating permission-display rewriting behavior. |
| src/vs/platform/agentHost/test/node/copilotAgentSession.test.ts | New tests validating live tool-start rewrite + past-tense messaging. |
| src/vs/platform/agentHost/test/node/protocol/toolApprovalRealSdk.integrationTest.ts | New gated real-SDK integration test asserting stripped command reaches session/toolCallReady. |
Copilot's findings
- Files reviewed: 10/10 changed files
- Comments generated: 2
Two Copilot review comments on PR #312019: 1. `commandLineHelpers.ts` `sameDirectory` did string-compare the raw extracted directory against `workingDirectory.fsPath`. On Windows, `URI.file('/repo/project').fsPath` is `\repo\project` while the model often emits `cd / separator mismatch maderepo/` project && the prefix slip through. (This was the root cause of the Windows / Browser + Windows / Electron CI failures: 3 stripRedundantCdPrefix tests asserted on stripping behavior that only worked on POSIX.) Fix: route both sides through `URI.file(...)` (after trimming trailing separators) and compare via `extUriBiasedIgnorePathCase`, which handles separator normalization and case-insensitivity on Windows / macOS. Added two Windows-only test cases (forward-slash extracted vs native backslash wd, and pure-backslash same-direction) to cover the regression. 2. `toolApprovalRealSdk.integrationTest.ts` used a substring check miss quoted variants like `cd "<` or pwsh-stylewd>" && `cd <`. Replaced with an anchored regex that tolerateswd>; optional surrounding quotes and either chain operator. (Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
auto-merge was automatically disabled
April 22, 2026 22:42
Pull request was converted to draft
The merge of origin/main into the branch accidentally reverted the
title change from main ("Run in terminal" -> "Run in terminal?").
Restore both occurrences in getPermissionDisplay's shell + custom-tool
branches.
(Written by Copilot)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…-bash-commands-plan # Conflicts: # src/vs/platform/agentHost/node/copilot/copilotToolDisplay.ts
pwang347
approved these changes
Apr 22, 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.
The Copilot CLI sometimes emits shell commands prefixed with a redundant
cd <workingDirectory> && …even though the agent already runs in that directory. The extension-host CLI strips this for display; this PR brings the same cleanup to the agent host so all AHP clients see the simplified command.Three live paths
All needed patching, and all share a new helper
stripRedundantCdPrefixinsrc/vs/platform/agentHost/common/commandLineHelpers.ts:mapSessionEvents.ts— history replay viagetMessages().copilotAgentSession.tsonToolStart— live tool execution. Mutatesparameters.commandin place; because_activeToolCallsstores the same object,getPastTenseMessageinonToolCompleteautomatically sees the rewritten command.copilotToolDisplay.tsgetPermissionDisplay— shell permission requests (both'shell'and'custom-tool'kinds).Testing
commandLineHelpers,copilotToolDisplay,mapSessionEvents, andcopilotAgentSession. 109 tests passing total in the agentHost module.stripRedundantCdPrefixin each call site made the corresponding positive-path tests fail with the expected "expected stripped, got prefixed" assertion errors. Negative-path tests stayed green.toolApprovalRealSdk.integrationTest.ts("strips redundantcd <workingDirectory> &&prefix from shell tool calls"). Gated byAGENT_HOST_REAL_SDK=1, runs through the full WebSocket →CopilotAgentSession→session/toolCallReadyaction path with a live model. Mock-agent integration tests can't reach this code because the mockIAgentbypassesCopilotAgentSessionentirely.Notes
extractCdPrefix. Three copies now exist (workbenchrunInTerminalHelpers.ts, extensioncopilotCLITools.ts, agent hostcommandLineHelpers.ts) — worth a future consolidation pass, not in scope here.presentationOverrideswere considered as an alternative; chose to rewrite at the AHP boundary so every client sees the simplified command without coordinating override metadata.&&→;rewriting and sandbox/background-detach behavior the workbench has are out of scope; this only addresses the redundantcdprefix.(Written by Copilot)