use parking_lot::RwLock;
use std::borrow::Cow;
use std::collections::HashSet;
use std::future::Future;
use std::path::PathBuf;
use std::pin::Pin;
use std::sync::Arc;
use zeph_common::SecurityEventCategory;
use zeph_common::task_supervisor::{BlockingHandle, TaskSupervisor};
use zeph_config::{
ContextStrategy, DocumentConfig, GraphConfig, PersonaConfig, ReasoningConfig, TrajectoryConfig,
TreeConfig,
};
use zeph_context::input::CorrectionConfig;
use zeph_context::manager::ContextManager;
use zeph_context::summarization::SummarizationDeps;
use zeph_context::typed_page::TypedPagesState;
use zeph_llm::any::AnyProvider;
use zeph_llm::provider::Message;
use zeph_memory::semantic::SemanticMemory;
use zeph_memory::{ConversationId, TokenCounter};
use zeph_sanitizer::ContentSanitizer;
use zeph_sanitizer::quarantine::QuarantinedSummarizer;
use zeph_skills::proactive::ProactiveExplorer;
use zeph_skills::registry::SkillRegistry;
use crate::compaction::{SubgoalExtractionResult, SubgoalRegistry};
pub struct MessageWindowView<'a> {
pub messages: &'a mut Vec<Message>,
pub last_persisted_message_id: &'a mut Option<i64>,
pub deferred_db_hide_ids: &'a mut Vec<i64>,
pub deferred_db_summaries: &'a mut Vec<String>,
pub cached_prompt_tokens: &'a mut u64,
pub token_counter: Arc<TokenCounter>,
pub completed_tool_ids: &'a mut HashSet<String>,
}
#[derive(Debug, Default)]
pub struct MetricsCounters {
pub sanitizer_runs: u64,
pub sanitizer_injection_flags: u64,
pub sanitizer_truncations: u64,
pub quarantine_invocations: u64,
pub quarantine_failures: u64,
}
pub trait SecurityEventSink: Send {
fn push(&mut self, category: SecurityEventCategory, source: &'static str, detail: String);
}
pub struct ContextAssemblyView<'a> {
pub memory: Option<Arc<SemanticMemory>>,
pub conversation_id: Option<ConversationId>,
pub recall_limit: usize,
pub cross_session_score_threshold: f32,
pub context_format: zeph_config::ContextFormat,
pub last_recall_confidence: &'a mut Option<f32>,
pub context_strategy: ContextStrategy,
pub crossover_turn_threshold: u32,
pub cached_session_digest: Option<(String, usize)>,
pub digest_enabled: bool,
pub graph_config: GraphConfig,
pub document_config: DocumentConfig,
pub persona_config: PersonaConfig,
pub trajectory_config: TrajectoryConfig,
pub reasoning_config: ReasoningConfig,
pub memcot_config: zeph_config::MemCotConfig,
pub memcot_state: Option<String>,
pub tree_config: TreeConfig,
pub last_skills_prompt: &'a mut String,
pub active_skill_names: &'a mut Vec<String>,
pub skill_registry: Arc<RwLock<SkillRegistry>>,
pub skill_paths: &'a [PathBuf],
#[cfg(feature = "index")]
pub index: Option<&'a dyn zeph_context::input::IndexAccess>,
pub correction_config: Option<CorrectionConfig>,
pub sidequest_turn_counter: u64,
pub proactive_explorer: Option<Arc<ProactiveExplorer>>,
pub sanitizer: &'a ContentSanitizer,
pub quarantine_summarizer: Option<&'a QuarantinedSummarizer>,
pub context_manager: &'a mut ContextManager,
pub token_counter: Arc<zeph_memory::TokenCounter>,
pub metrics: MetricsCounters,
pub security_events: &'a mut dyn SecurityEventSink,
pub cached_prompt_tokens: u64,
pub redact_credentials: bool,
pub channel_skills: &'a [String],
pub scrub: fn(&str) -> Cow<'_, str>,
}
#[derive(Debug, Default)]
pub struct ContextDelta {
pub code_context: Option<String>,
}
pub struct ContextSummarizationView<'a> {
pub messages: &'a mut Vec<Message>,
pub deferred_db_hide_ids: &'a mut Vec<i64>,
pub deferred_db_summaries: &'a mut Vec<String>,
pub cached_prompt_tokens: &'a mut u64,
pub context_manager: &'a mut ContextManager,
pub server_compaction_active: bool,
pub token_counter: Arc<TokenCounter>,
pub summarization_deps: SummarizationDeps,
pub task_supervisor: Arc<TaskSupervisor>,
pub memory: Option<Arc<SemanticMemory>>,
pub conversation_id: Option<ConversationId>,
pub tool_call_cutoff: usize,
pub subgoal_registry: &'a mut SubgoalRegistry,
pub pending_task_goal: &'a mut Option<BlockingHandle<Option<String>>>,
pub pending_subgoal: &'a mut Option<BlockingHandle<Option<SubgoalExtractionResult>>>,
pub current_task_goal: &'a mut Option<String>,
pub task_goal_user_msg_hash: &'a mut Option<u64>,
pub subgoal_user_msg_hash: &'a mut Option<u64>,
pub status_tx: Option<tokio::sync::mpsc::UnboundedSender<String>>,
pub scrub: fn(&str) -> Cow<'_, str>,
pub compression_guidelines: Option<String>,
pub probe: Option<&'a mut dyn CompactionProbeCallback>,
pub archive: Option<&'a dyn ToolOutputArchive>,
pub persistence: Option<&'a dyn CompactionPersistence>,
pub metrics: Option<&'a dyn MetricsCallback>,
pub typed_pages: Option<Arc<TypedPagesState>>,
}
impl ContextSummarizationView<'_> {
#[must_use]
pub fn with_compression_guidelines(mut self, guidelines: Option<String>) -> Self {
self.compression_guidelines = guidelines;
self
}
}
pub struct ProviderHandles {
pub primary: AnyProvider,
pub embedding: AnyProvider,
}
pub trait StatusSink: Send + Sync {
fn send_status(&self, msg: &str) -> impl Future<Output = ()> + Send + '_;
}
pub trait TrustGate: Send + Sync {
fn set_effective_trust(&self, level: zeph_common::SkillTrustLevel);
}
pub type QdrantPersistFuture = Pin<Box<dyn Future<Output = bool> + Send + 'static>>;
#[must_use]
pub enum CompactionOutcome {
Compacted {
qdrant_future: Option<QdrantPersistFuture>,
},
CompactedWithPersistError {
qdrant_future: Option<QdrantPersistFuture>,
},
ProbeRejected,
NoChange,
}
impl PartialEq for CompactionOutcome {
fn eq(&self, other: &Self) -> bool {
matches!(
(self, other),
(Self::Compacted { .. }, Self::Compacted { .. })
| (
Self::CompactedWithPersistError { .. },
Self::CompactedWithPersistError { .. }
)
| (Self::ProbeRejected, Self::ProbeRejected)
| (Self::NoChange, Self::NoChange)
)
}
}
impl std::fmt::Debug for CompactionOutcome {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Compacted { qdrant_future } => f
.debug_struct("Compacted")
.field("qdrant_future", &qdrant_future.as_ref().map(|_| "<future>"))
.finish(),
Self::CompactedWithPersistError { qdrant_future } => f
.debug_struct("CompactedWithPersistError")
.field("qdrant_future", &qdrant_future.as_ref().map(|_| "<future>"))
.finish(),
Self::ProbeRejected => write!(f, "ProbeRejected"),
Self::NoChange => write!(f, "NoChange"),
}
}
}
impl CompactionOutcome {
pub fn qdrant_future_take(&mut self) -> Option<QdrantPersistFuture> {
match self {
Self::Compacted { qdrant_future }
| Self::CompactedWithPersistError { qdrant_future } => qdrant_future.take(),
_ => None,
}
}
#[must_use]
pub fn is_compacted(&self) -> bool {
matches!(
self,
Self::Compacted { .. } | Self::CompactedWithPersistError { .. }
)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ProbeOutcome {
Pass,
SoftFail,
HardFail,
}
pub trait CompactionProbeCallback: Send {
fn validate<'a>(
&'a mut self,
to_compact: &'a [Message],
summary: &'a str,
) -> Pin<Box<dyn Future<Output = ProbeOutcome> + Send + 'a>>;
}
pub trait ToolOutputArchive: Send + Sync {
fn archive<'a>(
&'a self,
to_compact: &'a [Message],
) -> Pin<Box<dyn Future<Output = Vec<String>> + Send + 'a>>;
}
pub trait CompactionPersistence: Send + Sync {
fn after_compaction<'a>(
&'a self,
compacted_count: usize,
summary_content: &'a str,
summary: &'a str,
) -> Pin<Box<dyn Future<Output = (bool, Option<QdrantPersistFuture>)> + Send + 'a>>;
}
pub trait MetricsCallback: Send + Sync {
fn record_hard_compaction(&self, turns_since_last: Option<u32>);
fn record_tool_output_prune(&self, count: usize);
fn record_compaction_probe_pass(
&self,
score: f32,
category_scores: Vec<zeph_memory::CategoryScore>,
threshold: f32,
hard_fail_threshold: f32,
);
fn record_compaction_probe_soft_fail(
&self,
score: f32,
category_scores: Vec<zeph_memory::CategoryScore>,
threshold: f32,
hard_fail_threshold: f32,
);
fn record_compaction_probe_hard_fail(
&self,
score: f32,
category_scores: Vec<zeph_memory::CategoryScore>,
threshold: f32,
hard_fail_threshold: f32,
);
fn record_compaction_probe_error(&self);
}