use super::*;
pub fn session_file_target(file: &Path) -> Result<(ProjectDir, String)> {
if !file.is_file() {
bail!(
"no session transcript at {} (a `*.jsonl` target must be an existing session file)",
file.display()
);
}
if file
.components()
.any(|c| c.as_os_str().to_str() == Some("subagents"))
{
if let Some(parent_uuid) = crate::subagent::parent_session_id_from_path(file) {
let mut cur = file;
while let Some(p) = cur.parent() {
if p.file_name().and_then(|n| n.to_str()) == Some(parent_uuid.as_str()) {
if let Some(proj) = p.parent() {
return Ok((
ProjectDir {
dir: proj.to_path_buf(),
target_cwd: None,
},
parent_uuid,
));
}
}
cur = p;
}
}
}
let dir = file
.parent()
.ok_or_else(|| anyhow::anyhow!("session file {} has no parent dir", file.display()))?
.to_path_buf();
let sid = file
.file_stem()
.and_then(|s| s.to_str())
.ok_or_else(|| anyhow::anyhow!("session file {} has no stem", file.display()))?
.to_string();
Ok((
ProjectDir {
dir,
target_cwd: None,
},
sid,
))
}
pub fn extend_with_session_list(paths: &mut Vec<PathBuf>, src: &Path) -> Result<()> {
let data = if src.as_os_str() == "-" {
let mut s = String::new();
std::io::Read::read_to_string(&mut std::io::stdin(), &mut s)
.context("--sessions-from: reading stdin")?;
s
} else {
std::fs::read_to_string(src)
.with_context(|| format!("--sessions-from: reading {}", src.display()))?
};
for tok in data.split_whitespace() {
let id = tok.strip_prefix('@').unwrap_or(tok);
if is_uuid(id) || is_uuid_prefix(id) || is_subagent_id(id) {
paths.push(PathBuf::from(format!("@{id}")));
} else {
bail!(
"--sessions-from: {tok:?} is not a session id (want a uuid, a 4-11-hex uuid \
prefix, or an agent id — the ids csift emits)"
);
}
}
Ok(())
}
pub fn resolve_targets_with_session_list(
positionals: &[PathBuf],
sessions_from: Option<&Path>,
scope: SubagentScope,
caller: Caller,
) -> Result<Vec<PathBuf>> {
let mut paths = positionals.to_vec();
if let Some(src) = sessions_from {
extend_with_session_list(&mut paths, src)?;
if paths.is_empty() {
return Ok(Vec::new());
}
}
resolve_session_files(&paths, scope, caller)
}