agentfs 0.2.0

Agent Persistence
Documentation
//! Basic SQLite Example
//!
//! This example demonstrates:
//! - SQLite backend initialization
//! - File write/read operations
//! - KV store usage
//! - Tool call recording (workflow-based API)
//!
//! Run with: cargo run --example basic

use agentfs::{AgentFS, FileSystem, KvStore, ToolRecorder};
use agentsql::SqlBackend;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== AgentFS Basic Example (SQLite) ===\n");

    // Create a SQLite-backed agent filesystem
    println!("1. Initializing SQLite backend...");
    let backend = SqlBackend::sqlite("agent_example.db").await?;
    let agent_fs = AgentFS::new(Box::new(backend), "demo-agent", "/agent").await?;
    println!("   ✓ AgentFS initialized with agent_id: {}\n", agent_fs.agent_id());

    // File Operations
    println!("2. File Operations:");

    // Create a directory
    agent_fs.fs.mkdir("/output").await?;
    println!("   ✓ Created directory: /output");

    // Write a file
    let report_content = b"# Agent Report\n\nThis is a test report generated by the agent.";
    agent_fs.fs.write_file("/output/report.md", report_content).await?;
    println!("   ✓ Wrote file: /output/report.md");

    // Read the file back
    let read_content = agent_fs.fs.read_file("/output/report.md").await?.unwrap();
    println!("   ✓ Read file: /output/report.md ({} bytes)", read_content.len());

    // List directory contents
    let entries = agent_fs.fs.readdir("/output").await?.unwrap();
    println!("   ✓ Directory /output contains: {:?}\n", entries);

    // Key-Value Store Operations
    println!("3. Key-Value Store Operations:");

    // Store session state
    agent_fs.kv.set("session:id", b"abc-123-def").await?;
    agent_fs.kv.set("session:user", b"alice").await?;
    agent_fs.kv.set("config:theme", b"dark").await?;
    println!("   ✓ Stored 3 key-value pairs");

    // Retrieve a value
    let session_id = agent_fs.kv.get("session:id").await?.unwrap();
    println!("   ✓ Retrieved session:id = {}", String::from_utf8_lossy(&session_id));

    // Scan with prefix
    let session_keys = agent_fs.kv.scan("session:").await?;
    println!("   ✓ Keys with prefix 'session:': {:?}\n", session_keys);

    // Tool Call Recording (Workflow-based API)
    println!("4. Tool Call Recording:");

    // Start a tool call
    let params = serde_json::json!({
        "query": "What is the weather in San Francisco?",
        "location": "San Francisco, CA"
    });
    let call_id = agent_fs.tools.start("weather_api", Some(params)).await?;
    println!("   ✓ Started tool call (ID: {})", call_id);

    // Simulate tool execution
    tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;

    // Mark as successful
    let result = serde_json::json!({
        "temperature": 65,
        "condition": "Sunny",
        "humidity": 60
    });
    agent_fs.tools.success(call_id, Some(result)).await?;
    println!("   ✓ Marked tool call as successful");

    // Get tool call details
    let tool_call = agent_fs.tools.get(call_id).await?.unwrap();
    println!("   ✓ Tool call status: {:?}", tool_call.status);
    println!("   ✓ Duration: {} ms\n", tool_call.duration_ms.unwrap_or(0));

    // Record another tool call (single-shot API)
    println!("5. Single-Shot Tool Recording:");

    let start = std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)?
        .as_secs() as i64;

    tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;

    let end = std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)?
        .as_secs() as i64;

    let db_call_id = agent_fs.tools.record(
        "database_query",
        start,
        end,
        Some(serde_json::json!({"table": "users", "limit": 10})),
        Some(serde_json::json!({"rows": 10})),
        None,
    ).await?;
    println!("   ✓ Recorded database_query tool call (ID: {})\n", db_call_id);

    // Get statistics
    println!("6. Tool Call Statistics:");

    // Create a few more tool calls for stats
    for i in 0..3 {
        let id = agent_fs.tools.start("api_request", None).await?;
        tokio::time::sleep(tokio::time::Duration::from_millis(20)).await;
        if i < 2 {
            agent_fs.tools.success(id, None).await?;
        } else {
            agent_fs.tools.error(id, "Timeout").await?;
        }
    }

    let stats = agent_fs.tools.stats_for("api_request").await?.unwrap();
    println!("   Tool: {}", stats.name);
    println!("   Total calls: {}", stats.total_calls);
    println!("   Successful: {}", stats.successful);
    println!("   Failed: {}", stats.failed);
    println!("   Avg duration: {:.2} ms\n", stats.avg_duration_ms);

    println!("=== Example Complete ===");
    println!("\nDatabase file created: agent_example.db");
    println!("You can inspect it with: sqlite3 agent_example.db");

    Ok(())
}