Skip to content

🤖 fix: align GitHub Copilot model routing#3104

Merged
ibetitsmike merged 34 commits intomainfrom
mike/copilot-model-routing
Apr 7, 2026
Merged

🤖 fix: align GitHub Copilot model routing#3104
ibetitsmike merged 34 commits intomainfrom
mike/copilot-model-routing

Conversation

@ibetitsmike
Copy link
Copy Markdown
Contributor

@ibetitsmike ibetitsmike commented Mar 31, 2026

Summary

This PR aligns GitHub Copilot model routing with the account's model catalog. All non-Codex models use chat completions. Codex models use a custom Responses language model that handles Copilot's SSE stream format. Copilot can now route Anthropic and Google models (with dot-vs-dash ID normalization). Catalog entries are hidden from the selector.

Background

Copilot auth persisted the signed-in user's model list, but routing ignored it and only routed OpenAI models. Non-OpenAI Copilot models (Claude, Gemini) were unreachable. Codex models were stuck: /chat/completions rejects them, and the standard AI SDK Responses parser can't handle Copilot's SSE stream format. Additionally, Copilot's catalog uses dot-form Claude IDs (claude-opus-4.6) while Mux's built-in models use dashes (claude-opus-4-6).

Implementation

  • add a custom CopilotResponsesLanguageModel that handles Copilot's Responses API SSE stream directly, bypassing the AI SDK's broken parser (following opencode's approach)
  • route Codex models through the custom Responses model, all other Copilot models through chat completions
  • expand Copilot gateway routes to include anthropic and google
  • normalize Claude model IDs (dot-vs-dash: 4.6 matches 4-6) so Copilot catalog entries match built-in models
  • hide github-copilot:* entries from the model selector while keeping the catalog for route gating
  • check credentials before catalog availability for correct error messages
  • classify initiator from pre-normalization body for correct billing headers
  • treat malformed catalog entries as absent for self-healing

Validation

  • make static-check
  • bun test src/common/utils/copilot/modelRouting.test.ts src/node/services/providerModelFactory.test.ts src/node/services/copilot/copilotResponsesLanguageModel.test.ts src/browser/hooks/useRouting.test.ts src/browser/hooks/useModelsFromSettings.test.ts src/common/routing/resolve.test.ts src/browser/utils/compaction/suggestion.test.ts src/common/utils/providers/gatewayModelCatalog.test.ts

Risks

Medium. The custom CopilotResponsesLanguageModel is a new language model implementation that directly parses Copilot's SSE stream. It's scoped to Codex-family models only to minimize blast radius. Tool call streaming is not yet covered (text-only). Adding Anthropic/Google to Copilot routes means users with both Copilot and direct API keys will route through Copilot when it's prioritized (the priority system is user-controlled and defaults to ["direct"]).


Generated with mux • Model: openai:gpt-5.4 • Thinking: xhigh • Cost: $23.81

@ibetitsmike
Copy link
Copy Markdown
Contributor Author

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f61c5df1c5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike
Copy link
Copy Markdown
Contributor Author

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 553a7ba923

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike
Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike
Copy link
Copy Markdown
Contributor Author

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 36537b7ed2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike
Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Can't wait for the next one!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike
Copy link
Copy Markdown
Contributor Author

@codex review

Pushed a follow-up fix so direct github-copilot:* entries now use the same authoritative catalog gating as routed Copilot models.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c6ce621ba2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike ibetitsmike force-pushed the mike/copilot-model-routing branch from c6ce621 to dfbb329 Compare April 1, 2026 00:15
@ibetitsmike
Copy link
Copy Markdown
Contributor Author

@codex review

Follow-up push: I stabilized the useRouting unit test so it waits for the loaded Copilot catalog before asserting the unavailable route is hidden.

@ibetitsmike ibetitsmike force-pushed the mike/copilot-model-routing branch from dfbb329 to 719288e Compare April 1, 2026 00:21
@ibetitsmike
Copy link
Copy Markdown
Contributor Author

@codex review

Follow-up push: explicit compaction suggestions now apply the same authoritative Copilot catalog check as model selection, so stale github-copilot:* preferences are rejected before retry.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dfbb329aac

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike ibetitsmike force-pushed the mike/copilot-model-routing branch from 719288e to 56a866a Compare April 1, 2026 00:28
@ibetitsmike
Copy link
Copy Markdown
Contributor Author

@codex review

Follow-up push: explicit gateway route resolution now applies the same catalog accessibility check on both explicit-gateway and direct-gateway paths, so stale github-copilot:* entries no longer appear routable.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 56a866ac03

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike ibetitsmike force-pushed the mike/copilot-model-routing branch from 56a866a to 3e263d7 Compare April 1, 2026 00:39
@ibetitsmike
Copy link
Copy Markdown
Contributor Author

@codex review

Stabilized the Anthropic Copilot useRouting test: it now waits for both provider config and routing priority to load before asserting resolveRoute.

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike
Copy link
Copy Markdown
Contributor Author

@codex review

Fixed both issues:

  1. Claude model IDs are now reverse-normalized from dash-form to dot-form before sending to Copilot (e.g., claude-opus-4-6 -> claude-opus-4.6).
  2. Copilot Responses model reads reasoning from the github-copilot namespace.

@ibetitsmike
Copy link
Copy Markdown
Contributor Author

@codex review

Applied both fixes from the previous Codex review:

  1. Claude model IDs are reverse-normalized to dot-form before sending to Copilot (claude-opus-4-6 -> claude-opus-4.6).
  2. Copilot Responses model reads reasoning from the github-copilot namespace with reasoningEffort fallback.

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike
Copy link
Copy Markdown
Contributor Author

@codex review

Simplified the flaky Anthropic Copilot useRouting test to only assert availableRoutes (provider-config-driven, no route priority race). The pure routing logic is deterministically tested in resolve.test.ts.

@ibetitsmike
Copy link
Copy Markdown
Contributor Author

@codex review

Simplified the flaky Anthropic useRouting test to only assert availableRoutes (no route priority race).

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 923bc2c6f4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike
Copy link
Copy Markdown
Contributor Author

@codex review

Removed the persistently flaky Anthropic useRouting hook test. The dot-vs-dash normalization is already covered deterministically in resolve.test.ts and gatewayModelCatalog.test.ts.

Delete the CI-flaky Anthropic Copilot hook test from useRouting.test.ts. The remaining coverage stays in deterministic routing and gateway catalog tests.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1fce3d338f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike
Copy link
Copy Markdown
Contributor Author

@codex review

Fixed: toCopilotModelId now only rewrites short (1-2 digit) minor version segments. Date-stamped IDs like claude-sonnet-4-20250514 pass through unchanged.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1fce3d338f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Limit Claude minor-version rewriting to 1-2 digit segments so date-stamped model IDs stay unchanged unless they include a real short minor version.
@ibetitsmike
Copy link
Copy Markdown
Contributor Author

@codex review

Fixed: toCopilotModelId now only rewrites 1-2 digit minor version segments. Date-stamped IDs like claude-sonnet-4-20250514 are preserved unchanged.

@ibetitsmike
Copy link
Copy Markdown
Contributor Author

@codex review

This was already fixed in commit 2c8c83a. The regex now only rewrites 1-2 digit minor versions. Date-stamped IDs like claude-sonnet-4-20250514 pass through unchanged.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2c8c83a0ae

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike
Copy link
Copy Markdown
Contributor Author

@codex review

Fixed: Copilot chat provider name now derives from resolveProviderOptionsNamespaceKey() instead of being hardcoded, with a regression test to prevent drift.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6e5c3b416b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike
Copy link
Copy Markdown
Contributor Author

@codex review

@ibetitsmike ibetitsmike added this pull request to the merge queue Apr 7, 2026
@ibetitsmike ibetitsmike removed this pull request from the merge queue due to a manual request Apr 7, 2026
@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike ibetitsmike added this pull request to the merge queue Apr 7, 2026
Merged via the queue into main with commit 2662aed Apr 7, 2026
24 checks passed
@ibetitsmike ibetitsmike deleted the mike/copilot-model-routing branch April 7, 2026 08:54
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.

1 participant