Skip to content

GitHub Copilot preview models rejected — auth plugin sends raw OAuth token instead of exchanging for Copilot session token #19338

@ben-vargas

Description

@ben-vargas

Description

Preview models on the GitHub Copilot API (e.g. claude-opus-4.6-fast) fail with 400 model_not_supported when used through opencode, despite being valid and available on the Copilot API.

There are three interconnected issues in the copilot auth plugin (src/plugin/copilot.ts):

1. Wrong OAuth App for device flow

The plugin uses OAuth App client ID Ov23li8tweQw6odWQebz, which produces gho_ tokens. The Copilot session token exchange endpoint (/copilot_internal/v2/token) only accepts GitHub App user tokens (ghu_). The correct client ID is Iv1.b507a08c87ecfe98 (the GitHub Copilot CLI GitHub App), which other Copilot integrations use.

2. No session token exchange

The raw GitHub token is sent directly as the Authorization: Bearer header (line 126). This works for GA models but the Copilot API rejects preview models unless a proper Copilot session token (tid=...) is used, obtained via a GET to /copilot_internal/v2/token with Authorization: token <github_token>.

3. Missing Copilot integration headers on API requests

The fetch wrapper doesn't include Editor-Version, Editor-Plugin-Version, or Copilot-Integration-Id headers on API requests. The session token is scoped to the integration specified during the exchange, and the API returns 403 Forbidden: token not authorized for this integration if these headers are missing or mismatched.

Evidence

Tested by hitting the Copilot API endpoint (POST /chat/completions) with different token and header combinations:

Token type Headers claude-opus-4.6 (GA) claude-opus-4.6-fast (preview)
Raw gho_ (OAuth App) No integration headers ✅ 200 ❌ 400 model_not_supported
Raw ghu_ (GitHub App) No integration headers ✅ 200 ❌ 400 model_not_supported
Session token tid=... With integration headers ✅ 200 ✅ 200
Session token tid=... No integration headers ❌ 403 token not authorized ❌ 403 token not authorized

The token exchange endpoint itself:

Token type Auth scheme Result
gho_ (OAuth App) Bearer or token ❌ 404
ghu_ (GitHub App) token ✅ 200

Steps to reproduce

  1. Log in to GitHub Copilot in opencode via the device flow
  2. Add a preview model to opencode.jsonc:
    "provider": {
      "github-copilot": {
        "models": {
          "claude-opus-4.6-fast": {
            "name": "Claude Opus 4.6 (fast mode)",
            "reasoning": true,
            "limit": { "context": 200000, "output": 64000 }
          }
        }
      }
    }
  3. Select claude-opus-4.6-fast as the model
  4. Send any message

Expected: Model responds normally
Actual: The requested model is not supported.

Plugins

No response

OpenCode version

Latest dev branch

Metadata

Metadata

Assignees

Labels

coreAnything pertaining to core functionality of the application (opencode server stuff)

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions