pub use bindings::Bindings;
use std::io::{Read, Write};
use thiserror::Error;
pub mod apply_patch;
pub mod bash;
pub(crate) mod bindings;
pub mod cd;
pub(crate) mod child;
pub mod compaction;
pub mod dispatch;
pub mod load_skill;
pub mod message;
pub mod python;
pub mod read_file;
pub mod search_history;
const APPLY_PATCH: &str = "apply_patch";
const BASH: &str = "bash";
const CD: &str = "cd";
const DISPATCH: &str = "dispatch";
const LOAD_SKILL: &str = "load_skill";
const MESSAGE: &str = "message";
pub(crate) const PYTHON: &str = "python";
const READ_FILE: &str = "read_file";
const SEARCH_HISTORY: &str = "search_history";
pub const NAMES: [&str; 9] = [
APPLY_PATCH,
BASH,
CD,
DISPATCH,
LOAD_SKILL,
MESSAGE,
PYTHON,
READ_FILE,
SEARCH_HISTORY,
];
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)]
ApplyPatch(#[from] apply_patch::Error),
#[error(transparent)]
Bash(#[from] bash::Error),
#[error(transparent)]
Dispatch(#[from] dispatch::Error),
#[error(transparent)]
Message(#[from] message::Error),
#[error(transparent)]
Cd(#[from] cd::Error),
#[error(transparent)]
LoadSkill(#[from] load_skill::Error),
#[error(transparent)]
SearchHistory(#[from] search_history::Error),
#[error(transparent)]
Python(#[from] python::Error),
#[error(transparent)]
Compaction(#[from] compaction::Error),
}
#[rustfmt::skip]
pub fn run<R: Read, W: Write, E: Write>(
name: &str,
bindings: &Bindings<'_>,
stdin: &mut R,
stdout: &mut W,
stderr: &mut E,
) -> Result<i32, Error> {
if name == PYTHON {
return python::run(stdin, stdout, stderr, bindings, &dispatch::ProcessEnv)
.map_err(Error::Python);
}
let target = bindings.driver_target.to_path_buf();
let spawner = dispatch::SubprocessSpawner::with_exe(target.clone());
let sender = message::SubprocessSender::with_exe(target);
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 == APPLY_PATCH {
return apply_patch::run(stdin, stdout)
.map(|()| 0)
.map_err(Error::ApplyPatch);
}
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 == CD {
return cd::run(stdin, stdout, env).map(|()| 0).map_err(Error::Cd);
}
if name == LOAD_SKILL {
return load_skill::run(stdin, stdout, env)
.map(|()| 0)
.map_err(Error::LoadSkill);
}
if name == SEARCH_HISTORY {
return search_history::run(stdin, stdout, env)
.map(|()| 0)
.map_err(Error::SearchHistory);
}
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;