use std::io::{Read, Write};
use std::path::Path;
use thiserror::Error;
pub mod bash;
pub mod compaction;
pub mod dispatch;
pub mod load_skill;
pub mod message;
pub mod read_file;
const BASH: &str = "bash";
const DISPATCH: &str = "dispatch";
const LOAD_SKILL: &str = "load_skill";
const MESSAGE: &str = "message";
const READ_FILE: &str = "read_file";
pub const NAMES: [&str; 5] = [BASH, DISPATCH, LOAD_SKILL, MESSAGE, READ_FILE];
pub fn pool() -> String {
NAMES.join(", ")
}
#[derive(Debug, Error)]
pub enum Error {
#[error("unknown built-in tool: {0:?}; available: {available}", available = pool())]
Unknown(String),
#[error(transparent)]
ReadFile(#[from] read_file::Error),
#[error(transparent)]
Bash(#[from] bash::Error),
#[error(transparent)]
Dispatch(#[from] dispatch::Error),
#[error(transparent)]
Message(#[from] message::Error),
#[error(transparent)]
LoadSkill(#[from] load_skill::Error),
#[error(transparent)]
Compaction(#[from] compaction::Error),
}
#[rustfmt::skip]
pub fn run<R: Read, W: Write, E: Write>(
name: &str,
driver_target: &Path,
stdin: &mut R,
stdout: &mut W,
stderr: &mut E,
) -> Result<i32, Error> {
let spawner = dispatch::SubprocessSpawner::with_exe(driver_target.to_path_buf());
let sender = message::SubprocessSender::with_exe(driver_target.to_path_buf());
run_with(name, stdin, stdout, stderr, &dispatch::ProcessEnv, &spawner, &sender)
}
pub fn run_with<R: Read, W: Write, E: Write>(
name: &str,
stdin: &mut R,
stdout: &mut W,
stderr: &mut E,
env: &dyn dispatch::EnvLookup,
spawner: &dyn dispatch::Spawner,
sender: &dyn message::Sender,
) -> Result<i32, Error> {
if name == READ_FILE {
return read_file::run(stdin, stdout)
.map(|()| 0)
.map_err(Error::ReadFile);
}
if name == BASH {
return bash::run(stdin, stdout, stderr).map_err(Error::Bash);
}
if name == DISPATCH {
return dispatch::run(stdin, stdout, env, spawner)
.map(|()| 0)
.map_err(Error::Dispatch);
}
if name == MESSAGE {
return message::run(stdin, stdout, env, sender)
.map(|()| 0)
.map_err(Error::Message);
}
if name == LOAD_SKILL {
return load_skill::run(stdin, stdout, env)
.map(|()| 0)
.map_err(Error::LoadSkill);
}
if name == crate::prompt::compactor::tools::WRITE_SUMMARY {
return compaction::run_write_summary(stdin, stdout, env)
.map(|()| 0)
.map_err(Error::Compaction);
}
if name == crate::prompt::compactor::tools::MARK_FOR_DELETION {
return compaction::run_mark_for_deletion(stdin, stdout, env)
.map(|()| 0)
.map_err(Error::Compaction);
}
Err(Error::Unknown(name.to_string()))
}
#[cfg(test)]
mod tests;