Skip to content

OpenCode: catalog-placed providers, reasoning levels, session commands, titles and cost - #96

Merged
deymosh merged 5 commits into
masterfrom
feat/opencode-sessions-and-models
Oct 8, 2026
Merged

deymosh merged 5 commits into
masterfrom
feat/opencode-sessions-and-models

Conversation

@deymosh

@deymosh deymosh commented Oct 8, 2026 •

Copy link
Copy Markdown
Owner

Summary

Builds on #95 (based on its branch; GitHub retargets this to master once #95 merges).

Providers, through OpenCode's own catalog (models.dev)

  • A profile whose endpoint OpenCode's catalog knows (DeepSeek's API, OpenRouter's…) signs in to that provider, as /connect would: the catalog's models, prices and limits under the profile's name, plus any model the endpoint lists that the catalog lacks. One OpenCode already uses with its own key is left out rather than replaced.
  • Any other endpoint (a gateway) stays a provider of its own, its models filled in from the catalog where it knows them: limits, tool calls, image input and reasoning. Prices are never copied, a gateway's being its own.

Reasoning levels per model

  • ModelEntry.efforts (phone wire, corpus fixture): a model's own levels for an agent whose levels differ by model; such an agent lists none of its own, and the bridge leaves checking a level to it.
  • OpenCode lists each model's variants (default first), checks a chosen level against the session's model, and asks for it on every prompt and command. The phone offers the model's levels in the controls bar and the new-session form.

Sessions

  • /compact, /undo, /redo, /share, /unshare run through OpenCode's API instead of reaching the model as text; outcomes are status lines.
  • OpenCode names its sessions: they are created untitled, and the driver-protocol info event gains title, which wins over the first-message title and the session-meta topic.
  • Session cost: OpenCode reports it as usage; the controls bar shows any agent's session cost as a pill and re-asks after each turn. The model chip shows the model list's name (deepseek-v4.1-flash, not ccr/OpenCode Go/deepseek-v4.1-flash).

Not done on purpose: sending images as native file parts. The agents already read an attached image with their read tool, which returns it to any model that takes images, and catalog-filled gateway models now say they do; native parts would save one tool call at the cost of an attachment field through the bridge and every driver.

Test plan

  • cargo clippy + test (workspace), agent host typecheck + test + build, driver-protocol spawn test, bridge end-to-end test
  • driver-protocol TS types and UniFFI Kotlin bindings regenerated
  • Android unit tests, Paparazzi (new and changed snapshots reviewed), lint
  • Live on OpenCode 1.18.32: the catalog lists base URLs for 206 of 227 providers; a gateway model filled in from it is offered low/medium/high/max and image input with its real limits; /command lists only init and review of the built-ins
  • Live on OpenCode 1.18.32, one real turn on a free Zen model: an untitled session gets OpenCode's own title; revert marks the user turn the driver picks and keeps the messages listed; unrevert clears it; summarize succeeds

🤖 Generated with Claude Code

deymosh and others added 5 commits October 8, 2026 19:59
These commands are run by OpenCode's terminal itself, so its server does
not list them: typed on the phone they reached the model as plain text.
The driver now runs them through the server's API — summarize, revert and
unrevert, share and unshare — lists them in the command menu, and reports
each outcome as a status line. Undo takes back the last turn not yet
undone, and the line says the transcript keeps it until the next message;
a command a project defines under the same name still wins.

Co-Authored-By: Claude Code <noreply@anthropic.com>
The driver created every OpenCode session titled with the bridge's session
id, which stops OpenCode from naming it after its first message. Sessions
are now created untitled, and the title OpenCode gives one reaches the
bridge in the session's info (a new `title` field): it wins over the
title the bridge takes from the first message and over the session-meta
topic it asks the agent for, which still sets the project.

Co-Authored-By: Claude Code <noreply@anthropic.com>
OpenCode reports what a session has cost, as it prices its models, so its
catalog entry now says it has usage: the cost, with no subscription
windows. The controls bar shows a session's cost as a pill whenever the
agent reports one above zero (Claude Code's too, which was never shown),
and the phone asks for usage again each time a turn ends, so the figure
follows the session.

The model chip ran every id through the Claude tag table, which passes
anything else through whole: an OpenCode or gateway session read
"ccr/OpenCode Go/deepseek-v4.1-flash". It now shows the name the agent's
model list (or a provider profile's) gives the model, as the picker does;
the session screen asks for that list on open.

Co-Authored-By: Claude Code <noreply@anthropic.com>
OpenCode ships the models.dev catalog of providers and models, and its
server lists it with the base URL each provider is served at. A profile
is now placed by it:

- an endpoint the catalog knows (DeepSeek's API, OpenRouter's) signs in
  to that provider, as /connect would: the catalog's models, prices and
  limits under the name the user gave the profile, plus any model the
  endpoint lists that the catalog lacks. One OpenCode already uses with
  a key of its own is left out rather than replaced;
- any other endpoint stays a provider of its own, its models filled in
  from the catalog where it knows them (a routed "OpenCode Go/..." model
  is OpenCode Go's): limits, tool calls, image input and reasoning, which
  gives it OpenCode's reasoning levels. Prices are not copied, a
  gateway's being its own.

Checked on 1.18.32: a gateway model filled in so is offered the low,
medium, high and max levels and image input, with its real limits.

Co-Authored-By: Claude Code <noreply@anthropic.com>
OpenCode gives a model reasoning levels ("variants": low, high, max…)
that differ from model to model, so the agent-wide effort list could not
hold them and OpenCode sessions had no effort control at all. A model
entry now carries its own levels (`efforts`, with a corpus fixture); an
agent that lists no levels of its own has them per model, and the bridge
leaves checking one to the agent. The OpenCode driver lists each model's
variants with its default first, checks a chosen level against the
session's model, drops it when the model changes to one without it, and
asks for it on every prompt and command. The phone offers the session
model's levels in the controls bar and the new-session form.

Co-Authored-By: Claude Code <noreply@anthropic.com>
@deymosh
deymosh changed the base branch from feat/opencode-full-support to master October 8, 2026 18:34
@deymosh
deymosh merged commit 1a2ddc5 into master Oct 8, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant