vibecodingmachine-cli 2026.2.26-1752 → 2026.3.9-1621
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/bin/auth/auth-compliance.js +7 -1
- package/bin/commands/agent-commands.js +150 -228
- package/bin/commands/command-aliases.js +68 -0
- package/bin/vibecodingmachine.js +1 -2
- package/package.json +2 -2
- package/src/commands/agents/list.js +71 -115
- package/src/commands/agents-check.js +16 -4
- package/src/commands/analyze-file-sizes.js +1 -1
- package/src/commands/auto-direct/auto-provider-manager.js +290 -0
- package/src/commands/auto-direct/auto-status-display.js +331 -0
- package/src/commands/auto-direct/auto-utils.js +439 -0
- package/src/commands/auto-direct/file-operations.js +110 -0
- package/src/commands/auto-direct/provider-config.js +1 -1
- package/src/commands/auto-direct/provider-manager.js +1 -1
- package/src/commands/auto-direct/status-display.js +1 -1
- package/src/commands/auto-direct/utils.js +24 -18
- package/src/commands/auto-direct-refactored.js +413 -0
- package/src/commands/auto-direct.js +594 -188
- package/src/commands/requirements/commands.js +353 -0
- package/src/commands/requirements/default-handlers.js +272 -0
- package/src/commands/requirements/disable.js +97 -0
- package/src/commands/requirements/enable.js +97 -0
- package/src/commands/requirements/utils.js +194 -0
- package/src/commands/requirements-refactored.js +60 -0
- package/src/commands/requirements.js +38 -771
- package/src/commands/specs/disable.js +96 -0
- package/src/commands/specs/enable.js +96 -0
- package/src/trui/TruiInterface.js +5 -11
- package/src/trui/agents/AgentInterface.js +24 -396
- package/src/trui/agents/handlers/CommandHandler.js +93 -0
- package/src/trui/agents/handlers/ContextManager.js +117 -0
- package/src/trui/agents/handlers/DisplayHandler.js +243 -0
- package/src/trui/agents/handlers/HelpHandler.js +51 -0
- package/src/utils/auth.js +13 -111
- package/src/utils/config.js +4 -0
- package/src/utils/interactive/requirements-navigation.js +17 -15
- package/src/utils/interactive-broken.js +2 -2
- package/src/utils/provider-checker/agent-runner.js +15 -1
- package/src/utils/provider-checker/cli-installer.js +149 -7
- package/src/utils/provider-checker/opencode-checker.js +588 -0
- package/src/utils/provider-checker/provider-validator.js +88 -3
- package/src/utils/provider-checker/time-formatter.js +3 -2
- package/src/utils/provider-manager.js +28 -20
- package/src/utils/provider-registry.js +35 -3
- package/src/utils/requirements-navigator/index.js +94 -0
- package/src/utils/requirements-navigator/input-handler.js +217 -0
- package/src/utils/requirements-navigator/section-loader.js +188 -0
- package/src/utils/requirements-navigator/tree-builder.js +105 -0
- package/src/utils/requirements-navigator/tree-renderer.js +50 -0
- package/src/utils/requirements-navigator.js +2 -583
- package/src/utils/trui-clarifications.js +188 -0
- package/src/utils/trui-feedback.js +54 -1
- package/src/utils/trui-kiro-integration.js +398 -0
- package/src/utils/trui-main-handlers.js +194 -0
- package/src/utils/trui-main-menu.js +235 -0
- package/src/utils/trui-nav-agents.js +178 -25
- package/src/utils/trui-nav-requirements.js +203 -27
- package/src/utils/trui-nav-settings.js +114 -1
- package/src/utils/trui-nav-specifications.js +44 -3
- package/src/utils/trui-navigation-backup.js +603 -0
- package/src/utils/trui-navigation.js +70 -228
- package/src/utils/trui-provider-health.js +274 -0
- package/src/utils/trui-provider-manager.js +376 -0
- package/src/utils/trui-quick-menu.js +25 -1
- package/src/utils/trui-req-actions-backup.js +507 -0
- package/src/utils/trui-req-actions.js +148 -216
- package/src/utils/trui-req-editor.js +170 -0
- package/src/utils/trui-req-file-ops.js +278 -0
- package/src/utils/trui-req-tree-old.js +719 -0
- package/src/utils/trui-req-tree.js +348 -627
- package/src/utils/trui-specifications.js +25 -7
- package/src/utils/trui-windsurf.js +231 -10
- package/src/utils/welcome-screen-extracted.js +2 -2
- package/src/utils/welcome-screen.js +2 -2
|
@@ -0,0 +1,603 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TRUI Navigation — Main Menu
|
|
3
|
+
*
|
|
4
|
+
* Renders the status-rich main menu using showQuickMenu (raw keypress).
|
|
5
|
+
* Status/settings lines shown in gray at top; action items in white below.
|
|
6
|
+
* Uses inline accordion expansion for sections.
|
|
7
|
+
* Now using RUI pattern for consistent command structure.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const chalk = require('chalk');
|
|
11
|
+
const inquirer = require('inquirer');
|
|
12
|
+
const { showQuickMenu } = require('./trui-quick-menu');
|
|
13
|
+
const { showProviderManagerMenu } = require('./provider-manager');
|
|
14
|
+
const { initializeWindsurfIntegration, getWindsurfStatus } = require('./trui-windsurf');
|
|
15
|
+
const { debugLogger, perfMonitor, stateTracker } = require('./trui-debug');
|
|
16
|
+
const RUITRUIAdapter = require('./rui-trui-adapter');
|
|
17
|
+
|
|
18
|
+
// Import section modules
|
|
19
|
+
const {
|
|
20
|
+
loadRequirementsData,
|
|
21
|
+
buildRequirementChoices,
|
|
22
|
+
handleRequirementSelection,
|
|
23
|
+
handleRequirementMove,
|
|
24
|
+
} = require('./trui-nav-requirements');
|
|
25
|
+
|
|
26
|
+
const {
|
|
27
|
+
loadSettingsData,
|
|
28
|
+
buildSettingChoices,
|
|
29
|
+
handleSettingSelection,
|
|
30
|
+
showSettings,
|
|
31
|
+
} = require('./trui-nav-settings');
|
|
32
|
+
|
|
33
|
+
const {
|
|
34
|
+
loadSpecificationsData,
|
|
35
|
+
buildSpecificationChoices,
|
|
36
|
+
handleSpecificationSelection,
|
|
37
|
+
addSpecificationFlow,
|
|
38
|
+
} = require('./trui-nav-specifications');
|
|
39
|
+
|
|
40
|
+
const {
|
|
41
|
+
loadAgentsData,
|
|
42
|
+
buildAgentChoices,
|
|
43
|
+
handleAgentSelection,
|
|
44
|
+
handleAgentAction,
|
|
45
|
+
createAgentNavigationHandler,
|
|
46
|
+
} = require('./trui-nav-agents');
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Build main-menu items array with live status at top + inline accordion sections
|
|
50
|
+
* @param {Object} expandedSections - Map of section names to expanded state
|
|
51
|
+
* @param {Object} navigation - TRUINavigation instance for loading section data
|
|
52
|
+
*/
|
|
53
|
+
async function buildMainMenuItems(expandedSections = {}, navigation = null) {
|
|
54
|
+
const items = [];
|
|
55
|
+
|
|
56
|
+
// Auto Mode status
|
|
57
|
+
let autoStatus = { running: false };
|
|
58
|
+
try {
|
|
59
|
+
const { checkAutoModeStatus } = require('./auto-mode');
|
|
60
|
+
autoStatus = await checkAutoModeStatus();
|
|
61
|
+
} catch (_) {}
|
|
62
|
+
|
|
63
|
+
items.push({
|
|
64
|
+
type: 'setting',
|
|
65
|
+
name: `Auto Mode: ${autoStatus.running ? chalk.green('Running ✓') : chalk.yellow('Stopped ○')}`,
|
|
66
|
+
value: 'setting:auto',
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// Requirements summary (only show when requirements section is not expanded)
|
|
70
|
+
if (!expandedSections.requirements) {
|
|
71
|
+
try {
|
|
72
|
+
const { countRequirements } = require('./status-helpers-extracted');
|
|
73
|
+
const counts = await countRequirements();
|
|
74
|
+
if (counts) {
|
|
75
|
+
const total = (counts.todoCount || 0) + (counts.toVerifyCount || 0) + (counts.verifiedCount || 0);
|
|
76
|
+
const pct = n => total > 0 ? Math.round((n / total) * 100) : 0;
|
|
77
|
+
items.push({
|
|
78
|
+
type: 'setting',
|
|
79
|
+
name: `Requirements: ${chalk.yellow(counts.todoCount + ' todo')}, ${chalk.cyan(counts.toVerifyCount + ' verify')}, ${chalk.green(counts.verifiedCount + ' done')} (${pct(counts.verifiedCount)}% complete)`,
|
|
80
|
+
value: 'setting:requirements',
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
} catch (_) {}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Current agent display with rate-limit warning
|
|
87
|
+
try {
|
|
88
|
+
const { getProviderPreferences } = require('./provider-registry');
|
|
89
|
+
const prefs = await getProviderPreferences();
|
|
90
|
+
const { getProviderCache } = require('./config');
|
|
91
|
+
const cache = await getProviderCache();
|
|
92
|
+
|
|
93
|
+
// Find first enabled provider
|
|
94
|
+
let currentAgent = null;
|
|
95
|
+
let rateLimitWarning = '';
|
|
96
|
+
for (const agentId of (prefs.order || [])) {
|
|
97
|
+
if (prefs.enabled[agentId] !== false) {
|
|
98
|
+
currentAgent = agentId;
|
|
99
|
+
const agentCache = cache[agentId];
|
|
100
|
+
if (agentCache && agentCache.rateLimitRemaining !== undefined) {
|
|
101
|
+
if (agentCache.rateLimitRemaining < 10) {
|
|
102
|
+
rateLimitWarning = chalk.red(` (${agentCache.rateLimitRemaining} left)`);
|
|
103
|
+
} else if (agentCache.rateLimitRemaining < 50) {
|
|
104
|
+
rateLimitWarning = chalk.yellow(` (${agentCache.rateLimitRemaining} left)`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (currentAgent) {
|
|
112
|
+
const { getProviderDisplayName } = require('./provider-registry');
|
|
113
|
+
const displayName = getProviderDisplayName(currentAgent);
|
|
114
|
+
items.push({
|
|
115
|
+
type: 'setting',
|
|
116
|
+
name: `Agent: ${chalk.cyan(displayName)}${rateLimitWarning}`,
|
|
117
|
+
value: 'setting:agent',
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
} catch (_) {}
|
|
121
|
+
|
|
122
|
+
items.push({ type: 'blank', name: '', value: 'blank' });
|
|
123
|
+
|
|
124
|
+
// Requirements section with inline accordion
|
|
125
|
+
const reqExpanded = expandedSections.requirements || false;
|
|
126
|
+
const reqIcon = reqExpanded ? '▼' : '▶';
|
|
127
|
+
items.push({ type: 'action', name: `${reqIcon} 📋 Requirements`, value: 'requirements' });
|
|
128
|
+
if (reqExpanded && navigation) {
|
|
129
|
+
const reqData = await loadRequirementsData(navigation);
|
|
130
|
+
const reqChoices = buildRequirementChoices(reqData);
|
|
131
|
+
reqChoices.forEach(choice => {
|
|
132
|
+
if (choice instanceof inquirer.Separator) {
|
|
133
|
+
items.push({ type: 'separator', name: choice.line, value: 'separator' });
|
|
134
|
+
} else {
|
|
135
|
+
items.push({ type: 'sub-item', name: choice.name, value: choice.value });
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Agents section with inline accordion
|
|
141
|
+
const agentsExpanded = expandedSections.agents || false;
|
|
142
|
+
const agentsIcon = agentsExpanded ? '▼' : '▶';
|
|
143
|
+
items.push({ type: 'action', name: `${agentsIcon} 🤖 Agents`, value: 'agents' });
|
|
144
|
+
if (agentsExpanded && navigation) {
|
|
145
|
+
const agentsData = await loadAgentsData(navigation);
|
|
146
|
+
const agentsChoices = buildAgentChoices(agentsData);
|
|
147
|
+
agentsChoices.forEach(choice => {
|
|
148
|
+
if (choice instanceof inquirer.Separator) {
|
|
149
|
+
items.push({ type: 'separator', name: choice.line, value: 'separator' });
|
|
150
|
+
} else {
|
|
151
|
+
items.push({ type: 'sub-item', name: choice.name, value: choice.value });
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Specifications section with inline accordion
|
|
157
|
+
const specsExpanded = expandedSections.specifications || false;
|
|
158
|
+
const specsIcon = specsExpanded ? '▼' : '▶';
|
|
159
|
+
items.push({ type: 'action', name: `${specsIcon} 📐 Specifications`, value: 'specifications' });
|
|
160
|
+
if (specsExpanded) {
|
|
161
|
+
const specsData = await loadSpecificationsData();
|
|
162
|
+
const specsChoices = buildSpecificationChoices(specsData);
|
|
163
|
+
specsChoices.forEach(choice => {
|
|
164
|
+
items.push({ type: 'sub-item', name: choice.name, value: choice.value });
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Settings (non-accordion, opens separate view)
|
|
169
|
+
items.push({ type: 'action', name: '⚙️ Settings', value: 'settings' });
|
|
170
|
+
|
|
171
|
+
// Action shortcuts
|
|
172
|
+
items.push({ type: 'blank', name: '', value: 'blank' });
|
|
173
|
+
items.push({ type: 'action', name: '[+ Add Requirement]', value: 'add-req' });
|
|
174
|
+
items.push({ type: 'action', name: '[+ Add Specification]', value: 'add-spec' });
|
|
175
|
+
items.push({ type: 'action', name: '💬 Send Continue to Windsurf', value: 'continue-windsurf' });
|
|
176
|
+
items.push({ type: 'action', name: '🔄 Sync Now', value: 'sync' });
|
|
177
|
+
items.push({ type: 'action', name: 'Exit', value: 'exit' });
|
|
178
|
+
|
|
179
|
+
return items;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* TRUINavigation — main menu loop
|
|
184
|
+
*/
|
|
185
|
+
class TRUINavigation {
|
|
186
|
+
constructor() {
|
|
187
|
+
this._lastIndex = 0;
|
|
188
|
+
this.ruiAdapter = new RUITRUIAdapter();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
get resolver() {
|
|
192
|
+
if (!this.ruiAdapter.resolver) {
|
|
193
|
+
this.ruiAdapter.initialize();
|
|
194
|
+
}
|
|
195
|
+
return this.ruiAdapter.resolver;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async start() {
|
|
199
|
+
perfMonitor.start('TRUINavigation.start');
|
|
200
|
+
stateTracker.push({ type: 'navigation', phase: 'start' });
|
|
201
|
+
|
|
202
|
+
const { showWelcomeScreen } = require('./welcome-screen-extracted');
|
|
203
|
+
|
|
204
|
+
console.clear();
|
|
205
|
+
try { await showWelcomeScreen(); } catch (_) {}
|
|
206
|
+
|
|
207
|
+
// Initialize Windsurf integration with error handling
|
|
208
|
+
try {
|
|
209
|
+
initializeWindsurfIntegration();
|
|
210
|
+
} catch (error) {
|
|
211
|
+
console.log(chalk.yellow('⚠ Windsurf integration disabled: ' + error.message));
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
await this._loop();
|
|
215
|
+
|
|
216
|
+
perfMonitor.end('TRUINavigation.start');
|
|
217
|
+
stateTracker.pop();
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
async _loop() {
|
|
221
|
+
perfMonitor.start('TRUINavigation.loop');
|
|
222
|
+
stateTracker.push({ type: 'navigation', phase: 'loop' });
|
|
223
|
+
|
|
224
|
+
const { sendContinueToWindsurf } = require('./trui-windsurf');
|
|
225
|
+
|
|
226
|
+
// Track expanded sections state
|
|
227
|
+
const expandedSections = {
|
|
228
|
+
requirements: false,
|
|
229
|
+
agents: false,
|
|
230
|
+
specifications: false,
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
// Track data cache for sections
|
|
234
|
+
let requirementsData = null;
|
|
235
|
+
let agentsData = null;
|
|
236
|
+
let specificationsData = null;
|
|
237
|
+
|
|
238
|
+
while (true) {
|
|
239
|
+
try {
|
|
240
|
+
const items = await buildMainMenuItems(expandedSections, this);
|
|
241
|
+
|
|
242
|
+
// Force screen clear when menu content changes (like when sections expand/collapse)
|
|
243
|
+
if (process.stdout.isTTY) {
|
|
244
|
+
console.clear();
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Extra keys handler for special commands and agent actions
|
|
248
|
+
const extraKeys = (str, key, selectedIndex, context) => {
|
|
249
|
+
if (str === '!' || str === '1') {
|
|
250
|
+
// Run agents check command
|
|
251
|
+
context.resolveWith('agents-check');
|
|
252
|
+
return true;
|
|
253
|
+
}
|
|
254
|
+
if (str === 'n' || str === 'N') {
|
|
255
|
+
// Add requirement shortcut
|
|
256
|
+
context.resolveWith('add-requirement');
|
|
257
|
+
return true;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Handle agent enable/disable keys when agents section is expanded
|
|
261
|
+
if ((str === 'e' || str === 'E' || str === 'd' || str === 'D') && expandedSections.agents && agentsData) {
|
|
262
|
+
const currentItem = items[selectedIndex];
|
|
263
|
+
if (currentItem && currentItem.type === 'sub-item' && currentItem.value && currentItem.value.startsWith('agent:')) {
|
|
264
|
+
const agentIndex = parseInt(currentItem.value.substring(6), 10);
|
|
265
|
+
const agent = agentsData.agents[agentIndex];
|
|
266
|
+
if (agent) {
|
|
267
|
+
const action = str.toLowerCase() === 'e' ? 'enable' : 'disable';
|
|
268
|
+
context.resolveWith(`agent-${action}:${agentIndex}`);
|
|
269
|
+
return true;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Arrow key navigation for agents
|
|
275
|
+
if (expandedSections.agents && agentsData && (key.name === 'up' || key.name === 'down')) {
|
|
276
|
+
const choices = items.filter(item => item.type === 'sub-item' && item.value && item.value.startsWith('agent:'));
|
|
277
|
+
const agentNavHandler = createAgentNavigationHandler(agentsData, choices);
|
|
278
|
+
return agentNavHandler(str, key, selectedIndex, context);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return false;
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
const result = await showQuickMenu(items, this._lastIndex, extraKeys);
|
|
285
|
+
this._lastIndex = result.selectedIndex;
|
|
286
|
+
const action = result.value;
|
|
287
|
+
|
|
288
|
+
if (action === '__cancel__' || action === 'exit') {
|
|
289
|
+
await this._confirmExit();
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Handle section accordion toggles
|
|
294
|
+
if (action === 'requirements') {
|
|
295
|
+
expandedSections.requirements = !expandedSections.requirements;
|
|
296
|
+
if (expandedSections.requirements) {
|
|
297
|
+
requirementsData = await loadRequirementsData(this);
|
|
298
|
+
}
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (action === 'agents') {
|
|
303
|
+
expandedSections.agents = !expandedSections.agents;
|
|
304
|
+
if (expandedSections.agents) {
|
|
305
|
+
agentsData = await loadAgentsData(this);
|
|
306
|
+
}
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
if (action === 'specifications') {
|
|
311
|
+
expandedSections.specifications = !expandedSections.specifications;
|
|
312
|
+
if (expandedSections.specifications) {
|
|
313
|
+
specificationsData = await loadSpecificationsData();
|
|
314
|
+
}
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Handle requirement sub-item selections
|
|
319
|
+
if (action.startsWith('req:')) {
|
|
320
|
+
const reqIndex = parseInt(action.substring(4), 10);
|
|
321
|
+
const changed = await handleRequirementSelection(reqIndex, requirementsData, this);
|
|
322
|
+
if (changed) {
|
|
323
|
+
requirementsData = await loadRequirementsData(this);
|
|
324
|
+
}
|
|
325
|
+
console.clear();
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Handle requirement move up
|
|
330
|
+
if (action.startsWith('req-move-up:')) {
|
|
331
|
+
const reqIndex = parseInt(action.substring(12), 10);
|
|
332
|
+
const changed = await handleRequirementMove(reqIndex, requirementsData, 'up');
|
|
333
|
+
if (changed) {
|
|
334
|
+
requirementsData = await loadRequirementsData(this);
|
|
335
|
+
}
|
|
336
|
+
console.clear();
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Handle requirement move down
|
|
341
|
+
if (action.startsWith('req-move-down:')) {
|
|
342
|
+
const reqIndex = parseInt(action.substring(14), 10);
|
|
343
|
+
const changed = await handleRequirementMove(reqIndex, requirementsData, 'down');
|
|
344
|
+
if (changed) {
|
|
345
|
+
requirementsData = await loadRequirementsData(this);
|
|
346
|
+
}
|
|
347
|
+
console.clear();
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// Handle agent sub-item selections
|
|
352
|
+
if (action.startsWith('agent:')) {
|
|
353
|
+
const agentIndex = parseInt(action.substring(6), 10);
|
|
354
|
+
const changed = await handleAgentSelection(agentIndex, agentsData, this);
|
|
355
|
+
if (changed) {
|
|
356
|
+
agentsData = await loadAgentsData(this);
|
|
357
|
+
}
|
|
358
|
+
console.clear();
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Handle agent enable action
|
|
363
|
+
if (action.startsWith('agent-enable:')) {
|
|
364
|
+
const agentIndex = parseInt(action.substring(13), 10);
|
|
365
|
+
const changed = await handleAgentAction(agentIndex, agentsData, this, 'enable');
|
|
366
|
+
if (changed) {
|
|
367
|
+
agentsData = await loadAgentsData(this);
|
|
368
|
+
}
|
|
369
|
+
console.clear();
|
|
370
|
+
continue;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// Handle agent disable action
|
|
374
|
+
if (action.startsWith('agent-disable:')) {
|
|
375
|
+
const agentIndex = parseInt(action.substring(14), 10);
|
|
376
|
+
const changed = await handleAgentAction(agentIndex, agentsData, this, 'disable');
|
|
377
|
+
if (changed) {
|
|
378
|
+
agentsData = await loadAgentsData(this);
|
|
379
|
+
}
|
|
380
|
+
console.clear();
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
// Handle specification sub-item selections
|
|
386
|
+
if (action.startsWith('spec:')) {
|
|
387
|
+
const specDir = action.substring(5);
|
|
388
|
+
await handleSpecificationSelection(specDir, specificationsData, this);
|
|
389
|
+
console.clear();
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// Dispatch to sub-modules
|
|
394
|
+
try {
|
|
395
|
+
if (action === 'setting:auto') {
|
|
396
|
+
try {
|
|
397
|
+
const { checkAutoModeStatus, stopAutoMode } = require('./auto-mode');
|
|
398
|
+
const s = await checkAutoModeStatus();
|
|
399
|
+
if (s.running) {
|
|
400
|
+
await stopAutoMode('manual');
|
|
401
|
+
console.log(chalk.yellow('\n⏹ Auto mode stopped\n'));
|
|
402
|
+
await this._pause();
|
|
403
|
+
console.clear();
|
|
404
|
+
} else {
|
|
405
|
+
console.log(chalk.bold.cyan('\n▶ Starting Auto Mode...\n'));
|
|
406
|
+
try {
|
|
407
|
+
const { getAutoConfig } = require('./config');
|
|
408
|
+
const currentConfig = await getAutoConfig();
|
|
409
|
+
// Pick first enabled provider
|
|
410
|
+
const { getProviderPreferences } = require('./provider-registry');
|
|
411
|
+
const prefs = await getProviderPreferences();
|
|
412
|
+
let agentToUse = currentConfig.ide || currentConfig.agent || 'cline';
|
|
413
|
+
for (const agentId of (prefs.order || [])) {
|
|
414
|
+
if (prefs.enabled[agentId] !== false) { agentToUse = agentId; break; }
|
|
415
|
+
}
|
|
416
|
+
// Release raw mode before running auto (so Ctrl+C works)
|
|
417
|
+
if (process.stdin.isTTY && process.stdin.setRawMode) {
|
|
418
|
+
process.stdin.setRawMode(false);
|
|
419
|
+
}
|
|
420
|
+
const options = { ide: agentToUse };
|
|
421
|
+
if (currentConfig.neverStop) {
|
|
422
|
+
options.neverStop = true;
|
|
423
|
+
} else if (currentConfig.maxChats) {
|
|
424
|
+
options.maxChats = currentConfig.maxChats;
|
|
425
|
+
} else {
|
|
426
|
+
options.neverStop = true;
|
|
427
|
+
}
|
|
428
|
+
const { handleAutoStart } = require('../commands/auto-direct');
|
|
429
|
+
await handleAutoStart(options);
|
|
430
|
+
} catch (startErr) {
|
|
431
|
+
if (startErr.message && startErr.message.includes('User force closed')) {
|
|
432
|
+
console.log(chalk.yellow('\nCancelled\n'));
|
|
433
|
+
} else {
|
|
434
|
+
console.log(chalk.red(`\n✗ Error: ${startErr.message}`));
|
|
435
|
+
if (startErr.stack) console.log(chalk.gray(startErr.stack.split('\n').slice(0, 8).join('\n')));
|
|
436
|
+
console.log(chalk.yellow('\nReturning to menu in 5 seconds...'));
|
|
437
|
+
await new Promise(r => setTimeout(r, 5000));
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
await this._pause();
|
|
441
|
+
console.clear();
|
|
442
|
+
}
|
|
443
|
+
} catch (err) { console.log(chalk.red('Error: ' + err.message)); await this._pause(); console.clear(); }
|
|
444
|
+
continue;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
if (action === 'agents-check') {
|
|
448
|
+
try {
|
|
449
|
+
const { checkAgents } = require('../commands/agents-check');
|
|
450
|
+
console.clear();
|
|
451
|
+
console.log(chalk.bold.cyan('🔍 Checking agents...\n'));
|
|
452
|
+
await checkAgents();
|
|
453
|
+
await this._pause();
|
|
454
|
+
} catch (err) {
|
|
455
|
+
console.log(chalk.red('Agents check error: ' + err.message));
|
|
456
|
+
await this._pause();
|
|
457
|
+
}
|
|
458
|
+
console.clear();
|
|
459
|
+
continue;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
if (action === 'settings') {
|
|
463
|
+
try { await showSettings(); } catch (err) { console.log(chalk.red('Settings error: ' + err.message)); await this._pause(); }
|
|
464
|
+
console.clear();
|
|
465
|
+
continue;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
if (action === 'add-req' || action === 'add-requirement') {
|
|
469
|
+
try { await addRequirementFlow(this); } catch (err) { console.log(chalk.red('Error: ' + err.message)); await this._pause(); }
|
|
470
|
+
console.clear();
|
|
471
|
+
// Refresh requirements data if section is expanded
|
|
472
|
+
if (expandedSections.requirements) {
|
|
473
|
+
requirementsData = await loadRequirementsData(this);
|
|
474
|
+
}
|
|
475
|
+
continue;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
if (action === 'add-spec') {
|
|
479
|
+
try { await addSpecificationFlow(this); } catch (err) { console.log(chalk.red('Error: ' + err.message)); await this._pause(); }
|
|
480
|
+
console.clear();
|
|
481
|
+
// Refresh specifications data if section is expanded
|
|
482
|
+
if (expandedSections.specifications) {
|
|
483
|
+
specificationsData = await loadSpecificationsData();
|
|
484
|
+
}
|
|
485
|
+
continue;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
if (action === 'continue-windsurf') {
|
|
489
|
+
try {
|
|
490
|
+
await sendContinueToWindsurf();
|
|
491
|
+
console.log(chalk.green('\n✓ Continue message sent to Windsurf Cascade\n'));
|
|
492
|
+
} catch (err) { console.log(chalk.red('Error: ' + err.message)); }
|
|
493
|
+
await this._pause();
|
|
494
|
+
console.clear();
|
|
495
|
+
continue;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
if (action === 'sync') {
|
|
499
|
+
try {
|
|
500
|
+
const { execSync } = require('child_process');
|
|
501
|
+
console.log(chalk.cyan('\n🔄 Syncing...\n'));
|
|
502
|
+
execSync('vcm sync:now', { stdio: 'inherit' });
|
|
503
|
+
} catch (_) { console.log(chalk.gray('vcm sync:now: command unavailable')); }
|
|
504
|
+
await this._pause();
|
|
505
|
+
console.clear();
|
|
506
|
+
continue;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// Unknown action — skip noop/blank/separator
|
|
510
|
+
if (action === 'noop' || action === 'blank' || action === 'separator') {
|
|
511
|
+
continue;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// Unknown action — show error
|
|
515
|
+
console.log(chalk.yellow('Unknown action: ' + action));
|
|
516
|
+
await this._pause();
|
|
517
|
+
console.clear();
|
|
518
|
+
continue;
|
|
519
|
+
} catch (err) {
|
|
520
|
+
console.log(chalk.red('Action error: ' + err.message));
|
|
521
|
+
await this._pause();
|
|
522
|
+
console.clear();
|
|
523
|
+
continue;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
} catch (error) {
|
|
527
|
+
debugLogger.error('Menu loop error', { error: error.message, stack: error.stack });
|
|
528
|
+
console.log(chalk.red('Menu error: ' + error.message));
|
|
529
|
+
await this._pause();
|
|
530
|
+
continue;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
perfMonitor.end('TRUINavigation.loop');
|
|
535
|
+
stateTracker.pop();
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
async _confirmExit() {
|
|
539
|
+
console.clear();
|
|
540
|
+
console.log(chalk.yellow('\nExit Vibe Coding Machine? (Y/n/x)\n'));
|
|
541
|
+
|
|
542
|
+
return new Promise((resolve) => {
|
|
543
|
+
const readline = require('readline');
|
|
544
|
+
|
|
545
|
+
// Set up raw keypress handling
|
|
546
|
+
readline.emitKeypressEvents(process.stdin);
|
|
547
|
+
if (process.stdin.isTTY && process.stdin.setRawMode) {
|
|
548
|
+
process.stdin.setRawMode(true);
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
const onKeypress = (str, key) => {
|
|
552
|
+
// Handle left arrow - exit without confirmation
|
|
553
|
+
if (key && key.name === 'left') {
|
|
554
|
+
cleanup();
|
|
555
|
+
console.log(chalk.yellow('\nGoodbye!\n'));
|
|
556
|
+
process.exit(0);
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// Handle Enter or 'y' or 'Y' or 'x' - confirm exit
|
|
561
|
+
if (key && (key.name === 'return' || (str && (str === 'y' || str === 'Y' || str === 'x' || str === 'X')))) {
|
|
562
|
+
cleanup();
|
|
563
|
+
console.log(chalk.yellow('\nGoodbye!\n'));
|
|
564
|
+
process.exit(0);
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// Handle 'n' or 'N' or ESC or right arrow - cancel exit
|
|
569
|
+
if (key && (key.name === 'escape' || key.name === 'right' || (str && (str === 'n' || str === 'N')))) {
|
|
570
|
+
cleanup();
|
|
571
|
+
resolve();
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
|
|
576
|
+
const cleanup = () => {
|
|
577
|
+
if (process.stdin.isTTY && process.stdin.setRawMode) {
|
|
578
|
+
process.stdin.setRawMode(false);
|
|
579
|
+
}
|
|
580
|
+
process.stdin.removeListener('keypress', onKeypress);
|
|
581
|
+
process.stdin.pause();
|
|
582
|
+
};
|
|
583
|
+
|
|
584
|
+
process.stdin.on('keypress', onKeypress);
|
|
585
|
+
process.stdin.resume();
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
async _pause() {
|
|
590
|
+
const inquirer = require('inquirer');
|
|
591
|
+
await inquirer.prompt([{ type: 'input', name: 'c', message: chalk.gray('Press Enter to continue...') }]);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
async promptContinue() {
|
|
595
|
+
await this._pause();
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
module.exports = { TRUINavigation, buildMainMenuItems };
|
|
600
|
+
|
|
601
|
+
// Export a singleton instance for use by other modules
|
|
602
|
+
const navigationInstance = new TRUINavigation();
|
|
603
|
+
module.exports.promptContinue = () => navigationInstance.promptContinue();
|