use serde_json::{Map, Value, json};
use super::{Block, Entry, EntryKind, Transcript, Usage};
pub(crate) mod decode;
pub(crate) fn reply(transcript: &Transcript) -> Value {
json!({
"ok": true, "kind": "transcript",
"rows": Value::Array(transcript.entries.iter().map(entry_row).collect()),
})
}
fn entry_row(entry: &Entry) -> Value {
let mut map = Map::new();
map.insert("name".to_owned(), json!(entry.name));
map.insert("raw".to_owned(), json!(String::from_utf8_lossy(&entry.raw)));
kind_fields(&entry.kind, &mut map);
Value::Object(map)
}
fn kind_fields(kind: &EntryKind, map: &mut Map<String, Value>) {
let word = match kind {
EntryKind::Delivered {
sender,
epitaph,
body,
} => {
map.insert("sender".to_owned(), json!(sender));
if let Some(epitaph) = epitaph {
map.insert("epitaph".to_owned(), json!(epitaph.label()));
}
map.insert("body".to_owned(), json!(body));
"delivered"
}
EntryKind::Model {
model_id,
blocks,
usage,
} => {
map.insert("model_id".to_owned(), json!(model_id));
map.insert(
"blocks".to_owned(),
Value::Array(blocks.iter().map(block_value).collect()),
);
map.insert("usage".to_owned(), usage_value(usage));
"model"
}
EntryKind::ToolResult {
tool_use_id,
content,
is_error,
} => {
map.insert("tool_use_id".to_owned(), json!(tool_use_id));
map.insert("content".to_owned(), json!(content));
map.insert("is_error".to_owned(), json!(is_error));
"tool-result"
}
EntryKind::Streaming { thinking, text } => {
map.insert("thinking".to_owned(), json!(thinking));
map.insert("text".to_owned(), json!(text));
"streaming"
}
EntryKind::Compacted {
first,
last,
summary,
} => {
map.insert("first".to_owned(), json!(first));
map.insert("last".to_owned(), json!(last));
map.insert("summary".to_owned(), json!(summary));
"compacted"
}
EntryKind::Wounded { wound } => {
crate::steps_view::wire::wound_fields(wound, map);
"wounded"
}
EntryKind::Raw => "raw",
};
map.insert("kind".to_owned(), json!(word));
}
fn block_value(block: &Block) -> Value {
match block {
Block::Text(text) => json!({ "kind": "text", "text": text }),
Block::Thinking(text) => json!({ "kind": "thinking", "text": text }),
Block::ToolUse {
id,
name,
input_summary,
} => json!({ "kind": "tool-use", "id": id, "name": name, "input": input_summary }),
}
}
fn usage_value(usage: &Usage) -> Value {
Value::Object(
usage
.iter()
.map(|(name, count)| (name.clone(), json!(count)))
.collect(),
)
}