2026-03-07 17:30:20 +08:00
|
|
|
import 'route_navigation_tool.dart';
|
|
|
|
|
|
2026-02-28 13:36:30 +08:00
|
|
|
typedef ToolHandler =
|
|
|
|
|
Future<Map<String, dynamic>> Function(Map<String, dynamic> args);
|
|
|
|
|
|
2026-02-28 14:41:21 +08:00
|
|
|
/// 工具常量
|
2026-03-09 00:10:09 +08:00
|
|
|
const _toolNameNavigateRoute = 'front.navigate_to_route';
|
2026-02-28 14:41:21 +08:00
|
|
|
|
2026-02-28 13:36:30 +08:00
|
|
|
class ToolDefinition {
|
|
|
|
|
final String name;
|
|
|
|
|
final String description;
|
|
|
|
|
final Map<String, dynamic> parameters;
|
|
|
|
|
final ToolHandler handler;
|
|
|
|
|
|
|
|
|
|
ToolDefinition({
|
|
|
|
|
required this.name,
|
|
|
|
|
required this.description,
|
|
|
|
|
required this.parameters,
|
|
|
|
|
required this.handler,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ToolRegistry {
|
|
|
|
|
static final Map<String, ToolDefinition> _tools = {};
|
|
|
|
|
static bool _initialized = false;
|
|
|
|
|
|
|
|
|
|
static void initialize() {
|
|
|
|
|
if (_initialized) return;
|
|
|
|
|
|
2026-03-07 17:30:20 +08:00
|
|
|
_tools[_toolNameNavigateRoute] = ToolDefinition(
|
|
|
|
|
name: _toolNameNavigateRoute,
|
|
|
|
|
description: '在前端执行路由跳转',
|
|
|
|
|
parameters: {
|
|
|
|
|
'type': 'object',
|
|
|
|
|
'properties': {
|
|
|
|
|
'target': {'type': 'string', 'description': '跳转目标路由'},
|
|
|
|
|
'replace': {'type': 'boolean', 'description': '是否 replace 导航'},
|
|
|
|
|
},
|
|
|
|
|
'required': ['target'],
|
|
|
|
|
},
|
|
|
|
|
handler: _handleNavigateRoute,
|
|
|
|
|
);
|
|
|
|
|
|
2026-02-28 13:36:30 +08:00
|
|
|
_initialized = true;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-07 17:30:20 +08:00
|
|
|
static Future<Map<String, dynamic>> _handleNavigateRoute(
|
|
|
|
|
Map<String, dynamic> args,
|
|
|
|
|
) async {
|
|
|
|
|
return RouteNavigationTool.instance.execute(args);
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-28 13:36:30 +08:00
|
|
|
static ToolDefinition? getTool(String name) => _tools[name];
|
|
|
|
|
static List<ToolDefinition> getAllTools() => _tools.values.toList();
|
|
|
|
|
|
|
|
|
|
static Future<Map<String, dynamic>> execute(
|
|
|
|
|
String toolName,
|
|
|
|
|
Map<String, dynamic> 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<String, dynamic> args,
|
|
|
|
|
) {
|
|
|
|
|
final tool = _tools[toolName];
|
2026-02-28 14:41:21 +08:00
|
|
|
if (tool == null) {
|
2026-02-28 13:36:30 +08:00
|
|
|
return ToolValidationResult(
|
|
|
|
|
ok: false,
|
|
|
|
|
error: 'Tool not found: $toolName',
|
|
|
|
|
);
|
2026-02-28 14:41:21 +08:00
|
|
|
}
|
2026-02-28 13:36:30 +08:00
|
|
|
|
|
|
|
|
final required = tool.parameters['required'] as List<dynamic>? ?? [];
|
|
|
|
|
final missing = <String>[];
|
|
|
|
|
for (final field in required) {
|
2026-02-28 14:41:21 +08:00
|
|
|
if (!args.containsKey(field) || args[field] == null) {
|
2026-02-28 13:36:30 +08:00
|
|
|
missing.add(field as String);
|
2026-02-28 14:41:21 +08:00
|
|
|
}
|
2026-02-28 13:36:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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});
|
|
|
|
|
}
|