lumira 0.1.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.
Files changed (71) hide show
  1. package/README.md +165 -0
  2. package/dist/config.d.ts +3 -0
  3. package/dist/config.js +42 -0
  4. package/dist/config.js.map +1 -0
  5. package/dist/index.d.ts +3 -0
  6. package/dist/index.js +56 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/installer.d.ts +7 -0
  9. package/dist/installer.js +105 -0
  10. package/dist/installer.js.map +1 -0
  11. package/dist/parsers/git.d.ts +5 -0
  12. package/dist/parsers/git.js +31 -0
  13. package/dist/parsers/git.js.map +1 -0
  14. package/dist/parsers/gsd.d.ts +2 -0
  15. package/dist/parsers/gsd.js +37 -0
  16. package/dist/parsers/gsd.js.map +1 -0
  17. package/dist/parsers/memory.d.ts +2 -0
  18. package/dist/parsers/memory.js +28 -0
  19. package/dist/parsers/memory.js.map +1 -0
  20. package/dist/parsers/token-speed.d.ts +9 -0
  21. package/dist/parsers/token-speed.js +21 -0
  22. package/dist/parsers/token-speed.js.map +1 -0
  23. package/dist/parsers/transcript.d.ts +4 -0
  24. package/dist/parsers/transcript.js +148 -0
  25. package/dist/parsers/transcript.js.map +1 -0
  26. package/dist/render/colors.d.ts +20 -0
  27. package/dist/render/colors.js +59 -0
  28. package/dist/render/colors.js.map +1 -0
  29. package/dist/render/icons.d.ts +19 -0
  30. package/dist/render/icons.js +20 -0
  31. package/dist/render/icons.js.map +1 -0
  32. package/dist/render/index.d.ts +2 -0
  33. package/dist/render/index.js +27 -0
  34. package/dist/render/index.js.map +1 -0
  35. package/dist/render/line1.d.ts +3 -0
  36. package/dist/render/line1.js +89 -0
  37. package/dist/render/line1.js.map +1 -0
  38. package/dist/render/line2.d.ts +3 -0
  39. package/dist/render/line2.js +108 -0
  40. package/dist/render/line2.js.map +1 -0
  41. package/dist/render/line3.d.ts +3 -0
  42. package/dist/render/line3.js +60 -0
  43. package/dist/render/line3.js.map +1 -0
  44. package/dist/render/line4.d.ts +3 -0
  45. package/dist/render/line4.js +17 -0
  46. package/dist/render/line4.js.map +1 -0
  47. package/dist/render/minimal.d.ts +3 -0
  48. package/dist/render/minimal.js +120 -0
  49. package/dist/render/minimal.js.map +1 -0
  50. package/dist/render/text.d.ts +5 -0
  51. package/dist/render/text.js +70 -0
  52. package/dist/render/text.js.map +1 -0
  53. package/dist/stdin.d.ts +3 -0
  54. package/dist/stdin.js +40 -0
  55. package/dist/stdin.js.map +1 -0
  56. package/dist/types.d.ts +152 -0
  57. package/dist/types.js +45 -0
  58. package/dist/types.js.map +1 -0
  59. package/dist/utils/cache.d.ts +8 -0
  60. package/dist/utils/cache.js +48 -0
  61. package/dist/utils/cache.js.map +1 -0
  62. package/dist/utils/exec.d.ts +5 -0
  63. package/dist/utils/exec.js +14 -0
  64. package/dist/utils/exec.js.map +1 -0
  65. package/dist/utils/format.d.ts +4 -0
  66. package/dist/utils/format.js +36 -0
  67. package/dist/utils/format.js.map +1 -0
  68. package/dist/utils/terminal.d.ts +2 -0
  69. package/dist/utils/terminal.js +53 -0
  70. package/dist/utils/terminal.js.map +1 -0
  71. package/package.json +46 -0
@@ -0,0 +1,17 @@
1
+ import { ICONS } from './icons.js';
2
+ import { truncField } from './text.js';
3
+ export function renderLine4(gsd, c) {
4
+ if (!gsd)
5
+ return '';
6
+ if (!gsd.currentTask && !gsd.updateAvailable)
7
+ return '';
8
+ const parts = [c.dim('GSD')];
9
+ if (gsd.currentTask) {
10
+ parts.push(c.bold(`${ICONS.hammer} ${truncField(gsd.currentTask, 40)}`));
11
+ }
12
+ if (gsd.updateAvailable) {
13
+ parts.push(c.yellow(`${ICONS.warning} GSD update available`));
14
+ }
15
+ return parts.join(' ');
16
+ }
17
+ //# sourceMappingURL=line4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"line4.js","sourceRoot":"","sources":["../../src/render/line4.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAIvC,MAAM,UAAU,WAAW,CACzB,GAAmB,EACnB,CAAS;IAET,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,IAAI,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,GAAG,CAAC,eAAe;QAAE,OAAO,EAAE,CAAC;IAExD,MAAM,KAAK,GAAa,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IAEvC,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;QACpB,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,IAAI,UAAU,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3E,CAAC;IAED,IAAI,GAAG,CAAC,eAAe,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC,CAAC;IAChE,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type Colors } from './colors.js';
2
+ import type { ClaudeCodeInput, GitStatus, TranscriptData, DisplayToggles, GsdInfo } from '../types.js';
3
+ export declare function renderMinimal(input: ClaudeCodeInput, git: GitStatus, transcript: TranscriptData, tokenSpeed: number | null, gsd: GsdInfo | null, c: Colors, display: DisplayToggles, cols: number): string;
@@ -0,0 +1,120 @@
1
+ import { basename } from 'node:path';
2
+ import { ICONS } from './icons.js';
3
+ import { truncField } from './text.js';
4
+ import { getContextColor } from './colors.js';
5
+ import { formatTokens, formatDuration, formatCost } from '../utils/format.js';
6
+ import { renderLine3 } from './line3.js';
7
+ const SEP = ` \x1b[90m|\x1b[0m `;
8
+ function getModelName(model) {
9
+ if (typeof model === 'string')
10
+ return model;
11
+ if (model && typeof model === 'object' && 'display_name' in model)
12
+ return model.display_name;
13
+ return '';
14
+ }
15
+ function buildContextBar(pct, c) {
16
+ const SEGMENTS = 10;
17
+ const filled = Math.round((pct / 100) * SEGMENTS);
18
+ const colorFn = c[getContextColor(pct)];
19
+ const bar = colorFn(ICONS.barFull.repeat(filled)) + c.dim(ICONS.barEmpty.repeat(SEGMENTS - filled));
20
+ return `[${bar} ${colorFn(`${pct.toFixed(0)}%`)}]`;
21
+ }
22
+ export function renderMinimal(input, git, transcript, tokenSpeed, gsd, c, display, cols) {
23
+ const parts = [];
24
+ // Directory
25
+ const cwd = input.cwd || input.workspace?.current_dir || '';
26
+ if (display.directory && cwd) {
27
+ const dirName = basename(cwd) || cwd;
28
+ const dirLen = cols < 60 ? 12 : cols < 80 ? 20 : 30;
29
+ parts.push(c.brightBlue(truncField(dirName, dirLen)));
30
+ }
31
+ // Branch
32
+ if (display.branch && git.branch) {
33
+ const branchLen = cols < 60 ? 12 : cols < 80 ? 20 : git.branch.length;
34
+ let branchStr = c.magenta(truncField(git.branch, branchLen));
35
+ if (display.gitChanges) {
36
+ const changeParts = [];
37
+ if (git.staged > 0)
38
+ changeParts.push(c.green(`+${git.staged}`));
39
+ if (git.modified > 0)
40
+ changeParts.push(c.yellow(`~${git.modified}`));
41
+ if (git.untracked > 0)
42
+ changeParts.push(c.gray(`?${git.untracked}`));
43
+ if (changeParts.length > 0)
44
+ branchStr += ' ' + changeParts.join(' ');
45
+ }
46
+ parts.push(branchStr);
47
+ }
48
+ // Model
49
+ if (display.model) {
50
+ const modelName = getModelName(input.model);
51
+ if (modelName)
52
+ parts.push(c.cyan(truncField(modelName, 20)));
53
+ }
54
+ // Context bar
55
+ if (display.contextBar) {
56
+ parts.push(buildContextBar(input.context_window.used_percentage, c));
57
+ }
58
+ // Only add these if cols >= 60
59
+ if (cols >= 60) {
60
+ // Tokens
61
+ if (display.tokens) {
62
+ const inTokens = input.context_window.total_input_tokens;
63
+ const outTokens = input.context_window.total_output_tokens;
64
+ const tParts = [];
65
+ if (inTokens != null)
66
+ tParts.push(`${formatTokens(inTokens)}↑`);
67
+ if (outTokens != null)
68
+ tParts.push(`${formatTokens(outTokens)}↓`);
69
+ if (tParts.length > 0)
70
+ parts.push(tParts.join(' '));
71
+ }
72
+ // Cost
73
+ if (display.cost && input.cost) {
74
+ parts.push(formatCost(input.cost.total_cost_usd));
75
+ }
76
+ // Duration
77
+ if (display.duration && input.cost) {
78
+ parts.push(formatDuration(input.cost.total_duration_ms));
79
+ }
80
+ // Token speed
81
+ if (display.tokenSpeed && tokenSpeed != null) {
82
+ parts.push(c.dim(`${tokenSpeed} tok/s`));
83
+ }
84
+ // Lines changed
85
+ if (display.linesChanged && input.cost) {
86
+ const added = input.cost.total_lines_added ?? 0;
87
+ const removed = input.cost.total_lines_removed ?? 0;
88
+ if (added > 0 || removed > 0) {
89
+ parts.push(`${c.green(`+${added}`)}${c.red(`-${removed}`)}`);
90
+ }
91
+ }
92
+ // Style
93
+ if (display.style && input.output_style?.name) {
94
+ parts.push(c.dim(input.output_style.name));
95
+ }
96
+ // Version
97
+ if (display.version && input.version) {
98
+ parts.push(c.dim(`v${input.version}`));
99
+ }
100
+ // GSD current task
101
+ if (gsd?.currentTask) {
102
+ parts.push(c.yellow(truncField(gsd.currentTask, 20)));
103
+ }
104
+ // Worktree
105
+ if (display.worktree && input.worktree?.name) {
106
+ parts.push(c.dim(`${ICONS.tree} ${truncField(input.worktree.name, 12)}`));
107
+ }
108
+ // Agent
109
+ if (display.agent && input.agent?.name) {
110
+ parts.push(c.dim(`${ICONS.cubes} ${truncField(input.agent.name, 12)}`));
111
+ }
112
+ }
113
+ const mainLine = parts.join(SEP);
114
+ // Append tools/todos as extra line
115
+ const l3 = renderLine3(transcript.tools, transcript.todos, c);
116
+ if (l3)
117
+ return mainLine + '\n' + l3;
118
+ return mainLine;
119
+ }
120
+ //# sourceMappingURL=minimal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"minimal.js","sourceRoot":"","sources":["../../src/render/minimal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare function displayWidth(str: string): number;
2
+ export declare function truncField(str: string, max: number): string;
3
+ export declare function truncatePath(str: string, maxLen?: number): string;
4
+ export declare function fitSegments(left: string[], right: string[], sep: string, cols: number): string;
5
+ export declare function padLine(left: string, right: string, cols: number): string;
@@ -0,0 +1,70 @@
1
+ import { stripAnsi } from './colors.js';
2
+ export function displayWidth(str) {
3
+ const clean = stripAnsi(str);
4
+ let w = 0;
5
+ for (const ch of clean) {
6
+ const cp = ch.codePointAt(0);
7
+ if ((cp >= 0xFE00 && cp <= 0xFE0F) || cp === 0x200D || (cp >= 0x0300 && cp <= 0x036F))
8
+ continue;
9
+ if (cp >= 0x1F000 || (cp >= 0x2300 && cp <= 0x257F) || (cp >= 0x25A0 && cp <= 0x25FF) ||
10
+ (cp >= 0x2600 && cp <= 0x27BF) || (cp >= 0x2B00 && cp <= 0x2BFF) ||
11
+ (cp >= 0x4E00 && cp <= 0x9FFF) || (cp >= 0x3000 && cp <= 0x303F) || (cp >= 0xFF00 && cp <= 0xFFEF)) {
12
+ w += 2;
13
+ }
14
+ else {
15
+ w += 1;
16
+ }
17
+ }
18
+ return w;
19
+ }
20
+ export function truncField(str, max) {
21
+ if (displayWidth(str) <= max)
22
+ return str;
23
+ // Build truncated string character by character using display width
24
+ let result = '';
25
+ let w = 0;
26
+ for (const ch of str) {
27
+ const cw = displayWidth(ch);
28
+ if (w + cw + 1 > max)
29
+ break; // +1 for ellipsis
30
+ result += ch;
31
+ w += cw;
32
+ }
33
+ return result + '\u2026';
34
+ }
35
+ export function truncatePath(str, maxLen = 20) {
36
+ if (!str)
37
+ return '';
38
+ const normalized = str.replace(/\\/g, '/');
39
+ if (normalized.length <= maxLen)
40
+ return normalized;
41
+ const parts = normalized.split('/');
42
+ const filename = parts.pop() || normalized;
43
+ if (filename.length >= maxLen)
44
+ return filename.slice(0, maxLen - 3) + '...';
45
+ return '.../' + filename;
46
+ }
47
+ export function fitSegments(left, right, sep, cols) {
48
+ const safeCols = cols - 4;
49
+ const leftStr = left.join(sep);
50
+ const leftW = displayWidth(leftStr);
51
+ for (let r = right.length; r >= 0; r--) {
52
+ const rSlice = right.slice(0, r);
53
+ if (rSlice.length === 0)
54
+ return leftStr;
55
+ const rightStr = rSlice.join(sep);
56
+ const rightW = displayWidth(rightStr);
57
+ if (leftW + 1 + rightW <= safeCols) {
58
+ const gap = Math.max(1, safeCols - leftW - rightW);
59
+ return leftStr + ' '.repeat(gap) + rightStr;
60
+ }
61
+ }
62
+ return leftStr;
63
+ }
64
+ export function padLine(left, right, cols) {
65
+ const leftW = displayWidth(left);
66
+ const rightW = displayWidth(right);
67
+ const gap = Math.max(1, cols - leftW - rightW);
68
+ return left + ' '.repeat(gap) + right;
69
+ }
70
+ //# sourceMappingURL=text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/render/text.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,MAAM,EAAE,IAAI,KAAK,EAAE,CAAC;QACvB,MAAM,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC,CAAE,CAAC;QAC9B,IAAI,CAAC,EAAE,IAAI,MAAM,IAAI,EAAE,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,MAAM,IAAI,CAAC,EAAE,IAAI,MAAM,IAAI,EAAE,IAAI,MAAM,CAAC;YAAE,SAAS;QAChG,IAAI,EAAE,IAAI,OAAO,IAAI,CAAC,EAAE,IAAI,MAAM,IAAI,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,MAAM,IAAI,EAAE,IAAI,MAAM,CAAC;YACjF,CAAC,EAAE,IAAI,MAAM,IAAI,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,MAAM,IAAI,EAAE,IAAI,MAAM,CAAC;YAChE,CAAC,EAAE,IAAI,MAAM,IAAI,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,MAAM,IAAI,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,MAAM,IAAI,EAAE,IAAI,MAAM,CAAC,EAAE,CAAC;YACvG,CAAC,IAAI,CAAC,CAAC;QACT,CAAC;aAAM,CAAC;YAAC,CAAC,IAAI,CAAC,CAAC;QAAC,CAAC;IACpB,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,GAAW;IACjD,IAAI,YAAY,CAAC,GAAG,CAAC,IAAI,GAAG;QAAE,OAAO,GAAG,CAAC;IACzC,oEAAoE;IACpE,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,MAAM,EAAE,GAAG,YAAY,CAAC,EAAE,CAAC,CAAC;QAC5B,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,GAAG;YAAE,MAAM,CAAC,kBAAkB;QAC/C,MAAM,IAAI,EAAE,CAAC;QACb,CAAC,IAAI,EAAE,CAAC;IACV,CAAC;IACD,OAAO,MAAM,GAAG,QAAQ,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,SAAiB,EAAE;IAC3D,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC3C,IAAI,UAAU,CAAC,MAAM,IAAI,MAAM;QAAE,OAAO,UAAU,CAAC;IACnD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACpC,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,UAAU,CAAC;IAC3C,IAAI,QAAQ,CAAC,MAAM,IAAI,MAAM;QAAE,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;IAC5E,OAAO,MAAM,GAAG,QAAQ,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAc,EAAE,KAAe,EAAE,GAAW,EAAE,IAAY;IACpF,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC;IAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACpC,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACjC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,OAAO,CAAC;QACxC,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QACtC,IAAI,KAAK,GAAG,CAAC,GAAG,MAAM,IAAI,QAAQ,EAAE,CAAC;YACnC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC,CAAC;YACnD,OAAO,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC;QAC9C,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,IAAY,EAAE,KAAa,EAAE,IAAY;IAC/D,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,KAAK,GAAG,MAAM,CAAC,CAAC;IAC/C,OAAO,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AACxC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Readable } from 'node:stream';
2
+ import type { ClaudeCodeInput } from './types.js';
3
+ export declare function readStdin(stream?: Readable, firstByteTimeoutMs?: number, idleTimeoutMs?: number): Promise<ClaudeCodeInput>;
package/dist/stdin.js ADDED
@@ -0,0 +1,40 @@
1
+ export function readStdin(stream = process.stdin, firstByteTimeoutMs = 250, idleTimeoutMs = 30) {
2
+ return new Promise((resolve, reject) => {
3
+ let input = '';
4
+ let gotFirstByte = false;
5
+ const firstByteTimer = setTimeout(() => { cleanup(); reject(new Error('stdin timeout')); }, firstByteTimeoutMs);
6
+ let idleTimer = null;
7
+ const cleanup = () => { clearTimeout(firstByteTimer); if (idleTimer)
8
+ clearTimeout(idleTimer); stream.removeAllListeners(); };
9
+ const tryParse = () => { try {
10
+ const d = JSON.parse(input);
11
+ cleanup();
12
+ resolve(d);
13
+ return true;
14
+ }
15
+ catch {
16
+ return false;
17
+ } };
18
+ stream.setEncoding('utf8');
19
+ stream.on('data', (chunk) => {
20
+ if (!gotFirstByte) {
21
+ gotFirstByte = true;
22
+ clearTimeout(firstByteTimer);
23
+ }
24
+ input += chunk;
25
+ if (tryParse())
26
+ return;
27
+ if (idleTimer)
28
+ clearTimeout(idleTimer);
29
+ idleTimer = setTimeout(() => tryParse(), idleTimeoutMs);
30
+ });
31
+ stream.on('end', () => { cleanup(); try {
32
+ resolve(JSON.parse(input));
33
+ }
34
+ catch (e) {
35
+ reject(e);
36
+ } });
37
+ stream.on('error', (e) => { cleanup(); reject(e); });
38
+ });
39
+ }
40
+ //# sourceMappingURL=stdin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdin.js","sourceRoot":"","sources":["../src/stdin.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,SAAS,CAAC,SAAmB,OAAO,CAAC,KAAK,EAAE,qBAA6B,GAAG,EAAE,gBAAwB,EAAE;IACtH,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,KAAK,GAAG,EAAE,CAAC;QACf,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,MAAM,cAAc,GAAG,UAAU,CAAC,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAC;QAChH,IAAI,SAAS,GAAyC,IAAI,CAAC;QAE3D,MAAM,OAAO,GAAG,GAAG,EAAE,GAAG,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,SAAS;YAAE,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7H,MAAM,QAAQ,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC;YAAC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAAC,OAAO,EAAE,CAAC;YAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAAC,OAAO,IAAI,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,KAAK,CAAC;QAAC,CAAC,CAAC,CAAC,CAAC;QAE5H,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAC3B,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YAClC,IAAI,CAAC,YAAY,EAAE,CAAC;gBAAC,YAAY,GAAG,IAAI,CAAC;gBAAC,YAAY,CAAC,cAAc,CAAC,CAAC;YAAC,CAAC;YACzE,KAAK,IAAI,KAAK,CAAC;YACf,IAAI,QAAQ,EAAE;gBAAE,OAAO;YACvB,IAAI,SAAS;gBAAE,YAAY,CAAC,SAAS,CAAC,CAAC;YACvC,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,EAAE,aAAa,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC;YAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;QAAC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACpG,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,152 @@
1
+ export interface ClaudeCodeInput {
2
+ model: string | {
3
+ display_name: string;
4
+ };
5
+ session_id: string;
6
+ session_name?: string;
7
+ cwd?: string;
8
+ workspace?: {
9
+ current_dir: string;
10
+ };
11
+ context_window: {
12
+ used_percentage: number;
13
+ remaining_percentage: number;
14
+ total_input_tokens?: number;
15
+ total_output_tokens?: number;
16
+ current_usage?: {
17
+ output_tokens: number;
18
+ };
19
+ };
20
+ cost: {
21
+ total_cost_usd: number;
22
+ total_duration_ms: number;
23
+ total_lines_added?: number;
24
+ total_lines_removed?: number;
25
+ };
26
+ transcript_path?: string;
27
+ output_style?: {
28
+ name: string;
29
+ };
30
+ version?: string;
31
+ agent?: {
32
+ name: string;
33
+ };
34
+ worktree?: {
35
+ name: string;
36
+ };
37
+ vim?: {
38
+ mode: string;
39
+ };
40
+ rate_limits?: {
41
+ five_hour?: RateLimitWindow;
42
+ seven_day?: RateLimitWindow;
43
+ };
44
+ exceeds_200k_tokens?: boolean;
45
+ }
46
+ export interface RateLimitWindow {
47
+ used_percentage: number;
48
+ resets_at?: number;
49
+ }
50
+ export interface GitStatus {
51
+ branch: string;
52
+ staged: number;
53
+ modified: number;
54
+ untracked: number;
55
+ }
56
+ export declare const EMPTY_GIT: GitStatus;
57
+ export interface TranscriptData {
58
+ tools: ToolEntry[];
59
+ agents: AgentEntry[];
60
+ todos: TodoEntry[];
61
+ thinkingEffort: ThinkingEffort;
62
+ sessionStart: Date | null;
63
+ }
64
+ export declare const EMPTY_TRANSCRIPT: TranscriptData;
65
+ export type ThinkingEffort = 'low' | 'medium' | 'high' | 'max' | '';
66
+ export type ToolStatus = 'running' | 'completed' | 'error';
67
+ export interface ToolEntry {
68
+ id: string;
69
+ name: string;
70
+ target?: string;
71
+ status: ToolStatus;
72
+ startTime: Date;
73
+ endTime?: Date;
74
+ }
75
+ export interface AgentEntry {
76
+ id: string;
77
+ type: string;
78
+ model?: string;
79
+ description?: string;
80
+ status: ToolStatus;
81
+ startTime: Date;
82
+ endTime?: Date;
83
+ }
84
+ export type TodoStatus = 'pending' | 'in_progress' | 'completed';
85
+ export interface TodoEntry {
86
+ id: string;
87
+ content: string;
88
+ status: TodoStatus;
89
+ }
90
+ export interface GsdInfo {
91
+ currentTask?: string;
92
+ updateAvailable?: boolean;
93
+ }
94
+ export interface MemoryInfo {
95
+ usedBytes: number;
96
+ totalBytes: number;
97
+ percentage: number;
98
+ }
99
+ export interface RenderContext {
100
+ input: ClaudeCodeInput;
101
+ git: GitStatus;
102
+ transcript: TranscriptData;
103
+ tokenSpeed: number | null;
104
+ memory: MemoryInfo | null;
105
+ gsd: GsdInfo | null;
106
+ cols: number;
107
+ config: HudConfig;
108
+ }
109
+ export interface HudConfig {
110
+ layout: 'custom' | 'minimal' | 'auto';
111
+ gsd: boolean;
112
+ display: DisplayToggles;
113
+ colors: ColorConfig;
114
+ }
115
+ export interface DisplayToggles {
116
+ model: boolean;
117
+ branch: boolean;
118
+ gitChanges: boolean;
119
+ directory: boolean;
120
+ contextBar: boolean;
121
+ tokens: boolean;
122
+ cost: boolean;
123
+ burnRate: boolean;
124
+ duration: boolean;
125
+ tokenSpeed: boolean;
126
+ rateLimits: boolean;
127
+ tools: boolean;
128
+ todos: boolean;
129
+ vim: boolean;
130
+ effort: boolean;
131
+ worktree: boolean;
132
+ agent: boolean;
133
+ sessionName: boolean;
134
+ style: boolean;
135
+ version: boolean;
136
+ linesChanged: boolean;
137
+ memory: boolean;
138
+ }
139
+ export interface ColorConfig {
140
+ mode: 'auto' | 'named' | '256' | 'truecolor';
141
+ }
142
+ export declare const DEFAULT_DISPLAY: DisplayToggles;
143
+ export declare const DEFAULT_CONFIG: HudConfig;
144
+ export interface Dependencies {
145
+ readStdin: () => Promise<ClaudeCodeInput>;
146
+ parseGit: (cwd: string) => Promise<GitStatus>;
147
+ parseTranscript: (path: string) => Promise<TranscriptData>;
148
+ getTokenSpeed: (contextWindow: ClaudeCodeInput['context_window']) => number | null;
149
+ getMemoryInfo: () => MemoryInfo | null;
150
+ getGsdInfo: (session: string) => GsdInfo | null;
151
+ getTermCols: () => number;
152
+ }
package/dist/types.js ADDED
@@ -0,0 +1,45 @@
1
+ // ── Claude Code stdin JSON ──────────────────────────────────────────
2
+ export const EMPTY_GIT = {
3
+ branch: '',
4
+ staged: 0,
5
+ modified: 0,
6
+ untracked: 0,
7
+ };
8
+ export const EMPTY_TRANSCRIPT = {
9
+ tools: [],
10
+ agents: [],
11
+ todos: [],
12
+ thinkingEffort: '',
13
+ sessionStart: null,
14
+ };
15
+ export const DEFAULT_DISPLAY = {
16
+ model: true,
17
+ branch: true,
18
+ gitChanges: true,
19
+ directory: true,
20
+ contextBar: true,
21
+ tokens: true,
22
+ cost: true,
23
+ burnRate: true,
24
+ duration: true,
25
+ tokenSpeed: true,
26
+ rateLimits: true,
27
+ tools: true,
28
+ todos: true,
29
+ vim: true,
30
+ effort: true,
31
+ worktree: true,
32
+ agent: true,
33
+ sessionName: true,
34
+ style: true,
35
+ version: true,
36
+ linesChanged: true,
37
+ memory: true,
38
+ };
39
+ export const DEFAULT_CONFIG = {
40
+ layout: 'auto',
41
+ gsd: false,
42
+ display: { ...DEFAULT_DISPLAY },
43
+ colors: { mode: 'auto' },
44
+ };
45
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,uEAAuE;AAgDvE,MAAM,CAAC,MAAM,SAAS,GAAc;IAClC,MAAM,EAAE,EAAE;IACV,MAAM,EAAE,CAAC;IACT,QAAQ,EAAE,CAAC;IACX,SAAS,EAAE,CAAC;CACb,CAAC;AAUF,MAAM,CAAC,MAAM,gBAAgB,GAAmB;IAC9C,KAAK,EAAE,EAAE;IACT,MAAM,EAAE,EAAE;IACV,KAAK,EAAE,EAAE;IACT,cAAc,EAAE,EAAE;IAClB,YAAY,EAAE,IAAI;CACnB,CAAC;AA+FF,MAAM,CAAC,MAAM,eAAe,GAAmB;IAC7C,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,UAAU,EAAE,IAAI;IAChB,SAAS,EAAE,IAAI;IACf,UAAU,EAAE,IAAI;IAChB,MAAM,EAAE,IAAI;IACZ,IAAI,EAAE,IAAI;IACV,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;IACd,UAAU,EAAE,IAAI;IAChB,UAAU,EAAE,IAAI;IAChB,KAAK,EAAE,IAAI;IACX,KAAK,EAAE,IAAI;IACX,GAAG,EAAE,IAAI;IACT,MAAM,EAAE,IAAI;IACZ,QAAQ,EAAE,IAAI;IACd,KAAK,EAAE,IAAI;IACX,WAAW,EAAE,IAAI;IACjB,KAAK,EAAE,IAAI;IACX,OAAO,EAAE,IAAI;IACb,YAAY,EAAE,IAAI;IAClB,MAAM,EAAE,IAAI;CACb,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAc;IACvC,MAAM,EAAE,MAAM;IACd,GAAG,EAAE,KAAK;IACV,OAAO,EAAE,EAAE,GAAG,eAAe,EAAE;IAC/B,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;CACzB,CAAC"}
@@ -0,0 +1,8 @@
1
+ export declare function readTtlCache<T>(key: string, dir: string, ttlMs?: number): T | null;
2
+ export declare function writeTtlCache(key: string, data: unknown, dir: string): void;
3
+ export interface MtimeState {
4
+ mtime: number;
5
+ size: number;
6
+ }
7
+ export declare function isMtimeFresh(filePath: string, cached: MtimeState): boolean;
8
+ export declare function getMtimeState(filePath: string): MtimeState | null;
@@ -0,0 +1,48 @@
1
+ import { readFileSync, statSync, unlinkSync, openSync, writeSync, closeSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ export function readTtlCache(key, dir, ttlMs = 5000) {
4
+ const filePath = join(dir, `lumira-${key}.json`);
5
+ try {
6
+ const stat = statSync(filePath);
7
+ if (Date.now() - stat.mtimeMs > ttlMs)
8
+ return null;
9
+ return JSON.parse(readFileSync(filePath, 'utf8'));
10
+ }
11
+ catch {
12
+ return null;
13
+ }
14
+ }
15
+ export function writeTtlCache(key, data, dir) {
16
+ const filePath = join(dir, `lumira-${key}.json`);
17
+ try {
18
+ // Remove existing file first (prevents symlink following)
19
+ try {
20
+ unlinkSync(filePath);
21
+ }
22
+ catch { }
23
+ // Write with exclusive flag
24
+ const fd = openSync(filePath, 'wx', 0o600);
25
+ writeSync(fd, JSON.stringify(data));
26
+ closeSync(fd);
27
+ }
28
+ catch { }
29
+ }
30
+ export function isMtimeFresh(filePath, cached) {
31
+ try {
32
+ const stat = statSync(filePath);
33
+ return stat.mtimeMs === cached.mtime && stat.size === cached.size;
34
+ }
35
+ catch {
36
+ return false;
37
+ }
38
+ }
39
+ export function getMtimeState(filePath) {
40
+ try {
41
+ const stat = statSync(filePath);
42
+ return { mtime: stat.mtimeMs, size: stat.size };
43
+ }
44
+ catch {
45
+ return null;
46
+ }
47
+ }
48
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/utils/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC7F,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,UAAU,YAAY,CAAI,GAAW,EAAE,GAAW,EAAE,QAAgB,IAAI;IAC5E,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,CAAC;IACjD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAChC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,GAAG,KAAK;YAAE,OAAO,IAAI,CAAC;QACnD,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAM,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAW,EAAE,IAAa,EAAE,GAAW;IACnE,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,CAAC;IACjD,IAAI,CAAC;QACH,0DAA0D;QAC1D,IAAI,CAAC;YAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QACtC,4BAA4B;QAC5B,MAAM,EAAE,GAAG,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QAC3C,SAAS,CAAC,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;QACpC,SAAS,CAAC,EAAE,CAAC,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;AACZ,CAAC;AAOD,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,MAAkB;IAC/D,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAChC,OAAO,IAAI,CAAC,OAAO,KAAK,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC;IACpE,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,KAAK,CAAC;IAAC,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAChC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,5 @@
1
+ export interface ExecOptions {
2
+ cwd?: string;
3
+ timeoutMs?: number;
4
+ }
5
+ export declare function safeExec(cmd: string, args: string[], opts?: ExecOptions): Promise<string>;
@@ -0,0 +1,14 @@
1
+ import { execFile } from 'node:child_process';
2
+ export function safeExec(cmd, args, opts = {}) {
3
+ const { cwd, timeoutMs = 2000 } = opts;
4
+ return new Promise((resolve) => {
5
+ execFile(cmd, args, { cwd, timeout: timeoutMs, encoding: 'utf8' }, (error, stdout) => {
6
+ if (error) {
7
+ resolve('');
8
+ return;
9
+ }
10
+ resolve((stdout ?? '').trim());
11
+ });
12
+ });
13
+ }
14
+ //# sourceMappingURL=exec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exec.js","sourceRoot":"","sources":["../../src/utils/exec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAO9C,MAAM,UAAU,QAAQ,CAAC,GAAW,EAAE,IAAc,EAAE,OAAoB,EAAE;IAC1E,MAAM,EAAE,GAAG,EAAE,SAAS,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;IACvC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;YACnF,IAAI,KAAK,EAAE,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC,CAAC;gBAAC,OAAO;YAAC,CAAC;YACnC,OAAO,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function formatTokens(n: number): string;
2
+ export declare function formatDuration(ms: number): string;
3
+ export declare function formatCost(usd: number): string;
4
+ export declare function formatBurnRate(costUsd: number, durationMs: number): string | null;
@@ -0,0 +1,36 @@
1
+ export function formatTokens(n) {
2
+ if (n == null)
3
+ return '';
4
+ if (n >= 1_000_000)
5
+ return (n / 1_000_000).toFixed(1) + 'M';
6
+ if (n >= 1_000)
7
+ return Math.round(n / 1_000) + 'k';
8
+ return String(n);
9
+ }
10
+ export function formatDuration(ms) {
11
+ if (ms == null)
12
+ return '';
13
+ const totalSec = Math.floor(ms / 1000);
14
+ const h = Math.floor(totalSec / 3600);
15
+ const m = Math.floor((totalSec % 3600) / 60);
16
+ const s = totalSec % 60;
17
+ if (h > 0)
18
+ return `${h}h${String(m).padStart(2, '0')}m`;
19
+ if (m > 0)
20
+ return `${m}m${String(s).padStart(2, '0')}s`;
21
+ return `${s}s`;
22
+ }
23
+ export function formatCost(usd) {
24
+ if (usd == null)
25
+ return '';
26
+ if (usd < 0.01)
27
+ return '$' + usd.toFixed(4);
28
+ return '$' + usd.toFixed(2);
29
+ }
30
+ export function formatBurnRate(costUsd, durationMs) {
31
+ if (!costUsd || durationMs <= 60_000)
32
+ return null;
33
+ const perHour = costUsd / (durationMs / 3_600_000);
34
+ return '$' + perHour.toFixed(2) + '/h';
35
+ }
36
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/utils/format.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY,CAAC,CAAS;IACpC,IAAI,CAAC,IAAI,IAAI;QAAE,OAAO,EAAE,CAAC;IACzB,IAAI,CAAC,IAAI,SAAS;QAAE,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;IAC5D,IAAI,CAAC,IAAI,KAAK;QAAE,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC;IACnD,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,EAAU;IACvC,IAAI,EAAE,IAAI,IAAI;QAAE,OAAO,EAAE,CAAC;IAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IACvC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;IACtC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAC7C,MAAM,CAAC,GAAG,QAAQ,GAAG,EAAE,CAAC;IACxB,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC;IACxD,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC;IACxD,OAAO,GAAG,CAAC,GAAG,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,IAAI,GAAG,IAAI,IAAI;QAAE,OAAO,EAAE,CAAC;IAC3B,IAAI,GAAG,GAAG,IAAI;QAAE,OAAO,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC5C,OAAO,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAe,EAAE,UAAkB;IAChE,IAAI,CAAC,OAAO,IAAI,UAAU,IAAI,MAAM;QAAE,OAAO,IAAI,CAAC;IAClD,MAAM,OAAO,GAAG,OAAO,GAAG,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;IACnD,OAAO,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;AACzC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function getTermCols(): number;
2
+ export declare function getLayoutCols(rawCols: number, isTTY: boolean, factor?: number): number;