feat: initial public release (MAESTRO v0.1.0)
Open-source release of MAESTRO, an agent orchestration platform that runs LLM-driven tasks through sandboxed tools, with a web UI. Apache-2.0. See README.md and docs/ (getting-started, configuration, architecture).
This commit is contained in:
Executable
+162
@@ -0,0 +1,162 @@
|
||||
#!/usr/bin/env bash
|
||||
# Launch AAO in gateway mode (OpenAI-compatible LLM gateway, no UI).
|
||||
#
|
||||
# This is a sibling of scripts/server.sh (worker mode). Both can run
|
||||
# concurrently on the same host because:
|
||||
# - PID file: .gateway.pid (worker uses .server.pid)
|
||||
# - Log file: logs/gateway.log (worker uses logs/server.log)
|
||||
# - Listen port: $GATEWAY_PORT (default 4000)、worker は $PORT (default 9876)
|
||||
# - DB: 同じ data/aao.db を SQLite WAL mode で共有
|
||||
# (gateway は gateway_virtual_keys + gateway_key_usage の 2 table のみ touch)
|
||||
#
|
||||
# Usage:
|
||||
# scripts/gateway.sh start
|
||||
# scripts/gateway.sh stop
|
||||
# scripts/gateway.sh restart
|
||||
# scripts/gateway.sh status
|
||||
# scripts/gateway.sh logs
|
||||
#
|
||||
# Env override:
|
||||
# GATEWAY_PORT=4000 # gateway.listen_port を上書き (config.yaml より優先)
|
||||
# AAO_CONFIG=/etc/aao/config-gateway.yaml # 専用 config を使う場合
|
||||
# AAO_GATEWAY_NO_DB=1 # ステートレス起動 (virtual_keys は config 経由のみ、budget/rate-limit 無効)
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
PID_FILE="$PROJECT_DIR/.gateway.pid"
|
||||
LOG_FILE="$PROJECT_DIR/logs/gateway.log"
|
||||
GATEWAY_PORT="${GATEWAY_PORT:-4000}"
|
||||
|
||||
cd "$PROJECT_DIR"
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 {start|stop|restart|status|logs}"
|
||||
echo
|
||||
echo "Env:"
|
||||
echo " GATEWAY_PORT=$GATEWAY_PORT"
|
||||
echo " AAO_CONFIG=${AAO_CONFIG:-<repo config.yaml>}"
|
||||
echo " AAO_GATEWAY_NO_DB=${AAO_GATEWAY_NO_DB:-<unset, DB enabled>}"
|
||||
exit 1
|
||||
}
|
||||
|
||||
is_running() {
|
||||
if [[ -f "$PID_FILE" ]]; then
|
||||
local pid
|
||||
pid=$(cat "$PID_FILE")
|
||||
if kill -0 "$pid" 2>/dev/null; then
|
||||
return 0
|
||||
fi
|
||||
rm -f "$PID_FILE"
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
do_start() {
|
||||
if is_running; then
|
||||
echo "Gateway already running (PID $(cat "$PID_FILE"))"
|
||||
return 0
|
||||
fi
|
||||
|
||||
mkdir -p "$(dirname "$LOG_FILE")"
|
||||
|
||||
echo "Checking runtime dependencies..."
|
||||
"$SCRIPT_DIR/prepare.sh"
|
||||
|
||||
echo "Building..."
|
||||
npm run build --silent 2>&1 | tail -1
|
||||
|
||||
echo "Starting gateway on port $GATEWAY_PORT..."
|
||||
# AAO_MODE=gateway は src/main.ts の switch を gateway/bootstrap に向ける
|
||||
# GATEWAY_PORT は src/gateway/config.ts が config.yaml の listen_port を
|
||||
# env で上書きするためのキー (実装側で env > config の precedence)。
|
||||
AAO_MODE=gateway \
|
||||
GATEWAY_PORT="$GATEWAY_PORT" \
|
||||
${AAO_CONFIG:+AAO_CONFIG="$AAO_CONFIG"} \
|
||||
${AAO_GATEWAY_NO_DB:+AAO_GATEWAY_NO_DB="$AAO_GATEWAY_NO_DB"} \
|
||||
nohup node dist/main.js >> "$LOG_FILE" 2>&1 &
|
||||
local pid=$!
|
||||
echo "$pid" > "$PID_FILE"
|
||||
|
||||
# Wait briefly and verify it started
|
||||
sleep 2
|
||||
if kill -0 "$pid" 2>/dev/null; then
|
||||
echo "Gateway started (PID $pid, log: $LOG_FILE)"
|
||||
echo " Health: curl http://localhost:$GATEWAY_PORT/health/liveness"
|
||||
echo " Metrics: curl http://localhost:$GATEWAY_PORT/metrics"
|
||||
else
|
||||
rm -f "$PID_FILE"
|
||||
echo "Gateway failed to start. Last 20 log lines:"
|
||||
tail -20 "$LOG_FILE"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
do_stop() {
|
||||
if ! is_running; then
|
||||
echo "Gateway not running"
|
||||
# Also kill any stray process on the port
|
||||
local stray
|
||||
stray=$(lsof -ti:"$GATEWAY_PORT" 2>/dev/null || true)
|
||||
if [[ -n "$stray" ]]; then
|
||||
echo "Found stray process on port $GATEWAY_PORT (PID $stray), killing..."
|
||||
kill "$stray" 2>/dev/null || true
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
local pid
|
||||
pid=$(cat "$PID_FILE")
|
||||
echo "Stopping gateway (PID $pid)..."
|
||||
# SIGTERM で graceful shutdown (gateway.shutdown_graceful_sec で SSE drain)
|
||||
kill "$pid" 2>/dev/null || true
|
||||
|
||||
# Wait for graceful shutdown — gateway drain may take up to ~30s by default
|
||||
for i in {1..60}; do
|
||||
if ! kill -0 "$pid" 2>/dev/null; then
|
||||
rm -f "$PID_FILE"
|
||||
echo "Gateway stopped (graceful)"
|
||||
return 0
|
||||
fi
|
||||
sleep 0.5
|
||||
done
|
||||
|
||||
# Force kill
|
||||
echo "Graceful shutdown timed out; force killing..."
|
||||
kill -9 "$pid" 2>/dev/null || true
|
||||
rm -f "$PID_FILE"
|
||||
echo "Gateway stopped (forced)"
|
||||
}
|
||||
|
||||
do_status() {
|
||||
if is_running; then
|
||||
local pid
|
||||
pid=$(cat "$PID_FILE")
|
||||
echo "Gateway running (PID $pid, port $GATEWAY_PORT)"
|
||||
# Probe liveness for confirmation
|
||||
if curl -sS -o /dev/null -w "%{http_code}" "http://localhost:$GATEWAY_PORT/health/liveness" 2>/dev/null | grep -q 200; then
|
||||
echo " Liveness: OK"
|
||||
else
|
||||
echo " Liveness: NOT OK (process up but endpoint not responding)"
|
||||
fi
|
||||
else
|
||||
echo "Gateway not running"
|
||||
fi
|
||||
}
|
||||
|
||||
do_logs() {
|
||||
if [[ -f "$LOG_FILE" ]]; then
|
||||
tail -f "$LOG_FILE"
|
||||
else
|
||||
echo "No log file found at $LOG_FILE"
|
||||
fi
|
||||
}
|
||||
|
||||
case "${1:-}" in
|
||||
start) do_start ;;
|
||||
stop) do_stop ;;
|
||||
restart) do_stop; do_start ;;
|
||||
status) do_status ;;
|
||||
logs) do_logs ;;
|
||||
*) usage ;;
|
||||
esac
|
||||
Reference in New Issue
Block a user