forked from 1b-agent/opencadstudio-upstream
feat(plugin): emit SelectionChangedV4 to V4 plugins and add ocs_plugin_api architecture docs
- Add HostNotification::SelectionChangedV4 { tab_id, handles } with discriminant 7
- Broadcast active-tab selection changes at update() and automation_op boundaries
- Use stable order-independent signature to avoid spurious hover notifications
- Clear Scene selection in automation new/open to avoid stale handles
- Add crates/ocs_plugin_api/ARCHITECTURE.md and module-level rustdoc
- Cross-link README.md and docs/plugin-architecture.md
- Fix test env race with shared ENV_LOCK and EnvVarGuard helpers
This commit is contained in:
1 parent
f4a292a6b2
commit
f20bf93dfe
25 files changed
+592
-17
No files matched your search
@@ -2,6 +2,21 @@
|
||||
//!
|
||||
//! Built only with the `host` feature because it needs `acadrust`-typed
|
||||
//! messages and the plugin runner binary.
|
||||
//!
|
||||
//! Submodules:
|
||||
//!
|
||||
//! - [`protocol`](crate::ipc::protocol) — V2/V3 request/response enums and the
|
||||
//! initial runner handshake.
|
||||
//! - [`transport`](crate::ipc::transport) — length-framed bincode over a local
|
||||
//! socket; enforces `MAX_MESSAGE_SIZE`.
|
||||
//! - [`client`](crate::ipc::client) — plugin-side V2/V3 client and `HostApi`
|
||||
//! proxy.
|
||||
//! - [`server`](crate::ipc::server) — host-side handler that applies a
|
||||
//! `PluginRequest` to a `HostApi` implementation.
|
||||
//! - [`v4`](crate::ipc::v4) — multiplexed V4 frames, notifications, and
|
||||
//! correlation ids.
|
||||
//! - [`proxy`](crate::ipc::proxy) — optional TCP proxy so plugin child
|
||||
//! processes can forward requests to the host.
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
pub mod client;
|
||||
|
||||
@@ -4,6 +4,16 @@
|
||||
//! (expecting a response) or a response (to a previous request). This lets the
|
||||
//! host handle plugin RPCs inline while it waits for the result of a host→plugin
|
||||
//! request such as `Dispatch`, avoiding the need for two sockets or threads.
|
||||
//!
|
||||
//! Compatibility rule: new variants are appended at the end of every public enum
|
||||
//! (`HostRequest`, `HostResponse`, `PluginRequest`, `PluginResponse`,
|
||||
//! `RunnerHandshake`) so older plugins keep their bincode discriminant indices.
|
||||
//! The V4 additions are a separate frame layer in [`crate::ipc::v4`] and do not
|
||||
//! alter these enums.
|
||||
//!
|
||||
//! The pre-shared runner token is delivered through [`PLUGIN_TOKEN_ENV`]
|
||||
//! (`OCS_PLUGIN_TOKEN`). The runner must present the same token immediately
|
||||
//! after connecting or the host closes the connection.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
//! Length-framed transport over `interprocess::local_socket` streams.
|
||||
//!
|
||||
//! Messages are serialized with `bincode`, prefixed by a little-endian `u64`
|
||||
//! length, and sent over the stream. The receiver parses the length, bounds it
|
||||
//! against [`MAX_MESSAGE_SIZE`], then deserializes the payload.
|
||||
//!
|
||||
//! [`send`] and [`recv`] are synchronous and block until the full frame is read
|
||||
//! or the peer disconnects. `Disconnected` is returned on clean EOF; `TooLarge`
|
||||
//! rejects messages that exceed 64 MiB to protect host/runner memory.
|
||||
|
||||
use std::io::{Read, Write};
|
||||
|
||||
|
||||
@@ -761,7 +761,6 @@ impl DocumentReader for EmptyDocumentReader {
|
||||
#[cfg(all(test, feature = "host"))]
|
||||
mod tests {
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
use std::sync::Mutex as StdMutex;
|
||||
use std::thread;
|
||||
|
||||
use interprocess::local_socket::{
|
||||
@@ -772,10 +771,9 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::ipc::transport::recv;
|
||||
use crate::ipc::v4::protocol::{HostToPluginV4, PluginToHostV4};
|
||||
use crate::test_lock::ENV_LOCK;
|
||||
use acadrust::entities::Point;
|
||||
|
||||
static ENV_LOCK: StdMutex<()> = StdMutex::new(());
|
||||
|
||||
fn unique_socket_name() -> String {
|
||||
static COUNTER: AtomicU64 = AtomicU64::new(0);
|
||||
let n = COUNTER.fetch_add(1, Ordering::Relaxed);
|
||||
|
||||
@@ -4,6 +4,15 @@
|
||||
//! requests, responses, and best-effort notifications over a single local
|
||||
//! socket. The V3 files (`src/ipc/{protocol,client,server}.rs`) are left
|
||||
//! untouched; all V4 logic lives in this module.
|
||||
//!
|
||||
//! Submodules:
|
||||
//!
|
||||
//! - [`protocol`](crate::ipc::v4::protocol) — V4 wire frames, notification
|
||||
//! envelopes, and correlation ids.
|
||||
//! - [`client`](crate::ipc::v4::client) — plugin-side V4 client loop and
|
||||
//! notification dispatch.
|
||||
//! - [`server`](crate::ipc::v4::server) — host-side V4 connection and reader
|
||||
//! thread.
|
||||
|
||||
pub mod client;
|
||||
pub mod protocol;
|
||||
|
||||
@@ -1,4 +1,23 @@
|
||||
//! V4 wire frames and envelope types.
|
||||
//!
|
||||
//! V4 replaces the simple request/response pipe with a multiplexed frame layer.
|
||||
//! Every request and response carries a monotonically increasing correlation
|
||||
//! `id` so a plugin can send/receive out of order. Notifications carry an
|
||||
//! optional `command_id` so a plugin can associate a host notification with the
|
||||
//! long-running command that caused it.
|
||||
//!
|
||||
//! The two frame enums are:
|
||||
//!
|
||||
//! - [`HostToPluginV4`] — host → runner requests, responses to runner requests,
|
||||
//! and host notifications.
|
||||
//! - [`PluginToHostV4`] — runner → host requests, responses to host requests,
|
||||
//! and plugin notifications.
|
||||
//!
|
||||
//! Notifications are wrapped in [`NotificationEnvelope`] and are best-effort:
|
||||
//! a process that fails to accept a notification is logged and skipped, but the
|
||||
//! connection stays alive. Unknown host-notification discriminants deserialize
|
||||
//! to [`crate::host::HostNotification::Unknown`] so newer host notifications do
|
||||
//! not break older plugins.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
||||
Reference in new issue
Block a user