Skip to content

Auto mode: use the router's chosen_model instead of candidate_models[0]#324095

Merged
aashna merged 2 commits into
mainfrom
aashnagarg/fix-auto-intent-chosen-model
Jul 2, 2026
Merged

Auto mode: use the router's chosen_model instead of candidate_models[0]#324095
aashna merged 2 commits into
mainfrom
aashnagarg/fix-auto-intent-chosen-model

Conversation

@aashna

@aashna aashna commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Auto mode was picking the wrong model. When resolving the auto pseudo-model, we took candidate_models[0] from the router response and ignored chosen_model entirely. chosen_model is the router's actual pick after any server-side re-ranking (the Cost Sorting experiment being the one that bit us). The integrator contract is explicit about this:

Use chosen_model for the upcoming chat call, and use candidate_models as the ordered fallback list.

auto-intent-service integrator docs. The Copilot CLI already does this; VS Code was the odd one out.

This showed up as two separate-looking bugs that are really the same root cause:

  1. We sent a different model than the router chose. In the report, /models/session/intent returned GPT-5.4 mini but the chat completion actually went to GPT-5.3 Codex.
  2. The "Routed to …" label didn't match the response footer. The explainability label read the router's pick (GPT-5.4 mini) while the credits footer showed what actually served the request (GPT-5.3 Codex). Once selection reads chosen_model, the label, the request, and the footer all line up.

There's a knock-on effect too: because the Cost Sorting experiment only re-ranks chosen_model, anything reading candidate_models[0] was effectively invisible to it. That matches what we saw — the experiment moved the CLI but not VS Code.

What changed

In _tryRouterSelection (automodeService.ts):

  • Resolve chosen_model against the client's known endpoints first.
  • Only fall back to walking candidate_models when chosen_model is missing or we don't have an endpoint for it.
  • Emit chosen_model as candidateModel in the automode.routerModelSelection telemetry, so the "router pick vs actual model" comparison is actually meaningful.

Why the tests didn't catch it

Every mocked router response in the spec set chosen_model === candidate_models[0], so reading the wrong field gave the right answer by accident. The new tests decouple them:

  • should prefer chosen_model over candidate_models[0] — resolved endpoint follows chosen_model when the two differ.
  • should surface chosen_model in the routing decision the UI displays — the decision the "Routed to" label consumes matches the served endpoint (guards bug gulp-symdest does not preserve links on electron #2).
  • should emit candidateModel from chosen_model, not candidate_models[0] — pins the telemetry field.
  • Reworked the old iterate all candidate_models test into should fall back to candidate_models when chosen_model has no endpoint so it actually exercises the fallback path.

I confirmed the new tests fail on the pre-fix code (resolving gpt-5.3-codex instead of gpt-5.4-mini) and pass after the fix.

Test plan

  • vitest run automodeService.spec.ts — 37 passing
  • Verified the decoupled tests fail on the old code, reproducing the reported GPT-5.4 mini → GPT-5.3 Codex mismatch

Auto mode resolved the pseudo-model by picking candidate_models[0] (the
pre-experiment ranked list) and never consumed chosen_model, the router's
authoritative pick after server-side re-ranking (e.g. Cost Sorting). Per the
auto-intent-service contract (docs/integrators_onboarding.md), clients must
"use chosen_model for the upcoming chat call, and use candidate_models as the
ordered fallback list". The CLI already does this; VS Code did not, so VS Code
was invisible to the Cost Sorting experiment and sent a different model than
Auto Intent chose (e.g. router chose GPT 5.4 Mini, VS Code sent GPT 5.3 Codex).

Prefer chosen_model (resolved against known endpoints) and fall back to the
ordered candidate_models list only when chosen_model is absent or unresolvable.
Also report chosen_model as candidateModel in the automode.routerModelSelection
telemetry so router-pick vs actual comparisons are meaningful.

Existing tests hid the bug because every fixture set
chosen_model === candidate_models[0]. Added regression tests that decouple the
two fields.
Copilot AI review requested due to automatic review settings July 2, 2026 18:14

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.

Pull request overview

This PR fixes VS Code Copilot “Auto mode” routing to honor the router’s authoritative chosen_model (including post-ranking/experiment adjustments) instead of incorrectly using candidate_models[0], aligning behavior with the auto-intent-service integrator contract and the Copilot CLI.

Changes:

  • Update router selection logic to resolve chosen_model against knownEndpoints, falling back to the ordered candidate_models list only when needed.
  • Update routing telemetry (automode.routerModelSelection) so candidateModel reflects the router’s chosen_model.
  • Add regression tests that decouple chosen_model from candidate_models[0] and validate both selection and telemetry.
Show a summary per file
File Description
extensions/copilot/src/platform/endpoint/node/automodeService.ts Prefer router chosen_model for endpoint resolution; fall back to candidate_models when chosen_model can’t be resolved; emit telemetry using the router’s authoritative pick.
extensions/copilot/src/platform/endpoint/node/test/automodeService.spec.ts Add/adjust tests to ensure selection prefers chosen_model and telemetry reports candidateModel from chosen_model, plus a real fallback-path test.

Review details

  • Files reviewed: 2/2 changed files
  • Comments generated: 0
  • Review effort level: Low

Add a regression test asserting the routing decision surfaced to the UI (consumeLastRoutingDecision, which drives the 'Routed to <model>' explainability label) resolves to chosen_model, matching the served endpoint shown in the response footer. This locks in that the top label and bottom footer cannot diverge.
@aashna aashna changed the title Auto mode: send router's chosen_model, not candidate_models[0] Auto mode: use the router's chosen_model instead of candidate_models[0] Jul 2, 2026
@aashna
aashna marked this pull request as ready for review July 2, 2026 18:39
@aashna
aashna requested a review from bhavyaus July 2, 2026 18:48
@aashna
aashna enabled auto-merge July 2, 2026 18:48
@aashna
aashna merged commit 9bd6af9 into main Jul 2, 2026
29 checks passed
@aashna
aashna deleted the aashnagarg/fix-auto-intent-chosen-model branch July 2, 2026 20:14
@vs-code-engineering vs-code-engineering Bot added this to the 1.128.0 milestone Jul 2, 2026
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.

4 participants