use serde_json::Value;
use crate::canonical::{ContentKind, Delta, Event};
use crate::protocol::json::{text_of, u32_at};
use crate::protocol::{DecodeState, OpenBlock};
pub(super) fn content_block_start(v: &Value, state: &mut DecodeState) -> Vec<Event> {
let index = u32_at(v, "index");
let cb = &v["content_block"];
let kind = match cb["type"].as_str().unwrap_or_default() {
"text" => ContentKind::Text {},
"tool_use" => ContentKind::ToolUse {
id: text_of(cb, "id"),
name: text_of(cb, "name"),
},
"thinking" => ContentKind::Thinking { id: None }, "redacted_thinking" => ContentKind::RedactedThinking {
data: text_of(cb, "data"), },
"server_tool_use" => ContentKind::ServerToolUse {
id: text_of(cb, "id"),
name: text_of(cb, "name"),
},
t if t.ends_with("_tool_result") && t != "tool_result" => ContentKind::ServerToolResult {
kind: t.to_owned(),
tool_use_id: text_of(cb, "tool_use_id"),
content: cb["content"].clone(),
},
_ => return vec![],
};
state.open.insert(index, OpenBlock { kind: kind.clone() });
vec![Event::ContentStart { index, kind }]
}
pub(super) fn content_block_delta(v: &Value, state: &mut DecodeState) -> Vec<Event> {
let index = u32_at(v, "index");
if !state.open.contains_key(&index) {
return vec![];
}
let d = &v["delta"];
match d["type"].as_str().unwrap_or_default() {
"text_delta" => vec![delta(index, Delta::TextDelta(text_of(d, "text")))],
"input_json_delta" => vec![delta(index, Delta::JsonDelta(text_of(d, "partial_json")))],
"thinking_delta" => vec![delta(index, Delta::ThinkingDelta(text_of(d, "thinking")))],
"signature_delta" => vec![delta(index, Delta::SignatureDelta(text_of(d, "signature")))],
_ => vec![],
}
}
fn delta(index: u32, delta: Delta) -> Event {
Event::ContentDelta { index, delta }
}
pub(super) fn content_block_stop(v: &Value, state: &mut DecodeState) -> Vec<Event> {
let index = u32_at(v, "index");
if state.open.remove(&index).is_some() {
vec![Event::ContentStop { index }]
} else {
vec![]
}
}