deepdebug-local-agent 1.0.16 → 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 +316 -220
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);
@@ -850,19 +870,50 @@ app.post("/workspace/open", async (req, res) => {
850
870
  res.json({ ok: true, root: abs, workspaceId: wsId, mode: "local", meta, port });
851
871
  });
852
872
 
873
+
874
+
853
875
  /**
854
876
  * POST /workspace/clone
855
877
  * Clones a git repository into the local filesystem, then opens it as workspace.
856
878
  * Body: { gitUrl, targetPath, workspaceId? }
857
879
  */
858
880
  app.post("/workspace/clone", async (req, res) => {
859
- const { gitUrl, targetPath, workspaceId } = req.body || {};
860
-
861
- if (!gitUrl) return res.status(400).json({ ok: false, error: "gitUrl is required" });
862
- if (!targetPath) return res.status(400).json({ ok: false, error: "targetPath is required" });
881
+ const body = req.body || {};
882
+ const gitUrl = body.gitUrl || body.repoUrl;
883
+ const targetPath = body.targetPath || body.targetDir;
884
+ const tenantId = body.tenantId;
885
+ const workspaceId = body.workspaceId;
886
+ const gitToken = body.gitToken;
887
+ const branch = body.branch;
888
+
889
+ if (!gitUrl) return res.status(400).json({ ok: false, error: "gitUrl is required" });
890
+
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
+ }
863
905
 
864
- const absTarget = path.resolve(targetPath);
865
- console.log(` Clone request: ${gitUrl} -> ${absTarget}`);
906
+ let authenticatedUrl = gitUrl;
907
+ if (gitToken && gitUrl.startsWith('https://') && !gitUrl.includes('@')) {
908
+ if (gitUrl.includes('bitbucket.org')) {
909
+ authenticatedUrl = gitUrl.replace('https://', `https://x-token-auth:${gitToken}@`);
910
+ } else if (gitUrl.includes('gitlab.com')) {
911
+ authenticatedUrl = gitUrl.replace('https://', `https://oauth2:${gitToken}@`);
912
+ } else {
913
+ authenticatedUrl = gitUrl.replace('https://', `https://x-access-token:${gitToken}@`);
914
+ }
915
+ }
916
+ console.log(`Clone request: ${gitUrl} -> ${absTarget}`);
866
917
 
867
918
  try {
868
919
  // Ensure parent directory exists
@@ -874,13 +925,22 @@ app.post("/workspace/clone", async (req, res) => {
874
925
  const alreadyCloned = await exists(gitDir);
875
926
 
876
927
  if (alreadyCloned) {
877
- console.log(` Repo already exists at ${absTarget}, running git pull...`);
878
- const { stdout } = await execAsync('git pull', { cwd: absTarget, timeout: 120000 });
879
- 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
+ }
880
938
  } else {
881
- console.log(` Running: git clone "${gitUrl}" "${absTarget}"`);
882
- await execAsync(`git clone "${gitUrl}" "${absTarget}"`, { timeout: 300000 });
883
- console.log(` Clone complete: ${absTarget}`);
939
+ const safeLog = authenticatedUrl.replace(/x-token-auth:[^@]+@/g, 'x-token-auth:***@').replace(/oauth2:[^@]+@/g, 'oauth2:***@').replace(/x-access-token:[^@]+@/g, 'x-access-token:***@');
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}`);
884
944
  }
885
945
 
886
946
  // Open the cloned workspace
@@ -889,7 +949,7 @@ app.post("/workspace/clone", async (req, res) => {
889
949
  try {
890
950
  await wsManager.open(wsId, absTarget);
891
951
  } catch (err) {
892
- console.warn(` WorkspaceManager.open failed (non-fatal): ${err.message}`);
952
+ console.warn(`WorkspaceManager.open failed (non-fatal): ${err.message}`);
893
953
  }
894
954
 
895
955
  const meta = await detectProject(absTarget);
@@ -905,7 +965,7 @@ app.post("/workspace/clone", async (req, res) => {
905
965
  });
906
966
 
907
967
  } catch (err) {
908
- console.error(` Clone failed: ${err.message}`);
968
+ console.error(`Clone failed: ${err.message}`);
909
969
  const hint = err.message.includes('Authentication') || err.message.includes('could not read')
910
970
  ? "Authentication failed. Ensure the repo is public or GitHub integration is configured."
911
971
  : err.message.includes('not found') || err.message.includes('does not exist')
@@ -987,6 +1047,35 @@ app.get("/workspace/file-content", async (req, res) => {
987
1047
  }
988
1048
  });
989
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
+
990
1079
  /** L mltiplos arquivos */
991
1080
  app.post("/workspace/batch-read", async (req, res) => {
992
1081
  const wsRoot = resolveWorkspaceRoot(req);
@@ -1029,7 +1118,7 @@ app.get("/workspace/file-exists", async (req, res) => {
1029
1118
  const fullPath = path.join(wsRoot, relativePath);
1030
1119
  const fileExists = await exists(fullPath);
1031
1120
 
1032
- console.log(` [file-exists] ${relativePath} -> ${fileExists ? 'EXISTS' : 'NOT FOUND'}`);
1121
+ console.log(`[file-exists] ${relativePath} -> ${fileExists ? 'EXISTS' : 'NOT FOUND'}`);
1033
1122
 
1034
1123
  res.json({
1035
1124
  ok: true,
@@ -1038,7 +1127,7 @@ app.get("/workspace/file-exists", async (req, res) => {
1038
1127
  fullPath: fullPath
1039
1128
  });
1040
1129
  } catch (err) {
1041
- console.error(` [file-exists] Error:`, err.message);
1130
+ console.error(`[file-exists] Error:`, err.message);
1042
1131
  res.status(500).json({ ok: false, error: err.message });
1043
1132
  }
1044
1133
  });
@@ -1070,7 +1159,7 @@ app.post("/workspace/validate-paths", async (req, res) => {
1070
1159
  const allExist = results.every(r => r.exists);
1071
1160
  const missingPaths = results.filter(r => !r.exists).map(r => r.path);
1072
1161
 
1073
- console.log(` [validate-paths] Checked ${pathList.length} paths, ${missingPaths.length} missing`);
1162
+ console.log(`[validate-paths] Checked ${pathList.length} paths, ${missingPaths.length} missing`);
1074
1163
 
1075
1164
  res.json({
1076
1165
  ok: true,
@@ -1080,7 +1169,7 @@ app.post("/workspace/validate-paths", async (req, res) => {
1080
1169
  totalChecked: pathList.length
1081
1170
  });
1082
1171
  } catch (err) {
1083
- console.error(` [validate-paths] Error:`, err.message);
1172
+ console.error(`[validate-paths] Error:`, err.message);
1084
1173
  res.status(500).json({ ok: false, error: err.message });
1085
1174
  }
1086
1175
  });
@@ -1103,7 +1192,7 @@ app.post("/workspace/search-file", async (req, res) => {
1103
1192
  }
1104
1193
 
1105
1194
  try {
1106
- console.log(` [search-file] Searching for: ${fileName}`);
1195
+ console.log(`[search-file] Searching for: ${fileName}`);
1107
1196
 
1108
1197
  const rawFiles = await listRecursive(wsRoot, {
1109
1198
  maxDepth: 15,
@@ -1120,7 +1209,7 @@ app.post("/workspace/search-file", async (req, res) => {
1120
1209
  return String(f);
1121
1210
  }).filter(f => f && typeof f === 'string');
1122
1211
 
1123
- console.log(` [search-file] Scanning ${allFiles.length} files`);
1212
+ console.log(`[search-file] Scanning ${allFiles.length} files`);
1124
1213
 
1125
1214
  // Strategy 1: Exact path match
1126
1215
  let foundPath = allFiles.find(f => f.endsWith('/' + fileName) || f === fileName);
@@ -1150,14 +1239,14 @@ app.post("/workspace/search-file", async (req, res) => {
1150
1239
  }
1151
1240
 
1152
1241
  if (foundPath) {
1153
- console.log(` [search-file] Found: ${foundPath}`);
1242
+ console.log(`[search-file] Found: ${foundPath}`);
1154
1243
  res.json({ ok: true, found: true, path: foundPath, fileName });
1155
1244
  } else {
1156
- console.log(` [search-file] Not found: ${fileName}`);
1245
+ console.log(`[search-file] Not found: ${fileName}`);
1157
1246
  res.json({ ok: true, found: false, fileName, searchedFiles: allFiles.length });
1158
1247
  }
1159
1248
  } catch (err) {
1160
- console.error(` [search-file] Error:`, err.message);
1249
+ console.error(`[search-file] Error:`, err.message);
1161
1250
  res.status(500).json({ ok: false, error: err.message });
1162
1251
  }
1163
1252
  });
@@ -1181,7 +1270,7 @@ app.post("/workspace/search-by-content", async (req, res) => {
1181
1270
  }
1182
1271
 
1183
1272
  try {
1184
- console.log(` [search-by-content] Searching for terms: ${terms.join(', ')}`);
1273
+ console.log(`[search-by-content] Searching for terms: ${terms.join(', ')}`);
1185
1274
 
1186
1275
  const rawFiles = await listRecursive(wsRoot, {
1187
1276
  maxDepth: 15,
@@ -1201,7 +1290,7 @@ app.post("/workspace/search-by-content", async (req, res) => {
1201
1290
  return extensions.some(ext => filePath.endsWith(ext));
1202
1291
  });
1203
1292
 
1204
- console.log(` [search-by-content] Scanning ${filteredFiles.length} files`);
1293
+ console.log(`[search-by-content] Scanning ${filteredFiles.length} files`);
1205
1294
 
1206
1295
  const results = [];
1207
1296
 
@@ -1246,7 +1335,7 @@ app.post("/workspace/search-by-content", async (req, res) => {
1246
1335
  return true;
1247
1336
  }).slice(0, maxResults);
1248
1337
 
1249
- console.log(` [search-by-content] Found ${dedupedResults.length} matching files`);
1338
+ console.log(`[search-by-content] Found ${dedupedResults.length} matching files`);
1250
1339
 
1251
1340
  res.json({
1252
1341
  ok: true,
@@ -1255,7 +1344,7 @@ app.post("/workspace/search-by-content", async (req, res) => {
1255
1344
  termsSearched: terms
1256
1345
  });
1257
1346
  } catch (err) {
1258
- console.error(` [search-by-content] Error:`, err.message);
1347
+ console.error(`[search-by-content] Error:`, err.message);
1259
1348
  res.status(500).json({ ok: false, error: err.message });
1260
1349
  }
1261
1350
  });
@@ -1279,7 +1368,7 @@ app.post("/workspace/find-field-definition", async (req, res) => {
1279
1368
  }
1280
1369
 
1281
1370
  try {
1282
- console.log(` [find-field] Searching for field: ${fieldName}`);
1371
+ console.log(`[find-field] Searching for field: ${fieldName}`);
1283
1372
 
1284
1373
  const rawFiles = await listRecursive(wsRoot, {
1285
1374
  maxDepth: 15,
@@ -1358,7 +1447,7 @@ app.post("/workspace/find-field-definition", async (req, res) => {
1358
1447
  return 0;
1359
1448
  });
1360
1449
 
1361
- console.log(` [find-field] Found ${definitions.length} definitions for '${fieldName}'`);
1450
+ console.log(`[find-field] Found ${definitions.length} definitions for '${fieldName}'`);
1362
1451
 
1363
1452
  res.json({
1364
1453
  ok: true,
@@ -1367,7 +1456,7 @@ app.post("/workspace/find-field-definition", async (req, res) => {
1367
1456
  totalSearched: targetFiles.length
1368
1457
  });
1369
1458
  } catch (err) {
1370
- console.error(` [find-field] Error:`, err.message);
1459
+ console.error(`[find-field] Error:`, err.message);
1371
1460
  res.status(500).json({ ok: false, error: err.message });
1372
1461
  }
1373
1462
  });
@@ -1581,7 +1670,7 @@ app.post("/workspace/patch", async (req, res) => {
1581
1670
  if (!diff) return res.status(400).json({ error: "diff is required" });
1582
1671
 
1583
1672
  try {
1584
- console.log(` Applying patch for incident: ${incidentId || 'unknown'}`);
1673
+ console.log(`Applying patch for incident: ${incidentId || 'unknown'}`);
1585
1674
  const out = await applyUnifiedDiff(wsRoot, diff);
1586
1675
 
1587
1676
  // CRITICAL FIX: Format response as expected by Gateway
@@ -1596,7 +1685,7 @@ app.post("/workspace/patch", async (req, res) => {
1596
1685
  incidentId: incidentId
1597
1686
  };
1598
1687
 
1599
- console.log(` Patch applied successfully:`, {
1688
+ console.log(`Patch applied successfully:`, {
1600
1689
  target: out.target,
1601
1690
  bytes: out.bytes,
1602
1691
  incident: incidentId
@@ -1604,7 +1693,7 @@ app.post("/workspace/patch", async (req, res) => {
1604
1693
 
1605
1694
  res.json(response);
1606
1695
  } catch (e) {
1607
- console.error(` Patch failed:`, e.message);
1696
+ console.error(`Patch failed:`, e.message);
1608
1697
  res.status(400).json({
1609
1698
  ok: false,
1610
1699
  error: "patch failed",
@@ -1656,7 +1745,7 @@ let TEST_LOCAL_STATE = {
1656
1745
  * Returns current test local state with auto-detected port
1657
1746
  */
1658
1747
  app.get("/workspace/test-local/state", async (req, res) => {
1659
- console.log(" [TEST-LOCAL] Getting state:", TEST_LOCAL_STATE.status);
1748
+ console.log("[TEST-LOCAL] Getting state:", TEST_LOCAL_STATE.status);
1660
1749
 
1661
1750
  // Auto-detect port if not set in config
1662
1751
  let port = TEST_LOCAL_STATE.config?.server?.port;
@@ -1695,7 +1784,7 @@ app.post("/workspace/test-local/compile", async (req, res) => {
1695
1784
  if (!wsRoot) return res.status(400).json({ error: "workspace not set" });
1696
1785
 
1697
1786
  try {
1698
- console.log(" [TEST-LOCAL] Starting compilation...");
1787
+ console.log("[TEST-LOCAL] Starting compilation...");
1699
1788
  TEST_LOCAL_STATE.status = "compiling";
1700
1789
 
1701
1790
  const meta = await detectProject(wsRoot);
@@ -1730,7 +1819,7 @@ app.post("/workspace/test-local/compile", async (req, res) => {
1730
1819
  duration: compileResult.duration
1731
1820
  };
1732
1821
 
1733
- console.log(" [TEST-LOCAL] Compilation successful");
1822
+ console.log("[TEST-LOCAL] Compilation successful");
1734
1823
 
1735
1824
  res.json({
1736
1825
  ok: true,
@@ -1740,7 +1829,7 @@ app.post("/workspace/test-local/compile", async (req, res) => {
1740
1829
  stdout: compileResult.stdout
1741
1830
  });
1742
1831
  } catch (err) {
1743
- console.error(" [TEST-LOCAL] Compilation failed:", err.message);
1832
+ console.error("[TEST-LOCAL] Compilation failed:", err.message);
1744
1833
  TEST_LOCAL_STATE.status = "error";
1745
1834
  res.status(500).json({ ok: false, error: err.message });
1746
1835
  }
@@ -1793,7 +1882,7 @@ app.post("/workspace/test-local/start", async (req, res) => {
1793
1882
  const command = 'java';
1794
1883
  const args = ['-jar', jarPath, `--server.port=${serverPort}`];
1795
1884
 
1796
- console.log(` Command: ${command} ${args.join(' ')}`);
1885
+ console.log(`Command: ${command} ${args.join(' ')}`);
1797
1886
 
1798
1887
  // Env LIMPO - remover TODAS as variveis Spring que podem interferir
1799
1888
  const cleanEnv = { ...process.env };
@@ -1823,7 +1912,7 @@ app.post("/workspace/test-local/start", async (req, res) => {
1823
1912
  TEST_LOCAL_STATE.status = "running";
1824
1913
  TEST_LOCAL_STATE.config = { port: serverPort };
1825
1914
 
1826
- console.log(` [TEST-LOCAL] Server started on port ${serverPort}`);
1915
+ console.log(`[TEST-LOCAL] Server started on port ${serverPort}`);
1827
1916
 
1828
1917
  res.json({
1829
1918
  ok: true,
@@ -1873,7 +1962,7 @@ app.post("/workspace/test-local/start", async (req, res) => {
1873
1962
  });
1874
1963
  }
1875
1964
  } catch (err) {
1876
- console.error(" [TEST-LOCAL] Server start failed:", err.message);
1965
+ console.error("[TEST-LOCAL] Server start failed:", err.message);
1877
1966
  TEST_LOCAL_STATE.status = "error";
1878
1967
  res.status(500).json({ ok: false, error: err.message });
1879
1968
  }
@@ -1885,19 +1974,19 @@ app.post("/workspace/test-local/start", async (req, res) => {
1885
1974
  */
1886
1975
  app.post("/workspace/test-local/stop", async (req, res) => {
1887
1976
  try {
1888
- console.log(" [TEST-LOCAL] Stopping server...");
1977
+ console.log("[TEST-LOCAL] Stopping server...");
1889
1978
 
1890
1979
  await processManager.stop('test-local');
1891
1980
  TEST_LOCAL_STATE.status = "stopped";
1892
1981
 
1893
- console.log(" [TEST-LOCAL] Server stopped");
1982
+ console.log("[TEST-LOCAL] Server stopped");
1894
1983
 
1895
1984
  res.json({
1896
1985
  ok: true,
1897
1986
  status: "stopped"
1898
1987
  });
1899
1988
  } catch (err) {
1900
- console.error(" [TEST-LOCAL] Server stop failed:", err.message);
1989
+ console.error("[TEST-LOCAL] Server stop failed:", err.message);
1901
1990
  res.status(500).json({ ok: false, error: err.message });
1902
1991
  }
1903
1992
  });
@@ -1911,7 +2000,7 @@ app.get("/workspace/test-local/endpoints", async (req, res) => {
1911
2000
  if (!wsRoot) return res.status(400).json({ error: "workspace not set" });
1912
2001
 
1913
2002
  try {
1914
- console.log(" [TEST-LOCAL] Getting endpoints...");
2003
+ console.log("[TEST-LOCAL] Getting endpoints...");
1915
2004
 
1916
2005
  // If endpoints are cached, return them
1917
2006
  if (TEST_LOCAL_STATE.endpoints && TEST_LOCAL_STATE.endpoints.length > 0) {
@@ -1934,7 +2023,7 @@ app.get("/workspace/test-local/endpoints", async (req, res) => {
1934
2023
 
1935
2024
  TEST_LOCAL_STATE.endpoints = payloadDocs.endpoints;
1936
2025
 
1937
- console.log(` [TEST-LOCAL] Discovered ${payloadDocs.endpoints.length} endpoints`);
2026
+ console.log(`[TEST-LOCAL] Discovered ${payloadDocs.endpoints.length} endpoints`);
1938
2027
 
1939
2028
  res.json({
1940
2029
  ok: true,
@@ -1942,7 +2031,7 @@ app.get("/workspace/test-local/endpoints", async (req, res) => {
1942
2031
  cached: false
1943
2032
  });
1944
2033
  } catch (err) {
1945
- console.error(" [TEST-LOCAL] Failed to get endpoints:", err.message);
2034
+ console.error("[TEST-LOCAL] Failed to get endpoints:", err.message);
1946
2035
  res.status(500).json({ ok: false, error: err.message });
1947
2036
  }
1948
2037
  });
@@ -1962,7 +2051,7 @@ app.post("/workspace/test-local/execute", async (req, res) => {
1962
2051
  const serverPort = port || TEST_LOCAL_STATE.config?.server?.port || 8080;
1963
2052
  const url = `http://localhost:${serverPort}${reqPath}`;
1964
2053
 
1965
- console.log(` [TEST-LOCAL] Executing: ${method} ${url}`);
2054
+ console.log(`[TEST-LOCAL] Executing: ${method} ${url}`);
1966
2055
 
1967
2056
  const startTime = Date.now();
1968
2057
 
@@ -2011,14 +2100,14 @@ app.post("/workspace/test-local/execute", async (req, res) => {
2011
2100
  TEST_LOCAL_STATE.testResults.shift();
2012
2101
  }
2013
2102
 
2014
- console.log(` [TEST-LOCAL] Test result: ${response.status} (${duration}ms)`);
2103
+ console.log(`[TEST-LOCAL] Test result: ${response.status} (${duration}ms)`);
2015
2104
 
2016
2105
  res.json({
2017
2106
  ok: true,
2018
2107
  result
2019
2108
  });
2020
2109
  } catch (err) {
2021
- console.error(" [TEST-LOCAL] Test execution failed:", err.message);
2110
+ console.error("[TEST-LOCAL] Test execution failed:", err.message);
2022
2111
  res.json({
2023
2112
  ok: false,
2024
2113
  error: err.message,
@@ -2037,7 +2126,7 @@ app.post("/workspace/test-local/execute", async (req, res) => {
2037
2126
  * Returns stored test results
2038
2127
  */
2039
2128
  app.get("/workspace/test-local/results", (req, res) => {
2040
- console.log(" [TEST-LOCAL] Getting test results...");
2129
+ console.log("[TEST-LOCAL] Getting test results...");
2041
2130
 
2042
2131
  res.json({
2043
2132
  ok: true,
@@ -2051,7 +2140,7 @@ app.get("/workspace/test-local/results", (req, res) => {
2051
2140
  * Clears stored test results
2052
2141
  */
2053
2142
  app.post("/workspace/test-local/clear-results", (req, res) => {
2054
- console.log(" [TEST-LOCAL] Clearing test results...");
2143
+ console.log("[TEST-LOCAL] Clearing test results...");
2055
2144
 
2056
2145
  TEST_LOCAL_STATE.testResults = [];
2057
2146
 
@@ -2068,7 +2157,7 @@ app.post("/workspace/test-local/clear-results", (req, res) => {
2068
2157
  app.get("/workspace/test-local/logs", (req, res) => {
2069
2158
  const limit = parseInt(req.query.limit) || 500;
2070
2159
 
2071
- console.log(` [TEST-LOCAL] Getting logs (limit: ${limit})`);
2160
+ console.log(`[TEST-LOCAL] Getting logs (limit: ${limit})`);
2072
2161
 
2073
2162
  const logs = TEST_LOCAL_STATE.serverLogs.slice(-limit);
2074
2163
 
@@ -2087,7 +2176,7 @@ app.get("/workspace/controllers", async (req, res) => {
2087
2176
  if (!wsRoot) return res.status(400).json({ error: "workspace not set" });
2088
2177
 
2089
2178
  try {
2090
- console.log(" [CONTROLLERS] Discovering controllers...");
2179
+ console.log("[CONTROLLERS] Discovering controllers...");
2091
2180
 
2092
2181
  const scanner = new WorkspaceScanner(wsRoot);
2093
2182
  const structure = await scanner.scan();
@@ -2095,14 +2184,14 @@ app.get("/workspace/controllers", async (req, res) => {
2095
2184
  const controllerAnalyzer = new ControllerAnalyzer(wsRoot);
2096
2185
  const apiDocs = await controllerAnalyzer.generateApiDocs(structure.files);
2097
2186
 
2098
- console.log(` [CONTROLLERS] Found ${apiDocs.totalEndpoints} endpoints in ${apiDocs.totalControllers} controllers`);
2187
+ console.log(`[CONTROLLERS] Found ${apiDocs.totalEndpoints} endpoints in ${apiDocs.totalControllers} controllers`);
2099
2188
 
2100
2189
  res.json({
2101
2190
  ok: true,
2102
2191
  ...apiDocs
2103
2192
  });
2104
2193
  } catch (err) {
2105
- console.error(" [CONTROLLERS] Failed:", err.message);
2194
+ console.error("[CONTROLLERS] Failed:", err.message);
2106
2195
  res.status(500).json({ ok: false, error: err.message });
2107
2196
  }
2108
2197
  });
@@ -2113,7 +2202,7 @@ app.get("/workspace/dtos", async (req, res) => {
2113
2202
  if (!wsRoot) return res.status(400).json({ error: "workspace not set" });
2114
2203
 
2115
2204
  try {
2116
- console.log(" [DTOS] Analyzing DTOs...");
2205
+ console.log("[DTOS] Analyzing DTOs...");
2117
2206
 
2118
2207
  const scanner = new WorkspaceScanner(wsRoot);
2119
2208
  const structure = await scanner.scan();
@@ -2124,14 +2213,14 @@ app.get("/workspace/dtos", async (req, res) => {
2124
2213
  const dtoAnalyzer = new DTOAnalyzer(wsRoot);
2125
2214
  const payloadDocs = await dtoAnalyzer.generatePayloadDocs(structure.files, apiDocs.endpoints);
2126
2215
 
2127
- console.log(` [DTOS] Found ${payloadDocs.totalDtos} DTOs`);
2216
+ console.log(`[DTOS] Found ${payloadDocs.totalDtos} DTOs`);
2128
2217
 
2129
2218
  res.json({
2130
2219
  ok: true,
2131
2220
  ...payloadDocs
2132
2221
  });
2133
2222
  } catch (err) {
2134
- console.error(" [DTOS] Failed:", err.message);
2223
+ console.error("[DTOS] Failed:", err.message);
2135
2224
  res.status(500).json({ ok: false, error: err.message });
2136
2225
  }
2137
2226
  });
@@ -2142,19 +2231,19 @@ app.get("/workspace/config", async (req, res) => {
2142
2231
  if (!wsRoot) return res.status(400).json({ error: "workspace not set" });
2143
2232
 
2144
2233
  try {
2145
- console.log(" [CONFIG] Analyzing configuration...");
2234
+ console.log("[CONFIG] Analyzing configuration...");
2146
2235
 
2147
2236
  const configAnalyzer = new ConfigAnalyzer(wsRoot);
2148
2237
  const config = await configAnalyzer.analyze();
2149
2238
 
2150
- console.log(` [CONFIG] Server port: ${config.server.port}`);
2239
+ console.log(`[CONFIG] Server port: ${config.server.port}`);
2151
2240
 
2152
2241
  res.json({
2153
2242
  ok: true,
2154
2243
  ...config
2155
2244
  });
2156
2245
  } catch (err) {
2157
- console.error(" [CONFIG] Failed:", err.message);
2246
+ console.error("[CONFIG] Failed:", err.message);
2158
2247
  res.status(500).json({ ok: false, error: err.message });
2159
2248
  }
2160
2249
  });
@@ -2223,7 +2312,7 @@ app.post("/workspace/safe-patch", async (req, res) => {
2223
2312
  const { diff, incidentId } = req.body || {};
2224
2313
  if (!diff) return res.status(400).json({ error: "diff is required" });
2225
2314
 
2226
- console.log(` Safe patch requested for incident: ${incidentId || 'unknown'}`);
2315
+ console.log(`Safe patch requested for incident: ${incidentId || 'unknown'}`);
2227
2316
 
2228
2317
  try {
2229
2318
  // 1. Validate diff
@@ -2238,7 +2327,7 @@ app.post("/workspace/safe-patch", async (req, res) => {
2238
2327
 
2239
2328
  // 2. Extract target files
2240
2329
  const targetFiles = extractTargetFiles(diff);
2241
- console.log(` Target files: ${targetFiles.join(', ')}`);
2330
+ console.log(`Target files: ${targetFiles.join(', ')}`);
2242
2331
 
2243
2332
  // 3. Create backup
2244
2333
  const backupId = `backup-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
@@ -2269,23 +2358,23 @@ app.post("/workspace/safe-patch", async (req, res) => {
2269
2358
  }
2270
2359
  saveBackupIndex();
2271
2360
  } catch (e) {
2272
- console.warn(` Could not persist backup to disk: ${e.message}`);
2361
+ console.warn(`Could not persist backup to disk: ${e.message}`);
2273
2362
  }
2274
2363
 
2275
2364
  // Cleanup old backups if exceeded max
2276
2365
  if (BACKUPS.size > MAX_BACKUPS) {
2277
2366
  const oldest = Array.from(BACKUPS.keys())[0];
2278
2367
  BACKUPS.delete(oldest);
2279
- console.log(` Removed old backup: ${oldest}`);
2368
+ console.log(`Removed old backup: ${oldest}`);
2280
2369
  saveBackupIndex();
2281
2370
  }
2282
2371
 
2283
- console.log(` Backup created: ${backupId} (${backupFiles.length} files)`);
2372
+ console.log(`Backup created: ${backupId} (${backupFiles.length} files)`);
2284
2373
 
2285
2374
  // 4. Apply patch
2286
2375
  try {
2287
2376
  const result = await applyUnifiedDiff(wsRoot, diff);
2288
- console.log(` Patch applied successfully: ${result.target}`);
2377
+ console.log(`Patch applied successfully: ${result.target}`);
2289
2378
 
2290
2379
  res.json({
2291
2380
  ok: true,
@@ -2296,7 +2385,7 @@ app.post("/workspace/safe-patch", async (req, res) => {
2296
2385
  });
2297
2386
  } catch (patchError) {
2298
2387
  // 5. Rollback on failure
2299
- console.error(` Patch failed, rolling back: ${patchError.message}`);
2388
+ console.error(`Patch failed, rolling back: ${patchError.message}`);
2300
2389
 
2301
2390
  for (const file of backupFiles) {
2302
2391
  const fullPath = path.join(wsRoot, file.path);
@@ -2313,7 +2402,7 @@ app.post("/workspace/safe-patch", async (req, res) => {
2313
2402
  });
2314
2403
  }
2315
2404
  } catch (err) {
2316
- console.error(` Safe patch error: ${err.message}`);
2405
+ console.error(`Safe patch error: ${err.message}`);
2317
2406
  res.status(500).json({ ok: false, error: err.message });
2318
2407
  }
2319
2408
  });
@@ -2334,7 +2423,7 @@ app.post("/workspace/patch/dry-run", async (req, res) => {
2334
2423
  const { diff } = req.body || {};
2335
2424
  if (!diff) return res.status(400).json({ error: "diff is required" });
2336
2425
 
2337
- console.log(` Dry-run patch validation requested`);
2426
+ console.log(`Dry-run patch validation requested`);
2338
2427
 
2339
2428
  try {
2340
2429
  // 1. Validate diff format
@@ -2385,7 +2474,7 @@ app.post("/workspace/patch/dry-run", async (req, res) => {
2385
2474
  const allFilesExist = fileChecks.every(f => f.exists || diff.includes('--- /dev/null'));
2386
2475
  const missingFiles = fileChecks.filter(f => !f.exists && !diff.includes('--- /dev/null'));
2387
2476
 
2388
- console.log(` Dry-run complete: ${targetFiles.length} files, ${hunkCount} hunks`);
2477
+ console.log(`Dry-run complete: ${targetFiles.length} files, ${hunkCount} hunks`);
2389
2478
 
2390
2479
  res.json({
2391
2480
  ok: true,
@@ -2398,7 +2487,7 @@ app.post("/workspace/patch/dry-run", async (req, res) => {
2398
2487
  warnings: missingFiles.length > 0 ? [`${missingFiles.length} file(s) not found`] : []
2399
2488
  });
2400
2489
  } catch (err) {
2401
- console.error(` Dry-run error: ${err.message}`);
2490
+ console.error(`Dry-run error: ${err.message}`);
2402
2491
  res.status(500).json({ ok: false, error: err.message });
2403
2492
  }
2404
2493
  });
@@ -2466,7 +2555,7 @@ app.post("/workspace/backup", async (req, res) => {
2466
2555
  incidentId: incidentId || null
2467
2556
  });
2468
2557
 
2469
- console.log(` Manual backup created: ${backupId}`);
2558
+ console.log(`Manual backup created: ${backupId}`);
2470
2559
 
2471
2560
  res.json({
2472
2561
  ok: true,
@@ -2475,7 +2564,7 @@ app.post("/workspace/backup", async (req, res) => {
2475
2564
  timestamp: new Date().toISOString()
2476
2565
  });
2477
2566
  } catch (err) {
2478
- console.error(` Backup error: ${err.message}`);
2567
+ console.error(`Backup error: ${err.message}`);
2479
2568
  res.status(500).json({ ok: false, error: err.message });
2480
2569
  }
2481
2570
  });
@@ -2507,14 +2596,14 @@ app.post("/workspace/rollback", async (req, res) => {
2507
2596
  }
2508
2597
 
2509
2598
  try {
2510
- console.log(` Rolling back to backup: ${backupId}`);
2599
+ console.log(`Rolling back to backup: ${backupId}`);
2511
2600
 
2512
2601
  for (const file of backup.files) {
2513
2602
  const fullPath = path.join(wsRoot, file.path);
2514
2603
  await writeFile(fullPath, file.content, 'utf8');
2515
2604
  }
2516
2605
 
2517
- console.log(` Rollback completed: ${backup.files.length} files restored`);
2606
+ console.log(`Rollback completed: ${backup.files.length} files restored`);
2518
2607
 
2519
2608
  res.json({
2520
2609
  ok: true,
@@ -2523,7 +2612,7 @@ app.post("/workspace/rollback", async (req, res) => {
2523
2612
  timestamp: backup.timestamp
2524
2613
  });
2525
2614
  } catch (err) {
2526
- console.error(` Rollback error: ${err.message}`);
2615
+ console.error(`Rollback error: ${err.message}`);
2527
2616
  res.status(500).json({ ok: false, error: err.message });
2528
2617
  }
2529
2618
  });
@@ -2563,7 +2652,7 @@ app.delete("/workspace/backups/:backupId", (req, res) => {
2563
2652
  }
2564
2653
 
2565
2654
  BACKUPS.delete(backupId);
2566
- console.log(` Backup deleted: ${backupId}`);
2655
+ console.log(`Backup deleted: ${backupId}`);
2567
2656
 
2568
2657
  res.json({
2569
2658
  ok: true,
@@ -2622,7 +2711,7 @@ app.get("/workspace/diff/by-incident/:incidentId", async (req, res) => {
2622
2711
  }
2623
2712
 
2624
2713
  if (!matchedBackup) {
2625
- 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()));
2626
2715
  return res.status(404).json({
2627
2716
  ok: false,
2628
2717
  error: "No backup found for this incident",
@@ -2631,7 +2720,7 @@ app.get("/workspace/diff/by-incident/:incidentId", async (req, res) => {
2631
2720
  });
2632
2721
  }
2633
2722
 
2634
- console.log(` Found backup ${matchedBackupId} for incident ${incidentId}`);
2723
+ console.log(`Found backup ${matchedBackupId} for incident ${incidentId}`);
2635
2724
 
2636
2725
  // Reuse the diff logic
2637
2726
  try {
@@ -2668,7 +2757,7 @@ app.get("/workspace/diff/by-incident/:incidentId", async (req, res) => {
2668
2757
  files: diffs
2669
2758
  });
2670
2759
  } catch (err) {
2671
- console.error(` Diff error: ${err.message}`);
2760
+ console.error(`Diff error: ${err.message}`);
2672
2761
  res.status(500).json({ ok: false, error: err.message });
2673
2762
  }
2674
2763
  });
@@ -2740,7 +2829,7 @@ app.get("/workspace/diff/:backupId", async (req, res) => {
2740
2829
  }
2741
2830
  }
2742
2831
 
2743
- console.log(` Diff for ${backupId}: ${diffs.length} file(s) changed`);
2832
+ console.log(`Diff for ${backupId}: ${diffs.length} file(s) changed`);
2744
2833
 
2745
2834
  res.json({
2746
2835
  ok: true,
@@ -2752,7 +2841,7 @@ app.get("/workspace/diff/:backupId", async (req, res) => {
2752
2841
  files: diffs
2753
2842
  });
2754
2843
  } catch (err) {
2755
- console.error(` Diff error: ${err.message}`);
2844
+ console.error(`Diff error: ${err.message}`);
2756
2845
  res.status(500).json({ ok: false, error: err.message });
2757
2846
  }
2758
2847
  });
@@ -2785,7 +2874,7 @@ app.get("/workspace/detect-port", async (req, res) => {
2785
2874
 
2786
2875
  try {
2787
2876
  const fullPath = path.join(wsRoot, servicePath);
2788
- console.log(` Detecting port for service at: ${fullPath}`);
2877
+ console.log(`Detecting port for service at: ${fullPath}`);
2789
2878
 
2790
2879
  let port = null;
2791
2880
  let detectionMethod = null;
@@ -2820,7 +2909,7 @@ app.get("/workspace/detect-port", async (req, res) => {
2820
2909
  detectionMethod = 'global-detection';
2821
2910
  }
2822
2911
 
2823
- console.log(` Detected port: ${port || 'default'} via ${detectionMethod}`);
2912
+ console.log(`Detected port: ${port || 'default'} via ${detectionMethod}`);
2824
2913
 
2825
2914
  res.json({
2826
2915
  ok: true,
@@ -2831,7 +2920,7 @@ app.get("/workspace/detect-port", async (req, res) => {
2831
2920
  servicePath: servicePath || '/'
2832
2921
  });
2833
2922
  } catch (err) {
2834
- console.error(' Error detecting port:', err.message);
2923
+ console.error('Error detecting port:', err.message);
2835
2924
  res.status(500).json({ ok: false, error: err.message });
2836
2925
  }
2837
2926
  });
@@ -3042,7 +3131,7 @@ app.post("/workspace/test-local/prepare", async (req, res) => {
3042
3131
  if (!wsRoot) return res.status(400).json({ error: "workspace not set" });
3043
3132
 
3044
3133
  try {
3045
- console.log(" [TEST-LOCAL] Preparing test environment...");
3134
+ console.log("[TEST-LOCAL] Preparing test environment...");
3046
3135
  TEST_LOCAL_STATE.status = "compiling";
3047
3136
 
3048
3137
  // Step 1: Compile
@@ -3082,7 +3171,7 @@ app.post("/workspace/test-local/prepare", async (req, res) => {
3082
3171
  const config = await configAnalyzer.analyze();
3083
3172
  TEST_LOCAL_STATE.config = config;
3084
3173
 
3085
- console.log(` [TEST-LOCAL] Prepared: ${payloadDocs.endpoints.length} endpoints discovered`);
3174
+ console.log(`[TEST-LOCAL] Prepared: ${payloadDocs.endpoints.length} endpoints discovered`);
3086
3175
 
3087
3176
  res.json({
3088
3177
  ok: true,
@@ -3105,7 +3194,7 @@ app.post("/workspace/test-local/prepare", async (req, res) => {
3105
3194
  endpoints: payloadDocs.endpoints
3106
3195
  });
3107
3196
  } catch (err) {
3108
- console.error(" [TEST-LOCAL] Prepare failed:", err.message);
3197
+ console.error("[TEST-LOCAL] Prepare failed:", err.message);
3109
3198
  TEST_LOCAL_STATE.status = "error";
3110
3199
  res.status(500).json({ ok: false, error: err.message });
3111
3200
  }
@@ -3307,9 +3396,9 @@ app.post("/workspace/scan-files", async (req, res) => {
3307
3396
  });
3308
3397
  }
3309
3398
 
3310
- console.log(` [SCAN-FILES] Scanning: ${workspaceRoot}`);
3311
- console.log(` Extensions: ${includeExtensions.join(", ")}`);
3312
- console.log(` Exclude: ${excludePatterns.join(", ")}`);
3399
+ console.log(`[SCAN-FILES] Scanning: ${workspaceRoot}`);
3400
+ console.log(`Extensions: ${includeExtensions.join(", ")}`);
3401
+ console.log(`Exclude: ${excludePatterns.join(", ")}`);
3313
3402
 
3314
3403
  try {
3315
3404
  const files = [];
@@ -3359,13 +3448,13 @@ app.post("/workspace/scan-files", async (req, res) => {
3359
3448
  }
3360
3449
  }
3361
3450
  } catch (error) {
3362
- console.warn(` Cannot read directory ${dir}: ${error.message}`);
3451
+ console.warn(`Cannot read directory ${dir}: ${error.message}`);
3363
3452
  }
3364
3453
  }
3365
3454
 
3366
3455
  await scanDir(workspaceRoot);
3367
3456
 
3368
- console.log(` [SCAN-FILES] Found ${files.length} files`);
3457
+ console.log(`[SCAN-FILES] Found ${files.length} files`);
3369
3458
 
3370
3459
  res.json({
3371
3460
  success: true,
@@ -3375,7 +3464,7 @@ app.post("/workspace/scan-files", async (req, res) => {
3375
3464
  });
3376
3465
 
3377
3466
  } catch (error) {
3378
- console.error(` [SCAN-FILES] Error: ${error.message}`);
3467
+ console.error(`[SCAN-FILES] Error: ${error.message}`);
3379
3468
  res.status(500).json({
3380
3469
  success: false,
3381
3470
  error: error.message,
@@ -3404,7 +3493,7 @@ app.post("/workspace/read-file", async (req, res) => {
3404
3493
  });
3405
3494
  }
3406
3495
 
3407
- console.log(` [READ-FILE] Reading: ${filePath}`);
3496
+ console.log(`[READ-FILE] Reading: ${filePath}`);
3408
3497
 
3409
3498
  try {
3410
3499
  const fs = await import("fs/promises");
@@ -3435,7 +3524,7 @@ app.post("/workspace/read-file", async (req, res) => {
3435
3524
  });
3436
3525
 
3437
3526
  } catch (error) {
3438
- console.error(` [READ-FILE] Error: ${error.message}`);
3527
+ console.error(`[READ-FILE] Error: ${error.message}`);
3439
3528
  res.status(404).json({
3440
3529
  success: false,
3441
3530
  error: error.message,
@@ -3464,7 +3553,7 @@ app.post("/workspace/read-files", async (req, res) => {
3464
3553
  });
3465
3554
  }
3466
3555
 
3467
- console.log(` [READ-FILES] Reading ${filePaths.length} files`);
3556
+ console.log(`[READ-FILES] Reading ${filePaths.length} files`);
3468
3557
 
3469
3558
  try {
3470
3559
  const fs = await import("fs/promises");
@@ -3491,7 +3580,7 @@ app.post("/workspace/read-files", async (req, res) => {
3491
3580
  }
3492
3581
  }
3493
3582
 
3494
- 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`);
3495
3584
 
3496
3585
  res.json({
3497
3586
  success: true,
@@ -3501,7 +3590,7 @@ app.post("/workspace/read-files", async (req, res) => {
3501
3590
  });
3502
3591
 
3503
3592
  } catch (error) {
3504
- console.error(` [READ-FILES] Error: ${error.message}`);
3593
+ console.error(`[READ-FILES] Error: ${error.message}`);
3505
3594
  res.status(500).json({
3506
3595
  success: false,
3507
3596
  error: error.message
@@ -3519,7 +3608,7 @@ app.post("/workspace/read-files", async (req, res) => {
3519
3608
  * Abre o file picker nativo do sistema operacional
3520
3609
  */
3521
3610
  app.get("/system/folder-picker", async (req, res) => {
3522
- console.log(` [FOLDER-PICKER] Opening native folder picker...`);
3611
+ console.log(`[FOLDER-PICKER] Opening native folder picker...`);
3523
3612
 
3524
3613
  try {
3525
3614
  const platform = process.platform;
@@ -3602,7 +3691,7 @@ app.get("/system/folder-picker", async (req, res) => {
3602
3691
  selectedPath = selectedPath.slice(0, -1);
3603
3692
  }
3604
3693
 
3605
- console.log(` [FOLDER-PICKER] Selected: ${selectedPath}`);
3694
+ console.log(`[FOLDER-PICKER] Selected: ${selectedPath}`);
3606
3695
 
3607
3696
  res.json({
3608
3697
  success: true,
@@ -3611,7 +3700,7 @@ app.get("/system/folder-picker", async (req, res) => {
3611
3700
  });
3612
3701
 
3613
3702
  } catch (error) {
3614
- console.error(` [FOLDER-PICKER] Error:`, error.message);
3703
+ console.error(`[FOLDER-PICKER] Error:`, error.message);
3615
3704
  res.status(500).json({
3616
3705
  success: false,
3617
3706
  error: error.message,
@@ -3653,7 +3742,7 @@ app.get("/workspace/api-docs", async (req, res) => {
3653
3742
  });
3654
3743
  }
3655
3744
 
3656
- console.log(` [API-DOCS] Analyzing controllers in ${wsRoot}`);
3745
+ console.log(`[API-DOCS] Analyzing controllers in ${wsRoot}`);
3657
3746
 
3658
3747
  try {
3659
3748
  // Primeiro, escanear arquivos do workspace
@@ -3692,13 +3781,13 @@ app.get("/workspace/api-docs", async (req, res) => {
3692
3781
 
3693
3782
  await scanDir(wsRoot);
3694
3783
 
3695
- console.log(` [API-DOCS] Found ${files.length} Java files`);
3784
+ console.log(`[API-DOCS] Found ${files.length} Java files`);
3696
3785
 
3697
3786
  // Agora analisar os controllers
3698
3787
  const controllerAnalyzer = new ControllerAnalyzer(wsRoot);
3699
3788
  const apiDocs = await controllerAnalyzer.generateApiDocs(files);
3700
3789
 
3701
- 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`);
3702
3791
 
3703
3792
  res.json({
3704
3793
  success: true,
@@ -3710,7 +3799,7 @@ app.get("/workspace/api-docs", async (req, res) => {
3710
3799
  });
3711
3800
 
3712
3801
  } catch (error) {
3713
- console.error(` [API-DOCS] Error:`, error.message);
3802
+ console.error(`[API-DOCS] Error:`, error.message);
3714
3803
 
3715
3804
  res.json({
3716
3805
  success: false,
@@ -3737,7 +3826,7 @@ app.get("/workspace/api-docs/:controller", async (req, res) => {
3737
3826
  }
3738
3827
 
3739
3828
  const { controller } = req.params;
3740
- console.log(` [API-DOCS] Getting endpoints for controller: ${controller}`);
3829
+ console.log(`[API-DOCS] Getting endpoints for controller: ${controller}`);
3741
3830
 
3742
3831
  try {
3743
3832
  // Primeiro, escanear arquivos do workspace
@@ -3812,7 +3901,7 @@ app.get("/workspace/api-docs/:controller", async (req, res) => {
3812
3901
  });
3813
3902
 
3814
3903
  } catch (error) {
3815
- console.error(` [API-DOCS] Error:`, error.message);
3904
+ console.error(`[API-DOCS] Error:`, error.message);
3816
3905
  res.status(500).json({
3817
3906
  success: false,
3818
3907
  error: error.message
@@ -3902,7 +3991,7 @@ app.get("/workspace/smart-config", async (req, res) => {
3902
3991
  return res.status(400).json({ error: "workspace not set" });
3903
3992
  }
3904
3993
 
3905
- console.log(" [SMART-CONFIG] Collecting configuration files...");
3994
+ console.log("[SMART-CONFIG] Collecting configuration files...");
3906
3995
 
3907
3996
  try {
3908
3997
  const configPatterns = [
@@ -3936,9 +4025,9 @@ app.get("/workspace/smart-config", async (req, res) => {
3936
4025
  : content,
3937
4026
  size: content.length
3938
4027
  });
3939
- console.log(` Found: ${pattern}`);
4028
+ console.log(`Found: ${pattern}`);
3940
4029
  } catch (err) {
3941
- console.error(` Error reading ${pattern}: ${err.message}`);
4030
+ console.error(`Error reading ${pattern}: ${err.message}`);
3942
4031
  }
3943
4032
  }
3944
4033
  }
@@ -3954,7 +4043,7 @@ app.get("/workspace/smart-config", async (req, res) => {
3954
4043
  });
3955
4044
  }
3956
4045
 
3957
- console.log(` Collected ${collectedFiles.length} files, profiles: ${availableProfiles.join(', ')}`);
4046
+ console.log(`Collected ${collectedFiles.length} files, profiles: ${availableProfiles.join(', ')}`);
3958
4047
 
3959
4048
  res.json({
3960
4049
  ok: true,
@@ -3968,7 +4057,7 @@ app.get("/workspace/smart-config", async (req, res) => {
3968
4057
  });
3969
4058
 
3970
4059
  } catch (err) {
3971
- console.error(" [SMART-CONFIG] Error:", err.message);
4060
+ console.error("[SMART-CONFIG] Error:", err.message);
3972
4061
  res.status(500).json({ ok: false, error: err.message });
3973
4062
  }
3974
4063
  });
@@ -3979,7 +4068,7 @@ app.get("/workspace/smart-config", async (req, res) => {
3979
4068
  */
3980
4069
  app.post("/workspace/test-local/restart", async (req, res) => {
3981
4070
  try {
3982
- console.log(" [TEST-LOCAL] Restarting server...");
4071
+ console.log("[TEST-LOCAL] Restarting server...");
3983
4072
 
3984
4073
  // Stop
3985
4074
  await processManager.stop('test-local');
@@ -4024,7 +4113,7 @@ app.post("/workspace/test-local/restart", async (req, res) => {
4024
4113
  }
4025
4114
 
4026
4115
  } catch (err) {
4027
- console.error(" [TEST-LOCAL] Restart failed:", err.message);
4116
+ console.error("[TEST-LOCAL] Restart failed:", err.message);
4028
4117
  res.status(500).json({ ok: false, error: err.message });
4029
4118
  }
4030
4119
  });
@@ -4058,7 +4147,7 @@ app.post("/workspace/search", async (req, res) => {
4058
4147
  return res.status(400).json({ ok: false, error: "pattern is required" });
4059
4148
  }
4060
4149
 
4061
- console.log(` [workspace/search] pattern="${pattern}" filter="${fileFilter || '*'}"`);
4150
+ console.log(`[workspace/search] pattern="${pattern}" filter="${fileFilter || '*'}"`);
4062
4151
 
4063
4152
  try {
4064
4153
  const { execSync } = await import('child_process');
@@ -4116,7 +4205,7 @@ app.post("/workspace/search", async (req, res) => {
4116
4205
  .join('\n');
4117
4206
 
4118
4207
  const count = results.split('\n').filter(l => l.trim()).length;
4119
- console.log(` Found ${count} matches`);
4208
+ console.log(`Found ${count} matches`);
4120
4209
 
4121
4210
  res.json({
4122
4211
  ok: true,
@@ -4124,7 +4213,7 @@ app.post("/workspace/search", async (req, res) => {
4124
4213
  count: count
4125
4214
  });
4126
4215
  } catch (err) {
4127
- console.error(` [workspace/search] Error:`, err.message);
4216
+ console.error(`[workspace/search] Error:`, err.message);
4128
4217
  res.status(500).json({ ok: false, error: err.message });
4129
4218
  }
4130
4219
  });
@@ -4164,14 +4253,14 @@ app.post("/workspace/exec", async (req, res) => {
4164
4253
  ];
4165
4254
  const lowerCmd = command.toLowerCase().trim();
4166
4255
  if (dangerous.some(d => lowerCmd.includes(d))) {
4167
- console.warn(` [workspace/exec] BLOCKED dangerous command: ${command}`);
4256
+ console.warn(`[workspace/exec] BLOCKED dangerous command: ${command}`);
4168
4257
  return res.status(403).json({
4169
4258
  ok: false,
4170
4259
  error: "Command blocked for security reasons"
4171
4260
  });
4172
4261
  }
4173
4262
 
4174
- console.log(` [workspace/exec] Running: ${command.substring(0, 120)}...`);
4263
+ console.log(`[workspace/exec] Running: ${command.substring(0, 120)}...`);
4175
4264
 
4176
4265
  try {
4177
4266
  const { exec: execCb } = await import('child_process');
@@ -4185,7 +4274,7 @@ app.post("/workspace/exec", async (req, res) => {
4185
4274
  env: { ...process.env, FORCE_COLOR: '0' }
4186
4275
  });
4187
4276
 
4188
- console.log(` Command completed (stdout: ${result.stdout.length} chars)`);
4277
+ console.log(`Command completed (stdout: ${result.stdout.length} chars)`);
4189
4278
 
4190
4279
  res.json({
4191
4280
  ok: true,
@@ -4194,7 +4283,7 @@ app.post("/workspace/exec", async (req, res) => {
4194
4283
  exitCode: 0
4195
4284
  });
4196
4285
  } catch (err) {
4197
- 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));
4198
4287
  res.json({
4199
4288
  ok: false,
4200
4289
  stdout: err.stdout || '',
@@ -4227,7 +4316,7 @@ app.post("/workspace/test-endpoint", async (req, res) => {
4227
4316
  return res.status(403).json({ error: "Only localhost URLs allowed for security" });
4228
4317
  }
4229
4318
 
4230
- console.log(` Testing: ${method} ${url} (${testName || 'unnamed'})`);
4319
+ console.log(`Testing: ${method} ${url} (${testName || 'unnamed'})`);
4231
4320
 
4232
4321
  const startTime = Date.now();
4233
4322
 
@@ -4277,7 +4366,7 @@ app.post("/workspace/test-endpoint", async (req, res) => {
4277
4366
  : response.status >= 200 && response.status < 400
4278
4367
  };
4279
4368
 
4280
- console.log(` ${response.status} ${response.statusText} (${durationMs}ms) ${result.passed ? '' : ''}`);
4369
+ console.log(`${response.status} ${response.statusText} (${durationMs}ms) ${result.passed ? '' : ''}`);
4281
4370
  res.json(result);
4282
4371
 
4283
4372
  } catch (err) {
@@ -4353,7 +4442,7 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4353
4442
  try {
4354
4443
  const stashResult = execSync('git stash --include-untracked 2>&1', opts).trim();
4355
4444
  hadStash = !stashResult.includes('No local changes');
4356
- if (hadStash) console.log(' Stashed uncommitted changes');
4445
+ if (hadStash) console.log('Stashed uncommitted changes');
4357
4446
  } catch {}
4358
4447
 
4359
4448
  // 4. Create and checkout new branch (with unique name if exists)
@@ -4377,7 +4466,7 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4377
4466
  try {
4378
4467
  execSync('git stash pop', opts);
4379
4468
  } catch (e) {
4380
- console.warn(' Stash pop had conflicts, trying apply:', e.message);
4469
+ console.warn('Stash pop had conflicts, trying apply:', e.message);
4381
4470
  try { execSync('git stash apply', opts); } catch {}
4382
4471
  }
4383
4472
  }
@@ -4399,6 +4488,13 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4399
4488
  }
4400
4489
 
4401
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
+ }
4402
4498
  const safeMsg = commitMessage.replace(/"/g, '\\"').replace(/\n/g, '\\n');
4403
4499
  execSync(`git commit -m "${safeMsg}"`, opts);
4404
4500
 
@@ -4406,7 +4502,7 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4406
4502
  let pushResult = '';
4407
4503
  let pushed = false;
4408
4504
 
4409
- console.log(` Git push gitToken provided: ${!!gitToken}, repoUrl provided: ${!!repoUrl}`);
4505
+ console.log(`Git push gitToken provided: ${!!gitToken}, repoUrl provided: ${!!repoUrl}`);
4410
4506
 
4411
4507
  // If gitToken provided, set up authenticated remote URL for push
4412
4508
  if (gitToken) {
@@ -4418,11 +4514,11 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4418
4514
  // No remote configured use repoUrl from integration if available
4419
4515
  if (repoUrl) {
4420
4516
  remoteUrlRaw = repoUrl;
4421
- console.log(` No git remote, using repoUrl from integration: ${repoUrl}`);
4517
+ console.log(`No git remote, using repoUrl from integration: ${repoUrl}`);
4422
4518
  }
4423
4519
  }
4424
4520
 
4425
- console.log(` Remote URL: ${remoteUrlRaw.replace(gitToken, '***')}`);
4521
+ console.log(`Remote URL: ${remoteUrlRaw.replace(gitToken, '***')}`);
4426
4522
  let authenticatedUrl = '';
4427
4523
 
4428
4524
  if (remoteUrlRaw.includes('github.com')) {
@@ -4431,7 +4527,7 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4431
4527
  .replace(/^git@github\.com:/, '')
4432
4528
  .replace(/\.git$/, '');
4433
4529
  authenticatedUrl = `https://x-access-token:${gitToken}@github.com/${repoPath}.git`;
4434
- 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`);
4435
4531
  } else if (remoteUrlRaw.includes('gitlab.com') || remoteUrlRaw.includes('gitlab')) {
4436
4532
  const repoPath = remoteUrlRaw
4437
4533
  .replace(/^https?:\/\/(.*@)?[^\/]+\//, '')
@@ -4439,7 +4535,7 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4439
4535
  .replace(/\.git$/, '');
4440
4536
  const host = remoteUrlRaw.match(/https?:\/\/([^\/]+)/)?.[1] || 'gitlab.com';
4441
4537
  authenticatedUrl = `https://oauth2:${gitToken}@${host}/${repoPath}.git`;
4442
- console.log(` GitLab auth URL: https://oauth2:***@${host}/${repoPath}.git`);
4538
+ console.log(`GitLab auth URL: https://oauth2:***@${host}/${repoPath}.git`);
4443
4539
  } else if (remoteUrlRaw.includes('bitbucket.org') || remoteUrlRaw.includes('bitbucket')) {
4444
4540
  const repoPath = remoteUrlRaw
4445
4541
  .replace(/^https?:\/\/(.*@)?bitbucket\.org\//, '')
@@ -4453,11 +4549,11 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4453
4549
  const urlObj = new URL(remoteUrlRaw.replace(/^git@([^:]+):/, 'https://$1/'));
4454
4550
  authenticatedUrl = `https://oauth2:${gitToken}@${urlObj.host}${urlObj.pathname}`;
4455
4551
  if (!authenticatedUrl.endsWith('.git')) authenticatedUrl += '.git';
4456
- console.log(` Generic auth URL for ${urlObj.host}`);
4552
+ console.log(`Generic auth URL for ${urlObj.host}`);
4457
4553
  }
4458
4554
 
4459
4555
  if (authenticatedUrl) {
4460
- console.log(` Pushing ${finalBranchName} with token auth...`);
4556
+ console.log(`Pushing ${finalBranchName} with token auth...`);
4461
4557
  try {
4462
4558
  // Don't use 2>&1 let execSync capture stderr separately
4463
4559
  pushResult = execSync(`git push ${authenticatedUrl} ${finalBranchName}`, {
@@ -4466,20 +4562,20 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4466
4562
  stdio: ['pipe', 'pipe', 'pipe'] // capture stdin, stdout, stderr separately
4467
4563
  }).toString();
4468
4564
  pushed = true;
4469
- console.log(` Pushed with token authentication`);
4565
+ console.log(`Pushed with token authentication`);
4470
4566
  } catch (innerErr) {
4471
4567
  // Mask token in error messages before logging
4472
4568
  const maskToken = (str) => str ? str.replace(gitToken, '***TOKEN***') : '';
4473
4569
  const errMsg = maskToken(innerErr.stderr?.toString() || innerErr.stdout?.toString() || innerErr.message || '');
4474
- console.warn(` Authenticated push failed: ${errMsg}`);
4570
+ console.warn(`Authenticated push failed: ${errMsg}`);
4475
4571
  pushResult = errMsg;
4476
4572
  }
4477
4573
  } else {
4478
- console.warn(` Could not construct authenticated URL from: ${remoteUrlRaw}`);
4574
+ console.warn(`Could not construct authenticated URL from: ${remoteUrlRaw}`);
4479
4575
  }
4480
4576
  } catch (pushErr) {
4481
4577
  const maskToken = (str) => str ? str.replace(gitToken, '***TOKEN***') : '';
4482
- console.warn(` Git auth setup failed: ${maskToken(pushErr.message)}`);
4578
+ console.warn(`Git auth setup failed: ${maskToken(pushErr.message)}`);
4483
4579
  pushResult = maskToken(pushErr.message) || 'Push setup failed';
4484
4580
  }
4485
4581
  }
@@ -4494,7 +4590,7 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4494
4590
  pushResult = execSync(`git push origin ${finalBranchName} 2>&1`, opts).toString();
4495
4591
  pushed = true;
4496
4592
  } catch (pushErr2) {
4497
- console.warn(` Git push failed: ${pushErr2.message}`);
4593
+ console.warn(`Git push failed: ${pushErr2.message}`);
4498
4594
  pushResult = pushErr2.message || 'Push failed no remote configured or auth required';
4499
4595
  }
4500
4596
  }
@@ -4553,8 +4649,8 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4553
4649
  console.warn('Could not detect remote URL:', e.message);
4554
4650
  }
4555
4651
 
4556
- console.log(` Fix branch created: ${finalBranchName} (${commitSha.substring(0, 8)}) pushed=${pushed}`);
4557
- 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}`);
4558
4654
 
4559
4655
  // 10. Switch back to original branch and merge fix to keep changes on disk
4560
4656
  try {
@@ -4563,7 +4659,7 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4563
4659
  // This keeps the diff viewer working (disk has patched version)
4564
4660
  try {
4565
4661
  execSync(`git merge ${finalBranchName} --no-edit`, opts);
4566
- console.log(` Merged ${finalBranchName} into ${currentBranch}`);
4662
+ console.log(`Merged ${finalBranchName} into ${currentBranch}`);
4567
4663
  } catch (mergeErr) {
4568
4664
  // If merge fails (conflicts), just cherry-pick the changes without committing
4569
4665
  try {
@@ -4577,7 +4673,7 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4577
4673
  execSync(`git checkout ${finalBranchName} -- ${f}`, opts);
4578
4674
  } catch {}
4579
4675
  }
4580
- console.log(` Cherry-picked ${changedFiles.length} file(s) from ${finalBranchName}`);
4676
+ console.log(`Cherry-picked ${changedFiles.length} file(s) from ${finalBranchName}`);
4581
4677
  } catch {}
4582
4678
  }
4583
4679
  } catch {}
@@ -4624,14 +4720,14 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4624
4720
  if (response.ok) {
4625
4721
  const prData = await response.json();
4626
4722
  prUrl = prData.html_url;
4627
- console.log(` GitHub PR created: ${prUrl}`);
4723
+ console.log(`GitHub PR created: ${prUrl}`);
4628
4724
  } else {
4629
4725
  const errText = await response.text();
4630
- 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)}`);
4631
4727
  prUrl = mrUrl;
4632
4728
  }
4633
4729
  } catch (prErr) {
4634
- console.warn(` GitHub PR error: ${prErr.message}`);
4730
+ console.warn(`GitHub PR error: ${prErr.message}`);
4635
4731
  prUrl = mrUrl;
4636
4732
  }
4637
4733
 
@@ -4665,14 +4761,14 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4665
4761
  if (response.ok) {
4666
4762
  const mrData = await response.json();
4667
4763
  prUrl = mrData.web_url;
4668
- console.log(` GitLab MR created: ${prUrl}`);
4764
+ console.log(`GitLab MR created: ${prUrl}`);
4669
4765
  } else {
4670
4766
  const errText = await response.text();
4671
- 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)}`);
4672
4768
  prUrl = mrUrl;
4673
4769
  }
4674
4770
  } catch (glErr) {
4675
- console.warn(` GitLab MR error: ${glErr.message}`);
4771
+ console.warn(`GitLab MR error: ${glErr.message}`);
4676
4772
  prUrl = mrUrl;
4677
4773
  }
4678
4774
 
@@ -4725,14 +4821,14 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4725
4821
  if (response.ok) {
4726
4822
  const prData = await response.json();
4727
4823
  prUrl = prData.links && prData.links.html ? prData.links.html.href : mrUrl;
4728
- console.log(` Bitbucket PR created: ${prUrl}`);
4824
+ console.log(`Bitbucket PR created: ${prUrl}`);
4729
4825
  } else {
4730
4826
  const errText = await response.text();
4731
- 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)}`);
4732
4828
  prUrl = mrUrl;
4733
4829
  }
4734
4830
  } catch (bbErr) {
4735
- console.warn(` Bitbucket PR error: ${bbErr.message}`);
4831
+ console.warn(`Bitbucket PR error: ${bbErr.message}`);
4736
4832
  prUrl = mrUrl;
4737
4833
  }
4738
4834
  }
@@ -4755,7 +4851,7 @@ app.post("/workspace/git/create-fix-branch", async (req, res) => {
4755
4851
  });
4756
4852
 
4757
4853
  } catch (err) {
4758
- console.error(` Git branch creation failed: ${err.message}`);
4854
+ console.error(`Git branch creation failed: ${err.message}`);
4759
4855
  res.status(500).json({ ok: false, error: err.message });
4760
4856
  }
4761
4857
  });
@@ -4867,7 +4963,7 @@ app.get("/workspace/git/pr/comments", async (req, res) => {
4867
4963
  unresolvedCount: comments.filter(c => c.resolved === false || c.resolved === undefined).length
4868
4964
  });
4869
4965
  } catch (err) {
4870
- console.error(' Failed to fetch PR comments:', err.message);
4966
+ console.error('Failed to fetch PR comments:', err.message);
4871
4967
  res.status(500).json({ ok: false, error: err.message });
4872
4968
  }
4873
4969
  });
@@ -4904,7 +5000,7 @@ app.get("/workspace/git/pr/comments/:commentId", async (req, res) => {
4904
5000
 
4905
5001
  res.json({ ok: true, comment });
4906
5002
  } catch (err) {
4907
- console.error(' Failed to fetch PR comment:', err.message);
5003
+ console.error('Failed to fetch PR comment:', err.message);
4908
5004
  res.status(500).json({ ok: false, error: err.message });
4909
5005
  }
4910
5006
  });
@@ -4966,10 +5062,10 @@ app.post("/workspace/git/pr/comments", async (req, res) => {
4966
5062
  comment = await provider.instance.addPRComment(owner, repo, Number(prNumber), body);
4967
5063
  }
4968
5064
 
4969
- 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)}...`);
4970
5066
  res.json({ ok: true, comment });
4971
5067
  } catch (err) {
4972
- console.error(' Failed to add PR comment:', err.message);
5068
+ console.error('Failed to add PR comment:', err.message);
4973
5069
  res.status(500).json({ ok: false, error: err.message });
4974
5070
  }
4975
5071
  });
@@ -5004,10 +5100,10 @@ app.post("/workspace/git/pr/comments/:commentId/resolve", async (req, res) => {
5004
5100
  const { owner, repo } = provider.info;
5005
5101
  const result = await provider.instance.resolvePRComment(owner, repo, Number(prNumber), commentId);
5006
5102
 
5007
- console.log(` PR comment ${commentId} resolved on PR #${prNumber}`);
5103
+ console.log(`PR comment ${commentId} resolved on PR #${prNumber}`);
5008
5104
  res.json({ ok: true, commentId, ...result });
5009
5105
  } catch (err) {
5010
- console.error(' Failed to resolve PR comment:', err.message);
5106
+ console.error('Failed to resolve PR comment:', err.message);
5011
5107
  res.status(500).json({ ok: false, error: err.message });
5012
5108
  }
5013
5109
  });
@@ -5042,10 +5138,10 @@ app.post("/workspace/git/pr/comments/:commentId/unresolve", async (req, res) =>
5042
5138
  const { owner, repo } = provider.info;
5043
5139
  const result = await provider.instance.unresolvePRComment(owner, repo, Number(prNumber), commentId);
5044
5140
 
5045
- console.log(` PR comment ${commentId} unresolve on PR #${prNumber}`);
5141
+ console.log(`PR comment ${commentId} unresolve on PR #${prNumber}`);
5046
5142
  res.json({ ok: true, commentId, ...result });
5047
5143
  } catch (err) {
5048
- console.error(' Failed to unresolve PR comment:', err.message);
5144
+ console.error('Failed to unresolve PR comment:', err.message);
5049
5145
  res.status(500).json({ ok: false, error: err.message });
5050
5146
  }
5051
5147
  });
@@ -5090,9 +5186,9 @@ app.post("/workspace/git/pr/comments/:commentId/fix-and-resolve", async (req, re
5090
5186
  return res.status(404).json({ error: "Comment not found" });
5091
5187
  }
5092
5188
 
5093
- console.log(` AI Fix & Resolve: PR #${prNumber}, comment ${commentId}`);
5094
- console.log(` File: ${comment.path || '(general)'}, Line: ${comment.line || 'N/A'}`);
5095
- 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)}...`);
5096
5192
 
5097
5193
  // 2. Return the comment info for the Gateway to orchestrate the AI fix
5098
5194
  // The actual AI analysis + patch is handled by the Gateway's AI service,
@@ -5122,7 +5218,7 @@ app.post("/workspace/git/pr/comments/:commentId/fix-and-resolve", async (req, re
5122
5218
  message: 'Comment fetched. Gateway should now: 1) Read file, 2) AI analyze, 3) Apply patch, 4) Commit, 5) Reply, 6) Resolve'
5123
5219
  });
5124
5220
  } catch (err) {
5125
- console.error(' Failed to prepare fix-and-resolve:', err.message);
5221
+ console.error('Failed to prepare fix-and-resolve:', err.message);
5126
5222
  res.status(500).json({ ok: false, error: err.message });
5127
5223
  }
5128
5224
  });
@@ -5145,7 +5241,7 @@ async function _getGitProvider() {
5145
5241
  try {
5146
5242
  remoteUrl = execSync('git remote get-url origin', opts).trim();
5147
5243
  } catch {
5148
- console.warn(' No git remote found');
5244
+ console.warn('No git remote found');
5149
5245
  return null;
5150
5246
  }
5151
5247
 
@@ -5155,7 +5251,7 @@ async function _getGitProvider() {
5155
5251
  const providerId = registry.detectProviderFromUrl(remoteUrl);
5156
5252
 
5157
5253
  if (!providerId) {
5158
- console.warn(` Unknown git provider for URL: ${remoteUrl}`);
5254
+ console.warn(`Unknown git provider for URL: ${remoteUrl}`);
5159
5255
  return null;
5160
5256
  }
5161
5257
 
@@ -5170,7 +5266,7 @@ async function _getGitProvider() {
5170
5266
  }
5171
5267
 
5172
5268
  if (!token) {
5173
- 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.`);
5174
5270
  return null;
5175
5271
  }
5176
5272
 
@@ -5190,7 +5286,7 @@ async function _getGitProvider() {
5190
5286
 
5191
5287
  return { instance, info, providerId, remoteUrl };
5192
5288
  } catch (err) {
5193
- console.error(' Failed to initialize git provider:', err.message);
5289
+ console.error('Failed to initialize git provider:', err.message);
5194
5290
  return null;
5195
5291
  }
5196
5292
  }
@@ -5280,7 +5376,7 @@ app.post("/workspace/:workspaceId/run", async (req, res) => {
5280
5376
  // ============================================
5281
5377
  async function startWebSocketTunnel(port, gatewayUrl, apiKey, tenantId) {
5282
5378
  if (!gatewayUrl || !apiKey || !tenantId) {
5283
- 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');
5284
5380
  return;
5285
5381
  }
5286
5382
 
@@ -5298,7 +5394,7 @@ async function startWebSocketTunnel(port, gatewayUrl, apiKey, tenantId) {
5298
5394
  ws = new WebSocket(fullUrl);
5299
5395
 
5300
5396
  ws.on('open', () => {
5301
- console.log(` WebSocket tunnel connected to Gateway`);
5397
+ console.log(`WebSocket tunnel connected to Gateway`);
5302
5398
  reconnectDelay = 2000;
5303
5399
  ws.send(JSON.stringify({ type: 'register', tenantId, port, workspacePath: WORKSPACE_ROOT || null }));
5304
5400
  const hb = setInterval(() => {
@@ -5314,7 +5410,7 @@ async function startWebSocketTunnel(port, gatewayUrl, apiKey, tenantId) {
5314
5410
  try { request = JSON.parse(text); } catch { return; }
5315
5411
  const { requestId, command, params } = request;
5316
5412
  if (!requestId || !command) return;
5317
- console.log(` WS command: ${command}`);
5413
+ console.log(`WS command: ${command}`);
5318
5414
  let result;
5319
5415
  try { result = await handleWsCommand(command, params || {}); }
5320
5416
  catch (err) { result = { error: err.message }; }
@@ -5323,19 +5419,19 @@ async function startWebSocketTunnel(port, gatewayUrl, apiKey, tenantId) {
5323
5419
 
5324
5420
  ws.on('close', () => {
5325
5421
  if (!isShuttingDown) {
5326
- console.log(` WS disconnected. Reconnecting in ${reconnectDelay/1000}s...`);
5422
+ console.log(`WS disconnected. Reconnecting in ${reconnectDelay/1000}s...`);
5327
5423
  setTimeout(connect, reconnectDelay);
5328
5424
  reconnectDelay = Math.min(reconnectDelay * 2, 30000);
5329
5425
  }
5330
5426
  });
5331
5427
 
5332
- ws.on('error', (err) => console.warn(` WS error: ${err.message}`));
5428
+ ws.on('error', (err) => console.warn(`WS error: ${err.message}`));
5333
5429
 
5334
5430
  } catch (err) {
5335
5431
  if (err.code === 'ERR_MODULE_NOT_FOUND') {
5336
- console.warn(' WebSocket tunnel requires "ws" package. Run: npm install ws');
5432
+ console.warn('WebSocket tunnel requires "ws" package. Run: npm install ws');
5337
5433
  } else {
5338
- console.warn(` WS tunnel error: ${err.message}`);
5434
+ console.warn(`WS tunnel error: ${err.message}`);
5339
5435
  setTimeout(connect, reconnectDelay);
5340
5436
  reconnectDelay = Math.min(reconnectDelay * 2, 30000);
5341
5437
  }
@@ -5406,7 +5502,7 @@ async function startWebSocketTunnel(port, gatewayUrl, apiKey, tenantId) {
5406
5502
  return { error: 'backupId or incidentId is required' };
5407
5503
  }
5408
5504
 
5409
- console.log(` WS workspace.diff ${endpoint}`);
5505
+ console.log(`WS workspace.diff ${endpoint}`);
5410
5506
  const res = await fetch(`${localBase}${endpoint}`, {
5411
5507
  method: 'GET',
5412
5508
  headers: { 'Content-Type': 'application/json' }
@@ -5540,7 +5636,7 @@ async function startWebSocketTunnel(port, gatewayUrl, apiKey, tenantId) {
5540
5636
  }
5541
5637
 
5542
5638
  // ============================================
5543
- // 🤖 SETUP AGENT ROUTES
5639
+ // SETUP AGENT ROUTES
5544
5640
  // Supports the AI Assistant chat commands
5545
5641
  // ============================================
5546
5642
 
@@ -5557,7 +5653,7 @@ app.post("/setup/run-command", async (req, res) => {
5557
5653
  return res.status(403).json({ ok: false, error: "Command blocked for safety" });
5558
5654
  }
5559
5655
 
5560
- console.log(`🤖 [SetupAgent] Running: ${command.substring(0, 100)}`);
5656
+ console.log(`[SetupAgent] Running: ${command.substring(0, 100)}`);
5561
5657
  const { exec: execCb } = await import('child_process');
5562
5658
  const { promisify } = await import('util');
5563
5659
  const execAsync = promisify(execCb);
@@ -5655,10 +5751,10 @@ app.post("/setup/run-auth-command", async (req, res) => {
5655
5751
 
5656
5752
  const { exec: execCb } = await import('child_process');
5657
5753
  const bgCmd = process.platform === 'win32' ? `start cmd /c "${command}"` : `${command} &`;
5658
- console.log(`🔐 [SetupAgent] Starting auth: ${command.substring(0, 80)}`);
5754
+ console.log(`[SetupAgent] Starting auth: ${command.substring(0, 80)}`);
5659
5755
 
5660
5756
  execCb(bgCmd, { shell: true }, (err) => {
5661
- if (err) console.warn(`⚠️ Auth command warning: ${err.message}`);
5757
+ if (err) console.warn(`Auth command warning: ${err.message}`);
5662
5758
  });
5663
5759
 
5664
5760
  res.json({ ok: true, status: "started", session_id, message: "Auth command started, browser should open" });
@@ -5702,13 +5798,13 @@ app.get("/setup/auth-status", async (req, res) => {
5702
5798
  // ============================================
5703
5799
  app.listen(PORT, '0.0.0.0', async () => {
5704
5800
  console.log(`\n DeepDebug Local Agent listening on port ${PORT}`);
5705
- console.log(` Environment: ${process.env.NODE_ENV || 'development'}`);
5706
- console.log(` Process Manager initialized`);
5707
- console.log(` Backup system ready (max: ${MAX_BACKUPS} backups)`);
5708
- 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'}`);
5709
5805
  if (aiEngine) {
5710
- console.log(` Gateway URL: ${aiEngine.gatewayUrl}`);
5711
- console.log(` Max Retries: ${aiEngine.maxRetries}`);
5806
+ console.log(`Gateway URL: ${aiEngine.gatewayUrl}`);
5807
+ console.log(`Max Retries: ${aiEngine.maxRetries}`);
5712
5808
  }
5713
5809
  console.log(`\n Ready to receive requests!\n`);
5714
5810
 
@@ -5720,7 +5816,7 @@ app.listen(PORT, '0.0.0.0', async () => {
5720
5816
 
5721
5817
  const gwUrl = cfg.gatewayUrl || process.env.GATEWAY_URL;
5722
5818
  const apiKey = cfg.apiKey || process.env.DEEPDEBUG_API_KEY;
5723
- let tenantId = cfg.tenantId;
5819
+ let tenantId = cfg.tenantId || process.env.TENANT_ID;
5724
5820
  if (!tenantId && apiKey) {
5725
5821
  try {
5726
5822
  const payload = JSON.parse(Buffer.from(apiKey.split('.')[1], 'base64').toString());
@@ -5737,8 +5833,8 @@ app.listen(PORT, '0.0.0.0', async () => {
5737
5833
  try {
5738
5834
  startMCPHttpServer(wsManager, parseInt(MCP_PORT));
5739
5835
  } catch (err) {
5740
- console.warn(` MCP HTTP Server failed to start: ${err.message}`);
5741
- 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)`);
5742
5838
  }
5743
5839
 
5744
5840
  // Auto-register default workspace in WorkspaceManager