quotacap 0.0.41 → 0.0.43
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/dist/adapters/claude.js +16 -5
- package/dist/adapters/codex.d.ts +2 -1
- package/dist/adapters/codex.js +19 -8
- package/dist/adapters/goldens.d.ts +4 -0
- package/dist/adapters/goldens.js +20 -0
- package/dist/adapters/grok.d.ts +2 -1
- package/dist/adapters/grok.js +26 -12
- package/dist/adapters/index.d.ts +20 -6
- package/dist/adapters/index.js +96 -37
- package/dist/adapters/kimi.d.ts +2 -1
- package/dist/adapters/kimi.js +24 -13
- package/dist/adapters/muse.d.ts +2 -1
- package/dist/adapters/muse.js +30 -15
- package/dist/adapters/opencode-go.d.ts +1 -1
- package/dist/adapters/opencode-go.js +8 -1
- package/dist/adapters/pty.d.ts +7 -0
- package/dist/adapters/pty.js +32 -2
- package/dist/adapters/vt.d.ts +19 -0
- package/dist/adapters/vt.js +506 -0
- package/dist/cli/providers.js +2 -1
- package/dist/config.d.ts +12 -23
- package/dist/config.js +24 -0
- package/dist/diagnostics/bundle.d.ts +22 -0
- package/dist/diagnostics/bundle.js +125 -0
- package/dist/diagnostics/failure.d.ts +8 -1
- package/dist/diagnostics/failure.js +43 -2
- package/dist/format/rows.d.ts +1 -1
- package/dist/format/rows.js +9 -6
- package/dist/mcp/server.d.ts +2 -2
- package/dist/runtime/poll.d.ts +4 -0
- package/dist/runtime/poll.js +30 -1
- package/dist/runtime/service.js +3 -1
- package/dist/version.js +1 -1
- package/dist/web/src/App.js +1 -1
- package/dist/web/src/components/AdviceDrawer.js +1 -1
- package/dist/web/src/components/OpencodeGoBanner.d.ts +1 -1
- package/dist/web/src/components/OpencodeGoBanner.js +9 -2
- package/dist/web/src/components/PaceBar.d.ts +9 -4
- package/dist/web/src/components/PaceBar.js +26 -7
- package/dist/web/src/components/ProviderCard.js +2 -3
- package/dist/web/src/components/ProviderDrawer.js +3 -3
- package/dist/web/src/components/ProviderIcon.js +1 -1
- package/dist/web/src/components/ProviderRow.d.ts +1 -1
- package/dist/web/src/components/ProviderRow.js +2 -4
- package/dist/web/src/components/Recommendation.js +1 -1
- package/dist/web/src/components/ResetRail.js +1 -1
- package/dist/web/src/components/WindowsRow.d.ts +1 -1
- package/dist/web/src/components/WindowsRow.js +4 -4
- package/dist/web/src/components/settings/SettingsDrawer.js +1 -1
- package/dist/webAssets.js +1 -1
- package/dist/webHtml.js +1 -1
- package/package.json +5 -5
- package/web/dist/assets/{index-Dk6l5h27.css → index-C6ltEeGL.css} +1 -1
- package/web/dist/assets/index-DRDDTtxF.js +13 -0
- package/web/dist/index.html +2 -2
- package/web/dist/assets/index-BUK8xUHm.js +0 -12
package/dist/adapters/pty.d.ts
CHANGED
|
@@ -22,6 +22,13 @@ export interface PtyRunOptions {
|
|
|
22
22
|
*/
|
|
23
23
|
submitInput?: string;
|
|
24
24
|
submitAfterMs?: number;
|
|
25
|
+
/**
|
|
26
|
+
* Grace delay after the completion pattern first matches, before the
|
|
27
|
+
* child is killed. Usage dialogs paint asynchronously (header first,
|
|
28
|
+
* timestamp later); without this the kill can land mid-paint. Bounded
|
|
29
|
+
* and fixed (not quiescence-detected: spinners never settle). Default 400.
|
|
30
|
+
*/
|
|
31
|
+
completionSettleMs?: number;
|
|
25
32
|
/**
|
|
26
33
|
* Opt-in terminal-query responder: answers DSR, DA1 and OSC 4/10/11
|
|
27
34
|
* capability queries the child emits. Off by default; TUIs that never
|
package/dist/adapters/pty.js
CHANGED
|
@@ -222,6 +222,9 @@ async function runPtyBun(opts) {
|
|
|
222
222
|
let transcript = "";
|
|
223
223
|
let exited = false;
|
|
224
224
|
let exitCode;
|
|
225
|
+
const startedAt = Date.now();
|
|
226
|
+
const marks = { start: 0 };
|
|
227
|
+
const mark = (k) => { marks[k] = Date.now() - startedAt; };
|
|
225
228
|
// Genuine PTY via the Bun.spawn `terminal` option (verified on Bun 1.3.11):
|
|
226
229
|
// the child's stdin, stdout, and stderr are all the PTY slave, input goes
|
|
227
230
|
// through proc.terminal.write, and merged output arrives in `data`.
|
|
@@ -435,9 +438,11 @@ async function runPtyBun(opts) {
|
|
|
435
438
|
});
|
|
436
439
|
}
|
|
437
440
|
}
|
|
441
|
+
mark("input");
|
|
438
442
|
if (opts.completionRegex) {
|
|
439
443
|
const deadline = Date.now() + opts.timeoutMs;
|
|
440
444
|
let done = false;
|
|
445
|
+
let matched = false;
|
|
441
446
|
while (Date.now() < deadline) {
|
|
442
447
|
checkCap();
|
|
443
448
|
checkAborted();
|
|
@@ -445,6 +450,8 @@ async function runPtyBun(opts) {
|
|
|
445
450
|
checkAbort(clean);
|
|
446
451
|
if (regexTest(opts.completionRegex, clean)) {
|
|
447
452
|
done = true;
|
|
453
|
+
matched = true;
|
|
454
|
+
mark("completion");
|
|
448
455
|
break;
|
|
449
456
|
}
|
|
450
457
|
if (exited) {
|
|
@@ -468,8 +475,15 @@ async function runPtyBun(opts) {
|
|
|
468
475
|
checkpoint: "completion timeout",
|
|
469
476
|
durationMs: opts.timeoutMs,
|
|
470
477
|
stdout: transcript,
|
|
478
|
+
timings: { ...marks, completion: Date.now() - startedAt },
|
|
471
479
|
});
|
|
472
480
|
}
|
|
481
|
+
if (matched && !exited) {
|
|
482
|
+
await delay(opts.completionSettleMs ?? 400);
|
|
483
|
+
checkCap();
|
|
484
|
+
checkAborted();
|
|
485
|
+
checkAbort(stripAnsi(transcript));
|
|
486
|
+
}
|
|
473
487
|
}
|
|
474
488
|
else {
|
|
475
489
|
const deadline = Date.now() + opts.timeoutMs;
|
|
@@ -513,7 +527,8 @@ async function runPtyBun(opts) {
|
|
|
513
527
|
teardownAbort();
|
|
514
528
|
if (e instanceof DiagnosticError)
|
|
515
529
|
throw e;
|
|
516
|
-
|
|
530
|
+
mark("end");
|
|
531
|
+
throw diagnosticError(e, { source: "pty", stdout: transcript, exitCode, timings: { ...marks } });
|
|
517
532
|
}
|
|
518
533
|
}
|
|
519
534
|
async function runPtyNode(opts) {
|
|
@@ -542,6 +557,9 @@ async function runPtyNode(opts) {
|
|
|
542
557
|
let transcript = "";
|
|
543
558
|
let exited = false;
|
|
544
559
|
let exitCode;
|
|
560
|
+
const startedAt = Date.now();
|
|
561
|
+
const marks = { start: 0 };
|
|
562
|
+
const mark = (k) => { marks[k] = Date.now() - startedAt; };
|
|
545
563
|
const pty = getPty();
|
|
546
564
|
let ptyProcess;
|
|
547
565
|
try {
|
|
@@ -747,9 +765,11 @@ async function runPtyNode(opts) {
|
|
|
747
765
|
});
|
|
748
766
|
}
|
|
749
767
|
}
|
|
768
|
+
mark("input");
|
|
750
769
|
if (opts.completionRegex) {
|
|
751
770
|
const deadline = Date.now() + opts.timeoutMs;
|
|
752
771
|
let done = false;
|
|
772
|
+
let matched = false;
|
|
753
773
|
while (Date.now() < deadline) {
|
|
754
774
|
checkCap();
|
|
755
775
|
checkAborted();
|
|
@@ -757,6 +777,8 @@ async function runPtyNode(opts) {
|
|
|
757
777
|
checkAbort(clean);
|
|
758
778
|
if (regexTest(opts.completionRegex, clean)) {
|
|
759
779
|
done = true;
|
|
780
|
+
matched = true;
|
|
781
|
+
mark("completion");
|
|
760
782
|
break;
|
|
761
783
|
}
|
|
762
784
|
if (exited) {
|
|
@@ -780,8 +802,15 @@ async function runPtyNode(opts) {
|
|
|
780
802
|
checkpoint: "completion timeout",
|
|
781
803
|
durationMs: opts.timeoutMs,
|
|
782
804
|
stdout: transcript,
|
|
805
|
+
timings: { ...marks, completion: Date.now() - startedAt },
|
|
783
806
|
});
|
|
784
807
|
}
|
|
808
|
+
if (matched && !exited) {
|
|
809
|
+
await delay(opts.completionSettleMs ?? 400);
|
|
810
|
+
checkCap();
|
|
811
|
+
checkAborted();
|
|
812
|
+
checkAbort(stripAnsi(transcript));
|
|
813
|
+
}
|
|
785
814
|
}
|
|
786
815
|
else {
|
|
787
816
|
const deadline = Date.now() + opts.timeoutMs;
|
|
@@ -808,7 +837,8 @@ async function runPtyNode(opts) {
|
|
|
808
837
|
await kill();
|
|
809
838
|
if (e instanceof DiagnosticError)
|
|
810
839
|
throw e;
|
|
811
|
-
|
|
840
|
+
mark("end");
|
|
841
|
+
throw diagnosticError(e, { source: "pty", stdout: transcript, exitCode, timings: { ...marks } });
|
|
812
842
|
}
|
|
813
843
|
finally {
|
|
814
844
|
cleanup();
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ParsedQuota } from "./types.js";
|
|
2
|
+
export interface GridDims {
|
|
3
|
+
cols: number;
|
|
4
|
+
rows: number;
|
|
5
|
+
}
|
|
6
|
+
export declare const DEFAULT_GRID_DIMS: GridDims;
|
|
7
|
+
export declare function cellWidth(cp: number): 0 | 1 | 2;
|
|
8
|
+
/** Render the final visible screen of a PTY transcript. */
|
|
9
|
+
export declare function renderScreen(transcript: string, dims?: Partial<GridDims>): string;
|
|
10
|
+
/**
|
|
11
|
+
* Screen-first parsing with byte-soup fallback. The rendered screen is
|
|
12
|
+
* precise (overwrite artifacts resolved) but lossy in one case: a TUI that
|
|
13
|
+
* leaves alt-screen and clears on kill wipes the dialog the transcript
|
|
14
|
+
* captured earlier (observed: grok prints a resume line on exit). The
|
|
15
|
+
* cumulative soup never loses content but keeps cursor artifacts. So: parse
|
|
16
|
+
* the screen; on throw, or on an estimated reset the soup resolves exactly,
|
|
17
|
+
* parse the soup instead. Worst case equals the old soup-only behavior.
|
|
18
|
+
*/
|
|
19
|
+
export declare function parseScreens(text: string, dims: Partial<GridDims> | undefined, parse: (cleaned: string) => ParsedQuota): ParsedQuota;
|
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
// Minimal VT100/xterm screen renderer: replays a PTY transcript onto a
|
|
2
|
+
// cols×rows grid and returns the visible screen text. Cursor-addressed TUIs
|
|
3
|
+
// write fragments out of order ("Weekly lim" + CUP + "t (Tier)"); regexing
|
|
4
|
+
// the raw byte stream sees "Weekly limt", but the screen shows the truth.
|
|
5
|
+
// Parsing the rendered screen kills that whole artifact class (the 2026-09-28
|
|
6
|
+
// "Resets: October5, 10:22" grok failure was a cursor step over a blank cell,
|
|
7
|
+
// which the screen shows as a space and the byte stream drops entirely).
|
|
8
|
+
//
|
|
9
|
+
// Supported: CUP/HVP, CUU/CUD/CUF/CUB/CNL/CPL/CHA/VPA, ED, EL, IL/DL, DCH/ECH,
|
|
10
|
+
// SU/SD, DECSTBM scroll regions, SGR (ignored), alt-screen enter (clears),
|
|
11
|
+
// save/restore cursor (CSI s/u and DECSC/DECRC), RI/IND/NEL/HT/BS/CR/LF,
|
|
12
|
+
// OSC skip, RIS. Unknown sequences are ignored, never fatal.
|
|
13
|
+
import { stripAnsi } from "./pty.js";
|
|
14
|
+
export const DEFAULT_GRID_DIMS = { cols: 140, rows: 50 };
|
|
15
|
+
// Approximate wcwidth: 0 for combining/format marks, 2 for wide ranges,
|
|
16
|
+
// 1 otherwise. Box drawing (U+2500-257F) and braille (U+2800-28FF) are
|
|
17
|
+
// width 1, which the fast path below gets right.
|
|
18
|
+
const ZERO_WIDTH = [
|
|
19
|
+
[0x0300, 0x036f],
|
|
20
|
+
[0x0488, 0x0489],
|
|
21
|
+
[0x0591, 0x05bd],
|
|
22
|
+
[0x05bf, 0x05bf],
|
|
23
|
+
[0x05c1, 0x05c2],
|
|
24
|
+
[0x05c4, 0x05c5],
|
|
25
|
+
[0x05c7, 0x05c7],
|
|
26
|
+
[0x0610, 0x0617],
|
|
27
|
+
[0x064b, 0x065b],
|
|
28
|
+
[0x0670, 0x0670],
|
|
29
|
+
[0x06d6, 0x06dc],
|
|
30
|
+
[0x200b, 0x200f],
|
|
31
|
+
[0x2028, 0x202e],
|
|
32
|
+
[0xfe00, 0xfe0f],
|
|
33
|
+
[0xfe20, 0xfe2f],
|
|
34
|
+
[0xe0100, 0xe01ef],
|
|
35
|
+
];
|
|
36
|
+
const WIDE = [
|
|
37
|
+
[0x1100, 0x115f],
|
|
38
|
+
[0x231a, 0x231b],
|
|
39
|
+
[0x2329, 0x232a],
|
|
40
|
+
[0x23e9, 0x23ec],
|
|
41
|
+
[0x23f0, 0x23f0],
|
|
42
|
+
[0x23f3, 0x23f3],
|
|
43
|
+
[0x25fd, 0x25fe],
|
|
44
|
+
[0x2614, 0x2615],
|
|
45
|
+
[0x2648, 0x2653],
|
|
46
|
+
[0x267f, 0x267f],
|
|
47
|
+
[0x2693, 0x2693],
|
|
48
|
+
[0x26a1, 0x26a1],
|
|
49
|
+
[0x26aa, 0x26ab],
|
|
50
|
+
[0x26bd, 0x26be],
|
|
51
|
+
[0x26c4, 0x26c5],
|
|
52
|
+
[0x26ce, 0x26ce],
|
|
53
|
+
[0x26ea, 0x26ea],
|
|
54
|
+
[0x26f2, 0x26f3],
|
|
55
|
+
[0x26f5, 0x26f5],
|
|
56
|
+
[0x26fa, 0x26fa],
|
|
57
|
+
[0x2705, 0x2705],
|
|
58
|
+
[0x270a, 0x270b],
|
|
59
|
+
[0x2728, 0x2728],
|
|
60
|
+
[0x274c, 0x274c],
|
|
61
|
+
[0x274e, 0x274e],
|
|
62
|
+
[0x2753, 0x2755],
|
|
63
|
+
[0x2757, 0x2757],
|
|
64
|
+
[0x2795, 0x2797],
|
|
65
|
+
[0x27b0, 0x27b0],
|
|
66
|
+
[0x27bf, 0x27bf],
|
|
67
|
+
[0x2b1b, 0x2b1c],
|
|
68
|
+
[0x2b50, 0x2b50],
|
|
69
|
+
[0x2b55, 0x2b55],
|
|
70
|
+
[0x2e80, 0x303e],
|
|
71
|
+
[0x3041, 0x33ff],
|
|
72
|
+
[0x3400, 0x4dbf],
|
|
73
|
+
[0x4e00, 0x9fff],
|
|
74
|
+
[0xa000, 0xa4cf],
|
|
75
|
+
[0xac00, 0xd7a3],
|
|
76
|
+
[0xf900, 0xfaff],
|
|
77
|
+
[0xfe10, 0xfe19],
|
|
78
|
+
[0xfe30, 0xfe52],
|
|
79
|
+
[0xfe54, 0xfe66],
|
|
80
|
+
[0xfe68, 0xfe6b],
|
|
81
|
+
[0xff00, 0xff60],
|
|
82
|
+
[0xffe0, 0xffe6],
|
|
83
|
+
[0x16fe0, 0x16fe3],
|
|
84
|
+
[0x17000, 0x187ec],
|
|
85
|
+
[0x18800, 0x18af2],
|
|
86
|
+
[0x1b000, 0x1b001],
|
|
87
|
+
[0x1f004, 0x1f004],
|
|
88
|
+
[0x1f0cf, 0x1f0ff],
|
|
89
|
+
[0x1f18e, 0x1f251],
|
|
90
|
+
[0x1f300, 0x1f5ff],
|
|
91
|
+
[0x1f600, 0x1f64f],
|
|
92
|
+
[0x1f680, 0x1f6ff],
|
|
93
|
+
[0x1f900, 0x1f9ff],
|
|
94
|
+
[0x20000, 0x2fffd],
|
|
95
|
+
[0x30000, 0x3fffd],
|
|
96
|
+
];
|
|
97
|
+
function inRanges(ranges, cp) {
|
|
98
|
+
let lo = 0;
|
|
99
|
+
let hi = ranges.length - 1;
|
|
100
|
+
while (lo <= hi) {
|
|
101
|
+
const mid = (lo + hi) >> 1;
|
|
102
|
+
const [a, b] = ranges[mid];
|
|
103
|
+
if (cp < a)
|
|
104
|
+
hi = mid - 1;
|
|
105
|
+
else if (cp > b)
|
|
106
|
+
lo = mid + 1;
|
|
107
|
+
else
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
export function cellWidth(cp) {
|
|
113
|
+
if (cp < 0x0300 || (cp > 0xe01ef))
|
|
114
|
+
return 1;
|
|
115
|
+
if (cp < 0x1100)
|
|
116
|
+
return inRanges(ZERO_WIDTH, cp) ? 0 : 1;
|
|
117
|
+
if (inRanges(ZERO_WIDTH, cp))
|
|
118
|
+
return 0;
|
|
119
|
+
return inRanges(WIDE, cp) ? 2 : 1;
|
|
120
|
+
}
|
|
121
|
+
function blankRow(cols) {
|
|
122
|
+
return new Array(cols).fill(" ");
|
|
123
|
+
}
|
|
124
|
+
function parseParams(body) {
|
|
125
|
+
const priv = body.startsWith("?") || body.startsWith(">");
|
|
126
|
+
const nums = body
|
|
127
|
+
.replace(/^[?><=]/, "")
|
|
128
|
+
.split(";")
|
|
129
|
+
.map((p) => {
|
|
130
|
+
const n = parseInt(p, 10);
|
|
131
|
+
return Number.isFinite(n) ? n : 0;
|
|
132
|
+
});
|
|
133
|
+
return { nums, private: priv };
|
|
134
|
+
}
|
|
135
|
+
/** Render the final visible screen of a PTY transcript. */
|
|
136
|
+
export function renderScreen(transcript, dims) {
|
|
137
|
+
const cols = Math.max(1, dims?.cols ?? DEFAULT_GRID_DIMS.cols);
|
|
138
|
+
const rows = Math.max(1, dims?.rows ?? DEFAULT_GRID_DIMS.rows);
|
|
139
|
+
const grid = [];
|
|
140
|
+
for (let r = 0; r < rows; r++)
|
|
141
|
+
grid.push(blankRow(cols));
|
|
142
|
+
let x = 0;
|
|
143
|
+
let y = 0;
|
|
144
|
+
let savedX = 0;
|
|
145
|
+
let savedY = 0;
|
|
146
|
+
let scrollTop = 0;
|
|
147
|
+
let scrollBottom = rows - 1;
|
|
148
|
+
const clearAll = () => {
|
|
149
|
+
for (let r = 0; r < rows; r++)
|
|
150
|
+
grid[r] = blankRow(cols);
|
|
151
|
+
};
|
|
152
|
+
const scrollUp = (n) => {
|
|
153
|
+
for (let i = 0; i < n; i++) {
|
|
154
|
+
grid.splice(scrollTop, 1);
|
|
155
|
+
grid.splice(scrollBottom, 0, blankRow(cols));
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
const scrollDown = (n) => {
|
|
159
|
+
for (let i = 0; i < n; i++) {
|
|
160
|
+
grid.splice(scrollBottom, 1);
|
|
161
|
+
grid.splice(scrollTop, 0, blankRow(cols));
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
const lineFeed = () => {
|
|
165
|
+
if (y >= scrollBottom)
|
|
166
|
+
scrollUp(1);
|
|
167
|
+
else
|
|
168
|
+
y++;
|
|
169
|
+
};
|
|
170
|
+
const writeCell = (ch, w) => {
|
|
171
|
+
if (x + w > cols) {
|
|
172
|
+
x = 0;
|
|
173
|
+
lineFeed();
|
|
174
|
+
}
|
|
175
|
+
// A wide char straddling the right margin wraps instead of splitting.
|
|
176
|
+
if (x + w > cols)
|
|
177
|
+
return;
|
|
178
|
+
grid[y][x] = ch;
|
|
179
|
+
if (w === 2 && x + 1 < cols)
|
|
180
|
+
grid[y][x + 1] = null;
|
|
181
|
+
x += w;
|
|
182
|
+
if (x >= cols) {
|
|
183
|
+
x = 0;
|
|
184
|
+
lineFeed();
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
let i = 0;
|
|
188
|
+
const n = transcript.length;
|
|
189
|
+
while (i < n) {
|
|
190
|
+
const c = transcript[i];
|
|
191
|
+
if (c === "\x1b") {
|
|
192
|
+
const next = transcript[i + 1];
|
|
193
|
+
if (next === "[") {
|
|
194
|
+
// CSI: params + intermediates + final byte.
|
|
195
|
+
let j = i + 2;
|
|
196
|
+
while (j < n) {
|
|
197
|
+
const code = transcript.charCodeAt(j);
|
|
198
|
+
if (code >= 0x40 && code <= 0x7e)
|
|
199
|
+
break;
|
|
200
|
+
j++;
|
|
201
|
+
}
|
|
202
|
+
if (j >= n)
|
|
203
|
+
break; // Truncated sequence at kill time: stop.
|
|
204
|
+
const body = transcript.slice(i + 2, j);
|
|
205
|
+
const fin = transcript[j];
|
|
206
|
+
i = j + 1;
|
|
207
|
+
const { nums } = parseParams(body);
|
|
208
|
+
const p1 = nums[0] || 1;
|
|
209
|
+
switch (fin) {
|
|
210
|
+
case "H":
|
|
211
|
+
case "f": {
|
|
212
|
+
const r = (nums[0] || 1) - 1;
|
|
213
|
+
const col = (nums[1] || 1) - 1;
|
|
214
|
+
y = Math.min(rows - 1, Math.max(0, r));
|
|
215
|
+
x = Math.min(cols - 1, Math.max(0, col));
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
case "A":
|
|
219
|
+
y = Math.max(0, y - p1);
|
|
220
|
+
break;
|
|
221
|
+
case "B":
|
|
222
|
+
y = Math.min(rows - 1, y + p1);
|
|
223
|
+
break;
|
|
224
|
+
case "C":
|
|
225
|
+
x = Math.min(cols - 1, x + p1);
|
|
226
|
+
break;
|
|
227
|
+
case "D":
|
|
228
|
+
x = Math.max(0, x - p1);
|
|
229
|
+
break;
|
|
230
|
+
case "E":
|
|
231
|
+
x = 0;
|
|
232
|
+
y = Math.min(rows - 1, y + p1);
|
|
233
|
+
break;
|
|
234
|
+
case "F":
|
|
235
|
+
x = 0;
|
|
236
|
+
y = Math.max(0, y - p1);
|
|
237
|
+
break;
|
|
238
|
+
case "G":
|
|
239
|
+
x = Math.min(cols - 1, Math.max(0, p1 - 1));
|
|
240
|
+
break;
|
|
241
|
+
case "d":
|
|
242
|
+
y = Math.min(rows - 1, Math.max(0, p1 - 1));
|
|
243
|
+
break;
|
|
244
|
+
case "J": {
|
|
245
|
+
const mode = nums[0] || 0;
|
|
246
|
+
if (mode === 2 || mode === 3) {
|
|
247
|
+
clearAll();
|
|
248
|
+
}
|
|
249
|
+
else if (mode === 1) {
|
|
250
|
+
for (let r = 0; r < y; r++)
|
|
251
|
+
grid[r] = blankRow(cols);
|
|
252
|
+
for (let c0 = 0; c0 <= x && c0 < cols; c0++)
|
|
253
|
+
grid[y][c0] = " ";
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
for (let c0 = x; c0 < cols; c0++)
|
|
257
|
+
grid[y][c0] = " ";
|
|
258
|
+
for (let r = y + 1; r < rows; r++)
|
|
259
|
+
grid[r] = blankRow(cols);
|
|
260
|
+
}
|
|
261
|
+
break;
|
|
262
|
+
}
|
|
263
|
+
case "K": {
|
|
264
|
+
const mode = nums[0] || 0;
|
|
265
|
+
if (mode === 1) {
|
|
266
|
+
for (let c0 = 0; c0 <= x && c0 < cols; c0++)
|
|
267
|
+
grid[y][c0] = " ";
|
|
268
|
+
}
|
|
269
|
+
else if (mode === 2) {
|
|
270
|
+
grid[y] = blankRow(cols);
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
for (let c0 = x; c0 < cols; c0++)
|
|
274
|
+
grid[y][c0] = " ";
|
|
275
|
+
}
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
case "L": {
|
|
279
|
+
// Insert lines at cursor within the scroll region.
|
|
280
|
+
const count = Math.min(p1, scrollBottom - y + 1);
|
|
281
|
+
for (let k = 0; k < count; k++) {
|
|
282
|
+
grid.splice(scrollBottom, 1);
|
|
283
|
+
grid.splice(Math.max(scrollTop, y), 0, blankRow(cols));
|
|
284
|
+
}
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
case "M": {
|
|
288
|
+
// Delete lines at cursor within the scroll region.
|
|
289
|
+
const count = Math.min(p1, scrollBottom - y + 1);
|
|
290
|
+
for (let k = 0; k < count; k++) {
|
|
291
|
+
grid.splice(Math.max(scrollTop, y), 1);
|
|
292
|
+
grid.splice(scrollBottom, 0, blankRow(cols));
|
|
293
|
+
}
|
|
294
|
+
break;
|
|
295
|
+
}
|
|
296
|
+
case "P": {
|
|
297
|
+
// Delete characters at cursor.
|
|
298
|
+
const count = Math.min(p1, cols - x);
|
|
299
|
+
grid[y].splice(x, count);
|
|
300
|
+
while (grid[y].length < cols)
|
|
301
|
+
grid[y].push(" ");
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
case "@": {
|
|
305
|
+
// Insert blank characters at cursor.
|
|
306
|
+
const count = Math.min(p1, cols - x);
|
|
307
|
+
grid[y].splice(x, 0, ...blankRow(count));
|
|
308
|
+
grid[y].length = cols;
|
|
309
|
+
break;
|
|
310
|
+
}
|
|
311
|
+
case "X": {
|
|
312
|
+
// Erase characters at cursor.
|
|
313
|
+
const count = Math.min(p1, cols - x);
|
|
314
|
+
for (let c0 = x; c0 < x + count; c0++)
|
|
315
|
+
grid[y][c0] = " ";
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
case "S":
|
|
319
|
+
scrollUp(Math.min(p1, scrollBottom - scrollTop + 1));
|
|
320
|
+
break;
|
|
321
|
+
case "T":
|
|
322
|
+
scrollDown(Math.min(p1, scrollBottom - scrollTop + 1));
|
|
323
|
+
break;
|
|
324
|
+
case "r": {
|
|
325
|
+
// DECSTBM scroll region (1-based, inclusive).
|
|
326
|
+
const top = Math.max(1, nums[0] || 1);
|
|
327
|
+
const bottom = nums[1] || rows;
|
|
328
|
+
if (top <= bottom && top <= rows) {
|
|
329
|
+
scrollTop = Math.min(rows - 1, top - 1);
|
|
330
|
+
scrollBottom = Math.min(rows - 1, bottom - 1);
|
|
331
|
+
}
|
|
332
|
+
x = 0;
|
|
333
|
+
y = scrollTop;
|
|
334
|
+
break;
|
|
335
|
+
}
|
|
336
|
+
case "s":
|
|
337
|
+
savedX = x;
|
|
338
|
+
savedY = y;
|
|
339
|
+
break;
|
|
340
|
+
case "u":
|
|
341
|
+
x = Math.min(cols - 1, savedX);
|
|
342
|
+
y = Math.min(rows - 1, savedY);
|
|
343
|
+
break;
|
|
344
|
+
case "h":
|
|
345
|
+
case "l": {
|
|
346
|
+
// Alt-screen enter wipes to a fresh buffer; its exit cannot
|
|
347
|
+
// restore the main screen, so it is a no-op. All other private
|
|
348
|
+
// modes (cursor visibility, mouse, sync output) are ignored.
|
|
349
|
+
if (fin === "h" && /(?:^|;)1049(?:;|$)/.test(body.replace(/^[?><=]/, ""))) {
|
|
350
|
+
clearAll();
|
|
351
|
+
x = 0;
|
|
352
|
+
y = 0;
|
|
353
|
+
}
|
|
354
|
+
break;
|
|
355
|
+
}
|
|
356
|
+
default:
|
|
357
|
+
break; // SGR (m), queries (c/n), tabs, colors: no screen effect.
|
|
358
|
+
}
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
if (next === "]") {
|
|
362
|
+
// OSC: skip to BEL or ST.
|
|
363
|
+
let j = i + 2;
|
|
364
|
+
while (j < n) {
|
|
365
|
+
if (transcript[j] === "\x07") {
|
|
366
|
+
j++;
|
|
367
|
+
break;
|
|
368
|
+
}
|
|
369
|
+
if (transcript[j] === "\x1b" && transcript[j + 1] === "\\") {
|
|
370
|
+
j += 2;
|
|
371
|
+
break;
|
|
372
|
+
}
|
|
373
|
+
j++;
|
|
374
|
+
}
|
|
375
|
+
i = j;
|
|
376
|
+
continue;
|
|
377
|
+
}
|
|
378
|
+
if (next === "7") {
|
|
379
|
+
savedX = x;
|
|
380
|
+
savedY = y;
|
|
381
|
+
i += 2;
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
if (next === "8") {
|
|
385
|
+
x = Math.min(cols - 1, savedX);
|
|
386
|
+
y = Math.min(rows - 1, savedY);
|
|
387
|
+
i += 2;
|
|
388
|
+
continue;
|
|
389
|
+
}
|
|
390
|
+
if (next === "M") {
|
|
391
|
+
// Reverse index.
|
|
392
|
+
if (y <= scrollTop)
|
|
393
|
+
scrollDown(1);
|
|
394
|
+
else
|
|
395
|
+
y--;
|
|
396
|
+
i += 2;
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
if (next === "D") {
|
|
400
|
+
lineFeed();
|
|
401
|
+
i += 2;
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
if (next === "E") {
|
|
405
|
+
x = 0;
|
|
406
|
+
lineFeed();
|
|
407
|
+
i += 2;
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
if (next === "c") {
|
|
411
|
+
clearAll();
|
|
412
|
+
x = 0;
|
|
413
|
+
y = 0;
|
|
414
|
+
scrollTop = 0;
|
|
415
|
+
scrollBottom = rows - 1;
|
|
416
|
+
i += 2;
|
|
417
|
+
continue;
|
|
418
|
+
}
|
|
419
|
+
if (next === "(" || next === ")" || next === "#" || next === "=" || next === ">") {
|
|
420
|
+
i += 2; // Charset selects, keypad modes: no screen effect.
|
|
421
|
+
continue;
|
|
422
|
+
}
|
|
423
|
+
// Unknown ESC sequence: skip the introducer, keep scanning.
|
|
424
|
+
i += next === undefined ? 1 : 2;
|
|
425
|
+
continue;
|
|
426
|
+
}
|
|
427
|
+
if (c === "\r") {
|
|
428
|
+
x = 0;
|
|
429
|
+
i++;
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
432
|
+
if (c === "\n") {
|
|
433
|
+
// NEL-style: PTY output carries \r\n (ONLCR) so the \r already ran;
|
|
434
|
+
// plain fixtures carry bare \n and expect a fresh line start.
|
|
435
|
+
x = 0;
|
|
436
|
+
lineFeed();
|
|
437
|
+
i++;
|
|
438
|
+
continue;
|
|
439
|
+
}
|
|
440
|
+
if (c === "\b") {
|
|
441
|
+
x = Math.max(0, x - 1);
|
|
442
|
+
i++;
|
|
443
|
+
continue;
|
|
444
|
+
}
|
|
445
|
+
if (c === "\t") {
|
|
446
|
+
x = Math.min(cols - 1, x + 8 - (x % 8));
|
|
447
|
+
i++;
|
|
448
|
+
continue;
|
|
449
|
+
}
|
|
450
|
+
const code = transcript.charCodeAt(i);
|
|
451
|
+
if (code < 0x20 || code === 0x7f) {
|
|
452
|
+
i++; // Other C0 controls (BEL etc.): no screen effect.
|
|
453
|
+
continue;
|
|
454
|
+
}
|
|
455
|
+
const cp = transcript.codePointAt(i) ?? code;
|
|
456
|
+
const ch = String.fromCodePoint(cp);
|
|
457
|
+
i += ch.length;
|
|
458
|
+
const w = cellWidth(cp);
|
|
459
|
+
if (w === 0)
|
|
460
|
+
continue;
|
|
461
|
+
writeCell(ch, w);
|
|
462
|
+
}
|
|
463
|
+
const lines = [];
|
|
464
|
+
for (const row of grid) {
|
|
465
|
+
let end = row.length;
|
|
466
|
+
while (end > 0 && (row[end - 1] === "" || row[end - 1] === null || row[end - 1] === " "))
|
|
467
|
+
end--;
|
|
468
|
+
lines.push(row.slice(0, end).map((cell) => (cell === null ? "" : cell)).join(""));
|
|
469
|
+
}
|
|
470
|
+
while (lines.length > 0 && lines[lines.length - 1] === "")
|
|
471
|
+
lines.pop();
|
|
472
|
+
return lines.join("\n");
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Screen-first parsing with byte-soup fallback. The rendered screen is
|
|
476
|
+
* precise (overwrite artifacts resolved) but lossy in one case: a TUI that
|
|
477
|
+
* leaves alt-screen and clears on kill wipes the dialog the transcript
|
|
478
|
+
* captured earlier (observed: grok prints a resume line on exit). The
|
|
479
|
+
* cumulative soup never loses content but keeps cursor artifacts. So: parse
|
|
480
|
+
* the screen; on throw, or on an estimated reset the soup resolves exactly,
|
|
481
|
+
* parse the soup instead. Worst case equals the old soup-only behavior.
|
|
482
|
+
*/
|
|
483
|
+
export function parseScreens(text, dims, parse) {
|
|
484
|
+
const screen = renderScreen(text, dims);
|
|
485
|
+
try {
|
|
486
|
+
const first = parse(screen);
|
|
487
|
+
if (!first.resetsAtEstimated)
|
|
488
|
+
return first;
|
|
489
|
+
const soup = stripAnsi(text);
|
|
490
|
+
if (soup === screen)
|
|
491
|
+
return first;
|
|
492
|
+
try {
|
|
493
|
+
const second = parse(soup);
|
|
494
|
+
return second.resetsAtEstimated ? first : second;
|
|
495
|
+
}
|
|
496
|
+
catch {
|
|
497
|
+
return first;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
catch (screenErr) {
|
|
501
|
+
const soup = stripAnsi(text);
|
|
502
|
+
if (soup === screen)
|
|
503
|
+
throw screenErr;
|
|
504
|
+
return parse(soup);
|
|
505
|
+
}
|
|
506
|
+
}
|
package/dist/cli/providers.js
CHANGED
|
@@ -248,7 +248,8 @@ export function registerProvidersCommand(program, deps = {}) {
|
|
|
248
248
|
return;
|
|
249
249
|
}
|
|
250
250
|
}
|
|
251
|
-
console.log(`enabled ${id}
|
|
251
|
+
console.log(`enabled ${id}`);
|
|
252
|
+
console.log("Next: run quotacap service restart to start polling");
|
|
252
253
|
});
|
|
253
254
|
providers
|
|
254
255
|
.command("disable <id>")
|