Skip to main content

relay_knowledge/application/runtime/
mod.rs

1use std::{error::Error, fmt, path::PathBuf};
2
3use crate::{
4    env::{EnvError, EnvironmentConfig, windows_system_root_from_process},
5    net::{NetworkConfig, NetworkConfigError, NetworkRuntime, NetworkRuntimeError},
6    observability::{ObservabilityRuntime, TelemetryConfig},
7    paths::{PathError, RuntimePaths, windows_tasklist_command},
8    retrieval::ReadModelBackendConfig,
9};
10
11use super::update::{UpdateRuntimeConfig, UpdateRuntimeConfigError};
12use retrieval::retrieval_config_from_environment;
13
14mod agent;
15mod file_index;
16mod retrieval;
17mod status;
18mod storage;
19mod worker;
20
21pub use agent::{AgentRuntimeConfig, AgentRuntimeConfigError};
22pub use file_index::{FileIndexRootConfig, FileIndexRuntimeConfig, FileIndexRuntimeConfigError};
23pub use retrieval::RetrievalRuntimeConfigError;
24pub(super) use status::{
25    agent_protocol_status, runtime_status, runtime_status_with_model_profiles,
26};
27pub use storage::{StorageRuntimeConfig, StorageRuntimeConfigError};
28pub use worker::{WorkerRuntimeConfig, WorkerRuntimeConfigError};
29
30/// Resolved foundation configuration shared by all interfaces.
31#[derive(Debug, Clone)]
32pub struct RuntimeConfiguration {
33    pub paths: RuntimePaths,
34    pub process: ProcessRuntimeConfig,
35    pub network: NetworkRuntime,
36    pub observability: ObservabilityRuntime,
37    pub agent: AgentRuntimeConfig,
38    pub retrieval: ReadModelBackendConfig,
39    pub workers: WorkerRuntimeConfig,
40    pub file_index: FileIndexRuntimeConfig,
41    pub updates: UpdateRuntimeConfig,
42    pub storage: StorageRuntimeConfig,
43    pub watcher: crate::watcher::WatcherConfig,
44}
45
46impl RuntimeConfiguration {
47    /// Resolves runtime configuration from the current process environment.
48    pub async fn from_process_environment() -> Result<Self, RuntimeConfigurationError> {
49        let environment =
50            EnvironmentConfig::from_process().map_err(RuntimeConfigurationError::Environment)?;
51        let mut runtime = Self::from_environment(&environment).await?;
52        runtime.process =
53            ProcessRuntimeConfig::from_system_root(windows_system_root_from_process());
54
55        Ok(runtime)
56    }
57
58    /// Resolves runtime configuration from a typed environment snapshot.
59    pub async fn from_environment(
60        environment: &EnvironmentConfig,
61    ) -> Result<Self, RuntimeConfigurationError> {
62        let network = NetworkConfig::from_overrides(&environment.network)
63            .map_err(RuntimeConfigurationError::Network)?;
64        let observability =
65            ObservabilityRuntime::new(TelemetryConfig::from_environment(&environment.telemetry));
66        let agent = AgentRuntimeConfig::from_environment(environment, network.http.request_timeout)
67            .map_err(RuntimeConfigurationError::Agent)?;
68        let retrieval = retrieval_config_from_environment(&environment.retrieval)
69            .map_err(RuntimeConfigurationError::Retrieval)?;
70        let workers = WorkerRuntimeConfig::from_environment(environment)
71            .map_err(RuntimeConfigurationError::Workers)?;
72        let file_index = FileIndexRuntimeConfig::from_environment(environment)
73            .map_err(RuntimeConfigurationError::FileIndex)?;
74        let updates = UpdateRuntimeConfig::from_environment(&environment.updates)
75            .map_err(RuntimeConfigurationError::Updates)?;
76        let storage = StorageRuntimeConfig::from_environment(environment)
77            .map_err(RuntimeConfigurationError::Storage)?;
78
79        let watcher = crate::watcher::WatcherConfig::from_environment(&environment.watcher);
80
81        Ok(Self {
82            paths: RuntimePaths::resolve(&environment.platform, &environment.paths)
83                .map_err(RuntimeConfigurationError::Paths)?,
84            process: ProcessRuntimeConfig::default(),
85            network: NetworkRuntime::from_config(network),
86            observability,
87            agent,
88            retrieval,
89            workers,
90            file_index,
91            updates,
92            storage,
93            watcher,
94        })
95    }
96}
97
98/// Resolved process integration paths captured during runtime bootstrap.
99#[derive(Debug, Clone, PartialEq, Eq)]
100pub struct ProcessRuntimeConfig {
101    pub windows_tasklist_command: PathBuf,
102}
103
104impl Default for ProcessRuntimeConfig {
105    fn default() -> Self {
106        Self::from_system_root(None)
107    }
108}
109
110impl ProcessRuntimeConfig {
111    fn from_system_root(system_root: Option<std::ffi::OsString>) -> Self {
112        Self {
113            windows_tasklist_command: windows_tasklist_command(system_root.as_deref()),
114        }
115    }
116}
117
118/// Error raised while composing foundational runtime configuration.
119#[derive(Debug, Clone, PartialEq, Eq)]
120pub enum RuntimeConfigurationError {
121    Environment(EnvError),
122    Paths(PathError),
123    Network(NetworkConfigError),
124    NetworkRuntime(NetworkRuntimeError),
125    Agent(AgentRuntimeConfigError),
126    Retrieval(RetrievalRuntimeConfigError),
127    Workers(WorkerRuntimeConfigError),
128    FileIndex(FileIndexRuntimeConfigError),
129    Updates(UpdateRuntimeConfigError),
130    Storage(StorageRuntimeConfigError),
131}
132
133impl fmt::Display for RuntimeConfigurationError {
134    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
135        match self {
136            Self::Environment(error) => write!(formatter, "{error}"),
137            Self::Paths(error) => write!(formatter, "{error}"),
138            Self::Network(error) => write!(formatter, "{error}"),
139            Self::NetworkRuntime(error) => write!(formatter, "{error}"),
140            Self::Agent(error) => write!(formatter, "{error}"),
141            Self::Retrieval(error) => write!(formatter, "{error}"),
142            Self::Workers(error) => write!(formatter, "{error}"),
143            Self::FileIndex(error) => write!(formatter, "{error}"),
144            Self::Updates(error) => write!(formatter, "{error}"),
145            Self::Storage(error) => write!(formatter, "{error}"),
146        }
147    }
148}
149
150impl Error for RuntimeConfigurationError {}