195 lines
5.0 KiB
Go
195 lines
5.0 KiB
Go
/*
|
|
* Copyright 2025 coze-dev Authors
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package selector
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
einoCompose "github.com/cloudwego/eino/compose"
|
|
|
|
"github.com/coze-dev/coze-studio/backend/domain/workflow/entity"
|
|
"github.com/coze-dev/coze-studio/backend/domain/workflow/entity/vo"
|
|
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/canvas/convert"
|
|
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/nodes"
|
|
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/schema"
|
|
)
|
|
|
|
type ClauseRelation string
|
|
|
|
const (
|
|
ClauseRelationAND ClauseRelation = "and"
|
|
ClauseRelationOR ClauseRelation = "or"
|
|
)
|
|
|
|
type OneClauseSchema struct {
|
|
Single *Operator `json:"single,omitempty"`
|
|
Multi *MultiClauseSchema `json:"multi,omitempty"`
|
|
}
|
|
|
|
type MultiClauseSchema struct {
|
|
Clauses []*Operator `json:"clauses"`
|
|
Relation ClauseRelation `json:"relation"`
|
|
}
|
|
|
|
func (c ClauseRelation) ToVOLogicType() vo.LogicType {
|
|
if c == ClauseRelationAND {
|
|
return vo.AND
|
|
} else if c == ClauseRelationOR {
|
|
return vo.OR
|
|
}
|
|
|
|
panic(fmt.Sprintf("unknown clause relation: %s", c))
|
|
}
|
|
|
|
func (c *Config) Adapt(_ context.Context, n *vo.Node, _ ...nodes.AdaptOption) (*schema.NodeSchema, error) {
|
|
clauses := make([]*OneClauseSchema, 0)
|
|
ns := &schema.NodeSchema{
|
|
Key: vo.NodeKey(n.ID),
|
|
Name: n.Data.Meta.Title,
|
|
Type: entity.NodeTypeSelector,
|
|
Configs: c,
|
|
}
|
|
|
|
for i, branchCond := range n.Data.Inputs.Branches {
|
|
inputType := &vo.TypeInfo{
|
|
Type: vo.DataTypeObject,
|
|
Properties: map[string]*vo.TypeInfo{},
|
|
}
|
|
|
|
if len(branchCond.Condition.Conditions) == 1 { // single condition
|
|
cond := branchCond.Condition.Conditions[0]
|
|
|
|
left := cond.Left
|
|
if left == nil {
|
|
return nil, fmt.Errorf("operator left is nil")
|
|
}
|
|
|
|
leftType, err := convert.CanvasBlockInputToTypeInfo(left.Input)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
leftSources, err := convert.CanvasBlockInputToFieldInfo(left.Input, einoCompose.FieldPath{fmt.Sprintf("%d", i), LeftKey}, n.Parent())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
inputType.Properties[LeftKey] = leftType
|
|
|
|
ns.AddInputSource(leftSources...)
|
|
|
|
op, err := ToSelectorOperator(cond.Operator, leftType)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if cond.Right != nil {
|
|
rightType, err := convert.CanvasBlockInputToTypeInfo(cond.Right.Input)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
rightSources, err := convert.CanvasBlockInputToFieldInfo(cond.Right.Input, einoCompose.FieldPath{fmt.Sprintf("%d", i), RightKey}, n.Parent())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
inputType.Properties[RightKey] = rightType
|
|
ns.AddInputSource(rightSources...)
|
|
}
|
|
|
|
ns.SetInputType(fmt.Sprintf("%d", i), inputType)
|
|
|
|
clauses = append(clauses, &OneClauseSchema{
|
|
Single: &op,
|
|
})
|
|
|
|
continue
|
|
}
|
|
|
|
var relation ClauseRelation
|
|
logic := branchCond.Condition.Logic
|
|
if logic == vo.OR {
|
|
relation = ClauseRelationOR
|
|
} else if logic == vo.AND {
|
|
relation = ClauseRelationAND
|
|
}
|
|
|
|
var ops []*Operator
|
|
for j, cond := range branchCond.Condition.Conditions {
|
|
left := cond.Left
|
|
if left == nil {
|
|
return nil, fmt.Errorf("operator left is nil")
|
|
}
|
|
|
|
leftType, err := convert.CanvasBlockInputToTypeInfo(left.Input)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
leftSources, err := convert.CanvasBlockInputToFieldInfo(left.Input, einoCompose.FieldPath{fmt.Sprintf("%d", i), fmt.Sprintf("%d", j), LeftKey}, n.Parent())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
inputType.Properties[fmt.Sprintf("%d", j)] = &vo.TypeInfo{
|
|
Type: vo.DataTypeObject,
|
|
Properties: map[string]*vo.TypeInfo{
|
|
LeftKey: leftType,
|
|
},
|
|
}
|
|
|
|
ns.AddInputSource(leftSources...)
|
|
|
|
op, err := ToSelectorOperator(cond.Operator, leftType)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
ops = append(ops, &op)
|
|
|
|
if cond.Right != nil {
|
|
rightType, err := convert.CanvasBlockInputToTypeInfo(cond.Right.Input)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
rightSources, err := convert.CanvasBlockInputToFieldInfo(cond.Right.Input, einoCompose.FieldPath{fmt.Sprintf("%d", i), fmt.Sprintf("%d", j), RightKey}, n.Parent())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
inputType.Properties[fmt.Sprintf("%d", j)].Properties[RightKey] = rightType
|
|
ns.AddInputSource(rightSources...)
|
|
}
|
|
}
|
|
|
|
ns.SetInputType(fmt.Sprintf("%d", i), inputType)
|
|
|
|
clauses = append(clauses, &OneClauseSchema{
|
|
Multi: &MultiClauseSchema{
|
|
Clauses: ops,
|
|
Relation: relation,
|
|
},
|
|
})
|
|
}
|
|
|
|
c.Clauses = clauses
|
|
|
|
return ns, nil
|
|
}
|