feat(plugin): supports using json marshal to correct string types by … (#758)

This commit is contained in:
mrh997 2025-08-14 17:24:36 +08:00 committed by GitHub
parent 3030d4d627
commit d58783b11c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 23 additions and 19 deletions

View File

@ -263,28 +263,28 @@ func MustString(value any) string {
} }
} }
func TryFixValueType(paramName string, schemaRef *openapi3.SchemaRef, value any) (any, error) { func TryCorrectValueType(paramName string, schemaRef *openapi3.SchemaRef, value any) (any, error) {
if value == nil { if value == nil {
return "", fmt.Errorf("value of '%s' is nil", paramName) return "", fmt.Errorf("value of '%s' is nil", paramName)
} }
switch schemaRef.Value.Type { switch schemaRef.Value.Type {
case openapi3.TypeString: case openapi3.TypeString:
return tryString(value) return tryCorrectString(value)
case openapi3.TypeNumber: case openapi3.TypeNumber:
return tryFloat64(value) return tryCorrectFloat64(value)
case openapi3.TypeInteger: case openapi3.TypeInteger:
return tryInt64(value) return tryCorrectInt64(value)
case openapi3.TypeBoolean: case openapi3.TypeBoolean:
return tryBool(value) return tryCorrectBool(value)
case openapi3.TypeArray: case openapi3.TypeArray:
arrVal, ok := value.([]any) arrVal, ok := value.([]any)
if !ok { if !ok {
return nil, fmt.Errorf("[TryFixValueType] value '%s' is not array", paramName) return nil, fmt.Errorf("[TryCorrectValueType] value '%s' is not array", paramName)
} }
for i, v := range arrVal { for i, v := range arrVal {
_v, err := TryFixValueType(paramName, schemaRef.Value.Items, v) _v, err := TryCorrectValueType(paramName, schemaRef.Value.Items, v)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -296,7 +296,7 @@ func TryFixValueType(paramName string, schemaRef *openapi3.SchemaRef, value any)
case openapi3.TypeObject: case openapi3.TypeObject:
mapVal, ok := value.(map[string]any) mapVal, ok := value.(map[string]any)
if !ok { if !ok {
return nil, fmt.Errorf("[TryFixValueType] value '%s' is not object", paramName) return nil, fmt.Errorf("[TryCorrectValueType] value '%s' is not object", paramName)
} }
for k, v := range mapVal { for k, v := range mapVal {
@ -305,7 +305,7 @@ func TryFixValueType(paramName string, schemaRef *openapi3.SchemaRef, value any)
continue continue
} }
_v, err := TryFixValueType(k, p, v) _v, err := TryCorrectValueType(k, p, v)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -315,11 +315,11 @@ func TryFixValueType(paramName string, schemaRef *openapi3.SchemaRef, value any)
return mapVal, nil return mapVal, nil
default: default:
return nil, fmt.Errorf("[TryFixValueType] unsupported schema type '%s'", schemaRef.Value.Type) return nil, fmt.Errorf("[TryCorrectValueType] unsupported schema type '%s'", schemaRef.Value.Type)
} }
} }
func tryString(value any) (string, error) { func tryCorrectString(value any) (string, error) {
switch val := value.(type) { switch val := value.(type) {
case string: case string:
return val, nil return val, nil
@ -331,11 +331,15 @@ func tryString(value any) (string, error) {
case json.Number: case json.Number:
return val.String(), nil return val.String(), nil
default: default:
return "", fmt.Errorf("cannot convert type from '%T' to string", val) b, err := sonic.MarshalString(value)
if err != nil {
return "", fmt.Errorf("tryCorrectString failed, err=%w", err)
}
return b, nil
} }
} }
func tryInt64(value any) (int64, error) { func tryCorrectInt64(value any) (int64, error) {
switch val := value.(type) { switch val := value.(type) {
case string: case string:
vi64, _ := strconv.ParseInt(val, 10, 64) vi64, _ := strconv.ParseInt(val, 10, 64)
@ -352,7 +356,7 @@ func tryInt64(value any) (int64, error) {
} }
} }
func tryBool(value any) (bool, error) { func tryCorrectBool(value any) (bool, error) {
switch val := value.(type) { switch val := value.(type) {
case string: case string:
return strconv.ParseBool(val) return strconv.ParseBool(val)
@ -363,7 +367,7 @@ func tryBool(value any) (bool, error) {
} }
} }
func tryFloat64(value any) (float64, error) { func tryCorrectFloat64(value any) (float64, error) {
switch val := value.(type) { switch val := value.(type) {
case string: case string:
return strconv.ParseFloat(val, 64) return strconv.ParseFloat(val, 64)

View File

@ -1100,15 +1100,15 @@ func (t *toolExecutor) processWithInvalidRespProcessStrategyOfReturnErr(_ contex
processor = func(paramName string, paramVal any, schemaVal *openapi3.Schema) (any, error) { processor = func(paramName string, paramVal any, schemaVal *openapi3.Schema) (any, error) {
switch schemaVal.Type { switch schemaVal.Type {
case openapi3.TypeObject: case openapi3.TypeObject:
newParamValMap := map[string]any{}
paramValMap, ok := paramVal.(map[string]any) paramValMap, ok := paramVal.(map[string]any)
if !ok { if !ok {
return nil, errorx.New(errno.ErrPluginExecuteToolFailed, errorx.KVf(errno.PluginMsgKey, return nil, errorx.New(errno.ErrPluginExecuteToolFailed, errorx.KVf(errno.PluginMsgKey,
"expected '%s' to be of type 'object', but got '%T'", paramName, paramVal)) "expected '%s' to be of type 'object', but got '%T'", paramName, paramVal))
} }
newParamValMap := map[string]any{}
for paramName_, paramVal_ := range paramValMap { for paramName_, paramVal_ := range paramValMap {
paramSchema_, ok := schemaVal.Properties[paramName] paramSchema_, ok := schemaVal.Properties[paramName_]
if !ok || t.disabledParam(paramSchema_.Value) { // Only the object field can be disabled, and the top level of request and response must be the object structure if !ok || t.disabledParam(paramSchema_.Value) { // Only the object field can be disabled, and the top level of request and response must be the object structure
continue continue
} }
@ -1122,13 +1122,13 @@ func (t *toolExecutor) processWithInvalidRespProcessStrategyOfReturnErr(_ contex
return newParamValMap, nil return newParamValMap, nil
case openapi3.TypeArray: case openapi3.TypeArray:
newParamValSlice := []any{}
paramValSlice, ok := paramVal.([]any) paramValSlice, ok := paramVal.([]any)
if !ok { if !ok {
return nil, errorx.New(errno.ErrPluginExecuteToolFailed, errorx.KVf(errno.PluginMsgKey, return nil, errorx.New(errno.ErrPluginExecuteToolFailed, errorx.KVf(errno.PluginMsgKey,
"expected '%s' to be of type 'array', but got '%T'", paramName, paramVal)) "expected '%s' to be of type 'array', but got '%T'", paramName, paramVal))
} }
newParamValSlice := []any{}
for _, paramVal_ := range paramValSlice { for _, paramVal_ := range paramValSlice {
newParamVal, err := processor(paramName, paramVal_, schemaVal.Items.Value) newParamVal, err := processor(paramName, paramVal_, schemaVal.Items.Value)
if err != nil { if err != nil {
@ -1426,7 +1426,7 @@ func (t *toolExecutor) buildRequestBody(ctx context.Context, op *model.Openapi3O
continue continue
} }
_value, err := encoder.TryFixValueType(paramName, prop, value) _value, err := encoder.TryCorrectValueType(paramName, prop, value)
if err != nil { if err != nil {
return nil, "", err return nil, "", err
} }