Skip to content

GitHub Copilot provider shows zero models: all models return model_picker_enabled: false #42083

Description

@Keylessboi

Summary

On opencode 1.18.15 (Arch package), the github-copilot provider never appears in the model picker. opencode auth login -p github-copilot works (auth succeeds), but opencode models github-copilot returns "Provider not found", and /models in the TUI shows no Copilot models.

Root cause

In packages/opencode/src/plugin/github-copilot/copilot.ts, the models() hook returns only models where result.pickerEnabled.has(model.api.id):

return CopilotModels.get(...)
  .then((result) => {
    models = result.models
    return Object.fromEntries(
      Object.entries(result.models).filter(([, model]) => result.pickerEnabled.has(model.api.id)),
    )
  })

pickerEnabled (built in models.ts:257) is the set of models with model_picker_enabled: true in the API response:

pickerEnabled: new Set([...remote].filter(([, item]) => item.model_picker_enabled).map(([id]) => id)),

GitHub's GET https://api.githubcopilot.com/models currently returns model_picker_enabled: false for every single model — even ones that are policy.state: "enabled" and fully usable. So pickerEnabled is always empty, the filter drops everything, and the provider surfaces zero models.

Evidence

Using a valid, freshly-authenticated Copilot OAuth token (device flow, client_id=Ov23li8tweQw6odWQebz):

HTTP 200, total models: 47
policy states:  disabled: 18 | none: 23 (internal: copilot-search-*, exec-agent-*) | enabled: 6
model_picker_enabled=true: 0

The 6 policy.state: "enabled" models (gpt-4o, gpt-5-mini, claude-haiku-4.5, gpt-4.1, mai-code-1-flash, mai-code-1.1-flash) pass the existing usable() check (models.ts:207), and chat completions against them work fine:

POST https://api.githubcopilot.com/chat/completions → 200, "Hi there! ..."

So the account/subscription is fine — the filter is the problem. Note: exchanging the OAuth token for a Copilot session token via api.github.com/copilot_internal/v2/token and using that against /models returns 403, so the session-token route is not a workaround either.

Suggested fix

Filter by the already-existing usable() predicate (policy.state !== "disabled" + has max_output_tokens/max_prompt_tokens + has tool_calls) instead of, or in addition to, model_picker_enabled. Either:

  • Return result.models (already filtered by usable() inside CopilotModels.get) without the pickerEnabled filter, or
  • Union pickerEnabled with the usable set.

model_picker_enabled appears to be a deprecated/no-longer-reliable signal from GitHub's API.

Workaround

A local plugin overriding the provider's models() hook to return all usable models (same usable() criteria, no picker filter) restores all 25 available Copilot models:

// ~/.config/opencode/plugins/copilot-picker-fix.js
export const CopilotPickerFix = async () => ({
  provider: {
    id: "github-copilot",
    async models(provider, ctx) {
      if (ctx.auth?.type !== "oauth") return provider.models
      const base = ctx.auth.enterpriseUrl
        ? `https://copilot-api.${ctx.auth.enterpriseUrl.replace(/^https?:\/\//, "").replace(/\/$/, "")}`
        : "https://api.githubcopilot.com"
      const r = await fetch(`${base}/models`, {
        headers: { Authorization: `Bearer ${ctx.auth.refresh}`, "User-Agent": "opencode/1.18.15", "X-GitHub-Api-Version": "2026-06-01" },
        signal: AbortSignal.timeout(5000),
      })
      if (!r.ok) return provider.models
      const j = await r.json()
      const models = {}
      for (const m of j.data || []) {
        if (m.policy?.state === "disabled") continue
        const lim = m.capabilities?.limits
        if (!lim?.max_output_tokens || !lim?.max_prompt_tokens) continue
        if (m.capabilities?.supports?.tool_calls === undefined) continue
        const isMsg = m.supported_endpoints?.includes("/v1/messages")
        models[m.id] = {
          id: m.id, providerID: "github-copilot",
          api: { id: m.id, url: isMsg ? `${base}/v1` : base, npm: isMsg ? "@ai-sdk/anthropic" : "@ai-sdk/github-copilot" },
          status: "active",
          limit: { context: lim.max_context_window_tokens ?? lim.max_prompt_tokens, input: lim.max_prompt_tokens, output: lim.max_output_tokens },
          capabilities: { temperature: true, reasoning: true, attachment: true, toolcall: m.capabilities.supports.tool_calls, input: { text: true, audio: false, image: !!m.capabilities.supports.vision, video: false, pdf: false }, output: { text: true, audio: false, image: false, video: false, pdf: false }, interleaved: false },
          family: m.capabilities.family, name: m.name, cost: { input: 0, output: 0, cache: { read: 0, write: 0 } }, options: {}, headers: {},
          release_date: m.version.startsWith(`${m.id}-`) ? m.version.slice(m.id.length + 1) : m.version,
        }
      }
      return models
    },
  },
})

Environment

  • opencode 1.18.15-1 (Arch Linux package)
  • GitHub Copilot subscription: active (chat completions return 200)
  • OAuth apps tested: opencode's own (Ov23li8tweQw6odWQebz) and the VSCode Copilot app (Iv1.b507a08c87ecfe98) — same result either way

Activity

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions