agentic-ui-libs 1.2.0-beta.20 → 1.2.0-beta.22

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.
Files changed (32) hide show
  1. package/dist/assets/agentic-ui-libs.css +73 -0
  2. package/dist/features/dashboard/AnalyticsChart.d.ts.map +1 -1
  3. package/dist/features/dashboard/Dashboard.d.ts.map +1 -1
  4. package/dist/features/dashboard/DashboardSection.d.ts.map +1 -1
  5. package/dist/features/dashboard/MetricCard.d.ts.map +1 -1
  6. package/dist/features/dashboard/ModelListView.d.ts +1 -0
  7. package/dist/features/dashboard/ModelListView.d.ts.map +1 -1
  8. package/dist/features/dashboard/ToolListView.d.ts.map +1 -1
  9. package/dist/features/debug-logs/services/TreeBuilder.d.ts +9 -0
  10. package/dist/features/debug-logs/services/TreeBuilder.d.ts.map +1 -1
  11. package/dist/features/tracing/components/SessionsList.d.ts.map +1 -1
  12. package/dist/features/tracing/components/detail/DetailPage.d.ts +1 -1
  13. package/dist/features/tracing/components/detail/DetailPage.d.ts.map +1 -1
  14. package/dist/features/tracing/components/detail/EventLogsSlideout.d.ts +58 -0
  15. package/dist/features/tracing/components/detail/EventLogsSlideout.d.ts.map +1 -0
  16. package/dist/features/tracing/components/detail/VoiceEventLogsBanner.d.ts +11 -0
  17. package/dist/features/tracing/components/detail/VoiceEventLogsBanner.d.ts.map +1 -0
  18. package/dist/features/tracing/components/detail/index.d.ts +2 -0
  19. package/dist/features/tracing/components/detail/index.d.ts.map +1 -1
  20. package/dist/features/tracing/components/detail/services/DetailPageService.d.ts +1 -0
  21. package/dist/features/tracing/components/detail/services/DetailPageService.d.ts.map +1 -1
  22. package/dist/features/tracing/components/detail/types.d.ts +19 -0
  23. package/dist/features/tracing/components/detail/types.d.ts.map +1 -1
  24. package/dist/features/tracing/types.d.ts +11 -0
  25. package/dist/features/tracing/types.d.ts.map +1 -1
  26. package/dist/index.js +1253 -373
  27. package/dist/lib/dashboard-api.service.d.ts +1 -0
  28. package/dist/lib/dashboard-api.service.d.ts.map +1 -1
  29. package/dist/shared/types/index.d.ts +7 -0
  30. package/dist/shared/types/index.d.ts.map +1 -1
  31. package/dist/ui-libs.umd.js +1253 -373
  32. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -4291,7 +4291,7 @@ const MetricCard = ({
4291
4291
  onClick,
4292
4292
  isFirst = false
4293
4293
  }) => {
4294
- const { title, value, change, info, highlighted } = data;
4294
+ const { title, value, change, info, highlighted, failedCount } = data;
4295
4295
  const formatValue2 = (val) => {
4296
4296
  if (typeof val === "number") {
4297
4297
  return val.toLocaleString();
@@ -4345,6 +4345,11 @@ const MetricCard = ({
4345
4345
  ] }),
4346
4346
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-baseline gap-3", "data-test-id": `dashboard_metric_card_value_container_${data.metricType || data.title.toLowerCase().replace(/\s+/g, "_")}`, children: [
4347
4347
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-2xl font-semibold text-gray-900", "data-test-id": `dashboard_metric_card_value_${data.metricType || data.title.toLowerCase().replace(/\s+/g, "_")}`, children: formatValue2(value) }),
4348
+ (failedCount ?? 0) > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs font-medium text-red-500", "data-test-id": `dashboard_metric_card_failed_${data.metricType}`, children: [
4349
+ "(",
4350
+ failedCount,
4351
+ " failed)"
4352
+ ] }),
4348
4353
  change && /* @__PURE__ */ jsxRuntimeExports.jsxs(
4349
4354
  "div",
4350
4355
  {
@@ -21355,7 +21360,7 @@ function _toPrimitive$g(t2, r2) {
21355
21360
  if ("object" != _typeof$i(i2)) return i2;
21356
21361
  throw new TypeError("@@toPrimitive must return a primitive value.");
21357
21362
  }
21358
- return ("string" === r2 ? String : Number)(t2);
21363
+ return String(t2);
21359
21364
  }
21360
21365
  var Bar = /* @__PURE__ */ function(_PureComponent) {
21361
21366
  function Bar2() {
@@ -28662,7 +28667,7 @@ const CustomTooltip = ({
28662
28667
  return null;
28663
28668
  }
28664
28669
  const filteredPayload = payload.filter(
28665
- (entry) => entry.name && entry.name !== "" && entry.name !== entry.dataKey
28670
+ (entry) => entry.name && entry.name !== "" && entry.name !== entry.dataKey && entry.value != null && !(typeof entry.value === "number" && Number.isNaN(entry.value)) && !(entry.dataKey === "failedModelRuns" && Number(entry.value) === 0)
28666
28671
  );
28667
28672
  if (filteredPayload.length === 0) {
28668
28673
  return null;
@@ -28762,6 +28767,7 @@ const AnalyticsChart = ({
28762
28767
  agentRuns: 0,
28763
28768
  toolRuns: 0,
28764
28769
  modelRuns: 0,
28770
+ failedModelRuns: null,
28765
28771
  codeTools: 0,
28766
28772
  workflowTools: 0,
28767
28773
  knowledgeTools: 0,
@@ -28864,6 +28870,8 @@ const AnalyticsChart = ({
28864
28870
  label: config2.title,
28865
28871
  strokeWidth: 2
28866
28872
  }];
28873
+ const lineSeries = chartLines.filter((c3) => (c3.seriesType ?? "line") === "line");
28874
+ const barSeries = chartLines.filter((c3) => c3.seriesType === "bar");
28867
28875
  if (isLoading) {
28868
28876
  console.log("AnalyticsChart: Loading state active");
28869
28877
  return /* @__PURE__ */ jsxRuntimeExports.jsx(ChartSkeleton, { className, chartType: config2.type, height });
@@ -28970,7 +28978,7 @@ const AnalyticsChart = ({
28970
28978
  bottom: 20
28971
28979
  },
28972
28980
  children: [
28973
- /* @__PURE__ */ jsxRuntimeExports.jsx("defs", { children: chartLines.map((lineConfig, index) => /* @__PURE__ */ jsxRuntimeExports.jsxs("linearGradient", { id: `gradient-${lineConfig.dataKey}`, x1: "0", y1: "0", x2: "0", y2: "1", children: [
28981
+ /* @__PURE__ */ jsxRuntimeExports.jsx("defs", { children: lineSeries.map((lineConfig, index) => /* @__PURE__ */ jsxRuntimeExports.jsxs("linearGradient", { id: `gradient-${lineConfig.dataKey}`, x1: "0", y1: "0", x2: "0", y2: "1", children: [
28974
28982
  /* @__PURE__ */ jsxRuntimeExports.jsx("stop", { offset: "5%", stopColor: lineConfig.color, stopOpacity: 0.08 }),
28975
28983
  /* @__PURE__ */ jsxRuntimeExports.jsx("stop", { offset: "95%", stopColor: lineConfig.color, stopOpacity: 0.01 })
28976
28984
  ] }, `gradient-${index}`)) }),
@@ -29022,7 +29030,7 @@ const AnalyticsChart = ({
29022
29030
  allowEscapeViewBox: { x: false, y: false }
29023
29031
  }
29024
29032
  ),
29025
- chartLines.map((lineConfig) => /* @__PURE__ */ jsxRuntimeExports.jsx(
29033
+ lineSeries.map((lineConfig) => /* @__PURE__ */ jsxRuntimeExports.jsx(
29026
29034
  Area,
29027
29035
  {
29028
29036
  type: "monotone",
@@ -29030,12 +29038,13 @@ const AnalyticsChart = ({
29030
29038
  stroke: "none",
29031
29039
  fill: `url(#gradient-${lineConfig.dataKey})`,
29032
29040
  fillOpacity: 1,
29041
+ connectNulls: false,
29033
29042
  isAnimationActive: false,
29034
29043
  name: ""
29035
29044
  },
29036
29045
  `area-${lineConfig.dataKey}`
29037
29046
  )),
29038
- chartLines.map((lineConfig) => /* @__PURE__ */ jsxRuntimeExports.jsx(
29047
+ lineSeries.map((lineConfig) => /* @__PURE__ */ jsxRuntimeExports.jsx(
29039
29048
  Line,
29040
29049
  {
29041
29050
  type: "monotone",
@@ -29043,6 +29052,7 @@ const AnalyticsChart = ({
29043
29052
  stroke: lineConfig.color,
29044
29053
  strokeWidth: 2.5,
29045
29054
  strokeDasharray: lineConfig.strokeDasharray,
29055
+ connectNulls: false,
29046
29056
  dot: false,
29047
29057
  activeDot: {
29048
29058
  r: 5,
@@ -29053,6 +29063,19 @@ const AnalyticsChart = ({
29053
29063
  name: lineConfig.label
29054
29064
  },
29055
29065
  lineConfig.dataKey
29066
+ )),
29067
+ barSeries.map((lineConfig) => /* @__PURE__ */ jsxRuntimeExports.jsx(
29068
+ Bar,
29069
+ {
29070
+ dataKey: lineConfig.dataKey,
29071
+ fill: lineConfig.color,
29072
+ fillOpacity: 0.9,
29073
+ name: lineConfig.label,
29074
+ maxBarSize: 14,
29075
+ radius: [3, 3, 0, 0],
29076
+ isAnimationActive: false
29077
+ },
29078
+ `bar-${lineConfig.dataKey}`
29056
29079
  ))
29057
29080
  ]
29058
29081
  }
@@ -29074,8 +29097,15 @@ const AnalyticsChart = ({
29074
29097
  })
29075
29098
  ] })
29076
29099
  ] }) }),
29077
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-4", "data-test-id": "dashboard_analytics_chart_legend", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-4 text-sm text-muted-foreground", "data-test-id": "dashboard_analytics_chart_legend_items", children: chartLines.map((lineConfig) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", "data-test-id": `dashboard_analytics_chart_legend_item_${lineConfig.dataKey}`, children: [
29078
- /* @__PURE__ */ jsxRuntimeExports.jsx(
29100
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-4", "data-test-id": "dashboard_analytics_chart_legend", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-4 text-sm text-muted-foreground", "data-test-id": "dashboard_analytics_chart_legend_items", children: chartLines.filter((lineConfig) => !lineConfig.hideInLegend).map((lineConfig) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", "data-test-id": `dashboard_analytics_chart_legend_item_${lineConfig.dataKey}`, children: [
29101
+ lineConfig.seriesType === "bar" ? /* @__PURE__ */ jsxRuntimeExports.jsx(
29102
+ "div",
29103
+ {
29104
+ className: "w-2 h-2 rounded-[2px]",
29105
+ style: { backgroundColor: lineConfig.color },
29106
+ "data-test-id": `dashboard_analytics_chart_legend_color_${lineConfig.dataKey}`
29107
+ }
29108
+ ) : /* @__PURE__ */ jsxRuntimeExports.jsx(
29079
29109
  "div",
29080
29110
  {
29081
29111
  className: "w-[8px] h-[8px] rounded-full",
@@ -29632,6 +29662,8 @@ function getToolTypeStyle(type) {
29632
29662
  return "bg-green-100 text-green-800 border-green-200";
29633
29663
  if (["knowledge", "KNOWLEDGE", "knowledge tool"].includes(type) || ["knowledge", "knowledge tool"].includes(normalized))
29634
29664
  return "bg-purple-100 text-purple-800 border-purple-200";
29665
+ if (["PRE_PROCESSOR", "POST_PROCESSOR", "INPUT_PROCESSOR", "input_processor", "pre_processor", "post_processor", "processor"].includes(type) || ["pre_processor", "post_processor", "processor", "input_processor"].includes(normalized))
29666
+ return "bg-yellow-100 text-yellow-800 border-yellow-200";
29635
29667
  return "bg-gray-100 text-gray-800 border-gray-200";
29636
29668
  }
29637
29669
  function getToolTypeName(type) {
@@ -29640,6 +29672,8 @@ function getToolTypeName(type) {
29640
29672
  if (["toollibrary", "workflow tool"].includes(normalized)) return "Workflow Tool";
29641
29673
  if (["mcp", "mcptool"].includes(normalized)) return "MCP Tool";
29642
29674
  if (["knowledge", "knowledge tool", "knowledge"].includes(normalized) || type === "KNOWLEDGE") return "Knowledge";
29675
+ if (["pre_processor", "post_processor", "processor", "input_processor"].includes(normalized) || type === "PRE_PROCESSOR" || type === "POST_PROCESSOR" || type === "INPUT_PROCESSOR" || type === "input_processor")
29676
+ return "Processor";
29643
29677
  if (type === "inlineTool") return "Code Tool";
29644
29678
  if (type === "toolLibrary") return "Workflow Tool";
29645
29679
  if (type === "KNOWLEDGE") return "Knowledge";
@@ -29866,7 +29900,14 @@ const ModelListView = ({
29866
29900
  model.provider && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-gray-500 truncate", "data-test-id": `dashboard_model_list_view_row_provider_${index}`, children: getProviderDisplayName(model.provider) })
29867
29901
  ] })
29868
29902
  ] }),
29869
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-center font-medium text-xs text-gray-700", "data-test-id": `dashboard_model_list_view_row_runs_${index}`, children: formatValue2(model.runs || 0) }),
29903
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center font-medium text-xs text-gray-700 flex items-center justify-center gap-1", "data-test-id": `dashboard_model_list_view_row_runs_${index}`, children: [
29904
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: formatValue2(model.runs || 0) }),
29905
+ (model.failedRuns ?? 0) > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-red-500 text-[10px] font-medium", "data-test-id": `dashboard_model_list_view_row_failed_${index}`, children: [
29906
+ "(",
29907
+ model.failedRuns,
29908
+ " failed)"
29909
+ ] })
29910
+ ] }),
29870
29911
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-center font-medium text-xs text-gray-700", "data-test-id": `dashboard_model_list_view_row_tokens_${index}`, children: formatValue2(model.tokens || model.totalTokens || 0) }),
29871
29912
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-center font-medium text-xs text-gray-700", "data-test-id": `dashboard_model_list_view_row_response_time_${index}`, children: model.responseTime || (model.avgResponseTime ? `${model.avgResponseTime}ms` : "N/A") })
29872
29913
  ]
@@ -30546,6 +30587,7 @@ class DashboardApiService {
30546
30587
  {
30547
30588
  title: "Model Runs",
30548
30589
  value: data.data.modelRuns,
30590
+ failedCount: data.data.failedModelRuns || 0,
30549
30591
  metricType: "modelRuns",
30550
30592
  icon: "cpu",
30551
30593
  info: "Number of times the AI agents called various language models to generate responses",
@@ -30622,8 +30664,12 @@ class DashboardApiService {
30622
30664
  basePoint.toolRuns = point2.count || 0;
30623
30665
  break;
30624
30666
  case "modelRuns":
30667
+ case "modelruns": {
30668
+ const failed = point2.failedModelRuns;
30625
30669
  basePoint.modelRuns = point2.count || 0;
30670
+ basePoint.failedModelRuns = typeof failed === "number" && failed >= 0 ? failed : 0;
30626
30671
  break;
30672
+ }
30627
30673
  default:
30628
30674
  basePoint.users = point2.count || 0;
30629
30675
  basePoint.sessions = point2.count || 0;
@@ -30632,6 +30678,10 @@ class DashboardApiService {
30632
30678
  basePoint.agentRuns = point2.count || 0;
30633
30679
  basePoint.toolRuns = point2.count || 0;
30634
30680
  basePoint.modelRuns = point2.count || 0;
30681
+ {
30682
+ const failed = point2.failedModelRuns;
30683
+ basePoint.failedModelRuns = typeof failed === "number" && failed >= 0 ? failed : 0;
30684
+ }
30635
30685
  }
30636
30686
  console.log(`Transformed point ${index} for metric ${metricType}:`, basePoint);
30637
30687
  return basePoint;
@@ -30716,22 +30766,16 @@ class DashboardApiService {
30716
30766
  id: `model-${index + 1}`,
30717
30767
  name: item.connectionName ? `${item.modelName} - ${item.connectionName}` : item.modelName || `Model ${index + 1}`,
30718
30768
  modelName: item.modelName,
30719
- // Keep original modelName field
30720
30769
  provider: item.provider,
30721
- // Include provider information
30722
30770
  runs: item.count || 0,
30771
+ failedRuns: item.failedRuns || 0,
30723
30772
  responseTime: item.avgResponseTime ? item.avgResponseTime < 1e3 ? `${Math.round(item.avgResponseTime)}ms` : `${(item.avgResponseTime / 1e3).toFixed(2)}s` : "0ms",
30724
30773
  avgResponseTime: item.avgResponseTime,
30725
- // Keep original avgResponseTime
30726
30774
  tokens: item.tokens || item.totalTokens || Math.floor((item.count || 0) * 300),
30727
- // Use actual token data when available
30728
30775
  totalTokens: item.totalTokens || item.tokens,
30729
- // Include totalTokens field
30730
30776
  successRate: item.successRate ? `${Math.round(item.successRate)}%` : "98%",
30731
- // Default success rate for models
30732
30777
  lastRun: item.lastRun || new Date(Date.now() - Math.random() * 7 * 24 * 60 * 60 * 1e3).toLocaleDateString(),
30733
30778
  icon: item.icon
30734
- // Preserve original icon data if available
30735
30779
  }));
30736
30780
  }
30737
30781
  // Extract control options from listView data for agents
@@ -30785,9 +30829,11 @@ class DashboardApiService {
30785
30829
  if (["toollibrary", "workflow tool"].includes(normalized)) return "Workflow Tool";
30786
30830
  if (["mcp", "mcptool"].includes(normalized)) return "MCP Tool";
30787
30831
  if (["knowledge", "knowledge tool"].includes(normalized) || toolType === "KNOWLEDGE") return "Knowledge";
30832
+ if (["pre_processor", "post_processor", "processor", "input_processor"].includes(normalized)) return "Processor";
30788
30833
  if (toolType === "inlineTool") return "Code Tool";
30789
30834
  if (toolType === "toolLibrary") return "Workflow Tool";
30790
30835
  if (toolType === "MCP" || toolType === "mcpTool") return "MCP Tool";
30836
+ if (toolType === "PRE_PROCESSOR" || toolType === "POST_PROCESSOR" || toolType === "INPUT_PROCESSOR" || toolType === "input_processor") return "Processor";
30791
30837
  return "Code Tool";
30792
30838
  };
30793
30839
  options.push({
@@ -30914,6 +30960,7 @@ class DashboardApiService {
30914
30960
  if (aggregated.has(key)) {
30915
30961
  const existing = aggregated.get(key);
30916
30962
  existing.count = (existing.count || 0) + (item.count || 0);
30963
+ existing.failedRuns = (existing.failedRuns || 0) + (item.failedRuns || 0);
30917
30964
  existing.avgResponseTime = existing.avgResponseTime && item.avgResponseTime ? (existing.avgResponseTime + item.avgResponseTime) / 2 : existing.avgResponseTime || item.avgResponseTime;
30918
30965
  existing.tokens = (existing.tokens || 0) + (item.tokens || 0);
30919
30966
  } else {
@@ -30925,11 +30972,24 @@ class DashboardApiService {
30925
30972
  // Batch fetch enhanced data for all metrics with table and control data
30926
30973
  async fetchEnhancedMetricsData(fromTimestamp, toTimestamp, timeDimension, filters = []) {
30927
30974
  try {
30928
- const [agentsData, toolsData, modelsData] = await Promise.all([
30975
+ const results = await Promise.allSettled([
30929
30976
  this.fetchTimeSeriesDataWithTableData("agent-runs", "runs", fromTimestamp, toTimestamp, timeDimension, filters),
30930
30977
  this.fetchTimeSeriesDataWithTableData("tool-runs", "runs", fromTimestamp, toTimestamp, timeDimension, filters),
30931
30978
  this.fetchTimeSeriesDataWithTableData("model-runs", "runs", fromTimestamp, toTimestamp, timeDimension, filters)
30932
30979
  ]);
30980
+ if (results[0].status === "rejected") {
30981
+ console.error("Error fetching agent runs enhanced data:", results[0].reason);
30982
+ }
30983
+ if (results[1].status === "rejected") {
30984
+ console.error("Error fetching tool runs enhanced data:", results[1].reason);
30985
+ }
30986
+ if (results[2].status === "rejected") {
30987
+ console.error("Error fetching model runs enhanced data:", results[2].reason);
30988
+ }
30989
+ const emptyData = { chartData: [], tableData: [], controlOptions: [] };
30990
+ const agentsData = results[0].status === "fulfilled" ? results[0].value : emptyData;
30991
+ const toolsData = results[1].status === "fulfilled" ? results[1].value : emptyData;
30992
+ const modelsData = results[2].status === "fulfilled" ? results[2].value : emptyData;
30933
30993
  return {
30934
30994
  agents: agentsData,
30935
30995
  tools: toolsData,
@@ -30946,13 +31006,30 @@ class DashboardApiService {
30946
31006
  const getChangeType = (changePercent) => {
30947
31007
  return changePercent > 0 ? "increase" : "decrease";
30948
31008
  };
30949
- const [agentsData, toolsData, modelsData, toolRunsTimeSeriesData] = await Promise.all([
31009
+ const results = await Promise.allSettled([
30950
31010
  this.fetchTimeSeriesDataWithTableData("agent-runs", "runs", fromTimestamp, toTimestamp, timeDimension, filters),
30951
31011
  this.fetchTimeSeriesDataWithTableData("tool-runs", "runs", fromTimestamp, toTimestamp, timeDimension, filters),
30952
31012
  this.fetchTimeSeriesDataWithTableData("model-runs", "runs", fromTimestamp, toTimestamp, timeDimension, filters),
30953
31013
  this.fetchTimeSeriesData("tool-runs", "runs", fromTimestamp, toTimestamp, timeDimension, filters)
30954
31014
  ]);
30955
- const enhancedToolRunsChartData = this.transformTimeSeriesDataForToolRuns(toolRunsTimeSeriesData);
31015
+ if (results[0].status === "rejected") {
31016
+ console.error("Error fetching agent runs data:", results[0].reason);
31017
+ }
31018
+ if (results[1].status === "rejected") {
31019
+ console.error("Error fetching tool runs data:", results[1].reason);
31020
+ }
31021
+ if (results[2].status === "rejected") {
31022
+ console.error("Error fetching model runs data:", results[2].reason);
31023
+ }
31024
+ if (results[3].status === "rejected") {
31025
+ console.error("Error fetching tool runs time series data:", results[3].reason);
31026
+ }
31027
+ const emptyEnhancedData = { chartData: [], tableData: [], controlOptions: [] };
31028
+ const agentsData = results[0].status === "fulfilled" ? results[0].value : emptyEnhancedData;
31029
+ const toolsData = results[1].status === "fulfilled" ? results[1].value : emptyEnhancedData;
31030
+ const modelsData = results[2].status === "fulfilled" ? results[2].value : emptyEnhancedData;
31031
+ const toolRunsTimeSeriesData = results[3].status === "fulfilled" ? results[3].value : void 0;
31032
+ const enhancedToolRunsChartData = toolRunsTimeSeriesData ? this.transformTimeSeriesDataForToolRuns(toolRunsTimeSeriesData) : [];
30956
31033
  return [
30957
31034
  {
30958
31035
  title: "Agent Runs",
@@ -30966,68 +31043,70 @@ class DashboardApiService {
30966
31043
  value: Math.abs(trends.agentRuns.changePercent),
30967
31044
  type: getChangeType(trends.agentRuns.changePercent)
30968
31045
  } : void 0,
30969
- view: {
30970
- type: "chart",
30971
- chart: {
30972
- type: "line",
30973
- title: "Agent Runs",
30974
- data: agentsData.chartData,
30975
- dataKey: "agentRuns",
30976
- color: "#0BA5EC",
30977
- yAxisLabel: "Number of Agent Runs",
30978
- height: 300,
30979
- showGrid: true,
30980
- curve: "monotone",
30981
- tooltip: { show: true, style: "dark" },
30982
- dateRange: {
30983
- start: fromTimestamp.split("T")[0],
30984
- end: toTimestamp.split("T")[0]
30985
- }
30986
- },
30987
- table: {
30988
- title: "Agent Runs",
30989
- data: agentsData.tableData,
30990
- columns: [
30991
- {
30992
- key: "name",
30993
- title: "Name",
30994
- width: 200,
30995
- align: "left"
30996
- },
30997
- {
30998
- key: "runs",
30999
- title: "Runs",
31000
- width: 100,
31001
- align: "right",
31002
- formatter: (value) => `${Math.floor(value / 1e3)}k`
31003
- },
31004
- {
31005
- key: "responseTime",
31006
- title: "Response Time",
31007
- width: 120,
31008
- align: "right"
31009
- },
31010
- {
31011
- key: "tokens",
31012
- title: "Tokens",
31013
- width: 100,
31014
- align: "right",
31015
- formatter: (value) => `${Math.floor(value / 1e3)}k`
31046
+ ...agentsData && {
31047
+ view: {
31048
+ type: "chart",
31049
+ chart: {
31050
+ type: "line",
31051
+ title: "Agent Runs",
31052
+ data: agentsData.chartData,
31053
+ dataKey: "agentRuns",
31054
+ color: "#0BA5EC",
31055
+ yAxisLabel: "Number of Agent Runs",
31056
+ height: 300,
31057
+ showGrid: true,
31058
+ curve: "monotone",
31059
+ tooltip: { show: true, style: "dark" },
31060
+ dateRange: {
31061
+ start: fromTimestamp.split("T")[0],
31062
+ end: toTimestamp.split("T")[0]
31016
31063
  }
31017
- ]
31018
- }
31019
- },
31020
- controls: {
31021
- dropdown: {
31022
- label: "All Agents",
31023
- options: agentsData.controlOptions,
31024
- defaultValue: ["all"],
31025
- multiSelect: true,
31026
- searchable: true
31064
+ },
31065
+ table: {
31066
+ title: "Agent Runs",
31067
+ data: agentsData.tableData,
31068
+ columns: [
31069
+ {
31070
+ key: "name",
31071
+ title: "Name",
31072
+ width: 200,
31073
+ align: "left"
31074
+ },
31075
+ {
31076
+ key: "runs",
31077
+ title: "Runs",
31078
+ width: 100,
31079
+ align: "right",
31080
+ formatter: (value) => `${Math.floor(value / 1e3)}k`
31081
+ },
31082
+ {
31083
+ key: "responseTime",
31084
+ title: "Response Time",
31085
+ width: 120,
31086
+ align: "right"
31087
+ },
31088
+ {
31089
+ key: "tokens",
31090
+ title: "Tokens",
31091
+ width: 100,
31092
+ align: "right",
31093
+ formatter: (value) => `${Math.floor(value / 1e3)}k`
31094
+ }
31095
+ ]
31096
+ }
31027
31097
  },
31028
- toggle: {
31029
- chartView: true,
31030
- tableView: true
31098
+ controls: {
31099
+ dropdown: {
31100
+ label: "All Agents",
31101
+ options: agentsData.controlOptions,
31102
+ defaultValue: ["all"],
31103
+ multiSelect: true,
31104
+ searchable: true
31105
+ },
31106
+ toggle: {
31107
+ chartView: true,
31108
+ tableView: true
31109
+ }
31031
31110
  }
31032
31111
  }
31033
31112
  },
@@ -31042,99 +31121,107 @@ class DashboardApiService {
31042
31121
  value: Math.abs(trends.toolRuns.changePercent.total),
31043
31122
  type: getChangeType(trends.toolRuns.changePercent.total)
31044
31123
  } : void 0,
31045
- view: {
31046
- type: "chart",
31047
- chart: {
31048
- type: "line",
31049
- title: "Tool Runs",
31050
- data: enhancedToolRunsChartData,
31051
- yAxisLabel: "Number of Tool Runs",
31052
- lines: [
31053
- {
31054
- dataKey: "toolRuns",
31055
- color: "#667085",
31056
- label: "Tool Runs"
31057
- },
31058
- {
31059
- dataKey: "codeTools",
31060
- color: "#F38744",
31061
- label: "Code Tools"
31062
- },
31063
- {
31064
- dataKey: "workflowTools",
31065
- color: "#2970FF",
31066
- label: "Workflow Tools"
31067
- },
31068
- {
31069
- dataKey: "knowledgeTools",
31070
- color: "#7A5AF8",
31071
- label: "Knowledge"
31072
- },
31073
- {
31074
- dataKey: "mcpTools",
31075
- color: "#47CD89",
31076
- label: "MCP Tools"
31124
+ ...toolsData && {
31125
+ view: {
31126
+ type: "chart",
31127
+ chart: {
31128
+ type: "line",
31129
+ title: "Tool Runs",
31130
+ data: enhancedToolRunsChartData,
31131
+ yAxisLabel: "Number of Tool Runs",
31132
+ lines: [
31133
+ {
31134
+ dataKey: "toolRuns",
31135
+ color: "#667085",
31136
+ label: "Tool Runs"
31137
+ },
31138
+ {
31139
+ dataKey: "codeTools",
31140
+ color: "#F38744",
31141
+ label: "Code Tools"
31142
+ },
31143
+ {
31144
+ dataKey: "workflowTools",
31145
+ color: "#2970FF",
31146
+ label: "Workflow Tools"
31147
+ },
31148
+ {
31149
+ dataKey: "knowledgeTools",
31150
+ color: "#7A5AF8",
31151
+ label: "Knowledge"
31152
+ },
31153
+ {
31154
+ dataKey: "mcpTools",
31155
+ color: "#47CD89",
31156
+ label: "MCP Tools"
31157
+ },
31158
+ {
31159
+ dataKey: "processors",
31160
+ color: "#EAB308",
31161
+ label: "Processors"
31162
+ }
31163
+ ],
31164
+ height: 300,
31165
+ showGrid: true,
31166
+ showLegend: true,
31167
+ curve: "monotone",
31168
+ tooltip: { show: true, style: "dark" },
31169
+ dateRange: {
31170
+ start: fromTimestamp.split("T")[0],
31171
+ end: toTimestamp.split("T")[0]
31077
31172
  }
31078
- ],
31079
- height: 300,
31080
- showGrid: true,
31081
- showLegend: true,
31082
- curve: "monotone",
31083
- tooltip: { show: true, style: "dark" },
31084
- dateRange: {
31085
- start: fromTimestamp.split("T")[0],
31086
- end: toTimestamp.split("T")[0]
31173
+ },
31174
+ table: {
31175
+ title: "Tool Runs",
31176
+ data: toolsData.tableData,
31177
+ columns: [
31178
+ {
31179
+ key: "name",
31180
+ title: "Name",
31181
+ width: 200,
31182
+ align: "left"
31183
+ },
31184
+ {
31185
+ key: "type",
31186
+ title: "Type",
31187
+ width: 150,
31188
+ align: "left"
31189
+ },
31190
+ {
31191
+ key: "runs",
31192
+ title: "Runs",
31193
+ width: 100,
31194
+ align: "right",
31195
+ formatter: (value) => `${Math.floor(value / 1e3)}k`
31196
+ },
31197
+ {
31198
+ key: "responseTime",
31199
+ title: "Response Time",
31200
+ width: 120,
31201
+ align: "right"
31202
+ }
31203
+ ]
31087
31204
  }
31088
31205
  },
31089
- table: {
31090
- title: "Tool Runs",
31091
- data: toolsData.tableData,
31092
- columns: [
31093
- {
31094
- key: "name",
31095
- title: "Name",
31096
- width: 200,
31097
- align: "left"
31098
- },
31099
- {
31100
- key: "type",
31101
- title: "Type",
31102
- width: 150,
31103
- align: "left"
31104
- },
31105
- {
31106
- key: "runs",
31107
- title: "Runs",
31108
- width: 100,
31109
- align: "right",
31110
- formatter: (value) => `${Math.floor(value / 1e3)}k`
31111
- },
31112
- {
31113
- key: "responseTime",
31114
- title: "Response Time",
31115
- width: 120,
31116
- align: "right"
31117
- }
31118
- ]
31119
- }
31120
- },
31121
- controls: {
31122
- dropdown: {
31123
- label: "All Tools",
31124
- options: toolsData.controlOptions,
31125
- defaultValue: ["all"],
31126
- multiSelect: true,
31127
- searchable: true
31128
- },
31129
- toggle: {
31130
- chartView: true,
31131
- tableView: true
31206
+ controls: {
31207
+ dropdown: {
31208
+ label: "All Tools",
31209
+ options: toolsData.controlOptions,
31210
+ defaultValue: ["all"],
31211
+ multiSelect: true,
31212
+ searchable: true
31213
+ },
31214
+ toggle: {
31215
+ chartView: true,
31216
+ tableView: true
31217
+ }
31132
31218
  }
31133
31219
  }
31134
31220
  },
31135
31221
  {
31136
31222
  title: "Model Runs",
31137
31223
  value: data.data.modelRuns,
31224
+ failedCount: data.data.failedModelRuns || 0,
31138
31225
  metricType: "modelRuns",
31139
31226
  icon: "cpu",
31140
31227
  highlighted: false,
@@ -31143,68 +31230,79 @@ class DashboardApiService {
31143
31230
  value: Math.abs(trends.modelRuns.changePercent),
31144
31231
  type: getChangeType(trends.modelRuns.changePercent)
31145
31232
  } : void 0,
31146
- view: {
31147
- type: "chart",
31148
- chart: {
31149
- type: "line",
31150
- title: "Model Runs",
31151
- data: modelsData.chartData,
31152
- dataKey: "modelRuns",
31153
- color: "#47CD89",
31154
- yAxisLabel: "Number of Model Runs",
31155
- height: 300,
31156
- showGrid: true,
31157
- curve: "monotone",
31158
- tooltip: { show: true, style: "dark" },
31159
- dateRange: {
31160
- start: fromTimestamp.split("T")[0],
31161
- end: toTimestamp.split("T")[0]
31162
- }
31163
- },
31164
- table: {
31165
- title: "Model Runs",
31166
- data: modelsData.tableData,
31167
- columns: [
31168
- {
31169
- key: "name",
31170
- title: "Model Name",
31171
- width: 200,
31172
- align: "left"
31173
- },
31174
- {
31175
- key: "runs",
31176
- title: "Runs",
31177
- width: 100,
31178
- align: "right",
31179
- formatter: (value) => `${Math.floor(value / 1e3)}k`
31180
- },
31181
- {
31182
- key: "tokens",
31183
- title: "Tokens",
31184
- width: 120,
31185
- align: "right",
31186
- formatter: (value) => `${Math.floor(value / 1e3)}k`
31187
- },
31188
- {
31189
- key: "responseTime",
31190
- title: "Response Time",
31191
- width: 120,
31192
- align: "right"
31233
+ ...modelsData && {
31234
+ view: {
31235
+ type: "chart",
31236
+ chart: {
31237
+ type: "line",
31238
+ title: "Model Runs",
31239
+ data: modelsData.chartData,
31240
+ yAxisLabel: "Number of Model Runs",
31241
+ lines: [
31242
+ { dataKey: "modelRuns", color: "#47CD89", label: "Model Runs" },
31243
+ {
31244
+ dataKey: "failedModelRuns",
31245
+ color: "#ef4444",
31246
+ label: "Failed",
31247
+ seriesType: "bar",
31248
+ hideInLegend: true
31249
+ }
31250
+ ],
31251
+ height: 300,
31252
+ showGrid: true,
31253
+ showLegend: true,
31254
+ curve: "monotone",
31255
+ tooltip: { show: true, style: "dark" },
31256
+ dateRange: {
31257
+ start: fromTimestamp.split("T")[0],
31258
+ end: toTimestamp.split("T")[0]
31193
31259
  }
31194
- ]
31195
- }
31196
- },
31197
- controls: {
31198
- dropdown: {
31199
- label: "All Models",
31200
- options: modelsData.controlOptions,
31201
- defaultValue: ["all"],
31202
- multiSelect: true,
31203
- searchable: true
31260
+ },
31261
+ table: {
31262
+ title: "Model Runs",
31263
+ data: modelsData.tableData,
31264
+ columns: [
31265
+ {
31266
+ key: "name",
31267
+ title: "Model Name",
31268
+ width: 200,
31269
+ align: "left"
31270
+ },
31271
+ {
31272
+ key: "runs",
31273
+ title: "Runs",
31274
+ width: 100,
31275
+ align: "right",
31276
+ formatter: (value) => `${Math.floor(value / 1e3)}k`
31277
+ },
31278
+ {
31279
+ key: "tokens",
31280
+ title: "Tokens",
31281
+ width: 120,
31282
+ align: "right",
31283
+ formatter: (value) => `${Math.floor(value / 1e3)}k`
31284
+ },
31285
+ {
31286
+ key: "responseTime",
31287
+ title: "Response Time",
31288
+ width: 120,
31289
+ align: "right"
31290
+ }
31291
+ ]
31292
+ }
31204
31293
  },
31205
- toggle: {
31206
- chartView: true,
31207
- tableView: true
31294
+ controls: {
31295
+ dropdown: {
31296
+ label: "All Models",
31297
+ options: modelsData.controlOptions,
31298
+ defaultValue: ["all"],
31299
+ multiSelect: true,
31300
+ searchable: true
31301
+ },
31302
+ toggle: {
31303
+ chartView: true,
31304
+ tableView: true
31305
+ }
31208
31306
  }
31209
31307
  }
31210
31308
  }
@@ -31216,12 +31314,34 @@ class DashboardApiService {
31216
31314
  const getChangeType = (changePercent) => {
31217
31315
  return changePercent > 0 ? "increase" : "decrease";
31218
31316
  };
31219
- const [usersData, sessionsData, messagesData, tokensData] = await Promise.all([
31317
+ const results = await Promise.allSettled([
31220
31318
  this.fetchTimeSeriesData("users", "usage-analytics", fromTimestamp, toTimestamp, timeDimension, filters),
31221
31319
  this.fetchTimeSeriesData("sessions", "usage-analytics", fromTimestamp, toTimestamp, timeDimension, filters),
31222
31320
  this.fetchTimeSeriesData("messages", "usage-analytics", fromTimestamp, toTimestamp, timeDimension, filters),
31223
31321
  this.fetchTimeSeriesData("tokens", "usage-analytics", fromTimestamp, toTimestamp, timeDimension, filters)
31224
31322
  ]);
31323
+ if (results[0].status === "rejected") {
31324
+ console.error("Error fetching users data:", results[0].reason);
31325
+ }
31326
+ if (results[1].status === "rejected") {
31327
+ console.error("Error fetching sessions data:", results[1].reason);
31328
+ }
31329
+ if (results[2].status === "rejected") {
31330
+ console.error("Error fetching messages data:", results[2].reason);
31331
+ }
31332
+ if (results[3].status === "rejected") {
31333
+ console.error("Error fetching tokens data:", results[3].reason);
31334
+ }
31335
+ const emptyTimeSeries = {
31336
+ type: "time-series",
31337
+ category: "usage-analytics",
31338
+ metric: "",
31339
+ data: []
31340
+ };
31341
+ const usersData = results[0].status === "fulfilled" ? results[0].value : { ...emptyTimeSeries, metric: "users" };
31342
+ const sessionsData = results[1].status === "fulfilled" ? results[1].value : { ...emptyTimeSeries, metric: "sessions" };
31343
+ const messagesData = results[2].status === "fulfilled" ? results[2].value : { ...emptyTimeSeries, metric: "messages" };
31344
+ const tokensData = results[3].status === "fulfilled" ? results[3].value : { ...emptyTimeSeries, metric: "tokens" };
31225
31345
  return [
31226
31346
  {
31227
31347
  title: "Users",
@@ -31235,22 +31355,24 @@ class DashboardApiService {
31235
31355
  value: Math.abs(trends.users.changePercent),
31236
31356
  type: getChangeType(trends.users.changePercent)
31237
31357
  } : void 0,
31238
- view: {
31239
- type: "chart",
31240
- chart: {
31241
- type: "line",
31242
- title: "Total Users",
31243
- data: this.transformTimeSeriesDataForMetric(usersData, "users"),
31244
- dataKey: "users",
31245
- color: "#4E5BA6",
31246
- yAxisLabel: "Number of Users",
31247
- height: 300,
31248
- showGrid: true,
31249
- curve: "monotone",
31250
- tooltip: { show: true, style: "dark" },
31251
- dateRange: {
31252
- start: fromTimestamp.split("T")[0],
31253
- end: toTimestamp.split("T")[0]
31358
+ ...usersData && {
31359
+ view: {
31360
+ type: "chart",
31361
+ chart: {
31362
+ type: "line",
31363
+ title: "Total Users",
31364
+ data: this.transformTimeSeriesDataForMetric(usersData, "users"),
31365
+ dataKey: "users",
31366
+ color: "#4E5BA6",
31367
+ yAxisLabel: "Number of Users",
31368
+ height: 300,
31369
+ showGrid: true,
31370
+ curve: "monotone",
31371
+ tooltip: { show: true, style: "dark" },
31372
+ dateRange: {
31373
+ start: fromTimestamp.split("T")[0],
31374
+ end: toTimestamp.split("T")[0]
31375
+ }
31254
31376
  }
31255
31377
  }
31256
31378
  }
@@ -31266,22 +31388,24 @@ class DashboardApiService {
31266
31388
  value: Math.abs(trends.sessions.changePercent),
31267
31389
  type: getChangeType(trends.sessions.changePercent)
31268
31390
  } : void 0,
31269
- view: {
31270
- type: "chart",
31271
- chart: {
31272
- type: "line",
31273
- title: "Total Sessions",
31274
- data: this.transformTimeSeriesDataForMetric(sessionsData, "sessions"),
31275
- dataKey: "sessions",
31276
- color: "#0BA5EC",
31277
- yAxisLabel: "Number of Sessions",
31278
- height: 300,
31279
- showGrid: true,
31280
- curve: "monotone",
31281
- tooltip: { show: true, style: "dark" },
31282
- dateRange: {
31283
- start: fromTimestamp.split("T")[0],
31284
- end: toTimestamp.split("T")[0]
31391
+ ...sessionsData && {
31392
+ view: {
31393
+ type: "chart",
31394
+ chart: {
31395
+ type: "line",
31396
+ title: "Total Sessions",
31397
+ data: this.transformTimeSeriesDataForMetric(sessionsData, "sessions"),
31398
+ dataKey: "sessions",
31399
+ color: "#0BA5EC",
31400
+ yAxisLabel: "Number of Sessions",
31401
+ height: 300,
31402
+ showGrid: true,
31403
+ curve: "monotone",
31404
+ tooltip: { show: true, style: "dark" },
31405
+ dateRange: {
31406
+ start: fromTimestamp.split("T")[0],
31407
+ end: toTimestamp.split("T")[0]
31408
+ }
31285
31409
  }
31286
31410
  }
31287
31411
  }
@@ -31297,22 +31421,24 @@ class DashboardApiService {
31297
31421
  value: Math.abs(trends.messages.changePercent.total),
31298
31422
  type: getChangeType(trends.messages.changePercent.total)
31299
31423
  } : void 0,
31300
- view: {
31301
- type: "chart",
31302
- chart: {
31303
- type: "line",
31304
- title: "Total Messages",
31305
- data: this.transformTimeSeriesDataForMetric(messagesData, "messages"),
31306
- dataKey: "messages",
31307
- color: "#E478FA",
31308
- yAxisLabel: "Number of Messages",
31309
- height: 300,
31310
- showGrid: true,
31311
- curve: "monotone",
31312
- tooltip: { show: true, style: "dark" },
31313
- dateRange: {
31314
- start: fromTimestamp.split("T")[0],
31315
- end: toTimestamp.split("T")[0]
31424
+ ...messagesData && {
31425
+ view: {
31426
+ type: "chart",
31427
+ chart: {
31428
+ type: "line",
31429
+ title: "Total Messages",
31430
+ data: this.transformTimeSeriesDataForMetric(messagesData, "messages"),
31431
+ dataKey: "messages",
31432
+ color: "#E478FA",
31433
+ yAxisLabel: "Number of Messages",
31434
+ height: 300,
31435
+ showGrid: true,
31436
+ curve: "monotone",
31437
+ tooltip: { show: true, style: "dark" },
31438
+ dateRange: {
31439
+ start: fromTimestamp.split("T")[0],
31440
+ end: toTimestamp.split("T")[0]
31441
+ }
31316
31442
  }
31317
31443
  }
31318
31444
  }
@@ -31328,38 +31454,40 @@ class DashboardApiService {
31328
31454
  value: Math.abs(trends.tokens.changePercent.total),
31329
31455
  type: getChangeType(trends.tokens.changePercent.total)
31330
31456
  } : void 0,
31331
- view: {
31332
- type: "chart",
31333
- chart: {
31334
- type: "line",
31335
- title: "Token Usage Breakdown",
31336
- data: this.transformTimeSeriesDataForMetric(tokensData, "tokens"),
31337
- yAxisLabel: "Number of Tokens",
31338
- lines: [
31339
- {
31340
- dataKey: "totalTokens",
31341
- color: "#FF692E",
31342
- label: "Total Tokens"
31343
- },
31344
- {
31345
- dataKey: "inputTokens",
31346
- color: "#5925DC",
31347
- label: "Input Tokens"
31348
- },
31349
- {
31350
- dataKey: "outputTokens",
31351
- color: "#E478FA",
31352
- label: "Output Tokens"
31457
+ ...tokensData && {
31458
+ view: {
31459
+ type: "chart",
31460
+ chart: {
31461
+ type: "line",
31462
+ title: "Token Usage Breakdown",
31463
+ data: this.transformTimeSeriesDataForMetric(tokensData, "tokens"),
31464
+ yAxisLabel: "Number of Tokens",
31465
+ lines: [
31466
+ {
31467
+ dataKey: "totalTokens",
31468
+ color: "#FF692E",
31469
+ label: "Total Tokens"
31470
+ },
31471
+ {
31472
+ dataKey: "inputTokens",
31473
+ color: "#5925DC",
31474
+ label: "Input Tokens"
31475
+ },
31476
+ {
31477
+ dataKey: "outputTokens",
31478
+ color: "#E478FA",
31479
+ label: "Output Tokens"
31480
+ }
31481
+ ],
31482
+ height: 300,
31483
+ showGrid: true,
31484
+ showLegend: true,
31485
+ curve: "monotone",
31486
+ tooltip: { show: true, style: "dark" },
31487
+ dateRange: {
31488
+ start: fromTimestamp.split("T")[0],
31489
+ end: toTimestamp.split("T")[0]
31353
31490
  }
31354
- ],
31355
- height: 300,
31356
- showGrid: true,
31357
- showLegend: true,
31358
- curve: "monotone",
31359
- tooltip: { show: true, style: "dark" },
31360
- dateRange: {
31361
- start: fromTimestamp.split("T")[0],
31362
- end: toTimestamp.split("T")[0]
31363
31491
  }
31364
31492
  }
31365
31493
  }
@@ -31387,35 +31515,27 @@ class DashboardApiService {
31387
31515
  let workflowTools = 0;
31388
31516
  let knowledgeTools = 0;
31389
31517
  let mcpTools = 0;
31518
+ let processors = 0;
31390
31519
  if (point2.listView && Array.isArray(point2.listView)) {
31391
31520
  point2.listView.forEach((item) => {
31392
31521
  const count = item.count || 0;
31393
- const toolType = (item.toolType || item.tool_type || "").toLowerCase();
31394
- const toolName = (item.toolName || item.tool_name || "").toLowerCase();
31395
- console.log(`Processing listView item:`, { toolType, toolName, count });
31522
+ const toolType = item.toolType || item.tool_type || "";
31396
31523
  const normalizedToolType = toolType.toLowerCase();
31397
- if (["inlinetool", "inlineTool", "tool", "code", "codetool", "event", "EVENT"].includes(toolType) || ["inlinetool", "tool", "code", "codetool", "event"].includes(normalizedToolType)) {
31524
+ if (["inlinetool", "tool", "code", "codetool", "event"].includes(normalizedToolType)) {
31398
31525
  codeTools += count;
31399
- } else if (["toollibrary", "toolLibrary", "workflow", "tool"].includes(toolType) || ["toollibrary", "workflow", "tool"].includes(normalizedToolType)) {
31526
+ } else if (["toollibrary", "workflow"].includes(normalizedToolType)) {
31400
31527
  workflowTools += count;
31401
- } else if (["knowledge", "KNOWLEDGE", "knowledgetool"].includes(toolType) || ["knowledge", "knowledgetool"].includes(normalizedToolType)) {
31528
+ } else if (["knowledge", "knowledgetool"].includes(normalizedToolType) || toolType === "KNOWLEDGE") {
31402
31529
  knowledgeTools += count;
31403
- } else if (["mcp", "MCP", "mcptool", "mcpTool"].includes(toolType) || ["mcp", "mcptool"].includes(normalizedToolType)) {
31530
+ } else if (["mcp", "mcptool"].includes(normalizedToolType)) {
31404
31531
  mcpTools += count;
31532
+ } else if (["pre_processor", "post_processor", "processor", "input_processor"].includes(normalizedToolType) || toolType === "INPUT_PROCESSOR" || toolType === "input_processor") {
31533
+ processors += count;
31405
31534
  } else {
31406
- console.log(`Unknown tool type '${toolType}' for tool '${toolName}', defaulting to code tools`);
31407
31535
  codeTools += count;
31408
31536
  }
31409
31537
  });
31410
- console.log(`Calculated breakdown for point ${index}:`, {
31411
- codeTools,
31412
- workflowTools,
31413
- knowledgeTools,
31414
- mcpTools,
31415
- total: codeTools + workflowTools + knowledgeTools + mcpTools,
31416
- expectedTotal: totalToolRuns
31417
- });
31418
- const calculatedTotal = codeTools + workflowTools + knowledgeTools + mcpTools;
31538
+ const calculatedTotal = codeTools + workflowTools + knowledgeTools + mcpTools + processors;
31419
31539
  if (Math.abs(calculatedTotal - totalToolRuns) > 1) {
31420
31540
  console.warn(`Breakdown total (${calculatedTotal}) doesn't match expected total (${totalToolRuns}) for point ${index}`);
31421
31541
  const difference = totalToolRuns - calculatedTotal;
@@ -31423,7 +31543,6 @@ class DashboardApiService {
31423
31543
  console.log(`Adjusted codeTools by ${difference} to balance total`);
31424
31544
  }
31425
31545
  } else {
31426
- console.log(`No listView data for point ${index}, assigning all ${totalToolRuns} to codeTools`);
31427
31546
  codeTools = totalToolRuns;
31428
31547
  }
31429
31548
  const basePoint = {
@@ -31434,11 +31553,11 @@ class DashboardApiService {
31434
31553
  toolRuns: totalToolRuns,
31435
31554
  value: totalToolRuns,
31436
31555
  count: totalToolRuns,
31437
- // Tool breakdown data for multi-line chart (using actual data)
31438
31556
  codeTools,
31439
31557
  workflowTools,
31440
31558
  knowledgeTools,
31441
31559
  mcpTools,
31560
+ processors,
31442
31561
  // Token data
31443
31562
  input_tokens: point2.input_tokens || 0,
31444
31563
  output_tokens: point2.output_tokens || 0,
@@ -31476,14 +31595,33 @@ class DashboardApiService {
31476
31595
  // Enhanced batch fetch method that returns complete MetricData with embedded view and controls
31477
31596
  async fetchAllCardsDataWithEnhancedViews(fromTimestamp, toTimestamp, timeDimension, filters = []) {
31478
31597
  try {
31479
- const [usageAnalyticsCards, runsCards] = await Promise.all([
31598
+ const cardsResults = await Promise.allSettled([
31480
31599
  this.fetchUsageAnalyticsCards(fromTimestamp, toTimestamp, timeDimension, filters),
31481
31600
  this.fetchRunsCards(fromTimestamp, toTimestamp, timeDimension, filters)
31482
31601
  ]);
31483
- const [enhancedUsageAnalytics, enhancedRuns] = await Promise.all([
31484
- this.transformUsageAnalyticsCardsWithEnhancedData(usageAnalyticsCards, fromTimestamp, toTimestamp, timeDimension, filters),
31485
- this.transformRunsCardsWithEnhancedData(runsCards, fromTimestamp, toTimestamp, timeDimension, filters)
31602
+ if (cardsResults[0].status === "rejected") {
31603
+ console.error("Error fetching usage analytics cards:", cardsResults[0].reason);
31604
+ }
31605
+ if (cardsResults[1].status === "rejected") {
31606
+ console.error("Error fetching runs cards:", cardsResults[1].reason);
31607
+ }
31608
+ if (cardsResults[0].status === "rejected" && cardsResults[1].status === "rejected") {
31609
+ throw new Error("Both usage analytics and runs cards failed to load");
31610
+ }
31611
+ const usageAnalyticsCards = cardsResults[0].status === "fulfilled" ? cardsResults[0].value : void 0;
31612
+ const runsCards = cardsResults[1].status === "fulfilled" ? cardsResults[1].value : void 0;
31613
+ const enhancementResults = await Promise.allSettled([
31614
+ usageAnalyticsCards ? this.transformUsageAnalyticsCardsWithEnhancedData(usageAnalyticsCards, fromTimestamp, toTimestamp, timeDimension, filters) : Promise.resolve([]),
31615
+ runsCards ? this.transformRunsCardsWithEnhancedData(runsCards, fromTimestamp, toTimestamp, timeDimension, filters) : Promise.resolve([])
31486
31616
  ]);
31617
+ if (enhancementResults[0].status === "rejected") {
31618
+ console.error("Error transforming usage analytics cards:", enhancementResults[0].reason);
31619
+ }
31620
+ if (enhancementResults[1].status === "rejected") {
31621
+ console.error("Error transforming runs cards:", enhancementResults[1].reason);
31622
+ }
31623
+ const enhancedUsageAnalytics = enhancementResults[0].status === "fulfilled" ? enhancementResults[0].value : [];
31624
+ const enhancedRuns = enhancementResults[1].status === "fulfilled" ? enhancementResults[1].value : [];
31487
31625
  return {
31488
31626
  usageAnalytics: enhancedUsageAnalytics,
31489
31627
  runs: enhancedRuns
@@ -31496,13 +31634,21 @@ class DashboardApiService {
31496
31634
  // Batch fetch time series data for default selected metrics
31497
31635
  async fetchDefaultTimeSeriesData(fromTimestamp, toTimestamp, timeDimension, filters = []) {
31498
31636
  try {
31499
- const [sessionsData, agentRunsData] = await Promise.all([
31637
+ const results = await Promise.allSettled([
31500
31638
  this.fetchTimeSeriesData("sessions", "usage-analytics", fromTimestamp, toTimestamp, timeDimension, filters),
31501
31639
  this.fetchTimeSeriesData("agent-runs", "runs", fromTimestamp, toTimestamp, timeDimension, filters)
31502
31640
  ]);
31641
+ if (results[0].status === "rejected") {
31642
+ console.error("Error fetching sessions data:", results[0].reason);
31643
+ }
31644
+ if (results[1].status === "rejected") {
31645
+ console.error("Error fetching agent runs data:", results[1].reason);
31646
+ }
31647
+ const sessionsData = results[0].status === "fulfilled" ? results[0].value : void 0;
31648
+ const agentRunsData = results[1].status === "fulfilled" ? results[1].value : void 0;
31503
31649
  return {
31504
- sessions: this.transformTimeSeriesData(sessionsData),
31505
- agentRuns: this.transformTimeSeriesData(agentRunsData)
31650
+ sessions: sessionsData ? this.transformTimeSeriesData(sessionsData) : [],
31651
+ agentRuns: agentRunsData ? this.transformTimeSeriesData(agentRunsData) : []
31506
31652
  };
31507
31653
  } catch (error) {
31508
31654
  console.error("Error fetching default time series data:", error);
@@ -32229,6 +32375,10 @@ const SectionControls = ({
32229
32375
  ] })
32230
32376
  ] });
32231
32377
  };
32378
+ function modelListViewRowLabel(listItem) {
32379
+ if (!listItem.modelName) return "";
32380
+ return listItem.connectionName ? `${listItem.modelName} - ${listItem.connectionName}` : listItem.modelName;
32381
+ }
32232
32382
  const DashboardSection = ({
32233
32383
  section,
32234
32384
  className,
@@ -32326,16 +32476,17 @@ const DashboardSection = ({
32326
32476
  });
32327
32477
  return baseData.map((item) => {
32328
32478
  let filteredValue = 0;
32479
+ let matchingItems = [];
32329
32480
  if (item["listView"] && Array.isArray(item["listView"])) {
32330
- const matchingItems = item["listView"].filter((listItem) => {
32481
+ matchingItems = item["listView"].filter((listItem) => {
32331
32482
  if (metricType === "agentRuns" && listItem.agentName) {
32332
32483
  return listItem.agentName === selectedLabel || listItem.agentName.toLowerCase() === (selectedLabel == null ? void 0 : selectedLabel.toLowerCase());
32333
32484
  }
32334
32485
  if (metricType === "toolRuns" && listItem.toolName) {
32335
32486
  return listItem.toolName === selectedLabel || listItem.toolName.toLowerCase() === (selectedLabel == null ? void 0 : selectedLabel.toLowerCase());
32336
32487
  }
32337
- if (metricType === "modelRuns" && listItem.modelName) {
32338
- return listItem.modelName === selectedLabel || listItem.modelName.toLowerCase() === (selectedLabel == null ? void 0 : selectedLabel.toLowerCase());
32488
+ if (metricType === "modelRuns" && listItem.modelName && selectedLabel) {
32489
+ return modelListViewRowLabel(listItem) === selectedLabel;
32339
32490
  }
32340
32491
  return false;
32341
32492
  });
@@ -32345,10 +32496,17 @@ const DashboardSection = ({
32345
32496
  );
32346
32497
  }
32347
32498
  console.log("📊 Filtered value for", selectedLabel, ":", filteredValue);
32499
+ const failedModelRunsSum = metricType === "modelRuns" ? matchingItems.reduce(
32500
+ (sum2, listItem) => sum2 + (Number(listItem.failedRuns) || 0),
32501
+ 0
32502
+ ) : 0;
32348
32503
  const result = {
32349
32504
  ...item,
32350
32505
  [metricType]: filteredValue
32351
32506
  };
32507
+ if (metricType === "modelRuns") {
32508
+ result.failedModelRuns = failedModelRunsSum;
32509
+ }
32352
32510
  return result;
32353
32511
  });
32354
32512
  }
@@ -32360,8 +32518,9 @@ const DashboardSection = ({
32360
32518
  const selectedLabels = selectedOptions.map((opt) => opt.label);
32361
32519
  return baseData.map((item) => {
32362
32520
  let aggregatedValue = 0;
32521
+ let matchingItems = [];
32363
32522
  if (item["listView"] && Array.isArray(item["listView"])) {
32364
- const matchingItems = item["listView"].filter((listItem) => {
32523
+ matchingItems = item["listView"].filter((listItem) => {
32365
32524
  if (metricType === "agentRuns" && listItem.agentName) {
32366
32525
  return selectedLabels.some(
32367
32526
  (label) => listItem.agentName === label || listItem.agentName.toLowerCase() === (label == null ? void 0 : label.toLowerCase())
@@ -32373,9 +32532,8 @@ const DashboardSection = ({
32373
32532
  );
32374
32533
  }
32375
32534
  if (metricType === "modelRuns" && listItem.modelName) {
32376
- return selectedLabels.some(
32377
- (label) => listItem.modelName === label || listItem.modelName.toLowerCase() === (label == null ? void 0 : label.toLowerCase())
32378
- );
32535
+ const rowLabel = modelListViewRowLabel(listItem);
32536
+ return selectedLabels.some((label) => rowLabel === label);
32379
32537
  }
32380
32538
  return false;
32381
32539
  });
@@ -32384,10 +32542,18 @@ const DashboardSection = ({
32384
32542
  0
32385
32543
  );
32386
32544
  }
32387
- return {
32545
+ const failedModelRunsMulti = metricType === "modelRuns" ? matchingItems.reduce(
32546
+ (sum2, listItem) => sum2 + (Number(listItem.failedRuns) || 0),
32547
+ 0
32548
+ ) : 0;
32549
+ const multiResult = {
32388
32550
  ...item,
32389
32551
  [metricType]: aggregatedValue
32390
32552
  };
32553
+ if (metricType === "modelRuns") {
32554
+ multiResult.failedModelRuns = failedModelRunsMulti;
32555
+ }
32556
+ return multiResult;
32391
32557
  });
32392
32558
  }
32393
32559
  return baseData;
@@ -32619,35 +32785,30 @@ const DashboardSection = ({
32619
32785
  data: filteredData,
32620
32786
  yAxisLabel: "Number of Tool Runs",
32621
32787
  lines: [
32622
- {
32623
- dataKey: "toolRuns",
32624
- color: "#06b6d4",
32625
- // Blue for Tool Runs
32626
- label: "Tool Runs"
32627
- },
32628
32788
  {
32629
32789
  dataKey: "codeTools",
32630
32790
  color: "#f97316",
32631
- // Orange for Code Tools
32632
32791
  label: "Code Tools"
32633
32792
  },
32634
32793
  {
32635
32794
  dataKey: "workflowTools",
32636
32795
  color: "#10b981",
32637
- // Green for Workflow Tools
32638
32796
  label: "Workflow Tools"
32639
32797
  },
32640
32798
  {
32641
32799
  dataKey: "knowledgeTools",
32642
32800
  color: "#8b5cf6",
32643
- // Purple for Knowledge
32644
32801
  label: "Knowledge"
32645
32802
  },
32646
32803
  {
32647
32804
  dataKey: "mcpTools",
32648
32805
  color: "#ef4444",
32649
- // Red for MCP Tools
32650
32806
  label: "MCP Tools"
32807
+ },
32808
+ {
32809
+ dataKey: "processors",
32810
+ color: "#eab308",
32811
+ label: "Processors"
32651
32812
  }
32652
32813
  ],
32653
32814
  height: 300,
@@ -32667,12 +32828,20 @@ const DashboardSection = ({
32667
32828
  type: "line",
32668
32829
  title: getChartTitle("Model Runs"),
32669
32830
  data: getFilteredData(baseData, "modelRuns"),
32670
- dataKey: "modelRuns",
32671
- color: "#10b981",
32672
- // Green as shown in Figma
32673
32831
  yAxisLabel: "Number of Model Runs",
32832
+ lines: [
32833
+ { dataKey: "modelRuns", color: "#10b981", label: "Model Runs" },
32834
+ {
32835
+ dataKey: "failedModelRuns",
32836
+ color: "#ef4444",
32837
+ label: "Failed",
32838
+ seriesType: "bar",
32839
+ hideInLegend: true
32840
+ }
32841
+ ],
32674
32842
  height: 300,
32675
32843
  showGrid: true,
32844
+ showLegend: true,
32676
32845
  curve: "monotone",
32677
32846
  tooltip: { show: true, style: "dark" },
32678
32847
  dateRange: {
@@ -32685,12 +32854,20 @@ const DashboardSection = ({
32685
32854
  type: "line",
32686
32855
  title: getChartTitle("Model Runs"),
32687
32856
  data: filteredData,
32688
- dataKey: "modelRuns",
32689
- color: "#10b981",
32690
- // Green as shown in Figma
32691
32857
  yAxisLabel: "Number of Model Runs",
32858
+ lines: [
32859
+ { dataKey: "modelRuns", color: "#10b981", label: "Model Runs" },
32860
+ {
32861
+ dataKey: "failedModelRuns",
32862
+ color: "#ef4444",
32863
+ label: "Failed",
32864
+ seriesType: "bar",
32865
+ hideInLegend: true
32866
+ }
32867
+ ],
32692
32868
  height: 300,
32693
32869
  showGrid: true,
32870
+ showLegend: true,
32694
32871
  curve: "monotone",
32695
32872
  tooltip: { show: true, style: "dark" },
32696
32873
  dateRange: {
@@ -34942,8 +35119,11 @@ const Dashboard = ({
34942
35119
  if (appConfig) {
34943
35120
  try {
34944
35121
  apiServiceRef.current = new DashboardApiService(appConfig);
34945
- loadEnvironments();
34946
- loadInitialData();
35122
+ const initDashboard = async () => {
35123
+ await loadEnvironments();
35124
+ await loadInitialData();
35125
+ };
35126
+ initDashboard();
34947
35127
  } catch (err) {
34948
35128
  console.error("Failed to initialize API service:", err);
34949
35129
  }
@@ -106326,6 +106506,7 @@ class DetailPageService {
106326
106506
  );
106327
106507
  traceDetails = traceResponses.map((trace) => this.transformToTraceDetailData(trace));
106328
106508
  }
106509
+ const resolvedSessionReference = typeof sessionResponse.sessionReference === "string" && sessionResponse.sessionReference.trim() !== "" ? sessionResponse.sessionReference.trim() : void 0;
106329
106510
  return {
106330
106511
  id: sessionResponse.id,
106331
106512
  projectId: sessionResponse.projectId,
@@ -106333,7 +106514,8 @@ class DetailPageService {
106333
106514
  bookmarked: false,
106334
106515
  public: false,
106335
106516
  traces: traceDetails,
106336
- scores: []
106517
+ scores: [],
106518
+ sessionReference: resolvedSessionReference
106337
106519
  };
106338
106520
  }
106339
106521
  /**
@@ -106410,10 +106592,12 @@ class DetailPageService {
106410
106592
  projectId: this.projectId
106411
106593
  });
106412
106594
  const traceIds = (sessionResponse.traces || []).map((t2) => t2.id);
106595
+ const resolvedSessionReference = typeof sessionResponse.sessionReference === "string" && sessionResponse.sessionReference.trim() !== "" ? sessionResponse.sessionReference.trim() : void 0;
106413
106596
  onSessionMeta({
106414
106597
  id: sessionResponse.id,
106415
106598
  traceCount: traceIds.length,
106416
- traceIds
106599
+ traceIds,
106600
+ sessionReference: resolvedSessionReference
106417
106601
  });
106418
106602
  if (traceIds.length === 0) {
106419
106603
  return {
@@ -106423,7 +106607,8 @@ class DetailPageService {
106423
106607
  bookmarked: false,
106424
106608
  public: false,
106425
106609
  traces: [],
106426
- scores: []
106610
+ scores: [],
106611
+ sessionReference: resolvedSessionReference
106427
106612
  };
106428
106613
  }
106429
106614
  const firstTraceId = traceIds[0];
@@ -106470,7 +106655,8 @@ class DetailPageService {
106470
106655
  bookmarked: false,
106471
106656
  public: false,
106472
106657
  traces: allTraces,
106473
- scores: []
106658
+ scores: [],
106659
+ sessionReference: resolvedSessionReference
106474
106660
  };
106475
106661
  }
106476
106662
  // ============================================================================
@@ -106564,6 +106750,7 @@ class DetailPageService {
106564
106750
  totalCost: trace.totalCost || trace.calculatedTotalCost,
106565
106751
  totalTokens: trace.totalTokens,
106566
106752
  environment: trace.environment,
106753
+ source: typeof trace.source === "string" && trace.source.length > 0 ? trace.source : void 0,
106567
106754
  observations: (trace.observations || []).map(
106568
106755
  (obs) => this.transformObservation(obs)
106569
106756
  ),
@@ -109291,6 +109478,526 @@ function NodeDetailPanel({
109291
109478
  )
109292
109479
  ] });
109293
109480
  }
109481
+ const MicIcon = () => /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", className: "shrink-0", children: [
109482
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
109483
+ "path",
109484
+ {
109485
+ d: "M8 2C7.60218 2 7.22064 2.15804 6.93934 2.43934C6.65804 2.72064 6.5 3.10218 6.5 3.5V6.5C6.5 6.89782 6.65804 7.27936 6.93934 7.56066C7.22064 7.84196 7.60218 8 8 8C8.39782 8 8.77936 7.84196 9.06066 7.56066C9.34196 7.27936 9.5 6.89782 9.5 6.5V3.5C9.5 3.10218 9.34196 2.72064 9.06066 2.43934C8.77936 2.15804 8.39782 2 8 2Z",
109486
+ fill: "#155EEF"
109487
+ }
109488
+ ),
109489
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
109490
+ "path",
109491
+ {
109492
+ d: "M5.5 6V6.5C5.5 7.16304 5.76339 7.79893 6.23223 8.26777C6.70107 8.73661 7.33696 9 8 9C8.66304 9 9.29893 8.73661 9.76777 8.26777C10.2366 7.79893 10.5 7.16304 10.5 6.5V6",
109493
+ stroke: "#155EEF",
109494
+ strokeWidth: "1.2",
109495
+ strokeLinecap: "round",
109496
+ strokeLinejoin: "round"
109497
+ }
109498
+ ),
109499
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
109500
+ "path",
109501
+ {
109502
+ d: "M8 9V11",
109503
+ stroke: "#155EEF",
109504
+ strokeWidth: "1.2",
109505
+ strokeLinecap: "round",
109506
+ strokeLinejoin: "round"
109507
+ }
109508
+ ),
109509
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
109510
+ "path",
109511
+ {
109512
+ d: "M6.5 11H9.5",
109513
+ stroke: "#155EEF",
109514
+ strokeWidth: "1.2",
109515
+ strokeLinecap: "round",
109516
+ strokeLinejoin: "round"
109517
+ }
109518
+ )
109519
+ ] });
109520
+ function VoiceEventLogsBanner({ onViewEventLogs }) {
109521
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between rounded-[8px] bg-[#FFFFFF] border border-[#D0D5DD] px-[12px] py-[8px] mb-[8px]", children: [
109522
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-[8px]", children: [
109523
+ /* @__PURE__ */ jsxRuntimeExports.jsx(MicIcon, {}),
109524
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-semibold text-[11px] leading-[14px] text-[#98A2B3] uppercase tracking-[0.04em]", children: "Voice-to-Voice Event Logs" })
109525
+ ] }),
109526
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
109527
+ "button",
109528
+ {
109529
+ onClick: onViewEventLogs,
109530
+ className: "text-[12px] font-medium text-[#155EEF] hover:text-[#344054] hover:underline transition-colors cursor-pointer bg-transparent border-none p-0",
109531
+ "data-test-id": "view-event-logs-btn",
109532
+ children: "View Event Logs"
109533
+ }
109534
+ )
109535
+ ] });
109536
+ }
109537
+ function AlignLeftIcon({ className }) {
109538
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
109539
+ "svg",
109540
+ {
109541
+ width: "16",
109542
+ height: "16",
109543
+ viewBox: "0 0 16 16",
109544
+ fill: "none",
109545
+ className,
109546
+ "aria-hidden": "true",
109547
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(
109548
+ "path",
109549
+ {
109550
+ d: "M10.6667 6.66667H2M13.3333 4H2M13.3333 9.33333H2M10.6667 12H2",
109551
+ stroke: "currentColor",
109552
+ strokeWidth: "1.3",
109553
+ strokeLinecap: "round",
109554
+ strokeLinejoin: "round"
109555
+ }
109556
+ )
109557
+ }
109558
+ );
109559
+ }
109560
+ function JsonViewIcon({ className }) {
109561
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
109562
+ "svg",
109563
+ {
109564
+ width: "16",
109565
+ height: "16",
109566
+ viewBox: "0 0 16 16",
109567
+ fill: "none",
109568
+ className,
109569
+ "aria-hidden": "true",
109570
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(
109571
+ "path",
109572
+ {
109573
+ d: "M14 6.16602H8M14 2.66602H2M14 9.83268H8M14 13.3327H2M2.85333 5.70602L5.43111 7.63935C5.62411 7.78409 5.7206 7.85647 5.75511 7.94519C5.78533 8.02291 5.78533 8.10913 5.75511 8.18684C5.7206 8.27556 5.62411 8.34794 5.43111 8.49268L2.85333 10.426C2.57868 10.632 2.44135 10.735 2.3264 10.7326C2.22637 10.7305 2.13256 10.6836 2.07088 10.6048C2 10.5143 2 10.3427 2 9.99935V6.13268C2 5.78937 2 5.61771 2.07088 5.52718C2.13256 5.4484 2.22637 5.4015 2.3264 5.39942C2.44135 5.39703 2.57868 5.50003 2.85333 5.70602Z",
109574
+ stroke: "currentColor",
109575
+ strokeWidth: "1.3",
109576
+ strokeLinecap: "round",
109577
+ strokeLinejoin: "round"
109578
+ }
109579
+ )
109580
+ }
109581
+ );
109582
+ }
109583
+ function pickString(obj, keys2) {
109584
+ for (const key of keys2) {
109585
+ const value = obj[key];
109586
+ if (typeof value === "string" && value.length > 0) return value;
109587
+ if (typeof value === "number") return String(value);
109588
+ }
109589
+ return void 0;
109590
+ }
109591
+ function coerceDirection(raw) {
109592
+ if (raw === "incoming" || raw === "server" || raw === "response") return "in";
109593
+ return "out";
109594
+ }
109595
+ function normalizeEvent(raw, fallbackId, docTimestamp) {
109596
+ if (!raw || typeof raw !== "object") {
109597
+ return {
109598
+ id: fallbackId,
109599
+ timestamp: docTimestamp,
109600
+ name: "event",
109601
+ direction: "out",
109602
+ payload: raw
109603
+ };
109604
+ }
109605
+ const obj = raw;
109606
+ const id = pickString(obj, ["event_id", "eventId", "_id", "id"]) ?? fallbackId;
109607
+ const name = pickString(obj, ["type", "eventType", "event", "name"]) ?? "event";
109608
+ const direction = coerceDirection(obj.direction);
109609
+ return {
109610
+ id,
109611
+ timestamp: docTimestamp,
109612
+ name,
109613
+ direction,
109614
+ payload: raw
109615
+ };
109616
+ }
109617
+ function flattenEvents(data) {
109618
+ if (data === null || data === void 0) return [];
109619
+ const out = [];
109620
+ const visitDoc = (doc2, docIdx) => {
109621
+ if (!doc2 || typeof doc2 !== "object") return;
109622
+ const docObj = doc2;
109623
+ const docTimestamp = pickString(docObj, ["createdOn", "sT", "createdAt"]);
109624
+ const events = docObj.events;
109625
+ if (Array.isArray(events)) {
109626
+ events.forEach((ev, evIdx) => {
109627
+ out.push(normalizeEvent(ev, `${docIdx}-${evIdx}`, docTimestamp));
109628
+ });
109629
+ } else {
109630
+ out.push(normalizeEvent(doc2, String(docIdx), docTimestamp));
109631
+ }
109632
+ };
109633
+ if (Array.isArray(data)) {
109634
+ data.forEach((doc2, docIdx) => visitDoc(doc2, docIdx));
109635
+ return out;
109636
+ }
109637
+ if (typeof data === "object") {
109638
+ const obj = data;
109639
+ if (Array.isArray(obj.events)) {
109640
+ visitDoc(obj, 0);
109641
+ return out;
109642
+ }
109643
+ if (Array.isArray(obj.data)) {
109644
+ return flattenEvents(obj.data);
109645
+ }
109646
+ }
109647
+ return [];
109648
+ }
109649
+ function formatEventTime(iso) {
109650
+ if (!iso) return "--:--:--:---";
109651
+ const d3 = new Date(iso);
109652
+ if (Number.isNaN(d3.getTime())) return "--:--:--:---";
109653
+ const hh = String(d3.getHours()).padStart(2, "0");
109654
+ const mm = String(d3.getMinutes()).padStart(2, "0");
109655
+ const ss = String(d3.getSeconds()).padStart(2, "0");
109656
+ const ms = String(d3.getMilliseconds()).padStart(3, "0");
109657
+ return `${hh}:${mm}:${ss}:${ms}`;
109658
+ }
109659
+ function stringifyPayload(payload) {
109660
+ if (payload === null || payload === void 0) return "";
109661
+ if (typeof payload === "string") {
109662
+ try {
109663
+ return JSON.stringify(JSON.parse(payload), null, 2);
109664
+ } catch {
109665
+ return payload;
109666
+ }
109667
+ }
109668
+ try {
109669
+ return JSON.stringify(payload, null, 2);
109670
+ } catch {
109671
+ return String(payload);
109672
+ }
109673
+ }
109674
+ function compactPayload(payload) {
109675
+ if (payload === null || payload === void 0) return "";
109676
+ if (typeof payload === "string") {
109677
+ try {
109678
+ return JSON.stringify(JSON.parse(payload));
109679
+ } catch {
109680
+ return payload;
109681
+ }
109682
+ }
109683
+ try {
109684
+ return JSON.stringify(payload);
109685
+ } catch {
109686
+ return String(payload);
109687
+ }
109688
+ }
109689
+ function PayloadPanel({ payload, compactText }) {
109690
+ const [viewMode, setViewMode] = useState("json");
109691
+ const [fullscreen, setFullscreen] = useState(false);
109692
+ const [copied, setCopied] = useState(false);
109693
+ const displayText = viewMode === "json" ? payload : compactText;
109694
+ const handleCopy = useCallback(async () => {
109695
+ try {
109696
+ await navigator.clipboard.writeText(displayText);
109697
+ setCopied(true);
109698
+ await new Promise((resolve) => setTimeout(resolve, 1500));
109699
+ } catch {
109700
+ } finally {
109701
+ setCopied(false);
109702
+ }
109703
+ }, [displayText]);
109704
+ const toolbar = /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "h-[42px] px-[10px] border-b border-[#D0D5DD] flex items-center justify-between flex-shrink-0 bg-white", children: [
109705
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-[4px]", children: [
109706
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
109707
+ "button",
109708
+ {
109709
+ type: "button",
109710
+ onClick: () => setViewMode("json"),
109711
+ className: `p-[5px] rounded-[4px] transition-colors ${viewMode === "json" ? "text-[#155EEF] bg-[#EFF4FF]" : "text-[#98A2B3] hover:bg-[#F2F4F7]"}`,
109712
+ title: "Pretty JSON",
109713
+ "aria-label": "Pretty JSON view",
109714
+ "aria-pressed": viewMode === "json",
109715
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(JsonViewIcon, { className: "w-[16px] h-[16px]" })
109716
+ }
109717
+ ),
109718
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
109719
+ "button",
109720
+ {
109721
+ type: "button",
109722
+ onClick: () => setViewMode("text"),
109723
+ className: `p-[5px] rounded-[4px] transition-colors ${viewMode === "text" ? "text-[#155EEF] bg-[#EFF4FF]" : "text-[#98A2B3] hover:bg-[#F2F4F7]"}`,
109724
+ title: "Compact text",
109725
+ "aria-label": "Compact text view",
109726
+ "aria-pressed": viewMode === "text",
109727
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(AlignLeftIcon, { className: "w-[16px] h-[16px]" })
109728
+ }
109729
+ )
109730
+ ] }),
109731
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-[4px]", children: [
109732
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
109733
+ "button",
109734
+ {
109735
+ type: "button",
109736
+ onClick: () => setFullscreen((v) => !v),
109737
+ className: "p-[5px] rounded-[4px] text-[#98A2B3] hover:bg-[#F2F4F7] transition-colors",
109738
+ title: fullscreen ? "Exit fullscreen" : "Fullscreen",
109739
+ "aria-label": fullscreen ? "Exit fullscreen" : "Fullscreen",
109740
+ children: fullscreen ? /* @__PURE__ */ jsxRuntimeExports.jsx(Minimize2, { className: "w-[16px] h-[16px]" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Maximize2, { className: "w-[16px] h-[16px]" })
109741
+ }
109742
+ ),
109743
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
109744
+ "button",
109745
+ {
109746
+ type: "button",
109747
+ onClick: () => void handleCopy(),
109748
+ className: "p-[5px] rounded-[4px] text-[#98A2B3] hover:bg-[#F2F4F7] transition-colors",
109749
+ title: "Copy to clipboard",
109750
+ "aria-label": "Copy payload",
109751
+ "data-test-id": "event-logs-row-copy",
109752
+ children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "w-[16px] h-[16px] text-[#12B76A]" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "w-[16px] h-[16px]" })
109753
+ }
109754
+ )
109755
+ ] })
109756
+ ] });
109757
+ if (fullscreen) {
109758
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Portal, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "fixed inset-0 z-[20000] flex flex-col bg-[#F9FAFB]", children: [
109759
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "h-[48px] px-[16px] border-b border-[#E4E7EC] flex items-center justify-between flex-shrink-0 bg-white", children: [
109760
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-[4px]", children: [
109761
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
109762
+ "button",
109763
+ {
109764
+ type: "button",
109765
+ onClick: () => setViewMode("json"),
109766
+ className: `p-[5px] rounded-[4px] transition-colors ${viewMode === "json" ? "text-[#155EEF] bg-[#EFF4FF]" : "text-[#98A2B3] hover:bg-[#F2F4F7]"}`,
109767
+ title: "Pretty JSON",
109768
+ "aria-label": "Pretty JSON view",
109769
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(JsonViewIcon, { className: "w-[16px] h-[16px]" })
109770
+ }
109771
+ ),
109772
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
109773
+ "button",
109774
+ {
109775
+ type: "button",
109776
+ onClick: () => setViewMode("text"),
109777
+ className: `p-[5px] rounded-[4px] transition-colors ${viewMode === "text" ? "text-[#155EEF] bg-[#EFF4FF]" : "text-[#98A2B3] hover:bg-[#F2F4F7]"}`,
109778
+ title: "Compact text",
109779
+ "aria-label": "Compact text view",
109780
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(AlignLeftIcon, { className: "w-[16px] h-[16px]" })
109781
+ }
109782
+ )
109783
+ ] }),
109784
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-[4px]", children: [
109785
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
109786
+ "button",
109787
+ {
109788
+ type: "button",
109789
+ onClick: () => void handleCopy(),
109790
+ className: "p-[5px] rounded-[4px] text-[#98A2B3] hover:bg-[#F2F4F7] transition-colors",
109791
+ title: "Copy to clipboard",
109792
+ "aria-label": "Copy payload",
109793
+ children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "w-[16px] h-[16px] text-[#12B76A]" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "w-[16px] h-[16px]" })
109794
+ }
109795
+ ),
109796
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
109797
+ "button",
109798
+ {
109799
+ type: "button",
109800
+ onClick: () => setFullscreen(false),
109801
+ className: "p-[5px] rounded-[4px] text-[#98A2B3] hover:bg-[#F2F4F7] transition-colors",
109802
+ title: "Exit fullscreen",
109803
+ "aria-label": "Exit fullscreen",
109804
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(Minimize2, { className: "w-[16px] h-[16px]" })
109805
+ }
109806
+ )
109807
+ ] })
109808
+ ] }),
109809
+ /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "flex-1 overflow-auto m-0 p-[20px] text-[13px] leading-[20px] font-mono text-[#344054] whitespace-pre-wrap break-all", children: displayText })
109810
+ ] }) });
109811
+ }
109812
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-[10px] border border-[#D0D5DD] overflow-hidden mt-[12px]", children: [
109813
+ toolbar,
109814
+ /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "m-0 bg-[#F9FAFB] text-[#344054] p-[12px] text-[12px] leading-[18px] font-mono whitespace-pre-wrap break-all overflow-auto max-h-[360px]", children: displayText })
109815
+ ] });
109816
+ }
109817
+ function EventRow({ event, isExpanded, onToggle }) {
109818
+ const jsonText = useMemo(() => stringifyPayload(event.payload), [event.payload]);
109819
+ const compactText = useMemo(() => compactPayload(event.payload), [event.payload]);
109820
+ const hasPayload = jsonText.length > 0;
109821
+ const isInput = event.direction === "in";
109822
+ const DirectionIcon = isInput ? ArrowUp : ArrowDown;
109823
+ const directionLabel = isInput ? "Input" : "Output";
109824
+ const circleClasses = isInput ? "border-[#079455] text-[#079455]" : "border-[#D92D20] text-[#D92D20]";
109825
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative flex items-start gap-[12px]", "data-test-id": "event-logs-row", children: [
109826
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "relative flex-shrink-0 flex flex-col items-center w-[16px]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
109827
+ "div",
109828
+ {
109829
+ className: `relative z-10 w-[16px] h-[16px] rounded-full bg-white border flex items-center justify-center ${circleClasses}`,
109830
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(DirectionIcon, { className: "w-[8px] h-[8px]", strokeWidth: 2.5 })
109831
+ }
109832
+ ) }),
109833
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0 pb-[24px]", children: [
109834
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between gap-[16px]", children: [
109835
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0", children: [
109836
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[12px] leading-[16px] text-[#667085]", children: directionLabel }),
109837
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[14px] leading-[20px] font-medium text-[#344054] mt-[2px] break-all", children: event.name }),
109838
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
109839
+ "button",
109840
+ {
109841
+ type: "button",
109842
+ onClick: onToggle,
109843
+ className: "text-[13px] leading-[18px] text-[#155EEF] hover:underline mt-[4px] font-medium",
109844
+ "data-test-id": "event-logs-view-details",
109845
+ children: isExpanded ? "Hide details" : "View details"
109846
+ }
109847
+ )
109848
+ ] }),
109849
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-shrink-0 text-[12px] leading-[18px] text-[#344054] font-mono tabular-nums whitespace-nowrap pt-[2px]", children: formatEventTime(event.timestamp) })
109850
+ ] }),
109851
+ isExpanded && (hasPayload ? /* @__PURE__ */ jsxRuntimeExports.jsx(PayloadPanel, { payload: jsonText, compactText }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-[12px] text-[12px] text-[#667085] italic", children: "No payload recorded for this event." }))
109852
+ ] })
109853
+ ] });
109854
+ }
109855
+ function EventLogsSlideout({
109856
+ isOpen,
109857
+ onClose,
109858
+ sessionId,
109859
+ fetchEventLogs
109860
+ }) {
109861
+ const [rawData, setRawData] = useState(null);
109862
+ const [loading, setLoading] = useState(false);
109863
+ const [error, setError] = useState(null);
109864
+ const [expandedIds, setExpandedIds] = useState(() => /* @__PURE__ */ new Set());
109865
+ useEffect(() => {
109866
+ if (!isOpen || !sessionId || !fetchEventLogs) return;
109867
+ let cancelled = false;
109868
+ setLoading(true);
109869
+ setError(null);
109870
+ setRawData(null);
109871
+ (async () => {
109872
+ try {
109873
+ const data = await fetchEventLogs(sessionId);
109874
+ if (cancelled) return;
109875
+ setRawData(data);
109876
+ } catch (err) {
109877
+ if (cancelled) return;
109878
+ setError(err instanceof Error ? err.message : "Failed to fetch event logs");
109879
+ } finally {
109880
+ if (!cancelled) setLoading(false);
109881
+ }
109882
+ })();
109883
+ return () => {
109884
+ cancelled = true;
109885
+ };
109886
+ }, [isOpen, sessionId, fetchEventLogs]);
109887
+ const events = useMemo(() => flattenEvents(rawData), [rawData]);
109888
+ useEffect(() => {
109889
+ if (!isOpen) return;
109890
+ const handleKey = (e3) => {
109891
+ if (e3.key === "Escape") onClose();
109892
+ };
109893
+ document.addEventListener("keydown", handleKey);
109894
+ return () => document.removeEventListener("keydown", handleKey);
109895
+ }, [isOpen, onClose]);
109896
+ useEffect(() => {
109897
+ if (!isOpen) {
109898
+ setExpandedIds(/* @__PURE__ */ new Set());
109899
+ setRawData(null);
109900
+ setError(null);
109901
+ }
109902
+ }, [isOpen]);
109903
+ const toggleRow = useCallback((id) => {
109904
+ setExpandedIds((prev) => {
109905
+ const next = new Set(prev);
109906
+ if (next.has(id)) next.delete(id);
109907
+ else next.add(id);
109908
+ return next;
109909
+ });
109910
+ }, []);
109911
+ const expandAll = useCallback(() => {
109912
+ setExpandedIds(new Set(events.map((e3) => e3.id)));
109913
+ }, [events]);
109914
+ const collapseAll = useCallback(() => {
109915
+ setExpandedIds(/* @__PURE__ */ new Set());
109916
+ }, []);
109917
+ if (!isOpen) return null;
109918
+ const showToolbar = !loading && !error && events.length > 0;
109919
+ const allExpanded = showToolbar && expandedIds.size === events.length;
109920
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Portal, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "fixed inset-0 z-[10000]", children: [
109921
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
109922
+ "div",
109923
+ {
109924
+ className: "absolute inset-0 bg-black/40",
109925
+ onClick: onClose,
109926
+ "aria-hidden": "true"
109927
+ }
109928
+ ),
109929
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
109930
+ "div",
109931
+ {
109932
+ className: "absolute top-0 right-0 bottom-0 bg-white shadow-2xl flex flex-col",
109933
+ style: { width: "720px", maxWidth: "100vw" },
109934
+ role: "dialog",
109935
+ "aria-label": "Event Logs",
109936
+ onClick: (e3) => e3.stopPropagation(),
109937
+ children: [
109938
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between h-[56px] px-[20px] border-b border-[#E4E7EC] flex-shrink-0", children: [
109939
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-[8px]", children: [
109940
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[16px] font-semibold text-[#101828]", children: "Event Logs" }),
109941
+ !loading && !error && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[12px] font-medium text-[#667085] bg-[#F2F4F7] rounded-[10px] px-[8px] py-[2px]", children: events.length })
109942
+ ] }),
109943
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-[4px]", children: [
109944
+ showToolbar && /* @__PURE__ */ jsxRuntimeExports.jsx(
109945
+ "button",
109946
+ {
109947
+ type: "button",
109948
+ onClick: allExpanded ? collapseAll : expandAll,
109949
+ className: "text-[13px] font-medium text-[#155EEF] hover:underline px-[8px] py-[6px] rounded-[6px] transition-colors",
109950
+ "data-test-id": "event-logs-toggle-all",
109951
+ children: allExpanded ? "Collapse all" : "Expand all"
109952
+ }
109953
+ ),
109954
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
109955
+ "button",
109956
+ {
109957
+ type: "button",
109958
+ onClick: onClose,
109959
+ className: "p-[8px] rounded-[6px] hover:bg-[#F2F4F7] transition-colors",
109960
+ title: "Close Event Logs",
109961
+ "aria-label": "Close Event Logs",
109962
+ "data-test-id": "event-logs-close-btn",
109963
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "w-[16px] h-[16px] text-[#344054]" })
109964
+ }
109965
+ )
109966
+ ] })
109967
+ ] }),
109968
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-auto", children: loading ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "h-full flex flex-col items-center justify-center gap-[8px] text-[13px] text-[#667085]", children: [
109969
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Loader2, { className: "w-[20px] h-[20px] animate-spin text-[#155EEF]" }),
109970
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Loading event logs…" })
109971
+ ] }) : error ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "h-full flex flex-col items-center justify-center gap-[8px] text-[13px] text-[#B42318] px-[24px] text-center", children: [
109972
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium", children: "Couldn't load event logs" }),
109973
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[12px] text-[#667085]", children: error })
109974
+ ] }) : events.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full flex items-center justify-center text-[13px] text-[#667085]", children: "No events recorded for this session yet." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative px-[24px] pt-[28px] pb-[8px]", children: [
109975
+ events.length > 1 && /* @__PURE__ */ jsxRuntimeExports.jsx(
109976
+ "div",
109977
+ {
109978
+ className: "absolute w-px bg-[#D0D5DD]",
109979
+ style: { left: "32px", top: "36px", bottom: "28px" },
109980
+ "aria-hidden": "true"
109981
+ }
109982
+ ),
109983
+ events.map((event) => /* @__PURE__ */ jsxRuntimeExports.jsx(
109984
+ EventRow,
109985
+ {
109986
+ event,
109987
+ isExpanded: expandedIds.has(event.id),
109988
+ onToggle: () => toggleRow(event.id)
109989
+ },
109990
+ event.id
109991
+ ))
109992
+ ] }) })
109993
+ ]
109994
+ }
109995
+ )
109996
+ ] }) });
109997
+ }
109998
+ function hasNonEmptySessionReference(ref) {
109999
+ return typeof ref === "string" && ref.trim().length > 0;
110000
+ }
109294
110001
  function DetailPage({
109295
110002
  mode: initialMode,
109296
110003
  sessionId: initialSessionId,
@@ -109303,7 +110010,9 @@ function DetailPage({
109303
110010
  batchSize = DEFAULT_BATCH_SIZE,
109304
110011
  initialTraceCount,
109305
110012
  initialSessionData,
109306
- runHeaderInputMode = "display"
110013
+ runHeaderInputMode = "display",
110014
+ onViewEventLogs,
110015
+ fetchEventLogs
109307
110016
  }) {
109308
110017
  const [currentMode, setCurrentMode] = useState(initialMode);
109309
110018
  const [currentSessionId, setCurrentSessionId] = useState(initialSessionId);
@@ -109313,6 +110022,7 @@ function DetailPage({
109313
110022
  const traceId = currentTraceId;
109314
110023
  const [selectedNode, setSelectedNode] = useState(null);
109315
110024
  const [copiedId, setCopiedId] = useState(false);
110025
+ const [isEventLogsOpen, setIsEventLogsOpen] = useState(false);
109316
110026
  const minObservationLevel = "DEFAULT";
109317
110027
  const [hasAutoSelected, setHasAutoSelected] = useState(false);
109318
110028
  const hasInitialData = mode === "session" && initialSessionData;
@@ -109358,7 +110068,8 @@ function DetailPage({
109358
110068
  bookmarked: false,
109359
110069
  public: false,
109360
110070
  traces: [],
109361
- scores: []
110071
+ scores: [],
110072
+ sessionReference: meta.sessionReference
109362
110073
  });
109363
110074
  setLoadingState("success");
109364
110075
  },
@@ -109542,6 +110253,10 @@ function DetailPage({
109542
110253
  } : null
109543
110254
  };
109544
110255
  }, [mode, sessionData, traceData, sessionId, traceId, initialSessionData]);
110256
+ const sessionReferenceForEventLogs = useMemo(() => {
110257
+ return (initialSessionData == null ? void 0 : initialSessionData.sessionReference) ?? (sessionData == null ? void 0 : sessionData.sessionReference);
110258
+ }, [initialSessionData == null ? void 0 : initialSessionData.sessionReference, sessionData == null ? void 0 : sessionData.sessionReference]);
110259
+ const showEventLogsBanner = mode === "session" && hasNonEmptySessionReference(sessionReferenceForEventLogs);
109545
110260
  const traces = useMemo(() => {
109546
110261
  if (mode === "session" && sessionData) {
109547
110262
  const sorted = [...sessionData.traces].sort((a4, b2) => {
@@ -109590,6 +110305,16 @@ function DetailPage({
109590
110305
  mode,
109591
110306
  traceData
109592
110307
  ]);
110308
+ const handleViewEventLogs = useCallback(() => {
110309
+ setIsEventLogsOpen(true);
110310
+ if (onViewEventLogs && sessionId) {
110311
+ const firstTraceId = traces.length > 0 ? traces[0].id : void 0;
110312
+ onViewEventLogs(sessionId, firstTraceId);
110313
+ }
110314
+ }, [onViewEventLogs, sessionId, traces]);
110315
+ const handleCloseEventLogs = useCallback(() => {
110316
+ setIsEventLogsOpen(false);
110317
+ }, []);
109593
110318
  const handleNodeSelect = useCallback((node) => {
109594
110319
  setSelectedNode(node);
109595
110320
  }, []);
@@ -109806,6 +110531,7 @@ function DetailPage({
109806
110531
  ] }),
109807
110532
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 flex overflow-hidden", children: [
109808
110533
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-[480px] min-w-[400px] max-w-[600px] border-r border-[#E4E7EC] flex flex-col bg-[#F9FAFB] overflow-auto", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 p-[16px]", children: [
110534
+ showEventLogsBanner && /* @__PURE__ */ jsxRuntimeExports.jsx(VoiceEventLogsBanner, { onViewEventLogs: handleViewEventLogs }),
109809
110535
  traces.length === 0 && loadingState === "success" && progressiveState.traceCount === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "py-[32px] text-center text-[13px] text-[#667085]", children: "No traces available" }),
109810
110536
  traces.map((trace, index) => {
109811
110537
  var _a, _b, _c, _d;
@@ -109855,7 +110581,16 @@ function DetailPage({
109855
110581
  generationSummaryInputOverride
109856
110582
  }
109857
110583
  )
109858
- ] })
110584
+ ] }),
110585
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
110586
+ EventLogsSlideout,
110587
+ {
110588
+ isOpen: isEventLogsOpen,
110589
+ onClose: handleCloseEventLogs,
110590
+ sessionId: sessionId ?? null,
110591
+ fetchEventLogs
110592
+ }
110593
+ )
109859
110594
  ] });
109860
110595
  }
109861
110596
  const trace1Observations = [
@@ -110269,7 +111004,7 @@ function EnvironmentNameCell$1({ envId }) {
110269
111004
  return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-gray-600", title: envId || "-", children: displayName });
110270
111005
  }
110271
111006
  function SessionsListContent(props) {
110272
- const { apiConfig, onSessionClick, className = "", defaultFilters = [], defaultTimeRange = "24 hours", initialSessionId } = props;
111007
+ const { apiConfig, onSessionClick, className = "", defaultFilters = [], defaultTimeRange = "24 hours", initialSessionId, onViewEventLogs, fetchEventLogs } = props;
110273
111008
  const { environments, resolveEnvironmentName } = useEnvironment();
110274
111009
  const [selectedSessionId, setSelectedSessionId] = useState(() => initialSessionId ?? null);
110275
111010
  const [selectedSessionData, setSelectedSessionData] = useState(null);
@@ -110830,7 +111565,8 @@ function SessionsListContent(props) {
110830
111565
  totalCost: session.totalCost,
110831
111566
  totalTokens: session.totalTokens,
110832
111567
  sessionDuration: session.sessionDuration,
110833
- createdAt: session.createdAt
111568
+ createdAt: session.createdAt,
111569
+ sessionReference: session.sessionReference
110834
111570
  });
110835
111571
  setIsModalOpen(true);
110836
111572
  if (onSessionClick) {
@@ -110940,7 +111676,9 @@ function SessionsListContent(props) {
110940
111676
  sessionId: selectedSessionId,
110941
111677
  apiConfig,
110942
111678
  onClose: handleModalClose,
110943
- initialSessionData: selectedSessionData || void 0
111679
+ initialSessionData: selectedSessionData || void 0,
111680
+ onViewEventLogs,
111681
+ fetchEventLogs
110944
111682
  }
110945
111683
  ) })
110946
111684
  ] });
@@ -112816,6 +113554,57 @@ function calculateNodeMetrics(node) {
112816
113554
  return { totalTokens, totalCost, totalDuration };
112817
113555
  }
112818
113556
  class TreeBuilder {
113557
+ static isPreProcessorNode(node) {
113558
+ const normalizedName = (node.name || "").replace(/[^a-z0-9]/gi, "").toLowerCase();
113559
+ return node.type === "tool" && normalizedName === "preprocessor";
113560
+ }
113561
+ static normalizeNodeName(name) {
113562
+ return (name || "").replace(/[^a-z0-9]/gi, "").toLowerCase();
113563
+ }
113564
+ static normalizeLinkedEventType(node) {
113565
+ var _a;
113566
+ const linkedEventType = (_a = node.metadata) == null ? void 0 : _a.linkedEventType;
113567
+ if (typeof linkedEventType !== "string" || linkedEventType.trim().length === 0) {
113568
+ return null;
113569
+ }
113570
+ return linkedEventType.replace(/[^a-z0-9]/gi, "").toLowerCase();
113571
+ }
113572
+ static normalizeParentId(parentId) {
113573
+ if (typeof parentId !== "string") {
113574
+ return parentId ?? null;
113575
+ }
113576
+ const trimmedParentId = parentId.trim();
113577
+ if (trimmedParentId.length === 0 || trimmedParentId.toLowerCase() === "null" || trimmedParentId.toLowerCase() === "undefined") {
113578
+ return null;
113579
+ }
113580
+ return trimmedParentId;
113581
+ }
113582
+ static isTargetSystemEventNode(node) {
113583
+ const normalizedName = this.normalizeNodeName(node.name || "");
113584
+ if (this.TARGET_EVENT_NAMES.has(normalizedName)) return true;
113585
+ return typeof node.type === "string" && node.type.toLowerCase() === "event";
113586
+ }
113587
+ static compareNodesForDisplay(a4, b2) {
113588
+ const aIsPreProcessor = this.isPreProcessorNode(a4);
113589
+ const bIsPreProcessor = this.isPreProcessorNode(b2);
113590
+ const aIsTargetEvent = this.isTargetSystemEventNode(a4);
113591
+ const bIsTargetEvent = this.isTargetSystemEventNode(b2);
113592
+ const aLinkedEventType = this.normalizeLinkedEventType(a4);
113593
+ const bLinkedEventType = this.normalizeLinkedEventType(b2);
113594
+ const aTargetName = this.normalizeNodeName(a4.name || "");
113595
+ const bTargetName = this.normalizeNodeName(b2.name || "");
113596
+ if (aIsPreProcessor && bIsTargetEvent && aLinkedEventType !== null && aLinkedEventType === bTargetName) {
113597
+ return -1;
113598
+ }
113599
+ if (aIsTargetEvent && bIsPreProcessor && bLinkedEventType !== null && bLinkedEventType === aTargetName) {
113600
+ return 1;
113601
+ }
113602
+ const timestampDiff = new Date(a4.startTime).getTime() - new Date(b2.startTime).getTime();
113603
+ if (timestampDiff !== 0) {
113604
+ return timestampDiff;
113605
+ }
113606
+ return (a4.name || "").localeCompare(b2.name || "");
113607
+ }
112819
113608
  /**
112820
113609
  * Process execution events and build a hierarchical tree structure
112821
113610
  * Session > Run > Node Tree
@@ -112874,6 +113663,7 @@ class TreeBuilder {
112874
113663
  const node = this.createTreeNodeFromEvents(startedEvent, completedEvent, runId);
112875
113664
  nodes.push(node);
112876
113665
  }
113666
+ this.alignEventPreProcessorNodes(nodes);
112877
113667
  const rootNodes = this.buildNodeHierarchy(nodes);
112878
113668
  const runEvents = events.filter((e3) => e3.runId === runId);
112879
113669
  const startTime = Math.min(...runEvents.map((e3) => new Date(e3.data.timestamp).getTime()));
@@ -112956,8 +113746,10 @@ class TreeBuilder {
112956
113746
  nodes.forEach((node) => nodeMap.set(node.id, node));
112957
113747
  const rootNodes = [];
112958
113748
  nodes.forEach((node) => {
112959
- if (node.parentId && nodeMap.has(node.parentId)) {
112960
- const parent = nodeMap.get(node.parentId);
113749
+ const normalizedParentId = this.normalizeParentId(node.parentId);
113750
+ node.parentId = normalizedParentId;
113751
+ if (normalizedParentId && nodeMap.has(normalizedParentId)) {
113752
+ const parent = nodeMap.get(normalizedParentId);
112961
113753
  parent.children.push(node);
112962
113754
  node.level = parent.level + 1;
112963
113755
  } else {
@@ -112965,12 +113757,98 @@ class TreeBuilder {
112965
113757
  node.level = 0;
112966
113758
  }
112967
113759
  });
112968
- rootNodes.sort(
112969
- (a4, b2) => new Date(a4.startTime).getTime() - new Date(b2.startTime).getTime()
112970
- );
113760
+ rootNodes.sort((a4, b2) => this.compareNodesForDisplay(a4, b2));
112971
113761
  rootNodes.forEach((root2) => this.sortChildren(root2));
113762
+ this.relocateRootEventPreProcessors(rootNodes);
112972
113763
  return rootNodes;
112973
113764
  }
113765
+ static alignEventPreProcessorNodes(nodes) {
113766
+ const targetEvents = nodes.filter((node) => this.isTargetSystemEventNode(node)).sort((a4, b2) => new Date(a4.startTime).getTime() - new Date(b2.startTime).getTime());
113767
+ if (targetEvents.length === 0) {
113768
+ return;
113769
+ }
113770
+ const orphanPreProcessors = nodes.filter((node) => this.isPreProcessorNode(node) && this.normalizeParentId(node.parentId) === null).sort((a4, b2) => new Date(a4.startTime).getTime() - new Date(b2.startTime).getTime());
113771
+ for (const preProcessorNode of orphanPreProcessors) {
113772
+ const linkedEventType = this.normalizeLinkedEventType(preProcessorNode);
113773
+ if (linkedEventType === null) {
113774
+ continue;
113775
+ }
113776
+ const candidateEvents = targetEvents.filter(
113777
+ (eventNode) => this.normalizeNodeName(eventNode.name || "") === linkedEventType
113778
+ );
113779
+ if (candidateEvents.length === 0) {
113780
+ continue;
113781
+ }
113782
+ const preProcessorTime = new Date(preProcessorNode.startTime).getTime();
113783
+ let selectedTargetEvent = candidateEvents[0];
113784
+ let minDistance = Number.POSITIVE_INFINITY;
113785
+ for (const targetEvent of candidateEvents) {
113786
+ const distance = Math.abs(new Date(targetEvent.startTime).getTime() - preProcessorTime);
113787
+ if (distance < minDistance) {
113788
+ selectedTargetEvent = targetEvent;
113789
+ minDistance = distance;
113790
+ }
113791
+ }
113792
+ preProcessorNode.parentId = this.normalizeParentId(selectedTargetEvent.parentId);
113793
+ }
113794
+ }
113795
+ static relocateRootEventPreProcessors(rootNodes) {
113796
+ var _a;
113797
+ const preprocessorsAtRoot = rootNodes.filter((node) => this.isPreProcessorNode(node));
113798
+ if (preprocessorsAtRoot.length === 0) {
113799
+ return;
113800
+ }
113801
+ const collectTargetNodes = (nodesToSearch, parentNode2, collector) => {
113802
+ nodesToSearch.forEach((node, index) => {
113803
+ if (this.isTargetSystemEventNode(node)) {
113804
+ collector.push({ node, siblings: nodesToSearch, index, parentNode: parentNode2 });
113805
+ }
113806
+ if (node.children.length > 0) {
113807
+ collectTargetNodes(node.children, node, collector);
113808
+ }
113809
+ });
113810
+ };
113811
+ const targetNodes = [];
113812
+ collectTargetNodes(rootNodes, null, targetNodes);
113813
+ if (targetNodes.length === 0) {
113814
+ return;
113815
+ }
113816
+ const rootSet = new Set(rootNodes);
113817
+ for (const preProcessorNode of preprocessorsAtRoot) {
113818
+ if (!rootSet.has(preProcessorNode)) {
113819
+ continue;
113820
+ }
113821
+ const linkedEventType = this.normalizeLinkedEventType(preProcessorNode);
113822
+ if (linkedEventType === null) {
113823
+ continue;
113824
+ }
113825
+ const candidateTargets = targetNodes.filter(
113826
+ (target) => this.normalizeNodeName(target.node.name || "") === linkedEventType
113827
+ );
113828
+ if (candidateTargets.length === 0) {
113829
+ continue;
113830
+ }
113831
+ const preProcessorTime = new Date(preProcessorNode.startTime).getTime();
113832
+ let selectedTarget = candidateTargets[0];
113833
+ let selectedDistance = Number.POSITIVE_INFINITY;
113834
+ for (const candidate of candidateTargets) {
113835
+ const candidateTime = new Date(candidate.node.startTime).getTime();
113836
+ const distance = Math.abs(candidateTime - preProcessorTime);
113837
+ if (distance < selectedDistance) {
113838
+ selectedTarget = candidate;
113839
+ selectedDistance = distance;
113840
+ }
113841
+ }
113842
+ const rootIndex = rootNodes.indexOf(preProcessorNode);
113843
+ if (rootIndex >= 0) {
113844
+ rootNodes.splice(rootIndex, 1);
113845
+ rootSet.delete(preProcessorNode);
113846
+ }
113847
+ preProcessorNode.parentId = ((_a = selectedTarget.parentNode) == null ? void 0 : _a.id) ?? null;
113848
+ selectedTarget.siblings.splice(selectedTarget.index, 0, preProcessorNode);
113849
+ selectedTarget.siblings.sort((a4, b2) => this.compareNodesForDisplay(a4, b2));
113850
+ }
113851
+ }
112974
113852
  /**
112975
113853
  * Extract LLM usage metadata from output and event metadata (configurable path)
112976
113854
  */
@@ -113062,9 +113940,7 @@ class TreeBuilder {
113062
113940
  */
113063
113941
  static sortChildren(node) {
113064
113942
  if (!node) return;
113065
- node.children.sort(
113066
- (a4, b2) => new Date(a4.startTime).getTime() - new Date(b2.startTime).getTime()
113067
- );
113943
+ node.children.sort((a4, b2) => this.compareNodesForDisplay(a4, b2));
113068
113944
  node.children.forEach((child) => this.sortChildren(child));
113069
113945
  }
113070
113946
  /**
@@ -113318,6 +114194,10 @@ class TreeBuilder {
113318
114194
  );
113319
114195
  }
113320
114196
  }
114197
+ __publicField(TreeBuilder, "TARGET_EVENT_NAMES", /* @__PURE__ */ new Set([
114198
+ "endofconversation",
114199
+ "agenthandoff"
114200
+ ]));
113321
114201
  const CodeEditor = ({
113322
114202
  value,
113323
114203
  onChange,