This commit is contained in:
雷雨
2025-12-15 22:05:56 +08:00
commit 8635b84b2d
230 changed files with 53888 additions and 0 deletions

View File

@@ -0,0 +1,391 @@
#!/bin/bash
# 智能家居代理系统启动脚本 (Linux/macOS)
# Smart Home Agent System Startup Script (Linux/macOS)
#
# 架构设计:
# - 环境检查模块:统一检查所有运行环境
# - 配置管理模块:集中处理配置文件读取
# - 服务管理模块:统一启动/停止服务
# - 工具函数模块:提供可复用的通用功能
# ========================================
# 初始化设置
# ========================================
set -e # 遇到错误立即退出
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
GRAY='\033[0;90m'
NC='\033[0m'
# 全局变量
declare -A CONFIG
declare -a PIDS
PROJECT_ROOT=""
# ========================================
# 工具函数模块
# ========================================
print_section() {
echo
echo -e "${CYAN}========================================${NC}"
echo -e "${CYAN}$1${NC}"
echo -e "${CYAN}========================================${NC}"
echo
}
print_step() {
echo -e "${YELLOW}$1${NC}"
echo -e "${YELLOW}$2${NC}"
echo
}
print_success() {
echo -e "${GREEN}$1${NC}"
}
print_error() {
echo -e "${RED}$1${NC}"
}
print_info() {
echo -e "${GRAY} $1${NC}"
}
# ========================================
# 环境检查模块 - 统一检查所有必要的运行环境
# ========================================
check_command() {
local cmd=$1
local name=$2
local hint=$3
if ! command -v "$cmd" &> /dev/null; then
print_error "错误: 未找到 $name"
print_error "Error: $name not found"
echo -e "${YELLOW} $hint${NC}"
return 1
fi
local version=$("$cmd" --version 2>&1 | head -1)
print_success "$name: $version"
return 0
}
check_environment() {
print_step "检查运行环境..." "Checking runtime environment..."
local all_passed=1
check_command "python3" "Python" "请安装 Python 3.8+ / Please install Python 3.8+" || all_passed=0
check_command "node" "Node.js" "请安装 Node.js 16+ / Please install Node.js 16+" || all_passed=0
check_command "pnpm" "pnpm" "请运行: npm install -g pnpm" || all_passed=0
check_command "uv" "uv" "请运行: pip install uv 或访问 https://docs.astral.sh/uv/" || all_passed=0
echo
if [ $all_passed -eq 0 ]; then
exit 1
fi
}
# ========================================
# 项目定位模块 - 自动定位项目根目录
# ========================================
find_project_root() {
print_step "定位项目根目录..." "Locating project root directory..."
local paths=("." ".." "../..")
for path in "${paths[@]}"; do
if [ -f "$path/config.yaml" ]; then
cd "$path" || exit 1
PROJECT_ROOT=$(pwd)
print_success "配置文件已找到: $PROJECT_ROOT"
print_success "Configuration file found: $PROJECT_ROOT"
return 0
fi
done
print_error "错误: 未找到配置文件 config.yaml"
print_error "Error: Configuration file config.yaml not found"
print_error "当前目录: $PWD"
exit 1
}
# ========================================
# 配置管理模块 - 集中处理配置读取和默认值
# ========================================
read_yaml_port() {
local pattern=$1
local default=$2
local port=$(grep -E "$pattern" config.yaml | head -1 | sed 's/.*port: *\([0-9]*\).*/\1/')
echo "${port:-$default}"
}
initialize_config() {
print_step "读取配置文件..." "Reading configuration file..."
# 定义配置映射pattern|key|default
local configs=(
"backend:.*python:.*port:|BackendPort|3000"
"frontend:.*dev_server:.*port:|FrontendPort|1420"
"conductor:.*port:|ConductorPort|12000"
"air_conditioner:.*port:|AirCondPort|12001"
"air_cleaner:.*port:|AirCleanPort|12002"
"bedside_lamp:.*port:|BedsideLampPort|12004"
)
for config_line in "${configs[@]}"; do
IFS='|' read -r pattern key default <<< "$config_line"
CONFIG[$key]=$(read_yaml_port "$pattern" "$default")
done
print_success "配置读取完成"
print_info "后端端口 / Backend Port: ${CONFIG[BackendPort]}"
print_info "前端端口 / Frontend Port: ${CONFIG[FrontendPort]}"
print_info "Conductor端口: ${CONFIG[ConductorPort]}"
echo
}
# ========================================
# 目录准备模块 - 创建必要的目录
# ========================================
initialize_directories() {
mkdir -p logs temp
}
# ========================================
# 环境准备模块 - Python虚拟环境和依赖
# ========================================
initialize_python_environment() {
print_step "检查 Python 虚拟环境..." "Checking Python virtual environment..."
if [ ! -d ".venv" ]; then
print_error "虚拟环境不存在,正在创建..."
print_error "Virtual environment not found, creating..."
print_info "执行: uv venv"
uv venv
if [ $? -ne 0 ]; then
print_error "虚拟环境创建失败!"
print_error "Virtual environment creation failed!"
exit 1
fi
print_success "虚拟环境创建完成"
else
print_success "虚拟环境已存在"
fi
echo
print_step "安装 Python 依赖..." "Installing Python dependencies..."
print_info "执行: uv sync"
uv sync
if [ $? -ne 0 ]; then
print_error "Python 依赖安装失败!"
print_error "Python dependencies installation failed!"
exit 1
fi
print_success "Python 依赖已安装"
}
initialize_frontend_dependencies() {
print_step "检查前端依赖..." "Checking frontend dependencies..."
if [ ! -d "app/node_modules" ]; then
print_error "前端依赖未安装,正在安装..."
print_error "Frontend dependencies not installed, installing..."
echo
cd app || exit 1
print_info "执行: pnpm install"
pnpm install
if [ $? -ne 0 ]; then
cd ..
print_error "依赖安装失败!"
print_error "Dependency installation failed!"
exit 1
fi
cd ..
print_success "依赖安装完成"
else
print_success "前端依赖已安装"
fi
echo
}
# ========================================
# 服务启动模块 - 统一管理所有服务启动
# ========================================
start_service() {
local index=$1
local name_cn=$2
local name_en=$3
local directory=$4
local command=$5
local port_key=$6
local delay=$7
local port=${CONFIG[$port_key]}
echo -e "${CYAN}[$index/6] 启动$name_cn (端口 $port)...${NC}"
echo -e "${CYAN}[$index/6] Starting $name_en (Port $port)...${NC}"
cd "$PROJECT_ROOT/$directory" || exit 1
# 启动服务并重定向输出到日志
eval "$command" >> "$PROJECT_ROOT/logs/${name_en// /_}.log" 2>&1 &
local pid=$!
PIDS+=($pid)
cd "$PROJECT_ROOT" || exit 1
sleep "$delay"
print_success "$name_cn 已启动"
print_success "$name_en started"
echo
}
start_all_services() {
print_section "正在启动 Moss AI 本地开发环境...
Starting Moss AI Local Development Environment..."
# 定义服务配置index|name_cn|name_en|directory|command|port_key|delay
local services=(
"1|后端服务|Backend Service|app/backend-python|uv run .|BackendPort|3"
"2|总管理代理|Conductor Agent|agents/conductor_agent|uv run .|ConductorPort|3"
"3|空调代理|Air Conditioner Agent|agents/air_conditioner_agent|uv run .|AirCondPort|2"
"4|空气净化器|Air Cleaner Agent|agents/air_cleaner_agent|uv run .|AirCleanPort|2"
"5|床头灯代理|Bedside Lamp Agent|agents/bedside_lamp_agent|uv run .|BedsideLampPort|2"
"6|前端开发服务器|Frontend Dev Server|app|pnpm dev|FrontendPort|3"
)
for service_config in "${services[@]}"; do
IFS='|' read -r idx name_cn name_en dir cmd port_key delay <<< "$service_config"
start_service "$idx" "$name_cn" "$name_en" "$dir" "$cmd" "$port_key" "$delay"
done
print_info "所有服务窗口正在后台运行"
print_info "All services are running in background"
echo
}
# ========================================
# 信息显示模块 - 显示服务地址和使用说明
# ========================================
show_service_info() {
print_section "所有服务已启动完成!
All services started successfully!"
echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}"
echo -e "${CYAN}║ 服务地址 / Service URLs ║${NC}"
echo -e "${CYAN}╠════════════════════════════════════════════════════════════╣${NC}"
echo -e "${CYAN}║ ║${NC}"
echo -e "${CYAN}║ 【前端应用 / Frontend】 ║${NC}"
echo -e "${YELLOW}║ http://localhost:${CONFIG[FrontendPort]}${NC}"
echo -e "${CYAN}║ ★ 请在浏览器中打开此地址使用应用 ║${NC}"
echo -e "${CYAN}║ ║${NC}"
echo -e "${CYAN}║ 【后端服务 / Backend】 ║${NC}"
echo -e "${NC}║ http://localhost:${CONFIG[BackendPort]}${NC}"
echo -e "${CYAN}║ ║${NC}"
echo -e "${CYAN}║ 【智能代理 / Agents】 ║${NC}"
echo -e "${NC}║ 总管理代理 / Conductor: http://localhost:${CONFIG[ConductorPort]}${NC}"
echo -e "${NC}║ 空调代理 / Air Conditioner: http://localhost:${CONFIG[AirCondPort]}${NC}"
echo -e "${NC}║ 空气净化器 / Air Cleaner: http://localhost:${CONFIG[AirCleanPort]}${NC}"
echo -e "${NC}║ 床头灯 / Bedside Lamp: http://localhost:${CONFIG[BedsideLampPort]}${NC}"
echo -e "${CYAN}║ ║${NC}"
echo -e "${CYAN}╚════════════════════════════════════════════════════════════╝${NC}"
echo
}
# ========================================
# 服务停止模块 - 统一停止所有服务
# ========================================
stop_all_services() {
echo
print_step "正在停止所有服务..." "Stopping all services..."
# 停止所有启动的进程
for pid in "${PIDS[@]}"; do
if kill -0 "$pid" 2>/dev/null; then
print_info "停止进程 PID: $pid"
kill "$pid" 2>/dev/null || true
fi
done
# 停止端口占用的进程
local ports=(
"${CONFIG[FrontendPort]}"
"${CONFIG[BackendPort]}"
"${CONFIG[ConductorPort]}"
"${CONFIG[AirCondPort]}"
"${CONFIG[AirCleanPort]}"
"${CONFIG[BedsideLampPort]}"
)
for port in "${ports[@]}"; do
# Linux
if command -v lsof &> /dev/null; then
local pid=$(lsof -ti:"$port" 2>/dev/null || true)
if [ -n "$pid" ]; then
print_info "停止端口 $port 的进程 (PID: $pid)"
kill "$pid" 2>/dev/null || true
fi
# macOS alternative
elif command -v netstat &> /dev/null; then
local pid=$(netstat -vanp tcp 2>/dev/null | grep "\.$port " | awk '{print $9}' | head -1)
if [ -n "$pid" ]; then
print_info "停止端口 $port 的进程 (PID: $pid)"
kill "$pid" 2>/dev/null || true
fi
fi
done
print_success "所有服务已停止"
print_success "All services stopped"
}
# ========================================
# 信号处理 - 捕获 Ctrl+C 等中断信号
# ========================================
cleanup() {
stop_all_services
exit 0
}
trap cleanup SIGINT SIGTERM
# ========================================
# 主流程
# ========================================
main() {
clear
print_section "智能家居代理系统启动脚本
Smart Home Agent System Startup Script"
check_environment
find_project_root
initialize_config
initialize_directories
initialize_python_environment
initialize_frontend_dependencies
start_all_services
show_service_info
echo -e "${YELLOW}提示:按 Ctrl+C 停止所有服务并退出${NC}"
echo -e "${YELLOW}Note: Press Ctrl+C to stop all services and exit${NC}"
echo
# 等待用户中断
wait
}
# 运行主程序
main