- 新增 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,记录当前代码骨架、进度、使用方式和下一步计划
59 lines
1.8 KiB
Python
59 lines
1.8 KiB
Python
from pathlib import Path
|
|
|
|
from pam_deploy_graph.agent import PamDeployAgent
|
|
from pam_deploy_graph.fake_runner import FakeActionRunner
|
|
|
|
|
|
PARAMS = {
|
|
"HOME_BASE_URL": "https://pam.home.example.com",
|
|
"CLIENT_ID": "client",
|
|
"CLIENT_SECRET": "secret",
|
|
"AIRPORT_CODE": "HET",
|
|
"APP_NAME": "PAM",
|
|
"MODULE_NAME": "Node",
|
|
"VERSION_NUMBER": "2.0.5",
|
|
"ZIP_FILE_PATH": "C:/pkg.zip",
|
|
}
|
|
|
|
|
|
def test_run_deploy_flow_success(tmp_path: Path):
|
|
agent = PamDeployAgent(fake_runner=FakeActionRunner())
|
|
state = agent.create_state(
|
|
params=PARAMS,
|
|
execution_strategy="fake",
|
|
config_path=str(tmp_path / "config.txt"),
|
|
)
|
|
|
|
agent.run_deploy_flow(state)
|
|
|
|
assert state.pending_confirmation == ""
|
|
assert set(state.ip_states) == {"192.168.1.10", "192.168.1.11"}
|
|
assert all(item["status"] == "SUCCESS" for item in state.ip_states.values())
|
|
|
|
|
|
def test_run_deploy_flow_stops_on_verify_failure(tmp_path: Path):
|
|
fake = FakeActionRunner(
|
|
{
|
|
"verify-ip:192.168.1.10": {
|
|
"ACTION": "verify-ip",
|
|
"IP": "192.168.1.10",
|
|
"SUCCESS": "false",
|
|
"MESSAGE": "health check failed",
|
|
}
|
|
}
|
|
)
|
|
agent = PamDeployAgent(fake_runner=fake)
|
|
state = agent.create_state(
|
|
params=PARAMS,
|
|
execution_strategy="fake",
|
|
config_path=str(tmp_path / "config.txt"),
|
|
)
|
|
|
|
agent.run_deploy_flow(state)
|
|
|
|
assert state.pending_confirmation == "rollback-ip:192.168.1.10"
|
|
assert state.ip_states["192.168.1.10"]["status"] == "FAILED"
|
|
assert state.ip_states["192.168.1.10"]["rollback_status"] == "PENDING_AGENT_CONFIRMATION"
|
|
assert "192.168.1.11" not in state.ip_states
|
|
assert any(event["type"] == "CONFIRMATION_REQUIRED" for event in state.events)
|