use serde::{Deserialize, Serialize};
use serde_json::Value;
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct LoopToolResult {
pub content: Vec<Value>,
pub details: Value,
#[serde(skip_serializing_if = "Option::is_none")]
pub terminate: Option<bool>,
}
#[derive(Debug, Clone, Default)]
pub struct BeforeToolCallResult {
pub block: Option<bool>,
pub reason: Option<String>,
}
#[derive(Debug, Clone, Default)]
pub struct AfterToolCallResult {
pub content: Option<Vec<Value>>,
pub details: Option<Value>,
pub is_error: Option<bool>,
pub terminate: Option<bool>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn loop_tool_result_default() {
let r = LoopToolResult::default();
assert!(r.content.is_empty());
assert_eq!(r.details, Value::Null);
assert!(r.terminate.is_none());
}
#[test]
fn terminate_omitted_when_none() {
let r = LoopToolResult {
content: vec![],
details: Value::Null,
terminate: None,
};
let encoded = serde_json::to_string(&r).unwrap();
assert!(!encoded.contains("terminate"), "got: {encoded}");
}
#[test]
fn terminate_serializes_when_some() {
let r = LoopToolResult {
content: vec![],
details: Value::Null,
terminate: Some(true),
};
let encoded = serde_json::to_string(&r).unwrap();
assert!(encoded.contains("\"terminate\":true"), "got: {encoded}");
}
#[test]
fn before_default_is_no_block() {
let r = BeforeToolCallResult::default();
assert!(r.block.is_none());
assert!(r.reason.is_none());
}
#[test]
fn after_default_is_passthrough() {
let r = AfterToolCallResult::default();
assert!(r.content.is_none());
assert!(r.details.is_none());
assert!(r.is_error.is_none());
assert!(r.terminate.is_none());
}
}