#!/usr/bin/env python # -*- coding: utf-8 -*- """ 脚本与任务系统集成模块 提供动态路由处理和VWED任务中脚本模块引用运行 """ import asyncio from typing import Dict, Any, Optional, Callable, List from fastapi import Request, HTTPException from fastapi.routing import APIRoute from services.script_registry_service import get_global_registry from services.script_engine_service import get_script_engine from services.task_service import get_task_service from utils.logger import get_logger logger = get_logger("services.script_task_integration") class DynamicRouteHandler: """动态路由处理器 - 处理脚本注册的API接口""" def __init__(self): self.registry = get_global_registry() self.script_engine = get_script_engine() async def handle_dynamic_route(self, request: Request) -> Dict[str, Any]: """处理动态路由请求""" try: # 获取请求信息 path = request.url.path method = request.method # 查找对应的API路由 route_key = f"{method}:{path}" route_info = self.registry.get_api_route(path, method) if not route_info: raise HTTPException( status_code=404, detail=f"API路由未找到: {method} {path}" ) # 检查脚本是否还在运行 script_id = route_info["script_id"] running_scripts = self.script_engine.get_running_scripts() script_running = any(s["script_id"] == script_id for s in running_scripts) if not script_running: raise HTTPException( status_code=503, detail=f"脚本 {script_id} 未运行,无法处理请求" ) # 获取请求数据 request_data = await self._extract_request_data(request) # 调用处理函数 start_time = asyncio.get_event_loop().time() handler = route_info["handler"] try: # 检查是否为异步函数 if asyncio.iscoroutinefunction(handler): result = await handler(request_data) else: result = handler(request_data) # 更新调用统计 response_time_ms = int((asyncio.get_event_loop().time() - start_time) * 1000) self.registry.update_api_call_stats(route_key, response_time_ms) return {"success": True, "data": result} except Exception as e: logger.error(f"API处理函数执行失败: {route_key} -> {e}", exc_info=True) raise HTTPException( status_code=500, detail=f"API处理失败: {str(e)}" ) except HTTPException: raise except Exception as e: logger.error(f"动态路由处理失败: {e}", exc_info=True) raise HTTPException( status_code=500, detail=f"路由处理失败: {str(e)}" ) async def _extract_request_data(self, request: Request) -> Dict[str, Any]: """提取请求数据""" try: # 获取查询参数 query_params = dict(request.query_params) # 获取路径参数 path_params = dict(request.path_params) # 获取请求体数据 body_data = {} if request.method in ["POST", "PUT", "PATCH"]: content_type = request.headers.get("content-type", "") if "application/json" in content_type: body_data = await request.json() elif "application/x-www-form-urlencoded" in content_type: form_data = await request.form() body_data = dict(form_data) return { "method": request.method, "path": request.url.path, "query_params": query_params, "path_params": path_params, "body": body_data, "headers": dict(request.headers), "client": request.client.host if request.client else None } except Exception as e: logger.error(f"提取请求数据失败: {e}", exc_info=True) return {} class ScriptTaskIntegration: """脚本任务集成服务""" def __init__(self): self.registry = get_global_registry() self.script_engine = get_script_engine() self.task_service = get_task_service() async def execute_script_function_from_task(self, function_name: str, function_args: Any, task_context: Dict[str, Any] = None) -> Dict[str, Any]: """从VWED任务中执行脚本函数""" try: # 查找函数信息 func_info = self.registry.get_function_info(function_name) if not func_info: return { "success": False, "error": f"函数 {function_name} 未注册" } script_id = func_info["script_id"] # 检查脚本是否还在运行 running_scripts = self.script_engine.get_running_scripts() script_running = any(s["script_id"] == script_id for s in running_scripts) if not script_running: return { "success": False, "error": f"脚本 {script_id} 未运行,无法执行函数" } # 执行函数 result = await self.script_engine.execute_script_function( script_id=script_id, function_name=function_name, function_args=function_args ) # 如果有任务上下文,记录执行结果 if task_context: await self._record_task_execution( task_context, function_name, function_args, result ) return result except Exception as e: logger.error(f"从任务执行脚本函数失败: {e}", exc_info=True) return { "success": False, "error": f"执行脚本函数失败: {str(e)}" } async def get_available_functions(self, tags: list = None) -> List[Dict[str, Any]]: """获取可用的脚本函数列表(供任务编辑器使用)""" try: all_registrations = self.registry.get_all_registrations() functions = all_registrations.get("registered_functions", {}) function_list = [] for func_name, func_info in functions.items(): # 检查脚本是否运行 script_id = func_info["script_id"] running_scripts = self.script_engine.get_running_scripts() is_running = any(s["script_id"] == script_id for s in running_scripts) # 标签筛选 if tags: func_tags = func_info.get("tags", []) if not any(tag in func_tags for tag in tags): continue function_info = { "function_name": func_name, "script_id": script_id, "description": func_info.get("description", ""), "parameters": func_info.get("parameters", []), "return_schema": func_info.get("return_schema", {}), "is_async": func_info.get("is_async", False), "tags": func_info.get("tags", []), "is_running": is_running, "stats": { "call_count": func_info.get("call_count", 0), "success_count": func_info.get("success_count", 0), "error_count": func_info.get("error_count", 0), "average_execution_time_ms": func_info.get("average_execution_time_ms") } } function_list.append(function_info) return function_list except Exception as e: logger.error(f"获取可用函数列表失败: {e}", exc_info=True) return [] async def register_script_block_handler(self): """注册脚本块处理器到现有任务系统""" try: # 这里需要根据现有的任务系统架构进行集成 # 扩展现有的 ScriptHandler 来支持动态函数调用 from services.execution.handlers.script import ScriptBlockHandler # 增强脚本处理器 original_execute = ScriptBlockHandler.execute async def enhanced_execute(self, block_config: Dict[str, Any], context) -> Dict[str, Any]: """增强的脚本执行方法""" try: # 检查是否为函数调用模式 if block_config.get("execution_mode") == "function_call": function_name = block_config.get("function_name") function_args = block_config.get("function_args", {}) if not function_name: return {"success": False, "error": "未指定函数名"} # 使用集成服务执行函数 integration = ScriptTaskIntegration() result = await integration.execute_script_function_from_task( function_name=function_name, function_args=function_args, task_context=context.to_dict() if hasattr(context, 'to_dict') else {} ) return result else: # 使用原始处理逻辑 return await original_execute(self, block_config, context) except Exception as e: logger.error(f"增强脚本处理器执行失败: {e}", exc_info=True) return {"success": False, "error": f"脚本执行失败: {str(e)}"} # 替换原始方法 ScriptBlockHandler.execute = enhanced_execute logger.info("脚本块处理器已增强,支持动态函数调用") except Exception as e: logger.error(f"注册脚本块处理器失败: {e}", exc_info=True) async def _record_task_execution(self, task_context: Dict[str, Any], function_name: str, function_args: Any, execution_result: Dict[str, Any]): """记录任务执行信息""" try: # 这里可以记录到任务执行日志或其他监控系统 logger.info(f"任务脚本函数执行: {function_name} -> {execution_result.get('success', False)}") except Exception as e: logger.error(f"记录任务执行信息失败: {e}", exc_info=True) # 全局集成服务实例 _task_integration = ScriptTaskIntegration() _route_handler = DynamicRouteHandler() def get_task_integration() -> ScriptTaskIntegration: """获取脚本任务集成服务实例""" return _task_integration def get_dynamic_route_handler() -> DynamicRouteHandler: """获取动态路由处理器实例""" return _route_handler