# shepherd-api Protocol types for Shepherd IPC communication. ## Overview This crate defines the stable API between the Shepherd service (`shepherdd`) and its clients (launcher UI, HUD overlay, admin tools). It contains: - **Commands** - Requests from clients to the service - **Responses** - Service replies to commands - **Events** - Asynchronous notifications from service to clients - **Shared types** - Entry views, session info, reason codes, etc. ## Purpose `shepherd-api` establishes the contract between components, ensuring: 1. **Stability** - Versioned protocol with backward compatibility 2. **Type safety** - Strongly typed messages prevent protocol errors 3. **Decoupling** - Clients and service can evolve independently ## API Version ```rust use shepherd_api::API_VERSION; // Current API version assert_eq!(API_VERSION, 1); ``` ## Key Types ### Commands Commands are requests sent by clients to the service: ```rust use shepherd_api::Command; // Request available entries let cmd = Command::ListEntries; // Request to launch an entry let cmd = Command::Launch { entry_id: "minecraft".into() }; // Request to stop current session let cmd = Command::StopCurrent { mode: StopMode::Graceful }; // Subscribe to real-time events let cmd = Command::SubscribeEvents; ``` Available commands: - `GetState` - Get full service state snapshot - `ListEntries` - List all entries with availability - `Launch { entry_id }` - Launch an entry - `StopCurrent { mode }` - Stop the current session - `ReloadConfig` - Reload configuration (admin only) - `SubscribeEvents` - Subscribe to event stream - `GetHealth` - Get service health status - `SetVolume { level }` - Set system volume - `GetVolume` - Get current volume ### Events Events are pushed from the service to subscribed clients: ```rust use shepherd_api::{Event, EventPayload}; // Events received by clients match event.payload { EventPayload::StateChanged(snapshot) => { /* Update UI */ } EventPayload::SessionStarted(info) => { /* Show HUD */ } EventPayload::WarningIssued { threshold, remaining, severity, message } => { /* Alert user */ } EventPayload::SessionExpired { session_id } => { /* Time's up */ } EventPayload::SessionEnded { session_id, reason } => { /* Return to launcher */ } EventPayload::PolicyReloaded { entry_count } => { /* Refresh entry list */ } EventPayload::VolumeChanged(info) => { /* Update volume display */ } } ``` ### Entry Views Entries as presented to UIs: ```rust use shepherd_api::EntryView; let view: EntryView = /* from service */; if view.enabled { // Entry can be launched println!("Max run time: {:?}", view.max_run_if_started_now); } else { // Entry unavailable, show reasons for reason in &view.reasons { match reason { ReasonCode::OutsideTimeWindow { next_window_start } => { /* ... */ } ReasonCode::QuotaExhausted { used, quota } => { /* ... */ } ReasonCode::CooldownActive { available_at } => { /* ... */ } ReasonCode::SessionActive { entry_id, remaining } => { /* ... */ } ReasonCode::InternetUnavailable { check } => { /* ... */ } // ... } } } ``` ### Session Info Information about active sessions: ```rust use shepherd_api::{SessionInfo, SessionState}; let session: SessionInfo = /* from snapshot */; match session.state { SessionState::Launching => { /* Show spinner */ } SessionState::Running => { /* Show countdown */ } SessionState::Warned => { /* Highlight urgency */ } SessionState::Expiring => { /* Terminating... */ } SessionState::Ended => { /* Session over */ } } ``` ### Reason Codes Structured explanations for unavailability: - `OutsideTimeWindow` - Not within allowed time window - `QuotaExhausted` - Daily time limit reached - `CooldownActive` - Must wait after previous session - `SessionActive` - Another session is running - `UnsupportedKind` - Host doesn't support this entry type - `Disabled` - Entry explicitly disabled in config ## Design Philosophy - **Service is authoritative** - Clients display state, service enforces policy - **Structured reasons** - UIs can explain "why is this unavailable?" - **Event-driven** - Clients subscribe and react to changes - **Serializable** - All types derive `Serialize`/`Deserialize` for JSON transport ## Dependencies - `serde` - Serialization/deserialization - `chrono` - Timestamp types - `shepherd-util` - ID types