use super::channel_test_support::{TestResult, require, run};
use super::channel_wire_test_support::Publisher;
use liminal::protocol::Frame;
use liminal_sdk::{SubscriptionStream, lys_pass_credential};
use serde_json::json;
#[test]
fn agt001_send_schema_has_only_subject_text_and_optional_key() -> TestResult {
run(|_, host| {
host.initialize()?;
let listed = host.request("tools/list", &json!({}))?;
let tools = listed["result"]["tools"]
.as_array()
.ok_or("tools/list has no tools")?;
let tool = tools
.iter()
.find(|tool| tool["name"] == "send")
.ok_or("the send tool is missing")?;
let schema = &tool["inputSchema"];
require(
schema["required"] == json!(["subject", "text"]),
"send requires subject and text",
)?;
require(
schema["properties"]
.as_object()
.is_some_and(|fields| fields.len() == 3),
"send must expose exactly three arguments",
)?;
for field in ["subject", "text", "key"] {
require(
schema["properties"][field]["type"] == "string",
"every send argument is a string",
)?;
}
require(
schema["additionalProperties"] == false,
"send must refuse unknown arguments",
)
})
}
#[test]
fn agt001_send_preserves_raw_text_and_returns_the_ack_id() -> TestResult {
run(|exchange, host| {
host.initialize()?;
let credential = lys_pass_credential(&exchange.pass("beta")?);
let stream = SubscriptionStream::open_with_auth(
&exchange.address,
"agents.beta.inbox",
Vec::new(),
&credential,
)?;
let text = "{\"text\":\"alpha to beta\"}\r\n";
let answer = host.tool(
"send",
&json!({"subject":"agents.beta.inbox","text":text,"key":"first"}),
)?;
if answer["isError"] != false {
return Err(format!("a granted send must succeed: {answer}").into());
}
let data = &answer["structuredContent"];
require(
data["subject"] == "agents.beta.inbox",
"send must name its subject",
)?;
let id = data.get("id").ok_or("send must return the PublishAck id")?;
let delivered = stream.recv()?;
require(
delivered.payload() == text.as_bytes(),
"send must publish text bytes without JSON wrapping",
)?;
let message = delivered
.message()
.ok_or("delivery must carry the original server id")?;
require(
*id == json!(message.id),
"send must return the original PublishAck id without inventing one",
)
})
}
#[test]
fn agt001_ungranted_send_returns_the_real_publish_refusal_verbatim() -> TestResult {
run(|exchange, host| {
host.initialize()?;
let credential = lys_pass_credential(&exchange.pass("alpha")?);
let mut publisher = Publisher::connect(&exchange.address, &credential)?;
let Frame::PublishError {
message: Some(words),
..
} = publisher.publish("agents.ungranted.inbox", b"{}".to_vec())?
else {
return Err("the real server must return a named publish refusal".into());
};
let answer = host.tool(
"send",
&json!({"subject":"agents.ungranted.inbox","text":"{}","key":"refused"}),
)?;
require(answer["isError"] == true, "an ungranted send must fail")?;
require(
answer["structuredContent"]["subject"] == "agents.ungranted.inbox",
"send must name the refused subject",
)?;
require(
answer["structuredContent"]["error"] == words,
"send must preserve the server's refusal verbatim",
)?;
require(
answer["content"][0]["text"] == words,
"the text result must preserve the same server words",
)
})
}
#[test]
fn agt001_repeated_key_delivers_once_before_a_distinct_marker() -> TestResult {
run(|exchange, host| {
host.initialize()?;
let credential = lys_pass_credential(&exchange.pass("beta")?);
let stream = SubscriptionStream::open_with_auth(
&exchange.address,
"agents.beta.inbox",
Vec::new(),
&credential,
)?;
let arguments =
json!({"subject":"agents.beta.inbox","text":"{\"text\":\"same\"}","key":"same"});
let first = host.tool("send", &arguments)?;
let second = host.tool("send", &arguments)?;
require(
first["isError"] == false && second["isError"] == false,
"both same-key sends must answer their ack",
)?;
let marker = host.tool(
"send",
&json!({"subject":"agents.beta.inbox","text":"{\"text\":\"marker\"}","key":"distinct"}),
)?;
require(
marker["isError"] == false,
"the distinct marker must be accepted",
)?;
require(
stream.recv()?.payload() == b"{\"text\":\"same\"}",
"the first delivery must be the first publish",
)?;
require(
stream.recv()?.payload() == b"{\"text\":\"marker\"}",
"the next delivery must be the marker, with no duplicate between",
)
})
}
#[test]
fn agt001_oversize_send_is_refused_without_a_connection() -> TestResult {
run(|exchange, host| {
host.initialize()?;
let before = exchange.supervisor.active_connection_count();
let answer = host.tool(
"send",
&json!({"subject":"agents.beta.inbox","text":"x".repeat(65537)}),
)?;
require(answer["isError"] == true, "oversize text must be refused")?;
require(
answer["structuredContent"]["error"] == "text is 65537 bytes; the bound is 65536",
"oversize text must name its exact size and configured bound",
)?;
require(
exchange.supervisor.active_connection_count() == before,
"an oversize send must leave the server connection count unchanged",
)
})
}