Skip to content

feat: support opencode v2 plugin API alongside v1 - #81

Merged
iHildy merged 13 commits into
iHildy:mainfrom
jvacek:feat/v2-dual-support
Sep 23, 2026
Merged

iHildy merged 13 commits into
iHildy:mainfrom
jvacek:feat/v2-dual-support

Conversation

@jvacek

@jvacek jvacek commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Summary

One package supporting both opencode v1 (@opencode-ai/plugin, plugin key)
and v2 (@opencode/plugin, plugins key). V1 minimum >= 1.18.29 (object
entrypoints), v2 ^2.0.0. See docs/v2.md for the full mapping.

V2 replaces the single mutable config object with replayable, synchronous,
per-domain transforms, so each override key maps to the domain that owns it
(mcp/agent/model/provider); everything else warns instead of merging.

What's in the stack (13 commits)

Base v2 support (6):

  • refactor: extract shared sync plugin core — executeSyncCommand,
    command loading, tool args into src/shared.ts
  • feat: injectable AI provider and node shell shim — createV1AiProvider
    in src/sync/ai.ts, createNodeShell in src/shell-node.ts
  • feat: support opencode v2 plugin API — setupV2 in src/v2.ts
  • test: v2 dual export and domain transforms, docs, CI assertion

Review hardening (7, from senior review of docs/v2.md):

  • feat: shared blankEnvPlaceholders helper — single {env:…} pattern in
    src/sync/config.ts, reused by v2 for secret-free disabled MCP configs
  • feat: SyncService.dispose — stops the Turso sync loop/idle-flush timers;
    wired into v2 setup cleanup (fixes hot-reload leak)
  • docs: node shell shim differences — POSIX//bin/sh, inherited env,
    32 MiB buffer, exec error shape
  • refactor: harden v2 transforms — single-read override load (no TOCTOU),
    shared deepMerge, pure replay callbacks (unknown-ID warnings moved
    outside via best-effort list()), removed dead no-op fallback call,
    Set-based command lookup, hardened bare-repo parsing, prefixed logging
  • fix: explicit dual entrypoint — {id, setup, server}, no spread
  • test: replay purity, arg parsing, idempotent cleanup
  • docs: rewrite docs/v2.md to match the implementation

Known parity gaps (documented in docs/v2.md)

  • Non-MCP runtime keys are warn-only in v2; no fake global merge.
  • No toasts in v2 (console); Turso idle-gating skipped (empty status = idle,
    syncs immediately).
  • Slash commands parse a bare owner/repo token only; full options need the
    opencode_sync tool.
  • Overrides require host restart; no watcher/reload() calls.
  • V2 CommandDefinition has no template/agent/model — md templates execute
    directly with a session.synthetic reply.

Test plan

  • bun run check clean
  • bun test / vitest run — 205 pass (incl. 9 new v2 tests)
  • bun run build clean; dist exposes {id, setup, server}
  • Manual packed-tarball smoke on opencode v1 (plugin) and v2 (plugins)
  • CI matrix smoke (v1 + v2 installs vs packed plugin)

Fixes: n/a (new feature). Breaking: no — v1 server() behavior unchanged.

@jvacek

jvacek commented Sep 22, 2026

Copy link
Copy Markdown
Contributor Author

Hey @iHildy! Hope all's well, just wanted to tag you here so it shows up on your radar in case you're not watching the PRs here.

Thanks in advance!

@iHildy
iHildy merged commit 69f6ab2 into iHildy:main Sep 23, 2026
3 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.

2 participants