Add BrokerPort: loopd asks brokerd for every tool call

Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
This commit is contained in:
2026-09-20 19:40:35 -07:00
parent 1ceaa36b9b
commit 469be2c0a1
13 changed files with 1142 additions and 15 deletions
+11 -5
View File
@@ -348,7 +348,7 @@ fn the_baseline_fits_the_token_budget() {
cfg.paths.home = home.clone();
cfg.baseline.system = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../config/system.md");
let baseline =
loopd::baseline::Baseline::assemble(&cfg, &loopd::tools::Registry::m2b()).unwrap();
loopd::baseline::Baseline::assemble(&cfg, &loopd::tools::Registry::m3a()).unwrap();
let client = Client::new(cfg);
// The system text plus every tool schema as the request carries it.
let mut text = baseline.system.clone();
@@ -380,17 +380,23 @@ fn a_conversation_uses_tools_survives_a_restart_and_keeps_its_cache() {
"What is the current time? Use your clock tool, then tell me the year.",
);
assert!(a2.contains("2026") || a2.contains("202"), "{a2}");
// No broker is configured here, so the call fails in plain words and the turn goes on. What
// is checked is the path: find_tool, then call_tool, then an answer.
let a3 = served.say(
&session,
"Use the echo tool to echo the word cork back to me, and reply with just that word.",
"Find a tool that reads files, use it to read /etc/hostname, and tell me in one \
sentence what happened.",
);
assert!(a3.to_lowercase().contains("cork"), "{a3}");
assert!(!a3.trim().is_empty(), "the turn must end in an answer");
served.kill();
served = Served::start(&socket, &home);
let a4 = served.say(&session, "What word did you echo a moment ago? One word.");
let a4 = served.say(
&session,
"What were the exact words I first asked you to reply with?",
);
assert!(
a4.to_lowercase().contains("cork"),
a4.to_lowercase().contains("box made"),
"after a restart the session must still know: {a4}"
);