100 lines
4.1 KiB
Python
100 lines
4.1 KiB
Python
"""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)
|