anomalyco / anomalyco/opencode
GitHub Copilot provider shows zero models: all models return `model_picker_enabled: false`
@nexxeln is already working on this.
Since Aug 12, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
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 byusable()insideCopilotModels.get) without thepickerEnabledfilter, or - Union
pickerEnabledwith 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
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.