use serde::{Deserialize, Serialize};
#[cfg(feature = "openapi")]
use utoipa::ToSchema;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[serde(rename_all = "snake_case")]
pub enum CompactionReason {
ProactiveBudget,
RequestTooLarge,
Manual,
}
impl std::fmt::Display for CompactionReason {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::ProactiveBudget => write!(f, "proactive_budget"),
Self::RequestTooLarge => write!(f, "request_too_large"),
Self::Manual => write!(f, "manual"),
}
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[serde(rename_all = "snake_case")]
pub enum CompactionTrigger {
#[default]
ContextBudget,
CostPressure,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[serde(rename_all = "snake_case")]
pub enum CompactionSkipReason {
StrategyExcludesNative,
DriverUnsupported,
CheckpointStoreUnavailable,
CooldownActive,
NativeReturnedNone,
NoMaterialReduction,
GuardRejected,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[serde(rename_all = "snake_case")]
pub enum CompactionFailStage {
NativeCompaction,
CheckpointInstall,
Summarization,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
pub struct ContextCompactionSkippedData {
#[cfg_attr(feature = "openapi", schema(example = "proactive_budget"))]
pub reason: CompactionReason,
#[cfg_attr(feature = "openapi", schema(example = "context_budget"))]
pub trigger: CompactionTrigger,
#[cfg_attr(feature = "openapi", schema(example = "cooldown_active"))]
pub skip_reason: CompactionSkipReason,
#[cfg_attr(feature = "openapi", schema(example = "summary_then_trim"))]
pub strategy: String,
#[cfg_attr(feature = "openapi", schema(example = "gpt-5-mini"))]
pub model: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "openapi", schema(example = "openai"))]
pub provider: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "openapi", schema(example = "openai-chat"))]
pub driver: Option<String>,
#[cfg_attr(feature = "openapi", schema(example = 184320))]
pub tokens_observed: u64,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "openapi", schema(example = 8192))]
pub budget_remaining_tokens: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "openapi", schema(example = 481))]
pub source_sequence: Option<i64>,
#[cfg_attr(feature = "openapi", schema(example = 120))]
pub messages_observed: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
pub struct ContextCompactionFailedData {
#[cfg_attr(feature = "openapi", schema(example = "proactive_budget"))]
pub reason: CompactionReason,
#[cfg_attr(feature = "openapi", schema(example = "context_budget"))]
pub trigger: CompactionTrigger,
#[cfg_attr(feature = "openapi", schema(example = "summarization"))]
pub stage: CompactionFailStage,
#[cfg_attr(
feature = "openapi",
schema(example = "summarizer request failed: upstream timed out")
)]
pub error: String,
#[cfg_attr(feature = "openapi", schema(example = "summary_then_trim"))]
pub strategy: String,
#[cfg_attr(feature = "openapi", schema(example = "gpt-5-mini"))]
pub model: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "openapi", schema(example = "openai"))]
pub provider: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "openapi", schema(example = "openai-chat"))]
pub driver: Option<String>,
#[cfg_attr(feature = "openapi", schema(example = 184320))]
pub tokens_before: u64,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "openapi", schema(example = 8192))]
pub budget_remaining_tokens: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "openapi", schema(example = 481))]
pub source_sequence: Option<i64>,
#[cfg_attr(feature = "openapi", schema(example = 120))]
pub messages_before: usize,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(
feature = "openapi",
schema(example = "01934c2f-9f2e-7c1b-8d3e-4f5a6b7c8d9e")
)]
pub checkpoint_id: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
pub struct ContextCompactingData {
#[cfg_attr(feature = "openapi", schema(example = "proactive_budget"))]
pub reason: CompactionReason,
#[cfg_attr(feature = "openapi", schema(example = "summary_then_trim"))]
pub strategy: String,
#[cfg_attr(feature = "openapi", schema(example = 120))]
pub messages_before: usize,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "openapi", schema(example = 184320))]
pub tokens_before: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub bytes_before: Option<u64>,
#[serde(default)]
#[cfg_attr(feature = "openapi", schema(example = "context_budget"))]
pub trigger: CompactionTrigger,
#[serde(default)]
#[cfg_attr(feature = "openapi", schema(example = "gpt-5-mini"))]
pub model: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "openapi", schema(example = "openai"))]
pub provider: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "openapi", schema(example = "openai-chat"))]
pub driver: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "openapi", schema(example = 8192))]
pub budget_remaining_tokens: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "openapi", schema(example = 481))]
pub source_sequence: Option<i64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "openapi", schema(example = 90210))]
pub cache_read_tokens: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "openapi", schema(example = 1024))]
pub cache_creation_tokens: Option<u32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
pub struct CompactionStepData {
pub strategy: String,
pub messages_after: usize,
pub duration_ms: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
pub struct ContextCompactedData {
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(
feature = "openapi",
schema(example = "01934c2f-9f2e-7c1b-8d3e-4f5a6b7c8d9e")
)]
pub checkpoint_id: Option<String>,
pub strategy_used: String,
#[cfg_attr(feature = "openapi", schema(example = 120))]
pub messages_before: usize,
pub messages_after: usize,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "openapi", schema(example = 184320))]
pub tokens_before: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tokens_after: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub bytes_before: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub bytes_after: Option<u64>,
pub duration_ms: u64,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub steps: Vec<CompactionStepData>,
#[serde(default)]
#[cfg_attr(feature = "openapi", schema(example = "context_budget"))]
pub trigger: CompactionTrigger,
#[serde(default)]
#[cfg_attr(feature = "openapi", schema(example = "gpt-5-mini"))]
pub model: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "openapi", schema(example = "openai"))]
pub provider: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "openapi", schema(example = "openai-chat"))]
pub driver: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "openapi", schema(example = 8192))]
pub budget_remaining_tokens: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "openapi", schema(example = 481))]
pub source_sequence: Option<i64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "openapi", schema(example = 90210))]
pub cache_read_tokens: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "openapi", schema(example = 1024))]
pub cache_creation_tokens: Option<u32>,
}