mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-10 01:09:43 +02:00
fix(tiles): treat the server's clear frame as a refresh, not a bare clear
The server sends {t:'c'} from one place only: a fresh Claude pane's first
prompt (Session.startInteractive), meaning "refresh after startup". The
primary pane answers it with a refetch and replay (_onSessionClearTerminal),
and stands aside while the grid is open, so the tile's own handling was the
only one that ran. That handling was a bare xterm clear(), which keeps only
the cursor's row and drops the banner, a resumed transcript and all
scrollback. An idle Claude never repaints static rows, so a Claude session
Run into the grid, or Attached in a tile, came up as a near-empty tile.
_onLiveClear() now calls _refreshBuffer(), the {t:'r'} path: single-flight,
coalesced into one trailing refresh behind a load already running (a shell
pull's held frames included), and paced by the grid's TileLoadQueue. The
queued {clear:true} entry and its branch in _pullHistory's flush are gone,
along with the _clearTerminal helper they used.
Tests: two unit tests pinned the bare clear (a clear frame queued in order
during a pull, and one applied at once before the capture); they are
replaced by tests that the frame coalesces behind the pull and refetches,
plus a socket-level {t:'c'} test, a coalescing test, and a grid test that
the frame waits its turn in the load queue.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -278,6 +278,24 @@ describe('refreshes', () => {
|
||||
expect(b.terminal?.writes.slice(-2)).toEqual(['<CLEAR>', 'fresh']);
|
||||
});
|
||||
|
||||
it("a server {t:'c'} (a Claude pane's first prompt) is a refresh through the same queue", async () => {
|
||||
const { tiles } = makeGrid(['a', 'b']);
|
||||
await connectAll(tiles);
|
||||
const [a, b] = tiles;
|
||||
a.ws?.receive({ t: 'r' });
|
||||
b.ws?.receive({ t: 'c' });
|
||||
await settle();
|
||||
|
||||
// b waits behind a, like any refresh: one capture in flight.
|
||||
expect(captures.map((c) => c.url.split('/')[3])).toEqual(['a']);
|
||||
expect(await drain('banner')).toBe(1);
|
||||
expect(captures.map((c) => c.url)).toEqual([
|
||||
`/api/sessions/a/terminal?full=1&tail=${TAIL}${LINES}`,
|
||||
`/api/sessions/b/terminal?full=1&tail=${TAIL}${LINES}`,
|
||||
]);
|
||||
expect(b.terminal?.writes.at(-1)).toBe('banner');
|
||||
});
|
||||
|
||||
it('a history pull jumps ahead of background refreshes', async () => {
|
||||
const { tiles } = makeGrid(['a', 'b', 'sh'], { modes: { sh: 'shell' } });
|
||||
await connectAll(tiles);
|
||||
|
||||
Reference in New Issue
Block a user