summaryrefslogtreecommitdiffhomepage
path: root/src/features/chat
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-06-22 14:18:56 +0900
committerAdam Malczewski <[email protected]>2026-06-22 14:18:56 +0900
commit22605de0816a09a90058306ec614ea375ede67cc (patch)
tree3a0f511fc6b8bd2f3627928b9e7ff3f76e2a979a /src/features/chat
parentd35462646f9f7ecbbdb0df8af564e668c7bcfe7c (diff)
downloaddispatch-web-22605de0816a09a90058306ec614ea375ede67cc.tar.gz
dispatch-web-22605de0816a09a90058306ec614ea375ede67cc.zip
fix: trim provisional chunks during long turns (browser stays responsive)
trimTranscript now drops oldest provisional chunks (the in-flight turn) when committed chunks are exhausted. Previously it bailed with drop=0 when committed was empty, allowing unbounded provisional growth during long generating turns (300+ chunks → browser crawls). Root cause of the syncTail approach failing: the kernel emits step-complete (line 360) BEFORE calling onStepComplete (line 542) — chunks are persisted only after tool results come back, not when step-complete fires. So syncTail on step-complete found nothing. Reverted the applyHistory + syncTail-on-step-complete changes from d354626. The new approach is simpler: trim provisional directly in trimTranscript. Dropped chunks are lost temporarily (no Show Earlier) but come back as committed when the turn seals and syncTail fetches everything from the server. 686 tests green.
Diffstat (limited to 'src/features/chat')
-rw-r--r--src/features/chat/store.svelte.ts5
-rw-r--r--src/features/chat/store.test.ts8
2 files changed, 5 insertions, 8 deletions
diff --git a/src/features/chat/store.svelte.ts b/src/features/chat/store.svelte.ts
index f6c23fc..9beabfc 100644
--- a/src/features/chat/store.svelte.ts
+++ b/src/features/chat/store.svelte.ts
@@ -284,11 +284,6 @@ export function createChatStore(deps: ChatStoreDependencies): ChatStore {
if (transcript.sealedTurnId !== null) {
void syncTail();
void syncMetrics();
- } else if (msg.event.type === "step-complete") {
- // CR-6: backend persists chunks at step boundaries. Fetch them
- // as committed so trimTranscript can unload oldest chunks
- // uniformly — no unbounded provisional growth during long turns.
- void syncTail();
}
},
diff --git a/src/features/chat/store.test.ts b/src/features/chat/store.test.ts
index 2d75139..c1d62a6 100644
--- a/src/features/chat/store.test.ts
+++ b/src/features/chat/store.test.ts
@@ -1057,8 +1057,9 @@ describe("createChatStore", () => {
}
expect(store.chunks).toHaveLength(15);
- // Reader returns to the bottom — but provisional chunks are never unloaded,
- // so the deferred trim still can't shrink an all-provisional transcript.
+ // Reader returns to the bottom — the deferred trim now catches up.
+ // With no committed chunks, it drops the oldest provisional chunks
+ // (the in-flight turn) to stay within the limit.
atBottom = true;
store.handleDelta(
deltaEvent({
@@ -1071,7 +1072,8 @@ describe("createChatStore", () => {
stepId: "t1#15" as StepId,
}),
);
- expect(store.chunks).toHaveLength(16);
+ // 16 provisional, limit 10, quarter 3 → drop 6 oldest → 10 remain.
+ expect(store.chunks).toHaveLength(10);
store.dispose();
});