use crate::agent::Agent;
use crate::run::DirContext;
use crate::script::LuaEngine;
use crate::Result;
use simple_fs::SPath;
use std::sync::Arc;
#[derive(Debug, Default, Clone)]
pub struct Literals {
store: Arc<Vec<(&'static str, String)>>,
}
impl Literals {
pub(super) fn from_dir_context_and_agent_path(dir_context: &DirContext, agent: &Agent) -> Result<Literals> {
let mut store = Vec::new();
let agent_path = dir_context.current_dir().join(agent.file_path())?;
let agent_path = agent_path.diff(dir_context.workspace_dir())?;
let agent_path = SPath::new(format!("./{agent_path}"))?;
let agent_dir = agent_path
.parent()
.ok_or_else(|| format!("Agent {agent_path} does not have a parent dir"))?;
let devai_dir = dir_context.devai_dir();
store.push(("PWD", dir_context.current_dir().to_string()));
store.push(("WORKSPACE_DIR", dir_context.workspace_dir().to_string()));
store.push(("DEVAI_DIR", devai_dir.devai_dir().to_string()));
store.push(("AGENT_NAME", agent.name().to_string()));
store.push(("AGENT_FILE_NAME", agent_path.name().to_string()));
store.push(("AGENT_FILE_PATH", agent_path.to_str().to_string()));
store.push(("AGENT_FILE_DIR", agent_dir.to_string()));
store.push(("AGENT_FILE_STEM", agent_path.stem().to_string()));
Ok(Self { store: Arc::new(store) })
}
}
impl Literals {
#[allow(unused)]
pub fn as_strs(&self) -> Vec<(&str, &str)> {
self.store.iter().map(|(p, v)| (*p, v.as_str())).collect()
}
}
impl Literals {
pub fn to_lua(&self, lua_engine: &LuaEngine) -> Result<mlua::Value> {
let table = lua_engine.create_table()?;
for (name, value) in self.as_strs() {
table.set(name, value)?;
}
Ok(mlua::Value::Table(table))
}
}
#[cfg(test)]
mod tests {
type Result<T> = core::result::Result<T, Box<dyn std::error::Error>>;
use crate::_test_support::run_reflective_agent;
use std::path::Path;
use value_ext::JsonValueExt;
#[tokio::test]
async fn test_run_literals_devai_dir() -> Result<()> {
let script = r#"
return {
WORKSPACE_DIR = CTX.WORKSPACE_DIR,
DEVAI_DIR = CTX.DEVAI_DIR,
AGENT_FILE_NAME = CTX.AGENT_FILE_NAME,
AGENT_FILE_PATH = CTX.AGENT_FILE_PATH,
AGENT_FILE_DIR = CTX.AGENT_FILE_DIR,
AGENT_FILE_STEM = CTX.AGENT_FILE_STEM,
}
"#;
let res = run_reflective_agent(script, None).await?;
let workspace_dir = res.x_get_as::<&str>("WORKSPACE_DIR")?;
assert!(Path::new(workspace_dir).is_absolute(), "workspace_dir must be absolute");
assert!(
workspace_dir.ends_with("tests-data/sandbox-01"),
"WORKSPACE_DIR must end with 'tests-data/sandbox-01'"
);
assert_eq!(res.x_get_as::<&str>("DEVAI_DIR")?, "./.devai");
assert_eq!(
res.x_get_as::<&str>("AGENT_FILE_PATH")?,
"./mock/reflective-agent.devai"
);
assert_eq!(res.x_get_as::<&str>("AGENT_FILE_DIR")?, "./mock");
assert_eq!(res.x_get_as::<&str>("AGENT_FILE_NAME")?, "reflective-agent.devai");
assert_eq!(res.x_get_as::<&str>("AGENT_FILE_STEM")?, "reflective-agent");
Ok(())
}
}