* agent host: fix custom agent selection and per-chat agent/model changes
Two fixes for Copilot CLI agent-host sessions:
- The selected custom agent (e.g. a plugin/extension agent like "Inbox")
failed with "Custom agent '<name>' not found". The SDK validates the
session-start `agent:` option against `customAgents` by name and does not
consult `pluginDirectories`, but file-dir plugin agents were excluded from
`customAgents`. The new `toSdkSessionCustomAgents` helper force-includes the
resolved selected agent while other file-dir agents still load via
`pluginDirectories`.
- An additional (peer) chat in a session did not respect agent/model changes.
`SessionAgentChanged`/`SessionModelChanged` were dispatched to the session
URI (the default chat) instead of the per-chat turn channel, and the
`chatChannel` was dropped before reaching `changeAgent`/`changeModel`. These
now route to the peer chat's backend conversation in `_chatSessions`.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* sessions: address Copilot code review feedback
- Trim SDK custom-agent names to match parseAgentFile so a whitespace-padded
frontmatter name still matches the resolved selected agent (CCR finding 3).
- Dedup peer-chat agent/model side-channel dispatch against the last value
sent for that chat (tracked on AgentHostChatSession) instead of the session
summary, which only exists for the default chat (CCR findings 1 & 2).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* ci: split Electron test jobs into unit/integration and smoke
The Linux, Windows and macOS Electron PR test jobs are the slowest in CI,
dominated by the smoke test run. Split each into two parallel jobs - one
running unit + integration tests, the other running smoke tests - to cut
wall-clock time.
Done via two new parameters on the reusable workflows
(unit_and_integration_tests and smoke_tests, both defaulting to true) so
Browser and Remote jobs are unchanged. Artifact names get a -smoke suffix
on the smoke-only job to avoid upload collisions.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* ci: gate build and diagnostics to correct Electron test phase
Follow-up to the Electron job split. Ensure each half only does the work
it needs:
- Gate "Build integration tests" on unit_and_integration_tests so the
smoke-only job skips it.
- Scope the before/after diagnostics steps to their phase (combined with
always()) so they don't run in the wrong job.
- Move the Copilot extension build into the smoke phase (gated on
smoke_tests) instead of compiling it unconditionally; align Linux,
Windows and macOS on the same ordering.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* ci: drop space and parens from Electron-Smoke job name
The Windows 1ES runner builds its JobId label from job_name, producing
"windows-test-Electron (Smoke)-...". The space and parentheses prevented
the runner from picking up the job. Rename the smoke job to Electron-Smoke
on all three platforms so the JobId is a plain slug.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fixes
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
refactor: update restore-node-modules action to support lookup-only functionality
- Replaced 'extract' input with 'lookup-only' to allow cache entry checks without downloading or extracting.
- Updated action logic to conditionally extract node_modules based on the new 'lookup-only' input.
- Adjusted workflow files to utilize 'lookup-only' for cache-warming jobs on Linux, macOS, and Windows.
* CI: speed up node_modules cache with zstd + shared scripts
Switch the Linux/macOS node_modules cache from single-threaded gzip
(tar -czf) to multi-threaded zstd. The "Create node_modules archive"
step was spending ~5min of single-core gzip on a multi-GB tree on every
cache miss; zstd -T0 uses all cores and decompresses much faster, so
cache-hit jobs benefit too. Windows stays on 7-Zip (already threaded).
Extract the archive/extract commands into shared per-platform scripts
under .github/workflows/node_modules_cache/ (cache.sh / cache.ps1, each
dispatching on an archive|extract argument) so the format and flags live
in one place instead of being duplicated across ~8 workflows. Bump
build/.cachesalt to invalidate existing gzip caches.
Also remove the obsolete extensions/copilot CI workflows
(copilot-setup-steps.yml, ensure-node-modules-cache.yml, pr.yml) and the
unused build/listBuildCacheFiles.js, and drop their now-stale entries
(plus lit-html and signals-core) from .eslint-allowed-javascript-files.
* ci: seed copilot node_modules cache on main and rename cache keys
Add copilot-linux and copilot-windows jobs to pr-node-modules.yml so the
copilot node_modules cache is populated on main. Rename the copilot cache
keys to copilot-node_modules-linux / copilot-node_modules-windows in pr.yml.
* ci: extract node_modules cache into composite actions
Factor the repeated node_modules cache plumbing into two local composite
actions, restore-node-modules and save-node-modules, and migrate all
workflows that used the cache.sh/cache.ps1 archive flow (pr, pr-node-modules,
pr-{linux,darwin,win32}-test, copilot-setup-steps, component-fixtures,
css-order-scan).
- restore-node-modules computes the key, restores the cache, optionally
extracts on a hit, and exports the resolved key via $GITHUB_ENV.
- save-node-modules archives node_modules and saves it to the cache, reusing
the key exported by restore so callers don't repeat the prefix.
- Bespoke install steps stay in the workflows, so per-job env/secrets never
cross the action boundary.
- Only seed the cache on branch pushes (component-fixtures skips PRs, whose
caches aren't shared).
* save the node_modules cache for now to test it
* ci: fix node_modules cache save dropping the archive
cache.sh wrote its archive as cache.tzst, but actions/cache reserves that
name for its own tarball and passes --exclude cache.tzst, so our archive was
excluded and an empty (~200 B) cache was saved on Linux/macOS. Rename the
archive to node-modules.tzst and bump build/.cachesalt to invalidate the
broken cache entries.
* empty commit
* Remove again saving to the node modules cache from PR steps
* policy: add dev mock server for copilot_internal policy endpoints
Adds scripts/mock-policy-server, a standalone dev tool (npm run
mock-policy-server) that mocks the Copilot policy endpoints
DefaultAccountService calls: entitlements (/copilot_internal/user), token
(/copilot_internal/v2/token), MCP registry (/copilot/mcp_registry) and
managed settings (/copilot_internal/managed_settings).
A small web GUI lets devs pick presets or edit each JSON response, and
Wire/Unwire buttons point product.overrides.json at the local server
(preserving the rest of defaultChatAgent, since bootstrap-meta merges
overrides shallowly). The managed-settings JSON schema is loaded from
--schema/MANAGED_SETTINGS_SCHEMA, defaulting to
./copilot-agent-runtime/schema/managed-settings-schema.json relative to
the app cwd; web URLs and file URIs are accepted, and the GUI warns about
keys not declared in the schema.
The three browser/shared .js files are added to
.eslint-allowed-javascript-files since the GUI loads them directly.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* policy: address mock-policy-server review feedback
- Scope permissive CORS to the mocked GET endpoints only; keep /api/*
same-origin so a website can't drive /api/wire and rewrite
product.overrides.json (CSRF).
- Coerce an empty editor body to {} instead of "" so mocked responses
stay JSON objects.
- Build the endpoint meta line with textContent/DOM nodes instead of
innerHTML.
- Drop the misused tablist/tab ARIA roles; the nav now has an aria-label
and the active item uses aria-current.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* policy: document mock policy server in add-policy skill
Add local-testing.md to the add-policy skill with basic steps for using
the mock policy server (scripts/mock-policy-server) to exercise the
account/managed-settings flow locally, and link it from SKILL.md and
github-managed-settings.md.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* policy: polish mock server GUI — schema validation, wiring backup, localStorage persistence
* policy: auto-save, rename wiring to product.overrides.json, copy path button
* mock-policy-server: convert server.js to TypeScript; add raw response diagnostics
- Convert server.js → server.ts (runs via --experimental-strip-types)
- Add endpoints.d.ts type declarations for the UMD endpoints module
- Add managedSettingsRawResponse to IDefaultAccountProvider/IDefaultAccountService
- Show raw response in Developer: Sync Account Policy output
- Remove server.js from eslint allowed-javascript-files
* mock-policy-server: convert all JS to TypeScript
- endpoints.js → endpoints.ts with proper interfaces (replaces .d.ts)
- public/app.js → public/app.ts with full type annotations
- Server uses module.stripTypeScriptTypes() to serve .ts as plain JS
to the browser — no build step needed
- Remove all mock-policy-server entries from .eslint-allowed-javascript-files
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* policy: server-delivered managed settings win over native MDM
Managed settings can arrive from two channels: the server `managed_settings`
endpoint and native MDM (Windows registry / macOS plist). Previously the two
were merged with native MDM winning. This changes the precedence so the two
layers are never merged: at any point in time there is a single authoritative
source. The server is harder to bypass than local MDM/file policies, so when
the server delivers managed settings it wins outright and native MDM is ignored
entirely. Native MDM applies only when the server provides no managed settings.
Client-side merging still happens within the winning layer (e.g. enabledPlugins,
extraKnownMarketplaces).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* policy: move managed-settings precedence rationale into add-policy skill
Trim the verbose inline comment in AccountPolicyService.getPolicyData() down to
a one-line pointer; the full precedence rationale lives in the managed-settings
section of the add-policy skill doc.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* policy: drop code snippet from managed-settings precedence doc
Keep the precedence explanation as prose; the code lives in
AccountPolicyService.getPolicyData().
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* policy: add skill learning — prefer behavior/contract prose over copy-pasted code
Skills should document behavior and business-logic expectations and reserve
code blocks for the author-facing API contract, rather than reproducing
internal implementation that rots when the source changes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Implement multi-chat session support for Copilot CLI in Local Agent Host Provider
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address CCR feedback: session-rename telemetry, createChat race, observable read
- Add dedicated onDidRenameSession event + agents/sessionRenamed telemetry
so session-title renames are no longer misclassified as chat renames
- Re-check chat existence inside the per-session sequencer in createChat to
avoid a race overwriting/disposing an already-registered conversation
- Cache mainChat.title read in chatCompositeBar autorun
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* agentHost: dispatch default-chat turn lifecycle on session URI
After merging origin/main's default-chat compat layer, turn-lifecycle
actions (turnStarted, truncated, turnCancelled) must target the session
URI for the default chat (and the peer chat URI for peer chats), so the
server routes them to the default chat and subagent session URIs derive
correctly. Conversation side-channel actions and tool-call observation
keep using the resolved chat URI.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Document GitHub Copilot managed settings in add-policy skill
Add a github-managed-settings.md sub-file covering the new enterprise
managed-settings modality (native MDM / file / GitHub server -> the
canonical IPolicyData.managedSettings bag) and the policyReference
mechanism (one policy governing many settings). Update SKILL.md to link
the sub-file and refresh the policy-sources and key-files tables.
Grounded in PRs #318623, #320991, #321218, #321515.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Tighten managed-settings skill after council fact-check
Cross-checked every claim against the source and the four PRs:
- Correct the channel count: VS Code feeds the bag from native MDM +
server endpoint only; managed-settings.json is external-schema-only and
not read by VS Code.
- Fix "JSON.parse" -> PolicyConfiguration.parse() (lenient JSONC visitor).
- Quote ManagedSettingValue verbatim (= PolicyValue).
- Clarify native MDM is a separate input merged in getPolicyData, not on
policyData; document MDM-wins merge order precisely.
- Note schema is nested vs the flattened bag key; add the
extraKnownMarketplaces github/git-only divergence alongside the strict
boolean one.
- Soften the catalog claim: referencedSettings only captures references
loaded at export time (sessions Claude ref absent from policyData.jsonc).
- Fix example file path (chat.shared.contribution.ts) and restore the
chat_preview_features_enabled OR in the ChatToolsAutoApprove sample.
- Make the main.ts wiring snippet match the real two-step structure.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address PR review: annotate example minimumVersion values
Mark the concrete minimumVersion values in example blocks as historical
values transcribed from existing policies, with an inline note that new
policies derive minimumVersion from package.json major.minor (Step 1).
The file-based-channel and JSON.parse review comments were already
resolved in the prior council-fix commit.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Clarify policy multiplexing in add-policy skill
After another pass through the policy wiring, clarify that
MultiplexPolicyService is used in two places: main-process OS/file policy
reader multiplexing, and renderer/session multiplexing of the main policy
channel with AccountPolicyService.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Promote policyReference guidance to main add-policy skill
policyReference is a general policy mechanism, not specific to Copilot
managed settings. Make the main SKILL.md section self-contained with the
owner/reference model, validation rules, export behavior, IPC-safe
serialization, and diagnostics notes. Keep the managed-settings sub-file
as a cross-reference only for managed-settings-specific examples.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chat: delegate agent-host sessions
- Pass transcript handoff as an attachment so the prompt stays user-authored.
- Route agent-host delegation through the correct session-opening path in VS Code and Agents Window.
- Preserve attachment round-tripping and existing Agents Window behavior while matching the updated SDK behavior.
Fixes#319819
(Commit message generated by Copilot)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chat: preserve paste attachment rendering
- Keeps normal pasted chat context as opaque simple attachments so existing paste chips render as before.
- Uses delegation transcript metadata, not display kind, to restore transcript handoff attachments.
- Updates attachment restore coverage to distinguish tagged transcripts from display-kind-only paste attachments.
(Commit message generated by Copilot)
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>
* chat: remove generic attachment tooltip
- Avoids changing generic restored attachment UI while preserving metadata-based delegation transcript restore.
- Keeps normal simple attachment rendering behavior narrowly scoped to the existing generic path.
(Commit message generated by Copilot)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chat: remove delegation diagnostic logging
- Removes temporary attachment and delegation trace logging added while diagnosing transcript handoff.
- Restores the Copilot attachment log to its previous low-detail trace shape.
- Reverts the unintended API proposal type change so proposal versions remain supported.
(Commit message generated by Copilot)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chat: fix agent host paste attachment test
- Completes the paste attachment request test with the chat turn completion event used by the state-driven test helper.
- Keeps the assertion that normal paste variables stay simple attachments without paste display kind.
(Commit message generated by Copilot)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chat: skip unused repo lookup for agents delegation
- Avoids computing chat initial session options for the Agents Window agent-host delegation path where they are not consumed.
- Keeps repository options for paths that pass them through workbench chat session creation.
(Commit message generated by Copilot)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Revert "chat: skip unused repo lookup for agents delegation"
This reverts commit b67d77c920.
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
We've had this enabled for watch for many months. Let's finish the move by switching this over now too
Also gives a better name to the typecheck script
* ci: restore chat pipeline to windows-latest
* chore: remove node-gyp override
* chore: restore node-gyp override with comment
* refactor: rm dependency on key:sqlite
The module locks the node-gyp dependency to 8.x due to
its transitive sqlite3 native module dependency this in turn
blocks using newer windows CI, refs https://github.com/microsoft/vscode/issues/321267
The module can be replaced with built-in sqlite support
from Node.js without losing the on-disk cache format has
already been committed.
* chore: restore minimist
* chore: set sqlite busy timeout
* fix: decode json-buffer values for keyv cache compat
* sessions: inline rename for chats in the chat composite bar
Support renaming a chat directly inside its tab in the chat composite
bar, mirroring the inline rename of the session title. Double-click a
tab (or use the context menu "Rename") to reveal a themed InputBox
pre-filled with the chat title; Enter commits via renameChat, Escape or
blur cancels.
The rename input lives in a stable, empty per-tab container that is
toggled via the tab's `editing` CSS class; the InputBox is created lazily
only while editing and disposed when done, so no DOM is inserted/removed
on demand and unused tabs carry no widget overhead.
Also adds a component fixture (chatCompositeBar.fixture.ts) covering the
two-tab, mixed-status, long-title and renaming states for screenshot
testing.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* sessions: switch tabs via click, keep rename blur a pure cancel
Address PR review: the tab click handler bailed out while editing and the
input blur handler switched tabs via relatedTarget. Because blur clears
the editing state before the trailing click fires, this could switch
twice (extra openChat/flicker) and was order-sensitive.
Now blur only cancels the rename, and the tab click handler cancels any
in-progress edit before switching, so tab switching follows the normal
click path.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Document two antipatterns fixed in #320913 so AI agents avoid them and
Copilot Code Reviews flag them:
- `.monaco-editor-background` must be opaque (never transparent), otherwise
the reverse-rounded selection corners break and performance suffers.
- Editor highlights should use regular decorations with inlineClassName/className;
registerDecorationType/setDecorationsByType is reserved for the ext host API.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The "chat-lib tests (windows-latest)" job started failing at the
"Extract chat-lib" step (npm ci in extensions/copilot). npm ci builds
the native sqlite3@5.1.7 module — a transitive dependency of the
@keyv/sqlite devDependency — via `prebuild-install -r napi || node-gyp
rebuild`. prebuild-install finds no matching prebuilt, so it falls back
to node-gyp, which fails on the runner because the GitHub-hosted
windows-latest label now resolves to the Windows Server 2025 + Visual
Studio 2026 image, whose VS 18 toolchain the bundled node-gyp cannot
detect ("unknown version undefined ... could not find a version of
Visual Studio 2017 or newer").
This was the only npm ci job exposed to the new image: every other
Windows npm ci job runs on self-hosted pools pinned to windows-2022
(still VS 2022), and all other copilot npm ci jobs run on Linux/macOS.
Pin this matrix entry to windows-2022 to match, as recommended by the
runner-images migration notice (actions/runner-images#14017).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Commit c385fd3 introduced IAgentSessionsService.model.observeSession(...)
calls into the provider-agnostic sessions workbench (sessionsList renderer
and the visible-sessions grid) for lazy loading. IAgentSessionsService is a
Copilot-provider internal and must only be consumed by the Copilot chat
sessions provider.
Revert those observeSession triggers and the IAgentSessionsService
dependency from sessionsList.ts and visibleSessions.ts, and update the
affected tests to assert on provider-agnostic signals (open-promise
resolution / visibleSessions) instead of observation. Remove the now
vestigial IAgentSessionsService stub from the agent feedback test.
To prevent recurrence, add an ESLint no-restricted-imports ban on
**/agentSessions/agentSessionsService scoped to src/vs/sessions/** (the
Copilot provider folder is exempted), and document the rule in SESSIONS.md
and the sessions skill.
Follow-up for re-implementing lazy loading correctly: #320480
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Lots of logging for chat smoke tests
* PR test workflows: build extensions/copilot before smoke tests
* PR test workflows: drop duplicate copilot compile from linux/win32 (was already built before integration tests)
* smoke tests: remove musl Claude binary on Linux glibc runner
The musl variant is probed first by @anthropic-ai/claude-agent-sdk and
fails to exec on glibc (ENOENT from missing ELF interpreter), which
caused the Test Claude session tests to time out.
* sessions: split session model from view service
Separate the session model (ISessionsManagementService) from the view
(ISessionsViewService) so the model owns canonical session state and the
view owns visible-slot arrangement, focus and per-session view
persistence. Introduces the new `browser/sessionsViewService.ts` core
service and `browser/parts/sessionsParts.ts`, makes the part a passive
renderer, and adds support for opening a session without focusing it
(reactive preserve-focus intent published atomically with the active
session).
Also encapsulates the in-progress new-session draft in the model as a
reactive `newSession` observable with a conditional `discardNewSession`,
merges `openNewSessionView` into `openNewSession`, and routes new-session
creation through the view so the draft is activated (fixing the session
type picker rendering empty after reload).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* revert open from active session
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The session type picker only persisted on manual dropdown selection, so an
auto-selected or defaulted type was never written to storage and reverted to
the first provider by order (Copilot Chat) on reload. It now persists the
active session's {providerId, sessionTypeId} on every change, like any picker.
NewChatWidget no longer pre-validates the stored pick against the folder's
currently-available types in onDidSelectWorkspace (which discarded a valid
preference whose provider had not yet registered). Instead it creates the draft
immediately with the best available provider and upgrades it in place once the
preferred provider registers (driven by onDidChangeSessionTypes), cancelling on
re-pick or send. No timeout or LifecyclePhase give-up, since agent hosts can
connect arbitrarily late.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Restore the invariant that revealing the editor part also reveals the
auxiliary bar (e.g. opening a file from chat shows the secondary side
bar), but suppress that enforcement while restoring a session's editor
working set on session switch. The working-set reveal is programmatic,
so the session's saved auxiliary bar visibility now wins and a side bar
the user hid for a session stays hidden when returning to it.
Adds the LAYOUT_CONTROLLER.md spec documenting per-session layout state
and links it from LAYOUT.md, README.md, and the sessions skill.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the per-provider model picker actions with a single sessions-core
ModelPicker that wraps the shared workbench ModelPickerActionItem. The core
picker reads the available models from the active session's provider via the
new ISessionsProvider.getModels API, remembers the last used model per provider
per session type, and applies the selection through ISessionsProvider.setModel.
Providers stay authoritative for their own behavior:
- getModels resolves model metadata per provider (local/CLI/agent-host filter
registered language models; cloud synthesizes metadata from its option group).
- getModelPickerOptions lets each provider decide grouping, featured models and
whether the Manage Models action is shown, instead of core branching on
session type.
- onDidChangeModels lets the core picker refresh when models change.
Decouple the core picker from agent-host provider identity: the agent-host
mobile combined config picker now publishes the neutral
ActiveSessionUsesCombinedConfigPickerContext key, which the core picker uses to
gate itself out on phone layouts.
Add architecture guidelines: do not mirror runtime state into context keys,
delegate provider-specific decisions to the provider, and avoid large
mid-method comments.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
After adopting the sessions grid we lost the previous "restore on reload" behaviour. Restore the full visible grid (order, sticky/pinned state and the active session, including the empty new-session slot) from persisted workspace state instead of only the last active session.
- Snapshot the live visibility model on save and rebuild it atomically via VisibleSessions.restoreGrid so multiple restored sessions appear in one shot without flicker; late-arriving sessions are inserted into their persisted position incrementally.
- Suppress the empty new-session view while restore runs (view-owned restoring flag + grid hide) so the composer does not flash before sessions are laid out.
- Show per-leaf load progress on each chat view's own ProgressBar (mirroring editor-group ScopedProgressIndicator) while its chat model loads.
- Move keyboard focus into the active session by observing ISessionsManagementService.activeSession from the part, guarded so it never steals focus from another surface (e.g. the sessions list).
- Use a dedicated restore cancellation token that is actually cancelled when the user opens a session, and bound provider waits with a timeout so a deleted session cannot keep restore (and its listeners) pending forever.
- Add a coding guideline forbidding lazy invokeFunction/accessor.get service resolution.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Agents: session header command center and toolbar refactor
Restructure the Agents window titlebar and session view header:
- Add a VS Code editor style command center to the titlebar showing the
session kind icon, session title and workspace name. The session title
truncates while the workspace name stays fully visible.
- Split the monolithic ChatCompositeBar into a dedicated SessionHeader
(session identity, title, meta row and toolbars) and a tabs-only
ChatCompositeBar (chat tab strip).
- Move the Open in VS Code and Run actions next to the session header,
introducing menu ids as needed; keep terminal/run actions in place.
- Align the session header with the sessions list (status icon column +
stacked title/meta) and show a folder/worktree/cloud icon before the
workspace name.
- Add an architecture rule discouraging direct DOM traversal helpers
(closest, etc.).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Agents: update RunScriptContribution test for new menu location
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Agents: address PR review feedback
- sessionsTitleBarWidget: drop status/changes from the re-render autorun
(the widget only displays title + workspace, so tracking the extra
observables caused unnecessary DOM rebuilds).
- sessionHeader: guard the drag-start handler so drags don't initiate
from inside the title-row toolbar or the meta-row inline toolbar,
preventing button clicks from being swallowed by a session drag.
- chatCompositeBar: mark the tabs container as role="tablist" with an
aria-label so screen readers announce it as a set of tabs.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>