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, /// 播放开始 playbackStarted, /// 播放完成 playbackCompleted, /// 响应中断 responseInterrupted, /// AI助手Token assistantToken, /// AI助手完整响应 assistantResponse, /// 函数调用 functionCall, /// 函数调用结果 functionCallResult, /// 图片处理中 imageProcessing, /// 图片准备就绪 imageReady, /// 错误 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 'playback_started': return AgentServiceEventType.playbackStarted; case 'playback_completed': return AgentServiceEventType.playbackCompleted; 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; case 'image_processing': return AgentServiceEventType.imageProcessing; case 'image_ready': return AgentServiceEventType.imageReady; 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); } } /// 启动语音助手服务 /// /// 启动常驻的语音助手服务,支持后台蓝牙设备唤醒和媒体按钮唤醒 /// [config] 配置参数,应包含以下参数: /// - azureSpeechKey: Azure语音服务密钥 /// - azureSpeechRegion: Azure语音服务区域 /// - openaiApiKey: OpenAI API密钥 /// - openaiBaseUrl: (可选) OpenAI API 基础URL /// - openaiModel: (可选) OpenAI模型名称,默认为"gpt-3.5-turbo" /// - mcpServer: (可选) MCP服务器地址 /// /// 返回是否成功启动服务 static Future startAgentService(Map config) async { try { final bool result = await _channel.invokeMethod('startAgentService', { 'config': config, }); return result; } on PlatformException catch (e) { throw AgentServiceException(e.code, e.message ?? '启动语音助手服务失败', e.details); } } /// 停止语音助手服务 /// /// 停止常驻的语音助手服务 /// 返回是否成功停止服务 static Future stopAgentService() async { try { final bool result = await _channel.invokeMethod('stopAgentService'); 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 recognizeCallback() async { try { final bool result = await _channel.invokeMethod('recognizeCallback'); 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); } } // /// 停止对话 // /// // /// 停止语音识别 // /// 返回是否成功停止对话 // static Future audioContinue() async { // try { // final bool result = await _channel.invokeMethod('audioContinue'); // return result; // } on PlatformException catch (e) { // throw AgentServiceException(e.code, e.message ?? '停止对话失败', e.details); // } // } // /// 停止对话 // /// // /// 停止语音识别 // /// 返回是否成功停止对话 // static Future audioPause() async { // try { // final bool result = await _channel.invokeMethod('audioPause'); // 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 stopAiSteam() async { try { final bool result = await _channel.invokeMethod('stopAiSteam'); 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); } } /// 处理图片输入 /// /// [imagePath] 图片文件路径 /// [text] 可选的文本描述或问题 /// [speakResponse] 是否朗读响应 /// 返回是否成功处理图片 static Future processImageInput(String imagePath, String imageUrl, {String text = "", bool speakResponse = false}) async { try { final bool result = await _channel.invokeMethod('processImageInput', { 'imagePath': imagePath, 'imageUrl': imageUrl, 'text': text, 'speakResponse': speakResponse, }); return result; } on PlatformException catch (e) { throw AgentServiceException(e.code, e.message ?? '处理图片输入失败', e.details); } } /// 设置支持的语音识别语言 /// /// [languages] 支持的语言列表,如 ["zh-CN", "en-US"] /// 返回是否设置成功 static Future setSupportedLanguages(List languages) async { try { final bool result = await _channel.invokeMethod('setSupportedLanguages', { 'languages': languages, }); return result; } 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); } } }