Skip to content

Commit ad18b9c

Browse files
authored
fix(plugin): default value for tool execution response parameter type (#683)
Co-authored-by: mrh <mrh997>
1 parent 6501e9a commit ad18b9c

File tree

7 files changed

+394
-13
lines changed

7 files changed

+394
-13
lines changed

backend/api/model/crossdomain/plugin/consts.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ type InvalidResponseProcessStrategy int8
7777
const (
7878
InvalidResponseProcessStrategyOfReturnRaw InvalidResponseProcessStrategy = 0 // If the value of a field is invalid, the raw response value of the field is returned.
7979
InvalidResponseProcessStrategyOfReturnDefault InvalidResponseProcessStrategy = 1 // If the value of a field is invalid, the default value of the field is returned.
80+
InvalidResponseProcessStrategyOfReturnErr InvalidResponseProcessStrategy = 2 // If the value of a field is invalid, error is returned.
8081
)
8182

8283
const (

backend/api/model/crossdomain/plugin/openai.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ func (op *Openapi3Operation) ToEinoSchemaParameterInfo(ctx context.Context) (map
181181
if err != nil {
182182
return nil, err
183183
}
184+
if subParam == nil {
185+
continue
186+
}
184187

185188
subParams[paramName] = subParam
186189
}

backend/application/plugin/plugin.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1152,14 +1152,24 @@ func (p *PluginApplicationService) DebugAPI(ctx context.Context, req *pluginAPI.
11521152
Resp: "{}",
11531153
}
11541154

1155+
opts := []model.ExecuteToolOpt{}
1156+
switch req.Operation {
1157+
case common.DebugOperation_Debug:
1158+
opts = append(opts, model.WithInvalidRespProcessStrategy(model.InvalidResponseProcessStrategyOfReturnErr))
1159+
case common.DebugOperation_Parse:
1160+
opts = append(opts, model.WithAutoGenRespSchema(),
1161+
model.WithInvalidRespProcessStrategy(model.InvalidResponseProcessStrategyOfReturnRaw),
1162+
)
1163+
}
1164+
11551165
res, err := p.DomainSVC.ExecuteTool(ctx, &service.ExecuteToolRequest{
11561166
UserID: conv.Int64ToStr(*userID),
11571167
PluginID: req.PluginID,
11581168
ToolID: req.APIID,
11591169
ExecScene: model.ExecSceneOfToolDebug,
11601170
ExecDraftTool: true,
11611171
ArgumentsInJson: req.Parameters,
1162-
}, model.WithAutoGenRespSchema())
1172+
}, opts...)
11631173
if err != nil {
11641174
var e errorx.StatusError
11651175
if errors.As(err, &e) {

backend/domain/agent/singleagent/internal/agentflow/node_tool_plugin.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ func (p *pluginInvokableTool) InvokableRun(ctx context.Context, argumentsInJSON
121121
}
122122

123123
opts := []pluginEntity.ExecuteToolOpt{
124+
plugin.WithInvalidRespProcessStrategy(plugin.InvalidResponseProcessStrategyOfReturnDefault),
124125
plugin.WithToolVersion(p.toolInfo.GetVersion()),
125126
plugin.WithProjectInfo(p.projectInfo),
126127
}

backend/domain/agent/singleagent/internal/agentflow/node_tool_pre_retriever.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ func (pr *toolPreCallConf) toolPreRetrieve(ctx context.Context, ar *AgentRequest
6969
}
7070

7171
opts := []pluginEntity.ExecuteToolOpt{
72+
plugin.WithInvalidRespProcessStrategy(plugin.InvalidResponseProcessStrategyOfReturnDefault),
7273
plugin.WithProjectInfo(&plugin.ProjectInfo{
7374
ProjectID: ar.Identity.AgentID,
7475
ProjectType: plugin.ProjectTypeOfAgent,

backend/domain/plugin/service/exec_tool.go

Lines changed: 125 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,33 +1037,33 @@ func (t *toolExecutor) processResponse(ctx context.Context, rawResp string) (tri
10371037
return "", nil
10381038
}
10391039

1040-
// FIXME: trimming is a weak dependency function and does not affect the response
1041-
10421040
var trimmedRespMap map[string]any
10431041
switch t.invalidRespProcessStrategy {
10441042
case model.InvalidResponseProcessStrategyOfReturnRaw:
10451043
trimmedRespMap, err = t.processWithInvalidRespProcessStrategyOfReturnRaw(ctx, respMap, schemaVal)
10461044
if err != nil {
1047-
logs.CtxErrorf(ctx, "processWithInvalidRespProcessStrategyOfReturnRaw failed, err=%v", err)
1048-
return rawResp, nil
1045+
return "", err
10491046
}
10501047

10511048
case model.InvalidResponseProcessStrategyOfReturnDefault:
10521049
trimmedRespMap, err = t.processWithInvalidRespProcessStrategyOfReturnDefault(ctx, respMap, schemaVal)
10531050
if err != nil {
1054-
logs.CtxErrorf(ctx, "processWithInvalidRespProcessStrategyOfReturnDefault failed, err=%v", err)
1055-
return rawResp, nil
1051+
return "", err
1052+
}
1053+
1054+
case model.InvalidResponseProcessStrategyOfReturnErr:
1055+
trimmedRespMap, err = t.processWithInvalidRespProcessStrategyOfReturnErr(ctx, respMap, schemaVal)
1056+
if err != nil {
1057+
return "", err
10561058
}
10571059

10581060
default:
1059-
logs.CtxErrorf(ctx, "invalid response process strategy '%d'", t.invalidRespProcessStrategy)
1060-
return rawResp, nil
1061+
return rawResp, fmt.Errorf("invalid response process strategy '%d'", t.invalidRespProcessStrategy)
10611062
}
10621063

10631064
trimmedResp, err = sonic.MarshalString(trimmedRespMap)
10641065
if err != nil {
1065-
logs.CtxErrorf(ctx, "marshal trimmed response failed, err=%v", err)
1066-
return rawResp, nil
1066+
return "", errorx.Wrapf(err, "marshal trimmed response failed")
10671067
}
10681068

10691069
return trimmedResp, nil
@@ -1095,6 +1095,115 @@ func (t *toolExecutor) processWithInvalidRespProcessStrategyOfReturnRaw(ctx cont
10951095
return paramVals, nil
10961096
}
10971097

1098+
func (t *toolExecutor) processWithInvalidRespProcessStrategyOfReturnErr(_ context.Context, paramVals map[string]any, paramSchema *openapi3.Schema) (map[string]any, error) {
1099+
var processor func(paramName string, paramVal any, schemaVal *openapi3.Schema) (any, error)
1100+
processor = func(paramName string, paramVal any, schemaVal *openapi3.Schema) (any, error) {
1101+
switch schemaVal.Type {
1102+
case openapi3.TypeObject:
1103+
newParamValMap := map[string]any{}
1104+
paramValMap, ok := paramVal.(map[string]any)
1105+
if !ok {
1106+
return nil, errorx.New(errno.ErrPluginExecuteToolFailed, errorx.KVf(errno.PluginMsgKey,
1107+
"expected '%s' to be of type 'object', but got '%T'", paramName, paramVal))
1108+
}
1109+
1110+
for paramName_, paramVal_ := range paramValMap {
1111+
paramSchema_, ok := schemaVal.Properties[paramName]
1112+
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
1113+
continue
1114+
}
1115+
newParamVal, err := processor(paramName_, paramVal_, paramSchema_.Value)
1116+
if err != nil {
1117+
return nil, err
1118+
}
1119+
newParamValMap[paramName_] = newParamVal
1120+
}
1121+
1122+
return newParamValMap, nil
1123+
1124+
case openapi3.TypeArray:
1125+
newParamValSlice := []any{}
1126+
paramValSlice, ok := paramVal.([]any)
1127+
if !ok {
1128+
return nil, errorx.New(errno.ErrPluginExecuteToolFailed, errorx.KVf(errno.PluginMsgKey,
1129+
"expected '%s' to be of type 'array', but got '%T'", paramName, paramVal))
1130+
}
1131+
1132+
for _, paramVal_ := range paramValSlice {
1133+
newParamVal, err := processor(paramName, paramVal_, schemaVal.Items.Value)
1134+
if err != nil {
1135+
return nil, err
1136+
}
1137+
if newParamVal != nil {
1138+
newParamValSlice = append(newParamValSlice, newParamVal)
1139+
}
1140+
}
1141+
1142+
return newParamValSlice, nil
1143+
1144+
case openapi3.TypeString:
1145+
paramValStr, ok := paramVal.(string)
1146+
if !ok {
1147+
return nil, errorx.New(errno.ErrPluginExecuteToolFailed, errorx.KVf(errno.PluginMsgKey,
1148+
"expected '%s' to be of type 'string', but got '%T'", paramName, paramVal))
1149+
}
1150+
1151+
return paramValStr, nil
1152+
1153+
case openapi3.TypeBoolean:
1154+
paramValBool, ok := paramVal.(bool)
1155+
if !ok {
1156+
return false, fmt.Errorf("expected '%s' to be of type 'boolean', but got '%T'", paramName, paramVal)
1157+
}
1158+
1159+
return paramValBool, nil
1160+
1161+
case openapi3.TypeInteger:
1162+
paramValNum, ok := paramVal.(json.Number)
1163+
if !ok {
1164+
return nil, errorx.New(errno.ErrPluginExecuteToolFailed, errorx.KVf(errno.PluginMsgKey,
1165+
"expected '%s' to be of type 'integer', but got '%T'", paramName, paramVal))
1166+
}
1167+
paramValInt, err := paramValNum.Int64()
1168+
if err != nil {
1169+
return nil, errorx.New(errno.ErrPluginExecuteToolFailed, errorx.KVf(errno.PluginMsgKey,
1170+
"expected '%s' to be of type 'integer', but got '%T'", paramName, paramVal))
1171+
}
1172+
1173+
return paramValInt, nil
1174+
1175+
case openapi3.TypeNumber:
1176+
paramValNum, ok := paramVal.(json.Number)
1177+
if !ok {
1178+
return nil, errorx.New(errno.ErrPluginExecuteToolFailed, errorx.KVf(errno.PluginMsgKey,
1179+
"expected '%s' to be of type 'number', but got '%T'", paramName, paramVal))
1180+
}
1181+
1182+
return paramValNum, nil
1183+
1184+
default:
1185+
return nil, fmt.Errorf("unsupported type '%s'", schemaVal.Type)
1186+
}
1187+
}
1188+
1189+
newParamVals := make(map[string]any, len(paramVals))
1190+
for paramName, paramVal_ := range paramVals {
1191+
paramSchema_, ok := paramSchema.Properties[paramName]
1192+
if !ok || t.disabledParam(paramSchema_.Value) {
1193+
continue
1194+
}
1195+
1196+
newParamVal, err := processor(paramName, paramVal_, paramSchema_.Value)
1197+
if err != nil {
1198+
return nil, err
1199+
}
1200+
1201+
newParamVals[paramName] = newParamVal
1202+
}
1203+
1204+
return newParamVals, nil
1205+
}
1206+
10981207
func (t *toolExecutor) processWithInvalidRespProcessStrategyOfReturnDefault(_ context.Context, paramVals map[string]any, paramSchema *openapi3.Schema) (map[string]any, error) {
10991208
var processor func(paramVal any, schemaVal *openapi3.Schema) (any, error)
11001209
processor = func(paramVal any, schemaVal *openapi3.Schema) (any, error) {
@@ -1156,9 +1265,13 @@ func (t *toolExecutor) processWithInvalidRespProcessStrategyOfReturnDefault(_ co
11561265
return paramValBool, nil
11571266

11581267
case openapi3.TypeInteger:
1159-
paramValInt, ok := paramVal.(float64)
1268+
paramValNum, ok := paramVal.(json.Number)
11601269
if !ok {
1161-
return float64(0), nil
1270+
return int64(0), nil
1271+
}
1272+
paramValInt, err := paramValNum.Int64()
1273+
if err != nil {
1274+
return int64(0), nil
11621275
}
11631276

11641277
return paramValInt, nil

0 commit comments

Comments
 (0)