@mastra/playground-ui 66.0.0-alpha.5 → 66.0.0-alpha.6

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 (27) hide show
  1. package/dist/domains/threads/components/threads-explorer-body.cjs.js +2 -0
  2. package/dist/domains/threads/components/threads-explorer-body.cjs.js.map +1 -1
  3. package/dist/domains/threads/components/threads-explorer-body.es.js +2 -0
  4. package/dist/domains/threads/components/threads-explorer-body.es.js.map +1 -1
  5. package/dist/domains/threads/thread-filters.cjs.js +5 -3
  6. package/dist/domains/threads/thread-filters.cjs.js.map +1 -1
  7. package/dist/domains/threads/thread-filters.es.js +5 -3
  8. package/dist/domains/threads/thread-filters.es.js.map +1 -1
  9. package/dist/domains/threads/thread-list-row.cjs.js +1 -0
  10. package/dist/domains/threads/thread-list-row.cjs.js.map +1 -1
  11. package/dist/domains/threads/thread-list-row.es.js +1 -0
  12. package/dist/domains/threads/thread-list-row.es.js.map +1 -1
  13. package/dist/domains/traces/components/trace-columns-menu.cjs.js +1 -0
  14. package/dist/domains/traces/components/trace-columns-menu.cjs.js.map +1 -1
  15. package/dist/domains/traces/components/trace-columns-menu.es.js +1 -0
  16. package/dist/domains/traces/components/trace-columns-menu.es.js.map +1 -1
  17. package/dist/domains/traces/components/traces-list-view.cjs.js +6 -0
  18. package/dist/domains/traces/components/traces-list-view.cjs.js.map +1 -1
  19. package/dist/domains/traces/components/traces-list-view.es.js +6 -0
  20. package/dist/domains/traces/components/traces-list-view.es.js.map +1 -1
  21. package/dist/domains/traces/trace-list-columns.cjs.js +9 -0
  22. package/dist/domains/traces/trace-list-columns.cjs.js.map +1 -1
  23. package/dist/domains/traces/trace-list-columns.es.js +9 -1
  24. package/dist/domains/traces/trace-list-columns.es.js.map +1 -1
  25. package/dist/src/domains/traces/components/traces-list-view.d.ts +2 -0
  26. package/dist/src/domains/traces/trace-list-columns.d.ts +3 -1
  27. package/package.json +6 -6
@@ -1,6 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_domains_observability_components_observability_list_body = require("../../observability/components/observability-list-body.cjs.js");
3
3
  const require_domains_observability_hooks_use_observability_list_filters = require("../../observability/hooks/use-observability-list-filters.cjs.js");
4
+ const require_domains_traces_trace_list_columns = require("../../traces/trace-list-columns.cjs.js");
4
5
  const require_domains_traces_components_no_traces_info = require("../../traces/components/no-traces-info.cjs.js");
5
6
  const require_domains_traces_components_traces_error_content = require("../../traces/components/traces-error-content.cjs.js");
6
7
  const require_domains_traces_components_traces_list_view = require("../../traces/components/traces-list-view.cjs.js");
@@ -77,6 +78,7 @@ function ThreadsExplorerBody({ selectedThreadId, onSelectedThreadChange, onOpenS
77
78
  }) : void 0,
78
79
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_domains_traces_components_traces_list_view.TracesListView, {
79
80
  listId: "all-threads",
81
+ columnPreferences: require_domains_traces_trace_list_columns.THREAD_LIST_COLUMN_PREFERENCES,
80
82
  traces: rows,
81
83
  isLoading,
82
84
  isFetchingNextPage,
@@ -1 +1 @@
1
- {"version":3,"file":"threads-explorer-body.cjs.js","names":["useObservabilityListFilters","useTraceQueryAvailable","useFeedbackAvailable","useMemo","buildThreadQueryWhere","useThreadsListSource","threadToListRow","_Fragment","ObservabilityListBody","ActionRow","ThreadsFilterBar","TracesErrorContent","NoTracesInfo","TracesListView","TraceThreadPanel"],"sources":["../../../../src/domains/threads/components/threads-explorer-body.tsx"],"sourcesContent":["import type { ThreadQueryArgs } from '@mastra/react/hooks/traces';\nimport { useMemo } from 'react';\nimport { useThreadsListSource } from '../hooks/use-threads-list-source';\nimport { buildThreadQueryWhere } from '../thread-filters';\nimport { threadToListRow } from '../thread-list-row';\nimport { ThreadsFilterBar } from './threads-filter-bar';\nimport { useFeedbackAvailable, useTraceQueryAvailable } from '@/domains/capabilities';\nimport { ObservabilityListBody } from '@/domains/observability/components/observability-list-body';\nimport { useObservabilityListFilters } from '@/domains/observability/hooks/use-observability-list-filters';\nimport { NoTracesInfo } from '@/domains/traces/components/no-traces-info';\nimport { TraceThreadPanel } from '@/domains/traces/components/trace-thread-panel';\nimport { TracesErrorContent } from '@/domains/traces/components/traces-error-content';\nimport { TracesListView } from '@/domains/traces/components/traces-list-view';\nimport type { TracesListViewTrace } from '@/domains/traces/components/traces-list-view';\nimport { ActionRow } from '@/ds/components/ActionRow';\n\nexport type ThreadsExplorerBodyProps = {\n /** The open thread. The host keeps it (e.g. in the URL) so it survives a reload. */\n selectedThreadId: string | undefined;\n onSelectedThreadChange: (threadId: string | undefined) => void;\n /** Opens a score from the thread drawer; scores live on host routes. */\n onOpenScore: (traceId: string, scoreId: string) => void;\n};\n\n/** The threads page body: filter bar, thread list and the thread drawer. Router-agnostic. */\nexport function ThreadsExplorerBody({\n selectedThreadId,\n onSelectedThreadChange,\n onOpenScore,\n}: ThreadsExplorerBodyProps) {\n const filters = useObservabilityListFilters();\n const { timeRange, tokens, groups, sort } = filters;\n const withQueryTrace = useTraceQueryAvailable().enabled;\n const withFeedback = useFeedbackAvailable().enabled;\n\n // Threads with trace activity in the window, like the traces list for the same chip.\n const query = useMemo<ThreadQueryArgs>(() => {\n const where = buildThreadQueryWhere(tokens, groups);\n return {\n timeRange: { traces: timeRange },\n orderBy: [{ field: 'startedAt', direction: sort }],\n ...(where ? { where } : {}),\n };\n }, [timeRange, sort, tokens, groups]);\n\n const { threads, hasNextPage, isFetchingNextPage, setEndOfListElement, isLoading, isError, error } =\n useThreadsListSource({ query, rolling: filters.rolling });\n\n const rows = useMemo(() => (threads ?? []).map(threadToListRow), [threads]);\n const selectedRow = rows.find(row => row.threadId === selectedThreadId);\n\n // The drawer is modal, so the list behind it cannot be clicked while a thread is open.\n const handleThreadClick = (row: TracesListViewTrace) => {\n if (row.threadId) onSelectedThreadChange(row.threadId);\n };\n\n // Same rule as /traces: an empty window without filters gets the full-page empty state.\n const showEmptyState =\n !isLoading && !isError && rows.length === 0 && !filters.contentFiltersApplied && !selectedThreadId;\n\n return (\n <>\n <h1 className=\"sr-only\">Threads</h1>\n <ObservabilityListBody\n toolbar={\n <ActionRow>\n <ActionRow.Start>\n <ThreadsFilterBar\n datePreset={filters.datePreset}\n dateFrom={filters.dateFrom}\n dateTo={filters.dateTo}\n tokens={tokens}\n groups={groups}\n onDatePresetChange={filters.onDatePresetChange}\n onDateChange={filters.onDateChange}\n onDateRangeChange={filters.onDateRangeChange}\n onFiltersChange={filters.onFiltersChange}\n disabled={isLoading}\n />\n </ActionRow.Start>\n </ActionRow>\n }\n error={\n isError ? (\n <TracesErrorContent error={error} resource=\"threads\" errorTitle=\"Failed to load threads\" />\n ) : undefined\n }\n empty={\n showEmptyState ? (\n <NoTracesInfo\n resource=\"threads\"\n datePreset={filters.datePreset}\n dateFrom={filters.dateFrom}\n dateTo={filters.dateTo}\n />\n ) : undefined\n }\n >\n <TracesListView\n listId=\"all-threads\"\n traces={rows}\n isLoading={isLoading}\n isFetchingNextPage={isFetchingNextPage}\n hasNextPage={hasNextPage}\n setEndOfListElement={setEndOfListElement}\n filtersApplied={filters.filtersApplied}\n resource=\"threads\"\n createdSort={sort}\n onSortChange={filters.setSort}\n featuredTraceId={selectedRow?.traceId}\n onTraceClick={handleThreadClick}\n />\n </ObservabilityListBody>\n <TraceThreadPanel\n open={!!selectedThreadId}\n threadId={selectedThreadId ?? ''}\n depth={1}\n closeLabel=\"Close\"\n withQueryTrace={withQueryTrace}\n withFeedback={withFeedback}\n onOpenScore={onOpenScore}\n onClose={() => onSelectedThreadChange(undefined)}\n />\n </>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAyBA,SAAgB,oBAAoB,EAClC,kBACA,wBACA,eAC2B;CAC3B,MAAM,UAAUA,mEAAAA,4BAA4B;CAC5C,MAAM,EAAE,WAAW,QAAQ,QAAQ,SAAS;CAC5C,MAAM,kBAAA,GAAiBC,iCAAAA,uBAAAA,CAAuB,CAAC,CAAC;CAChD,MAAM,gBAAA,GAAeC,iCAAAA,qBAAAA,CAAqB,CAAC,CAAC;CAG5C,MAAM,SAAA,GAAQC,MAAAA,QAAAA,OAA+B;EAC3C,MAAM,QAAQC,uCAAAA,sBAAsB,QAAQ,MAAM;EAClD,OAAO;GACL,WAAW,EAAE,QAAQ,UAAU;GAC/B,SAAS,CAAC;IAAE,OAAO;IAAa,WAAW;GAAK,CAAC;GACjD,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;EAC3B;CACF,GAAG;EAAC;EAAW;EAAM;EAAQ;CAAM,CAAC;CAEpC,MAAM,EAAE,SAAS,aAAa,oBAAoB,qBAAqB,WAAW,SAAS,UACzFC,sDAAAA,qBAAqB;EAAE;EAAO,SAAS,QAAQ;CAAQ,CAAC;CAE1D,MAAM,QAAA,GAAOF,MAAAA,QAAAA,QAAe,WAAW,CAAC,EAAA,CAAG,IAAIG,wCAAAA,eAAe,GAAG,CAAC,OAAO,CAAC;CAC1E,MAAM,cAAc,KAAK,MAAK,QAAO,IAAI,aAAa,gBAAgB;CAGtE,MAAM,qBAAqB,QAA6B;EACtD,IAAI,IAAI,UAAU,uBAAuB,IAAI,QAAQ;CACvD;CAGA,MAAM,iBACJ,CAAC,aAAa,CAAC,WAAW,KAAK,WAAW,KAAK,CAAC,QAAQ,yBAAyB,CAAC;CAEpF,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAAC,kBAAAA,UAAA,EAAA,UAAA;EACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD;GAAI,WAAU;GAAU,UAAA;EAAW,CAAA;EACnC,iBAAA,GAAA,kBAAA,IAAA,CAACC,iEAAAA,uBAAD;GACE,SACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,kBAAAA,WAAD,EAAA,UACE,iBAAA,GAAA,kBAAA,IAAA,CAACA,kBAAAA,UAAU,OAAX,EAAA,UACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,sDAAAA,kBAAD;IACE,YAAY,QAAQ;IACpB,UAAU,QAAQ;IAClB,QAAQ,QAAQ;IACR;IACA;IACR,oBAAoB,QAAQ;IAC5B,cAAc,QAAQ;IACtB,mBAAmB,QAAQ;IAC3B,iBAAiB,QAAQ;IACzB,UAAU;GACX,CAAA,EACc,CAAA,EACR,CAAA;GAEb,OACE,UACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,uDAAAA,oBAAD;IAA2B;IAAO,UAAS;IAAU,YAAW;GAA0B,CAAA,IACxF,KAAA;GAEN,OACE,iBACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,iDAAAA,cAAD;IACE,UAAS;IACT,YAAY,QAAQ;IACpB,UAAU,QAAQ;IAClB,QAAQ,QAAQ;GACjB,CAAA,IACC,KAAA;GAGN,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAACC,mDAAAA,gBAAD;IACE,QAAO;IACP,QAAQ;IACG;IACS;IACP;IACQ;IACrB,gBAAgB,QAAQ;IACxB,UAAS;IACT,aAAa;IACb,cAAc,QAAQ;IACtB,iBAAiB,aAAa;IAC9B,cAAc;GACf,CAAA;EACoB,CAAA;EACvB,iBAAA,GAAA,kBAAA,IAAA,CAACC,qDAAAA,kBAAD;GACE,MAAM,CAAC,CAAC;GACR,UAAU,oBAAoB;GAC9B,OAAO;GACP,YAAW;GACK;GACF;GACD;GACb,eAAe,uBAAuB,KAAA,CAAS;EAChD,CAAA;CACD,EAAA,CAAA;AAEN"}
1
+ {"version":3,"file":"threads-explorer-body.cjs.js","names":["useObservabilityListFilters","useTraceQueryAvailable","useFeedbackAvailable","useMemo","buildThreadQueryWhere","useThreadsListSource","threadToListRow","_Fragment","ObservabilityListBody","ActionRow","ThreadsFilterBar","TracesErrorContent","NoTracesInfo","TracesListView","THREAD_LIST_COLUMN_PREFERENCES","TraceThreadPanel"],"sources":["../../../../src/domains/threads/components/threads-explorer-body.tsx"],"sourcesContent":["import type { ThreadQueryArgs } from '@mastra/react/hooks/traces';\nimport { useMemo } from 'react';\nimport { useThreadsListSource } from '../hooks/use-threads-list-source';\nimport { buildThreadQueryWhere } from '../thread-filters';\nimport { threadToListRow } from '../thread-list-row';\nimport { ThreadsFilterBar } from './threads-filter-bar';\nimport { useFeedbackAvailable, useTraceQueryAvailable } from '@/domains/capabilities';\nimport { ObservabilityListBody } from '@/domains/observability/components/observability-list-body';\nimport { useObservabilityListFilters } from '@/domains/observability/hooks/use-observability-list-filters';\nimport { NoTracesInfo } from '@/domains/traces/components/no-traces-info';\nimport { TraceThreadPanel } from '@/domains/traces/components/trace-thread-panel';\nimport { TracesErrorContent } from '@/domains/traces/components/traces-error-content';\nimport { TracesListView } from '@/domains/traces/components/traces-list-view';\nimport type { TracesListViewTrace } from '@/domains/traces/components/traces-list-view';\nimport { THREAD_LIST_COLUMN_PREFERENCES } from '@/domains/traces/trace-list-columns';\nimport { ActionRow } from '@/ds/components/ActionRow';\n\nexport type ThreadsExplorerBodyProps = {\n /** The open thread. The host keeps it (e.g. in the URL) so it survives a reload. */\n selectedThreadId: string | undefined;\n onSelectedThreadChange: (threadId: string | undefined) => void;\n /** Opens a score from the thread drawer; scores live on host routes. */\n onOpenScore: (traceId: string, scoreId: string) => void;\n};\n\n/** The threads page body: filter bar, thread list and the thread drawer. Router-agnostic. */\nexport function ThreadsExplorerBody({\n selectedThreadId,\n onSelectedThreadChange,\n onOpenScore,\n}: ThreadsExplorerBodyProps) {\n const filters = useObservabilityListFilters();\n const { timeRange, tokens, groups, sort } = filters;\n const withQueryTrace = useTraceQueryAvailable().enabled;\n const withFeedback = useFeedbackAvailable().enabled;\n\n // Threads with trace activity in the window, like the traces list for the same chip.\n const query = useMemo<ThreadQueryArgs>(() => {\n const where = buildThreadQueryWhere(tokens, groups);\n return {\n timeRange: { traces: timeRange },\n orderBy: [{ field: 'startedAt', direction: sort }],\n ...(where ? { where } : {}),\n };\n }, [timeRange, sort, tokens, groups]);\n\n const { threads, hasNextPage, isFetchingNextPage, setEndOfListElement, isLoading, isError, error } =\n useThreadsListSource({ query, rolling: filters.rolling });\n\n const rows = useMemo(() => (threads ?? []).map(threadToListRow), [threads]);\n const selectedRow = rows.find(row => row.threadId === selectedThreadId);\n\n // The drawer is modal, so the list behind it cannot be clicked while a thread is open.\n const handleThreadClick = (row: TracesListViewTrace) => {\n if (row.threadId) onSelectedThreadChange(row.threadId);\n };\n\n // Same rule as /traces: an empty window without filters gets the full-page empty state.\n const showEmptyState =\n !isLoading && !isError && rows.length === 0 && !filters.contentFiltersApplied && !selectedThreadId;\n\n return (\n <>\n <h1 className=\"sr-only\">Threads</h1>\n <ObservabilityListBody\n toolbar={\n <ActionRow>\n <ActionRow.Start>\n <ThreadsFilterBar\n datePreset={filters.datePreset}\n dateFrom={filters.dateFrom}\n dateTo={filters.dateTo}\n tokens={tokens}\n groups={groups}\n onDatePresetChange={filters.onDatePresetChange}\n onDateChange={filters.onDateChange}\n onDateRangeChange={filters.onDateRangeChange}\n onFiltersChange={filters.onFiltersChange}\n disabled={isLoading}\n />\n </ActionRow.Start>\n </ActionRow>\n }\n error={\n isError ? (\n <TracesErrorContent error={error} resource=\"threads\" errorTitle=\"Failed to load threads\" />\n ) : undefined\n }\n empty={\n showEmptyState ? (\n <NoTracesInfo\n resource=\"threads\"\n datePreset={filters.datePreset}\n dateFrom={filters.dateFrom}\n dateTo={filters.dateTo}\n />\n ) : undefined\n }\n >\n <TracesListView\n listId=\"all-threads\"\n columnPreferences={THREAD_LIST_COLUMN_PREFERENCES}\n traces={rows}\n isLoading={isLoading}\n isFetchingNextPage={isFetchingNextPage}\n hasNextPage={hasNextPage}\n setEndOfListElement={setEndOfListElement}\n filtersApplied={filters.filtersApplied}\n resource=\"threads\"\n createdSort={sort}\n onSortChange={filters.setSort}\n featuredTraceId={selectedRow?.traceId}\n onTraceClick={handleThreadClick}\n />\n </ObservabilityListBody>\n <TraceThreadPanel\n open={!!selectedThreadId}\n threadId={selectedThreadId ?? ''}\n depth={1}\n closeLabel=\"Close\"\n withQueryTrace={withQueryTrace}\n withFeedback={withFeedback}\n onOpenScore={onOpenScore}\n onClose={() => onSelectedThreadChange(undefined)}\n />\n </>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA0BA,SAAgB,oBAAoB,EAClC,kBACA,wBACA,eAC2B;CAC3B,MAAM,UAAUA,mEAAAA,4BAA4B;CAC5C,MAAM,EAAE,WAAW,QAAQ,QAAQ,SAAS;CAC5C,MAAM,kBAAA,GAAiBC,iCAAAA,uBAAAA,CAAuB,CAAC,CAAC;CAChD,MAAM,gBAAA,GAAeC,iCAAAA,qBAAAA,CAAqB,CAAC,CAAC;CAG5C,MAAM,SAAA,GAAQC,MAAAA,QAAAA,OAA+B;EAC3C,MAAM,QAAQC,uCAAAA,sBAAsB,QAAQ,MAAM;EAClD,OAAO;GACL,WAAW,EAAE,QAAQ,UAAU;GAC/B,SAAS,CAAC;IAAE,OAAO;IAAa,WAAW;GAAK,CAAC;GACjD,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;EAC3B;CACF,GAAG;EAAC;EAAW;EAAM;EAAQ;CAAM,CAAC;CAEpC,MAAM,EAAE,SAAS,aAAa,oBAAoB,qBAAqB,WAAW,SAAS,UACzFC,sDAAAA,qBAAqB;EAAE;EAAO,SAAS,QAAQ;CAAQ,CAAC;CAE1D,MAAM,QAAA,GAAOF,MAAAA,QAAAA,QAAe,WAAW,CAAC,EAAA,CAAG,IAAIG,wCAAAA,eAAe,GAAG,CAAC,OAAO,CAAC;CAC1E,MAAM,cAAc,KAAK,MAAK,QAAO,IAAI,aAAa,gBAAgB;CAGtE,MAAM,qBAAqB,QAA6B;EACtD,IAAI,IAAI,UAAU,uBAAuB,IAAI,QAAQ;CACvD;CAGA,MAAM,iBACJ,CAAC,aAAa,CAAC,WAAW,KAAK,WAAW,KAAK,CAAC,QAAQ,yBAAyB,CAAC;CAEpF,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAAC,kBAAAA,UAAA,EAAA,UAAA;EACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD;GAAI,WAAU;GAAU,UAAA;EAAW,CAAA;EACnC,iBAAA,GAAA,kBAAA,IAAA,CAACC,iEAAAA,uBAAD;GACE,SACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,kBAAAA,WAAD,EAAA,UACE,iBAAA,GAAA,kBAAA,IAAA,CAACA,kBAAAA,UAAU,OAAX,EAAA,UACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,sDAAAA,kBAAD;IACE,YAAY,QAAQ;IACpB,UAAU,QAAQ;IAClB,QAAQ,QAAQ;IACR;IACA;IACR,oBAAoB,QAAQ;IAC5B,cAAc,QAAQ;IACtB,mBAAmB,QAAQ;IAC3B,iBAAiB,QAAQ;IACzB,UAAU;GACX,CAAA,EACc,CAAA,EACR,CAAA;GAEb,OACE,UACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,uDAAAA,oBAAD;IAA2B;IAAO,UAAS;IAAU,YAAW;GAA0B,CAAA,IACxF,KAAA;GAEN,OACE,iBACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,iDAAAA,cAAD;IACE,UAAS;IACT,YAAY,QAAQ;IACpB,UAAU,QAAQ;IAClB,QAAQ,QAAQ;GACjB,CAAA,IACC,KAAA;GAGN,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAACC,mDAAAA,gBAAD;IACE,QAAO;IACP,mBAAmBC,0CAAAA;IACnB,QAAQ;IACG;IACS;IACP;IACQ;IACrB,gBAAgB,QAAQ;IACxB,UAAS;IACT,aAAa;IACb,cAAc,QAAQ;IACtB,iBAAiB,aAAa;IAC9B,cAAc;GACf,CAAA;EACoB,CAAA;EACvB,iBAAA,GAAA,kBAAA,IAAA,CAACC,qDAAAA,kBAAD;GACE,MAAM,CAAC,CAAC;GACR,UAAU,oBAAoB;GAC9B,OAAO;GACP,YAAW;GACK;GACF;GACD;GACb,eAAe,uBAAuB,KAAA,CAAS;EAChD,CAAA;CACD,EAAA,CAAA;AAEN"}
@@ -1,6 +1,7 @@
1
1
  import { useFeedbackAvailable, useTraceQueryAvailable } from "../../capabilities.es.js";
2
2
  import { ObservabilityListBody } from "../../observability/components/observability-list-body.es.js";
3
3
  import { useObservabilityListFilters } from "../../observability/hooks/use-observability-list-filters.es.js";
4
+ import { THREAD_LIST_COLUMN_PREFERENCES } from "../../traces/trace-list-columns.es.js";
4
5
  import { NoTracesInfo } from "../../traces/components/no-traces-info.es.js";
5
6
  import { TracesErrorContent } from "../../traces/components/traces-error-content.es.js";
6
7
  import { TracesListView } from "../../traces/components/traces-list-view.es.js";
@@ -76,6 +77,7 @@ function ThreadsExplorerBody({ selectedThreadId, onSelectedThreadChange, onOpenS
76
77
  }) : void 0,
77
78
  children: /* @__PURE__ */ jsx(TracesListView, {
78
79
  listId: "all-threads",
80
+ columnPreferences: THREAD_LIST_COLUMN_PREFERENCES,
79
81
  traces: rows,
80
82
  isLoading,
81
83
  isFetchingNextPage,
@@ -1 +1 @@
1
- {"version":3,"file":"threads-explorer-body.es.js","names":["_Fragment"],"sources":["../../../../src/domains/threads/components/threads-explorer-body.tsx"],"sourcesContent":["import type { ThreadQueryArgs } from '@mastra/react/hooks/traces';\nimport { useMemo } from 'react';\nimport { useThreadsListSource } from '../hooks/use-threads-list-source';\nimport { buildThreadQueryWhere } from '../thread-filters';\nimport { threadToListRow } from '../thread-list-row';\nimport { ThreadsFilterBar } from './threads-filter-bar';\nimport { useFeedbackAvailable, useTraceQueryAvailable } from '@/domains/capabilities';\nimport { ObservabilityListBody } from '@/domains/observability/components/observability-list-body';\nimport { useObservabilityListFilters } from '@/domains/observability/hooks/use-observability-list-filters';\nimport { NoTracesInfo } from '@/domains/traces/components/no-traces-info';\nimport { TraceThreadPanel } from '@/domains/traces/components/trace-thread-panel';\nimport { TracesErrorContent } from '@/domains/traces/components/traces-error-content';\nimport { TracesListView } from '@/domains/traces/components/traces-list-view';\nimport type { TracesListViewTrace } from '@/domains/traces/components/traces-list-view';\nimport { ActionRow } from '@/ds/components/ActionRow';\n\nexport type ThreadsExplorerBodyProps = {\n /** The open thread. The host keeps it (e.g. in the URL) so it survives a reload. */\n selectedThreadId: string | undefined;\n onSelectedThreadChange: (threadId: string | undefined) => void;\n /** Opens a score from the thread drawer; scores live on host routes. */\n onOpenScore: (traceId: string, scoreId: string) => void;\n};\n\n/** The threads page body: filter bar, thread list and the thread drawer. Router-agnostic. */\nexport function ThreadsExplorerBody({\n selectedThreadId,\n onSelectedThreadChange,\n onOpenScore,\n}: ThreadsExplorerBodyProps) {\n const filters = useObservabilityListFilters();\n const { timeRange, tokens, groups, sort } = filters;\n const withQueryTrace = useTraceQueryAvailable().enabled;\n const withFeedback = useFeedbackAvailable().enabled;\n\n // Threads with trace activity in the window, like the traces list for the same chip.\n const query = useMemo<ThreadQueryArgs>(() => {\n const where = buildThreadQueryWhere(tokens, groups);\n return {\n timeRange: { traces: timeRange },\n orderBy: [{ field: 'startedAt', direction: sort }],\n ...(where ? { where } : {}),\n };\n }, [timeRange, sort, tokens, groups]);\n\n const { threads, hasNextPage, isFetchingNextPage, setEndOfListElement, isLoading, isError, error } =\n useThreadsListSource({ query, rolling: filters.rolling });\n\n const rows = useMemo(() => (threads ?? []).map(threadToListRow), [threads]);\n const selectedRow = rows.find(row => row.threadId === selectedThreadId);\n\n // The drawer is modal, so the list behind it cannot be clicked while a thread is open.\n const handleThreadClick = (row: TracesListViewTrace) => {\n if (row.threadId) onSelectedThreadChange(row.threadId);\n };\n\n // Same rule as /traces: an empty window without filters gets the full-page empty state.\n const showEmptyState =\n !isLoading && !isError && rows.length === 0 && !filters.contentFiltersApplied && !selectedThreadId;\n\n return (\n <>\n <h1 className=\"sr-only\">Threads</h1>\n <ObservabilityListBody\n toolbar={\n <ActionRow>\n <ActionRow.Start>\n <ThreadsFilterBar\n datePreset={filters.datePreset}\n dateFrom={filters.dateFrom}\n dateTo={filters.dateTo}\n tokens={tokens}\n groups={groups}\n onDatePresetChange={filters.onDatePresetChange}\n onDateChange={filters.onDateChange}\n onDateRangeChange={filters.onDateRangeChange}\n onFiltersChange={filters.onFiltersChange}\n disabled={isLoading}\n />\n </ActionRow.Start>\n </ActionRow>\n }\n error={\n isError ? (\n <TracesErrorContent error={error} resource=\"threads\" errorTitle=\"Failed to load threads\" />\n ) : undefined\n }\n empty={\n showEmptyState ? (\n <NoTracesInfo\n resource=\"threads\"\n datePreset={filters.datePreset}\n dateFrom={filters.dateFrom}\n dateTo={filters.dateTo}\n />\n ) : undefined\n }\n >\n <TracesListView\n listId=\"all-threads\"\n traces={rows}\n isLoading={isLoading}\n isFetchingNextPage={isFetchingNextPage}\n hasNextPage={hasNextPage}\n setEndOfListElement={setEndOfListElement}\n filtersApplied={filters.filtersApplied}\n resource=\"threads\"\n createdSort={sort}\n onSortChange={filters.setSort}\n featuredTraceId={selectedRow?.traceId}\n onTraceClick={handleThreadClick}\n />\n </ObservabilityListBody>\n <TraceThreadPanel\n open={!!selectedThreadId}\n threadId={selectedThreadId ?? ''}\n depth={1}\n closeLabel=\"Close\"\n withQueryTrace={withQueryTrace}\n withFeedback={withFeedback}\n onOpenScore={onOpenScore}\n onClose={() => onSelectedThreadChange(undefined)}\n />\n </>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAyBA,SAAgB,oBAAoB,EAClC,kBACA,wBACA,eAC2B;CAC3B,MAAM,UAAU,4BAA4B;CAC5C,MAAM,EAAE,WAAW,QAAQ,QAAQ,SAAS;CAC5C,MAAM,iBAAiB,uBAAuB,CAAC,CAAC;CAChD,MAAM,eAAe,qBAAqB,CAAC,CAAC;CAG5C,MAAM,QAAQ,cAA+B;EAC3C,MAAM,QAAQ,sBAAsB,QAAQ,MAAM;EAClD,OAAO;GACL,WAAW,EAAE,QAAQ,UAAU;GAC/B,SAAS,CAAC;IAAE,OAAO;IAAa,WAAW;GAAK,CAAC;GACjD,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;EAC3B;CACF,GAAG;EAAC;EAAW;EAAM;EAAQ;CAAM,CAAC;CAEpC,MAAM,EAAE,SAAS,aAAa,oBAAoB,qBAAqB,WAAW,SAAS,UACzF,qBAAqB;EAAE;EAAO,SAAS,QAAQ;CAAQ,CAAC;CAE1D,MAAM,OAAO,eAAe,WAAW,CAAC,EAAA,CAAG,IAAI,eAAe,GAAG,CAAC,OAAO,CAAC;CAC1E,MAAM,cAAc,KAAK,MAAK,QAAO,IAAI,aAAa,gBAAgB;CAGtE,MAAM,qBAAqB,QAA6B;EACtD,IAAI,IAAI,UAAU,uBAAuB,IAAI,QAAQ;CACvD;CAGA,MAAM,iBACJ,CAAC,aAAa,CAAC,WAAW,KAAK,WAAW,KAAK,CAAC,QAAQ,yBAAyB,CAAC;CAEpF,OACE,qBAAAA,YAAA,EAAA,UAAA;EACE,oBAAC,MAAD;GAAI,WAAU;GAAU,UAAA;EAAW,CAAA;EACnC,oBAAC,uBAAD;GACE,SACE,oBAAC,WAAD,EAAA,UACE,oBAAC,UAAU,OAAX,EAAA,UACE,oBAAC,kBAAD;IACE,YAAY,QAAQ;IACpB,UAAU,QAAQ;IAClB,QAAQ,QAAQ;IACR;IACA;IACR,oBAAoB,QAAQ;IAC5B,cAAc,QAAQ;IACtB,mBAAmB,QAAQ;IAC3B,iBAAiB,QAAQ;IACzB,UAAU;GACX,CAAA,EACc,CAAA,EACR,CAAA;GAEb,OACE,UACE,oBAAC,oBAAD;IAA2B;IAAO,UAAS;IAAU,YAAW;GAA0B,CAAA,IACxF,KAAA;GAEN,OACE,iBACE,oBAAC,cAAD;IACE,UAAS;IACT,YAAY,QAAQ;IACpB,UAAU,QAAQ;IAClB,QAAQ,QAAQ;GACjB,CAAA,IACC,KAAA;GAGN,UAAA,oBAAC,gBAAD;IACE,QAAO;IACP,QAAQ;IACG;IACS;IACP;IACQ;IACrB,gBAAgB,QAAQ;IACxB,UAAS;IACT,aAAa;IACb,cAAc,QAAQ;IACtB,iBAAiB,aAAa;IAC9B,cAAc;GACf,CAAA;EACoB,CAAA;EACvB,oBAAC,kBAAD;GACE,MAAM,CAAC,CAAC;GACR,UAAU,oBAAoB;GAC9B,OAAO;GACP,YAAW;GACK;GACF;GACD;GACb,eAAe,uBAAuB,KAAA,CAAS;EAChD,CAAA;CACD,EAAA,CAAA;AAEN"}
1
+ {"version":3,"file":"threads-explorer-body.es.js","names":["_Fragment"],"sources":["../../../../src/domains/threads/components/threads-explorer-body.tsx"],"sourcesContent":["import type { ThreadQueryArgs } from '@mastra/react/hooks/traces';\nimport { useMemo } from 'react';\nimport { useThreadsListSource } from '../hooks/use-threads-list-source';\nimport { buildThreadQueryWhere } from '../thread-filters';\nimport { threadToListRow } from '../thread-list-row';\nimport { ThreadsFilterBar } from './threads-filter-bar';\nimport { useFeedbackAvailable, useTraceQueryAvailable } from '@/domains/capabilities';\nimport { ObservabilityListBody } from '@/domains/observability/components/observability-list-body';\nimport { useObservabilityListFilters } from '@/domains/observability/hooks/use-observability-list-filters';\nimport { NoTracesInfo } from '@/domains/traces/components/no-traces-info';\nimport { TraceThreadPanel } from '@/domains/traces/components/trace-thread-panel';\nimport { TracesErrorContent } from '@/domains/traces/components/traces-error-content';\nimport { TracesListView } from '@/domains/traces/components/traces-list-view';\nimport type { TracesListViewTrace } from '@/domains/traces/components/traces-list-view';\nimport { THREAD_LIST_COLUMN_PREFERENCES } from '@/domains/traces/trace-list-columns';\nimport { ActionRow } from '@/ds/components/ActionRow';\n\nexport type ThreadsExplorerBodyProps = {\n /** The open thread. The host keeps it (e.g. in the URL) so it survives a reload. */\n selectedThreadId: string | undefined;\n onSelectedThreadChange: (threadId: string | undefined) => void;\n /** Opens a score from the thread drawer; scores live on host routes. */\n onOpenScore: (traceId: string, scoreId: string) => void;\n};\n\n/** The threads page body: filter bar, thread list and the thread drawer. Router-agnostic. */\nexport function ThreadsExplorerBody({\n selectedThreadId,\n onSelectedThreadChange,\n onOpenScore,\n}: ThreadsExplorerBodyProps) {\n const filters = useObservabilityListFilters();\n const { timeRange, tokens, groups, sort } = filters;\n const withQueryTrace = useTraceQueryAvailable().enabled;\n const withFeedback = useFeedbackAvailable().enabled;\n\n // Threads with trace activity in the window, like the traces list for the same chip.\n const query = useMemo<ThreadQueryArgs>(() => {\n const where = buildThreadQueryWhere(tokens, groups);\n return {\n timeRange: { traces: timeRange },\n orderBy: [{ field: 'startedAt', direction: sort }],\n ...(where ? { where } : {}),\n };\n }, [timeRange, sort, tokens, groups]);\n\n const { threads, hasNextPage, isFetchingNextPage, setEndOfListElement, isLoading, isError, error } =\n useThreadsListSource({ query, rolling: filters.rolling });\n\n const rows = useMemo(() => (threads ?? []).map(threadToListRow), [threads]);\n const selectedRow = rows.find(row => row.threadId === selectedThreadId);\n\n // The drawer is modal, so the list behind it cannot be clicked while a thread is open.\n const handleThreadClick = (row: TracesListViewTrace) => {\n if (row.threadId) onSelectedThreadChange(row.threadId);\n };\n\n // Same rule as /traces: an empty window without filters gets the full-page empty state.\n const showEmptyState =\n !isLoading && !isError && rows.length === 0 && !filters.contentFiltersApplied && !selectedThreadId;\n\n return (\n <>\n <h1 className=\"sr-only\">Threads</h1>\n <ObservabilityListBody\n toolbar={\n <ActionRow>\n <ActionRow.Start>\n <ThreadsFilterBar\n datePreset={filters.datePreset}\n dateFrom={filters.dateFrom}\n dateTo={filters.dateTo}\n tokens={tokens}\n groups={groups}\n onDatePresetChange={filters.onDatePresetChange}\n onDateChange={filters.onDateChange}\n onDateRangeChange={filters.onDateRangeChange}\n onFiltersChange={filters.onFiltersChange}\n disabled={isLoading}\n />\n </ActionRow.Start>\n </ActionRow>\n }\n error={\n isError ? (\n <TracesErrorContent error={error} resource=\"threads\" errorTitle=\"Failed to load threads\" />\n ) : undefined\n }\n empty={\n showEmptyState ? (\n <NoTracesInfo\n resource=\"threads\"\n datePreset={filters.datePreset}\n dateFrom={filters.dateFrom}\n dateTo={filters.dateTo}\n />\n ) : undefined\n }\n >\n <TracesListView\n listId=\"all-threads\"\n columnPreferences={THREAD_LIST_COLUMN_PREFERENCES}\n traces={rows}\n isLoading={isLoading}\n isFetchingNextPage={isFetchingNextPage}\n hasNextPage={hasNextPage}\n setEndOfListElement={setEndOfListElement}\n filtersApplied={filters.filtersApplied}\n resource=\"threads\"\n createdSort={sort}\n onSortChange={filters.setSort}\n featuredTraceId={selectedRow?.traceId}\n onTraceClick={handleThreadClick}\n />\n </ObservabilityListBody>\n <TraceThreadPanel\n open={!!selectedThreadId}\n threadId={selectedThreadId ?? ''}\n depth={1}\n closeLabel=\"Close\"\n withQueryTrace={withQueryTrace}\n withFeedback={withFeedback}\n onOpenScore={onOpenScore}\n onClose={() => onSelectedThreadChange(undefined)}\n />\n </>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AA0BA,SAAgB,oBAAoB,EAClC,kBACA,wBACA,eAC2B;CAC3B,MAAM,UAAU,4BAA4B;CAC5C,MAAM,EAAE,WAAW,QAAQ,QAAQ,SAAS;CAC5C,MAAM,iBAAiB,uBAAuB,CAAC,CAAC;CAChD,MAAM,eAAe,qBAAqB,CAAC,CAAC;CAG5C,MAAM,QAAQ,cAA+B;EAC3C,MAAM,QAAQ,sBAAsB,QAAQ,MAAM;EAClD,OAAO;GACL,WAAW,EAAE,QAAQ,UAAU;GAC/B,SAAS,CAAC;IAAE,OAAO;IAAa,WAAW;GAAK,CAAC;GACjD,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;EAC3B;CACF,GAAG;EAAC;EAAW;EAAM;EAAQ;CAAM,CAAC;CAEpC,MAAM,EAAE,SAAS,aAAa,oBAAoB,qBAAqB,WAAW,SAAS,UACzF,qBAAqB;EAAE;EAAO,SAAS,QAAQ;CAAQ,CAAC;CAE1D,MAAM,OAAO,eAAe,WAAW,CAAC,EAAA,CAAG,IAAI,eAAe,GAAG,CAAC,OAAO,CAAC;CAC1E,MAAM,cAAc,KAAK,MAAK,QAAO,IAAI,aAAa,gBAAgB;CAGtE,MAAM,qBAAqB,QAA6B;EACtD,IAAI,IAAI,UAAU,uBAAuB,IAAI,QAAQ;CACvD;CAGA,MAAM,iBACJ,CAAC,aAAa,CAAC,WAAW,KAAK,WAAW,KAAK,CAAC,QAAQ,yBAAyB,CAAC;CAEpF,OACE,qBAAAA,YAAA,EAAA,UAAA;EACE,oBAAC,MAAD;GAAI,WAAU;GAAU,UAAA;EAAW,CAAA;EACnC,oBAAC,uBAAD;GACE,SACE,oBAAC,WAAD,EAAA,UACE,oBAAC,UAAU,OAAX,EAAA,UACE,oBAAC,kBAAD;IACE,YAAY,QAAQ;IACpB,UAAU,QAAQ;IAClB,QAAQ,QAAQ;IACR;IACA;IACR,oBAAoB,QAAQ;IAC5B,cAAc,QAAQ;IACtB,mBAAmB,QAAQ;IAC3B,iBAAiB,QAAQ;IACzB,UAAU;GACX,CAAA,EACc,CAAA,EACR,CAAA;GAEb,OACE,UACE,oBAAC,oBAAD;IAA2B;IAAO,UAAS;IAAU,YAAW;GAA0B,CAAA,IACxF,KAAA;GAEN,OACE,iBACE,oBAAC,cAAD;IACE,UAAS;IACT,YAAY,QAAQ;IACpB,UAAU,QAAQ;IAClB,QAAQ,QAAQ;GACjB,CAAA,IACC,KAAA;GAGN,UAAA,oBAAC,gBAAD;IACE,QAAO;IACP,mBAAmB;IACnB,QAAQ;IACG;IACS;IACP;IACQ;IACrB,gBAAgB,QAAQ;IACxB,UAAS;IACT,aAAa;IACb,cAAc,QAAQ;IACtB,iBAAiB,aAAa;IAC9B,cAAc;GACf,CAAA;EACoB,CAAA;EACvB,oBAAC,kBAAD;GACE,MAAM,CAAC,CAAC;GACR,UAAU,oBAAoB;GAC9B,OAAO;GACP,YAAW;GACK;GACF;GACD;GACb,eAAe,uBAAuB,KAAA,CAAS;EAChD,CAAA;CACD,EAAA,CAAA;AAEN"}
@@ -1,5 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_trace_filters = require("../../trace-filters-HWOGfVqx.cjs");
3
+ let lucide_react = require("lucide-react");
3
4
  let _mastra_core_observability = require("@mastra/core/observability");
4
5
  // src/domains/threads/thread-filters.ts
5
6
  /** Thread query fields the filter bar offers. `startedAt`/`endedAt` are left to the time-range chip. */
@@ -42,7 +43,7 @@ var TRACE_COUNT_OPERATORS = [
42
43
  ];
43
44
  var THREAD_FILTER_BAR_LABELS = {
44
45
  ...require_trace_filters.TRACE_FILTER_BAR_LABELS,
45
- traceCount: "Trace count",
46
+ traceCount: "Messages",
46
47
  timeToFirstChunkMs: "Time to first chunk (ms)",
47
48
  executionSource: "Execution source",
48
49
  entityType: "Primitive type",
@@ -50,16 +51,17 @@ var THREAD_FILTER_BAR_LABELS = {
50
51
  };
51
52
  /** Thread fields without their own trace icon borrow the icon of the closest trace field. */
52
53
  var THREAD_ICON_FIELD_ALIASES = {
53
- traceCount: "traceId",
54
54
  timeToFirstChunkMs: "durationMs",
55
55
  executionSource: "runId",
56
56
  entityType: "rootEntityType",
57
57
  entityVersionId: "entityId"
58
58
  };
59
+ /** Thread fields with an icon of their own: Messages uses the Threads tab's icon. */
60
+ var THREAD_FILTER_BAR_ICONS = { traceCount: lucide_react.MessagesSquareIcon };
59
61
  var threadFieldBase = (id) => ({
60
62
  id,
61
63
  label: THREAD_FILTER_BAR_LABELS[id] ?? id,
62
- icon: require_trace_filters.traceFilterFieldIcon(THREAD_ICON_FIELD_ALIASES[id] ?? id),
64
+ icon: THREAD_FILTER_BAR_ICONS[id] ?? require_trace_filters.traceFilterFieldIcon(THREAD_ICON_FIELD_ALIASES[id] ?? id),
63
65
  color: require_trace_filters.traceFilterFieldColor(id)
64
66
  });
65
67
  var humanize = (value) => {
@@ -1 +1 @@
1
- {"version":3,"file":"thread-filters.cjs.js","names":["TRACE_FILTER_BAR_LABELS","traceFilterFieldIcon","traceFilterFieldColor","ROOT_ENTITY_TYPE_OPTIONS","EntityType","TRACE_STATUS_OPTIONS","TRACE_STRING_OPERATORS","TRACE_REQUIRED_STRING_OPERATORS","TRACE_NUMBER_OPERATORS","isLegacyAnyValue","scalarPredicate","isTraceFilterGroup"],"sources":["../../../src/domains/threads/thread-filters.ts"],"sourcesContent":["import { EntityType } from '@mastra/core/observability';\nimport type { TraceQueryScalarPredicate } from '@mastra/core/storage';\nimport {\n isLegacyAnyValue,\n ROOT_ENTITY_TYPE_OPTIONS,\n TRACE_FILTER_BAR_LABELS,\n TRACE_NUMBER_OPERATORS,\n TRACE_REQUIRED_STRING_OPERATORS,\n TRACE_STATUS_OPTIONS,\n TRACE_STRING_OPERATORS,\n traceFilterFieldColor,\n traceFilterFieldIcon,\n} from '../traces/trace-filters';\nimport { isTraceFilterGroup, scalarPredicate } from '../traces/trace-query-filters';\nimport type { TraceFilterGroup, TraceFilterOperatorId, TraceFilterToken } from '../traces/trace-query-filters';\nimport type { FilterBarField, FilterBarOption } from '@/ds/components/FilterBar/types';\n\n/** Thread query fields the filter bar offers. `startedAt`/`endedAt` are left to the time-range chip. */\nexport const THREAD_FILTER_FIELD_IDS = [\n 'status',\n 'traceCount',\n 'timeToFirstChunkMs',\n 'entityType',\n 'entityId',\n 'entityName',\n 'entityVersionId',\n 'threadId',\n 'resourceId',\n 'userId',\n 'organizationId',\n 'runId',\n 'sessionId',\n 'requestId',\n 'serviceName',\n 'experimentId',\n 'environment',\n 'executionSource',\n] as const;\n\nconst FIELD_IDS: ReadonlySet<string> = new Set(THREAD_FILTER_FIELD_IDS);\nconst NUMBER_FIELD_IDS: ReadonlySet<string> = new Set(['traceCount', 'timeToFirstChunkMs']);\n/** Fields every thread row carries. On any other field, \"is not X\" must also keep threads where it is missing. */\nconst REQUIRED_FIELD_IDS: ReadonlySet<string> = new Set(['threadId', 'status', 'traceCount']);\n/** The thread query compares `traceCount` but has no set membership or presence check for it. */\nconst TRACE_COUNT_OPERATORS: TraceFilterOperatorId[] = ['is', 'isNot', 'gt', 'gte', 'lt', 'lte'];\n\nconst THREAD_FILTER_BAR_LABELS: Record<string, string> = {\n ...TRACE_FILTER_BAR_LABELS,\n traceCount: 'Trace count',\n timeToFirstChunkMs: 'Time to first chunk (ms)',\n executionSource: 'Execution source',\n entityType: 'Primitive type',\n entityVersionId: 'Primitive version ID',\n};\n\n/** Thread fields without their own trace icon borrow the icon of the closest trace field. */\nconst THREAD_ICON_FIELD_ALIASES: Record<string, string> = {\n traceCount: 'traceId',\n timeToFirstChunkMs: 'durationMs',\n executionSource: 'runId',\n entityType: 'rootEntityType',\n entityVersionId: 'entityId',\n};\n\nconst threadFieldBase = (id: string) => ({\n id,\n label: THREAD_FILTER_BAR_LABELS[id] ?? id,\n icon: traceFilterFieldIcon(THREAD_ICON_FIELD_ALIASES[id] ?? id),\n color: traceFilterFieldColor(id),\n});\n\nconst humanize = (value: string) => {\n const words = value.replace(/_/g, ' ');\n return words.charAt(0).toUpperCase() + words.slice(1);\n};\n\nconst ENTITY_TYPE_LABELS: Record<string, string> = Object.fromEntries(\n ROOT_ENTITY_TYPE_OPTIONS.map(option => [option.entityType, option.label]),\n);\n\nconst ENTITY_TYPE_OPTIONS: FilterBarOption[] = Object.values(EntityType)\n .map(value => ({ value, label: ENTITY_TYPE_LABELS[value] ?? humanize(value) }))\n .sort((a, b) => a.label.localeCompare(b.label));\n\nconst STATUS_OPTIONS: FilterBarOption[] = TRACE_STATUS_OPTIONS.filter(option => option.value !== 'running').map(\n option => ({ value: option.value, label: option.label }),\n);\n\n/** FilterBar fields for the threads page: only paths and operators `queryTraceThreads()` accepts. */\nexport function createThreadFilterBarFields({\n entityNames,\n environments,\n}: {\n entityNames: readonly string[];\n environments: readonly string[];\n}): FilterBarField[] {\n const pick = (\n id: string,\n suggestions: FilterBarOption[],\n operators: TraceFilterOperatorId[] = TRACE_STRING_OPERATORS,\n ): FilterBarField => ({ ...threadFieldBase(id), operators, strict: true, suggestions });\n\n const field = (id: string): FilterBarField => {\n switch (id) {\n case 'status':\n return pick(id, STATUS_OPTIONS, TRACE_REQUIRED_STRING_OPERATORS);\n case 'entityType':\n return pick(id, ENTITY_TYPE_OPTIONS);\n case 'entityName':\n return pick(\n id,\n entityNames.map(value => ({ value })),\n );\n case 'environment':\n return pick(\n id,\n environments.map(value => ({ value })),\n );\n case 'traceCount':\n return { ...threadFieldBase(id), type: 'number', operators: TRACE_COUNT_OPERATORS };\n case 'timeToFirstChunkMs':\n return { ...threadFieldBase(id), type: 'number', operators: TRACE_NUMBER_OPERATORS };\n case 'threadId':\n return { ...threadFieldBase(id), operators: TRACE_REQUIRED_STRING_OPERATORS };\n default:\n return { ...threadFieldBase(id), operators: TRACE_STRING_OPERATORS };\n }\n };\n\n return THREAD_FILTER_FIELD_IDS.map(field).sort((a, b) => a.label.localeCompare(b.label));\n}\n\nfunction tokenToThreadQueryPredicate(token: TraceFilterToken): TraceQueryScalarPredicate | undefined {\n const { fieldId } = token;\n if (!FIELD_IDS.has(fieldId)) return undefined;\n const operatorId = token.operatorId ?? 'is';\n const isPresence = operatorId === 'exists' || operatorId === 'notExists';\n\n const rawValues = (Array.isArray(token.value) ? token.value : [token.value]).filter(\n (value): value is string =>\n typeof value === 'string' && Boolean(value.trim()) && !isLegacyAnyValue(value, operatorId),\n );\n if (!rawValues.length && !isPresence) return undefined;\n\n let values: (string | number)[] = rawValues;\n if (NUMBER_FIELD_IDS.has(fieldId)) {\n values = rawValues.map(Number).filter(value => !Number.isNaN(value));\n if (!values.length && !isPresence) return undefined;\n }\n if (fieldId === 'traceCount' && (isPresence || values.length > 1 || !TRACE_COUNT_OPERATORS.includes(operatorId))) {\n return undefined;\n }\n\n const predicate = scalarPredicate(operatorId, fieldId, values);\n if (!predicate) return undefined;\n if ((operatorId === 'isNot' || operatorId === 'notIn') && !REQUIRED_FIELD_IDS.has(fieldId)) {\n return { op: 'or', args: [predicate, { op: 'notExists', path: fieldId }] };\n }\n return predicate;\n}\n\nfunction groupToThreadQueryPredicate(group: TraceFilterGroup): TraceQueryScalarPredicate | undefined {\n const args = group.nodes\n .map(node => (isTraceFilterGroup(node) ? groupToThreadQueryPredicate(node) : tokenToThreadQueryPredicate(node)))\n .filter((predicate): predicate is TraceQueryScalarPredicate => Boolean(predicate));\n if (args.length === 0) return undefined;\n return args.length === 1 ? args[0] : { op: group.logic, args };\n}\n\n/**\n * The thread query `where` for the filter bar's tokens and groups, or `undefined` when nothing applies.\n * Conditions the thread query can't run (unknown fields, unusable values) are left out instead of\n * failing the request.\n */\nexport function buildThreadQueryWhere(\n tokens: TraceFilterToken[],\n groups: TraceFilterGroup[],\n): TraceQueryScalarPredicate | undefined {\n const args = [...tokens.map(tokenToThreadQueryPredicate), ...groups.map(groupToThreadQueryPredicate)].filter(\n (predicate): predicate is TraceQueryScalarPredicate => Boolean(predicate),\n );\n return args.length ? { op: 'and', args } : undefined;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"thread-filters.cjs.js","names":["TRACE_FILTER_BAR_LABELS","MessagesSquareIcon","traceFilterFieldIcon","traceFilterFieldColor","ROOT_ENTITY_TYPE_OPTIONS","EntityType","TRACE_STATUS_OPTIONS","TRACE_STRING_OPERATORS","TRACE_REQUIRED_STRING_OPERATORS","TRACE_NUMBER_OPERATORS","isLegacyAnyValue","scalarPredicate","isTraceFilterGroup"],"sources":["../../../src/domains/threads/thread-filters.ts"],"sourcesContent":["import { EntityType } from '@mastra/core/observability';\nimport type { TraceQueryScalarPredicate } from '@mastra/core/storage';\nimport { MessagesSquareIcon } from 'lucide-react';\nimport type { LucideIcon } from 'lucide-react';\nimport {\n isLegacyAnyValue,\n ROOT_ENTITY_TYPE_OPTIONS,\n TRACE_FILTER_BAR_LABELS,\n TRACE_NUMBER_OPERATORS,\n TRACE_REQUIRED_STRING_OPERATORS,\n TRACE_STATUS_OPTIONS,\n TRACE_STRING_OPERATORS,\n traceFilterFieldColor,\n traceFilterFieldIcon,\n} from '../traces/trace-filters';\nimport { isTraceFilterGroup, scalarPredicate } from '../traces/trace-query-filters';\nimport type { TraceFilterGroup, TraceFilterOperatorId, TraceFilterToken } from '../traces/trace-query-filters';\nimport type { FilterBarField, FilterBarOption } from '@/ds/components/FilterBar/types';\n\n/** Thread query fields the filter bar offers. `startedAt`/`endedAt` are left to the time-range chip. */\nexport const THREAD_FILTER_FIELD_IDS = [\n 'status',\n 'traceCount',\n 'timeToFirstChunkMs',\n 'entityType',\n 'entityId',\n 'entityName',\n 'entityVersionId',\n 'threadId',\n 'resourceId',\n 'userId',\n 'organizationId',\n 'runId',\n 'sessionId',\n 'requestId',\n 'serviceName',\n 'experimentId',\n 'environment',\n 'executionSource',\n] as const;\n\nconst FIELD_IDS: ReadonlySet<string> = new Set(THREAD_FILTER_FIELD_IDS);\nconst NUMBER_FIELD_IDS: ReadonlySet<string> = new Set(['traceCount', 'timeToFirstChunkMs']);\n/** Fields every thread row carries. On any other field, \"is not X\" must also keep threads where it is missing. */\nconst REQUIRED_FIELD_IDS: ReadonlySet<string> = new Set(['threadId', 'status', 'traceCount']);\n/** The thread query compares `traceCount` but has no set membership or presence check for it. */\nconst TRACE_COUNT_OPERATORS: TraceFilterOperatorId[] = ['is', 'isNot', 'gt', 'gte', 'lt', 'lte'];\n\nconst THREAD_FILTER_BAR_LABELS: Record<string, string> = {\n ...TRACE_FILTER_BAR_LABELS,\n traceCount: 'Messages',\n timeToFirstChunkMs: 'Time to first chunk (ms)',\n executionSource: 'Execution source',\n entityType: 'Primitive type',\n entityVersionId: 'Primitive version ID',\n};\n\n/** Thread fields without their own trace icon borrow the icon of the closest trace field. */\nconst THREAD_ICON_FIELD_ALIASES: Record<string, string> = {\n timeToFirstChunkMs: 'durationMs',\n executionSource: 'runId',\n entityType: 'rootEntityType',\n entityVersionId: 'entityId',\n};\n\n/** Thread fields with an icon of their own: Messages uses the Threads tab's icon. */\nconst THREAD_FILTER_BAR_ICONS: Record<string, LucideIcon> = {\n traceCount: MessagesSquareIcon,\n};\n\nconst threadFieldBase = (id: string) => ({\n id,\n label: THREAD_FILTER_BAR_LABELS[id] ?? id,\n icon: THREAD_FILTER_BAR_ICONS[id] ?? traceFilterFieldIcon(THREAD_ICON_FIELD_ALIASES[id] ?? id),\n color: traceFilterFieldColor(id),\n});\n\nconst humanize = (value: string) => {\n const words = value.replace(/_/g, ' ');\n return words.charAt(0).toUpperCase() + words.slice(1);\n};\n\nconst ENTITY_TYPE_LABELS: Record<string, string> = Object.fromEntries(\n ROOT_ENTITY_TYPE_OPTIONS.map(option => [option.entityType, option.label]),\n);\n\nconst ENTITY_TYPE_OPTIONS: FilterBarOption[] = Object.values(EntityType)\n .map(value => ({ value, label: ENTITY_TYPE_LABELS[value] ?? humanize(value) }))\n .sort((a, b) => a.label.localeCompare(b.label));\n\nconst STATUS_OPTIONS: FilterBarOption[] = TRACE_STATUS_OPTIONS.filter(option => option.value !== 'running').map(\n option => ({ value: option.value, label: option.label }),\n);\n\n/** FilterBar fields for the threads page: only paths and operators `queryTraceThreads()` accepts. */\nexport function createThreadFilterBarFields({\n entityNames,\n environments,\n}: {\n entityNames: readonly string[];\n environments: readonly string[];\n}): FilterBarField[] {\n const pick = (\n id: string,\n suggestions: FilterBarOption[],\n operators: TraceFilterOperatorId[] = TRACE_STRING_OPERATORS,\n ): FilterBarField => ({ ...threadFieldBase(id), operators, strict: true, suggestions });\n\n const field = (id: string): FilterBarField => {\n switch (id) {\n case 'status':\n return pick(id, STATUS_OPTIONS, TRACE_REQUIRED_STRING_OPERATORS);\n case 'entityType':\n return pick(id, ENTITY_TYPE_OPTIONS);\n case 'entityName':\n return pick(\n id,\n entityNames.map(value => ({ value })),\n );\n case 'environment':\n return pick(\n id,\n environments.map(value => ({ value })),\n );\n case 'traceCount':\n return { ...threadFieldBase(id), type: 'number', operators: TRACE_COUNT_OPERATORS };\n case 'timeToFirstChunkMs':\n return { ...threadFieldBase(id), type: 'number', operators: TRACE_NUMBER_OPERATORS };\n case 'threadId':\n return { ...threadFieldBase(id), operators: TRACE_REQUIRED_STRING_OPERATORS };\n default:\n return { ...threadFieldBase(id), operators: TRACE_STRING_OPERATORS };\n }\n };\n\n return THREAD_FILTER_FIELD_IDS.map(field).sort((a, b) => a.label.localeCompare(b.label));\n}\n\nfunction tokenToThreadQueryPredicate(token: TraceFilterToken): TraceQueryScalarPredicate | undefined {\n const { fieldId } = token;\n if (!FIELD_IDS.has(fieldId)) return undefined;\n const operatorId = token.operatorId ?? 'is';\n const isPresence = operatorId === 'exists' || operatorId === 'notExists';\n\n const rawValues = (Array.isArray(token.value) ? token.value : [token.value]).filter(\n (value): value is string =>\n typeof value === 'string' && Boolean(value.trim()) && !isLegacyAnyValue(value, operatorId),\n );\n if (!rawValues.length && !isPresence) return undefined;\n\n let values: (string | number)[] = rawValues;\n if (NUMBER_FIELD_IDS.has(fieldId)) {\n values = rawValues.map(Number).filter(value => !Number.isNaN(value));\n if (!values.length && !isPresence) return undefined;\n }\n if (fieldId === 'traceCount' && (isPresence || values.length > 1 || !TRACE_COUNT_OPERATORS.includes(operatorId))) {\n return undefined;\n }\n\n const predicate = scalarPredicate(operatorId, fieldId, values);\n if (!predicate) return undefined;\n if ((operatorId === 'isNot' || operatorId === 'notIn') && !REQUIRED_FIELD_IDS.has(fieldId)) {\n return { op: 'or', args: [predicate, { op: 'notExists', path: fieldId }] };\n }\n return predicate;\n}\n\nfunction groupToThreadQueryPredicate(group: TraceFilterGroup): TraceQueryScalarPredicate | undefined {\n const args = group.nodes\n .map(node => (isTraceFilterGroup(node) ? groupToThreadQueryPredicate(node) : tokenToThreadQueryPredicate(node)))\n .filter((predicate): predicate is TraceQueryScalarPredicate => Boolean(predicate));\n if (args.length === 0) return undefined;\n return args.length === 1 ? args[0] : { op: group.logic, args };\n}\n\n/**\n * The thread query `where` for the filter bar's tokens and groups, or `undefined` when nothing applies.\n * Conditions the thread query can't run (unknown fields, unusable values) are left out instead of\n * failing the request.\n */\nexport function buildThreadQueryWhere(\n tokens: TraceFilterToken[],\n groups: TraceFilterGroup[],\n): TraceQueryScalarPredicate | undefined {\n const args = [...tokens.map(tokenToThreadQueryPredicate), ...groups.map(groupToThreadQueryPredicate)].filter(\n (predicate): predicate is TraceQueryScalarPredicate => Boolean(predicate),\n );\n return args.length ? { op: 'and', args } : undefined;\n}\n"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { D as TRACE_STRING_OPERATORS, S as TRACE_REQUIRED_STRING_OPERATORS, V as isLegacyAnyValue, X as traceFilterFieldIcon, Y as traceFilterFieldColor, l as TRACE_FILTER_BAR_LABELS, lt as scalarPredicate, ot as isTraceFilterGroup, r as ROOT_ENTITY_TYPE_OPTIONS, v as TRACE_NUMBER_OPERATORS, w as TRACE_STATUS_OPTIONS } from "../../trace-filters-BpIMoLTk.js";
2
+ import { MessagesSquareIcon } from "lucide-react";
2
3
  import { EntityType } from "@mastra/core/observability";
3
4
  // src/domains/threads/thread-filters.ts
4
5
  /** Thread query fields the filter bar offers. `startedAt`/`endedAt` are left to the time-range chip. */
@@ -41,7 +42,7 @@ var TRACE_COUNT_OPERATORS = [
41
42
  ];
42
43
  var THREAD_FILTER_BAR_LABELS = {
43
44
  ...TRACE_FILTER_BAR_LABELS,
44
- traceCount: "Trace count",
45
+ traceCount: "Messages",
45
46
  timeToFirstChunkMs: "Time to first chunk (ms)",
46
47
  executionSource: "Execution source",
47
48
  entityType: "Primitive type",
@@ -49,16 +50,17 @@ var THREAD_FILTER_BAR_LABELS = {
49
50
  };
50
51
  /** Thread fields without their own trace icon borrow the icon of the closest trace field. */
51
52
  var THREAD_ICON_FIELD_ALIASES = {
52
- traceCount: "traceId",
53
53
  timeToFirstChunkMs: "durationMs",
54
54
  executionSource: "runId",
55
55
  entityType: "rootEntityType",
56
56
  entityVersionId: "entityId"
57
57
  };
58
+ /** Thread fields with an icon of their own: Messages uses the Threads tab's icon. */
59
+ var THREAD_FILTER_BAR_ICONS = { traceCount: MessagesSquareIcon };
58
60
  var threadFieldBase = (id) => ({
59
61
  id,
60
62
  label: THREAD_FILTER_BAR_LABELS[id] ?? id,
61
- icon: traceFilterFieldIcon(THREAD_ICON_FIELD_ALIASES[id] ?? id),
63
+ icon: THREAD_FILTER_BAR_ICONS[id] ?? traceFilterFieldIcon(THREAD_ICON_FIELD_ALIASES[id] ?? id),
62
64
  color: traceFilterFieldColor(id)
63
65
  });
64
66
  var humanize = (value) => {
@@ -1 +1 @@
1
- {"version":3,"file":"thread-filters.es.js","names":[],"sources":["../../../src/domains/threads/thread-filters.ts"],"sourcesContent":["import { EntityType } from '@mastra/core/observability';\nimport type { TraceQueryScalarPredicate } from '@mastra/core/storage';\nimport {\n isLegacyAnyValue,\n ROOT_ENTITY_TYPE_OPTIONS,\n TRACE_FILTER_BAR_LABELS,\n TRACE_NUMBER_OPERATORS,\n TRACE_REQUIRED_STRING_OPERATORS,\n TRACE_STATUS_OPTIONS,\n TRACE_STRING_OPERATORS,\n traceFilterFieldColor,\n traceFilterFieldIcon,\n} from '../traces/trace-filters';\nimport { isTraceFilterGroup, scalarPredicate } from '../traces/trace-query-filters';\nimport type { TraceFilterGroup, TraceFilterOperatorId, TraceFilterToken } from '../traces/trace-query-filters';\nimport type { FilterBarField, FilterBarOption } from '@/ds/components/FilterBar/types';\n\n/** Thread query fields the filter bar offers. `startedAt`/`endedAt` are left to the time-range chip. */\nexport const THREAD_FILTER_FIELD_IDS = [\n 'status',\n 'traceCount',\n 'timeToFirstChunkMs',\n 'entityType',\n 'entityId',\n 'entityName',\n 'entityVersionId',\n 'threadId',\n 'resourceId',\n 'userId',\n 'organizationId',\n 'runId',\n 'sessionId',\n 'requestId',\n 'serviceName',\n 'experimentId',\n 'environment',\n 'executionSource',\n] as const;\n\nconst FIELD_IDS: ReadonlySet<string> = new Set(THREAD_FILTER_FIELD_IDS);\nconst NUMBER_FIELD_IDS: ReadonlySet<string> = new Set(['traceCount', 'timeToFirstChunkMs']);\n/** Fields every thread row carries. On any other field, \"is not X\" must also keep threads where it is missing. */\nconst REQUIRED_FIELD_IDS: ReadonlySet<string> = new Set(['threadId', 'status', 'traceCount']);\n/** The thread query compares `traceCount` but has no set membership or presence check for it. */\nconst TRACE_COUNT_OPERATORS: TraceFilterOperatorId[] = ['is', 'isNot', 'gt', 'gte', 'lt', 'lte'];\n\nconst THREAD_FILTER_BAR_LABELS: Record<string, string> = {\n ...TRACE_FILTER_BAR_LABELS,\n traceCount: 'Trace count',\n timeToFirstChunkMs: 'Time to first chunk (ms)',\n executionSource: 'Execution source',\n entityType: 'Primitive type',\n entityVersionId: 'Primitive version ID',\n};\n\n/** Thread fields without their own trace icon borrow the icon of the closest trace field. */\nconst THREAD_ICON_FIELD_ALIASES: Record<string, string> = {\n traceCount: 'traceId',\n timeToFirstChunkMs: 'durationMs',\n executionSource: 'runId',\n entityType: 'rootEntityType',\n entityVersionId: 'entityId',\n};\n\nconst threadFieldBase = (id: string) => ({\n id,\n label: THREAD_FILTER_BAR_LABELS[id] ?? id,\n icon: traceFilterFieldIcon(THREAD_ICON_FIELD_ALIASES[id] ?? id),\n color: traceFilterFieldColor(id),\n});\n\nconst humanize = (value: string) => {\n const words = value.replace(/_/g, ' ');\n return words.charAt(0).toUpperCase() + words.slice(1);\n};\n\nconst ENTITY_TYPE_LABELS: Record<string, string> = Object.fromEntries(\n ROOT_ENTITY_TYPE_OPTIONS.map(option => [option.entityType, option.label]),\n);\n\nconst ENTITY_TYPE_OPTIONS: FilterBarOption[] = Object.values(EntityType)\n .map(value => ({ value, label: ENTITY_TYPE_LABELS[value] ?? humanize(value) }))\n .sort((a, b) => a.label.localeCompare(b.label));\n\nconst STATUS_OPTIONS: FilterBarOption[] = TRACE_STATUS_OPTIONS.filter(option => option.value !== 'running').map(\n option => ({ value: option.value, label: option.label }),\n);\n\n/** FilterBar fields for the threads page: only paths and operators `queryTraceThreads()` accepts. */\nexport function createThreadFilterBarFields({\n entityNames,\n environments,\n}: {\n entityNames: readonly string[];\n environments: readonly string[];\n}): FilterBarField[] {\n const pick = (\n id: string,\n suggestions: FilterBarOption[],\n operators: TraceFilterOperatorId[] = TRACE_STRING_OPERATORS,\n ): FilterBarField => ({ ...threadFieldBase(id), operators, strict: true, suggestions });\n\n const field = (id: string): FilterBarField => {\n switch (id) {\n case 'status':\n return pick(id, STATUS_OPTIONS, TRACE_REQUIRED_STRING_OPERATORS);\n case 'entityType':\n return pick(id, ENTITY_TYPE_OPTIONS);\n case 'entityName':\n return pick(\n id,\n entityNames.map(value => ({ value })),\n );\n case 'environment':\n return pick(\n id,\n environments.map(value => ({ value })),\n );\n case 'traceCount':\n return { ...threadFieldBase(id), type: 'number', operators: TRACE_COUNT_OPERATORS };\n case 'timeToFirstChunkMs':\n return { ...threadFieldBase(id), type: 'number', operators: TRACE_NUMBER_OPERATORS };\n case 'threadId':\n return { ...threadFieldBase(id), operators: TRACE_REQUIRED_STRING_OPERATORS };\n default:\n return { ...threadFieldBase(id), operators: TRACE_STRING_OPERATORS };\n }\n };\n\n return THREAD_FILTER_FIELD_IDS.map(field).sort((a, b) => a.label.localeCompare(b.label));\n}\n\nfunction tokenToThreadQueryPredicate(token: TraceFilterToken): TraceQueryScalarPredicate | undefined {\n const { fieldId } = token;\n if (!FIELD_IDS.has(fieldId)) return undefined;\n const operatorId = token.operatorId ?? 'is';\n const isPresence = operatorId === 'exists' || operatorId === 'notExists';\n\n const rawValues = (Array.isArray(token.value) ? token.value : [token.value]).filter(\n (value): value is string =>\n typeof value === 'string' && Boolean(value.trim()) && !isLegacyAnyValue(value, operatorId),\n );\n if (!rawValues.length && !isPresence) return undefined;\n\n let values: (string | number)[] = rawValues;\n if (NUMBER_FIELD_IDS.has(fieldId)) {\n values = rawValues.map(Number).filter(value => !Number.isNaN(value));\n if (!values.length && !isPresence) return undefined;\n }\n if (fieldId === 'traceCount' && (isPresence || values.length > 1 || !TRACE_COUNT_OPERATORS.includes(operatorId))) {\n return undefined;\n }\n\n const predicate = scalarPredicate(operatorId, fieldId, values);\n if (!predicate) return undefined;\n if ((operatorId === 'isNot' || operatorId === 'notIn') && !REQUIRED_FIELD_IDS.has(fieldId)) {\n return { op: 'or', args: [predicate, { op: 'notExists', path: fieldId }] };\n }\n return predicate;\n}\n\nfunction groupToThreadQueryPredicate(group: TraceFilterGroup): TraceQueryScalarPredicate | undefined {\n const args = group.nodes\n .map(node => (isTraceFilterGroup(node) ? groupToThreadQueryPredicate(node) : tokenToThreadQueryPredicate(node)))\n .filter((predicate): predicate is TraceQueryScalarPredicate => Boolean(predicate));\n if (args.length === 0) return undefined;\n return args.length === 1 ? args[0] : { op: group.logic, args };\n}\n\n/**\n * The thread query `where` for the filter bar's tokens and groups, or `undefined` when nothing applies.\n * Conditions the thread query can't run (unknown fields, unusable values) are left out instead of\n * failing the request.\n */\nexport function buildThreadQueryWhere(\n tokens: TraceFilterToken[],\n groups: TraceFilterGroup[],\n): TraceQueryScalarPredicate | undefined {\n const args = [...tokens.map(tokenToThreadQueryPredicate), ...groups.map(groupToThreadQueryPredicate)].filter(\n (predicate): predicate is TraceQueryScalarPredicate => Boolean(predicate),\n );\n return args.length ? { op: 'and', args } : undefined;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"thread-filters.es.js","names":[],"sources":["../../../src/domains/threads/thread-filters.ts"],"sourcesContent":["import { EntityType } from '@mastra/core/observability';\nimport type { TraceQueryScalarPredicate } from '@mastra/core/storage';\nimport { MessagesSquareIcon } from 'lucide-react';\nimport type { LucideIcon } from 'lucide-react';\nimport {\n isLegacyAnyValue,\n ROOT_ENTITY_TYPE_OPTIONS,\n TRACE_FILTER_BAR_LABELS,\n TRACE_NUMBER_OPERATORS,\n TRACE_REQUIRED_STRING_OPERATORS,\n TRACE_STATUS_OPTIONS,\n TRACE_STRING_OPERATORS,\n traceFilterFieldColor,\n traceFilterFieldIcon,\n} from '../traces/trace-filters';\nimport { isTraceFilterGroup, scalarPredicate } from '../traces/trace-query-filters';\nimport type { TraceFilterGroup, TraceFilterOperatorId, TraceFilterToken } from '../traces/trace-query-filters';\nimport type { FilterBarField, FilterBarOption } from '@/ds/components/FilterBar/types';\n\n/** Thread query fields the filter bar offers. `startedAt`/`endedAt` are left to the time-range chip. */\nexport const THREAD_FILTER_FIELD_IDS = [\n 'status',\n 'traceCount',\n 'timeToFirstChunkMs',\n 'entityType',\n 'entityId',\n 'entityName',\n 'entityVersionId',\n 'threadId',\n 'resourceId',\n 'userId',\n 'organizationId',\n 'runId',\n 'sessionId',\n 'requestId',\n 'serviceName',\n 'experimentId',\n 'environment',\n 'executionSource',\n] as const;\n\nconst FIELD_IDS: ReadonlySet<string> = new Set(THREAD_FILTER_FIELD_IDS);\nconst NUMBER_FIELD_IDS: ReadonlySet<string> = new Set(['traceCount', 'timeToFirstChunkMs']);\n/** Fields every thread row carries. On any other field, \"is not X\" must also keep threads where it is missing. */\nconst REQUIRED_FIELD_IDS: ReadonlySet<string> = new Set(['threadId', 'status', 'traceCount']);\n/** The thread query compares `traceCount` but has no set membership or presence check for it. */\nconst TRACE_COUNT_OPERATORS: TraceFilterOperatorId[] = ['is', 'isNot', 'gt', 'gte', 'lt', 'lte'];\n\nconst THREAD_FILTER_BAR_LABELS: Record<string, string> = {\n ...TRACE_FILTER_BAR_LABELS,\n traceCount: 'Messages',\n timeToFirstChunkMs: 'Time to first chunk (ms)',\n executionSource: 'Execution source',\n entityType: 'Primitive type',\n entityVersionId: 'Primitive version ID',\n};\n\n/** Thread fields without their own trace icon borrow the icon of the closest trace field. */\nconst THREAD_ICON_FIELD_ALIASES: Record<string, string> = {\n timeToFirstChunkMs: 'durationMs',\n executionSource: 'runId',\n entityType: 'rootEntityType',\n entityVersionId: 'entityId',\n};\n\n/** Thread fields with an icon of their own: Messages uses the Threads tab's icon. */\nconst THREAD_FILTER_BAR_ICONS: Record<string, LucideIcon> = {\n traceCount: MessagesSquareIcon,\n};\n\nconst threadFieldBase = (id: string) => ({\n id,\n label: THREAD_FILTER_BAR_LABELS[id] ?? id,\n icon: THREAD_FILTER_BAR_ICONS[id] ?? traceFilterFieldIcon(THREAD_ICON_FIELD_ALIASES[id] ?? id),\n color: traceFilterFieldColor(id),\n});\n\nconst humanize = (value: string) => {\n const words = value.replace(/_/g, ' ');\n return words.charAt(0).toUpperCase() + words.slice(1);\n};\n\nconst ENTITY_TYPE_LABELS: Record<string, string> = Object.fromEntries(\n ROOT_ENTITY_TYPE_OPTIONS.map(option => [option.entityType, option.label]),\n);\n\nconst ENTITY_TYPE_OPTIONS: FilterBarOption[] = Object.values(EntityType)\n .map(value => ({ value, label: ENTITY_TYPE_LABELS[value] ?? humanize(value) }))\n .sort((a, b) => a.label.localeCompare(b.label));\n\nconst STATUS_OPTIONS: FilterBarOption[] = TRACE_STATUS_OPTIONS.filter(option => option.value !== 'running').map(\n option => ({ value: option.value, label: option.label }),\n);\n\n/** FilterBar fields for the threads page: only paths and operators `queryTraceThreads()` accepts. */\nexport function createThreadFilterBarFields({\n entityNames,\n environments,\n}: {\n entityNames: readonly string[];\n environments: readonly string[];\n}): FilterBarField[] {\n const pick = (\n id: string,\n suggestions: FilterBarOption[],\n operators: TraceFilterOperatorId[] = TRACE_STRING_OPERATORS,\n ): FilterBarField => ({ ...threadFieldBase(id), operators, strict: true, suggestions });\n\n const field = (id: string): FilterBarField => {\n switch (id) {\n case 'status':\n return pick(id, STATUS_OPTIONS, TRACE_REQUIRED_STRING_OPERATORS);\n case 'entityType':\n return pick(id, ENTITY_TYPE_OPTIONS);\n case 'entityName':\n return pick(\n id,\n entityNames.map(value => ({ value })),\n );\n case 'environment':\n return pick(\n id,\n environments.map(value => ({ value })),\n );\n case 'traceCount':\n return { ...threadFieldBase(id), type: 'number', operators: TRACE_COUNT_OPERATORS };\n case 'timeToFirstChunkMs':\n return { ...threadFieldBase(id), type: 'number', operators: TRACE_NUMBER_OPERATORS };\n case 'threadId':\n return { ...threadFieldBase(id), operators: TRACE_REQUIRED_STRING_OPERATORS };\n default:\n return { ...threadFieldBase(id), operators: TRACE_STRING_OPERATORS };\n }\n };\n\n return THREAD_FILTER_FIELD_IDS.map(field).sort((a, b) => a.label.localeCompare(b.label));\n}\n\nfunction tokenToThreadQueryPredicate(token: TraceFilterToken): TraceQueryScalarPredicate | undefined {\n const { fieldId } = token;\n if (!FIELD_IDS.has(fieldId)) return undefined;\n const operatorId = token.operatorId ?? 'is';\n const isPresence = operatorId === 'exists' || operatorId === 'notExists';\n\n const rawValues = (Array.isArray(token.value) ? token.value : [token.value]).filter(\n (value): value is string =>\n typeof value === 'string' && Boolean(value.trim()) && !isLegacyAnyValue(value, operatorId),\n );\n if (!rawValues.length && !isPresence) return undefined;\n\n let values: (string | number)[] = rawValues;\n if (NUMBER_FIELD_IDS.has(fieldId)) {\n values = rawValues.map(Number).filter(value => !Number.isNaN(value));\n if (!values.length && !isPresence) return undefined;\n }\n if (fieldId === 'traceCount' && (isPresence || values.length > 1 || !TRACE_COUNT_OPERATORS.includes(operatorId))) {\n return undefined;\n }\n\n const predicate = scalarPredicate(operatorId, fieldId, values);\n if (!predicate) return undefined;\n if ((operatorId === 'isNot' || operatorId === 'notIn') && !REQUIRED_FIELD_IDS.has(fieldId)) {\n return { op: 'or', args: [predicate, { op: 'notExists', path: fieldId }] };\n }\n return predicate;\n}\n\nfunction groupToThreadQueryPredicate(group: TraceFilterGroup): TraceQueryScalarPredicate | undefined {\n const args = group.nodes\n .map(node => (isTraceFilterGroup(node) ? groupToThreadQueryPredicate(node) : tokenToThreadQueryPredicate(node)))\n .filter((predicate): predicate is TraceQueryScalarPredicate => Boolean(predicate));\n if (args.length === 0) return undefined;\n return args.length === 1 ? args[0] : { op: group.logic, args };\n}\n\n/**\n * The thread query `where` for the filter bar's tokens and groups, or `undefined` when nothing applies.\n * Conditions the thread query can't run (unknown fields, unusable values) are left out instead of\n * failing the request.\n */\nexport function buildThreadQueryWhere(\n tokens: TraceFilterToken[],\n groups: TraceFilterGroup[],\n): TraceQueryScalarPredicate | undefined {\n const args = [...tokens.map(tokenToThreadQueryPredicate), ...groups.map(groupToThreadQueryPredicate)].filter(\n (predicate): predicate is TraceQueryScalarPredicate => Boolean(predicate),\n );\n return args.length ? { op: 'and', args } : undefined;\n}\n"],"mappings":"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"}
@@ -16,6 +16,7 @@ function threadToListRow(thread) {
16
16
  errorPreview: thread.errorPreview ?? void 0,
17
17
  startedAt: thread.startedAt,
18
18
  endedAt: thread.endedAt,
19
+ traceCount: thread.traceCount,
19
20
  createdAt: thread.startedAt
20
21
  };
21
22
  }
@@ -1 +1 @@
1
- {"version":3,"file":"thread-list-row.cjs.js","names":[],"sources":["../../../src/domains/threads/thread-list-row.ts"],"sourcesContent":["import type { ThreadRow } from '@mastra/react/hooks/traces';\nimport type { TracesListViewTrace } from '@/domains/traces/components/traces-list-view';\n\n// A thread spans several traces; its latest one keys the row, since it is unique per thread.\nexport function threadToListRow(thread: ThreadRow): TracesListViewTrace {\n return {\n traceId: thread.lastTraceId,\n name: thread.entityName ?? thread.threadId,\n entityType: thread.entityType,\n entityId: thread.entityId,\n entityName: thread.entityName,\n threadId: thread.threadId,\n resourceId: thread.resourceId,\n environment: thread.environment,\n status: thread.status,\n inputPreview: thread.inputPreview,\n outputPreview: thread.outputPreview ?? undefined,\n errorPreview: thread.errorPreview ?? undefined,\n startedAt: thread.startedAt,\n endedAt: thread.endedAt,\n createdAt: thread.startedAt,\n };\n}\n"],"mappings":";;AAIA,SAAgB,gBAAgB,QAAwC;CACtE,OAAO;EACL,SAAS,OAAO;EAChB,MAAM,OAAO,cAAc,OAAO;EAClC,YAAY,OAAO;EACnB,UAAU,OAAO;EACjB,YAAY,OAAO;EACnB,UAAU,OAAO;EACjB,YAAY,OAAO;EACnB,aAAa,OAAO;EACpB,QAAQ,OAAO;EACf,cAAc,OAAO;EACrB,eAAe,OAAO,iBAAiB,KAAA;EACvC,cAAc,OAAO,gBAAgB,KAAA;EACrC,WAAW,OAAO;EAClB,SAAS,OAAO;EAChB,WAAW,OAAO;CACpB;AACF"}
1
+ {"version":3,"file":"thread-list-row.cjs.js","names":[],"sources":["../../../src/domains/threads/thread-list-row.ts"],"sourcesContent":["import type { ThreadRow } from '@mastra/react/hooks/traces';\nimport type { TracesListViewTrace } from '@/domains/traces/components/traces-list-view';\n\n// A thread spans several traces; its latest one keys the row, since it is unique per thread.\nexport function threadToListRow(thread: ThreadRow): TracesListViewTrace {\n return {\n traceId: thread.lastTraceId,\n name: thread.entityName ?? thread.threadId,\n entityType: thread.entityType,\n entityId: thread.entityId,\n entityName: thread.entityName,\n threadId: thread.threadId,\n resourceId: thread.resourceId,\n environment: thread.environment,\n status: thread.status,\n inputPreview: thread.inputPreview,\n outputPreview: thread.outputPreview ?? undefined,\n errorPreview: thread.errorPreview ?? undefined,\n startedAt: thread.startedAt,\n endedAt: thread.endedAt,\n traceCount: thread.traceCount,\n createdAt: thread.startedAt,\n };\n}\n"],"mappings":";;AAIA,SAAgB,gBAAgB,QAAwC;CACtE,OAAO;EACL,SAAS,OAAO;EAChB,MAAM,OAAO,cAAc,OAAO;EAClC,YAAY,OAAO;EACnB,UAAU,OAAO;EACjB,YAAY,OAAO;EACnB,UAAU,OAAO;EACjB,YAAY,OAAO;EACnB,aAAa,OAAO;EACpB,QAAQ,OAAO;EACf,cAAc,OAAO;EACrB,eAAe,OAAO,iBAAiB,KAAA;EACvC,cAAc,OAAO,gBAAgB,KAAA;EACrC,WAAW,OAAO;EAClB,SAAS,OAAO;EAChB,YAAY,OAAO;EACnB,WAAW,OAAO;CACpB;AACF"}
@@ -15,6 +15,7 @@ function threadToListRow(thread) {
15
15
  errorPreview: thread.errorPreview ?? void 0,
16
16
  startedAt: thread.startedAt,
17
17
  endedAt: thread.endedAt,
18
+ traceCount: thread.traceCount,
18
19
  createdAt: thread.startedAt
19
20
  };
20
21
  }
@@ -1 +1 @@
1
- {"version":3,"file":"thread-list-row.es.js","names":[],"sources":["../../../src/domains/threads/thread-list-row.ts"],"sourcesContent":["import type { ThreadRow } from '@mastra/react/hooks/traces';\nimport type { TracesListViewTrace } from '@/domains/traces/components/traces-list-view';\n\n// A thread spans several traces; its latest one keys the row, since it is unique per thread.\nexport function threadToListRow(thread: ThreadRow): TracesListViewTrace {\n return {\n traceId: thread.lastTraceId,\n name: thread.entityName ?? thread.threadId,\n entityType: thread.entityType,\n entityId: thread.entityId,\n entityName: thread.entityName,\n threadId: thread.threadId,\n resourceId: thread.resourceId,\n environment: thread.environment,\n status: thread.status,\n inputPreview: thread.inputPreview,\n outputPreview: thread.outputPreview ?? undefined,\n errorPreview: thread.errorPreview ?? undefined,\n startedAt: thread.startedAt,\n endedAt: thread.endedAt,\n createdAt: thread.startedAt,\n };\n}\n"],"mappings":";AAIA,SAAgB,gBAAgB,QAAwC;CACtE,OAAO;EACL,SAAS,OAAO;EAChB,MAAM,OAAO,cAAc,OAAO;EAClC,YAAY,OAAO;EACnB,UAAU,OAAO;EACjB,YAAY,OAAO;EACnB,UAAU,OAAO;EACjB,YAAY,OAAO;EACnB,aAAa,OAAO;EACpB,QAAQ,OAAO;EACf,cAAc,OAAO;EACrB,eAAe,OAAO,iBAAiB,KAAA;EACvC,cAAc,OAAO,gBAAgB,KAAA;EACrC,WAAW,OAAO;EAClB,SAAS,OAAO;EAChB,WAAW,OAAO;CACpB;AACF"}
1
+ {"version":3,"file":"thread-list-row.es.js","names":[],"sources":["../../../src/domains/threads/thread-list-row.ts"],"sourcesContent":["import type { ThreadRow } from '@mastra/react/hooks/traces';\nimport type { TracesListViewTrace } from '@/domains/traces/components/traces-list-view';\n\n// A thread spans several traces; its latest one keys the row, since it is unique per thread.\nexport function threadToListRow(thread: ThreadRow): TracesListViewTrace {\n return {\n traceId: thread.lastTraceId,\n name: thread.entityName ?? thread.threadId,\n entityType: thread.entityType,\n entityId: thread.entityId,\n entityName: thread.entityName,\n threadId: thread.threadId,\n resourceId: thread.resourceId,\n environment: thread.environment,\n status: thread.status,\n inputPreview: thread.inputPreview,\n outputPreview: thread.outputPreview ?? undefined,\n errorPreview: thread.errorPreview ?? undefined,\n startedAt: thread.startedAt,\n endedAt: thread.endedAt,\n traceCount: thread.traceCount,\n createdAt: thread.startedAt,\n };\n}\n"],"mappings":";AAIA,SAAgB,gBAAgB,QAAwC;CACtE,OAAO;EACL,SAAS,OAAO;EAChB,MAAM,OAAO,cAAc,OAAO;EAClC,YAAY,OAAO;EACnB,UAAU,OAAO;EACjB,YAAY,OAAO;EACnB,UAAU,OAAO;EACjB,YAAY,OAAO;EACnB,aAAa,OAAO;EACpB,QAAQ,OAAO;EACf,cAAc,OAAO;EACrB,eAAe,OAAO,iBAAiB,KAAA;EACvC,cAAc,OAAO,gBAAgB,KAAA;EACrC,WAAW,OAAO;EAClB,SAAS,OAAO;EAChB,YAAY,OAAO;EACnB,WAAW,OAAO;CACpB;AACF"}
@@ -17,6 +17,7 @@ var COLUMN_LABELS = {
17
17
  input: "Input",
18
18
  output: "Output",
19
19
  duration: "Duration",
20
+ traceCount: "Messages",
20
21
  timeToFirstChunk: "Time to first chunk",
21
22
  endTime: "End",
22
23
  environment: "Environment",
@@ -1 +1 @@
1
- {"version":3,"file":"trace-columns-menu.cjs.js","names":["TRACE_COLUMN_CATALOGS","useState","useMemo","_Fragment","DropdownMenu","Button","Columns3Icon","TRACE_USAGE_COLUMNS","Txt","TRACE_CUSTOM_COLUMN_FIELDS","TRACE_CUSTOM_COLUMN_LABELS","PlusIcon","Dialog","DialogContent","Form","DialogHeader","DialogTitle","DialogDescription","DialogBody","Field","FieldLabel","Combobox","FieldError","DialogFooter","DialogCancel","DialogAction"],"sources":["../../../../src/domains/traces/components/trace-columns-menu.tsx"],"sourcesContent":["import { Columns3Icon, PlusIcon } from 'lucide-react';\nimport { useMemo, useState } from 'react';\nimport type { FormEvent } from 'react';\nimport {\n TRACE_COLUMN_CATALOGS,\n TRACE_CUSTOM_COLUMN_FIELDS,\n TRACE_CUSTOM_COLUMN_LABELS,\n TRACE_USAGE_COLUMNS,\n} from '../trace-list-columns';\nimport type {\n TraceColumnCatalog,\n TraceColumnPreferences,\n TraceCustomColumn,\n TraceOptionalColumn,\n} from '../trace-list-columns';\nimport { Button } from '@/ds/components/Button';\nimport { Combobox } from '@/ds/components/Combobox';\nimport {\n Dialog,\n DialogAction,\n DialogBody,\n DialogCancel,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@/ds/components/Dialog';\nimport { DropdownMenu } from '@/ds/components/DropdownMenu';\nimport { Field, FieldError, FieldLabel } from '@/ds/components/Field';\nimport { Form } from '@/ds/components/Form';\nimport { Txt } from '@/ds/components/Txt';\n\nconst EMPTY_KEYS: readonly string[] = [];\n\nconst COLUMN_LABELS: Record<TraceOptionalColumn, string> = {\n type: 'Primitive type',\n input: 'Input',\n output: 'Output',\n duration: 'Duration',\n timeToFirstChunk: 'Time to first chunk',\n endTime: 'End',\n environment: 'Environment',\n model: 'Model',\n provider: 'Provider',\n inputTokens: 'Input tokens',\n outputTokens: 'Output tokens',\n totalTokens: 'Total tokens',\n estimatedCost: 'Estimated cost',\n};\n\ntype TraceColumnsMenuProps = {\n preferences: TraceColumnPreferences;\n /** Which columns the list offers. Defaults to the traces catalog. */\n catalog?: TraceColumnCatalog;\n /** Top-level metadata keys observed on traces in the current time range, offered in the picker. */\n availableMetadataKeys?: readonly string[];\n usageDisabledReason?: string;\n /** When false (server without the trace-query API), metadata columns can't be added. Defaults to true. */\n withQueryTrace?: boolean;\n onToggleColumn: (column: TraceOptionalColumn) => void;\n onAddCustomColumn: (field: TraceCustomColumn) => void;\n onRemoveCustomColumn: (field: TraceCustomColumn) => void;\n onAddMetadataColumn: (key: string) => void;\n onRemoveMetadataColumn: (key: string) => void;\n onReset: () => void;\n /** Keeps the trigger in place but inert, e.g. while capabilities load. */\n disabled?: boolean;\n};\n\nexport function TraceColumnsMenu({\n preferences,\n catalog = TRACE_COLUMN_CATALOGS.traces,\n availableMetadataKeys = EMPTY_KEYS,\n usageDisabledReason,\n withQueryTrace = true,\n onToggleColumn,\n onAddCustomColumn,\n onRemoveCustomColumn,\n onAddMetadataColumn,\n onRemoveMetadataColumn,\n onReset,\n disabled,\n}: TraceColumnsMenuProps) {\n const withMetadata = catalog.metadata && withQueryTrace;\n const [isMetadataDialogOpen, setIsMetadataDialogOpen] = useState(false);\n const [metadataKey, setMetadataKey] = useState('');\n const [metadataError, setMetadataError] = useState<string | undefined>();\n\n const metadataKeyOptions = useMemo(() => {\n const keys = availableMetadataKeys.filter(key => !preferences.metadataKeys.includes(key));\n if (metadataKey && !keys.includes(metadataKey)) keys.push(metadataKey);\n return keys.map(key => ({ label: key, value: key }));\n }, [availableMetadataKeys, preferences.metadataKeys, metadataKey]);\n\n const handleDialogOpenChange = (open: boolean) => {\n setIsMetadataDialogOpen(open);\n if (!open) {\n setMetadataKey('');\n setMetadataError(undefined);\n }\n };\n\n const handleAddMetadata = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const normalizedKey = metadataKey.trim();\n if (!normalizedKey) {\n setMetadataError('Enter a metadata key.');\n return;\n }\n if (preferences.metadataKeys.includes(normalizedKey)) {\n setMetadataError('That metadata column is already visible.');\n return;\n }\n\n onAddMetadataColumn(normalizedKey);\n handleDialogOpenChange(false);\n };\n\n return (\n <>\n <DropdownMenu>\n <DropdownMenu.Trigger\n disabled={disabled}\n render={\n <Button variant=\"ghost\" size=\"md\" icon={<Columns3Icon aria-hidden />}>\n Columns\n </Button>\n }\n />\n <DropdownMenu.Content align=\"end\" className=\"min-w-56\">\n <DropdownMenu.Label>Standard columns</DropdownMenu.Label>\n {catalog.standardColumns.map(column => (\n <DropdownMenu.CheckboxItem\n key={column}\n checked={preferences.visibleColumns.includes(column)}\n onCheckedChange={() => onToggleColumn(column)}\n >\n {COLUMN_LABELS[column]}\n </DropdownMenu.CheckboxItem>\n ))}\n\n {catalog.usage && (\n <>\n <DropdownMenu.Separator />\n <DropdownMenu.Label>Usage columns</DropdownMenu.Label>\n {TRACE_USAGE_COLUMNS.map(column => (\n <DropdownMenu.CheckboxItem\n key={column}\n checked={preferences.visibleColumns.includes(column)}\n disabled={Boolean(usageDisabledReason)}\n onCheckedChange={() => onToggleColumn(column)}\n >\n {COLUMN_LABELS[column]}\n </DropdownMenu.CheckboxItem>\n ))}\n {usageDisabledReason && (\n <Txt variant=\"meta\" tone=\"faint\" className=\"px-2 py-1\" role=\"note\">\n {usageDisabledReason}\n </Txt>\n )}\n </>\n )}\n\n <DropdownMenu.Separator />\n <DropdownMenu.Label>Custom columns</DropdownMenu.Label>\n {TRACE_CUSTOM_COLUMN_FIELDS.map(field => {\n const isVisible = preferences.customColumns.includes(field);\n return (\n <DropdownMenu.CheckboxItem\n key={field}\n checked={isVisible}\n onCheckedChange={() => (isVisible ? onRemoveCustomColumn(field) : onAddCustomColumn(field))}\n >\n {TRACE_CUSTOM_COLUMN_LABELS[field]}\n </DropdownMenu.CheckboxItem>\n );\n })}\n\n {catalog.metadata && (withQueryTrace || preferences.metadataKeys.length > 0) && (\n <>\n <DropdownMenu.Separator />\n <DropdownMenu.Label>Metadata columns</DropdownMenu.Label>\n {preferences.metadataKeys.map(key => (\n <DropdownMenu.CheckboxItem\n key={key}\n checked\n title={key}\n onCheckedChange={() => onRemoveMetadataColumn(key)}\n >\n {key}\n </DropdownMenu.CheckboxItem>\n ))}\n {withMetadata && (\n <DropdownMenu.Item onSelect={() => setIsMetadataDialogOpen(true)}>\n <PlusIcon aria-hidden />\n Add metadata column\n </DropdownMenu.Item>\n )}\n </>\n )}\n\n <DropdownMenu.Separator />\n <DropdownMenu.Item onSelect={onReset}>Reset to defaults</DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>\n\n {withMetadata && (\n <Dialog open={isMetadataDialogOpen} onOpenChange={handleDialogOpenChange}>\n <DialogContent>\n <Form onSubmit={handleAddMetadata} className=\"gap-0\">\n <DialogHeader>\n <DialogTitle>Add metadata column</DialogTitle>\n <DialogDescription>\n Pick a top-level trace metadata key observed in the current time range, or type one. Only the key is\n saved, never its values.\n </DialogDescription>\n </DialogHeader>\n <DialogBody>\n <Field invalid={Boolean(metadataError)}>\n <FieldLabel>Metadata key</FieldLabel>\n <Combobox\n options={metadataKeyOptions}\n value={metadataKey}\n onValueChange={key => {\n setMetadataKey(key);\n setMetadataError(undefined);\n }}\n allowCustomValue\n placeholder=\"Select a metadata key…\"\n searchPlaceholder=\"Search metadata keys…\"\n emptyText=\"No metadata keys observed. Type one to add it.\"\n />\n <FieldError>{metadataError}</FieldError>\n </Field>\n </DialogBody>\n <DialogFooter>\n <DialogCancel>Cancel</DialogCancel>\n <DialogAction type=\"submit\">Add column</DialogAction>\n </DialogFooter>\n </Form>\n </DialogContent>\n </Dialog>\n )}\n </>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"trace-columns-menu.cjs.js","names":["TRACE_COLUMN_CATALOGS","useState","useMemo","_Fragment","DropdownMenu","Button","Columns3Icon","TRACE_USAGE_COLUMNS","Txt","TRACE_CUSTOM_COLUMN_FIELDS","TRACE_CUSTOM_COLUMN_LABELS","PlusIcon","Dialog","DialogContent","Form","DialogHeader","DialogTitle","DialogDescription","DialogBody","Field","FieldLabel","Combobox","FieldError","DialogFooter","DialogCancel","DialogAction"],"sources":["../../../../src/domains/traces/components/trace-columns-menu.tsx"],"sourcesContent":["import { Columns3Icon, PlusIcon } from 'lucide-react';\nimport { useMemo, useState } from 'react';\nimport type { FormEvent } from 'react';\nimport {\n TRACE_COLUMN_CATALOGS,\n TRACE_CUSTOM_COLUMN_FIELDS,\n TRACE_CUSTOM_COLUMN_LABELS,\n TRACE_USAGE_COLUMNS,\n} from '../trace-list-columns';\nimport type {\n TraceColumnCatalog,\n TraceColumnPreferences,\n TraceCustomColumn,\n TraceOptionalColumn,\n} from '../trace-list-columns';\nimport { Button } from '@/ds/components/Button';\nimport { Combobox } from '@/ds/components/Combobox';\nimport {\n Dialog,\n DialogAction,\n DialogBody,\n DialogCancel,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@/ds/components/Dialog';\nimport { DropdownMenu } from '@/ds/components/DropdownMenu';\nimport { Field, FieldError, FieldLabel } from '@/ds/components/Field';\nimport { Form } from '@/ds/components/Form';\nimport { Txt } from '@/ds/components/Txt';\n\nconst EMPTY_KEYS: readonly string[] = [];\n\nconst COLUMN_LABELS: Record<TraceOptionalColumn, string> = {\n type: 'Primitive type',\n input: 'Input',\n output: 'Output',\n duration: 'Duration',\n traceCount: 'Messages',\n timeToFirstChunk: 'Time to first chunk',\n endTime: 'End',\n environment: 'Environment',\n model: 'Model',\n provider: 'Provider',\n inputTokens: 'Input tokens',\n outputTokens: 'Output tokens',\n totalTokens: 'Total tokens',\n estimatedCost: 'Estimated cost',\n};\n\ntype TraceColumnsMenuProps = {\n preferences: TraceColumnPreferences;\n /** Which columns the list offers. Defaults to the traces catalog. */\n catalog?: TraceColumnCatalog;\n /** Top-level metadata keys observed on traces in the current time range, offered in the picker. */\n availableMetadataKeys?: readonly string[];\n usageDisabledReason?: string;\n /** When false (server without the trace-query API), metadata columns can't be added. Defaults to true. */\n withQueryTrace?: boolean;\n onToggleColumn: (column: TraceOptionalColumn) => void;\n onAddCustomColumn: (field: TraceCustomColumn) => void;\n onRemoveCustomColumn: (field: TraceCustomColumn) => void;\n onAddMetadataColumn: (key: string) => void;\n onRemoveMetadataColumn: (key: string) => void;\n onReset: () => void;\n /** Keeps the trigger in place but inert, e.g. while capabilities load. */\n disabled?: boolean;\n};\n\nexport function TraceColumnsMenu({\n preferences,\n catalog = TRACE_COLUMN_CATALOGS.traces,\n availableMetadataKeys = EMPTY_KEYS,\n usageDisabledReason,\n withQueryTrace = true,\n onToggleColumn,\n onAddCustomColumn,\n onRemoveCustomColumn,\n onAddMetadataColumn,\n onRemoveMetadataColumn,\n onReset,\n disabled,\n}: TraceColumnsMenuProps) {\n const withMetadata = catalog.metadata && withQueryTrace;\n const [isMetadataDialogOpen, setIsMetadataDialogOpen] = useState(false);\n const [metadataKey, setMetadataKey] = useState('');\n const [metadataError, setMetadataError] = useState<string | undefined>();\n\n const metadataKeyOptions = useMemo(() => {\n const keys = availableMetadataKeys.filter(key => !preferences.metadataKeys.includes(key));\n if (metadataKey && !keys.includes(metadataKey)) keys.push(metadataKey);\n return keys.map(key => ({ label: key, value: key }));\n }, [availableMetadataKeys, preferences.metadataKeys, metadataKey]);\n\n const handleDialogOpenChange = (open: boolean) => {\n setIsMetadataDialogOpen(open);\n if (!open) {\n setMetadataKey('');\n setMetadataError(undefined);\n }\n };\n\n const handleAddMetadata = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const normalizedKey = metadataKey.trim();\n if (!normalizedKey) {\n setMetadataError('Enter a metadata key.');\n return;\n }\n if (preferences.metadataKeys.includes(normalizedKey)) {\n setMetadataError('That metadata column is already visible.');\n return;\n }\n\n onAddMetadataColumn(normalizedKey);\n handleDialogOpenChange(false);\n };\n\n return (\n <>\n <DropdownMenu>\n <DropdownMenu.Trigger\n disabled={disabled}\n render={\n <Button variant=\"ghost\" size=\"md\" icon={<Columns3Icon aria-hidden />}>\n Columns\n </Button>\n }\n />\n <DropdownMenu.Content align=\"end\" className=\"min-w-56\">\n <DropdownMenu.Label>Standard columns</DropdownMenu.Label>\n {catalog.standardColumns.map(column => (\n <DropdownMenu.CheckboxItem\n key={column}\n checked={preferences.visibleColumns.includes(column)}\n onCheckedChange={() => onToggleColumn(column)}\n >\n {COLUMN_LABELS[column]}\n </DropdownMenu.CheckboxItem>\n ))}\n\n {catalog.usage && (\n <>\n <DropdownMenu.Separator />\n <DropdownMenu.Label>Usage columns</DropdownMenu.Label>\n {TRACE_USAGE_COLUMNS.map(column => (\n <DropdownMenu.CheckboxItem\n key={column}\n checked={preferences.visibleColumns.includes(column)}\n disabled={Boolean(usageDisabledReason)}\n onCheckedChange={() => onToggleColumn(column)}\n >\n {COLUMN_LABELS[column]}\n </DropdownMenu.CheckboxItem>\n ))}\n {usageDisabledReason && (\n <Txt variant=\"meta\" tone=\"faint\" className=\"px-2 py-1\" role=\"note\">\n {usageDisabledReason}\n </Txt>\n )}\n </>\n )}\n\n <DropdownMenu.Separator />\n <DropdownMenu.Label>Custom columns</DropdownMenu.Label>\n {TRACE_CUSTOM_COLUMN_FIELDS.map(field => {\n const isVisible = preferences.customColumns.includes(field);\n return (\n <DropdownMenu.CheckboxItem\n key={field}\n checked={isVisible}\n onCheckedChange={() => (isVisible ? onRemoveCustomColumn(field) : onAddCustomColumn(field))}\n >\n {TRACE_CUSTOM_COLUMN_LABELS[field]}\n </DropdownMenu.CheckboxItem>\n );\n })}\n\n {catalog.metadata && (withQueryTrace || preferences.metadataKeys.length > 0) && (\n <>\n <DropdownMenu.Separator />\n <DropdownMenu.Label>Metadata columns</DropdownMenu.Label>\n {preferences.metadataKeys.map(key => (\n <DropdownMenu.CheckboxItem\n key={key}\n checked\n title={key}\n onCheckedChange={() => onRemoveMetadataColumn(key)}\n >\n {key}\n </DropdownMenu.CheckboxItem>\n ))}\n {withMetadata && (\n <DropdownMenu.Item onSelect={() => setIsMetadataDialogOpen(true)}>\n <PlusIcon aria-hidden />\n Add metadata column\n </DropdownMenu.Item>\n )}\n </>\n )}\n\n <DropdownMenu.Separator />\n <DropdownMenu.Item onSelect={onReset}>Reset to defaults</DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>\n\n {withMetadata && (\n <Dialog open={isMetadataDialogOpen} onOpenChange={handleDialogOpenChange}>\n <DialogContent>\n <Form onSubmit={handleAddMetadata} className=\"gap-0\">\n <DialogHeader>\n <DialogTitle>Add metadata column</DialogTitle>\n <DialogDescription>\n Pick a top-level trace metadata key observed in the current time range, or type one. Only the key is\n saved, never its values.\n </DialogDescription>\n </DialogHeader>\n <DialogBody>\n <Field invalid={Boolean(metadataError)}>\n <FieldLabel>Metadata key</FieldLabel>\n <Combobox\n options={metadataKeyOptions}\n value={metadataKey}\n onValueChange={key => {\n setMetadataKey(key);\n setMetadataError(undefined);\n }}\n allowCustomValue\n placeholder=\"Select a metadata key…\"\n searchPlaceholder=\"Search metadata keys…\"\n emptyText=\"No metadata keys observed. Type one to add it.\"\n />\n <FieldError>{metadataError}</FieldError>\n </Field>\n </DialogBody>\n <DialogFooter>\n <DialogCancel>Cancel</DialogCancel>\n <DialogAction type=\"submit\">Add column</DialogAction>\n </DialogFooter>\n </Form>\n </DialogContent>\n </Dialog>\n )}\n </>\n );\n}\n"],"mappings":"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"}
@@ -16,6 +16,7 @@ var COLUMN_LABELS = {
16
16
  input: "Input",
17
17
  output: "Output",
18
18
  duration: "Duration",
19
+ traceCount: "Messages",
19
20
  timeToFirstChunk: "Time to first chunk",
20
21
  endTime: "End",
21
22
  environment: "Environment",
@@ -1 +1 @@
1
- {"version":3,"file":"trace-columns-menu.es.js","names":["_Fragment"],"sources":["../../../../src/domains/traces/components/trace-columns-menu.tsx"],"sourcesContent":["import { Columns3Icon, PlusIcon } from 'lucide-react';\nimport { useMemo, useState } from 'react';\nimport type { FormEvent } from 'react';\nimport {\n TRACE_COLUMN_CATALOGS,\n TRACE_CUSTOM_COLUMN_FIELDS,\n TRACE_CUSTOM_COLUMN_LABELS,\n TRACE_USAGE_COLUMNS,\n} from '../trace-list-columns';\nimport type {\n TraceColumnCatalog,\n TraceColumnPreferences,\n TraceCustomColumn,\n TraceOptionalColumn,\n} from '../trace-list-columns';\nimport { Button } from '@/ds/components/Button';\nimport { Combobox } from '@/ds/components/Combobox';\nimport {\n Dialog,\n DialogAction,\n DialogBody,\n DialogCancel,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@/ds/components/Dialog';\nimport { DropdownMenu } from '@/ds/components/DropdownMenu';\nimport { Field, FieldError, FieldLabel } from '@/ds/components/Field';\nimport { Form } from '@/ds/components/Form';\nimport { Txt } from '@/ds/components/Txt';\n\nconst EMPTY_KEYS: readonly string[] = [];\n\nconst COLUMN_LABELS: Record<TraceOptionalColumn, string> = {\n type: 'Primitive type',\n input: 'Input',\n output: 'Output',\n duration: 'Duration',\n timeToFirstChunk: 'Time to first chunk',\n endTime: 'End',\n environment: 'Environment',\n model: 'Model',\n provider: 'Provider',\n inputTokens: 'Input tokens',\n outputTokens: 'Output tokens',\n totalTokens: 'Total tokens',\n estimatedCost: 'Estimated cost',\n};\n\ntype TraceColumnsMenuProps = {\n preferences: TraceColumnPreferences;\n /** Which columns the list offers. Defaults to the traces catalog. */\n catalog?: TraceColumnCatalog;\n /** Top-level metadata keys observed on traces in the current time range, offered in the picker. */\n availableMetadataKeys?: readonly string[];\n usageDisabledReason?: string;\n /** When false (server without the trace-query API), metadata columns can't be added. Defaults to true. */\n withQueryTrace?: boolean;\n onToggleColumn: (column: TraceOptionalColumn) => void;\n onAddCustomColumn: (field: TraceCustomColumn) => void;\n onRemoveCustomColumn: (field: TraceCustomColumn) => void;\n onAddMetadataColumn: (key: string) => void;\n onRemoveMetadataColumn: (key: string) => void;\n onReset: () => void;\n /** Keeps the trigger in place but inert, e.g. while capabilities load. */\n disabled?: boolean;\n};\n\nexport function TraceColumnsMenu({\n preferences,\n catalog = TRACE_COLUMN_CATALOGS.traces,\n availableMetadataKeys = EMPTY_KEYS,\n usageDisabledReason,\n withQueryTrace = true,\n onToggleColumn,\n onAddCustomColumn,\n onRemoveCustomColumn,\n onAddMetadataColumn,\n onRemoveMetadataColumn,\n onReset,\n disabled,\n}: TraceColumnsMenuProps) {\n const withMetadata = catalog.metadata && withQueryTrace;\n const [isMetadataDialogOpen, setIsMetadataDialogOpen] = useState(false);\n const [metadataKey, setMetadataKey] = useState('');\n const [metadataError, setMetadataError] = useState<string | undefined>();\n\n const metadataKeyOptions = useMemo(() => {\n const keys = availableMetadataKeys.filter(key => !preferences.metadataKeys.includes(key));\n if (metadataKey && !keys.includes(metadataKey)) keys.push(metadataKey);\n return keys.map(key => ({ label: key, value: key }));\n }, [availableMetadataKeys, preferences.metadataKeys, metadataKey]);\n\n const handleDialogOpenChange = (open: boolean) => {\n setIsMetadataDialogOpen(open);\n if (!open) {\n setMetadataKey('');\n setMetadataError(undefined);\n }\n };\n\n const handleAddMetadata = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const normalizedKey = metadataKey.trim();\n if (!normalizedKey) {\n setMetadataError('Enter a metadata key.');\n return;\n }\n if (preferences.metadataKeys.includes(normalizedKey)) {\n setMetadataError('That metadata column is already visible.');\n return;\n }\n\n onAddMetadataColumn(normalizedKey);\n handleDialogOpenChange(false);\n };\n\n return (\n <>\n <DropdownMenu>\n <DropdownMenu.Trigger\n disabled={disabled}\n render={\n <Button variant=\"ghost\" size=\"md\" icon={<Columns3Icon aria-hidden />}>\n Columns\n </Button>\n }\n />\n <DropdownMenu.Content align=\"end\" className=\"min-w-56\">\n <DropdownMenu.Label>Standard columns</DropdownMenu.Label>\n {catalog.standardColumns.map(column => (\n <DropdownMenu.CheckboxItem\n key={column}\n checked={preferences.visibleColumns.includes(column)}\n onCheckedChange={() => onToggleColumn(column)}\n >\n {COLUMN_LABELS[column]}\n </DropdownMenu.CheckboxItem>\n ))}\n\n {catalog.usage && (\n <>\n <DropdownMenu.Separator />\n <DropdownMenu.Label>Usage columns</DropdownMenu.Label>\n {TRACE_USAGE_COLUMNS.map(column => (\n <DropdownMenu.CheckboxItem\n key={column}\n checked={preferences.visibleColumns.includes(column)}\n disabled={Boolean(usageDisabledReason)}\n onCheckedChange={() => onToggleColumn(column)}\n >\n {COLUMN_LABELS[column]}\n </DropdownMenu.CheckboxItem>\n ))}\n {usageDisabledReason && (\n <Txt variant=\"meta\" tone=\"faint\" className=\"px-2 py-1\" role=\"note\">\n {usageDisabledReason}\n </Txt>\n )}\n </>\n )}\n\n <DropdownMenu.Separator />\n <DropdownMenu.Label>Custom columns</DropdownMenu.Label>\n {TRACE_CUSTOM_COLUMN_FIELDS.map(field => {\n const isVisible = preferences.customColumns.includes(field);\n return (\n <DropdownMenu.CheckboxItem\n key={field}\n checked={isVisible}\n onCheckedChange={() => (isVisible ? onRemoveCustomColumn(field) : onAddCustomColumn(field))}\n >\n {TRACE_CUSTOM_COLUMN_LABELS[field]}\n </DropdownMenu.CheckboxItem>\n );\n })}\n\n {catalog.metadata && (withQueryTrace || preferences.metadataKeys.length > 0) && (\n <>\n <DropdownMenu.Separator />\n <DropdownMenu.Label>Metadata columns</DropdownMenu.Label>\n {preferences.metadataKeys.map(key => (\n <DropdownMenu.CheckboxItem\n key={key}\n checked\n title={key}\n onCheckedChange={() => onRemoveMetadataColumn(key)}\n >\n {key}\n </DropdownMenu.CheckboxItem>\n ))}\n {withMetadata && (\n <DropdownMenu.Item onSelect={() => setIsMetadataDialogOpen(true)}>\n <PlusIcon aria-hidden />\n Add metadata column\n </DropdownMenu.Item>\n )}\n </>\n )}\n\n <DropdownMenu.Separator />\n <DropdownMenu.Item onSelect={onReset}>Reset to defaults</DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>\n\n {withMetadata && (\n <Dialog open={isMetadataDialogOpen} onOpenChange={handleDialogOpenChange}>\n <DialogContent>\n <Form onSubmit={handleAddMetadata} className=\"gap-0\">\n <DialogHeader>\n <DialogTitle>Add metadata column</DialogTitle>\n <DialogDescription>\n Pick a top-level trace metadata key observed in the current time range, or type one. Only the key is\n saved, never its values.\n </DialogDescription>\n </DialogHeader>\n <DialogBody>\n <Field invalid={Boolean(metadataError)}>\n <FieldLabel>Metadata key</FieldLabel>\n <Combobox\n options={metadataKeyOptions}\n value={metadataKey}\n onValueChange={key => {\n setMetadataKey(key);\n setMetadataError(undefined);\n }}\n allowCustomValue\n placeholder=\"Select a metadata key…\"\n searchPlaceholder=\"Search metadata keys…\"\n emptyText=\"No metadata keys observed. Type one to add it.\"\n />\n <FieldError>{metadataError}</FieldError>\n </Field>\n </DialogBody>\n <DialogFooter>\n <DialogCancel>Cancel</DialogCancel>\n <DialogAction type=\"submit\">Add column</DialogAction>\n </DialogFooter>\n </Form>\n </DialogContent>\n </Dialog>\n )}\n </>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"trace-columns-menu.es.js","names":["_Fragment"],"sources":["../../../../src/domains/traces/components/trace-columns-menu.tsx"],"sourcesContent":["import { Columns3Icon, PlusIcon } from 'lucide-react';\nimport { useMemo, useState } from 'react';\nimport type { FormEvent } from 'react';\nimport {\n TRACE_COLUMN_CATALOGS,\n TRACE_CUSTOM_COLUMN_FIELDS,\n TRACE_CUSTOM_COLUMN_LABELS,\n TRACE_USAGE_COLUMNS,\n} from '../trace-list-columns';\nimport type {\n TraceColumnCatalog,\n TraceColumnPreferences,\n TraceCustomColumn,\n TraceOptionalColumn,\n} from '../trace-list-columns';\nimport { Button } from '@/ds/components/Button';\nimport { Combobox } from '@/ds/components/Combobox';\nimport {\n Dialog,\n DialogAction,\n DialogBody,\n DialogCancel,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@/ds/components/Dialog';\nimport { DropdownMenu } from '@/ds/components/DropdownMenu';\nimport { Field, FieldError, FieldLabel } from '@/ds/components/Field';\nimport { Form } from '@/ds/components/Form';\nimport { Txt } from '@/ds/components/Txt';\n\nconst EMPTY_KEYS: readonly string[] = [];\n\nconst COLUMN_LABELS: Record<TraceOptionalColumn, string> = {\n type: 'Primitive type',\n input: 'Input',\n output: 'Output',\n duration: 'Duration',\n traceCount: 'Messages',\n timeToFirstChunk: 'Time to first chunk',\n endTime: 'End',\n environment: 'Environment',\n model: 'Model',\n provider: 'Provider',\n inputTokens: 'Input tokens',\n outputTokens: 'Output tokens',\n totalTokens: 'Total tokens',\n estimatedCost: 'Estimated cost',\n};\n\ntype TraceColumnsMenuProps = {\n preferences: TraceColumnPreferences;\n /** Which columns the list offers. Defaults to the traces catalog. */\n catalog?: TraceColumnCatalog;\n /** Top-level metadata keys observed on traces in the current time range, offered in the picker. */\n availableMetadataKeys?: readonly string[];\n usageDisabledReason?: string;\n /** When false (server without the trace-query API), metadata columns can't be added. Defaults to true. */\n withQueryTrace?: boolean;\n onToggleColumn: (column: TraceOptionalColumn) => void;\n onAddCustomColumn: (field: TraceCustomColumn) => void;\n onRemoveCustomColumn: (field: TraceCustomColumn) => void;\n onAddMetadataColumn: (key: string) => void;\n onRemoveMetadataColumn: (key: string) => void;\n onReset: () => void;\n /** Keeps the trigger in place but inert, e.g. while capabilities load. */\n disabled?: boolean;\n};\n\nexport function TraceColumnsMenu({\n preferences,\n catalog = TRACE_COLUMN_CATALOGS.traces,\n availableMetadataKeys = EMPTY_KEYS,\n usageDisabledReason,\n withQueryTrace = true,\n onToggleColumn,\n onAddCustomColumn,\n onRemoveCustomColumn,\n onAddMetadataColumn,\n onRemoveMetadataColumn,\n onReset,\n disabled,\n}: TraceColumnsMenuProps) {\n const withMetadata = catalog.metadata && withQueryTrace;\n const [isMetadataDialogOpen, setIsMetadataDialogOpen] = useState(false);\n const [metadataKey, setMetadataKey] = useState('');\n const [metadataError, setMetadataError] = useState<string | undefined>();\n\n const metadataKeyOptions = useMemo(() => {\n const keys = availableMetadataKeys.filter(key => !preferences.metadataKeys.includes(key));\n if (metadataKey && !keys.includes(metadataKey)) keys.push(metadataKey);\n return keys.map(key => ({ label: key, value: key }));\n }, [availableMetadataKeys, preferences.metadataKeys, metadataKey]);\n\n const handleDialogOpenChange = (open: boolean) => {\n setIsMetadataDialogOpen(open);\n if (!open) {\n setMetadataKey('');\n setMetadataError(undefined);\n }\n };\n\n const handleAddMetadata = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const normalizedKey = metadataKey.trim();\n if (!normalizedKey) {\n setMetadataError('Enter a metadata key.');\n return;\n }\n if (preferences.metadataKeys.includes(normalizedKey)) {\n setMetadataError('That metadata column is already visible.');\n return;\n }\n\n onAddMetadataColumn(normalizedKey);\n handleDialogOpenChange(false);\n };\n\n return (\n <>\n <DropdownMenu>\n <DropdownMenu.Trigger\n disabled={disabled}\n render={\n <Button variant=\"ghost\" size=\"md\" icon={<Columns3Icon aria-hidden />}>\n Columns\n </Button>\n }\n />\n <DropdownMenu.Content align=\"end\" className=\"min-w-56\">\n <DropdownMenu.Label>Standard columns</DropdownMenu.Label>\n {catalog.standardColumns.map(column => (\n <DropdownMenu.CheckboxItem\n key={column}\n checked={preferences.visibleColumns.includes(column)}\n onCheckedChange={() => onToggleColumn(column)}\n >\n {COLUMN_LABELS[column]}\n </DropdownMenu.CheckboxItem>\n ))}\n\n {catalog.usage && (\n <>\n <DropdownMenu.Separator />\n <DropdownMenu.Label>Usage columns</DropdownMenu.Label>\n {TRACE_USAGE_COLUMNS.map(column => (\n <DropdownMenu.CheckboxItem\n key={column}\n checked={preferences.visibleColumns.includes(column)}\n disabled={Boolean(usageDisabledReason)}\n onCheckedChange={() => onToggleColumn(column)}\n >\n {COLUMN_LABELS[column]}\n </DropdownMenu.CheckboxItem>\n ))}\n {usageDisabledReason && (\n <Txt variant=\"meta\" tone=\"faint\" className=\"px-2 py-1\" role=\"note\">\n {usageDisabledReason}\n </Txt>\n )}\n </>\n )}\n\n <DropdownMenu.Separator />\n <DropdownMenu.Label>Custom columns</DropdownMenu.Label>\n {TRACE_CUSTOM_COLUMN_FIELDS.map(field => {\n const isVisible = preferences.customColumns.includes(field);\n return (\n <DropdownMenu.CheckboxItem\n key={field}\n checked={isVisible}\n onCheckedChange={() => (isVisible ? onRemoveCustomColumn(field) : onAddCustomColumn(field))}\n >\n {TRACE_CUSTOM_COLUMN_LABELS[field]}\n </DropdownMenu.CheckboxItem>\n );\n })}\n\n {catalog.metadata && (withQueryTrace || preferences.metadataKeys.length > 0) && (\n <>\n <DropdownMenu.Separator />\n <DropdownMenu.Label>Metadata columns</DropdownMenu.Label>\n {preferences.metadataKeys.map(key => (\n <DropdownMenu.CheckboxItem\n key={key}\n checked\n title={key}\n onCheckedChange={() => onRemoveMetadataColumn(key)}\n >\n {key}\n </DropdownMenu.CheckboxItem>\n ))}\n {withMetadata && (\n <DropdownMenu.Item onSelect={() => setIsMetadataDialogOpen(true)}>\n <PlusIcon aria-hidden />\n Add metadata column\n </DropdownMenu.Item>\n )}\n </>\n )}\n\n <DropdownMenu.Separator />\n <DropdownMenu.Item onSelect={onReset}>Reset to defaults</DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>\n\n {withMetadata && (\n <Dialog open={isMetadataDialogOpen} onOpenChange={handleDialogOpenChange}>\n <DialogContent>\n <Form onSubmit={handleAddMetadata} className=\"gap-0\">\n <DialogHeader>\n <DialogTitle>Add metadata column</DialogTitle>\n <DialogDescription>\n Pick a top-level trace metadata key observed in the current time range, or type one. Only the key is\n saved, never its values.\n </DialogDescription>\n </DialogHeader>\n <DialogBody>\n <Field invalid={Boolean(metadataError)}>\n <FieldLabel>Metadata key</FieldLabel>\n <Combobox\n options={metadataKeyOptions}\n value={metadataKey}\n onValueChange={key => {\n setMetadataKey(key);\n setMetadataError(undefined);\n }}\n allowCustomValue\n placeholder=\"Select a metadata key…\"\n searchPlaceholder=\"Search metadata keys…\"\n emptyText=\"No metadata keys observed. Type one to add it.\"\n />\n <FieldError>{metadataError}</FieldError>\n </Field>\n </DialogBody>\n <DialogFooter>\n <DialogCancel>Cancel</DialogCancel>\n <DialogAction type=\"submit\">Add column</DialogAction>\n </DialogFooter>\n </Form>\n </DialogContent>\n </Dialog>\n )}\n </>\n );\n}\n"],"mappings":"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"}
@@ -96,6 +96,11 @@ function TracesListView({ traces, isLoading, isFetchingNextPage, hasNextPage, se
96
96
  className: "justify-end text-right",
97
97
  children: "Duration"
98
98
  }),
99
+ require_domains_traces_trace_list_columns.hasTraceColumn(columnPreferences, "traceCount") && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_DataList.TracesDataList.TopCellWithTooltip, {
100
+ tooltip: "Messages sent in this thread, counting the whole thread, not just the selected time range",
101
+ className: "justify-end text-right",
102
+ children: "Messages"
103
+ }),
99
104
  require_domains_traces_trace_list_columns.hasTraceColumn(columnPreferences, "timeToFirstChunk") && (onTimeToFirstChunkSortChange ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_DataList.TracesDataList.SortableTopCell, {
100
105
  sortKey: "timeToFirstChunkMs",
101
106
  sort: timeToFirstChunkSort,
@@ -206,6 +211,7 @@ function TracesListView({ traces, isLoading, isFetchingNextPage, hasNextPage, se
206
211
  font: "mono",
207
212
  children: require_utils_duration.formatDuration(require_domains_traces_utils_span_utils.getSpanDurationMs(trace.startedAt, trace.endedAt))
208
213
  }),
214
+ require_domains_traces_trace_list_columns.hasTraceColumn(columnPreferences, "traceCount") && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_data_list.DataList.NumberCell, { children: trace.traceCount === void 0 ? void 0 : require_cost.formatCompactNumber(trace.traceCount) }),
209
215
  require_domains_traces_trace_list_columns.hasTraceColumn(columnPreferences, "timeToFirstChunk") && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_data_list.DataList.NumberCell, {
210
216
  font: "mono",
211
217
  children: require_utils_duration.formatDuration(trace.timeToFirstChunkMs)
@@ -1 +1 @@
1
- {"version":3,"file":"traces-list-view.cjs.js","names":["Tooltip","TooltipTrigger","TooltipContent","DEFAULT_TRACE_COLUMN_PREFERENCES","useRef","buildTraceListColumns","buildTraceListColumnKeys","useVirtualizer","useDataListKeyboard","TracesDataList","hasTraceColumn","TRACE_CUSTOM_COLUMN_LABELS","DropdownMenu","cn","focusRing","ListFilterIcon","Txt","DataListSkeletonRows","splitColumns","_Fragment","getInputPreview","TraceErrorCell","DataList","formatDuration","getSpanDurationMs","formatCompactNumber","formatCost","formatTraceMetadataValue"],"sources":["../../../../src/domains/traces/components/traces-list-view.tsx"],"sourcesContent":["import { useVirtualizer } from '@tanstack/react-virtual';\nimport { ListFilterIcon } from 'lucide-react';\nimport { useRef } from 'react';\nimport {\n DEFAULT_TRACE_COLUMN_PREFERENCES,\n TRACE_CUSTOM_COLUMN_LABELS,\n buildTraceListColumnKeys,\n buildTraceListColumns,\n formatTraceMetadataValue,\n hasTraceColumn,\n} from '../trace-list-columns';\nimport type { TraceColumnPreferences, TraceCustomColumn, TraceUsageSummary } from '../trace-list-columns';\nimport { getInputPreview, getSpanDurationMs } from '../utils/span-utils';\nimport { TraceErrorCell } from './trace-error-cell';\nimport { DataList, DataListSkeletonRows, TracesDataList, useDataListKeyboard } from '@/ds/components/DataList';\nimport type { DataListSort } from '@/ds/components/DataList';\nimport { splitColumns } from '@/ds/components/DataList/shared';\nimport { DropdownMenu } from '@/ds/components/DropdownMenu';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/ds/components/Tooltip';\nimport { Txt } from '@/ds/components/Txt/Txt';\nimport { focusRing } from '@/ds/primitives/transitions';\nimport { formatCompactNumber, formatCost } from '@/lib/cost';\nimport { cn } from '@/lib/utils';\nimport { formatDuration } from '@/utils/duration';\n\nexport type TracesListViewTrace = {\n traceId: string;\n /** Required for branch rows; absent on plain trace rows (which are root-rooted). */\n spanId?: string | null;\n /** `null`/missing → root span. Drives the Kind column's icon (top-level trace vs nested branch). */\n parentSpanId?: string | null;\n name: string;\n entityType?: string | null;\n entityId?: string | null;\n entityName?: string | null;\n threadId?: string | null;\n resourceId?: string | null;\n environment?: string | null;\n /** Model and provider of a model span; only span rows carry them. */\n model?: string | null;\n provider?: string | null;\n status?: string | null;\n /** Server-rendered preview of `input`. Present on lightweight rows, which omit `input` itself. */\n inputPreview?: string | null;\n input?: unknown;\n /** Server-rendered preview of the root span's output. */\n outputPreview?: string;\n /** Server-rendered preview of the root span's error. Shown in place of the output when `status` is `'error'`. */\n errorPreview?: string;\n metadata?: Record<string, unknown> | null;\n startedAt?: Date | string | null;\n endedAt?: Date | string | null;\n /** The root span's time to first chunk; `null` when it never streamed one. */\n timeToFirstChunkMs?: number | null;\n createdAt: Date | string;\n};\n\nconst ROW_HEIGHT = 36;\nconst OVERSCAN = 8;\n/** Distinct values offered in a custom column's \"filter by value\" header menu. */\nconst MAX_FILTER_VALUES = 20;\n\nfunction customColumnValue(trace: TracesListViewTrace, field: TraceCustomColumn): string | null | undefined {\n return trace[field];\n}\n\nfunction distinctCustomColumnValues(traces: TracesListViewTrace[], field: TraceCustomColumn): string[] {\n const values = new Set<string>();\n for (const trace of traces) {\n const value = trace[field];\n if (typeof value === 'string' && value) values.add(value);\n if (values.size >= MAX_FILTER_VALUES) break;\n }\n return [...values];\n}\n\nfunction sumTokens(usage: TraceUsageSummary | undefined): number | undefined {\n if (usage?.inputTokens === undefined && usage?.outputTokens === undefined) return undefined;\n return (usage?.inputTokens ?? 0) + (usage?.outputTokens ?? 0);\n}\n\ntype FailedTrace = TracesListViewTrace & { spanId: string; errorPreview: string };\n\n/** A failed row whose error preview can open the full error from its span. */\nfunction isFailedTrace(trace: TracesListViewTrace): trace is FailedTrace {\n return trace.status === 'error' && !!trace.errorPreview && !!trace.spanId;\n}\n\n/** The TTFC abbreviation, spelled out on hover; the sort button already names the column for screen readers. */\nfunction TimeToFirstChunkLabel() {\n return (\n <Tooltip>\n <TooltipTrigger render={<span />}>TTFC</TooltipTrigger>\n <TooltipContent>Time to first chunk</TooltipContent>\n </Tooltip>\n );\n}\n\nexport type TracesListViewProps = {\n traces: TracesListViewTrace[];\n isLoading?: boolean;\n isFetchingNextPage?: boolean;\n hasNextPage?: boolean;\n setEndOfListElement?: (element: HTMLDivElement | null) => void;\n filtersApplied?: boolean;\n /** What the rows hold, named in the empty messages. Defaults to `traces`. */\n resource?: 'traces' | 'spans' | 'threads';\n /** Currently featured/selected trace — its row gets the highlighted background. */\n featuredTraceId?: string | null;\n /**\n * Required in branches mode to disambiguate rows sharing a `traceId`. When set,\n * a row is featured only when both `traceId` and `spanId` match.\n */\n featuredSpanId?: string | null;\n /** Branches mode mixes root traces with subtraces — enables the Trace/Subtrace tooltip on the\n * level icon in the Name column, which is meaningless when every row is a root. */\n isBranchesMode?: boolean;\n /** Keys (`traceId:spanId`) of rows that just arrived via delta polling. Rows whose key is in\n * this set get a temporary tint to distinguish them from rows present since the last page-mode\n * fetch. Auto-expires upstream (in useTraces) after a short window. */\n recentlyAddedKeys?: Set<string>;\n /** Optional and metadata columns selected for this project. */\n columnPreferences?: TraceColumnPreferences;\n /** Token and estimated-cost totals, aggregated across model spans by trace ID. */\n usageByTraceId?: ReadonlyMap<string, TraceUsageSummary>;\n /** Called when a row is clicked. The current selection logic (toggle on same id) is the consumer's call. */\n onTraceClick: (trace: TracesListViewTrace) => void;\n /** Current sort of the Created column. When `onSortChange` is provided the header becomes sortable. */\n createdSort?: DataListSort;\n onSortChange?: (direction: DataListSort, key: 'startedAt') => void;\n /** Current sort of the TTFC column. When `onTimeToFirstChunkSortChange` is provided the header becomes sortable. */\n timeToFirstChunkSort?: DataListSort;\n onTimeToFirstChunkSortChange?: (direction: DataListSort) => void;\n /** When provided, custom column headers offer an `is <value>` filter for every value currently listed. */\n onFilterByField?: (field: TraceCustomColumn, value: string) => void;\n /** Storage id for the persisted column order. Use a distinct id per page so each keeps its own order. */\n listId?: string;\n};\n\n/**\n * Virtualized presentational list. Renders only the visible window via TanStack Virtual, and\n * uses DataList primitives for layout (CSS Grid with subgrid rows).\n */\nexport function TracesListView({\n traces,\n isLoading,\n isFetchingNextPage,\n hasNextPage,\n setEndOfListElement,\n filtersApplied,\n resource = 'traces',\n featuredTraceId,\n featuredSpanId,\n isBranchesMode,\n recentlyAddedKeys,\n columnPreferences = DEFAULT_TRACE_COLUMN_PREFERENCES,\n usageByTraceId,\n onTraceClick,\n createdSort,\n onSortChange,\n timeToFirstChunkSort,\n onTimeToFirstChunkSortChange,\n onFilterByField,\n listId = 'all-traces',\n}: TracesListViewProps) {\n const scrollRef = useRef<HTMLDivElement | null>(null);\n const columns = buildTraceListColumns(columnPreferences);\n const columnKeys = buildTraceListColumnKeys(columnPreferences);\n\n const virtualizer = useVirtualizer({\n count: traces.length,\n getScrollElement: () => scrollRef.current,\n estimateSize: () => ROW_HEIGHT,\n overscan: OVERSCAN,\n });\n\n const { getRowProps } = useDataListKeyboard({\n count: traces.length,\n containerRef: scrollRef,\n onNavigate: index => virtualizer.scrollToIndex(index),\n global: true,\n });\n\n const virtualItems = virtualizer.getVirtualItems();\n const totalSize = virtualizer.getTotalSize();\n const paddingTop = virtualItems[0]?.start ?? 0;\n const paddingBottom =\n virtualItems.length > 0 ? Math.max(0, totalSize - (virtualItems[virtualItems.length - 1]?.end ?? 0)) : 0;\n\n return (\n <TracesDataList\n reorderable\n id={listId}\n columns={columns}\n columnKeys={columnKeys}\n fit=\"container\"\n scrollRef={scrollRef}\n className=\"min-w-0\"\n >\n <TracesDataList.Top>\n {onSortChange ? (\n <TracesDataList.SortableTopCell sortKey=\"startedAt\" sort={createdSort} onSortChange={onSortChange}>\n Start\n </TracesDataList.SortableTopCell>\n ) : (\n <TracesDataList.TopCell>Start</TracesDataList.TopCell>\n )}\n {hasTraceColumn(columnPreferences, 'type') && <TracesDataList.TopCell>Primitive type</TracesDataList.TopCell>}\n <TracesDataList.TopCell>Primitive name</TracesDataList.TopCell>\n {hasTraceColumn(columnPreferences, 'input') && <TracesDataList.TopCell>Input</TracesDataList.TopCell>}\n {hasTraceColumn(columnPreferences, 'output') && <TracesDataList.TopCell>Output</TracesDataList.TopCell>}\n <TracesDataList.TopCell>Status</TracesDataList.TopCell>\n {hasTraceColumn(columnPreferences, 'duration') && (\n <TracesDataList.TopCell className=\"justify-end text-right\">Duration</TracesDataList.TopCell>\n )}\n {hasTraceColumn(columnPreferences, 'timeToFirstChunk') &&\n (onTimeToFirstChunkSortChange ? (\n <TracesDataList.SortableTopCell\n sortKey=\"timeToFirstChunkMs\"\n sort={timeToFirstChunkSort}\n onSortChange={onTimeToFirstChunkSortChange}\n label=\"Time to first chunk\"\n align=\"end\"\n >\n <TimeToFirstChunkLabel />\n </TracesDataList.SortableTopCell>\n ) : (\n <TracesDataList.TopCellWithTooltip tooltip=\"Time to first chunk\" className=\"justify-end text-right\">\n TTFC\n </TracesDataList.TopCellWithTooltip>\n ))}\n {hasTraceColumn(columnPreferences, 'endTime') && <TracesDataList.TopCell>End</TracesDataList.TopCell>}\n {hasTraceColumn(columnPreferences, 'environment') && (\n <TracesDataList.TopCell>Environment</TracesDataList.TopCell>\n )}\n {hasTraceColumn(columnPreferences, 'model') && <TracesDataList.TopCell>Model</TracesDataList.TopCell>}\n {hasTraceColumn(columnPreferences, 'provider') && <TracesDataList.TopCell>Provider</TracesDataList.TopCell>}\n {hasTraceColumn(columnPreferences, 'inputTokens') && (\n <TracesDataList.TopCell className=\"justify-end text-right\">Input tokens</TracesDataList.TopCell>\n )}\n {hasTraceColumn(columnPreferences, 'outputTokens') && (\n <TracesDataList.TopCell className=\"justify-end text-right\">Output tokens</TracesDataList.TopCell>\n )}\n {hasTraceColumn(columnPreferences, 'totalTokens') && (\n <TracesDataList.TopCell className=\"justify-end text-right\">Total tokens</TracesDataList.TopCell>\n )}\n {hasTraceColumn(columnPreferences, 'estimatedCost') && (\n <TracesDataList.TopCell className=\"justify-end text-right\">Est. cost</TracesDataList.TopCell>\n )}\n {columnPreferences.customColumns.map(field => {\n const label = TRACE_CUSTOM_COLUMN_LABELS[field];\n const filterValues = onFilterByField ? distinctCustomColumnValues(traces, field) : [];\n if (!onFilterByField || filterValues.length === 0) {\n return <TracesDataList.TopCell key={field}>{label}</TracesDataList.TopCell>;\n }\n return (\n <TracesDataList.TopCell key={field} className=\"overflow-visible\">\n <DropdownMenu>\n <DropdownMenu.Trigger\n render={\n <button\n type=\"button\"\n className={cn('flex min-w-0 items-center gap-1 rounded-sm hover:text-foreground', focusRing)}\n >\n <span className=\"min-w-0 truncate\">{label}</span>\n <ListFilterIcon aria-hidden className=\"size-[1.2em] shrink-0\" />\n </button>\n }\n />\n <DropdownMenu.Content align=\"start\">\n <DropdownMenu.Label>Filter by value</DropdownMenu.Label>\n {filterValues.map(value => (\n <DropdownMenu.Item key={value} onSelect={() => onFilterByField(field, value)}>\n <Txt as=\"span\" variant=\"body-sm\" font=\"mono\" className=\"min-w-0 truncate\">\n {value}\n </Txt>\n </DropdownMenu.Item>\n ))}\n </DropdownMenu.Content>\n </DropdownMenu>\n </TracesDataList.TopCell>\n );\n })}\n {columnPreferences.metadataKeys.map(key => (\n <TracesDataList.TopCellWithTooltip key={key} tooltip={key}>\n {key}\n </TracesDataList.TopCellWithTooltip>\n ))}\n </TracesDataList.Top>\n\n {isLoading ? (\n <DataListSkeletonRows columnCount={splitColumns(columns).length} />\n ) : traces.length === 0 ? (\n <TracesDataList.NoMatch\n message={filtersApplied ? `No ${resource} found for applied filters` : `No ${resource} found yet`}\n />\n ) : (\n <>\n <TracesDataList.Spacer height={paddingTop} />\n {virtualItems.map(vi => {\n const trace = traces[vi.index];\n if (!trace) return null;\n\n const isFeatured =\n trace.traceId === featuredTraceId && (featuredSpanId == null || trace.spanId === featuredSpanId);\n const rowKey = `${trace.traceId}:${trace.spanId ?? ''}`;\n const isRecentlyAdded = recentlyAddedKeys?.has(rowKey) ?? false;\n const displayDate = trace.startedAt ?? trace.createdAt;\n const usage = usageByTraceId?.get(trace.traceId);\n\n return (\n <TracesDataList.RowButton\n key={rowKey}\n ref={virtualizer.measureElement}\n data-index={vi.index}\n {...getRowProps(vi.index)}\n onClick={() => onTraceClick(trace)}\n featured={isFeatured}\n className={cn(isRecentlyAdded && 'animate-row-highlight')}\n >\n <TracesDataList.CreatedCell timestamp={displayDate} preset=\"day-time-seconds\" />\n {hasTraceColumn(columnPreferences, 'type') && <TracesDataList.TypeCell entityType={trace.entityType} />}\n <TracesDataList.NameCell\n name={trace.entityName || trace.name}\n parentSpanId={trace.parentSpanId}\n showLevelTooltip={isBranchesMode}\n />\n {hasTraceColumn(columnPreferences, 'input') && (\n <TracesDataList.InputCell input={trace.inputPreview ?? getInputPreview(trace.input)} />\n )}\n {hasTraceColumn(columnPreferences, 'output') &&\n (isFailedTrace(trace) ? (\n <TraceErrorCell traceId={trace.traceId} spanId={trace.spanId} errorPreview={trace.errorPreview} />\n ) : (\n <TracesDataList.OutputCell\n output={trace.outputPreview}\n error={trace.errorPreview}\n status={trace.status}\n />\n ))}\n <TracesDataList.StatusCell status={trace.status} />\n {hasTraceColumn(columnPreferences, 'duration') && (\n <DataList.NumberCell font=\"mono\">\n {formatDuration(getSpanDurationMs(trace.startedAt, trace.endedAt))}\n </DataList.NumberCell>\n )}\n {hasTraceColumn(columnPreferences, 'timeToFirstChunk') && (\n <DataList.NumberCell font=\"mono\">{formatDuration(trace.timeToFirstChunkMs)}</DataList.NumberCell>\n )}\n {hasTraceColumn(columnPreferences, 'endTime') && (\n <TracesDataList.CreatedCell timestamp={trace.endedAt ?? ''} preset=\"day-time-seconds\" />\n )}\n {hasTraceColumn(columnPreferences, 'environment') && (\n <DataList.TextCell>{trace.environment || '—'}</DataList.TextCell>\n )}\n {hasTraceColumn(columnPreferences, 'model') && (\n <DataList.TextCell>{trace.model || '—'}</DataList.TextCell>\n )}\n {hasTraceColumn(columnPreferences, 'provider') && (\n <DataList.TextCell>{trace.provider || '—'}</DataList.TextCell>\n )}\n {hasTraceColumn(columnPreferences, 'inputTokens') && (\n <DataList.NumberCell>\n {usage?.inputTokens === undefined ? undefined : formatCompactNumber(usage.inputTokens)}\n </DataList.NumberCell>\n )}\n {hasTraceColumn(columnPreferences, 'outputTokens') && (\n <DataList.NumberCell>\n {usage?.outputTokens === undefined ? undefined : formatCompactNumber(usage.outputTokens)}\n </DataList.NumberCell>\n )}\n {hasTraceColumn(columnPreferences, 'totalTokens') && (\n <DataList.NumberCell>\n {(() => {\n const total = sumTokens(usage);\n return total === undefined ? undefined : formatCompactNumber(total);\n })()}\n </DataList.NumberCell>\n )}\n {hasTraceColumn(columnPreferences, 'estimatedCost') && (\n <DataList.NumberCell>\n {usage?.estimatedCost === undefined ? undefined : formatCost(usage.estimatedCost, usage.costUnit)}\n </DataList.NumberCell>\n )}\n {columnPreferences.customColumns.map(field => (\n <DataList.TextCell font=\"mono\" key={field}>\n {customColumnValue(trace, field) ?? undefined}\n </DataList.TextCell>\n ))}\n {columnPreferences.metadataKeys.map(key => {\n const value = formatTraceMetadataValue(trace.metadata, key);\n return (\n <DataList.TextCell font=\"mono\" key={key}>\n {value}\n </DataList.TextCell>\n );\n })}\n </TracesDataList.RowButton>\n );\n })}\n <TracesDataList.Spacer height={paddingBottom} />\n <TracesDataList.NextPageLoading\n isLoading={isFetchingNextPage}\n hasMore={hasNextPage}\n setEndOfListElement={setEndOfListElement}\n />\n </>\n )}\n </TracesDataList>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAyDA,IAAM,aAAa;AACnB,IAAM,WAAW;;AAEjB,IAAM,oBAAoB;AAE1B,SAAS,kBAAkB,OAA4B,OAAqD;CAC1G,OAAO,MAAM;AACf;AAEA,SAAS,2BAA2B,QAA+B,OAAoC;CACrG,MAAM,yBAAS,IAAI,IAAY;CAC/B,KAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,QAAQ,MAAM;EACpB,IAAI,OAAO,UAAU,YAAY,OAAO,OAAO,IAAI,KAAK;EACxD,IAAI,OAAO,QAAQ,mBAAmB;CACxC;CACA,OAAO,CAAC,GAAG,MAAM;AACnB;AAEA,SAAS,UAAU,OAA0D;CAC3E,IAAI,OAAO,gBAAgB,KAAA,KAAa,OAAO,iBAAiB,KAAA,GAAW,OAAO,KAAA;CAClF,QAAQ,OAAO,eAAe,MAAM,OAAO,gBAAgB;AAC7D;;AAKA,SAAS,cAAc,OAAkD;CACvE,OAAO,MAAM,WAAW,WAAW,CAAC,CAAC,MAAM,gBAAgB,CAAC,CAAC,MAAM;AACrE;;AAGA,SAAS,wBAAwB;CAC/B,OACE,iBAAA,GAAA,kBAAA,KAAA,CAACA,gBAAAA,SAAD,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,gBAAAA,gBAAD;EAAgB,QAAQ,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,CAAO,CAAA;EAAG,UAAA;CAAoB,CAAA,GACtD,iBAAA,GAAA,kBAAA,IAAA,CAACC,gBAAAA,gBAAD,EAAA,UAAgB,sBAAmC,CAAA,CAC5C,EAAA,CAAA;AAEb;;;;;AA+CA,SAAgB,eAAe,EAC7B,QACA,WACA,oBACA,aACA,qBACA,gBACA,WAAW,UACX,iBACA,gBACA,gBACA,mBACA,oBAAoBC,0CAAAA,kCACpB,gBACA,cACA,aACA,cACA,sBACA,8BACA,iBACA,SAAS,gBACa;CACtB,MAAM,aAAA,GAAYC,MAAAA,OAAAA,CAA8B,IAAI;CACpD,MAAM,UAAUC,0CAAAA,sBAAsB,iBAAiB;CACvD,MAAM,aAAaC,0CAAAA,yBAAyB,iBAAiB;CAE7D,MAAM,eAAA,GAAcC,wBAAAA,eAAAA,CAAe;EACjC,OAAO,OAAO;EACd,wBAAwB,UAAU;EAClC,oBAAoB;EACpB,UAAU;CACZ,CAAC;CAED,MAAM,EAAE,gBAAgBC,+BAAAA,oBAAoB;EAC1C,OAAO,OAAO;EACd,cAAc;EACd,aAAY,UAAS,YAAY,cAAc,KAAK;EACpD,QAAQ;CACV,CAAC;CAED,MAAM,eAAe,YAAY,gBAAgB;CACjD,MAAM,YAAY,YAAY,aAAa;CAC3C,MAAM,aAAa,aAAa,EAAE,EAAE,SAAS;CAC7C,MAAM,gBACJ,aAAa,SAAS,IAAI,KAAK,IAAI,GAAG,aAAa,aAAa,aAAa,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI;CAEzG,OACE,iBAAA,GAAA,kBAAA,KAAA,CAACC,iBAAAA,gBAAD;EACE,aAAA;EACA,IAAI;EACK;EACG;EACZ,KAAI;EACO;EACX,WAAU;EAPZ,UAAA,CASE,iBAAA,GAAA,kBAAA,KAAA,CAACA,iBAAAA,eAAe,KAAhB,EAAA,UAAA;GACG,eACC,iBAAA,GAAA,kBAAA,IAAA,CAACA,iBAAAA,eAAe,iBAAhB;IAAgC,SAAQ;IAAY,MAAM;IAA2B;IAAc,UAAA;GAEnE,CAAA,IAEhC,iBAAA,GAAA,kBAAA,IAAA,CAACA,iBAAAA,eAAe,SAAhB,EAAA,UAAwB,QAA6B,CAAA;GAEtDC,0CAAAA,eAAe,mBAAmB,MAAM,KAAK,iBAAA,GAAA,kBAAA,IAAA,CAACD,iBAAAA,eAAe,SAAhB,EAAA,UAAwB,iBAAsC,CAAA;GAC5G,iBAAA,GAAA,kBAAA,IAAA,CAACA,iBAAAA,eAAe,SAAhB,EAAA,UAAwB,iBAAsC,CAAA;GAC7DC,0CAAAA,eAAe,mBAAmB,OAAO,KAAK,iBAAA,GAAA,kBAAA,IAAA,CAACD,iBAAAA,eAAe,SAAhB,EAAA,UAAwB,QAA6B,CAAA;GACnGC,0CAAAA,eAAe,mBAAmB,QAAQ,KAAK,iBAAA,GAAA,kBAAA,IAAA,CAACD,iBAAAA,eAAe,SAAhB,EAAA,UAAwB,SAA8B,CAAA;GACtG,iBAAA,GAAA,kBAAA,IAAA,CAACA,iBAAAA,eAAe,SAAhB,EAAA,UAAwB,SAA8B,CAAA;GACrDC,0CAAAA,eAAe,mBAAmB,UAAU,KAC3C,iBAAA,GAAA,kBAAA,IAAA,CAACD,iBAAAA,eAAe,SAAhB;IAAwB,WAAU;IAAyB,UAAA;GAAgC,CAAA;GAE5FC,0CAAAA,eAAe,mBAAmB,kBAAkB,MAClD,+BACC,iBAAA,GAAA,kBAAA,IAAA,CAACD,iBAAAA,eAAe,iBAAhB;IACE,SAAQ;IACR,MAAM;IACN,cAAc;IACd,OAAM;IACN,OAAM;IAEN,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,uBAAD,CAAwB,CAAA;GACM,CAAA,IAEhC,iBAAA,GAAA,kBAAA,IAAA,CAACA,iBAAAA,eAAe,oBAAhB;IAAmC,SAAQ;IAAsB,WAAU;IAAyB,UAAA;GAEjE,CAAA;GAEtCC,0CAAAA,eAAe,mBAAmB,SAAS,KAAK,iBAAA,GAAA,kBAAA,IAAA,CAACD,iBAAAA,eAAe,SAAhB,EAAA,UAAwB,MAA2B,CAAA;GACnGC,0CAAAA,eAAe,mBAAmB,aAAa,KAC9C,iBAAA,GAAA,kBAAA,IAAA,CAACD,iBAAAA,eAAe,SAAhB,EAAA,UAAwB,cAAmC,CAAA;GAE5DC,0CAAAA,eAAe,mBAAmB,OAAO,KAAK,iBAAA,GAAA,kBAAA,IAAA,CAACD,iBAAAA,eAAe,SAAhB,EAAA,UAAwB,QAA6B,CAAA;GACnGC,0CAAAA,eAAe,mBAAmB,UAAU,KAAK,iBAAA,GAAA,kBAAA,IAAA,CAACD,iBAAAA,eAAe,SAAhB,EAAA,UAAwB,WAAgC,CAAA;GACzGC,0CAAAA,eAAe,mBAAmB,aAAa,KAC9C,iBAAA,GAAA,kBAAA,IAAA,CAACD,iBAAAA,eAAe,SAAhB;IAAwB,WAAU;IAAyB,UAAA;GAAoC,CAAA;GAEhGC,0CAAAA,eAAe,mBAAmB,cAAc,KAC/C,iBAAA,GAAA,kBAAA,IAAA,CAACD,iBAAAA,eAAe,SAAhB;IAAwB,WAAU;IAAyB,UAAA;GAAqC,CAAA;GAEjGC,0CAAAA,eAAe,mBAAmB,aAAa,KAC9C,iBAAA,GAAA,kBAAA,IAAA,CAACD,iBAAAA,eAAe,SAAhB;IAAwB,WAAU;IAAyB,UAAA;GAAoC,CAAA;GAEhGC,0CAAAA,eAAe,mBAAmB,eAAe,KAChD,iBAAA,GAAA,kBAAA,IAAA,CAACD,iBAAAA,eAAe,SAAhB;IAAwB,WAAU;IAAyB,UAAA;GAAiC,CAAA;GAE7F,kBAAkB,cAAc,KAAI,UAAS;IAC5C,MAAM,QAAQE,0CAAAA,2BAA2B;IACzC,MAAM,eAAe,kBAAkB,2BAA2B,QAAQ,KAAK,IAAI,CAAC;IACpF,IAAI,CAAC,mBAAmB,aAAa,WAAW,GAC9C,OAAO,iBAAA,GAAA,kBAAA,IAAA,CAACF,iBAAAA,eAAe,SAAhB,EAAA,UAAqC,MAA8B,GAAtC,KAAsC;IAE5E,OACE,iBAAA,GAAA,kBAAA,IAAA,CAACA,iBAAAA,eAAe,SAAhB;KAAoC,WAAU;KAC5C,UAAA,iBAAA,GAAA,kBAAA,KAAA,CAACG,sBAAAA,cAAD,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAACA,sBAAAA,aAAa,SAAd,EACE,QACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;MACE,MAAK;MACL,WAAWC,cAAAA,GAAG,oEAAoEC,+BAAAA,SAAS;MAF7F,UAAA,CAIE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;OAAM,WAAU;OAAoB,UAAA;MAAY,CAAA,GAChD,iBAAA,GAAA,kBAAA,IAAA,CAACC,aAAAA,gBAAD;OAAgB,eAAA;OAAY,WAAU;MAAyB,CAAA,CACzD;KAEX,CAAA,EAAA,CAAA,GACD,iBAAA,GAAA,kBAAA,KAAA,CAACH,sBAAAA,aAAa,SAAd;MAAsB,OAAM;MAA5B,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAACA,sBAAAA,aAAa,OAAd,EAAA,UAAoB,kBAAmC,CAAA,GACtD,aAAa,KAAI,UAChB,iBAAA,GAAA,kBAAA,IAAA,CAACA,sBAAAA,aAAa,MAAd;OAA+B,gBAAgB,gBAAgB,OAAO,KAAK;OACzE,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAACI,YAAAA,KAAD;QAAK,IAAG;QAAO,SAAQ;QAAU,MAAK;QAAO,WAAU;QACpD,UAAA;OACE,CAAA;MACY,GAJK,KAIL,CACpB,CACmB;KACV,CAAA,CAAA,EAAA,CAAA;IACQ,GAxBK,KAwBL;GAE5B,CAAC;GACA,kBAAkB,aAAa,KAAI,QAClC,iBAAA,GAAA,kBAAA,IAAA,CAACP,iBAAAA,eAAe,oBAAhB;IAA6C,SAAS;IACnD,UAAA;GACgC,GAFK,GAEL,CACpC;EACiB,EAAA,CAAA,GAEnB,YACC,iBAAA,GAAA,kBAAA,IAAA,CAACQ,iBAAAA,sBAAD,EAAsB,aAAaC,kBAAAA,aAAa,OAAO,CAAC,CAAC,OAAS,CAAA,IAChE,OAAO,WAAW,IACpB,iBAAA,GAAA,kBAAA,IAAA,CAACT,iBAAAA,eAAe,SAAhB,EACE,SAAS,iBAAiB,MAAM,SAAS,8BAA8B,MAAM,SAAS,YACvF,CAAA,IAED,iBAAA,GAAA,kBAAA,KAAA,CAAAU,kBAAAA,UAAA,EAAA,UAAA;GACE,iBAAA,GAAA,kBAAA,IAAA,CAACV,iBAAAA,eAAe,QAAhB,EAAuB,QAAQ,WAAa,CAAA;GAC3C,aAAa,KAAI,OAAM;IACtB,MAAM,QAAQ,OAAO,GAAG;IACxB,IAAI,CAAC,OAAO,OAAO;IAEnB,MAAM,aACJ,MAAM,YAAY,oBAAoB,kBAAkB,QAAQ,MAAM,WAAW;IACnF,MAAM,SAAS,GAAG,MAAM,QAAQ,GAAG,MAAM,UAAU;IACnD,MAAM,kBAAkB,mBAAmB,IAAI,MAAM,KAAK;IAC1D,MAAM,cAAc,MAAM,aAAa,MAAM;IAC7C,MAAM,QAAQ,gBAAgB,IAAI,MAAM,OAAO;IAE/C,OACE,iBAAA,GAAA,kBAAA,KAAA,CAACA,iBAAAA,eAAe,WAAhB;KAEE,KAAK,YAAY;KACjB,cAAY,GAAG;KACf,GAAI,YAAY,GAAG,KAAK;KACxB,eAAe,aAAa,KAAK;KACjC,UAAU;KACV,WAAWI,cAAAA,GAAG,mBAAmB,uBAAuB;KAP1D,UAAA;MASE,iBAAA,GAAA,kBAAA,IAAA,CAACJ,iBAAAA,eAAe,aAAhB;OAA4B,WAAW;OAAa,QAAO;MAAoB,CAAA;MAC9EC,0CAAAA,eAAe,mBAAmB,MAAM,KAAK,iBAAA,GAAA,kBAAA,IAAA,CAACD,iBAAAA,eAAe,UAAhB,EAAyB,YAAY,MAAM,WAAa,CAAA;MACtG,iBAAA,GAAA,kBAAA,IAAA,CAACA,iBAAAA,eAAe,UAAhB;OACE,MAAM,MAAM,cAAc,MAAM;OAChC,cAAc,MAAM;OACpB,kBAAkB;MACnB,CAAA;MACAC,0CAAAA,eAAe,mBAAmB,OAAO,KACxC,iBAAA,GAAA,kBAAA,IAAA,CAACD,iBAAAA,eAAe,WAAhB,EAA0B,OAAO,MAAM,gBAAgBW,wCAAAA,gBAAgB,MAAM,KAAK,EAAI,CAAA;MAEvFV,0CAAAA,eAAe,mBAAmB,QAAQ,MACxC,cAAc,KAAK,IAClB,iBAAA,GAAA,kBAAA,IAAA,CAACW,mDAAAA,gBAAD;OAAgB,SAAS,MAAM;OAAS,QAAQ,MAAM;OAAQ,cAAc,MAAM;MAAe,CAAA,IAEjG,iBAAA,GAAA,kBAAA,IAAA,CAACZ,iBAAAA,eAAe,YAAhB;OACE,QAAQ,MAAM;OACd,OAAO,MAAM;OACb,QAAQ,MAAM;MACf,CAAA;MAEL,iBAAA,GAAA,kBAAA,IAAA,CAACA,iBAAAA,eAAe,YAAhB,EAA2B,QAAQ,MAAM,OAAS,CAAA;MACjDC,0CAAAA,eAAe,mBAAmB,UAAU,KAC3C,iBAAA,GAAA,kBAAA,IAAA,CAACY,kBAAAA,SAAS,YAAV;OAAqB,MAAK;OACvB,UAAAC,uBAAAA,eAAeC,wCAAAA,kBAAkB,MAAM,WAAW,MAAM,OAAO,CAAC;MAC9C,CAAA;MAEtBd,0CAAAA,eAAe,mBAAmB,kBAAkB,KACnD,iBAAA,GAAA,kBAAA,IAAA,CAACY,kBAAAA,SAAS,YAAV;OAAqB,MAAK;OAAQ,UAAAC,uBAAAA,eAAe,MAAM,kBAAkB;MAAuB,CAAA;MAEjGb,0CAAAA,eAAe,mBAAmB,SAAS,KAC1C,iBAAA,GAAA,kBAAA,IAAA,CAACD,iBAAAA,eAAe,aAAhB;OAA4B,WAAW,MAAM,WAAW;OAAI,QAAO;MAAoB,CAAA;MAExFC,0CAAAA,eAAe,mBAAmB,aAAa,KAC9C,iBAAA,GAAA,kBAAA,IAAA,CAACY,kBAAAA,SAAS,UAAV,EAAA,UAAoB,MAAM,eAAe,IAAuB,CAAA;MAEjEZ,0CAAAA,eAAe,mBAAmB,OAAO,KACxC,iBAAA,GAAA,kBAAA,IAAA,CAACY,kBAAAA,SAAS,UAAV,EAAA,UAAoB,MAAM,SAAS,IAAuB,CAAA;MAE3DZ,0CAAAA,eAAe,mBAAmB,UAAU,KAC3C,iBAAA,GAAA,kBAAA,IAAA,CAACY,kBAAAA,SAAS,UAAV,EAAA,UAAoB,MAAM,YAAY,IAAuB,CAAA;MAE9DZ,0CAAAA,eAAe,mBAAmB,aAAa,KAC9C,iBAAA,GAAA,kBAAA,IAAA,CAACY,kBAAAA,SAAS,YAAV,EAAA,UACG,OAAO,gBAAgB,KAAA,IAAY,KAAA,IAAYG,aAAAA,oBAAoB,MAAM,WAAW,EAClE,CAAA;MAEtBf,0CAAAA,eAAe,mBAAmB,cAAc,KAC/C,iBAAA,GAAA,kBAAA,IAAA,CAACY,kBAAAA,SAAS,YAAV,EAAA,UACG,OAAO,iBAAiB,KAAA,IAAY,KAAA,IAAYG,aAAAA,oBAAoB,MAAM,YAAY,EACpE,CAAA;MAEtBf,0CAAAA,eAAe,mBAAmB,aAAa,KAC9C,iBAAA,GAAA,kBAAA,IAAA,CAACY,kBAAAA,SAAS,YAAV,EAAA,iBACU;OACN,MAAM,QAAQ,UAAU,KAAK;OAC7B,OAAO,UAAU,KAAA,IAAY,KAAA,IAAYG,aAAAA,oBAAoB,KAAK;MACpE,EAAA,CAAG,EACgB,CAAA;MAEtBf,0CAAAA,eAAe,mBAAmB,eAAe,KAChD,iBAAA,GAAA,kBAAA,IAAA,CAACY,kBAAAA,SAAS,YAAV,EAAA,UACG,OAAO,kBAAkB,KAAA,IAAY,KAAA,IAAYI,aAAAA,WAAW,MAAM,eAAe,MAAM,QAAQ,EAC7E,CAAA;MAEtB,kBAAkB,cAAc,KAAI,UACnC,iBAAA,GAAA,kBAAA,IAAA,CAACJ,kBAAAA,SAAS,UAAV;OAAmB,MAAK;OACrB,UAAA,kBAAkB,OAAO,KAAK,KAAK,KAAA;MACnB,GAFiB,KAEjB,CACpB;MACA,kBAAkB,aAAa,KAAI,QAAO;OACzC,MAAM,QAAQK,0CAAAA,yBAAyB,MAAM,UAAU,GAAG;OAC1D,OACE,iBAAA,GAAA,kBAAA,IAAA,CAACL,kBAAAA,SAAS,UAAV;QAAmB,MAAK;QACrB,UAAA;OACgB,GAFiB,GAEjB;MAEvB,CAAC;KACuB;IArFnB,GAAA,MAqFmB;GAE9B,CAAC;GACD,iBAAA,GAAA,kBAAA,IAAA,CAACb,iBAAAA,eAAe,QAAhB,EAAuB,QAAQ,cAAgB,CAAA;GAC/C,iBAAA,GAAA,kBAAA,IAAA,CAACA,iBAAAA,eAAe,iBAAhB;IACE,WAAW;IACX,SAAS;IACY;GACtB,CAAA;EACD,EAAA,CAAA,CAEU;;AAEpB"}
1
+ {"version":3,"file":"traces-list-view.cjs.js","names":["Tooltip","TooltipTrigger","TooltipContent","DEFAULT_TRACE_COLUMN_PREFERENCES","useRef","buildTraceListColumns","buildTraceListColumnKeys","useVirtualizer","useDataListKeyboard","TracesDataList","hasTraceColumn","TRACE_CUSTOM_COLUMN_LABELS","DropdownMenu","cn","focusRing","ListFilterIcon","Txt","DataListSkeletonRows","splitColumns","_Fragment","getInputPreview","TraceErrorCell","DataList","formatDuration","getSpanDurationMs","formatCompactNumber","formatCost","formatTraceMetadataValue"],"sources":["../../../../src/domains/traces/components/traces-list-view.tsx"],"sourcesContent":["import { useVirtualizer } from '@tanstack/react-virtual';\nimport { ListFilterIcon } from 'lucide-react';\nimport { useRef } from 'react';\nimport {\n DEFAULT_TRACE_COLUMN_PREFERENCES,\n TRACE_CUSTOM_COLUMN_LABELS,\n buildTraceListColumnKeys,\n buildTraceListColumns,\n formatTraceMetadataValue,\n hasTraceColumn,\n} from '../trace-list-columns';\nimport type { TraceColumnPreferences, TraceCustomColumn, TraceUsageSummary } from '../trace-list-columns';\nimport { getInputPreview, getSpanDurationMs } from '../utils/span-utils';\nimport { TraceErrorCell } from './trace-error-cell';\nimport { DataList, DataListSkeletonRows, TracesDataList, useDataListKeyboard } from '@/ds/components/DataList';\nimport type { DataListSort } from '@/ds/components/DataList';\nimport { splitColumns } from '@/ds/components/DataList/shared';\nimport { DropdownMenu } from '@/ds/components/DropdownMenu';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/ds/components/Tooltip';\nimport { Txt } from '@/ds/components/Txt/Txt';\nimport { focusRing } from '@/ds/primitives/transitions';\nimport { formatCompactNumber, formatCost } from '@/lib/cost';\nimport { cn } from '@/lib/utils';\nimport { formatDuration } from '@/utils/duration';\n\nexport type TracesListViewTrace = {\n traceId: string;\n /** Required for branch rows; absent on plain trace rows (which are root-rooted). */\n spanId?: string | null;\n /** `null`/missing → root span. Drives the Kind column's icon (top-level trace vs nested branch). */\n parentSpanId?: string | null;\n name: string;\n entityType?: string | null;\n entityId?: string | null;\n entityName?: string | null;\n threadId?: string | null;\n resourceId?: string | null;\n environment?: string | null;\n /** Model and provider of a model span; only span rows carry them. */\n model?: string | null;\n provider?: string | null;\n status?: string | null;\n /** Server-rendered preview of `input`. Present on lightweight rows, which omit `input` itself. */\n inputPreview?: string | null;\n input?: unknown;\n /** Server-rendered preview of the root span's output. */\n outputPreview?: string;\n /** Server-rendered preview of the root span's error. Shown in place of the output when `status` is `'error'`. */\n errorPreview?: string;\n metadata?: Record<string, unknown> | null;\n startedAt?: Date | string | null;\n endedAt?: Date | string | null;\n /** The root span's time to first chunk; `null` when it never streamed one. */\n timeToFirstChunkMs?: number | null;\n /** Thread rows only: every trace in the thread, regardless of the listed time range. */\n traceCount?: number;\n createdAt: Date | string;\n};\n\nconst ROW_HEIGHT = 36;\nconst OVERSCAN = 8;\n/** Distinct values offered in a custom column's \"filter by value\" header menu. */\nconst MAX_FILTER_VALUES = 20;\n\nfunction customColumnValue(trace: TracesListViewTrace, field: TraceCustomColumn): string | null | undefined {\n return trace[field];\n}\n\nfunction distinctCustomColumnValues(traces: TracesListViewTrace[], field: TraceCustomColumn): string[] {\n const values = new Set<string>();\n for (const trace of traces) {\n const value = trace[field];\n if (typeof value === 'string' && value) values.add(value);\n if (values.size >= MAX_FILTER_VALUES) break;\n }\n return [...values];\n}\n\nfunction sumTokens(usage: TraceUsageSummary | undefined): number | undefined {\n if (usage?.inputTokens === undefined && usage?.outputTokens === undefined) return undefined;\n return (usage?.inputTokens ?? 0) + (usage?.outputTokens ?? 0);\n}\n\ntype FailedTrace = TracesListViewTrace & { spanId: string; errorPreview: string };\n\n/** A failed row whose error preview can open the full error from its span. */\nfunction isFailedTrace(trace: TracesListViewTrace): trace is FailedTrace {\n return trace.status === 'error' && !!trace.errorPreview && !!trace.spanId;\n}\n\n/** The TTFC abbreviation, spelled out on hover; the sort button already names the column for screen readers. */\nfunction TimeToFirstChunkLabel() {\n return (\n <Tooltip>\n <TooltipTrigger render={<span />}>TTFC</TooltipTrigger>\n <TooltipContent>Time to first chunk</TooltipContent>\n </Tooltip>\n );\n}\n\nexport type TracesListViewProps = {\n traces: TracesListViewTrace[];\n isLoading?: boolean;\n isFetchingNextPage?: boolean;\n hasNextPage?: boolean;\n setEndOfListElement?: (element: HTMLDivElement | null) => void;\n filtersApplied?: boolean;\n /** What the rows hold, named in the empty messages. Defaults to `traces`. */\n resource?: 'traces' | 'spans' | 'threads';\n /** Currently featured/selected trace — its row gets the highlighted background. */\n featuredTraceId?: string | null;\n /**\n * Required in branches mode to disambiguate rows sharing a `traceId`. When set,\n * a row is featured only when both `traceId` and `spanId` match.\n */\n featuredSpanId?: string | null;\n /** Branches mode mixes root traces with subtraces — enables the Trace/Subtrace tooltip on the\n * level icon in the Name column, which is meaningless when every row is a root. */\n isBranchesMode?: boolean;\n /** Keys (`traceId:spanId`) of rows that just arrived via delta polling. Rows whose key is in\n * this set get a temporary tint to distinguish them from rows present since the last page-mode\n * fetch. Auto-expires upstream (in useTraces) after a short window. */\n recentlyAddedKeys?: Set<string>;\n /** Optional and metadata columns selected for this project. */\n columnPreferences?: TraceColumnPreferences;\n /** Token and estimated-cost totals, aggregated across model spans by trace ID. */\n usageByTraceId?: ReadonlyMap<string, TraceUsageSummary>;\n /** Called when a row is clicked. The current selection logic (toggle on same id) is the consumer's call. */\n onTraceClick: (trace: TracesListViewTrace) => void;\n /** Current sort of the Created column. When `onSortChange` is provided the header becomes sortable. */\n createdSort?: DataListSort;\n onSortChange?: (direction: DataListSort, key: 'startedAt') => void;\n /** Current sort of the TTFC column. When `onTimeToFirstChunkSortChange` is provided the header becomes sortable. */\n timeToFirstChunkSort?: DataListSort;\n onTimeToFirstChunkSortChange?: (direction: DataListSort) => void;\n /** When provided, custom column headers offer an `is <value>` filter for every value currently listed. */\n onFilterByField?: (field: TraceCustomColumn, value: string) => void;\n /** Storage id for the persisted column order. Use a distinct id per page so each keeps its own order. */\n listId?: string;\n};\n\n/**\n * Virtualized presentational list. Renders only the visible window via TanStack Virtual, and\n * uses DataList primitives for layout (CSS Grid with subgrid rows).\n */\nexport function TracesListView({\n traces,\n isLoading,\n isFetchingNextPage,\n hasNextPage,\n setEndOfListElement,\n filtersApplied,\n resource = 'traces',\n featuredTraceId,\n featuredSpanId,\n isBranchesMode,\n recentlyAddedKeys,\n columnPreferences = DEFAULT_TRACE_COLUMN_PREFERENCES,\n usageByTraceId,\n onTraceClick,\n createdSort,\n onSortChange,\n timeToFirstChunkSort,\n onTimeToFirstChunkSortChange,\n onFilterByField,\n listId = 'all-traces',\n}: TracesListViewProps) {\n const scrollRef = useRef<HTMLDivElement | null>(null);\n const columns = buildTraceListColumns(columnPreferences);\n const columnKeys = buildTraceListColumnKeys(columnPreferences);\n\n const virtualizer = useVirtualizer({\n count: traces.length,\n getScrollElement: () => scrollRef.current,\n estimateSize: () => ROW_HEIGHT,\n overscan: OVERSCAN,\n });\n\n const { getRowProps } = useDataListKeyboard({\n count: traces.length,\n containerRef: scrollRef,\n onNavigate: index => virtualizer.scrollToIndex(index),\n global: true,\n });\n\n const virtualItems = virtualizer.getVirtualItems();\n const totalSize = virtualizer.getTotalSize();\n const paddingTop = virtualItems[0]?.start ?? 0;\n const paddingBottom =\n virtualItems.length > 0 ? Math.max(0, totalSize - (virtualItems[virtualItems.length - 1]?.end ?? 0)) : 0;\n\n return (\n <TracesDataList\n reorderable\n id={listId}\n columns={columns}\n columnKeys={columnKeys}\n fit=\"container\"\n scrollRef={scrollRef}\n className=\"min-w-0\"\n >\n <TracesDataList.Top>\n {onSortChange ? (\n <TracesDataList.SortableTopCell sortKey=\"startedAt\" sort={createdSort} onSortChange={onSortChange}>\n Start\n </TracesDataList.SortableTopCell>\n ) : (\n <TracesDataList.TopCell>Start</TracesDataList.TopCell>\n )}\n {hasTraceColumn(columnPreferences, 'type') && <TracesDataList.TopCell>Primitive type</TracesDataList.TopCell>}\n <TracesDataList.TopCell>Primitive name</TracesDataList.TopCell>\n {hasTraceColumn(columnPreferences, 'input') && <TracesDataList.TopCell>Input</TracesDataList.TopCell>}\n {hasTraceColumn(columnPreferences, 'output') && <TracesDataList.TopCell>Output</TracesDataList.TopCell>}\n <TracesDataList.TopCell>Status</TracesDataList.TopCell>\n {hasTraceColumn(columnPreferences, 'duration') && (\n <TracesDataList.TopCell className=\"justify-end text-right\">Duration</TracesDataList.TopCell>\n )}\n {hasTraceColumn(columnPreferences, 'traceCount') && (\n <TracesDataList.TopCellWithTooltip\n tooltip=\"Messages sent in this thread, counting the whole thread, not just the selected time range\"\n className=\"justify-end text-right\"\n >\n Messages\n </TracesDataList.TopCellWithTooltip>\n )}\n {hasTraceColumn(columnPreferences, 'timeToFirstChunk') &&\n (onTimeToFirstChunkSortChange ? (\n <TracesDataList.SortableTopCell\n sortKey=\"timeToFirstChunkMs\"\n sort={timeToFirstChunkSort}\n onSortChange={onTimeToFirstChunkSortChange}\n label=\"Time to first chunk\"\n align=\"end\"\n >\n <TimeToFirstChunkLabel />\n </TracesDataList.SortableTopCell>\n ) : (\n <TracesDataList.TopCellWithTooltip tooltip=\"Time to first chunk\" className=\"justify-end text-right\">\n TTFC\n </TracesDataList.TopCellWithTooltip>\n ))}\n {hasTraceColumn(columnPreferences, 'endTime') && <TracesDataList.TopCell>End</TracesDataList.TopCell>}\n {hasTraceColumn(columnPreferences, 'environment') && (\n <TracesDataList.TopCell>Environment</TracesDataList.TopCell>\n )}\n {hasTraceColumn(columnPreferences, 'model') && <TracesDataList.TopCell>Model</TracesDataList.TopCell>}\n {hasTraceColumn(columnPreferences, 'provider') && <TracesDataList.TopCell>Provider</TracesDataList.TopCell>}\n {hasTraceColumn(columnPreferences, 'inputTokens') && (\n <TracesDataList.TopCell className=\"justify-end text-right\">Input tokens</TracesDataList.TopCell>\n )}\n {hasTraceColumn(columnPreferences, 'outputTokens') && (\n <TracesDataList.TopCell className=\"justify-end text-right\">Output tokens</TracesDataList.TopCell>\n )}\n {hasTraceColumn(columnPreferences, 'totalTokens') && (\n <TracesDataList.TopCell className=\"justify-end text-right\">Total tokens</TracesDataList.TopCell>\n )}\n {hasTraceColumn(columnPreferences, 'estimatedCost') && (\n <TracesDataList.TopCell className=\"justify-end text-right\">Est. cost</TracesDataList.TopCell>\n )}\n {columnPreferences.customColumns.map(field => {\n const label = TRACE_CUSTOM_COLUMN_LABELS[field];\n const filterValues = onFilterByField ? distinctCustomColumnValues(traces, field) : [];\n if (!onFilterByField || filterValues.length === 0) {\n return <TracesDataList.TopCell key={field}>{label}</TracesDataList.TopCell>;\n }\n return (\n <TracesDataList.TopCell key={field} className=\"overflow-visible\">\n <DropdownMenu>\n <DropdownMenu.Trigger\n render={\n <button\n type=\"button\"\n className={cn('flex min-w-0 items-center gap-1 rounded-sm hover:text-foreground', focusRing)}\n >\n <span className=\"min-w-0 truncate\">{label}</span>\n <ListFilterIcon aria-hidden className=\"size-[1.2em] shrink-0\" />\n </button>\n }\n />\n <DropdownMenu.Content align=\"start\">\n <DropdownMenu.Label>Filter by value</DropdownMenu.Label>\n {filterValues.map(value => (\n <DropdownMenu.Item key={value} onSelect={() => onFilterByField(field, value)}>\n <Txt as=\"span\" variant=\"body-sm\" font=\"mono\" className=\"min-w-0 truncate\">\n {value}\n </Txt>\n </DropdownMenu.Item>\n ))}\n </DropdownMenu.Content>\n </DropdownMenu>\n </TracesDataList.TopCell>\n );\n })}\n {columnPreferences.metadataKeys.map(key => (\n <TracesDataList.TopCellWithTooltip key={key} tooltip={key}>\n {key}\n </TracesDataList.TopCellWithTooltip>\n ))}\n </TracesDataList.Top>\n\n {isLoading ? (\n <DataListSkeletonRows columnCount={splitColumns(columns).length} />\n ) : traces.length === 0 ? (\n <TracesDataList.NoMatch\n message={filtersApplied ? `No ${resource} found for applied filters` : `No ${resource} found yet`}\n />\n ) : (\n <>\n <TracesDataList.Spacer height={paddingTop} />\n {virtualItems.map(vi => {\n const trace = traces[vi.index];\n if (!trace) return null;\n\n const isFeatured =\n trace.traceId === featuredTraceId && (featuredSpanId == null || trace.spanId === featuredSpanId);\n const rowKey = `${trace.traceId}:${trace.spanId ?? ''}`;\n const isRecentlyAdded = recentlyAddedKeys?.has(rowKey) ?? false;\n const displayDate = trace.startedAt ?? trace.createdAt;\n const usage = usageByTraceId?.get(trace.traceId);\n\n return (\n <TracesDataList.RowButton\n key={rowKey}\n ref={virtualizer.measureElement}\n data-index={vi.index}\n {...getRowProps(vi.index)}\n onClick={() => onTraceClick(trace)}\n featured={isFeatured}\n className={cn(isRecentlyAdded && 'animate-row-highlight')}\n >\n <TracesDataList.CreatedCell timestamp={displayDate} preset=\"day-time-seconds\" />\n {hasTraceColumn(columnPreferences, 'type') && <TracesDataList.TypeCell entityType={trace.entityType} />}\n <TracesDataList.NameCell\n name={trace.entityName || trace.name}\n parentSpanId={trace.parentSpanId}\n showLevelTooltip={isBranchesMode}\n />\n {hasTraceColumn(columnPreferences, 'input') && (\n <TracesDataList.InputCell input={trace.inputPreview ?? getInputPreview(trace.input)} />\n )}\n {hasTraceColumn(columnPreferences, 'output') &&\n (isFailedTrace(trace) ? (\n <TraceErrorCell traceId={trace.traceId} spanId={trace.spanId} errorPreview={trace.errorPreview} />\n ) : (\n <TracesDataList.OutputCell\n output={trace.outputPreview}\n error={trace.errorPreview}\n status={trace.status}\n />\n ))}\n <TracesDataList.StatusCell status={trace.status} />\n {hasTraceColumn(columnPreferences, 'duration') && (\n <DataList.NumberCell font=\"mono\">\n {formatDuration(getSpanDurationMs(trace.startedAt, trace.endedAt))}\n </DataList.NumberCell>\n )}\n {hasTraceColumn(columnPreferences, 'traceCount') && (\n <DataList.NumberCell>\n {trace.traceCount === undefined ? undefined : formatCompactNumber(trace.traceCount)}\n </DataList.NumberCell>\n )}\n {hasTraceColumn(columnPreferences, 'timeToFirstChunk') && (\n <DataList.NumberCell font=\"mono\">{formatDuration(trace.timeToFirstChunkMs)}</DataList.NumberCell>\n )}\n {hasTraceColumn(columnPreferences, 'endTime') && (\n <TracesDataList.CreatedCell timestamp={trace.endedAt ?? ''} preset=\"day-time-seconds\" />\n )}\n {hasTraceColumn(columnPreferences, 'environment') && (\n <DataList.TextCell>{trace.environment || '—'}</DataList.TextCell>\n )}\n {hasTraceColumn(columnPreferences, 'model') && (\n <DataList.TextCell>{trace.model || '—'}</DataList.TextCell>\n )}\n {hasTraceColumn(columnPreferences, 'provider') && (\n <DataList.TextCell>{trace.provider || '—'}</DataList.TextCell>\n )}\n {hasTraceColumn(columnPreferences, 'inputTokens') && (\n <DataList.NumberCell>\n {usage?.inputTokens === undefined ? undefined : formatCompactNumber(usage.inputTokens)}\n </DataList.NumberCell>\n )}\n {hasTraceColumn(columnPreferences, 'outputTokens') && (\n <DataList.NumberCell>\n {usage?.outputTokens === undefined ? undefined : formatCompactNumber(usage.outputTokens)}\n </DataList.NumberCell>\n )}\n {hasTraceColumn(columnPreferences, 'totalTokens') && (\n <DataList.NumberCell>\n {(() => {\n const total = sumTokens(usage);\n return total === undefined ? undefined : formatCompactNumber(total);\n })()}\n </DataList.NumberCell>\n )}\n {hasTraceColumn(columnPreferences, 'estimatedCost') && (\n <DataList.NumberCell>\n {usage?.estimatedCost === undefined ? undefined : formatCost(usage.estimatedCost, usage.costUnit)}\n </DataList.NumberCell>\n )}\n {columnPreferences.customColumns.map(field => (\n <DataList.TextCell font=\"mono\" key={field}>\n {customColumnValue(trace, field) ?? undefined}\n </DataList.TextCell>\n ))}\n {columnPreferences.metadataKeys.map(key => {\n const value = formatTraceMetadataValue(trace.metadata, key);\n return (\n <DataList.TextCell font=\"mono\" key={key}>\n {value}\n </DataList.TextCell>\n );\n })}\n </TracesDataList.RowButton>\n );\n })}\n <TracesDataList.Spacer height={paddingBottom} />\n <TracesDataList.NextPageLoading\n isLoading={isFetchingNextPage}\n hasMore={hasNextPage}\n setEndOfListElement={setEndOfListElement}\n />\n </>\n )}\n </TracesDataList>\n );\n}\n"],"mappings":"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"}
@@ -95,6 +95,11 @@ function TracesListView({ traces, isLoading, isFetchingNextPage, hasNextPage, se
95
95
  className: "justify-end text-right",
96
96
  children: "Duration"
97
97
  }),
98
+ hasTraceColumn(columnPreferences, "traceCount") && /* @__PURE__ */ jsx(TracesDataList.TopCellWithTooltip, {
99
+ tooltip: "Messages sent in this thread, counting the whole thread, not just the selected time range",
100
+ className: "justify-end text-right",
101
+ children: "Messages"
102
+ }),
98
103
  hasTraceColumn(columnPreferences, "timeToFirstChunk") && (onTimeToFirstChunkSortChange ? /* @__PURE__ */ jsx(TracesDataList.SortableTopCell, {
99
104
  sortKey: "timeToFirstChunkMs",
100
105
  sort: timeToFirstChunkSort,
@@ -205,6 +210,7 @@ function TracesListView({ traces, isLoading, isFetchingNextPage, hasNextPage, se
205
210
  font: "mono",
206
211
  children: formatDuration(getSpanDurationMs(trace.startedAt, trace.endedAt))
207
212
  }),
213
+ hasTraceColumn(columnPreferences, "traceCount") && /* @__PURE__ */ jsx(DataList.NumberCell, { children: trace.traceCount === void 0 ? void 0 : formatCompactNumber(trace.traceCount) }),
208
214
  hasTraceColumn(columnPreferences, "timeToFirstChunk") && /* @__PURE__ */ jsx(DataList.NumberCell, {
209
215
  font: "mono",
210
216
  children: formatDuration(trace.timeToFirstChunkMs)
@@ -1 +1 @@
1
- {"version":3,"file":"traces-list-view.es.js","names":["_Fragment"],"sources":["../../../../src/domains/traces/components/traces-list-view.tsx"],"sourcesContent":["import { useVirtualizer } from '@tanstack/react-virtual';\nimport { ListFilterIcon } from 'lucide-react';\nimport { useRef } from 'react';\nimport {\n DEFAULT_TRACE_COLUMN_PREFERENCES,\n TRACE_CUSTOM_COLUMN_LABELS,\n buildTraceListColumnKeys,\n buildTraceListColumns,\n formatTraceMetadataValue,\n hasTraceColumn,\n} from '../trace-list-columns';\nimport type { TraceColumnPreferences, TraceCustomColumn, TraceUsageSummary } from '../trace-list-columns';\nimport { getInputPreview, getSpanDurationMs } from '../utils/span-utils';\nimport { TraceErrorCell } from './trace-error-cell';\nimport { DataList, DataListSkeletonRows, TracesDataList, useDataListKeyboard } from '@/ds/components/DataList';\nimport type { DataListSort } from '@/ds/components/DataList';\nimport { splitColumns } from '@/ds/components/DataList/shared';\nimport { DropdownMenu } from '@/ds/components/DropdownMenu';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/ds/components/Tooltip';\nimport { Txt } from '@/ds/components/Txt/Txt';\nimport { focusRing } from '@/ds/primitives/transitions';\nimport { formatCompactNumber, formatCost } from '@/lib/cost';\nimport { cn } from '@/lib/utils';\nimport { formatDuration } from '@/utils/duration';\n\nexport type TracesListViewTrace = {\n traceId: string;\n /** Required for branch rows; absent on plain trace rows (which are root-rooted). */\n spanId?: string | null;\n /** `null`/missing → root span. Drives the Kind column's icon (top-level trace vs nested branch). */\n parentSpanId?: string | null;\n name: string;\n entityType?: string | null;\n entityId?: string | null;\n entityName?: string | null;\n threadId?: string | null;\n resourceId?: string | null;\n environment?: string | null;\n /** Model and provider of a model span; only span rows carry them. */\n model?: string | null;\n provider?: string | null;\n status?: string | null;\n /** Server-rendered preview of `input`. Present on lightweight rows, which omit `input` itself. */\n inputPreview?: string | null;\n input?: unknown;\n /** Server-rendered preview of the root span's output. */\n outputPreview?: string;\n /** Server-rendered preview of the root span's error. Shown in place of the output when `status` is `'error'`. */\n errorPreview?: string;\n metadata?: Record<string, unknown> | null;\n startedAt?: Date | string | null;\n endedAt?: Date | string | null;\n /** The root span's time to first chunk; `null` when it never streamed one. */\n timeToFirstChunkMs?: number | null;\n createdAt: Date | string;\n};\n\nconst ROW_HEIGHT = 36;\nconst OVERSCAN = 8;\n/** Distinct values offered in a custom column's \"filter by value\" header menu. */\nconst MAX_FILTER_VALUES = 20;\n\nfunction customColumnValue(trace: TracesListViewTrace, field: TraceCustomColumn): string | null | undefined {\n return trace[field];\n}\n\nfunction distinctCustomColumnValues(traces: TracesListViewTrace[], field: TraceCustomColumn): string[] {\n const values = new Set<string>();\n for (const trace of traces) {\n const value = trace[field];\n if (typeof value === 'string' && value) values.add(value);\n if (values.size >= MAX_FILTER_VALUES) break;\n }\n return [...values];\n}\n\nfunction sumTokens(usage: TraceUsageSummary | undefined): number | undefined {\n if (usage?.inputTokens === undefined && usage?.outputTokens === undefined) return undefined;\n return (usage?.inputTokens ?? 0) + (usage?.outputTokens ?? 0);\n}\n\ntype FailedTrace = TracesListViewTrace & { spanId: string; errorPreview: string };\n\n/** A failed row whose error preview can open the full error from its span. */\nfunction isFailedTrace(trace: TracesListViewTrace): trace is FailedTrace {\n return trace.status === 'error' && !!trace.errorPreview && !!trace.spanId;\n}\n\n/** The TTFC abbreviation, spelled out on hover; the sort button already names the column for screen readers. */\nfunction TimeToFirstChunkLabel() {\n return (\n <Tooltip>\n <TooltipTrigger render={<span />}>TTFC</TooltipTrigger>\n <TooltipContent>Time to first chunk</TooltipContent>\n </Tooltip>\n );\n}\n\nexport type TracesListViewProps = {\n traces: TracesListViewTrace[];\n isLoading?: boolean;\n isFetchingNextPage?: boolean;\n hasNextPage?: boolean;\n setEndOfListElement?: (element: HTMLDivElement | null) => void;\n filtersApplied?: boolean;\n /** What the rows hold, named in the empty messages. Defaults to `traces`. */\n resource?: 'traces' | 'spans' | 'threads';\n /** Currently featured/selected trace — its row gets the highlighted background. */\n featuredTraceId?: string | null;\n /**\n * Required in branches mode to disambiguate rows sharing a `traceId`. When set,\n * a row is featured only when both `traceId` and `spanId` match.\n */\n featuredSpanId?: string | null;\n /** Branches mode mixes root traces with subtraces — enables the Trace/Subtrace tooltip on the\n * level icon in the Name column, which is meaningless when every row is a root. */\n isBranchesMode?: boolean;\n /** Keys (`traceId:spanId`) of rows that just arrived via delta polling. Rows whose key is in\n * this set get a temporary tint to distinguish them from rows present since the last page-mode\n * fetch. Auto-expires upstream (in useTraces) after a short window. */\n recentlyAddedKeys?: Set<string>;\n /** Optional and metadata columns selected for this project. */\n columnPreferences?: TraceColumnPreferences;\n /** Token and estimated-cost totals, aggregated across model spans by trace ID. */\n usageByTraceId?: ReadonlyMap<string, TraceUsageSummary>;\n /** Called when a row is clicked. The current selection logic (toggle on same id) is the consumer's call. */\n onTraceClick: (trace: TracesListViewTrace) => void;\n /** Current sort of the Created column. When `onSortChange` is provided the header becomes sortable. */\n createdSort?: DataListSort;\n onSortChange?: (direction: DataListSort, key: 'startedAt') => void;\n /** Current sort of the TTFC column. When `onTimeToFirstChunkSortChange` is provided the header becomes sortable. */\n timeToFirstChunkSort?: DataListSort;\n onTimeToFirstChunkSortChange?: (direction: DataListSort) => void;\n /** When provided, custom column headers offer an `is <value>` filter for every value currently listed. */\n onFilterByField?: (field: TraceCustomColumn, value: string) => void;\n /** Storage id for the persisted column order. Use a distinct id per page so each keeps its own order. */\n listId?: string;\n};\n\n/**\n * Virtualized presentational list. Renders only the visible window via TanStack Virtual, and\n * uses DataList primitives for layout (CSS Grid with subgrid rows).\n */\nexport function TracesListView({\n traces,\n isLoading,\n isFetchingNextPage,\n hasNextPage,\n setEndOfListElement,\n filtersApplied,\n resource = 'traces',\n featuredTraceId,\n featuredSpanId,\n isBranchesMode,\n recentlyAddedKeys,\n columnPreferences = DEFAULT_TRACE_COLUMN_PREFERENCES,\n usageByTraceId,\n onTraceClick,\n createdSort,\n onSortChange,\n timeToFirstChunkSort,\n onTimeToFirstChunkSortChange,\n onFilterByField,\n listId = 'all-traces',\n}: TracesListViewProps) {\n const scrollRef = useRef<HTMLDivElement | null>(null);\n const columns = buildTraceListColumns(columnPreferences);\n const columnKeys = buildTraceListColumnKeys(columnPreferences);\n\n const virtualizer = useVirtualizer({\n count: traces.length,\n getScrollElement: () => scrollRef.current,\n estimateSize: () => ROW_HEIGHT,\n overscan: OVERSCAN,\n });\n\n const { getRowProps } = useDataListKeyboard({\n count: traces.length,\n containerRef: scrollRef,\n onNavigate: index => virtualizer.scrollToIndex(index),\n global: true,\n });\n\n const virtualItems = virtualizer.getVirtualItems();\n const totalSize = virtualizer.getTotalSize();\n const paddingTop = virtualItems[0]?.start ?? 0;\n const paddingBottom =\n virtualItems.length > 0 ? Math.max(0, totalSize - (virtualItems[virtualItems.length - 1]?.end ?? 0)) : 0;\n\n return (\n <TracesDataList\n reorderable\n id={listId}\n columns={columns}\n columnKeys={columnKeys}\n fit=\"container\"\n scrollRef={scrollRef}\n className=\"min-w-0\"\n >\n <TracesDataList.Top>\n {onSortChange ? (\n <TracesDataList.SortableTopCell sortKey=\"startedAt\" sort={createdSort} onSortChange={onSortChange}>\n Start\n </TracesDataList.SortableTopCell>\n ) : (\n <TracesDataList.TopCell>Start</TracesDataList.TopCell>\n )}\n {hasTraceColumn(columnPreferences, 'type') && <TracesDataList.TopCell>Primitive type</TracesDataList.TopCell>}\n <TracesDataList.TopCell>Primitive name</TracesDataList.TopCell>\n {hasTraceColumn(columnPreferences, 'input') && <TracesDataList.TopCell>Input</TracesDataList.TopCell>}\n {hasTraceColumn(columnPreferences, 'output') && <TracesDataList.TopCell>Output</TracesDataList.TopCell>}\n <TracesDataList.TopCell>Status</TracesDataList.TopCell>\n {hasTraceColumn(columnPreferences, 'duration') && (\n <TracesDataList.TopCell className=\"justify-end text-right\">Duration</TracesDataList.TopCell>\n )}\n {hasTraceColumn(columnPreferences, 'timeToFirstChunk') &&\n (onTimeToFirstChunkSortChange ? (\n <TracesDataList.SortableTopCell\n sortKey=\"timeToFirstChunkMs\"\n sort={timeToFirstChunkSort}\n onSortChange={onTimeToFirstChunkSortChange}\n label=\"Time to first chunk\"\n align=\"end\"\n >\n <TimeToFirstChunkLabel />\n </TracesDataList.SortableTopCell>\n ) : (\n <TracesDataList.TopCellWithTooltip tooltip=\"Time to first chunk\" className=\"justify-end text-right\">\n TTFC\n </TracesDataList.TopCellWithTooltip>\n ))}\n {hasTraceColumn(columnPreferences, 'endTime') && <TracesDataList.TopCell>End</TracesDataList.TopCell>}\n {hasTraceColumn(columnPreferences, 'environment') && (\n <TracesDataList.TopCell>Environment</TracesDataList.TopCell>\n )}\n {hasTraceColumn(columnPreferences, 'model') && <TracesDataList.TopCell>Model</TracesDataList.TopCell>}\n {hasTraceColumn(columnPreferences, 'provider') && <TracesDataList.TopCell>Provider</TracesDataList.TopCell>}\n {hasTraceColumn(columnPreferences, 'inputTokens') && (\n <TracesDataList.TopCell className=\"justify-end text-right\">Input tokens</TracesDataList.TopCell>\n )}\n {hasTraceColumn(columnPreferences, 'outputTokens') && (\n <TracesDataList.TopCell className=\"justify-end text-right\">Output tokens</TracesDataList.TopCell>\n )}\n {hasTraceColumn(columnPreferences, 'totalTokens') && (\n <TracesDataList.TopCell className=\"justify-end text-right\">Total tokens</TracesDataList.TopCell>\n )}\n {hasTraceColumn(columnPreferences, 'estimatedCost') && (\n <TracesDataList.TopCell className=\"justify-end text-right\">Est. cost</TracesDataList.TopCell>\n )}\n {columnPreferences.customColumns.map(field => {\n const label = TRACE_CUSTOM_COLUMN_LABELS[field];\n const filterValues = onFilterByField ? distinctCustomColumnValues(traces, field) : [];\n if (!onFilterByField || filterValues.length === 0) {\n return <TracesDataList.TopCell key={field}>{label}</TracesDataList.TopCell>;\n }\n return (\n <TracesDataList.TopCell key={field} className=\"overflow-visible\">\n <DropdownMenu>\n <DropdownMenu.Trigger\n render={\n <button\n type=\"button\"\n className={cn('flex min-w-0 items-center gap-1 rounded-sm hover:text-foreground', focusRing)}\n >\n <span className=\"min-w-0 truncate\">{label}</span>\n <ListFilterIcon aria-hidden className=\"size-[1.2em] shrink-0\" />\n </button>\n }\n />\n <DropdownMenu.Content align=\"start\">\n <DropdownMenu.Label>Filter by value</DropdownMenu.Label>\n {filterValues.map(value => (\n <DropdownMenu.Item key={value} onSelect={() => onFilterByField(field, value)}>\n <Txt as=\"span\" variant=\"body-sm\" font=\"mono\" className=\"min-w-0 truncate\">\n {value}\n </Txt>\n </DropdownMenu.Item>\n ))}\n </DropdownMenu.Content>\n </DropdownMenu>\n </TracesDataList.TopCell>\n );\n })}\n {columnPreferences.metadataKeys.map(key => (\n <TracesDataList.TopCellWithTooltip key={key} tooltip={key}>\n {key}\n </TracesDataList.TopCellWithTooltip>\n ))}\n </TracesDataList.Top>\n\n {isLoading ? (\n <DataListSkeletonRows columnCount={splitColumns(columns).length} />\n ) : traces.length === 0 ? (\n <TracesDataList.NoMatch\n message={filtersApplied ? `No ${resource} found for applied filters` : `No ${resource} found yet`}\n />\n ) : (\n <>\n <TracesDataList.Spacer height={paddingTop} />\n {virtualItems.map(vi => {\n const trace = traces[vi.index];\n if (!trace) return null;\n\n const isFeatured =\n trace.traceId === featuredTraceId && (featuredSpanId == null || trace.spanId === featuredSpanId);\n const rowKey = `${trace.traceId}:${trace.spanId ?? ''}`;\n const isRecentlyAdded = recentlyAddedKeys?.has(rowKey) ?? false;\n const displayDate = trace.startedAt ?? trace.createdAt;\n const usage = usageByTraceId?.get(trace.traceId);\n\n return (\n <TracesDataList.RowButton\n key={rowKey}\n ref={virtualizer.measureElement}\n data-index={vi.index}\n {...getRowProps(vi.index)}\n onClick={() => onTraceClick(trace)}\n featured={isFeatured}\n className={cn(isRecentlyAdded && 'animate-row-highlight')}\n >\n <TracesDataList.CreatedCell timestamp={displayDate} preset=\"day-time-seconds\" />\n {hasTraceColumn(columnPreferences, 'type') && <TracesDataList.TypeCell entityType={trace.entityType} />}\n <TracesDataList.NameCell\n name={trace.entityName || trace.name}\n parentSpanId={trace.parentSpanId}\n showLevelTooltip={isBranchesMode}\n />\n {hasTraceColumn(columnPreferences, 'input') && (\n <TracesDataList.InputCell input={trace.inputPreview ?? getInputPreview(trace.input)} />\n )}\n {hasTraceColumn(columnPreferences, 'output') &&\n (isFailedTrace(trace) ? (\n <TraceErrorCell traceId={trace.traceId} spanId={trace.spanId} errorPreview={trace.errorPreview} />\n ) : (\n <TracesDataList.OutputCell\n output={trace.outputPreview}\n error={trace.errorPreview}\n status={trace.status}\n />\n ))}\n <TracesDataList.StatusCell status={trace.status} />\n {hasTraceColumn(columnPreferences, 'duration') && (\n <DataList.NumberCell font=\"mono\">\n {formatDuration(getSpanDurationMs(trace.startedAt, trace.endedAt))}\n </DataList.NumberCell>\n )}\n {hasTraceColumn(columnPreferences, 'timeToFirstChunk') && (\n <DataList.NumberCell font=\"mono\">{formatDuration(trace.timeToFirstChunkMs)}</DataList.NumberCell>\n )}\n {hasTraceColumn(columnPreferences, 'endTime') && (\n <TracesDataList.CreatedCell timestamp={trace.endedAt ?? ''} preset=\"day-time-seconds\" />\n )}\n {hasTraceColumn(columnPreferences, 'environment') && (\n <DataList.TextCell>{trace.environment || '—'}</DataList.TextCell>\n )}\n {hasTraceColumn(columnPreferences, 'model') && (\n <DataList.TextCell>{trace.model || '—'}</DataList.TextCell>\n )}\n {hasTraceColumn(columnPreferences, 'provider') && (\n <DataList.TextCell>{trace.provider || '—'}</DataList.TextCell>\n )}\n {hasTraceColumn(columnPreferences, 'inputTokens') && (\n <DataList.NumberCell>\n {usage?.inputTokens === undefined ? undefined : formatCompactNumber(usage.inputTokens)}\n </DataList.NumberCell>\n )}\n {hasTraceColumn(columnPreferences, 'outputTokens') && (\n <DataList.NumberCell>\n {usage?.outputTokens === undefined ? undefined : formatCompactNumber(usage.outputTokens)}\n </DataList.NumberCell>\n )}\n {hasTraceColumn(columnPreferences, 'totalTokens') && (\n <DataList.NumberCell>\n {(() => {\n const total = sumTokens(usage);\n return total === undefined ? undefined : formatCompactNumber(total);\n })()}\n </DataList.NumberCell>\n )}\n {hasTraceColumn(columnPreferences, 'estimatedCost') && (\n <DataList.NumberCell>\n {usage?.estimatedCost === undefined ? undefined : formatCost(usage.estimatedCost, usage.costUnit)}\n </DataList.NumberCell>\n )}\n {columnPreferences.customColumns.map(field => (\n <DataList.TextCell font=\"mono\" key={field}>\n {customColumnValue(trace, field) ?? undefined}\n </DataList.TextCell>\n ))}\n {columnPreferences.metadataKeys.map(key => {\n const value = formatTraceMetadataValue(trace.metadata, key);\n return (\n <DataList.TextCell font=\"mono\" key={key}>\n {value}\n </DataList.TextCell>\n );\n })}\n </TracesDataList.RowButton>\n );\n })}\n <TracesDataList.Spacer height={paddingBottom} />\n <TracesDataList.NextPageLoading\n isLoading={isFetchingNextPage}\n hasMore={hasNextPage}\n setEndOfListElement={setEndOfListElement}\n />\n </>\n )}\n </TracesDataList>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"traces-list-view.es.js","names":["_Fragment"],"sources":["../../../../src/domains/traces/components/traces-list-view.tsx"],"sourcesContent":["import { useVirtualizer } from '@tanstack/react-virtual';\nimport { ListFilterIcon } from 'lucide-react';\nimport { useRef } from 'react';\nimport {\n DEFAULT_TRACE_COLUMN_PREFERENCES,\n TRACE_CUSTOM_COLUMN_LABELS,\n buildTraceListColumnKeys,\n buildTraceListColumns,\n formatTraceMetadataValue,\n hasTraceColumn,\n} from '../trace-list-columns';\nimport type { TraceColumnPreferences, TraceCustomColumn, TraceUsageSummary } from '../trace-list-columns';\nimport { getInputPreview, getSpanDurationMs } from '../utils/span-utils';\nimport { TraceErrorCell } from './trace-error-cell';\nimport { DataList, DataListSkeletonRows, TracesDataList, useDataListKeyboard } from '@/ds/components/DataList';\nimport type { DataListSort } from '@/ds/components/DataList';\nimport { splitColumns } from '@/ds/components/DataList/shared';\nimport { DropdownMenu } from '@/ds/components/DropdownMenu';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/ds/components/Tooltip';\nimport { Txt } from '@/ds/components/Txt/Txt';\nimport { focusRing } from '@/ds/primitives/transitions';\nimport { formatCompactNumber, formatCost } from '@/lib/cost';\nimport { cn } from '@/lib/utils';\nimport { formatDuration } from '@/utils/duration';\n\nexport type TracesListViewTrace = {\n traceId: string;\n /** Required for branch rows; absent on plain trace rows (which are root-rooted). */\n spanId?: string | null;\n /** `null`/missing → root span. Drives the Kind column's icon (top-level trace vs nested branch). */\n parentSpanId?: string | null;\n name: string;\n entityType?: string | null;\n entityId?: string | null;\n entityName?: string | null;\n threadId?: string | null;\n resourceId?: string | null;\n environment?: string | null;\n /** Model and provider of a model span; only span rows carry them. */\n model?: string | null;\n provider?: string | null;\n status?: string | null;\n /** Server-rendered preview of `input`. Present on lightweight rows, which omit `input` itself. */\n inputPreview?: string | null;\n input?: unknown;\n /** Server-rendered preview of the root span's output. */\n outputPreview?: string;\n /** Server-rendered preview of the root span's error. Shown in place of the output when `status` is `'error'`. */\n errorPreview?: string;\n metadata?: Record<string, unknown> | null;\n startedAt?: Date | string | null;\n endedAt?: Date | string | null;\n /** The root span's time to first chunk; `null` when it never streamed one. */\n timeToFirstChunkMs?: number | null;\n /** Thread rows only: every trace in the thread, regardless of the listed time range. */\n traceCount?: number;\n createdAt: Date | string;\n};\n\nconst ROW_HEIGHT = 36;\nconst OVERSCAN = 8;\n/** Distinct values offered in a custom column's \"filter by value\" header menu. */\nconst MAX_FILTER_VALUES = 20;\n\nfunction customColumnValue(trace: TracesListViewTrace, field: TraceCustomColumn): string | null | undefined {\n return trace[field];\n}\n\nfunction distinctCustomColumnValues(traces: TracesListViewTrace[], field: TraceCustomColumn): string[] {\n const values = new Set<string>();\n for (const trace of traces) {\n const value = trace[field];\n if (typeof value === 'string' && value) values.add(value);\n if (values.size >= MAX_FILTER_VALUES) break;\n }\n return [...values];\n}\n\nfunction sumTokens(usage: TraceUsageSummary | undefined): number | undefined {\n if (usage?.inputTokens === undefined && usage?.outputTokens === undefined) return undefined;\n return (usage?.inputTokens ?? 0) + (usage?.outputTokens ?? 0);\n}\n\ntype FailedTrace = TracesListViewTrace & { spanId: string; errorPreview: string };\n\n/** A failed row whose error preview can open the full error from its span. */\nfunction isFailedTrace(trace: TracesListViewTrace): trace is FailedTrace {\n return trace.status === 'error' && !!trace.errorPreview && !!trace.spanId;\n}\n\n/** The TTFC abbreviation, spelled out on hover; the sort button already names the column for screen readers. */\nfunction TimeToFirstChunkLabel() {\n return (\n <Tooltip>\n <TooltipTrigger render={<span />}>TTFC</TooltipTrigger>\n <TooltipContent>Time to first chunk</TooltipContent>\n </Tooltip>\n );\n}\n\nexport type TracesListViewProps = {\n traces: TracesListViewTrace[];\n isLoading?: boolean;\n isFetchingNextPage?: boolean;\n hasNextPage?: boolean;\n setEndOfListElement?: (element: HTMLDivElement | null) => void;\n filtersApplied?: boolean;\n /** What the rows hold, named in the empty messages. Defaults to `traces`. */\n resource?: 'traces' | 'spans' | 'threads';\n /** Currently featured/selected trace — its row gets the highlighted background. */\n featuredTraceId?: string | null;\n /**\n * Required in branches mode to disambiguate rows sharing a `traceId`. When set,\n * a row is featured only when both `traceId` and `spanId` match.\n */\n featuredSpanId?: string | null;\n /** Branches mode mixes root traces with subtraces — enables the Trace/Subtrace tooltip on the\n * level icon in the Name column, which is meaningless when every row is a root. */\n isBranchesMode?: boolean;\n /** Keys (`traceId:spanId`) of rows that just arrived via delta polling. Rows whose key is in\n * this set get a temporary tint to distinguish them from rows present since the last page-mode\n * fetch. Auto-expires upstream (in useTraces) after a short window. */\n recentlyAddedKeys?: Set<string>;\n /** Optional and metadata columns selected for this project. */\n columnPreferences?: TraceColumnPreferences;\n /** Token and estimated-cost totals, aggregated across model spans by trace ID. */\n usageByTraceId?: ReadonlyMap<string, TraceUsageSummary>;\n /** Called when a row is clicked. The current selection logic (toggle on same id) is the consumer's call. */\n onTraceClick: (trace: TracesListViewTrace) => void;\n /** Current sort of the Created column. When `onSortChange` is provided the header becomes sortable. */\n createdSort?: DataListSort;\n onSortChange?: (direction: DataListSort, key: 'startedAt') => void;\n /** Current sort of the TTFC column. When `onTimeToFirstChunkSortChange` is provided the header becomes sortable. */\n timeToFirstChunkSort?: DataListSort;\n onTimeToFirstChunkSortChange?: (direction: DataListSort) => void;\n /** When provided, custom column headers offer an `is <value>` filter for every value currently listed. */\n onFilterByField?: (field: TraceCustomColumn, value: string) => void;\n /** Storage id for the persisted column order. Use a distinct id per page so each keeps its own order. */\n listId?: string;\n};\n\n/**\n * Virtualized presentational list. Renders only the visible window via TanStack Virtual, and\n * uses DataList primitives for layout (CSS Grid with subgrid rows).\n */\nexport function TracesListView({\n traces,\n isLoading,\n isFetchingNextPage,\n hasNextPage,\n setEndOfListElement,\n filtersApplied,\n resource = 'traces',\n featuredTraceId,\n featuredSpanId,\n isBranchesMode,\n recentlyAddedKeys,\n columnPreferences = DEFAULT_TRACE_COLUMN_PREFERENCES,\n usageByTraceId,\n onTraceClick,\n createdSort,\n onSortChange,\n timeToFirstChunkSort,\n onTimeToFirstChunkSortChange,\n onFilterByField,\n listId = 'all-traces',\n}: TracesListViewProps) {\n const scrollRef = useRef<HTMLDivElement | null>(null);\n const columns = buildTraceListColumns(columnPreferences);\n const columnKeys = buildTraceListColumnKeys(columnPreferences);\n\n const virtualizer = useVirtualizer({\n count: traces.length,\n getScrollElement: () => scrollRef.current,\n estimateSize: () => ROW_HEIGHT,\n overscan: OVERSCAN,\n });\n\n const { getRowProps } = useDataListKeyboard({\n count: traces.length,\n containerRef: scrollRef,\n onNavigate: index => virtualizer.scrollToIndex(index),\n global: true,\n });\n\n const virtualItems = virtualizer.getVirtualItems();\n const totalSize = virtualizer.getTotalSize();\n const paddingTop = virtualItems[0]?.start ?? 0;\n const paddingBottom =\n virtualItems.length > 0 ? Math.max(0, totalSize - (virtualItems[virtualItems.length - 1]?.end ?? 0)) : 0;\n\n return (\n <TracesDataList\n reorderable\n id={listId}\n columns={columns}\n columnKeys={columnKeys}\n fit=\"container\"\n scrollRef={scrollRef}\n className=\"min-w-0\"\n >\n <TracesDataList.Top>\n {onSortChange ? (\n <TracesDataList.SortableTopCell sortKey=\"startedAt\" sort={createdSort} onSortChange={onSortChange}>\n Start\n </TracesDataList.SortableTopCell>\n ) : (\n <TracesDataList.TopCell>Start</TracesDataList.TopCell>\n )}\n {hasTraceColumn(columnPreferences, 'type') && <TracesDataList.TopCell>Primitive type</TracesDataList.TopCell>}\n <TracesDataList.TopCell>Primitive name</TracesDataList.TopCell>\n {hasTraceColumn(columnPreferences, 'input') && <TracesDataList.TopCell>Input</TracesDataList.TopCell>}\n {hasTraceColumn(columnPreferences, 'output') && <TracesDataList.TopCell>Output</TracesDataList.TopCell>}\n <TracesDataList.TopCell>Status</TracesDataList.TopCell>\n {hasTraceColumn(columnPreferences, 'duration') && (\n <TracesDataList.TopCell className=\"justify-end text-right\">Duration</TracesDataList.TopCell>\n )}\n {hasTraceColumn(columnPreferences, 'traceCount') && (\n <TracesDataList.TopCellWithTooltip\n tooltip=\"Messages sent in this thread, counting the whole thread, not just the selected time range\"\n className=\"justify-end text-right\"\n >\n Messages\n </TracesDataList.TopCellWithTooltip>\n )}\n {hasTraceColumn(columnPreferences, 'timeToFirstChunk') &&\n (onTimeToFirstChunkSortChange ? (\n <TracesDataList.SortableTopCell\n sortKey=\"timeToFirstChunkMs\"\n sort={timeToFirstChunkSort}\n onSortChange={onTimeToFirstChunkSortChange}\n label=\"Time to first chunk\"\n align=\"end\"\n >\n <TimeToFirstChunkLabel />\n </TracesDataList.SortableTopCell>\n ) : (\n <TracesDataList.TopCellWithTooltip tooltip=\"Time to first chunk\" className=\"justify-end text-right\">\n TTFC\n </TracesDataList.TopCellWithTooltip>\n ))}\n {hasTraceColumn(columnPreferences, 'endTime') && <TracesDataList.TopCell>End</TracesDataList.TopCell>}\n {hasTraceColumn(columnPreferences, 'environment') && (\n <TracesDataList.TopCell>Environment</TracesDataList.TopCell>\n )}\n {hasTraceColumn(columnPreferences, 'model') && <TracesDataList.TopCell>Model</TracesDataList.TopCell>}\n {hasTraceColumn(columnPreferences, 'provider') && <TracesDataList.TopCell>Provider</TracesDataList.TopCell>}\n {hasTraceColumn(columnPreferences, 'inputTokens') && (\n <TracesDataList.TopCell className=\"justify-end text-right\">Input tokens</TracesDataList.TopCell>\n )}\n {hasTraceColumn(columnPreferences, 'outputTokens') && (\n <TracesDataList.TopCell className=\"justify-end text-right\">Output tokens</TracesDataList.TopCell>\n )}\n {hasTraceColumn(columnPreferences, 'totalTokens') && (\n <TracesDataList.TopCell className=\"justify-end text-right\">Total tokens</TracesDataList.TopCell>\n )}\n {hasTraceColumn(columnPreferences, 'estimatedCost') && (\n <TracesDataList.TopCell className=\"justify-end text-right\">Est. cost</TracesDataList.TopCell>\n )}\n {columnPreferences.customColumns.map(field => {\n const label = TRACE_CUSTOM_COLUMN_LABELS[field];\n const filterValues = onFilterByField ? distinctCustomColumnValues(traces, field) : [];\n if (!onFilterByField || filterValues.length === 0) {\n return <TracesDataList.TopCell key={field}>{label}</TracesDataList.TopCell>;\n }\n return (\n <TracesDataList.TopCell key={field} className=\"overflow-visible\">\n <DropdownMenu>\n <DropdownMenu.Trigger\n render={\n <button\n type=\"button\"\n className={cn('flex min-w-0 items-center gap-1 rounded-sm hover:text-foreground', focusRing)}\n >\n <span className=\"min-w-0 truncate\">{label}</span>\n <ListFilterIcon aria-hidden className=\"size-[1.2em] shrink-0\" />\n </button>\n }\n />\n <DropdownMenu.Content align=\"start\">\n <DropdownMenu.Label>Filter by value</DropdownMenu.Label>\n {filterValues.map(value => (\n <DropdownMenu.Item key={value} onSelect={() => onFilterByField(field, value)}>\n <Txt as=\"span\" variant=\"body-sm\" font=\"mono\" className=\"min-w-0 truncate\">\n {value}\n </Txt>\n </DropdownMenu.Item>\n ))}\n </DropdownMenu.Content>\n </DropdownMenu>\n </TracesDataList.TopCell>\n );\n })}\n {columnPreferences.metadataKeys.map(key => (\n <TracesDataList.TopCellWithTooltip key={key} tooltip={key}>\n {key}\n </TracesDataList.TopCellWithTooltip>\n ))}\n </TracesDataList.Top>\n\n {isLoading ? (\n <DataListSkeletonRows columnCount={splitColumns(columns).length} />\n ) : traces.length === 0 ? (\n <TracesDataList.NoMatch\n message={filtersApplied ? `No ${resource} found for applied filters` : `No ${resource} found yet`}\n />\n ) : (\n <>\n <TracesDataList.Spacer height={paddingTop} />\n {virtualItems.map(vi => {\n const trace = traces[vi.index];\n if (!trace) return null;\n\n const isFeatured =\n trace.traceId === featuredTraceId && (featuredSpanId == null || trace.spanId === featuredSpanId);\n const rowKey = `${trace.traceId}:${trace.spanId ?? ''}`;\n const isRecentlyAdded = recentlyAddedKeys?.has(rowKey) ?? false;\n const displayDate = trace.startedAt ?? trace.createdAt;\n const usage = usageByTraceId?.get(trace.traceId);\n\n return (\n <TracesDataList.RowButton\n key={rowKey}\n ref={virtualizer.measureElement}\n data-index={vi.index}\n {...getRowProps(vi.index)}\n onClick={() => onTraceClick(trace)}\n featured={isFeatured}\n className={cn(isRecentlyAdded && 'animate-row-highlight')}\n >\n <TracesDataList.CreatedCell timestamp={displayDate} preset=\"day-time-seconds\" />\n {hasTraceColumn(columnPreferences, 'type') && <TracesDataList.TypeCell entityType={trace.entityType} />}\n <TracesDataList.NameCell\n name={trace.entityName || trace.name}\n parentSpanId={trace.parentSpanId}\n showLevelTooltip={isBranchesMode}\n />\n {hasTraceColumn(columnPreferences, 'input') && (\n <TracesDataList.InputCell input={trace.inputPreview ?? getInputPreview(trace.input)} />\n )}\n {hasTraceColumn(columnPreferences, 'output') &&\n (isFailedTrace(trace) ? (\n <TraceErrorCell traceId={trace.traceId} spanId={trace.spanId} errorPreview={trace.errorPreview} />\n ) : (\n <TracesDataList.OutputCell\n output={trace.outputPreview}\n error={trace.errorPreview}\n status={trace.status}\n />\n ))}\n <TracesDataList.StatusCell status={trace.status} />\n {hasTraceColumn(columnPreferences, 'duration') && (\n <DataList.NumberCell font=\"mono\">\n {formatDuration(getSpanDurationMs(trace.startedAt, trace.endedAt))}\n </DataList.NumberCell>\n )}\n {hasTraceColumn(columnPreferences, 'traceCount') && (\n <DataList.NumberCell>\n {trace.traceCount === undefined ? undefined : formatCompactNumber(trace.traceCount)}\n </DataList.NumberCell>\n )}\n {hasTraceColumn(columnPreferences, 'timeToFirstChunk') && (\n <DataList.NumberCell font=\"mono\">{formatDuration(trace.timeToFirstChunkMs)}</DataList.NumberCell>\n )}\n {hasTraceColumn(columnPreferences, 'endTime') && (\n <TracesDataList.CreatedCell timestamp={trace.endedAt ?? ''} preset=\"day-time-seconds\" />\n )}\n {hasTraceColumn(columnPreferences, 'environment') && (\n <DataList.TextCell>{trace.environment || '—'}</DataList.TextCell>\n )}\n {hasTraceColumn(columnPreferences, 'model') && (\n <DataList.TextCell>{trace.model || '—'}</DataList.TextCell>\n )}\n {hasTraceColumn(columnPreferences, 'provider') && (\n <DataList.TextCell>{trace.provider || '—'}</DataList.TextCell>\n )}\n {hasTraceColumn(columnPreferences, 'inputTokens') && (\n <DataList.NumberCell>\n {usage?.inputTokens === undefined ? undefined : formatCompactNumber(usage.inputTokens)}\n </DataList.NumberCell>\n )}\n {hasTraceColumn(columnPreferences, 'outputTokens') && (\n <DataList.NumberCell>\n {usage?.outputTokens === undefined ? undefined : formatCompactNumber(usage.outputTokens)}\n </DataList.NumberCell>\n )}\n {hasTraceColumn(columnPreferences, 'totalTokens') && (\n <DataList.NumberCell>\n {(() => {\n const total = sumTokens(usage);\n return total === undefined ? undefined : formatCompactNumber(total);\n })()}\n </DataList.NumberCell>\n )}\n {hasTraceColumn(columnPreferences, 'estimatedCost') && (\n <DataList.NumberCell>\n {usage?.estimatedCost === undefined ? undefined : formatCost(usage.estimatedCost, usage.costUnit)}\n </DataList.NumberCell>\n )}\n {columnPreferences.customColumns.map(field => (\n <DataList.TextCell font=\"mono\" key={field}>\n {customColumnValue(trace, field) ?? undefined}\n </DataList.TextCell>\n ))}\n {columnPreferences.metadataKeys.map(key => {\n const value = formatTraceMetadataValue(trace.metadata, key);\n return (\n <DataList.TextCell font=\"mono\" key={key}>\n {value}\n </DataList.TextCell>\n );\n })}\n </TracesDataList.RowButton>\n );\n })}\n <TracesDataList.Spacer height={paddingBottom} />\n <TracesDataList.NextPageLoading\n isLoading={isFetchingNextPage}\n hasMore={hasNextPage}\n setEndOfListElement={setEndOfListElement}\n />\n </>\n )}\n </TracesDataList>\n );\n}\n"],"mappings":"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"}
@@ -5,6 +5,7 @@ var TRACE_OPTIONAL_COLUMNS = [
5
5
  "input",
6
6
  "output",
7
7
  "duration",
8
+ "traceCount",
8
9
  "timeToFirstChunk",
9
10
  "endTime",
10
11
  "environment",
@@ -45,6 +46,11 @@ var DEFAULT_TRACE_COLUMN_PREFERENCES = {
45
46
  customColumns: [],
46
47
  metadataKeys: []
47
48
  };
49
+ /** The Threads list: the trace defaults plus each thread's trace count. Not offered in any column picker. */
50
+ var THREAD_LIST_COLUMN_PREFERENCES = {
51
+ ...DEFAULT_TRACE_COLUMN_PREFERENCES,
52
+ visibleColumns: [...DEFAULT_TRACE_COLUMN_PREFERENCES.visibleColumns, "traceCount"]
53
+ };
48
54
  var TRACE_COLUMN_CATALOGS = {
49
55
  traces: {
50
56
  standardColumns: [
@@ -146,6 +152,7 @@ function buildTraceListColumnKeys(preferences) {
146
152
  keys.push("status");
147
153
  for (const column of [
148
154
  "duration",
155
+ "traceCount",
149
156
  "timeToFirstChunk",
150
157
  "endTime",
151
158
  "environment",
@@ -167,6 +174,7 @@ function buildTraceListColumns(preferences) {
167
174
  if (visible.has("output")) columns.push("minmax(8rem,1fr)");
168
175
  columns.push("6rem");
169
176
  if (visible.has("duration")) columns.push("7rem");
177
+ if (visible.has("traceCount")) columns.push("6rem");
170
178
  if (visible.has("timeToFirstChunk")) columns.push("7rem");
171
179
  if (visible.has("endTime")) columns.push("11rem");
172
180
  if (visible.has("environment")) columns.push("8rem");
@@ -242,6 +250,7 @@ function isTraceUsageColumn(column) {
242
250
  return TRACE_USAGE_COLUMN_SET.has(column);
243
251
  }
244
252
  exports.DEFAULT_TRACE_COLUMN_PREFERENCES = DEFAULT_TRACE_COLUMN_PREFERENCES;
253
+ exports.THREAD_LIST_COLUMN_PREFERENCES = THREAD_LIST_COLUMN_PREFERENCES;
245
254
  exports.TRACE_COLUMN_CATALOGS = TRACE_COLUMN_CATALOGS;
246
255
  exports.TRACE_CUSTOM_COLUMN_FIELDS = TRACE_CUSTOM_COLUMN_FIELDS;
247
256
  exports.TRACE_CUSTOM_COLUMN_LABELS = TRACE_CUSTOM_COLUMN_LABELS;
@@ -1 +1 @@
1
- {"version":3,"file":"trace-list-columns.cjs.js","names":[],"sources":["../../../src/domains/traces/trace-list-columns.ts"],"sourcesContent":["export const TRACE_OPTIONAL_COLUMNS = [\n 'type',\n 'input',\n 'output',\n 'duration',\n 'timeToFirstChunk',\n 'endTime',\n 'environment',\n 'model',\n 'provider',\n 'inputTokens',\n 'outputTokens',\n 'totalTokens',\n 'estimatedCost',\n] as const;\n\nexport type TraceOptionalColumn = (typeof TRACE_OPTIONAL_COLUMNS)[number];\n\nexport const TRACE_USAGE_COLUMNS = [\n 'inputTokens',\n 'outputTokens',\n 'totalTokens',\n 'estimatedCost',\n] as const satisfies readonly TraceOptionalColumn[];\n\n/** Trace properties that are not regular columns but can be pinned as a custom column. */\nexport const TRACE_CUSTOM_COLUMN_FIELDS = ['traceId', 'threadId', 'resourceId', 'entityId'] as const;\n\nexport type TraceCustomColumn = (typeof TRACE_CUSTOM_COLUMN_FIELDS)[number];\n\nexport const TRACE_CUSTOM_COLUMN_LABELS: Record<TraceCustomColumn, string> = {\n traceId: 'Trace ID',\n threadId: 'Thread ID',\n resourceId: 'Resource ID',\n entityId: 'Primitive ID',\n};\n\nexport type TraceColumnPreferences = {\n readonly visibleColumns: readonly TraceOptionalColumn[];\n readonly customColumns: readonly TraceCustomColumn[];\n readonly metadataKeys: readonly string[];\n};\n\nimport type { TraceUsageSummary } from '@mastra/react/hooks/traces';\nexport type { TraceUsageSummary };\n\nexport const DEFAULT_TRACE_COLUMN_PREFERENCES: TraceColumnPreferences = {\n visibleColumns: ['type', 'input', 'output', 'duration', 'estimatedCost'],\n customColumns: [],\n metadataKeys: [],\n};\n\n/** A list a column selection belongs to. Each list only offers the columns its rows carry. */\nexport type TraceColumnScope = 'traces' | 'spans';\n\nexport type TraceColumnCatalog = {\n /** Plain columns offered in the picker, in menu order. */\n readonly standardColumns: readonly TraceOptionalColumn[];\n /** Whether rows carry token and cost usage. */\n readonly usage: boolean;\n /** Whether rows carry metadata that can be shown as columns. */\n readonly metadata: boolean;\n readonly defaults: TraceColumnPreferences;\n};\n\nexport const TRACE_COLUMN_CATALOGS: Record<TraceColumnScope, TraceColumnCatalog> = {\n traces: {\n standardColumns: ['type', 'input', 'output', 'duration', 'timeToFirstChunk', 'endTime', 'environment'],\n usage: true,\n metadata: true,\n defaults: DEFAULT_TRACE_COLUMN_PREFERENCES,\n },\n spans: {\n standardColumns: ['type', 'input', 'output', 'duration', 'endTime', 'environment', 'model', 'provider'],\n usage: false,\n metadata: false,\n defaults: { visibleColumns: ['type', 'input', 'output', 'duration'], customColumns: [], metadataKeys: [] },\n },\n};\n\n// v2: 'entity' became 'type' and moved before Name; duration + cost joined the defaults.\n// v3: added `customColumns`; a v2 payload is migrated rather than reset.\n// v4: added 'output', shown after 'input' for anyone who had Input visible.\nconst TRACE_COLUMN_PREFERENCES_VERSION = 4;\nconst TRACE_COLUMN_PREFERENCES_MIGRATABLE_VERSIONS = new Set<unknown>([2, 3, TRACE_COLUMN_PREFERENCES_VERSION]);\nconst TRACE_COLUMN_SET = new Set<string>(TRACE_OPTIONAL_COLUMNS);\nconst TRACE_USAGE_COLUMN_SET = new Set<TraceOptionalColumn>(TRACE_USAGE_COLUMNS);\nconst TRACE_CUSTOM_COLUMN_SET = new Set<string>(TRACE_CUSTOM_COLUMN_FIELDS);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isTraceOptionalColumn(value: unknown): value is TraceOptionalColumn {\n return typeof value === 'string' && TRACE_COLUMN_SET.has(value);\n}\n\nexport function isTraceCustomColumn(value: unknown): value is TraceCustomColumn {\n return typeof value === 'string' && TRACE_CUSTOM_COLUMN_SET.has(value);\n}\n\nfunction uniqueMetadataKeys(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n\n const keys = value\n .filter(key => typeof key === 'string')\n .map(key => key.trim())\n .filter(Boolean);\n\n return [...new Set(keys)];\n}\n\nexport function parseTraceColumnPreferences(\n serialized: string | undefined,\n defaults: TraceColumnPreferences = DEFAULT_TRACE_COLUMN_PREFERENCES,\n): TraceColumnPreferences {\n if (!serialized) return defaults;\n\n try {\n const parsed: unknown = JSON.parse(serialized);\n if (!isRecord(parsed) || !TRACE_COLUMN_PREFERENCES_MIGRATABLE_VERSIONS.has(parsed.version)) {\n return defaults;\n }\n\n const visibleColumns = Array.isArray(parsed.visibleColumns)\n ? [...new Set(parsed.visibleColumns.filter(isTraceOptionalColumn))]\n : [...defaults.visibleColumns];\n if (parsed.version !== TRACE_COLUMN_PREFERENCES_VERSION && !visibleColumns.includes('output')) {\n const input = visibleColumns.indexOf('input');\n if (input !== -1) visibleColumns.splice(input + 1, 0, 'output');\n }\n const customColumns = Array.isArray(parsed.customColumns)\n ? [...new Set(parsed.customColumns.filter(isTraceCustomColumn))]\n : [];\n\n return {\n visibleColumns,\n customColumns,\n metadataKeys: uniqueMetadataKeys(parsed.metadataKeys),\n };\n } catch {\n return defaults;\n }\n}\n\nexport function serializeTraceColumnPreferences(preferences: TraceColumnPreferences): string {\n return JSON.stringify({\n version: TRACE_COLUMN_PREFERENCES_VERSION,\n visibleColumns: preferences.visibleColumns,\n customColumns: preferences.customColumns,\n metadataKeys: preferences.metadataKeys,\n });\n}\n\n/** Stable key per column of `buildTraceListColumns`, in the same order. Used to persist the column order. */\nexport function buildTraceListColumnKeys(preferences: TraceColumnPreferences): string[] {\n const visible = new Set(preferences.visibleColumns);\n const keys = ['startTime'];\n if (visible.has('type')) keys.push('type');\n keys.push('name');\n if (visible.has('input')) keys.push('input');\n if (visible.has('output')) keys.push('output');\n keys.push('status');\n for (const column of [\n 'duration',\n 'timeToFirstChunk',\n 'endTime',\n 'environment',\n 'model',\n 'provider',\n ...TRACE_USAGE_COLUMNS,\n ] as const) {\n if (visible.has(column)) keys.push(column);\n }\n keys.push(...preferences.customColumns.map(field => `custom:${field}`));\n keys.push(...preferences.metadataKeys.map(key => `metadata:${key}`));\n return keys;\n}\n\nexport function buildTraceListColumns(preferences: TraceColumnPreferences): string {\n const visible = new Set(preferences.visibleColumns);\n // Name is bounded when Input or Output is visible so they (1fr each) absorb the free space;\n // without either, Name is the flexible track that fills the grid.\n const columns = ['11rem'];\n const hasPreview = visible.has('input') || visible.has('output');\n\n if (visible.has('type')) columns.push('7rem');\n columns.push(hasPreview ? '14rem' : 'minmax(8rem,1fr)');\n if (visible.has('input')) columns.push('minmax(8rem,1fr)');\n if (visible.has('output')) columns.push('minmax(8rem,1fr)');\n\n columns.push('6rem');\n\n if (visible.has('duration')) columns.push('7rem');\n if (visible.has('timeToFirstChunk')) columns.push('7rem');\n if (visible.has('endTime')) columns.push('11rem');\n if (visible.has('environment')) columns.push('8rem');\n if (visible.has('model')) columns.push('10rem');\n if (visible.has('provider')) columns.push('8rem');\n if (visible.has('inputTokens')) columns.push('8rem');\n if (visible.has('outputTokens')) columns.push('8rem');\n if (visible.has('totalTokens')) columns.push('8rem');\n if (visible.has('estimatedCost')) columns.push('8rem');\n\n for (const _field of preferences.customColumns) {\n columns.push('minmax(8rem,14rem)');\n }\n\n for (const _key of preferences.metadataKeys) {\n columns.push('minmax(8rem,14rem)');\n }\n\n return columns.join(' ');\n}\n\nconst RUN_PREFIX_PATTERN = /^(?:agent|workflow|scorer) run: '(.+?)'(.*)$/;\n\n/** Core names root spans `agent run: 'id'` (+ optional ` (resumed)`); the Primitive type column already carries\n * the kind, so the list shows just the id and any suffix. Core names are untouched for exporters. */\nexport function displayTraceName<T extends string | null | undefined>(name: T): T {\n if (!name) return name;\n return name.replace(RUN_PREFIX_PATTERN, '$1$2') as T;\n}\n\nexport function formatTraceMetadataValue(\n metadata: Record<string, unknown> | null | undefined,\n key: string,\n): string | undefined {\n if (!metadata || !Object.prototype.hasOwnProperty.call(metadata, key)) return undefined;\n const value = metadata[key];\n if (value == null) return undefined;\n\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') return String(value);\n\n try {\n return JSON.stringify(value) ?? undefined;\n } catch {\n return undefined;\n }\n}\n\nexport function hasTraceColumn(preferences: TraceColumnPreferences, column: TraceOptionalColumn): boolean {\n return preferences.visibleColumns.includes(column);\n}\n\nexport function toggleTraceColumn(\n preferences: TraceColumnPreferences,\n column: TraceOptionalColumn,\n): TraceColumnPreferences {\n return {\n ...preferences,\n visibleColumns: preferences.visibleColumns.includes(column)\n ? preferences.visibleColumns.filter(visibleColumn => visibleColumn !== column)\n : [...preferences.visibleColumns, column],\n };\n}\n\nexport function addTraceCustomColumn(\n preferences: TraceColumnPreferences,\n field: TraceCustomColumn,\n): TraceColumnPreferences {\n if (preferences.customColumns.includes(field)) return preferences;\n return { ...preferences, customColumns: [...preferences.customColumns, field] };\n}\n\nexport function removeTraceCustomColumn(\n preferences: TraceColumnPreferences,\n field: TraceCustomColumn,\n): TraceColumnPreferences {\n return { ...preferences, customColumns: preferences.customColumns.filter(customColumn => customColumn !== field) };\n}\n\nexport function addTraceMetadataColumn(preferences: TraceColumnPreferences, key: string): TraceColumnPreferences {\n const normalizedKey = key.trim();\n if (!normalizedKey || preferences.metadataKeys.includes(normalizedKey)) return preferences;\n return { ...preferences, metadataKeys: [...preferences.metadataKeys, normalizedKey] };\n}\n\nexport function removeTraceMetadataColumn(preferences: TraceColumnPreferences, key: string): TraceColumnPreferences {\n return { ...preferences, metadataKeys: preferences.metadataKeys.filter(metadataKey => metadataKey !== key) };\n}\n\nexport function hasTraceUsageColumn(preferences: TraceColumnPreferences): boolean {\n return preferences.visibleColumns.some(isTraceUsageColumn);\n}\n\nexport function isTraceUsageColumn(column: TraceOptionalColumn): boolean {\n return TRACE_USAGE_COLUMN_SET.has(column);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"trace-list-columns.cjs.js","names":[],"sources":["../../../src/domains/traces/trace-list-columns.ts"],"sourcesContent":["export const TRACE_OPTIONAL_COLUMNS = [\n 'type',\n 'input',\n 'output',\n 'duration',\n 'traceCount',\n 'timeToFirstChunk',\n 'endTime',\n 'environment',\n 'model',\n 'provider',\n 'inputTokens',\n 'outputTokens',\n 'totalTokens',\n 'estimatedCost',\n] as const;\n\nexport type TraceOptionalColumn = (typeof TRACE_OPTIONAL_COLUMNS)[number];\n\nexport const TRACE_USAGE_COLUMNS = [\n 'inputTokens',\n 'outputTokens',\n 'totalTokens',\n 'estimatedCost',\n] as const satisfies readonly TraceOptionalColumn[];\n\n/** Trace properties that are not regular columns but can be pinned as a custom column. */\nexport const TRACE_CUSTOM_COLUMN_FIELDS = ['traceId', 'threadId', 'resourceId', 'entityId'] as const;\n\nexport type TraceCustomColumn = (typeof TRACE_CUSTOM_COLUMN_FIELDS)[number];\n\nexport const TRACE_CUSTOM_COLUMN_LABELS: Record<TraceCustomColumn, string> = {\n traceId: 'Trace ID',\n threadId: 'Thread ID',\n resourceId: 'Resource ID',\n entityId: 'Primitive ID',\n};\n\nexport type TraceColumnPreferences = {\n readonly visibleColumns: readonly TraceOptionalColumn[];\n readonly customColumns: readonly TraceCustomColumn[];\n readonly metadataKeys: readonly string[];\n};\n\nimport type { TraceUsageSummary } from '@mastra/react/hooks/traces';\nexport type { TraceUsageSummary };\n\nexport const DEFAULT_TRACE_COLUMN_PREFERENCES: TraceColumnPreferences = {\n visibleColumns: ['type', 'input', 'output', 'duration', 'estimatedCost'],\n customColumns: [],\n metadataKeys: [],\n};\n\n/** The Threads list: the trace defaults plus each thread's trace count. Not offered in any column picker. */\nexport const THREAD_LIST_COLUMN_PREFERENCES: TraceColumnPreferences = {\n ...DEFAULT_TRACE_COLUMN_PREFERENCES,\n visibleColumns: [...DEFAULT_TRACE_COLUMN_PREFERENCES.visibleColumns, 'traceCount'],\n};\n\n/** A list a column selection belongs to. Each list only offers the columns its rows carry. */\nexport type TraceColumnScope = 'traces' | 'spans';\n\nexport type TraceColumnCatalog = {\n /** Plain columns offered in the picker, in menu order. */\n readonly standardColumns: readonly TraceOptionalColumn[];\n /** Whether rows carry token and cost usage. */\n readonly usage: boolean;\n /** Whether rows carry metadata that can be shown as columns. */\n readonly metadata: boolean;\n readonly defaults: TraceColumnPreferences;\n};\n\nexport const TRACE_COLUMN_CATALOGS: Record<TraceColumnScope, TraceColumnCatalog> = {\n traces: {\n standardColumns: ['type', 'input', 'output', 'duration', 'timeToFirstChunk', 'endTime', 'environment'],\n usage: true,\n metadata: true,\n defaults: DEFAULT_TRACE_COLUMN_PREFERENCES,\n },\n spans: {\n standardColumns: ['type', 'input', 'output', 'duration', 'endTime', 'environment', 'model', 'provider'],\n usage: false,\n metadata: false,\n defaults: { visibleColumns: ['type', 'input', 'output', 'duration'], customColumns: [], metadataKeys: [] },\n },\n};\n\n// v2: 'entity' became 'type' and moved before Name; duration + cost joined the defaults.\n// v3: added `customColumns`; a v2 payload is migrated rather than reset.\n// v4: added 'output', shown after 'input' for anyone who had Input visible.\nconst TRACE_COLUMN_PREFERENCES_VERSION = 4;\nconst TRACE_COLUMN_PREFERENCES_MIGRATABLE_VERSIONS = new Set<unknown>([2, 3, TRACE_COLUMN_PREFERENCES_VERSION]);\nconst TRACE_COLUMN_SET = new Set<string>(TRACE_OPTIONAL_COLUMNS);\nconst TRACE_USAGE_COLUMN_SET = new Set<TraceOptionalColumn>(TRACE_USAGE_COLUMNS);\nconst TRACE_CUSTOM_COLUMN_SET = new Set<string>(TRACE_CUSTOM_COLUMN_FIELDS);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isTraceOptionalColumn(value: unknown): value is TraceOptionalColumn {\n return typeof value === 'string' && TRACE_COLUMN_SET.has(value);\n}\n\nexport function isTraceCustomColumn(value: unknown): value is TraceCustomColumn {\n return typeof value === 'string' && TRACE_CUSTOM_COLUMN_SET.has(value);\n}\n\nfunction uniqueMetadataKeys(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n\n const keys = value\n .filter(key => typeof key === 'string')\n .map(key => key.trim())\n .filter(Boolean);\n\n return [...new Set(keys)];\n}\n\nexport function parseTraceColumnPreferences(\n serialized: string | undefined,\n defaults: TraceColumnPreferences = DEFAULT_TRACE_COLUMN_PREFERENCES,\n): TraceColumnPreferences {\n if (!serialized) return defaults;\n\n try {\n const parsed: unknown = JSON.parse(serialized);\n if (!isRecord(parsed) || !TRACE_COLUMN_PREFERENCES_MIGRATABLE_VERSIONS.has(parsed.version)) {\n return defaults;\n }\n\n const visibleColumns = Array.isArray(parsed.visibleColumns)\n ? [...new Set(parsed.visibleColumns.filter(isTraceOptionalColumn))]\n : [...defaults.visibleColumns];\n if (parsed.version !== TRACE_COLUMN_PREFERENCES_VERSION && !visibleColumns.includes('output')) {\n const input = visibleColumns.indexOf('input');\n if (input !== -1) visibleColumns.splice(input + 1, 0, 'output');\n }\n const customColumns = Array.isArray(parsed.customColumns)\n ? [...new Set(parsed.customColumns.filter(isTraceCustomColumn))]\n : [];\n\n return {\n visibleColumns,\n customColumns,\n metadataKeys: uniqueMetadataKeys(parsed.metadataKeys),\n };\n } catch {\n return defaults;\n }\n}\n\nexport function serializeTraceColumnPreferences(preferences: TraceColumnPreferences): string {\n return JSON.stringify({\n version: TRACE_COLUMN_PREFERENCES_VERSION,\n visibleColumns: preferences.visibleColumns,\n customColumns: preferences.customColumns,\n metadataKeys: preferences.metadataKeys,\n });\n}\n\n/** Stable key per column of `buildTraceListColumns`, in the same order. Used to persist the column order. */\nexport function buildTraceListColumnKeys(preferences: TraceColumnPreferences): string[] {\n const visible = new Set(preferences.visibleColumns);\n const keys = ['startTime'];\n if (visible.has('type')) keys.push('type');\n keys.push('name');\n if (visible.has('input')) keys.push('input');\n if (visible.has('output')) keys.push('output');\n keys.push('status');\n for (const column of [\n 'duration',\n 'traceCount',\n 'timeToFirstChunk',\n 'endTime',\n 'environment',\n 'model',\n 'provider',\n ...TRACE_USAGE_COLUMNS,\n ] as const) {\n if (visible.has(column)) keys.push(column);\n }\n keys.push(...preferences.customColumns.map(field => `custom:${field}`));\n keys.push(...preferences.metadataKeys.map(key => `metadata:${key}`));\n return keys;\n}\n\nexport function buildTraceListColumns(preferences: TraceColumnPreferences): string {\n const visible = new Set(preferences.visibleColumns);\n // Name is bounded when Input or Output is visible so they (1fr each) absorb the free space;\n // without either, Name is the flexible track that fills the grid.\n const columns = ['11rem'];\n const hasPreview = visible.has('input') || visible.has('output');\n\n if (visible.has('type')) columns.push('7rem');\n columns.push(hasPreview ? '14rem' : 'minmax(8rem,1fr)');\n if (visible.has('input')) columns.push('minmax(8rem,1fr)');\n if (visible.has('output')) columns.push('minmax(8rem,1fr)');\n\n columns.push('6rem');\n\n if (visible.has('duration')) columns.push('7rem');\n if (visible.has('traceCount')) columns.push('6rem');\n if (visible.has('timeToFirstChunk')) columns.push('7rem');\n if (visible.has('endTime')) columns.push('11rem');\n if (visible.has('environment')) columns.push('8rem');\n if (visible.has('model')) columns.push('10rem');\n if (visible.has('provider')) columns.push('8rem');\n if (visible.has('inputTokens')) columns.push('8rem');\n if (visible.has('outputTokens')) columns.push('8rem');\n if (visible.has('totalTokens')) columns.push('8rem');\n if (visible.has('estimatedCost')) columns.push('8rem');\n\n for (const _field of preferences.customColumns) {\n columns.push('minmax(8rem,14rem)');\n }\n\n for (const _key of preferences.metadataKeys) {\n columns.push('minmax(8rem,14rem)');\n }\n\n return columns.join(' ');\n}\n\nconst RUN_PREFIX_PATTERN = /^(?:agent|workflow|scorer) run: '(.+?)'(.*)$/;\n\n/** Core names root spans `agent run: 'id'` (+ optional ` (resumed)`); the Primitive type column already carries\n * the kind, so the list shows just the id and any suffix. Core names are untouched for exporters. */\nexport function displayTraceName<T extends string | null | undefined>(name: T): T {\n if (!name) return name;\n return name.replace(RUN_PREFIX_PATTERN, '$1$2') as T;\n}\n\nexport function formatTraceMetadataValue(\n metadata: Record<string, unknown> | null | undefined,\n key: string,\n): string | undefined {\n if (!metadata || !Object.prototype.hasOwnProperty.call(metadata, key)) return undefined;\n const value = metadata[key];\n if (value == null) return undefined;\n\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') return String(value);\n\n try {\n return JSON.stringify(value) ?? undefined;\n } catch {\n return undefined;\n }\n}\n\nexport function hasTraceColumn(preferences: TraceColumnPreferences, column: TraceOptionalColumn): boolean {\n return preferences.visibleColumns.includes(column);\n}\n\nexport function toggleTraceColumn(\n preferences: TraceColumnPreferences,\n column: TraceOptionalColumn,\n): TraceColumnPreferences {\n return {\n ...preferences,\n visibleColumns: preferences.visibleColumns.includes(column)\n ? preferences.visibleColumns.filter(visibleColumn => visibleColumn !== column)\n : [...preferences.visibleColumns, column],\n };\n}\n\nexport function addTraceCustomColumn(\n preferences: TraceColumnPreferences,\n field: TraceCustomColumn,\n): TraceColumnPreferences {\n if (preferences.customColumns.includes(field)) return preferences;\n return { ...preferences, customColumns: [...preferences.customColumns, field] };\n}\n\nexport function removeTraceCustomColumn(\n preferences: TraceColumnPreferences,\n field: TraceCustomColumn,\n): TraceColumnPreferences {\n return { ...preferences, customColumns: preferences.customColumns.filter(customColumn => customColumn !== field) };\n}\n\nexport function addTraceMetadataColumn(preferences: TraceColumnPreferences, key: string): TraceColumnPreferences {\n const normalizedKey = key.trim();\n if (!normalizedKey || preferences.metadataKeys.includes(normalizedKey)) return preferences;\n return { ...preferences, metadataKeys: [...preferences.metadataKeys, normalizedKey] };\n}\n\nexport function removeTraceMetadataColumn(preferences: TraceColumnPreferences, key: string): TraceColumnPreferences {\n return { ...preferences, metadataKeys: preferences.metadataKeys.filter(metadataKey => metadataKey !== key) };\n}\n\nexport function hasTraceUsageColumn(preferences: TraceColumnPreferences): boolean {\n return preferences.visibleColumns.some(isTraceUsageColumn);\n}\n\nexport function isTraceUsageColumn(column: TraceOptionalColumn): boolean {\n return TRACE_USAGE_COLUMN_SET.has(column);\n}\n"],"mappings":"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"}
@@ -4,6 +4,7 @@ var TRACE_OPTIONAL_COLUMNS = [
4
4
  "input",
5
5
  "output",
6
6
  "duration",
7
+ "traceCount",
7
8
  "timeToFirstChunk",
8
9
  "endTime",
9
10
  "environment",
@@ -44,6 +45,11 @@ var DEFAULT_TRACE_COLUMN_PREFERENCES = {
44
45
  customColumns: [],
45
46
  metadataKeys: []
46
47
  };
48
+ /** The Threads list: the trace defaults plus each thread's trace count. Not offered in any column picker. */
49
+ var THREAD_LIST_COLUMN_PREFERENCES = {
50
+ ...DEFAULT_TRACE_COLUMN_PREFERENCES,
51
+ visibleColumns: [...DEFAULT_TRACE_COLUMN_PREFERENCES.visibleColumns, "traceCount"]
52
+ };
47
53
  var TRACE_COLUMN_CATALOGS = {
48
54
  traces: {
49
55
  standardColumns: [
@@ -145,6 +151,7 @@ function buildTraceListColumnKeys(preferences) {
145
151
  keys.push("status");
146
152
  for (const column of [
147
153
  "duration",
154
+ "traceCount",
148
155
  "timeToFirstChunk",
149
156
  "endTime",
150
157
  "environment",
@@ -166,6 +173,7 @@ function buildTraceListColumns(preferences) {
166
173
  if (visible.has("output")) columns.push("minmax(8rem,1fr)");
167
174
  columns.push("6rem");
168
175
  if (visible.has("duration")) columns.push("7rem");
176
+ if (visible.has("traceCount")) columns.push("6rem");
169
177
  if (visible.has("timeToFirstChunk")) columns.push("7rem");
170
178
  if (visible.has("endTime")) columns.push("11rem");
171
179
  if (visible.has("environment")) columns.push("8rem");
@@ -240,6 +248,6 @@ function hasTraceUsageColumn(preferences) {
240
248
  function isTraceUsageColumn(column) {
241
249
  return TRACE_USAGE_COLUMN_SET.has(column);
242
250
  }
243
- export { DEFAULT_TRACE_COLUMN_PREFERENCES, TRACE_COLUMN_CATALOGS, TRACE_CUSTOM_COLUMN_FIELDS, TRACE_CUSTOM_COLUMN_LABELS, TRACE_OPTIONAL_COLUMNS, TRACE_USAGE_COLUMNS, addTraceCustomColumn, addTraceMetadataColumn, buildTraceListColumnKeys, buildTraceListColumns, displayTraceName, formatTraceMetadataValue, hasTraceColumn, hasTraceUsageColumn, isTraceCustomColumn, isTraceUsageColumn, parseTraceColumnPreferences, removeTraceCustomColumn, removeTraceMetadataColumn, serializeTraceColumnPreferences, toggleTraceColumn };
251
+ export { DEFAULT_TRACE_COLUMN_PREFERENCES, THREAD_LIST_COLUMN_PREFERENCES, TRACE_COLUMN_CATALOGS, TRACE_CUSTOM_COLUMN_FIELDS, TRACE_CUSTOM_COLUMN_LABELS, TRACE_OPTIONAL_COLUMNS, TRACE_USAGE_COLUMNS, addTraceCustomColumn, addTraceMetadataColumn, buildTraceListColumnKeys, buildTraceListColumns, displayTraceName, formatTraceMetadataValue, hasTraceColumn, hasTraceUsageColumn, isTraceCustomColumn, isTraceUsageColumn, parseTraceColumnPreferences, removeTraceCustomColumn, removeTraceMetadataColumn, serializeTraceColumnPreferences, toggleTraceColumn };
244
252
 
245
253
  //# sourceMappingURL=trace-list-columns.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"trace-list-columns.es.js","names":[],"sources":["../../../src/domains/traces/trace-list-columns.ts"],"sourcesContent":["export const TRACE_OPTIONAL_COLUMNS = [\n 'type',\n 'input',\n 'output',\n 'duration',\n 'timeToFirstChunk',\n 'endTime',\n 'environment',\n 'model',\n 'provider',\n 'inputTokens',\n 'outputTokens',\n 'totalTokens',\n 'estimatedCost',\n] as const;\n\nexport type TraceOptionalColumn = (typeof TRACE_OPTIONAL_COLUMNS)[number];\n\nexport const TRACE_USAGE_COLUMNS = [\n 'inputTokens',\n 'outputTokens',\n 'totalTokens',\n 'estimatedCost',\n] as const satisfies readonly TraceOptionalColumn[];\n\n/** Trace properties that are not regular columns but can be pinned as a custom column. */\nexport const TRACE_CUSTOM_COLUMN_FIELDS = ['traceId', 'threadId', 'resourceId', 'entityId'] as const;\n\nexport type TraceCustomColumn = (typeof TRACE_CUSTOM_COLUMN_FIELDS)[number];\n\nexport const TRACE_CUSTOM_COLUMN_LABELS: Record<TraceCustomColumn, string> = {\n traceId: 'Trace ID',\n threadId: 'Thread ID',\n resourceId: 'Resource ID',\n entityId: 'Primitive ID',\n};\n\nexport type TraceColumnPreferences = {\n readonly visibleColumns: readonly TraceOptionalColumn[];\n readonly customColumns: readonly TraceCustomColumn[];\n readonly metadataKeys: readonly string[];\n};\n\nimport type { TraceUsageSummary } from '@mastra/react/hooks/traces';\nexport type { TraceUsageSummary };\n\nexport const DEFAULT_TRACE_COLUMN_PREFERENCES: TraceColumnPreferences = {\n visibleColumns: ['type', 'input', 'output', 'duration', 'estimatedCost'],\n customColumns: [],\n metadataKeys: [],\n};\n\n/** A list a column selection belongs to. Each list only offers the columns its rows carry. */\nexport type TraceColumnScope = 'traces' | 'spans';\n\nexport type TraceColumnCatalog = {\n /** Plain columns offered in the picker, in menu order. */\n readonly standardColumns: readonly TraceOptionalColumn[];\n /** Whether rows carry token and cost usage. */\n readonly usage: boolean;\n /** Whether rows carry metadata that can be shown as columns. */\n readonly metadata: boolean;\n readonly defaults: TraceColumnPreferences;\n};\n\nexport const TRACE_COLUMN_CATALOGS: Record<TraceColumnScope, TraceColumnCatalog> = {\n traces: {\n standardColumns: ['type', 'input', 'output', 'duration', 'timeToFirstChunk', 'endTime', 'environment'],\n usage: true,\n metadata: true,\n defaults: DEFAULT_TRACE_COLUMN_PREFERENCES,\n },\n spans: {\n standardColumns: ['type', 'input', 'output', 'duration', 'endTime', 'environment', 'model', 'provider'],\n usage: false,\n metadata: false,\n defaults: { visibleColumns: ['type', 'input', 'output', 'duration'], customColumns: [], metadataKeys: [] },\n },\n};\n\n// v2: 'entity' became 'type' and moved before Name; duration + cost joined the defaults.\n// v3: added `customColumns`; a v2 payload is migrated rather than reset.\n// v4: added 'output', shown after 'input' for anyone who had Input visible.\nconst TRACE_COLUMN_PREFERENCES_VERSION = 4;\nconst TRACE_COLUMN_PREFERENCES_MIGRATABLE_VERSIONS = new Set<unknown>([2, 3, TRACE_COLUMN_PREFERENCES_VERSION]);\nconst TRACE_COLUMN_SET = new Set<string>(TRACE_OPTIONAL_COLUMNS);\nconst TRACE_USAGE_COLUMN_SET = new Set<TraceOptionalColumn>(TRACE_USAGE_COLUMNS);\nconst TRACE_CUSTOM_COLUMN_SET = new Set<string>(TRACE_CUSTOM_COLUMN_FIELDS);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isTraceOptionalColumn(value: unknown): value is TraceOptionalColumn {\n return typeof value === 'string' && TRACE_COLUMN_SET.has(value);\n}\n\nexport function isTraceCustomColumn(value: unknown): value is TraceCustomColumn {\n return typeof value === 'string' && TRACE_CUSTOM_COLUMN_SET.has(value);\n}\n\nfunction uniqueMetadataKeys(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n\n const keys = value\n .filter(key => typeof key === 'string')\n .map(key => key.trim())\n .filter(Boolean);\n\n return [...new Set(keys)];\n}\n\nexport function parseTraceColumnPreferences(\n serialized: string | undefined,\n defaults: TraceColumnPreferences = DEFAULT_TRACE_COLUMN_PREFERENCES,\n): TraceColumnPreferences {\n if (!serialized) return defaults;\n\n try {\n const parsed: unknown = JSON.parse(serialized);\n if (!isRecord(parsed) || !TRACE_COLUMN_PREFERENCES_MIGRATABLE_VERSIONS.has(parsed.version)) {\n return defaults;\n }\n\n const visibleColumns = Array.isArray(parsed.visibleColumns)\n ? [...new Set(parsed.visibleColumns.filter(isTraceOptionalColumn))]\n : [...defaults.visibleColumns];\n if (parsed.version !== TRACE_COLUMN_PREFERENCES_VERSION && !visibleColumns.includes('output')) {\n const input = visibleColumns.indexOf('input');\n if (input !== -1) visibleColumns.splice(input + 1, 0, 'output');\n }\n const customColumns = Array.isArray(parsed.customColumns)\n ? [...new Set(parsed.customColumns.filter(isTraceCustomColumn))]\n : [];\n\n return {\n visibleColumns,\n customColumns,\n metadataKeys: uniqueMetadataKeys(parsed.metadataKeys),\n };\n } catch {\n return defaults;\n }\n}\n\nexport function serializeTraceColumnPreferences(preferences: TraceColumnPreferences): string {\n return JSON.stringify({\n version: TRACE_COLUMN_PREFERENCES_VERSION,\n visibleColumns: preferences.visibleColumns,\n customColumns: preferences.customColumns,\n metadataKeys: preferences.metadataKeys,\n });\n}\n\n/** Stable key per column of `buildTraceListColumns`, in the same order. Used to persist the column order. */\nexport function buildTraceListColumnKeys(preferences: TraceColumnPreferences): string[] {\n const visible = new Set(preferences.visibleColumns);\n const keys = ['startTime'];\n if (visible.has('type')) keys.push('type');\n keys.push('name');\n if (visible.has('input')) keys.push('input');\n if (visible.has('output')) keys.push('output');\n keys.push('status');\n for (const column of [\n 'duration',\n 'timeToFirstChunk',\n 'endTime',\n 'environment',\n 'model',\n 'provider',\n ...TRACE_USAGE_COLUMNS,\n ] as const) {\n if (visible.has(column)) keys.push(column);\n }\n keys.push(...preferences.customColumns.map(field => `custom:${field}`));\n keys.push(...preferences.metadataKeys.map(key => `metadata:${key}`));\n return keys;\n}\n\nexport function buildTraceListColumns(preferences: TraceColumnPreferences): string {\n const visible = new Set(preferences.visibleColumns);\n // Name is bounded when Input or Output is visible so they (1fr each) absorb the free space;\n // without either, Name is the flexible track that fills the grid.\n const columns = ['11rem'];\n const hasPreview = visible.has('input') || visible.has('output');\n\n if (visible.has('type')) columns.push('7rem');\n columns.push(hasPreview ? '14rem' : 'minmax(8rem,1fr)');\n if (visible.has('input')) columns.push('minmax(8rem,1fr)');\n if (visible.has('output')) columns.push('minmax(8rem,1fr)');\n\n columns.push('6rem');\n\n if (visible.has('duration')) columns.push('7rem');\n if (visible.has('timeToFirstChunk')) columns.push('7rem');\n if (visible.has('endTime')) columns.push('11rem');\n if (visible.has('environment')) columns.push('8rem');\n if (visible.has('model')) columns.push('10rem');\n if (visible.has('provider')) columns.push('8rem');\n if (visible.has('inputTokens')) columns.push('8rem');\n if (visible.has('outputTokens')) columns.push('8rem');\n if (visible.has('totalTokens')) columns.push('8rem');\n if (visible.has('estimatedCost')) columns.push('8rem');\n\n for (const _field of preferences.customColumns) {\n columns.push('minmax(8rem,14rem)');\n }\n\n for (const _key of preferences.metadataKeys) {\n columns.push('minmax(8rem,14rem)');\n }\n\n return columns.join(' ');\n}\n\nconst RUN_PREFIX_PATTERN = /^(?:agent|workflow|scorer) run: '(.+?)'(.*)$/;\n\n/** Core names root spans `agent run: 'id'` (+ optional ` (resumed)`); the Primitive type column already carries\n * the kind, so the list shows just the id and any suffix. Core names are untouched for exporters. */\nexport function displayTraceName<T extends string | null | undefined>(name: T): T {\n if (!name) return name;\n return name.replace(RUN_PREFIX_PATTERN, '$1$2') as T;\n}\n\nexport function formatTraceMetadataValue(\n metadata: Record<string, unknown> | null | undefined,\n key: string,\n): string | undefined {\n if (!metadata || !Object.prototype.hasOwnProperty.call(metadata, key)) return undefined;\n const value = metadata[key];\n if (value == null) return undefined;\n\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') return String(value);\n\n try {\n return JSON.stringify(value) ?? undefined;\n } catch {\n return undefined;\n }\n}\n\nexport function hasTraceColumn(preferences: TraceColumnPreferences, column: TraceOptionalColumn): boolean {\n return preferences.visibleColumns.includes(column);\n}\n\nexport function toggleTraceColumn(\n preferences: TraceColumnPreferences,\n column: TraceOptionalColumn,\n): TraceColumnPreferences {\n return {\n ...preferences,\n visibleColumns: preferences.visibleColumns.includes(column)\n ? preferences.visibleColumns.filter(visibleColumn => visibleColumn !== column)\n : [...preferences.visibleColumns, column],\n };\n}\n\nexport function addTraceCustomColumn(\n preferences: TraceColumnPreferences,\n field: TraceCustomColumn,\n): TraceColumnPreferences {\n if (preferences.customColumns.includes(field)) return preferences;\n return { ...preferences, customColumns: [...preferences.customColumns, field] };\n}\n\nexport function removeTraceCustomColumn(\n preferences: TraceColumnPreferences,\n field: TraceCustomColumn,\n): TraceColumnPreferences {\n return { ...preferences, customColumns: preferences.customColumns.filter(customColumn => customColumn !== field) };\n}\n\nexport function addTraceMetadataColumn(preferences: TraceColumnPreferences, key: string): TraceColumnPreferences {\n const normalizedKey = key.trim();\n if (!normalizedKey || preferences.metadataKeys.includes(normalizedKey)) return preferences;\n return { ...preferences, metadataKeys: [...preferences.metadataKeys, normalizedKey] };\n}\n\nexport function removeTraceMetadataColumn(preferences: TraceColumnPreferences, key: string): TraceColumnPreferences {\n return { ...preferences, metadataKeys: preferences.metadataKeys.filter(metadataKey => metadataKey !== key) };\n}\n\nexport function hasTraceUsageColumn(preferences: TraceColumnPreferences): boolean {\n return preferences.visibleColumns.some(isTraceUsageColumn);\n}\n\nexport function isTraceUsageColumn(column: TraceOptionalColumn): boolean {\n return TRACE_USAGE_COLUMN_SET.has(column);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"trace-list-columns.es.js","names":[],"sources":["../../../src/domains/traces/trace-list-columns.ts"],"sourcesContent":["export const TRACE_OPTIONAL_COLUMNS = [\n 'type',\n 'input',\n 'output',\n 'duration',\n 'traceCount',\n 'timeToFirstChunk',\n 'endTime',\n 'environment',\n 'model',\n 'provider',\n 'inputTokens',\n 'outputTokens',\n 'totalTokens',\n 'estimatedCost',\n] as const;\n\nexport type TraceOptionalColumn = (typeof TRACE_OPTIONAL_COLUMNS)[number];\n\nexport const TRACE_USAGE_COLUMNS = [\n 'inputTokens',\n 'outputTokens',\n 'totalTokens',\n 'estimatedCost',\n] as const satisfies readonly TraceOptionalColumn[];\n\n/** Trace properties that are not regular columns but can be pinned as a custom column. */\nexport const TRACE_CUSTOM_COLUMN_FIELDS = ['traceId', 'threadId', 'resourceId', 'entityId'] as const;\n\nexport type TraceCustomColumn = (typeof TRACE_CUSTOM_COLUMN_FIELDS)[number];\n\nexport const TRACE_CUSTOM_COLUMN_LABELS: Record<TraceCustomColumn, string> = {\n traceId: 'Trace ID',\n threadId: 'Thread ID',\n resourceId: 'Resource ID',\n entityId: 'Primitive ID',\n};\n\nexport type TraceColumnPreferences = {\n readonly visibleColumns: readonly TraceOptionalColumn[];\n readonly customColumns: readonly TraceCustomColumn[];\n readonly metadataKeys: readonly string[];\n};\n\nimport type { TraceUsageSummary } from '@mastra/react/hooks/traces';\nexport type { TraceUsageSummary };\n\nexport const DEFAULT_TRACE_COLUMN_PREFERENCES: TraceColumnPreferences = {\n visibleColumns: ['type', 'input', 'output', 'duration', 'estimatedCost'],\n customColumns: [],\n metadataKeys: [],\n};\n\n/** The Threads list: the trace defaults plus each thread's trace count. Not offered in any column picker. */\nexport const THREAD_LIST_COLUMN_PREFERENCES: TraceColumnPreferences = {\n ...DEFAULT_TRACE_COLUMN_PREFERENCES,\n visibleColumns: [...DEFAULT_TRACE_COLUMN_PREFERENCES.visibleColumns, 'traceCount'],\n};\n\n/** A list a column selection belongs to. Each list only offers the columns its rows carry. */\nexport type TraceColumnScope = 'traces' | 'spans';\n\nexport type TraceColumnCatalog = {\n /** Plain columns offered in the picker, in menu order. */\n readonly standardColumns: readonly TraceOptionalColumn[];\n /** Whether rows carry token and cost usage. */\n readonly usage: boolean;\n /** Whether rows carry metadata that can be shown as columns. */\n readonly metadata: boolean;\n readonly defaults: TraceColumnPreferences;\n};\n\nexport const TRACE_COLUMN_CATALOGS: Record<TraceColumnScope, TraceColumnCatalog> = {\n traces: {\n standardColumns: ['type', 'input', 'output', 'duration', 'timeToFirstChunk', 'endTime', 'environment'],\n usage: true,\n metadata: true,\n defaults: DEFAULT_TRACE_COLUMN_PREFERENCES,\n },\n spans: {\n standardColumns: ['type', 'input', 'output', 'duration', 'endTime', 'environment', 'model', 'provider'],\n usage: false,\n metadata: false,\n defaults: { visibleColumns: ['type', 'input', 'output', 'duration'], customColumns: [], metadataKeys: [] },\n },\n};\n\n// v2: 'entity' became 'type' and moved before Name; duration + cost joined the defaults.\n// v3: added `customColumns`; a v2 payload is migrated rather than reset.\n// v4: added 'output', shown after 'input' for anyone who had Input visible.\nconst TRACE_COLUMN_PREFERENCES_VERSION = 4;\nconst TRACE_COLUMN_PREFERENCES_MIGRATABLE_VERSIONS = new Set<unknown>([2, 3, TRACE_COLUMN_PREFERENCES_VERSION]);\nconst TRACE_COLUMN_SET = new Set<string>(TRACE_OPTIONAL_COLUMNS);\nconst TRACE_USAGE_COLUMN_SET = new Set<TraceOptionalColumn>(TRACE_USAGE_COLUMNS);\nconst TRACE_CUSTOM_COLUMN_SET = new Set<string>(TRACE_CUSTOM_COLUMN_FIELDS);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isTraceOptionalColumn(value: unknown): value is TraceOptionalColumn {\n return typeof value === 'string' && TRACE_COLUMN_SET.has(value);\n}\n\nexport function isTraceCustomColumn(value: unknown): value is TraceCustomColumn {\n return typeof value === 'string' && TRACE_CUSTOM_COLUMN_SET.has(value);\n}\n\nfunction uniqueMetadataKeys(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n\n const keys = value\n .filter(key => typeof key === 'string')\n .map(key => key.trim())\n .filter(Boolean);\n\n return [...new Set(keys)];\n}\n\nexport function parseTraceColumnPreferences(\n serialized: string | undefined,\n defaults: TraceColumnPreferences = DEFAULT_TRACE_COLUMN_PREFERENCES,\n): TraceColumnPreferences {\n if (!serialized) return defaults;\n\n try {\n const parsed: unknown = JSON.parse(serialized);\n if (!isRecord(parsed) || !TRACE_COLUMN_PREFERENCES_MIGRATABLE_VERSIONS.has(parsed.version)) {\n return defaults;\n }\n\n const visibleColumns = Array.isArray(parsed.visibleColumns)\n ? [...new Set(parsed.visibleColumns.filter(isTraceOptionalColumn))]\n : [...defaults.visibleColumns];\n if (parsed.version !== TRACE_COLUMN_PREFERENCES_VERSION && !visibleColumns.includes('output')) {\n const input = visibleColumns.indexOf('input');\n if (input !== -1) visibleColumns.splice(input + 1, 0, 'output');\n }\n const customColumns = Array.isArray(parsed.customColumns)\n ? [...new Set(parsed.customColumns.filter(isTraceCustomColumn))]\n : [];\n\n return {\n visibleColumns,\n customColumns,\n metadataKeys: uniqueMetadataKeys(parsed.metadataKeys),\n };\n } catch {\n return defaults;\n }\n}\n\nexport function serializeTraceColumnPreferences(preferences: TraceColumnPreferences): string {\n return JSON.stringify({\n version: TRACE_COLUMN_PREFERENCES_VERSION,\n visibleColumns: preferences.visibleColumns,\n customColumns: preferences.customColumns,\n metadataKeys: preferences.metadataKeys,\n });\n}\n\n/** Stable key per column of `buildTraceListColumns`, in the same order. Used to persist the column order. */\nexport function buildTraceListColumnKeys(preferences: TraceColumnPreferences): string[] {\n const visible = new Set(preferences.visibleColumns);\n const keys = ['startTime'];\n if (visible.has('type')) keys.push('type');\n keys.push('name');\n if (visible.has('input')) keys.push('input');\n if (visible.has('output')) keys.push('output');\n keys.push('status');\n for (const column of [\n 'duration',\n 'traceCount',\n 'timeToFirstChunk',\n 'endTime',\n 'environment',\n 'model',\n 'provider',\n ...TRACE_USAGE_COLUMNS,\n ] as const) {\n if (visible.has(column)) keys.push(column);\n }\n keys.push(...preferences.customColumns.map(field => `custom:${field}`));\n keys.push(...preferences.metadataKeys.map(key => `metadata:${key}`));\n return keys;\n}\n\nexport function buildTraceListColumns(preferences: TraceColumnPreferences): string {\n const visible = new Set(preferences.visibleColumns);\n // Name is bounded when Input or Output is visible so they (1fr each) absorb the free space;\n // without either, Name is the flexible track that fills the grid.\n const columns = ['11rem'];\n const hasPreview = visible.has('input') || visible.has('output');\n\n if (visible.has('type')) columns.push('7rem');\n columns.push(hasPreview ? '14rem' : 'minmax(8rem,1fr)');\n if (visible.has('input')) columns.push('minmax(8rem,1fr)');\n if (visible.has('output')) columns.push('minmax(8rem,1fr)');\n\n columns.push('6rem');\n\n if (visible.has('duration')) columns.push('7rem');\n if (visible.has('traceCount')) columns.push('6rem');\n if (visible.has('timeToFirstChunk')) columns.push('7rem');\n if (visible.has('endTime')) columns.push('11rem');\n if (visible.has('environment')) columns.push('8rem');\n if (visible.has('model')) columns.push('10rem');\n if (visible.has('provider')) columns.push('8rem');\n if (visible.has('inputTokens')) columns.push('8rem');\n if (visible.has('outputTokens')) columns.push('8rem');\n if (visible.has('totalTokens')) columns.push('8rem');\n if (visible.has('estimatedCost')) columns.push('8rem');\n\n for (const _field of preferences.customColumns) {\n columns.push('minmax(8rem,14rem)');\n }\n\n for (const _key of preferences.metadataKeys) {\n columns.push('minmax(8rem,14rem)');\n }\n\n return columns.join(' ');\n}\n\nconst RUN_PREFIX_PATTERN = /^(?:agent|workflow|scorer) run: '(.+?)'(.*)$/;\n\n/** Core names root spans `agent run: 'id'` (+ optional ` (resumed)`); the Primitive type column already carries\n * the kind, so the list shows just the id and any suffix. Core names are untouched for exporters. */\nexport function displayTraceName<T extends string | null | undefined>(name: T): T {\n if (!name) return name;\n return name.replace(RUN_PREFIX_PATTERN, '$1$2') as T;\n}\n\nexport function formatTraceMetadataValue(\n metadata: Record<string, unknown> | null | undefined,\n key: string,\n): string | undefined {\n if (!metadata || !Object.prototype.hasOwnProperty.call(metadata, key)) return undefined;\n const value = metadata[key];\n if (value == null) return undefined;\n\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') return String(value);\n\n try {\n return JSON.stringify(value) ?? undefined;\n } catch {\n return undefined;\n }\n}\n\nexport function hasTraceColumn(preferences: TraceColumnPreferences, column: TraceOptionalColumn): boolean {\n return preferences.visibleColumns.includes(column);\n}\n\nexport function toggleTraceColumn(\n preferences: TraceColumnPreferences,\n column: TraceOptionalColumn,\n): TraceColumnPreferences {\n return {\n ...preferences,\n visibleColumns: preferences.visibleColumns.includes(column)\n ? preferences.visibleColumns.filter(visibleColumn => visibleColumn !== column)\n : [...preferences.visibleColumns, column],\n };\n}\n\nexport function addTraceCustomColumn(\n preferences: TraceColumnPreferences,\n field: TraceCustomColumn,\n): TraceColumnPreferences {\n if (preferences.customColumns.includes(field)) return preferences;\n return { ...preferences, customColumns: [...preferences.customColumns, field] };\n}\n\nexport function removeTraceCustomColumn(\n preferences: TraceColumnPreferences,\n field: TraceCustomColumn,\n): TraceColumnPreferences {\n return { ...preferences, customColumns: preferences.customColumns.filter(customColumn => customColumn !== field) };\n}\n\nexport function addTraceMetadataColumn(preferences: TraceColumnPreferences, key: string): TraceColumnPreferences {\n const normalizedKey = key.trim();\n if (!normalizedKey || preferences.metadataKeys.includes(normalizedKey)) return preferences;\n return { ...preferences, metadataKeys: [...preferences.metadataKeys, normalizedKey] };\n}\n\nexport function removeTraceMetadataColumn(preferences: TraceColumnPreferences, key: string): TraceColumnPreferences {\n return { ...preferences, metadataKeys: preferences.metadataKeys.filter(metadataKey => metadataKey !== key) };\n}\n\nexport function hasTraceUsageColumn(preferences: TraceColumnPreferences): boolean {\n return preferences.visibleColumns.some(isTraceUsageColumn);\n}\n\nexport function isTraceUsageColumn(column: TraceOptionalColumn): boolean {\n return TRACE_USAGE_COLUMN_SET.has(column);\n}\n"],"mappings":"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"}
@@ -29,6 +29,8 @@ export type TracesListViewTrace = {
29
29
  endedAt?: Date | string | null;
30
30
  /** The root span's time to first chunk; `null` when it never streamed one. */
31
31
  timeToFirstChunkMs?: number | null;
32
+ /** Thread rows only: every trace in the thread, regardless of the listed time range. */
33
+ traceCount?: number;
32
34
  createdAt: Date | string;
33
35
  };
34
36
  export type TracesListViewProps = {
@@ -1,4 +1,4 @@
1
- export declare const TRACE_OPTIONAL_COLUMNS: readonly ['type', 'input', 'output', 'duration', 'timeToFirstChunk', 'endTime', 'environment', 'model', 'provider', 'inputTokens', 'outputTokens', 'totalTokens', 'estimatedCost'];
1
+ export declare const TRACE_OPTIONAL_COLUMNS: readonly ['type', 'input', 'output', 'duration', 'traceCount', 'timeToFirstChunk', 'endTime', 'environment', 'model', 'provider', 'inputTokens', 'outputTokens', 'totalTokens', 'estimatedCost'];
2
2
  export type TraceOptionalColumn = (typeof TRACE_OPTIONAL_COLUMNS)[number];
3
3
  export declare const TRACE_USAGE_COLUMNS: readonly ["inputTokens", "outputTokens", "totalTokens", "estimatedCost"];
4
4
  /** Trace properties that are not regular columns but can be pinned as a custom column. */
@@ -13,6 +13,8 @@ export type TraceColumnPreferences = {
13
13
  import type { TraceUsageSummary } from '@mastra/react/hooks/traces';
14
14
  export type { TraceUsageSummary };
15
15
  export declare const DEFAULT_TRACE_COLUMN_PREFERENCES: TraceColumnPreferences;
16
+ /** The Threads list: the trace defaults plus each thread's trace count. Not offered in any column picker. */
17
+ export declare const THREAD_LIST_COLUMN_PREFERENCES: TraceColumnPreferences;
16
18
  /** A list a column selection belongs to. Each list only offers the columns its rows carry. */
17
19
  export type TraceColumnScope = 'traces' | 'spans';
18
20
  export type TraceColumnCatalog = {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mastra/playground-ui",
3
3
  "type": "module",
4
- "version": "66.0.0-alpha.5",
4
+ "version": "66.0.0-alpha.6",
5
5
  "description": "Mastra Playground components",
6
6
  "sideEffects": [
7
7
  "**/*.css"
@@ -219,9 +219,9 @@
219
219
  "react": ">=19.0.0",
220
220
  "react-dom": ">=19.0.0",
221
221
  "tailwindcss": "^4.0.0",
222
- "@mastra/client-js": "^1.57.0-alpha.5",
223
222
  "@mastra/ai-sdk": "^1.11.2",
224
- "@mastra/react": "1.13.0-alpha.5"
223
+ "@mastra/react": "1.13.0-alpha.6",
224
+ "@mastra/client-js": "^1.57.0-alpha.6"
225
225
  },
226
226
  "devDependencies": {
227
227
  "@modelcontextprotocol/sdk": "^1.32.2",
@@ -263,10 +263,10 @@
263
263
  "vitest": "4.1.12",
264
264
  "@internal/lint": "0.0.145",
265
265
  "@mastra/ai-sdk": "1.11.2",
266
- "@mastra/client-js": "^1.57.0-alpha.5",
267
- "@mastra/core": "1.80.0-alpha.5",
268
266
  "@mastra/memory": "1.39.1-alpha.3",
269
- "@mastra/react": "1.13.0-alpha.5",
267
+ "@mastra/react": "1.13.0-alpha.6",
268
+ "@mastra/client-js": "^1.57.0-alpha.6",
269
+ "@mastra/core": "1.80.0-alpha.6",
270
270
  "@mastra/schema-compat": "1.3.17-alpha.0"
271
271
  },
272
272
  "homepage": "https://mastra.ai",