//// A refused retrieval call answers with an error payload the model can
//// correct, instead of ending the turn: subagents died whole on
//// "run failed: LCM node not found in this session" after handing a
//// transcript row seq to an LCM node tool.
import albedo/daemon/conversation
import albedo/harness/extensions
import albedo/harness/extensions/lcm/memory as lcm_memory
import albedo/harness/runtime
import albedo/openai_api/types
import gleam/dynamic/decode
import gleam/json
import gleam/option.{None}
import gleam/string
import gleeunit/should
fn host() -> #(runtime.Runtime, runtime.Session) {
let assert Ok(host) =
runtime.start_with_config(
":memory:",
extensions.Config([lcm_memory.extension()], ["lcm-memory"]),
)
let ledger = runtime.ledger(host)
let assert Ok(_) = conversation.initialise(ledger)
let assert Ok(_) =
conversation.create(
ledger,
conversation.Info(
"tool-error-test",
"new session",
"/tmp",
"provider",
"model",
types.Responses,
conversation.Idle,
None,
None,
),
)
let assert Ok(session) = runtime.open_session(host, "tool-error-test", "/tmp")
#(host, session)
}
fn answer(
host: runtime.Runtime,
session: runtime.Session,
name: String,
arguments: String,
) -> String {
// The regression is Ok against Error: a refused read must not fail the run.
let assert Ok(output) =
runtime.invoke(
host,
session,
types.ToolCall("call_1", name, arguments),
types.any_images,
)
let assert types.ToolOutput(_, body, []) = output
body
}
pub fn missing_lcm_node_answers_as_tool_output_test() -> Nil {
let #(host, session) = host()
// 35049 is a transcript row seq, the exact confusion that killed a child.
let body = answer(host, session, "lcm_describe", "{\"id\":35049}")
let assert Ok(reason) =
json.parse(body, decode.field("error", decode.string, decode.success))
string.contains(reason, "LCM node 35049 not found") |> should.be_true
string.contains(reason, "transcript_read") |> should.be_true
runtime.stop(host)
}
pub fn missing_summary_scope_answers_as_tool_output_test() -> Nil {
let #(host, session) = host()
let body =
answer(
host,
session,
"lcm_grep",
"{\"pattern\":\"needle\",\"summary_id\":7}",
)
let assert Ok(reason) =
json.parse(body, decode.field("error", decode.string, decode.success))
string.contains(reason, "LCM node 7 not found") |> should.be_true
runtime.stop(host)
}
pub fn answering_tools_still_answer_normally_test() -> Nil {
let #(host, session) = host()
let body = answer(host, session, "lcm_list", "{}")
let assert Ok(total) =
json.parse(body, decode.field("total", decode.int, decode.success))
total |> should.equal(0)
runtime.stop(host)
}