Skip to main content

mockforge_foundation/intelligent_behavior/
config.rs

1//! Configuration for the Intelligent Mock Behavior system
2//!
3//! Moved from `mockforge-core::intelligent_behavior::config` (Phase 6 / A8).
4//! All dependencies (BehaviorRules, StateMachine, ConsistencyRule, Persona,
5//! SessionTracking) are now in foundation.
6
7use super::session::SessionTracking;
8use super::{types::BehaviorRules, Persona};
9use serde::{Deserialize, Serialize};
10use std::time::Duration;
11
12/// Configuration for the Intelligent Mock Behavior system
13#[derive(Debug, Clone, Serialize, Deserialize, Default)]
14#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
15pub struct IntelligentBehaviorConfig {
16    /// Enable intelligent behavior
17    #[serde(default)]
18    pub enabled: bool,
19    /// Session tracking configuration
20    #[serde(default)]
21    pub session_tracking: SessionTracking,
22    /// Behavior model configuration
23    #[serde(default)]
24    pub behavior_model: BehaviorModelConfig,
25    /// Vector store configuration
26    #[serde(default)]
27    pub vector_store: VectorStoreConfig,
28    /// Performance settings
29    #[serde(default)]
30    pub performance: PerformanceConfig,
31    /// Smart Personas configuration
32    #[serde(default)]
33    pub personas: PersonasConfig,
34}
35
36/// Personas configuration for consistent data generation
37#[derive(Debug, Clone, Serialize, Deserialize, Default)]
38#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
39pub struct PersonasConfig {
40    /// List of configured personas
41    #[serde(default)]
42    pub personas: Vec<Persona>,
43    /// Active persona name (if None, uses first persona or defaults)
44    pub active_persona: Option<String>,
45}
46
47impl PersonasConfig {
48    /// Get the active persona, or the first persona if no active persona is set
49    pub fn get_active_persona(&self) -> Option<&Persona> {
50        if let Some(active_name) = &self.active_persona {
51            self.personas.iter().find(|p| p.name == *active_name)
52        } else if !self.personas.is_empty() {
53            Some(&self.personas[0])
54        } else {
55            None
56        }
57    }
58}
59
60/// Behavior model configuration
61#[derive(Debug, Clone, Serialize, Deserialize)]
62#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
63pub struct BehaviorModelConfig {
64    /// LLM provider (openai, anthropic, ollama, openai-compatible)
65    pub llm_provider: String,
66    /// Model name (e.g., gpt-4, claude-3-opus, llama2)
67    pub model: String,
68    /// API key (optional, can use environment variable)
69    pub api_key: Option<String>,
70    /// API endpoint (optional, uses provider default)
71    pub api_endpoint: Option<String>,
72    /// Temperature for LLM generation (0.0 to 2.0)
73    #[serde(default = "default_temperature")]
74    pub temperature: f64,
75    /// Maximum tokens for LLM response
76    #[serde(default = "default_max_tokens")]
77    pub max_tokens: usize,
78    /// Sampling seed for deterministic AI generation (#852). When set,
79    /// requests default to this seed unless overridden per-request; also
80    /// readable from the MOCKFORGE_AI_SEED environment variable.
81    #[serde(default)]
82    pub seed: Option<i64>,
83
84    /// Behavior rules
85    #[serde(default)]
86    pub rules: BehaviorRules,
87}
88
89impl Default for BehaviorModelConfig {
90    fn default() -> Self {
91        Self {
92            llm_provider: "openai".to_string(),
93            model: "gpt-3.5-turbo".to_string(),
94            api_key: None,
95            api_endpoint: None,
96            temperature: default_temperature(),
97            max_tokens: default_max_tokens(),
98            seed: None,
99            rules: BehaviorRules::default(),
100        }
101    }
102}
103
104/// Vector store configuration
105#[derive(Debug, Clone, Serialize, Deserialize)]
106#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
107pub struct VectorStoreConfig {
108    /// Enable vector store for long-term memory
109    #[serde(default)]
110    pub enabled: bool,
111    /// Embedding provider (openai, openai-compatible)
112    #[serde(default = "default_embedding_provider")]
113    pub embedding_provider: String,
114    /// Embedding model (e.g., text-embedding-ada-002)
115    #[serde(default = "default_embedding_model")]
116    pub embedding_model: String,
117    /// Storage path (optional, defaults to in-memory)
118    pub storage_path: Option<String>,
119    /// Number of top results to retrieve for semantic search
120    #[serde(default = "default_search_limit")]
121    pub semantic_search_limit: usize,
122    /// Similarity threshold for semantic search (0.0 to 1.0)
123    #[serde(default = "default_similarity_threshold")]
124    pub similarity_threshold: f32,
125}
126
127impl Default for VectorStoreConfig {
128    fn default() -> Self {
129        Self {
130            enabled: false,
131            embedding_provider: default_embedding_provider(),
132            embedding_model: default_embedding_model(),
133            storage_path: None,
134            semantic_search_limit: default_search_limit(),
135            similarity_threshold: default_similarity_threshold(),
136        }
137    }
138}
139
140/// Performance configuration
141#[derive(Debug, Clone, Serialize, Deserialize)]
142#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
143pub struct PerformanceConfig {
144    /// Cache TTL in seconds
145    #[serde(default = "default_cache_ttl")]
146    pub cache_ttl_seconds: u64,
147    /// Maximum number of interactions to keep in session history
148    #[serde(default = "default_max_history")]
149    pub max_history_length: usize,
150    /// Session timeout in seconds (inactive sessions are removed)
151    #[serde(default = "default_session_timeout")]
152    pub session_timeout_seconds: u64,
153    /// Enable response caching for identical requests
154    #[serde(default = "default_true")]
155    pub enable_response_cache: bool,
156}
157
158impl Default for PerformanceConfig {
159    fn default() -> Self {
160        Self {
161            cache_ttl_seconds: default_cache_ttl(),
162            max_history_length: default_max_history(),
163            session_timeout_seconds: default_session_timeout(),
164            enable_response_cache: true,
165        }
166    }
167}
168
169impl PerformanceConfig {
170    /// Get cache TTL as Duration
171    pub fn cache_ttl(&self) -> Duration {
172        Duration::from_secs(self.cache_ttl_seconds)
173    }
174
175    /// Get session timeout as Duration
176    pub fn session_timeout(&self) -> Duration {
177        Duration::from_secs(self.session_timeout_seconds)
178    }
179}
180
181fn default_temperature() -> f64 {
182    0.7
183}
184
185fn default_max_tokens() -> usize {
186    1024
187}
188
189fn default_embedding_provider() -> String {
190    "openai".to_string()
191}
192
193fn default_embedding_model() -> String {
194    "text-embedding-ada-002".to_string()
195}
196
197fn default_search_limit() -> usize {
198    10
199}
200
201fn default_similarity_threshold() -> f32 {
202    0.7
203}
204
205fn default_cache_ttl() -> u64 {
206    300
207}
208
209fn default_max_history() -> usize {
210    50
211}
212
213fn default_session_timeout() -> u64 {
214    3600
215}
216
217fn default_true() -> bool {
218    true
219}