Skip to content

setup always reports providers: [] — /provider response shape mismatch #6

Description

@azdolinski

Summary
opencode-companion.mjs setup (and setup --json) always returns an empty providers array, even when OpenCode has providers configured and connected. The handler assumes the GET /provider endpoint returns an array, but current OpenCode returns an object { all, default, connected }. The Array.isArray() guard is therefore always false and providers is never populated.

Environment
Plugin: tasict-opencode-plugin-cc, opencode companion 1.0.0
OpenCode CLI: 1.17.0
OpenCode server API: 1.16.2 / 1.17.0 (both return the object shape)
Node: v20+
OS: Linux
Affected code
scripts/opencode-companion.mjs → handleSetup() (provider detection block), which calls client.listProviders() defined in scripts/lib/opencode-server.mjs:170 as request("GET", "/provider").

Root cause
GET /provider returns:

{
  "all":       [ { "id": "...", "name": "...", "models": {...} }, ... ],  // full catalog of known providers
  "default":   { "<providerId>": "<defaultModel>", ... },
  "connected": [ "zai-coding-plan", "opencode" ]                          // providers with credentials configured
}

The companion expects a bare array:

const providerList = await client.listProviders();
if (Array.isArray(providerList)) {                 // ← false: response is an object
  providers = providerList.map((p) => p.id ?? p.name).filter(Boolean);
}

Because the response is an object, the branch never executes and providers stays [] regardless of configuration. The list of actually configured/authenticated providers lives in connected.

Steps to reproduce
Configure a provider (e.g. opencode auth login → Z.AI Coding Plan), confirm with opencode providers list / opencode models.
Run node scripts/opencode-companion.mjs setup --json.
Observe "providers": [].
Compare with curl -s http://127.0.0.1:4096/provider → connected clearly lists the configured provider(s).
Expected vs actual
Expected: providers reflects the configured/connected providers (e.g. ["zai-coding-plan", "opencode"]).
Actual: providers is always [].
Proposed fix
Handle the object shape and read from connected (fall back to all for forward/backward compatibility, and keep the array branch for older servers):

         const providerList = await client.listProviders();
         if (Array.isArray(providerList)) {
           providers = providerList.map((p) => p.id ?? p.name).filter(Boolean);
-        }
+        } else if (providerList && typeof providerList === "object") {
+          // Newer OpenCode returns { all, default, connected }; the providers
+          // with credentials configured live in `connected`.
+          if (Array.isArray(providerList.connected)) {
+            providers = providerList.connected;
+          } else if (Array.isArray(providerList.all)) {
+            providers = providerList.all.map((p) => p.id ?? p.name).filter(Boolean);
+          }
+        }

After the fix, setup --json correctly reports:

{ "installed": true, "version": "1.17.0", "serverRunning": true, "providers": ["zai-coding-plan", "opencode"], "reviewGate": false }

Additional note (not a plugin bug, but interacts with this)
The companion talks to a hardcoded server at http://127.0.0.1:4096. A long‑lived opencode serve --port 4096 started before new credentials were added will keep reporting a stale connected list (in my case it omitted zai-coding-plan and showed a normalized zai instead). Restarting that server makes it re‑read auth.json and report correctly. Consider either (a) detecting/refreshing a stale server, or (b) documenting that the 4096 server must be restarted after changing OpenCode auth — otherwise the corrected setup output can still look wrong purely due to a stale server process.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions