mirror of
https://wget.la/https://github.com/leookun/cursor-byok
synced 2026-08-18 03:57:06 +08:00
111 lines
2.8 KiB
Go
111 lines
2.8 KiB
Go
package runtimecore
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strings"
|
|
)
|
|
|
|
// MCPToolPayload 表示 CallMcpTool 的宽容解码结果。
|
|
type MCPToolPayload struct {
|
|
Server string
|
|
ProviderIdentifier string
|
|
ToolName string
|
|
Name string
|
|
Arguments map[string]any
|
|
}
|
|
|
|
// DecodeMCPToolPayload 解析 CallMcpTool 参数,并兼容字符串化的 arguments 对象。
|
|
func DecodeMCPToolPayload(raw []byte) (MCPToolPayload, error) {
|
|
payload := MCPToolPayload{
|
|
Arguments: make(map[string]any),
|
|
}
|
|
if len(raw) == 0 {
|
|
return payload, nil
|
|
}
|
|
|
|
var decoded map[string]any
|
|
if err := json.Unmarshal(raw, &decoded); err != nil {
|
|
return payload, err
|
|
}
|
|
if decoded == nil {
|
|
return payload, nil
|
|
}
|
|
|
|
payload.Server = decodeJSONStringValue(decoded["server"])
|
|
payload.ProviderIdentifier = decodeJSONStringValue(decoded["providerIdentifier"])
|
|
payload.ToolName = decodeJSONStringValue(decoded["toolName"])
|
|
payload.Name = decodeJSONStringValue(decoded["name"])
|
|
payload.Arguments = decodeJSONObjectLike(decoded["arguments"])
|
|
if len(payload.Arguments) == 0 {
|
|
payload.Arguments = decodeJSONObjectLike(decoded["args"])
|
|
}
|
|
return payload, nil
|
|
}
|
|
|
|
// InferMCPServerIdentifier 从 canonical lookup name 中反推出 server identifier。
|
|
func InferMCPServerIdentifier(name string) string {
|
|
trimmed := strings.TrimSpace(name)
|
|
if trimmed == "" {
|
|
return ""
|
|
}
|
|
if index := strings.Index(trimmed, "-"); index > 0 {
|
|
return strings.TrimSpace(trimmed[:index])
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// InferMCPToolName 从 canonical lookup name 中反推出 tool name。
|
|
func InferMCPToolName(serverIdentifier string, name string) string {
|
|
trimmedName := strings.TrimSpace(name)
|
|
if trimmedName == "" {
|
|
return ""
|
|
}
|
|
trimmedServer := strings.TrimSpace(serverIdentifier)
|
|
if trimmedServer != "" && strings.HasPrefix(trimmedName, trimmedServer+"-") {
|
|
return strings.TrimSpace(strings.TrimPrefix(trimmedName, trimmedServer+"-"))
|
|
}
|
|
return trimmedName
|
|
}
|
|
|
|
func decodeJSONStringValue(value any) string {
|
|
text, ok := value.(string)
|
|
if !ok {
|
|
return ""
|
|
}
|
|
return strings.TrimSpace(text)
|
|
}
|
|
|
|
func decodeJSONObjectLike(value any) map[string]any {
|
|
switch item := value.(type) {
|
|
case map[string]any:
|
|
if item == nil {
|
|
return make(map[string]any)
|
|
}
|
|
return item
|
|
case string:
|
|
return decodeJSONObjectBytes([]byte(item))
|
|
case []byte:
|
|
return decodeJSONObjectBytes(item)
|
|
case json.RawMessage:
|
|
return decodeJSONObjectBytes([]byte(item))
|
|
default:
|
|
return make(map[string]any)
|
|
}
|
|
}
|
|
|
|
func decodeJSONObjectBytes(raw []byte) map[string]any {
|
|
trimmed := strings.TrimSpace(string(raw))
|
|
if trimmed == "" {
|
|
return make(map[string]any)
|
|
}
|
|
var decoded any
|
|
if err := json.Unmarshal([]byte(trimmed), &decoded); err != nil {
|
|
return make(map[string]any)
|
|
}
|
|
object, ok := decoded.(map[string]any)
|
|
if !ok || object == nil {
|
|
return make(map[string]any)
|
|
}
|
|
return object
|
|
}
|