@ganakailabs/cloudeval-cli 0.26.11 → 0.26.12

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/cli.js CHANGED
@@ -26,17 +26,20 @@ import {
26
26
  writeCliConfigValue
27
27
  } from "./chunk-QSBGUI25.js";
28
28
  import {
29
+ clearActiveCLITraceContext,
30
+ createCLITraceContext,
29
31
  getBundledAgentProfile,
30
32
  getBundledAgentProfiles,
31
33
  getCLIHeaders,
32
34
  isSensitiveSecretKey,
33
35
  normalizeApiBase,
34
36
  redactSensitiveSecrets,
35
- redactSensitiveText
36
- } from "./chunk-2OLI5VOG.js";
37
+ redactSensitiveText,
38
+ setActiveCLITraceContext
39
+ } from "./chunk-USSCB2ZU.js";
37
40
  import {
38
41
  CLI_VERSION
39
- } from "./chunk-Y5L2F7X3.js";
42
+ } from "./chunk-4AK6A5GF.js";
40
43
 
41
44
  // src/runtime/prepareInk.ts
42
45
  import fs from "fs";
@@ -1649,7 +1652,7 @@ var resolveReportProjectId = async ({
1649
1652
  if (!token) {
1650
1653
  throw new Error("No project specified. Use --project <id> for report access.");
1651
1654
  }
1652
- const resolvedWorkspace = workspace ?? await import("./dist-MQQKC6DZ.js").then((core) => ({
1655
+ const resolvedWorkspace = workspace ?? await import("./dist-PEYJDO7A.js").then((core) => ({
1653
1656
  checkUserStatus: core.checkUserStatus,
1654
1657
  getProjects: core.getProjects
1655
1658
  }));
@@ -1678,7 +1681,7 @@ var warnIfAccessKeyFromCliOption = (options, command) => {
1678
1681
  };
1679
1682
  var resolveAuthContext = async (options, command, deps) => {
1680
1683
  const baseUrl = await deps.resolveBaseUrl(options, command);
1681
- const core = await import("./dist-MQQKC6DZ.js");
1684
+ const core = await import("./dist-PEYJDO7A.js");
1682
1685
  core.assertSecureBaseUrl(baseUrl);
1683
1686
  warnIfAccessKeyFromCliOption(options, command);
1684
1687
  let accessKey = options.accessKey;
@@ -1764,7 +1767,7 @@ var resolveToken = async (options, baseUrl, deps, command) => {
1764
1767
  if (options.accessKey) {
1765
1768
  return options.accessKey;
1766
1769
  }
1767
- const { getAuthToken } = await import("./dist-MQQKC6DZ.js");
1770
+ const { getAuthToken } = await import("./dist-PEYJDO7A.js");
1768
1771
  try {
1769
1772
  return await getAuthToken({
1770
1773
  accessKey: options.accessKey,
@@ -1775,7 +1778,7 @@ var resolveToken = async (options, baseUrl, deps, command) => {
1775
1778
  if (!canLogin) {
1776
1779
  throw error;
1777
1780
  }
1778
- const { login } = await import("./dist-MQQKC6DZ.js");
1781
+ const { login } = await import("./dist-PEYJDO7A.js");
1779
1782
  process.stderr.write("Authentication required. Starting login flow...\n");
1780
1783
  const token = await login(baseUrl, {
1781
1784
  headless: Boolean(process.env.SSH_TTY || process.env.CLOUDEVAL_HEADLESS_LOGIN)
@@ -1941,7 +1944,7 @@ var registerReportsCommand = (program2, deps) => {
1941
1944
  token,
1942
1945
  requestedProjectId: options.project
1943
1946
  });
1944
- const core = await import("./dist-MQQKC6DZ.js");
1947
+ const core = await import("./dist-PEYJDO7A.js");
1945
1948
  const status = token ? await core.checkUserStatus(baseUrl, token) : void 0;
1946
1949
  const reports2 = await core.listReports({
1947
1950
  baseUrl,
@@ -1963,7 +1966,7 @@ var registerReportsCommand = (program2, deps) => {
1963
1966
  try {
1964
1967
  const baseUrl = await deps.resolveBaseUrl(options, command);
1965
1968
  const token = await resolveToken(options, baseUrl, deps, command);
1966
- const core = await import("./dist-MQQKC6DZ.js");
1969
+ const core = await import("./dist-PEYJDO7A.js");
1967
1970
  const status = token ? await core.checkUserStatus(baseUrl, token) : void 0;
1968
1971
  const projectId = await resolveReportProjectId({
1969
1972
  baseUrl,
@@ -2066,7 +2069,7 @@ var registerReportsCommand = (program2, deps) => {
2066
2069
  try {
2067
2070
  const baseUrl = await deps.resolveBaseUrl(options, command);
2068
2071
  const token = await resolveToken(options, baseUrl, deps, command);
2069
- const core = await import("./dist-MQQKC6DZ.js");
2072
+ const core = await import("./dist-PEYJDO7A.js");
2070
2073
  const status = token ? await core.checkUserStatus(baseUrl, token) : void 0;
2071
2074
  const projectId = await resolveReportProjectId({
2072
2075
  baseUrl,
@@ -2136,7 +2139,7 @@ var registerReportsCommand = (program2, deps) => {
2136
2139
  token,
2137
2140
  requestedProjectId: options.project
2138
2141
  });
2139
- const core = await import("./dist-MQQKC6DZ.js");
2142
+ const core = await import("./dist-PEYJDO7A.js");
2140
2143
  const status = token ? await core.checkUserStatus(baseUrl, token) : void 0;
2141
2144
  const report = await core.getWafReport({
2142
2145
  baseUrl,
@@ -2175,7 +2178,7 @@ var registerReportsCommand = (program2, deps) => {
2175
2178
  token,
2176
2179
  requestedProjectId: options.project
2177
2180
  });
2178
- const core = await import("./dist-MQQKC6DZ.js");
2181
+ const core = await import("./dist-PEYJDO7A.js");
2179
2182
  const status = token ? await core.checkUserStatus(baseUrl, token) : void 0;
2180
2183
  const report = await core.getReport({
2181
2184
  baseUrl,
@@ -2203,7 +2206,7 @@ var registerReportsCommand = (program2, deps) => {
2203
2206
  token,
2204
2207
  requestedProjectId: options.project
2205
2208
  });
2206
- const core = await import("./dist-MQQKC6DZ.js");
2209
+ const core = await import("./dist-PEYJDO7A.js");
2207
2210
  const status = token ? await core.checkUserStatus(baseUrl, token) : void 0;
2208
2211
  const report = await core.getCostReport({
2209
2212
  baseUrl,
@@ -2232,7 +2235,7 @@ var registerReportsCommand = (program2, deps) => {
2232
2235
  token,
2233
2236
  requestedProjectId: options.project
2234
2237
  });
2235
- const core = await import("./dist-MQQKC6DZ.js");
2238
+ const core = await import("./dist-PEYJDO7A.js");
2236
2239
  const status = token ? await core.checkUserStatus(baseUrl, token) : void 0;
2237
2240
  const report = await core.getWafReport({
2238
2241
  baseUrl,
@@ -2493,11 +2496,13 @@ var reviewReportStatus = (report) => ({
2493
2496
  var reviewReportStatuses = ({
2494
2497
  cost,
2495
2498
  waf,
2496
- preload
2499
+ preload,
2500
+ graph
2497
2501
  }) => ({
2498
2502
  cost: reviewReportStatus(cost),
2499
2503
  wellArchitected: reviewReportStatus(waf),
2500
- preload: reviewReportStatus(preload)
2504
+ preload: reviewReportStatus(preload),
2505
+ graph: reviewReportStatus(graph)
2501
2506
  });
2502
2507
  var publicJobStatus = (value) => {
2503
2508
  const record = firstRecord(value);
@@ -2534,18 +2539,198 @@ var formatMoney = (amount, currency, fallback = "not available") => {
2534
2539
  }
2535
2540
  return currency ? `${numericAmount} ${currency}` : String(numericAmount);
2536
2541
  };
2537
- var formatValidation = (validation) => {
2538
- const policyFailed = displayNumber(validation?.policyChecks?.failed);
2539
- const unitFailed = displayNumber(validation?.unitTests?.failed);
2540
- return `Policy checks ${policyFailed} failed, unit tests ${unitFailed} failed`;
2542
+ var trimNumber = (value, fractionDigits = 2) => Number.isInteger(value) ? String(value) : String(Number(value.toFixed(fractionDigits)));
2543
+ var formatScore = (value, fallback = "unknown") => {
2544
+ const numericValue = numberFrom(value);
2545
+ return numericValue === void 0 ? fallback : `${trimNumber(numericValue)}/100`;
2546
+ };
2547
+ var scoreRating = (value) => {
2548
+ const numericValue = numberFrom(value);
2549
+ if (numericValue === void 0) {
2550
+ return void 0;
2551
+ }
2552
+ if (numericValue >= 90) {
2553
+ return "EXCELLENT";
2554
+ }
2555
+ if (numericValue >= 75) {
2556
+ return "GOOD";
2557
+ }
2558
+ if (numericValue >= 50) {
2559
+ return "FAIR";
2560
+ }
2561
+ if (numericValue >= 30) {
2562
+ return "POOR";
2563
+ }
2564
+ return "CRITICAL";
2541
2565
  };
2542
- var compactValidation = (validation) => {
2566
+ var scoreRatingIcon = (rating) => {
2567
+ switch (rating) {
2568
+ case "EXCELLENT":
2569
+ return "\u{1F7E2}";
2570
+ case "GOOD":
2571
+ return "\u{1F535}";
2572
+ case "FAIR":
2573
+ return "\u{1F7E1}";
2574
+ case "POOR":
2575
+ return "\u{1F7E0}";
2576
+ case "CRITICAL":
2577
+ return "\u{1F534}";
2578
+ default:
2579
+ return "\u26AA";
2580
+ }
2581
+ };
2582
+ var formatMonthlyMoney = (amount, currency, fallback = "not available") => {
2583
+ const value = formatMoney(amount, currency, fallback);
2584
+ return value === fallback ? value : `${value}/mo`;
2585
+ };
2586
+ var compactBudgetLabel = (amount, currency) => {
2587
+ if (amount === void 0 || !Number.isFinite(amount)) {
2588
+ return void 0;
2589
+ }
2590
+ if (Math.abs(amount) >= 1e6) {
2591
+ return `${trimNumber(amount / 1e6, 1)}M`;
2592
+ }
2593
+ if (Math.abs(amount) >= 1e3) {
2594
+ return `${trimNumber(amount / 1e3, 1)}K`;
2595
+ }
2596
+ return formatMonthlyMoney(amount, currency);
2597
+ };
2598
+ var costSummaryLine = (cost) => {
2599
+ const amount = numberFrom(cost?.amount);
2600
+ if (amount === void 0) {
2601
+ return "\u26AA Cost: not available";
2602
+ }
2603
+ const formattedCost = formatMonthlyMoney(amount, cost?.currency);
2604
+ const threshold = numberFrom(cost?.threshold);
2605
+ if (threshold === void 0) {
2606
+ return `\u26AA Cost: ${formattedCost} (not gated)`;
2607
+ }
2608
+ const budget = compactBudgetLabel(threshold, cost?.currency) ?? "configured";
2609
+ return String(cost?.status ?? "").toLowerCase() === "fail" ? `\u{1F534} Cost: ${formattedCost} (over ${budget} budget)` : `\u{1F7E2} Cost: ${formattedCost} (under ${budget} budget)`;
2610
+ };
2611
+ var statusIcon = (status) => {
2612
+ switch (String(status ?? "").toLowerCase()) {
2613
+ case "pass":
2614
+ case "passed":
2615
+ case "success":
2616
+ case "succeeded":
2617
+ return "\u{1F7E2}";
2618
+ case "warn":
2619
+ case "warning":
2620
+ return "\u{1F7E1}";
2621
+ case "fail":
2622
+ case "failed":
2623
+ case "error":
2624
+ return "\u{1F534}";
2625
+ default:
2626
+ return "\u26AA";
2627
+ }
2628
+ };
2629
+ var formatValidation = (validation) => {
2543
2630
  const policyFailed = numberFrom(validation?.policyChecks?.failed);
2544
2631
  const unitFailed = numberFrom(validation?.unitTests?.failed);
2545
2632
  if (policyFailed === 0 && unitFailed === 0) {
2546
- return "validation clean";
2633
+ return "Validation clean";
2634
+ }
2635
+ const parts = [];
2636
+ if (unitFailed !== void 0) {
2637
+ parts.push(unitFailed === 0 ? "unit tests clean" : `${unitFailed} unit tests failed`);
2638
+ }
2639
+ if (policyFailed !== void 0) {
2640
+ parts.push(policyFailed === 0 ? "policy checks clean" : `${policyFailed} policy checks failed`);
2641
+ }
2642
+ return parts.length ? parts.join(", ") : "Validation not available";
2643
+ };
2644
+ var validationSummaryLine = (validation) => {
2645
+ const unitFailed = numberFrom(validation?.unitTests?.failed);
2646
+ if (unitFailed === void 0) {
2647
+ return "\u26AA Validation: not available";
2648
+ }
2649
+ return unitFailed > 0 ? `\u{1F534} Validation: ${unitFailed} unit tests failed` : "\u{1F7E2} Validation: GOOD";
2650
+ };
2651
+ var policySummaryLine = (validation) => {
2652
+ const policyFailed = numberFrom(validation?.policyChecks?.failed);
2653
+ if (policyFailed === void 0) {
2654
+ return "\u26AA Policy checks: not available";
2655
+ }
2656
+ return policyFailed > 0 ? `\u{1F534} Policy checks: ${policyFailed} failed` : "\u{1F7E2} Policy checks: GOOD";
2657
+ };
2658
+ var validationDetailLines = (validation) => {
2659
+ if (!validation) {
2660
+ return ["- Validation data was not available."];
2661
+ }
2662
+ const lines = [];
2663
+ const unitTotal = numberFrom(validation.unitTests?.total);
2664
+ const unitPassed = numberFrom(validation.unitTests?.passed);
2665
+ const unitFailed = numberFrom(validation.unitTests?.failed);
2666
+ if (unitTotal !== void 0 || unitPassed !== void 0 || unitFailed !== void 0) {
2667
+ const parts = [];
2668
+ if (unitPassed !== void 0) parts.push(`**${unitPassed} passed**`);
2669
+ if (unitFailed !== void 0) parts.push(`**${unitFailed} failed**`);
2670
+ if (unitTotal !== void 0) parts.push(`${unitTotal} total`);
2671
+ lines.push(`- Unit tests: ${parts.join(", ")}`);
2672
+ }
2673
+ const policyTotal = numberFrom(validation.policyChecks?.total);
2674
+ const policyPassed = numberFrom(validation.policyChecks?.passed);
2675
+ const policyFailed = numberFrom(validation.policyChecks?.failed);
2676
+ if (policyTotal !== void 0 || policyPassed !== void 0 || policyFailed !== void 0) {
2677
+ const parts = [];
2678
+ if (policyPassed !== void 0) parts.push(`**${policyPassed} passed**`);
2679
+ if (policyFailed !== void 0) parts.push(`**${policyFailed} failed**`);
2680
+ if (policyTotal !== void 0) parts.push(`${policyTotal} total`);
2681
+ lines.push(`- Policy checks: ${parts.join(", ")}`);
2682
+ }
2683
+ return lines.length ? lines : ["- Validation data was not available."];
2684
+ };
2685
+ var namedAmount = (record) => numberFrom(
2686
+ record.amount,
2687
+ record.monthly_cost,
2688
+ record.monthlyCost,
2689
+ record.cost,
2690
+ record.value
2691
+ );
2692
+ var namedLabel = (record, fallback) => String(record.name ?? record.service ?? record.label ?? record.category ?? fallback);
2693
+ var mermaidLabel = (value) => value.replace(/"/g, "'");
2694
+ var costServiceRows = (services, currency) => (Array.isArray(services) ? services : []).map((service, index) => {
2695
+ const record = asRecord(service);
2696
+ const amount = namedAmount(record);
2697
+ if (amount === void 0) {
2698
+ return void 0;
2699
+ }
2700
+ const rowCurrency = String(record.currency ?? currency ?? "") || void 0;
2701
+ return {
2702
+ name: namedLabel(record, `Service ${index + 1}`),
2703
+ amount,
2704
+ ...rowCurrency ? { currency: rowCurrency } : {}
2705
+ };
2706
+ }).filter((service) => service !== void 0);
2707
+ var reconcileCostServiceRows = (services, totalAmount, currency) => {
2708
+ const total = numberFrom(totalAmount);
2709
+ if (total === void 0 || services.length === 0) {
2710
+ return services;
2711
+ }
2712
+ const serviceSum = services.reduce((sum, service) => sum + service.amount, 0);
2713
+ if (serviceSum > total + 1e-3) {
2714
+ return [
2715
+ {
2716
+ name: "Reported total",
2717
+ amount: total,
2718
+ ...currency ? { currency } : {}
2719
+ }
2720
+ ];
2547
2721
  }
2548
- return formatValidation(validation);
2722
+ const delta = Number((total - serviceSum).toFixed(3));
2723
+ if (delta > 1e-3) {
2724
+ return [
2725
+ ...services,
2726
+ {
2727
+ name: "Other",
2728
+ amount: delta,
2729
+ ...currency ? { currency } : {}
2730
+ }
2731
+ ];
2732
+ }
2733
+ return services;
2549
2734
  };
2550
2735
  var markdownLink = (label, url) => url ? `[${label}](${url})` : label;
2551
2736
  var extractPillars = (waf) => {
@@ -2615,11 +2800,65 @@ var extractValidation = ({
2615
2800
  }
2616
2801
  };
2617
2802
  };
2803
+ var extractArchitectureInsights = ({
2804
+ waf,
2805
+ preload,
2806
+ graph,
2807
+ project
2808
+ }) => {
2809
+ const graphNodes = Array.isArray(graph?.nodes) ? graph.nodes : [];
2810
+ const graphEdges = Array.isArray(graph?.edges) ? graph.edges : [];
2811
+ const graphResourceTypes = new Set(
2812
+ graphNodes.map((node) => asRecord(node).type).filter((type) => typeof type === "string" && type.trim().length > 0)
2813
+ );
2814
+ const metrics = firstRecord(
2815
+ preload?.reports?.architecture?.metrics,
2816
+ preload?.latest_payloads?.architecture?.summary,
2817
+ waf?.architecture,
2818
+ waf?.parsed?.architecture,
2819
+ project?.architecture,
2820
+ project?.graph
2821
+ );
2822
+ const resources = numberFrom(
2823
+ metrics?.resource_count,
2824
+ metrics?.resourceCount,
2825
+ metrics?.resources,
2826
+ metrics?.node_count,
2827
+ metrics?.nodeCount,
2828
+ graphNodes.length || void 0
2829
+ );
2830
+ const relationships = numberFrom(
2831
+ metrics?.relationship_count,
2832
+ metrics?.relationshipCount,
2833
+ metrics?.relationships,
2834
+ metrics?.edge_count,
2835
+ metrics?.edgeCount,
2836
+ graphEdges.length || void 0
2837
+ );
2838
+ const resourceTypes = numberFrom(
2839
+ metrics?.resource_type_count,
2840
+ metrics?.resourceTypeCount,
2841
+ metrics?.types,
2842
+ metrics?.resource_types,
2843
+ metrics?.resourceTypes,
2844
+ graphResourceTypes.size || void 0
2845
+ );
2846
+ if (resources === void 0 && relationships === void 0 && resourceTypes === void 0) {
2847
+ return void 0;
2848
+ }
2849
+ return {
2850
+ resources,
2851
+ relationships,
2852
+ resourceTypes,
2853
+ relationshipDensity: resources !== void 0 && resources > 0 && relationships !== void 0 ? relationships / resources : void 0
2854
+ };
2855
+ };
2618
2856
  var evaluateGate = ({
2619
2857
  configText,
2620
2858
  waf,
2621
2859
  cost,
2622
2860
  preload,
2861
+ graph,
2623
2862
  project
2624
2863
  }) => {
2625
2864
  const gateConfig = parseGateConfig(configText);
@@ -2672,6 +2911,7 @@ var evaluateGate = ({
2672
2911
  };
2673
2912
  });
2674
2913
  const validation = extractValidation({ waf, preload, project });
2914
+ const architecture = extractArchitectureInsights({ waf, preload, graph, project });
2675
2915
  const wellArchitected = {
2676
2916
  overall: {
2677
2917
  score: overallScore,
@@ -2710,7 +2950,8 @@ var evaluateGate = ({
2710
2950
  monthlyCost,
2711
2951
  wellArchitected,
2712
2952
  cost: costSummary,
2713
- validation
2953
+ validation,
2954
+ architecture
2714
2955
  };
2715
2956
  }
2716
2957
  const failures = [];
@@ -2749,7 +2990,8 @@ var evaluateGate = ({
2749
2990
  monthlyCost,
2750
2991
  wellArchitected,
2751
2992
  cost: costSummary,
2752
- validation
2993
+ validation,
2994
+ architecture
2753
2995
  };
2754
2996
  };
2755
2997
  var safeFetch = async (input) => {
@@ -2865,7 +3107,7 @@ var fetchReviewReports = async ({
2865
3107
  projectId,
2866
3108
  userId
2867
3109
  }) => {
2868
- const [cost, waf, preload] = await Promise.all([
3110
+ const [cost, waf, preload, graph] = await Promise.all([
2869
3111
  safeFetch({
2870
3112
  baseUrl,
2871
3113
  authToken: token,
@@ -2880,9 +3122,14 @@ var fetchReviewReports = async ({
2880
3122
  baseUrl,
2881
3123
  authToken: token,
2882
3124
  path: `/reports/preload/${encodeURIComponent(projectId)}?user_id=${encodeURIComponent(userId)}&include_payload=true`
3125
+ }) : Promise.resolve(void 0),
3126
+ userId ? safeFetch({
3127
+ baseUrl,
3128
+ authToken: token,
3129
+ path: `/projects/${encodeURIComponent(projectId)}/graph?user_id=${encodeURIComponent(userId)}`
2883
3130
  }) : Promise.resolve(void 0)
2884
3131
  ]);
2885
- return { cost, waf, preload };
3132
+ return { cost, waf, preload, graph };
2886
3133
  };
2887
3134
  var waitForReviewReports = async ({
2888
3135
  baseUrl,
@@ -2906,8 +3153,11 @@ var waitForReviewReports = async ({
2906
3153
  };
2907
3154
  var buildAiSummaryPrompt = (data) => [
2908
3155
  "Write a concise CloudEval pull request review summary in Markdown.",
2909
- "Focus on gate status, Well-Architected posture, cost posture, and security/operational risks.",
2910
- "Keep it under 160 words. Do not invent facts not present below.",
3156
+ "Return exactly two sections: Short Summary and Details.",
3157
+ "Short Summary: one dense paragraph under 45 words with gate status, Well-Architected posture, validation, and cost.",
3158
+ "Details: short bullets with bold labels only when useful, such as **Key risks:**, **Cost posture:**, and **Recommended next step:**.",
3159
+ "Keep the full response under 180 words. Do not invent facts not present below.",
3160
+ "Do not include citations, source markers, hidden tool ids, or HTML comments.",
2911
3161
  "",
2912
3162
  `Project: ${data.projectId}`,
2913
3163
  `Repository: ${data.repo ?? "unknown"}`,
@@ -2924,10 +3174,81 @@ var isTransientAiSummaryText = (text) => {
2924
3174
  if (!text?.trim()) {
2925
3175
  return false;
2926
3176
  }
2927
- return /too many requests|rate[- ]?limit|try again in a moment|temporarily unavailable/i.test(
3177
+ 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(
2928
3178
  text
2929
3179
  );
2930
3180
  };
3181
+ var normalizeAiSummaryMarkdown = (text) => {
3182
+ return normalizeAiSummarySections(text).markdown;
3183
+ };
3184
+ var normalizeAiSummarySections = (text) => {
3185
+ const trimmed = String(text ?? "").trim();
3186
+ if (!trimmed) {
3187
+ return { shortSummary: "", detailsMarkdown: "", markdown: "" };
3188
+ }
3189
+ const withNewlines = sanitizeAiSummaryMarkdown(trimmed.replace(/\\n/g, "\n"));
3190
+ const requestMatch = /\bRequest:\s*/i.exec(withNewlines);
3191
+ const sourceText = requestMatch ? withNewlines.slice(requestMatch.index + requestMatch[0].length).split(/\n\s*\nThe request reached\b/i)[0].trim() || withNewlines : withNewlines;
3192
+ const sections = splitAiSummarySections(sourceText);
3193
+ return {
3194
+ ...sections,
3195
+ markdown: renderAiSummarySections(sections.shortSummary, sections.detailsMarkdown)
3196
+ };
3197
+ };
3198
+ var sanitizeAiSummaryMarkdown = (text) => text.replace(/<!--[\s\S]*?-->/g, "").replace(/\s*\[S_[A-Za-z0-9_:-]+\]/g, "").replace(/\n{3,}/g, "\n\n").trim();
3199
+ 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();
3200
+ var normalizeAiDetailHeadings = (text) => text.split("\n").map((line) => {
3201
+ const cleaned = line.replace(/^\s*#{1,6}\s*/, "").replace(/^\s*[-*]\s+/, "").trimEnd();
3202
+ 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);
3203
+ if (!labelMatch) {
3204
+ return cleaned;
3205
+ }
3206
+ return `- **${labelMatch[1]}:** ${labelMatch[2]}`.trimEnd();
3207
+ }).join("\n").trim();
3208
+ var splitAiSummarySections = (text) => {
3209
+ const cleaned = sanitizeAiSummaryMarkdown(text).replace(/^\s*#{1,6}\s*AI summary\s*$/gim, "").trim();
3210
+ const shortMatch = /\bShort Summary\s*:\s*/i.exec(cleaned);
3211
+ const detailsMatch = /\bDetails\s*:\s*/i.exec(cleaned);
3212
+ if (shortMatch && detailsMatch && shortMatch.index < detailsMatch.index) {
3213
+ const shortSummary2 = stripAiSectionLabel(
3214
+ cleaned.slice(shortMatch.index, detailsMatch.index).trim(),
3215
+ "Short Summary"
3216
+ );
3217
+ const detailsMarkdown2 = normalizeAiDetailHeadings(
3218
+ stripAiSectionLabel(cleaned.slice(detailsMatch.index).trim(), "Details")
3219
+ );
3220
+ return { shortSummary: shortSummary2, detailsMarkdown: detailsMarkdown2 };
3221
+ }
3222
+ const paragraphs = cleaned.split(/\n\s*\n/).map((paragraph) => paragraph.trim()).filter(Boolean);
3223
+ const shortSummary = stripAiSectionLabel(paragraphs[0] ?? cleaned, "Short Summary");
3224
+ const detailsMarkdown = normalizeAiDetailHeadings(paragraphs.slice(1).join("\n\n"));
3225
+ return { shortSummary, detailsMarkdown };
3226
+ };
3227
+ var renderAiSummarySections = (shortSummary, detailsMarkdown) => {
3228
+ const lines = [`**Short summary:** ${shortSummary.trim()}`];
3229
+ if (detailsMarkdown.trim()) {
3230
+ lines.push(
3231
+ "",
3232
+ "<details>",
3233
+ "<summary>AI details</summary>",
3234
+ "",
3235
+ detailsMarkdown.trim(),
3236
+ "",
3237
+ "</details>"
3238
+ );
3239
+ }
3240
+ return lines.join("\n");
3241
+ };
3242
+ var aiSummaryAttemptTimeoutMs = () => {
3243
+ const raw = process.env.CLOUDEVAL_REVIEW_AI_ATTEMPT_TIMEOUT_MS;
3244
+ if (raw?.trim()) {
3245
+ const parsed = Number.parseInt(raw.trim(), 10);
3246
+ if (Number.isFinite(parsed) && parsed > 0) {
3247
+ return parsed;
3248
+ }
3249
+ }
3250
+ return 18e4;
3251
+ };
2931
3252
  var aiSummaryRetryDelaysMs = () => {
2932
3253
  const raw = process.env.CLOUDEVAL_REVIEW_AI_RETRY_DELAYS_MS;
2933
3254
  if (raw?.trim()) {
@@ -2945,11 +3266,23 @@ var generateAiSummaryAttempt = async ({
2945
3266
  agentProfileId,
2946
3267
  data
2947
3268
  }) => {
2948
- const core = await import("./dist-MQQKC6DZ.js");
3269
+ const core = await import("./dist-PEYJDO7A.js");
2949
3270
  const threadId = `review-${data.projectId}-${Date.now()}`;
2950
3271
  let markdown = "";
2951
3272
  let chatState = { ...core.initialChatState, threadId };
2952
- for await (const chunk of core.streamChat({
3273
+ const attemptTimeoutMs = aiSummaryAttemptTimeoutMs();
3274
+ let timedOut = false;
3275
+ let timeoutId;
3276
+ const timeoutPromise = new Promise((_, reject) => {
3277
+ timeoutId = setTimeout(() => {
3278
+ timedOut = true;
3279
+ reject(
3280
+ new Error(`AI summary did not complete within ${attemptTimeoutMs}ms.`)
3281
+ );
3282
+ }, attemptTimeoutMs);
3283
+ timeoutId.unref?.();
3284
+ });
3285
+ const iterator = core.streamChat({
2953
3286
  baseUrl,
2954
3287
  authToken: token,
2955
3288
  message: buildAiSummaryPrompt(data),
@@ -2977,35 +3310,94 @@ var generateAiSummaryAttempt = async ({
2977
3310
  completeAfterResponse: true,
2978
3311
  responseCompletionGraceMs: 250,
2979
3312
  streamIdleTimeoutMs: 12e4
2980
- })) {
2981
- chatState = core.reduceChunk(chatState, chunk);
2982
- const latestMessage = [...chatState.messages ?? []].reverse().find((message) => message.role === "assistant");
2983
- const chunkAssistantMessage = Array.isArray(chunk?.messages) ? [...chunk.messages].reverse().find((message) => message?.role === "assistant" && typeof message?.content === "string")?.content : void 0;
2984
- const content = chunk?.content;
2985
- if (typeof chunkAssistantMessage === "string" && chunkAssistantMessage.trim()) {
2986
- markdown = chunkAssistantMessage;
3313
+ });
3314
+ try {
3315
+ while (true) {
3316
+ const next = await Promise.race([iterator.next(), timeoutPromise]);
3317
+ if (next.done) {
3318
+ break;
3319
+ }
3320
+ const chunk = next.value;
3321
+ chatState = core.reduceChunk(chatState, chunk);
3322
+ const latestMessage = [...chatState.messages ?? []].reverse().find((message) => message.role === "assistant");
3323
+ const chunkAssistantMessage = Array.isArray(chunk?.messages) ? [...chunk.messages].reverse().find((message) => message?.role === "assistant" && typeof message?.content === "string")?.content : void 0;
3324
+ const content = chunk?.content;
3325
+ if (typeof chunkAssistantMessage === "string" && chunkAssistantMessage.trim()) {
3326
+ markdown = chunkAssistantMessage;
3327
+ }
3328
+ if (chunk.type === "responding" && typeof content === "string") {
3329
+ markdown = latestMessage?.content || `${markdown}${content}`;
3330
+ }
2987
3331
  }
2988
- if (chunk.type === "responding" && typeof content === "string") {
2989
- markdown = latestMessage?.content || `${markdown}${content}`;
3332
+ } finally {
3333
+ if (timeoutId) {
3334
+ clearTimeout(timeoutId);
3335
+ }
3336
+ if (timedOut) {
3337
+ await iterator.return?.(void 0).catch(() => void 0);
2990
3338
  }
2991
3339
  }
2992
3340
  const finalMessage = [...chatState.messages ?? []].reverse().find((message) => message.role === "assistant");
3341
+ const rawMarkdown = String(finalMessage?.content || markdown).trim();
3342
+ const normalized = normalizeAiSummarySections(rawMarkdown);
2993
3343
  return {
2994
3344
  enabled: true,
2995
3345
  status: "ok",
2996
3346
  mode,
2997
3347
  ...mode === "agent" ? { agentProfileId: agentProfileId ?? "architecture" } : {},
2998
3348
  ...model ? { model } : {},
2999
- markdown: String(finalMessage?.content || markdown).trim(),
3349
+ ...normalized,
3000
3350
  threadId
3001
3351
  };
3002
3352
  };
3003
3353
  var generateAiSummary = async (input) => {
3004
3354
  const retryDelays = aiSummaryRetryDelaysMs();
3005
3355
  let lastResult;
3356
+ let activeInput = input;
3357
+ let fallbackFromMode;
3006
3358
  for (let attemptIndex = 0; attemptIndex <= retryDelays.length; attemptIndex += 1) {
3007
- const result = await generateAiSummaryAttempt(input);
3359
+ let result;
3360
+ try {
3361
+ result = await generateAiSummaryAttempt(activeInput);
3362
+ } catch (error) {
3363
+ const message = error?.message ?? "AI summary failed";
3364
+ if (!isTransientAiSummaryText(message)) {
3365
+ throw error;
3366
+ }
3367
+ result = {
3368
+ enabled: true,
3369
+ status: "transient_error",
3370
+ mode: activeInput.mode,
3371
+ ...activeInput.mode === "agent" ? { agentProfileId: activeInput.agentProfileId ?? "architecture" } : {},
3372
+ ...activeInput.model ? { model: activeInput.model } : {},
3373
+ markdown: message,
3374
+ error: message
3375
+ };
3376
+ }
3008
3377
  result.attempts = attemptIndex + 1;
3378
+ if (fallbackFromMode) {
3379
+ result.fallbackFromMode = fallbackFromMode;
3380
+ }
3381
+ const normalizedSummary = typeof result.shortSummary === "string" || typeof result.detailsMarkdown === "string" ? {
3382
+ shortSummary: String(result.shortSummary ?? "").trim(),
3383
+ detailsMarkdown: String(result.detailsMarkdown ?? "").trim(),
3384
+ markdown: renderAiSummarySections(
3385
+ String(result.shortSummary ?? "").trim(),
3386
+ String(result.detailsMarkdown ?? "").trim()
3387
+ )
3388
+ } : normalizeAiSummarySections(result.markdown);
3389
+ result = { ...result, ...normalizedSummary };
3390
+ if (isTransientAiSummaryText(result.markdown)) {
3391
+ const normalizedError = normalizeAiSummaryMarkdown(result.error);
3392
+ if (normalizedError && !isTransientAiSummaryText(normalizedError)) {
3393
+ result = {
3394
+ ...result,
3395
+ ...normalizeAiSummarySections(normalizedError)
3396
+ };
3397
+ result.status = "ok";
3398
+ delete result.error;
3399
+ }
3400
+ }
3009
3401
  lastResult = result;
3010
3402
  if (!isTransientAiSummaryText(result.markdown)) {
3011
3403
  return result;
@@ -3015,14 +3407,23 @@ var generateAiSummary = async (input) => {
3015
3407
  break;
3016
3408
  }
3017
3409
  await sleep2(retryDelay);
3410
+ if (activeInput.mode === "agent") {
3411
+ fallbackFromMode = "agent";
3412
+ activeInput = {
3413
+ ...input,
3414
+ mode: "ask",
3415
+ agentProfileId: void 0
3416
+ };
3417
+ }
3018
3418
  }
3019
3419
  return {
3020
3420
  ...lastResult ?? {},
3021
3421
  enabled: true,
3022
3422
  status: "unavailable",
3023
- mode: input.mode,
3024
- ...input.mode === "agent" ? { agentProfileId: input.agentProfileId ?? "architecture" } : {},
3423
+ mode: activeInput.mode,
3424
+ ...activeInput.mode === "agent" ? { agentProfileId: activeInput.agentProfileId ?? "architecture" } : {},
3025
3425
  ...input.model ? { model: input.model } : {},
3426
+ ...fallbackFromMode ? { fallbackFromMode } : {},
3026
3427
  attempts: lastResult?.attempts ?? retryDelays.length + 1,
3027
3428
  error: lastResult?.markdown || "AI summary unavailable",
3028
3429
  markdown: "AI summary unavailable: CloudEval AI was rate-limited. Retry the workflow or rerun `cloudeval review`."
@@ -3030,18 +3431,55 @@ var generateAiSummary = async (input) => {
3030
3431
  };
3031
3432
  var buildMarkdownSummary = (data) => {
3032
3433
  const gateStatus = String(data.gate?.status ?? "unknown").toUpperCase();
3033
- const score = data.gate?.overallScore ?? "unknown";
3434
+ const score = data.gate?.overallScore ?? data.gate?.wellArchitected?.overall?.score;
3034
3435
  const cost = data.gate?.cost?.monthly;
3035
3436
  const validation = data.gate?.validation;
3437
+ const architecture = data.gate?.architecture;
3036
3438
  const projectLabel = String(data.project?.name ?? data.projectName ?? data.projectId);
3037
3439
  const projectDisplay = markdownLink(projectLabel, data.project?.url ?? data.projectUrl);
3038
3440
  const source = data.repo ? `${data.repo}${data.ref ? ` @ ${data.ref}` : ""}` : data.ref ?? "unknown source";
3039
3441
  const commit = String(data.commitSha ?? "unknown").slice(0, 12);
3040
- const pillarLines = Array.isArray(data.gate?.wellArchitected?.pillars) ? data.gate.wellArchitected.pillars.map(
3041
- (pillar) => `- ${pillar.label}: ${pillar.score} - ${String(pillar.status ?? "unknown").toUpperCase()}`
3042
- ) : [];
3442
+ const pillarLines = Array.isArray(data.gate?.wellArchitected?.pillars) ? data.gate.wellArchitected.pillars.map((pillar) => {
3443
+ const rating = scoreRating(pillar.score);
3444
+ return `| ${pillar.label} | **${formatScore(pillar.score)}** | ${scoreRatingIcon(rating)} ${rating ?? "UNKNOWN"} |`;
3445
+ }) : [];
3446
+ const riskLines = [
3447
+ ["High-risk findings", data.gate?.wellArchitected?.risks?.high],
3448
+ ["Medium-risk findings", data.gate?.wellArchitected?.risks?.medium],
3449
+ ["Critical findings", data.gate?.wellArchitected?.risks?.critical]
3450
+ ].filter(([, value]) => numberFrom(value) !== void 0).map(([label, value]) => `- ${label}: **${displayNumber(value)}**`);
3451
+ const costServices = reconcileCostServiceRows(
3452
+ costServiceRows(data.gate?.cost?.topServices, cost?.currency),
3453
+ cost?.amount,
3454
+ cost?.currency
3455
+ );
3456
+ const positiveCostServices = costServices.filter((service) => service.amount > 0);
3457
+ const architectureLines = [
3458
+ ["Resources", architecture?.resources],
3459
+ ["Relationships", architecture?.relationships],
3460
+ ["Resource types", architecture?.resourceTypes]
3461
+ ].filter(([, value]) => numberFrom(value) !== void 0).map(([label, value]) => `- ${label}: **${displayNumber(value)}**`);
3462
+ const density = numberFrom(architecture?.relationshipDensity);
3463
+ if (density !== void 0) {
3464
+ architectureLines.push(
3465
+ `- Graph connectivity: **${trimNumber(density, 2)} relationships per resource**`
3466
+ );
3467
+ }
3468
+ const resourceCount = numberFrom(architecture?.resources);
3469
+ const resourceTypeCount = numberFrom(architecture?.resourceTypes);
3470
+ if (resourceCount !== void 0 && resourceTypeCount !== void 0) {
3471
+ architectureLines.push(
3472
+ `- Resource diversity: **${displayNumber(resourceTypeCount)} types across ${displayNumber(resourceCount)} resources**`
3473
+ );
3474
+ }
3475
+ const overallRating = scoreRating(score);
3043
3476
  const lines = [
3044
- `**${gateStatus}** for ${projectDisplay}: Well-Architected ${score}, cost ${formatMoney(cost?.amount, cost?.currency)}, ${compactValidation(validation)}.`,
3477
+ `${statusIcon(data.gate?.status)} **Overall** : ${gateStatus}`,
3478
+ `${scoreRatingIcon(overallRating)} Well-Architected Posture: ${formatScore(score)} (${overallRating ?? "UNKNOWN"})`,
3479
+ validationSummaryLine(validation),
3480
+ policySummaryLine(validation),
3481
+ costSummaryLine(cost),
3482
+ `**Cloudeval Project**: ${projectDisplay}`,
3045
3483
  "",
3046
3484
  `Source: \`${source}\` \xB7 commit \`${commit}\``
3047
3485
  ];
@@ -3055,38 +3493,75 @@ var buildMarkdownSummary = (data) => {
3055
3493
  lines.push(
3056
3494
  "",
3057
3495
  "<details>",
3058
- "<summary>Well-Architected details</summary>",
3496
+ "<summary>Well-Architected drilldown</summary>",
3497
+ "",
3498
+ ...riskLines,
3059
3499
  "",
3060
- `- Overall score: ${score}`,
3500
+ "| Pillar | Score | Rating |",
3501
+ "| --- | ---: | --- |",
3061
3502
  ...pillarLines,
3062
3503
  "",
3063
3504
  "</details>"
3064
3505
  );
3065
3506
  }
3066
3507
  if (cost?.amount !== void 0 || cost?.threshold !== void 0) {
3067
- const costLines = [`- Monthly estimate: ${formatMoney(cost?.amount, cost?.currency)}`];
3508
+ const costLines = [];
3068
3509
  if (data.gate?.cost?.estimatedSavings?.amount !== void 0) {
3069
3510
  costLines.push(
3070
- `- Estimated savings: ${formatMoney(data.gate.cost.estimatedSavings.amount, data.gate.cost.estimatedSavings.currency)}`
3511
+ `- Estimated savings: **${formatMonthlyMoney(data.gate.cost.estimatedSavings.amount, data.gate.cost.estimatedSavings.currency)}**`
3071
3512
  );
3072
3513
  }
3514
+ if (costServices.length) {
3515
+ costLines.push(
3516
+ "",
3517
+ "| Service | Monthly cost |",
3518
+ "| --- | ---: |",
3519
+ ...costServices.map(
3520
+ (service) => `| ${service.name} | **${formatMonthlyMoney(service.amount, service.currency)}** |`
3521
+ )
3522
+ );
3523
+ }
3524
+ if (positiveCostServices.length) {
3525
+ costLines.push(
3526
+ "",
3527
+ "```mermaid",
3528
+ "pie title Monthly cost by service",
3529
+ ...positiveCostServices.map(
3530
+ (service) => ` "${mermaidLabel(service.name)}" : ${trimNumber(service.amount, 3)}`
3531
+ ),
3532
+ "```"
3533
+ );
3534
+ }
3535
+ if (costLines.length) {
3536
+ lines.push(
3537
+ "",
3538
+ "<details>",
3539
+ "<summary>Cost drilldown</summary>",
3540
+ "",
3541
+ ...costLines,
3542
+ "",
3543
+ "</details>"
3544
+ );
3545
+ }
3546
+ }
3547
+ if (validation) {
3073
3548
  lines.push(
3074
3549
  "",
3075
3550
  "<details>",
3076
- "<summary>Cost details</summary>",
3551
+ "<summary>Validation details</summary>",
3077
3552
  "",
3078
- ...costLines,
3553
+ ...validationDetailLines(validation),
3079
3554
  "",
3080
3555
  "</details>"
3081
3556
  );
3082
3557
  }
3083
- if (validation) {
3558
+ if (architectureLines.length) {
3084
3559
  lines.push(
3085
3560
  "",
3086
3561
  "<details>",
3087
- "<summary>Validation details</summary>",
3562
+ "<summary>Architecture insights</summary>",
3088
3563
  "",
3089
- `- ${formatValidation(validation)}`,
3564
+ ...architectureLines,
3090
3565
  "",
3091
3566
  "</details>"
3092
3567
  );
@@ -3150,7 +3625,7 @@ var registerReviewCommand = (program2, deps) => {
3150
3625
  9e5
3151
3626
  )
3152
3627
  }) : void 0;
3153
- const [{ cost, waf, preload }, configText] = await Promise.all([
3628
+ const [{ cost, waf, preload, graph }, configText] = await Promise.all([
3154
3629
  waitForReviewReports({
3155
3630
  baseUrl: context.baseUrl,
3156
3631
  token: context.token,
@@ -3188,8 +3663,8 @@ var registerReviewCommand = (program2, deps) => {
3188
3663
  commitSha,
3189
3664
  sourceRoot,
3190
3665
  sync: reviewSyncStatus(sync, finalStatus),
3191
- reports: reviewReportStatuses({ cost, waf, preload }),
3192
- gate: evaluateGate({ configText, waf, cost, preload, project })
3666
+ reports: reviewReportStatuses({ cost, waf, preload, graph }),
3667
+ gate: evaluateGate({ configText, waf, cost, preload, graph, project })
3193
3668
  };
3194
3669
  if (options.aiSummary !== false) {
3195
3670
  try {
@@ -4567,7 +5042,7 @@ var runChatRecipe = async (recipe, prompt2, options, command, deps) => {
4567
5042
  });
4568
5043
  progressWriter.write({ type: "auth", step: "auth", message: "Resolving authentication" });
4569
5044
  const context = await resolveAuthContext(options, command, deps);
4570
- const core = await import("./dist-MQQKC6DZ.js");
5045
+ const core = await import("./dist-PEYJDO7A.js");
4571
5046
  progressWriter.write({
4572
5047
  type: "request",
4573
5048
  step: "project",
@@ -5656,6 +6131,8 @@ var generateWorkspaceConfig = (entry, parameters, sourceEntry) => {
5656
6131
  ` : "";
5657
6132
  const sourceEntryLine = sourceEntry ? ` source_entry: ${sourceEntry}` : "";
5658
6133
  return [
6134
+ "# CloudEval config v1. Paths are relative to this workspace root.",
6135
+ "# Visualization source for diagrams and reports.",
5659
6136
  "version: 1",
5660
6137
  "stacks:",
5661
6138
  " - id: main",
@@ -5663,10 +6140,23 @@ var generateWorkspaceConfig = (entry, parameters, sourceEntry) => {
5663
6140
  sourceEntryLine,
5664
6141
  parameterLine.trimEnd(),
5665
6142
  "resolve:",
6143
+ " # Follow relative ARM templateLink files when building the analysis bundle.",
5666
6144
  " linked_templates: true",
5667
6145
  "analysis:",
6146
+ " # Run the normal import -> resolve -> report refresh pipeline after upload.",
5668
6147
  " auto_resolve_on_import: true",
5669
6148
  " auto_refresh_on_resolve: true",
6149
+ "",
6150
+ "# Optional CI gates for `cloudeval review` and GitHub Actions.",
6151
+ "# Uncomment and tune these when pull requests should be blocked by CloudEval.",
6152
+ "# ci:",
6153
+ "# gates:",
6154
+ "# enforcement: required # required fails CI; warn only reports failures",
6155
+ "# overall_score_min: 80 # minimum Well-Architected score out of 100",
6156
+ "# pillar_score_min: 75 # optional default minimum for every pillar",
6157
+ "# fail_on_high_risk: true # fail when high-risk architecture findings exist",
6158
+ "# fail_on_validation_errors: true # fail when policy checks or unit tests fail",
6159
+ "# max_monthly_cost: 500 # optional monthly budget gate",
5670
6160
  ""
5671
6161
  ].filter((line) => line.length > 0).join("\n");
5672
6162
  };
@@ -6036,7 +6526,7 @@ var configureDiagramExportCommand = (command, deps) => addAuthOptions(command, d
6036
6526
  const context = requireAuthUser(
6037
6527
  await resolveAuthContext(options, actionCommand, deps)
6038
6528
  );
6039
- const core = await import("./dist-MQQKC6DZ.js");
6529
+ const core = await import("./dist-PEYJDO7A.js");
6040
6530
  const projects = await core.getProjects(
6041
6531
  context.baseUrl,
6042
6532
  context.token,
@@ -6113,7 +6603,7 @@ var registerProjectsCommand = (program2, deps) => {
6113
6603
  addCommon(addAuthOptions(projects.command("list").description("List projects"), deps.defaultBaseUrl)).action(async (options, command) => {
6114
6604
  try {
6115
6605
  const context = await resolveAuthContext(options, command, deps);
6116
- const core = await import("./dist-MQQKC6DZ.js");
6606
+ const core = await import("./dist-PEYJDO7A.js");
6117
6607
  const data = await listProjectsForContext(core, context);
6118
6608
  const url = buildFrontendUrl({ baseUrl: frontendBase(context, options), target: "projects" });
6119
6609
  await writeProjectListOutput({ data, options, frontendUrl: url });
@@ -6131,7 +6621,7 @@ var registerProjectsCommand = (program2, deps) => {
6131
6621
  ).action(async (id, options, command) => {
6132
6622
  try {
6133
6623
  const context = await resolveAuthContext(options, command, deps);
6134
- const core = await import("./dist-MQQKC6DZ.js");
6624
+ const core = await import("./dist-PEYJDO7A.js");
6135
6625
  const list = await listProjectsForContext(core, context);
6136
6626
  const data = list.find((project) => project.id === id);
6137
6627
  if (!data) {
@@ -6196,7 +6686,7 @@ var registerProjectsCommand = (program2, deps) => {
6196
6686
  try {
6197
6687
  assertSingleProjectSource(options);
6198
6688
  const context = requireAuthUser(await resolveAuthContext(options, command, deps));
6199
- const core = await import("./dist-MQQKC6DZ.js");
6689
+ const core = await import("./dist-PEYJDO7A.js");
6200
6690
  const template = await fileBlob(options.templateFile);
6201
6691
  const parameters = await fileBlob(options.parametersFile);
6202
6692
  const workspace = options.workspaceDir ? await collectWorkspaceFiles(options.workspaceDir, options) : void 0;
@@ -6325,7 +6815,7 @@ var registerConnectionsCommand = (program2, deps) => {
6325
6815
  addCommon2(addAuthOptions(connections.command("list").description("List connections"), deps.defaultBaseUrl)).action(async (options, command) => {
6326
6816
  try {
6327
6817
  const context = requireAuthUser(await resolveAuthContext(options, command, deps));
6328
- const core = await import("./dist-MQQKC6DZ.js");
6818
+ const core = await import("./dist-PEYJDO7A.js");
6329
6819
  const data = await core.listConnections({
6330
6820
  baseUrl: context.baseUrl,
6331
6821
  authToken: context.token,
@@ -6350,7 +6840,7 @@ var registerConnectionsCommand = (program2, deps) => {
6350
6840
  ).action(async (id, options, command) => {
6351
6841
  try {
6352
6842
  const context = requireAuthUser(await resolveAuthContext(options, command, deps));
6353
- const core = await import("./dist-MQQKC6DZ.js");
6843
+ const core = await import("./dist-PEYJDO7A.js");
6354
6844
  const data = await core.getConnection({
6355
6845
  baseUrl: context.baseUrl,
6356
6846
  authToken: context.token,
@@ -6688,7 +7178,7 @@ var checkoutReturnUrl = (context, options) => options.returnTo || billingUrl(con
6688
7178
  var runTopUpCheckout = async (commandName, packId, options, command, deps) => {
6689
7179
  try {
6690
7180
  const context = requireAuthUser(await resolveAuthContext(options, command, deps));
6691
- const core = await import("./dist-MQQKC6DZ.js");
7181
+ const core = await import("./dist-PEYJDO7A.js");
6692
7182
  const returnTo = checkoutReturnUrl(context, options);
6693
7183
  const session = await core.createTopUpCheckoutSession({
6694
7184
  baseUrl: context.baseUrl,
@@ -6728,7 +7218,7 @@ var registerBillingCommands = (program2, deps) => {
6728
7218
  ).action(async (options, command) => {
6729
7219
  try {
6730
7220
  const context = requireAuthUser(await resolveAuthContext(options, command, deps));
6731
- const core = await import("./dist-MQQKC6DZ.js");
7221
+ const core = await import("./dist-PEYJDO7A.js");
6732
7222
  const range = rangeToDates("30d");
6733
7223
  const [entitlement, usageSummary] = await Promise.all([
6734
7224
  core.getBillingEntitlement({
@@ -6758,7 +7248,7 @@ var registerBillingCommands = (program2, deps) => {
6758
7248
  addCommon3(addAuthOptions(billing.command("summary").description("Show billing summary"), deps.defaultBaseUrl)).action(async (options, command) => {
6759
7249
  try {
6760
7250
  const context = requireAuthUser(await resolveAuthContext(options, command, deps));
6761
- const core = await import("./dist-MQQKC6DZ.js");
7251
+ const core = await import("./dist-PEYJDO7A.js");
6762
7252
  const range = rangeToDates("30d");
6763
7253
  const [entitlement, subscriptionStatus, usageSummary] = await Promise.all([
6764
7254
  core.getBillingEntitlement({ baseUrl: context.baseUrl, authToken: context.token }),
@@ -6794,7 +7284,7 @@ var registerBillingCommands = (program2, deps) => {
6794
7284
  addCommon3(addAuthOptions(billing.command("plans").description("Show billing plans"), deps.defaultBaseUrl)).action(async (options, command) => {
6795
7285
  try {
6796
7286
  const context = await resolveAuthContext(options, command, deps);
6797
- const core = await import("./dist-MQQKC6DZ.js");
7287
+ const core = await import("./dist-PEYJDO7A.js");
6798
7288
  const data = await core.getBillingConfig({ baseUrl: context.baseUrl, authToken: context.token });
6799
7289
  const url = billingUrl(context, { ...options, tab: "plans" });
6800
7290
  await write("billing plans", data, options, url);
@@ -6806,7 +7296,7 @@ var registerBillingCommands = (program2, deps) => {
6806
7296
  addCommon3(addAuthOptions(billing.command("usage").description("Show billing usage summary"), deps.defaultBaseUrl)).option("--range <range>", "Usage range: 7d, 30d, 90d, all", "30d").option("--start-at <iso>", "Start timestamp").option("--end-at <iso>", "End timestamp").option("--granularity <value>", "Granularity: hour, day, month", "day").option("--action-type <type>", "Action type filter").option("--model <name>", "Model filter").option("--outcome <outcome>", "Outcome filter").option("--charge-status <status>", "Charge status filter").action(async (options, command) => {
6807
7297
  try {
6808
7298
  const context = requireAuthUser(await resolveAuthContext(options, command, deps));
6809
- const core = await import("./dist-MQQKC6DZ.js");
7299
+ const core = await import("./dist-PEYJDO7A.js");
6810
7300
  const range = rangeToDates(options.range);
6811
7301
  const data = await core.getBillingUsageSummary({
6812
7302
  baseUrl: context.baseUrl,
@@ -6829,7 +7319,7 @@ var registerBillingCommands = (program2, deps) => {
6829
7319
  addCommon3(addAuthOptions(billing.command("ledger").description("Show billing ledger"), deps.defaultBaseUrl)).option("--range <range>", "Usage range: 7d, 30d, 90d, all", "30d").option("--start-at <iso>", "Start timestamp").option("--end-at <iso>", "End timestamp").option("--action-type <type>", "Action type filter").option("--model <name>", "Model filter").option("--outcome <outcome>", "Outcome filter").option("--charge-status <status>", "Charge status filter").option("--limit <n>", "Page size", "25").option("--cursor <cursor>", "Pagination cursor").action(async (options, command) => {
6830
7320
  try {
6831
7321
  const context = requireAuthUser(await resolveAuthContext(options, command, deps));
6832
- const core = await import("./dist-MQQKC6DZ.js");
7322
+ const core = await import("./dist-PEYJDO7A.js");
6833
7323
  const range = rangeToDates(options.range);
6834
7324
  const data = await core.getBillingUsageLedger({
6835
7325
  baseUrl: context.baseUrl,
@@ -6857,7 +7347,7 @@ var registerBillingCommands = (program2, deps) => {
6857
7347
  addCommon3(addAuthOptions(billing.command(name).description(`Show billing ${name}`), deps.defaultBaseUrl)).option("--limit <n>", "Result limit", "25").action(async (options, command) => {
6858
7348
  try {
6859
7349
  const context = requireAuthUser(await resolveAuthContext(options, command, deps));
6860
- const core = await import("./dist-MQQKC6DZ.js");
7350
+ const core = await import("./dist-PEYJDO7A.js");
6861
7351
  const data = await core[getter]({
6862
7352
  baseUrl: context.baseUrl,
6863
7353
  authToken: context.token,
@@ -6875,7 +7365,7 @@ var registerBillingCommands = (program2, deps) => {
6875
7365
  addCommon3(addAuthOptions(topups, deps.defaultBaseUrl)).option("--limit <n>", "Result limit", "25").action(async (options, command) => {
6876
7366
  try {
6877
7367
  const context = requireAuthUser(await resolveAuthContext(options, command, deps));
6878
- const core = await import("./dist-MQQKC6DZ.js");
7368
+ const core = await import("./dist-PEYJDO7A.js");
6879
7369
  const data = await core.getTopUpPacks({
6880
7370
  baseUrl: context.baseUrl,
6881
7371
  authToken: context.token
@@ -7404,12 +7894,13 @@ var getRule = async (input) => fetchCloudEvalJson({
7404
7894
 
7405
7895
  // src/telemetry.ts
7406
7896
  import os3 from "os";
7897
+ import { createHash } from "crypto";
7407
7898
 
7408
7899
  // src/telemetryConnectionString.generated.ts
7409
7900
  var PACKAGED_APPLICATIONINSIGHTS_CONNECTION_STRING = "InstrumentationKey=ca7b6ae2-ce35-4e67-8756-439ebe2da618;IngestionEndpoint=https://westeurope-5.in.applicationinsights.azure.com/;LiveEndpoint=https://westeurope.livediagnostics.monitor.azure.com/;ApplicationId=28327903-cb61-4210-bed7-d4d8f9f65cfe";
7410
7901
 
7411
7902
  // src/telemetry.ts
7412
- var TELEMETRY_SCHEMA_VERSION = "1";
7903
+ var TELEMETRY_SCHEMA_VERSION = "2";
7413
7904
  var TRUE_VALUES = /* @__PURE__ */ new Set(["1", "true", "yes", "on"]);
7414
7905
  var FALSE_VALUES = /* @__PURE__ */ new Set(["0", "false", "no", "off"]);
7415
7906
  var PROPERTY_ALLOWLIST = /* @__PURE__ */ new Set([
@@ -7421,23 +7912,20 @@ var PROPERTY_ALLOWLIST = /* @__PURE__ */ new Set([
7421
7912
  "command",
7422
7913
  "completionShell",
7423
7914
  "completions",
7424
- "email",
7425
7915
  "errorCategory",
7426
7916
  "exitCode",
7427
- "firstName",
7428
7917
  "format",
7429
- "fullName",
7430
7918
  "installSource",
7431
7919
  "installerResult",
7432
7920
  "installerType",
7433
7921
  "interactive",
7434
- "lastName",
7435
7922
  "mcpSetup",
7436
7923
  "nodeVersion",
7437
7924
  "os",
7438
7925
  "osVersionMajor",
7439
7926
  "previousCliVersion",
7440
7927
  "requestedVersion",
7928
+ "requestId",
7441
7929
  "resolvedVersion",
7442
7930
  "runtime",
7443
7931
  "subcommand",
@@ -7447,8 +7935,10 @@ var PROPERTY_ALLOWLIST = /* @__PURE__ */ new Set([
7447
7935
  "toolName",
7448
7936
  "toolset",
7449
7937
  "targetCliVersion",
7938
+ "traceId",
7450
7939
  "tuiInitialTab",
7451
- "updateAction"
7940
+ "updateAction",
7941
+ "user_hash"
7452
7942
  ]);
7453
7943
  var MEASUREMENT_ALLOWLIST = /* @__PURE__ */ new Set(["durationMs"]);
7454
7944
  var trimString = (value) => {
@@ -7516,16 +8006,12 @@ var buildTelemetryUserProperties = (user) => {
7516
8006
  if (!user || typeof user !== "object") {
7517
8007
  return {};
7518
8008
  }
7519
- const email = trimString(user.email);
7520
- const fullName = trimString(user.fullName) || trimString(user.full_name) || trimString(user.name);
7521
- const firstName = trimString(user.firstName);
7522
- const lastName = trimString(user.lastName);
7523
- const nameParts = fullName?.split(/\s+/).filter(Boolean) || [];
8009
+ const internalId = trimString(user.id) || trimString(user.userId) || trimString(user.user_id) || trimString(user.accountId) || trimString(user.account_id);
8010
+ if (!internalId) {
8011
+ return {};
8012
+ }
7524
8013
  return {
7525
- ...email ? { email } : {},
7526
- ...firstName || nameParts[0] ? { firstName: firstName || nameParts[0] } : {},
7527
- ...lastName || nameParts.length > 1 ? { lastName: lastName || nameParts[nameParts.length - 1] } : {},
7528
- ...fullName ? { fullName } : {}
8014
+ user_hash: `h_${createHash("sha256").update("cloudeval-cli:user:").update(internalId).digest("hex").slice(0, 32)}`
7529
8015
  };
7530
8016
  };
7531
8017
  var classifyTelemetryError = (error) => {
@@ -7585,6 +8071,16 @@ var createApplicationInsightsClient = async (connectionString) => {
7585
8071
  disableDiskRetryCaching(client);
7586
8072
  return client;
7587
8073
  };
8074
+ var setTelemetryClientRole = (client) => {
8075
+ try {
8076
+ const context = client.context;
8077
+ const cloudRoleKey = context?.keys?.cloudRole;
8078
+ if (cloudRoleKey && context?.tags) {
8079
+ context.tags[cloudRoleKey] = "cloudeval-cli";
8080
+ }
8081
+ } catch {
8082
+ }
8083
+ };
7588
8084
  var disableDiskRetryCaching = (client) => {
7589
8085
  try {
7590
8086
  client.setUseDiskRetryCaching?.(false);
@@ -7641,6 +8137,7 @@ var createCliTelemetry = async (options) => {
7641
8137
  let client;
7642
8138
  try {
7643
8139
  client = options.clientFactory ? options.clientFactory(connectionString) : await createApplicationInsightsClient(connectionString);
8140
+ setTelemetryClientRole(client);
7644
8141
  } catch {
7645
8142
  return createNoopTelemetry();
7646
8143
  }
@@ -9546,7 +10043,7 @@ var reportsFrontendUrl = (config, input) => buildFrontendUrl({
9546
10043
  reportVerbosity: input.reportVerbosity
9547
10044
  });
9548
10045
  var resolveAuth = async (config, options = {}) => {
9549
- const core = await import("./dist-MQQKC6DZ.js");
10046
+ const core = await import("./dist-PEYJDO7A.js");
9550
10047
  core.assertSecureBaseUrl(config.baseUrl);
9551
10048
  let token;
9552
10049
  try {
@@ -9642,7 +10139,7 @@ var assertModelAvailable = async (config, token) => {
9642
10139
  if (!config.model) {
9643
10140
  return;
9644
10141
  }
9645
- const core = await import("./dist-MQQKC6DZ.js");
10142
+ const core = await import("./dist-PEYJDO7A.js");
9646
10143
  try {
9647
10144
  const response = await fetch(
9648
10145
  `${core.normalizeApiBase(config.baseUrl)}/models`,
@@ -9899,7 +10396,7 @@ var buildToolHandlers = (serverOptions) => {
9899
10396
  });
9900
10397
  handlers.set("agent_profiles_list", async (args) => {
9901
10398
  const config = await resolveInvocationConfig(serverOptions, args);
9902
- const core = await import("./dist-MQQKC6DZ.js");
10399
+ const core = await import("./dist-PEYJDO7A.js");
9903
10400
  const data = await listProfilesForDiscovery(core, config.baseUrl);
9904
10401
  return withEnvelope({
9905
10402
  command: "agents list",
@@ -9912,7 +10409,7 @@ var buildToolHandlers = (serverOptions) => {
9912
10409
  throw new Error("profileId is required.");
9913
10410
  }
9914
10411
  const config = await resolveInvocationConfig(serverOptions, args);
9915
- const core = await import("./dist-MQQKC6DZ.js");
10412
+ const core = await import("./dist-PEYJDO7A.js");
9916
10413
  const data = await getProfileForDiscovery(core, config.baseUrl, profileId);
9917
10414
  return withEnvelope({
9918
10415
  command: "agents show",
@@ -10549,7 +11046,7 @@ var buildToolHandlers = (serverOptions) => {
10549
11046
  });
10550
11047
  handlers.set("auth_status", async (args) => {
10551
11048
  const config = await resolveInvocationConfig(serverOptions, args);
10552
- const core = await import("./dist-MQQKC6DZ.js");
11049
+ const core = await import("./dist-PEYJDO7A.js");
10553
11050
  const data = await core.getAuthStatus(config.baseUrl, { validate: true });
10554
11051
  return withEnvelope({
10555
11052
  command: "auth status",
@@ -10558,7 +11055,7 @@ var buildToolHandlers = (serverOptions) => {
10558
11055
  });
10559
11056
  handlers.set("status", async (args) => {
10560
11057
  const config = await resolveInvocationConfig(serverOptions, args);
10561
- const core = await import("./dist-MQQKC6DZ.js");
11058
+ const core = await import("./dist-PEYJDO7A.js");
10562
11059
  const auth = await core.getAuthStatus(config.baseUrl, { validate: true });
10563
11060
  return withEnvelope({
10564
11061
  command: "status",
@@ -10589,7 +11086,7 @@ var buildToolHandlers = (serverOptions) => {
10589
11086
  }
10590
11087
  ];
10591
11088
  try {
10592
- const core = await import("./dist-MQQKC6DZ.js");
11089
+ const core = await import("./dist-PEYJDO7A.js");
10593
11090
  core.assertSecureBaseUrl(config.baseUrl);
10594
11091
  checks.push({
10595
11092
  id: "base-url-secure",
@@ -11109,7 +11606,7 @@ var buildToolHandlers = (serverOptions) => {
11109
11606
  } catch {
11110
11607
  token = config.accessKey;
11111
11608
  }
11112
- const core = await import("./dist-MQQKC6DZ.js");
11609
+ const core = await import("./dist-PEYJDO7A.js");
11113
11610
  const data = await core.getBillingConfig({
11114
11611
  baseUrl: config.baseUrl,
11115
11612
  authToken: token
@@ -11963,7 +12460,7 @@ var registerCapabilitiesCommand = (program2, deps) => {
11963
12460
  warnIfAccessKeyFromCliOption(options, command);
11964
12461
  let data = capabilities;
11965
12462
  if (options.live) {
11966
- const core = await import("./dist-MQQKC6DZ.js");
12463
+ const core = await import("./dist-PEYJDO7A.js");
11967
12464
  const baseUrl = await deps.resolveBaseUrl(options, command);
11968
12465
  const accessKey = options.accessKeyStdin ? await deps.readStdinValue() : options.accessKey;
11969
12466
  const token = await core.getAuthToken({ accessKey, baseUrl });
@@ -12101,7 +12598,7 @@ var writeCredentialOutput = async (input) => {
12101
12598
  };
12102
12599
  var resolveCoreAuth = async (options, command, deps) => {
12103
12600
  const context = await resolveAuthContext(options, command, deps);
12104
- const core = await import("./dist-MQQKC6DZ.js");
12601
+ const core = await import("./dist-PEYJDO7A.js");
12105
12602
  return { ...context, core };
12106
12603
  };
12107
12604
  var parseCapabilities = (value) => value?.split(",").map((item) => item.trim()).filter(Boolean);
@@ -12418,7 +12915,7 @@ var registerAgentsCommand = (program2, deps) => {
12418
12915
  const agents = program2.command("agents").description("CloudEval Agent Profile utilities");
12419
12916
  addAgentOutputOptions(agents.command("list").description("List Agent Profiles"), deps).action(async (options, command) => {
12420
12917
  const baseUrl = await deps.resolveBaseUrl(options, command);
12421
- const core = await import("./dist-MQQKC6DZ.js");
12918
+ const core = await import("./dist-PEYJDO7A.js");
12422
12919
  core.assertSecureBaseUrl(baseUrl);
12423
12920
  const data = await listProfilesForDiscovery2(core, baseUrl);
12424
12921
  await writeProfiles({
@@ -12434,7 +12931,7 @@ var registerAgentsCommand = (program2, deps) => {
12434
12931
  deps
12435
12932
  ).action(async (profileId, options, command) => {
12436
12933
  const baseUrl = await deps.resolveBaseUrl(options, command);
12437
- const core = await import("./dist-MQQKC6DZ.js");
12934
+ const core = await import("./dist-PEYJDO7A.js");
12438
12935
  core.assertSecureBaseUrl(baseUrl);
12439
12936
  const data = await getProfileForDiscovery2(core, baseUrl, profileId);
12440
12937
  await writeProfiles({
@@ -12453,7 +12950,7 @@ var registerAgentsCommand = (program2, deps) => {
12453
12950
  const cliProfile = getActiveConfigProfile(command);
12454
12951
  const cliConfig = await loadCliConfig(cliProfile);
12455
12952
  const auth = await resolveAuthContext(options, command, deps);
12456
- const core = await import("./dist-MQQKC6DZ.js");
12953
+ const core = await import("./dist-PEYJDO7A.js");
12457
12954
  const profileResponse = await core.getAgentProfile({
12458
12955
  baseUrl: auth.baseUrl,
12459
12956
  authToken: auth.token,
@@ -12951,7 +13448,7 @@ var registerDiagnosticsCommands = (program2, deps) => {
12951
13448
  const baseUrl = await deps.resolveBaseUrl(options, command);
12952
13449
  const profile = getActiveConfigProfile(command);
12953
13450
  const config = await loadCliConfig(profile);
12954
- const core = await import("./dist-MQQKC6DZ.js");
13451
+ const core = await import("./dist-PEYJDO7A.js");
12955
13452
  const auth = await core.getAuthStatus(baseUrl, { validate: true });
12956
13453
  if (options.format === "text" || !options.format) {
12957
13454
  process.stdout.write(
@@ -13001,7 +13498,7 @@ var registerDiagnosticsCommands = (program2, deps) => {
13001
13498
  detail: getCliConfigPath(profile)
13002
13499
  });
13003
13500
  try {
13004
- const core = await import("./dist-MQQKC6DZ.js");
13501
+ const core = await import("./dist-PEYJDO7A.js");
13005
13502
  core.assertSecureBaseUrl(baseUrl);
13006
13503
  checks.push({
13007
13504
  id: "base-url-secure",
@@ -13101,7 +13598,7 @@ var resolveToken2 = async (options, deps, baseUrl, command) => {
13101
13598
  return options.accessKey;
13102
13599
  }
13103
13600
  try {
13104
- const core = await import("./dist-MQQKC6DZ.js");
13601
+ const core = await import("./dist-PEYJDO7A.js");
13105
13602
  return await core.getAuthToken({
13106
13603
  baseUrl
13107
13604
  });
@@ -13185,7 +13682,7 @@ var registerModelsCommand = (program2, deps) => {
13185
13682
  let source = "fallback";
13186
13683
  let modelList = fallbackModels;
13187
13684
  try {
13188
- const core = await import("./dist-MQQKC6DZ.js");
13685
+ const core = await import("./dist-PEYJDO7A.js");
13189
13686
  const response = await fetch(`${core.normalizeApiBase(baseUrl)}/models`, {
13190
13687
  headers: {
13191
13688
  Accept: "application/json",
@@ -14364,7 +14861,7 @@ var uninstallCompletionScript = async (shell) => {
14364
14861
  var runInteractiveLoginOnboarding = async (baseUrl, token) => {
14365
14862
  const [{ render }, { Onboarding }] = await Promise.all([
14366
14863
  import("ink"),
14367
- import("./Onboarding-CORIICF5.js")
14864
+ import("./Onboarding-GAN3Q5TS.js")
14368
14865
  ]);
14369
14866
  await new Promise((resolve) => {
14370
14867
  let app;
@@ -14630,7 +15127,13 @@ var getActiveCliTelemetry = () => activeTelemetry;
14630
15127
  var initializeCommandTelemetry = async (actionCommand, options) => {
14631
15128
  activeTelemetryStartedAt = Date.now();
14632
15129
  activeTelemetryFinished = false;
14633
- activeTelemetryProperties = telemetryPropertiesForCommand(actionCommand, options);
15130
+ const traceContext = createCLITraceContext();
15131
+ setActiveCLITraceContext(traceContext);
15132
+ activeTelemetryProperties = {
15133
+ ...telemetryPropertiesForCommand(actionCommand, options),
15134
+ traceId: traceContext.traceId,
15135
+ requestId: traceContext.requestId
15136
+ };
14634
15137
  const config = await resolveCliConfig(actionCommand);
14635
15138
  activeTelemetry = await createCliTelemetry({
14636
15139
  config,
@@ -14639,27 +15142,33 @@ var initializeCommandTelemetry = async (actionCommand, options) => {
14639
15142
  };
14640
15143
  var finishCommandTelemetry = async (exitCode, error) => {
14641
15144
  if (!activeTelemetry || activeTelemetryFinished) {
15145
+ clearActiveCLITraceContext();
14642
15146
  return;
14643
15147
  }
14644
15148
  activeTelemetryFinished = true;
14645
15149
  const durationMs = Math.max(0, Date.now() - activeTelemetryStartedAt);
14646
- if (error) {
14647
- await activeTelemetry.track("cli.error", {
15150
+ try {
15151
+ if (error) {
15152
+ await activeTelemetry.track("cli.error", {
15153
+ ...activeTelemetryProperties,
15154
+ durationMs,
15155
+ exitCode,
15156
+ success: false,
15157
+ errorCategory: classifyTelemetryError(error)
15158
+ });
15159
+ }
15160
+ await activeTelemetry.track("cli.command", {
14648
15161
  ...activeTelemetryProperties,
14649
15162
  durationMs,
14650
15163
  exitCode,
14651
- success: false,
14652
- errorCategory: classifyTelemetryError(error)
15164
+ success: exitCode === 0,
15165
+ ...error ? { errorCategory: classifyTelemetryError(error) } : {}
14653
15166
  });
15167
+ await activeTelemetry.flush();
15168
+ } finally {
15169
+ clearActiveCLITraceContext();
15170
+ activeTelemetry = void 0;
14654
15171
  }
14655
- await activeTelemetry.track("cli.command", {
14656
- ...activeTelemetryProperties,
14657
- durationMs,
14658
- exitCode,
14659
- success: exitCode === 0,
14660
- ...error ? { errorCategory: classifyTelemetryError(error) } : {}
14661
- });
14662
- await activeTelemetry.flush();
14663
15172
  };
14664
15173
  var exitCli = async (exitCode, error) => {
14665
15174
  await finishCommandTelemetry(exitCode, error);
@@ -14686,7 +15195,7 @@ var resolveBaseUrl = async (options, command) => {
14686
15195
  });
14687
15196
  }
14688
15197
  try {
14689
- const { getAuthStatus } = await import("./dist-MQQKC6DZ.js");
15198
+ const { getAuthStatus } = await import("./dist-PEYJDO7A.js");
14690
15199
  const status = await getAuthStatus();
14691
15200
  const storedBaseUrl = status.baseUrl;
14692
15201
  if (storedBaseUrl && shouldUseStoredBaseUrl(storedBaseUrl)) {
@@ -14760,7 +15269,7 @@ program.command("login").description("Authenticate with Cloudeval").option(
14760
15269
  checkUserStatus,
14761
15270
  ensurePlaygroundProject,
14762
15271
  login
14763
- } = await import("./dist-MQQKC6DZ.js");
15272
+ } = await import("./dist-PEYJDO7A.js");
14764
15273
  assertSecureBaseUrl(options.baseUrl);
14765
15274
  const headlessEnvironment = isHeadlessEnvironment();
14766
15275
  const headlessLogin = options.headless || headlessEnvironment;
@@ -14835,7 +15344,7 @@ program.command("logout").description("Log out and clear stored authentication s
14835
15344
  DEFAULT_BASE_URL
14836
15345
  ).option("--all-devices", "Revoke sessions on all devices", false).action(async (options) => {
14837
15346
  try {
14838
- const { assertSecureBaseUrl, logout } = await import("./dist-MQQKC6DZ.js");
15347
+ const { assertSecureBaseUrl, logout } = await import("./dist-PEYJDO7A.js");
14839
15348
  assertSecureBaseUrl(options.baseUrl);
14840
15349
  const result = await logout({
14841
15350
  baseUrl: options.baseUrl,
@@ -14869,7 +15378,7 @@ authCommand.command("status").description("Show current authentication status").
14869
15378
  DEFAULT_BASE_URL
14870
15379
  ).option("--format <format>", "Output format: text, json, ndjson, markdown", "text").option("--show-sensitive-ids", "Show full account/session identifiers in command output", false).option("-v, --verbose", "Enable verbose logging and show full non-token identifiers", false).action(async (options, command) => {
14871
15380
  try {
14872
- const { assertSecureBaseUrl, getAuthStatus } = await import("./dist-MQQKC6DZ.js");
15381
+ const { assertSecureBaseUrl, getAuthStatus } = await import("./dist-PEYJDO7A.js");
14873
15382
  const effectiveBaseUrl = await resolveBaseUrl(options, command);
14874
15383
  assertSecureBaseUrl(effectiveBaseUrl);
14875
15384
  const status = await getAuthStatus(effectiveBaseUrl, { validate: true });
@@ -15086,10 +15595,10 @@ program.command("tui").description("Open the CloudEval Terminal UI").option(
15086
15595
  "Access key for automation",
15087
15596
  process.env.CLOUDEVAL_ACCESS_KEY
15088
15597
  ).option("--access-key-stdin", "Read access key from stdin (recommended for automation)", false).option("--model <name>", "Model name").option("--debug", "Log raw chunks", false).option("--health-check", "Enable health check (disabled by default)").option("--no-banner", "Disable ASCII banner").option("--animate", "Enable TUI animations (default)").option("--no-anim", "Disable TUI animations").option("-v, --verbose", "Enable verbose logging", false).action(async (options, command) => {
15089
- const { assertSecureBaseUrl } = await import("./dist-MQQKC6DZ.js");
15598
+ const { assertSecureBaseUrl } = await import("./dist-PEYJDO7A.js");
15090
15599
  const [{ render }, { App }] = await Promise.all([
15091
15600
  import("ink"),
15092
- import("./App-VZXTX4H7.js")
15601
+ import("./App-H7B3T5QW.js")
15093
15602
  ]);
15094
15603
  const baseUrl = await resolveBaseUrl(options, command);
15095
15604
  assertSecureBaseUrl(baseUrl);
@@ -15144,10 +15653,10 @@ program.command("chat").description("Start an interactive chat session").option(
15144
15653
  "Access key for automation",
15145
15654
  process.env.CLOUDEVAL_ACCESS_KEY
15146
15655
  ).option("--access-key-stdin", "Read access key from stdin (recommended for automation)", false).option("--conversation <id>", "Conversation/thread id to resume").option("--continue", "Resume the most recent local chat session", false).option("--resume <id-or-title>", "Resume a local chat session by thread id or title").option("--model <name>", "Model name").option("--mode <mode>", "Initial chat mode: ask, agent").option("--debug", "Log raw chunks", false).option("--health-check", "Enable health check (disabled by default)").option("--no-banner", "Disable ASCII banner").option("--animate", "Enable TUI animations (default)").option("--no-anim", "Disable TUI animations").option("-v, --verbose", "Enable verbose logging", false).action(async (options, command) => {
15147
- const { assertSecureBaseUrl } = await import("./dist-MQQKC6DZ.js");
15656
+ const { assertSecureBaseUrl } = await import("./dist-PEYJDO7A.js");
15148
15657
  const [{ render }, { App }] = await Promise.all([
15149
15658
  import("ink"),
15150
- import("./App-VZXTX4H7.js")
15659
+ import("./App-H7B3T5QW.js")
15151
15660
  ]);
15152
15661
  const baseUrl = await resolveBaseUrl(options, command);
15153
15662
  assertSecureBaseUrl(baseUrl);
@@ -15222,7 +15731,7 @@ program.command("ask").alias("agent").description("Ask a single question or run
15222
15731
  const question = Array.isArray(questionParts) ? questionParts.join(" ") : String(questionParts);
15223
15732
  const commandName = command.parent?.args?.[0] === "agent" ? "agent" : "ask";
15224
15733
  const selectedMode = commandName === "agent" ? "agent" : "ask";
15225
- const { assertSecureBaseUrl } = await import("./dist-MQQKC6DZ.js");
15734
+ const { assertSecureBaseUrl } = await import("./dist-PEYJDO7A.js");
15226
15735
  const baseUrl = await resolveBaseUrl(options, command);
15227
15736
  assertSecureBaseUrl(baseUrl);
15228
15737
  const selectedProfile = getActiveConfigProfile(command);
@@ -15263,7 +15772,7 @@ program.command("ask").alias("agent").description("Ask a single question or run
15263
15772
  const fs14 = await import("fs");
15264
15773
  const fsPromises = await import("fs/promises");
15265
15774
  const { randomUUID: randomUUID5 } = await import("crypto");
15266
- const core = await import("./dist-MQQKC6DZ.js");
15775
+ const core = await import("./dist-PEYJDO7A.js");
15267
15776
  const {
15268
15777
  streamChat,
15269
15778
  reduceChunk,
@@ -15319,7 +15828,7 @@ program.command("ask").alias("agent").description("Ask a single question or run
15319
15828
  console.error("Authentication required. Starting login process...\n");
15320
15829
  }
15321
15830
  try {
15322
- const { login } = await import("./dist-MQQKC6DZ.js");
15831
+ const { login } = await import("./dist-PEYJDO7A.js");
15323
15832
  verboseLog("Calling interactive login", { baseUrl });
15324
15833
  token = await login(baseUrl, {
15325
15834
  headless: isHeadlessEnvironment()
@@ -15383,7 +15892,7 @@ program.command("ask").alias("agent").description("Ask a single question or run
15383
15892
  message: error.message
15384
15893
  });
15385
15894
  }
15386
- const { resolveAskProject } = await import("./resolveAskProject-KQKI5GRT.js");
15895
+ const { resolveAskProject } = await import("./resolveAskProject-DQJXPS5G.js");
15387
15896
  let project;
15388
15897
  try {
15389
15898
  project = await resolveAskProject({
@@ -15901,7 +16410,7 @@ Error: ${errorMsg}
15901
16410
  program.command("banner").description("Preview the startup banner and terminal capabilities").action(async () => {
15902
16411
  const { render } = await import("ink");
15903
16412
  const BannerPreview = React.lazy(async () => ({
15904
- default: (await import("./Banner-URKZ37H4.js")).Banner
16413
+ default: (await import("./Banner-MOLW4ADA.js")).Banner
15905
16414
  }));
15906
16415
  render(
15907
16416
  /* @__PURE__ */ jsx(React.Suspense, { fallback: null, children: /* @__PURE__ */ jsx(BannerPreview, { disable: false }) })