nightralph 0.0.9 → 0.0.11

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.
@@ -1,298 +0,0 @@
1
- // src/display.ts
2
- var ESC = "\x1B[";
3
- var ansi = {
4
- cursorUp(n) {
5
- return `${ESC}${n}A`;
6
- },
7
- cursorTo(col) {
8
- return `${ESC}${col}G`;
9
- },
10
- eraseLine() {
11
- return `${ESC}2K`;
12
- },
13
- eraseLines(n) {
14
- let out = "";
15
- for (let i = 0; i < n; i++) {
16
- out += ansi.eraseLine();
17
- if (i < n - 1) out += ansi.cursorUp(1);
18
- }
19
- return out;
20
- },
21
- cursorHide() {
22
- return `${ESC}?25l`;
23
- },
24
- cursorShow() {
25
- return `${ESC}?25h`;
26
- }
27
- };
28
- var color = {
29
- green(text) {
30
- return `${ESC}32m${text}${ESC}0m`;
31
- },
32
- yellow(text) {
33
- return `${ESC}33m${text}${ESC}0m`;
34
- },
35
- red(text) {
36
- return `${ESC}31m${text}${ESC}0m`;
37
- },
38
- dim(text) {
39
- return `${ESC}2m${text}${ESC}0m`;
40
- }
41
- };
42
- var FILLED_DOT = "\u25CF";
43
- var EMPTY_DOT = "\u25CB";
44
- function renderDot(status) {
45
- switch (status) {
46
- case "pending":
47
- return color.dim(EMPTY_DOT);
48
- case "in-progress":
49
- return color.yellow(FILLED_DOT);
50
- case "done":
51
- return color.green(FILLED_DOT);
52
- case "failed":
53
- return color.red(FILLED_DOT);
54
- }
55
- }
56
- var StatusDisplay = class {
57
- wave = null;
58
- messages = [];
59
- renderedLines = 0;
60
- config;
61
- viewportStart = 0;
62
- resizeListener = null;
63
- signalHandler = null;
64
- constructor(config) {
65
- this.config = {
66
- messageLines: config?.messageLines ?? 4,
67
- stream: config?.stream ?? process.stdout
68
- };
69
- }
70
- getAvailableRows() {
71
- const termHeight = this.config.stream.rows ?? 24;
72
- const overhead = 2 + this.config.messageLines;
73
- const available = termHeight - overhead;
74
- return Math.max(1, available);
75
- }
76
- startWave(waveNum, totalWaves, tickets2) {
77
- this.wave = {
78
- waveNum,
79
- totalWaves,
80
- tickets: tickets2.map((t) => ({
81
- ...t,
82
- status: "pending"
83
- }))
84
- };
85
- this.messages = [];
86
- this.viewportStart = 0;
87
- this.config.stream.write(ansi.cursorHide());
88
- if (this.config.stream.isTTY) {
89
- if (this.resizeListener) {
90
- this.config.stream.removeListener(
91
- "resize",
92
- this.resizeListener
93
- );
94
- }
95
- this.resizeListener = () => this.render();
96
- this.config.stream.on(
97
- "resize",
98
- this.resizeListener
99
- );
100
- }
101
- if (this.signalHandler) {
102
- process.removeListener("SIGINT", this.signalHandler);
103
- process.removeListener("SIGTERM", this.signalHandler);
104
- }
105
- this.signalHandler = () => this.cleanup();
106
- process.on("SIGINT", this.signalHandler);
107
- process.on("SIGTERM", this.signalHandler);
108
- this.render();
109
- }
110
- setTicketStatus(num, status) {
111
- if (!this.wave) return;
112
- const ticket = this.wave.tickets.find((t) => t.num === num);
113
- if (ticket) {
114
- ticket.status = status;
115
- if (status === "in-progress") {
116
- const ticketIndex = this.wave.tickets.indexOf(ticket);
117
- const availableRows = this.getAvailableRows();
118
- const totalTickets = this.wave.tickets.length;
119
- if (ticketIndex < this.viewportStart) {
120
- this.viewportStart = ticketIndex;
121
- } else if (ticketIndex >= this.viewportStart + availableRows) {
122
- this.viewportStart = ticketIndex - availableRows + 3;
123
- }
124
- this.viewportStart = Math.max(
125
- 0,
126
- Math.min(
127
- this.viewportStart,
128
- totalTickets - 1
129
- )
130
- );
131
- }
132
- this.render();
133
- }
134
- }
135
- log(message) {
136
- this.messages.push(message);
137
- if (this.messages.length > this.config.messageLines) {
138
- this.messages.shift();
139
- }
140
- this.render();
141
- }
142
- cleanup() {
143
- if (this.resizeListener && this.config.stream.isTTY) {
144
- this.config.stream.removeListener("resize", this.resizeListener);
145
- }
146
- if (this.signalHandler) {
147
- process.removeListener("SIGINT", this.signalHandler);
148
- process.removeListener("SIGTERM", this.signalHandler);
149
- }
150
- this.config.stream.write(ansi.cursorShow());
151
- }
152
- render() {
153
- if (!this.wave) return;
154
- let output = "";
155
- if (this.renderedLines > 0) {
156
- output += ansi.eraseLines(this.renderedLines + 1);
157
- }
158
- const completed = this.wave.tickets.filter(
159
- (t) => t.status === "done"
160
- ).length;
161
- const total = this.wave.tickets.length;
162
- const pct = total === 0 ? 0 : Math.round(completed / total * 100);
163
- output += `Wave ${this.wave.waveNum}/${this.wave.totalWaves} -- ${pct}% complete
164
- `;
165
- const availableRows = this.getAvailableRows();
166
- const tickets2 = this.wave.tickets;
167
- let renderedTicketCount = 0;
168
- if (tickets2.length <= availableRows) {
169
- for (const ticket of tickets2) {
170
- const dot = renderDot(ticket.status);
171
- output += `${dot} ${ticket.filename}
172
- `;
173
- }
174
- renderedTicketCount = tickets2.length;
175
- } else {
176
- this.viewportStart = Math.max(
177
- 0,
178
- Math.min(
179
- this.viewportStart,
180
- tickets2.length - 1
181
- )
182
- );
183
- let hasMoreAbove = this.viewportStart > 0;
184
- let tentativeCount = availableRows - (hasMoreAbove ? 1 : 0);
185
- let hasMoreBelow = this.viewportStart + tentativeCount < tickets2.length;
186
- let ticketsToShow = Math.max(
187
- 0,
188
- tentativeCount - (hasMoreBelow ? 1 : 0)
189
- );
190
- const maxStart = Math.max(
191
- 0,
192
- tickets2.length - Math.max(1, ticketsToShow)
193
- );
194
- if (this.viewportStart > maxStart) {
195
- this.viewportStart = maxStart;
196
- hasMoreAbove = this.viewportStart > 0;
197
- tentativeCount = availableRows - (hasMoreAbove ? 1 : 0);
198
- hasMoreBelow = this.viewportStart + tentativeCount < tickets2.length;
199
- ticketsToShow = Math.max(
200
- 0,
201
- tentativeCount - (hasMoreBelow ? 1 : 0)
202
- );
203
- }
204
- if (hasMoreAbove) {
205
- const moreCount = this.viewportStart;
206
- output += ` ... ${moreCount} more above
207
- `;
208
- }
209
- const visibleTickets = tickets2.slice(
210
- this.viewportStart,
211
- this.viewportStart + ticketsToShow
212
- );
213
- for (const ticket of visibleTickets) {
214
- const dot = renderDot(ticket.status);
215
- output += `${dot} ${ticket.filename}
216
- `;
217
- }
218
- if (hasMoreBelow) {
219
- const moreCount = tickets2.length - (this.viewportStart + ticketsToShow);
220
- output += ` ... ${moreCount} more below
221
- `;
222
- }
223
- renderedTicketCount = (hasMoreAbove ? 1 : 0) + visibleTickets.length + (hasMoreBelow ? 1 : 0);
224
- }
225
- output += "-".repeat(50) + "\n";
226
- const msgLines = Math.max(
227
- 0,
228
- this.config.messageLines - this.messages.length
229
- );
230
- for (const msg of this.messages) {
231
- output += `${msg}
232
- `;
233
- }
234
- for (let i = 0; i < msgLines; i++) {
235
- output += "\n";
236
- }
237
- this.renderedLines = 2 + renderedTicketCount + this.config.messageLines;
238
- this.config.stream.write(output);
239
- }
240
- };
241
-
242
- // demo-display.ts
243
- function sleep(ms) {
244
- return new Promise((r) => setTimeout(r, ms));
245
- }
246
- var tickets = [
247
- { num: 1, filename: "001-add-login-page.md" },
248
- { num: 2, filename: "002-fix-header-alignment.md" },
249
- { num: 3, filename: "003-refactor-auth-module.md" },
250
- { num: 4, filename: "004-update-dependencies.md" },
251
- { num: 5, filename: "005-add-dark-mode.md" },
252
- { num: 6, filename: "006-improve-error-messages.md" },
253
- { num: 7, filename: "007-add-search-feature.md" },
254
- { num: 8, filename: "008-optimize-queries.md" }
255
- ];
256
- async function main() {
257
- const display = new StatusDisplay();
258
- const wave1 = tickets.slice(0, 4);
259
- display.startWave(1, 3, wave1);
260
- display.log("Starting wave 1...");
261
- for (const t of wave1) {
262
- await sleep(600);
263
- display.setTicketStatus(t.num, "in-progress");
264
- display.log(`Agent working on ${t.filename}`);
265
- await sleep(1200);
266
- const status = t.num === 3 ? "failed" : "done";
267
- display.setTicketStatus(t.num, status);
268
- display.log(
269
- status === "done" ? `Completed ${t.filename}` : `Failed ${t.filename}`
270
- );
271
- }
272
- await sleep(1e3);
273
- const wave2 = tickets.slice(4, 7);
274
- display.startWave(2, 3, wave2);
275
- display.log("Starting wave 2...");
276
- for (const t of wave2) {
277
- await sleep(600);
278
- display.setTicketStatus(t.num, "in-progress");
279
- display.log(`Agent working on ${t.filename}`);
280
- await sleep(1e3);
281
- display.setTicketStatus(t.num, "done");
282
- display.log(`Completed ${t.filename}`);
283
- }
284
- await sleep(1e3);
285
- const wave3 = tickets.slice(7);
286
- display.startWave(3, 3, wave3);
287
- display.log("Starting wave 3...");
288
- await sleep(600);
289
- display.setTicketStatus(8, "in-progress");
290
- display.log("Agent working on 008-optimize-queries.md");
291
- await sleep(1500);
292
- display.setTicketStatus(8, "done");
293
- display.log("Completed 008-optimize-queries.md");
294
- await sleep(800);
295
- display.cleanup();
296
- console.log("\nDemo complete.");
297
- }
298
- main();