fix(gateway): filter delivery-mirror entries from chat.history#38075
fix(gateway): filter delivery-mirror entries from chat.history#38075MumuTW wants to merge 1 commit into
Conversation
When a delivery channel (e.g. Telegram) is configured, each assistant reply is mirrored into the session transcript as an internal delivery-mirror entry (provider=openclaw, model=delivery-mirror). The chat.history endpoint returned these mirror entries alongside the real provider messages, causing webchat to display the same assistant reply twice. Telegram was unaffected because it only receives the actual delivery. Filter out delivery-mirror messages in sanitizeChatHistoryMessages() so that chat.history returns only the original assistant replies. Fixes openclaw#38061 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Greptile SummaryThis PR filters out internal The implementation adds a small
Confidence Score: 4/5
Last reviewed commit: ec0aafb |
| function isDeliveryMirrorMessage(message: unknown): boolean { | ||
| if (!message || typeof message !== "object") { | ||
| return false; | ||
| } | ||
| const entry = message as Record<string, unknown>; | ||
| return entry.role === "assistant" && entry.model === "delivery-mirror"; | ||
| } |
There was a problem hiding this comment.
Misplaced JSDoc comment
The existing JSDoc block (lines 214–219) that describes extractAssistantTextForSilentCheck ("Extract the visible text from an assistant history message for silent-token checks…") now directly precedes the newly inserted isDeliveryMirrorMessage function. In TypeScript/JSDoc tooling, a /** … */ comment attaches to the declaration that immediately follows it, so the wrong function now appears to be documented by that comment while extractAssistantTextForSilentCheck loses its documentation entirely.
The new function should be inserted before the JSDoc block (i.e., above line 214), or a separate JSDoc should be added for isDeliveryMirrorMessage so both functions retain accurate documentation.
| function isDeliveryMirrorMessage(message: unknown): boolean { | |
| if (!message || typeof message !== "object") { | |
| return false; | |
| } | |
| const entry = message as Record<string, unknown>; | |
| return entry.role === "assistant" && entry.model === "delivery-mirror"; | |
| } | |
| /** | |
| * Returns true when the message is an internal delivery-mirror transcript entry | |
| * that should be excluded from `chat.history` responses. | |
| */ | |
| function isDeliveryMirrorMessage(message: unknown): boolean { | |
| if (!message || typeof message !== "object") { | |
| return false; | |
| } | |
| const entry = message as Record<string, unknown>; | |
| return entry.role === "assistant" && entry.model === "delivery-mirror"; | |
| } |
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/gateway/server-methods/chat.ts
Line: 220-226
Comment:
**Misplaced JSDoc comment**
The existing JSDoc block (lines 214–219) that describes `extractAssistantTextForSilentCheck` ("Extract the visible text from an assistant history message for silent-token checks…") now directly precedes the newly inserted `isDeliveryMirrorMessage` function. In TypeScript/JSDoc tooling, a `/** … */` comment attaches to the declaration that immediately follows it, so the wrong function now appears to be documented by that comment while `extractAssistantTextForSilentCheck` loses its documentation entirely.
The new function should be inserted *before* the JSDoc block (i.e., above line 214), or a separate JSDoc should be added for `isDeliveryMirrorMessage` so both functions retain accurate documentation.
```suggestion
/**
* Returns true when the message is an internal delivery-mirror transcript entry
* that should be excluded from `chat.history` responses.
*/
function isDeliveryMirrorMessage(message: unknown): boolean {
if (!message || typeof message !== "object") {
return false;
}
const entry = message as Record<string, unknown>;
return entry.role === "assistant" && entry.model === "delivery-mirror";
}
```
How can I resolve this? If you propose a fix, please make it concise.|
Friendly bump — this filters delivery-mirror entries from chat.history. Any concerns? |
|
This pull request has been automatically marked as stale due to inactivity. |
|
Closing this as duplicate or superseded after Codex automated review. PR #38075 is superseded by the merged write-side fix in #67185. Current main prevents the duplicate visible-reply case by reusing the latest matching real assistant transcript entry instead of appending a redundant delivery-mirror row, with regression coverage and a v2026.4.15 changelog entry. Best possible solution: Keep the shipped #67185 write-side dedupe as the canonical fix for duplicate visible replies, close this older chat.history-only PR as superseded, and use #40716 or a new focused issue only if maintainers still want historical cleanup or broader consumer-path filtering. What I checked:
So I’m closing this here and keeping the remaining discussion on the canonical linked item. Codex Review notes: model gpt-5.5, reasoning high; reviewed against 46b9044c3f9d; fix evidence: release v2026.4.15, commit d842ec417924. |
Summary
delivery-mirrortranscript entries fromchat.historyresponses so webchat no longer displays duplicate assistant messages.model: "delivery-mirror". Thechat.historyendpoint was returning these alongside real provider messages, causing webchat to render the same reply twice.sanitizeChatHistoryMessages()that drops messages withmodel === "delivery-mirror", consistent with the existing pattern for filtering silent-reply messages.Test plan
chat.historyAPI response no longer containsdelivery-mirrorentriesFixes #38061