4.4 KiB
4.4 KiB
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:
- Stability - Versioned protocol with backward compatibility
- Type safety - Strongly typed messages prevent protocol errors
- Decoupling - Clients and service can evolve independently
API Version
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:
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 snapshotListEntries- List all entries with availabilityLaunch { entry_id }- Launch an entryStopCurrent { mode }- Stop the current sessionReloadConfig- Reload configuration (admin only)SubscribeEvents- Subscribe to event streamGetHealth- Get service health statusSetVolume { level }- Set system volumeGetVolume- Get current volume
Events
Events are pushed from the service to subscribed clients:
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:
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:
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 windowQuotaExhausted- Daily time limit reachedCooldownActive- Must wait after previous sessionSessionActive- Another session is runningUnsupportedKind- Host doesn't support this entry typeDisabled- 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/Deserializefor JSON transport
Dependencies
serde- Serialization/deserializationchrono- Timestamp typesshepherd-util- ID types