Skip to main content

systemprompt_agent/services/shared/
config.rs

1//! Runtime configuration for agent services: connection, runtime, and service
2//! settings, plus a builder and validation for assembling them.
3//!
4//! Copyright (c) systemprompt.io — Business Source License 1.1.
5//! See <https://systemprompt.io> for licensing details.
6
7use crate::services::shared::error::{AgentServiceError, Result};
8use serde::{Deserialize, Serialize};
9use std::time::Duration;
10use systemprompt_identifiers::AgentId;
11
12#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
13pub struct ServiceConfiguration {
14    pub enabled: bool,
15    pub timeout_seconds: u64,
16    pub retry_attempts: u32,
17    pub retry_delay_milliseconds: u64,
18    pub max_connections: usize,
19}
20
21impl ServiceConfiguration {
22    pub const fn timeout(&self) -> Duration {
23        Duration::from_secs(self.timeout_seconds)
24    }
25
26    pub const fn retry_delay(&self) -> Duration {
27        Duration::from_millis(self.retry_delay_milliseconds)
28    }
29
30    pub fn validate(&self) -> Result<()> {
31        if self.retry_attempts == 0 {
32            return Err(AgentServiceError::Configuration(
33                "ServiceConfiguration".to_owned(),
34                "retry_attempts must be at least 1".to_owned(),
35            ));
36        }
37        if self.max_connections == 0 {
38            return Err(AgentServiceError::Configuration(
39                "ServiceConfiguration".to_owned(),
40                "max_connections must be at least 1".to_owned(),
41            ));
42        }
43        Ok(())
44    }
45}
46
47impl Default for ServiceConfiguration {
48    fn default() -> Self {
49        Self {
50            enabled: true,
51            timeout_seconds: 30,
52            retry_attempts: 3,
53            retry_delay_milliseconds: 500,
54            max_connections: 10,
55        }
56    }
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize)]
60pub struct RuntimeConfiguration {
61    pub agent_id: AgentId,
62    pub name: String,
63    pub port: u16,
64    pub host: String,
65    pub ssl_enabled: bool,
66    pub auth_required: bool,
67    pub system_prompt: Option<String>,
68}
69
70#[derive(Debug, Clone)]
71pub struct RuntimeConfigurationBuilder {
72    agent_id: AgentId,
73    name: String,
74    port: u16,
75    host: String,
76    ssl_enabled: bool,
77    auth_required: bool,
78    system_prompt: Option<String>,
79}
80
81impl RuntimeConfigurationBuilder {
82    pub fn new(agent_id: AgentId, name: String) -> Self {
83        Self {
84            agent_id,
85            name,
86            port: 8080,
87            host: "localhost".to_owned(),
88            ssl_enabled: false,
89            auth_required: false,
90            system_prompt: None,
91        }
92    }
93
94    pub const fn port(mut self, port: u16) -> Self {
95        self.port = port;
96        self
97    }
98
99    pub fn host(mut self, host: String) -> Self {
100        self.host = host;
101        self
102    }
103
104    pub const fn enable_ssl(mut self) -> Self {
105        self.ssl_enabled = true;
106        self
107    }
108
109    pub const fn require_auth(mut self) -> Self {
110        self.auth_required = true;
111        self
112    }
113
114    pub fn system_prompt(mut self, prompt: String) -> Self {
115        self.system_prompt = Some(prompt);
116        self
117    }
118
119    pub fn build(self) -> RuntimeConfiguration {
120        RuntimeConfiguration {
121            agent_id: self.agent_id,
122            name: self.name,
123            port: self.port,
124            host: self.host,
125            ssl_enabled: self.ssl_enabled,
126            auth_required: self.auth_required,
127            system_prompt: self.system_prompt,
128        }
129    }
130}
131
132#[derive(Debug, Clone, Serialize, Deserialize)]
133pub struct ConnectionConfiguration {
134    pub url: String,
135    pub timeout_seconds: u64,
136    pub keepalive_enabled: bool,
137    pub pool_size: usize,
138}
139
140impl ConnectionConfiguration {
141    pub const fn timeout(&self) -> Duration {
142        Duration::from_secs(self.timeout_seconds)
143    }
144}
145
146#[derive(Debug, Clone, Serialize, Deserialize)]
147pub struct AgentServiceConfig {
148    pub agent_id: AgentId,
149    pub name: String,
150    pub description: String,
151    pub version: String,
152    pub endpoint: String,
153    pub port: u16,
154    pub is_active: bool,
155}
156
157impl AgentServiceConfig {
158    pub fn validate(&self) -> Result<()> {
159        if self.agent_id.as_str().is_empty() {
160            return Err(AgentServiceError::Validation(
161                "agent_id".to_owned(),
162                "cannot be empty".to_owned(),
163            ));
164        }
165        if self.port == 0 {
166            return Err(AgentServiceError::Validation(
167                "port".to_owned(),
168                "must be greater than 0".to_owned(),
169            ));
170        }
171        if self.name.is_empty() {
172            return Err(AgentServiceError::Validation(
173                "name".to_owned(),
174                "cannot be empty".to_owned(),
175            ));
176        }
177        Ok(())
178    }
179}
180
181impl Default for AgentServiceConfig {
182    fn default() -> Self {
183        Self {
184            agent_id: AgentId::generate(),
185            name: "Default Agent".to_owned(),
186            description: "Default agent instance".to_owned(),
187            version: "0.1.0".to_owned(),
188            endpoint: "http://localhost:8080".to_owned(),
189            port: 8080,
190            is_active: true,
191        }
192    }
193}