omniharness-cli 0.1.37 → 0.1.39

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.
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Terminal capability primitives — zero-dependency escape sequences that
3
+ * degrade to nothing on terminals that don't support them.
4
+ *
5
+ * Pure helpers plus two small stateful wrappers (`wrapSynchronizedOutput`,
6
+ * `isSyncOutputReply`). Nothing here assumes a capability: callers probe
7
+ * first (like the kitty-protocol query in `keys.ts`) and only enable a
8
+ * feature once the terminal answers.
9
+ *
10
+ * - Synchronized Output (DECSET 2026): bracket each frame so the terminal
11
+ * composites the whole update at once instead of tearing mid-repaint.
12
+ * - OSC 52: write the system clipboard (works over SSH and tmux). Most
13
+ * terminals allow writes and refuse reads, so this is write-only.
14
+ * - OSC 9: fire a desktop notification when a long run finishes.
15
+ * - BEL: the terminal bell, gated by the caller to "long + unfocused".
16
+ */
17
+ /** DECSET 2026 — begin a synchronized (tear-free) frame. */
18
+ export const SYNC_BEGIN = '\x1b[?2026h';
19
+ /** DECRST 2026 — end the synchronized frame; terminal flushes it atomically. */
20
+ export const SYNC_END = '\x1b[?2026l';
21
+ /** DECRQM 2026 — ask whether synchronized output is supported. */
22
+ export const SYNC_QUERY = '\x1b[?2026$p';
23
+ /**
24
+ * True when `chunk` is the terminal's answer to {@link SYNC_QUERY}
25
+ * (`ESC [ ? 2026 ; <state> $ y`). State 1 = set, 2 = reset, 3/4 = permanently
26
+ * set/reset — any of them means the mode is recognised, which is all we need.
27
+ */
28
+ export function isSyncOutputReply(chunk) {
29
+ return /\x1b\[\?2026;[0-4]\$y/.test(chunk);
30
+ }
31
+ /**
32
+ * Wrap a writable stream so every string write is bracketed by the
33
+ * synchronized-output markers. Ink emits one `write()` per rendered frame, so
34
+ * this makes each frame tear-free without hooking React's commit phase.
35
+ * Returns a restore function. Non-string chunks (rare from Ink) pass through
36
+ * untouched so binary writes are never corrupted.
37
+ */
38
+ export function wrapSynchronizedOutput(stream) {
39
+ const original = stream.write.bind(stream);
40
+ stream.write = (chunk, ...rest) => {
41
+ if (typeof chunk === 'string' && chunk.length > 0) {
42
+ return original(`${SYNC_BEGIN}${chunk}${SYNC_END}`, ...rest);
43
+ }
44
+ return original(chunk, ...rest);
45
+ };
46
+ return () => { stream.write = original; };
47
+ }
48
+ /**
49
+ * OSC 52 clipboard-write sequence for `text`. Base64 is required by the
50
+ * protocol. Terminals cap the payload (commonly ~74–100 KB before the encode);
51
+ * we refuse anything that would obviously exceed that rather than emit a
52
+ * sequence the terminal will silently drop.
53
+ */
54
+ export function osc52Copy(text) {
55
+ const encoded = Buffer.from(text, 'utf8').toString('base64');
56
+ if (encoded.length > 96_000)
57
+ return null;
58
+ return `\x1b]52;c;${encoded}\x07`;
59
+ }
60
+ /** OSC 9 desktop-notification sequence (iTerm2, WezTerm, Ghostty, Windows Terminal). */
61
+ export function osc9Notify(title) {
62
+ // Strip control characters; the sequence is terminated by BEL.
63
+ return `\x1b]9;${title.replace(/[\x00-\x1f\x7f]/g, ' ').slice(0, 200)}\x07`;
64
+ }
65
+ /** The terminal bell. Caller decides when it's warranted. */
66
+ export const BEL = '\x07';
67
+ /**
68
+ * Whether a "run finished" nudge (bell + notification) is warranted: the run
69
+ * took long enough to have caused a context switch, and the terminal isn't
70
+ * the focused window. Focus is unknowable without extra querying, so callers
71
+ * pass what they have; default is "assume unfocused after a long run".
72
+ */
73
+ export function shouldNudgeOnFinish(elapsedMs, focused = false, thresholdMs = 10_000) {
74
+ return elapsedMs >= thresholdMs && !focused;
75
+ }
76
+ //# sourceMappingURL=termcaps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"termcaps.js","sourceRoot":"","sources":["../../src/ui/termcaps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,4DAA4D;AAC5D,MAAM,CAAC,MAAM,UAAU,GAAG,aAAa,CAAC;AACxC,gFAAgF;AAChF,MAAM,CAAC,MAAM,QAAQ,GAAG,aAAa,CAAC;AACtC,kEAAkE;AAClE,MAAM,CAAC,MAAM,UAAU,GAAG,cAAc,CAAC;AAEzC;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,OAAO,uBAAuB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAkE;IACvG,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,CAAC,KAAK,GAAG,CAAC,KAAc,EAAE,GAAG,IAAe,EAAW,EAAE;QAC7D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClD,OAAO,QAAQ,CAAC,GAAG,UAAU,GAAG,KAAK,GAAG,QAAQ,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,QAAQ,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,CAAC;IAClC,CAAC,CAAC;IACF,OAAO,GAAG,EAAE,GAAG,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC7D,IAAI,OAAO,CAAC,MAAM,GAAG,MAAM;QAAE,OAAO,IAAI,CAAC;IACzC,OAAO,aAAa,OAAO,MAAM,CAAC;AACpC,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,+DAA+D;IAC/D,OAAO,UAAU,KAAK,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC;AAC9E,CAAC;AAED,6DAA6D;AAC7D,MAAM,CAAC,MAAM,GAAG,GAAG,MAAM,CAAC;AAE1B;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,SAAiB,EAAE,OAAO,GAAG,KAAK,EAAE,WAAW,GAAG,MAAM;IAC1F,OAAO,SAAS,IAAI,WAAW,IAAI,CAAC,OAAO,CAAC;AAC9C,CAAC"}