Files
bench/start.sh
T

91 lines
2.8 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
# Start the task manager: wire the project, sort out the port, serve the board.
#
# ./.task-manager/start.sh # foreground; Ctrl-C stops the board
# ./.task-manager/start.sh --no-open # extra args pass through to board.py
#
# Port logic (BOARD_PORT from env, else manager/.env, else 26071):
# - our own board already answering there -> just open the browser
# - port free -> start on it
# - something else squatting on it -> take the next free port AND
# persist it to manager/.env, so the hooks and agents (which read the same
# file) follow the board to its new port instead of reporting into the void.
set -euo pipefail
TM="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MANAGER="$TM/manager"
CORE="$MANAGER/core"
ENV_FILE="$MANAGER/local/.env"
port="${BOARD_PORT:-}"
if [ -z "$port" ] && [ -f "$ENV_FILE" ]; then
port="$(sed -n 's/^[[:space:]]*BOARD_PORT[[:space:]]*=[[:space:]]*//p' "$ENV_FILE" | tail -1 | tr -d "'\"")"
fi
port="${port:-26071}"
# Idempotent project wiring; a project without .claude/ still gets the board.
python3 "$TM/install.py" || true
echo
is_free() {
python3 - "$1" <<'PY'
import socket, sys
s = socket.socket()
try:
s.bind(("127.0.0.1", int(sys.argv[1])))
except OSError:
sys.exit(1)
finally:
s.close()
PY
}
is_our_board() {
python3 -c '
import json, sys, urllib.request
try:
with urllib.request.urlopen("http://127.0.0.1:%s/api/state" % sys.argv[1], timeout=2) as r:
data = json.load(r)
except Exception:
sys.exit(1)
sys.exit(0 if data.get("board", {}).get("root") == sys.argv[2] else 1)
' "$1" "$TM/tasks"
}
if is_our_board "$port"; then
echo "Board already running at http://127.0.0.1:$port/ — opening it."
python3 -m webbrowser -t "http://127.0.0.1:$port/" >/dev/null
exit 0
fi
if ! is_free "$port"; then
original=$port
for offset in $(seq 1 20); do
candidate=$((original + offset))
if is_free "$candidate"; then port=$candidate; break; fi
done
if [ "$port" = "$original" ]; then
echo "error: ports $original-$((original + 20)) all busy — set BOARD_PORT yourself." >&2
exit 1
fi
echo "Port $original is taken by something else — using $port instead."
echo "Persisting BOARD_PORT=$port to manager/.env so hooks and agents follow."
python3 - "$ENV_FILE" "$port" <<'PY'
import pathlib, sys
path, port = pathlib.Path(sys.argv[1]), sys.argv[2]
lines = path.read_text(encoding="utf-8").splitlines() if path.exists() else []
out, replaced = [], False
for line in lines:
if line.strip().startswith("BOARD_PORT"):
out.append(f"BOARD_PORT={port}")
replaced = True
else:
out.append(line)
if not replaced:
out.append(f"BOARD_PORT={port}")
path.write_text("\n".join(out) + "\n", encoding="utf-8")
PY
fi
exec python3 "$CORE/board.py" --port "$port" "$@"