Browse Source

上传 mcp 参数解析bug修复

newdev_shunjiawei
liwei1dao 1 year ago
parent
commit
a96995f84a
  1. 99
      local_plugins/open_ai_service/android/src/main/kotlin/com/yunqiinnovation/open_ai_service/MCPClient.kt

99
local_plugins/open_ai_service/android/src/main/kotlin/com/yunqiinnovation/open_ai_service/MCPClient.kt

@ -199,88 +199,69 @@ class MCPSubClient(
*/ */
private fun updateToolMaps() { private fun updateToolMaps() {
toolMaps.clear() toolMaps.clear()
try { try {
// 转换MCP工具为OpenAI函数格式
tools.forEach { toolUnion -> tools.forEach { toolUnion ->
val tool = toolUnion.tool().getOrNull() ?: return@forEach val tool = toolUnion.tool().getOrNull() ?: return@forEach
try { try {
// 获取工具的输入模式
val inputSchema = tool.inputSchema() ?: return@forEach val inputSchema = tool.inputSchema() ?: return@forEach
// 使用toString()获取完整JSON字符串
val schemaStr = inputSchema.toString() val schemaStr = inputSchema.toString()
Log.d(TAG, "工具 ${tool.name()} 的Schema: $schemaStr") Log.d(TAG, "工具 ${tool.name()} 的Schema: $schemaStr")
// 解析properties和required
val propertiesMap = HashMap<String, Any>() val propertiesMap = HashMap<String, Any>()
val requiredList = ArrayList<String>() val requiredList = ArrayList<String>()
try { try {
// 匹配properties内部的内容 // ✅ 替换原来的正则方式,使用括号匹配方式提取 properties 内容
val propertiesPattern = "properties=\\{(.*?)\\}(?:,|\\s|$)".toRegex(RegexOption.DOT_MATCHES_ALL) val propertiesContent = extractPropertiesContent(schemaStr)
val propertiesMatch = propertiesPattern.find(schemaStr) if (propertiesContent != null) {
if (propertiesMatch != null) {
val propertiesContent = propertiesMatch.groupValues[1]
// 匹配每个属性字段,例如 query={description=搜索信息, type=string}
val fieldPattern = "([a-zA-Z0-9_]+)=\\{([^{}]+?)\\}".toRegex() val fieldPattern = "([a-zA-Z0-9_]+)=\\{([^{}]+?)\\}".toRegex()
val fieldMatches = fieldPattern.findAll(propertiesContent) val fieldMatches = fieldPattern.findAll(propertiesContent)
fieldMatches.forEach { fieldMatch -> fieldMatches.forEach { fieldMatch ->
val fieldName = fieldMatch.groupValues[1] val fieldName = fieldMatch.groupValues[1]
val fieldContent = fieldMatch.groupValues[2] val fieldContent = fieldMatch.groupValues[2]
// 解析字段属性
val fieldMap = HashMap<String, Any>() val fieldMap = HashMap<String, Any>()
// 解析如 description=搜索信息, type=string 格式的键值对
// 同时处理带引号和不带引号的情况
val keyValuePattern = "([a-zA-Z0-9_]+)=(\"[^\"]*\"|'[^']*'|[^,}\\s]+)".toRegex() val keyValuePattern = "([a-zA-Z0-9_]+)=(\"[^\"]*\"|'[^']*'|[^,}\\s]+)".toRegex()
val keyValueMatches = keyValuePattern.findAll(fieldContent) val keyValueMatches = keyValuePattern.findAll(fieldContent)
keyValueMatches.forEach { kvMatch -> keyValueMatches.forEach { kvMatch ->
val key = kvMatch.groupValues[1] val key = kvMatch.groupValues[1]
var value = kvMatch.groupValues[2].trim() var value = kvMatch.groupValues[2].trim()
// 去除引号(如果有) if ((value.startsWith("\"") && value.endsWith("\"")) ||
if ((value.startsWith("\"") && value.endsWith("\"")) ||
(value.startsWith("'") && value.endsWith("'"))) { (value.startsWith("'") && value.endsWith("'"))) {
value = value.substring(1, value.length - 1) value = value.substring(1, value.length - 1)
} }
// 处理不同类型的值
val processedValue: Any = when { val processedValue: Any = when {
value.equals("true", ignoreCase = true) -> true value.equals("true", ignoreCase = true) -> true
value.equals("false", ignoreCase = true) -> false value.equals("false", ignoreCase = true) -> false
value.matches("\\d+".toRegex()) -> value.toIntOrNull() ?: value value.matches("\\d+".toRegex()) -> value.toIntOrNull() ?: value
value.matches("\\d+\\.\\d+".toRegex()) -> value.toDoubleOrNull() ?: value value.matches("\\d+\\.\\d+".toRegex()) -> value.toDoubleOrNull() ?: value
else -> value // 保持为字符串 else -> value
} }
fieldMap[key] = processedValue fieldMap[key] = processedValue
} }
// 添加到属性映射
propertiesMap[fieldName] = fieldMap propertiesMap[fieldName] = fieldMap
} }
Log.d(TAG, "成功解析属性: $propertiesMap") Log.d(TAG, "成功解析属性: $propertiesMap")
} }
// 解析required // ✅ required 部分保持不变
val requiredPattern = "required=\\[(.*?)\\]".toRegex() val requiredPattern = "required=\\[(.*?)\\]".toRegex()
val requiredMatch = requiredPattern.find(schemaStr) val requiredMatch = requiredPattern.find(schemaStr)
if (requiredMatch != null) { if (requiredMatch != null) {
val requiredStr = requiredMatch.groupValues[1] val requiredStr = requiredMatch.groupValues[1]
if (requiredStr.isNotEmpty()) { if (requiredStr.isNotEmpty()) {
// 处理可能带引号的字段名 val fieldNames = requiredStr.split(",").map {
val fieldNames = requiredStr.split(",").map {
val trimmed = it.trim() val trimmed = it.trim()
if ((trimmed.startsWith("\"") && trimmed.endsWith("\"")) || if ((trimmed.startsWith("\"") && trimmed.endsWith("\"")) ||
(trimmed.startsWith("'") && trimmed.endsWith("'"))) { (trimmed.startsWith("'") && trimmed.endsWith("'"))) {
trimmed.substring(1, trimmed.length - 1) trimmed.substring(1, trimmed.length - 1)
} else { } else {
@ -295,8 +276,7 @@ class MCPSubClient(
Log.e(TAG, "解析Schema字符串失败: ${e.message}", e) Log.e(TAG, "解析Schema字符串失败: ${e.message}", e)
Log.e(TAG, "原始Schema: $schemaStr") Log.e(TAG, "原始Schema: $schemaStr")
} }
// 创建OpenAI函数格式
val functionMap = mapOf( val functionMap = mapOf(
"name" to tool.name(), "name" to tool.name(),
"description" to (tool.description() ?: ""), "description" to (tool.description() ?: ""),
@ -306,13 +286,12 @@ class MCPSubClient(
"required" to requiredList "required" to requiredList
) )
) )
// 添加到工具列表
toolMaps.add(mapOf( toolMaps.add(mapOf(
"type" to "function", "type" to "function",
"function" to functionMap "function" to functionMap
)) ))
Log.d(TAG, "成功转换工具 ${tool.name()} 到OpenAI函数格式 $functionMap") Log.d(TAG, "成功转换工具 ${tool.name()} 到OpenAI函数格式 $functionMap")
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "转换工具 ${tool.name()} 失败: ${e.message}") Log.e(TAG, "转换工具 ${tool.name()} 失败: ${e.message}")
@ -321,10 +300,36 @@ class MCPSubClient(
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "更新工具映射失败: ${e.message}") Log.e(TAG, "更新工具映射失败: ${e.message}")
} }
Log.d(TAG, "更新工具映射完成,共 ${toolMaps.size} 个工具") Log.d(TAG, "更新工具映射完成,共 ${toolMaps.size} 个工具")
} }
private fun extractPropertiesContent(schemaStr: String): String? {
val startKey = "properties={"
val startIndex = schemaStr.indexOf(startKey)
if (startIndex == -1) return null
var braceCount = 0
var endIndex = -1
val contentStart = startIndex + startKey.length
for (i in contentStart until schemaStr.length) {
when (schemaStr[i]) {
'{' -> braceCount++
'}' -> {
if (braceCount == 0) {
endIndex = i
break
} else {
braceCount--
}
}
}
}
return if (endIndex != -1) schemaStr.substring(contentStart, endIndex) else null
}
/** /**
* 将JsonNode转换为Map * 将JsonNode转换为Map
*/ */

Loading…
Cancel
Save