fix(gateway): retire native clarify cards on timeout, reset and prose cancel
One adapter-facing seam replaces the Slack-only callback: an adapter whose clarify prompt is a persistent card (Slack Block Kit) defines `retire_clarify_card(clarify_id, notice)`, and the gateway calls it from every path that ends a clarify without a button click: - TurnRunner._clarify_callback_sync: when the bounded wait returns a sentinel (timeout, /new or run-end clear_session), schedule the retire with the expired notice on the gateway loop (#110821). - run_inbound TEXT_REJECTED_PROSE: retire with the cancelled notice before the prose is routed as a follow-up (#111019). Lookup is on the adapter class so MagicMock doubles cannot fabricate the method; no platform == SLACK special-case. The Slack map is keyed by clarify_id and popped before the first await, so a late timer cannot touch a newer prompt and the button handler's ts-keyed guard makes a racing click a no-op. Gateway-restart-orphaned cards stay out of scope: nothing is waiting on the new process, and the click path already renders them expired. Tests trimmed to invariants: the runner-level timeout probe (card adapter vs no-card adapter), the inbound prose retire, and one Slack test covering buttons-dropped + late-click-noop. Docs updated for the new in-place edit.
This commit is contained in:
@@ -1048,8 +1048,8 @@ class SlackAdapter(BasePlatformAdapter):
|
||||
# Bounded: never-clicked prompts would otherwise leak forever.
|
||||
self._approval_resolved: Dict[Any, bool] = {}
|
||||
self._clarify_resolved: Dict[Any, bool] = {}
|
||||
# clarify_id → (channel_id, message_ts, rendered_question). This lets the inbound
|
||||
# free-prose path retire a native card that will no longer accept a response.
|
||||
# clarify_id → (channel_id, message_ts, rendered_question) so the gateway can retire a
|
||||
# card whose clarify ended without a click (timeout, reset, superseding prose).
|
||||
self._clarify_messages: Dict[str, Tuple[str, str, str]] = {}
|
||||
# Model picker state keyed by workspace message marker (team_id, ts) →
|
||||
# picker context (providers, session_key, on_model_selected, stage).
|
||||
@@ -5416,12 +5416,13 @@ class SlackAdapter(BasePlatformAdapter):
|
||||
channel_id, msg_ts, question_text, decision_text, "Clarification", "clarify", sanitize=False
|
||||
)
|
||||
|
||||
async def cancel_clarify_message(self, clarify_id: str) -> None:
|
||||
"""Retire a Block Kit clarify card released by unmatched free prose.
|
||||
async def retire_clarify_card(self, clarify_id: str, notice: str) -> None:
|
||||
"""Rewrite a still-live clarify card into a terminal, button-less state.
|
||||
|
||||
The generic inbound path intentionally lets that prose continue as a normal follow-up.
|
||||
Slack alone needs to edit its already-posted interactive card so its buttons do not
|
||||
advertise an answer path that the released clarify can no longer accept.
|
||||
The gateway calls this whenever it ends a clarify without a button click — the wait
|
||||
timed out, the session was reset, or unmatched free prose superseded the prompt — so
|
||||
the card stops advertising an answer path the released clarify can no longer accept.
|
||||
Keyed by clarify_id, so a late call cannot touch a newer prompt; no-op once resolved.
|
||||
"""
|
||||
target = self._clarify_messages.pop(clarify_id, None)
|
||||
if target is None:
|
||||
@@ -5429,9 +5430,7 @@ class SlackAdapter(BasePlatformAdapter):
|
||||
channel_id, msg_ts, question_text = target
|
||||
# A late action handler must be a no-op while the best-effort chat.update is in flight.
|
||||
self._clarify_resolved[msg_ts] = True
|
||||
await self._update_clarify_message(
|
||||
channel_id, msg_ts, question_text,
|
||||
"↩️ Clarification cancelled — your message will be handled as a follow-up.")
|
||||
await self._update_clarify_message(channel_id, msg_ts, question_text, notice)
|
||||
|
||||
async def _handle_clarify_action(self, ack, body, action) -> None:
|
||||
"""Handle a clarify button click (a choice or "Other") from Block Kit."""
|
||||
|
||||
Reference in New Issue
Block a user