Skip to content

Commit 458aac2

Browse files
committed
fix(webview): deterministic chat update ordering and safer throttles
Task: sort batched messageUpdated by ts; clear messageUpdateTimer in dispose; use provider.log; remove any-cast for ts ClineProvider: void postMessage in throttle callbacks; clear indexStatusThrottleTimer in dispose
1 parent 03d28f9 commit 458aac2

File tree

2 files changed

+35
-11
lines changed

2 files changed

+35
-11
lines changed

src/core/task/Task.ts

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -663,7 +663,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
663663
}
664664

665665
// Batch UI updates within a short window to avoid overwhelming the webview
666-
const ts = (message as any)?.ts as number | undefined
666+
const ts = message.ts as number | undefined
667667
if (typeof ts === "number") {
668668
this.messageUpdateBuffer.set(ts, message)
669669
} else {
@@ -684,28 +684,38 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
684684
this.messageUpdateBuffer = new Map()
685685
this.messageUpdateTimer = undefined
686686

687-
const batch = Array.from(batchMap.values())
687+
const batch = Array.from(batchMap.values()).sort((a, b) => (a.ts ?? 0) - (b.ts ?? 0))
688688

689689
const providerNow = this.providerRef.deref()
690690
if (!providerNow) {
691-
console.warn(
692-
`[Task#updateClineMessage] Dropping ${batch.length} messageUpdated deltas: provider unavailable`,
693-
)
691+
this.providerRef
692+
.deref()
693+
?.log(
694+
`[Task#updateClineMessage] Dropping ${batch.length} messageUpdated deltas: provider unavailable`,
695+
)
694696
return
695697
}
696698
if (!providerNow.isVisible()) {
697699
// Drop deltas while hidden; UI will receive a full state sync on visibility
698-
console.debug(
699-
`[Task#updateClineMessage] Dropping ${batch.length} messageUpdated deltas while hidden`,
700-
)
700+
this.providerRef
701+
.deref()
702+
?.log(
703+
`[Task#updateClineMessage] Dropping ${batch.length} messageUpdated deltas while hidden`,
704+
)
701705
return
702706
}
703707

704708
for (const m of batch) {
705709
await providerNow.postMessageToWebview({ type: "messageUpdated", clineMessage: m })
706710
}
707711
} catch (e) {
708-
console.error("[Task#updateClineMessage] Failed to flush message updates:", e)
712+
this.providerRef
713+
.deref()
714+
?.log(
715+
`[Task#updateClineMessage] Failed to flush message updates: ${
716+
e instanceof Error ? e.message : String(e)
717+
}`,
718+
)
709719
}
710720
}, this.MESSAGE_UPDATE_THROTTLE_MS)
711721
}
@@ -1581,6 +1591,13 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
15811591
public dispose(): void {
15821592
console.log(`[Task#dispose] disposing task ${this.taskId}.${this.instanceId}`)
15831593

1594+
// Clear pending batched message timer and buffer
1595+
if (this.messageUpdateTimer) {
1596+
clearTimeout(this.messageUpdateTimer)
1597+
this.messageUpdateTimer = undefined
1598+
}
1599+
this.messageUpdateBuffer.clear()
1600+
15841601
// Dispose message queue and remove event listeners.
15851602
try {
15861603
if (this.messageQueueStateChangedHandler) {

src/core/webview/ClineProvider.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,13 @@ export class ClineProvider
583583
async dispose() {
584584
this.log("Disposing ClineProvider...")
585585

586+
// Clear throttled timers
587+
if (this.indexStatusThrottleTimer) {
588+
clearTimeout(this.indexStatusThrottleTimer)
589+
this.indexStatusThrottleTimer = undefined
590+
}
591+
this.pendingIndexStatus = undefined
592+
586593
// Clear all tasks from the stack.
587594
while (this.clineStack.length > 0) {
588595
await this.removeClineFromStack()
@@ -2478,7 +2485,7 @@ export class ClineProvider
24782485
this.pendingIndexStatus = undefined
24792486
this.indexStatusThrottleTimer = undefined
24802487

2481-
this.postMessageToWebview({
2488+
void this.postMessageToWebview({
24822489
type: "indexingStatusUpdate",
24832490
values,
24842491
})
@@ -2491,7 +2498,7 @@ export class ClineProvider
24912498
}
24922499

24932500
// Send initial status for the current workspace
2494-
this.postMessageToWebview({
2501+
void this.postMessageToWebview({
24952502
type: "indexingStatusUpdate",
24962503
values: currentManager.getCurrentStatus(),
24972504
})

0 commit comments

Comments
 (0)