Repository navigation
agentHost: mirror Fusion to remote and tunnel Agent Hosts - #342136
Merged
Merged
Conversation
`chat.copilot.ensemble.enabled` (Fusion) was forwarded only to the local Agent Host by `AgentHostRootConfigForwarder`, because its value also depends on the account's `chat_preview_features_enabled` gate, which remote hosts cannot read. Sessions on a remote or tunnel host therefore always showed plain Auto, even when the user enabled Fusion or was assigned the experiment. Fold the preview-features gate into the setting itself with a `CopilotFusion` policy (locked to false when the account disables preview features) and mirror the setting declaratively with `agentHost`, so every host - local, remote extension host, and tunnel - receives the policy- and experiment-resolved value. Also write the legacy `ensemble` key for hosts built before the Ensemble to Fusion rename. The local-only forwarder no longer owns the key; it still derives the HydraFusion keys from Fusion for the local host, and remote hosts already couple HydraFusion to Fusion themselves. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
🔵 Needs a closer look
The new enterprise-policy contract needs maintainer resolution of the legacy-channel restriction and canonical export validation.
1 open finding
What changed in this PR
Extends Fusion configuration mirroring to remote and tunnel Agent Hosts, preserving compatibility with older hosts.
Changes:
- Moves Fusion registration into a shared module and mirrors both
fusionand legacyensemble. - Adds the
CopilotFusionpolicy and removes local-only Fusion forwarding. - Tests cross-host mirroring and preview-feature gating.
| File | Description |
|---|---|
| src/vs/workbench/contrib/chat/test/browser/agentSessions/agentHostCopilotCliSettingsContribution.test.ts | Updates local forwarding expectations. |
| src/vs/workbench/contrib/chat/browser/chat.shared.contribution.ts | Registers the shared Fusion definition. |
| src/vs/workbench/contrib/chat/browser/agentSessions/agentHost/agentHostCopilotCliSettingsContribution.ts | Removes local-only Fusion forwarding. |
| src/vs/platform/agentHost/test/common/agentHostConfigurationSync.test.ts | Tests mirroring and policy resolution. |
| src/vs/platform/agentHost/common/fusionConfiguration.ts | Defines Fusion mirroring and policy metadata. |
| src/vs/platform/agentHost/common/agentHostPolicySupport.ts | Marks the policy as enforced. |
| build/lib/policies/policyData.jsonc | Adds the enterprise-policy catalog entry. |
🧠 Review effort: Balanced
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Preserve account preview-feature gating in the protocol client and cover remote transitions with three focused tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
No blocking defects remain identified, and focused regression coverage supports the forwarding behavior, although live tunnel UI verification remains outstanding.
0 open findings
1 resolved since last review
🧠 Review effort: Balanced
…e-agent-host # Conflicts: # src/vs/platform/agentHost/browser/agentHostProtocolClient.ts # src/vs/platform/agentHost/test/electron-browser/agentHostProtocolClient.test.ts # src/vs/workbench/contrib/chat/browser/agentSessions/agentHost/agentHostCopilotCliSettingsContribution.ts # src/vs/workbench/contrib/chat/browser/chat.shared.contribution.ts # src/vs/workbench/contrib/chat/test/browser/agentSessions/agentHostCopilotCliSettingsContribution.test.ts
Bhavya U (bhavyaus)
force-pushed
the
bhavyaus/fusion-remote-agent-host
branch
from
October 17, 2026 00:11
1bb7bfb to
bbe5953
Compare
Contributor
Dmitriy Vasyura (dmitrivMS)
approved these changes
Oct 17, 2026
Bhavya U (bhavyaus)
enabled auto-merge (squash)
October 17, 2026 00:16
|
محمد
في سبت، ١٧ أكتوبر، ٢٠٢٦ في ٣:٣٠ ص، كتب Copilot ***@***.***
…:
***@***.**** commented on this pull request.
🔵 Needs a closer look
Shared remote runtime configuration and unresolved account-initialization
and experiment-tracking concerns require maintainer review.
*2 open issues*
- [image: Medium severity] Reconcile Fusion after delayed default
account initialization
<#342136 (comment)>
· New
- [image: Medium severity] Track Fusion experiment exposure for
remote-only users
<#342136 (comment)>
· New
Review effort: Max
------------------------------
In src/vs/platform/agentHost/browser/agentHostProtocolClient.ts
<#342136 (comment)>:
> + const enabled = this._defaultAccountService.policyData?.chat_preview_features_enabled !== false
+ && getGlobalConfigurationValue<boolean>(this._configurationService, AgentHostFusionEnabledSettingId) === true;
On a cold start without cached policy, a remote host can connect before
the initial account refresh finishes. This sends true while policyData is
null. DefaultAccountService.setDefaultAccountProvider() only subscribes
to policy changes after that refresh completes (
src/vs/workbench/services/accounts/browser/defaultAccount.ts:193–199), so
the initial restrictive result is not forwarded and Fusion can remain
enabled until another update or reconnect. Reconcile Fusion when
getDefaultAccount() resolves without blocking the handshake, including
when initialization finishes during the handshake, and add a
delayed-initialization regression test.
------------------------------
In src/vs/platform/agentHost/browser/agentHostProtocolClient.ts
<#342136 (comment)>:
> + const enabled = this._defaultAccountService.policyData?.chat_preview_features_enabled !== false
+ && getGlobalConfigurationValue<boolean>(this._configurationService, AgentHostFusionEnabledSettingId) === true;
+ // Older hosts still consume the pre-rename Ensemble key.
+ this._dispatchRootConfig({ [CopilotCliConfigKey.Fusion]: enabled, ensemble: enabled });
Forwarding the experiment default now exposes remote-only users to Fusion
without recording the existing experiment trigger.
CopilotAgent._reportFusionExperimentTrigger() waits for
copilotCliVSCodeAssignmentContext (
src/vs/platform/agentHost/node/copilot/copilotAgent.ts:3374–3378), but
its only writer is the local AgentHostPrewarmer, which is also skipped in
remote-authority windows (
src/vs/workbench/services/agentHost/electron-browser/agentHostService.ts:111–136).
These exposures are therefore missing from the triggered scorecard,
potentially biasing its results. Extend exposure tracking to remote hosts
at the same arm-independent Auto-model publication boundary, with the
client's assignment context, or explicitly revise the experiment design
before analyzing this expanded rollout.
—
Reply to this email directly, view it on GitHub
<#342136?email_source=notifications&email_token=A47VY6RGP2DWYYTKK6C6VYT5UK4UBA5CNFSNUABKM5UWIORPF5TWS5BNNB2WEL2QOVWGYUTFOF2WK43UKJSXM2LFO4XTKNJVGUYDOMZQG4ZKM4TFMFZW63VKON2WE43DOJUWEZLEUVSXMZLOOSWGM33PORSXEX3DNRUWG2Y#pullrequestreview-5555073072>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/A47VY6VDW6EB5GGVLWOVAYL5UK4UBAVCNFSNUABEKJSXA33TNF2G64TZHM2DCOBYGE4TAMB3JFZXG5LFHM2TQOBYG44TSMRRGOQXMAQ>
.
Triage notifications, keep track of coding agent tasks and review pull
requests on the go with GitHub Mobile for iOS
<https://github.com/notifications/mobile/ios/A47VY6QMLSLUEAPLMQ464NT5UK4UBA5CNFSNUABKM5UWIORPF5TWS5BNNB2WEL2QOVWGYUTFOF2WK43UKJSXM2LFO4XTKNJVGUYDOMZQG4ZKM4TFMFZW63VKON2WE43DOJUWEZLEUVSXMZLOOSVGM33PORSXEX3JN5ZQ>
and Android
<https://github.com/notifications/mobile/android/A47VY6UR2ZVYYXJPPNRSRRT5UK4UBA5CNFSNUABKM5UWIORPF5TWS5BNNB2WEL2QOVWGYUTFOF2WK43UKJSXM2LFO4XTKNJVGUYDOMZQG4ZKM4TFMFZW63VKON2WE43DOJUWEZLEUVSXMZLOOSXGM33PORSXEX3BNZSHE33JMQ>.
Download it today!
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
Bhavya U (bhavyaus)
added a commit
that referenced
this pull request
Oct 17, 2026
…preview-features gate `chat.copilot.dynamicAutoTiers.enabled` was forwarded only to the local Agent Host, and without the account's `chat_preview_features_enabled` gate. So an experiment could turn on server-driven tiers, which can offer HydraFusion, for accounts that disabled preview features, while remote and tunnel Agent Hosts never got the setting. Forward it the way #342136 forwards Fusion: the protocol client dispatches `dynamicAutoTiers` to every host (local, remote, and tunnel) on connect, on reconnect, when the setting changes outside the workspace layers, and when the account's policy changes, and only while preview features are allowed. The setting is registered beside Fusion in `fusionConfiguration.ts`, and the local-only forwarder no longer owns the key. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Bhavya U (bhavyaus)
added a commit
that referenced
this pull request
Oct 17, 2026
…lot.dynamicAutoTiers.enabled (#341688) * Agent host: read Auto tiers from runtime models.list behind chat.copilot.dynamicAutoTiers.enabled Adds a client-owned opt-in, off by default, that launches the Copilot runtime with DYNAMIC_AUTO_TIERS. With it on, server-level models.list returns the provider's Auto tiers from CAPI /meta (SDK 1.0.23-preview.0, github/copilot-agent-runtime#26406), and Auto's "Optimize for" picker is built from them instead of the hard-coded efficiency/balance/intelligence. - The setting is a startup key: changing it restarts the runtime after active turns finish, and the restart drops the old runtime's tiers so sessions never send a tier the new runtime rejects. - Sessions accept exactly the enabled auto/fusion tiers the provider advertises; without Auto metadata the built-in tiers apply. - HydraFusion Max is offered only with HydraFusion v2, since the runtime rejects the hydrafusion-max preference without HYDRAFUSION_PLAN_V2. - Committed Auto tiers reported by the runtime (for example hydrafusion) are kept for edit attribution instead of being dropped. Based on the proof of concept in #341429. Co-authored-by: Andy Salerno <ansalern@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Agent host: show unavailable Auto tiers disabled with their reason, per copilot-api#39882 Follows the /meta integration rules in github/copilot-api#39882 and fixes the review findings on this PR. - Tiers the provider lists with status.enabled false are shown in the picker, in the provider's order, but cannot be selected; status.message (or a generic reason) is their tooltip. The protocol tier enum still holds only selectable tiers; the full list travels in the Auto model's _meta (vscode.chat.autoTiers), so other clients keep working. A saved tier that becomes unavailable is dropped and reads as the default. - Stale models.list responses no longer overwrite tier metadata: the metadata is applied together with the catalog, under the same token and generation checks, and schemas are built from the response's own metadata. The fallback Auto model is built per metadata as well. - Metadata whose tiers are all unavailable now accepts no preference, instead of falling back to the built-in tiers the runtime would reject. - A provider tier restored before the Auto model registers keeps its value and provenance until the schema can validate it. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Agent host: show the service's Fusion tier promotions in the Fusion discount Wires /meta service_messages promotions (github/copilot-api#39882) into how Fusion presents its discount. - The agent host reads service_messages from the same models.list response as the Auto tiers (defensively, until the SDK types it), keeps promotion kinds that target auto_tier IDs with valid dates, and attaches them to the Auto model's _meta (vscode.chat.autoTierPromotions). - With Fusion, a running promotion replaces Fusion's own discount on the tiers it covers ("Models routed via Fusion Max receive a 30% discount."), and the header chip shows it when it covers every Fusion tier. The card shows the service's message: running ones with their end date, upcoming ones with their start date; ended ones are hidden. The picker re-publishes when a promotion starts or ends. - Fusion now names the provider's tiers Lite (balance), Balance (hydrafusion), and Max (hydrafusion-max), including unavailable ones, and no longer adds the HydraFusion models as extra Balance/Max options when its tiers already offer them. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Agent host: keep Auto tier availability consistent across restarts and chat-scoped choices Addresses review feedback on the provider Auto tiers. - A runtime restart that keeps DYNAMIC_AUTO_TIERS re-derives the accepted tiers from the retained provider metadata with the current HydraFusion v2 setting, so a restart that turns v2 off stops accepting hydrafusion-max before the models refresh. - When the provider lists picker tiers but none are selectable, the Auto tier property stays with an empty enum and no default, so the picker can still list the unavailable tiers and their reasons. - A chat's own tier choices (the per-chat configuration report) keep the provider's unavailable tiers disabled, in the shared order, rebuilding enum, labels, descriptions and enumItemDisabled together instead of leaving them misaligned. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Agent host: tighten Fusion's presentation of provider Auto tiers Addresses a full review of the provider Auto tiers. - A chat on a HydraFusion model moves to Fusion with that model's tier when Fusion's provider tiers offer it, so the picker shows it selected instead of an unrelated tier. Unavailable or read-only tiers stay put. - Fusion offers Balance once: the legacy intelligence tier is left out when the provider's HydraFusion tier is Fusion's Balance. - Fusion renames only the tiers it knows (balance, intelligence, hydrafusion, hydrafusion-max) and keeps the provider's label for others. - Fusion's default falls back to Balance only when offered, else the first tier, and a saved Efficiency runs as Balance only while the provider accepts it; otherwise the runtime's default applies. - Tiers the provider keeps out of the picker (status.tier_picker_enabled false, github/copilot-api#39882) are hidden, read defensively until the SDK types it; they stay accepted, like fast. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Agent host: never save a Fusion tier the picker derives from a HydraFusion model Found by driving the Agents window against the real runtime and a mock /meta (Auto and Fusion with provider tiers). - A new chat can start on the HydraFusion model because it is the first model available before the catalog loads. Showing that chat as Fusion with the hydrafusion tier wrote the tier through the global model configuration when the picker had no chat-scoped configuration, so every later chat inherited Balance (HydraFusion) as an explicit choice. The tier is now only presented for the chat; without chat-scoped configuration the selection is left as it is. - In that case the card keeps the HydraFusion model as an option, so the chat's model is still shown as selected. - Presenting a provider tier (for example hydrafusion) now marks it as session state like a built-in tier, rather than leaving it to be treated as an explicit selection. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Agent host: trim comments and redundant tests for provider Auto tiers Keeps only comments that explain non-obvious behavior, and drops tests whose behavior is already covered by other tests in the change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address Copilot review: override precedence, shared tier validation, promotion refresh, hidden Max Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Agent host: offer only runtime-listed HydraFusion with DYNAMIC_AUTO_TIERS With DYNAMIC_AUTO_TIERS the runtime's /meta catalog decides whether an account can run HydraFusion (as Auto tiers, disabled with a reason when unavailable), so stop injecting the setting-driven HydraFusion and HydraFusion Max rows in _publishModels. Injecting them offered HydraFusion to accounts the runtime rejects before routing (#339959). Runtimes without the flag keep the injected rows. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Agent host: read Auto tier picker visibility and promotions in the runtime's shape github/copilot-agent-runtime#27103 applies `/meta` `service_messages` in the runtime and exposes them on `models.list().auto`, so match its SDK contract instead of the CAPI field names: - Picker visibility is `auto.tiers[].status.pickerVisible` (absent means visible), not `tier_picker_enabled` / `tierPickerEnabled`. - Promotions are per tier on `auto.tiers[].billing.promo`, not a top-level `service_messages` list. The runtime already drops unknown kinds and targets and ended promotions and keeps one per tier, so the agent host only groups them by promotion into the tiers each covers. - `id`, `message` and `discountPercent` are optional in that contract: an unnamed promotion is keyed by its content, a missing discount is an announcement, and a promotion without a message changes the discount line without a banner. The SDK does not type these fields yet, so they are read defensively and light up with the next SDK bump. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Agent host: mirror Dynamic Auto Tiers to every Agent Host behind the preview-features gate `chat.copilot.dynamicAutoTiers.enabled` was forwarded only to the local Agent Host, and without the account's `chat_preview_features_enabled` gate. So an experiment could turn on server-driven tiers, which can offer HydraFusion, for accounts that disabled preview features, while remote and tunnel Agent Hosts never got the setting. Forward it the way #342136 forwards Fusion: the protocol client dispatches `dynamicAutoTiers` to every host (local, remote, and tunnel) on connect, on reconnect, when the setting changes outside the workspace layers, and when the account's policy changes, and only while preview features are allowed. The setting is registered beside Fusion in `fusionConfiguration.ts`, and the local-only forwarder no longer owns the key. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Agent host: let the service's Auto tier promotions alone decide Fusion's discount While `/meta` promotes Auto's tiers, Fusion also kept Auto's own discount from the model catalog: the picker row and the card's header showed "10% discount" and the other tiers said "receive a 10% discount", next to promotions for 20% and 30%. While any promotion is published for Auto's tiers, the agent host no longer publishes Auto's own discount, so the discount comes only from the promotions: the header shows a running promotion that covers every tier, and a tier's line shows the running promotion that covers it. Without promotions, or once they end, Auto's own discount returns. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Agent host: test that DYNAMIC_AUTO_TIERS keeps HydraFusion hidden while signed out Covers #342040 with the runtime flag on. Signed out, only BYOK models are published: no Auto, and no HydraFusion row. Signed in, the picker shows only the runtime's catalog, with HydraFusion offered only as an Auto tier. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Andy Salerno <ansalern@microsoft.com> 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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.

Summary
Forward Fusion to remote and tunnel Agent Hosts while preserving the existing account preview-feature restriction, without adding a public enterprise policy.
Previously,
chat.copilot.ensemble.enabledand the account preview-feature gate were combined by a local-only forwarder. Remote/tunnel hosts did not receive that result, so enabling the client setting or its experiment default normally left remote sessions showing Auto.Changes
chat_preview_features_enabled !== false, then send the result on connection, reconnection, setting changes, and account policy-data changes.fusionand legacyensemblefor hosts predating the rename in Rename Ensemble to Fusion across the codebase #341932.chat.copilot.ensemble.enabledsetting ID, startup experiment, false default, and application-machine scope. Do not overwrite the user's preference when the account restricts preview features.CopilotFusionpolicy and its support/catalog entries. The canonically regenerated policy catalog exactly matches the pre-PR catalog.Validation
npm run build-fast -- --client-only— passed.npm run typecheck-client— passed.npm run eslint -- src\vs\platform\agentHost\test\electron-browser\agentHostProtocolClient.test.ts— passed.The inherited
COPILOT_HOMEwas cleared only in the test subprocess; otherwise two existing attachment-path fixtures used the caller's home instead of their test home.git diff --check— passed.The Windows native build toolchain lacks Spectre libraries. Required exporter native modules were restored from the installed official VS Code after checking exact package versions and identical Electron version/ABI/architecture. The exporter completed despite warnings for other unavailable native components. Live tunnel UI verification has not been performed for this revision.
After merging
main(incl. #342200 and #342167):npm run typecheck-clientpassed. ESLint on the changed files passed. The affected suites (protocol client, SSH/WSL, settings contribution, chat contribution, model picker telemetry) — 1,107 passing, 0 failing. The Fusion routing settings and wire keys keep #342200's names. This PR only updates thechat.copilot.ensemble.enableddescription infusionConfiguration.tsto say "Standard, High, or Max".Manual verification
"chat.copilot.ensemble.enabled": true; confirm the host receivesfusion=trueandensemble=true.A runtime restart is conditional on startup configuration changing and can be deferred while work is active, so a restart log alone is not the verification criterion.
Scope and caveats
chat.copilot.ensemble.intelligenceUsesHydraFusion) remains local-only.