Add autonomous agent framework and prompt library
- Self-healing, self-monitoring, self-optimizing agent framework - Prompt library with reusable templates for agent interactions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
700
scripts/autonomous-agents.sh
Normal file
700
scripts/autonomous-agents.sh
Normal file
@@ -0,0 +1,700 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# BlackRoad Memory Autonomous Agents
|
||||||
|
# Self-healing, self-monitoring, self-optimizing agents
|
||||||
|
|
||||||
|
MEMORY_DIR="$HOME/.blackroad/memory"
|
||||||
|
AGENTS_DIR="$MEMORY_DIR/agents"
|
||||||
|
AGENTS_DB="$AGENTS_DIR/agents.db"
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
PURPLE='\033[0;35m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
init() {
|
||||||
|
echo -e "${PURPLE}╔════════════════════════════════════════════════╗${NC}"
|
||||||
|
echo -e "${PURPLE}║ 🤖 Autonomous Agent System ║${NC}"
|
||||||
|
echo -e "${PURPLE}╚════════════════════════════════════════════════╝${NC}\n"
|
||||||
|
|
||||||
|
mkdir -p "$AGENTS_DIR/logs"
|
||||||
|
|
||||||
|
# Create agents database
|
||||||
|
sqlite3 "$AGENTS_DB" <<'SQL'
|
||||||
|
-- Autonomous agents
|
||||||
|
CREATE TABLE IF NOT EXISTS agents (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
name TEXT UNIQUE NOT NULL,
|
||||||
|
type TEXT NOT NULL, -- 'monitor', 'healer', 'optimizer', 'predictor'
|
||||||
|
status TEXT DEFAULT 'idle', -- 'idle', 'running', 'paused', 'error'
|
||||||
|
config TEXT, -- JSON configuration
|
||||||
|
created_at INTEGER NOT NULL,
|
||||||
|
started_at INTEGER,
|
||||||
|
last_action INTEGER,
|
||||||
|
actions_taken INTEGER DEFAULT 0,
|
||||||
|
success_count INTEGER DEFAULT 0,
|
||||||
|
failure_count INTEGER DEFAULT 0
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Agent actions log
|
||||||
|
CREATE TABLE IF NOT EXISTS agent_actions (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
agent_id INTEGER NOT NULL,
|
||||||
|
action_type TEXT NOT NULL,
|
||||||
|
target TEXT,
|
||||||
|
details TEXT,
|
||||||
|
success INTEGER,
|
||||||
|
duration INTEGER, -- milliseconds
|
||||||
|
timestamp INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY (agent_id) REFERENCES agents(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Agent insights
|
||||||
|
CREATE TABLE IF NOT EXISTS agent_insights (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
agent_id INTEGER NOT NULL,
|
||||||
|
insight_type TEXT NOT NULL, -- 'anomaly', 'pattern', 'recommendation', 'prediction'
|
||||||
|
insight_data TEXT NOT NULL, -- JSON data
|
||||||
|
confidence REAL,
|
||||||
|
timestamp INTEGER NOT NULL,
|
||||||
|
acted_upon INTEGER DEFAULT 0,
|
||||||
|
FOREIGN KEY (agent_id) REFERENCES agents(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Agent communication (inter-agent messaging)
|
||||||
|
CREATE TABLE IF NOT EXISTS agent_messages (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
from_agent_id INTEGER NOT NULL,
|
||||||
|
to_agent_id INTEGER, -- NULL for broadcast
|
||||||
|
message_type TEXT NOT NULL,
|
||||||
|
message TEXT NOT NULL,
|
||||||
|
timestamp INTEGER NOT NULL,
|
||||||
|
read INTEGER DEFAULT 0,
|
||||||
|
FOREIGN KEY (from_agent_id) REFERENCES agents(id),
|
||||||
|
FOREIGN KEY (to_agent_id) REFERENCES agents(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Create indexes
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_agent_actions_agent ON agent_actions(agent_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_agent_actions_timestamp ON agent_actions(timestamp);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_agent_insights_agent ON agent_insights(agent_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_agent_insights_timestamp ON agent_insights(timestamp);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_agent_messages_to ON agent_messages(to_agent_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_agent_messages_read ON agent_messages(read);
|
||||||
|
|
||||||
|
SQL
|
||||||
|
|
||||||
|
# Create default agents
|
||||||
|
local timestamp=$(date +%s)
|
||||||
|
|
||||||
|
sqlite3 "$AGENTS_DB" <<SQL
|
||||||
|
INSERT OR IGNORE INTO agents (name, type, config, created_at)
|
||||||
|
VALUES
|
||||||
|
('Guardian', 'monitor', '{"check_interval":60,"alert_threshold":"high"}', $timestamp),
|
||||||
|
('Healer', 'healer', '{"auto_heal":true,"max_attempts":3}', $timestamp),
|
||||||
|
('Optimizer', 'optimizer', '{"optimize_interval":3600,"targets":["indexes","performance"]}', $timestamp),
|
||||||
|
('Prophet', 'predictor', '{"prediction_interval":300,"confidence_threshold":0.7}', $timestamp),
|
||||||
|
('Scout', 'monitor', '{"watch":["journal","api","stream"],"report_interval":300}', $timestamp);
|
||||||
|
SQL
|
||||||
|
|
||||||
|
echo -e "${GREEN}✓${NC} Autonomous agent system initialized"
|
||||||
|
echo -e "${CYAN}Created 5 default agents:${NC}"
|
||||||
|
echo -e " 🛡️ ${PURPLE}Guardian${NC} - System health monitor"
|
||||||
|
echo -e " 🏥 ${PURPLE}Healer${NC} - Auto-healing agent"
|
||||||
|
echo -e " ⚡ ${PURPLE}Optimizer${NC} - Performance optimizer"
|
||||||
|
echo -e " 🔮 ${PURPLE}Prophet${NC} - Predictive agent"
|
||||||
|
echo -e " 🔍 ${PURPLE}Scout${NC} - Activity scout"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get agent ID by name
|
||||||
|
get_agent_id() {
|
||||||
|
local name="$1"
|
||||||
|
sqlite3 "$AGENTS_DB" "SELECT id FROM agents WHERE name = '$name'"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Log agent action
|
||||||
|
log_action() {
|
||||||
|
local agent_name="$1"
|
||||||
|
local action_type="$2"
|
||||||
|
local target="$3"
|
||||||
|
local details="$4"
|
||||||
|
local success="$5"
|
||||||
|
local duration="${6:-0}"
|
||||||
|
|
||||||
|
local agent_id=$(get_agent_id "$agent_name")
|
||||||
|
local timestamp=$(date +%s)
|
||||||
|
|
||||||
|
sqlite3 "$AGENTS_DB" <<SQL
|
||||||
|
INSERT INTO agent_actions (agent_id, action_type, target, details, success, duration, timestamp)
|
||||||
|
VALUES ($agent_id, '$action_type', '$target', '$details', $success, $duration, $timestamp);
|
||||||
|
|
||||||
|
UPDATE agents SET
|
||||||
|
last_action = $timestamp,
|
||||||
|
actions_taken = actions_taken + 1,
|
||||||
|
success_count = success_count + $success,
|
||||||
|
failure_count = failure_count + $([ "$success" -eq 0 ] && echo 1 || echo 0)
|
||||||
|
WHERE id = $agent_id;
|
||||||
|
SQL
|
||||||
|
}
|
||||||
|
|
||||||
|
# Record agent insight
|
||||||
|
record_insight() {
|
||||||
|
local agent_name="$1"
|
||||||
|
local insight_type="$2"
|
||||||
|
local insight_data="$3"
|
||||||
|
local confidence="$4"
|
||||||
|
|
||||||
|
local agent_id=$(get_agent_id "$agent_name")
|
||||||
|
local timestamp=$(date +%s)
|
||||||
|
|
||||||
|
sqlite3 "$AGENTS_DB" <<SQL
|
||||||
|
INSERT INTO agent_insights (agent_id, insight_type, insight_data, confidence, timestamp)
|
||||||
|
VALUES ($agent_id, '$insight_type', '$(echo "$insight_data" | sed "s/'/''/g")', $confidence, $timestamp);
|
||||||
|
SQL
|
||||||
|
}
|
||||||
|
|
||||||
|
# Send agent message
|
||||||
|
send_message() {
|
||||||
|
local from_agent="$1"
|
||||||
|
local to_agent="$2" # "broadcast" for all agents
|
||||||
|
local message_type="$3"
|
||||||
|
local message="$4"
|
||||||
|
|
||||||
|
local from_id=$(get_agent_id "$from_agent")
|
||||||
|
local to_id=""
|
||||||
|
|
||||||
|
if [ "$to_agent" != "broadcast" ]; then
|
||||||
|
to_id=$(get_agent_id "$to_agent")
|
||||||
|
fi
|
||||||
|
|
||||||
|
local timestamp=$(date +%s)
|
||||||
|
|
||||||
|
sqlite3 "$AGENTS_DB" <<SQL
|
||||||
|
INSERT INTO agent_messages (from_agent_id, to_agent_id, message_type, message, timestamp)
|
||||||
|
VALUES ($from_id, $([ -z "$to_id" ] && echo "NULL" || echo "$to_id"), '$message_type', '$message', $timestamp);
|
||||||
|
SQL
|
||||||
|
}
|
||||||
|
|
||||||
|
# Read agent messages
|
||||||
|
read_messages() {
|
||||||
|
local agent_name="$1"
|
||||||
|
local agent_id=$(get_agent_id "$agent_name")
|
||||||
|
|
||||||
|
sqlite3 "$AGENTS_DB" <<SQL
|
||||||
|
SELECT
|
||||||
|
(SELECT name FROM agents WHERE id = from_agent_id) as from_agent,
|
||||||
|
message_type,
|
||||||
|
message,
|
||||||
|
datetime(timestamp, 'unixepoch', 'localtime') as received
|
||||||
|
FROM agent_messages
|
||||||
|
WHERE (to_agent_id = $agent_id OR to_agent_id IS NULL) AND read = 0
|
||||||
|
ORDER BY timestamp DESC;
|
||||||
|
SQL
|
||||||
|
|
||||||
|
# Mark as read
|
||||||
|
sqlite3 "$AGENTS_DB" <<SQL
|
||||||
|
UPDATE agent_messages SET read = 1 WHERE to_agent_id = $agent_id OR to_agent_id IS NULL;
|
||||||
|
SQL
|
||||||
|
}
|
||||||
|
|
||||||
|
# AGENT: Guardian (Monitor)
|
||||||
|
run_guardian() {
|
||||||
|
local agent="Guardian"
|
||||||
|
local timestamp=$(date +%s)
|
||||||
|
|
||||||
|
echo -e "${CYAN}🛡️ Guardian Agent: Starting health monitoring...${NC}"
|
||||||
|
|
||||||
|
sqlite3 "$AGENTS_DB" "UPDATE agents SET status = 'running', started_at = $timestamp WHERE name = '$agent'"
|
||||||
|
|
||||||
|
local iteration=0
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
iteration=$((iteration + 1))
|
||||||
|
local start_time=$(date +%s%3N)
|
||||||
|
|
||||||
|
echo -e "\n${PURPLE}[Guardian] Iteration $iteration - $(date '+%H:%M:%S')${NC}"
|
||||||
|
|
||||||
|
# Check memory system health
|
||||||
|
local journal_size=$(wc -l < "$MEMORY_DIR/journals/master-journal.jsonl" 2>/dev/null || echo 0)
|
||||||
|
|
||||||
|
if [ "$journal_size" -gt 0 ]; then
|
||||||
|
echo -e "${GREEN}✓${NC} Memory journal: $journal_size entries"
|
||||||
|
log_action "$agent" "health_check" "memory_journal" "Healthy: $journal_size entries" 1 0
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗${NC} Memory journal: Empty or missing"
|
||||||
|
log_action "$agent" "health_check" "memory_journal" "Error: Empty or missing" 0 0
|
||||||
|
send_message "$agent" "Healer" "alert" "Memory journal is empty or missing"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check indexes
|
||||||
|
if [ -f "$MEMORY_DIR/indexes/indexes.db" ]; then
|
||||||
|
local indexed=$(sqlite3 "$MEMORY_DIR/indexes/indexes.db" "SELECT COUNT(*) FROM action_index" 2>/dev/null || echo 0)
|
||||||
|
echo -e "${GREEN}✓${NC} Indexes: $indexed actions indexed"
|
||||||
|
log_action "$agent" "health_check" "indexes" "Healthy: $indexed actions" 1 0
|
||||||
|
|
||||||
|
# Detect if indexes are out of sync
|
||||||
|
local diff=$((journal_size - indexed))
|
||||||
|
if [ "$diff" -gt 100 ]; then
|
||||||
|
echo -e "${YELLOW}⚠️${NC} Indexes out of sync: $diff entries behind"
|
||||||
|
record_insight "$agent" "anomaly" "{\"type\":\"index_lag\",\"entries_behind\":$diff}" 0.9
|
||||||
|
send_message "$agent" "Optimizer" "suggestion" "Indexes need rebuilding: $diff entries behind"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗${NC} Indexes: Database missing"
|
||||||
|
log_action "$agent" "health_check" "indexes" "Error: Database missing" 0 0
|
||||||
|
send_message "$agent" "Healer" "alert" "Index database is missing"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check codex
|
||||||
|
if [ -f "$MEMORY_DIR/codex/codex.db" ]; then
|
||||||
|
local solutions=$(sqlite3 "$MEMORY_DIR/codex/codex.db" "SELECT COUNT(*) FROM solutions" 2>/dev/null || echo 0)
|
||||||
|
echo -e "${GREEN}✓${NC} Codex: $solutions solutions"
|
||||||
|
log_action "$agent" "health_check" "codex" "Healthy: $solutions solutions" 1 0
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}⚠️${NC} Codex: Database missing"
|
||||||
|
log_action "$agent" "health_check" "codex" "Warning: Database missing" 0 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check disk space
|
||||||
|
local disk_usage=$(df -h "$MEMORY_DIR" | tail -1 | awk '{print $5}' | tr -d '%')
|
||||||
|
if [ "$disk_usage" -gt 90 ]; then
|
||||||
|
echo -e "${RED}✗${NC} Disk space: ${disk_usage}% used (CRITICAL)"
|
||||||
|
log_action "$agent" "health_check" "disk_space" "Critical: ${disk_usage}% used" 0 0
|
||||||
|
send_message "$agent" "Healer" "alert" "Disk space critical: ${disk_usage}% used"
|
||||||
|
elif [ "$disk_usage" -gt 75 ]; then
|
||||||
|
echo -e "${YELLOW}⚠️${NC} Disk space: ${disk_usage}% used (Warning)"
|
||||||
|
log_action "$agent" "health_check" "disk_space" "Warning: ${disk_usage}% used" 1 0
|
||||||
|
else
|
||||||
|
echo -e "${GREEN}✓${NC} Disk space: ${disk_usage}% used"
|
||||||
|
log_action "$agent" "health_check" "disk_space" "Healthy: ${disk_usage}% used" 1 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for stuck processes
|
||||||
|
local stuck=$(ps aux | grep -c "sqlite3.*memory" | grep -v grep)
|
||||||
|
if [ "$stuck" -gt 5 ]; then
|
||||||
|
echo -e "${RED}✗${NC} Processes: $stuck sqlite processes (possible lock)"
|
||||||
|
log_action "$agent" "health_check" "processes" "Warning: $stuck processes" 0 0
|
||||||
|
send_message "$agent" "Healer" "alert" "Possible database lock: $stuck sqlite processes"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check messages from other agents
|
||||||
|
local messages=$(sqlite3 "$AGENTS_DB" "SELECT COUNT(*) FROM agent_messages WHERE to_agent_id = $(get_agent_id "$agent") AND read = 0")
|
||||||
|
if [ "$messages" -gt 0 ]; then
|
||||||
|
echo -e "${CYAN}📬 $messages new messages${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local end_time=$(date +%s%3N)
|
||||||
|
local duration=$((end_time - start_time))
|
||||||
|
|
||||||
|
echo -e "${CYAN}Duration: ${duration}ms${NC}"
|
||||||
|
|
||||||
|
# Sleep 60 seconds
|
||||||
|
sleep 60
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# AGENT: Healer (Auto-healing)
|
||||||
|
run_healer() {
|
||||||
|
local agent="Healer"
|
||||||
|
local timestamp=$(date +%s)
|
||||||
|
|
||||||
|
echo -e "${CYAN}🏥 Healer Agent: Starting auto-healing service...${NC}"
|
||||||
|
|
||||||
|
sqlite3 "$AGENTS_DB" "UPDATE agents SET status = 'running', started_at = $timestamp WHERE name = '$agent'"
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
# Check for alerts from Guardian
|
||||||
|
local alerts=$(sqlite3 "$AGENTS_DB" "SELECT COUNT(*) FROM agent_messages WHERE to_agent_id = $(get_agent_id "$agent") AND read = 0 AND message_type = 'alert'")
|
||||||
|
|
||||||
|
if [ "$alerts" -gt 0 ]; then
|
||||||
|
echo -e "\n${YELLOW}🚨 $alerts alerts received from Guardian${NC}"
|
||||||
|
|
||||||
|
# Read and process alerts
|
||||||
|
sqlite3 "$AGENTS_DB" "SELECT message FROM agent_messages WHERE to_agent_id = $(get_agent_id "$agent") AND read = 0 AND message_type = 'alert'" | \
|
||||||
|
while IFS= read -r alert; do
|
||||||
|
echo -e "${CYAN}Processing: $alert${NC}"
|
||||||
|
|
||||||
|
local start_time=$(date +%s%3N)
|
||||||
|
|
||||||
|
# Determine healing action
|
||||||
|
if echo "$alert" | grep -qi "journal.*empty"; then
|
||||||
|
echo -e "${YELLOW}🔧 Attempting to restore journal...${NC}"
|
||||||
|
# Try to restore from backup
|
||||||
|
if [ -f "$MEMORY_DIR/journals/master-journal.jsonl.bak" ]; then
|
||||||
|
cp "$MEMORY_DIR/journals/master-journal.jsonl.bak" "$MEMORY_DIR/journals/master-journal.jsonl"
|
||||||
|
echo -e "${GREEN}✓${NC} Journal restored from backup"
|
||||||
|
log_action "$agent" "heal" "memory_journal" "Restored from backup" 1 0
|
||||||
|
send_message "$agent" "Guardian" "success" "Journal restored successfully"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗${NC} No backup available"
|
||||||
|
log_action "$agent" "heal" "memory_journal" "Failed: No backup" 0 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
elif echo "$alert" | grep -qi "index.*missing"; then
|
||||||
|
echo -e "${YELLOW}🔧 Rebuilding indexes...${NC}"
|
||||||
|
~/memory-indexer.sh rebuild >/dev/null 2>&1
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo -e "${GREEN}✓${NC} Indexes rebuilt"
|
||||||
|
log_action "$agent" "heal" "indexes" "Rebuilt successfully" 1 0
|
||||||
|
send_message "$agent" "Guardian" "success" "Indexes rebuilt successfully"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗${NC} Rebuild failed"
|
||||||
|
log_action "$agent" "heal" "indexes" "Rebuild failed" 0 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
elif echo "$alert" | grep -qi "disk.*critical"; then
|
||||||
|
echo -e "${YELLOW}🔧 Cleaning up old data...${NC}"
|
||||||
|
# Clean old stream events
|
||||||
|
sqlite3 "$MEMORY_DIR/stream/stream.db" "DELETE FROM stream_events WHERE timestamp < strftime('%s', 'now', '-7 days')" 2>/dev/null
|
||||||
|
# Clean old API logs
|
||||||
|
sqlite3 "$MEMORY_DIR/api/api.db" "DELETE FROM api_requests WHERE timestamp < strftime('%s', 'now', '-30 days')" 2>/dev/null
|
||||||
|
echo -e "${GREEN}✓${NC} Old data cleaned"
|
||||||
|
log_action "$agent" "heal" "disk_space" "Cleaned old data" 1 0
|
||||||
|
send_message "$agent" "Guardian" "success" "Disk space cleaned"
|
||||||
|
|
||||||
|
elif echo "$alert" | grep -qi "database lock"; then
|
||||||
|
echo -e "${YELLOW}🔧 Clearing stuck processes...${NC}"
|
||||||
|
pkill -f "sqlite3.*memory" 2>/dev/null
|
||||||
|
sleep 1
|
||||||
|
echo -e "${GREEN}✓${NC} Processes cleared"
|
||||||
|
log_action "$agent" "heal" "processes" "Cleared stuck processes" 1 0
|
||||||
|
send_message "$agent" "Guardian" "success" "Database locks cleared"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local end_time=$(date +%s%3N)
|
||||||
|
local duration=$((end_time - start_time))
|
||||||
|
echo -e "${CYAN}Healing duration: ${duration}ms${NC}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Mark alerts as read
|
||||||
|
sqlite3 "$AGENTS_DB" "UPDATE agent_messages SET read = 1 WHERE to_agent_id = $(get_agent_id "$agent") AND message_type = 'alert'"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Sleep 10 seconds
|
||||||
|
sleep 10
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# AGENT: Optimizer (Performance)
|
||||||
|
run_optimizer() {
|
||||||
|
local agent="Optimizer"
|
||||||
|
local timestamp=$(date +%s)
|
||||||
|
|
||||||
|
echo -e "${CYAN}⚡ Optimizer Agent: Starting optimization service...${NC}"
|
||||||
|
|
||||||
|
sqlite3 "$AGENTS_DB" "UPDATE agents SET status = 'running', started_at = $timestamp WHERE name = '$agent'"
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
echo -e "\n${PURPLE}[Optimizer] Running optimization cycle - $(date '+%H:%M:%S')${NC}"
|
||||||
|
|
||||||
|
local start_time=$(date +%s%3N)
|
||||||
|
|
||||||
|
# Optimize indexes
|
||||||
|
echo -e "${CYAN}🔧 Optimizing indexes...${NC}"
|
||||||
|
sqlite3 "$MEMORY_DIR/indexes/indexes.db" "VACUUM; ANALYZE;" 2>/dev/null
|
||||||
|
echo -e "${GREEN}✓${NC} Indexes optimized"
|
||||||
|
log_action "$agent" "optimize" "indexes" "Optimized" 1 0
|
||||||
|
|
||||||
|
# Optimize codex
|
||||||
|
echo -e "${CYAN}🔧 Optimizing codex...${NC}"
|
||||||
|
sqlite3 "$MEMORY_DIR/codex/codex.db" "VACUUM; ANALYZE;" 2>/dev/null
|
||||||
|
echo -e "${GREEN}✓${NC} Codex optimized"
|
||||||
|
log_action "$agent" "optimize" "codex" "Optimized" 1 0
|
||||||
|
|
||||||
|
# Optimize agent database
|
||||||
|
echo -e "${CYAN}🔧 Optimizing agent database...${NC}"
|
||||||
|
sqlite3 "$AGENTS_DB" "VACUUM; ANALYZE;" 2>/dev/null
|
||||||
|
echo -e "${GREEN}✓${NC} Agent database optimized"
|
||||||
|
log_action "$agent" "optimize" "agents_db" "Optimized" 1 0
|
||||||
|
|
||||||
|
# Check for suggestions from Guardian
|
||||||
|
local suggestions=$(sqlite3 "$AGENTS_DB" "SELECT COUNT(*) FROM agent_messages WHERE to_agent_id = $(get_agent_id "$agent") AND read = 0 AND message_type = 'suggestion'")
|
||||||
|
|
||||||
|
if [ "$suggestions" -gt 0 ]; then
|
||||||
|
echo -e "${CYAN}💡 $suggestions optimization suggestions received${NC}"
|
||||||
|
|
||||||
|
sqlite3 "$AGENTS_DB" "SELECT message FROM agent_messages WHERE to_agent_id = $(get_agent_id "$agent") AND read = 0 AND message_type = 'suggestion'" | \
|
||||||
|
while IFS= read -r suggestion; do
|
||||||
|
echo -e "${YELLOW}Processing: $suggestion${NC}"
|
||||||
|
|
||||||
|
if echo "$suggestion" | grep -qi "indexes.*rebuild"; then
|
||||||
|
echo -e "${CYAN}🔧 Rebuilding indexes as suggested...${NC}"
|
||||||
|
~/memory-indexer.sh rebuild >/dev/null 2>&1
|
||||||
|
echo -e "${GREEN}✓${NC} Indexes rebuilt"
|
||||||
|
log_action "$agent" "optimize" "indexes" "Rebuilt from suggestion" 1 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
sqlite3 "$AGENTS_DB" "UPDATE agent_messages SET read = 1 WHERE to_agent_id = $(get_agent_id "$agent") AND message_type = 'suggestion'"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local end_time=$(date +%s%3N)
|
||||||
|
local duration=$((end_time - start_time))
|
||||||
|
|
||||||
|
echo -e "${CYAN}Optimization cycle completed in ${duration}ms${NC}"
|
||||||
|
|
||||||
|
# Sleep 1 hour
|
||||||
|
sleep 3600
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# AGENT: Prophet (Predictor)
|
||||||
|
run_prophet() {
|
||||||
|
local agent="Prophet"
|
||||||
|
local timestamp=$(date +%s)
|
||||||
|
|
||||||
|
echo -e "${CYAN}🔮 Prophet Agent: Starting prediction service...${NC}"
|
||||||
|
|
||||||
|
sqlite3 "$AGENTS_DB" "UPDATE agents SET status = 'running', started_at = $timestamp WHERE name = '$agent'"
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
echo -e "\n${PURPLE}[Prophet] Running prediction cycle - $(date '+%H:%M:%S')${NC}"
|
||||||
|
|
||||||
|
# Detect anomalies
|
||||||
|
echo -e "${CYAN}🔍 Detecting anomalies...${NC}"
|
||||||
|
local anomalies=$(~/memory-predictor.sh anomalies 2>/dev/null | tail -n +2)
|
||||||
|
|
||||||
|
if [ -n "$anomalies" ]; then
|
||||||
|
echo -e "${YELLOW}⚠️ Anomalies detected:${NC}"
|
||||||
|
echo "$anomalies"
|
||||||
|
|
||||||
|
# Record insights
|
||||||
|
local anomaly_count=$(echo "$anomalies" | wc -l)
|
||||||
|
record_insight "$agent" "anomaly" "{\"count\":$anomaly_count,\"details\":\"$(echo "$anomalies" | tr '\n' ' ')\"}" 0.85
|
||||||
|
|
||||||
|
# Alert Guardian
|
||||||
|
send_message "$agent" "Guardian" "info" "Detected $anomaly_count anomalies in recent activity"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Forecast activity
|
||||||
|
echo -e "${CYAN}📊 Forecasting activity...${NC}"
|
||||||
|
~/memory-predictor.sh forecast 7 2>/dev/null | tail -5
|
||||||
|
|
||||||
|
# Make predictions for high-risk entities
|
||||||
|
local high_risk=$(sqlite3 "$MEMORY_DIR/indexes/indexes.db" "SELECT DISTINCT entity FROM action_index WHERE action = 'failed' ORDER BY timestamp DESC LIMIT 5" 2>/dev/null)
|
||||||
|
|
||||||
|
if [ -n "$high_risk" ]; then
|
||||||
|
echo -e "${YELLOW}🎯 Analyzing high-risk entities...${NC}"
|
||||||
|
echo "$high_risk" | while IFS= read -r entity; do
|
||||||
|
local prediction=$(~/memory-predictor.sh predict "$entity" 2>/dev/null)
|
||||||
|
echo -e " ${CYAN}$entity:${NC} $prediction"
|
||||||
|
|
||||||
|
if echo "$prediction" | grep -qi "LOW"; then
|
||||||
|
# Low success probability - send recommendation
|
||||||
|
record_insight "$agent" "prediction" "{\"entity\":\"$entity\",\"prediction\":\"low_success\"}" 0.8
|
||||||
|
send_message "$agent" "broadcast" "warning" "Entity $entity has low predicted success rate"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Sleep 5 minutes
|
||||||
|
sleep 300
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# List all agents
|
||||||
|
list_agents() {
|
||||||
|
echo -e "${PURPLE}╔════════════════════════════════════════════════╗${NC}"
|
||||||
|
echo -e "${PURPLE}║ Autonomous Agents ║${NC}"
|
||||||
|
echo -e "${PURPLE}╚════════════════════════════════════════════════╝${NC}\n"
|
||||||
|
|
||||||
|
sqlite3 -header -column "$AGENTS_DB" <<SQL
|
||||||
|
SELECT
|
||||||
|
name,
|
||||||
|
type,
|
||||||
|
status,
|
||||||
|
actions_taken,
|
||||||
|
success_count,
|
||||||
|
failure_count,
|
||||||
|
ROUND(100.0 * success_count / NULLIF(actions_taken, 0), 1) as success_rate
|
||||||
|
FROM agents
|
||||||
|
ORDER BY name;
|
||||||
|
SQL
|
||||||
|
}
|
||||||
|
|
||||||
|
# Show agent statistics
|
||||||
|
show_agent_stats() {
|
||||||
|
local agent_name="$1"
|
||||||
|
|
||||||
|
if [ -z "$agent_name" ]; then
|
||||||
|
echo -e "${RED}Error: Agent name required${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local agent_id=$(get_agent_id "$agent_name")
|
||||||
|
|
||||||
|
if [ -z "$agent_id" ]; then
|
||||||
|
echo -e "${RED}Error: Agent not found: $agent_name${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${PURPLE}╔════════════════════════════════════════════════╗${NC}"
|
||||||
|
echo -e "${PURPLE}║ Agent: $agent_name${NC}"
|
||||||
|
echo -e "${PURPLE}╚════════════════════════════════════════════════╝${NC}\n"
|
||||||
|
|
||||||
|
# Basic stats
|
||||||
|
sqlite3 -header -column "$AGENTS_DB" <<SQL
|
||||||
|
SELECT
|
||||||
|
type,
|
||||||
|
status,
|
||||||
|
actions_taken,
|
||||||
|
success_count,
|
||||||
|
failure_count,
|
||||||
|
ROUND(100.0 * success_count / NULLIF(actions_taken, 0), 1) as success_rate,
|
||||||
|
datetime(created_at, 'unixepoch', 'localtime') as created,
|
||||||
|
datetime(started_at, 'unixepoch', 'localtime') as started,
|
||||||
|
datetime(last_action, 'unixepoch', 'localtime') as last_action
|
||||||
|
FROM agents
|
||||||
|
WHERE id = $agent_id;
|
||||||
|
SQL
|
||||||
|
|
||||||
|
# Recent actions
|
||||||
|
echo -e "\n${PURPLE}Recent Actions:${NC}"
|
||||||
|
sqlite3 -header -column "$AGENTS_DB" <<SQL
|
||||||
|
SELECT
|
||||||
|
action_type,
|
||||||
|
target,
|
||||||
|
CASE WHEN success = 1 THEN '✓' ELSE '✗' END as result,
|
||||||
|
duration || 'ms' as duration,
|
||||||
|
datetime(timestamp, 'unixepoch', 'localtime') as time
|
||||||
|
FROM agent_actions
|
||||||
|
WHERE agent_id = $agent_id
|
||||||
|
ORDER BY timestamp DESC
|
||||||
|
LIMIT 10;
|
||||||
|
SQL
|
||||||
|
|
||||||
|
# Insights
|
||||||
|
echo -e "\n${PURPLE}Recent Insights:${NC}"
|
||||||
|
sqlite3 -header -column "$AGENTS_DB" <<SQL
|
||||||
|
SELECT
|
||||||
|
insight_type,
|
||||||
|
SUBSTR(insight_data, 1, 50) as insight,
|
||||||
|
ROUND(confidence * 100, 1) || '%' as confidence,
|
||||||
|
datetime(timestamp, 'unixepoch', 'localtime') as time
|
||||||
|
FROM agent_insights
|
||||||
|
WHERE agent_id = $agent_id
|
||||||
|
ORDER BY timestamp DESC
|
||||||
|
LIMIT 5;
|
||||||
|
SQL
|
||||||
|
}
|
||||||
|
|
||||||
|
# Start all agents
|
||||||
|
start_all_agents() {
|
||||||
|
echo -e "${PURPLE}╔════════════════════════════════════════════════╗${NC}"
|
||||||
|
echo -e "${PURPLE}║ 🚀 Starting All Autonomous Agents ║${NC}"
|
||||||
|
echo -e "${PURPLE}╚════════════════════════════════════════════════╝${NC}\n"
|
||||||
|
|
||||||
|
# Start each agent in background
|
||||||
|
run_guardian >> "$AGENTS_DIR/logs/guardian.log" 2>&1 &
|
||||||
|
echo $! > "$AGENTS_DIR/guardian.pid"
|
||||||
|
echo -e "${GREEN}✓${NC} Guardian started (PID: $!)"
|
||||||
|
|
||||||
|
run_healer >> "$AGENTS_DIR/logs/healer.log" 2>&1 &
|
||||||
|
echo $! > "$AGENTS_DIR/healer.pid"
|
||||||
|
echo -e "${GREEN}✓${NC} Healer started (PID: $!)"
|
||||||
|
|
||||||
|
run_optimizer >> "$AGENTS_DIR/logs/optimizer.log" 2>&1 &
|
||||||
|
echo $! > "$AGENTS_DIR/optimizer.pid"
|
||||||
|
echo -e "${GREEN}✓${NC} Optimizer started (PID: $!)"
|
||||||
|
|
||||||
|
run_prophet >> "$AGENTS_DIR/logs/prophet.log" 2>&1 &
|
||||||
|
echo $! > "$AGENTS_DIR/prophet.pid"
|
||||||
|
echo -e "${GREEN}✓${NC} Prophet started (PID: $!)"
|
||||||
|
|
||||||
|
echo -e "\n${GREEN}🤖 All autonomous agents running!${NC}"
|
||||||
|
echo -e "\n${CYAN}Logs:${NC}"
|
||||||
|
echo -e " Guardian: tail -f $AGENTS_DIR/logs/guardian.log"
|
||||||
|
echo -e " Healer: tail -f $AGENTS_DIR/logs/healer.log"
|
||||||
|
echo -e " Optimizer: tail -f $AGENTS_DIR/logs/optimizer.log"
|
||||||
|
echo -e " Prophet: tail -f $AGENTS_DIR/logs/prophet.log"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Stop all agents
|
||||||
|
stop_all_agents() {
|
||||||
|
echo -e "${YELLOW}🛑 Stopping all autonomous agents...${NC}"
|
||||||
|
|
||||||
|
for agent in guardian healer optimizer prophet; do
|
||||||
|
local pid_file="$AGENTS_DIR/$agent.pid"
|
||||||
|
if [ -f "$pid_file" ]; then
|
||||||
|
local pid=$(cat "$pid_file")
|
||||||
|
kill "$pid" 2>/dev/null && echo -e "${GREEN}✓${NC} ${agent^} stopped"
|
||||||
|
rm "$pid_file"
|
||||||
|
|
||||||
|
# Update status
|
||||||
|
sqlite3 "$AGENTS_DB" "UPDATE agents SET status = 'idle' WHERE name = '${agent^}'"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -e "${GREEN}✓${NC} All agents stopped"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main execution
|
||||||
|
case "${1:-help}" in
|
||||||
|
init)
|
||||||
|
init
|
||||||
|
;;
|
||||||
|
start)
|
||||||
|
start_all_agents
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
stop_all_agents
|
||||||
|
;;
|
||||||
|
list)
|
||||||
|
list_agents
|
||||||
|
;;
|
||||||
|
stats)
|
||||||
|
show_agent_stats "$2"
|
||||||
|
;;
|
||||||
|
guardian)
|
||||||
|
run_guardian
|
||||||
|
;;
|
||||||
|
healer)
|
||||||
|
run_healer
|
||||||
|
;;
|
||||||
|
optimizer)
|
||||||
|
run_optimizer
|
||||||
|
;;
|
||||||
|
prophet)
|
||||||
|
run_prophet
|
||||||
|
;;
|
||||||
|
help|*)
|
||||||
|
echo -e "${PURPLE}╔════════════════════════════════════════════════╗${NC}"
|
||||||
|
echo -e "${PURPLE}║ 🤖 Autonomous Agent System ║${NC}"
|
||||||
|
echo -e "${PURPLE}╚════════════════════════════════════════════════╝${NC}\n"
|
||||||
|
echo "Self-healing, self-monitoring AI agents"
|
||||||
|
echo ""
|
||||||
|
echo "Usage: $0 COMMAND [OPTIONS]"
|
||||||
|
echo ""
|
||||||
|
echo "Setup:"
|
||||||
|
echo " init - Initialize agent system"
|
||||||
|
echo ""
|
||||||
|
echo "Control:"
|
||||||
|
echo " start - Start all agents"
|
||||||
|
echo " stop - Stop all agents"
|
||||||
|
echo ""
|
||||||
|
echo "Individual Agents:"
|
||||||
|
echo " guardian - Run Guardian (monitor)"
|
||||||
|
echo " healer - Run Healer (auto-heal)"
|
||||||
|
echo " optimizer - Run Optimizer (performance)"
|
||||||
|
echo " prophet - Run Prophet (predictions)"
|
||||||
|
echo ""
|
||||||
|
echo "Monitoring:"
|
||||||
|
echo " list - List all agents"
|
||||||
|
echo " stats AGENT - Show agent statistics"
|
||||||
|
echo ""
|
||||||
|
echo "Examples:"
|
||||||
|
echo " $0 init"
|
||||||
|
echo " $0 start"
|
||||||
|
echo " $0 stats Guardian"
|
||||||
|
echo " $0 list"
|
||||||
|
echo ""
|
||||||
|
echo "Agents:"
|
||||||
|
echo " 🛡️ Guardian - Monitors system health"
|
||||||
|
echo " 🏥 Healer - Auto-heals detected issues"
|
||||||
|
echo " ⚡ Optimizer - Optimizes performance"
|
||||||
|
echo " 🔮 Prophet - Predicts and prevents issues"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
442
scripts/prompt-library.sh
Normal file
442
scripts/prompt-library.sh
Normal file
@@ -0,0 +1,442 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# BlackRoad Prompt Library
|
||||||
|
# Curated collection of AI prompts for the cluster
|
||||||
|
# Agent: Icarus (b3e01bd9)
|
||||||
|
|
||||||
|
PINK='\033[38;5;205m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
RESET='\033[0m'
|
||||||
|
|
||||||
|
PROMPTS_DIR="$HOME/.blackroad/prompts"
|
||||||
|
PROMPTS_DB="$PROMPTS_DIR/prompts.db"
|
||||||
|
|
||||||
|
# Initialize
|
||||||
|
init() {
|
||||||
|
mkdir -p "$PROMPTS_DIR"/{templates,chains,personas}
|
||||||
|
|
||||||
|
sqlite3 "$PROMPTS_DB" << 'SQL'
|
||||||
|
CREATE TABLE IF NOT EXISTS prompts (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
name TEXT,
|
||||||
|
category TEXT,
|
||||||
|
description TEXT,
|
||||||
|
template TEXT,
|
||||||
|
variables TEXT,
|
||||||
|
model TEXT DEFAULT 'llama3.2:1b',
|
||||||
|
usage_count INTEGER DEFAULT 0,
|
||||||
|
rating REAL DEFAULT 0,
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS chains (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
name TEXT,
|
||||||
|
description TEXT,
|
||||||
|
steps TEXT,
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS personas (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
name TEXT,
|
||||||
|
system_prompt TEXT,
|
||||||
|
traits TEXT,
|
||||||
|
model TEXT DEFAULT 'llama3.2:1b'
|
||||||
|
);
|
||||||
|
SQL
|
||||||
|
|
||||||
|
# Seed with built-in prompts
|
||||||
|
seed_prompts
|
||||||
|
|
||||||
|
echo -e "${GREEN}Prompt library initialized${RESET}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Seed built-in prompts
|
||||||
|
seed_prompts() {
|
||||||
|
# Check if already seeded
|
||||||
|
local count=$(sqlite3 "$PROMPTS_DB" "SELECT COUNT(*) FROM prompts")
|
||||||
|
[ "$count" -gt 0 ] && return
|
||||||
|
|
||||||
|
# Analysis prompts
|
||||||
|
sqlite3 "$PROMPTS_DB" "INSERT OR IGNORE INTO prompts (id, name, category, description, template, variables, model) VALUES
|
||||||
|
('analyze-sentiment', 'Sentiment Analysis', 'analysis', 'Analyze text sentiment', 'Analyze the sentiment of this text and classify as positive, negative, or neutral. Explain why.\n\nText: {{TEXT}}', 'TEXT', 'llama3.2:1b'),
|
||||||
|
('summarize', 'Summarize Text', 'analysis', 'Create concise summary', 'Summarize the following text in 2-3 sentences, capturing the main points:\n\n{{TEXT}}', 'TEXT', 'llama3.2:1b'),
|
||||||
|
('extract-keywords', 'Extract Keywords', 'analysis', 'Extract key terms', 'Extract the 5 most important keywords from this text:\n\n{{TEXT}}', 'TEXT', 'llama3.2:1b'),
|
||||||
|
('explain-simple', 'Explain Simply', 'analysis', 'Explain for beginners', 'Explain {{TOPIC}} as if you were explaining it to a 10-year-old. Use simple language and examples.', 'TOPIC', 'llama3.2:1b')
|
||||||
|
"
|
||||||
|
|
||||||
|
# Coding prompts
|
||||||
|
sqlite3 "$PROMPTS_DB" "INSERT OR IGNORE INTO prompts (id, name, category, description, template, variables, model) VALUES
|
||||||
|
('code-review', 'Code Review', 'coding', 'Review code quality', 'Review this code for bugs, security issues, and improvements:\n\n\`\`\`{{LANGUAGE}}\n{{CODE}}\n\`\`\`', 'LANGUAGE,CODE', 'codellama:7b'),
|
||||||
|
('code-explain', 'Explain Code', 'coding', 'Explain what code does', 'Explain what this code does line by line:\n\n\`\`\`{{LANGUAGE}}\n{{CODE}}\n\`\`\`', 'LANGUAGE,CODE', 'codellama:7b'),
|
||||||
|
('code-convert', 'Convert Code', 'coding', 'Convert between languages', 'Convert this {{FROM}} code to {{TO}}:\n\n\`\`\`{{FROM}}\n{{CODE}}\n\`\`\`', 'FROM,TO,CODE', 'codellama:7b'),
|
||||||
|
('code-fix', 'Fix Bug', 'coding', 'Fix code bug', 'This code has a bug. Fix it and explain what was wrong:\n\n\`\`\`{{LANGUAGE}}\n{{CODE}}\n\`\`\`\n\nError: {{ERROR}}', 'LANGUAGE,CODE,ERROR', 'codellama:7b')
|
||||||
|
"
|
||||||
|
|
||||||
|
# Creative prompts
|
||||||
|
sqlite3 "$PROMPTS_DB" "INSERT OR IGNORE INTO prompts (id, name, category, description, template, variables, model) VALUES
|
||||||
|
('brainstorm', 'Brainstorm Ideas', 'creative', 'Generate ideas', 'Brainstorm 5 creative ideas for: {{TOPIC}}', 'TOPIC', 'llama3.2:1b'),
|
||||||
|
('write-email', 'Write Email', 'creative', 'Draft professional email', 'Write a professional email about {{SUBJECT}} to {{RECIPIENT}}. Tone: {{TONE}}', 'SUBJECT,RECIPIENT,TONE', 'llama3.2:1b'),
|
||||||
|
('storytelling', 'Tell Story', 'creative', 'Create short story', 'Write a short story (100 words) about {{TOPIC}} in the style of {{STYLE}}', 'TOPIC,STYLE', 'llama3.2:1b')
|
||||||
|
"
|
||||||
|
|
||||||
|
# System prompts
|
||||||
|
sqlite3 "$PROMPTS_DB" "INSERT OR IGNORE INTO prompts (id, name, category, description, template, variables, model) VALUES
|
||||||
|
('sysadmin', 'Sysadmin Help', 'system', 'Linux administration help', 'You are a Linux sysadmin expert. Help with: {{QUESTION}}', 'QUESTION', 'llama3.2:1b'),
|
||||||
|
('docker-help', 'Docker Help', 'system', 'Docker container help', 'You are a Docker expert. Help with: {{QUESTION}}\n\nContext: {{CONTEXT}}', 'QUESTION,CONTEXT', 'llama3.2:1b')
|
||||||
|
"
|
||||||
|
|
||||||
|
# Seed personas
|
||||||
|
sqlite3 "$PROMPTS_DB" "INSERT OR IGNORE INTO personas (id, name, system_prompt, traits, model) VALUES
|
||||||
|
('lucidia', 'Lucidia', 'You are Lucidia, a helpful AI assistant created by BlackRoad OS. You are friendly, knowledgeable, and slightly playful. You run on a distributed Raspberry Pi cluster.', 'helpful,friendly,playful,technical', 'llama3.2:1b'),
|
||||||
|
('coder', 'CodeBot', 'You are an expert programmer. You write clean, efficient, well-documented code. Always explain your solutions.', 'precise,technical,educational', 'codellama:7b'),
|
||||||
|
('analyst', 'Analyst', 'You are a data analyst. You break down complex problems, identify patterns, and provide actionable insights.', 'analytical,thorough,objective', 'llama3.2:3b'),
|
||||||
|
('creative', 'Creative', 'You are a creative thinker. You generate novel ideas and think outside the box. Be imaginative and unconventional.', 'creative,innovative,playful', 'llama3.2:1b')
|
||||||
|
"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add a prompt
|
||||||
|
add() {
|
||||||
|
local name="$1"
|
||||||
|
local category="$2"
|
||||||
|
local template="$3"
|
||||||
|
local description="${4:-}"
|
||||||
|
local variables="${5:-}"
|
||||||
|
local model="${6:-llama3.2:1b}"
|
||||||
|
|
||||||
|
local id=$(echo "$name" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')
|
||||||
|
|
||||||
|
sqlite3 "$PROMPTS_DB" "
|
||||||
|
INSERT OR REPLACE INTO prompts (id, name, category, description, template, variables, model)
|
||||||
|
VALUES ('$id', '$name', '$category', '$description', '$(echo "$template" | sed "s/'/''/g")', '$variables', '$model')
|
||||||
|
"
|
||||||
|
|
||||||
|
echo -e "${GREEN}Added prompt: $id${RESET}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get and use a prompt
|
||||||
|
use() {
|
||||||
|
local prompt_id="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
local prompt=$(sqlite3 "$PROMPTS_DB" "
|
||||||
|
SELECT template, variables, model FROM prompts WHERE id = '$prompt_id'
|
||||||
|
")
|
||||||
|
|
||||||
|
if [ -z "$prompt" ]; then
|
||||||
|
echo -e "${RED}Prompt not found: $prompt_id${RESET}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local template=$(echo "$prompt" | cut -d'|' -f1)
|
||||||
|
local variables=$(echo "$prompt" | cut -d'|' -f2)
|
||||||
|
local model=$(echo "$prompt" | cut -d'|' -f3)
|
||||||
|
|
||||||
|
# Replace variables
|
||||||
|
local filled="$template"
|
||||||
|
for var in "$@"; do
|
||||||
|
local key="${var%%=*}"
|
||||||
|
local value="${var#*=}"
|
||||||
|
filled=$(echo "$filled" | sed "s/{{$key}}/$value/g")
|
||||||
|
done
|
||||||
|
|
||||||
|
# Check for unfilled variables
|
||||||
|
if echo "$filled" | grep -q '{{'; then
|
||||||
|
echo -e "${YELLOW}Missing variables in prompt${RESET}"
|
||||||
|
echo "Required: $variables"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Update usage count
|
||||||
|
sqlite3 "$PROMPTS_DB" "UPDATE prompts SET usage_count = usage_count + 1 WHERE id = '$prompt_id'"
|
||||||
|
|
||||||
|
echo -e "${BLUE}Using prompt: $prompt_id (model: $model)${RESET}"
|
||||||
|
echo
|
||||||
|
echo "$filled"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run prompt against LLM
|
||||||
|
run() {
|
||||||
|
local prompt_id="$1"
|
||||||
|
shift
|
||||||
|
local node="${RUN_NODE:-cecilia}"
|
||||||
|
|
||||||
|
local filled=$(use "$prompt_id" "$@")
|
||||||
|
local model=$(sqlite3 "$PROMPTS_DB" "SELECT model FROM prompts WHERE id = '$prompt_id'")
|
||||||
|
|
||||||
|
echo -e "${PINK}=== RUNNING PROMPT ===${RESET}"
|
||||||
|
echo
|
||||||
|
|
||||||
|
ssh -o ConnectTimeout=30 "$node" \
|
||||||
|
"curl -s http://localhost:11434/api/generate -d '{\"model\":\"$model\",\"prompt\":\"$filled\",\"stream\":false}'" 2>/dev/null \
|
||||||
|
| jq -r '.response // "No response"'
|
||||||
|
}
|
||||||
|
|
||||||
|
# List prompts
|
||||||
|
list() {
|
||||||
|
local category="${1:-all}"
|
||||||
|
|
||||||
|
echo -e "${PINK}=== PROMPT LIBRARY ===${RESET}"
|
||||||
|
echo
|
||||||
|
|
||||||
|
local where=""
|
||||||
|
[ "$category" != "all" ] && where="WHERE category = '$category'"
|
||||||
|
|
||||||
|
sqlite3 "$PROMPTS_DB" "
|
||||||
|
SELECT id, name, category, usage_count FROM prompts $where ORDER BY category, name
|
||||||
|
" | while IFS='|' read -r id name category usage; do
|
||||||
|
printf " %-20s %-15s %-12s (%d uses)\n" "$id" "[$category]" "$name" "$usage"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Categories:"
|
||||||
|
sqlite3 "$PROMPTS_DB" "SELECT DISTINCT category FROM prompts" | tr '\n' ' '
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
# Search prompts
|
||||||
|
search() {
|
||||||
|
local query="$1"
|
||||||
|
|
||||||
|
echo -e "${PINK}=== SEARCH: $query ===${RESET}"
|
||||||
|
echo
|
||||||
|
|
||||||
|
sqlite3 "$PROMPTS_DB" "
|
||||||
|
SELECT id, name, description FROM prompts
|
||||||
|
WHERE name LIKE '%$query%' OR description LIKE '%$query%' OR template LIKE '%$query%'
|
||||||
|
" | while IFS='|' read -r id name desc; do
|
||||||
|
echo " $id: $name"
|
||||||
|
echo " $desc"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Show prompt details
|
||||||
|
show() {
|
||||||
|
local prompt_id="$1"
|
||||||
|
|
||||||
|
local prompt=$(sqlite3 "$PROMPTS_DB" -line "SELECT * FROM prompts WHERE id = '$prompt_id'")
|
||||||
|
|
||||||
|
if [ -z "$prompt" ]; then
|
||||||
|
echo -e "${RED}Prompt not found: $prompt_id${RESET}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${PINK}=== PROMPT: $prompt_id ===${RESET}"
|
||||||
|
echo
|
||||||
|
echo "$prompt"
|
||||||
|
}
|
||||||
|
|
||||||
|
# List personas
|
||||||
|
personas() {
|
||||||
|
echo -e "${PINK}=== PERSONAS ===${RESET}"
|
||||||
|
echo
|
||||||
|
|
||||||
|
sqlite3 "$PROMPTS_DB" "
|
||||||
|
SELECT id, name, traits FROM personas
|
||||||
|
" | while IFS='|' read -r id name traits; do
|
||||||
|
echo " $id: $name"
|
||||||
|
echo " Traits: $traits"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Chat with persona
|
||||||
|
chat_persona() {
|
||||||
|
local persona_id="$1"
|
||||||
|
local node="${CHAT_NODE:-cecilia}"
|
||||||
|
|
||||||
|
local persona=$(sqlite3 "$PROMPTS_DB" "
|
||||||
|
SELECT name, system_prompt, model FROM personas WHERE id = '$persona_id'
|
||||||
|
")
|
||||||
|
|
||||||
|
if [ -z "$persona" ]; then
|
||||||
|
echo -e "${RED}Persona not found: $persona_id${RESET}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local name=$(echo "$persona" | cut -d'|' -f1)
|
||||||
|
local system=$(echo "$persona" | cut -d'|' -f2)
|
||||||
|
local model=$(echo "$persona" | cut -d'|' -f3)
|
||||||
|
|
||||||
|
echo -e "${PINK}╔══════════════════════════════════════════════════════════════╗${RESET}"
|
||||||
|
echo -e "${PINK}║ 💬 CHAT WITH $name ║${RESET}"
|
||||||
|
echo -e "${PINK}╚══════════════════════════════════════════════════════════════╝${RESET}"
|
||||||
|
echo
|
||||||
|
echo "Model: $model | Node: $node"
|
||||||
|
echo "Type 'exit' to quit"
|
||||||
|
echo
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
echo -n -e "${GREEN}You: ${RESET}"
|
||||||
|
read -r input
|
||||||
|
|
||||||
|
[ "$input" = "exit" ] && break
|
||||||
|
|
||||||
|
local prompt="$system\n\nUser: $input\n$name:"
|
||||||
|
|
||||||
|
echo -n -e "${CYAN}$name: ${RESET}"
|
||||||
|
ssh "$node" "curl -s http://localhost:11434/api/generate -d '{\"model\":\"$model\",\"prompt\":\"$prompt\",\"stream\":false}'" 2>/dev/null \
|
||||||
|
| jq -r '.response // "..."'
|
||||||
|
echo
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create prompt chain
|
||||||
|
chain() {
|
||||||
|
local name="$1"
|
||||||
|
local steps="$2"
|
||||||
|
local description="${3:-}"
|
||||||
|
|
||||||
|
local id=$(echo "$name" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')
|
||||||
|
|
||||||
|
sqlite3 "$PROMPTS_DB" "
|
||||||
|
INSERT OR REPLACE INTO chains (id, name, description, steps)
|
||||||
|
VALUES ('$id', '$name', '$description', '$steps')
|
||||||
|
"
|
||||||
|
|
||||||
|
echo -e "${GREEN}Created chain: $id${RESET}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run chain
|
||||||
|
run_chain() {
|
||||||
|
local chain_id="$1"
|
||||||
|
local input="$2"
|
||||||
|
|
||||||
|
local chain=$(sqlite3 "$PROMPTS_DB" "SELECT steps FROM chains WHERE id = '$chain_id'")
|
||||||
|
|
||||||
|
if [ -z "$chain" ]; then
|
||||||
|
echo -e "${RED}Chain not found: $chain_id${RESET}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${PINK}=== RUNNING CHAIN: $chain_id ===${RESET}"
|
||||||
|
echo
|
||||||
|
|
||||||
|
local result="$input"
|
||||||
|
local step_num=0
|
||||||
|
|
||||||
|
for prompt_id in $(echo "$chain" | tr ',' '\n'); do
|
||||||
|
((step_num++))
|
||||||
|
echo -e "${BLUE}[Step $step_num: $prompt_id]${RESET}"
|
||||||
|
|
||||||
|
result=$(run "$prompt_id" "TEXT=$result" 2>/dev/null)
|
||||||
|
echo "$result"
|
||||||
|
echo
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Rate prompt
|
||||||
|
rate() {
|
||||||
|
local prompt_id="$1"
|
||||||
|
local rating="$2"
|
||||||
|
|
||||||
|
if [ "$rating" -lt 1 ] || [ "$rating" -gt 5 ]; then
|
||||||
|
echo "Rating must be 1-5"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
sqlite3 "$PROMPTS_DB" "UPDATE prompts SET rating = $rating WHERE id = '$prompt_id'"
|
||||||
|
echo -e "${GREEN}Rated $prompt_id: $rating/5${RESET}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Export prompts
|
||||||
|
export_prompts() {
|
||||||
|
local format="${1:-json}"
|
||||||
|
|
||||||
|
case "$format" in
|
||||||
|
json)
|
||||||
|
sqlite3 "$PROMPTS_DB" -json "SELECT * FROM prompts"
|
||||||
|
;;
|
||||||
|
markdown)
|
||||||
|
echo "# BlackRoad Prompt Library"
|
||||||
|
echo
|
||||||
|
sqlite3 "$PROMPTS_DB" "SELECT category, id, name, description, template FROM prompts ORDER BY category" | while IFS='|' read -r cat id name desc tmpl; do
|
||||||
|
echo "## $cat / $name ($id)"
|
||||||
|
echo "$desc"
|
||||||
|
echo '```'
|
||||||
|
echo "$tmpl"
|
||||||
|
echo '```'
|
||||||
|
echo
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Help
|
||||||
|
help() {
|
||||||
|
echo -e "${PINK}BlackRoad Prompt Library${RESET}"
|
||||||
|
echo
|
||||||
|
echo "Curated AI prompts for the cluster"
|
||||||
|
echo
|
||||||
|
echo "Commands:"
|
||||||
|
echo " list [category] List prompts"
|
||||||
|
echo " search <query> Search prompts"
|
||||||
|
echo " show <id> Show prompt details"
|
||||||
|
echo " use <id> [VAR=val...] Fill prompt template"
|
||||||
|
echo " run <id> [VAR=val...] Run prompt on LLM"
|
||||||
|
echo " add <name> <cat> <tmpl> Add custom prompt"
|
||||||
|
echo " personas List personas"
|
||||||
|
echo " chat <persona> Chat with persona"
|
||||||
|
echo " chain <name> <steps> Create prompt chain"
|
||||||
|
echo " run-chain <id> <input> Run prompt chain"
|
||||||
|
echo " rate <id> <1-5> Rate prompt"
|
||||||
|
echo " export [json|markdown] Export prompts"
|
||||||
|
echo
|
||||||
|
echo "Examples:"
|
||||||
|
echo " $0 list coding"
|
||||||
|
echo " $0 run summarize TEXT='Long text here'"
|
||||||
|
echo " $0 chat lucidia"
|
||||||
|
echo " $0 chain 'analyze' 'summarize,extract-keywords'"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ensure initialized
|
||||||
|
[ -f "$PROMPTS_DB" ] || init >/dev/null
|
||||||
|
|
||||||
|
case "${1:-help}" in
|
||||||
|
init)
|
||||||
|
init
|
||||||
|
;;
|
||||||
|
add)
|
||||||
|
add "$2" "$3" "$4" "$5" "$6" "$7"
|
||||||
|
;;
|
||||||
|
use|fill)
|
||||||
|
shift
|
||||||
|
use "$@"
|
||||||
|
;;
|
||||||
|
run|exec)
|
||||||
|
shift
|
||||||
|
run "$@"
|
||||||
|
;;
|
||||||
|
list|ls)
|
||||||
|
list "$2"
|
||||||
|
;;
|
||||||
|
search|find)
|
||||||
|
search "$2"
|
||||||
|
;;
|
||||||
|
show|info)
|
||||||
|
show "$2"
|
||||||
|
;;
|
||||||
|
personas)
|
||||||
|
personas
|
||||||
|
;;
|
||||||
|
chat)
|
||||||
|
chat_persona "$2"
|
||||||
|
;;
|
||||||
|
chain)
|
||||||
|
chain "$2" "$3" "$4"
|
||||||
|
;;
|
||||||
|
run-chain)
|
||||||
|
run_chain "$2" "$3"
|
||||||
|
;;
|
||||||
|
rate)
|
||||||
|
rate "$2" "$3"
|
||||||
|
;;
|
||||||
|
export)
|
||||||
|
export_prompts "$2"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
help
|
||||||
|
;;
|
||||||
|
esac
|
||||||
Reference in New Issue
Block a user