use serde_json::{json, Value};
pub(super) fn timeline_payload_from_thread_item(raw_type: &str, item: &Value) -> Value {
match raw_type {
"userMessage" => json!({
"role": item.get("role").cloned().unwrap_or_else(|| json!("user")),
"content": item.get("content").cloned().unwrap_or(Value::Null),
"text": item.get("text").cloned().unwrap_or(Value::Null),
}),
"message" => json!({
"role": item.get("role").cloned().unwrap_or(Value::Null),
"phase": item.get("phase").cloned().unwrap_or(Value::Null),
"status": item.get("status").cloned().unwrap_or(Value::Null),
"content": item.get("content").cloned().unwrap_or(Value::Null),
"text": item.get("text").cloned().unwrap_or(Value::Null),
}),
"hookPrompt" => json!({
"fragments": item.get("fragments").cloned().unwrap_or_else(|| json!([])),
}),
"agentMessage" => json!({
"role": item.get("role").cloned().unwrap_or_else(|| json!("assistant")),
"phase": item.get("phase").cloned().unwrap_or(Value::Null),
"status": item.get("status").cloned().unwrap_or(Value::Null),
"memoryCitation": item.get("memoryCitation").cloned().unwrap_or(Value::Null),
"content": item.get("content").cloned().unwrap_or(Value::Null),
"text": item.get("text").cloned().unwrap_or(Value::Null),
}),
"plan" => json!({
"text": item.get("text").cloned().unwrap_or(Value::Null),
}),
"reasoning" | "reasoning_text" | "summary_text" => json!({
"summary": item.get("summary").cloned().unwrap_or_else(|| json!([])),
"content": item.get("content").cloned().unwrap_or_else(|| json!([])),
}),
"commandExecution" => json!({
"command": item.get("command").cloned().unwrap_or(Value::Null),
"commandActions": item.get("commandActions").cloned().unwrap_or_else(|| json!([])),
"cwd": item.get("cwd").cloned().unwrap_or(Value::Null),
"exitCode": item.get("exitCode").cloned().unwrap_or(Value::Null),
"durationMs": item.get("durationMs").cloned().unwrap_or(Value::Null),
"processId": item.get("processId").cloned().unwrap_or(Value::Null),
"source": item.get("source").cloned().unwrap_or(Value::Null),
}),
"fileChange" => json!({
"changes": item.get("changes").cloned().unwrap_or_else(|| json!([])),
}),
"mcpToolCall" => json!({
"server": item.get("server").cloned().unwrap_or(Value::Null),
"tool": item.get("tool").cloned().unwrap_or(Value::Null),
"arguments": item.get("arguments").cloned().unwrap_or(Value::Null),
"result": item.get("result").cloned().unwrap_or(Value::Null),
"error": item.get("error").cloned().unwrap_or(Value::Null),
"durationMs": item.get("durationMs").cloned().unwrap_or(Value::Null),
}),
"dynamicToolCall" => json!({
"tool": item.get("tool").cloned().unwrap_or(Value::Null),
"arguments": item.get("arguments").cloned().unwrap_or(Value::Null),
"contentItems": item.get("contentItems").cloned().unwrap_or(Value::Null),
"success": item.get("success").cloned().unwrap_or(Value::Null),
"durationMs": item.get("durationMs").cloned().unwrap_or(Value::Null),
}),
"collabToolCall" | "collabAgentToolCall" => json!({
"tool": item.get("tool").cloned().unwrap_or(Value::Null),
"agentsStates": item.get("agentsStates").cloned().unwrap_or(Value::Null),
"model": item.get("model").cloned().unwrap_or(Value::Null),
"prompt": item.get("prompt").cloned().unwrap_or(Value::Null),
"reasoningEffort": item.get("reasoningEffort").cloned().unwrap_or(Value::Null),
"receiverThreadIds": item.get("receiverThreadIds").cloned().unwrap_or(Value::Null),
"senderThreadId": item.get("senderThreadId").cloned().unwrap_or(Value::Null),
}),
"webSearch" => json!({
"query": item.get("query").cloned().unwrap_or(Value::Null),
"action": item.get("action").cloned().unwrap_or(Value::Null),
}),
"imageView" => json!({
"path": item.get("path").cloned().unwrap_or(Value::Null),
}),
"imageGeneration" => json!({
"result": item.get("result").cloned().unwrap_or(Value::Null),
"revisedPrompt": item.get("revisedPrompt").cloned().unwrap_or(Value::Null),
"savedPath": item.get("savedPath").cloned().unwrap_or(Value::Null),
}),
"function_call" => json!({
"name": item.get("name").cloned().unwrap_or(Value::Null),
"namespace": item.get("namespace").cloned().unwrap_or(Value::Null),
"arguments": item.get("arguments").cloned().unwrap_or(Value::Null),
"callId": call_id_value(item),
"status": item.get("status").cloned().unwrap_or(Value::Null),
}),
"function_call_output" => json!({
"callId": call_id_value(item),
"output": item.get("output").cloned().unwrap_or(Value::Null),
"status": item.get("status").cloned().unwrap_or(Value::Null),
}),
"custom_tool_call" => json!({
"name": item.get("name").cloned().unwrap_or(Value::Null),
"input": item.get("input").cloned().unwrap_or(Value::Null),
"arguments": item.get("arguments").cloned().unwrap_or(Value::Null),
"callInput": item.get("call_input").cloned().unwrap_or(Value::Null),
"callId": call_id_value(item),
"status": item.get("status").cloned().unwrap_or(Value::Null),
}),
"custom_tool_call_output" => json!({
"callId": call_id_value(item),
"output": item.get("output").cloned().unwrap_or(Value::Null),
"status": item.get("status").cloned().unwrap_or(Value::Null),
}),
"file_search_call" => json!({
"callId": call_id_value(item),
"queries": item.get("queries").cloned().unwrap_or(Value::Null),
"results": item.get("results").cloned().unwrap_or(Value::Null),
"status": item.get("status").cloned().unwrap_or(Value::Null),
}),
"web_search_call" => json!({
"callId": call_id_value(item),
"query": item.get("query").cloned().unwrap_or(Value::Null),
"action": item.get("action").cloned().unwrap_or(Value::Null),
"results": item.get("results").cloned().unwrap_or(Value::Null),
"status": item.get("status").cloned().unwrap_or(Value::Null),
}),
"computer_call" => json!({
"callId": call_id_value(item),
"action": item.get("action").cloned().unwrap_or(Value::Null),
"arguments": item.get("arguments").cloned().unwrap_or(Value::Null),
"status": item.get("status").cloned().unwrap_or(Value::Null),
}),
"computer_call_output" => json!({
"callId": call_id_value(item),
"output": item.get("output").cloned().unwrap_or(Value::Null),
"status": item.get("status").cloned().unwrap_or(Value::Null),
}),
"code_interpreter_call" => json!({
"callId": call_id_value(item),
"code": item.get("code").cloned().unwrap_or(Value::Null),
"outputs": item.get("outputs").cloned().unwrap_or(Value::Null),
"status": item.get("status").cloned().unwrap_or(Value::Null),
}),
"shell_call" | "local_shell_call" => json!({
"callId": call_id_value(item),
"action": item.get("action").cloned().unwrap_or(Value::Null),
"command": item.get("command").cloned().unwrap_or(Value::Null),
"commands": item.get("commands").cloned().unwrap_or(Value::Null),
"status": item.get("status").cloned().unwrap_or(Value::Null),
}),
"shell_call_output" | "local_shell_call_output" => json!({
"callId": call_id_value(item),
"output": item.get("output").cloned().unwrap_or(Value::Null),
"stdout": item.get("stdout").cloned().unwrap_or(Value::Null),
"stderr": item.get("stderr").cloned().unwrap_or(Value::Null),
"status": item.get("status").cloned().unwrap_or(Value::Null),
}),
"apply_patch_call" => json!({
"callId": call_id_value(item),
"operation": item.get("operation").cloned().unwrap_or(Value::Null),
"status": item.get("status").cloned().unwrap_or(Value::Null),
}),
"apply_patch_call_output" => json!({
"callId": call_id_value(item),
"output": item.get("output").cloned().unwrap_or(Value::Null),
"status": item.get("status").cloned().unwrap_or(Value::Null),
}),
"image_generation_call" => json!({
"callId": call_id_value(item),
"result": item.get("result").cloned().unwrap_or(Value::Null),
"status": item.get("status").cloned().unwrap_or(Value::Null),
}),
"mcp_call" => json!({
"callId": call_id_value(item),
"serverLabel": item.get("server_label").cloned().unwrap_or(Value::Null),
"name": item.get("name").cloned().unwrap_or(Value::Null),
"arguments": item.get("arguments").cloned().unwrap_or(Value::Null),
"output": item.get("output").cloned().unwrap_or(Value::Null),
"error": item.get("error").cloned().unwrap_or(Value::Null),
"status": item.get("status").cloned().unwrap_or(Value::Null),
}),
"mcp_approval_request" => json!({
"serverLabel": item.get("server_label").cloned().unwrap_or(Value::Null),
"name": item.get("name").cloned().unwrap_or(Value::Null),
"arguments": item.get("arguments").cloned().unwrap_or(Value::Null),
}),
"mcp_approval_response" => json!({
"approve": item.get("approve").cloned().unwrap_or(Value::Null),
"reason": item.get("reason").cloned().unwrap_or(Value::Null),
}),
"mcp_list_tools" => json!({
"serverLabel": item.get("server_label").cloned().unwrap_or(Value::Null),
"tools": item.get("tools").cloned().unwrap_or(Value::Null),
"error": item.get("error").cloned().unwrap_or(Value::Null),
}),
"enteredReviewMode" | "exitedReviewMode" => json!({
"review": item.get("review").cloned().unwrap_or(Value::Null),
}),
"contextCompaction" | "compaction" => json!({}),
_ => item.clone(),
}
}
fn call_id_value(item: &Value) -> Value {
item.get("call_id")
.cloned()
.or_else(|| item.get("callId").cloned())
.unwrap_or(Value::Null)
}