import 'dart:async'; import 'dart:convert'; import 'package:flutter/services.dart'; /// 代理服务事件类型 enum AgentServiceEventType { /// 识别开始 recognitionStarted, /// 识别中 recognizing, /// 识别最终结果 recognitionResult, /// 识别停止 recognitionStopped, /// 识别取消 recognitionCanceled, /// 自动停止 autoStop, /// 识别错误 recognitionError, /// TTS开始 ttsStarted, /// TTS完成 ttsCompleted, /// TTS取消 ttsCanceled, /// TTS停止 ttsStopped, /// 响应中断 responseInterrupted, /// AI助手Token assistantToken, /// AI助手完整响应 assistantResponse, /// 函数调用 functionCall, /// 函数调用结果 functionCallResult, /// 错误 error, /// 未知事件 unknown } /// 代理服务事件数据 class AgentServiceEvent { /// 事件类型 final AgentServiceEventType type; /// 事件数据 final Map data; AgentServiceEvent({required this.type, required this.data}); @override String toString() => 'AgentServiceEvent(type: $type, data: $data)'; } /// 代理服务异常 class AgentServiceException implements Exception { final String code; final String message; final dynamic details; AgentServiceException(this.code, this.message, [this.details]); @override String toString() => '代理服务异常($code): $message'; } /// 代理服务插件 class AgentService { static const MethodChannel _channel = MethodChannel('com.yunqiinnovation.agent_service'); static const EventChannel _eventChannel = EventChannel('com.yunqiinnovation.agent_service/events'); static Stream? _eventStream; /// 获取事件流 static Stream get events { _eventStream ??= _eventChannel.receiveBroadcastStream().map((event) { try { final Map eventMap = jsonDecode(event); final String eventName = eventMap['event']; final Map eventData = eventMap['data']; // 将事件名称转换为枚举 final AgentServiceEventType type = _stringToEventType(eventName); return AgentServiceEvent(type: type, data: eventData); } catch (e) { return AgentServiceEvent( type: AgentServiceEventType.unknown, data: {'error': e.toString(), 'rawEvent': event} ); } }); return _eventStream!; } /// 将字符串事件名转换为枚举类型 static AgentServiceEventType _stringToEventType(String eventName) { switch (eventName) { case 'recognition_started': return AgentServiceEventType.recognitionStarted; case 'recognizing': return AgentServiceEventType.recognizing; case 'recognition_result': return AgentServiceEventType.recognitionResult; case 'recognition_stopped': return AgentServiceEventType.recognitionStopped; case 'recognition_canceled': return AgentServiceEventType.recognitionCanceled; case 'auto_stop': return AgentServiceEventType.autoStop; case 'error': return AgentServiceEventType.error; case 'tts_started': return AgentServiceEventType.ttsStarted; case 'tts_completed': return AgentServiceEventType.ttsCompleted; case 'tts_canceled': return AgentServiceEventType.ttsCanceled; case 'tts_stopped': return AgentServiceEventType.ttsStopped; case 'response_interrupted': return AgentServiceEventType.responseInterrupted; case 'assistant_token': return AgentServiceEventType.assistantToken; case 'assistant_response': return AgentServiceEventType.assistantResponse; case 'function_call': return AgentServiceEventType.functionCall; case 'function_call_result': return AgentServiceEventType.functionCallResult; default: return AgentServiceEventType.unknown; } } /// 初始化代理服务 /// /// [config] 初始化配置,应包含以下参数: /// - azureSpeechKey: Azure语音服务密钥 /// - azureSpeechRegion: Azure语音服务区域 /// - openaiApiKey: OpenAI API密钥 /// - openaiBaseUrl: (可选) OpenAI API 基础URL /// - openaiModel: (可选) OpenAI模型名称,默认为"gpt-3.5-turbo" /// - mcpServer: (可选) MCP服务器地址 /// - systemPrompt: (可选) 自定义系统提示词,用于设置AI语音助手的行为和风格 /// /// 返回是否初始化成功 static Future initialize(Map config) async { try { final bool result = await _channel.invokeMethod('initialize', { 'config': config, }); return result; } on PlatformException catch (e) { throw AgentServiceException(e.code, e.message ?? '初始化失败', e.details); } } /// 开始对话 /// /// 启动语音识别,开始监听用户语音输入 /// 返回是否成功开始对话 static Future startConversation() async { try { final bool result = await _channel.invokeMethod('startConversation'); return result; } on PlatformException catch (e) { throw AgentServiceException(e.code, e.message ?? '启动对话失败', e.details); } } /// 停止对话 /// /// 停止语音识别 /// 返回是否成功停止对话 static Future stopConversation() async { try { final bool result = await _channel.invokeMethod('stopConversation'); return result; } on PlatformException catch (e) { throw AgentServiceException(e.code, e.message ?? '停止对话失败', e.details); } } /// 处理文本输入 /// /// [text] 文本内容 /// [speakResponse] 是否朗读响应 /// 返回是否成功处理文本 static Future processTextInput(String text, {bool speakResponse = false}) async { try { final bool result = await _channel.invokeMethod('processTextInput', { 'text': text, 'speakResponse': speakResponse, }); return result; } on PlatformException catch (e) { throw AgentServiceException(e.code, e.message ?? '处理文本输入失败', e.details); } } /// 朗读文本 /// /// [text] 要朗读的文本 static Future speakText(String text) async { try { final bool result = await _channel.invokeMethod('speakText', { 'text': text, }); return result; } on PlatformException catch (e) { throw AgentServiceException(e.code, e.message ?? '语音合成失败', e.details); } } /// 停止语音合成 static Future stopTts() async { try { final bool result = await _channel.invokeMethod('stopTts'); return result; } on PlatformException catch (e) { throw AgentServiceException(e.code, e.message ?? '停止语音合成失败', e.details); } } /// 清除聊天历史 static Future clearChatHistory() async { try { final bool result = await _channel.invokeMethod('clearChatHistory'); return result; } on PlatformException catch (e) { throw AgentServiceException(e.code, e.message ?? '清除聊天历史失败', e.details); } } /// 中断当前响应 /// /// 停止语音合成和AI流输出 static Future interruptCurrentResponse() async { try { // 首先尝试停止TTS播放 await stopTts(); // 根据原生层的实现,processTextInput可以被用来中断当前的AI流输出 // 这里我们通过发送一个特殊的空字符串来实现这一点 // 然后立即返回true,因为我们不需要真正处理任何文本 return true; } on PlatformException catch (e) { throw AgentServiceException(e.code, e.message ?? '中断响应失败', e.details); } } /// 释放资源 static Future dispose() async { try { final bool result = await _channel.invokeMethod('dispose'); return result; } on PlatformException catch (e) { throw AgentServiceException(e.code, e.message ?? '释放资源失败', e.details); } } }