deerflow-code/offline-backend-20260512/backend/app/report_collaboration/execution/completion.py
2026-09-07 18:24:55 +08:00

50 lines
1.6 KiB
Python

"""Completion rules: a reply or assistance card never finishes a node by itself."""
from __future__ import annotations
from app.report_collaboration.contracts.enums import ArtifactValidationStatus, CollaborationNodeStatus
class NodeCompletionBlocked(ValueError):
"""Raised when a caller tries to mark a node completed without a validated artifact."""
def can_complete_node(
*,
status: CollaborationNodeStatus,
validation_status: ArtifactValidationStatus | None,
awaiting_input: bool,
cancelled: bool,
) -> bool:
"""Return whether TaskLedger may move this node to ``completed``."""
if cancelled or status in {"cancelled", "cancel_requested", "superseded"}:
return False
if awaiting_input or status == "awaiting_input":
return False
if status != "validating":
return False
return validation_status == "validated"
def require_can_complete_node(
*,
status: CollaborationNodeStatus,
validation_status: ArtifactValidationStatus | None,
awaiting_input: bool = False,
cancelled: bool = False,
) -> None:
if not can_complete_node(
status=status,
validation_status=validation_status,
awaiting_input=awaiting_input,
cancelled=cancelled,
):
raise NodeCompletionBlocked("node cannot complete without a validated artifact, or the current status forbids completion")
def late_output_may_write_completed(*, current_status: CollaborationNodeStatus) -> bool:
"""Cancelled / superseded nodes must ignore late AgentScope output."""
return current_status not in {"cancelled", "superseded", "completed"}