systemprompt_runtime/context/
mod.rs1use std::sync::{Arc, OnceLock};
11
12
13use systemprompt_agent::repository::A2ARepositories;
14use systemprompt_ai::repository::AiRepositories;
15use systemprompt_analytics::repository::AnalyticsRepositories;
16use systemprompt_analytics::{AnalyticsService, FingerprintRepository, GeoIpReader};
17use systemprompt_config::paths::AppPaths;
18use systemprompt_content::repository::ContentRepositories;
19use systemprompt_database::{DbPool, SchemaInstallReport, ServiceRepository};
20use systemprompt_events::EventBridgeHandle;
21use systemprompt_extension::ExtensionRegistry;
22use systemprompt_files::FileRepository;
23use systemprompt_marketplace::inventory::PublishGuard;
24use systemprompt_marketplace::managed::ManagedRepository;
25use systemprompt_marketplace::{MarketplaceCache, MarketplaceFilter};
26use systemprompt_mcp::repository::McpSessionRepository;
27use systemprompt_mcp::services::registry::RegistryService;
28use systemprompt_models::services::SystemAdmin;
29use systemprompt_models::{Config, ContentConfigRaw, ContentRouting, RouteClassifier};
30use systemprompt_oauth::repository::OAuthRepositories;
31use systemprompt_security::authz::SharedAuthzHook;
32use systemprompt_security::policy::GovernanceEngine;
33use systemprompt_traits::FileStorage;
34use systemprompt_users::{UserRepository, UserService};
35
36mod context_loaders;
37mod debug_impls;
38mod repositories;
39mod shutdown;
40
41pub use shutdown::ShutdownRequest;
42
43use crate::builder::AppContextBuilder;
44use crate::error::RuntimeResult;
45use crate::registry::ModuleApiRegistry;
46
47#[derive(Clone)]
52pub struct DataPlane {
53 pub database: DbPool,
54 pub analytics_service: Arc<AnalyticsService>,
55 pub fingerprint_repo: Option<Arc<FingerprintRepository>>,
56 pub user_service: Option<Arc<UserService>>,
57 pub a2a_repositories: Arc<A2ARepositories>,
58 pub content_repositories: Arc<ContentRepositories>,
59 pub oauth_repositories: Arc<OAuthRepositories>,
60 pub user_repository: Arc<UserRepository>,
61 pub service_repository: Arc<ServiceRepository>,
62 pub ai_repositories: Arc<AiRepositories>,
63 pub analytics_repositories: Arc<AnalyticsRepositories>,
64 pub feedback_snapshots_repository:
65 Arc<systemprompt_analytics::snapshots::FeedbackSnapshotsRepository>,
66 pub feedback_facts_repository: Arc<systemprompt_analytics::feedback::FeedbackFactsRepository>,
67 pub file_repository: Arc<FileRepository>,
68 pub mcp_session_repository: Arc<McpSessionRepository>,
69 pub managed_repository: Arc<ManagedRepository>,
70}
71
72#[derive(Clone)]
73pub struct ConfigPlane {
74 pub config: Arc<Config>,
75 pub app_paths: Arc<AppPaths>,
76 pub content_config: Option<Arc<ContentConfigRaw>>,
77 pub route_classifier: Arc<RouteClassifier>,
78}
79
80#[derive(Clone)]
81pub struct Plugins {
82 pub extension_registry: Arc<ExtensionRegistry>,
83 pub api_registry: Arc<ModuleApiRegistry>,
84 pub mcp_registry: RegistryService,
85 pub marketplace_filter: Arc<dyn MarketplaceFilter>,
86 pub marketplace_cache: Arc<MarketplaceCache>,
87}
88
89#[derive(Clone)]
90pub struct Subsystems {
91 pub system_admin: Arc<SystemAdmin>,
92 pub authz_hook: SharedAuthzHook,
93 pub governance: Arc<GovernanceEngine>,
94 pub schema_install: Arc<SchemaInstallReport>,
95 pub event_bridge: Arc<OnceLock<EventBridgeHandle>>,
96 pub geoip_reader: Option<GeoIpReader>,
97 pub file_storage: Arc<dyn FileStorage>,
98 pub shutdown: ShutdownRequest,
99 pub publish_guard: Arc<tokio::sync::Mutex<PublishGuard>>,
100 pub snapshot_wakeup: Arc<crate::reporting::SnapshotWakeup>,
101}
102
103#[derive(Clone)]
115pub struct AppContext {
116 pub(crate) data: DataPlane,
117 pub(crate) cfg: ConfigPlane,
118 pub(crate) plugins: Plugins,
119 pub(crate) subsystems: Subsystems,
120}
121
122impl AppContext {
123 pub async fn new() -> RuntimeResult<Self> {
124 Self::builder().build().await
125 }
126
127 #[must_use]
128 pub fn builder() -> AppContextBuilder {
129 AppContextBuilder::new()
130 }
131
132 #[must_use]
133 pub const fn from_parts(
134 data: DataPlane,
135 cfg: ConfigPlane,
136 plugins: Plugins,
137 subsystems: Subsystems,
138 ) -> Self {
139 Self {
140 data,
141 cfg,
142 plugins,
143 subsystems,
144 }
145 }
146
147 pub fn load_geoip_database(
148 config: &Config,
149 show_warnings: bool,
150 ) -> Result<Option<GeoIpReader>, crate::error::RuntimeError> {
151 context_loaders::load_geoip_database(config, show_warnings)
152 }
153
154 pub fn load_content_config(
155 config: &Config,
156 app_paths: &AppPaths,
157 ) -> Option<Arc<ContentConfigRaw>> {
158 context_loaders::load_content_config(config, app_paths)
159 }
160
161 pub fn config(&self) -> &Config {
162 &self.cfg.config
163 }
164
165 pub fn content_config(&self) -> Option<&ContentConfigRaw> {
166 self.cfg.content_config.as_ref().map(AsRef::as_ref)
167 }
168
169 pub fn content_routing(&self) -> Option<Arc<dyn ContentRouting>> {
170 let concrete = Arc::clone(self.cfg.content_config.as_ref()?);
171 let routing: Arc<dyn ContentRouting> = concrete;
172 Some(routing)
173 }
174
175 pub const fn db_pool(&self) -> &DbPool {
176 &self.data.database
177 }
178
179 pub fn api_registry(&self) -> &ModuleApiRegistry {
180 &self.plugins.api_registry
181 }
182
183 pub fn extension_registry(&self) -> &ExtensionRegistry {
184 &self.plugins.extension_registry
185 }
186
187 pub fn server_address(&self) -> String {
188 format!("{}:{}", self.cfg.config.host, self.cfg.config.port)
189 }
190
191 pub const fn geoip_reader(&self) -> Option<&GeoIpReader> {
192 self.subsystems.geoip_reader.as_ref()
193 }
194
195 pub const fn file_storage(&self) -> &Arc<dyn FileStorage> {
196 &self.subsystems.file_storage
197 }
198
199 pub const fn analytics_service(&self) -> &Arc<AnalyticsService> {
200 &self.data.analytics_service
201 }
202
203 #[must_use]
204 pub fn session_usage(&self) -> systemprompt_traits::DynSessionUsageCounters {
205 self.data.analytics_repositories.sessions.owner()
206 }
207
208 pub fn context_materializer(&self) -> systemprompt_traits::DynContextMaterializer {
209 Arc::new(systemprompt_agent::services::ContextProviderService::new(
210 self.data.a2a_repositories.contexts.clone(),
211 ))
212 }
213
214 pub const fn route_classifier(&self) -> &Arc<RouteClassifier> {
215 &self.cfg.route_classifier
216 }
217
218 pub fn app_paths(&self) -> &AppPaths {
219 &self.cfg.app_paths
220 }
221
222 pub const fn app_paths_arc(&self) -> &Arc<AppPaths> {
223 &self.cfg.app_paths
224 }
225
226 pub fn marketplace_filter(&self) -> &Arc<dyn MarketplaceFilter> {
227 &self.plugins.marketplace_filter
228 }
229
230 pub const fn marketplace_cache(&self) -> &Arc<MarketplaceCache> {
231 &self.plugins.marketplace_cache
232 }
233
234 pub const fn event_bridge(&self) -> &Arc<OnceLock<EventBridgeHandle>> {
235 &self.subsystems.event_bridge
236 }
237
238 pub const fn publish_guard(&self) -> &Arc<tokio::sync::Mutex<PublishGuard>> {
242 &self.subsystems.publish_guard
243 }
244
245 pub const fn snapshot_wakeup(&self) -> &Arc<crate::reporting::SnapshotWakeup> {
246 &self.subsystems.snapshot_wakeup
247 }
248
249 pub fn system_admin(&self) -> &SystemAdmin {
250 &self.subsystems.system_admin
251 }
252
253 pub const fn mcp_registry(&self) -> &RegistryService {
254 &self.plugins.mcp_registry
255 }
256
257 pub const fn authz_hook(&self) -> &SharedAuthzHook {
258 &self.subsystems.authz_hook
259 }
260
261 #[must_use]
262 pub fn governance(&self) -> &GovernanceEngine {
263 &self.subsystems.governance
264 }
265
266 #[must_use]
267 pub fn governance_arc(&self) -> Arc<GovernanceEngine> {
268 Arc::clone(&self.subsystems.governance)
269 }
270
271 #[must_use]
272 pub fn schema_install(&self) -> &SchemaInstallReport {
273 &self.subsystems.schema_install
274 }
275
276 pub const fn shutdown_request(&self) -> &ShutdownRequest {
277 &self.subsystems.shutdown
278 }
279
280 pub fn request_restart(&self, reason: &str) {
281 self.subsystems.shutdown.request(reason);
282 }
283}