@ganakailabs/cloudeval-cli 0.26.10 → 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-IVGJTC5I.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`;
2541
2546
  };
2542
- var compactValidation = (validation) => {
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";
2565
+ };
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`);
2547
2638
  }
2548
- return formatValidation(validation);
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
+ ];
2721
+ }
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"}`,
@@ -2920,7 +3170,93 @@ var buildAiSummaryPrompt = (data) => [
2920
3170
  `Validation: ${formatValidation(data.gate?.validation)}`,
2921
3171
  Array.isArray(data.gate?.failures) && data.gate.failures.length ? `Gate failures: ${data.gate.failures.join("; ")}` : "Gate failures: none reported"
2922
3172
  ].join("\n");
2923
- var generateAiSummary = async ({
3173
+ var isTransientAiSummaryText = (text) => {
3174
+ if (!text?.trim()) {
3175
+ return false;
3176
+ }
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(
3178
+ text
3179
+ );
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
+ };
3252
+ var aiSummaryRetryDelaysMs = () => {
3253
+ const raw = process.env.CLOUDEVAL_REVIEW_AI_RETRY_DELAYS_MS;
3254
+ if (raw?.trim()) {
3255
+ return raw.split(",").map((value) => Number.parseInt(value.trim(), 10)).filter((value) => Number.isFinite(value) && value >= 0);
3256
+ }
3257
+ return [5e3, 15e3];
3258
+ };
3259
+ var generateAiSummaryAttempt = async ({
2924
3260
  baseUrl,
2925
3261
  token,
2926
3262
  user,
@@ -2930,11 +3266,23 @@ var generateAiSummary = async ({
2930
3266
  agentProfileId,
2931
3267
  data
2932
3268
  }) => {
2933
- const core = await import("./dist-MQQKC6DZ.js");
3269
+ const core = await import("./dist-PEYJDO7A.js");
2934
3270
  const threadId = `review-${data.projectId}-${Date.now()}`;
2935
3271
  let markdown = "";
2936
3272
  let chatState = { ...core.initialChatState, threadId };
2937
- 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({
2938
3286
  baseUrl,
2939
3287
  authToken: token,
2940
3288
  message: buildAiSummaryPrompt(data),
@@ -2962,42 +3310,176 @@ var generateAiSummary = async ({
2962
3310
  completeAfterResponse: true,
2963
3311
  responseCompletionGraceMs: 250,
2964
3312
  streamIdleTimeoutMs: 12e4
2965
- })) {
2966
- chatState = core.reduceChunk(chatState, chunk);
2967
- const latestMessage = [...chatState.messages ?? []].reverse().find((message) => message.role === "assistant");
2968
- const chunkAssistantMessage = Array.isArray(chunk?.messages) ? [...chunk.messages].reverse().find((message) => message?.role === "assistant" && typeof message?.content === "string")?.content : void 0;
2969
- const content = chunk?.content;
2970
- if (typeof chunkAssistantMessage === "string" && chunkAssistantMessage.trim()) {
2971
- 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
+ }
3331
+ }
3332
+ } finally {
3333
+ if (timeoutId) {
3334
+ clearTimeout(timeoutId);
2972
3335
  }
2973
- if (chunk.type === "responding" && typeof content === "string") {
2974
- markdown = latestMessage?.content || `${markdown}${content}`;
3336
+ if (timedOut) {
3337
+ await iterator.return?.(void 0).catch(() => void 0);
2975
3338
  }
2976
3339
  }
2977
3340
  const finalMessage = [...chatState.messages ?? []].reverse().find((message) => message.role === "assistant");
3341
+ const rawMarkdown = String(finalMessage?.content || markdown).trim();
3342
+ const normalized = normalizeAiSummarySections(rawMarkdown);
2978
3343
  return {
2979
3344
  enabled: true,
3345
+ status: "ok",
2980
3346
  mode,
2981
3347
  ...mode === "agent" ? { agentProfileId: agentProfileId ?? "architecture" } : {},
2982
3348
  ...model ? { model } : {},
2983
- markdown: String(finalMessage?.content || markdown).trim(),
3349
+ ...normalized,
2984
3350
  threadId
2985
3351
  };
2986
3352
  };
3353
+ var generateAiSummary = async (input) => {
3354
+ const retryDelays = aiSummaryRetryDelaysMs();
3355
+ let lastResult;
3356
+ let activeInput = input;
3357
+ let fallbackFromMode;
3358
+ for (let attemptIndex = 0; attemptIndex <= retryDelays.length; attemptIndex += 1) {
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
+ }
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
+ }
3401
+ lastResult = result;
3402
+ if (!isTransientAiSummaryText(result.markdown)) {
3403
+ return result;
3404
+ }
3405
+ const retryDelay = retryDelays[attemptIndex];
3406
+ if (retryDelay === void 0) {
3407
+ break;
3408
+ }
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
+ }
3418
+ }
3419
+ return {
3420
+ ...lastResult ?? {},
3421
+ enabled: true,
3422
+ status: "unavailable",
3423
+ mode: activeInput.mode,
3424
+ ...activeInput.mode === "agent" ? { agentProfileId: activeInput.agentProfileId ?? "architecture" } : {},
3425
+ ...input.model ? { model: input.model } : {},
3426
+ ...fallbackFromMode ? { fallbackFromMode } : {},
3427
+ attempts: lastResult?.attempts ?? retryDelays.length + 1,
3428
+ error: lastResult?.markdown || "AI summary unavailable",
3429
+ markdown: "AI summary unavailable: CloudEval AI was rate-limited. Retry the workflow or rerun `cloudeval review`."
3430
+ };
3431
+ };
2987
3432
  var buildMarkdownSummary = (data) => {
2988
3433
  const gateStatus = String(data.gate?.status ?? "unknown").toUpperCase();
2989
- const score = data.gate?.overallScore ?? "unknown";
3434
+ const score = data.gate?.overallScore ?? data.gate?.wellArchitected?.overall?.score;
2990
3435
  const cost = data.gate?.cost?.monthly;
2991
3436
  const validation = data.gate?.validation;
3437
+ const architecture = data.gate?.architecture;
2992
3438
  const projectLabel = String(data.project?.name ?? data.projectName ?? data.projectId);
2993
3439
  const projectDisplay = markdownLink(projectLabel, data.project?.url ?? data.projectUrl);
2994
3440
  const source = data.repo ? `${data.repo}${data.ref ? ` @ ${data.ref}` : ""}` : data.ref ?? "unknown source";
2995
3441
  const commit = String(data.commitSha ?? "unknown").slice(0, 12);
2996
- const pillarLines = Array.isArray(data.gate?.wellArchitected?.pillars) ? data.gate.wellArchitected.pillars.map(
2997
- (pillar) => `- ${pillar.label}: ${pillar.score} - ${String(pillar.status ?? "unknown").toUpperCase()}`
2998
- ) : [];
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);
2999
3476
  const lines = [
3000
- `**${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}`,
3001
3483
  "",
3002
3484
  `Source: \`${source}\` \xB7 commit \`${commit}\``
3003
3485
  ];
@@ -3011,38 +3493,75 @@ var buildMarkdownSummary = (data) => {
3011
3493
  lines.push(
3012
3494
  "",
3013
3495
  "<details>",
3014
- "<summary>Well-Architected details</summary>",
3496
+ "<summary>Well-Architected drilldown</summary>",
3497
+ "",
3498
+ ...riskLines,
3015
3499
  "",
3016
- `- Overall score: ${score}`,
3500
+ "| Pillar | Score | Rating |",
3501
+ "| --- | ---: | --- |",
3017
3502
  ...pillarLines,
3018
3503
  "",
3019
3504
  "</details>"
3020
3505
  );
3021
3506
  }
3022
3507
  if (cost?.amount !== void 0 || cost?.threshold !== void 0) {
3023
- const costLines = [`- Monthly estimate: ${formatMoney(cost?.amount, cost?.currency)}`];
3508
+ const costLines = [];
3024
3509
  if (data.gate?.cost?.estimatedSavings?.amount !== void 0) {
3025
3510
  costLines.push(
3026
- `- 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)}**`
3512
+ );
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>"
3027
3544
  );
3028
3545
  }
3546
+ }
3547
+ if (validation) {
3029
3548
  lines.push(
3030
3549
  "",
3031
3550
  "<details>",
3032
- "<summary>Cost details</summary>",
3551
+ "<summary>Validation details</summary>",
3033
3552
  "",
3034
- ...costLines,
3553
+ ...validationDetailLines(validation),
3035
3554
  "",
3036
3555
  "</details>"
3037
3556
  );
3038
3557
  }
3039
- if (validation) {
3558
+ if (architectureLines.length) {
3040
3559
  lines.push(
3041
3560
  "",
3042
3561
  "<details>",
3043
- "<summary>Validation details</summary>",
3562
+ "<summary>Architecture insights</summary>",
3044
3563
  "",
3045
- `- ${formatValidation(validation)}`,
3564
+ ...architectureLines,
3046
3565
  "",
3047
3566
  "</details>"
3048
3567
  );
@@ -3106,7 +3625,7 @@ var registerReviewCommand = (program2, deps) => {
3106
3625
  9e5
3107
3626
  )
3108
3627
  }) : void 0;
3109
- const [{ cost, waf, preload }, configText] = await Promise.all([
3628
+ const [{ cost, waf, preload, graph }, configText] = await Promise.all([
3110
3629
  waitForReviewReports({
3111
3630
  baseUrl: context.baseUrl,
3112
3631
  token: context.token,
@@ -3144,8 +3663,8 @@ var registerReviewCommand = (program2, deps) => {
3144
3663
  commitSha,
3145
3664
  sourceRoot,
3146
3665
  sync: reviewSyncStatus(sync, finalStatus),
3147
- reports: reviewReportStatuses({ cost, waf, preload }),
3148
- gate: evaluateGate({ configText, waf, cost, preload, project })
3666
+ reports: reviewReportStatuses({ cost, waf, preload, graph }),
3667
+ gate: evaluateGate({ configText, waf, cost, preload, graph, project })
3149
3668
  };
3150
3669
  if (options.aiSummary !== false) {
3151
3670
  try {
@@ -4523,7 +5042,7 @@ var runChatRecipe = async (recipe, prompt2, options, command, deps) => {
4523
5042
  });
4524
5043
  progressWriter.write({ type: "auth", step: "auth", message: "Resolving authentication" });
4525
5044
  const context = await resolveAuthContext(options, command, deps);
4526
- const core = await import("./dist-MQQKC6DZ.js");
5045
+ const core = await import("./dist-PEYJDO7A.js");
4527
5046
  progressWriter.write({
4528
5047
  type: "request",
4529
5048
  step: "project",
@@ -5612,6 +6131,8 @@ var generateWorkspaceConfig = (entry, parameters, sourceEntry) => {
5612
6131
  ` : "";
5613
6132
  const sourceEntryLine = sourceEntry ? ` source_entry: ${sourceEntry}` : "";
5614
6133
  return [
6134
+ "# CloudEval config v1. Paths are relative to this workspace root.",
6135
+ "# Visualization source for diagrams and reports.",
5615
6136
  "version: 1",
5616
6137
  "stacks:",
5617
6138
  " - id: main",
@@ -5619,10 +6140,23 @@ var generateWorkspaceConfig = (entry, parameters, sourceEntry) => {
5619
6140
  sourceEntryLine,
5620
6141
  parameterLine.trimEnd(),
5621
6142
  "resolve:",
6143
+ " # Follow relative ARM templateLink files when building the analysis bundle.",
5622
6144
  " linked_templates: true",
5623
6145
  "analysis:",
6146
+ " # Run the normal import -> resolve -> report refresh pipeline after upload.",
5624
6147
  " auto_resolve_on_import: true",
5625
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",
5626
6160
  ""
5627
6161
  ].filter((line) => line.length > 0).join("\n");
5628
6162
  };
@@ -5992,7 +6526,7 @@ var configureDiagramExportCommand = (command, deps) => addAuthOptions(command, d
5992
6526
  const context = requireAuthUser(
5993
6527
  await resolveAuthContext(options, actionCommand, deps)
5994
6528
  );
5995
- const core = await import("./dist-MQQKC6DZ.js");
6529
+ const core = await import("./dist-PEYJDO7A.js");
5996
6530
  const projects = await core.getProjects(
5997
6531
  context.baseUrl,
5998
6532
  context.token,
@@ -6069,7 +6603,7 @@ var registerProjectsCommand = (program2, deps) => {
6069
6603
  addCommon(addAuthOptions(projects.command("list").description("List projects"), deps.defaultBaseUrl)).action(async (options, command) => {
6070
6604
  try {
6071
6605
  const context = await resolveAuthContext(options, command, deps);
6072
- const core = await import("./dist-MQQKC6DZ.js");
6606
+ const core = await import("./dist-PEYJDO7A.js");
6073
6607
  const data = await listProjectsForContext(core, context);
6074
6608
  const url = buildFrontendUrl({ baseUrl: frontendBase(context, options), target: "projects" });
6075
6609
  await writeProjectListOutput({ data, options, frontendUrl: url });
@@ -6087,7 +6621,7 @@ var registerProjectsCommand = (program2, deps) => {
6087
6621
  ).action(async (id, options, command) => {
6088
6622
  try {
6089
6623
  const context = await resolveAuthContext(options, command, deps);
6090
- const core = await import("./dist-MQQKC6DZ.js");
6624
+ const core = await import("./dist-PEYJDO7A.js");
6091
6625
  const list = await listProjectsForContext(core, context);
6092
6626
  const data = list.find((project) => project.id === id);
6093
6627
  if (!data) {
@@ -6152,7 +6686,7 @@ var registerProjectsCommand = (program2, deps) => {
6152
6686
  try {
6153
6687
  assertSingleProjectSource(options);
6154
6688
  const context = requireAuthUser(await resolveAuthContext(options, command, deps));
6155
- const core = await import("./dist-MQQKC6DZ.js");
6689
+ const core = await import("./dist-PEYJDO7A.js");
6156
6690
  const template = await fileBlob(options.templateFile);
6157
6691
  const parameters = await fileBlob(options.parametersFile);
6158
6692
  const workspace = options.workspaceDir ? await collectWorkspaceFiles(options.workspaceDir, options) : void 0;
@@ -6281,7 +6815,7 @@ var registerConnectionsCommand = (program2, deps) => {
6281
6815
  addCommon2(addAuthOptions(connections.command("list").description("List connections"), deps.defaultBaseUrl)).action(async (options, command) => {
6282
6816
  try {
6283
6817
  const context = requireAuthUser(await resolveAuthContext(options, command, deps));
6284
- const core = await import("./dist-MQQKC6DZ.js");
6818
+ const core = await import("./dist-PEYJDO7A.js");
6285
6819
  const data = await core.listConnections({
6286
6820
  baseUrl: context.baseUrl,
6287
6821
  authToken: context.token,
@@ -6306,7 +6840,7 @@ var registerConnectionsCommand = (program2, deps) => {
6306
6840
  ).action(async (id, options, command) => {
6307
6841
  try {
6308
6842
  const context = requireAuthUser(await resolveAuthContext(options, command, deps));
6309
- const core = await import("./dist-MQQKC6DZ.js");
6843
+ const core = await import("./dist-PEYJDO7A.js");
6310
6844
  const data = await core.getConnection({
6311
6845
  baseUrl: context.baseUrl,
6312
6846
  authToken: context.token,
@@ -6644,7 +7178,7 @@ var checkoutReturnUrl = (context, options) => options.returnTo || billingUrl(con
6644
7178
  var runTopUpCheckout = async (commandName, packId, options, command, deps) => {
6645
7179
  try {
6646
7180
  const context = requireAuthUser(await resolveAuthContext(options, command, deps));
6647
- const core = await import("./dist-MQQKC6DZ.js");
7181
+ const core = await import("./dist-PEYJDO7A.js");
6648
7182
  const returnTo = checkoutReturnUrl(context, options);
6649
7183
  const session = await core.createTopUpCheckoutSession({
6650
7184
  baseUrl: context.baseUrl,
@@ -6684,7 +7218,7 @@ var registerBillingCommands = (program2, deps) => {
6684
7218
  ).action(async (options, command) => {
6685
7219
  try {
6686
7220
  const context = requireAuthUser(await resolveAuthContext(options, command, deps));
6687
- const core = await import("./dist-MQQKC6DZ.js");
7221
+ const core = await import("./dist-PEYJDO7A.js");
6688
7222
  const range = rangeToDates("30d");
6689
7223
  const [entitlement, usageSummary] = await Promise.all([
6690
7224
  core.getBillingEntitlement({
@@ -6714,7 +7248,7 @@ var registerBillingCommands = (program2, deps) => {
6714
7248
  addCommon3(addAuthOptions(billing.command("summary").description("Show billing summary"), deps.defaultBaseUrl)).action(async (options, command) => {
6715
7249
  try {
6716
7250
  const context = requireAuthUser(await resolveAuthContext(options, command, deps));
6717
- const core = await import("./dist-MQQKC6DZ.js");
7251
+ const core = await import("./dist-PEYJDO7A.js");
6718
7252
  const range = rangeToDates("30d");
6719
7253
  const [entitlement, subscriptionStatus, usageSummary] = await Promise.all([
6720
7254
  core.getBillingEntitlement({ baseUrl: context.baseUrl, authToken: context.token }),
@@ -6750,7 +7284,7 @@ var registerBillingCommands = (program2, deps) => {
6750
7284
  addCommon3(addAuthOptions(billing.command("plans").description("Show billing plans"), deps.defaultBaseUrl)).action(async (options, command) => {
6751
7285
  try {
6752
7286
  const context = await resolveAuthContext(options, command, deps);
6753
- const core = await import("./dist-MQQKC6DZ.js");
7287
+ const core = await import("./dist-PEYJDO7A.js");
6754
7288
  const data = await core.getBillingConfig({ baseUrl: context.baseUrl, authToken: context.token });
6755
7289
  const url = billingUrl(context, { ...options, tab: "plans" });
6756
7290
  await write("billing plans", data, options, url);
@@ -6762,7 +7296,7 @@ var registerBillingCommands = (program2, deps) => {
6762
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) => {
6763
7297
  try {
6764
7298
  const context = requireAuthUser(await resolveAuthContext(options, command, deps));
6765
- const core = await import("./dist-MQQKC6DZ.js");
7299
+ const core = await import("./dist-PEYJDO7A.js");
6766
7300
  const range = rangeToDates(options.range);
6767
7301
  const data = await core.getBillingUsageSummary({
6768
7302
  baseUrl: context.baseUrl,
@@ -6785,7 +7319,7 @@ var registerBillingCommands = (program2, deps) => {
6785
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) => {
6786
7320
  try {
6787
7321
  const context = requireAuthUser(await resolveAuthContext(options, command, deps));
6788
- const core = await import("./dist-MQQKC6DZ.js");
7322
+ const core = await import("./dist-PEYJDO7A.js");
6789
7323
  const range = rangeToDates(options.range);
6790
7324
  const data = await core.getBillingUsageLedger({
6791
7325
  baseUrl: context.baseUrl,
@@ -6813,7 +7347,7 @@ var registerBillingCommands = (program2, deps) => {
6813
7347
  addCommon3(addAuthOptions(billing.command(name).description(`Show billing ${name}`), deps.defaultBaseUrl)).option("--limit <n>", "Result limit", "25").action(async (options, command) => {
6814
7348
  try {
6815
7349
  const context = requireAuthUser(await resolveAuthContext(options, command, deps));
6816
- const core = await import("./dist-MQQKC6DZ.js");
7350
+ const core = await import("./dist-PEYJDO7A.js");
6817
7351
  const data = await core[getter]({
6818
7352
  baseUrl: context.baseUrl,
6819
7353
  authToken: context.token,
@@ -6831,7 +7365,7 @@ var registerBillingCommands = (program2, deps) => {
6831
7365
  addCommon3(addAuthOptions(topups, deps.defaultBaseUrl)).option("--limit <n>", "Result limit", "25").action(async (options, command) => {
6832
7366
  try {
6833
7367
  const context = requireAuthUser(await resolveAuthContext(options, command, deps));
6834
- const core = await import("./dist-MQQKC6DZ.js");
7368
+ const core = await import("./dist-PEYJDO7A.js");
6835
7369
  const data = await core.getTopUpPacks({
6836
7370
  baseUrl: context.baseUrl,
6837
7371
  authToken: context.token
@@ -7360,12 +7894,13 @@ var getRule = async (input) => fetchCloudEvalJson({
7360
7894
 
7361
7895
  // src/telemetry.ts
7362
7896
  import os3 from "os";
7897
+ import { createHash } from "crypto";
7363
7898
 
7364
7899
  // src/telemetryConnectionString.generated.ts
7365
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";
7366
7901
 
7367
7902
  // src/telemetry.ts
7368
- var TELEMETRY_SCHEMA_VERSION = "1";
7903
+ var TELEMETRY_SCHEMA_VERSION = "2";
7369
7904
  var TRUE_VALUES = /* @__PURE__ */ new Set(["1", "true", "yes", "on"]);
7370
7905
  var FALSE_VALUES = /* @__PURE__ */ new Set(["0", "false", "no", "off"]);
7371
7906
  var PROPERTY_ALLOWLIST = /* @__PURE__ */ new Set([
@@ -7377,23 +7912,20 @@ var PROPERTY_ALLOWLIST = /* @__PURE__ */ new Set([
7377
7912
  "command",
7378
7913
  "completionShell",
7379
7914
  "completions",
7380
- "email",
7381
7915
  "errorCategory",
7382
7916
  "exitCode",
7383
- "firstName",
7384
7917
  "format",
7385
- "fullName",
7386
7918
  "installSource",
7387
7919
  "installerResult",
7388
7920
  "installerType",
7389
7921
  "interactive",
7390
- "lastName",
7391
7922
  "mcpSetup",
7392
7923
  "nodeVersion",
7393
7924
  "os",
7394
7925
  "osVersionMajor",
7395
7926
  "previousCliVersion",
7396
7927
  "requestedVersion",
7928
+ "requestId",
7397
7929
  "resolvedVersion",
7398
7930
  "runtime",
7399
7931
  "subcommand",
@@ -7403,8 +7935,10 @@ var PROPERTY_ALLOWLIST = /* @__PURE__ */ new Set([
7403
7935
  "toolName",
7404
7936
  "toolset",
7405
7937
  "targetCliVersion",
7938
+ "traceId",
7406
7939
  "tuiInitialTab",
7407
- "updateAction"
7940
+ "updateAction",
7941
+ "user_hash"
7408
7942
  ]);
7409
7943
  var MEASUREMENT_ALLOWLIST = /* @__PURE__ */ new Set(["durationMs"]);
7410
7944
  var trimString = (value) => {
@@ -7472,16 +8006,12 @@ var buildTelemetryUserProperties = (user) => {
7472
8006
  if (!user || typeof user !== "object") {
7473
8007
  return {};
7474
8008
  }
7475
- const email = trimString(user.email);
7476
- const fullName = trimString(user.fullName) || trimString(user.full_name) || trimString(user.name);
7477
- const firstName = trimString(user.firstName);
7478
- const lastName = trimString(user.lastName);
7479
- 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
+ }
7480
8013
  return {
7481
- ...email ? { email } : {},
7482
- ...firstName || nameParts[0] ? { firstName: firstName || nameParts[0] } : {},
7483
- ...lastName || nameParts.length > 1 ? { lastName: lastName || nameParts[nameParts.length - 1] } : {},
7484
- ...fullName ? { fullName } : {}
8014
+ user_hash: `h_${createHash("sha256").update("cloudeval-cli:user:").update(internalId).digest("hex").slice(0, 32)}`
7485
8015
  };
7486
8016
  };
7487
8017
  var classifyTelemetryError = (error) => {
@@ -7541,6 +8071,16 @@ var createApplicationInsightsClient = async (connectionString) => {
7541
8071
  disableDiskRetryCaching(client);
7542
8072
  return client;
7543
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
+ };
7544
8084
  var disableDiskRetryCaching = (client) => {
7545
8085
  try {
7546
8086
  client.setUseDiskRetryCaching?.(false);
@@ -7597,6 +8137,7 @@ var createCliTelemetry = async (options) => {
7597
8137
  let client;
7598
8138
  try {
7599
8139
  client = options.clientFactory ? options.clientFactory(connectionString) : await createApplicationInsightsClient(connectionString);
8140
+ setTelemetryClientRole(client);
7600
8141
  } catch {
7601
8142
  return createNoopTelemetry();
7602
8143
  }
@@ -9502,7 +10043,7 @@ var reportsFrontendUrl = (config, input) => buildFrontendUrl({
9502
10043
  reportVerbosity: input.reportVerbosity
9503
10044
  });
9504
10045
  var resolveAuth = async (config, options = {}) => {
9505
- const core = await import("./dist-MQQKC6DZ.js");
10046
+ const core = await import("./dist-PEYJDO7A.js");
9506
10047
  core.assertSecureBaseUrl(config.baseUrl);
9507
10048
  let token;
9508
10049
  try {
@@ -9598,7 +10139,7 @@ var assertModelAvailable = async (config, token) => {
9598
10139
  if (!config.model) {
9599
10140
  return;
9600
10141
  }
9601
- const core = await import("./dist-MQQKC6DZ.js");
10142
+ const core = await import("./dist-PEYJDO7A.js");
9602
10143
  try {
9603
10144
  const response = await fetch(
9604
10145
  `${core.normalizeApiBase(config.baseUrl)}/models`,
@@ -9855,7 +10396,7 @@ var buildToolHandlers = (serverOptions) => {
9855
10396
  });
9856
10397
  handlers.set("agent_profiles_list", async (args) => {
9857
10398
  const config = await resolveInvocationConfig(serverOptions, args);
9858
- const core = await import("./dist-MQQKC6DZ.js");
10399
+ const core = await import("./dist-PEYJDO7A.js");
9859
10400
  const data = await listProfilesForDiscovery(core, config.baseUrl);
9860
10401
  return withEnvelope({
9861
10402
  command: "agents list",
@@ -9868,7 +10409,7 @@ var buildToolHandlers = (serverOptions) => {
9868
10409
  throw new Error("profileId is required.");
9869
10410
  }
9870
10411
  const config = await resolveInvocationConfig(serverOptions, args);
9871
- const core = await import("./dist-MQQKC6DZ.js");
10412
+ const core = await import("./dist-PEYJDO7A.js");
9872
10413
  const data = await getProfileForDiscovery(core, config.baseUrl, profileId);
9873
10414
  return withEnvelope({
9874
10415
  command: "agents show",
@@ -10505,7 +11046,7 @@ var buildToolHandlers = (serverOptions) => {
10505
11046
  });
10506
11047
  handlers.set("auth_status", async (args) => {
10507
11048
  const config = await resolveInvocationConfig(serverOptions, args);
10508
- const core = await import("./dist-MQQKC6DZ.js");
11049
+ const core = await import("./dist-PEYJDO7A.js");
10509
11050
  const data = await core.getAuthStatus(config.baseUrl, { validate: true });
10510
11051
  return withEnvelope({
10511
11052
  command: "auth status",
@@ -10514,7 +11055,7 @@ var buildToolHandlers = (serverOptions) => {
10514
11055
  });
10515
11056
  handlers.set("status", async (args) => {
10516
11057
  const config = await resolveInvocationConfig(serverOptions, args);
10517
- const core = await import("./dist-MQQKC6DZ.js");
11058
+ const core = await import("./dist-PEYJDO7A.js");
10518
11059
  const auth = await core.getAuthStatus(config.baseUrl, { validate: true });
10519
11060
  return withEnvelope({
10520
11061
  command: "status",
@@ -10545,7 +11086,7 @@ var buildToolHandlers = (serverOptions) => {
10545
11086
  }
10546
11087
  ];
10547
11088
  try {
10548
- const core = await import("./dist-MQQKC6DZ.js");
11089
+ const core = await import("./dist-PEYJDO7A.js");
10549
11090
  core.assertSecureBaseUrl(config.baseUrl);
10550
11091
  checks.push({
10551
11092
  id: "base-url-secure",
@@ -11065,7 +11606,7 @@ var buildToolHandlers = (serverOptions) => {
11065
11606
  } catch {
11066
11607
  token = config.accessKey;
11067
11608
  }
11068
- const core = await import("./dist-MQQKC6DZ.js");
11609
+ const core = await import("./dist-PEYJDO7A.js");
11069
11610
  const data = await core.getBillingConfig({
11070
11611
  baseUrl: config.baseUrl,
11071
11612
  authToken: token
@@ -11919,7 +12460,7 @@ var registerCapabilitiesCommand = (program2, deps) => {
11919
12460
  warnIfAccessKeyFromCliOption(options, command);
11920
12461
  let data = capabilities;
11921
12462
  if (options.live) {
11922
- const core = await import("./dist-MQQKC6DZ.js");
12463
+ const core = await import("./dist-PEYJDO7A.js");
11923
12464
  const baseUrl = await deps.resolveBaseUrl(options, command);
11924
12465
  const accessKey = options.accessKeyStdin ? await deps.readStdinValue() : options.accessKey;
11925
12466
  const token = await core.getAuthToken({ accessKey, baseUrl });
@@ -12057,7 +12598,7 @@ var writeCredentialOutput = async (input) => {
12057
12598
  };
12058
12599
  var resolveCoreAuth = async (options, command, deps) => {
12059
12600
  const context = await resolveAuthContext(options, command, deps);
12060
- const core = await import("./dist-MQQKC6DZ.js");
12601
+ const core = await import("./dist-PEYJDO7A.js");
12061
12602
  return { ...context, core };
12062
12603
  };
12063
12604
  var parseCapabilities = (value) => value?.split(",").map((item) => item.trim()).filter(Boolean);
@@ -12374,7 +12915,7 @@ var registerAgentsCommand = (program2, deps) => {
12374
12915
  const agents = program2.command("agents").description("CloudEval Agent Profile utilities");
12375
12916
  addAgentOutputOptions(agents.command("list").description("List Agent Profiles"), deps).action(async (options, command) => {
12376
12917
  const baseUrl = await deps.resolveBaseUrl(options, command);
12377
- const core = await import("./dist-MQQKC6DZ.js");
12918
+ const core = await import("./dist-PEYJDO7A.js");
12378
12919
  core.assertSecureBaseUrl(baseUrl);
12379
12920
  const data = await listProfilesForDiscovery2(core, baseUrl);
12380
12921
  await writeProfiles({
@@ -12390,7 +12931,7 @@ var registerAgentsCommand = (program2, deps) => {
12390
12931
  deps
12391
12932
  ).action(async (profileId, options, command) => {
12392
12933
  const baseUrl = await deps.resolveBaseUrl(options, command);
12393
- const core = await import("./dist-MQQKC6DZ.js");
12934
+ const core = await import("./dist-PEYJDO7A.js");
12394
12935
  core.assertSecureBaseUrl(baseUrl);
12395
12936
  const data = await getProfileForDiscovery2(core, baseUrl, profileId);
12396
12937
  await writeProfiles({
@@ -12409,7 +12950,7 @@ var registerAgentsCommand = (program2, deps) => {
12409
12950
  const cliProfile = getActiveConfigProfile(command);
12410
12951
  const cliConfig = await loadCliConfig(cliProfile);
12411
12952
  const auth = await resolveAuthContext(options, command, deps);
12412
- const core = await import("./dist-MQQKC6DZ.js");
12953
+ const core = await import("./dist-PEYJDO7A.js");
12413
12954
  const profileResponse = await core.getAgentProfile({
12414
12955
  baseUrl: auth.baseUrl,
12415
12956
  authToken: auth.token,
@@ -12907,7 +13448,7 @@ var registerDiagnosticsCommands = (program2, deps) => {
12907
13448
  const baseUrl = await deps.resolveBaseUrl(options, command);
12908
13449
  const profile = getActiveConfigProfile(command);
12909
13450
  const config = await loadCliConfig(profile);
12910
- const core = await import("./dist-MQQKC6DZ.js");
13451
+ const core = await import("./dist-PEYJDO7A.js");
12911
13452
  const auth = await core.getAuthStatus(baseUrl, { validate: true });
12912
13453
  if (options.format === "text" || !options.format) {
12913
13454
  process.stdout.write(
@@ -12957,7 +13498,7 @@ var registerDiagnosticsCommands = (program2, deps) => {
12957
13498
  detail: getCliConfigPath(profile)
12958
13499
  });
12959
13500
  try {
12960
- const core = await import("./dist-MQQKC6DZ.js");
13501
+ const core = await import("./dist-PEYJDO7A.js");
12961
13502
  core.assertSecureBaseUrl(baseUrl);
12962
13503
  checks.push({
12963
13504
  id: "base-url-secure",
@@ -13057,7 +13598,7 @@ var resolveToken2 = async (options, deps, baseUrl, command) => {
13057
13598
  return options.accessKey;
13058
13599
  }
13059
13600
  try {
13060
- const core = await import("./dist-MQQKC6DZ.js");
13601
+ const core = await import("./dist-PEYJDO7A.js");
13061
13602
  return await core.getAuthToken({
13062
13603
  baseUrl
13063
13604
  });
@@ -13141,7 +13682,7 @@ var registerModelsCommand = (program2, deps) => {
13141
13682
  let source = "fallback";
13142
13683
  let modelList = fallbackModels;
13143
13684
  try {
13144
- const core = await import("./dist-MQQKC6DZ.js");
13685
+ const core = await import("./dist-PEYJDO7A.js");
13145
13686
  const response = await fetch(`${core.normalizeApiBase(baseUrl)}/models`, {
13146
13687
  headers: {
13147
13688
  Accept: "application/json",
@@ -14320,7 +14861,7 @@ var uninstallCompletionScript = async (shell) => {
14320
14861
  var runInteractiveLoginOnboarding = async (baseUrl, token) => {
14321
14862
  const [{ render }, { Onboarding }] = await Promise.all([
14322
14863
  import("ink"),
14323
- import("./Onboarding-CORIICF5.js")
14864
+ import("./Onboarding-GAN3Q5TS.js")
14324
14865
  ]);
14325
14866
  await new Promise((resolve) => {
14326
14867
  let app;
@@ -14586,7 +15127,13 @@ var getActiveCliTelemetry = () => activeTelemetry;
14586
15127
  var initializeCommandTelemetry = async (actionCommand, options) => {
14587
15128
  activeTelemetryStartedAt = Date.now();
14588
15129
  activeTelemetryFinished = false;
14589
- 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
+ };
14590
15137
  const config = await resolveCliConfig(actionCommand);
14591
15138
  activeTelemetry = await createCliTelemetry({
14592
15139
  config,
@@ -14595,27 +15142,33 @@ var initializeCommandTelemetry = async (actionCommand, options) => {
14595
15142
  };
14596
15143
  var finishCommandTelemetry = async (exitCode, error) => {
14597
15144
  if (!activeTelemetry || activeTelemetryFinished) {
15145
+ clearActiveCLITraceContext();
14598
15146
  return;
14599
15147
  }
14600
15148
  activeTelemetryFinished = true;
14601
15149
  const durationMs = Math.max(0, Date.now() - activeTelemetryStartedAt);
14602
- if (error) {
14603
- 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", {
14604
15161
  ...activeTelemetryProperties,
14605
15162
  durationMs,
14606
15163
  exitCode,
14607
- success: false,
14608
- errorCategory: classifyTelemetryError(error)
15164
+ success: exitCode === 0,
15165
+ ...error ? { errorCategory: classifyTelemetryError(error) } : {}
14609
15166
  });
15167
+ await activeTelemetry.flush();
15168
+ } finally {
15169
+ clearActiveCLITraceContext();
15170
+ activeTelemetry = void 0;
14610
15171
  }
14611
- await activeTelemetry.track("cli.command", {
14612
- ...activeTelemetryProperties,
14613
- durationMs,
14614
- exitCode,
14615
- success: exitCode === 0,
14616
- ...error ? { errorCategory: classifyTelemetryError(error) } : {}
14617
- });
14618
- await activeTelemetry.flush();
14619
15172
  };
14620
15173
  var exitCli = async (exitCode, error) => {
14621
15174
  await finishCommandTelemetry(exitCode, error);
@@ -14642,7 +15195,7 @@ var resolveBaseUrl = async (options, command) => {
14642
15195
  });
14643
15196
  }
14644
15197
  try {
14645
- const { getAuthStatus } = await import("./dist-MQQKC6DZ.js");
15198
+ const { getAuthStatus } = await import("./dist-PEYJDO7A.js");
14646
15199
  const status = await getAuthStatus();
14647
15200
  const storedBaseUrl = status.baseUrl;
14648
15201
  if (storedBaseUrl && shouldUseStoredBaseUrl(storedBaseUrl)) {
@@ -14716,7 +15269,7 @@ program.command("login").description("Authenticate with Cloudeval").option(
14716
15269
  checkUserStatus,
14717
15270
  ensurePlaygroundProject,
14718
15271
  login
14719
- } = await import("./dist-MQQKC6DZ.js");
15272
+ } = await import("./dist-PEYJDO7A.js");
14720
15273
  assertSecureBaseUrl(options.baseUrl);
14721
15274
  const headlessEnvironment = isHeadlessEnvironment();
14722
15275
  const headlessLogin = options.headless || headlessEnvironment;
@@ -14791,7 +15344,7 @@ program.command("logout").description("Log out and clear stored authentication s
14791
15344
  DEFAULT_BASE_URL
14792
15345
  ).option("--all-devices", "Revoke sessions on all devices", false).action(async (options) => {
14793
15346
  try {
14794
- const { assertSecureBaseUrl, logout } = await import("./dist-MQQKC6DZ.js");
15347
+ const { assertSecureBaseUrl, logout } = await import("./dist-PEYJDO7A.js");
14795
15348
  assertSecureBaseUrl(options.baseUrl);
14796
15349
  const result = await logout({
14797
15350
  baseUrl: options.baseUrl,
@@ -14825,7 +15378,7 @@ authCommand.command("status").description("Show current authentication status").
14825
15378
  DEFAULT_BASE_URL
14826
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) => {
14827
15380
  try {
14828
- const { assertSecureBaseUrl, getAuthStatus } = await import("./dist-MQQKC6DZ.js");
15381
+ const { assertSecureBaseUrl, getAuthStatus } = await import("./dist-PEYJDO7A.js");
14829
15382
  const effectiveBaseUrl = await resolveBaseUrl(options, command);
14830
15383
  assertSecureBaseUrl(effectiveBaseUrl);
14831
15384
  const status = await getAuthStatus(effectiveBaseUrl, { validate: true });
@@ -15042,10 +15595,10 @@ program.command("tui").description("Open the CloudEval Terminal UI").option(
15042
15595
  "Access key for automation",
15043
15596
  process.env.CLOUDEVAL_ACCESS_KEY
15044
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) => {
15045
- const { assertSecureBaseUrl } = await import("./dist-MQQKC6DZ.js");
15598
+ const { assertSecureBaseUrl } = await import("./dist-PEYJDO7A.js");
15046
15599
  const [{ render }, { App }] = await Promise.all([
15047
15600
  import("ink"),
15048
- import("./App-RQYQISZ6.js")
15601
+ import("./App-H7B3T5QW.js")
15049
15602
  ]);
15050
15603
  const baseUrl = await resolveBaseUrl(options, command);
15051
15604
  assertSecureBaseUrl(baseUrl);
@@ -15100,10 +15653,10 @@ program.command("chat").description("Start an interactive chat session").option(
15100
15653
  "Access key for automation",
15101
15654
  process.env.CLOUDEVAL_ACCESS_KEY
15102
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) => {
15103
- const { assertSecureBaseUrl } = await import("./dist-MQQKC6DZ.js");
15656
+ const { assertSecureBaseUrl } = await import("./dist-PEYJDO7A.js");
15104
15657
  const [{ render }, { App }] = await Promise.all([
15105
15658
  import("ink"),
15106
- import("./App-RQYQISZ6.js")
15659
+ import("./App-H7B3T5QW.js")
15107
15660
  ]);
15108
15661
  const baseUrl = await resolveBaseUrl(options, command);
15109
15662
  assertSecureBaseUrl(baseUrl);
@@ -15178,7 +15731,7 @@ program.command("ask").alias("agent").description("Ask a single question or run
15178
15731
  const question = Array.isArray(questionParts) ? questionParts.join(" ") : String(questionParts);
15179
15732
  const commandName = command.parent?.args?.[0] === "agent" ? "agent" : "ask";
15180
15733
  const selectedMode = commandName === "agent" ? "agent" : "ask";
15181
- const { assertSecureBaseUrl } = await import("./dist-MQQKC6DZ.js");
15734
+ const { assertSecureBaseUrl } = await import("./dist-PEYJDO7A.js");
15182
15735
  const baseUrl = await resolveBaseUrl(options, command);
15183
15736
  assertSecureBaseUrl(baseUrl);
15184
15737
  const selectedProfile = getActiveConfigProfile(command);
@@ -15219,7 +15772,7 @@ program.command("ask").alias("agent").description("Ask a single question or run
15219
15772
  const fs14 = await import("fs");
15220
15773
  const fsPromises = await import("fs/promises");
15221
15774
  const { randomUUID: randomUUID5 } = await import("crypto");
15222
- const core = await import("./dist-MQQKC6DZ.js");
15775
+ const core = await import("./dist-PEYJDO7A.js");
15223
15776
  const {
15224
15777
  streamChat,
15225
15778
  reduceChunk,
@@ -15275,7 +15828,7 @@ program.command("ask").alias("agent").description("Ask a single question or run
15275
15828
  console.error("Authentication required. Starting login process...\n");
15276
15829
  }
15277
15830
  try {
15278
- const { login } = await import("./dist-MQQKC6DZ.js");
15831
+ const { login } = await import("./dist-PEYJDO7A.js");
15279
15832
  verboseLog("Calling interactive login", { baseUrl });
15280
15833
  token = await login(baseUrl, {
15281
15834
  headless: isHeadlessEnvironment()
@@ -15339,7 +15892,7 @@ program.command("ask").alias("agent").description("Ask a single question or run
15339
15892
  message: error.message
15340
15893
  });
15341
15894
  }
15342
- const { resolveAskProject } = await import("./resolveAskProject-KQKI5GRT.js");
15895
+ const { resolveAskProject } = await import("./resolveAskProject-DQJXPS5G.js");
15343
15896
  let project;
15344
15897
  try {
15345
15898
  project = await resolveAskProject({
@@ -15857,7 +16410,7 @@ Error: ${errorMsg}
15857
16410
  program.command("banner").description("Preview the startup banner and terminal capabilities").action(async () => {
15858
16411
  const { render } = await import("ink");
15859
16412
  const BannerPreview = React.lazy(async () => ({
15860
- default: (await import("./Banner-AMIGQPVN.js")).Banner
16413
+ default: (await import("./Banner-MOLW4ADA.js")).Banner
15861
16414
  }));
15862
16415
  render(
15863
16416
  /* @__PURE__ */ jsx(React.Suspense, { fallback: null, children: /* @__PURE__ */ jsx(BannerPreview, { disable: false }) })