tui: stabilize transcript scrollback
This commit is contained in:
parent
e2724636d0
commit
fcecbb2eff
@ -50,11 +50,16 @@ export class ChatLog extends Container {
|
|||||||
|
|
||||||
private append(component: Component) {
|
private append(component: Component) {
|
||||||
const wasAtLatest = this.scrollOffset === 0;
|
const wasAtLatest = this.scrollOffset === 0;
|
||||||
|
const previousLineCount = wasAtLatest ? 0 : this.getRenderedLineCount(this.lastRenderWidth);
|
||||||
this.addChild(component);
|
this.addChild(component);
|
||||||
this.pruneOverflow();
|
this.pruneOverflow();
|
||||||
if (wasAtLatest) {
|
if (wasAtLatest) {
|
||||||
this.scrollToLatest();
|
this.scrollToLatest();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
const nextLineCount = this.getRenderedLineCount(this.lastRenderWidth);
|
||||||
|
this.scrollOffset += Math.max(0, nextLineCount - previousLineCount);
|
||||||
|
this.clampScrollOffset();
|
||||||
}
|
}
|
||||||
|
|
||||||
setViewportHeight(height: number | null) {
|
setViewportHeight(height: number | null) {
|
||||||
@ -109,6 +114,7 @@ export class ChatLog extends Container {
|
|||||||
this.toolById.clear();
|
this.toolById.clear();
|
||||||
this.streamingRuns.clear();
|
this.streamingRuns.clear();
|
||||||
this.btwMessage = null;
|
this.btwMessage = null;
|
||||||
|
this.scrollToLatest();
|
||||||
}
|
}
|
||||||
|
|
||||||
addSystem(text: string) {
|
addSystem(text: string) {
|
||||||
|
|||||||
@ -230,6 +230,10 @@ export function resolveInitialTuiAgentId(params: {
|
|||||||
return normalizeAgentId(params.fallbackAgentId);
|
return normalizeAgentId(params.fallbackAgentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isMouseSgrSequence(data: string): boolean {
|
||||||
|
return /^\x1b\[<\d+;\d+;\d+[Mm]$/.test(data);
|
||||||
|
}
|
||||||
|
|
||||||
export function parseMouseWheelEvent(data: string): { direction: "up" | "down"; row: number; col: number } | null {
|
export function parseMouseWheelEvent(data: string): { direction: "up" | "down"; row: number; col: number } | null {
|
||||||
const match = /^\x1b\[<(\d+);(\d+);(\d+)([Mm])$/.exec(data);
|
const match = /^\x1b\[<(\d+);(\d+);(\d+)([Mm])$/.exec(data);
|
||||||
if (!match) {
|
if (!match) {
|
||||||
@ -552,12 +556,15 @@ export async function runTui(opts: TuiOptions) {
|
|||||||
const tui = new TUI(new ProcessTerminal());
|
const tui = new TUI(new ProcessTerminal());
|
||||||
const dedupeBackspace = createBackspaceDeduper();
|
const dedupeBackspace = createBackspaceDeduper();
|
||||||
tui.addInputListener((data) => {
|
tui.addInputListener((data) => {
|
||||||
const mouse = parseMouseWheelEvent(data);
|
if (!isMouseSgrSequence(data)) {
|
||||||
if (!mouse || tui.hasOverlay()) {
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
const mouse = parseMouseWheelEvent(data);
|
||||||
|
if (!mouse || tui.hasOverlay()) {
|
||||||
|
return { consume: true };
|
||||||
|
}
|
||||||
if (mouse.row < chatViewportTop || mouse.row > chatViewportBottom) {
|
if (mouse.row < chatViewportTop || mouse.row > chatViewportBottom) {
|
||||||
return undefined;
|
return { consume: true };
|
||||||
}
|
}
|
||||||
if (mouse.direction === "up") {
|
if (mouse.direction === "up") {
|
||||||
chatLog.scrollLines(3);
|
chatLog.scrollLines(3);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user