Skip to content

feat(core): reload discovered plugins from source edits - #39174

Merged
kitlangton merged 6 commits into
v2from
plugin-reload
Jul 27, 2026
Merged

kitlangton merged 6 commits into
v2from
plugin-reload

Conversation

@kitlangton

@kitlangton kitlangton commented Jul 27, 2026 •

Copy link
Copy Markdown
Contributor

What

Reload auto-discovered plugin files when their source changes under an existing Config root.

This fixes edits to {plugin,plugins}/*.{ts,js} being observed by the filesystem watcher but suppressed by Config's unchanged Config.Entry[] equality check.

Before / After

Before

  1. A user edits .opencode/plugin/local.ts.
  2. Config's existing root watcher observes the edit and rediscovers Config entries.
  3. The entries are structurally unchanged, so config.updated is not published.
  4. PluginSupervisor does not rescan and the old plugin generation remains active.

After

  1. The existing Config root watcher publishes the raw path through config.changes().
  2. PluginSupervisor accepts paths at or below {plugin,plugins} and coalesces the filesystem burst.
  3. The Supervisor rescans plugin operations and activates the changed generation.
  4. plugin.updated is published after the new generation is readable.

How

  • packages/core/src/plugin/supervisor.ts filters config.changes() with normalized path containment under each active Config directory's plugin and plugins children.
  • The predicate intentionally has no suffix check so directory-level filesystem events still invalidate the source set.
  • Matching filesystem events receive a generation before the 100 ms debounce, keeping PluginSupervisor.flush aware of accepted startup work.
  • Structured Config and SDK plugin updates retain their existing immediate signal path.
  • packages/core/test/config/plugin.test.ts removes the synthetic config.updated publication from the existing source-edit test and uses plugin.updated as the read barrier.

Scope

This PR deliberately does not add direct watches for configured local paths outside Config roots. That needs a separate versioned source plan coupling the Config snapshot, resolved entrypoint, watch kind, content revision, activation, and watcher commit.

The Watcher.acquireRelease interruption-safety change is also deferred to a separate PR with focused acquisition, interruption, and teardown coverage.

Testing

  • bun test --only-failures test/config/plugin.test.ts --timeout 30000 — 11 passed, 0 failed.
  • bun typecheck from packages/core — passed.
  • Push hook bun turbo typecheck --concurrency=3 — 32 tasks passed.

Flow

sequenceDiagram
  participant Editor
  participant Config
  participant Supervisor as PluginSupervisor
  participant Registry as Plugin Registry

  Editor->>Config: edit plugin source
  Config->>Supervisor: config.changes(path)
  Supervisor->>Supervisor: filter + debounce + rescan
  Supervisor->>Registry: activate generation
  Registry-->>Supervisor: plugin.updated
Loading

@kitlangton kitlangton changed the title feat(core): reload plugins from source changes feat(core): reload discovered plugins from source edits Jul 27, 2026
@kitlangton
kitlangton merged commit 8b4b0d6 into v2 Jul 27, 2026
7 of 9 checks passed
@kitlangton
kitlangton deleted the plugin-reload branch July 27, 2026 22:20
jinhuang712 pushed a commit to jinhuang712/opencode that referenced this pull request Sep 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant