Skip to content

OpenCode 2.x: fails to load — V1 entrypoint, no V2 setup(ctx) #33

Description

@alanjholiveira

Summary

The plugin does not load on OpenCode 2.x. It still ships a V1-only entrypoint, so OpenCode's plugin loader rejects it before setup ever runs.

Error

PluginModule.LoadError: Plugin must export a default definition with an id and an effect or setup function.
(cause: SchemaError(Expected object at ["default"])))

Logged as level=WARN message="failed to load plugin" target=opencode-auto-resume on every load, in both opencode run and the desktop/background service.

Environment

  • OpenCode 2.0.12 / 2.0.14 (desktop + CLI), config key is plugins
  • opencode-auto-resume@1.1.18
  • Reproduced by adding it with opencode plugin add opencode-auto-resume and starting any session

Why

V2 requires a default-exported object with an id and a setup(ctx) (or effect(ctx)). The published entrypoint has no default export matching that shape, so the schema check fails during module load.

Migration reference: https://opencode.ai/v2/docs/build/plugins/migrate-v1

The dual-entrypoint escape hatch documented upstream would keep V1 working while adding V2:

export default {
  ...Plugin.define({
    id: "auto-resume",
    async setup(ctx) {
      // V2 hooks
    },
  }),
  async server() {
    return {
      // existing V1 hooks
    }
  },
}

Port scope (heads-up, this is the non-obvious part)

Beyond renaming the entrypoint, several V1 APIs the plugin relies on are not exposed on the V2 plugin context, so a straight server() → setup() copy will not be enough:

Missing on ctx (verified by logging Object.keys(ctx) and Object.keys(ctx.session) in a V2 plugin):

  • client.session.list, session.status, session.abort, session.summarize, session.todo, session.messages
  • client.app.log
  • client.provider, client.config, client.tool.ids
  • client.tui (TUI is a separate plugin surface in V2)

V2 ctx.session only exposes: hook, create, get, switchAgent, switchModel, prompt, generate, command, synthetic, interrupt, update, move, wait, context.

Hooks with no direct V2 equivalent:

  • chat.message → closest is ctx.session.hook("prompt", ...) (runs at prompt admission, not per message)
  • command.execute.before → docs say to use a command transform or the prompt hook depending on intent
  • tool.execute.before → ctx.tool.hook("execute.before", ...) (note: args arrive as event.input, and the shell tool is now named shell, not bash)
  • tool.execute.after → ctx.tool.hook("execute.after", ...)

Happy to test a next/V2 build if you want a hand verifying it.

Workaround currently used

None — the plugin has to be removed from plugins to keep the log clean.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions