diff --git a/scripts/start-webui.sh b/scripts/start-webui.sh new file mode 100755 index 0000000..f011acf --- /dev/null +++ b/scripts/start-webui.sh @@ -0,0 +1,108 @@ +#!/usr/bin/env bash +set -euo pipefail + +# 一键启动本地 WebUI: +# - 后端 FastAPI: 127.0.0.1:8765 +# - 前端 Next.js: 127.0.0.1:3000 +# - PID 和日志统一写入 .port_sessions,重复执行会清理上一次由本脚本启动的进程。 + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +RUN_DIR="${ROOT_DIR}/.port_sessions" +BACKEND_HOST="${CLAW_BACKEND_HOST:-127.0.0.1}" +BACKEND_PORT="${CLAW_BACKEND_PORT:-8765}" +FRONTEND_HOST="${CLAW_FRONTEND_HOST:-127.0.0.1}" +FRONTEND_PORT="${CLAW_FRONTEND_PORT:-3000}" +BACKEND_URL="http://${BACKEND_HOST}:${BACKEND_PORT}" +FRONTEND_URL="http://${FRONTEND_HOST}:${FRONTEND_PORT}" + +mkdir -p "${RUN_DIR}" + +stop_pid_file() { + local pid_file="$1" + local name="$2" + if [[ ! -f "${pid_file}" ]]; then + return + fi + local pid + pid="$(cat "${pid_file}" 2>/dev/null || true)" + if [[ -n "${pid}" ]] && kill -0 "${pid}" 2>/dev/null; then + echo "Stopping previous ${name} (${pid})..." + kill "${pid}" 2>/dev/null || true + for _ in {1..20}; do + if ! kill -0 "${pid}" 2>/dev/null; then + break + fi + sleep 0.1 + done + if kill -0 "${pid}" 2>/dev/null; then + kill -9 "${pid}" 2>/dev/null || true + fi + fi + rm -f "${pid_file}" +} + +wait_for_url() { + local url="$1" + local name="$2" + local log_file="$3" + for _ in {1..80}; do + if curl -fsS "${url}" >/dev/null 2>&1; then + echo "${name} ready: ${url}" + return 0 + fi + sleep 0.25 + done + echo "${name} did not become ready: ${url}" >&2 + echo "---- ${name} log tail ----" >&2 + tail -80 "${log_file}" >&2 || true + return 1 +} + +stop_pid_file "${RUN_DIR}/webui-frontend.pid" "frontend" +stop_pid_file "${RUN_DIR}/webui-backend.pid" "backend" + +export OPENAI_API_KEY="${OPENAI_API_KEY:-sk-Jxoh5lf1jWg6HQZYYyfyagXudGxUXNAgkZklxMnnXHn7pFmU}" +export OPENAI_BASE_URL="${OPENAI_BASE_URL:-http://model.mify.ai.srv/v1}" +export OPENAI_MODEL="${OPENAI_MODEL:-xiaomi/mimo-v2-flash}" + +BACKEND_LOG="${RUN_DIR}/webui-backend.log" +FRONTEND_LOG="${RUN_DIR}/webui-frontend.log" + +echo "Starting backend on ${BACKEND_URL}..." +( + cd "${ROOT_DIR}" + exec python3 -m src.gui \ + --host "${BACKEND_HOST}" \ + --port "${BACKEND_PORT}" \ + --cwd "${ROOT_DIR}" \ + --session-dir "${RUN_DIR}/agent" \ + --allow-write \ + --allow-shell \ + --no-browser +) >"${BACKEND_LOG}" 2>&1 & +echo "$!" >"${RUN_DIR}/webui-backend.pid" + +wait_for_url "${BACKEND_URL}/api/state" "backend" "${BACKEND_LOG}" + +echo "Starting frontend on ${FRONTEND_URL}..." +( + cd "${ROOT_DIR}/frontend/app" + export CLAW_API_URL="${BACKEND_URL}" + exec npm run dev -- --hostname "${FRONTEND_HOST}" --port "${FRONTEND_PORT}" +) >"${FRONTEND_LOG}" 2>&1 & +echo "$!" >"${RUN_DIR}/webui-frontend.pid" + +wait_for_url "${FRONTEND_URL}" "frontend" "${FRONTEND_LOG}" + +cat <