systemprompt_runtime/context/
mod.rs1use std::sync::{Arc, OnceLock};
11
12use tokio::task::JoinHandle;
13
14use systemprompt_agent::repository::A2ARepositories;
15use systemprompt_ai::repository::AiRepositories;
16use systemprompt_analytics::repository::AnalyticsRepositories;
17use systemprompt_analytics::{AnalyticsService, FingerprintRepository, GeoIpReader};
18use systemprompt_content::repository::ContentRepositories;
19use systemprompt_database::{DbPool, ServiceRepository};
20use systemprompt_extension::ExtensionRegistry;
21use systemprompt_files::FileRepository;
22use systemprompt_marketplace::MarketplaceFilter;
23use systemprompt_mcp::repository::McpSessionRepository;
24use systemprompt_mcp::services::registry::RegistryService;
25use systemprompt_models::services::SystemAdmin;
26use systemprompt_models::{AppPaths, Config, ContentConfigRaw, ContentRouting, RouteClassifier};
27use systemprompt_oauth::repository::OAuthRepositories;
28use systemprompt_security::authz::SharedAuthzHook;
29use systemprompt_users::{UserRepository, UserService};
30
31mod context_loaders;
32mod debug_impls;
33
34use crate::builder::AppContextBuilder;
35use crate::error::RuntimeResult;
36use crate::registry::ModuleApiRegistry;
37
38#[derive(Clone)]
43pub struct DataPlane {
44 pub database: DbPool,
45 pub analytics_service: Arc<AnalyticsService>,
46 pub fingerprint_repo: Option<Arc<FingerprintRepository>>,
47 pub user_service: Option<Arc<UserService>>,
48 pub a2a_repositories: Arc<A2ARepositories>,
49 pub content_repositories: Arc<ContentRepositories>,
50 pub oauth_repositories: Arc<OAuthRepositories>,
51 pub user_repository: Arc<UserRepository>,
52 pub service_repository: Arc<ServiceRepository>,
53 pub ai_repositories: Arc<AiRepositories>,
54 pub analytics_repositories: Arc<AnalyticsRepositories>,
55 pub file_repository: Arc<FileRepository>,
56 pub mcp_session_repository: Arc<McpSessionRepository>,
57}
58
59#[derive(Clone)]
60pub struct ConfigPlane {
61 pub config: Arc<Config>,
62 pub app_paths: Arc<AppPaths>,
63 pub content_config: Option<Arc<ContentConfigRaw>>,
64 pub route_classifier: Arc<RouteClassifier>,
65}
66
67#[derive(Clone)]
68pub struct Plugins {
69 pub extension_registry: Arc<ExtensionRegistry>,
70 pub api_registry: Arc<ModuleApiRegistry>,
71 pub mcp_registry: RegistryService,
72 pub marketplace_filter: Arc<dyn MarketplaceFilter>,
73}
74
75#[derive(Clone)]
76pub struct Subsystems {
77 pub system_admin: Arc<SystemAdmin>,
78 pub authz_hook: SharedAuthzHook,
79 pub event_bridge: Arc<OnceLock<JoinHandle<()>>>,
80 pub geoip_reader: Option<GeoIpReader>,
81}
82
83#[derive(Clone)]
95pub struct AppContext {
96 pub(crate) data: DataPlane,
97 pub(crate) cfg: ConfigPlane,
98 pub(crate) plugins: Plugins,
99 pub(crate) subsystems: Subsystems,
100}
101
102impl AppContext {
103 pub async fn new() -> RuntimeResult<Self> {
104 Self::builder().build().await
105 }
106
107 #[must_use]
108 pub fn builder() -> AppContextBuilder {
109 AppContextBuilder::new()
110 }
111
112 #[must_use]
113 pub const fn from_parts(
114 data: DataPlane,
115 cfg: ConfigPlane,
116 plugins: Plugins,
117 subsystems: Subsystems,
118 ) -> Self {
119 Self {
120 data,
121 cfg,
122 plugins,
123 subsystems,
124 }
125 }
126
127 pub fn load_geoip_database(
128 config: &Config,
129 show_warnings: bool,
130 ) -> Result<Option<GeoIpReader>, crate::error::RuntimeError> {
131 context_loaders::load_geoip_database(config, show_warnings)
132 }
133
134 pub fn load_content_config(
135 config: &Config,
136 app_paths: &AppPaths,
137 ) -> Option<Arc<ContentConfigRaw>> {
138 context_loaders::load_content_config(config, app_paths)
139 }
140
141 pub fn config(&self) -> &Config {
142 &self.cfg.config
143 }
144
145 pub fn content_config(&self) -> Option<&ContentConfigRaw> {
146 self.cfg.content_config.as_ref().map(AsRef::as_ref)
147 }
148
149 pub fn content_routing(&self) -> Option<Arc<dyn ContentRouting>> {
150 let concrete = Arc::clone(self.cfg.content_config.as_ref()?);
151 let routing: Arc<dyn ContentRouting> = concrete;
152 Some(routing)
153 }
154
155 pub const fn db_pool(&self) -> &DbPool {
156 &self.data.database
157 }
158
159 pub fn api_registry(&self) -> &ModuleApiRegistry {
160 &self.plugins.api_registry
161 }
162
163 pub fn extension_registry(&self) -> &ExtensionRegistry {
164 &self.plugins.extension_registry
165 }
166
167 pub fn server_address(&self) -> String {
168 format!("{}:{}", self.cfg.config.host, self.cfg.config.port)
169 }
170
171 pub const fn geoip_reader(&self) -> Option<&GeoIpReader> {
172 self.subsystems.geoip_reader.as_ref()
173 }
174
175 pub const fn analytics_service(&self) -> &Arc<AnalyticsService> {
176 &self.data.analytics_service
177 }
178
179 #[must_use]
180 pub fn session_usage(&self) -> systemprompt_traits::DynSessionUsageCounters {
181 Arc::new(self.data.analytics_service.session_repo().clone())
182 }
183
184 pub fn context_materializer(&self) -> systemprompt_traits::DynContextMaterializer {
185 Arc::new(systemprompt_agent::services::ContextProviderService::new(
186 self.data.a2a_repositories.contexts.clone(),
187 ))
188 }
189
190 pub const fn a2a_repositories(&self) -> &Arc<A2ARepositories> {
191 &self.data.a2a_repositories
192 }
193
194 pub const fn content_repositories(&self) -> &Arc<ContentRepositories> {
195 &self.data.content_repositories
196 }
197
198 pub const fn oauth_repositories(&self) -> &Arc<OAuthRepositories> {
199 &self.data.oauth_repositories
200 }
201
202 pub const fn user_repository(&self) -> &Arc<UserRepository> {
203 &self.data.user_repository
204 }
205
206 pub const fn service_repository(&self) -> &Arc<ServiceRepository> {
207 &self.data.service_repository
208 }
209
210 pub const fn ai_repositories(&self) -> &Arc<AiRepositories> {
211 &self.data.ai_repositories
212 }
213
214 pub const fn analytics_repositories(&self) -> &Arc<AnalyticsRepositories> {
215 &self.data.analytics_repositories
216 }
217
218 pub const fn file_repository(&self) -> &Arc<FileRepository> {
219 &self.data.file_repository
220 }
221
222 pub const fn mcp_session_repository(&self) -> &Arc<McpSessionRepository> {
223 &self.data.mcp_session_repository
224 }
225
226 pub const fn route_classifier(&self) -> &Arc<RouteClassifier> {
227 &self.cfg.route_classifier
228 }
229
230 pub fn app_paths(&self) -> &AppPaths {
231 &self.cfg.app_paths
232 }
233
234 pub const fn app_paths_arc(&self) -> &Arc<AppPaths> {
235 &self.cfg.app_paths
236 }
237
238 pub fn marketplace_filter(&self) -> &Arc<dyn MarketplaceFilter> {
239 &self.plugins.marketplace_filter
240 }
241
242 pub const fn event_bridge(&self) -> &Arc<OnceLock<JoinHandle<()>>> {
243 &self.subsystems.event_bridge
244 }
245
246 pub fn system_admin(&self) -> &SystemAdmin {
247 &self.subsystems.system_admin
248 }
249
250 pub const fn mcp_registry(&self) -> &RegistryService {
251 &self.plugins.mcp_registry
252 }
253
254 pub const fn authz_hook(&self) -> &SharedAuthzHook {
255 &self.subsystems.authz_hook
256 }
257}