fix(coding-agent): flush throttled output tails

This commit is contained in:
Wolfgang Schoenberger
2026-07-10 18:43:31 -07:00
parent 7aa1d581c6
commit 71aaad50e6
3 changed files with 88 additions and 13 deletions
@@ -1,4 +1,4 @@
import { afterEach, describe, expect, test } from "bun:test";
import { afterEach, describe, expect, test, vi } from "bun:test";
import * as fs from "node:fs/promises";
import * as os from "node:os";
import * as path from "node:path";
@@ -32,6 +32,7 @@ function byteLength(text: string): number {
}
afterEach(async () => {
vi.useRealTimers();
for (const dir of createdTempDirs.splice(0)) {
await removeWithRetries(dir);
}
@@ -317,6 +318,48 @@ describe("OutputSink", () => {
expect(dumped.output).toBe("abc");
});
test("throttled onChunk emits a quiet tail at the throttle boundary", () => {
vi.useFakeTimers();
const chunks: string[] = [];
const sink = new OutputSink({ onChunk: chunk => chunks.push(chunk), chunkThrottleMs: 20 });
sink.push("a");
sink.push("b");
expect(chunks).toEqual(["a"]);
vi.advanceTimersByTime(20);
expect(chunks).toEqual(["a", "b"]);
});
test("dump flushes a throttled tail once and cancels its timer", async () => {
vi.useFakeTimers();
const chunks: string[] = [];
const sink = new OutputSink({ onChunk: chunk => chunks.push(chunk), chunkThrottleMs: 20 });
sink.push("a");
sink.push("b");
expect((await sink.dump()).output).toBe("ab");
expect(chunks).toEqual(["a", "b"]);
vi.advanceTimersByTime(20);
expect(chunks).toEqual(["a", "b"]);
});
test("replace cancels a throttled tail and discards its pending preview", () => {
vi.useFakeTimers();
const chunks: string[] = [];
const sink = new OutputSink({ onChunk: chunk => chunks.push(chunk), chunkThrottleMs: 20 });
sink.push("a");
sink.push("superseded");
sink.replace("replacement");
vi.advanceTimersByTime(20);
expect(chunks).toEqual(["a"]);
});
test("caps artifact-on-disk size: head + notice + tail when stream exceeds cap", async () => {
const dir = await createTempDir();
const artifactPath = path.join(dir, "capped.log");