Skip to main content

systemprompt_extension/traits/
extension.rs

1//! The core `Extension` trait defining metadata, schemas, routers, and
2//! providers an extension contributes.
3//!
4//! Copyright (c) systemprompt.io — Business Source License 1.1.
5//! See <https://systemprompt.io> for licensing details.
6
7use std::sync::Arc;
8
9use serde_json::Value as JsonValue;
10use systemprompt_provider_contracts::{
11    ComponentRenderer, ConfigPlane, ContentDataProvider, FrontmatterProcessor, Job,
12    PageDataProvider, PagePrerenderer, RssFeedProvider, SitemapProvider, TemplateDataExtender,
13    TemplateProvider, ToolProvider,
14};
15use systemprompt_traits::RunnerService;
16
17use crate::asset::{AssetDefinition, AssetPaths};
18use crate::context::ExtensionContext;
19use crate::error::ExtensionConfigError;
20use crate::health::{MetricDescriptor, ReadinessCheck};
21use crate::metadata::{ExtensionMetadata, ExtensionRole, SchemaDefinition};
22use crate::migration::Migration;
23use crate::router::{ExtensionRouter, ExtensionRouterConfig, SiteAuthConfig};
24use crate::seed::Seed;
25
26pub trait Extension: Send + Sync + 'static {
27    fn metadata(&self) -> ExtensionMetadata;
28
29    fn schemas(&self) -> Vec<SchemaDefinition> {
30        vec![]
31    }
32
33    fn router(&self, _ctx: &dyn ExtensionContext) -> Option<ExtensionRouter> {
34        None
35    }
36
37    fn router_config(&self) -> Option<ExtensionRouterConfig> {
38        None
39    }
40
41    fn site_auth(&self) -> Option<SiteAuthConfig> {
42        None
43    }
44
45    fn jobs(&self) -> Vec<Arc<dyn Job>> {
46        vec![]
47    }
48
49    fn config_planes(&self) -> Vec<Arc<dyn ConfigPlane>> {
50        vec![]
51    }
52
53    fn runner_services(&self) -> Vec<Arc<dyn RunnerService>> {
54        vec![]
55    }
56
57    fn readiness(&self, _ctx: &dyn ExtensionContext) -> Vec<Arc<dyn ReadinessCheck>> {
58        vec![]
59    }
60
61    fn metrics(&self) -> Vec<MetricDescriptor> {
62        vec![]
63    }
64
65    fn config_prefix(&self) -> Option<&str> {
66        None
67    }
68
69    // JSON: Extension config block from the profile YAML; the extension owns it.
70    fn config_schema(&self) -> Option<JsonValue> {
71        None
72    }
73
74    // JSON: Extension config block from the profile YAML; the extension owns it.
75    fn validate_config(&self, _config: &JsonValue) -> Result<(), ExtensionConfigError> {
76        Ok(())
77    }
78
79    fn tool_providers(&self) -> Vec<Arc<dyn ToolProvider>> {
80        vec![]
81    }
82
83    fn template_providers(&self) -> Vec<Arc<dyn TemplateProvider>> {
84        vec![]
85    }
86
87    fn component_renderers(&self, _ctx: &dyn ExtensionContext) -> Vec<Arc<dyn ComponentRenderer>> {
88        vec![]
89    }
90
91    fn template_data_extenders(
92        &self,
93        _ctx: &dyn ExtensionContext,
94    ) -> Vec<Arc<dyn TemplateDataExtender>> {
95        vec![]
96    }
97
98    fn page_data_providers(&self, _ctx: &dyn ExtensionContext) -> Vec<Arc<dyn PageDataProvider>> {
99        vec![]
100    }
101
102    fn page_prerenderers(&self, _ctx: &dyn ExtensionContext) -> Vec<Arc<dyn PagePrerenderer>> {
103        vec![]
104    }
105
106    fn frontmatter_processors(&self) -> Vec<Arc<dyn FrontmatterProcessor>> {
107        vec![]
108    }
109
110    fn content_data_providers(
111        &self,
112        _ctx: &dyn ExtensionContext,
113    ) -> Vec<Arc<dyn ContentDataProvider>> {
114        vec![]
115    }
116
117    fn rss_feed_providers(&self) -> Vec<Arc<dyn RssFeedProvider>> {
118        vec![]
119    }
120
121    fn sitemap_providers(&self) -> Vec<Arc<dyn SitemapProvider>> {
122        vec![]
123    }
124
125    fn required_storage_paths(&self) -> Vec<&'static str> {
126        vec![]
127    }
128
129    fn dependencies(&self) -> Vec<&'static str> {
130        vec![]
131    }
132
133    fn is_required(&self) -> bool {
134        false
135    }
136
137    fn migrations(&self) -> Vec<Migration> {
138        vec![]
139    }
140
141    fn seeds(&self) -> Vec<Seed> {
142        Vec::new()
143    }
144
145    fn retirements(&self) -> Vec<SchemaDefinition> {
146        Vec::new()
147    }
148
149    fn cross_extension_tables(&self) -> Vec<&'static str> {
150        Vec::new()
151    }
152
153    fn roles(&self) -> Vec<ExtensionRole> {
154        vec![]
155    }
156
157    fn priority(&self) -> u32 {
158        100
159    }
160
161    fn id(&self) -> &'static str {
162        self.metadata().id
163    }
164
165    fn name(&self) -> &'static str {
166        self.metadata().name
167    }
168
169    fn version(&self) -> &'static str {
170        self.metadata().version
171    }
172
173    fn has_schemas(&self) -> bool {
174        !self.schemas().is_empty()
175    }
176
177    fn has_jobs(&self) -> bool {
178        !self.jobs().is_empty()
179    }
180
181    fn has_config(&self) -> bool {
182        self.config_prefix().is_some()
183    }
184
185    fn has_tool_providers(&self) -> bool {
186        !self.tool_providers().is_empty()
187    }
188
189    fn has_template_providers(&self) -> bool {
190        !self.template_providers().is_empty()
191    }
192
193    fn has_storage_paths(&self) -> bool {
194        !self.required_storage_paths().is_empty()
195    }
196
197    fn has_roles(&self) -> bool {
198        !self.roles().is_empty()
199    }
200
201    fn has_migrations(&self) -> bool {
202        !self.migrations().is_empty()
203    }
204
205    fn declares_assets(&self) -> bool {
206        false
207    }
208
209    fn required_assets(&self, _paths: &dyn AssetPaths) -> Vec<AssetDefinition> {
210        vec![]
211    }
212}