- frontend/.../terminal/core.ts: `useResilientTerminal` owns the xterm lifecycle (init, fit, debounced resize, reconnect, refit-on-visible) with a pluggable transport. Two connectors: `wsConnector` (agent terminal → container PTY over WS) and `nodeWebrtcConnector` (node terminal → host PTY, direct WebRTC DataChannel with WS-relay fallback, input buffered during the race). The agent terminal now gets the node terminal's robust reconnect for free; both share one xterm setup. - TerminalApp (agent) + NodeTerminalApp (node) reduced to thin wrappers over the core — net ~330 lines of duplicated transport/reconnect/xterm code removed. - scripts/deploy.sh: the deploys were manual, so the locally-built agent images (agent-base/browser/terminal — not in any registry) were never shipped and 404'd on provision. The script always (re)builds + loads them onto gw-04 AND every fleet node, with a skip-if-identical guard so unchanged images aren't re-transferred. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
80 lines
3.4 KiB
Bash
Executable File
80 lines
3.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Deploy ClawMates: build the server, frontend, node daemon, AND the agent runtime
|
|
# images on the build host (tank), then load + recreate on the gateway. The agent
|
|
# images (agent-base / agent-browser / agent-terminal) are locally-built dev images
|
|
# — not in any registry — so a `docker pull` can't fetch them. This script loads
|
|
# them onto the gateway AND every fleet node, so agent/terminal containers never
|
|
# 404 with "No such image" (the failure mode this script exists to prevent).
|
|
#
|
|
# Usage: scripts/deploy.sh # full deploy
|
|
# IMAGES_ONLY=1 scripts/deploy.sh # just (re)build + load the agent images
|
|
#
|
|
# Override hosts via env: BUILD_HOST, GW, NODES, TAG.
|
|
set -euo pipefail
|
|
|
|
BUILD_HOST=${BUILD_HOST:-osobh@tank} # builds the images + the linux daemon
|
|
GW=${GW:-gw-04} # the gateway (server + frontend + postgres)
|
|
NODES=${NODES:-"morpheus osobh@tank"} # fleet nodes that provision agent containers
|
|
TAG=${TAG:-latest}
|
|
AGENT_IMAGES=(agent-base agent-browser agent-terminal)
|
|
|
|
load() { ssh "$BUILD_HOST" "docker save $1" | ssh "$2" "docker load"; }
|
|
|
|
# Load only if the target lacks the exact image (skips re-transferring unchanged
|
|
# multi-hundred-MB agent images to every node on each code deploy).
|
|
load_if_changed() {
|
|
local lid rid
|
|
lid=$(ssh "$BUILD_HOST" "docker image inspect -f '{{.Id}}' $1 2>/dev/null" || true)
|
|
rid=$(ssh "$2" "docker image inspect -f '{{.Id}}' $1 2>/dev/null" || true)
|
|
if [ -n "$lid" ] && [ "$lid" = "$rid" ]; then
|
|
echo " (unchanged — skip)"
|
|
return 0
|
|
fi
|
|
load "$1" "$2"
|
|
}
|
|
|
|
echo "→ sync to $BUILD_HOST"
|
|
rsync -az --delete --exclude target/ --exclude node_modules/ --exclude .git/ \
|
|
--exclude '.next/' --exclude 'frontend/public/dl/' --exclude '**/.DS_Store' \
|
|
./ "$BUILD_HOST":~/clawmates/
|
|
|
|
if [ -z "${IMAGES_ONLY:-}" ]; then
|
|
echo "→ build server + frontend + daemon on $BUILD_HOST"
|
|
ssh "$BUILD_HOST" 'set -e; cd ~/clawmates
|
|
export PATH=$HOME/.cargo/bin:$PATH CARGO_NET_GIT_FETCH_WITH_CLI=true SQLX_OFFLINE=true
|
|
cargo build --release -p clawmates-node
|
|
cp target/release/clawmates-node frontend/public/dl/clawmates-node-linux-amd64
|
|
docker build -f images/server.Dockerfile -t clawmates/server:'"$TAG"' .
|
|
docker build -f images/frontend.Dockerfile -t clawmates/frontend:'"$TAG"' .'
|
|
fi
|
|
|
|
echo "→ build agent runtime images on $BUILD_HOST"
|
|
ssh "$BUILD_HOST" 'set -e; cd ~/clawmates
|
|
for i in '"${AGENT_IMAGES[*]}"'; do
|
|
docker build -f images/$i/Dockerfile -t clawmates/$i:dev images/$i/
|
|
done'
|
|
|
|
if [ -z "${IMAGES_ONLY:-}" ]; then
|
|
echo "→ load + recreate server + frontend on $GW"
|
|
ssh "$GW" "docker tag clawmates/server:$TAG clawmates/server:rollback 2>/dev/null || true
|
|
docker tag clawmates/frontend:$TAG clawmates/frontend:rollback 2>/dev/null || true"
|
|
load "clawmates/server:$TAG" "$GW"
|
|
load "clawmates/frontend:$TAG" "$GW"
|
|
fi
|
|
|
|
echo "→ load agent runtime images onto $GW + every fleet node"
|
|
for img in "${AGENT_IMAGES[@]}"; do
|
|
for host in "$GW" $NODES; do
|
|
printf ' %-26s → %s\n' "clawmates/$img:dev" "$host"
|
|
load_if_changed "clawmates/$img:dev" "$host"
|
|
done
|
|
done
|
|
|
|
if [ -z "${IMAGES_ONLY:-}" ]; then
|
|
echo "→ recreate server + frontend"
|
|
ssh "$GW" "cd /root/clawmates && docker-compose -p clawmates up -d --force-recreate server frontend"
|
|
sleep 6
|
|
curl -s -o /dev/null -w "edge HTTP %{http_code}\n" -m 10 https://clawmates.work/ || true
|
|
fi
|
|
echo "✓ deploy complete"
|