#!/usr/bin/env bash # # deploy-gigafactory.sh — one-shot local deploy of the Agent Gigafactory # (platform-service fleet module) against the configured backend, then register # the ecosystem products so live /api/fleet/* calls return data. # # Prereqs: # - learning_ai_common_plat checked out as a sibling of this repo # - services/platform-service/.env filled (Cosmos endpoint/key, JWT_SECRET, ...) # e.g. populated from Azure: COSMOS_ENDPOINT/COSMOS_KEY/AZURE_BLOB_CONNECTION_STRING # - pnpm deps installed in common_plat; Node 18+ # # Usage: # ./deploy-gigafactory.sh # start service, wait for health, register products, smoke # ./deploy-gigafactory.sh --register-only # service already running on $PORT; just register products # ./deploy-gigafactory.sh --stop # stop a service started by this script # ./deploy-gigafactory.sh --no-register # start + health only, skip product registration # # Env overrides: # COMMON_PLAT path to learning_ai_common_plat (default: ../learning_ai_common_plat) # PORT platform-service port (default: 4003) # PRODUCTS space-separated "id|DisplayName|PREFIX" tuples (default: ecosystem set) set -euo pipefail HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" COMMON_PLAT="${COMMON_PLAT:-$(cd "$HERE/../../learning_ai_common_plat" 2>/dev/null && pwd || true)}" PORT="${PORT:-4003}" PS_DIR="$COMMON_PLAT/services/platform-service" ENV_FILE="$PS_DIR/.env" PID_FILE="$HERE/.gigafactory-platform-service.pid" LOG_FILE="${TMPDIR:-/tmp}/gigafactory-platform-service.log" BASE="http://localhost:$PORT" PRODUCTS="${PRODUCTS:-\ lysnrai|LysnrAI|LYS \ mindlyst|MindLyst|MIND \ chronomind|ChronoMind|CHR \ jarvisjr|JarvisJr|JAR \ nomgap|NomGap|NOM \ peakpulse|PeakPulse|PEAK \ flowmonk|FlowMonk|FLOW \ notelett|NoteLett|NOTE \ actiontrail|ActionTrail|ACT \ localmemgpt|LocalMemGPT|LMG \ efforise|EffoRise|EFF}" die() { echo "error: $*" >&2; exit 1; } stop_service() { if [ -f "$PID_FILE" ]; then local pid; pid="$(cat "$PID_FILE")" if kill -0 "$pid" 2>/dev/null; then kill "$pid" && echo "stopped platform-service (pid $pid)"; fi rm -f "$PID_FILE" else echo "no pid file; nothing started by this script" fi } mint_token() { node -e ' const c=require("crypto");const s=process.env.JWT_SECRET; if(!s){console.error("JWT_SECRET not set");process.exit(1);} const b=o=>Buffer.from(JSON.stringify(o)).toString("base64url"); const h=b({alg:"HS256",typ:"JWT"});const n=Math.floor(Date.now()/1e3); const p=b({sub:"gigafactory-deploy",email:"deploy@bytelyst.local",role:"admin",type:"access",iat:n,exp:n+3600}); console.log(`${h}.${p}.`+c.createHmac("sha256",s).update(`${h}.${p}`).digest("base64url")); ' } wait_for_health() { echo -n "waiting for $BASE/health " for _ in $(seq 1 60); do if curl -fsS "$BASE/health" >/dev/null 2>&1; then echo "— ok"; return 0; fi echo -n "."; sleep 1 done echo; die "platform-service did not become healthy (see $LOG_FILE)" } register_products() { local token; token="$(mint_token)" local created=0 existed=0 failed=0 for tuple in $PRODUCTS; do IFS='|' read -r id name prefix <<<"$tuple" local code; code="$(curl -s -o /dev/null -w '%{http_code}' -X POST "$BASE/api/products" \ -H "Authorization: Bearer $token" -H "content-type: application/json" \ -H "x-product-id: $id" \ -d "{\"productId\":\"$id\",\"displayName\":\"$name\",\"licensePrefix\":\"$prefix\"}")" case "$code" in 200|201) echo " created $id"; created=$((created+1));; 409) echo " exists $id"; existed=$((existed+1));; *) echo " FAILED $id (HTTP $code)"; failed=$((failed+1));; esac done echo "products: created=$created existed=$existed failed=$failed" # live smoke: fleet metrics for the first product local first; first="$(echo "$PRODUCTS" | awk '{print $1}' | cut -d'|' -f1)" echo -n "smoke GET /api/fleet/metrics ($first): " curl -s -H "Authorization: Bearer $(mint_token)" -H "x-product-id: $first" \ "$BASE/api/fleet/metrics" | head -c 200; echo } # ── main ───────────────────────────────────────────────────────── case "${1:-}" in --stop) stop_service; exit 0;; esac [ -n "$COMMON_PLAT" ] && [ -d "$PS_DIR" ] || die "platform-service not found (set COMMON_PLAT). Looked in: $PS_DIR" [ -f "$ENV_FILE" ] || die "$ENV_FILE missing — fill it (Cosmos endpoint/key, JWT_SECRET, blob CS)" set -a; . "$ENV_FILE"; set +a if [ "${1:-}" != "--register-only" ]; then if curl -fsS "$BASE/health" >/dev/null 2>&1; then echo "platform-service already healthy on :$PORT — reusing it" else echo "starting platform-service on :$PORT (log: $LOG_FILE)" ( cd "$PS_DIR" && pnpm exec tsx src/server.ts >"$LOG_FILE" 2>&1 ) & echo $! >"$PID_FILE" wait_for_health fi fi if [ "${1:-}" != "--no-register" ]; then register_products fi cat <