3ac09475ad
- Add voice recording with transcribe endpoint (ASR) for multimodal input - Android: add RECORD_AUDIO and INTERNET permissions - Refactor tool naming: frontend tools use 'front.' prefix, backend tools use 'back.' - Migrate calendar tools: create_calendar_event -> back.mutate/list/delete events - Add calendar_event_list.v1 and calendar_operation.v1 UI card types - Update all Flutter and Python tests to match new tool naming conventions - Add record package dependency for voice recording
174 lines
5.3 KiB
Dart
174 lines
5.3 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:social_app/features/chat/data/ai/ai_decision_engine.dart';
|
|
|
|
void main() {
|
|
late AiDecisionEngine engine;
|
|
|
|
setUp(() {
|
|
engine = AiDecisionEngine();
|
|
});
|
|
|
|
group('matchIntent', () {
|
|
test('returns searchEvent for "今天有什么日程"', () {
|
|
expect(engine.matchIntent('今天有什么日程'), Intent.searchEvent);
|
|
});
|
|
|
|
test('returns searchEvent for "查看日程"', () {
|
|
expect(engine.matchIntent('查看日程'), Intent.searchEvent);
|
|
});
|
|
|
|
test('returns searchEvent for "查询安排"', () {
|
|
expect(engine.matchIntent('查询安排'), Intent.searchEvent);
|
|
});
|
|
|
|
test('returns createEvent for "提醒我明天开会"', () {
|
|
expect(engine.matchIntent('提醒我明天开会'), Intent.createEvent);
|
|
});
|
|
|
|
test('returns createEvent for "安排时间"', () {
|
|
expect(engine.matchIntent('安排时间'), Intent.createEvent);
|
|
});
|
|
|
|
test('returns createEvent for time pattern "明天10点"', () {
|
|
expect(engine.matchIntent('明天10点'), Intent.createEvent);
|
|
});
|
|
|
|
test('returns unknown for "你好"', () {
|
|
expect(engine.matchIntent('你好'), Intent.unknown);
|
|
});
|
|
|
|
test('returns unknown for random text', () {
|
|
expect(engine.matchIntent('随便说点什么'), Intent.unknown);
|
|
});
|
|
});
|
|
|
|
group('shouldTriggerToolCall', () {
|
|
test('returns false for "你好"', () {
|
|
expect(engine.shouldTriggerToolCall('你好'), false);
|
|
});
|
|
|
|
test('returns false for search intent', () {
|
|
expect(engine.shouldTriggerToolCall('今天有什么日程'), false);
|
|
});
|
|
|
|
test('returns true for create event intent', () {
|
|
expect(engine.shouldTriggerToolCall('提醒我明天开会'), true);
|
|
});
|
|
|
|
test('returns true for time pattern', () {
|
|
expect(engine.shouldTriggerToolCall('明天10点开会'), true);
|
|
});
|
|
});
|
|
|
|
group('tryExtractEventArgs', () {
|
|
test('returns map with title and startAt for "提醒我明天10点开会"', () {
|
|
final result = engine.tryExtractEventArgs('提醒我明天10点开会');
|
|
|
|
expect(result, isNotNull);
|
|
expect(result!['title'], isNotNull);
|
|
expect(result['startAt'], isNotNull);
|
|
expect(result['timezone'], 'Asia/Shanghai');
|
|
});
|
|
|
|
test('returns null for "你好"', () {
|
|
expect(engine.tryExtractEventArgs('你好'), isNull);
|
|
});
|
|
|
|
test('returns null for search intent', () {
|
|
expect(engine.tryExtractEventArgs('今天有什么日程'), isNull);
|
|
});
|
|
|
|
test('extracts title correctly', () {
|
|
final result = engine.tryExtractEventArgs('提醒我开会明天10点');
|
|
|
|
expect(result, isNotNull);
|
|
expect(result!['title'], contains('开会'));
|
|
});
|
|
|
|
test('parses today time correctly', () {
|
|
final result = engine.tryExtractEventArgs('开会今天14:30');
|
|
final now = DateTime.now();
|
|
|
|
expect(result, isNotNull);
|
|
final startAt = DateTime.parse(result!['startAt'] as String);
|
|
expect(startAt.year, now.year);
|
|
expect(startAt.month, now.month);
|
|
expect(startAt.day, now.day);
|
|
expect(startAt.hour, 14);
|
|
expect(startAt.minute, 30);
|
|
});
|
|
|
|
test('parses tomorrow time correctly', () {
|
|
final result = engine.tryExtractEventArgs('开会明天9点');
|
|
final now = DateTime.now();
|
|
final expectedTomorrow = DateTime(now.year, now.month, now.day + 1);
|
|
|
|
expect(result, isNotNull);
|
|
final startAt = DateTime.parse(result!['startAt'] as String);
|
|
expect(startAt.day, equals(expectedTomorrow.day));
|
|
expect(startAt.hour, 9);
|
|
expect(startAt.minute, 0);
|
|
});
|
|
});
|
|
|
|
group('tryForceTrigger', () {
|
|
test(
|
|
'returns ForceTriggerResult for "#tool:front.navigate_to_route {}"',
|
|
() {
|
|
final result = engine.tryForceTrigger(
|
|
'#tool:front.navigate_to_route {}',
|
|
);
|
|
|
|
expect(result, isNotNull);
|
|
expect(result!.toolName, 'front.navigate_to_route');
|
|
expect(result.args, isEmpty);
|
|
},
|
|
);
|
|
|
|
test(
|
|
'returns ForceTriggerResult with args for "#tool:custom {"key": "value"}"',
|
|
() {
|
|
final result = engine.tryForceTrigger('#tool:custom {"key": "value"}');
|
|
|
|
expect(result, isNotNull);
|
|
expect(result!.toolName, 'custom');
|
|
expect(result.args['key'], 'value');
|
|
},
|
|
);
|
|
|
|
test('returns null for normal text', () {
|
|
expect(engine.tryForceTrigger('普通文本'), isNull);
|
|
});
|
|
|
|
test('returns null for empty string', () {
|
|
expect(engine.tryForceTrigger(''), isNull);
|
|
});
|
|
|
|
test('handles invalid JSON gracefully', () {
|
|
final result = engine.tryForceTrigger('#tool:test {invalid json}');
|
|
|
|
expect(result, isNotNull);
|
|
expect(result!.toolName, 'test');
|
|
expect(result.args, isEmpty);
|
|
});
|
|
});
|
|
|
|
group('getToolCallArgs', () {
|
|
test('returns args for create event intent', () {
|
|
final result = engine.getToolCallArgs('提醒我明天10点开会');
|
|
|
|
expect(result, isNotNull);
|
|
expect(result!['title'], isNotNull);
|
|
expect(result['startAt'], isNotNull);
|
|
});
|
|
|
|
test('returns null for non-create intent', () {
|
|
expect(engine.getToolCallArgs('你好'), isNull);
|
|
});
|
|
|
|
test('returns null for search intent', () {
|
|
expect(engine.getToolCallArgs('今天有什么日程'), isNull);
|
|
});
|
|
});
|
|
}
|