Files
blackroad/scripts/blackroad-agent-registry.sh
Alexa Amundson 78fbe80f2a Initial monorepo — everything BlackRoad in one place
bin/       230 CLI tools (ask-*, br-*, agent-*, roadid, carpool)
scripts/   99 automation scripts
fleet/     Node configs and deployment
workers/   Cloudflare Worker sources (roadpay, road-search, squad webhooks)
roadc/     RoadC programming language
roadnet/   Mesh network (5 APs, WireGuard)
operator/  Memory system scripts
config/    System configs
dotfiles/  Shell configs
docs/      Documentation

BlackRoad OS — Pave Tomorrow.

RoadChain-SHA2048: d1a24f55318d338b
RoadChain-Identity: alexa@sovereign
RoadChain-Full: d1a24f55318d338b24b60bad7be39286379c76ae5470817482100cb0ddbbcb97e147d07ac7243da0a9f0363e4e5c833d612b9c0df3a3cd20802465420278ef74875a5b77f55af6fe42a931b8b635b3d0d0b6bde9abf33dc42eea52bc03c951406d8cbe49f1a3d29b26a94dade05e9477f34a7d4d4c6ec4005c3c2ac54e73a68440c512c8e83fd9b1fe234750b898ef8f4032c23db173961fe225e67a0432b5293a9714f76c5c57ed5fdf35b9fb40fd73c03ebf88b7253c6a0575f5afb6a6b49b3bda310602fb1ef676859962dad2aebbb2875814b30eee0a8ba195e482d4cbc91d8819e7f38f6db53e8063401649c77bb994371473cabfb917fb53e8cbe73d60
2026-03-14 17:08:41 -05:00

303 lines
12 KiB
Bash
Executable File

#!/usr/bin/env bash
# BlackRoad Agent Registry CLI
# Manage and query all BlackRoad agents (hardware + AI)
set -eo pipefail
# Source centralized config
source "$HOME/.blackroad/config/nodes.sh" 2>/dev/null || true
# Source SHA-2048 identity bridge
source ~/roadchain-identity.sh 2>/dev/null || true
# Dependency check
command -v sqlite3 &>/dev/null || { echo "ERROR: sqlite3 required" >&2; exit 1; }
# SQL-safe string escaping
_sql_escape() { echo "$1" | sed "s/'/''/g"; }
# Colors (use config or fallback)
NC="${RESET:-\033[0m}"
# Database
REGISTRY_DB="${HOME}/.blackroad-agent-registry.db"
# Initialize database
init_db() {
sqlite3 "$REGISTRY_DB" <<EOF
CREATE TABLE IF NOT EXISTS agents (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT UNIQUE NOT NULL,
type TEXT NOT NULL, -- hardware, ai, human
platform TEXT, -- raspberry_pi, claude, grok, etc.
ip_local TEXT,
ip_tailscale TEXT,
role TEXT,
status TEXT DEFAULT 'active',
sha2048_fingerprint TEXT,
sha2048_short TEXT,
provider TEXT DEFAULT '',
last_seen DATETIME,
metadata TEXT, -- JSON for extra data
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS agent_services (
id INTEGER PRIMARY KEY AUTOINCREMENT,
agent_id INTEGER,
service_name TEXT,
port INTEGER,
status TEXT DEFAULT 'running',
FOREIGN KEY (agent_id) REFERENCES agents(id)
);
CREATE TABLE IF NOT EXISTS agent_capabilities (
id INTEGER PRIMARY KEY AUTOINCREMENT,
agent_id INTEGER,
capability TEXT,
FOREIGN KEY (agent_id) REFERENCES agents(id)
);
EOF
# Ensure columns exist if table was created before they were added
sqlite3 "$REGISTRY_DB" "ALTER TABLE agents ADD COLUMN sha2048_fingerprint TEXT;" 2>/dev/null || true
sqlite3 "$REGISTRY_DB" "ALTER TABLE agents ADD COLUMN sha2048_short TEXT;" 2>/dev/null || true
sqlite3 "$REGISTRY_DB" "ALTER TABLE agents ADD COLUMN provider TEXT DEFAULT '';" 2>/dev/null || true
echo -e "${GREEN}Database initialized at ${REGISTRY_DB}${NC}"
}
# Register an agent
register() {
local name="$1"
local type="$2"
local platform="${3:-unknown}"
local ip="${4:-}"
local role="${5:-general}"
if [[ -z "$name" || -z "$type" ]]; then
echo -e "${RED}Usage: $0 register <name> <type> [platform] [ip] [role]${NC}"
echo "Types: hardware, ai, human"
return 1
fi
# Compute SHA-2048 identity
local sha2048="" sha2048_short="" provider_val=""
if type sha2048_compute &>/dev/null; then
sha2048=$(sha2048_compute "${name}-${type}-${platform}")
sha2048_short="${sha2048:0:16}"
fi
provider_val="${platform:-unknown}"
sqlite3 "$REGISTRY_DB" "INSERT OR REPLACE INTO agents (name, type, platform, ip_local, role, sha2048_fingerprint, sha2048_short, provider, last_seen, updated_at)
VALUES ('$name', '$type', '$platform', '$ip', '$role', '$sha2048', '$sha2048_short', '$provider_val', datetime('now'), datetime('now'));"
echo -e "${GREEN}Registered agent: ${WHITE}$name${NC}"
echo -e " Type: $type"
echo -e " Platform: $platform"
echo -e " IP: $ip"
echo -e " Role: $role"
echo -e " SHA-2048: ${sha2048_short:-computing...} (2048-bit)"
}
# List all agents
list_agents() {
echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}"
echo -e "${CYAN}║ 🖤🛣️ BLACKROAD AGENT REGISTRY 🖤🛣️ ║${NC}"
echo -e "${CYAN}╚════════════════════════════════════════════════════════════╝${NC}"
echo
echo -e "${WHITE}=== HARDWARE AGENTS ===${NC}"
sqlite3 -column -header "$REGISTRY_DB" "SELECT name, platform, ip_local, role, status FROM agents WHERE type='hardware' ORDER BY name;"
echo
echo -e "${WHITE}=== AI AGENTS ===${NC}"
sqlite3 -column -header "$REGISTRY_DB" "SELECT name, platform, role, sha2048_short as identity, status FROM agents WHERE type='ai' ORDER BY name;"
echo
echo -e "${WHITE}=== HUMAN AGENTS ===${NC}"
sqlite3 -column -header "$REGISTRY_DB" "SELECT name, role, status FROM agents WHERE type='human' ORDER BY name;"
}
# Show agent details
show() {
local name="$1"
if [[ -z "$name" ]]; then
echo -e "${RED}Usage: $0 show <agent-name>${NC}"
return 1
fi
echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}"
echo -e "${CYAN}║ AGENT: ${WHITE}${name}${CYAN}${NC}"
echo -e "${CYAN}╚════════════════════════════════════════════════════════════╝${NC}"
sqlite3 -line "$REGISTRY_DB" "SELECT * FROM agents WHERE name='$name';"
}
# Ping hardware agents
ping_all() {
echo -e "${CYAN}Pinging all hardware agents...${NC}"
echo
local agents=$(sqlite3 "$REGISTRY_DB" "SELECT name, ip_local FROM agents WHERE type='hardware' AND ip_local IS NOT NULL AND ip_local != '';")
while IFS='|' read -r name ip; do
if [[ -n "$ip" ]]; then
echo -n -e " ${WHITE}$name${NC} ($ip): "
if ping -c 1 -W 1 "$ip" &>/dev/null; then
echo -e "${GREEN}ONLINE${NC}"
sqlite3 "$REGISTRY_DB" "UPDATE agents SET status='active', last_seen=datetime('now') WHERE name='$name';"
else
echo -e "${RED}OFFLINE${NC}"
sqlite3 "$REGISTRY_DB" "UPDATE agents SET status='offline' WHERE name='$name';"
fi
fi
done <<< "$agents"
}
# SSH into agent
connect() {
local name="$1"
if [[ -z "$name" ]]; then
echo -e "${RED}Usage: $0 connect <agent-name>${NC}"
return 1
fi
local ip=$(sqlite3 "$REGISTRY_DB" "SELECT ip_local FROM agents WHERE name='$name' AND type='hardware';")
if [[ -n "$ip" ]]; then
echo -e "${GREEN}Connecting to ${WHITE}$name${GREEN} at ${ip}...${NC}"
ssh "pi@$ip"
else
echo -e "${RED}Agent not found or not a hardware agent: $name${NC}"
return 1
fi
}
# Show statistics
stats() {
echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}"
echo -e "${CYAN}║ 📊 AGENT REGISTRY STATISTICS 📊 ║${NC}"
echo -e "${CYAN}╚════════════════════════════════════════════════════════════╝${NC}"
echo
local total=$(sqlite3 "$REGISTRY_DB" "SELECT COUNT(*) FROM agents;")
local hardware=$(sqlite3 "$REGISTRY_DB" "SELECT COUNT(*) FROM agents WHERE type='hardware';")
local ai=$(sqlite3 "$REGISTRY_DB" "SELECT COUNT(*) FROM agents WHERE type='ai';")
local human=$(sqlite3 "$REGISTRY_DB" "SELECT COUNT(*) FROM agents WHERE type='human';")
local active=$(sqlite3 "$REGISTRY_DB" "SELECT COUNT(*) FROM agents WHERE status='active';")
echo -e "${WHITE}Total Agents:${NC} $total"
echo -e "${WHITE}Hardware:${NC} $hardware"
echo -e "${WHITE}AI:${NC} $ai"
echo -e "${WHITE}Human:${NC} $human"
echo -e "${GREEN}Active:${NC} $active"
}
# Seed initial data
seed() {
echo -e "${CYAN}Seeding BlackRoad agent registry...${NC}"
# Human
register "Alexandria" "human" "human_in_the_loop" "" "founder_ceo"
# AI Agents
register "Cecilia" "ai" "claude" "" "primary_ai_partner"
register "Cadence" "ai" "chatgpt" "" "creative_ai"
register "Silas" "ai" "grok" "" "analyst_ai"
register "Gematria" "ai" "gemini" "" "research_ai"
# Hardware Agents
register "Alice" "hardware" "raspberry_pi_5" "192.168.4.49" "gateway"
register "Aria" "hardware" "raspberry_pi_5" "192.168.4.64" "api_services"
register "Octavia" "hardware" "raspberry_pi_5" "192.168.4.74" "ai_inference"
register "Olympia" "hardware" "raspberry_pi_5" "" "ai_inference_secondary"
register "Lucidia" "hardware" "raspberry_pi_4b" "192.168.4.38" "legacy_services"
register "Anastasia" "hardware" "raspberry_pi_400" "" "development"
register "Shellfish" "hardware" "digitalocean" "174.138.44.45" "cloud_infrastructure"
echo
echo -e "${GREEN}Registry seeded with 11 agents!${NC}"
}
# Export to JSON
export_json() {
echo -e "${CYAN}Exporting registry to JSON...${NC}"
sqlite3 -json "$REGISTRY_DB" "SELECT * FROM agents;" > "${HOME}/blackroad-agents.json"
echo -e "${GREEN}Exported to ~/blackroad-agents.json${NC}"
}
# Help
show_help() {
echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}"
echo -e "${CYAN}║ 🖤🛣️ BLACKROAD AGENT REGISTRY CLI 🖤🛣️ ║${NC}"
echo -e "${CYAN}╚════════════════════════════════════════════════════════════╝${NC}"
echo
echo -e "${WHITE}Usage:${NC} $0 <command> [args]"
echo
echo -e "${WHITE}Commands:${NC}"
echo -e " ${GREEN}init${NC} Initialize the database"
echo -e " ${GREEN}seed${NC} Seed with BlackRoad agents"
echo -e " ${GREEN}register${NC} <n> <t> [p] [i] [r] Register new agent"
echo -e " ${GREEN}list${NC} List all agents"
echo -e " ${GREEN}show${NC} <name> Show agent details"
echo -e " ${GREEN}ping${NC} Ping all hardware agents"
echo -e " ${GREEN}connect${NC} <name> SSH into hardware agent"
echo -e " ${GREEN}stats${NC} Show statistics"
echo -e " ${GREEN}export${NC} Export to JSON"
echo -e " ${GREEN}help${NC} Show this help"
echo
echo -e "${WHITE}Agent Types:${NC} hardware, ai, human"
echo
echo -e "${WHITE}Examples:${NC}"
echo -e " $0 init && $0 seed # First time setup"
echo -e " $0 list # Show all agents"
echo -e " $0 connect alice # SSH to Alice"
echo -e " $0 ping # Check which agents are online"
}
# Show identity for an agent
show_identity() {
local name="$1"
if [[ -z "$name" ]]; then
echo -e "${RED}Usage: $0 identity <agent-name>${NC}"
return 1
fi
local sha2048=$(sqlite3 "$REGISTRY_DB" "SELECT sha2048_fingerprint FROM agents WHERE name='$name';")
local sha2048_short=$(sqlite3 "$REGISTRY_DB" "SELECT sha2048_short FROM agents WHERE name='$name';")
local provider=$(sqlite3 "$REGISTRY_DB" "SELECT provider FROM agents WHERE name='$name';")
if [[ -z "$sha2048" ]]; then
echo -e "${YELLOW}No SHA-2048 identity for $name. Computing...${NC}"
if type sha2048_compute &>/dev/null; then
sha2048=$(sha2048_compute "${name}")
sha2048_short="${sha2048:0:16}"
sqlite3 "$REGISTRY_DB" "UPDATE agents SET sha2048_fingerprint='$sha2048', sha2048_short='$sha2048_short' WHERE name='$name';"
echo -e "${GREEN}SHA-2048 computed and stored.${NC}"
fi
fi
if type identity_banner &>/dev/null && [[ -n "$sha2048" ]]; then
identity_banner "$name" "$sha2048" "${provider:-sovereign}"
else
echo -e "${WHITE}Agent:${NC} $name"
echo -e "${CYAN}SHA-2048:${NC} $sha2048_short"
echo -e "${CYAN}Provider:${NC} ${provider:-unknown}"
fi
}
# Main
case "${1:-help}" in
init) init_db ;;
seed) seed ;;
register) register "$2" "$3" "$4" "$5" "$6" ;;
list) list_agents ;;
show) show "$2" ;;
identity) show_identity "$2" ;;
ping) ping_all ;;
connect) connect "$2" ;;
stats) stats ;;
export) export_json ;;
help|*) show_help ;;
esac