//! Dispatch of `subagent`: not the port, unknown keys, child ids. Do not edit. use bxcore::CallId; use bxcore::SessionId; use loopd::subagent::{self, SUBAGENT}; use loopd::tools::{Dispatch, Registry, dispatch}; #[test] fn call_tool_unwraps_subagent_and_does_not_send_it_to_the_port() { let r = Registry::m5c(); match dispatch( &r, "call_tool", r#"{"name":"subagent","arguments":{"task":"look around"}}"#, ) { Dispatch::Subagent { task } => assert_eq!(task, "look around"), other => panic!("{other:?}"), } match dispatch(&r, SUBAGENT, r#"{"task":"look around"}"#) { Dispatch::Subagent { task } => assert_eq!(task, "look around"), other => panic!("{other:?}"), } } #[test] fn unknown_keys_and_a_missing_task_are_invalid_arguments() { let r = Registry::m5c(); let cases = [ (r#"{"task":"x","extra":1}"#, "unknown field: extra"), (r#"{"text":"x"}"#, "unknown field: text"), ("{}", "task is required"), (r#"{"task":1}"#, "task must be a string"), ("[]", "arguments must be a JSON object"), ("not json", "arguments must be a JSON object"), ]; for (args, want) in cases { match dispatch(&r, SUBAGENT, args) { Dispatch::Local(text) => { assert!( text.starts_with("Denied: the arguments are not valid for this tool:"), "{args}: {text}" ); assert!(text.contains(want), "{args}: {text}"); } other => panic!("{args}: {other:?}"), } } } #[test] fn a_parent_id_that_cannot_fit_a_child_is_named_in_the_denial() { let parent = SessionId::new(&"a".repeat(59)).unwrap(); let err = subagent::child_id(&parent, CallId(1)).unwrap_err(); assert!(err.len() > 64, "{err}"); assert!(err.starts_with("sub-"), "{err}"); assert!(subagent::child_id(&SessionId::new("mm-thread").unwrap(), CallId(3)).is_ok()); }