typedef ToolHandler = Future> Function(Map args); /// 工具常量 const _toolNameCreateCalendar = 'create_calendar_event'; const _defaultTimezone = 'Asia/Shanghai'; const _defaultEventColor = '#4F46E5'; const _defaultSourceType = 'agentGenerated'; const _titleMinLength = 1; const _titleMaxLength = 100; class ToolDefinition { final String name; final String description; final Map parameters; final ToolHandler handler; ToolDefinition({ required this.name, required this.description, required this.parameters, required this.handler, }); } class ToolRegistry { static final Map _tools = {}; static bool _initialized = false; static void initialize() { if (_initialized) return; _tools[_toolNameCreateCalendar] = ToolDefinition( name: _toolNameCreateCalendar, description: '创建一个日历事件或待办事项', parameters: { 'type': 'object', 'properties': { 'title': { 'type': 'string', 'description': '事件标题', 'minLength': _titleMinLength, 'maxLength': _titleMaxLength, }, 'description': {'type': 'string', 'description': '事件描述'}, 'startAt': { 'type': 'string', 'format': 'date-time', 'description': '开始时间 (ISO8601)', }, 'endAt': { 'type': 'string', 'format': 'date-time', 'description': '结束时间 (ISO8601)', }, 'timezone': {'type': 'string', 'default': _defaultTimezone}, 'location': {'type': 'string'}, 'notes': {'type': 'string'}, }, 'required': ['title', 'startAt'], }, handler: _handleCreateCalendarEvent, ); _initialized = true; } static Future> _handleCreateCalendarEvent( Map args, ) async { final eventId = 'evt_${DateTime.now().millisecondsSinceEpoch}'; return { 'eventId': eventId, 'ok': true, 'message': '日程已创建', 'title': args['title'], 'description': args['description'], 'startAt': args['startAt'], 'endAt': args['endAt'], 'timezone': args['timezone'] ?? _defaultTimezone, 'location': args['location'], 'color': _defaultEventColor, 'sourceType': _defaultSourceType, }; } static ToolDefinition? getTool(String name) => _tools[name]; static List getAllTools() => _tools.values.toList(); static Future> execute( String toolName, Map args, ) async { final tool = _tools[toolName]; if (tool == null) throw ToolNotFoundException('Tool not found: $toolName'); return tool.handler(args); } static ToolValidationResult validateArgs( String toolName, Map args, ) { final tool = _tools[toolName]; if (tool == null) { return ToolValidationResult( ok: false, error: 'Tool not found: $toolName', ); } final required = tool.parameters['required'] as List? ?? []; final missing = []; for (final field in required) { if (!args.containsKey(field) || args[field] == null) { missing.add(field as String); } } if (missing.isNotEmpty) { return ToolValidationResult( ok: false, error: 'Missing required fields: ${missing.join(', ')}', ); } return ToolValidationResult(ok: true); } } class ToolNotFoundException implements Exception { final String message; ToolNotFoundException(this.message); @override String toString() => 'ToolNotFoundException: $message'; } class ToolValidationResult { final bool ok; final String? error; ToolValidationResult({required this.ok, this.error}); }