use crate::defaults::default_true;
use crate::providers::ProviderName;
use serde::{Deserialize, Serialize};
fn default_sidequest_interval_turns() -> u32 {
4
}
fn default_sidequest_max_eviction_ratio() -> f32 {
0.5
}
fn default_sidequest_max_cursors() -> usize {
30
}
fn default_sidequest_min_cursor_tokens() -> usize {
100
}
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(default)]
pub struct SidequestConfig {
pub enabled: bool,
#[serde(default = "default_sidequest_interval_turns")]
pub interval_turns: u32,
#[serde(default = "default_sidequest_max_eviction_ratio")]
pub max_eviction_ratio: f32,
#[serde(default = "default_sidequest_max_cursors")]
pub max_cursors: usize,
#[serde(default = "default_sidequest_min_cursor_tokens")]
pub min_cursor_tokens: usize,
}
impl Default for SidequestConfig {
fn default() -> Self {
Self {
enabled: false,
interval_turns: default_sidequest_interval_turns(),
max_eviction_ratio: default_sidequest_max_eviction_ratio(),
max_cursors: default_sidequest_max_cursors(),
min_cursor_tokens: default_sidequest_min_cursor_tokens(),
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(default)]
pub struct PersonaConfig {
pub enabled: bool,
pub persona_provider: ProviderName,
pub min_confidence: f64,
pub min_messages: usize,
pub max_messages: usize,
pub extraction_timeout_secs: u64,
pub context_budget_tokens: usize,
}
impl Default for PersonaConfig {
fn default() -> Self {
Self {
enabled: false,
persona_provider: ProviderName::default(),
min_confidence: 0.6,
min_messages: 3,
max_messages: 10,
extraction_timeout_secs: 10,
context_budget_tokens: 500,
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(default)]
pub struct TrajectoryConfig {
pub enabled: bool,
pub trajectory_provider: ProviderName,
pub context_budget_tokens: usize,
pub max_messages: usize,
pub extraction_timeout_secs: u64,
pub recall_top_k: usize,
pub min_confidence: f64,
}
impl Default for TrajectoryConfig {
fn default() -> Self {
Self {
enabled: false,
trajectory_provider: ProviderName::default(),
context_budget_tokens: 400,
max_messages: 10,
extraction_timeout_secs: 10,
recall_top_k: 5,
min_confidence: 0.6,
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(default)]
pub struct CategoryConfig {
pub enabled: bool,
pub auto_tag: bool,
}
impl Default for CategoryConfig {
fn default() -> Self {
Self {
enabled: false,
auto_tag: true,
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(default)]
pub struct TreeConfig {
pub enabled: bool,
pub consolidation_provider: ProviderName,
pub sweep_interval_secs: u64,
pub batch_size: usize,
pub similarity_threshold: f32,
pub max_level: u32,
pub context_budget_tokens: usize,
pub recall_top_k: usize,
pub min_cluster_size: usize,
}
impl Default for TreeConfig {
fn default() -> Self {
Self {
enabled: false,
consolidation_provider: ProviderName::default(),
sweep_interval_secs: 300,
batch_size: 20,
similarity_threshold: 0.8,
max_level: 3,
context_budget_tokens: 400,
recall_top_k: 5,
min_cluster_size: 2,
}
}
}
fn validate_tra_nonneg_weight<'de, D>(deserializer: D) -> Result<f64, D::Error>
where
D: serde::Deserializer<'de>,
{
let value = <f64 as serde::Deserialize>::deserialize(deserializer)?;
if value.is_nan() || value.is_infinite() || value < 0.0 {
return Err(serde::de::Error::custom(
"signal weight and severity multiplier values must be finite and non-negative",
));
}
Ok(value)
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TrajectorySignalWeights {
#[serde(
default = "default_sw_policy_violation",
deserialize_with = "validate_tra_nonneg_weight"
)]
pub policy_violation: f64,
#[serde(
default = "default_sw_prompt_injection",
deserialize_with = "validate_tra_nonneg_weight"
)]
pub prompt_injection: f64,
#[serde(
default = "default_sw_tool_chain_anomaly",
deserialize_with = "validate_tra_nonneg_weight"
)]
pub tool_chain_anomaly: f64,
#[serde(
default = "default_sw_confidence_drop",
deserialize_with = "validate_tra_nonneg_weight"
)]
pub confidence_drop: f64,
}
fn default_sw_policy_violation() -> f64 {
0.30
}
fn default_sw_prompt_injection() -> f64 {
0.50
}
fn default_sw_tool_chain_anomaly() -> f64 {
0.25
}
fn default_sw_confidence_drop() -> f64 {
0.15
}
impl Default for TrajectorySignalWeights {
fn default() -> Self {
Self {
policy_violation: default_sw_policy_violation(),
prompt_injection: default_sw_prompt_injection(),
tool_chain_anomaly: default_sw_tool_chain_anomaly(),
confidence_drop: default_sw_confidence_drop(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TrajectorySeverityMultipliers {
#[serde(
default = "default_sev_low",
deserialize_with = "validate_tra_nonneg_weight"
)]
pub low: f64,
#[serde(
default = "default_sev_medium",
deserialize_with = "validate_tra_nonneg_weight"
)]
pub medium: f64,
#[serde(
default = "default_sev_high",
deserialize_with = "validate_tra_nonneg_weight"
)]
pub high: f64,
}
fn default_sev_low() -> f64 {
0.5
}
fn default_sev_medium() -> f64 {
1.0
}
fn default_sev_high() -> f64 {
2.0
}
impl Default for TrajectorySeverityMultipliers {
fn default() -> Self {
Self {
low: default_sev_low(),
medium: default_sev_medium(),
high: default_sev_high(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TrajectoryRiskAccumulatorConfig {
#[serde(default)]
pub enabled: bool,
#[serde(default = "default_tra_risk_threshold")]
pub risk_threshold: f64,
#[serde(default = "default_tra_escalation_threshold")]
pub escalation_threshold: f64,
#[serde(default = "default_tra_risk_halflife_turns")]
pub risk_halflife_turns: u32,
#[serde(default = "default_tra_signal_history_cap")]
pub signal_history_cap: usize,
#[serde(default = "default_true")]
pub tui_show_risk_gauge: bool,
#[serde(default)]
pub reset_on_compaction: bool,
#[serde(default)]
pub signal_weights: TrajectorySignalWeights,
#[serde(default)]
pub severity_multipliers: TrajectorySeverityMultipliers,
}
fn default_tra_risk_threshold() -> f64 {
0.75
}
fn default_tra_escalation_threshold() -> f64 {
0.50
}
fn default_tra_risk_halflife_turns() -> u32 {
10
}
fn default_tra_signal_history_cap() -> usize {
200
}
impl Default for TrajectoryRiskAccumulatorConfig {
fn default() -> Self {
Self {
enabled: false,
risk_threshold: default_tra_risk_threshold(),
escalation_threshold: default_tra_escalation_threshold(),
risk_halflife_turns: default_tra_risk_halflife_turns(),
signal_history_cap: default_tra_signal_history_cap(),
tui_show_risk_gauge: true,
reset_on_compaction: false,
signal_weights: TrajectorySignalWeights::default(),
severity_multipliers: TrajectorySeverityMultipliers::default(),
}
}
}