Skip to content

desktop: custom provider models missing from /models dialog #50726

Closed

Description

@pavligd

Description

Summary

Custom OpenAI-compatible provider models are served by the server (model.list returns all 22, enabled: true) and work for inference (opencode run --model polza/... succeeds), but the desktop /models dialog does not list any of them — neither by browsing the full list nor by filtering with the provider name or model names.

Environment

  • opencode version: 2.0.14 (desktop + bundled CLI, resources/opencode-cli.version)
  • OS: Windows 10 Pro 10.0.19045 x64
  • Terminal: OpenCode Desktop app (Electron TUI)
  • Shell: PowerShell (irrelevant — issue is in the desktop models dialog)
  • Install/channel: latest (release channel per app-update.yml)
  • Active plugins: none (no plugins in config, no .opencode/plugin* dirs)

Reproduction

  1. Add a custom OpenAI-compatible provider with explicitly listed models to the global opencode.json:
    {
      "model": "polza/gigachat-2-pro",
      "providers": {
        "polza": {
          "name": "Polza",
          "package": "@opencode/ai/providers/openai-compatible",
          "settings": {
            "baseURL": "https://polza.ai/api/v1",
            "apiKey": "<redacted>"
          },
          "models": {
            "gigachat-2-pro": { "modelID": "sber/gigachat-2-pro", "name": "GigaChat 2 Pro" }
            // ... 22 models total
          }
        }
      }
    }
  2. Restart the desktop app (also tried: full OS reboot + deleting Electron Cache, Code Cache, GPUCache, Session Storage).
  3. Open /models, scroll the whole list or filter by polza, gigachat, qwen, grok, luna.

Expected Behavior

A Polza group (or the configured models) appears in /models and is selectable, since the server reports them as available and enabled.

Actual Behavior

No polza/* models appear in /models at all. Other (catalog) models are listed normally.

Additional Context

  • opencode api provider.list → polza present, activation: "enabled", correct package/settings.
  • opencode api model.list → 96 models total, all 22 polza/* present with enabled: true (e.g. polza/gigachat-2-pro, polza/qwen3.8-flash).
  • opencode run '...' --model polza/qwen3.8-flash → succeeds, model responds. API key and endpoint are functional.
  • Default "model": "polza/gigachat-2-pro" in config does not surface the models in the dialog either.
  • Frequency: consistent, survives app restart, OS reboot, and Electron cache purge.
  • Related: config hot-reload works (provider.updated events in opencode.log), no provider load errors in logs.
  • Workaround: switch models by editing "model" in opencode.json manually, or one-shot via opencode run --model polza/<id>.

Plugins

No response

OpenCode version

No response

Steps to reproduce

No response

Screenshot and/or share link

No response

Operating System

Windows 10

Terminal

No response

Activity

  1. github-actions commented on Sep 22, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    If your issue is distinct from these, please mention how it differs.

  2. pavligd commented on Sep 22, 2026

    @pavligd
    Author

    Update: found a workaround.

    In the providers UI I disabled the Personal / OpenCode group, clicked around, then re-enabled it — after that the Polza group appeared in /models and the custom models became selectable.

    So the data was always there (server-side model.list returned all 22 polza/* models with enabled: true all along); the /models dialog just never refreshed its list — not on config hot-reload (provider.updated events fire, I verified in opencode.log), not on app restart, OS reboot, or Electron cache purge. Toggling an unrelated provider forced the refresh.

    Looks like the dialog caches the model list on first open and doesn't invalidate it when providers/models update.

  3. opencodejr commented on Oct 28, 2026

    @opencodejr

    Thanks for the detailed report! I was able to reproduce this on 2.0.14, and it still happens on the newest release, 2.2.0. I couldn't run the latest dev from source in my sandbox, so 2.2.0 is the newest version I checked.

    What I did:

    • Added a custom polza provider using @opencode/ai/providers/openai-compatible, with two models (name + modelID, no releaseDate) and "model": "polza/gigachat-2-pro", like your config.
    • Started opencode serve: /api/model lists both polza/* models with enabled: true.
    • Opened the app (the same UI the desktop app wraps), started a new session and opened the model picker. The composer shows GigaChat 2 Pro as the selected model, but the picker only lists the OpenCode group, and searching polza, gigachat or qwen gives "No model results". The screenshots below show this on both versions, and the script below automates it.

    A likely cause, not confirmed yet: models declared in config without a release date get a release time of 0, which the app reads as 1970-01-01. The picker hides models with a release date older than six months by default (unless they are the newest in their model family), and its search only covers visible models. That would hide these models in both places.

    Until this is fixed, your workarounds (setting "model" in the config, or using opencode run --model) should keep working, and turning these models on in Manage models may also help.

    Related: #59840 reports the same symptom on macOS with 2.2.0.

    Screenshot

    Screenshot

    Screenshot

    Screenshot

    Reproduction script (web.mjs)
    // Reproduces #50726 in the desktop/web app UI served by `opencode serve`.
    // Setup: global opencode.json with a custom openai-compatible provider "polza"
    // (models with name + modelID, no releaseDate), then `opencode serve --port 4590`.
    // Config used (~/.config/opencode/opencode.json; baseURL/apiKey are dummies, no request is made):
    //   { "model": "polza/gigachat-2-pro",
    //     "providers": { "polza": { "name": "Polza", "package": "@opencode/ai/providers/openai-compatible",
    //       "settings": { "baseURL": "http://127.0.0.1:9/v1", "apiKey": "x" },
    //       "models": { "gigachat-2-pro": { "modelID": "sber/gigachat-2-pro", "name": "GigaChat 2 Pro" },
    //                   "qwen3.8-flash":  { "modelID": "qwen/qwen3.8-flash",  "name": "Qwen 3.8 Flash" } } } } }
    // Needs: npm i playwright && npx playwright install chromium
    // Run:   URL=http://127.0.0.1:4590 PASS=<server password> node web.mjs
    import { chromium } from "playwright"
    const out = process.env.OUT ?? "/workspace/repro"
    const browser = await chromium.launch()
    const page = await browser.newPage({ httpCredentials: { username: "opencode", password: process.env.PASS }, viewport: { width: 1400, height: 900 } })
    await page.goto(process.env.URL)
    await page.waitForTimeout(4000)
    // Newer releases (2.2.x) first show a "Connect to a server" screen
    if (await page.getByRole("button", { name: "Use password" }).count()) {
      await page.getByRole("button", { name: "Use password" }).click()
      await page.locator('input[type="password"]').fill(process.env.PASS)
      await page.getByRole("button", { name: "Connect" }).click()
      await page.waitForTimeout(5000)
    }
    await page.getByText("Add project").first().click()
    await page.waitForTimeout(1500)
    await page.getByRole("button", { name: "Select folder" }).click()
    await page.waitForTimeout(4000)
    await page.getByRole("button", { name: "New session" }).last().click()
    await page.waitForTimeout(4000)
    await page.screenshot({ path: `${out}/04-draft.png` })
    // Open the model picker from the composer (the selected model is the configured default polza/gigachat-2-pro)
    await page.getByRole("button", { name: "GigaChat 2 Pro" }).click()
    await page.waitForTimeout(2500)
    await page.screenshot({ path: `${out}/05-picker.png` })
    const picker = page.locator("body")
    console.log("--- picker (no filter) ---\n" + (await page.locator("body").innerText()).slice(0, 3000))
    const search = page.getByPlaceholder("Search models")
    for (const q of ["polza", "gigachat", "qwen"]) {
      await search.fill(q)
      await page.waitForTimeout(1500)
      await page.screenshot({ path: `${out}/06-search-${q}.png` })
      console.log(`--- search "${q}" ---\n` + (await picker.innerText()).slice(0, 800))
    }
    await browser.close()

    Run it: bun web.mjs

  4. saeedyaqoob commented on Oct 28, 2026

    @saeedyaqoob

    Same bug, but on the built-in Ollama provider (auto-discovered, not config-declared), which extends the scope beyond custom providers.

    Environment

    • opencode 2.2.0 (desktop app), Windows 11 10.0.26300.9711 x64
    • Ollama running at http://127.0.0.1:11434 with one model pulled: qwen2.5-coder:3b
    • No plugins

    What I see

    • GET /api/model returns ollama/qwen2.5-coder:3b with enabled: true, status: "active", capabilities.tools: true, limit.context: 32768.
    • GET /api/provider returns ollama with activation: "enabled".
    • The desktop /models dialog does not list it, and searching qwen or ollama in the picker returns no results.
    • Not location-specific: the same snapshot is returned for the home directory and two project directories (9 models each: 8 opencode/* plus the Ollama one).

    Confirms the release-date hypothesis

    The discovered model's time is {"released": 0} → 1970-01-01.

    Adding an explicit release date in config:

    "providers": {
      "ollama": {
        "models": {
          "qwen2.5-coder:3b": { "releaseDate": "2026-10-28" }
        }
      }
    }

    changes /api/model to time: {"released": 1793145600000} (2026-10-28), while settings.baseURL, capabilities.tools and limit.context are preserved.

    So models discovered from a local provider with released: 0 are affected too, not only config-declared ones. Setting releaseDate is a usable workaround in the meantime.

    Possibly related

    The ollama entry in /api/provider has no integrationID, while opencode has "integrationID": "opencode". Not sure whether the picker's provider grouping relies on it.

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions