mirror of
https://github.com/harivansh-afk/clanker-agent.git
synced 2026-04-15 19:05:14 +00:00
- Copy all pi-mono source into apps/companion-os/ - Update Dockerfile to COPY pre-built binary instead of downloading from GitHub Releases - Update deploy-staging.yml to build pi from source (bun compile) before Docker build - Add apps/companion-os/** to path triggers - No more cross-repo dispatch needed Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
113 lines
3.2 KiB
TypeScript
113 lines
3.2 KiB
TypeScript
/**
|
|
* TUI viewport overwrite repro
|
|
*
|
|
* Place this file at: packages/tui/test/viewport-overwrite-repro.ts
|
|
* Run from repo root: npx tsx packages/tui/test/viewport-overwrite-repro.ts
|
|
*
|
|
* For reliable repro, run in a small terminal (8-12 rows) or a tmux session:
|
|
* tmux new-session -d -s tui-bug -x 80 -y 12
|
|
* tmux send-keys -t tui-bug "npx tsx packages/tui/test/viewport-overwrite-repro.ts" Enter
|
|
* tmux attach -t tui-bug
|
|
*
|
|
* Expected behavior:
|
|
* - PRE-TOOL lines remain visible above tool output.
|
|
* - POST-TOOL lines append after tool output without overwriting earlier content.
|
|
*
|
|
* Actual behavior (bug):
|
|
* - When content exceeds the viewport and new lines arrive after a tool-call pause,
|
|
* some earlier PRE-TOOL lines near the bottom are overwritten by POST-TOOL lines.
|
|
*/
|
|
import { ProcessTerminal } from "../src/terminal.js";
|
|
import { type Component, TUI } from "../src/tui.js";
|
|
|
|
const sleep = (ms: number): Promise<void> =>
|
|
new Promise((resolve) => setTimeout(resolve, ms));
|
|
|
|
class Lines implements Component {
|
|
private lines: string[] = [];
|
|
|
|
set(lines: string[]): void {
|
|
this.lines = lines;
|
|
}
|
|
|
|
append(lines: string[]): void {
|
|
this.lines.push(...lines);
|
|
}
|
|
|
|
render(width: number): string[] {
|
|
return this.lines.map((line) => {
|
|
if (line.length > width) return line.slice(0, width);
|
|
return line.padEnd(width, " ");
|
|
});
|
|
}
|
|
|
|
invalidate(): void {}
|
|
}
|
|
|
|
async function streamLines(
|
|
buffer: Lines,
|
|
label: string,
|
|
count: number,
|
|
delayMs: number,
|
|
ui: TUI,
|
|
): Promise<void> {
|
|
for (let i = 1; i <= count; i += 1) {
|
|
buffer.append([`${label} ${String(i).padStart(2, "0")}`]);
|
|
ui.requestRender();
|
|
await sleep(delayMs);
|
|
}
|
|
}
|
|
|
|
async function main(): Promise<void> {
|
|
const ui = new TUI(new ProcessTerminal());
|
|
const buffer = new Lines();
|
|
ui.addChild(buffer);
|
|
ui.start();
|
|
|
|
const height = ui.terminal.rows;
|
|
const preCount = height + 8; // Ensure content exceeds viewport
|
|
const toolCount = height + 12; // Tool output pushes further into scrollback
|
|
const postCount = 6;
|
|
|
|
buffer.set([
|
|
"TUI viewport overwrite repro",
|
|
`Viewport rows detected: ${height}`,
|
|
"(Resize to ~8-12 rows for best repro)",
|
|
"",
|
|
"=== PRE-TOOL STREAM ===",
|
|
]);
|
|
ui.requestRender();
|
|
await sleep(300);
|
|
|
|
// Phase 1: Stream pre-tool text until viewport is exceeded.
|
|
await streamLines(buffer, "PRE-TOOL LINE", preCount, 30, ui);
|
|
|
|
// Phase 2: Simulate tool call pause and tool output.
|
|
buffer.append(["", "--- TOOL CALL START ---", "(pause...)", ""]);
|
|
ui.requestRender();
|
|
await sleep(700);
|
|
|
|
await streamLines(buffer, "TOOL OUT", toolCount, 20, ui);
|
|
|
|
// Phase 3: Post-tool streaming. This is where overwrite often appears.
|
|
buffer.append(["", "=== POST-TOOL STREAM ==="]);
|
|
ui.requestRender();
|
|
await sleep(300);
|
|
await streamLines(buffer, "POST-TOOL LINE", postCount, 40, ui);
|
|
|
|
// Leave the output visible briefly, then restore terminal state.
|
|
await sleep(1500);
|
|
ui.stop();
|
|
}
|
|
|
|
main().catch((error) => {
|
|
// Ensure terminal is restored if something goes wrong.
|
|
try {
|
|
const ui = new TUI(new ProcessTerminal());
|
|
ui.stop();
|
|
} catch {
|
|
// Ignore restore errors.
|
|
}
|
|
process.stderr.write(`${String(error)}\n`);
|
|
process.exitCode = 1;
|
|
});
|