diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts
index fa5282d77..cf7591c68 100644
--- a/android/settings.gradle.kts
+++ b/android/settings.gradle.kts
@@ -39,7 +39,7 @@ include(":ble_service")
include(":classic_bluetooth")
include(":agent_service")
include(":speech")
-include(":open_ai_service")
+include(":chat_api")
// 设置azure_speech项目的路径
project(":azure_speech").projectDir = file("../local_plugins/azure_speech/android")
@@ -50,4 +50,4 @@ project(":ble_service").projectDir = file("../local_plugins/ble_service/android"
project(":classic_bluetooth").projectDir = file("../local_plugins/classic_bluetooth/android")
project(":agent_service").projectDir = file("../local_plugins/agent_service/android")
project(":speech").projectDir = file("../local_plugins/speech/android")
-project(":open_ai_service").projectDir = file("../local_plugins/open_ai_service/android")
\ No newline at end of file
+project(":chat_api").projectDir = file("../local_plugins/chat_api/android")
\ No newline at end of file
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index 9a7b93fa1..b7e7fc98f 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -123,9 +123,9 @@
NSBluetoothPeripheralUsageDescription
需要蓝牙权限用于连接和管理音频设备
NSLocationAlwaysAndWhenInUseUsageDescription
- 需要位置权限用于搜索附近的蓝牙设备
+ 语音助手需要位置权限来为您提供基于位置的信息和服务
NSLocationWhenInUseUsageDescription
- 需要位置权限用于搜索附近的蓝牙设备
+ 语音助手需要位置权限来为您提供基于位置的信息和服务
NSMicrophoneUsageDescription
需要麦克风权限用于语音识别和录音功能
NSCalendarsUsageDescription
diff --git a/local_plugins/agent_service/android/build.gradle.kts b/local_plugins/agent_service/android/build.gradle.kts
index 64a0b9518..1fd600fb7 100644
--- a/local_plugins/agent_service/android/build.gradle.kts
+++ b/local_plugins/agent_service/android/build.gradle.kts
@@ -48,5 +48,5 @@ dependencies {
add("compileOnly", project(":music_service"))
add("compileOnly", project(":amap_service"))
add("compileOnly", project(":speech"))
- add("compileOnly", project(":open_ai_service"))
+ add("compileOnly", project(":chat_api"))
}
\ No newline at end of file
diff --git a/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt b/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt
index 94eae0890..d9f358d34 100644
--- a/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt
+++ b/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt
@@ -4,7 +4,8 @@ import android.content.Context
import org.json.JSONArray
import org.json.JSONObject
import com.yunqiinnovation.azure_speech.AzureAsrHelper
-import com.yunqiinnovation.open_ai_service.OpenAIService
+import com.yunqiinnovation.chat_api.ChatApiService
+import com.yunqiinnovation.chat_api.StreamCallback
import com.yunqiinnovation.chat_storage.ChatStorageHelper
import com.yunqiinnovation.music_service.MusicServiceStarter
import com.yunqiinnovation.amap_service.NavigationServiceHelper
@@ -53,8 +54,8 @@ object AgentService : CoroutineScope {
// 使用AzureTtsHelper作为唯一的TTS实现
private var ttsService: AzureTtsHelper? = null
- // OpenAI服务 - 修改为使用OpenAIService
- private lateinit var openAIService: OpenAIService
+ // ChatAPI服务 - 使用新的ChatApiService
+ private lateinit var chatApiService: ChatApiService
// 聊天存储服务
private lateinit var chatStorageHelper: ChatStorageHelper
@@ -121,7 +122,7 @@ object AgentService : CoroutineScope {
try {
// 初始化上下文和服务
this.context = appContext.applicationContext
- this.openAIService = OpenAIService(context)
+ this.chatApiService = ChatApiService(context)
this.chatStorageHelper = ChatStorageHelper(context)
this.audioPlayer = AudioPlayer(context)
@@ -146,8 +147,8 @@ object AgentService : CoroutineScope {
// 初始化TTS服务
initializeTtsEngine(config)
- // 初始化OpenAI服务
- openAIService.initialize(
+ // 初始化ChatAPI服务
+ chatApiService.initialize(
config["openaiApiKey"]?.toString() ?: "",
config["openaiBaseUrl"]?.toString() ?: "",
config["openaiModel"]?.toString() ?: "",
@@ -181,9 +182,9 @@ object AgentService : CoroutineScope {
azureAsrHelper?.dispose()
- // 释放OpenAI服务
- if (::openAIService.isInitialized) {
- openAIService.cancelAll()
+ // 释放ChatAPI服务
+ if (::chatApiService.isInitialized) {
+ chatApiService.cancelCurrentStream()
}
// 释放TTS服务
@@ -401,7 +402,7 @@ object AgentService : CoroutineScope {
"language" to detectedLanguage
))
- processWithOpenAI(result)
+ processWithChatApi(result)
}
// 重置状态,继续识别
@@ -513,8 +514,8 @@ object AgentService : CoroutineScope {
currentAiJob?.cancel()
currentAiJob = null
- // 通知OpenAI服务终止当前流式请求
- openAIService.cancelCurrentStream()
+ // 通知ChatAPI服务终止当前流式请求
+ chatApiService.cancelCurrentStream()
// 记录日志
Log.d(TAG, "AI流输出已停止")
@@ -543,43 +544,43 @@ object AgentService : CoroutineScope {
return false
}
- // 使用OpenAI处理文本
- processWithOpenAI(text, speakResponse)
+ // 使用ChatAPI处理文本
+ processWithChatApi(text, speakResponse)
return true
}
/**
- * 使用OpenAI处理语音识别结果
+ * 使用ChatAPI处理语音识别结果
*/
- private fun processWithOpenAI(text: String) {
- processWithOpenAI(text, true)
+ private fun processWithChatApi(text: String) {
+ processWithChatApi(text, true)
}
/**
- * 使用OpenAI处理文本消息
+ * 使用ChatAPI处理文本消息
*
* @param text 用户输入文本
* @param speakResponse 是否使用TTS朗读回复
*/
- private fun processWithOpenAI(
+ private fun processWithChatApi(
text: String,
speakResponse: Boolean = true
) {
Log.d(TAG, "用户问题: $text")
// 创建用户文本消息并处理
- val userMessage = openAIService.createUserMessage(text)
- processWithOpenAIInternal(userMessage, text, speakResponse)
+ val userMessage = createUserMessage(text)
+ processWithChatApiInternal(userMessage, text, speakResponse)
}
/**
- * 使用OpenAI处理图片
+ * 使用ChatAPI处理图片
*
* @param imageBase64 Base64编码的图片数据
* @param text 可选的文本描述或问题
* @param speakResponse 是否朗读回复
*/
- private fun processImageWithOpenAI(
+ private fun processImageWithChatApi(
imageBase64: String,
text: String = "",
speakResponse: Boolean = false
@@ -587,14 +588,14 @@ object AgentService : CoroutineScope {
Log.d(TAG, "处理图片输入: ${if (text.isEmpty()) "无附加文本" else "附带文本: $text"}")
// 创建带图片的用户消息并处理
- val userMessage = openAIService.createUserMessageWithImage(text, imageBase64)
+ val userMessage = createUserMessageWithImage(text, imageBase64)
// 图片描述用于存储
val displayText = text.ifEmpty { "[图片]" }
- processWithOpenAIInternal(userMessage, displayText, speakResponse, true)
+ processWithChatApiInternal(userMessage, displayText, speakResponse, true)
}
/**
- * 内部方法:通用的OpenAI处理逻辑
+ * 内部方法:通用的ChatAPI处理逻辑
*
* @param userMessage 用户消息(可以是文本或图片格式)
* @param displayText 用于显示和存储的文本
@@ -602,7 +603,7 @@ object AgentService : CoroutineScope {
* @param hasImage 是否包含图片
* @param imagePath 图片路径(如果有)
*/
- private fun processWithOpenAIInternal(
+ private fun processWithChatApiInternal(
userMessage: JSONObject,
displayText: String,
speakResponse: Boolean = true,
@@ -634,7 +635,7 @@ object AgentService : CoroutineScope {
// 先添加系统提示词
if (systemPrompt.isNotEmpty()) {
- messagesWithSystemPrompt.put(openAIService.createSystemMessage(systemPrompt))
+ messagesWithSystemPrompt.put(createSystemMessage(systemPrompt))
// Log.d(TAG, "系统提示词: ${systemPrompt}")
}
@@ -672,9 +673,9 @@ object AgentService : CoroutineScope {
addToHistoryMessages(userMessage)
}
- openAIService.sendMessageStream(
+ chatApiService.sendMessageStream(
messagesWithSystemPrompt,
- object : OpenAIService.StreamCallback {
+ object : StreamCallback {
override fun onToken(token: String) {
responseBuilder.append(token)
if (speakResponse && !nobroadcast) {
@@ -704,7 +705,7 @@ object AgentService : CoroutineScope {
sendEvent("assistant_response", responseData)
// 添加AI回复到历史记录
- addToHistoryMessages(openAIService.createAssistantMessage(response))
+ addToHistoryMessages(createAssistantMessage(response))
// 保存聊天记录
saveChatMessage(displayText, response,aiMetadata,userMetadata.toString())
@@ -796,9 +797,9 @@ object AgentService : CoroutineScope {
val content = message["message"] as String
if (sender == "user") {
- addToHistoryMessages(openAIService.createUserMessage(content))
+ addToHistoryMessages(createUserMessage(content))
} else if (sender == "assistant") {
- addToHistoryMessages(openAIService.createAssistantMessage(content))
+ addToHistoryMessages(createAssistantMessage(content))
}
}
@@ -945,6 +946,62 @@ object AgentService : CoroutineScope {
return result == android.content.pm.PackageManager.PERMISSION_GRANTED
}
+ /**
+ * 创建用户消息
+ */
+ private fun createUserMessage(content: String): JSONObject {
+ return JSONObject().apply {
+ put("role", "user")
+ put("content", content)
+ }
+ }
+
+ /**
+ * 创建系统消息
+ */
+ private fun createSystemMessage(content: String): JSONObject {
+ return JSONObject().apply {
+ put("role", "system")
+ put("content", content)
+ }
+ }
+
+ /**
+ * 创建助手消息
+ */
+ private fun createAssistantMessage(content: String): JSONObject {
+ return JSONObject().apply {
+ put("role", "assistant")
+ put("content", content)
+ }
+ }
+
+ /**
+ * 创建带图片的用户消息
+ */
+ private fun createUserMessageWithImage(text: String, imageBase64: String): JSONObject {
+ val content = JSONArray().apply {
+ if (text.isNotEmpty()) {
+ put(JSONObject().apply {
+ put("type", "text")
+ put("text", text)
+ })
+ }
+ put(JSONObject().apply {
+ put("type", "image_url")
+ put("image_url", JSONObject().apply {
+ put("url", "data:image/jpeg;base64,$imageBase64")
+ put("detail", "auto")
+ })
+ })
+ }
+
+ return JSONObject().apply {
+ put("role", "user")
+ put("content", content)
+ }
+ }
+
/**
* 处理图片输入
*/
@@ -971,7 +1028,7 @@ object AgentService : CoroutineScope {
launch {
try {
// 将图片转换为Base64格式
- val imageBase64 = openAIService.fileToBase64(imagePath) ?: run {
+ val imageBase64 = chatApiService.fileToBase64(imagePath) ?: run {
sendEvent("error", mapOf(
"code" to "IMAGE_CONVERSION_FAILED",
"message" to "图片转换失败"
@@ -980,9 +1037,9 @@ object AgentService : CoroutineScope {
}
// 创建带图片的用户消息并处理
- val userMessage = openAIService.createUserMessageWithImage(text, imageBase64)
- // 图片描述用于存储
- val displayText = text.ifEmpty { "[图片]" }
+ val userMessage = createUserMessageWithImage(text, imageBase64)
+ // 图片描述用于存储
+ val displayText = text.ifEmpty { "[图片]" }
// 通知图片准备完成
sendEvent("image_ready", mapOf(
@@ -991,7 +1048,7 @@ object AgentService : CoroutineScope {
))
// 处理消息并传入存储路径
- processWithOpenAIInternal(userMessage, displayText, speakResponse, true, imagePath)
+ processWithChatApiInternal(userMessage, displayText, speakResponse, true, imagePath)
} catch (e: Exception) {
Log.e(TAG, "处理图片失败: ${e.message}")
sendEvent("error", mapOf(
diff --git a/local_plugins/chat_api/README.md b/local_plugins/chat_api/README.md
index be47e00d0..463e1c3d6 100644
--- a/local_plugins/chat_api/README.md
+++ b/local_plugins/chat_api/README.md
@@ -15,6 +15,7 @@
## 平台支持
- iOS 16.0+
+- Android (API 21+)
## MCP 功能
@@ -138,6 +139,7 @@ chatApi.eventStream.listen((event) {
## 架构
+### iOS
```
ChatApiService (Flutter层)
↓
@@ -150,3 +152,14 @@ ChatApiService (iOS原生服务)
└── SystemFunctionHandler (内置系统功能)
```
+### Android
+```
+ChatApiService (Flutter层)
+ ↓
+ChatApiPlugin (Android插件桥接)
+ ↓
+ChatApiService (Android原生服务)
+ ├── OpenAI客户端 (aallam/openai-kotlin 4.0.1)
+ └── MCP功能 (暂时留空,接口预留)
+```
+
diff --git a/local_plugins/chat_api/android/README.md b/local_plugins/chat_api/android/README.md
new file mode 100644
index 000000000..99c528b5f
--- /dev/null
+++ b/local_plugins/chat_api/android/README.md
@@ -0,0 +1,70 @@
+# ChatAPI Android 实现
+
+基于 [openai-kotlin 4.0.1](https://github.com/aallam/openai-kotlin/tree/4.0.1) 的 ChatAPI 插件 Android 实现。
+
+## 特性
+
+- ✅ 基于 openai-kotlin 4.0.1 的 OpenAI API 客户端
+- ✅ 与 iOS 版本接口完全一致
+- ✅ 支持流式和非流式对话
+- ✅ 支持多模态内容(文本和图像识别)
+- ✅ 工具调用架构预留(MCP 功能暂时留空)
+- ✅ 协程支持和异步处理
+- ✅ 完整的错误处理和取消机制
+
+## 依赖
+
+- openai-kotlin 4.0.1
+- ktor-client-okhttp 2.3.2
+- kotlinx-coroutines
+- gson
+
+## 主要文件
+
+- `ChatApiPlugin.kt` - Flutter 插件桥接层
+- `ChatApiService.kt` - 核心 ChatAPI 服务实现
+- `StreamCallback.kt` - 流式回调接口
+
+## 与 iOS 版本的一致性
+
+Android 实现完全遵循 iOS 版本的接口定义:
+
+1. **初始化方法**: `initialize(apiKey, baseUrl, model, mcpServer)`
+2. **消息创建**: `createUserMessage()`, `createAssistantMessage()`
+3. **消息发送**: `sendMessage()` (非流式), `sendMessageStream()` (流式)
+4. **函数注册**: `registerFunction()`
+5. **MCP 相关**: 接口保留,功能暂时留空
+6. **流式事件**: 完全一致的事件类型和回调
+
+## MCP 功能状态
+
+MCP (Model Context Protocol) 相关功能在 Android 版本中暂时留空,包括:
+
+- `initializeMcpClient()` - 返回 false
+- `isMcpInitialized()` - 返回 false
+- `handleMcpToolCall()` - 返回占位符消息
+- 工具调用会通知上层但不会实际执行
+
+## 使用示例
+
+```kotlin
+// 初始化
+chatApiService.initialize(
+ apiKey = "your-api-key",
+ baseUrl = "https://api.openai.com/v1/",
+ model = "gpt-3.5-turbo",
+ mcpServer = ""
+)
+
+// 流式对话
+chatApiService.sendMessageStream(listOf(
+ mapOf("role" to "user", "content" to "Hello!")
+))
+```
+
+## 注意事项
+
+1. 需要网络权限 `INTERNET` 和 `ACCESS_NETWORK_STATE`
+2. 所有网络请求在后台线程执行
+3. 流式回调在主线程触发
+4. 支持取消正在进行的请求
\ No newline at end of file
diff --git a/local_plugins/chat_api/android/build.gradle.kts b/local_plugins/chat_api/android/build.gradle.kts
new file mode 100644
index 000000000..1eb929ecf
--- /dev/null
+++ b/local_plugins/chat_api/android/build.gradle.kts
@@ -0,0 +1,50 @@
+plugins {
+ id("com.android.library")
+ id("org.jetbrains.kotlin.android")
+ kotlin("plugin.serialization") version "1.9.24"
+}
+
+android {
+ namespace = "com.yunqiinnovation.chat_api"
+ compileSdk = 35
+
+ defaultConfig {
+ minSdk = 21
+ targetSdk = 33
+ }
+
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_11
+ targetCompatibility = JavaVersion.VERSION_11
+ }
+
+ kotlinOptions {
+ jvmTarget = "11"
+ }
+
+ packaging {
+ resources {
+ excludes.add("META-INF/DEPENDENCIES")
+ excludes.add("META-INF/LICENSE")
+ excludes.add("META-INF/LICENSE.txt")
+ excludes.add("META-INF/license.txt")
+ excludes.add("META-INF/NOTICE")
+ excludes.add("META-INF/NOTICE.txt")
+ excludes.add("META-INF/notice.txt")
+ excludes.add("META-INF/*.kotlin_module")
+ }
+ }
+}
+
+dependencies {
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4")
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
+
+ // OpenAI Kotlin 4.0.1
+ implementation("com.aallam.openai:openai-client:4.0.1")
+ implementation("io.ktor:ktor-client-okhttp:2.3.2")
+
+ // JSON处理
+ implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0")
+ implementation("com.google.code.gson:gson:2.10.1")
+}
\ No newline at end of file
diff --git a/local_plugins/chat_api/android/settings.gradle.kts b/local_plugins/chat_api/android/settings.gradle.kts
new file mode 100644
index 000000000..c953e09ff
--- /dev/null
+++ b/local_plugins/chat_api/android/settings.gradle.kts
@@ -0,0 +1 @@
+rootProject.name = "chat_api"
\ No newline at end of file
diff --git a/local_plugins/chat_api/android/src/main/AndroidManifest.xml b/local_plugins/chat_api/android/src/main/AndroidManifest.xml
new file mode 100644
index 000000000..11db23350
--- /dev/null
+++ b/local_plugins/chat_api/android/src/main/AndroidManifest.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/ChatApiPlugin.kt b/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/ChatApiPlugin.kt
new file mode 100644
index 000000000..bc7801951
--- /dev/null
+++ b/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/ChatApiPlugin.kt
@@ -0,0 +1,252 @@
+package com.yunqiinnovation.chat_api
+
+import android.os.Handler
+import android.os.Looper
+import io.flutter.embedding.engine.plugins.FlutterPlugin
+import io.flutter.plugin.common.EventChannel
+import io.flutter.plugin.common.MethodCall
+import io.flutter.plugin.common.MethodChannel
+import io.flutter.plugin.common.MethodChannel.MethodCallHandler
+import io.flutter.plugin.common.MethodChannel.Result
+import kotlinx.coroutines.*
+
+/**
+ * ChatApiPlugin
+ *
+ * 基于 openai-kotlin 4.0.1 的 ChatAPI 插件 Android 实现
+ * 与 iOS 版本接口完全一致
+ */
+class ChatApiPlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamHandler {
+ private lateinit var methodChannel: MethodChannel
+ private lateinit var eventChannel: EventChannel
+ private var eventSink: EventChannel.EventSink? = null
+
+ private val chatApiService = ChatApiService()
+ private val mainHandler = Handler(Looper.getMainLooper())
+
+ // 协程作用域
+ private val pluginScope = CoroutineScope(Dispatchers.Main + SupervisorJob())
+
+ override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
+ methodChannel = MethodChannel(flutterPluginBinding.binaryMessenger, "com.yunqiinnovation.chat_api/methods")
+ methodChannel.setMethodCallHandler(this)
+
+ eventChannel = EventChannel(flutterPluginBinding.binaryMessenger, "com.yunqiinnovation.chat_api/events")
+ eventChannel.setStreamHandler(this)
+
+ // 设置流式回调
+ chatApiService.setStreamCallback(object : com.yunqiinnovation.chat_api.StreamCallback {
+ override fun onToken(token: String) {
+ sendEvent("token", token)
+ }
+
+ override fun onComplete() {
+ sendEvent("complete", null)
+ }
+
+ override fun onError(error: Exception) {
+ sendEvent("error", error.message ?: "未知错误")
+ }
+
+ override fun onFunctionCall(functionCall: org.json.JSONObject) {
+ try {
+ val jsonString = functionCall.toString()
+ sendEvent("functionCall", jsonString)
+ } catch (e: Exception) {
+ sendEvent("error", "Failed to serialize function call: ${e.message}")
+ }
+ }
+
+ override fun onFunctionCallResult(functionCall: org.json.JSONObject, functionCallResult: org.json.JSONObject) {
+ try {
+ val meta = org.json.JSONObject().apply {
+ put("functionCall", functionCall)
+ put("functionCallResult", functionCallResult)
+ }
+ val metaString = meta.toString()
+ val context = functionCallResult.optString("context", "")
+
+ sendEvent("functionCall", context, metaString)
+ } catch (e: Exception) {
+ sendEvent("error", "Failed to serialize function call result: ${e.message}")
+ }
+ }
+ })
+ }
+
+ override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
+ methodChannel.setMethodCallHandler(null)
+ eventChannel.setStreamHandler(null)
+ pluginScope.cancel()
+ }
+
+ override fun onMethodCall(call: MethodCall, result: Result) {
+ when (call.method) {
+ "initialize" -> handleInitialize(call, result)
+ "createUserMessage" -> handleCreateUserMessage(call, result)
+ "createAssistantMessage" -> handleCreateAssistantMessage(call, result)
+ "sendMessage" -> handleSendMessage(call, result)
+ "sendMessageStream" -> handleSendMessageStream(call, result)
+ "sendFunctionCallResult" -> handleSendFunctionCallResult(call, result)
+ "cancelCurrentStream" -> handleCancelCurrentStream(result)
+ "registerFunction" -> handleRegisterFunction(call, result)
+ "initializeMcpClient" -> handleInitializeMcpClient(call, result)
+ "isMcpInitialized" -> handleIsMcpInitialized(result)
+ "closeMcpClient" -> handleCloseMcpClient(result)
+ "handleMcpToolCall" -> handleMcpToolCall(call, result)
+ else -> result.notImplemented()
+ }
+ }
+
+ // MARK: - Method Handlers
+
+ private fun handleInitialize(call: MethodCall, result: Result) {
+ val apiKey = call.argument("apiKey")
+ if (apiKey.isNullOrEmpty()) {
+ result.error("INVALID_ARGS", "缺少必要参数", null)
+ return
+ }
+
+ val baseUrl = call.argument("baseUrl") ?: ""
+ val model = call.argument("model") ?: ""
+ val mcpServer = call.argument("mcpServer") ?: ""
+
+ val success = chatApiService.initialize(apiKey, baseUrl, model, mcpServer)
+ result.success(success)
+ }
+
+ private fun handleCreateUserMessage(call: MethodCall, result: Result) {
+ val content = call.argument("content")
+ if (content.isNullOrEmpty()) {
+ result.error("INVALID_ARGS", "缺少必要参数", null)
+ return
+ }
+
+ val message = chatApiService.createUserMessage(content)
+ result.success(message)
+ }
+
+ private fun handleCreateAssistantMessage(call: MethodCall, result: Result) {
+ val content = call.argument("content")
+ if (content.isNullOrEmpty()) {
+ result.error("INVALID_ARGS", "缺少必要参数", null)
+ return
+ }
+
+ val message = chatApiService.createAssistantMessage(content)
+ result.success(message)
+ }
+
+ private fun handleSendMessage(call: MethodCall, result: Result) {
+ @Suppress("UNCHECKED_CAST")
+ val messages = call.argument>>("messages")
+ if (messages == null) {
+ result.error("INVALID_ARGS", "缺少必要参数", null)
+ return
+ }
+
+ pluginScope.launch {
+ try {
+ val response = chatApiService.sendMessage(messages)
+ mainHandler.post {
+ result.success(response)
+ }
+ } catch (e: Exception) {
+ mainHandler.post {
+ result.error("SEND_ERROR", e.message, null)
+ }
+ }
+ }
+ }
+
+ private fun handleSendMessageStream(call: MethodCall, result: Result) {
+ @Suppress("UNCHECKED_CAST")
+ val messages = call.argument>>("messages")
+ if (messages == null) {
+ result.error("INVALID_ARGS", "缺少必要参数", null)
+ return
+ }
+
+ chatApiService.sendMessageStream(messages)
+ result.success(true)
+ }
+
+ private fun handleSendFunctionCallResult(call: MethodCall, result: Result) {
+ result.error("DEPRECATED", "sendFunctionCallResult已废弃,工具调用结果现在自动处理", null)
+ }
+
+ private fun handleCancelCurrentStream(result: Result) {
+ val success = chatApiService.cancelCurrentStream()
+ result.success(success)
+ }
+
+ private fun handleRegisterFunction(call: MethodCall, result: Result) {
+ val name = call.argument("name")
+ val description = call.argument("description")
+ @Suppress("UNCHECKED_CAST")
+ val parameters = call.argument