use crate::mcp::core::plan::storage::ExecutionPlan;
use crate::session::Message;
use anyhow::Result;
use std::fs::OpenOptions;
use std::io::Write;
use std::path::PathBuf;
use std::time::{SystemTime, UNIX_EPOCH};
pub fn get_session_log_file(session_name: &str) -> Result<PathBuf> {
let sessions_dir = crate::directories::get_sessions_dir()?;
Ok(sessions_dir.join(format!("{}.jsonl", session_name)))
}
pub fn get_session_log_path(session_name: &str) -> Result<PathBuf> {
get_session_log_file(session_name)
}
pub fn log_restoration_point(
session_name: &str,
user_message: &str,
assistant_response: &str,
) -> Result<()> {
let log_file = get_session_log_file(session_name)?;
let entry = serde_json::json!({
"type": "RESTORATION_POINT",
"timestamp": get_timestamp(),
"user_message": user_message,
"assistant_response": assistant_response,
});
append_to_log(&log_file, &serde_json::to_string(&entry)?)
}
pub fn log_compression_point(
session_name: &str,
compression_type: &str,
messages_removed: usize,
tokens_saved: u64,
post_compression_messages: &[Message],
) -> Result<()> {
let log_file = get_session_log_file(session_name)?;
let entry = serde_json::json!({
"type": "COMPRESSION_POINT",
"timestamp": get_timestamp(),
"compression_type": compression_type,
"messages_removed": messages_removed,
"tokens_saved": tokens_saved,
});
append_to_log(&log_file, &serde_json::to_string(&entry)?)?;
for msg in post_compression_messages {
let json = serde_json::to_string(msg)?;
append_to_log(&log_file, &json)?;
}
Ok(())
}
pub fn log_knowledge_entry(session_name: &str, knowledge: &str) -> Result<()> {
let log_file = get_session_log_file(session_name)?;
let entry = serde_json::json!({
"type": "KNOWLEDGE_ENTRY",
"timestamp": get_timestamp(),
"content": knowledge,
});
append_to_log(&log_file, &serde_json::to_string(&entry)?)
}
pub fn log_session_command(session_name: &str, command_line: &str) -> Result<()> {
let log_file = get_session_log_file(session_name)?;
let entry = serde_json::json!({
"type": "COMMAND",
"timestamp": get_timestamp(),
"command": command_line,
});
append_to_log(&log_file, &serde_json::to_string(&entry)?)
}
pub fn log_plan_snapshot(session_name: &str, plan: &ExecutionPlan) -> Result<()> {
let log_file = get_session_log_file(session_name)?;
let entry = serde_json::json!({
"type": "PLAN_SNAPSHOT",
"timestamp": get_timestamp(),
"plan": plan,
});
append_to_log(&log_file, &serde_json::to_string(&entry)?)
}
pub fn log_plan_cleared(session_name: &str) -> Result<()> {
let log_file = get_session_log_file(session_name)?;
let entry = serde_json::json!({
"type": "PLAN_CLEARED",
"timestamp": get_timestamp(),
});
append_to_log(&log_file, &serde_json::to_string(&entry)?)
}
fn get_timestamp() -> u64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_secs()
}
fn append_to_log(log_file: &PathBuf, content: &str) -> Result<()> {
let mut file = OpenOptions::new()
.create(true)
.append(true)
.open(log_file)?;
let single_line = content.replace(['\n', '\r'], " ");
writeln!(file, "{}", single_line)?;
Ok(())
}