50 lines
1.6 KiB
Python
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"}
|