From 781da768e03ca35eb18539c6749d0d1ca0b07958 Mon Sep 17 00:00:00 2001 From: Bernardo Johnston Date: Sat, 14 Feb 2026 20:02:31 -0600 Subject: [PATCH] =?UTF-8?q?feat:=20v0.9.5=20=E2=80=94=20always-on=20proxy-?= =?UTF-8?q?router=20with=20launchd=20auto-restart?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause of Morpheus fallback failure: the proxy-router (Go binary, port 8082) had no launchd KeepAlive service. When it died, the JS proxy (8083) couldn't open blockchain sessions → 502 errors → OpenClaw cooldown → agent offline whenever Venice DIEM exhausted. New files: - scripts/mor-launch-headless.sh: launchd-compatible router launcher with 1Password key injection (falls back to macOS Keychain) - templates/com.morpheus.router.plist: KeepAlive launchd service Updated: - README.md: added Always-On Router to architecture diagram - docs/index.html: added Always-On Router to website architecture --- README.md | 1 + docs/index.html | 1 + scripts/mor-launch-headless.sh | 50 +++++++++++++++++++++++++++++ templates/com.morpheus.router.plist | 40 +++++++++++++++++++++++ 4 files changed, 92 insertions(+) create mode 100755 scripts/mor-launch-headless.sh create mode 100644 templates/com.morpheus.router.plist 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__ + + +