* chat: normalize tool call IDs across model switches
Kimi requires function-indexed tool call IDs, while Anthropic accepts only a restricted character set. Normalize outbound request copies for each provider without mutating stored conversation history.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chat: avoid collisions in normalized tool call IDs
Reserve valid IDs before allocating sanitized Anthropic IDs, then reuse the request-scoped mapping for matching tool results.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* agent host e2e: reuse one replay server per suite for Copilot
The agent host e2e replay suite restarted the whole server (and re-spawned
the provider SDK/CLI subprocess) for every test. Profiling showed the
dominant per-test cost is server fork (~0.5s) plus the provider SDK client
cold start (~0.5s, an ~8MB CLI bundle loaded on the Electron-as-node
binary), with session teardown effectively free.
Reuse one server across the suite for providers that can be returned to a
clean state via disposeSession, swapping the per-test replay fixture on the
in-process CapiReplayProxy without restarting (the proxy URL the agent host
was forked against stays fixed):
- CapiReplayProxy: add resetForReplay (re-point at a new fixture, clear
replay buckets + cache-miss log), assertNoCacheMisses (verify strict
replay without stopping), and close (drop the socket without the strict
check). stop() now composes these.
- Add AgentHostE2EServerLease to encapsulate per-test vs shared strategies,
gated by a new supportsSharedReplayServer provider flag (replay only;
recording always uses a fresh proxy + fixture per test).
- Enable it for Copilot. Claude stays per-test: its mid-turn dispose can
wedge the shared agent host process, which per-test kill-and-refork
isolation guards against.
- Drain the permission test's post-tool continuation to turnComplete in all
modes so the session ends cleanly before dispose (returning mid-turn would
wedge the reused client).
Copilot suite drops from ~29s to ~14s mocha time. Claude and Codex are
unchanged (per-test path).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* agent host e2e: address Copilot review feedback
- CapiReplayProxy: route the constructor's fixture-existence check and error
message through this._fixturePath so all fixture-path access has a single
source of truth.
- AgentHostE2EServerLease.acquire: fail fast with a clear error instead of a
non-null assertion when a shared server unexpectedly has no capiReplay proxy.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* agent host e2e: document the shared replay server in the README
Add a "Server lifecycle" section covering the per-test vs shared strategies,
how AgentHostE2EServerLease and CapiReplayProxy.resetForReplay swap fixtures
without restarting (in-process, no IPC), why sharing is opt-in per provider
(Copilot yes, Claude no), and the "don't return mid-turn" rule for authors.
Also add the supportsSharedReplayServer gate row, list the lease in the
components table, and add a troubleshooting entry for cross-test state leaks.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* agent host e2e: enable the shared replay server for Claude and Codex
Investigated the long-standing "Claude mid-turn dispose wedges the agent
host" caveat that kept server reuse Copilot-only. It dates from the live
real-SDK era (real streaming turns actually in flight). In today's
deterministic replay suite there is no mid-turn dispose: the abort test is
record-only and every turn drains to `turnComplete` before teardown.
Deliberately reproducing the old failure (reverting the permission test's
drain) showed it is not a process wedge at all but a strict cache miss: an
undrained turn's continuation HTTP call fires after the fixture is swapped
and lands in the next test's window as an unrecorded call. The proxy detects
it loudly. The cure is exactly the drain already in place, so with every turn
drained there is nothing to leak.
Enable `supportsSharedReplayServer` for Claude and Codex (verified green and
stable across repeated runs; Claude ~16s -> ~9s, Codex likewise). Correct the
drain rationale and the README/lease/flag comments to describe the real
mechanism (leaked async traffic) instead of the "wedge" folklore.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* agent host e2e: drop supportsSharedReplayServer, share by default in replay
The flag was true for all three providers, so it modeled the wrong thing: a
per-provider capability, when the real requirement is a per-test invariant
(drain your turns) that every provider already meets. Server reuse is really
a property of replay mode, gated only by recording (which needs a fresh proxy
per fixture).
Remove the flag and make the lease share by default in replay
(`_shared = !RECORD`). No behavior change (all three suites already reused the
server); this just deletes dead config and the misleading "some providers
can't share" framing. Single-test isolation for diagnosing a cross-test leak
is still available via `--grep`.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Style overrides: Adjust line height for action labels and add gap for actions container
Co-authored-by: mrleemurray <mrleemurray@users.noreply.github.com>
* style: update margins and paddings for floating panels and status bar for improved layout consistency
* style: adjust status bar padding to account for border thickness
Co-authored-by: Copilot <copilot@github.com>
---------
Co-authored-by: mrleemurray <mrleemurray@users.noreply.github.com>
Co-authored-by: Copilot <copilot@github.com>
* Fix status dashboard checkbox flicker
Keep the language completion tri-state synchronized with configured settings while preserving immediate feedback and serialized writes.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 089ad95e-853f-4c52-8a82-3b463b724cb8
* Fix status dashboard browser test
Keep the regression test focused on the checkbox state, configured value, and override hint that this change owns.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 089ad95e-853f-4c52-8a82-3b463b724cb8
* Handle inherited completion overrides
Remove language entries from every configured scope, resync the override hint after failed writes, and keep the browser regression test focused on owned state.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 089ad95e-853f-4c52-8a82-3b463b724cb8
* Support platform-specific built-in extensions from GitHub releases
Adds support for downloading platform-specific built-in extension VSIXs
from GitHub releases, keyed by marketplace target platform. Also downloads
the latest pre-release assets for insiders builds, ignoring the pinned
version and checksum.
- extensionTarget.ts: resolve build target + release asset name
- builtInExtensions.ts: platformSpecific checksum map + insiders detection
- extensions.ts/fetch.ts: fromGithub asset selection + prerelease support
- CI: platform-aware cache key and target env plumbing
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Insiders downloads the latest release instead of latest pre-release
Insiders builds should always be on the newest published release, so the
GitHub download now resolves the most recently published release (including
pre-releases) rather than filtering to pre-releases only.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address code review feedback for platform-specific extensions
- Sort latest releases by published_at instead of created_at
- Log a warning when skipping checksum validation in latest mode
- Document that platform-specific extensions always download from GitHub
- Skip gracefully on unsupported platforms; keep a clear error for a
known target missing from the platformSpecific map
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address CCR feedback: restrict targets and harden helpers
- Restrict getExtensionTarget to the supported marketplace targets, returning
undefined for unsupported OS/arch (e.g. win32-ia32, linux-riscv64) so callers
skip gracefully instead of failing with a missing-asset error
- Remove the bogus ia32 -> x86 mapping (no win32-x86 target exists)
- Validate the target format in getPlatformSpecificAssetName and throw a clear
error for malformed targets
- Guard the latest-release sort against NaN timestamps (missing published_at
sorts to the end deterministically)
- Update tests accordingly
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Align asset naming with VS Code convention and support product.overrides.json
The platform-specific extension this feature targets (typescript-go's
TypeScriptTeam.native-preview) publishes VSIX assets named
<name>-<target>.vsix using the raw marketplace target platform, not the
node-vsce-sign osx/win/arm aliasing. Update getPlatformSpecificAssetName to
the standard <name>-<target>.vsix convention and validate against the
supported target set.
- fetch.ts: in latest mode, select the newest published release that actually
contains the requested asset, so releases shipping only other artifacts
(e.g. tarballs) without a matching VSIX are skipped
- builtInExtensions.ts: merge product.overrides.json (gitignored, local) so
overridden built-in extensions are downloaded, mirroring bootstrap-meta
- Update tests for the new naming convention
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Detect extensions project by path segment, not substring
ESBuildTranspiler decided CJS vs ESM output via configFilePath.includes('extensions').
When the repo is checked out (e.g. as a git worktree) into a folder whose name
merely contains the substring 'extensions', the 'src' project was wrongly treated
as an extension and transpiled to CJS, breaking top-level await in src/cli.ts,
src/server-cli.ts and src/server-main.ts. Match an 'extensions' path segment instead.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Remove product.overrides.json support from built-in extensions download
Revert the download script to read product.json directly, per review feedback.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Decorations - fall back to lower-priority colors
* Fix decoration badge color fallback
* Attestation commit
---------
Co-authored-by: Alex Ross <38270282+alexr00@users.noreply.github.com>
The agent-feedback overlay resolves a session's changed files from the
active editor via getActiveResourceCandidates, which only unwrapped a
plain MultiDiffEditorInput. In the single-pane side pane layout the
Changes editor is a SessionChangesEditorInput that wraps the multi-diff
input, so the file URIs could not be resolved and the Submit Feedback
action stayed hidden. Expose the wrapped input and unwrap it during
resolution so feedback affordances work in both layouts.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* sessions: polish hover tooltips on isolation checkbox and branch chip
- Remove the hover tooltip on the read-only Branch chip; its value is
already visible as the label and the generic schema description read
awkwardly as a hover for a fixed value.
- Reuse the schema's own 'worktree' enum description for the New
Worktree checkbox tooltip (e.g. 'Create a Git worktree for
isolation') instead of the generic isolation description, which had
an awkward tense for a checkbox.
Fixes#325662
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* sessions: keep Branch hover tooltip for the editable (worktree) chip
Only suppress the Branch tooltip when the chip is read-only; the
editable Branch chip under worktree isolation keeps its 'Base branch
to work from' description, which is useful context there.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix tunnelProtocol context key always resolving to https on focus
* Attestation commit
---------
Co-authored-by: Alex Ross <38270282+alexr00@users.noreply.github.com>
* agentHost: push BYOK models over onDidChangeModels
Change the reverse BYOK LM bridge from a pull model to a push model. The
renderer now owns its model set and pushes the current snapshot over
`onDidChangeModels` (on subscribe and on every change) instead of answering
`listModels()` round-trips. `IByokLmBridgeConnection.onDidChangeModels` becomes
required and carries `IByokLmModelInfo[]`; the client channel serves a snapshot
stream that enumerates renderer-locally and drops `listModels`.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* agentHost: cache pushed BYOK snapshots in the bridge registry
Subscribe to each connection's onDidChangeModels on register and cache the
pushed snapshot rather than enumerating connections. A connection becomes
serving once it pushes its first snapshot (even empty). Drop listModels and the
per-connection re-enumeration path from the registry.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* agentHost: read BYOK session models from the registry cache
Read the serving window's models from the registry's cache of renderer-pushed
snapshots. The renderer pushes on connect, so the cache is warm by session-create
time; drop the preferCache parameter and the live-enumeration fallback.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* agentHost: update BYOK tests for the push model
Rework the BYOK tests to drive connections by pushing model snapshots over
onDidChangeModels instead of scripting listModels, and assert against the
registry cache. Non-serving windows are modeled as connections that never push.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* agentHost: implement throttling for BYOK model snapshot emissions
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chat: flush queued/steering messages when a streamed session turn completes
Contributed chat sessions whose in-progress turn is streamed via
activeResponseCallback (progressObs) — e.g. Copilot cloud sessions —
register a synthetic pending request while streaming. A message sent
mid-turn is therefore queued as a steering/queued message. The
streaming-completion branch in loadRemoteSession deleted that pending
request without flushing the queue, so the queued message was stranded
in the model forever and never sent (steering 'limbo').
Mirror the normal request-completion path by calling
processPendingRequests when the streamed turn completes. It is a no-op
while another request is in flight and returns early for server-managed
(agent-host) queues, so it is safe on every completion tick.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chat: true mid-turn steering for cloud sessions
Builds on the queued-message flush fix to inject a steer into a live
cloud turn instead of only sending it after the turn settles, matching
github.com/copilot/agents.
Core (chatServiceImpl): for non-server-managed streamed
(activeResponseCallback) sessions, dispatch a queued Steering message
immediately when the in-flight pending request is the synthetic
streamed-turn tracker (no requestId) — never over a real in-flight
request. Re-establish tracking on the next progress tick so the turn
stays in-progress.
Extension (copilotCloudSessionsProvider):
- Track live TaskTurnStreamer taskIds; when a stream is already active,
handleTaskFollowUp only POSTs /steer and lets the running stream
render the injected result (no second streamer).
- Make the follow-up stream yield-aware (mirrors the Copilot CLI
provider): poll context.yieldRequested and return on yield so the
chat service flushes the next steer immediately.
- Choose the render mode from the pre-steer task state: a steer into an
active turn renders mode:'current' (the injection has no new
task.sessions[] row, so mode:'next' would time out); a steer onto a
settled task renders mode:'next'.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chat: address review — fix synthetic-tracker race, tracking restore, stale task state
- Identify the synthetic streamed-turn pending request via an explicit
WeakSet instead of `requestId === undefined`: real requests are inserted
into _pendingRequests before their requestId is assigned, so the old guard
could delete a live request and start a concurrent invocation.
- Restore in-progress tracking deterministically when the immediate-steer
dispatch settles (hook responseCompletePromise) instead of relying on a
future progress tick that may never fire.
- Cloud provider: treat a follow-up as mid-turn (render mode:'current')
only when BOTH the task and its latest turn are active, so a terminal
task with a stale in_progress latest turn doesn't pick a streamer that
exits before the steered turn appears.
- Rework the regression tests: the steering test now asserts immediate
dispatch, no duplicate dispatch on completion, and preserved in-progress
tracking; a separate test covers completion-flush of a non-steering
queued message.
- Condense multi-line inline comments.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Claude: rich rendering for Skill and task-list tools
The agent-host (Claude) chat rendered the Skill, TaskCreate, TaskUpdate,
TaskList and TaskGet tool calls as their bare tool name in the collapsed
row — you had to expand them to learn what happened. Every other Claude
built-in tool already shows a self-explanatory label.
Add these tools to the claudeToolDisplay mapping so they render rich
invocation / past-tense messages:
- Skill -> "Running skill `<name>`" / "Ran skill `<name>`"
- TaskCreate -> "Creating task: <subject>" / "Created task: <subject>"
- TaskUpdate -> status-aware: Starting/Completing/Deleting/Updating task
- TaskList -> "Reading task list" / "Read task list"
- TaskGet -> "Reading task" / "Read task"
Also give Skill a dedicated `skill` permissionKind (added to both the
Claude union and the shared IAgentToolPendingConfirmationSignal union) so
its confirmation prompt reads "Run skill?" rather than the generic
"Allow tool call?", driven by kind like every other tool.
Snapshot tests extended to cover the new tools and the TaskUpdate status
branches.
Fixes#325389
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Tighten readTaskUpdateStatus JSDoc
Address PR review: trim the helper's doc to the invariant callers need
rather than enumerating every branch.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
typescript: suppress Copilot Chat plugin crash notification
Do not show the JS/TS language service crash notification when Copilot Chat is the only contributing TypeScript server plugin. Continue reporting other plugins and preserve the existing no-plugin notification.\n\n(Written by Copilot)\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fix GitHub MCP initial authentication
Reuse the existing GitHub token for the official MCP endpoint's initial scope-less request, while preserving challenge scopes separately from the server's supported scope catalog.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* agentHost: Resolve symlinked read paths before auto-approval
Check literal and real paths against the session working directory and require confirmation when realpath resolution is denied. Exercise directory-link containment on Windows with junctions.\n\n(Written by Copilot)\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* agentHost: Preserve URI schemes in permission checks
Avoid resolving non-file working directories through the local filesystem and use URI-relative home dotfile detection so Windows path casing remains safe.\n\n(Written by Copilot)\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* agentHost: add Copilot SDK log level setting
Forward a VS Code setting through agent host root configuration and restart the Copilot SDK client when the startup-only value changes. Preserve the existing agent host log level mapping as the default.\n\n(Written by Copilot)\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address Copilot SDK log level review feedback
Make the shared setting application-scoped and resolve the default log level immediately before creating the SDK client.
(Written by Copilot)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix Copilot SDK startup config snapshots
Use the same captured values to construct startup-only SDK options and detect stale starts.
(Written by Copilot)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Simplify Copilot SDK log level setting
Limit the setting to info and trace while preserving VS Code trace logging as an additional way to enable full SDK diagnostics.
(Written by Copilot)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Restore slash command provider method spacing
Restore the separator accidentally removed while resolving merge hygiene.
(Written by Copilot)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Remove redundant hideEhCopilotCli visibility logic from session picker
The `_isVisible` override in SessionTypePickerActionItem duplicated the
Extension Host Copilot CLI hide check that isVisibleEditorChatSessionType
already performs (keyed on the same chat.editor.copilotCli.hideExtensionHost
setting). It also introduced an isSessionTypeVisible delegate hook that no
delegate ever implemented.
Restore _isVisible to the pre-#323914 one-liner that defers to the shared
isVisibleEditorChatSessionType, and drop the now-dead isSessionTypeVisible
member from the picker delegate interface. No behavior change: the hide rule
remains centralized in isVisibleEditorChatSessionType.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 53512dbc-d36f-4137-b6fe-739338b4844b
* Remove dead IAutomationSessionTypeProvider bridge
The IAutomationSessionTypeProvider abstraction was registered as a singleton
but never injected or called by anyone. It was intended as the layering seam
for a workbench-side automations UI to reach the Sessions layer, but the
automations dialog lives in vs/sessions and drives its session-type picker
(MobileSessionTypePicker) directly against ISessionsManagementService.
getSessionTypesForFolder, bypassing the bridge entirely.
Delete the interface, its IAutomationSessionTypeChoice type, the
AutomationSessionTypeProvider implementation, and the singleton
registration. No behavior change: the live path was always the sessions
picker.
In the Agents window single side-pane view, move the Run Code Review
action into the primary (left) editor header next to the diff-stats
action, in its own menu group so a separator renders before it.
The diff-stats action now always renders the rich, clickable "N files
+X -Y" pill (previously only shown when the editor area was collapsed;
a separate non-interactive label was shown when it was open). Clicking
it opens/re-opens the Changes editor regardless of editor-area state.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Follow-up to the cloud sessions v2 "Copilot stopped" work, addressing PR
review feedback:
- Add an explicit `default` branch to `isActiveTaskState` so an unknown
task state added server-side returns `true` (active) instead of falling
through to `undefined`. This matches `taskStateToChatSessionStatus`
(unknown -> InProgress) and avoids reintroducing the stuck "Session is
in progress..." spinner when the detail view would otherwise settle
while the session state still reads `in_progress`.
- Remove a stale duplicate comment block in the task history builder.
- Add tests covering `isActiveTaskState`/`isFailedTaskState` across all
states plus the unknown/forward-compat case.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore: bump windows-process-tree to 0.8.0
Picks up microsoft/vscode-windows-process-tree#87, which fixes
process command lines being converted with CP_ACP instead of CP_UTF8,
so non-ANSI characters (e.g. Cyrillic) rendered as ? in the Process
Explorer.
Fixes#219183
* fix: update allow-scripts
---------
Co-authored-by: deepak1556 <hop2deep@gmail.com>
* Fix: Preserve MCP server list selection/focus when list refreshes
When the MCP server picker list refreshes (e.g., servers are added/removed), the
selection state was being lost and jumping back to the first entry. This was
particularly noticeable when using arrow keys to navigate the list while the
servers were being updated.
This fix preserves the currently selected item ID before updating the items list.
When the list is updated, if the previously selected item still exists, it is
restored as the active selection. This ensures smooth navigation and maintains
user intent even when the underlying data changes.
Fixes#325588
* Fix: Preserve all focusable items in MCP server list when refreshing
Copilot review noted that the previous fix excluded special items (\ and
\) from focus restoration, but these items are always present and
keyboard-focusable. By excluding them from the restoration check, the focus
would still jump when users had these items selected during a list refresh.
This change removes those exclusions and restores any previously selected item
that still exists in the new list, regardless of whether it's a special item or
a server entry. The find() call already safely handles cases where items
disappear (e.g., \ when servers are available), so unrestricted
restoration is safe.