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