Source code for cadrumo.entrypoints.tui.operations.interactions
"""Safe REVIEW rendering and separately authorized APPLY/REJECT controls.Only the registered safe REVIEW projection and the response-controlauthorization are ever rendered. Public ``INPUT`` and ``CHOICE`` interactionkinds are treated as unsupported: no later contract has enrolled a TUIrenderer for them yet, so this module never attempts to draw one.These are runtime render states rather than wire contracts (a bound responsecontrol cannot cross a process boundary), so they are plain immutabledataclasses rather than pydantic models; the wire-safe fields they carry(``interaction``, ``projection``) are already-validated public contractmodels."""from__future__importannotationsfromdataclassesimportdataclass,fieldfromtypingimportLiteral,assert_neverfrompydanticimportBaseModelfrom....application.operations.frontend_contractsimportOperationReviewProjectionResultV1from....application.operations.frontend_projectionimport(OperationNoPendingInteractionV1,OperationPublicProjectionV1,OperationReviewAvailableInteractionV1,OperationUnsupportedInteractionV1,)from....application.operations.frontend_requestsimport(OperationResponseControlSuccessV1,OperationReviewProjectionSuccessV1,)from....application.operations.interactionsimportOperationResponseIntentValuefrom.controllerimportOperationBoundResponseControl,OperationController
[docs]@dataclass(frozen=True,slots=True)classOperationModalNoInteractionV1:"""The modal has no interaction to render."""disposition:Literal["none"]="none"
[docs]@dataclass(frozen=True,slots=True)classOperationModalReviewInteractionV1[ReviewProjectionT:BaseModel]:"""A registered safe REVIEW projection with its already-bound controls. ``control`` is bound exactly once per pending REVIEW (the underlying response capability is single-use), so this same instance answers both the availability check and the eventual APPLY or REJECT. """interaction:OperationReviewAvailableInteractionV1projection:ReviewProjectionTcontrol:OperationBoundResponseControlapply_enabled:boolreject_enabled:booldisposition:Literal["review_available"]=field(default="review_available",init=False)def__post_init__(self)->None:"""Confirm the rendered interaction reproduces its own safe reference."""ifself.interaction.revision!=self.interaction.review_reference.revision:raiseValueError("modal REVIEW interaction does not match its own safe reference")
[docs]@dataclass(frozen=True,slots=True)classOperationModalReviewUnavailableV1:"""A pending REVIEW whose safe projection could not currently be resolved."""interaction:OperationReviewAvailableInteractionV1disposition:Literal["review_unavailable"]=field(default="review_unavailable",init=False)
[docs]@dataclass(frozen=True,slots=True)classOperationModalUnsupportedInteractionV1:"""A pending interaction this modal cannot yet render (INPUT or CHOICE)."""interaction:OperationUnsupportedInteractionV1disposition:Literal["unsupported"]=field(default="unsupported",init=False)
[docs]asyncdefresolve_modal_interaction_state[ReviewProjectionT:BaseModel](controller:OperationController,projection:OperationPublicProjectionV1,*,current:OperationModalInteractionStateV1[ReviewProjectionT]|None=None,)->OperationModalInteractionStateV1[ReviewProjectionT]:"""Resolve the exact modal interaction state for the current projection. ``current`` is the state a repeating caller already holds. When the same REVIEW is still pending at the same revision it is returned unchanged, because the response capability behind it is single-use: binding a second control for an interaction already bound consumes the authority and every later availability check refuses, which switches the operator's APPLY and REJECT controls off while the operation is still waiting for exactly that answer. A caller that polls therefore MUST pass what it holds. """# Dispatch over the closed pending-interaction union rather than re-testing# the member the two arms above already excluded: `assert_never` makes a new# member break the build instead of reaching a narrowing that cannot hold.matchprojection.pending_interaction:caseOperationNoPendingInteractionV1():returnOperationModalNoInteractionV1()caseOperationUnsupportedInteractionV1()asunsupported:returnOperationModalUnsupportedInteractionV1(interaction=unsupported)caseOperationReviewAvailableInteractionV1()aspending:passcase_:assert_never(projection.pending_interaction)if(isinstance(current,OperationModalReviewInteractionV1)andcurrent.interaction.interaction_id==pending.interaction_idandcurrent.interaction.revision==pending.revision):returncurrentresolved:OperationReviewProjectionResultV1[ReviewProjectionT]=awaitcontroller.resolve_review(pending.review_reference)ifnotisinstance(resolved,OperationReviewProjectionSuccessV1):returnOperationModalReviewUnavailableV1(interaction=pending)control=awaitcontroller.response_control(interaction_id=pending.interaction_id,revision=pending.revision,)availability=awaitcontrol.inspect()permitted:frozenset[OperationResponseIntentValue]=(availability.permitted_intentsifisinstance(availability,OperationResponseControlSuccessV1)elsefrozenset[OperationResponseIntentValue]())returnOperationModalReviewInteractionV1[ReviewProjectionT](interaction=pending,projection=resolved.projection,control=control,apply_enabled="apply"inpermitted,reject_enabled="reject"inpermitted,)