swiftide_core/
agent_traits.rsuse std::{path::PathBuf, sync::Arc};
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
    }
}
#[async_trait]
impl ToolExecutor for Arc<dyn ToolExecutor> {
    async fn exec_cmd(&self, cmd: &Command) -> Result<CommandOutput, CommandError> {
        (**self).exec_cmd(cmd).await
    }
}
#[async_trait]
impl ToolExecutor for Box<dyn ToolExecutor> {
    async fn exec_cmd(&self, cmd: &Command) -> Result<CommandOutput, CommandError> {
        (**self).exec_cmd(cmd).await
    }
}
#[async_trait]
impl ToolExecutor for &dyn ToolExecutor {
    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>;
    async fn redrive(&self);
}
#[async_trait]
impl AgentContext for Box<dyn AgentContext> {
    async fn next_completion(&self) -> Option<Vec<ChatMessage>> {
        (**self).next_completion().await
    }
    async fn current_new_messages(&self) -> Vec<ChatMessage> {
        (**self).current_new_messages().await
    }
    async fn add_messages(&self, item: Vec<ChatMessage>) {
        (**self).add_messages(item).await;
    }
    async fn add_message(&self, item: ChatMessage) {
        (**self).add_message(item).await;
    }
    async fn exec_cmd(&self, cmd: &Command) -> Result<CommandOutput, CommandError> {
        (**self).exec_cmd(cmd).await
    }
    async fn history(&self) -> Vec<ChatMessage> {
        (**self).history().await
    }
    async fn redrive(&self) {
        (**self).redrive().await;
    }
}
#[async_trait]
impl AgentContext for Arc<dyn AgentContext> {
    async fn next_completion(&self) -> Option<Vec<ChatMessage>> {
        (**self).next_completion().await
    }
    async fn current_new_messages(&self) -> Vec<ChatMessage> {
        (**self).current_new_messages().await
    }
    async fn add_messages(&self, item: Vec<ChatMessage>) {
        (**self).add_messages(item).await;
    }
    async fn add_message(&self, item: ChatMessage) {
        (**self).add_message(item).await;
    }
    async fn exec_cmd(&self, cmd: &Command) -> Result<CommandOutput, CommandError> {
        (**self).exec_cmd(cmd).await
    }
    async fn history(&self) -> Vec<ChatMessage> {
        (**self).history().await
    }
    async fn redrive(&self) {
        (**self).redrive().await;
    }
}
#[async_trait]
impl AgentContext for &dyn AgentContext {
    async fn next_completion(&self) -> Option<Vec<ChatMessage>> {
        (**self).next_completion().await
    }
    async fn current_new_messages(&self) -> Vec<ChatMessage> {
        (**self).current_new_messages().await
    }
    async fn add_messages(&self, item: Vec<ChatMessage>) {
        (**self).add_messages(item).await;
    }
    async fn add_message(&self, item: ChatMessage) {
        (**self).add_message(item).await;
    }
    async fn exec_cmd(&self, cmd: &Command) -> Result<CommandOutput, CommandError> {
        (**self).exec_cmd(cmd).await
    }
    async fn history(&self) -> Vec<ChatMessage> {
        (**self).history().await
    }
    async fn redrive(&self) {
        (**self).redrive().await;
    }
}