use crate::prompt::step::STEPS_DIR;
use crate::template::GitRunner;
use crate::workspace;
use std::ffi::OsString;
use std::path::{Path, PathBuf};
pub(super) struct Caller {
pub(super) workspace: PathBuf,
pub(super) agent_id: String,
pub(super) cwd: PathBuf,
}
impl Caller {
pub(super) fn resolve(step_dir: &Path, git: &dyn GitRunner) -> Option<Self> {
let agent_dir = step_dir.parent()?;
let agent_id = agent_dir.file_name()?.to_str()?.to_string();
let workspace = agent_dir
.parent()
.filter(|p| p.ends_with(STEPS_DIR))?
.parent()?;
let worktree = workspace::agent_worktree(workspace, &agent_id);
if !worktree.is_dir() {
return None;
}
let moved = workspace::cwd::read(workspace, &agent_id, git);
let cwd = moved.filter(|p| p.is_dir()).unwrap_or(worktree);
Some(Self {
workspace: workspace.to_path_buf(),
agent_id,
cwd,
})
}
pub(super) fn record_rel(&self, dir: &Path) -> PathBuf {
dir.strip_prefix(&self.workspace)
.unwrap_or(dir)
.to_path_buf()
}
pub(super) fn env(&self) -> Vec<(&'static str, OsString)> {
vec![
(
crate::prompt::tool::ENV_CONV_BRANCH,
OsString::from(&self.agent_id),
),
(
crate::prompt::tool::ENV_CONV_REPO,
self.workspace.as_os_str().to_owned(),
),
]
}
}
#[cfg(test)]
mod tests {
use super::Caller;
use std::path::{Path, PathBuf};
fn caller(workspace: &str) -> Caller {
Caller {
workspace: PathBuf::from(workspace),
agent_id: "a".into(),
cwd: PathBuf::from(workspace).join("agents/a"),
}
}
#[test]
fn record_rel_strips_the_workspace_prefix() {
let rel = caller("/ws").record_rel(Path::new("/ws/steps/a/001/tools/tu_1"));
assert_eq!(rel, Path::new("steps/a/001/tools/tu_1"));
}
#[test]
fn record_rel_is_total_off_the_workspace() {
let rel = caller("/ws").record_rel(Path::new("/elsewhere/tools/tu_1"));
assert_eq!(rel, Path::new("/elsewhere/tools/tu_1"));
}
}