[pull] main from microsoft:main#1392
Merged
Merged
Conversation
Wrap the user callback of DisposableResizeObserver with scheduleAtNextAnimationFrame so layout writes done by the callback (scanDomNode, KaTeX layout, height assignments, ...) land in the next layout pass instead of re-entering the current one. Also coalesce multiple deliveries within a frame into a single callback invocation. This fixes the root cause of the "ResizeObserver loop completed with undelivered notifications" warning that has been the top error bucket since v1.106 (#293359 - 54M hits / 2.5M users). The warning is benign on its own (Chromium just defers the leftover entries to the next frame), but every occurrence costs an extra layout pass per frame on the affected element. With chat streaming UI (thinking, tool confirmations, plan review, KaTeX) all observing simultaneously, this adds up to several extra layout passes per streamed token on slow machines. Also accept an optional targetWindow so observers created for elements in an auxiliary window use that window's ResizeObserver constructor and animation-frame timer. Convert the three remaining raw `new ResizeObserver(...)` sites to use the wrapper so they inherit the batching + disposable lifetime: - chatMarkdownContentPart (KaTeX layout participants) - chatTerminalToolProgressPart (terminal output resize) - browserEditorFindFeature (find widget height tracking - now passes getWindow(container) to preserve aux-window correctness) Refs #293359
Addresses Copilot review feedback on #314411 — covers rAF deferral, per-frame coalescing, cancel-on-dispose, and reschedule-after-frame.
Addresses @mjbvz review on #314411 — drops the global mutation and any-casts in the DisposableResizeObserver test suite by adding an optional resizeObserverCtor parameter (DI). Also addresses Copilot's coalescing finding: per-target latest-wins so consumers reading entries[0] always see the freshest size.
…tions Records the rule that arose from review on #314411: don't mutate globals or use any-casts to install fakes in tests; inject the dependency via an optional constructor parameter.
…ution
Reverts the rAF deferral and per-frame coalescing introduced earlier in this PR. Behavior is now identical to the pre-PR sync wrapper, plus:
- targetWindow parameter (preserved) for aux-window correctness.
- try/catch around the user callback so a single bad consumer cannot kill delivery for every other observer in the realm.
- name + creationStack capture, plus a one-shot window 'error' listener that prints which DisposableResizeObservers' callbacks ran in the same task whenever the 'ResizeObserver loop completed with undelivered notifications' warning fires. The browser dispatches that warning as an ErrorEvent (not a thrown exception, error is null), so a try/catch around the callback cannot capture it; we use addEventListener('error', ...).
- resizeObserverCtor option for tests (DI seam, replaces global mutation in the test suite).
…r name Replace the previous suspect-set + window error listener attribution with a simpler design: - DisposableResizeObserver now takes a required `name: string` as its first constructor parameter. Drop the per-instance creation stack capture (callstacks change across releases and bloat telemetry). - Track the most recently invoked observer in a module-level slot and expose `getRecentDisposableResizeObserverAttributionForLoopError(msg)` which, for the stackless `ResizeObserver loop completed with undelivered notifications` warning, returns `[DisposableResizeObserver(<name>)] <msg>`. - Browser ErrorTelemetry uses the helper to prefix both `msg` and `callstack` so the telemetry bucket carries the offending observer's name instead of just the generic warning. - Name all 17 production sites with `<ClassName>.<purpose>` (e.g. ChatListItemRenderer.itemHeight, ChatInputPart.containerHeight). Refs #293359.
…microtask The slot is set just before the user callback runs and cleared by a microtask in the same step, so the attribution helper only returns a name when the loop warning fires in the same task as the offending observer's callback. Unrelated errors fired later in the renderer no longer inherit a stale observer name.
chat: add copy microinteraction to code blocks (#314490) Reuse the existing chat copy action view item for code block toolbars so the copy button shows the same copy-to-check transition, tooltip, ARIA label, and clipboard announcement as response copy actions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…setTimeout(0) queueMicrotask clears the slot too eagerly: Chromium runs a microtask checkpoint after each ResizeObserver callback returns, which is *before* the synthetic 'ResizeObserver loop completed with undelivered notifications' error fires at the end of the observation phase. A 0-ms timer runs after the entire current task (callbacks + loop-error dispatch) completes, so the slot is still set when window.onerror picks it up, while still being cleared before any unrelated error in the next task can inherit a stale name. Verified by hand in Code-OSS DevTools.
…-batch dom: attribute ResizeObserver loop telemetry to DisposableResizeObserver name
Add logging for unexpected InstancePolicy.prompt in sessions window
* Discover plugins installed by Copilot CLI (#302152) Adds `CopilotCliAgentPluginDiscovery` which scans `~/.copilot/installed-plugins/<marketplace>/< the two-levelplugin>/` directory layout used by the Copilot and surfaces each leafCLI directory as an `IAgentPlugin`, so CLI-installed plugins appear in VS Code without a separate install step. File watchers are set up on the root and each marketplace bucket so installs and uninstalls made via the CLI are reflected live. The remove() action prompts the user before deleting the directory from disk, since the CLI manages this location. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR review feedback - Watch the deepest existing ancestor of installed-plugins so the first-ever CLI install is detected without a reload (non-recursive Node watchers fail on ENOENT). - Use trash on UI-driven plugin removal and update the prompt detail to say so. - Wrap the recursive setupWatchers() call inside the change handler with a .catch() to keep watcher setup best-effort. - Update AGENTS_PLUGINS.md to accurately describe the (non-recursive) watcher strategy. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
NODE_OPTIONS can be used to inject arbitrary flags (--require, --inspect, etc.) into forked Node processes, which can cause crashes and unexpected behavior in the extension host and other forked processes. Co-authored-by: Megan Rogge <meganrogge@Megans-MacBook-Pro.local>
…314822) * chat: use ILabelService for remote agent host names in permission UI `AgentHostPermissionUiContribution` is registered for VS Code proper, but in VS Code we cannot depend directly on `IRemoteAgentHostService` since that service is only registered in the Agents window / sessions layer. Route the human-readable host name lookup through `ILabelService` instead. - `RemoteAgentHostService` now registers a per-host `ResourceLabelFormatter` for the `vscode-agent-host` scheme, with the entry name as the formatter's `workspaceSuffix`. The formatter is refreshed on entry add / name change and disposed on removal. - `AgentHostPermissionUiContribution` drops the `IRemoteAgentHostService` dependency and resolves the host name via `ILabelService.getHostLabel(AGENT_HOST_SCHEME, agentHostAuthority(address))`, falling back to the raw address when no formatter is registered (e.g. in regular VS Code workbench). - Updates the contribution and service tests accordingly. (Commit message generated by Copilot) * address review feedback
* sessions: retain attached editor maximize state Remember the maximized state of main editors that are reopened from the auxiliary-bar-attached flow so closing and reopening an embedded editor preserves its layout. Keep modal editor flows unchanged and document the behavior in the sessions layout spec. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: clear attached editor restore on aux hide Cancel the remembered attached-editor maximize restore when the auxiliary bar is hidden and add regression coverage for hiding and showing the bar before the next editor reopen. 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>
--------- Co-authored-by: Copilot <copilot@github.com>
* agent-host: restore selected model in picker Use session state as the source of truth for existing agent host sessions, while keeping resource-scheme-scoped storage as the view-state fallback for new untitled sessions. (Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agent-host: track status for model picker restore Recompute Agent Host model picker state when the active session status changes so storage fallback is only used while a session is untitled. (Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Fixes tool invocation permalinks in MCP by using chatStreamToolCallId when available, with a fallback to callId for backward compatibility - Ensures tool results in chat responses are correctly linked to their stream tool call context Fixes #314706 (Commit message generated by Copilot)
* Fix loc files encoding * Address review feedback: strip duplicate BOM and fix Hungarian disk-space key * Remove unused codePage / InnoSetup config from i18n pipeline * Strip leading BOM in TextModel so .isl parsing is BOM-tolerant
adding request.options.tools event to 3p
* Implement Pull Request state for Agent Host sessions
Adds an Open Pull Request button + live PR/CI state for Agent Host
sessions, mirroring what already works for Extension Host CLI sessions.
Server-side (platform/agentHost):
- Extend ISessionGitState with githubOwner/githubRepo
- agentHostGitService parses 'git remote -v' (preferring origin, falling
back to first GitHub remote) and writes {owner, repo} to _meta.git
alongside the existing branch/upstream/changes data
- Handles SCP-like (git@github.com:o/r), https://, and ssh:// remotes
Client-side (sessions/contrib):
- IGitHubService.findPullRequestNumberByHeadBranch(owner, repo, branch)
uses GET /repos/{o}/{r}/pulls?head={o}:{branch}&state=all to find the
most recently updated PR for a head branch; cached in-memory per key
- AgentHostSessionAdapter.gitHubInfo is now a derived chain:
_meta.git -> {owner, repo, branch} -> PR number lookup -> IGitHubInfo
with live PR icon refresh via createPullRequestModelReference +
computePullRequestIcon
- Thread IGitHubService through local + remote agent-host providers
Result: the existing OpenPullRequestAction (gated by
ActiveSessionContextKeys.HasPullRequest) now lights up automatically once
the session's branch has a PR on GitHub, with the live status icon.
Tests: extends agentHostGitService.test.ts with a parseGitHubRepoFromRemote
suite covering ssh, https, ssh://, origin-preferred, fallback-to-non-origin,
empty input, and non-GitHub remotes.
(Written by Copilot)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address PR review feedback
- githubService: don't cache transient failures or undefined PR lookups
so a later retry succeeds once a PR is created. Successful numeric
results are still cached indefinitely (PR number is monotonic).
- sessionState: clarify githubOwner/githubRepo doc comments to reflect
actual fallback behavior (origin-preferred, otherwise first GitHub
remote).
- Stub IGitHubService in localAgentHostSessionsProvider and
remoteAgentHostSessionsProvider tests.
(Written by Copilot)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Hide Sync PR button when there's nothing to sync
When the working tree is fully in sync with the open PR, the
'Sync Pull Request' primary button was still shown alongside
'Mark as Done', resulting in two competing primary buttons in the
changes view toolbar.
Match the EH CLI guard: only show 'Sync Pull Request' when there are
incoming, outgoing, or uncommitted changes. This is mutually exclusive
with 'Mark as Done' (which requires no such changes).
(Written by Copilot)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* sessions: match panel tabs to auxiliary bar Reuse the same title-tab treatment for the sessions panel that the Changes/Files tabs already use in the auxiliary bar. This removes the persistent active underline, switches labels to sentence case, tightens the pill spacing, and bumps the label weight to 500. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: correct panel tab casing docs Update the sessions layout spec to describe the existing panel and auxiliary bar tab labels as title case. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…e-land) (#314533) * agentHost/claude: post-Phase-4 cleanup - roadmap.md: mark Phase 4 as DONE, link merged PR #313780. - phase4-plan.md: record live-system smoke completion in §7.8; disabled-gate run skipped (covered by unit tests + env-var guard). - claudeAgent.test.ts: drop gratuitous 'as unknown as' cast in the CCAModel fixture (literal already matches CCAModelBilling exactly; plan §7.4 forbids unsafe casts in tests). * agentHost/claude: lock Phase 5 implementation plan Handoff plan for Phase 5 (replace 7 throwing stubs in claudeAgent.ts). Locked against post-PR-#313841 reality (provisional sessions, onDidMaterializeSession, 30s empty-session GC) and the IAgent contract on origin/main. Decisions captured: - Non-fork createSession is synchronous and in-memory; fork deferred to Phase 6 (throws TODO). - IClaudeAgentSdkService surface mirrors IAgent (no dir parameter on listSessions); SDK loader caches resolved module, retries on failure, logs once. - listSessions joins SDK enumeration with workbench session DB metadata via ISessionDataService; per-entry try/catch resilience. - shutdown() routes per-session teardown through the same SequencerByKey<string> used by disposeSession() so concurrent shutdown/disposeSession cannot double-dispose a wrapper in Phase 6. - 14 unit tests defined (12 lifecycle + 2 resolved-config), including log-once contract and shutdown/disposeSession race guard. * agentHost/claude: Phase 5 — IAgent provider skeleton Lands the ClaudeAgent IAgent provider behind the 'chat.agentHost.claudeAgent.enabled' setting (env gate VSCODE_AGENT_HOST_ENABLE_CLAUDE=1). Pins @anthropic-ai/claude-agent-sdk@0.2.112 in workspace + remote/. Implemented in this phase: * createSession - non-fork, in-memory wrapper only. Honors config.session for restore. The fork path and SDK session creation are deferred to Phase 6. * listSessions - SDK is source of truth; per-session DB read is a best-effort overlay (failure never excludes an entry). * disposeSession / shutdown - routed through a per-session SequencerByKey to serialize teardown. * getDescriptor, getProtectedResources, models, onDidSessionProgress, setClientCustomizations, setClientTools, onClientToolCallComplete, setCustomizationEnabled, authenticate, respondTo*Request - minimal Phase-5 wiring. Stubbed for Phase 6 (throw async 'TODO: Phase 6'): sendMessage, abortSession, changeModel, getSessionMessages, plus the createSession fork path. Tests: 29 unit tests in claudeAgent.test.ts cover the createSession restore-id path, listSessions overlay resilience, dispose serialization, and stub surfaces. Note: provisional / onDidMaterializeSession is intentionally omitted in Phase 5 (see plan section 3.3.1) - the workbench needs an immediate sessionAdded until the agent has real materialization work, which arrives in Phase 6 alongside SDK query() startup. * agentHost/claude: Phase 6 — sendMessage, single-turn, no tools Implements the Phase 6 plan: provisional sessions materialize on first sendMessage, route a single-turn prompt through the Anthropic Claude Agent SDK's WarmQuery, and stream SDKMessages back as protocol AgentSignals via a pure mapSDKMessageToAgentSignals reducer. Tools remain denied (canUseTool: 'deny'); fork moves to Phase 6.5; Plan Mode UI moves to Phase 7. Highlights: - ClaudeAgent.sendMessage routes through _sessionSequencer to collapse concurrent first sends into one materialize + N ordered sends. - _materializeProvisional has two abort gates (post-startup + post-customizationDirectory write) so disposeSession landing mid-materialize cannot leak a WarmQuery subprocess. - ClaudeAgentSession owns the prompt iterator + per-turn deferreds; mapSDKMessageToAgentSignals is a pure reducer with state owned by the session. - IClaudeAgentSdkService gains startup() alongside listSessions(). Tests: 43 unit + 2 proxy-backed integration. Council-review fixes (C1 dispose race, C2 missing integration test, S1 cwd-less ratification) included. * agentHost/claude: address PR review (listSessions resilience, dispose abort) Two Copilot-reviewer comments on #314216: 1. listSessions: wrap _sdkService.listSessions() in try/catch. AgentService.listSessions fans out across providers via Promise.all; an SDK dynamic-import failure would otherwise nuke every other provider's session list. Now logs and returns []. 2. dispose: abort _provisionalSessions AbortControllers before super.dispose(). Previously a racing first sendMessage parked inside _writeCustomizationDirectory could pass the materialize abort gates and call _sessions.set on a disposed DisposableMap, orphaning the WarmQuery. Aborting first triggers the existing post-customization-write abort gate, which asyncDisposes the WarmQuery. Tests: 2 new regressions (listSessions empty on SDK throw; agent.dispose() during racing materialize disposes the WarmQuery). 45/45 unit + 2/2 integration pass. * Drop stale @anthropic-ai/sandbox-runtime dep from merge resolution * Bump @anthropic-ai/claude-agent-sdk 0.2.112 → 0.2.128 The new SDK no longer vendors native binaries inside the main package. It now ships a ~200MB `claude` executable per platform via 8 optional platform-specific packages, mirroring the @github/copilot pattern: @anthropic-ai/claude-agent-sdk-{darwin,win32}-{x64,arm64} @anthropic-ai/claude-agent-sdk-linux-{x64,arm64}{,-musl} The SDK loader picks the right package at runtime via process.platform /process.arch (and tries -musl first on linux). To strip off-target packages from the build output: - build/lib/claudeAgentSdk.ts mirrors build/lib/copilot.ts - gulpfile.vscode.ts and gulpfile.reh.ts apply the filter alongside the existing copilot one - gulpfile.vscode.ts asar-unpacks @anthropic-ai/claude-agent-sdk-* so the executable stays on disk (asar would break exec permissions) - alpine-{arch} maps to linux-{arch}-musl (claude is statically linked against libc and must match the host) cglicenses.json gets 8 new entries mirroring the parent SDK's "© Anthropic PBC. All rights reserved." text. The new SDK Query interface adds a `readFile` method; FakeQuery and RoundTripQuery test doubles get matching stubs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * build: cross-copy @anthropic-ai/claude-agent-sdk darwin packages for universal app Mirror the existing @github/copilot pattern in create-universal-app.ts. Each darwin arch build only contains its own platform package (npm only installs the optionalDependency matching the host CPU), so the universal merger fails with files unique to one side. Cross-copy node_modules/@anthropic-ai/claude-agent-sdk-{darwin-x64,darwin-arm64}/ between the two builds, skip them from the equality comparison, and tag the per-arch `claude` executable as arch-specific so the merger keeps both. Also extend verify-macho's skip list to ignore the single-arch `claude` binaries inside the universal app. * agentHost/claude: address PR review - claudeAgent: rewrite `rgPath` from node_modules.asar → node_modules.asar.unpacked before putting it on the Claude subprocess PATH. Mirrors copilotAgent.ts and the workbench search engine helpers; without this, packaged builds advertise a path that doesn't exist on disk. - cglicenses.json: add "// Reason: …" justification comments to the parent @anthropic-ai/claude-agent-sdk entry and each of the 8 new platform sub-packages, matching the file's convention. * build: bump DMG volume size from 1g to 2g The universal macOS app now carries platform-specific binaries for both x64 and arm64 — @github/copilot-darwin-* (~128MB each) and the new @anthropic-ai/claude-agent-sdk-darwin-* (~207MB each) — so the source filesystem the DMG is built from has crossed 1GB. dmgbuild fails with `No space left on device` when ditto can't fit the app inside the volume. Output DMG is LZMA-compressed (format = 'ULMO') so this only changes the build-time staging size, not the shipped artifact size. * agentHost/claude: don't bundle claude-agent-sdk; load it from a user-specified path Move `@anthropic-ai/claude-agent-sdk` from `dependencies` to `devDependencies` so the ~200MB-per-arch platform binaries are no longer shipped with VS Code. The SDK becomes opt-in and externally-installed. User-facing surface: - Replace boolean setting `chat.agentHost.claudeAgent.enabled` with string setting `chat.agentHost.claudeAgent.path`. When the setting is non-empty, the Claude provider registers; when empty (the default), it does not. - The setting value is forwarded to the agent host via the `VSCODE_AGENT_HOST_CLAUDE_SDK_PATH` env var (replacing the previous `VSCODE_AGENT_HOST_ENABLE_CLAUDE` flag). - `agentHostServerMain` exposes a `--claude-sdk-path <path>` CLI flag in place of the previous `--enable-claude-agent` flag. Runtime loader: - `ClaudeAgentSdkService._loadSdk()` now reads the env var and dynamic-imports from there. If the path is a directory, the package's main entry is resolved from `package.json` (`exports['.']` / `main`) before the import — Node ESM does not support directory imports of `file://` URLs. Build/packaging cleanup (no longer needed once the SDK is gone from production deps): - Drop `build/lib/claudeAgentSdk.ts` and its callers in `gulpfile.{vscode,reh}.ts`. - Drop the `@anthropic-ai/claude-agent-sdk-*` glob from the asar-unpack list in `gulpfile.vscode.ts`. - Revert universal-app cross-copy + filesToSkip + x64ArchFiles entries in `build/darwin/create-universal-app.ts` and the corresponding skip patterns in `build/darwin/verify-macho.ts`. - Revert DMG volume size from 2g back to 1g in `build/darwin/dmg-settings.py.template` (was bumped earlier in this branch to fit the bundled SDK; no longer needed). - Remove the 9 `@anthropic-ai/claude-agent-sdk*` entries from `cglicenses.json` (no longer shipped, no manifest to license). Type imports of `@anthropic-ai/claude-agent-sdk` continue to work via the devDependency, so source code that does `import type` from the package still typechecks. * revert cglicenses change --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Agent host: prefer origin/<default> for worktree base Match the extension-host CLI behaviour of preferring the remote-tracking ref over a possibly-stale local branch when picking the worktree start point, and pass --no-track to git worktree add so the new agent branch does not pick up upstream tracking from the start point. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…14871) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )