deepdebug-local-agent 1.0.6 → 1.0.9

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.
Files changed (2) hide show
  1. package/bin/install.js +169 -18
  2. 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: [], // Empty - workspaces configured in dashboard
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
- try { execSync('docker stop deepdebug-agent', { stdio: 'ignore' }); execSync('docker rm deepdebug-agent', { stdio: 'ignore' }); } catch {}
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.replace(/\\/g, '/').replace(/^([A-Za-z]):/, '/$1');
431
+ configMount = convertToDockerPath(configMount);
432
+ projectsMount = convertToDockerPath(projectsMount);
332
433
  }
333
434
 
435
+ // Build docker run command
334
436
  const dockerArgs = [
335
- 'run', '-d', '--name', 'deepdebug-agent', '-p', '5055:5055',
437
+ 'run', '-d',
438
+ '--name', 'deepdebug-agent',
439
+ '-p', '5055:5055',
336
440
  '-v', `${configMount}:/home/deepdebug/.deepdebug:ro`,
337
- '-e', `DEEPDEBUG_GATEWAY_URL=${config.gatewayUrl}`,
338
- '-e', `DEEPDEBUG_TENANT_ID=${config.tenantId}`,
339
- '-e', `DEEPDEBUG_AUTH_TOKEN=${config.authorizationToken}`,
340
- '--restart', 'unless-stopped', DOCKER_IMAGE
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) { logError(`Authorization failed: ${authResult.error}`); process.exit(1); }
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('Workspaces can be configured in the DeepDebug dashboard.');
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) { logError('Not configured. Run "npx deepdebug-local-agent install" first.'); process.exit(1); }
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) { logError(`Authorization invalid: ${validation.message}`); process.exit(1); }
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 { execSync('docker stop deepdebug-agent', { stdio: 'inherit' }); logSuccess('Agent stopped.'); }
477
- catch { logWarning('Agent is not running.'); }
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 { logWarning('Health: Cannot connect'); }
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 { execSync('docker stop deepdebug-agent', { stdio: 'ignore' }); execSync('docker rm deepdebug-agent', { stdio: 'ignore' }); } catch {}
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 {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepdebug-local-agent",
3
- "version": "1.0.6",
3
+ "version": "1.0.9",
4
4
  "description": "DeepDebug Local Agent - AI-powered code debugging assistant",
5
5
  "private": false,
6
6
  "type": "module",