use super::*;
const ZERO_INDEX: &str = "24:0303030303030303030303031:41:81:03:raw";
const BAD_RESULT_STATUS: &str = "24:0101010101010101010101011:21:17:success3:raw";
const SHORT_RESULT_V2: &str = "24:0202020202020202020202021:31:12:ok3:raw";
fn tid(byte: u8, sequence: u64) -> ToolCallId {
ToolCallId::new([byte; 12], sequence)
}
fn hidden_box(box_type: &str, hidden_type: &str, hidden_contents: &str) -> ChatBox {
ChatBox::new(
BoxId::new(1),
box_type.into(),
String::new(),
hidden_type.into(),
hidden_contents.into(),
)
}
#[test]
fn established_v1_encodings_are_exact_and_round_trip() {
let call = ProviderCall {
tool_call_id: tid(0xab, 7),
name: "é".into(),
arguments: "{}\n".into(),
};
let call_box = tool_call_box(&call);
assert_eq!(
(call_box.contents(), call_box.hidden_contents()),
(
"Call ID: abababababababababababab/7\nCall Name: é\nArguments:\n{}\n",
"24:abababababababababababab1:72:é3:{}\n"
)
);
assert_eq!(call_box.tool_call_metadata().unwrap(), Some(call));
let result_box = tool_result_box(tid(1, 2), BoxId::new(12), Err("bad\n".into()));
assert_eq!(
(result_box.contents(), result_box.hidden_contents()),
(
"Call ID: 010101010101010101010101/2\nOriginating Call Box ID: 12\nStatus: error\nResult:\nbad\n",
"24:0101010101010101010101011:22:123:err4:bad\n"
)
);
assert_eq!(
result_box.tool_result_metadata().unwrap(),
Some(ToolResultMetadata {
tool_call_id: tid(1, 2),
originating_call: BoxId::new(12),
result: Err("bad\n".into()),
})
);
}
#[test]
fn tool_result_v2_preserves_v1_fields_and_opaque_metadata() {
let metadata = ToolResultV2Metadata {
tool_call_id: tid(2, 3),
originating_call: BoxId::new(4),
result: Ok("✓".into()),
metadata_type: "x/y".into(),
metadata_contents: "é\0".into(),
};
let common = ToolResultMetadata {
tool_call_id: metadata.tool_call_id,
originating_call: metadata.originating_call,
result: metadata.result.clone(),
};
let value = tool_result_v2_box(&metadata);
assert_eq!(
value.hidden_contents(),
"24:0202020202020202020202021:31:42:ok3:✓3:x/y3:é\0"
);
assert_eq!(value.tool_result_metadata().unwrap(), Some(common));
assert_eq!(value.tool_result_v2_metadata().unwrap(), Some(metadata));
}
#[test]
fn tool_messages_require_and_preserve_one_based_indexes() {
let metadata = ToolMessageMetadata {
tool_call_id: tid(3, 4),
originating_call: BoxId::new(8),
message_index: 1,
message: "a\né".into(),
};
let value = tool_message_box(&metadata).unwrap();
assert_eq!(
value.hidden_contents(),
"24:0303030303030303030303031:41:81:14:a\né"
);
assert_eq!(
value.tool_message_metadata().unwrap(),
Some(metadata.clone())
);
let mut zero = metadata;
zero.message_index = 0;
assert_eq!(tool_message_box(&zero), Err(MetadataError));
let malformed = hidden_box(TOOL_MESSAGE_TYPE, TOOL_MESSAGE_HIDDEN_TYPE, ZERO_INDEX);
assert_eq!(malformed.tool_message_metadata(), Err(MetadataError));
}
#[test]
fn recognized_malformed_metadata_fails_closed() {
let call = hidden_box(TOOL_CALL_TYPE, TOOL_CALL_HIDDEN_TYPE, "1:é");
assert_eq!(call.tool_call_metadata(), Err(MetadataError));
let result = hidden_box(TOOL_RESULT_TYPE, TOOL_RESULT_HIDDEN_TYPE, BAD_RESULT_STATUS);
assert_eq!(result.tool_result_metadata(), Err(MetadataError));
let v2 = hidden_box(
TOOL_RESULT_TYPE,
TOOL_RESULT_V2_HIDDEN_TYPE,
SHORT_RESULT_V2,
);
assert_eq!(v2.tool_result_v2_metadata(), Err(MetadataError));
let wrong_call = hidden_box(USER_MESSAGE_TYPE, TOOL_CALL_HIDDEN_TYPE, "");
assert_eq!(wrong_call.tool_call_metadata(), Err(MetadataError));
let wrong_message = hidden_box(USER_MESSAGE_TYPE, TOOL_MESSAGE_HIDDEN_TYPE, "");
assert_eq!(wrong_message.tool_message_metadata(), Err(MetadataError));
let wrong_result = hidden_box(USER_MESSAGE_TYPE, TOOL_RESULT_HIDDEN_TYPE, "");
assert_eq!(wrong_result.tool_result_metadata(), Err(MetadataError));
let wrong_v2 = hidden_box(USER_MESSAGE_TYPE, TOOL_RESULT_V2_HIDDEN_TYPE, "");
assert_eq!(wrong_v2.tool_result_metadata(), Err(MetadataError));
assert_eq!(wrong_v2.tool_result_v2_metadata(), Err(MetadataError));
}
#[test]
fn unknown_hidden_conventions_remain_generic_boxes() {
let call = hidden_box(TOOL_CALL_TYPE, "future/tool-call", "anything");
assert_eq!(call.tool_call_metadata().unwrap(), None);
let result = hidden_box(TOOL_RESULT_TYPE, "future/tool-result", "anything");
assert_eq!(result.tool_result_v2_metadata().unwrap(), None);
}