feat(agent): add voice input capability and standardize tool naming

- 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
This commit is contained in:
zl-q
2026-03-09 00:10:09 +08:00
parent 6c83e35a69
commit 3ac09475ad
30 changed files with 1593 additions and 438 deletions
@@ -94,6 +94,61 @@ void main() {
expect(find.text('AI生成'), findsOneWidget);
});
testWidgets('calendar_card.v1 renders agent generated tag', (tester) async {
final card = UiCard(
cardType: 'calendar_card.v1',
data: CalendarCardData(
id: 'evt_001',
title: 'Meeting',
startAt: '2026-03-01T10:00:00Z',
sourceType: 'agent_generated',
).toJson(),
);
await tester.pumpWidget(
MaterialApp(home: Scaffold(body: UiSchemaRenderer.render(card))),
);
expect(find.text('AI生成'), findsOneWidget);
});
testWidgets('calendar_event_list.v1 renders list items', (tester) async {
final card = UiCard(
cardType: 'calendar_event_list.v1',
data: {
'items': [
{'id': 'evt_1', 'title': '晨会'},
{'id': 'evt_2', 'title': '评审'},
],
'pagination': {'page': 1, 'total': 2},
},
);
await tester.pumpWidget(
MaterialApp(home: Scaffold(body: UiSchemaRenderer.render(card))),
);
expect(find.text('日程列表'), findsOneWidget);
expect(find.text('晨会'), findsOneWidget);
expect(find.text('评审'), findsOneWidget);
});
testWidgets('calendar_operation.v1 renders operation message', (
tester,
) async {
final card = UiCard(
cardType: 'calendar_operation.v1',
data: {'operation': 'delete', 'ok': true, 'message': '日程已删除'},
);
await tester.pumpWidget(
MaterialApp(home: Scaffold(body: UiSchemaRenderer.render(card))),
);
expect(find.text('日程delete结果'), findsOneWidget);
expect(find.text('日程已删除'), findsOneWidget);
});
testWidgets('error_card.v1 renders error message', (tester) async {
final card = UiCard(
cardType: 'error_card.v1',