Skip to main content

relay_knowledge/application/runtime/
mod.rs

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