@agfpd/iapeer 0.2.88 → 0.2.89
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/shadow/render.ts +10 -13
- package/src/supervisor/daemon.ts +18 -17
package/package.json
CHANGED
package/src/shadow/render.ts
CHANGED
|
@@ -30,22 +30,19 @@ export function modelToPlainText(term: Terminal, cols: number, rows: number): st
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
|
-
* ATTACH
|
|
34
|
-
*
|
|
35
|
-
* the
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* blanks. SGR colour is a deliberate follow-up — plain text first kills the mush without colour as a
|
|
42
|
-
* second source of truth.
|
|
33
|
+
* ATTACH HISTORY rows — the model's SCROLLBACK ONLY (rows `0..baseY`, the committed history ABOVE the
|
|
34
|
+
* live viewport), as physical rows of plain text. The LIVE viewport (`baseY..`) is DELIBERATELY EXCLUDED:
|
|
35
|
+
* claude paints the current screen itself (its live render, forwarded right after attach), so including
|
|
36
|
+
* the viewport here would DOUBLE-PAINT it — the snapshot's copy collides with claude's live repaint →
|
|
37
|
+
* smeared overlap (the recurring bug). So on attach we ONLY prepend the history; claude shows the current
|
|
38
|
+
* screen. The @xterm model has already flattened claude's relative-cursor redraws into committed lines, so
|
|
39
|
+
* these rows render as native scrollback with no duplication. Trailing blank rows are dropped. SGR colour
|
|
40
|
+
* is a deliberate follow-up — plain text first.
|
|
43
41
|
*/
|
|
44
|
-
export function modelAttachSnapshotRows(term: Terminal, cols: number
|
|
42
|
+
export function modelAttachSnapshotRows(term: Terminal, cols: number): string[] {
|
|
45
43
|
const b = term.buffer.active
|
|
46
44
|
const out: string[] = []
|
|
47
|
-
|
|
48
|
-
for (let y = 0; y < end; y++) {
|
|
45
|
+
for (let y = 0; y < b.baseY; y++) {
|
|
49
46
|
const l = b.getLine(y)
|
|
50
47
|
out.push(l ? l.translateToString(true, 0, cols) : '')
|
|
51
48
|
}
|
package/src/supervisor/daemon.ts
CHANGED
|
@@ -311,13 +311,14 @@ export function runSupervisorDaemon(opts: SupervisorDaemonOptions): void {
|
|
|
311
311
|
// scrollback for claude's relative-cursor, no-scroll-region TUI. Scrollback rows are spinner-stripped, the
|
|
312
312
|
// viewport is verbatim. NO clears (\x1b[2J/3J): a fresh window needs none; Apple Terminal mishandles them.
|
|
313
313
|
const sendSnapshot = (s: { write(b: Buffer): number }): void => {
|
|
314
|
-
const
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
314
|
+
const historyRows = modelAttachSnapshotRows(xterm, cols) // SCROLLBACK only — claude paints the viewport live
|
|
315
|
+
const cleaned = stripSpinnerScrollback(historyRows.join('\r\n'), 0) // strip spinner remnants from ALL of history
|
|
316
|
+
// Prepend the committed HISTORY above the screen claude is about to repaint, after a modes-restore prefix.
|
|
317
|
+
// NO viewport rows — that is claude's job (forwarded live), which avoids the snapshot↔live double-paint
|
|
318
|
+
// overlap. Always send at least the modes prefix (restores bracketed-paste / app-cursor for a fresh session).
|
|
319
|
+
const body = '\x1b[0m' + terminalModesPrefix(xterm) + (cleaned ? cleaned + '\r\n' : '')
|
|
320
|
+
sendClient(s, frame(FRAME_DATA, Buffer.from(body, 'utf8'))) // UTF-8: rows carry real glyphs (❯, box chars)
|
|
321
|
+
initializing.delete(s as object) // history sent → resume live forwarding (claude's viewport repaint)
|
|
321
322
|
}
|
|
322
323
|
|
|
323
324
|
// Resize the model + child pty to (c, r). Shared by LATER client resizes and the last-detach restore.
|
|
@@ -356,16 +357,16 @@ export function runSupervisorDaemon(opts: SupervisorDaemonOptions): void {
|
|
|
356
357
|
cols = c
|
|
357
358
|
rows = r
|
|
358
359
|
}
|
|
359
|
-
sendSnapshot(s) //
|
|
360
|
-
//
|
|
361
|
-
//
|
|
362
|
-
//
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
360
|
+
sendSnapshot(s) // prepend the scrollback HISTORY (no viewport) + lift gate — synchronous, no interleave
|
|
361
|
+
// Force claude to repaint its CURRENT viewport BELOW the prepended history. A SIGWINCH triggers a full
|
|
362
|
+
// redraw; the (r-1)→r nudge guarantees it fires even on a SAME-size reattach (else an idle claude would
|
|
363
|
+
// leave the viewport blank until its next frame). Safe now: the snapshot carries NO viewport, so claude's
|
|
364
|
+
// repaint has nothing to collide with — the smeared-overlap class is gone at its source.
|
|
365
|
+
try {
|
|
366
|
+
child.terminal.resize(c, Math.max(1, r - 1))
|
|
367
|
+
child.terminal.resize(c, r)
|
|
368
|
+
} catch {
|
|
369
|
+
/* transient */
|
|
369
370
|
}
|
|
370
371
|
}
|
|
371
372
|
// Restore the serve geometry when the last client detaches, so the unattached session never sticks at
|