deerflow-code/offline-backend-20260512/backend/packages/harness/deerflow/workflows/nodes/base.py
2026-09-07 18:24:55 +08:00

53 lines
1.6 KiB
Python

"""Node executor protocol and registry."""
from __future__ import annotations
from typing import Any, Protocol, runtime_checkable
from deerflow.workflows.errors import WorkflowError
from deerflow.workflows.ports import ACTIVE_PORTS
from deerflow.workflows.runtime.context import RunContext
from deerflow.workflows.schemas import NodeResult, NodeType, WorkflowNode
@runtime_checkable
class NodeExecutor(Protocol):
async def execute(self, node: WorkflowNode, ctx: RunContext) -> NodeResult: ...
class NodeRegistry:
"""Maps node type → executor. Unknown types fail with a typed error."""
def __init__(self) -> None:
self._executors: dict[str, NodeExecutor] = {}
def register(self, node_type: NodeType | str, executor: NodeExecutor) -> None:
self._executors[str(node_type)] = executor
def get(self, node_type: str) -> NodeExecutor:
executor = self._executors.get(node_type)
if executor is None:
raise WorkflowError(
"WORKFLOW_RESOURCE_MISSING",
f"节点类型暂不支持执行:{node_type}",
details={"nodeType": node_type},
)
return executor
def supported(self) -> list[str]:
return sorted(self._executors)
def require_dep(value: Any, *, node: WorkflowNode, what: str) -> Any:
if value is None:
raise WorkflowError(
"WORKFLOW_RESOURCE_MISSING",
f"运行环境缺少{what}能力,无法执行该节点",
node_id=node.id,
details={"capability": what},
)
return value
__all__ = ["ACTIVE_PORTS", "NodeExecutor", "NodeRegistry", "require_dep"]