From 67b3b778b886cb67ec2cbaa56213d1b78beed85c Mon Sep 17 00:00:00 2001 From: YueGuobin Date: Tue, 12 May 2026 13:37:59 +0800 Subject: [PATCH] feat: add PacketAnalysisSkillsTool - Register packet_analysis_skills as a LangChain tool for LLM - LLM can query protocol field definitions before calling packet_analysis - Follows the same pattern as DeviceSkillsTool and InjectionSkillsTool --- .../agent/gns3_copilot/agent/gns3_copilot.py | 3 + .../agent/gns3_copilot/skills/__init__.py | 2 + .../agent/gns3_copilot/skills/registry.py | 67 +++++++++++++++++++ 3 files changed, 72 insertions(+) diff --git a/gns3server/agent/gns3_copilot/agent/gns3_copilot.py b/gns3server/agent/gns3_copilot/agent/gns3_copilot.py index 1ba5cb0d7..a675d2074 100644 --- a/gns3server/agent/gns3_copilot/agent/gns3_copilot.py +++ b/gns3server/agent/gns3_copilot/agent/gns3_copilot.py @@ -97,6 +97,7 @@ from gns3server.agent.gns3_copilot.tools_v2.vpcs_tools_netmiko import VPCSComman from gns3server.agent.gns3_copilot.tools_v2 import PacketAnalysisTool from gns3server.agent.gns3_copilot.skills import DeviceSkillsTool from gns3server.agent.gns3_copilot.skills import InjectionSkillsTool +from gns3server.agent.gns3_copilot.skills import PacketAnalysisSkillsTool # Set up logger for GNS3-Copilot logger = logging.getLogger(__name__) @@ -116,6 +117,7 @@ TEACHING_ASSISTANT_MODE_TOOLS = [ ExecuteMultipleDeviceCommands(), # Execute show/display/debug commands # (READ-ONLY) PacketAnalysisTool(), # Protocol-oriented packet analysis with tshark + PacketAnalysisSkillsTool(), # Query packet analysis protocol definitions DeviceSkillsTool(), # Get device-specific skills and command knowledge ] @@ -133,6 +135,7 @@ LAB_AUTOMATION_ASSISTANT_MODE_TOOLS = [ ExecuteMultipleDeviceConfigCommands(), # Execute configuration commands VPCSCommands(), # Execute VPCS commands using Netmiko PacketAnalysisTool(), # Protocol-oriented packet analysis with tshark + PacketAnalysisSkillsTool(), # Query packet analysis protocol definitions DeviceSkillsTool(), # Get device-specific skills and command knowledge ] diff --git a/gns3server/agent/gns3_copilot/skills/__init__.py b/gns3server/agent/gns3_copilot/skills/__init__.py index bbc0ebb73..c23c9d8b8 100644 --- a/gns3server/agent/gns3_copilot/skills/__init__.py +++ b/gns3server/agent/gns3_copilot/skills/__init__.py @@ -43,6 +43,7 @@ from .registry import ( get_injection_skill, DeviceSkillsTool, InjectionSkillsTool, + PacketAnalysisSkillsTool, set_skills_manager, get_skills_manager, reload_injection_skills, @@ -60,6 +61,7 @@ __all__ = [ "get_injection_skill", "DeviceSkillsTool", "InjectionSkillsTool", + "PacketAnalysisSkillsTool", "SkillsManager", "SkillsLoader", "set_skills_manager", diff --git a/gns3server/agent/gns3_copilot/skills/registry.py b/gns3server/agent/gns3_copilot/skills/registry.py index 40e04f4a6..eb6b2b5b6 100644 --- a/gns3server/agent/gns3_copilot/skills/registry.py +++ b/gns3server/agent/gns3_copilot/skills/registry.py @@ -783,3 +783,70 @@ class InjectionSkillsTool(BaseTool): skill = get_injection_skill(device_type, detail=detail, issue=issue) return json.dumps(skill, ensure_ascii=False, indent=2) + + +class PacketAnalysisSkillsTool(BaseTool): + """ + LangChain tool for querying packet analysis protocol definitions. + + Use this tool to list available protocols and get protocol-specific + tshark fields, display filters, and check rules. + """ + + name: str = "packet_analysis_skills" + description: str = """ + Get or list packet analysis protocol definitions. + + Before calling packet_analysis tool, use this to query the protocol's + available tshark fields, display filters, and check rules. + + USAGE: + - List available protocols: + {"action": "list"} + + - Get protocol definition with fields: + {"action": "get", "protocol": "ospf"} + + PARAMETERS: + - action: "list" or "get" (required) + - protocol: Protocol key for action="get" (e.g., "ospf", "bgp", "arp", "icmp") + """ + + def _run( + self, + tool_input: str | dict[str, Any], + run_manager: CallbackManagerForToolRun | None = None, + **kwargs: Any, + ) -> str: + """Execute the packet analysis skills lookup.""" + logger.debug("PacketAnalysisSkillsTool invoked with input: %s", tool_input) + + if isinstance(tool_input, str): + try: + params = json.loads(tool_input) + except json.JSONDecodeError as e: + return json.dumps({ + "error": f"Invalid JSON input: {e}", + "hint": 'Expected format: {"action": "get", "protocol": "ospf"}' + }, ensure_ascii=False, indent=2) + else: + params = tool_input + + action = params.get("action", "get") + + if action == "list": + protocols = list_available_packet_analysis_protocols() + return json.dumps({ + "count": len(protocols), + "protocols": protocols + }, ensure_ascii=False, indent=2) + + protocol = params.get("protocol") + if not protocol: + return json.dumps({ + "error": "Missing required field: protocol", + "available_protocols": list(PACKET_ANALYSIS_REGISTRY.keys()), + }, ensure_ascii=False, indent=2) + + result = get_packet_analysis_protocol(protocol) + return json.dumps(result, ensure_ascii=False, indent=2)