Skip to content

fix: restore external plugin loading in Plugin.init() #408

@randomm

Description

@randomm

What happened

Plugin.init() in packages/opencode/src/plugin/index.ts is a stub that only logs "plugin system stub - init called" and returns. External plugins from ~/.config/opencode/plugins/ are never loaded.

This was introduced in commit 53f683f when we aligned the plugin system with upstream in PR #392. The alignment restored upstream's Effect-based plugin files but left init() as a stub since the fork doesn't use Effect.

Expected behaviour

  • Plugin.init() loads internal plugins (CodexAuthPlugin, CopilotAuthPlugin)
  • Plugin.init() loads external plugins from config directories via PluginLoader.loadExternal()
  • Plugins receive a PluginInput with an SDK client, project info, and Bun shell access
  • Plugin load failures are logged but don't crash the system

Root Cause

Commit 53f683f replaced the working init() with a stub:

export async function init() {
  log.info("plugin system stub - init called")
}

All the supporting infrastructure still exists and works:

  • Config.get() scans ~/.config/opencode/plugins/*.{ts,js} and populates config.plugin[] (config.ts:460-474, 1338-1345)
  • PluginLoader.loadExternal() fully functional (loader.ts:152)
  • applyPlugin() defined (index.ts:46-52)
  • INTERNAL_PLUGINS defined (index.ts:15)
  • PluginInput type from @opencode-ai/plugin (packages/plugin/src/index.ts:26-33)

Implementation

Replace the stub init() in packages/opencode/src/plugin/index.ts:

  1. Add imports: Config, Server, Instance, createOpencodeClient
  2. Create an SDK client with in-process fetch adapter (no HTTP roundtrip — use Server.App().fetch() directly)
  3. Build PluginInput from Instance context
  4. Load internal plugins via INTERNAL_PLUGINS array
  5. Load external plugins via PluginLoader.loadExternal() with error reporting
  6. Update .fork-features/manifest.json with "plugin-loading" feature entry documenting this divergence from upstream

Quality Gate: @ts-ignore

The proposed code uses @ts-ignore for the fetch type incompatibility between Hono and native fetch. Per AGENTS.md, @ts-ignore is forbidden. Use a type-safe approach instead (e.g., a properly typed adapter function or explicit cast with explanatory comment).

Acceptance Criteria

  • Plugin.init() loads internal plugins (CodexAuthPlugin, CopilotAuthPlugin)
  • Plugin.init() loads external plugins from ~/.config/opencode/plugins/*.{ts,js} via PluginLoader.loadExternal()
  • External plugin load failures are logged but don't crash the system
  • No @ts-ignore, as any, or other quality gate violations
  • bun run typecheck passes with 0 errors
  • bun test passes (existing + new tests for plugin loading)
  • .fork-features/manifest.json updated with "plugin-loading" feature entry
  • bun run .fork-features/verify.ts passes

Definition of Done

  • Tests written for plugin loading (TDD preferred)
  • 80%+ coverage for new code in init()
  • All linting passes
  • Fork-features manifest entry created with proper criticalCode markers
  • Verified that Plugin.trigger() still works with loaded hooks

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions