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,207 +1,207 @@
|
|
|
1
|
-
const blessed = require('blessed');
|
|
2
|
-
const chalk = require('chalk');
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Create and display a blessed-based UI for Auto Mode
|
|
6
|
-
* Shows: persistent menu header, status card, and scrolling output
|
|
7
|
-
* @param {object} options - UI configuration
|
|
8
|
-
* @param {string} options.menuContent - Menu content to display in header
|
|
9
|
-
* @param {function} options.onExit - Callback when user presses Ctrl+C or q
|
|
10
|
-
* @returns {object} UI interface with methods to update status and append output
|
|
11
|
-
*/
|
|
12
|
-
function createAutoModeUI(options = {}) {
|
|
13
|
-
const { menuContent = '', onExit } = options;
|
|
14
|
-
|
|
15
|
-
// Create screen
|
|
16
|
-
const screen = blessed.screen({
|
|
17
|
-
smartCSR: true,
|
|
18
|
-
title: 'AllNightAI Auto Mode',
|
|
19
|
-
fullUnicode: true,
|
|
20
|
-
forceUnicode: true
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
// Clear screen and render immediately
|
|
24
|
-
screen.clearRegion(0, screen.width, 0, screen.height);
|
|
25
|
-
|
|
26
|
-
// Header box (menu) - use fixed height instead of shrink
|
|
27
|
-
const headerHeight = 11; // Fixed height for header
|
|
28
|
-
const header = blessed.box({
|
|
29
|
-
top: 0,
|
|
30
|
-
left: 0,
|
|
31
|
-
width: '100%',
|
|
32
|
-
height: headerHeight,
|
|
33
|
-
content: menuContent,
|
|
34
|
-
tags: true,
|
|
35
|
-
border: {
|
|
36
|
-
type: 'line'
|
|
37
|
-
},
|
|
38
|
-
style: {
|
|
39
|
-
border: {
|
|
40
|
-
fg: 'cyan'
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
// Status card (purple/magenta border like GUI)
|
|
46
|
-
const statusCardHeight = 12;
|
|
47
|
-
const statusCard = blessed.box({
|
|
48
|
-
top: headerHeight,
|
|
49
|
-
left: 0,
|
|
50
|
-
width: '100%',
|
|
51
|
-
height: statusCardHeight,
|
|
52
|
-
tags: true,
|
|
53
|
-
border: {
|
|
54
|
-
type: 'round'
|
|
55
|
-
},
|
|
56
|
-
style: {
|
|
57
|
-
border: {
|
|
58
|
-
fg: 'magenta'
|
|
59
|
-
}
|
|
60
|
-
},
|
|
61
|
-
label: ' Auto Mode Status '
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
// Output log (scrollable)
|
|
65
|
-
const totalHeaderHeight = headerHeight + statusCardHeight;
|
|
66
|
-
const outputLog = blessed.log({
|
|
67
|
-
top: totalHeaderHeight,
|
|
68
|
-
left: 0,
|
|
69
|
-
width: '100%',
|
|
70
|
-
height: `100%-${totalHeaderHeight}`,
|
|
71
|
-
tags: true,
|
|
72
|
-
border: {
|
|
73
|
-
type: 'line'
|
|
74
|
-
},
|
|
75
|
-
style: {
|
|
76
|
-
border: {
|
|
77
|
-
fg: 'green'
|
|
78
|
-
}
|
|
79
|
-
},
|
|
80
|
-
label: ' Aider Output ',
|
|
81
|
-
scrollable: true,
|
|
82
|
-
alwaysScroll: true,
|
|
83
|
-
mouse: true,
|
|
84
|
-
keys: true,
|
|
85
|
-
vi: true,
|
|
86
|
-
scrollbar: {
|
|
87
|
-
ch: ' ',
|
|
88
|
-
track: {
|
|
89
|
-
bg: 'cyan'
|
|
90
|
-
},
|
|
91
|
-
style: {
|
|
92
|
-
inverse: true
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
// Append all elements to screen
|
|
98
|
-
screen.append(header);
|
|
99
|
-
screen.append(statusCard);
|
|
100
|
-
screen.append(outputLog);
|
|
101
|
-
|
|
102
|
-
// Focus the output log for scrolling
|
|
103
|
-
outputLog.focus();
|
|
104
|
-
|
|
105
|
-
// Key bindings
|
|
106
|
-
screen.key(['escape', 'q', 'C-c'], () => {
|
|
107
|
-
if (onExit) {
|
|
108
|
-
onExit();
|
|
109
|
-
}
|
|
110
|
-
screen.destroy();
|
|
111
|
-
process.exit(0);
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
// Initial render
|
|
115
|
-
screen.render();
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Update the status card with new status information
|
|
119
|
-
* @param {object} status - Status object
|
|
120
|
-
* @param {string} status.requirement - Current requirement
|
|
121
|
-
* @param {string} status.step - Current step (PREPARE, ACT, CLEAN UP, VERIFY, DONE)
|
|
122
|
-
* @param {number} status.chatCount - Current chat count
|
|
123
|
-
* @param {number|null} status.maxChats - Max chats or null for unlimited
|
|
124
|
-
* @param {number} status.progress - Progress percentage (0-100)
|
|
125
|
-
*/
|
|
126
|
-
function updateStatus(status) {
|
|
127
|
-
const {
|
|
128
|
-
requirement = 'No requirement loaded',
|
|
129
|
-
step = 'UNKNOWN',
|
|
130
|
-
chatCount = 0,
|
|
131
|
-
maxChats = null,
|
|
132
|
-
progress = 0
|
|
133
|
-
} = status;
|
|
134
|
-
|
|
135
|
-
// Step color mapping
|
|
136
|
-
const stepColors = {
|
|
137
|
-
'PREPARE': '{cyan-fg}',
|
|
138
|
-
'ACT': '{yellow-fg}',
|
|
139
|
-
'CLEAN UP': '{magenta-fg}',
|
|
140
|
-
'VERIFY': '{blue-fg}',
|
|
141
|
-
'DONE': '{green-fg}',
|
|
142
|
-
'UNKNOWN': '{gray-fg}'
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
const stepColor = stepColors[step] || '{gray-fg}';
|
|
146
|
-
|
|
147
|
-
// Progress bar
|
|
148
|
-
const barWidth = 40;
|
|
149
|
-
const filledWidth = Math.round((progress / 100) * barWidth);
|
|
150
|
-
const emptyWidth = barWidth - filledWidth;
|
|
151
|
-
const progressBar = '{green-fg}' + '█'.repeat(filledWidth) + '{/green-fg}' +
|
|
152
|
-
'{gray-fg}' + '░'.repeat(emptyWidth) + '{/gray-fg}';
|
|
153
|
-
|
|
154
|
-
// Chat counter
|
|
155
|
-
const chatDisplay = maxChats
|
|
156
|
-
? `Chat ${chatCount}/${maxChats}`
|
|
157
|
-
: `Chat ${chatCount} (unlimited)`;
|
|
158
|
-
|
|
159
|
-
// Build card content
|
|
160
|
-
const content = `
|
|
161
|
-
{bold}📋 Current Requirement{/bold}
|
|
162
|
-
|
|
163
|
-
${requirement.length > 70 ? requirement.substring(0, 67) + '...' : requirement}
|
|
164
|
-
|
|
165
|
-
{bold}🚦 Status:{/bold} ${stepColor}{bold}${step}{/bold}{/}
|
|
166
|
-
|
|
167
|
-
${progressBar} ${progress}%
|
|
168
|
-
|
|
169
|
-
{gray-fg}${chatDisplay}{/gray-fg}
|
|
170
|
-
`;
|
|
171
|
-
|
|
172
|
-
statusCard.setContent(content);
|
|
173
|
-
screen.render();
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Append a line to the output log
|
|
178
|
-
* @param {string} line - Line to append
|
|
179
|
-
*/
|
|
180
|
-
function appendOutput(line) {
|
|
181
|
-
outputLog.log(line);
|
|
182
|
-
screen.render();
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Clear the output log
|
|
187
|
-
*/
|
|
188
|
-
function clearOutput() {
|
|
189
|
-
outputLog.setContent('');
|
|
190
|
-
screen.render();
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
return {
|
|
194
|
-
screen,
|
|
195
|
-
header,
|
|
196
|
-
statusCard,
|
|
197
|
-
outputLog,
|
|
198
|
-
updateStatus,
|
|
199
|
-
appendOutput,
|
|
200
|
-
clearOutput,
|
|
201
|
-
destroy: () => screen.destroy()
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
module.exports = {
|
|
206
|
-
createAutoModeUI
|
|
207
|
-
};
|
|
1
|
+
const blessed = require('blessed');
|
|
2
|
+
const chalk = require('chalk');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Create and display a blessed-based UI for Auto Mode
|
|
6
|
+
* Shows: persistent menu header, status card, and scrolling output
|
|
7
|
+
* @param {object} options - UI configuration
|
|
8
|
+
* @param {string} options.menuContent - Menu content to display in header
|
|
9
|
+
* @param {function} options.onExit - Callback when user presses Ctrl+C or q
|
|
10
|
+
* @returns {object} UI interface with methods to update status and append output
|
|
11
|
+
*/
|
|
12
|
+
function createAutoModeUI(options = {}) {
|
|
13
|
+
const { menuContent = '', onExit } = options;
|
|
14
|
+
|
|
15
|
+
// Create screen
|
|
16
|
+
const screen = blessed.screen({
|
|
17
|
+
smartCSR: true,
|
|
18
|
+
title: 'AllNightAI Auto Mode',
|
|
19
|
+
fullUnicode: true,
|
|
20
|
+
forceUnicode: true
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// Clear screen and render immediately
|
|
24
|
+
screen.clearRegion(0, screen.width, 0, screen.height);
|
|
25
|
+
|
|
26
|
+
// Header box (menu) - use fixed height instead of shrink
|
|
27
|
+
const headerHeight = 11; // Fixed height for header
|
|
28
|
+
const header = blessed.box({
|
|
29
|
+
top: 0,
|
|
30
|
+
left: 0,
|
|
31
|
+
width: '100%',
|
|
32
|
+
height: headerHeight,
|
|
33
|
+
content: menuContent,
|
|
34
|
+
tags: true,
|
|
35
|
+
border: {
|
|
36
|
+
type: 'line'
|
|
37
|
+
},
|
|
38
|
+
style: {
|
|
39
|
+
border: {
|
|
40
|
+
fg: 'cyan'
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// Status card (purple/magenta border like GUI)
|
|
46
|
+
const statusCardHeight = 12;
|
|
47
|
+
const statusCard = blessed.box({
|
|
48
|
+
top: headerHeight,
|
|
49
|
+
left: 0,
|
|
50
|
+
width: '100%',
|
|
51
|
+
height: statusCardHeight,
|
|
52
|
+
tags: true,
|
|
53
|
+
border: {
|
|
54
|
+
type: 'round'
|
|
55
|
+
},
|
|
56
|
+
style: {
|
|
57
|
+
border: {
|
|
58
|
+
fg: 'magenta'
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
label: ' Auto Mode Status '
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Output log (scrollable)
|
|
65
|
+
const totalHeaderHeight = headerHeight + statusCardHeight;
|
|
66
|
+
const outputLog = blessed.log({
|
|
67
|
+
top: totalHeaderHeight,
|
|
68
|
+
left: 0,
|
|
69
|
+
width: '100%',
|
|
70
|
+
height: `100%-${totalHeaderHeight}`,
|
|
71
|
+
tags: true,
|
|
72
|
+
border: {
|
|
73
|
+
type: 'line'
|
|
74
|
+
},
|
|
75
|
+
style: {
|
|
76
|
+
border: {
|
|
77
|
+
fg: 'green'
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
label: ' Aider Output ',
|
|
81
|
+
scrollable: true,
|
|
82
|
+
alwaysScroll: true,
|
|
83
|
+
mouse: true,
|
|
84
|
+
keys: true,
|
|
85
|
+
vi: true,
|
|
86
|
+
scrollbar: {
|
|
87
|
+
ch: ' ',
|
|
88
|
+
track: {
|
|
89
|
+
bg: 'cyan'
|
|
90
|
+
},
|
|
91
|
+
style: {
|
|
92
|
+
inverse: true
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Append all elements to screen
|
|
98
|
+
screen.append(header);
|
|
99
|
+
screen.append(statusCard);
|
|
100
|
+
screen.append(outputLog);
|
|
101
|
+
|
|
102
|
+
// Focus the output log for scrolling
|
|
103
|
+
outputLog.focus();
|
|
104
|
+
|
|
105
|
+
// Key bindings
|
|
106
|
+
screen.key(['escape', 'q', 'C-c'], () => {
|
|
107
|
+
if (onExit) {
|
|
108
|
+
onExit();
|
|
109
|
+
}
|
|
110
|
+
screen.destroy();
|
|
111
|
+
process.exit(0);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// Initial render
|
|
115
|
+
screen.render();
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Update the status card with new status information
|
|
119
|
+
* @param {object} status - Status object
|
|
120
|
+
* @param {string} status.requirement - Current requirement
|
|
121
|
+
* @param {string} status.step - Current step (PREPARE, ACT, CLEAN UP, VERIFY, DONE)
|
|
122
|
+
* @param {number} status.chatCount - Current chat count
|
|
123
|
+
* @param {number|null} status.maxChats - Max chats or null for unlimited
|
|
124
|
+
* @param {number} status.progress - Progress percentage (0-100)
|
|
125
|
+
*/
|
|
126
|
+
function updateStatus(status) {
|
|
127
|
+
const {
|
|
128
|
+
requirement = 'No requirement loaded',
|
|
129
|
+
step = 'UNKNOWN',
|
|
130
|
+
chatCount = 0,
|
|
131
|
+
maxChats = null,
|
|
132
|
+
progress = 0
|
|
133
|
+
} = status;
|
|
134
|
+
|
|
135
|
+
// Step color mapping
|
|
136
|
+
const stepColors = {
|
|
137
|
+
'PREPARE': '{cyan-fg}',
|
|
138
|
+
'ACT': '{yellow-fg}',
|
|
139
|
+
'CLEAN UP': '{magenta-fg}',
|
|
140
|
+
'VERIFY': '{blue-fg}',
|
|
141
|
+
'DONE': '{green-fg}',
|
|
142
|
+
'UNKNOWN': '{gray-fg}'
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const stepColor = stepColors[step] || '{gray-fg}';
|
|
146
|
+
|
|
147
|
+
// Progress bar
|
|
148
|
+
const barWidth = 40;
|
|
149
|
+
const filledWidth = Math.round((progress / 100) * barWidth);
|
|
150
|
+
const emptyWidth = barWidth - filledWidth;
|
|
151
|
+
const progressBar = '{green-fg}' + '█'.repeat(filledWidth) + '{/green-fg}' +
|
|
152
|
+
'{gray-fg}' + '░'.repeat(emptyWidth) + '{/gray-fg}';
|
|
153
|
+
|
|
154
|
+
// Chat counter
|
|
155
|
+
const chatDisplay = maxChats
|
|
156
|
+
? `Chat ${chatCount}/${maxChats}`
|
|
157
|
+
: `Chat ${chatCount} (unlimited)`;
|
|
158
|
+
|
|
159
|
+
// Build card content
|
|
160
|
+
const content = `
|
|
161
|
+
{bold}📋 Current Requirement{/bold}
|
|
162
|
+
|
|
163
|
+
${requirement.length > 70 ? requirement.substring(0, 67) + '...' : requirement}
|
|
164
|
+
|
|
165
|
+
{bold}🚦 Status:{/bold} ${stepColor}{bold}${step}{/bold}{/}
|
|
166
|
+
|
|
167
|
+
${progressBar} ${progress}%
|
|
168
|
+
|
|
169
|
+
{gray-fg}${chatDisplay}{/gray-fg}
|
|
170
|
+
`;
|
|
171
|
+
|
|
172
|
+
statusCard.setContent(content);
|
|
173
|
+
screen.render();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Append a line to the output log
|
|
178
|
+
* @param {string} line - Line to append
|
|
179
|
+
*/
|
|
180
|
+
function appendOutput(line) {
|
|
181
|
+
outputLog.log(line);
|
|
182
|
+
screen.render();
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Clear the output log
|
|
187
|
+
*/
|
|
188
|
+
function clearOutput() {
|
|
189
|
+
outputLog.setContent('');
|
|
190
|
+
screen.render();
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return {
|
|
194
|
+
screen,
|
|
195
|
+
header,
|
|
196
|
+
statusCard,
|
|
197
|
+
outputLog,
|
|
198
|
+
updateStatus,
|
|
199
|
+
appendOutput,
|
|
200
|
+
clearOutput,
|
|
201
|
+
destroy: () => screen.destroy()
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
module.exports = {
|
|
206
|
+
createAutoModeUI
|
|
207
|
+
};
|
package/src/utils/auto-mode.js
CHANGED
|
@@ -1,65 +1,65 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const fs = require('fs-extra');
|
|
3
|
-
const { getRepoPath } = require('./config');
|
|
4
|
-
const { logAutoModeStart, logAutoModeStop } = require('vibecodingmachine-core');
|
|
5
|
-
|
|
6
|
-
function getStatusPath(repoPath) {
|
|
7
|
-
return path.join(repoPath, '.vibecodingmachine', 'temp', 'auto-status.json');
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
async function checkAutoModeStatus() {
|
|
11
|
-
const repoPath = await getRepoPath();
|
|
12
|
-
if (!repoPath) return { running: false };
|
|
13
|
-
const statusPath = getStatusPath(repoPath);
|
|
14
|
-
if (!await fs.pathExists(statusPath)) return { running: false };
|
|
15
|
-
try {
|
|
16
|
-
const status = await fs.readJson(statusPath);
|
|
17
|
-
return status;
|
|
18
|
-
} catch {
|
|
19
|
-
return { running: false };
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async function startAutoMode(repoPath, config) {
|
|
24
|
-
const statusPath = getStatusPath(repoPath);
|
|
25
|
-
await fs.ensureDir(path.dirname(statusPath));
|
|
26
|
-
const status = {
|
|
27
|
-
running: true,
|
|
28
|
-
startedAt: new Date().toISOString(),
|
|
29
|
-
chatCount: 0,
|
|
30
|
-
ide: config.ide || 'cline'
|
|
31
|
-
};
|
|
32
|
-
await fs.writeJson(statusPath, status, { spaces: 2 });
|
|
33
|
-
|
|
34
|
-
// Log to audit log
|
|
35
|
-
logAutoModeStart(config.ide || 'cline', config.maxChats || 0);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async function stopAutoMode(reason = 'manual') {
|
|
39
|
-
const repoPath = await getRepoPath();
|
|
40
|
-
if (!repoPath) return;
|
|
41
|
-
const statusPath = getStatusPath(repoPath);
|
|
42
|
-
if (!await fs.pathExists(statusPath)) return;
|
|
43
|
-
const current = await fs.readJson(statusPath).catch(() => ({}));
|
|
44
|
-
await fs.writeJson(statusPath, { ...current, running: false }, { spaces: 2 });
|
|
45
|
-
|
|
46
|
-
// Log to audit log
|
|
47
|
-
logAutoModeStop(reason);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
async function updateAutoModeStatus(repoPath, updates) {
|
|
51
|
-
const statusPath = getStatusPath(repoPath);
|
|
52
|
-
if (!await fs.pathExists(statusPath)) return;
|
|
53
|
-
const current = await fs.readJson(statusPath).catch(() => ({ running: true }));
|
|
54
|
-
await fs.writeJson(statusPath, { ...current, ...updates }, { spaces: 2 });
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
module.exports = {
|
|
58
|
-
checkAutoModeStatus,
|
|
59
|
-
startAutoMode,
|
|
60
|
-
stopAutoMode,
|
|
61
|
-
updateAutoModeStatus
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const fs = require('fs-extra');
|
|
3
|
+
const { getRepoPath } = require('./config');
|
|
4
|
+
const { logAutoModeStart, logAutoModeStop } = require('vibecodingmachine-core');
|
|
5
|
+
|
|
6
|
+
function getStatusPath(repoPath) {
|
|
7
|
+
return path.join(repoPath, '.vibecodingmachine', 'temp', 'auto-status.json');
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async function checkAutoModeStatus() {
|
|
11
|
+
const repoPath = await getRepoPath();
|
|
12
|
+
if (!repoPath) return { running: false };
|
|
13
|
+
const statusPath = getStatusPath(repoPath);
|
|
14
|
+
if (!await fs.pathExists(statusPath)) return { running: false };
|
|
15
|
+
try {
|
|
16
|
+
const status = await fs.readJson(statusPath);
|
|
17
|
+
return status;
|
|
18
|
+
} catch {
|
|
19
|
+
return { running: false };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function startAutoMode(repoPath, config) {
|
|
24
|
+
const statusPath = getStatusPath(repoPath);
|
|
25
|
+
await fs.ensureDir(path.dirname(statusPath));
|
|
26
|
+
const status = {
|
|
27
|
+
running: true,
|
|
28
|
+
startedAt: new Date().toISOString(),
|
|
29
|
+
chatCount: 0,
|
|
30
|
+
ide: config.ide || 'cline'
|
|
31
|
+
};
|
|
32
|
+
await fs.writeJson(statusPath, status, { spaces: 2 });
|
|
33
|
+
|
|
34
|
+
// Log to audit log
|
|
35
|
+
logAutoModeStart(config.ide || 'cline', config.maxChats || 0);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function stopAutoMode(reason = 'manual') {
|
|
39
|
+
const repoPath = await getRepoPath();
|
|
40
|
+
if (!repoPath) return;
|
|
41
|
+
const statusPath = getStatusPath(repoPath);
|
|
42
|
+
if (!await fs.pathExists(statusPath)) return;
|
|
43
|
+
const current = await fs.readJson(statusPath).catch(() => ({}));
|
|
44
|
+
await fs.writeJson(statusPath, { ...current, running: false }, { spaces: 2 });
|
|
45
|
+
|
|
46
|
+
// Log to audit log
|
|
47
|
+
logAutoModeStop(reason);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function updateAutoModeStatus(repoPath, updates) {
|
|
51
|
+
const statusPath = getStatusPath(repoPath);
|
|
52
|
+
if (!await fs.pathExists(statusPath)) return;
|
|
53
|
+
const current = await fs.readJson(statusPath).catch(() => ({ running: true }));
|
|
54
|
+
await fs.writeJson(statusPath, { ...current, ...updates }, { spaces: 2 });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
module.exports = {
|
|
58
|
+
checkAutoModeStatus,
|
|
59
|
+
startAutoMode,
|
|
60
|
+
stopAutoMode,
|
|
61
|
+
updateAutoModeStatus
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
package/src/utils/config.js
CHANGED
|
@@ -1,64 +1,64 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const os = require('os');
|
|
3
|
-
const fs = require('fs-extra');
|
|
4
|
-
|
|
5
|
-
const DEFAULT_CONFIG_DIR = path.join(os.homedir(), '.config', 'vibecodingmachine');
|
|
6
|
-
const DEFAULT_CONFIG_PATH = path.join(DEFAULT_CONFIG_DIR, 'config.json');
|
|
7
|
-
|
|
8
|
-
function getConfigPath() {
|
|
9
|
-
const override = process.env.ALLNIGHTAI_CONFIG_PATH;
|
|
10
|
-
if (override) return override;
|
|
11
|
-
return DEFAULT_CONFIG_PATH;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
async function ensureConfigFile() {
|
|
15
|
-
const cfgPath = getConfigPath();
|
|
16
|
-
await fs.ensureDir(path.dirname(cfgPath));
|
|
17
|
-
if (!await fs.pathExists(cfgPath)) {
|
|
18
|
-
const defaultConfig = { repoPath: null, auto: {} };
|
|
19
|
-
await fs.writeJson(cfgPath, defaultConfig, { spaces: 2 });
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async function readConfig() {
|
|
24
|
-
await ensureConfigFile();
|
|
25
|
-
return fs.readJson(getConfigPath());
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async function writeConfig(config) {
|
|
29
|
-
await fs.writeJson(getConfigPath(), config, { spaces: 2 });
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async function getRepoPath() {
|
|
33
|
-
const cfg = await readConfig();
|
|
34
|
-
return cfg.repoPath || null;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async function setRepoPath(repoPath) {
|
|
38
|
-
const cfg = await readConfig();
|
|
39
|
-
cfg.repoPath = repoPath;
|
|
40
|
-
await writeConfig(cfg);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
async function getAutoConfig() {
|
|
44
|
-
const cfg = await readConfig();
|
|
45
|
-
return cfg.auto || {};
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async function setAutoConfig(autoConfig) {
|
|
49
|
-
const cfg = await readConfig();
|
|
50
|
-
// Merge with existing auto config to preserve fields like aiderModel
|
|
51
|
-
cfg.auto = { ...(cfg.auto || {}), ...(autoConfig || {}) };
|
|
52
|
-
await writeConfig(cfg);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
module.exports = {
|
|
56
|
-
getRepoPath,
|
|
57
|
-
setRepoPath,
|
|
58
|
-
getAutoConfig,
|
|
59
|
-
setAutoConfig,
|
|
60
|
-
readConfig,
|
|
61
|
-
writeConfig
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const os = require('os');
|
|
3
|
+
const fs = require('fs-extra');
|
|
4
|
+
|
|
5
|
+
const DEFAULT_CONFIG_DIR = path.join(os.homedir(), '.config', 'vibecodingmachine');
|
|
6
|
+
const DEFAULT_CONFIG_PATH = path.join(DEFAULT_CONFIG_DIR, 'config.json');
|
|
7
|
+
|
|
8
|
+
function getConfigPath() {
|
|
9
|
+
const override = process.env.ALLNIGHTAI_CONFIG_PATH;
|
|
10
|
+
if (override) return override;
|
|
11
|
+
return DEFAULT_CONFIG_PATH;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async function ensureConfigFile() {
|
|
15
|
+
const cfgPath = getConfigPath();
|
|
16
|
+
await fs.ensureDir(path.dirname(cfgPath));
|
|
17
|
+
if (!await fs.pathExists(cfgPath)) {
|
|
18
|
+
const defaultConfig = { repoPath: null, auto: {} };
|
|
19
|
+
await fs.writeJson(cfgPath, defaultConfig, { spaces: 2 });
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function readConfig() {
|
|
24
|
+
await ensureConfigFile();
|
|
25
|
+
return fs.readJson(getConfigPath());
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function writeConfig(config) {
|
|
29
|
+
await fs.writeJson(getConfigPath(), config, { spaces: 2 });
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async function getRepoPath() {
|
|
33
|
+
const cfg = await readConfig();
|
|
34
|
+
return cfg.repoPath || null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function setRepoPath(repoPath) {
|
|
38
|
+
const cfg = await readConfig();
|
|
39
|
+
cfg.repoPath = repoPath;
|
|
40
|
+
await writeConfig(cfg);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function getAutoConfig() {
|
|
44
|
+
const cfg = await readConfig();
|
|
45
|
+
return cfg.auto || {};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function setAutoConfig(autoConfig) {
|
|
49
|
+
const cfg = await readConfig();
|
|
50
|
+
// Merge with existing auto config to preserve fields like aiderModel
|
|
51
|
+
cfg.auto = { ...(cfg.auto || {}), ...(autoConfig || {}) };
|
|
52
|
+
await writeConfig(cfg);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
module.exports = {
|
|
56
|
+
getRepoPath,
|
|
57
|
+
setRepoPath,
|
|
58
|
+
getAutoConfig,
|
|
59
|
+
setAutoConfig,
|
|
60
|
+
readConfig,
|
|
61
|
+
writeConfig
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
|