@aiready/core 0.9.22 → 0.9.25

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/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,11 +17,20 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
21
31
  var index_exports = {};
22
32
  __export(index_exports, {
33
+ DEFAULT_COST_CONFIG: () => DEFAULT_COST_CONFIG,
23
34
  DEFAULT_EXCLUDE: () => DEFAULT_EXCLUDE,
24
35
  DEFAULT_TOOL_WEIGHTS: () => DEFAULT_TOOL_WEIGHTS,
25
36
  LANGUAGE_EXTENSIONS: () => LANGUAGE_EXTENSIONS,
@@ -29,13 +40,20 @@ __export(index_exports, {
29
40
  PythonParser: () => PythonParser,
30
41
  TOOL_NAME_MAP: () => TOOL_NAME_MAP,
31
42
  TypeScriptParser: () => TypeScriptParser,
43
+ calculateComprehensionDifficulty: () => calculateComprehensionDifficulty,
32
44
  calculateImportSimilarity: () => calculateImportSimilarity,
45
+ calculateMonthlyCost: () => calculateMonthlyCost,
33
46
  calculateOverallScore: () => calculateOverallScore,
47
+ calculateProductivityImpact: () => calculateProductivityImpact,
34
48
  estimateTokens: () => estimateTokens,
35
49
  extractFunctions: () => extractFunctions,
36
50
  extractImports: () => extractImports,
51
+ formatAcceptanceRate: () => formatAcceptanceRate,
52
+ formatCost: () => formatCost,
53
+ formatHours: () => formatHours,
37
54
  formatScore: () => formatScore,
38
55
  formatToolScore: () => formatToolScore,
56
+ generateHTML: () => generateHTML,
39
57
  getElapsedTime: () => getElapsedTime,
40
58
  getFileExtension: () => getFileExtension,
41
59
  getParser: () => getParser,
@@ -54,6 +72,7 @@ __export(index_exports, {
54
72
  parseCode: () => parseCode,
55
73
  parseFileExports: () => parseFileExports,
56
74
  parseWeightString: () => parseWeightString,
75
+ predictAcceptanceRate: () => predictAcceptanceRate,
57
76
  readFileContent: () => readFileContent,
58
77
  resolveOutputPath: () => resolveOutputPath,
59
78
  scanFiles: () => scanFiles
@@ -96,6 +115,7 @@ var import_glob = require("glob");
96
115
  var import_promises = require("fs/promises");
97
116
  var import_fs = require("fs");
98
117
  var import_path = require("path");
118
+ var import_ignore = __toESM(require("ignore"));
99
119
  var DEFAULT_EXCLUDE = [
100
120
  // Dependencies
101
121
  "**/node_modules/**",
@@ -164,6 +184,22 @@ async function scanFiles(options) {
164
184
  ignore: finalExclude,
165
185
  absolute: true
166
186
  });
187
+ const gitignorePath = (0, import_path.join)(rootDir || ".", ".gitignore");
188
+ if ((0, import_fs.existsSync)(gitignorePath)) {
189
+ try {
190
+ const gitTxt = await (0, import_promises.readFile)(gitignorePath, "utf-8");
191
+ const ig = (0, import_ignore.default)();
192
+ ig.add(gitTxt);
193
+ const filtered = files.filter((f) => {
194
+ let rel = (0, import_path.relative)(rootDir || ".", f).replace(/\\/g, "/");
195
+ if (rel === "") rel = f;
196
+ return !ig.ignores(rel);
197
+ });
198
+ return filtered;
199
+ } catch (e) {
200
+ return files;
201
+ }
202
+ }
167
203
  return files;
168
204
  }
169
205
  async function readFileContent(filePath) {
@@ -472,6 +508,172 @@ function getElapsedTime(startTime) {
472
508
  return ((Date.now() - startTime) / 1e3).toFixed(2);
473
509
  }
474
510
 
511
+ // src/utils/visualization.ts
512
+ function generateHTML(graph) {
513
+ const payload = JSON.stringify(graph, null, 2);
514
+ return `<!doctype html>
515
+ <html>
516
+ <head>
517
+ <meta charset="utf-8" />
518
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
519
+ <title>AIReady Visualization</title>
520
+ <style>
521
+ html,body { height: 100%; margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #0f172a; color: #e2e8f0 }
522
+ #container { display:flex; height:100vh }
523
+ #panel { width: 320px; padding: 16px; background: #071130; box-shadow: -2px 0 8px rgba(0,0,0,0.3); overflow:auto }
524
+ #canvasWrap { flex:1; display:flex; align-items:center; justify-content:center }
525
+ canvas { background: #0b1220; border-radius:8px }
526
+ .stat { margin-bottom:12px }
527
+ </style>
528
+ </head>
529
+ <body>
530
+ <div id="container">
531
+ <div id="canvasWrap"><canvas id="canvas" width="1200" height="800"></canvas></div>
532
+ <div id="panel">
533
+ <h2>AIReady Visualization</h2>
534
+ <div class="stat"><strong>Files:</strong> <span id="stat-files"></span></div>
535
+ <div class="stat"><strong>Dependencies:</strong> <span id="stat-deps"></span></div>
536
+ <div class="stat"><strong>Legend</strong></div>
537
+ <div style="font-size:13px;line-height:1.3;color:#cbd5e1;margin-top:8px">
538
+ <div style="margin-bottom:8px"><span style="display:inline-block;width:12px;height:12px;background:#ff4d4f;margin-right:8px;border:1px solid rgba(255,255,255,0.06)"></span><strong>Critical</strong>: highest severity issues.</div>
539
+ <div style="margin-bottom:8px"><span style="display:inline-block;width:12px;height:12px;background:#ff9900;margin-right:8px;border:1px solid rgba(255,255,255,0.06)"></span><strong>Major</strong>: important issues.</div>
540
+ <div style="margin-bottom:8px"><span style="display:inline-block;width:12px;height:12px;background:#ffd666;margin-right:8px;border:1px solid rgba(255,255,255,0.06)"></span><strong>Minor</strong>: low priority issues.</div>
541
+ <div style="margin-bottom:8px"><span style="display:inline-block;width:12px;height:12px;background:#91d5ff;margin-right:8px;border:1px solid rgba(255,255,255,0.06)"></span><strong>Info</strong>: informational notes.</div>
542
+ <div style="margin-top:10px;color:#94a3b8"><strong>Node size</strong>: larger = higher token cost, more issues or dependency weight.</div>
543
+ <div style="margin-top:6px;color:#94a3b8"><strong>Proximity</strong>: nodes that are spatially close are more contextually related; relatedness is represented by distance and size rather than explicit edges.</div>
544
+ <div style="margin-top:6px;color:#94a3b8"><strong>Edge colors</strong>: <span style="color:#fb7e81">Similarity</span>, <span style="color:#84c1ff">Dependency</span>, <span style="color:#ffa500">Reference</span>, default <span style="color:#334155">Other</span>.</div>
545
+ </div>
546
+ </div>
547
+ </div>
548
+
549
+ <script>
550
+ const graphData = ${payload};
551
+ document.getElementById('stat-files').textContent = graphData.metadata.totalFiles;
552
+ document.getElementById('stat-deps').textContent = graphData.metadata.totalDependencies;
553
+
554
+ const canvas = document.getElementById('canvas');
555
+ const ctx = canvas.getContext('2d');
556
+
557
+ const nodes = graphData.nodes.map((n, i) => ({
558
+ ...n,
559
+ x: canvas.width / 2 + Math.cos(i / graphData.nodes.length * Math.PI * 2) * (Math.min(canvas.width, canvas.height) / 3),
560
+ y: canvas.height / 2 + Math.sin(i / graphData.nodes.length * Math.PI * 2) * (Math.min(canvas.width, canvas.height) / 3),
561
+ }));
562
+
563
+ function draw() {
564
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
565
+
566
+ graphData.edges.forEach(edge => {
567
+ const s = nodes.find(n => n.id === edge.source);
568
+ const t = nodes.find(n => n.id === edge.target);
569
+ if (!s || !t) return;
570
+ if (edge.type === 'related') return;
571
+ if (edge.type === 'similarity') {
572
+ ctx.strokeStyle = '#fb7e81';
573
+ ctx.lineWidth = 1.2;
574
+ } else if (edge.type === 'dependency') {
575
+ ctx.strokeStyle = '#84c1ff';
576
+ ctx.lineWidth = 1.0;
577
+ } else if (edge.type === 'reference') {
578
+ ctx.strokeStyle = '#ffa500';
579
+ ctx.lineWidth = 0.9;
580
+ } else {
581
+ ctx.strokeStyle = '#334155';
582
+ ctx.lineWidth = 0.8;
583
+ }
584
+ ctx.beginPath();
585
+ ctx.moveTo(s.x, s.y);
586
+ ctx.lineTo(t.x, t.y);
587
+ ctx.stroke();
588
+ });
589
+
590
+ const groups = {};
591
+ nodes.forEach(n => {
592
+ const g = n.group || '__default';
593
+ if (!groups[g]) groups[g] = { minX: n.x, minY: n.y, maxX: n.x, maxY: n.y };
594
+ groups[g].minX = Math.min(groups[g].minX, n.x);
595
+ groups[g].minY = Math.min(groups[g].minY, n.y);
596
+ groups[g].maxX = Math.max(groups[g].maxX, n.x);
597
+ groups[g].maxY = Math.max(groups[g].maxY, n.y);
598
+ });
599
+
600
+ const groupRelations = {};
601
+ graphData.edges.forEach(edge => {
602
+ const sNode = nodes.find(n => n.id === edge.source);
603
+ const tNode = nodes.find(n => n.id === edge.target);
604
+ if (!sNode || !tNode) return;
605
+ const g1 = sNode.group || '__default';
606
+ const g2 = tNode.group || '__default';
607
+ if (g1 === g2) return;
608
+ const key = g1 < g2 ? g1 + '::' + g2 : g2 + '::' + g1;
609
+ groupRelations[key] = (groupRelations[key] || 0) + 1;
610
+ });
611
+
612
+ Object.keys(groupRelations).forEach(k => {
613
+ const count = groupRelations[k];
614
+ const [ga, gb] = k.split('::');
615
+ if (!groups[ga] || !groups[gb]) return;
616
+ const ax = (groups[ga].minX + groups[ga].maxX) / 2;
617
+ const ay = (groups[ga].minY + groups[ga].maxY) / 2;
618
+ const bx = (groups[gb].minX + groups[gb].maxX) / 2;
619
+ const by = (groups[gb].minY + groups[gb].maxY) / 2;
620
+ ctx.beginPath();
621
+ ctx.strokeStyle = 'rgba(148,163,184,0.25)';
622
+ ctx.lineWidth = Math.min(6, 0.6 + Math.sqrt(count));
623
+ ctx.moveTo(ax, ay);
624
+ ctx.lineTo(bx, by);
625
+ ctx.stroke();
626
+ });
627
+
628
+ Object.keys(groups).forEach(g => {
629
+ if (g === '__default') return;
630
+ const box = groups[g];
631
+ const pad = 16;
632
+ const x = box.minX - pad;
633
+ const y = box.minY - pad;
634
+ const w = (box.maxX - box.minX) + pad * 2;
635
+ const h = (box.maxY - box.minY) + pad * 2;
636
+ ctx.save();
637
+ ctx.fillStyle = 'rgba(30,64,175,0.04)';
638
+ ctx.strokeStyle = 'rgba(30,64,175,0.12)';
639
+ ctx.lineWidth = 1.2;
640
+ const r = 8;
641
+ ctx.beginPath();
642
+ ctx.moveTo(x + r, y);
643
+ ctx.arcTo(x + w, y, x + w, y + h, r);
644
+ ctx.arcTo(x + w, y + h, x, y + h, r);
645
+ ctx.arcTo(x, y + h, x, y, r);
646
+ ctx.arcTo(x, y, x + w, y, r);
647
+ ctx.closePath();
648
+ ctx.fill();
649
+ ctx.stroke();
650
+ ctx.restore();
651
+ ctx.fillStyle = '#94a3b8';
652
+ ctx.font = '11px sans-serif';
653
+ ctx.fillText(g, x + 8, y + 14);
654
+ });
655
+
656
+ nodes.forEach(n => {
657
+ const sizeVal = (n.size || n.value || 1);
658
+ const r = 6 + (sizeVal / 2);
659
+ ctx.beginPath();
660
+ ctx.fillStyle = n.color || '#60a5fa';
661
+ ctx.arc(n.x, n.y, r, 0, Math.PI * 2);
662
+ ctx.fill();
663
+
664
+ ctx.fillStyle = '#e2e8f0';
665
+ ctx.font = '11px sans-serif';
666
+ ctx.textAlign = 'center';
667
+ ctx.fillText(n.label || n.id.split('/').slice(-1)[0], n.x, n.y + r + 12);
668
+ });
669
+ }
670
+
671
+ draw();
672
+ </script>
673
+ </body>
674
+ </html>`;
675
+ }
676
+
475
677
  // src/scoring.ts
476
678
  var DEFAULT_TOOL_WEIGHTS = {
477
679
  "pattern-detect": 40,
@@ -616,6 +818,167 @@ function formatToolScore(output) {
616
818
  return result;
617
819
  }
618
820
 
821
+ // src/business-metrics.ts
822
+ var DEFAULT_COST_CONFIG = {
823
+ pricePer1KTokens: 0.01,
824
+ // $0.01 per 1K tokens (GPT-4)
825
+ queriesPerDevPerDay: 50,
826
+ // Average AI queries per developer
827
+ developerCount: 5,
828
+ // Default team size
829
+ daysPerMonth: 30
830
+ };
831
+ var SEVERITY_TIME_ESTIMATES = {
832
+ critical: 4,
833
+ // Complex architectural issues
834
+ major: 2,
835
+ // Significant refactoring needed
836
+ minor: 0.5,
837
+ // Simple naming/style fixes
838
+ info: 0.25
839
+ // Documentation improvements
840
+ };
841
+ var DEFAULT_HOURLY_RATE = 75;
842
+ function calculateMonthlyCost(tokenWaste, config = {}) {
843
+ const cfg = { ...DEFAULT_COST_CONFIG, ...config };
844
+ const tokensPerDay = tokenWaste * cfg.queriesPerDevPerDay;
845
+ const tokensPerMonth = tokensPerDay * cfg.daysPerMonth;
846
+ const cost = tokensPerMonth / 1e3 * cfg.pricePer1KTokens;
847
+ return Math.round(cost * 100) / 100;
848
+ }
849
+ function calculateProductivityImpact(issues, hourlyRate = DEFAULT_HOURLY_RATE) {
850
+ const counts = {
851
+ critical: issues.filter((i) => i.severity === "critical").length,
852
+ major: issues.filter((i) => i.severity === "major").length,
853
+ minor: issues.filter((i) => i.severity === "minor").length,
854
+ info: issues.filter((i) => i.severity === "info").length
855
+ };
856
+ const hours = {
857
+ critical: counts.critical * SEVERITY_TIME_ESTIMATES.critical,
858
+ major: counts.major * SEVERITY_TIME_ESTIMATES.major,
859
+ minor: counts.minor * SEVERITY_TIME_ESTIMATES.minor,
860
+ info: counts.info * SEVERITY_TIME_ESTIMATES.info
861
+ };
862
+ const totalHours = hours.critical + hours.major + hours.minor + hours.info;
863
+ const totalCost = totalHours * hourlyRate;
864
+ return {
865
+ totalHours: Math.round(totalHours * 10) / 10,
866
+ hourlyRate,
867
+ totalCost: Math.round(totalCost),
868
+ bySeverity: {
869
+ critical: { hours: Math.round(hours.critical * 10) / 10, cost: Math.round(hours.critical * hourlyRate) },
870
+ major: { hours: Math.round(hours.major * 10) / 10, cost: Math.round(hours.major * hourlyRate) },
871
+ minor: { hours: Math.round(hours.minor * 10) / 10, cost: Math.round(hours.minor * hourlyRate) }
872
+ }
873
+ };
874
+ }
875
+ function predictAcceptanceRate(toolOutputs) {
876
+ const factors = [];
877
+ const patterns = toolOutputs.get("pattern-detect");
878
+ if (patterns) {
879
+ const patternImpact = (patterns.score - 50) * 0.3;
880
+ factors.push({
881
+ name: "Semantic Duplication",
882
+ impact: Math.round(patternImpact)
883
+ });
884
+ }
885
+ const context = toolOutputs.get("context-analyzer");
886
+ if (context) {
887
+ const contextImpact = (context.score - 50) * 0.4;
888
+ factors.push({
889
+ name: "Context Efficiency",
890
+ impact: Math.round(contextImpact)
891
+ });
892
+ }
893
+ const consistency = toolOutputs.get("consistency");
894
+ if (consistency) {
895
+ const consistencyImpact = (consistency.score - 50) * 0.3;
896
+ factors.push({
897
+ name: "Code Consistency",
898
+ impact: Math.round(consistencyImpact)
899
+ });
900
+ }
901
+ const baseRate = 0.65;
902
+ const totalImpact = factors.reduce((sum, f) => sum + f.impact / 100, 0);
903
+ const rate = Math.max(0.1, Math.min(0.95, baseRate + totalImpact));
904
+ const confidence = toolOutputs.size >= 3 ? 0.8 : toolOutputs.size >= 2 ? 0.6 : 0.4;
905
+ return {
906
+ rate: Math.round(rate * 100) / 100,
907
+ confidence,
908
+ factors
909
+ };
910
+ }
911
+ function calculateComprehensionDifficulty(contextBudget, importDepth, fragmentation, consistencyScore, totalFiles) {
912
+ const budgetFactor = Math.min(100, Math.max(0, (contextBudget - 5e3) / 250));
913
+ const depthFactor = Math.min(100, Math.max(0, (importDepth - 5) * 10));
914
+ const fragmentationFactor = Math.min(100, Math.max(0, (fragmentation - 0.3) * 250));
915
+ const consistencyFactor = Math.min(100, Math.max(0, 100 - consistencyScore));
916
+ const fileFactor = Math.min(100, Math.max(0, (totalFiles - 50) / 5));
917
+ const score = Math.round(
918
+ budgetFactor * 0.35 + depthFactor * 0.2 + fragmentationFactor * 0.2 + consistencyFactor * 0.15 + fileFactor * 0.1
919
+ );
920
+ let rating;
921
+ if (score < 20) rating = "trivial";
922
+ else if (score < 40) rating = "easy";
923
+ else if (score < 60) rating = "moderate";
924
+ else if (score < 80) rating = "difficult";
925
+ else rating = "expert";
926
+ return {
927
+ score,
928
+ rating,
929
+ factors: [
930
+ {
931
+ name: "Context Budget",
932
+ contribution: Math.round(budgetFactor * 0.35),
933
+ description: `${Math.round(contextBudget)} tokens required`
934
+ },
935
+ {
936
+ name: "Import Depth",
937
+ contribution: Math.round(depthFactor * 0.2),
938
+ description: `${importDepth.toFixed(1)} average levels`
939
+ },
940
+ {
941
+ name: "Code Fragmentation",
942
+ contribution: Math.round(fragmentationFactor * 0.2),
943
+ description: `${(fragmentation * 100).toFixed(0)}% fragmentation`
944
+ },
945
+ {
946
+ name: "Consistency",
947
+ contribution: Math.round(consistencyFactor * 0.15),
948
+ description: `${consistencyScore}/100 consistency score`
949
+ },
950
+ {
951
+ name: "Project Scale",
952
+ contribution: Math.round(fileFactor * 0.1),
953
+ description: `${totalFiles} files analyzed`
954
+ }
955
+ ]
956
+ };
957
+ }
958
+ function formatCost(cost) {
959
+ if (cost < 1) {
960
+ return `$${cost.toFixed(2)}`;
961
+ } else if (cost < 1e3) {
962
+ return `$${cost.toFixed(0)}`;
963
+ } else {
964
+ return `$${(cost / 1e3).toFixed(1)}k`;
965
+ }
966
+ }
967
+ function formatHours(hours) {
968
+ if (hours < 1) {
969
+ return `${Math.round(hours * 60)}min`;
970
+ } else if (hours < 8) {
971
+ return `${hours.toFixed(1)}h`;
972
+ } else if (hours < 40) {
973
+ return `${Math.round(hours)}h`;
974
+ } else {
975
+ return `${(hours / 40).toFixed(1)} weeks`;
976
+ }
977
+ }
978
+ function formatAcceptanceRate(rate) {
979
+ return `${Math.round(rate * 100)}%`;
980
+ }
981
+
619
982
  // src/parsers/typescript-parser.ts
620
983
  var import_typescript_estree2 = require("@typescript-eslint/typescript-estree");
621
984
  var TypeScriptParser = class {
@@ -1097,6 +1460,7 @@ function getSupportedLanguages() {
1097
1460
  }
1098
1461
  // Annotate the CommonJS export names for ESM import in node:
1099
1462
  0 && (module.exports = {
1463
+ DEFAULT_COST_CONFIG,
1100
1464
  DEFAULT_EXCLUDE,
1101
1465
  DEFAULT_TOOL_WEIGHTS,
1102
1466
  LANGUAGE_EXTENSIONS,
@@ -1106,13 +1470,20 @@ function getSupportedLanguages() {
1106
1470
  PythonParser,
1107
1471
  TOOL_NAME_MAP,
1108
1472
  TypeScriptParser,
1473
+ calculateComprehensionDifficulty,
1109
1474
  calculateImportSimilarity,
1475
+ calculateMonthlyCost,
1110
1476
  calculateOverallScore,
1477
+ calculateProductivityImpact,
1111
1478
  estimateTokens,
1112
1479
  extractFunctions,
1113
1480
  extractImports,
1481
+ formatAcceptanceRate,
1482
+ formatCost,
1483
+ formatHours,
1114
1484
  formatScore,
1115
1485
  formatToolScore,
1486
+ generateHTML,
1116
1487
  getElapsedTime,
1117
1488
  getFileExtension,
1118
1489
  getParser,
@@ -1131,6 +1502,7 @@ function getSupportedLanguages() {
1131
1502
  parseCode,
1132
1503
  parseFileExports,
1133
1504
  parseWeightString,
1505
+ predictAcceptanceRate,
1134
1506
  readFileContent,
1135
1507
  resolveOutputPath,
1136
1508
  scanFiles