From df8338401ebc37c46b55de20387bc0518ef2ecb7 Mon Sep 17 00:00:00 2001 From: YueGuobin Date: Sat, 14 Mar 2026 14:54:12 +0800 Subject: [PATCH] feat(copilot): filter built-in utility templates from GNS3TemplateTool Add filtering logic to exclude built-in utility templates that are not useful for network device configuration, making AI focus on actual network devices. - Add FILTERED_TEMPLATES constant with 6 utility template types * atm_switch - ATM switch * cloud - Cloud * ethernet_hub - Ethernet hub * ethernet_switch - Ethernet switch (built-in) * frame_relay_switch - Frame Relay switch * nat - NAT device - Add should_filter_template() function * Exact match on template_type field * Simple and reliable filtering logic - Update GNS3TemplateTool * Apply filtering in _run() method * Log filtered count for transparency * Update tool description - Update documentation (node-control-tools.md) * Document filtered template types * List retained template types * Add changelog entry - Code quality * All comments in English * flake8 check passed * mypy check passed --- .../implemented/node-control-tools.md | 40 +++++++++-- .../tools_v2/gns3_get_node_temp.py | 72 ++++++++++++++++--- 2 files changed, 98 insertions(+), 14 deletions(-) diff --git a/docs/gns3-copilot/implemented/node-control-tools.md b/docs/gns3-copilot/implemented/node-control-tools.md index f3c56a0b4..984263bbb 100644 --- a/docs/gns3-copilot/implemented/node-control-tools.md +++ b/docs/gns3-copilot/implemented/node-control-tools.md @@ -10,7 +10,7 @@ GNS3-Copilot provides tools for managing the lifecycle of network devices and to **Tool Name:** `get_gns3_templates` -**Description:** Retrieves all available device templates from the GNS3 server, including template names, IDs, and types. +**Description:** Retrieves all available device templates from the GNS3 server, including template names, IDs, and types. Filters out built-in utility templates that are not useful for network device configuration. **Input:** ```json @@ -24,26 +24,47 @@ GNS3-Copilot provides tools for managing the lifecycle of network devices and to { "name": "Cisco IOSv", "template_id": "uuid-of-template", - "template_type": "router" + "template_type": "qemu" }, { - "name": "Ethernet switch", + "name": "VPCS", "template_id": "uuid-of-template2", - "template_type": "switch" + "template_type": "vpcs" } ] } ``` **Features:** -- Lists all available device templates +- Lists all available device templates for network labs +- Filters out built-in utility templates (see filtered list below) - No input required (connects to configured GNS3 server) - Returns template_id needed for node creation +- Logs total templates, filtered count, and remaining count + +**Filtered Templates:** +The following built-in utility templates are excluded as they are not actual network devices: +- `atm_switch` - ATM switch +- `cloud` - Cloud +- `ethernet_hub` - Ethernet hub +- `ethernet_switch` - Ethernet switch (built-in, not user appliances) +- `frame_relay_switch` - Frame Relay switch +- `nat` - NAT device + +**Retained Template Types:** +- `vpcs` - Virtual PC Simulator +- `dynamips` - Cisco router simulator (IOSv, IOSv-L2, etc.) +- `iou` - Cisco IOS on Unix +- `qemu` - QEMU virtual machines +- `docker` - Docker containers +- `virtualbox` - VirtualBox VMs +- `vmware` - VMware VMs **Use Cases:** - Discover available device types before creating nodes - Get template_id for GNS3CreateNodeTool - Template inventory management +- Focus on network devices rather than utility templates ### GNS3CreateNodeTool 🆕 @@ -468,6 +489,7 @@ Starting 3 node(s), please wait... | **Suspended** | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes | *Except special node types: cloud, nat, ethernet_switch, ethernet_hub, frame_relay_switch, atm_switch +Note: These special node types are filtered out by GNS3TemplateTool and won't appear in template listings for network lab creation. ## Copilot Mode Integration @@ -885,4 +907,12 @@ logger.info("Suspend command sent for node %s (%s)", node_id, node.name) _Implementation Date: 2026-03-12_ +_Last Updated: 2026-03-14 (Added template filtering to exclude built-in utility templates)_ + _Status: ✅ Implemented - Topology management tools available in both modes. Full lifecycle management (start/stop/suspend) available in Lab Automation Assistant Mode_ + +_Changelog:_ +- **2026-03-14**: Added template filtering + - `GNS3TemplateTool` now filters out built-in utility templates (cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch) + - Focuses on network devices suitable for lab configuration + - Logs filtered count for transparency diff --git a/gns3server/agent/gns3_copilot/tools_v2/gns3_get_node_temp.py b/gns3server/agent/gns3_copilot/tools_v2/gns3_get_node_temp.py index bcfff1bb0..fabd78f5a 100644 --- a/gns3server/agent/gns3_copilot/tools_v2/gns3_get_node_temp.py +++ b/gns3server/agent/gns3_copilot/tools_v2/gns3_get_node_temp.py @@ -28,6 +28,7 @@ GNS3 template retrieval tool for device discovery. Provides functionality to retrieve all available device templates from a GNS3 server, including template names, IDs, and types. +Filters out built-in utility templates that are not useful for network labs. """ import json @@ -43,11 +44,42 @@ from gns3server.agent.gns3_copilot.gns3_client import get_gns3_connector # Configure logging logger = logging.getLogger(__name__) +# Built-in templates to filter out (utility templates, not actual network devices) +FILTERED_TEMPLATES = { + "atm_switch", # ATM switch + "cloud", # Cloud + "ethernet_hub", # Ethernet hub + "ethernet_switch", # Ethernet switch (built-in) + "frame_relay_switch", # Frame Relay switch + "nat", # NAT device +} + + +def should_filter_template(template: dict[str, Any]) -> bool: + """ + Determine whether a template should be filtered out. + + Filter condition: + 1. Template type is in the filter list (exact match) + + Args: + template: Template dictionary + + Returns: + True if template should be filtered, False if it should be kept + """ + template_type = template.get("template_type", "") + + # Check if template_type is in filter list + # This is the most reliable way to identify built-in utility templates + return template_type in FILTERED_TEMPLATES + class GNS3TemplateTool(BaseTool): """ LangChain tool to retrieve available device templates from GNS3 server. Connects to GNS3 server and extracts name, template_id, and template_type. + Filters out built-in utility templates that are not useful for network labs. **Input:** No input required. Connects to GNS3 server at default URL. @@ -55,12 +87,24 @@ class GNS3TemplateTool(BaseTool): **Output:** Dict with list of dicts (name, template_id, template_type). If error, returns dict with error message. + + **Filtered Templates:** + The following built-in utility templates are excluded: + - ATM switch + - Cloud + - Ethernet hub + - Ethernet switch (built-in) + - Frame Relay switch + - NAT """ name: str = "get_gns3_templates" description: str = """ - Retrieves available device templates from GNS3 server. + Retrieves available device templates from GNS3 server for network labs. Returns dict with list of dicts (name, template_id, template_type). + Filters out built-in utility templates (ATM switch, Cloud, Ethernet hub, + Ethernet switch, Frame Relay switch, NAT) as they are not useful for + network device configuration. No input required. If connection fails, returns dict with error message. """ @@ -96,23 +140,33 @@ class GNS3TemplateTool(BaseTool): # Retrieve all available templates templates = gns3_server.get_templates() - # Extract name, template_id, and template_type - template_info = [ - { + + # Filter out utility templates and extract relevant info + template_info = [] + filtered_count = 0 + for template in templates: + # Check if template should be filtered + if should_filter_template(template): + filtered_count += 1 + logger.debug("Filtered out template: %s", template.get("name")) + continue + + # Extract name, template_id, and template_type + template_info.append({ "name": template.get("name", "N/A"), "template_id": template.get("template_id", "N/A"), "template_type": template.get("template_type", "N/A"), - } - for template in templates - ] + }) # Return JSON-formatted result with full logging result = {"templates": template_info} logger.info( - "Template retrieval completed. Total: %d. Result: %s", + "Template retrieval completed. Total: %d, Filtered: %d, Remaining: %d", + len(templates), + filtered_count, len(template_info), - json.dumps(result, indent=2, ensure_ascii=False), ) + logger.debug("Result: %s", json.dumps(result, indent=2, ensure_ascii=False)) return result except Exception as e: