dark 14e297a488 feat: 落地 PAM 智能部署 Agent 骨架
- 新增 pam_deploy_graph 包,包含 Agent runtime、ActionRouter、脚本/MCP/fake runner
- 支持 hybrid_node_mcp 策略:PAM_HOME 走脚本 action,PAM_NODE 走 MCP
- 支持 script_only 离线策略,全部 action 走现有脚本 action
- 新增 LLM structured output 骨架和规则 fallback,支持意图识别、参数抽取、计划生成
- 新增 LangGraph StateGraph 工厂和 MCP client adapter
- 新增 CLI:preview、analyze、run-global、run-deploy
- 增加 fake 完整部署流程、单 IP 失败待回滚确认状态和报告输出
- 增加单元测试覆盖路由、parser、runner、Skill 加载、LLM 输出、MCP adapter 和 LangGraph 图
- 更新 README,记录当前代码骨架、进度、使用方式和下一步计划
2026-05-29 15:53:47 +08:00

28 lines
1.2 KiB
Python

"""Validation and guardrails for LLM structured outputs."""
from __future__ import annotations
from pam_deploy_graph.constants import ALLOWED_ACTIONS
from pam_deploy_graph.models import LlmDeployPlan, LlmIntentResult
VALID_INTENTS = {"deploy", "show_usage", "preview", "query_node_ips", "rollback"}
FORBIDDEN_TEXT = ("bash ", "powershell ", "deploy.sh", "deploy.ps1", "CLIENT_SECRET=")
def validate_intent_result(result: LlmIntentResult) -> None:
if result.intent not in VALID_INTENTS:
raise ValueError(f"Invalid intent: {result.intent}")
if not 0 <= result.confidence <= 1:
raise ValueError("Intent confidence must be between 0 and 1")
def validate_deploy_plan(plan: LlmDeployPlan) -> None:
invalid = [action for action in plan.planned_actions if action not in ALLOWED_ACTIONS]
if invalid:
raise ValueError(f"Plan contains invalid actions: {', '.join(invalid)}")
combined_text = "\n".join([plan.summary, *plan.risk_notes])
lowered = combined_text.lower()
forbidden = [item for item in FORBIDDEN_TEXT if item.lower() in lowered]
if forbidden:
raise ValueError(f"Plan contains forbidden executable text: {', '.join(forbidden)}")