refactor: how to add a node type in workflow (#558)
This commit is contained in:
@@ -19,24 +19,48 @@ package vo
|
||||
import (
|
||||
"github.com/coze-dev/coze-studio/backend/api/model/ocean/cloud/workflow"
|
||||
"github.com/coze-dev/coze-studio/backend/domain/workflow/crossdomain/model"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/i18n"
|
||||
"github.com/coze-dev/coze-studio/backend/pkg/lang/ternary"
|
||||
)
|
||||
|
||||
// Canvas is the definition of FRONTEND schema for a workflow.
|
||||
type Canvas struct {
|
||||
Nodes []*Node `json:"nodes"`
|
||||
Edges []*Edge `json:"edges"`
|
||||
Versions any `json:"versions"`
|
||||
}
|
||||
|
||||
// Node represents a node within a workflow canvas.
|
||||
type Node struct {
|
||||
ID string `json:"id"`
|
||||
Type BlockType `json:"type"`
|
||||
Meta any `json:"meta"`
|
||||
Data *Data `json:"data"`
|
||||
Blocks []*Node `json:"blocks,omitempty"`
|
||||
Edges []*Edge `json:"edges,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
// ID is the unique node ID within the workflow.
|
||||
// In normal use cases, this ID is generated by frontend.
|
||||
// It does NOT need to be unique between parent workflow and sub workflows.
|
||||
// The Entry node and Exit node of a workflow always have fixed node IDs: 100001 and 900001.
|
||||
ID string `json:"id"`
|
||||
|
||||
parent *Node
|
||||
// Type is the Node Type of this node instance.
|
||||
// It corresponds to the string value of 'ID' field of NodeMeta.
|
||||
Type string `json:"type"`
|
||||
|
||||
// Meta holds meta data used by frontend, such as the node's position within canvas.
|
||||
Meta any `json:"meta"`
|
||||
|
||||
// Data holds the actual configurations of a node, such as inputs, outputs and exception handling.
|
||||
// It also holds exclusive configurations for different node types, such as LLM configurations.
|
||||
Data *Data `json:"data"`
|
||||
|
||||
// Blocks holds the sub nodes of this node.
|
||||
// It is only used when the node type is Composite, such as NodeTypeBatch and NodeTypeLoop.
|
||||
Blocks []*Node `json:"blocks,omitempty"`
|
||||
|
||||
// Edges are the connections between nodes.
|
||||
// Strictly corresponds to connections drawn on canvas.
|
||||
Edges []*Edge `json:"edges,omitempty"`
|
||||
|
||||
// Version is the version of this node type's schema.
|
||||
Version string `json:"version,omitempty"`
|
||||
|
||||
parent *Node // if this node is within a composite node, coze will set this. No need to set manually
|
||||
}
|
||||
|
||||
func (n *Node) SetParent(parent *Node) {
|
||||
@@ -47,7 +71,7 @@ func (n *Node) Parent() *Node {
|
||||
return n.parent
|
||||
}
|
||||
|
||||
type NodeMeta struct {
|
||||
type NodeMetaFE struct {
|
||||
Title string `json:"title,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Icon string `json:"icon,omitempty"`
|
||||
@@ -62,52 +86,88 @@ type Edge struct {
|
||||
TargetPortID string `json:"targetPortID,omitempty"`
|
||||
}
|
||||
|
||||
// Data holds the actual configuration of a Node.
|
||||
type Data struct {
|
||||
Meta *NodeMeta `json:"nodeMeta,omitempty"`
|
||||
Outputs []any `json:"outputs,omitempty"` // either []*Variable or []*Param
|
||||
Inputs *Inputs `json:"inputs,omitempty"`
|
||||
Size any `json:"size,omitempty"`
|
||||
// Meta is the meta data of this node. Only used by frontend.
|
||||
Meta *NodeMetaFE `json:"nodeMeta,omitempty"`
|
||||
|
||||
// Outputs configures the output fields and their types.
|
||||
// Outputs can be either []*Variable (most of the cases, just fields and types),
|
||||
// or []*Param (used by composite nodes as they need to refer to outputs of sub nodes)
|
||||
Outputs []any `json:"outputs,omitempty"`
|
||||
|
||||
// Inputs configures ALL input information of a node,
|
||||
// including fixed input fields and dynamic input fields defined by user.
|
||||
Inputs *Inputs `json:"inputs,omitempty"`
|
||||
|
||||
// Size configures the size of this node in frontend.
|
||||
// Only used by NodeTypeComment.
|
||||
Size any `json:"size,omitempty"`
|
||||
}
|
||||
|
||||
type Inputs struct {
|
||||
InputParameters []*Param `json:"inputParameters"`
|
||||
Content *BlockInput `json:"content"`
|
||||
TerminatePlan *TerminatePlan `json:"terminatePlan,omitempty"`
|
||||
StreamingOutput bool `json:"streamingOutput,omitempty"`
|
||||
CallTransferVoice bool `json:"callTransferVoice,omitempty"`
|
||||
ChatHistoryWriting string `json:"chatHistoryWriting,omitempty"`
|
||||
LLMParam any `json:"llmParam,omitempty"` // The LLMParam type may be one of the LLMParam or IntentDetectorLLMParam type or QALLMParam type
|
||||
FCParam *FCParam `json:"fcParam,omitempty"`
|
||||
SettingOnError *SettingOnError `json:"settingOnError,omitempty"`
|
||||
// InputParameters are the fields defined by user for this particular node.
|
||||
InputParameters []*Param `json:"inputParameters"`
|
||||
|
||||
// SettingOnError configures common error handling strategy for nodes.
|
||||
// NOTE: enable in frontend node's form first.
|
||||
SettingOnError *SettingOnError `json:"settingOnError,omitempty"`
|
||||
|
||||
// NodeBatchInfo configures batch mode for nodes.
|
||||
// NOTE: not to be confused with NodeTypeBatch.
|
||||
NodeBatchInfo *NodeBatch `json:"batch,omitempty"`
|
||||
|
||||
// LLMParam may be one of the LLMParam or IntentDetectorLLMParam or SimpleLLMParam.
|
||||
// Shared between most nodes requiring an ChatModel to function.
|
||||
LLMParam any `json:"llmParam,omitempty"`
|
||||
|
||||
*OutputEmitter // exclusive configurations for NodeTypeEmitter and NodeTypeExit in Answer mode
|
||||
*Exit // exclusive configurations for NodeTypeExit
|
||||
*LLM // exclusive configurations for NodeTypeLLM
|
||||
*Loop // exclusive configurations for NodeTypeLoop
|
||||
*Selector // exclusive configurations for NodeTypeSelector
|
||||
*TextProcessor // exclusive configurations for NodeTypeTextProcessor
|
||||
*SubWorkflow // exclusive configurations for NodeTypeSubWorkflow
|
||||
*IntentDetector // exclusive configurations for NodeTypeIntentDetector
|
||||
*DatabaseNode // exclusive configurations for various Database nodes
|
||||
*HttpRequestNode // exclusive configurations for NodeTypeHTTPRequester
|
||||
*Knowledge // exclusive configurations for various Knowledge nodes
|
||||
*CodeRunner // exclusive configurations for NodeTypeCodeRunner
|
||||
*PluginAPIParam // exclusive configurations for NodeTypePlugin
|
||||
*VariableAggregator // exclusive configurations for NodeTypeVariableAggregator
|
||||
*VariableAssigner // exclusive configurations for NodeTypeVariableAssigner
|
||||
*QA // exclusive configurations for NodeTypeQuestionAnswer
|
||||
*Batch // exclusive configurations for NodeTypeBatch
|
||||
*Comment // exclusive configurations for NodeTypeComment
|
||||
*InputReceiver // exclusive configurations for NodeTypeInputReceiver
|
||||
}
|
||||
|
||||
type OutputEmitter struct {
|
||||
Content *BlockInput `json:"content"`
|
||||
StreamingOutput bool `json:"streamingOutput,omitempty"`
|
||||
}
|
||||
|
||||
type Exit struct {
|
||||
TerminatePlan *TerminatePlan `json:"terminatePlan,omitempty"`
|
||||
}
|
||||
|
||||
type LLM struct {
|
||||
FCParam *FCParam `json:"fcParam,omitempty"`
|
||||
}
|
||||
|
||||
type Loop struct {
|
||||
LoopType LoopType `json:"loopType,omitempty"`
|
||||
LoopCount *BlockInput `json:"loopCount,omitempty"`
|
||||
VariableParameters []*Param `json:"variableParameters,omitempty"`
|
||||
}
|
||||
|
||||
type Selector struct {
|
||||
Branches []*struct {
|
||||
Condition struct {
|
||||
Logic LogicType `json:"logic"`
|
||||
Conditions []*Condition `json:"conditions"`
|
||||
} `json:"condition"`
|
||||
} `json:"branches,omitempty"`
|
||||
|
||||
NodeBatchInfo *NodeBatch `json:"batch,omitempty"` // node in batch mode
|
||||
|
||||
*TextProcessor
|
||||
*SubWorkflow
|
||||
*IntentDetector
|
||||
*DatabaseNode
|
||||
*HttpRequestNode
|
||||
*KnowledgeIndexer
|
||||
*CodeRunner
|
||||
*PluginAPIParam
|
||||
*VariableAggregator
|
||||
*VariableAssigner
|
||||
*QA
|
||||
*Batch
|
||||
*Comment
|
||||
|
||||
OutputSchema string `json:"outputSchema,omitempty"`
|
||||
}
|
||||
|
||||
type Comment struct {
|
||||
@@ -127,7 +187,7 @@ type VariableAssigner struct {
|
||||
|
||||
type LLMParam = []*Param
|
||||
type IntentDetectorLLMParam = map[string]any
|
||||
type QALLMParam struct {
|
||||
type SimpleLLMParam struct {
|
||||
GenerationDiversity string `json:"generationDiversity"`
|
||||
MaxTokens int `json:"maxTokens"`
|
||||
ModelName string `json:"modelName"`
|
||||
@@ -248,7 +308,7 @@ type CodeRunner struct {
|
||||
Language int64 `json:"language"`
|
||||
}
|
||||
|
||||
type KnowledgeIndexer struct {
|
||||
type Knowledge struct {
|
||||
DatasetParam []*Param `json:"datasetParam,omitempty"`
|
||||
StrategyParam StrategyParam `json:"strategyParam,omitempty"`
|
||||
}
|
||||
@@ -384,23 +444,54 @@ type ChatHistorySetting struct {
|
||||
type Intent struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// Param is a node's field with type and source info.
|
||||
type Param struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Input *BlockInput `json:"input,omitempty"`
|
||||
Left *BlockInput `json:"left,omitempty"`
|
||||
Right *BlockInput `json:"right,omitempty"`
|
||||
// Name is the field's name.
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
// Input is the configurations for normal, singular field.
|
||||
Input *BlockInput `json:"input,omitempty"`
|
||||
|
||||
// Left is the configurations for the left half of an expression,
|
||||
// such as an assignment in NodeTypeVariableAssigner.
|
||||
Left *BlockInput `json:"left,omitempty"`
|
||||
|
||||
// Right is the configuration for the right half of an expression.
|
||||
Right *BlockInput `json:"right,omitempty"`
|
||||
|
||||
// Variables are configurations for a group of fields.
|
||||
// Only used in NodeTypeVariableAggregator.
|
||||
Variables []*BlockInput `json:"variables,omitempty"`
|
||||
}
|
||||
|
||||
// Variable is the configuration of a node's field, either input or output.
|
||||
type Variable struct {
|
||||
Name string `json:"name"`
|
||||
Type VariableType `json:"type"`
|
||||
Required bool `json:"required,omitempty"`
|
||||
AssistType AssistType `json:"assistType,omitempty"`
|
||||
Schema any `json:"schema,omitempty"` // either []*Variable (for object) or *Variable (for list)
|
||||
Description string `json:"description,omitempty"`
|
||||
ReadOnly bool `json:"readOnly,omitempty"`
|
||||
DefaultValue any `json:"defaultValue,omitempty"`
|
||||
// Name is the field's name as defined on canvas.
|
||||
Name string `json:"name"`
|
||||
|
||||
// Type is the field's data type, such as string, integer, number, object, array, etc.
|
||||
Type VariableType `json:"type"`
|
||||
|
||||
// Required is set to true if you checked the 'required box' on this field
|
||||
Required bool `json:"required,omitempty"`
|
||||
|
||||
// AssistType is the 'secondary' type of string fields, such as different types of file and image, or time.
|
||||
AssistType AssistType `json:"assistType,omitempty"`
|
||||
|
||||
// Schema contains detailed info for sub-fields of an object field, or element type of an array.
|
||||
Schema any `json:"schema,omitempty"` // either []*Variable (for object) or *Variable (for list)
|
||||
|
||||
// Description describes the field's intended use. Used on Entry node. Useful for workflow tools.
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
// ReadOnly indicates a field is not to be set by Node's business logic.
|
||||
// e.g. the ErrorBody field when exception strategy is configured.
|
||||
ReadOnly bool `json:"readOnly,omitempty"`
|
||||
|
||||
// DefaultValue configures the 'default value' if this field is missing in input.
|
||||
// Effective only in Entry node.
|
||||
DefaultValue any `json:"defaultValue,omitempty"`
|
||||
}
|
||||
|
||||
type BlockInput struct {
|
||||
@@ -436,48 +527,6 @@ type SubWorkflow struct {
|
||||
SpaceID string `json:"spaceId,omitempty"`
|
||||
}
|
||||
|
||||
// BlockType is the enumeration of node types for front-end canvas schema.
|
||||
// To add a new BlockType, start from a really big number such as 1000, to avoid conflict with future extensions.
|
||||
type BlockType string
|
||||
|
||||
func (b BlockType) String() string {
|
||||
return string(b)
|
||||
}
|
||||
|
||||
const (
|
||||
BlockTypeBotStart BlockType = "1"
|
||||
BlockTypeBotEnd BlockType = "2"
|
||||
BlockTypeBotLLM BlockType = "3"
|
||||
BlockTypeBotAPI BlockType = "4"
|
||||
BlockTypeBotCode BlockType = "5"
|
||||
BlockTypeBotDataset BlockType = "6"
|
||||
BlockTypeCondition BlockType = "8"
|
||||
BlockTypeBotSubWorkflow BlockType = "9"
|
||||
BlockTypeDatabase BlockType = "12"
|
||||
BlockTypeBotMessage BlockType = "13"
|
||||
BlockTypeBotText BlockType = "15"
|
||||
BlockTypeQuestion BlockType = "18"
|
||||
BlockTypeBotBreak BlockType = "19"
|
||||
BlockTypeBotLoopSetVariable BlockType = "20"
|
||||
BlockTypeBotLoop BlockType = "21"
|
||||
BlockTypeBotIntent BlockType = "22"
|
||||
BlockTypeBotDatasetWrite BlockType = "27"
|
||||
BlockTypeBotInput BlockType = "30"
|
||||
BlockTypeBotBatch BlockType = "28"
|
||||
BlockTypeBotContinue BlockType = "29"
|
||||
BlockTypeBotComment BlockType = "31"
|
||||
BlockTypeBotVariableMerge BlockType = "32"
|
||||
BlockTypeBotAssignVariable BlockType = "40"
|
||||
BlockTypeDatabaseUpdate BlockType = "42"
|
||||
BlockTypeDatabaseSelect BlockType = "43"
|
||||
BlockTypeDatabaseDelete BlockType = "44"
|
||||
BlockTypeBotHttp BlockType = "45"
|
||||
BlockTypeDatabaseInsert BlockType = "46"
|
||||
BlockTypeJsonSerialization BlockType = "58"
|
||||
BlockTypeJsonDeserialization BlockType = "59"
|
||||
BlockTypeBotDatasetDelete BlockType = "60"
|
||||
)
|
||||
|
||||
type VariableType string
|
||||
|
||||
const (
|
||||
@@ -536,19 +585,31 @@ const (
|
||||
type ErrorProcessType int
|
||||
|
||||
const (
|
||||
ErrorProcessTypeThrow ErrorProcessType = 1
|
||||
ErrorProcessTypeDefault ErrorProcessType = 2
|
||||
ErrorProcessTypeExceptionBranch ErrorProcessType = 3
|
||||
ErrorProcessTypeThrow ErrorProcessType = 1 // throws the error as usual
|
||||
ErrorProcessTypeReturnDefaultData ErrorProcessType = 2 // return DataOnErr configured in SettingOnError
|
||||
ErrorProcessTypeExceptionBranch ErrorProcessType = 3 // executes the exception branch on error
|
||||
)
|
||||
|
||||
// SettingOnError contains common error handling strategy.
|
||||
type SettingOnError struct {
|
||||
DataOnErr string `json:"dataOnErr,omitempty"`
|
||||
Switch bool `json:"switch,omitempty"`
|
||||
// DataOnErr defines the JSON result to be returned on error.
|
||||
DataOnErr string `json:"dataOnErr,omitempty"`
|
||||
// Switch defines whether ANY error handling strategy is active.
|
||||
// If set to false, it's equivalent to set ProcessType = ErrorProcessTypeThrow
|
||||
Switch bool `json:"switch,omitempty"`
|
||||
// ProcessType determines the error handling strategy for this node.
|
||||
ProcessType *ErrorProcessType `json:"processType,omitempty"`
|
||||
RetryTimes int64 `json:"retryTimes,omitempty"`
|
||||
TimeoutMs int64 `json:"timeoutMs,omitempty"`
|
||||
Ext *struct {
|
||||
BackupLLMParam string `json:"backupLLMParam,omitempty"` // only for LLM Node, marshaled from QALLMParam
|
||||
// RetryTimes determines how many times to retry. 0 means no retry.
|
||||
// If positive, any retries will be executed immediately after error.
|
||||
RetryTimes int64 `json:"retryTimes,omitempty"`
|
||||
// TimeoutMs sets the timeout duration in millisecond.
|
||||
// If any retry happens, ALL retry attempts accumulates to the same timeout threshold.
|
||||
TimeoutMs int64 `json:"timeoutMs,omitempty"`
|
||||
// Ext sets any extra settings specific to NodeType
|
||||
Ext *struct {
|
||||
// BackupLLMParam is only for LLM Node, marshaled from SimpleLLMParam.
|
||||
// If retry happens, the backup LLM will be used instead of the main LLM.
|
||||
BackupLLMParam string `json:"backupLLMParam,omitempty"`
|
||||
} `json:"ext,omitempty"`
|
||||
}
|
||||
|
||||
@@ -597,32 +658,8 @@ const (
|
||||
LoopTypeInfinite LoopType = "infinite"
|
||||
)
|
||||
|
||||
type WorkflowIdentity struct {
|
||||
ID string `json:"id"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
func (c *Canvas) GetAllSubWorkflowIdentities() []*WorkflowIdentity {
|
||||
workflowEntities := make([]*WorkflowIdentity, 0)
|
||||
|
||||
var collectSubWorkFlowEntities func(nodes []*Node)
|
||||
collectSubWorkFlowEntities = func(nodes []*Node) {
|
||||
for _, n := range nodes {
|
||||
if n.Type == BlockTypeBotSubWorkflow {
|
||||
workflowEntities = append(workflowEntities, &WorkflowIdentity{
|
||||
ID: n.Data.Inputs.WorkflowID,
|
||||
Version: n.Data.Inputs.WorkflowVersion,
|
||||
})
|
||||
}
|
||||
if len(n.Blocks) > 0 {
|
||||
collectSubWorkFlowEntities(n.Blocks)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
collectSubWorkFlowEntities(c.Nodes)
|
||||
|
||||
return workflowEntities
|
||||
type InputReceiver struct {
|
||||
OutputSchema string `json:"outputSchema,omitempty"`
|
||||
}
|
||||
|
||||
func GenerateNodeIDForBatchMode(key string) string {
|
||||
@@ -632,3 +669,163 @@ func GenerateNodeIDForBatchMode(key string) string {
|
||||
func IsGeneratedNodeForBatchMode(key string, parentKey string) bool {
|
||||
return key == GenerateNodeIDForBatchMode(parentKey)
|
||||
}
|
||||
|
||||
const defaultZhCNInitCanvasJsonSchema = `{
|
||||
"nodes": [
|
||||
{
|
||||
"id": "100001",
|
||||
"type": "1",
|
||||
"meta": {
|
||||
"position": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"nodeMeta": {
|
||||
"description": "工作流的起始节点,用于设定启动工作流需要的信息",
|
||||
"icon": "https://lf3-static.bytednsdoc.com/obj/eden-cn/dvsmryvd_avi_dvsm/ljhwZthlaukjlkulzlp/icon/icon-Start.png",
|
||||
"subTitle": "",
|
||||
"title": "开始"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "input",
|
||||
"required": false
|
||||
}
|
||||
],
|
||||
"trigger_parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "input",
|
||||
"required": false
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "900001",
|
||||
"type": "2",
|
||||
"meta": {
|
||||
"position": {
|
||||
"x": 1000,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"nodeMeta": {
|
||||
"description": "工作流的最终节点,用于返回工作流运行后的结果信息",
|
||||
"icon": "https://lf3-static.bytednsdoc.com/obj/eden-cn/dvsmryvd_avi_dvsm/ljhwZthlaukjlkulzlp/icon/icon-End.png",
|
||||
"subTitle": "",
|
||||
"title": "结束"
|
||||
},
|
||||
"inputs": {
|
||||
"terminatePlan": "returnVariables",
|
||||
"inputParameters": [
|
||||
{
|
||||
"name": "output",
|
||||
"input": {
|
||||
"type": "string",
|
||||
"value": {
|
||||
"type": "ref",
|
||||
"content": {
|
||||
"source": "block-output",
|
||||
"blockID": "",
|
||||
"name": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"edges": [],
|
||||
"versions": {
|
||||
"loop": "v2"
|
||||
}
|
||||
}`
|
||||
|
||||
const defaultEnUSInitCanvasJsonSchema = `{
|
||||
"nodes": [
|
||||
{
|
||||
"id": "100001",
|
||||
"type": "1",
|
||||
"meta": {
|
||||
"position": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"nodeMeta": {
|
||||
"description": "The starting node of the workflow, used to set the information needed to initiate the workflow.",
|
||||
"icon": "https://lf3-static.bytednsdoc.com/obj/eden-cn/dvsmryvd_avi_dvsm/ljhwZthlaukjlkulzlp/icon/icon-Start.png",
|
||||
"subTitle": "",
|
||||
"title": "Start"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "input",
|
||||
"required": false
|
||||
}
|
||||
],
|
||||
"trigger_parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "input",
|
||||
"required": false
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "900001",
|
||||
"type": "2",
|
||||
"meta": {
|
||||
"position": {
|
||||
"x": 1000,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"nodeMeta": {
|
||||
"description": "The final node of the workflow, used to return the result information after the workflow runs.",
|
||||
"icon": "https://lf3-static.bytednsdoc.com/obj/eden-cn/dvsmryvd_avi_dvsm/ljhwZthlaukjlkulzlp/icon/icon-End.png",
|
||||
"subTitle": "",
|
||||
"title": "End"
|
||||
},
|
||||
"inputs": {
|
||||
"terminatePlan": "returnVariables",
|
||||
"inputParameters": [
|
||||
{
|
||||
"name": "output",
|
||||
"input": {
|
||||
"type": "string",
|
||||
"value": {
|
||||
"type": "ref",
|
||||
"content": {
|
||||
"source": "block-output",
|
||||
"blockID": "",
|
||||
"name": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"edges": [],
|
||||
"versions": {
|
||||
"loop": "v2"
|
||||
}
|
||||
}`
|
||||
|
||||
func GetDefaultInitCanvasJsonSchema(locale i18n.Locale) string {
|
||||
return ternary.IFElse(locale == i18n.LocaleEN, defaultEnUSInitCanvasJsonSchema, defaultZhCNInitCanvasJsonSchema)
|
||||
}
|
||||
|
||||
@@ -47,12 +47,6 @@ type FieldSource struct {
|
||||
Val any `json:"val,omitempty"`
|
||||
}
|
||||
|
||||
type ImplicitNodeDependency struct {
|
||||
NodeID string
|
||||
FieldPath compose.FieldPath
|
||||
TypeInfo *TypeInfo
|
||||
}
|
||||
|
||||
type TypeInfo struct {
|
||||
Type DataType `json:"type"`
|
||||
ElemTypeInfo *TypeInfo `json:"elem_type_info,omitempty"`
|
||||
|
||||
Reference in New Issue
Block a user