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

Loading…
Cancel
Save