@dbx-tools/ui-mastra 0.9.4 → 0.9.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.
package/index.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  // Hand edits are overwritten on the next watch; this file is read-only.
4
4
 
5
5
  export const PACKAGE_IDENTIFIER = "@dbx-tools/ui-mastra";
6
- export const PACKAGE_VERSION = "0.9.4";
6
+ export const PACKAGE_VERSION = "0.9.6";
7
7
  export * as reactBubbles from "./src/react/bubbles.tsx";
8
8
  export * as reactChatApprovals from "./src/react/chat-approvals.ts";
9
9
  export * as reactChatComposer from "./src/react/chat-composer.tsx";
package/package.json CHANGED
@@ -31,12 +31,12 @@
31
31
  "react-dom": "~19.2.4"
32
32
  },
33
33
  "dependencies": {
34
- "@dbx-tools/shared-core": "^0.9.4",
35
- "@dbx-tools/shared-genie": "^0.9.4",
36
- "@dbx-tools/shared-mastra": "^0.9.4",
37
- "@dbx-tools/shared-model": "^0.9.4",
38
- "@dbx-tools/ui-appkit": "^0.9.4",
39
- "@dbx-tools/ui-branding": "^0.9.4",
34
+ "@dbx-tools/shared-core": "^0.9.6",
35
+ "@dbx-tools/shared-genie": "^0.9.6",
36
+ "@dbx-tools/shared-mastra": "^0.9.6",
37
+ "@dbx-tools/shared-model": "^0.9.6",
38
+ "@dbx-tools/ui-appkit": "^0.9.6",
39
+ "@dbx-tools/ui-branding": "^0.9.6",
40
40
  "@mastra/client-js": "1.50.0",
41
41
  "@mastra/core": "1.71.0",
42
42
  "@tanstack/react-table": "^8.21.3",
@@ -53,7 +53,7 @@
53
53
  "publishConfig": {
54
54
  "access": "public"
55
55
  },
56
- "version": "0.9.4",
56
+ "version": "0.9.6",
57
57
  "type": "module",
58
58
  "exports": {
59
59
  "./react": "./src/react/index.ts",
@@ -1,5 +1,5 @@
1
- import { convertMessages } from "@mastra/core/agent/message-list";
2
1
  import type { ListMemoryThreadMessagesResponse } from "@mastra/client-js";
2
+ import { convertMessages } from "@mastra/core/agent/message-list";
3
3
  import type { UIMessage } from "ai";
4
4
 
5
5
  /** Convert a newest-first native memory page to chronological AI SDK UI messages. */
@@ -1,4 +1,5 @@
1
- import { string } from "@dbx-tools/shared-core";
1
+ import { stringUtils } from "@dbx-tools/shared-core";
2
+ import type { ReasoningEffort } from "@dbx-tools/shared-model";
2
3
  import {
3
4
  Button,
4
5
  DropdownMenu,
@@ -36,7 +37,7 @@ interface ModelSelectorProps {
36
37
 
37
38
  /** Convert a normalized family token into a compact menu label. */
38
39
  function familyLabel(family: string): string {
39
- return family.length <= 3 ? family.toUpperCase() : string.toLabel(family);
40
+ return family.length <= 3 ? family.toUpperCase() : stringUtils.toLabel(family);
40
41
  }
41
42
 
42
43
  /** Resolve the label shown for a model endpoint. */
@@ -50,12 +51,12 @@ const ReasoningControl = ({
50
51
  value,
51
52
  onChange,
52
53
  }: {
53
- efforts: string[];
54
+ efforts: ReasoningEffort[];
54
55
  value: ChatViewProps["reasoningEffort"];
55
56
  onChange: NonNullable<ChatViewProps["onReasoningEffortChange"]>;
56
57
  }) => {
57
58
  const selectedIndex = value === undefined ? 0 : Math.max(0, efforts.indexOf(value) + 1);
58
- const selectedLabel = value === undefined ? "Auto" : string.toLabel(value);
59
+ const selectedLabel = value === undefined ? "Auto" : stringUtils.toLabel(value);
59
60
 
60
61
  return (
61
62
  <div className="space-y-2 px-2 py-1.5">
@@ -28,8 +28,8 @@ import {
28
28
  } from "lucide-react";
29
29
  import { useCallback, useId, useLayoutEffect, useRef, useState } from "react";
30
30
  import { autosizeComposerTextarea, observeComposerWidth } from "./_composer-autosize.ts";
31
- import { ExportMenu } from "./export-menu.tsx";
32
31
  import { ModelSelector } from "./_model-selector.tsx";
32
+ import { ExportMenu } from "./export-menu.tsx";
33
33
  import { SuggestionPills } from "./suggestion-pills.tsx";
34
34
  import type { ChatViewProps } from "./types.ts";
35
35
 
@@ -1,4 +1,4 @@
1
- import { error as sharedError, log } from "@dbx-tools/shared-core";
1
+ import { errorUtils, log } from "@dbx-tools/shared-core";
2
2
  import type { UIMessage } from "ai";
3
3
  import { useCallback, useRef } from "react";
4
4
  import type { ThreadSessionUpdater } from "./chat-sessions.ts";
@@ -51,7 +51,7 @@ export function useChatFeedback({
51
51
  } catch (error) {
52
52
  logger.error("feedback error", {
53
53
  traceId,
54
- error: sharedError.errorMessage(error),
54
+ error: errorUtils.errorMessage(error),
55
55
  });
56
56
  }
57
57
  },
@@ -1,13 +1,13 @@
1
- import { error as sharedError, log } from "@dbx-tools/shared-core";
1
+ import { errorUtils, log } from "@dbx-tools/shared-core";
2
2
  import type { UIMessage } from "ai";
3
3
  import { useCallback, useEffect, useRef, useState } from "react";
4
+ import { toChronologicalUiMessages } from "./_history-messages.ts";
4
5
  import type {
5
6
  ThreadMessageWriter,
6
7
  ThreadSessionReader,
7
8
  ThreadSessionUpdater,
8
9
  } from "./chat-sessions.ts";
9
10
  import type { PendingApproval } from "./types.ts";
10
- import { toChronologicalUiMessages } from "./_history-messages.ts";
11
11
  import type { MastraPluginClient } from "../support/mastra-client.ts";
12
12
 
13
13
  const HISTORY_PAGE_SIZE = 20;
@@ -115,7 +115,7 @@ export function useChatHistory({
115
115
  .catch((error: unknown) => {
116
116
  if ((error as { name?: string }).name === "AbortError") throw error;
117
117
  logger.warn("suspended-run discovery error", {
118
- error: sharedError.errorMessage(error),
118
+ error: errorUtils.errorMessage(error),
119
119
  });
120
120
  return { runs: [], total: 0 };
121
121
  });
@@ -137,7 +137,7 @@ export function useChatHistory({
137
137
  .catch((error: unknown) => {
138
138
  if (cancelled || (error as { name?: string }).name === "AbortError") return;
139
139
  logger.error("history load error", {
140
- error: sharedError.errorMessage(error),
140
+ error: errorUtils.errorMessage(error),
141
141
  });
142
142
  updateSession(threadId, (current) => ({
143
143
  ...current,
@@ -178,7 +178,7 @@ export function useChatHistory({
178
178
  .catch((error: unknown) => {
179
179
  logger.error("history load-more error", {
180
180
  page,
181
- error: sharedError.errorMessage(error),
181
+ error: errorUtils.errorMessage(error),
182
182
  });
183
183
  updateSession(threadId, (current) => ({
184
184
  ...current,
@@ -1,4 +1,4 @@
1
- import { error as sharedError } from "@dbx-tools/shared-core";
1
+ import { errorUtils } from "@dbx-tools/shared-core";
2
2
  import {
3
3
  Alert,
4
4
  AlertDescription,
@@ -269,7 +269,7 @@ export const ChatTranscript = ({
269
269
  <AlertTitle>Something went wrong</AlertTitle>
270
270
  <AlertDescription>
271
271
  {error
272
- ? sharedError.errorMessage(error)
272
+ ? errorUtils.errorMessage(error)
273
273
  : "The assistant ran into an error. Please try again."}
274
274
  </AlertDescription>
275
275
  </Alert>
@@ -1,4 +1,4 @@
1
- import { string } from "@dbx-tools/shared-core";
1
+ import { stringUtils } from "@dbx-tools/shared-core";
2
2
  import {
3
3
  Button,
4
4
  DropdownMenu,
@@ -82,8 +82,8 @@ export function renderDataCell(value: unknown): React.ReactNode {
82
82
  * column id, accessor key, and CSV header, so only the on-screen label
83
83
  * is prettified.
84
84
  */
85
- export function humanizeLabel(value: string, options?: string.TokenizeOptions): string {
86
- return string.toLabel(value, options);
85
+ export function humanizeLabel(value: string, options?: stringUtils.TokenizeOptions): string {
86
+ return stringUtils.toLabel(value, options);
87
87
  }
88
88
 
89
89
  /**
@@ -1,4 +1,4 @@
1
- import { marker as sharedMarkers, type ParsedMarker } from "@dbx-tools/shared-mastra";
1
+ import { markers, type ParsedMarker } from "@dbx-tools/shared-mastra";
2
2
  import { Spinner } from "@dbx-tools/ui-appkit/react";
3
3
  import { ClockIcon } from "lucide-react";
4
4
  import { lazy, Suspense, useMemo, useRef } from "react";
@@ -189,7 +189,7 @@ type RenderSegment =
189
189
  * resolves to a slot.
190
190
  */
191
191
  const markerSegment = (marker: ParsedMarker): RenderSegment => {
192
- if (!sharedMarkers.isUuid(marker.id)) return { kind: "text", text: "" };
192
+ if (!markers.isUuid(marker.id)) return { kind: "text", text: "" };
193
193
  switch (marker.type) {
194
194
  case "chart":
195
195
  return { kind: "chart", chartId: marker.id };
@@ -206,7 +206,7 @@ const splitTextWithEmbeds = (text: string): RenderSegment[] => {
206
206
  // `parseMarkers` yields hits in source order with no overlaps (one
207
207
  // regex pass), so the spans splice in directly - no sort or
208
208
  // overlap guard needed.
209
- for (const marker of sharedMarkers.parseMarkers(text)) {
209
+ for (const marker of markers.parseMarkers(text)) {
210
210
  if (marker.start > lastIdx) {
211
211
  segments.push({ kind: "text", text: text.slice(lastIdx, marker.start) });
212
212
  }
@@ -250,7 +250,7 @@ export const MarkdownWithEmbeds = ({
250
250
  text: string;
251
251
  streaming?: boolean;
252
252
  }) => {
253
- const segments = splitTextWithEmbeds(sharedMarkers.stripIncompleteMarkerTail(text));
253
+ const segments = splitTextWithEmbeds(markers.stripIncompleteMarkerTail(text));
254
254
  return (
255
255
  <>
256
256
  {segments.map((seg, i) => {
@@ -1,4 +1,4 @@
1
- import { error as sharedError, hash, log } from "@dbx-tools/shared-core";
1
+ import { errorUtils, hash, log } from "@dbx-tools/shared-core";
2
2
  import type { ReasoningEffort } from "@dbx-tools/shared-model";
3
3
  import { useBrand } from "@dbx-tools/ui-branding/react";
4
4
  import type { UIMessage } from "ai";
@@ -470,11 +470,11 @@ export const useMastraChat = <TValues extends Record<string, unknown> = Record<s
470
470
  } catch (caught) {
471
471
  if (getSession(threadId).runToken !== token) return;
472
472
  logger.error("stream error", {
473
- error: sharedError.errorMessage(caught),
473
+ error: errorUtils.errorMessage(caught),
474
474
  });
475
475
  updateSession(threadId, (session) => ({
476
476
  ...session,
477
- error: sharedError.toError(caught),
477
+ error: errorUtils.toError(caught),
478
478
  status: "error",
479
479
  abortController: session.abortController === controller ? null : session.abortController,
480
480
  runId: runIdRef.current,
@@ -678,7 +678,7 @@ export const useMastraChat = <TValues extends Record<string, unknown> = Record<s
678
678
  logger.info("history cleared", { threadId });
679
679
  } catch (error) {
680
680
  logger.error("history clear error", {
681
- error: sharedError.errorMessage(error),
681
+ error: errorUtils.errorMessage(error),
682
682
  });
683
683
  }
684
684
  resetSession(threadId, true);
@@ -719,7 +719,7 @@ export const useMastraChat = <TValues extends Record<string, unknown> = Record<s
719
719
  } catch (error) {
720
720
  logger.error("thread delete error", {
721
721
  threadId,
722
- error: sharedError.errorMessage(error),
722
+ error: errorUtils.errorMessage(error),
723
723
  });
724
724
  }
725
725
  removeSession(threadId);
@@ -764,7 +764,7 @@ export const useMastraChat = <TValues extends Record<string, unknown> = Record<s
764
764
  } catch (error) {
765
765
  logger.error("thread rename error", {
766
766
  threadId,
767
- error: sharedError.errorMessage(error),
767
+ error: errorUtils.errorMessage(error),
768
768
  });
769
769
  setRenamedThreads((prev) => {
770
770
  if (!(threadId in prev)) return prev;
@@ -807,11 +807,11 @@ export const useMastraChat = <TValues extends Record<string, unknown> = Record<s
807
807
  .catch((error: unknown) => {
808
808
  logger.error("regenerate cleanup error", {
809
809
  threadId,
810
- error: sharedError.errorMessage(error),
810
+ error: errorUtils.errorMessage(error),
811
811
  });
812
812
  updateSession(threadId, (session) => ({
813
813
  ...session,
814
- error: sharedError.toError(error),
814
+ error: errorUtils.toError(error),
815
815
  status: "error",
816
816
  }));
817
817
  });
@@ -877,7 +877,7 @@ export const useMastraChat = <TValues extends Record<string, unknown> = Record<s
877
877
  } catch (error) {
878
878
  logger.error("conversation export error", {
879
879
  format,
880
- error: sharedError.errorMessage(error),
880
+ error: errorUtils.errorMessage(error),
881
881
  });
882
882
  }
883
883
  },
@@ -899,7 +899,7 @@ export const useMastraChat = <TValues extends Record<string, unknown> = Record<s
899
899
  } catch (error) {
900
900
  logger.error("message export error", {
901
901
  format,
902
- error: sharedError.errorMessage(error),
902
+ error: errorUtils.errorMessage(error),
903
903
  });
904
904
  }
905
905
  },
@@ -1,4 +1,4 @@
1
- import { string } from "@dbx-tools/shared-core";
1
+ import { stringUtils } from "@dbx-tools/shared-core";
2
2
  import { genieModel } from "@dbx-tools/shared-genie";
3
3
  import {
4
4
  Collapsible,
@@ -26,7 +26,7 @@ import type { ToolEvent, ToolProgress } from "./types.ts";
26
26
  * `ask_genie_sales` -> `Ask Genie Sales`
27
27
  * `myCoolTool` -> `My Cool Tool`
28
28
  */
29
- export const humanizeToolName = (toolName: string): string => string.toLabel(toolName);
29
+ export const humanizeToolName = (toolName: string): string => stringUtils.toLabel(toolName);
30
30
 
31
31
  /**
32
32
  * Track the freshest status label a running tool has published so the
@@ -41,7 +41,7 @@ const runningLabelFor = (event: ToolEvent): string => {
41
41
  .reverse()
42
42
  .find((p): p is Extract<ToolProgress, { type: "status" }> => p.type === "status");
43
43
  return latest
44
- ? string.capitalize(genieModel.humanizeStatus(latest.status))
44
+ ? stringUtils.capitalize(genieModel.humanizeStatus(latest.status))
45
45
  : `Calling ${humanizeToolName(event.toolName)}`;
46
46
  };
47
47
 
@@ -243,7 +243,7 @@ const askGenieQuestion = (event: ToolEvent): string | undefined => {
243
243
  * `THOUGHT_TYPE_UNDERSTANDING` -> `Understanding`
244
244
  */
245
245
  const humanizeThoughtType = (kind: string): string =>
246
- string.toLabel(kind.replace(/^THOUGHT_TYPE_/i, ""));
246
+ stringUtils.toLabel(kind.replace(/^THOUGHT_TYPE_/i, ""));
247
247
 
248
248
  /**
249
249
  * Genie attaches one of three payload kinds per attachment slot:
@@ -23,8 +23,8 @@
23
23
  * @module
24
24
  */
25
25
 
26
- import { string } from "@dbx-tools/shared-core";
27
- import { marker as sharedMarkers, type Chart, type StatementData } from "@dbx-tools/shared-mastra";
26
+ import { stringUtils } from "@dbx-tools/shared-core";
27
+ import { markers, type Chart, type StatementData } from "@dbx-tools/shared-mastra";
28
28
  import type { UIMessage } from "ai";
29
29
  import type { EChartsCoreOption } from "echarts";
30
30
  import { normalizeChartOption } from "./chart-option.ts";
@@ -197,11 +197,11 @@ type Segment =
197
197
  function splitSegments(text: string): Segment[] {
198
198
  const segments: Segment[] = [];
199
199
  let last = 0;
200
- for (const marker of sharedMarkers.parseMarkers(text)) {
200
+ for (const marker of markers.parseMarkers(text)) {
201
201
  if (marker.start > last) {
202
202
  segments.push({ kind: "text", text: text.slice(last, marker.start) });
203
203
  }
204
- if (sharedMarkers.isUuid(marker.id) && (marker.type === "chart" || marker.type === "data")) {
204
+ if (markers.isUuid(marker.id) && (marker.type === "chart" || marker.type === "data")) {
205
205
  segments.push({ kind: marker.type, id: marker.id });
206
206
  }
207
207
  last = marker.end;
@@ -226,7 +226,7 @@ function messageText(message: UIMessage): string {
226
226
  function roleLabel(role: UIMessage["role"], userLabel: string): string {
227
227
  if (role === "user") return userLabel;
228
228
  if (role === "assistant") return "Assistant";
229
- return string.capitalize(role);
229
+ return stringUtils.capitalize(role);
230
230
  }
231
231
 
232
232
  /* --------------------------------- HTML ---------------------------------- */
@@ -335,7 +335,7 @@ async function chartSvg(resolver: EmbedResolver, id: string): Promise<string | n
335
335
  async function dataTableHtml(resolver: EmbedResolver, id: string): Promise<string | null> {
336
336
  const data = await safeStatement(resolver, id);
337
337
  if (!data || data.rows.length === 0) return null;
338
- const head = data.columns.map((c) => `<th>${escapeHtml(string.toLabel(c))}</th>`).join("");
338
+ const head = data.columns.map((c) => `<th>${escapeHtml(stringUtils.toLabel(c))}</th>`).join("");
339
339
  const body = data.rows
340
340
  .map(
341
341
  (row) =>
@@ -403,7 +403,7 @@ function chartTitle(chart: Chart): string {
403
403
  async function dataTableMarkdown(resolver: EmbedResolver, id: string): Promise<string | null> {
404
404
  const data = await safeStatement(resolver, id);
405
405
  if (!data || data.rows.length === 0) return null;
406
- const header = `| ${data.columns.map((c) => mdCell(string.toLabel(c))).join(" | ")} |`;
406
+ const header = `| ${data.columns.map((c) => mdCell(stringUtils.toLabel(c))).join(" | ")} |`;
407
407
  const sep = `| ${data.columns.map(() => "---").join(" | ")} |`;
408
408
  const rows = data.rows.map(
409
409
  (row) => `| ${data.columns.map((c) => mdCell(cellText(row[c]))).join(" | ")} |`,
@@ -448,11 +448,11 @@ function mdCell(value: string): string {
448
448
  }
449
449
 
450
450
  /** Escape HTML-significant characters (from the shared string utils). */
451
- const escapeHtml = string.escapeHtml;
451
+ const escapeHtml = stringUtils.escapeHtml;
452
452
 
453
453
  /** Turn a title into a safe, lowercase filename stem. */
454
454
  function slugify(value: string): string {
455
- return string.toSlugWithOptions({ maxLength: 60 }, value) || "conversation";
455
+ return stringUtils.toSlugWithOptions({ maxLength: 60 }, value) || "conversation";
456
456
  }
457
457
 
458
458
  /**
@@ -1,4 +1,4 @@
1
- import { error as sharedError } from "@dbx-tools/shared-core";
1
+ import { errorUtils } from "@dbx-tools/shared-core";
2
2
  import {
3
3
  feedback,
4
4
  override,
@@ -606,7 +606,7 @@ export const useMastraModels = (
606
606
  })
607
607
  .catch((e: unknown) => {
608
608
  if (controller.signal.aborted) return;
609
- setError(sharedError.toError(e));
609
+ setError(errorUtils.toError(e));
610
610
  })
611
611
  .finally(() => {
612
612
  if (!controller.signal.aborted) setLoading(false);
@@ -765,7 +765,7 @@ export const useMastraThreads = (
765
765
  })
766
766
  .catch((e: unknown) => {
767
767
  if (controller.signal.aborted || (e as { name?: string }).name === "AbortError") return;
768
- setError(sharedError.toError(e));
768
+ setError(errorUtils.toError(e));
769
769
  setThreads([]);
770
770
  })
771
771
  .finally(() => {
@@ -930,7 +930,7 @@ function useByIdFetch<T>(
930
930
  })
931
931
  .catch((e: unknown) => {
932
932
  if (cancelled) return;
933
- setError(sharedError.toError(e));
933
+ setError(errorUtils.toError(e));
934
934
  setLoading(false);
935
935
  });
936
936
 
@@ -1,4 +1,4 @@
1
- import { string } from "@dbx-tools/shared-core";
1
+ import { stringUtils } from "@dbx-tools/shared-core";
2
2
  import type { BundledLanguage, BundledTheme } from "shiki";
3
3
  import type { HighlighterCore } from "shiki/core";
4
4
  import type { CodeHighlighterPlugin } from "streamdown";
@@ -59,7 +59,7 @@ function highlightTokens(h: HighlighterCore, code: string, language: BundledLang
59
59
  }
60
60
 
61
61
  /** Escape HTML-significant characters (from the shared string utils). */
62
- const escapeHtml = string.escapeHtml;
62
+ const escapeHtml = stringUtils.escapeHtml;
63
63
 
64
64
  /**
65
65
  * Highlight `code` into minimal inline HTML: one colored `<span>` per