调整 workflow 执行逻辑:每个 action 完成后统一进入 LLM/规则审核,审核开始/结果可播报,审核阻断时自动暂停并给出建议 增强 chat 交互:支持执行中 Ctrl+C 中断并保存 checkpoint,后续可 resume 继续 增加运行时热更新能力:支持 set KEY=VALUE 和 load params <路径> 同步更新当前 state、config.txt 和 checkpoint 支持自定义 action 审核提示词:新增 --llm-action-analysis-prompt-file / PAM_LLM_ACTION_ANALYSIS_PROMPT_FILE 新增 prompts/action_review.txt,落地保存当前默认审核提示词,便于后续按基线调整 更新 Linux 打包脚本,将 prompts/action_review.txt 一并带入发布包 同步更新 README、流程图、todo 和打包文档,修正 --analyze-actions 语义说明与 chat 最新行为说明
212 lines
7.5 KiB
Bash
212 lines
7.5 KiB
Bash
#!/usr/bin/env bash
|
||
# 构建 Linux 解压即用包:包含 Python 运行时、依赖、CLI 可执行程序和脚本文档。
|
||
|
||
set -euo pipefail
|
||
|
||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||
cd "$ROOT_DIR"
|
||
|
||
PYTHON_BIN="${PYTHON_BIN:-python3}"
|
||
APP_NAME="pam-deploy-agent"
|
||
RELEASE_NAME="${APP_NAME}-linux-x86_64"
|
||
PACKAGE_EXTRAS="${PACKAGE_EXTRAS:-mcp,chat}"
|
||
BUILD_DIR="${BUILD_DIR:-$ROOT_DIR/build/linux_self_contained}"
|
||
DIST_DIR="${DIST_DIR:-$ROOT_DIR/dist/linux_self_contained}"
|
||
RELEASE_DIR="$DIST_DIR/$RELEASE_NAME"
|
||
ARCHIVE_PATH="$DIST_DIR/${RELEASE_NAME}.tar.gz"
|
||
|
||
if [[ "$(uname -s)" != "Linux" ]]; then
|
||
echo "该脚本需要在 Linux x86_64 构建机上运行。"
|
||
exit 1
|
||
fi
|
||
|
||
if ! command -v "$PYTHON_BIN" >/dev/null 2>&1; then
|
||
echo "未找到 Python: $PYTHON_BIN"
|
||
exit 1
|
||
fi
|
||
|
||
echo "==> 清理旧构建目录"
|
||
rm -rf "$BUILD_DIR" "$RELEASE_DIR" "$ARCHIVE_PATH"
|
||
mkdir -p "$BUILD_DIR" "$DIST_DIR"
|
||
|
||
echo "==> 创建构建虚拟环境"
|
||
"$PYTHON_BIN" -m venv "$BUILD_DIR/venv"
|
||
source "$BUILD_DIR/venv/bin/activate"
|
||
|
||
echo "==> 安装构建依赖"
|
||
python -m pip install --upgrade pip setuptools wheel
|
||
python -m pip install pyinstaller
|
||
|
||
echo "==> 安装项目依赖"
|
||
if [[ -n "$PACKAGE_EXTRAS" ]]; then
|
||
python -m pip install -e ".[${PACKAGE_EXTRAS}]"
|
||
else
|
||
python -m pip install -e .
|
||
fi
|
||
|
||
echo "==> 使用 PyInstaller 生成自带 Python 运行时的可执行目录"
|
||
python -m PyInstaller \
|
||
--clean \
|
||
--noconfirm \
|
||
--name "$APP_NAME" \
|
||
--onedir \
|
||
--console \
|
||
--distpath "$BUILD_DIR/pyinstaller_dist" \
|
||
--workpath "$BUILD_DIR/pyinstaller_build" \
|
||
--specpath "$BUILD_DIR" \
|
||
--collect-submodules pam_deploy_graph \
|
||
--collect-submodules langgraph \
|
||
--hidden-import pam_deploy_graph.cli \
|
||
packaging/pyinstaller_entry.py
|
||
|
||
echo "==> 组装发布目录"
|
||
mkdir -p "$RELEASE_DIR"
|
||
cp -a "$BUILD_DIR/pyinstaller_dist/$APP_NAME/." "$RELEASE_DIR/"
|
||
|
||
mkdir -p "$RELEASE_DIR/doc_scripts"
|
||
cp -a doc_scripts/deploy.sh "$RELEASE_DIR/doc_scripts/deploy.sh"
|
||
cp -a doc_scripts/config.txt.example "$RELEASE_DIR/doc_scripts/config.txt.example"
|
||
cp -a doc_scripts/PAM_AUTO_DEPLY_SKILL.md "$RELEASE_DIR/doc_scripts/PAM_AUTO_DEPLY_SKILL.md"
|
||
chmod +x "$RELEASE_DIR/doc_scripts/deploy.sh"
|
||
|
||
mkdir -p "$RELEASE_DIR/prompts"
|
||
cp -a prompts/action_review.txt "$RELEASE_DIR/prompts/action_review.txt"
|
||
|
||
cp -a packaging/README_packaged_agent.md "$RELEASE_DIR/README.md"
|
||
cp -a packaging/mcp_client.example.json "$RELEASE_DIR/mcp_client.example.json"
|
||
cp -a LICENSE "$RELEASE_DIR/LICENSE"
|
||
|
||
cat > "$RELEASE_DIR/run.sh" <<'RUN_SCRIPT'
|
||
#!/usr/bin/env bash
|
||
set -euo pipefail
|
||
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
cd "$DIR"
|
||
|
||
print_help() {
|
||
cat <<'HELP_TEXT'
|
||
PAM 部署 Agent 解压即用包
|
||
|
||
用法:
|
||
./run.sh <命令> [参数]
|
||
|
||
常用命令:
|
||
chat 启动交互式对话框。推荐从这里开始使用。
|
||
analyze 只做自然语言理解和部署计划生成,不执行 action。
|
||
preview 根据配置预演 action 路由和关键参数。
|
||
run-global 执行全局阶段:token、版本、上传、发布、Node URL、下载任务。
|
||
run-deploy 执行完整部署流程:全局阶段 + 逐 IP 阶段。
|
||
resume 从 checkpoint 继续执行。
|
||
confirm 处理待人工确认事项,目前用于失败 IP 回滚确认。
|
||
|
||
通用参数:
|
||
--config <路径>
|
||
参数配置文件。支持 config.txt 风格和 JSON。打包内置示例:
|
||
doc_scripts/config.txt.example
|
||
|
||
--strategy <策略>
|
||
执行策略:
|
||
fake 全部使用 fake runner,不访问真实环境。
|
||
script_only 全部 action 走脚本。
|
||
hybrid_node_mcp PAM_HOME 走脚本,PAM_NODE 走 MCP。
|
||
|
||
--checkpoint <路径>
|
||
checkpoint JSON 路径。用于断点续跑和人工确认恢复。
|
||
示例:runtime/checkpoints/demo.json
|
||
|
||
--target-ip <IP>
|
||
指定目标工作站 IP。可重复传入多次。
|
||
|
||
--mcp-config <路径>
|
||
MCP client JSON 配置文件。通常配置 server_url 和独立鉴权信息;
|
||
Agent 会从 server list_tools 自动发现 tools。hybrid_node_mcp 策略、
|
||
resume 或 confirm 需要执行 MCP action 时使用。
|
||
示例:mcp_client.example.json
|
||
|
||
--confirm
|
||
非交互命令执行真实 action 前必须显式传入。
|
||
chat 模式会在会话中要求输入 run,并分别确认参数、目标范围和最终执行。
|
||
|
||
--analyze-actions
|
||
每个 action 完成后追加 LLM/规则诊断建议。诊断只作为辅助建议,
|
||
不会自动决定继续、回滚或修改参数。
|
||
|
||
LLM 参数:
|
||
--llm-base-url <URL>
|
||
OpenAI-compatible LLM 服务地址,例如 https://example.com/v1
|
||
|
||
--llm-api-key <KEY>
|
||
LLM API Key。也可通过环境变量 PAM_LLM_API_KEY 提供。
|
||
|
||
--llm-model <模型名>
|
||
LLM 模型名称。也可通过环境变量 PAM_LLM_MODEL 提供。
|
||
|
||
LLM 环境变量:
|
||
PAM_LLM_BASE_URL
|
||
PAM_LLM_API_KEY
|
||
PAM_LLM_MODEL
|
||
|
||
示例:
|
||
./run.sh chat --config doc_scripts/config.txt.example --strategy fake --checkpoint runtime/checkpoints/demo.json
|
||
|
||
./run.sh chat --config doc_scripts/config.txt.example --strategy hybrid_node_mcp --mcp-config mcp_client.example.json --checkpoint runtime/checkpoints/demo.json
|
||
|
||
./run.sh analyze --config doc_scripts/config.txt.example --text "请用 MCP 预演部署 HET PAM Node 版本 2.0.5,不要动环境"
|
||
|
||
./run.sh run-deploy --config doc_scripts/config.txt.example --strategy fake --checkpoint runtime/checkpoints/demo.json --confirm
|
||
|
||
./run.sh confirm --checkpoint runtime/checkpoints/demo.json --decision approve --confirm
|
||
# 如果进程中断或需要再次续跑:
|
||
./run.sh resume --checkpoint runtime/checkpoints/demo.json --confirm
|
||
|
||
查看子命令原始参数:
|
||
./run.sh chat --help
|
||
./run.sh run-deploy --help
|
||
|
||
说明:
|
||
1. 本包已包含 Python 运行时和 Python 依赖,目标机器不需要安装 Python 包。
|
||
2. doc_scripts 只包含运行必需文件:deploy.sh、config.txt.example、PAM_AUTO_DEPLY_SKILL.md。
|
||
3. prompts/action_review.txt 是当前默认 action 审核提示词基线,可复制后自行修改。
|
||
4. mcp_client.example.json 是 MCP server URL + 独立鉴权配置示例,需要按真实 MCP server 修改。
|
||
5. confirm 会通过 LangGraph interrupt resume 处理确认,并继续后续图节点;进程中断时再使用 resume。
|
||
6. chat 会在执行前归一化并展示实际写入脚本配置的参数;script_only / hybrid_node_mcp 会先检查 ZIP_FILE_PATH 是否存在。
|
||
7. chat 执行过程中会播报每个 action 的开始、完成或失败;普通问候不会触发 LLM/结构化分析。
|
||
8. chat 内可使用 params、events、list checkpoints、load checkpoint、load params、llm config、mcp config 等命令。
|
||
9. checkpoint 会保存完整运行参数,请放在受控目录。
|
||
HELP_TEXT
|
||
}
|
||
|
||
if [[ $# -eq 0 || "${1:-}" == "-h" || "${1:-}" == "--help" || "${1:-}" == "help" ]]; then
|
||
print_help
|
||
exit 0
|
||
fi
|
||
|
||
exec "$DIR/pam-deploy-agent" "$@"
|
||
RUN_SCRIPT
|
||
chmod +x "$RELEASE_DIR/run.sh"
|
||
|
||
echo "==> 生成 tar.gz"
|
||
tar -C "$DIST_DIR" -czf "$ARCHIVE_PATH" "$RELEASE_NAME"
|
||
|
||
format_bytes() {
|
||
local bytes="$1"
|
||
python - "$bytes" <<'PY'
|
||
import sys
|
||
value = float(sys.argv[1])
|
||
units = ["B", "KB", "MB", "GB"]
|
||
for unit in units:
|
||
if value < 1024 or unit == units[-1]:
|
||
print(f"{value:.1f} {unit}")
|
||
break
|
||
value /= 1024
|
||
PY
|
||
}
|
||
|
||
EXTRACTED_BYTES="$(du -sb "$RELEASE_DIR" | awk '{print $1}')"
|
||
ARCHIVE_BYTES="$(du -sb "$ARCHIVE_PATH" | awk '{print $1}')"
|
||
|
||
echo "==> 构建完成"
|
||
echo "发布目录: $RELEASE_DIR"
|
||
echo "压缩包: $ARCHIVE_PATH"
|
||
echo "解压后大小: $(format_bytes "$EXTRACTED_BYTES")"
|
||
echo "压缩包大小: $(format_bytes "$ARCHIVE_BYTES")"
|