diff --git a/gns3server/agent/gns3_copilot/gns3_client/api_handlers.py b/gns3server/agent/gns3_copilot/gns3_client/api_handlers.py index b0934c201..4f7105881 100644 --- a/gns3server/agent/gns3_copilot/gns3_client/api_handlers.py +++ b/gns3server/agent/gns3_copilot/gns3_client/api_handlers.py @@ -162,14 +162,14 @@ def build_gns3_ctx(jwt_token: str | None = None, url: str | None = None) -> dict } -def _filter_node_response(node: dict, fields: list[str] = None) -> dict: +def _filter_node_response(node: dict, fields: list[str] | None = None) -> dict: """Filter node response to only include requested fields.""" if not fields: fields = ["node_id", "name", "node_type", "status", "console"] return {k: node[k] for k in fields if k in node} -def _filter_link_response(link: dict, fields: list[str] = None) -> dict: +def _filter_link_response(link: dict, fields: list[str] | None = None) -> dict: """Filter link response to only include requested fields.""" if not fields: fields = LINK_DEFAULT_FIELDS @@ -332,7 +332,7 @@ def suspend_node_handler(params: dict[str, Any], gns3_ctx: dict[str, Any]) -> di return {"message": f"Node {node_id} suspended", "node_id": node_id} -def create_node_handler(params: dict[str, Any], gns3_ctx: dict[str, Any]) -> dict[str, Any]: +def create_node_handler(params: dict[str, Any], gns3_ctx: dict[str, Any]) -> dict[str, Any] | list[dict[str, Any]]: project_id = params.get("project_id") if not project_id: @@ -401,7 +401,7 @@ def create_node_handler(params: dict[str, Any], gns3_ctx: dict[str, Any]) -> dic return _filter_node_response(resp, fields) -def delete_node_handler(params: dict[str, Any], gns3_ctx: dict[str, Any]) -> dict[str, Any]: +def delete_node_handler(params: dict[str, Any], gns3_ctx: dict[str, Any]) -> dict[str, Any] | list[dict[str, Any]]: project_id = params.get("project_id") if not project_id: return {"error": "project_id is required"} @@ -706,7 +706,7 @@ def available_filters_handler(params: dict[str, Any], gns3_ctx: dict[str, Any]) return conn.http_call("get", url).json() -def create_link_handler(params: dict[str, Any], gns3_ctx: dict[str, Any]) -> dict[str, Any]: +def create_link_handler(params: dict[str, Any], gns3_ctx: dict[str, Any]) -> dict[str, Any] | list[dict[str, Any]]: project_id = params.get("project_id") if not project_id: return {"error": "project_id is required"} @@ -762,7 +762,7 @@ def create_link_handler(params: dict[str, Any], gns3_ctx: dict[str, Any]) -> dic return _filter_link_response(resp, fields) -def delete_link_handler(params: dict[str, Any], gns3_ctx: dict[str, Any]) -> dict[str, Any]: +def delete_link_handler(params: dict[str, Any], gns3_ctx: dict[str, Any]) -> dict[str, Any] | list[dict[str, Any]]: project_id = params.get("project_id") if not project_id: return {"error": "project_id is required"} @@ -809,7 +809,7 @@ def update_link_handler(params: dict[str, Any], gns3_ctx: dict[str, Any]) -> dic # ── Link capture / reset handlers ────────────────────────────────────── -def reset_link_handler(params: dict[str, Any], gns3_ctx: dict[str, Any]) -> dict[str, Any]: +def reset_link_handler(params: dict[str, Any], gns3_ctx: dict[str, Any]) -> dict[str, Any] | list[dict[str, Any]]: project_id = params.get("project_id") if not project_id: return {"error": "project_id is required"} diff --git a/gns3server/agent/gns3_copilot/tools_v2/gns3_create_link.py b/gns3server/agent/gns3_copilot/tools_v2/gns3_create_link.py index 8f926586b..ff11c6a44 100644 --- a/gns3server/agent/gns3_copilot/tools_v2/gns3_create_link.py +++ b/gns3server/agent/gns3_copilot/tools_v2/gns3_create_link.py @@ -222,6 +222,8 @@ class GNS3LinkTool(BaseTool): }, gns3_ctx, ) + if isinstance(link_resp, list): + raise RuntimeError("Unexpected batch response when creating a single link") if "error" in link_resp: raise RuntimeError(link_resp["error"]) diff --git a/gns3server/agent/gns3_copilot/tools_v2/gns3_create_node.py b/gns3server/agent/gns3_copilot/tools_v2/gns3_create_node.py index a511de21f..bdbc0bf42 100644 --- a/gns3server/agent/gns3_copilot/tools_v2/gns3_create_node.py +++ b/gns3server/agent/gns3_copilot/tools_v2/gns3_create_node.py @@ -230,6 +230,8 @@ class GNS3CreateNodeTool(BaseTool): }, gns3_ctx, ) + if isinstance(created, list): + raise RuntimeError("Unexpected batch response when creating a single node") if "error" in created: raise RuntimeError(created["error"]) node_info = { diff --git a/pyproject.toml b/pyproject.toml index a2e9c2872..ee860c022 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -296,7 +296,6 @@ enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"] module = [ "gns3server.agent.gns3_copilot.agent.context_manager", # 5 "gns3server.agent.gns3_copilot.agent.model_factory", # 4 - "gns3server.agent.gns3_copilot.gns3_client.api_handlers", # 10 "gns3server.agent.gns3_copilot.gns3_client.connector_factory", # 1 "gns3server.agent.gns3_copilot.gns3_client.project_inventory", # 2 "gns3server.agent.gns3_copilot.skills.loader", # 1