Skip to main content

systemprompt_runtime/
context_traits.rs

1//! Trait impls for [`crate::AppContext`].
2//!
3//! Split out of `context.rs` so the core type definition stays under
4//! the 300-line public-API ceiling.
5//!
6//! Copyright (c) systemprompt.io — Business Source License 1.1.
7//! See <https://systemprompt.io> for licensing details.
8
9use std::sync::Arc;
10
11use systemprompt_analytics::{AnalyticsService, FingerprintRepository};
12use systemprompt_extension::{
13    Extension, ExtensionContext, HasAnalytics, HasFingerprint, HasRouteClassifier, HasUserService,
14};
15use systemprompt_models::RouteClassifier;
16use systemprompt_traits::{
17    AnalyticsProvider, AppContext as AppContextTrait, ConfigProvider, DatabaseHandle,
18    FingerprintProvider, UserProvider,
19};
20use systemprompt_users::UserService;
21
22use crate::AppContext;
23
24impl AppContextTrait for AppContext {
25    fn config(&self) -> Arc<dyn ConfigProvider> {
26        let concrete = Arc::clone(&self.cfg.config);
27        let provider: Arc<dyn ConfigProvider> = concrete;
28        provider
29    }
30
31    fn database_handle(&self) -> Arc<dyn DatabaseHandle> {
32        let concrete = Arc::clone(&self.data.database);
33        let handle: Arc<dyn DatabaseHandle> = concrete;
34        handle
35    }
36
37    fn session_provider(&self) -> Option<Arc<dyn systemprompt_traits::SessionProvider>> {
38        Some(self.session_store())
39    }
40
41    fn analytics_provider(&self) -> Option<Arc<dyn AnalyticsProvider>> {
42        let concrete = Arc::clone(&self.data.analytics_service);
43        let provider: Arc<dyn AnalyticsProvider> = concrete;
44        Some(provider)
45    }
46
47    fn fingerprint_provider(&self) -> Option<Arc<dyn FingerprintProvider>> {
48        let concrete = Arc::clone(self.data.fingerprint_repo.as_ref()?);
49        let provider: Arc<dyn FingerprintProvider> = concrete;
50        Some(provider)
51    }
52
53    fn user_provider(&self) -> Option<Arc<dyn UserProvider>> {
54        let concrete = Arc::clone(self.data.user_service.as_ref()?);
55        let provider: Arc<dyn UserProvider> = concrete;
56        Some(provider)
57    }
58}
59
60impl ExtensionContext for AppContext {
61    fn system_owner_id(&self) -> systemprompt_identifiers::UserId {
62        self.system_admin().id().clone()
63    }
64
65    fn config(&self) -> Arc<dyn ConfigProvider> {
66        let concrete = Arc::clone(&self.cfg.config);
67        let provider: Arc<dyn ConfigProvider> = concrete;
68        provider
69    }
70
71    fn database(&self) -> Arc<dyn DatabaseHandle> {
72        let concrete = Arc::clone(&self.data.database);
73        let handle: Arc<dyn DatabaseHandle> = concrete;
74        handle
75    }
76
77    fn file_storage(&self) -> Arc<dyn systemprompt_traits::FileStorage> {
78        Arc::clone(Self::file_storage(self))
79    }
80
81    fn instance_id(&self) -> systemprompt_identifiers::InstanceId {
82        self.config().instance_id.clone()
83    }
84
85    fn instances(&self) -> systemprompt_traits::DynInstanceRegistry {
86        let concrete = Arc::clone(self.service_repository());
87        let registry: systemprompt_traits::DynInstanceRegistry = concrete;
88        registry
89    }
90
91    fn leases(&self) -> systemprompt_traits::DynLeaseRepository {
92        let concrete = Arc::clone(&self.coordination_repositories().leases);
93        let leases: systemprompt_traits::DynLeaseRepository = concrete;
94        leases
95    }
96
97    fn advisory_locks(&self) -> systemprompt_traits::DynAdvisoryLocks {
98        let concrete = Arc::clone(&self.coordination_repositories().locks);
99        let locks: systemprompt_traits::DynAdvisoryLocks = concrete;
100        locks
101    }
102
103    fn secret(&self, name: &str) -> Option<systemprompt_traits::ExtensionSecret> {
104        let secrets = match systemprompt_config::SecretsBootstrap::get() {
105            Ok(secrets) => secrets,
106            Err(error) => {
107                tracing::warn!(%error, secret = name, "extension secret requested before secrets loaded");
108                return None;
109            },
110        };
111        secrets
112            .custom_secret(name)
113            .map(|value| systemprompt_traits::ExtensionSecret::new(value.clone()))
114    }
115
116    fn get_extension(&self, id: &str) -> Option<Arc<dyn Extension>> {
117        self.plugins.extension_registry.get(id).cloned()
118    }
119
120    fn config_planes(
121        &self,
122    ) -> systemprompt_provider_contracts::ConfigPlaneResult<crate::ConfigPlaneSet> {
123        Self::config_planes(self)
124    }
125}
126
127impl HasAnalytics for AppContext {
128    type Analytics = Arc<AnalyticsService>;
129
130    fn analytics(&self) -> &Self::Analytics {
131        &self.data.analytics_service
132    }
133}
134
135impl HasFingerprint for AppContext {
136    type Fingerprint = Arc<FingerprintRepository>;
137
138    fn fingerprint(&self) -> Option<&Self::Fingerprint> {
139        self.data.fingerprint_repo.as_ref()
140    }
141}
142
143impl HasUserService for AppContext {
144    type UserService = Arc<UserService>;
145
146    fn user_service(&self) -> Option<&Self::UserService> {
147        self.data.user_service.as_ref()
148    }
149}
150
151impl HasRouteClassifier for AppContext {
152    type RouteClassifier = Arc<RouteClassifier>;
153
154    fn route_classifier(&self) -> &Self::RouteClassifier {
155        &self.cfg.route_classifier
156    }
157}