diff --git a/.idea/AI-powered-switches.iml b/.idea/AI-powered-switches.iml
index a1bf3bb..b5db305 100644
--- a/.idea/AI-powered-switches.iml
+++ b/.idea/AI-powered-switches.iml
@@ -9,7 +9,7 @@
-
+
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 1d3ce46..0ce539e 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -3,5 +3,5 @@
-
+
\ No newline at end of file
diff --git a/src/backend/app/api/endpoints.py b/src/backend/app/api/endpoints.py
index e2dd6fd..44e75fa 100644
--- a/src/backend/app/api/endpoints.py
+++ b/src/backend/app/api/endpoints.py
@@ -126,6 +126,40 @@ async def apply_config(request: ConfigRequest):
status_code=500,
detail=f"Failed to apply config: {str(e)}"
)
+
+
+class CLICommandRequest(BaseModel):
+ switch_ip: str
+ commands: List[str] # 前端生成的CLI命令列表
+ is_ensp: bool = False # 是否为eNSP模拟器模式
+
+
+@router.post("/execute_cli_commands", response_model=dict)
+async def execute_cli_commands(request: CLICommandRequest):
+ """
+ 执行前端生成的CLI命令
+ """
+ try:
+ configurator = SwitchConfigurator(
+ username=settings.SWITCH_USERNAME,
+ password=settings.SWITCH_PASSWORD,
+ timeout=settings.SWITCH_TIMEOUT,
+ ensp_mode=request.is_ensp
+ )
+
+ # 直接发送命令到交换机
+ result = await configurator.execute_raw_commands(
+ ip=request.switch_ip,
+ commands=request.commands
+ )
+ return {
+ "success": True,
+ "output": result,
+ "mode": "eNSP" if request.is_ensp else "SSH"
+ }
+ except Exception as e:
+ raise HTTPException(500, detail=str(e))
+
@router.get("/traffic/interfaces", summary="获取所有网络接口")
async def get_network_interfaces():
return {
diff --git a/src/backend/app/api/network_config.py b/src/backend/app/api/network_config.py
index 54cce3b..edd2371 100644
--- a/src/backend/app/api/network_config.py
+++ b/src/backend/app/api/network_config.py
@@ -179,6 +179,13 @@ class SwitchConfigurator:
except Exception as e:
raise SSHConnectionException(f"连接异常: {str(e)}")
+ async def execute_raw_commands(self, ip: str, commands: List[str]) -> str:
+ """
+ 执行原始CLI命令
+ """
+ return await self._send_commands(ip, commands)
+
+
@staticmethod
def _generate_standard_commands(config: SwitchConfig) -> List[str]:
"""生成标准CLI命令"""
@@ -242,6 +249,7 @@ class SwitchConfigurator:
logging.error(f"恢复失败: {str(e)}")
return False
+
@retry(
stop=stop_after_attempt(2),
wait=wait_exponential(multiplier=1, min=4, max=10)
diff --git a/src/backend/app/services/ai_services.py b/src/backend/app/services/ai_services.py
index 8953941..442efae 100644
--- a/src/backend/app/services/ai_services.py
+++ b/src/backend/app/services/ai_services.py
@@ -1,4 +1,6 @@
from typing import Dict, Any, Coroutine
+
+import httpx
from openai import OpenAI
import json
from src.backend.app.utils.exceptions import SiliconFlowAPIException
@@ -12,7 +14,8 @@ class AIService:
self.api_url = api_url
self.client = OpenAI(
api_key=self.api_key,
- base_url=self.api_url
+ base_url=self.api_url,
+ # timeout=httpx.Timeout(30.0)
)
async def parse_command(self, command: str) -> Any | None:
diff --git a/src/backend/requirements.txt b/src/backend/requirements.txt
index 880ac77..3febf22 100644
--- a/src/backend/requirements.txt
+++ b/src/backend/requirements.txt
@@ -4,12 +4,12 @@ python-dotenv==1.0.1
pysnmp
pydantic==2.6.4
pydantic-settings==2.2.1
-
+openai==1.93.2
asyncssh==2.14.2
telnetlib3==2.0.3
httpx==0.27.0
python-nmap==0.7.1
-
+pysnmp==7.1.21
aiofiles==23.2.1
loguru==0.7.2