@nclamvn/vibecode-cli 1.3.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vibecode/learning/fixes.json +1 -0
- package/.vibecode/learning/preferences.json +1 -0
- package/README.md +310 -49
- package/bin/vibecode.js +103 -2
- package/package.json +4 -2
- package/src/agent/decomposition.js +476 -0
- package/src/agent/index.js +325 -0
- package/src/agent/memory.js +542 -0
- package/src/agent/orchestrator.js +713 -0
- package/src/agent/self-healing.js +516 -0
- package/src/commands/agent.js +255 -0
- package/src/commands/assist.js +413 -0
- package/src/commands/build.js +13 -3
- package/src/commands/debug.js +457 -0
- package/src/commands/go.js +387 -0
- package/src/commands/learn.js +294 -0
- package/src/commands/undo.js +281 -0
- package/src/commands/wizard.js +322 -0
- package/src/core/backup.js +325 -0
- package/src/core/learning.js +295 -0
- package/src/core/test-runner.js +38 -5
- package/src/debug/analyzer.js +329 -0
- package/src/debug/evidence.js +228 -0
- package/src/debug/fixer.js +348 -0
- package/src/debug/index.js +378 -0
- package/src/debug/verifier.js +346 -0
- package/src/index.js +62 -0
- package/src/ui/__tests__/error-translator.test.js +390 -0
- package/src/ui/dashboard.js +364 -0
- package/src/ui/error-translator.js +775 -0
package/src/commands/build.js
CHANGED
|
@@ -22,6 +22,8 @@ import { STATES } from '../config/constants.js';
|
|
|
22
22
|
import { getBuildReportTemplate } from '../config/templates.js';
|
|
23
23
|
import { ensureDir, pathExists, appendToFile, readMarkdown, writeJson } from '../utils/files.js';
|
|
24
24
|
import { printBox, printError, printSuccess, printWarning, printNextStep } from '../ui/output.js';
|
|
25
|
+
import { showError, inlineError } from '../ui/error-translator.js';
|
|
26
|
+
import { BackupManager } from '../core/backup.js';
|
|
25
27
|
import {
|
|
26
28
|
spawnClaudeCode,
|
|
27
29
|
isClaudeCodeAvailable,
|
|
@@ -75,7 +77,7 @@ export async function buildCommand(options = {}) {
|
|
|
75
77
|
}
|
|
76
78
|
|
|
77
79
|
} catch (error) {
|
|
78
|
-
|
|
80
|
+
showError(error, { verbose: options.verbose });
|
|
79
81
|
process.exit(1);
|
|
80
82
|
}
|
|
81
83
|
}
|
|
@@ -85,6 +87,10 @@ export async function buildCommand(options = {}) {
|
|
|
85
87
|
* "Contract LOCKED = License to build"
|
|
86
88
|
*/
|
|
87
89
|
async function handleAutoBuild(currentState, projectName, sessionId, sessionPath, specHash, options) {
|
|
90
|
+
// Create backup before build
|
|
91
|
+
const backup = new BackupManager();
|
|
92
|
+
await backup.createBackup('build-auto');
|
|
93
|
+
|
|
88
94
|
// Check state - must be PLAN_CREATED or BUILD_IN_PROGRESS or REVIEW_FAILED
|
|
89
95
|
const validStates = [STATES.PLAN_CREATED, STATES.BUILD_IN_PROGRESS, STATES.REVIEW_FAILED];
|
|
90
96
|
if (!validStates.includes(currentState)) {
|
|
@@ -227,7 +233,7 @@ ${evidence.screenshots > 0 ? ` ✅ ${evidence.screenshots} screenshots` : '
|
|
|
227
233
|
|
|
228
234
|
} catch (error) {
|
|
229
235
|
await appendToFile(logPath, `\nERROR: ${error.message}\n`);
|
|
230
|
-
|
|
236
|
+
showError(error);
|
|
231
237
|
process.exit(1);
|
|
232
238
|
}
|
|
233
239
|
}
|
|
@@ -240,6 +246,10 @@ async function handleIterativeBuild(currentState, projectName, sessionId, sessio
|
|
|
240
246
|
const maxIterations = options.max || 3;
|
|
241
247
|
const strictMode = options.strict || false;
|
|
242
248
|
|
|
249
|
+
// Create backup before iterative build
|
|
250
|
+
const backup = new BackupManager();
|
|
251
|
+
await backup.createBackup('build-iterate');
|
|
252
|
+
|
|
243
253
|
// Check state - must be PLAN_CREATED or BUILD_IN_PROGRESS or REVIEW_FAILED
|
|
244
254
|
const validStates = [STATES.PLAN_CREATED, STATES.BUILD_IN_PROGRESS, STATES.REVIEW_FAILED];
|
|
245
255
|
if (!validStates.includes(currentState)) {
|
|
@@ -451,7 +461,7 @@ Starting build-test-fix loop...`;
|
|
|
451
461
|
}
|
|
452
462
|
|
|
453
463
|
} catch (error) {
|
|
454
|
-
console.log(
|
|
464
|
+
console.log('\n' + inlineError(error));
|
|
455
465
|
await logIteration(logPath, iteration, `Error: ${error.message}`);
|
|
456
466
|
|
|
457
467
|
iterationState = finalizeIterationState(iterationState, 'error');
|
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
2
|
+
// VIBECODE CLI - Debug Command
|
|
3
|
+
// Phase G: Intelligent 9-Step Bug Fixing
|
|
4
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
5
|
+
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
import ora from 'ora';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import fs from 'fs-extra';
|
|
10
|
+
import readline from 'readline';
|
|
11
|
+
import { printBox, printError, printSuccess, printWarning, printNextStep } from '../ui/output.js';
|
|
12
|
+
import { createDebugEngine } from '../debug/index.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Debug Command Entry Point
|
|
16
|
+
* Usage:
|
|
17
|
+
* vibecode debug - Interactive mode (default)
|
|
18
|
+
* vibecode debug "error description" - Debug with description
|
|
19
|
+
* vibecode debug --log - Paste error log
|
|
20
|
+
* vibecode debug --image <path> - Debug from screenshot
|
|
21
|
+
* vibecode debug --auto - Auto-scan and fix
|
|
22
|
+
*/
|
|
23
|
+
export async function debugCommand(args = [], options = {}) {
|
|
24
|
+
try {
|
|
25
|
+
const projectPath = process.cwd();
|
|
26
|
+
|
|
27
|
+
// Parse command arguments
|
|
28
|
+
const input = parseDebugInput(args, options);
|
|
29
|
+
|
|
30
|
+
// If interactive mode or no input provided, enter interactive mode
|
|
31
|
+
if (options.interactive || (!input.description && !input.log && !input.image && !input.auto)) {
|
|
32
|
+
return interactiveDebug(projectPath, options);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Create debug engine
|
|
36
|
+
const engine = createDebugEngine(projectPath, {
|
|
37
|
+
autoFix: options.autoFix !== false,
|
|
38
|
+
maxAttempts: options.attempts || 3,
|
|
39
|
+
verbose: options.verbose || false,
|
|
40
|
+
interactive: !options.quiet
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Show intro
|
|
44
|
+
console.log();
|
|
45
|
+
printBox(`🔍 VIBECODE DEBUG
|
|
46
|
+
|
|
47
|
+
Intelligent 9-Step Bug Fixing
|
|
48
|
+
Mode: ${input.auto ? 'Auto-Scan' : input.log ? 'Log Analysis' : input.image ? 'Image Analysis' : 'Description'}
|
|
49
|
+
Max Attempts: ${options.attempts || 3}`, { borderColor: 'cyan' });
|
|
50
|
+
console.log();
|
|
51
|
+
|
|
52
|
+
// Run debug workflow
|
|
53
|
+
const result = await engine.debug(input);
|
|
54
|
+
|
|
55
|
+
// Show final result
|
|
56
|
+
await showDebugResult(result, projectPath);
|
|
57
|
+
|
|
58
|
+
} catch (error) {
|
|
59
|
+
printError(`Debug failed: ${error.message}`);
|
|
60
|
+
if (options.verbose) {
|
|
61
|
+
console.error(error.stack);
|
|
62
|
+
}
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Parse debug input from args and options
|
|
69
|
+
*/
|
|
70
|
+
function parseDebugInput(args, options) {
|
|
71
|
+
const input = {
|
|
72
|
+
description: null,
|
|
73
|
+
log: null,
|
|
74
|
+
image: null,
|
|
75
|
+
auto: options.auto || false
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// Join args as description
|
|
79
|
+
if (args.length > 0) {
|
|
80
|
+
input.description = args.join(' ');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Log paste mode
|
|
84
|
+
if (options.log) {
|
|
85
|
+
if (typeof options.log === 'string') {
|
|
86
|
+
input.log = options.log;
|
|
87
|
+
} else {
|
|
88
|
+
// Will need to read from stdin or file
|
|
89
|
+
input.log = options.logContent || null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Image mode
|
|
94
|
+
if (options.image) {
|
|
95
|
+
input.image = options.image;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return input;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Show debug result summary
|
|
103
|
+
*/
|
|
104
|
+
async function showDebugResult(result, projectPath) {
|
|
105
|
+
console.log();
|
|
106
|
+
|
|
107
|
+
if (result.status === 'resolved') {
|
|
108
|
+
const content = `✅ BUG FIXED!
|
|
109
|
+
|
|
110
|
+
Status: ${result.status}
|
|
111
|
+
Attempts: ${result.session.attempts}
|
|
112
|
+
Steps: ${result.session.steps}
|
|
113
|
+
|
|
114
|
+
Documentation saved to:
|
|
115
|
+
.vibecode/debug/fixes.md
|
|
116
|
+
|
|
117
|
+
Prevention rules added to:
|
|
118
|
+
CLAUDE.md`;
|
|
119
|
+
|
|
120
|
+
printBox(content, { borderColor: 'green' });
|
|
121
|
+
printNextStep('Build your project to verify the fix');
|
|
122
|
+
|
|
123
|
+
} else if (result.status === 'no_error') {
|
|
124
|
+
printSuccess('No errors found to fix!');
|
|
125
|
+
|
|
126
|
+
} else if (result.status === 'no_hypothesis') {
|
|
127
|
+
printWarning('Could not determine how to fix this error.');
|
|
128
|
+
console.log(chalk.gray('\nTry:'));
|
|
129
|
+
console.log(chalk.gray(' • Providing more details about the error'));
|
|
130
|
+
console.log(chalk.gray(' • Pasting the full error log with --log'));
|
|
131
|
+
console.log(chalk.gray(' • Running vibecode debug --auto to scan project'));
|
|
132
|
+
|
|
133
|
+
} else {
|
|
134
|
+
// Show escalation options - user NEVER bế tắc
|
|
135
|
+
console.log(chalk.yellow(`
|
|
136
|
+
╭───────────────────────────────────────────────────────────────────╮
|
|
137
|
+
│ │
|
|
138
|
+
│ ⚠️ COULD NOT AUTO-RESOLVE │
|
|
139
|
+
│ │
|
|
140
|
+
│ Status: ${result.status.padEnd(47)}│
|
|
141
|
+
│ Attempts: ${String(result.session.attempts).padEnd(45)}│
|
|
142
|
+
│ │
|
|
143
|
+
│ Don't worry! You have options: │
|
|
144
|
+
│ │
|
|
145
|
+
│ 1. vibecode assist "describe your issue" │
|
|
146
|
+
│ → Direct AI expert access with full context │
|
|
147
|
+
│ │
|
|
148
|
+
│ 2. vibecode debug -i │
|
|
149
|
+
│ → Interactive debug with more context │
|
|
150
|
+
│ │
|
|
151
|
+
│ 3. vibecode debug --attempts 5 │
|
|
152
|
+
│ → Retry with more attempts │
|
|
153
|
+
│ │
|
|
154
|
+
╰───────────────────────────────────────────────────────────────────╯
|
|
155
|
+
`));
|
|
156
|
+
|
|
157
|
+
// Ask if user wants to auto-escalate to summon
|
|
158
|
+
const rl = readline.createInterface({
|
|
159
|
+
input: process.stdin,
|
|
160
|
+
output: process.stdout
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
try {
|
|
164
|
+
const answer = await new Promise(resolve => {
|
|
165
|
+
rl.question(chalk.cyan('\n🤝 Escalate to AI Assist? (Y/n): '), resolve);
|
|
166
|
+
});
|
|
167
|
+
rl.close();
|
|
168
|
+
|
|
169
|
+
if (answer.toLowerCase() !== 'n') {
|
|
170
|
+
const { assistCommand } = await import('./assist.js');
|
|
171
|
+
const errorMsg = result.message || 'the error that occurred';
|
|
172
|
+
await assistCommand([`Fix ${errorMsg}`], {});
|
|
173
|
+
}
|
|
174
|
+
} catch {
|
|
175
|
+
rl.close();
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Show debug command help
|
|
182
|
+
*/
|
|
183
|
+
function showDebugHelp() {
|
|
184
|
+
console.log();
|
|
185
|
+
printBox(`🔍 VIBECODE DEBUG - Help
|
|
186
|
+
|
|
187
|
+
Intelligent 9-step bug fixing powered by AI.
|
|
188
|
+
|
|
189
|
+
Usage:
|
|
190
|
+
vibecode debug "error description" Quick fix from description
|
|
191
|
+
vibecode debug --auto Auto-scan project for errors
|
|
192
|
+
vibecode debug --log "error text" Fix from error log
|
|
193
|
+
vibecode debug --image path/to/img Fix from screenshot
|
|
194
|
+
|
|
195
|
+
Options:
|
|
196
|
+
--auto Auto-scan mode - find and fix errors
|
|
197
|
+
--log <text> Provide error log directly
|
|
198
|
+
--image <path> Provide error screenshot
|
|
199
|
+
--attempts <n> Max fix attempts (default: 3)
|
|
200
|
+
--verbose Show detailed output
|
|
201
|
+
--quiet Minimal output
|
|
202
|
+
|
|
203
|
+
Examples:
|
|
204
|
+
vibecode debug "Cannot read property of undefined"
|
|
205
|
+
vibecode debug --auto
|
|
206
|
+
vibecode debug --log "TypeError: x is not a function"
|
|
207
|
+
vibecode debug --attempts 5 "module not found"`, { borderColor: 'cyan' });
|
|
208
|
+
console.log();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Interactive Debug Mode
|
|
213
|
+
* REPL-like interface for debugging
|
|
214
|
+
*/
|
|
215
|
+
async function interactiveDebug(projectPath, options) {
|
|
216
|
+
const engine = createDebugEngine(projectPath, {
|
|
217
|
+
autoFix: true,
|
|
218
|
+
maxAttempts: options.attempts || 3,
|
|
219
|
+
verbose: options.verbose || false,
|
|
220
|
+
interactive: true
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
// Show welcome banner
|
|
224
|
+
console.log(chalk.cyan(`
|
|
225
|
+
╭────────────────────────────────────────────────────────────────────╮
|
|
226
|
+
│ │
|
|
227
|
+
│ 🔍 VIBECODE DEBUG (Interactive Mode) │
|
|
228
|
+
│ │
|
|
229
|
+
│ Commands: │
|
|
230
|
+
│ • Type error description or paste log │
|
|
231
|
+
│ • /scan - Auto-scan project for errors │
|
|
232
|
+
│ • /fix - Apply last suggested fix │
|
|
233
|
+
│ • /retry - Retry with current context │
|
|
234
|
+
│ • /clear - Clear context │
|
|
235
|
+
│ • /help - Show help │
|
|
236
|
+
│ • /quit - Exit │
|
|
237
|
+
│ │
|
|
238
|
+
╰────────────────────────────────────────────────────────────────────╯
|
|
239
|
+
`));
|
|
240
|
+
|
|
241
|
+
const rl = readline.createInterface({
|
|
242
|
+
input: process.stdin,
|
|
243
|
+
output: process.stdout,
|
|
244
|
+
prompt: chalk.green('debug> ')
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// Session context
|
|
248
|
+
const context = {
|
|
249
|
+
errors: [],
|
|
250
|
+
lastAnalysis: null,
|
|
251
|
+
lastFix: null,
|
|
252
|
+
lastEvidence: null
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
rl.prompt();
|
|
256
|
+
|
|
257
|
+
rl.on('line', async (line) => {
|
|
258
|
+
const input = line.trim();
|
|
259
|
+
|
|
260
|
+
if (!input) {
|
|
261
|
+
rl.prompt();
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Handle commands
|
|
266
|
+
if (input.startsWith('/')) {
|
|
267
|
+
await handleDebugCommand(input, engine, context, rl);
|
|
268
|
+
} else {
|
|
269
|
+
// Treat as error description or log
|
|
270
|
+
await handleDebugInput(input, engine, context);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
rl.prompt();
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
rl.on('close', () => {
|
|
277
|
+
console.log(chalk.cyan('\n👋 Debug session ended.\n'));
|
|
278
|
+
process.exit(0);
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Handle debug commands (/scan, /fix, etc.)
|
|
284
|
+
*/
|
|
285
|
+
async function handleDebugCommand(cmd, engine, context, rl) {
|
|
286
|
+
const command = cmd.toLowerCase().split(' ')[0];
|
|
287
|
+
|
|
288
|
+
switch (command) {
|
|
289
|
+
case '/scan':
|
|
290
|
+
console.log(chalk.blue('\n🔍 Scanning project for errors...\n'));
|
|
291
|
+
try {
|
|
292
|
+
const result = await engine.debug({ auto: true });
|
|
293
|
+
context.lastAnalysis = result;
|
|
294
|
+
context.lastEvidence = result.evidence;
|
|
295
|
+
|
|
296
|
+
if (result.status === 'resolved') {
|
|
297
|
+
console.log(chalk.green('\n✅ All errors resolved!'));
|
|
298
|
+
} else if (result.status === 'no_error') {
|
|
299
|
+
console.log(chalk.green('\n✅ No errors found!'));
|
|
300
|
+
} else {
|
|
301
|
+
console.log(chalk.yellow('\n⚠️ Some issues found. Use /fix to apply fixes.'));
|
|
302
|
+
}
|
|
303
|
+
} catch (error) {
|
|
304
|
+
console.log(chalk.red(`\nScan error: ${error.message}`));
|
|
305
|
+
}
|
|
306
|
+
break;
|
|
307
|
+
|
|
308
|
+
case '/fix':
|
|
309
|
+
if (context.lastAnalysis && context.lastAnalysis.fixPrompt) {
|
|
310
|
+
console.log(chalk.blue('\n🔧 Applying fix...\n'));
|
|
311
|
+
try {
|
|
312
|
+
const fixResult = await engine.applyFix(context.lastAnalysis.fixPrompt);
|
|
313
|
+
if (fixResult.success) {
|
|
314
|
+
console.log(chalk.green('\n✅ Fix applied! Run /scan to verify.'));
|
|
315
|
+
} else {
|
|
316
|
+
console.log(chalk.yellow(`\n⚠️ Fix may have issues: ${fixResult.error || 'Check output above'}`));
|
|
317
|
+
}
|
|
318
|
+
} catch (error) {
|
|
319
|
+
console.log(chalk.red(`\nFix error: ${error.message}`));
|
|
320
|
+
}
|
|
321
|
+
} else if (context.errors.length > 0) {
|
|
322
|
+
// Try to generate fix from accumulated context
|
|
323
|
+
console.log(chalk.blue('\n🔧 Generating fix from context...\n'));
|
|
324
|
+
try {
|
|
325
|
+
const result = await engine.debug({ description: context.errors.join('\n\n') });
|
|
326
|
+
context.lastAnalysis = result;
|
|
327
|
+
} catch (error) {
|
|
328
|
+
console.log(chalk.red(`\nError: ${error.message}`));
|
|
329
|
+
}
|
|
330
|
+
} else {
|
|
331
|
+
console.log(chalk.yellow('\nNo analysis to fix. Run /scan or describe an error first.'));
|
|
332
|
+
}
|
|
333
|
+
break;
|
|
334
|
+
|
|
335
|
+
case '/retry':
|
|
336
|
+
if (context.errors.length > 0) {
|
|
337
|
+
console.log(chalk.blue('\n🔄 Retrying with accumulated context...\n'));
|
|
338
|
+
try {
|
|
339
|
+
const result = await engine.debug({ description: context.errors.join('\n\n') });
|
|
340
|
+
context.lastAnalysis = result;
|
|
341
|
+
} catch (error) {
|
|
342
|
+
console.log(chalk.red(`\nRetry error: ${error.message}`));
|
|
343
|
+
}
|
|
344
|
+
} else {
|
|
345
|
+
console.log(chalk.yellow('\nNo context to retry with. Describe an error first.'));
|
|
346
|
+
}
|
|
347
|
+
break;
|
|
348
|
+
|
|
349
|
+
case '/clear':
|
|
350
|
+
context.errors = [];
|
|
351
|
+
context.lastAnalysis = null;
|
|
352
|
+
context.lastFix = null;
|
|
353
|
+
context.lastEvidence = null;
|
|
354
|
+
console.log(chalk.green('\n✓ Context cleared.\n'));
|
|
355
|
+
break;
|
|
356
|
+
|
|
357
|
+
case '/context':
|
|
358
|
+
console.log(chalk.cyan('\n📋 Current Context:'));
|
|
359
|
+
console.log(chalk.gray(` Errors collected: ${context.errors.length}`));
|
|
360
|
+
console.log(chalk.gray(` Last analysis: ${context.lastAnalysis ? 'Yes' : 'No'}`));
|
|
361
|
+
if (context.errors.length > 0) {
|
|
362
|
+
console.log(chalk.gray('\n Recent errors:'));
|
|
363
|
+
context.errors.slice(-3).forEach((e, i) => {
|
|
364
|
+
console.log(chalk.gray(` ${i + 1}. ${e.substring(0, 60)}${e.length > 60 ? '...' : ''}`));
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
console.log();
|
|
368
|
+
break;
|
|
369
|
+
|
|
370
|
+
case '/help':
|
|
371
|
+
console.log(chalk.cyan(`
|
|
372
|
+
Commands:
|
|
373
|
+
/scan Auto-scan project for errors
|
|
374
|
+
/fix Apply last suggested fix
|
|
375
|
+
/retry Retry with accumulated context
|
|
376
|
+
/clear Clear all context
|
|
377
|
+
/context Show current context
|
|
378
|
+
/help Show this help
|
|
379
|
+
/quit Exit debug mode
|
|
380
|
+
|
|
381
|
+
Tips:
|
|
382
|
+
• Paste error messages directly for analysis
|
|
383
|
+
• Describe what's wrong in plain English
|
|
384
|
+
• Use /scan for automatic error detection
|
|
385
|
+
• Context accumulates - use /clear to reset
|
|
386
|
+
`));
|
|
387
|
+
break;
|
|
388
|
+
|
|
389
|
+
case '/quit':
|
|
390
|
+
case '/exit':
|
|
391
|
+
case '/q':
|
|
392
|
+
rl.close();
|
|
393
|
+
break;
|
|
394
|
+
|
|
395
|
+
default:
|
|
396
|
+
console.log(chalk.yellow(`\nUnknown command: ${cmd}`));
|
|
397
|
+
console.log(chalk.gray('Type /help for available commands.\n'));
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Handle user input (error description or log)
|
|
403
|
+
*/
|
|
404
|
+
async function handleDebugInput(input, engine, context) {
|
|
405
|
+
// Add to context
|
|
406
|
+
context.errors.push(input);
|
|
407
|
+
|
|
408
|
+
// Show spinner
|
|
409
|
+
const spinner = ora('Analyzing error...').start();
|
|
410
|
+
|
|
411
|
+
try {
|
|
412
|
+
const result = await engine.debug({ description: input });
|
|
413
|
+
context.lastAnalysis = result;
|
|
414
|
+
|
|
415
|
+
spinner.stop();
|
|
416
|
+
|
|
417
|
+
if (result.status === 'resolved') {
|
|
418
|
+
console.log(chalk.green('\n✅ Error analyzed and fixed!\n'));
|
|
419
|
+
} else if (result.status === 'no_error') {
|
|
420
|
+
console.log(chalk.green('\n✅ No actionable error found.\n'));
|
|
421
|
+
} else {
|
|
422
|
+
console.log(chalk.yellow('\n⚠️ Analysis complete. Use /fix to apply suggested fix.\n'));
|
|
423
|
+
|
|
424
|
+
// Show brief analysis
|
|
425
|
+
if (result.session && result.session.steps > 0) {
|
|
426
|
+
console.log(chalk.gray(` Steps completed: ${result.session.steps}`));
|
|
427
|
+
console.log(chalk.gray(` Attempts: ${result.session.attempts}`));
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
} catch (error) {
|
|
431
|
+
spinner.stop();
|
|
432
|
+
console.log(chalk.red(`\nAnalysis error: ${error.message}\n`));
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Interactive log paste mode (for future enhancement)
|
|
438
|
+
*/
|
|
439
|
+
async function interactiveLogMode() {
|
|
440
|
+
console.log(chalk.cyan('Paste your error log below (end with Ctrl+D):'));
|
|
441
|
+
console.log(chalk.gray('---'));
|
|
442
|
+
|
|
443
|
+
let logContent = '';
|
|
444
|
+
|
|
445
|
+
process.stdin.setEncoding('utf8');
|
|
446
|
+
|
|
447
|
+
return new Promise((resolve) => {
|
|
448
|
+
process.stdin.on('data', (chunk) => {
|
|
449
|
+
logContent += chunk;
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
process.stdin.on('end', () => {
|
|
453
|
+
console.log(chalk.gray('---'));
|
|
454
|
+
resolve(logContent.trim());
|
|
455
|
+
});
|
|
456
|
+
});
|
|
457
|
+
}
|