feat(homecore-server): seed 13 default services across 6 domains on boot
Operators (and the new web UI) saw "No services registered" on every vanilla boot because nothing in the boot sequence called `ServiceRegistry::register()`. The Assist pipeline registers intent handlers — a different surface — but `/api/services` stayed empty until a plugin or integration loaded. Adds `seed_default_services()` after `HomeCore::new()`. Each handler is a `FnHandler` that echoes the call back as a JSON acknowledgement so the service registry is exercise-able from day one. Integrations override these by re-registering the same `ServiceName` with a real handler later. Seeded set: homeassistant: restart, stop, reload_core_config light: turn_on, turn_off, toggle switch: turn_on, turn_off, toggle scene: apply automation: trigger homecore: ping, snapshot_state (HOMECORE-native) Boot log now reports: Service registry seeded with 13 default service(s) GET /api/services now returns 6 domains with 13 services total. The HOMECORE web UI's Services page shows them under proper domain headings. Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
parent
4253c0e4fc
commit
75f984e515
|
|
@ -25,7 +25,8 @@ use anyhow::Result;
|
|||
use clap::Parser;
|
||||
use tracing::{info, warn};
|
||||
|
||||
use homecore::HomeCore;
|
||||
use homecore::{HomeCore, ServiceCall, ServiceError, ServiceName};
|
||||
use homecore::service::FnHandler;
|
||||
use homecore_api::{router, LongLivedTokenStore, SharedState};
|
||||
use homecore_assist::pipeline::default_pipeline;
|
||||
use homecore_assist::RegexIntentRecognizer;
|
||||
|
|
@ -66,6 +67,13 @@ async fn main() -> Result<()> {
|
|||
let hc = HomeCore::new();
|
||||
info!("HomeCore state machine + event bus + service registry online");
|
||||
|
||||
// Seed a representative set of built-in services so the web UI
|
||||
// and HA-wire-compat clients see a populated /api/services on
|
||||
// first boot. These are no-op handlers (they just echo back the
|
||||
// call as JSON for observability) — integrations override them
|
||||
// by registering the same ServiceName later.
|
||||
seed_default_services(&hc).await;
|
||||
|
||||
// ── 2. Recorder (optional) ──────────────────────────────────────
|
||||
if !cli.no_recorder {
|
||||
match Recorder::open(&cli.db).await {
|
||||
|
|
@ -154,3 +162,50 @@ fn init_tracing() {
|
|||
)
|
||||
.init();
|
||||
}
|
||||
|
||||
/// Register a representative set of built-in services so `/api/services`
|
||||
/// is non-empty on first boot. Each handler simply echoes the call back
|
||||
/// as a JSON acknowledgement — integrations override these by
|
||||
/// re-registering the same `ServiceName` with a real handler later.
|
||||
///
|
||||
/// The set covers the HA wire-compat "starter pack" (homeassistant /
|
||||
/// light / switch / scene / automation domains) plus a `homecore.*`
|
||||
/// domain so operators can see HOMECORE-native services distinguished
|
||||
/// from the HA-compat ones.
|
||||
async fn seed_default_services(hc: &HomeCore) {
|
||||
let echo = || FnHandler(|call: ServiceCall| async move {
|
||||
Ok(serde_json::json!({
|
||||
"called": format!("{}.{}", call.name.domain, call.name.service),
|
||||
"service_data": call.data,
|
||||
"acknowledged": true,
|
||||
}))
|
||||
});
|
||||
|
||||
let svcs = [
|
||||
// Conventional HA wire-compat services
|
||||
("homeassistant", "restart"),
|
||||
("homeassistant", "stop"),
|
||||
("homeassistant", "reload_core_config"),
|
||||
("light", "turn_on"),
|
||||
("light", "turn_off"),
|
||||
("light", "toggle"),
|
||||
("switch", "turn_on"),
|
||||
("switch", "turn_off"),
|
||||
("switch", "toggle"),
|
||||
("scene", "apply"),
|
||||
("automation", "trigger"),
|
||||
// HOMECORE-native services
|
||||
("homecore", "ping"),
|
||||
("homecore", "snapshot_state"),
|
||||
];
|
||||
|
||||
for (domain, service) in svcs {
|
||||
hc.services()
|
||||
.register(ServiceName::new(domain, service), echo())
|
||||
.await;
|
||||
}
|
||||
|
||||
let count = hc.services().registered_services().await.len();
|
||||
let _ = ServiceError::NotRegistered { domain: String::new(), service: String::new() };
|
||||
info!("Service registry seeded with {} default service(s)", count);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue