@anusornneal/chat-relay 0.11.0 → 0.11.1
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/cli/tui.mjs +14 -5
- package/package.json +1 -1
package/cli/tui.mjs
CHANGED
|
@@ -3,6 +3,10 @@ import { humanizeToolCall } from "../agent/toolcall-summary.mjs";
|
|
|
3
3
|
const ESC = "\x1b[";
|
|
4
4
|
const LABEL_WIDTH = 12;
|
|
5
5
|
const GAP = 3;
|
|
6
|
+
const MIN_FRAME_WIDTH = 60;
|
|
7
|
+
const MAX_FRAME_WIDTH = 179;
|
|
8
|
+
const FRAME_FIXED_ROWS = 11;
|
|
9
|
+
const FRAME_BOTTOM_MARGIN = 1;
|
|
6
10
|
|
|
7
11
|
function clamp(value, min, max) {
|
|
8
12
|
return Math.max(min, Math.min(max, value));
|
|
@@ -22,7 +26,7 @@ function field(label, value, width) {
|
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
export function formatTwoColumnHeader(state, width = 110) {
|
|
25
|
-
const usable = clamp(Number(width) || 110,
|
|
29
|
+
const usable = clamp(Number(width) || 110, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH);
|
|
26
30
|
const leftWidth = Math.floor((usable - GAP) / 2);
|
|
27
31
|
const rightWidth = usable - GAP - leftWidth;
|
|
28
32
|
const rows = [
|
|
@@ -117,7 +121,9 @@ export class RemoteTui {
|
|
|
117
121
|
|
|
118
122
|
start() {
|
|
119
123
|
if (this.closed) return;
|
|
120
|
-
|
|
124
|
+
// Use the terminal's alternate screen so periodic redraws never accumulate
|
|
125
|
+
// in scrollback. Keep one column unused to avoid automatic line wrapping.
|
|
126
|
+
this.output.write(ESC + "?1049h" + ESC + "?25l" + ESC + "2J" + ESC + "H");
|
|
121
127
|
this.render();
|
|
122
128
|
this.timer = setInterval(() => this.render(), 1000);
|
|
123
129
|
this.timer.unref?.();
|
|
@@ -128,7 +134,7 @@ export class RemoteTui {
|
|
|
128
134
|
this.closed = true;
|
|
129
135
|
if (this.timer) clearInterval(this.timer);
|
|
130
136
|
this.timer = null;
|
|
131
|
-
this.output.write(ESC + "?25h
|
|
137
|
+
this.output.write(ESC + "?25h" + ESC + "?1049l");
|
|
132
138
|
}
|
|
133
139
|
|
|
134
140
|
handleMessage(message) {
|
|
@@ -178,14 +184,17 @@ export class RemoteTui {
|
|
|
178
184
|
|
|
179
185
|
render() {
|
|
180
186
|
if (this.closed) return;
|
|
181
|
-
const
|
|
187
|
+
const terminalWidth = Number(this.output.columns) || 110;
|
|
188
|
+
const width = clamp(terminalWidth - 1, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH);
|
|
182
189
|
const height = Math.max(16, Number(this.output.rows) || 30);
|
|
183
190
|
const separator = "─".repeat(width);
|
|
184
191
|
const header = formatTwoColumnHeader({
|
|
185
192
|
...this.state,
|
|
186
193
|
uptimeMs: Date.now() - this.startedAt,
|
|
187
194
|
}, width);
|
|
188
|
-
|
|
195
|
+
// Fixed frame content occupies 11 rows. Leave one spare row at the
|
|
196
|
+
// bottom so Windows Terminal never scrolls the screen while repainting.
|
|
197
|
+
const availableRows = Math.max(1, height - FRAME_FIXED_ROWS - FRAME_BOTTOM_MARGIN);
|
|
189
198
|
const rows = this.transactions.slice(-availableRows).map((item) => formatTransactionRow(item, width));
|
|
190
199
|
while (rows.length < Math.min(availableRows, 4)) rows.unshift("");
|
|
191
200
|
|
package/package.json
CHANGED