fix(coding-agent): fixed append-only detection for in-place streaming line growth
- Updated live transcript state derivation to treat a trailing-line extension with unchanged rows as append-only. - Replaced the prior append-grew heuristic with preserved-row checks so non-rewritten history is not marked volatile. - Added a regression test covering in-place streaming line growth and scrollback commit safety in transcript containers.
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
import { describe, expect, it } from "bun:test";
|
||||
import { type Component, TERMINAL } from "@oh-my-pi/pi-tui";
|
||||
import { TranscriptContainer } from "../src/modes/components/transcript-container";
|
||||
|
||||
type MutableTerminalInfo = { eagerEraseScrollbackRisk: boolean };
|
||||
const mutableTerminalInfo = TERMINAL as unknown as MutableTerminalInfo;
|
||||
|
||||
async function withTerminalRisk<T>(risk: boolean, run: () => T | Promise<T>): Promise<T> {
|
||||
const saved = TERMINAL.eagerEraseScrollbackRisk;
|
||||
mutableTerminalInfo.eagerEraseScrollbackRisk = risk;
|
||||
try {
|
||||
return await run();
|
||||
} finally {
|
||||
mutableTerminalInfo.eagerEraseScrollbackRisk = saved;
|
||||
}
|
||||
}
|
||||
|
||||
class MutableLiveBlock implements Component {
|
||||
#lines: string[];
|
||||
constructor(lines: string[]) {
|
||||
this.#lines = [...lines];
|
||||
}
|
||||
render(width: number): string[] {
|
||||
return this.#lines.map(line => line.slice(0, width));
|
||||
}
|
||||
setLines(lines: string[]): void {
|
||||
this.#lines = [...lines];
|
||||
}
|
||||
isTranscriptBlockFinalized(): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
describe("transcript streaming commit (assistant text)", () => {
|
||||
it("treats in-place growth of the trailing line as append-only", async () => {
|
||||
await withTerminalRisk(true, () => {
|
||||
const chat = new TranscriptContainer();
|
||||
// Models a streaming assistant reply: stable head rows plus a current
|
||||
// line that grows token-by-token without adding a new row.
|
||||
const block = new MutableLiveBlock(["para one", "para two", "the quick brown"]);
|
||||
chat.addChild(block);
|
||||
|
||||
chat.render(80);
|
||||
|
||||
block.setLines(["para one", "para two", "the quick brown fox"]);
|
||||
chat.render(80);
|
||||
// The head rows never changed; only the trailing line grew. Its scrolled-
|
||||
// off head must be committable to native scrollback (tmux pane history).
|
||||
expect(chat.getNativeScrollbackCommitSafeEnd()).toBe(3);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user