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
+33 -2
View File
@@ -194,7 +194,7 @@ void main() {
final json = {
'type': 'TOOL_CALL_START',
'toolCallId': 'tc_123',
'toolCallName': 'create_calendar_event',
'toolCallName': 'back.mutate_calendar_event',
'parentMessageId': 'msg_001',
};
@@ -203,7 +203,7 @@ void main() {
expect(event, isA<ToolCallStartEvent>());
final toolStart = event as ToolCallStartEvent;
expect(toolStart.toolCallId, 'tc_123');
expect(toolStart.toolCallName, 'create_calendar_event');
expect(toolStart.toolCallName, 'back.mutate_calendar_event');
expect(toolStart.parentMessageId, 'msg_001');
});
@@ -265,6 +265,37 @@ void main() {
expect(toolResult.result['eventId'], 'evt_001');
});
test('ToolCallResultEvent.ui parses from payload.ui', () {
final json = {
'type': 'TOOL_CALL_RESULT',
'messageId': 'msg_123',
'toolCallId': 'tc_123',
'content':
'{"ui":{"type":"calendar_card.v1","version":"v1","data":{"id":"evt_1","title":"会议","startAt":"2026-03-01T10:00:00Z"},"actions":[]}}',
};
final event = AgUiEvent.fromJson(json) as ToolCallResultEvent;
expect(event.ui, isNotNull);
expect(event.ui!.cardType, 'calendar_card.v1');
});
test(
'ToolCallResultEvent.ui parses from payload.result when result is UiCard',
() {
final json = {
'type': 'TOOL_CALL_RESULT',
'messageId': 'msg_123',
'toolCallId': 'tc_123',
'content':
'{"result":{"type":"calendar_operation.v1","version":"v1","data":{"operation":"delete","ok":true},"actions":[]}}',
};
final event = AgUiEvent.fromJson(json) as ToolCallResultEvent;
expect(event.ui, isNotNull);
expect(event.ui!.cardType, 'calendar_operation.v1');
},
);
test('parses ToolCallErrorEvent', () {
final json = {
'type': 'TOOL_CALL_ERROR',