fix(chat): fix ChatBloc event callback and test reliability

- Fix onEvent callback initialization in ChatBloc constructor
- Add MockAgUiService to isolate test from mock API behavior
- Remove unnecessary non-null assertions in tests
This commit is contained in:
qzl
2026-02-28 14:41:21 +08:00
parent 92781ddbbe
commit d37677c533
9 changed files with 254 additions and 217 deletions
@@ -1,6 +1,14 @@
typedef ToolHandler =
Future<Map<String, dynamic>> Function(Map<String, dynamic> 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;
@@ -22,8 +30,8 @@ class ToolRegistry {
static void initialize() {
if (_initialized) return;
_tools['create_calendar_event'] = ToolDefinition(
name: 'create_calendar_event',
_tools[_toolNameCreateCalendar] = ToolDefinition(
name: _toolNameCreateCalendar,
description: '创建一个日历事件或待办事项',
parameters: {
'type': 'object',
@@ -31,8 +39,8 @@ class ToolRegistry {
'title': {
'type': 'string',
'description': '事件标题',
'minLength': 1,
'maxLength': 100,
'minLength': _titleMinLength,
'maxLength': _titleMaxLength,
},
'description': {'type': 'string', 'description': '事件描述'},
'startAt': {
@@ -45,7 +53,7 @@ class ToolRegistry {
'format': 'date-time',
'description': '结束时间 (ISO8601)',
},
'timezone': {'type': 'string', 'default': 'Asia/Shanghai'},
'timezone': {'type': 'string', 'default': _defaultTimezone},
'location': {'type': 'string'},
'notes': {'type': 'string'},
},
@@ -69,10 +77,10 @@ class ToolRegistry {
'description': args['description'],
'startAt': args['startAt'],
'endAt': args['endAt'],
'timezone': args['timezone'] ?? 'Asia/Shanghai',
'timezone': args['timezone'] ?? _defaultTimezone,
'location': args['location'],
'color': '#4F46E5',
'sourceType': 'agentGenerated',
'color': _defaultEventColor,
'sourceType': _defaultSourceType,
};
}
@@ -93,17 +101,19 @@ class ToolRegistry {
Map<String, dynamic> args,
) {
final tool = _tools[toolName];
if (tool == null)
if (tool == null) {
return ToolValidationResult(
ok: false,
error: 'Tool not found: $toolName',
);
}
final required = tool.parameters['required'] as List<dynamic>? ?? [];
final missing = <String>[];
for (final field in required) {
if (!args.containsKey(field) || args[field] == null)
if (!args.containsKey(field) || args[field] == null) {
missing.add(field as String);
}
}
if (missing.isNotEmpty) {