fix(13-08): confirm timeout 120s→300s + chrome closes an expired dialog
On-device UAT: the operator was timed out mid-read (120s), the chat turn
returned 'declined' while the dialog was still up, and their Approve then
hit a dead entry ('no such pending confirmation', 13:37:12 log). Nothing
executed — the gate failed safe — but the UX was a lie in both directions.
- CONFIRM_TIMEOUT 120s→300s: human-speed per T-13-51's own rubric.
- ContextBroker dispatches aiui:tool-confirm-expired when a pending action
vanishes node-side (poll) or the turn ends; Chat.vue closes the modal on
it. Same host-only CustomEvent discipline; iframe has no path to it.
- Two new tests; 21/21 green across toolConfirm + chatAiuiEmbed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
44f552cc3d
commit
31f9a4d5bf
@@ -217,6 +217,16 @@ function dismissToolConfirm() {
|
||||
toolConfirm.value = null
|
||||
}
|
||||
|
||||
function onToolConfirmExpired(e: Event) {
|
||||
// 13-08 on-device UAT: the node no longer holds this pending action
|
||||
// (timed out, or resolved elsewhere) — close the dialog rather than
|
||||
// leave the human an Approve button whose click can only be refused.
|
||||
const detail = (e as CustomEvent).detail as { reqId?: string }
|
||||
if (toolConfirm.value && detail?.reqId === toolConfirm.value.reqId) {
|
||||
toolConfirm.value = null
|
||||
}
|
||||
}
|
||||
|
||||
function onAiuiMessage(event: MessageEvent) {
|
||||
if (!aiuiUrl.value) return
|
||||
// Validate origin — only accept messages from AIUI
|
||||
@@ -246,6 +256,8 @@ function armChatLive() {
|
||||
window.addEventListener('message', onAiuiMessage)
|
||||
window.removeEventListener('aiui:tool-confirm-request', onToolConfirmRequest)
|
||||
window.addEventListener('aiui:tool-confirm-request', onToolConfirmRequest)
|
||||
window.removeEventListener('aiui:tool-confirm-expired', onToolConfirmExpired)
|
||||
window.addEventListener('aiui:tool-confirm-expired', onToolConfirmExpired)
|
||||
broker?.stop()
|
||||
broker = null
|
||||
if (aiuiUrl.value) {
|
||||
@@ -266,6 +278,7 @@ onActivated(() => armChatLive())
|
||||
onDeactivated(() => {
|
||||
window.removeEventListener('message', onAiuiMessage)
|
||||
window.removeEventListener('aiui:tool-confirm-request', onToolConfirmRequest)
|
||||
window.removeEventListener('aiui:tool-confirm-expired', onToolConfirmExpired)
|
||||
broker?.stop()
|
||||
broker = null
|
||||
if (loadTimeout) { clearTimeout(loadTimeout); loadTimeout = null }
|
||||
@@ -280,6 +293,7 @@ onMounted(() => armChatLive())
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('message', onAiuiMessage)
|
||||
window.removeEventListener('aiui:tool-confirm-request', onToolConfirmRequest)
|
||||
window.removeEventListener('aiui:tool-confirm-expired', onToolConfirmExpired)
|
||||
broker?.stop()
|
||||
broker = null
|
||||
if (loadTimeout) { clearTimeout(loadTimeout); loadTimeout = null }
|
||||
|
||||
Reference in New Issue
Block a user