deepdebug-local-agent 1.0.22 → 1.1.0

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 (188) hide show
  1. package/.claude/context.md +76 -0
  2. package/.claude/skills/README.md +25 -0
  3. package/.claude/skills/tdd-debugging/SKILL.md +53 -0
  4. package/.claude/skills/tdd-debugging/references/anti-patterns.md +43 -0
  5. package/.claude/skills/tdd-debugging/references/command-reference.md +46 -0
  6. package/.claude/standards/README.md +51 -0
  7. package/.claude/standards/clean-code.md +75 -0
  8. package/.claude/standards/code-review-checklist.md +61 -0
  9. package/.claude/standards/layered-architecture.md +163 -0
  10. package/.claude/standards/node.md +45 -0
  11. package/.claude/standards/security-owasp.md +114 -0
  12. package/.claude/standards/simplicity.md +42 -0
  13. package/.claude/standards/solid.md +64 -0
  14. package/.claude/standards/testing.md +59 -0
  15. package/.cursor/rules/standards.mdc +17 -0
  16. package/.github/workflows/build-byoc-image.yml +315 -0
  17. package/.github/workflows/deploy-gcp.yml +102 -0
  18. package/.github/workflows/npm-publish.yml +69 -8
  19. package/AGENTS.md +21 -0
  20. package/CHANGELOG.md +69 -0
  21. package/CLAUDE.md +13 -0
  22. package/CLAUDE_CODE_AGENT_INFINITE.md +5 -3
  23. package/Dockerfile +4 -0
  24. package/Dockerfile.full +55 -3
  25. package/README.md +81 -0
  26. package/bin/install.js +16 -5
  27. package/cloudbuild-full.yaml +57 -0
  28. package/docker-compose.yml +5 -3
  29. package/docs/OBSERVABILITY.md +164 -0
  30. package/docs/byoc-agent-image.md +70 -0
  31. package/docs/graphify-packaging-plan.md +133 -0
  32. package/docs/graphify-validation-run-2026-10-28.md +243 -0
  33. package/docs/legacy-connectors.md +268 -0
  34. package/docs/releasing.md +43 -0
  35. package/docs/signed-commands.md +163 -0
  36. package/env.example +30 -0
  37. package/helm/Chart.yaml +2 -2
  38. package/helm/templates/deployment.yaml +13 -3
  39. package/helm/templates/networkpolicy.yaml +22 -0
  40. package/helm/templates/secret.yaml +1 -0
  41. package/helm/values.yaml +13 -14
  42. package/mcp-server.js +4 -1
  43. package/package.json +12 -4
  44. package/scripts/sync-fixtures.mjs +246 -0
  45. package/scripts/upgrade-observability-push.sh +227 -0
  46. package/src/adapters/as400/as400-parser.js +12 -0
  47. package/src/adapters/as400/index.js +134 -0
  48. package/src/adapters/cobol/cobol-parser.js +37 -0
  49. package/src/adapters/cobol/index.js +151 -0
  50. package/src/adapters/ibmmq/ibmmq-parser.js +23 -0
  51. package/src/adapters/ibmmq/index.js +137 -0
  52. package/src/adapters/index.js +79 -0
  53. package/src/adapters/oracle-forms/index.js +145 -0
  54. package/src/adapters/oracle-forms/oracle-forms-parser.js +11 -0
  55. package/src/adapters/sap/index.js +146 -0
  56. package/src/adapters/sap/sap-parser.js +41 -0
  57. package/src/ai-engine.js +22 -22
  58. package/src/config/trusted-signing-keys.json +3 -0
  59. package/src/detectors/build-tool-detector.js +50 -0
  60. package/src/detectors/multi-project-detector.js +22 -22
  61. package/src/detectors/service-detector.js +24 -24
  62. package/src/exec-utils.js +26 -4
  63. package/src/git/base-git-provider.js +117 -117
  64. package/src/git/bitbucket-provider.js +2 -2
  65. package/src/git/git-provider-registry.js +18 -18
  66. package/src/git/github-provider.js +13 -13
  67. package/src/git/multi-repo-pr.js +161 -0
  68. package/src/mcp-http-server.js +32 -16
  69. package/src/observability/bundle-files.js +418 -0
  70. package/src/observability/detect.js +151 -0
  71. package/src/observability/provision.js +212 -0
  72. package/src/observability/render-cli.js +59 -0
  73. package/src/observability/routes.js +88 -0
  74. package/src/patch/patch-engine.js +28 -28
  75. package/src/patch-manager.js +85 -85
  76. package/src/patch_bkp.js +14 -14
  77. package/src/ports.js +4 -4
  78. package/src/routes/workspace.route.js +47 -16
  79. package/src/runtimes/base-runtime.js +75 -75
  80. package/src/runtimes/java/gradle-runtime.js +17 -17
  81. package/src/runtimes/java/java-integrations.js +25 -25
  82. package/src/runtimes/java/maven-runtime.js +34 -34
  83. package/src/runtimes/node/node-integrations.js +1 -1
  84. package/src/runtimes/node/npm-runtime.js +14 -14
  85. package/src/runtimes/node/yarn-runtime.js +4 -4
  86. package/src/runtimes/runtime-registry.js +25 -25
  87. package/src/server-local.js +4 -4
  88. package/src/server.js +1412 -335
  89. package/src/siblings/burst-suppressor.js +89 -0
  90. package/src/siblings/capabilities.js +273 -0
  91. package/src/siblings/env-compat.cjs +58 -0
  92. package/src/siblings/incident-forwarder.js +320 -0
  93. package/src/siblings/logger.js +15 -0
  94. package/src/siblings/metrics.js +94 -0
  95. package/src/utils/agent-auth.js +184 -0
  96. package/src/utils/approval-token.js +56 -0
  97. package/src/utils/bind-host.js +29 -0
  98. package/src/utils/branch-refspec.js +98 -0
  99. package/src/utils/child-env.js +34 -0
  100. package/src/utils/environment-diagnostics.js +55 -55
  101. package/src/utils/exec-policy.js +962 -0
  102. package/src/utils/exec-utils.js +15 -15
  103. package/src/utils/file-count.js +46 -0
  104. package/src/utils/fs-utils.js +10 -10
  105. package/src/utils/multi-repo-open.js +132 -0
  106. package/src/utils/open-gate.js +183 -0
  107. package/src/utils/ranged-read.js +65 -0
  108. package/src/utils/request-guards.js +77 -0
  109. package/src/utils/request-signing.js +342 -0
  110. package/src/utils/root-recovery.js +244 -0
  111. package/src/utils/safe-exec-args.js +58 -0
  112. package/src/utils/sandbox.js +182 -0
  113. package/src/utils/search-outcome.js +56 -0
  114. package/src/utils/workspace-root.js +80 -0
  115. package/src/validators/syntax-validator.js +149 -0
  116. package/src/workspace/detect-port.js +16 -16
  117. package/src/workspace/file-reader.js +1 -1
  118. package/src/workspace/process-manager.js +46 -46
  119. package/src/workspace-manager.js +86 -24
  120. package/test/adapters/as400/as400.test.js +121 -0
  121. package/test/adapters/cobol/cobol.test.js +217 -0
  122. package/test/adapters/ibmmq/ibmmq.test.js +122 -0
  123. package/test/adapters/oracle-forms/oracle-forms.test.js +180 -0
  124. package/test/adapters/registry.test.js +108 -0
  125. package/test/adapters/sap/sap.test.js +142 -0
  126. package/test/agent-auth.test.js +194 -0
  127. package/test/bind-host.test.js +26 -0
  128. package/test/branch-refspec.test.js +224 -0
  129. package/test/burst-suppressor.test.js +60 -0
  130. package/test/capabilities-access.test.js +47 -0
  131. package/test/capabilities.test.js +87 -0
  132. package/test/child-env.test.js +23 -0
  133. package/test/env-compat.test.js +71 -0
  134. package/test/exec-policy.test.js +463 -0
  135. package/test/file-count.test.js +64 -0
  136. package/test/incident-forwarder.test.js +231 -0
  137. package/test/multi-repo-open.test.js +180 -0
  138. package/test/multi-repo-pr.test.js +129 -0
  139. package/test/observability-detect.test.js +199 -0
  140. package/test/open-gate.test.js +341 -0
  141. package/test/ranged-read.test.js +60 -0
  142. package/test/request-guards.test.js +91 -0
  143. package/test/request-signing.test.js +284 -0
  144. package/test/root-recovery-sidecar.test.js +171 -0
  145. package/test/root-recovery.test.js +274 -0
  146. package/test/safe-exec-args.test.js +58 -0
  147. package/test/sandbox.test.js +98 -0
  148. package/test/search-outcome.test.js +50 -0
  149. package/test/workspace-root.test.js +64 -0
  150. package/tools/graphify-validation/README.md +92 -0
  151. package/tools/graphify-validation/config/questions.json +31 -0
  152. package/tools/graphify-validation/config/repos.json +9 -0
  153. package/tools/graphify-validation/config/symbols.json +6 -0
  154. package/tools/graphify-validation/fixtures/spring/expected.json +34 -0
  155. package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/AppConfig.java +29 -0
  156. package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/AuditLogger.java +15 -0
  157. package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/Cache.java +7 -0
  158. package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/CheckoutService.java +25 -0
  159. package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/InMemoryCache.java +18 -0
  160. package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/OrderController.java +22 -0
  161. package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/PaymentGateway.java +5 -0
  162. package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/PaypalGateway.java +11 -0
  163. package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/RefundService.java +14 -0
  164. package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/StripeGateway.java +11 -0
  165. package/tools/graphify-validation/lib/affected_vs_rg.py +81 -0
  166. package/tools/graphify-validation/lib/audit_hook/sitecustomize.py +22 -0
  167. package/tools/graphify-validation/lib/graph_metrics.py +96 -0
  168. package/tools/graphify-validation/lib/gv_common.py +130 -0
  169. package/tools/graphify-validation/lib/licenses.py +47 -0
  170. package/tools/graphify-validation/lib/pip_audit_summary.py +18 -0
  171. package/tools/graphify-validation/lib/recall.py +115 -0
  172. package/tools/graphify-validation/lib/report.py +226 -0
  173. package/tools/graphify-validation/lib/run_all.py +237 -0
  174. package/tools/graphify-validation/lib/run_graphify.py +144 -0
  175. package/tools/graphify-validation/lib/rusage_helper.py +17 -0
  176. package/tools/graphify-validation/lib/sample_edges.py +246 -0
  177. package/tools/graphify-validation/lib/spring_fixture.py +81 -0
  178. package/tools/graphify-validation/requirements-py311.lock +508 -0
  179. package/tools/graphify-validation/requirements-tools.in +1 -0
  180. package/tools/graphify-validation/requirements-tools.lock +371 -0
  181. package/tools/graphify-validation/requirements.in +1 -0
  182. package/tools/graphify-validation/requirements.lock +502 -0
  183. package/tools/graphify-validation/run.sh +43 -0
  184. package/tools/graphify-validation/tests/test_harness.py +151 -0
  185. package/cloudbuild-agent-qa.yaml +0 -43
  186. package/cloudbuild-agent-staging.yaml +0 -40
  187. package/cloudbuild.yaml.deprecated +0 -42
  188. package/src/local-agent-source.tar.gz +0 -0
package/src/ports.js CHANGED
@@ -18,10 +18,10 @@ export async function detectPort(root) {
18
18
  const content = await readFile(full, "utf8");
19
19
  const doc = yaml.load(content);
20
20
 
21
- // Tentar pegar do objeto parseado
21
+ // Try to read it from the parsed object
22
22
  let port = doc?.server?.port ?? doc?.SERVER?.PORT;
23
23
 
24
- // Se for string com ${PORT:8090}, extrair o valor padrão
24
+ // If it is a string like ${PORT:8090}, extract the default value
25
25
  if (typeof port === 'string') {
26
26
  const match = port.match(/\$\{PORT:(\d+)\}/);
27
27
  if (match) port = match[1];
@@ -43,7 +43,7 @@ export async function detectPort(root) {
43
43
  const props = PropertiesReader(full);
44
44
  let port = props.get("server.port");
45
45
 
46
- // Se for string com ${PORT:8090}, extrair o valor padrão
46
+ // If it is a string like ${PORT:8090}, extract the default value
47
47
  if (typeof port === 'string') {
48
48
  const match = port.match(/\$\{PORT:(\d+)\}/);
49
49
  if (match) port = match[1];
@@ -54,7 +54,7 @@ export async function detectPort(root) {
54
54
  }
55
55
  }
56
56
 
57
- // Node (com .env padrão)
57
+ // Node (with default .env)
58
58
  const envCandidates = [".env", "src/.env"];
59
59
  for (const rel of envCandidates) {
60
60
  const full = path.join(root, rel);
@@ -5,7 +5,7 @@ import os from "os";
5
5
 
6
6
  const router = express.Router();
7
7
 
8
- // 🔹 Caminho global do workspace (inicializado com fallback padrão)
8
+ // 🔹 Global workspace path (initialized with a default fallback)
9
9
  // ✅ FIX: Read WORKSPACE_ROOT (set by install.js Docker) OR WORKSPACE_BASE (legacy)
10
10
  let workspacePath =
11
11
  process.env.WORKSPACE_ROOT ||
@@ -89,7 +89,7 @@ function translateToDockerPath(hostPath) {
89
89
 
90
90
  // --------------------------------------------------
91
91
  // 🧩 1️⃣ GET /workspace/info
92
- // Retorna informações sobre o workspace atual
92
+ // Returns information about the current workspace
93
93
  // --------------------------------------------------
94
94
  router.get("/info", async (req, res) => {
95
95
  try {
@@ -199,11 +199,22 @@ async function ensureRepoCloned(repoUrl, token, branch = 'main') {
199
199
  // Fresh clone
200
200
  console.log(`📂 [git] Cloning ${repoUrl} (branch: ${branch})...`);
201
201
 
202
- const result = execAsync(
202
+ let result = execAsync(
203
203
  `git clone --branch ${branch} --single-branch --depth 50 "${authUrl}" "${clonePath}"`,
204
204
  { timeout: 180000 } // 3 minutes for large repos
205
205
  );
206
206
 
207
+ if (result.exitCode !== 0 && /could not find remote branch/i.test(result.stderr || '')) {
208
+ // Requested branch may not exist (repo uses master, caller assumed main):
209
+ // fall back to the repo's default branch instead of failing the session.
210
+ console.warn(`⚠️ [git] Branch '${branch}' not found — falling back to the repo default branch`);
211
+ execAsync(`rm -rf "${clonePath}"`);
212
+ result = execAsync(
213
+ `git clone --single-branch --depth 50 "${authUrl}" "${clonePath}"`,
214
+ { timeout: 180000 }
215
+ );
216
+ }
217
+
207
218
  if (result.exitCode !== 0) {
208
219
  throw new Error(`Git clone failed: ${result.stderr}`);
209
220
  }
@@ -225,6 +236,18 @@ async function ensureRepoCloned(repoUrl, token, branch = 'main') {
225
236
 
226
237
  router.post("/open", async (req, res) => {
227
238
  try {
239
+ // ==========================================
240
+ // Input validation and sanitization
241
+ // ==========================================
242
+ if (!req.body || typeof req.body !== 'object') {
243
+ console.error(`❌ [/workspace/open] Invalid request body:`, req.body);
244
+ return res.status(400).json({
245
+ ok: false,
246
+ error: "Invalid request body - expected JSON object"
247
+ });
248
+ }
249
+
250
+ // Now safe to destructure
228
251
  const { root, workspacePath: wpPath, repoUrl, token, branch = 'main' } = req.body;
229
252
 
230
253
  // ==========================================
@@ -272,7 +295,10 @@ router.post("/open", async (req, res) => {
272
295
  const requestedPath = root || wpPath;
273
296
 
274
297
  if (!requestedPath) {
275
- return res.status(400).json({ error: "Missing 'root', 'workspacePath', or 'repoUrl' in body" });
298
+ return res.status(400).json({
299
+ ok: false,
300
+ error: "Missing 'root', 'workspacePath', or 'repoUrl' in body"
301
+ });
276
302
  }
277
303
 
278
304
  // Translate host path to docker path if needed
@@ -301,6 +327,7 @@ router.post("/open", async (req, res) => {
301
327
 
302
328
  console.error(`❌ [/workspace/open] Directory not found: ${resolvedPath}`);
303
329
  return res.status(400).json({
330
+ ok: false,
304
331
  error: `Directory not found: ${resolvedPath}`,
305
332
  requestedPath, resolvedPath,
306
333
  availableProjects: availableDirs,
@@ -329,14 +356,18 @@ router.post("/open", async (req, res) => {
329
356
  port: null
330
357
  });
331
358
  } catch (err) {
332
- console.error("❌ [/workspace/open] Error:", err);
333
- return res.status(500).json({ error: err.message });
359
+ console.error("❌ [/workspace/open] Unexpected error:", err);
360
+ return res.status(500).json({
361
+ ok: false,
362
+ error: err.message || "Internal server error",
363
+ stack: process.env.NODE_ENV === 'development' ? err.stack : undefined
364
+ });
334
365
  }
335
366
  });
336
367
 
337
368
  // --------------------------------------------------
338
369
  // 🧩 2️⃣ POST /workspace
339
- // Atualiza o diretório de workspace selecionado pelo usuário
370
+ // Updates the workspace directory selected by the user
340
371
  // (legacy endpoint - kept for backward compatibility)
341
372
  // --------------------------------------------------
342
373
  router.post("/", async (req, res) => {
@@ -370,7 +401,7 @@ router.post("/", async (req, res) => {
370
401
 
371
402
  // --------------------------------------------------
372
403
  // 🧩 3️⃣ GET /workspace/files
373
- // Lista arquivos .java (até 3 níveis de profundidade)
404
+ // Lists .java files (up to 3 levels deep)
374
405
  // --------------------------------------------------
375
406
  router.get("/files", async (req, res) => {
376
407
  try {
@@ -421,7 +452,7 @@ router.get("/files", async (req, res) => {
421
452
 
422
453
  // --------------------------------------------------
423
454
  // 🧩 4️⃣ GET /workspace/file
424
- // Lê o conteúdo de um arquivo específico dentro do workspace
455
+ // Reads the content of a specific file inside the workspace
425
456
  // --------------------------------------------------
426
457
  router.get("/file", async (req, res) => {
427
458
  try {
@@ -431,7 +462,7 @@ router.get("/file", async (req, res) => {
431
462
  return res.status(400).json({ error: "Missing 'path' query parameter" });
432
463
  }
433
464
 
434
- // 🔹 Corrige o caminho caso venha relativo (ex: "src/...") ou com prefixo incorreto
465
+ // 🔹 Fix the path if it comes in relative (e.g. "src/...") or with an incorrect prefix
435
466
  let fullPath = requestedPath;
436
467
 
437
468
  if (!path.isAbsolute(requestedPath) || !requestedPath.startsWith(workspacePath)) {
@@ -470,7 +501,7 @@ router.get("/file", async (req, res) => {
470
501
 
471
502
  // --------------------------------------------------
472
503
  // 🧩 5️⃣ POST /workspace/resolve
473
- // Resolve caminho relativo a absoluto (para exibição no frontend)
504
+ // Resolves a relative path to an absolute one (for display in the frontend)
474
505
  // --------------------------------------------------
475
506
  router.post("/resolve", async (req, res) => {
476
507
  try {
@@ -498,7 +529,7 @@ router.post("/resolve", async (req, res) => {
498
529
 
499
530
  // --------------------------------------------------
500
531
  // 🧩 6️⃣ GET /workspace/detect
501
- // Detecta tipo de projeto (Maven / Gradle / Outro)
532
+ // Detects the project type (Maven / Gradle / Other)
502
533
  // --------------------------------------------------
503
534
  router.get("/detect", async (req, res) => {
504
535
  try {
@@ -526,7 +557,7 @@ router.get("/detect", async (req, res) => {
526
557
 
527
558
  // --------------------------------------------------
528
559
  // 🧩 7️⃣ GET /workspace/search-file
529
- // Busca um arquivo pelo nome dentro do workspace
560
+ // Searches for a file by name inside the workspace
530
561
  // --------------------------------------------------
531
562
  router.get("/search-file", async (req, res) => {
532
563
  try {
@@ -590,7 +621,7 @@ router.get("/search-file", async (req, res) => {
590
621
 
591
622
  // --------------------------------------------------
592
623
  // 🧩 8️⃣ POST /workspace/search
593
- // Busca por conteúdo dentro dos arquivos do workspace
624
+ // Searches for content inside the workspace files
594
625
  // --------------------------------------------------
595
626
  router.post("/search", async (req, res) => {
596
627
  try {
@@ -654,7 +685,7 @@ router.post("/search", async (req, res) => {
654
685
 
655
686
  // --------------------------------------------------
656
687
  // 🧩 9️⃣ GET /workspace/scan
657
- // Lista TODOS os arquivos do workspace (para list_files tool)
688
+ // Lists ALL workspace files (for the list_files tool)
658
689
  // --------------------------------------------------
659
690
  router.get("/scan", async (req, res) => {
660
691
  try {
@@ -718,7 +749,7 @@ router.get("/scan", async (req, res) => {
718
749
 
719
750
  // --------------------------------------------------
720
751
  // 🧩 🔟 GET /workspace/file-content
721
- // Alias para /workspace/file (compatibilidade com código Java)
752
+ // Alias for /workspace/file (compatibility with Java code)
722
753
  // --------------------------------------------------
723
754
  router.get("/file-content", async (req, res) => {
724
755
  try {
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * BaseRuntime
3
3
  *
4
- * Interface abstrata para todos os runtimes de linguagem.
5
- * Cada linguagem (Java, Node, Python, etc.) deve implementar esta interface.
4
+ * Abstract interface for all language runtimes.
5
+ * Each language (Java, Node, Python, etc.) must implement this interface.
6
6
  *
7
7
  * @abstract
8
8
  */
@@ -19,32 +19,32 @@ export class BaseRuntime {
19
19
  // ==========================================
20
20
 
21
21
  /**
22
- * Identificador único do runtime
23
- * @returns {string} Ex: 'java-maven', 'node-npm', 'python-pip'
22
+ * Unique identifier of the runtime
23
+ * @returns {string} e.g.: 'java-maven', 'node-npm', 'python-pip'
24
24
  */
25
25
  getId() {
26
26
  throw new Error('Method getId() must be implemented');
27
27
  }
28
28
 
29
29
  /**
30
- * Nome amigável do runtime
31
- * @returns {string} Ex: 'Java (Maven)', 'Node.js (npm)'
30
+ * Friendly name of the runtime
31
+ * @returns {string} e.g.: 'Java (Maven)', 'Node.js (npm)'
32
32
  */
33
33
  getName() {
34
34
  throw new Error('Method getName() must be implemented');
35
35
  }
36
36
 
37
37
  /**
38
- * Linguagem do runtime
39
- * @returns {string} Ex: 'java', 'node', 'python', 'dotnet', 'go'
38
+ * Language of the runtime
39
+ * @returns {string} e.g.: 'java', 'node', 'python', 'dotnet', 'go'
40
40
  */
41
41
  getLanguage() {
42
42
  throw new Error('Method getLanguage() must be implemented');
43
43
  }
44
44
 
45
45
  /**
46
- * Build tool usado
47
- * @returns {string} Ex: 'maven', 'gradle', 'npm', 'yarn', 'pip'
46
+ * Build tool used
47
+ * @returns {string} e.g.: 'maven', 'gradle', 'npm', 'yarn', 'pip'
48
48
  */
49
49
  getBuildTool() {
50
50
  throw new Error('Method getBuildTool() must be implemented');
@@ -55,16 +55,16 @@ export class BaseRuntime {
55
55
  // ==========================================
56
56
 
57
57
  /**
58
- * Arquivos marcadores que indicam este runtime
59
- * @returns {string[]} Ex: ['pom.xml'], ['package.json']
58
+ * Marker files that indicate this runtime
59
+ * @returns {string[]} e.g.: ['pom.xml'], ['package.json']
60
60
  */
61
61
  getMarkerFiles() {
62
62
  throw new Error('Method getMarkerFiles() must be implemented');
63
63
  }
64
64
 
65
65
  /**
66
- * Verifica se este runtime é compatível com o workspace
67
- * @param {string} workspacePath - Caminho do workspace
66
+ * Checks whether this runtime is compatible with the workspace
67
+ * @param {string} workspacePath - Workspace path
68
68
  * @returns {Promise<boolean>}
69
69
  */
70
70
  async isCompatible(workspacePath) {
@@ -72,8 +72,8 @@ export class BaseRuntime {
72
72
  }
73
73
 
74
74
  /**
75
- * Detecta informações do projeto
76
- * @param {string} workspacePath - Caminho do workspace
75
+ * Detects project information
76
+ * @param {string} workspacePath - Workspace path
77
77
  * @returns {Promise<ProjectInfo>}
78
78
  */
79
79
  async detectProject(workspacePath) {
@@ -85,9 +85,9 @@ export class BaseRuntime {
85
85
  // ==========================================
86
86
 
87
87
  /**
88
- * Instala dependências do projeto
89
- * @param {string} workspacePath - Caminho do workspace
90
- * @param {object} options - Opções adicionais
88
+ * Installs the project dependencies
89
+ * @param {string} workspacePath - Workspace path
90
+ * @param {object} options - Additional options
91
91
  * @returns {Promise<CommandResult>}
92
92
  */
93
93
  async install(workspacePath, options = {}) {
@@ -95,9 +95,9 @@ export class BaseRuntime {
95
95
  }
96
96
 
97
97
  /**
98
- * Compila o projeto
99
- * @param {string} workspacePath - Caminho do workspace
100
- * @param {object} options - Opções adicionais
98
+ * Compiles the project
99
+ * @param {string} workspacePath - Workspace path
100
+ * @param {object} options - Additional options
101
101
  * @returns {Promise<CommandResult>}
102
102
  */
103
103
  async build(workspacePath, options = {}) {
@@ -105,8 +105,8 @@ export class BaseRuntime {
105
105
  }
106
106
 
107
107
  /**
108
- * Retorna o comando para iniciar o serviço
109
- * @param {object} options - Opções (port, profile, etc.)
108
+ * Returns the command to start the service
109
+ * @param {object} options - Options (port, profile, etc.)
110
110
  * @returns {StartCommand} { cmd: string, args: string[], env?: object }
111
111
  */
112
112
  getStartCommand(options = {}) {
@@ -114,7 +114,7 @@ export class BaseRuntime {
114
114
  }
115
115
 
116
116
  /**
117
- * Padrão regex para detectar quando o serviço está pronto
117
+ * Regex pattern to detect when the service is ready
118
118
  * @returns {RegExp}
119
119
  */
120
120
  getReadyPattern() {
@@ -122,7 +122,7 @@ export class BaseRuntime {
122
122
  }
123
123
 
124
124
  /**
125
- * Porta padrão do framework
125
+ * Default port of the framework
126
126
  * @returns {number}
127
127
  */
128
128
  getDefaultPort() {
@@ -130,8 +130,8 @@ export class BaseRuntime {
130
130
  }
131
131
 
132
132
  /**
133
- * Detecta a porta configurada no projeto
134
- * @param {string} workspacePath - Caminho do workspace
133
+ * Detects the port configured in the project
134
+ * @param {string} workspacePath - Workspace path
135
135
  * @returns {Promise<number|null>}
136
136
  */
137
137
  async detectPort(workspacePath) {
@@ -143,9 +143,9 @@ export class BaseRuntime {
143
143
  // ==========================================
144
144
 
145
145
  /**
146
- * Executa testes do projeto
147
- * @param {string} workspacePath - Caminho do workspace
148
- * @param {object} options - Opções (testFile, coverage, etc.)
146
+ * Runs the project tests
147
+ * @param {string} workspacePath - Workspace path
148
+ * @param {object} options - Options (testFile, coverage, etc.)
149
149
  * @returns {Promise<TestResult>}
150
150
  */
151
151
  async test(workspacePath, options = {}) {
@@ -153,9 +153,9 @@ export class BaseRuntime {
153
153
  }
154
154
 
155
155
  /**
156
- * Executa um teste específico
157
- * @param {string} workspacePath - Caminho do workspace
158
- * @param {string} testFile - Arquivo de teste
156
+ * Runs a specific test
157
+ * @param {string} workspacePath - Workspace path
158
+ * @param {string} testFile - Test file
159
159
  * @returns {Promise<TestResult>}
160
160
  */
161
161
  async testSingle(workspacePath, testFile) {
@@ -167,16 +167,16 @@ export class BaseRuntime {
167
167
  // ==========================================
168
168
 
169
169
  /**
170
- * Extensões de arquivo suportadas
171
- * @returns {string[]} Ex: ['.java'], ['.js', '.ts']
170
+ * Supported file extensions
171
+ * @returns {string[]} e.g.: ['.java'], ['.js', '.ts']
172
172
  */
173
173
  getFileExtensions() {
174
174
  throw new Error('Method getFileExtensions() must be implemented');
175
175
  }
176
176
 
177
177
  /**
178
- * Encontra integrações HTTP no código
179
- * @param {string} workspacePath - Caminho do workspace
178
+ * Finds HTTP integrations in the code
179
+ * @param {string} workspacePath - Workspace path
180
180
  * @returns {Promise<Integration[]>}
181
181
  */
182
182
  async findIntegrations(workspacePath) {
@@ -184,9 +184,9 @@ export class BaseRuntime {
184
184
  }
185
185
 
186
186
  /**
187
- * Analisa imports/dependências de um arquivo
188
- * @param {string} filePath - Caminho do arquivo
189
- * @param {string} content - Conteúdo do arquivo
187
+ * Analyzes the imports/dependencies of a file
188
+ * @param {string} filePath - File path
189
+ * @param {string} content - File content
190
190
  * @returns {Promise<Dependency[]>}
191
191
  */
192
192
  async analyzeImports(filePath, content) {
@@ -198,8 +198,8 @@ export class BaseRuntime {
198
198
  // ==========================================
199
199
 
200
200
  /**
201
- * Valida se um diff é aplicável
202
- * @param {string} workspacePath - Caminho do workspace
201
+ * Validates whether a diff is applicable
202
+ * @param {string} workspacePath - Workspace path
203
203
  * @param {string} diff - Unified diff
204
204
  * @returns {Promise<ValidationResult>}
205
205
  */
@@ -208,13 +208,13 @@ export class BaseRuntime {
208
208
  }
209
209
 
210
210
  /**
211
- * Ações pós-patch (ex: reformatar código)
212
- * @param {string} workspacePath - Caminho do workspace
213
- * @param {string[]} modifiedFiles - Arquivos modificados
211
+ * Post-patch actions (e.g.: reformat code)
212
+ * @param {string} workspacePath - Workspace path
213
+ * @param {string[]} modifiedFiles - Modified files
214
214
  * @returns {Promise<void>}
215
215
  */
216
216
  async postPatchActions(workspacePath, modifiedFiles) {
217
- // Override nas implementações específicas
217
+ // Override in the specific implementations
218
218
  }
219
219
  }
220
220
 
@@ -224,12 +224,12 @@ export class BaseRuntime {
224
224
 
225
225
  /**
226
226
  * @typedef {object} ProjectInfo
227
- * @property {string} name - Nome do projeto
228
- * @property {string} version - Versão
229
- * @property {string} language - Linguagem
230
- * @property {string} framework - Framework detectado
227
+ * @property {string} name - Project name
228
+ * @property {string} version - Version
229
+ * @property {string} language - Language
230
+ * @property {string} framework - Detected framework
231
231
  * @property {string} buildTool - Build tool
232
- * @property {number} port - Porta configurada
232
+ * @property {number} port - Configured port
233
233
  */
234
234
 
235
235
  /**
@@ -237,54 +237,54 @@ export class BaseRuntime {
237
237
  * @property {number} code - Exit code
238
238
  * @property {string} stdout - Standard output
239
239
  * @property {string} stderr - Standard error
240
- * @property {number} duration - Duração em ms
240
+ * @property {number} duration - Duration in ms
241
241
  */
242
242
 
243
243
  /**
244
244
  * @typedef {object} StartCommand
245
- * @property {string} cmd - Comando
246
- * @property {string[]} args - Argumentos
247
- * @property {object} [env] - Variáveis de ambiente adicionais
245
+ * @property {string} cmd - Command
246
+ * @property {string[]} args - Arguments
247
+ * @property {object} [env] - Additional environment variables
248
248
  */
249
249
 
250
250
  /**
251
251
  * @typedef {object} TestResult
252
- * @property {boolean} success - Se todos os testes passaram
253
- * @property {number} passed - Número de testes que passaram
254
- * @property {number} failed - Número de testes que falharam
255
- * @property {number} skipped - Número de testes ignorados
256
- * @property {number} duration - Duração em ms
257
- * @property {string} output - Output completo
258
- * @property {TestFailure[]} failures - Lista de falhas
252
+ * @property {boolean} success - Whether all tests passed
253
+ * @property {number} passed - Number of tests that passed
254
+ * @property {number} failed - Number of tests that failed
255
+ * @property {number} skipped - Number of skipped tests
256
+ * @property {number} duration - Duration in ms
257
+ * @property {string} output - Full output
258
+ * @property {TestFailure[]} failures - List of failures
259
259
  */
260
260
 
261
261
  /**
262
262
  * @typedef {object} TestFailure
263
- * @property {string} testName - Nome do teste
264
- * @property {string} message - Mensagem de erro
263
+ * @property {string} testName - Test name
264
+ * @property {string} message - Error message
265
265
  * @property {string} stackTrace - Stack trace
266
266
  */
267
267
 
268
268
  /**
269
269
  * @typedef {object} Integration
270
- * @property {string} type - Tipo (rest-templates, feign, axios, etc.)
271
- * @property {string} file - Arquivo onde foi encontrado
272
- * @property {number} line - Linha
273
- * @property {string} targetUrl - URL alvo (se detectável)
274
- * @property {string} method - Método HTTP (se detectável)
270
+ * @property {string} type - Type (rest-templates, feign, axios, etc.)
271
+ * @property {string} file - File where it was found
272
+ * @property {number} line - Line
273
+ * @property {string} targetUrl - Target URL (if detectable)
274
+ * @property {string} method - HTTP method (if detectable)
275
275
  */
276
276
 
277
277
  /**
278
278
  * @typedef {object} Dependency
279
- * @property {string} name - Nome da dependência
280
- * @property {string} type - Tipo (import, require, using)
281
- * @property {boolean} isExternal - Se é externa ao projeto
279
+ * @property {string} name - Dependency name
280
+ * @property {string} type - Type (import, require, using)
281
+ * @property {boolean} isExternal - Whether it is external to the project
282
282
  */
283
283
 
284
284
  /**
285
285
  * @typedef {object} ValidationResult
286
- * @property {boolean} valid - Se o patch é válido
287
- * @property {string[]} errors - Lista de erros
286
+ * @property {boolean} valid - Whether the patch is valid
287
+ * @property {string[]} errors - List of errors
288
288
  */
289
289
 
290
290
  export default BaseRuntime;
@@ -6,15 +6,15 @@ import { run } from '../../utils/exec-utils.js';
6
6
  /**
7
7
  * GradleRuntime
8
8
  *
9
- * Runtime para projetos Java com Gradle.
10
- * Suporta Spring Boot, Quarkus, e projetos Gradle genéricos.
9
+ * Runtime for Java projects using Gradle.
10
+ * Supports Spring Boot, Quarkus, and generic Gradle projects.
11
11
  */
12
12
  export class GradleRuntime extends BaseRuntime {
13
13
 
14
14
  constructor() {
15
15
  super();
16
16
  this.framework = null;
17
- this.useWrapper = true; // Usar ./gradlew por padrão
17
+ this.useWrapper = true; // Use ./gradlew by default
18
18
  }
19
19
 
20
20
  // ==========================================
@@ -64,11 +64,11 @@ export class GradleRuntime extends BaseRuntime {
64
64
  buildContent = await readFile(kotlinPath, 'utf8');
65
65
  }
66
66
 
67
- // Verificar se existe wrapper
67
+ // Check whether a wrapper exists
68
68
  const wrapperPath = path.join(workspacePath, 'gradlew');
69
69
  this.useWrapper = await exists(wrapperPath);
70
70
 
71
- // Detectar nome do projeto
71
+ // Detect the project name
72
72
  const settingsPath = path.join(workspacePath, 'settings.gradle');
73
73
  const settingsKtsPath = path.join(workspacePath, 'settings.gradle.kts');
74
74
  let name = path.basename(workspacePath);
@@ -83,15 +83,15 @@ export class GradleRuntime extends BaseRuntime {
83
83
  if (match) name = match[1];
84
84
  }
85
85
 
86
- // Detectar versão
86
+ // Detect the version
87
87
  const versionMatch = buildContent.match(/version\s*=?\s*['"]([^'"]+)['"]/);
88
88
  const version = versionMatch ? versionMatch[1] : '0.0.1';
89
89
 
90
- // Detectar framework
90
+ // Detect the framework
91
91
  const framework = this.detectFramework(buildContent);
92
92
  this.framework = framework;
93
93
 
94
- // Detectar porta
94
+ // Detect the port
95
95
  const port = await this.detectPort(workspacePath);
96
96
 
97
97
  return {
@@ -207,7 +207,7 @@ export class GradleRuntime extends BaseRuntime {
207
207
  }
208
208
 
209
209
  async detectPort(workspacePath) {
210
- // Mesma lógica do Maven - configs são iguais
210
+ // Same logic as Maven - the configs are identical
211
211
  const propsPath = path.join(workspacePath, 'src/main/resources/application.properties');
212
212
  if (await exists(propsPath)) {
213
213
  const content = await readFile(propsPath, 'utf8');
@@ -233,10 +233,10 @@ export class GradleRuntime extends BaseRuntime {
233
233
  const startTime = Date.now();
234
234
  const cmd = this.getGradleCommand();
235
235
 
236
- // Clean primeiro
236
+ // Clean first
237
237
  await run(cmd, ['clean', '--quiet'], workspacePath);
238
238
 
239
- // Rodar testes
239
+ // Run the tests
240
240
  const result = await run(cmd, ['test', '--quiet'], workspacePath);
241
241
 
242
242
  const testResult = this.parseTestOutput(result, workspacePath);
@@ -249,7 +249,7 @@ export class GradleRuntime extends BaseRuntime {
249
249
  const startTime = Date.now();
250
250
  const cmd = this.getGradleCommand();
251
251
 
252
- // Extrair nome da classe
252
+ // Extract the class name
253
253
  const className = path.basename(testFile, '.java');
254
254
 
255
255
  const result = await run(cmd, [
@@ -268,10 +268,10 @@ export class GradleRuntime extends BaseRuntime {
268
268
  async parseTestOutput(result, workspacePath) {
269
269
  const output = result.stdout + result.stderr;
270
270
 
271
- // Tentar ler relatório XML do Gradle se disponível
271
+ // Try to read the Gradle XML report if available
272
272
  const reportDir = path.join(workspacePath, 'build/test-results/test');
273
273
 
274
- // Parse básico do output
274
+ // Basic parsing of the output
275
275
  let passed = 0;
276
276
  let failed = 0;
277
277
  let skipped = 0;
@@ -303,7 +303,7 @@ export class GradleRuntime extends BaseRuntime {
303
303
  extractFailures(output) {
304
304
  const failures = [];
305
305
 
306
- // Gradle mostra falhas com formato específico
306
+ // Gradle shows failures in a specific format
307
307
  const failureRegex = /(\w+Test)\s+>\s+(\w+).*FAILED/g;
308
308
  let match;
309
309
 
@@ -323,7 +323,7 @@ export class GradleRuntime extends BaseRuntime {
323
323
  // ==========================================
324
324
 
325
325
  getFileExtensions() {
326
- return ['.java', '.kt']; // Suporte a Kotlin também
326
+ return ['.java', '.kt']; // Kotlin support as well
327
327
  }
328
328
 
329
329
  async findIntegrations(workspacePath) {
@@ -333,7 +333,7 @@ export class GradleRuntime extends BaseRuntime {
333
333
  }
334
334
 
335
335
  async analyzeImports(filePath, content) {
336
- // Mesma lógica do Maven
336
+ // Same logic as Maven
337
337
  const imports = [];
338
338
  const importRegex = /import\s+(static\s+)?([a-zA-Z0-9_.]+)(?:\.\*)?;/g;
339
339