@dbx-tools/ui-mastra 0.6.222 → 0.6.224

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/README.md CHANGED
@@ -26,8 +26,8 @@ Key features:
26
26
  resumed-stream handling. An email-shaped input (the `send_email` tool)
27
27
  renders as a formatted To / Cc / Subject / Markdown-body preview rather than
28
28
  raw JSON.
29
- - Complete native tool input/results retained behind expandable Request and
30
- Response rows in each tool pill.
29
+ - Complete native tool input/results retained behind expandable,
30
+ syntax-highlighted JSON Request and Response rows in each tool pill.
31
31
  - Typed per-turn application context through Mastra's native `RequestContext`
32
32
  and server-side `requestContextSchema`.
33
33
  - Inline embed rendering for `[chart:<id>]` and `[data:<id>]` markers produced by
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.6.222";
6
+ export const PACKAGE_VERSION = "0.6.224";
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";
@@ -52,7 +52,7 @@ export type { DataRow } from "./src/react/data-grid.tsx";
52
52
  export { MarkdownWithEmbeds } from "./src/react/embed-slots.tsx";
53
53
  export { ExportMenu } from "./src/react/export-menu.tsx";
54
54
  export { FeedbackControls } from "./src/react/feedback-controls.tsx";
55
- export { AssistantMarkdown, ToolMarkdown, SqlBlock } from "./src/react/markdown.tsx";
55
+ export { AssistantMarkdown, ToolMarkdown, SqlBlock, JsonBlock } from "./src/react/markdown.tsx";
56
56
  export type { MastraAssistantMode, MastraAssistantSide, MastraAssistantLauncherPosition, MastraAssistantResizeOptions, MastraAssistantLauncherOptions, MastraAssistantController, MastraAssistantProps } from "./src/react/mastra-assistant.tsx";
57
57
  export { useMastraChat, MastraChat } from "./src/react/mastra-chat.tsx";
58
58
  export type { UseMastraChatOptions, MastraChatProps } from "./src/react/mastra-chat.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.6.222",
35
- "@dbx-tools/shared-genie": "0.6.222",
36
- "@dbx-tools/shared-mastra": "0.6.222",
37
- "@dbx-tools/shared-model": "0.6.222",
38
- "@dbx-tools/ui-appkit": "0.6.222",
39
- "@dbx-tools/ui-branding": "0.6.222",
34
+ "@dbx-tools/shared-core": "0.6.224",
35
+ "@dbx-tools/shared-genie": "0.6.224",
36
+ "@dbx-tools/shared-mastra": "0.6.224",
37
+ "@dbx-tools/shared-model": "0.6.224",
38
+ "@dbx-tools/ui-appkit": "0.6.224",
39
+ "@dbx-tools/ui-branding": "0.6.224",
40
40
  "@mastra/client-js": "1.50.0",
41
41
  "@tanstack/react-table": "^8.21.3",
42
42
  "ai": "^5.0.0",
@@ -52,7 +52,7 @@
52
52
  "publishConfig": {
53
53
  "access": "public"
54
54
  },
55
- "version": "0.6.222",
55
+ "version": "0.6.224",
56
56
  "type": "module",
57
57
  "exports": {
58
58
  "./react": "./src/react/index.ts",
@@ -21,7 +21,7 @@ import { createShikiPlugin, highlightToHtml } from "../support/shiki-plugin.ts";
21
21
 
22
22
  // Markdown rendering for the chat: the streaming `Streamdown` engine
23
23
  // wired with shiki highlighting and AppKit table primitives, plus the
24
- // standalone syntax-highlighted SQL block and a compact copy button.
24
+ // standalone syntax-highlighted SQL/JSON blocks and a compact copy button.
25
25
 
26
26
  /**
27
27
  * Minimal hast node shape we walk to lift a GFM markdown table out of
@@ -181,6 +181,27 @@ const TOOL_MARKDOWN_COMPONENTS = {
181
181
  */
182
182
  const SHIKI_PLUGIN = { code: createShikiPlugin() };
183
183
 
184
+ /** Resolve syntax-highlighted HTML while preserving plaintext during lazy load. */
185
+ function useHighlightedHtml(source: string, language: string): string | null {
186
+ const [highlighted, setHighlighted] = useState<{
187
+ source: string;
188
+ language: string;
189
+ html: string;
190
+ } | null>(null);
191
+ useEffect(() => {
192
+ let active = true;
193
+ void highlightToHtml(source, language).then((result) => {
194
+ if (active) setHighlighted({ source, language, html: result });
195
+ });
196
+ return () => {
197
+ active = false;
198
+ };
199
+ }, [language, source]);
200
+ return highlighted?.source === source && highlighted.language === language
201
+ ? highlighted.html
202
+ : null;
203
+ }
204
+
184
205
  /**
185
206
  * Per-word fade-in applied while a reply is still streaming. Streamdown
186
207
  * wraps each newly arrived token in a `[data-sd-animate]` span and only
@@ -346,17 +367,12 @@ const CopyButton = ({ value, className }: { value: string; className?: string })
346
367
  */
347
368
  export const SqlBlock = ({ sql }: { sql: string }) => {
348
369
  const [formatted, setFormatted] = useState(sql);
349
- const [html, setHtml] = useState<string | null>(null);
370
+ const html = useHighlightedHtml(formatted, "sql");
350
371
  useEffect(() => {
351
372
  let active = true;
352
373
  setFormatted(sql);
353
- setHtml(null);
354
374
  void _prettySql(sql).then((source) => {
355
- if (!active) return;
356
- setFormatted(source);
357
- void highlightToHtml(source, "sql").then((result) => {
358
- if (active) setHtml(result);
359
- });
375
+ if (active) setFormatted(source);
360
376
  });
361
377
  return () => {
362
378
  active = false;
@@ -378,3 +394,21 @@ export const SqlBlock = ({ sql }: { sql: string }) => {
378
394
  </div>
379
395
  );
380
396
  };
397
+
398
+ /**
399
+ * Render formatted JSON with the same lazily loaded Shiki runtime used by
400
+ * SQL and fenced Markdown code blocks.
401
+ */
402
+ export const JsonBlock = ({ json, className }: { json: string; className?: string }) => {
403
+ const html = useHighlightedHtml(json, "json");
404
+ return (
405
+ <pre
406
+ className={cn(
407
+ "max-w-full overflow-auto whitespace-pre-wrap break-words font-mono text-[11px] leading-relaxed",
408
+ className,
409
+ )}
410
+ >
411
+ {html === null ? <code>{json}</code> : <code dangerouslySetInnerHTML={{ __html: html }} />}
412
+ </pre>
413
+ );
414
+ };
@@ -8,7 +8,7 @@ import {
8
8
  cn,
9
9
  } from "@dbx-tools/ui-appkit/react";
10
10
  import { CheckIcon, ChevronDownIcon, XIcon } from "lucide-react";
11
- import { SqlBlock, ToolMarkdown } from "./markdown.tsx";
11
+ import { JsonBlock, SqlBlock, ToolMarkdown } from "./markdown.tsx";
12
12
  import type { ToolEvent, ToolProgress } from "./types.ts";
13
13
 
14
14
  // Consolidated tool-session pill and its Genie progress detail view:
@@ -465,9 +465,10 @@ const RawToolPayload = ({ label, value }: { label: "Request" | "Response"; value
465
465
  <span>{label}</span>
466
466
  </CollapsibleTrigger>
467
467
  <CollapsibleContent>
468
- <pre className="max-h-80 overflow-auto whitespace-pre-wrap break-words border-t border-border/50 px-2 py-2 font-mono text-[11px] leading-relaxed text-foreground">
469
- {formatRawToolPayload(value)}
470
- </pre>
468
+ <JsonBlock
469
+ json={formatRawToolPayload(value)}
470
+ className="max-h-80 border-t border-border/50 px-2 py-2 text-foreground"
471
+ />
471
472
  </CollapsibleContent>
472
473
  </Collapsible>
473
474
  );