@ganakailabs/cloudeval-cli 0.27.0 → 0.27.2
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/{App-GQMIIL3U.js → App-VSOTHLOD.js} +2 -2
- package/dist/{Banner-J2ESX3JN.js → Banner-7XUOJYL5.js} +2 -2
- package/dist/{chunk-5AH64UNL.js → chunk-3DBCT463.js} +1 -1
- package/dist/{chunk-YW5JWFYV.js → chunk-SLRYBS3P.js} +1 -1
- package/dist/cli.js +294 -299
- package/package.json +1 -1
- package/sbom.spdx.json +1 -1
|
@@ -38,10 +38,10 @@ import {
|
|
|
38
38
|
} from "./chunk-USSCB2ZU.js";
|
|
39
39
|
import {
|
|
40
40
|
Banner
|
|
41
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-3DBCT463.js";
|
|
42
42
|
import {
|
|
43
43
|
CLI_VERSION
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-SLRYBS3P.js";
|
|
45
45
|
import {
|
|
46
46
|
raisedButtonStyle,
|
|
47
47
|
terminalTheme
|
package/dist/cli.js
CHANGED
|
@@ -39,7 +39,7 @@ import {
|
|
|
39
39
|
} from "./chunk-USSCB2ZU.js";
|
|
40
40
|
import {
|
|
41
41
|
CLI_VERSION
|
|
42
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-SLRYBS3P.js";
|
|
43
43
|
|
|
44
44
|
// src/runtime/prepareInk.ts
|
|
45
45
|
import fs from "fs";
|
|
@@ -2506,6 +2506,14 @@ var firstRecord = (...values) => {
|
|
|
2506
2506
|
}
|
|
2507
2507
|
return void 0;
|
|
2508
2508
|
};
|
|
2509
|
+
var firstArray = (...values) => {
|
|
2510
|
+
for (const value of values) {
|
|
2511
|
+
if (Array.isArray(value)) {
|
|
2512
|
+
return value;
|
|
2513
|
+
}
|
|
2514
|
+
}
|
|
2515
|
+
return void 0;
|
|
2516
|
+
};
|
|
2509
2517
|
var entriesAsNamedRecords = (value, amountKey = "amount") => {
|
|
2510
2518
|
const record = firstRecord(value);
|
|
2511
2519
|
if (!record) {
|
|
@@ -2570,7 +2578,8 @@ var formatMoney = (amount, currency, fallback = "not available") => {
|
|
|
2570
2578
|
if (numericAmount === void 0) {
|
|
2571
2579
|
return fallback;
|
|
2572
2580
|
}
|
|
2573
|
-
|
|
2581
|
+
const formattedAmount = trimNumber(numericAmount);
|
|
2582
|
+
return currency ? `${formattedAmount} ${currency}` : formattedAmount;
|
|
2574
2583
|
};
|
|
2575
2584
|
var trimNumber = (value, fractionDigits = 2) => Number.isInteger(value) ? String(value) : String(Number(value.toFixed(fractionDigits)));
|
|
2576
2585
|
var formatScore = (value, fallback = "unknown") => {
|
|
@@ -2659,21 +2668,6 @@ var statusIcon = (status) => {
|
|
|
2659
2668
|
return "\u26AA";
|
|
2660
2669
|
}
|
|
2661
2670
|
};
|
|
2662
|
-
var formatValidation = (validation) => {
|
|
2663
|
-
const policyFailed = numberFrom(validation?.policyChecks?.failed);
|
|
2664
|
-
const unitFailed = numberFrom(validation?.unitTests?.failed);
|
|
2665
|
-
if (policyFailed === 0 && unitFailed === 0) {
|
|
2666
|
-
return "Validation clean";
|
|
2667
|
-
}
|
|
2668
|
-
const parts = [];
|
|
2669
|
-
if (unitFailed !== void 0) {
|
|
2670
|
-
parts.push(unitFailed === 0 ? "unit tests clean" : `${unitFailed} unit tests failed`);
|
|
2671
|
-
}
|
|
2672
|
-
if (policyFailed !== void 0) {
|
|
2673
|
-
parts.push(policyFailed === 0 ? "policy checks clean" : `${policyFailed} policy checks failed`);
|
|
2674
|
-
}
|
|
2675
|
-
return parts.length ? parts.join(", ") : "Validation not available";
|
|
2676
|
-
};
|
|
2677
2671
|
var validationSummaryLine = (validation) => {
|
|
2678
2672
|
const unitFailed = numberFrom(validation?.unitTests?.failed);
|
|
2679
2673
|
if (unitFailed === void 0) {
|
|
@@ -2715,6 +2709,135 @@ var validationDetailLines = (validation) => {
|
|
|
2715
2709
|
}
|
|
2716
2710
|
return lines.length ? lines : ["- Validation data was not available."];
|
|
2717
2711
|
};
|
|
2712
|
+
var failedValidationRecords = (records) => (Array.isArray(records) ? records : []).map(asRecord).filter((record) => {
|
|
2713
|
+
const status = String(
|
|
2714
|
+
record.status ?? record.outcome ?? record.result ?? record.state ?? ""
|
|
2715
|
+
).toLowerCase();
|
|
2716
|
+
if (record.passed === false || record.success === false) {
|
|
2717
|
+
return true;
|
|
2718
|
+
}
|
|
2719
|
+
return ["fail", "failed", "error", "critical"].includes(status);
|
|
2720
|
+
});
|
|
2721
|
+
var severityIcon = (severity) => {
|
|
2722
|
+
switch (String(severity ?? "").toLowerCase()) {
|
|
2723
|
+
case "critical":
|
|
2724
|
+
case "error":
|
|
2725
|
+
case "high":
|
|
2726
|
+
case "fail":
|
|
2727
|
+
case "failed":
|
|
2728
|
+
return "\u{1F534}";
|
|
2729
|
+
case "warning":
|
|
2730
|
+
case "warn":
|
|
2731
|
+
case "medium":
|
|
2732
|
+
return "\u{1F7E1}";
|
|
2733
|
+
case "info":
|
|
2734
|
+
case "low":
|
|
2735
|
+
return "\u{1F535}";
|
|
2736
|
+
default:
|
|
2737
|
+
return "\u26AA";
|
|
2738
|
+
}
|
|
2739
|
+
};
|
|
2740
|
+
var compactMarkdownCell = (value, fallback = "not available") => {
|
|
2741
|
+
const text = String(value ?? "").replace(/\s+/g, " ").replace(/\|/g, "\\|").trim();
|
|
2742
|
+
return text || fallback;
|
|
2743
|
+
};
|
|
2744
|
+
var failureName = (record, fallback) => compactMarkdownCell(
|
|
2745
|
+
record.test_name ?? record.testName ?? record.rule_name ?? record.ruleName ?? record.name ?? record.title ?? record.id ?? fallback
|
|
2746
|
+
);
|
|
2747
|
+
var failureLocation = (record) => compactMarkdownCell(
|
|
2748
|
+
record.file_path ?? record.filePath ?? record.path ?? record.resource_id ?? record.resourceId ?? record.resource ?? record.target,
|
|
2749
|
+
"-"
|
|
2750
|
+
);
|
|
2751
|
+
var failureWhy = (record) => {
|
|
2752
|
+
const message = compactMarkdownCell(
|
|
2753
|
+
record.message ?? record.reason ?? record.description ?? record.details,
|
|
2754
|
+
""
|
|
2755
|
+
);
|
|
2756
|
+
const recommendation = compactMarkdownCell(
|
|
2757
|
+
record.recommendation ?? record.remediation ?? record.fix ?? record.next_step,
|
|
2758
|
+
""
|
|
2759
|
+
);
|
|
2760
|
+
if (message && recommendation && message !== recommendation) {
|
|
2761
|
+
return `${message} ${recommendation}`;
|
|
2762
|
+
}
|
|
2763
|
+
return message || recommendation || "No failure reason was included in the report payload.";
|
|
2764
|
+
};
|
|
2765
|
+
var validationFailureRows = (validation) => {
|
|
2766
|
+
const rows = [];
|
|
2767
|
+
const unitFailures = (Array.isArray(validation?.unitTests?.failures) ? validation?.unitTests?.failures : []).map(asRecord).slice(0, 5);
|
|
2768
|
+
const policyFailures = (Array.isArray(validation?.policyChecks?.failures) ? validation?.policyChecks?.failures : []).map(asRecord).slice(0, 5);
|
|
2769
|
+
const groupedFailures = [
|
|
2770
|
+
["Unit test", unitFailures],
|
|
2771
|
+
["Policy check", policyFailures]
|
|
2772
|
+
];
|
|
2773
|
+
for (const [kind, failures] of groupedFailures) {
|
|
2774
|
+
failures.forEach((failure, index) => {
|
|
2775
|
+
const severity = compactMarkdownCell(
|
|
2776
|
+
failure.severity ?? failure.status ?? failure.outcome,
|
|
2777
|
+
"failed"
|
|
2778
|
+
);
|
|
2779
|
+
rows.push(
|
|
2780
|
+
`| ${kind} | ${failureName(failure, `${kind} ${index + 1}`)} | \`${failureLocation(failure)}\` | ${severityIcon(severity)} ${severity} | ${failureWhy(failure)} |`
|
|
2781
|
+
);
|
|
2782
|
+
});
|
|
2783
|
+
}
|
|
2784
|
+
return rows;
|
|
2785
|
+
};
|
|
2786
|
+
var architectureSignalLines = ({
|
|
2787
|
+
architecture,
|
|
2788
|
+
costServices,
|
|
2789
|
+
costCurrency,
|
|
2790
|
+
highRiskFindings,
|
|
2791
|
+
pillars
|
|
2792
|
+
}) => {
|
|
2793
|
+
const lines = [];
|
|
2794
|
+
const resourceCount = numberFrom(architecture?.resources);
|
|
2795
|
+
const resourceTypeCount = numberFrom(architecture?.resourceTypes);
|
|
2796
|
+
const relationshipCount = numberFrom(architecture?.relationships);
|
|
2797
|
+
const density = numberFrom(architecture?.relationshipDensity);
|
|
2798
|
+
if (resourceCount !== void 0 && resourceTypeCount !== void 0) {
|
|
2799
|
+
lines.push(
|
|
2800
|
+
`- Scale: **${displayNumber(resourceCount)} resources** across **${displayNumber(resourceTypeCount)} resource types**`
|
|
2801
|
+
);
|
|
2802
|
+
} else if (resourceCount !== void 0) {
|
|
2803
|
+
lines.push(`- Scale: **${displayNumber(resourceCount)} resources**`);
|
|
2804
|
+
}
|
|
2805
|
+
if (relationshipCount !== void 0) {
|
|
2806
|
+
const densityText = density !== void 0 ? ` (**${trimNumber(density, 2)} per resource**)` : "";
|
|
2807
|
+
const shape = density !== void 0 && density < 0.5 ? "; sparse dependency graph, review isolated resources and missing links" : density !== void 0 && density > 2 ? "; dense dependency graph, review blast radius before changes" : "";
|
|
2808
|
+
lines.push(
|
|
2809
|
+
`- Dependency shape: **${displayNumber(relationshipCount)} relationships**${densityText}${shape}`
|
|
2810
|
+
);
|
|
2811
|
+
}
|
|
2812
|
+
const highRisk = numberFrom(highRiskFindings);
|
|
2813
|
+
const weakestPillar = pillars.map((pillar) => ({
|
|
2814
|
+
label: String(pillar.label ?? pillar.id ?? "pillar"),
|
|
2815
|
+
score: numberFrom(pillar.score)
|
|
2816
|
+
})).filter((pillar) => pillar.score !== void 0).sort((left, right) => left.score - right.score)[0];
|
|
2817
|
+
if (highRisk !== void 0 || weakestPillar) {
|
|
2818
|
+
const parts = [];
|
|
2819
|
+
if (highRisk !== void 0) {
|
|
2820
|
+
parts.push(`**${displayNumber(highRisk)} high-risk findings**`);
|
|
2821
|
+
}
|
|
2822
|
+
if (weakestPillar) {
|
|
2823
|
+
const rating = scoreRating(weakestPillar.score);
|
|
2824
|
+
parts.push(
|
|
2825
|
+
`weakest pillar **${weakestPillar.label} ${formatScore(weakestPillar.score)} (${rating ?? "UNKNOWN"})**`
|
|
2826
|
+
);
|
|
2827
|
+
}
|
|
2828
|
+
lines.push(`- Risk concentration: ${parts.join("; ")}`);
|
|
2829
|
+
}
|
|
2830
|
+
const topCostDrivers = costServices.filter((service) => service.amount > 0).sort((left, right) => right.amount - left.amount).slice(0, 2);
|
|
2831
|
+
if (topCostDrivers.length) {
|
|
2832
|
+
const total = topCostDrivers.reduce((sum, service) => sum + service.amount, 0);
|
|
2833
|
+
lines.push(
|
|
2834
|
+
`- Cost drivers: ${joinReadableList(
|
|
2835
|
+
topCostDrivers.map((service) => `**${service.name}**`)
|
|
2836
|
+
)} account for **${formatMonthlyMoney(total, costCurrency ?? topCostDrivers[0]?.currency)}**`
|
|
2837
|
+
);
|
|
2838
|
+
}
|
|
2839
|
+
return lines;
|
|
2840
|
+
};
|
|
2718
2841
|
var namedAmount = (record) => numberFrom(
|
|
2719
2842
|
record.amount,
|
|
2720
2843
|
record.monthly_cost,
|
|
@@ -2724,6 +2847,15 @@ var namedAmount = (record) => numberFrom(
|
|
|
2724
2847
|
);
|
|
2725
2848
|
var namedLabel = (record, fallback) => String(record.name ?? record.service ?? record.label ?? record.category ?? fallback);
|
|
2726
2849
|
var mermaidLabel = (value) => value.replace(/"/g, "'");
|
|
2850
|
+
var joinReadableList = (values) => {
|
|
2851
|
+
if (values.length <= 1) {
|
|
2852
|
+
return values[0] ?? "";
|
|
2853
|
+
}
|
|
2854
|
+
if (values.length === 2) {
|
|
2855
|
+
return `${values[0]} and ${values[1]}`;
|
|
2856
|
+
}
|
|
2857
|
+
return `${values.slice(0, -1).join(", ")}, and ${values[values.length - 1]}`;
|
|
2858
|
+
};
|
|
2727
2859
|
var costServiceRows = (services, currency) => (Array.isArray(services) ? services : []).map((service, index) => {
|
|
2728
2860
|
const record = asRecord(service);
|
|
2729
2861
|
const amount = namedAmount(record);
|
|
@@ -2817,19 +2949,41 @@ var extractValidation = ({
|
|
|
2817
2949
|
preload?.reports?.unit_tests?.metrics,
|
|
2818
2950
|
project?.status?.unit_tests
|
|
2819
2951
|
);
|
|
2952
|
+
const unitFailures = failedValidationRecords(
|
|
2953
|
+
firstArray(
|
|
2954
|
+
preload?.latest_payloads?.unit_tests?.test_results,
|
|
2955
|
+
preload?.latest_payloads?.unit_tests?.results,
|
|
2956
|
+
preload?.reports?.unit_tests?.metrics?.test_results,
|
|
2957
|
+
preload?.reports?.unit_tests?.metrics?.results,
|
|
2958
|
+
project?.status?.unit_tests?.test_results,
|
|
2959
|
+
project?.status?.unit_tests?.results
|
|
2960
|
+
)
|
|
2961
|
+
);
|
|
2962
|
+
const policyFailures = failedValidationRecords(
|
|
2963
|
+
firstArray(
|
|
2964
|
+
policySummary?.results,
|
|
2965
|
+
policySummary?.checks,
|
|
2966
|
+
waf?.parsed?.validation_results,
|
|
2967
|
+
waf?.parsed?.rules,
|
|
2968
|
+
waf?.raw?.rules,
|
|
2969
|
+
failedRules
|
|
2970
|
+
)
|
|
2971
|
+
);
|
|
2820
2972
|
return {
|
|
2821
2973
|
policyChecks: {
|
|
2822
2974
|
total: numberFrom(policySummary?.total_rules, policySummary?.totalRules, rules.length),
|
|
2823
2975
|
passed: numberFrom(policySummary?.passed_rules, policySummary?.passedRules),
|
|
2824
2976
|
failed: numberFrom(policySummary?.failed_rules, policySummary?.failedRules, failedRules.length),
|
|
2825
|
-
errors: numberFrom(policySummary?.error_rules, policySummary?.errorRules)
|
|
2977
|
+
errors: numberFrom(policySummary?.error_rules, policySummary?.errorRules),
|
|
2978
|
+
failures: policyFailures.slice(0, 5)
|
|
2826
2979
|
},
|
|
2827
2980
|
unitTests: {
|
|
2828
2981
|
status: unitSummary?.status,
|
|
2829
2982
|
total: numberFrom(unitSummary?.total_tests, unitSummary?.totalTests),
|
|
2830
2983
|
passed: numberFrom(unitSummary?.passed_tests, unitSummary?.passedTests),
|
|
2831
2984
|
failed: numberFrom(unitSummary?.failed_tests, unitSummary?.failedTests),
|
|
2832
|
-
skipped: numberFrom(unitSummary?.skipped_tests, unitSummary?.skippedTests)
|
|
2985
|
+
skipped: numberFrom(unitSummary?.skipped_tests, unitSummary?.skippedTests),
|
|
2986
|
+
failures: unitFailures.slice(0, 5)
|
|
2833
2987
|
}
|
|
2834
2988
|
};
|
|
2835
2989
|
};
|
|
@@ -3184,81 +3338,8 @@ var waitForReviewReports = async ({
|
|
|
3184
3338
|
}
|
|
3185
3339
|
return latest;
|
|
3186
3340
|
};
|
|
3187
|
-
var buildAiSummaryPrompt = (data) => [
|
|
3188
|
-
"Write a concise CloudEval pull request review summary in Markdown.",
|
|
3189
|
-
"Return exactly two sections: Short Summary and Details.",
|
|
3190
|
-
"Short Summary: one dense paragraph under 45 words with gate status, Well-Architected posture, validation, and cost.",
|
|
3191
|
-
"Details: short bullets with bold labels only when useful, such as **Key risks:**, **Cost posture:**, and **Recommended next step:**.",
|
|
3192
|
-
"Keep the full response under 180 words. Do not invent facts not present below.",
|
|
3193
|
-
"Do not include citations, source markers, hidden tool ids, or HTML comments.",
|
|
3194
|
-
"",
|
|
3195
|
-
`Project: ${data.projectId}`,
|
|
3196
|
-
`Repository: ${data.repo ?? "unknown"}`,
|
|
3197
|
-
`Ref: ${data.ref ?? "unknown"}`,
|
|
3198
|
-
`Commit: ${data.commitSha ?? "unknown"}`,
|
|
3199
|
-
`Gate: ${String(data.gate?.status ?? "unknown").toUpperCase()}`,
|
|
3200
|
-
`Well-Architected score: ${data.gate?.wellArchitected?.overall?.score ?? data.gate?.overallScore ?? "unknown"}`,
|
|
3201
|
-
`High-risk findings: ${data.gate?.wellArchitected?.risks?.high ?? data.gate?.highRisk ?? "unknown"}`,
|
|
3202
|
-
`Monthly cost: ${formatMoney(data.gate?.cost?.monthly?.amount ?? data.gate?.monthlyCost, data.gate?.cost?.monthly?.currency)}`,
|
|
3203
|
-
`Validation: ${formatValidation(data.gate?.validation)}`,
|
|
3204
|
-
Array.isArray(data.gate?.failures) && data.gate.failures.length ? `Gate failures: ${data.gate.failures.join("; ")}` : "Gate failures: none reported"
|
|
3205
|
-
].join("\n");
|
|
3206
|
-
var isTransientAiSummaryText = (text) => {
|
|
3207
|
-
if (!text?.trim()) {
|
|
3208
|
-
return false;
|
|
3209
|
-
}
|
|
3210
|
-
return /too many requests|rate[- ]?limit|try again in a moment|temporarily unavailable|something went wrong while processing|please try again or ask a different question|did not complete within/i.test(
|
|
3211
|
-
text
|
|
3212
|
-
);
|
|
3213
|
-
};
|
|
3214
|
-
var normalizeAiSummaryMarkdown = (text) => {
|
|
3215
|
-
return normalizeAiSummarySections(text).markdown;
|
|
3216
|
-
};
|
|
3217
|
-
var normalizeAiSummarySections = (text) => {
|
|
3218
|
-
const trimmed = String(text ?? "").trim();
|
|
3219
|
-
if (!trimmed) {
|
|
3220
|
-
return { shortSummary: "", detailsMarkdown: "", markdown: "" };
|
|
3221
|
-
}
|
|
3222
|
-
const withNewlines = sanitizeAiSummaryMarkdown(trimmed.replace(/\\n/g, "\n"));
|
|
3223
|
-
const requestMatch = /\bRequest:\s*/i.exec(withNewlines);
|
|
3224
|
-
const sourceText = requestMatch ? withNewlines.slice(requestMatch.index + requestMatch[0].length).split(/\n\s*\nThe request reached\b/i)[0].trim() || withNewlines : withNewlines;
|
|
3225
|
-
const sections = splitAiSummarySections(sourceText);
|
|
3226
|
-
return {
|
|
3227
|
-
...sections,
|
|
3228
|
-
markdown: renderAiSummarySections(sections.shortSummary, sections.detailsMarkdown)
|
|
3229
|
-
};
|
|
3230
|
-
};
|
|
3231
|
-
var sanitizeAiSummaryMarkdown = (text) => text.replace(/<!--[\s\S]*?-->/g, "").replace(/\s*\[S_[A-Za-z0-9_:-]+\]/g, "").replace(/\n{3,}/g, "\n\n").trim();
|
|
3232
|
-
var stripAiSectionLabel = (text, label) => text.replace(new RegExp(`^\\s*#{0,6}\\s*\\*\\*?${label}\\*\\*?\\s*:?\\s*`, "i"), "").replace(new RegExp(`^\\s*${label}\\s*:?\\s*`, "i"), "").trim();
|
|
3233
|
-
var normalizeAiDetailHeadings = (text) => text.split("\n").map((line) => {
|
|
3234
|
-
const cleaned = line.replace(/^\s*#{1,6}\s*/, "").replace(/^\s*[-*]\s+/, "").trimEnd();
|
|
3235
|
-
const labelMatch = cleaned.match(/^\*\*(Key risks|Cost posture|Recommended next step|Recommendation|Validation|Impact):\*\*\s*(.*)$/i) ?? cleaned.match(/^\*\*(Key risks|Cost posture|Recommended next step|Recommendation|Validation|Impact)\*\*\s*:\s*(.*)$/i) ?? cleaned.match(/^(Key risks|Cost posture|Recommended next step|Recommendation|Validation|Impact)\s*:\s*(.*)$/i);
|
|
3236
|
-
if (!labelMatch) {
|
|
3237
|
-
return cleaned;
|
|
3238
|
-
}
|
|
3239
|
-
return `- **${labelMatch[1]}:** ${labelMatch[2]}`.trimEnd();
|
|
3240
|
-
}).join("\n").trim();
|
|
3241
|
-
var splitAiSummarySections = (text) => {
|
|
3242
|
-
const cleaned = sanitizeAiSummaryMarkdown(text).replace(/^\s*#{1,6}\s*AI summary\s*$/gim, "").trim();
|
|
3243
|
-
const shortMatch = /\bShort Summary\s*:\s*/i.exec(cleaned);
|
|
3244
|
-
const detailsMatch = /\bDetails\s*:\s*/i.exec(cleaned);
|
|
3245
|
-
if (shortMatch && detailsMatch && shortMatch.index < detailsMatch.index) {
|
|
3246
|
-
const shortSummary2 = stripAiSectionLabel(
|
|
3247
|
-
cleaned.slice(shortMatch.index, detailsMatch.index).trim(),
|
|
3248
|
-
"Short Summary"
|
|
3249
|
-
);
|
|
3250
|
-
const detailsMarkdown2 = normalizeAiDetailHeadings(
|
|
3251
|
-
stripAiSectionLabel(cleaned.slice(detailsMatch.index).trim(), "Details")
|
|
3252
|
-
);
|
|
3253
|
-
return { shortSummary: shortSummary2, detailsMarkdown: detailsMarkdown2 };
|
|
3254
|
-
}
|
|
3255
|
-
const paragraphs = cleaned.split(/\n\s*\n/).map((paragraph) => paragraph.trim()).filter(Boolean);
|
|
3256
|
-
const shortSummary = stripAiSectionLabel(paragraphs[0] ?? cleaned, "Short Summary");
|
|
3257
|
-
const detailsMarkdown = normalizeAiDetailHeadings(paragraphs.slice(1).join("\n\n"));
|
|
3258
|
-
return { shortSummary, detailsMarkdown };
|
|
3259
|
-
};
|
|
3260
3341
|
var renderAiSummarySections = (shortSummary, detailsMarkdown) => {
|
|
3261
|
-
const lines = [
|
|
3342
|
+
const lines = [shortSummary.trim()];
|
|
3262
3343
|
if (detailsMarkdown.trim()) {
|
|
3263
3344
|
lines.push(
|
|
3264
3345
|
"",
|
|
@@ -3272,195 +3353,108 @@ var renderAiSummarySections = (shortSummary, detailsMarkdown) => {
|
|
|
3272
3353
|
}
|
|
3273
3354
|
return lines.join("\n");
|
|
3274
3355
|
};
|
|
3275
|
-
var
|
|
3276
|
-
const
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
}
|
|
3282
|
-
}
|
|
3283
|
-
return 18e4;
|
|
3284
|
-
};
|
|
3285
|
-
var aiSummaryRetryDelaysMs = () => {
|
|
3286
|
-
const raw = process.env.CLOUDEVAL_REVIEW_AI_RETRY_DELAYS_MS;
|
|
3287
|
-
if (raw?.trim()) {
|
|
3288
|
-
return raw.split(",").map((value) => Number.parseInt(value.trim(), 10)).filter((value) => Number.isFinite(value) && value >= 0);
|
|
3356
|
+
var githubWorkflowRunUrl = () => {
|
|
3357
|
+
const server = process.env.GITHUB_SERVER_URL;
|
|
3358
|
+
const repo = process.env.GITHUB_REPOSITORY;
|
|
3359
|
+
const runId = process.env.GITHUB_RUN_ID;
|
|
3360
|
+
if (server && repo && runId) {
|
|
3361
|
+
return `${server.replace(/\/$/, "")}/${repo}/actions/runs/${runId}`;
|
|
3289
3362
|
}
|
|
3290
|
-
return
|
|
3363
|
+
return void 0;
|
|
3291
3364
|
};
|
|
3292
|
-
var
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
data
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
cloud_provider: typeof project.cloud_provider === "string" ? project.cloud_provider : void 0,
|
|
3332
|
-
type: typeof project.type === "string" ? project.type : void 0,
|
|
3333
|
-
connection_ids: Array.isArray(project.connection_ids) ? project.connection_ids : void 0
|
|
3334
|
-
} : {
|
|
3335
|
-
id: String(data.projectId),
|
|
3336
|
-
name: String(data.projectId)
|
|
3337
|
-
},
|
|
3338
|
-
settings: {
|
|
3339
|
-
mode,
|
|
3340
|
-
...model ? { model } : {}
|
|
3341
|
-
},
|
|
3342
|
-
...mode === "agent" ? { agentProfileId: agentProfileId ?? "architecture" } : {},
|
|
3343
|
-
completeAfterResponse: true,
|
|
3344
|
-
responseCompletionGraceMs: 250,
|
|
3345
|
-
streamIdleTimeoutMs: 12e4
|
|
3346
|
-
});
|
|
3347
|
-
try {
|
|
3348
|
-
while (true) {
|
|
3349
|
-
const next = await Promise.race([iterator.next(), timeoutPromise]);
|
|
3350
|
-
if (next.done) {
|
|
3351
|
-
break;
|
|
3352
|
-
}
|
|
3353
|
-
const chunk = next.value;
|
|
3354
|
-
chatState = core.reduceChunk(chatState, chunk);
|
|
3355
|
-
const latestMessage = [...chatState.messages ?? []].reverse().find((message) => message.role === "assistant");
|
|
3356
|
-
const chunkAssistantMessage = Array.isArray(chunk?.messages) ? [...chunk.messages].reverse().find((message) => message?.role === "assistant" && typeof message?.content === "string")?.content : void 0;
|
|
3357
|
-
const content = chunk?.content;
|
|
3358
|
-
if (typeof chunkAssistantMessage === "string" && chunkAssistantMessage.trim()) {
|
|
3359
|
-
markdown = chunkAssistantMessage;
|
|
3360
|
-
}
|
|
3361
|
-
if (chunk.type === "responding" && typeof content === "string") {
|
|
3362
|
-
markdown = latestMessage?.content || `${markdown}${content}`;
|
|
3363
|
-
}
|
|
3364
|
-
}
|
|
3365
|
-
} finally {
|
|
3366
|
-
if (timeoutId) {
|
|
3367
|
-
clearTimeout(timeoutId);
|
|
3368
|
-
}
|
|
3369
|
-
if (timedOut) {
|
|
3370
|
-
await iterator.return?.(void 0).catch(() => void 0);
|
|
3371
|
-
}
|
|
3372
|
-
}
|
|
3373
|
-
const finalMessage = [...chatState.messages ?? []].reverse().find((message) => message.role === "assistant");
|
|
3374
|
-
const rawMarkdown = String(finalMessage?.content || markdown).trim();
|
|
3375
|
-
const normalized = normalizeAiSummarySections(rawMarkdown);
|
|
3365
|
+
var reviewSurface = () => {
|
|
3366
|
+
const event = String(process.env.GITHUB_EVENT_NAME ?? "").toLowerCase();
|
|
3367
|
+
const ref = String(process.env.GITHUB_REF ?? "").toLowerCase();
|
|
3368
|
+
return event.startsWith("pull_request") || ref.startsWith("refs/pull/") ? "pull_request" : "local_review";
|
|
3369
|
+
};
|
|
3370
|
+
var buildReviewSummaryPayload = (data) => ({
|
|
3371
|
+
source: process.env.GITHUB_ACTIONS === "true" ? "github_action" : "cli",
|
|
3372
|
+
surface: reviewSurface(),
|
|
3373
|
+
project: data.project ?? { id: data.projectId },
|
|
3374
|
+
repository: { full_name: data.repo },
|
|
3375
|
+
ref: data.ref,
|
|
3376
|
+
commit_sha: data.commitSha,
|
|
3377
|
+
workflow_run_url: githubWorkflowRunUrl(),
|
|
3378
|
+
gate_result: {
|
|
3379
|
+
status: data.gate?.status,
|
|
3380
|
+
failures: data.gate?.failures ?? [],
|
|
3381
|
+
thresholds: data.gate?.thresholds ?? {},
|
|
3382
|
+
enforcement: data.gate?.enforcement
|
|
3383
|
+
},
|
|
3384
|
+
well_architected: data.gate?.wellArchitected ?? {},
|
|
3385
|
+
cost: data.gate?.cost ?? {},
|
|
3386
|
+
validation: data.gate?.validation ?? {},
|
|
3387
|
+
policy: data.gate?.validation?.policy ?? data.gate?.policy ?? {},
|
|
3388
|
+
architecture_signals: data.gate?.architecture ?? {},
|
|
3389
|
+
changed_files: data.changedFiles ?? []
|
|
3390
|
+
});
|
|
3391
|
+
var deterministicAiSummary = (data, error) => {
|
|
3392
|
+
const score = data.gate?.wellArchitected?.overall?.score ?? data.gate?.overallScore;
|
|
3393
|
+
const rating = scoreRating(score) ?? "UNKNOWN";
|
|
3394
|
+
const validation = data.gate?.validation ?? {};
|
|
3395
|
+
const cost = data.gate?.cost?.monthly ?? {};
|
|
3396
|
+
const failedTests = numberFrom(validation?.unitTests?.failed) ?? numberFrom(validation?.unit_tests?.failed) ?? numberFrom(validation?.failedUnitTests) ?? numberFrom(validation?.failed_tests) ?? 0;
|
|
3397
|
+
const policyFailed = numberFrom(validation?.policyChecks?.failed) ?? numberFrom(validation?.policy_checks?.failed) ?? numberFrom(data.gate?.policy?.failed) ?? 0;
|
|
3398
|
+
const policyStatus = policyFailed > 0 ? "has failed checks" : "GOOD";
|
|
3399
|
+
const summary = [
|
|
3400
|
+
`CloudEval review completed with ${String(data.gate?.status ?? "UNKNOWN").toUpperCase()}.`,
|
|
3401
|
+
`Well-Architected posture is ${formatScore(score)} (${rating}), validation has ${displayNumber(failedTests)} failed unit tests, policy checks are ${policyStatus}, and monthly cost is ${formatMonthlyMoney(cost?.amount, cost?.currency)}.`,
|
|
3402
|
+
"Prioritize failed validation checks and the weakest Well-Architected pillar first."
|
|
3403
|
+
].join(" ");
|
|
3376
3404
|
return {
|
|
3377
3405
|
enabled: true,
|
|
3378
|
-
status: "
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3406
|
+
status: "fallback",
|
|
3407
|
+
fallbackUsed: true,
|
|
3408
|
+
warnings: error ? [`Review summary endpoint failed: ${error}`] : [],
|
|
3409
|
+
shortSummary: summary,
|
|
3410
|
+
detailsMarkdown: [
|
|
3411
|
+
"**Main risk**\nCloudEval could not produce an AI-written review summary, so use the deterministic gate evidence.",
|
|
3412
|
+
"**Why it matters**\nFailed validation and weak architecture pillars are the highest-signal remediation inputs.",
|
|
3413
|
+
"**Recommended actions**\nFix failed validation checks, address the weakest pillar, rerun CloudEval review, and compare the updated gate.",
|
|
3414
|
+
"**Evidence used**\nGate status, Well-Architected score, validation totals, policy totals, and monthly cost."
|
|
3415
|
+
].join("\n\n"),
|
|
3416
|
+
markdown: renderAiSummarySections(
|
|
3417
|
+
summary,
|
|
3418
|
+
[
|
|
3419
|
+
"**Main risk**\nCloudEval could not produce an AI-written review summary, so use the deterministic gate evidence.",
|
|
3420
|
+
"**Why it matters**\nFailed validation and weak architecture pillars are the highest-signal remediation inputs.",
|
|
3421
|
+
"**Recommended actions**\nFix failed validation checks, address the weakest pillar, rerun CloudEval review, and compare the updated gate.",
|
|
3422
|
+
"**Evidence used**\nGate status, Well-Architected score, validation totals, policy totals, and monthly cost."
|
|
3423
|
+
].join("\n\n")
|
|
3424
|
+
)
|
|
3384
3425
|
};
|
|
3385
3426
|
};
|
|
3386
3427
|
var generateAiSummary = async (input) => {
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
enabled: true,
|
|
3402
|
-
status: "transient_error",
|
|
3403
|
-
mode: activeInput.mode,
|
|
3404
|
-
...activeInput.mode === "agent" ? { agentProfileId: activeInput.agentProfileId ?? "architecture" } : {},
|
|
3405
|
-
...activeInput.model ? { model: activeInput.model } : {},
|
|
3406
|
-
markdown: message,
|
|
3407
|
-
error: message
|
|
3408
|
-
};
|
|
3409
|
-
}
|
|
3410
|
-
result.attempts = attemptIndex + 1;
|
|
3411
|
-
if (fallbackFromMode) {
|
|
3412
|
-
result.fallbackFromMode = fallbackFromMode;
|
|
3413
|
-
}
|
|
3414
|
-
const normalizedSummary = typeof result.shortSummary === "string" || typeof result.detailsMarkdown === "string" ? {
|
|
3415
|
-
shortSummary: String(result.shortSummary ?? "").trim(),
|
|
3416
|
-
detailsMarkdown: String(result.detailsMarkdown ?? "").trim(),
|
|
3417
|
-
markdown: renderAiSummarySections(
|
|
3418
|
-
String(result.shortSummary ?? "").trim(),
|
|
3419
|
-
String(result.detailsMarkdown ?? "").trim()
|
|
3420
|
-
)
|
|
3421
|
-
} : normalizeAiSummarySections(result.markdown);
|
|
3422
|
-
result = { ...result, ...normalizedSummary };
|
|
3423
|
-
if (isTransientAiSummaryText(result.markdown)) {
|
|
3424
|
-
const normalizedError = normalizeAiSummaryMarkdown(result.error);
|
|
3425
|
-
if (normalizedError && !isTransientAiSummaryText(normalizedError)) {
|
|
3426
|
-
result = {
|
|
3427
|
-
...result,
|
|
3428
|
-
...normalizeAiSummarySections(normalizedError)
|
|
3429
|
-
};
|
|
3430
|
-
result.status = "ok";
|
|
3431
|
-
delete result.error;
|
|
3432
|
-
}
|
|
3433
|
-
}
|
|
3434
|
-
lastResult = result;
|
|
3435
|
-
if (!isTransientAiSummaryText(result.markdown)) {
|
|
3436
|
-
return result;
|
|
3437
|
-
}
|
|
3438
|
-
const retryDelay = retryDelays[attemptIndex];
|
|
3439
|
-
if (retryDelay === void 0) {
|
|
3440
|
-
break;
|
|
3441
|
-
}
|
|
3442
|
-
await sleep2(retryDelay);
|
|
3443
|
-
if (activeInput.mode === "agent") {
|
|
3444
|
-
fallbackFromMode = "agent";
|
|
3445
|
-
activeInput = {
|
|
3446
|
-
...input,
|
|
3447
|
-
mode: "ask",
|
|
3448
|
-
agentProfileId: void 0
|
|
3449
|
-
};
|
|
3428
|
+
try {
|
|
3429
|
+
const payload = buildReviewSummaryPayload(input.data);
|
|
3430
|
+
const response = await fetchCloudEvalJson({
|
|
3431
|
+
baseUrl: input.baseUrl,
|
|
3432
|
+
authToken: input.token,
|
|
3433
|
+
path: `/projects/${encodeURIComponent(String(input.data.projectId))}/review/summary`,
|
|
3434
|
+
method: "POST",
|
|
3435
|
+
body: payload,
|
|
3436
|
+
idempotencyKey: `cloudeval-review-summary-${input.data.projectId}-${input.data.commitSha ?? "head"}`
|
|
3437
|
+
});
|
|
3438
|
+
const shortSummary = String(response.summary ?? "").trim();
|
|
3439
|
+
const detailsMarkdown = String(response.details ?? "").trim();
|
|
3440
|
+
if (!shortSummary) {
|
|
3441
|
+
return deterministicAiSummary(input.data, "Review summary endpoint returned no summary.");
|
|
3450
3442
|
}
|
|
3443
|
+
return {
|
|
3444
|
+
enabled: true,
|
|
3445
|
+
status: response.fallback_used ? "fallback" : "ok",
|
|
3446
|
+
fallbackUsed: Boolean(response.fallback_used),
|
|
3447
|
+
warnings: Array.isArray(response.warnings) ? response.warnings : [],
|
|
3448
|
+
riskHighlights: Array.isArray(response.risk_highlights) ? response.risk_highlights : [],
|
|
3449
|
+
recommendedActions: Array.isArray(response.recommended_actions) ? response.recommended_actions : [],
|
|
3450
|
+
evidenceUsed: Array.isArray(response.evidence_used) ? response.evidence_used : [],
|
|
3451
|
+
shortSummary,
|
|
3452
|
+
detailsMarkdown,
|
|
3453
|
+
markdown: renderAiSummarySections(shortSummary, detailsMarkdown)
|
|
3454
|
+
};
|
|
3455
|
+
} catch (error) {
|
|
3456
|
+
return deterministicAiSummary(input.data, error?.message ?? "request failed");
|
|
3451
3457
|
}
|
|
3452
|
-
return {
|
|
3453
|
-
...lastResult ?? {},
|
|
3454
|
-
enabled: true,
|
|
3455
|
-
status: "unavailable",
|
|
3456
|
-
mode: activeInput.mode,
|
|
3457
|
-
...activeInput.mode === "agent" ? { agentProfileId: activeInput.agentProfileId ?? "architecture" } : {},
|
|
3458
|
-
...input.model ? { model: input.model } : {},
|
|
3459
|
-
...fallbackFromMode ? { fallbackFromMode } : {},
|
|
3460
|
-
attempts: lastResult?.attempts ?? retryDelays.length + 1,
|
|
3461
|
-
error: lastResult?.markdown || "AI summary unavailable",
|
|
3462
|
-
markdown: "AI summary unavailable: CloudEval AI was rate-limited. Retry the workflow or rerun `cloudeval review`."
|
|
3463
|
-
};
|
|
3464
3458
|
};
|
|
3465
3459
|
var buildMarkdownSummary = (data) => {
|
|
3466
3460
|
const gateStatus = String(data.gate?.status ?? "unknown").toUpperCase();
|
|
@@ -3470,7 +3464,8 @@ var buildMarkdownSummary = (data) => {
|
|
|
3470
3464
|
const architecture = data.gate?.architecture;
|
|
3471
3465
|
const projectLabel = String(data.project?.name ?? data.projectName ?? data.projectId);
|
|
3472
3466
|
const projectDisplay = markdownLink(projectLabel, data.project?.url ?? data.projectUrl);
|
|
3473
|
-
const
|
|
3467
|
+
const repository = String(data.repo ?? "unknown repository");
|
|
3468
|
+
const ref = String(data.ref ?? "unknown ref");
|
|
3474
3469
|
const commit = String(data.commitSha ?? "unknown").slice(0, 12);
|
|
3475
3470
|
const pillarLines = Array.isArray(data.gate?.wellArchitected?.pillars) ? data.gate.wellArchitected.pillars.map((pillar) => {
|
|
3476
3471
|
const rating = scoreRating(pillar.score);
|
|
@@ -3487,24 +3482,14 @@ var buildMarkdownSummary = (data) => {
|
|
|
3487
3482
|
cost?.currency
|
|
3488
3483
|
);
|
|
3489
3484
|
const positiveCostServices = costServices.filter((service) => service.amount > 0);
|
|
3490
|
-
const architectureLines =
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
`- Graph connectivity: **${trimNumber(density, 2)} relationships per resource**`
|
|
3499
|
-
);
|
|
3500
|
-
}
|
|
3501
|
-
const resourceCount = numberFrom(architecture?.resources);
|
|
3502
|
-
const resourceTypeCount = numberFrom(architecture?.resourceTypes);
|
|
3503
|
-
if (resourceCount !== void 0 && resourceTypeCount !== void 0) {
|
|
3504
|
-
architectureLines.push(
|
|
3505
|
-
`- Resource diversity: **${displayNumber(resourceTypeCount)} types across ${displayNumber(resourceCount)} resources**`
|
|
3506
|
-
);
|
|
3507
|
-
}
|
|
3485
|
+
const architectureLines = architectureSignalLines({
|
|
3486
|
+
architecture,
|
|
3487
|
+
costServices,
|
|
3488
|
+
costCurrency: cost?.currency,
|
|
3489
|
+
highRiskFindings: data.gate?.wellArchitected?.risks?.high,
|
|
3490
|
+
pillars: Array.isArray(data.gate?.wellArchitected?.pillars) ? data.gate.wellArchitected.pillars : []
|
|
3491
|
+
});
|
|
3492
|
+
const validationRows = validationFailureRows(validation);
|
|
3508
3493
|
const overallRating = scoreRating(score);
|
|
3509
3494
|
const lines = [
|
|
3510
3495
|
`${statusIcon(data.gate?.status)} **Overall** : ${gateStatus}`,
|
|
@@ -3512,9 +3497,13 @@ var buildMarkdownSummary = (data) => {
|
|
|
3512
3497
|
validationSummaryLine(validation),
|
|
3513
3498
|
policySummaryLine(validation),
|
|
3514
3499
|
costSummaryLine(cost),
|
|
3515
|
-
`**Cloudeval Project**: ${projectDisplay}`,
|
|
3516
3500
|
"",
|
|
3517
|
-
|
|
3501
|
+
"#### Source",
|
|
3502
|
+
"",
|
|
3503
|
+
`- **CloudEval project**: ${projectDisplay}`,
|
|
3504
|
+
`- **Repository**: \`${repository}\``,
|
|
3505
|
+
`- **Ref**: \`${ref}\``,
|
|
3506
|
+
`- **Commit**: \`${commit}\``
|
|
3518
3507
|
];
|
|
3519
3508
|
if (data.aiSummary?.markdown) {
|
|
3520
3509
|
lines.push("", "#### AI summary", "", data.aiSummary.markdown);
|
|
@@ -3581,9 +3570,15 @@ var buildMarkdownSummary = (data) => {
|
|
|
3581
3570
|
lines.push(
|
|
3582
3571
|
"",
|
|
3583
3572
|
"<details>",
|
|
3584
|
-
"
|
|
3573
|
+
`<summary>${validationRows.length ? "Validation failures" : "Validation details"}</summary>`,
|
|
3585
3574
|
"",
|
|
3586
3575
|
...validationDetailLines(validation),
|
|
3576
|
+
...validationRows.length ? [
|
|
3577
|
+
"",
|
|
3578
|
+
"| Type | Name | Location | Severity | Why / next step |",
|
|
3579
|
+
"| --- | --- | --- | --- | --- |",
|
|
3580
|
+
...validationRows
|
|
3581
|
+
] : [],
|
|
3587
3582
|
"",
|
|
3588
3583
|
"</details>"
|
|
3589
3584
|
);
|
|
@@ -3592,7 +3587,7 @@ var buildMarkdownSummary = (data) => {
|
|
|
3592
3587
|
lines.push(
|
|
3593
3588
|
"",
|
|
3594
3589
|
"<details>",
|
|
3595
|
-
"<summary>Architecture
|
|
3590
|
+
"<summary>Architecture signals</summary>",
|
|
3596
3591
|
"",
|
|
3597
3592
|
...architectureLines,
|
|
3598
3593
|
"",
|
|
@@ -15631,7 +15626,7 @@ program.command("tui").description("Open the CloudEval Terminal UI").option(
|
|
|
15631
15626
|
const { assertSecureBaseUrl } = await import("./dist-PEYJDO7A.js");
|
|
15632
15627
|
const [{ render }, { App }] = await Promise.all([
|
|
15633
15628
|
import("ink"),
|
|
15634
|
-
import("./App-
|
|
15629
|
+
import("./App-VSOTHLOD.js")
|
|
15635
15630
|
]);
|
|
15636
15631
|
const baseUrl = await resolveBaseUrl(options, command);
|
|
15637
15632
|
assertSecureBaseUrl(baseUrl);
|
|
@@ -15689,7 +15684,7 @@ program.command("chat").description("Start an interactive chat session").option(
|
|
|
15689
15684
|
const { assertSecureBaseUrl } = await import("./dist-PEYJDO7A.js");
|
|
15690
15685
|
const [{ render }, { App }] = await Promise.all([
|
|
15691
15686
|
import("ink"),
|
|
15692
|
-
import("./App-
|
|
15687
|
+
import("./App-VSOTHLOD.js")
|
|
15693
15688
|
]);
|
|
15694
15689
|
const baseUrl = await resolveBaseUrl(options, command);
|
|
15695
15690
|
assertSecureBaseUrl(baseUrl);
|
|
@@ -16443,7 +16438,7 @@ Error: ${errorMsg}
|
|
|
16443
16438
|
program.command("banner").description("Preview the startup banner and terminal capabilities").action(async () => {
|
|
16444
16439
|
const { render } = await import("ink");
|
|
16445
16440
|
const BannerPreview = React.lazy(async () => ({
|
|
16446
|
-
default: (await import("./Banner-
|
|
16441
|
+
default: (await import("./Banner-7XUOJYL5.js")).Banner
|
|
16447
16442
|
}));
|
|
16448
16443
|
render(
|
|
16449
16444
|
/* @__PURE__ */ jsx(React.Suspense, { fallback: null, children: /* @__PURE__ */ jsx(BannerPreview, { disable: false }) })
|
package/package.json
CHANGED
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.27.
|
|
17
|
+
"versionInfo": "0.27.2",
|
|
18
18
|
"downloadLocation": "https://github.com/ganakailabs/cloudeval-cli",
|
|
19
19
|
"filesAnalyzed": false,
|
|
20
20
|
"licenseConcluded": "LicenseRef-CloudEval-CLI",
|