swiftide_core/
agent_traits.rsuse std::path::PathBuf;
use crate::chat_completion::ChatMessage;
use anyhow::Result;
use async_trait::async_trait;
use thiserror::Error;
#[async_trait]
pub trait ToolExecutor: Send + Sync {
async fn exec_cmd(&self, cmd: &Command) -> Result<CommandOutput, CommandError>;
}
#[async_trait]
impl<T: ToolExecutor> ToolExecutor for &T {
async fn exec_cmd(&self, cmd: &Command) -> Result<CommandOutput, CommandError> {
(*self).exec_cmd(cmd).await
}
}
#[derive(Debug, Error)]
pub enum CommandError {
#[error("executor error: {0:#}")]
ExecutorError(#[from] anyhow::Error),
#[error("command failed with NonZeroExit: {0}")]
NonZeroExit(CommandOutput),
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub enum Command {
Shell(String),
ReadFile(PathBuf),
WriteFile(PathBuf, String),
}
impl Command {
pub fn shell<S: Into<String>>(cmd: S) -> Self {
Command::Shell(cmd.into())
}
pub fn read_file<P: Into<PathBuf>>(path: P) -> Self {
Command::ReadFile(path.into())
}
pub fn write_file<P: Into<PathBuf>, S: Into<String>>(path: P, content: S) -> Self {
Command::WriteFile(path.into(), content.into())
}
}
#[derive(Debug, Clone)]
pub struct CommandOutput {
pub output: String,
}
impl CommandOutput {
pub fn empty() -> Self {
CommandOutput {
output: String::new(),
}
}
pub fn new(output: impl Into<String>) -> Self {
CommandOutput {
output: output.into(),
}
}
pub fn is_empty(&self) -> bool {
self.output.is_empty()
}
}
impl std::fmt::Display for CommandOutput {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.output.fmt(f)
}
}
impl<T: Into<String>> From<T> for CommandOutput {
fn from(value: T) -> Self {
CommandOutput {
output: value.into(),
}
}
}
#[async_trait]
pub trait AgentContext: Send + Sync {
async fn next_completion(&self) -> Option<Vec<ChatMessage>>;
async fn current_new_messages(&self) -> Vec<ChatMessage>;
async fn add_messages(&self, item: Vec<ChatMessage>);
async fn add_message(&self, item: ChatMessage);
async fn exec_cmd(&self, cmd: &Command) -> Result<CommandOutput, CommandError>;
async fn history(&self) -> Vec<ChatMessage>;
}