acuvo-code 0.4.3 → 0.5.0
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/ENTERPRISE.md +1 -1
- package/bin/acuvo.mjs +7 -0
- package/lib/banner.mjs +155 -125
- package/lib/chat.mjs +521 -487
- package/lib/colour.mjs +25 -0
- package/lib/input-box.mjs +58 -0
- package/package.json +1 -1
package/lib/colour.mjs
CHANGED
|
@@ -32,6 +32,21 @@ const CODES = {
|
|
|
32
32
|
green: '\x1b[32m', // it worked
|
|
33
33
|
red: '\x1b[31m', // it failed or was refused
|
|
34
34
|
cyan: '\x1b[36m', // a remote thing: MCP, a service
|
|
35
|
+
/**
|
|
36
|
+
* ── ⭐ THE BRAND GREEN, SAMPLED FROM THE MARK ITSELF ───────────────────────
|
|
37
|
+
*
|
|
38
|
+
* #C8E91E — the most common opaque pixel in
|
|
39
|
+
* `console/public/brand/acuvo-mark.png`, read rather than eyeballed, so the
|
|
40
|
+
* logo in a terminal is the same green as the one on the website.
|
|
41
|
+
*
|
|
42
|
+
* ⚠️ TRUECOLOR WITH A 256-COLOUR FALLBACK. `ESC[38;2;R;G;Bm` is exact and
|
|
43
|
+
* widely supported (Windows Terminal, iTerm2, kitty, modern VS Code) — but a
|
|
44
|
+
* terminal that does not speak it renders the sequence as LITERAL TEXT across
|
|
45
|
+
* the logo. Index 190 is the nearest lime in the 256-colour cube and is
|
|
46
|
+
* understood almost everywhere, so it ships unless truecolor is advertised.
|
|
47
|
+
*/
|
|
48
|
+
brand: '\x1b[38;5;190m',
|
|
49
|
+
brandTrue: '\x1b[38;2;200;233;30m',
|
|
35
50
|
};
|
|
36
51
|
|
|
37
52
|
/**
|
|
@@ -66,6 +81,16 @@ export function createPainter(enabled = colourEnabled()) {
|
|
|
66
81
|
green: wrap(CODES.green),
|
|
67
82
|
red: wrap(CODES.red),
|
|
68
83
|
cyan: wrap(CODES.cyan),
|
|
84
|
+
/**
|
|
85
|
+
* ⚠️ TRUECOLOR ONLY WHEN THE TERMINAL SAYS SO. `COLORTERM=truecolor` is the
|
|
86
|
+
* signal every emitter uses; without it a 24-bit sequence can print as raw
|
|
87
|
+
* text, which would smear escape codes across the first thing a user sees.
|
|
88
|
+
*/
|
|
89
|
+
brand: wrap(
|
|
90
|
+
(process.env.COLORTERM === 'truecolor' || process.env.COLORTERM === '24bit')
|
|
91
|
+
? CODES.brandTrue
|
|
92
|
+
: CODES.brand,
|
|
93
|
+
),
|
|
69
94
|
};
|
|
70
95
|
}
|
|
71
96
|
|
package/lib/input-box.mjs
CHANGED
|
@@ -349,3 +349,61 @@ export function readBoxedLine({ input, output, history = [], onInterrupt = null,
|
|
|
349
349
|
input.once('end', onEnd);
|
|
350
350
|
});
|
|
351
351
|
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* ── ⭐⭐⭐ PINNING THE BOX TO THE BOTTOM OF THE SCREEN ───────────────────────
|
|
355
|
+
*
|
|
356
|
+
* Roman: *"we need that prompt box stuck down the bottom, it is professional."*
|
|
357
|
+
*
|
|
358
|
+
* A terminal can be told to scroll only PART of itself. `ESC[{top};{bottom}r`
|
|
359
|
+
* sets the scrolling region; everything printed scrolls inside it, and the rows
|
|
360
|
+
* below are left alone. Reserve the last three and the box never moves while
|
|
361
|
+
* output flows past above it.
|
|
362
|
+
*
|
|
363
|
+
* ── ⚠️⚠️ THE PART THAT MUST NEVER BE GOT WRONG ──────────────────────────────
|
|
364
|
+
*
|
|
365
|
+
* A process that exits WITHOUT releasing the region leaves the user with a
|
|
366
|
+
* terminal that scrolls inside a box forever, fixable only by typing `reset`
|
|
367
|
+
* blind. That is the same class of harm as leaving raw mode on, and it must be
|
|
368
|
+
* released on every path out — normal exit, Ctrl-C, SIGTERM, and an uncaught
|
|
369
|
+
* throw. `release()` is idempotent and safe to call from all of them.
|
|
370
|
+
*
|
|
371
|
+
* ⚠️ AND IT IS OPT-IN. A reserved region is a claim on somebody's whole screen;
|
|
372
|
+
* off a TTY, in CI, under a pipe or with ACUVO_NO_PIN=1 it is never set.
|
|
373
|
+
*/
|
|
374
|
+
export function pinRegion(output, { rows = 3, env = process.env } = {}) {
|
|
375
|
+
const height = output?.rows ?? process.stdout?.rows ?? 0;
|
|
376
|
+
const enabled = Boolean(output?.isTTY)
|
|
377
|
+
&& height > rows + 4
|
|
378
|
+
&& String(env.ACUVO_NO_PIN ?? '') !== '1'
|
|
379
|
+
&& String(env.CI ?? '').toLowerCase() !== 'true';
|
|
380
|
+
|
|
381
|
+
if (!enabled) return { enabled: false, release() {}, rows: 0, bottom: 0 };
|
|
382
|
+
|
|
383
|
+
const bottom = height - rows;
|
|
384
|
+
let released = false;
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* ⚠️ THE CURSOR IS PARKED INSIDE THE SCROLL REGION BEFORE ANYTHING PRINTS.
|
|
388
|
+
* Setting a region moves the cursor to home (1,1) on most terminals, so
|
|
389
|
+
* without this the next line of output lands at the TOP of the screen and the
|
|
390
|
+
* transcript reads backwards.
|
|
391
|
+
*/
|
|
392
|
+
output.write(`${CSI}1;${bottom}r${CSI}${bottom};1H`);
|
|
393
|
+
|
|
394
|
+
const release = () => {
|
|
395
|
+
if (released) return;
|
|
396
|
+
released = true;
|
|
397
|
+
/**
|
|
398
|
+
* ⚠️ `ESC[r` WITH NO ARGUMENTS RESETS TO THE FULL SCREEN. Then the cursor is
|
|
399
|
+
* moved below the reserved rows so the shell prompt does not land on top of
|
|
400
|
+
* our box — an exit that leaves the terminal technically correct and
|
|
401
|
+
* visually broken is still a bad exit.
|
|
402
|
+
*/
|
|
403
|
+
try {
|
|
404
|
+
output.write(`${CSI}r${CSI}${height};1H\n`);
|
|
405
|
+
} catch { /* the stream may already be gone on a hard exit */ }
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
return { enabled: true, release, rows, bottom };
|
|
409
|
+
}
|