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

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 (65) hide show
  1. package/dist/assets/agentic-ui-libs.css +69 -4
  2. package/dist/features/debug-logs/DebugPanel.d.ts.map +1 -1
  3. package/dist/features/debug-logs/components/DebugCard.d.ts.map +1 -1
  4. package/dist/features/debug-logs/index.d.ts +1 -1
  5. package/dist/features/debug-logs/index.d.ts.map +1 -1
  6. package/dist/features/debug-logs/services/ApiService.d.ts.map +1 -1
  7. package/dist/features/debug-logs/services/TreeBuilder.d.ts +3 -3
  8. package/dist/features/debug-logs/services/TreeBuilder.d.ts.map +1 -1
  9. package/dist/features/debug-logs/types.d.ts +13 -2
  10. package/dist/features/debug-logs/types.d.ts.map +1 -1
  11. package/dist/features/md-editor/MDEditor.d.ts.map +1 -1
  12. package/dist/features/md-editor/components/AIDesignPanel.d.ts.map +1 -1
  13. package/dist/features/md-editor/components/EmptyStatePlaceholder.d.ts +21 -0
  14. package/dist/features/md-editor/components/EmptyStatePlaceholder.d.ts.map +1 -0
  15. package/dist/features/md-editor/components/UnifiedToolbar.d.ts +4 -0
  16. package/dist/features/md-editor/components/UnifiedToolbar.d.ts.map +1 -1
  17. package/dist/features/md-editor/components/VariableMenu.d.ts.map +1 -1
  18. package/dist/features/md-editor/components/icons/CategoryIcons.d.ts +1 -0
  19. package/dist/features/md-editor/components/icons/CategoryIcons.d.ts.map +1 -1
  20. package/dist/features/md-editor/components/index.d.ts +2 -0
  21. package/dist/features/md-editor/components/index.d.ts.map +1 -1
  22. package/dist/features/md-editor/hooks/useAIRefinementSession.d.ts +3 -1
  23. package/dist/features/md-editor/hooks/useAIRefinementSession.d.ts.map +1 -1
  24. package/dist/features/md-editor/index.d.ts +1 -1
  25. package/dist/features/md-editor/index.d.ts.map +1 -1
  26. package/dist/features/md-editor/types.d.ts +58 -2
  27. package/dist/features/md-editor/types.d.ts.map +1 -1
  28. package/dist/features/md-editor/utils/index.d.ts +1 -0
  29. package/dist/features/md-editor/utils/index.d.ts.map +1 -1
  30. package/dist/features/md-editor/utils/variableContext.d.ts +38 -0
  31. package/dist/features/md-editor/utils/variableContext.d.ts.map +1 -0
  32. package/dist/features/tracing/components/SessionsList.d.ts.map +1 -1
  33. package/dist/features/tracing/components/TracesList.d.ts.map +1 -1
  34. package/dist/features/tracing/components/detail/DetailPage.d.ts +1 -1
  35. package/dist/features/tracing/components/detail/DetailPage.d.ts.map +1 -1
  36. package/dist/features/tracing/components/detail/NodeDetailPanel.d.ts +1 -1
  37. package/dist/features/tracing/components/detail/NodeDetailPanel.d.ts.map +1 -1
  38. package/dist/features/tracing/components/detail/ObservationNode.d.ts.map +1 -1
  39. package/dist/features/tracing/components/detail/TraceTree.d.ts +1 -1
  40. package/dist/features/tracing/components/detail/TraceTree.d.ts.map +1 -1
  41. package/dist/features/tracing/components/detail/config/observationFilterConfig.d.ts.map +1 -1
  42. package/dist/features/tracing/components/detail/services/DetailPageService.d.ts.map +1 -1
  43. package/dist/features/tracing/components/detail/types.d.ts +22 -0
  44. package/dist/features/tracing/components/detail/types.d.ts.map +1 -1
  45. package/dist/features/tracing/components/shared/CopyableId.d.ts +11 -0
  46. package/dist/features/tracing/components/shared/CopyableId.d.ts.map +1 -0
  47. package/dist/features/tracing/components/shared/TracingListHeader.d.ts +2 -1
  48. package/dist/features/tracing/components/shared/TracingListHeader.d.ts.map +1 -1
  49. package/dist/features/tracing/components/shared/TracingTable.d.ts.map +1 -1
  50. package/dist/features/tracing/components/shared/index.d.ts +1 -0
  51. package/dist/features/tracing/components/shared/index.d.ts.map +1 -1
  52. package/dist/features/tracing/services/TraceTreeService.d.ts +39 -2
  53. package/dist/features/tracing/services/TraceTreeService.d.ts.map +1 -1
  54. package/dist/features/tracing/services/TracingApiService.d.ts +13 -1
  55. package/dist/features/tracing/services/TracingApiService.d.ts.map +1 -1
  56. package/dist/features/tracing/types.d.ts +10 -0
  57. package/dist/features/tracing/types.d.ts.map +1 -1
  58. package/dist/index.angular.d.ts +1 -1
  59. package/dist/index.angular.d.ts.map +1 -1
  60. package/dist/index.d.ts +1 -1
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +1554 -433
  63. package/dist/shared/ui/DataViewer.d.ts.map +1 -1
  64. package/dist/ui-libs.umd.js +1554 -433
  65. package/package.json +3 -2
package/dist/index.js CHANGED
@@ -30860,7 +30860,7 @@ class DashboardApiService {
30860
30860
  listViewData.forEach((item) => {
30861
30861
  if (item.modelName) {
30862
30862
  options.push({
30863
- label: item.modelName,
30863
+ label: item.connectionName ? `${item.modelName} - ${item.connectionName}` : item.modelName,
30864
30864
  value: item.modelName.replace(/[-\.]/g, ""),
30865
30865
  icon: getModelIconPath2(item.provider),
30866
30866
  // Use actual SVG icon path
@@ -35509,6 +35509,31 @@ class TracingApiService {
35509
35509
  traces: data.traces || []
35510
35510
  };
35511
35511
  }
35512
+ /**
35513
+ * Get total count of traces matching filters (for pagination)
35514
+ * Endpoint: /tracing/api/trpc/traces.countAll
35515
+ */
35516
+ async fetchTracesCount(projectId, filters, options = {}) {
35517
+ const input = {
35518
+ json: {
35519
+ projectId,
35520
+ filter: filters,
35521
+ searchQuery: options.searchQuery ?? null,
35522
+ searchType: options.searchType ?? ["id"],
35523
+ page: 0,
35524
+ limit: 0,
35525
+ orderBy: options.orderBy ?? null
35526
+ },
35527
+ meta: {
35528
+ values: this.buildMetaValues(filters)
35529
+ }
35530
+ };
35531
+ const url = this.buildTrpcUrl("traces.countAll", input);
35532
+ const data = await this.makeRequest(url);
35533
+ return {
35534
+ totalCount: (data == null ? void 0 : data.totalCount) ?? 0
35535
+ };
35536
+ }
35512
35537
  /**
35513
35538
  * Fetch metrics for multiple traces (latency, tokens, cost)
35514
35539
  * Endpoint: /tracing/api/trpc/traces.metrics
@@ -36582,6 +36607,140 @@ function TokenBreakdownTooltip(props) {
36582
36607
  ] }) })
36583
36608
  ] });
36584
36609
  }
36610
+ const CopyButton$1 = ({
36611
+ text,
36612
+ className = "",
36613
+ iconClassName = "",
36614
+ iconStyle,
36615
+ title = "Copy to clipboard",
36616
+ onCopySuccess,
36617
+ onCopyError,
36618
+ tooltipText = "Copied!",
36619
+ tooltipPosition = "bottom",
36620
+ size = "md"
36621
+ }) => {
36622
+ const [showTooltip, setShowTooltip] = useState(false);
36623
+ const getSizeClasses = () => {
36624
+ switch (size) {
36625
+ case "sm":
36626
+ return {
36627
+ button: "p-1",
36628
+ icon: "w-[12px] h-[12px]",
36629
+ tooltip: "text-xs py-1 px-2"
36630
+ };
36631
+ case "lg":
36632
+ return {
36633
+ button: "p-2",
36634
+ icon: "w-[20px] h-[20px]",
36635
+ tooltip: "text-sm py-2 px-3"
36636
+ };
36637
+ default:
36638
+ return {
36639
+ button: "p-1.5",
36640
+ icon: "w-[16px] h-[16px]",
36641
+ tooltip: "text-xs py-1 px-2"
36642
+ };
36643
+ }
36644
+ };
36645
+ const getTooltipPositionClasses = () => {
36646
+ const baseClasses = "absolute bg-gray-800 text-white rounded whitespace-nowrap z-50";
36647
+ switch (tooltipPosition) {
36648
+ case "bottom":
36649
+ return `${baseClasses} top-full mt-1 left-1/2 -translate-x-1/2`;
36650
+ case "left":
36651
+ return `${baseClasses} right-full mr-1 top-1/2 -translate-y-1/2`;
36652
+ case "right":
36653
+ return `${baseClasses} left-full ml-1 top-1/2 -translate-y-1/2`;
36654
+ default:
36655
+ return `${baseClasses} bottom-full mb-1 left-1/2 -translate-x-1/2`;
36656
+ }
36657
+ };
36658
+ const sizeClasses2 = getSizeClasses();
36659
+ const showCopyTooltip = useCallback(() => {
36660
+ setShowTooltip(true);
36661
+ setTimeout(() => setShowTooltip(false), 1e3);
36662
+ }, []);
36663
+ const copyToClipboard2 = useCallback(async () => {
36664
+ try {
36665
+ if (navigator.clipboard && navigator.clipboard.writeText) {
36666
+ await navigator.clipboard.writeText(text);
36667
+ showCopyTooltip();
36668
+ onCopySuccess == null ? void 0 : onCopySuccess();
36669
+ return;
36670
+ }
36671
+ const textArea = document.createElement("textarea");
36672
+ textArea.value = text;
36673
+ textArea.style.position = "fixed";
36674
+ textArea.style.left = "-999999px";
36675
+ textArea.style.top = "-999999px";
36676
+ document.body.appendChild(textArea);
36677
+ textArea.focus();
36678
+ textArea.select();
36679
+ try {
36680
+ document.execCommand("copy");
36681
+ showCopyTooltip();
36682
+ onCopySuccess == null ? void 0 : onCopySuccess();
36683
+ } catch (err) {
36684
+ const error = err instanceof Error ? err : new Error("Copy failed");
36685
+ console.warn("Copy to clipboard failed:", error);
36686
+ onCopyError == null ? void 0 : onCopyError(error);
36687
+ } finally {
36688
+ document.body.removeChild(textArea);
36689
+ }
36690
+ } catch (err) {
36691
+ const error = err instanceof Error ? err : new Error("Copy failed");
36692
+ console.warn("Copy to clipboard failed:", error);
36693
+ onCopyError == null ? void 0 : onCopyError(error);
36694
+ }
36695
+ }, [text, showCopyTooltip, onCopySuccess, onCopyError]);
36696
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative inline-flex", children: [
36697
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
36698
+ "button",
36699
+ {
36700
+ onClick: copyToClipboard2,
36701
+ className: `${sizeClasses2.button} hover:bg-gray-100 rounded transition-colors ${className}`,
36702
+ title,
36703
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: `${sizeClasses2.icon} text-gray-400 ${iconClassName}`, style: iconStyle })
36704
+ }
36705
+ ),
36706
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
36707
+ "div",
36708
+ {
36709
+ className: `${getTooltipPositionClasses()} ${sizeClasses2.tooltip} transition-opacity duration-150 ${showTooltip ? "opacity-100 animate-fade-in" : "opacity-0 pointer-events-none"}`,
36710
+ style: {
36711
+ visibility: showTooltip ? "visible" : "hidden"
36712
+ },
36713
+ children: tooltipText
36714
+ }
36715
+ )
36716
+ ] });
36717
+ };
36718
+ function CopyableId({ value, truncateLength = 30 }) {
36719
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "copyable-id-wrapper", title: value, children: [
36720
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm font-medium text-gray-900 truncate", children: TracingUtils.truncate(value, truncateLength) }),
36721
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
36722
+ "span",
36723
+ {
36724
+ className: "copyable-id-btn",
36725
+ onClick: (e3) => {
36726
+ e3.stopPropagation();
36727
+ e3.preventDefault();
36728
+ },
36729
+ onMouseDown: (e3) => e3.stopPropagation(),
36730
+ onMouseUp: (e3) => e3.stopPropagation(),
36731
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(
36732
+ CopyButton$1,
36733
+ {
36734
+ text: value,
36735
+ size: "sm",
36736
+ title: "Copy to clipboard",
36737
+ iconClassName: "text-[#667085]"
36738
+ }
36739
+ )
36740
+ }
36741
+ )
36742
+ ] });
36743
+ }
36585
36744
  function Shimmer$2({ className = "", children }) {
36586
36745
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `animate-pulse bg-[#F2F4F7] rounded ${className}`, children });
36587
36746
  }
@@ -104592,6 +104751,9 @@ function TracingTable(props) {
104592
104751
  }, [columns]);
104593
104752
  const handleRowClick = useCallback(
104594
104753
  (event) => {
104754
+ var _a;
104755
+ const target = (_a = event.event) == null ? void 0 : _a.target;
104756
+ if (target == null ? void 0 : target.closest(".copyable-id-btn")) return;
104595
104757
  if (onRowClick && event.data) {
104596
104758
  onRowClick(event.data);
104597
104759
  }
@@ -104688,9 +104850,10 @@ function TracingTable(props) {
104688
104850
  onClick: goToFirstPage,
104689
104851
  disabled: currentPage === 0,
104690
104852
  className: "p-2 rounded hover:bg-gray-100 disabled:opacity-50 disabled:cursor-not-allowed",
104853
+ style: { color: "var(--colors-gray-light-mode-700, #344054)" },
104691
104854
  title: "First page",
104692
104855
  "data-test-id": "tracing-table-first-page-btn",
104693
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronsLeft, { className: "w-4 h-4" })
104856
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronsLeft, { size: 16 })
104694
104857
  }
104695
104858
  ),
104696
104859
  /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -104699,12 +104862,13 @@ function TracingTable(props) {
104699
104862
  onClick: goToPreviousPage,
104700
104863
  disabled: currentPage === 0,
104701
104864
  className: "p-2 rounded hover:bg-gray-100 disabled:opacity-50 disabled:cursor-not-allowed",
104865
+ style: { color: "var(--colors-gray-light-mode-700, #344054)" },
104702
104866
  title: "Previous page",
104703
104867
  "data-test-id": "tracing-table-prev-page-btn",
104704
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronLeft, { className: "w-4 h-4" })
104868
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronLeft, { size: 16 })
104705
104869
  }
104706
104870
  ),
104707
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "px-4 py-2 text-sm text-gray-700", "data-test-id": "tracing-table-page-info", children: [
104871
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "px-4 py-2 text-sm", style: { color: "var(--colors-gray-light-mode-700, #344054)" }, "data-test-id": "tracing-table-page-info", children: [
104708
104872
  "Page ",
104709
104873
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium", children: currentPage + 1 }),
104710
104874
  " of",
@@ -104717,9 +104881,10 @@ function TracingTable(props) {
104717
104881
  onClick: goToNextPage,
104718
104882
  disabled: currentPage >= totalPages - 1,
104719
104883
  className: "p-2 rounded hover:bg-gray-100 disabled:opacity-50 disabled:cursor-not-allowed",
104884
+ style: { color: "var(--colors-gray-light-mode-700, #344054)" },
104720
104885
  title: "Next page",
104721
104886
  "data-test-id": "tracing-table-next-page-btn",
104722
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "w-4 h-4" })
104887
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { size: 16 })
104723
104888
  }
104724
104889
  ),
104725
104890
  /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -104728,13 +104893,14 @@ function TracingTable(props) {
104728
104893
  onClick: goToLastPage,
104729
104894
  disabled: currentPage >= totalPages - 1,
104730
104895
  className: "p-2 rounded hover:bg-gray-100 disabled:opacity-50 disabled:cursor-not-allowed",
104896
+ style: { color: "var(--colors-gray-light-mode-700, #344054)" },
104731
104897
  title: "Last page",
104732
104898
  "data-test-id": "tracing-table-last-page-btn",
104733
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronsRight, { className: "w-4 h-4" })
104899
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronsRight, { size: 16 })
104734
104900
  }
104735
104901
  )
104736
104902
  ] }),
104737
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center text-sm text-gray-700 shrink-0 absolute right-[24px]", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
104903
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center text-sm shrink-0 absolute right-[24px]", style: { color: "var(--colors-gray-light-mode-700, #344054)" }, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
104738
104904
  "Showing ",
104739
104905
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-semibold", children: startRow }),
104740
104906
  " to",
@@ -104762,9 +104928,12 @@ function TracingListHeader(props) {
104762
104928
  timeRangePresetLabel,
104763
104929
  onTimeRangeChange,
104764
104930
  filters,
104931
+ filterColumns: filterColumnsProp,
104765
104932
  onFiltersClick,
104766
104933
  onModifyColumnsClick,
104767
104934
  showModifyColumns = true,
104935
+ onClearFilters,
104936
+ onRemoveFilter,
104768
104937
  onRefresh,
104769
104938
  isRefreshing = false
104770
104939
  } = props;
@@ -104809,6 +104978,50 @@ function TracingListHeader(props) {
104809
104978
  }
104810
104979
  return `Searches in ${fields}.`;
104811
104980
  };
104981
+ const activeFilters = filters.filter(TracingUtils.isFilterActive);
104982
+ const [filtersExpanded, setFiltersExpanded] = useState(false);
104983
+ const [isOverflowing, setIsOverflowing] = useState(false);
104984
+ const chipsContainerRef = useRef(null);
104985
+ const checkOverflow = useCallback(() => {
104986
+ const el = chipsContainerRef.current;
104987
+ if (!el) return;
104988
+ setIsOverflowing(el.scrollHeight > el.clientHeight);
104989
+ }, []);
104990
+ useEffect(() => {
104991
+ checkOverflow();
104992
+ window.addEventListener("resize", checkOverflow);
104993
+ return () => window.removeEventListener("resize", checkOverflow);
104994
+ }, [checkOverflow, activeFilters.length]);
104995
+ const getFilterChipLabel = (filter) => {
104996
+ const col = filterColumnsProp == null ? void 0 : filterColumnsProp.find((c3) => c3.field === filter.column);
104997
+ const label = (col == null ? void 0 : col.label) ?? filter.column;
104998
+ let valueText;
104999
+ if (filter.type === "datetime") {
105000
+ valueText = new Date(filter.value).toLocaleDateString();
105001
+ } else if (filter.type === "number") {
105002
+ valueText = parseFloat(filter.value).toLocaleString();
105003
+ } else if (Array.isArray(filter.value)) {
105004
+ valueText = filter.value.length <= 2 ? filter.value.join(", ") : `${filter.value.length} selected`;
105005
+ } else {
105006
+ valueText = String(filter.value ?? "");
105007
+ }
105008
+ const shortOp = {
105009
+ "=": "",
105010
+ "!=": "≠ ",
105011
+ ">": "> ",
105012
+ ">=": "≥ ",
105013
+ "<": "< ",
105014
+ "<=": "≤ ",
105015
+ "contains": "~ ",
105016
+ "does not contain": "!~ ",
105017
+ "starts with": "starts ",
105018
+ "ends with": "ends ",
105019
+ "any of": "",
105020
+ "none of": "not "
105021
+ };
105022
+ const op = shortOp[filter.operator] ?? `${filter.operator} `;
105023
+ return `${label}: ${op}${valueText}`;
105024
+ };
104812
105025
  const handleDateRangeChange = (dateRange, presetLabel) => {
104813
105026
  if (dateRange && dateRange.from && dateRange.to) {
104814
105027
  const fromDate = dateRange.from;
@@ -104961,7 +105174,66 @@ function TracingListHeader(props) {
104961
105174
  }
104962
105175
  )
104963
105176
  ] })
104964
- ] })
105177
+ ] }),
105178
+ activeFilters.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
105179
+ "div",
105180
+ {
105181
+ className: "flex items-start gap-[8px] border border-gray-200 rounded-[8px] px-[12px] py-[8px]",
105182
+ "data-test-id": "tracing-filter-chips",
105183
+ children: [
105184
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[12px] font-medium leading-[28px] text-gray-500 shrink-0", children: "Filters" }),
105185
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
105186
+ "div",
105187
+ {
105188
+ ref: chipsContainerRef,
105189
+ className: `flex items-center gap-[8px] flex-wrap flex-1 min-w-0 ${!filtersExpanded ? "max-h-[28px] overflow-hidden" : ""}`,
105190
+ children: activeFilters.map((filter, idx) => {
105191
+ const originalIndex = filters.indexOf(filter);
105192
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
105193
+ "div",
105194
+ {
105195
+ className: "inline-flex items-center gap-[4px] h-[28px] px-[10px] py-[4px] bg-blue-50 border border-blue-200 rounded-[6px] text-[12px] leading-[16px] text-blue-800 max-w-[260px]",
105196
+ children: [
105197
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate font-medium", children: getFilterChipLabel(filter) }),
105198
+ onRemoveFilter && /* @__PURE__ */ jsxRuntimeExports.jsx(
105199
+ "button",
105200
+ {
105201
+ onClick: () => onRemoveFilter(originalIndex),
105202
+ className: "flex items-center justify-center shrink-0 text-blue-400 hover:text-blue-700 transition-colors",
105203
+ title: "Remove filter",
105204
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "w-[14px] h-[14px]", strokeWidth: 2 })
105205
+ }
105206
+ )
105207
+ ]
105208
+ },
105209
+ `chip-${idx}`
105210
+ );
105211
+ })
105212
+ }
105213
+ ),
105214
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-[8px] shrink-0 leading-[28px]", children: [
105215
+ (isOverflowing || filtersExpanded) && /* @__PURE__ */ jsxRuntimeExports.jsx(
105216
+ "button",
105217
+ {
105218
+ onClick: () => setFiltersExpanded((prev) => !prev),
105219
+ className: "text-[12px] font-medium text-blue-600 hover:text-blue-800 transition-colors whitespace-nowrap",
105220
+ "data-test-id": "tracing-filter-toggle",
105221
+ children: filtersExpanded ? "View less" : "View all"
105222
+ }
105223
+ ),
105224
+ onClearFilters && /* @__PURE__ */ jsxRuntimeExports.jsx(
105225
+ "button",
105226
+ {
105227
+ onClick: onClearFilters,
105228
+ className: "text-[12px] font-medium text-gray-500 hover:text-gray-700 transition-colors whitespace-nowrap",
105229
+ "data-test-id": "tracing-filter-clear-all",
105230
+ children: "Clear all"
105231
+ }
105232
+ )
105233
+ ] })
105234
+ ]
105235
+ }
105236
+ )
104965
105237
  ] });
104966
105238
  }
104967
105239
  function ColumnCustomization(props) {
@@ -105448,6 +105720,8 @@ function FilterPanel(props) {
105448
105720
  ] })
105449
105721
  ] });
105450
105722
  }
105723
+ const TRACE_PII_DISPLAY_USER_MESSAGE_KEY = "piiDisplayUserMessage";
105724
+ const TRACE_PII_DISPLAY_APP_RESPONSE_KEY = "piiDisplayAppResponse";
105451
105725
  class TraceTreeService {
105452
105726
  /**
105453
105727
  * Build a hierarchical tree from a flat list of observations
@@ -105620,43 +105894,205 @@ class TraceTreeService {
105620
105894
  });
105621
105895
  }
105622
105896
  /**
105623
- * Extract user message from trace input
105897
+ * Extract user message from trace input for display.
105898
+ * Handles string, object with message/content/text/query, and messages array (e.g. voice/chat).
105899
+ */
105900
+ /**
105901
+ * Parse trace metadata from API (string or object) into a plain object.
105902
+ */
105903
+ static parseTraceMetadata(metadata) {
105904
+ if (metadata === null || metadata === void 0) {
105905
+ return {};
105906
+ }
105907
+ if (typeof metadata === "string") {
105908
+ try {
105909
+ return JSON.parse(metadata);
105910
+ } catch {
105911
+ return {};
105912
+ }
105913
+ }
105914
+ if (typeof metadata === "object" && !Array.isArray(metadata)) {
105915
+ return metadata;
105916
+ }
105917
+ return {};
105918
+ }
105919
+ /**
105920
+ * Read PII display strings from Langfuse/Kore trace metadata (if present).
105624
105921
  */
105922
+ static extractPiiDisplayFromTraceMetadata(metadata) {
105923
+ const obj = this.parseTraceMetadata(metadata);
105924
+ const userRaw = obj[TRACE_PII_DISPLAY_USER_MESSAGE_KEY];
105925
+ const appRaw = obj[TRACE_PII_DISPLAY_APP_RESPONSE_KEY];
105926
+ const result = {};
105927
+ if (typeof userRaw === "string" && userRaw.length > 0) {
105928
+ result.displayUserMessage = userRaw;
105929
+ }
105930
+ if (typeof appRaw === "string" && appRaw.length > 0) {
105931
+ result.displayAppResponse = appRaw;
105932
+ }
105933
+ return result;
105934
+ }
105935
+ /**
105936
+ * Some tracing APIs expose custom PII display keys on trace root as well as under metadata.
105937
+ */
105938
+ static extractPiiDisplayFromApiTrace(trace) {
105939
+ const fromMeta = this.extractPiiDisplayFromTraceMetadata(trace.metadata);
105940
+ const userTop = trace[TRACE_PII_DISPLAY_USER_MESSAGE_KEY];
105941
+ const appTop = trace[TRACE_PII_DISPLAY_APP_RESPONSE_KEY];
105942
+ const fromTop = {};
105943
+ if (typeof userTop === "string" && userTop.length > 0) {
105944
+ fromTop.displayUserMessage = userTop;
105945
+ }
105946
+ if (typeof appTop === "string" && appTop.length > 0) {
105947
+ fromTop.displayAppResponse = appTop;
105948
+ }
105949
+ return {
105950
+ displayUserMessage: fromTop.displayUserMessage ?? fromMeta.displayUserMessage,
105951
+ displayAppResponse: fromTop.displayAppResponse ?? fromMeta.displayAppResponse
105952
+ };
105953
+ }
105625
105954
  static extractUserMessage(input) {
105626
105955
  if (!input) return "";
105627
105956
  if (typeof input === "string") {
105628
105957
  try {
105629
105958
  const parsed = JSON.parse(input);
105630
- return (parsed == null ? void 0 : parsed.message) || (parsed == null ? void 0 : parsed.content) || (parsed == null ? void 0 : parsed.text) || (parsed == null ? void 0 : parsed.query) || input;
105959
+ const fromParsed = (parsed == null ? void 0 : parsed.message) ?? (parsed == null ? void 0 : parsed.content) ?? (parsed == null ? void 0 : parsed.text) ?? (parsed == null ? void 0 : parsed.query);
105960
+ if (fromParsed !== void 0 && fromParsed !== null) return String(fromParsed);
105961
+ if (Array.isArray(parsed == null ? void 0 : parsed.messages)) {
105962
+ return this.extractLastUserMessageFromArray(parsed.messages);
105963
+ }
105964
+ return input;
105631
105965
  } catch {
105632
105966
  return input;
105633
105967
  }
105634
105968
  }
105635
105969
  if (typeof input === "object") {
105636
105970
  const obj = input;
105637
- return String((obj == null ? void 0 : obj["message"]) || (obj == null ? void 0 : obj["content"]) || (obj == null ? void 0 : obj["text"]) || (obj == null ? void 0 : obj["query"]) || "");
105971
+ const direct = (obj == null ? void 0 : obj["message"]) ?? (obj == null ? void 0 : obj["content"]) ?? (obj == null ? void 0 : obj["text"]) ?? (obj == null ? void 0 : obj["query"]);
105972
+ if (direct !== void 0 && direct !== null && direct !== "") {
105973
+ return typeof direct === "object" ? JSON.stringify(direct) : String(direct);
105974
+ }
105975
+ if (Array.isArray(obj == null ? void 0 : obj.messages)) {
105976
+ return this.extractLastUserMessageFromArray(obj.messages);
105977
+ }
105978
+ if (Array.isArray(input)) {
105979
+ return this.extractLastUserMessageFromArray(input);
105980
+ }
105981
+ return JSON.stringify(obj);
105638
105982
  }
105639
105983
  return String(input);
105640
105984
  }
105641
105985
  /**
105642
- * Extract app response from trace output
105986
+ * LangChain-serialized messages store role/content under `kwargs` and type in `id`.
105987
+ */
105988
+ static getLangchainMessageContent(msg) {
105989
+ if (msg["content"] !== void 0 && msg["content"] !== null) {
105990
+ return msg["content"];
105991
+ }
105992
+ const kwargs = msg["kwargs"];
105993
+ if (kwargs && typeof kwargs === "object" && !Array.isArray(kwargs)) {
105994
+ const c3 = kwargs["content"];
105995
+ if (c3 !== void 0 && c3 !== null) {
105996
+ return c3;
105997
+ }
105998
+ }
105999
+ return void 0;
106000
+ }
106001
+ static inferLangchainMessageRole(msg) {
106002
+ if (typeof msg["role"] === "string") {
106003
+ return msg["role"];
106004
+ }
106005
+ const kwargs = msg["kwargs"];
106006
+ if (kwargs && typeof kwargs === "object" && !Array.isArray(kwargs)) {
106007
+ const r2 = kwargs["role"];
106008
+ if (typeof r2 === "string") {
106009
+ return r2;
106010
+ }
106011
+ }
106012
+ const id = msg["id"];
106013
+ if (Array.isArray(id)) {
106014
+ const tail = id[id.length - 1];
106015
+ if (tail === "HumanMessage") {
106016
+ return "user";
106017
+ }
106018
+ if (tail === "AIMessage" || tail === "AIMessageChunk") {
106019
+ return "assistant";
106020
+ }
106021
+ if (tail === "SystemMessage") {
106022
+ return "system";
106023
+ }
106024
+ if (tail === "ToolMessage") {
106025
+ return "tool";
106026
+ }
106027
+ }
106028
+ return void 0;
106029
+ }
106030
+ /**
106031
+ * Get last user message content from a messages array (chat/voice format).
106032
+ */
106033
+ static extractLastUserMessageFromArray(messages) {
106034
+ if (!messages.length) return "";
106035
+ for (let i2 = messages.length - 1; i2 >= 0; i2--) {
106036
+ const msg = messages[i2];
106037
+ const role = this.inferLangchainMessageRole(msg);
106038
+ const content2 = this.getLangchainMessageContent(msg);
106039
+ if (role === "user" && content2 != null) {
106040
+ return typeof content2 === "string" ? content2 : JSON.stringify(content2);
106041
+ }
106042
+ }
106043
+ const last2 = messages[messages.length - 1];
106044
+ const content = this.getLangchainMessageContent(last2);
106045
+ if (content != null) {
106046
+ return typeof content === "string" ? content : JSON.stringify(content);
106047
+ }
106048
+ return JSON.stringify(messages[messages.length - 1]);
106049
+ }
106050
+ /**
106051
+ * Extract app response from trace output for display.
106052
+ * Handles string, object with message/content/text/response, and messages array.
105643
106053
  */
105644
106054
  static extractAppResponse(output) {
105645
106055
  if (!output) return "";
105646
106056
  if (typeof output === "string") {
105647
106057
  try {
105648
106058
  const parsed = JSON.parse(output);
105649
- return (parsed == null ? void 0 : parsed.message) || (parsed == null ? void 0 : parsed.content) || (parsed == null ? void 0 : parsed.text) || (parsed == null ? void 0 : parsed.response) || output;
106059
+ const fromParsed = (parsed == null ? void 0 : parsed.message) ?? (parsed == null ? void 0 : parsed.content) ?? (parsed == null ? void 0 : parsed.text) ?? (parsed == null ? void 0 : parsed.response);
106060
+ if (fromParsed !== void 0 && fromParsed !== null) return String(fromParsed);
106061
+ if (Array.isArray(parsed == null ? void 0 : parsed.messages)) {
106062
+ return this.extractLastMessageContentFromArray(parsed.messages);
106063
+ }
106064
+ return output;
105650
106065
  } catch {
105651
106066
  return output;
105652
106067
  }
105653
106068
  }
105654
106069
  if (typeof output === "object") {
105655
106070
  const obj = output;
105656
- return String((obj == null ? void 0 : obj["message"]) || (obj == null ? void 0 : obj["content"]) || (obj == null ? void 0 : obj["text"]) || (obj == null ? void 0 : obj["response"]) || "");
106071
+ const direct = (obj == null ? void 0 : obj["message"]) ?? (obj == null ? void 0 : obj["content"]) ?? (obj == null ? void 0 : obj["text"]) ?? (obj == null ? void 0 : obj["response"]);
106072
+ if (direct !== void 0 && direct !== null && direct !== "") {
106073
+ return typeof direct === "object" ? JSON.stringify(direct) : String(direct);
106074
+ }
106075
+ if (Array.isArray(obj == null ? void 0 : obj.messages)) {
106076
+ return this.extractLastMessageContentFromArray(obj.messages);
106077
+ }
106078
+ if (Array.isArray(output)) {
106079
+ return this.extractLastMessageContentFromArray(output);
106080
+ }
106081
+ return JSON.stringify(obj);
105657
106082
  }
105658
106083
  return String(output);
105659
106084
  }
106085
+ /**
106086
+ * Get last message content from a messages array for output display.
106087
+ */
106088
+ static extractLastMessageContentFromArray(messages) {
106089
+ if (!messages.length) return "";
106090
+ const last2 = messages[messages.length - 1];
106091
+ const fromKwargs = this.getLangchainMessageContent(last2);
106092
+ const content = fromKwargs ?? (last2 == null ? void 0 : last2.message) ?? (last2 == null ? void 0 : last2.text);
106093
+ if (content != null) return typeof content === "string" ? content : JSON.stringify(content);
106094
+ return JSON.stringify(last2);
106095
+ }
105660
106096
  /**
105661
106097
  * Calculate trace metrics from observations
105662
106098
  */
@@ -105666,7 +106102,9 @@ class TraceTreeService {
105666
106102
  let maxEndTime = 0;
105667
106103
  let minStartTime = Infinity;
105668
106104
  observations.forEach((obs) => {
105669
- totalTokens += obs.totalTokens || 0;
106105
+ var _a;
106106
+ const obsTokens = ((_a = obs.usageDetails) == null ? void 0 : _a.total) ?? obs.totalUsage ?? obs.totalTokens;
106107
+ totalTokens += typeof obsTokens === "number" ? obsTokens : parseInt(String(obsTokens || 0), 10) || 0;
105670
106108
  const cost = parseFloat(obs.totalCost || "0");
105671
106109
  if (!isNaN(cost)) totalCost += cost;
105672
106110
  const startMs = new Date(obs.startTime).getTime();
@@ -105689,7 +106127,15 @@ class TraceTreeService {
105689
106127
  );
105690
106128
  const generation = sorted.find((obs) => obs.type === "GENERATION");
105691
106129
  if (!generation) {
105692
- return { observation: null, ancestorIds: [] };
106130
+ const tree = this.buildObservationTree(observations);
106131
+ if (tree.length === 0) return { observation: null, ancestorIds: [] };
106132
+ const findFirstLeaf = (node) => {
106133
+ if (node.children.length === 0) return node;
106134
+ return findFirstLeaf(node.children[0]);
106135
+ };
106136
+ const leafNode = findFirstLeaf(tree[0]);
106137
+ const ancestorIds2 = this.getAncestorIds(observations, leafNode.observation.id);
106138
+ return { observation: leafNode.observation, ancestorIds: ancestorIds2 };
105693
106139
  }
105694
106140
  const ancestorIds = this.getAncestorIds(observations, generation.id);
105695
106141
  return { observation: generation, ancestorIds };
@@ -105836,6 +106282,7 @@ const observationFilterConfig = {
105836
106282
  "toolNode",
105837
106283
  "agent_toolNode",
105838
106284
  "PreProcessor",
106285
+ "PostProcessor",
105839
106286
  "MergerNode"
105840
106287
  ]
105841
106288
  }
@@ -106095,6 +106542,7 @@ class DetailPageService {
106095
106542
  * Transform API trace response to TraceDetailData
106096
106543
  */
106097
106544
  transformToTraceDetailData(trace) {
106545
+ const piiDisplay = TraceTreeService.extractPiiDisplayFromApiTrace(trace);
106098
106546
  return {
106099
106547
  id: trace.id,
106100
106548
  name: trace.name || "",
@@ -106107,6 +106555,8 @@ class DetailPageService {
106107
106555
  input: trace.input,
106108
106556
  output: trace.output,
106109
106557
  metadata: trace.metadata,
106558
+ displayUserMessage: piiDisplay.displayUserMessage,
106559
+ displayAppResponse: piiDisplay.displayAppResponse,
106110
106560
  tags: trace.tags || [],
106111
106561
  bookmarked: trace.bookmarked || false,
106112
106562
  public: trace.public || false,
@@ -106168,6 +106618,8 @@ class DetailPageService {
106168
106618
  timestamp: trace.timestamp,
106169
106619
  input: trace.input,
106170
106620
  output: trace.output,
106621
+ displayUserMessage: trace.displayUserMessage,
106622
+ displayAppResponse: trace.displayAppResponse,
106171
106623
  latency: trace.latency,
106172
106624
  totalTokens: trace.totalTokens,
106173
106625
  totalCost: typeof trace.totalCost === "number" ? String(trace.totalCost) : trace.totalCost,
@@ -106321,6 +106773,19 @@ function getObservationIconProps(observation) {
106321
106773
  name
106322
106774
  };
106323
106775
  }
106776
+ function getObservationTokens(obs) {
106777
+ var _a;
106778
+ const total = ((_a = obs.usageDetails) == null ? void 0 : _a.total) ?? obs.totalUsage ?? obs.totalTokens;
106779
+ if (total === void 0 || total === null) return 0;
106780
+ return typeof total === "number" ? total : parseInt(String(total), 10) || 0;
106781
+ }
106782
+ function getAggregatedTotalTokens(node) {
106783
+ let sum2 = getObservationTokens(node.observation);
106784
+ node.children.forEach((child) => {
106785
+ sum2 += getAggregatedTotalTokens(child);
106786
+ });
106787
+ return sum2;
106788
+ }
106324
106789
  const SuccessIcon = () => /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
106325
106790
  /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "6", cy: "6", r: "5.5", fill: "#17B26A" }),
106326
106791
  /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M4 6L5.5 7.5L8 4.5", stroke: "white", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
@@ -106382,7 +106847,11 @@ function ObservationNode({
106382
106847
  return observation.name || observation.type || "";
106383
106848
  };
106384
106849
  const displayName = getDisplayName3();
106385
- const displayTokens = ((_d = observation.usageDetails) == null ? void 0 : _d.total) || observation.totalUsage || observation.totalTokens;
106850
+ const displayTokens = ((_d = observation.usageDetails) == null ? void 0 : _d.total) ?? observation.totalUsage ?? observation.totalTokens;
106851
+ const aggregatedTotalTokens = useMemo(() => {
106852
+ if (!isSupervisorOrAgent) return 0;
106853
+ return getAggregatedTotalTokens(node);
106854
+ }, [node, isSupervisorOrAgent]);
106386
106855
  const handleRowClick = () => {
106387
106856
  if (hasChildren) {
106388
106857
  onToggle(observation.id);
@@ -106429,34 +106898,43 @@ function ObservationNode({
106429
106898
  className: "w-[24px] h-[24px] rounded-[8px]"
106430
106899
  }
106431
106900
  ) }),
106432
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-semibold text-[12px] leading-[16px] text-[#101828] truncate flex-1 min-w-0", title: displayName, children: displayName }),
106433
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-[8px] flex-shrink-0", children: [
106434
- isSupervisorOrAgent && (modelFromMetadata || observation.model) && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] leading-[12px] text-[#667085] font-normal", children: modelFromMetadata || observation.model }),
106435
- (isGeneration || isSupervisorOrAgent) && displayTokens !== void 0 && displayTokens > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[10px] leading-[12px] text-[#667085] font-normal whitespace-nowrap", children: [
106436
- TraceTreeService.formatTokens(displayTokens),
106901
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-[2px] flex-1 min-w-0", children: [
106902
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-semibold text-[12px] leading-[16px] text-[#101828] truncate", title: displayName, children: displayName }),
106903
+ isSupervisorOrAgent && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-[6px] flex-wrap text-[10px] leading-[12px] text-[#667085] font-normal", children: [
106904
+ modelFromMetadata || observation.model ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate", children: modelFromMetadata || observation.model }) : null,
106905
+ aggregatedTotalTokens > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
106906
+ (modelFromMetadata || observation.model) && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "·" }),
106907
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "whitespace-nowrap", children: [
106908
+ TraceTreeService.formatTokens(aggregatedTotalTokens),
106909
+ " Tokens"
106910
+ ] })
106911
+ ] }),
106912
+ duration > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
106913
+ modelFromMetadata || observation.model || aggregatedTotalTokens > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "·" }) : null,
106914
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "whitespace-nowrap flex items-center gap-[4px]", children: [
106915
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ClockIcon, {}),
106916
+ TraceTreeService.formatDuration(duration)
106917
+ ] })
106918
+ ] })
106919
+ ] })
106920
+ ] }),
106921
+ !isSupervisorOrAgent && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-[8px] flex-shrink-0", children: [
106922
+ isGeneration && displayTokens !== void 0 && Number(displayTokens) > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[10px] leading-[12px] text-[#667085] font-normal whitespace-nowrap", children: [
106923
+ TraceTreeService.formatTokens(Number(displayTokens)),
106437
106924
  " Tokens"
106438
106925
  ] }),
106439
106926
  duration > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-[4px]", children: [
106440
106927
  /* @__PURE__ */ jsxRuntimeExports.jsx(ClockIcon, {}),
106441
106928
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] leading-[12px] text-[#667085] font-normal whitespace-nowrap", children: TraceTreeService.formatDuration(duration) })
106442
106929
  ] }),
106443
- isError && /* @__PURE__ */ jsxRuntimeExports.jsx(
106444
- "div",
106445
- {
106446
- className: "flex-shrink-0 cursor-help",
106447
- title: statusTooltip,
106448
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorIcon, {})
106449
- }
106450
- ),
106451
- isWarning && !isError && /* @__PURE__ */ jsxRuntimeExports.jsx(
106452
- "div",
106453
- {
106454
- className: "flex-shrink-0 cursor-help",
106455
- title: statusTooltip,
106456
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(WarningIcon, {})
106457
- }
106458
- ),
106930
+ isError && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-shrink-0 cursor-help", title: statusTooltip, children: /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorIcon, {}) }),
106931
+ isWarning && !isError && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-shrink-0 cursor-help", title: statusTooltip, children: /* @__PURE__ */ jsxRuntimeExports.jsx(WarningIcon, {}) }),
106459
106932
  isCompleted && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SuccessIcon, {}) })
106933
+ ] }),
106934
+ isSupervisorOrAgent && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-shrink-0 flex items-center", children: [
106935
+ isError && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "cursor-help", title: statusTooltip, children: /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorIcon, {}) }),
106936
+ isWarning && !isError && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "cursor-help", title: statusTooltip, children: /* @__PURE__ */ jsxRuntimeExports.jsx(WarningIcon, {}) }),
106937
+ isCompleted && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsx(SuccessIcon, {}) })
106460
106938
  ] })
106461
106939
  ]
106462
106940
  }
@@ -106494,8 +106972,10 @@ function TraceTree({
106494
106972
  onNodeSelect,
106495
106973
  onExpandToggle,
106496
106974
  showTraceId = true,
106975
+ onTraceIdClick,
106497
106976
  isLoading = false,
106498
- defaultExpandedNodeIds
106977
+ defaultExpandedNodeIds,
106978
+ runHeaderInputMode = "display"
106499
106979
  }) {
106500
106980
  const [isExpanded, setIsExpanded] = useState(defaultExpanded);
106501
106981
  const [expandedNodeIds, setExpandedNodeIds] = useState(
@@ -106513,11 +106993,20 @@ function TraceTree({
106513
106993
  return TraceTreeService.buildObservationTree(observations);
106514
106994
  }, [observations]);
106515
106995
  const userMessage = useMemo(() => {
106996
+ if (runHeaderInputMode !== "tokenized" && trace.displayUserMessage !== void 0 && trace.displayUserMessage.length > 0) {
106997
+ return trace.displayUserMessage;
106998
+ }
106516
106999
  return TraceTreeService.extractUserMessage(trace.input);
106517
- }, [trace.input]);
107000
+ }, [trace.input, trace.displayUserMessage, runHeaderInputMode]);
106518
107001
  const appResponse = useMemo(() => {
107002
+ if (runHeaderInputMode !== "tokenized" && trace.displayAppResponse !== void 0 && trace.displayAppResponse.length > 0) {
107003
+ return trace.displayAppResponse;
107004
+ }
106519
107005
  return TraceTreeService.extractAppResponse(trace.output);
106520
- }, [trace.output]);
107006
+ }, [trace.output, trace.displayAppResponse, runHeaderInputMode]);
107007
+ const traceMetrics = useMemo(() => {
107008
+ return TraceTreeService.calculateTraceMetrics(trace, observations);
107009
+ }, [trace, observations]);
106521
107010
  const handleTraceToggle = useCallback(() => {
106522
107011
  setIsExpanded((prev) => !prev);
106523
107012
  onExpandToggle == null ? void 0 : onExpandToggle();
@@ -106544,7 +107033,16 @@ function TraceTree({
106544
107033
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-[4px] w-full mb-[8px]", children: [
106545
107034
  showTraceId && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-[8px] items-center px-0 py-[4px] w-full", children: [
106546
107035
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] leading-[12px] text-[#98A2B3]", children: "Trace ID" }),
106547
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium text-[10px] leading-[12px] text-[#667085]", children: trace.id }),
107036
+ onTraceIdClick ? /* @__PURE__ */ jsxRuntimeExports.jsx(
107037
+ "button",
107038
+ {
107039
+ onClick: () => onTraceIdClick(trace.id),
107040
+ className: "font-medium text-[10px] leading-[12px] text-[#155EEF] hover:underline cursor-pointer bg-transparent border-none p-0",
107041
+ title: "View Trace Details",
107042
+ "data-test-id": `trace-tree-id-link-${trace.id}`,
107043
+ children: trace.id
107044
+ }
107045
+ ) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium text-[10px] leading-[12px] text-[#667085]", children: trace.id }),
106548
107046
  /* @__PURE__ */ jsxRuntimeExports.jsx(
106549
107047
  "button",
106550
107048
  {
@@ -106619,10 +107117,18 @@ function TraceTree({
106619
107117
  rootNode.observation.id
106620
107118
  )) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "py-[16px] text-[12px] text-[#667085] text-center", children: "No observations available" }) }),
106621
107119
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white flex flex-col gap-[8px] p-[12px] border-t border-[#EAECF0]", children: [
106622
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex gap-[8px] items-center w-full", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-[8px] items-center flex-1 min-w-0", children: [
106623
- /* @__PURE__ */ jsxRuntimeExports.jsx(AppResponseIcon, {}),
106624
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-semibold text-[11px] leading-[14px] text-[#98A2B3] uppercase tracking-[0.02em] flex-1", children: "APP RESPONSE" })
106625
- ] }) }),
107120
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-[8px] items-center w-full", children: [
107121
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-[8px] items-center flex-1 min-w-0", children: [
107122
+ /* @__PURE__ */ jsxRuntimeExports.jsx(AppResponseIcon, {}),
107123
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-semibold text-[11px] leading-[14px] text-[#98A2B3] uppercase tracking-[0.02em]", children: "APP RESPONSE" })
107124
+ ] }),
107125
+ (traceMetrics.latency > 0 || traceMetrics.totalTokens > 0) && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[10px] leading-[12px] text-[#667085] font-normal whitespace-nowrap flex-shrink-0", children: [
107126
+ TraceTreeService.formatDuration(traceMetrics.latency),
107127
+ " · ",
107128
+ TraceTreeService.formatTokens(traceMetrics.totalTokens),
107129
+ " Tokens"
107130
+ ] })
107131
+ ] }),
106626
107132
  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "font-medium text-[12px] leading-[16px] text-[#101828]", children: appResponse ? appResponse.length > 150 && !isResponseExpanded ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
106627
107133
  appResponse.substring(0, 150),
106628
107134
  "...",
@@ -106655,114 +107161,6 @@ function TraceTree({
106655
107161
  ] })
106656
107162
  ] });
106657
107163
  }
106658
- const CopyButton$1 = ({
106659
- text,
106660
- className = "",
106661
- iconClassName = "",
106662
- iconStyle,
106663
- title = "Copy to clipboard",
106664
- onCopySuccess,
106665
- onCopyError,
106666
- tooltipText = "Copied!",
106667
- tooltipPosition = "bottom",
106668
- size = "md"
106669
- }) => {
106670
- const [showTooltip, setShowTooltip] = useState(false);
106671
- const getSizeClasses = () => {
106672
- switch (size) {
106673
- case "sm":
106674
- return {
106675
- button: "p-1",
106676
- icon: "w-[12px] h-[12px]",
106677
- tooltip: "text-xs py-1 px-2"
106678
- };
106679
- case "lg":
106680
- return {
106681
- button: "p-2",
106682
- icon: "w-[20px] h-[20px]",
106683
- tooltip: "text-sm py-2 px-3"
106684
- };
106685
- default:
106686
- return {
106687
- button: "p-1.5",
106688
- icon: "w-[16px] h-[16px]",
106689
- tooltip: "text-xs py-1 px-2"
106690
- };
106691
- }
106692
- };
106693
- const getTooltipPositionClasses = () => {
106694
- const baseClasses = "absolute bg-gray-800 text-white rounded whitespace-nowrap z-50";
106695
- switch (tooltipPosition) {
106696
- case "bottom":
106697
- return `${baseClasses} top-full mt-1 left-1/2 -translate-x-1/2`;
106698
- case "left":
106699
- return `${baseClasses} right-full mr-1 top-1/2 -translate-y-1/2`;
106700
- case "right":
106701
- return `${baseClasses} left-full ml-1 top-1/2 -translate-y-1/2`;
106702
- default:
106703
- return `${baseClasses} bottom-full mb-1 left-1/2 -translate-x-1/2`;
106704
- }
106705
- };
106706
- const sizeClasses2 = getSizeClasses();
106707
- const showCopyTooltip = useCallback(() => {
106708
- setShowTooltip(true);
106709
- setTimeout(() => setShowTooltip(false), 1e3);
106710
- }, []);
106711
- const copyToClipboard2 = useCallback(async () => {
106712
- try {
106713
- if (navigator.clipboard && navigator.clipboard.writeText) {
106714
- await navigator.clipboard.writeText(text);
106715
- showCopyTooltip();
106716
- onCopySuccess == null ? void 0 : onCopySuccess();
106717
- return;
106718
- }
106719
- const textArea = document.createElement("textarea");
106720
- textArea.value = text;
106721
- textArea.style.position = "fixed";
106722
- textArea.style.left = "-999999px";
106723
- textArea.style.top = "-999999px";
106724
- document.body.appendChild(textArea);
106725
- textArea.focus();
106726
- textArea.select();
106727
- try {
106728
- document.execCommand("copy");
106729
- showCopyTooltip();
106730
- onCopySuccess == null ? void 0 : onCopySuccess();
106731
- } catch (err) {
106732
- const error = err instanceof Error ? err : new Error("Copy failed");
106733
- console.warn("Copy to clipboard failed:", error);
106734
- onCopyError == null ? void 0 : onCopyError(error);
106735
- } finally {
106736
- document.body.removeChild(textArea);
106737
- }
106738
- } catch (err) {
106739
- const error = err instanceof Error ? err : new Error("Copy failed");
106740
- console.warn("Copy to clipboard failed:", error);
106741
- onCopyError == null ? void 0 : onCopyError(error);
106742
- }
106743
- }, [text, showCopyTooltip, onCopySuccess, onCopyError]);
106744
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative inline-flex", children: [
106745
- /* @__PURE__ */ jsxRuntimeExports.jsx(
106746
- "button",
106747
- {
106748
- onClick: copyToClipboard2,
106749
- className: `${sizeClasses2.button} hover:bg-gray-100 rounded transition-colors ${className}`,
106750
- title,
106751
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: `${sizeClasses2.icon} text-gray-400 ${iconClassName}`, style: iconStyle })
106752
- }
106753
- ),
106754
- /* @__PURE__ */ jsxRuntimeExports.jsx(
106755
- "div",
106756
- {
106757
- className: `${getTooltipPositionClasses()} ${sizeClasses2.tooltip} transition-opacity duration-150 ${showTooltip ? "opacity-100 animate-fade-in" : "opacity-0 pointer-events-none"}`,
106758
- style: {
106759
- visibility: showTooltip ? "visible" : "hidden"
106760
- },
106761
- children: tooltipText
106762
- }
106763
- )
106764
- ] });
106765
- };
106766
107164
  function __awaiter(thisArg, _arguments, P2, generator) {
106767
107165
  function adopt(value) {
106768
107166
  return value instanceof P2 ? value : new P2(function(resolve) {
@@ -107927,21 +108325,35 @@ const DataModal = ({
107927
108325
  )
107928
108326
  ] })
107929
108327
  ] }),
107930
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-auto bg-gray-800 p-4", children: viewMode === "interactive" && useEnhancedJsonView ? /* @__PURE__ */ jsxRuntimeExports.jsx(
107931
- JsonView,
108328
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
108329
+ "div",
107932
108330
  {
107933
- src: parsedData,
107934
- theme: "github",
107935
- dark: true,
107936
- collapseObjectsAfterLength: 20,
107937
- collapseStringsAfterLength: 500,
107938
- collapseStringMode: "word",
107939
- displaySize: "collapsed",
107940
- matchesURL: true,
107941
- customizeCopy: (node) => stringifyJsonNode(node),
107942
- className: "w-full text-xs"
108331
+ className: "flex-1 overflow-auto bg-gray-800 p-4",
108332
+ style: {
108333
+ "--json-property": "#ffffff",
108334
+ "--json-index": "#e2e8f0",
108335
+ "--json-number": "#e2e8f0",
108336
+ "--json-string": "#e2e8f0",
108337
+ "--json-boolean": "#e2e8f0",
108338
+ "--json-null": "#e2e8f0"
108339
+ },
108340
+ children: viewMode === "interactive" && useEnhancedJsonView ? /* @__PURE__ */ jsxRuntimeExports.jsx(
108341
+ JsonView,
108342
+ {
108343
+ src: parsedData,
108344
+ dark: true,
108345
+ collapseObjectsAfterLength: 20,
108346
+ collapseStringsAfterLength: 500,
108347
+ collapseStringMode: "word",
108348
+ displaySize: "collapsed",
108349
+ matchesURL: true,
108350
+ customizeCopy: (node) => stringifyJsonNode(node),
108351
+ className: "w-full text-xs",
108352
+ style: { color: "#f1f5f9" }
108353
+ }
108354
+ ) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs whitespace-pre text-white font-mono", children: stringifyJsonNode(parsedData) })
107943
108355
  }
107944
- ) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs whitespace-pre text-gray-300 font-mono", children: stringifyJsonNode(parsedData) }) })
108356
+ )
107945
108357
  ] }) });
107946
108358
  };
107947
108359
  const JsonViewer = ({
@@ -108309,6 +108721,23 @@ function formatUnknownValue(value) {
108309
108721
  function isObservation(node) {
108310
108722
  return node !== null && "traceId" in node && "type" in node;
108311
108723
  }
108724
+ function metadataForDisplay(metadata) {
108725
+ if (metadata === null || metadata === void 0) return {};
108726
+ let obj;
108727
+ if (typeof metadata === "string") {
108728
+ try {
108729
+ obj = JSON.parse(metadata);
108730
+ } catch {
108731
+ return {};
108732
+ }
108733
+ } else if (typeof metadata === "object") {
108734
+ obj = metadata;
108735
+ } else {
108736
+ return {};
108737
+ }
108738
+ const { tools: _tools, ...rest } = obj;
108739
+ return rest;
108740
+ }
108312
108741
  const defaultMetrics = {
108313
108742
  totalCost: "0",
108314
108743
  totalTokens: 0,
@@ -108357,7 +108786,7 @@ function SectionHeader({ title }) {
108357
108786
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 h-[1px] bg-[#EAECF0]" })
108358
108787
  ] });
108359
108788
  }
108360
- function PreviewContent({ input, output, metadata, statusMessage, isLoading = false, modelParameters }) {
108789
+ function PreviewContent({ input, output, metadata, statusMessage, isLoading = false }) {
108361
108790
  const [showAllMetadata, setShowAllMetadata] = useState(false);
108362
108791
  const messages = useMemo(() => {
108363
108792
  if (!input || typeof input !== "object") return null;
@@ -108389,15 +108818,6 @@ function PreviewContent({ input, output, metadata, statusMessage, isLoading = fa
108389
108818
  }
108390
108819
  return String(output);
108391
108820
  }, [output]);
108392
- const modelName = useMemo(() => {
108393
- if (!input || typeof input !== "object") return null;
108394
- return input["model"] ?? null;
108395
- }, [input]);
108396
- const formatParamValue = (value) => {
108397
- if (value === null || value === void 0) return "";
108398
- if (typeof value === "object") return JSON.stringify(value);
108399
- return String(value);
108400
- };
108401
108821
  if (isLoading) {
108402
108822
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-[16px] p-[16px] overflow-y-auto h-full", children: [
108403
108823
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3", children: [
@@ -108411,29 +108831,6 @@ function PreviewContent({ input, output, metadata, statusMessage, isLoading = fa
108411
108831
  ] });
108412
108832
  }
108413
108833
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-[20px] p-[16px] overflow-y-auto h-full", children: [
108414
- (modelName || modelParameters && Object.keys(modelParameters).length > 0) && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-[6px]", children: [
108415
- modelName && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "px-[8px] py-[4px] bg-[#F2F4F7] rounded-[4px] text-[11px] font-medium text-[#344054]", children: [
108416
- "Model: ",
108417
- modelName
108418
- ] }),
108419
- modelParameters && typeof modelParameters === "object" && Object.entries(modelParameters).filter(([_2, value]) => value !== null && value !== void 0).map(([key, value]) => {
108420
- const valueString = formatParamValue(value);
108421
- const displayKey = key.replace(/_/g, " ");
108422
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(
108423
- "span",
108424
- {
108425
- className: "px-[8px] py-[4px] bg-[#F2F4F7] border border-[#EAECF0] rounded-[4px] text-[11px] font-medium text-[#344054] max-w-[200px] truncate",
108426
- title: `${key}: ${valueString}`,
108427
- children: [
108428
- displayKey,
108429
- ": ",
108430
- valueString
108431
- ]
108432
- },
108433
- key
108434
- );
108435
- })
108436
- ] }),
108437
108834
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
108438
108835
  /* @__PURE__ */ jsxRuntimeExports.jsx(SectionHeader, { title: "Input" }),
108439
108836
  messages ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-col gap-[8px]", children: messages.map((msg, index) => /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -108520,14 +108917,21 @@ function CodeEditorSection({
108520
108917
  showHeader: true,
108521
108918
  useEnhancedJsonView: true,
108522
108919
  collapseStringsAfterLength: 500,
108523
- collapseObjectsAfterLength: 20,
108920
+ collapseObjectsAfterLength: selectedTab === "metadata" ? 100 : 20,
108921
+ defaultExpanded: selectedTab === "metadata",
108524
108922
  maxHeight: "100%",
108525
108923
  className: "h-full border-0 rounded-none"
108526
- }
108924
+ },
108925
+ selectedTab
108527
108926
  ) })
108528
108927
  ] });
108529
108928
  }
108530
- function NodeDetailPanel({ node, nodeType: _nodeType, apiConfig }) {
108929
+ function NodeDetailPanel({
108930
+ node,
108931
+ nodeType: _nodeType,
108932
+ apiConfig,
108933
+ generationSummaryInputOverride = null
108934
+ }) {
108531
108935
  const [selectedTab, setSelectedTab] = useState("preview");
108532
108936
  const [showTokenTooltip, setShowTokenTooltip] = useState(false);
108533
108937
  const tooltipTimeoutRef = useRef(null);
@@ -108614,6 +109018,7 @@ function NodeDetailPanel({ node, nodeType: _nodeType, apiConfig }) {
108614
109018
  }
108615
109019
  return TraceTreeService.extractUserMessage(displayNode.input);
108616
109020
  }, [displayNode]);
109021
+ const summaryInputLine = generationSummaryInputOverride !== null && generationSummaryInputOverride.length > 0 ? generationSummaryInputOverride : inputText;
108617
109022
  const isGeneration = useMemo(() => {
108618
109023
  return node !== null && isObservation(node) && node.type === "GENERATION";
108619
109024
  }, [node]);
@@ -108697,7 +109102,7 @@ function NodeDetailPanel({ node, nodeType: _nodeType, apiConfig }) {
108697
109102
  case "response":
108698
109103
  return displayNode.output || {};
108699
109104
  case "metadata":
108700
- return isObservation(displayNode) ? displayNode.metadata || {} : {};
109105
+ return isObservation(displayNode) ? metadataForDisplay(displayNode.metadata || {}) : {};
108701
109106
  case "logs":
108702
109107
  return {
108703
109108
  id: isObservation(displayNode) ? displayNode.id : displayNode.id,
@@ -108717,11 +109122,17 @@ function NodeDetailPanel({ node, nodeType: _nodeType, apiConfig }) {
108717
109122
  return {
108718
109123
  input: formattedInput,
108719
109124
  output: displayNode.output || {},
108720
- metadata: isObservation(displayNode) ? displayNode.metadata || {} : {},
109125
+ metadata: isObservation(displayNode) ? metadataForDisplay(displayNode.metadata || {}) : {},
108721
109126
  statusMessage: isObservation(displayNode) ? displayNode.statusMessage : void 0,
108722
109127
  modelParameters: isObservation(displayNode) ? displayNode.modelParameters : void 0
108723
109128
  };
108724
109129
  }, [displayNode, formattedInput]);
109130
+ const summaryModelInfo = useMemo(() => {
109131
+ if (!isGeneration || !displayNode) return { modelName: null, modelParameters: {} };
109132
+ const modelName = typeof formattedInput === "object" && formattedInput !== null && "model" in formattedInput ? formattedInput.model ?? null : null;
109133
+ const modelParameters = isObservation(displayNode) && displayNode.modelParameters && typeof displayNode.modelParameters === "object" ? displayNode.modelParameters : {};
109134
+ return { modelName, modelParameters };
109135
+ }, [isGeneration, displayNode, formattedInput]);
108725
109136
  const tokenTooltipContent = metrics.totalTokens > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs(
108726
109137
  "div",
108727
109138
  {
@@ -108814,10 +109225,10 @@ function NodeDetailPanel({ node, nodeType: _nodeType, apiConfig }) {
108814
109225
  ] })
108815
109226
  ),
108816
109227
  /* @__PURE__ */ jsxRuntimeExports.jsx(ContentDivider, {}),
108817
- isGeneration && inputText.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
109228
+ isGeneration && summaryInputLine.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
108818
109229
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-[8px]", children: [
108819
109230
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[12px] font-medium leading-[16px] text-[#98A2B3]", children: "Input" }),
108820
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[12px] font-medium leading-[16px] text-[#101828] truncate", children: inputText })
109231
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[12px] font-medium leading-[16px] text-[#101828] truncate", children: summaryInputLine })
108821
109232
  ] }),
108822
109233
  /* @__PURE__ */ jsxRuntimeExports.jsx(ContentDivider, {})
108823
109234
  ] }),
@@ -108833,6 +109244,37 @@ function NodeDetailPanel({ node, nodeType: _nodeType, apiConfig }) {
108833
109244
  ] })
108834
109245
  ] }),
108835
109246
  /* @__PURE__ */ jsxRuntimeExports.jsx(ContentDivider, {})
109247
+ ] }),
109248
+ isGeneration && (summaryModelInfo.modelName || Object.keys(summaryModelInfo.modelParameters).length > 0) && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
109249
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-[8px]", children: [
109250
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[12px] font-medium leading-[16px] text-[#98A2B3]", children: "Model parameters" }),
109251
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-[6px]", children: [
109252
+ summaryModelInfo.modelName && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "px-[8px] py-[4px] bg-[#F2F4F7] rounded-[4px] text-[11px] font-medium text-[#344054]", children: [
109253
+ "Model: ",
109254
+ summaryModelInfo.modelName
109255
+ ] }),
109256
+ Object.entries(summaryModelInfo.modelParameters).filter(
109257
+ ([_2, value]) => value !== null && value !== void 0
109258
+ ).map(([key, value]) => {
109259
+ const valueStr = typeof value === "object" ? JSON.stringify(value) : String(value);
109260
+ const displayKey = key.replace(/_/g, " ");
109261
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
109262
+ "span",
109263
+ {
109264
+ className: "px-[8px] py-[4px] bg-[#F2F4F7] border border-[#EAECF0] rounded-[4px] text-[11px] font-medium text-[#344054] max-w-[200px] truncate",
109265
+ title: `${key}: ${valueStr}`,
109266
+ children: [
109267
+ displayKey,
109268
+ ": ",
109269
+ valueStr
109270
+ ]
109271
+ },
109272
+ key
109273
+ );
109274
+ })
109275
+ ] })
109276
+ ] }),
109277
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ContentDivider, {})
108836
109278
  ] })
108837
109279
  ] })
108838
109280
  ] }),
@@ -108860,7 +109302,8 @@ function DetailPage({
108860
109302
  selectedObservationId,
108861
109303
  batchSize = DEFAULT_BATCH_SIZE,
108862
109304
  initialTraceCount,
108863
- initialSessionData
109305
+ initialSessionData,
109306
+ runHeaderInputMode = "display"
108864
109307
  }) {
108865
109308
  const [currentMode, setCurrentMode] = useState(initialMode);
108866
109309
  const [currentSessionId, setCurrentSessionId] = useState(initialSessionId);
@@ -109101,12 +109544,52 @@ function DetailPage({
109101
109544
  }, [mode, sessionData, traceData, sessionId, traceId, initialSessionData]);
109102
109545
  const traces = useMemo(() => {
109103
109546
  if (mode === "session" && sessionData) {
109104
- return sessionData.traces.map((t2) => service.transformToTraceData(t2));
109547
+ const sorted = [...sessionData.traces].sort((a4, b2) => {
109548
+ const tA = a4.timestamp ? new Date(a4.timestamp).getTime() : 0;
109549
+ const tB = b2.timestamp ? new Date(b2.timestamp).getTime() : 0;
109550
+ return tA - tB;
109551
+ });
109552
+ return sorted.map((t2) => service.transformToTraceData(t2));
109105
109553
  } else if (mode === "trace" && traceData) {
109106
109554
  return [service.transformToTraceData(traceData)];
109107
109555
  }
109108
109556
  return [];
109109
109557
  }, [mode, sessionData, traceData, service]);
109558
+ const generationSummaryInputOverride = useMemo(() => {
109559
+ var _a;
109560
+ if (runHeaderInputMode === "tokenized") {
109561
+ return null;
109562
+ }
109563
+ if (!selectedNode || !("traceId" in selectedNode) || !("type" in selectedNode)) {
109564
+ return null;
109565
+ }
109566
+ const obs = selectedNode;
109567
+ if (obs.type !== "GENERATION") {
109568
+ return null;
109569
+ }
109570
+ const traceRow = traces.find((t2) => t2.id === obs.traceId);
109571
+ if (!traceRow) {
109572
+ return null;
109573
+ }
109574
+ const displayUser = traceRow.displayUserMessage && traceRow.displayUserMessage.length > 0 ? traceRow.displayUserMessage : TraceTreeService.extractUserMessage(traceRow.input);
109575
+ if (!displayUser || displayUser.length === 0) {
109576
+ return null;
109577
+ }
109578
+ const fromState = (_a = traceObservations[obs.traceId]) == null ? void 0 : _a.observations;
109579
+ const observations = fromState && fromState.length > 0 ? fromState : mode === "trace" && (traceData == null ? void 0 : traceData.id) === obs.traceId && traceData.observations.length > 0 ? traceData.observations : [];
109580
+ const { observation: firstGen } = TraceTreeService.findFirstGeneration(observations);
109581
+ if (!firstGen || firstGen.id !== obs.id) {
109582
+ return null;
109583
+ }
109584
+ return displayUser;
109585
+ }, [
109586
+ runHeaderInputMode,
109587
+ selectedNode,
109588
+ traces,
109589
+ traceObservations,
109590
+ mode,
109591
+ traceData
109592
+ ]);
109110
109593
  const handleNodeSelect = useCallback((node) => {
109111
109594
  setSelectedNode(node);
109112
109595
  }, []);
@@ -109155,6 +109638,23 @@ function DetailPage({
109155
109638
  firstTraceId: null
109156
109639
  });
109157
109640
  }, []);
109641
+ const handleNavigateToTrace = useCallback((targetTraceId) => {
109642
+ setSelectedNode(null);
109643
+ setSessionData(null);
109644
+ setTraceData(null);
109645
+ setTraceObservations({});
109646
+ setLoadingState("idle");
109647
+ setError(null);
109648
+ setHasAutoSelected(false);
109649
+ setCurrentMode("trace");
109650
+ setCurrentTraceId(targetTraceId);
109651
+ setProgressiveState({
109652
+ traceCount: 0,
109653
+ pendingTraceIds: [],
109654
+ firstTraceLoaded: false,
109655
+ firstTraceId: null
109656
+ });
109657
+ }, []);
109158
109658
  if (loadingState === "loading") {
109159
109659
  const canShowHeader = mode === "session" && initialSessionData;
109160
109660
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `h-full flex flex-col bg-white ${className}`, children: [
@@ -109323,8 +109823,10 @@ function DetailPage({
109323
109823
  onNodeSelect: handleNodeSelect,
109324
109824
  onExpandToggle: () => handleTraceExpand(trace.id, trace.timestamp),
109325
109825
  showTraceId: mode === "session",
109826
+ onTraceIdClick: mode === "session" ? handleNavigateToTrace : void 0,
109326
109827
  isLoading: isLoadingObservations,
109327
- defaultExpandedNodeIds: autoExpandIds
109828
+ defaultExpandedNodeIds: autoExpandIds,
109829
+ runHeaderInputMode
109328
109830
  },
109329
109831
  trace.id
109330
109832
  );
@@ -109344,7 +109846,15 @@ function DetailPage({
109344
109846
  );
109345
109847
  }) })
109346
109848
  ] }) }),
109347
- !selectedNode && !hasAutoSelected ? /* @__PURE__ */ jsxRuntimeExports.jsx(NodeDetailSkeleton, { showFullSummary: true }) : /* @__PURE__ */ jsxRuntimeExports.jsx(NodeDetailPanel, { node: selectedNode, nodeType, apiConfig })
109849
+ !selectedNode && !hasAutoSelected ? /* @__PURE__ */ jsxRuntimeExports.jsx(NodeDetailSkeleton, { showFullSummary: true }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
109850
+ NodeDetailPanel,
109851
+ {
109852
+ node: selectedNode,
109853
+ nodeType,
109854
+ apiConfig,
109855
+ generationSummaryInputOverride
109856
+ }
109857
+ )
109348
109858
  ] })
109349
109859
  ] });
109350
109860
  }
@@ -109759,22 +110269,25 @@ function EnvironmentNameCell$1({ envId }) {
109759
110269
  return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-gray-600", title: envId || "-", children: displayName });
109760
110270
  }
109761
110271
  function SessionsListContent(props) {
109762
- const { apiConfig, onSessionClick, className = "", defaultFilters = [], defaultTimeRange = "24 hours" } = props;
109763
- const { environments } = useEnvironment();
109764
- const [selectedSessionId, setSelectedSessionId] = useState(null);
110272
+ const { apiConfig, onSessionClick, className = "", defaultFilters = [], defaultTimeRange = "24 hours", initialSessionId } = props;
110273
+ const { environments, resolveEnvironmentName } = useEnvironment();
110274
+ const [selectedSessionId, setSelectedSessionId] = useState(() => initialSessionId ?? null);
109765
110275
  const [selectedSessionData, setSelectedSessionData] = useState(null);
109766
- const [isModalOpen, setIsModalOpen] = useState(false);
110276
+ const [isModalOpen, setIsModalOpen] = useState(() => !!initialSessionId);
109767
110277
  const [sessions, setSessions] = useState([]);
109768
110278
  const [totalCount, setTotalCount] = useState(0);
109769
110279
  const [loading, setLoading] = useState(true);
109770
110280
  const [hasInitiallyLoaded, setHasInitiallyLoaded] = useState(false);
110281
+ const [appVersionOptions, setAppVersionOptions] = useState([]);
110282
+ const [searchTerm, setSearchTerm] = useState("");
109771
110283
  const initialFilters = useMemo(() => {
109772
110284
  const hasEnvFilter = defaultFilters.some((f) => f.column === "envId");
109773
- if (hasEnvFilter) {
109774
- return defaultFilters;
110285
+ const base2 = hasEnvFilter ? defaultFilters : [createDraftEnvironmentFilter$1(), ...defaultFilters];
110286
+ if (initialSessionId) {
110287
+ return [...base2, { column: "id", type: "string", operator: "=", value: initialSessionId }];
109775
110288
  }
109776
- return [createDraftEnvironmentFilter$1(), ...defaultFilters];
109777
- }, [defaultFilters]);
110289
+ return base2;
110290
+ }, [defaultFilters, initialSessionId]);
109778
110291
  const [filters, setFilters] = useState(initialFilters);
109779
110292
  const [showFilterPanel, setShowFilterPanel] = useState(false);
109780
110293
  const [showColumnCustomization, setShowColumnCustomization] = useState(false);
@@ -109783,6 +110296,32 @@ function SessionsListContent(props) {
109783
110296
  const [pagination, setPagination] = useState({ page: 0, limit: 50 });
109784
110297
  const [orderBy, setOrderBy] = useState({ column: "createdAt", order: "DESC" });
109785
110298
  const apiService = useMemo(() => new TracingApiService(apiConfig), [apiConfig]);
110299
+ useEffect(() => {
110300
+ if (initialSessionId) {
110301
+ setSelectedSessionId(initialSessionId);
110302
+ setIsModalOpen(true);
110303
+ }
110304
+ }, [initialSessionId]);
110305
+ useEffect(() => {
110306
+ const fetchAppVersions = async () => {
110307
+ try {
110308
+ const filterOptionsData = await apiService.fetchFilterOptions({
110309
+ projectId: apiConfig.projectId
110310
+ });
110311
+ if ((filterOptionsData == null ? void 0 : filterOptionsData.appvIds) && Array.isArray(filterOptionsData.appvIds)) {
110312
+ setAppVersionOptions(
110313
+ filterOptionsData.appvIds.map((item) => ({
110314
+ value: item.value,
110315
+ label: item.value
110316
+ }))
110317
+ );
110318
+ }
110319
+ } catch (error) {
110320
+ console.warn("Failed to fetch app version filter options:", error);
110321
+ }
110322
+ };
110323
+ fetchAppVersions();
110324
+ }, [apiService, apiConfig.projectId]);
109786
110325
  const convertPresetToDateRange = (preset) => {
109787
110326
  const now2 = /* @__PURE__ */ new Date();
109788
110327
  let pastDate;
@@ -109844,7 +110383,6 @@ function SessionsListContent(props) {
109844
110383
  });
109845
110384
  }
109846
110385
  const allFilters = [...timeFilters, ...filters];
109847
- if (apiConfig.projectId) ;
109848
110386
  return allFilters;
109849
110387
  }, [timeRange, filters]);
109850
110388
  const fetchSessions = useCallback(async () => {
@@ -109904,6 +110442,28 @@ function SessionsListContent(props) {
109904
110442
  useEffect(() => {
109905
110443
  fetchSessions();
109906
110444
  }, [fetchSessions]);
110445
+ const filteredSessions = useMemo(() => {
110446
+ const term = searchTerm.trim().toLowerCase();
110447
+ if (!term) return sessions;
110448
+ return sessions.filter((session) => {
110449
+ var _a;
110450
+ const envName = ((_a = resolveEnvironmentName(session.envId)) == null ? void 0 : _a.toLowerCase()) || "";
110451
+ const searchableFields = [
110452
+ session.id,
110453
+ envName,
110454
+ session.envId,
110455
+ session.appvId,
110456
+ session.source,
110457
+ session.environment,
110458
+ session.sessionReference,
110459
+ session.userReference,
110460
+ ...session.userIds || []
110461
+ ];
110462
+ return searchableFields.some(
110463
+ (field) => field && String(field).toLowerCase().includes(term)
110464
+ );
110465
+ });
110466
+ }, [sessions, searchTerm, resolveEnvironmentName]);
109907
110467
  const defaultColumns = useMemo(
109908
110468
  () => [
109909
110469
  {
@@ -109912,8 +110472,7 @@ function SessionsListContent(props) {
109912
110472
  width: 320,
109913
110473
  pinned: "left",
109914
110474
  hide: false,
109915
- // Pinned columns should always be visible
109916
- cellRenderer: (params) => /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm font-medium text-gray-900", title: params.value, children: TracingUtils.truncate(params.value, 30) })
110475
+ cellRenderer: (params) => /* @__PURE__ */ jsxRuntimeExports.jsx(CopyableId, { value: params.value, truncateLength: 30 })
109917
110476
  },
109918
110477
  {
109919
110478
  field: "envId",
@@ -110040,6 +110599,20 @@ function SessionsListContent(props) {
110040
110599
  disabled: true,
110041
110600
  valueFormatter: (params) => TracingUtils.formatTokens(params.value),
110042
110601
  cellRenderer: (params) => /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-gray-700", children: TracingUtils.formatTokens(params.value) })
110602
+ },
110603
+ {
110604
+ field: "sessionReference",
110605
+ headerName: "Session Reference",
110606
+ width: 180,
110607
+ hide: true,
110608
+ cellRenderer: (params) => /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-gray-700", title: params.value || "-", children: params.value || "-" })
110609
+ },
110610
+ {
110611
+ field: "identity",
110612
+ headerName: "User Reference",
110613
+ width: 180,
110614
+ hide: true,
110615
+ cellRenderer: (params) => /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-gray-700", title: params.value || "-", children: params.value || "-" })
110043
110616
  }
110044
110617
  // {
110045
110618
  // field: 'traceTags',
@@ -110159,8 +110732,9 @@ function SessionsListContent(props) {
110159
110732
  // User-friendly label
110160
110733
  apiColumnName: "App Version ID",
110161
110734
  // API expects "App Version ID" (koretracing uiTableName)
110162
- type: "string",
110163
- operators: ["=", "!=", "contains"]
110735
+ type: "stringOptions",
110736
+ operators: ["any of", "none of"],
110737
+ options: appVersionOptions
110164
110738
  },
110165
110739
  {
110166
110740
  field: "source",
@@ -110212,10 +110786,27 @@ function SessionsListContent(props) {
110212
110786
  // API expects "Output Tokens" (koretracing uiTableName)
110213
110787
  type: "number",
110214
110788
  operators: ["=", ">", ">=", "<", "<="]
110789
+ },
110790
+ {
110791
+ field: "sessionReference",
110792
+ label: "Session Reference",
110793
+ apiColumnName: "Session Reference",
110794
+ type: "string",
110795
+ operators: ["=", "!=", "contains"]
110796
+ },
110797
+ {
110798
+ field: "identity",
110799
+ label: "User Reference",
110800
+ apiColumnName: "User Reference",
110801
+ type: "string",
110802
+ operators: ["=", "!=", "contains"]
110215
110803
  }
110216
110804
  ],
110217
- [environments]
110805
+ [environments, appVersionOptions]
110218
110806
  );
110807
+ const handleSearch = useCallback((term) => {
110808
+ setSearchTerm(term);
110809
+ }, []);
110219
110810
  const handleTimeRangeChange = (value, presetLabel) => {
110220
110811
  console.log("🗓️ SessionsList: Time range change requested:", value, presetLabel);
110221
110812
  setTimeRange(value);
@@ -110257,6 +110848,7 @@ function SessionsListContent(props) {
110257
110848
  };
110258
110849
  const handleClearFilters = () => {
110259
110850
  setFilters([]);
110851
+ setSearchTerm("");
110260
110852
  setTimeRange("24 hours");
110261
110853
  };
110262
110854
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `h-full flex flex-col w-full ${className}`, children: [
@@ -110265,11 +110857,19 @@ function SessionsListContent(props) {
110265
110857
  {
110266
110858
  title: "Sessions",
110267
110859
  description: "Review session logs and trace details to analyze conversation logs and app behavior.",
110268
- showSearch: false,
110860
+ searchPlaceholder: "Search sessions...",
110861
+ showSearch: true,
110862
+ searchConfig: {
110863
+ metadataSearchFields: ["Session ID", "Environment", "App Version", "User ID", "Source"],
110864
+ updateQuery: handleSearch,
110865
+ currentQuery: searchTerm,
110866
+ tableAllowsFullTextSearch: false
110867
+ },
110269
110868
  timeRange,
110270
110869
  timeRangePresetLabel,
110271
110870
  onTimeRangeChange: handleTimeRangeChange,
110272
110871
  filters,
110872
+ filterColumns,
110273
110873
  onFiltersClick: () => setShowFilterPanel(!showFilterPanel),
110274
110874
  onModifyColumnsClick: () => setShowColumnCustomization(true),
110275
110875
  onExportClick: handleExport,
@@ -110320,10 +110920,10 @@ function SessionsListContent(props) {
110320
110920
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-auto p-[24px] pt-[8px]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
110321
110921
  TracingTable,
110322
110922
  {
110323
- data: sessions,
110923
+ data: filteredSessions,
110324
110924
  columns,
110325
110925
  loading,
110326
- totalCount,
110926
+ totalCount: searchTerm.trim() ? filteredSessions.length : totalCount,
110327
110927
  pagination,
110328
110928
  onPaginationChange: setPagination,
110329
110929
  onRowClick: handleRowClick,
@@ -110370,24 +110970,26 @@ function TracesListContent(props) {
110370
110970
  onTraceClick,
110371
110971
  className = "",
110372
110972
  defaultFilters = [],
110373
- sessionId
110973
+ sessionId,
110974
+ initialTraceId
110374
110975
  } = props;
110375
110976
  const { environments } = useEnvironment();
110376
- const [selectedTraceId, setSelectedTraceId] = useState(null);
110377
- const [isModalOpen, setIsModalOpen] = useState(false);
110977
+ const [selectedTraceId, setSelectedTraceId] = useState(() => initialTraceId ?? null);
110978
+ const [isModalOpen, setIsModalOpen] = useState(() => !!initialTraceId);
110378
110979
  const [traces, setTraces] = useState([]);
110379
110980
  const [totalCount, setTotalCount] = useState(0);
110380
110981
  const [loading, setLoading] = useState(true);
110381
110982
  const [hasInitiallyLoaded, setHasInitiallyLoaded] = useState(false);
110382
110983
  const [searchTerm, setSearchTerm] = useState("");
110383
- const [searchType, setSearchType] = useState(["id"]);
110984
+ const [searchType, setSearchType] = useState(["id", "content"]);
110384
110985
  const initialFilters = useMemo(() => {
110385
110986
  const hasEnvFilter = defaultFilters.some((f) => f.column === "envId");
110386
- if (hasEnvFilter) {
110387
- return defaultFilters;
110987
+ const base2 = hasEnvFilter ? defaultFilters : [createDraftEnvironmentFilter(), ...defaultFilters];
110988
+ if (initialTraceId) {
110989
+ return [...base2, { column: "id", type: "string", operator: "=", value: initialTraceId }];
110388
110990
  }
110389
- return [createDraftEnvironmentFilter(), ...defaultFilters];
110390
- }, [defaultFilters]);
110991
+ return base2;
110992
+ }, [defaultFilters, initialTraceId]);
110391
110993
  const [filters, setFilters] = useState(initialFilters);
110392
110994
  const [showFilterPanel, setShowFilterPanel] = useState(false);
110393
110995
  const [showColumnCustomization, setShowColumnCustomization] = useState(false);
@@ -110396,6 +110998,12 @@ function TracesListContent(props) {
110396
110998
  const [pagination, setPagination] = useState({ page: 0, limit: 50 });
110397
110999
  const [orderBy, setOrderBy] = useState({ column: "timestamp", order: "DESC" });
110398
111000
  const [detailedTraceData, setDetailedTraceData] = useState(/* @__PURE__ */ new Map());
111001
+ useEffect(() => {
111002
+ if (initialTraceId) {
111003
+ setSelectedTraceId(initialTraceId);
111004
+ setIsModalOpen(true);
111005
+ }
111006
+ }, [initialTraceId]);
110399
111007
  const apiService = useMemo(() => new TracingApiService(apiConfig), [apiConfig]);
110400
111008
  const convertPresetToDateRange = (preset) => {
110401
111009
  const now2 = /* @__PURE__ */ new Date();
@@ -110481,18 +111089,24 @@ function TracesListContent(props) {
110481
111089
  orderBy
110482
111090
  });
110483
111091
  const apiFilters = TracingUtils.convertFiltersToApiFormat(effectiveFilters, filterColumns);
110484
- const tracesResponse = await apiService.fetchTraces({
110485
- projectId: apiConfig.projectId,
110486
- filter: apiFilters,
110487
- orderBy,
110488
- page: pagination.page,
110489
- limit: pagination.limit,
110490
- searchQuery: searchTerm || null,
110491
- searchType
110492
- // 'id' for IDs/Names, ['id', 'content'] for Full Text
110493
- });
111092
+ const [tracesResponse, countResponse] = await Promise.all([
111093
+ apiService.fetchTraces({
111094
+ projectId: apiConfig.projectId,
111095
+ filter: apiFilters,
111096
+ orderBy,
111097
+ page: pagination.page,
111098
+ limit: pagination.limit,
111099
+ searchQuery: searchTerm || null,
111100
+ searchType
111101
+ }),
111102
+ apiService.fetchTracesCount(apiConfig.projectId, apiFilters, {
111103
+ searchQuery: searchTerm || null,
111104
+ searchType,
111105
+ orderBy
111106
+ })
111107
+ ]);
110494
111108
  const basicTraces = tracesResponse.traces || [];
110495
- console.log("✅ Basic traces loaded:", { count: basicTraces.length });
111109
+ console.log("✅ Basic traces loaded:", { count: basicTraces.length, total: countResponse.totalCount });
110496
111110
  if (basicTraces.length > 0) {
110497
111111
  const traceIds = basicTraces.map((t2) => t2.id);
110498
111112
  try {
@@ -110527,7 +111141,7 @@ function TracesListContent(props) {
110527
111141
  } else {
110528
111142
  setTraces([]);
110529
111143
  }
110530
- setTotalCount(basicTraces.length);
111144
+ setTotalCount(countResponse.totalCount);
110531
111145
  } catch (error) {
110532
111146
  console.error("❌ Error fetching traces:", error);
110533
111147
  setTraces([]);
@@ -110556,11 +111170,13 @@ function TracesListContent(props) {
110556
111170
  projectId: apiConfig.projectId,
110557
111171
  timestamp: trace.timestamp
110558
111172
  });
111173
+ const inputDisplay = TraceTreeService.extractUserMessage(detail["input"]);
111174
+ const outputDisplay = TraceTreeService.extractAppResponse(detail["output"]);
110559
111175
  setDetailedTraceData((prev) => {
110560
111176
  const newMap = new Map(prev);
110561
111177
  newMap.set(traceId, {
110562
- input: detail["input"],
110563
- output: detail["output"],
111178
+ input: inputDisplay,
111179
+ output: outputDisplay,
110564
111180
  totalCost: detail["totalCost"],
110565
111181
  envId: detail["envId"],
110566
111182
  source: detail["source"]
@@ -110597,8 +111213,7 @@ function TracesListContent(props) {
110597
111213
  width: 320,
110598
111214
  pinned: "left",
110599
111215
  hide: false,
110600
- // Pinned columns should always be visible
110601
- cellRenderer: (params) => /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm font-medium text-gray-900", title: params.value, children: TracingUtils.truncate(params.value, 30) })
111216
+ cellRenderer: (params) => /* @__PURE__ */ jsxRuntimeExports.jsx(CopyableId, { value: params.value, truncateLength: 30 })
110602
111217
  }
110603
111218
  ];
110604
111219
  {
@@ -110609,11 +111224,13 @@ function TracesListContent(props) {
110609
111224
  hide: false,
110610
111225
  cellRenderer: (params) => {
110611
111226
  const detailData = detailedTraceData.get(params.data.id);
110612
- const inputText = detailData == null ? void 0 : detailData.input;
110613
- if (inputText === void 0) {
111227
+ const rawInput = detailData == null ? void 0 : detailData.input;
111228
+ if (rawInput === void 0) {
110614
111229
  return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-gray-400 italic", children: "Loading..." });
110615
111230
  }
110616
- return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-gray-700", title: inputText, children: TracingUtils.truncate(inputText || "-", 50) });
111231
+ const inputText = typeof rawInput === "string" ? rawInput : TraceTreeService.extractUserMessage(rawInput);
111232
+ const displayText = TracingUtils.truncate(inputText || "-", 50);
111233
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-gray-700", title: inputText || void 0, children: displayText });
110617
111234
  }
110618
111235
  });
110619
111236
  }
@@ -110642,11 +111259,13 @@ function TracesListContent(props) {
110642
111259
  hide: false,
110643
111260
  cellRenderer: (params) => {
110644
111261
  const detailData = detailedTraceData.get(params.data.id);
110645
- const outputText = detailData == null ? void 0 : detailData.output;
110646
- if (outputText === void 0) {
111262
+ const rawOutput = detailData == null ? void 0 : detailData.output;
111263
+ if (rawOutput === void 0) {
110647
111264
  return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-gray-400 italic", children: "Loading..." });
110648
111265
  }
110649
- return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-gray-700", title: outputText, children: TracingUtils.truncate(outputText || "-", 50) });
111266
+ const outputText = typeof rawOutput === "string" ? rawOutput : TraceTreeService.extractAppResponse(rawOutput);
111267
+ const displayText = TracingUtils.truncate(outputText || "-", 50);
111268
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-gray-700", title: outputText || void 0, children: displayText });
110650
111269
  }
110651
111270
  });
110652
111271
  }
@@ -110709,11 +111328,9 @@ function TracesListContent(props) {
110709
111328
  // },
110710
111329
  {
110711
111330
  field: "timestamp",
110712
- headerName: "Timestamp",
111331
+ headerName: "Created At",
110713
111332
  width: 180,
110714
- hide: true,
110715
- // DISABLED - This is the main sort column for traces
110716
- disabled: true,
111333
+ hide: false,
110717
111334
  cellRenderer: (params) => /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-gray-500", children: params.value ? new Date(params.value).toLocaleString() : "-" })
110718
111335
  },
110719
111336
  {
@@ -110788,6 +111405,20 @@ function TracesListContent(props) {
110788
111405
  return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-gray-600", children: source || "-" });
110789
111406
  }
110790
111407
  },
111408
+ {
111409
+ field: "sessionReference",
111410
+ headerName: "Session Reference",
111411
+ width: 180,
111412
+ hide: true,
111413
+ cellRenderer: (params) => /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-gray-700", title: params.value || "-", children: params.value || "-" })
111414
+ },
111415
+ {
111416
+ field: "identity",
111417
+ headerName: "User Reference",
111418
+ width: 180,
111419
+ hide: true,
111420
+ cellRenderer: (params) => /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-gray-700", title: params.value || "-", children: params.value || "-" })
111421
+ },
110791
111422
  {
110792
111423
  field: "promptTokens",
110793
111424
  headerName: "Input Tokens",
@@ -110964,10 +111595,9 @@ function TracesListContent(props) {
110964
111595
  },
110965
111596
  {
110966
111597
  field: "timestamp",
110967
- label: "Timestamp",
110968
- // Same as API
111598
+ label: "Created At",
110969
111599
  apiColumnName: "Timestamp",
110970
- // API expects "Timestamp" (koretracing uiTableName)
111600
+ // Backend payload: keep "Timestamp" for API
110971
111601
  type: "datetime",
110972
111602
  operators: [">=", "<=", "="]
110973
111603
  },
@@ -111058,6 +111688,20 @@ function TracesListContent(props) {
111058
111688
  label: "Output Tokens",
111059
111689
  type: "number",
111060
111690
  operators: ["=", ">", ">=", "<", "<="]
111691
+ },
111692
+ {
111693
+ field: "sessionReference",
111694
+ label: "Session Reference",
111695
+ apiColumnName: "Session Reference",
111696
+ type: "string",
111697
+ operators: ["=", "!=", "contains"]
111698
+ },
111699
+ {
111700
+ field: "identity",
111701
+ label: "User Reference",
111702
+ apiColumnName: "User Reference",
111703
+ type: "string",
111704
+ operators: ["=", "!=", "contains"]
111061
111705
  }
111062
111706
  );
111063
111707
  return baseColumns;
@@ -111124,6 +111768,7 @@ function TracesListContent(props) {
111124
111768
  timeRangePresetLabel,
111125
111769
  onTimeRangeChange: handleTimeRangeChange,
111126
111770
  filters,
111771
+ filterColumns,
111127
111772
  onFiltersClick: () => setShowFilterPanel(!showFilterPanel),
111128
111773
  onModifyColumnsClick: () => setShowColumnCustomization(true),
111129
111774
  onExportClick: handleExport,
@@ -112175,12 +112820,12 @@ class TreeBuilder {
112175
112820
  * Process execution events and build a hierarchical tree structure
112176
112821
  * Session > Run > Node Tree
112177
112822
  */
112178
- static buildSessionTree(events, sessionId) {
112823
+ static buildSessionTree(events, sessionId, options) {
112179
112824
  var _a;
112180
112825
  const runGroups = this.groupEventsByRun(events);
112181
112826
  const runs = [];
112182
112827
  for (const [runId, runEvents] of runGroups.entries()) {
112183
- const runTree = this.buildRunTree(runId, runEvents);
112828
+ const runTree = this.buildRunTree(runId, runEvents, options);
112184
112829
  runs.push(runTree);
112185
112830
  }
112186
112831
  runs.sort((a4, b2) => new Date(a4.startTime).getTime() - new Date(b2.startTime).getTime());
@@ -112206,11 +112851,11 @@ class TreeBuilder {
112206
112851
  /**
112207
112852
  * Build tree for a single run
112208
112853
  */
112209
- static buildRunTree(runId, events) {
112854
+ static buildRunTree(runId, events, options) {
112210
112855
  var _a;
112211
112856
  const nodeEventMap = /* @__PURE__ */ new Map();
112212
112857
  events.forEach((event) => {
112213
- const nodeKey = `${event.data.id}|${event.data.name}|${event.data.toolName}`;
112858
+ const nodeKey = event.data.id;
112214
112859
  if (!nodeEventMap.has(nodeKey)) {
112215
112860
  nodeEventMap.set(nodeKey, {});
112216
112861
  }
@@ -112237,7 +112882,7 @@ class TreeBuilder {
112237
112882
  const status = this.calculateRunStatus(runEvents);
112238
112883
  const duration = endTime && startTime ? endTime - startTime : void 0;
112239
112884
  const totalTokens = this.calculateRunTokens(runEvents);
112240
- const userInput = this.extractUserInput(runEvents);
112885
+ const userInput = this.extractUserInput(runEvents, options);
112241
112886
  const finalOutput = this.extractFinalOutput(runEvents);
112242
112887
  return {
112243
112888
  runId,
@@ -112256,11 +112901,12 @@ class TreeBuilder {
112256
112901
  * Create TreeNode from paired started/completed events
112257
112902
  */
112258
112903
  static createTreeNodeFromEvents(startedEvent, completedEvent, runId) {
112904
+ var _a;
112259
112905
  const startTime = startedEvent.data.timestamp;
112260
112906
  const endTime = completedEvent == null ? void 0 : completedEvent.data.timestamp;
112261
112907
  const duration = endTime && startTime ? new Date(endTime).getTime() - new Date(startTime).getTime() : void 0;
112262
112908
  const primaryEvent = completedEvent || startedEvent;
112263
- const hasInputOutput = primaryEvent.data.type === "llm" || primaryEvent.data.type === "tool" || primaryEvent.data.type === "GuardrailsInputScan" || primaryEvent.data.type === "GuardrailsOutputScan" || primaryEvent.data.type === "Agent" || primaryEvent.data.type === "External Orchestrator" || primaryEvent.data.type === "ProxyWorker" || primaryEvent.data.type === "event";
112909
+ const hasInputOutput = primaryEvent.data.type === "llm" || primaryEvent.data.type === "tool" || primaryEvent.data.type === "GuardrailsInputScan" || primaryEvent.data.type === "GuardrailsOutputScan" || primaryEvent.data.type === "Agent" || primaryEvent.data.type === "External Orchestrator" || primaryEvent.data.type === "ProxyWorker" || primaryEvent.data.type === "PostProcessor" || primaryEvent.data.type === "event";
112264
112910
  const input = hasInputOutput ? startedEvent.data.input : void 0;
112265
112911
  let output = void 0;
112266
112912
  let error = void 0;
@@ -112274,7 +112920,8 @@ class TreeBuilder {
112274
112920
  const { toolInvocations, isResponse } = this.extractToolInvocations(output);
112275
112921
  console.log("toolInvocations", toolInvocations);
112276
112922
  console.log("isResponse", isResponse);
112277
- const provider = primaryEvent.data.type === "llm" ? this.extractProvider(primaryEvent.data.name || primaryEvent.data.toolName) : void 0;
112923
+ const extractedProvider = primaryEvent.data.type === "llm" ? this.extractProvider(primaryEvent.data.name || primaryEvent.data.toolName) : void 0;
112924
+ const provider = ((_a = primaryEvent.data.metadata) == null ? void 0 : _a.provider) || extractedProvider;
112278
112925
  return {
112279
112926
  id: primaryEvent.data.id,
112280
112927
  parentId: primaryEvent.data.parentId,
@@ -112433,12 +113080,22 @@ class TreeBuilder {
112433
113080
  /**
112434
113081
  * Extract initial user input from the first LLM node's input
112435
113082
  */
112436
- static extractUserInput(events) {
113083
+ static extractUserInput(events, options) {
113084
+ const preferDisplay = ((options == null ? void 0 : options.runHeaderInputMode) ?? "display") === "display";
112437
113085
  const llmEvents = events.filter(
112438
113086
  (e3) => e3.type === "node_started" && e3.data.type === "llm"
112439
113087
  ).sort((a4, b2) => new Date(a4.data.timestamp).getTime() - new Date(b2.data.timestamp).getTime());
112440
113088
  if (llmEvents.length > 0) {
112441
113089
  const firstLlmEvent = llmEvents[0];
113090
+ if (preferDisplay && firstLlmEvent.data.displayInput !== void 0 && firstLlmEvent.data.displayInput !== null) {
113091
+ const d3 = firstLlmEvent.data.displayInput;
113092
+ if (typeof d3 === "string") {
113093
+ return d3;
113094
+ }
113095
+ if (typeof d3 === "object") {
113096
+ return JSON.stringify(d3);
113097
+ }
113098
+ }
112442
113099
  if (firstLlmEvent.data.input) {
112443
113100
  if (typeof firstLlmEvent.data.input === "string") {
112444
113101
  return firstLlmEvent.data.input;
@@ -112506,6 +113163,22 @@ class TreeBuilder {
112506
113163
  */
112507
113164
  static extractFinalOutput(events) {
112508
113165
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
113166
+ const postProcessorEvents = events.filter(
113167
+ (e3) => {
113168
+ var _a2;
113169
+ return e3.type === "node_completed" && e3.data.type === "tool" && ((_a2 = e3.data.metadata) == null ? void 0 : _a2.type) === "PostProcessor" && e3.data.output;
113170
+ }
113171
+ );
113172
+ if (postProcessorEvents.length > 0) {
113173
+ const lastPP = postProcessorEvents[postProcessorEvents.length - 1];
113174
+ const ppOutput = lastPP.data.output;
113175
+ if (typeof ppOutput === "object" && ppOutput.output) {
113176
+ return typeof ppOutput.output === "string" ? ppOutput.output : JSON.stringify(ppOutput.output);
113177
+ }
113178
+ if (typeof ppOutput === "string") {
113179
+ return ppOutput;
113180
+ }
113181
+ }
112509
113182
  const errorEvents = events.filter(
112510
113183
  (e3) => e3.type === "node_completed" && e3.data.error && (e3.data.status === "errored" || e3.data.status === "failed")
112511
113184
  );
@@ -112632,8 +113305,8 @@ class TreeBuilder {
112632
113305
  /**
112633
113306
  * Update tree with new events (optimized for real-time updates)
112634
113307
  */
112635
- static updateTree(existingTree, _newEvents, allEvents) {
112636
- return this.buildSessionTree(allEvents, existingTree.sessionId);
113308
+ static updateTree(existingTree, _newEvents, allEvents, options) {
113309
+ return this.buildSessionTree(allEvents, existingTree.sessionId, options);
112637
113310
  }
112638
113311
  /**
112639
113312
  * Merge new events into existing events efficiently
@@ -112985,7 +113658,7 @@ class ApiService {
112985
113658
  nodeId,
112986
113659
  totalObservations: observations.length
112987
113660
  });
112988
- const matchedObservation = observations.find((obs) => {
113661
+ const matchingObservations = observations.filter((obs) => {
112989
113662
  let metadata = obs.metadata;
112990
113663
  if (typeof metadata === "string") {
112991
113664
  try {
@@ -113006,6 +113679,7 @@ class ApiService {
113006
113679
  });
113007
113680
  return nodeId === observationNodeId;
113008
113681
  });
113682
+ const matchedObservation = matchingObservations.find((obs) => obs.type === "GENERATION") || matchingObservations[0] || null;
113009
113683
  if (!matchedObservation) {
113010
113684
  const parts = nodeId.split("_");
113011
113685
  if (parts.length === 2) {
@@ -113147,6 +113821,36 @@ class ApiService {
113147
113821
  return this.config;
113148
113822
  }
113149
113823
  }
113824
+ function sanitizeForTestId(value) {
113825
+ return value.trim().toLowerCase().replace(/[\s_]+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/-+/g, "-").replace(/^-|-$/g, "") || "node";
113826
+ }
113827
+ function getDebuggerCallTypeTestId(node) {
113828
+ const name = (node.name ?? "unknown").toString();
113829
+ let slug = sanitizeForTestId(name);
113830
+ switch (node.type) {
113831
+ case "event":
113832
+ slug = slug.replace(/-event$/, "") || "event";
113833
+ return `debugger-event-${slug}`;
113834
+ case "Agent":
113835
+ return `debugger-${slug}-call`;
113836
+ case "tool":
113837
+ return `debugger-${slug}-call`;
113838
+ case "llm":
113839
+ return `debugger-llm-${slug}`;
113840
+ case "GuardrailsInputScan":
113841
+ return `debugger-guardrails-input-${slug}`;
113842
+ case "GuardrailsOutputScan":
113843
+ return `debugger-guardrails-output-${slug}`;
113844
+ case "External Orchestrator":
113845
+ return `debugger-orchestrator-${slug}`;
113846
+ case "ProxyWorker":
113847
+ return `debugger-proxy-${slug}`;
113848
+ case "PostProcessor":
113849
+ return `debugger-postprocessor-${slug}`;
113850
+ default:
113851
+ return `debugger-${String(node.type).toLowerCase().replace(/\s+/g, "-")}-${slug}`;
113852
+ }
113853
+ }
113150
113854
  function DebugCard({
113151
113855
  node,
113152
113856
  onToggle,
@@ -113158,9 +113862,12 @@ function DebugCard({
113158
113862
  projectId,
113159
113863
  nodeIndex = 0
113160
113864
  }) {
113865
+ var _a;
113866
+ const callTypeTestId = useMemo(() => getDebuggerCallTypeTestId(node), [node.type, node.name]);
113867
+ const cardTestId = useMemo(() => `${callTypeTestId}_${node.id}`, [callTypeTestId, node.id]);
113161
113868
  const isGuardrailsNode = useMemo(() => {
113162
- var _a;
113163
- return node.type === "GuardrailsInputScan" || node.type === "GuardrailsOutputScan" || ((_a = node.name) == null ? void 0 : _a.toLowerCase().includes("guardrail"));
113869
+ var _a2;
113870
+ return node.type === "GuardrailsInputScan" || node.type === "GuardrailsOutputScan" || ((_a2 = node.name) == null ? void 0 : _a2.toLowerCase().includes("guardrail"));
113164
113871
  }, [node.type, node.name]);
113165
113872
  const availableTabs = useMemo(() => {
113166
113873
  switch (node.type) {
@@ -113337,7 +114044,7 @@ function DebugCard({
113337
114044
  }
113338
114045
  };
113339
114046
  const getNodeIcon = () => {
113340
- var _a, _b;
114047
+ var _a2, _b;
113341
114048
  if (isGuardrailsNode) {
113342
114049
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-shrink-0 relative w-[24px] h-[24px] bg-gray-200 rounded-[8px] flex items-center justify-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "17", height: "21", viewBox: "0 0 17 21", fill: "none", className: "w-[16px] h-[16px]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
113343
114050
  "path",
@@ -113372,7 +114079,7 @@ function DebugCard({
113372
114079
  size: "small",
113373
114080
  name: node.name,
113374
114081
  className: "w-[24px] h-[24px]",
113375
- toolType: node.type === "tool" ? (_a = node.metadata) == null ? void 0 : _a.type : void 0,
114082
+ toolType: node.type === "tool" ? (_a2 = node.metadata) == null ? void 0 : _a2.type : void 0,
113376
114083
  provider: node.type === "llm" ? (_b = node.metadata) == null ? void 0 : _b.provider : void 0,
113377
114084
  modelName: node.type === "llm" ? node.name : void 0
113378
114085
  }
@@ -113396,7 +114103,7 @@ function DebugCard({
113396
114103
  return availableTabs;
113397
114104
  };
113398
114105
  const renderActionContent = () => {
113399
- var _a, _b;
114106
+ var _a2, _b;
113400
114107
  let toolInvocations = node.toolInvocations || [];
113401
114108
  if (node.type === "llm" && Array.isArray(node.output)) {
113402
114109
  toolInvocations = node.output.filter(
@@ -113418,7 +114125,7 @@ function DebugCard({
113418
114125
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-gray-600 truncate", children: child.name || "Unknown" })
113419
114126
  ] }, child.id || index))
113420
114127
  ] }),
113421
- toolInvocations.length > 0 && ((_b = (_a = toolInvocations[0]) == null ? void 0 : _a.args) == null ? void 0 : _b.reason) && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
114128
+ toolInvocations.length > 0 && ((_b = (_a2 = toolInvocations[0]) == null ? void 0 : _a2.args) == null ? void 0 : _b.reason) && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
113422
114129
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs font-medium text-gray-400 mb-[4px]", children: "Reason" }),
113423
114130
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-gray-600", children: toolInvocations[0].args.reason })
113424
114131
  ] })
@@ -113445,14 +114152,14 @@ function DebugCard({
113445
114152
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-gray-500 italic", children: "No actions taken" });
113446
114153
  };
113447
114154
  const extractOutputMessage = (output) => {
113448
- var _a, _b, _c, _d;
114155
+ var _a2, _b, _c, _d;
113449
114156
  if (!output || typeof output !== "object") return void 0;
113450
114157
  if (Array.isArray(output)) {
113451
114158
  const routeToUserTool = output.find(
113452
114159
  (item) => item && typeof item === "object" && (item.name === "route_to_user" || item.toolName === "route_to_user")
113453
114160
  );
113454
114161
  if (routeToUserTool) {
113455
- return ((_a = routeToUserTool.args) == null ? void 0 : _a.message) || routeToUserTool.message || ((_b = routeToUserTool.output) == null ? void 0 : _b.message);
114162
+ return ((_a2 = routeToUserTool.args) == null ? void 0 : _a2.message) || routeToUserTool.message || ((_b = routeToUserTool.output) == null ? void 0 : _b.message);
113456
114163
  }
113457
114164
  } else if (output.name === "route_to_user" || output.toolName === "route_to_user") {
113458
114165
  return ((_c = output.args) == null ? void 0 : _c.message) || output.message || ((_d = output.output) == null ? void 0 : _d.message);
@@ -113549,7 +114256,7 @@ function DebugCard({
113549
114256
  ] });
113550
114257
  };
113551
114258
  const renderTabContent = () => {
113552
- var _a;
114259
+ var _a2;
113553
114260
  switch (activeTab) {
113554
114261
  case "summary":
113555
114262
  if (isGuardrailsNode) {
@@ -113740,7 +114447,7 @@ function DebugCard({
113740
114447
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
113741
114448
  DataViewer,
113742
114449
  {
113743
- data: ((_a = node.metadata) == null ? void 0 : _a["logs"]) || {},
114450
+ data: ((_a2 = node.metadata) == null ? void 0 : _a2["logs"]) || {},
113744
114451
  title: "Execution Logs",
113745
114452
  maxHeight: "250px",
113746
114453
  defaultExpanded: true,
@@ -113753,15 +114460,15 @@ function DebugCard({
113753
114460
  };
113754
114461
  return (
113755
114462
  // bg-white w-full border-t border-gray-200
113756
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white w-full", "data-test-id": `debug_card_${node.id}`, children: [
114463
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white w-full", "data-test-id": cardTestId, "data-call-type-test-id": callTypeTestId, children: [
113757
114464
  /* @__PURE__ */ jsxRuntimeExports.jsx(
113758
114465
  "div",
113759
114466
  {
113760
114467
  className: `flex items-center pl-[8px] pr-[8px] relative transition-colors cursor-pointer w-full
113761
114468
  ${isSelected ? "" : ""}`,
113762
114469
  onClick: handleNodeClick,
113763
- "data-test-id": `debug_card_header_${node.id}`,
113764
- children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-[10px] w-full", "data-test-id": `debug_card_header_content_${node.id}`, children: [
114470
+ "data-test-id": `${callTypeTestId}_header`,
114471
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-[10px] w-full", "data-test-id": `${callTypeTestId}_header_content`, children: [
113765
114472
  /* @__PURE__ */ jsxRuntimeExports.jsx(
113766
114473
  "div",
113767
114474
  {
@@ -113775,7 +114482,7 @@ function DebugCard({
113775
114482
  }
113776
114483
  },
113777
114484
  title: hasChildren ? isExpanded ? "Collapse" : "Expand" : "Show details",
113778
- "data-test-id": `debug_card_toggle_${node.id}`,
114485
+ "data-test-id": `${callTypeTestId}_toggle`,
113779
114486
  children: /* @__PURE__ */ jsxRuntimeExports.jsx(
113780
114487
  ChevronRight,
113781
114488
  {
@@ -113784,28 +114491,28 @@ function DebugCard({
113784
114491
  )
113785
114492
  }
113786
114493
  ),
113787
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-[8px] w-full py-[8px] border-b border-gray-200", "data-test-id": `debug_card_node_info_${node.id}`, children: [
113788
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-shrink-0 rounded-[8px] bg-[#B2DDFF]", "data-test-id": `debug_card_node_icon_${node.id}`, children: getNodeIcon() }),
114494
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-[8px] w-full py-[8px] border-b border-gray-200", "data-test-id": `${callTypeTestId}_node_info`, children: [
114495
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-shrink-0 rounded-[8px] bg-[#B2DDFF]", "data-test-id": `${callTypeTestId}_node_icon`, children: getNodeIcon() }),
113789
114496
  /* @__PURE__ */ jsxRuntimeExports.jsx(
113790
114497
  "span",
113791
114498
  {
113792
114499
  className: "font-semibold text-gray-900 text-xs truncate w-full",
113793
114500
  title: node.type === "llm" ? node.name : void 0,
113794
- "data-test-id": `debug_card_node_name_${node.id}`,
113795
- children: isGuardrailsNode ? node.type === "GuardrailsInputScan" ? "Input Guardrails Scanner" : "Output Guardrails Scanner" : node.type === "llm" ? "AI Model Call" : node.type === "tool" ? formatToolName(node.name) : node.name
114501
+ "data-test-id": `${callTypeTestId}_node_name`,
114502
+ children: isGuardrailsNode ? node.type === "GuardrailsInputScan" ? "Input Guardrails Scanner" : "Output Guardrails Scanner" : node.type === "llm" ? ((_a = node == null ? void 0 : node.metadata) == null ? void 0 : _a.isRoutedModel) ? `AI Model Call (${node.name})` : "AI Model Call" : node.type === "PostProcessor" ? "Response Processor" : node.type === "tool" ? formatToolName(node.name) : node.name
113796
114503
  }
113797
114504
  ),
113798
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-[12px] text-[10px] text-gray-500", "data-test-id": `debug_card_node_metadata_${node.id}`, children: [
114505
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-[12px] text-[10px] text-gray-500", "data-test-id": `${callTypeTestId}_node_metadata`, children: [
113799
114506
  node.type === "Agent" && (() => {
113800
- var _a;
113801
- const llmChild = (_a = node.children) == null ? void 0 : _a.find((child) => child.type === "llm");
114507
+ var _a2;
114508
+ const llmChild = (_a2 = node.children) == null ? void 0 : _a2.find((child) => child.type === "llm");
113802
114509
  if (llmChild == null ? void 0 : llmChild.name) {
113803
114510
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
113804
114511
  "span",
113805
114512
  {
113806
114513
  className: "text-[10px] text-gray-500 truncate max-w-[100px]",
113807
114514
  title: llmChild.name,
113808
- "data-test-id": `debug_card_node_model_name_${node.id}`,
114515
+ "data-test-id": `${callTypeTestId}_node_model_name`,
113809
114516
  children: llmChild.name
113810
114517
  }
113811
114518
  );
@@ -113813,7 +114520,7 @@ function DebugCard({
113813
114520
  return null;
113814
114521
  })(),
113815
114522
  (node.type === "Agent" || node.type === "llm" || isGuardrailsNode) && (() => {
113816
- var _a, _b, _c;
114523
+ var _a2, _b, _c;
113817
114524
  let llmUsage = node.llmUsage;
113818
114525
  if (node.type === "Agent" && node.children) {
113819
114526
  const llmChildren = node.children.filter((child) => child.type === "llm");
@@ -113835,10 +114542,10 @@ function DebugCard({
113835
114542
  "span",
113836
114543
  {
113837
114544
  className: "text-[10px] text-gray-500 whitespace-nowrap cursor-help",
113838
- title: `Input: ${((_a = llmUsage.input_tokens) == null ? void 0 : _a.toLocaleString()) || 0} tokens
114545
+ title: `Input: ${((_a2 = llmUsage.input_tokens) == null ? void 0 : _a2.toLocaleString()) || 0} tokens
113839
114546
  Output: ${((_b = llmUsage.output_tokens) == null ? void 0 : _b.toLocaleString()) || 0} tokens
113840
114547
  Total: ${((_c = llmUsage.total_tokens) == null ? void 0 : _c.toLocaleString()) || 0} tokens`,
113841
- "data-test-id": `debug_card_node_tokens_${node.id}`,
114548
+ "data-test-id": `${callTypeTestId}_node_tokens`,
113842
114549
  children: [
113843
114550
  llmUsage.total_tokens.toLocaleString(),
113844
114551
  " Tokens"
@@ -113848,34 +114555,34 @@ Total: ${((_c = llmUsage.total_tokens) == null ? void 0 : _c.toLocaleString()) |
113848
114555
  }
113849
114556
  return null;
113850
114557
  })(),
113851
- node.duration && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-[4px]", "data-test-id": `debug_card_node_duration_${node.id}`, children: [
114558
+ node.duration && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-[4px]", "data-test-id": `${callTypeTestId}_node_duration`, children: [
113852
114559
  /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "w-[12px] h-[12px]" }),
113853
114560
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] text-gray-500 whitespace-nowrap", children: formatDuration(node.duration) })
113854
114561
  ] })
113855
114562
  ] }),
113856
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-shrink-0", "data-test-id": `debug_card_node_status_${node.id}`, children: getStatusIcon() })
114563
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-shrink-0", "data-test-id": `${callTypeTestId}_node_status`, children: getStatusIcon() })
113857
114564
  ] })
113858
114565
  ] })
113859
114566
  }
113860
114567
  ),
113861
- isSelected && availableTabs.length > 0 && showDetailView && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full pl-[32px] relative", "data-test-id": `debug_card_detail_panel_${node.id}`, children: [
113862
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute top-[-40px] left-[16px] w-[1px] border-l border-dashed border-gray-200 h-[calc(100%+40px)] z-[1]", "data-test-id": `debug_card_detail_panel_connector_${node.id}` }),
113863
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-[4px] py-[8px] w-full", "data-test-id": `debug_card_detail_panel_content_${node.id}`, children: [
113864
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "bg-gray-50 rounded-[4px] p-[4px] inline-flex gap-[4px] mb-[8px] border border-gray-200", "data-test-id": `debug_card_detail_panel_tabs_${node.id}`, children: getTabsForNodeType().map((tab) => /* @__PURE__ */ jsxRuntimeExports.jsx(
114568
+ isSelected && availableTabs.length > 0 && showDetailView && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full pl-[32px] relative", "data-test-id": `${callTypeTestId}_detail_panel`, children: [
114569
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute top-[-40px] left-[16px] w-[1px] border-l border-dashed border-gray-200 h-[calc(100%+40px)] z-[1]", "data-test-id": `${callTypeTestId}_detail_panel_connector` }),
114570
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-[4px] py-[8px] w-full", "data-test-id": `${callTypeTestId}_detail_panel_content`, children: [
114571
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "bg-gray-50 rounded-[4px] p-[4px] inline-flex gap-[4px] mb-[8px] border border-gray-200", "data-test-id": `${callTypeTestId}_detail_panel_tabs`, children: getTabsForNodeType().map((tab) => /* @__PURE__ */ jsxRuntimeExports.jsx(
113865
114572
  "button",
113866
114573
  {
113867
114574
  onClick: () => handleTabClick(tab),
113868
114575
  className: `px-[8px] py-[4px] text-xs font-medium rounded-[4px] text-gray-500 hover:text-gray-700 hover:shadow-tab hover:bg-white transition-colors ${activeTab === tab ? "bg-white text-gray-900 shadow-tab" : "text-gray-500 hover:text-gray-700 hover:bg-white"}`,
113869
- "data-test-id": `debug_card_detail_panel_tab_${node.id}_${tab}`,
114576
+ "data-test-id": `${callTypeTestId}_detail_panel_tab_${tab}`,
113870
114577
  children: tab.charAt(0).toUpperCase() + tab.slice(1)
113871
114578
  },
113872
114579
  tab
113873
114580
  )) }),
113874
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-[4px]", "data-test-id": `debug_card_detail_panel_tab_content_${node.id}`, children: renderTabContent() })
114581
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-[4px]", "data-test-id": `${callTypeTestId}_detail_panel_tab_content`, children: renderTabContent() })
113875
114582
  ] })
113876
114583
  ] }),
113877
- isExpanded && hasChildren && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full pl-[32px] relative", "data-test-id": `debug_card_children_${node.id}`, children: [
113878
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute top-[-40px] left-[16px] w-[1px] border-l border-dashed border-gray-200 h-[calc(100%+40px)] z-[1]", "data-test-id": `debug_card_children_connector_${node.id}` }),
114584
+ isExpanded && hasChildren && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full pl-[32px] relative", "data-test-id": `${callTypeTestId}_children`, children: [
114585
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute top-[-40px] left-[16px] w-[1px] border-l border-dashed border-gray-200 h-[calc(100%+40px)] z-[1]", "data-test-id": `${callTypeTestId}_children_connector` }),
113879
114586
  node.children.map((child, index) => /* @__PURE__ */ jsxRuntimeExports.jsx(
113880
114587
  DebugCard,
113881
114588
  {
@@ -113911,6 +114618,7 @@ const DebugPanel = forwardRef(({
113911
114618
  expansionMode = "none",
113912
114619
  showExpansionControls = false,
113913
114620
  defaultDetailView = true,
114621
+ runHeaderInputMode = "display",
113914
114622
  apiConfig
113915
114623
  } = config2;
113916
114624
  console.log("🔧 DebugPanel - Config received:", {
@@ -113971,10 +114679,12 @@ const DebugPanel = forwardRef(({
113971
114679
  }
113972
114680
  }), []);
113973
114681
  const sessionTree = useMemo(() => {
113974
- const tree = TreeBuilder.buildSessionTree(executionEvents, sessionId);
114682
+ const tree = TreeBuilder.buildSessionTree(executionEvents, sessionId, {
114683
+ runHeaderInputMode
114684
+ });
113975
114685
  prevSessionTreeRef.current = tree;
113976
114686
  return tree;
113977
- }, [executionEvents, sessionId]);
114687
+ }, [executionEvents, sessionId, runHeaderInputMode]);
113978
114688
  const getAllNodeIds = (tree) => {
113979
114689
  const nodeIds = [];
113980
114690
  const collectIds = (node) => {
@@ -114382,16 +115092,25 @@ const DebugPanel = forwardRef(({
114382
115092
  const findFinalOutput = (nodes) => {
114383
115093
  let lastOutput = void 0;
114384
115094
  let routeToUserOutput = void 0;
115095
+ let postProcessorOutput = void 0;
114385
115096
  const traverse = (nodeList) => {
114386
- var _a, _b, _c, _d, _e;
115097
+ var _a, _b, _c, _d, _e, _f;
114387
115098
  for (const node of nodeList) {
115099
+ if (node.type === "tool" && ((_a = node.metadata) == null ? void 0 : _a.type) === "PostProcessor" && node.output) {
115100
+ const ppOut = node.output;
115101
+ if (typeof ppOut === "object" && ppOut.output) {
115102
+ postProcessorOutput = typeof ppOut.output === "string" ? ppOut.output : JSON.stringify(ppOut.output);
115103
+ } else if (typeof ppOut === "string") {
115104
+ postProcessorOutput = ppOut;
115105
+ }
115106
+ }
114388
115107
  if (node.type === "tool" && (node.name === "route_to_user" || node.name === "route_to_user")) {
114389
115108
  if (node.output) {
114390
115109
  if (typeof node.output === "string") {
114391
115110
  routeToUserOutput = node.output;
114392
- } else if ((_a = node.output) == null ? void 0 : _a.message) {
115111
+ } else if ((_b = node.output) == null ? void 0 : _b.message) {
114393
115112
  routeToUserOutput = node.output.message;
114394
- } else if ((_b = node.output) == null ? void 0 : _b.result) {
115113
+ } else if ((_c = node.output) == null ? void 0 : _c.result) {
114395
115114
  routeToUserOutput = node.output.result;
114396
115115
  }
114397
115116
  }
@@ -114401,7 +115120,7 @@ const DebugPanel = forwardRef(({
114401
115120
  (item) => (item == null ? void 0 : item.name) === "route_to_user" || (item == null ? void 0 : item.toolName) === "route_to_user"
114402
115121
  );
114403
115122
  if (routeItem) {
114404
- if ((_c = routeItem.args) == null ? void 0 : _c.message) {
115123
+ if ((_d = routeItem.args) == null ? void 0 : _d.message) {
114405
115124
  routeToUserOutput = routeItem.args.message;
114406
115125
  } else if (routeItem.message) {
114407
115126
  routeToUserOutput = routeItem.message;
@@ -114412,9 +115131,9 @@ const DebugPanel = forwardRef(({
114412
115131
  if (typeof node.output === "string") {
114413
115132
  lastOutput = node.output;
114414
115133
  } else if (!Array.isArray(node.output)) {
114415
- if ((_d = node.output) == null ? void 0 : _d.message) {
115134
+ if ((_e = node.output) == null ? void 0 : _e.message) {
114416
115135
  lastOutput = node.output.message;
114417
- } else if ((_e = node.output) == null ? void 0 : _e.result) {
115136
+ } else if ((_f = node.output) == null ? void 0 : _f.result) {
114418
115137
  lastOutput = node.output.result;
114419
115138
  } else if (typeof node.output === "object") {
114420
115139
  if (!node.output.name && !node.output.toolName) {
@@ -114429,7 +115148,7 @@ const DebugPanel = forwardRef(({
114429
115148
  }
114430
115149
  };
114431
115150
  traverse(nodes);
114432
- return routeToUserOutput || lastOutput;
115151
+ return postProcessorOutput || routeToUserOutput || lastOutput;
114433
115152
  };
114434
115153
  const outputFromNodes = run2.rootNodes ? findFinalOutput(run2.rootNodes) : void 0;
114435
115154
  const finalOutput = outputFromNodes || run2.finalOutput;
@@ -141250,6 +141969,57 @@ function nodeContentToInline(content) {
141250
141969
  };
141251
141970
  });
141252
141971
  }
141972
+ function getVariableContextAtPosition(editor, pos) {
141973
+ const { doc: doc2 } = editor.state;
141974
+ if (pos < 2 || pos > doc2.content.size) {
141975
+ return null;
141976
+ }
141977
+ const $pos = doc2.resolve(pos);
141978
+ const parent = $pos.parent;
141979
+ if (!parent.isTextblock) {
141980
+ return null;
141981
+ }
141982
+ const contentStart = $pos.start();
141983
+ let text = "";
141984
+ const posMap = [];
141985
+ parent.forEach((node, offset2) => {
141986
+ const nodeDocStart = contentStart + offset2;
141987
+ if (nodeDocStart >= pos) return;
141988
+ if (node.isText && node.text) {
141989
+ const charsToTake = Math.min(node.text.length, pos - nodeDocStart);
141990
+ for (let i2 = 0; i2 < charsToTake; i2++) {
141991
+ posMap.push(nodeDocStart + i2);
141992
+ text += node.text[i2];
141993
+ }
141994
+ }
141995
+ });
141996
+ const lastOpen = text.lastIndexOf("{{");
141997
+ if (lastOpen === -1) {
141998
+ return null;
141999
+ }
142000
+ const queryText = text.substring(lastOpen + 2);
142001
+ if (queryText.includes("}}")) {
142002
+ return null;
142003
+ }
142004
+ const triggerFrom = posMap[lastOpen];
142005
+ if (triggerFrom === void 0) {
142006
+ return null;
142007
+ }
142008
+ const trimmedQuery = /^\}*$/.test(queryText) ? "" : queryText;
142009
+ return { triggerFrom, query: trimmedQuery };
142010
+ }
142011
+ const TYPE_PREFIXES = ["env", "memory", "system", "content"];
142012
+ function inferVariableType(path) {
142013
+ const firstDot = path.indexOf(".");
142014
+ if (firstDot === -1) return "custom";
142015
+ const prefix2 = path.substring(0, firstDot).toLowerCase();
142016
+ return TYPE_PREFIXES.includes(prefix2) ? prefix2 : "custom";
142017
+ }
142018
+ function removeTypePrefix(path) {
142019
+ const type = inferVariableType(path);
142020
+ if (type === "custom") return path;
142021
+ return path.substring(type.length + 1);
142022
+ }
141253
142023
  const buildVariableSyntax = (variableType, path) => {
141254
142024
  if (variableType === "system" || variableType === "custom") {
141255
142025
  return `{{${path}}}`;
@@ -141968,6 +142738,27 @@ const ChevronRightIcon = ({ size = 16, className }) => /* @__PURE__ */ jsxRuntim
141968
142738
  )
141969
142739
  }
141970
142740
  );
142741
+ const AIStarIcon = ({ size = 14, className }) => /* @__PURE__ */ jsxRuntimeExports.jsx(
142742
+ "svg",
142743
+ {
142744
+ width: size,
142745
+ height: size,
142746
+ viewBox: "0 0 14 14",
142747
+ fill: "none",
142748
+ xmlns: "http://www.w3.org/2000/svg",
142749
+ className,
142750
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(
142751
+ "path",
142752
+ {
142753
+ d: "M2.10833 12.3167V9.4M2.10833 3.56667V0.65M0.65 2.10833H3.56667M0.65 10.8583H3.56667M7.06667 1.23333L6.05506 3.8635C5.89056 4.29122 5.8083 4.50508 5.68039 4.68497C5.56703 4.8444 5.42773 4.98369 5.2683 5.09706C5.08841 5.22497 4.87455 5.30722 4.44684 5.47173L1.81667 6.48333L4.44684 7.49494C4.87455 7.65944 5.08841 7.7417 5.2683 7.86961C5.42773 7.98297 5.56703 8.12227 5.68039 8.2817C5.8083 8.46159 5.89056 8.67545 6.05506 9.10316L7.06667 11.7333L8.07827 9.10316C8.24278 8.67545 8.32503 8.46159 8.45294 8.2817C8.56631 8.12227 8.7056 7.98297 8.86503 7.86961C9.04492 7.7417 9.25878 7.65944 9.6865 7.49494L12.3167 6.48333L9.6865 5.47173C9.25878 5.30722 9.04492 5.22497 8.86503 5.09706C8.7056 4.98369 8.56631 4.8444 8.45294 4.68497C8.32503 4.50508 8.24278 4.29122 8.07827 3.8635L7.06667 1.23333Z",
142754
+ stroke: "currentColor",
142755
+ strokeWidth: "1.3",
142756
+ strokeLinecap: "round",
142757
+ strokeLinejoin: "round"
142758
+ }
142759
+ )
142760
+ }
142761
+ );
141971
142762
  const CATEGORY_ICON_MAP = {
141972
142763
  agents: AgentsIcon,
141973
142764
  tools: ToolsIcon,
@@ -142844,7 +143635,7 @@ const VariableMenu = ({
142844
143635
  setCurrentPath(parsedQuery.path);
142845
143636
  }
142846
143637
  }, [parsedQuery.category, parsedQuery.path, activeCategory]);
142847
- useEffect(() => {
143638
+ useLayoutEffect(() => {
142848
143639
  if (!menuRef.current) return;
142849
143640
  const menuRect = menuRef.current.getBoundingClientRect();
142850
143641
  const viewportWidth = window.innerWidth;
@@ -142865,7 +143656,7 @@ const VariableMenu = ({
142865
143656
  newTop = padding;
142866
143657
  }
142867
143658
  setAdjustedPosition({ top: newTop, left: newLeft });
142868
- }, [position]);
143659
+ }, [position, activeCategory, currentPath.length, query]);
142869
143660
  const categories = [
142870
143661
  { id: "env", label: "Environment Variables", icon: VariableIcon, variables: envVariables },
142871
143662
  { id: "memory", label: "Memory", icon: MemoryIcon, variables: memoryVariables },
@@ -142940,13 +143731,21 @@ const VariableMenu = ({
142940
143731
  }
142941
143732
  }, [editorControlled]);
142942
143733
  useEffect(() => {
143734
+ const isEventInsideMenu = (event) => {
143735
+ if (!menuRef.current) return false;
143736
+ const path = typeof event.composedPath === "function" ? event.composedPath() : [];
143737
+ if (path.length > 0) {
143738
+ return path.includes(menuRef.current);
143739
+ }
143740
+ return menuRef.current.contains(event.target);
143741
+ };
142943
143742
  const handleClickOutside = (e3) => {
142944
- if (menuRef.current && !menuRef.current.contains(e3.target)) {
143743
+ if (!isEventInsideMenu(e3)) {
142945
143744
  onClose();
142946
143745
  }
142947
143746
  };
142948
- document.addEventListener("mousedown", handleClickOutside);
142949
- return () => document.removeEventListener("mousedown", handleClickOutside);
143747
+ document.addEventListener("mousedown", handleClickOutside, true);
143748
+ return () => document.removeEventListener("mousedown", handleClickOutside, true);
142950
143749
  }, [onClose]);
142951
143750
  useEffect(() => {
142952
143751
  const handleKeyDown2 = (e3) => {
@@ -143033,6 +143832,10 @@ const VariableMenu = ({
143033
143832
  "button",
143034
143833
  {
143035
143834
  type: "button",
143835
+ onMouseDown: (e3) => {
143836
+ e3.preventDefault();
143837
+ e3.stopPropagation();
143838
+ },
143036
143839
  onClick: handleBack,
143037
143840
  className: "flex items-center justify-center w-[24px] h-[24px] p-0 border-0 bg-[#F9FAFB] rounded-[4px] cursor-pointer text-[#667085] hover:bg-[#F2F4F7]",
143038
143841
  "aria-label": "Go back",
@@ -143058,7 +143861,7 @@ const VariableMenu = ({
143058
143861
  )
143059
143862
  ] }) }),
143060
143863
  !activeCategory && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pt-[8px] pb-[4px] px-[12px]", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[12px] leading-[16px] font-normal text-[#667085]", children: "Type to search or choose from:" }) }),
143061
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto", children: items.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "py-[16px] text-center text-[#667085] text-[14px]", children: "No items found" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: items.map((item, index) => {
143864
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 min-h-0 overflow-y-auto", children: items.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "py-[16px] text-center text-[#667085] text-[14px]", children: "No items found" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: items.map((item, index) => {
143062
143865
  var _a;
143063
143866
  const isCategory = "variables" in item;
143064
143867
  const Icon = isCategory ? item.icon : getIconForType(item.type);
@@ -143067,7 +143870,11 @@ const VariableMenu = ({
143067
143870
  "button",
143068
143871
  {
143069
143872
  type: "button",
143070
- onClick: () => handleItemClick(item),
143873
+ onMouseDown: (e3) => {
143874
+ e3.preventDefault();
143875
+ e3.stopPropagation();
143876
+ handleItemClick(item);
143877
+ },
143071
143878
  className: `flex items-center gap-[8px] w-full px-[12px] py-[8px] border-0 rounded-[4px] text-left cursor-pointer transition-colors duration-100 ${index === selectedIndex ? "bg-[#F9FAFB]" : "bg-transparent hover:bg-[#F9FAFB]"}`,
143072
143879
  onMouseEnter: () => setSelectedIndex(index),
143073
143880
  "data-test-id": `md-editor-variable-item-${isCategory ? item.id : item.id}`,
@@ -143643,7 +144450,9 @@ const UnifiedToolbar = ({
143643
144450
  theme = "light",
143644
144451
  disabled = false,
143645
144452
  containerRef,
143646
- followSelection = false
144453
+ followSelection = false,
144454
+ showDesignWithAI = false,
144455
+ onDesignWithAI
143647
144456
  }) => {
143648
144457
  const [position, setPosition] = useState(null);
143649
144458
  const [isAtSelection, setIsAtSelection] = useState(false);
@@ -144001,7 +144810,30 @@ const UnifiedToolbar = ({
144001
144810
  )
144002
144811
  ] }),
144003
144812
  /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarDivider$2, {}),
144004
- showAIButton && onAIAction && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { ref: aiDropdownRef, className: "relative shrink-0", children: [
144813
+ showDesignWithAI && onDesignWithAI && /* @__PURE__ */ jsxRuntimeExports.jsxs(
144814
+ "button",
144815
+ {
144816
+ type: "button",
144817
+ onClick: (e3) => {
144818
+ e3.preventDefault();
144819
+ e3.stopPropagation();
144820
+ onDesignWithAI();
144821
+ },
144822
+ disabled,
144823
+ className: `
144824
+ flex items-center justify-center gap-1 px-3 py-1 rounded-[4px]
144825
+ text-[12px] leading-[16px] font-medium transition-colors duration-150 whitespace-nowrap
144826
+ border border-[#6A11CB] text-[#004EEB] hover:bg-[#EFF4FF]
144827
+ ${disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}
144828
+ `,
144829
+ "data-id": "toolbar-design-with-ai",
144830
+ children: [
144831
+ /* @__PURE__ */ jsxRuntimeExports.jsx(AIStarIcon, { size: 14, className: "text-[#155EEF]" }),
144832
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Design with AI" })
144833
+ ]
144834
+ }
144835
+ ),
144836
+ showAIButton && onAIAction && !showDesignWithAI && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { ref: aiDropdownRef, className: "relative shrink-0", children: [
144005
144837
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
144006
144838
  "button",
144007
144839
  {
@@ -144116,7 +144948,8 @@ const ACTION_LABELS = {
144116
144948
  "make-shorter": "Make Shorter",
144117
144949
  "make-longer": "Make Longer",
144118
144950
  "convert-to-yaml": "Convert to YAML",
144119
- "custom": "Custom Modify"
144951
+ "custom": "Custom Modify",
144952
+ "generate": "Generate"
144120
144953
  };
144121
144954
  function calculateTextSimilarity(text1, text2) {
144122
144955
  if (text1 === text2) return 1;
@@ -144150,7 +144983,7 @@ const AIDesignPanel = ({
144150
144983
  sessionState,
144151
144984
  sessionActions
144152
144985
  }) => {
144153
- var _a, _b;
144986
+ var _a, _b, _c;
144154
144987
  const useSessionMode = !!sessionState && !!sessionActions;
144155
144988
  const [messages, setMessages] = useState([]);
144156
144989
  const [inputValue, setInputValue] = useState("");
@@ -144166,6 +144999,36 @@ const AIDesignPanel = ({
144166
144999
  const modificationReason = useSessionMode ? sessionState.modificationReason : selectionModifiedReason;
144167
145000
  const currentGeneratedContent = useSessionMode ? (_b = sessionState.session) == null ? void 0 : _b.lastGeneratedContent : generatedContent;
144168
145001
  const displayMessages = useSessionMode ? convertSessionHistoryToMessages(sessionState) : messages;
145002
+ const [appliedFeedback, setAppliedFeedback] = useState(null);
145003
+ const [copiedFeedback, setCopiedFeedback] = useState(false);
145004
+ const [pendingApplyMode, setPendingApplyMode] = useState(null);
145005
+ const [autocopiedOnFail, setAutocopiedOnFail] = useState(false);
145006
+ const appliedTimerRef = useRef(null);
145007
+ const copiedTimerRef = useRef(null);
145008
+ const lastAssistantMsgId = useMemo(() => {
145009
+ const assistantMsgs = displayMessages.filter(
145010
+ (m3) => m3.type === "assistant" && !m3.isGenerating && !m3.isError
145011
+ );
145012
+ return assistantMsgs.length > 0 ? assistantMsgs[assistantMsgs.length - 1].id : null;
145013
+ }, [displayMessages]);
145014
+ const showInsertButton = isSelectionMode;
145015
+ const cursorInsertActive = useSessionMode && sessionState.cursorInsertPosition !== null;
145016
+ const replaceTooltip = isSelectionMode ? "Replace selection" : "Replace all";
145017
+ const insertTooltip = cursorInsertActive ? "Insert at cursor" : "Insert below selection";
145018
+ useEffect(() => {
145019
+ return () => {
145020
+ if (appliedTimerRef.current) clearTimeout(appliedTimerRef.current);
145021
+ if (copiedTimerRef.current) clearTimeout(copiedTimerRef.current);
145022
+ };
145023
+ }, []);
145024
+ useEffect(() => {
145025
+ if (isCurrentlyGenerating) {
145026
+ setAppliedFeedback(null);
145027
+ setCopiedFeedback(false);
145028
+ setPendingApplyMode(null);
145029
+ setAutocopiedOnFail(false);
145030
+ }
145031
+ }, [isCurrentlyGenerating]);
144169
145032
  useEffect(() => {
144170
145033
  var _a2;
144171
145034
  (_a2 = messagesEndRef.current) == null ? void 0 : _a2.scrollIntoView({ behavior: "smooth" });
@@ -144269,8 +145132,9 @@ const AIDesignPanel = ({
144269
145132
  setGeneratedContent(response.refinedText);
144270
145133
  onContentGenerated == null ? void 0 : onContentGenerated(true);
144271
145134
  } catch (error) {
145135
+ const errorMsg = error instanceof Error ? error.message : "Failed to generate. Please try again.";
144272
145136
  setMessages((prev) => prev.map(
144273
- (msg) => msg.id === aiMsgId ? { ...msg, content: "Failed to generate. Please try again.", isGenerating: false, isError: true } : msg
145137
+ (msg) => msg.id === aiMsgId ? { ...msg, content: errorMsg, isGenerating: false, isError: true } : msg
144274
145138
  ));
144275
145139
  } finally {
144276
145140
  setIsGenerating(false);
@@ -144312,8 +145176,9 @@ const AIDesignPanel = ({
144312
145176
  setGeneratedContent(response.refinedText);
144313
145177
  onContentGenerated == null ? void 0 : onContentGenerated(true);
144314
145178
  } catch (error) {
145179
+ const errorMsg = error instanceof Error ? error.message : "Failed to generate. Please try again.";
144315
145180
  setMessages((prev) => prev.map(
144316
- (msg) => msg.id === aiMsgId ? { ...msg, content: "Failed to generate. Please try again.", isGenerating: false, isError: true } : msg
145181
+ (msg) => msg.id === aiMsgId ? { ...msg, content: errorMsg, isGenerating: false, isError: true } : msg
144317
145182
  ));
144318
145183
  } finally {
144319
145184
  setIsGenerating(false);
@@ -144348,6 +145213,52 @@ const AIDesignPanel = ({
144348
145213
  };
144349
145214
  }
144350
145215
  }, [useSessionMode, sessionActions, generatedContent, onReplace, isSelectionMode]);
145216
+ const handleCopy = useCallback(async () => {
145217
+ var _a2;
145218
+ const content = useSessionMode ? (_a2 = sessionState == null ? void 0 : sessionState.session) == null ? void 0 : _a2.lastGeneratedContent : generatedContent;
145219
+ if (content) {
145220
+ await navigator.clipboard.writeText(content);
145221
+ setCopiedFeedback(true);
145222
+ if (copiedTimerRef.current) clearTimeout(copiedTimerRef.current);
145223
+ copiedTimerRef.current = setTimeout(() => setCopiedFeedback(false), 2e3);
145224
+ }
145225
+ }, [useSessionMode, sessionState, generatedContent]);
145226
+ const handleInsertWithFeedback = useCallback(() => {
145227
+ setPendingApplyMode("insert");
145228
+ setAutocopiedOnFail(false);
145229
+ handleInsert();
145230
+ }, [handleInsert]);
145231
+ const handleReplaceWithFeedback = useCallback(() => {
145232
+ setPendingApplyMode("replace");
145233
+ setAutocopiedOnFail(false);
145234
+ handleReplace();
145235
+ }, [handleReplace]);
145236
+ useEffect(() => {
145237
+ var _a2;
145238
+ if (!pendingApplyMode) return;
145239
+ if (useSessionMode) {
145240
+ if (sessionState.status === "applied") {
145241
+ setAppliedFeedback(pendingApplyMode);
145242
+ setPendingApplyMode(null);
145243
+ if (appliedTimerRef.current) clearTimeout(appliedTimerRef.current);
145244
+ appliedTimerRef.current = setTimeout(() => setAppliedFeedback(null), 2500);
145245
+ } else if (sessionState.isOriginalModified) {
145246
+ const content = (_a2 = sessionState.session) == null ? void 0 : _a2.lastGeneratedContent;
145247
+ if (content) {
145248
+ navigator.clipboard.writeText(content).catch(() => {
145249
+ });
145250
+ setAutocopiedOnFail(true);
145251
+ }
145252
+ setAppliedFeedback(null);
145253
+ setPendingApplyMode(null);
145254
+ }
145255
+ } else {
145256
+ setAppliedFeedback(pendingApplyMode);
145257
+ setPendingApplyMode(null);
145258
+ if (appliedTimerRef.current) clearTimeout(appliedTimerRef.current);
145259
+ appliedTimerRef.current = setTimeout(() => setAppliedFeedback(null), 2500);
145260
+ }
145261
+ }, [pendingApplyMode, useSessionMode, sessionState == null ? void 0 : sessionState.status, sessionState == null ? void 0 : sessionState.isOriginalModified, (_c = sessionState == null ? void 0 : sessionState.session) == null ? void 0 : _c.lastGeneratedContent]);
144351
145262
  const handleStop = useCallback(() => {
144352
145263
  if (useSessionMode) {
144353
145264
  return;
@@ -144447,34 +145358,71 @@ const AIDesignPanel = ({
144447
145358
  // Result - gray background bubble
144448
145359
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full", children: [
144449
145360
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "bg-[#F2F4F7] rounded-xl p-3", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm text-[#101828] leading-relaxed whitespace-pre-wrap", children: message.content }) }),
144450
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 mt-2", children: [
144451
- /* @__PURE__ */ jsxRuntimeExports.jsx(
144452
- "button",
144453
- {
144454
- type: "button",
144455
- onClick: handleInsert,
144456
- disabled: isModified,
144457
- title: isModified ? modificationReason || "Selected text has been modified" : void 0,
144458
- className: `px-2.5 py-0.5 text-sm font-medium rounded-full border transition-colors ${isModified ? "text-[#98A2B3] bg-[#F9FAFB] border-[#EAECF0] cursor-not-allowed" : "text-[#344054] bg-white border-[#EAECF0] hover:bg-gray-50 cursor-pointer"}`,
144459
- children: "Insert"
144460
- }
144461
- ),
144462
- (onReplace || useSessionMode) && /* @__PURE__ */ jsxRuntimeExports.jsx(
144463
- "button",
144464
- {
144465
- type: "button",
144466
- onClick: handleReplace,
144467
- disabled: isModified,
144468
- title: isModified ? modificationReason || "Selected text has been modified" : void 0,
144469
- className: `px-2.5 py-0.5 text-sm font-medium rounded-full border transition-colors ${isModified ? "text-[#98A2B3] bg-[#F9FAFB] border-[#EAECF0] cursor-not-allowed" : "text-[#344054] bg-white border-[#EAECF0] hover:bg-gray-50 cursor-pointer"}`,
144470
- children: "Replace"
144471
- }
144472
- )
144473
- ] }),
144474
- isModified && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs text-[#F79009] mt-1.5 flex items-center gap-1", children: [
144475
- /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M6 4V6M6 8H6.005M10.5 6C10.5 8.48528 8.48528 10.5 6 10.5C3.51472 10.5 1.5 8.48528 1.5 6C1.5 3.51472 3.51472 1.5 6 1.5C8.48528 1.5 10.5 3.51472 10.5 6Z", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }),
144476
- modificationReason || "Original text was modified"
144477
- ] })
145361
+ message.id === lastAssistantMsgId && /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: appliedFeedback ? (
145362
+ /* Success feedback */
145363
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5 mt-2 text-[#12B76A] animate-[fadeIn_0.2s_ease-out]", children: [
145364
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { size: 14, strokeWidth: 2.5 }),
145365
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm font-medium", children: appliedFeedback === "replace" ? "Replaced" : "Inserted" }),
145366
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs text-[#667085] ml-1", children: [
145367
+ navigator.platform.includes("Mac") ? "⌘Z" : "Ctrl+Z",
145368
+ " to undo"
145369
+ ] })
145370
+ ] })
145371
+ ) : isModified ? (
145372
+ /* Recovery UI -- original text was modified, apply would fail */
145373
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-2 animate-[fadeIn_0.2s_ease-out]", children: [
145374
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
145375
+ "button",
145376
+ {
145377
+ type: "button",
145378
+ onClick: handleCopy,
145379
+ className: "px-2.5 py-0.5 text-sm font-medium rounded-full border transition-colors text-[#344054] bg-white border-[#EAECF0] hover:bg-gray-50 cursor-pointer flex items-center gap-1.5",
145380
+ children: copiedFeedback || autocopiedOnFail ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
145381
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { size: 12, className: "text-[#12B76A]" }),
145382
+ " Copied"
145383
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
145384
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { size: 12 }),
145385
+ " Copy content"
145386
+ ] })
145387
+ }
145388
+ ) }),
145389
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-[#667085] mt-1.5", children: autocopiedOnFail ? "Content saved to clipboard. Paste manually or re-select text to try again." : `${modificationReason || "Original text changed"}. Copy content and paste manually, or re-select text.` })
145390
+ ] })
145391
+ ) : (
145392
+ /* Normal action buttons */
145393
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 mt-2", children: [
145394
+ (onReplace || useSessionMode) && /* @__PURE__ */ jsxRuntimeExports.jsx(
145395
+ "button",
145396
+ {
145397
+ type: "button",
145398
+ onClick: handleReplaceWithFeedback,
145399
+ title: replaceTooltip,
145400
+ className: "px-2.5 py-0.5 text-sm font-medium rounded-full border transition-colors text-white bg-[#155EEF] border-[#155EEF] hover:bg-[#1849D6] cursor-pointer",
145401
+ children: "Replace"
145402
+ }
145403
+ ),
145404
+ showInsertButton && /* @__PURE__ */ jsxRuntimeExports.jsx(
145405
+ "button",
145406
+ {
145407
+ type: "button",
145408
+ onClick: handleInsertWithFeedback,
145409
+ title: insertTooltip,
145410
+ className: "px-2.5 py-0.5 text-sm font-medium rounded-full border transition-colors text-[#344054] bg-white border-[#EAECF0] hover:bg-gray-50 cursor-pointer",
145411
+ children: "Insert"
145412
+ }
145413
+ ),
145414
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
145415
+ "button",
145416
+ {
145417
+ type: "button",
145418
+ onClick: handleCopy,
145419
+ title: copiedFeedback ? "Copied!" : "Copy to clipboard",
145420
+ className: "p-1 text-[#667085] hover:text-[#344054] hover:bg-gray-100 rounded transition-colors cursor-pointer",
145421
+ children: copiedFeedback ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { size: 14, className: "text-[#12B76A]" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { size: 14 })
145422
+ }
145423
+ )
145424
+ ] })
145425
+ ) })
144478
145426
  ] })
144479
145427
  ) })
144480
145428
  ) }, message.id)),
@@ -144557,6 +145505,32 @@ function convertSessionHistoryToMessages(sessionState) {
144557
145505
  }
144558
145506
  return messages;
144559
145507
  }
145508
+ const EmptyStatePlaceholder = ({
145509
+ placeholder = "Write your agent definition here or type '/' to insert variables, agents, tools, memory & more",
145510
+ example,
145511
+ isFocused = false
145512
+ }) => {
145513
+ if (isFocused) return null;
145514
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
145515
+ "div",
145516
+ {
145517
+ className: "absolute inset-0 pointer-events-none px-[32px] py-[24px] overflow-hidden",
145518
+ "data-id": "md-editor-empty-state",
145519
+ children: [
145520
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[14px] leading-[20px] text-[#98A2B3] mb-[8px]", children: placeholder }),
145521
+ example && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[14px] leading-[20px] text-[#98A2B3]", children: example })
145522
+ ]
145523
+ }
145524
+ );
145525
+ };
145526
+ const AgentDefinitionExample = () => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
145527
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mb-[14px]", children: "e.g., You are a meeting scheduler agent who coordinate sales meetings by checking team availability, matching prospect needs with appropriate sales specialists, and sending prep materials." }),
145528
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("ul", { className: "list-disc ml-[21px]", children: [
145529
+ /* @__PURE__ */ jsxRuntimeExports.jsx("li", { className: "mb-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "leading-[20px]", children: "Match prospect needs with sales expertise" }) }),
145530
+ /* @__PURE__ */ jsxRuntimeExports.jsx("li", { className: "mb-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "leading-[20px]", children: "Find optimal meeting times across calendars" }) }),
145531
+ /* @__PURE__ */ jsxRuntimeExports.jsx("li", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "leading-[20px]", children: "Distribute meeting agenda and materials" }) })
145532
+ ] })
145533
+ ] });
144560
145534
  function hashString(str) {
144561
145535
  let hash2 = 5381;
144562
145536
  for (let i2 = 0; i2 < str.length; i2++) {
@@ -144766,7 +145740,8 @@ const initialState = {
144766
145740
  modificationReason: "",
144767
145741
  pendingSelection: null,
144768
145742
  showSwitchBanner: false,
144769
- error: null
145743
+ error: null,
145744
+ cursorInsertPosition: null
144770
145745
  };
144771
145746
  function refinementReducer(state, action) {
144772
145747
  switch (action.type) {
@@ -144877,7 +145852,7 @@ function refinementReducer(state, action) {
144877
145852
  }
144878
145853
  case "APPLY_CONTENT": {
144879
145854
  if (!state.session) return state;
144880
- const { appliedContent } = action.payload;
145855
+ const { appliedContent, newFingerprint } = action.payload;
144881
145856
  return {
144882
145857
  ...state,
144883
145858
  status: "applied",
@@ -144885,8 +145860,11 @@ function refinementReducer(state, action) {
144885
145860
  ...state.session,
144886
145861
  appliedContent,
144887
145862
  applyCount: state.session.applyCount + 1,
144888
- workingContent: appliedContent
145863
+ workingContent: appliedContent,
144889
145864
  // For subsequent refinements
145865
+ // Update fingerprint to track the newly applied content's position
145866
+ // This enables subsequent iterations to work on the replaced content
145867
+ fingerprint: newFingerprint || state.session.fingerprint
144890
145868
  },
144891
145869
  isOriginalModified: false,
144892
145870
  modificationReason: ""
@@ -144894,9 +145872,9 @@ function refinementReducer(state, action) {
144894
145872
  }
144895
145873
  case "SELECTION_CHANGED": {
144896
145874
  if (!state.session) return state;
144897
- const { fingerprint } = action.payload;
144898
- const isFullDocument = fingerprint.contextBefore === "" && fingerprint.contextAfter === "";
144899
- const newMode = isFullDocument ? "full-document" : "selection";
145875
+ const { fingerprint, explicitMode } = action.payload;
145876
+ const inferredMode = fingerprint.contextBefore === "" && fingerprint.contextAfter === "" ? "full-document" : "selection";
145877
+ const newMode = explicitMode ?? inferredMode;
144900
145878
  return {
144901
145879
  ...state,
144902
145880
  session: {
@@ -144904,8 +145882,10 @@ function refinementReducer(state, action) {
144904
145882
  mode: newMode,
144905
145883
  fingerprint,
144906
145884
  workingContent: fingerprint.selectedMarkdown,
144907
- // Reset applied content since selection changed
144908
- appliedContent: null
145885
+ // Reset apply state since selection changed -- previous apply context is irrelevant
145886
+ appliedContent: null,
145887
+ applyCount: 0,
145888
+ lastGeneratedContent: null
144909
145889
  },
144910
145890
  // Clear modification state since we have a fresh selection
144911
145891
  isOriginalModified: false,
@@ -144913,7 +145893,8 @@ function refinementReducer(state, action) {
144913
145893
  // Only show switch banner if there was content and this is user-initiated selection change
144914
145894
  // For now, keep it simple - don't show banner, just update context
144915
145895
  pendingSelection: null,
144916
- showSwitchBanner: false
145896
+ showSwitchBanner: false,
145897
+ cursorInsertPosition: null
144917
145898
  };
144918
145899
  }
144919
145900
  case "CONFIRM_SWITCH": {
@@ -144982,6 +145963,11 @@ function refinementReducer(state, action) {
144982
145963
  }
144983
145964
  };
144984
145965
  }
145966
+ case "SET_CURSOR_INSERT_POSITION":
145967
+ return {
145968
+ ...state,
145969
+ cursorInsertPosition: action.payload.position
145970
+ };
144985
145971
  default:
144986
145972
  return state;
144987
145973
  }
@@ -144991,7 +145977,8 @@ function useAIRefinementSession({
144991
145977
  onRefine,
144992
145978
  editorContent,
144993
145979
  promptType,
144994
- agentContext
145980
+ agentContext,
145981
+ onContentApplied
144995
145982
  }) {
144996
145983
  const [state, dispatch] = useReducer(refinementReducer, initialState);
144997
145984
  const hasGeneratedContentRef = useRef(false);
@@ -145010,14 +145997,18 @@ function useAIRefinementSession({
145010
145997
  });
145011
145998
  if (editor) {
145012
145999
  let fingerprint;
145013
- if (range3 && range3.from !== range3.to) {
146000
+ const isSelection = !!range3 && range3.from !== range3.to;
146001
+ if (isSelection) {
145014
146002
  fingerprint = createSelectionFingerprint(editor, range3.from, range3.to);
145015
146003
  } else {
145016
146004
  fingerprint = createFullDocumentFingerprint(editor);
145017
146005
  }
145018
146006
  dispatch({
145019
146007
  type: "SELECTION_CHANGED",
145020
- payload: { fingerprint }
146008
+ payload: {
146009
+ fingerprint,
146010
+ explicitMode: isSelection ? "selection" : "full-document"
146011
+ }
145021
146012
  });
145022
146013
  }
145023
146014
  }, [editor]);
@@ -145027,13 +146018,24 @@ function useAIRefinementSession({
145027
146018
  }, []);
145028
146019
  const startGeneration = useCallback(async (action, instruction) => {
145029
146020
  if (!onRefine || !state.session) return;
145030
- const contextText = state.session.applyCount > 0 ? state.session.appliedContent || state.session.workingContent : state.session.lastGeneratedContent || state.session.workingContent;
146021
+ let contextText;
146022
+ if (state.session.mode === "full-document" && state.session.applyCount > 0) {
146023
+ contextText = editorContent || state.session.appliedContent || state.session.workingContent;
146024
+ } else if (state.session.applyCount > 0) {
146025
+ contextText = state.session.appliedContent || state.session.workingContent;
146026
+ } else {
146027
+ contextText = state.session.lastGeneratedContent || state.session.workingContent;
146028
+ }
146029
+ if (!contextText) {
146030
+ contextText = editorContent;
146031
+ }
145031
146032
  const actionLabels = {
145032
146033
  "improve": "Improve",
145033
146034
  "make-shorter": "Make Shorter",
145034
146035
  "make-longer": "Make Longer",
145035
146036
  "convert-to-yaml": "Convert to YAML",
145036
- "custom": instruction || "Custom"
146037
+ "custom": instruction || "Custom",
146038
+ "generate": "Generate new content"
145037
146039
  };
145038
146040
  const displayMessage = instruction || actionLabels[action] || action;
145039
146041
  const isFirstMessage = state.session.conversationHistory.length === 0;
@@ -145093,7 +146095,7 @@ function useAIRefinementSession({
145093
146095
  "custom": instruction || "Custom"
145094
146096
  };
145095
146097
  const displayMessage = instruction || actionLabels[action] || action;
145096
- const contentForAI = ((_a = state.session.fingerprint) == null ? void 0 : _a.selectedMarkdown) || state.session.workingContent;
146098
+ const contentForAI = ((_a = state.session.fingerprint) == null ? void 0 : _a.selectedMarkdown) || state.session.workingContent || editorContent;
145097
146099
  const quotedText = contentForAI.length > 100 ? `${contentForAI.substring(0, 100)}...` : contentForAI;
145098
146100
  dispatch({
145099
146101
  type: "START_GENERATION",
@@ -145137,11 +146139,13 @@ function useAIRefinementSession({
145137
146139
  if (!editor || !state.session || !state.session.lastGeneratedContent) return;
145138
146140
  const refinedText = state.session.lastGeneratedContent;
145139
146141
  let result;
146142
+ let newFingerprint;
145140
146143
  if (state.session.mode === "full-document") {
145141
146144
  try {
145142
146145
  const parsed = markdownToEditorJson(refinedText);
145143
146146
  editor.commands.setContent(parsed);
145144
146147
  result = { success: true };
146148
+ newFingerprint = createFullDocumentFingerprint(editor);
145145
146149
  } catch (error) {
145146
146150
  result = {
145147
146151
  success: false,
@@ -145161,10 +146165,17 @@ function useAIRefinementSession({
145161
146165
  } else {
145162
146166
  try {
145163
146167
  const parsedContent = markdownToEditorJson(refinedText);
146168
+ const insertionStart = matchedRange.from;
145164
146169
  if (mode === "replace") {
145165
146170
  editor.chain().focus().setTextSelection(matchedRange).deleteSelection().insertContent(parsedContent).run();
146171
+ const newEndPos = editor.state.selection.to;
146172
+ newFingerprint = createSelectionFingerprint(editor, insertionStart, newEndPos);
145166
146173
  } else {
145167
- editor.chain().focus().setTextSelection({ from: matchedRange.to, to: matchedRange.to }).insertContent("\n\n").insertContent(parsedContent).run();
146174
+ const useCursorPos = state.cursorInsertPosition !== null && state.cursorInsertPosition !== matchedRange.to;
146175
+ const insertPos = useCursorPos ? state.cursorInsertPosition : matchedRange.to;
146176
+ editor.chain().focus().setTextSelection({ from: insertPos, to: insertPos }).insertContent("\n\n").insertContent(parsedContent).run();
146177
+ const newEndPos = editor.state.selection.to;
146178
+ newFingerprint = createSelectionFingerprint(editor, insertPos + 2, newEndPos);
145168
146179
  }
145169
146180
  result = { success: true };
145170
146181
  } catch (error) {
@@ -145179,8 +146190,12 @@ function useAIRefinementSession({
145179
146190
  if (result.success) {
145180
146191
  dispatch({
145181
146192
  type: "APPLY_CONTENT",
145182
- payload: { mode, appliedContent: refinedText }
146193
+ payload: { mode, appliedContent: refinedText, newFingerprint }
145183
146194
  });
146195
+ if (onContentApplied && editor) {
146196
+ const fullMarkdown = state.session.mode === "full-document" ? refinedText : editorJsonToMarkdown(editor.getJSON());
146197
+ onContentApplied(fullMarkdown);
146198
+ }
145184
146199
  } else {
145185
146200
  dispatch({
145186
146201
  type: "SET_MODIFIED",
@@ -145190,7 +146205,7 @@ function useAIRefinementSession({
145190
146205
  }
145191
146206
  });
145192
146207
  }
145193
- }, [editor, state.session]);
146208
+ }, [editor, state.session, state.cursorInsertPosition, onContentApplied]);
145194
146209
  const handleSelectionChange = useCallback((from2, to, _text) => {
145195
146210
  if (!editor || !state.session) return;
145196
146211
  if (from2 === to) return;
@@ -145202,7 +146217,7 @@ function useAIRefinementSession({
145202
146217
  }
145203
146218
  dispatch({
145204
146219
  type: "SELECTION_CHANGED",
145205
- payload: { fingerprint: newFingerprint }
146220
+ payload: { fingerprint: newFingerprint, explicitMode: "selection" }
145206
146221
  });
145207
146222
  }, [editor, state.session]);
145208
146223
  const confirmSwitch = useCallback(() => {
@@ -145241,19 +146256,31 @@ function useAIRefinementSession({
145241
146256
  useEffect(() => {
145242
146257
  if (!editor || state.status === "idle") return;
145243
146258
  const handleSelectionUpdate = () => {
146259
+ var _a, _b;
145244
146260
  const { from: from2, to } = editor.state.selection;
145245
146261
  const hasSelection2 = from2 !== to;
145246
- if (!hasSelection2 || !hasGeneratedContentRef.current) {
145247
- return;
146262
+ if (hasSelection2) {
146263
+ if (hasGeneratedContentRef.current) {
146264
+ const selectedText = editor.state.doc.textBetween(from2, to, " ", "\n");
146265
+ handleSelectionChange(from2, to, selectedText);
146266
+ }
146267
+ if (state.cursorInsertPosition !== null) {
146268
+ dispatch({ type: "SET_CURSOR_INSERT_POSITION", payload: { position: null } });
146269
+ }
146270
+ } else if (((_a = state.session) == null ? void 0 : _a.mode) === "selection" && ((_b = state.session) == null ? void 0 : _b.fingerprint) && hasGeneratedContentRef.current) {
146271
+ const fp = state.session.fingerprint;
146272
+ const isOutside = from2 < fp.originalRange.from || from2 > fp.originalRange.to;
146273
+ const newPos = isOutside ? from2 : null;
146274
+ if (newPos !== state.cursorInsertPosition) {
146275
+ dispatch({ type: "SET_CURSOR_INSERT_POSITION", payload: { position: newPos } });
146276
+ }
145248
146277
  }
145249
- const selectedText = editor.state.doc.textBetween(from2, to, " ", "\n");
145250
- handleSelectionChange(from2, to, selectedText);
145251
146278
  };
145252
146279
  editor.on("selectionUpdate", handleSelectionUpdate);
145253
146280
  return () => {
145254
146281
  editor.off("selectionUpdate", handleSelectionUpdate);
145255
146282
  };
145256
- }, [editor, state.status, handleSelectionChange]);
146283
+ }, [editor, state.status, state.session, state.cursorInsertPosition, handleSelectionChange]);
145257
146284
  const actions = {
145258
146285
  openPanel,
145259
146286
  closePanel,
@@ -145320,7 +146347,12 @@ const MDEditor = forwardRef(
145320
146347
  onFocus,
145321
146348
  onBlur,
145322
146349
  onLoadSuggestions,
145323
- suggestionsLoading: propSuggestionsLoading = false
146350
+ suggestionsLoading: propSuggestionsLoading = false,
146351
+ // Empty state props
146352
+ emptyStatePlaceholder,
146353
+ emptyStateExample,
146354
+ showDesignWithAI = false,
146355
+ onDesignWithAI
145324
146356
  } = props;
145325
146357
  const mergedSlashConfig = { ...DEFAULT_SLASH_COMMAND_CONFIG, ...slashCommandConfig };
145326
146358
  const mergedAIConfig = { ...DEFAULT_AI_CONFIG, ...aiConfig };
@@ -145328,13 +146360,16 @@ const MDEditor = forwardRef(
145328
146360
  const lastEmittedMarkdownRef = useRef("");
145329
146361
  const isInternalUpdateRef = useRef(false);
145330
146362
  const editorContainerRef = useRef(null);
146363
+ const skipRawSyncRef = useRef(false);
146364
+ const skipEditorSyncRef = useRef(false);
145331
146365
  const [asyncSuggestions, setAsyncSuggestions] = useState(null);
145332
146366
  const [suggestionsLoading, setSuggestionsLoading] = useState(false);
145333
146367
  const [variableMenuOpen, setVariableMenuOpen] = useState(false);
145334
146368
  const [variableMenuPosition, setVariableMenuPosition] = useState({ top: 0, left: 0 });
145335
146369
  const [variableMenuQuery, setVariableMenuQuery] = useState("");
145336
- const [editingVariableChip, setEditingVariableChip] = useState(null);
145337
146370
  const variableTriggerPosRef = useRef(null);
146371
+ const hasVariableSuggestionsRef = useRef(false);
146372
+ const variableMenuOpenRef = useRef(false);
145338
146373
  const [editorMode, setEditorMode] = useState("editor");
145339
146374
  const [rawMarkdown, setRawMarkdown] = useState("");
145340
146375
  const isRawMode = editorMode === "preview";
@@ -145378,12 +146413,7 @@ const MDEditor = forwardRef(
145378
146413
  contentVariables: mergedContentVariables,
145379
146414
  loading: finalSuggestionsLoading
145380
146415
  };
145381
- console.log("MDEditor render: suggestionsRef updated with:", {
145382
- agentsCount: mergedAgents.length,
145383
- toolsCount: mergedTools.length,
145384
- knowledgeCount: mergedKnowledge.length,
145385
- hasAsyncSuggestions: !!asyncSuggestions
145386
- });
146416
+ hasVariableSuggestionsRef.current = mergedEnvVariables.length > 0 || mergedMemoryVariables.length > 0 || mergedSystemVariables.length > 0 || mergedContentVariables.length > 0;
145387
146417
  const defaultCategories = useMemo(() => {
145388
146418
  const categories = [];
145389
146419
  if (mergedAgents.length > 0) {
@@ -145448,21 +146478,6 @@ const MDEditor = forwardRef(
145448
146478
  (variable, triggerPos) => {
145449
146479
  if (!editorRef.current) return;
145450
146480
  const editor2 = editorRef.current;
145451
- if (editingVariableChip) {
145452
- const { position, nodeSize: nodeSize2 } = editingVariableChip;
145453
- editor2.chain().focus().deleteRange({ from: position, to: position + nodeSize2 }).insertContentAt(position, {
145454
- type: "variableChip",
145455
- attrs: {
145456
- variableType: variable.type,
145457
- path: variable.path,
145458
- displayName: variable.name
145459
- }
145460
- }).run();
145461
- setEditingVariableChip(null);
145462
- setVariableMenuOpen(false);
145463
- setVariableMenuQuery("");
145464
- return;
145465
- }
145466
146481
  const deleteFrom = triggerPos ?? variableTriggerPosRef.current;
145467
146482
  if (deleteFrom !== null) {
145468
146483
  const { from: from2 } = editor2.state.selection;
@@ -145475,6 +146490,10 @@ const MDEditor = forwardRef(
145475
146490
  displayName: variable.name
145476
146491
  }
145477
146492
  }).insertContent(" ").run();
146493
+ const posAfter = editor2.state.selection.from;
146494
+ if (posAfter + 2 <= editor2.state.doc.content.size && editor2.state.doc.textBetween(posAfter, posAfter + 2) === "}}") {
146495
+ editor2.chain().focus().deleteRange({ from: posAfter, to: posAfter + 2 }).run();
146496
+ }
145478
146497
  } else {
145479
146498
  editor2.chain().focus().insertContent({
145480
146499
  type: "variableChip",
@@ -145489,7 +146508,19 @@ const MDEditor = forwardRef(
145489
146508
  setVariableMenuQuery("");
145490
146509
  variableTriggerPosRef.current = null;
145491
146510
  },
145492
- [editingVariableChip]
146511
+ []
146512
+ );
146513
+ const handleVariableQueryChange = useCallback(
146514
+ (newQuery) => {
146515
+ setVariableMenuQuery(newQuery);
146516
+ if (!editorRef.current || variableTriggerPosRef.current === null) return;
146517
+ const editor2 = editorRef.current;
146518
+ const triggerPos = variableTriggerPosRef.current;
146519
+ const insertFrom = triggerPos + 2;
146520
+ const { from: from2 } = editor2.state.selection;
146521
+ editor2.chain().focus().deleteRange({ from: insertFrom, to: from2 }).insertContentAt(insertFrom, newQuery).run();
146522
+ },
146523
+ []
145493
146524
  );
145494
146525
  const insertMention = useCallback(
145495
146526
  (mention) => {
@@ -145524,14 +146555,23 @@ const MDEditor = forwardRef(
145524
146555
  const json = editorRef.current.getJSON();
145525
146556
  const markdown = editorJsonToMarkdown(json);
145526
146557
  setRawMarkdown(markdown);
146558
+ lastEmittedMarkdownRef.current = markdown;
146559
+ skipRawSyncRef.current = true;
145527
146560
  }
145528
146561
  if (currentMode === "preview" && newMode === "editor") {
145529
146562
  const parsedContent = markdownToEditorJson(rawMarkdown);
146563
+ isInternalUpdateRef.current = true;
145530
146564
  editorRef.current.commands.setContent(parsedContent);
145531
146565
  lastEmittedMarkdownRef.current = rawMarkdown;
146566
+ skipEditorSyncRef.current = true;
146567
+ onMarkdownChange == null ? void 0 : onMarkdownChange(rawMarkdown);
146568
+ if (onChange) {
146569
+ const doc2 = editorJsonToDocument(parsedContent);
146570
+ onChange(doc2, rawMarkdown);
146571
+ }
145532
146572
  }
145533
146573
  setEditorMode(newMode);
145534
- }, [editorMode, rawMarkdown]);
146574
+ }, [editorMode, rawMarkdown, onChange, onMarkdownChange]);
145535
146575
  const toggleRawMode = useCallback(() => {
145536
146576
  handleModeChange(isRawMode ? "editor" : "preview");
145537
146577
  }, [handleModeChange, isRawMode]);
@@ -145546,13 +146586,17 @@ const MDEditor = forwardRef(
145546
146586
  dropcursor: false
145547
146587
  }),
145548
146588
  Placeholder.configure({
145549
- placeholder: ({ node }) => {
146589
+ placeholder: ({ node, editor: placeholderEditor }) => {
146590
+ if (emptyStatePlaceholder && placeholderEditor.isEmpty) {
146591
+ return "";
146592
+ }
145550
146593
  if (node.type.name === "heading") {
145551
146594
  const level = node.attrs["level"];
145552
146595
  return `Heading ${level}`;
145553
146596
  }
145554
146597
  if (node.type.name === "paragraph") {
145555
- return placeholder;
146598
+ const focusPlaceholder = "Type here or '/' to insert variables, agents, tools, memory & more";
146599
+ return placeholderEditor.isEmpty ? placeholder : focusPlaceholder;
145556
146600
  }
145557
146601
  return "";
145558
146602
  },
@@ -145622,7 +146666,7 @@ const MDEditor = forwardRef(
145622
146666
  );
145623
146667
  }
145624
146668
  return exts;
145625
- }, [mergedFeatures, placeholder, defaultCategories, handleSlashCommandSelect, mergedSlashConfig.highlightMentions]);
146669
+ }, [mergedFeatures, placeholder, emptyStatePlaceholder, defaultCategories, handleSlashCommandSelect, mergedSlashConfig.highlightMentions]);
145626
146670
  const editorRef = useRef(null);
145627
146671
  const editor = useEditor({
145628
146672
  extensions,
@@ -145656,12 +146700,24 @@ const MDEditor = forwardRef(
145656
146700
  editorRef.current = editor;
145657
146701
  }, [editor]);
145658
146702
  const editorContent = editor ? editorJsonToMarkdown(editor.getJSON()) : "";
146703
+ const handleAIContentApplied = useCallback((markdown) => {
146704
+ lastEmittedMarkdownRef.current = markdown;
146705
+ if (onMarkdownChange) {
146706
+ onMarkdownChange(markdown);
146707
+ }
146708
+ if (onChange) {
146709
+ const json = markdownToEditorJson(markdown);
146710
+ const doc2 = editorJsonToDocument(json);
146711
+ onChange(doc2, markdown);
146712
+ }
146713
+ }, [onMarkdownChange, onChange]);
145659
146714
  const { state: aiSessionState, actions: aiSessionActions, isOpen: aiPanelOpen } = useAIRefinementSession({
145660
146715
  editor,
145661
146716
  onRefine: onAIRefine,
145662
146717
  editorContent,
145663
146718
  promptType: props.promptType,
145664
- agentContext: props.agentContext
146719
+ agentContext: props.agentContext,
146720
+ onContentApplied: handleAIContentApplied
145665
146721
  });
145666
146722
  const openAIRefine = useCallback(
145667
146723
  (_type = "selection") => {
@@ -145688,6 +146744,22 @@ const MDEditor = forwardRef(
145688
146744
  // autoGenerate
145689
146745
  );
145690
146746
  }, [aiSessionActions]);
146747
+ const handleDesignWithAI = useCallback(() => {
146748
+ aiSessionActions.openPanel(
146749
+ "generate",
146750
+ "",
146751
+ // Empty text since we're generating from scratch
146752
+ void 0,
146753
+ // No selection range
146754
+ void 0,
146755
+ // No custom prompt - AI will use context
146756
+ true
146757
+ // autoGenerate - start generation immediately
146758
+ );
146759
+ if (onDesignWithAI) {
146760
+ onDesignWithAI();
146761
+ }
146762
+ }, [aiSessionActions, onDesignWithAI]);
145691
146763
  const handleCloseAIPanel = useCallback(() => {
145692
146764
  if (editorRef.current) {
145693
146765
  editorRef.current.setEditable(!readOnly);
@@ -145722,11 +146794,27 @@ const MDEditor = forwardRef(
145722
146794
  from2
145723
146795
  );
145724
146796
  if (textAfterTrigger.includes("}}")) {
146797
+ const pathRaw = textAfterTrigger.split("}}")[0].trim();
146798
+ if (pathRaw) {
146799
+ const varType = inferVariableType(pathRaw);
146800
+ const cleanPath = removeTypePrefix(pathRaw);
146801
+ const displayName = cleanPath.split(".").pop() || cleanPath;
146802
+ editor.chain().focus().deleteRange({ from: triggerPos, to: from2 }).insertContent({
146803
+ type: "variableChip",
146804
+ attrs: {
146805
+ variableType: varType,
146806
+ path: cleanPath,
146807
+ displayName
146808
+ }
146809
+ }).insertContent(" ").run();
146810
+ }
145725
146811
  setVariableMenuOpen(false);
145726
146812
  variableTriggerPosRef.current = null;
145727
146813
  return;
145728
146814
  }
145729
146815
  setVariableMenuQuery(textAfterTrigger);
146816
+ const coords = editor.view.coordsAtPos(from2);
146817
+ setVariableMenuPosition({ top: coords.bottom + 8, left: coords.left });
145730
146818
  };
145731
146819
  const editorElement = editor.view.dom;
145732
146820
  editorElement.addEventListener("keydown", handleKeyDown2);
@@ -145736,12 +146824,36 @@ const MDEditor = forwardRef(
145736
146824
  editorElement.removeEventListener("input", handleInput);
145737
146825
  };
145738
146826
  }, [editor, mergedFeatures.variableChips, variableMenuOpen]);
146827
+ useEffect(() => {
146828
+ variableMenuOpenRef.current = variableMenuOpen;
146829
+ }, [variableMenuOpen]);
146830
+ useEffect(() => {
146831
+ if (!editor || !mergedFeatures.variableChips) return;
146832
+ const detectVariableContext = () => {
146833
+ if (variableMenuOpenRef.current) return;
146834
+ if (!hasVariableSuggestionsRef.current) return;
146835
+ const { from: from2 } = editor.state.selection;
146836
+ const context = getVariableContextAtPosition(editor, from2);
146837
+ if (context) {
146838
+ variableTriggerPosRef.current = context.triggerFrom;
146839
+ setVariableMenuQuery(context.query);
146840
+ const coords = editor.view.coordsAtPos(from2);
146841
+ setVariableMenuPosition({ top: coords.bottom + 8, left: coords.left });
146842
+ setVariableMenuOpen(true);
146843
+ }
146844
+ };
146845
+ editor.on("focus", detectVariableContext);
146846
+ editor.on("selectionUpdate", detectVariableContext);
146847
+ return () => {
146848
+ editor.off("focus", detectVariableContext);
146849
+ editor.off("selectionUpdate", detectVariableContext);
146850
+ };
146851
+ }, [editor, mergedFeatures.variableChips]);
145739
146852
  useEffect(() => {
145740
146853
  if (!variableMenuOpen) return;
145741
146854
  const handleKeyDown2 = (event) => {
145742
146855
  if (event.key === "Escape") {
145743
146856
  setVariableMenuOpen(false);
145744
- setEditingVariableChip(null);
145745
146857
  variableTriggerPosRef.current = null;
145746
146858
  editor == null ? void 0 : editor.chain().focus().run();
145747
146859
  }
@@ -145754,19 +146866,11 @@ const MDEditor = forwardRef(
145754
146866
  const handleVariableChipEdit = (event) => {
145755
146867
  const customEvent = event;
145756
146868
  const { variableType, path, position, nodeSize: nodeSize2 } = customEvent.detail;
145757
- const coords = editor.view.coordsAtPos(position);
145758
- setEditingVariableChip({
145759
- position,
145760
- nodeSize: nodeSize2,
145761
- variableType,
145762
- path
145763
- });
145764
- setVariableMenuPosition({
145765
- top: coords.bottom + 8,
145766
- left: coords.left
145767
- });
145768
- setVariableMenuQuery("");
145769
- setVariableMenuOpen(true);
146869
+ const innerPath = variableType === "system" || variableType === "custom" ? path : `${variableType}.${path}`;
146870
+ const fullText = `{{${innerPath}}}`;
146871
+ editor.chain().focus().deleteRange({ from: position, to: position + nodeSize2 }).insertContentAt(position, fullText).run();
146872
+ const cursorPos = position + 2 + innerPath.length;
146873
+ editor.chain().focus().setTextSelection(cursorPos).run();
145770
146874
  };
145771
146875
  const editorElement = editor.view.dom;
145772
146876
  editorElement.addEventListener("variable-chip-edit", handleVariableChipEdit);
@@ -145775,6 +146879,10 @@ const MDEditor = forwardRef(
145775
146879
  };
145776
146880
  }, [editor]);
145777
146881
  useEffect(() => {
146882
+ if (skipEditorSyncRef.current) {
146883
+ skipEditorSyncRef.current = false;
146884
+ return;
146885
+ }
145778
146886
  if (!editor || isInternalUpdateRef.current) {
145779
146887
  isInternalUpdateRef.current = false;
145780
146888
  return;
@@ -145806,6 +146914,10 @@ const MDEditor = forwardRef(
145806
146914
  return () => clearTimeout(timer);
145807
146915
  }, [rawMarkdown, isRawMode, onMarkdownChange, onChange]);
145808
146916
  useEffect(() => {
146917
+ if (skipRawSyncRef.current) {
146918
+ skipRawSyncRef.current = false;
146919
+ return;
146920
+ }
145809
146921
  if (isRawMode && markdownValue !== void 0 && markdownValue !== lastEmittedMarkdownRef.current) {
145810
146922
  setRawMarkdown(markdownValue);
145811
146923
  }
@@ -145946,6 +147058,13 @@ const MDEditor = forwardRef(
145946
147058
  editor,
145947
147059
  className: "k-md-editor__content w-full h-full"
145948
147060
  }
147061
+ ),
147062
+ (editor == null ? void 0 : editor.isEmpty) && emptyStatePlaceholder && /* @__PURE__ */ jsxRuntimeExports.jsx(
147063
+ EmptyStatePlaceholder,
147064
+ {
147065
+ placeholder: emptyStatePlaceholder,
147066
+ example: emptyStateExample
147067
+ }
145949
147068
  )
145950
147069
  ] })
145951
147070
  ) }),
@@ -145954,20 +147073,18 @@ const MDEditor = forwardRef(
145954
147073
  {
145955
147074
  position: variableMenuPosition,
145956
147075
  query: variableMenuQuery,
145957
- onQueryChange: setVariableMenuQuery,
147076
+ onQueryChange: handleVariableQueryChange,
145958
147077
  onSelect: (variable) => insertVariable(variable),
145959
147078
  onClose: () => {
145960
147079
  setVariableMenuOpen(false);
145961
147080
  setVariableMenuQuery("");
145962
- setEditingVariableChip(null);
145963
147081
  variableTriggerPosRef.current = null;
145964
147082
  },
145965
147083
  envVariables: mergedEnvVariables,
145966
147084
  memoryVariables: mergedMemoryVariables,
145967
147085
  systemVariables: mergedSystemVariables,
145968
147086
  contentVariables: mergedContentVariables,
145969
- editorControlled: !editingVariableChip,
145970
- isEditMode: !!editingVariableChip
147087
+ editorControlled: true
145971
147088
  }
145972
147089
  )
145973
147090
  ] }),
@@ -145981,7 +147098,9 @@ const MDEditor = forwardRef(
145981
147098
  onAIAction: isAIEnabled ? handleAIToolbarAction : void 0,
145982
147099
  theme: theme === "dark" || theme.includes("dark") ? "dark" : "light",
145983
147100
  disabled: readOnly,
145984
- containerRef: editorContainerRef
147101
+ containerRef: editorContainerRef,
147102
+ showDesignWithAI: showDesignWithAI && (editor == null ? void 0 : editor.isEmpty),
147103
+ onDesignWithAI: isAIEnabled ? handleDesignWithAI : onDesignWithAI
145985
147104
  }
145986
147105
  )
145987
147106
  ] }),
@@ -149524,6 +150643,7 @@ export {
149524
150643
  AIRefineDropdown,
149525
150644
  AIRefineExtension,
149526
150645
  AIRefinePanel,
150646
+ AgentDefinitionExample,
149527
150647
  AgentListView,
149528
150648
  AnalyticsChart,
149529
150649
  AnalyticsTable,
@@ -149549,6 +150669,7 @@ export {
149549
150669
  DetailPage,
149550
150670
  DetailPageService,
149551
150671
  EmptyState,
150672
+ EmptyStatePlaceholder,
149552
150673
  EndpointsConfigService,
149553
150674
  EnvironmentContext,
149554
150675
  EnvironmentProvider,