opencode icon indicating copy to clipboard operation
opencode copied to clipboard

feat(plugin)!: migrate plugin system to SDK v2

Open aryasaatvik opened this issue 4 days ago • 3 comments

Summary

  • Migrates plugin system to use SDK v2 types and client exclusively
  • Removes v1 SDK compatibility layer - this is now a full breaking change
  • Key context: Many hooks already had type drift between v1 contract and v2 runtime, so this breaking change is less severe than it appears

Why This Breaking Change Is Acceptable

Hook Types Were Already Broken

Analysis revealed significant type drift between what the plugin package defined and what the OpenCode core actually passed at runtime:

Hook Plugin Expected Core Passed Impact
permission.ask Permission with title Permission.Info with message Field name mismatch - input.title returns undefined
chat.params Provider Promise<Provider.Info> Promise wrapper not in type
chat.message UserMessage MessageV2.Info Different type structure

The core was already using @ts-expect-error workarounds to suppress these mismatches. Plugins accessing input.title in permission.ask were already getting undefined at runtime.

This Change Fixes the Type Mismatch

Instead of maintaining broken v1 types, we:

  1. Update the plugin contract to match the actual v2 runtime behavior
  2. Provide clean, consistent types that match what OpenCode core actually passes
  3. Remove the UnifiedClient complexity (no more .v2 accessor needed)

Changes

Plugin Package (packages/plugin)

  • Updated all imports from @opencode-ai/sdk@opencode-ai/sdk/v2
  • Changed hook types to use v2 SDK types (PermissionRequest instead of Permission, etc.)
  • Simplified PluginInput.client to be v2 OpencodeClient only
  • Added ToolContext.metadata() and ToolResult types

Plugin Loader (packages/opencode)

  • Removed v1 SDK client creation
  • Removed unified client proxy (.v2 accessor)
  • Now creates and passes v2 SDK client only

Breaking Changes

What Before After
SDK client input.client (v1) + input.client.v2 (v2) input.client (v2 only)
Permission type Permission with title PermissionRequest with permission
Permission reply status: ask/deny/allow reply: once/always/reject
SDK calls Nested { path, body, query } Flattened parameters

Migration for Plugin Authors

  1. Change imports: @opencode-ai/plugin (no /v2)
  2. Update permission hook:
    // Before
    (input: Permission, output: { status: "ask" | "deny" | "allow" }) => { ... }
    
    // After
    (input: PermissionRequest, output: { reply: "once" | "always" | "reject" }) => { ... }
    
  3. Update SDK calls to use flattened parameters

Why Not Maintain v1 Compatibility?

  • The SDK client had massive breaking changes (every method call changed from nested to flat)
  • Hook types already had significant drift (not just style changes, but actual field mismatches)
  • Maintaining both v1 and v2 code paths added complexity
  • Clean break forces plugin authors to update, resulting in better type safety

Closes #7641

aryasaatvik avatar Jan 10 '26 13:01 aryasaatvik