use std::io;
use rig_core::conversation::Conversation;
use crate::format::SESSION;
use crate::session::{Fold, Folded, fold, log_lines, read_header};
use crate::{SessionError, Store, main_order};
pub fn read_conversation(
store: &dyn Store,
agent: Option<&str>,
) -> Result<(String, Conversation), SessionError> {
let how = Fold::WHOLE;
let folded = match agent {
Some(agent) => fold(store, agent, how)?,
None => main_log(store, how)?,
};
let Some(folded) = folded.filter(|folded| folded.name != SESSION) else {
let why = format!("the session has no agent {}", agent.unwrap_or("to talk to"));
return Err(io::Error::new(io::ErrorKind::NotFound, why).into());
};
Ok((folded.name, folded.conversation))
}
fn main_log(store: &dyn Store, how: Fold) -> Result<Option<Folded>, SessionError> {
let mut candidates = Vec::new();
for name in store.logs()? {
if name == SESSION {
continue;
}
let Some(lines) = log_lines(store, &name)? else {
continue;
};
if let Some((_, _, first)) = lines.iter().next() {
let (_, header) = read_header(&name, first)?;
if header.parent.is_none() {
candidates.push(name);
}
}
}
candidates.sort_by(|a, b| main_order(false, a).cmp(&main_order(false, b)));
for name in candidates {
if let Some(folded) = fold(store, &name, how)?.filter(|folded| !folded.retired) {
return Ok(Some(folded));
}
}
Ok(None)
}
#[cfg(test)]
mod tests;