vv-agent 0.6.2

VectorVein agent runtime, SDK, CLI, tools, and workspace backends
Documentation
use std::sync::{Arc, Mutex};

use serde_json::json;
use vv_agent::{
    LLMResponse, LlmClient, LlmError, LlmRequest, Message, ScriptStep, ScriptedLlmClient,
};

#[test]
fn scripted_llm_accepts_callable_steps() {
    let seen = Arc::new(Mutex::new(Vec::new()));
    let seen_for_step = Arc::clone(&seen);
    let llm = ScriptedLlmClient::from_steps(vec![
        ScriptStep::callback(move |request| {
            seen_for_step.lock().expect("seen lock").push(format!(
                "{}:{}:{}",
                request.model,
                request.messages[0].content,
                request.tools.len()
            ));
            Ok(LLMResponse::new("dynamic response"))
        }),
        ScriptStep::response(LLMResponse::new("static response")),
    ]);

    let mut request = LlmRequest::new("model-a", vec![Message::user("hello")]);
    request.tools.push(json!({
        "type": "function",
        "function": {"name": "task_finish", "parameters": {"type": "object"}}
    }));

    let first = llm.complete(request).expect("dynamic step");
    let second = llm
        .complete(LlmRequest::new("model-b", Vec::new()))
        .expect("static step");

    assert_eq!(first.content, "dynamic response");
    assert_eq!(second.content, "static response");
    assert_eq!(
        seen.lock().expect("seen lock").as_slice(),
        ["model-a:hello:1"]
    );
}

#[test]
fn scripted_llm_reports_exhausted_steps() {
    let llm = ScriptedLlmClient::new(Vec::new());
    let error = llm
        .complete(LlmRequest::new("model", Vec::new()))
        .expect_err("empty scripted queue should fail");

    assert!(matches!(error, LlmError::ScriptExhausted));
}