@justmpm/ai-tool 3.22.0 → 3.22.2
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.
|
@@ -1832,10 +1832,22 @@ function formatChangesText(result, ctx = "cli") {
|
|
|
1832
1832
|
return out;
|
|
1833
1833
|
}
|
|
1834
1834
|
const targetLabel = result.target === "staged" ? "staged" : result.target === "unstaged" ? "unstaged" : "unstaged + staged";
|
|
1835
|
-
|
|
1835
|
+
const parts = [];
|
|
1836
|
+
parts.push(`Files: ${result.summary.totalFiles} modified (${targetLabel})`);
|
|
1837
|
+
parts.push(`+${result.summary.totalAdded} -${result.summary.totalRemoved}`);
|
|
1836
1838
|
if (result.summary.totalNewFiles > 0) {
|
|
1837
|
-
|
|
1839
|
+
parts.push(`${result.summary.totalNewFiles} new (untracked, ${result.summary.totalUntrackedLines} lines)`);
|
|
1840
|
+
}
|
|
1841
|
+
if (result.summary.totalRenames > 0) {
|
|
1842
|
+
parts.push(`${result.summary.totalRenames} renamed`);
|
|
1843
|
+
}
|
|
1844
|
+
if (result.summary.totalAddedFiles > 0) {
|
|
1845
|
+
parts.push(`${result.summary.totalAddedFiles} added`);
|
|
1838
1846
|
}
|
|
1847
|
+
if (result.summary.totalDeletedFiles > 0) {
|
|
1848
|
+
parts.push(`${result.summary.totalDeletedFiles} deleted`);
|
|
1849
|
+
}
|
|
1850
|
+
let summaryLine = parts.join(" | ");
|
|
1839
1851
|
out += `${summaryLine}
|
|
1840
1852
|
`;
|
|
1841
1853
|
const kindCounts = {};
|
|
@@ -1859,11 +1871,11 @@ function formatChangesText(result, ctx = "cli") {
|
|
|
1859
1871
|
};
|
|
1860
1872
|
const kindParts = [];
|
|
1861
1873
|
for (const [kind, counts] of Object.entries(kindCounts)) {
|
|
1862
|
-
const
|
|
1863
|
-
if (counts.added > 0)
|
|
1864
|
-
if (counts.modified > 0)
|
|
1865
|
-
if (counts.removed > 0)
|
|
1866
|
-
if (
|
|
1874
|
+
const parts2 = [];
|
|
1875
|
+
if (counts.added > 0) parts2.push(`+${counts.added}`);
|
|
1876
|
+
if (counts.modified > 0) parts2.push(`~${counts.modified}`);
|
|
1877
|
+
if (counts.removed > 0) parts2.push(`-${counts.removed}`);
|
|
1878
|
+
if (parts2.length > 0) kindParts.push(`${kindLabels[kind]}: ${parts2.join(" ")}`);
|
|
1867
1879
|
}
|
|
1868
1880
|
if (kindParts.length > 0) {
|
|
1869
1881
|
out += `${kindParts.join(" | ")}
|
|
@@ -1891,10 +1903,12 @@ COMPACT MODE: Too many files. Use --file=<path> for details.
|
|
|
1891
1903
|
|
|
1892
1904
|
`;
|
|
1893
1905
|
const modifiedCompact = result.files.filter((f) => !f.newFile);
|
|
1894
|
-
|
|
1906
|
+
const renamedCompact = modifiedCompact.filter((f) => f.renamed);
|
|
1907
|
+
const otherModifiedCompact = modifiedCompact.filter((f) => !f.renamed);
|
|
1908
|
+
if (otherModifiedCompact.length > 0) {
|
|
1895
1909
|
out += `Modified files:
|
|
1896
1910
|
`;
|
|
1897
|
-
for (const file of
|
|
1911
|
+
for (const file of otherModifiedCompact) {
|
|
1898
1912
|
const changeCount = file.changes.length;
|
|
1899
1913
|
out += ` ${file.path} (+${file.stats.added} -${file.stats.removed})`;
|
|
1900
1914
|
if (changeCount > 0) {
|
|
@@ -1903,6 +1917,20 @@ COMPACT MODE: Too many files. Use --file=<path> for details.
|
|
|
1903
1917
|
out += ` - (no semantic changes)`;
|
|
1904
1918
|
}
|
|
1905
1919
|
out += `
|
|
1920
|
+
`;
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1923
|
+
if (renamedCompact.length > 0) {
|
|
1924
|
+
out += `
|
|
1925
|
+
Renamed files:
|
|
1926
|
+
`;
|
|
1927
|
+
for (const file of renamedCompact) {
|
|
1928
|
+
out += ` ${file.renamedFrom} -> ${file.path} (+${file.stats.added} -${file.stats.removed})`;
|
|
1929
|
+
const changeCount = file.changes.length;
|
|
1930
|
+
if (changeCount > 0) {
|
|
1931
|
+
out += ` - ${changeCount} changes`;
|
|
1932
|
+
}
|
|
1933
|
+
out += `
|
|
1906
1934
|
`;
|
|
1907
1935
|
}
|
|
1908
1936
|
}
|
|
@@ -2000,11 +2028,33 @@ NEW FILES (${newFiles.length}, untracked)
|
|
|
2000
2028
|
}
|
|
2001
2029
|
}
|
|
2002
2030
|
}
|
|
2031
|
+
const renamedFiles = semanticFiles.filter((f) => f.renamed);
|
|
2032
|
+
if (renamedFiles.length > 0) {
|
|
2033
|
+
out += `
|
|
2034
|
+
RENAMED FILES (${renamedFiles.length})
|
|
2035
|
+
`;
|
|
2036
|
+
for (const file of renamedFiles) {
|
|
2037
|
+
out += ` ${file.renamedFrom} -> ${file.path} (+${file.stats.added} -${file.stats.removed})
|
|
2038
|
+
`;
|
|
2039
|
+
if (file.changes.length > 0) {
|
|
2040
|
+
for (const entry of file.changes) {
|
|
2041
|
+
const prefix = formatKindIcon(entry.kind);
|
|
2042
|
+
const detail = entry.detail ? ` - ${entry.detail}` : "";
|
|
2043
|
+
out += ` ${prefix} ${entry.name}${detail}
|
|
2044
|
+
`;
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
}
|
|
2003
2049
|
if (otherFiles.length > 0) {
|
|
2004
2050
|
out += `
|
|
2005
|
-
OTHER FILES (${otherFiles.length}):
|
|
2006
|
-
|
|
2007
|
-
|
|
2051
|
+
OTHER FILES (${otherFiles.length}):
|
|
2052
|
+
`;
|
|
2053
|
+
for (const f of otherFiles) {
|
|
2054
|
+
const fileName = f.path.split("/").pop() || f.path;
|
|
2055
|
+
out += ` ${fileName} (+${f.stats.added} -${f.stats.removed})
|
|
2056
|
+
`;
|
|
2057
|
+
}
|
|
2008
2058
|
}
|
|
2009
2059
|
out += nextSteps("changes", ctx);
|
|
2010
2060
|
return out;
|
|
@@ -5297,26 +5347,12 @@ function getUntrackedFiles(cwd) {
|
|
|
5297
5347
|
return [];
|
|
5298
5348
|
}
|
|
5299
5349
|
}
|
|
5300
|
-
function
|
|
5301
|
-
if (!hasGitRepo(cwd)) return [];
|
|
5302
|
-
try {
|
|
5303
|
-
const diffArgs = getDiffArgs(target);
|
|
5304
|
-
const cmd = `git diff --name-only ${diffArgs.join(" ")}`;
|
|
5305
|
-
const output = execSync2(cmd, {
|
|
5306
|
-
cwd,
|
|
5307
|
-
encoding: "utf-8",
|
|
5308
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
5309
|
-
});
|
|
5310
|
-
return output.trim().split("\n").filter((line) => line.trim() !== "").map((line) => line.trim());
|
|
5311
|
-
} catch {
|
|
5312
|
-
return [];
|
|
5313
|
-
}
|
|
5314
|
-
}
|
|
5315
|
-
function getDiffForFile(filePath, target, cwd) {
|
|
5350
|
+
function getFullDiffText(target, cwd, filePath) {
|
|
5316
5351
|
if (!hasGitRepo(cwd)) return "";
|
|
5317
5352
|
try {
|
|
5318
5353
|
const diffArgs = getDiffArgs(target);
|
|
5319
|
-
const
|
|
5354
|
+
const fileArg = filePath ? ` -- "${filePath}"` : "";
|
|
5355
|
+
const cmd = `git diff --unified=10${fileArg} ${diffArgs.join(" ")}`;
|
|
5320
5356
|
const output = execSync2(cmd, {
|
|
5321
5357
|
cwd,
|
|
5322
5358
|
encoding: "utf-8",
|
|
@@ -5327,28 +5363,6 @@ function getDiffForFile(filePath, target, cwd) {
|
|
|
5327
5363
|
return "";
|
|
5328
5364
|
}
|
|
5329
5365
|
}
|
|
5330
|
-
function getDiffStats(filePath, target, cwd) {
|
|
5331
|
-
if (!hasGitRepo(cwd)) return null;
|
|
5332
|
-
try {
|
|
5333
|
-
const diffArgs = getDiffArgs(target);
|
|
5334
|
-
const cmd = `git diff --numstat ${diffArgs.join(" ")} -- "${filePath}"`;
|
|
5335
|
-
const output = execSync2(cmd, {
|
|
5336
|
-
cwd,
|
|
5337
|
-
encoding: "utf-8",
|
|
5338
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
5339
|
-
});
|
|
5340
|
-
const line = output.trim().split("\n")[0];
|
|
5341
|
-
if (!line) return null;
|
|
5342
|
-
const parts = line.split(" ");
|
|
5343
|
-
if (parts.length < 2) return null;
|
|
5344
|
-
const added = parts[0] === "-" ? 0 : parseInt(parts[0], 10);
|
|
5345
|
-
const removed = parts[1] === "-" ? 0 : parseInt(parts[1], 10);
|
|
5346
|
-
if (Number.isNaN(added) || Number.isNaN(removed)) return null;
|
|
5347
|
-
return { added, removed };
|
|
5348
|
-
} catch {
|
|
5349
|
-
return null;
|
|
5350
|
-
}
|
|
5351
|
-
}
|
|
5352
5366
|
|
|
5353
5367
|
// src/commands/impact.ts
|
|
5354
5368
|
async function impact(target, options = {}) {
|
|
@@ -7262,6 +7276,7 @@ function getTriggerIcon(trigger) {
|
|
|
7262
7276
|
// src/commands/changes.ts
|
|
7263
7277
|
import * as path from "path";
|
|
7264
7278
|
import { readFileSync as readFileSync7 } from "fs";
|
|
7279
|
+
import parseGitDiff from "parse-git-diff";
|
|
7265
7280
|
var UNTRACKED_PREVIEW_LINES = 20;
|
|
7266
7281
|
async function changes(options = {}) {
|
|
7267
7282
|
const { cwd, format } = parseCommandOptions(options);
|
|
@@ -7271,62 +7286,55 @@ async function changes(options = {}) {
|
|
|
7271
7286
|
throw new Error("Nao e um repositorio Git. Execute este comando em um projeto com Git.");
|
|
7272
7287
|
}
|
|
7273
7288
|
try {
|
|
7274
|
-
const
|
|
7289
|
+
const diffText = getFullDiffText(target, cwd, options.file || void 0);
|
|
7275
7290
|
const untrackedFiles = getUntrackedFiles(cwd);
|
|
7276
|
-
if (changedFiles.length === 0 && untrackedFiles.length === 0) {
|
|
7277
|
-
const result2 = {
|
|
7278
|
-
version: "1.0.0",
|
|
7279
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7280
|
-
target,
|
|
7281
|
-
summary: {
|
|
7282
|
-
totalFiles: 0,
|
|
7283
|
-
totalNewFiles: 0,
|
|
7284
|
-
totalAdded: 0,
|
|
7285
|
-
totalRemoved: 0
|
|
7286
|
-
},
|
|
7287
|
-
files: []
|
|
7288
|
-
};
|
|
7289
|
-
return formatOutput(result2, format, (r) => formatChangesText(r, ctx));
|
|
7290
|
-
}
|
|
7291
7291
|
const DEFAULT_IGNORE = [".analyze/"];
|
|
7292
|
-
|
|
7293
|
-
|
|
7294
|
-
|
|
7295
|
-
|
|
7296
|
-
(f) => !DEFAULT_IGNORE.some((pattern) => f.includes(pattern))
|
|
7297
|
-
);
|
|
7298
|
-
const filesToProcess = options.file ? filesFiltered.filter(
|
|
7299
|
-
(f) => f.toLowerCase().includes(options.file.toLowerCase())
|
|
7300
|
-
) : filesFiltered;
|
|
7301
|
-
const untrackedToProcess = options.file ? untrackedFiltered.filter(
|
|
7302
|
-
(f) => f.toLowerCase().includes(options.file.toLowerCase())
|
|
7303
|
-
) : untrackedFiltered;
|
|
7292
|
+
let parsed = null;
|
|
7293
|
+
if (diffText.trim()) {
|
|
7294
|
+
parsed = parseGitDiff(diffText);
|
|
7295
|
+
}
|
|
7304
7296
|
const fileChanges = [];
|
|
7305
7297
|
let totalAdded = 0;
|
|
7306
7298
|
let totalRemoved = 0;
|
|
7299
|
+
let totalRenames = 0;
|
|
7300
|
+
let totalAddedFiles = 0;
|
|
7301
|
+
let totalDeletedFiles = 0;
|
|
7307
7302
|
const symbolsIndex = await loadCachedSymbolsIndex(cwd);
|
|
7308
|
-
|
|
7309
|
-
const
|
|
7310
|
-
|
|
7311
|
-
|
|
7312
|
-
|
|
7313
|
-
totalAdded += stats.added;
|
|
7314
|
-
totalRemoved += stats.removed;
|
|
7315
|
-
}
|
|
7316
|
-
if (entries.length === 0 && stats && stats.added + stats.removed > 0) {
|
|
7317
|
-
const ext = path.extname(filePath).toLowerCase();
|
|
7318
|
-
if (!CODE_EXTENSIONS2.has(ext)) {
|
|
7319
|
-
entries = extractGenericDiffPreview(diffText, filePath);
|
|
7303
|
+
if (parsed && parsed.files.length > 0) {
|
|
7304
|
+
for (const file of parsed.files) {
|
|
7305
|
+
const filePath = resolveFilePath(file);
|
|
7306
|
+
if (options.file) {
|
|
7307
|
+
if (!filePath.toLowerCase().includes(options.file.toLowerCase())) continue;
|
|
7320
7308
|
}
|
|
7309
|
+
if (DEFAULT_IGNORE.some((p) => filePath.includes(p))) continue;
|
|
7310
|
+
const chunks = extractChunks(file);
|
|
7311
|
+
const { added, removed, entries } = processChunks(chunks, filePath, symbolsIndex);
|
|
7312
|
+
const fileType = resolveFileType(file);
|
|
7313
|
+
const change = {
|
|
7314
|
+
path: filePath,
|
|
7315
|
+
category: detectCategory(filePath),
|
|
7316
|
+
stats: { added, removed },
|
|
7317
|
+
changes: entries,
|
|
7318
|
+
fileType
|
|
7319
|
+
};
|
|
7320
|
+
if (file.type === "RenamedFile") {
|
|
7321
|
+
const renamedFile = file;
|
|
7322
|
+
change.renamed = true;
|
|
7323
|
+
change.renamedFrom = renamedFile.pathBefore;
|
|
7324
|
+
totalRenames++;
|
|
7325
|
+
}
|
|
7326
|
+
if (file.type === "AddedFile") totalAddedFiles++;
|
|
7327
|
+
if (file.type === "DeletedFile") totalDeletedFiles++;
|
|
7328
|
+
totalAdded += added;
|
|
7329
|
+
totalRemoved += removed;
|
|
7330
|
+
fileChanges.push(change);
|
|
7321
7331
|
}
|
|
7322
|
-
const enrichedEntries = enrichWithJsDoc(entries, filePath, symbolsIndex);
|
|
7323
|
-
fileChanges.push({
|
|
7324
|
-
path: filePath,
|
|
7325
|
-
category: detectCategory(filePath),
|
|
7326
|
-
stats: stats || { added: 0, removed: 0 },
|
|
7327
|
-
changes: enrichedEntries
|
|
7328
|
-
});
|
|
7329
7332
|
}
|
|
7333
|
+
let totalUntrackedLines = 0;
|
|
7334
|
+
const untrackedFiltered = untrackedFiles.filter(
|
|
7335
|
+
(f) => !DEFAULT_IGNORE.some((p) => f.includes(p))
|
|
7336
|
+
);
|
|
7337
|
+
const untrackedToProcess = options.file ? untrackedFiltered.filter((f) => f.toLowerCase().includes(options.file.toLowerCase())) : untrackedFiltered;
|
|
7330
7338
|
for (const filePath of untrackedToProcess) {
|
|
7331
7339
|
const fullFilePath = path.resolve(cwd, filePath);
|
|
7332
7340
|
let lineCount = 0;
|
|
@@ -7348,31 +7356,36 @@ async function changes(options = {}) {
|
|
|
7348
7356
|
category: detectCategory(filePath),
|
|
7349
7357
|
stats: { added: lineCount, removed: 0 },
|
|
7350
7358
|
changes: enrichedEntries,
|
|
7351
|
-
newFile: true
|
|
7359
|
+
newFile: true,
|
|
7360
|
+
fileType: "added"
|
|
7352
7361
|
});
|
|
7353
|
-
|
|
7362
|
+
totalUntrackedLines += lineCount;
|
|
7354
7363
|
} catch {
|
|
7355
7364
|
fileChanges.push({
|
|
7356
7365
|
path: filePath,
|
|
7357
7366
|
category: detectCategory(filePath),
|
|
7358
7367
|
stats: { added: 0, removed: 0 },
|
|
7359
7368
|
changes: [],
|
|
7360
|
-
newFile: true
|
|
7369
|
+
newFile: true,
|
|
7370
|
+
fileType: "added"
|
|
7361
7371
|
});
|
|
7362
7372
|
}
|
|
7363
7373
|
}
|
|
7364
7374
|
const affectedAreas = buildAffectedAreas(fileChanges, cwd);
|
|
7365
|
-
const
|
|
7366
|
-
const totalNewForSummary = options.file ? fileChanges.filter((f) => f.newFile).length : untrackedFiles.length;
|
|
7375
|
+
const trackedFiles = fileChanges.filter((f) => !f.newFile);
|
|
7367
7376
|
const result = {
|
|
7368
7377
|
version: "1.0.0",
|
|
7369
7378
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7370
7379
|
target,
|
|
7371
7380
|
summary: {
|
|
7372
|
-
totalFiles:
|
|
7373
|
-
totalNewFiles:
|
|
7381
|
+
totalFiles: trackedFiles.length,
|
|
7382
|
+
totalNewFiles: untrackedToProcess.length,
|
|
7374
7383
|
totalAdded,
|
|
7375
|
-
totalRemoved
|
|
7384
|
+
totalRemoved,
|
|
7385
|
+
totalUntrackedLines,
|
|
7386
|
+
totalRenames,
|
|
7387
|
+
totalAddedFiles,
|
|
7388
|
+
totalDeletedFiles
|
|
7376
7389
|
},
|
|
7377
7390
|
files: fileChanges,
|
|
7378
7391
|
affectedAreas: affectedAreas.length > 0 ? affectedAreas : void 0
|
|
@@ -7383,6 +7396,142 @@ async function changes(options = {}) {
|
|
|
7383
7396
|
throw new Error(`Erro ao executar changes: ${message}`);
|
|
7384
7397
|
}
|
|
7385
7398
|
}
|
|
7399
|
+
function resolveFilePath(file) {
|
|
7400
|
+
if (file.type === "RenamedFile") return file.pathAfter;
|
|
7401
|
+
return file.path;
|
|
7402
|
+
}
|
|
7403
|
+
function extractChunks(file) {
|
|
7404
|
+
if ("chunks" in file) {
|
|
7405
|
+
return file.chunks.filter((c) => c.type === "Chunk");
|
|
7406
|
+
}
|
|
7407
|
+
return [];
|
|
7408
|
+
}
|
|
7409
|
+
function resolveFileType(file) {
|
|
7410
|
+
switch (file.type) {
|
|
7411
|
+
case "AddedFile":
|
|
7412
|
+
return "added";
|
|
7413
|
+
case "DeletedFile":
|
|
7414
|
+
return "deleted";
|
|
7415
|
+
case "RenamedFile":
|
|
7416
|
+
return "renamed";
|
|
7417
|
+
case "ChangedFile":
|
|
7418
|
+
return "changed";
|
|
7419
|
+
}
|
|
7420
|
+
}
|
|
7421
|
+
function processChunks(chunks, filePath, symbolsIndex) {
|
|
7422
|
+
let added = 0;
|
|
7423
|
+
let removed = 0;
|
|
7424
|
+
const allAddedLines = [];
|
|
7425
|
+
const allDeletedLines = [];
|
|
7426
|
+
for (const chunk of chunks) {
|
|
7427
|
+
for (const change of chunk.changes) {
|
|
7428
|
+
if (change.type === "AddedLine") {
|
|
7429
|
+
added++;
|
|
7430
|
+
allAddedLines.push(change.content);
|
|
7431
|
+
} else if (change.type === "DeletedLine") {
|
|
7432
|
+
removed++;
|
|
7433
|
+
allDeletedLines.push(change.content);
|
|
7434
|
+
}
|
|
7435
|
+
}
|
|
7436
|
+
}
|
|
7437
|
+
const entries = classifyFromStructuredLines(allAddedLines, allDeletedLines);
|
|
7438
|
+
if (entries.length === 0 && added + removed > 0) {
|
|
7439
|
+
const previewText = buildSyntheticDiff(allAddedLines, allDeletedLines);
|
|
7440
|
+
const genericEntries = extractGenericDiffPreview(previewText, filePath);
|
|
7441
|
+
entries.push(...genericEntries);
|
|
7442
|
+
}
|
|
7443
|
+
const enrichedEntries = enrichWithJsDoc(entries, filePath, symbolsIndex);
|
|
7444
|
+
return { added, removed, entries: enrichedEntries };
|
|
7445
|
+
}
|
|
7446
|
+
function buildSyntheticDiff(addedLines, deletedLines) {
|
|
7447
|
+
const lines = [];
|
|
7448
|
+
const maxPreview = 10;
|
|
7449
|
+
for (const line of deletedLines.slice(0, maxPreview)) {
|
|
7450
|
+
lines.push(`-${line}`);
|
|
7451
|
+
}
|
|
7452
|
+
for (const line of addedLines.slice(0, maxPreview)) {
|
|
7453
|
+
lines.push(`+${line}`);
|
|
7454
|
+
}
|
|
7455
|
+
return lines.join("\n");
|
|
7456
|
+
}
|
|
7457
|
+
function classifyFromStructuredLines(addedLines, deletedLines) {
|
|
7458
|
+
const entries = [];
|
|
7459
|
+
const removedSymbols = /* @__PURE__ */ new Map();
|
|
7460
|
+
for (const line of deletedLines) {
|
|
7461
|
+
const multiReexport = extractMultipleReexports(line);
|
|
7462
|
+
if (multiReexport) {
|
|
7463
|
+
for (const name of multiReexport.names) {
|
|
7464
|
+
if (!removedSymbols.has(name)) {
|
|
7465
|
+
removedSymbols.set(name, { kind: multiReexport.kind, content: line });
|
|
7466
|
+
}
|
|
7467
|
+
}
|
|
7468
|
+
continue;
|
|
7469
|
+
}
|
|
7470
|
+
const info = extractSymbolInfo(line);
|
|
7471
|
+
if (info && info.name && isRelevantSymbol(info)) {
|
|
7472
|
+
if (!removedSymbols.has(info.name)) {
|
|
7473
|
+
removedSymbols.set(info.name, { kind: info.kind, content: line });
|
|
7474
|
+
}
|
|
7475
|
+
}
|
|
7476
|
+
}
|
|
7477
|
+
const addedSymbols = /* @__PURE__ */ new Map();
|
|
7478
|
+
for (const line of addedLines) {
|
|
7479
|
+
const multiReexport = extractMultipleReexports(line);
|
|
7480
|
+
if (multiReexport) {
|
|
7481
|
+
for (const name of multiReexport.names) {
|
|
7482
|
+
if (!addedSymbols.has(name)) {
|
|
7483
|
+
addedSymbols.set(name, { kind: multiReexport.kind, content: line });
|
|
7484
|
+
}
|
|
7485
|
+
}
|
|
7486
|
+
continue;
|
|
7487
|
+
}
|
|
7488
|
+
const info = extractSymbolInfo(line);
|
|
7489
|
+
if (info && info.name && isRelevantSymbol(info)) {
|
|
7490
|
+
if (!addedSymbols.has(info.name)) {
|
|
7491
|
+
addedSymbols.set(info.name, { kind: info.kind, content: line });
|
|
7492
|
+
}
|
|
7493
|
+
}
|
|
7494
|
+
}
|
|
7495
|
+
const modifiedNames = /* @__PURE__ */ new Set();
|
|
7496
|
+
for (const name of removedSymbols.keys()) {
|
|
7497
|
+
if (addedSymbols.has(name)) modifiedNames.add(name);
|
|
7498
|
+
}
|
|
7499
|
+
for (const [name, { kind }] of removedSymbols) {
|
|
7500
|
+
if (!modifiedNames.has(name)) {
|
|
7501
|
+
entries.push({ kind, type: "removed", name });
|
|
7502
|
+
}
|
|
7503
|
+
}
|
|
7504
|
+
for (const name of modifiedNames) {
|
|
7505
|
+
const removed = removedSymbols.get(name);
|
|
7506
|
+
const added = addedSymbols.get(name);
|
|
7507
|
+
const detail = generateModifiedDetail(removed.content, added.content, added.kind);
|
|
7508
|
+
entries.push({ kind: added.kind, type: "modified", name, detail });
|
|
7509
|
+
}
|
|
7510
|
+
for (const [name, { kind, content }] of addedSymbols) {
|
|
7511
|
+
if (!modifiedNames.has(name)) {
|
|
7512
|
+
const previewLines = buildPreviewFromLines([content], "added");
|
|
7513
|
+
entries.push({
|
|
7514
|
+
kind,
|
|
7515
|
+
type: "added",
|
|
7516
|
+
name,
|
|
7517
|
+
previewLines: previewLines.length > 0 ? previewLines : void 0
|
|
7518
|
+
});
|
|
7519
|
+
}
|
|
7520
|
+
}
|
|
7521
|
+
return entries;
|
|
7522
|
+
}
|
|
7523
|
+
function buildPreviewFromLines(lines, type) {
|
|
7524
|
+
const preview = [];
|
|
7525
|
+
const limit = type === "added" ? 2 : 4;
|
|
7526
|
+
for (const line of lines) {
|
|
7527
|
+
if (preview.length >= limit) break;
|
|
7528
|
+
const trimmed = line.trim();
|
|
7529
|
+
if (trimmed && !trimmed.startsWith("//") && !trimmed.startsWith("/*") && !/^[})\];,]*$/.test(trimmed)) {
|
|
7530
|
+
preview.push(type === "added" ? `[+] ${line}` : `[+] ${line}`);
|
|
7531
|
+
}
|
|
7532
|
+
}
|
|
7533
|
+
return preview.slice(0, limit);
|
|
7534
|
+
}
|
|
7386
7535
|
function enrichWithJsDoc(entries, filePath, cachedIndex) {
|
|
7387
7536
|
const needsEnrichment = (e) => e.kind !== "import" && e.kind !== "config" && !e.detail;
|
|
7388
7537
|
if (!entries.some(needsEnrichment)) {
|
|
@@ -7495,13 +7644,9 @@ function classifyChanges(diffText) {
|
|
|
7495
7644
|
if (multiReexport) {
|
|
7496
7645
|
for (const name of multiReexport.names) {
|
|
7497
7646
|
if (line.prefix === "remove") {
|
|
7498
|
-
if (!removedSymbols.has(name))
|
|
7499
|
-
removedSymbols.set(name, line);
|
|
7500
|
-
}
|
|
7647
|
+
if (!removedSymbols.has(name)) removedSymbols.set(name, line);
|
|
7501
7648
|
} else {
|
|
7502
|
-
if (!addedSymbols.has(name))
|
|
7503
|
-
addedSymbols.set(name, line);
|
|
7504
|
-
}
|
|
7649
|
+
if (!addedSymbols.has(name)) addedSymbols.set(name, line);
|
|
7505
7650
|
}
|
|
7506
7651
|
}
|
|
7507
7652
|
continue;
|
|
@@ -7509,32 +7654,22 @@ function classifyChanges(diffText) {
|
|
|
7509
7654
|
const info = extractSymbolInfo(line.content);
|
|
7510
7655
|
if (info && info.name && isRelevantSymbol(info)) {
|
|
7511
7656
|
if (line.prefix === "remove") {
|
|
7512
|
-
if (!removedSymbols.has(info.name))
|
|
7513
|
-
removedSymbols.set(info.name, line);
|
|
7514
|
-
}
|
|
7657
|
+
if (!removedSymbols.has(info.name)) removedSymbols.set(info.name, line);
|
|
7515
7658
|
} else {
|
|
7516
|
-
if (!addedSymbols.has(info.name))
|
|
7517
|
-
addedSymbols.set(info.name, line);
|
|
7518
|
-
}
|
|
7659
|
+
if (!addedSymbols.has(info.name)) addedSymbols.set(info.name, line);
|
|
7519
7660
|
}
|
|
7520
7661
|
}
|
|
7521
7662
|
}
|
|
7522
7663
|
const modifiedNames = /* @__PURE__ */ new Set();
|
|
7523
7664
|
for (const name of removedSymbols.keys()) {
|
|
7524
|
-
if (addedSymbols.has(name))
|
|
7525
|
-
modifiedNames.add(name);
|
|
7526
|
-
}
|
|
7665
|
+
if (addedSymbols.has(name)) modifiedNames.add(name);
|
|
7527
7666
|
}
|
|
7528
7667
|
for (const [name, line] of removedSymbols) {
|
|
7529
7668
|
if (!modifiedNames.has(name)) {
|
|
7530
7669
|
const info = extractSymbolInfo(line.content);
|
|
7531
7670
|
if (info) {
|
|
7532
7671
|
processed.add(line.line);
|
|
7533
|
-
entries.push({
|
|
7534
|
-
kind: info.kind,
|
|
7535
|
-
type: "removed",
|
|
7536
|
-
name
|
|
7537
|
-
});
|
|
7672
|
+
entries.push({ kind: info.kind, type: "removed", name });
|
|
7538
7673
|
}
|
|
7539
7674
|
}
|
|
7540
7675
|
}
|
|
@@ -7547,15 +7682,7 @@ function classifyChanges(diffText) {
|
|
|
7547
7682
|
processed.add(removedLine.line);
|
|
7548
7683
|
processed.add(addedLine.line);
|
|
7549
7684
|
const detail = generateModifiedDetail(removedLine.content, addedLine.content, addedInfo.kind);
|
|
7550
|
-
|
|
7551
|
-
const previewLines = extractPreviewLines(diffText, lineNumbers, "modified");
|
|
7552
|
-
entries.push({
|
|
7553
|
-
kind: addedInfo.kind,
|
|
7554
|
-
type: "modified",
|
|
7555
|
-
name,
|
|
7556
|
-
detail,
|
|
7557
|
-
previewLines: previewLines.length > 0 ? previewLines : void 0
|
|
7558
|
-
});
|
|
7685
|
+
entries.push({ kind: addedInfo.kind, type: "modified", name, detail });
|
|
7559
7686
|
}
|
|
7560
7687
|
}
|
|
7561
7688
|
for (const [name, line] of addedSymbols) {
|
|
@@ -7563,13 +7690,7 @@ function classifyChanges(diffText) {
|
|
|
7563
7690
|
const info = extractSymbolInfo(line.content);
|
|
7564
7691
|
if (info) {
|
|
7565
7692
|
processed.add(line.line);
|
|
7566
|
-
|
|
7567
|
-
entries.push({
|
|
7568
|
-
kind: info.kind,
|
|
7569
|
-
type: "added",
|
|
7570
|
-
name,
|
|
7571
|
-
previewLines: previewLines.length > 0 ? previewLines : void 0
|
|
7572
|
-
});
|
|
7693
|
+
entries.push({ kind: info.kind, type: "added", name });
|
|
7573
7694
|
}
|
|
7574
7695
|
}
|
|
7575
7696
|
}
|
|
@@ -7786,52 +7907,6 @@ function extractTypeBody(line) {
|
|
|
7786
7907
|
const eqIndex = line.indexOf("=");
|
|
7787
7908
|
return eqIndex >= 0 ? line.slice(eqIndex + 1).trim() : line.trim();
|
|
7788
7909
|
}
|
|
7789
|
-
var PREVIEW_LINES_LIMIT = 3;
|
|
7790
|
-
function extractPreviewLines(diffText, lineNumbers, type) {
|
|
7791
|
-
if (lineNumbers.length === 0) return [];
|
|
7792
|
-
const lines = diffText.split("\n");
|
|
7793
|
-
const previewLines = [];
|
|
7794
|
-
let foundSymbol = false;
|
|
7795
|
-
for (const targetLine of lineNumbers) {
|
|
7796
|
-
if (previewLines.length >= PREVIEW_LINES_LIMIT) break;
|
|
7797
|
-
const searchStart = Math.max(0, targetLine - 3);
|
|
7798
|
-
const searchEnd = Math.min(lines.length, targetLine + 2);
|
|
7799
|
-
for (let i = searchStart; i < searchEnd; i++) {
|
|
7800
|
-
if (previewLines.length >= PREVIEW_LINES_LIMIT) break;
|
|
7801
|
-
const line = lines[i];
|
|
7802
|
-
if (!line) continue;
|
|
7803
|
-
if (line.startsWith("@@") || line.startsWith("diff ") || line.startsWith("index ")) {
|
|
7804
|
-
continue;
|
|
7805
|
-
}
|
|
7806
|
-
const isAdded = line.startsWith("+");
|
|
7807
|
-
const isRemoved = line.startsWith("-");
|
|
7808
|
-
if (type === "added" && isAdded) {
|
|
7809
|
-
const content = line.slice(1);
|
|
7810
|
-
const trimmed = content.trim();
|
|
7811
|
-
if (trimmed && !trimmed.startsWith("//") && !trimmed.startsWith("/*") && !/^[})\];,\s]*$/.test(trimmed)) {
|
|
7812
|
-
previewLines.push(`[+] ${content}`);
|
|
7813
|
-
foundSymbol = true;
|
|
7814
|
-
}
|
|
7815
|
-
} else if (type === "modified") {
|
|
7816
|
-
if (isRemoved) {
|
|
7817
|
-
const content = line.slice(1);
|
|
7818
|
-
const trimmed = content.trim();
|
|
7819
|
-
if (trimmed && !trimmed.startsWith("//") && !trimmed.startsWith("/*") && !/^[})\];,\s]*$/.test(trimmed)) {
|
|
7820
|
-
previewLines.push(`[-] ${content}`);
|
|
7821
|
-
}
|
|
7822
|
-
} else if (isAdded) {
|
|
7823
|
-
const content = line.slice(1);
|
|
7824
|
-
const trimmed = content.trim();
|
|
7825
|
-
if (trimmed && !trimmed.startsWith("//") && !trimmed.startsWith("/*") && !/^[})\];,\s]*$/.test(trimmed)) {
|
|
7826
|
-
previewLines.push(`[+] ${content}`);
|
|
7827
|
-
}
|
|
7828
|
-
}
|
|
7829
|
-
}
|
|
7830
|
-
}
|
|
7831
|
-
if (foundSymbol && type === "added") break;
|
|
7832
|
-
}
|
|
7833
|
-
return previewLines.slice(0, PREVIEW_LINES_LIMIT);
|
|
7834
|
-
}
|
|
7835
7910
|
var GENERIC_PREVIEW_LINES_LIMIT = 5;
|
|
7836
7911
|
function extractGenericDiffPreview(diffText, filePath) {
|
|
7837
7912
|
if (!diffText.trim()) return [];
|
package/dist/cli.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
depsInfo,
|
|
5
5
|
depsSearch,
|
|
6
6
|
describe
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-4AFO5NLB.js";
|
|
8
8
|
import {
|
|
9
9
|
VERSION,
|
|
10
10
|
area,
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
impact,
|
|
21
21
|
map,
|
|
22
22
|
suggest
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-WESIQAV2.js";
|
|
24
24
|
|
|
25
25
|
// src/cli.ts
|
|
26
26
|
import { resolve } from "path";
|
|
@@ -131,7 +131,7 @@ async function main() {
|
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
if (flags.mcp) {
|
|
134
|
-
const { startMcpServer } = await import("./server-
|
|
134
|
+
const { startMcpServer } = await import("./server-XCWCN2RZ.js");
|
|
135
135
|
await startMcpServer();
|
|
136
136
|
return;
|
|
137
137
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -400,6 +400,12 @@ interface FileChange {
|
|
|
400
400
|
changes: ChangeEntry[];
|
|
401
401
|
/** Arquivo untracked (nunca commitado) */
|
|
402
402
|
newFile?: boolean;
|
|
403
|
+
/** Arquivo foi renomeado */
|
|
404
|
+
renamed?: boolean;
|
|
405
|
+
/** Path original antes do rename */
|
|
406
|
+
renamedFrom?: string;
|
|
407
|
+
/** Tipo de mudança do arquivo no git */
|
|
408
|
+
fileType?: "added" | "deleted" | "changed" | "renamed";
|
|
403
409
|
}
|
|
404
410
|
interface ChangesOptions extends CommandOptions {
|
|
405
411
|
target?: "staged" | "unstaged" | "all";
|
|
@@ -421,6 +427,14 @@ interface ChangesResult {
|
|
|
421
427
|
totalNewFiles: number;
|
|
422
428
|
totalAdded: number;
|
|
423
429
|
totalRemoved: number;
|
|
430
|
+
/** Linhas de arquivos untracked (separado do total de tracked files) */
|
|
431
|
+
totalUntrackedLines: number;
|
|
432
|
+
/** Quantidade de arquivos renomeados */
|
|
433
|
+
totalRenames: number;
|
|
434
|
+
/** Arquivos completamente novos (added no git) */
|
|
435
|
+
totalAddedFiles: number;
|
|
436
|
+
/** Arquivos completamente deletados */
|
|
437
|
+
totalDeletedFiles: number;
|
|
424
438
|
};
|
|
425
439
|
files: FileChange[];
|
|
426
440
|
affectedAreas?: AffectedArea[];
|
|
@@ -625,9 +639,10 @@ declare function functions(options?: FunctionsOptions): Promise<string>;
|
|
|
625
639
|
/**
|
|
626
640
|
* Comando CHANGES - Resumo semantico de mudancas git
|
|
627
641
|
*
|
|
628
|
-
* Analisa arquivos modificados via git diff
|
|
629
|
-
* (added/modified/removed) e categoria
|
|
630
|
-
* usando pattern matching deterministico,
|
|
642
|
+
* Analisa arquivos modificados via git diff usando parse-git-diff como parser,
|
|
643
|
+
* classifica mudancas por tipo (added/modified/removed) e categoria
|
|
644
|
+
* (function/type/import/const/component/hook) usando pattern matching deterministico,
|
|
645
|
+
* e retorna um resumo estruturado.
|
|
631
646
|
*/
|
|
632
647
|
|
|
633
648
|
/**
|
|
@@ -635,6 +650,7 @@ declare function functions(options?: FunctionsOptions): Promise<string>;
|
|
|
635
650
|
*
|
|
636
651
|
* Retorna um resumo semantico de mudancas git otimizado para consumo de IA.
|
|
637
652
|
* Ao inves de mostrar diff bruto, classifica mudancas por tipo e categoria.
|
|
653
|
+
* Usa parse-git-diff como parser principal para maior confiabilidade.
|
|
638
654
|
*/
|
|
639
655
|
declare function changes(options?: ChangesOptions): Promise<string>;
|
|
640
656
|
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
depsInfo,
|
|
4
4
|
depsSearch,
|
|
5
5
|
describe
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-4AFO5NLB.js";
|
|
7
7
|
import {
|
|
8
8
|
VERSION,
|
|
9
9
|
area,
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
map,
|
|
20
20
|
recoveryHint,
|
|
21
21
|
suggest
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-WESIQAV2.js";
|
|
23
23
|
|
|
24
24
|
// src/mcp/server.ts
|
|
25
25
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@justmpm/ai-tool",
|
|
3
|
-
"version": "3.22.
|
|
3
|
+
"version": "3.22.2",
|
|
4
4
|
"description": "Ferramenta de análise de dependências e impacto para projetos TypeScript/JavaScript. Usa Skott + Knip internamente. Inclui busca por descrição, integração Git e testes inteligentes.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dependency-analysis",
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
47
47
|
"knip": "^5.44.0",
|
|
48
48
|
"minimatch": "^10.0.1",
|
|
49
|
+
"parse-git-diff": "^0.0.20",
|
|
49
50
|
"skott": "^0.35.8",
|
|
50
51
|
"ts-morph": "^27.0.2",
|
|
51
52
|
"zod": "^3.25.76"
|