Browse Source

上传mcp代码

weicu
liwei1dao 1 year ago
parent
commit
650e89bbce
  1. 4
      lib/data/models/appconfig_model.dart
  2. 6
      lib/data/models/appconfig_model.g.dart
  3. 5
      lib/data/models/user_Info.dart
  4. 1
      lib/modules/login/controllers/login_controller.dart
  5. 6
      lib/modules/pairing/controllers/pairing_controller.dart
  6. 8
      local_plugins/open_ai_service/android/src/main/kotlin/com/yunqiinnovation/open_ai_service/OpenAIService.kt
  7. 72
      local_plugins/open_ai_service/android/src/main/kotlin/com/yunqiinnovation/open_ai_service/mcp/CustomSseClientTransport.kt

4
lib/data/models/appconfig_model.dart

@ -27,7 +27,7 @@ class DBAgent {
final String? welcomeMessage; final String? welcomeMessage;
final String? voiceWelcomeMessage; final String? voiceWelcomeMessage;
final String? systemPrompt; final String? systemPrompt;
final List<String>? tools; final String? tools;
DBAgent({ DBAgent({
required this.id, required this.id,
@ -52,7 +52,7 @@ class DBAgent {
class DBMCPServer { class DBMCPServer {
final String servername; final String servername;
final String url; final String url;
final List<String>? tools; final String? tools;
DBMCPServer({ DBMCPServer({
required this.servername, required this.servername,
required this.url, required this.url,

6
lib/data/models/appconfig_model.g.dart

@ -37,8 +37,7 @@ DBAgent _$DBAgentFromJson(Map<String, dynamic> json) => DBAgent(
welcomeMessage: json['welcomeMessage'] as String?, welcomeMessage: json['welcomeMessage'] as String?,
voiceWelcomeMessage: json['voiceWelcomeMessage'] as String?, voiceWelcomeMessage: json['voiceWelcomeMessage'] as String?,
systemPrompt: json['systemPrompt'] as String?, systemPrompt: json['systemPrompt'] as String?,
tools: tools: json['tools'] as String?,
(json['tools'] as List<dynamic>?)?.map((e) => e as String).toList(),
); );
Map<String, dynamic> _$DBAgentToJson(DBAgent instance) => <String, dynamic>{ Map<String, dynamic> _$DBAgentToJson(DBAgent instance) => <String, dynamic>{
@ -58,8 +57,7 @@ Map<String, dynamic> _$DBAgentToJson(DBAgent instance) => <String, dynamic>{
DBMCPServer _$DBMCPServerFromJson(Map<String, dynamic> json) => DBMCPServer( DBMCPServer _$DBMCPServerFromJson(Map<String, dynamic> json) => DBMCPServer(
servername: json['servername'] as String, servername: json['servername'] as String,
url: json['url'] as String, url: json['url'] as String,
tools: tools: json['tools'] as String?,
(json['tools'] as List<dynamic>?)?.map((e) => e as String).toList(),
); );
Map<String, dynamic> _$DBMCPServerToJson(DBMCPServer instance) => Map<String, dynamic> _$DBMCPServerToJson(DBMCPServer instance) =>

5
lib/data/models/user_Info.dart

@ -1,6 +1,3 @@
import 'dart:convert';
import 'dart:ffi';
class User { class User {
// 单例实例 // 单例实例
static User? _instance; static User? _instance;
@ -24,7 +21,7 @@ class User {
String phone; String phone;
String phonemac; String phonemac;
String password; String password;
int membershipLevel=0;//添加会员等级字段,0表示普通用户 int membershipLevel = 0; //添加会员等级字段,0表示普通用户
// final Int64 lastbettime; // final Int64 lastbettime;
// final Int64 createtime; // final Int64 createtime;
// final String wxopenid; // final String wxopenid;

1
lib/modules/login/controllers/login_controller.dart

@ -5,7 +5,6 @@ import 'package:flutter/material.dart';
import 'package:logger/web.dart'; import 'package:logger/web.dart';
import '../../../routes/app_routes.dart'; import '../../../routes/app_routes.dart';
import 'dart:convert'; import 'dart:convert';
import 'dart:ffi';
import 'facebookLogin.dart'; import 'facebookLogin.dart';
import 'googleLogin.dart'; import 'googleLogin.dart';
import 'weixinLogin.dart'; import 'weixinLogin.dart';

6
lib/modules/pairing/controllers/pairing_controller.dart

@ -224,7 +224,8 @@ class PairingController extends GetxController {
// 如果有权限未授予,但不是永久拒绝,继续尝试 // 如果有权限未授予,但不是永久拒绝,继续尝试
if (!allGranted) { if (!allGranted) {
bool hasPermanentlyDenied = statuses.values.any((status) => status.isPermanentlyDenied); bool hasPermanentlyDenied =
statuses.values.any((status) => status.isPermanentlyDenied);
if (hasPermanentlyDenied) { if (hasPermanentlyDenied) {
// 有权限被永久拒绝,需要引导用户去设置 // 有权限被永久拒绝,需要引导用户去设置
_showPermissionSettingsDialog('部分权限被永久拒绝,请在设置中启用'); _showPermissionSettingsDialog('部分权限被永久拒绝,请在设置中启用');
@ -239,7 +240,8 @@ class PairingController extends GetxController {
// 检测AccessorySetupKit支持情况(iOS 18+特性) // 检测AccessorySetupKit支持情况(iOS 18+特性)
bool companionSupported = await _bleService.isCompanionSupported(); bool companionSupported = await _bleService.isCompanionSupported();
Logger.i(_tag, 'iOS Companion支持检查: ${companionSupported ? "支持" : "不支持"}'); Logger.i(
_tag, 'iOS Companion支持检查: ${companionSupported ? "支持" : "不支持"}');
if (companionSupported) { if (companionSupported) {
// 针对iOS 18+,尝试预热AccessorySetupKit框架 // 针对iOS 18+,尝试预热AccessorySetupKit框架

8
local_plugins/open_ai_service/android/src/main/kotlin/com/yunqiinnovation/open_ai_service/OpenAIService.kt

@ -677,10 +677,9 @@ class OpenAIService(private val context: Context? = null) : CoroutineScope {
if (function.has("arguments")) { if (function.has("arguments")) {
toolCallInfo.arguments += function.getString("arguments") toolCallInfo.arguments += function.getString("arguments")
} }
Log.d(TAG, "liwei---------------------- AI发起工具调用: tool=$function")
} }
} }
Log.d(TAG, "liwei---------------------- AI发起工具调用: tool=$toolCallsArray")
} }
} }
@ -722,11 +721,12 @@ class OpenAIService(private val context: Context? = null) : CoroutineScope {
val args = mcpClient?.parseJsonArguments(firstToolCall.arguments) ?: mapOf() val args = mcpClient?.parseJsonArguments(firstToolCall.arguments) ?: mapOf()
mcpClient?.callTool(firstToolCall.name, args) mcpClient?.callTool(firstToolCall.name, args)
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "liwei----------------------- 工具调用错误: ${e.message}") Log.e(TAG, "liwei----------------------- 工具调用错误: $e")
JSONObject().put("context", "工具调用失败: ${e.message}") JSONObject().put("context", "工具调用失败: ${e.message}")
} }
if (!isCanceled) { if (!isCanceled) {
// 处理结果 // 处理结果
val resultObj = result ?: JSONObject().put("context", "工具调用失败") val resultObj = result ?: JSONObject().put("context", "工具调用失败")
callback.onFunctionCallResult(functionCall, resultObj) callback.onFunctionCallResult(functionCall, resultObj)
@ -747,7 +747,7 @@ class OpenAIService(private val context: Context? = null) : CoroutineScope {
} }
} catch (e: Exception) { } catch (e: Exception) {
if (!isCanceled) { if (!isCanceled) {
Log.e(TAG, "liwei----------------------- 处理工具调用异常: ${e.message}") Log.e(TAG, "liwei----------------------- 处理工具调用异常: $e")
try { try {
val errorMessage = "工具调用处理失败: ${e.message}" val errorMessage = "工具调用处理失败: ${e.message}"
sendFunctionCallResult( sendFunctionCallResult(

72
local_plugins/open_ai_service/android/src/main/kotlin/com/yunqiinnovation/open_ai_service/mcp/CustomSseClientTransport.kt

@ -1,5 +1,7 @@
package com.yunqiinnovation.open_ai_service.mcp package com.yunqiinnovation.open_ai_service.mcp
import android.os.Parcel
import android.os.Parcelable
import android.util.Log import android.util.Log
import io.ktor.client.* import io.ktor.client.*
import io.ktor.client.plugins.sse.* import io.ktor.client.plugins.sse.*
@ -7,6 +9,7 @@ import io.ktor.client.request.*
import io.ktor.client.statement.* import io.ktor.client.statement.*
import io.ktor.http.* import io.ktor.http.*
import io.modelcontextprotocol.kotlin.sdk.JSONRPCMessage import io.modelcontextprotocol.kotlin.sdk.JSONRPCMessage
import io.modelcontextprotocol.kotlin.sdk.JSONRPCRequest
import io.modelcontextprotocol.kotlin.sdk.shared.AbstractTransport import io.modelcontextprotocol.kotlin.sdk.shared.AbstractTransport
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.serialization.encodeToString import kotlinx.serialization.encodeToString
@ -16,6 +19,40 @@ import kotlin.properties.Delegates
import kotlin.time.Duration import kotlin.time.Duration
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
import org.json.JSONObject import org.json.JSONObject
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonPrimitive
//@Serializable
//data class JSONRPCRequest(
// val jsonrpc: String = "2.0",
// val method: String,
// val params: JsonElement? = null,
// val id: JsonPrimitive? = null
//) : JSONRPCMessage, Parcelable {
//
// constructor(parcel: Parcel) : this(
// parcel.readString() ?: "2.0",
// parcel.readString() ?: "",
// parcel.readString()?.let { Json.decodeFromString<JsonElement>(it) },
// parcel.readString()?.let { Json.decodeFromString<JsonPrimitive>(it) }
// )
//
// override fun writeToParcel(parcel: Parcel, flags: Int) {
// parcel.writeString(jsonrpc)
// parcel.writeString(method)
// parcel.writeString(params?.let { Json.encodeToString(it) })
// parcel.writeString(id?.let { Json.encodeToString(it) })
// }
//
// override fun describeContents(): Int = 0
//
// companion object CREATOR : Parcelable.Creator<JSONRPCRequest> {
// override fun createFromParcel(parcel: Parcel): JSONRPCRequest = JSONRPCRequest(parcel)
// override fun newArray(size: Int): Array<JSONRPCRequest?> = arrayOfNulls(size)
// }
//}
/** /**
* 自定义SSE客户端传输层,修复原始SseClientTransport中的URL拼接问题 * 自定义SSE客户端传输层,修复原始SseClientTransport中的URL拼接问题
@ -40,6 +77,11 @@ class CustomSseClientTransport(
private var job: Job? = null private var job: Job? = null
private val heartbeatIntervalMs = 30_000L // 30秒
private var heartbeatJob: Job? = null
// 创建JSON解析器,增强灵活性设置 // 创建JSON解析器,增强灵活性设置
private val json = Json { private val json = Json {
ignoreUnknownKeys = true // 忽略未知字段 ignoreUnknownKeys = true // 忽略未知字段
@ -299,6 +341,9 @@ class CustomSseClientTransport(
// 收集SSE事件 // 收集SSE事件
collectEvents() collectEvents()
// 启动心跳任务
startHeartbeat()
// 等待endpoint就绪 // 等待endpoint就绪
endpoint.await() endpoint.await()
Log.d(TAG, "传输层启动完成,消息端点已就绪") Log.d(TAG, "传输层启动完成,消息端点已就绪")
@ -346,7 +391,7 @@ class CustomSseClientTransport(
Log.e(TAG, "关闭失败: 传输层未初始化") Log.e(TAG, "关闭失败: 传输层未初始化")
error("CustomSseClientTransport is not initialized!") error("CustomSseClientTransport is not initialized!")
} }
heartbeatJob?.cancel()
session.cancel() session.cancel()
_onClose() _onClose()
job?.cancelAndJoin() job?.cancelAndJoin()
@ -359,4 +404,29 @@ class CustomSseClientTransport(
fun isInitialized(): Boolean { fun isInitialized(): Boolean {
return initialized.get() return initialized.get()
} }
private fun startHeartbeat() {
heartbeatJob = scope.launch {
while (isActive) {
delay(heartbeatIntervalMs)
try {
sendHeartbeat()
} catch (e: Exception) {
Log.e(TAG, "心跳发送失败: ${e.message}", e)
_onError(e)
}
}
}
}
private suspend fun sendHeartbeat() {
val pingMessage = JSONRPCRequest(
method = "ping",
jsonrpc = "2.0"
)
send(pingMessage)
}
} }
Loading…
Cancel
Save