mirror of
https://github.com/ruvnet/RuView
synced 2026-08-04 19:31:42 +00:00
feat(homecore-plugins/p1): ADR-128 plugin runtime scaffold
Adds `v2/crates/homecore-plugins` (0.1.0-alpha.0) — the P1 scaffold for the HOMECORE-PLUGINS WASM integration system (ADR-128): - `manifest.rs`: `PluginManifest` — superset of HA manifest.json; serde round-trip + required-field validation (`domain`/`name`/`version`). - `error.rs`: `PluginError` typed enum (InvalidManifest, AlreadyLoaded, NotFound, RuntimeError, SetupFailed, UnloadFailed, Io). - `plugin.rs`: `HomeCorePlugin` async trait + `PluginId` newtype. - `runtime.rs`: `PluginRuntime` trait + `InProcessRuntime` (native Rust, first-party plugins). `WasmtimeRuntime` stub gated on `--features wasmtime` (default-off; 30 MB dep deferred to P2). - `registry.rs`: `PluginRegistry<R>` — load/unload/list/contains via RwLock. - 10 unit tests, 0 failed. Wasmtime vs wasm3 runtime selection is still open (ADR-128 §8 Q2); this scaffold makes the choice swappable via the `PluginRuntime` trait. The `wasmtime` and `wasm3` features are default-off; P2 resolves the choice and wires host ABI (`hc_state_get`/`hc_state_set`/etc.) to ADR-127. Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
//! `HomeCorePlugin` trait + `PluginId` newtype.
|
||||
//!
|
||||
//! Every first-party and third-party HOMECORE integration must implement
|
||||
//! `HomeCorePlugin`. P1 provides an in-process native Rust implementation;
|
||||
//! the WASM ABI wrapper (which maps the WASM exports `setup_entry`,
|
||||
//! `call_service_handler`, `receive_event` to this trait) lands in P2.
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use homecore::HomeCore;
|
||||
|
||||
use crate::error::PluginError;
|
||||
|
||||
/// Unique identifier for a loaded plugin — mirrors the `domain` field of
|
||||
/// the plugin's `PluginManifest` (e.g. `"mqtt"`, `"homecore_lights"`).
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct PluginId(pub String);
|
||||
|
||||
impl PluginId {
|
||||
/// Create a new `PluginId` from any string-like value.
|
||||
pub fn new(s: impl Into<String>) -> Self {
|
||||
Self(s.into())
|
||||
}
|
||||
|
||||
/// Return the inner domain string.
|
||||
pub fn as_str(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for PluginId {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Lifecycle trait that every HOMECORE integration must implement.
|
||||
///
|
||||
/// Implementing types are passed to [`PluginRuntime::load`]; the runtime
|
||||
/// calls these methods at the appropriate lifecycle points.
|
||||
///
|
||||
/// # Async
|
||||
/// Both methods are `async` to allow network / IO initialisation without
|
||||
/// blocking the Tokio runtime. The `async_trait` macro erases the `impl`
|
||||
/// return type so it works in trait objects.
|
||||
#[async_trait]
|
||||
pub trait HomeCorePlugin: Send + Sync + 'static {
|
||||
/// Called once when the plugin's config entry is being set up.
|
||||
///
|
||||
/// The plugin receives a reference to the `HomeCore` runtime and should
|
||||
/// register its entities, services, and event subscriptions here.
|
||||
async fn setup(&self, hc: HomeCore) -> Result<(), PluginError>;
|
||||
|
||||
/// Called when the plugin is being removed from the registry.
|
||||
///
|
||||
/// The plugin should clean up subscriptions and deregister its entities.
|
||||
async fn unload(&self) -> Result<(), PluginError>;
|
||||
}
|
||||
Reference in New Issue
Block a user