1use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6use crate::message::ToolCall;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct ToolCallResponse {
11 pub id: String,
12 pub name: String,
13 pub parameters: HashMap<String, serde_json::Value>,
14 #[serde(skip_serializing_if = "Option::is_none")]
15 pub result: Option<String>,
16 #[serde(skip_serializing_if = "Option::is_none")]
17 pub error: Option<String>,
18 #[serde(skip_serializing_if = "Option::is_none")]
19 pub result_summary: Option<String>,
20 #[serde(skip_serializing_if = "Option::is_none")]
21 pub approved: Option<bool>,
22 #[serde(skip_serializing_if = "Option::is_none")]
23 pub nested_tool_calls: Option<Vec<ToolCallResponse>>,
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize)]
28pub struct MessageResponse {
29 pub role: String,
30 pub content: String,
31 #[serde(skip_serializing_if = "Option::is_none")]
32 pub timestamp: Option<String>,
33 #[serde(skip_serializing_if = "Option::is_none")]
34 pub tool_calls: Option<Vec<ToolCallResponse>>,
35 #[serde(skip_serializing_if = "Option::is_none")]
36 pub thinking_trace: Option<String>,
37 #[serde(skip_serializing_if = "Option::is_none")]
38 pub reasoning_content: Option<String>,
39}
40
41#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct SessionResponse {
44 pub id: String,
45 pub working_dir: String,
46 pub created_at: String,
47 pub updated_at: String,
48 pub message_count: usize,
49 pub total_tokens: u64,
50 #[serde(skip_serializing_if = "Option::is_none")]
51 pub title: Option<String>,
52 #[serde(default)]
53 pub has_session_model: bool,
54}
55
56pub fn tool_call_to_response(tc: &ToolCall) -> ToolCallResponse {
60 let nested = if tc.nested_tool_calls.is_empty() {
61 None
62 } else {
63 Some(
64 tc.nested_tool_calls
65 .iter()
66 .map(tool_call_to_response)
67 .collect(),
68 )
69 };
70
71 let result = tc.result.as_ref().map(|r| {
72 if let serde_json::Value::String(s) = r {
73 s.clone()
74 } else {
75 serde_json::to_string(r).unwrap_or_else(|_| r.to_string())
76 }
77 });
78
79 ToolCallResponse {
80 id: tc.id.clone(),
81 name: tc.name.clone(),
82 parameters: tc.parameters.clone(),
83 result,
84 error: tc.error.clone(),
85 result_summary: tc.result_summary.clone(),
86 approved: Some(tc.approved),
87 nested_tool_calls: nested,
88 }
89}
90
91#[cfg(test)]
92#[path = "api_tests.rs"]
93mod tests;