Skip to content

V2: support registering SDK plugins after a Location has booted #34799

Closed

Description

@kitlangton

In the embedded SDK (@opencode-ai/sdk-next), plugins contributed through opencode.plugin(...) only apply to Locations booted after registration. packages/core/src/plugin/sdk.ts documents this: a plugin registered after a Location has booted only applies to Locations booted afterward, and embedders are expected to register at startup before creating Sessions.

For long-lived embedders this turns into a startup-ordering invariant that every host app has to enforce itself. The opencode-agent app uses one long-lived Location, so a plugin registered even slightly late (a persona agent, a native bridge tool) silently never applies for the whole process generation. We have hit this twice and now structure the app's entire startup around "register everything before any Session can possibly be created", which is fragile knowledge that will not survive a second embedder.

Request: allow plugin registration to take effect on already-booted Locations, at least for Sessions created after registration. That would make plugin() safe to call at any point in the host's lifecycle and remove the ordering requirement entirely. Dynamic registration also opens up hosts that want to add capabilities at runtime rather than only at boot.

Happy to discuss implementation. The relevant seam looks like SdkPlugins.Service plus PluginInternal's per-Location-boot ctx.plugin.add application in packages/core/src/plugin/internal.ts.

Activity

  1. added
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    enhancementNew feature or request
    on Jul 5, 2026
  2. kitlangton commented on Jul 6, 2026

    @kitlangton
    ContributorAuthor

    Hard evidence for this from the #35556 investigation, verified on origin/v2 at 175d200: a plugin registered through opencode.plugin(...) after a Location has booted never activates in that Location. A core-level test polls the plugin registry and materialized tools for 2 seconds after registration and sees nothing, then activates immediately after one config Event.Updated, which is the supervisor's only post-boot reload trigger. With LocationServiceMap's 60 minute idle TTL never expiring under continuous traffic, a long-lived host waits forever unless a config file happens to change.

    So the current documented behavior is not just an ordering invariant for hosts to enforce, it is a silent no-op with no error and no recovery path in a steady-state process. Whichever way the policy lands (apply to booted Locations or reject loudly), silent success should stop being an outcome.

  3. kitlangton commented on Jul 6, 2026

    @kitlangton
    ContributorAuthor

    Fixed by #35576. SDK registration now publishes an unlocated sdk.plugin.updated event, and every already-booted Location reloads through the ordinary serialized generation path. Regression coverage verifies multi-Location reloads and isolation between independent embedded hosts. Closing this issue; the separate initial empty-generation race remains tracked in #35556.

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

    2.0coreAnything pertaining to core functionality of the application (opencode server stuff)enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions