Skip to main content

systemprompt_api/services/gateway/
parse.rs

1use systemprompt_identifiers::AiToolCallId;
2
3use super::captures::{CapturedToolUse, CapturedUsage};
4use super::protocol::canonical::CanonicalContent;
5use super::protocol::canonical_response::CanonicalResponse;
6
7pub fn extract_from_canonical(
8    response: &CanonicalResponse,
9) -> (CapturedUsage, Vec<CapturedToolUse>) {
10    let usage = CapturedUsage {
11        input_tokens: response.usage.input_tokens,
12        output_tokens: response.usage.output_tokens,
13    };
14    let mut tool_calls = Vec::new();
15    for part in &response.content {
16        if let CanonicalContent::ToolUse {
17            id, name, input, ..
18        } = part
19        {
20            tool_calls.push(CapturedToolUse {
21                ai_tool_call_id: AiToolCallId::new(id.clone()),
22                tool_name: name.clone(),
23                tool_input: serde_json::to_string(input).unwrap_or_else(|e| {
24                    tracing::warn!(error = %e, tool = %name, "failed to serialise tool_input");
25                    String::new()
26                }),
27            });
28        }
29    }
30    (usage, tool_calls)
31}
32
33pub fn extract_assistant_text(response: &CanonicalResponse) -> Option<String> {
34    let mut out = String::new();
35    for part in &response.content {
36        if let CanonicalContent::Text(t) = part {
37            if !out.is_empty() {
38                out.push('\n');
39            }
40            out.push_str(t);
41        }
42    }
43    if out.is_empty() { None } else { Some(out) }
44}