* Show only cloud coding agent tasks in cloud sessions list (v2)
Two fixes to the Task API (v2) cloud sessions list, where local VS Code /
CLI / JetBrains sessions mirrored into Mission Control were leaking in and
settled tasks were stuck showing "In Progress".
- Filter the list to cloud coding agent tasks only. The owning surface is
identified by the agent integration slug on a task's `agent_collaborators`
(`copilot-developer` / `copilot-swe-agent` = cloud; `copilot-developer-cli`,
`vscode-chat`, `jetbrains-chat` = local clients). Adds the exported pure
helper `isCloudCodingAgentTask` and applies it in `fetchSessionList`.
`agent_collaborators` is returned to first-party CAPI tokens but not yet
modeled in `@vscode/copilot-api`, so a minimal local type is used.
- Carry the raw `AgentTaskState` across the backend seam and map it directly
to `ChatSessionStatus` in the provider, so `idle` renders as Completed and
`waiting_for_user` as NeedsInput instead of collapsing to InProgress.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address review: guard malformed slugs and add status fallback
- isCloudCodingAgentTask: use a `typeof c.slug === 'string'` guard so null /
non-string slugs in the untyped server payload can't reach `Set.has`.
- taskStateToChatSessionStatus: add a `default` branch returning InProgress so
an unknown/forward-compat task state can't yield an invalid `undefined`
status. Added tests for both.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: drop diagnostics with missing range at the language diagnostics boundary
Other extensions can publish vscode.Diagnostic entries whose `range` is
undefined (violating the non-nullable `range: Range` type via an `any` cast).
These reach copilot verbatim through `vscode.languages.getDiagnostics()` and
crash the many consumers that dereference `diagnostic.range` - notably the
`LintErrors.getData` telemetry path that scans every extension's diagnostics
via `getAllDiagnostics()`. Sanitize at the boundary service so every consumer
is protected once, and log dropped entries so the producer stays diagnosable.
Fixesmicrosoft/vscode#323148
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: Copilot - Test lint — use strict equality for range null/undefined check
The eqeqeq ESLint rule (configured as 'warn', enforced with --max-warnings=0)
flagged `range != null` in _dropMalformedDiagnostics. Replace the loose
equality with an explicit strict check that preserves the original semantics
of dropping diagnostics whose range is either null or undefined.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: vs-code-engineering[bot] <122617954+vs-code-engineering[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
In an untrusted (Restricted Mode) workspace the agent-host harnesses
(claude-code, copilotcli) register their session-scoped models without a
workspace-trust gate, so they stay live. getModelPickerUnavailableReason
treated any live, picker-offered model as usable and returned "available",
which masked the Restricted state behind a misleading "Auto" for the Agent
Host (Copilot CLI / Claude) model picker -- while the Local harness correctly
showed "Pick Model". General-purpose models are withheld while untrusted,
which is why Local behaved correctly.
Make Restricted Mode take precedence: an untrusted workspace now reports
Restricted before the live-model check, so every picker routed through this
function (chat editor input + sessions config bar) shows the Restricted state.
A live BYOK model still wins over setup-required in a trusted workspace
(signed in or out), since that check still runs when trusted.
Relates to #322794, #322564
Addresses https://github.com/microsoft/vscode/issues/322564#issuecomment-4811816607
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Agent host: only suffix worktree branch names on collision, strip prefix from folder
The Copilot agent host generated worktree branch names of the form
`agents/<hint>-<sessionId8>`, which always appended a session-id suffix and
produced verbose worktree directory names like `agents-<hint>-<sessionId8>`.
- Only append a short suffix (the first 8 chars of the session id) when the
candidate branch name collides with an existing branch, via a new optional
`branchExists` predicate on the generator request (wired to
`IAgentHostGitService.branchExists`). Unique names stay clean (`agents/<hint>`).
- Keep the `agents/` prefix on the branch name, but strip it from the worktree
directory name so folders are just `<hint>` instead of `agents-<hint>`.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Agent host: fix worktree announcement test and address review feedback
- Update the `worktree announcement` test to expect the un-suffixed branch
name `agents/add-feature` now that the session-id suffix is only appended
on a branch collision (the test's fake git service reports no collision).
- Clarify wording in the branch name generator docs/comments and test name:
the collision suffix is derived from the session id, not random.
- Treat a failed `branchExists` check as a collision so we fall back to a
suffixed branch name rather than risk `addWorktree` failing on an existing
branch.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Agent Host changes for agents/adhoc-request-sender-mode-extension-55e2bb6f
* Remove unconfigured react-hooks/exhaustive-deps eslint directive
The eslint-disable directive referenced a rule that isn't registered in
this repo's ESLint config, which caused ESLint to error with
"Definition for rule 'react-hooks/exhaustive-deps' was not found" and
failed the Compile & Hygiene and Copilot - Test CI checks.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Coalesce adhoc tag-decoration rescans with requestAnimationFrame
Rescanning the whole editor text on every content change is wasteful for
bursty updates (e.g. a streamed response). Debounce the decoration update
to at most once per animation frame and cancel any pending frame during
cleanup so the callback can't run after the editor is disposed. The
initial scan stays synchronous so tags are highlighted immediately on mount.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address PR feedback: dispose token source; validate adhoc request JSON
- adhocRequestSender: always dispose the per-send CancellationTokenSource
in the finally block (separate from the current-send guard) so its
cancellation listeners don't leak across repeated Send/Stop cycles.
- simulationMain: validate and normalize the adhoc request JSON before use
so malformed input (missing/null/wrong-typed model/user/system) yields a
focused error message instead of a thrown stack trace.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The pill label shows the session's default changeset, but activating it opened
the shared per-session diff editor, which follows the Changes view's currently
selected changeset. After a manual selection the label and the opened diff
could disagree.
Reset the Changes view selection to the default before opening so the pill, the
diff editor, and the Changes view panel all reflect the default changeset.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Use Accept/Remove button bar for created agent feedback comments
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix eslint querySelector usage and address review feedback
- Track action bar elements in a map instead of querySelector (eslint no-restricted-syntax)
- Stop click propagation from the button bar
- Restore focus to the widget after dismissing the button bar
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Make onboarding.developerMode a per-scenario map
Change the onboarding.developerMode setting from a boolean to an object mapping scenario/tour id to a boolean, so developer mode can be toggled per scenario. The default lists every registered scenario id set to false and is kept in sync as scenarios register/unregister, making the ids discoverable in the settings editor.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Clarify developer-mode replay behavior in docs
In developer mode the once-per-window-session gate uses in-memory state, which the Reset Onboarding Shown State command does not clear. Update the setting doc comment and description to say reload the window to replay.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Render the New Chat action as a labeled "New Chat" button in the session
header (via SessionHeaderMetaActionViewItem, registered through the
IActionViewItemService so the header toolbar stays generic) and keep it
always available. It is hidden only when the chat tab strip is shown
(more than one open chat), where the tab strip offers its own "+" button
instead - gated by the new SessionHasMultipleOpenChats context key.
The Conversations menu keeps its existing behaviour (shown in the header
once the session has more than one committed chat) and Mark as Done is
grouped with Pin/Close. Header toolbar items are now spaced with a small
gap so New Chat and Conversations no longer render flush.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* sessions: pre-select archived session's folder on return to new-session view
When marking a session as done (archiving), the new-session view was shown
with the last user-picked folder selected (from storage) instead of the
folder of the session just archived.
Pass the archived session's workspace folder URI to openNewSession so a
draft for that folder is created and the workspace picker syncs to it via
_syncWorkspacePickerFromActiveSession. Falls back to the no-folder path
when the session has no workspace.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* sessions: also pass providerId and sessionType when returning to new-session view after archive
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* sessions: keep new-session side pane closed when toggled shut
Closing the whole Side Pane (editor + auxiliary bar) ran under
`_togglingSidePane`, so the per-session capture listener skipped it and
the shared new-session view state stayed `undefined`. The restore logic
(D3b) treated `undefined` as "default open" and re-opened the aux bar on
the next sync.
Add an `_onSidePaneToggled` hook called at the end of `toggleSidePane`.
The desktop controller records the resulting aux-bar visibility for
uncreated sessions, so a side-pane close on a new session is remembered
just like hiding the aux bar alone. It now stays closed when the same new
session re-syncs (gains a workspace, un-maximizes, collapses back from a
multi-session view) and when the next new session is created. Created
sessions keep the existing D9 behaviour (the hook is a no-op).
Adds D9b unit tests and updates the layout controller specs.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* sessions: condense side-pane toggle hook comments
Address review feedback: shorten the inline comment in toggleSidePane to a
single line and trim the _onSidePaneToggled JSDoc to 1-2 sentences, with the
detailed rationale kept in desktopSessionLayoutController.md.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* sessions: header diff-stats pill shows the session's default changeset
The session header diff-stats pill (and the `hasChanges` context key that
gates it) located the branch diff by the well-known `branchChanges` id and
otherwise fell back to the session's top-level changes. For agent-host
sessions the branch changeset uses a different id (`branch`), so the lookup
missed and the pill rendered the full Session Changes totals instead of the
Branch Changes shown by the Changes view.
Read the provider-marked default changeset (`isDefault`) instead — the same
changeset the Changes view selects by default (branch-vs-base for a git
workspace, otherwise the session's working changes) — so the header is
provider-agnostic and stays independent of the changeset currently selected
in the Changes view.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* sessions: address CCR feedback — tighten changeset comments
Shorten the diff-stats pill JSDoc and the `hasChanges` inline comment to
describe the logic (default changeset + fallback) without baking in
provider-specific rationale.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* sessions: bypass renderer HTTP cache for GitHub PR polling
PR status icons are computed from a live PR model that is polled with a conditional If-None-Match request so GitHub can answer a cheap 304. The sessions window runs in a renderer, so the request goes through fetch with the default cache mode. GitHub serves PR responses with a Cache-Control max-age, so the browser HTTP cache returned a stale 200 body during the freshness window and our conditional request never reached the server, making the PR icon miss state changes such as a merge.
Set disableCache: true on all GitHub API requests so polling always reaches the server while still sending If-None-Match, keeping polling both reliable and rate-limit friendly.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* sessions: address PR feedback on GitHub API client test
Make the fake request service disposable and register suite disposables with the leak-tracking store before creation; collapse the inline cache comment to one line.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* sessions: fix FakeAuthenticationService.getSessions return type in test
Return proper AuthenticationSession objects so the fake's getSessions matches IAuthenticationService, fixing the Compile & Hygiene CI failure.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The Fix CI button is already shown in many other locations, so the redundant action button in the checks collapsible widget header is removed. Also removes the now-unused activeSessionResourceObs from ChecksViewModel.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* sessions: add quick-navigate support to the sessions picker
Pressing the sessions picker keybinding (Ctrl+R / Ctrl+R on Mac) while
already holding the modifier now cycles through the session list instead
of reopening the picker, mirroring the Ctrl+Tab editor-switcher behaviour:
- hold modifier, press trigger -> picker opens, active session focused
- keep holding, press trigger again -> next session focused (Shift goes back)
- release modifier -> focused session is opened
Implementation follows the same three-part recipe as the editor switcher:
1. picker.quickNavigate is set from the command's own keybindings so the
platform's built-in KEY_UP handler accepts the focused item on modifier
release.
2. A new SessionsPickerVisibleContext key is set/reset around the picker
lifecycle to scope the navigate keybindings.
3. Two KeybindingsRegistry rules (navigateNext / navigatePrevious) bound to
the same chord at +50 weight call getQuickNavigateHandler, which advances
focus via quickInputService.navigate().
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* sessions: fix SessionsPickerVisibleContext description
Remove the inaccurate "(recently opened sessions)" qualifier — the picker
shows new-session, recently-opened, and other-sessions groups.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The agent feedback input banner's `Address Comments` button now accepts the surfaced reviewable comments and submits them via the feedback service, attaching the feedback items to the `/act-on-feedback` request just like the agent feedback editor overlay's Submit button. Previously it sent a bare command without attaching any feedback.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Open created/added-only file edits in a normal editor, not a diff
When a chat file edit pill references a change that is a pure addition into an empty (newly created) original, clicking it now opens the resulting file in a normal editor instead of a diff editor. This already worked for the chat editing pipeline (CollapsedCodeBlock) and for created files in the agent host pipeline; this applies the same behavior to edited files with only additions in the agent host pill (ChatExternalEditContentPart) and shares the empty-origin check via a new isResourceContentEmpty helper.
Fixes#322682
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Use type-only import for ITextModelService in chatEditPillElement
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>