use crate::db::models::Session;
use uuid::Uuid;
pub fn resolve_one_by_prefix(sessions: &[Session], prefix: &str) -> Result<Uuid, String> {
let prefix = prefix.to_lowercase();
let matches: Vec<&Session> = sessions
.iter()
.filter(|s| s.id.to_string().to_lowercase().starts_with(&prefix))
.collect();
match matches.len() {
0 => Err(format!("no session id starts with '{prefix}'")),
1 => Ok(matches[0].id),
_ => Err(format!(
"'{prefix}' is ambiguous — candidates:\n{}",
candidates(&matches)
)),
}
}
pub(crate) fn resolve_session_id(sessions: &[Session], id: &str) -> Result<Uuid, String> {
if let Ok(uuid) = Uuid::parse_str(id) {
return Ok(uuid);
}
resolve_one_by_prefix(sessions, id)
}
pub(crate) fn candidates(matches: &[&Session]) -> String {
matches
.iter()
.map(|s| {
format!(
" {} {}",
&s.id.to_string()[..8],
s.title.as_deref().unwrap_or("untitled")
)
})
.collect::<Vec<_>>()
.join("\n")
}
pub(crate) async fn resolve_or_create_session(
session_service: &crate::services::SessionService,
arg: Option<&str>,
default_title: &str,
) -> anyhow::Result<crate::db::models::Session> {
use crate::db::repository::SessionListOptions;
let Some(id) = arg else {
return session_service
.create_session(Some(default_title.to_string()))
.await;
};
let sessions = session_service
.list_sessions(SessionListOptions {
include_archived: true,
..Default::default()
})
.await?;
let uuid = resolve_session_id(&sessions, id).map_err(anyhow::Error::msg)?;
session_service
.get_session(uuid)
.await?
.ok_or_else(|| anyhow::anyhow!("session not found: {id}"))
}