codex-mobile-bridge 0.2.11

Remote bridge and service manager for codex-mobile.
Documentation
use serde_json::{Value, json};

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)
}