@ganakailabs/cloudeval-cli 0.25.0 → 0.26.0

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.
@@ -38,10 +38,10 @@ import {
38
38
  } from "./chunk-KBHRBGSX.js";
39
39
  import {
40
40
  Banner
41
- } from "./chunk-TISPT6EB.js";
41
+ } from "./chunk-U5TI24XX.js";
42
42
  import {
43
43
  CLI_VERSION
44
- } from "./chunk-LKVKOGVL.js";
44
+ } from "./chunk-IAXSLM2G.js";
45
45
  import {
46
46
  raisedButtonStyle,
47
47
  terminalTheme
@@ -3,8 +3,8 @@ import {
3
3
  bannerMetaColor,
4
4
  bannerSegmentColor,
5
5
  splitBannerLineSegments
6
- } from "./chunk-TISPT6EB.js";
7
- import "./chunk-LKVKOGVL.js";
6
+ } from "./chunk-U5TI24XX.js";
7
+ import "./chunk-IAXSLM2G.js";
8
8
  import "./chunk-ZDKRIOMB.js";
9
9
  export {
10
10
  Banner,
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var CLI_VERSION = "0.25.0";
2
+ var CLI_VERSION = "0.26.0";
3
3
 
4
4
  export {
5
5
  CLI_VERSION
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  CLI_VERSION
3
- } from "./chunk-LKVKOGVL.js";
3
+ } from "./chunk-IAXSLM2G.js";
4
4
  import {
5
5
  shouldUseColor,
6
6
  terminalTheme
package/dist/cli.js CHANGED
@@ -36,7 +36,7 @@ import {
36
36
  } from "./chunk-KBHRBGSX.js";
37
37
  import {
38
38
  CLI_VERSION
39
- } from "./chunk-LKVKOGVL.js";
39
+ } from "./chunk-IAXSLM2G.js";
40
40
 
41
41
  // src/runtime/prepareInk.ts
42
42
  import fs from "fs";
@@ -453,6 +453,8 @@ var cliCommands = [
453
453
  "--wait-timeout",
454
454
  "--poll-interval",
455
455
  "--no-ai-summary",
456
+ "--ai-summary-mode",
457
+ "--ai-summary-profile",
456
458
  "--ignore-dirty",
457
459
  "--output",
458
460
  "--format",
@@ -2398,6 +2400,10 @@ var parseGateConfig = (configText) => {
2398
2400
  if (!configText || !/^\s*ci\s*:/m.test(configText) || !/^\s*gates\s*:/m.test(configText)) {
2399
2401
  return void 0;
2400
2402
  }
2403
+ const stringValue2 = (key) => {
2404
+ const match = configText.match(new RegExp(`^\\s*${key}\\s*:\\s*([^\\s#]+)`, "m"));
2405
+ return match ? match[1].trim() : void 0;
2406
+ };
2401
2407
  const numberValue2 = (key) => {
2402
2408
  const match = configText.match(new RegExp(`^\\s*${key}\\s*:\\s*([0-9]+(?:\\.[0-9]+)?)`, "m"));
2403
2409
  return match ? Number(match[1]) : void 0;
@@ -2406,9 +2412,35 @@ var parseGateConfig = (configText) => {
2406
2412
  const match = configText.match(new RegExp(`^\\s*${key}\\s*:\\s*(true|false)`, "im"));
2407
2413
  return match ? match[1].toLowerCase() === "true" : void 0;
2408
2414
  };
2415
+ const pillarScoreMins = {};
2416
+ const pillarBlock = configText.match(/^(\s*)pillars\s*:\s*$(?<body>(?:\n\s+[-\w]+\s*:\s*[0-9]+(?:\.[0-9]+)?\s*)+)/m);
2417
+ const pillarBody = pillarBlock?.groups?.body ?? "";
2418
+ for (const line of pillarBody.split("\n")) {
2419
+ const match = line.match(/^\s+([-\w]+)\s*:\s*([0-9]+(?:\.[0-9]+)?)/);
2420
+ if (match) {
2421
+ pillarScoreMins[match[1].replace(/-/g, "_").toLowerCase()] = Number(match[2]);
2422
+ }
2423
+ }
2424
+ for (const key of [
2425
+ "security",
2426
+ "reliability",
2427
+ "operational_excellence",
2428
+ "performance_efficiency",
2429
+ "cost_optimization"
2430
+ ]) {
2431
+ const value = numberValue2(`${key}_score_min`);
2432
+ if (value !== void 0) {
2433
+ pillarScoreMins[key] = value;
2434
+ }
2435
+ }
2436
+ const enforcement = stringValue2("enforcement")?.toLowerCase();
2409
2437
  return {
2438
+ enforcement: enforcement === "warn" ? "warn" : "required",
2410
2439
  overallScoreMin: numberValue2("overall_score_min") ?? 80,
2440
+ pillarScoreMin: numberValue2("pillar_score_min"),
2441
+ pillarScoreMins,
2411
2442
  failOnHighRisk: booleanValue2("fail_on_high_risk") ?? true,
2443
+ failOnValidationErrors: booleanValue2("fail_on_validation_errors") ?? true,
2412
2444
  maxMonthlyCost: numberValue2("max_monthly_cost")
2413
2445
  };
2414
2446
  };
@@ -2423,10 +2455,86 @@ var numberFrom = (...values) => {
2423
2455
  }
2424
2456
  return void 0;
2425
2457
  };
2458
+ var normalizeKey = (value) => String(value ?? "").trim().replace(/[\s-]+/g, "_").toLowerCase();
2459
+ var firstRecord = (...values) => {
2460
+ for (const value of values) {
2461
+ if (value && typeof value === "object" && !Array.isArray(value)) {
2462
+ return value;
2463
+ }
2464
+ }
2465
+ return void 0;
2466
+ };
2467
+ var extractPillars = (waf) => {
2468
+ const fromArray = waf?.parsed?.score?.pillars;
2469
+ if (Array.isArray(fromArray)) {
2470
+ return fromArray.map((pillar) => {
2471
+ const record = asRecord(pillar);
2472
+ const id = normalizeKey(record.id ?? record.name ?? record.label);
2473
+ const score = numberFrom(record.score, record.value);
2474
+ if (!id || score === void 0) return void 0;
2475
+ return {
2476
+ id,
2477
+ label: String(record.label ?? record.name ?? id),
2478
+ score,
2479
+ passed: numberFrom(record.passed, record.passed_rules),
2480
+ warned: numberFrom(record.warned, record.warning_rules),
2481
+ failed: numberFrom(record.failed, record.failed_rules)
2482
+ };
2483
+ }).filter((pillar) => pillar !== void 0);
2484
+ }
2485
+ const scores = firstRecord(
2486
+ waf?.parsed?.pillar_scores,
2487
+ waf?.parsed?.score?.pillar_scores,
2488
+ waf?.raw?.pillar_scores
2489
+ );
2490
+ if (!scores) return [];
2491
+ return Object.entries(scores).map(([id, score]) => ({
2492
+ id: normalizeKey(id),
2493
+ label: id,
2494
+ score: numberFrom(score)
2495
+ })).filter((pillar) => pillar.score !== void 0);
2496
+ };
2497
+ var extractValidation = ({
2498
+ waf,
2499
+ preload,
2500
+ project
2501
+ }) => {
2502
+ const psRuleSummary = firstRecord(
2503
+ waf?.parsed?.validation_summary,
2504
+ waf?.raw?.validation_summary,
2505
+ waf?.validation_summary
2506
+ );
2507
+ const rules = Array.isArray(waf?.parsed?.rules) ? waf?.parsed?.rules : [];
2508
+ const failedRules = rules.filter(
2509
+ (rule) => ["fail", "failed", "error"].includes(String(rule?.status ?? rule?.outcome ?? "").toLowerCase())
2510
+ );
2511
+ const unitSummary = firstRecord(
2512
+ preload?.latest_payloads?.unit_tests?.summary,
2513
+ preload?.reports?.unit_tests?.metrics,
2514
+ project?.status?.unit_tests
2515
+ );
2516
+ return {
2517
+ psRule: {
2518
+ total: numberFrom(psRuleSummary?.total_rules, psRuleSummary?.totalRules, rules.length),
2519
+ passed: numberFrom(psRuleSummary?.passed_rules, psRuleSummary?.passedRules),
2520
+ failed: numberFrom(psRuleSummary?.failed_rules, psRuleSummary?.failedRules, failedRules.length),
2521
+ errors: numberFrom(psRuleSummary?.error_rules, psRuleSummary?.errorRules)
2522
+ },
2523
+ unitTests: {
2524
+ status: unitSummary?.status,
2525
+ total: numberFrom(unitSummary?.total_tests, unitSummary?.totalTests),
2526
+ passed: numberFrom(unitSummary?.passed_tests, unitSummary?.passedTests),
2527
+ failed: numberFrom(unitSummary?.failed_tests, unitSummary?.failedTests),
2528
+ skipped: numberFrom(unitSummary?.skipped_tests, unitSummary?.skippedTests)
2529
+ }
2530
+ };
2531
+ };
2426
2532
  var evaluateGate = ({
2427
2533
  configText,
2428
2534
  waf,
2429
- cost
2535
+ cost,
2536
+ preload,
2537
+ project
2430
2538
  }) => {
2431
2539
  const gateConfig = parseGateConfig(configText);
2432
2540
  const overallScore = numberFrom(
@@ -2444,13 +2552,61 @@ var evaluateGate = ({
2444
2552
  cost?.parsed?.total_spend?.amount,
2445
2553
  cost?.raw?.total
2446
2554
  );
2555
+ const currency = String(
2556
+ cost?.parsed?.totalSpend?.currency ?? cost?.parsed?.total_spend?.currency ?? cost?.raw?.currency ?? ""
2557
+ ) || void 0;
2558
+ const savings = numberFrom(
2559
+ cost?.parsed?.estimatedSavings?.amount,
2560
+ cost?.parsed?.estimated_savings?.amount
2561
+ );
2562
+ const pillars = extractPillars(waf).map((pillar) => {
2563
+ const threshold = gateConfig?.pillarScoreMins[pillar.id] ?? gateConfig?.pillarScoreMin;
2564
+ return {
2565
+ ...pillar,
2566
+ threshold,
2567
+ status: threshold !== void 0 && pillar.score < threshold ? "fail" : "pass"
2568
+ };
2569
+ });
2570
+ const validation = extractValidation({ waf, preload, project });
2571
+ const wellArchitected = {
2572
+ overall: {
2573
+ score: overallScore,
2574
+ threshold: gateConfig?.overallScoreMin,
2575
+ status: gateConfig && overallScore !== void 0 && overallScore < gateConfig.overallScoreMin ? "fail" : "pass"
2576
+ },
2577
+ pillars,
2578
+ risks: {
2579
+ high: highRisk,
2580
+ medium: numberFrom(waf?.parsed?.counts?.mediumRisk, waf?.parsed?.counts?.medium_count),
2581
+ critical: numberFrom(waf?.parsed?.counts?.criticalRisk, waf?.parsed?.counts?.critical_count)
2582
+ },
2583
+ topFindings: Array.isArray(waf?.parsed?.rules) ? waf.parsed.rules.slice(0, 5) : []
2584
+ };
2585
+ const costSummary = {
2586
+ monthly: {
2587
+ amount: monthlyCost,
2588
+ currency,
2589
+ threshold: gateConfig?.maxMonthlyCost,
2590
+ status: gateConfig?.maxMonthlyCost !== void 0 && monthlyCost !== void 0 && monthlyCost > gateConfig.maxMonthlyCost ? "fail" : "pass"
2591
+ },
2592
+ estimatedSavings: {
2593
+ amount: savings,
2594
+ currency
2595
+ },
2596
+ topServices: Array.isArray(cost?.parsed?.serviceGroups) ? cost.parsed.serviceGroups.slice(0, 5) : [],
2597
+ recommendations: Array.isArray(cost?.parsed?.recommendations) ? cost.parsed.recommendations.slice(0, 5) : []
2598
+ };
2447
2599
  if (!gateConfig) {
2448
2600
  return {
2449
2601
  status: "warn",
2450
2602
  reason: "ci.gates is not configured in .cloudeval/config.yaml.",
2603
+ enforcement: "warn",
2451
2604
  overallScore,
2452
2605
  highRisk,
2453
- monthlyCost
2606
+ monthlyCost,
2607
+ wellArchitected,
2608
+ cost: costSummary,
2609
+ validation
2454
2610
  };
2455
2611
  }
2456
2612
  const failures = [];
@@ -2462,16 +2618,34 @@ var evaluateGate = ({
2462
2618
  if (gateConfig.failOnHighRisk && highRisk !== void 0 && highRisk > 0) {
2463
2619
  failures.push(`${highRisk} high-risk architecture findings`);
2464
2620
  }
2621
+ for (const pillar of pillars) {
2622
+ if (pillar.status === "fail") {
2623
+ failures.push(`${pillar.label} score ${pillar.score} is below ${pillar.threshold}`);
2624
+ }
2625
+ }
2626
+ const failedPsRules = validation.psRule.failed ?? 0;
2627
+ const failedUnitTests = validation.unitTests.failed ?? 0;
2628
+ if (gateConfig.failOnValidationErrors && (failedPsRules > 0 || failedUnitTests > 0)) {
2629
+ failures.push(
2630
+ `validation has ${failedPsRules} failed PSRule checks and ${failedUnitTests} failed unit tests`
2631
+ );
2632
+ }
2465
2633
  if (gateConfig.maxMonthlyCost !== void 0 && monthlyCost !== void 0 && monthlyCost > gateConfig.maxMonthlyCost) {
2466
2634
  failures.push(`monthly cost ${monthlyCost} exceeds ${gateConfig.maxMonthlyCost}`);
2467
2635
  }
2636
+ const wouldFail = failures.length > 0;
2468
2637
  return {
2469
- status: failures.length ? "fail" : "pass",
2638
+ status: wouldFail && gateConfig.enforcement === "required" ? "fail" : wouldFail ? "warn" : "pass",
2639
+ enforcement: gateConfig.enforcement,
2640
+ wouldFail,
2470
2641
  failures,
2471
2642
  thresholds: gateConfig,
2472
2643
  overallScore,
2473
2644
  highRisk,
2474
- monthlyCost
2645
+ monthlyCost,
2646
+ wellArchitected,
2647
+ cost: costSummary,
2648
+ validation
2475
2649
  };
2476
2650
  };
2477
2651
  var safeFetch = async (input) => {
@@ -2579,6 +2753,7 @@ var buildAiSummaryPrompt = (data) => [
2579
2753
  `Well-Architected score: ${data.gate?.overallScore ?? "unknown"}`,
2580
2754
  `High-risk findings: ${data.gate?.highRisk ?? "unknown"}`,
2581
2755
  `Monthly cost: ${data.gate?.monthlyCost ?? "unknown"}`,
2756
+ `Validation: PSRule failed ${data.gate?.validation?.psRule?.failed ?? "unknown"}, unit tests failed ${data.gate?.validation?.unitTests?.failed ?? "unknown"}`,
2582
2757
  Array.isArray(data.gate?.failures) && data.gate.failures.length ? `Gate failures: ${data.gate.failures.join("; ")}` : "Gate failures: none reported"
2583
2758
  ].join("\n");
2584
2759
  var generateAiSummary = async ({
@@ -2587,6 +2762,8 @@ var generateAiSummary = async ({
2587
2762
  user,
2588
2763
  project,
2589
2764
  model,
2765
+ mode,
2766
+ agentProfileId,
2590
2767
  data
2591
2768
  }) => {
2592
2769
  const core = await import("./dist-CFLR5FML.js");
@@ -2613,9 +2790,10 @@ var generateAiSummary = async ({
2613
2790
  name: String(data.projectId)
2614
2791
  },
2615
2792
  settings: {
2616
- mode: "ask",
2793
+ mode,
2617
2794
  ...model ? { model } : {}
2618
2795
  },
2796
+ ...mode === "agent" ? { agentProfileId: agentProfileId ?? "architecture" } : {},
2619
2797
  completeAfterResponse: true,
2620
2798
  responseCompletionGraceMs: 250,
2621
2799
  streamIdleTimeoutMs: 3e4
@@ -2627,7 +2805,8 @@ var generateAiSummary = async ({
2627
2805
  }
2628
2806
  return {
2629
2807
  enabled: true,
2630
- mode: "ask",
2808
+ mode,
2809
+ ...mode === "agent" ? { agentProfileId: agentProfileId ?? "architecture" } : {},
2631
2810
  ...model ? { model } : {},
2632
2811
  markdown: markdown.trim(),
2633
2812
  threadId
@@ -2636,7 +2815,11 @@ var generateAiSummary = async ({
2636
2815
  var buildMarkdownSummary = (data) => {
2637
2816
  const gateStatus = String(data.gate?.status ?? "unknown").toUpperCase();
2638
2817
  const score = data.gate?.overallScore ?? "unknown";
2639
- const cost = data.gate?.monthlyCost ?? "unknown";
2818
+ const cost = data.gate?.cost?.monthly;
2819
+ const validation = data.gate?.validation;
2820
+ const pillarLines = Array.isArray(data.gate?.wellArchitected?.pillars) ? data.gate.wellArchitected.pillars.map(
2821
+ (pillar) => ` - ${pillar.label}: ${pillar.score}${pillar.threshold !== void 0 ? ` (min ${pillar.threshold})` : ""} - ${String(pillar.status ?? "unknown").toUpperCase()}`
2822
+ ) : [];
2640
2823
  const lines = [
2641
2824
  "### CloudEval review",
2642
2825
  "",
@@ -2646,8 +2829,31 @@ var buildMarkdownSummary = (data) => {
2646
2829
  `- **Commit:** \`${String(data.commitSha ?? "unknown").slice(0, 12)}\``,
2647
2830
  `- **Gate:** ${gateStatus}`,
2648
2831
  `- **Well-Architected score:** ${score}`,
2649
- `- **Monthly cost:** ${cost}`
2832
+ `- **Cost:** ${cost?.amount ?? "unknown"} ${cost?.currency ?? ""}`.trim(),
2833
+ `- **Validation:** PSRule ${validation?.psRule?.failed ?? "unknown"} failed, unit tests ${validation?.unitTests?.failed ?? "unknown"} failed`
2650
2834
  ];
2835
+ if (Array.isArray(data.gate?.failures) && data.gate.failures.length) {
2836
+ lines.push("", "#### Gate failures", "", ...data.gate.failures.map((failure) => `- ${failure}`));
2837
+ }
2838
+ if (pillarLines.length) {
2839
+ lines.push("", "#### Well-Architected drilldown", "", ...pillarLines);
2840
+ }
2841
+ if (cost?.amount !== void 0 || cost?.threshold !== void 0) {
2842
+ lines.push(
2843
+ "",
2844
+ "#### Cost drilldown",
2845
+ "",
2846
+ `- Cost: ${cost?.amount ?? "unknown"} ${cost?.currency ?? ""}${cost?.threshold !== void 0 ? ` (max ${cost.threshold})` : ""}`.trim()
2847
+ );
2848
+ }
2849
+ if (validation) {
2850
+ lines.push(
2851
+ "",
2852
+ "#### Validation drilldown",
2853
+ "",
2854
+ `- Validation: PSRule ${validation.psRule?.failed ?? "unknown"} failed, unit tests ${validation.unitTests?.failed ?? "unknown"} failed`
2855
+ );
2856
+ }
2651
2857
  if (data.aiSummary?.markdown) {
2652
2858
  lines.push("", "## AI summary", "", data.aiSummary.markdown);
2653
2859
  }
@@ -2657,7 +2863,7 @@ var registerReviewCommand = (program2, deps) => {
2657
2863
  const command = addAuthOptions(
2658
2864
  program2.command("review").description("Review the current GitHub-backed project from a pushed commit"),
2659
2865
  deps.defaultBaseUrl
2660
- ).option("--project <id>", "CloudEval project id. If omitted, resolve by GitHub repo metadata.").option("--repo <owner/repo>", "GitHub repository. Defaults to git origin.").option("--ref <name>", "Git branch/ref. Defaults to current branch.").option("--commit-sha <sha>", "Commit SHA to sync/review. Defaults to local HEAD.").option("--source-root <path>", "GitHub source root used by the CloudEval project.").option("--config <path>", "Path to .cloudeval/config.yaml for gate thresholds.").option("--no-wait", "Submit GitHub sync and return without waiting for analysis.").option("--wait-timeout <ms>", "Maximum time to wait for GitHub sync.", "900000").option("--poll-interval <ms>", "Polling interval while waiting for GitHub sync.", "5000").option("--no-ai-summary", "Skip the AI-written review summary.").option("--ignore-dirty", "Review HEAD even if the local working tree has uncommitted changes.", false).option("--output <dir>", "Write review.json and review.md into a directory.").option("--quiet", "Accepted for CI parity; review output stays machine-readable.", false).option("--progress <mode>", "Accepted for CI parity; review does not stream progress.", "none").option("--model <model>", "Accepted for CI parity with ask/agent modes.").option("--format <format>", "Output format: text, json, ndjson, markdown", "text");
2866
+ ).option("--project <id>", "CloudEval project id. If omitted, resolve by GitHub repo metadata.").option("--repo <owner/repo>", "GitHub repository. Defaults to git origin.").option("--ref <name>", "Git branch/ref. Defaults to current branch.").option("--commit-sha <sha>", "Commit SHA to sync/review. Defaults to local HEAD.").option("--source-root <path>", "GitHub source root used by the CloudEval project.").option("--config <path>", "Path to .cloudeval/config.yaml for gate thresholds.").option("--no-wait", "Submit GitHub sync and return without waiting for analysis.").option("--wait-timeout <ms>", "Maximum time to wait for GitHub sync.", "900000").option("--poll-interval <ms>", "Polling interval while waiting for GitHub sync.", "5000").option("--no-ai-summary", "Skip the AI-written review summary.").option("--ai-summary-mode <mode>", "AI summary mode: ask or agent.", "ask").option("--ai-summary-profile <profile-id>", "Agent Profile id when --ai-summary-mode agent is used.", "architecture").option("--ignore-dirty", "Review HEAD even if the local working tree has uncommitted changes.", false).option("--output <dir>", "Write review.json and review.md into a directory.").option("--quiet", "Accepted for CI parity; review output stays machine-readable.", false).option("--progress <mode>", "Accepted for CI parity; review does not stream progress.", "none").option("--model <model>", "Accepted for CI parity with ask/agent modes.").option("--format <format>", "Output format: text, json, ndjson, markdown", "text");
2661
2867
  command.action(async (options, actionCommand) => {
2662
2868
  try {
2663
2869
  const cwd = process.cwd();
@@ -2720,6 +2926,11 @@ var registerReviewCommand = (program2, deps) => {
2720
2926
  token: context.token,
2721
2927
  projectId
2722
2928
  });
2929
+ const preload = context.user?.id ? await safeFetch({
2930
+ baseUrl: context.baseUrl,
2931
+ authToken: context.token,
2932
+ path: `/reports/preload/${encodeURIComponent(projectId)}?user_id=${encodeURIComponent(context.user.id)}&include_payload=true`
2933
+ }) : void 0;
2723
2934
  const data = {
2724
2935
  projectId,
2725
2936
  repo,
@@ -2729,18 +2940,25 @@ var registerReviewCommand = (program2, deps) => {
2729
2940
  sync: finalStatus ? { ...asRecord(sync), finalStatus } : sync,
2730
2941
  reports: {
2731
2942
  cost,
2732
- waf
2943
+ waf,
2944
+ preload
2733
2945
  },
2734
- gate: evaluateGate({ configText, waf, cost })
2946
+ gate: evaluateGate({ configText, waf, cost, preload, project })
2735
2947
  };
2736
2948
  if (options.aiSummary !== false) {
2737
2949
  try {
2950
+ const aiSummaryMode = String(options.aiSummaryMode ?? "ask").toLowerCase();
2951
+ if (!["ask", "agent"].includes(aiSummaryMode)) {
2952
+ throw new Error("--ai-summary-mode must be ask or agent.");
2953
+ }
2738
2954
  data.aiSummary = await generateAiSummary({
2739
2955
  baseUrl: context.baseUrl,
2740
2956
  token: context.token,
2741
2957
  user: context.user,
2742
2958
  project,
2743
2959
  model: options.model,
2960
+ mode: aiSummaryMode,
2961
+ agentProfileId: options.aiSummaryProfile,
2744
2962
  data
2745
2963
  });
2746
2964
  } catch (error) {
@@ -14625,7 +14843,7 @@ program.command("tui").description("Open the CloudEval Terminal UI").option(
14625
14843
  const { assertSecureBaseUrl } = await import("./dist-CFLR5FML.js");
14626
14844
  const [{ render }, { App }] = await Promise.all([
14627
14845
  import("ink"),
14628
- import("./App-H46FRLWK.js")
14846
+ import("./App-XNVJF2ON.js")
14629
14847
  ]);
14630
14848
  const baseUrl = await resolveBaseUrl(options, command);
14631
14849
  assertSecureBaseUrl(baseUrl);
@@ -14683,7 +14901,7 @@ program.command("chat").description("Start an interactive chat session").option(
14683
14901
  const { assertSecureBaseUrl } = await import("./dist-CFLR5FML.js");
14684
14902
  const [{ render }, { App }] = await Promise.all([
14685
14903
  import("ink"),
14686
- import("./App-H46FRLWK.js")
14904
+ import("./App-XNVJF2ON.js")
14687
14905
  ]);
14688
14906
  const baseUrl = await resolveBaseUrl(options, command);
14689
14907
  assertSecureBaseUrl(baseUrl);
@@ -15437,7 +15655,7 @@ Error: ${errorMsg}
15437
15655
  program.command("banner").description("Preview the startup banner and terminal capabilities").action(async () => {
15438
15656
  const { render } = await import("ink");
15439
15657
  const BannerPreview = React.lazy(async () => ({
15440
- default: (await import("./Banner-7X2VHUVH.js")).Banner
15658
+ default: (await import("./Banner-2FNO54OA.js")).Banner
15441
15659
  }));
15442
15660
  render(
15443
15661
  /* @__PURE__ */ jsx(React.Suspense, { fallback: null, children: /* @__PURE__ */ jsx(BannerPreview, { disable: false }) })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ganakailabs/cloudeval-cli",
3
- "version": "0.25.0",
3
+ "version": "0.26.0",
4
4
  "license": "LicenseRef-CloudEval-CLI",
5
5
  "type": "module",
6
6
  "description": "CloudEval CLI for cloud architecture, cost, report, automation, and MCP workflows.",
package/sbom.spdx.json CHANGED
@@ -14,7 +14,7 @@
14
14
  {
15
15
  "SPDXID": "SPDXRef-Package-CloudEval-CLI",
16
16
  "name": "CloudEval CLI",
17
- "versionInfo": "0.25.0",
17
+ "versionInfo": "0.26.0",
18
18
  "downloadLocation": "https://github.com/ganakailabs/cloudeval-cli",
19
19
  "filesAnalyzed": false,
20
20
  "licenseConcluded": "LicenseRef-CloudEval-CLI",