agentic_memory/v3/
claude_hooks.rs1use super::block::*;
5use super::engine::{MemoryEngineV3, SessionResumeResult};
6
7pub struct ClaudeHooks;
9
10impl ClaudeHooks {
11 pub fn on_message_start(
13 engine: &MemoryEngineV3,
14 role: &str,
15 content: &str,
16 _context_tokens: u32,
17 ) {
18 let _ = match role {
19 "user" => engine.capture_user_message(content, Some(estimate_tokens(content))),
20 "assistant" => {
21 engine.capture_assistant_message(content, Some(estimate_tokens(content)))
22 }
23 _ => engine.capture_user_message(content, Some(estimate_tokens(content))),
24 };
25 }
26
27 pub fn on_tool_start(_engine: &MemoryEngineV3, _tool_name: &str, _input: &serde_json::Value) {
29 }
32
33 pub fn on_tool_complete(
35 engine: &MemoryEngineV3,
36 tool_name: &str,
37 input: serde_json::Value,
38 output: serde_json::Value,
39 duration_ms: u64,
40 success: bool,
41 ) {
42 let _ = engine.capture_tool_call(
43 tool_name,
44 input.clone(),
45 Some(output),
46 Some(duration_ms),
47 success,
48 );
49
50 if tool_name == "create_file" || tool_name == "str_replace" || tool_name == "view" {
52 if let Some(path) = input.get("path").and_then(|p| p.as_str()) {
53 let op = match tool_name {
54 "create_file" => FileOperation::Create,
55 "str_replace" => FileOperation::Update,
56 "view" => FileOperation::Read,
57 _ => FileOperation::Read,
58 };
59 let _ = engine.capture_file_operation(path, op, None, None, None);
60 }
61 }
62 }
63
64 pub fn on_context_pressure(engine: &MemoryEngineV3, current_tokens: u32, max_tokens: u32) {
66 if current_tokens as f32 / max_tokens as f32 > 0.8 {
67 let _ = engine.capture_checkpoint(
69 vec![], "Context pressure detected",
71 vec![],
72 );
73 }
74 }
75
76 pub fn on_pre_compaction(
79 engine: &MemoryEngineV3,
80 context_tokens_before: u32,
81 summary: &str,
82 active_files: Vec<String>,
83 pending_tasks: Vec<String>,
84 working_context: &str,
85 ) {
86 let _ = engine.capture_checkpoint(active_files.clone(), working_context, pending_tasks);
88
89 let _ = engine.capture_boundary(
91 BoundaryType::Compaction,
92 context_tokens_before,
93 0, summary,
95 Some(&format!("Active files: {:?}", active_files)),
96 );
97 }
98
99 pub fn on_post_compaction(_engine: &MemoryEngineV3, _context_tokens_after: u32) {
101 }
104
105 pub fn on_session_end(engine: &MemoryEngineV3, summary: &str) {
107 let _ = engine.capture_boundary(BoundaryType::SessionEnd, 0, 0, summary, None);
108 }
109
110 pub fn on_session_start(engine: &MemoryEngineV3) -> SessionResumeResult {
112 let _ = engine.capture_boundary(
114 BoundaryType::SessionStart,
115 0,
116 0,
117 "New session started",
118 None,
119 );
120
121 engine.session_resume()
123 }
124}
125
126fn estimate_tokens(text: &str) -> u32 {
128 (text.len() / 4) as u32 + 1
130}