secubox-openwrt/package/secubox/secubox-localrecall/files/usr/bin/localrecallctl
CyberMind-FR f2dfb5c144 feat(ai): Add v0.19 AI agent packages
Network Anomaly Agent (secubox-network-anomaly):
- 5 detection modules: bandwidth, connection flood, port scan, DNS, protocol
- EMA-based baseline comparison
- LocalAI integration for threat assessment
- network-anomalyctl CLI

LocalRecall Memory System (secubox-localrecall):
- Persistent memory for AI agents
- Categories: threats, decisions, patterns, configs, conversations
- EMA-based importance scoring
- LocalAI integration for summarization
- localrecallctl CLI with 13 commands

AI Insights Dashboard (luci-app-ai-insights):
- Unified view across all AI agents
- Security posture scoring (0-100)
- Agent status grid with alert counts
- Aggregated alerts from all agents
- Run All Agents and AI Analysis actions

LuCI Dashboards:
- luci-app-network-anomaly with real-time stats
- luci-app-localrecall with memory management

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 18:58:08 +01:00

368 lines
7.1 KiB
Bash

#!/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 <<EOF
LocalRecall Memory Controller v$VERSION
Usage: $(basename "$0") <command> [options]
Commands:
status Show memory status
add <cat> <content> Add a memory (category: threats|decisions|patterns|configs|conversations)
get <id> Get memory by ID
search <query> 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 <id> Delete a memory
cleanup Cleanup old memories
export <file> Export memories to file
import <file> Import memories from file
summarize [cat] AI-summarize memories
context <agent> Get context for an agent
stats Show memory statistics
Options:
-a, --agent <name> 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 <<EOF
{
"enabled": $([ "$enabled" = "1" ] && echo "true" || echo "false"),
"total_memories": $total,
"threats": $threats,
"decisions": $decisions,
"patterns": $patterns,
"max_memories": ${max_mem:-1000},
"storage_path": "${storage:-/var/lib/localrecall}",
"storage_size": "$storage_size",
"localai_status": "$localai_status"
}
EOF
else
echo "LocalRecall Memory Status"
echo "========================="
echo "Enabled: $([ "$enabled" = "1" ] && echo "Yes" || echo "No")"
echo "Total: $total memories"
echo " Threats: $threats"
echo " Decisions: $decisions"
echo " Patterns: $patterns"
echo "Max: ${max_mem:-1000}"
echo "Storage: ${storage:-/var/lib/localrecall} ($storage_size)"
echo "LocalAI: $localai_status"
fi
}
cmd_add() {
local category="$1"
local content="$2"
local agent="${AGENT:-user}"
local importance="${IMPORTANCE:-5}"
if [ -z "$category" ] || [ -z "$content" ]; then
echo "Error: Category and content required"
echo "Usage: localrecallctl add <category> <content>"
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