- 新增 MCP client 配置加载,支持 CLI/chat 通过配置文件接入 MCP - 完善 chat 交互命令,支持参数查看、事件查看、checkpoint 列表与加载 - 增加 LLM action 后诊断能力,支持真实 LLM 和本地规则兜底 - 将 chat 人工确认点接入 LangGraph interrupt/checkpointer - 更新 README、流程图、待办文档和打包说明 - 补充相关单元测试
133 lines
4.2 KiB
Python
133 lines
4.2 KiB
Python
from pathlib import Path
|
|
|
|
from pam_deploy_graph.agent import PamDeployAgent
|
|
from pam_deploy_graph.fake_runner import FakeActionRunner
|
|
from pam_deploy_graph.interactive import InteractiveCliSession
|
|
|
|
|
|
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 run_session(session: InteractiveCliSession, inputs: list[str]) -> list[str]:
|
|
output: list[str] = []
|
|
iterator = iter(inputs)
|
|
session.input = lambda _prompt: next(iterator)
|
|
session.output = output.append
|
|
session.run()
|
|
return output
|
|
|
|
|
|
def test_chat_analyzes_natural_language_and_updates_context(tmp_path: Path):
|
|
session = InteractiveCliSession(
|
|
agent=PamDeployAgent(),
|
|
params=PARAMS,
|
|
strategy="fake",
|
|
checkpoint_path=str(tmp_path / "checkpoint.json"),
|
|
)
|
|
|
|
output = run_session(session, ["analyze please use MCP deploy 192.168.1.10", "exit"])
|
|
|
|
assert session.strategy == "hybrid_node_mcp"
|
|
assert session.target_ips == ["192.168.1.10"]
|
|
assert any("执行请输 run" in item for item in output)
|
|
|
|
|
|
def test_chat_run_executes_fake_deploy_and_writes_checkpoint(tmp_path: Path):
|
|
checkpoint = tmp_path / "checkpoint.json"
|
|
session = InteractiveCliSession(
|
|
agent=PamDeployAgent(fake_runner=FakeActionRunner()),
|
|
params=PARAMS,
|
|
strategy="fake",
|
|
checkpoint_path=str(checkpoint),
|
|
)
|
|
|
|
run_session(session, ["run", "yes", "yes", "yes", "exit"])
|
|
|
|
assert checkpoint.exists()
|
|
assert session.state is not None
|
|
assert session.state.pending_confirmation == ""
|
|
assert all(item["status"] == "SUCCESS" for item in session.state.ip_states.values())
|
|
|
|
|
|
def test_chat_approve_then_resume_continues_after_failed_ip(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",
|
|
}
|
|
}
|
|
)
|
|
session = InteractiveCliSession(
|
|
agent=PamDeployAgent(fake_runner=fake),
|
|
params=PARAMS,
|
|
strategy="fake",
|
|
checkpoint_path=str(tmp_path / "checkpoint.json"),
|
|
)
|
|
|
|
run_session(session, ["run", "yes", "yes", "yes", "approve", "resume", "exit"])
|
|
|
|
assert session.state is not None
|
|
assert session.state.pending_confirmation == ""
|
|
assert session.state.ip_states["192.168.1.10"]["rollback_status"] == "ROLLBACK_DONE"
|
|
assert session.state.ip_states["192.168.1.11"]["status"] == "SUCCESS"
|
|
|
|
|
|
def test_chat_params_events_and_checkpoint_commands(tmp_path: Path):
|
|
checkpoint = tmp_path / "checkpoint.json"
|
|
session = InteractiveCliSession(
|
|
agent=PamDeployAgent(fake_runner=FakeActionRunner(), action_analysis_enabled=True),
|
|
params=PARAMS,
|
|
strategy="fake",
|
|
checkpoint_path=str(checkpoint),
|
|
)
|
|
|
|
output = run_session(
|
|
session,
|
|
[
|
|
"params",
|
|
"llm action-analysis on",
|
|
"run",
|
|
"yes",
|
|
"yes",
|
|
"yes",
|
|
"events 2",
|
|
"list checkpoints",
|
|
"load checkpoint " + str(checkpoint),
|
|
"exit",
|
|
],
|
|
)
|
|
|
|
assert session.state is not None
|
|
assert any("CLIENT_SECRET: ***" in item for item in output)
|
|
assert any("ACTION_ANALYSIS" in item for item in output)
|
|
assert any("checkpoint 列表" in item for item in output)
|
|
|
|
|
|
def test_chat_can_hot_load_mcp_config(tmp_path: Path):
|
|
mcp_config = tmp_path / "mcp.json"
|
|
mcp_config.write_text('{"transport": "stdio", "command": "python"}', encoding="utf-8")
|
|
session = InteractiveCliSession(
|
|
agent=PamDeployAgent(),
|
|
params=PARAMS,
|
|
strategy="hybrid_node_mcp",
|
|
checkpoint_path=str(tmp_path / "checkpoint.json"),
|
|
)
|
|
|
|
output = run_session(session, ["mcp config " + mcp_config.as_posix(), "exit"])
|
|
|
|
assert session.agent.mcp_runner is not None
|
|
assert session.agent.router.mcp_runner is not None
|
|
assert any("MCP 配置已加载" in item for item in output)
|