Skip to content

Commit a6675c6

Browse files
authored
refactor: Optimize parameter conversion for get_api_detail func (#1869)
1 parent c34f0ca commit a6675c6

File tree

4 files changed

+385
-29
lines changed

4 files changed

+385
-29
lines changed

backend/application/workflow/workflow.go

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3631,7 +3631,25 @@ func toWorkflowAPIParameterAssistType(ty vo.FileSubType) workflow.AssistParamete
36313631
}
36323632
}
36333633

3634+
func toVariableSlice(params []*workflow.APIParameter) ([]*vo.Variable, error) {
3635+
if len(params) == 0 {
3636+
return nil, nil
3637+
}
3638+
res := make([]*vo.Variable, 0, len(params))
3639+
for _, p := range params {
3640+
v, err := toVariable(p)
3641+
if err != nil {
3642+
return nil, err
3643+
}
3644+
res = append(res, v)
3645+
}
3646+
return res, nil
3647+
}
3648+
36343649
func toVariable(p *workflow.APIParameter) (*vo.Variable, error) {
3650+
if p == nil {
3651+
return nil, nil
3652+
}
36353653
v := &vo.Variable{
36363654
Name: p.Name,
36373655
Description: p.Desc,
@@ -3653,38 +3671,33 @@ func toVariable(p *workflow.APIParameter) (*vo.Variable, error) {
36533671
v.Type = vo.VariableTypeBoolean
36543672
case workflow.ParameterType_Array:
36553673
v.Type = vo.VariableTypeList
3656-
if len(p.SubParameters) == 1 && p.SubType != nil && *p.SubType != workflow.ParameterType_Object {
3657-
av, err := toVariable(p.SubParameters[0])
3674+
if p.SubType == nil {
3675+
return nil, fmt.Errorf("array parameter '%s' is missing a SubType", p.Name)
3676+
}
3677+
// The schema of a list variable is a single variable describing the items.
3678+
itemSchema := &vo.Variable{
3679+
Type: vo.VariableType(strings.ToLower(p.SubType.String())),
3680+
}
3681+
// If the items in the array are objects, describe their structure.
3682+
if *p.SubType == workflow.ParameterType_Object {
3683+
itemFields, err := toVariableSlice(p.SubParameters)
36583684
if err != nil {
36593685
return nil, err
36603686
}
3661-
v.Schema = &av
3687+
itemSchema.Schema = itemFields
36623688
} else {
3663-
subVs := make([]any, 0)
3664-
for _, ap := range p.SubParameters {
3665-
av, err := toVariable(ap)
3666-
if err != nil {
3667-
return nil, err
3668-
}
3669-
subVs = append(subVs, av)
3670-
}
3671-
v.Schema = &vo.Variable{
3672-
Type: vo.VariableTypeObject,
3673-
Schema: subVs,
3689+
if len(p.SubParameters) > 0 && p.SubParameters[0].AssistType != nil {
3690+
itemSchema.AssistType = vo.AssistType(*p.SubParameters[0].AssistType)
36743691
}
36753692
}
3693+
v.Schema = itemSchema
36763694
case workflow.ParameterType_Object:
36773695
v.Type = vo.VariableTypeObject
3678-
vs := make([]*vo.Variable, 0)
3679-
for _, v := range p.SubParameters {
3680-
objV, err := toVariable(v)
3681-
if err != nil {
3682-
return nil, err
3683-
}
3684-
vs = append(vs, objV)
3685-
3696+
subVars, err := toVariableSlice(p.SubParameters)
3697+
if err != nil {
3698+
return nil, err
36863699
}
3687-
v.Schema = vs
3700+
v.Schema = subVars
36883701
default:
36893702
return nil, fmt.Errorf("unknown workflow api parameter type: %v", p.Type)
36903703
}
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
/*
2+
* Copyright 2025 coze-dev Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package workflow
18+
19+
import (
20+
"fmt"
21+
"strings"
22+
"testing"
23+
24+
"github.com/coze-dev/coze-studio/backend/api/model/workflow"
25+
"github.com/coze-dev/coze-studio/backend/domain/workflow/entity/vo"
26+
"github.com/coze-dev/coze-studio/backend/pkg/lang/ptr"
27+
"github.com/stretchr/testify/assert"
28+
"github.com/stretchr/testify/require"
29+
)
30+
31+
func TestToVariable(t *testing.T) {
32+
fileAssistType := workflow.AssistParameterType_DEFAULT
33+
34+
testCases := []struct {
35+
name string
36+
input *workflow.APIParameter
37+
expected *vo.Variable
38+
expectErr bool
39+
expectedErrAs any
40+
}{
41+
{
42+
name: "Nil Input",
43+
input: nil,
44+
expected: nil,
45+
},
46+
{
47+
name: "Simple String",
48+
input: &workflow.APIParameter{
49+
Name: "prompt", Type: workflow.ParameterType_String, IsRequired: true,
50+
},
51+
expected: &vo.Variable{
52+
Name: "prompt", Type: vo.VariableTypeString, Required: true,
53+
},
54+
},
55+
{
56+
name: "Simple Object",
57+
input: &workflow.APIParameter{
58+
Name: "user",
59+
Type: workflow.ParameterType_Object,
60+
SubParameters: []*workflow.APIParameter{
61+
{Name: "name", Type: workflow.ParameterType_String},
62+
{Name: "age", Type: workflow.ParameterType_Integer},
63+
},
64+
},
65+
expected: &vo.Variable{
66+
Name: "user",
67+
Type: vo.VariableTypeObject,
68+
Schema: []*vo.Variable{
69+
{Name: "name", Type: vo.VariableTypeString},
70+
{Name: "age", Type: vo.VariableTypeInteger},
71+
},
72+
},
73+
},
74+
{
75+
name: "Array of Objects",
76+
input: &workflow.APIParameter{
77+
Name: "items",
78+
Type: workflow.ParameterType_Array,
79+
SubType: ptr.Of(workflow.ParameterType_Object),
80+
SubParameters: []*workflow.APIParameter{
81+
{Name: "id", Type: workflow.ParameterType_String},
82+
{Name: "price", Type: workflow.ParameterType_Number},
83+
},
84+
},
85+
expected: &vo.Variable{
86+
Name: "items",
87+
Type: vo.VariableTypeList,
88+
Schema: &vo.Variable{
89+
Type: vo.VariableTypeObject,
90+
Schema: []*vo.Variable{
91+
{Name: "id", Type: vo.VariableTypeString},
92+
{Name: "price", Type: vo.VariableTypeFloat},
93+
},
94+
},
95+
},
96+
},
97+
{
98+
name: "Array of Primitives (File)",
99+
input: &workflow.APIParameter{
100+
Name: "attachments",
101+
Type: workflow.ParameterType_Array,
102+
SubType: ptr.Of(workflow.ParameterType_String),
103+
SubParameters: []*workflow.APIParameter{
104+
{AssistType: &fileAssistType},
105+
},
106+
},
107+
expected: &vo.Variable{
108+
Name: "attachments",
109+
Type: vo.VariableTypeList,
110+
Schema: &vo.Variable{
111+
Type: vo.VariableTypeString,
112+
AssistType: vo.AssistType(fileAssistType),
113+
},
114+
},
115+
},
116+
{
117+
name: "Array of Primitives (String)",
118+
input: &workflow.APIParameter{
119+
Name: "tags",
120+
Type: workflow.ParameterType_Array,
121+
SubType: ptr.Of(workflow.ParameterType_String),
122+
},
123+
expected: &vo.Variable{
124+
Name: "tags",
125+
Type: vo.VariableTypeList,
126+
Schema: &vo.Variable{
127+
Type: vo.VariableTypeString,
128+
},
129+
},
130+
},
131+
{
132+
name: "Array with missing SubType",
133+
input: &workflow.APIParameter{
134+
Name: "bad_array",
135+
Type: workflow.ParameterType_Array,
136+
},
137+
expectErr: true,
138+
expectedErrAs: "missing a SubType",
139+
},
140+
}
141+
142+
for _, tc := range testCases {
143+
t.Run(tc.name, func(t *testing.T) {
144+
actual, err := toVariable(tc.input)
145+
146+
if tc.expectErr {
147+
require.Error(t, err)
148+
if tc.expectedErrAs != nil {
149+
assert.True(t, strings.Contains(err.Error(), fmt.Sprint(tc.expectedErrAs)))
150+
}
151+
return
152+
}
153+
154+
require.NoError(t, err)
155+
assert.Equal(t, tc.expected, actual)
156+
})
157+
}
158+
}

backend/crossdomain/impl/plugin/plugin.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -571,31 +571,29 @@ func toWorkflowAPIParameter(parameter *common.APIParameter) *workflow3.APIParame
571571
if parameter.SubType != nil {
572572
p.SubType = ptr.Of(workflow3.ParameterType(*parameter.SubType))
573573
}
574-
575574
if parameter.DefaultParamSource != nil {
576575
p.DefaultParamSource = ptr.Of(workflow3.DefaultParamSource(*parameter.DefaultParamSource))
577576
}
578577
if parameter.AssistType != nil {
579578
p.AssistType = ptr.Of(workflow3.AssistParameterType(*parameter.AssistType))
580579
}
581580

582-
// Check if it's an array that needs unwrapping.
581+
// Check if it's a specially wrapped array that needs unwrapping.
583582
if parameter.Type == common.ParameterType_Array && len(parameter.SubParameters) == 1 && parameter.SubParameters[0].Name == "[Array Item]" {
584583
arrayItem := parameter.SubParameters[0]
584+
// The actual type of array elements is the type of the "[Array Item]".
585585
p.SubType = ptr.Of(workflow3.ParameterType(arrayItem.Type))
586-
// If the "[Array Item]" is an object, its sub-parameters become the array's sub-parameters.
586+
// If the array elements are objects, their sub-parameters (fields) are lifted up.
587587
if arrayItem.Type == common.ParameterType_Object {
588588
p.SubParameters = make([]*workflow3.APIParameter, 0, len(arrayItem.SubParameters))
589589
for _, subParam := range arrayItem.SubParameters {
590590
p.SubParameters = append(p.SubParameters, toWorkflowAPIParameter(subParam))
591591
}
592592
} else {
593-
// The array's SubType is the Type of the "[Array Item]".
594593
p.SubParameters = make([]*workflow3.APIParameter, 0, 1)
595594
p.SubParameters = append(p.SubParameters, toWorkflowAPIParameter(arrayItem))
596-
p.SubParameters[0].Name = "" // Remove the "[Array Item]" name.
597595
}
598-
} else if len(parameter.SubParameters) > 0 { // A simple object or a non-wrapped array.
596+
} else if len(parameter.SubParameters) > 0 {
599597
p.SubParameters = make([]*workflow3.APIParameter, 0, len(parameter.SubParameters))
600598
for _, subParam := range parameter.SubParameters {
601599
p.SubParameters = append(p.SubParameters, toWorkflowAPIParameter(subParam))

0 commit comments

Comments
 (0)