|
|
@ -1,25 +1,21 @@ |
|
|
import 'dart:async'; |
|
|
import 'dart:async'; |
|
|
import 'dart:convert'; |
|
|
import 'dart:convert'; |
|
|
import 'dart:ffi'; |
|
|
|
|
|
import 'dart:io'; |
|
|
import 'dart:io'; |
|
|
import 'package:amap_service/amap_service.dart'; |
|
|
import 'package:amap_service/amap_service.dart'; |
|
|
import 'package:http/http.dart' as http; |
|
|
|
|
|
import 'package:package_info_plus/package_info_plus.dart'; |
|
|
import 'package:package_info_plus/package_info_plus.dart'; |
|
|
import 'package:url_launcher/url_launcher.dart'; |
|
|
import 'package:url_launcher/url_launcher.dart'; |
|
|
|
|
|
import 'package:uuid/uuid.dart'; |
|
|
import 'package:voitrans/data/models/appconfig.dart'; |
|
|
import 'package:voitrans/data/models/appconfig.dart'; |
|
|
import 'package:voitrans/data/models/song_model.dart'; |
|
|
import 'package:voitrans/data/models/song_model.dart'; |
|
|
import 'package:voitrans/data/services/ble_manager.dart'; |
|
|
import 'package:voitrans/data/services/ble_manager.dart'; |
|
|
import 'package:voitrans/data/services/bluetooth_manager.dart'; |
|
|
import 'package:voitrans/data/services/bluetooth_manager.dart'; |
|
|
import 'package:voitrans/data/services/qq_music.dart'; |
|
|
import 'package:voitrans/data/services/qq_music.dart'; |
|
|
import 'package:flutter_intro/flutter_intro.dart'; |
|
|
import 'package:flutter_intro/flutter_intro.dart'; |
|
|
import '../../../data/services/ble_manager.dart'; |
|
|
|
|
|
import '../../../data/services/bluetooth_manager.dart'; |
|
|
|
|
|
import '../../../data/services/novice_guide_service.dart'; |
|
|
import '../../../data/services/novice_guide_service.dart'; |
|
|
import '/core/utils/upload_oss.dart'; |
|
|
import '/core/utils/upload_oss.dart'; |
|
|
import '/data/models/user_Info.dart'; |
|
|
import '/data/models/user_Info.dart'; |
|
|
import '/data/services/music_manager.dart'; |
|
|
import '/data/services/music_manager.dart'; |
|
|
import '/data/services/navigation_manager.dart'; |
|
|
import '/data/services/navigation_manager.dart'; |
|
|
import '/data/services/network/api.dart'; |
|
|
|
|
|
import 'package:ble_service/ble_service.dart'; |
|
|
import 'package:ble_service/ble_service.dart'; |
|
|
import 'package:flutter/material.dart'; |
|
|
import 'package:flutter/material.dart'; |
|
|
import 'package:get/get.dart'; |
|
|
import 'package:get/get.dart'; |
|
|
@ -46,6 +42,7 @@ class AgentController extends GetxController with WidgetsBindingObserver { |
|
|
|
|
|
|
|
|
// 聊天消息列表 |
|
|
// 聊天消息列表 |
|
|
final messages = <Message>[].obs; |
|
|
final messages = <Message>[].obs; |
|
|
|
|
|
final currsessionid = ''.obs; |
|
|
|
|
|
|
|
|
// UI控制器 |
|
|
// UI控制器 |
|
|
final TextEditingController textController = TextEditingController(); |
|
|
final TextEditingController textController = TextEditingController(); |
|
|
@ -138,7 +135,7 @@ class AgentController extends GetxController with WidgetsBindingObserver { |
|
|
final TAG = 'AgentController'; |
|
|
final TAG = 'AgentController'; |
|
|
var AppDir = "".obs; |
|
|
var AppDir = "".obs; |
|
|
// 会话ID |
|
|
// 会话ID |
|
|
final String sessionId = 'default_agent'; |
|
|
final String agentId = 'default_agent'; |
|
|
|
|
|
|
|
|
// 分页加载相关状态 |
|
|
// 分页加载相关状态 |
|
|
final isLoadingMore = false.obs; // 是否正在加载更多消息 |
|
|
final isLoadingMore = false.obs; // 是否正在加载更多消息 |
|
|
@ -312,7 +309,7 @@ class AgentController extends GetxController with WidgetsBindingObserver { |
|
|
Logger.i(TAG, '正在加载聊天历史...'); |
|
|
Logger.i(TAG, '正在加载聊天历史...'); |
|
|
//通过本地插件ChatStorage获取聊天记录 |
|
|
//通过本地插件ChatStorage获取聊天记录 |
|
|
final result = await ChatStorage.getMessages( |
|
|
final result = await ChatStorage.getMessages( |
|
|
sessionId: sessionId, //会话ID |
|
|
agentId: agentId, //会话ID |
|
|
page: 1, //从第一页开始 |
|
|
page: 1, //从第一页开始 |
|
|
pageSize: pageSize, //每页20条记录 |
|
|
pageSize: pageSize, //每页20条记录 |
|
|
); |
|
|
); |
|
|
@ -367,7 +364,7 @@ class AgentController extends GetxController with WidgetsBindingObserver { |
|
|
Logger.i(TAG, '正在加载第 $nextPage 页历史消息...'); |
|
|
Logger.i(TAG, '正在加载第 $nextPage 页历史消息...'); |
|
|
|
|
|
|
|
|
final result = await ChatStorage.getMessages( |
|
|
final result = await ChatStorage.getMessages( |
|
|
sessionId: sessionId, |
|
|
agentId: agentId, |
|
|
page: nextPage, |
|
|
page: nextPage, |
|
|
pageSize: pageSize, |
|
|
pageSize: pageSize, |
|
|
); |
|
|
); |
|
|
@ -421,6 +418,7 @@ class AgentController extends GetxController with WidgetsBindingObserver { |
|
|
: null; |
|
|
: null; |
|
|
|
|
|
|
|
|
return Message( |
|
|
return Message( |
|
|
|
|
|
sessionid: msg.sessionId, // 会话ID |
|
|
isUser: msg.sender == 'user', |
|
|
isUser: msg.sender == 'user', |
|
|
text: msg.message, |
|
|
text: msg.message, |
|
|
meta: meta, |
|
|
meta: meta, |
|
|
@ -488,6 +486,7 @@ class AgentController extends GetxController with WidgetsBindingObserver { |
|
|
// 添加初始欢迎消息 |
|
|
// 添加初始欢迎消息 |
|
|
void _addWelcomeMessage() { |
|
|
void _addWelcomeMessage() { |
|
|
messages.add(Message( |
|
|
messages.add(Message( |
|
|
|
|
|
sessionid: "", // 会话ID |
|
|
isUser: false, |
|
|
isUser: false, |
|
|
text: 'welcomeMessage'.tr, // 你好!我是**小言**,我能帮你: |
|
|
text: 'welcomeMessage'.tr, // 你好!我是**小言**,我能帮你: |
|
|
)); |
|
|
)); |
|
|
@ -504,6 +503,7 @@ class AgentController extends GetxController with WidgetsBindingObserver { |
|
|
// isTextInputMode.refresh(); |
|
|
// isTextInputMode.refresh(); |
|
|
// 只标记识别开始,不添加消息 |
|
|
// 只标记识别开始,不添加消息 |
|
|
Logger.i(TAG, '识别开始'); |
|
|
Logger.i(TAG, '识别开始'); |
|
|
|
|
|
|
|
|
break; |
|
|
break; |
|
|
case AgentServiceEventType.recognitionStopped: |
|
|
case AgentServiceEventType.recognitionStopped: |
|
|
isListening.value = false; |
|
|
isListening.value = false; |
|
|
@ -527,25 +527,29 @@ class AgentController extends GetxController with WidgetsBindingObserver { |
|
|
break; |
|
|
break; |
|
|
|
|
|
|
|
|
case AgentServiceEventType.recognizing: |
|
|
case AgentServiceEventType.recognizing: |
|
|
|
|
|
final sessionid = event.data['sessionid'] ?? ''; |
|
|
final text = event.data['text'] ?? ''; |
|
|
final text = event.data['text'] ?? ''; |
|
|
currentText.value = text; // 保留当前文本,以便其他地方使用 |
|
|
currentText.value = text; // 保留当前文本,以便其他地方使用 |
|
|
Logger.i(TAG, '识别中间结果: $text'); |
|
|
Logger.i(TAG, '识别中间结果: $text'); |
|
|
if (text.isNotEmpty) { |
|
|
if (text.isNotEmpty) { |
|
|
// 查找是否有正在识别中的消息 |
|
|
// 查找是否有正在识别中的消息 |
|
|
final index = messages |
|
|
final index = messages.lastIndexWhere( |
|
|
.lastIndexWhere((msg) => msg.isRecognizing && msg.isUser); |
|
|
(msg) => msg.sessionid == sessionid && msg.isUser); |
|
|
|
|
|
|
|
|
if (index >= 0) { |
|
|
if (index >= 0) { |
|
|
// 更新已有的识别中消息 |
|
|
// 更新已有的识别中消息 |
|
|
messages[index] = Message( |
|
|
messages[index] = Message( |
|
|
|
|
|
sessionid: sessionid, // 会话ID |
|
|
isUser: true, |
|
|
isUser: true, |
|
|
text: text, |
|
|
text: text, |
|
|
isRecognizing: true, |
|
|
isRecognizing: true, |
|
|
timestamp: messages[index].timestamp, |
|
|
timestamp: messages[index].timestamp, |
|
|
); |
|
|
); |
|
|
} else { |
|
|
} else { |
|
|
|
|
|
currsessionid.value = event.data['sessionid'] ?? ''; |
|
|
// 没有识别中的消息,创建新消息 |
|
|
// 没有识别中的消息,创建新消息 |
|
|
messages.add(Message( |
|
|
messages.add(Message( |
|
|
|
|
|
sessionid: sessionid, // 会话ID |
|
|
isUser: true, |
|
|
isUser: true, |
|
|
text: text, |
|
|
text: text, |
|
|
isRecognizing: true, |
|
|
isRecognizing: true, |
|
|
@ -556,26 +560,33 @@ class AgentController extends GetxController with WidgetsBindingObserver { |
|
|
break; |
|
|
break; |
|
|
|
|
|
|
|
|
case AgentServiceEventType.recognitionResult: |
|
|
case AgentServiceEventType.recognitionResult: |
|
|
|
|
|
final sessionid = event.data['sessionid'] ?? ''; |
|
|
final text = event.data['text'] ?? ''; |
|
|
final text = event.data['text'] ?? ''; |
|
|
Logger.i(TAG, '识别最终结果: $text'); |
|
|
Logger.i(TAG, '识别最终结果: $text'); |
|
|
// 查找是否有正在识别中的消息 |
|
|
// 查找是否有正在识别中的消息 |
|
|
final index = |
|
|
final index = messages.lastIndexWhere( |
|
|
messages.lastIndexWhere((msg) => msg.isRecognizing && msg.isUser); |
|
|
(msg) => msg.sessionid == sessionid && msg.isUser); |
|
|
|
|
|
|
|
|
if (text.isNotEmpty) { |
|
|
if (text.isNotEmpty) { |
|
|
if (index >= 0) { |
|
|
if (index >= 0) { |
|
|
// 将识别中的消息转换为最终消息 |
|
|
// 将识别中的消息转换为最终消息 |
|
|
messages[index] = Message( |
|
|
messages[index] = Message( |
|
|
|
|
|
sessionid: sessionid, |
|
|
isUser: true, |
|
|
isUser: true, |
|
|
text: text, |
|
|
text: text, |
|
|
isRecognizing: false, |
|
|
isRecognizing: false, |
|
|
timestamp: messages[index].timestamp, |
|
|
timestamp: messages[index].timestamp, |
|
|
|
|
|
functionCalls: messages[index].functionCalls, |
|
|
|
|
|
isToolCallsExpanded: messages[index].isToolCallsExpanded, |
|
|
); |
|
|
); |
|
|
// messages.refresh(); |
|
|
// messages.refresh(); |
|
|
} else { |
|
|
} else { |
|
|
// 如果没有找到识别中的消息,添加新消息 |
|
|
// 如果没有找到识别中的消息,添加新消息 |
|
|
messages |
|
|
messages.add(Message( |
|
|
.add(Message(isUser: true, text: text, isRecognizing: false)); |
|
|
sessionid: sessionid, |
|
|
|
|
|
isUser: true, |
|
|
|
|
|
text: text, |
|
|
|
|
|
isRecognizing: false)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
isProcessing.value = true; |
|
|
isProcessing.value = true; |
|
|
@ -590,24 +601,31 @@ class AgentController extends GetxController with WidgetsBindingObserver { |
|
|
break; |
|
|
break; |
|
|
//识别取消(网络波动会触发) |
|
|
//识别取消(网络波动会触发) |
|
|
case AgentServiceEventType.recognitionCanceled: |
|
|
case AgentServiceEventType.recognitionCanceled: |
|
|
|
|
|
final sessionid = event.data['sessionid'] ?? ''; |
|
|
// 查找是否有正在识别中的消息 |
|
|
// 查找是否有正在识别中的消息 |
|
|
final index = |
|
|
final index = messages.lastIndexWhere( |
|
|
messages.lastIndexWhere((msg) => msg.isRecognizing && msg.isUser); |
|
|
(msg) => msg.sessionid == sessionid && msg.isUser); |
|
|
|
|
|
|
|
|
if (currentText.value.isNotEmpty) { |
|
|
if (currentText.value.isNotEmpty) { |
|
|
if (index >= 0) { |
|
|
if (index >= 0) { |
|
|
// 将识别中的消息转换为最终消息 |
|
|
// 将识别中的消息转换为最终消息 |
|
|
messages[index] = Message( |
|
|
messages[index] = Message( |
|
|
|
|
|
sessionid: sessionid, // 会话ID |
|
|
isUser: true, |
|
|
isUser: true, |
|
|
text: currentText.value, |
|
|
text: currentText.value, |
|
|
isRecognizing: false, |
|
|
isRecognizing: false, |
|
|
timestamp: messages[index].timestamp, |
|
|
timestamp: messages[index].timestamp, |
|
|
|
|
|
functionCalls: messages[index].functionCalls, |
|
|
|
|
|
isToolCallsExpanded: messages[index].isToolCallsExpanded, |
|
|
); |
|
|
); |
|
|
// messages.refresh(); |
|
|
// messages.refresh(); |
|
|
} else { |
|
|
} else { |
|
|
// 如果没有找到识别中的消息,添加新消息 |
|
|
// 如果没有找到识别中的消息,添加新消息 |
|
|
messages.add(Message( |
|
|
messages.add(Message( |
|
|
isUser: true, text: currentText.value, isRecognizing: false)); |
|
|
sessionid: sessionid, |
|
|
|
|
|
isUser: true, |
|
|
|
|
|
text: currentText.value, |
|
|
|
|
|
isRecognizing: false)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
isProcessing.value = true; |
|
|
isProcessing.value = true; |
|
|
@ -654,29 +672,27 @@ class AgentController extends GetxController with WidgetsBindingObserver { |
|
|
|
|
|
|
|
|
case AgentServiceEventType.assistantToken: |
|
|
case AgentServiceEventType.assistantToken: |
|
|
if (!isProcessing.value) isProcessing.value = true; |
|
|
if (!isProcessing.value) isProcessing.value = true; |
|
|
|
|
|
final sessionid = event.data['sessionid'] ?? ''; |
|
|
final token = event.data['token'] ?? ''; |
|
|
final token = event.data['token'] ?? ''; |
|
|
final responseId = event.data['responseId'] ?? ''; |
|
|
|
|
|
// Logger.i(TAG, 'AI回复Token: $token, responseId: $responseId'); |
|
|
// Logger.i(TAG, 'AI回复Token: $token, responseId: $responseId'); |
|
|
if (token.isNotEmpty) { |
|
|
if (token.isNotEmpty) { |
|
|
// 如果是新的回复或者响应ID改变,创建新消息 |
|
|
// 如果是新的回复或者响应ID改变,创建新消息 |
|
|
if (_isNewAssistantResponse || |
|
|
final index = messages.lastIndexWhere( |
|
|
(_currentResponseId != responseId && responseId.isNotEmpty)) { |
|
|
(msg) => msg.sessionid == sessionid && !msg.isUser); |
|
|
messages.add(Message(isUser: false, text: token)); |
|
|
if (index == -1) { |
|
|
|
|
|
messages.add( |
|
|
|
|
|
Message(sessionid: sessionid, isUser: false, text: token)); |
|
|
_isNewAssistantResponse = false; |
|
|
_isNewAssistantResponse = false; |
|
|
_currentResponseId = responseId; |
|
|
|
|
|
} else { |
|
|
} else { |
|
|
// 否则更新最后一条消息 |
|
|
messages[index] = Message( |
|
|
final lastIndex = messages.length - 1; |
|
|
sessionid: sessionid, |
|
|
|
|
|
isUser: false, |
|
|
if (lastIndex >= 0 && !messages[lastIndex].isUser) { |
|
|
text: messages[index].text + token, |
|
|
messages[lastIndex] = Message( |
|
|
meta: messages[index].meta, |
|
|
isUser: false, |
|
|
timestamp: messages[index].timestamp, |
|
|
text: messages[lastIndex].text + token, |
|
|
functionCalls: messages[index].functionCalls, |
|
|
meta: messages[lastIndex].meta, |
|
|
isToolCallsExpanded: messages[index].isToolCallsExpanded, |
|
|
timestamp: messages[lastIndex].timestamp, |
|
|
); |
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
// 使用reverse:true时通常不需要手动滚动 |
|
|
// 使用reverse:true时通常不需要手动滚动 |
|
|
} |
|
|
} |
|
|
@ -713,10 +729,10 @@ class AgentController extends GetxController with WidgetsBindingObserver { |
|
|
|
|
|
|
|
|
case AgentServiceEventType.autoStop: |
|
|
case AgentServiceEventType.autoStop: |
|
|
isListening.value = false; |
|
|
isListening.value = false; |
|
|
|
|
|
final sessionid = event.data['sessionid'] ?? ''; |
|
|
// 移除临时的识别消息 |
|
|
// 移除临时的识别消息 |
|
|
final index = |
|
|
final index = messages.lastIndexWhere( |
|
|
messages.lastIndexWhere((msg) => msg.isRecognizing && msg.isUser); |
|
|
(msg) => msg.sessionid == sessionid && msg.isUser); |
|
|
if (index >= 0) { |
|
|
if (index >= 0) { |
|
|
// 只有当消息为空或文本太短时才移除 |
|
|
// 只有当消息为空或文本太短时才移除 |
|
|
if (messages[index].text.trim().length < 2) { |
|
|
if (messages[index].text.trim().length < 2) { |
|
|
@ -725,21 +741,25 @@ class AgentController extends GetxController with WidgetsBindingObserver { |
|
|
} else { |
|
|
} else { |
|
|
// 否则转换为正式消息 |
|
|
// 否则转换为正式消息 |
|
|
messages[index] = Message( |
|
|
messages[index] = Message( |
|
|
|
|
|
sessionid: sessionid, |
|
|
isUser: true, |
|
|
isUser: true, |
|
|
text: messages[index].text, |
|
|
text: messages[index].text, |
|
|
timestamp: messages[index].timestamp, |
|
|
timestamp: messages[index].timestamp, |
|
|
|
|
|
functionCalls: messages[index].functionCalls, |
|
|
|
|
|
isToolCallsExpanded: messages[index].isToolCallsExpanded, |
|
|
); |
|
|
); |
|
|
// messages.refresh(); |
|
|
// messages.refresh(); |
|
|
|
|
|
|
|
|
// 发送此消息到AI处理 |
|
|
// 发送此消息到AI处理 |
|
|
isProcessing.value = true; |
|
|
isProcessing.value = true; |
|
|
_isNewAssistantResponse = true; |
|
|
_isNewAssistantResponse = true; |
|
|
_handleAutoStop(index); |
|
|
_handleAutoStop(sessionid, index); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
break; |
|
|
break; |
|
|
|
|
|
|
|
|
case AgentServiceEventType.functionCall: |
|
|
case AgentServiceEventType.functionCall: |
|
|
|
|
|
final sessionid = event.data['sessionid'] ?? ''; |
|
|
final functionName = event.data['name'] ?? ''; |
|
|
final functionName = event.data['name'] ?? ''; |
|
|
final arguments = event.data['arguments'] ?? ''; |
|
|
final arguments = event.data['arguments'] ?? ''; |
|
|
// debugPrint('Fultter 开始调用 mcp: $functionName, $arguments'); |
|
|
// debugPrint('Fultter 开始调用 mcp: $functionName, $arguments'); |
|
|
@ -748,15 +768,39 @@ class AgentController extends GetxController with WidgetsBindingObserver { |
|
|
endPhoneCall(); //退出语音交互,同时退出打电话模式 |
|
|
endPhoneCall(); //退出语音交互,同时退出打电话模式 |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
final index = messages.lastIndexWhere( |
|
|
|
|
|
(msg) => msg.sessionid == sessionid && !msg.isUser); |
|
|
|
|
|
if (index == -1) { |
|
|
|
|
|
messages.add(Message( |
|
|
|
|
|
sessionid: sessionid, |
|
|
|
|
|
isUser: false, |
|
|
|
|
|
text: '', |
|
|
|
|
|
functionCalls: [functionName])); |
|
|
|
|
|
_isNewAssistantResponse = false; |
|
|
|
|
|
} else { |
|
|
|
|
|
// 否则更新最后一条消息 |
|
|
|
|
|
final lastIndex = messages.length - 1; |
|
|
|
|
|
|
|
|
|
|
|
if (lastIndex >= 0 && !messages[lastIndex].isUser) { |
|
|
|
|
|
messages[lastIndex] = Message( |
|
|
|
|
|
sessionid: sessionid, |
|
|
|
|
|
isUser: false, |
|
|
|
|
|
text: messages[lastIndex].text, |
|
|
|
|
|
meta: messages[lastIndex].meta, |
|
|
|
|
|
timestamp: messages[lastIndex].timestamp, |
|
|
|
|
|
functionCalls: messages[lastIndex].functionCalls ?? [] |
|
|
|
|
|
..add(functionName), |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
break; |
|
|
break; |
|
|
|
|
|
|
|
|
case AgentServiceEventType.functionCallResult: |
|
|
case AgentServiceEventType.functionCallResult: |
|
|
final responseId = event.data['responseId'] ?? ''; |
|
|
final sessionid = event.data['sessionid'] ?? ''; |
|
|
// final result = event.data['result']; |
|
|
// final result = event.data['result']; |
|
|
final metaStr = event.data['meta'] ?? ''; |
|
|
final metaStr = event.data['meta'] ?? ''; |
|
|
final functionCall = event.data['function_call'] ?? ''; |
|
|
final functionCall = event.data['function_call'] ?? ''; |
|
|
Logger.i(TAG, 'Flutter 结束调用 mcp: $metaStr'); |
|
|
Logger.i(TAG, 'Flutter 结束调用 $sessionid mcp: $metaStr'); |
|
|
if (metaStr.isNotEmpty) { |
|
|
if (metaStr.isNotEmpty) { |
|
|
Map<String, dynamic> metaResult = {}; |
|
|
Map<String, dynamic> metaResult = {}; |
|
|
metaResult = jsonDecode(metaStr) as Map<String, dynamic>; |
|
|
metaResult = jsonDecode(metaStr) as Map<String, dynamic>; |
|
|
@ -771,25 +815,31 @@ class AgentController extends GetxController with WidgetsBindingObserver { |
|
|
//不回复直接返回 |
|
|
//不回复直接返回 |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
final index = messages.lastIndexWhere( |
|
|
|
|
|
(msg) => msg.sessionid == sessionid && !msg.isUser); |
|
|
|
|
|
Logger.i(TAG, 'Flutter 结束调用 卡片数据 $index $metaResult'); |
|
|
// 判断是否为新的回复或响应ID是否改变 |
|
|
// 判断是否为新的回复或响应ID是否改变 |
|
|
if (_isNewAssistantResponse || _currentResponseId != responseId) { |
|
|
if (index == -1) { |
|
|
// 添加新消息 |
|
|
// 添加新消息 |
|
|
messages |
|
|
messages.add(Message( |
|
|
.add(Message(isUser: false, text: "", meta: metaResult)); |
|
|
sessionid: sessionid, |
|
|
|
|
|
isUser: false, |
|
|
|
|
|
text: "", |
|
|
|
|
|
meta: metaResult)); |
|
|
_isNewAssistantResponse = false; |
|
|
_isNewAssistantResponse = false; |
|
|
_currentResponseId = responseId; |
|
|
|
|
|
} else { |
|
|
} else { |
|
|
// 更新最后一条消息 |
|
|
// 更新最后一条消息 |
|
|
final lastIndex = messages.length - 1; |
|
|
messages[index] = Message( |
|
|
if (lastIndex >= 0 && !messages[lastIndex].isUser) { |
|
|
sessionid: sessionid, |
|
|
messages[lastIndex] = Message( |
|
|
isUser: false, |
|
|
isUser: false, |
|
|
text: messages[index].text, |
|
|
text: messages[lastIndex].text, |
|
|
meta: metaResult, |
|
|
meta: metaResult, |
|
|
timestamp: messages[index].timestamp, |
|
|
timestamp: messages[lastIndex].timestamp, |
|
|
functionCalls: messages[index].functionCalls, |
|
|
); |
|
|
isToolCallsExpanded: messages[index].isToolCallsExpanded, |
|
|
} |
|
|
); |
|
|
} |
|
|
} |
|
|
|
|
|
messages.refresh(); |
|
|
if (metaResult.containsKey("maps_route_navigation")) { |
|
|
if (metaResult.containsKey("maps_route_navigation")) { |
|
|
final maps_route_navigation = |
|
|
final maps_route_navigation = |
|
|
metaResult["maps_route_navigation"]; |
|
|
metaResult["maps_route_navigation"]; |
|
|
@ -847,6 +897,9 @@ class AgentController extends GetxController with WidgetsBindingObserver { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
// 其他函数调用 |
|
|
|
|
|
Logger.i(TAG, 'Flutter 结束调用 解析失败 $metaStr'); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
if (functionCall.contains("music")) { |
|
|
if (functionCall.contains("music")) { |
|
|
@ -893,6 +946,7 @@ class AgentController extends GetxController with WidgetsBindingObserver { |
|
|
|
|
|
|
|
|
// ✅ 创建新的 Message 替换原来的 |
|
|
// ✅ 创建新的 Message 替换原来的 |
|
|
messages[index] = Message( |
|
|
messages[index] = Message( |
|
|
|
|
|
sessionid: result.sessionid, |
|
|
isUser: result.isUser, |
|
|
isUser: result.isUser, |
|
|
text: result.text, |
|
|
text: result.text, |
|
|
meta: newMeta, |
|
|
meta: newMeta, |
|
|
@ -1002,10 +1056,13 @@ class AgentController extends GetxController with WidgetsBindingObserver { |
|
|
// 标记为新的AI回复 |
|
|
// 标记为新的AI回复 |
|
|
_isNewAssistantResponse = true; |
|
|
_isNewAssistantResponse = true; |
|
|
newAIReplyCompleted.value = false; |
|
|
newAIReplyCompleted.value = false; |
|
|
|
|
|
currsessionid.value = const Uuid().v4(); |
|
|
|
|
|
final sessionid = currsessionid.value; |
|
|
// 根据TTS状态决定是否朗读 |
|
|
// 根据TTS状态决定是否朗读 |
|
|
await AgentService.processTextInput(text, |
|
|
AgentService.processTextInput(sessionid, text, |
|
|
speakResponse: isTtsEnabled.value); |
|
|
speakResponse: isTtsEnabled.value); |
|
|
final message = Message(isUser: true, text: text); |
|
|
final message = Message(sessionid: sessionid, isUser: true, text: text); |
|
|
|
|
|
Logger.i(TAG, '发送AI消息:$sessionid $text'); |
|
|
messages.add(message); |
|
|
messages.add(message); |
|
|
textController.clear(); |
|
|
textController.clear(); |
|
|
} catch (e) { |
|
|
} catch (e) { |
|
|
@ -1029,12 +1086,17 @@ class AgentController extends GetxController with WidgetsBindingObserver { |
|
|
var ImageUrl = await UploadOss.upload( |
|
|
var ImageUrl = await UploadOss.upload( |
|
|
filepath: permanentImagePath, |
|
|
filepath: permanentImagePath, |
|
|
rootDir: 'User/${User.instance.uid}/ChatImages'); |
|
|
rootDir: 'User/${User.instance.uid}/ChatImages'); |
|
|
Logger.i(TAG, '图片上传: $permanentImagePath URL: $ImageUrl'); |
|
|
|
|
|
// 显示的文本,如果没有提供则使用默认值 |
|
|
// 显示的文本,如果没有提供则使用默认值 |
|
|
final displayText = text?.isNotEmpty == true ? text! : '[图片]'; |
|
|
final displayText = text?.isNotEmpty == true ? text! : '[图片]'; |
|
|
|
|
|
|
|
|
|
|
|
currsessionid.value = const Uuid().v4(); |
|
|
|
|
|
final sessionid = currsessionid.value; |
|
|
|
|
|
Logger.i(TAG, |
|
|
|
|
|
'发送AI图片消息:$sessionid $displayText $permanentImagePath URL: $ImageUrl'); |
|
|
// 添加用户消息 |
|
|
// 添加用户消息 |
|
|
final message = Message( |
|
|
final message = Message( |
|
|
|
|
|
sessionid: sessionid, |
|
|
isUser: true, |
|
|
isUser: true, |
|
|
text: displayText, |
|
|
text: displayText, |
|
|
hasImage: true, |
|
|
hasImage: true, |
|
|
@ -1055,9 +1117,11 @@ class AgentController extends GetxController with WidgetsBindingObserver { |
|
|
|
|
|
|
|
|
// 保存消息到持久化存储 |
|
|
// 保存消息到持久化存储 |
|
|
//await _saveMessageToStorage(message); |
|
|
//await _saveMessageToStorage(message); |
|
|
|
|
|
currsessionid.value = const Uuid().v4(); |
|
|
|
|
|
final sessionid = currsessionid.value; |
|
|
// 调用Agent Service处理图片,考虑TTS状态 |
|
|
// 调用Agent Service处理图片,考虑TTS状态 |
|
|
await AgentService.processImageInput( |
|
|
await AgentService.processImageInput( |
|
|
|
|
|
sessionid, |
|
|
relativeImagePath, |
|
|
relativeImagePath, |
|
|
ImageUrl, |
|
|
ImageUrl, |
|
|
text: text ?? '', |
|
|
text: text ?? '', |
|
|
@ -1855,11 +1919,13 @@ class AgentController extends GetxController with WidgetsBindingObserver { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 修改自动停止处理,遵循TTS设置 |
|
|
// 修改自动停止处理,遵循TTS设置 |
|
|
void _handleAutoStop(int index) { |
|
|
void _handleAutoStop(String sessionid, int index) { |
|
|
// 发送此消息到AI处理 |
|
|
// 发送此消息到AI处理 |
|
|
isProcessing.value = true; |
|
|
isProcessing.value = true; |
|
|
|
|
|
// 标记为新的AI回复 |
|
|
_isNewAssistantResponse = true; |
|
|
_isNewAssistantResponse = true; |
|
|
AgentService.processTextInput(messages[index].text, |
|
|
currsessionid.value = sessionid; |
|
|
|
|
|
AgentService.processTextInput(sessionid, messages[index].text, |
|
|
speakResponse: isTtsEnabled.value); |
|
|
speakResponse: isTtsEnabled.value); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -2612,4 +2678,15 @@ class AgentController extends GetxController with WidgetsBindingObserver { |
|
|
Get.snackbar('错误', '打开苹果地图时发生错误'); |
|
|
Get.snackbar('错误', '打开苹果地图时发生错误'); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Future<void> updateToolCallsExpanded( |
|
|
|
|
|
String sessionid, |
|
|
|
|
|
bool isExpanded, |
|
|
|
|
|
) async { |
|
|
|
|
|
final message = messages.firstWhere( |
|
|
|
|
|
(msg) => msg.sessionid == sessionid && msg.isUser == false, |
|
|
|
|
|
); |
|
|
|
|
|
message.isToolCallsExpanded = isExpanded; |
|
|
|
|
|
messages.refresh(); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|