@aiready/core 0.9.35 → 0.9.38

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.mjs CHANGED
@@ -18,7 +18,7 @@ import {
18
18
  getToolWeight,
19
19
  normalizeToolName,
20
20
  parseWeightString
21
- } from "./chunk-HFLFBA6F.mjs";
21
+ } from "./chunk-UQGI67WR.mjs";
22
22
 
23
23
  // src/utils/file-scanner.ts
24
24
  import { glob } from "glob";
@@ -516,80 +516,65 @@ function getElapsedTime(startTime) {
516
516
 
517
517
  // src/business-metrics.ts
518
518
  var MODEL_PRICING_PRESETS = {
519
- "gpt-4": {
520
- name: "GPT-4",
521
- pricePer1KInputTokens: 0.03,
522
- pricePer1KOutputTokens: 0.06,
523
- contextTier: "standard",
524
- typicalQueriesPerDevPerDay: 40
519
+ "gpt-5.3": {
520
+ name: "GPT-5.3",
521
+ pricePer1KInputTokens: 2e-3,
522
+ pricePer1KOutputTokens: 8e-3,
523
+ contextTier: "frontier",
524
+ typicalQueriesPerDevPerDay: 100
525
+ },
526
+ "claude-4.6": {
527
+ name: "Claude 4.6",
528
+ pricePer1KInputTokens: 15e-4,
529
+ pricePer1KOutputTokens: 75e-4,
530
+ contextTier: "frontier",
531
+ typicalQueriesPerDevPerDay: 100
532
+ },
533
+ "gemini-3.1": {
534
+ name: "Gemini 3.1 Pro",
535
+ pricePer1KInputTokens: 8e-4,
536
+ pricePer1KOutputTokens: 3e-3,
537
+ contextTier: "frontier",
538
+ typicalQueriesPerDevPerDay: 120
525
539
  },
526
540
  "gpt-4o": {
527
- name: "GPT-4o",
541
+ name: "GPT-4o (legacy)",
528
542
  pricePer1KInputTokens: 5e-3,
529
543
  pricePer1KOutputTokens: 0.015,
530
544
  contextTier: "extended",
531
545
  typicalQueriesPerDevPerDay: 60
532
546
  },
533
- "gpt-4o-mini": {
534
- name: "GPT-4o mini",
535
- pricePer1KInputTokens: 15e-5,
536
- pricePer1KOutputTokens: 6e-4,
537
- contextTier: "extended",
538
- typicalQueriesPerDevPerDay: 120
539
- },
540
547
  "claude-3-5-sonnet": {
541
- name: "Claude 3.5 Sonnet",
548
+ name: "Claude 3.5 Sonnet (legacy)",
542
549
  pricePer1KInputTokens: 3e-3,
543
550
  pricePer1KOutputTokens: 0.015,
544
551
  contextTier: "extended",
545
552
  typicalQueriesPerDevPerDay: 80
546
553
  },
547
- "claude-3-7-sonnet": {
548
- name: "Claude 3.7 Sonnet",
549
- pricePer1KInputTokens: 3e-3,
550
- pricePer1KOutputTokens: 0.015,
551
- contextTier: "frontier",
552
- typicalQueriesPerDevPerDay: 80
553
- },
554
- "claude-sonnet-4": {
555
- name: "Claude Sonnet 4",
556
- pricePer1KInputTokens: 3e-3,
557
- pricePer1KOutputTokens: 0.015,
558
- contextTier: "frontier",
559
- typicalQueriesPerDevPerDay: 80
560
- },
561
554
  "gemini-1-5-pro": {
562
- name: "Gemini 1.5 Pro",
555
+ name: "Gemini 1.5 Pro (legacy)",
563
556
  pricePer1KInputTokens: 125e-5,
564
557
  pricePer1KOutputTokens: 5e-3,
565
558
  contextTier: "frontier",
566
559
  typicalQueriesPerDevPerDay: 80
567
560
  },
568
- "gemini-2-0-flash": {
569
- name: "Gemini 2.0 Flash",
570
- pricePer1KInputTokens: 1e-4,
571
- pricePer1KOutputTokens: 4e-4,
572
- contextTier: "frontier",
573
- typicalQueriesPerDevPerDay: 150
574
- },
575
561
  copilot: {
576
562
  name: "GitHub Copilot (subscription)",
577
- // Amortized per-request cost for a $19/month plan at 80 queries/day
578
- pricePer1KInputTokens: 1e-4,
579
- pricePer1KOutputTokens: 1e-4,
580
- contextTier: "extended",
581
- typicalQueriesPerDevPerDay: 80
563
+ pricePer1KInputTokens: 8e-5,
564
+ pricePer1KOutputTokens: 8e-5,
565
+ contextTier: "frontier",
566
+ typicalQueriesPerDevPerDay: 150
582
567
  },
583
568
  "cursor-pro": {
584
569
  name: "Cursor Pro (subscription)",
585
- pricePer1KInputTokens: 1e-4,
586
- pricePer1KOutputTokens: 1e-4,
570
+ pricePer1KInputTokens: 8e-5,
571
+ pricePer1KOutputTokens: 8e-5,
587
572
  contextTier: "frontier",
588
- typicalQueriesPerDevPerDay: 100
573
+ typicalQueriesPerDevPerDay: 200
589
574
  }
590
575
  };
591
576
  function getModelPreset(modelId) {
592
- return MODEL_PRICING_PRESETS[modelId] ?? MODEL_PRICING_PRESETS["gpt-4o"];
577
+ return MODEL_PRICING_PRESETS[modelId] ?? MODEL_PRICING_PRESETS["claude-4.6"];
593
578
  }
594
579
  var DEFAULT_COST_CONFIG = {
595
580
  pricePer1KTokens: 5e-3,
@@ -602,21 +587,75 @@ var DEFAULT_COST_CONFIG = {
602
587
  };
603
588
  var SEVERITY_TIME_ESTIMATES = {
604
589
  critical: 4,
605
- // Complex architectural issues
590
+ // Complex architectural issues (industry avg: 6.8h)
606
591
  major: 2,
607
- // Significant refactoring needed
592
+ // Significant refactoring needed (avg: 3.4h)
608
593
  minor: 0.5,
609
- // Simple naming/style fixes
594
+ // Simple naming/style fixes (avg: 0.8h)
610
595
  info: 0.25
611
596
  // Documentation improvements
612
597
  };
613
598
  var DEFAULT_HOURLY_RATE = 75;
614
599
  function calculateMonthlyCost(tokenWaste, config = {}) {
600
+ const budget = calculateTokenBudget({
601
+ totalContextTokens: tokenWaste * 2.5,
602
+ // Heuristic: context is larger than waste
603
+ wastedTokens: {
604
+ duplication: tokenWaste * 0.7,
605
+ fragmentation: tokenWaste * 0.3,
606
+ chattiness: 0
607
+ }
608
+ });
609
+ const preset = getModelPreset("claude-4.6");
610
+ return estimateCostFromBudget(budget, preset, config);
611
+ }
612
+ function calculateTokenBudget(params) {
613
+ const { totalContextTokens, wastedTokens } = params;
614
+ const estimatedResponseTokens = params.estimatedResponseTokens ?? totalContextTokens * 0.2;
615
+ const totalWaste = wastedTokens.duplication + wastedTokens.fragmentation + wastedTokens.chattiness;
616
+ const efficiencyRatio = Math.max(
617
+ 0,
618
+ Math.min(
619
+ 1,
620
+ (totalContextTokens - totalWaste) / Math.max(1, totalContextTokens)
621
+ )
622
+ );
623
+ return {
624
+ totalContextTokens: Math.round(totalContextTokens),
625
+ estimatedResponseTokens: Math.round(estimatedResponseTokens),
626
+ wastedTokens: {
627
+ total: Math.round(totalWaste),
628
+ bySource: {
629
+ duplication: Math.round(wastedTokens.duplication),
630
+ fragmentation: Math.round(wastedTokens.fragmentation),
631
+ chattiness: Math.round(wastedTokens.chattiness)
632
+ }
633
+ },
634
+ efficiencyRatio: Math.round(efficiencyRatio * 100) / 100,
635
+ potentialRetrievableTokens: Math.round(totalWaste * 0.8)
636
+ // Heuristic: 80% is fixable
637
+ };
638
+ }
639
+ function estimateCostFromBudget(budget, model, config = {}) {
615
640
  const cfg = { ...DEFAULT_COST_CONFIG, ...config };
616
- const tokensPerDay = tokenWaste * cfg.queriesPerDevPerDay;
641
+ const wastePerQuery = budget.wastedTokens.total;
642
+ const tokensPerDay = wastePerQuery * cfg.queriesPerDevPerDay;
617
643
  const tokensPerMonth = tokensPerDay * cfg.daysPerMonth;
618
- const cost = tokensPerMonth / 1e3 * cfg.pricePer1KTokens;
619
- return Math.round(cost * 100) / 100;
644
+ const totalWeight = cfg.developerCount;
645
+ const price = config.pricePer1KTokens ?? model.pricePer1KInputTokens;
646
+ const baseCost = tokensPerMonth / 1e3 * price * totalWeight;
647
+ let confidence = 0.85;
648
+ if (model.contextTier === "frontier") confidence = 0.7;
649
+ const variance = 0.25;
650
+ const range = [
651
+ Math.round(baseCost * (1 - variance) * 100) / 100,
652
+ Math.round(baseCost * (1 + variance) * 100) / 100
653
+ ];
654
+ return {
655
+ total: Math.round(baseCost * 100) / 100,
656
+ range,
657
+ confidence
658
+ };
620
659
  }
621
660
  function calculateProductivityImpact(issues, hourlyRate = DEFAULT_HOURLY_RATE) {
622
661
  const counts = {
@@ -999,6 +1038,52 @@ function getDebtBreakdown(patternCost, contextCost, consistencyCost) {
999
1038
  return priorityOrder[a.priority] - priorityOrder[b.priority];
1000
1039
  });
1001
1040
  }
1041
+ function generateValueChain(params) {
1042
+ const { issueType, count, severity } = params;
1043
+ const impacts = {
1044
+ "duplicate-pattern": {
1045
+ ai: "Ambiguous context leads to code generation variants. AI picks wrong implementation 40% of the time.",
1046
+ dev: "Developers must manually resolve conflicts between suggested variants.",
1047
+ risk: "high"
1048
+ },
1049
+ "context-fragmentation": {
1050
+ ai: "Context window overflow causes model to forget mid-file dependencies resulting in hallucinations.",
1051
+ dev: "Slower AI responses and increased need for manual context pinning.",
1052
+ risk: "critical"
1053
+ },
1054
+ "naming-inconsistency": {
1055
+ ai: "Degraded intent inference. AI misidentifies domain concepts across file boundaries.",
1056
+ dev: "Increased cognitive load for new devs during onboarding.",
1057
+ risk: "moderate"
1058
+ }
1059
+ };
1060
+ const impact = impacts[issueType] || {
1061
+ ai: "Reduced suggestion quality.",
1062
+ dev: "Slowed development velocity.",
1063
+ risk: "moderate"
1064
+ };
1065
+ const productivityLoss = severity === "critical" ? 0.25 : severity === "major" ? 0.1 : 0.05;
1066
+ return {
1067
+ issueType,
1068
+ technicalMetric: "Issue Count",
1069
+ technicalValue: count,
1070
+ aiImpact: {
1071
+ description: impact.ai,
1072
+ scoreImpact: severity === "critical" ? -15 : -5
1073
+ },
1074
+ developerImpact: {
1075
+ description: impact.dev,
1076
+ productivityLoss
1077
+ },
1078
+ businessOutcome: {
1079
+ directCost: count * 12,
1080
+ // Placeholder linear cost
1081
+ opportunityCost: productivityLoss * 15e3,
1082
+ // Monthly avg dev cost $15k
1083
+ riskLevel: impact.risk
1084
+ }
1085
+ };
1086
+ }
1002
1087
 
1003
1088
  // src/parsers/typescript-parser.ts
1004
1089
  import { parse as parse2 } from "@typescript-eslint/typescript-estree";
@@ -1438,7 +1523,9 @@ var ParserFactory = class _ParserFactory {
1438
1523
  registerParser(parser) {
1439
1524
  this.parsers.set(parser.language, parser);
1440
1525
  parser.extensions.forEach((ext) => {
1441
- this.extensionMap.set(ext, parser.language);
1526
+ const lang = LANGUAGE_EXTENSIONS[ext] || parser.language;
1527
+ this.extensionMap.set(ext, lang);
1528
+ this.parsers.set(lang, parser);
1442
1529
  });
1443
1530
  }
1444
1531
  /**
@@ -2454,6 +2541,45 @@ function getLineRangeLastModifiedCached(lineStamps, startLine, endLine) {
2454
2541
  }
2455
2542
  return latest;
2456
2543
  }
2544
+ function getRepoMetadata(directory) {
2545
+ const metadata = {};
2546
+ try {
2547
+ try {
2548
+ metadata.url = execSync("git config --get remote.origin.url", {
2549
+ cwd: directory,
2550
+ encoding: "utf-8",
2551
+ stdio: ["ignore", "pipe", "ignore"]
2552
+ }).trim();
2553
+ } catch {
2554
+ }
2555
+ try {
2556
+ metadata.branch = execSync("git rev-parse --abbrev-ref HEAD", {
2557
+ cwd: directory,
2558
+ encoding: "utf-8",
2559
+ stdio: ["ignore", "pipe", "ignore"]
2560
+ }).trim();
2561
+ } catch {
2562
+ }
2563
+ try {
2564
+ metadata.commit = execSync("git rev-parse HEAD", {
2565
+ cwd: directory,
2566
+ encoding: "utf-8",
2567
+ stdio: ["ignore", "pipe", "ignore"]
2568
+ }).trim();
2569
+ } catch {
2570
+ }
2571
+ try {
2572
+ metadata.author = execSync("git log -1 --format=%ae", {
2573
+ cwd: directory,
2574
+ encoding: "utf-8",
2575
+ stdio: ["ignore", "pipe", "ignore"]
2576
+ }).trim();
2577
+ } catch {
2578
+ }
2579
+ } catch {
2580
+ }
2581
+ return metadata;
2582
+ }
2457
2583
  export {
2458
2584
  CONTEXT_TIER_THRESHOLDS,
2459
2585
  DEFAULT_COST_CONFIG,
@@ -2490,7 +2616,9 @@ export {
2490
2616
  calculateSemanticDistance,
2491
2617
  calculateTechnicalDebtInterest,
2492
2618
  calculateTestabilityIndex,
2619
+ calculateTokenBudget,
2493
2620
  clearHistory,
2621
+ estimateCostFromBudget,
2494
2622
  estimateTokens,
2495
2623
  exportHistory,
2496
2624
  extractFunctions,
@@ -2501,6 +2629,7 @@ export {
2501
2629
  formatScore,
2502
2630
  formatToolScore,
2503
2631
  generateHTML,
2632
+ generateValueChain,
2504
2633
  getDebtBreakdown,
2505
2634
  getElapsedTime,
2506
2635
  getFileCommitTimestamps,
@@ -2514,6 +2643,7 @@ export {
2514
2643
  getRatingDisplay,
2515
2644
  getRatingWithContext,
2516
2645
  getRecommendedThreshold,
2646
+ getRepoMetadata,
2517
2647
  getSupportedLanguages,
2518
2648
  getToolWeight,
2519
2649
  handleCLIError,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiready/core",
3
- "version": "0.9.35",
3
+ "version": "0.9.38",
4
4
  "description": "Shared utilities for AIReady analysis tools",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -53,6 +53,7 @@
53
53
  "scripts": {
54
54
  "build": "tsup src/index.ts src/client.ts --format cjs,esm --dts",
55
55
  "dev": "tsup src/index.ts src/client.ts --format cjs,esm --watch",
56
+ "test": "vitest run",
56
57
  "lint": "eslint src",
57
58
  "clean": "rm -rf dist",
58
59
  "release": "pnpm build && pnpm publish --no-git-checks"