"""Tool call dispatcher — maps tool names to handler functions.""" import asyncio from ._helpers import _truncate_response from .load_data import _handle_load_data from .profile import _handle_profile_data from .filter import _handle_filter_data from .preprocess import _handle_preprocess_data from .clustering import _handle_run_clustering, _handle_filter_and_cluster from .evaluate import _handle_evaluate_clustering from .features import _handle_extract_features from .export import _handle_export_results from .entities import _handle_build_entity_profiles, _handle_compute_scores from .anomalies import _handle_detect_anomalies, _handle_visualize_anomalies from .diagnostics import ( _handle_validate_data, _handle_explore_distributions, _handle_find_outliers, _handle_diagnose_clustering, _handle_compare_datasets, _handle_export_debug_sample, _handle_repair_schema, ) from .analysis import ( _handle_analyze_patterns, _handle_analyze_temporal, _handle_analyze_fft, _handle_analyze_tls_health, _handle_analyze_geo_distribution, _handle_analyze_entity_detail, ) from .data_mgmt import _handle_list_datasets, _handle_drop_dataset, _handle_clone_dataset from .distance_matrix import _handle_compute_distance_matrix async def handle_call(name: str, arguments: dict) -> dict: """Dispatch a tool call to the appropriate handler. Extracts the mandatory ``_timeout`` parameter (set by the LLM) from *arguments* and enforces it as an ``asyncio.wait_for`` deadline. Args: name: Tool name (must match one of the 30 tools). arguments: Tool-specific parameters, must include ``_timeout``. Returns: A JSON-serialisable dict. Raises: ValueError: If *name* is not a recognised tool. """ _handlers = { 'load_data': _handle_load_data, 'profile_data': _handle_profile_data, 'filter_data': _handle_filter_data, 'preprocess_data': _handle_preprocess_data, 'run_clustering': _handle_run_clustering, 'evaluate_clustering': _handle_evaluate_clustering, 'extract_features': _handle_extract_features, 'export_results': _handle_export_results, 'list_datasets': _handle_list_datasets, 'drop_dataset': _handle_drop_dataset, 'clone_dataset': _handle_clone_dataset, 'build_entity_profiles': _handle_build_entity_profiles, 'compute_scores': _handle_compute_scores, 'filter_and_cluster': _handle_filter_and_cluster, 'detect_anomalies': _handle_detect_anomalies, 'visualize_anomalies': _handle_visualize_anomalies, 'validate_data': _handle_validate_data, 'explore_distributions': _handle_explore_distributions, 'find_outliers': _handle_find_outliers, 'diagnose_clustering': _handle_diagnose_clustering, 'compare_datasets': _handle_compare_datasets, 'export_debug_sample': _handle_export_debug_sample, 'repair_schema': _handle_repair_schema, 'analyze_patterns': _handle_analyze_patterns, 'analyze_temporal': _handle_analyze_temporal, 'analyze_fft': _handle_analyze_fft, 'analyze_tls_health': _handle_analyze_tls_health, 'analyze_geo_distribution': _handle_analyze_geo_distribution, 'analyze_entity_detail': _handle_analyze_entity_detail, 'compute_distance_matrix': _handle_compute_distance_matrix, } handler = _handlers.get(name) if handler is None: raise ValueError(f"Unknown tool: '{name}'") # Extract mandatory _timeout from the LLM-provided arguments timeout = arguments.pop('_timeout', 0) cleaned_args = arguments # _timeout already removed by pop # Execute the handler with optional timeout if timeout and timeout > 0: try: result = await asyncio.wait_for( handler(**cleaned_args), timeout=timeout, ) except asyncio.TimeoutError: result = {'error': f'工具 {name} 执行超时 ({timeout}秒)'} else: result = await handler(**cleaned_args) # Always ensure truncated key exists if 'truncated' not in result: result['truncated'] = False return _truncate_response(result)