@justmpm/ai-tool 0.9.2 → 1.0.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/dist/chunk-35SMNOXI.js +252 -0
- package/dist/{chunk-6ZWPDZDS.js → chunk-LC7H7LGY.js} +444 -262
- package/dist/cli.js +3 -3
- package/dist/index.d.ts +51 -1
- package/dist/index.js +7 -1
- package/dist/{server-CMKKGDE4.js → server-DN6J3SYB.js} +120 -48
- package/package.json +1 -1
- package/dist/chunk-2ONTJF3R.js +0 -145
|
@@ -143,8 +143,235 @@ function isCodeFile(filePath) {
|
|
|
143
143
|
return CODE_EXTENSIONS.some((ext) => filePath.endsWith(ext));
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
// src/utils/hints.ts
|
|
147
|
+
var COMMAND_MAP = {
|
|
148
|
+
map: {
|
|
149
|
+
cli: "ai-tool map",
|
|
150
|
+
mcp: "analyze__aitool_project_map"
|
|
151
|
+
},
|
|
152
|
+
dead: {
|
|
153
|
+
cli: "ai-tool dead",
|
|
154
|
+
mcp: "analyze__aitool_dead_code"
|
|
155
|
+
},
|
|
156
|
+
impact: {
|
|
157
|
+
cli: "ai-tool impact <arquivo>",
|
|
158
|
+
mcp: "analyze__aitool_impact_analysis { target: '<arquivo>' }"
|
|
159
|
+
},
|
|
160
|
+
suggest: {
|
|
161
|
+
cli: "ai-tool suggest <arquivo>",
|
|
162
|
+
mcp: "analyze__aitool_suggest_reads { target: '<arquivo>' }"
|
|
163
|
+
},
|
|
164
|
+
context: {
|
|
165
|
+
cli: "ai-tool context <arquivo>",
|
|
166
|
+
mcp: "analyze__aitool_file_context { target: '<arquivo>' }"
|
|
167
|
+
},
|
|
168
|
+
area_context: {
|
|
169
|
+
cli: "ai-tool context --area=<nome>",
|
|
170
|
+
mcp: "analyze__aitool_area_context { area: '<nome>' }"
|
|
171
|
+
},
|
|
172
|
+
areas: {
|
|
173
|
+
cli: "ai-tool areas",
|
|
174
|
+
mcp: "analyze__aitool_list_areas"
|
|
175
|
+
},
|
|
176
|
+
area: {
|
|
177
|
+
cli: "ai-tool area <nome>",
|
|
178
|
+
mcp: "analyze__aitool_area_detail { target: '<nome>' }"
|
|
179
|
+
},
|
|
180
|
+
areas_init: {
|
|
181
|
+
cli: "ai-tool areas init",
|
|
182
|
+
mcp: "analyze__aitool_areas_init"
|
|
183
|
+
},
|
|
184
|
+
find: {
|
|
185
|
+
cli: "ai-tool find <termo>",
|
|
186
|
+
mcp: "analyze__aitool_find { query: '<termo>' }"
|
|
187
|
+
},
|
|
188
|
+
describe: {
|
|
189
|
+
cli: "ai-tool describe <termo>",
|
|
190
|
+
mcp: "analyze__aitool_describe { query: '<termo>' }"
|
|
191
|
+
},
|
|
192
|
+
functions: {
|
|
193
|
+
cli: "ai-tool functions",
|
|
194
|
+
mcp: "analyze__aitool_list_functions"
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
function hint(command, ctx, params) {
|
|
198
|
+
const mapping = COMMAND_MAP[command];
|
|
199
|
+
if (!mapping) return command;
|
|
200
|
+
let instruction = mapping[ctx];
|
|
201
|
+
if (params) {
|
|
202
|
+
for (const [placeholder, value] of Object.entries(params)) {
|
|
203
|
+
instruction = instruction.replaceAll(placeholder, value);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return instruction;
|
|
207
|
+
}
|
|
208
|
+
var NEXT_STEPS = {
|
|
209
|
+
map: [
|
|
210
|
+
{ command: "area", description: "ver arquivos de uma area" },
|
|
211
|
+
{ command: "suggest", description: "o que ler antes de editar" },
|
|
212
|
+
{ command: "context", description: "ver API de um arquivo" }
|
|
213
|
+
],
|
|
214
|
+
impact: [
|
|
215
|
+
{ command: "suggest", description: "o que ler antes de editar este arquivo" },
|
|
216
|
+
{ command: "context", description: "ver assinaturas dos arquivos upstream" },
|
|
217
|
+
{ command: "find", description: "localizar usos de exports especificos" }
|
|
218
|
+
],
|
|
219
|
+
suggest: [
|
|
220
|
+
{ command: "context", description: "ver assinaturas de cada arquivo sugerido" },
|
|
221
|
+
{ command: "impact", description: "ver impacto completo da mudanca" }
|
|
222
|
+
],
|
|
223
|
+
context: [
|
|
224
|
+
{ command: "impact", description: "ver quem sera afetado por mudancas" },
|
|
225
|
+
{ command: "find", description: "localizar usos de uma funcao ou tipo" },
|
|
226
|
+
{ command: "suggest", description: "o que ler antes de editar" }
|
|
227
|
+
],
|
|
228
|
+
area_context: [
|
|
229
|
+
{ command: "find", description: "buscar usos de simbolos desta area" },
|
|
230
|
+
{ command: "area", description: "ver lista de arquivos desta area" },
|
|
231
|
+
{ command: "impact", description: "ver impacto de modificar um arquivo" }
|
|
232
|
+
],
|
|
233
|
+
find: [
|
|
234
|
+
{ command: "context", description: "ver assinaturas completas do arquivo" },
|
|
235
|
+
{ command: "impact", description: "ver impacto de modificar o arquivo" },
|
|
236
|
+
{ command: "describe", description: "buscar areas por descricao" }
|
|
237
|
+
],
|
|
238
|
+
describe: [
|
|
239
|
+
{ command: "area", description: "ver detalhes de uma area" },
|
|
240
|
+
{ command: "area_context", description: "contexto completo de uma area" }
|
|
241
|
+
],
|
|
242
|
+
areas: [
|
|
243
|
+
{ command: "area", description: "ver arquivos de uma area especifica" },
|
|
244
|
+
{ command: "describe", description: "buscar areas por descricao" }
|
|
245
|
+
],
|
|
246
|
+
area: [
|
|
247
|
+
{ command: "area_context", description: "contexto consolidado (tipos, hooks, funcoes)" },
|
|
248
|
+
{ command: "context", description: "ver assinaturas de um arquivo especifico" },
|
|
249
|
+
{ command: "find", description: "buscar simbolos dentro da area" }
|
|
250
|
+
],
|
|
251
|
+
dead: [
|
|
252
|
+
{ command: "impact", description: "verificar se um arquivo morto e realmente nao usado" },
|
|
253
|
+
{ command: "map", description: "ver estrutura atualizada do projeto" }
|
|
254
|
+
],
|
|
255
|
+
functions: [
|
|
256
|
+
{ command: "find", description: "buscar uma Cloud Function especifica" },
|
|
257
|
+
{ command: "impact", description: "ver impacto de modificar uma function" },
|
|
258
|
+
{ command: "context", description: "ver assinaturas de uma function" }
|
|
259
|
+
]
|
|
260
|
+
};
|
|
261
|
+
function nextSteps(command, ctx) {
|
|
262
|
+
const steps = NEXT_STEPS[command];
|
|
263
|
+
if (!steps || steps.length === 0) return "";
|
|
264
|
+
let out = "\n\u{1F4D6} Proximos passos:\n";
|
|
265
|
+
for (const step of steps) {
|
|
266
|
+
const instruction = hint(step.command, ctx);
|
|
267
|
+
out += ` \u2192 ${instruction} - ${step.description}
|
|
268
|
+
`;
|
|
269
|
+
}
|
|
270
|
+
return out;
|
|
271
|
+
}
|
|
272
|
+
function recoveryHint(errorType, ctx, _extra) {
|
|
273
|
+
switch (errorType) {
|
|
274
|
+
case "file_not_found":
|
|
275
|
+
return `
|
|
276
|
+
\u{1F4A1} Dicas:
|
|
277
|
+
\u2192 ${hint("map", ctx)} - ver arquivos disponiveis
|
|
278
|
+
\u2192 ${hint("find", ctx)} - buscar por nome de simbolo
|
|
279
|
+
`;
|
|
280
|
+
case "area_not_found":
|
|
281
|
+
return `
|
|
282
|
+
\u{1F4A1} Dicas:
|
|
283
|
+
\u2192 ${hint("areas", ctx)} - listar areas disponiveis
|
|
284
|
+
\u2192 ${hint("describe", ctx)} - buscar areas por descricao
|
|
285
|
+
\u2192 ${hint("areas_init", ctx)} - gerar configuracao de areas
|
|
286
|
+
`;
|
|
287
|
+
case "no_results":
|
|
288
|
+
return `
|
|
289
|
+
\u{1F4A1} Dicas:
|
|
290
|
+
\u2192 ${hint("find", ctx)} - buscar com outro termo
|
|
291
|
+
\u2192 ${hint("describe", ctx)} - buscar areas por descricao
|
|
292
|
+
\u2192 ${hint("map", ctx)} - ver estrutura do projeto
|
|
293
|
+
`;
|
|
294
|
+
case "no_firebase":
|
|
295
|
+
return `
|
|
296
|
+
\u{1F4A1} Este projeto nao usa Firebase. Comandos disponiveis:
|
|
297
|
+
\u2192 ${hint("map", ctx)} - ver estrutura do projeto
|
|
298
|
+
\u2192 ${hint("find", ctx)} - buscar simbolos no codigo
|
|
299
|
+
\u2192 ${hint("areas", ctx)} - listar areas funcionais
|
|
300
|
+
`;
|
|
301
|
+
case "generic":
|
|
302
|
+
return `
|
|
303
|
+
\u{1F4A1} Tente:
|
|
304
|
+
\u2192 ${hint("map", ctx)} - verificar estrutura do projeto
|
|
305
|
+
\u2192 Verifique se o caminho (cwd) esta correto
|
|
306
|
+
`;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// src/utils/similarity.ts
|
|
311
|
+
function levenshteinDistance(a, b) {
|
|
312
|
+
const matrix = [];
|
|
313
|
+
for (let i = 0; i <= b.length; i++) {
|
|
314
|
+
matrix[i] = [i];
|
|
315
|
+
}
|
|
316
|
+
for (let j = 0; j <= a.length; j++) {
|
|
317
|
+
matrix[0][j] = j;
|
|
318
|
+
}
|
|
319
|
+
for (let i = 1; i <= b.length; i++) {
|
|
320
|
+
for (let j = 1; j <= a.length; j++) {
|
|
321
|
+
if (b.charAt(i - 1) === a.charAt(j - 1)) {
|
|
322
|
+
matrix[i][j] = matrix[i - 1][j - 1];
|
|
323
|
+
} else {
|
|
324
|
+
matrix[i][j] = Math.min(
|
|
325
|
+
matrix[i - 1][j - 1] + 1,
|
|
326
|
+
// substituição
|
|
327
|
+
matrix[i][j - 1] + 1,
|
|
328
|
+
// inserção
|
|
329
|
+
matrix[i - 1][j] + 1
|
|
330
|
+
// deleção
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
return matrix[b.length][a.length];
|
|
336
|
+
}
|
|
337
|
+
function findSimilar(target, candidates, options = {}) {
|
|
338
|
+
const {
|
|
339
|
+
maxDistance = 3,
|
|
340
|
+
limit = 5,
|
|
341
|
+
normalize: normalize2 = true,
|
|
342
|
+
extractKey = (item) => String(item)
|
|
343
|
+
} = options;
|
|
344
|
+
const normalizedTarget = normalize2 ? target.toLowerCase() : target;
|
|
345
|
+
const scored = candidates.map((item) => {
|
|
346
|
+
const key = extractKey(item);
|
|
347
|
+
const normalizedKey = normalize2 ? key.toLowerCase() : key;
|
|
348
|
+
const keyNoExt = normalizedKey.replace(/\.(tsx?|jsx?|mjs|cjs)$/, "");
|
|
349
|
+
let score = Infinity;
|
|
350
|
+
if (normalizedKey.includes(normalizedTarget) || keyNoExt.includes(normalizedTarget)) {
|
|
351
|
+
score = 0;
|
|
352
|
+
} else {
|
|
353
|
+
score = levenshteinDistance(keyNoExt, normalizedTarget);
|
|
354
|
+
}
|
|
355
|
+
return { item, score };
|
|
356
|
+
}).filter(({ score }) => score <= maxDistance).sort((a, b) => a.score - b.score).slice(0, limit);
|
|
357
|
+
return scored.map(({ item }) => item);
|
|
358
|
+
}
|
|
359
|
+
function findBestMatch(target, candidates, extractKey = (item) => String(item)) {
|
|
360
|
+
const similar = findSimilar(target, candidates, {
|
|
361
|
+
maxDistance: 2,
|
|
362
|
+
// Mais restritivo para "você quis dizer"
|
|
363
|
+
limit: 1,
|
|
364
|
+
extractKey
|
|
365
|
+
});
|
|
366
|
+
return similar.length > 0 ? similar[0] : null;
|
|
367
|
+
}
|
|
368
|
+
function extractFileName(filePath) {
|
|
369
|
+
const fileName = filePath.split("/").pop() || filePath;
|
|
370
|
+
return fileName.replace(/\.(tsx?|jsx?|mjs|cjs)$/, "");
|
|
371
|
+
}
|
|
372
|
+
|
|
146
373
|
// src/formatters/text.ts
|
|
147
|
-
function formatMapSummary(result, areasInfo) {
|
|
374
|
+
function formatMapSummary(result, areasInfo, ctx = "cli") {
|
|
148
375
|
let out = "";
|
|
149
376
|
out += `\u{1F4CA} ${result.summary.totalFiles} arquivos | ${result.summary.totalFolders} pastas
|
|
150
377
|
`;
|
|
@@ -172,9 +399,15 @@ function formatMapSummary(result, areasInfo) {
|
|
|
172
399
|
}
|
|
173
400
|
out += ` ${catParts.join(", ")}
|
|
174
401
|
`;
|
|
402
|
+
const topFolders = result.folders.sort((a, b) => b.fileCount - a.fileCount).slice(0, 5);
|
|
403
|
+
if (topFolders.length > 0) {
|
|
404
|
+
const folderParts = topFolders.map((f) => `${f.path}/ (${f.fileCount})`);
|
|
405
|
+
out += `\u{1F4C1} ${folderParts.join(", ")}
|
|
406
|
+
`;
|
|
407
|
+
}
|
|
175
408
|
if (areasInfo && areasInfo.total > 0) {
|
|
176
409
|
out += `
|
|
177
|
-
\u{1F5C2}\uFE0F
|
|
410
|
+
\u{1F5C2}\uFE0F Areas: ${areasInfo.names.join(", ")}
|
|
178
411
|
`;
|
|
179
412
|
}
|
|
180
413
|
out += `
|
|
@@ -185,43 +418,30 @@ function formatMapSummary(result, areasInfo) {
|
|
|
185
418
|
`;
|
|
186
419
|
out += ` ${cloudFunctionCount} function(s) em functions/src/
|
|
187
420
|
`;
|
|
188
|
-
out += ` \u2192
|
|
421
|
+
out += ` \u2192 ${hint("functions", ctx)}
|
|
189
422
|
|
|
190
423
|
`;
|
|
191
424
|
}
|
|
192
425
|
if (result.circularDependencies.length > 0) {
|
|
193
|
-
out += `\u26A0\uFE0F ${result.circularDependencies.length}
|
|
426
|
+
out += `\u26A0\uFE0F ${result.circularDependencies.length} dependencia(s) circular(es) detectada(s)
|
|
194
427
|
`;
|
|
195
|
-
out += ` \u2192
|
|
428
|
+
out += ` \u2192 ${hint("impact", ctx)} para investigar
|
|
196
429
|
|
|
197
430
|
`;
|
|
198
431
|
}
|
|
199
432
|
if (areasInfo && areasInfo.unmappedCount > 0) {
|
|
200
|
-
out += `\u26A0\uFE0F ${areasInfo.unmappedCount} arquivo(s) sem
|
|
433
|
+
out += `\u26A0\uFE0F ${areasInfo.unmappedCount} arquivo(s) sem area definida
|
|
201
434
|
`;
|
|
202
|
-
out += ` \u2192
|
|
435
|
+
out += ` \u2192 ${hint("areas_init", ctx)} para configurar
|
|
203
436
|
|
|
204
437
|
`;
|
|
205
438
|
}
|
|
206
|
-
out +=
|
|
207
|
-
`;
|
|
208
|
-
out += ` \u2192 area <nome> - ver arquivos de uma \xE1rea
|
|
209
|
-
`;
|
|
210
|
-
out += ` \u2192 suggest <arquivo> - o que ler antes de editar
|
|
211
|
-
`;
|
|
212
|
-
out += ` \u2192 context <arquivo> - ver API de um arquivo
|
|
213
|
-
`;
|
|
439
|
+
out += nextSteps("map", ctx);
|
|
214
440
|
return out;
|
|
215
441
|
}
|
|
216
|
-
function formatMapText(result) {
|
|
442
|
+
function formatMapText(result, ctx = "cli") {
|
|
217
443
|
let out = "";
|
|
218
|
-
out +=
|
|
219
|
-
`;
|
|
220
|
-
out += `\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
221
|
-
`;
|
|
222
|
-
out += `\u2551 \u{1F4C1} PROJECT MAP \u2551
|
|
223
|
-
`;
|
|
224
|
-
out += `\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
444
|
+
out += `## \u{1F4C1} PROJECT MAP
|
|
225
445
|
|
|
226
446
|
`;
|
|
227
447
|
out += `\u{1F4CA} RESUMO
|
|
@@ -230,7 +450,7 @@ function formatMapText(result) {
|
|
|
230
450
|
`;
|
|
231
451
|
out += ` Pastas: ${result.summary.totalFolders}
|
|
232
452
|
`;
|
|
233
|
-
out += `
|
|
453
|
+
out += ` Diretorio: ${result.cwd}
|
|
234
454
|
|
|
235
455
|
`;
|
|
236
456
|
out += `\u{1F4C2} CATEGORIAS
|
|
@@ -272,7 +492,7 @@ function formatMapText(result) {
|
|
|
272
492
|
}
|
|
273
493
|
if (result.circularDependencies.length > 0) {
|
|
274
494
|
out += `
|
|
275
|
-
\u26A0\uFE0F
|
|
495
|
+
\u26A0\uFE0F DEPENDENCIAS CIRCULARES (${result.circularDependencies.length})
|
|
276
496
|
`;
|
|
277
497
|
for (const cycle of result.circularDependencies.slice(0, 5)) {
|
|
278
498
|
out += ` ${cycle.join(" \u2192 ")}
|
|
@@ -283,41 +503,37 @@ function formatMapText(result) {
|
|
|
283
503
|
`;
|
|
284
504
|
}
|
|
285
505
|
}
|
|
506
|
+
out += nextSteps("map", ctx);
|
|
286
507
|
return out;
|
|
287
508
|
}
|
|
288
|
-
function formatDeadText(result) {
|
|
509
|
+
function formatDeadText(result, ctx = "cli") {
|
|
289
510
|
let out = "";
|
|
290
|
-
out +=
|
|
291
|
-
`;
|
|
292
|
-
out += `\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
293
|
-
`;
|
|
294
|
-
out += `\u2551 \u{1F480} DEAD CODE \u2551
|
|
295
|
-
`;
|
|
296
|
-
out += `\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
511
|
+
out += `## \u{1F480} DEAD CODE
|
|
297
512
|
|
|
298
513
|
`;
|
|
299
514
|
if (result.summary.totalDead === 0) {
|
|
300
|
-
out += `\u2705 Nenhum
|
|
515
|
+
out += `\u2705 Nenhum codigo morto encontrado!
|
|
301
516
|
`;
|
|
302
|
-
out += ` Todos os arquivos e exports
|
|
517
|
+
out += ` Todos os arquivos e exports estao sendo utilizados.
|
|
303
518
|
`;
|
|
519
|
+
out += nextSteps("dead", ctx);
|
|
304
520
|
return out;
|
|
305
521
|
}
|
|
306
522
|
out += `\u{1F4CA} RESUMO
|
|
307
523
|
`;
|
|
308
|
-
out += ` Total: ${result.summary.totalDead} itens
|
|
524
|
+
out += ` Total: ${result.summary.totalDead} itens nao utilizados
|
|
309
525
|
`;
|
|
310
|
-
out += ` Arquivos
|
|
526
|
+
out += ` Arquivos orfaos: ${result.summary.byType.files}
|
|
311
527
|
`;
|
|
312
|
-
out += ` Exports
|
|
528
|
+
out += ` Exports nao usados: ${result.summary.byType.exports}
|
|
313
529
|
`;
|
|
314
|
-
out += `
|
|
530
|
+
out += ` Dependencias nao usadas: ${result.summary.byType.dependencies}
|
|
315
531
|
|
|
316
532
|
`;
|
|
317
533
|
if (result.files.length > 0) {
|
|
318
|
-
out += `\u{1F5D1}\uFE0F ARQUIVOS
|
|
534
|
+
out += `\u{1F5D1}\uFE0F ARQUIVOS ORFAOS (${result.files.length})
|
|
319
535
|
`;
|
|
320
|
-
out += ` Arquivos que
|
|
536
|
+
out += ` Arquivos que ninguem importa:
|
|
321
537
|
|
|
322
538
|
`;
|
|
323
539
|
const byCategory = /* @__PURE__ */ new Map();
|
|
@@ -344,7 +560,7 @@ function formatDeadText(result) {
|
|
|
344
560
|
}
|
|
345
561
|
}
|
|
346
562
|
if (result.exports.length > 0) {
|
|
347
|
-
out += `\u{1F4E4} EXPORTS
|
|
563
|
+
out += `\u{1F4E4} EXPORTS NAO USADOS (${result.exports.length})
|
|
348
564
|
`;
|
|
349
565
|
for (const exp of result.exports.slice(0, 10)) {
|
|
350
566
|
out += ` ${exp.file}: ${exp.export}
|
|
@@ -358,7 +574,7 @@ function formatDeadText(result) {
|
|
|
358
574
|
`;
|
|
359
575
|
}
|
|
360
576
|
if (result.dependencies.length > 0) {
|
|
361
|
-
out += `\u{1F4E6}
|
|
577
|
+
out += `\u{1F4E6} DEPENDENCIAS NAO USADAS (${result.dependencies.length})
|
|
362
578
|
`;
|
|
363
579
|
for (const dep of result.dependencies) {
|
|
364
580
|
out += ` ${dep}
|
|
@@ -394,12 +610,12 @@ function formatDeadText(result) {
|
|
|
394
610
|
`;
|
|
395
611
|
out += ` 3. Ver detalhes em JSON:
|
|
396
612
|
`;
|
|
397
|
-
out += `
|
|
613
|
+
out += ` ${hint("dead", ctx)} --format=json
|
|
398
614
|
`;
|
|
399
615
|
const suggestions = generateIgnoreSuggestions(result);
|
|
400
616
|
if (suggestions.length > 0) {
|
|
401
617
|
out += `
|
|
402
|
-
\u{1F3AF}
|
|
618
|
+
\u{1F3AF} SUGESTOES INTELIGENTES
|
|
403
619
|
|
|
404
620
|
`;
|
|
405
621
|
for (const suggestion of suggestions) {
|
|
@@ -412,6 +628,7 @@ function formatDeadText(result) {
|
|
|
412
628
|
`;
|
|
413
629
|
}
|
|
414
630
|
}
|
|
631
|
+
out += nextSteps("dead", ctx);
|
|
415
632
|
return out;
|
|
416
633
|
}
|
|
417
634
|
function generateIgnoreSuggestions(result) {
|
|
@@ -431,7 +648,7 @@ function generateIgnoreSuggestions(result) {
|
|
|
431
648
|
suggestions.push({
|
|
432
649
|
icon: "\u{1F9EA}",
|
|
433
650
|
pattern: "**/*.(test|spec).(ts|tsx|js|jsx)",
|
|
434
|
-
reason: "Arquivos de teste geralmente
|
|
651
|
+
reason: "Arquivos de teste geralmente sao entry points proprios",
|
|
435
652
|
count: testFiles.length
|
|
436
653
|
});
|
|
437
654
|
}
|
|
@@ -442,7 +659,7 @@ function generateIgnoreSuggestions(result) {
|
|
|
442
659
|
suggestions.push({
|
|
443
660
|
icon: "\u2699\uFE0F",
|
|
444
661
|
pattern: "**/*.config.(ts|js|mjs|cjs)",
|
|
445
|
-
reason: "Arquivos de
|
|
662
|
+
reason: "Arquivos de configuracao sao entry points",
|
|
446
663
|
count: configFiles.length
|
|
447
664
|
});
|
|
448
665
|
}
|
|
@@ -451,7 +668,7 @@ function generateIgnoreSuggestions(result) {
|
|
|
451
668
|
suggestions.push({
|
|
452
669
|
icon: "\u{1F4D8}",
|
|
453
670
|
pattern: "**/*.d.ts",
|
|
454
|
-
reason: "Arquivos de
|
|
671
|
+
reason: "Arquivos de definicao TypeScript",
|
|
455
672
|
count: dtsFiles.length
|
|
456
673
|
});
|
|
457
674
|
}
|
|
@@ -460,21 +677,15 @@ function generateIgnoreSuggestions(result) {
|
|
|
460
677
|
suggestions.push({
|
|
461
678
|
icon: "\u{1F4DC}",
|
|
462
679
|
pattern: "scripts/**",
|
|
463
|
-
reason: "Scripts de
|
|
680
|
+
reason: "Scripts de automacao sao entry points",
|
|
464
681
|
count: scriptFiles.length
|
|
465
682
|
});
|
|
466
683
|
}
|
|
467
684
|
return suggestions;
|
|
468
685
|
}
|
|
469
|
-
function formatImpactText(result) {
|
|
686
|
+
function formatImpactText(result, ctx = "cli") {
|
|
470
687
|
let out = "";
|
|
471
|
-
out +=
|
|
472
|
-
`;
|
|
473
|
-
out += `\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
474
|
-
`;
|
|
475
|
-
out += `\u2551 \u{1F3AF} IMPACT ANALYSIS \u2551
|
|
476
|
-
`;
|
|
477
|
-
out += `\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
688
|
+
out += `## \u{1F3AF} IMPACT ANALYSIS
|
|
478
689
|
|
|
479
690
|
`;
|
|
480
691
|
const icon = categoryIcons[result.category];
|
|
@@ -483,10 +694,7 @@ function formatImpactText(result) {
|
|
|
483
694
|
out += ` ${icon} ${result.category}
|
|
484
695
|
|
|
485
696
|
`;
|
|
486
|
-
out += `\
|
|
487
|
-
|
|
488
|
-
`;
|
|
489
|
-
out += `\u2B06\uFE0F USADO POR (${result.upstream.total} arquivo${result.upstream.total !== 1 ? "s" : ""} \xFAnico${result.upstream.total !== 1 ? "s" : ""})
|
|
697
|
+
out += `\u2B06\uFE0F USADO POR (${result.upstream.total} arquivo${result.upstream.total !== 1 ? "s" : ""} unico${result.upstream.total !== 1 ? "s" : ""})
|
|
490
698
|
`;
|
|
491
699
|
if (result.upstream.direct.length > 0 || result.upstream.indirect.length > 0) {
|
|
492
700
|
out += ` \u{1F4CD} ${result.upstream.direct.length} direto${result.upstream.direct.length !== 1 ? "s" : ""} + ${result.upstream.indirect.length} indireto${result.upstream.indirect.length !== 1 ? "s" : ""}
|
|
@@ -496,7 +704,7 @@ function formatImpactText(result) {
|
|
|
496
704
|
|
|
497
705
|
`;
|
|
498
706
|
if (result.upstream.total === 0) {
|
|
499
|
-
out += `
|
|
707
|
+
out += ` Ninguem importa este arquivo diretamente.
|
|
500
708
|
`;
|
|
501
709
|
} else {
|
|
502
710
|
for (const file of result.upstream.direct.slice(0, 10)) {
|
|
@@ -519,10 +727,8 @@ function formatImpactText(result) {
|
|
|
519
727
|
}
|
|
520
728
|
}
|
|
521
729
|
out += `
|
|
522
|
-
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
523
|
-
|
|
524
730
|
`;
|
|
525
|
-
out += `\u2B07\uFE0F
|
|
731
|
+
out += `\u2B07\uFE0F DEPENDENCIAS (${result.downstream.total} arquivo${result.downstream.total !== 1 ? "s" : ""} unico${result.downstream.total !== 1 ? "s" : ""})
|
|
526
732
|
`;
|
|
527
733
|
if (result.downstream.direct.length > 0 || result.downstream.indirect.length > 0) {
|
|
528
734
|
out += ` \u{1F4CD} ${result.downstream.direct.length} direto${result.downstream.direct.length !== 1 ? "s" : ""} + ${result.downstream.indirect.length} indireto${result.downstream.indirect.length !== 1 ? "s" : ""}
|
|
@@ -532,7 +738,7 @@ function formatImpactText(result) {
|
|
|
532
738
|
|
|
533
739
|
`;
|
|
534
740
|
if (result.downstream.total === 0) {
|
|
535
|
-
out += ` Este arquivo
|
|
741
|
+
out += ` Este arquivo nao importa nenhum arquivo local.
|
|
536
742
|
`;
|
|
537
743
|
} else {
|
|
538
744
|
for (const file of result.downstream.direct.slice(0, 10)) {
|
|
@@ -546,15 +752,13 @@ function formatImpactText(result) {
|
|
|
546
752
|
}
|
|
547
753
|
}
|
|
548
754
|
out += `
|
|
549
|
-
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
550
|
-
|
|
551
755
|
`;
|
|
552
|
-
out += `\u{1F4CA}
|
|
756
|
+
out += `\u{1F4CA} METRICAS DE IMPACTO
|
|
553
757
|
|
|
554
758
|
`;
|
|
555
|
-
out += ` Arquivos que importam este (upstream): ${result.upstream.total}
|
|
759
|
+
out += ` Arquivos que importam este (upstream): ${result.upstream.total} unico${result.upstream.total !== 1 ? "s" : ""}
|
|
556
760
|
`;
|
|
557
|
-
out += ` Arquivos que este importa (downstream): ${result.downstream.total}
|
|
761
|
+
out += ` Arquivos que este importa (downstream): ${result.downstream.total} unico${result.downstream.total !== 1 ? "s" : ""}
|
|
558
762
|
`;
|
|
559
763
|
if (result.risks.length > 0) {
|
|
560
764
|
out += `
|
|
@@ -569,7 +773,7 @@ function formatImpactText(result) {
|
|
|
569
773
|
}
|
|
570
774
|
if (result.suggestions.length > 0) {
|
|
571
775
|
out += `
|
|
572
|
-
\u{1F4A1}
|
|
776
|
+
\u{1F4A1} SUGESTOES
|
|
573
777
|
|
|
574
778
|
`;
|
|
575
779
|
for (const suggestion of result.suggestions) {
|
|
@@ -579,11 +783,11 @@ function formatImpactText(result) {
|
|
|
579
783
|
}
|
|
580
784
|
if (result.gitHistory && result.gitHistory.hasGitRepo) {
|
|
581
785
|
out += `
|
|
582
|
-
\u{1F4DC}
|
|
786
|
+
\u{1F4DC} HISTORICO GIT (ultimos ${result.gitHistory.recentCommits.length} commits)
|
|
583
787
|
|
|
584
788
|
`;
|
|
585
789
|
if (result.gitHistory.recentCommits.length === 0) {
|
|
586
|
-
out += ` Arquivo
|
|
790
|
+
out += ` Arquivo nao esta no repositorio Git ou sem historico.
|
|
587
791
|
`;
|
|
588
792
|
} else {
|
|
589
793
|
for (const commit of result.gitHistory.recentCommits) {
|
|
@@ -599,17 +803,12 @@ function formatImpactText(result) {
|
|
|
599
803
|
}
|
|
600
804
|
}
|
|
601
805
|
}
|
|
806
|
+
out += nextSteps("impact", ctx);
|
|
602
807
|
return out;
|
|
603
808
|
}
|
|
604
|
-
function formatSuggestText(result) {
|
|
809
|
+
function formatSuggestText(result, ctx = "cli") {
|
|
605
810
|
let out = "";
|
|
606
|
-
out +=
|
|
607
|
-
`;
|
|
608
|
-
out += `\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
609
|
-
`;
|
|
610
|
-
out += `\u2551 \u{1F4DA} SUGGEST \u2551
|
|
611
|
-
`;
|
|
612
|
-
out += `\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
811
|
+
out += `## \u{1F4DA} SUGGEST
|
|
613
812
|
|
|
614
813
|
`;
|
|
615
814
|
const icon = categoryIcons[result.category];
|
|
@@ -623,11 +822,9 @@ function formatSuggestText(result) {
|
|
|
623
822
|
`;
|
|
624
823
|
out += ` Este arquivo nao tem dependencias ou arquivos relacionados.
|
|
625
824
|
`;
|
|
825
|
+
out += nextSteps("suggest", ctx);
|
|
626
826
|
return out;
|
|
627
827
|
}
|
|
628
|
-
out += `\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
629
|
-
|
|
630
|
-
`;
|
|
631
828
|
const byPriority = {
|
|
632
829
|
critical: result.suggestions.filter((s) => s.priority === "critical"),
|
|
633
830
|
high: result.suggestions.filter((s) => s.priority === "high"),
|
|
@@ -698,9 +895,6 @@ function formatSuggestText(result) {
|
|
|
698
895
|
out += `
|
|
699
896
|
`;
|
|
700
897
|
}
|
|
701
|
-
out += `\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
702
|
-
|
|
703
|
-
`;
|
|
704
898
|
out += `\u{1F4CA} RESUMO
|
|
705
899
|
`;
|
|
706
900
|
out += ` Total de arquivos sugeridos: ${result.suggestions.length}
|
|
@@ -723,10 +917,7 @@ function formatSuggestText(result) {
|
|
|
723
917
|
}
|
|
724
918
|
if (result.testSuggestions.length > 0) {
|
|
725
919
|
out += `
|
|
726
|
-
\
|
|
727
|
-
|
|
728
|
-
`;
|
|
729
|
-
out += `\u{1F9EA} TESTES E VERIFICA\xC7\xD5ES
|
|
920
|
+
\u{1F9EA} TESTES E VERIFICACOES
|
|
730
921
|
|
|
731
922
|
`;
|
|
732
923
|
for (const testSuggestion of result.testSuggestions) {
|
|
@@ -734,17 +925,12 @@ function formatSuggestText(result) {
|
|
|
734
925
|
`;
|
|
735
926
|
}
|
|
736
927
|
}
|
|
928
|
+
out += nextSteps("suggest", ctx);
|
|
737
929
|
return out;
|
|
738
930
|
}
|
|
739
|
-
function formatContextText(result) {
|
|
931
|
+
function formatContextText(result, ctx = "cli") {
|
|
740
932
|
let out = "";
|
|
741
|
-
out +=
|
|
742
|
-
`;
|
|
743
|
-
out += `\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
744
|
-
`;
|
|
745
|
-
out += `\u2551 \u{1F4C4} CONTEXT \u2551
|
|
746
|
-
`;
|
|
747
|
-
out += `\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
933
|
+
out += `## \u{1F4C4} CONTEXT
|
|
748
934
|
|
|
749
935
|
`;
|
|
750
936
|
const icon = categoryIcons[result.category];
|
|
@@ -752,9 +938,6 @@ function formatContextText(result) {
|
|
|
752
938
|
`;
|
|
753
939
|
out += ` ${icon} ${result.category}
|
|
754
940
|
|
|
755
|
-
`;
|
|
756
|
-
out += `\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
757
|
-
|
|
758
941
|
`;
|
|
759
942
|
if (result.imports.length > 0) {
|
|
760
943
|
out += `\u{1F4E5} IMPORTS (${result.imports.length})
|
|
@@ -798,10 +981,10 @@ function formatContextText(result) {
|
|
|
798
981
|
`;
|
|
799
982
|
for (const fn of result.functions) {
|
|
800
983
|
const exported = fn.isExported ? "export " : "";
|
|
801
|
-
const
|
|
984
|
+
const asyncLabel = fn.isAsync ? "async " : "";
|
|
802
985
|
const arrow = fn.isArrowFunction ? " =>" : "";
|
|
803
986
|
const params = fn.params.map((p) => `${p.name}: ${p.type}`).join(", ");
|
|
804
|
-
out += ` ${exported}${
|
|
987
|
+
out += ` ${exported}${asyncLabel}${fn.name}(${params})${arrow}: ${fn.returnType}
|
|
805
988
|
`;
|
|
806
989
|
if (fn.jsdoc) {
|
|
807
990
|
out += ` /** ${fn.jsdoc} */
|
|
@@ -811,9 +994,18 @@ function formatContextText(result) {
|
|
|
811
994
|
`;
|
|
812
995
|
}
|
|
813
996
|
}
|
|
814
|
-
|
|
997
|
+
if (result.constants && result.constants.length > 0) {
|
|
998
|
+
out += `\u{1F4CC} CONSTANTS (${result.constants.length})
|
|
815
999
|
|
|
816
1000
|
`;
|
|
1001
|
+
for (const c of result.constants) {
|
|
1002
|
+
const exported = c.isExported ? "export " : "";
|
|
1003
|
+
out += ` ${exported}${c.name}: ${c.type}
|
|
1004
|
+
`;
|
|
1005
|
+
}
|
|
1006
|
+
out += `
|
|
1007
|
+
`;
|
|
1008
|
+
}
|
|
817
1009
|
out += `\u{1F4CA} RESUMO
|
|
818
1010
|
`;
|
|
819
1011
|
out += ` Imports: ${result.imports.length}
|
|
@@ -824,35 +1016,31 @@ function formatContextText(result) {
|
|
|
824
1016
|
`;
|
|
825
1017
|
out += ` Functions: ${result.functions.length}
|
|
826
1018
|
`;
|
|
1019
|
+
if (result.constants && result.constants.length > 0) {
|
|
1020
|
+
out += ` Constants: ${result.constants.length}
|
|
1021
|
+
`;
|
|
1022
|
+
}
|
|
1023
|
+
out += nextSteps("context", ctx);
|
|
827
1024
|
return out;
|
|
828
1025
|
}
|
|
829
|
-
function formatAreasText(result) {
|
|
1026
|
+
function formatAreasText(result, ctx = "cli") {
|
|
830
1027
|
let out = "";
|
|
831
|
-
out +=
|
|
832
|
-
`;
|
|
833
|
-
out += `\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
834
|
-
`;
|
|
835
|
-
out += `\u2551 \u{1F4E6} PROJECT AREAS \u2551
|
|
836
|
-
`;
|
|
837
|
-
out += `\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
1028
|
+
out += `## \u{1F4E6} PROJECT AREAS
|
|
838
1029
|
|
|
839
1030
|
`;
|
|
840
1031
|
out += `\u{1F4CA} RESUMO
|
|
841
1032
|
`;
|
|
842
|
-
out += `
|
|
1033
|
+
out += ` Areas: ${result.summary.totalAreas}
|
|
843
1034
|
`;
|
|
844
1035
|
out += ` Arquivos: ${result.summary.totalFiles}
|
|
845
1036
|
`;
|
|
846
1037
|
if (result.summary.unmappedCount > 0) {
|
|
847
|
-
out += ` \u26A0\uFE0F Sem
|
|
1038
|
+
out += ` \u26A0\uFE0F Sem area: ${result.summary.unmappedCount}
|
|
848
1039
|
`;
|
|
849
1040
|
}
|
|
850
1041
|
out += `
|
|
851
1042
|
`;
|
|
852
|
-
out += `\
|
|
853
|
-
|
|
854
|
-
`;
|
|
855
|
-
out += `\u{1F4E6} \xC1REAS DETECTADAS
|
|
1043
|
+
out += `\u{1F4E6} AREAS DETECTADAS
|
|
856
1044
|
|
|
857
1045
|
`;
|
|
858
1046
|
for (const area2 of result.areas) {
|
|
@@ -872,15 +1060,12 @@ function formatAreasText(result) {
|
|
|
872
1060
|
`;
|
|
873
1061
|
}
|
|
874
1062
|
if (result.unmapped.length > 0) {
|
|
875
|
-
out += `\
|
|
876
|
-
|
|
877
|
-
`;
|
|
878
|
-
out += `\u26A0\uFE0F ARQUIVOS SEM \xC1REA (${result.unmapped.length})
|
|
1063
|
+
out += `\u26A0\uFE0F ARQUIVOS SEM AREA (${result.unmapped.length})
|
|
879
1064
|
|
|
880
1065
|
`;
|
|
881
1066
|
for (const file of result.unmapped.slice(0, 10)) {
|
|
882
|
-
const
|
|
883
|
-
out += ` ${
|
|
1067
|
+
const fileIcon = categoryIcons[file.category];
|
|
1068
|
+
out += ` ${fileIcon} ${file.path}
|
|
884
1069
|
`;
|
|
885
1070
|
}
|
|
886
1071
|
if (result.unmapped.length > 10) {
|
|
@@ -888,32 +1073,19 @@ function formatAreasText(result) {
|
|
|
888
1073
|
`;
|
|
889
1074
|
}
|
|
890
1075
|
out += `
|
|
891
|
-
\u{1F4A1} Adicione
|
|
1076
|
+
\u{1F4A1} Adicione padroes em .analyze/areas.config.json
|
|
892
1077
|
`;
|
|
893
|
-
out += ` ou execute
|
|
1078
|
+
out += ` ou execute ${hint("areas_init", ctx)} para gerar configuracao
|
|
894
1079
|
`;
|
|
895
1080
|
}
|
|
896
|
-
out +=
|
|
897
|
-
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
898
|
-
|
|
899
|
-
`;
|
|
900
|
-
out += `\u{1F4A1} Use 'ai-tool area <nome>' para ver detalhes de uma \xE1rea
|
|
901
|
-
`;
|
|
902
|
-
out += ` Exemplo: ai-tool area auth
|
|
903
|
-
`;
|
|
1081
|
+
out += nextSteps("areas", ctx);
|
|
904
1082
|
return out;
|
|
905
1083
|
}
|
|
906
|
-
function formatAreaDetailText(result, options = {}) {
|
|
1084
|
+
function formatAreaDetailText(result, options = {}, ctx = "cli") {
|
|
907
1085
|
const { full = false, filterType } = options;
|
|
908
1086
|
const { area: area2, byCategory } = result;
|
|
909
1087
|
let out = "";
|
|
910
|
-
out +=
|
|
911
|
-
`;
|
|
912
|
-
out += `\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
913
|
-
`;
|
|
914
|
-
out += `\u2551 \u{1F4E6} AREA DETAIL \u2551
|
|
915
|
-
`;
|
|
916
|
-
out += `\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
1088
|
+
out += `## \u{1F4E6} AREA DETAIL
|
|
917
1089
|
|
|
918
1090
|
`;
|
|
919
1091
|
out += `\u{1F4E6} ${area2.name}
|
|
@@ -951,9 +1123,6 @@ function formatAreaDetailText(result, options = {}) {
|
|
|
951
1123
|
out += catParts.join(" ");
|
|
952
1124
|
out += `
|
|
953
1125
|
|
|
954
|
-
`;
|
|
955
|
-
out += `\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
956
|
-
|
|
957
1126
|
`;
|
|
958
1127
|
if (filterType) {
|
|
959
1128
|
const files = byCategory[filterType] || [];
|
|
@@ -965,6 +1134,7 @@ function formatAreaDetailText(result, options = {}) {
|
|
|
965
1134
|
out += ` ${file.path}${desc}
|
|
966
1135
|
`;
|
|
967
1136
|
}
|
|
1137
|
+
out += nextSteps("area", ctx);
|
|
968
1138
|
return out;
|
|
969
1139
|
}
|
|
970
1140
|
const maxFilesPerCategory = full ? 100 : 8;
|
|
@@ -996,17 +1166,12 @@ function formatAreaDetailText(result, options = {}) {
|
|
|
996
1166
|
out += `\u{1F4A1} Use --full para ver todos os arquivos
|
|
997
1167
|
`;
|
|
998
1168
|
}
|
|
1169
|
+
out += nextSteps("area", ctx);
|
|
999
1170
|
return out;
|
|
1000
1171
|
}
|
|
1001
|
-
function formatFindText(result) {
|
|
1172
|
+
function formatFindText(result, ctx = "cli", symbolNames) {
|
|
1002
1173
|
let out = "";
|
|
1003
|
-
out +=
|
|
1004
|
-
`;
|
|
1005
|
-
out += `\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
1006
|
-
`;
|
|
1007
|
-
out += `\u2551 \u{1F50D} FIND \u2551
|
|
1008
|
-
`;
|
|
1009
|
-
out += `\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
1174
|
+
out += `## \u{1F50D} FIND
|
|
1010
1175
|
|
|
1011
1176
|
`;
|
|
1012
1177
|
if (result.query) {
|
|
@@ -1021,7 +1186,7 @@ function formatFindText(result) {
|
|
|
1021
1186
|
|
|
1022
1187
|
`;
|
|
1023
1188
|
} else {
|
|
1024
|
-
out += `\u{1F4CB} Listando todos os
|
|
1189
|
+
out += `\u{1F4CB} Listando todos os simbolos do tipo: ${result.filters.type || "all"}
|
|
1025
1190
|
|
|
1026
1191
|
`;
|
|
1027
1192
|
}
|
|
@@ -1031,33 +1196,45 @@ function formatFindText(result) {
|
|
|
1031
1196
|
|
|
1032
1197
|
`;
|
|
1033
1198
|
} else {
|
|
1034
|
-
out += `\u274C Nenhum
|
|
1199
|
+
out += `\u274C Nenhum simbolo do tipo "${result.filters.type}" encontrado
|
|
1035
1200
|
|
|
1036
1201
|
`;
|
|
1037
1202
|
}
|
|
1203
|
+
if (symbolNames && symbolNames.length > 0 && result.query) {
|
|
1204
|
+
const similar = findSimilar(result.query, symbolNames, { maxDistance: 3, limit: 5 });
|
|
1205
|
+
if (similar.length > 0) {
|
|
1206
|
+
out += `\u{1F4A1} Voce quis dizer?
|
|
1207
|
+
`;
|
|
1208
|
+
for (const name of similar) {
|
|
1209
|
+
out += ` \u2192 ${hint("find", ctx, { "<termo>": name })}
|
|
1210
|
+
`;
|
|
1211
|
+
}
|
|
1212
|
+
out += `
|
|
1213
|
+
`;
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1038
1216
|
out += `\u{1F4A1} Dicas:
|
|
1039
1217
|
`;
|
|
1040
|
-
out += ` \
|
|
1218
|
+
out += ` \u2192 Verifique a ortografia
|
|
1041
1219
|
`;
|
|
1042
|
-
out += ` \
|
|
1220
|
+
out += ` \u2192 Tente buscar parte do nome
|
|
1043
1221
|
`;
|
|
1044
|
-
out += ` \
|
|
1222
|
+
out += ` \u2192 Remova filtros de tipo ou area
|
|
1223
|
+
`;
|
|
1224
|
+
out += ` \u2192 ${hint("describe", ctx)} - buscar areas por descricao
|
|
1045
1225
|
`;
|
|
1046
1226
|
return out;
|
|
1047
1227
|
}
|
|
1048
|
-
out += `\u{1F4CA} ${result.summary.definitions}
|
|
1049
|
-
|
|
1050
|
-
`;
|
|
1051
|
-
out += `\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
1228
|
+
out += `\u{1F4CA} ${result.summary.definitions} definicao, ${result.summary.references} referencias em ${result.summary.files} arquivos
|
|
1052
1229
|
|
|
1053
1230
|
`;
|
|
1054
1231
|
if (result.definition) {
|
|
1055
|
-
out += `\u{1F4CD}
|
|
1232
|
+
out += `\u{1F4CD} DEFINICAO
|
|
1056
1233
|
|
|
1057
1234
|
`;
|
|
1058
1235
|
const def = result.definition;
|
|
1059
|
-
const
|
|
1060
|
-
out += ` ${
|
|
1236
|
+
const defIcon = categoryIcons[def.category];
|
|
1237
|
+
out += ` ${defIcon} ${def.file}:${def.line}
|
|
1061
1238
|
`;
|
|
1062
1239
|
out += ` ${def.code}
|
|
1063
1240
|
`;
|
|
@@ -1072,8 +1249,8 @@ function formatFindText(result) {
|
|
|
1072
1249
|
|
|
1073
1250
|
`;
|
|
1074
1251
|
for (const ref of imports.slice(0, 10)) {
|
|
1075
|
-
const
|
|
1076
|
-
out += ` ${
|
|
1252
|
+
const refIcon = categoryIcons[ref.category];
|
|
1253
|
+
out += ` ${refIcon} ${ref.file}:${ref.line}
|
|
1077
1254
|
`;
|
|
1078
1255
|
out += ` ${ref.code}
|
|
1079
1256
|
`;
|
|
@@ -1090,8 +1267,8 @@ function formatFindText(result) {
|
|
|
1090
1267
|
|
|
1091
1268
|
`;
|
|
1092
1269
|
for (const ref of usages.slice(0, 15)) {
|
|
1093
|
-
const
|
|
1094
|
-
out += ` ${
|
|
1270
|
+
const refIcon = categoryIcons[ref.category];
|
|
1271
|
+
out += ` ${refIcon} ${ref.file}:${ref.line}
|
|
1095
1272
|
`;
|
|
1096
1273
|
out += ` ${ref.code}
|
|
1097
1274
|
`;
|
|
@@ -1106,15 +1283,9 @@ function formatFindText(result) {
|
|
|
1106
1283
|
}
|
|
1107
1284
|
return out;
|
|
1108
1285
|
}
|
|
1109
|
-
function formatAreaContextText(result) {
|
|
1286
|
+
function formatAreaContextText(result, ctx = "cli") {
|
|
1110
1287
|
let out = "";
|
|
1111
|
-
out +=
|
|
1112
|
-
`;
|
|
1113
|
-
out += `\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
1114
|
-
`;
|
|
1115
|
-
out += `\u2551 \u{1F4E6} AREA CONTEXT \u2551
|
|
1116
|
-
`;
|
|
1117
|
-
out += `\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
1288
|
+
out += `## \u{1F4E6} AREA CONTEXT
|
|
1118
1289
|
|
|
1119
1290
|
`;
|
|
1120
1291
|
out += `\u{1F4E6} ${result.area.name} - Contexto Consolidado (${result.area.fileCount} arquivos)
|
|
@@ -1124,9 +1295,6 @@ function formatAreaContextText(result) {
|
|
|
1124
1295
|
`;
|
|
1125
1296
|
}
|
|
1126
1297
|
out += `
|
|
1127
|
-
`;
|
|
1128
|
-
out += `\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
1129
|
-
|
|
1130
1298
|
`;
|
|
1131
1299
|
if (result.types.length > 0) {
|
|
1132
1300
|
out += `\u{1F3F7}\uFE0F TYPES (${result.types.length})
|
|
@@ -1232,9 +1400,6 @@ function formatAreaContextText(result) {
|
|
|
1232
1400
|
`;
|
|
1233
1401
|
}
|
|
1234
1402
|
}
|
|
1235
|
-
out += `\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
1236
|
-
|
|
1237
|
-
`;
|
|
1238
1403
|
out += `\u{1F4CA} RESUMO
|
|
1239
1404
|
`;
|
|
1240
1405
|
out += ` Types: ${result.types.length}
|
|
@@ -1253,6 +1418,7 @@ function formatAreaContextText(result) {
|
|
|
1253
1418
|
out += ` Triggers: ${result.triggers.length}
|
|
1254
1419
|
`;
|
|
1255
1420
|
}
|
|
1421
|
+
out += nextSteps("area_context", ctx);
|
|
1256
1422
|
return out;
|
|
1257
1423
|
}
|
|
1258
1424
|
|
|
@@ -2091,69 +2257,6 @@ ${output}`;
|
|
|
2091
2257
|
// src/commands/impact.ts
|
|
2092
2258
|
import skott2 from "skott";
|
|
2093
2259
|
|
|
2094
|
-
// src/utils/similarity.ts
|
|
2095
|
-
function levenshteinDistance(a, b) {
|
|
2096
|
-
const matrix = [];
|
|
2097
|
-
for (let i = 0; i <= b.length; i++) {
|
|
2098
|
-
matrix[i] = [i];
|
|
2099
|
-
}
|
|
2100
|
-
for (let j = 0; j <= a.length; j++) {
|
|
2101
|
-
matrix[0][j] = j;
|
|
2102
|
-
}
|
|
2103
|
-
for (let i = 1; i <= b.length; i++) {
|
|
2104
|
-
for (let j = 1; j <= a.length; j++) {
|
|
2105
|
-
if (b.charAt(i - 1) === a.charAt(j - 1)) {
|
|
2106
|
-
matrix[i][j] = matrix[i - 1][j - 1];
|
|
2107
|
-
} else {
|
|
2108
|
-
matrix[i][j] = Math.min(
|
|
2109
|
-
matrix[i - 1][j - 1] + 1,
|
|
2110
|
-
// substituição
|
|
2111
|
-
matrix[i][j - 1] + 1,
|
|
2112
|
-
// inserção
|
|
2113
|
-
matrix[i - 1][j] + 1
|
|
2114
|
-
// deleção
|
|
2115
|
-
);
|
|
2116
|
-
}
|
|
2117
|
-
}
|
|
2118
|
-
}
|
|
2119
|
-
return matrix[b.length][a.length];
|
|
2120
|
-
}
|
|
2121
|
-
function findSimilar(target, candidates, options = {}) {
|
|
2122
|
-
const {
|
|
2123
|
-
maxDistance = 3,
|
|
2124
|
-
limit = 5,
|
|
2125
|
-
normalize: normalize2 = true,
|
|
2126
|
-
extractKey = (item) => String(item)
|
|
2127
|
-
} = options;
|
|
2128
|
-
const normalizedTarget = normalize2 ? target.toLowerCase() : target;
|
|
2129
|
-
const scored = candidates.map((item) => {
|
|
2130
|
-
const key = extractKey(item);
|
|
2131
|
-
const normalizedKey = normalize2 ? key.toLowerCase() : key;
|
|
2132
|
-
const keyNoExt = normalizedKey.replace(/\.(tsx?|jsx?|mjs|cjs)$/, "");
|
|
2133
|
-
let score = Infinity;
|
|
2134
|
-
if (normalizedKey.includes(normalizedTarget) || keyNoExt.includes(normalizedTarget)) {
|
|
2135
|
-
score = 0;
|
|
2136
|
-
} else {
|
|
2137
|
-
score = levenshteinDistance(keyNoExt, normalizedTarget);
|
|
2138
|
-
}
|
|
2139
|
-
return { item, score };
|
|
2140
|
-
}).filter(({ score }) => score <= maxDistance).sort((a, b) => a.score - b.score).slice(0, limit);
|
|
2141
|
-
return scored.map(({ item }) => item);
|
|
2142
|
-
}
|
|
2143
|
-
function findBestMatch(target, candidates, extractKey = (item) => String(item)) {
|
|
2144
|
-
const similar = findSimilar(target, candidates, {
|
|
2145
|
-
maxDistance: 2,
|
|
2146
|
-
// Mais restritivo para "você quis dizer"
|
|
2147
|
-
limit: 1,
|
|
2148
|
-
extractKey
|
|
2149
|
-
});
|
|
2150
|
-
return similar.length > 0 ? similar[0] : null;
|
|
2151
|
-
}
|
|
2152
|
-
function extractFileName(filePath) {
|
|
2153
|
-
const fileName = filePath.split("/").pop() || filePath;
|
|
2154
|
-
return fileName.replace(/\.(tsx?|jsx?|mjs|cjs)$/, "");
|
|
2155
|
-
}
|
|
2156
|
-
|
|
2157
2260
|
// src/utils/errors.ts
|
|
2158
2261
|
var COMMAND_REFERENCE = {
|
|
2159
2262
|
map: "Resumo do projeto (sem target)",
|
|
@@ -2919,6 +3022,7 @@ function generateTestSuggestions(suggestions, allFiles) {
|
|
|
2919
3022
|
// src/commands/context.ts
|
|
2920
3023
|
import { existsSync as existsSync6, readdirSync as readdirSync3, statSync as statSync3 } from "fs";
|
|
2921
3024
|
import { join as join6, resolve as resolve2, basename, extname as extname3 } from "path";
|
|
3025
|
+
import { SyntaxKind as SyntaxKind3 } from "ts-morph";
|
|
2922
3026
|
|
|
2923
3027
|
// src/ts/extractor.ts
|
|
2924
3028
|
import { Project, SyntaxKind } from "ts-morph";
|
|
@@ -3800,6 +3904,24 @@ async function context(target, options = {}) {
|
|
|
3800
3904
|
const functions2 = extractFunctions(sourceFile);
|
|
3801
3905
|
const types = extractTypes(sourceFile);
|
|
3802
3906
|
const exports = extractExports(sourceFile);
|
|
3907
|
+
const constants = [];
|
|
3908
|
+
for (const varStatement of sourceFile.getVariableStatements()) {
|
|
3909
|
+
if (!varStatement.isExported()) continue;
|
|
3910
|
+
for (const decl of varStatement.getDeclarations()) {
|
|
3911
|
+
const init = decl.getInitializer();
|
|
3912
|
+
if (init) {
|
|
3913
|
+
const kind = init.getKind();
|
|
3914
|
+
if (kind === SyntaxKind3.ArrowFunction || kind === SyntaxKind3.FunctionExpression) {
|
|
3915
|
+
continue;
|
|
3916
|
+
}
|
|
3917
|
+
}
|
|
3918
|
+
constants.push({
|
|
3919
|
+
name: decl.getName(),
|
|
3920
|
+
type: simplifyType(decl.getType().getText()),
|
|
3921
|
+
isExported: true
|
|
3922
|
+
});
|
|
3923
|
+
}
|
|
3924
|
+
}
|
|
3803
3925
|
const result = {
|
|
3804
3926
|
version: "1.0.0",
|
|
3805
3927
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -3808,7 +3930,8 @@ async function context(target, options = {}) {
|
|
|
3808
3930
|
imports,
|
|
3809
3931
|
exports,
|
|
3810
3932
|
functions: functions2,
|
|
3811
|
-
types
|
|
3933
|
+
types,
|
|
3934
|
+
constants: constants.length > 0 ? constants : void 0
|
|
3812
3935
|
};
|
|
3813
3936
|
return formatOutput(result, format, formatContextText);
|
|
3814
3937
|
} catch (error) {
|
|
@@ -3927,9 +4050,19 @@ async function areaContext(areaName, options = {}) {
|
|
|
3927
4050
|
}
|
|
3928
4051
|
}
|
|
3929
4052
|
if (areaFiles.length === 0) {
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
4053
|
+
const availableAreas = /* @__PURE__ */ new Map();
|
|
4054
|
+
for (const filePath of Object.keys(index.files)) {
|
|
4055
|
+
if (isFileIgnored(filePath, config)) continue;
|
|
4056
|
+
const fileAreas = detectFileAreas(filePath, config);
|
|
4057
|
+
for (const areaId of fileAreas) {
|
|
4058
|
+
availableAreas.set(areaId, (availableAreas.get(areaId) || 0) + 1);
|
|
4059
|
+
}
|
|
4060
|
+
}
|
|
4061
|
+
const areaList = [...availableAreas.entries()].map(([id, count]) => ({ id, count })).sort((a, b) => b.count - a.count);
|
|
4062
|
+
if (format === "json") {
|
|
4063
|
+
return JSON.stringify({ error: `Area nao encontrada: "${areaName}"`, availableAreas: areaList });
|
|
4064
|
+
}
|
|
4065
|
+
return formatAreaNotFound({ target: areaName, availableAreas: areaList });
|
|
3933
4066
|
}
|
|
3934
4067
|
const types = [];
|
|
3935
4068
|
const hooks = [];
|
|
@@ -4682,12 +4815,40 @@ async function functions(options = {}) {
|
|
|
4682
4815
|
const useCache = options.cache !== false;
|
|
4683
4816
|
const filterTrigger = options.trigger;
|
|
4684
4817
|
if (!isFirebaseProject(cwd)) {
|
|
4685
|
-
const errorMsg = "Este
|
|
4686
|
-
|
|
4818
|
+
const errorMsg = "Este nao e um projeto Firebase (nao encontrou .firebaserc ou firebase.json)";
|
|
4819
|
+
if (format === "json") {
|
|
4820
|
+
return JSON.stringify({ error: errorMsg });
|
|
4821
|
+
}
|
|
4822
|
+
let out = `\u274C ${errorMsg}
|
|
4823
|
+
`;
|
|
4824
|
+
out += `
|
|
4825
|
+
\u{1F4A1} Comandos disponiveis para este projeto:
|
|
4826
|
+
`;
|
|
4827
|
+
out += ` \u2192 ai-tool map - ver estrutura do projeto
|
|
4828
|
+
`;
|
|
4829
|
+
out += ` \u2192 ai-tool find <termo> - buscar simbolos no codigo
|
|
4830
|
+
`;
|
|
4831
|
+
out += ` \u2192 ai-tool areas - listar areas funcionais
|
|
4832
|
+
`;
|
|
4833
|
+
return out;
|
|
4687
4834
|
}
|
|
4688
4835
|
if (!hasFirebaseFunctions(cwd)) {
|
|
4689
|
-
const errorMsg = "Projeto Firebase sem Cloud Functions
|
|
4690
|
-
|
|
4836
|
+
const errorMsg = "Projeto Firebase detectado, mas sem Cloud Functions";
|
|
4837
|
+
if (format === "json") {
|
|
4838
|
+
return JSON.stringify({ error: errorMsg });
|
|
4839
|
+
}
|
|
4840
|
+
let out = `\u274C ${errorMsg}
|
|
4841
|
+
`;
|
|
4842
|
+
out += ` Nao foi encontrado functions/src/index.ts
|
|
4843
|
+
|
|
4844
|
+
`;
|
|
4845
|
+
out += `\u{1F4A1} Para adicionar Cloud Functions:
|
|
4846
|
+
`;
|
|
4847
|
+
out += ` \u2192 firebase init functions
|
|
4848
|
+
`;
|
|
4849
|
+
out += ` \u2192 Documentacao: https://firebase.google.com/docs/functions
|
|
4850
|
+
`;
|
|
4851
|
+
return out;
|
|
4691
4852
|
}
|
|
4692
4853
|
try {
|
|
4693
4854
|
let index;
|
|
@@ -4946,7 +5107,19 @@ async function find(query, options = {}) {
|
|
|
4946
5107
|
}
|
|
4947
5108
|
}
|
|
4948
5109
|
if (allowedFiles.size === 0) {
|
|
4949
|
-
|
|
5110
|
+
const availableAreas = /* @__PURE__ */ new Map();
|
|
5111
|
+
for (const filePath of Object.keys(index.files)) {
|
|
5112
|
+
if (isFileIgnored(filePath, config)) continue;
|
|
5113
|
+
const fileAreas = detectFileAreas(filePath, config);
|
|
5114
|
+
for (const areaId of fileAreas) {
|
|
5115
|
+
availableAreas.set(areaId, (availableAreas.get(areaId) || 0) + 1);
|
|
5116
|
+
}
|
|
5117
|
+
}
|
|
5118
|
+
const areaList = [...availableAreas.entries()].map(([id, count]) => ({ id, count })).sort((a, b) => b.count - a.count);
|
|
5119
|
+
if (format === "json") {
|
|
5120
|
+
return JSON.stringify({ error: `Nenhum arquivo encontrado na area "${filterArea}"`, availableAreas: areaList });
|
|
5121
|
+
}
|
|
5122
|
+
return formatAreaNotFound({ target: filterArea, availableAreas: areaList });
|
|
4950
5123
|
}
|
|
4951
5124
|
}
|
|
4952
5125
|
const matches = searchInIndex(index, query, filterType, allowedFiles);
|
|
@@ -4991,7 +5164,8 @@ async function find(query, options = {}) {
|
|
|
4991
5164
|
},
|
|
4992
5165
|
fromCache
|
|
4993
5166
|
};
|
|
4994
|
-
|
|
5167
|
+
const allSymbolNames = Object.keys(index.symbolsByName);
|
|
5168
|
+
return formatOutput(result, format, (r) => formatFindText(r, "cli", allSymbolNames), fromCache);
|
|
4995
5169
|
} catch (error) {
|
|
4996
5170
|
const message = error instanceof Error ? error.message : String(error);
|
|
4997
5171
|
throw new Error(`Erro ao executar find: ${message}`);
|
|
@@ -5118,6 +5292,13 @@ export {
|
|
|
5118
5292
|
categoryIcons,
|
|
5119
5293
|
isEntryPoint,
|
|
5120
5294
|
isCodeFile,
|
|
5295
|
+
hint,
|
|
5296
|
+
nextSteps,
|
|
5297
|
+
recoveryHint,
|
|
5298
|
+
levenshteinDistance,
|
|
5299
|
+
findSimilar,
|
|
5300
|
+
findBestMatch,
|
|
5301
|
+
extractFileName,
|
|
5121
5302
|
isFirebaseProject,
|
|
5122
5303
|
hasFirebaseFunctions,
|
|
5123
5304
|
isExportedCloudFunction,
|
|
@@ -5125,7 +5306,10 @@ export {
|
|
|
5125
5306
|
clearFirebaseCache,
|
|
5126
5307
|
getCacheDir,
|
|
5127
5308
|
isCacheValid,
|
|
5309
|
+
updateCacheMeta,
|
|
5128
5310
|
invalidateCache,
|
|
5311
|
+
cacheSymbolsIndex,
|
|
5312
|
+
getCachedSymbolsIndex,
|
|
5129
5313
|
configExists,
|
|
5130
5314
|
readConfig,
|
|
5131
5315
|
writeConfig,
|
|
@@ -5143,10 +5327,6 @@ export {
|
|
|
5143
5327
|
map,
|
|
5144
5328
|
dead,
|
|
5145
5329
|
deadFix,
|
|
5146
|
-
levenshteinDistance,
|
|
5147
|
-
findSimilar,
|
|
5148
|
-
findBestMatch,
|
|
5149
|
-
extractFileName,
|
|
5150
5330
|
COMMAND_REFERENCE,
|
|
5151
5331
|
formatFileNotFound,
|
|
5152
5332
|
formatAreaNotFound,
|
|
@@ -5154,6 +5334,8 @@ export {
|
|
|
5154
5334
|
formatInvalidCommand,
|
|
5155
5335
|
impact,
|
|
5156
5336
|
suggest,
|
|
5337
|
+
getAllCodeFiles,
|
|
5338
|
+
indexProject,
|
|
5157
5339
|
context,
|
|
5158
5340
|
areaContext,
|
|
5159
5341
|
areas,
|