claude-auto 0.12.5 → 0.13.1
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/README.md +2 -2
- package/dist/src/cli/cli.d.ts.map +1 -1
- package/dist/src/cli/cli.js +35 -0
- package/dist/src/cli/cli.js.map +1 -1
- package/dist/src/cli/cli.test.js +1 -1
- package/dist/src/cli/cli.test.js.map +1 -1
- package/dist/src/cli/tui/banner.d.ts +2 -0
- package/dist/src/cli/tui/banner.d.ts.map +1 -0
- package/dist/src/cli/tui/banner.js +95 -0
- package/dist/src/cli/tui/banner.js.map +1 -0
- package/dist/src/cli/tui/banner.test.d.ts +2 -0
- package/dist/src/cli/tui/banner.test.d.ts.map +1 -0
- package/dist/src/cli/tui/banner.test.js +53 -0
- package/dist/src/cli/tui/banner.test.js.map +1 -0
- package/dist/src/cli/tui/detect.d.ts +2 -0
- package/dist/src/cli/tui/detect.d.ts.map +1 -0
- package/dist/src/cli/tui/detect.js +13 -0
- package/dist/src/cli/tui/detect.js.map +1 -0
- package/dist/src/cli/tui/detect.test.d.ts +2 -0
- package/dist/src/cli/tui/detect.test.d.ts.map +1 -0
- package/dist/src/cli/tui/detect.test.js +33 -0
- package/dist/src/cli/tui/detect.test.js.map +1 -0
- package/dist/src/cli/tui/launcher.d.ts +10 -0
- package/dist/src/cli/tui/launcher.d.ts.map +1 -0
- package/dist/src/cli/tui/launcher.js +14 -0
- package/dist/src/cli/tui/launcher.js.map +1 -0
- package/dist/src/cli/tui/launcher.test.d.ts +2 -0
- package/dist/src/cli/tui/launcher.test.d.ts.map +1 -0
- package/dist/src/cli/tui/launcher.test.js +46 -0
- package/dist/src/cli/tui/launcher.test.js.map +1 -0
- package/dist/src/cli/tui/log-color.d.ts +2 -0
- package/dist/src/cli/tui/log-color.d.ts.map +1 -0
- package/dist/src/cli/tui/log-color.js +36 -0
- package/dist/src/cli/tui/log-color.js.map +1 -0
- package/dist/src/cli/tui/log-color.test.d.ts +2 -0
- package/dist/src/cli/tui/log-color.test.d.ts.map +1 -0
- package/dist/src/cli/tui/log-color.test.js +59 -0
- package/dist/src/cli/tui/log-color.test.js.map +1 -0
- package/dist/src/cli/tui/log-tailer.d.ts +8 -0
- package/dist/src/cli/tui/log-tailer.d.ts.map +1 -0
- package/dist/src/cli/tui/log-tailer.js +70 -0
- package/dist/src/cli/tui/log-tailer.js.map +1 -0
- package/dist/src/cli/tui/log-tailer.test.d.ts +2 -0
- package/dist/src/cli/tui/log-tailer.test.d.ts.map +1 -0
- package/dist/src/cli/tui/log-tailer.test.js +63 -0
- package/dist/src/cli/tui/log-tailer.test.js.map +1 -0
- package/dist/src/cli/tui/screen.d.ts +7 -0
- package/dist/src/cli/tui/screen.d.ts.map +1 -0
- package/dist/src/cli/tui/screen.js +27 -0
- package/dist/src/cli/tui/screen.js.map +1 -0
- package/dist/src/cli/tui/screen.test.d.ts +2 -0
- package/dist/src/cli/tui/screen.test.d.ts.map +1 -0
- package/dist/src/cli/tui/screen.test.js +48 -0
- package/dist/src/cli/tui/screen.test.js.map +1 -0
- package/dist/src/cli/tui/tui.d.ts +14 -0
- package/dist/src/cli/tui/tui.d.ts.map +1 -0
- package/dist/src/cli/tui/tui.js +38 -0
- package/dist/src/cli/tui/tui.js.map +1 -0
- package/dist/src/cli/tui/tui.test.d.ts +2 -0
- package/dist/src/cli/tui/tui.test.d.ts.map +1 -0
- package/dist/src/cli/tui/tui.test.js +88 -0
- package/dist/src/cli/tui/tui.test.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ That's not multiplication. That's marginally faster serial work.
|
|
|
20
20
|
|
|
21
21
|
---
|
|
22
22
|
|
|
23
|
-
## The Solution: The Quality
|
|
23
|
+
## The Solution: The Quality Loop
|
|
24
24
|
|
|
25
25
|
Claude Auto creates trust. Trust enables parallelization.
|
|
26
26
|
|
|
@@ -141,7 +141,7 @@ The on.auto team ships 5-10 features per week. Not 1-2.
|
|
|
141
141
|
| ------------------------------------------------ | ------------------------------- |
|
|
142
142
|
| [Getting Started](./docs/getting-started.md) | 5-minute transformation |
|
|
143
143
|
| [Installation](./docs/installation.md) | Detailed installation guide |
|
|
144
|
-
| [The
|
|
144
|
+
| [The Ketchup Technique](./docs/ketchup-technique.md) | The planning methodology |
|
|
145
145
|
| [Configuration](./docs/configuration.md) | All configuration options |
|
|
146
146
|
| [Hooks Guide](./docs/hooks-guide.md) | Configure your supervision |
|
|
147
147
|
| [Reminders Guide](./docs/reminders-guide.md) | Context injection system |
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../src/cli/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../src/cli/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmCpC,wBAAgB,SAAS,IAAI,OAAO,CA0CnC"}
|
package/dist/src/cli/cli.js
CHANGED
|
@@ -3,6 +3,31 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.createCli = createCli;
|
|
4
4
|
const commander_1 = require("commander");
|
|
5
5
|
const install_js_1 = require("./install.js");
|
|
6
|
+
async function runTui() {
|
|
7
|
+
const { launchTui } = await import('./tui/launcher.js');
|
|
8
|
+
const cwd = process.cwd();
|
|
9
|
+
process.stdout.write('\x1b[?25l');
|
|
10
|
+
const result = launchTui({
|
|
11
|
+
dir: cwd,
|
|
12
|
+
write: (s) => process.stdout.write(s),
|
|
13
|
+
cols: process.stdout.columns || 80,
|
|
14
|
+
rows: process.stdout.rows || 24,
|
|
15
|
+
});
|
|
16
|
+
if (!result.ok) {
|
|
17
|
+
process.stdout.write('\x1b[?25h');
|
|
18
|
+
console.error('No claude-auto configuration found in this directory.');
|
|
19
|
+
console.error('Run `claude-ketchup install` first.');
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
process.stdout.on('resize', () => {
|
|
23
|
+
result.tui.resize(process.stdout.columns || 80, process.stdout.rows || 24);
|
|
24
|
+
});
|
|
25
|
+
process.on('SIGINT', () => {
|
|
26
|
+
result.tui.stop();
|
|
27
|
+
process.stdout.write('\x1b[?25h');
|
|
28
|
+
process.exit(0);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
6
31
|
function createCli() {
|
|
7
32
|
const program = new commander_1.Command();
|
|
8
33
|
program.name('claude-auto').description('Husky-style hooks and skills management for Claude Code');
|
|
@@ -27,6 +52,16 @@ function createCli() {
|
|
|
27
52
|
program.command('doctor').description('Diagnose symlink health');
|
|
28
53
|
program.command('repair').description('Recreate symlinks');
|
|
29
54
|
program.command('reminders').description('List reminders with metadata');
|
|
55
|
+
program.command('tui').description('Launch interactive TUI with live log tailing').action(runTui);
|
|
56
|
+
program.action(async () => {
|
|
57
|
+
const { isAutoConfigured } = await import('./tui/detect.js');
|
|
58
|
+
if (isAutoConfigured(process.cwd())) {
|
|
59
|
+
await runTui();
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
program.help();
|
|
63
|
+
}
|
|
64
|
+
});
|
|
30
65
|
return program;
|
|
31
66
|
}
|
|
32
67
|
//# sourceMappingURL=cli.js.map
|
package/dist/src/cli/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../src/cli/cli.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../src/cli/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/src/cli/cli.test.js
CHANGED
|
@@ -13,7 +13,7 @@ const cli_js_1 = require("./cli.js");
|
|
|
13
13
|
}).toEqual({
|
|
14
14
|
name: 'claude-auto',
|
|
15
15
|
description: 'Husky-style hooks and skills management for Claude Code',
|
|
16
|
-
commands: ['install', 'status', 'doctor', 'repair', 'reminders'],
|
|
16
|
+
commands: ['install', 'status', 'doctor', 'repair', 'reminders', 'tui'],
|
|
17
17
|
});
|
|
18
18
|
});
|
|
19
19
|
(0, vitest_1.it)('install command accepts an optional path argument', () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.test.js","sourceRoot":"","sources":["../../../src/cli/cli.test.ts"],"names":[],"mappings":";;AAAA,mCAA8C;AAE9C,qCAAqC;AAErC,IAAA,iBAAQ,EAAC,WAAW,EAAE,GAAG,EAAE;IACzB,IAAA,WAAE,EAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,OAAO,GAAG,IAAA,kBAAS,GAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;QAE3D,IAAA,eAAM,EAAC;YACL,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE;YACpB,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE;YAClC,QAAQ;SACT,CAAC,CAAC,OAAO,CAAC;YACT,IAAI,EAAE,aAAa;YACnB,WAAW,EAAE,yDAAyD;YACtE,QAAQ,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.test.js","sourceRoot":"","sources":["../../../src/cli/cli.test.ts"],"names":[],"mappings":";;AAAA,mCAA8C;AAE9C,qCAAqC;AAErC,IAAA,iBAAQ,EAAC,WAAW,EAAE,GAAG,EAAE;IACzB,IAAA,WAAE,EAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,OAAO,GAAG,IAAA,kBAAS,GAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;QAE3D,IAAA,eAAM,EAAC;YACL,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE;YACpB,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE;YAClC,QAAQ;SACT,CAAC,CAAC,OAAO,CAAC;YACT,IAAI,EAAE,aAAa;YACnB,WAAW,EAAE,yDAAyD;YACtE,QAAQ,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,CAAC;SACxE,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,OAAO,GAAG,IAAA,kBAAS,GAAE,CAAC;QAC5B,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,SAAS,CAAC,CAAC;QAC5E,IAAA,eAAM,EAAC,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC;QACjC,IAAA,eAAM,EAAC,UAAW,CAAC,mBAAmB,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACxD,IAAA,eAAM,EAAC,UAAW,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"banner.d.ts","sourceRoot":"","sources":["../../../../src/cli/tui/banner.ts"],"names":[],"mappings":"AAiFA,wBAAgB,YAAY,IAAI,MAAM,CA2BrC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.renderBanner = renderBanner;
|
|
4
|
+
const R = '\x1b[0m';
|
|
5
|
+
const rgb = (r, g, b) => `\x1b[38;2;${r};${g};${b}m`;
|
|
6
|
+
const orange = rgb(255, 138, 29);
|
|
7
|
+
const blue = rgb(66, 195, 247);
|
|
8
|
+
const red = rgb(236, 63, 74);
|
|
9
|
+
const green = rgb(94, 199, 45);
|
|
10
|
+
const gray = rgb(180, 180, 180);
|
|
11
|
+
const stripeColors = [red, orange, green, blue];
|
|
12
|
+
const bandWidth = 3;
|
|
13
|
+
const gapWidth = 2;
|
|
14
|
+
const stripeStart = 62;
|
|
15
|
+
const slopeMultiplier = 2;
|
|
16
|
+
function parseAnsiTokens(line) {
|
|
17
|
+
const tokens = [];
|
|
18
|
+
let i = 0;
|
|
19
|
+
while (i < line.length) {
|
|
20
|
+
if (line[i] === '\x1b') {
|
|
21
|
+
const end = line.indexOf('m', i);
|
|
22
|
+
if (end >= 0) {
|
|
23
|
+
tokens.push(line.slice(i, end + 1));
|
|
24
|
+
i = end + 1;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
tokens.push(line[i]);
|
|
29
|
+
i++;
|
|
30
|
+
}
|
|
31
|
+
return tokens;
|
|
32
|
+
}
|
|
33
|
+
function overlayStripes(line, plainLen, row, totalWidth) {
|
|
34
|
+
const tokens = parseAnsiTokens(line);
|
|
35
|
+
let visibleCount = 0;
|
|
36
|
+
for (const t of tokens) {
|
|
37
|
+
if (!t.startsWith('\x1b'))
|
|
38
|
+
visibleCount++;
|
|
39
|
+
}
|
|
40
|
+
for (let p = visibleCount; p < totalWidth; p++) {
|
|
41
|
+
tokens.push(' ');
|
|
42
|
+
}
|
|
43
|
+
const result = [];
|
|
44
|
+
let visibleCol = 0;
|
|
45
|
+
for (const token of tokens) {
|
|
46
|
+
if (token.startsWith('\x1b')) {
|
|
47
|
+
result.push(token);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (visibleCol >= plainLen) {
|
|
51
|
+
const stripe = getStripeColor(visibleCol, row);
|
|
52
|
+
result.push(stripe ? `${stripe}█${R}` : token);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
result.push(token);
|
|
56
|
+
}
|
|
57
|
+
visibleCol++;
|
|
58
|
+
}
|
|
59
|
+
return result.join('');
|
|
60
|
+
}
|
|
61
|
+
function getStripeColor(col, row) {
|
|
62
|
+
const diag = col + row * slopeMultiplier;
|
|
63
|
+
for (let i = 0; i < stripeColors.length; i++) {
|
|
64
|
+
const bandStart = stripeStart + i * (bandWidth + gapWidth);
|
|
65
|
+
const bandEnd = bandStart + bandWidth;
|
|
66
|
+
if (diag >= bandStart && diag < bandEnd) {
|
|
67
|
+
return stripeColors[i];
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
function renderBanner() {
|
|
73
|
+
const claudeLines = [
|
|
74
|
+
{ text: `${orange} ██████╗██╗ █████╗ ██╗ ██╗██████╗ ███████╗${R}`, len: 50 },
|
|
75
|
+
{ text: `${orange}██╔════╝██║ ██╔══██╗██║ ██║██╔══██╗██╔════╝${R}`, len: 50 },
|
|
76
|
+
{ text: `${orange}██║ ██║ ███████║██║ ██║██║ ██║█████╗ ${R}`, len: 50 },
|
|
77
|
+
{ text: `${orange}██║ ██║ ██╔══██║██║ ██║██║ ██║██╔══╝ ${R}`, len: 50 },
|
|
78
|
+
{ text: `${orange}╚██████╗███████╗██║ ██║╚██████╔╝██████╔╝███████╗${R}`, len: 50 },
|
|
79
|
+
{ text: `${orange} ╚═════╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝${R}`, len: 51 },
|
|
80
|
+
];
|
|
81
|
+
const autoLines = [
|
|
82
|
+
{ text: `${gray} █████╗ ██╗ ██╗████████╗ ██████╗ ${R}`, len: 36 },
|
|
83
|
+
{ text: `${gray}██╔══██╗██║ ██║╚══██╔══╝██╔═══██╗${R}`, len: 36 },
|
|
84
|
+
{ text: `${gray}███████║██║ ██║ ██║ ██║ ██║${R}`, len: 36 },
|
|
85
|
+
{ text: `${gray}██╔══██║██║ ██║ ██║ ██║ ██║${R}`, len: 36 },
|
|
86
|
+
{ text: `${gray}██║ ██║╚██████╔╝ ██║ ╚██████╔╝${R}`, len: 36 },
|
|
87
|
+
{ text: `${gray}╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ${R}`, len: 36 },
|
|
88
|
+
];
|
|
89
|
+
const totalWidth = 85;
|
|
90
|
+
const allRows = [...claudeLines, ...autoLines];
|
|
91
|
+
const rendered = allRows.map((r, i) => overlayStripes(r.text, r.len, i, totalWidth));
|
|
92
|
+
const lines = ['', ...rendered, ''];
|
|
93
|
+
return lines.join('\n');
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=banner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"banner.js","sourceRoot":"","sources":["../../../../src/cli/tui/banner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"banner.test.d.ts","sourceRoot":"","sources":["../../../../src/cli/tui/banner.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const banner_js_1 = require("./banner.js");
|
|
5
|
+
const ESC = String.fromCharCode(27);
|
|
6
|
+
const ANSI_PATTERN = new RegExp(`${ESC}\\[[0-9;]*m`, 'g');
|
|
7
|
+
function stripAnsi(str) {
|
|
8
|
+
return str.replace(ANSI_PATTERN, '');
|
|
9
|
+
}
|
|
10
|
+
(0, vitest_1.describe)('renderBanner', () => {
|
|
11
|
+
(0, vitest_1.it)('returns large block-letter ASCII art for CLAUDE and AUTO', () => {
|
|
12
|
+
const banner = (0, banner_js_1.renderBanner)();
|
|
13
|
+
const plain = stripAnsi(banner);
|
|
14
|
+
const lines = plain.split('\n');
|
|
15
|
+
(0, vitest_1.expect)({
|
|
16
|
+
hasBlockArt: plain.includes('██'),
|
|
17
|
+
hasBoxDrawing: plain.includes('╗'),
|
|
18
|
+
hasMultipleLines: lines.length > 10,
|
|
19
|
+
}).toEqual({
|
|
20
|
+
hasBlockArt: true,
|
|
21
|
+
hasBoxDrawing: true,
|
|
22
|
+
hasMultipleLines: true,
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
(0, vitest_1.it)('includes ANSI color codes', () => {
|
|
26
|
+
const banner = (0, banner_js_1.renderBanner)();
|
|
27
|
+
(0, vitest_1.expect)(banner.includes(ESC)).toBe(true);
|
|
28
|
+
});
|
|
29
|
+
(0, vitest_1.it)('renders diagonal stripe bands to the right of the text', () => {
|
|
30
|
+
const banner = (0, banner_js_1.renderBanner)();
|
|
31
|
+
const lines = banner.split('\n').filter((l) => l.length > 0);
|
|
32
|
+
const linesWithMultipleColors = lines.filter((l) => {
|
|
33
|
+
const colorMatches = l.match(new RegExp(`${ESC}\\[38;2;`, 'g'));
|
|
34
|
+
return colorMatches && colorMatches.length > 2;
|
|
35
|
+
});
|
|
36
|
+
(0, vitest_1.expect)(linesWithMultipleColors.length).toBeGreaterThan(3);
|
|
37
|
+
});
|
|
38
|
+
(0, vitest_1.it)('uses all four brand colors in the stripes', () => {
|
|
39
|
+
const banner = (0, banner_js_1.renderBanner)();
|
|
40
|
+
(0, vitest_1.expect)({
|
|
41
|
+
hasRed: banner.includes(`${ESC}[38;2;236;63;74m`),
|
|
42
|
+
hasOrange: banner.includes(`${ESC}[38;2;255;138;29m`),
|
|
43
|
+
hasGreen: banner.includes(`${ESC}[38;2;94;199;45m`),
|
|
44
|
+
hasBlue: banner.includes(`${ESC}[38;2;66;195;247m`),
|
|
45
|
+
}).toEqual({
|
|
46
|
+
hasRed: true,
|
|
47
|
+
hasOrange: true,
|
|
48
|
+
hasGreen: true,
|
|
49
|
+
hasBlue: true,
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
//# sourceMappingURL=banner.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"banner.test.js","sourceRoot":"","sources":["../../../../src/cli/tui/banner.test.ts"],"names":[],"mappings":";;AAAA,mCAA8C;AAE9C,2CAA2C;AAE3C,MAAM,GAAG,GAAG,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;AACpC,MAAM,YAAY,GAAG,IAAI,MAAM,CAAC,GAAG,GAAG,aAAa,EAAE,GAAG,CAAC,CAAC;AAE1D,SAAS,SAAS,CAAC,GAAW;IAC5B,OAAO,GAAG,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;AACvC,CAAC;AAED,IAAA,iBAAQ,EAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,IAAA,WAAE,EAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,MAAM,GAAG,IAAA,wBAAY,GAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;QAChC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEhC,IAAA,eAAM,EAAC;YACL,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;YACjC,aAAa,EAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC;YAClC,gBAAgB,EAAE,KAAK,CAAC,MAAM,GAAG,EAAE;SACpC,CAAC,CAAC,OAAO,CAAC;YACT,WAAW,EAAE,IAAI;YACjB,aAAa,EAAE,IAAI;YACnB,gBAAgB,EAAE,IAAI;SACvB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,2BAA2B,EAAE,GAAG,EAAE;QACnC,MAAM,MAAM,GAAG,IAAA,wBAAY,GAAE,CAAC;QAC9B,IAAA,eAAM,EAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,MAAM,MAAM,GAAG,IAAA,wBAAY,GAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC7D,MAAM,uBAAuB,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;YACjD,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,GAAG,GAAG,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;YAChE,OAAO,YAAY,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;QAEH,IAAA,eAAM,EAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,MAAM,GAAG,IAAA,wBAAY,GAAE,CAAC;QAE9B,IAAA,eAAM,EAAC;YACL,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,GAAG,kBAAkB,CAAC;YACjD,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,GAAG,mBAAmB,CAAC;YACrD,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,GAAG,kBAAkB,CAAC;YACnD,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,GAAG,mBAAmB,CAAC;SACpD,CAAC,CAAC,OAAO,CAAC;YACT,MAAM,EAAE,IAAI;YACZ,SAAS,EAAE,IAAI;YACf,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../../../src/cli/tui/detect.ts"],"names":[],"mappings":"AAGA,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAKrD"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.isAutoConfigured = isAutoConfigured;
|
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
function isAutoConfigured(dir) {
|
|
10
|
+
return (node_fs_1.default.existsSync(node_path_1.default.join(dir, '.ketchup', '.claude.hooks.json')) ||
|
|
11
|
+
node_fs_1.default.existsSync(node_path_1.default.join(dir, '.claude.hooks.json')));
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=detect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.js","sourceRoot":"","sources":["../../../../src/cli/tui/detect.ts"],"names":[],"mappings":";;;;;AAGA,4CAKC;AARD,sDAAyB;AACzB,0DAA6B;AAE7B,SAAgB,gBAAgB,CAAC,GAAW;IAC1C,OAAO,CACL,iBAAE,CAAC,UAAU,CAAC,mBAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,oBAAoB,CAAC,CAAC;QAC/D,iBAAE,CAAC,UAAU,CAAC,mBAAI,CAAC,IAAI,CAAC,GAAG,EAAE,oBAAoB,CAAC,CAAC,CACpD,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.test.d.ts","sourceRoot":"","sources":["../../../../src/cli/tui/detect.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
7
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const vitest_1 = require("vitest");
|
|
10
|
+
const detect_js_1 = require("./detect.js");
|
|
11
|
+
(0, vitest_1.describe)('isAutoConfigured', () => {
|
|
12
|
+
let tempDir;
|
|
13
|
+
(0, vitest_1.beforeEach)(() => {
|
|
14
|
+
tempDir = node_fs_1.default.mkdtempSync(node_path_1.default.join(node_os_1.default.tmpdir(), 'auto-detect-'));
|
|
15
|
+
});
|
|
16
|
+
(0, vitest_1.afterEach)(() => {
|
|
17
|
+
node_fs_1.default.rmSync(tempDir, { recursive: true, force: true });
|
|
18
|
+
});
|
|
19
|
+
(0, vitest_1.it)('returns false when .ketchup directory does not exist', () => {
|
|
20
|
+
(0, vitest_1.expect)((0, detect_js_1.isAutoConfigured)(tempDir)).toBe(false);
|
|
21
|
+
});
|
|
22
|
+
(0, vitest_1.it)('returns false when .ketchup exists but .claude.hooks.json is missing', () => {
|
|
23
|
+
node_fs_1.default.mkdirSync(node_path_1.default.join(tempDir, '.ketchup'));
|
|
24
|
+
(0, vitest_1.expect)((0, detect_js_1.isAutoConfigured)(tempDir)).toBe(false);
|
|
25
|
+
});
|
|
26
|
+
(0, vitest_1.it)('returns true when .ketchup/.claude.hooks.json exists', () => {
|
|
27
|
+
const ketchupDir = node_path_1.default.join(tempDir, '.ketchup');
|
|
28
|
+
node_fs_1.default.mkdirSync(ketchupDir);
|
|
29
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(ketchupDir, '.claude.hooks.json'), '{}');
|
|
30
|
+
(0, vitest_1.expect)((0, detect_js_1.isAutoConfigured)(tempDir)).toBe(true);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
//# sourceMappingURL=detect.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.test.js","sourceRoot":"","sources":["../../../../src/cli/tui/detect.test.ts"],"names":[],"mappings":";;;;;AAAA,sDAAyB;AACzB,sDAAyB;AACzB,0DAA6B;AAC7B,mCAAqE;AAErE,2CAA+C;AAE/C,IAAA,iBAAQ,EAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,IAAI,OAAe,CAAC;IAEpB,IAAA,mBAAU,EAAC,GAAG,EAAE;QACd,OAAO,GAAG,iBAAE,CAAC,WAAW,CAAC,mBAAI,CAAC,IAAI,CAAC,iBAAE,CAAC,MAAM,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,IAAA,kBAAS,EAAC,GAAG,EAAE;QACb,iBAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,IAAA,eAAM,EAAC,IAAA,4BAAgB,EAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,sEAAsE,EAAE,GAAG,EAAE;QAC9E,iBAAE,CAAC,SAAS,CAAC,mBAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;QAC7C,IAAA,eAAM,EAAC,IAAA,4BAAgB,EAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,UAAU,GAAG,mBAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAClD,iBAAE,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QACzB,iBAAE,CAAC,aAAa,CAAC,mBAAI,CAAC,IAAI,CAAC,UAAU,EAAE,oBAAoB,CAAC,EAAE,IAAI,CAAC,CAAC;QACpE,IAAA,eAAM,EAAC,IAAA,4BAAgB,EAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Tui, TuiOptions } from './tui.js';
|
|
2
|
+
export type LaunchResult = {
|
|
3
|
+
ok: true;
|
|
4
|
+
tui: Tui;
|
|
5
|
+
} | {
|
|
6
|
+
ok: false;
|
|
7
|
+
reason: 'not-configured';
|
|
8
|
+
};
|
|
9
|
+
export declare function launchTui(options: TuiOptions): LaunchResult;
|
|
10
|
+
//# sourceMappingURL=launcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launcher.d.ts","sourceRoot":"","sources":["../../../../src/cli/tui/launcher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGhD,MAAM,MAAM,YAAY,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,GAAG,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAE5F,wBAAgB,SAAS,CAAC,OAAO,EAAE,UAAU,GAAG,YAAY,CAQ3D"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.launchTui = launchTui;
|
|
4
|
+
const detect_js_1 = require("./detect.js");
|
|
5
|
+
const tui_js_1 = require("./tui.js");
|
|
6
|
+
function launchTui(options) {
|
|
7
|
+
if (!(0, detect_js_1.isAutoConfigured)(options.dir)) {
|
|
8
|
+
return { ok: false, reason: 'not-configured' };
|
|
9
|
+
}
|
|
10
|
+
const tui = (0, tui_js_1.createTui)(options);
|
|
11
|
+
tui.render();
|
|
12
|
+
return { ok: true, tui };
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=launcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launcher.js","sourceRoot":"","sources":["../../../../src/cli/tui/launcher.ts"],"names":[],"mappings":";;AAMA,8BAQC;AAdD,2CAA+C;AAE/C,qCAAqC;AAIrC,SAAgB,SAAS,CAAC,OAAmB;IAC3C,IAAI,CAAC,IAAA,4BAAgB,EAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACnC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACjD,CAAC;IAED,MAAM,GAAG,GAAG,IAAA,kBAAS,EAAC,OAAO,CAAC,CAAC;IAC/B,GAAG,CAAC,MAAM,EAAE,CAAC;IACb,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;AAC3B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launcher.test.d.ts","sourceRoot":"","sources":["../../../../src/cli/tui/launcher.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
7
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const vitest_1 = require("vitest");
|
|
10
|
+
const launcher_js_1 = require("./launcher.js");
|
|
11
|
+
(0, vitest_1.describe)('launchTui', () => {
|
|
12
|
+
let tempDir;
|
|
13
|
+
(0, vitest_1.beforeEach)(() => {
|
|
14
|
+
tempDir = node_fs_1.default.mkdtempSync(node_path_1.default.join(node_os_1.default.tmpdir(), 'launcher-'));
|
|
15
|
+
});
|
|
16
|
+
(0, vitest_1.afterEach)(() => {
|
|
17
|
+
node_fs_1.default.rmSync(tempDir, { recursive: true, force: true });
|
|
18
|
+
});
|
|
19
|
+
(0, vitest_1.it)('returns error when directory is not configured', () => {
|
|
20
|
+
const writes = [];
|
|
21
|
+
const result = (0, launcher_js_1.launchTui)({
|
|
22
|
+
dir: tempDir,
|
|
23
|
+
write: (s) => writes.push(s),
|
|
24
|
+
cols: 80,
|
|
25
|
+
rows: 24,
|
|
26
|
+
});
|
|
27
|
+
(0, vitest_1.expect)(result).toEqual({ ok: false, reason: 'not-configured' });
|
|
28
|
+
});
|
|
29
|
+
(0, vitest_1.it)('returns tui handle when directory is configured', () => {
|
|
30
|
+
const ketchupDir = node_path_1.default.join(tempDir, '.ketchup');
|
|
31
|
+
node_fs_1.default.mkdirSync(node_path_1.default.join(ketchupDir, 'logs'), { recursive: true });
|
|
32
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(ketchupDir, '.claude.hooks.json'), '{}');
|
|
33
|
+
const writes = [];
|
|
34
|
+
const result = (0, launcher_js_1.launchTui)({
|
|
35
|
+
dir: tempDir,
|
|
36
|
+
write: (s) => writes.push(s),
|
|
37
|
+
cols: 80,
|
|
38
|
+
rows: 24,
|
|
39
|
+
});
|
|
40
|
+
(0, vitest_1.expect)(result.ok).toBe(true);
|
|
41
|
+
if (result.ok) {
|
|
42
|
+
result.tui.stop();
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
//# sourceMappingURL=launcher.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launcher.test.js","sourceRoot":"","sources":["../../../../src/cli/tui/launcher.test.ts"],"names":[],"mappings":";;;;;AAAA,sDAAyB;AACzB,sDAAyB;AACzB,0DAA6B;AAC7B,mCAAqE;AAErE,+CAA0C;AAE1C,IAAA,iBAAQ,EAAC,WAAW,EAAE,GAAG,EAAE;IACzB,IAAI,OAAe,CAAC;IAEpB,IAAA,mBAAU,EAAC,GAAG,EAAE;QACd,OAAO,GAAG,iBAAE,CAAC,WAAW,CAAC,mBAAI,CAAC,IAAI,CAAC,iBAAE,CAAC,MAAM,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,IAAA,kBAAS,EAAC,GAAG,EAAE;QACb,iBAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,IAAA,uBAAS,EAAC;YACvB,GAAG,EAAE,OAAO;YACZ,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;YAC5B,IAAI,EAAE,EAAE;YACR,IAAI,EAAE,EAAE;SACT,CAAC,CAAC;QAEH,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,UAAU,GAAG,mBAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAClD,iBAAE,CAAC,SAAS,CAAC,mBAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACjE,iBAAE,CAAC,aAAa,CAAC,mBAAI,CAAC,IAAI,CAAC,UAAU,EAAE,oBAAoB,CAAC,EAAE,IAAI,CAAC,CAAC;QAEpE,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,IAAA,uBAAS,EAAC;YACvB,GAAG,EAAE,OAAO;YACZ,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;YAC5B,IAAI,EAAE,EAAE;YACR,IAAI,EAAE,EAAE;SACT,CAAC,CAAC;QAEH,IAAA,eAAM,EAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;YACd,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACpB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-color.d.ts","sourceRoot":"","sources":["../../../../src/cli/tui/log-color.ts"],"names":[],"mappings":"AA2BA,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAUpD"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.colorizeLogLine = colorizeLogLine;
|
|
4
|
+
const R = '\x1b[0m';
|
|
5
|
+
const DIM = '\x1b[2m';
|
|
6
|
+
const BOLD = '\x1b[1m';
|
|
7
|
+
const CYAN = '\x1b[36m';
|
|
8
|
+
const GREEN = '\x1b[32m';
|
|
9
|
+
const RED = '\x1b[31m';
|
|
10
|
+
const YELLOW = '\x1b[33m';
|
|
11
|
+
const LOG_PATTERN = /^(\d{2}-\d{2} \d{2}:\d{2}:\d{2}) (\[[0-9a-f]+\]) (\S+:) (.*)$/;
|
|
12
|
+
const STATUS_STYLES = [
|
|
13
|
+
{ pattern: /\bNACK\b/g, color: `${BOLD}${RED}` },
|
|
14
|
+
{ pattern: /\bDENIED\b/g, color: `${BOLD}${RED}` },
|
|
15
|
+
{ pattern: /\bACK\b/g, color: `${BOLD}${GREEN}` },
|
|
16
|
+
{ pattern: /\bERROR\b/g, color: RED },
|
|
17
|
+
{ pattern: /\bWARN\b/g, color: YELLOW },
|
|
18
|
+
{ pattern: /\bSKIP\b/g, color: YELLOW },
|
|
19
|
+
];
|
|
20
|
+
function colorizeMessage(msg) {
|
|
21
|
+
let result = msg;
|
|
22
|
+
for (const { pattern, color } of STATUS_STYLES) {
|
|
23
|
+
result = result.replace(pattern, (match) => `${color}${match}${R}`);
|
|
24
|
+
}
|
|
25
|
+
return result;
|
|
26
|
+
}
|
|
27
|
+
function colorizeLogLine(line) {
|
|
28
|
+
const match = LOG_PATTERN.exec(line);
|
|
29
|
+
if (!match) {
|
|
30
|
+
return `${DIM}${line}${R}`;
|
|
31
|
+
}
|
|
32
|
+
const [, timestamp, sessionId, hookName, message] = match;
|
|
33
|
+
const coloredMessage = colorizeMessage(message);
|
|
34
|
+
return `${DIM}${timestamp}${R} ${DIM}${sessionId}${R} ${CYAN}${hookName}${R} ${coloredMessage}`;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=log-color.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-color.js","sourceRoot":"","sources":["../../../../src/cli/tui/log-color.ts"],"names":[],"mappings":";;AA2BA,0CAUC;AArCD,MAAM,CAAC,GAAG,SAAS,CAAC;AACpB,MAAM,GAAG,GAAG,SAAS,CAAC;AACtB,MAAM,IAAI,GAAG,SAAS,CAAC;AACvB,MAAM,IAAI,GAAG,UAAU,CAAC;AACxB,MAAM,KAAK,GAAG,UAAU,CAAC;AACzB,MAAM,GAAG,GAAG,UAAU,CAAC;AACvB,MAAM,MAAM,GAAG,UAAU,CAAC;AAE1B,MAAM,WAAW,GAAG,+DAA+D,CAAC;AAEpF,MAAM,aAAa,GAA8C;IAC/D,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,IAAI,GAAG,GAAG,EAAE,EAAE;IAChD,EAAE,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,GAAG,IAAI,GAAG,GAAG,EAAE,EAAE;IAClD,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,IAAI,GAAG,KAAK,EAAE,EAAE;IACjD,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,GAAG,EAAE;IACrC,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE;IACvC,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE;CACxC,CAAC;AAEF,SAAS,eAAe,CAAC,GAAW;IAClC,IAAI,MAAM,GAAG,GAAG,CAAC;IACjB,KAAK,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,aAAa,EAAE,CAAC;QAC/C,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,GAAG,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAgB,eAAe,CAAC,IAAY;IAC1C,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,GAAG,GAAG,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC;IAC7B,CAAC;IAED,MAAM,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC;IAC1D,MAAM,cAAc,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IAEhD,OAAO,GAAG,GAAG,GAAG,SAAS,GAAG,CAAC,IAAI,GAAG,GAAG,SAAS,GAAG,CAAC,IAAI,IAAI,GAAG,QAAQ,GAAG,CAAC,IAAI,cAAc,EAAE,CAAC;AAClG,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-color.test.d.ts","sourceRoot":"","sources":["../../../../src/cli/tui/log-color.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const log_color_js_1 = require("./log-color.js");
|
|
5
|
+
const ESC = String.fromCharCode(27);
|
|
6
|
+
const ANSI_PATTERN = new RegExp(`${ESC}\\[[0-9;]*m`, 'g');
|
|
7
|
+
function stripAnsi(str) {
|
|
8
|
+
return str.replace(ANSI_PATTERN, '');
|
|
9
|
+
}
|
|
10
|
+
(0, vitest_1.describe)('colorizeLogLine', () => {
|
|
11
|
+
(0, vitest_1.it)('preserves plain text content when colorized', () => {
|
|
12
|
+
const line = '02-03 18:12:39 [e7934e89] session-start: loaded 9 reminders';
|
|
13
|
+
const result = (0, log_color_js_1.colorizeLogLine)(line);
|
|
14
|
+
const plain = stripAnsi(result);
|
|
15
|
+
(0, vitest_1.expect)(plain).toBe(line);
|
|
16
|
+
});
|
|
17
|
+
(0, vitest_1.it)('adds ANSI color codes to structured log lines', () => {
|
|
18
|
+
const line = '02-03 18:12:39 [e7934e89] session-start: loaded 9 reminders';
|
|
19
|
+
const result = (0, log_color_js_1.colorizeLogLine)(line);
|
|
20
|
+
(0, vitest_1.expect)(result.includes(ESC)).toBe(true);
|
|
21
|
+
});
|
|
22
|
+
(0, vitest_1.it)('dims the timestamp portion', () => {
|
|
23
|
+
const line = '02-03 18:12:39 [e7934e89] session-start: loaded 9 reminders';
|
|
24
|
+
const result = (0, log_color_js_1.colorizeLogLine)(line);
|
|
25
|
+
(0, vitest_1.expect)(result.startsWith('\x1b[2m02-03 18:12:39')).toBe(true);
|
|
26
|
+
});
|
|
27
|
+
(0, vitest_1.it)('dims the session ID', () => {
|
|
28
|
+
const line = '02-03 18:12:39 [e7934e89] session-start: loaded 9 reminders';
|
|
29
|
+
const result = (0, log_color_js_1.colorizeLogLine)(line);
|
|
30
|
+
(0, vitest_1.expect)(result.includes('\x1b[2m[e7934e89]')).toBe(true);
|
|
31
|
+
});
|
|
32
|
+
(0, vitest_1.it)('highlights hook name in cyan', () => {
|
|
33
|
+
const line = '02-03 18:12:39 [e7934e89] session-start: loaded 9 reminders';
|
|
34
|
+
const result = (0, log_color_js_1.colorizeLogLine)(line);
|
|
35
|
+
(0, vitest_1.expect)(result.includes('\x1b[36msession-start:')).toBe(true);
|
|
36
|
+
});
|
|
37
|
+
(0, vitest_1.it)('highlights ACK in green bold', () => {
|
|
38
|
+
const line = '02-03 18:34:57 [db3b58fe] pre-tool-use: validator complete: hygiene → ACK (in:34244 out:86)';
|
|
39
|
+
const result = (0, log_color_js_1.colorizeLogLine)(line);
|
|
40
|
+
(0, vitest_1.expect)(result.includes('\x1b[1m\x1b[32mACK\x1b[0m')).toBe(true);
|
|
41
|
+
});
|
|
42
|
+
(0, vitest_1.it)('highlights NACK in red bold', () => {
|
|
43
|
+
const line = '02-03 18:34:57 [db3b58fe] pre-tool-use: validator complete: hygiene → NACK';
|
|
44
|
+
const result = (0, log_color_js_1.colorizeLogLine)(line);
|
|
45
|
+
(0, vitest_1.expect)(result.includes('\x1b[1m\x1b[31mNACK\x1b[0m')).toBe(true);
|
|
46
|
+
});
|
|
47
|
+
(0, vitest_1.it)('returns unstructured lines with dim styling', () => {
|
|
48
|
+
const line = 'some random text without log format';
|
|
49
|
+
const result = (0, log_color_js_1.colorizeLogLine)(line);
|
|
50
|
+
(0, vitest_1.expect)(result).toBe(`\x1b[2m${line}\x1b[0m`);
|
|
51
|
+
});
|
|
52
|
+
(0, vitest_1.it)('highlights validator names in the message', () => {
|
|
53
|
+
const line = '02-03 18:34:51 [db3b58fe] pre-tool-use: validator spawn: batch-0 → validators: backwards-compat, burst-atomicity';
|
|
54
|
+
const result = (0, log_color_js_1.colorizeLogLine)(line);
|
|
55
|
+
const plain = stripAnsi(result);
|
|
56
|
+
(0, vitest_1.expect)(plain).toBe(line);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
//# sourceMappingURL=log-color.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-color.test.js","sourceRoot":"","sources":["../../../../src/cli/tui/log-color.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-tailer.d.ts","sourceRoot":"","sources":["../../../../src/cli/tui/log-tailer.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,SAAS;IACxB,OAAO,IAAI,MAAM,EAAE,CAAC;IACpB,IAAI,IAAI,IAAI,CAAC;CACd;AAED,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAC/B,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9B,SAAS,CAiEX"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createLogTailer = createLogTailer;
|
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
function createLogTailer(ketchupDir, onLine, options) {
|
|
10
|
+
const logFile = node_path_1.default.join(ketchupDir, 'logs', 'activity.log');
|
|
11
|
+
const maxLines = options?.maxLines;
|
|
12
|
+
let lines = [];
|
|
13
|
+
let watcher;
|
|
14
|
+
let offset = 0;
|
|
15
|
+
let stopped = false;
|
|
16
|
+
function loadExisting() {
|
|
17
|
+
if (!node_fs_1.default.existsSync(logFile))
|
|
18
|
+
return;
|
|
19
|
+
const content = node_fs_1.default.readFileSync(logFile, 'utf-8');
|
|
20
|
+
offset = Buffer.byteLength(content, 'utf-8');
|
|
21
|
+
const raw = content.split('\n').filter((l) => l.length > 0);
|
|
22
|
+
lines = maxLines ? raw.slice(-maxLines) : raw;
|
|
23
|
+
}
|
|
24
|
+
function pollNewLines() {
|
|
25
|
+
if (stopped || !node_fs_1.default.existsSync(logFile))
|
|
26
|
+
return;
|
|
27
|
+
const stat = node_fs_1.default.statSync(logFile);
|
|
28
|
+
if (stat.size <= offset)
|
|
29
|
+
return;
|
|
30
|
+
const fd = node_fs_1.default.openSync(logFile, 'r');
|
|
31
|
+
const buf = Buffer.alloc(stat.size - offset);
|
|
32
|
+
node_fs_1.default.readSync(fd, buf, 0, buf.length, offset);
|
|
33
|
+
node_fs_1.default.closeSync(fd);
|
|
34
|
+
offset = stat.size;
|
|
35
|
+
const chunk = buf.toString('utf-8');
|
|
36
|
+
const newLines = chunk.split('\n').filter((l) => l.length > 0);
|
|
37
|
+
for (const line of newLines) {
|
|
38
|
+
lines.push(line);
|
|
39
|
+
if (maxLines && lines.length > maxLines) {
|
|
40
|
+
lines.shift();
|
|
41
|
+
}
|
|
42
|
+
onLine?.(line);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
loadExisting();
|
|
46
|
+
if (onLine && node_fs_1.default.existsSync(logFile)) {
|
|
47
|
+
watcher = node_fs_1.default.watch(node_path_1.default.dirname(logFile), () => {
|
|
48
|
+
if (!stopped)
|
|
49
|
+
pollNewLines();
|
|
50
|
+
});
|
|
51
|
+
const interval = setInterval(() => {
|
|
52
|
+
if (stopped) {
|
|
53
|
+
clearInterval(interval);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
pollNewLines();
|
|
57
|
+
}, 100);
|
|
58
|
+
watcher.on('close', () => clearInterval(interval));
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
readAll() {
|
|
62
|
+
return [...lines];
|
|
63
|
+
},
|
|
64
|
+
stop() {
|
|
65
|
+
stopped = true;
|
|
66
|
+
watcher?.close();
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=log-tailer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-tailer.js","sourceRoot":"","sources":["../../../../src/cli/tui/log-tailer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-tailer.test.d.ts","sourceRoot":"","sources":["../../../../src/cli/tui/log-tailer.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
7
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const vitest_1 = require("vitest");
|
|
10
|
+
const log_tailer_js_1 = require("./log-tailer.js");
|
|
11
|
+
(0, vitest_1.describe)('createLogTailer', () => {
|
|
12
|
+
let tempDir;
|
|
13
|
+
let logsDir;
|
|
14
|
+
let logFile;
|
|
15
|
+
(0, vitest_1.beforeEach)(() => {
|
|
16
|
+
tempDir = node_fs_1.default.mkdtempSync(node_path_1.default.join(node_os_1.default.tmpdir(), 'log-tailer-'));
|
|
17
|
+
logsDir = node_path_1.default.join(tempDir, 'logs');
|
|
18
|
+
node_fs_1.default.mkdirSync(logsDir, { recursive: true });
|
|
19
|
+
logFile = node_path_1.default.join(logsDir, 'activity.log');
|
|
20
|
+
});
|
|
21
|
+
(0, vitest_1.afterEach)(() => {
|
|
22
|
+
node_fs_1.default.rmSync(tempDir, { recursive: true, force: true });
|
|
23
|
+
});
|
|
24
|
+
(0, vitest_1.it)('reads existing log lines on start', () => {
|
|
25
|
+
node_fs_1.default.writeFileSync(logFile, 'line1\nline2\n');
|
|
26
|
+
const tailer = (0, log_tailer_js_1.createLogTailer)(tempDir);
|
|
27
|
+
const lines = tailer.readAll();
|
|
28
|
+
tailer.stop();
|
|
29
|
+
(0, vitest_1.expect)(lines).toEqual(['line1', 'line2']);
|
|
30
|
+
});
|
|
31
|
+
(0, vitest_1.it)('returns empty array when log file does not exist', () => {
|
|
32
|
+
const tailer = (0, log_tailer_js_1.createLogTailer)(tempDir);
|
|
33
|
+
const lines = tailer.readAll();
|
|
34
|
+
tailer.stop();
|
|
35
|
+
(0, vitest_1.expect)(lines).toEqual([]);
|
|
36
|
+
});
|
|
37
|
+
(0, vitest_1.it)('detects new lines appended after start', async () => {
|
|
38
|
+
node_fs_1.default.writeFileSync(logFile, '');
|
|
39
|
+
const received = [];
|
|
40
|
+
const tailer = (0, log_tailer_js_1.createLogTailer)(tempDir, (line) => received.push(line));
|
|
41
|
+
node_fs_1.default.appendFileSync(logFile, 'new-line\n');
|
|
42
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
43
|
+
tailer.stop();
|
|
44
|
+
(0, vitest_1.expect)(received).toEqual(['new-line']);
|
|
45
|
+
});
|
|
46
|
+
(0, vitest_1.it)('keeps only last N lines via maxLines option', () => {
|
|
47
|
+
node_fs_1.default.writeFileSync(logFile, 'a\nb\nc\nd\ne\n');
|
|
48
|
+
const tailer = (0, log_tailer_js_1.createLogTailer)(tempDir, undefined, { maxLines: 3 });
|
|
49
|
+
const lines = tailer.readAll();
|
|
50
|
+
tailer.stop();
|
|
51
|
+
(0, vitest_1.expect)(lines).toEqual(['c', 'd', 'e']);
|
|
52
|
+
});
|
|
53
|
+
(0, vitest_1.it)('stop prevents further callbacks', async () => {
|
|
54
|
+
node_fs_1.default.writeFileSync(logFile, '');
|
|
55
|
+
const received = [];
|
|
56
|
+
const tailer = (0, log_tailer_js_1.createLogTailer)(tempDir, (line) => received.push(line));
|
|
57
|
+
tailer.stop();
|
|
58
|
+
node_fs_1.default.appendFileSync(logFile, 'after-stop\n');
|
|
59
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
60
|
+
(0, vitest_1.expect)(received).toEqual([]);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
//# sourceMappingURL=log-tailer.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-tailer.test.js","sourceRoot":"","sources":["../../../../src/cli/tui/log-tailer.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screen.d.ts","sourceRoot":"","sources":["../../../../src/cli/tui/screen.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAuB3D"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.renderScreen = renderScreen;
|
|
4
|
+
const logger_js_1 = require("../../logger.js");
|
|
5
|
+
const banner_js_1 = require("./banner.js");
|
|
6
|
+
const log_color_js_1 = require("./log-color.js");
|
|
7
|
+
function renderScreen(options) {
|
|
8
|
+
const { logLines, cols, rows } = options;
|
|
9
|
+
const banner = (0, banner_js_1.renderBanner)();
|
|
10
|
+
const bannerLines = banner.split('\n');
|
|
11
|
+
const separator = `${logger_js_1.colors.dim}${'─'.repeat(Math.min(cols, 50))}${logger_js_1.colors.reset}`;
|
|
12
|
+
const header = `${logger_js_1.colors.dim} activity log${logger_js_1.colors.reset}`;
|
|
13
|
+
const headerHeight = bannerLines.length + 2;
|
|
14
|
+
const availableRows = Math.max(1, rows - headerHeight - 1);
|
|
15
|
+
const output = [...bannerLines, separator, header];
|
|
16
|
+
if (logLines.length === 0) {
|
|
17
|
+
output.push(`${logger_js_1.colors.dim} waiting for activity...${logger_js_1.colors.reset}`);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
const visible = logLines.slice(-availableRows);
|
|
21
|
+
for (const line of visible) {
|
|
22
|
+
output.push(` ${(0, log_color_js_1.colorizeLogLine)(line)}`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return output.join('\n');
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=screen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screen.js","sourceRoot":"","sources":["../../../../src/cli/tui/screen.ts"],"names":[],"mappings":";;AAUA,oCAuBC;AAjCD,+CAAyC;AACzC,2CAA2C;AAC3C,iDAAiD;AAQjD,SAAgB,YAAY,CAAC,OAAsB;IACjD,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IACzC,MAAM,MAAM,GAAG,IAAA,wBAAY,GAAE,CAAC;IAC9B,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAEvC,MAAM,SAAS,GAAG,GAAG,kBAAM,CAAC,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,kBAAM,CAAC,KAAK,EAAE,CAAC;IAClF,MAAM,MAAM,GAAG,GAAG,kBAAM,CAAC,GAAG,gBAAgB,kBAAM,CAAC,KAAK,EAAE,CAAC;IAE3D,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;IAC5C,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,YAAY,GAAG,CAAC,CAAC,CAAC;IAE3D,MAAM,MAAM,GAAa,CAAC,GAAG,WAAW,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IAE7D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,CAAC,IAAI,CAAC,GAAG,kBAAM,CAAC,GAAG,4BAA4B,kBAAM,CAAC,KAAK,EAAE,CAAC,CAAC;IACvE,CAAC;SAAM,CAAC;QACN,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC,CAAC;QAC/C,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;YAC3B,MAAM,CAAC,IAAI,CAAC,KAAK,IAAA,8BAAe,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screen.test.d.ts","sourceRoot":"","sources":["../../../../src/cli/tui/screen.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const screen_js_1 = require("./screen.js");
|
|
5
|
+
const ESC = String.fromCharCode(27);
|
|
6
|
+
const ANSI_PATTERN = new RegExp(`${ESC}\\[[0-9;]*m`, 'g');
|
|
7
|
+
function stripAnsi(str) {
|
|
8
|
+
return str.replace(ANSI_PATTERN, '');
|
|
9
|
+
}
|
|
10
|
+
(0, vitest_1.describe)('renderScreen', () => {
|
|
11
|
+
(0, vitest_1.it)('renders banner followed by log lines', () => {
|
|
12
|
+
const output = (0, screen_js_1.renderScreen)({ logLines: ['line-A', 'line-B'], cols: 80, rows: 24 });
|
|
13
|
+
const plain = stripAnsi(output);
|
|
14
|
+
(0, vitest_1.expect)({
|
|
15
|
+
hasBanner: plain.includes('█'),
|
|
16
|
+
containsLogA: plain.includes('line-A'),
|
|
17
|
+
containsLogB: plain.includes('line-B'),
|
|
18
|
+
}).toEqual({
|
|
19
|
+
hasBanner: true,
|
|
20
|
+
containsLogA: true,
|
|
21
|
+
containsLogB: true,
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
(0, vitest_1.it)('renders empty state when no log lines', () => {
|
|
25
|
+
const output = (0, screen_js_1.renderScreen)({ logLines: [], cols: 80, rows: 24 });
|
|
26
|
+
const plain = stripAnsi(output);
|
|
27
|
+
(0, vitest_1.expect)({
|
|
28
|
+
hasBanner: plain.includes('█'),
|
|
29
|
+
containsWaiting: plain.includes('waiting'),
|
|
30
|
+
}).toEqual({
|
|
31
|
+
hasBanner: true,
|
|
32
|
+
containsWaiting: true,
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
(0, vitest_1.it)('includes a separator between banner and logs', () => {
|
|
36
|
+
const output = (0, screen_js_1.renderScreen)({ logLines: ['test'], cols: 80, rows: 24 });
|
|
37
|
+
const plain = stripAnsi(output);
|
|
38
|
+
(0, vitest_1.expect)(plain.includes('─')).toBe(true);
|
|
39
|
+
});
|
|
40
|
+
(0, vitest_1.it)('truncates log lines to fit available rows', () => {
|
|
41
|
+
const manyLines = Array.from({ length: 50 }, (_, i) => `log-${i}`);
|
|
42
|
+
const output = (0, screen_js_1.renderScreen)({ logLines: manyLines, cols: 80, rows: 40 });
|
|
43
|
+
const plain = stripAnsi(output);
|
|
44
|
+
(0, vitest_1.expect)(plain.includes('log-49')).toBe(true);
|
|
45
|
+
(0, vitest_1.expect)(plain.includes('log-0')).toBe(false);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
//# sourceMappingURL=screen.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screen.test.js","sourceRoot":"","sources":["../../../../src/cli/tui/screen.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface TuiOptions {
|
|
2
|
+
dir: string;
|
|
3
|
+
write: (s: string) => void;
|
|
4
|
+
cols: number;
|
|
5
|
+
rows: number;
|
|
6
|
+
}
|
|
7
|
+
export interface Tui {
|
|
8
|
+
render(): void;
|
|
9
|
+
resize(cols: number, rows: number): void;
|
|
10
|
+
stop(): void;
|
|
11
|
+
isStopped(): boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare function createTui(options: TuiOptions): Tui;
|
|
14
|
+
//# sourceMappingURL=tui.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../../../../src/cli/tui/tui.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,GAAG;IAClB,MAAM,IAAI,IAAI,CAAC;IACf,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,IAAI,IAAI,IAAI,CAAC;IACb,SAAS,IAAI,OAAO,CAAC;CACtB;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,UAAU,GAAG,GAAG,CAkClD"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createTui = createTui;
|
|
4
|
+
const log_tailer_js_1 = require("./log-tailer.js");
|
|
5
|
+
const screen_js_1 = require("./screen.js");
|
|
6
|
+
function createTui(options) {
|
|
7
|
+
const { dir, write } = options;
|
|
8
|
+
const ketchupDir = `${dir}/.ketchup`;
|
|
9
|
+
let currentCols = options.cols;
|
|
10
|
+
let currentRows = options.rows;
|
|
11
|
+
let stopped = false;
|
|
12
|
+
const tailer = (0, log_tailer_js_1.createLogTailer)(ketchupDir, () => {
|
|
13
|
+
if (!stopped)
|
|
14
|
+
render();
|
|
15
|
+
});
|
|
16
|
+
function render() {
|
|
17
|
+
const logLines = tailer.readAll();
|
|
18
|
+
const screen = (0, screen_js_1.renderScreen)({ logLines, cols: currentCols, rows: currentRows });
|
|
19
|
+
write(`\x1b[2J\x1b[H${screen}`);
|
|
20
|
+
}
|
|
21
|
+
function resize(cols, rows) {
|
|
22
|
+
currentCols = cols;
|
|
23
|
+
currentRows = rows;
|
|
24
|
+
if (!stopped)
|
|
25
|
+
render();
|
|
26
|
+
}
|
|
27
|
+
function stop() {
|
|
28
|
+
stopped = true;
|
|
29
|
+
tailer.stop();
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
render,
|
|
33
|
+
resize,
|
|
34
|
+
stop,
|
|
35
|
+
isStopped: () => stopped,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=tui.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui.js","sourceRoot":"","sources":["../../../../src/cli/tui/tui.ts"],"names":[],"mappings":";;AAiBA,8BAkCC;AAnDD,mDAAkD;AAClD,2CAA2C;AAgB3C,SAAgB,SAAS,CAAC,OAAmB;IAC3C,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IAC/B,MAAM,UAAU,GAAG,GAAG,GAAG,WAAW,CAAC;IACrC,IAAI,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAC/B,IAAI,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAC/B,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,MAAM,MAAM,GAAG,IAAA,+BAAe,EAAC,UAAU,EAAE,GAAG,EAAE;QAC9C,IAAI,CAAC,OAAO;YAAE,MAAM,EAAE,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,SAAS,MAAM;QACb,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,IAAA,wBAAY,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;QAChF,KAAK,CAAC,gBAAgB,MAAM,EAAE,CAAC,CAAC;IAClC,CAAC;IAED,SAAS,MAAM,CAAC,IAAY,EAAE,IAAY;QACxC,WAAW,GAAG,IAAI,CAAC;QACnB,WAAW,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,OAAO;YAAE,MAAM,EAAE,CAAC;IACzB,CAAC;IAED,SAAS,IAAI;QACX,OAAO,GAAG,IAAI,CAAC;QACf,MAAM,CAAC,IAAI,EAAE,CAAC;IAChB,CAAC;IAED,OAAO;QACL,MAAM;QACN,MAAM;QACN,IAAI;QACJ,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO;KACzB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui.test.d.ts","sourceRoot":"","sources":["../../../../src/cli/tui/tui.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
7
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const vitest_1 = require("vitest");
|
|
10
|
+
const tui_js_1 = require("./tui.js");
|
|
11
|
+
(0, vitest_1.describe)('createTui', () => {
|
|
12
|
+
let tempDir;
|
|
13
|
+
(0, vitest_1.beforeEach)(() => {
|
|
14
|
+
tempDir = node_fs_1.default.mkdtempSync(node_path_1.default.join(node_os_1.default.tmpdir(), 'tui-'));
|
|
15
|
+
const ketchupDir = node_path_1.default.join(tempDir, '.ketchup');
|
|
16
|
+
node_fs_1.default.mkdirSync(node_path_1.default.join(ketchupDir, 'logs'), { recursive: true });
|
|
17
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(ketchupDir, '.claude.hooks.json'), '{}');
|
|
18
|
+
});
|
|
19
|
+
(0, vitest_1.afterEach)(() => {
|
|
20
|
+
node_fs_1.default.rmSync(tempDir, { recursive: true, force: true });
|
|
21
|
+
});
|
|
22
|
+
(0, vitest_1.it)('renders screen content with banner and log section', () => {
|
|
23
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(tempDir, '.ketchup', 'logs', 'activity.log'), 'test-entry\n');
|
|
24
|
+
const writes = [];
|
|
25
|
+
const tui = (0, tui_js_1.createTui)({
|
|
26
|
+
dir: tempDir,
|
|
27
|
+
write: (s) => writes.push(s),
|
|
28
|
+
cols: 80,
|
|
29
|
+
rows: 24,
|
|
30
|
+
});
|
|
31
|
+
tui.render();
|
|
32
|
+
tui.stop();
|
|
33
|
+
const output = writes.join('');
|
|
34
|
+
(0, vitest_1.expect)({
|
|
35
|
+
containsEntry: output.includes('test-entry'),
|
|
36
|
+
hasBanner: output.includes('█'),
|
|
37
|
+
hasContent: output.length > 0,
|
|
38
|
+
}).toEqual({
|
|
39
|
+
containsEntry: true,
|
|
40
|
+
hasBanner: true,
|
|
41
|
+
hasContent: true,
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
(0, vitest_1.it)('renders waiting message when no logs exist', () => {
|
|
45
|
+
const writes = [];
|
|
46
|
+
const tui = (0, tui_js_1.createTui)({
|
|
47
|
+
dir: tempDir,
|
|
48
|
+
write: (s) => writes.push(s),
|
|
49
|
+
cols: 80,
|
|
50
|
+
rows: 24,
|
|
51
|
+
});
|
|
52
|
+
tui.render();
|
|
53
|
+
tui.stop();
|
|
54
|
+
const output = writes.join('');
|
|
55
|
+
(0, vitest_1.expect)(output.includes('waiting')).toBe(true);
|
|
56
|
+
});
|
|
57
|
+
(0, vitest_1.it)('resize updates dimensions and re-renders', () => {
|
|
58
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(tempDir, '.ketchup', 'logs', 'activity.log'), 'resize-test\n');
|
|
59
|
+
const writes = [];
|
|
60
|
+
const tui = (0, tui_js_1.createTui)({
|
|
61
|
+
dir: tempDir,
|
|
62
|
+
write: (s) => writes.push(s),
|
|
63
|
+
cols: 80,
|
|
64
|
+
rows: 24,
|
|
65
|
+
});
|
|
66
|
+
writes.length = 0;
|
|
67
|
+
tui.resize(120, 40);
|
|
68
|
+
tui.stop();
|
|
69
|
+
(0, vitest_1.expect)({
|
|
70
|
+
reRendered: writes.length > 0,
|
|
71
|
+
containsEntry: writes.join('').includes('resize-test'),
|
|
72
|
+
}).toEqual({
|
|
73
|
+
reRendered: true,
|
|
74
|
+
containsEntry: true,
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
(0, vitest_1.it)('stop cleans up resources', () => {
|
|
78
|
+
const tui = (0, tui_js_1.createTui)({
|
|
79
|
+
dir: tempDir,
|
|
80
|
+
write: () => { },
|
|
81
|
+
cols: 80,
|
|
82
|
+
rows: 24,
|
|
83
|
+
});
|
|
84
|
+
tui.stop();
|
|
85
|
+
(0, vitest_1.expect)(tui.isStopped()).toBe(true);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
//# sourceMappingURL=tui.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui.test.js","sourceRoot":"","sources":["../../../../src/cli/tui/tui.test.ts"],"names":[],"mappings":"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"}
|