mod cache;
mod content;
mod indexer;
mod parse;
use camino::Utf8PathBuf;
use jiff::Timestamp;
use serde::{Deserialize, Serialize};
use self::content::Content;
pub(crate) use self::{
indexer::{Indexer, cached_sessions, rebuild},
parse::{Role, Transcript, transcript},
};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub(crate) struct Session {
pub(crate) id: String,
pub(crate) path: Utf8PathBuf,
pub(crate) cwd: Utf8PathBuf,
pub(crate) branch: Option<String>,
pub(crate) title: String,
#[serde(skip)]
pub(crate) content: Content,
pub(crate) started: Timestamp,
pub(crate) updated: Timestamp,
pub(crate) turns: u32,
pub(crate) replies: u32,
pub(crate) bytes: u64,
pub(crate) model: Option<String>,
pub(crate) ctx_tokens: u64,
pub(crate) out_tokens: u64,
pub(crate) agents: u32,
}
impl Session {
pub(crate) fn short_id(&self) -> &str {
return self.id.get(.. 8).unwrap_or(&self.id);
}
pub(crate) fn short_cwd(&self) -> String {
return dirs::home_dir()
.and_then(|home| self.cwd.strip_prefix(home).ok())
.map(|rest| if rest.as_str().is_empty() { "~".to_string() } else { format!("~/{rest}") })
.unwrap_or_else(|| self.cwd.to_string());
}
pub(crate) fn project(&self) -> String {
return match self.short_cwd().as_str() {
"~" => "~".to_string(),
_ => self.cwd.file_name().unwrap_or("/").to_string(),
};
}
}