tracevault-cli 0.8.0

CLI tool for TraceVault - AI code tracing and attribution
Documentation
use std::path::Path;
use tracevault_core::streaming::StreamEventRequest;

use super::HookAdapter;

pub struct ClaudeCodeAdapter;

impl HookAdapter for ClaudeCodeAdapter {
    fn tool_name(&self) -> &str {
        "claude-code"
    }

    fn parse_event(&self, raw: &str) -> Result<StreamEventRequest, String> {
        let mut req: StreamEventRequest =
            serde_json::from_str(raw).map_err(|e| format!("Failed to parse event JSON: {e}"))?;
        req.tool = Some("claude-code".to_string());
        if req.protocol_version == 0 {
            req.protocol_version = 2;
        }
        Ok(req)
    }

    fn parse_transcript(&self, path: &Path) -> Result<Vec<serde_json::Value>, String> {
        let content =
            std::fs::read_to_string(path).map_err(|e| format!("Failed to read transcript: {e}"))?;
        let mut lines = Vec::new();
        for line in content.lines() {
            if line.trim().is_empty() {
                continue;
            }
            match serde_json::from_str(line) {
                Ok(v) => lines.push(v),
                Err(_) => continue,
            }
        }
        Ok(lines)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn parse_event_sets_tool_name() {
        let adapter = ClaudeCodeAdapter;
        let json = serde_json::json!({
            "protocol_version": 2,
            "event_type": "tool_use",
            "session_id": "sess-1",
            "timestamp": "2026-01-01T00:00:00Z"
        });
        let result = adapter
            .parse_event(&serde_json::to_string(&json).unwrap())
            .unwrap();
        assert_eq!(result.tool.as_deref(), Some("claude-code"));
    }

    #[test]
    fn parse_event_upgrades_version_0() {
        let adapter = ClaudeCodeAdapter;
        let json = serde_json::json!({
            "protocol_version": 0,
            "event_type": "tool_use",
            "session_id": "sess-1",
            "timestamp": "2026-01-01T00:00:00Z"
        });
        let result = adapter
            .parse_event(&serde_json::to_string(&json).unwrap())
            .unwrap();
        assert_eq!(result.protocol_version, 2);
    }
}