Coverage for aipyapp/cli/cli_agent.py: 0%
150 statements
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-11 12:02 +0200
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-11 12:02 +0200
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
4from typing import Dict, Any, Optional
5from datetime import datetime
7import uvicorn
8from fastapi import FastAPI, HTTPException, BackgroundTasks
9from pydantic import BaseModel, Field
11from loguru import logger
13from .. import T, __version__
14from ..aipy.agent_taskmgr import AgentTaskManager
15from ..display import DisplayManager
17# API 数据模型
18class TaskRequest(BaseModel):
19 instruction: str = Field(..., description="任务指令")
20 metadata: Optional[Dict[str, Any]] = Field(default=None, description="任务元数据")
22class TaskResponse(BaseModel):
23 task_id: str = Field(..., description="任务ID")
24 status: str = Field(..., description="任务状态")
25 message: str = Field(..., description="响应消息")
27class TaskStatusResponse(BaseModel):
28 task_id: str
29 instruction: str
30 status: str
31 created_at: str
32 started_at: Optional[str]
33 completed_at: Optional[str]
34 error: Optional[str]
36class TaskResultResponse(BaseModel):
37 task_id: str
38 instruction: str
39 status: str
40 created_at: str
41 started_at: Optional[str]
42 completed_at: Optional[str]
43 error: Optional[str]
44 output: Optional[Dict[str, Any]]
46# 全局变量
47agent_manager: Optional[AgentTaskManager] = None
48app = FastAPI(
49 title="AIPython Agent API",
50 description="HTTP API for n8n integration with AIPython",
51 version=__version__
52)
54@app.on_event("startup")
55async def startup_event():
56 """应用启动时初始化"""
57 logger.info("Starting AIPython Agent API server...")
59@app.on_event("shutdown")
60async def shutdown_event():
61 """应用关闭时清理"""
62 logger.info("Shutting down AIPython Agent API server...")
63 if agent_manager and hasattr(agent_manager, 'executor'):
64 agent_manager.executor.shutdown(wait=True)
66@app.get("/", response_model=Dict[str, str])
67async def root():
68 """根路径 - API信息"""
69 return {
70 "name": "AIPython Agent API",
71 "version": __version__,
72 "status": "running",
73 "timestamp": datetime.now().isoformat(),
74 "endpoints": {
75 "submit_task": "POST /tasks",
76 "get_task_status": "GET /tasks/{task_id}",
77 "get_task_result": "GET /tasks/{task_id}/result",
78 "list_tasks": "GET /tasks",
79 "cancel_task": "DELETE /tasks/{task_id}",
80 "health": "GET /health"
81 }
82 }
84@app.get("/health")
85async def health_check():
86 """健康检查"""
87 return {
88 "status": "healthy",
89 "timestamp": datetime.now().isoformat(),
90 "agent_manager": "initialized" if agent_manager else "not_initialized"
91 }
93@app.post("/tasks", response_model=TaskResponse)
94async def submit_task(task_request: TaskRequest, background_tasks: BackgroundTasks):
95 """提交新任务"""
96 if not agent_manager:
97 raise HTTPException(status_code=500, detail="Agent manager not initialized")
99 try:
100 # 提交任务
101 task_id = await agent_manager.submit_task(
102 instruction=task_request.instruction,
103 metadata=task_request.metadata
104 )
106 # 在后台执行任务
107 background_tasks.add_task(execute_task_background, task_id)
109 return TaskResponse(
110 task_id=task_id,
111 status="pending",
112 message="Task submitted successfully"
113 )
115 except Exception as e:
116 logger.error(f"Failed to submit task: {e}")
117 raise HTTPException(status_code=500, detail=str(e))
119async def execute_task_background(task_id: str):
120 """后台执行任务"""
121 try:
122 await agent_manager.execute_task(task_id)
123 logger.info(f"Task {task_id} completed")
124 except Exception as e:
125 logger.error(f"Task {task_id} failed: {e}")
127@app.get("/tasks/{task_id}", response_model=TaskStatusResponse)
128async def get_task_status(task_id: str):
129 """获取任务状态"""
130 if not agent_manager:
131 raise HTTPException(status_code=500, detail="Agent manager not initialized")
133 try:
134 task_data = await agent_manager.get_task_status(task_id)
135 return TaskStatusResponse(**task_data)
136 except ValueError as e:
137 raise HTTPException(status_code=404, detail=str(e))
138 except Exception as e:
139 logger.error(f"Failed to get task status: {e}")
140 raise HTTPException(status_code=500, detail=str(e))
142@app.get("/tasks/{task_id}/result", response_model=TaskResultResponse)
143async def get_task_result(task_id: str):
144 """获取任务结果"""
145 if not agent_manager:
146 raise HTTPException(status_code=500, detail="Agent manager not initialized")
148 try:
149 result = await agent_manager.get_task_result(task_id)
150 return TaskResultResponse(**result)
151 except ValueError as e:
152 raise HTTPException(status_code=404, detail=str(e))
153 except Exception as e:
154 logger.error(f"Failed to get task result: {e}")
155 raise HTTPException(status_code=500, detail=str(e))
157@app.get("/tasks")
158async def list_tasks():
159 """列出所有任务"""
160 if not agent_manager:
161 raise HTTPException(status_code=500, detail="Agent manager not initialized")
163 try:
164 tasks = await agent_manager.list_tasks()
165 return {"tasks": tasks}
166 except Exception as e:
167 logger.error(f"Failed to list tasks: {e}")
168 raise HTTPException(status_code=500, detail=str(e))
170@app.delete("/tasks/{task_id}")
171async def cancel_task(task_id: str):
172 """取消任务"""
173 if not agent_manager:
174 raise HTTPException(status_code=500, detail="Agent manager not initialized")
176 try:
177 success = await agent_manager.cancel_task(task_id)
178 if success:
179 return {"message": f"Task {task_id} cancelled"}
180 else:
181 raise HTTPException(status_code=400, detail="Task cannot be cancelled")
182 except Exception as e:
183 logger.error(f"Failed to cancel task: {e}")
184 raise HTTPException(status_code=500, detail=str(e))
186@app.post("/admin/cleanup")
187async def cleanup_tasks(max_age_hours: int = 24):
188 """清理完成的任务"""
189 if not agent_manager:
190 raise HTTPException(status_code=500, detail="Agent manager not initialized")
192 try:
193 cleaned_count = agent_manager.cleanup_completed_tasks(max_age_hours)
194 return {"message": f"Cleaned up {cleaned_count} tasks"}
195 except Exception as e:
196 logger.error(f"Failed to cleanup tasks: {e}")
197 raise HTTPException(status_code=500, detail=str(e))
199def init_agent_manager(settings):
200 """初始化Agent管理器"""
201 global agent_manager
202 try:
203 display_config = {'style': 'agent', 'quiet': True}
204 display_manager = DisplayManager(display_config)
205 agent_manager = AgentTaskManager(settings, display_manager=display_manager)
206 logger.info("Agent manager initialized successfully")
207 return True
208 except Exception as e:
209 logger.error(f"Failed to initialize agent manager: {e}")
210 return False
212def main(settings):
213 """Agent模式主函数"""
214 global agent_manager
216 host = settings.get('host', '127.0.0.1')
217 port = settings.get('port', 8848)
218 print(f"🤖 AIPython Agent Mode ({__version__})")
219 print(f"🚀 Starting HTTP API server on {host}:{port}")
221 # 初始化Agent管理器
222 if not init_agent_manager(settings):
223 print(f"❌ {T('Failed to initialize agent manager')}")
224 return
226 print(f"✅ {T('Agent manager initialized')}")
227 print(f"🔗 API Documentation: http://{host}:{port}/docs")
228 print(f"📊 Health Check: http://{host}:{port}/health")
230 # 启动服务器
231 try:
232 uvicorn.run(
233 app,
234 host=host,
235 port=port,
236 log_level="info" if settings.get('debug', False) else "warning"
237 )
238 except KeyboardInterrupt:
239 print(f"\n⏹️ {T('Server stopped by user')}")
240 except Exception as e:
241 print(f"❌ {T('Server error')}: {e}")
242 logger.error(f"Server error: {e}")