agent-host: report git-driven session file diffs#312632
Merged
roblourens merged 8 commits intomainfrom Apr 27, 2026
Merged
Conversation
Adds an alternative diff source for agent sessions that derives changes from the working-tree git state instead of from edit-tool emissions, so edits made via terminal/shell commands also show up in the Changes view. Approach -------- * IAgentHostGitService gains computeSessionFileDiffs() and showBlob(). * gitDiffContent.ts encodes 'git-blob:' content URIs that pin a blob to a session + sha + repo-relative path. * AgentService routes 'git-blob:' resourceRead requests to gitService.showBlob(); AgentHostFileSystemProvider.stat() short- circuits 'git-blob:' alongside 'session-db:' so the diff editor's stat-then-read flow works end-to-end. * AgentSideEffects._tryComputeGitDiffs runs after each turn (debounced with the existing diff scheduler) and overrides edit-tool diffs when git is available. Tests ----- Unit + integration coverage in src/vs/platform/agentHost/test/node/.
Adds five tests against AgentHostFileSystemProvider covering the synthetic content scheme fast-path in stat(): git-blob: and session-db: URIs must return a File stat directly without trying to list a parent directory that doesn't exist. Verified by reverting the git-blob: branch of the theallowlist new 'git-blob: stat' and 'full stat-then-read round-trip' tests fail with EntryNotFound, which is exactly the error the diff editor surfaced when opening a diff of a new file. (Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a git-driven session diff pipeline in the agent host so the “Changes” view reflects working-tree modifications (including terminal/shell edits) rather than relying solely on edit-tool emissions.
Changes:
- Extend
IAgentHostGitServicewithcomputeSessionFileDiffs()(git diff vs merge-base) andshowBlob()(git show for baseline content). - Introduce
git-blob:content URIs and routeresourceRead+ filesystemstat()so diff editors can read baseline blobs end-to-end. - Prefer git-derived diffs in
AgentSideEffectswith fallback to the existing edit-tracker aggregator; add unit/integration/protocol tests for coverage.
Show a summary per file
| File | Description |
|---|---|
| src/vs/platform/agentHost/node/agentHostGitService.ts | Implements git-driven diff computation, temp-index flow for untracked files, and blob retrieval. |
| src/vs/platform/agentHost/node/gitDiffContent.ts | Defines git-blob: URI encoding/decoding for baseline blob content. |
| src/vs/platform/agentHost/node/agentSideEffects.ts | Prefers git-driven diff computation per session, with fallback to edit-tracker diffs. |
| src/vs/platform/agentHost/node/agentService.ts | Routes git-blob: resourceRead requests to gitService.showBlob(). |
| src/vs/platform/agentHost/common/agentHostFileSystemProvider.ts | Treats git-blob: URIs as readonly files in stat() to satisfy diff editor flows. |
| src/vs/platform/agentHost/node/copilot/copilotAgent.ts | Persists base-branch metadata (META_DIFF_BASE_BRANCH) for merge-base anchoring. |
| src/vs/platform/agentHost/node/agentHostServerMain.ts | Reuses a single git service instance for AgentService and agent registration. |
| src/vs/platform/agentHost/test/node/gitDiffContent.test.ts | Unit tests for git-blob: URI round-tripping and non-matching inputs. |
| src/vs/platform/agentHost/test/node/agentHostGitService.test.ts | Unit tests for untracked parsing, raw/numstat parsing, and empty-tree SHA export. |
| src/vs/platform/agentHost/test/node/agentHostGitService.integrationTest.ts | Real-git integration tests for computeSessionFileDiffs() and showBlob(). |
| src/vs/platform/agentHost/test/node/agentSideEffects.test.ts | Verifies git-driven diffs override edit-tracker diffs and fallback behavior. |
| src/vs/platform/agentHost/test/node/protocol/sessionDiffs.integrationTest.ts | Protocol integration test verifying session/diffsChanged broadcast with git diffs. |
| src/vs/platform/agentHost/test/node/protocol/sessionDiffsRealSdk.integrationTest.ts | Gated real-SDK end-to-end test ensuring terminal-driven edits appear in summary.diffs. |
| src/vs/platform/agentHost/test/node/mockAgent.ts | Adds a mock prompt that edits files “via terminal” without file-edit content events. |
| src/vs/platform/agentHost/test/node/agentService.test.ts | Updates git service stubs for the expanded interface. |
| src/vs/platform/agentHost/test/node/copilotAgent.test.ts | Updates git service test stub to match the expanded interface. |
| src/vs/platform/agentHost/test/node/copilotGitProject.test.ts | Updates git service test stub to match the expanded interface. |
| src/vs/platform/agentHost/test/common/sessionTestHelpers.ts | Updates noop git service stub to match the expanded interface. |
Copilot's findings
- Files reviewed: 19/19 changed files
- Comments generated: 5
- agentHostGitService: bump default execFile maxBuffer to 32MB so diff output in large repos doesn't fail with ENOBUFS and silently drop terminal-driven diffs. - agentHostGitService.showBlob: validate sha is a hex object name before passing it to git, so a malformed git-blob: URI can't inject options or resolve to surprising refs. - mockAgent terminal-edit branch: void+catch the async IIFE so a filesystem failure surfaces as a chat delta instead of an unhandled rejection (test flake source). - agentSideEffects.test: replace setTimeout(100) with awaiting the SessionDiffsChanged envelope event for both new diff-computation deterministic and immune to slow CI.tests - sessionDiffsRealSdk integrationTest: shell-quote the target file path so temp dirs containing spaces don't break the prompt. (Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…stGitService Replace direct fs/promises and os.tmpdir usage with platform services so the temp-index dance in computeSessionFileDiffs goes through the same file system abstraction as the rest of the workbench. (Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Mirrors the extension's buildTempIndexEnv which sets this flag to avoid holding the GVFS command hook lock during temp-index git operations. (Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Instead of threading gitService through IAgentSideEffectsOptions, register it in the local ServiceCollection and inject it via @IAgentHostGitService decorator, which is the normal pattern everywhere else. (Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ven-diff-reporting
…difiedUri for deletions For deleted files, the 'modified' side of the diff editor must be absent. The renderer detects deletions via `change.modifiedUri === undefined`, so producing `IChatSessionFileChange2` (which carries a `uri` key alongside optional `modifiedUri`) is the right shape. Previously diffsToChanges returned IChatSessionFileChange (required modifiedUri) and fell back to the deleted file's pre-deletion path as modifiedUri, causing the diff editor to try to read a nonexistent file. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
osortega
approved these changes
Apr 27, 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.
Adds an alternative diff source for agent sessions that derives changes from working-tree git state instead of from edit-tool emissions, so edits made via terminal/shell commands also show up in the Changes view.
Approach
IAgentHostGitServicegainscomputeSessionFileDiffs()andshowBlob(). Diffs come fromgit diff --raw --numstatagainst the merge-base of HEAD and an optional base branch (META_DIFF_BASE_BRANCHin session metadata). Untracked files are included via a temp-index trick (read-tree HEAD+add -Ain a throwawayGIT_INDEX_FILE).gitDiffContent.tsencodesgit-blob:content URIs that pin a blob to a session + sha + repo-relative path.AgentServiceroutesgit-blob:resourceReadrequests togitService.showBlob().AgentHostFileSystemProvider.stat()short-circuitsgit-blob:URIs alongsidesession-db:so the diff editor's stat-then-read flow works end-to-end.AgentSideEffects._tryComputeGitDiffsruns after each turn (debounced with the existing diff scheduler) and overrides edit-tool diffs when git is available; falls back to the edit-tool path otherwise.Tests
gitDiffContent.test.ts),parseGitDiffRawNumstatadd/modify/delete/rename + numstat pairing.agentHostGitService.integrationTest.ts—computeSessionFileDiffs+showBlob.agentSideEffects.test.ts— verifies git-driven path overrides edit-tool diffs and falls back when git returns undefined.protocol/sessionDiffs.integrationTest.ts—session/diffsChangedround-trip with mock git.protocol/sessionDiffsRealSdk.integrationTest.ts(skipped without env var).(Written by Copilot)