Skip to content

Plugin system fixes#4679

Merged
zachwolfe merged 24 commits into
developmentfrom
plugin-system-fixes
Jul 18, 2026
Merged

Plugin system fixes#4679
zachwolfe merged 24 commits into
developmentfrom
plugin-system-fixes

Conversation

@zachwolfe

Copy link
Copy Markdown
Collaborator

Summary

  • Detect source plugins with only a .csproj (no .cs files required)
  • Don't set reload cooldown when plugin load fails
  • Clean up failed plugins when their directory is deleted

Plugins that consist of a .csproj with NuGet package references but no
source files are a valid pattern (e.g. wrapper plugins). The previous
check rejected these because it required at least one .cs file.
A failed load was blocking subsequent retry attempts when DLLs appeared
shortly after the directory was created (e.g. during plugin installation).
Previously, deleting a failed plugin's directory left a stale entry in
_failedPlugins because GetPluginIdByDirectory only checks _knownPlugins.
Now fires PluginUnloaded so the UI updates accordingly.
Without this, the plugin settings view never re-rendered after a failed
load because no event was fired to trigger UsePluginState().
Ensures PluginLoadFailed fires on all genuine load failures so the UI
updates. Removes redundant LogPluginLoadFailure, centralizes logging
in RecordFailure, and avoids firing the event when the write lock is held.
Previously, deleting a plugin directory would unload it but leave it in
_knownPlugins, causing it to appear as "Unloaded" with no way to reload.
… system

Fired when a plugin directory is deleted (whether it was loaded, unloaded,
or failed). Ensures the UI removes it from all lists without needing a restart.
….yaml

Same fix as directory deletion — unloading alone leaves the plugin in
_knownPlugins, showing it as "Unloaded" with no way to reload.
Previously, exceptions thrown during Configure (e.g. missing dependency
DLLs) would propagate unhandled without recording the failure or firing
PluginLoadFailed, leaving the plugin invisible in the UI.
Comment thread src/Ivy/Core/Plugins/PluginLoader.cs Fixed
…er startup

When enabled, UsePlugins skips the synchronous DiscoverAndLoad during
setup and instead loads all plugins in a background task after the
server is ready. This significantly improves startup time when source
plugins need to be built.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment thread src/Ivy/Core/Plugins/PluginLoader.cs Fixed
Comment thread src/Ivy/Core/Plugins/PluginLoader.cs Dismissed
Comment thread src/Ivy/Core/Plugins/PluginLoader.cs Fixed
Comment thread src/Ivy/Core/Plugins/PluginLoader.cs Fixed
zachwolfe and others added 14 commits July 1, 2026 02:01
…utes

Plugins can now register endpoints under /ivy/plugins/{slug}/ via a
dedicated API instead of requiring raw UseWebApplication access. Endpoints
are backed by a dynamic data source so they're added/removed with the
plugin lifecycle. Also moves the plugin icon asset route to
/ivy/plugin-icons/ to avoid path collisions with plugin endpoints.
…erface

These APIs expose too much of the ASP.NET pipeline to plugins. Plugins
should use UseEndpoints for HTTP routes instead. The methods remain on
Server for internal first-party use (DesktopWindow, DocsServer).
- Fix whitespace in PluginContext.cs (missing indentation on field and method)
- Fix indentation on goto label in PluginLoader.cs
- Add 'when' exception filters to exclude OutOfMemoryException and
  StackOverflowException from plugin isolation catches, satisfying
  CodeQL cs/generic-catch-clause rule

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Suppress CP0006 (new interface member on IIvyExtendedPluginContext.UseEndpoints)
and CP0002 (removed UseWebApplication/UseWebApplicationBuilder from PluginContextBase).

Context interfaces are safe to extend per project conventions — plugins
call into them, not implement them.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
System.Linq is already included via ImplicitUsings, so the explicit
using directive triggers IDE0005 in CI's dotnet format check.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
PluginLoadFailed and PluginRemoved are new members on IPluginManager,
which is a host-provided interface not implemented by plugins, so this
is not a breaking change for deployed plugins.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ention

The File icon kind added complexity (route handler, validation, path traversal
protection) with zero adopters. Icons for available plugins will now flow through
a tendril.json file in the .nupkg, supporting only Named and Url kinds.
Fixes IDE0005 format check failure in CI.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@zachwolfe
zachwolfe marked this pull request as ready for review July 18, 2026 23:04
@zachwolfe
zachwolfe merged commit 58e457b into development Jul 18, 2026
9 checks passed
@artem-ivy-ai

Copy link
Copy Markdown
Collaborator

Staging removed

Staging environment has been deleted for this PR.

@zachwolfe
zachwolfe deleted the plugin-system-fixes branch July 18, 2026 23:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants