Skip to main content

oxios_kernel/kernel_handle/
infra_api.rs

1//! Infra API — Git, cron, resources, events, system.
2
3use crate::ToolMeta;
4use crate::config::OxiosConfig;
5use crate::cron::{CronJob, CronJobUpdate, CronScheduler};
6use crate::event_bus::{EventBus, KernelEvent};
7use crate::git_layer::{GitLayer, LogEntry};
8use crate::resource_monitor::{ResourceMonitor, ResourceSnapshot};
9use crate::tools::{PendingAskUser, PendingToolApprovals, known_tools};
10use std::sync::Arc;
11use std::time::{Duration, Instant};
12
13/// Infrastructure system calls.
14pub struct InfraApi {
15    pub(crate) git_layer: Arc<GitLayer>,
16    pub(crate) cron_scheduler: Arc<CronScheduler>,
17    pub(crate) resource_monitor: Arc<ResourceMonitor>,
18    pub(crate) event_bus: EventBus,
19    pub(crate) config: OxiosConfig,
20    pub(crate) start_time: Instant,
21    /// Hot-reloadable orchestrator config (evolution iterations, score threshold).
22    pub(crate) orchestrator_config: parking_lot::RwLock<crate::config::OrchestratorConfig>,
23    /// Pending tool approval requests (HitL escalation).
24    pub(crate) pending_tool_approvals: PendingToolApprovals,
25    /// Pending `ask_user` requests (RFC-027 agent-driven clarification).
26    pub(crate) pending_ask_user: Arc<PendingAskUser>,
27}
28
29impl InfraApi {
30    /// Create a new InfraApi.
31    pub fn new(
32        git_layer: Arc<GitLayer>,
33        cron_scheduler: Arc<CronScheduler>,
34        resource_monitor: Arc<ResourceMonitor>,
35        event_bus: EventBus,
36        config: OxiosConfig,
37        start_time: Instant,
38    ) -> Self {
39        Self {
40            git_layer,
41            cron_scheduler,
42            resource_monitor,
43            event_bus,
44            config,
45            start_time,
46            orchestrator_config: parking_lot::RwLock::new(
47                crate::config::OrchestratorConfig::default(),
48            ),
49            pending_tool_approvals: PendingToolApprovals::new(),
50            pending_ask_user: Arc::new(PendingAskUser::new()),
51        }
52    }
53    /// Get a reference to the GitLayer.
54    pub fn git(&self) -> &GitLayer {
55        &self.git_layer
56    }
57
58    /// Get commit log.
59    pub fn git_log(&self, max: usize) -> anyhow::Result<Vec<LogEntry>> {
60        self.git_layer.log(max)
61    }
62
63    /// Tag current state.
64    pub fn git_tag(&self, name: &str, message: &str) -> anyhow::Result<()> {
65        self.git_layer.tag(name, message)
66    }
67
68    /// Restore file from commit.
69    pub fn git_restore(&self, path: &str, hash: &str) -> anyhow::Result<()> {
70        self.git_layer.restore_file(path, hash)
71    }
72
73    /// Verify git repository integrity.
74    pub fn git_verify(&self) -> anyhow::Result<bool> {
75        self.git_layer.verify()
76    }
77
78    /// List git tags.
79    pub fn git_tags(&self) -> anyhow::Result<Vec<String>> {
80        self.git_layer.list_tags()
81    }
82
83    /// Add a cron job.
84    pub async fn add_cron(&self, job: CronJob) -> anyhow::Result<uuid::Uuid> {
85        self.cron_scheduler.add_job(job).await
86    }
87
88    /// Get a cron job by ID.
89    pub fn get_cron(&self, id: uuid::Uuid) -> Option<CronJob> {
90        self.cron_scheduler.get_job(id)
91    }
92
93    /// Update a cron job.
94    pub async fn update_cron(&self, id: uuid::Uuid, update: CronJobUpdate) -> anyhow::Result<()> {
95        self.cron_scheduler.update_job(id, update).await
96    }
97
98    /// Remove a cron job by ID.
99    pub async fn remove_cron(&self, id: uuid::Uuid) -> anyhow::Result<()> {
100        self.cron_scheduler.remove_job(id).await
101    }
102
103    /// Trigger a cron job manually.
104    pub fn trigger_cron(&self, id: uuid::Uuid) -> anyhow::Result<CronJob> {
105        self.cron_scheduler.trigger_job(id)
106    }
107
108    /// Mark cron job completed.
109    pub async fn complete_cron(&self, id: uuid::Uuid, success: bool, summary: String) {
110        self.cron_scheduler
111            .mark_job_completed(id, success, summary)
112            .await
113    }
114
115    /// List all cron jobs.
116    pub fn list_crons(&self) -> Vec<CronJob> {
117        self.cron_scheduler.list_jobs()
118    }
119
120    /// Get resource snapshot.
121    pub fn resource_snapshot(&self) -> ResourceSnapshot {
122        self.resource_monitor.snapshot()
123    }
124
125    /// Get resource history snapshots.
126    pub fn resource_history(&self, last_n: usize) -> Vec<ResourceSnapshot> {
127        self.resource_monitor.history(last_n)
128    }
129
130    /// Check if system is overloaded.
131    pub fn is_overloaded(&self) -> bool {
132        self.resource_monitor.is_overloaded()
133    }
134
135    /// Subscribe to kernel events.
136    pub fn subscribe(&self) -> tokio::sync::broadcast::Receiver<KernelEvent> {
137        self.event_bus.subscribe()
138    }
139
140    /// Publish a kernel event.
141    pub fn publish(&self, event: KernelEvent) -> anyhow::Result<()> {
142        self.event_bus
143            .publish(event)
144            .map_err(|e| anyhow::anyhow!("broadcast error: {e}"))
145    }
146
147    /// Get config reference.
148    pub fn config(&self) -> &OxiosConfig {
149        &self.config
150    }
151
152    /// Resource monitor reference — for hot-reload config propagation.
153    pub fn resource_monitor(&self) -> &Arc<ResourceMonitor> {
154        &self.resource_monitor
155    }
156
157    /// Hot-reload orchestrator config (stored in InfraApi for propagation).
158    pub fn update_orchestrator_config(&self, config: crate::config::OrchestratorConfig) {
159        *self.orchestrator_config.write() = config;
160    }
161
162    /// Get system uptime.
163    pub fn uptime(&self) -> Duration {
164        self.start_time.elapsed()
165    }
166
167    /// Access the pending tool approvals registry.
168    pub fn pending_tool_approvals(&self) -> &PendingToolApprovals {
169        &self.pending_tool_approvals
170    }
171
172    /// Access the pending `ask_user` registry (RFC-027 agent-driven clarification).
173    pub fn pending_ask_user(&self) -> Arc<PendingAskUser> {
174        Arc::clone(&self.pending_ask_user)
175    }
176
177    /// Clone the underlying event bus so tools can publish `KernelEvent`s
178    /// without routing through the wrapping `publish` helper.
179    pub fn event_bus_clone(&self) -> EventBus {
180        self.event_bus.clone()
181    }
182
183    /// List all known tool metadata (static catalog).
184    pub fn list_available_tools(&self) -> &'static [ToolMeta] {
185        known_tools()
186    }
187}