#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct SessionConfig {
pub system_prompt: Option<String>,
pub context_window: u64,
pub compact_threshold: u8,
pub auto_compact: bool,
}
impl Default for SessionConfig {
fn default() -> Self {
Self {
system_prompt: None,
context_window: 200_000,
compact_threshold: 80,
auto_compact: true,
}
}
}
impl SessionConfig {
#[must_use]
pub fn with_system_prompt(mut self, system_prompt: impl Into<String>) -> Self {
self.system_prompt = Some(system_prompt.into());
self
}
#[must_use]
pub fn with_context_window(mut self, context_window: u64) -> Self {
self.context_window = context_window;
self
}
#[must_use]
pub fn with_compact_threshold(mut self, compact_threshold: u8) -> Self {
self.compact_threshold = compact_threshold.min(100);
self
}
#[must_use]
pub fn with_auto_compact(mut self, auto_compact: bool) -> Self {
self.auto_compact = auto_compact;
self
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ParallelMode {
Sequential,
Parallel,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct ParallelDispatchConfig {
pub mode: ParallelMode,
pub max_concurrency: usize,
}
impl Default for ParallelDispatchConfig {
fn default() -> Self {
Self {
mode: ParallelMode::Sequential,
max_concurrency: 8,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn session_config_default_context_window() {
let config = SessionConfig::default();
assert_eq!(config.context_window, 200_000);
assert!(config.system_prompt.is_none());
}
#[test]
fn session_config_with_system_prompt_sets_some() {
let config = SessionConfig::default().with_system_prompt("be helpful");
assert_eq!(config.system_prompt.as_deref(), Some("be helpful"));
}
#[test]
fn session_config_with_context_window_sets_field() {
let config = SessionConfig::default().with_context_window(8192);
assert_eq!(config.context_window, 8192);
}
#[test]
fn session_config_builder_chain_composes_without_clobbering() {
let config = SessionConfig::default()
.with_system_prompt("p")
.with_context_window(128_000);
assert_eq!(config.system_prompt.as_deref(), Some("p"));
assert_eq!(config.context_window, 128_000);
}
#[test]
fn session_config_builder_does_not_mutate_source() {
let original = SessionConfig::default();
let _modified = original.clone().with_context_window(1);
assert_eq!(original.context_window, 200_000);
}
#[test]
fn parallel_dispatch_default_is_sequential_concurrency_8() {
let dispatch = ParallelDispatchConfig::default();
assert_eq!(dispatch.mode, ParallelMode::Sequential);
assert_eq!(dispatch.max_concurrency, 8);
}
#[test]
fn parallel_dispatch_struct_literal_round_trips() {
let dispatch = ParallelDispatchConfig {
mode: ParallelMode::Parallel,
max_concurrency: 4,
};
assert_eq!(dispatch.mode, ParallelMode::Parallel);
assert_eq!(dispatch.max_concurrency, 4);
}
}