tracevault_cli/commands/
hook.rs1use std::fs::{self, OpenOptions};
2use std::io::{self, Read, Write};
3use std::path::Path;
4use tracevault_core::hooks::{parse_hook_event, HookResponse};
5
6pub fn handle_hook_from_stdin(project_root: &Path) -> Result<(), io::Error> {
7 let mut input = String::new();
8 io::stdin().read_to_string(&mut input)?;
9 handle_hook_event(&input, project_root)?;
10
11 let response = HookResponse::allow();
13 println!("{}", serde_json::to_string(&response).unwrap());
14 Ok(())
15}
16
17pub fn handle_hook_event(json_input: &str, project_root: &Path) -> Result<(), io::Error> {
18 let event =
19 parse_hook_event(json_input).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
20
21 let session_dir = project_root
23 .join(".tracevault")
24 .join("sessions")
25 .join(&event.session_id);
26 fs::create_dir_all(&session_dir)?;
27
28 let events_path = session_dir.join("events.jsonl");
30 let mut file = OpenOptions::new()
31 .create(true)
32 .append(true)
33 .open(&events_path)?;
34
35 let event_json = serde_json::to_string(&event).map_err(io::Error::other)?;
36 writeln!(file, "{event_json}")?;
37
38 let meta_path = session_dir.join("metadata.json");
40 if !meta_path.exists() {
41 let metadata = serde_json::json!({
42 "session_id": event.session_id,
43 "transcript_path": event.transcript_path,
44 "cwd": event.cwd,
45 "started_at": chrono::Utc::now().to_rfc3339(),
46 });
47 fs::write(&meta_path, serde_json::to_string_pretty(&metadata).unwrap())?;
48 }
49
50 Ok(())
51}