@justmpm/ai-tool 3.22.1 → 3.22.3
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,6 +2028,24 @@ 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
2051
|
OTHER FILES (${otherFiles.length}):
|
|
@@ -5301,58 +5347,45 @@ function getUntrackedFiles(cwd) {
|
|
|
5301
5347
|
return [];
|
|
5302
5348
|
}
|
|
5303
5349
|
}
|
|
5304
|
-
function
|
|
5305
|
-
if (!hasGitRepo(cwd)) return [];
|
|
5306
|
-
try {
|
|
5307
|
-
const diffArgs = getDiffArgs(target);
|
|
5308
|
-
const cmd = `git diff --name-only ${diffArgs.join(" ")}`;
|
|
5309
|
-
const output = execSync2(cmd, {
|
|
5310
|
-
cwd,
|
|
5311
|
-
encoding: "utf-8",
|
|
5312
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
5313
|
-
});
|
|
5314
|
-
return output.trim().split("\n").filter((line) => line.trim() !== "").map((line) => line.trim());
|
|
5315
|
-
} catch {
|
|
5316
|
-
return [];
|
|
5317
|
-
}
|
|
5318
|
-
}
|
|
5319
|
-
function getDiffForFile(filePath, target, cwd) {
|
|
5350
|
+
function getFullDiffText(target, cwd, filePath) {
|
|
5320
5351
|
if (!hasGitRepo(cwd)) return "";
|
|
5352
|
+
const fileArg = filePath ? ` -- "${filePath}"` : "";
|
|
5321
5353
|
try {
|
|
5354
|
+
if (target === "all") {
|
|
5355
|
+
let output2 = "";
|
|
5356
|
+
try {
|
|
5357
|
+
output2 += execSync2(`git diff --unified=10${fileArg} --cached`, {
|
|
5358
|
+
cwd,
|
|
5359
|
+
encoding: "utf-8",
|
|
5360
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
5361
|
+
maxBuffer: 10 * 1024 * 1024
|
|
5362
|
+
});
|
|
5363
|
+
} catch {
|
|
5364
|
+
}
|
|
5365
|
+
try {
|
|
5366
|
+
output2 += execSync2(`git diff --unified=10${fileArg}`, {
|
|
5367
|
+
cwd,
|
|
5368
|
+
encoding: "utf-8",
|
|
5369
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
5370
|
+
maxBuffer: 10 * 1024 * 1024
|
|
5371
|
+
});
|
|
5372
|
+
} catch {
|
|
5373
|
+
}
|
|
5374
|
+
return output2;
|
|
5375
|
+
}
|
|
5322
5376
|
const diffArgs = getDiffArgs(target);
|
|
5323
|
-
const cmd = `git diff
|
|
5377
|
+
const cmd = `git diff --unified=10${fileArg} ${diffArgs.join(" ")}`;
|
|
5324
5378
|
const output = execSync2(cmd, {
|
|
5325
5379
|
cwd,
|
|
5326
5380
|
encoding: "utf-8",
|
|
5327
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
5381
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
5382
|
+
maxBuffer: 10 * 1024 * 1024
|
|
5328
5383
|
});
|
|
5329
5384
|
return output;
|
|
5330
5385
|
} catch {
|
|
5331
5386
|
return "";
|
|
5332
5387
|
}
|
|
5333
5388
|
}
|
|
5334
|
-
function getDiffStats(filePath, target, cwd) {
|
|
5335
|
-
if (!hasGitRepo(cwd)) return null;
|
|
5336
|
-
try {
|
|
5337
|
-
const diffArgs = getDiffArgs(target);
|
|
5338
|
-
const cmd = `git diff --numstat ${diffArgs.join(" ")} -- "${filePath}"`;
|
|
5339
|
-
const output = execSync2(cmd, {
|
|
5340
|
-
cwd,
|
|
5341
|
-
encoding: "utf-8",
|
|
5342
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
5343
|
-
});
|
|
5344
|
-
const line = output.trim().split("\n")[0];
|
|
5345
|
-
if (!line) return null;
|
|
5346
|
-
const parts = line.split(" ");
|
|
5347
|
-
if (parts.length < 2) return null;
|
|
5348
|
-
const added = parts[0] === "-" ? 0 : parseInt(parts[0], 10);
|
|
5349
|
-
const removed = parts[1] === "-" ? 0 : parseInt(parts[1], 10);
|
|
5350
|
-
if (Number.isNaN(added) || Number.isNaN(removed)) return null;
|
|
5351
|
-
return { added, removed };
|
|
5352
|
-
} catch {
|
|
5353
|
-
return null;
|
|
5354
|
-
}
|
|
5355
|
-
}
|
|
5356
5389
|
|
|
5357
5390
|
// src/commands/impact.ts
|
|
5358
5391
|
async function impact(target, options = {}) {
|
|
@@ -7266,6 +7299,7 @@ function getTriggerIcon(trigger) {
|
|
|
7266
7299
|
// src/commands/changes.ts
|
|
7267
7300
|
import * as path from "path";
|
|
7268
7301
|
import { readFileSync as readFileSync7 } from "fs";
|
|
7302
|
+
import parseGitDiff from "parse-git-diff";
|
|
7269
7303
|
var UNTRACKED_PREVIEW_LINES = 20;
|
|
7270
7304
|
async function changes(options = {}) {
|
|
7271
7305
|
const { cwd, format } = parseCommandOptions(options);
|
|
@@ -7275,59 +7309,55 @@ async function changes(options = {}) {
|
|
|
7275
7309
|
throw new Error("Nao e um repositorio Git. Execute este comando em um projeto com Git.");
|
|
7276
7310
|
}
|
|
7277
7311
|
try {
|
|
7278
|
-
const
|
|
7312
|
+
const diffText = getFullDiffText(target, cwd, options.file || void 0);
|
|
7279
7313
|
const untrackedFiles = getUntrackedFiles(cwd);
|
|
7280
|
-
if (changedFiles.length === 0 && untrackedFiles.length === 0) {
|
|
7281
|
-
const result2 = {
|
|
7282
|
-
version: "1.0.0",
|
|
7283
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7284
|
-
target,
|
|
7285
|
-
summary: {
|
|
7286
|
-
totalFiles: 0,
|
|
7287
|
-
totalNewFiles: 0,
|
|
7288
|
-
totalAdded: 0,
|
|
7289
|
-
totalRemoved: 0
|
|
7290
|
-
},
|
|
7291
|
-
files: []
|
|
7292
|
-
};
|
|
7293
|
-
return formatOutput(result2, format, (r) => formatChangesText(r, ctx));
|
|
7294
|
-
}
|
|
7295
7314
|
const DEFAULT_IGNORE = [".analyze/"];
|
|
7296
|
-
|
|
7297
|
-
|
|
7298
|
-
|
|
7299
|
-
|
|
7300
|
-
(f) => !DEFAULT_IGNORE.some((pattern) => f.includes(pattern))
|
|
7301
|
-
);
|
|
7302
|
-
const filesToProcess = options.file ? filesFiltered.filter(
|
|
7303
|
-
(f) => f.toLowerCase().includes(options.file.toLowerCase())
|
|
7304
|
-
) : filesFiltered;
|
|
7305
|
-
const untrackedToProcess = options.file ? untrackedFiltered.filter(
|
|
7306
|
-
(f) => f.toLowerCase().includes(options.file.toLowerCase())
|
|
7307
|
-
) : untrackedFiltered;
|
|
7315
|
+
let parsed = null;
|
|
7316
|
+
if (diffText.trim()) {
|
|
7317
|
+
parsed = parseGitDiff(diffText);
|
|
7318
|
+
}
|
|
7308
7319
|
const fileChanges = [];
|
|
7309
7320
|
let totalAdded = 0;
|
|
7310
7321
|
let totalRemoved = 0;
|
|
7322
|
+
let totalRenames = 0;
|
|
7323
|
+
let totalAddedFiles = 0;
|
|
7324
|
+
let totalDeletedFiles = 0;
|
|
7311
7325
|
const symbolsIndex = await loadCachedSymbolsIndex(cwd);
|
|
7312
|
-
|
|
7313
|
-
const
|
|
7314
|
-
|
|
7315
|
-
|
|
7316
|
-
|
|
7317
|
-
|
|
7318
|
-
|
|
7319
|
-
|
|
7320
|
-
|
|
7321
|
-
|
|
7322
|
-
|
|
7323
|
-
|
|
7324
|
-
|
|
7325
|
-
|
|
7326
|
-
|
|
7327
|
-
|
|
7328
|
-
|
|
7329
|
-
|
|
7326
|
+
if (parsed && parsed.files.length > 0) {
|
|
7327
|
+
for (const file of parsed.files) {
|
|
7328
|
+
const filePath = resolveFilePath(file);
|
|
7329
|
+
if (options.file) {
|
|
7330
|
+
if (!filePath.toLowerCase().includes(options.file.toLowerCase())) continue;
|
|
7331
|
+
}
|
|
7332
|
+
if (DEFAULT_IGNORE.some((p) => filePath.includes(p))) continue;
|
|
7333
|
+
const chunks = extractChunks(file);
|
|
7334
|
+
const { added, removed, entries } = processChunks(chunks, filePath, symbolsIndex);
|
|
7335
|
+
const fileType = resolveFileType(file);
|
|
7336
|
+
const change = {
|
|
7337
|
+
path: filePath,
|
|
7338
|
+
category: detectCategory(filePath),
|
|
7339
|
+
stats: { added, removed },
|
|
7340
|
+
changes: entries,
|
|
7341
|
+
fileType
|
|
7342
|
+
};
|
|
7343
|
+
if (file.type === "RenamedFile") {
|
|
7344
|
+
const renamedFile = file;
|
|
7345
|
+
change.renamed = true;
|
|
7346
|
+
change.renamedFrom = renamedFile.pathBefore;
|
|
7347
|
+
totalRenames++;
|
|
7348
|
+
}
|
|
7349
|
+
if (file.type === "AddedFile") totalAddedFiles++;
|
|
7350
|
+
if (file.type === "DeletedFile") totalDeletedFiles++;
|
|
7351
|
+
totalAdded += added;
|
|
7352
|
+
totalRemoved += removed;
|
|
7353
|
+
fileChanges.push(change);
|
|
7354
|
+
}
|
|
7330
7355
|
}
|
|
7356
|
+
let totalUntrackedLines = 0;
|
|
7357
|
+
const untrackedFiltered = untrackedFiles.filter(
|
|
7358
|
+
(f) => !DEFAULT_IGNORE.some((p) => f.includes(p))
|
|
7359
|
+
);
|
|
7360
|
+
const untrackedToProcess = options.file ? untrackedFiltered.filter((f) => f.toLowerCase().includes(options.file.toLowerCase())) : untrackedFiltered;
|
|
7331
7361
|
for (const filePath of untrackedToProcess) {
|
|
7332
7362
|
const fullFilePath = path.resolve(cwd, filePath);
|
|
7333
7363
|
let lineCount = 0;
|
|
@@ -7349,31 +7379,36 @@ async function changes(options = {}) {
|
|
|
7349
7379
|
category: detectCategory(filePath),
|
|
7350
7380
|
stats: { added: lineCount, removed: 0 },
|
|
7351
7381
|
changes: enrichedEntries,
|
|
7352
|
-
newFile: true
|
|
7382
|
+
newFile: true,
|
|
7383
|
+
fileType: "added"
|
|
7353
7384
|
});
|
|
7354
|
-
|
|
7385
|
+
totalUntrackedLines += lineCount;
|
|
7355
7386
|
} catch {
|
|
7356
7387
|
fileChanges.push({
|
|
7357
7388
|
path: filePath,
|
|
7358
7389
|
category: detectCategory(filePath),
|
|
7359
7390
|
stats: { added: 0, removed: 0 },
|
|
7360
7391
|
changes: [],
|
|
7361
|
-
newFile: true
|
|
7392
|
+
newFile: true,
|
|
7393
|
+
fileType: "added"
|
|
7362
7394
|
});
|
|
7363
7395
|
}
|
|
7364
7396
|
}
|
|
7365
7397
|
const affectedAreas = buildAffectedAreas(fileChanges, cwd);
|
|
7366
|
-
const
|
|
7367
|
-
const totalNewForSummary = options.file ? fileChanges.filter((f) => f.newFile).length : untrackedFiles.length;
|
|
7398
|
+
const trackedFiles = fileChanges.filter((f) => !f.newFile);
|
|
7368
7399
|
const result = {
|
|
7369
7400
|
version: "1.0.0",
|
|
7370
7401
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7371
7402
|
target,
|
|
7372
7403
|
summary: {
|
|
7373
|
-
totalFiles:
|
|
7374
|
-
totalNewFiles:
|
|
7404
|
+
totalFiles: trackedFiles.length,
|
|
7405
|
+
totalNewFiles: untrackedToProcess.length,
|
|
7375
7406
|
totalAdded,
|
|
7376
|
-
totalRemoved
|
|
7407
|
+
totalRemoved,
|
|
7408
|
+
totalUntrackedLines,
|
|
7409
|
+
totalRenames,
|
|
7410
|
+
totalAddedFiles,
|
|
7411
|
+
totalDeletedFiles
|
|
7377
7412
|
},
|
|
7378
7413
|
files: fileChanges,
|
|
7379
7414
|
affectedAreas: affectedAreas.length > 0 ? affectedAreas : void 0
|
|
@@ -7384,6 +7419,142 @@ async function changes(options = {}) {
|
|
|
7384
7419
|
throw new Error(`Erro ao executar changes: ${message}`);
|
|
7385
7420
|
}
|
|
7386
7421
|
}
|
|
7422
|
+
function resolveFilePath(file) {
|
|
7423
|
+
if (file.type === "RenamedFile") return file.pathAfter;
|
|
7424
|
+
return file.path;
|
|
7425
|
+
}
|
|
7426
|
+
function extractChunks(file) {
|
|
7427
|
+
if ("chunks" in file) {
|
|
7428
|
+
return file.chunks.filter((c) => c.type === "Chunk");
|
|
7429
|
+
}
|
|
7430
|
+
return [];
|
|
7431
|
+
}
|
|
7432
|
+
function resolveFileType(file) {
|
|
7433
|
+
switch (file.type) {
|
|
7434
|
+
case "AddedFile":
|
|
7435
|
+
return "added";
|
|
7436
|
+
case "DeletedFile":
|
|
7437
|
+
return "deleted";
|
|
7438
|
+
case "RenamedFile":
|
|
7439
|
+
return "renamed";
|
|
7440
|
+
case "ChangedFile":
|
|
7441
|
+
return "changed";
|
|
7442
|
+
}
|
|
7443
|
+
}
|
|
7444
|
+
function processChunks(chunks, filePath, symbolsIndex) {
|
|
7445
|
+
let added = 0;
|
|
7446
|
+
let removed = 0;
|
|
7447
|
+
const allAddedLines = [];
|
|
7448
|
+
const allDeletedLines = [];
|
|
7449
|
+
for (const chunk of chunks) {
|
|
7450
|
+
for (const change of chunk.changes) {
|
|
7451
|
+
if (change.type === "AddedLine") {
|
|
7452
|
+
added++;
|
|
7453
|
+
allAddedLines.push(change.content);
|
|
7454
|
+
} else if (change.type === "DeletedLine") {
|
|
7455
|
+
removed++;
|
|
7456
|
+
allDeletedLines.push(change.content);
|
|
7457
|
+
}
|
|
7458
|
+
}
|
|
7459
|
+
}
|
|
7460
|
+
const entries = classifyFromStructuredLines(allAddedLines, allDeletedLines);
|
|
7461
|
+
if (entries.length === 0 && added + removed > 0) {
|
|
7462
|
+
const previewText = buildSyntheticDiff(allAddedLines, allDeletedLines);
|
|
7463
|
+
const genericEntries = extractGenericDiffPreview(previewText, filePath);
|
|
7464
|
+
entries.push(...genericEntries);
|
|
7465
|
+
}
|
|
7466
|
+
const enrichedEntries = enrichWithJsDoc(entries, filePath, symbolsIndex);
|
|
7467
|
+
return { added, removed, entries: enrichedEntries };
|
|
7468
|
+
}
|
|
7469
|
+
function buildSyntheticDiff(addedLines, deletedLines) {
|
|
7470
|
+
const lines = [];
|
|
7471
|
+
const maxPreview = 10;
|
|
7472
|
+
for (const line of deletedLines.slice(0, maxPreview)) {
|
|
7473
|
+
lines.push(`-${line}`);
|
|
7474
|
+
}
|
|
7475
|
+
for (const line of addedLines.slice(0, maxPreview)) {
|
|
7476
|
+
lines.push(`+${line}`);
|
|
7477
|
+
}
|
|
7478
|
+
return lines.join("\n");
|
|
7479
|
+
}
|
|
7480
|
+
function classifyFromStructuredLines(addedLines, deletedLines) {
|
|
7481
|
+
const entries = [];
|
|
7482
|
+
const removedSymbols = /* @__PURE__ */ new Map();
|
|
7483
|
+
for (const line of deletedLines) {
|
|
7484
|
+
const multiReexport = extractMultipleReexports(line);
|
|
7485
|
+
if (multiReexport) {
|
|
7486
|
+
for (const name of multiReexport.names) {
|
|
7487
|
+
if (!removedSymbols.has(name)) {
|
|
7488
|
+
removedSymbols.set(name, { kind: multiReexport.kind, content: line });
|
|
7489
|
+
}
|
|
7490
|
+
}
|
|
7491
|
+
continue;
|
|
7492
|
+
}
|
|
7493
|
+
const info = extractSymbolInfo(line);
|
|
7494
|
+
if (info && info.name && isRelevantSymbol(info)) {
|
|
7495
|
+
if (!removedSymbols.has(info.name)) {
|
|
7496
|
+
removedSymbols.set(info.name, { kind: info.kind, content: line });
|
|
7497
|
+
}
|
|
7498
|
+
}
|
|
7499
|
+
}
|
|
7500
|
+
const addedSymbols = /* @__PURE__ */ new Map();
|
|
7501
|
+
for (const line of addedLines) {
|
|
7502
|
+
const multiReexport = extractMultipleReexports(line);
|
|
7503
|
+
if (multiReexport) {
|
|
7504
|
+
for (const name of multiReexport.names) {
|
|
7505
|
+
if (!addedSymbols.has(name)) {
|
|
7506
|
+
addedSymbols.set(name, { kind: multiReexport.kind, content: line });
|
|
7507
|
+
}
|
|
7508
|
+
}
|
|
7509
|
+
continue;
|
|
7510
|
+
}
|
|
7511
|
+
const info = extractSymbolInfo(line);
|
|
7512
|
+
if (info && info.name && isRelevantSymbol(info)) {
|
|
7513
|
+
if (!addedSymbols.has(info.name)) {
|
|
7514
|
+
addedSymbols.set(info.name, { kind: info.kind, content: line });
|
|
7515
|
+
}
|
|
7516
|
+
}
|
|
7517
|
+
}
|
|
7518
|
+
const modifiedNames = /* @__PURE__ */ new Set();
|
|
7519
|
+
for (const name of removedSymbols.keys()) {
|
|
7520
|
+
if (addedSymbols.has(name)) modifiedNames.add(name);
|
|
7521
|
+
}
|
|
7522
|
+
for (const [name, { kind }] of removedSymbols) {
|
|
7523
|
+
if (!modifiedNames.has(name)) {
|
|
7524
|
+
entries.push({ kind, type: "removed", name });
|
|
7525
|
+
}
|
|
7526
|
+
}
|
|
7527
|
+
for (const name of modifiedNames) {
|
|
7528
|
+
const removed = removedSymbols.get(name);
|
|
7529
|
+
const added = addedSymbols.get(name);
|
|
7530
|
+
const detail = generateModifiedDetail(removed.content, added.content, added.kind);
|
|
7531
|
+
entries.push({ kind: added.kind, type: "modified", name, detail });
|
|
7532
|
+
}
|
|
7533
|
+
for (const [name, { kind, content }] of addedSymbols) {
|
|
7534
|
+
if (!modifiedNames.has(name)) {
|
|
7535
|
+
const previewLines = buildPreviewFromLines([content], "added");
|
|
7536
|
+
entries.push({
|
|
7537
|
+
kind,
|
|
7538
|
+
type: "added",
|
|
7539
|
+
name,
|
|
7540
|
+
previewLines: previewLines.length > 0 ? previewLines : void 0
|
|
7541
|
+
});
|
|
7542
|
+
}
|
|
7543
|
+
}
|
|
7544
|
+
return entries;
|
|
7545
|
+
}
|
|
7546
|
+
function buildPreviewFromLines(lines, type) {
|
|
7547
|
+
const preview = [];
|
|
7548
|
+
const limit = type === "added" ? 2 : 4;
|
|
7549
|
+
for (const line of lines) {
|
|
7550
|
+
if (preview.length >= limit) break;
|
|
7551
|
+
const trimmed = line.trim();
|
|
7552
|
+
if (trimmed && !trimmed.startsWith("//") && !trimmed.startsWith("/*") && !/^[})\];,]*$/.test(trimmed)) {
|
|
7553
|
+
preview.push(type === "added" ? `[+] ${line}` : `[+] ${line}`);
|
|
7554
|
+
}
|
|
7555
|
+
}
|
|
7556
|
+
return preview.slice(0, limit);
|
|
7557
|
+
}
|
|
7387
7558
|
function enrichWithJsDoc(entries, filePath, cachedIndex) {
|
|
7388
7559
|
const needsEnrichment = (e) => e.kind !== "import" && e.kind !== "config" && !e.detail;
|
|
7389
7560
|
if (!entries.some(needsEnrichment)) {
|
|
@@ -7496,13 +7667,9 @@ function classifyChanges(diffText) {
|
|
|
7496
7667
|
if (multiReexport) {
|
|
7497
7668
|
for (const name of multiReexport.names) {
|
|
7498
7669
|
if (line.prefix === "remove") {
|
|
7499
|
-
if (!removedSymbols.has(name))
|
|
7500
|
-
removedSymbols.set(name, line);
|
|
7501
|
-
}
|
|
7670
|
+
if (!removedSymbols.has(name)) removedSymbols.set(name, line);
|
|
7502
7671
|
} else {
|
|
7503
|
-
if (!addedSymbols.has(name))
|
|
7504
|
-
addedSymbols.set(name, line);
|
|
7505
|
-
}
|
|
7672
|
+
if (!addedSymbols.has(name)) addedSymbols.set(name, line);
|
|
7506
7673
|
}
|
|
7507
7674
|
}
|
|
7508
7675
|
continue;
|
|
@@ -7510,32 +7677,22 @@ function classifyChanges(diffText) {
|
|
|
7510
7677
|
const info = extractSymbolInfo(line.content);
|
|
7511
7678
|
if (info && info.name && isRelevantSymbol(info)) {
|
|
7512
7679
|
if (line.prefix === "remove") {
|
|
7513
|
-
if (!removedSymbols.has(info.name))
|
|
7514
|
-
removedSymbols.set(info.name, line);
|
|
7515
|
-
}
|
|
7680
|
+
if (!removedSymbols.has(info.name)) removedSymbols.set(info.name, line);
|
|
7516
7681
|
} else {
|
|
7517
|
-
if (!addedSymbols.has(info.name))
|
|
7518
|
-
addedSymbols.set(info.name, line);
|
|
7519
|
-
}
|
|
7682
|
+
if (!addedSymbols.has(info.name)) addedSymbols.set(info.name, line);
|
|
7520
7683
|
}
|
|
7521
7684
|
}
|
|
7522
7685
|
}
|
|
7523
7686
|
const modifiedNames = /* @__PURE__ */ new Set();
|
|
7524
7687
|
for (const name of removedSymbols.keys()) {
|
|
7525
|
-
if (addedSymbols.has(name))
|
|
7526
|
-
modifiedNames.add(name);
|
|
7527
|
-
}
|
|
7688
|
+
if (addedSymbols.has(name)) modifiedNames.add(name);
|
|
7528
7689
|
}
|
|
7529
7690
|
for (const [name, line] of removedSymbols) {
|
|
7530
7691
|
if (!modifiedNames.has(name)) {
|
|
7531
7692
|
const info = extractSymbolInfo(line.content);
|
|
7532
7693
|
if (info) {
|
|
7533
7694
|
processed.add(line.line);
|
|
7534
|
-
entries.push({
|
|
7535
|
-
kind: info.kind,
|
|
7536
|
-
type: "removed",
|
|
7537
|
-
name
|
|
7538
|
-
});
|
|
7695
|
+
entries.push({ kind: info.kind, type: "removed", name });
|
|
7539
7696
|
}
|
|
7540
7697
|
}
|
|
7541
7698
|
}
|
|
@@ -7548,15 +7705,7 @@ function classifyChanges(diffText) {
|
|
|
7548
7705
|
processed.add(removedLine.line);
|
|
7549
7706
|
processed.add(addedLine.line);
|
|
7550
7707
|
const detail = generateModifiedDetail(removedLine.content, addedLine.content, addedInfo.kind);
|
|
7551
|
-
|
|
7552
|
-
const previewLines = extractPreviewLines(diffText, lineNumbers, "modified");
|
|
7553
|
-
entries.push({
|
|
7554
|
-
kind: addedInfo.kind,
|
|
7555
|
-
type: "modified",
|
|
7556
|
-
name,
|
|
7557
|
-
detail,
|
|
7558
|
-
previewLines: previewLines.length > 0 ? previewLines : void 0
|
|
7559
|
-
});
|
|
7708
|
+
entries.push({ kind: addedInfo.kind, type: "modified", name, detail });
|
|
7560
7709
|
}
|
|
7561
7710
|
}
|
|
7562
7711
|
for (const [name, line] of addedSymbols) {
|
|
@@ -7564,13 +7713,7 @@ function classifyChanges(diffText) {
|
|
|
7564
7713
|
const info = extractSymbolInfo(line.content);
|
|
7565
7714
|
if (info) {
|
|
7566
7715
|
processed.add(line.line);
|
|
7567
|
-
|
|
7568
|
-
entries.push({
|
|
7569
|
-
kind: info.kind,
|
|
7570
|
-
type: "added",
|
|
7571
|
-
name,
|
|
7572
|
-
previewLines: previewLines.length > 0 ? previewLines : void 0
|
|
7573
|
-
});
|
|
7716
|
+
entries.push({ kind: info.kind, type: "added", name });
|
|
7574
7717
|
}
|
|
7575
7718
|
}
|
|
7576
7719
|
}
|
|
@@ -7787,52 +7930,6 @@ function extractTypeBody(line) {
|
|
|
7787
7930
|
const eqIndex = line.indexOf("=");
|
|
7788
7931
|
return eqIndex >= 0 ? line.slice(eqIndex + 1).trim() : line.trim();
|
|
7789
7932
|
}
|
|
7790
|
-
var PREVIEW_LINES_LIMIT = 3;
|
|
7791
|
-
function extractPreviewLines(diffText, lineNumbers, type) {
|
|
7792
|
-
if (lineNumbers.length === 0) return [];
|
|
7793
|
-
const lines = diffText.split("\n");
|
|
7794
|
-
const previewLines = [];
|
|
7795
|
-
let foundSymbol = false;
|
|
7796
|
-
for (const targetLine of lineNumbers) {
|
|
7797
|
-
if (previewLines.length >= PREVIEW_LINES_LIMIT) break;
|
|
7798
|
-
const searchStart = Math.max(0, targetLine - 3);
|
|
7799
|
-
const searchEnd = Math.min(lines.length, targetLine + 2);
|
|
7800
|
-
for (let i = searchStart; i < searchEnd; i++) {
|
|
7801
|
-
if (previewLines.length >= PREVIEW_LINES_LIMIT) break;
|
|
7802
|
-
const line = lines[i];
|
|
7803
|
-
if (!line) continue;
|
|
7804
|
-
if (line.startsWith("@@") || line.startsWith("diff ") || line.startsWith("index ")) {
|
|
7805
|
-
continue;
|
|
7806
|
-
}
|
|
7807
|
-
const isAdded = line.startsWith("+");
|
|
7808
|
-
const isRemoved = line.startsWith("-");
|
|
7809
|
-
if (type === "added" && isAdded) {
|
|
7810
|
-
const content = line.slice(1);
|
|
7811
|
-
const trimmed = content.trim();
|
|
7812
|
-
if (trimmed && !trimmed.startsWith("//") && !trimmed.startsWith("/*") && !/^[})\];,\s]*$/.test(trimmed)) {
|
|
7813
|
-
previewLines.push(`[+] ${content}`);
|
|
7814
|
-
foundSymbol = true;
|
|
7815
|
-
}
|
|
7816
|
-
} else if (type === "modified") {
|
|
7817
|
-
if (isRemoved) {
|
|
7818
|
-
const content = line.slice(1);
|
|
7819
|
-
const trimmed = content.trim();
|
|
7820
|
-
if (trimmed && !trimmed.startsWith("//") && !trimmed.startsWith("/*") && !/^[})\];,\s]*$/.test(trimmed)) {
|
|
7821
|
-
previewLines.push(`[-] ${content}`);
|
|
7822
|
-
}
|
|
7823
|
-
} else if (isAdded) {
|
|
7824
|
-
const content = line.slice(1);
|
|
7825
|
-
const trimmed = content.trim();
|
|
7826
|
-
if (trimmed && !trimmed.startsWith("//") && !trimmed.startsWith("/*") && !/^[})\];,\s]*$/.test(trimmed)) {
|
|
7827
|
-
previewLines.push(`[+] ${content}`);
|
|
7828
|
-
}
|
|
7829
|
-
}
|
|
7830
|
-
}
|
|
7831
|
-
}
|
|
7832
|
-
if (foundSymbol && type === "added") break;
|
|
7833
|
-
}
|
|
7834
|
-
return previewLines.slice(0, PREVIEW_LINES_LIMIT);
|
|
7835
|
-
}
|
|
7836
7933
|
var GENERIC_PREVIEW_LINES_LIMIT = 5;
|
|
7837
7934
|
function extractGenericDiffPreview(diffText, filePath) {
|
|
7838
7935
|
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-WSOR2KFZ.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-A56FYR42.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-R46RC5Y2.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-WSOR2KFZ.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-A56FYR42.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.3",
|
|
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"
|