release: bump version to 0.62.0
Some checks failed
ci / backend (push) Has been cancelled
ci / frontend (push) Has been cancelled
ci / delivery (push) Has been cancelled
release / images (push) Has been cancelled

This commit is contained in:
linkong
2026-05-21 01:37:32 +08:00
parent 5c65ee24d6
commit fbca381512
138 changed files with 21303 additions and 5721 deletions

212
planet.sh
View File

@@ -577,12 +577,16 @@ finish_wait_spinner() {
}
# Logging helpers
log_timestamp() {
date '+%Y-%m-%d %H:%M:%S'
}
log_line() {
local label="$1"
local color="$2"
local message="$3"
clear_wait_spinner
printf "${DIM}·${NC} ${color}%-4s${NC} ${WHITE}%s${NC}\n" "$label" "$message"
printf "${DIM}·${NC} ${color}%-4s${NC} ${WHITE}%s${NC} ${DIM}%s${NC}\n" "$label" "$message" "$(log_timestamp)"
resume_wait_session
}
@@ -1294,6 +1298,51 @@ ensure_uv_backend_deps() {
fi
}
ensure_python_runtime() {
ensure_local_runtime_bins_on_path
if ! command -v uv >/dev/null 2>&1; then
install_uv_if_needed
fi
cd "$SCRIPT_DIR"
set_wait_detail "安装 Python 3.14 运行时"
if ! run_with_retry \
"$DEPENDENCY_INSTALL_MAX_RETRIES" \
"$DEPENDENCY_INSTALL_RETRY_INTERVAL" \
"Python 3.14 运行时安装失败,已重试 ${DEPENDENCY_INSTALL_MAX_RETRIES}" \
"uv python install 3.14" \
uv python install 3.14; then
exit 1
fi
}
sync_python_deps() {
ensure_local_runtime_bins_on_path
if ! command -v uv >/dev/null 2>&1; then
install_uv_if_needed
fi
cd "$SCRIPT_DIR"
set_wait_detail "同步 Python 依赖"
if ! run_with_retry \
"$DEPENDENCY_INSTALL_MAX_RETRIES" \
"$DEPENDENCY_INSTALL_RETRY_INTERVAL" \
"uv 环境初始化失败,已重试 ${DEPENDENCY_INSTALL_MAX_RETRIES}" \
"uv sync" \
uv sync --group dev; then
exit 1
fi
if [ ! -x "$SCRIPT_DIR/.venv/bin/python" ]; then
log_error "uv 环境初始化失败,未找到 .venv/bin/python"
exit 1
fi
}
motion_agent_live_deps_ready() {
"$SCRIPT_DIR/.venv/bin/python" - <<'PY' >/dev/null 2>&1
import cv2 # noqa: F401
@@ -2841,6 +2890,161 @@ cleanup_failed_start() {
fi
}
ensure_env_file() {
local target_file="$1"
local example_file="$2"
local label="$3"
if [ -f "$target_file" ]; then
log_note "${label} 已存在,跳过"
return 0
fi
if [ ! -f "$example_file" ]; then
log_warn "${label} 模板不存在,跳过: ${example_file}"
return 0
fi
cp "$example_file" "$target_file"
chmod 600 "$target_file" 2>/dev/null || true
log_note "已创建 ${label}: ${target_file}"
}
ensure_planet_env_files() {
ensure_env_file "$SCRIPT_DIR/backend/.env" "$SCRIPT_DIR/backend/.env.example" "backend/.env"
ensure_env_file "$SCRIPT_DIR/aiprovider/.env" "$SCRIPT_DIR/aiprovider/.env.example" "aiprovider/.env"
ensure_env_file "$SCRIPT_DIR/frontend/.env.local" "$SCRIPT_DIR/frontend/.env.example" "frontend/.env.local"
}
sync_frontend_deps() {
set_wait_detail "解析前端运行时"
if ! resolve_frontend_runtime; then
install_bun_if_needed
if ! resolve_frontend_runtime; then
log_error "未找到 bun自动安装后仍无法解析运行时"
exit 1
fi
fi
cd "$SCRIPT_DIR/frontend"
set_wait_detail "同步前端依赖"
if ! run_with_retry \
"$DEPENDENCY_INSTALL_MAX_RETRIES" \
"$DEPENDENCY_INSTALL_RETRY_INTERVAL" \
"前端依赖安装失败,已重试 ${DEPENDENCY_INSTALL_MAX_RETRIES}" \
"bun install" \
"$FRONTEND_RUNTIME_BIN" install; then
exit 1
fi
}
initialize_backend_database() {
cd "$SCRIPT_DIR/backend"
PYTHONPATH="$SCRIPT_DIR/backend" "$SCRIPT_DIR/.venv/bin/python" - <<'PY'
import asyncio
from app.db.session import init_db
asyncio.run(init_db())
PY
}
planet_app_services_running() {
local backend_port=""
local frontend_port=""
local ai_provider_port=""
local motion_agent_port=""
backend_port="$(read_port_state_value BACKEND_PORT "$DEFAULT_BACKEND_PORT")"
frontend_port="$(read_port_state_value FRONTEND_PORT "$DEFAULT_FRONTEND_PORT")"
ai_provider_port="$(read_port_state_value AI_PROVIDER_PORT "$DEFAULT_AI_PROVIDER_PORT")"
motion_agent_port="$(read_port_state_value MOTION_AGENT_PORT "$DEFAULT_MOTION_AGENT_PORT")"
if http_ok "http://localhost:${backend_port}/health"; then
return 0
fi
if http_ok "http://localhost:${frontend_port}"; then
return 0
fi
if http_ok "http://localhost:${ai_provider_port}/health"; then
return 0
fi
if ! can_bind_port "$motion_agent_port"; then
return 0
fi
if pgrep -f "python.*-m motion_agent" >/dev/null 2>&1; then
return 0
fi
return 1
}
guard_init_when_services_running() {
if ! planet_app_services_running; then
return 0
fi
log_warn "检测到 Planet 应用服务正在运行,跳过初始化"
log_note "当前项目看起来已经完成初始化;重复 init 可能会打扰运行中的服务。"
log_note "如需重新初始化,请先执行 ./planet.sh stop再按需清理数据库卷或配置。"
log_note "查看当前状态: ./planet.sh health"
return 1
}
init() {
if ! guard_init_when_services_running; then
return 0
fi
print_splash
start_wait_session "准备 Python 运行时"
ensure_python_runtime
stop_wait_session
log_success "Python 运行时已就绪"
start_wait_session "同步 Python 依赖"
sync_python_deps
stop_wait_session
log_success "Python 依赖已就绪"
start_wait_session "同步前端依赖"
sync_frontend_deps
stop_wait_session
log_success "前端依赖已就绪"
log_step "检查环境变量文件"
ensure_planet_env_files
log_success "环境变量文件已就绪"
start_wait_session "启动数据库服务"
ensure_database_services_healthy
stop_wait_session
log_success "数据库服务已就绪"
start_wait_session "初始化数据库数据"
set_wait_detail "创建表并写入默认数据"
if ! run_command_with_spinner "初始化数据库数据" initialize_backend_database; then
stop_wait_session
log_error "数据库初始化失败"
exit 1
fi
stop_wait_session
log_success "初始化完成"
log_note "默认本地登录用户:"
log_note " admin / admin123"
log_note " linkong / 12345678"
log_note "下一步: ./planet.sh start"
}
create_user() {
local username
local password
@@ -3214,6 +3418,9 @@ parse_global_args "$@"
set -- "${GLOBAL_ARG_REMAINDER[@]}"
case "$1" in
init)
init
;;
start)
shift
start "$@"
@@ -3235,8 +3442,9 @@ case "$1" in
log "$2"
;;
*)
log_error "用法: ./planet.sh {start|stop|restart|createuser|health|log}"
log_error "用法: ./planet.sh {init|start|stop|restart|createuser|health|log}"
log_note "全局参数: -v, --verbose 在状态提示之间增量输出命令日志"
log_note "init 首次初始化空项目: 同步 uv/bun 依赖、生成缺失 env、启动数据库并写入默认数据"
log_note "start 启动服务,可选: -b <后端端口> -f <前端端口> -a <AI Provider 端口> -m/--motion-agent --motion-agent-port <端口> --motion-agent-camera-indexes 0,1 --motion-agent-camera-urls rtsp://... --motion-agent-dry-run --allow-lan --verbose"
log_note "stop 停止服务"
log_note "restart 重启服务,可选: -b [后端端口] -f [前端端口] -a [AI Provider 端口] -m [Motion Agent] -d --allow-lan --verbose"