Skip to content

Commit 8a9bbb2

Browse files
profbernardojDavidAJohnston
authored andcommitted
feat: v0.9.5 — always-on proxy-router with launchd auto-restart
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
1 parent d1edef2 commit 8a9bbb2

4 files changed

Lines changed: 92 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ SmartAgent
9090
├── Everclaw (decentralized inference)
9191
│ ├── Morpheus API Gateway (open access, cloud)
9292
│ ├── Morpheus P2P Proxy (local, staked MOR)
93+
│ ├── Always-On Proxy-Router (launchd KeepAlive, auto-restart)
9394
│ ├── Gateway Guardian v4 (billing-aware self-healing watchdog)
9495
│ └── Smart Session Archiver (prevents dashboard overload)
9596
└── SmartAgent Config

docs/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ <h2>Under the Hood</h2>
515515
├── <span class="hl3">Everclaw</span> <span style="color: var(--text-muted);">(decentralized inference)</span>
516516
│ ├── Morpheus API Gateway <span style="color: var(--text-muted);">— open access, cloud</span>
517517
│ ├── Morpheus P2P Proxy <span style="color: var(--text-muted);">— local, staked MOR</span>
518+
│ ├── Always-On Router <span style="color: var(--text-muted);">— launchd KeepAlive, auto-restart</span>
518519
│ ├── Gateway Guardian v4 <span style="color: var(--text-muted);">— billing-aware self-healing watchdog</span>
519520
│ └── Session Archiver <span style="color: var(--text-muted);">— prevents dashboard overload</span>
520521
└── <span class="hl">SmartAgent Config</span>

scripts/mor-launch-headless.sh

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#!/bin/bash
2+
# mor-launch-headless.sh — launchd-compatible Morpheus proxy-router launcher
3+
#
4+
# Retrieves wallet private key from 1Password at runtime via macOS Keychain.
5+
# Designed to run under launchd KeepAlive — runs in foreground via exec.
6+
#
7+
# If 1Password is not configured, falls back to macOS Keychain (everclaw-wallet).
8+
#
9+
# Usage: Called by com.morpheus.router launchd plist (not manually)
10+
11+
MORPHEUS_DIR="$(cd "$(dirname "$0")" && pwd)"
12+
cd "$MORPHEUS_DIR"
13+
14+
# Source .env for ETH_NODE_ADDRESS and other config
15+
if [[ -f .env ]]; then
16+
set -a
17+
source .env
18+
set +a
19+
fi
20+
21+
# --- Key retrieval: try 1Password first, then macOS Keychain ---
22+
WALLET_KEY=""
23+
24+
# Method 1: 1Password service account
25+
OP_TOKEN=$(security find-generic-password -a "bernardo-agent" -s "op-service-account-token" -w 2>/dev/null || true)
26+
if [[ -n "$OP_TOKEN" ]]; then
27+
export OP_SERVICE_ACCOUNT_TOKEN="$OP_TOKEN"
28+
WALLET_KEY=$(op item get "Base Session Key" --vault "Bernardo Agent Vault" --fields "Private Key" --reveal 2>/dev/null || true)
29+
fi
30+
31+
# Method 2: macOS Keychain (everclaw-wallet.mjs stores keys here)
32+
if [[ -z "$WALLET_KEY" ]]; then
33+
WALLET_KEY=$(security find-generic-password -s "everclaw-wallet" -w 2>/dev/null || true)
34+
fi
35+
36+
if [[ -z "$WALLET_KEY" ]]; then
37+
echo "$(date -u +%Y-%m-%dT%H:%M:%S) FATAL: Cannot retrieve wallet key from 1Password or Keychain" >&2
38+
exit 1
39+
fi
40+
41+
export WALLET_PRIVATE_KEY="$WALLET_KEY"
42+
export ETH_NODE_ADDRESS="${ETH_NODE_ADDRESS:-https://base-mainnet.public.blastapi.io}"
43+
44+
# Ensure log directory exists
45+
mkdir -p "$MORPHEUS_DIR/data/logs"
46+
47+
echo "$(date -u +%Y-%m-%dT%H:%M:%S) Starting proxy-router (headless, launchd-managed)"
48+
49+
# Run in foreground so launchd can track the process
50+
exec ./proxy-router
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>Label</key>
6+
<string>com.morpheus.router</string>
7+
8+
<key>ProgramArguments</key>
9+
<array>
10+
<string>/bin/bash</string>
11+
<string>__MORPHEUS_DIR__/mor-launch-headless.sh</string>
12+
</array>
13+
14+
<key>WorkingDirectory</key>
15+
<string>__MORPHEUS_DIR__</string>
16+
17+
<key>KeepAlive</key>
18+
<true/>
19+
20+
<key>RunAtLoad</key>
21+
<true/>
22+
23+
<key>ThrottleInterval</key>
24+
<integer>30</integer>
25+
26+
<key>StandardOutPath</key>
27+
<string>__MORPHEUS_DIR__/data/logs/router-stdout.log</string>
28+
29+
<key>StandardErrorPath</key>
30+
<string>__MORPHEUS_DIR__/data/logs/router-stderr.log</string>
31+
32+
<key>EnvironmentVariables</key>
33+
<dict>
34+
<key>PATH</key>
35+
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
36+
<key>HOME</key>
37+
<string>__HOME__</string>
38+
</dict>
39+
</dict>
40+
</plist>

0 commit comments

Comments
 (0)