use serde_json::{Value, json};
pub fn thread_started(thread_id: &str) -> Value {
json!({ "type": "thread.started", "thread_id": thread_id })
}
pub fn turn_started() -> Value {
json!({ "type": "turn.started" })
}
pub fn turn_completed(input: u64, cached: u64, output: u64) -> Value {
json!({
"type": "turn.completed",
"usage": { "input_tokens": input, "cached_input_tokens": cached, "output_tokens": output }
})
}
pub fn turn_failed(message: &str) -> Value {
json!({ "type": "turn.failed", "error": { "message": message } })
}
pub fn agent_message_started(id: &str) -> Value {
json!({ "type": "item.started", "item": { "type": "agent_message", "id": id, "text": "" } })
}
pub fn agent_message_updated(id: &str, text: &str) -> Value {
json!({ "type": "item.updated", "item": { "type": "agent_message", "id": id, "text": text } })
}
pub fn agent_message_completed(id: &str, text: &str) -> Value {
json!({ "type": "item.completed", "item": { "type": "agent_message", "id": id, "text": text } })
}
pub fn command_started(id: &str, command: &str) -> Value {
json!({ "type": "item.started", "item": {
"type": "command_execution", "id": id, "command": command,
"aggregated_output": "", "status": "in_progress"
}})
}
pub fn command_completed(id: &str, command: &str, output: &str, exit_code: i32) -> Value {
json!({ "type": "item.completed", "item": {
"type": "command_execution", "id": id, "command": command,
"aggregated_output": output, "exit_code": exit_code, "status": "completed"
}})
}
pub fn reasoning_started(id: &str) -> Value {
json!({ "type": "item.started", "item": { "type": "reasoning", "id": id, "text": "" } })
}
pub fn reasoning_completed(id: &str, text: &str) -> Value {
json!({ "type": "item.completed", "item": { "type": "reasoning", "id": id, "text": text } })
}
pub fn approval_request(id: &str, command: &str) -> Value {
json!({ "type": "exec_approval_request", "id": id, "command": command })
}
pub fn error(message: &str) -> Value {
json!({ "type": "error", "message": message })
}
#[cfg(test)]
mod tests {
use super::*;
use crate::types::events::ThreadEvent;
#[test]
fn builders_produce_parseable_events() {
let events = vec![
thread_started("t1"),
turn_started(),
agent_message_started("msg-1"),
agent_message_updated("msg-1", "hello"),
agent_message_completed("msg-1", "hello world"),
command_started("cmd-1", "ls"),
command_completed("cmd-1", "ls", "file.txt", 0),
reasoning_started("r-1"),
reasoning_completed("r-1", "thinking..."),
approval_request("ap-1", "rm -rf /"),
turn_completed(100, 0, 50),
turn_failed("oops"),
error("bad"),
];
for event_json in events {
let result = serde_json::from_value::<ThreadEvent>(event_json.clone());
assert!(
result.is_ok(),
"Failed to parse: {}",
serde_json::to_string(&event_json).unwrap()
);
}
}
}