vv-agent 0.6.2

VectorVein agent runtime, SDK, CLI, tools, and workspace backends
Documentation
use std::collections::BTreeMap;

use serde_json::json;

use crate::app_server::client::AppServerClient;
use crate::app_server::processor::MessageProcessor;
use crate::app_server::thread_store::SqliteThreadStore;
use crate::app_server::transport::ConnectionId;
use crate::{
    Agent, FunctionTool, LLMResponse, ModelRef, Runner, ScriptedModelProvider, ToolCall, ToolOutput,
};

pub fn scripted_app_server_client(responses: Vec<LLMResponse>) -> AppServerClient {
    let runner = Runner::builder()
        .model_provider(ScriptedModelProvider::new(
            "scripted",
            "demo-model",
            responses,
        ))
        .workspace(".")
        .build()
        .expect("runner");
    let agent = Agent::builder("assistant")
        .instructions("Answer the user, then finish.")
        .model(ModelRef::named("demo-model"))
        .build()
        .expect("agent");
    client_from_runner(runner, agent)
}

pub fn approval_app_server_client() -> AppServerClient {
    let dangerous = FunctionTool::builder("dangerous")
        .description("Requires approval.")
        .json_schema(json!({"type":"object","properties":{},"required":[]}))
        .handler(|_ctx, _args: serde_json::Value| async move { Ok(ToolOutput::text("allowed")) })
        .build()
        .expect("tool");
    let runner = Runner::builder()
        .model_provider(ScriptedModelProvider::new(
            "scripted",
            "approval-model",
            vec![
                LLMResponse::with_tool_calls(
                    "",
                    vec![ToolCall::from_raw_arguments(
                        "call_1",
                        "dangerous",
                        json!({}),
                    )],
                ),
                finish_response("done"),
            ],
        ))
        .workspace(".")
        .build()
        .expect("runner");
    let agent = Agent::builder("approver")
        .instructions("Call dangerous, then finish.")
        .model(ModelRef::named("approval-model"))
        .tool(dangerous)
        .build()
        .expect("agent");
    client_from_runner(runner, agent)
}

pub fn finish_response(message: &str) -> LLMResponse {
    let mut args = BTreeMap::new();
    args.insert("message".to_string(), json!(message));
    LLMResponse::with_tool_calls(message, vec![ToolCall::new("finish", "task_finish", args)])
}

fn client_from_runner(runner: Runner, agent: Agent) -> AppServerClient {
    let (processor, outgoing) = MessageProcessor::new_for_tests_with_runtime(
        128,
        runner,
        agent,
        SqliteThreadStore::in_memory().expect("store"),
    );
    AppServerClient::new_for_processor(processor, outgoing, ConnectionId::new(1))
}