* Revert "fix: builtin resolution of electron modules via asar hook (#324861)"
This reverts commit 5928613aa1.
* Revert "fix: restrict asar esm hook resolution to app resources (#324851)"
This reverts commit 89bc3825bd.
* Revert "feat: restore asar for node_modules (#324084)"
This reverts commit c9dda3b36a.
* feat: restore node_modules bundled into asar
* fix: store node_modules at top level inside asar archive
* Revert "fix: store node_modules at top level inside asar archive"
This reverts commit 4747aa5e375cc1fe49b8eb510dd1acec1fd6a581.
* fix: pack node_modules into asar
* fix: read copilot/ripgrep natives from node_modules.asar.unpacked
* fix: load node-context modules and native binaries from ASAR
- bootstrap-esm: resolve bare specifiers via package self-reference so
Node applies the package's real `exports`/`main` and ESM conditions.
The previous CommonJS `require.resolve()` picked the `require`
condition and loaded the CJS entry of dual CJS/ESM packages (e.g.
playwright-core), which did not expose their named ESM exports.
- amdX: in `_nodeJSLoadScript`, read module files with the ASAR-aware
`require('fs')` instead of `import('fs')`, which the resolution hook
maps to the ASAR-unaware `original-fs` and therefore cannot read
files inside the archive (e.g. @vscode/iconv-lite-umd).
- agentHost commandAutoApprover: load the tree-sitter `.wasm` files
from node_modules.asar.unpacked in built apps (node_modules in dev).
- agentHost copilotAgent: resolve the @github/copilot-<platform> CLI
and the @microsoft/mxc-sdk sandbox binaries from
node_modules.asar.unpacked in built apps, and unpack
@microsoft/mxc-sdk/bin so those executables can be spawned.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: resolve ASAR modules relative to the archive root
Two follow-up fixes for ASAR support:
- bootstrap-esm: resolve packages inside node_modules.asar with relative
specifiers (require.resolve("./<pkg>/package.json") and "./<spec>")
instead of bare specifiers. The archive directory is named
node_modules.asar, so a bare-specifier resolution walks for a
node_modules directory that does not exist and fails. This broke every
native module imported from main.js in the packaged app
(@vscode/spdlog, @vscode/sqlite3, native-keymap, @vscode/deviceid,
@vscode/policy-watcher), preventing startup.
- create-universal-app: pass `singleArchFiles` so the universal merger
allows files that are unique to a single arch inside the merged
node_modules.asar (the @github/copilot-<arch> platform package and the
arch-specific copilot/ripgrep binaries). These paths are ASAR-internal
(top level, no node_modules prefix); without the allowlist the merge
aborts with "Detected unique file ... not covered by allowList rule".
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: resolve sandbox runtime and Windows CJS lookups with ASAR
* fix: resolve ESM modules from the importer's own node_modules
* fix: unpack node-pty package.json
* fix: resolve node-pty binaries from unpacked asar in Copilot shim
* fix: resolve Copilot native binaries from node_modules.asar.unpacked
* fix: universal build for mxc
* fix: load tree-sitter wasm from node_modules on web
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix Agent Host telemetry gaps (#8209)
- trackEditSurvival: resolve ahp-chat sub-channel URIs to the parent
harness before extracting provider/id (gap #6)
- turnCompleted: add isSubagentSession so subagent activity is
measurable from turn events (gap #4)
- interactiveSessionProviderInvoked: add a harness property derived from
the remote session type so remote AH can be split by harness (gap #2)
- agents/requestSent: fire once per user message (including follow-ups),
add isNewChat, so it works as a per-message counter (gap #5)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Forward host telemetry IDs to local agent host (#8209)
The local agent host process computed machineId/sqmId/devDeviceId live on
every launch, which can diverge from the workbench's persisted, state-backed
identifiers and break per-user telemetry joins. Forward the main process's
already-resolved IDs via env vars and prefer them in the agent host telemetry
service, falling back to live computation when absent (e.g. remote/server AH).
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Revert gap #4 (isSubagentSession on turnCompleted) and gap #5 (agents/requestSent)
turnCompleted never fires for subagent sessions (no matching turnStarted),
and after ahp-chat resolution the session is always the parent, so the
isSubagentSession field was always false. The agents/requestSent
session-create-only behavior was by design. Also restores the JSDoc on
parseRemoteAgentHostSessionTypeAuthority.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add support for system-wide (OS global) keybindings
Allow user keybindings in keybindings.json to be marked with "systemWide": true so they register as operating-system global shortcuts that fire even when the window is not focused.
- Thread the systemWide flag through IUserFriendlyKeybinding, ResolvedKeybindingItem and KeybindingIO (read + serialize)
- New GlobalKeybindingsMainService owns Electron's globalShortcut, reconciles per-window registrations, resolves conflicts deterministically and routes triggers through the existing vscode:runAction path
- New renderer contribution syncs opted-in bindings to the main process, gated behind the experimental, off-by-default setting keyboard.enableSystemWideKeybindings with a one-time confirmation dialog
- Enable the GlobalShortcutsPortal feature on Linux/Wayland
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Avoid focusing the routing window on system-wide keybinding trigger
Force-focusing the routing (main) window before dispatching the command
pulled it to the foreground even when the command opens/reveals a different
window (e.g. openAgentsWindow reveals the agents window), producing a visible
flicker. Remove the force-focus and let the invoked command control what is
surfaced/focused, matching every other vscode:runAction sender.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Add workbench.action.focusWindow to raise the current window
Adds a generic command that brings the current window to the foreground and
focuses it using FocusMode.Force (which works even when the application is not
the active app). This lets users compose system-wide keybindings via
runCommands to reveal the window before running a command that surfaces UI in
it, e.g. [workbench.action.focusWindow, workbench.action.quickOpen].
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Address Copilot review: schema default, mnemonic comment, test grammar
- keybindingService.ts: correct 'systemWide' schema default to false to match
KeybindingIO parsing (defaults to false when absent/invalid)
- systemWideKeybindings.contribution.ts: add '&& denotes a mnemonic' translator
comment to the Enable button label
- keybindingEditing.test.ts: fix test title grammar (a user)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Always enable system-wide keybindings; drop the enablement setting
Removes the experimental `keyboard.enableSystemWideKeybindings` setting so the
feature is always active: any user keybinding with "systemWide": true is a
candidate. The one-time confirmation dialog is retained and now serves as the
opt-out - its Enable/Disable choice is persisted as a tri-state consent
(unset -> ask, granted -> register, denied -> stay off and never re-ask).
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Make the first-run dialog an informational notice, not a permission prompt
The system-wide keybindings feature is always on, so the first-run dialog no
longer needs to grant/deny permission. Replace the Enable/Disable confirm dialog
with a single-button informational notice ("I Understand") shown once before the
first registration. Collapses the tri-state consent to a boolean acknowledged
flag; the feature has no decline path, so there is no stuck off-state.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Add an `experiment: { mode: 'startup' }` hook to `chat.agentHost.enabled`
so the Experimentation Service can cohort-enable it for Stable users. The
static default is unchanged, so Insiders (default-on) and existing related
experiments are unaffected; an override is only registered when the
treatment differs from the default.
Close the main-process spawn gap by always instantiating
ElectronAgentHostStarter + AgentHostProcessManager in app.ts. They are
cheap and spawn the utility process lazily on the first window connection,
so the renderer stays the gate (honoring experiment overrides + policy +
web) for whether the agent host actually starts. Renderer experiment
overrides are never persisted to settings.json, so the previous
main-process `isAgentHostEnabled` guard would have left cohorted Stable
users without a spawned agent host.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a file-based managed-settings delivery channel that reads
managed-settings.json from a well-known per-OS disk path in the main
process and exposes it to renderer windows over IPC. Mirrors the
existing Copilot managed-settings (server / native MDM) channels.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* agent-host: add WSL connection support
Add WSL-based remote agent host connections as a third connection type
alongside SSH and dev tunnels. On Windows, users can pick "WSL..." in the
Remote group of the session workspace picker, choose an installed WSL 2
distro, and the agent host is launched inside that distro. Connected
distros are persisted as remembered entries and auto-reconnected on
startup -- but only when WSL is already running, we never auto-boot a
shut-down distro.
- New IPC contract `IWSLRemoteAgentHostService` / `IWSLRemoteAgentHostMainService`
mirrors the SSH shape. A shared `RelayTransport` base is extracted from
`SSHRelayTransport` so SSH and WSL share the IPC relay pump.
- Shared-process service spawns `wsl.exe -d <distro> -e bash -lc <bootstrap>`,
reuses the SSH CLI install layout helpers verbatim (`~/.vscode-server/cli/...`),
parses the `ws://127.0.0.1:PORT?tkn=...` URL the agent host prints, opens a
local WebSocket, and pumps frames over IPC. Retries the open on
ECONNREFUSED/AggregateError to ride out WSL 2's localhost-forwarding setup
delay on first connect.
- Contribution layer adds `WSLReconnectState` mirroring `SSHReconnectState`
and extracts a shared `_attemptManagedReconnect` template so SSH and WSL
share retry-loop logic (status transitions, incompatible short-circuit,
cached-session unpublish on failure). WSL retries are gated on
`wsl --list --running` so a stopped distro is never auto-booted.
- New "WSL..." action gated on `isWindows && chat.remoteAgentHostsEnabled`;
surfaces install docs (`aka.ms/vscode-remote/wsl/install-wsl`) when WSL is
missing or no WSL 2 distro is installed. The "Select..." button stays
enabled even while a distro is stopped -- explicit user click overrides
the never-auto-boot rule and boots the distro on demand.
- Workspace picker scopes `resolveWorkspace` to the matching connection
authority so a folder picked from one agent host is no longer attributed
to another.
- New `canConnectOnDemand` provider capability keeps `Select...` enabled
while disconnected/connecting for providers with a connect-on-demand
hook; concurrent on-demand clicks join the in-flight reconnect promise
instead of returning early with a misleading toast.
- New parser tests for `wsl --list --verbose` / `--running` output and the
`wsl.exe` UTF-8 / UTF-16LE decode heuristic.
Fixes https://github.com/microsoft/vscode/issues/307568
(Commit message generated by Copilot)
* agent-host: fix test URI authorities for resolveWorkspace scoping
Tests in remoteAgentHostSessionsProvider.test.ts used hardcoded `vscode-agent-host://auth/...` URIs but the provider's connectionAuthority is derived from the configured address (default `localhost:4321` -> `localhost__4321`). After tightening `resolveWorkspace` to only claim URIs whose authority matches its own (Linux/Browser CI failure on PR #319971), these tests started failing. Update the URI authorities to match the actual default.
* fix: combine URI flags to prevent Electron argument filtering on Windows
On Windows, Electron/Chromium's security layer filters out standalone
command-line arguments that look like URLs (containing "://"). This
causes --folder-uri and --file-uri to fail silently when the URI value
is not the last argument.
Combine --folder-uri and --file-uri with their values using "=" syntax
before spawning the Electron process, so Chromium treats them as flags
rather than standalone URL arguments.
Fixes#209072
* Stop rewriting --folder-uri / --file-uri past the -- end-of-options marker
---------
Co-authored-by: Dmitriy Vasyura <dmitriv@microsoft.com>
Fix#317643
The shared-process `UnusedWorkspaceStorageDataCleaner` was deleting the
agents window's workspace storage folder (chat sessions, edits, images,
test results, etc.) when the agents window was not open within ~30s of
Code launching.
The agents window uses a synthetic workspace identifier computed in the
renderer via the browser-side `getWorkspaceIdentifier` (a short hex
hash). The on-disk storage folder is named with this short id, but none
of the cleaner's preservation checks matched it:
- length check expects 32-char MD5 ids
- ext-dev id check does not match
- main-side `window.workspace.id` is the 32-char MD5 (mismatch)
- `isUsed` only true while the agents window is actually open
Changes:
- Move `getWorkspaceIdentifier`/`getSingleFolderWorkspaceIdentifier`
from `workbench/services/workspaces/browser/workspaces.ts` to
`platform/workspaces/common/workspaceIdentifier.ts` so the
shared-process cleaner can import them without layer violations.
- Promote `IEnvironmentService.agentSessionsWorkspace` to required and
add a browser-side implementation in `BrowserWorkbenchEnvironmentService`
(stub in `StandaloneEnvironmentService`).
- In the cleaner, preserve the folder matching
`getWorkspaceIdentifier(env.agentSessionsWorkspace).id`.
- Add a unit test that asserts the agents window folder survives cleanup
while other empty-workspace folders are removed.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove quality !== 'stable' guards from --agents CLI flag handling and last-running marker restore in app.ts
- Remove quality !== 'stable' guard from launchMainService when re-launching with --agents flag
- Remove quality !== 'stable' guard from OPEN_AGENTS_WINDOW_PRECONDITION context key expression
- Enable 'Try out the new Agents' banner in stable (canShowAgentsBanner no longer checks quality)
- Remove the 'tip.openAgentsWindow' chat tip shown above the chat input
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* refactor: remove sub application support
* chore: remove OS entries
* chore: update additional shortcut location on windows
* chore: show one time deprecation banner
* remove other indirect instances of embedded app
---------
Co-authored-by: Sandeep Somavarapu <sasomava@microsoft.com>
Two boot-time/race-condition paths in the shared-process extension management service produce `unhandledRejection` events that surface as `unhandlederror-Cannot read the extension from ...` telemetry buckets, even though the underlying install failure is already reported by the primary install task or logged by the cleanup/migrate flows themselves.
1. Duplicate-install wait promise (abstractExtensionManagementService.ts): when a second install request races for an extension that's already being installed, a sibling promise is created via `Event.toPromise(onDidInstallExtensions).then(...)` and pushed into `alreadyRequestedInstallations`. It's awaited on the success path, but if the outer `try` throws first (e.g. another extension in the same batch fails) control jumps to `catch` and the sibling promise is never observed -> Node fires `unhandledRejection`. Attach a no-op rejection handler so the rejection is always observed; the original promise is still awaited via `joinAllSettled` on the happy path, and the underlying failure is already surfaced through the primary task's error result.
2. Fire-and-forget startup tasks (sharedProcess/contrib/extensions.ts): `extensionManagementService.cleanUp()` and `migrateUnsupportedExtensions()` are called without `await` and without a `.catch`. Any rejection becomes an unhandled rejection. Both paths already log their own internal failures, so the only thing missing is a top-level `.catch(logService.error)` to swallow the orphan.
Net effect: removes the entire `unhandlederror-Cannot read the extension from ...` family from top error buckets without losing any real diagnostic signal.
* Run Agents App in transient mode when VS Code is launched with --transient
When VS Code is launched with --transient, the Agents App now also runs
in transient mode with its own dedicated temporary user data and
extensions directories created under the same temp parent folder.
- Add `--agents-user-data-dir` and `--agents-extensions-dir` CLI args
- In --transient handling, create `agents-data/` and `agents-extensions/`
subdirs alongside existing temp dirs and pass them via the new args
- In `launchSiblingApp`, forward transient agents dirs as
`--user-data-dir` and `--extensions-dir` to the sibling Agents process
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Also forward --shared-data-dir and --agent-plugins-dir to sibling Agents app
To ensure the sibling Agents process is fully isolated in transient mode,
forward shared-data-dir and agent-plugins-dir in addition to user-data-dir
and extensions-dir.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Share secrets between Code and Agents app via macOS Keychain
Add a shared keychain service that stores secrets directly in the macOS
Keychain, allowing Code and its embedded Agents app to share auth tokens
without re-authentication.
Architecture:
- ISharedKeychainService (common interface) with ISharedKeychainMainService
running in the Electron main process, exposed to renderer via IPC
- SharedKeychainMainService wraps @vscode/macos-keychain native addon
- NativeSecretStorageService now writes to both the shared keychain and
the legacy safeStorage+SQLite pipeline (for rollback safety)
- On read, shared keychain is tried first, falling back to legacy
Product configuration:
- darwinSharedKeychainServiceName: per-flavor service name for data
isolation between Stable/Insiders/Exploration
- Access group auto-detected from entitlements by the native addon
Key design decisions:
- Shared keychain only used when type is 'persisted' (not in-memory)
- BaseSecretStorageService refactored to expose protected _doGet/_doSet/
_doDelete/_doGetKeys for use by subclasses within sequencer tasks
- Native addon is an optional dependency (macOS-only)
Files:
- build/azure-pipelines/darwin/app-entitlements.plist (keychain-access-groups)
- src/vs/platform/secrets/common/sharedKeychainService.ts (interface)
- src/vs/platform/secrets/electron-main/sharedKeychainMainService.ts (impl)
- src/vs/workbench/services/secrets/electron-browser/sharedKeychainService.ts (IPC proxy)
- src/vs/workbench/services/secrets/electron-browser/secretStorageService.ts (wiring)
Issue: #308028
* Address review feedback
* Add one-time migration of legacy secrets to shared keychain
On first secret operation, migrate all existing secrets from the legacy
safeStorage+SQLite pipeline into the shared macOS Keychain. This ensures
the Agents app can read secrets that were stored before the shared
keychain was introduced.
- Migration is lazy (triggered on first get/set/delete/keys)
- Guarded by a 'sharedKeychain.migrationDone' storage flag
- Idempotent: keychain writes are upserts, re-running is safe
- Best-effort per key: individual failures don't block the rest
- Skipped when type is 'in-memory'
- Also: make set() in SharedKeychainMainService best-effort (log, don't throw)
* update the current implementation
* restrict shared keychain to CROSS_APP_SHARED_SECRET_KEYS
* kick off shared keychain migration eagerly in constructor
* update @vscode/macos-keychain to 0.0.1
* Use provisioning profile for keychain access groups when available
During signing, check for build/darwin/distribution.provisionprofile.
If present, use it as the provisioning profile and keep the
keychain-access-groups entitlement in app-entitlements.plist.
If not present (e.g. OSS builds), strip the keychain-access-groups
section from a temp copy of the entitlements plist to avoid signing
failures. The shared keychain still works via the app's default
keychain without access-group isolation.
* Add entitlements diagnostic dump after signing
Dump the actual entitlements from the signed binary to validate
whether $(TeamIdentifierPrefix) is being expanded by codesign.
Hypothesis: the variable is passed literally to the entitlements
plist without expansion, causing a mismatch with the provisioning
profile and resulting in Killed: 9 on launch.
* Exclude provisioning profile from unicode hygiene check
* update package-lock.json
* Adopt multiple provision profiles
* fix: expand teamidentifier in the entitlement
* Re-sign without provisioning profile for tests
Run the entitlements step twice in CI:
1. First with provisioning profile (keychain-access-groups) for codesign/notarize
2. Then without provisioning profile for tests (in parallel with codesign)
This avoids making codesign sequential with tests while still
supporting the keychain-access-groups entitlement that requires
a provisioning profile.
- Add --skip-provisioning-profile flag to sign.ts
- Add 'Set Hardened Entitlements (for tests)' pipeline step
* Skip plist modifications when re-signing for tests
The plutil -insert calls fail on the second sign pass because the
keys already exist from the first pass. Skip plist modifications
when --skip-provisioning-profile is set since they are not needed.
* Move shared keychain migration from renderer to main process
Replace crossAppIPC-based secret handshake with direct shared keychain
writes in the main process:
- MacOSCrossAppSecretSharing now reads safeStorage+SQLite and writes to
shared keychain via SharedKeychainMainService (no crossAppIPC needed)
- Code.app migrates on startup; Agents app spawns Code.app once if
keychain is incomplete
- NativeSecretStorageService no longer does migration — just reads/writes
shared keychain for cross-app keys
* Add isMacintosh guards before using the shared keychain service
Co-authored-by: Copilot <copilot@github.com>
* Remove spec
* Tweak comments
---------
Co-authored-by: deepak1556 <hop2deep@gmail.com>
Co-authored-by: Copilot <copilot@github.com>
* Move agentPluginsHome to IUserDataProfile and IEnvironmentService
- Add agentPluginsHome to IEnvironmentService (platform level)
- Add agentPluginsHome to IUserDataProfile (same value for all profiles)
- Remove agentPluginsHome from IWorkbenchEnvironmentService
- Remove agentPluginsHome getter from NativeWorkbenchEnvironmentService
- Update AgentPluginRepositoryService to read from IUserDataProfileService
- Update toUserDataProfile signature with new agentPluginsHome parameter
- Update all test files and consumers
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address review feedback
- Remove redundant agentPluginsHome override in embedded app
(already correct from environment service since dataFolderName is shared)
- Add agentPluginsHome to isUserDataProfile type guard
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add --agent-plugins-dir to --transient feature
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Derive agentPluginsPath from extensions parent directory
Agent plugins are now stored as a sibling of the extensions directory
(e.g., ~/.vscode-insiders/agent-plugins/ next to ~/.vscode-insiders/extensions/).
This means --extensions-dir and --transient automatically co-locate
agent plugins without needing a separate --agent-plugins-dir flag.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix test: only co-locate agent-plugins when extensions-dir is explicitly set
Avoid calling this.extensionsPath in the default agentPluginsPath
fallback, which breaks tests where environment args are empty objects.
Instead, check args['extensions-dir'] directly and only co-locate
when it is explicitly overridden.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Revert env service change; only co-locate agent-plugins in --transient
Keep agentPluginsPath original logic in environment service. The
--transient handler in cli.ts passes --agent-plugins-dir explicitly
to co-locate agent plugins under the same temp parent directory.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Compute host agent-plugins path for embedded Agents app
Extract getAgentPluginsPath as a shared function. In the embedded
Agents app, compute the host VS Code's agent-plugins directory using
quality-specific dataFolderName, matching the hostUserRoamingDataHome
pattern. Add --agent-plugins-dir to --transient feature.
Add agentPluginsHome to isUserDataProfile type guard.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix warnings
* simplify
Co-authored-by: Copilot <copilot@github.com>
* fix
Co-authored-by: Copilot <copilot@github.com>
* fix
Co-authored-by: Copilot <copilot@github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <copilot@github.com>
Restore agents application support on Linux
Remove the Linux platform check that was added in 683373f3, re-enabling
the agents window on Linux for non-stable builds.
- Restore `ProductQualityContext.notEqualsTo('stable')` in the command
precondition instead of the Linux-specific context key expression
- Clean up unused `isLinux`/`IsLinuxContext` imports
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace crossAppIPC-based secret handshake with direct shared keychain
writes in the main process:
- MacOSCrossAppSecretSharing now reads safeStorage+SQLite and writes to
shared keychain via SharedKeychainMainService (no crossAppIPC needed)
- Code.app migrates on startup; Agents app spawns Code.app once if
keychain is incomplete
- NativeSecretStorageService no longer does migration — just reads/writes
shared keychain for cross-app keys
* agentHost: resolve user shell environment for agent host process
Spawn the agent host with the user's resolved shell environment merged
in (PATH and friends from the login shell), matching what other VS Code
processes do via getResolvedShellEnv. Without this, tools and terminals
launched by the agent host on macOS/Linux GUI launches don't see the
user's PATH.
Both ElectronAgentHostStarter and NodeAgentHostStarter now resolve the
shell env before spawning. IAgentHostStarter.start() is now async; the
process managers await it and guard against being disposed mid-await.
In the Electron starter, the renderer's createMessageChannel request
could race ahead of the now-async start() and call utilityProcess.connect()
before utilityProcess.start() had run, silently dropping the MessagePort
and leaving the renderer with no agents. _onWindowConnection now awaits
a DeferredPromise that completes once the utility process has actually
been spawned.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* agentHost: address Copilot review feedback
- ElectronAgentHostStarter: spread shellEnv after process.env so the
resolved login shell PATH actually wins over the GUI-launched env.
(NodeAgentHostStarter is fine as-is: ipc.cp.Client merges process.env
before the options env, so shellEnv there already wins.)
- AgentHostProcessManager._start / ServerAgentHostManager._start: wrap
the body in try/catch so a rejection from starter.start() doesn't
surface as an unhandled promise rejection. Reset state on failure so
future starts can retry. Server manager applies the same MaxRestarts
policy as the unexpected-exit path.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* shared application storage
* add tests
* fix tests
Co-authored-by: Copilot <copilot@github.com>
* add logging and address feedback
* Add application shared storage scope
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add fallback migration for APPLICATION_SHARED storage
VS Code: AbstractStorageService.get() falls back from
APPLICATION_SHARED to APPLICATION scope transparently,
enabling lazy per-key migration without a registry.
Agents App: SharedSQLiteStorageDatabase reads the host
(VS Code) app's application storage DB as a fallback
during getItems(), merging missing keys so shared data
is available even before VS Code runs with new scope code.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Move storage fallback into Storage class with auto-migration
Move the APPLICATION → APPLICATION_SHARED fallback logic from
AbstractStorageService into the base Storage class via the new
fallbackStorage property on IStorage. When a key is not found,
the fallback is checked and the value is automatically written
through to persist the migration.
This eliminates duplicated fallback code in get/getBoolean/
getNumber and ensures write-through happens for all access
patterns.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Make fallbackStorage an implementation detail of Storage
Remove fallbackStorage from IStorage interface. It is now a
property on the Storage class only, set directly by callers
that have access to the concrete type.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Pass fallback storage via ApplicationSharedStorageMain constructor
Wire up the application storage as fallback during doCreate()
instead of post-init. The ApplicationStorageMain is created
first and passed to ApplicationSharedStorageMain's constructor.
The fallback is set on the Storage instance when the shared
database is created, so it's ready by the time reads happen.
Removes setFallbackStorage() method and post-init wiring.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Remove fallbackDatabasePath - use fallbackStorage only
The in-memory fallbackStorage (application storage) makes the
DB-level fallback (reading VS Code's DB from disk) redundant.
Both VS Code and Agents App now use the same mechanism: the
Storage.fallbackStorage property that reads from application
storage and auto-migrates on hit.
Removes getHostUserDataPath, IProductService dependency, and
INativeEnvironmentService from StorageMainService.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add MigratingStorage with persisted migration tracking
Introduce MigratingStorage that migrates keys from a fallback
storage on first access. Migrated keys are tracked via a
persisted marker key (__$__migratedStorageMarker) in the DB
so deleted keys are never resurrected from the fallback.
- VS Code windows: MigratingStorage falls back to own
APPLICATION storage for transparent key migration
- Sessions windows: MigratingStorage falls back to host
(VS Code) application storage loaded via IPC
- Main process: ApplicationSharedStorageMain uses
HostApplicationStorageMain for embedded app fallback
- sharedDataFolderName added to product configuration
- Workspace trust migration simplified (handled by
MigratingStorage automatically)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix compilation
* minimise changes
* some fixes
Co-authored-by: Copilot <copilot@github.com>
* fixes
* fix
* delete migrated key
* fix removing migrated key
* update distro
* feedback
* Fix MigratingStorage: persist marker only on actual migration
Add key to migratedKeys immediately before checking fallback
to prevent redundant lookups. Only persist the MIGRATED_KEY
marker when a value was actually found and migrated, avoiding
unnecessary writes when the key doesn't exist in the fallback.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feedback
* fix tests
Co-authored-by: Copilot <copilot@github.com>
* fix application storage path
* fix compilation
---------
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>