80 lines
2.8 KiB
Python
80 lines
2.8 KiB
Python
# Copyright (c) 2025 Patrick Motsch
|
|
# Input/Human node executor - creates tasks and pauses execution.
|
|
|
|
import logging
|
|
from typing import Dict, Any
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class PauseForHumanTaskError(Exception):
|
|
"""Raised when execution must pause for a human task. Contains runId, taskId."""
|
|
|
|
def __init__(self, runId: str, taskId: str, nodeId: str):
|
|
self.runId = runId
|
|
self.taskId = taskId
|
|
self.nodeId = nodeId
|
|
super().__init__(f"Pause for human task {taskId} (run {runId}, node {nodeId})")
|
|
|
|
|
|
class PauseForEmailWaitError(Exception):
|
|
"""Raised when execution must pause waiting for a new email. Background poller will resume."""
|
|
|
|
def __init__(self, runId: str, nodeId: str, waitConfig: Dict[str, Any]):
|
|
self.runId = runId
|
|
self.nodeId = nodeId
|
|
self.waitConfig = waitConfig
|
|
super().__init__(f"Pause for email wait (run {runId}, node {nodeId})")
|
|
|
|
|
|
class InputExecutor:
|
|
"""
|
|
Execute input/human nodes. Creates a HumanTask, pauses the run, and raises
|
|
PauseForHumanTaskError so the engine returns { paused: true, taskId, runId }.
|
|
"""
|
|
|
|
def __init__(self, automation2_interface: Any):
|
|
self.automation2 = automation2_interface
|
|
|
|
async def execute(
|
|
self,
|
|
node: Dict[str, Any],
|
|
context: Dict[str, Any],
|
|
) -> Any:
|
|
nodeType = node.get("type", "")
|
|
nodeId = node.get("id", "")
|
|
runId = context.get("_runId")
|
|
workflowId = context.get("workflowId")
|
|
instanceId = context.get("instanceId")
|
|
userId = context.get("userId")
|
|
|
|
if not runId or not workflowId:
|
|
logger.error("InputExecutor: runId/workflowId missing in context - cannot create task")
|
|
return {"error": "Missing run context", "success": False}
|
|
|
|
config = dict(node.get("parameters") or {})
|
|
logger.info("InputExecutor node %s type=%s creating task", nodeId, nodeType)
|
|
|
|
task = self.automation2.createTask(
|
|
runId=runId,
|
|
workflowId=workflowId,
|
|
nodeId=nodeId,
|
|
nodeType=nodeType,
|
|
config=config,
|
|
assigneeId=userId,
|
|
)
|
|
taskId = task.get("id")
|
|
|
|
self.automation2.updateRun(
|
|
runId,
|
|
status="paused",
|
|
nodeOutputs=context.get("nodeOutputs"),
|
|
currentNodeId=nodeId,
|
|
context={
|
|
"connectionMap": context.get("connectionMap"),
|
|
"inputSources": context.get("inputSources"),
|
|
"orderedNodeIds": [n.get("id") for n in context.get("_orderedNodes", []) if n.get("id")],
|
|
},
|
|
)
|
|
logger.info("InputExecutor node %s: created task %s, run %s paused", nodeId, taskId, runId)
|
|
raise PauseForHumanTaskError(runId=runId, taskId=taskId, nodeId=nodeId)
|