From 87378b452d8635b12ec23e33c95bfbedccc3de00 Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 1 Jun 2026 01:11:10 +0800 Subject: [PATCH] fix(api): normalize ssh mcp evidence inputs --- .../src/plugins/mcp/providers/ssh_provider.py | 6 +++++- apps/api/src/services/decision_manager.py | 2 +- .../src/services/pre_decision_investigator.py | 1 + .../tests/test_pre_decision_investigator.py | 19 +++++++++++++++++++ apps/api/tests/test_ssh_provider_tools.py | 13 +++++++++++++ 5 files changed, 39 insertions(+), 2 deletions(-) diff --git a/apps/api/src/plugins/mcp/providers/ssh_provider.py b/apps/api/src/plugins/mcp/providers/ssh_provider.py index 07cd4a53..f5bca931 100644 --- a/apps/api/src/plugins/mcp/providers/ssh_provider.py +++ b/apps/api/src/plugins/mcp/providers/ssh_provider.py @@ -70,6 +70,7 @@ SHORT_HOST_MAP = { "120": "192.168.0.120", "121": "192.168.0.121", "188": "192.168.0.188", + "wooo": "192.168.0.110", } DIAG_TIMEOUT = 10 # 診斷類超時(秒) OP_TIMEOUT = 60 # 操作類超時(秒) @@ -587,7 +588,10 @@ class SSHProvider(MCPToolProvider): return f"docker logs {name} --tail {tail} 2>&1" if tool_name == "ssh_get_container_status": - name = _validate_param("filter_name", params["filter_name"]) + raw_name = params.get("filter_name") or params.get("container_name") or params.get("name") + if not raw_name: + raise ValueError("Missing filter_name for ssh_get_container_status") + name = _validate_param("filter_name", str(raw_name)) return f"docker ps -a --filter name={name}" if tool_name == "ssh_get_service_status": diff --git a/apps/api/src/services/decision_manager.py b/apps/api/src/services/decision_manager.py index 24cfb607..075a6bbd 100644 --- a/apps/api/src/services/decision_manager.py +++ b/apps/api/src/services/decision_manager.py @@ -2661,7 +2661,7 @@ class DecisionManager: ssh.execute( tool_name="ssh_get_container_status", # P0.4 fix 2026-04-24 ogt + Claude Sonnet 4.6: params= → parameters=(符合 MCPToolProvider.execute 簽名) - parameters={"host": host, "container_name": container}, + parameters={"host": host, "filter_name": container, "container_name": container}, ), timeout=_MCP_TIMEOUT, ) diff --git a/apps/api/src/services/pre_decision_investigator.py b/apps/api/src/services/pre_decision_investigator.py index c6ae6375..e7031c34 100644 --- a/apps/api/src/services/pre_decision_investigator.py +++ b/apps/api/src/services/pre_decision_investigator.py @@ -552,6 +552,7 @@ _SHORT_HOST_MAP: dict[str, str] = { "188": "192.168.0.188", "ollama": "192.168.0.188", "ai-web": "192.168.0.188", + "wooo": "192.168.0.110", "harbor": "192.168.0.110", "gitea": "192.168.0.110", } diff --git a/apps/api/tests/test_pre_decision_investigator.py b/apps/api/tests/test_pre_decision_investigator.py index c4c2dd90..0097996e 100644 --- a/apps/api/tests/test_pre_decision_investigator.py +++ b/apps/api/tests/test_pre_decision_investigator.py @@ -173,6 +173,25 @@ def test_build_tool_params_uses_host_alias_and_service_from_affected_service() - assert params["time_window_minutes"] == 30 +def test_build_tool_params_maps_wooo_alias_to_allowed_ssh_host() -> None: + class _Signal: + alert_name = "HostHighCpuLoad" + labels = { + "alertname": "HostHighCpuLoad", + "instance": "wooo:9100", + } + + class _Incident: + incident_id = "INC-WOOO" + signals = [_Signal()] + affected_services = ["gitea"] + + params = _build_tool_params(_Incident()) + + assert params["host"] == "192.168.0.110" + assert params["filter_name"] == "gitea" + + # ───────────────────────────────────────────────────────────────────────────── # _compute_fingerprint # ───────────────────────────────────────────────────────────────────────────── diff --git a/apps/api/tests/test_ssh_provider_tools.py b/apps/api/tests/test_ssh_provider_tools.py index 4f7630e9..1a181652 100644 --- a/apps/api/tests/test_ssh_provider_tools.py +++ b/apps/api/tests/test_ssh_provider_tools.py @@ -45,6 +45,8 @@ def test_ssh_provider_uses_ollama_user_for_188(): [ ("192.168.0.110:9100", "192.168.0.110"), ("110:9100", "192.168.0.110"), + ("wooo", "192.168.0.110"), + ("wooo:9100", "192.168.0.110"), ("188", "192.168.0.188"), ("wooo@192.168.0.110", "192.168.0.110"), ("ssh://wooo@192.168.0.110:22", "192.168.0.110"), @@ -90,3 +92,14 @@ async def test_ssh_execute_normalizes_host_before_allowed_check(monkeypatch): assert result.success is True assert captured["host"] == "192.168.0.110" assert isinstance(captured["timeout"], int) + + +def test_ssh_container_status_accepts_legacy_container_name_alias(): + provider = SSHProvider() + + command = provider._build_command( + "ssh_get_container_status", + {"container_name": "awoooi-api"}, + ) + + assert command == "docker ps -a --filter name=awoooi-api"