- Add _validate_bpf_syntax() method to validate BPF expressions
- Use tshark with 1-second timeout for syntax checking
- Check for "Invalid" in output to detect syntax errors
- Validate BPF filters before applying them to links
- Handle tshark not installed scenario gracefully
- Support both single and multiple BPF expressions
- Return detailed error messages for syntax validation failures
- Add show_filters_icon parameter with default value False
- Pass show_filters_icon to link.update() in set and clear operations
- Update tool description to explain default behavior
- Remove "clear" action from description to simplify interface
- Hide filter icon in GNS3 Web UI by default for cleaner UI during fault injection
Add comprehensive packet filter management functionality to GNS3-Copilot,
enabling AI-powered fault injection scenarios with network simulation
capabilities like latency, packet loss, and corruption.
## Changes
### New Features
- **GNS3PacketFilterTool**: New LangChain tool for managing packet filters
on GNS3 links with support for delay, packet loss, corruption,
frequency_drop, and BPF filtering
- Actions: get_available, set, get, clear
- Integrated into troubleshooting_injection mode for fault scenarios
### API Integration
- **Link.available_filters()**: Added method to custom_gns3fy.py Link class
- Queries available filter types for specific links
- API v3+ only (raises ValueError for v2 connectors)
- Returns filter definitions with parameters and constraints
### Tool Integration
- Added GNS3PacketFilterTool to TROUBLESHOOTING_INJECTION_MODE_TOOLS
- Positioned as 3rd tool in fault injection workflow
- Optimized for troubleshooting practice scenarios
## Files Modified
- gns3server/agent/gns3_copilot/agent/gns3_copilot.py
- gns3server/agent/gns3_copilot/gns3_client/custom_gns3fy.py
- gns3server/agent/gns3_copilot/tools_v2/__init__.py
## Files Added
- gns3server/agent/gns3_copilot/tools_v2/gns3_packet_filter.py
## Testing
- All validation tests passed
- Version checking verified (v3+ only)
- Tool integration confirmed in troubleshooting mode
This commit adds a new property to the Link class, allowing users to control whether filter icons are displayed in the Web UI at the individual link level.
**Changes:**
- Added attribute to Link class (default: True)
- Added property getter
- Added method for updating the property
- Updated to include the new field with backward compatibility
- Added field to LinkBase schema using Optional[bool] = Field(True, ...) pattern
- Updated API routes to handle the new field in create and update operations
- Added loading logic for show_filters_icon in project.open() to preserve settings when reopening projects
**Schema Definition:**
Uses the same pattern as the field:
**API Impact:**
- POST /v3/projects/{project_id}/links - accepts in request body
- PUT /v3/projects/{project_id}/links/{link_id} - can update
- GET /v3/projects/{project_id}/links/{link_id} - returns field
**Future Applications:**
This feature provides granular control for future AI fault injection modules to manage link-level protocol failures while maintaining clean UI presentation.
Set default value for show_filters_icon in LinkBase schema to ensure the field is always included in API responses, even when response_model_exclude_unset=True is used.
This commit adds a new `show_filters_icon` property to the Link class, allowing users to control whether filter icons are displayed in the Web UI at the individual link level.
**Changes:**
- Added `_show_filters_icon` attribute to Link class (default: True)
- Added `show_filters_icon` property getter
- Added `update_show_filters_icon()` method for updating the property
- Updated `asdict()` to include the new field in both topology and regular dumps
- Added `show_filters_icon` field to LinkBase schema
- Updated API routes to handle the new field in create and update operations
**API Impact:**
- POST /v3/projects/{project_id}/links - accepts `show_filters_icon` in request body
- PUT /v3/projects/{project_id}/links/{link_id} - can update `show_filters_icon`
- GET /v3/projects/{project_id}/links/{link_id} - returns `show_filters_icon` field
**Future Applications:**
This feature provides granular control for future AI fault injection modules to manage link-level protocol failures while maintaining clean UI presentation.
The Web Wireshark WebSocket endpoint created a WebWiresharkManager but
never called close(), leaving the DockerHTTPClient's ClientSession with
UnixConnector unclosed when users closed the browser tab.
Also switch asyncio.wait in WebSocket proxy from ALL_COMPLETED to
FIRST_COMPLETED to avoid blocking cleanup when one direction disconnects.
- 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
- Delete packet_capture_tools.py (analyze_packets with packet_number)
- PacketAnalysisTool is more flexible and can do everything the old tool could
- Update tool registration to use only PacketAnalysisTool
- Cleaner, more unified packet analysis interface
- Add PacketAnalysisTool that accepts user-provided tshark arguments
- LLM constructs tshark commands based on protocol knowledge from skills
- Add PACKET_ANALYSIS_REGISTRY for protocol definitions
- Add load_packet_analysis_protocols() to SkillsLoader
- Add get_packet_analysis_protocol() and list functions to registry
- Register PacketAnalysisTool in teaching and lab automation modes
- Update SkillsManager to reload packet analysis protocols
Related: GNS3-Skills commit 7bc45d2
- Remove 5s thread.join() timeout so git clone/pull is not truncated
- Remove _init_complete flag, reset _init_in_progress on failure instead
- Let /reload/skills API retry initialization after network failure
- Raise GIT_HTTP_LOW_SPEED_LIMIT from 1 KB/s to 10 KB/s
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
## Summary
Add a complete fault injection system for GNS3 Copilot, migrate all
skills from local Python files to an external Git repository with
hot reload support, and restructure Copilot API under /copilot/.
## Key Changes
### Fault Injection
- New troubleshooting_injection mode with InjectionSkillsTool
- 368 fault scenarios across 39 protocol categories
- Context-based filtering (LLM must pass topology protocols)
### External Skills Repository
- SkillsManager: Git clone/pull, version tracking, smart updates
- SkillsLoader: YAML skills + Markdown prompts from external repo
- Hot reload via POST /copilot/reload/skills
- Configurable via gns3_server.conf
### Architecture
- API unified under /copilot/ prefix
- SkillsManager moved from Controller to agent module
- Lazy initialization with startup background preload
- Per-command Git timeout, smart update checks
- Forbidden commands hot-reloadable from external repo
- 32 INFO logs downgraded to DEBUG
DeepSeek models (deepseek-v4-flash/pro) enable thinking mode by default,
which returns reasoning_content that must be passed back to the API in
subsequent requests. This causes 400 errors in multi-turn conversations
when the reasoning_content is not properly handled.
This commit disables thinking mode by passing extra_body={"thinking": {"type": "disabled"}}
as an explicit parameter to DeepSeek models, preventing the reasoning_content
field from being generated.
Modified:
- create_base_model(): Add extra_body parameter with thinking mode disabled
- create_title_model(): Add extra_body parameter with thinking mode disabled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When importing a project, the round-robin logic would attempt to distribute
nodes across all configured compute resources, including offline ones. This
caused import failures when any remote compute was unreachable.
This fix filters the compute list to only include connected computes before
round-robin distribution. If no remote computes are connected, all nodes
are assigned to the local compute.
This matches the approach used in project._get_disconnected_computes() and
prevents the issue where importing a project fails with:
"Cannot connect to compute 'X' with request POST /projects"
Fixes issue introduced in commit 90e3a8d6 (2017) which added round-robin
load balancing without considering offline compute nodes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix F821 undefined name 'status' error by importing the status
module from fastapi. This resolves build errors when using
status.HTTP_403_FORBIDDEN and status.HTTP_404_NOT_FOUND.
Add exception handling in stop_wrap_console to gracefully handle
ConnectionResetError, BrokenPipeError, and OSError when waiting
for console writer to close.
This prevents 500 errors when stopping QEMU nodes if the console
connection is reset before the writer finishes closing.
Fixes race condition where QEMU process exits and closes connections
before the console writer cleanup completes.
Remove MD5 checksum calculation from the node files API since
disk image files are dynamic and change frequently. MD5 calculation
was also causing significant performance overhead.
Changes:
- Remove md5sum field from NodeFile schema
- Remove MD5 calculation from list_node_files method
- Improve error handling for timestamp conversion
- Simplify code by removing lambda functions
Performance improvement:
- Response time reduced from ~0.5-1s to ~0.017s (30-60x faster)
- Especially beneficial for large files and multiple files
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add NodeFile to the schemas __init__.py exports to fix
import error when starting the server.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Enhance the node files API to include comprehensive file metadata:
- File size in bytes
- File creation time (ISO 8601 format)
- File modification time (ISO 8601 format)
- File extension
Create new NodeFile schema to support these additional fields
while keeping the existing ProjectFile schema for backward compatibility.
This provides users with better information to manage and identify
files in the Web UI.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implement issue #2719 - Add API endpoint to list project files
- Add GET /v3/projects/{project_id}/nodes/{node_id}/files endpoint
- Add list_node_files() method to Project class
- Add security checks to prevent path traversal
- Filter out .ghost temporary files
- Return file paths with MD5 checksums
- Require Node.Audit privilege
This allows users to discover dynamically created files
such as QEMU disk images created via the disk image API.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>