distri_types/configuration/
config.rs

1use crate::a2a::{AgentCapabilities, AgentProvider, SecurityScheme};
2use schemars::JsonSchema;
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
7pub struct StoreConfig {
8    /// Metadata store (agent_config, tool_auth) - persistent across sessions
9    #[serde(default)]
10    pub metadata: MetadataStoreConfig,
11
12    /// Memory store configuration (for vector search) - persistent cross-session memory
13    #[serde(default)]
14    pub memory: Option<MemoryStoreConfig>,
15
16    /// Session stores (threads, tasks, scratchpad, session) - ephemeral by default
17    #[serde(default)]
18    pub session: SessionStoreConfig,
19}
20#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default, PartialEq, Eq, Hash)]
21#[serde(tag = "type", content = "config", rename_all = "lowercase")]
22pub enum StoreType {
23    #[default]
24    Sqlite,
25    Postgres,
26    Custom {
27        name: String,
28    },
29}
30
31impl StoreType {
32    pub fn label(&self) -> &str {
33        match self {
34            StoreType::Sqlite => "sqlite",
35            StoreType::Postgres => "postgres",
36            StoreType::Custom { name } => name.as_str(),
37        }
38    }
39}
40
41#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
42pub struct MetadataStoreConfig {
43    #[serde(default)]
44    pub store_type: StoreType,
45    #[serde(default)]
46    pub db_config: Option<DbConnectionConfig>,
47}
48
49impl Default for MetadataStoreConfig {
50    fn default() -> Self {
51        Self {
52            store_type: StoreType::Sqlite,
53            db_config: Some(DbConnectionConfig::default()),
54        }
55    }
56}
57
58#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
59pub struct MemoryStoreConfig {
60    #[serde(default)]
61    pub store_type: StoreType,
62    #[serde(default)]
63    pub db_config: Option<DbConnectionConfig>,
64    #[serde(default = "default_embedding_dimension")]
65    pub embedding_dimension: usize,
66    #[serde(default = "default_similarity_threshold")]
67    pub similarity_threshold: f32,
68    #[serde(default = "default_max_results")]
69    pub max_results: usize,
70    pub openai_api_key: Option<String>,
71}
72
73impl Default for MemoryStoreConfig {
74    fn default() -> Self {
75        Self {
76            store_type: StoreType::Sqlite,
77            db_config: Some(DbConnectionConfig::default()),
78            embedding_dimension: default_embedding_dimension(),
79            similarity_threshold: default_similarity_threshold(),
80            max_results: default_max_results(),
81            openai_api_key: None,
82        }
83    }
84}
85
86#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
87pub struct SessionStoreConfig {
88    /// If true, creates a new ephemeral in-memory SQLite connection for each thread execution
89    /// When ephemeral, store_type and db_config are ignored (always uses in-memory SQLite)
90    #[serde(default = "default_ephemeral")]
91    pub ephemeral: bool,
92    /// Store type (only used when ephemeral=false)
93    #[serde(default)]
94    pub store_type: StoreType,
95    /// Database config (only used when ephemeral=false)
96    #[serde(default)]
97    pub db_config: Option<DbConnectionConfig>,
98}
99
100fn default_ephemeral() -> bool {
101    true
102}
103
104impl Default for SessionStoreConfig {
105    fn default() -> Self {
106        Self {
107            ephemeral: true,
108            store_type: StoreType::Sqlite,
109            db_config: Some(DbConnectionConfig::default()),
110        }
111    }
112}
113
114#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
115pub struct PostgresConfig {
116    pub database_url: String,
117    #[serde(default = "default_postgres_max_connections")]
118    pub max_connections: u32,
119    #[serde(default = "default_postgres_min_connections")]
120    pub min_connections: u32,
121    #[serde(default = "default_postgres_connection_timeout")]
122    pub connection_timeout: u64,
123    #[serde(default = "default_postgres_idle_timeout")]
124    pub idle_timeout: u64,
125}
126
127fn default_postgres_max_connections() -> u32 {
128    10
129}
130
131fn default_postgres_min_connections() -> u32 {
132    1
133}
134
135fn default_postgres_connection_timeout() -> u64 {
136    30
137}
138
139fn default_postgres_idle_timeout() -> u64 {
140    600
141}
142
143#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
144pub struct DbConnectionConfig {
145    #[serde(default = "default_database_url")]
146    pub database_url: String,
147    #[serde(default = "default_connections")]
148    pub max_connections: u32,
149}
150
151impl Default for DbConnectionConfig {
152    fn default() -> Self {
153        DbConnectionConfig {
154            database_url: default_database_url(),
155            max_connections: default_connections(),
156        }
157    }
158}
159
160fn default_database_url() -> String {
161    // "file::memory:".to_string()
162    ".distri/distri.db".to_string()
163}
164
165fn default_connections() -> u32 {
166    10
167}
168
169#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
170#[serde(tag = "type", content = "config", rename_all = "lowercase")]
171pub enum ObjectStorageConfig {
172    /// Local filesystem storage
173    #[serde(rename = "filesystem")]
174    FileSystem {
175        /// Base directory for storing objects
176        base_path: String,
177    },
178
179    /// Google Cloud Storage
180    #[serde(rename = "gcs")]
181    GoogleCloudStorage {
182        bucket: String,
183        project_id: String,
184        /// Path to service account key file
185        service_account_key: Option<String>,
186        /// Base64 encoded service account key
187        service_account_key_base64: Option<String>,
188    },
189
190    /// AWS S3 (future implementation)
191    #[serde(rename = "s3")]
192    S3 {
193        bucket: String,
194        region: String,
195        endpoint: Option<String>,
196        access_key_id: String,
197        secret_access_key: String,
198        path_style: Option<bool>,
199    },
200}
201
202impl Default for ObjectStorageConfig {
203    fn default() -> Self {
204        Self::FileSystem {
205            base_path: "./data/artifacts".to_string(),
206        }
207    }
208}
209
210fn default_embedding_dimension() -> usize {
211    1536
212}
213
214fn default_similarity_threshold() -> f32 {
215    0.7
216}
217
218fn default_max_results() -> usize {
219    10
220}
221
222#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
223pub struct ServerConfig {
224    #[serde(default = "default_server_url")]
225    pub base_url: String,
226    #[serde(default)]
227    pub port: Option<u16>,
228    #[serde(default)]
229    pub host: Option<String>,
230    #[serde(default = "default_agent_provider")]
231    pub agent_provider: AgentProvider,
232    #[serde(default)]
233    pub default_input_modes: Vec<String>,
234    #[serde(default)]
235    pub default_output_modes: Vec<String>,
236    #[serde(default)]
237    pub security_schemes: HashMap<String, SecurityScheme>,
238    #[serde(default)]
239    pub security: Vec<HashMap<String, Vec<String>>>,
240    #[serde(default = "default_capabilities")]
241    pub capabilities: AgentCapabilities,
242    #[serde(default = "default_preferred_transport")]
243    pub preferred_transport: Option<String>,
244    #[serde(default = "default_documentation_url")]
245    pub documentation_url: Option<String>,
246}
247
248fn default_capabilities() -> AgentCapabilities {
249    AgentCapabilities {
250        streaming: true,
251        push_notifications: false,
252        state_transition_history: true,
253        extensions: vec![],
254    }
255}
256
257impl Default for ServerConfig {
258    fn default() -> Self {
259        Self {
260            base_url: default_server_url(),
261            agent_provider: default_agent_provider(),
262            default_input_modes: vec![],
263            default_output_modes: vec![],
264            security_schemes: HashMap::new(),
265            security: vec![],
266            capabilities: default_capabilities(),
267            port: None,
268            host: None,
269            preferred_transport: default_preferred_transport(),
270            documentation_url: default_documentation_url(),
271        }
272    }
273}
274
275fn default_agent_provider() -> AgentProvider {
276    AgentProvider {
277        organization: "Distri".to_string(),
278        url: "https://distri.ai".to_string(),
279    }
280}
281
282fn default_server_url() -> String {
283    "http://localhost:8081/v1".to_string()
284}
285
286fn default_documentation_url() -> Option<String> {
287    Some("https://github.com/distrihub/distri".to_string())
288}
289
290fn default_preferred_transport() -> Option<String> {
291    Some("JSONRPC".to_string())
292}
293
294#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
295pub struct ExternalMcpServer {
296    pub name: String,
297    #[serde(default, flatten)]
298    pub config: crate::McpServerMetadata,
299}