From 582f292114c00422e0a5b6b9687b0f1d90aab4a3 Mon Sep 17 00:00:00 2001 From: JOJO <1498581755@qq.com> Date: Mon, 1 Jun 2026 17:19:45 +0800 Subject: [PATCH] =?UTF-8?q?feat(release):=20=E6=96=B0=E5=A2=9E=E5=BC=80?= =?UTF-8?q?=E7=AE=B1=E5=90=AF=E5=8A=A8=E8=84=9A=E6=9C=AC=20setup.sh=20/=20?= =?UTF-8?q?start.sh=EF=BC=88P4=20=E7=AC=AC=E4=B8=80=E6=AD=A5=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 为 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) --- CLAUDE.md | 12 +++++++- _bootstrap.sh | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++ setup.sh | 28 ++++++++++++++++++ start.sh | 42 +++++++++++++++++++++++++++ 4 files changed, 161 insertions(+), 1 deletion(-) create mode 100755 _bootstrap.sh create mode 100755 setup.sh create mode 100755 start.sh diff --git a/CLAUDE.md b/CLAUDE.md index f22dd81..ffc1da8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -61,8 +61,18 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ### Build & Run ```bash +# === 开箱即用(release / 首次部署,推荐)=== +# 首次初始化:建 venv、装依赖、跑配置向导(模式/端口/管理员/密钥/模型) +./setup.sh +# 启动(首次无 .env 会自动跑向导,然后起服务) +./start.sh +# start.sh 透传参数给 server.app,例如: +./start.sh --thinking-mode + +# === 手动方式(开发) === # 安装 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 . diff --git a/_bootstrap.sh b/_bootstrap.sh new file mode 100755 index 0000000..0b155b5 --- /dev/null +++ b/_bootstrap.sh @@ -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" ] +} diff --git a/setup.sh b/setup.sh new file mode 100755 index 0000000..8eac6fe --- /dev/null +++ b/setup.sh @@ -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 "$@" diff --git a/start.sh b/start.sh new file mode 100755 index 0000000..f09b4c1 --- /dev/null +++ b/start.sh @@ -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 "$@"