Skip to content

fix(providers): route Copilot enterprise tokens via proxy endpoint#358

Open
lijunle wants to merge 2 commits intomoltis-org:mainfrom
lijunle:fix/copilot-enterprise-proxy-endpoint
Open

fix(providers): route Copilot enterprise tokens via proxy endpoint#358
lijunle wants to merge 2 commits intomoltis-org:mainfrom
lijunle:fix/copilot-enterprise-proxy-endpoint

Conversation

@lijunle
Copy link
Copy Markdown
Contributor

@lijunle lijunle commented Mar 8, 2026

Summary

Route GitHub Copilot enterprise tokens through the proxy endpoint returned in the token exchange response, fixing HTTP 421 errors for enterprise accounts.

  • Parse endpoints.api from the Copilot token exchange response and persist it alongside the cached API token
  • Route all API calls (models, chat completions) through the enterprise proxy endpoint when present
  • Force streaming for complete() on enterprise proxy (non-streaming returns 400), reusing the existing stream_with_tools() path and collecting the SSE stream into a CompletionResponse
  • Individual (non-enterprise) tokens continue using api.individual.githubcopilot.com unchanged

Closes #352

Validation

Completed

  • cargo +nightly-2025-11-30 fmt --all -- --check
  • cargo check -p moltis-providers -p moltis-gateway
  • cargo test -p moltis-providers --features provider-github-copilot -- copilot
  • No warnings

Remaining

  • ./scripts/local-validate.sh
  • Manual QA with an enterprise Copilot account

Manual QA

  1. Authenticate Moltis with a Copilot Enterprise account
  2. Verify model listing works (GET {proxy-ep}/models returns 200)
  3. Send a chat message — verify streaming works
  4. Verify complete() path works (tool-calling flows use this)
  5. Authenticate with an individual Copilot account — verify existing behavior unchanged

…oltis-org#352)

The Copilot token exchange response includes an `endpoints.api` field
that specifies the correct API base URL. Enterprise tokens point at
the enterprise proxy (e.g. proxy.enterprise.githubcopilot.com) rather
than the individual endpoint (api.individual.githubcopilot.com).

Changes:
- Parse `endpoints.api` from CopilotTokenResponse
- Persist the resolved API base URL alongside the cached Copilot token
- Use the dynamic endpoint for models, complete, and streaming requests
- Detect enterprise proxy in complete() and delegate to streaming,
  since the enterprise proxy rejects non-streaming requests (HTTP 400)
- Add collect_stream_response() helper to assemble streamed events
  into a CompletionResponse for the non-streaming code path
- Add tests for endpoint parsing, stream collection, and error propagation

Closes moltis-org#352

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@lijunle
Copy link
Copy Markdown
Contributor Author

lijunle commented Mar 10, 2026

Hi @penso Could you check on this fix? I confirmed this working with my github account.

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.

[Model]: Copilot enterprise tokens return 421 unless using proxy endpoint + streaming

1 participant