mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-10 07:46:02 +00:00
backend
This commit is contained in:
@@ -5,7 +5,7 @@ Node metadata is loaded from: ../../templates/metadata/nodes/call_pipeline.yaml
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
import langbot_plugin.api.definition.abstract.platform.adapter as abstract_platform_adapter
|
||||
import langbot_plugin.api.entities.builtin.pipeline.query as pipeline_query
|
||||
@@ -15,26 +15,13 @@ import langbot_plugin.api.entities.builtin.platform.message as platform_message
|
||||
import langbot_plugin.api.entities.builtin.provider.session as provider_session
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('call_pipeline')
|
||||
class CallPipelineNode(WorkflowNode):
|
||||
"""Call pipeline node - invoke an existing pipeline"""
|
||||
|
||||
type_name = 'call_pipeline'
|
||||
category = 'action'
|
||||
icon = 'Workflow'
|
||||
name = 'call_pipeline'
|
||||
description = 'call_pipeline'
|
||||
name_zh = '调用 Pipeline'
|
||||
name_en = 'Call Pipeline'
|
||||
description_zh = '调用现有的 Pipeline 进行处理'
|
||||
description_en = 'Invoke an existing Pipeline for processing'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
if not self.ap:
|
||||
@@ -124,7 +111,6 @@ class CallPipelineNode(WorkflowNode):
|
||||
if context.message_context and context.message_context.is_group:
|
||||
group = platform_entities.Group(
|
||||
id=context.message_context.group_id or context.session_id or 'workflow_group',
|
||||
name='Workflow Group',
|
||||
permission=platform_entities.Permission.Member,
|
||||
)
|
||||
sender = platform_entities.GroupMember(
|
||||
@@ -152,7 +138,6 @@ class CallPipelineNode(WorkflowNode):
|
||||
else None,
|
||||
)
|
||||
|
||||
|
||||
class _WorkflowPipelineCaptureAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
|
||||
responses: list[dict[str, Any]] = []
|
||||
|
||||
|
||||
@@ -7,29 +7,16 @@ from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('code_executor')
|
||||
class CodeExecutorNode(WorkflowNode):
|
||||
"""Code executor node - run Python or JavaScript code"""
|
||||
|
||||
type_name = 'code_executor'
|
||||
category = 'process'
|
||||
icon = 'Code'
|
||||
name = 'code_executor'
|
||||
description = 'code_executor'
|
||||
name_zh = '代码执行'
|
||||
name_en = 'Code Executor'
|
||||
description_zh = '执行自定义代码处理数据'
|
||||
description_en = 'Execute custom code to process data'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
code = self.get_config('code', '')
|
||||
|
||||
@@ -5,30 +5,17 @@ Node metadata is loaded from: ../../templates/metadata/nodes/condition.yaml
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
from ..safe_eval import safe_eval_with_vars
|
||||
|
||||
|
||||
@workflow_node('condition')
|
||||
class ConditionNode(WorkflowNode):
|
||||
"""Condition node - branch based on condition"""
|
||||
|
||||
type_name = 'condition'
|
||||
category = 'control'
|
||||
icon = 'GitBranch'
|
||||
name = 'condition'
|
||||
description = 'condition'
|
||||
name_zh = '条件分支'
|
||||
name_en = 'Condition'
|
||||
description_zh = '根据条件分支工作流'
|
||||
description_en = 'Branch workflow based on a condition'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
condition_type = self.get_config('condition_type', 'expression')
|
||||
|
||||
@@ -5,29 +5,16 @@ Node metadata is loaded from: ../../templates/metadata/nodes/coze_bot.yaml
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('coze_bot')
|
||||
class CozeBotNode(WorkflowNode):
|
||||
"""Coze bot node - call Coze API bot"""
|
||||
|
||||
type_name = 'coze_bot'
|
||||
category = 'integration'
|
||||
icon = 'MessageSquare'
|
||||
name = 'coze_bot'
|
||||
description = 'coze_bot'
|
||||
name_zh = 'Coze Bot'
|
||||
name_en = 'Coze Bot'
|
||||
description_zh = '调用扣子 Bot'
|
||||
description_en = 'Call a Coze Bot'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
api_key = self.get_config('api_key', '')
|
||||
|
||||
@@ -5,29 +5,16 @@ Node metadata is loaded from: ../../templates/metadata/nodes/cron_trigger.yaml
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('cron_trigger')
|
||||
class CronTriggerNode(WorkflowNode):
|
||||
"""Cron trigger node - triggers workflow on schedule"""
|
||||
|
||||
type_name = 'cron_trigger'
|
||||
category = 'trigger'
|
||||
icon = 'Timer'
|
||||
name = 'cron_trigger'
|
||||
description = 'cron_trigger'
|
||||
name_zh = '定时触发'
|
||||
name_en = 'Scheduled Trigger'
|
||||
description_zh = '按定时计划触发工作流'
|
||||
description_en = 'Trigger workflow on a scheduled time'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
from datetime import datetime
|
||||
|
||||
@@ -5,30 +5,17 @@ Node metadata is loaded from: ../../templates/metadata/nodes/data_transform.yaml
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
from ..safe_eval import safe_eval_with_vars
|
||||
|
||||
|
||||
@workflow_node('data_transform')
|
||||
class DataTransformNode(WorkflowNode):
|
||||
"""Data transform node - transform data using templates or JSONPath"""
|
||||
|
||||
type_name = 'data_transform'
|
||||
category = 'process'
|
||||
icon = 'ArrowRightLeft'
|
||||
name = 'data_transform'
|
||||
description = 'data_transform'
|
||||
name_zh = '数据转换'
|
||||
name_en = 'Data Transform'
|
||||
description_zh = '使用模板或 JSONPath 转换数据'
|
||||
description_en = 'Transform data using templates or JSONPath'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
data = inputs.get('data')
|
||||
|
||||
@@ -5,29 +5,16 @@ Node metadata is loaded from: ../../templates/metadata/nodes/database_query.yaml
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('database_query')
|
||||
class DatabaseQueryNode(WorkflowNode):
|
||||
"""Database query node - execute database queries"""
|
||||
|
||||
type_name = 'database_query'
|
||||
category = 'integration'
|
||||
icon = 'Database'
|
||||
name = 'database_query'
|
||||
description = 'database_query'
|
||||
name_zh = '数据库查询'
|
||||
name_en = 'Database Query'
|
||||
description_zh = '执行数据库查询'
|
||||
description_en = 'Execute database queries'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
connection_type = self.get_config('connection_type', 'postgresql')
|
||||
|
||||
@@ -5,29 +5,16 @@ Node metadata is loaded from: ../../templates/metadata/nodes/dify_knowledge_quer
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('dify_knowledge_query')
|
||||
class DifyKnowledgeQueryNode(WorkflowNode):
|
||||
"""Dify knowledge base query node - query Dify knowledge base"""
|
||||
|
||||
type_name = 'dify_knowledge_query'
|
||||
category = 'integration'
|
||||
icon = 'BookOpen'
|
||||
name = 'dify_knowledge_query'
|
||||
description = 'dify_knowledge_query'
|
||||
name_zh = 'Dify 知识库查询'
|
||||
name_en = 'Dify Knowledge Query'
|
||||
description_zh = '查询 Dify 知识库'
|
||||
description_en = 'Query Dify knowledge base'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
base_url = self.get_config('base_url', 'https://api.dify.ai/v1')
|
||||
|
||||
@@ -5,29 +5,16 @@ Node metadata is loaded from: ../../templates/metadata/nodes/dify_workflow.yaml
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('dify_workflow')
|
||||
class DifyWorkflowNode(WorkflowNode):
|
||||
"""Dify workflow node - call Dify service API"""
|
||||
|
||||
type_name = 'dify_workflow'
|
||||
category = 'integration'
|
||||
icon = 'Bot'
|
||||
name = 'dify_workflow'
|
||||
description = 'dify_workflow'
|
||||
name_zh = 'Dify 工作流'
|
||||
name_en = 'Dify Workflow'
|
||||
description_zh = '调用 Dify 平台工作流'
|
||||
description_en = 'Call a Dify platform workflow'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
base_url = self.get_config('base_url', 'https://api.dify.ai/v1')
|
||||
|
||||
@@ -5,29 +5,16 @@ Node metadata is loaded from: ../../templates/metadata/nodes/end.yaml
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('end')
|
||||
class EndNode(WorkflowNode):
|
||||
"""End node - marks the end of workflow execution"""
|
||||
|
||||
type_name = 'end'
|
||||
category = 'action'
|
||||
icon = 'PauseCircle'
|
||||
name = 'end'
|
||||
description = 'end'
|
||||
name_zh = '结束'
|
||||
name_en = 'End'
|
||||
description_zh = '结束工作流执行'
|
||||
description_en = 'End the workflow execution'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
category = 'control'
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
result = inputs.get('result')
|
||||
|
||||
@@ -5,29 +5,16 @@ Node metadata is loaded from: ../../templates/metadata/nodes/event_trigger.yaml
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('event_trigger')
|
||||
class EventTriggerNode(WorkflowNode):
|
||||
"""Event trigger node - triggers workflow on system events"""
|
||||
|
||||
type_name = 'event_trigger'
|
||||
category = 'trigger'
|
||||
icon = 'Bell'
|
||||
name = 'event_trigger'
|
||||
description = 'event_trigger'
|
||||
name_zh = '事件触发'
|
||||
name_en = 'Event Trigger'
|
||||
description_zh = '当系统事件发生时触发工作流'
|
||||
description_en = 'Trigger workflow when a system event occurs'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
from datetime import datetime
|
||||
|
||||
@@ -5,29 +5,16 @@ Node metadata is loaded from: ../../templates/metadata/nodes/http_request.yaml
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('http_request')
|
||||
class HTTPRequestNode(WorkflowNode):
|
||||
"""HTTP request node - make HTTP API calls"""
|
||||
|
||||
type_name = 'http_request'
|
||||
category = 'process'
|
||||
icon = 'Globe'
|
||||
name = 'http_request'
|
||||
description = 'http_request'
|
||||
name_zh = 'HTTP 请求'
|
||||
name_en = 'HTTP Request'
|
||||
description_zh = '向外部 API 发送 HTTP 请求'
|
||||
description_en = 'Make HTTP requests to external APIs'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
category = 'action'
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
import aiohttp
|
||||
|
||||
@@ -2,47 +2,16 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('iterator')
|
||||
class IteratorNode(WorkflowNode):
|
||||
"""Iterator node - iterate over array items one by one"""
|
||||
|
||||
type_name = 'iterator'
|
||||
category = 'control'
|
||||
icon = 'Repeat'
|
||||
name = 'iterator'
|
||||
name_zh = '迭代器'
|
||||
name_en = 'Iterator'
|
||||
description = 'iterator'
|
||||
description_zh = '逐个遍历数组元素'
|
||||
description_en = 'Iterate over array elements one by one'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = [
|
||||
NodePort(name='items', type='array', description='Array to iterate over', required=True),
|
||||
]
|
||||
outputs: ClassVar[list[NodePort]] = [
|
||||
NodePort(name='item', type='any', description='Current item'),
|
||||
NodePort(name='index', type='number', description='Current index'),
|
||||
NodePort(name='is_first', type='boolean', description='Whether this is the first item'),
|
||||
NodePort(name='is_last', type='boolean', description='Whether this is the last item'),
|
||||
NodePort(name='results', type='array', description='All iteration results'),
|
||||
NodePort(name='completed', type='boolean', description='Whether iteration completed'),
|
||||
]
|
||||
config_schema: ClassVar[list[NodeConfig]] = [
|
||||
NodeConfig(
|
||||
name='max_iterations',
|
||||
type='integer',
|
||||
required=False,
|
||||
default=1000,
|
||||
description='Maximum iterations (safety limit)',
|
||||
label={'en_US': 'Max Iterations', 'zh_Hans': '最大迭代次数'},
|
||||
),
|
||||
]
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
items = inputs.get('items', [])
|
||||
|
||||
@@ -5,29 +5,16 @@ Node metadata is loaded from: ../../templates/metadata/nodes/knowledge_retrieval
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('knowledge_retrieval')
|
||||
class KnowledgeRetrievalNode(WorkflowNode):
|
||||
"""Knowledge retrieval node - search in knowledge base"""
|
||||
|
||||
type_name = 'knowledge_retrieval'
|
||||
category = 'process'
|
||||
icon = 'Search'
|
||||
name = 'knowledge_retrieval'
|
||||
description = 'knowledge_retrieval'
|
||||
name_zh = '知识库检索'
|
||||
name_en = 'Knowledge Retrieval'
|
||||
description_zh = '从知识库中检索相关信息'
|
||||
description_en = 'Retrieve relevant information from knowledge bases'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
query = inputs.get('query', '')
|
||||
|
||||
@@ -5,29 +5,16 @@ Node metadata is loaded from: ../../templates/metadata/nodes/langflow_flow.yaml
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('langflow_flow')
|
||||
class LangflowFlowNode(WorkflowNode):
|
||||
"""Langflow flow node - call Langflow API"""
|
||||
|
||||
type_name = 'langflow_flow'
|
||||
category = 'integration'
|
||||
icon = 'GitBranch'
|
||||
name = 'langflow_flow'
|
||||
description = 'langflow_flow'
|
||||
name_zh = 'Langflow 流程'
|
||||
name_en = 'Langflow Flow'
|
||||
description_zh = '调用 Langflow 流程'
|
||||
description_en = 'Call a Langflow flow'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
base_url = self.get_config('base_url', 'http://localhost:7860')
|
||||
|
||||
@@ -4,81 +4,20 @@ from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import re
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
import langbot_plugin.api.entities.builtin.provider.message as provider_message
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@workflow_node('llm_call')
|
||||
class LLMCallNode(WorkflowNode):
|
||||
"""LLM call node - invoke large language model"""
|
||||
|
||||
type_name = 'llm_call'
|
||||
category = 'process'
|
||||
icon = 'Brain'
|
||||
name = 'llm_call'
|
||||
name_zh = 'LLM 调用'
|
||||
name_en = 'LLM Call'
|
||||
description = 'llm_call'
|
||||
description_zh = '调用大语言模型生成响应'
|
||||
description_en = 'Call a large language model to generate responses'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = [
|
||||
NodePort(name='input', type='string', description='Input text to send to the model', required=False),
|
||||
NodePort(name='context', type='object', description='Additional context data', required=False),
|
||||
]
|
||||
outputs: ClassVar[list[NodePort]] = [
|
||||
NodePort(name='response', type='string', description='Model response text'),
|
||||
NodePort(name='usage', type='object', description='Token usage information'),
|
||||
]
|
||||
config_schema: ClassVar[list[NodeConfig]] = [
|
||||
NodeConfig(
|
||||
name='model',
|
||||
type='llm-model-selector',
|
||||
required=True,
|
||||
description='Select the LLM model to use',
|
||||
label={'en_US': 'Model', 'zh_Hans': '模型'},
|
||||
),
|
||||
NodeConfig(
|
||||
name='system_prompt',
|
||||
type='textarea',
|
||||
required=False,
|
||||
default='',
|
||||
description='System prompt to set model behavior',
|
||||
label={'en_US': 'System Prompt', 'zh_Hans': '系统提示词'},
|
||||
),
|
||||
NodeConfig(
|
||||
name='user_prompt_template',
|
||||
type='textarea',
|
||||
required=True,
|
||||
default='{{input}}',
|
||||
description='User prompt template with variable placeholders',
|
||||
label={'en_US': 'User Prompt Template', 'zh_Hans': '用户提示词模板'},
|
||||
),
|
||||
NodeConfig(
|
||||
name='temperature',
|
||||
type='number',
|
||||
required=False,
|
||||
default=0.7,
|
||||
description='Controls randomness (0.0-2.0)',
|
||||
label={'en_US': 'Temperature', 'zh_Hans': '温度'},
|
||||
min_value=0.0,
|
||||
max_value=2.0,
|
||||
),
|
||||
NodeConfig(
|
||||
name='max_tokens',
|
||||
type='integer',
|
||||
required=False,
|
||||
default=0,
|
||||
description='Max tokens to generate (0 = model default)',
|
||||
label={'en_US': 'Max Tokens', 'zh_Hans': '最大令牌数'},
|
||||
),
|
||||
]
|
||||
|
||||
def _resolve_template(self, template: str, inputs: dict[str, Any], context: ExecutionContext) -> str:
|
||||
"""Resolve {{variable}} placeholders in a template string."""
|
||||
|
||||
@@ -2,54 +2,16 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('loop')
|
||||
class LoopNode(WorkflowNode):
|
||||
"""Loop node - iterate over items"""
|
||||
|
||||
type_name = 'loop'
|
||||
category = 'control'
|
||||
icon = 'Repeat'
|
||||
name = 'loop'
|
||||
name_zh = '循环'
|
||||
name_en = 'Loop'
|
||||
description = 'loop'
|
||||
description_zh = '遍历项目或重复直到满足条件'
|
||||
description_en = 'Iterate over items or repeat until condition'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = [
|
||||
NodePort(name='items', type='array', description='Items to iterate over', required=False),
|
||||
]
|
||||
outputs: ClassVar[list[NodePort]] = [
|
||||
NodePort(name='item', type='any', description='Current item in iteration'),
|
||||
NodePort(name='index', type='number', description='Current iteration index'),
|
||||
NodePort(name='results', type='array', description='All iteration results'),
|
||||
NodePort(name='completed', type='boolean', description='Whether loop completed'),
|
||||
]
|
||||
config_schema: ClassVar[list[NodeConfig]] = [
|
||||
NodeConfig(
|
||||
name='loop_type',
|
||||
type='select',
|
||||
required=True,
|
||||
default='foreach',
|
||||
description='Type of loop',
|
||||
label={'en_US': 'Loop Type', 'zh_Hans': '循环类型'},
|
||||
options=['foreach', 'while', 'count'],
|
||||
),
|
||||
NodeConfig(
|
||||
name='max_iterations',
|
||||
type='integer',
|
||||
required=False,
|
||||
default=100,
|
||||
description='Maximum iterations (safety limit)',
|
||||
label={'en_US': 'Max Iterations', 'zh_Hans': '最大迭代次数'},
|
||||
),
|
||||
]
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
items = inputs.get('items', [])
|
||||
|
||||
@@ -9,36 +9,24 @@ The i18n for label and description is handled on the frontend side.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('mcp_tool')
|
||||
class MCPToolNode(WorkflowNode):
|
||||
"""MCP tool node - invoke MCP (Model Context Protocol) tools"""
|
||||
|
||||
# Node type for registration
|
||||
type_name = 'mcp_tool'
|
||||
|
||||
# Category and icon - these are not i18n
|
||||
category = 'integration'
|
||||
icon = 'Wrench'
|
||||
|
||||
# Name and description - i18n handled on frontend side
|
||||
# Frontend will use node type key to look up translation
|
||||
name = 'mcp_tool'
|
||||
description = 'mcp_tool'
|
||||
name_zh = 'MCP 工具'
|
||||
name_en = 'MCP Tool'
|
||||
description_zh = '调用 MCP 工具'
|
||||
description_en = 'Invoke an MCP (Model Context Protocol) tool'
|
||||
|
||||
# Inputs/outputs/config - loaded from YAML at runtime
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
"""Execute the MCP tool node
|
||||
|
||||
@@ -5,11 +5,10 @@ Node metadata is loaded from: ../../templates/metadata/nodes/memory_store.yaml
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
class MemoryHelper:
|
||||
"""Helper class wrapping context.memory dict with get/set/delete/list_all/append operations"""
|
||||
@@ -47,24 +46,11 @@ class MemoryHelper:
|
||||
self.set(key, current, scope=scope, ttl=ttl)
|
||||
return current
|
||||
|
||||
|
||||
@workflow_node('memory_store')
|
||||
class MemoryStoreNode(WorkflowNode):
|
||||
"""Memory store node - store and retrieve from workflow memory"""
|
||||
|
||||
type_name = 'memory_store'
|
||||
category = 'integration'
|
||||
icon = 'HardDrive'
|
||||
name = 'memory_store'
|
||||
description = 'memory_store'
|
||||
name_zh = '记忆存储'
|
||||
name_en = 'Memory Store'
|
||||
description_zh = '从工作流记忆中存储和检索数据'
|
||||
description_en = 'Store and retrieve data from workflow memory'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
operation = self.get_config('operation', 'get')
|
||||
|
||||
@@ -5,29 +5,16 @@ Node metadata is loaded from: ../../templates/metadata/nodes/merge.yaml
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('merge')
|
||||
class MergeNode(WorkflowNode):
|
||||
"""Merge node - combine multiple inputs"""
|
||||
|
||||
type_name = 'merge'
|
||||
category = 'control'
|
||||
icon = 'GitMerge'
|
||||
name = 'merge'
|
||||
description = 'merge'
|
||||
name_zh = '合并'
|
||||
name_en = 'Merge'
|
||||
description_zh = '将多个分支合并在一起'
|
||||
description_en = 'Merge multiple branches back together'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
strategy = self.get_config('merge_strategy', 'object')
|
||||
|
||||
@@ -7,29 +7,16 @@ Node metadata (label, description, inputs, outputs, config) is loaded from:
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('message_trigger')
|
||||
class MessageTriggerNode(WorkflowNode):
|
||||
"""Message trigger node - triggers workflow on message arrival"""
|
||||
|
||||
type_name = 'message_trigger'
|
||||
category = 'trigger'
|
||||
icon = 'MessageSquare'
|
||||
name = 'message_trigger'
|
||||
description = 'message_trigger'
|
||||
name_zh = '消息触发'
|
||||
name_en = 'Message Trigger'
|
||||
description_zh = '当收到消息时触发工作流'
|
||||
description_en = 'Trigger workflow when a message is received'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
msg_ctx = context.message_context
|
||||
|
||||
@@ -5,29 +5,16 @@ Node metadata is loaded from: ../../templates/metadata/nodes/n8n_workflow.yaml
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('n8n_workflow')
|
||||
class N8nWorkflowNode(WorkflowNode):
|
||||
"""n8n workflow node - call n8n workflow API"""
|
||||
|
||||
type_name = 'n8n_workflow'
|
||||
category = 'integration'
|
||||
icon = 'Workflow'
|
||||
name = 'n8n_workflow'
|
||||
description = 'n8n_workflow'
|
||||
name_zh = 'n8n 工作流'
|
||||
name_en = 'N8n Workflow'
|
||||
description_zh = '通过 webhook 调用 n8n 工作流'
|
||||
description_en = 'Call an n8n workflow via webhook'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
webhook_url = self.get_config('webhook_url', '')
|
||||
|
||||
@@ -5,29 +5,16 @@ Node metadata is loaded from: ../../templates/metadata/nodes/opening_statement.y
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('opening_statement')
|
||||
class OpeningStatementNode(WorkflowNode):
|
||||
"""Opening statement node - provide conversation opener and suggested questions"""
|
||||
|
||||
type_name = 'opening_statement'
|
||||
category = 'action'
|
||||
icon = 'MessageSquare'
|
||||
name = 'opening_statement'
|
||||
description = 'opening_statement'
|
||||
name_zh = '对话开场白'
|
||||
name_en = 'Opening Statement'
|
||||
description_zh = '提供对话开场白和建议问题'
|
||||
description_en = 'Provide conversation opener and suggested questions'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
statement = self.get_config('statement', '')
|
||||
|
||||
@@ -2,51 +2,16 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('parallel')
|
||||
class ParallelNode(WorkflowNode):
|
||||
"""Parallel node - execute multiple branches simultaneously"""
|
||||
|
||||
type_name = 'parallel'
|
||||
category = 'control'
|
||||
icon = 'Layers'
|
||||
name = 'parallel'
|
||||
name_zh = '并行执行'
|
||||
name_en = 'Parallel'
|
||||
description = 'parallel'
|
||||
description_zh = '并行执行多个分支'
|
||||
description_en = 'Execute multiple branches in parallel'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = [
|
||||
NodePort(name='input', type='any', description='Input data for all branches', required=False),
|
||||
]
|
||||
outputs: ClassVar[list[NodePort]] = [
|
||||
NodePort(name='results', type='object', description='Combined results from all branches'),
|
||||
NodePort(name='errors', type='array', description='Errors from branches (if any)'),
|
||||
]
|
||||
config_schema: ClassVar[list[NodeConfig]] = [
|
||||
NodeConfig(
|
||||
name='wait_all',
|
||||
type='boolean',
|
||||
required=False,
|
||||
default=True,
|
||||
description='Wait for all branches to complete',
|
||||
label={'en_US': 'Wait for All', 'zh_Hans': '等待全部完成'},
|
||||
),
|
||||
NodeConfig(
|
||||
name='fail_fast',
|
||||
type='boolean',
|
||||
required=False,
|
||||
default=False,
|
||||
description='Stop all branches if any fails',
|
||||
label={'en_US': 'Fail Fast', 'zh_Hans': '快速失败'},
|
||||
),
|
||||
]
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
return {
|
||||
|
||||
@@ -5,29 +5,17 @@ Node metadata is loaded from: ../../templates/metadata/nodes/parameter_extractor
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('parameter_extractor')
|
||||
class ParameterExtractorNode(WorkflowNode):
|
||||
"""Parameter extractor node - extract structured parameters from text"""
|
||||
|
||||
type_name = 'parameter_extractor'
|
||||
category = 'process'
|
||||
icon: str = 'Variable'
|
||||
name = 'parameter_extractor'
|
||||
description = 'parameter_extractor'
|
||||
name_zh = '参数提取器'
|
||||
name_en = 'Parameter Extractor'
|
||||
description_zh = '使用 AI 从文本中提取结构化参数'
|
||||
description_en = 'Extract structured parameters from text using AI'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
param_defs = self.get_config('parameters', [])
|
||||
|
||||
@@ -5,11 +5,10 @@
|
||||
|
||||
# from __future__ import annotations
|
||||
|
||||
# from typing import Any, ClassVar
|
||||
# from typing import Any
|
||||
|
||||
# from ..entities import ExecutionContext
|
||||
# from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
# from ..node import WorkflowNode, workflow_node
|
||||
|
||||
# @workflow_node('plugin_call')
|
||||
# class PluginCallNode(WorkflowNode):
|
||||
|
||||
@@ -5,29 +5,16 @@ Node metadata is loaded from: ../../templates/metadata/nodes/question_classifier
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('question_classifier')
|
||||
class QuestionClassifierNode(WorkflowNode):
|
||||
"""Question classifier node - classify user questions into categories"""
|
||||
|
||||
type_name = 'question_classifier'
|
||||
category = 'process'
|
||||
icon = 'ListFilter'
|
||||
name = 'question_classifier'
|
||||
description = 'question_classifier'
|
||||
name_zh = '问题分类器'
|
||||
name_en = 'Question Classifier'
|
||||
description_zh = '使用 AI 将问题分类到预定义类别'
|
||||
description_en = 'Classify questions into predefined categories using AI'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
categories = self.get_config('categories', [])
|
||||
|
||||
@@ -5,29 +5,16 @@ Node metadata is loaded from: ../../templates/metadata/nodes/redis_operation.yam
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('redis_operation')
|
||||
class RedisOperationNode(WorkflowNode):
|
||||
"""Redis operation node - perform Redis cache operations"""
|
||||
|
||||
type_name = 'redis_operation'
|
||||
category = 'integration'
|
||||
icon = 'Server'
|
||||
name = 'redis_operation'
|
||||
description = 'redis_operation'
|
||||
name_zh = 'Redis 操作'
|
||||
name_en = 'Redis Operation'
|
||||
description_zh = '执行 Redis 缓存操作'
|
||||
description_en = 'Perform Redis cache operations'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
connection_url = self.get_config('connection_url', 'redis://localhost:6379')
|
||||
|
||||
@@ -6,31 +6,18 @@ Node metadata is loaded from: ../../templates/metadata/nodes/reply_message.yaml
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@workflow_node('reply_message')
|
||||
class ReplyMessageNode(WorkflowNode):
|
||||
"""Reply message node - reply to the triggering message"""
|
||||
|
||||
type_name = 'reply_message'
|
||||
category = 'action'
|
||||
icon = 'Send'
|
||||
name = 'reply_message'
|
||||
description = 'reply_message'
|
||||
name_zh = '回复消息'
|
||||
name_en = 'Reply Message'
|
||||
description_zh = '回复触发工作流的消息'
|
||||
description_en = 'Reply to the message that triggered the workflow'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
message = inputs.get('message')
|
||||
|
||||
@@ -5,29 +5,16 @@ Node metadata is loaded from: ../../templates/metadata/nodes/send_message.yaml
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('send_message')
|
||||
class SendMessageNode(WorkflowNode):
|
||||
"""Send message node - send message to a target"""
|
||||
|
||||
type_name = 'send_message'
|
||||
category = 'action'
|
||||
icon = 'MessageCircle'
|
||||
name = 'send_message'
|
||||
description = 'send_message'
|
||||
name_zh = '发送消息'
|
||||
name_en = 'Send Message'
|
||||
description_zh = '向聊天或用户发送消息'
|
||||
description_en = 'Send a message to a chat or user'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
return {'status': 'sent', 'message_id': f'msg_{context.execution_id}'}
|
||||
|
||||
@@ -5,29 +5,16 @@ Node metadata is loaded from: ../../templates/metadata/nodes/set_variable.yaml
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('set_variable')
|
||||
class SetVariableNode(WorkflowNode):
|
||||
"""Set variable node - set workflow or conversation variable"""
|
||||
|
||||
type_name = 'set_variable'
|
||||
category = 'action'
|
||||
icon = 'Variable'
|
||||
name = 'set_variable'
|
||||
description = 'set_variable'
|
||||
name_zh = '设置变量'
|
||||
name_en = 'Set Variable'
|
||||
description_zh = '设置上下文变量值'
|
||||
description_en = 'Set a context variable value'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
value = inputs.get('value')
|
||||
|
||||
@@ -5,29 +5,16 @@ Node metadata is loaded from: ../../templates/metadata/nodes/store_data.yaml
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('store_data')
|
||||
class StoreDataNode(WorkflowNode):
|
||||
"""Store data node - save data to storage"""
|
||||
|
||||
type_name = 'store_data'
|
||||
category = 'action'
|
||||
icon = 'Database'
|
||||
name = 'store_data'
|
||||
description = 'store_data'
|
||||
name_zh = '存储数据'
|
||||
name_en = 'Store Data'
|
||||
description_zh = '将数据存储到持久化存储'
|
||||
description_en = 'Store data to persistent storage'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
key = inputs.get('key', '')
|
||||
|
||||
@@ -5,29 +5,16 @@ Node metadata is loaded from: ../../templates/metadata/nodes/switch.yaml
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('switch')
|
||||
class SwitchNode(WorkflowNode):
|
||||
"""Switch node - multi-way branch based on value"""
|
||||
|
||||
type_name = 'switch'
|
||||
category = 'control'
|
||||
icon = 'Split'
|
||||
name = 'switch'
|
||||
description = 'switch'
|
||||
name_zh = '多路分支'
|
||||
name_en = 'Switch'
|
||||
description_zh = '根据多个条件分支工作流'
|
||||
description_en = 'Branch workflow based on multiple cases'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
expression = self.get_config('expression', '')
|
||||
|
||||
@@ -5,29 +5,16 @@ Node metadata is loaded from: ../../templates/metadata/nodes/variable_aggregator
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('variable_aggregator')
|
||||
class VariableAggregatorNode(WorkflowNode):
|
||||
"""Variable aggregator node - aggregate variables from multiple branches"""
|
||||
|
||||
type_name = 'variable_aggregator'
|
||||
category = 'control'
|
||||
icon = 'GitMerge'
|
||||
name = 'variable_aggregator'
|
||||
description = 'variable_aggregator'
|
||||
name_zh = '变量聚合器'
|
||||
name_en = 'Variable Aggregator'
|
||||
description_zh = '聚合多个分支的变量输出'
|
||||
description_en = 'Aggregate variable outputs from multiple branches'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
variables = inputs.get('variables', {})
|
||||
|
||||
@@ -5,29 +5,16 @@ Node metadata is loaded from: ../../templates/metadata/nodes/wait.yaml
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('wait')
|
||||
class WaitNode(WorkflowNode):
|
||||
"""Wait node - pause execution for a duration"""
|
||||
|
||||
type_name = 'wait'
|
||||
category = 'control'
|
||||
icon = 'Clock'
|
||||
name = 'wait'
|
||||
description = 'wait'
|
||||
name_zh = '等待'
|
||||
name_en = 'Wait'
|
||||
description_zh = '暂停工作流执行指定时间'
|
||||
description_en = 'Pause workflow execution for a specified duration'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
import asyncio
|
||||
|
||||
@@ -5,29 +5,16 @@ Node metadata is loaded from: ../../templates/metadata/nodes/webhook_trigger.yam
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any
|
||||
|
||||
from ..entities import ExecutionContext
|
||||
from ..node import WorkflowNode, workflow_node, NodePort, NodeConfig
|
||||
|
||||
from ..node import WorkflowNode, workflow_node
|
||||
|
||||
@workflow_node('webhook_trigger')
|
||||
class WebhookTriggerNode(WorkflowNode):
|
||||
"""Webhook trigger node - triggers workflow via HTTP request"""
|
||||
|
||||
type_name = 'webhook_trigger'
|
||||
category = 'trigger'
|
||||
icon = 'Webhook'
|
||||
name = 'webhook_trigger'
|
||||
description = 'webhook_trigger'
|
||||
name_zh = 'Webhook 触发'
|
||||
name_en = 'Webhook Trigger'
|
||||
description_zh = '通过 HTTP 请求触发工作流'
|
||||
description_en = 'Trigger workflow via HTTP webhook'
|
||||
|
||||
inputs: ClassVar[list[NodePort]] = []
|
||||
outputs: ClassVar[list[NodePort]] = []
|
||||
config_schema: ClassVar[list[NodeConfig]] = []
|
||||
|
||||
async def execute(self, inputs: dict[str, Any], context: ExecutionContext) -> dict[str, Any]:
|
||||
trigger_data = context.trigger_data
|
||||
|
||||
Reference in New Issue
Block a user