Fix queued chat message parity#935
Conversation
Mirror web UI queue behavior by assigning stable per-message send run IDs and forwarding them as chat.send idempotency keys. Reconcile queued prompts by identity instead of prompt text so duplicate user messages remain distinct. Handle deferred in_flight admissions by requeueing with bounded backoff, failing visibly when the gateway never admits the run, and preventing ambiguous assistant retransmits from being replayed across queued-user boundaries. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
Codex review: needs changes before merge. Reviewed July 7, 2026, 7:12 PM ET / 23:12 UTC. Summary Reproducibility: yes. from source inspection: feed the PR a queued chat.send acknowledgement with Review metrics: 2 noteworthy metrics.
Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Copy recommended automerge instructionNext step before merge
Security Review findings
Review detailsBest possible solution: Classify gateway Do we have a high-confidence way to reproduce the issue? Yes, from source inspection: feed the PR a queued chat.send acknowledgement with Is this the best way to solve the issue? No: the provider-level queue identity/idempotency direction is the right boundary, but the patch needs terminal timeout handling before it is the narrow maintainable fix. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 87634727b65b. Label changesLabel changes:
Label justifications:
Evidence reviewedAcceptance criteria:
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
Catch and warn on unexpected exceptions from fire-and-forget queued send drain dispatch so failures are diagnosable instead of becoming unobserved task exceptions. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Allow native tray chat users to remove queued or failed queued messages by local queue identity before they are dispatched. Wire the cancel action through the chat provider and composer, and add accessible state-specific controls for pending and failed cards. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Expose native chat queue inspection and cancellation through local MCP app.chat tools, include queued entries in chat snapshots, and document the new winnode surface. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Disable the model and reasoning controls while an assistant turn is active or queued messages remain, leaving the session selector available for UX testing. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Keep queued run/idempotency mappings and local echo suppression alive while an in_flight send waits for retry, and track accepted deferred run IDs for lifecycle promotion/reset gating. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Summary
chat.send.idempotencyKey.in_flightas deferred admission with bounded backoff, visible failure on exhaustion, safe handling for active-run/direct-send races, and preserved run/idempotency correlation through lifecycle promotion or terminal cleanup.Validation
./build.ps1— passeddotnet test ./tests/OpenClaw.Shared.Tests/OpenClaw.Shared.Tests.csproj --no-restore— 2701 passed / 31 skippeddotnet test ./tests/OpenClaw.Tray.Tests/OpenClaw.Tray.Tests.csproj --no-restore— 1597 passeddotnet test ./tests/OpenClaw.WinNode.Cli.Tests/OpenClaw.WinNode.Cli.Tests.csproj --no-restore— 120 passedGateway status contract
ChatSendAckStatusdefinition:"started" | "in_flight" | "ok" | "timeout" | "error".in_flightis the deferred non-terminal admission status.timeoutanderrorare terminal failure statuses,startedis accepted/admitted, andokis completed/idempotent success.Real behavior proof
hellomessages through the tray chat UI; all three drained successfully, leaving 0 queued cards and 3 visiblehellouser turns.GatewayProtocolLiveRoundTripTests.ChatSend_UsesCallerProvidedIdempotencyKeyOnWire, provingOpenClawGatewayClientsends caller-providedidempotencyKey.QueuedSend_InFlightAckThenLifecycleBeforeRetry_PromotesWithoutResend, coveringin_flightfollowed by matchinglifecycle.startbefore retry, with no resend and no duplicate user echo.Current-head MCP proof
winnode --list-toolsadvertised both queue tools from current PR head:Controlled proof run
proof-155257queued two duplicate outgoing messages, listed both over MCP, canceled onlyq2, and confirmedq3remained queued:Current-head UIA transcript
After the MCP cancel, UIA saw the remaining duplicate queued card and exactly one cancel control for that sibling:
Screenshot of queued messages:

Review
Not verified / blocked