Commit Graph
21 Commits
Author SHA1 Message Date
Felix RiestraandClaude Sonnet 5 bd49bd66d4 docs(plugin): fix inaccuracies and flag real gaps found building a plugin
Found while building an out-of-tree scripting plugin from scratch against
this doc and the actual ocs_plugin_api/host source. Two categories:

Fixed outright (docs/examples didn't match the real code):
- The worked CadModule example returned Vec<RibbonGroup> from
  ribbon_groups(); the real trait requires &[RibbonGroup] - the example
  wouldn't compile. Fixed with the OnceLock pattern the host's own
  benchmark code already uses.
- Reconciled a contradiction between "process isolation removes the need
  for a shared Rust ABI" and the exact-rustc_version requirement described
  a few paragraphs earlier in the same doc.
- The roadmap's "Next" list still had external automation as unstarted;
  --mcp/--serve are real and operational (src/cli.rs, src/mcp.rs).
- Added the missing plugin.toml to docs/plugin-template-v2 (its own
  DESIGN.md already claimed one could be installed).
- Documented that plugin-template's CI floats rust-toolchain@stable, which
  doesn't guarantee matching the host's exact rustc - added acadrust_source
  to both templates' plugin.toml plus the release.yml step that fills it
  from Cargo.lock's resolved acadrust source, alongside the existing
  rustc_version fill.

Flagging for your call, not fixed here (found the behavior, not sure it's
the intended one, prefer to ask than guess at a fix):
- acadrust_compatible()'s ABI gate only runs at all if plugin.toml declares
  acadrust_source - an undeclared field is silently treated as compatible,
  unlike rustc_version (undeclared = incompatible). The same shortcut
  appears in two places: ExternalPlugin::acadrust_compatible
  (src/plugin/external.rs) and the inline check inside fetch_release_info
  (src/plugin/marketplace.rs). If this is deliberate (e.g. back-compat with
  manifests from before the field existed), no action needed beyond a
  comment; if not, both call sites need the same fix.
- The command line still uppercases typed/pasted input even with the `>`
  literal-spaces prefix (Message::CommandInput, src/app/update/mod.rs) -
  `>` only stops a space from auto-submitting the line, it doesn't skip
  `s.to_uppercase()`. A plugin command needing a case-sensitive typed
  argument has no escape today short of automation.
- fetch_release_info (src/plugin/marketplace.rs) returns every release
  under a linked repo with no filter on the manifest's own id field (which
  it already parses to build ReleaseInfo) - a repo hosting more than one
  plugin under tag-namespaced releases surfaces all of them mixed
  together in one plugin's version list.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-16 03:37:54 +02:00
Hakan Seven 0d766be3df fix(plugins): preserve document path encoding
Keep OS-native path data intact across IPC instead of replacing non-UTF-8 bytes.

Refs #901
2026-08-29 16:00:18 +03:00
Hakan Seven 2842f6dc58 fix(plugins): gate on_load behind API v5
BREAKING CHANGE: plugins using on_load must target API v5 and declare api_version = 5.

Refs #901
2026-08-29 15:57:26 +03:00
Hakan Seven 466ab99c63 fix(plugins): enforce rustc compatibility
BREAKING CHANGE: API v4+ plugin packages must declare the exact rustc version used to build the binary.

Refs #901
2026-08-29 15:54:41 +03:00
Sebastian ed3e064a47 feat(plugins): include rustc version in plugin compatibility gate
OpenCADStudio/plugins#901

- Record the host's rustc --version output in the embedded version_info.json.
- Add rustc_version/rustc_declared/rustc_compatible to plugin manifests and
  release metadata, mirroring the existing acadrust gate.
- Reject API v4+ plugins whose declared rustc differs from the host, with a
  clear one-line error message.
- Propagate the rustc gate through the marketplace, install flow, and UI.
- Update plugin architecture docs to describe the new ABI metadata.
2026-08-29 10:34:47 +02:00
Hakan Seven 81e7add1dd fix(tolerance): complete workflow integration
Sync current main and companion codec changes before preserving unsupported frame rows, rendering in the entity plane, and sharing final layout metrics with placement preview.
2026-08-27 00:14:08 +03:00
Hakan Seven fcc6e1f8e1 fix(web): link plugins to desktop app
Keep browser entry points visible while explaining that native
plugins require a desktop install.

Refs #567
2026-07-29 16:28:20 +03:00
Hakan Seven 2424eeb74d fix(web): hide unsupported plugin manager
Fixes #567
2026-07-29 16:17:17 +03:00
Sebastian b18be4dacc Adding timeout protection to host from stuck runner 2026-06-26 10:10:56 +02:00
Sebastian dcfaed0182 Initial commit 2026-06-25 00:01:36 +03:00
Hakan SevenandClaude Opus 4.8 707c143212 feat(plugin): object-pick acquisition for interactive commands
Extend InteractiveCommand with needs_object_pick / on_object_pick so a
plugin tool can prompt the user to pick an existing entity (handle + point)
rather than a free point — the structure-pick path Storm Sewer's SS_PIPE
needs to connect existing structures. The host adapter delegates to the
internal entity-pick flow; over --serve the pick is fed as a hex handle.
Stays API v2 (no released plugin implements InteractiveCommand yet).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-18 01:43:53 +03:00
Hakan SevenandClaude Opus 4.8 931eb908a9 feat(plugin): InteractiveCommand hook for click-to-place (API v2)
Plugins could dispatch commands but not register interactive (click-to-
place) tools — the gap mf4633 flagged on #100 for Storm Sewer's SS_INLET
/ SS_PIPE. Add an InteractiveCommand trait + CommandStep to ocs_plugin_api
and HostApi::start_interactive; a host adapter bridges it to the internal
CadCommand, so a plugin tool drives the host's point-collection flow.

Hybrid by construction: the same command works by clicking in the viewport
AND by feeding coordinates over --serve (run "CMD x,y x,y"). Adding a
HostApi method changes the contract vtable, so API_VERSION bumps to 2 —
v1 plugin binaries are now refused at load.

Part of the #100 extensibility epic.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-17 21:43:35 +03:00
Hakan SevenandClaude Opus 4.8 1175675c5e docs(plugin): rewrite architecture + template for the external-only model
OpenCADStudio ships no built-in plugins, so the spec and scaffold no
longer describe the in-tree inventory path, demo_plugin, or the fictional
Storm Sewer reference. The architecture doc now covers the external cdylib
model end to end (ocs_plugin_api contract, export_plugin!, building +
publishing per-platform releases, runtime loading, the marketplace +
curated registry, the approach-B ABI caveat). The template becomes a
standalone cdylib crate (Cargo.toml + src/lib.rs + release workflow)
instead of an in-tree module.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-17 16:02:16 +03:00
Hakan SevenandClaude Opus 4.8 29c71be101 feat(plugin): load external cdylib plugins at runtime (phase 2)
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]>
2026-06-17 14:48:56 +03:00
Hakan SevenandClaude Opus 4.8 5ccf5cfe36 feat(plugin): lift host surface behind a HostApi trait (phase 1b)
Plugins targeted the host's concrete HostSession type. Add a HostApi
trait in ocs_plugin_api behind an optional `host` feature (the only thing
that pulls acadrust, so the core crate stays dependency-free). HostSession
implements it and BuiltinPlugin::dispatch now takes `&mut dyn HostApi`, so
an out-of-tree add-on compiles against the contract crate alone. Per-tab
plugin state is reached through object-safe plugin_state* helpers.

Completes the phase-1 host-surface extraction in the #100 epic.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-17 11:31:05 +03:00
Hakan SevenandClaude Opus 4.8 a3b8acb59e feat(plugin): XDATA read/write/remove helpers on HostSession
Plugins persisted domain data via the raw acadrust::xdata API with
boilerplate and no APPID registration. Add read_record / write_record /
remove_record keyed by entity handle; write_record replaces an existing
record for the same app and registers the application in the APPID table
so the data round-trips through DWG/DXF for other CAD apps.

Part of the #100 extensibility epic (surfaced in #106).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-17 10:28:12 +03:00
Hakan SevenandClaude Opus 4.8 50825b6346 feat(plugin): ModuleEvent::PluginFileDialog for native file import
Add-ons had no way to request a file picker — only the host's own Open
dialog. PluginFileDialog lets a plugin tool ask the host to open a native
picker; on selection the host dispatches "<command> <path>" back to the
plugin with original case preserved (bypassing the command-line
upper-casing that mangles case-sensitive paths on Linux/macOS). The demo
plugin gains an Import tool exercising it.

Part of the #100 extensibility epic (surfaced in #106).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-17 10:22:08 +03:00
Hakan SevenandClaude Opus 4.8 844069b4ef feat(plugin): enable/disable plugins from the Plugin Manager
The manager was a read-only inventory. Each plugin now has an
Enable/Disable toggle: a disabled plugin keeps its manifest listed but
drops its ribbon tab and command dispatch. The disabled-id set persists
in settings.txt (disabled_plugins=) and the ribbon rebuilds on toggle.

Part of the #100 extensibility epic.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-17 10:15:38 +03:00
Hakan SevenandClaude Opus 4.8 ec865a95aa feat(plugin): add a Plugin Manager window listing installed add-ons
Read-only inventory of the add-ons compiled into the build — name, version,
id, API level, description, command prefixes — built from the extracted
`ocs_plugin_api` manifest. Opened with the `PLUGINS` / `PLUGINMANAGER` command
or the Start-page "Plugins" button.

Adds `installed_manifests()` to the plugin registry and wires the window the
same way as the existing About / Shortcuts windows.

Part of #100 (phase-1 plugin manager UI stub).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-15 01:46:09 +03:00
Hakan SevenandClaude Opus 4.8 72ec1146df refactor(plugin): extract ocs_plugin_api crate for the stable add-on contract
Move the dependency-free, semver-versioned half of the plugin contract into a
standalone workspace crate `crates/ocs_plugin_api`:

- manifest types: PluginManifest, ApiVersion, API_VERSION
- ribbon vocabulary: CadModule trait + ToolDef/RibbonGroup/RibbonItem/IconKind/
  ModuleEvent/StyleKey

The host re-exports them from `crate::plugin::manifest` and `crate::modules`, so
every existing call site is unchanged. The acadrust-typed runtime surface
(HostSession) stays in the host binary; lifting it behind a HostApi trait in the
same crate is the remaining phase-1b step.

Part of #100. Docs updated in docs/plugin-architecture.md.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-15 01:36:04 +03:00
Michael Flynn e46701456f Add plugin host architecture and Storm Sewer add-on package
Generic plugin runtime (src/plugin/, HostSession, per-tab plugin_state, command router). QGIS-style add-on layout with plugin.toml and single PluginRegistration. Storm Sewer refactored as reference consumer with dispatch.rs, catchments, LandXML, headless tests (43 passing). Core update.rs decoupled from storm_sewer via CadCommand object-pick hooks. Docs: plugin-architecture.md, plugin-template, PR and issue-78 reply drafts.
2026-06-09 13:41:21 -04:00