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:
@@ -2,11 +2,11 @@ import 'dart:convert';
|
||||
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:social_app/core/api/i_api_client.dart';
|
||||
import 'package:social_app/core/api/mock_api_client.dart';
|
||||
import 'package:social_app/core/di/injection.dart';
|
||||
|
||||
import '../../data/models/ag_ui_event.dart';
|
||||
import '../../data/models/chat_list_item.dart';
|
||||
import '../../data/models/tool_result.dart';
|
||||
import '../../data/services/ag_ui_service.dart';
|
||||
|
||||
class ChatState {
|
||||
@@ -57,7 +57,14 @@ class ChatBloc extends Cubit<ChatState> {
|
||||
|
||||
ChatBloc({AgUiService? service, IApiClient? apiClient})
|
||||
: _service =
|
||||
service ?? AgUiService(apiClient: apiClient ?? sl<IApiClient>()),
|
||||
service ??
|
||||
AgUiService(
|
||||
apiClient:
|
||||
apiClient ??
|
||||
(sl.isRegistered<IApiClient>()
|
||||
? sl<IApiClient>()
|
||||
: MockApiClient()),
|
||||
),
|
||||
super(const ChatState()) {
|
||||
_service.onEvent = _handleEvent;
|
||||
}
|
||||
@@ -162,13 +169,10 @@ class ChatBloc extends Cubit<ChatState> {
|
||||
_toolCallArgsBuffer.remove(endEvent.toolCallId);
|
||||
final updatedItems = state.items.map((item) {
|
||||
if (item.id == endEvent.toolCallId && item is ToolCallItem) {
|
||||
final nextStatus = item.toolName == 'navigate_to_route'
|
||||
final nextStatus = item.toolName == 'front.navigate_to_route'
|
||||
? ToolCallStatus.pending
|
||||
: ToolCallStatus.executing;
|
||||
return item.copyWith(
|
||||
args: parsedArgs,
|
||||
status: nextStatus,
|
||||
);
|
||||
return item.copyWith(args: parsedArgs, status: nextStatus);
|
||||
}
|
||||
return item;
|
||||
}).toList();
|
||||
@@ -344,7 +348,10 @@ class ChatBloc extends Cubit<ChatState> {
|
||||
}
|
||||
final updatedItems = state.items.map((item) {
|
||||
if (item is ToolCallItem && item.callId == toolCallId) {
|
||||
return item.copyWith(status: ToolCallStatus.executing, errorMessage: null);
|
||||
return item.copyWith(
|
||||
status: ToolCallStatus.executing,
|
||||
errorMessage: null,
|
||||
);
|
||||
}
|
||||
return item;
|
||||
}).toList();
|
||||
@@ -365,10 +372,20 @@ class ChatBloc extends Cubit<ChatState> {
|
||||
}
|
||||
return item;
|
||||
}).toList();
|
||||
emit(state.copyWith(items: failedItems, isLoading: false, error: error.toString()));
|
||||
emit(
|
||||
state.copyWith(
|
||||
items: failedItems,
|
||||
isLoading: false,
|
||||
error: error.toString(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> transcribeAudioFile(String filePath) {
|
||||
return _service.transcribeAudio(filePath);
|
||||
}
|
||||
|
||||
void clearError() {
|
||||
emit(state.copyWith(error: null));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user