Skip to content

feat: OpenCode 2 plugin API support - #32

Merged
yuseferi merged 9 commits into
yuseferi:mainfrom
AlexanderWillner:rfc/opencode-v2-plugin-api
Sep 29, 2026
Merged

yuseferi merged 9 commits into
yuseferi:mainfrom
AlexanderWillner:rfc/opencode-v2-plugin-api

Conversation

@AlexanderWillner

@AlexanderWillner AlexanderWillner commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Summary

This PR adds OpenCode 2 plugin API support while retaining the existing OpenCode 1 server entrypoint.

It also fixes modality discovery for LiteLLM chat models. When LiteLLM does not report capability metadata, the plugin now registers the model as text-only instead of relying on OpenCode's image-capable fallback. The model cache version is incremented so stale entries are refreshed after the upgrade.

Type of change

  • Bug fix (non-breaking)
  • OpenCode 2 compatibility
  • Documentation and tests

Checklist

  • npm run typecheck passes
  • npm test passes
  • No new runtime dependencies beyond the OpenCode 2 plugin package
  • README updated for the behavior change
  • CHANGELOG.md updated under ## [Unreleased]
  • Commit messages follow Conventional Commits

How was this tested?

  • npm test: 67 tests passed
  • npm run typecheck
  • git diff --check
  • Live OpenCode 2 smoke test against the configured LiteLLM route
  • Text completion succeeded
  • An image attachment no longer produced the mmproj backend error or retry loop

The model catalog now reports level-1-lokal with input: ["text"] and output: ["text"] when capability metadata is absent. A route with a working multimodal projector can opt in with modelCapabilities: { "model-id": { "supports_vision": true } }.

Maintainer questions

  1. Should the package support OpenCode 1 and 2 in one release, or should V2 support be a major-version transition?
  2. Is @opencode/plugin the preferred dependency and API surface for V2 plugins?
  3. Does the V2 provider and authentication integration match the expected configuration and /connect behavior?
  4. Are provider transform/reload and event subscription the intended lifecycle hooks for discovering new models?

Related to #31. This RFC intentionally does not close the issue.

Summary by CodeRabbit

  • New Features
    • Added support for OpenCode 2 alongside the existing OpenCode 1 integration.
    • OpenCode 2 can discover and refresh LiteLLM models, preserve custom models, and update provider credentials when they change.
    • LiteLLM can use an explicitly configured URL or automatically detect a local server.
  • Bug Fixes
    • Models without modality information are treated as text-only, preventing image requests to text-only model routes.
  • Documentation
    • Updated setup, configuration, compatibility, and troubleshooting guidance for both OpenCode versions.

@coderabbitai

coderabbitai Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 2243629c-f79b-4bf3-bace-e1dcf41b7c69

📥 Commits

Reviewing files that changed from the base of the PR and between c930c4d and 3cb746d.

⛔ Files ignored due to path filters (2)
  • assets/architecture.svg is excluded by !**/*.svg
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (12)
  • CHANGELOG.md
  • CONTRIBUTING.md
  • README.md
  • package.json
  • src/index.ts
  • src/plugin/index.ts
  • src/plugin/v2.ts
  • src/utils/litellm-api.ts
  • src/utils/model-cache.ts
  • test/model-cache.test.ts
  • test/plugin-v2.test.ts
  • test/to-config-model.test.ts
 _______________________________________________
< Finding your faults 10 times faster than Mom. >
 -----------------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Default LiteLLM chat models to explicit text-only modalities when capability metadata is absent, and invalidate stale model caches. Add regression coverage for OpenCode 2 discovery and cache upgrades.
Explain the conservative default for LiteLLM models without modality metadata and record the fix in the Unreleased changelog.
@yuseferi

Copy link
Copy Markdown
Owner

Independently verified the loader contract behind this PR's hybrid approach on two real runtimes (probe plugins under opencode models --print-logs --log-level DEBUG, plus opencode debug v2). Confirming the design and weighing in on the maintainer questions.

Verification result

  • Stable 1.18.31 and newest dev (0.0.0-dev-202609221946) both run the V1 loader only. A default export that is an object with server() loads; a { id, setup }-only default (no server()) is rejected with must default export an object with server(), and its setup/catalog.transform never fire.
  • LiteLLMPluginDefinition = { ...Plugin.define({ id, setup }), async server(input) { return LiteLLMPlugin(input) } } therefore loads on current runtimes via server(), with the V2 setup carried inert until upstream wires the V2 loader. This is the right shape — the hybrid works today and is forward-compatible. (I did not run this branch end-to-end; this confirms the export contract it relies on.)

Maintainer questions

  1. One release or a major-version transition? One release. The object-with-server() form satisfies both contracts simultaneously, so V1 keeps working while V2 rides along dormant — no major bump needed just for the transition.
  2. Is @opencode/plugin the preferred V2 dependency/surface? Yes for this design. The older @opencode-ai/plugin/v2/promise CatalogDraft only exposes update/remove — no model add — so it cannot register discovered models, and its setup isn't invoked by any shipping runtime. @opencode/plugin@2.x has provider.transform + editor.add + event.subscribe, which is what issue OpenCode 2 plugin API compatibility #31 actually asks for.
  3. /connect + auth integration: matches what I saw — the V1 server() path resolves the stored credential the same way it does today; nothing in the loader verification contradicts it.
  4. Are provider transform/reload + event subscribe the intended lifecycle hooks? They're the correct V2 hooks on the @opencode/plugin@2.x surface. Caveat worth a note in the README: on the runtimes I tested those V2 hooks are not yet invoked (V1 loader only), so the active code path today is still server() + the V1 config/event hooks. The V2 path becomes live when OpenCode flips the loader.

The modality fix (always emit modalities, defaulting to text-only, so llama.cpp routes don't receive image parts) and the cache-version bump both look correct and address a real failure mode.

@yuseferi

Copy link
Copy Markdown
Owner

Thanks @AlexanderWillner and the maintainers for the OpenCode 2/V1 hybrid work and the modality fix.

I pushed follow-up commit 3cb746d to harden the latest V2 path:

  • prune stale plugin-discovered models while preserving curated models;
  • remove the V2 legacy auth.json fallback;
  • prevent connection-managed credentials from being materialized into provider settings;
  • make the V2 tests hermetic and add regressions.

Validation: typecheck passed, 70 tests passed (including with ambient LiteLLM environment variables), and a real OpenCode V2 2.0.19 smoke test completed through a mock LiteLLM provider. The live-runtime check plus focused regressions sped up the review/fix process and helped narrow the remaining issues quickly.

@yuseferi yuseferi changed the title [RFC] OpenCode 2 plugin API support feat: OpenCode 2 plugin API support Sep 29, 2026
@yuseferi
yuseferi marked this pull request as ready for review September 29, 2026 08:57
@yuseferi
yuseferi merged commit 6215ca7 into yuseferi:main Sep 29, 2026
3 checks passed
github-actions Bot pushed a commit that referenced this pull request Sep 29, 2026
# [1.4.0](v1.3.0...v1.4.0) (2026-09-29)

### Features

* OpenCode 2 plugin API support ([#32](#32)) ([6215ca7](6215ca7))
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.

2 participants