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.
- package/.claude/context.md +76 -0
- package/.claude/skills/README.md +25 -0
- package/.claude/skills/tdd-debugging/SKILL.md +53 -0
- package/.claude/skills/tdd-debugging/references/anti-patterns.md +43 -0
- package/.claude/skills/tdd-debugging/references/command-reference.md +46 -0
- package/.claude/standards/README.md +51 -0
- package/.claude/standards/clean-code.md +75 -0
- package/.claude/standards/code-review-checklist.md +61 -0
- package/.claude/standards/layered-architecture.md +163 -0
- package/.claude/standards/node.md +45 -0
- package/.claude/standards/security-owasp.md +114 -0
- package/.claude/standards/simplicity.md +42 -0
- package/.claude/standards/solid.md +64 -0
- package/.claude/standards/testing.md +59 -0
- package/.cursor/rules/standards.mdc +17 -0
- package/.github/workflows/build-byoc-image.yml +315 -0
- package/.github/workflows/deploy-gcp.yml +102 -0
- package/.github/workflows/npm-publish.yml +69 -8
- package/AGENTS.md +21 -0
- package/CHANGELOG.md +69 -0
- package/CLAUDE.md +13 -0
- package/CLAUDE_CODE_AGENT_INFINITE.md +5 -3
- package/Dockerfile +4 -0
- package/Dockerfile.full +55 -3
- package/README.md +81 -0
- package/bin/install.js +16 -5
- package/cloudbuild-full.yaml +57 -0
- package/docker-compose.yml +5 -3
- package/docs/OBSERVABILITY.md +164 -0
- package/docs/byoc-agent-image.md +70 -0
- package/docs/graphify-packaging-plan.md +133 -0
- package/docs/graphify-validation-run-2026-10-28.md +243 -0
- package/docs/legacy-connectors.md +268 -0
- package/docs/releasing.md +43 -0
- package/docs/signed-commands.md +163 -0
- package/env.example +30 -0
- package/helm/Chart.yaml +2 -2
- package/helm/templates/deployment.yaml +13 -3
- package/helm/templates/networkpolicy.yaml +22 -0
- package/helm/templates/secret.yaml +1 -0
- package/helm/values.yaml +13 -14
- package/mcp-server.js +4 -1
- package/package.json +12 -4
- package/scripts/sync-fixtures.mjs +246 -0
- package/scripts/upgrade-observability-push.sh +227 -0
- package/src/adapters/as400/as400-parser.js +12 -0
- package/src/adapters/as400/index.js +134 -0
- package/src/adapters/cobol/cobol-parser.js +37 -0
- package/src/adapters/cobol/index.js +151 -0
- package/src/adapters/ibmmq/ibmmq-parser.js +23 -0
- package/src/adapters/ibmmq/index.js +137 -0
- package/src/adapters/index.js +79 -0
- package/src/adapters/oracle-forms/index.js +145 -0
- package/src/adapters/oracle-forms/oracle-forms-parser.js +11 -0
- package/src/adapters/sap/index.js +146 -0
- package/src/adapters/sap/sap-parser.js +41 -0
- package/src/ai-engine.js +22 -22
- package/src/config/trusted-signing-keys.json +3 -0
- package/src/detectors/build-tool-detector.js +50 -0
- package/src/detectors/multi-project-detector.js +22 -22
- package/src/detectors/service-detector.js +24 -24
- package/src/exec-utils.js +26 -4
- package/src/git/base-git-provider.js +117 -117
- package/src/git/bitbucket-provider.js +2 -2
- package/src/git/git-provider-registry.js +18 -18
- package/src/git/github-provider.js +13 -13
- package/src/git/multi-repo-pr.js +161 -0
- package/src/mcp-http-server.js +32 -16
- package/src/observability/bundle-files.js +418 -0
- package/src/observability/detect.js +151 -0
- package/src/observability/provision.js +212 -0
- package/src/observability/render-cli.js +59 -0
- package/src/observability/routes.js +88 -0
- package/src/patch/patch-engine.js +28 -28
- package/src/patch-manager.js +85 -85
- package/src/patch_bkp.js +14 -14
- package/src/ports.js +4 -4
- package/src/routes/workspace.route.js +47 -16
- package/src/runtimes/base-runtime.js +75 -75
- package/src/runtimes/java/gradle-runtime.js +17 -17
- package/src/runtimes/java/java-integrations.js +25 -25
- package/src/runtimes/java/maven-runtime.js +34 -34
- package/src/runtimes/node/node-integrations.js +1 -1
- package/src/runtimes/node/npm-runtime.js +14 -14
- package/src/runtimes/node/yarn-runtime.js +4 -4
- package/src/runtimes/runtime-registry.js +25 -25
- package/src/server-local.js +4 -4
- package/src/server.js +1412 -335
- package/src/siblings/burst-suppressor.js +89 -0
- package/src/siblings/capabilities.js +273 -0
- package/src/siblings/env-compat.cjs +58 -0
- package/src/siblings/incident-forwarder.js +320 -0
- package/src/siblings/logger.js +15 -0
- package/src/siblings/metrics.js +94 -0
- package/src/utils/agent-auth.js +184 -0
- package/src/utils/approval-token.js +56 -0
- package/src/utils/bind-host.js +29 -0
- package/src/utils/branch-refspec.js +98 -0
- package/src/utils/child-env.js +34 -0
- package/src/utils/environment-diagnostics.js +55 -55
- package/src/utils/exec-policy.js +962 -0
- package/src/utils/exec-utils.js +15 -15
- package/src/utils/file-count.js +46 -0
- package/src/utils/fs-utils.js +10 -10
- package/src/utils/multi-repo-open.js +132 -0
- package/src/utils/open-gate.js +183 -0
- package/src/utils/ranged-read.js +65 -0
- package/src/utils/request-guards.js +77 -0
- package/src/utils/request-signing.js +342 -0
- package/src/utils/root-recovery.js +244 -0
- package/src/utils/safe-exec-args.js +58 -0
- package/src/utils/sandbox.js +182 -0
- package/src/utils/search-outcome.js +56 -0
- package/src/utils/workspace-root.js +80 -0
- package/src/validators/syntax-validator.js +149 -0
- package/src/workspace/detect-port.js +16 -16
- package/src/workspace/file-reader.js +1 -1
- package/src/workspace/process-manager.js +46 -46
- package/src/workspace-manager.js +86 -24
- package/test/adapters/as400/as400.test.js +121 -0
- package/test/adapters/cobol/cobol.test.js +217 -0
- package/test/adapters/ibmmq/ibmmq.test.js +122 -0
- package/test/adapters/oracle-forms/oracle-forms.test.js +180 -0
- package/test/adapters/registry.test.js +108 -0
- package/test/adapters/sap/sap.test.js +142 -0
- package/test/agent-auth.test.js +194 -0
- package/test/bind-host.test.js +26 -0
- package/test/branch-refspec.test.js +224 -0
- package/test/burst-suppressor.test.js +60 -0
- package/test/capabilities-access.test.js +47 -0
- package/test/capabilities.test.js +87 -0
- package/test/child-env.test.js +23 -0
- package/test/env-compat.test.js +71 -0
- package/test/exec-policy.test.js +463 -0
- package/test/file-count.test.js +64 -0
- package/test/incident-forwarder.test.js +231 -0
- package/test/multi-repo-open.test.js +180 -0
- package/test/multi-repo-pr.test.js +129 -0
- package/test/observability-detect.test.js +199 -0
- package/test/open-gate.test.js +341 -0
- package/test/ranged-read.test.js +60 -0
- package/test/request-guards.test.js +91 -0
- package/test/request-signing.test.js +284 -0
- package/test/root-recovery-sidecar.test.js +171 -0
- package/test/root-recovery.test.js +274 -0
- package/test/safe-exec-args.test.js +58 -0
- package/test/sandbox.test.js +98 -0
- package/test/search-outcome.test.js +50 -0
- package/test/workspace-root.test.js +64 -0
- package/tools/graphify-validation/README.md +92 -0
- package/tools/graphify-validation/config/questions.json +31 -0
- package/tools/graphify-validation/config/repos.json +9 -0
- package/tools/graphify-validation/config/symbols.json +6 -0
- package/tools/graphify-validation/fixtures/spring/expected.json +34 -0
- package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/AppConfig.java +29 -0
- package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/AuditLogger.java +15 -0
- package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/Cache.java +7 -0
- package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/CheckoutService.java +25 -0
- package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/InMemoryCache.java +18 -0
- package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/OrderController.java +22 -0
- package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/PaymentGateway.java +5 -0
- package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/PaypalGateway.java +11 -0
- package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/RefundService.java +14 -0
- package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/StripeGateway.java +11 -0
- package/tools/graphify-validation/lib/affected_vs_rg.py +81 -0
- package/tools/graphify-validation/lib/audit_hook/sitecustomize.py +22 -0
- package/tools/graphify-validation/lib/graph_metrics.py +96 -0
- package/tools/graphify-validation/lib/gv_common.py +130 -0
- package/tools/graphify-validation/lib/licenses.py +47 -0
- package/tools/graphify-validation/lib/pip_audit_summary.py +18 -0
- package/tools/graphify-validation/lib/recall.py +115 -0
- package/tools/graphify-validation/lib/report.py +226 -0
- package/tools/graphify-validation/lib/run_all.py +237 -0
- package/tools/graphify-validation/lib/run_graphify.py +144 -0
- package/tools/graphify-validation/lib/rusage_helper.py +17 -0
- package/tools/graphify-validation/lib/sample_edges.py +246 -0
- package/tools/graphify-validation/lib/spring_fixture.py +81 -0
- package/tools/graphify-validation/requirements-py311.lock +508 -0
- package/tools/graphify-validation/requirements-tools.in +1 -0
- package/tools/graphify-validation/requirements-tools.lock +371 -0
- package/tools/graphify-validation/requirements.in +1 -0
- package/tools/graphify-validation/requirements.lock +502 -0
- package/tools/graphify-validation/run.sh +43 -0
- package/tools/graphify-validation/tests/test_harness.py +151 -0
- package/cloudbuild-agent-qa.yaml +0 -43
- package/cloudbuild-agent-staging.yaml +0 -40
- package/cloudbuild.yaml.deprecated +0 -42
- package/src/local-agent-source.tar.gz +0 -0
|
@@ -4,7 +4,7 @@ import { readFile, readdir, stat } from '../../utils/fs-utils.js';
|
|
|
4
4
|
/**
|
|
5
5
|
* JavaIntegrationAnalyzer
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* Analyzes Java code to find HTTP integrations:
|
|
8
8
|
* - RestTemplate
|
|
9
9
|
* - WebClient
|
|
10
10
|
* - FeignClient
|
|
@@ -20,7 +20,7 @@ export class JavaIntegrationAnalyzer {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
23
|
+
* Finds all integrations in the workspace
|
|
24
24
|
* @returns {Promise<Integration[]>}
|
|
25
25
|
*/
|
|
26
26
|
async findAll() {
|
|
@@ -33,7 +33,7 @@ export class JavaIntegrationAnalyzer {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
|
-
*
|
|
36
|
+
* Scans a directory recursively
|
|
37
37
|
*/
|
|
38
38
|
async scanDirectory(dir) {
|
|
39
39
|
try {
|
|
@@ -49,12 +49,12 @@ export class JavaIntegrationAnalyzer {
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
} catch (e) {
|
|
52
|
-
//
|
|
52
|
+
// Directory does not exist or read error
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
/**
|
|
57
|
-
*
|
|
57
|
+
* Analyzes a Java file
|
|
58
58
|
*/
|
|
59
59
|
async analyzeFile(filePath) {
|
|
60
60
|
try {
|
|
@@ -62,7 +62,7 @@ export class JavaIntegrationAnalyzer {
|
|
|
62
62
|
const relativePath = path.relative(this.workspacePath, filePath);
|
|
63
63
|
const lines = content.split('\n');
|
|
64
64
|
|
|
65
|
-
//
|
|
65
|
+
// Analyze each type of integration
|
|
66
66
|
this.findRestTemplate(content, relativePath, lines);
|
|
67
67
|
this.findWebClient(content, relativePath, lines);
|
|
68
68
|
this.findFeignClient(content, relativePath, lines);
|
|
@@ -71,24 +71,24 @@ export class JavaIntegrationAnalyzer {
|
|
|
71
71
|
this.findRabbitMQ(content, relativePath, lines);
|
|
72
72
|
|
|
73
73
|
} catch (e) {
|
|
74
|
-
//
|
|
74
|
+
// Error reading the file
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
/**
|
|
79
|
-
*
|
|
79
|
+
* Finds RestTemplate usage
|
|
80
80
|
*/
|
|
81
81
|
findRestTemplate(content, filePath, lines) {
|
|
82
|
-
//
|
|
82
|
+
// RestTemplate patterns
|
|
83
83
|
const patterns = [
|
|
84
|
-
//
|
|
84
|
+
// Injection
|
|
85
85
|
{ regex: /@Autowired\s*\n?\s*(?:private|protected|public)?\s*RestTemplate\s+\w+/g, type: 'injection' },
|
|
86
86
|
{ regex: /private\s+(?:final\s+)?RestTemplate\s+\w+/g, type: 'field' },
|
|
87
87
|
|
|
88
|
-
//
|
|
88
|
+
// HTTP calls
|
|
89
89
|
{ regex: /restTemplate\.(getForObject|getForEntity|postForObject|postForEntity|exchange|put|delete)\s*\(/gi, type: 'call' },
|
|
90
90
|
|
|
91
|
-
//
|
|
91
|
+
// Instantiation
|
|
92
92
|
{ regex: /new\s+RestTemplate\s*\(/g, type: 'instantiation' },
|
|
93
93
|
{ regex: /RestTemplateBuilder/g, type: 'builder' }
|
|
94
94
|
];
|
|
@@ -114,7 +114,7 @@ export class JavaIntegrationAnalyzer {
|
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
/**
|
|
117
|
-
*
|
|
117
|
+
* Finds WebClient usage (Spring WebFlux)
|
|
118
118
|
*/
|
|
119
119
|
findWebClient(content, filePath, lines) {
|
|
120
120
|
const patterns = [
|
|
@@ -147,7 +147,7 @@ export class JavaIntegrationAnalyzer {
|
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
/**
|
|
150
|
-
*
|
|
150
|
+
* Finds FeignClient
|
|
151
151
|
*/
|
|
152
152
|
findFeignClient(content, filePath, lines) {
|
|
153
153
|
// @FeignClient annotation
|
|
@@ -158,7 +158,7 @@ export class JavaIntegrationAnalyzer {
|
|
|
158
158
|
const line = this.getLineNumber(content, match.index);
|
|
159
159
|
const serviceName = match[1];
|
|
160
160
|
|
|
161
|
-
//
|
|
161
|
+
// Extract the URL if specified
|
|
162
162
|
const urlMatch = content.substring(match.index, match.index + 200)
|
|
163
163
|
.match(/url\s*=\s*["']([^"']+)["']/);
|
|
164
164
|
|
|
@@ -174,7 +174,7 @@ export class JavaIntegrationAnalyzer {
|
|
|
174
174
|
});
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
-
//
|
|
177
|
+
// FeignClient methods
|
|
178
178
|
const methodPatterns = [
|
|
179
179
|
{ regex: /@GetMapping\s*\(?\s*["']?([^"'\s)]*)/g, method: 'GET' },
|
|
180
180
|
{ regex: /@PostMapping\s*\(?\s*["']?([^"'\s)]*)/g, method: 'POST' },
|
|
@@ -183,7 +183,7 @@ export class JavaIntegrationAnalyzer {
|
|
|
183
183
|
{ regex: /@PatchMapping\s*\(?\s*["']?([^"'\s)]*)/g, method: 'PATCH' }
|
|
184
184
|
];
|
|
185
185
|
|
|
186
|
-
//
|
|
186
|
+
// Only look for methods if the file has @FeignClient
|
|
187
187
|
if (content.includes('@FeignClient')) {
|
|
188
188
|
for (const pattern of methodPatterns) {
|
|
189
189
|
let methodMatch;
|
|
@@ -205,7 +205,7 @@ export class JavaIntegrationAnalyzer {
|
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
/**
|
|
208
|
-
*
|
|
208
|
+
* Finds Java HttpClient (11+)
|
|
209
209
|
*/
|
|
210
210
|
findHttpClient(content, filePath, lines) {
|
|
211
211
|
const patterns = [
|
|
@@ -234,7 +234,7 @@ export class JavaIntegrationAnalyzer {
|
|
|
234
234
|
}
|
|
235
235
|
|
|
236
236
|
/**
|
|
237
|
-
*
|
|
237
|
+
* Finds Kafka integrations
|
|
238
238
|
*/
|
|
239
239
|
findKafka(content, filePath, lines) {
|
|
240
240
|
const patterns = [
|
|
@@ -261,7 +261,7 @@ export class JavaIntegrationAnalyzer {
|
|
|
261
261
|
}
|
|
262
262
|
|
|
263
263
|
/**
|
|
264
|
-
*
|
|
264
|
+
* Finds RabbitMQ integrations
|
|
265
265
|
*/
|
|
266
266
|
findRabbitMQ(content, filePath, lines) {
|
|
267
267
|
const patterns = [
|
|
@@ -292,20 +292,20 @@ export class JavaIntegrationAnalyzer {
|
|
|
292
292
|
// ==========================================
|
|
293
293
|
|
|
294
294
|
/**
|
|
295
|
-
*
|
|
295
|
+
* Gets the line number from the index
|
|
296
296
|
*/
|
|
297
297
|
getLineNumber(content, index) {
|
|
298
298
|
return content.substring(0, index).split('\n').length;
|
|
299
299
|
}
|
|
300
300
|
|
|
301
301
|
/**
|
|
302
|
-
*
|
|
302
|
+
* Tries to extract a URL from the context
|
|
303
303
|
*/
|
|
304
304
|
extractUrl(content, startIndex) {
|
|
305
|
-
//
|
|
305
|
+
// Look for a URL in the next 500 characters
|
|
306
306
|
const context = content.substring(startIndex, startIndex + 500);
|
|
307
307
|
|
|
308
|
-
//
|
|
308
|
+
// URL patterns
|
|
309
309
|
const urlPatterns = [
|
|
310
310
|
/"(https?:\/\/[^"]+)"/,
|
|
311
311
|
/'(https?:\/\/[^']+)'/,
|
|
@@ -323,7 +323,7 @@ export class JavaIntegrationAnalyzer {
|
|
|
323
323
|
}
|
|
324
324
|
|
|
325
325
|
/**
|
|
326
|
-
*
|
|
326
|
+
* Extracts the HTTP method from the call
|
|
327
327
|
*/
|
|
328
328
|
extractHttpMethod(snippet) {
|
|
329
329
|
if (/getFor|\.get\(/i.test(snippet)) return 'GET';
|
|
@@ -6,14 +6,14 @@ import { run } from '../../utils/exec-utils.js';
|
|
|
6
6
|
/**
|
|
7
7
|
* MavenRuntime
|
|
8
8
|
*
|
|
9
|
-
* Runtime
|
|
10
|
-
*
|
|
9
|
+
* Runtime for Java projects using Maven.
|
|
10
|
+
* Supports Spring Boot, Quarkus, and generic Maven projects.
|
|
11
11
|
*/
|
|
12
12
|
export class MavenRuntime extends BaseRuntime {
|
|
13
13
|
|
|
14
14
|
constructor() {
|
|
15
15
|
super();
|
|
16
|
-
this.framework = null; //
|
|
16
|
+
this.framework = null; // Detected dynamically
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
// ==========================================
|
|
@@ -53,16 +53,16 @@ export class MavenRuntime extends BaseRuntime {
|
|
|
53
53
|
const pomPath = path.join(workspacePath, 'pom.xml');
|
|
54
54
|
const pomContent = await readFile(pomPath, 'utf8');
|
|
55
55
|
|
|
56
|
-
//
|
|
56
|
+
// Basic parsing of pom.xml
|
|
57
57
|
const name = this.extractXmlValue(pomContent, 'artifactId') ||
|
|
58
58
|
path.basename(workspacePath);
|
|
59
59
|
const version = this.extractXmlValue(pomContent, 'version') || '0.0.1';
|
|
60
60
|
|
|
61
|
-
//
|
|
61
|
+
// Detect the framework
|
|
62
62
|
const framework = this.detectFramework(pomContent);
|
|
63
63
|
this.framework = framework;
|
|
64
64
|
|
|
65
|
-
//
|
|
65
|
+
// Detect the port
|
|
66
66
|
const port = await this.detectPort(workspacePath);
|
|
67
67
|
|
|
68
68
|
return {
|
|
@@ -93,11 +93,11 @@ export class MavenRuntime extends BaseRuntime {
|
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
/**
|
|
96
|
-
*
|
|
97
|
-
*
|
|
96
|
+
* Extracts an XML value ignoring the <parent> block
|
|
97
|
+
* This is needed because <parent> has its own artifactId/version
|
|
98
98
|
*/
|
|
99
99
|
extractXmlValue(xml, tag) {
|
|
100
|
-
// Remove
|
|
100
|
+
// Remove the <parent>...</parent> block so we do not pick parent values
|
|
101
101
|
const xmlWithoutParent = xml.replace(/<parent>[\s\S]*?<\/parent>/gi, '');
|
|
102
102
|
|
|
103
103
|
const regex = new RegExp(`<${tag}>([^<]+)</${tag}>`);
|
|
@@ -136,22 +136,22 @@ export class MavenRuntime extends BaseRuntime {
|
|
|
136
136
|
|
|
137
137
|
getStartCommand(options = {}) {
|
|
138
138
|
const framework = options.framework || this.framework || 'spring-boot';
|
|
139
|
-
const port = options.port; //
|
|
139
|
+
const port = options.port; // May be undefined if no override is needed
|
|
140
140
|
const profile = options.profile || 'default';
|
|
141
141
|
|
|
142
142
|
if (framework === 'spring-boot') {
|
|
143
143
|
const args = [
|
|
144
144
|
'spring-boot:run',
|
|
145
|
-
'-Dspring-boot.run.fork=false' //
|
|
145
|
+
'-Dspring-boot.run.fork=false' // Keeps Java in the same process
|
|
146
146
|
];
|
|
147
147
|
|
|
148
|
-
//
|
|
149
|
-
//
|
|
148
|
+
// Only add the port if it was explicitly provided
|
|
149
|
+
// If the project already has a port in application.yml, no need
|
|
150
150
|
if (port) {
|
|
151
151
|
args.push(`-Dspring-boot.run.arguments=--server.port=${port}`);
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
//
|
|
154
|
+
// Active profile
|
|
155
155
|
if (profile !== 'default') {
|
|
156
156
|
args.push(`-Dspring.profiles.active=${profile}`);
|
|
157
157
|
}
|
|
@@ -177,7 +177,7 @@ export class MavenRuntime extends BaseRuntime {
|
|
|
177
177
|
};
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
-
//
|
|
180
|
+
// Generic fallback
|
|
181
181
|
return {
|
|
182
182
|
cmd: 'mvn',
|
|
183
183
|
args: ['exec:java', '-q'],
|
|
@@ -203,7 +203,7 @@ export class MavenRuntime extends BaseRuntime {
|
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
async detectPort(workspacePath) {
|
|
206
|
-
//
|
|
206
|
+
// Try application.properties
|
|
207
207
|
const propsPath = path.join(workspacePath, 'src/main/resources/application.properties');
|
|
208
208
|
if (await exists(propsPath)) {
|
|
209
209
|
const content = await readFile(propsPath, 'utf8');
|
|
@@ -211,7 +211,7 @@ export class MavenRuntime extends BaseRuntime {
|
|
|
211
211
|
if (port) return port;
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
-
//
|
|
214
|
+
// Try application.yml
|
|
215
215
|
const ymlPath = path.join(workspacePath, 'src/main/resources/application.yml');
|
|
216
216
|
if (await exists(ymlPath)) {
|
|
217
217
|
const content = await readFile(ymlPath, 'utf8');
|
|
@@ -219,7 +219,7 @@ export class MavenRuntime extends BaseRuntime {
|
|
|
219
219
|
if (port) return port;
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
-
//
|
|
222
|
+
// Try application.yaml
|
|
223
223
|
const yamlPath = path.join(workspacePath, 'src/main/resources/application.yaml');
|
|
224
224
|
if (await exists(yamlPath)) {
|
|
225
225
|
const content = await readFile(yamlPath, 'utf8');
|
|
@@ -231,15 +231,15 @@ export class MavenRuntime extends BaseRuntime {
|
|
|
231
231
|
}
|
|
232
232
|
|
|
233
233
|
/**
|
|
234
|
-
*
|
|
235
|
-
*
|
|
234
|
+
* Extracts the port from application.properties
|
|
235
|
+
* Supports: server.port=8090 or server.port=${PORT:8090}
|
|
236
236
|
*/
|
|
237
237
|
extractPortFromProperties(content) {
|
|
238
|
-
//
|
|
238
|
+
// First try: server.port=8090
|
|
239
239
|
let match = content.match(/server\.port\s*=\s*(\d+)/);
|
|
240
240
|
if (match) return parseInt(match[1]);
|
|
241
241
|
|
|
242
|
-
//
|
|
242
|
+
// Then try: server.port=${PORT:8090} or ${SERVER_PORT:8090}
|
|
243
243
|
match = content.match(/server\.port\s*=\s*\$\{[^:}]+:(\d+)\}/);
|
|
244
244
|
if (match) return parseInt(match[1]);
|
|
245
245
|
|
|
@@ -247,15 +247,15 @@ export class MavenRuntime extends BaseRuntime {
|
|
|
247
247
|
}
|
|
248
248
|
|
|
249
249
|
/**
|
|
250
|
-
*
|
|
251
|
-
*
|
|
250
|
+
* Extracts the port from application.yml/yaml
|
|
251
|
+
* Supports: port: 8090 or port: ${PORT:8090}
|
|
252
252
|
*/
|
|
253
253
|
extractPortFromYaml(content) {
|
|
254
|
-
//
|
|
254
|
+
// First try: port: 8090
|
|
255
255
|
let match = content.match(/port:\s*(\d+)/);
|
|
256
256
|
if (match) return parseInt(match[1]);
|
|
257
257
|
|
|
258
|
-
//
|
|
258
|
+
// Then try: port: ${PORT:8090} or port: ${SERVER_PORT:8090}
|
|
259
259
|
match = content.match(/port:\s*\$\{[^:}]+:(\d+)\}/);
|
|
260
260
|
if (match) return parseInt(match[1]);
|
|
261
261
|
|
|
@@ -269,10 +269,10 @@ export class MavenRuntime extends BaseRuntime {
|
|
|
269
269
|
async test(workspacePath, options = {}) {
|
|
270
270
|
const startTime = Date.now();
|
|
271
271
|
|
|
272
|
-
// Clean
|
|
272
|
+
// Clean first
|
|
273
273
|
await run('mvn', ['clean', '-q'], workspacePath);
|
|
274
274
|
|
|
275
|
-
//
|
|
275
|
+
// Run the tests
|
|
276
276
|
const result = await run('mvn', ['test', '-q'], workspacePath);
|
|
277
277
|
|
|
278
278
|
const testResult = this.parseTestOutput(result);
|
|
@@ -284,7 +284,7 @@ export class MavenRuntime extends BaseRuntime {
|
|
|
284
284
|
async testSingle(workspacePath, testFile) {
|
|
285
285
|
const startTime = Date.now();
|
|
286
286
|
|
|
287
|
-
//
|
|
287
|
+
// Extract the class name from the path
|
|
288
288
|
const className = path.basename(testFile, '.java');
|
|
289
289
|
|
|
290
290
|
const result = await run('mvn', [
|
|
@@ -302,7 +302,7 @@ export class MavenRuntime extends BaseRuntime {
|
|
|
302
302
|
parseTestOutput(result) {
|
|
303
303
|
const output = result.stdout + result.stderr;
|
|
304
304
|
|
|
305
|
-
//
|
|
305
|
+
// Try to parse the Surefire/JUnit output
|
|
306
306
|
const testsRunMatch = output.match(/Tests run: (\d+)/);
|
|
307
307
|
const failuresMatch = output.match(/Failures: (\d+)/);
|
|
308
308
|
const errorsMatch = output.match(/Errors: (\d+)/);
|
|
@@ -387,17 +387,17 @@ export class MavenRuntime extends BaseRuntime {
|
|
|
387
387
|
// ==========================================
|
|
388
388
|
|
|
389
389
|
async validatePatch(workspacePath, diff) {
|
|
390
|
-
//
|
|
390
|
+
// Validate whether the files exist
|
|
391
391
|
const errors = [];
|
|
392
392
|
|
|
393
|
-
//
|
|
393
|
+
// Extract the files from the diff
|
|
394
394
|
const fileRegex = /^[\+\-]{3}\s+[ab]\/(.+)$/gm;
|
|
395
395
|
let match;
|
|
396
396
|
|
|
397
397
|
while ((match = fileRegex.exec(diff)) !== null) {
|
|
398
398
|
const filePath = path.join(workspacePath, match[1]);
|
|
399
399
|
if (match[0].startsWith('---') && !(await exists(filePath))) {
|
|
400
|
-
//
|
|
400
|
+
// The file being modified does not exist
|
|
401
401
|
if (!diff.includes('+++ /dev/null')) {
|
|
402
402
|
errors.push(`File not found: ${match[1]}`);
|
|
403
403
|
}
|
|
@@ -411,7 +411,7 @@ export class MavenRuntime extends BaseRuntime {
|
|
|
411
411
|
}
|
|
412
412
|
|
|
413
413
|
async postPatchActions(workspacePath, modifiedFiles) {
|
|
414
|
-
//
|
|
414
|
+
// Optional: run a formatter after the patch
|
|
415
415
|
// await run('mvn', ['formatter:format', '-q'], workspacePath);
|
|
416
416
|
}
|
|
417
417
|
}
|
|
@@ -4,7 +4,7 @@ import { readFile, readdir } from '../../utils/fs-utils.js';
|
|
|
4
4
|
/**
|
|
5
5
|
* NodeIntegrationAnalyzer
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* Analyzes Node.js/TypeScript code to find HTTP integrations:
|
|
8
8
|
* - axios
|
|
9
9
|
* - fetch / node-fetch
|
|
10
10
|
* - got
|
|
@@ -6,8 +6,8 @@ import { run } from '../../utils/exec-utils.js';
|
|
|
6
6
|
/**
|
|
7
7
|
* NpmRuntime
|
|
8
8
|
*
|
|
9
|
-
* Runtime
|
|
10
|
-
*
|
|
9
|
+
* Runtime for Node.js projects using npm.
|
|
10
|
+
* Supports Express, NestJS, Next.js, React, Vue, etc.
|
|
11
11
|
*/
|
|
12
12
|
export class NpmRuntime extends BaseRuntime {
|
|
13
13
|
|
|
@@ -49,7 +49,7 @@ export class NpmRuntime extends BaseRuntime {
|
|
|
49
49
|
const pkgPath = path.join(workspacePath, 'package.json');
|
|
50
50
|
const yarnLock = path.join(workspacePath, 'yarn.lock');
|
|
51
51
|
|
|
52
|
-
//
|
|
52
|
+
// If there is a yarn.lock, prefer YarnRuntime
|
|
53
53
|
if (await exists(yarnLock)) {
|
|
54
54
|
return false;
|
|
55
55
|
}
|
|
@@ -65,11 +65,11 @@ export class NpmRuntime extends BaseRuntime {
|
|
|
65
65
|
const name = this.packageJson.name || path.basename(workspacePath);
|
|
66
66
|
const version = this.packageJson.version || '0.0.1';
|
|
67
67
|
|
|
68
|
-
//
|
|
68
|
+
// Detect the framework
|
|
69
69
|
const framework = this.detectFramework(this.packageJson);
|
|
70
70
|
this.framework = framework;
|
|
71
71
|
|
|
72
|
-
//
|
|
72
|
+
// Detect the port
|
|
73
73
|
const port = await this.detectPort(workspacePath);
|
|
74
74
|
|
|
75
75
|
return {
|
|
@@ -103,7 +103,7 @@ export class NpmRuntime extends BaseRuntime {
|
|
|
103
103
|
if (deps['koa']) return 'koa';
|
|
104
104
|
if (deps['hapi'] || deps['@hapi/hapi']) return 'hapi';
|
|
105
105
|
|
|
106
|
-
//
|
|
106
|
+
// Other tools
|
|
107
107
|
if (deps['electron']) return 'electron';
|
|
108
108
|
|
|
109
109
|
return 'node-plain';
|
|
@@ -135,7 +135,7 @@ export class NpmRuntime extends BaseRuntime {
|
|
|
135
135
|
async build(workspacePath, options = {}) {
|
|
136
136
|
const startTime = Date.now();
|
|
137
137
|
|
|
138
|
-
//
|
|
138
|
+
// Check whether a build script exists
|
|
139
139
|
if (!this.packageJson?.scripts?.build) {
|
|
140
140
|
return {
|
|
141
141
|
code: 0,
|
|
@@ -157,7 +157,7 @@ export class NpmRuntime extends BaseRuntime {
|
|
|
157
157
|
const framework = options.framework || this.framework || 'node-plain';
|
|
158
158
|
const port = options.port || 3000;
|
|
159
159
|
|
|
160
|
-
//
|
|
160
|
+
// Framework-specific commands
|
|
161
161
|
const commands = {
|
|
162
162
|
'next': {
|
|
163
163
|
cmd: 'npm',
|
|
@@ -239,7 +239,7 @@ export class NpmRuntime extends BaseRuntime {
|
|
|
239
239
|
}
|
|
240
240
|
|
|
241
241
|
async detectPort(workspacePath) {
|
|
242
|
-
//
|
|
242
|
+
// Try .env
|
|
243
243
|
const envPath = path.join(workspacePath, '.env');
|
|
244
244
|
if (await exists(envPath)) {
|
|
245
245
|
const content = await readFile(envPath, 'utf8');
|
|
@@ -247,7 +247,7 @@ export class NpmRuntime extends BaseRuntime {
|
|
|
247
247
|
if (match) return parseInt(match[1]);
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
-
//
|
|
250
|
+
// Try .env.local
|
|
251
251
|
const envLocalPath = path.join(workspacePath, '.env.local');
|
|
252
252
|
if (await exists(envLocalPath)) {
|
|
253
253
|
const content = await readFile(envLocalPath, 'utf8');
|
|
@@ -255,7 +255,7 @@ export class NpmRuntime extends BaseRuntime {
|
|
|
255
255
|
if (match) return parseInt(match[1]);
|
|
256
256
|
}
|
|
257
257
|
|
|
258
|
-
//
|
|
258
|
+
// For Next.js, check next.config.js
|
|
259
259
|
if (this.framework === 'next') {
|
|
260
260
|
const nextConfigPath = path.join(workspacePath, 'next.config.js');
|
|
261
261
|
if (await exists(nextConfigPath)) {
|
|
@@ -275,7 +275,7 @@ export class NpmRuntime extends BaseRuntime {
|
|
|
275
275
|
async test(workspacePath, options = {}) {
|
|
276
276
|
const startTime = Date.now();
|
|
277
277
|
|
|
278
|
-
//
|
|
278
|
+
// Check whether a test script exists
|
|
279
279
|
if (!this.packageJson?.scripts?.test) {
|
|
280
280
|
return {
|
|
281
281
|
success: true,
|
|
@@ -299,7 +299,7 @@ export class NpmRuntime extends BaseRuntime {
|
|
|
299
299
|
async testSingle(workspacePath, testFile) {
|
|
300
300
|
const startTime = Date.now();
|
|
301
301
|
|
|
302
|
-
//
|
|
302
|
+
// Detect the test runner
|
|
303
303
|
const deps = {
|
|
304
304
|
...this.packageJson?.dependencies,
|
|
305
305
|
...this.packageJson?.devDependencies
|
|
@@ -449,7 +449,7 @@ export class NpmRuntime extends BaseRuntime {
|
|
|
449
449
|
}
|
|
450
450
|
|
|
451
451
|
async postPatchActions(workspacePath, modifiedFiles) {
|
|
452
|
-
//
|
|
452
|
+
// Run prettier if available
|
|
453
453
|
const deps = {
|
|
454
454
|
...this.packageJson?.dependencies,
|
|
455
455
|
...this.packageJson?.devDependencies
|
|
@@ -6,8 +6,8 @@ import { run } from '../../utils/exec-utils.js';
|
|
|
6
6
|
/**
|
|
7
7
|
* YarnRuntime
|
|
8
8
|
*
|
|
9
|
-
* Runtime
|
|
10
|
-
*
|
|
9
|
+
* Runtime for Node.js projects using Yarn.
|
|
10
|
+
* Supports Express, NestJS, Next.js, React, Vue, etc.
|
|
11
11
|
*/
|
|
12
12
|
export class YarnRuntime extends BaseRuntime {
|
|
13
13
|
|
|
@@ -15,7 +15,7 @@ export class YarnRuntime extends BaseRuntime {
|
|
|
15
15
|
super();
|
|
16
16
|
this.framework = null;
|
|
17
17
|
this.packageJson = null;
|
|
18
|
-
this.yarnVersion = 1; // 1
|
|
18
|
+
this.yarnVersion = 1; // 1 or 2+
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
// ==========================================
|
|
@@ -56,7 +56,7 @@ export class YarnRuntime extends BaseRuntime {
|
|
|
56
56
|
const content = await readFile(pkgPath, 'utf8');
|
|
57
57
|
this.packageJson = JSON.parse(content);
|
|
58
58
|
|
|
59
|
-
//
|
|
59
|
+
// Detect the Yarn version
|
|
60
60
|
const yarnrcPath = path.join(workspacePath, '.yarnrc.yml');
|
|
61
61
|
if (await exists(yarnrcPath)) {
|
|
62
62
|
this.yarnVersion = 2;
|