deepdebug-local-agent 0.3.15 → 0.3.17

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepdebug-local-agent",
3
- "version": "0.3.15",
3
+ "version": "0.3.17",
4
4
  "description": "Insptech AI — DeepDebug Local Agent. Autonomous code debugging agent for production environments.",
5
5
  "type": "module",
6
6
  "main": "src/server.js",
@@ -161,7 +161,7 @@ export function startMCPHttpServer(workspaceManager, port = 5056) {
161
161
 
162
162
  try {
163
163
  const root = workspaceManager.resolveRoot(workspaceId);
164
- const results = await grepWorkspace(root, query, filePattern, maxResults);
164
+ const results = await grepWorkspaceX(root, query, filePattern, maxResults);
165
165
  res.json({ ok: true, query, matches: results.length, results });
166
166
  } catch (e) {
167
167
  res.status(400).json({ error: e.message });
@@ -183,7 +183,7 @@ export function startMCPHttpServer(workspaceManager, port = 5056) {
183
183
 
184
184
  try {
185
185
  const root = workspaceManager.resolveRoot(workspaceId);
186
- const result = await execInWorkspace(root, command, timeout);
186
+ const result = await execInWorkspaceX(root, command, timeout);
187
187
  res.json({ ok: result.exitCode === 0, ...result });
188
188
  } catch (e) {
189
189
  res.status(400).json({ error: e.message });
@@ -310,4 +310,100 @@ function execInWorkspace(root, command, timeoutSec) {
310
310
  resolve({ exitCode: code, stdout, stderr: stderr.substring(0, 5000), timedOut: false });
311
311
  });
312
312
  });
313
- }
313
+ }
314
+ // ========================================
315
+ // WINDOWS IMPLEMENTATIONS
316
+ // ========================================
317
+
318
+ import fs from "fs";
319
+ const { promises: fsp } = fs;
320
+
321
+ /**
322
+ * grepWorkspaceWindows — Pure Node.js search, no grep required.
323
+ * Used automatically on Windows (process.platform === "win32").
324
+ */
325
+ async function grepWorkspaceWindows(root, query, filePattern, maxResults) {
326
+ const results = [];
327
+ const queryLower = query.toLowerCase();
328
+
329
+ let fileRegex = null;
330
+ if (filePattern && filePattern !== "*") {
331
+ const escaped = filePattern
332
+ .replace(/[.+^${}()|[\]\\]/g, "\\$&")
333
+ .replace(/\*/g, ".*");
334
+ fileRegex = new RegExp(escaped + "$", "i");
335
+ }
336
+
337
+ async function searchDir(dir) {
338
+ if (results.length >= maxResults) return;
339
+ let entries;
340
+ try { entries = await fsp.readdir(dir, { withFileTypes: true }); }
341
+ catch { return; }
342
+
343
+ for (const entry of entries) {
344
+ if (results.length >= maxResults) break;
345
+ const fullPath = path.join(dir, entry.name);
346
+ const relPath = path.relative(root, fullPath).replace(/\\/g, "/");
347
+
348
+ if (entry.isDirectory()) {
349
+ if (IGNORE_DIRS.includes(entry.name)) continue;
350
+ await searchDir(fullPath);
351
+ } else if (entry.isFile()) {
352
+ if (fileRegex && !fileRegex.test(entry.name)) continue;
353
+ const stat = await fsp.stat(fullPath).catch(() => null);
354
+ if (!stat || stat.size > 500000) continue;
355
+
356
+ try {
357
+ const content = await fsp.readFile(fullPath, "utf8");
358
+ const lines = content.split("\n");
359
+ for (let i = 0; i < lines.length && results.length < maxResults; i++) {
360
+ if (lines[i].toLowerCase().includes(queryLower)) {
361
+ results.push({ file: relPath, line: i + 1, content: lines[i].trim() });
362
+ }
363
+ }
364
+ } catch { /* skip unreadable */ }
365
+ }
366
+ }
367
+ }
368
+
369
+ await searchDir(root);
370
+ return results;
371
+ }
372
+
373
+ /**
374
+ * execInWorkspaceWindows — Uses cmd.exe instead of sh.
375
+ * Used automatically on Windows.
376
+ */
377
+ function execInWorkspaceWindows(root, command, timeoutSec) {
378
+ return new Promise((resolve) => {
379
+ const child = spawn("cmd.exe", ["/c", command], { cwd: root });
380
+ let stdout = "";
381
+ let stderr = "";
382
+
383
+ child.stdout.on("data", d => stdout += d.toString());
384
+ child.stderr.on("data", d => stderr += d.toString());
385
+
386
+ child.on("error", (err) => {
387
+ resolve({ exitCode: -1, stdout: "", stderr: err.message, timedOut: false });
388
+ });
389
+
390
+ const timer = setTimeout(() => {
391
+ try { child.kill("SIGKILL"); } catch {}
392
+ resolve({ exitCode: -1, stdout, stderr, timedOut: true });
393
+ }, timeoutSec * 1000);
394
+
395
+ child.on("close", (code) => {
396
+ clearTimeout(timer);
397
+ const maxLen = 10000;
398
+ if (stdout.length > maxLen) {
399
+ stdout = stdout.substring(0, maxLen / 2) + "\n...(truncated)...\n" + stdout.substring(stdout.length - maxLen / 2);
400
+ }
401
+ resolve({ exitCode: code ?? 0, stdout, stderr: stderr.substring(0, 5000), timedOut: false });
402
+ });
403
+ });
404
+ }
405
+
406
+ // Platform dispatchers — original functions unchanged above
407
+ const IS_WINDOWS = process.platform === "win32";
408
+ const grepWorkspaceX = IS_WINDOWS ? grepWorkspaceWindows : grepWorkspace;
409
+ const execInWorkspaceX = IS_WINDOWS ? execInWorkspaceWindows : execInWorkspace;
package/src/server.js CHANGED
@@ -27,11 +27,9 @@ import { startMCPHttpServer } from "./mcp-http-server.js";
27
27
 
28
28
  const execAsync = promisify(exec);
29
29
 
30
- // ============================================
31
30
  // 🧠 AI VIBE CODING ENGINE
32
31
  // Sistema universal de auto-healing que usa AI
33
32
  // para resolver QUALQUER erro automaticamente
34
- // ============================================
35
33
 
36
34
  class AIVibeCodingEngine extends EventEmitter {
37
35
  constructor(processManager, getWorkspaceRoot) {
@@ -557,10 +555,7 @@ app.use(cors({
557
555
  // Cloud Run URLs (regex patterns)
558
556
  /https:\/\/.*\.run\.app$/,
559
557
  /https:\/\/.*\.web\.app$/,
560
- <<<<<<< HEAD
561
558
  // Production frontend
562
- =======
563
- >>>>>>> dd7d3ab (fix: add deepdebug.ai to CORS origins)
564
559
  "https://deepdebug.ai",
565
560
  "https://www.deepdebug.ai"
566
561
  ],
@@ -591,10 +586,8 @@ const MCP_PORT = process.env.MCP_PORT || 5056;
591
586
  // 🧠 Inicializar AI Vibe Coding Engine
592
587
  aiEngine = new AIVibeCodingEngine(processManager, () => WORKSPACE_ROOT);
593
588
 
594
- // ============================================
595
589
  // 🆕 BACKUP STORAGE (Sprint 1.3)
596
590
  // In-memory backup storage with configurable max size
597
- // ============================================
598
591
  const BACKUPS = new Map();
599
592
  const MAX_BACKUPS = 50;
600
593
  const BACKUP_INDEX_PATH = path.join(os.tmpdir(), 'deepdebug-backups-index.json');
@@ -891,9 +884,7 @@ app.post("/workspace/batch-read", async (req, res) => {
891
884
  }
892
885
  });
893
886
 
894
- // ============================================
895
887
  // 🆕 FILE VALIDATION ENDPOINTS (Enhanced Analysis)
896
- // ============================================
897
888
 
898
889
  /**
899
890
  * GET /workspace/file-exists
@@ -1253,9 +1244,7 @@ app.post("/workspace/find-field-definition", async (req, res) => {
1253
1244
  });
1254
1245
 
1255
1246
 
1256
- // ============================================
1257
1247
  // 🆕 RUNTIME MANAGEMENT ENDPOINTS
1258
- // ============================================
1259
1248
 
1260
1249
  /** Detecta serviços no workspace */
1261
1250
  app.get("/workspace/services/detect", async (_req, res) => {
@@ -1406,9 +1395,7 @@ app.get("/workspace/services/:serviceId/logs/stream", (req, res) => {
1406
1395
  });
1407
1396
  });
1408
1397
 
1409
- // ============================================
1410
1398
  // ENDPOINTS LEGADOS (manter compatibilidade)
1411
- // ============================================
1412
1399
 
1413
1400
  app.get("/workspace/files", async (req, res) => {
1414
1401
  if (!WORKSPACE_ROOT) return res.status(400).json({ error: "workspace not set" });
@@ -1441,9 +1428,7 @@ app.post("/workspace/write", async (req, res) => {
1441
1428
  }
1442
1429
  });
1443
1430
 
1444
- // ============================================
1445
1431
  // ✅ CORRECTED: /workspace/patch endpoint
1446
- // ============================================
1447
1432
  app.post("/workspace/patch", async (req, res) => {
1448
1433
  if (!WORKSPACE_ROOT) return res.status(400).json({ error: "workspace not set" });
1449
1434
  const { diff, incidentId } = req.body || {};
@@ -1499,9 +1484,7 @@ app.post("/workspace/run", async (req, res) => {
1499
1484
  res.json(out);
1500
1485
  });
1501
1486
 
1502
- // ============================================
1503
1487
  // 🆕 TEST LOCAL ENDPOINTS
1504
- // ============================================
1505
1488
 
1506
1489
  /** Store test local state */
1507
1490
  let TEST_LOCAL_STATE = {
@@ -1514,9 +1497,7 @@ let TEST_LOCAL_STATE = {
1514
1497
  serverLogs: [] // Buffer circular de logs do servidor (últimos 1000)
1515
1498
  };
1516
1499
 
1517
- // ============================================
1518
1500
  // 🆕 TEST LOCAL STATE ENDPOINTS (ADDED)
1519
- // ============================================
1520
1501
 
1521
1502
  /**
1522
1503
  * GET /workspace/test-local/state
@@ -2020,10 +2001,8 @@ app.get("/workspace/config", async (_req, res) => {
2020
2001
  }
2021
2002
  });
2022
2003
 
2023
- // ============================================
2024
2004
  // 🆕 BACKUP & ROLLBACK ENDPOINTS (Sprint 1.3)
2025
2005
  // Added without modifying existing endpoints
2026
- // ============================================
2027
2006
 
2028
2007
  /**
2029
2008
  * Helper: Validate diff format
@@ -2428,11 +2407,9 @@ app.delete("/workspace/backups/:backupId", (req, res) => {
2428
2407
  });
2429
2408
  });
2430
2409
 
2431
- // ============================================
2432
2410
  // 📊 DIFF VIEWER ENDPOINT
2433
2411
  // Returns before/after content for files modified by a patch
2434
2412
  // Used by the frontend diff viewer
2435
- // ============================================
2436
2413
 
2437
2414
  /**
2438
2415
  * GET /workspace/diff/by-incident/:incidentId
@@ -2612,10 +2589,8 @@ app.get("/workspace/diff/:backupId", async (req, res) => {
2612
2589
  }
2613
2590
  });
2614
2591
 
2615
- // ============================================
2616
2592
  // 🆕 DETECT PORT ENDPOINT (Sprint 1.2)
2617
2593
  // Multi-language port detection
2618
- // ============================================
2619
2594
 
2620
2595
  /**
2621
2596
  * GET /workspace/detect-port
@@ -2886,9 +2861,7 @@ async function detectDotNetPort(servicePath) {
2886
2861
  return { port: 5000, method: 'dotnet-default' };
2887
2862
  }
2888
2863
 
2889
- // ============================================
2890
2864
  // TEST LOCAL ENDPOINTS (existing)
2891
- // ============================================
2892
2865
 
2893
2866
  /** Prepare for testing: compile + discover endpoints */
2894
2867
  app.post("/workspace/test-local/prepare", async (req, res) => {
@@ -3139,10 +3112,8 @@ app.get("/workspace/test-local/logs/stream", async (req, res) => {
3139
3112
  }
3140
3113
  });
3141
3114
 
3142
- // ============================================
3143
3115
  // 🆕 AUTO-TRAINING ENDPOINTS
3144
3116
  // Escanear e ler arquivos para treinamento AI
3145
- // ============================================
3146
3117
 
3147
3118
  /**
3148
3119
  * POST /workspace/scan-files
@@ -3361,10 +3332,8 @@ app.post("/workspace/read-files", async (req, res) => {
3361
3332
  }
3362
3333
  });
3363
3334
 
3364
- // ============================================
3365
3335
  // 🆕 SYSTEM FOLDER PICKER ENDPOINT
3366
3336
  // Abre file picker nativo do SO (Windows/Mac/Linux)
3367
- // ============================================
3368
3337
 
3369
3338
  /**
3370
3339
  * GET /system/folder-picker
@@ -3487,10 +3456,8 @@ app.get("/system/info", (req, res) => {
3487
3456
  });
3488
3457
  });
3489
3458
 
3490
- // ============================================
3491
3459
  // 🆕 API DOCS ENDPOINT
3492
3460
  // Retorna endpoints detectados das controllers
3493
- // ============================================
3494
3461
 
3495
3462
  /**
3496
3463
  * GET /workspace/api-docs
@@ -3670,9 +3637,7 @@ app.get("/workspace/api-docs/:controller", async (req, res) => {
3670
3637
  }
3671
3638
  });
3672
3639
 
3673
- // ============================================
3674
3640
  // 🧠 AI ENGINE ENDPOINTS
3675
- // ============================================
3676
3641
 
3677
3642
  /**
3678
3643
  * GET /ai-engine/status
@@ -3878,10 +3843,8 @@ app.post("/workspace/test-local/restart", async (req, res) => {
3878
3843
  }
3879
3844
  });
3880
3845
 
3881
- // ============================================
3882
3846
  // 🤖 AGENTIC TOOLS ENDPOINTS
3883
3847
  // Used by the agentic Claude loop for autonomous debugging
3884
- // ============================================
3885
3848
 
3886
3849
  /**
3887
3850
  * POST /workspace/search
@@ -4051,10 +4014,8 @@ app.post("/workspace/exec", async (req, res) => {
4051
4014
  }
4052
4015
  });
4053
4016
 
4054
- // ============================================
4055
4017
  // 🧪 ENDPOINT TESTING
4056
4018
  // Execute curl-like requests and capture full request/response
4057
- // ============================================
4058
4019
 
4059
4020
  /**
4060
4021
  * POST /workspace/test-endpoint
@@ -4145,10 +4106,8 @@ app.post("/workspace/test-endpoint", async (req, res) => {
4145
4106
  }
4146
4107
  });
4147
4108
 
4148
- // ============================================
4149
4109
  // 🔀 GIT INTEGRATION
4150
4110
  // Create branch, commit, push for auto-fix PRs
4151
- // ============================================
4152
4111
 
4153
4112
  /**
4154
4113
  * POST /workspace/git/create-fix-branch
@@ -4617,11 +4576,9 @@ app.get("/workspace/git/status", async (req, res) => {
4617
4576
  }
4618
4577
  });
4619
4578
 
4620
- // ============================================
4621
4579
  // 💬 PULL REQUEST COMMENTS ENDPOINTS
4622
4580
  // Read, reply, and resolve PR comments via git providers
4623
4581
  // Used by the frontend "Code Review" tab in incident detail
4624
- // ============================================
4625
4582
 
4626
4583
  /**
4627
4584
  * GET /workspace/git/pr/comments
@@ -4941,10 +4898,8 @@ app.post("/workspace/git/pr/comments/:commentId/fix-and-resolve", async (req, re
4941
4898
  });
4942
4899
 
4943
4900
 
4944
- // ============================================
4945
4901
  // 🔧 GIT PROVIDER HELPER (internal)
4946
4902
  // Detects provider from remote URL and configures with token
4947
- // ============================================
4948
4903
 
4949
4904
  async function _getGitProvider() {
4950
4905
  if (!WORKSPACE_ROOT) return null;
@@ -5007,9 +4962,7 @@ async function _getGitProvider() {
5007
4962
  return null;
5008
4963
  }
5009
4964
  }
5010
- // ============================================
5011
4965
  // 📂 MULTI-WORKSPACE ENDPOINTS
5012
- // ============================================
5013
4966
 
5014
4967
  /** Lista todos os workspaces abertos */
5015
4968
  app.get("/workspaces", (_req, res) => {
@@ -5087,10 +5040,8 @@ app.post("/workspace/:workspaceId/run", async (req, res) => {
5087
5040
  });
5088
5041
 
5089
5042
 
5090
- // ============================================
5091
5043
  // 🔌 WEBSOCKET REVERSE TUNNEL
5092
5044
  // Connects Local Agent to Gateway — no public URL needed
5093
- // ============================================
5094
5045
  async function startWebSocketTunnel(port, gatewayUrl, apiKey, tenantId) {
5095
5046
  if (!gatewayUrl || !apiKey || !tenantId) {
5096
5047
  console.log('⚠️ WebSocket tunnel skipped: missing gatewayUrl, apiKey or tenantId in ~/.deepdebug/config.json');
@@ -5204,9 +5155,7 @@ async function startWebSocketTunnel(port, gatewayUrl, apiKey, tenantId) {
5204
5155
  return await res.json();
5205
5156
  }
5206
5157
 
5207
- // ============================================
5208
5158
  // MCP TOOLS — routed via MCP HTTP Bridge (port 5056)
5209
- // ============================================
5210
5159
  case 'mcp.read-file': {
5211
5160
  const mcpBase = `http://localhost:5056`;
5212
5161
  const res = await fetch(`${mcpBase}/mcp/read-file`, {
@@ -5329,9 +5278,7 @@ async function startWebSocketTunnel(port, gatewayUrl, apiKey, tenantId) {
5329
5278
  connect();
5330
5279
  }
5331
5280
 
5332
- // ============================================
5333
5281
  // START SERVER
5334
- // ============================================
5335
5282
  app.listen(PORT, '0.0.0.0', async () => {
5336
5283
  console.log(`\n🔌 DeepDebug Local Agent listening on port ${PORT}`);
5337
5284
  console.log(`📦 Environment: ${process.env.NODE_ENV || 'development'}`);