### Run Friendev Application with Options Source: https://github.com/helloaixiaoji/friendev/blob/master/AGENTS.md Shows different ways to start the Friendev application, including basic startup, auto-approval mode, smart approval mode, and forcing configuration setup. ```bash # Basic startup cargo run --release # With auto-approval (bypasses approval prompts) cargo run --release -- --ally # With smart approval mode (AI reviews approval prompts) cargo run --release -- --shorekeeper # Force setup configuration cargo run --release -- --setup ``` -------------------------------- ### Build and Run Friendev Project Source: https://github.com/helloaixiaoji/friendev/blob/master/AGENTS.md Commands to clone the repository, build the project in release mode, and run the application. Assumes Rust and Cargo are installed. ```bash # Clone the repository git clone cd friendev # Build the project cargo build --release # Run the application cargo run --release ``` -------------------------------- ### Minimal Rust Example for Friendev Application Source: https://context7.com/helloaixiaoji/friendev/llms.txt Provides a minimal working example for the Friendev application, demonstrating the essential steps of initializing the application state and then running the interactive REPL loop. This serves as a basic entry point for the application. ```rust use anyhow::Result; #[tokio::main] async fn main() -> Result<()> { // Initialize application (config, i18n, session, API client) let state = app::initialize_app().await?; // Run interactive REPL loop app::run_repl(state).await?; Ok(()) } ``` -------------------------------- ### Initialize API Client Source: https://context7.com/helloaixiaoji/friendev/llms.txt Demonstrates how to load configuration and initialize the ApiClient for use with AI models. It handles both existing configuration files and interactive setup. ```APIDOC ## POST /api/client/initialize ### Description Initializes the API client by loading configuration from `~/.friendev/config.json`. If the configuration file is not found, it initiates an interactive setup process. ### Method POST ### Endpoint /api/client/initialize ### Parameters #### Query Parameters None #### Request Body None ### Request Example ```rust use api::ApiClient; use config::Config; #[tokio::main] async fn main() -> anyhow::Result<()> { // Load configuration from ~/.friendev/config.json let config = match Config::load()? { Some(c) => c, None => Config::initialize()?, }; // Create API client with 5-minute timeout and retry logic let api_client = ApiClient::new(config.clone()); println!("API Client configured for: {}", config.api_url); println!("Using model: {}", config.current_model); Ok(()) } ``` ### Response #### Success Response (200) - **ApiClient** (object) - An initialized API client ready for use. #### Response Example ```json { "message": "API Client initialized successfully." } ``` ``` -------------------------------- ### Initialize and Run REPL Application in Rust Source: https://context7.com/helloaixiaoji/friendev/llms.txt Shows the complete application startup process, including initialization of application state and running the Read-Eval-Print Loop (REPL). The initialization supports command-line flags for auto-approval and forced setup. The REPL supports multi-line input and various exit/interrupt commands. ```rust use app::{initialize_app, run_repl}; use anyhow::Result; #[tokio::main] async fn main() -> Result<()> { // Initialize application with command line flags support: // --ally / --yolo: Auto-approve all operations // --shorekeeper: AI-powered smart approval // --setup: Force configuration setup let state = initialize_app().await?; // State includes: // - config: Configuration settings // - i18n: Internationalization // - session: Chat session with history // - api_client: API client for AI communication // - auto_approve: Boolean flag for approval mode println!("Friendev initialized successfully!"); println!("Model: {}", state.config.current_model); println!("Session: {}", state.session.id); println!("Auto-approve: {}", state.auto_approve); // Run REPL loop with reedline input editor // Supports: multi-line input, Ctrl+C (double tap to exit), // Ctrl+D to exit, ESC to interrupt, ! prefix for prompt optimization run_repl(state).await?; Ok(()) } ``` -------------------------------- ### Rust: Initialize API Client with Configuration Source: https://context7.com/helloaixiaoji/friendev/llms.txt Initializes the API client by loading configuration from '~/.friendev/config.json' or performing an interactive setup if the configuration is not found. The client is then created with specified timeout and retry logic, making it ready for streaming chat completions. ```rust use api::ApiClient; use config::Config; #[tokio::main] async fn main() -> anyhow::Result<()> { // Load configuration from ~/.friendev/config.json let config = match Config::load()? { Some(c) => c, None => Config::initialize()?, }; // Create API client with 5-minute timeout and retry logic let api_client = ApiClient::new(config.clone()); // The client is now ready for streaming chat completions println!("API Client configured for: {}", config.api_url); println!("Using model: {}", config.current_model); Ok(()) } ``` -------------------------------- ### Resetting Friendev Configuration Source: https://github.com/helloaixiaoji/friendev/blob/master/AGENTS.md Demonstrates the bash command to reset the Friendev application's configuration by removing its configuration directory and then running the application with a setup flag. ```bash # Reset configuration rm -rf ~/.friendev/ cargo run --release -- --setup ``` -------------------------------- ### Stream Chat Completions Source: https://context7.com/helloaixiaoji/friendev/llms.txt Provides an example of streaming chat completions from the AI model with automatic retry logic. This is useful for interactive chat applications where responses should appear as they are generated. ```APIDOC ## POST /api/chat/stream ### Description Streams chat completions from the AI model. It supports automatic retries with exponential backoff in case of network issues or API errors. The stream processes chunks of the response, including text content and tool calls. ### Method POST ### Endpoint /api/chat/stream ### Parameters #### Query Parameters None #### Request Body - **messages** (array[object]) - Required - A list of message objects representing the conversation history. Each message object should have `role` (string: 'system', 'user', 'assistant'), `content` (string), and optional `tool_calls` (array), `tool_call_id` (string), `name` (string). ### Request Example ```rust use api::ApiClient; use history::Message; use futures::StreamExt; async fn chat_with_retry(api_client: &ApiClient) -> anyhow::Result<()> { let messages = vec![ Message { role: "system".to_string(), content: "You are a helpful coding assistant.".to_string(), tool_calls: None, tool_call_id: None, name: None, }, Message { role: "user".to_string(), content: "Write a function to calculate fibonacci numbers".to_string(), tool_calls: None, tool_call_id: None, name: None, }, ]; let mut stream = api_client.chat_stream_with_retry(messages).await?; while let Some(chunk_result) = stream.next().await { match chunk_result { Ok(chunk) => { if let Some(content) = chunk.delta_content { print!("{}", content); } if let Some(tool_calls) = chunk.delta_tool_calls { for tool_call in tool_calls { println!("\nTool call: {} - {}", tool_call.name, tool_call.arguments); } } } Err(e) => eprintln!("Stream error: {}", e), } } Ok(()) } ``` ### Response #### Success Response (200) - **StreamChunk** (object) - A chunk of the streamed response. Contains `delta_content` (string, optional) and `delta_tool_calls` (array[object], optional). #### Response Example ```json { "delta_content": "Here is a function..." } ``` ```json { "delta_tool_calls": [ { "name": "fibonacci_calculator", "arguments": "{\"n\": 10}" } ] } ``` ``` -------------------------------- ### Perform Advanced File Editing with Diff Hunks in Rust Source: https://context7.com/helloaixiaoji/friendev/llms.txt Enables precise, multi-location file modifications using diff-style hunks. This function utilizes `tools::execute_tool` with the `file_diff_edit` command. It requires the file path and a list of hunks, each specifying the start line, number of lines to replace, and the new content. The output indicates success or failure with a descriptive message. ```rust use tools::execute_tool; use serde_json::json; async fn diff_based_editing() -> anyhow::Result<()> { // Edit file using diff-style hunks for precise multi-location changes let diff_result = execute_tool( "file_diff_edit", json!({ "path": "./src/lib.rs", "hunks": [ { "start_line": 1, "num_lines": 2, "new_content": "// Updated module\n// Version 2.0\n" }, { "start_line": 10, "num_lines": 5, "new_content": "pub fn new_implementation() {\n // Refactored logic\n}\n" } ] }) ).await?; if diff_result.success { println!("Applied strof hunks successfully", 2); } else { eprintln!("Diff edit failed: strof", diff_result.message); } Ok(()) } ``` -------------------------------- ### Compile Friendev for Different Targets Source: https://github.com/helloaixiaoji/friendev/blob/master/AGENTS.md Demonstrates how to build the Friendev project for the current platform, a specific target, and using cross-compilation tools for multi-platform support. ```bash # Build for current platform cargo build --release # Build for specific target cargo build --release --target x86_64-unknown-linux-gnu # Cross-compilation (requires cross tool) cargo install cross --locked cross build --release --target x86_64-unknown-musl ``` -------------------------------- ### Execute Friendev Project Tests Source: https://github.com/helloaixiaoji/friendev/blob/master/AGENTS.md Provides commands to run all tests, execute tests with verbose output, and run tests for a specific crate within the Friendev project. ```bash # Run all tests cargo test # Run tests with verbose output cargo test -- --verbose # Run tests for specific crate cargo test -p app ``` -------------------------------- ### Friendev Project Structure Overview Source: https://github.com/helloaixiaoji/friendev/blob/master/AGENTS.md Illustrates the directory structure of the Friendev project, highlighting key modules for AI assistance, API integration, UI, and development tools. ```tree friendev/ ├── agents_md_file/ # AGENTS.md generation and management ├── api/ # API client and network communication ├── app/ # Main application logic and REPL ├── chat/ # Chat session management ├── commands/ # Command implementations ├── config/ # Configuration management ├── history/ # Chat history persistence ├── i18n/ # Internationalization support ├── prompts/ # Prompt templates and optimization ├── search_tool/ # Web search functionality ├── security/ # Security and approval mechanisms ├── src/ # Root source (main entry point) ├── target/ # Build artifacts ├── tools/ # Development tools and utilities └── ui/ # User interface components ``` -------------------------------- ### Load and Update Configuration using Rust Source: https://context7.com/helloaixiaoji/friendev/llms.txt This Rust code snippet demonstrates how to load an existing configuration, initialize a new one if it doesn't exist, update model and UI language settings, and save the configuration. It utilizes the `config` and `anyhow` crates for configuration management and error handling. The function prompts for user input during initialization and prints current and updated settings. ```rust use config::Config; use anyhow::Result; #[tokio::main] async fn main() -> Result<()> { // Load existing config or create new one let mut config = match Config::load()? { Some(c) => c, None => { println!("No config found, starting interactive setup..."); Config::initialize()? // Prompts user for API key, URL, model, language } }; println!("Current model: {}", config.current_model); println!("API URL: {}", config.api_url); println!("UI Language: {}", config.ui_language); // Update model and save config.update_model("gpt-4".to_string())?; config.save()?; println!("Updated model to: {}", config.current_model); // Update UI language config.update_ui_language("zh-CN".to_string())?; config.save()?; // Get config directory and file paths let config_dir = Config::config_dir()?; let config_path = Config::config_path()?; println!("Config stored at: {}", config_path.display()); Ok(()) } ``` -------------------------------- ### Manage Friendev Code Style and Linting Source: https://github.com/helloaixiaoji/friendev/blob/master/AGENTS.md Commands for checking code formatting, applying standard formatting using `cargo fmt`, and running `clippy` for linting and code analysis. ```bash # Check code style cargo fmt -- --check # Format code cargo fmt # Run clippy lints cargo clippy -- -D warnings ``` -------------------------------- ### Troubleshooting Build Failures in Rust Source: https://github.com/helloaixiaoji/friendev/blob/master/AGENTS.md Provides common bash commands to resolve build issues in a Rust project. Includes updating the toolchain, cleaning build artifacts, and checking for missing dependencies. ```bash # Update Rust toolchain rustup update stable # Clean build artifacts cargo clean # Check for missing dependencies cargo check --all ``` -------------------------------- ### List Available Tools and Descriptions in Rust Source: https://context7.com/helloaixiaoji/friendev/llms.txt Illustrates how to retrieve and display a list of available tools and their descriptions from the `tools` module. This allows users to see what functionalities are available for the AI to use, such as file operations, network searches, and command execution. ```rust use tools::{get_available_tools, get_tools_description}; fn main() { // Get all tool definitions for AI API let tools = get_available_tools(); println!("Available tools: {}", tools.len()); for tool in &tools { println!("- {} ({}): {}", tool.function.name, tool.tool_type, tool.function.description ); } // Get human-readable description let description = get_tools_description(); println!("\nTools description:\n{}", description); // Tools include: // file_list, file_read, file_write, file_replace, file_search, // file_outline, file_search_by_outline, index_file, file_diff_edit, // network_search_auto, network_search_duckduckgo, network_search_bing, // network_get_content, run_command } ``` -------------------------------- ### Git Pull Request Workflow Source: https://github.com/helloaixiaoji/friendev/blob/master/AGENTS.md Outlines the steps for preparing code for a pull request, including updating the main branch, creating a bugfix branch, committing changes, and pushing the branch. ```bash # Pull request process git checkout main git pull origin main git checkout -b feature/bugfix # ... make changes ... git commit -m "fix: resolve issue #123" git push origin feature/bugfix ``` -------------------------------- ### Rust Project Dependency Configuration Source: https://github.com/helloaixiaoji/friendev/blob/master/AGENTS.md Illustrates how internal dependencies are managed in a Rust project using path dependencies with version constraints. This allows for modular development within a workspace. ```toml [dependencies] api = { path = "../api", version = "0.1.0" } config = { path = "../config", version = "0.1.0" } # ... etc ``` -------------------------------- ### Execute System Commands in Rust (Foreground/Background) Source: https://context7.com/helloaixiaoji/friendev/llms.txt Allows execution of system commands, with options for foreground (blocking) or background (non-blocking) execution. It uses `tools::execute_tool` with the `run_command` tool. Inputs include the command string and a boolean `background` flag. Foreground execution returns the command output, while background execution returns a run ID. ```rust use tools::execute_tool; use serde_json::json; async fn run_system_commands() -> anyhow::Result<()> { // Run command in foreground (waits for completion) let fg_result = execute_tool( "run_command", json!({ "command": "cargo build --release", "background": false }) ).await?; println!("Build output:\n strof", fg_result.message); // Run command in background (returns immediately with run_id) let bg_result = execute_tool( "run_command", json!({ "command": "cargo test", "background": true }) ).await?; println!("Started background task: strof", bg_result.message); Ok(()) } ``` -------------------------------- ### Enabling Debug Logging and Backtraces in Rust Source: https://github.com/helloaixiaoji/friendev/blob/master/AGENTS.md Shows how to enable detailed logging and backtraces for debugging Rust applications. These environment variables help in diagnosing runtime issues. ```bash # Enable debug logging RUST_LOG=debug cargo run --release # Enable backtraces RUST_BACKTRACE=1 cargo run --release ``` -------------------------------- ### File Operations Tools using Rust Source: https://context7.com/helloaixiaoji/friendev/llms.txt This Rust code snippet showcases the use of file operation tools within the Friendev project. It demonstrates reading file content, writing (overwriting and appending) to files, replacing content with batch edits using regular expressions, and listing directory contents. It relies on the `tools` crate for executing these operations and `serde_json` for JSON payload construction. ```rust use tools::{execute_tool, ToolResult}; use serde_json::json; #[tokio::main] async fn main() -> anyhow::Result<()> { // Read file content let read_result = execute_tool( "file_read", json!({ "path": "./src/main.rs" }) ).await?; if read_result.success { println!("File content:\n{}", read_result.message); } // Write to file (overwrite mode by default) let write_result = execute_tool( "file_write", json!({ "path": "./output.txt", "content": "Hello from Friendev", "mode": "overwrite" }) ).await?; // Append to file let append_result = execute_tool( "file_write", json!({ "path": "./output.txt", "content": "\nAdditional line", "mode": "append" }) ).await?; // Replace content in file with batch edits let replace_result = execute_tool( "file_replace", json!({ "path": "./src/main.rs", "edits": [ { "old": "fn main()", "new": "#[tokio::main]\nasync fn main()", "replace_all": false, "normalize": false }, { "old": "println!\\(.*\\)", "new": "log::info!(\"Updated\")", "replace_all": true, "regex": true } ] }) ).await?; // List files in directory let list_result = execute_tool( "file_list", json!({ "path": "./src" }) ).await?; Ok(()) } ``` -------------------------------- ### Git Feature Branch Workflow Source: https://github.com/helloaixiaoji/friendev/blob/master/AGENTS.md Illustrates the standard Git workflow for creating and pushing a new feature branch. This is a common practice for collaborative development. ```bash # Feature branch workflow git checkout -b feature/new-feature git commit -m "feat: add new feature" git push origin feature/new-feature ``` -------------------------------- ### Handle Built-in Commands in Rust Source: https://context7.com/helloaixiaoji/friendev/llms.txt Demonstrates handling various built-in commands within the Friendev application using the `handle_command` function. These commands control application settings like model selection, history management, UI language, and more. It requires `commands`, `config`, `history`, and `api` modules. ```rust use commands::handle_command; use config::Config; use history::ChatSession; use api::ApiClient; use std::env; #[tokio::main] async fn main() -> anyhow::Result<()> { let mut config = Config::load()?.unwrap(); let mut session = ChatSession::new(env::current_dir()?); let mut api_client = ApiClient::new(config.clone()); // Switch model handle_command("/model gpt-4", &mut config, &mut session, &mut api_client).await?; // List available models handle_command("/model list", &mut config, &mut session, &mut api_client).await?; // View history handle_command("/history list", &mut config, &mut session, &mut api_client).await?; // Export history handle_command("/history export", &mut config, &mut session, &mut api_client).await?; // Change UI language handle_command("/language ui zh-CN", &mut config, &mut session, &mut api_client).await?; // Change AI language handle_command("/language ai Chinese", &mut config, &mut session, &mut api_client).await?; // Generate AGENTS.md documentation handle_command("/agents.md", &mut config, &mut session, &mut api_client).await?; // Manage outline index handle_command("/index outline", &mut config, &mut session, &mut api_client).await?; // Display help handle_command("/help", &mut config, &mut session, &mut api_client).await?; // Exit application // handle_command("/exit", &mut config, &mut session, &mut api_client).await?; Ok(()) } ``` -------------------------------- ### Search and Code Analysis Tools using Rust Source: https://context7.com/helloaixiaoji/friendev/llms.txt This Rust code snippet demonstrates advanced file and code analysis capabilities using Friendev's tool execution system. It covers searching for patterns within files (similar to `ripgrep`), extracting code outlines using Tree-sitter, searching an outline index with SQL LIKE syntax, and updating the outline index for a specific file. ```rust use tools::execute_tool; use serde_json::json; async fn search_and_analyze() -> anyhow::Result<()> { // Search for pattern in files (like ripgrep) let search_result = execute_tool( "file_search", json!({ "pattern": "async fn.*\\(", "path": "./src", "include": "*.rs", "ignore_case": false }) ).await?; println!("Search results:\n{}", search_result.message); // Extract code outline using Tree-sitter let outline_result = execute_tool( "file_outline", json!({ "path": "./src/main.rs" }) ).await?; println!("Functions and structs:\n{}", outline_result.message); // Search outline index (database-backed, fast) let outline_search = execute_tool( "file_search_by_outline", json!({ "pattern": "process%" // SQL LIKE syntax }) ).await?; // Update outline index for a file let index_result = execute_tool( "index_file", json!({ "path": "./src/new_module.rs" }) ).await?; Ok(()) } ``` -------------------------------- ### Perform Network Searches and Fetch Web Content in Rust Source: https://context7.com/helloaixiaoji/friendev/llms.txt Executes network search operations using different engines (auto-detect, DuckDuckGo, Bing) and fetches web page content. It utilizes the `tools::execute_tool` function and requires `serde_json` for JSON payload construction. Inputs include search keywords, max results, URLs, and max bytes for content fetching. Outputs are search results or fetched content messages. ```rust use tools::execute_tool; use serde_json::json; async fn web_operations() -> anyhow::Result<()> { // Automatic search with fallback (DuckDuckGo -> Bing) let search_result = execute_tool( "network_search_auto", json!({ "keywords": "rust async programming", "max_results": 10 }) ).await?; println!("Search results:\n{}", search_result.message); // Direct DuckDuckGo search let ddg_result = execute_tool( "network_search_duckduckgo", json!({ "keywords": "tokio runtime", "max_results": 5 }) ).await?; // Direct Bing search let bing_result = execute_tool( "network_search_bing", json!({ "keywords": "rust error handling", "max_results": 5 }) ).await?; // Fetch web page content let content_result = execute_tool( "network_get_content", json!({ "url": "https://doc.rust-lang.org/book/", "max_bytes": 100000 }) ).await?; if content_result.success { println!("Fetched content (first 500 chars):\n strof{}", &content_result.message[..500.min(content_result.message.len())]); } Ok(()) } ``` -------------------------------- ### Manage Chat Sessions and Messages in Rust Source: https://context7.com/helloaixiaoji/friendev/llms.txt Provides functionality to create, manage, and persist chat sessions. It uses the `history::{ChatSession, Message, ToolCall, FunctionCall}` structs. Key operations include creating a new session, adding user/assistant/tool messages, saving the session to disk, retrieving all messages, and cleaning up empty sessions. Dependencies include `tokio` for async operations and `std::env`. ```rust use history::{ChatSession, Message, ToolCall, FunctionCall}; use std::env; #[tokio::main] async fn main() -> anyhow::Result<()> { let working_dir = env::current_dir()?; // Create new session with unique ID let mut session = ChatSession::new(working_dir.clone()); println!("Session ID: strof", session.id); // Add user message session.add_message(Message { role: "user".to_string(), content: "Help me refactor this code".to_string(), tool_calls: None, tool_call_id: None, name: None, }); // Add assistant message with tool calls session.add_message(Message { role: "assistant".to_string(), content: "I'll read the file first.".to_string(), tool_calls: Some(vec![ ToolCall { id: "call_abc123".to_string(), call_type: "function".to_string(), function: FunctionCall { name: "file_read".to_string(), arguments: r#"{{\"path\": \"./src/main.rs\"}}"# }, } ]), tool_call_id: None, name: None, }); // Add tool response session.add_message(Message { role: "tool".to_string(), content: "fn main() { println!(\"Hello\"); }".to_string(), tool_calls: None, tool_call_id: Some("call_abc123".to_string()), name: Some("file_read".to_string()), }); // Save session to disk (~/.friendev/history/.json) session.save()?; // Get all messages let messages = session.get_messages(); println!("Total messages: strof", messages.len()); // Cleanup empty sessions ChatSession::cleanup_empty_sessions()?; Ok(()) } ``` -------------------------------- ### Rust: Stream Chat Completions with Automatic Retry Source: https://context7.com/helloaixiaoji/friendev/llms.txt Streams chat completions from the API client, including automatic retry logic with exponential backoff. It processes streaming chunks, printing content and identifying tool calls. Errors during streaming are printed to stderr. ```rust use api::ApiClient; use history::Message; use futures::StreamExt; async fn chat_with_retry(api_client: &ApiClient) -> anyhow::Result<()> { let messages = vec![ Message { role: "system".to_string(), content: "You are a helpful coding assistant.".to_string(), tool_calls: None, tool_call_id: None, name: None, }, Message { role: "user".to_string(), content: "Write a function to calculate fibonacci numbers".to_string(), tool_calls: None, tool_call_id: None, name: None, }, ]; // Automatic retry with exponential backoff (configured by max_retries and retry_delay_ms) let mut stream = api_client.chat_stream_with_retry(messages).await?; // Process streaming chunks while let Some(chunk_result) = stream.next().await { match chunk_result { Ok(chunk) => { if let Some(content) = chunk.delta_content { print!("{}", content); } if let Some(tool_calls) = chunk.delta_tool_calls { for tool_call in tool_calls { println!("\nTool call: {} - {}", tool_call.name, tool_call.arguments); } } } Err(e) => eprintln!("Stream error: {}", e), } } Ok(()) } ``` -------------------------------- ### Conventional Commit Message Format Source: https://github.com/helloaixiaoji/friendev/blob/master/AGENTS.md Defines the structure and types for commit messages following the Conventional Commits standard. This ensures consistency in the project's commit history. ```plaintext (): [body]