diff --git a/README.md b/README.md index 2577ce3..44acf0c 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,7 @@ SmartAgent ├── Everclaw (decentralized inference) │ ├── Morpheus API Gateway (open access, cloud) │ ├── Morpheus P2P Proxy (local, staked MOR) +│ ├── Always-On Proxy-Router (launchd KeepAlive, auto-restart) │ ├── Gateway Guardian v4 (billing-aware self-healing watchdog) │ └── Smart Session Archiver (prevents dashboard overload) └── SmartAgent Config diff --git a/docs/index.html b/docs/index.html index 9901b40..f30a861 100644 --- a/docs/index.html +++ b/docs/index.html @@ -515,6 +515,7 @@

Under the Hood

├── Everclaw (decentralized inference) │ ├── Morpheus API Gateway — open access, cloud │ ├── Morpheus P2P Proxy — local, staked MOR +│ ├── Always-On Router — launchd KeepAlive, auto-restart │ ├── Gateway Guardian v4 — billing-aware self-healing watchdog │ └── Session Archiver — prevents dashboard overload └── SmartAgent Config diff --git a/scripts/mor-launch-headless.sh b/scripts/mor-launch-headless.sh new file mode 100755 index 0000000..0b276c3 --- /dev/null +++ b/scripts/mor-launch-headless.sh @@ -0,0 +1,50 @@ +#!/bin/bash +# mor-launch-headless.sh — launchd-compatible Morpheus proxy-router launcher +# +# Retrieves wallet private key from 1Password at runtime via macOS Keychain. +# Designed to run under launchd KeepAlive — runs in foreground via exec. +# +# If 1Password is not configured, falls back to macOS Keychain (everclaw-wallet). +# +# Usage: Called by com.morpheus.router launchd plist (not manually) + +MORPHEUS_DIR="$(cd "$(dirname "$0")" && pwd)" +cd "$MORPHEUS_DIR" + +# Source .env for ETH_NODE_ADDRESS and other config +if [[ -f .env ]]; then + set -a + source .env + set +a +fi + +# --- Key retrieval: try 1Password first, then macOS Keychain --- +WALLET_KEY="" + +# Method 1: 1Password service account +OP_TOKEN=$(security find-generic-password -a "bernardo-agent" -s "op-service-account-token" -w 2>/dev/null || true) +if [[ -n "$OP_TOKEN" ]]; then + export OP_SERVICE_ACCOUNT_TOKEN="$OP_TOKEN" + WALLET_KEY=$(op item get "Base Session Key" --vault "Bernardo Agent Vault" --fields "Private Key" --reveal 2>/dev/null || true) +fi + +# Method 2: macOS Keychain (everclaw-wallet.mjs stores keys here) +if [[ -z "$WALLET_KEY" ]]; then + WALLET_KEY=$(security find-generic-password -s "everclaw-wallet" -w 2>/dev/null || true) +fi + +if [[ -z "$WALLET_KEY" ]]; then + echo "$(date -u +%Y-%m-%dT%H:%M:%S) FATAL: Cannot retrieve wallet key from 1Password or Keychain" >&2 + exit 1 +fi + +export WALLET_PRIVATE_KEY="$WALLET_KEY" +export ETH_NODE_ADDRESS="${ETH_NODE_ADDRESS:-https://base-mainnet.public.blastapi.io}" + +# Ensure log directory exists +mkdir -p "$MORPHEUS_DIR/data/logs" + +echo "$(date -u +%Y-%m-%dT%H:%M:%S) Starting proxy-router (headless, launchd-managed)" + +# Run in foreground so launchd can track the process +exec ./proxy-router diff --git a/templates/com.morpheus.router.plist b/templates/com.morpheus.router.plist new file mode 100644 index 0000000..b51e392 --- /dev/null +++ b/templates/com.morpheus.router.plist @@ -0,0 +1,40 @@ + + + + + Label + com.morpheus.router + + ProgramArguments + + /bin/bash + __MORPHEUS_DIR__/mor-launch-headless.sh + + + WorkingDirectory + __MORPHEUS_DIR__ + + KeepAlive + + + RunAtLoad + + + ThrottleInterval + 30 + + StandardOutPath + __MORPHEUS_DIR__/data/logs/router-stdout.log + + StandardErrorPath + __MORPHEUS_DIR__/data/logs/router-stderr.log + + EnvironmentVariables + + PATH + /opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin + HOME + __HOME__ + + +