From aa957bdc9516724359fe85196c8432905be9435b Mon Sep 17 00:00:00 2001 From: liwei1dao Date: Thu, 12 Jun 2025 21:39:36 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0android=20=E7=9A=84mcp?= =?UTF-8?q?=E8=BF=9E=E6=8E=A5=E5=92=8C=E5=BC=82=E5=B8=B8=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat_api/ChatApiService.kt | 32 ++++++++----------- .../chat_api/CustomSseClientTransport.kt | 4 ++- .../yunqiinnovation/chat_api/MCPSubClient.kt | 6 ++-- 3 files changed, 19 insertions(+), 23 deletions(-) diff --git a/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/ChatApiService.kt b/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/ChatApiService.kt index 190e2a1f0..150321d7e 100644 --- a/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/ChatApiService.kt +++ b/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/ChatApiService.kt @@ -333,7 +333,7 @@ class ChatApiService(private val context: android.content.Context? = null) : Cor chatsFlow.collect { result -> if (isCanceled) return@collect - val choice = result.choices?.firstOrNull() + val choice = result.choices.firstOrNull() if (choice == null) { Log.e("ChatApiService", "choice为null") return@collect @@ -352,33 +352,35 @@ class ChatApiService(private val context: android.content.Context? = null) : Cor // 收集工具调用信息 delta.toolCalls?.forEach { toolCall -> + val id = toolCall.id ?: run { + Log.e("ChatApiService", "toolCall.id 为空,跳过本次处理") + return@forEach + } + Log.e("ChatApiService", "AI发起工具调用: ${toolCall.id} ${toolCall.index} ${toolCall.function?.name} ${toolCall.function?.arguments}") val index = toolCall.index // 创建或获取现有的工具调用信息 val toolCallInfo = toolCalls.getOrPut(index) { ToolCallInfo() } - // 安全处理工具调用ID try { - toolCall.id?.let { id -> - toolCallInfo.id = id.toString() + toolCall.id?.let { i -> + toolCallInfo.id = i.toString() } } catch (e: Exception) { Log.e("ChatApiService", "处理工具调用ID异常: ${e.message}") } - // 安全处理函数信息 try { toolCall.function?.let { function -> try { - function.name?.let { name -> + function.name.let { name -> toolCallInfo.name = name } } catch (e: Exception) { - Log.e("ChatApiService", "处理工具调用函数名称异常: ${e.message}") + Log.e("ChatApiService", "处理工具调用函数名称异常! function:${toolCall.function} err:${e.message}") } - try { - function.arguments?.let { args -> + function.arguments.let { args -> toolCallInfo.arguments += args } } catch (e: Exception) { @@ -417,11 +419,9 @@ class ChatApiService(private val context: android.content.Context? = null) : Cor Log.e("ChatApiService", "查找有效工具调用异常: ${e.message}") null } - if (firstToolCall == null) { return false } - // 创建函数调用字典 val functionCall = try { mapOf( @@ -433,10 +433,8 @@ class ChatApiService(private val context: android.content.Context? = null) : Cor Log.e("ChatApiService", "创建函数调用字典异常: ${e.message}") return false } - // 通知上层工具调用事件 streamCallback?.onFunctionCall(convertMapToJsonObject(functionCall)) - // 在后台队列处理工具调用 launch { try { @@ -444,14 +442,13 @@ class ChatApiService(private val context: android.content.Context? = null) : Cor // 通过MCP客户端处理工具调用 val functionName = firstToolCall.name val argumentsJson = firstToolCall.arguments - val result = if (_mcpClient?.hasToolWithName(functionName) == true) { // 解析参数 val arguments = _mcpClient?.parseJsonArguments(argumentsJson) ?: emptyMap() // 调用MCP工具 val toolResult = _mcpClient?.callTool(functionName, arguments) - + Log.e("ChatApiService", "AI调用工具结果: $functionName}:$arguments} toolResult:${toolResult}") // 处理结果 if (toolResult != null) { if (toolResult["isError"] == true) { @@ -478,14 +475,12 @@ class ChatApiService(private val context: android.content.Context? = null) : Cor // 工具不存在 mapOf("context" to "Tool not found: $functionName") } - if (!isCanceled) { // 处理结果 streamCallback?.onFunctionCallResult( convertMapToJsonObject(functionCall), convertMapToJsonObject(result) ) - // 将结果发送回OpenAI继续对话 sendFunctionCallResultInternal( messages = currentMessages, @@ -855,12 +850,11 @@ class ChatApiService(private val context: android.content.Context? = null) : Cor nameOrNull = name, argumentsOrNull = arguments ) - + val toolCall = ToolCall.Function( id = ToolId(id), function = functionCall ) - toolCallsList.add(toolCall) } } diff --git a/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/CustomSseClientTransport.kt b/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/CustomSseClientTransport.kt index 14777d02a..f4bf2de9b 100644 --- a/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/CustomSseClientTransport.kt +++ b/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/CustomSseClientTransport.kt @@ -107,7 +107,9 @@ class CustomSseClientTransport( "open" -> { // SSE连接已打开 } - + "ping" -> { + // 心跳 + } "endpoint" -> { try { val eventData = event.data ?: "" diff --git a/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/MCPSubClient.kt b/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/MCPSubClient.kt index 3290c2297..a332689e2 100644 --- a/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/MCPSubClient.kt +++ b/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/MCPSubClient.kt @@ -77,11 +77,11 @@ class MCPSubClient( } // 连接到服务器 - client?.connect(transport) + client.connect(transport) // 获取可用工具列表 try { - val toolsResult = client?.listTools() + val toolsResult = client.listTools() if (toolsResult != null) { availableTools.clear() val filtered = toolsResult.tools.filter { tool -> @@ -101,7 +101,7 @@ class MCPSubClient( retryCount = 0 currentReconnectDelay = initialReconnectDelay // 启动心跳检测 - startHeartbeat() +// startHeartbeat() true } catch (e: Exception) {