subconscious: move install_hook() from daemon.rs to hook.rs
The install_hook() function is about hook infrastructure setup, not daemon runtime. Move it to hook.rs where it belongs alongside the hook execution logic. - Move install_hook() from daemon.rs to hook.rs - Update caller in daemon.rs to use crate::subconscious:🪝:install_hook() - Update caller in cli/admin.rs to use crate::subconscious:🪝:install_hook() This improves module boundaries: daemon.rs now only contains daemon runtime and admin commands, while hook.rs contains all hook-related functionality.
This commit is contained in:
parent
e91449b905
commit
1b47b45566
3 changed files with 108 additions and 107 deletions
|
|
@ -40,7 +40,7 @@ pub fn cmd_init() -> Result<(), String> {
|
||||||
println!("Indexed {} memory units", count);
|
println!("Indexed {} memory units", count);
|
||||||
|
|
||||||
// Install hooks
|
// Install hooks
|
||||||
crate::daemon::install_hook()?;
|
crate::subconscious::hook::install_hook()?;
|
||||||
|
|
||||||
// Create config if none exists
|
// Create config if none exists
|
||||||
let config_path = std::env::var("POC_MEMORY_CONFIG")
|
let config_path = std::env::var("POC_MEMORY_CONFIG")
|
||||||
|
|
|
||||||
|
|
@ -1534,7 +1534,7 @@ WantedBy=default.target
|
||||||
install_notify_daemon(&unit_dir, &home)?;
|
install_notify_daemon(&unit_dir, &home)?;
|
||||||
|
|
||||||
// Install memory-search + poc-hook into Claude settings
|
// Install memory-search + poc-hook into Claude settings
|
||||||
install_hook()?;
|
crate::subconscious::hook::install_hook()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -1590,111 +1590,6 @@ WantedBy=default.target
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Install memory-search and poc-hook into Claude Code settings.json.
|
|
||||||
/// Public so `poc-memory init` can call it too.
|
|
||||||
///
|
|
||||||
/// Hook layout:
|
|
||||||
/// UserPromptSubmit: memory-search (10s), poc-hook (5s)
|
|
||||||
/// PostToolUse: poc-hook (5s)
|
|
||||||
/// Stop: poc-hook (5s)
|
|
||||||
pub fn install_hook() -> Result<(), String> {
|
|
||||||
let home = std::env::var("HOME").map_err(|e| format!("HOME: {}", e))?;
|
|
||||||
let exe = std::env::current_exe()
|
|
||||||
.map_err(|e| format!("current_exe: {}", e))?;
|
|
||||||
let settings_path = PathBuf::from(&home).join(".claude/settings.json");
|
|
||||||
|
|
||||||
let memory_search = exe.with_file_name("memory-search");
|
|
||||||
let poc_hook = exe.with_file_name("poc-hook");
|
|
||||||
|
|
||||||
let mut settings: serde_json::Value = if settings_path.exists() {
|
|
||||||
let content = fs::read_to_string(&settings_path)
|
|
||||||
.map_err(|e| format!("read settings: {}", e))?;
|
|
||||||
serde_json::from_str(&content)
|
|
||||||
.map_err(|e| format!("parse settings: {}", e))?
|
|
||||||
} else {
|
|
||||||
serde_json::json!({})
|
|
||||||
};
|
|
||||||
|
|
||||||
let obj = settings.as_object_mut().ok_or("settings not an object")?;
|
|
||||||
let hooks_obj = obj.entry("hooks")
|
|
||||||
.or_insert_with(|| serde_json::json!({}))
|
|
||||||
.as_object_mut().ok_or("hooks not an object")?;
|
|
||||||
|
|
||||||
let mut changed = false;
|
|
||||||
|
|
||||||
// Helper: ensure a hook binary is present in an event's hook list
|
|
||||||
let ensure_hook = |hooks_obj: &mut serde_json::Map<String, serde_json::Value>,
|
|
||||||
event: &str,
|
|
||||||
binary: &Path,
|
|
||||||
timeout: u32,
|
|
||||||
changed: &mut bool| {
|
|
||||||
if !binary.exists() {
|
|
||||||
eprintln!("Warning: {} not found — skipping", binary.display());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let cmd = binary.to_string_lossy().to_string();
|
|
||||||
let name = binary.file_name().unwrap().to_string_lossy().to_string();
|
|
||||||
|
|
||||||
let event_array = hooks_obj.entry(event)
|
|
||||||
.or_insert_with(|| serde_json::json!([{"hooks": []}]))
|
|
||||||
.as_array_mut().unwrap();
|
|
||||||
if event_array.is_empty() {
|
|
||||||
event_array.push(serde_json::json!({"hooks": []}));
|
|
||||||
}
|
|
||||||
let inner = event_array[0]
|
|
||||||
.as_object_mut().unwrap()
|
|
||||||
.entry("hooks")
|
|
||||||
.or_insert_with(|| serde_json::json!([]))
|
|
||||||
.as_array_mut().unwrap();
|
|
||||||
|
|
||||||
// Remove legacy load-memory.sh
|
|
||||||
let before = inner.len();
|
|
||||||
inner.retain(|h| {
|
|
||||||
let c = h.get("command").and_then(|c| c.as_str()).unwrap_or("");
|
|
||||||
!c.contains("load-memory")
|
|
||||||
});
|
|
||||||
if inner.len() < before {
|
|
||||||
eprintln!("Removed load-memory.sh from {event}");
|
|
||||||
*changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
let already = inner.iter().any(|h| {
|
|
||||||
h.get("command").and_then(|c| c.as_str())
|
|
||||||
.is_some_and(|c| c.contains(&name))
|
|
||||||
});
|
|
||||||
|
|
||||||
if !already {
|
|
||||||
inner.push(serde_json::json!({
|
|
||||||
"type": "command",
|
|
||||||
"command": cmd,
|
|
||||||
"timeout": timeout
|
|
||||||
}));
|
|
||||||
*changed = true;
|
|
||||||
eprintln!("Installed {name} in {event}");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// UserPromptSubmit: memory-search + poc-hook
|
|
||||||
ensure_hook(hooks_obj, "UserPromptSubmit", &memory_search, 10, &mut changed);
|
|
||||||
ensure_hook(hooks_obj, "UserPromptSubmit", &poc_hook, 5, &mut changed);
|
|
||||||
|
|
||||||
// PostToolUse + Stop: poc-hook only
|
|
||||||
ensure_hook(hooks_obj, "PostToolUse", &poc_hook, 5, &mut changed);
|
|
||||||
ensure_hook(hooks_obj, "Stop", &poc_hook, 5, &mut changed);
|
|
||||||
|
|
||||||
if changed {
|
|
||||||
let json = serde_json::to_string_pretty(&settings)
|
|
||||||
.map_err(|e| format!("serialize settings: {}", e))?;
|
|
||||||
fs::write(&settings_path, json)
|
|
||||||
.map_err(|e| format!("write settings: {}", e))?;
|
|
||||||
eprintln!("Updated {}", settings_path.display());
|
|
||||||
} else {
|
|
||||||
eprintln!("All hooks already installed in {}", settings_path.display());
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Drill down into a task's log file. Finds the log path from:
|
/// Drill down into a task's log file. Finds the log path from:
|
||||||
/// 1. Running task status (daemon-status.json)
|
/// 1. Running task status (daemon-status.json)
|
||||||
/// 2. daemon.log started events (for completed/failed tasks)
|
/// 2. daemon.log started events (for completed/failed tasks)
|
||||||
|
|
|
||||||
|
|
@ -204,3 +204,109 @@ fn hook(session: &HookSession) -> String {
|
||||||
|
|
||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Install memory-search and poc-hook into Claude Code settings.json.
|
||||||
|
///
|
||||||
|
/// Hook layout:
|
||||||
|
/// UserPromptSubmit: memory-search (10s), poc-hook (5s)
|
||||||
|
/// PostToolUse: poc-hook (5s)
|
||||||
|
/// Stop: poc-hook (5s)
|
||||||
|
pub fn install_hook() -> Result<(), String> {
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
let home = std::env::var("HOME").map_err(|e| format!("HOME: {}", e))?;
|
||||||
|
let exe = std::env::current_exe()
|
||||||
|
.map_err(|e| format!("current_exe: {}", e))?;
|
||||||
|
let settings_path = PathBuf::from(&home).join(".claude/settings.json");
|
||||||
|
|
||||||
|
let memory_search = exe.with_file_name("memory-search");
|
||||||
|
let poc_hook = exe.with_file_name("poc-hook");
|
||||||
|
|
||||||
|
let mut settings: serde_json::Value = if settings_path.exists() {
|
||||||
|
let content = fs::read_to_string(&settings_path)
|
||||||
|
.map_err(|e| format!("read settings: {}", e))?;
|
||||||
|
serde_json::from_str(&content)
|
||||||
|
.map_err(|e| format!("parse settings: {}", e))?
|
||||||
|
} else {
|
||||||
|
serde_json::json!({})
|
||||||
|
};
|
||||||
|
|
||||||
|
let obj = settings.as_object_mut().ok_or("settings not an object")?;
|
||||||
|
let hooks_obj = obj.entry("hooks")
|
||||||
|
.or_insert_with(|| serde_json::json!({}))
|
||||||
|
.as_object_mut().ok_or("hooks not an object")?;
|
||||||
|
|
||||||
|
let mut changed = false;
|
||||||
|
|
||||||
|
// Helper: ensure a hook binary is present in an event's hook list
|
||||||
|
let ensure_hook = |hooks_obj: &mut serde_json::Map<String, serde_json::Value>,
|
||||||
|
event: &str,
|
||||||
|
binary: &Path,
|
||||||
|
timeout: u32,
|
||||||
|
changed: &mut bool| {
|
||||||
|
if !binary.exists() {
|
||||||
|
eprintln!("Warning: {} not found — skipping", binary.display());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let cmd = binary.to_string_lossy().to_string();
|
||||||
|
let name = binary.file_name().unwrap().to_string_lossy().to_string();
|
||||||
|
|
||||||
|
let event_array = hooks_obj.entry(event)
|
||||||
|
.or_insert_with(|| serde_json::json!([{"hooks": []}]))
|
||||||
|
.as_array_mut().unwrap();
|
||||||
|
if event_array.is_empty() {
|
||||||
|
event_array.push(serde_json::json!({"hooks": []}));
|
||||||
|
}
|
||||||
|
let inner = event_array[0]
|
||||||
|
.as_object_mut().unwrap()
|
||||||
|
.entry("hooks")
|
||||||
|
.or_insert_with(|| serde_json::json!([]))
|
||||||
|
.as_array_mut().unwrap();
|
||||||
|
|
||||||
|
// Remove legacy load-memory.sh
|
||||||
|
let before = inner.len();
|
||||||
|
inner.retain(|h| {
|
||||||
|
let c = h.get("command").and_then(|c| c.as_str()).unwrap_or("");
|
||||||
|
!c.contains("load-memory")
|
||||||
|
});
|
||||||
|
if inner.len() < before {
|
||||||
|
eprintln!("Removed load-memory.sh from {event}");
|
||||||
|
*changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let already = inner.iter().any(|h| {
|
||||||
|
h.get("command").and_then(|c| c.as_str())
|
||||||
|
.is_some_and(|c| c.contains(&name))
|
||||||
|
});
|
||||||
|
|
||||||
|
if !already {
|
||||||
|
inner.push(serde_json::json!({
|
||||||
|
"type": "command",
|
||||||
|
"command": cmd,
|
||||||
|
"timeout": timeout
|
||||||
|
}));
|
||||||
|
*changed = true;
|
||||||
|
eprintln!("Installed {name} in {event}");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// UserPromptSubmit: memory-search + poc-hook
|
||||||
|
ensure_hook(hooks_obj, "UserPromptSubmit", &memory_search, 10, &mut changed);
|
||||||
|
ensure_hook(hooks_obj, "UserPromptSubmit", &poc_hook, 5, &mut changed);
|
||||||
|
|
||||||
|
// PostToolUse + Stop: poc-hook only
|
||||||
|
ensure_hook(hooks_obj, "PostToolUse", &poc_hook, 5, &mut changed);
|
||||||
|
ensure_hook(hooks_obj, "Stop", &poc_hook, 5, &mut changed);
|
||||||
|
|
||||||
|
if changed {
|
||||||
|
let json = serde_json::to_string_pretty(&settings)
|
||||||
|
.map_err(|e| format!("serialize settings: {}", e))?;
|
||||||
|
fs::write(&settings_path, json)
|
||||||
|
.map_err(|e| format!("write settings: {}", e))?;
|
||||||
|
eprintln!("Updated {}", settings_path.display());
|
||||||
|
} else {
|
||||||
|
eprintln!("All hooks already installed in {}", settings_path.display());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue