@mastra/playground-ui 28.0.1-alpha.0 → 28.0.1-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,37 @@
1
1
  # @mastra/playground-ui
2
2
 
3
+ ## 28.0.1-alpha.2
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [[`816b974`](https://github.com/mastra-ai/mastra/commit/816b974b424e4a1bfae3af30cc41263b6f1c0344), [`816b974`](https://github.com/mastra-ai/mastra/commit/816b974b424e4a1bfae3af30cc41263b6f1c0344), [`b32ba5f`](https://github.com/mastra-ai/mastra/commit/b32ba5fde524b46a4ff1bdf38e30d62a2bb29b04)]:
8
+ - @mastra/core@1.35.0-alpha.2
9
+ - @mastra/client-js@1.19.1-alpha.2
10
+ - @mastra/react@0.3.3-alpha.2
11
+
12
+ ## 28.0.1-alpha.1
13
+
14
+ ### Patch Changes
15
+
16
+ - Fixed the Observability traces page on storage providers that don't support the Branches list mode. The page now falls back to Traces mode, hides the Branches option in the filter, and shows a dismissible notice instead of a full-screen error. ([#16601](https://github.com/mastra-ai/mastra/pull/16601))
17
+
18
+ - Improved the Observability traces list to make the with-subtraces view more discoverable. ([#16643](https://github.com/mastra-ai/mastra/pull/16643))
19
+ - **Added:** A **Level** column whose icon distinguishes top-level **Trace** rows from nested **Subtrace** rows.
20
+ - **Added:** A tooltip legend on the **Level** header showing both icons side by side.
21
+ - **Added:** A standalone **Show subtraces** toggle next to **Add Filter** — off keeps the default top-level view, on includes subtraces.
22
+ - **Removed:** The **List mode** entry from the **Add Filter** menu (now driven by the toggle).
23
+
24
+ **Usage:** Open Observability → Traces → switch **Show subtraces** on. The **Level** column updates: top-level rows keep the Trace icon, nested rows show the Subtrace (↳) icon. The toggle is hidden automatically when the active storage provider doesn't support subtraces.
25
+
26
+ - Removed the "Group traces by thread" option from the Observability traces page. The list now always displays a flat view of traces, without thread-id subheaders. To narrow results to a specific thread, use the Thread ID property in the Add filter menu (open Observability → Traces → Add filter → Thread ID → paste the threadId). ([#16633](https://github.com/mastra-ai/mastra/pull/16633))
27
+
28
+ - Polished the property filter dropdown so the chevron icon next to each option keeps the same shape when its side panel opens ([#16635](https://github.com/mastra-ai/mastra/pull/16635))
29
+
30
+ - Updated dependencies [[`bad08e9`](https://github.com/mastra-ai/mastra/commit/bad08e99c5291884c3ac76743c78c74f53a302c2)]:
31
+ - @mastra/core@1.35.0-alpha.1
32
+ - @mastra/client-js@1.19.1-alpha.1
33
+ - @mastra/react@0.3.3-alpha.1
34
+
3
35
  ## 28.0.1-alpha.0
4
36
 
5
37
  ### Patch Changes
package/dist/index.cjs.js CHANGED
@@ -8637,7 +8637,7 @@ function PickMultiMenuItem({ field, tokens, onChange, open, onToggle, onClose })
8637
8637
  });
8638
8638
  },
8639
8639
  children: [
8640
- open && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeftIcon, { className: "h-4 w-4 text-neutral3 shrink-0" }),
8640
+ open && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRightIcon, { className: "h-4 w-4 text-neutral3 shrink-0" }),
8641
8641
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: field.label }),
8642
8642
  !open && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRightIcon, { className: "h-4 w-4 ml-auto text-neutral3 shrink-0" })
8643
8643
  ]
@@ -13238,6 +13238,12 @@ function getShortId(id) {
13238
13238
  function TracesDataListIdCell({ traceId }) {
13239
13239
  return /* @__PURE__ */ jsxRuntime.jsx(DataListCell, { height: "compact", className: "text-ui-smd font-mono text-neutral3", children: getShortId(traceId) });
13240
13240
  }
13241
+ function TracesDataListKindCell({ parentSpanId }) {
13242
+ const isRoot = parentSpanId == null;
13243
+ const Icon = isRoot ? lucideReact.ListTreeIcon : lucideReact.CornerDownRightIcon;
13244
+ const label = isRoot ? "Trace" : "Subtrace";
13245
+ return /* @__PURE__ */ jsxRuntime.jsx(DataListCell, { height: "compact", className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx("span", { title: label, "aria-label": label, className: "inline-flex", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: cn("shrink-0", isRoot ? "size-4 text-neutral3" : "size-3 text-neutral3"), "aria-hidden": true }) }) });
13246
+ }
13241
13247
  function TracesDataListDateCell({ timestamp }) {
13242
13248
  const date = toDate$2(timestamp);
13243
13249
  return /* @__PURE__ */ jsxRuntime.jsx(DataListCell, { height: "compact", className: "text-ui-smd text-neutral2", children: date ? dateFns.isToday(date) ? "Today" : dateFns.format(date, "MMM dd") : "-" });
@@ -13295,12 +13301,14 @@ function TracesDataListRoot(props) {
13295
13301
  const TracesDataList = Object.assign(TracesDataListRoot, {
13296
13302
  Top: DataListTop,
13297
13303
  TopCell: DataListTopCell,
13304
+ TopCellWithTooltip: DataListTopCellWithTooltip,
13298
13305
  RowButton: DataListRowButton,
13299
13306
  NoMatch: DataListNoMatch,
13300
13307
  Subheader: DataListSubheader,
13301
13308
  SubHeading: DataListSubHeading,
13302
13309
  Spacer: DataListSpacer,
13303
13310
  IdCell: TracesDataListIdCell,
13311
+ KindCell: TracesDataListKindCell,
13304
13312
  DateCell: TracesDataListDateCell,
13305
13313
  TimeCell: TracesDataListTimeCell,
13306
13314
  NameCell: TracesDataListNameCell,
@@ -15461,6 +15469,12 @@ function is403ForbiddenError(error) {
15461
15469
  }
15462
15470
  return false;
15463
15471
  }
15472
+ function isBranchesNotSupportedError(error) {
15473
+ if (!error || typeof error !== "object" || !("message" in error)) return false;
15474
+ const message = error.message;
15475
+ if (typeof message !== "string") return false;
15476
+ return message.includes("does not support listing trace branches");
15477
+ }
15464
15478
  function isNonRetryableError(error) {
15465
15479
  if (!error || typeof error !== "object") return false;
15466
15480
  if ("status" in error) {
@@ -18119,7 +18133,7 @@ const TRACE_STATUS_OPTIONS = [
18119
18133
  { label: "Success", value: "success" },
18120
18134
  { label: "Error", value: "error" }
18121
18135
  ];
18122
- const TRACE_SYNTHETIC_FILTER_FIELD_IDS = ["rootEntityType", "status", "mode"];
18136
+ const TRACE_SYNTHETIC_FILTER_FIELD_IDS = ["rootEntityType", "status"];
18123
18137
  const TRACE_ROOT_ENTITY_TYPE_PARAM = "rootEntityType";
18124
18138
  const TRACE_STATUS_PARAM = "status";
18125
18139
  const TRACE_LIST_MODE_PARAM = "listMode";
@@ -18218,17 +18232,6 @@ function createTracePropertyFilterFields({
18218
18232
  placeholder: "Choose entity type",
18219
18233
  emptyText: "No entity types."
18220
18234
  },
18221
- {
18222
- id: "mode",
18223
- label: "List mode",
18224
- kind: "pick-multi",
18225
- searchable: false,
18226
- options: TRACE_LIST_MODE_OPTIONS.map((o) => ({ label: o.label, value: o.value })),
18227
- placeholder: "Choose list mode",
18228
- emptyText: "No list modes.",
18229
- omitAnyOption: true,
18230
- defaultValue: "traces"
18231
- },
18232
18235
  {
18233
18236
  id: "entityName",
18234
18237
  label: "Primitive Name",
@@ -18287,17 +18290,15 @@ function createTracePropertyFilterFields({
18287
18290
  { id: "experimentId", label: "Experiment ID", kind: "text" }
18288
18291
  ];
18289
18292
  const byLabel = (a, b) => a.label.localeCompare(b.label);
18290
- const mode = fields.filter((f) => f.id === "mode");
18291
- const pickMulti = fields.filter((f) => f.kind === "pick-multi" && f.id !== "mode").sort(byLabel);
18293
+ const pickMulti = fields.filter((f) => f.kind === "pick-multi").sort(byLabel);
18292
18294
  const text = fields.filter((f) => f.kind === "text").sort(byLabel);
18293
- return [...mode, ...pickMulti, ...text];
18295
+ return [...pickMulti, ...text];
18294
18296
  }
18295
18297
  function getTracePropertyFilterTokens(searchParams) {
18296
18298
  const tokens = [];
18297
18299
  const paramToFieldId = /* @__PURE__ */ new Map([
18298
18300
  [TRACE_ROOT_ENTITY_TYPE_PARAM, "rootEntityType"],
18299
- [TRACE_STATUS_PARAM, "status"],
18300
- [TRACE_LIST_MODE_PARAM, "mode"]
18301
+ [TRACE_STATUS_PARAM, "status"]
18301
18302
  ]);
18302
18303
  for (const fieldId of TRACE_PROPERTY_FILTER_FIELD_IDS) {
18303
18304
  paramToFieldId.set(TRACE_PROPERTY_FILTER_PARAM_BY_FIELD[fieldId], fieldId);
@@ -18344,7 +18345,6 @@ function getPreservedTraceFilterParams(searchParams) {
18344
18345
  function applyTracePropertyFilterTokens(params, tokens) {
18345
18346
  params.delete(TRACE_ROOT_ENTITY_TYPE_PARAM);
18346
18347
  params.delete(TRACE_STATUS_PARAM);
18347
- params.delete(TRACE_LIST_MODE_PARAM);
18348
18348
  for (const fieldId of TRACE_PROPERTY_FILTER_FIELD_IDS) {
18349
18349
  params.delete(TRACE_PROPERTY_FILTER_PARAM_BY_FIELD[fieldId]);
18350
18350
  }
@@ -18357,10 +18357,6 @@ function applyTracePropertyFilterTokens(params, tokens) {
18357
18357
  params.set(TRACE_STATUS_PARAM, token.value);
18358
18358
  continue;
18359
18359
  }
18360
- if (token.fieldId === "mode" && typeof token.value === "string") {
18361
- params.set(TRACE_LIST_MODE_PARAM, token.value);
18362
- continue;
18363
- }
18364
18360
  const param = TRACE_PROPERTY_FILTER_PARAM_BY_FIELD[token.fieldId];
18365
18361
  if (!param) continue;
18366
18362
  if (token.fieldId === "tags" && Array.isArray(token.value)) {
@@ -20037,34 +20033,7 @@ function TracesLayout({
20037
20033
  );
20038
20034
  }
20039
20035
 
20040
- function groupTracesByThread(traces) {
20041
- const threadMap = /* @__PURE__ */ new Map();
20042
- const ungrouped = [];
20043
- for (const trace of traces) {
20044
- if (trace.threadId) {
20045
- const existing = threadMap.get(trace.threadId);
20046
- if (existing) {
20047
- existing.push(trace);
20048
- } else {
20049
- threadMap.set(trace.threadId, [trace]);
20050
- }
20051
- } else {
20052
- ungrouped.push(trace);
20053
- }
20054
- }
20055
- const groups = Array.from(threadMap.entries()).map(([threadId, traces2]) => ({
20056
- threadId,
20057
- traces: traces2
20058
- }));
20059
- groups.sort((a, b) => {
20060
- const aLatest = Math.max(...a.traces.map((t) => new Date(t.createdAt).getTime()));
20061
- const bLatest = Math.max(...b.traces.map((t) => new Date(t.createdAt).getTime()));
20062
- return bLatest - aLatest;
20063
- });
20064
- return { groups, ungrouped };
20065
- }
20066
-
20067
- const COLUMNS$1 = "7rem 6rem 9rem 14rem minmax(8rem,1fr) 14rem 6rem";
20036
+ const COLUMNS$1 = "4rem 6rem 9rem 14rem minmax(8rem,1fr) 14rem 6rem";
20068
20037
  const ROW_HEIGHT$1 = 36;
20069
20038
  const OVERSCAN$1 = 8;
20070
20039
  function TracesListView({
@@ -20076,65 +20045,11 @@ function TracesListView({
20076
20045
  filtersApplied,
20077
20046
  featuredTraceId,
20078
20047
  featuredSpanId,
20079
- onTraceClick,
20080
- groupByThread,
20081
- threadTitles
20048
+ onTraceClick
20082
20049
  }) {
20083
20050
  const scrollRef = React.useRef(null);
20084
- const items = React.useMemo(() => {
20085
- if (traces.length === 0) return [];
20086
- if (!groupByThread) {
20087
- return traces.map((trace) => ({ kind: "row", key: `${trace.traceId}:${trace.spanId ?? ""}`, trace }));
20088
- }
20089
- const { groups, ungrouped } = groupTracesByThread(traces);
20090
- const result = [];
20091
- for (const group of groups) {
20092
- result.push({
20093
- kind: "subheader",
20094
- key: `header-${group.threadId}`,
20095
- node: /* @__PURE__ */ jsxRuntime.jsxs(TracesDataList.SubHeading, { className: "flex gap-2", children: [
20096
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "uppercase", children: "Thread" }),
20097
- threadTitles?.[group.threadId] && /* @__PURE__ */ jsxRuntime.jsxs("b", { children: [
20098
- "'",
20099
- threadTitles[group.threadId],
20100
- "'"
20101
- ] }),
20102
- /* @__PURE__ */ jsxRuntime.jsxs("b", { children: [
20103
- "# ",
20104
- group.threadId
20105
- ] }),
20106
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-neutral2", children: [
20107
- "(",
20108
- group.traces.length,
20109
- ")"
20110
- ] })
20111
- ] })
20112
- });
20113
- for (const trace of group.traces) {
20114
- result.push({ kind: "row", key: `${trace.traceId}:${trace.spanId ?? ""}`, trace });
20115
- }
20116
- }
20117
- if (ungrouped.length > 0) {
20118
- result.push({
20119
- kind: "subheader",
20120
- key: "header-ungrouped",
20121
- node: /* @__PURE__ */ jsxRuntime.jsxs(TracesDataList.SubHeading, { className: "flex gap-2 uppercase", children: [
20122
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "No thread" }),
20123
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-neutral2", children: [
20124
- "(",
20125
- ungrouped.length,
20126
- ")"
20127
- ] })
20128
- ] })
20129
- });
20130
- for (const trace of ungrouped) {
20131
- result.push({ kind: "row", key: `${trace.traceId}:${trace.spanId ?? ""}`, trace });
20132
- }
20133
- }
20134
- return result;
20135
- }, [traces, groupByThread, threadTitles]);
20136
20051
  const virtualizer = reactVirtual.useVirtualizer({
20137
- count: items.length,
20052
+ count: traces.length,
20138
20053
  getScrollElement: () => scrollRef.current,
20139
20054
  estimateSize: () => ROW_HEIGHT$1,
20140
20055
  overscan: OVERSCAN$1
@@ -20155,7 +20070,22 @@ function TracesListView({
20155
20070
  const paddingBottom = virtualItems.length > 0 ? Math.max(0, totalSize - (virtualItems[virtualItems.length - 1]?.end ?? 0)) : 0;
20156
20071
  return /* @__PURE__ */ jsxRuntime.jsxs(TracesDataList, { columns: COLUMNS$1, scrollRef, className: "min-w-0", children: [
20157
20072
  /* @__PURE__ */ jsxRuntime.jsxs(TracesDataList.Top, { children: [
20158
- /* @__PURE__ */ jsxRuntime.jsx(TracesDataList.TopCell, { children: "ID" }),
20073
+ /* @__PURE__ */ jsxRuntime.jsx(
20074
+ TracesDataList.TopCellWithTooltip,
20075
+ {
20076
+ tooltip: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-1", children: [
20077
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1.5", children: [
20078
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ListTreeIcon, { className: "size-4 shrink-0", "aria-hidden": true }),
20079
+ "Trace"
20080
+ ] }),
20081
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1.5", children: [
20082
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CornerDownRightIcon, { className: "size-4 shrink-0", "aria-hidden": true }),
20083
+ "Subtrace"
20084
+ ] })
20085
+ ] }),
20086
+ children: "Level"
20087
+ }
20088
+ ),
20159
20089
  /* @__PURE__ */ jsxRuntime.jsx(TracesDataList.TopCell, { children: "Date" }),
20160
20090
  /* @__PURE__ */ jsxRuntime.jsx(TracesDataList.TopCell, { children: "Time" }),
20161
20091
  /* @__PURE__ */ jsxRuntime.jsx(TracesDataList.TopCell, { children: "Name" }),
@@ -20163,7 +20093,7 @@ function TracesListView({
20163
20093
  /* @__PURE__ */ jsxRuntime.jsx(TracesDataList.TopCell, { children: "Entity" }),
20164
20094
  /* @__PURE__ */ jsxRuntime.jsx(TracesDataList.TopCell, { children: "Status" })
20165
20095
  ] }),
20166
- items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(
20096
+ traces.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(
20167
20097
  TracesDataList.NoMatch,
20168
20098
  {
20169
20099
  message: filtersApplied ? "No traces found for applied filters" : "No traces found yet"
@@ -20171,12 +20101,8 @@ function TracesListView({
20171
20101
  ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
20172
20102
  /* @__PURE__ */ jsxRuntime.jsx(TracesDataList.Spacer, { height: paddingTop }),
20173
20103
  virtualItems.map((vi) => {
20174
- const item = items[vi.index];
20175
- if (!item) return null;
20176
- if (item.kind === "subheader") {
20177
- return /* @__PURE__ */ jsxRuntime.jsx(TracesDataList.Subheader, { ref: virtualizer.measureElement, "data-index": vi.index, children: item.node }, item.key);
20178
- }
20179
- const trace = item.trace;
20104
+ const trace = traces[vi.index];
20105
+ if (!trace) return null;
20180
20106
  const isFeatured = trace.traceId === featuredTraceId && (featuredSpanId == null || trace.spanId === featuredSpanId);
20181
20107
  const displayDate = trace.startedAt ?? trace.createdAt;
20182
20108
  const entityName = trace.entityName || trace.entityId || trace.attributes?.agentId || trace.attributes?.workflowId;
@@ -20188,7 +20114,7 @@ function TracesListView({
20188
20114
  onClick: () => onTraceClick(trace),
20189
20115
  className: cn(isFeatured && "bg-surface4"),
20190
20116
  children: [
20191
- /* @__PURE__ */ jsxRuntime.jsx(TracesDataList.IdCell, { traceId: trace.traceId }),
20117
+ /* @__PURE__ */ jsxRuntime.jsx(TracesDataList.KindCell, { parentSpanId: trace.parentSpanId }),
20192
20118
  /* @__PURE__ */ jsxRuntime.jsx(TracesDataList.DateCell, { timestamp: displayDate }),
20193
20119
  /* @__PURE__ */ jsxRuntime.jsx(TracesDataList.TimeCell, { timestamp: displayDate }),
20194
20120
  /* @__PURE__ */ jsxRuntime.jsx(TracesDataList.NameCell, { name: trace.name }),
@@ -20197,7 +20123,7 @@ function TracesListView({
20197
20123
  /* @__PURE__ */ jsxRuntime.jsx(TracesDataList.StatusCell, { status: trace.attributes?.status })
20198
20124
  ]
20199
20125
  },
20200
- trace.traceId
20126
+ `${trace.traceId}:${trace.spanId ?? ""}`
20201
20127
  );
20202
20128
  }),
20203
20129
  /* @__PURE__ */ jsxRuntime.jsx(TracesDataList.Spacer, { height: paddingBottom }),
@@ -20446,13 +20372,7 @@ function selectUniqueTraces(data) {
20446
20372
  seen.add(key);
20447
20373
  return true;
20448
20374
  });
20449
- const threadTitles = {};
20450
- for (const page of data.pages) {
20451
- if (page.threadTitles) {
20452
- Object.assign(threadTitles, page.threadTitles);
20453
- }
20454
- }
20455
- return { spans, threadTitles };
20375
+ return { spans };
20456
20376
  }
20457
20377
  const useTraces = ({ filters, listMode = "traces" }) => {
20458
20378
  const client = react.useMastraClient();
@@ -22042,7 +21962,6 @@ exports.getToPreviousEntryFn = getToPreviousEntryFn;
22042
21962
  exports.getToPreviousItemFn = getToPreviousItemFn;
22043
21963
  exports.getTokenLimitMessage = getTokenLimitMessage;
22044
21964
  exports.getTracePropertyFilterTokens = getTracePropertyFilterTokens;
22045
- exports.groupTracesByThread = groupTracesByThread;
22046
21965
  exports.hasAnyLogsFilterParams = hasAnyLogsFilterParams;
22047
21966
  exports.hasAnyMetricsFilterParams = hasAnyMetricsFilterParams;
22048
21967
  exports.hasAnyTraceFilterParams = hasAnyTraceFilterParams;
@@ -22051,6 +21970,7 @@ exports.hoverEffects = hoverEffects;
22051
21970
  exports.inputVariants = inputVariants;
22052
21971
  exports.is401UnauthorizedError = is401UnauthorizedError;
22053
21972
  exports.is403ForbiddenError = is403ForbiddenError;
21973
+ exports.isBranchesNotSupportedError = isBranchesNotSupportedError;
22054
21974
  exports.isNonRetryableError = isNonRetryableError;
22055
21975
  exports.isObjectEmpty = isObjectEmpty;
22056
21976
  exports.isRule = isRule;