feat(release): 新增开箱启动脚本 setup.sh / start.sh(P4 第一步)

为 release 开箱即用提供入口,把首启向导串进启动流程。Python/Node 均
依赖系统已装运行时(不内置解释器),便携包只带源码 + venv 创建逻辑。

- _bootstrap.sh: 共享引导逻辑(被 source)
  - ensure_python_env: 系统 python 建/复用 .venv,装 requirements.lock.txt
  - ensure_node_env: 系统 node 装 easyagent 依赖 + 前端构建(缺失才装)
  - has_env_file: 首启判断
- setup.sh: 初始化入口 → 备好环境 → 跑 python -m scripts.setup 向导
- start.sh: 启动入口 → 备好环境 → 无 .env 自动跑向导 → python -m server.app
  (透传参数给 server.app,如 --thinking-mode)
- CLAUDE.md: Build & Run 增加开箱方式(./setup.sh / ./start.sh)与
  requirements.lock 说明

验证:bash -n 语法通过;_bootstrap 函数逻辑(ROOT 定位 / 选系统 python /
has_env_file / node_modules 已存在时跳过)实测正确;setup 向导在系统
Python 3.9 下端到端跑通(含写文件),确认 from __future__ annotations
使新式类型注解在 3.9 兼容。

注:实际「建 venv + 联网装依赖 + 解压验证」需在本机网络环境执行;
沙箱内仅做了不联网的逻辑校验。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
JOJO 2026-06-01 17:19:45 +08:00
parent 1d3703b0e5
commit 582f292114
4 changed files with 161 additions and 1 deletions

View File

@ -61,8 +61,18 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
### Build & Run ### Build & Run
```bash ```bash
# === 开箱即用release / 首次部署,推荐)===
# 首次初始化:建 venv、装依赖、跑配置向导模式/端口/管理员/密钥/模型)
./setup.sh
# 启动(首次无 .env 会自动跑向导,然后起服务)
./start.sh
# start.sh 透传参数给 server.app例如
./start.sh --thinking-mode
# === 手动方式(开发) ===
# 安装 Python 依赖 # 安装 Python 依赖
pip install -r requirements.txt pip install -r requirements.txt # 开发用,宽松
pip install -r requirements.lock.txt # 可复现/打包用,精确版本
# 构建终端镜像 # 构建终端镜像
docker build -f docker/terminal.Dockerfile -t my-agent-shell:latest . docker build -f docker/terminal.Dockerfile -t my-agent-shell:latest .

80
_bootstrap.sh Executable file
View File

@ -0,0 +1,80 @@
#!/usr/bin/env bash
# 共享引导逻辑:被 setup.sh / start.sh 引用source
# 负责定位项目根、准备 Python venv 与依赖、准备 Node 依赖。
# 不直接执行;由入口脚本 source 后调用其中的函数。
# 出错即停;管道任一环节失败也算失败。
set -euo pipefail
# 项目根目录 = 本脚本所在目录。
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
VENV_DIR="$ROOT/.venv"
VENV_PY="$VENV_DIR/bin/python"
# 选择系统 Python优先 python3回退 python。
_pick_system_python() {
if command -v python3 >/dev/null 2>&1; then
echo "python3"
elif command -v python >/dev/null 2>&1; then
echo "python"
else
echo ""
fi
}
# 准备虚拟环境与 Python 依赖(依赖系统已装 Python不内置解释器
# 已存在 venv 则复用;缺失则创建并安装 requirements.lock.txt优先或 requirements.txt。
ensure_python_env() {
if [ ! -x "$VENV_PY" ]; then
local sys_py
sys_py="$(_pick_system_python)"
if [ -z "$sys_py" ]; then
echo "[error] 未找到系统 Python需要 python3 或 python。请先安装 Python 3.9+。" >&2
return 1
fi
echo "[setup] 使用 $sys_py 创建虚拟环境:$VENV_DIR"
"$sys_py" -m venv "$VENV_DIR"
fi
echo "[setup] 升级 pip 并安装依赖..."
"$VENV_PY" -m pip install --upgrade pip >/dev/null
if [ -f "$ROOT/requirements.lock.txt" ]; then
"$VENV_PY" -m pip install -r "$ROOT/requirements.lock.txt"
elif [ -f "$ROOT/requirements.txt" ]; then
"$VENV_PY" -m pip install -r "$ROOT/requirements.txt"
else
echo "[error] 找不到 requirements.lock.txt 或 requirements.txt" >&2
return 1
fi
}
# 准备 Node 依赖(依赖系统已装 Node不内置 Node
# easyagent 仅需运行时依赖前端需要构建产物vite build
ensure_node_env() {
if ! command -v node >/dev/null 2>&1; then
echo "[warn] 未找到系统 Node。子智能体easyagent与前端构建将不可用。" >&2
echo " 如需完整功能,请安装 Node.js 18+ 后重跑。" >&2
return 0
fi
if ! command -v npm >/dev/null 2>&1; then
echo "[warn] 找到 node 但未找到 npm跳过 Node 依赖安装。" >&2
return 0
fi
# easyagent 运行时依赖
if [ -f "$ROOT/easyagent/package.json" ] && [ ! -d "$ROOT/easyagent/node_modules" ]; then
echo "[setup] 安装 easyagent 依赖npm ci..."
( cd "$ROOT/easyagent" && npm ci )
fi
# 前端构建产物static/dist 之类)。仅在缺失时构建,避免每次启动都跑。
if [ -f "$ROOT/package.json" ] && [ ! -d "$ROOT/node_modules" ]; then
echo "[setup] 安装前端依赖并构建npm ci && npm run build..."
( cd "$ROOT" && npm ci && npm run build )
fi
}
# .env 是否存在(首次启动判断依据)。
has_env_file() {
[ -f "$ROOT/.env" ]
}

28
setup.sh Executable file
View File

@ -0,0 +1,28 @@
#!/usr/bin/env bash
# 首次初始化入口:准备运行环境,然后运行交互式配置向导。
#
# 做的事:
# 1. 创建/复用 Python 虚拟环境并安装依赖
# 2. 准备 Node 依赖easyagent / 前端,依赖系统已装 Node
# 3. 运行 python -m scripts.setup 交互式向导,写出 .env 与模型配置
#
# 用法:
# ./setup.sh # 首次初始化(已存在 .env 时向导会提示备份后重配)
# ./setup.sh --force # 跳过『已存在 .env』确认仍会备份
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=_bootstrap.sh
source "$ROOT/_bootstrap.sh"
echo "========================================"
echo " AI Agent 初始化"
echo "========================================"
ensure_python_env
ensure_node_env
echo ""
echo "[setup] 启动配置向导..."
exec "$VENV_PY" -m scripts.setup "$@"

42
start.sh Executable file
View File

@ -0,0 +1,42 @@
#!/usr/bin/env bash
# 启动入口:准备运行环境(按需),首次运行自动跑配置向导,然后启动 Web 服务。
#
# 做的事:
# 1. 确保 Python venv 与依赖就绪(缺失才安装)
# 2. 确保 Node 依赖就绪(缺失才安装)
# 3. 若没有 .env首次启动自动运行配置向导
# 4. 启动 python -m server.app
#
# 端口/监听地址/模式等由 .env 决定(见 config/server.py、config/paths.py
# 透传的命令行参数会传给 server.app如 --port / --path / --thinking-mode
#
# 用法:
# ./start.sh # 正常启动(首次会自动初始化)
# ./start.sh --thinking-mode # 透传参数给 server.app
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=_bootstrap.sh
source "$ROOT/_bootstrap.sh"
# 1+2) 环境就绪(已存在则很快跳过)
ensure_python_env
ensure_node_env
# 3) 首次启动:没有 .env 则先跑向导
if ! has_env_file; then
echo ""
echo "[start] 未检测到 .env进入首次初始化向导..."
"$VENV_PY" -m scripts.setup
if ! has_env_file; then
echo "[start] 初始化未完成(未生成 .env已退出。" >&2
exit 1
fi
fi
# 4) 启动服务
echo ""
echo "[start] 启动 Web 服务..."
cd "$ROOT"
exec "$VENV_PY" -m server.app "$@"