use std::sync::Arc;
use anyhow::Result;
use tokio::sync::mpsc;
use crate::provider::ToolDefinition;
use crate::session::Session;
use crate::session::SessionEvent;
use crate::session::helper::compression::{CompressContext, compress_last_message_if_oversized};
use crate::session::helper::experimental;
use super::compress_step::run_compression_step;
use super::helpers::{DerivedContext, messages_len_changed};
pub async fn derive_context(
session: &Session,
provider: Arc<dyn crate::provider::Provider>,
model: &str,
system_prompt: &str,
tools: &[ToolDefinition],
event_tx: Option<&mpsc::Sender<SessionEvent>>,
force_keep_last: Option<usize>,
) -> Result<DerivedContext> {
let origin_len = session.messages.len();
let mut messages = session.messages.clone();
let ctx = CompressContext::from_session(session);
let step0 =
compress_last_message_if_oversized(&mut messages, &ctx, Arc::clone(&provider), model)
.await?;
experimental::apply_all(&mut messages);
let before = messages.len();
let step1 = run_compression_step(
&mut messages,
&ctx,
provider,
model,
system_prompt,
tools,
event_tx,
force_keep_last,
)
.await?;
experimental::pairing::repair_orphans(&mut messages);
let compressed = step0 || step1 || messages_len_changed(before, &messages);
Ok(DerivedContext {
messages,
origin_len,
compressed,
})
}