



























@@ -219,15 +219,23 @@ function isTerminalRunEvent(event: OpenClawEvent): boolean {
219219function normalizeChatProjectionEvent(
220220event: OpenClawEvent,
221221projection: ChatProjection,
222+previousText: string | undefined,
222223): OpenClawEvent {
223224const text = readChatProjectionText(projection.payload);
225+const isReplacement = Boolean(
226+previousText && text !== undefined && !text.startsWith(previousText),
227+);
224228return {
225229 ...event,
226230type: projection.state === "delta" ? "assistant.delta" : "run.completed",
227231data:
228232projection.state === "delta"
229233 ? text !== undefined
230- ? { delta: text }
234+ ? {
235+ text,
236+delta: isReplacement ? text : text.slice(previousText?.length ?? 0),
237+ ...(isReplacement ? { replace: true } : {}),
238+}
231239 : event.data
232240 : { phase: "end", ...(text !== undefined ? { outputText: text } : {}) },
233241};
@@ -335,20 +343,30 @@ export class OpenClaw {
335343const replayEvents = this.replaySnapshot(runId);
336344let hasCanonicalAssistantRunEvent = replayEvents.some(isAssistantRunEvent);
337345let hasTerminalRunEvent = replayEvents.some(isTerminalRunEvent);
346+let previousChatProjectionText: string | undefined;
338347const toRunStreamEvent = (event: OpenClawEvent): OpenClawEvent | undefined => {
339348const chatProjection = readChatProjection(event);
340349if (chatProjection?.state === "delta") {
341350if (hasCanonicalAssistantRunEvent) {
342351return undefined;
343352}
344-return normalizeChatProjectionEvent(event, chatProjection);
353+const runEvent = normalizeChatProjectionEvent(
354+event,
355+chatProjection,
356+previousChatProjectionText,
357+);
358+const text = readChatProjectionText(chatProjection.payload);
359+if (text !== undefined) {
360+previousChatProjectionText = text;
361+}
362+return runEvent;
345363}
346364if (chatProjection?.state === "final") {
347365if (hasTerminalRunEvent) {
348366return undefined;
349367}
350368hasTerminalRunEvent = true;
351-return normalizeChatProjectionEvent(event, chatProjection);
369+return normalizeChatProjectionEvent(event, chatProjection, previousChatProjectionText);
352370}
353371if (isAssistantRunEvent(event)) {
354372hasCanonicalAssistantRunEvent = true;
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。