* Review changes (P1): add overlayPathIntoTree git primitive
Add `IAgentHostGitService.overlayPathIntoTree(base, path, source)` which
builds a new tree equal to `base` with a single repo-relative path replaced
by (or removed to match) the content in `source`, using a throwaway
GIT_INDEX_FILE so the user's real index is untouched.
This is the file-level building block for the upcoming reviewed-ref based
"review changes" feature: mark reviewed = overlay from the working-tree
snapshot; unmark = overlay from the baseline tree.
Includes the `parseSingleLsTreeEntry` helper and real-git integration tests
covering modified, added, and removed paths, plus the non-git no-op case.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Review changes (P2): extract shared Branch Changes baseline resolver
Extract the Branch Changes baseline resolution so the changeset service and
the upcoming review service cannot drift on which baseline they use:
- Add `IAgentHostGitService.resolveBranchBaselineCommit(workingDirectory,
baseBranch?)` which resolves the merge-base commit-ish the Branch Changes
diff is anchored on (origin/<base> preference, HEAD fallback, empty-tree
fallback). `computeSessionFileDiffs` now delegates to the same private
`_resolveBranchMergeBaseCommit` helper -- pure refactor, no behavior change.
- Add the pure `resolveDiffBaseBranchName(persisted, gitState)` helper for the
base-branch-name precedence and use it from the changeset service.
Adds unit tests for both pure helpers and real-git integration tests for
`resolveBranchBaselineCommit`; existing `computeSessionFileDiffs` tests still
pass.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Review changes (P3): add reviewed-ref review service core
Add `IAgentHostReviewService` and its node implementation, tracking which
files in a session's Branch Changes the user has reviewed as a session-private
synthetic git ref (`refs/agents/<sid>/reviewed`) whose tree snapshots the
reviewed content.
- `markFileReviewed` overlays the file's current working-tree content into the
reviewed tree; `unmarkFileReviewed` resets it to the baseline content. Each
action appends a parent-chained commit (first parent = baseline commit) and
advances the ref; no-op mutations are skipped so the chain doesn't grow.
- `getReviewedPaths` derives review status from git trees: reviewed = Branch
Changes files whose reviewed-tree content matches the working tree. Editing a
reviewed file therefore auto-unreviews it.
- Mutations/reads are serialized per session; the reviewed ref is deleted on
session data disposal. Operations no-op when not in a git work tree (a future
milestone adds the non-git DB fallback).
Also adds the `diffTreePaths` git primitive used to compute review status, and
wires the service into the agent-host node and server entry points. Covered by
real-git integration tests.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Review changes (P4): wire the review operation handler + provider
Add `AgentHostReviewFileOperationHandler` (mark/unmark, one instance per
direction) and `AgentHostReviewOperationContribution`, advertising the
`mark-as-reviewed` / `mark-as-unreviewed` resource-scoped operations for the
Branch Changes changeset and delegating to `IAgentHostReviewService`.
The handler resolves the session's working directory and base branch (via the
shared `resolveDiffBaseBranchName`) so review status is keyed on the same
baseline the Branch Changes diff uses.
Plumb the review service into `AgentService`'s inner DI (mirroring the
checkpoint service, defaulting to `NULL_REVIEW_SERVICE`) and register the
contribution. Covered by handler unit tests using a fake review service.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Review changes (P5): surface per-file review status on the Branch changeset
Populate `ChangesetFile._meta.reviewed` for the Branch Changes changeset so the
client can render reviewed/unreviewed affordances per file:
- Inject `IAgentHostReviewService` into the changeset service and, when
publishing the Branch changeset, look up the reviewed repo-relative paths and
set `_meta.reviewed` per file (keyed by the file id's repo-relative path).
- Extract the base-branch resolution into a shared `_resolveBranchBaseBranch`
helper reused by the diff computation and the review-status lookup.
- After a mark/unmark, the operation handler triggers `refreshBranchChangeset`
so the updated `_meta.reviewed` is republished (the working tree is unchanged
by a review toggle, so no file-watcher event would otherwise fire).
Adds a reusable `createNoopChangesetService` test helper, updates the handler
test to assert the refresh, and threads the new dependency through existing
agent-host test fakes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Review changes (P6): copy the reviewed ref on session fork
Add `IAgentHostReviewService.copyReviewedRef(source, target, workingDirectory)`
which points the forked session's reviewed ref at the same commit as the
source's, so a fork starts with the parent's review progress. No-op when the
source has no reviewed ref or the directory is not a git work tree.
Wire it into the Copilot session-fork path (best-effort, after the forked
session's database is copied), and inject the review service into CopilotAgent.
Covered by a real-git integration test.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* More refactoring/cleanup
* More changes to get things working
* Fix the actions in the toolbar
* Collapse multi-file diff item that is reviewed
* Remove precondition
* Fix tests + pull request feedback
* Fix hygiene
* Skip integration tests for now
* Make the UI snappier
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
fix: zero-pad percent-encoding for code points below 0x10 in UriTemplate
pctEncode emitted '%' + chr.toString(16) without padding, so a code point < 0x10 produced a single-digit escape (e.g. tab -> %9, newline -> %0A becomes %A, CR -> %D) instead of the RFC 3986/6570 two-digit form. The result is a malformed URI that decodeURIComponent rejects with "URI malformed". UriTemplate is used to resolve MCP and agent resource URIs, where a variable value containing a control character would yield a broken URL.
Zero-pad to two hex digits with padStart(2, '0'); this is a no-op for code points >= 0x10, so existing escapes (%20, %21, ...) are unchanged. Adds a regression test.
* sessions requiring input
* Dismiss blocked-sessions dropdown + context-specific requires-input messages
- Close the dropdown on Escape or an outside click (contextView onDOMEvent)
- Show a specific titlebar message when all blocked sessions share one reason (terminal approval, failing CI, question, unresolved comments); fall back to the generic 'N sessions require input' for a mix
- Animate the first requires-input appearance (preserve the blink class across redundant re-renders)
Removes the standalone "Subagents" dropdown above the chat input and
instead surfaces a chat's subagents as a separate group at the bottom of
the Conversations menu, scoped to the currently-active chat.
- Delete SessionAgentsControl and its CSS; drop it from ChatView.
- SessionConversationsMenuContribution now registers the active chat's
subagents in a `2_subagents` group below the session's chats.
- Add SessionActiveChatHasSubagentsContext so the Conversations menu
surfaces even when the parent is the only committed chat.
- Show the chat tab strip as soon as the session has any subagent, so
the Conversations menu moves to the tab bar.
- Add a regression test asserting a spawned subagent chat is resolvable
from the inline pill resource via parseChatUri (the Open-Subagent
contract), guarding against the pill/catalog identity desyncing.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* theme: add foreground color for problems warning icon in 2026 Light theme
css: remove opacity adjustments for warning and info labels in chat widget
* theme: update foreground color for problems warning icon in 2026 Light theme
Co-authored-by: Copilot <copilot@github.com>
---------
Co-authored-by: mrleemurray <mrleemurray@users.noreply.github.com>
Co-authored-by: Copilot <copilot@github.com>
The chat list rows span the full viewport width while the item container is centered with a max-width, leaving gutters on either side. The base list stylesheet sets cursor: pointer on rows, so the gutters showed a pointer cursor even though the item container uses cursor: default. Force default cursor on chat list rows so the gutters match.
Fixes#324173
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Some deps ship their native binary in a per-platform package declared as an
*optional* dependency of a small base package (e.g. `@openai/codex` ->
`@openai/codex-<platform>-<arch>`, `@anthropic-ai/claude-agent-sdk` ->
`@anthropic-ai/claude-agent-sdk-<platform>-<arch>`). npm does not fail when an
optional dependency can't be installed, so a transient hiccup can leave the base
package present but the per-platform package missing — and that broken tree then
gets frozen into the shared node_modules cache and served to every consumer
(see #323881).
Add build/azure-pipelines/common/checkNativeOptionalDeps.ts and run it after
`npm ci` in the linux, macOS and windows cache-build jobs (before the cache is
saved). For each configured base package that is installed, it asserts the
matching `<base>-<platform>-<arch>` package exists, and fails the job otherwise
so a poisoned cache is never saved.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Remove the system-wide keybindings first-run dialog
The first-run notice could appear in multiple windows at once on startup, and
the single-window election meant to prevent that was racy across concurrently
syncing renderers. Rather than harden the election, remove the dialog entirely:
the feature is always on and users who opt a keybinding into "systemWide" know
what they are doing.
This deletes the whole notice path, which existed only to serve the dialog:
- renderer: drop the first-run notification, the acknowledged-storage gate, and
the IDialogService/IStorageService deps; sync() now just warns about ignored
when-clauses and pushes to the main process.
- main process: drop the elected-window bookkeeping so INativeSystemWideKeybindingResult
only reports failures.
- update the systemWide keybindings.json schema description and drop the
now-obsolete election unit tests.
Global registration and trigger routing are unchanged.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Add a specification doc for system-wide keybindings
Co-locate an architecture/spec document next to the renderer contribution so
future work has the full feature context (user contract, renderer<->main-process
flow, the systemWide flag plumbing, design rationale, tests, and gotchas).
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Bump @anthropic-ai/claude-agent-sdk to 0.3.198
Bumps the pinned Claude agent SDK from 0.3.187 to 0.3.198 following
build/agent-sdk/README.md: updates the exact version in the build
agent-sdk pin and its lockfile, plus the matching root devDependency
types pin and root lockfile so shipped types and the build-time pin
stay in lockstep.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Implement Query.reinitialize in test fakes
0.3.198 adds reinitialize() to the SDK's Query interface. Add the
matching stub to the three test doubles that implement Query
(FakeQuery, RoundTripQuery, ImmediatelyDoneQuery), following each
file's existing "not modeled" pattern.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Refine how VS Code-configured MCP servers reach the agent host:
- resolveCustomizationRefs now excludes workspace-discovered MCP servers
by default, since the agent host discovers workspace `.mcp.json` itself
(via enableConfigDiscovery). The exception is `.vscode/mcp.json`, which
the SDK does not discover: those servers are synced explicitly, but only
when their config resolves without user interaction. Resolution uses
IConfigurationResolverService.resolveAsync + ConfigurationResolverExpression
and skips servers that reference interactive variables (${input:…},
${command:…}) or fail to resolve.
- Enable `enableConfigDiscovery` when creating/resuming Copilot agent-host
sessions so the host discovers workspace `.mcp.json` on its own.
- Move MCP_CONFIGURATION_COLLECTION_ID_PREFIX and add
McpCollectionDefinition.isWorkspaceDiscovered / isVscodeMcpJson helpers to
mcpTypes so the collection-classification logic lives in one place.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Support local folder paths in Install Plugin from Source
"Install Plugin from Source" now accepts local folder paths (file:// URIs,
absolute paths, and ~-prefixed paths) in addition to GitHub shorthand and
git URLs. Local folders are inspected to route them to the right setting: a
marketplace (has marketplace.json) is registered under chat.plugins.marketplaces,
while a standalone plugin (has a single-plugin manifest) is registered under
chat.pluginLocations.
Also consolidates installPluginFromSource and installPluginFromValidatedSource
into a single result-returning installPluginFromSource; callers now surface
source-level error messages themselves.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address review: verify trust before persisting local marketplace
Declining the trust prompt for a local folder that is a marketplace no longer
persists it under chat.plugins.marketplaces; the trust check now runs before
config is written, mirroring the git path. Also fixes a chat.plugins.marketplaces
doc typo in AGENTS_PLUGINS.md.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chat: show "Starting MCP servers…" hint for slow agent-host startup
When a new agent-host turn begins and one or more MCP servers stay in the
`starting` state past a short grace period (5s) without any content arriving
from the host, surface a lightweight progress hint listing the servers still
starting. The hint is observable-backed: it updates as servers finish and hides
itself once every server has started, content starts being received, or the
turn ends — whichever happens first. There is no interactive affordance (no
"Skip").
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>