#!/bin/sh # LocalRecall Memory Controller # Persistent memory for AI agents VERSION="1.0.0" CONFIG="localrecall" # Load libraries . /usr/lib/localrecall/memory.sh . /usr/lib/localrecall/ai.sh usage() { cat < [options] Commands: status Show memory status add Add a memory (category: threats|decisions|patterns|configs|conversations) get Get memory by ID search Search memories by content list [category] List memories (optionally by category) recent [N] Show N most recent memories (default: 20) important [N] Show important memories (importance >= 7) delete Delete a memory cleanup Cleanup old memories export Export memories to file import Import memories from file summarize [cat] AI-summarize memories context Get context for an agent stats Show memory statistics Options: -a, --agent Specify agent name (default: user) -i, --importance N Set importance (1-10, default: 5) -j, --json Output in JSON format -q, --quiet Suppress output Examples: $(basename "$0") add threats "Detected SQL injection attempt from 192.168.1.100" $(basename "$0") search "SQL injection" $(basename "$0") context threat_analyst $(basename "$0") summarize threats EOF } uci_get() { uci -q get "${CONFIG}.$1" } cmd_status() { local json_mode="$1" local enabled=$(uci_get main.enabled) local storage=$(uci_get main.storage_path) local max_mem=$(uci_get main.max_memories) local total=$(count_memories) local threats=$(count_category threats) local decisions=$(count_category decisions) local patterns=$(count_category patterns) local localai_status="offline" check_localai && localai_status="online" local storage_size="0" [ -d "$storage" ] && storage_size=$(du -sh "$storage" 2>/dev/null | cut -f1) if [ "$json_mode" = "1" ]; then cat < " return 1 fi # Validate category case "$category" in threats|decisions|patterns|configs|conversations) ;; *) echo "Error: Invalid category. Use: threats|decisions|patterns|configs|conversations" return 1 ;; esac local id=$(add_memory "$category" "$agent" "$content" '{}' "$importance") echo "Memory added: $id" } cmd_get() { local id="$1" if [ -z "$id" ]; then echo "Error: Memory ID required" return 1 fi local memory=$(get_memory "$id") if [ -n "$memory" ]; then echo "$memory" else echo "Memory not found: $id" return 1 fi } cmd_search() { local query="$1" local limit="${2:-20}" if [ -z "$query" ]; then echo "Error: Search query required" return 1 fi echo "Searching for: $query" echo "---" search_content "$query" "$limit" } cmd_list() { local category="$1" local limit="${2:-50}" if [ -n "$category" ]; then echo "Memories in category: $category" echo "---" search_category "$category" "$limit" else echo "All memories (last $limit)" echo "---" get_recent "$limit" fi } cmd_recent() { local limit="${1:-20}" echo "Recent memories (last $limit)" echo "---" get_recent "$limit" } cmd_important() { local limit="${1:-50}" echo "Important memories (importance >= 7)" echo "---" get_important "$limit" } cmd_delete() { local id="$1" if [ -z "$id" ]; then echo "Error: Memory ID required" return 1 fi delete_memory "$id" echo "Memory deleted: $id" } cmd_cleanup() { local retention=$(uci_get main.retention_days) local keep_imp=$(uci_get cleanup.keep_important) echo "Cleaning up memories older than ${retention:-90} days..." local deleted=$(cleanup_old "${retention:-90}" "${keep_imp:-1}") echo "Deleted: $deleted memories" } cmd_export() { local file="$1" if [ -z "$file" ]; then echo "Error: Output file required" return 1 fi export_memories "$file" echo "Memories exported to: $file" } cmd_import() { local file="$1" if [ -z "$file" ]; then echo "Error: Input file required" return 1 fi if [ ! -f "$file" ]; then echo "Error: File not found: $file" return 1 fi import_memories "$file" echo "Memories imported from: $file" } cmd_summarize() { local category="$1" if ! check_localai; then echo "Error: LocalAI not available" return 1 fi echo "Summarizing memories..." echo "---" summarize_memories "$category" } cmd_context() { local agent="$1" if [ -z "$agent" ]; then echo "Error: Agent name required" return 1 fi get_agent_context "$agent" "" } cmd_stats() { local total=$(count_memories) local threats=$(count_category threats) local decisions=$(count_category decisions) local patterns=$(count_category patterns) local configs=$(count_category configs) local convs=$(count_category conversations) echo "Memory Statistics" echo "=================" echo "Total: $total" echo "" echo "By Category:" echo " Threats: $threats" echo " Decisions: $decisions" echo " Patterns: $patterns" echo " Configs: $configs" echo " Conversations: $convs" echo "" # Agent breakdown echo "By Agent:" for agent in threat_analyst dns_guard network_anomaly cve_triage user; do local count=$(search_agent "$agent" 9999 | wc -l) [ "$count" -gt 0 ] && echo " $agent: $count" done } # Parse global options AGENT="user" IMPORTANCE=5 JSON=0 QUIET=0 while [ $# -gt 0 ]; do case "$1" in -a|--agent) AGENT="$2" shift 2 ;; -i|--importance) IMPORTANCE="$2" shift 2 ;; -j|--json) JSON=1 shift ;; -q|--quiet) QUIET=1 shift ;; *) break ;; esac done # Parse command case "$1" in status) cmd_status "$JSON" ;; add) cmd_add "$2" "$3" ;; get) cmd_get "$2" ;; search) cmd_search "$2" "$3" ;; list) cmd_list "$2" "$3" ;; recent) cmd_recent "$2" ;; important) cmd_important "$2" ;; delete) cmd_delete "$2" ;; cleanup) cmd_cleanup ;; export) cmd_export "$2" ;; import) cmd_import "$2" ;; summarize) cmd_summarize "$2" ;; context) cmd_context "$2" ;; stats) cmd_stats ;; help|--help|-h|"") usage ;; *) echo "Unknown command: $1" usage exit 1 ;; esac