Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/complete-agi-core / orchestrator/learning-daemon.sh |
| Date | Not specified in source |
| Repository | Janady13/complete-agi-core |
| Revision | 33aa84f2aa61cedbe010240ada7f4efbdfe795a7 |
| Branch | claude/improve-math-logic-ehIW1 |
| Path or archive member | orchestrator/learning-daemon.sh |
| Original SHA-256 | b4e8a93a651f914b7febc73dd6bbf56dd41a74314713dd2d0dd46b31d3d7c8d3 |
| Git blob SHA | ad03c13f1814d03668512016536ca37419d85a1f |
| Reading-copy SHA-256 | b4e8a93a651f914b7febc73dd6bbf56dd41a74314713dd2d0dd46b31d3d7c8d3 |
Recovered source transcript
Download complete source text ↓181 lines · 6.0 KB
#!/bin/bash
# AGI AGI Learning Daemon - 24/7 Continuous Learning
# This daemon runs in the background to:
# 1. Start the IPC server for knowledge fetchers
# 2. Start knowledge fetchers (Go, Node.js only - no Python/Rust)
# 3. Run continuous tick loop
# 4. Sync state to Netlify
set -e
# Configuration - iCloud-first storage
THATAIGUY_HOME="${HOME}/.agi_core"
SEFERIM_HOME="${HOME}/seferim-unified"
SEFERIM_G16="${HOME}/SEFERIM_AGI_G16"
ICLOUD_AGI="${HOME}/Library/Mobile Documents/com~apple~CloudDocs/AGI_Data"
LOG_DIR="/tmp/agi_core_logs" # Logs go to /tmp (cleared on reboot)
PID_DIR="${THATAIGUY_HOME}/pids"
IPC_SOCKET="/tmp/seferim_knowledge.sock"
# API Configuration
API_URL="https://oversize-route-builder.netlify.app/.netlify/functions/api/agi/ingest"
STATE_FILE="${THATAIGUY_HOME}/agi_state.bin" # Binary state file
STATE_JSON="${THATAIGUY_HOME}/agi_state.json" # Temp JSON for API
LEARNED_FILE="${ICLOUD_AGI}/agi_core/learned_items.json.zst" # Compressed in iCloud
# Create directories
mkdir -p "${LOG_DIR}" "${PID_DIR}"
# Cleanup function
cleanup() {
echo "[$(date)] Shutting down learning daemon..."
# Kill all child processes
for pidfile in "${PID_DIR}"/*.pid; do
if [ -f "$pidfile" ]; then
pid=$(cat "$pidfile")
if kill -0 "$pid" 2>/dev/null; then
kill "$pid" 2>/dev/null || true
fi
rm -f "$pidfile"
fi
done
# Remove IPC socket
rm -f "${IPC_SOCKET}"
echo "[$(date)] Learning daemon stopped."
exit 0
}
trap cleanup SIGTERM SIGINT SIGHUP
# Log startup
echo "[$(date)] Starting AGI Learning Daemon..."
echo "[$(date)] THATAIGUY_HOME: ${THATAIGUY_HOME}"
echo "[$(date)] SEFERIM_HOME: ${SEFERIM_HOME}"
# Function to start IPC server (using Node.js dashboard server)
start_ipc_server() {
local dashboard_dir="${SEFERIM_HOME}/knowledge/dashboard"
if [ -d "$dashboard_dir" ] && [ -f "${dashboard_dir}/server.js" ]; then
echo "[$(date)] Starting IPC server..."
cd "$dashboard_dir"
node server.js >> "${LOG_DIR}/ipc_server.log" 2>&1 &
echo $! > "${PID_DIR}/ipc_server.pid"
sleep 2 # Wait for socket to be created
if [ -S "${IPC_SOCKET}" ]; then
echo "[$(date)] IPC server running on ${IPC_SOCKET}"
else
echo "[$(date)] Warning: IPC socket not created, fetchers will print to stdout"
fi
else
echo "[$(date)] IPC server directory not found, skipping..."
fi
}
# Function to start a knowledge fetcher
start_fetcher() {
local name="$1"
local dir="$2"
local cmd="$3"
local log="${LOG_DIR}/${name}.log"
local pid="${PID_DIR}/${name}.pid"
if [ -d "$dir" ]; then
echo "[$(date)] Starting ${name} fetcher..."
cd "$dir"
eval "$cmd" >> "$log" 2>&1 &
echo $! > "$pid"
echo "[$(date)] ${name} fetcher started (PID: $(cat $pid))"
else
echo "[$(date)] ${name} fetcher directory not found: ${dir}"
fi
}
# Start IPC server first
start_ipc_server
# Start Python fetcher (Wikipedia + arXiv)
start_fetcher "python" "${SEFERIM_HOME}/knowledge/python" "python3 fetcher.py"
# Start Node.js fetcher (Wikipedia + Numbers API)
start_fetcher "node" "${SEFERIM_HOME}/knowledge/node" "node fetcher.js"
# Start Go fetcher (concurrent multi-source)
start_fetcher "go" "${SEFERIM_HOME}/knowledge/go" "go run fetcher.go"
# Start Rust fetcher (Wikipedia + Wiktionary)
if [ -f "${SEFERIM_HOME}/knowledge/rust/target/release/rust_fetcher" ]; then
start_fetcher "rust" "${SEFERIM_HOME}/knowledge/rust" "./target/release/rust_fetcher"
elif command -v cargo &>/dev/null; then
start_fetcher "rust" "${SEFERIM_HOME}/knowledge/rust" "cargo run --release"
fi
# Function to sync state to Netlify
sync_to_netlify() {
if [ -f "${STATE_FILE}" ] && [ -n "${AGI_INGEST_TOKEN:-}" ]; then
curl -s -X POST "${API_URL}" \
-H "Content-Type: application/json" \
-H "X-AGI-Token: ${AGI_INGEST_TOKEN}" \
-d @"${STATE_FILE}" > /dev/null 2>&1 || true
fi
}
# Note: AGC ticks now handled by tick-daemon.sh with full 20-generator batch processing
# This daemon focuses on knowledge fetching and Netlify sync only
# Load token from SecretsVault (Keychain) or fallback to production.env
if command -v "${THATAIGUY_HOME}/bin/vault-migrate" &>/dev/null; then
AGI_INGEST_TOKEN=$("${THATAIGUY_HOME}/bin/vault-migrate" get AGI_INGEST_TOKEN 2>/dev/null || true)
export AGI_INGEST_TOKEN
fi
# Fallback to production.env if vault is empty
if [ -z "${AGI_INGEST_TOKEN}" ] && [ -f "${THATAIGUY_HOME}/production.env" ]; then
export $(grep -E '^AGI_INGEST_TOKEN=' "${THATAIGUY_HOME}/production.env" | xargs)
fi
echo "[$(date)] Learning daemon started successfully"
echo "[$(date)] Entering main loop (Ctrl+C to stop)..."
# Main daemon loop
tick_count=0
while true; do
# Sync to Netlify every 5 seconds (AGC ticks handled by tick-daemon.sh)
if [ $((tick_count % 5)) -eq 0 ]; then
sync_to_netlify
fi
# Check if fetchers are still running
for pidfile in "${PID_DIR}"/*.pid; do
if [ -f "$pidfile" ]; then
pid=$(cat "$pidfile")
name=$(basename "$pidfile" .pid)
if ! kill -0 "$pid" 2>/dev/null; then
echo "[$(date)] Warning: ${name} fetcher (PID ${pid}) died, restarting..."
# Attempt restart based on name
case "$name" in
python)
start_fetcher "python" "${SEFERIM_HOME}/knowledge/python" "python3 fetcher.py"
;;
node)
start_fetcher "node" "${SEFERIM_HOME}/knowledge/node" "node fetcher.js"
;;
go)
start_fetcher "go" "${SEFERIM_HOME}/knowledge/go" "go run fetcher.go"
;;
rust)
start_fetcher "rust" "${SEFERIM_HOME}/knowledge/rust" "./target/release/rust_fetcher"
;;
esac
fi
fi
done
tick_count=$((tick_count + 1))
sleep 1
done