use aura_ui::ai::acp::{AcpClient, AcpEvent};
use aura_ui::ai::mcp::McpConfig;
use serde_json::json;
use std::sync::mpsc;
use std::time::Duration;
fn fake_config() -> McpConfig {
let script = format!("{}/tests/acp_fake.py", env!("CARGO_MANIFEST_DIR"));
McpConfig { command: "python3".into(), args: vec![script], ..Default::default() }
}
fn conversation(option: Option<&str>) -> (String, Vec<AcpEvent>) {
let (sender, receiver) = mpsc::channel();
let client = AcpClient::start(&fake_config(), &std::env::temp_dir(), move |event| {
sender.send(event).expect("canal");
})
.expect("arranca el agente");
client.prompt("lee a.txt").expect("prompt");
let (mut text, mut seen) = (String::new(), Vec::new());
loop {
let event = receiver.recv_timeout(Duration::from_secs(10)).expect("evento a tiempo");
match &event {
AcpEvent::Text(chunk) => text.push_str(chunk),
AcpEvent::Permission { request, .. } => client.answer_permission(request, option).expect("respuesta"),
AcpEvent::ReadFile { request, path, .. } => {
assert_eq!(path, "a.txt");
client.answer(request, Ok(json!({ "content": "hola desde el cliente" }))).expect("archivo");
}
AcpEvent::Done(_) | AcpEvent::Error(_) => {
seen.push(event);
return (text, seen);
}
_ => {}
}
seen.push(event);
}
}
#[test]
fn permiso_concedido_el_agente_lee_el_archivo_del_cliente() {
let (text, events) = conversation(Some("si"));
assert_eq!(text, "Voy a leer. Contenido: hola desde el cliente");
assert!(matches!(events.last(), Some(AcpEvent::Done(reason)) if reason == "end_turn"));
let permission = events.iter().find_map(|event| match event {
AcpEvent::Permission { title, options, .. } => Some((title.clone(), options.len())),
_ => None,
});
assert_eq!(permission, Some(("Leer a.txt".to_owned(), 2)));
}
#[test]
fn permiso_rechazado_el_agente_no_lee_nada() {
let (text, events) = conversation(None);
assert_eq!(text, "Voy a leer. No me dejaron.");
assert!(!events.iter().any(|event| matches!(event, AcpEvent::ReadFile { .. })));
}
#[test]
fn iniciar_sesion_llama_a_authenticate_con_el_metodo_pedido() {
let dir = std::env::temp_dir();
AcpClient::authenticate(&fake_config(), &dir, "chatgpt").expect("sesión iniciada");
let error = AcpClient::authenticate(&fake_config(), &dir, "otro").expect_err("método rechazado");
assert!(error.to_string().contains("método desconocido"), "{error}");
}
#[test]
fn retoma_la_sesion_guardada_y_si_falla_abre_una_nueva() {
let dir = std::env::temp_dir();
let start = |resume: Option<&str>| {
AcpClient::start_resuming(&fake_config(), &dir, resume, |_| {})
.expect("arranca el agente")
.session_id()
.to_owned()
};
assert_eq!(start(None), "s-new");
assert_eq!(start(Some("s-viejo")), "s-viejo");
assert_eq!(start(Some("malo")), "s-new");
}