thoughts_tool/utils/
logging.rs1use crate::documents::active_logs_dir;
7use agentic_logging::CallTimer;
8use agentic_logging::LogWriter;
9use agentic_logging::ToolCallRecord;
10
11fn classify_failure_kind(success: bool, error: Option<&str>) -> Option<String> {
12 if success {
13 return None;
14 }
15
16 let error = error.unwrap_or_default().to_ascii_lowercase();
17 if error.contains("timed out") || error.contains("timeout") {
18 Some("timeout".to_string())
19 } else if error.contains("cancelled") || error.contains("canceled") {
20 Some("cancelled".to_string())
21 } else {
22 Some("error".to_string())
23 }
24}
25
26pub fn log_tool_call(
31 timer: &CallTimer,
32 tool: &str,
33 request: serde_json::Value,
34 success: bool,
35 error: Option<String>,
36 summary: Option<serde_json::Value>,
37) {
38 let writer = match active_logs_dir() {
39 Ok(dir) => LogWriter::new(dir),
40 Err(_) => return, };
42
43 let (completed_at, duration_ms) = timer.finish();
44 let record = ToolCallRecord {
45 call_id: timer.call_id.clone(),
46 server: "thoughts_tool".into(),
47 tool: tool.into(),
48 started_at: timer.started_at,
49 completed_at,
50 duration_ms,
51 request,
52 response_file: None,
53 success,
54 failure_kind: classify_failure_kind(success, error.as_deref()),
55 error,
56 model: None,
57 token_usage: None,
58 summary,
59 };
60
61 if let Err(e) = writer.append_jsonl(&record) {
62 tracing::warn!("Failed to append JSONL log: {}", e);
63 }
64}