Skip to main content

tracevault_cli/hooks/
claude_code.rs

1use std::path::Path;
2use tracevault_core::streaming::StreamEventRequest;
3
4use super::HookAdapter;
5
6pub struct ClaudeCodeAdapter;
7
8impl HookAdapter for ClaudeCodeAdapter {
9    fn tool_name(&self) -> &str {
10        "claude-code"
11    }
12
13    fn parse_event(&self, raw: &str) -> Result<StreamEventRequest, String> {
14        let mut req: StreamEventRequest =
15            serde_json::from_str(raw).map_err(|e| format!("Failed to parse event JSON: {e}"))?;
16        req.tool = Some("claude-code".to_string());
17        if req.protocol_version == 0 {
18            req.protocol_version = 2;
19        }
20        Ok(req)
21    }
22
23    fn parse_transcript(&self, path: &Path) -> Result<Vec<serde_json::Value>, String> {
24        let content =
25            std::fs::read_to_string(path).map_err(|e| format!("Failed to read transcript: {e}"))?;
26        let mut lines = Vec::new();
27        for line in content.lines() {
28            if line.trim().is_empty() {
29                continue;
30            }
31            match serde_json::from_str(line) {
32                Ok(v) => lines.push(v),
33                Err(_) => continue,
34            }
35        }
36        Ok(lines)
37    }
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43
44    #[test]
45    fn parse_event_sets_tool_name() {
46        let adapter = ClaudeCodeAdapter;
47        let json = serde_json::json!({
48            "protocol_version": 2,
49            "event_type": "tool_use",
50            "session_id": "sess-1",
51            "timestamp": "2026-01-01T00:00:00Z"
52        });
53        let result = adapter
54            .parse_event(&serde_json::to_string(&json).unwrap())
55            .unwrap();
56        assert_eq!(result.tool.as_deref(), Some("claude-code"));
57    }
58
59    #[test]
60    fn parse_event_upgrades_version_0() {
61        let adapter = ClaudeCodeAdapter;
62        let json = serde_json::json!({
63            "protocol_version": 0,
64            "event_type": "tool_use",
65            "session_id": "sess-1",
66            "timestamp": "2026-01-01T00:00:00Z"
67        });
68        let result = adapter
69            .parse_event(&serde_json::to_string(&json).unwrap())
70            .unwrap();
71        assert_eq!(result.protocol_version, 2);
72    }
73}