fix(gateway): expose idempotencyKey on chat.history __openclaw envelope (#79844)#80044
fix(gateway): expose idempotencyKey on chat.history __openclaw envelope (#79844)#80044Sanjays2402 wants to merge 1 commit into
Conversation
…pe (openclaw#79844) When a user message is sent with an idempotencyKey, that key is persisted on the transcript message but was only available as a top-level message field on hydration. Clients consuming chat.history (and the SSE inline message stream) expect identity-style metadata to live inside the __openclaw envelope alongside seq, id, importedFrom, etc. Hoist the persisted idempotencyKey into __openclaw at hydration time: - parsedSessionEntryToMessage (chat.history reads + recent-tail reads) - SessionHistorySseState.appendInlineMessage (live SSE inline append) - broadcastSessionMessage in server-session-events (inline broadcast path) The original top-level field is preserved for back-compat, so no existing reader breaks. Tests: - session-utils.fs.test.ts: idempotencyKey surfaces on full + recent reads - session-history-state.test.ts: idempotencyKey surfaces on inline append
|
Codex review: needs real behavior proof before merge. Summary Reproducibility: yes. by source inspection. A transcript row with Real behavior proof Next step before merge Security Review findings
Review detailsBest possible solution: Carry the client idempotency key at the canonical Do we have a high-confidence way to reproduce the issue? Yes, by source inspection. A transcript row with Is this the best way to solve the issue? No. The history hydration change is the right direction, but the live SSE fix should pass the client key into the canonical Full review comments:
Overall correctness: patch is incorrect What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against 862be9fb3d6c. |
|
Closing — stale (15+ days). Will reopen / resubmit if still relevant. |
Fixes #79844.
Problem
When a user message is sent with an
idempotencyKey, that key is persisted on the transcript message but only surfaces as a top-level message field on hydration. Clients consumingchat.history(and the SSE inline stream) expect identity-style metadata to live inside the__openclawenvelope alongsideseq,id,importedFrom, etc., so they can correlate echoed messages without sniffing top-level fields.Change
Hoist the persisted
idempotencyKeyinto the__openclawenvelope at hydration time:parsedSessionEntryToMessageinsrc/gateway/session-utils.fs.ts— coverschat.historyfull reads and recent-tail reads.SessionHistorySseState.appendInlineMessageinsrc/gateway/session-history-state.ts— covers the live inline SSE append.broadcastSessionMessageinsrc/gateway/server-session-events.ts— covers the inline broadcast path.The original top-level
idempotencyKeyfield is preserved on the message object for back-compat, so existing readers do not regress.Tests
src/gateway/session-utils.fs.test.ts— new test verifiesidempotencyKeysurfaces on both full and recent-tail reads, and is absent when the persisted message has no key.src/gateway/session-history-state.test.ts— new test verifies inline-append surfacesidempotencyKeyin__openclawalongsideid/seq.Verification
pnpm tsgo:core— cleanpnpm tsgo:core:test— cleannode scripts/run-vitest.mjs run --config test/vitest/vitest.gateway.config.ts src/gateway/session-utils.fs.test.ts src/gateway/session-history-state.test.ts— 92/92 passnode scripts/run-oxlint.mjs --tsconfig config/tsconfig/oxlint.core.jsonover the touched files — clean