deepdebug-local-agent 1.0.17 → 1.0.18

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/package.json +1 -1
  2. package/src/server.js +298 -230
package/src/server.js CHANGED
@@ -48,7 +48,7 @@ class AIVibeCodingEngine extends EventEmitter {
48
48
  this.currentSession = null;
49
49
  this.lastSuccessfulConfig = null;
50
50
 
51
- console.log(' [AI-Engine] Vibe Coding Engine initialized');
51
+ console.log('[AI-Engine] Vibe Coding Engine initialized');
52
52
  this.setupErrorMonitoring();
53
53
  }
54
54
 
@@ -61,9 +61,9 @@ class AIVibeCodingEngine extends EventEmitter {
61
61
 
62
62
  this.processManager.on('stopped', async ({ serviceId, code, signal }) => {
63
63
  if (this.isActive && code !== 0 && code !== null) {
64
- console.log(` [AI-Engine] Process ${serviceId} crashed (code: ${code})`);
64
+ console.log(`[AI-Engine] Process ${serviceId} crashed (code: ${code})`);
65
65
  if (this.pendingFixes.length > 0) {
66
- console.log(` [AI-Engine] ${this.pendingFixes.length} fixes pending`);
66
+ console.log(`[AI-Engine] ${this.pendingFixes.length} fixes pending`);
67
67
  }
68
68
  }
69
69
  });
@@ -164,12 +164,12 @@ class AIVibeCodingEngine extends EventEmitter {
164
164
  this.errorHistory.push(entry);
165
165
  if (this.errorHistory.length > 200) this.errorHistory = this.errorHistory.slice(-200);
166
166
 
167
- console.log(` [AI-Engine] Error: ${classification.type} (${classification.severity})`);
167
+ console.log(`[AI-Engine] Error: ${classification.type} (${classification.severity})`);
168
168
 
169
169
  if (classification.autoFixable) {
170
170
  const fix = this.getQuickFix(classification.type, errorMessage);
171
171
  if (fix) {
172
- console.log(` [AI-Engine] Quick fix: ${fix.description}`);
172
+ console.log(`[AI-Engine] Quick fix: ${fix.description}`);
173
173
  this.pendingFixes.push({ errorId: entry.id, fix, timestamp: Date.now() });
174
174
  }
175
175
  }
@@ -204,7 +204,7 @@ class AIVibeCodingEngine extends EventEmitter {
204
204
  }
205
205
 
206
206
  async startWithAutoHealing(config) {
207
- console.log(' [AI-Engine] Starting with auto-healing...');
207
+ console.log('[AI-Engine] Starting with auto-healing...');
208
208
 
209
209
  this.currentSession = {
210
210
  startTime: Date.now(),
@@ -222,12 +222,12 @@ class AIVibeCodingEngine extends EventEmitter {
222
222
 
223
223
  if (attempts > 1 && this.pendingFixes.length > 0) {
224
224
  const fix = this.pendingFixes.shift();
225
- console.log(` Applying: ${fix.fix.description}`);
225
+ console.log(`Applying: ${fix.fix.description}`);
226
226
  currentConfig = this.applyFix(currentConfig, fix.fix);
227
227
  }
228
228
 
229
229
  if (currentConfig.recompile) {
230
- console.log(' Recompiling...');
230
+ console.log('Recompiling...');
231
231
  await this.recompile();
232
232
  delete currentConfig.recompile;
233
233
  }
@@ -257,16 +257,16 @@ class AIVibeCodingEngine extends EventEmitter {
257
257
  }
258
258
 
259
259
  lastError = result.error;
260
- console.log(` Attempt ${attempts} failed: ${lastError?.substring(0, 100)}...`);
260
+ console.log(`Attempt ${attempts} failed: ${lastError?.substring(0, 100)}...`);
261
261
 
262
262
  const fix = this.getFix(result.error, currentConfig);
263
263
  if (fix) {
264
- console.log(` Fix: ${fix.description}`);
264
+ console.log(`Fix: ${fix.description}`);
265
265
  currentConfig = this.applyFix(currentConfig, fix);
266
266
  } else {
267
267
  const ai = await this.analyzeWithAI('startup', lastError, currentConfig);
268
268
  if (ai?.newConfig) {
269
- console.log(` AI: ${ai.suggestion}`);
269
+ console.log(`AI: ${ai.suggestion}`);
270
270
  currentConfig = ai.newConfig;
271
271
  } else {
272
272
  break;
@@ -305,7 +305,7 @@ class AIVibeCodingEngine extends EventEmitter {
305
305
 
306
306
  // Detectar sucesso nos logs do Spring Boot
307
307
  if (isStartupSuccess(message) && !resolved) {
308
- console.log(` [AI-Engine] Detected startup success: ${message.substring(0, 80)}...`);
308
+ console.log(`[AI-Engine] Detected startup success: ${message.substring(0, 80)}...`);
309
309
  resolved = true;
310
310
  cleanup();
311
311
  resolve({ success: true, logs });
@@ -372,7 +372,7 @@ class AIVibeCodingEngine extends EventEmitter {
372
372
  newConfig.profile = next;
373
373
  newConfig.args = this.updateArgs(config.args, 'profile', next);
374
374
  newConfig.env = { ...config.env, SPRING_PROFILES_ACTIVE: next };
375
- console.log(` Profile: ${config.profile} ${next}`);
375
+ console.log(`Profile: ${config.profile} ${next}`);
376
376
  break;
377
377
 
378
378
  case 'change_port':
@@ -380,7 +380,7 @@ class AIVibeCodingEngine extends EventEmitter {
380
380
  newConfig.port = newPort;
381
381
  newConfig.args = this.updateArgs(config.args, 'port', newPort);
382
382
  newConfig.env = { ...config.env, SERVER_PORT: String(newPort), PORT: String(newPort) };
383
- console.log(` Port: ${config.port} ${newPort}`);
383
+ console.log(`Port: ${config.port} ${newPort}`);
384
384
  break;
385
385
 
386
386
  case 'recompile':
@@ -418,7 +418,7 @@ class AIVibeCodingEngine extends EventEmitter {
418
418
 
419
419
  if (response.ok) return await response.json();
420
420
  } catch (err) {
421
- console.log(` [AI-Engine] AI unavailable: ${err.message}`);
421
+ console.log(`[AI-Engine] AI unavailable: ${err.message}`);
422
422
  }
423
423
 
424
424
  return this.localFallback(errorType, error, config);
@@ -527,7 +527,7 @@ class AIVibeCodingEngine extends EventEmitter {
527
527
 
528
528
  setActive(active) {
529
529
  this.isActive = active;
530
- console.log(` [AI-Engine] ${active ? 'ENABLED' : 'DISABLED'}`);
530
+ console.log(`[AI-Engine] ${active ? 'ENABLED' : 'DISABLED'}`);
531
531
  }
532
532
 
533
533
  clearHistory() {
@@ -577,7 +577,7 @@ const DEFAULT_WORKSPACE = process.env.DEFAULT_WORKSPACE || '/Users/macintosh/Ide
577
577
 
578
578
  let WORKSPACE_ROOT = fs.existsSync(DEFAULT_WORKSPACE) ? DEFAULT_WORKSPACE : null;
579
579
  if (WORKSPACE_ROOT) {
580
- console.log(` Default workspace: ${WORKSPACE_ROOT}`);
580
+ console.log(`Default workspace: ${WORKSPACE_ROOT}`);
581
581
  }
582
582
 
583
583
  let DETECTED_SERVICES = [];
@@ -585,11 +585,31 @@ const processManager = new ProcessManager();
585
585
  const wsManager = new WorkspaceManager();
586
586
 
587
587
  function resolveWorkspaceRoot(req) {
588
+ // TENANT ISOLATION: stateless, never mutates global state.
589
+ // Returns the workspace path for THIS specific request only.
590
+ //
591
+ // Priority:
592
+ // 1. X-Workspace-Root header -- sent by Gateway with tenant NFS path (post-onboarding)
593
+ // 2. X-Workspace-Id header -- fallback via WorkspaceManager (dev/local mode)
594
+ // 3. null -- no workspace for this request (onboarding flow)
595
+ //
596
+ // IMPORTANT: Does NOT fall back to WORKSPACE_ROOT global.
597
+ // A request without a workspace header gets null, not another tenant's path.
598
+
599
+ // 1. Tenant-isolated NFS path from Gateway
600
+ const secureRoot = req.headers['x-workspace-root'];
601
+ if (secureRoot && secureRoot.trim()) {
602
+ return secureRoot.trim();
603
+ }
604
+
605
+ // 2. WorkspaceId (dev/local mode only)
588
606
  const wsId = req.headers['x-workspace-id']
589
607
  || (req.body && req.body.workspaceId)
590
608
  || req.query.workspaceId;
591
609
  if (wsId && wsManager.isOpen(wsId)) return wsManager.getRoot(wsId);
592
- return WORKSPACE_ROOT;
610
+
611
+ // 3. No workspace -- caller must handle null (e.g. onboarding endpoints)
612
+ return null;
593
613
  }
594
614
  const MCP_PORT = process.env.MCP_PORT || 5056;
595
615
 
@@ -652,7 +672,7 @@ function loadBackupIndex() {
652
672
  });
653
673
  }
654
674
  }
655
- console.log(` Restored ${BACKUPS.size} backups from disk`);
675
+ console.log(`Restored ${BACKUPS.size} backups from disk`);
656
676
  }
657
677
  } catch (e) {
658
678
  console.warn('Could not load backup index:', e.message);
@@ -664,19 +684,19 @@ loadBackupIndex();
664
684
 
665
685
  // Event listeners do ProcessManager
666
686
  processManager.on("started", ({ serviceId }) => {
667
- console.log(` Service ${serviceId} started successfully`);
687
+ console.log(`Service ${serviceId} started successfully`);
668
688
  updateServiceStatus(serviceId, "running");
669
689
  addServerLog("info", `Service ${serviceId} started successfully`);
670
690
  });
671
691
 
672
692
  processManager.on("stopped", ({ serviceId }) => {
673
- console.log(` Service ${serviceId} stopped`);
693
+ console.log(`Service ${serviceId} stopped`);
674
694
  updateServiceStatus(serviceId, "stopped");
675
695
  addServerLog("info", `Service ${serviceId} stopped`);
676
696
  });
677
697
 
678
698
  processManager.on("error", ({ serviceId, error }) => {
679
- console.error(` Service ${serviceId} error: ${error}`);
699
+ console.error(`Service ${serviceId} error: ${error}`);
680
700
  updateServiceStatus(serviceId, "failed");
681
701
  addServerLog("error", `Service ${serviceId} error: ${error}`);
682
702
  });
@@ -731,7 +751,7 @@ app.post("/workspace/open", async (req, res) => {
731
751
  // CLOUD MODE: Git clone (when Gateway sends repoUrl)
732
752
  // ==========================================
733
753
  if (repoUrl) {
734
- console.log(` [/workspace/open] CLOUD MODE cloning ${repoUrl} (branch: ${branch})`);
754
+ console.log(`[/workspace/open] CLOUD MODE cloning ${repoUrl} (branch: ${branch})`);
735
755
 
736
756
  try {
737
757
  // Extract repo name: https://github.com/org/repo org_repo
@@ -772,16 +792,16 @@ app.post("/workspace/open", async (req, res) => {
772
792
  const alreadyCloned = await exists(gitDir);
773
793
 
774
794
  if (alreadyCloned) {
775
- console.log(` [cloud] Repo exists: ${clonePath}, updating...`);
795
+ console.log(`[cloud] Repo exists: ${clonePath}, updating...`);
776
796
  // Update remote URL with fresh token
777
797
  await execAsync(`git remote set-url origin "${authUrl}"`, { cwd: clonePath }).catch(() => {});
778
798
  await execAsync(`git fetch origin`, { cwd: clonePath, timeout: 120000 });
779
799
  // Checkout correct branch and reset to remote (discard previous patches)
780
800
  await execAsync(`git checkout ${branch} 2>/dev/null || git checkout -b ${branch} origin/${branch}`, { cwd: clonePath }).catch(() => {});
781
801
  await execAsync(`git reset --hard origin/${branch}`, { cwd: clonePath });
782
- console.log(` [cloud] Updated to latest ${branch}`);
802
+ console.log(`[cloud] Updated to latest ${branch}`);
783
803
  } else {
784
- console.log(` [cloud] Cloning ${repoUrl} (branch: ${branch})...`);
804
+ console.log(`[cloud] Cloning ${repoUrl} (branch: ${branch})...`);
785
805
  await execAsync(
786
806
  `git clone --branch ${branch} --single-branch --depth 50 "${authUrl}" "${clonePath}"`,
787
807
  { timeout: 300000 }
@@ -789,7 +809,7 @@ app.post("/workspace/open", async (req, res) => {
789
809
  // Configure git user for future commits
790
810
  await execAsync(`git config user.email "deepdebug-ai@deepdebug.ai"`, { cwd: clonePath });
791
811
  await execAsync(`git config user.name "DeepDebug AI"`, { cwd: clonePath });
792
- console.log(` [cloud] Cloned successfully: ${clonePath}`);
812
+ console.log(`[cloud] Cloned successfully: ${clonePath}`);
793
813
  }
794
814
 
795
815
  // Set as active workspace
@@ -799,7 +819,7 @@ app.post("/workspace/open", async (req, res) => {
799
819
  }
800
820
  const wsId = workspaceId || "default";
801
821
  try { await wsManager.open(wsId, clonePath); } catch (err) {
802
- console.warn(` WorkspaceManager.open failed (non-fatal): ${err.message}`);
822
+ console.warn(`WorkspaceManager.open failed (non-fatal): ${err.message}`);
803
823
  }
804
824
 
805
825
  const meta = await detectProject(clonePath);
@@ -815,7 +835,7 @@ app.post("/workspace/open", async (req, res) => {
815
835
  });
816
836
 
817
837
  } catch (gitErr) {
818
- console.error(` [cloud] Git clone failed:`, gitErr.message);
838
+ console.error(`[cloud] Git clone failed:`, gitErr.message);
819
839
  const hint = gitErr.message.includes('Authentication') || gitErr.message.includes('could not read')
820
840
  ? "Authentication failed. Check token and repo URL."
821
841
  : gitErr.message.includes('not found') || gitErr.message.includes('does not exist')
@@ -842,7 +862,7 @@ app.post("/workspace/open", async (req, res) => {
842
862
  try {
843
863
  await wsManager.open(wsId, abs);
844
864
  } catch (err) {
845
- console.warn(` WorkspaceManager open failed (non-fatal): ${err.message}`);
865
+ console.warn(`WorkspaceManager open failed (non-fatal): ${err.message}`);
846
866
  }
847
867
 
848
868
  const meta = await detectProject(abs);
@@ -859,24 +879,30 @@ app.post("/workspace/open", async (req, res) => {
859
879
  */
860
880
  app.post("/workspace/clone", async (req, res) => {
861
881
  const body = req.body || {};
862
- // Accept both naming conventions:
863
- // - gitUrl + targetPath (local agent format)
864
- // - repoUrl + targetDir (cloud format)
865
- const gitUrl = body.gitUrl || body.repoUrl;
866
- const targetPath = body.targetPath || body.targetDir;
882
+ const gitUrl = body.gitUrl || body.repoUrl;
883
+ const targetPath = body.targetPath || body.targetDir;
884
+ const tenantId = body.tenantId;
867
885
  const workspaceId = body.workspaceId;
868
- const gitToken = body.gitToken;
869
- const branch = body.branch;
886
+ const gitToken = body.gitToken;
887
+ const branch = body.branch;
870
888
 
871
889
  if (!gitUrl) return res.status(400).json({ ok: false, error: "gitUrl is required" });
872
890
 
873
- // If targetPath not provided, derive from repo name
874
- const repoName = gitUrl.split('/').pop().replace('.git', '');
875
- const resolvedTarget = targetPath
876
- ? path.resolve(targetPath)
877
- : path.join(process.env.HOME || '/home/deepdebug', 'DeepDebug', repoName);
891
+ const repoName = gitUrl.split('/').pop().replace('.git', '');
892
+
893
+ const NFS_MOUNT = '/mnt/workspaces';
894
+ let absTarget;
895
+ if (tenantId && fs.existsSync(NFS_MOUNT)) {
896
+ absTarget = path.join(NFS_MOUNT, tenantId, repoName);
897
+ console.log(`[clone] Using NFS persistent storage: ${absTarget}`);
898
+ } else if (targetPath) {
899
+ absTarget = path.resolve(targetPath);
900
+ console.log(`[clone] Using explicit targetPath: ${absTarget}`);
901
+ } else {
902
+ absTarget = path.join(process.env.HOME || '/home/deepdebug', 'DeepDebug', repoName);
903
+ console.log(`[clone] Using fallback path: ${absTarget}`);
904
+ }
878
905
 
879
- // If gitToken provided and not already embedded in URL, embed it
880
906
  let authenticatedUrl = gitUrl;
881
907
  if (gitToken && gitUrl.startsWith('https://') && !gitUrl.includes('@')) {
882
908
  if (gitUrl.includes('bitbucket.org')) {
@@ -887,9 +913,7 @@ app.post("/workspace/clone", async (req, res) => {
887
913
  authenticatedUrl = gitUrl.replace('https://', `https://x-access-token:${gitToken}@`);
888
914
  }
889
915
  }
890
-
891
- const absTarget = resolvedTarget;
892
- console.log(` Clone request: ${gitUrl} -> ${absTarget}`);
916
+ console.log(`Clone request: ${gitUrl} -> ${absTarget}`);
893
917
 
894
918
  try {
895
919
  // Ensure parent directory exists
@@ -901,14 +925,22 @@ app.post("/workspace/clone", async (req, res) => {
901
925
  const alreadyCloned = await exists(gitDir);
902
926
 
903
927
  if (alreadyCloned) {
904
- console.log(` Repo already exists at ${absTarget}, running git pull...`);
905
- const { stdout } = await execAsync('git pull', { cwd: absTarget, timeout: 120000 });
906
- console.log(` git pull: ${stdout.trim()}`);
928
+ const targetBranch = branch || 'develop';
929
+ console.log(`Repo already exists at ${absTarget}, updating branch: ${targetBranch}...`);
930
+ await execAsync('git fetch --all', { cwd: absTarget, timeout: 60000 });
931
+ try {
932
+ await execAsync(`git checkout ${targetBranch}`, { cwd: absTarget, timeout: 30000 });
933
+ const { stdout } = await execAsync(`git pull origin ${targetBranch}`, { cwd: absTarget, timeout: 120000 });
934
+ console.log(`git pull: ${stdout.trim()}`);
935
+ } catch (checkoutErr) {
936
+ console.warn(`Checkout ${targetBranch} failed, staying on current branch: ${checkoutErr.message}`);
937
+ }
907
938
  } else {
908
939
  const safeLog = authenticatedUrl.replace(/x-token-auth:[^@]+@/g, 'x-token-auth:***@').replace(/oauth2:[^@]+@/g, 'oauth2:***@').replace(/x-access-token:[^@]+@/g, 'x-access-token:***@');
909
- console.log(` Running: git clone "${safeLog}" "${absTarget}"`);
910
- await execAsync(`git clone "${authenticatedUrl}" "${absTarget}"`, { timeout: 300000 });
911
- console.log(` Clone complete: ${absTarget}`);
940
+ const cloneCmd = branch ? `git clone -b ${branch} "${authenticatedUrl}" "${absTarget}"` : `git clone "${authenticatedUrl}" "${absTarget}"`;
941
+ console.log(`Running: git clone${branch ? ' -b ' + branch : ''} "${safeLog}" "${absTarget}"`);
942
+ await execAsync(cloneCmd, { timeout: 300000 });
943
+ console.log(`Clone complete: ${absTarget}`);
912
944
  }
913
945
 
914
946
  // Open the cloned workspace
@@ -917,7 +949,7 @@ app.post("/workspace/clone", async (req, res) => {
917
949
  try {
918
950
  await wsManager.open(wsId, absTarget);
919
951
  } catch (err) {
920
- console.warn(` WorkspaceManager.open failed (non-fatal): ${err.message}`);
952
+ console.warn(`WorkspaceManager.open failed (non-fatal): ${err.message}`);
921
953
  }
922
954
 
923
955
  const meta = await detectProject(absTarget);
@@ -933,7 +965,7 @@ app.post("/workspace/clone", async (req, res) => {
933
965
  });
934
966
 
935
967
  } catch (err) {
936
- console.error(` Clone failed: ${err.message}`);
968
+ console.error(`Clone failed: ${err.message}`);
937
969
  const hint = err.message.includes('Authentication') || err.message.includes('could not read')
938
970
  ? "Authentication failed. Ensure the repo is public or GitHub integration is configured."
939
971
  : err.message.includes('not found') || err.message.includes('does not exist')
@@ -1015,6 +1047,35 @@ app.get("/workspace/file-content", async (req, res) => {
1015
1047
  }
1016
1048
  });
1017
1049
 
1050
+ /** Escreve/salva conteudo de arquivo no workspace */
1051
+ app.post("/workspace/write-file", async (req, res) => {
1052
+ const workspaceRoot = getEffectiveRoot(req);
1053
+ if (!workspaceRoot) return res.status(400).json({ error: "workspace not set" });
1054
+
1055
+ const { path: relativePath, content: fileContent } = req.body || {};
1056
+ if (!relativePath) return res.status(400).json({ error: "path is required" });
1057
+ if (fileContent === undefined || fileContent === null) return res.status(400).json({ error: "content is required" });
1058
+
1059
+ const pathMod = await import('path');
1060
+ const fullPath = pathMod.default.resolve(workspaceRoot, relativePath);
1061
+
1062
+ // Security: prevent path traversal outside workspace root
1063
+ if (!fullPath.startsWith(workspaceRoot)) {
1064
+ return res.status(403).json({ error: "Path traversal not allowed" });
1065
+ }
1066
+
1067
+ try {
1068
+ const { mkdir } = await import('fs/promises');
1069
+ await mkdir(pathMod.default.dirname(fullPath), { recursive: true });
1070
+ await fsPromises.writeFile(fullPath, fileContent, 'utf8');
1071
+ res.json({ ok: true, path: relativePath, size: fileContent.length });
1072
+ } catch (err) {
1073
+ res.status(500).json({ error: "Could not write file", details: err.message });
1074
+ }
1075
+ });
1076
+
1077
+
1078
+
1018
1079
  /** L mltiplos arquivos */
1019
1080
  app.post("/workspace/batch-read", async (req, res) => {
1020
1081
  const wsRoot = resolveWorkspaceRoot(req);
@@ -1057,7 +1118,7 @@ app.get("/workspace/file-exists", async (req, res) => {
1057
1118
  const fullPath = path.join(wsRoot, relativePath);
1058
1119
  const fileExists = await exists(fullPath);
1059
1120
 
1060
- console.log(` [file-exists] ${relativePath} -> ${fileExists ? 'EXISTS' : 'NOT FOUND'}`);
1121
+ console.log(`[file-exists] ${relativePath} -> ${fileExists ? 'EXISTS' : 'NOT FOUND'}`);
1061
1122
 
1062
1123
  res.json({
1063
1124
  ok: true,
@@ -1066,7 +1127,7 @@ app.get("/workspace/file-exists", async (req, res) => {
1066
1127
  fullPath: fullPath
1067
1128
  });
1068
1129
  } catch (err) {
1069
- console.error(` [file-exists] Error:`, err.message);
1130
+ console.error(`[file-exists] Error:`, err.message);
1070
1131
  res.status(500).json({ ok: false, error: err.message });
1071
1132
  }
1072
1133
  });
@@ -1098,7 +1159,7 @@ app.post("/workspace/validate-paths", async (req, res) => {
1098
1159
  const allExist = results.every(r => r.exists);
1099
1160
  const missingPaths = results.filter(r => !r.exists).map(r => r.path);
1100
1161
 
1101
- console.log(` [validate-paths] Checked ${pathList.length} paths, ${missingPaths.length} missing`);
1162
+ console.log(`[validate-paths] Checked ${pathList.length} paths, ${missingPaths.length} missing`);
1102
1163
 
1103
1164
  res.json({
1104
1165
  ok: true,
@@ -1108,7 +1169,7 @@ app.post("/workspace/validate-paths", async (req, res) => {
1108
1169
  totalChecked: pathList.length
1109
1170
  });
1110
1171
  } catch (err) {
1111
- console.error(` [validate-paths] Error:`, err.message);
1172
+ console.error(`[validate-paths] Error:`, err.message);
1112
1173
  res.status(500).json({ ok: false, error: err.message });
1113
1174
  }
1114
1175
  });
@@ -1131,7 +1192,7 @@ app.post("/workspace/search-file", async (req, res) => {
1131
1192
  }
1132
1193
 
1133
1194
  try {
1134
- console.log(` [search-file] Searching for: ${fileName}`);
1195
+ console.log(`[search-file] Searching for: ${fileName}`);
1135
1196
 
1136
1197
  const rawFiles = await listRecursive(wsRoot, {
1137
1198
  maxDepth: 15,
@@ -1148,7 +1209,7 @@ app.post("/workspace/search-file", async (req, res) => {
1148
1209
  return String(f);
1149
1210
  }).filter(f => f && typeof f === 'string');
1150
1211
 
1151
- console.log(` [search-file] Scanning ${allFiles.length} files`);
1212
+ console.log(`[search-file] Scanning ${allFiles.length} files`);
1152
1213
 
1153
1214
  // Strategy 1: Exact path match
1154
1215
  let foundPath = allFiles.find(f => f.endsWith('/' + fileName) || f === fileName);
@@ -1178,14 +1239,14 @@ app.post("/workspace/search-file", async (req, res) => {
1178
1239
  }
1179
1240
 
1180
1241
  if (foundPath) {
1181
- console.log(` [search-file] Found: ${foundPath}`);
1242
+ console.log(`[search-file] Found: ${foundPath}`);
1182
1243
  res.json({ ok: true, found: true, path: foundPath, fileName });
1183
1244
  } else {
1184
- console.log(` [search-file] Not found: ${fileName}`);
1245
+ console.log(`[search-file] Not found: ${fileName}`);
1185
1246
  res.json({ ok: true, found: false, fileName, searchedFiles: allFiles.length });
1186
1247
  }
1187
1248
  } catch (err) {
1188
- console.error(` [search-file] Error:`, err.message);
1249
+ console.error(`[search-file] Error:`, err.message);
1189
1250
  res.status(500).json({ ok: false, error: err.message });
1190
1251
  }
1191
1252
  });
@@ -1209,7 +1270,7 @@ app.post("/workspace/search-by-content", async (req, res) => {
1209
1270
  }
1210
1271
 
1211
1272
  try {
1212
- console.log(` [search-by-content] Searching for terms: ${terms.join(', ')}`);
1273
+ console.log(`[search-by-content] Searching for terms: ${terms.join(', ')}`);
1213
1274
 
1214
1275
  const rawFiles = await listRecursive(wsRoot, {
1215
1276
  maxDepth: 15,
@@ -1229,7 +1290,7 @@ app.post("/workspace/search-by-content", async (req, res) => {
1229
1290
  return extensions.some(ext => filePath.endsWith(ext));
1230
1291
  });
1231
1292
 
1232
- console.log(` [search-by-content] Scanning ${filteredFiles.length} files`);
1293
+ console.log(`[search-by-content] Scanning ${filteredFiles.length} files`);
1233
1294
 
1234
1295
  const results = [];
1235
1296
 
@@ -1274,7 +1335,7 @@ app.post("/workspace/search-by-content", async (req, res) => {
1274
1335
  return true;
1275
1336
  }).slice(0, maxResults);
1276
1337
 
1277
- console.log(` [search-by-content] Found ${dedupedResults.length} matching files`);
1338
+ console.log(`[search-by-content] Found ${dedupedResults.length} matching files`);
1278
1339
 
1279
1340
  res.json({
1280
1341
  ok: true,
@@ -1283,7 +1344,7 @@ app.post("/workspace/search-by-content", async (req, res) => {
1283
1344
  termsSearched: terms
1284
1345
  });
1285
1346
  } catch (err) {
1286
- console.error(` [search-by-content] Error:`, err.message);
1347
+ console.error(`[search-by-content] Error:`, err.message);
1287
1348
  res.status(500).json({ ok: false, error: err.message });
1288
1349
  }
1289
1350
  });
@@ -1307,7 +1368,7 @@ app.post("/workspace/find-field-definition", async (req, res) => {
1307
1368
  }
1308
1369
 
1309
1370
  try {
1310
- console.log(` [find-field] Searching for field: ${fieldName}`);
1371
+ console.log(`[find-field] Searching for field: ${fieldName}`);
1311
1372
 
1312
1373
  const rawFiles = await listRecursive(wsRoot, {
1313
1374
  maxDepth: 15,
@@ -1386,7 +1447,7 @@ app.post("/workspace/find-field-definition", async (req, res) => {
1386
1447
  return 0;
1387
1448
  });
1388
1449
 
1389
- console.log(` [find-field] Found ${definitions.length} definitions for '${fieldName}'`);
1450
+ console.log(`[find-field] Found ${definitions.length} definitions for '${fieldName}'`);
1390
1451
 
1391
1452
  res.json({
1392
1453
  ok: true,
@@ -1395,7 +1456,7 @@ app.post("/workspace/find-field-definition", async (req, res) => {
1395
1456
  totalSearched: targetFiles.length
1396
1457
  });
1397
1458
  } catch (err) {
1398
- console.error(` [find-field] Error:`, err.message);
1459
+ console.error(`[find-field] Error:`, err.message);
1399
1460
  res.status(500).json({ ok: false, error: err.message });
1400
1461
  }
1401
1462
  });
@@ -1609,7 +1670,7 @@ app.post("/workspace/patch", async (req, res) => {
1609
1670
  if (!diff) return res.status(400).json({ error: "diff is required" });
1610
1671
 
1611
1672
  try {
1612
- console.log(` Applying patch for incident: ${incidentId || 'unknown'}`);
1673
+ console.log(`Applying patch for incident: ${incidentId || 'unknown'}`);
1613
1674
  const out = await applyUnifiedDiff(wsRoot, diff);
1614
1675
 
1615
1676
  // CRITICAL FIX: Format response as expected by Gateway
@@ -1624,7 +1685,7 @@ app.post("/workspace/patch", async (req, res) => {
1624
1685
  incidentId: incidentId
1625
1686
  };
1626
1687
 
1627
- console.log(` Patch applied successfully:`, {
1688
+ console.log(`Patch applied successfully:`, {
1628
1689
  target: out.target,
1629
1690
  bytes: out.bytes,
1630
1691
  incident: incidentId
@@ -1632,7 +1693,7 @@ app.post("/workspace/patch", async (req, res) => {
1632
1693
 
1633
1694
  res.json(response);
1634
1695
  } catch (e) {
1635
- console.error(` Patch failed:`, e.message);
1696
+ console.error(`Patch failed:`, e.message);
1636
1697
  res.status(400).json({
1637
1698
  ok: false,
1638
1699
  error: "patch failed",
@@ -1684,7 +1745,7 @@ let TEST_LOCAL_STATE = {
1684
1745
  * Returns current test local state with auto-detected port
1685
1746
  */
1686
1747
  app.get("/workspace/test-local/state", async (req, res) => {
1687
- console.log(" [TEST-LOCAL] Getting state:", TEST_LOCAL_STATE.status);
1748
+ console.log("[TEST-LOCAL] Getting state:", TEST_LOCAL_STATE.status);
1688
1749
 
1689
1750
  // Auto-detect port if not set in config
1690
1751
  let port = TEST_LOCAL_STATE.config?.server?.port;
@@ -1723,7 +1784,7 @@ app.post("/workspace/test-local/compile", async (req, res) => {
1723
1784
  if (!wsRoot) return res.status(400).json({ error: "workspace not set" });
1724
1785
 
1725
1786
  try {
1726
- console.log(" [TEST-LOCAL] Starting compilation...");
1787
+ console.log("[TEST-LOCAL] Starting compilation...");
1727
1788
  TEST_LOCAL_STATE.status = "compiling";
1728
1789
 
1729
1790
  const meta = await detectProject(wsRoot);
@@ -1758,7 +1819,7 @@ app.post("/workspace/test-local/compile", async (req, res) => {
1758
1819
  duration: compileResult.duration
1759
1820
  };
1760
1821
 
1761
- console.log(" [TEST-LOCAL] Compilation successful");
1822
+ console.log("[TEST-LOCAL] Compilation successful");
1762
1823
 
1763
1824
  res.json({
1764
1825
  ok: true,
@@ -1768,7 +1829,7 @@ app.post("/workspace/test-local/compile", async (req, res) => {
1768
1829
  stdout: compileResult.stdout
1769
1830
  });
1770
1831
  } catch (err) {
1771
- console.error(" [TEST-LOCAL] Compilation failed:", err.message);
1832
+ console.error("[TEST-LOCAL] Compilation failed:", err.message);
1772
1833
  TEST_LOCAL_STATE.status = "error";
1773
1834
  res.status(500).json({ ok: false, error: err.message });
1774
1835
  }
@@ -1821,7 +1882,7 @@ app.post("/workspace/test-local/start", async (req, res) => {
1821
1882
  const command = 'java';
1822
1883
  const args = ['-jar', jarPath, `--server.port=${serverPort}`];
1823
1884
 
1824
- console.log(` Command: ${command} ${args.join(' ')}`);
1885
+ console.log(`Command: ${command} ${args.join(' ')}`);
1825
1886
 
1826
1887
  // Env LIMPO - remover TODAS as variveis Spring que podem interferir
1827
1888
  const cleanEnv = { ...process.env };
@@ -1851,7 +1912,7 @@ app.post("/workspace/test-local/start", async (req, res) => {
1851
1912
  TEST_LOCAL_STATE.status = "running";
1852
1913
  TEST_LOCAL_STATE.config = { port: serverPort };
1853
1914
 
1854
- console.log(` [TEST-LOCAL] Server started on port ${serverPort}`);
1915
+ console.log(`[TEST-LOCAL] Server started on port ${serverPort}`);
1855
1916
 
1856
1917
  res.json({
1857
1918
  ok: true,
@@ -1901,7 +1962,7 @@ app.post("/workspace/test-local/start", async (req, res) => {
1901
1962
  });
1902
1963
  }
1903
1964
  } catch (err) {
1904
- console.error(" [TEST-LOCAL] Server start failed:", err.message);
1965
+ console.error("[TEST-LOCAL] Server start failed:", err.message);
1905
1966
  TEST_LOCAL_STATE.status = "error";
1906
1967
  res.status(500).json({ ok: false, error: err.message });
1907
1968
  }
@@ -1913,19 +1974,19 @@ app.post("/workspace/test-local/start", async (req, res) => {
1913
1974
  */
1914
1975
  app.post("/workspace/test-local/stop", async (req, res) => {
1915
1976
  try {
1916
- console.log(" [TEST-LOCAL] Stopping server...");
1977
+ console.log("[TEST-LOCAL] Stopping server...");
1917
1978
 
1918
1979
  await processManager.stop('test-local');
1919
1980
  TEST_LOCAL_STATE.status = "stopped";
1920
1981
 
1921
- console.log(" [TEST-LOCAL] Server stopped");
1982
+ console.log("[TEST-LOCAL] Server stopped");
1922
1983
 
1923
1984
  res.json({
1924
1985
  ok: true,
1925
1986
  status: "stopped"
1926
1987
  });
1927
1988
  } catch (err) {
1928
- console.error(" [TEST-LOCAL] Server stop failed:", err.message);
1989
+ console.error("[TEST-LOCAL] Server stop failed:", err.message);
1929
1990
  res.status(500).json({ ok: false, error: err.message });
1930
1991
  }
1931
1992
  });
@@ -1939,7 +2000,7 @@ app.get("/workspace/test-local/endpoints", async (req, res) => {
1939
2000
  if (!wsRoot) return res.status(400).json({ error: "workspace not set" });
1940
2001
 
1941
2002
  try {
1942
- console.log(" [TEST-LOCAL] Getting endpoints...");
2003
+ console.log("[TEST-LOCAL] Getting endpoints...");
1943
2004
 
1944
2005
  // If endpoints are cached, return them
1945
2006
  if (TEST_LOCAL_STATE.endpoints && TEST_LOCAL_STATE.endpoints.length > 0) {
@@ -1962,7 +2023,7 @@ app.get("/workspace/test-local/endpoints", async (req, res) => {
1962
2023
 
1963
2024
  TEST_LOCAL_STATE.endpoints = payloadDocs.endpoints;
1964
2025
 
1965
- console.log(` [TEST-LOCAL] Discovered ${payloadDocs.endpoints.length} endpoints`);
2026
+ console.log(`[TEST-LOCAL] Discovered ${payloadDocs.endpoints.length} endpoints`);
1966
2027
 
1967
2028
  res.json({
1968
2029
  ok: true,
@@ -1970,7 +2031,7 @@ app.get("/workspace/test-local/endpoints", async (req, res) => {
1970
2031
  cached: false
1971
2032
  });
1972
2033
  } catch (err) {
1973
- console.error(" [TEST-LOCAL] Failed to get endpoints:", err.message);
2034
+ console.error("[TEST-LOCAL] Failed to get endpoints:", err.message);
1974
2035
  res.status(500).json({ ok: false, error: err.message });
1975
2036
  }
1976
2037
  });
@@ -1990,7 +2051,7 @@ app.post("/workspace/test-local/execute", async (req, res) => {
1990
2051
  const serverPort = port || TEST_LOCAL_STATE.config?.server?.port || 8080;
1991
2052
  const url = `http://localhost:${serverPort}${reqPath}`;
1992
2053
 
1993
- console.log(` [TEST-LOCAL] Executing: ${method} ${url}`);
2054
+ console.log(`[TEST-LOCAL] Executing: ${method} ${url}`);
1994
2055
 
1995
2056
  const startTime = Date.now();
1996
2057
 
@@ -2039,14 +2100,14 @@ app.post("/workspace/test-local/execute", async (req, res) => {
2039
2100
  TEST_LOCAL_STATE.testResults.shift();
2040
2101
  }
2041
2102
 
2042
- console.log(` [TEST-LOCAL] Test result: ${response.status} (${duration}ms)`);
2103
+ console.log(`[TEST-LOCAL] Test result: ${response.status} (${duration}ms)`);
2043
2104
 
2044
2105
  res.json({
2045
2106
  ok: true,
2046
2107
  result
2047
2108
  });
2048
2109
  } catch (err) {
2049
- console.error(" [TEST-LOCAL] Test execution failed:", err.message);
2110
+ console.error("[TEST-LOCAL] Test execution failed:", err.message);
2050
2111
  res.json({
2051
2112
  ok: false,
2052
2113
  error: err.message,
@@ -2065,7 +2126,7 @@ app.post("/workspace/test-local/execute", async (req, res) => {
2065
2126
  * Returns stored test results
2066
2127
  */
2067
2128
  app.get("/workspace/test-local/results", (req, res) => {
2068
- console.log(" [TEST-LOCAL] Getting test results...");
2129
+ console.log("[TEST-LOCAL] Getting test results...");
2069
2130
 
2070
2131
  res.json({
2071
2132
  ok: true,
@@ -2079,7 +2140,7 @@ app.get("/workspace/test-local/results", (req, res) => {
2079
2140
  * Clears stored test results
2080
2141
  */
2081
2142
  app.post("/workspace/test-local/clear-results", (req, res) => {
2082
- console.log(" [TEST-LOCAL] Clearing test results...");
2143
+ console.log("[TEST-LOCAL] Clearing test results...");
2083
2144
 
2084
2145
  TEST_LOCAL_STATE.testResults = [];
2085
2146
 
@@ -2096,7 +2157,7 @@ app.post("/workspace/test-local/clear-results", (req, res) => {
2096
2157
  app.get("/workspace/test-local/logs", (req, res) => {
2097
2158
  const limit = parseInt(req.query.limit) || 500;
2098
2159
 
2099
- console.log(` [TEST-LOCAL] Getting logs (limit: ${limit})`);
2160
+ console.log(`[TEST-LOCAL] Getting logs (limit: ${limit})`);
2100
2161
 
2101
2162
  const logs = TEST_LOCAL_STATE.serverLogs.slice(-limit);
2102
2163
 
@@ -2115,7 +2176,7 @@ app.get("/workspace/controllers", async (req, res) => {
2115
2176
  if (!wsRoot) return res.status(400).json({ error: "workspace not set" });
2116
2177
 
2117
2178
  try {
2118
- console.log(" [CONTROLLERS] Discovering controllers...");
2179
+ console.log("[CONTROLLERS] Discovering controllers...");
2119
2180
 
2120
2181
  const scanner = new WorkspaceScanner(wsRoot);
2121
2182
  const structure = await scanner.scan();
@@ -2123,14 +2184,14 @@ app.get("/workspace/controllers", async (req, res) => {
2123
2184
  const controllerAnalyzer = new ControllerAnalyzer(wsRoot);
2124
2185
  const apiDocs = await controllerAnalyzer.generateApiDocs(structure.files);
2125
2186
 
2126
- console.log(` [CONTROLLERS] Found ${apiDocs.totalEndpoints} endpoints in ${apiDocs.totalControllers} controllers`);
2187
+ console.log(`[CONTROLLERS] Found ${apiDocs.totalEndpoints} endpoints in ${apiDocs.totalControllers} controllers`);
2127
2188
 
2128
2189
  res.json({
2129
2190
  ok: true,
2130
2191
  ...apiDocs
2131
2192
  });
2132
2193
  } catch (err) {
2133
- console.error(" [CONTROLLERS] Failed:", err.message);
2194
+ console.error("[CONTROLLERS] Failed:", err.message);
2134
2195
  res.status(500).json({ ok: false, error: err.message });
2135
2196
  }
2136
2197
  });
@@ -2141,7 +2202,7 @@ app.get("/workspace/dtos", async (req, res) => {
2141
2202
  if (!wsRoot) return res.status(400).json({ error: "workspace not set" });
2142
2203
 
2143
2204
  try {
2144
- console.log(" [DTOS] Analyzing DTOs...");
2205
+ console.log("[DTOS] Analyzing DTOs...");
2145
2206
 
2146
2207
  const scanner = new WorkspaceScanner(wsRoot);
2147
2208
  const structure = await scanner.scan();
@@ -2152,14 +2213,14 @@ app.get("/workspace/dtos", async (req, res) => {
2152
2213
  const dtoAnalyzer = new DTOAnalyzer(wsRoot);
2153
2214
  const payloadDocs = await dtoAnalyzer.generatePayloadDocs(structure.files, apiDocs.endpoints);
2154
2215
 
2155
- console.log(` [DTOS] Found ${payloadDocs.totalDtos} DTOs`);
2216
+ console.log(`[DTOS] Found ${payloadDocs.totalDtos} DTOs`);
2156
2217
 
2157
2218
  res.json({
2158
2219
  ok: true,
2159
2220
  ...payloadDocs
2160
2221
  });
2161
2222
  } catch (err) {
2162
- console.error(" [DTOS] Failed:", err.message);
2223
+ console.error("[DTOS] Failed:", err.message);
2163
2224
  res.status(500).json({ ok: false, error: err.message });
2164
2225
  }
2165
2226
  });
@@ -2170,19 +2231,19 @@ app.get("/workspace/config", async (req, res) => {
2170
2231
  if (!wsRoot) return res.status(400).json({ error: "workspace not set" });
2171
2232
 
2172
2233
  try {
2173
- console.log(" [CONFIG] Analyzing configuration...");
2234
+ console.log("[CONFIG] Analyzing configuration...");
2174
2235
 
2175
2236
  const configAnalyzer = new ConfigAnalyzer(wsRoot);
2176
2237
  const config = await configAnalyzer.analyze();
2177
2238
 
2178
- console.log(` [CONFIG] Server port: ${config.server.port}`);
2239
+ console.log(`[CONFIG] Server port: ${config.server.port}`);
2179
2240
 
2180
2241
  res.json({
2181
2242
  ok: true,
2182
2243
  ...config
2183
2244
  });
2184
2245
  } catch (err) {
2185
- console.error(" [CONFIG] Failed:", err.message);
2246
+ console.error("[CONFIG] Failed:", err.message);
2186
2247
  res.status(500).json({ ok: false, error: err.message });
2187
2248
  }
2188
2249
  });
@@ -2251,7 +2312,7 @@ app.post("/workspace/safe-patch", async (req, res) => {
2251
2312
  const { diff, incidentId } = req.body || {};
2252
2313
  if (!diff) return res.status(400).json({ error: "diff is required" });
2253
2314
 
2254
- console.log(` Safe patch requested for incident: ${incidentId || 'unknown'}`);
2315
+ console.log(`Safe patch requested for incident: ${incidentId || 'unknown'}`);
2255
2316
 
2256
2317
  try {
2257
2318
  // 1. Validate diff
@@ -2266,7 +2327,7 @@ app.post("/workspace/safe-patch", async (req, res) => {
2266
2327
 
2267
2328
  // 2. Extract target files
2268
2329
  const targetFiles = extractTargetFiles(diff);
2269
- console.log(` Target files: ${targetFiles.join(', ')}`);
2330
+ console.log(`Target files: ${targetFiles.join(', ')}`);
2270
2331
 
2271
2332
  // 3. Create backup
2272
2333
  const backupId = `backup-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
@@ -2297,23 +2358,23 @@ app.post("/workspace/safe-patch", async (req, res) => {
2297
2358
  }
2298
2359
  saveBackupIndex();
2299
2360
  } catch (e) {
2300
- console.warn(` Could not persist backup to disk: ${e.message}`);
2361
+ console.warn(`Could not persist backup to disk: ${e.message}`);
2301
2362
  }
2302
2363
 
2303
2364
  // Cleanup old backups if exceeded max
2304
2365
  if (BACKUPS.size > MAX_BACKUPS) {
2305
2366
  const oldest = Array.from(BACKUPS.keys())[0];
2306
2367
  BACKUPS.delete(oldest);
2307
- console.log(` Removed old backup: ${oldest}`);
2368
+ console.log(`Removed old backup: ${oldest}`);
2308
2369
  saveBackupIndex();
2309
2370
  }
2310
2371
 
2311
- console.log(` Backup created: ${backupId} (${backupFiles.length} files)`);
2372
+ console.log(`Backup created: ${backupId} (${backupFiles.length} files)`);
2312
2373
 
2313
2374
  // 4. Apply patch
2314
2375
  try {
2315
2376
  const result = await applyUnifiedDiff(wsRoot, diff);
2316
- console.log(` Patch applied successfully: ${result.target}`);
2377
+ console.log(`Patch applied successfully: ${result.target}`);
2317
2378
 
2318
2379
  res.json({
2319
2380
  ok: true,
@@ -2324,7 +2385,7 @@ app.post("/workspace/safe-patch", async (req, res) => {
2324
2385
  });
2325
2386
  } catch (patchError) {
2326
2387
  // 5. Rollback on failure
2327
- console.error(` Patch failed, rolling back: ${patchError.message}`);
2388
+ console.error(`Patch failed, rolling back: ${patchError.message}`);
2328
2389
 
2329
2390
  for (const file of backupFiles) {
2330
2391
  const fullPath = path.join(wsRoot, file.path);
@@ -2341,7 +2402,7 @@ app.post("/workspace/safe-patch", async (req, res) => {
2341
2402
  });
2342
2403
  }
2343
2404
  } catch (err) {
2344
- console.error(` Safe patch error: ${err.message}`);
2405
+ console.error(`Safe patch error: ${err.message}`);
2345
2406
  res.status(500).json({ ok: false, error: err.message });
2346
2407
  }
2347
2408
  });
@@ -2362,7 +2423,7 @@ app.post("/workspace/patch/dry-run", async (req, res) => {
2362
2423
  const { diff } = req.body || {};
2363
2424
  if (!diff) return res.status(400).json({ error: "diff is required" });
2364
2425
 
2365
- console.log(` Dry-run patch validation requested`);
2426
+ console.log(`Dry-run patch validation requested`);
2366
2427
 
2367
2428
  try {
2368
2429
  // 1. Validate diff format
@@ -2413,7 +2474,7 @@ app.post("/workspace/patch/dry-run", async (req, res) => {
2413
2474
  const allFilesExist = fileChecks.every(f => f.exists || diff.includes('--- /dev/null'));
2414
2475
  const missingFiles = fileChecks.filter(f => !f.exists && !diff.includes('--- /dev/null'));
2415
2476
 
2416
- console.log(` Dry-run complete: ${targetFiles.length} files, ${hunkCount} hunks`);
2477
+ console.log(`Dry-run complete: ${targetFiles.length} files, ${hunkCount} hunks`);
2417
2478
 
2418
2479
  res.json({
2419
2480
  ok: true,
@@ -2426,7 +2487,7 @@ app.post("/workspace/patch/dry-run", async (req, res) => {
2426
2487
  warnings: missingFiles.length > 0 ? [`${missingFiles.length} file(s) not found`] : []
2427
2488
  });
2428
2489
  } catch (err) {
2429
- console.error(` Dry-run error: ${err.message}`);
2490
+ console.error(`Dry-run error: ${err.message}`);
2430
2491
  res.status(500).json({ ok: false, error: err.message });
2431
2492
  }
2432
2493
  });
@@ -2494,7 +2555,7 @@ app.post("/workspace/backup", async (req, res) => {
2494
2555
  incidentId: incidentId || null
2495
2556
  });
2496
2557
 
2497
- console.log(` Manual backup created: ${backupId}`);
2558
+ console.log(`Manual backup created: ${backupId}`);
2498
2559
 
2499
2560
  res.json({
2500
2561
  ok: true,
@@ -2503,7 +2564,7 @@ app.post("/workspace/backup", async (req, res) => {
2503
2564
  timestamp: new Date().toISOString()
2504
2565
  });
2505
2566
  } catch (err) {
2506
- console.error(` Backup error: ${err.message}`);
2567
+ console.error(`Backup error: ${err.message}`);
2507
2568
  res.status(500).json({ ok: false, error: err.message });
2508
2569
  }
2509
2570
  });
@@ -2535,14 +2596,14 @@ app.post("/workspace/rollback", async (req, res) => {
2535
2596
  }
2536
2597
 
2537
2598
  try {
2538
- console.log(` Rolling back to backup: ${backupId}`);
2599
+ console.log(`Rolling back to backup: ${backupId}`);
2539
2600
 
2540
2601
  for (const file of backup.files) {
2541
2602
  const fullPath = path.join(wsRoot, file.path);
2542
2603
  await writeFile(fullPath, file.content, 'utf8');
2543
2604
  }
2544
2605
 
2545
- console.log(` Rollback completed: ${backup.files.length} files restored`);
2606
+ console.log(`Rollback completed: ${backup.files.length} files restored`);
2546
2607
 
2547
2608
  res.json({
2548
2609
  ok: true,
@@ -2551,7 +2612,7 @@ app.post("/workspace/rollback", async (req, res) => {
2551
2612
  timestamp: backup.timestamp
2552
2613
  });
2553
2614
  } catch (err) {
2554
- console.error(` Rollback error: ${err.message}`);
2615
+ console.error(`Rollback error: ${err.message}`);
2555
2616
  res.status(500).json({ ok: false, error: err.message });
2556
2617
  }
2557
2618
  });
@@ -2591,7 +2652,7 @@ app.delete("/workspace/backups/:backupId", (req, res) => {
2591
2652
  }
2592
2653
 
2593
2654
  BACKUPS.delete(backupId);
2594
- console.log(` Backup deleted: ${backupId}`);
2655
+ console.log(`Backup deleted: ${backupId}`);
2595
2656
 
2596
2657
  res.json({
2597
2658
  ok: true,
@@ -2650,7 +2711,7 @@ app.get("/workspace/diff/by-incident/:incidentId", async (req, res) => {
2650
2711
  }
2651
2712
 
2652
2713
  if (!matchedBackup) {
2653
- console.log(` No backup found for incident ${incidentId}. Available backups:`, Array.from(BACKUPS.keys()));
2714
+ console.log(`No backup found for incident ${incidentId}. Available backups:`, Array.from(BACKUPS.keys()));
2654
2715
  return res.status(404).json({
2655
2716
  ok: false,
2656
2717
  error: "No backup found for this incident",
@@ -2659,7 +2720,7 @@ app.get("/workspace/diff/by-incident/:incidentId", async (req, res) => {
2659
2720
  });
2660
2721
  }
2661
2722
 
2662
- console.log(` Found backup ${matchedBackupId} for incident ${incidentId}`);
2723
+ console.log(`Found backup ${matchedBackupId} for incident ${incidentId}`);
2663
2724
 
2664
2725
  // Reuse the diff logic
2665
2726
  try {
@@ -2696,7 +2757,7 @@ app.get("/workspace/diff/by-incident/:incidentId", async (req, res) => {
2696
2757
  files: diffs
2697
2758
  });
2698
2759
  } catch (err) {
2699
- console.error(` Diff error: ${err.message}`);
2760
+ console.error(`Diff error: ${err.message}`);
2700
2761
  res.status(500).json({ ok: false, error: err.message });
2701
2762
  }
2702
2763
  });
@@ -2768,7 +2829,7 @@ app.get("/workspace/diff/:backupId", async (req, res) => {
2768
2829
  }
2769
2830
  }
2770
2831
 
2771
- console.log(` Diff for ${backupId}: ${diffs.length} file(s) changed`);
2832
+ console.log(`Diff for ${backupId}: ${diffs.length} file(s) changed`);
2772
2833
 
2773
2834
  res.json({
2774
2835
  ok: true,
@@ -2780,7 +2841,7 @@ app.get("/workspace/diff/:backupId", async (req, res) => {
2780
2841
  files: diffs
2781
2842
  });
2782
2843
  } catch (err) {
2783
- console.error(` Diff error: ${err.message}`);
2844
+ console.error(`Diff error: ${err.message}`);
2784
2845
  res.status(500).json({ ok: false, error: err.message });
2785
2846
  }
2786
2847
  });
@@ -2813,7 +2874,7 @@ app.get("/workspace/detect-port", async (req, res) => {
2813
2874
 
2814
2875
  try {
2815
2876
  const fullPath = path.join(wsRoot, servicePath);
2816
- console.log(` Detecting port for service at: ${fullPath}`);
2877
+ console.log(`Detecting port for service at: ${fullPath}`);
2817
2878
 
2818
2879
  let port = null;
2819
2880
  let detectionMethod = null;
@@ -2848,7 +2909,7 @@ app.get("/workspace/detect-port", async (req, res) => {
2848
2909
  detectionMethod = 'global-detection';
2849
2910
  }
2850
2911
 
2851
- console.log(` Detected port: ${port || 'default'} via ${detectionMethod}`);
2912
+ console.log(`Detected port: ${port || 'default'} via ${detectionMethod}`);
2852
2913
 
2853
2914
  res.json({
2854
2915
  ok: true,
@@ -2859,7 +2920,7 @@ app.get("/workspace/detect-port", async (req, res) => {
2859
2920
  servicePath: servicePath || '/'
2860
2921
  });
2861
2922
  } catch (err) {
2862
- console.error(' Error detecting port:', err.message);
2923
+ console.error('Error detecting port:', err.message);
2863
2924
  res.status(500).json({ ok: false, error: err.message });
2864
2925
  }
2865
2926
  });
@@ -3070,7 +3131,7 @@ app.post("/workspace/test-local/prepare", async (req, res) => {
3070
3131
  if (!wsRoot) return res.status(400).json({ error: "workspace not set" });
3071
3132
 
3072
3133
  try {
3073
- console.log(" [TEST-LOCAL] Preparing test environment...");
3134
+ console.log("[TEST-LOCAL] Preparing test environment...");
3074
3135
  TEST_LOCAL_STATE.status = "compiling";
3075
3136
 
3076
3137
  // Step 1: Compile
@@ -3110,7 +3171,7 @@ app.post("/workspace/test-local/prepare", async (req, res) => {
3110
3171
  const config = await configAnalyzer.analyze();
3111
3172
  TEST_LOCAL_STATE.config = config;
3112
3173
 
3113
- console.log(` [TEST-LOCAL] Prepared: ${payloadDocs.endpoints.length} endpoints discovered`);
3174
+ console.log(`[TEST-LOCAL] Prepared: ${payloadDocs.endpoints.length} endpoints discovered`);
3114
3175
 
3115
3176
  res.json({
3116
3177
  ok: true,
@@ -3133,7 +3194,7 @@ app.post("/workspace/test-local/prepare", async (req, res) => {
3133
3194
  endpoints: payloadDocs.endpoints
3134
3195
  });
3135
3196
  } catch (err) {
3136
- console.error(" [TEST-LOCAL] Prepare failed:", err.message);
3197
+ console.error("[TEST-LOCAL] Prepare failed:", err.message);
3137
3198
  TEST_LOCAL_STATE.status = "error";
3138
3199
  res.status(500).json({ ok: false, error: err.message });
3139
3200
  }
@@ -3335,9 +3396,9 @@ app.post("/workspace/scan-files", async (req, res) => {
3335
3396
  });
3336
3397
  }
3337
3398
 
3338
- console.log(` [SCAN-FILES] Scanning: ${workspaceRoot}`);
3339
- console.log(` Extensions: ${includeExtensions.join(", ")}`);
3340
- console.log(` Exclude: ${excludePatterns.join(", ")}`);
3399
+ console.log(`[SCAN-FILES] Scanning: ${workspaceRoot}`);
3400
+ console.log(`Extensions: ${includeExtensions.join(", ")}`);
3401
+ console.log(`Exclude: ${excludePatterns.join(", ")}`);
3341
3402
 
3342
3403
  try {
3343
3404
  const files = [];
@@ -3387,13 +3448,13 @@ app.post("/workspace/scan-files", async (req, res) => {
3387
3448
  }
3388
3449
  }
3389
3450
  } catch (error) {
3390
- console.warn(` Cannot read directory ${dir}: ${error.message}`);
3451
+ console.warn(`Cannot read directory ${dir}: ${error.message}`);
3391
3452
  }
3392
3453
  }
3393
3454
 
3394
3455
  await scanDir(workspaceRoot);
3395
3456
 
3396
- console.log(` [SCAN-FILES] Found ${files.length} files`);
3457
+ console.log(`[SCAN-FILES] Found ${files.length} files`);
3397
3458
 
3398
3459
  res.json({
3399
3460
  success: true,
@@ -3403,7 +3464,7 @@ app.post("/workspace/scan-files", async (req, res) => {
3403
3464
  });
3404
3465
 
3405
3466
  } catch (error) {
3406
- console.error(` [SCAN-FILES] Error: ${error.message}`);
3467
+ console.error(`[SCAN-FILES] Error: ${error.message}`);
3407
3468
  res.status(500).json({
3408
3469
  success: false,
3409
3470
  error: error.message,
@@ -3432,7 +3493,7 @@ app.post("/workspace/read-file", async (req, res) => {
3432
3493
  });
3433
3494
  }
3434
3495
 
3435
- console.log(` [READ-FILE] Reading: ${filePath}`);
3496
+ console.log(`[READ-FILE] Reading: ${filePath}`);
3436
3497
 
3437
3498
  try {
3438
3499
  const fs = await import("fs/promises");
@@ -3463,7 +3524,7 @@ app.post("/workspace/read-file", async (req, res) => {
3463
3524
  });
3464
3525
 
3465
3526
  } catch (error) {
3466
- console.error(` [READ-FILE] Error: ${error.message}`);
3527
+ console.error(`[READ-FILE] Error: ${error.message}`);
3467
3528
  res.status(404).json({
3468
3529
  success: false,
3469
3530
  error: error.message,
@@ -3492,7 +3553,7 @@ app.post("/workspace/read-files", async (req, res) => {
3492
3553
  });
3493
3554
  }
3494
3555
 
3495
- console.log(` [READ-FILES] Reading ${filePaths.length} files`);
3556
+ console.log(`[READ-FILES] Reading ${filePaths.length} files`);
3496
3557
 
3497
3558
  try {
3498
3559
  const fs = await import("fs/promises");
@@ -3519,7 +3580,7 @@ app.post("/workspace/read-files", async (req, res) => {
3519
3580
  }
3520
3581
  }
3521
3582
 
3522
- console.log(` [READ-FILES] Read ${Object.keys(files).length} files, ${errors.length} errors`);
3583
+ console.log(`[READ-FILES] Read ${Object.keys(files).length} files, ${errors.length} errors`);
3523
3584
 
3524
3585
  res.json({
3525
3586
  success: true,
@@ -3529,7 +3590,7 @@ app.post("/workspace/read-files", async (req, res) => {
3529
3590
  });
3530
3591
 
3531
3592
  } catch (error) {
3532
- console.error(` [READ-FILES] Error: ${error.message}`);
3593
+ console.error(`[READ-FILES] Error: ${error.message}`);
3533
3594
  res.status(500).json({
3534
3595
  success: false,
3535
3596
  error: error.message
@@ -3547,7 +3608,7 @@ app.post("/workspace/read-files", async (req, res) => {
3547
3608
  * Abre o file picker nativo do sistema operacional
3548
3609
  */
3549
3610
  app.get("/system/folder-picker", async (req, res) => {
3550
- console.log(` [FOLDER-PICKER] Opening native folder picker...`);
3611
+ console.log(`[FOLDER-PICKER] Opening native folder picker...`);
3551
3612
 
3552
3613
  try {
3553
3614
  const platform = process.platform;
@@ -3630,7 +3691,7 @@ app.get("/system/folder-picker", async (req, res) => {
3630
3691
  selectedPath = selectedPath.slice(0, -1);
3631
3692
  }
3632
3693
 
3633
- console.log(` [FOLDER-PICKER] Selected: ${selectedPath}`);
3694
+ console.log(`[FOLDER-PICKER] Selected: ${selectedPath}`);
3634
3695
 
3635
3696
  res.json({
3636
3697
  success: true,
@@ -3639,7 +3700,7 @@ app.get("/system/folder-picker", async (req, res) => {
3639
3700
  });
3640
3701
 
3641
3702
  } catch (error) {
3642
- console.error(` [FOLDER-PICKER] Error:`, error.message);
3703
+ console.error(`[FOLDER-PICKER] Error:`, error.message);
3643
3704
  res.status(500).json({
3644
3705
  success: false,
3645
3706
  error: error.message,
@@ -3681,7 +3742,7 @@ app.get("/workspace/api-docs", async (req, res) => {
3681
3742
  });
3682
3743
  }
3683
3744
 
3684
- console.log(` [API-DOCS] Analyzing controllers in ${wsRoot}`);
3745
+ console.log(`[API-DOCS] Analyzing controllers in ${wsRoot}`);
3685
3746
 
3686
3747
  try {
3687
3748
  // Primeiro, escanear arquivos do workspace
@@ -3720,13 +3781,13 @@ app.get("/workspace/api-docs", async (req, res) => {
3720
3781
 
3721
3782
  await scanDir(wsRoot);
3722
3783
 
3723
- console.log(` [API-DOCS] Found ${files.length} Java files`);
3784
+ console.log(`[API-DOCS] Found ${files.length} Java files`);
3724
3785
 
3725
3786
  // Agora analisar os controllers
3726
3787
  const controllerAnalyzer = new ControllerAnalyzer(wsRoot);
3727
3788
  const apiDocs = await controllerAnalyzer.generateApiDocs(files);
3728
3789
 
3729
- console.log(` [API-DOCS] Found ${apiDocs.totalEndpoints} endpoints in ${apiDocs.totalControllers} controllers`);
3790
+ console.log(`[API-DOCS] Found ${apiDocs.totalEndpoints} endpoints in ${apiDocs.totalControllers} controllers`);
3730
3791
 
3731
3792
  res.json({
3732
3793
  success: true,
@@ -3738,7 +3799,7 @@ app.get("/workspace/api-docs", async (req, res) => {
3738
3799
  });
3739
3800
 
3740
3801
  } catch (error) {
3741
- console.error(` [API-DOCS] Error:`, error.message);
3802
+ console.error(`[API-DOCS] Error:`, error.message);
3742
3803
 
3743
3804
  res.json({
3744
3805
  success: false,
@@ -3765,7 +3826,7 @@ app.get("/workspace/api-docs/:controller", async (req, res) => {
3765
3826
  }
3766
3827
 
3767
3828
  const { controller } = req.params;
3768
- console.log(` [API-DOCS] Getting endpoints for controller: ${controller}`);
3829
+ console.log(`[API-DOCS] Getting endpoints for controller: ${controller}`);
3769
3830
 
3770
3831
  try {
3771
3832
  // Primeiro, escanear arquivos do workspace
@@ -3840,7 +3901,7 @@ app.get("/workspace/api-docs/:controller", async (req, res) => {
3840
3901
  });
3841
3902
 
3842
3903
  } catch (error) {
3843
- console.error(` [API-DOCS] Error:`, error.message);
3904
+ console.error(`[API-DOCS] Error:`, error.message);
3844
3905
  res.status(500).json({
3845
3906
  success: false,
3846
3907
  error: error.message
@@ -3930,7 +3991,7 @@ app.get("/workspace/smart-config", async (req, res) => {
3930
3991
  return res.status(400).json({ error: "workspace not set" });
3931
3992
  }
3932
3993
 
3933
- console.log(" [SMART-CONFIG] Collecting configuration files...");
3994
+ console.log("[SMART-CONFIG] Collecting configuration files...");
3934
3995
 
3935
3996
  try {
3936
3997
  const configPatterns = [
@@ -3964,9 +4025,9 @@ app.get("/workspace/smart-config", async (req, res) => {
3964
4025
  : content,
3965
4026
  size: content.length
3966
4027
  });
3967
- console.log(` Found: ${pattern}`);
4028
+ console.log(`Found: ${pattern}`);
3968
4029
  } catch (err) {
3969
- console.error(` Error reading ${pattern}: ${err.message}`);
4030
+ console.error(`Error reading ${pattern}: ${err.message}`);
3970
4031
  }
3971
4032
  }
3972
4033
  }
@@ -3982,7 +4043,7 @@ app.get("/workspace/smart-config", async (req, res) => {
3982
4043
  });
3983
4044
  }
3984
4045
 
3985
- console.log(` Collected ${collectedFiles.length} files, profiles: ${availableProfiles.join(', ')}`);
4046
+ console.log(`Collected ${collectedFiles.length} files, profiles: ${availableProfiles.join(', ')}`);
3986
4047
 
3987
4048
  res.json({
3988
4049
  ok: true,
@@ -3996,7 +4057,7 @@ app.get("/workspace/smart-config", async (req, res) => {
3996
4057
  });
3997
4058
 
3998
4059
  } catch (err) {
3999
- console.error(" [SMART-CONFIG] Error:", err.message);
4060
+ console.error("[SMART-CONFIG] Error:", err.message);
4000
4061
  res.status(500).json({ ok: false, error: err.message });
4001
4062
  }
4002
4063
  });
@@ -4007,7 +4068,7 @@ app.get("/workspace/smart-config", async (req, res) => {
4007
4068
  */
4008
4069
  app.post("/workspace/test-local/restart", async (req, res) => {
4009
4070
  try {
4010
- console.log(" [TEST-LOCAL] Restarting server...");
4071
+ console.log("[TEST-LOCAL] Restarting server...");
4011
4072
 
4012
4073
  // Stop
4013
4074
  await processManager.stop('test-local');
@@ -4052,7 +4113,7 @@ app.post("/workspace/test-local/restart", async (req, res) => {
4052
4113
  }
4053
4114
 
4054
4115
  } catch (err) {
4055
- console.error(" [TEST-LOCAL] Restart failed:", err.message);
4116
+ console.error("[TEST-LOCAL] Restart failed:", err.message);
4056
4117
  res.status(500).json({ ok: false, error: err.message });
4057
4118
  }
4058
4119
  });
@@ -4086,7 +4147,7 @@ app.post("/workspace/search", async (req, res) => {
4086
4147
  return res.status(400).json({ ok: false, error: "pattern is required" });
4087
4148
  }
4088
4149
 
4089
- console.log(` [workspace/search] pattern="${pattern}" filter="${fileFilter || '*'}"`);
4150
+ console.log(`[workspace/search] pattern="${pattern}" filter="${fileFilter || '*'}"`);
4090
4151
 
4091
4152
  try {
4092
4153
  const { execSync } = await import('child_process');
@@ -4144,7 +4205,7 @@ app.post("/workspace/search", async (req, res) => {
4144
4205
  .join('\n');
4145
4206
 
4146
4207
  const count = results.split('\n').filter(l => l.trim()).length;
4147
- console.log(` Found ${count} matches`);
4208
+ console.log(`Found ${count} matches`);
4148
4209
 
4149
4210
  res.json({
4150
4211
  ok: true,
@@ -4152,7 +4213,7 @@ app.post("/workspace/search", async (req, res) => {
4152
4213
  count: count
4153
4214
  });
4154
4215
  } catch (err) {
4155
- console.error(` [workspace/search] Error:`, err.message);
4216
+ console.error(`[workspace/search] Error:`, err.message);
4156
4217
  res.status(500).json({ ok: false, error: err.message });
4157
4218
  }
4158
4219
  });
@@ -4192,14 +4253,14 @@ app.post("/workspace/exec", async (req, res) => {
4192
4253
  ];
4193
4254
  const lowerCmd = command.toLowerCase().trim();
4194
4255
  if (dangerous.some(d => lowerCmd.includes(d))) {
4195
- console.warn(` [workspace/exec] BLOCKED dangerous command: ${command}`);
4256
+ console.warn(`[workspace/exec] BLOCKED dangerous command: ${command}`);
4196
4257
  return res.status(403).json({
4197
4258
  ok: false,
4198
4259
  error: "Command blocked for security reasons"
4199
4260
  });
4200
4261
  }
4201
4262
 
4202
- console.log(` [workspace/exec] Running: ${command.substring(0, 120)}...`);
4263
+ console.log(`[workspace/exec] Running: ${command.substring(0, 120)}...`);
4203
4264
 
4204
4265
  try {
4205
4266
  const { exec: execCb } = await import('child_process');
@@ -4213,7 +4274,7 @@ app.post("/workspace/exec", async (req, res) => {
4213
4274
  env: { ...process.env, FORCE_COLOR: '0' }
4214
4275
  });
4215
4276
 
4216
- console.log(` Command completed (stdout: ${result.stdout.length} chars)`);
4277
+ console.log(`Command completed (stdout: ${result.stdout.length} chars)`);
4217
4278
 
4218
4279
  res.json({
4219
4280
  ok: true,
@@ -4222,7 +4283,7 @@ app.post("/workspace/exec", async (req, res) => {
4222
4283
  exitCode: 0
4223
4284
  });
4224
4285
  } catch (err) {
4225
- console.error(` Command failed (exit: ${err.code}):`, err.message?.substring(0, 200));
4286
+ console.error(`Command failed (exit: ${err.code}):`, err.message?.substring(0, 200));
4226
4287
  res.json({
4227
4288
  ok: false,
4228
4289
  stdout: err.stdout || '',
@@ -4255,7 +4316,7 @@ app.post("/workspace/test-endpoint", async (req, res) => {
4255
4316
  return res.status(403).json({ error: "Only localhost URLs allowed for security" });
4256
4317
  }
4257
4318
 
4258
- console.log(` Testing: ${method} ${url} (${testName || 'unnamed'})`);
4319
+ console.log(`Testing: ${method} ${url} (${testName || 'unnamed'})`);
4259
4320
 
4260
4321
  const startTime = Date.now();
4261
4322
 
@@ -4305,7 +4366,7 @@ app.post("/workspace/test-endpoint", async (req, res) => {
4305
4366
  : response.status >= 200 && response.status < 400
4306
4367
  };
4307
4368
 
4308
- console.log(` ${response.status} ${response.statusText} (${durationMs}ms) ${result.passed ? '' : ''}`);
4369
+ console.log(`${response.status} ${response.statusText} (${durationMs}ms) ${result.passed ? '' : ''}`);
4309
4370
  res.json(result);
4310
4371
 
4311
4372
  } catch (err) {
@@ -4381,7 +4442,7 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4381
4442
  try {
4382
4443
  const stashResult = execSync('git stash --include-untracked 2>&1', opts).trim();
4383
4444
  hadStash = !stashResult.includes('No local changes');
4384
- if (hadStash) console.log(' Stashed uncommitted changes');
4445
+ if (hadStash) console.log('Stashed uncommitted changes');
4385
4446
  } catch {}
4386
4447
 
4387
4448
  // 4. Create and checkout new branch (with unique name if exists)
@@ -4405,7 +4466,7 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4405
4466
  try {
4406
4467
  execSync('git stash pop', opts);
4407
4468
  } catch (e) {
4408
- console.warn(' Stash pop had conflicts, trying apply:', e.message);
4469
+ console.warn('Stash pop had conflicts, trying apply:', e.message);
4409
4470
  try { execSync('git stash apply', opts); } catch {}
4410
4471
  }
4411
4472
  }
@@ -4427,6 +4488,13 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4427
4488
  }
4428
4489
 
4429
4490
  // 8. Commit
4491
+ // Ensure git identity is configured (required in Cloud Run environment)
4492
+ try {
4493
+ execSync('git config user.email "ai@deepdebug.ai"', opts);
4494
+ execSync('git config user.name "DeepDebug AI"', opts);
4495
+ } catch (e) {
4496
+ console.warn('Could not set git config:', e.message);
4497
+ }
4430
4498
  const safeMsg = commitMessage.replace(/"/g, '\\"').replace(/\n/g, '\\n');
4431
4499
  execSync(`git commit -m "${safeMsg}"`, opts);
4432
4500
 
@@ -4434,7 +4502,7 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4434
4502
  let pushResult = '';
4435
4503
  let pushed = false;
4436
4504
 
4437
- console.log(` Git push gitToken provided: ${!!gitToken}, repoUrl provided: ${!!repoUrl}`);
4505
+ console.log(`Git push gitToken provided: ${!!gitToken}, repoUrl provided: ${!!repoUrl}`);
4438
4506
 
4439
4507
  // If gitToken provided, set up authenticated remote URL for push
4440
4508
  if (gitToken) {
@@ -4446,11 +4514,11 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4446
4514
  // No remote configured use repoUrl from integration if available
4447
4515
  if (repoUrl) {
4448
4516
  remoteUrlRaw = repoUrl;
4449
- console.log(` No git remote, using repoUrl from integration: ${repoUrl}`);
4517
+ console.log(`No git remote, using repoUrl from integration: ${repoUrl}`);
4450
4518
  }
4451
4519
  }
4452
4520
 
4453
- console.log(` Remote URL: ${remoteUrlRaw.replace(gitToken, '***')}`);
4521
+ console.log(`Remote URL: ${remoteUrlRaw.replace(gitToken, '***')}`);
4454
4522
  let authenticatedUrl = '';
4455
4523
 
4456
4524
  if (remoteUrlRaw.includes('github.com')) {
@@ -4459,7 +4527,7 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4459
4527
  .replace(/^git@github\.com:/, '')
4460
4528
  .replace(/\.git$/, '');
4461
4529
  authenticatedUrl = `https://x-access-token:${gitToken}@github.com/${repoPath}.git`;
4462
- console.log(` GitHub auth URL: https://x-access-token:***@github.com/${repoPath}.git`);
4530
+ console.log(`GitHub auth URL: https://x-access-token:***@github.com/${repoPath}.git`);
4463
4531
  } else if (remoteUrlRaw.includes('gitlab.com') || remoteUrlRaw.includes('gitlab')) {
4464
4532
  const repoPath = remoteUrlRaw
4465
4533
  .replace(/^https?:\/\/(.*@)?[^\/]+\//, '')
@@ -4467,7 +4535,7 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4467
4535
  .replace(/\.git$/, '');
4468
4536
  const host = remoteUrlRaw.match(/https?:\/\/([^\/]+)/)?.[1] || 'gitlab.com';
4469
4537
  authenticatedUrl = `https://oauth2:${gitToken}@${host}/${repoPath}.git`;
4470
- console.log(` GitLab auth URL: https://oauth2:***@${host}/${repoPath}.git`);
4538
+ console.log(`GitLab auth URL: https://oauth2:***@${host}/${repoPath}.git`);
4471
4539
  } else if (remoteUrlRaw.includes('bitbucket.org') || remoteUrlRaw.includes('bitbucket')) {
4472
4540
  const repoPath = remoteUrlRaw
4473
4541
  .replace(/^https?:\/\/(.*@)?bitbucket\.org\//, '')
@@ -4481,11 +4549,11 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4481
4549
  const urlObj = new URL(remoteUrlRaw.replace(/^git@([^:]+):/, 'https://$1/'));
4482
4550
  authenticatedUrl = `https://oauth2:${gitToken}@${urlObj.host}${urlObj.pathname}`;
4483
4551
  if (!authenticatedUrl.endsWith('.git')) authenticatedUrl += '.git';
4484
- console.log(` Generic auth URL for ${urlObj.host}`);
4552
+ console.log(`Generic auth URL for ${urlObj.host}`);
4485
4553
  }
4486
4554
 
4487
4555
  if (authenticatedUrl) {
4488
- console.log(` Pushing ${finalBranchName} with token auth...`);
4556
+ console.log(`Pushing ${finalBranchName} with token auth...`);
4489
4557
  try {
4490
4558
  // Don't use 2>&1 let execSync capture stderr separately
4491
4559
  pushResult = execSync(`git push ${authenticatedUrl} ${finalBranchName}`, {
@@ -4494,20 +4562,20 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4494
4562
  stdio: ['pipe', 'pipe', 'pipe'] // capture stdin, stdout, stderr separately
4495
4563
  }).toString();
4496
4564
  pushed = true;
4497
- console.log(` Pushed with token authentication`);
4565
+ console.log(`Pushed with token authentication`);
4498
4566
  } catch (innerErr) {
4499
4567
  // Mask token in error messages before logging
4500
4568
  const maskToken = (str) => str ? str.replace(gitToken, '***TOKEN***') : '';
4501
4569
  const errMsg = maskToken(innerErr.stderr?.toString() || innerErr.stdout?.toString() || innerErr.message || '');
4502
- console.warn(` Authenticated push failed: ${errMsg}`);
4570
+ console.warn(`Authenticated push failed: ${errMsg}`);
4503
4571
  pushResult = errMsg;
4504
4572
  }
4505
4573
  } else {
4506
- console.warn(` Could not construct authenticated URL from: ${remoteUrlRaw}`);
4574
+ console.warn(`Could not construct authenticated URL from: ${remoteUrlRaw}`);
4507
4575
  }
4508
4576
  } catch (pushErr) {
4509
4577
  const maskToken = (str) => str ? str.replace(gitToken, '***TOKEN***') : '';
4510
- console.warn(` Git auth setup failed: ${maskToken(pushErr.message)}`);
4578
+ console.warn(`Git auth setup failed: ${maskToken(pushErr.message)}`);
4511
4579
  pushResult = maskToken(pushErr.message) || 'Push setup failed';
4512
4580
  }
4513
4581
  }
@@ -4522,7 +4590,7 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4522
4590
  pushResult = execSync(`git push origin ${finalBranchName} 2>&1`, opts).toString();
4523
4591
  pushed = true;
4524
4592
  } catch (pushErr2) {
4525
- console.warn(` Git push failed: ${pushErr2.message}`);
4593
+ console.warn(`Git push failed: ${pushErr2.message}`);
4526
4594
  pushResult = pushErr2.message || 'Push failed no remote configured or auth required';
4527
4595
  }
4528
4596
  }
@@ -4581,8 +4649,8 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4581
4649
  console.warn('Could not detect remote URL:', e.message);
4582
4650
  }
4583
4651
 
4584
- console.log(` Fix branch created: ${finalBranchName} (${commitSha.substring(0, 8)}) pushed=${pushed}`);
4585
- if (mrUrl) console.log(` MR URL: ${mrUrl}`);
4652
+ console.log(`Fix branch created: ${finalBranchName} (${commitSha.substring(0, 8)}) pushed=${pushed}`);
4653
+ if (mrUrl) console.log(`MR URL: ${mrUrl}`);
4586
4654
 
4587
4655
  // 10. Switch back to original branch and merge fix to keep changes on disk
4588
4656
  try {
@@ -4591,7 +4659,7 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4591
4659
  // This keeps the diff viewer working (disk has patched version)
4592
4660
  try {
4593
4661
  execSync(`git merge ${finalBranchName} --no-edit`, opts);
4594
- console.log(` Merged ${finalBranchName} into ${currentBranch}`);
4662
+ console.log(`Merged ${finalBranchName} into ${currentBranch}`);
4595
4663
  } catch (mergeErr) {
4596
4664
  // If merge fails (conflicts), just cherry-pick the changes without committing
4597
4665
  try {
@@ -4605,7 +4673,7 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4605
4673
  execSync(`git checkout ${finalBranchName} -- ${f}`, opts);
4606
4674
  } catch {}
4607
4675
  }
4608
- console.log(` Cherry-picked ${changedFiles.length} file(s) from ${finalBranchName}`);
4676
+ console.log(`Cherry-picked ${changedFiles.length} file(s) from ${finalBranchName}`);
4609
4677
  } catch {}
4610
4678
  }
4611
4679
  } catch {}
@@ -4652,14 +4720,14 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4652
4720
  if (response.ok) {
4653
4721
  const prData = await response.json();
4654
4722
  prUrl = prData.html_url;
4655
- console.log(` GitHub PR created: ${prUrl}`);
4723
+ console.log(`GitHub PR created: ${prUrl}`);
4656
4724
  } else {
4657
4725
  const errText = await response.text();
4658
- console.warn(` GitHub PR creation failed (${response.status}): ${errText.substring(0, 200)}`);
4726
+ console.warn(`GitHub PR creation failed (${response.status}): ${errText.substring(0, 200)}`);
4659
4727
  prUrl = mrUrl;
4660
4728
  }
4661
4729
  } catch (prErr) {
4662
- console.warn(` GitHub PR error: ${prErr.message}`);
4730
+ console.warn(`GitHub PR error: ${prErr.message}`);
4663
4731
  prUrl = mrUrl;
4664
4732
  }
4665
4733
 
@@ -4693,14 +4761,14 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4693
4761
  if (response.ok) {
4694
4762
  const mrData = await response.json();
4695
4763
  prUrl = mrData.web_url;
4696
- console.log(` GitLab MR created: ${prUrl}`);
4764
+ console.log(`GitLab MR created: ${prUrl}`);
4697
4765
  } else {
4698
4766
  const errText = await response.text();
4699
- console.warn(` GitLab MR creation failed (${response.status}): ${errText.substring(0, 200)}`);
4767
+ console.warn(`GitLab MR creation failed (${response.status}): ${errText.substring(0, 200)}`);
4700
4768
  prUrl = mrUrl;
4701
4769
  }
4702
4770
  } catch (glErr) {
4703
- console.warn(` GitLab MR error: ${glErr.message}`);
4771
+ console.warn(`GitLab MR error: ${glErr.message}`);
4704
4772
  prUrl = mrUrl;
4705
4773
  }
4706
4774
 
@@ -4753,14 +4821,14 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4753
4821
  if (response.ok) {
4754
4822
  const prData = await response.json();
4755
4823
  prUrl = prData.links && prData.links.html ? prData.links.html.href : mrUrl;
4756
- console.log(` Bitbucket PR created: ${prUrl}`);
4824
+ console.log(`Bitbucket PR created: ${prUrl}`);
4757
4825
  } else {
4758
4826
  const errText = await response.text();
4759
- console.warn(` Bitbucket PR creation failed (${response.status}): ${errText.substring(0, 200)}`);
4827
+ console.warn(`Bitbucket PR creation failed (${response.status}): ${errText.substring(0, 200)}`);
4760
4828
  prUrl = mrUrl;
4761
4829
  }
4762
4830
  } catch (bbErr) {
4763
- console.warn(` Bitbucket PR error: ${bbErr.message}`);
4831
+ console.warn(`Bitbucket PR error: ${bbErr.message}`);
4764
4832
  prUrl = mrUrl;
4765
4833
  }
4766
4834
  }
@@ -4783,7 +4851,7 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4783
4851
  });
4784
4852
 
4785
4853
  } catch (err) {
4786
- console.error(` Git branch creation failed: ${err.message}`);
4854
+ console.error(`Git branch creation failed: ${err.message}`);
4787
4855
  res.status(500).json({ ok: false, error: err.message });
4788
4856
  }
4789
4857
  });
@@ -4895,7 +4963,7 @@ app.get("/workspace/git/pr/comments", async (req, res) => {
4895
4963
  unresolvedCount: comments.filter(c => c.resolved === false || c.resolved === undefined).length
4896
4964
  });
4897
4965
  } catch (err) {
4898
- console.error(' Failed to fetch PR comments:', err.message);
4966
+ console.error('Failed to fetch PR comments:', err.message);
4899
4967
  res.status(500).json({ ok: false, error: err.message });
4900
4968
  }
4901
4969
  });
@@ -4932,7 +5000,7 @@ app.get("/workspace/git/pr/comments/:commentId", async (req, res) => {
4932
5000
 
4933
5001
  res.json({ ok: true, comment });
4934
5002
  } catch (err) {
4935
- console.error(' Failed to fetch PR comment:', err.message);
5003
+ console.error('Failed to fetch PR comment:', err.message);
4936
5004
  res.status(500).json({ ok: false, error: err.message });
4937
5005
  }
4938
5006
  });
@@ -4994,10 +5062,10 @@ app.post("/workspace/git/pr/comments", async (req, res) => {
4994
5062
  comment = await provider.instance.addPRComment(owner, repo, Number(prNumber), body);
4995
5063
  }
4996
5064
 
4997
- console.log(` PR comment added to PR #${prNumber}: ${body.substring(0, 50)}...`);
5065
+ console.log(`PR comment added to PR #${prNumber}: ${body.substring(0, 50)}...`);
4998
5066
  res.json({ ok: true, comment });
4999
5067
  } catch (err) {
5000
- console.error(' Failed to add PR comment:', err.message);
5068
+ console.error('Failed to add PR comment:', err.message);
5001
5069
  res.status(500).json({ ok: false, error: err.message });
5002
5070
  }
5003
5071
  });
@@ -5032,10 +5100,10 @@ app.post("/workspace/git/pr/comments/:commentId/resolve", async (req, res) => {
5032
5100
  const { owner, repo } = provider.info;
5033
5101
  const result = await provider.instance.resolvePRComment(owner, repo, Number(prNumber), commentId);
5034
5102
 
5035
- console.log(` PR comment ${commentId} resolved on PR #${prNumber}`);
5103
+ console.log(`PR comment ${commentId} resolved on PR #${prNumber}`);
5036
5104
  res.json({ ok: true, commentId, ...result });
5037
5105
  } catch (err) {
5038
- console.error(' Failed to resolve PR comment:', err.message);
5106
+ console.error('Failed to resolve PR comment:', err.message);
5039
5107
  res.status(500).json({ ok: false, error: err.message });
5040
5108
  }
5041
5109
  });
@@ -5070,10 +5138,10 @@ app.post("/workspace/git/pr/comments/:commentId/unresolve", async (req, res) =>
5070
5138
  const { owner, repo } = provider.info;
5071
5139
  const result = await provider.instance.unresolvePRComment(owner, repo, Number(prNumber), commentId);
5072
5140
 
5073
- console.log(` PR comment ${commentId} unresolve on PR #${prNumber}`);
5141
+ console.log(`PR comment ${commentId} unresolve on PR #${prNumber}`);
5074
5142
  res.json({ ok: true, commentId, ...result });
5075
5143
  } catch (err) {
5076
- console.error(' Failed to unresolve PR comment:', err.message);
5144
+ console.error('Failed to unresolve PR comment:', err.message);
5077
5145
  res.status(500).json({ ok: false, error: err.message });
5078
5146
  }
5079
5147
  });
@@ -5118,9 +5186,9 @@ app.post("/workspace/git/pr/comments/:commentId/fix-and-resolve", async (req, re
5118
5186
  return res.status(404).json({ error: "Comment not found" });
5119
5187
  }
5120
5188
 
5121
- console.log(` AI Fix & Resolve: PR #${prNumber}, comment ${commentId}`);
5122
- console.log(` File: ${comment.path || '(general)'}, Line: ${comment.line || 'N/A'}`);
5123
- console.log(` Request: ${comment.body.substring(0, 100)}...`);
5189
+ console.log(`AI Fix & Resolve: PR #${prNumber}, comment ${commentId}`);
5190
+ console.log(`File: ${comment.path || '(general)'}, Line: ${comment.line || 'N/A'}`);
5191
+ console.log(`Request: ${comment.body.substring(0, 100)}...`);
5124
5192
 
5125
5193
  // 2. Return the comment info for the Gateway to orchestrate the AI fix
5126
5194
  // The actual AI analysis + patch is handled by the Gateway's AI service,
@@ -5150,7 +5218,7 @@ app.post("/workspace/git/pr/comments/:commentId/fix-and-resolve", async (req, re
5150
5218
  message: 'Comment fetched. Gateway should now: 1) Read file, 2) AI analyze, 3) Apply patch, 4) Commit, 5) Reply, 6) Resolve'
5151
5219
  });
5152
5220
  } catch (err) {
5153
- console.error(' Failed to prepare fix-and-resolve:', err.message);
5221
+ console.error('Failed to prepare fix-and-resolve:', err.message);
5154
5222
  res.status(500).json({ ok: false, error: err.message });
5155
5223
  }
5156
5224
  });
@@ -5173,7 +5241,7 @@ async function _getGitProvider() {
5173
5241
  try {
5174
5242
  remoteUrl = execSync('git remote get-url origin', opts).trim();
5175
5243
  } catch {
5176
- console.warn(' No git remote found');
5244
+ console.warn('No git remote found');
5177
5245
  return null;
5178
5246
  }
5179
5247
 
@@ -5183,7 +5251,7 @@ async function _getGitProvider() {
5183
5251
  const providerId = registry.detectProviderFromUrl(remoteUrl);
5184
5252
 
5185
5253
  if (!providerId) {
5186
- console.warn(` Unknown git provider for URL: ${remoteUrl}`);
5254
+ console.warn(`Unknown git provider for URL: ${remoteUrl}`);
5187
5255
  return null;
5188
5256
  }
5189
5257
 
@@ -5198,7 +5266,7 @@ async function _getGitProvider() {
5198
5266
  }
5199
5267
 
5200
5268
  if (!token) {
5201
- console.warn(` No token found for ${providerId}. Set ${providerId.toUpperCase()}_TOKEN or GIT_TOKEN env var.`);
5269
+ console.warn(`No token found for ${providerId}. Set ${providerId.toUpperCase()}_TOKEN or GIT_TOKEN env var.`);
5202
5270
  return null;
5203
5271
  }
5204
5272
 
@@ -5218,7 +5286,7 @@ async function _getGitProvider() {
5218
5286
 
5219
5287
  return { instance, info, providerId, remoteUrl };
5220
5288
  } catch (err) {
5221
- console.error(' Failed to initialize git provider:', err.message);
5289
+ console.error('Failed to initialize git provider:', err.message);
5222
5290
  return null;
5223
5291
  }
5224
5292
  }
@@ -5308,7 +5376,7 @@ app.post("/workspace/:workspaceId/run", async (req, res) => {
5308
5376
  // ============================================
5309
5377
  async function startWebSocketTunnel(port, gatewayUrl, apiKey, tenantId) {
5310
5378
  if (!gatewayUrl || !apiKey || !tenantId) {
5311
- console.log(' WebSocket tunnel skipped: missing gatewayUrl, apiKey or tenantId in ~/.deepdebug/config.json');
5379
+ console.log('WebSocket tunnel skipped: missing gatewayUrl, apiKey or tenantId in ~/.deepdebug/config.json');
5312
5380
  return;
5313
5381
  }
5314
5382
 
@@ -5326,7 +5394,7 @@ async function startWebSocketTunnel(port, gatewayUrl, apiKey, tenantId) {
5326
5394
  ws = new WebSocket(fullUrl);
5327
5395
 
5328
5396
  ws.on('open', () => {
5329
- console.log(` WebSocket tunnel connected to Gateway`);
5397
+ console.log(`WebSocket tunnel connected to Gateway`);
5330
5398
  reconnectDelay = 2000;
5331
5399
  ws.send(JSON.stringify({ type: 'register', tenantId, port, workspacePath: WORKSPACE_ROOT || null }));
5332
5400
  const hb = setInterval(() => {
@@ -5342,7 +5410,7 @@ async function startWebSocketTunnel(port, gatewayUrl, apiKey, tenantId) {
5342
5410
  try { request = JSON.parse(text); } catch { return; }
5343
5411
  const { requestId, command, params } = request;
5344
5412
  if (!requestId || !command) return;
5345
- console.log(` WS command: ${command}`);
5413
+ console.log(`WS command: ${command}`);
5346
5414
  let result;
5347
5415
  try { result = await handleWsCommand(command, params || {}); }
5348
5416
  catch (err) { result = { error: err.message }; }
@@ -5351,19 +5419,19 @@ async function startWebSocketTunnel(port, gatewayUrl, apiKey, tenantId) {
5351
5419
 
5352
5420
  ws.on('close', () => {
5353
5421
  if (!isShuttingDown) {
5354
- console.log(` WS disconnected. Reconnecting in ${reconnectDelay/1000}s...`);
5422
+ console.log(`WS disconnected. Reconnecting in ${reconnectDelay/1000}s...`);
5355
5423
  setTimeout(connect, reconnectDelay);
5356
5424
  reconnectDelay = Math.min(reconnectDelay * 2, 30000);
5357
5425
  }
5358
5426
  });
5359
5427
 
5360
- ws.on('error', (err) => console.warn(` WS error: ${err.message}`));
5428
+ ws.on('error', (err) => console.warn(`WS error: ${err.message}`));
5361
5429
 
5362
5430
  } catch (err) {
5363
5431
  if (err.code === 'ERR_MODULE_NOT_FOUND') {
5364
- console.warn(' WebSocket tunnel requires "ws" package. Run: npm install ws');
5432
+ console.warn('WebSocket tunnel requires "ws" package. Run: npm install ws');
5365
5433
  } else {
5366
- console.warn(` WS tunnel error: ${err.message}`);
5434
+ console.warn(`WS tunnel error: ${err.message}`);
5367
5435
  setTimeout(connect, reconnectDelay);
5368
5436
  reconnectDelay = Math.min(reconnectDelay * 2, 30000);
5369
5437
  }
@@ -5434,7 +5502,7 @@ async function startWebSocketTunnel(port, gatewayUrl, apiKey, tenantId) {
5434
5502
  return { error: 'backupId or incidentId is required' };
5435
5503
  }
5436
5504
 
5437
- console.log(` WS workspace.diff ${endpoint}`);
5505
+ console.log(`WS workspace.diff ${endpoint}`);
5438
5506
  const res = await fetch(`${localBase}${endpoint}`, {
5439
5507
  method: 'GET',
5440
5508
  headers: { 'Content-Type': 'application/json' }
@@ -5568,7 +5636,7 @@ async function startWebSocketTunnel(port, gatewayUrl, apiKey, tenantId) {
5568
5636
  }
5569
5637
 
5570
5638
  // ============================================
5571
- // 🤖 SETUP AGENT ROUTES
5639
+ // SETUP AGENT ROUTES
5572
5640
  // Supports the AI Assistant chat commands
5573
5641
  // ============================================
5574
5642
 
@@ -5585,7 +5653,7 @@ app.post("/setup/run-command", async (req, res) => {
5585
5653
  return res.status(403).json({ ok: false, error: "Command blocked for safety" });
5586
5654
  }
5587
5655
 
5588
- console.log(`🤖 [SetupAgent] Running: ${command.substring(0, 100)}`);
5656
+ console.log(`[SetupAgent] Running: ${command.substring(0, 100)}`);
5589
5657
  const { exec: execCb } = await import('child_process');
5590
5658
  const { promisify } = await import('util');
5591
5659
  const execAsync = promisify(execCb);
@@ -5683,10 +5751,10 @@ app.post("/setup/run-auth-command", async (req, res) => {
5683
5751
 
5684
5752
  const { exec: execCb } = await import('child_process');
5685
5753
  const bgCmd = process.platform === 'win32' ? `start cmd /c "${command}"` : `${command} &`;
5686
- console.log(`🔐 [SetupAgent] Starting auth: ${command.substring(0, 80)}`);
5754
+ console.log(`[SetupAgent] Starting auth: ${command.substring(0, 80)}`);
5687
5755
 
5688
5756
  execCb(bgCmd, { shell: true }, (err) => {
5689
- if (err) console.warn(`⚠️ Auth command warning: ${err.message}`);
5757
+ if (err) console.warn(`Auth command warning: ${err.message}`);
5690
5758
  });
5691
5759
 
5692
5760
  res.json({ ok: true, status: "started", session_id, message: "Auth command started, browser should open" });
@@ -5730,13 +5798,13 @@ app.get("/setup/auth-status", async (req, res) => {
5730
5798
  // ============================================
5731
5799
  app.listen(PORT, '0.0.0.0', async () => {
5732
5800
  console.log(`\n DeepDebug Local Agent listening on port ${PORT}`);
5733
- console.log(` Environment: ${process.env.NODE_ENV || 'development'}`);
5734
- console.log(` Process Manager initialized`);
5735
- console.log(` Backup system ready (max: ${MAX_BACKUPS} backups)`);
5736
- console.log(` AI Vibe Coding Engine: ${aiEngine?.isActive ? 'ACTIVE' : 'DISABLED'}`);
5801
+ console.log(`Environment: ${process.env.NODE_ENV || 'development'}`);
5802
+ console.log(`Process Manager initialized`);
5803
+ console.log(`Backup system ready (max: ${MAX_BACKUPS} backups)`);
5804
+ console.log(`AI Vibe Coding Engine: ${aiEngine?.isActive ? 'ACTIVE' : 'DISABLED'}`);
5737
5805
  if (aiEngine) {
5738
- console.log(` Gateway URL: ${aiEngine.gatewayUrl}`);
5739
- console.log(` Max Retries: ${aiEngine.maxRetries}`);
5806
+ console.log(`Gateway URL: ${aiEngine.gatewayUrl}`);
5807
+ console.log(`Max Retries: ${aiEngine.maxRetries}`);
5740
5808
  }
5741
5809
  console.log(`\n Ready to receive requests!\n`);
5742
5810
 
@@ -5748,7 +5816,7 @@ app.listen(PORT, '0.0.0.0', async () => {
5748
5816
 
5749
5817
  const gwUrl = cfg.gatewayUrl || process.env.GATEWAY_URL;
5750
5818
  const apiKey = cfg.apiKey || process.env.DEEPDEBUG_API_KEY;
5751
- let tenantId = cfg.tenantId;
5819
+ let tenantId = cfg.tenantId || process.env.TENANT_ID;
5752
5820
  if (!tenantId && apiKey) {
5753
5821
  try {
5754
5822
  const payload = JSON.parse(Buffer.from(apiKey.split('.')[1], 'base64').toString());
@@ -5765,8 +5833,8 @@ app.listen(PORT, '0.0.0.0', async () => {
5765
5833
  try {
5766
5834
  startMCPHttpServer(wsManager, parseInt(MCP_PORT));
5767
5835
  } catch (err) {
5768
- console.warn(` MCP HTTP Server failed to start: ${err.message}`);
5769
- console.warn(` (MCP features disabled, REST API continues normally)`);
5836
+ console.warn(`MCP HTTP Server failed to start: ${err.message}`);
5837
+ console.warn(`(MCP features disabled, REST API continues normally)`);
5770
5838
  }
5771
5839
 
5772
5840
  // Auto-register default workspace in WorkspaceManager