vibecodingmachine-cli 1.0.5 → 1.0.6
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/.allnightai/REQUIREMENTS.md +11 -11
- package/.allnightai/temp/auto-status.json +6 -0
- package/.env +7 -0
- package/.eslintrc.js +16 -16
- package/README.md +85 -85
- package/bin/vibecodingmachine.js +274 -274
- package/jest.config.js +8 -8
- package/logs/audit/2025-11-07.jsonl +2 -2
- package/package.json +62 -62
- package/scripts/README.md +128 -128
- package/scripts/auto-start-wrapper.sh +92 -92
- package/scripts/postinstall.js +81 -81
- package/src/commands/auth.js +96 -96
- package/src/commands/auto-direct.js +1748 -1748
- package/src/commands/auto.js +4692 -4692
- package/src/commands/auto.js.bak +710 -710
- package/src/commands/ide.js +70 -70
- package/src/commands/repo.js +159 -159
- package/src/commands/requirements.js +161 -161
- package/src/commands/setup.js +91 -91
- package/src/commands/status.js +88 -88
- package/src/index.js +5 -5
- package/src/utils/auth.js +571 -577
- package/src/utils/auto-mode-ansi-ui.js +238 -238
- package/src/utils/auto-mode-simple-ui.js +161 -161
- package/src/utils/auto-mode-ui.js.bak.blessed +207 -207
- package/src/utils/auto-mode.js +65 -65
- package/src/utils/config.js +64 -64
- package/src/utils/interactive.js +3616 -3616
- package/src/utils/keyboard-handler.js +153 -152
- package/src/utils/logger.js +4 -4
- package/src/utils/persistent-header.js +116 -116
- package/src/utils/provider-registry.js +128 -128
- package/src/utils/status-card.js +120 -120
- package/src/utils/stdout-interceptor.js +127 -127
- package/tests/auto-mode.test.js +37 -37
- package/tests/config.test.js +34 -34
|
@@ -1,152 +1,153 @@
|
|
|
1
|
-
const readline = require('readline');
|
|
2
|
-
const chalk = require('chalk');
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Lightweight keyboard handler for Auto Mode
|
|
6
|
-
* Listens for 'x' key and Ctrl+C without interfering with child process stdin
|
|
7
|
-
*/
|
|
8
|
-
class KeyboardHandler {
|
|
9
|
-
constructor(options = {}) {
|
|
10
|
-
this.onExit = options.onExit;
|
|
11
|
-
this.isActive = false;
|
|
12
|
-
this.exitConfirmMode = false;
|
|
13
|
-
this.keypressHandler = null;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Start listening for keyboard input
|
|
18
|
-
*/
|
|
19
|
-
start() {
|
|
20
|
-
if (this.isActive) return;
|
|
21
|
-
|
|
22
|
-
this.isActive = true;
|
|
23
|
-
|
|
24
|
-
// Set up keypress events on stdin
|
|
25
|
-
readline.emitKeypressEvents(process.stdin);
|
|
26
|
-
|
|
27
|
-
// Only set raw mode if stdin is a TTY
|
|
28
|
-
if (process.stdin.isTTY && !process.stdin.isRaw) {
|
|
29
|
-
process.stdin.setRawMode(true);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Create keypress handler
|
|
33
|
-
this.keypressHandler = (str, key) => {
|
|
34
|
-
if (!key) return;
|
|
35
|
-
|
|
36
|
-
// Handle Ctrl+C - immediate exit
|
|
37
|
-
if (key.ctrl && key.name === 'c') {
|
|
38
|
-
this.handleImmediateExit();
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Handle 'x' key - show confirmation
|
|
43
|
-
if (key.name === 'x' && !this.exitConfirmMode) {
|
|
44
|
-
this.showExitConfirmation();
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// In confirmation mode, handle y/n
|
|
49
|
-
if (this.exitConfirmMode) {
|
|
50
|
-
if (key.name === 'y') {
|
|
51
|
-
this.confirmExit();
|
|
52
|
-
} else if (key.name === 'n' || key.name === 'escape') {
|
|
53
|
-
this.cancelExit();
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
// Attach handler
|
|
59
|
-
process.stdin.on('keypress', this.keypressHandler);
|
|
60
|
-
process.stdin.resume();
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Stop listening for keyboard input
|
|
65
|
-
*/
|
|
66
|
-
stop() {
|
|
67
|
-
if (!this.isActive) return;
|
|
68
|
-
|
|
69
|
-
this.isActive = false;
|
|
70
|
-
|
|
71
|
-
// Remove keypress handler
|
|
72
|
-
if (this.keypressHandler) {
|
|
73
|
-
process.stdin.removeListener('keypress', this.keypressHandler);
|
|
74
|
-
this.keypressHandler = null;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Restore stdin to normal mode
|
|
78
|
-
if (process.stdin.isTTY && process.stdin.isRaw) {
|
|
79
|
-
process.stdin.setRawMode(false);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
process.stdin.pause();
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
showExitConfirmation() {
|
|
86
|
-
this.exitConfirmMode = true;
|
|
87
|
-
console.log('\n' + chalk.yellow('─'.repeat(60)));
|
|
88
|
-
console.log(chalk.yellow.bold(' Exit Auto Mode?'));
|
|
89
|
-
console.log(chalk.yellow(' Press ') + chalk.white.bold('y') + chalk.yellow(' to exit, ') + chalk.white.bold('n') + chalk.yellow(' to cancel'));
|
|
90
|
-
console.log(chalk.yellow('─'.repeat(60)) + '\n');
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
cancelExit() {
|
|
94
|
-
this.exitConfirmMode = false;
|
|
95
|
-
console.log(chalk.gray(' Cancelled - continuing Auto Mode...\n'));
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
confirmExit() {
|
|
99
|
-
this.exitConfirmMode = false;
|
|
100
|
-
this.stop();
|
|
101
|
-
|
|
102
|
-
console.log(chalk.green(' Exiting Auto Mode...\n'));
|
|
103
|
-
|
|
104
|
-
if (this.onExit) {
|
|
105
|
-
this.onExit();
|
|
106
|
-
} else {
|
|
107
|
-
process.exit(0);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
handleImmediateExit() {
|
|
112
|
-
console.log(chalk.yellow('\n Ctrl+C detected - force exiting...\n'));
|
|
113
|
-
|
|
114
|
-
// Call onExit callback first if provided (for cleanup)
|
|
115
|
-
if (this.onExit) {
|
|
116
|
-
try {
|
|
117
|
-
this.onExit();
|
|
118
|
-
} catch (err) {
|
|
119
|
-
// Ignore errors during cleanup
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Force exit immediately - don't wait for async cleanup
|
|
124
|
-
// This is critical because the event loop may be blocked on child processes
|
|
125
|
-
this.stop();
|
|
126
|
-
process.exit(0);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Create a keyboard handler for Auto Mode
|
|
132
|
-
* @param {object} options - Configuration options
|
|
133
|
-
* @param {function} options.onExit - Callback when user exits
|
|
134
|
-
* @returns {KeyboardHandler}
|
|
135
|
-
*/
|
|
136
|
-
function createKeyboardHandler(options = {}) {
|
|
137
|
-
return new KeyboardHandler(options);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
module.exports = {
|
|
141
|
-
KeyboardHandler,
|
|
142
|
-
createKeyboardHandler
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
1
|
+
const readline = require('readline');
|
|
2
|
+
const chalk = require('chalk');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Lightweight keyboard handler for Auto Mode
|
|
6
|
+
* Listens for 'x' key and Ctrl+C without interfering with child process stdin
|
|
7
|
+
*/
|
|
8
|
+
class KeyboardHandler {
|
|
9
|
+
constructor(options = {}) {
|
|
10
|
+
this.onExit = options.onExit;
|
|
11
|
+
this.isActive = false;
|
|
12
|
+
this.exitConfirmMode = false;
|
|
13
|
+
this.keypressHandler = null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Start listening for keyboard input
|
|
18
|
+
*/
|
|
19
|
+
start() {
|
|
20
|
+
if (this.isActive) return;
|
|
21
|
+
|
|
22
|
+
this.isActive = true;
|
|
23
|
+
|
|
24
|
+
// Set up keypress events on stdin
|
|
25
|
+
readline.emitKeypressEvents(process.stdin);
|
|
26
|
+
|
|
27
|
+
// Only set raw mode if stdin is a TTY
|
|
28
|
+
if (process.stdin.isTTY && !process.stdin.isRaw) {
|
|
29
|
+
process.stdin.setRawMode(true);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Create keypress handler
|
|
33
|
+
this.keypressHandler = (str, key) => {
|
|
34
|
+
if (!key) return;
|
|
35
|
+
|
|
36
|
+
// Handle Ctrl+C - immediate exit
|
|
37
|
+
if (key.ctrl && key.name === 'c') {
|
|
38
|
+
this.handleImmediateExit();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Handle 'x' key - show confirmation
|
|
43
|
+
if (key.name === 'x' && !this.exitConfirmMode) {
|
|
44
|
+
this.showExitConfirmation();
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// In confirmation mode, handle y/n
|
|
49
|
+
if (this.exitConfirmMode) {
|
|
50
|
+
if (key.name === 'y') {
|
|
51
|
+
this.confirmExit();
|
|
52
|
+
} else if (key.name === 'n' || key.name === 'escape') {
|
|
53
|
+
this.cancelExit();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// Attach handler
|
|
59
|
+
process.stdin.on('keypress', this.keypressHandler);
|
|
60
|
+
process.stdin.resume();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Stop listening for keyboard input
|
|
65
|
+
*/
|
|
66
|
+
stop() {
|
|
67
|
+
if (!this.isActive) return;
|
|
68
|
+
|
|
69
|
+
this.isActive = false;
|
|
70
|
+
|
|
71
|
+
// Remove keypress handler
|
|
72
|
+
if (this.keypressHandler) {
|
|
73
|
+
process.stdin.removeListener('keypress', this.keypressHandler);
|
|
74
|
+
this.keypressHandler = null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Restore stdin to normal mode
|
|
78
|
+
if (process.stdin.isTTY && process.stdin.isRaw) {
|
|
79
|
+
process.stdin.setRawMode(false);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
process.stdin.pause();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
showExitConfirmation() {
|
|
86
|
+
this.exitConfirmMode = true;
|
|
87
|
+
console.log('\n' + chalk.yellow('─'.repeat(60)));
|
|
88
|
+
console.log(chalk.yellow.bold(' Exit Auto Mode?'));
|
|
89
|
+
console.log(chalk.yellow(' Press ') + chalk.white.bold('y') + chalk.yellow(' to exit, ') + chalk.white.bold('n') + chalk.yellow(' to cancel'));
|
|
90
|
+
console.log(chalk.yellow('─'.repeat(60)) + '\n');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
cancelExit() {
|
|
94
|
+
this.exitConfirmMode = false;
|
|
95
|
+
console.log(chalk.gray(' Cancelled - continuing Auto Mode...\n'));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
confirmExit() {
|
|
99
|
+
this.exitConfirmMode = false;
|
|
100
|
+
this.stop();
|
|
101
|
+
|
|
102
|
+
console.log(chalk.green(' Exiting Auto Mode...\n'));
|
|
103
|
+
|
|
104
|
+
if (this.onExit) {
|
|
105
|
+
this.onExit();
|
|
106
|
+
} else {
|
|
107
|
+
process.exit(0);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
handleImmediateExit() {
|
|
112
|
+
console.log(chalk.yellow('\n Ctrl+C detected - force exiting...\n'));
|
|
113
|
+
|
|
114
|
+
// Call onExit callback first if provided (for cleanup)
|
|
115
|
+
if (this.onExit) {
|
|
116
|
+
try {
|
|
117
|
+
this.onExit();
|
|
118
|
+
} catch (err) {
|
|
119
|
+
// Ignore errors during cleanup
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Force exit immediately - don't wait for async cleanup
|
|
124
|
+
// This is critical because the event loop may be blocked on child processes
|
|
125
|
+
this.stop();
|
|
126
|
+
process.exit(0);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Create a keyboard handler for Auto Mode
|
|
132
|
+
* @param {object} options - Configuration options
|
|
133
|
+
* @param {function} options.onExit - Callback when user exits
|
|
134
|
+
* @returns {KeyboardHandler}
|
|
135
|
+
*/
|
|
136
|
+
function createKeyboardHandler(options = {}) {
|
|
137
|
+
return new KeyboardHandler(options);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
module.exports = {
|
|
141
|
+
KeyboardHandler,
|
|
142
|
+
createKeyboardHandler
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
|
package/src/utils/logger.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { logger } = require('vibecodingmachine-core');
|
|
2
|
-
|
|
3
|
-
// Re-export the logger from core for CLI use
|
|
4
|
-
module.exports = logger;
|
|
1
|
+
const { logger } = require('vibecodingmachine-core');
|
|
2
|
+
|
|
3
|
+
// Re-export the logger from core for CLI use
|
|
4
|
+
module.exports = logger;
|
|
@@ -1,116 +1,116 @@
|
|
|
1
|
-
const chalk = require('chalk');
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Simple persistent header that stays at top while content scrolls below
|
|
5
|
-
* Uses ANSI terminal control codes instead of blessed
|
|
6
|
-
*/
|
|
7
|
-
class PersistentHeader {
|
|
8
|
-
constructor(lines = 10) {
|
|
9
|
-
this.headerLines = lines;
|
|
10
|
-
this.headerContent = '';
|
|
11
|
-
this.isActive = false;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Initialize the header by saving cursor and creating space
|
|
16
|
-
*/
|
|
17
|
-
start() {
|
|
18
|
-
if (this.isActive) return;
|
|
19
|
-
this.isActive = true;
|
|
20
|
-
|
|
21
|
-
// Clear screen and move to top
|
|
22
|
-
process.stdout.write('\x1B[2J\x1B[H');
|
|
23
|
-
|
|
24
|
-
// Create space for header by printing empty lines
|
|
25
|
-
for (let i = 0; i < this.headerLines; i++) {
|
|
26
|
-
process.stdout.write('\n');
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Update the header content
|
|
32
|
-
* @param {string} content - New header content
|
|
33
|
-
*/
|
|
34
|
-
update(content) {
|
|
35
|
-
if (!this.isActive) return;
|
|
36
|
-
|
|
37
|
-
this.headerContent = content;
|
|
38
|
-
|
|
39
|
-
// Save current cursor position
|
|
40
|
-
process.stdout.write('\x1B[s');
|
|
41
|
-
|
|
42
|
-
// Move to top of screen
|
|
43
|
-
process.stdout.write('\x1B[H');
|
|
44
|
-
|
|
45
|
-
// Clear the header area
|
|
46
|
-
for (let i = 0; i < this.headerLines; i++) {
|
|
47
|
-
process.stdout.write('\x1B[2K'); // Clear line
|
|
48
|
-
if (i < this.headerLines - 1) process.stdout.write('\n');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Move back to top
|
|
52
|
-
process.stdout.write('\x1B[H');
|
|
53
|
-
|
|
54
|
-
// Write header content
|
|
55
|
-
process.stdout.write(content);
|
|
56
|
-
|
|
57
|
-
// Restore cursor position
|
|
58
|
-
process.stdout.write('\x1B[u');
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Stop the persistent header
|
|
63
|
-
*/
|
|
64
|
-
stop() {
|
|
65
|
-
if (!this.isActive) return;
|
|
66
|
-
this.isActive = false;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Format auto mode header
|
|
72
|
-
*/
|
|
73
|
-
function formatAutoModeHeader(status) {
|
|
74
|
-
const {
|
|
75
|
-
requirement = 'No requirement',
|
|
76
|
-
step = 'PREPARE',
|
|
77
|
-
chatCount = 0,
|
|
78
|
-
maxChats = null,
|
|
79
|
-
progress = 0,
|
|
80
|
-
repoPath = '',
|
|
81
|
-
hostname = ''
|
|
82
|
-
} = status;
|
|
83
|
-
|
|
84
|
-
const stepColors = {
|
|
85
|
-
'PREPARE': chalk.cyan,
|
|
86
|
-
'ACT': chalk.yellow,
|
|
87
|
-
'CLEAN UP': chalk.magenta,
|
|
88
|
-
'VERIFY': chalk.blue,
|
|
89
|
-
'DONE': chalk.green,
|
|
90
|
-
'UNKNOWN': chalk.gray
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
const stepColor = stepColors[step] || chalk.gray;
|
|
94
|
-
|
|
95
|
-
const chatDisplay = maxChats
|
|
96
|
-
? `Chat ${chatCount}/${maxChats}`
|
|
97
|
-
: `Chat ${chatCount} (unlimited)`;
|
|
98
|
-
|
|
99
|
-
const progressBar = chalk.green('█'.repeat(Math.floor(progress / 5))) +
|
|
100
|
-
chalk.gray('░'.repeat(20 - Math.floor(progress / 5)));
|
|
101
|
-
|
|
102
|
-
return `${chalk.cyan('━'.repeat(80))}
|
|
103
|
-
${chalk.bold.cyan(' VibeCodingMachine Auto Mode')} ${chalk.gray('- Press Ctrl+C to stop')}
|
|
104
|
-
${chalk.cyan('━'.repeat(80))}
|
|
105
|
-
${chalk.bold(' Requirement:')} ${requirement.substring(0, 60)}
|
|
106
|
-
${chalk.bold(' Status:')} ${stepColor(step)} ${chalk.bold('Progress:')} ${progressBar} ${progress}%
|
|
107
|
-
${chalk.bold(' Chats:')} ${chatDisplay}
|
|
108
|
-
${chalk.cyan('━'.repeat(80))}
|
|
109
|
-
|
|
110
|
-
`;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
module.exports = {
|
|
114
|
-
PersistentHeader,
|
|
115
|
-
formatAutoModeHeader
|
|
116
|
-
};
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Simple persistent header that stays at top while content scrolls below
|
|
5
|
+
* Uses ANSI terminal control codes instead of blessed
|
|
6
|
+
*/
|
|
7
|
+
class PersistentHeader {
|
|
8
|
+
constructor(lines = 10) {
|
|
9
|
+
this.headerLines = lines;
|
|
10
|
+
this.headerContent = '';
|
|
11
|
+
this.isActive = false;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Initialize the header by saving cursor and creating space
|
|
16
|
+
*/
|
|
17
|
+
start() {
|
|
18
|
+
if (this.isActive) return;
|
|
19
|
+
this.isActive = true;
|
|
20
|
+
|
|
21
|
+
// Clear screen and move to top
|
|
22
|
+
process.stdout.write('\x1B[2J\x1B[H');
|
|
23
|
+
|
|
24
|
+
// Create space for header by printing empty lines
|
|
25
|
+
for (let i = 0; i < this.headerLines; i++) {
|
|
26
|
+
process.stdout.write('\n');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Update the header content
|
|
32
|
+
* @param {string} content - New header content
|
|
33
|
+
*/
|
|
34
|
+
update(content) {
|
|
35
|
+
if (!this.isActive) return;
|
|
36
|
+
|
|
37
|
+
this.headerContent = content;
|
|
38
|
+
|
|
39
|
+
// Save current cursor position
|
|
40
|
+
process.stdout.write('\x1B[s');
|
|
41
|
+
|
|
42
|
+
// Move to top of screen
|
|
43
|
+
process.stdout.write('\x1B[H');
|
|
44
|
+
|
|
45
|
+
// Clear the header area
|
|
46
|
+
for (let i = 0; i < this.headerLines; i++) {
|
|
47
|
+
process.stdout.write('\x1B[2K'); // Clear line
|
|
48
|
+
if (i < this.headerLines - 1) process.stdout.write('\n');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Move back to top
|
|
52
|
+
process.stdout.write('\x1B[H');
|
|
53
|
+
|
|
54
|
+
// Write header content
|
|
55
|
+
process.stdout.write(content);
|
|
56
|
+
|
|
57
|
+
// Restore cursor position
|
|
58
|
+
process.stdout.write('\x1B[u');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Stop the persistent header
|
|
63
|
+
*/
|
|
64
|
+
stop() {
|
|
65
|
+
if (!this.isActive) return;
|
|
66
|
+
this.isActive = false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Format auto mode header
|
|
72
|
+
*/
|
|
73
|
+
function formatAutoModeHeader(status) {
|
|
74
|
+
const {
|
|
75
|
+
requirement = 'No requirement',
|
|
76
|
+
step = 'PREPARE',
|
|
77
|
+
chatCount = 0,
|
|
78
|
+
maxChats = null,
|
|
79
|
+
progress = 0,
|
|
80
|
+
repoPath = '',
|
|
81
|
+
hostname = ''
|
|
82
|
+
} = status;
|
|
83
|
+
|
|
84
|
+
const stepColors = {
|
|
85
|
+
'PREPARE': chalk.cyan,
|
|
86
|
+
'ACT': chalk.yellow,
|
|
87
|
+
'CLEAN UP': chalk.magenta,
|
|
88
|
+
'VERIFY': chalk.blue,
|
|
89
|
+
'DONE': chalk.green,
|
|
90
|
+
'UNKNOWN': chalk.gray
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const stepColor = stepColors[step] || chalk.gray;
|
|
94
|
+
|
|
95
|
+
const chatDisplay = maxChats
|
|
96
|
+
? `Chat ${chatCount}/${maxChats}`
|
|
97
|
+
: `Chat ${chatCount} (unlimited)`;
|
|
98
|
+
|
|
99
|
+
const progressBar = chalk.green('█'.repeat(Math.floor(progress / 5))) +
|
|
100
|
+
chalk.gray('░'.repeat(20 - Math.floor(progress / 5)));
|
|
101
|
+
|
|
102
|
+
return `${chalk.cyan('━'.repeat(80))}
|
|
103
|
+
${chalk.bold.cyan(' VibeCodingMachine Auto Mode')} ${chalk.gray('- Press Ctrl+C to stop')}
|
|
104
|
+
${chalk.cyan('━'.repeat(80))}
|
|
105
|
+
${chalk.bold(' Requirement:')} ${requirement.substring(0, 60)}
|
|
106
|
+
${chalk.bold(' Status:')} ${stepColor(step)} ${chalk.bold('Progress:')} ${progressBar} ${progress}%
|
|
107
|
+
${chalk.bold(' Chats:')} ${chatDisplay}
|
|
108
|
+
${chalk.cyan('━'.repeat(80))}
|
|
109
|
+
|
|
110
|
+
`;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
module.exports = {
|
|
114
|
+
PersistentHeader,
|
|
115
|
+
formatAutoModeHeader
|
|
116
|
+
};
|