deepdebug-local-agent 0.3.8 → 0.3.9

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.
@@ -0,0 +1,176 @@
1
+ // Adicionar no server.js do Local Agent
2
+
3
+ /**
4
+ * GET /workspace/detect-port
5
+ *
6
+ * Detecta porta de um serviço específico lendo arquivos de configuração
7
+ *
8
+ * Query params:
9
+ * - servicePath: caminho relativo do serviço
10
+ * - language: linguagem do serviço
11
+ * - framework: framework do serviço
12
+ */
13
+ app.get("/workspace/detect-port", async (req, res) => {
14
+ if (!WORKSPACE_ROOT) {
15
+ return res.status(400).json({
16
+ error: "workspace not set",
17
+ hint: "call POST /workspace/open first"
18
+ });
19
+ }
20
+
21
+ const { servicePath, language, framework } = req.query;
22
+
23
+ if (!servicePath) {
24
+ return res.status(400).json({ error: "servicePath is required" });
25
+ }
26
+
27
+ try {
28
+ const fullPath = path.join(WORKSPACE_ROOT, servicePath);
29
+
30
+ console.log(`🔍 Detecting port for service at: ${fullPath}`);
31
+
32
+ let port = null;
33
+
34
+ // Detectar porta baseado na linguagem/framework
35
+ if (language === 'java' && framework === 'spring-boot') {
36
+ port = await detectSpringBootPort(fullPath);
37
+ } else if (language === 'node') {
38
+ port = await detectNodePort(fullPath);
39
+ } else if (language === 'python') {
40
+ port = await detectPythonPort(fullPath);
41
+ } else if (language === 'dotnet') {
42
+ port = await detectDotNetPort(fullPath);
43
+ }
44
+
45
+ console.log(`✅ Detected port: ${port || 'default'}`);
46
+
47
+ res.json({ port });
48
+ } catch (err) {
49
+ console.error('❌ Error detecting port:', err);
50
+ res.status(500).json({ error: err.message });
51
+ }
52
+ });
53
+
54
+ /**
55
+ * Detecta porta do Spring Boot
56
+ */
57
+ async function detectSpringBootPort(servicePath) {
58
+ const candidates = [
59
+ path.join(servicePath, 'src/main/resources/application.yml'),
60
+ path.join(servicePath, 'src/main/resources/application.yaml'),
61
+ path.join(servicePath, 'src/main/resources/application.properties'),
62
+ path.join(servicePath, 'application.yml'),
63
+ path.join(servicePath, 'application.yaml'),
64
+ path.join(servicePath, 'application.properties')
65
+ ];
66
+
67
+ for (const filePath of candidates) {
68
+ if (await exists(filePath)) {
69
+ console.log(`📄 Reading config: ${filePath}`);
70
+ const content = await readFile(filePath, 'utf8');
71
+
72
+ // YAML
73
+ if (filePath.endsWith('.yml') || filePath.endsWith('.yaml')) {
74
+ const match = content.match(/server:\s+port:\s*(\d+)/);
75
+ if (match) {
76
+ console.log(`✓ Found port in YAML: ${match[1]}`);
77
+ return parseInt(match[1]);
78
+ }
79
+ }
80
+
81
+ // Properties
82
+ if (filePath.endsWith('.properties')) {
83
+ const match = content.match(/server\.port\s*=\s*(\d+)/);
84
+ if (match) {
85
+ console.log(`✓ Found port in Properties: ${match[1]}`);
86
+ return parseInt(match[1]);
87
+ }
88
+ }
89
+ }
90
+ }
91
+
92
+ console.log('⚠️ No port config found, using default: 8080');
93
+ return 8080; // Default Spring Boot
94
+ }
95
+
96
+ /**
97
+ * Detecta porta do Node.js
98
+ */
99
+ async function detectNodePort(servicePath) {
100
+ // Tentar .env
101
+ const envPath = path.join(servicePath, '.env');
102
+ if (await exists(envPath)) {
103
+ const content = await readFile(envPath, 'utf8');
104
+ const match = content.match(/PORT\s*=\s*(\d+)/i);
105
+ if (match) {
106
+ console.log(`✓ Found port in .env: ${match[1]}`);
107
+ return parseInt(match[1]);
108
+ }
109
+ }
110
+
111
+ // Tentar package.json scripts
112
+ const pkgPath = path.join(servicePath, 'package.json');
113
+ if (await exists(pkgPath)) {
114
+ const content = await readFile(pkgPath, 'utf8');
115
+ const pkg = JSON.parse(content);
116
+
117
+ // Procurar por --port ou PORT= nos scripts
118
+ const scripts = JSON.stringify(pkg.scripts || {});
119
+ const match = scripts.match(/--port[=\s]+(\d+)|PORT[=\s]+(\d+)/i);
120
+ if (match) {
121
+ const port = parseInt(match[1] || match[2]);
122
+ console.log(`✓ Found port in package.json: ${port}`);
123
+ return port;
124
+ }
125
+ }
126
+
127
+ console.log('⚠️ No port config found, using default: 3000');
128
+ return 3000; // Default Node
129
+ }
130
+
131
+ /**
132
+ * Detecta porta do Python
133
+ */
134
+ async function detectPythonPort(servicePath) {
135
+ // Tentar .env
136
+ const envPath = path.join(servicePath, '.env');
137
+ if (await exists(envPath)) {
138
+ const content = await readFile(envPath, 'utf8');
139
+ const match = content.match(/PORT\s*=\s*(\d+)/i);
140
+ if (match) {
141
+ console.log(`✓ Found port in .env: ${match[1]}`);
142
+ return parseInt(match[1]);
143
+ }
144
+ }
145
+
146
+ // Defaults por framework
147
+ console.log('⚠️ No port config found, using framework default');
148
+ return 8000; // Default Django/FastAPI
149
+ }
150
+
151
+ /**
152
+ * Detecta porta do .NET
153
+ */
154
+ async function detectDotNetPort(servicePath) {
155
+ const launchSettings = path.join(servicePath, 'Properties/launchSettings.json');
156
+
157
+ if (await exists(launchSettings)) {
158
+ const content = await readFile(launchSettings, 'utf8');
159
+ const settings = JSON.parse(content);
160
+
161
+ // Procurar em profiles
162
+ const profiles = settings.profiles || {};
163
+ for (const profile of Object.values(profiles)) {
164
+ if (profile.applicationUrl) {
165
+ const match = profile.applicationUrl.match(/:(\d+)/);
166
+ if (match) {
167
+ console.log(`✓ Found port in launchSettings: ${match[1]}`);
168
+ return parseInt(match[1]);
169
+ }
170
+ }
171
+ }
172
+ }
173
+
174
+ console.log('⚠️ No port config found, using default: 5000');
175
+ return 5000; // Default .NET
176
+ }
@@ -0,0 +1,54 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+
4
+ export class FileReader {
5
+ constructor(rootPath) {
6
+ this.rootPath = rootPath;
7
+ this.ignorePatterns = ['node_modules', 'target', '.git', 'build', 'dist'];
8
+ }
9
+
10
+ async read(relativePath) {
11
+ const fullPath = path.join(this.rootPath, relativePath);
12
+
13
+ // Validação de segurança - previne path traversal
14
+ if (!fullPath.startsWith(this.rootPath)) {
15
+ throw new Error('Path traversal detected');
16
+ }
17
+
18
+ const content = await fs.readFile(fullPath, 'utf8');
19
+ return {
20
+ path: relativePath,
21
+ content,
22
+ lines: content.split('\n').length,
23
+ size: Buffer.byteLength(content, 'utf8')
24
+ };
25
+ }
26
+
27
+ async readMultiple(paths) {
28
+ return Promise.all(paths.map(p => this.read(p)));
29
+ }
30
+
31
+ async findByPattern(pattern) {
32
+ const allFiles = await this.getAllFiles();
33
+ return allFiles.filter(f => pattern.test(f));
34
+ }
35
+
36
+ async getAllFiles(dir = this.rootPath) {
37
+ const files = [];
38
+ const entries = await fs.readdir(dir, { withFileTypes: true });
39
+
40
+ for (const entry of entries) {
41
+ const fullPath = path.join(dir, entry.name);
42
+ if (entry.isDirectory() && !this.shouldIgnore(entry.name)) {
43
+ files.push(...await this.getAllFiles(fullPath));
44
+ } else if (entry.isFile()) {
45
+ files.push(path.relative(this.rootPath, fullPath));
46
+ }
47
+ }
48
+ return files;
49
+ }
50
+
51
+ shouldIgnore(name) {
52
+ return this.ignorePatterns.includes(name);
53
+ }
54
+ }
File without changes