Skip to content

[Exploration] Prototype a managed Auto-tier default - #336833

Closed
Ross Wollman (rwoll) wants to merge 1 commit into
mainfrom
rwoll/auto-tier-managed-default-prototype
Closed

Ross Wollman (rwoll) wants to merge 1 commit into
mainfrom
rwoll/auto-tier-managed-default-prototype

Conversation

@rwoll

Copy link
Copy Markdown
Member

Exploratory implementation, not a shipping proposal

Refs #336829. This draft sizes the managed Auto-tier default through the real model-configuration/picker/request seams. Names, lifecycle semantics, and the cross-client schema are not finalized. No reasoning/context-tier settings, model restrictions, or policy-precedence redesign are proposed here.

Validation limitation: source transpilation and targeted lint pass. The execution environment denied both focused browser and Node unit-test commands. The added tests have not run; no interactive, live-runtime, or end-to-end success is claimed. Full typecheck also remains blocked by checkout prerequisites described below.

Provisional contract

{ "autoTier": "intelligence" }
  • Only this experimental top-level key is assumed, localized beside the existing managed-model keys. It projects through ChatDefaultAutoTier into hidden, application-scoped chat.experimental.defaultAutoTier. The consumer reads the policy value, not workspace/user values of this delivery slot.
  • Accepted values reuse the existing Agent Host vocabulary: efficiency, balance, intelligence. No alias translation, fast, reasoning level, or context tier is invented.
  • This does not select Auto. Existing model selection, including chat.defaultModel, user choices, and model eligibility, is unchanged. The tier matters only when a catalog-advertised Auto model supports it.
  • Explicit/restored tier selections and remembered scoped configurations win. A non-default profile-global tier also wins. No managed value means no new default.

Implemented path

Managed-settings projection → configuration policy → editor-scoped ChatModelConfigurationStore → Auto picker and ChatWidget.getSelectedModelRequestOptions() → existing AHP ModelSelection.config.tier.

The store overlays the default transiently, labels its provenance in the Auto row without disabling controls, and omits it from persisted input drafts/preferences. Selecting any tier, including the currently displayed default or schema-default Balance, becomes an explicit choice.

The existing Agent Host implementation forwards that selection as SDK capi.autoTier on creation and through model changes. SDK 1.0.14 is already bundled; no SDK/runtime upgrade or parallel routing implementation is added. Ordinary resume deliberately preserves runtime-owned routing state; empty-history fallback uses creation semantics. This draft leaves that distinction intact.

The legacy permissions bridge in agentHostManagedSettings.ts is intentionally untouched. The bundled SDK's host-injected ManagedSettings contract is permissions-only and rejects unknown siblings: sending autoTier there would be wrong. Standalone/headless host defaults and upstream managed-document acceptance remain separate work, not a faked transport success.

Edge cases, evidence, and unresolved behavior

“Tests authored” below means coverage exists in this diff, not that it executed.

Case Implementation/evidence Remaining issue
No policy; user-only delivery-slot value Preserves baseline; tests authored Runtime regression execution
Fresh Auto + managed default Actual picker/configuration store and AHP creation tests authored Live SDK turn validation
Explicit tier, including Balance and reselecting the managed value Overrides default; picker radio activation and persistence tests authored Cross-window replay
Concrete model; default model Auto vs concrete Tier code does not change selection; non-Auto exclusion test authored; selection controller unchanged Full widget/model-default cross-product
Existing scoped entry or restored tier Wins, including an empty scoped reset; tests authored Scoped storage cannot distinguish “changed context only” from a stripped explicit default tier. Conservative choice: any existing scoped entry wins
Profile-global default-valued tier Global service already materializes/strips schema defaults An explicit global Balance without a scoped entry is indistinguishable from no preference. This pre-existing information loss needs a product/storage decision
Late policy / update / removal Unchosen in-memory stores re-read policy and emit changes; tests authored A draft already captured before policy arrival contains a baseline tier and is conservatively treated as restored choice; test authored. This is not a promise that every open conversation retargets
SDK resume/reconnect Existing launcher preserves committed runtime state on ordinary resume; falls back to create for empty history Durable requested/default/effective provenance and reconnect behavior need integration tests
Restoring governed Auto history Effective historical tier stays session-scoped rather than seeding user preferences; test authored SDK history lacks default provenance. This conservative prototype also stops restored context configuration from seeding the scoped bucket while Auto is governed
Switching away/back; harness changes Per-model snapshots retained; existing harness scope change calls store clear() Full lifecycle tests still needed
Missing catalog / unsupported or unknown tier Current schema and shared vocabulary checked; unsupported values log a warning, show no managed-default provenance; registration/removal tests authored. Non-string managed values use existing projection diagnostics Catalog-change race and capability downgrade integration
Eligibility, model allowlists, plan constraints No catalog entries, capabilities, or model-selection rules are added/relaxed Real account/plan tests
Account, workspace, window changes Default is read in the requesting editor, not copied into shared host root config Authentication transitions and multi-window drafts are unverified; effective default is intentionally absent from draft synchronization
Parent/subagent inheritance No global model-configuration service or shared host default is changed Existing explicit-selection inheritance still applies; automation and non-widget/headless creation do not gain this default
Debug/eval tier override Existing override retains its existing priority Can supersede picker display; not reinterpreted as enterprise enforcement

Local is not assumed equivalent to Agent Host. Local's current extension path reads modelConfiguration.tier, uses it in Auto routing, and includes the tier in cache compatibility. Its inline-chat resolver intentionally substitutes a surface default when the materialized tier equals Balance, unlike Agent Host. Thus a managed Balance cannot currently express the same inline behavior. No extension changes or claims of Local runtime verification are included. Automation uses another configuration store and is not covered by this widget prototype.

Reasoning effort/context configuration share the same snapshot, restore, default-stripping, and persistence machinery. That coupling—not the number of settings—is the significant sizing risk. This draft deliberately does not add speculative reasoning/context policies.

Overlap inspected: existing Auto-tier support and SDK switching (#329463, #333626, #335103, #336597) are reused, not reimplemented. #329405 is a different Local settings experiment; #336533 concerns server-assigned model defaults, not managed tier selection. #327879's default-versus-lock distinction is retained.

Scope and remaining work

The small policy declaration is not the feature's cost. The prototype changes nine TypeScript files and adds 15 test cases (12 store/picker cases, two parameterized AHP cases, one projection case). Completing this is a moderate-to-large state/lifecycle integration, not a settings-only patch:

  1. Settle managed key/schema and whether defaults follow policy changes or are frozen per conversation.
  2. Represent explicit versus default tier intent durably across scoped/global storage, drafts, history, AHP, and runtime resume. Avoid migrating an administrator's choice into user preferences.
  3. Decide the Local inline, automation/headless, remote host, account-change, and subagent behavior; then test those paths.
  4. Resolve policy-provenance UX for restored sessions and debug overrides without suggesting a mandatory model lock.
  5. Run the authored tests, live routing verification, and generate/review policy artifacts before any rollout.

build/lib/policies/policyData.jsonc is not manually edited or regenerated in this draft. Its official exporter needs the Workbench and Agents application export paths; this checkout lacks Electron prerequisites. Generated administrative templates and final policy naming are explicit completion blockers, not shipped artifacts.

Exact validation and limits

Node 24.18.0, matching .nvmrc.

Passed:

npm run transpile-client
git diff --check
npm run eslint -- \
  src/vs/platform/policy/common/copilotManagedSettings.ts \
  src/vs/platform/policy/test/common/copilotManagedSettings.test.ts \
  src/vs/workbench/contrib/chat/browser/chat.shared.contribution.ts \
  src/vs/workbench/contrib/chat/browser/widget/input/chatInputPart.ts \
  src/vs/workbench/contrib/chat/browser/widget/input/chatModelConfigurationStore.ts \
  src/vs/workbench/contrib/chat/browser/widget/input/modelPicker/modelPickerAutoRow.ts \
  src/vs/workbench/contrib/chat/common/languageModels.ts \
  src/vs/workbench/contrib/chat/test/browser/widget/input/chatManagedAutoTier.test.ts \
  src/vs/workbench/contrib/chat/test/browser/agentSessions/agentHostChatContribution.test.ts

Execution denied; not retried through an alternate runner:

node test/unit/browser/index.js --browser chromium \
  --runGlob '**/{chatManagedAutoTier,chatModelConfigurationStore,modelPickerAutoRow,chatInputModelSelectionController}.test.js' \
  --reporter dot
node test/unit/node/index.js \
  --run vs/platform/policy/test/common/copilotManagedSettings.test \
  --run vs/platform/agentHost/test/node/copilotSessionLauncher.test \
  --grep 'Copilot managed settings projection|CopilotSessionLauncher auto tier'

npm run typecheck-client reports 374 diagnostics, including missing generated Electron typings, Electron-derived types, and sparse theme assets. There are no diagnostics in the nine changed files, but this is not a passing full typecheck. The supported prerequisite-restoration command was denied; no bypass was attempted.

Dependencies were restored only after a missing-module failure, using npm ci --ignore-scripts --registry=https://packagefeedproxy.microsoft.io/npm --no-audit --no-fund in the root and build. No dependency manifests were changed.

Refs #336829. Keep the experimental contract isolated and preserve explicit tier choices without persisting managed defaults.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings September 18, 2026 20:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Policy export, accessibility, restoration, and live picker-update issues remain unresolved.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 High severity · 2 Medium severity

Open (3)
What changed in this PR

Prototypes a managed Auto-tier default across policy projection, chat configuration, picker UX, and Agent Host requests.

Changes:

  • Adds the provisional autoTier managed-setting contract.
  • Applies transient managed defaults without persisting them as user choices.
  • Adds store, picker, projection, and Agent Host tests.
File Description
copilotManagedSettings.ts Defines managed tier keys.
copilotManagedSettings.test.ts Tests managed-setting projection.
chat.shared.contribution.ts Registers the policy-backed setting.
languageModels.ts Exposes managed-default provenance.
chatModelConfigurationStore.ts Implements default overlay and lifecycle.
chatInputPart.ts Excludes defaults from drafts.
modelPickerAutoRow.ts Displays organization provenance.
chatManagedAutoTier.test.ts Covers store and picker behavior.
agentHostChatContribution.test.ts Tests Agent Host forwarding.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

scope: ConfigurationScope.APPLICATION,
included: false,
description: nls.localize('chat.defaultAutoTier', "Experimental enterprise default for Auto's Optimize for preference. Users can still select a different preference."),
policy: {
Comment on lines +59 to +64
this._register(configurationService.onDidChangeConfiguration(event => {
if (event.affectsConfiguration(COPILOT_AUTO_TIER_CONFIG)) {
this._autoTierWarnings.clear();
for (const modelId of this._overrides.keys()) {
this._onDidChange.fire(modelId);
}
Comment on lines +124 to +127
const managedDefault = tier && this._options.configurationAccess.isModelConfigurationDefaultManaged?.(this._options.autoModel.identifier, tier.key)
? localize('chat.modelPicker.autoTierManagedDefault', "Organization default. You can choose another preference.")
: undefined;
const parts = [detail, tierDescription, managedDefault].filter(part => !!part);
@github-actions

Copy link
Copy Markdown
Contributor

Screenshot Changes

Base: 6b0c54ee Current: c8938034

Changed (1)

sessions/connectionDiagnostics/connectionDiagnostics/DesktopDismissedDiscovery/Light
Before After
before after

2 insignificant change(s) omitted (≤20 px, Δ≤2). See CI logs for details.

@rwoll

Copy link
Copy Markdown
Member Author

This draft explored the rough shape of the change, but the configuration schema is still being finalized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants