feat: Implement aishell - AI-powered shell automation tool
Implemented a generic alternative to Claude Code with the following features: Core Implementation: - Multi-LLM provider support (OpenAI compatible APIs) - Function calling for direct tool execution by LLM - Interactive REPL shell interface - MCP server mode for Claude Desktop integration - Shell executor with bash, read, write, list tools Architecture: - src/cli: Interactive REPL implementation - src/llm: LLM provider abstraction (OpenAI compatible) - src/shell: Shell execution engine with duct - src/mcp: MCP server for Claude Desktop - src/config: Configuration management Technical Stack: - Rust 2021 with tokio async runtime - clap for CLI framework - reqwest for HTTP client - duct for shell execution - rustyline for REPL interface This tool integrates with aigpt to form AIOS (AI Operating System), enabling AI-driven OS management and automation. Based on aigpt architecture for CLI and MCP patterns.
This commit is contained in:
104
src/llm/provider.rs
Normal file
104
src/llm/provider.rs
Normal file
@@ -0,0 +1,104 @@
|
||||
use anyhow::Result;
|
||||
use async_trait::async_trait;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum Role {
|
||||
System,
|
||||
User,
|
||||
Assistant,
|
||||
Tool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Message {
|
||||
pub role: Role,
|
||||
pub content: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub tool_calls: Option<Vec<ToolCall>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub tool_call_id: Option<String>,
|
||||
}
|
||||
|
||||
impl Message {
|
||||
pub fn system(content: impl Into<String>) -> Self {
|
||||
Self {
|
||||
role: Role::System,
|
||||
content: content.into(),
|
||||
tool_calls: None,
|
||||
tool_call_id: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn user(content: impl Into<String>) -> Self {
|
||||
Self {
|
||||
role: Role::User,
|
||||
content: content.into(),
|
||||
tool_calls: None,
|
||||
tool_call_id: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn assistant(content: impl Into<String>) -> Self {
|
||||
Self {
|
||||
role: Role::Assistant,
|
||||
content: content.into(),
|
||||
tool_calls: None,
|
||||
tool_call_id: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tool(content: impl Into<String>, tool_call_id: String) -> Self {
|
||||
Self {
|
||||
role: Role::Tool,
|
||||
content: content.into(),
|
||||
tool_calls: None,
|
||||
tool_call_id: Some(tool_call_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ToolCall {
|
||||
pub id: String,
|
||||
#[serde(rename = "type")]
|
||||
pub call_type: String,
|
||||
pub function: FunctionCall,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct FunctionCall {
|
||||
pub name: String,
|
||||
pub arguments: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ToolDefinition {
|
||||
#[serde(rename = "type")]
|
||||
pub tool_type: String,
|
||||
pub function: FunctionDefinition,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct FunctionDefinition {
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
pub parameters: serde_json::Value,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ChatResponse {
|
||||
pub content: String,
|
||||
pub tool_calls: Option<Vec<ToolCall>>,
|
||||
pub finish_reason: String,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait LLMProvider: Send + Sync {
|
||||
/// Send a chat completion request
|
||||
async fn chat(&self, messages: Vec<Message>, tools: Option<Vec<ToolDefinition>>) -> Result<ChatResponse>;
|
||||
|
||||
/// Get the model name
|
||||
fn model_name(&self) -> &str;
|
||||
}
|
||||
Reference in New Issue
Block a user