Extract lib.rs, inline search in memory-search hook

Create lib.rs so all binaries can share library code directly instead
of shelling out to poc-memory. memory-search now calls search::search()
and store::Store::load() in-process instead of Command::new("poc-memory").

The load-context call still shells out (needs get_group_content moved
from main.rs to a library module).

Also: add search::format_results(), deduplicate extract_query_terms.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Kent Overstreet 2026-03-05 22:23:03 -05:00
parent 0c15002797
commit aa24c40a1c
5 changed files with 59 additions and 31 deletions

View file

@ -7,6 +7,8 @@
// Reads JSON from stdin (Claude Code UserPromptSubmit hook format),
// outputs results for injection into the conversation.
use poc_memory::search;
use poc_memory::store;
use std::collections::HashSet;
use std::fs;
use std::io::{self, Read, Write};
@ -76,24 +78,24 @@ fn main() {
}
}
let query = extract_query_terms(prompt, 3);
let query = search::extract_query_terms(prompt, 3);
if query.is_empty() {
return;
}
let output = Command::new("poc-memory")
.args(["search", &query])
.output();
let search_output = match output {
Ok(o) if o.status.success() => String::from_utf8_lossy(&o.stdout).to_string(),
_ => return,
let store = match store::Store::load() {
Ok(s) => s,
Err(_) => return,
};
if search_output.trim().is_empty() {
let results = search::search(&query, &store);
if results.is_empty() {
return;
}
// Format results like poc-memory search output
let search_output = search::format_results(&results);
let cookie = fs::read_to_string(&cookie_path).unwrap_or_default().trim().to_string();
let seen = load_seen(&state_dir, session_id);
@ -128,27 +130,6 @@ fn main() {
cleanup_stale_files(&state_dir, Duration::from_secs(86400));
}
fn extract_query_terms(text: &str, max_terms: usize) -> String {
const STOP_WORDS: &[&str] = &[
"the", "a", "an", "is", "are", "was", "were", "do", "does", "did",
"have", "has", "had", "will", "would", "could", "should", "can",
"may", "might", "shall", "been", "being", "to", "of", "in", "for",
"on", "with", "at", "by", "from", "as", "but", "or", "and", "not",
"no", "if", "then", "than", "that", "this", "it", "its", "my",
"your", "our", "we", "you", "i", "me", "he", "she", "they", "them",
"what", "how", "why", "when", "where", "about", "just", "let",
"want", "tell", "show", "think", "know", "see", "look", "make",
"get", "go", "some", "any", "all", "very", "really", "also", "too",
"so", "up", "out", "here", "there",
];
text.to_lowercase()
.split(|c: char| !c.is_alphanumeric())
.filter(|w| !w.is_empty() && w.len() > 2 && !STOP_WORDS.contains(w))
.take(max_terms)
.collect::<Vec<_>>()
.join(" ")
}
fn extract_key_from_line(line: &str) -> Option<String> {
let after_bracket = line.find("] ")?;

28
src/lib.rs Normal file
View file

@ -0,0 +1,28 @@
// poc-memory library — shared modules for all binaries
//
// Re-exports modules so that memory-search and other binaries
// can call library functions directly instead of shelling out.
pub mod config;
pub mod store;
pub mod util;
pub mod llm;
pub mod digest;
pub mod audit;
pub mod enrich;
pub mod consolidate;
pub mod graph;
pub mod search;
pub mod similarity;
pub mod migrate;
pub mod neuro;
pub mod query;
pub mod spectral;
pub mod lookups;
pub mod daemon;
pub mod fact_mine;
pub mod knowledge;
pub mod memory_capnp {
include!(concat!(env!("OUT_DIR"), "/schema/memory_capnp.rs"));
}

View file

@ -139,3 +139,18 @@ pub fn extract_query_terms(text: &str, max_terms: usize) -> String {
.collect::<Vec<_>>()
.join(" ")
}
/// Format search results as text lines (for hook consumption).
pub fn format_results(results: &[SearchResult]) -> String {
let mut out = String::new();
for (i, r) in results.iter().enumerate().take(5) {
let marker = if r.is_direct { "" } else { " " };
out.push_str(&format!("{}{:2}. [{:.2}/{:.2}] {}",
marker, i + 1, r.activation, r.activation, r.key));
out.push('\n');
if let Some(ref snippet) = r.snippet {
out.push_str(&format!(" {}\n", snippet));
}
}
out
}

View file

@ -6,7 +6,7 @@ use std::fs;
use std::path::PathBuf;
/// Ensure a subdirectory of the memory dir exists and return its path.
pub(crate) fn memory_subdir(name: &str) -> Result<PathBuf, String> {
pub fn memory_subdir(name: &str) -> Result<PathBuf, String> {
let dir = store::memory_dir().join(name);
fs::create_dir_all(&dir)
.map_err(|e| format!("create {}: {}", dir.display(), e))?;