|
|
@@ -2,15 +2,21 @@ package kit
|
|
|
|
|
|
import (
|
|
|
"bytes"
|
|
|
+ "context"
|
|
|
+ "crypto/rand"
|
|
|
"encoding/csv"
|
|
|
+ "encoding/hex"
|
|
|
"encoding/json"
|
|
|
"errors"
|
|
|
"fmt"
|
|
|
+ "net"
|
|
|
"reflect"
|
|
|
"strings"
|
|
|
"unicode/utf8"
|
|
|
|
|
|
"github.com/mark3labs/mcp-go/mcp"
|
|
|
+ "go.mongodb.org/mongo-driver/mongo"
|
|
|
+ "go.uber.org/zap"
|
|
|
|
|
|
"fwh-toolbox-server/utils/pii"
|
|
|
)
|
|
|
@@ -40,7 +46,38 @@ func Failf(format string, a ...any) *mcp.CallToolResult {
|
|
|
|
|
|
// Upstream 上游(FWH 平台、数据库、Plane 等)调用失败。
|
|
|
func Upstream(source string, err error) *mcp.CallToolResult {
|
|
|
- return mcp.NewToolResultError(fmt.Sprintf("调用%s失败:%v。可以稍后重试,或缩小查询范围。", source, err))
|
|
|
+ return mcp.NewToolResultError(UpstreamText(source, err) + "。可以稍后重试,或缩小查询范围。")
|
|
|
+}
|
|
|
+
|
|
|
+// UpstreamText 写给模型的上游错误说明:只给数据源、错误类别与错误编号。
|
|
|
+// 原始错误可能含内部地址、SQL、库表名,只写入日志(按错误编号检索),不返回给模型。
|
|
|
+func UpstreamText(source string, err error) string {
|
|
|
+ ref := errorRef()
|
|
|
+ zap.L().Warn("[agent-mcp] 上游调用失败", zap.String("source", source), zap.String("ref", ref), zap.Error(err))
|
|
|
+ return fmt.Sprintf("调用%s失败(%s,错误编号 %s)", source, errorKind(err), ref)
|
|
|
+}
|
|
|
+
|
|
|
+func errorKind(err error) string {
|
|
|
+ var ne net.Error
|
|
|
+ switch {
|
|
|
+ case errors.Is(err, context.DeadlineExceeded):
|
|
|
+ return "请求超时"
|
|
|
+ case errors.Is(err, context.Canceled):
|
|
|
+ return "请求已取消"
|
|
|
+ case errors.Is(err, mongo.ErrNoDocuments):
|
|
|
+ return "没有找到对应记录"
|
|
|
+ case errors.As(err, &ne) && ne.Timeout():
|
|
|
+ return "请求超时"
|
|
|
+ case errors.As(err, &ne):
|
|
|
+ return "网络连接失败"
|
|
|
+ }
|
|
|
+ return "数据源返回错误"
|
|
|
+}
|
|
|
+
|
|
|
+func errorRef() string {
|
|
|
+ b := make([]byte, 4)
|
|
|
+ _, _ = rand.Read(b)
|
|
|
+ return hex.EncodeToString(b)
|
|
|
}
|
|
|
|
|
|
// Empty 无数据时的统一返回(不是错误)。
|