Skip to content

feat: add shared model utilities and OpenCode 2 (V2) support - #15

Open
Majidalee1 wants to merge 4 commits into
brent-weatherall:mainfrom
Majidalee1:pr1-refactor/shared-models
Open

feat: add shared model utilities and OpenCode 2 (V2) support#15
Majidalee1 wants to merge 4 commits into
brent-weatherall:mainfrom
Majidalee1:pr1-refactor/shared-models

Conversation

@Majidalee1

@Majidalee1 Majidalee1 commented Aug 7, 2026

Copy link
Copy Markdown

Summary

This PR adds support for OpenCode 2. It also moves model logic into one shared file. The shared file works for OpenCode 1 (V1) and OpenCode 2 (V2).

Problem

OpenCode 2 loads plugins in a new way. A plugin file must export { id, setup }. The current plugin.ts file exports a factory function instead. This function returns { config, auth }. This is the V1 format. OpenCode 2 cannot load this format. It shows this error:

SchemaError: Expected object, got async function commandcodePlugin()

The provider code already works with OpenCode 2. The files index.ts and src/model.ts implement the LanguageModelV3 interface from the AI SDK. The provider only needs a new V2 plugin file to register it.

Changes

1. Shared model utilities

  • Add src/models.ts. This file loads and converts model data from models.json.
  • Add these functions:
    • toConfigKey — creates a short, stable key for each model.
    • toV1ModelConfig — creates a model config for the V1 plugin.
    • toV2ModelDraft and toV2ModelMap — create model entries for the V2 catalog.
  • Update plugin.ts to use the shared functions. The V1 plugin behavior does not change.
  • Add tests in tests/unit/models.test.ts for all functions.

2. OpenCode 2 (V2) plugin entrypoint

  • Add v2.ts. This file exports the V2 plugin as { id, setup }.
  • The V2 plugin registers the commandcode provider through ctx.catalog.transform.
  • The provider ID is aisdk:commandcode-go-opencode-provider. It has a default baseURL.
  • Update package.json:
    • Add a new export path, ./v2.
    • Add v2.ts to the published files.
    • Set the version to 0.5.0.
  • Update tsconfig.json to include v2.ts.
  • Add tests in tests/unit/v2.test.ts. These tests check provider registration, settings overrides, and that all 21 models from models.json register with the correct shape.

3. Documentation

  • Update README.md:
    • Add a new "OpenCode 2 (V2)" section. It explains how to install the plugin: plugins: ["commandcode-go-opencode-provider/v2"].
    • Explain how to set the API key. Use the /connect command or the COMMANDCODE_API_KEY variable.
    • Explain how to select a model.
    • Add a note: the old plugin/provider block still works for the OpenCode 1 (V1) CLI.
    • Add a local-development example. It uses a file:// path to the ./v2 entrypoint.
  • Update opencode.json. Change the example config to the V2 format (plugins and providers).

How to use OpenCode 2 support

Add this to your config:

{
  "plugins": ["commandcode-go-opencode-provider/v2"]
}

You do not need a provider block. You do not need a hand-written model list.

Verification

  • bun run typecheck passes.
  • bun test tests/unit/ passes. It runs 90+ tests with 0 failures.
  • The v2.ts plugin was tested in a live opencode2 instance. The provider and all 21 models registered correctly. This was checked through the /api/provider and /api/model endpoints.

Note on PR history

This PR replaces PR #15, PR #16, and PR #17. Those PRs formed a stack. GitHub does not allow a PR to use a fork branch as its base in the upstream repo. This blocks true stacking across a fork without push access to the upstream repo. This PR combines all three changes into one PR against main. PR #16 and PR #17 are now closed. Both point to this PR.

Introduce src/models.ts so the V1 plugin and the upcoming V2 entrypoint
share one source of truth for loading models.json and converting entries
into their runtime-specific shapes.

- loadModels(): reads models.json once, typed as ModelEntry[]
- toConfigKey(): stable short key derivation (preserves prior behavior)
- toV1ModelConfig(): legacy { config } hook model shape
- toV2ModelDraft()/toV2ModelMap(): OpenCode V2 catalog model drafts

plugin.ts now delegates to the shared module; behavior is unchanged
and covered by tests.
OpenCode 2 loads plugins from a module's default export as
{ id, setup }, and requires provider/model registration through the
catalog transform API. The legacy plugin.ts factory (V1 only) fails to
load in V2 with a SchemaError.

Add a new ./v2 entrypoint that exports { id, setup } and registers the
commandcode provider plus all models from models.json via
ctx.catalog.transform. Users can now opt in with:

  plugins: ["commandcode-go-opencode-provider/v2"]

No provider block or hand-written model list is needed.

- v2.ts: V2 plugin default export ({ id, setup })
- package.json: expose ./v2, include v2.ts in files, bump to 0.5.0
- tsconfig.json: include v2.ts
- tests/unit/v2.test.ts: coverage for provider/model registration
Add a V2 section to the README covering install via the ./v2 entrypoint,
API-key setup, and model selection. Add a V2 local-development snippet and
switch the repo's example opencode.json to the native V2 plugin config.
@Majidalee1 Majidalee1 changed the title refactor: extract shared model conversion utilities feat: add shared model utilities and OpenCode 2 (V2) support Aug 7, 2026
Command Code can emit error events whose payload is a structured object
({ type, message, statusCode, isRetryable }). The parser passed the raw
object into the error part, which opencode rendered as '[object Object]'
instead of a readable message.

Extract the message field when the error is an object, and fall back to
JSON.stringify otherwise. Adds regression tests for both paths.
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