deepdebug-local-agent 0.3.1

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 (50) hide show
  1. package/.dockerignore +24 -0
  2. package/.idea/deepdebug-local-agent.iml +12 -0
  3. package/.idea/modules.xml +8 -0
  4. package/.idea/vcs.xml +6 -0
  5. package/Dockerfile +46 -0
  6. package/cloudbuild.yaml +42 -0
  7. package/index.js +42 -0
  8. package/mcp-server.js +533 -0
  9. package/package.json +22 -0
  10. package/src/ai-engine.js +861 -0
  11. package/src/analyzers/config-analyzer.js +446 -0
  12. package/src/analyzers/controller-analyzer.js +429 -0
  13. package/src/analyzers/dto-analyzer.js +455 -0
  14. package/src/detectors/build-tool-detector.js +0 -0
  15. package/src/detectors/framework-detector.js +91 -0
  16. package/src/detectors/language-detector.js +89 -0
  17. package/src/detectors/multi-project-detector.js +191 -0
  18. package/src/detectors/service-detector.js +244 -0
  19. package/src/detectors.js +30 -0
  20. package/src/exec-utils.js +215 -0
  21. package/src/fs-utils.js +34 -0
  22. package/src/git/base-git-provider.js +384 -0
  23. package/src/git/git-provider-registry.js +110 -0
  24. package/src/git/github-provider.js +502 -0
  25. package/src/mcp-http-server.js +313 -0
  26. package/src/patch/patch-engine.js +339 -0
  27. package/src/patch-manager.js +816 -0
  28. package/src/patch.js +607 -0
  29. package/src/patch_bkp.js +154 -0
  30. package/src/ports.js +69 -0
  31. package/src/routes/workspace.route.js +528 -0
  32. package/src/runtimes/base-runtime.js +290 -0
  33. package/src/runtimes/java/gradle-runtime.js +378 -0
  34. package/src/runtimes/java/java-integrations.js +339 -0
  35. package/src/runtimes/java/maven-runtime.js +418 -0
  36. package/src/runtimes/node/node-integrations.js +247 -0
  37. package/src/runtimes/node/npm-runtime.js +466 -0
  38. package/src/runtimes/node/yarn-runtime.js +354 -0
  39. package/src/runtimes/runtime-registry.js +256 -0
  40. package/src/server-local.js +576 -0
  41. package/src/server.js +4565 -0
  42. package/src/utils/environment-diagnostics.js +666 -0
  43. package/src/utils/exec-utils.js +264 -0
  44. package/src/utils/fs-utils.js +218 -0
  45. package/src/workspace/detect-port.js +176 -0
  46. package/src/workspace/file-reader.js +54 -0
  47. package/src/workspace/git-client.js +0 -0
  48. package/src/workspace/process-manager.js +619 -0
  49. package/src/workspace/scanner.js +72 -0
  50. package/src/workspace-manager.js +172 -0
@@ -0,0 +1,34 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { promisify } from "util";
4
+
5
+ export const stat = promisify(fs.stat);
6
+ export const readdir = promisify(fs.readdir);
7
+ export const readFile = promisify(fs.readFile);
8
+ export const writeFile = promisify(fs.writeFile);
9
+ export const access = promisify(fs.access);
10
+
11
+ export async function exists(p) {
12
+ try { await access(p, fs.constants.F_OK); return true; }
13
+ catch { return false; }
14
+ }
15
+
16
+ export async function listRecursive(root, { maxFiles = 5000, includeHidden = false } = {}) {
17
+ const results = [];
18
+ async function walk(dir) {
19
+ const entries = await readdir(dir, { withFileTypes: true });
20
+ for (const e of entries) {
21
+ if (!includeHidden && e.name.startsWith(".")) continue;
22
+ const full = path.join(dir, e.name);
23
+ if (e.isDirectory()) {
24
+ results.push({ type: "dir", path: path.relative(root, full) });
25
+ await walk(full);
26
+ } else {
27
+ results.push({ type: "file", path: path.relative(root, full) });
28
+ if (results.length >= maxFiles) return;
29
+ }
30
+ }
31
+ }
32
+ await walk(root);
33
+ return results;
34
+ }
@@ -0,0 +1,384 @@
1
+ /**
2
+ * BaseGitProvider
3
+ *
4
+ * Interface abstrata para Git providers (GitHub, GitLab, Bitbucket).
5
+ * Cada provider deve implementar esta interface.
6
+ *
7
+ * @abstract
8
+ */
9
+ export class BaseGitProvider {
10
+
11
+ constructor(config = {}) {
12
+ if (this.constructor === BaseGitProvider) {
13
+ throw new Error('BaseGitProvider is abstract and cannot be instantiated directly');
14
+ }
15
+
16
+ this.config = config;
17
+ this.accessToken = config.accessToken || null;
18
+ }
19
+
20
+ // ==========================================
21
+ // IDENTIFICATION
22
+ // ==========================================
23
+
24
+ /**
25
+ * Identificador único do provider
26
+ * @returns {string} Ex: 'github', 'gitlab', 'bitbucket'
27
+ */
28
+ getId() {
29
+ throw new Error('Method getId() must be implemented');
30
+ }
31
+
32
+ /**
33
+ * Nome amigável do provider
34
+ * @returns {string} Ex: 'GitHub', 'GitLab', 'Bitbucket'
35
+ */
36
+ getName() {
37
+ throw new Error('Method getName() must be implemented');
38
+ }
39
+
40
+ /**
41
+ * URL base da API
42
+ * @returns {string}
43
+ */
44
+ getApiBaseUrl() {
45
+ throw new Error('Method getApiBaseUrl() must be implemented');
46
+ }
47
+
48
+ // ==========================================
49
+ // AUTHENTICATION
50
+ // ==========================================
51
+
52
+ /**
53
+ * Define o token de acesso
54
+ * @param {string} token
55
+ */
56
+ setAccessToken(token) {
57
+ this.accessToken = token;
58
+ }
59
+
60
+ /**
61
+ * Retorna URL para OAuth authorization
62
+ * @param {string} redirectUri - URI de callback
63
+ * @param {string} state - State para CSRF protection
64
+ * @returns {string}
65
+ */
66
+ getAuthorizationUrl(redirectUri, state) {
67
+ throw new Error('Method getAuthorizationUrl() must be implemented');
68
+ }
69
+
70
+ /**
71
+ * Troca authorization code por access token
72
+ * @param {string} code - Authorization code
73
+ * @param {string} redirectUri - URI de callback
74
+ * @returns {Promise<TokenResponse>}
75
+ */
76
+ async exchangeCodeForToken(code, redirectUri) {
77
+ throw new Error('Method exchangeCodeForToken() must be implemented');
78
+ }
79
+
80
+ /**
81
+ * Valida se o token ainda é válido
82
+ * @returns {Promise<boolean>}
83
+ */
84
+ async validateToken() {
85
+ throw new Error('Method validateToken() must be implemented');
86
+ }
87
+
88
+ // ==========================================
89
+ // USER
90
+ // ==========================================
91
+
92
+ /**
93
+ * Obtém informações do usuário autenticado
94
+ * @returns {Promise<UserInfo>}
95
+ */
96
+ async getCurrentUser() {
97
+ throw new Error('Method getCurrentUser() must be implemented');
98
+ }
99
+
100
+ // ==========================================
101
+ // REPOSITORIES
102
+ // ==========================================
103
+
104
+ /**
105
+ * Lista repositórios do usuário
106
+ * @param {object} options - { page, perPage, sort }
107
+ * @returns {Promise<Repository[]>}
108
+ */
109
+ async listRepositories(options = {}) {
110
+ throw new Error('Method listRepositories() must be implemented');
111
+ }
112
+
113
+ /**
114
+ * Obtém informações de um repositório
115
+ * @param {string} owner - Owner do repo
116
+ * @param {string} repo - Nome do repo
117
+ * @returns {Promise<Repository>}
118
+ */
119
+ async getRepository(owner, repo) {
120
+ throw new Error('Method getRepository() must be implemented');
121
+ }
122
+
123
+ /**
124
+ * Clona um repositório
125
+ * @param {string} owner - Owner do repo
126
+ * @param {string} repo - Nome do repo
127
+ * @param {string} destPath - Caminho de destino
128
+ * @param {object} options - { branch, depth }
129
+ * @returns {Promise<CloneResult>}
130
+ */
131
+ async cloneRepository(owner, repo, destPath, options = {}) {
132
+ throw new Error('Method cloneRepository() must be implemented');
133
+ }
134
+
135
+ // ==========================================
136
+ // BRANCHES
137
+ // ==========================================
138
+
139
+ /**
140
+ * Lista branches do repositório
141
+ * @param {string} owner - Owner do repo
142
+ * @param {string} repo - Nome do repo
143
+ * @returns {Promise<Branch[]>}
144
+ */
145
+ async listBranches(owner, repo) {
146
+ throw new Error('Method listBranches() must be implemented');
147
+ }
148
+
149
+ /**
150
+ * Cria uma nova branch
151
+ * @param {string} owner - Owner do repo
152
+ * @param {string} repo - Nome do repo
153
+ * @param {string} branchName - Nome da nova branch
154
+ * @param {string} fromRef - Ref de origem (sha ou branch)
155
+ * @returns {Promise<Branch>}
156
+ */
157
+ async createBranch(owner, repo, branchName, fromRef) {
158
+ throw new Error('Method createBranch() must be implemented');
159
+ }
160
+
161
+ /**
162
+ * Obtém informações de uma branch
163
+ * @param {string} owner - Owner do repo
164
+ * @param {string} repo - Nome do repo
165
+ * @param {string} branch - Nome da branch
166
+ * @returns {Promise<Branch>}
167
+ */
168
+ async getBranch(owner, repo, branch) {
169
+ throw new Error('Method getBranch() must be implemented');
170
+ }
171
+
172
+ // ==========================================
173
+ // COMMITS
174
+ // ==========================================
175
+
176
+ /**
177
+ * Lista commits de uma branch
178
+ * @param {string} owner - Owner do repo
179
+ * @param {string} repo - Nome do repo
180
+ * @param {string} branch - Nome da branch
181
+ * @param {object} options - { page, perPage }
182
+ * @returns {Promise<Commit[]>}
183
+ */
184
+ async listCommits(owner, repo, branch, options = {}) {
185
+ throw new Error('Method listCommits() must be implemented');
186
+ }
187
+
188
+ /**
189
+ * Cria um commit com mudanças
190
+ * @param {string} owner - Owner do repo
191
+ * @param {string} repo - Nome do repo
192
+ * @param {string} branch - Nome da branch
193
+ * @param {string} message - Mensagem do commit
194
+ * @param {FileChange[]} changes - Lista de mudanças
195
+ * @returns {Promise<Commit>}
196
+ */
197
+ async createCommit(owner, repo, branch, message, changes) {
198
+ throw new Error('Method createCommit() must be implemented');
199
+ }
200
+
201
+ // ==========================================
202
+ // FILES
203
+ // ==========================================
204
+
205
+ /**
206
+ * Obtém conteúdo de um arquivo
207
+ * @param {string} owner - Owner do repo
208
+ * @param {string} repo - Nome do repo
209
+ * @param {string} path - Caminho do arquivo
210
+ * @param {string} ref - Branch ou sha
211
+ * @returns {Promise<FileContent>}
212
+ */
213
+ async getFileContent(owner, repo, path, ref = 'main') {
214
+ throw new Error('Method getFileContent() must be implemented');
215
+ }
216
+
217
+ /**
218
+ * Cria ou atualiza um arquivo
219
+ * @param {string} owner - Owner do repo
220
+ * @param {string} repo - Nome do repo
221
+ * @param {string} path - Caminho do arquivo
222
+ * @param {string} content - Conteúdo (base64 ou texto)
223
+ * @param {string} message - Mensagem do commit
224
+ * @param {string} branch - Branch
225
+ * @param {string} sha - SHA atual (para update)
226
+ * @returns {Promise<FileCommit>}
227
+ */
228
+ async createOrUpdateFile(owner, repo, path, content, message, branch, sha = null) {
229
+ throw new Error('Method createOrUpdateFile() must be implemented');
230
+ }
231
+
232
+ // ==========================================
233
+ // PULL REQUESTS
234
+ // ==========================================
235
+
236
+ /**
237
+ * Lista pull requests
238
+ * @param {string} owner - Owner do repo
239
+ * @param {string} repo - Nome do repo
240
+ * @param {object} options - { state, page, perPage }
241
+ * @returns {Promise<PullRequest[]>}
242
+ */
243
+ async listPullRequests(owner, repo, options = {}) {
244
+ throw new Error('Method listPullRequests() must be implemented');
245
+ }
246
+
247
+ /**
248
+ * Cria um pull request
249
+ * @param {string} owner - Owner do repo
250
+ * @param {string} repo - Nome do repo
251
+ * @param {object} pr - { title, body, head, base }
252
+ * @returns {Promise<PullRequest>}
253
+ */
254
+ async createPullRequest(owner, repo, pr) {
255
+ throw new Error('Method createPullRequest() must be implemented');
256
+ }
257
+
258
+ /**
259
+ * Obtém informações de um pull request
260
+ * @param {string} owner - Owner do repo
261
+ * @param {string} repo - Nome do repo
262
+ * @param {number} prNumber - Número do PR
263
+ * @returns {Promise<PullRequest>}
264
+ */
265
+ async getPullRequest(owner, repo, prNumber) {
266
+ throw new Error('Method getPullRequest() must be implemented');
267
+ }
268
+
269
+ // ==========================================
270
+ // WEBHOOKS
271
+ // ==========================================
272
+
273
+ /**
274
+ * Cria um webhook
275
+ * @param {string} owner - Owner do repo
276
+ * @param {string} repo - Nome do repo
277
+ * @param {object} webhook - { url, events, secret }
278
+ * @returns {Promise<Webhook>}
279
+ */
280
+ async createWebhook(owner, repo, webhook) {
281
+ throw new Error('Method createWebhook() must be implemented');
282
+ }
283
+
284
+ // ==========================================
285
+ // HELPER METHODS
286
+ // ==========================================
287
+
288
+ /**
289
+ * Constrói URL de clone
290
+ * @param {string} owner - Owner do repo
291
+ * @param {string} repo - Nome do repo
292
+ * @param {boolean} useHttps - Usar HTTPS (default) ou SSH
293
+ * @returns {string}
294
+ */
295
+ getCloneUrl(owner, repo, useHttps = true) {
296
+ throw new Error('Method getCloneUrl() must be implemented');
297
+ }
298
+
299
+ /**
300
+ * Parsea URL de repositório para extrair owner e repo
301
+ * @param {string} url - URL do repositório
302
+ * @returns {{ owner: string, repo: string }}
303
+ */
304
+ parseRepositoryUrl(url) {
305
+ throw new Error('Method parseRepositoryUrl() must be implemented');
306
+ }
307
+ }
308
+
309
+ // ==========================================
310
+ // TYPE DEFINITIONS
311
+ // ==========================================
312
+
313
+ /**
314
+ * @typedef {object} TokenResponse
315
+ * @property {string} accessToken
316
+ * @property {string} tokenType
317
+ * @property {string} [refreshToken]
318
+ * @property {number} [expiresIn]
319
+ */
320
+
321
+ /**
322
+ * @typedef {object} UserInfo
323
+ * @property {string} id
324
+ * @property {string} username
325
+ * @property {string} email
326
+ * @property {string} name
327
+ * @property {string} avatarUrl
328
+ */
329
+
330
+ /**
331
+ * @typedef {object} Repository
332
+ * @property {string} id
333
+ * @property {string} name
334
+ * @property {string} fullName
335
+ * @property {string} description
336
+ * @property {string} defaultBranch
337
+ * @property {boolean} private
338
+ * @property {string} cloneUrl
339
+ * @property {string} htmlUrl
340
+ */
341
+
342
+ /**
343
+ * @typedef {object} Branch
344
+ * @property {string} name
345
+ * @property {string} sha
346
+ * @property {boolean} protected
347
+ */
348
+
349
+ /**
350
+ * @typedef {object} Commit
351
+ * @property {string} sha
352
+ * @property {string} message
353
+ * @property {string} authorName
354
+ * @property {string} authorEmail
355
+ * @property {Date} date
356
+ */
357
+
358
+ /**
359
+ * @typedef {object} FileChange
360
+ * @property {string} path
361
+ * @property {string} content
362
+ * @property {string} action - 'create' | 'update' | 'delete'
363
+ */
364
+
365
+ /**
366
+ * @typedef {object} FileContent
367
+ * @property {string} path
368
+ * @property {string} content
369
+ * @property {string} sha
370
+ * @property {string} encoding
371
+ */
372
+
373
+ /**
374
+ * @typedef {object} PullRequest
375
+ * @property {number} number
376
+ * @property {string} title
377
+ * @property {string} body
378
+ * @property {string} state
379
+ * @property {string} head
380
+ * @property {string} base
381
+ * @property {string} htmlUrl
382
+ */
383
+
384
+ export default BaseGitProvider;
@@ -0,0 +1,110 @@
1
+ import { GitHubProvider } from './github-provider.js';
2
+
3
+ /**
4
+ * GitProviderRegistry
5
+ *
6
+ * Factory/Registry para gerenciar Git providers.
7
+ */
8
+ export class GitProviderRegistry {
9
+
10
+ constructor() {
11
+ this.providers = new Map();
12
+ this.registerDefaults();
13
+ }
14
+
15
+ registerDefaults() {
16
+ // Registrar providers disponíveis
17
+ this.register('github', GitHubProvider);
18
+
19
+ // GitLab e Bitbucket serão implementados depois
20
+ // this.register('gitlab', GitLabProvider);
21
+ // this.register('bitbucket', BitbucketProvider);
22
+ }
23
+
24
+ /**
25
+ * Registra um provider
26
+ * @param {string} id - ID do provider
27
+ * @param {class} ProviderClass - Classe do provider
28
+ */
29
+ register(id, ProviderClass) {
30
+ this.providers.set(id, ProviderClass);
31
+ console.log(`📦 Registered git provider: ${id}`);
32
+ }
33
+
34
+ /**
35
+ * Cria instância de um provider
36
+ * @param {string} id - ID do provider
37
+ * @param {object} config - Configuração do provider
38
+ * @returns {BaseGitProvider}
39
+ */
40
+ create(id, config = {}) {
41
+ const ProviderClass = this.providers.get(id);
42
+
43
+ if (!ProviderClass) {
44
+ throw new Error(`Git provider not found: ${id}`);
45
+ }
46
+
47
+ return new ProviderClass(config);
48
+ }
49
+
50
+ /**
51
+ * Lista IDs dos providers disponíveis
52
+ * @returns {string[]}
53
+ */
54
+ listProviders() {
55
+ return Array.from(this.providers.keys());
56
+ }
57
+
58
+ /**
59
+ * Detecta provider a partir da URL
60
+ * @param {string} url - URL do repositório
61
+ * @returns {string|null} - ID do provider
62
+ */
63
+ detectProviderFromUrl(url) {
64
+ if (url.includes('github.com')) {
65
+ return 'github';
66
+ }
67
+ if (url.includes('gitlab.com') || url.includes('gitlab')) {
68
+ return 'gitlab';
69
+ }
70
+ if (url.includes('bitbucket.org') || url.includes('bitbucket')) {
71
+ return 'bitbucket';
72
+ }
73
+ return null;
74
+ }
75
+
76
+ /**
77
+ * Cria provider a partir da URL do repositório
78
+ * @param {string} url - URL do repositório
79
+ * @param {object} config - Configuração
80
+ * @returns {BaseGitProvider}
81
+ */
82
+ createFromUrl(url, config = {}) {
83
+ const providerId = this.detectProviderFromUrl(url);
84
+
85
+ if (!providerId) {
86
+ throw new Error(`Unable to detect git provider from URL: ${url}`);
87
+ }
88
+
89
+ return this.create(providerId, config);
90
+ }
91
+ }
92
+
93
+ // ==========================================
94
+ // SINGLETON INSTANCE
95
+ // ==========================================
96
+
97
+ let instance = null;
98
+
99
+ /**
100
+ * Obtém instância singleton do GitProviderRegistry
101
+ * @returns {GitProviderRegistry}
102
+ */
103
+ export function getGitProviderRegistry() {
104
+ if (!instance) {
105
+ instance = new GitProviderRegistry();
106
+ }
107
+ return instance;
108
+ }
109
+
110
+ export default GitProviderRegistry;