Skip to main content

systemprompt_api/services/gateway/
parse.rs

1use serde_json::Value;
2
3use super::audit::{CapturedToolUse, CapturedUsage};
4
5pub fn extract_from_anthropic_response(bytes: &[u8]) -> (CapturedUsage, Vec<CapturedToolUse>) {
6    let Ok(value) = serde_json::from_slice::<Value>(bytes) else {
7        return (CapturedUsage::default(), Vec::new());
8    };
9    extract_from_anthropic_value(&value)
10}
11
12pub fn extract_assistant_text(bytes: &[u8]) -> Option<String> {
13    let value = serde_json::from_slice::<Value>(bytes).ok()?;
14    let content = value.get("content")?.as_array()?;
15    let mut out = String::new();
16    for block in content {
17        if block.get("type").and_then(Value::as_str) == Some("text") {
18            if let Some(text) = block.get("text").and_then(Value::as_str) {
19                if !out.is_empty() {
20                    out.push('\n');
21                }
22                out.push_str(text);
23            }
24        }
25    }
26    if out.is_empty() { None } else { Some(out) }
27}
28
29pub fn extract_from_anthropic_value(value: &Value) -> (CapturedUsage, Vec<CapturedToolUse>) {
30    let usage = CapturedUsage {
31        input_tokens: value
32            .get("usage")
33            .and_then(|u| u.get("input_tokens"))
34            .and_then(Value::as_u64)
35            .unwrap_or(0) as u32,
36        output_tokens: value
37            .get("usage")
38            .and_then(|u| u.get("output_tokens"))
39            .and_then(Value::as_u64)
40            .unwrap_or(0) as u32,
41    };
42
43    let mut tool_calls = Vec::new();
44    if let Some(content) = value.get("content").and_then(Value::as_array) {
45        for block in content {
46            if block.get("type").and_then(Value::as_str) == Some("tool_use") {
47                let id = block
48                    .get("id")
49                    .and_then(Value::as_str)
50                    .unwrap_or("")
51                    .to_string();
52                let name = block
53                    .get("name")
54                    .and_then(Value::as_str)
55                    .unwrap_or("")
56                    .to_string();
57                let input = block
58                    .get("input")
59                    .map(|v| serde_json::to_string(v).unwrap_or_default())
60                    .unwrap_or_default();
61                tool_calls.push(CapturedToolUse {
62                    ai_tool_call_id: id,
63                    tool_name: name,
64                    tool_input: input,
65                });
66            }
67        }
68    }
69
70    (usage, tool_calls)
71}