deepdebug-local-agent 1.0.5 → 1.0.8
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/install.js +169 -18
- package/package.json +1 -1
package/bin/install.js
CHANGED
|
@@ -47,6 +47,35 @@ function getOsVersion() {
|
|
|
47
47
|
return `${os.type()} ${os.release()}`;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
function getDefaultProjectsPath() {
|
|
51
|
+
const home = os.homedir();
|
|
52
|
+
if (isWindows) {
|
|
53
|
+
// Check common Windows paths
|
|
54
|
+
const documentsProjects = path.join(home, 'Documents', 'Projects');
|
|
55
|
+
const projects = path.join(home, 'Projects');
|
|
56
|
+
const repos = path.join(home, 'repos');
|
|
57
|
+
const source = path.join(home, 'source', 'repos'); // Visual Studio default
|
|
58
|
+
|
|
59
|
+
if (fs.existsSync(documentsProjects)) return documentsProjects;
|
|
60
|
+
if (fs.existsSync(projects)) return projects;
|
|
61
|
+
if (fs.existsSync(repos)) return repos;
|
|
62
|
+
if (fs.existsSync(source)) return source;
|
|
63
|
+
return documentsProjects; // Default
|
|
64
|
+
} else {
|
|
65
|
+
// macOS / Linux
|
|
66
|
+
const projects = path.join(home, 'Projects');
|
|
67
|
+
const dev = path.join(home, 'dev');
|
|
68
|
+
const code = path.join(home, 'code');
|
|
69
|
+
const repos = path.join(home, 'repos');
|
|
70
|
+
|
|
71
|
+
if (fs.existsSync(projects)) return projects;
|
|
72
|
+
if (fs.existsSync(dev)) return dev;
|
|
73
|
+
if (fs.existsSync(code)) return code;
|
|
74
|
+
if (fs.existsSync(repos)) return repos;
|
|
75
|
+
return projects; // Default
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
50
79
|
// ============================================
|
|
51
80
|
// Console colors (cross-platform)
|
|
52
81
|
// ============================================
|
|
@@ -245,10 +274,67 @@ async function selectPermissions() {
|
|
|
245
274
|
return granted;
|
|
246
275
|
}
|
|
247
276
|
|
|
277
|
+
// ============================================
|
|
278
|
+
// Projects folder selection
|
|
279
|
+
// ============================================
|
|
280
|
+
async function selectProjectsFolder() {
|
|
281
|
+
console.log();
|
|
282
|
+
log('╔══════════════════════════════════════════════════════════════════╗', 'cyan');
|
|
283
|
+
log('║ PROJECTS FOLDER SETUP ║', 'cyan');
|
|
284
|
+
log('╚══════════════════════════════════════════════════════════════════╝', 'cyan');
|
|
285
|
+
console.log();
|
|
286
|
+
log('DeepDebug needs access to your projects folder to:', 'bright');
|
|
287
|
+
log(' • Read source code for error analysis', 'reset');
|
|
288
|
+
log(' • Apply AI-suggested fixes (with your permission)', 'reset');
|
|
289
|
+
log(' • Monitor build outputs and logs', 'reset');
|
|
290
|
+
console.log();
|
|
291
|
+
|
|
292
|
+
const defaultPath = getDefaultProjectsPath();
|
|
293
|
+
log(`Detected default projects folder: ${defaultPath}`, 'cyan');
|
|
294
|
+
console.log();
|
|
295
|
+
|
|
296
|
+
const customPath = await prompt(`Enter your projects folder path [${defaultPath}]: `);
|
|
297
|
+
const selectedPath = customPath || defaultPath;
|
|
298
|
+
|
|
299
|
+
// Validate path exists
|
|
300
|
+
if (!fs.existsSync(selectedPath)) {
|
|
301
|
+
logWarning(`Folder does not exist: ${selectedPath}`);
|
|
302
|
+
const create = await promptYesNo('Create this folder?', true);
|
|
303
|
+
if (create) {
|
|
304
|
+
fs.mkdirSync(selectedPath, { recursive: true });
|
|
305
|
+
logSuccess(`Created folder: ${selectedPath}`);
|
|
306
|
+
} else {
|
|
307
|
+
logError('Projects folder is required for DeepDebug to function.');
|
|
308
|
+
process.exit(1);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// List subfolders (potential projects)
|
|
313
|
+
try {
|
|
314
|
+
const items = fs.readdirSync(selectedPath, { withFileTypes: true });
|
|
315
|
+
const folders = items.filter(i => i.isDirectory() && !i.name.startsWith('.')).map(i => i.name);
|
|
316
|
+
|
|
317
|
+
if (folders.length > 0) {
|
|
318
|
+
console.log();
|
|
319
|
+
log('Found projects in this folder:', 'green');
|
|
320
|
+
folders.slice(0, 10).forEach(f => log(` 📁 ${f}`, 'reset'));
|
|
321
|
+
if (folders.length > 10) {
|
|
322
|
+
log(` ... and ${folders.length - 10} more`, 'reset');
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
} catch (e) {
|
|
326
|
+
// Ignore errors listing folder
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
console.log();
|
|
330
|
+
logSuccess(`Projects folder: ${selectedPath}`);
|
|
331
|
+
return selectedPath;
|
|
332
|
+
}
|
|
333
|
+
|
|
248
334
|
// ============================================
|
|
249
335
|
// API functions
|
|
250
336
|
// ============================================
|
|
251
|
-
async function authorizeWithServer(apiKey, permissions) {
|
|
337
|
+
async function authorizeWithServer(apiKey, permissions, projectsPath) {
|
|
252
338
|
const machineId = getMachineId();
|
|
253
339
|
const machineName = getMachineName();
|
|
254
340
|
const osType = getOsType();
|
|
@@ -268,7 +354,7 @@ async function authorizeWithServer(apiKey, permissions) {
|
|
|
268
354
|
osType,
|
|
269
355
|
osVersion,
|
|
270
356
|
permissions,
|
|
271
|
-
workspacePaths: [],
|
|
357
|
+
workspacePaths: [projectsPath],
|
|
272
358
|
agentVersion
|
|
273
359
|
})
|
|
274
360
|
});
|
|
@@ -320,25 +406,48 @@ function isAgentContainerRunning() {
|
|
|
320
406
|
} catch { return false; }
|
|
321
407
|
}
|
|
322
408
|
|
|
409
|
+
function convertToDockerPath(windowsPath) {
|
|
410
|
+
if (!isWindows) return windowsPath;
|
|
411
|
+
// Convert C:\Users\foo to /c/Users/foo for Docker
|
|
412
|
+
return windowsPath.replace(/\\/g, '/').replace(/^([A-Za-z]):/, (_, letter) => `/${letter.toLowerCase()}`);
|
|
413
|
+
}
|
|
414
|
+
|
|
323
415
|
function startDockerAgent(config) {
|
|
324
416
|
try {
|
|
325
|
-
|
|
417
|
+
// Stop existing container
|
|
418
|
+
try {
|
|
419
|
+
execSync('docker stop deepdebug-agent', { stdio: 'ignore' });
|
|
420
|
+
execSync('docker rm deepdebug-agent', { stdio: 'ignore' });
|
|
421
|
+
} catch {}
|
|
422
|
+
|
|
326
423
|
logInfo('Pulling latest DeepDebug Local Agent image...');
|
|
327
424
|
execSync(`docker pull ${DOCKER_IMAGE}`, { stdio: 'inherit' });
|
|
328
425
|
|
|
426
|
+
// Prepare paths for Docker
|
|
329
427
|
let configMount = CONFIG_DIR;
|
|
428
|
+
let projectsMount = config.projectsPath;
|
|
429
|
+
|
|
330
430
|
if (isWindows) {
|
|
331
|
-
configMount = configMount
|
|
431
|
+
configMount = convertToDockerPath(configMount);
|
|
432
|
+
projectsMount = convertToDockerPath(projectsMount);
|
|
332
433
|
}
|
|
333
434
|
|
|
435
|
+
// Build docker run command
|
|
334
436
|
const dockerArgs = [
|
|
335
|
-
'run', '-d',
|
|
437
|
+
'run', '-d',
|
|
438
|
+
'--name', 'deepdebug-agent',
|
|
439
|
+
'-p', '5055:5055',
|
|
336
440
|
'-v', `${configMount}:/home/deepdebug/.deepdebug:ro`,
|
|
337
|
-
'-
|
|
338
|
-
'-e', `
|
|
339
|
-
'-e', `
|
|
340
|
-
'
|
|
441
|
+
'-v', `${projectsMount}:/workspace:rw`,
|
|
442
|
+
'-e', `GATEWAY_URL=${config.gatewayUrl}`,
|
|
443
|
+
'-e', `TENANT_ID=${config.tenantId}`,
|
|
444
|
+
'-e', `AUTH_TOKEN=${config.authorizationToken}`,
|
|
445
|
+
'-e', `WORKSPACE_ROOT=/workspace`,
|
|
446
|
+
'--restart', 'unless-stopped',
|
|
447
|
+
DOCKER_IMAGE
|
|
341
448
|
];
|
|
449
|
+
|
|
450
|
+
logInfo('Starting Docker container with workspace mounted...');
|
|
342
451
|
execSync(`docker ${dockerArgs.join(' ')}`, { stdio: 'inherit' });
|
|
343
452
|
logSuccess('DeepDebug Local Agent started successfully!');
|
|
344
453
|
return true;
|
|
@@ -364,12 +473,16 @@ async function install(options = {}) {
|
|
|
364
473
|
if (isConfigured() && !options.force) {
|
|
365
474
|
const config = loadConfig();
|
|
366
475
|
logInfo(`Already configured for tenant: ${config.tenantName || config.tenantId}`);
|
|
476
|
+
if (config.projectsPath) {
|
|
477
|
+
logInfo(`Projects folder: ${config.projectsPath}`);
|
|
478
|
+
}
|
|
367
479
|
if (!await promptYesNo('Do you want to reconfigure?', false)) {
|
|
368
480
|
logInfo('Run "npx deepdebug-local-agent start" to start the agent.');
|
|
369
481
|
return;
|
|
370
482
|
}
|
|
371
483
|
}
|
|
372
484
|
|
|
485
|
+
// Step 1: API Key
|
|
373
486
|
let apiKey = options.apiKey;
|
|
374
487
|
if (!apiKey) {
|
|
375
488
|
console.log();
|
|
@@ -381,20 +494,30 @@ async function install(options = {}) {
|
|
|
381
494
|
}
|
|
382
495
|
if (!apiKey) { logError('API Key is required'); process.exit(1); }
|
|
383
496
|
|
|
497
|
+
// Step 2: Authorization terms
|
|
384
498
|
displayAuthorizationTerms();
|
|
385
499
|
if (!await promptYesNo('Do you authorize the DeepDebug Local Agent with these permissions?', false)) {
|
|
386
500
|
logWarning('Authorization declined. Installation cancelled.');
|
|
387
501
|
process.exit(0);
|
|
388
502
|
}
|
|
389
503
|
|
|
504
|
+
// Step 3: Select permissions
|
|
390
505
|
const permissions = await selectPermissions();
|
|
391
506
|
logInfo(`Selected permissions: ${permissions.join(', ')}`);
|
|
392
507
|
|
|
508
|
+
// Step 4: Projects folder
|
|
509
|
+
const projectsPath = await selectProjectsFolder();
|
|
510
|
+
|
|
511
|
+
// Step 5: Authorize with server
|
|
393
512
|
console.log();
|
|
394
|
-
const authResult = await authorizeWithServer(apiKey, permissions);
|
|
395
|
-
if (!authResult.success) {
|
|
513
|
+
const authResult = await authorizeWithServer(apiKey, permissions, projectsPath);
|
|
514
|
+
if (!authResult.success) {
|
|
515
|
+
logError(`Authorization failed: ${authResult.error}`);
|
|
516
|
+
process.exit(1);
|
|
517
|
+
}
|
|
396
518
|
logSuccess(`Authorized for tenant: ${authResult.tenantName}`);
|
|
397
519
|
|
|
520
|
+
// Step 6: Save config
|
|
398
521
|
const config = {
|
|
399
522
|
authorizationToken: authResult.authorizationToken,
|
|
400
523
|
authorizationId: authResult.authorizationId,
|
|
@@ -403,6 +526,7 @@ async function install(options = {}) {
|
|
|
403
526
|
gatewayUrl: authResult.gatewayUrl,
|
|
404
527
|
websocketUrl: authResult.websocketUrl,
|
|
405
528
|
permissions,
|
|
529
|
+
projectsPath,
|
|
406
530
|
machineId: getMachineId(),
|
|
407
531
|
machineName: getMachineName(),
|
|
408
532
|
osType: getOsType(),
|
|
@@ -411,6 +535,7 @@ async function install(options = {}) {
|
|
|
411
535
|
};
|
|
412
536
|
saveConfig(config);
|
|
413
537
|
|
|
538
|
+
// Step 7: Docker check
|
|
414
539
|
console.log();
|
|
415
540
|
logInfo('Checking Docker installation...');
|
|
416
541
|
if (!isDockerInstalled()) {
|
|
@@ -426,6 +551,7 @@ async function install(options = {}) {
|
|
|
426
551
|
}
|
|
427
552
|
logSuccess('Docker is installed and running');
|
|
428
553
|
|
|
554
|
+
// Step 8: Start agent
|
|
429
555
|
console.log();
|
|
430
556
|
if (await promptYesNo('Start DeepDebug Local Agent now?', true)) {
|
|
431
557
|
await start();
|
|
@@ -433,12 +559,14 @@ async function install(options = {}) {
|
|
|
433
559
|
logInfo('To start later: npx deepdebug-local-agent start');
|
|
434
560
|
}
|
|
435
561
|
|
|
562
|
+
// Done!
|
|
436
563
|
console.log();
|
|
437
564
|
log('╔══════════════════════════════════════════════════════════════════╗', 'green');
|
|
438
565
|
log('║ Installation Complete! 🎉 ║', 'green');
|
|
439
566
|
log('╚══════════════════════════════════════════════════════════════════╝', 'green');
|
|
440
567
|
console.log();
|
|
441
|
-
logInfo(
|
|
568
|
+
logInfo(`Projects folder mounted: ${projectsPath}`);
|
|
569
|
+
logInfo('All projects in this folder are now accessible to DeepDebug.');
|
|
442
570
|
log('Dashboard: https://deepdebug.ai/settings/agent', 'blue');
|
|
443
571
|
console.log();
|
|
444
572
|
}
|
|
@@ -447,11 +575,23 @@ async function start() {
|
|
|
447
575
|
console.log();
|
|
448
576
|
log('🚀 Starting DeepDebug Local Agent...', 'cyan');
|
|
449
577
|
const config = loadConfig();
|
|
450
|
-
if (!config?.authorizationToken) {
|
|
578
|
+
if (!config?.authorizationToken) {
|
|
579
|
+
logError('Not configured. Run "npx deepdebug-local-agent install" first.');
|
|
580
|
+
process.exit(1);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
if (!config.projectsPath) {
|
|
584
|
+
logWarning('No projects folder configured.');
|
|
585
|
+
logInfo('Run "npx deepdebug-local-agent install --force" to reconfigure.');
|
|
586
|
+
process.exit(1);
|
|
587
|
+
}
|
|
451
588
|
|
|
452
589
|
logInfo('Validating authorization...');
|
|
453
590
|
const validation = await validateAuthorization(config.authorizationToken, config.machineId);
|
|
454
|
-
if (!validation.valid) {
|
|
591
|
+
if (!validation.valid) {
|
|
592
|
+
logError(`Authorization invalid: ${validation.message}`);
|
|
593
|
+
process.exit(1);
|
|
594
|
+
}
|
|
455
595
|
logSuccess('Authorization valid');
|
|
456
596
|
|
|
457
597
|
if (!isDockerInstalled()) { logError('Docker is not installed.'); process.exit(1); }
|
|
@@ -465,6 +605,7 @@ async function start() {
|
|
|
465
605
|
if (startDockerAgent(config)) {
|
|
466
606
|
console.log();
|
|
467
607
|
logSuccess('Agent is running!');
|
|
608
|
+
logInfo(`Projects folder: ${config.projectsPath}`);
|
|
468
609
|
logInfo('Dashboard: https://deepdebug.ai/monitoring');
|
|
469
610
|
logInfo('Local API: http://localhost:5055/health');
|
|
470
611
|
logInfo('Logs: docker logs -f deepdebug-agent');
|
|
@@ -473,8 +614,12 @@ async function start() {
|
|
|
473
614
|
|
|
474
615
|
async function stop() {
|
|
475
616
|
log('🛑 Stopping DeepDebug Local Agent...', 'yellow');
|
|
476
|
-
try {
|
|
477
|
-
|
|
617
|
+
try {
|
|
618
|
+
execSync('docker stop deepdebug-agent', { stdio: 'inherit' });
|
|
619
|
+
logSuccess('Agent stopped.');
|
|
620
|
+
} catch {
|
|
621
|
+
logWarning('Agent is not running.');
|
|
622
|
+
}
|
|
478
623
|
}
|
|
479
624
|
|
|
480
625
|
async function status() {
|
|
@@ -488,6 +633,7 @@ async function status() {
|
|
|
488
633
|
const config = loadConfig();
|
|
489
634
|
if (config) {
|
|
490
635
|
logSuccess(`Configured for: ${config.tenantName || config.tenantId}`);
|
|
636
|
+
logInfo(`Projects folder: ${config.projectsPath || 'Not configured'}`);
|
|
491
637
|
logInfo(`Permissions: ${config.permissions?.join(', ') || 'N/A'}`);
|
|
492
638
|
} else {
|
|
493
639
|
logWarning('Not configured. Run: npx deepdebug-local-agent install');
|
|
@@ -498,7 +644,9 @@ async function status() {
|
|
|
498
644
|
try {
|
|
499
645
|
const resp = await fetch('http://localhost:5055/health');
|
|
500
646
|
logSuccess(resp.ok ? 'Health: OK' : 'Health: Degraded');
|
|
501
|
-
} catch {
|
|
647
|
+
} catch {
|
|
648
|
+
logWarning('Health: Cannot connect');
|
|
649
|
+
}
|
|
502
650
|
} else {
|
|
503
651
|
logWarning('Agent: Not running');
|
|
504
652
|
}
|
|
@@ -511,7 +659,10 @@ async function logs() {
|
|
|
511
659
|
|
|
512
660
|
async function uninstall() {
|
|
513
661
|
if (!await promptYesNo('Uninstall DeepDebug Local Agent?', false)) return;
|
|
514
|
-
try {
|
|
662
|
+
try {
|
|
663
|
+
execSync('docker stop deepdebug-agent', { stdio: 'ignore' });
|
|
664
|
+
execSync('docker rm deepdebug-agent', { stdio: 'ignore' });
|
|
665
|
+
} catch {}
|
|
515
666
|
if (fs.existsSync(CONFIG_FILE)) fs.unlinkSync(CONFIG_FILE);
|
|
516
667
|
if (fs.existsSync(MACHINE_ID_FILE)) fs.unlinkSync(MACHINE_ID_FILE);
|
|
517
668
|
try { fs.rmdirSync(CONFIG_DIR); } catch {}
|