- API v2/v3 plugins bypass the acadrust gate entirely, preserving backwards compatibility.
- Marketplace repo-level policy only affects undeclared v4+ releases.
- Local load_at_startup only enforces the gate for v4+ plugins.
- Add host_acadrust_source and source-hash comparison helpers to ocs_plugin_api.
- Track acadrust_source and acadrust_declared in ExternalPlugin/ReleaseInfo.
- Apply repo-level policy: if any release in a repo declares acadrust_source, undeclared v4+ releases from that repo are incompatible.
- Preserve API v2/v3 backwards compatibility: legacy undeclared releases stay installable.
- Update Plugin Manager UI to only offer compatible releases and show 'acadrust mismatch' status.
- Drop acadrust_version from gate logic; only acadrust_source is required.
- Run Plugin Manager release fetches on OS threads so they execute in
parallel instead of serialising on the async executor.
- Reduce V4Connection shutdown poll from 3s to 100ms; the runner is killed
and reaped without blocking host shutdown.
- Add PluginManager::remove and PluginProcess::shutdown_and_wait so
uninstall can stop the runner before deleting files, fixing Windows
access-denied errors on plugin removal.
- Rebuild ribbon immediately after uninstall so the tab disappears.
Gate target-specific code so neither build warns about the other's items:
native-only helpers (view, window icon, file dialogs, file association, plugin
host/guard/registry, self-update) are cfg'd to non-wasm; the wasm-only font
fallback (script_of / cjk_lang / request) is cfg'd to wasm. Drop an unused mut,
allow the few genuinely-conditional dead items (mesh_click_hit, GPU layout
helpers, parity stubs), and gate the embedded PlotSettings-unrelated dead
constants. Both targets now build clean (only the unavoidable nom/quick-xml
future-incompat dependency notice remains).
Co-Authored-By: Claude Opus 4.8 <[email protected]>
A buggy external plugin that panicked anywhere — during load (version,
register, manifest), during ribbon build / dispatch, or inside an
interactive command (prompt, on_point, on_enter, on_object_pick) — took
the host down with it (#134). Run every cdylib entry point under
catch_unwind so the host stays up: the plugin's call is treated as
inert (load fails, dispatch returns "didn't handle it", interactive
hooks resolve to Cancel) and a "Plugin <hook> panicked: …" line lands
in the command line on the next tick. (#145)
Scope is Rust panics across the cdylib boundary, not genuine UB —
real isolation (segfault-proof) still requires out-of-process plugins.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Remove accidental dead code (unused imports, the superseded paste tool()
helper, a never-read TORIENT handles field, a duplicate let binding, an
unneeded mut) and mark intentional-but-unwired scaffolding with
allow(dead_code): the web-only save_to_bytes, the plugin loadable() probe,
the planned PICK_HIGHLIGHT colours, the DynFieldSpec label, and the layout
ribbon helpers. Native build is now warning-clean apart from the upstream
nom/quick-xml future-incompat notices.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Add an Uninstall button on installed external plugin cards that deletes
the package folder (effective next restart — the library stays resident
for the session). Reinstalling or upgrading via the marketplace now
clears any stale native library with a different name before writing the
new one, so the loader always picks the freshly installed binary.
Part of the #100 extensibility epic (phase 2).
Co-Authored-By: Claude Opus 4.8 <[email protected]>
OpenCADStudio no longer bundles plugins — every add-on is an external
cdylib loaded from the plugins folder or installed via the marketplace.
- Remove the demo plugin and the in-tree ocs_example_plugin crate.
- Remove the inventory-based built-in registration path (PluginRegistration,
all_plugins, installed_manifests); registry now serves core ribbon tabs
plus loaded external plugins, and try_dispatch routes only to externals.
- Plugin Manager drops the 'compiled into this build' section; the
enable/disable toggle moves onto loaded external cards.
- Prune the now-dead HostSession/DocumentTab helpers and re-exports.
Part of the #100 extensibility epic (phase 2).
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Add a Plugin Manager marketplace that installs external add-ons from a
GitHub repo's Releases. A curated registry (plugins/registry.json in this
repo, extended by PR) lists discoverable plugins; the host fetches it,
shows each entry with a release dropdown, and on install downloads the
asset matching the user's platform plus plugin.toml into the plugins
folder (API-version checked first). Users can also link arbitrary
owner/repo manually. Linked repos persist in settings.
Desktop only (ureq + serde_json); the install path reuses the phase-2
loader. Part of the #100 extensibility epic (phase 2).
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Move BuiltinPlugin into ocs_plugin_api (host feature) so out-of-tree
crates can implement it, and add export_plugin! to emit the two C
symbols a cdylib exposes: ocs_plugin_api_version (checked first, so an
ABI-incompatible build never runs) and ocs_plugin_register -> boxed
BuiltinPlugin. The host loads every compatible package from the plugins
folder at startup via libloading (desktop only), keeps the library
resident for the session, and merges its ribbon tab + command dispatch
into the same paths as built-ins (honouring enable/disable). The Plugin
Manager shows external packages with a Loaded / incompatible status.
Approach B: the plugin hands back a boxed trait object, assuming a
matching toolchain + ocs_plugin_api version (the version symbol enforces
the latter). crates/ocs_example_plugin is the reference cdylib.
Part of the #100 extensibility epic (phase 2).
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Phase-2 groundwork: scan <config>/OpenCADStudio/plugins/<id>/plugin.toml,
parse the documented keys (no new TOML dep), check for a platform native
library beside it, and gate on the API version. The Plugin Manager gains
an "External (plugins folder)" section showing each package with a
status pill (Ready to load / API incompatible / No library). Discovery
only — actually loading the cdylib is the next step.
Part of the #100 extensibility epic (phase 2).
Co-Authored-By: Claude Opus 4.8 <[email protected]>