@aiready/context-analyzer 0.19.9 → 0.19.11
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/.turbo/turbo-build.log +10 -10
- package/.turbo/turbo-test.log +20 -20
- package/dist/chunk-P5YV5WIX.mjs +1803 -0
- package/dist/cli.js +164 -155
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +158 -149
- package/dist/index.mjs +1 -1
- package/package.json +2 -2
- package/src/index.ts +1 -0
- package/src/provider.ts +1 -1
- package/src/summary.ts +13 -1
- package/src/types.ts +1 -0
package/dist/index.js
CHANGED
|
@@ -37,7 +37,7 @@ __export(python_context_exports, {
|
|
|
37
37
|
});
|
|
38
38
|
async function analyzePythonContext(files, rootDir) {
|
|
39
39
|
const results = [];
|
|
40
|
-
const parser = (0,
|
|
40
|
+
const parser = (0, import_core9.getParser)("dummy.py");
|
|
41
41
|
if (!parser) {
|
|
42
42
|
console.warn("Python parser not available");
|
|
43
43
|
return results;
|
|
@@ -101,7 +101,7 @@ async function analyzePythonContext(files, rootDir) {
|
|
|
101
101
|
}
|
|
102
102
|
async function buildPythonDependencyGraph(files, rootDir) {
|
|
103
103
|
const graph = /* @__PURE__ */ new Map();
|
|
104
|
-
const parser = (0,
|
|
104
|
+
const parser = (0, import_core9.getParser)("dummy.py");
|
|
105
105
|
if (!parser) return graph;
|
|
106
106
|
for (const file of files) {
|
|
107
107
|
try {
|
|
@@ -181,7 +181,7 @@ async function calculatePythonImportDepth(file, dependencyGraph, visited, depth
|
|
|
181
181
|
}
|
|
182
182
|
function estimateContextBudget(code, imports, dependencyGraph) {
|
|
183
183
|
void dependencyGraph;
|
|
184
|
-
let budget = (0,
|
|
184
|
+
let budget = (0, import_core9.estimateTokens)(code);
|
|
185
185
|
const avgTokensPerDep = 500;
|
|
186
186
|
budget += imports.length * avgTokensPerDep;
|
|
187
187
|
return budget;
|
|
@@ -231,11 +231,11 @@ function detectCircularDependencies2(file, dependencyGraph) {
|
|
|
231
231
|
dfs(file, []);
|
|
232
232
|
return [...new Set(circular)];
|
|
233
233
|
}
|
|
234
|
-
var
|
|
234
|
+
var import_core9, import_path, import_fs;
|
|
235
235
|
var init_python_context = __esm({
|
|
236
236
|
"src/analyzers/python-context.ts"() {
|
|
237
237
|
"use strict";
|
|
238
|
-
|
|
238
|
+
import_core9 = require("@aiready/core");
|
|
239
239
|
import_path = require("path");
|
|
240
240
|
import_fs = __toESM(require("fs"));
|
|
241
241
|
}
|
|
@@ -291,7 +291,7 @@ __export(index_exports, {
|
|
|
291
291
|
mapScoreToRating: () => mapScoreToRating
|
|
292
292
|
});
|
|
293
293
|
module.exports = __toCommonJS(index_exports);
|
|
294
|
-
var
|
|
294
|
+
var import_core10 = require("@aiready/core");
|
|
295
295
|
|
|
296
296
|
// src/analyzer.ts
|
|
297
297
|
var import_core4 = require("@aiready/core");
|
|
@@ -1490,11 +1490,146 @@ function isBuildArtifact(filePath) {
|
|
|
1490
1490
|
return lower.includes("/node_modules/") || lower.includes("/dist/") || lower.includes("/build/") || lower.includes("/out/") || lower.includes("/.next/");
|
|
1491
1491
|
}
|
|
1492
1492
|
|
|
1493
|
+
// src/summary.ts
|
|
1494
|
+
var import_core5 = require("@aiready/core");
|
|
1495
|
+
function generateSummary(results, options) {
|
|
1496
|
+
const config = options ? Object.fromEntries(
|
|
1497
|
+
Object.entries(options).filter(
|
|
1498
|
+
([key]) => !import_core5.GLOBAL_SCAN_OPTIONS.includes(key) || key === "rootDir"
|
|
1499
|
+
)
|
|
1500
|
+
) : void 0;
|
|
1501
|
+
if (results.length === 0) {
|
|
1502
|
+
return {
|
|
1503
|
+
totalFiles: 0,
|
|
1504
|
+
totalTokens: 0,
|
|
1505
|
+
avgContextBudget: 0,
|
|
1506
|
+
maxContextBudget: 0,
|
|
1507
|
+
avgImportDepth: 0,
|
|
1508
|
+
maxImportDepth: 0,
|
|
1509
|
+
deepFiles: [],
|
|
1510
|
+
avgFragmentation: 0,
|
|
1511
|
+
fragmentedModules: [],
|
|
1512
|
+
avgCohesion: 0,
|
|
1513
|
+
lowCohesionFiles: [],
|
|
1514
|
+
criticalIssues: 0,
|
|
1515
|
+
majorIssues: 0,
|
|
1516
|
+
minorIssues: 0,
|
|
1517
|
+
totalPotentialSavings: 0,
|
|
1518
|
+
topExpensiveFiles: [],
|
|
1519
|
+
config
|
|
1520
|
+
};
|
|
1521
|
+
}
|
|
1522
|
+
const totalFiles = results.length;
|
|
1523
|
+
const totalTokens = results.reduce((sum, r) => sum + r.tokenCost, 0);
|
|
1524
|
+
const totalContextBudget = results.reduce(
|
|
1525
|
+
(sum, r) => sum + r.contextBudget,
|
|
1526
|
+
0
|
|
1527
|
+
);
|
|
1528
|
+
const avgContextBudget = totalContextBudget / totalFiles;
|
|
1529
|
+
const maxContextBudget = Math.max(...results.map((r) => r.contextBudget));
|
|
1530
|
+
const avgImportDepth = results.reduce((sum, r) => sum + r.importDepth, 0) / totalFiles;
|
|
1531
|
+
const maxImportDepth = Math.max(...results.map((r) => r.importDepth));
|
|
1532
|
+
const deepFiles = results.filter((r) => r.importDepth >= 5).map((r) => ({ file: r.file, depth: r.importDepth })).sort((a, b) => b.depth - a.depth).slice(0, 10);
|
|
1533
|
+
const avgFragmentation = results.reduce((sum, r) => sum + r.fragmentationScore, 0) / totalFiles;
|
|
1534
|
+
const moduleMap = /* @__PURE__ */ new Map();
|
|
1535
|
+
for (const result of results) {
|
|
1536
|
+
for (const domain of result.domains) {
|
|
1537
|
+
if (!moduleMap.has(domain)) moduleMap.set(domain, []);
|
|
1538
|
+
moduleMap.get(domain).push(result);
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1541
|
+
const fragmentedModules = [];
|
|
1542
|
+
for (const [domain, files] of moduleMap.entries()) {
|
|
1543
|
+
let jaccard2 = function(a, b) {
|
|
1544
|
+
const s1 = new Set(a || []);
|
|
1545
|
+
const s2 = new Set(b || []);
|
|
1546
|
+
if (s1.size === 0 && s2.size === 0) return 0;
|
|
1547
|
+
const inter = new Set([...s1].filter((x) => s2.has(x)));
|
|
1548
|
+
const uni = /* @__PURE__ */ new Set([...s1, ...s2]);
|
|
1549
|
+
return uni.size === 0 ? 0 : inter.size / uni.size;
|
|
1550
|
+
};
|
|
1551
|
+
var jaccard = jaccard2;
|
|
1552
|
+
if (files.length < 2) continue;
|
|
1553
|
+
const fragmentationScore = files.reduce((sum, f) => sum + f.fragmentationScore, 0) / files.length;
|
|
1554
|
+
if (fragmentationScore < 0.3) continue;
|
|
1555
|
+
const totalTokens2 = files.reduce((sum, f) => sum + f.tokenCost, 0);
|
|
1556
|
+
const avgCohesion2 = files.reduce((sum, f) => sum + f.cohesionScore, 0) / files.length;
|
|
1557
|
+
const targetFiles = Math.max(1, Math.ceil(files.length / 3));
|
|
1558
|
+
const filePaths = files.map((f) => f.file);
|
|
1559
|
+
const pathEntropy = calculatePathEntropy(filePaths);
|
|
1560
|
+
const directoryDistance = calculateDirectoryDistance(filePaths);
|
|
1561
|
+
let importSimTotal = 0;
|
|
1562
|
+
let importPairs = 0;
|
|
1563
|
+
for (let i = 0; i < files.length; i++) {
|
|
1564
|
+
for (let j = i + 1; j < files.length; j++) {
|
|
1565
|
+
importSimTotal += jaccard2(
|
|
1566
|
+
files[i].dependencyList || [],
|
|
1567
|
+
files[j].dependencyList || []
|
|
1568
|
+
);
|
|
1569
|
+
importPairs++;
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
const importCohesion = importPairs > 0 ? importSimTotal / importPairs : 0;
|
|
1573
|
+
fragmentedModules.push({
|
|
1574
|
+
domain,
|
|
1575
|
+
files: files.map((f) => f.file),
|
|
1576
|
+
totalTokens: totalTokens2,
|
|
1577
|
+
fragmentationScore,
|
|
1578
|
+
avgCohesion: avgCohesion2,
|
|
1579
|
+
importCohesion,
|
|
1580
|
+
pathEntropy,
|
|
1581
|
+
directoryDistance,
|
|
1582
|
+
suggestedStructure: {
|
|
1583
|
+
targetFiles,
|
|
1584
|
+
consolidationPlan: [
|
|
1585
|
+
`Consolidate ${files.length} files across ${new Set(files.map((f) => f.file.split("/").slice(0, -1).join("/"))).size} directories`,
|
|
1586
|
+
`Target ~${targetFiles} core modules to reduce context switching`
|
|
1587
|
+
]
|
|
1588
|
+
}
|
|
1589
|
+
});
|
|
1590
|
+
}
|
|
1591
|
+
const avgCohesion = results.reduce((sum, r) => sum + r.cohesionScore, 0) / totalFiles;
|
|
1592
|
+
const lowCohesionFiles = results.filter((r) => r.cohesionScore < 0.4).map((r) => ({ file: r.file, score: r.cohesionScore })).sort((a, b) => a.score - b.score).slice(0, 10);
|
|
1593
|
+
const criticalIssues = results.filter(
|
|
1594
|
+
(r) => r.severity === "critical"
|
|
1595
|
+
).length;
|
|
1596
|
+
const majorIssues = results.filter((r) => r.severity === "major").length;
|
|
1597
|
+
const minorIssues = results.filter((r) => r.severity === "minor").length;
|
|
1598
|
+
const totalPotentialSavings = results.reduce(
|
|
1599
|
+
(sum, r) => sum + r.potentialSavings,
|
|
1600
|
+
0
|
|
1601
|
+
);
|
|
1602
|
+
const topExpensiveFiles = results.sort((a, b) => b.contextBudget - a.contextBudget).slice(0, 10).map((r) => ({
|
|
1603
|
+
file: r.file,
|
|
1604
|
+
contextBudget: r.contextBudget,
|
|
1605
|
+
severity: r.severity
|
|
1606
|
+
}));
|
|
1607
|
+
return {
|
|
1608
|
+
totalFiles,
|
|
1609
|
+
totalTokens,
|
|
1610
|
+
avgContextBudget,
|
|
1611
|
+
maxContextBudget,
|
|
1612
|
+
avgImportDepth,
|
|
1613
|
+
maxImportDepth,
|
|
1614
|
+
deepFiles,
|
|
1615
|
+
avgFragmentation,
|
|
1616
|
+
fragmentedModules,
|
|
1617
|
+
avgCohesion,
|
|
1618
|
+
lowCohesionFiles,
|
|
1619
|
+
criticalIssues,
|
|
1620
|
+
majorIssues,
|
|
1621
|
+
minorIssues,
|
|
1622
|
+
totalPotentialSavings,
|
|
1623
|
+
topExpensiveFiles,
|
|
1624
|
+
config
|
|
1625
|
+
};
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1493
1628
|
// src/provider.ts
|
|
1494
|
-
var
|
|
1629
|
+
var import_core7 = require("@aiready/core");
|
|
1495
1630
|
|
|
1496
1631
|
// src/scoring.ts
|
|
1497
|
-
var
|
|
1632
|
+
var import_core6 = require("@aiready/core");
|
|
1498
1633
|
function calculateContextScore(summary, costConfig) {
|
|
1499
1634
|
const {
|
|
1500
1635
|
avgContextBudget,
|
|
@@ -1590,8 +1725,8 @@ function calculateContextScore(summary, costConfig) {
|
|
|
1590
1725
|
priority: "high"
|
|
1591
1726
|
});
|
|
1592
1727
|
}
|
|
1593
|
-
const cfg = { ...
|
|
1594
|
-
const estimatedMonthlyCost = (0,
|
|
1728
|
+
const cfg = { ...import_core6.DEFAULT_COST_CONFIG, ...costConfig };
|
|
1729
|
+
const estimatedMonthlyCost = (0, import_core6.calculateMonthlyCost)(
|
|
1595
1730
|
avgContextBudget * (summary.totalFiles || 1),
|
|
1596
1731
|
cfg
|
|
1597
1732
|
);
|
|
@@ -1599,9 +1734,9 @@ function calculateContextScore(summary, costConfig) {
|
|
|
1599
1734
|
...Array(criticalIssues).fill({ severity: "critical" }),
|
|
1600
1735
|
...Array(majorIssues).fill({ severity: "major" })
|
|
1601
1736
|
];
|
|
1602
|
-
const productivityImpact = (0,
|
|
1737
|
+
const productivityImpact = (0, import_core6.calculateProductivityImpact)(issues);
|
|
1603
1738
|
return {
|
|
1604
|
-
toolName:
|
|
1739
|
+
toolName: import_core6.ToolName.ContextAnalyzer,
|
|
1605
1740
|
score,
|
|
1606
1741
|
rawMetrics: {
|
|
1607
1742
|
avgContextBudget: Math.round(avgContextBudget),
|
|
@@ -1628,16 +1763,16 @@ function mapScoreToRating(score) {
|
|
|
1628
1763
|
|
|
1629
1764
|
// src/provider.ts
|
|
1630
1765
|
var ContextAnalyzerProvider = {
|
|
1631
|
-
id:
|
|
1766
|
+
id: import_core7.ToolName.ContextAnalyzer,
|
|
1632
1767
|
alias: ["context", "fragmentation", "budget"],
|
|
1633
1768
|
async analyze(options) {
|
|
1634
1769
|
const results = await analyzeContext(options);
|
|
1635
|
-
const summary = generateSummary(results);
|
|
1770
|
+
const summary = generateSummary(results, options);
|
|
1636
1771
|
const normalizedResults = results.map(
|
|
1637
1772
|
(r) => ({
|
|
1638
1773
|
fileName: r.file,
|
|
1639
1774
|
issues: r.issues.map((msg) => ({
|
|
1640
|
-
type:
|
|
1775
|
+
type: import_core7.IssueType.ContextFragmentation,
|
|
1641
1776
|
severity: r.severity,
|
|
1642
1777
|
message: msg,
|
|
1643
1778
|
location: { file: r.file, line: 1 },
|
|
@@ -1650,13 +1785,13 @@ var ContextAnalyzerProvider = {
|
|
|
1650
1785
|
}
|
|
1651
1786
|
})
|
|
1652
1787
|
);
|
|
1653
|
-
return
|
|
1788
|
+
return import_core7.SpokeOutputSchema.parse({
|
|
1654
1789
|
results: normalizedResults,
|
|
1655
1790
|
summary: {
|
|
1656
1791
|
...summary
|
|
1657
1792
|
},
|
|
1658
1793
|
metadata: {
|
|
1659
|
-
toolName:
|
|
1794
|
+
toolName: import_core7.ToolName.ContextAnalyzer,
|
|
1660
1795
|
version: "0.17.5",
|
|
1661
1796
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1662
1797
|
}
|
|
@@ -1670,9 +1805,9 @@ var ContextAnalyzerProvider = {
|
|
|
1670
1805
|
};
|
|
1671
1806
|
|
|
1672
1807
|
// src/defaults.ts
|
|
1673
|
-
var
|
|
1808
|
+
var import_core8 = require("@aiready/core");
|
|
1674
1809
|
async function getSmartDefaults(directory, userOptions) {
|
|
1675
|
-
const files = await (0,
|
|
1810
|
+
const files = await (0, import_core8.scanFiles)({
|
|
1676
1811
|
rootDir: directory,
|
|
1677
1812
|
include: userOptions.include,
|
|
1678
1813
|
exclude: userOptions.exclude
|
|
@@ -1716,135 +1851,8 @@ async function getSmartDefaults(directory, userOptions) {
|
|
|
1716
1851
|
};
|
|
1717
1852
|
}
|
|
1718
1853
|
|
|
1719
|
-
// src/summary.ts
|
|
1720
|
-
function generateSummary(results) {
|
|
1721
|
-
if (results.length === 0) {
|
|
1722
|
-
return {
|
|
1723
|
-
totalFiles: 0,
|
|
1724
|
-
totalTokens: 0,
|
|
1725
|
-
avgContextBudget: 0,
|
|
1726
|
-
maxContextBudget: 0,
|
|
1727
|
-
avgImportDepth: 0,
|
|
1728
|
-
maxImportDepth: 0,
|
|
1729
|
-
deepFiles: [],
|
|
1730
|
-
avgFragmentation: 0,
|
|
1731
|
-
fragmentedModules: [],
|
|
1732
|
-
avgCohesion: 0,
|
|
1733
|
-
lowCohesionFiles: [],
|
|
1734
|
-
criticalIssues: 0,
|
|
1735
|
-
majorIssues: 0,
|
|
1736
|
-
minorIssues: 0,
|
|
1737
|
-
totalPotentialSavings: 0,
|
|
1738
|
-
topExpensiveFiles: []
|
|
1739
|
-
};
|
|
1740
|
-
}
|
|
1741
|
-
const totalFiles = results.length;
|
|
1742
|
-
const totalTokens = results.reduce((sum, r) => sum + r.tokenCost, 0);
|
|
1743
|
-
const totalContextBudget = results.reduce(
|
|
1744
|
-
(sum, r) => sum + r.contextBudget,
|
|
1745
|
-
0
|
|
1746
|
-
);
|
|
1747
|
-
const avgContextBudget = totalContextBudget / totalFiles;
|
|
1748
|
-
const maxContextBudget = Math.max(...results.map((r) => r.contextBudget));
|
|
1749
|
-
const avgImportDepth = results.reduce((sum, r) => sum + r.importDepth, 0) / totalFiles;
|
|
1750
|
-
const maxImportDepth = Math.max(...results.map((r) => r.importDepth));
|
|
1751
|
-
const deepFiles = results.filter((r) => r.importDepth >= 5).map((r) => ({ file: r.file, depth: r.importDepth })).sort((a, b) => b.depth - a.depth).slice(0, 10);
|
|
1752
|
-
const avgFragmentation = results.reduce((sum, r) => sum + r.fragmentationScore, 0) / totalFiles;
|
|
1753
|
-
const moduleMap = /* @__PURE__ */ new Map();
|
|
1754
|
-
for (const result of results) {
|
|
1755
|
-
for (const domain of result.domains) {
|
|
1756
|
-
if (!moduleMap.has(domain)) moduleMap.set(domain, []);
|
|
1757
|
-
moduleMap.get(domain).push(result);
|
|
1758
|
-
}
|
|
1759
|
-
}
|
|
1760
|
-
const fragmentedModules = [];
|
|
1761
|
-
for (const [domain, files] of moduleMap.entries()) {
|
|
1762
|
-
let jaccard2 = function(a, b) {
|
|
1763
|
-
const s1 = new Set(a || []);
|
|
1764
|
-
const s2 = new Set(b || []);
|
|
1765
|
-
if (s1.size === 0 && s2.size === 0) return 0;
|
|
1766
|
-
const inter = new Set([...s1].filter((x) => s2.has(x)));
|
|
1767
|
-
const uni = /* @__PURE__ */ new Set([...s1, ...s2]);
|
|
1768
|
-
return uni.size === 0 ? 0 : inter.size / uni.size;
|
|
1769
|
-
};
|
|
1770
|
-
var jaccard = jaccard2;
|
|
1771
|
-
if (files.length < 2) continue;
|
|
1772
|
-
const fragmentationScore = files.reduce((sum, f) => sum + f.fragmentationScore, 0) / files.length;
|
|
1773
|
-
if (fragmentationScore < 0.3) continue;
|
|
1774
|
-
const totalTokens2 = files.reduce((sum, f) => sum + f.tokenCost, 0);
|
|
1775
|
-
const avgCohesion2 = files.reduce((sum, f) => sum + f.cohesionScore, 0) / files.length;
|
|
1776
|
-
const targetFiles = Math.max(1, Math.ceil(files.length / 3));
|
|
1777
|
-
const filePaths = files.map((f) => f.file);
|
|
1778
|
-
const pathEntropy = calculatePathEntropy(filePaths);
|
|
1779
|
-
const directoryDistance = calculateDirectoryDistance(filePaths);
|
|
1780
|
-
let importSimTotal = 0;
|
|
1781
|
-
let importPairs = 0;
|
|
1782
|
-
for (let i = 0; i < files.length; i++) {
|
|
1783
|
-
for (let j = i + 1; j < files.length; j++) {
|
|
1784
|
-
importSimTotal += jaccard2(
|
|
1785
|
-
files[i].dependencyList || [],
|
|
1786
|
-
files[j].dependencyList || []
|
|
1787
|
-
);
|
|
1788
|
-
importPairs++;
|
|
1789
|
-
}
|
|
1790
|
-
}
|
|
1791
|
-
const importCohesion = importPairs > 0 ? importSimTotal / importPairs : 0;
|
|
1792
|
-
fragmentedModules.push({
|
|
1793
|
-
domain,
|
|
1794
|
-
files: files.map((f) => f.file),
|
|
1795
|
-
totalTokens: totalTokens2,
|
|
1796
|
-
fragmentationScore,
|
|
1797
|
-
avgCohesion: avgCohesion2,
|
|
1798
|
-
importCohesion,
|
|
1799
|
-
pathEntropy,
|
|
1800
|
-
directoryDistance,
|
|
1801
|
-
suggestedStructure: {
|
|
1802
|
-
targetFiles,
|
|
1803
|
-
consolidationPlan: [
|
|
1804
|
-
`Consolidate ${files.length} files across ${new Set(files.map((f) => f.file.split("/").slice(0, -1).join("/"))).size} directories`,
|
|
1805
|
-
`Target ~${targetFiles} core modules to reduce context switching`
|
|
1806
|
-
]
|
|
1807
|
-
}
|
|
1808
|
-
});
|
|
1809
|
-
}
|
|
1810
|
-
const avgCohesion = results.reduce((sum, r) => sum + r.cohesionScore, 0) / totalFiles;
|
|
1811
|
-
const lowCohesionFiles = results.filter((r) => r.cohesionScore < 0.4).map((r) => ({ file: r.file, score: r.cohesionScore })).sort((a, b) => a.score - b.score).slice(0, 10);
|
|
1812
|
-
const criticalIssues = results.filter(
|
|
1813
|
-
(r) => r.severity === "critical"
|
|
1814
|
-
).length;
|
|
1815
|
-
const majorIssues = results.filter((r) => r.severity === "major").length;
|
|
1816
|
-
const minorIssues = results.filter((r) => r.severity === "minor").length;
|
|
1817
|
-
const totalPotentialSavings = results.reduce(
|
|
1818
|
-
(sum, r) => sum + r.potentialSavings,
|
|
1819
|
-
0
|
|
1820
|
-
);
|
|
1821
|
-
const topExpensiveFiles = results.sort((a, b) => b.contextBudget - a.contextBudget).slice(0, 10).map((r) => ({
|
|
1822
|
-
file: r.file,
|
|
1823
|
-
contextBudget: r.contextBudget,
|
|
1824
|
-
severity: r.severity
|
|
1825
|
-
}));
|
|
1826
|
-
return {
|
|
1827
|
-
totalFiles,
|
|
1828
|
-
totalTokens,
|
|
1829
|
-
avgContextBudget,
|
|
1830
|
-
maxContextBudget,
|
|
1831
|
-
avgImportDepth,
|
|
1832
|
-
maxImportDepth,
|
|
1833
|
-
deepFiles,
|
|
1834
|
-
avgFragmentation,
|
|
1835
|
-
fragmentedModules,
|
|
1836
|
-
avgCohesion,
|
|
1837
|
-
lowCohesionFiles,
|
|
1838
|
-
criticalIssues,
|
|
1839
|
-
majorIssues,
|
|
1840
|
-
minorIssues,
|
|
1841
|
-
totalPotentialSavings,
|
|
1842
|
-
topExpensiveFiles
|
|
1843
|
-
};
|
|
1844
|
-
}
|
|
1845
|
-
|
|
1846
1854
|
// src/index.ts
|
|
1847
|
-
|
|
1855
|
+
import_core10.ToolRegistry.register(ContextAnalyzerProvider);
|
|
1848
1856
|
async function analyzeContext(options) {
|
|
1849
1857
|
const {
|
|
1850
1858
|
maxDepth = 5,
|
|
@@ -1855,7 +1863,7 @@ async function analyzeContext(options) {
|
|
|
1855
1863
|
includeNodeModules = false,
|
|
1856
1864
|
...scanOptions
|
|
1857
1865
|
} = options;
|
|
1858
|
-
const files = await (0,
|
|
1866
|
+
const files = await (0, import_core10.scanFiles)({
|
|
1859
1867
|
...scanOptions,
|
|
1860
1868
|
exclude: includeNodeModules && scanOptions.exclude ? scanOptions.exclude.filter(
|
|
1861
1869
|
(pattern) => pattern !== "**/node_modules/**"
|
|
@@ -1865,7 +1873,7 @@ async function analyzeContext(options) {
|
|
|
1865
1873
|
const fileContents = await Promise.all(
|
|
1866
1874
|
files.map(async (file) => ({
|
|
1867
1875
|
file,
|
|
1868
|
-
content: await (0,
|
|
1876
|
+
content: await (0, import_core10.readFileContent)(file)
|
|
1869
1877
|
}))
|
|
1870
1878
|
);
|
|
1871
1879
|
const graph = buildDependencyGraph(
|
|
@@ -2020,6 +2028,7 @@ async function analyzeContext(options) {
|
|
|
2020
2028
|
});
|
|
2021
2029
|
}
|
|
2022
2030
|
const allResults = [...results, ...pythonResults];
|
|
2031
|
+
const finalSummary = generateSummary(allResults, options);
|
|
2023
2032
|
return allResults.sort((a, b) => {
|
|
2024
2033
|
const severityOrder = { critical: 0, major: 1, minor: 2, info: 3 };
|
|
2025
2034
|
const severityDiff = severityOrder[a.severity] - severityOrder[b.severity];
|
package/dist/index.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiready/context-analyzer",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.11",
|
|
4
4
|
"description": "AI context window cost analysis - detect fragmented code, deep import chains, and expensive context budgets",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"commander": "^14.0.0",
|
|
50
50
|
"chalk": "^5.3.0",
|
|
51
51
|
"prompts": "^2.4.2",
|
|
52
|
-
"@aiready/core": "0.21.
|
|
52
|
+
"@aiready/core": "0.21.11"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@types/node": "^24.0.0",
|
package/src/index.ts
CHANGED
|
@@ -244,6 +244,7 @@ export async function analyzeContext(
|
|
|
244
244
|
}
|
|
245
245
|
|
|
246
246
|
const allResults = [...results, ...pythonResults];
|
|
247
|
+
const finalSummary = generateSummary(allResults, options);
|
|
247
248
|
return allResults.sort((a, b) => {
|
|
248
249
|
const severityOrder = { critical: 0, major: 1, minor: 2, info: 3 };
|
|
249
250
|
const severityDiff = severityOrder[a.severity] - severityOrder[b.severity];
|
package/src/provider.ts
CHANGED
|
@@ -22,7 +22,7 @@ export const ContextAnalyzerProvider: ToolProvider = {
|
|
|
22
22
|
|
|
23
23
|
async analyze(options: ScanOptions): Promise<SpokeOutput> {
|
|
24
24
|
const results = await analyzeContext(options as ContextAnalyzerOptions);
|
|
25
|
-
const summary = generateSummary(results);
|
|
25
|
+
const summary = generateSummary(results, options);
|
|
26
26
|
|
|
27
27
|
// Normalize to SpokeOutput format
|
|
28
28
|
const normalizedResults: AnalysisResult[] = results.map(
|
package/src/summary.ts
CHANGED
|
@@ -4,13 +4,23 @@ import type {
|
|
|
4
4
|
ModuleCluster,
|
|
5
5
|
} from './types';
|
|
6
6
|
import { calculatePathEntropy, calculateDirectoryDistance } from './analyzer';
|
|
7
|
+
import { GLOBAL_SCAN_OPTIONS } from '@aiready/core';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Generate summary of context analysis results
|
|
10
11
|
*/
|
|
11
12
|
export function generateSummary(
|
|
12
|
-
results: ContextAnalysisResult[]
|
|
13
|
+
results: ContextAnalysisResult[],
|
|
14
|
+
options?: any
|
|
13
15
|
): ContextSummary {
|
|
16
|
+
const config = options
|
|
17
|
+
? Object.fromEntries(
|
|
18
|
+
Object.entries(options).filter(
|
|
19
|
+
([key]) => !GLOBAL_SCAN_OPTIONS.includes(key) || key === 'rootDir'
|
|
20
|
+
)
|
|
21
|
+
)
|
|
22
|
+
: undefined;
|
|
23
|
+
|
|
14
24
|
if (results.length === 0) {
|
|
15
25
|
return {
|
|
16
26
|
totalFiles: 0,
|
|
@@ -29,6 +39,7 @@ export function generateSummary(
|
|
|
29
39
|
minorIssues: 0,
|
|
30
40
|
totalPotentialSavings: 0,
|
|
31
41
|
topExpensiveFiles: [],
|
|
42
|
+
config,
|
|
32
43
|
};
|
|
33
44
|
}
|
|
34
45
|
|
|
@@ -164,5 +175,6 @@ export function generateSummary(
|
|
|
164
175
|
minorIssues,
|
|
165
176
|
totalPotentialSavings,
|
|
166
177
|
topExpensiveFiles,
|
|
178
|
+
config,
|
|
167
179
|
};
|
|
168
180
|
}
|