@mastra/playground-ui 51.2.0 → 51.3.0-alpha.1

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 (160) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/LICENSE.md +6 -4
  3. package/dist/components/DataCodeSection.cjs.js +1 -1
  4. package/dist/components/DataCodeSection.es.js +1 -1
  5. package/dist/components/DataPanel.cjs.js +1 -1
  6. package/dist/components/DataPanel.es.js +1 -1
  7. package/dist/components/FormFieldBlocks.cjs.js +1 -1
  8. package/dist/components/FormFieldBlocks.es.js +1 -1
  9. package/dist/components/ListSearch.cjs.js +13 -2
  10. package/dist/components/ListSearch.cjs.js.map +1 -1
  11. package/dist/components/ListSearch.es.js +14 -3
  12. package/dist/components/ListSearch.es.js.map +1 -1
  13. package/dist/components/LogsDataList.cjs.js +0 -1
  14. package/dist/components/LogsDataList.cjs.js.map +1 -1
  15. package/dist/components/LogsDataList.es.js +0 -1
  16. package/dist/components/LogsDataList.es.js.map +1 -1
  17. package/dist/components/MarkdownRenderer.cjs.js +3 -65
  18. package/dist/components/MarkdownRenderer.cjs.js.map +1 -1
  19. package/dist/components/MarkdownRenderer.es.js +1 -67
  20. package/dist/components/MarkdownRenderer.es.js.map +1 -1
  21. package/dist/components/ai/message-reveal.cjs.js +50 -0
  22. package/dist/components/ai/message-reveal.cjs.js.map +1 -0
  23. package/dist/components/ai/message-reveal.d.ts +2 -0
  24. package/dist/components/ai/message-reveal.es.js +44 -0
  25. package/dist/components/ai/message-reveal.es.js.map +1 -0
  26. package/dist/{data-code-section-sK4cZuA-.cjs → data-code-section-C3ZRkULz.cjs} +2 -2
  27. package/dist/{data-code-section-sK4cZuA-.cjs.map → data-code-section-C3ZRkULz.cjs.map} +1 -1
  28. package/dist/{data-code-section-g1jBtzwR.js → data-code-section-CSt_ZuUP.js} +2 -2
  29. package/dist/{data-code-section-g1jBtzwR.js.map → data-code-section-CSt_ZuUP.js.map} +1 -1
  30. package/dist/{data-panel-B3AECYLW.cjs → data-panel-DHNc5Y4L.cjs} +2 -2
  31. package/dist/{data-panel-B3AECYLW.cjs.map → data-panel-DHNc5Y4L.cjs.map} +1 -1
  32. package/dist/{data-panel-B527Q_Zh.js → data-panel-DJpAfEsG.js} +2 -2
  33. package/dist/{data-panel-B527Q_Zh.js.map → data-panel-DJpAfEsG.js.map} +1 -1
  34. package/dist/domains/traces/components/span-data-panel-view.cjs.js +1 -1
  35. package/dist/domains/traces/components/span-data-panel-view.es.js +1 -1
  36. package/dist/domains/traces/components/timeline-name-col.cjs.js +1 -1
  37. package/dist/domains/traces/components/timeline-name-col.cjs.js.map +1 -1
  38. package/dist/domains/traces/components/timeline-name-col.es.js +1 -1
  39. package/dist/domains/traces/components/timeline-name-col.es.js.map +1 -1
  40. package/dist/domains/traces/components/trace-data-panel-view.cjs.js +44 -9
  41. package/dist/domains/traces/components/trace-data-panel-view.cjs.js.map +1 -1
  42. package/dist/domains/traces/components/trace-data-panel-view.es.js +45 -10
  43. package/dist/domains/traces/components/trace-data-panel-view.es.js.map +1 -1
  44. package/dist/domains/traces/components/trace-timeline.cjs.js +18 -14
  45. package/dist/domains/traces/components/trace-timeline.cjs.js.map +1 -1
  46. package/dist/domains/traces/components/trace-timeline.es.js +18 -14
  47. package/dist/domains/traces/components/trace-timeline.es.js.map +1 -1
  48. package/dist/domains/traces/hooks/use-branch.cjs.js +4 -0
  49. package/dist/domains/traces/hooks/use-branch.cjs.js.map +1 -1
  50. package/dist/domains/traces/hooks/use-branch.es.js +4 -0
  51. package/dist/domains/traces/hooks/use-branch.es.js.map +1 -1
  52. package/dist/domains/traces/hooks/use-trace-light-spans.cjs.js +4 -0
  53. package/dist/domains/traces/hooks/use-trace-light-spans.cjs.js.map +1 -1
  54. package/dist/domains/traces/hooks/use-trace-light-spans.es.js +4 -0
  55. package/dist/domains/traces/hooks/use-trace-light-spans.es.js.map +1 -1
  56. package/dist/domains/traces/hooks/use-trace-or-branch-spans.cjs.js +2 -2
  57. package/dist/domains/traces/hooks/use-trace-or-branch-spans.cjs.js.map +1 -1
  58. package/dist/domains/traces/hooks/use-trace-or-branch-spans.es.js +2 -2
  59. package/dist/domains/traces/hooks/use-trace-or-branch-spans.es.js.map +1 -1
  60. package/dist/domains/traces/hooks/use-trace-search.cjs.js +21 -0
  61. package/dist/domains/traces/hooks/use-trace-search.cjs.js.map +1 -0
  62. package/dist/domains/traces/hooks/use-trace-search.d.ts +2 -0
  63. package/dist/domains/traces/hooks/use-trace-search.es.js +17 -0
  64. package/dist/domains/traces/hooks/use-trace-search.es.js.map +1 -0
  65. package/dist/domains/traces/hooks/use-trace-spans.cjs.js +11 -1
  66. package/dist/domains/traces/hooks/use-trace-spans.cjs.js.map +1 -1
  67. package/dist/domains/traces/hooks/use-trace-spans.es.js +11 -1
  68. package/dist/domains/traces/hooks/use-trace-spans.es.js.map +1 -1
  69. package/dist/domains/traces/hooks.cjs.js +2 -0
  70. package/dist/domains/traces/hooks.cjs.js.map +1 -1
  71. package/dist/domains/traces/hooks.es.js +1 -0
  72. package/dist/domains/traces/hooks.es.js.map +1 -1
  73. package/dist/domains/traces/types.cjs.js.map +1 -1
  74. package/dist/domains/traces/types.es.js.map +1 -1
  75. package/dist/domains/traces/utils/filter-spans-keeping-ancestors.cjs.js +47 -0
  76. package/dist/domains/traces/utils/filter-spans-keeping-ancestors.cjs.js.map +1 -0
  77. package/dist/domains/traces/utils/filter-spans-keeping-ancestors.d.ts +2 -0
  78. package/dist/domains/traces/utils/filter-spans-keeping-ancestors.es.js +43 -0
  79. package/dist/domains/traces/utils/filter-spans-keeping-ancestors.es.js.map +1 -0
  80. package/dist/domains/traces/utils/flatten-to-search-text.cjs.js +78 -0
  81. package/dist/domains/traces/utils/flatten-to-search-text.cjs.js.map +1 -0
  82. package/dist/domains/traces/utils/flatten-to-search-text.d.ts +2 -0
  83. package/dist/domains/traces/utils/flatten-to-search-text.es.js +74 -0
  84. package/dist/domains/traces/utils/flatten-to-search-text.es.js.map +1 -0
  85. package/dist/domains/traces/utils/to-searchable-spans.cjs.js +22 -0
  86. package/dist/domains/traces/utils/to-searchable-spans.cjs.js.map +1 -0
  87. package/dist/domains/traces/utils/to-searchable-spans.d.ts +2 -0
  88. package/dist/domains/traces/utils/to-searchable-spans.es.js +17 -0
  89. package/dist/domains/traces/utils/to-searchable-spans.es.js.map +1 -0
  90. package/dist/domains/traces/utils.cjs.js +7 -0
  91. package/dist/domains/traces/utils.cjs.js.map +1 -1
  92. package/dist/domains/traces/utils.es.js +3 -0
  93. package/dist/domains/traces/utils.es.js.map +1 -1
  94. package/dist/domains/traces.cjs.js +9 -0
  95. package/dist/domains/traces.cjs.js.map +1 -1
  96. package/dist/domains/traces.es.js +4 -0
  97. package/dist/domains/traces.es.js.map +1 -1
  98. package/dist/ee/topics/components/topic-trace-details-panel.cjs.js +2 -2
  99. package/dist/ee/topics/components/topic-trace-details-panel.cjs.js.map +1 -1
  100. package/dist/ee/topics/components/topic-trace-details-panel.es.js +2 -2
  101. package/dist/ee/topics/components/topic-trace-details-panel.es.js.map +1 -1
  102. package/dist/hooks/use-text-highlight.cjs.js +68 -0
  103. package/dist/hooks/use-text-highlight.cjs.js.map +1 -0
  104. package/dist/hooks/use-text-highlight.d.ts +2 -0
  105. package/dist/hooks/use-text-highlight.es.js +64 -0
  106. package/dist/hooks/use-text-highlight.es.js.map +1 -0
  107. package/dist/{search-field-block-BqRM53jf.cjs → search-field-block-CjCIzUhN.cjs} +8 -3
  108. package/dist/search-field-block-CjCIzUhN.cjs.map +1 -0
  109. package/dist/{search-field-block-CgrC6f9t.js → search-field-block-DoNywsJC.js} +8 -3
  110. package/dist/search-field-block-DoNywsJC.js.map +1 -0
  111. package/dist/src/domains/traces/components/trace-data-panel-view.d.ts +2 -2
  112. package/dist/src/domains/traces/components/trace-timeline.d.ts +4 -2
  113. package/dist/src/domains/traces/hooks/index.d.ts +1 -0
  114. package/dist/src/domains/traces/hooks/use-branch.d.ts +2 -2
  115. package/dist/src/domains/traces/hooks/use-trace-light-spans.d.ts +2 -2
  116. package/dist/src/domains/traces/hooks/use-trace-or-branch-spans.d.ts +5 -2
  117. package/dist/src/domains/traces/hooks/use-trace-search.d.ts +27 -0
  118. package/dist/src/domains/traces/hooks/use-trace-spans.d.ts +11 -2
  119. package/dist/src/domains/traces/types.d.ts +16 -0
  120. package/dist/src/domains/traces/utils/filter-spans-keeping-ancestors.d.ts +19 -0
  121. package/dist/src/domains/traces/utils/flatten-to-search-text.d.ts +25 -0
  122. package/dist/src/domains/traces/utils/index.d.ts +3 -0
  123. package/dist/src/domains/traces/utils/to-searchable-spans.d.ts +41 -0
  124. package/dist/src/ds/components/Arrival/arrival.stories.d.ts +6 -0
  125. package/dist/src/ds/components/Card/card.stories.d.ts +8 -0
  126. package/dist/src/ds/components/Columns/columns.stories.d.ts +7 -0
  127. package/dist/src/ds/components/DataDetailsPanel/data-details-panel.stories.d.ts +9 -0
  128. package/dist/src/ds/components/DataFilter/select-data-filter.stories.d.ts +8 -0
  129. package/dist/src/ds/components/DateRangeTimeline/date-range-timeline.stories.d.ts +8 -0
  130. package/dist/src/ds/components/ErrorState/error-state.stories.d.ts +7 -0
  131. package/dist/src/ds/components/FormFieldBlocks/fields/search-field-block.d.ts +4 -1
  132. package/dist/src/ds/components/ListSearch/list-search.d.ts +6 -1
  133. package/dist/src/ds/components/ListSearch/list-search.stories.d.ts +7 -0
  134. package/dist/src/ds/components/LogsDataList/logs-data-list.stories.d.ts +8 -0
  135. package/dist/src/ds/components/MessageScroller/message-scroller.stories.d.ts +7 -0
  136. package/dist/src/ds/components/MetricsLineChart/metrics-line-chart.stories.d.ts +8 -0
  137. package/dist/src/ds/components/PageHeader/page-header.stories.d.ts +8 -0
  138. package/dist/src/ds/components/PageLayout/page-layout.stories.d.ts +8 -0
  139. package/dist/src/ds/components/PendingIndicator/pending-indicator.stories.d.ts +7 -0
  140. package/dist/src/ds/components/PermissionDenied/permission-denied.stories.d.ts +8 -0
  141. package/dist/src/ds/components/PrevNextNav/prev-next-nav.stories.d.ts +8 -0
  142. package/dist/src/ds/components/SessionExpired/session-expired.stories.d.ts +7 -0
  143. package/dist/src/ds/components/Shimmer/shimmer.stories.d.ts +7 -0
  144. package/dist/src/ds/components/StatusBadge/status-badge.stories.d.ts +8 -0
  145. package/dist/src/ds/components/ThreadList/thread-list.stories.d.ts +8 -0
  146. package/dist/src/ds/components/ThreadRail/thread-rail.stories.d.ts +7 -0
  147. package/dist/src/ds/components/TokenBudget/token-budget.stories.d.ts +8 -0
  148. package/dist/src/ds/components/ai/message-reveal/index.d.ts +1 -0
  149. package/dist/src/ds/components/ai/message-reveal/message-reveal.d.ts +22 -0
  150. package/dist/src/hooks/use-text-highlight.d.ts +18 -0
  151. package/dist/src/test/highlight-api.d.ts +28 -0
  152. package/dist/style.css +80 -0
  153. package/dist/use-reveal-Sa456jZb.cjs +70 -0
  154. package/dist/use-reveal-Sa456jZb.cjs.map +1 -0
  155. package/dist/use-reveal-d77hxHz9.js +68 -0
  156. package/dist/use-reveal-d77hxHz9.js.map +1 -0
  157. package/dist/use-text-highlight.css +8 -0
  158. package/package.json +8 -8
  159. package/dist/search-field-block-BqRM53jf.cjs.map +0 -1
  160. package/dist/search-field-block-CgrC6f9t.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"use-trace-light-spans.cjs.js","sources":["../../../../src/domains/traces/hooks/use-trace-light-spans.ts"],"sourcesContent":["import type { LightSpanRecord } from '@mastra/core/storage';\nimport { useMastraClient } from '@mastra/react';\nimport { useQuery } from '@tanstack/react-query';\nimport type { UseQueryResult } from '@tanstack/react-query';\n\nconst IMMUTABLE_CACHE_TIME = 1000 * 60 * 60 * 24 * 30; // 30 days, massive cache, span data is immutable\n\nexport function useTraceLightSpans(\n traceId: string | null | undefined,\n): UseQueryResult<{ traceId: string; spans: LightSpanRecord[] } | null> {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['trace-light-spans', traceId],\n queryFn: async () => {\n if (!traceId) {\n throw new Error('Trace ID is required');\n }\n const res = await client.getTraceLight(traceId);\n return res;\n },\n enabled: !!traceId,\n staleTime: query => {\n const data = query.state.data;\n\n const isFinished = data?.spans.every(d => Boolean(d.endedAt));\n\n if (isFinished) {\n return IMMUTABLE_CACHE_TIME;\n }\n\n return 0;\n },\n });\n}\n"],"names":["useMastraClient","useQuery"],"mappings":";;;;;;;AAKA,MAAM,oBAAA,GAAuB,GAAA,GAAO,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,EAAA;AAE5C,SAAS,mBACd,OAAA,EACsE;AACtE,EAAA,MAAM,SAASA,qBAAA,EAAgB;AAE/B,EAAA,OAAOC,mBAAA,CAAS;AAAA,IACd,QAAA,EAAU,CAAC,mBAAA,EAAqB,OAAO,CAAA;AAAA,IACvC,SAAS,YAAY;AACnB,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,MAAM,IAAI,MAAM,sBAAsB,CAAA;AAAA,MACxC;AACA,MAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,aAAA,CAAc,OAAO,CAAA;AAC9C,MAAA,OAAO,GAAA;AAAA,IACT,CAAA;AAAA,IACA,OAAA,EAAS,CAAC,CAAC,OAAA;AAAA,IACX,WAAW,CAAA,KAAA,KAAS;AAClB,MAAA,MAAM,IAAA,GAAO,MAAM,KAAA,CAAM,IAAA;AAEzB,MAAA,MAAM,UAAA,GAAa,MAAM,KAAA,CAAM,KAAA,CAAM,OAAK,OAAA,CAAQ,CAAA,CAAE,OAAO,CAAC,CAAA;AAE5D,MAAA,IAAI,UAAA,EAAY;AACd,QAAA,OAAO,oBAAA;AAAA,MACT;AAEA,MAAA,OAAO,CAAA;AAAA,IACT;AAAA,GACD,CAAA;AACH;;;;"}
1
+ {"version":3,"file":"use-trace-light-spans.cjs.js","sources":["../../../../src/domains/traces/hooks/use-trace-light-spans.ts"],"sourcesContent":["import { useMastraClient } from '@mastra/react';\nimport { useQuery } from '@tanstack/react-query';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport type { SearchableSpan } from '../types';\nimport { selectSearchableSpans } from '../utils';\n\nconst IMMUTABLE_CACHE_TIME = 1000 * 60 * 60 * 24 * 30; // 30 days, massive cache, span data is immutable\n\nexport function useTraceLightSpans(\n traceId: string | null | undefined,\n): UseQueryResult<{ traceId: string; spans: SearchableSpan[] } | null> {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['trace-light-spans', traceId],\n queryFn: async () => {\n if (!traceId) {\n throw new Error('Trace ID is required');\n }\n const res = await client.getTraceLight(traceId);\n return res;\n },\n // Builds each span's search haystack once per fetch, cached with the query.\n select: selectSearchableSpans,\n enabled: !!traceId,\n staleTime: query => {\n const data = query.state.data;\n\n const isFinished = data?.spans.every(d => Boolean(d.endedAt));\n\n if (isFinished) {\n return IMMUTABLE_CACHE_TIME;\n }\n\n return 0;\n },\n });\n}\n"],"names":["useMastraClient","useQuery","selectSearchableSpans"],"mappings":";;;;;;;;;AAMA,MAAM,oBAAA,GAAuB,GAAA,GAAO,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,EAAA;AAE5C,SAAS,mBACd,OAAA,EACqE;AACrE,EAAA,MAAM,SAASA,qBAAA,EAAgB;AAE/B,EAAA,OAAOC,mBAAA,CAAS;AAAA,IACd,QAAA,EAAU,CAAC,mBAAA,EAAqB,OAAO,CAAA;AAAA,IACvC,SAAS,YAAY;AACnB,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,MAAM,IAAI,MAAM,sBAAsB,CAAA;AAAA,MACxC;AACA,MAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,aAAA,CAAc,OAAO,CAAA;AAC9C,MAAA,OAAO,GAAA;AAAA,IACT,CAAA;AAAA;AAAA,IAEA,MAAA,EAAQC,4DAAA;AAAA,IACR,OAAA,EAAS,CAAC,CAAC,OAAA;AAAA,IACX,WAAW,CAAA,KAAA,KAAS;AAClB,MAAA,MAAM,IAAA,GAAO,MAAM,KAAA,CAAM,IAAA;AAEzB,MAAA,MAAM,UAAA,GAAa,MAAM,KAAA,CAAM,KAAA,CAAM,OAAK,OAAA,CAAQ,CAAA,CAAE,OAAO,CAAC,CAAA;AAE5D,MAAA,IAAI,UAAA,EAAY;AACd,QAAA,OAAO,oBAAA;AAAA,MACT;AAEA,MAAA,OAAO,CAAA;AAAA,IACT;AAAA,GACD,CAAA;AACH;;;;"}
@@ -1,5 +1,7 @@
1
1
  import { useMastraClient } from '@mastra/react';
2
2
  import { useQuery } from '@tanstack/react-query';
3
+ import { selectSearchableSpans } from '../utils/to-searchable-spans.es.js';
4
+ import 'date-fns';
3
5
 
4
6
  const IMMUTABLE_CACHE_TIME = 1e3 * 60 * 60 * 24 * 30;
5
7
  function useTraceLightSpans(traceId) {
@@ -13,6 +15,8 @@ function useTraceLightSpans(traceId) {
13
15
  const res = await client.getTraceLight(traceId);
14
16
  return res;
15
17
  },
18
+ // Builds each span's search haystack once per fetch, cached with the query.
19
+ select: selectSearchableSpans,
16
20
  enabled: !!traceId,
17
21
  staleTime: (query) => {
18
22
  const data = query.state.data;
@@ -1 +1 @@
1
- {"version":3,"file":"use-trace-light-spans.es.js","sources":["../../../../src/domains/traces/hooks/use-trace-light-spans.ts"],"sourcesContent":["import type { LightSpanRecord } from '@mastra/core/storage';\nimport { useMastraClient } from '@mastra/react';\nimport { useQuery } from '@tanstack/react-query';\nimport type { UseQueryResult } from '@tanstack/react-query';\n\nconst IMMUTABLE_CACHE_TIME = 1000 * 60 * 60 * 24 * 30; // 30 days, massive cache, span data is immutable\n\nexport function useTraceLightSpans(\n traceId: string | null | undefined,\n): UseQueryResult<{ traceId: string; spans: LightSpanRecord[] } | null> {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['trace-light-spans', traceId],\n queryFn: async () => {\n if (!traceId) {\n throw new Error('Trace ID is required');\n }\n const res = await client.getTraceLight(traceId);\n return res;\n },\n enabled: !!traceId,\n staleTime: query => {\n const data = query.state.data;\n\n const isFinished = data?.spans.every(d => Boolean(d.endedAt));\n\n if (isFinished) {\n return IMMUTABLE_CACHE_TIME;\n }\n\n return 0;\n },\n });\n}\n"],"names":[],"mappings":";;;AAKA,MAAM,oBAAA,GAAuB,GAAA,GAAO,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,EAAA;AAE5C,SAAS,mBACd,OAAA,EACsE;AACtE,EAAA,MAAM,SAAS,eAAA,EAAgB;AAE/B,EAAA,OAAO,QAAA,CAAS;AAAA,IACd,QAAA,EAAU,CAAC,mBAAA,EAAqB,OAAO,CAAA;AAAA,IACvC,SAAS,YAAY;AACnB,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,MAAM,IAAI,MAAM,sBAAsB,CAAA;AAAA,MACxC;AACA,MAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,aAAA,CAAc,OAAO,CAAA;AAC9C,MAAA,OAAO,GAAA;AAAA,IACT,CAAA;AAAA,IACA,OAAA,EAAS,CAAC,CAAC,OAAA;AAAA,IACX,WAAW,CAAA,KAAA,KAAS;AAClB,MAAA,MAAM,IAAA,GAAO,MAAM,KAAA,CAAM,IAAA;AAEzB,MAAA,MAAM,UAAA,GAAa,MAAM,KAAA,CAAM,KAAA,CAAM,OAAK,OAAA,CAAQ,CAAA,CAAE,OAAO,CAAC,CAAA;AAE5D,MAAA,IAAI,UAAA,EAAY;AACd,QAAA,OAAO,oBAAA;AAAA,MACT;AAEA,MAAA,OAAO,CAAA;AAAA,IACT;AAAA,GACD,CAAA;AACH;;;;"}
1
+ {"version":3,"file":"use-trace-light-spans.es.js","sources":["../../../../src/domains/traces/hooks/use-trace-light-spans.ts"],"sourcesContent":["import { useMastraClient } from '@mastra/react';\nimport { useQuery } from '@tanstack/react-query';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport type { SearchableSpan } from '../types';\nimport { selectSearchableSpans } from '../utils';\n\nconst IMMUTABLE_CACHE_TIME = 1000 * 60 * 60 * 24 * 30; // 30 days, massive cache, span data is immutable\n\nexport function useTraceLightSpans(\n traceId: string | null | undefined,\n): UseQueryResult<{ traceId: string; spans: SearchableSpan[] } | null> {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['trace-light-spans', traceId],\n queryFn: async () => {\n if (!traceId) {\n throw new Error('Trace ID is required');\n }\n const res = await client.getTraceLight(traceId);\n return res;\n },\n // Builds each span's search haystack once per fetch, cached with the query.\n select: selectSearchableSpans,\n enabled: !!traceId,\n staleTime: query => {\n const data = query.state.data;\n\n const isFinished = data?.spans.every(d => Boolean(d.endedAt));\n\n if (isFinished) {\n return IMMUTABLE_CACHE_TIME;\n }\n\n return 0;\n },\n });\n}\n"],"names":[],"mappings":";;;;;AAMA,MAAM,oBAAA,GAAuB,GAAA,GAAO,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,EAAA;AAE5C,SAAS,mBACd,OAAA,EACqE;AACrE,EAAA,MAAM,SAAS,eAAA,EAAgB;AAE/B,EAAA,OAAO,QAAA,CAAS;AAAA,IACd,QAAA,EAAU,CAAC,mBAAA,EAAqB,OAAO,CAAA;AAAA,IACvC,SAAS,YAAY;AACnB,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,MAAM,IAAI,MAAM,sBAAsB,CAAA;AAAA,MACxC;AACA,MAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,aAAA,CAAc,OAAO,CAAA;AAC9C,MAAA,OAAO,GAAA;AAAA,IACT,CAAA;AAAA;AAAA,IAEA,MAAA,EAAQ,qBAAA;AAAA,IACR,OAAA,EAAS,CAAC,CAAC,OAAA;AAAA,IACX,WAAW,CAAA,KAAA,KAAS;AAClB,MAAA,MAAM,IAAA,GAAO,MAAM,KAAA,CAAM,IAAA;AAEzB,MAAA,MAAM,UAAA,GAAa,MAAM,KAAA,CAAM,KAAA,CAAM,OAAK,OAAA,CAAQ,CAAA,CAAE,OAAO,CAAC,CAAA;AAE5D,MAAA,IAAI,UAAA,EAAY;AACd,QAAA,OAAO,oBAAA;AAAA,MACT;AAEA,MAAA,OAAO,CAAA;AAAA,IACT;AAAA,GACD,CAAA;AACH;;;;"}
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
4
 
5
5
  const domains_traces_hooks_useBranch = require('./use-branch.cjs.js');
6
- const domains_traces_hooks_useTraceLightSpans = require('./use-trace-light-spans.cjs.js');
6
+ const domains_traces_hooks_useTraceSpans = require('./use-trace-spans.cjs.js');
7
7
 
8
8
  function useTraceOrBranchSpans({
9
9
  traceId,
@@ -12,7 +12,7 @@ function useTraceOrBranchSpans({
12
12
  depth
13
13
  }) {
14
14
  const isBranches = listMode === "branches";
15
- const traceQuery = domains_traces_hooks_useTraceLightSpans.useTraceLightSpans(isBranches ? null : traceId);
15
+ const traceQuery = domains_traces_hooks_useTraceSpans.useTraceSpans(isBranches ? null : traceId);
16
16
  const branchQuery = domains_traces_hooks_useBranch.useBranch({
17
17
  traceId: isBranches ? traceId : null,
18
18
  spanId: isBranches ? anchorSpanId : null,
@@ -1 +1 @@
1
- {"version":3,"file":"use-trace-or-branch-spans.cjs.js","sources":["../../../../src/domains/traces/hooks/use-trace-or-branch-spans.ts"],"sourcesContent":["import type { LightSpanRecord } from '@mastra/core/storage';\nimport type { TraceListMode } from '../trace-filters';\nimport { useBranch } from './use-branch';\nimport { useTraceLightSpans } from './use-trace-light-spans';\n\nexport interface UseTraceOrBranchSpansArgs {\n traceId: string | null | undefined;\n /** Required when `listMode === 'branches'` — the anchor span identifying the displayed\n * subtree. The hook fetches `getBranch(traceId, anchorSpanId)`. Intra-panel span selection\n * is separate (the caller's `spanIdParam`); the anchor stays put while it changes. */\n anchorSpanId?: string | null;\n listMode: TraceListMode;\n depth?: number;\n}\n\nexport interface UseTraceOrBranchSpansResult {\n spans: LightSpanRecord[] | undefined;\n /** Set in branches mode; undefined in traces mode (which uses parentSpanId == null). */\n anchorSpanId: string | undefined;\n isLoading: boolean;\n isError: boolean;\n error: unknown;\n}\n\n/**\n * Unified data source for the trace/span detail panel. Returns trace spans (full tree from the\n * root) in traces mode, or branch spans (subtree rooted at `anchorSpanId`) in branches mode.\n * Only the active query fires; the inactive one is disabled via its `enabled` flag.\n */\nexport function useTraceOrBranchSpans({\n traceId,\n anchorSpanId,\n listMode,\n depth,\n}: UseTraceOrBranchSpansArgs): UseTraceOrBranchSpansResult {\n const isBranches = listMode === 'branches';\n\n const traceQuery = useTraceLightSpans(isBranches ? null : traceId);\n const branchQuery = useBranch({\n traceId: isBranches ? traceId : null,\n spanId: isBranches ? anchorSpanId : null,\n depth,\n });\n\n if (isBranches) {\n return {\n spans: branchQuery.data?.spans,\n anchorSpanId: anchorSpanId ?? undefined,\n isLoading: branchQuery.isLoading,\n isError: branchQuery.isError,\n error: branchQuery.error,\n };\n }\n\n return {\n spans: traceQuery.data?.spans,\n anchorSpanId: undefined,\n isLoading: traceQuery.isLoading,\n isError: traceQuery.isError,\n error: traceQuery.error,\n };\n}\n"],"names":["useTraceLightSpans","useBranch"],"mappings":";;;;;;;AA6BO,SAAS,qBAAA,CAAsB;AAAA,EACpC,OAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,EAA2D;AACzD,EAAA,MAAM,aAAa,QAAA,KAAa,UAAA;AAEhC,EAAA,MAAM,UAAA,GAAaA,0DAAA,CAAmB,UAAA,GAAa,IAAA,GAAO,OAAO,CAAA;AACjE,EAAA,MAAM,cAAcC,wCAAA,CAAU;AAAA,IAC5B,OAAA,EAAS,aAAa,OAAA,GAAU,IAAA;AAAA,IAChC,MAAA,EAAQ,aAAa,YAAA,GAAe,IAAA;AAAA,IACpC;AAAA,GACD,CAAA;AAED,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,YAAY,IAAA,EAAM,KAAA;AAAA,MACzB,cAAc,YAAA,IAAgB,MAAA;AAAA,MAC9B,WAAW,WAAA,CAAY,SAAA;AAAA,MACvB,SAAS,WAAA,CAAY,OAAA;AAAA,MACrB,OAAO,WAAA,CAAY;AAAA,KACrB;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,WAAW,IAAA,EAAM,KAAA;AAAA,IACxB,YAAA,EAAc,MAAA;AAAA,IACd,WAAW,UAAA,CAAW,SAAA;AAAA,IACtB,SAAS,UAAA,CAAW,OAAA;AAAA,IACpB,OAAO,UAAA,CAAW;AAAA,GACpB;AACF;;;;"}
1
+ {"version":3,"file":"use-trace-or-branch-spans.cjs.js","sources":["../../../../src/domains/traces/hooks/use-trace-or-branch-spans.ts"],"sourcesContent":["import type { TraceListMode } from '../trace-filters';\nimport type { SearchableSpan } from '../types';\nimport { useBranch } from './use-branch';\nimport { useTraceSpans } from './use-trace-spans';\n\nexport interface UseTraceOrBranchSpansArgs {\n traceId: string | null | undefined;\n /** Required when `listMode === 'branches'` — the anchor span identifying the displayed\n * subtree. The hook fetches `getBranch(traceId, anchorSpanId)`. Intra-panel span selection\n * is separate (the caller's `spanIdParam`); the anchor stays put while it changes. */\n anchorSpanId?: string | null;\n listMode: TraceListMode;\n depth?: number;\n}\n\nexport interface UseTraceOrBranchSpansResult {\n spans: SearchableSpan[] | undefined;\n /** Set in branches mode; undefined in traces mode (which uses parentSpanId == null). */\n anchorSpanId: string | undefined;\n isLoading: boolean;\n isError: boolean;\n error: unknown;\n}\n\n/**\n * Unified data source for the trace/span detail panel. Returns trace spans (full tree from the\n * root) in traces mode, or branch spans (subtree rooted at `anchorSpanId`) in branches mode.\n * Only the active query fires; the inactive one is disabled via its `enabled` flag.\n *\n * Both modes carry full span payloads: the panel renders and searches them, so a lightweight\n * projection here would hide content from the reader looking straight at it.\n */\nexport function useTraceOrBranchSpans({\n traceId,\n anchorSpanId,\n listMode,\n depth,\n}: UseTraceOrBranchSpansArgs): UseTraceOrBranchSpansResult {\n const isBranches = listMode === 'branches';\n\n const traceQuery = useTraceSpans(isBranches ? null : traceId);\n const branchQuery = useBranch({\n traceId: isBranches ? traceId : null,\n spanId: isBranches ? anchorSpanId : null,\n depth,\n });\n\n if (isBranches) {\n return {\n spans: branchQuery.data?.spans,\n anchorSpanId: anchorSpanId ?? undefined,\n isLoading: branchQuery.isLoading,\n isError: branchQuery.isError,\n error: branchQuery.error,\n };\n }\n\n return {\n spans: traceQuery.data?.spans,\n anchorSpanId: undefined,\n isLoading: traceQuery.isLoading,\n isError: traceQuery.isError,\n error: traceQuery.error,\n };\n}\n"],"names":["useTraceSpans","useBranch"],"mappings":";;;;;;;AAgCO,SAAS,qBAAA,CAAsB;AAAA,EACpC,OAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,EAA2D;AACzD,EAAA,MAAM,aAAa,QAAA,KAAa,UAAA;AAEhC,EAAA,MAAM,UAAA,GAAaA,gDAAA,CAAc,UAAA,GAAa,IAAA,GAAO,OAAO,CAAA;AAC5D,EAAA,MAAM,cAAcC,wCAAA,CAAU;AAAA,IAC5B,OAAA,EAAS,aAAa,OAAA,GAAU,IAAA;AAAA,IAChC,MAAA,EAAQ,aAAa,YAAA,GAAe,IAAA;AAAA,IACpC;AAAA,GACD,CAAA;AAED,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,YAAY,IAAA,EAAM,KAAA;AAAA,MACzB,cAAc,YAAA,IAAgB,MAAA;AAAA,MAC9B,WAAW,WAAA,CAAY,SAAA;AAAA,MACvB,SAAS,WAAA,CAAY,OAAA;AAAA,MACrB,OAAO,WAAA,CAAY;AAAA,KACrB;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,WAAW,IAAA,EAAM,KAAA;AAAA,IACxB,YAAA,EAAc,MAAA;AAAA,IACd,WAAW,UAAA,CAAW,SAAA;AAAA,IACtB,SAAS,UAAA,CAAW,OAAA;AAAA,IACpB,OAAO,UAAA,CAAW;AAAA,GACpB;AACF;;;;"}
@@ -1,5 +1,5 @@
1
1
  import { useBranch } from './use-branch.es.js';
2
- import { useTraceLightSpans } from './use-trace-light-spans.es.js';
2
+ import { useTraceSpans } from './use-trace-spans.es.js';
3
3
 
4
4
  function useTraceOrBranchSpans({
5
5
  traceId,
@@ -8,7 +8,7 @@ function useTraceOrBranchSpans({
8
8
  depth
9
9
  }) {
10
10
  const isBranches = listMode === "branches";
11
- const traceQuery = useTraceLightSpans(isBranches ? null : traceId);
11
+ const traceQuery = useTraceSpans(isBranches ? null : traceId);
12
12
  const branchQuery = useBranch({
13
13
  traceId: isBranches ? traceId : null,
14
14
  spanId: isBranches ? anchorSpanId : null,
@@ -1 +1 @@
1
- {"version":3,"file":"use-trace-or-branch-spans.es.js","sources":["../../../../src/domains/traces/hooks/use-trace-or-branch-spans.ts"],"sourcesContent":["import type { LightSpanRecord } from '@mastra/core/storage';\nimport type { TraceListMode } from '../trace-filters';\nimport { useBranch } from './use-branch';\nimport { useTraceLightSpans } from './use-trace-light-spans';\n\nexport interface UseTraceOrBranchSpansArgs {\n traceId: string | null | undefined;\n /** Required when `listMode === 'branches'` — the anchor span identifying the displayed\n * subtree. The hook fetches `getBranch(traceId, anchorSpanId)`. Intra-panel span selection\n * is separate (the caller's `spanIdParam`); the anchor stays put while it changes. */\n anchorSpanId?: string | null;\n listMode: TraceListMode;\n depth?: number;\n}\n\nexport interface UseTraceOrBranchSpansResult {\n spans: LightSpanRecord[] | undefined;\n /** Set in branches mode; undefined in traces mode (which uses parentSpanId == null). */\n anchorSpanId: string | undefined;\n isLoading: boolean;\n isError: boolean;\n error: unknown;\n}\n\n/**\n * Unified data source for the trace/span detail panel. Returns trace spans (full tree from the\n * root) in traces mode, or branch spans (subtree rooted at `anchorSpanId`) in branches mode.\n * Only the active query fires; the inactive one is disabled via its `enabled` flag.\n */\nexport function useTraceOrBranchSpans({\n traceId,\n anchorSpanId,\n listMode,\n depth,\n}: UseTraceOrBranchSpansArgs): UseTraceOrBranchSpansResult {\n const isBranches = listMode === 'branches';\n\n const traceQuery = useTraceLightSpans(isBranches ? null : traceId);\n const branchQuery = useBranch({\n traceId: isBranches ? traceId : null,\n spanId: isBranches ? anchorSpanId : null,\n depth,\n });\n\n if (isBranches) {\n return {\n spans: branchQuery.data?.spans,\n anchorSpanId: anchorSpanId ?? undefined,\n isLoading: branchQuery.isLoading,\n isError: branchQuery.isError,\n error: branchQuery.error,\n };\n }\n\n return {\n spans: traceQuery.data?.spans,\n anchorSpanId: undefined,\n isLoading: traceQuery.isLoading,\n isError: traceQuery.isError,\n error: traceQuery.error,\n };\n}\n"],"names":[],"mappings":";;;AA6BO,SAAS,qBAAA,CAAsB;AAAA,EACpC,OAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,EAA2D;AACzD,EAAA,MAAM,aAAa,QAAA,KAAa,UAAA;AAEhC,EAAA,MAAM,UAAA,GAAa,kBAAA,CAAmB,UAAA,GAAa,IAAA,GAAO,OAAO,CAAA;AACjE,EAAA,MAAM,cAAc,SAAA,CAAU;AAAA,IAC5B,OAAA,EAAS,aAAa,OAAA,GAAU,IAAA;AAAA,IAChC,MAAA,EAAQ,aAAa,YAAA,GAAe,IAAA;AAAA,IACpC;AAAA,GACD,CAAA;AAED,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,YAAY,IAAA,EAAM,KAAA;AAAA,MACzB,cAAc,YAAA,IAAgB,MAAA;AAAA,MAC9B,WAAW,WAAA,CAAY,SAAA;AAAA,MACvB,SAAS,WAAA,CAAY,OAAA;AAAA,MACrB,OAAO,WAAA,CAAY;AAAA,KACrB;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,WAAW,IAAA,EAAM,KAAA;AAAA,IACxB,YAAA,EAAc,MAAA;AAAA,IACd,WAAW,UAAA,CAAW,SAAA;AAAA,IACtB,SAAS,UAAA,CAAW,OAAA;AAAA,IACpB,OAAO,UAAA,CAAW;AAAA,GACpB;AACF;;;;"}
1
+ {"version":3,"file":"use-trace-or-branch-spans.es.js","sources":["../../../../src/domains/traces/hooks/use-trace-or-branch-spans.ts"],"sourcesContent":["import type { TraceListMode } from '../trace-filters';\nimport type { SearchableSpan } from '../types';\nimport { useBranch } from './use-branch';\nimport { useTraceSpans } from './use-trace-spans';\n\nexport interface UseTraceOrBranchSpansArgs {\n traceId: string | null | undefined;\n /** Required when `listMode === 'branches'` — the anchor span identifying the displayed\n * subtree. The hook fetches `getBranch(traceId, anchorSpanId)`. Intra-panel span selection\n * is separate (the caller's `spanIdParam`); the anchor stays put while it changes. */\n anchorSpanId?: string | null;\n listMode: TraceListMode;\n depth?: number;\n}\n\nexport interface UseTraceOrBranchSpansResult {\n spans: SearchableSpan[] | undefined;\n /** Set in branches mode; undefined in traces mode (which uses parentSpanId == null). */\n anchorSpanId: string | undefined;\n isLoading: boolean;\n isError: boolean;\n error: unknown;\n}\n\n/**\n * Unified data source for the trace/span detail panel. Returns trace spans (full tree from the\n * root) in traces mode, or branch spans (subtree rooted at `anchorSpanId`) in branches mode.\n * Only the active query fires; the inactive one is disabled via its `enabled` flag.\n *\n * Both modes carry full span payloads: the panel renders and searches them, so a lightweight\n * projection here would hide content from the reader looking straight at it.\n */\nexport function useTraceOrBranchSpans({\n traceId,\n anchorSpanId,\n listMode,\n depth,\n}: UseTraceOrBranchSpansArgs): UseTraceOrBranchSpansResult {\n const isBranches = listMode === 'branches';\n\n const traceQuery = useTraceSpans(isBranches ? null : traceId);\n const branchQuery = useBranch({\n traceId: isBranches ? traceId : null,\n spanId: isBranches ? anchorSpanId : null,\n depth,\n });\n\n if (isBranches) {\n return {\n spans: branchQuery.data?.spans,\n anchorSpanId: anchorSpanId ?? undefined,\n isLoading: branchQuery.isLoading,\n isError: branchQuery.isError,\n error: branchQuery.error,\n };\n }\n\n return {\n spans: traceQuery.data?.spans,\n anchorSpanId: undefined,\n isLoading: traceQuery.isLoading,\n isError: traceQuery.isError,\n error: traceQuery.error,\n };\n}\n"],"names":[],"mappings":";;;AAgCO,SAAS,qBAAA,CAAsB;AAAA,EACpC,OAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,EAA2D;AACzD,EAAA,MAAM,aAAa,QAAA,KAAa,UAAA;AAEhC,EAAA,MAAM,UAAA,GAAa,aAAA,CAAc,UAAA,GAAa,IAAA,GAAO,OAAO,CAAA;AAC5D,EAAA,MAAM,cAAc,SAAA,CAAU;AAAA,IAC5B,OAAA,EAAS,aAAa,OAAA,GAAU,IAAA;AAAA,IAChC,MAAA,EAAQ,aAAa,YAAA,GAAe,IAAA;AAAA,IACpC;AAAA,GACD,CAAA;AAED,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,YAAY,IAAA,EAAM,KAAA;AAAA,MACzB,cAAc,YAAA,IAAgB,MAAA;AAAA,MAC9B,WAAW,WAAA,CAAY,SAAA;AAAA,MACvB,SAAS,WAAA,CAAY,OAAA;AAAA,MACrB,OAAO,WAAA,CAAY;AAAA,KACrB;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,WAAW,IAAA,EAAM,KAAA;AAAA,IACxB,YAAA,EAAc,MAAA;AAAA,IACd,WAAW,UAAA,CAAW,SAAA;AAAA,IACtB,SAAS,UAAA,CAAW,OAAA;AAAA,IACpB,OAAO,UAAA,CAAW;AAAA,GACpB;AACF;;;;"}
@@ -0,0 +1,21 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
+
5
+ const React = require('react');
6
+ const domains_traces_utils_filterSpansKeepingAncestors = require('../utils/filter-spans-keeping-ancestors.cjs.js');
7
+ require('date-fns');
8
+
9
+ function useTraceSearch(spans) {
10
+ const [query, setQuery] = React.useState("");
11
+ const deferredQuery = React.useDeferredValue(query);
12
+ const results = React.useMemo(() => {
13
+ const term = deferredQuery.trim().toLowerCase();
14
+ if (!term) return spans;
15
+ return domains_traces_utils_filterSpansKeepingAncestors.filterSpansKeepingAncestors(spans, (span) => span.searchText.includes(term));
16
+ }, [spans, deferredQuery]);
17
+ return { query, setQuery, results, isPending: query !== deferredQuery };
18
+ }
19
+
20
+ exports.useTraceSearch = useTraceSearch;
21
+ //# sourceMappingURL=use-trace-search.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-trace-search.cjs.js","sources":["../../../../src/domains/traces/hooks/use-trace-search.ts"],"sourcesContent":["import { useDeferredValue, useMemo, useState } from 'react';\nimport type { SearchableSpan } from '../types';\nimport { filterSpansKeepingAncestors } from '../utils';\n\nexport interface UseTraceSearchResult {\n /** The immediate, user-facing input value. Bind this to the search field. */\n query: string;\n setQuery: (query: string) => void;\n /** Rows matching the deferred query. An empty query returns the input array reference. */\n results: SearchableSpan[];\n /** True while the deferred value is behind `query` (the list is still catching up). */\n isPending: boolean;\n}\n\n/**\n * Client-side search over a flat span list.\n *\n * Matching is a substring test against `searchText`, the haystack built once per span when\n * the query resolved (see `toSearchableSpans`). That is what makes the open-ended `metadata`\n * and `error` payloads searchable: their shapes are unknown, so no fixed list of fields can\n * read them. Both sides are already lowercased, so the test is a bare `includes`.\n *\n * Filtering is keyed on a deferred copy of the query, so typing stays responsive while a\n * large list re-filters at lower priority — bind the input to `query`, not to the deferred\n * value. A matching span keeps its ancestors and its whole subtree, so the hierarchy stays\n * intact.\n *\n * `spans` is required. Resolving the loading/empty state is the caller's job — a component\n * holding a query result passes `data?.spans ?? []`.\n */\nexport function useTraceSearch(spans: SearchableSpan[]): UseTraceSearchResult {\n const [query, setQuery] = useState('');\n const deferredQuery = useDeferredValue(query);\n\n const results = useMemo(() => {\n const term = deferredQuery.trim().toLowerCase();\n if (!term) return spans;\n return filterSpansKeepingAncestors(spans, span => span.searchText.includes(term));\n }, [spans, deferredQuery]);\n\n return { query, setQuery, results, isPending: query !== deferredQuery };\n}\n"],"names":["useState","useDeferredValue","useMemo","filterSpansKeepingAncestors"],"mappings":";;;;;;;;AA8BO,SAAS,eAAe,KAAA,EAA+C;AAC5E,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIA,eAAS,EAAE,CAAA;AACrC,EAAA,MAAM,aAAA,GAAgBC,uBAAiB,KAAK,CAAA;AAE5C,EAAA,MAAM,OAAA,GAAUC,cAAQ,MAAM;AAC5B,IAAA,MAAM,IAAA,GAAO,aAAA,CAAc,IAAA,EAAK,CAAE,WAAA,EAAY;AAC9C,IAAA,IAAI,CAAC,MAAM,OAAO,KAAA;AAClB,IAAA,OAAOC,6EAA4B,KAAA,EAAO,CAAA,IAAA,KAAQ,KAAK,UAAA,CAAW,QAAA,CAAS,IAAI,CAAC,CAAA;AAAA,EAClF,CAAA,EAAG,CAAC,KAAA,EAAO,aAAa,CAAC,CAAA;AAEzB,EAAA,OAAO,EAAE,KAAA,EAAO,QAAA,EAAU,OAAA,EAAS,SAAA,EAAW,UAAU,aAAA,EAAc;AACxE;;;;"}
@@ -0,0 +1,2 @@
1
+ export * from '../../../src/domains/traces/hooks/use-trace-search'
2
+ export {}
@@ -0,0 +1,17 @@
1
+ import { useState, useDeferredValue, useMemo } from 'react';
2
+ import { filterSpansKeepingAncestors } from '../utils/filter-spans-keeping-ancestors.es.js';
3
+ import 'date-fns';
4
+
5
+ function useTraceSearch(spans) {
6
+ const [query, setQuery] = useState("");
7
+ const deferredQuery = useDeferredValue(query);
8
+ const results = useMemo(() => {
9
+ const term = deferredQuery.trim().toLowerCase();
10
+ if (!term) return spans;
11
+ return filterSpansKeepingAncestors(spans, (span) => span.searchText.includes(term));
12
+ }, [spans, deferredQuery]);
13
+ return { query, setQuery, results, isPending: query !== deferredQuery };
14
+ }
15
+
16
+ export { useTraceSearch };
17
+ //# sourceMappingURL=use-trace-search.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-trace-search.es.js","sources":["../../../../src/domains/traces/hooks/use-trace-search.ts"],"sourcesContent":["import { useDeferredValue, useMemo, useState } from 'react';\nimport type { SearchableSpan } from '../types';\nimport { filterSpansKeepingAncestors } from '../utils';\n\nexport interface UseTraceSearchResult {\n /** The immediate, user-facing input value. Bind this to the search field. */\n query: string;\n setQuery: (query: string) => void;\n /** Rows matching the deferred query. An empty query returns the input array reference. */\n results: SearchableSpan[];\n /** True while the deferred value is behind `query` (the list is still catching up). */\n isPending: boolean;\n}\n\n/**\n * Client-side search over a flat span list.\n *\n * Matching is a substring test against `searchText`, the haystack built once per span when\n * the query resolved (see `toSearchableSpans`). That is what makes the open-ended `metadata`\n * and `error` payloads searchable: their shapes are unknown, so no fixed list of fields can\n * read them. Both sides are already lowercased, so the test is a bare `includes`.\n *\n * Filtering is keyed on a deferred copy of the query, so typing stays responsive while a\n * large list re-filters at lower priority — bind the input to `query`, not to the deferred\n * value. A matching span keeps its ancestors and its whole subtree, so the hierarchy stays\n * intact.\n *\n * `spans` is required. Resolving the loading/empty state is the caller's job — a component\n * holding a query result passes `data?.spans ?? []`.\n */\nexport function useTraceSearch(spans: SearchableSpan[]): UseTraceSearchResult {\n const [query, setQuery] = useState('');\n const deferredQuery = useDeferredValue(query);\n\n const results = useMemo(() => {\n const term = deferredQuery.trim().toLowerCase();\n if (!term) return spans;\n return filterSpansKeepingAncestors(spans, span => span.searchText.includes(term));\n }, [spans, deferredQuery]);\n\n return { query, setQuery, results, isPending: query !== deferredQuery };\n}\n"],"names":[],"mappings":";;;;AA8BO,SAAS,eAAe,KAAA,EAA+C;AAC5E,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAS,EAAE,CAAA;AACrC,EAAA,MAAM,aAAA,GAAgB,iBAAiB,KAAK,CAAA;AAE5C,EAAA,MAAM,OAAA,GAAU,QAAQ,MAAM;AAC5B,IAAA,MAAM,IAAA,GAAO,aAAA,CAAc,IAAA,EAAK,CAAE,WAAA,EAAY;AAC9C,IAAA,IAAI,CAAC,MAAM,OAAO,KAAA;AAClB,IAAA,OAAO,4BAA4B,KAAA,EAAO,CAAA,IAAA,KAAQ,KAAK,UAAA,CAAW,QAAA,CAAS,IAAI,CAAC,CAAA;AAAA,EAClF,CAAA,EAAG,CAAC,KAAA,EAAO,aAAa,CAAC,CAAA;AAEzB,EAAA,OAAO,EAAE,KAAA,EAAO,QAAA,EAAU,OAAA,EAAS,SAAA,EAAW,UAAU,aAAA,EAAc;AACxE;;;;"}
@@ -4,7 +4,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
4
 
5
5
  const react = require('@mastra/react');
6
6
  const reactQuery = require('@tanstack/react-query');
7
+ const domains_traces_utils_toSearchableSpans = require('../utils/to-searchable-spans.cjs.js');
8
+ require('date-fns');
7
9
 
10
+ const IMMUTABLE_CACHE_TIME = 1e3 * 60 * 60 * 24 * 30;
8
11
  function useTraceSpans(traceId) {
9
12
  const client = react.useMastraClient();
10
13
  return reactQuery.useQuery({
@@ -16,7 +19,14 @@ function useTraceSpans(traceId) {
16
19
  const res = await client.getTrace(traceId);
17
20
  return res;
18
21
  },
19
- enabled: !!traceId
22
+ // Builds each span's search haystack once per fetch, cached with the query.
23
+ select: domains_traces_utils_toSearchableSpans.selectSearchableSpans,
24
+ enabled: !!traceId,
25
+ staleTime: (query) => {
26
+ const data = query.state.data;
27
+ const isFinished = data?.spans.every((span) => Boolean(span.endedAt));
28
+ return isFinished ? IMMUTABLE_CACHE_TIME : 0;
29
+ }
20
30
  });
21
31
  }
22
32
 
@@ -1 +1 @@
1
- {"version":3,"file":"use-trace-spans.cjs.js","sources":["../../../../src/domains/traces/hooks/use-trace-spans.ts"],"sourcesContent":["import type { LightSpanRecord } from '@mastra/core/storage';\nimport { useMastraClient } from '@mastra/react';\nimport { useQuery } from '@tanstack/react-query';\nimport type { UseQueryResult } from '@tanstack/react-query';\n\nexport function useTraceSpans(\n traceId: string | null | undefined,\n): UseQueryResult<{ traceId: string; spans: LightSpanRecord[] } | null> {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['trace-spans', traceId],\n queryFn: async () => {\n if (!traceId) {\n throw new Error('Trace ID is required');\n }\n const res = await client.getTrace(traceId);\n return res;\n },\n enabled: !!traceId,\n });\n}\n"],"names":["useMastraClient","useQuery"],"mappings":";;;;;;;AAKO,SAAS,cACd,OAAA,EACsE;AACtE,EAAA,MAAM,SAASA,qBAAA,EAAgB;AAE/B,EAAA,OAAOC,mBAAA,CAAS;AAAA,IACd,QAAA,EAAU,CAAC,aAAA,EAAe,OAAO,CAAA;AAAA,IACjC,SAAS,YAAY;AACnB,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,MAAM,IAAI,MAAM,sBAAsB,CAAA;AAAA,MACxC;AACA,MAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,QAAA,CAAS,OAAO,CAAA;AACzC,MAAA,OAAO,GAAA;AAAA,IACT,CAAA;AAAA,IACA,OAAA,EAAS,CAAC,CAAC;AAAA,GACZ,CAAA;AACH;;;;"}
1
+ {"version":3,"file":"use-trace-spans.cjs.js","sources":["../../../../src/domains/traces/hooks/use-trace-spans.ts"],"sourcesContent":["import { useMastraClient } from '@mastra/react';\nimport { useQuery } from '@tanstack/react-query';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport type { SearchableSpan } from '../types';\nimport { selectSearchableSpans } from '../utils';\n\nconst IMMUTABLE_CACHE_TIME = 1000 * 60 * 60 * 24 * 30; // 30 days, massive cache, span data is immutable\n\n/**\n * Every span of a single trace, with its full payload.\n *\n * The lightweight projection exists to keep blob columns off the read path of a\n * *list*, where the cost is paid once per trace on screen. A trace that is open\n * has already narrowed that to one, and the panel both renders and searches\n * these spans -- `input`, `output` and `attributes` included -- so the\n * projection would only hide content the reader is looking at.\n */\nexport function useTraceSpans(\n traceId: string | null | undefined,\n): UseQueryResult<{ traceId: string; spans: SearchableSpan[] } | null> {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['trace-spans', traceId],\n queryFn: async () => {\n if (!traceId) {\n throw new Error('Trace ID is required');\n }\n const res = await client.getTrace(traceId);\n return res;\n },\n // Builds each span's search haystack once per fetch, cached with the query.\n select: selectSearchableSpans,\n enabled: !!traceId,\n staleTime: query => {\n const data = query.state.data;\n const isFinished = data?.spans.every(span => Boolean(span.endedAt));\n return isFinished ? IMMUTABLE_CACHE_TIME : 0;\n },\n });\n}\n"],"names":["useMastraClient","useQuery","selectSearchableSpans"],"mappings":";;;;;;;;;AAMA,MAAM,oBAAA,GAAuB,GAAA,GAAO,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,EAAA;AAW5C,SAAS,cACd,OAAA,EACqE;AACrE,EAAA,MAAM,SAASA,qBAAA,EAAgB;AAE/B,EAAA,OAAOC,mBAAA,CAAS;AAAA,IACd,QAAA,EAAU,CAAC,aAAA,EAAe,OAAO,CAAA;AAAA,IACjC,SAAS,YAAY;AACnB,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,MAAM,IAAI,MAAM,sBAAsB,CAAA;AAAA,MACxC;AACA,MAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,QAAA,CAAS,OAAO,CAAA;AACzC,MAAA,OAAO,GAAA;AAAA,IACT,CAAA;AAAA;AAAA,IAEA,MAAA,EAAQC,4DAAA;AAAA,IACR,OAAA,EAAS,CAAC,CAAC,OAAA;AAAA,IACX,WAAW,CAAA,KAAA,KAAS;AAClB,MAAA,MAAM,IAAA,GAAO,MAAM,KAAA,CAAM,IAAA;AACzB,MAAA,MAAM,UAAA,GAAa,MAAM,KAAA,CAAM,KAAA,CAAM,UAAQ,OAAA,CAAQ,IAAA,CAAK,OAAO,CAAC,CAAA;AAClE,MAAA,OAAO,aAAa,oBAAA,GAAuB,CAAA;AAAA,IAC7C;AAAA,GACD,CAAA;AACH;;;;"}
@@ -1,6 +1,9 @@
1
1
  import { useMastraClient } from '@mastra/react';
2
2
  import { useQuery } from '@tanstack/react-query';
3
+ import { selectSearchableSpans } from '../utils/to-searchable-spans.es.js';
4
+ import 'date-fns';
3
5
 
6
+ const IMMUTABLE_CACHE_TIME = 1e3 * 60 * 60 * 24 * 30;
4
7
  function useTraceSpans(traceId) {
5
8
  const client = useMastraClient();
6
9
  return useQuery({
@@ -12,7 +15,14 @@ function useTraceSpans(traceId) {
12
15
  const res = await client.getTrace(traceId);
13
16
  return res;
14
17
  },
15
- enabled: !!traceId
18
+ // Builds each span's search haystack once per fetch, cached with the query.
19
+ select: selectSearchableSpans,
20
+ enabled: !!traceId,
21
+ staleTime: (query) => {
22
+ const data = query.state.data;
23
+ const isFinished = data?.spans.every((span) => Boolean(span.endedAt));
24
+ return isFinished ? IMMUTABLE_CACHE_TIME : 0;
25
+ }
16
26
  });
17
27
  }
18
28
 
@@ -1 +1 @@
1
- {"version":3,"file":"use-trace-spans.es.js","sources":["../../../../src/domains/traces/hooks/use-trace-spans.ts"],"sourcesContent":["import type { LightSpanRecord } from '@mastra/core/storage';\nimport { useMastraClient } from '@mastra/react';\nimport { useQuery } from '@tanstack/react-query';\nimport type { UseQueryResult } from '@tanstack/react-query';\n\nexport function useTraceSpans(\n traceId: string | null | undefined,\n): UseQueryResult<{ traceId: string; spans: LightSpanRecord[] } | null> {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['trace-spans', traceId],\n queryFn: async () => {\n if (!traceId) {\n throw new Error('Trace ID is required');\n }\n const res = await client.getTrace(traceId);\n return res;\n },\n enabled: !!traceId,\n });\n}\n"],"names":[],"mappings":";;;AAKO,SAAS,cACd,OAAA,EACsE;AACtE,EAAA,MAAM,SAAS,eAAA,EAAgB;AAE/B,EAAA,OAAO,QAAA,CAAS;AAAA,IACd,QAAA,EAAU,CAAC,aAAA,EAAe,OAAO,CAAA;AAAA,IACjC,SAAS,YAAY;AACnB,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,MAAM,IAAI,MAAM,sBAAsB,CAAA;AAAA,MACxC;AACA,MAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,QAAA,CAAS,OAAO,CAAA;AACzC,MAAA,OAAO,GAAA;AAAA,IACT,CAAA;AAAA,IACA,OAAA,EAAS,CAAC,CAAC;AAAA,GACZ,CAAA;AACH;;;;"}
1
+ {"version":3,"file":"use-trace-spans.es.js","sources":["../../../../src/domains/traces/hooks/use-trace-spans.ts"],"sourcesContent":["import { useMastraClient } from '@mastra/react';\nimport { useQuery } from '@tanstack/react-query';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport type { SearchableSpan } from '../types';\nimport { selectSearchableSpans } from '../utils';\n\nconst IMMUTABLE_CACHE_TIME = 1000 * 60 * 60 * 24 * 30; // 30 days, massive cache, span data is immutable\n\n/**\n * Every span of a single trace, with its full payload.\n *\n * The lightweight projection exists to keep blob columns off the read path of a\n * *list*, where the cost is paid once per trace on screen. A trace that is open\n * has already narrowed that to one, and the panel both renders and searches\n * these spans -- `input`, `output` and `attributes` included -- so the\n * projection would only hide content the reader is looking at.\n */\nexport function useTraceSpans(\n traceId: string | null | undefined,\n): UseQueryResult<{ traceId: string; spans: SearchableSpan[] } | null> {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['trace-spans', traceId],\n queryFn: async () => {\n if (!traceId) {\n throw new Error('Trace ID is required');\n }\n const res = await client.getTrace(traceId);\n return res;\n },\n // Builds each span's search haystack once per fetch, cached with the query.\n select: selectSearchableSpans,\n enabled: !!traceId,\n staleTime: query => {\n const data = query.state.data;\n const isFinished = data?.spans.every(span => Boolean(span.endedAt));\n return isFinished ? IMMUTABLE_CACHE_TIME : 0;\n },\n });\n}\n"],"names":[],"mappings":";;;;;AAMA,MAAM,oBAAA,GAAuB,GAAA,GAAO,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,EAAA;AAW5C,SAAS,cACd,OAAA,EACqE;AACrE,EAAA,MAAM,SAAS,eAAA,EAAgB;AAE/B,EAAA,OAAO,QAAA,CAAS;AAAA,IACd,QAAA,EAAU,CAAC,aAAA,EAAe,OAAO,CAAA;AAAA,IACjC,SAAS,YAAY;AACnB,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,MAAM,IAAI,MAAM,sBAAsB,CAAA;AAAA,MACxC;AACA,MAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,QAAA,CAAS,OAAO,CAAA;AACzC,MAAA,OAAO,GAAA;AAAA,IACT,CAAA;AAAA;AAAA,IAEA,MAAA,EAAQ,qBAAA;AAAA,IACR,OAAA,EAAS,CAAC,CAAC,OAAA;AAAA,IACX,WAAW,CAAA,KAAA,KAAS;AAClB,MAAA,MAAM,IAAA,GAAO,MAAM,KAAA,CAAM,IAAA;AACzB,MAAA,MAAM,UAAA,GAAa,MAAM,KAAA,CAAM,KAAA,CAAM,UAAQ,OAAA,CAAQ,IAAA,CAAK,OAAO,CAAC,CAAA;AAClE,MAAA,OAAO,aAAa,oBAAA,GAAuB,CAAA;AAAA,IAC7C;AAAA,GACD,CAAA;AACH;;;;"}
@@ -8,6 +8,7 @@ const domains_traces_hooks_useDownloadTraceJson = require('./hooks/use-download-
8
8
  const domains_traces_hooks_useSpanDetail = require('./hooks/use-span-detail.cjs.js');
9
9
  const domains_traces_hooks_useTraceLightSpans = require('./hooks/use-trace-light-spans.cjs.js');
10
10
  const domains_traces_hooks_useTraceOrBranchSpans = require('./hooks/use-trace-or-branch-spans.cjs.js');
11
+ const domains_traces_hooks_useTraceSearch = require('./hooks/use-trace-search.cjs.js');
11
12
  const domains_traces_hooks_useTraceSpans = require('./hooks/use-trace-spans.cjs.js');
12
13
  const domains_traces_hooks_useTraces = require('./hooks/use-traces.cjs.js');
13
14
  const domains_traces_hooks_useTags = require('./hooks/use-tags.cjs.js');
@@ -28,6 +29,7 @@ exports.useDownloadTraceJson = domains_traces_hooks_useDownloadTraceJson.useDown
28
29
  exports.useSpanDetail = domains_traces_hooks_useSpanDetail.useSpanDetail;
29
30
  exports.useTraceLightSpans = domains_traces_hooks_useTraceLightSpans.useTraceLightSpans;
30
31
  exports.useTraceOrBranchSpans = domains_traces_hooks_useTraceOrBranchSpans.useTraceOrBranchSpans;
32
+ exports.useTraceSearch = domains_traces_hooks_useTraceSearch.useTraceSearch;
31
33
  exports.useTraceSpans = domains_traces_hooks_useTraceSpans.useTraceSpans;
32
34
  exports.useTraces = domains_traces_hooks_useTraces.useTraces;
33
35
  exports.useTags = domains_traces_hooks_useTags.useTags;
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"hooks.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -4,6 +4,7 @@ export { useDownloadTraceJson } from './hooks/use-download-trace-json.es.js';
4
4
  export { useSpanDetail } from './hooks/use-span-detail.es.js';
5
5
  export { useTraceLightSpans } from './hooks/use-trace-light-spans.es.js';
6
6
  export { useTraceOrBranchSpans } from './hooks/use-trace-or-branch-spans.es.js';
7
+ export { useTraceSearch } from './hooks/use-trace-search.es.js';
7
8
  export { useTraceSpans } from './hooks/use-trace-spans.es.js';
8
9
  export { useTraces } from './hooks/use-traces.es.js';
9
10
  export { useTags } from './hooks/use-tags.es.js';
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.es.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"hooks.es.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.cjs.js","sources":["../../../src/domains/traces/types.ts"],"sourcesContent":["import type { EntityType } from '@mastra/core/observability';\nimport type { ReactNode } from 'react';\n\nexport type UISpan = {\n id: string;\n name: string;\n type: string;\n latency: number;\n startTime: string;\n endTime?: string;\n spans?: UISpan[];\n parentSpanId?: string | null;\n};\n\nexport type UISpanStyle = {\n icon?: ReactNode;\n color?: string;\n label?: string;\n typePrefix: string;\n};\n\n// -- Trace filtering types ----------------------------------------------------\n\nexport type EntityOptions =\n | { value: string; label: string; type: EntityType.AGENT }\n | { value: string; label: string; type: EntityType.WORKFLOW_RUN }\n | { value: string; label: string; type: 'all' };\n\nexport type TraceDatePreset = 'all' | 'last-24h' | 'last-3d' | 'last-7d' | 'last-14d' | 'last-30d' | 'custom';\n\n/** Tab identifier for SpanDataPanelView. */\nexport type SpanTab = 'details' | 'feedback';\n\n/** Canonical list of context field IDs used for trace filtering and value extraction */\nexport const CONTEXT_FIELD_IDS = [\n 'environment',\n 'serviceName',\n 'source',\n 'scope',\n 'userId',\n 'organizationId',\n 'resourceId',\n 'runId',\n 'sessionId',\n 'threadId',\n 'requestId',\n 'experimentId',\n 'spanType',\n 'entityName',\n 'parentEntityType',\n 'parentEntityId',\n 'parentEntityName',\n 'rootEntityType',\n 'rootEntityId',\n 'rootEntityName',\n] as const;\n"],"names":[],"mappings":";;;;AAkCO,MAAM,iBAAA,GAAoB;AAAA,EAC/B,aAAA;AAAA,EACA,aAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,gBAAA;AAAA,EACA,YAAA;AAAA,EACA,OAAA;AAAA,EACA,WAAA;AAAA,EACA,UAAA;AAAA,EACA,WAAA;AAAA,EACA,cAAA;AAAA,EACA,UAAA;AAAA,EACA,YAAA;AAAA,EACA,kBAAA;AAAA,EACA,gBAAA;AAAA,EACA,kBAAA;AAAA,EACA,gBAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF;;;;"}
1
+ {"version":3,"file":"types.cjs.js","sources":["../../../src/domains/traces/types.ts"],"sourcesContent":["import type { EntityType } from '@mastra/core/observability';\nimport type { LightSpanRecord } from '@mastra/core/storage';\nimport type { ReactNode } from 'react';\n\n/**\n * A light span carrying a precomputed haystack of everything it holds.\n *\n * `LightSpanRecord` exposes searchable content across a fixed set of columns\n * plus open-ended payloads whose shape is unknown, so a search cannot read it\n * field by field. `searchText` is that content flattened once — see\n * `flattenToSearchText` — so filtering is a substring test per span instead of\n * a re-walk of every payload on every keystroke.\n *\n * It holds field names as well as values, so a span is findable by the shape of\n * its payload and not only by its content.\n */\nexport type SearchableSpan = LightSpanRecord & {\n searchText: string;\n};\n\nexport type UISpan = {\n id: string;\n name: string;\n type: string;\n latency: number;\n startTime: string;\n endTime?: string;\n spans?: UISpan[];\n parentSpanId?: string | null;\n};\n\nexport type UISpanStyle = {\n icon?: ReactNode;\n color?: string;\n label?: string;\n typePrefix: string;\n};\n\n// -- Trace filtering types ----------------------------------------------------\n\nexport type EntityOptions =\n | { value: string; label: string; type: EntityType.AGENT }\n | { value: string; label: string; type: EntityType.WORKFLOW_RUN }\n | { value: string; label: string; type: 'all' };\n\nexport type TraceDatePreset = 'all' | 'last-24h' | 'last-3d' | 'last-7d' | 'last-14d' | 'last-30d' | 'custom';\n\n/** Tab identifier for SpanDataPanelView. */\nexport type SpanTab = 'details' | 'feedback';\n\n/** Canonical list of context field IDs used for trace filtering and value extraction */\nexport const CONTEXT_FIELD_IDS = [\n 'environment',\n 'serviceName',\n 'source',\n 'scope',\n 'userId',\n 'organizationId',\n 'resourceId',\n 'runId',\n 'sessionId',\n 'threadId',\n 'requestId',\n 'experimentId',\n 'spanType',\n 'entityName',\n 'parentEntityType',\n 'parentEntityId',\n 'parentEntityName',\n 'rootEntityType',\n 'rootEntityId',\n 'rootEntityName',\n] as const;\n"],"names":[],"mappings":";;;;AAmDO,MAAM,iBAAA,GAAoB;AAAA,EAC/B,aAAA;AAAA,EACA,aAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,gBAAA;AAAA,EACA,YAAA;AAAA,EACA,OAAA;AAAA,EACA,WAAA;AAAA,EACA,UAAA;AAAA,EACA,WAAA;AAAA,EACA,cAAA;AAAA,EACA,UAAA;AAAA,EACA,YAAA;AAAA,EACA,kBAAA;AAAA,EACA,gBAAA;AAAA,EACA,kBAAA;AAAA,EACA,gBAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.es.js","sources":["../../../src/domains/traces/types.ts"],"sourcesContent":["import type { EntityType } from '@mastra/core/observability';\nimport type { ReactNode } from 'react';\n\nexport type UISpan = {\n id: string;\n name: string;\n type: string;\n latency: number;\n startTime: string;\n endTime?: string;\n spans?: UISpan[];\n parentSpanId?: string | null;\n};\n\nexport type UISpanStyle = {\n icon?: ReactNode;\n color?: string;\n label?: string;\n typePrefix: string;\n};\n\n// -- Trace filtering types ----------------------------------------------------\n\nexport type EntityOptions =\n | { value: string; label: string; type: EntityType.AGENT }\n | { value: string; label: string; type: EntityType.WORKFLOW_RUN }\n | { value: string; label: string; type: 'all' };\n\nexport type TraceDatePreset = 'all' | 'last-24h' | 'last-3d' | 'last-7d' | 'last-14d' | 'last-30d' | 'custom';\n\n/** Tab identifier for SpanDataPanelView. */\nexport type SpanTab = 'details' | 'feedback';\n\n/** Canonical list of context field IDs used for trace filtering and value extraction */\nexport const CONTEXT_FIELD_IDS = [\n 'environment',\n 'serviceName',\n 'source',\n 'scope',\n 'userId',\n 'organizationId',\n 'resourceId',\n 'runId',\n 'sessionId',\n 'threadId',\n 'requestId',\n 'experimentId',\n 'spanType',\n 'entityName',\n 'parentEntityType',\n 'parentEntityId',\n 'parentEntityName',\n 'rootEntityType',\n 'rootEntityId',\n 'rootEntityName',\n] as const;\n"],"names":[],"mappings":"AAkCO,MAAM,iBAAA,GAAoB;AAAA,EAC/B,aAAA;AAAA,EACA,aAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,gBAAA;AAAA,EACA,YAAA;AAAA,EACA,OAAA;AAAA,EACA,WAAA;AAAA,EACA,UAAA;AAAA,EACA,WAAA;AAAA,EACA,cAAA;AAAA,EACA,UAAA;AAAA,EACA,YAAA;AAAA,EACA,kBAAA;AAAA,EACA,gBAAA;AAAA,EACA,kBAAA;AAAA,EACA,gBAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF;;;;"}
1
+ {"version":3,"file":"types.es.js","sources":["../../../src/domains/traces/types.ts"],"sourcesContent":["import type { EntityType } from '@mastra/core/observability';\nimport type { LightSpanRecord } from '@mastra/core/storage';\nimport type { ReactNode } from 'react';\n\n/**\n * A light span carrying a precomputed haystack of everything it holds.\n *\n * `LightSpanRecord` exposes searchable content across a fixed set of columns\n * plus open-ended payloads whose shape is unknown, so a search cannot read it\n * field by field. `searchText` is that content flattened once — see\n * `flattenToSearchText` — so filtering is a substring test per span instead of\n * a re-walk of every payload on every keystroke.\n *\n * It holds field names as well as values, so a span is findable by the shape of\n * its payload and not only by its content.\n */\nexport type SearchableSpan = LightSpanRecord & {\n searchText: string;\n};\n\nexport type UISpan = {\n id: string;\n name: string;\n type: string;\n latency: number;\n startTime: string;\n endTime?: string;\n spans?: UISpan[];\n parentSpanId?: string | null;\n};\n\nexport type UISpanStyle = {\n icon?: ReactNode;\n color?: string;\n label?: string;\n typePrefix: string;\n};\n\n// -- Trace filtering types ----------------------------------------------------\n\nexport type EntityOptions =\n | { value: string; label: string; type: EntityType.AGENT }\n | { value: string; label: string; type: EntityType.WORKFLOW_RUN }\n | { value: string; label: string; type: 'all' };\n\nexport type TraceDatePreset = 'all' | 'last-24h' | 'last-3d' | 'last-7d' | 'last-14d' | 'last-30d' | 'custom';\n\n/** Tab identifier for SpanDataPanelView. */\nexport type SpanTab = 'details' | 'feedback';\n\n/** Canonical list of context field IDs used for trace filtering and value extraction */\nexport const CONTEXT_FIELD_IDS = [\n 'environment',\n 'serviceName',\n 'source',\n 'scope',\n 'userId',\n 'organizationId',\n 'resourceId',\n 'runId',\n 'sessionId',\n 'threadId',\n 'requestId',\n 'experimentId',\n 'spanType',\n 'entityName',\n 'parentEntityType',\n 'parentEntityId',\n 'parentEntityName',\n 'rootEntityType',\n 'rootEntityId',\n 'rootEntityName',\n] as const;\n"],"names":[],"mappings":"AAmDO,MAAM,iBAAA,GAAoB;AAAA,EAC/B,aAAA;AAAA,EACA,aAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,gBAAA;AAAA,EACA,YAAA;AAAA,EACA,OAAA;AAAA,EACA,WAAA;AAAA,EACA,UAAA;AAAA,EACA,WAAA;AAAA,EACA,cAAA;AAAA,EACA,UAAA;AAAA,EACA,YAAA;AAAA,EACA,kBAAA;AAAA,EACA,gBAAA;AAAA,EACA,kBAAA;AAAA,EACA,gBAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF;;;;"}
@@ -0,0 +1,47 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
+
5
+ function filterSpansKeepingAncestors(spans, predicate) {
6
+ if (!spans || spans.length === 0) {
7
+ return [];
8
+ }
9
+ const byId = /* @__PURE__ */ new Map();
10
+ const childrenByParent = /* @__PURE__ */ new Map();
11
+ const matches = [];
12
+ for (const span of spans) {
13
+ if (!span) continue;
14
+ byId.set(span.spanId, span);
15
+ if (span.parentSpanId) {
16
+ const siblings = childrenByParent.get(span.parentSpanId);
17
+ if (siblings) siblings.push(span);
18
+ else childrenByParent.set(span.parentSpanId, [span]);
19
+ }
20
+ if (predicate(span)) matches.push(span);
21
+ }
22
+ if (matches.length === 0) {
23
+ return [];
24
+ }
25
+ const kept = /* @__PURE__ */ new Set();
26
+ const stack = [...matches];
27
+ while (stack.length > 0) {
28
+ const span = stack.pop();
29
+ if (!span || kept.has(span.spanId)) continue;
30
+ kept.add(span.spanId);
31
+ const children = childrenByParent.get(span.spanId);
32
+ if (children) stack.push(...children);
33
+ }
34
+ for (const match of matches) {
35
+ let parentSpanId = match.parentSpanId;
36
+ while (parentSpanId && !kept.has(parentSpanId)) {
37
+ const parent = byId.get(parentSpanId);
38
+ if (!parent) break;
39
+ kept.add(parent.spanId);
40
+ parentSpanId = parent.parentSpanId;
41
+ }
42
+ }
43
+ return spans.filter((span) => span && kept.has(span.spanId));
44
+ }
45
+
46
+ exports.filterSpansKeepingAncestors = filterSpansKeepingAncestors;
47
+ //# sourceMappingURL=filter-spans-keeping-ancestors.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-spans-keeping-ancestors.cjs.js","sources":["../../../../src/domains/traces/utils/filter-spans-keeping-ancestors.ts"],"sourcesContent":["import type { LightSpanRecord } from '@mastra/core/storage';\n\n/**\n * Filter a flat span list down to the spans matching `predicate`, plus every\n * ancestor needed to keep those spans connected to their root, plus the whole\n * subtree below each match — a matching span is shown intact, not truncated.\n *\n * `spans` may arrive in any order. Trace payloads are flat lists sorted by\n * `startedAt` (and the list API defaults to `direction: 'DESC'`), so children\n * routinely precede their parents; the traversal below indexes the list up\n * front rather than assuming a topological order.\n *\n * The output preserves the input's relative order, so it can be fed straight\n * into `formatHierarchicalSpans`. `predicate` is called exactly once per span.\n *\n * Generic over the span type: only `spanId` and `parentSpanId` are read, and the\n * exact input type comes back out, so enriched spans such as `SearchableSpan`\n * survive the filter instead of being widened to `LightSpanRecord`.\n */\nexport function filterSpansKeepingAncestors<T extends Pick<LightSpanRecord, 'spanId' | 'parentSpanId'>>(\n spans: T[],\n predicate: (span: T) => boolean,\n): T[] {\n if (!spans || spans.length === 0) {\n return [];\n }\n\n const byId = new Map<string, T>();\n const childrenByParent = new Map<string, T[]>();\n const matches: T[] = [];\n\n for (const span of spans) {\n if (!span) continue;\n\n byId.set(span.spanId, span);\n\n if (span.parentSpanId) {\n const siblings = childrenByParent.get(span.parentSpanId);\n if (siblings) siblings.push(span);\n else childrenByParent.set(span.parentSpanId, [span]);\n }\n\n if (predicate(span)) matches.push(span);\n }\n\n if (matches.length === 0) {\n return [];\n }\n\n const kept = new Set<string>();\n\n // Downwards: every descendant of every match. `kept` doubles as the visited\n // set, so cycles and self-parented spans terminate.\n const stack = [...matches];\n while (stack.length > 0) {\n const span = stack.pop();\n if (!span || kept.has(span.spanId)) continue;\n\n kept.add(span.spanId);\n\n const children = childrenByParent.get(span.spanId);\n if (children) stack.push(...children);\n }\n\n // Upwards: the ancestor chain of every match, stopping at the first span\n // already kept or at a parent that isn't in the list (branch boundary).\n for (const match of matches) {\n let parentSpanId = match.parentSpanId;\n\n while (parentSpanId && !kept.has(parentSpanId)) {\n const parent = byId.get(parentSpanId);\n if (!parent) break;\n\n kept.add(parent.spanId);\n parentSpanId = parent.parentSpanId;\n }\n }\n\n return spans.filter(span => span && kept.has(span.spanId));\n}\n"],"names":[],"mappings":";;;;AAmBO,SAAS,2BAAA,CACd,OACA,SAAA,EACK;AACL,EAAA,IAAI,CAAC,KAAA,IAAS,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG;AAChC,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAe;AAChC,EAAA,MAAM,gBAAA,uBAAuB,GAAA,EAAiB;AAC9C,EAAA,MAAM,UAAe,EAAC;AAEtB,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,IAAI,CAAC,IAAA,EAAM;AAEX,IAAA,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,MAAA,EAAQ,IAAI,CAAA;AAE1B,IAAA,IAAI,KAAK,YAAA,EAAc;AACrB,MAAA,MAAM,QAAA,GAAW,gBAAA,CAAiB,GAAA,CAAI,IAAA,CAAK,YAAY,CAAA;AACvD,MAAA,IAAI,QAAA,EAAU,QAAA,CAAS,IAAA,CAAK,IAAI,CAAA;AAAA,4BACV,GAAA,CAAI,IAAA,CAAK,YAAA,EAAc,CAAC,IAAI,CAAC,CAAA;AAAA,IACrD;AAEA,IAAA,IAAI,SAAA,CAAU,IAAI,CAAA,EAAG,OAAA,CAAQ,KAAK,IAAI,CAAA;AAAA,EACxC;AAEA,EAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAI7B,EAAA,MAAM,KAAA,GAAQ,CAAC,GAAG,OAAO,CAAA;AACzB,EAAA,OAAO,KAAA,CAAM,SAAS,CAAA,EAAG;AACvB,IAAA,MAAM,IAAA,GAAO,MAAM,GAAA,EAAI;AACvB,IAAA,IAAI,CAAC,IAAA,IAAQ,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,MAAM,CAAA,EAAG;AAEpC,IAAA,IAAA,CAAK,GAAA,CAAI,KAAK,MAAM,CAAA;AAEpB,IAAA,MAAM,QAAA,GAAW,gBAAA,CAAiB,GAAA,CAAI,IAAA,CAAK,MAAM,CAAA;AACjD,IAAA,IAAI,QAAA,EAAU,KAAA,CAAM,IAAA,CAAK,GAAG,QAAQ,CAAA;AAAA,EACtC;AAIA,EAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,IAAA,IAAI,eAAe,KAAA,CAAM,YAAA;AAEzB,IAAA,OAAO,YAAA,IAAgB,CAAC,IAAA,CAAK,GAAA,CAAI,YAAY,CAAA,EAAG;AAC9C,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,YAAY,CAAA;AACpC,MAAA,IAAI,CAAC,MAAA,EAAQ;AAEb,MAAA,IAAA,CAAK,GAAA,CAAI,OAAO,MAAM,CAAA;AACtB,MAAA,YAAA,GAAe,MAAA,CAAO,YAAA;AAAA,IACxB;AAAA,EACF;AAEA,EAAA,OAAO,KAAA,CAAM,OAAO,CAAA,IAAA,KAAQ,IAAA,IAAQ,KAAK,GAAA,CAAI,IAAA,CAAK,MAAM,CAAC,CAAA;AAC3D;;;;"}
@@ -0,0 +1,2 @@
1
+ export * from '../../../src/domains/traces/utils/filter-spans-keeping-ancestors'
2
+ export {}
@@ -0,0 +1,43 @@
1
+ function filterSpansKeepingAncestors(spans, predicate) {
2
+ if (!spans || spans.length === 0) {
3
+ return [];
4
+ }
5
+ const byId = /* @__PURE__ */ new Map();
6
+ const childrenByParent = /* @__PURE__ */ new Map();
7
+ const matches = [];
8
+ for (const span of spans) {
9
+ if (!span) continue;
10
+ byId.set(span.spanId, span);
11
+ if (span.parentSpanId) {
12
+ const siblings = childrenByParent.get(span.parentSpanId);
13
+ if (siblings) siblings.push(span);
14
+ else childrenByParent.set(span.parentSpanId, [span]);
15
+ }
16
+ if (predicate(span)) matches.push(span);
17
+ }
18
+ if (matches.length === 0) {
19
+ return [];
20
+ }
21
+ const kept = /* @__PURE__ */ new Set();
22
+ const stack = [...matches];
23
+ while (stack.length > 0) {
24
+ const span = stack.pop();
25
+ if (!span || kept.has(span.spanId)) continue;
26
+ kept.add(span.spanId);
27
+ const children = childrenByParent.get(span.spanId);
28
+ if (children) stack.push(...children);
29
+ }
30
+ for (const match of matches) {
31
+ let parentSpanId = match.parentSpanId;
32
+ while (parentSpanId && !kept.has(parentSpanId)) {
33
+ const parent = byId.get(parentSpanId);
34
+ if (!parent) break;
35
+ kept.add(parent.spanId);
36
+ parentSpanId = parent.parentSpanId;
37
+ }
38
+ }
39
+ return spans.filter((span) => span && kept.has(span.spanId));
40
+ }
41
+
42
+ export { filterSpansKeepingAncestors };
43
+ //# sourceMappingURL=filter-spans-keeping-ancestors.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-spans-keeping-ancestors.es.js","sources":["../../../../src/domains/traces/utils/filter-spans-keeping-ancestors.ts"],"sourcesContent":["import type { LightSpanRecord } from '@mastra/core/storage';\n\n/**\n * Filter a flat span list down to the spans matching `predicate`, plus every\n * ancestor needed to keep those spans connected to their root, plus the whole\n * subtree below each match — a matching span is shown intact, not truncated.\n *\n * `spans` may arrive in any order. Trace payloads are flat lists sorted by\n * `startedAt` (and the list API defaults to `direction: 'DESC'`), so children\n * routinely precede their parents; the traversal below indexes the list up\n * front rather than assuming a topological order.\n *\n * The output preserves the input's relative order, so it can be fed straight\n * into `formatHierarchicalSpans`. `predicate` is called exactly once per span.\n *\n * Generic over the span type: only `spanId` and `parentSpanId` are read, and the\n * exact input type comes back out, so enriched spans such as `SearchableSpan`\n * survive the filter instead of being widened to `LightSpanRecord`.\n */\nexport function filterSpansKeepingAncestors<T extends Pick<LightSpanRecord, 'spanId' | 'parentSpanId'>>(\n spans: T[],\n predicate: (span: T) => boolean,\n): T[] {\n if (!spans || spans.length === 0) {\n return [];\n }\n\n const byId = new Map<string, T>();\n const childrenByParent = new Map<string, T[]>();\n const matches: T[] = [];\n\n for (const span of spans) {\n if (!span) continue;\n\n byId.set(span.spanId, span);\n\n if (span.parentSpanId) {\n const siblings = childrenByParent.get(span.parentSpanId);\n if (siblings) siblings.push(span);\n else childrenByParent.set(span.parentSpanId, [span]);\n }\n\n if (predicate(span)) matches.push(span);\n }\n\n if (matches.length === 0) {\n return [];\n }\n\n const kept = new Set<string>();\n\n // Downwards: every descendant of every match. `kept` doubles as the visited\n // set, so cycles and self-parented spans terminate.\n const stack = [...matches];\n while (stack.length > 0) {\n const span = stack.pop();\n if (!span || kept.has(span.spanId)) continue;\n\n kept.add(span.spanId);\n\n const children = childrenByParent.get(span.spanId);\n if (children) stack.push(...children);\n }\n\n // Upwards: the ancestor chain of every match, stopping at the first span\n // already kept or at a parent that isn't in the list (branch boundary).\n for (const match of matches) {\n let parentSpanId = match.parentSpanId;\n\n while (parentSpanId && !kept.has(parentSpanId)) {\n const parent = byId.get(parentSpanId);\n if (!parent) break;\n\n kept.add(parent.spanId);\n parentSpanId = parent.parentSpanId;\n }\n }\n\n return spans.filter(span => span && kept.has(span.spanId));\n}\n"],"names":[],"mappings":"AAmBO,SAAS,2BAAA,CACd,OACA,SAAA,EACK;AACL,EAAA,IAAI,CAAC,KAAA,IAAS,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG;AAChC,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAe;AAChC,EAAA,MAAM,gBAAA,uBAAuB,GAAA,EAAiB;AAC9C,EAAA,MAAM,UAAe,EAAC;AAEtB,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,IAAI,CAAC,IAAA,EAAM;AAEX,IAAA,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,MAAA,EAAQ,IAAI,CAAA;AAE1B,IAAA,IAAI,KAAK,YAAA,EAAc;AACrB,MAAA,MAAM,QAAA,GAAW,gBAAA,CAAiB,GAAA,CAAI,IAAA,CAAK,YAAY,CAAA;AACvD,MAAA,IAAI,QAAA,EAAU,QAAA,CAAS,IAAA,CAAK,IAAI,CAAA;AAAA,4BACV,GAAA,CAAI,IAAA,CAAK,YAAA,EAAc,CAAC,IAAI,CAAC,CAAA;AAAA,IACrD;AAEA,IAAA,IAAI,SAAA,CAAU,IAAI,CAAA,EAAG,OAAA,CAAQ,KAAK,IAAI,CAAA;AAAA,EACxC;AAEA,EAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAI7B,EAAA,MAAM,KAAA,GAAQ,CAAC,GAAG,OAAO,CAAA;AACzB,EAAA,OAAO,KAAA,CAAM,SAAS,CAAA,EAAG;AACvB,IAAA,MAAM,IAAA,GAAO,MAAM,GAAA,EAAI;AACvB,IAAA,IAAI,CAAC,IAAA,IAAQ,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,MAAM,CAAA,EAAG;AAEpC,IAAA,IAAA,CAAK,GAAA,CAAI,KAAK,MAAM,CAAA;AAEpB,IAAA,MAAM,QAAA,GAAW,gBAAA,CAAiB,GAAA,CAAI,IAAA,CAAK,MAAM,CAAA;AACjD,IAAA,IAAI,QAAA,EAAU,KAAA,CAAM,IAAA,CAAK,GAAG,QAAQ,CAAA;AAAA,EACtC;AAIA,EAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,IAAA,IAAI,eAAe,KAAA,CAAM,YAAA;AAEzB,IAAA,OAAO,YAAA,IAAgB,CAAC,IAAA,CAAK,GAAA,CAAI,YAAY,CAAA,EAAG;AAC9C,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,YAAY,CAAA;AACpC,MAAA,IAAI,CAAC,MAAA,EAAQ;AAEb,MAAA,IAAA,CAAK,GAAA,CAAI,OAAO,MAAM,CAAA;AACtB,MAAA,YAAA,GAAe,MAAA,CAAO,YAAA;AAAA,IACxB;AAAA,EACF;AAEA,EAAA,OAAO,KAAA,CAAM,OAAO,CAAA,IAAA,KAAQ,IAAA,IAAQ,KAAK,GAAA,CAAI,IAAA,CAAK,MAAM,CAAC,CAAA;AAC3D;;;;"}
@@ -0,0 +1,78 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
+
5
+ function flattenToSearchText(value) {
6
+ const parts = [];
7
+ const path = /* @__PURE__ */ new Set();
8
+ collect(value, parts, path);
9
+ return parts.join(" ");
10
+ }
11
+ function collect(value, parts, path) {
12
+ if (value === null || value === void 0) return;
13
+ switch (typeof value) {
14
+ case "string": {
15
+ const trimmed = value.trim();
16
+ if (trimmed) parts.push(trimmed);
17
+ return;
18
+ }
19
+ case "number": {
20
+ if (Number.isFinite(value)) parts.push(String(value));
21
+ return;
22
+ }
23
+ case "boolean":
24
+ case "bigint":
25
+ parts.push(String(value));
26
+ return;
27
+ case "function":
28
+ case "symbol":
29
+ return;
30
+ }
31
+ const object = value;
32
+ if (path.has(object)) return;
33
+ path.add(object);
34
+ try {
35
+ collectFromObject(object, parts, path);
36
+ } finally {
37
+ path.delete(object);
38
+ }
39
+ }
40
+ function collectFromObject(object, parts, path) {
41
+ if (object instanceof Date) {
42
+ const time = object.getTime();
43
+ if (!Number.isNaN(time)) parts.push(object.toISOString());
44
+ return;
45
+ }
46
+ if (object instanceof Error) {
47
+ collect(object.message, parts, path);
48
+ return;
49
+ }
50
+ if (Array.isArray(object)) {
51
+ for (const item of object) collect(item, parts, path);
52
+ return;
53
+ }
54
+ if (object instanceof Map) {
55
+ for (const [key, item] of object) {
56
+ collect(key, parts, path);
57
+ collect(item, parts, path);
58
+ }
59
+ return;
60
+ }
61
+ if (object instanceof Set) {
62
+ for (const item of object) collect(item, parts, path);
63
+ return;
64
+ }
65
+ for (const key of Object.keys(object)) {
66
+ collect(key, parts, path);
67
+ let item;
68
+ try {
69
+ item = object[key];
70
+ } catch {
71
+ continue;
72
+ }
73
+ collect(item, parts, path);
74
+ }
75
+ }
76
+
77
+ exports.flattenToSearchText = flattenToSearchText;
78
+ //# sourceMappingURL=flatten-to-search-text.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flatten-to-search-text.cjs.js","sources":["../../../../src/domains/traces/utils/flatten-to-search-text.ts"],"sourcesContent":["/**\n * Flatten an arbitrary value into a single space-separated string containing\n * every searchable token it holds, however deeply nested.\n *\n * Built for span payloads whose shape is not known ahead of time (`attributes`,\n * `output`, `errorInfo`): the caller cannot enumerate fields, so this walks\n * whatever it is handed.\n *\n * **Keys are emitted alongside their values**, so a field name is searchable\n * even when its value is not — `{ error: null }` still answers a search for\n * `error`. The cost is that structural names present on every span (`traceId`,\n * `usage`, …) are searchable too, which makes short generic terms match widely.\n *\n * Values that no one can usefully search for are dropped rather than\n * stringified: `null`, `undefined`, `NaN`, infinities, functions, symbols,\n * invalid dates and whitespace-only strings. Dropping them keeps the output\n * free of noise words like `\"Invalid Date\"` that would produce false hits.\n * Array indices are dropped for the same reason — `0 1 2` is not content.\n *\n * Cycles are detected along the current path, so a self-referencing object\n * terminates while a value referenced twice as a sibling is emitted twice.\n * Only own, string-keyed properties are read, and a getter that throws is\n * skipped instead of taking the whole trace down.\n */\nexport function flattenToSearchText(value: unknown): string {\n const parts: string[] = [];\n const path = new Set<object>();\n\n collect(value, parts, path);\n\n return parts.join(' ');\n}\n\nfunction collect(value: unknown, parts: string[], path: Set<object>): void {\n if (value === null || value === undefined) return;\n\n switch (typeof value) {\n case 'string': {\n const trimmed = value.trim();\n if (trimmed) parts.push(trimmed);\n return;\n }\n case 'number': {\n // NaN and infinities have no useful search form.\n if (Number.isFinite(value)) parts.push(String(value));\n return;\n }\n case 'boolean':\n case 'bigint':\n parts.push(String(value));\n return;\n case 'function':\n case 'symbol':\n return;\n }\n\n const object = value as object;\n\n // Guard the current path only: a cycle must terminate, but the same object\n // referenced twice side by side is legitimately worth emitting twice.\n if (path.has(object)) return;\n path.add(object);\n\n try {\n collectFromObject(object, parts, path);\n } finally {\n path.delete(object);\n }\n}\n\nfunction collectFromObject(object: object, parts: string[], path: Set<object>): void {\n if (object instanceof Date) {\n const time = object.getTime();\n if (!Number.isNaN(time)) parts.push(object.toISOString());\n return;\n }\n\n if (object instanceof Error) {\n collect(object.message, parts, path);\n return;\n }\n\n // Indices carry no meaning, so an array contributes only its items.\n if (Array.isArray(object)) {\n for (const item of object) collect(item, parts, path);\n return;\n }\n\n if (object instanceof Map) {\n for (const [key, item] of object) {\n collect(key, parts, path);\n collect(item, parts, path);\n }\n return;\n }\n\n // A Set has members, not fields.\n if (object instanceof Set) {\n for (const item of object) collect(item, parts, path);\n return;\n }\n\n // Own string keys only: skips the prototype chain and symbol-keyed entries.\n for (const key of Object.keys(object)) {\n // The key is emitted even when the value turns out to be unsearchable, so\n // the presence of a field is itself findable.\n collect(key, parts, path);\n\n let item: unknown;\n try {\n item = (object as Record<string, unknown>)[key];\n } catch {\n // A getter that throws is not a reason to lose the rest of the payload.\n continue;\n }\n collect(item, parts, path);\n }\n}\n"],"names":[],"mappings":";;;;AAwBO,SAAS,oBAAoB,KAAA,EAAwB;AAC1D,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAE7B,EAAA,OAAA,CAAQ,KAAA,EAAO,OAAO,IAAI,CAAA;AAE1B,EAAA,OAAO,KAAA,CAAM,KAAK,GAAG,CAAA;AACvB;AAEA,SAAS,OAAA,CAAQ,KAAA,EAAgB,KAAA,EAAiB,IAAA,EAAyB;AACzE,EAAA,IAAI,KAAA,KAAU,IAAA,IAAQ,KAAA,KAAU,MAAA,EAAW;AAE3C,EAAA,QAAQ,OAAO,KAAA;AAAO,IACpB,KAAK,QAAA,EAAU;AACb,MAAA,MAAM,OAAA,GAAU,MAAM,IAAA,EAAK;AAC3B,MAAA,IAAI,OAAA,EAAS,KAAA,CAAM,IAAA,CAAK,OAAO,CAAA;AAC/B,MAAA;AAAA,IACF;AAAA,IACA,KAAK,QAAA,EAAU;AAEb,MAAA,IAAI,MAAA,CAAO,SAAS,KAAK,CAAA,QAAS,IAAA,CAAK,MAAA,CAAO,KAAK,CAAC,CAAA;AACpD,MAAA;AAAA,IACF;AAAA,IACA,KAAK,SAAA;AAAA,IACL,KAAK,QAAA;AACH,MAAA,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,KAAK,CAAC,CAAA;AACxB,MAAA;AAAA,IACF,KAAK,UAAA;AAAA,IACL,KAAK,QAAA;AACH,MAAA;AAAA;AAGJ,EAAA,MAAM,MAAA,GAAS,KAAA;AAIf,EAAA,IAAI,IAAA,CAAK,GAAA,CAAI,MAAM,CAAA,EAAG;AACtB,EAAA,IAAA,CAAK,IAAI,MAAM,CAAA;AAEf,EAAA,IAAI;AACF,IAAA,iBAAA,CAAkB,MAAA,EAAQ,OAAO,IAAI,CAAA;AAAA,EACvC,CAAA,SAAE;AACA,IAAA,IAAA,CAAK,OAAO,MAAM,CAAA;AAAA,EACpB;AACF;AAEA,SAAS,iBAAA,CAAkB,MAAA,EAAgB,KAAA,EAAiB,IAAA,EAAyB;AACnF,EAAA,IAAI,kBAAkB,IAAA,EAAM;AAC1B,IAAA,MAAM,IAAA,GAAO,OAAO,OAAA,EAAQ;AAC5B,IAAA,IAAI,CAAC,OAAO,KAAA,CAAM,IAAI,GAAG,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,WAAA,EAAa,CAAA;AACxD,IAAA;AAAA,EACF;AAEA,EAAA,IAAI,kBAAkB,KAAA,EAAO;AAC3B,IAAA,OAAA,CAAQ,MAAA,CAAO,OAAA,EAAS,KAAA,EAAO,IAAI,CAAA;AACnC,IAAA;AAAA,EACF;AAGA,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA,EAAG;AACzB,IAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,EAAQ,OAAA,CAAQ,IAAA,EAAM,OAAO,IAAI,CAAA;AACpD,IAAA;AAAA,EACF;AAEA,EAAA,IAAI,kBAAkB,GAAA,EAAK;AACzB,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,IAAI,CAAA,IAAK,MAAA,EAAQ;AAChC,MAAA,OAAA,CAAQ,GAAA,EAAK,OAAO,IAAI,CAAA;AACxB,MAAA,OAAA,CAAQ,IAAA,EAAM,OAAO,IAAI,CAAA;AAAA,IAC3B;AACA,IAAA;AAAA,EACF;AAGA,EAAA,IAAI,kBAAkB,GAAA,EAAK;AACzB,IAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,EAAQ,OAAA,CAAQ,IAAA,EAAM,OAAO,IAAI,CAAA;AACpD,IAAA;AAAA,EACF;AAGA,EAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,EAAG;AAGrC,IAAA,OAAA,CAAQ,GAAA,EAAK,OAAO,IAAI,CAAA;AAExB,IAAA,IAAI,IAAA;AACJ,IAAA,IAAI;AACF,MAAA,IAAA,GAAQ,OAAmC,GAAG,CAAA;AAAA,IAChD,CAAA,CAAA,MAAQ;AAEN,MAAA;AAAA,IACF;AACA,IAAA,OAAA,CAAQ,IAAA,EAAM,OAAO,IAAI,CAAA;AAAA,EAC3B;AACF;;;;"}
@@ -0,0 +1,2 @@
1
+ export * from '../../../src/domains/traces/utils/flatten-to-search-text'
2
+ export {}
@@ -0,0 +1,74 @@
1
+ function flattenToSearchText(value) {
2
+ const parts = [];
3
+ const path = /* @__PURE__ */ new Set();
4
+ collect(value, parts, path);
5
+ return parts.join(" ");
6
+ }
7
+ function collect(value, parts, path) {
8
+ if (value === null || value === void 0) return;
9
+ switch (typeof value) {
10
+ case "string": {
11
+ const trimmed = value.trim();
12
+ if (trimmed) parts.push(trimmed);
13
+ return;
14
+ }
15
+ case "number": {
16
+ if (Number.isFinite(value)) parts.push(String(value));
17
+ return;
18
+ }
19
+ case "boolean":
20
+ case "bigint":
21
+ parts.push(String(value));
22
+ return;
23
+ case "function":
24
+ case "symbol":
25
+ return;
26
+ }
27
+ const object = value;
28
+ if (path.has(object)) return;
29
+ path.add(object);
30
+ try {
31
+ collectFromObject(object, parts, path);
32
+ } finally {
33
+ path.delete(object);
34
+ }
35
+ }
36
+ function collectFromObject(object, parts, path) {
37
+ if (object instanceof Date) {
38
+ const time = object.getTime();
39
+ if (!Number.isNaN(time)) parts.push(object.toISOString());
40
+ return;
41
+ }
42
+ if (object instanceof Error) {
43
+ collect(object.message, parts, path);
44
+ return;
45
+ }
46
+ if (Array.isArray(object)) {
47
+ for (const item of object) collect(item, parts, path);
48
+ return;
49
+ }
50
+ if (object instanceof Map) {
51
+ for (const [key, item] of object) {
52
+ collect(key, parts, path);
53
+ collect(item, parts, path);
54
+ }
55
+ return;
56
+ }
57
+ if (object instanceof Set) {
58
+ for (const item of object) collect(item, parts, path);
59
+ return;
60
+ }
61
+ for (const key of Object.keys(object)) {
62
+ collect(key, parts, path);
63
+ let item;
64
+ try {
65
+ item = object[key];
66
+ } catch {
67
+ continue;
68
+ }
69
+ collect(item, parts, path);
70
+ }
71
+ }
72
+
73
+ export { flattenToSearchText };
74
+ //# sourceMappingURL=flatten-to-search-text.es.js.map