@mastra/playground-ui 49.0.0-alpha.3 → 49.0.0-alpha.4

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 (30) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/code-BJMC6T9D.cjs +78 -0
  3. package/dist/code-BJMC6T9D.cjs.map +1 -0
  4. package/dist/code-DRGJVroV.js +57 -0
  5. package/dist/code-DRGJVroV.js.map +1 -0
  6. package/dist/{code-block-Dn0K3DkE.cjs → code-block-BZUY8Fj9.cjs} +2 -2
  7. package/dist/{code-block-Dn0K3DkE.cjs.map → code-block-BZUY8Fj9.cjs.map} +1 -1
  8. package/dist/{code-block-DqKXZajq.js → code-block-V4wpmbud.js} +2 -2
  9. package/dist/{code-block-DqKXZajq.js.map → code-block-V4wpmbud.js.map} +1 -1
  10. package/dist/components/Code.cjs.js +1 -1
  11. package/dist/components/Code.es.js +1 -1
  12. package/dist/components/CodeBlock.cjs.js +1 -1
  13. package/dist/components/CodeBlock.es.js +1 -1
  14. package/dist/components/MarkdownRenderer.cjs.js +1 -1
  15. package/dist/components/MarkdownRenderer.es.js +1 -1
  16. package/dist/components/ai/plan.cjs.js +1 -1
  17. package/dist/components/ai/plan.es.js +1 -1
  18. package/dist/{markdown-renderer-DmYYQHxu.js → markdown-renderer-CB2WMnTG.js} +9 -4
  19. package/dist/markdown-renderer-CB2WMnTG.js.map +1 -0
  20. package/dist/{markdown-renderer-D1vSFfp9.cjs → markdown-renderer-DvJfqb-D.cjs} +9 -4
  21. package/dist/markdown-renderer-DvJfqb-D.cjs.map +1 -0
  22. package/dist/src/ds/components/Code/code.d.ts +5 -0
  23. package/dist/src/ds/components/MarkdownRenderer/markdown-renderer.d.ts +5 -1
  24. package/package.json +7 -7
  25. package/dist/code-Cj09LVys.js +0 -47
  26. package/dist/code-Cj09LVys.js.map +0 -1
  27. package/dist/code-FZwLnf_f.cjs +0 -68
  28. package/dist/code-FZwLnf_f.cjs.map +0 -1
  29. package/dist/markdown-renderer-D1vSFfp9.cjs.map +0 -1
  30. package/dist/markdown-renderer-DmYYQHxu.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # @mastra/playground-ui
2
2
 
3
+ ## 49.0.0-alpha.4
4
+
5
+ ### Patch Changes
6
+
7
+ - Fixed code blocks flickering between colored and plain text while an agent streams a fenced snippet. The part already highlighted now keeps its colors, and only the characters that just landed show uncolored until highlighting catches up. ([#21415](https://github.com/mastra-ai/mastra/pull/21415))
8
+
9
+ - Improved chat responsiveness on long conversations. `MarkdownRenderer` is memoized, so a streaming reply no longer re-parses the markdown of every message already on screen on each chunk it receives — only the message actually being written is re-parsed. ([#21416](https://github.com/mastra-ai/mastra/pull/21416))
10
+
11
+ - Updated dependencies [[`be31796`](https://github.com/mastra-ai/mastra/commit/be3179624ad5f77cff5fa342cd08046bf7605283), [`79dd7c2`](https://github.com/mastra-ai/mastra/commit/79dd7c261ee6be1fafedd4651959394db21d2cba), [`b9a28ec`](https://github.com/mastra-ai/mastra/commit/b9a28ecf7acdc0cb7a543d5b660f9fbee301df9a), [`be31796`](https://github.com/mastra-ai/mastra/commit/be3179624ad5f77cff5fa342cd08046bf7605283)]:
12
+ - @mastra/client-js@1.40.0-alpha.4
13
+ - @mastra/core@1.59.0-alpha.4
14
+ - @mastra/react@1.4.3-alpha.4
15
+
3
16
  ## 49.0.0-alpha.3
4
17
 
5
18
  ### Patch Changes
@@ -0,0 +1,78 @@
1
+ 'use strict';
2
+
3
+ const jsxRuntime = require('react/jsx-runtime');
4
+ const React = require('react');
5
+ const highlight = require('./highlight-CEt2vhD8.cjs');
6
+
7
+ function _interopNamespaceDefault(e) {
8
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: 'Module' } });
9
+ if (e) {
10
+ for (const k in e) {
11
+ if (k !== 'default') {
12
+ const d = Object.getOwnPropertyDescriptor(e, k);
13
+ Object.defineProperty(n, k, d.get ? d : {
14
+ enumerable: true,
15
+ get: () => e[k]
16
+ });
17
+ }
18
+ }
19
+ }
20
+ n.default = e;
21
+ return Object.freeze(n);
22
+ }
23
+
24
+ const React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
25
+
26
+ function tokenStyle(token) {
27
+ if (token.htmlStyle && typeof token.htmlStyle === "object") {
28
+ return token.htmlStyle;
29
+ }
30
+ return token.color ? { color: token.color } : void 0;
31
+ }
32
+ function usableHighlight(highlighted, code, lang) {
33
+ if (!highlighted || highlighted.lang !== lang) return null;
34
+ return code.startsWith(highlighted.code) ? highlighted : null;
35
+ }
36
+ const Code = React__namespace.memo(function Code2({ code, lang, ...props }) {
37
+ const [highlighted, setHighlighted] = React__namespace.useState(null);
38
+ React__namespace.useEffect(() => {
39
+ if (!lang) {
40
+ setHighlighted(null);
41
+ return;
42
+ }
43
+ let cancelled = false;
44
+ void highlight.highlight(code, lang).then((tokens) => {
45
+ if (!cancelled && tokens?.length) setHighlighted({ code, lang, tokens });
46
+ }).catch(() => {
47
+ });
48
+ return () => {
49
+ cancelled = true;
50
+ };
51
+ }, [code, lang]);
52
+ const usable = usableHighlight(highlighted, code, lang);
53
+ if (!usable) {
54
+ return /* @__PURE__ */ jsxRuntime.jsx("pre", { ...props, children: code });
55
+ }
56
+ const tail = code.slice(usable.code.length);
57
+ let codeOffset = 0;
58
+ return /* @__PURE__ */ jsxRuntime.jsx("pre", { ...props, children: /* @__PURE__ */ jsxRuntime.jsxs("code", { children: [
59
+ usable.tokens.map((line, lineIndex) => {
60
+ const lineOffset = codeOffset;
61
+ let tokenOffset = lineOffset;
62
+ const tokenSpans = line.map((token) => {
63
+ const key = tokenOffset;
64
+ tokenOffset += token.content.length;
65
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shiki-token", style: tokenStyle(token), children: token.content }, key);
66
+ });
67
+ codeOffset = tokenOffset + 1;
68
+ return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
69
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: tokenSpans }),
70
+ lineIndex !== usable.tokens.length - 1 && "\n"
71
+ ] }, lineOffset);
72
+ }),
73
+ tail
74
+ ] }) });
75
+ });
76
+
77
+ exports.Code = Code;
78
+ //# sourceMappingURL=code-BJMC6T9D.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-BJMC6T9D.cjs","sources":["../src/ds/components/Code/code.tsx"],"sourcesContent":["import * as React from 'react';\nimport type { ThemedToken } from 'shiki/core';\n\nimport { highlight } from '../CodeEditor/highlight';\n\nexport interface CodeProps extends React.HTMLAttributes<HTMLPreElement> {\n code: string;\n lang?: string;\n}\n\nfunction tokenStyle(token: ThemedToken): React.CSSProperties | undefined {\n if (token.htmlStyle && typeof token.htmlStyle === 'object') {\n return token.htmlStyle as React.CSSProperties;\n }\n\n return token.color ? { color: token.color } : undefined;\n}\n\ninterface Highlighted {\n code: string;\n lang: string;\n tokens: ThemedToken[][];\n}\n\n/** Colors from an earlier pass still hold when the new code only appends to the old. */\nfunction usableHighlight(highlighted: Highlighted | null, code: string, lang?: string): Highlighted | null {\n if (!highlighted || highlighted.lang !== lang) return null;\n return code.startsWith(highlighted.code) ? highlighted : null;\n}\n\n/**\n * Low-level shiki token renderer shared by `CodeBlock` and `MarkdownRenderer`.\n * Dual-theme colors stay as `--shiki-light` / `--shiki-dark` CSS variables on\n * each token span; the `.shiki-token` class (index.css) picks the variant from\n * the `.dark` root class, so theme switching is pure CSS — no ThemeProvider\n * required. Renders plain text while highlighting is pending or when the\n * language is missing/unknown.\n *\n * A streaming fence re-renders on every delta while highlighting stays a frame\n * behind. Dropping the previous tokens each time would strobe the whole block\n * between colored and plain, so the settled prefix keeps its colors and only\n * the newly arrived tail waits, uncolored, for the next pass.\n */\nexport const Code = React.memo(function Code({ code, lang, ...props }: CodeProps) {\n const [highlighted, setHighlighted] = React.useState<Highlighted | null>(null);\n\n React.useEffect(() => {\n if (!lang) {\n setHighlighted(null);\n return;\n }\n\n let cancelled = false;\n\n void highlight(code, lang)\n .then(tokens => {\n if (!cancelled && tokens?.length) setHighlighted({ code, lang, tokens });\n })\n .catch(() => {});\n\n return () => {\n cancelled = true;\n };\n }, [code, lang]);\n\n const usable = usableHighlight(highlighted, code, lang);\n if (!usable) {\n return <pre {...props}>{code}</pre>;\n }\n\n const tail = code.slice(usable.code.length);\n let codeOffset = 0;\n\n return (\n <pre {...props}>\n <code>\n {usable.tokens.map((line, lineIndex) => {\n const lineOffset = codeOffset;\n let tokenOffset = lineOffset;\n const tokenSpans = line.map(token => {\n const key = tokenOffset;\n tokenOffset += token.content.length;\n\n return (\n <span key={key} className=\"shiki-token\" style={tokenStyle(token)}>\n {token.content}\n </span>\n );\n });\n\n codeOffset = tokenOffset + 1;\n\n return (\n <React.Fragment key={lineOffset}>\n <span>{tokenSpans}</span>\n {lineIndex !== usable.tokens.length - 1 && '\\n'}\n </React.Fragment>\n );\n })}\n {tail}\n </code>\n </pre>\n );\n});\n"],"names":["React","Code","highlight","jsx","jsxs"],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+ import { h as highlight } from './highlight-CSJjjoqh.js';
4
+
5
+ function tokenStyle(token) {
6
+ if (token.htmlStyle && typeof token.htmlStyle === "object") {
7
+ return token.htmlStyle;
8
+ }
9
+ return token.color ? { color: token.color } : void 0;
10
+ }
11
+ function usableHighlight(highlighted, code, lang) {
12
+ if (!highlighted || highlighted.lang !== lang) return null;
13
+ return code.startsWith(highlighted.code) ? highlighted : null;
14
+ }
15
+ const Code = React.memo(function Code2({ code, lang, ...props }) {
16
+ const [highlighted, setHighlighted] = React.useState(null);
17
+ React.useEffect(() => {
18
+ if (!lang) {
19
+ setHighlighted(null);
20
+ return;
21
+ }
22
+ let cancelled = false;
23
+ void highlight(code, lang).then((tokens) => {
24
+ if (!cancelled && tokens?.length) setHighlighted({ code, lang, tokens });
25
+ }).catch(() => {
26
+ });
27
+ return () => {
28
+ cancelled = true;
29
+ };
30
+ }, [code, lang]);
31
+ const usable = usableHighlight(highlighted, code, lang);
32
+ if (!usable) {
33
+ return /* @__PURE__ */ jsx("pre", { ...props, children: code });
34
+ }
35
+ const tail = code.slice(usable.code.length);
36
+ let codeOffset = 0;
37
+ return /* @__PURE__ */ jsx("pre", { ...props, children: /* @__PURE__ */ jsxs("code", { children: [
38
+ usable.tokens.map((line, lineIndex) => {
39
+ const lineOffset = codeOffset;
40
+ let tokenOffset = lineOffset;
41
+ const tokenSpans = line.map((token) => {
42
+ const key = tokenOffset;
43
+ tokenOffset += token.content.length;
44
+ return /* @__PURE__ */ jsx("span", { className: "shiki-token", style: tokenStyle(token), children: token.content }, key);
45
+ });
46
+ codeOffset = tokenOffset + 1;
47
+ return /* @__PURE__ */ jsxs(React.Fragment, { children: [
48
+ /* @__PURE__ */ jsx("span", { children: tokenSpans }),
49
+ lineIndex !== usable.tokens.length - 1 && "\n"
50
+ ] }, lineOffset);
51
+ }),
52
+ tail
53
+ ] }) });
54
+ });
55
+
56
+ export { Code as C };
57
+ //# sourceMappingURL=code-DRGJVroV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-DRGJVroV.js","sources":["../src/ds/components/Code/code.tsx"],"sourcesContent":["import * as React from 'react';\nimport type { ThemedToken } from 'shiki/core';\n\nimport { highlight } from '../CodeEditor/highlight';\n\nexport interface CodeProps extends React.HTMLAttributes<HTMLPreElement> {\n code: string;\n lang?: string;\n}\n\nfunction tokenStyle(token: ThemedToken): React.CSSProperties | undefined {\n if (token.htmlStyle && typeof token.htmlStyle === 'object') {\n return token.htmlStyle as React.CSSProperties;\n }\n\n return token.color ? { color: token.color } : undefined;\n}\n\ninterface Highlighted {\n code: string;\n lang: string;\n tokens: ThemedToken[][];\n}\n\n/** Colors from an earlier pass still hold when the new code only appends to the old. */\nfunction usableHighlight(highlighted: Highlighted | null, code: string, lang?: string): Highlighted | null {\n if (!highlighted || highlighted.lang !== lang) return null;\n return code.startsWith(highlighted.code) ? highlighted : null;\n}\n\n/**\n * Low-level shiki token renderer shared by `CodeBlock` and `MarkdownRenderer`.\n * Dual-theme colors stay as `--shiki-light` / `--shiki-dark` CSS variables on\n * each token span; the `.shiki-token` class (index.css) picks the variant from\n * the `.dark` root class, so theme switching is pure CSS — no ThemeProvider\n * required. Renders plain text while highlighting is pending or when the\n * language is missing/unknown.\n *\n * A streaming fence re-renders on every delta while highlighting stays a frame\n * behind. Dropping the previous tokens each time would strobe the whole block\n * between colored and plain, so the settled prefix keeps its colors and only\n * the newly arrived tail waits, uncolored, for the next pass.\n */\nexport const Code = React.memo(function Code({ code, lang, ...props }: CodeProps) {\n const [highlighted, setHighlighted] = React.useState<Highlighted | null>(null);\n\n React.useEffect(() => {\n if (!lang) {\n setHighlighted(null);\n return;\n }\n\n let cancelled = false;\n\n void highlight(code, lang)\n .then(tokens => {\n if (!cancelled && tokens?.length) setHighlighted({ code, lang, tokens });\n })\n .catch(() => {});\n\n return () => {\n cancelled = true;\n };\n }, [code, lang]);\n\n const usable = usableHighlight(highlighted, code, lang);\n if (!usable) {\n return <pre {...props}>{code}</pre>;\n }\n\n const tail = code.slice(usable.code.length);\n let codeOffset = 0;\n\n return (\n <pre {...props}>\n <code>\n {usable.tokens.map((line, lineIndex) => {\n const lineOffset = codeOffset;\n let tokenOffset = lineOffset;\n const tokenSpans = line.map(token => {\n const key = tokenOffset;\n tokenOffset += token.content.length;\n\n return (\n <span key={key} className=\"shiki-token\" style={tokenStyle(token)}>\n {token.content}\n </span>\n );\n });\n\n codeOffset = tokenOffset + 1;\n\n return (\n <React.Fragment key={lineOffset}>\n <span>{tokenSpans}</span>\n {lineIndex !== usable.tokens.length - 1 && '\\n'}\n </React.Fragment>\n );\n })}\n {tail}\n </code>\n </pre>\n );\n});\n"],"names":["Code"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const jsxRuntime = require('react/jsx-runtime');
4
- const code = require('./code-FZwLnf_f.cjs');
4
+ const code = require('./code-BJMC6T9D.cjs');
5
5
  const copyButton = require('./copy-button-BfawWA4t.cjs');
6
6
  const select = require('./select-OAXqZLkC.cjs');
7
7
  const tabsRoot = require('./tabs-root-VtBc6K2q.cjs');
@@ -85,4 +85,4 @@ function CodeBlock({
85
85
  }
86
86
 
87
87
  exports.CodeBlock = CodeBlock;
88
- //# sourceMappingURL=code-block-Dn0K3DkE.cjs.map
88
+ //# sourceMappingURL=code-block-BZUY8Fj9.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"code-block-Dn0K3DkE.cjs","sources":["../src/ds/components/CodeBlock/code-block.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { Code } from '../Code/code';\nimport { CopyButton } from '../CopyButton/copy-button';\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../Select/select';\nimport { TabList } from '../Tabs/tabs-list';\nimport { Tabs } from '../Tabs/tabs-root';\nimport { Tab } from '../Tabs/tabs-tab';\nimport { transitions } from '@/ds/primitives/transitions';\nimport { cn } from '@/lib/utils';\n\nexport type CodeBlockSelector = 'select' | 'tabs';\n\nexport type CodeBlockOverflow = 'wrap' | 'scroll';\n\nexport interface CodeBlockOption {\n label: string;\n value: string;\n}\n\nexport interface CodeBlockProps {\n code: string;\n options?: CodeBlockOption[];\n value?: string;\n onValueChange?: (value: string) => void;\n selector?: CodeBlockSelector;\n fileName?: string;\n lang?: string;\n /** `wrap` (default) breaks long lines — best for commands and snippets.\n * `scroll` preserves columns behind a horizontal scroll — best for source code. */\n overflow?: CodeBlockOverflow;\n copyMessage?: string;\n copyTooltip?: string;\n actions?: ReactNode;\n className?: string;\n}\n\nexport function CodeBlock({\n code,\n options,\n value,\n onValueChange,\n selector = 'select',\n fileName,\n lang,\n overflow = 'wrap',\n copyMessage,\n copyTooltip,\n actions,\n className,\n}: CodeBlockProps) {\n const hasOptions = options && options.length > 0;\n const useTabs = hasOptions && selector === 'tabs';\n const useSelect = hasOptions && selector === 'select';\n const firstOption = options?.[0];\n const activeValue = value ?? firstOption?.value;\n\n return (\n <figure\n className={cn(\n 'group relative flex w-full flex-col overflow-hidden rounded-2xl border border-border2/40 bg-surface2',\n className,\n )}\n >\n {useTabs && firstOption && (\n <Tabs defaultTab={firstOption.value} value={activeValue} onValueChange={onValueChange ?? (() => {})}>\n <div className=\"flex items-stretch\">\n <div className=\"min-w-0 flex-1\">\n <TabList>\n {options.map(opt => (\n <Tab key={opt.value} value={opt.value}>\n {opt.label}\n </Tab>\n ))}\n </TabList>\n </div>\n {actions && <div className=\"border-border1 flex shrink-0 items-center border-b pr-2 pl-3\">{actions}</div>}\n </div>\n </Tabs>\n )}\n\n {useSelect && options && (\n <div className=\"border-border2/40 flex items-center border-b px-2 py-1.5\">\n <Select value={activeValue} onValueChange={onValueChange}>\n <SelectTrigger size=\"sm\" variant=\"ghost\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {options.map(opt => (\n <SelectItem key={opt.value} value={opt.value}>\n {opt.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {actions && <div className=\"ml-auto flex items-center\">{actions}</div>}\n </div>\n )}\n\n {!hasOptions && fileName && (\n <div className=\"border-border2/40 flex items-center border-b px-4 py-2\">\n <figcaption className=\"text-ui-sm text-neutral4 font-mono\">{fileName}</figcaption>\n {actions && <div className=\"ml-auto flex items-center\">{actions}</div>}\n </div>\n )}\n\n {!hasOptions && !fileName && actions && (\n <div className=\"border-border2/40 flex items-center justify-end border-b px-2 py-1.5\">{actions}</div>\n )}\n\n <div className=\"relative\">\n <Code\n code={code}\n lang={lang}\n className={cn(\n 'px-4 py-3 font-mono text-ui-sm text-neutral5',\n overflow === 'scroll' ? 'overflow-x-auto whitespace-pre' : 'break-all whitespace-pre-wrap',\n )}\n />\n <CopyButton\n content={code}\n copyMessage={copyMessage}\n tooltip={copyTooltip}\n size=\"sm\"\n className={cn(\n 'absolute top-2 right-2 opacity-100 group-focus-within:opacity-100 group-hover:opacity-100 pointer-fine:opacity-0',\n transitions.opacity,\n )}\n />\n </div>\n </figure>\n );\n}\n"],"names":["code","jsxs","cn","jsx","Tabs","TabList","Tab","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","Code","CopyButton","transitions"],"mappings":"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"}
1
+ {"version":3,"file":"code-block-BZUY8Fj9.cjs","sources":["../src/ds/components/CodeBlock/code-block.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { Code } from '../Code/code';\nimport { CopyButton } from '../CopyButton/copy-button';\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../Select/select';\nimport { TabList } from '../Tabs/tabs-list';\nimport { Tabs } from '../Tabs/tabs-root';\nimport { Tab } from '../Tabs/tabs-tab';\nimport { transitions } from '@/ds/primitives/transitions';\nimport { cn } from '@/lib/utils';\n\nexport type CodeBlockSelector = 'select' | 'tabs';\n\nexport type CodeBlockOverflow = 'wrap' | 'scroll';\n\nexport interface CodeBlockOption {\n label: string;\n value: string;\n}\n\nexport interface CodeBlockProps {\n code: string;\n options?: CodeBlockOption[];\n value?: string;\n onValueChange?: (value: string) => void;\n selector?: CodeBlockSelector;\n fileName?: string;\n lang?: string;\n /** `wrap` (default) breaks long lines — best for commands and snippets.\n * `scroll` preserves columns behind a horizontal scroll — best for source code. */\n overflow?: CodeBlockOverflow;\n copyMessage?: string;\n copyTooltip?: string;\n actions?: ReactNode;\n className?: string;\n}\n\nexport function CodeBlock({\n code,\n options,\n value,\n onValueChange,\n selector = 'select',\n fileName,\n lang,\n overflow = 'wrap',\n copyMessage,\n copyTooltip,\n actions,\n className,\n}: CodeBlockProps) {\n const hasOptions = options && options.length > 0;\n const useTabs = hasOptions && selector === 'tabs';\n const useSelect = hasOptions && selector === 'select';\n const firstOption = options?.[0];\n const activeValue = value ?? firstOption?.value;\n\n return (\n <figure\n className={cn(\n 'group relative flex w-full flex-col overflow-hidden rounded-2xl border border-border2/40 bg-surface2',\n className,\n )}\n >\n {useTabs && firstOption && (\n <Tabs defaultTab={firstOption.value} value={activeValue} onValueChange={onValueChange ?? (() => {})}>\n <div className=\"flex items-stretch\">\n <div className=\"min-w-0 flex-1\">\n <TabList>\n {options.map(opt => (\n <Tab key={opt.value} value={opt.value}>\n {opt.label}\n </Tab>\n ))}\n </TabList>\n </div>\n {actions && <div className=\"border-border1 flex shrink-0 items-center border-b pr-2 pl-3\">{actions}</div>}\n </div>\n </Tabs>\n )}\n\n {useSelect && options && (\n <div className=\"border-border2/40 flex items-center border-b px-2 py-1.5\">\n <Select value={activeValue} onValueChange={onValueChange}>\n <SelectTrigger size=\"sm\" variant=\"ghost\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {options.map(opt => (\n <SelectItem key={opt.value} value={opt.value}>\n {opt.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {actions && <div className=\"ml-auto flex items-center\">{actions}</div>}\n </div>\n )}\n\n {!hasOptions && fileName && (\n <div className=\"border-border2/40 flex items-center border-b px-4 py-2\">\n <figcaption className=\"text-ui-sm text-neutral4 font-mono\">{fileName}</figcaption>\n {actions && <div className=\"ml-auto flex items-center\">{actions}</div>}\n </div>\n )}\n\n {!hasOptions && !fileName && actions && (\n <div className=\"border-border2/40 flex items-center justify-end border-b px-2 py-1.5\">{actions}</div>\n )}\n\n <div className=\"relative\">\n <Code\n code={code}\n lang={lang}\n className={cn(\n 'px-4 py-3 font-mono text-ui-sm text-neutral5',\n overflow === 'scroll' ? 'overflow-x-auto whitespace-pre' : 'break-all whitespace-pre-wrap',\n )}\n />\n <CopyButton\n content={code}\n copyMessage={copyMessage}\n tooltip={copyTooltip}\n size=\"sm\"\n className={cn(\n 'absolute top-2 right-2 opacity-100 group-focus-within:opacity-100 group-hover:opacity-100 pointer-fine:opacity-0',\n transitions.opacity,\n )}\n />\n </div>\n </figure>\n );\n}\n"],"names":["code","jsxs","cn","jsx","Tabs","TabList","Tab","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","Code","CopyButton","transitions"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
- import { C as Code } from './code-Cj09LVys.js';
2
+ import { C as Code } from './code-DRGJVroV.js';
3
3
  import { C as CopyButton } from './copy-button-BLGUkVE8.js';
4
4
  import { S as Select, d as SelectTrigger, e as SelectValue, a as SelectContent, c as SelectItem } from './select-B_E0ADD5.js';
5
5
  import { a as Tabs, T as TabList } from './tabs-root-BBPou4QC.js';
@@ -83,4 +83,4 @@ function CodeBlock({
83
83
  }
84
84
 
85
85
  export { CodeBlock as C };
86
- //# sourceMappingURL=code-block-DqKXZajq.js.map
86
+ //# sourceMappingURL=code-block-V4wpmbud.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"code-block-DqKXZajq.js","sources":["../src/ds/components/CodeBlock/code-block.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { Code } from '../Code/code';\nimport { CopyButton } from '../CopyButton/copy-button';\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../Select/select';\nimport { TabList } from '../Tabs/tabs-list';\nimport { Tabs } from '../Tabs/tabs-root';\nimport { Tab } from '../Tabs/tabs-tab';\nimport { transitions } from '@/ds/primitives/transitions';\nimport { cn } from '@/lib/utils';\n\nexport type CodeBlockSelector = 'select' | 'tabs';\n\nexport type CodeBlockOverflow = 'wrap' | 'scroll';\n\nexport interface CodeBlockOption {\n label: string;\n value: string;\n}\n\nexport interface CodeBlockProps {\n code: string;\n options?: CodeBlockOption[];\n value?: string;\n onValueChange?: (value: string) => void;\n selector?: CodeBlockSelector;\n fileName?: string;\n lang?: string;\n /** `wrap` (default) breaks long lines — best for commands and snippets.\n * `scroll` preserves columns behind a horizontal scroll — best for source code. */\n overflow?: CodeBlockOverflow;\n copyMessage?: string;\n copyTooltip?: string;\n actions?: ReactNode;\n className?: string;\n}\n\nexport function CodeBlock({\n code,\n options,\n value,\n onValueChange,\n selector = 'select',\n fileName,\n lang,\n overflow = 'wrap',\n copyMessage,\n copyTooltip,\n actions,\n className,\n}: CodeBlockProps) {\n const hasOptions = options && options.length > 0;\n const useTabs = hasOptions && selector === 'tabs';\n const useSelect = hasOptions && selector === 'select';\n const firstOption = options?.[0];\n const activeValue = value ?? firstOption?.value;\n\n return (\n <figure\n className={cn(\n 'group relative flex w-full flex-col overflow-hidden rounded-2xl border border-border2/40 bg-surface2',\n className,\n )}\n >\n {useTabs && firstOption && (\n <Tabs defaultTab={firstOption.value} value={activeValue} onValueChange={onValueChange ?? (() => {})}>\n <div className=\"flex items-stretch\">\n <div className=\"min-w-0 flex-1\">\n <TabList>\n {options.map(opt => (\n <Tab key={opt.value} value={opt.value}>\n {opt.label}\n </Tab>\n ))}\n </TabList>\n </div>\n {actions && <div className=\"border-border1 flex shrink-0 items-center border-b pr-2 pl-3\">{actions}</div>}\n </div>\n </Tabs>\n )}\n\n {useSelect && options && (\n <div className=\"border-border2/40 flex items-center border-b px-2 py-1.5\">\n <Select value={activeValue} onValueChange={onValueChange}>\n <SelectTrigger size=\"sm\" variant=\"ghost\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {options.map(opt => (\n <SelectItem key={opt.value} value={opt.value}>\n {opt.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {actions && <div className=\"ml-auto flex items-center\">{actions}</div>}\n </div>\n )}\n\n {!hasOptions && fileName && (\n <div className=\"border-border2/40 flex items-center border-b px-4 py-2\">\n <figcaption className=\"text-ui-sm text-neutral4 font-mono\">{fileName}</figcaption>\n {actions && <div className=\"ml-auto flex items-center\">{actions}</div>}\n </div>\n )}\n\n {!hasOptions && !fileName && actions && (\n <div className=\"border-border2/40 flex items-center justify-end border-b px-2 py-1.5\">{actions}</div>\n )}\n\n <div className=\"relative\">\n <Code\n code={code}\n lang={lang}\n className={cn(\n 'px-4 py-3 font-mono text-ui-sm text-neutral5',\n overflow === 'scroll' ? 'overflow-x-auto whitespace-pre' : 'break-all whitespace-pre-wrap',\n )}\n />\n <CopyButton\n content={code}\n copyMessage={copyMessage}\n tooltip={copyTooltip}\n size=\"sm\"\n className={cn(\n 'absolute top-2 right-2 opacity-100 group-focus-within:opacity-100 group-hover:opacity-100 pointer-fine:opacity-0',\n transitions.opacity,\n )}\n />\n </div>\n </figure>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"code-block-V4wpmbud.js","sources":["../src/ds/components/CodeBlock/code-block.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { Code } from '../Code/code';\nimport { CopyButton } from '../CopyButton/copy-button';\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../Select/select';\nimport { TabList } from '../Tabs/tabs-list';\nimport { Tabs } from '../Tabs/tabs-root';\nimport { Tab } from '../Tabs/tabs-tab';\nimport { transitions } from '@/ds/primitives/transitions';\nimport { cn } from '@/lib/utils';\n\nexport type CodeBlockSelector = 'select' | 'tabs';\n\nexport type CodeBlockOverflow = 'wrap' | 'scroll';\n\nexport interface CodeBlockOption {\n label: string;\n value: string;\n}\n\nexport interface CodeBlockProps {\n code: string;\n options?: CodeBlockOption[];\n value?: string;\n onValueChange?: (value: string) => void;\n selector?: CodeBlockSelector;\n fileName?: string;\n lang?: string;\n /** `wrap` (default) breaks long lines — best for commands and snippets.\n * `scroll` preserves columns behind a horizontal scroll — best for source code. */\n overflow?: CodeBlockOverflow;\n copyMessage?: string;\n copyTooltip?: string;\n actions?: ReactNode;\n className?: string;\n}\n\nexport function CodeBlock({\n code,\n options,\n value,\n onValueChange,\n selector = 'select',\n fileName,\n lang,\n overflow = 'wrap',\n copyMessage,\n copyTooltip,\n actions,\n className,\n}: CodeBlockProps) {\n const hasOptions = options && options.length > 0;\n const useTabs = hasOptions && selector === 'tabs';\n const useSelect = hasOptions && selector === 'select';\n const firstOption = options?.[0];\n const activeValue = value ?? firstOption?.value;\n\n return (\n <figure\n className={cn(\n 'group relative flex w-full flex-col overflow-hidden rounded-2xl border border-border2/40 bg-surface2',\n className,\n )}\n >\n {useTabs && firstOption && (\n <Tabs defaultTab={firstOption.value} value={activeValue} onValueChange={onValueChange ?? (() => {})}>\n <div className=\"flex items-stretch\">\n <div className=\"min-w-0 flex-1\">\n <TabList>\n {options.map(opt => (\n <Tab key={opt.value} value={opt.value}>\n {opt.label}\n </Tab>\n ))}\n </TabList>\n </div>\n {actions && <div className=\"border-border1 flex shrink-0 items-center border-b pr-2 pl-3\">{actions}</div>}\n </div>\n </Tabs>\n )}\n\n {useSelect && options && (\n <div className=\"border-border2/40 flex items-center border-b px-2 py-1.5\">\n <Select value={activeValue} onValueChange={onValueChange}>\n <SelectTrigger size=\"sm\" variant=\"ghost\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {options.map(opt => (\n <SelectItem key={opt.value} value={opt.value}>\n {opt.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {actions && <div className=\"ml-auto flex items-center\">{actions}</div>}\n </div>\n )}\n\n {!hasOptions && fileName && (\n <div className=\"border-border2/40 flex items-center border-b px-4 py-2\">\n <figcaption className=\"text-ui-sm text-neutral4 font-mono\">{fileName}</figcaption>\n {actions && <div className=\"ml-auto flex items-center\">{actions}</div>}\n </div>\n )}\n\n {!hasOptions && !fileName && actions && (\n <div className=\"border-border2/40 flex items-center justify-end border-b px-2 py-1.5\">{actions}</div>\n )}\n\n <div className=\"relative\">\n <Code\n code={code}\n lang={lang}\n className={cn(\n 'px-4 py-3 font-mono text-ui-sm text-neutral5',\n overflow === 'scroll' ? 'overflow-x-auto whitespace-pre' : 'break-all whitespace-pre-wrap',\n )}\n />\n <CopyButton\n content={code}\n copyMessage={copyMessage}\n tooltip={copyTooltip}\n size=\"sm\"\n className={cn(\n 'absolute top-2 right-2 opacity-100 group-focus-within:opacity-100 group-hover:opacity-100 pointer-fine:opacity-0',\n transitions.opacity,\n )}\n />\n </div>\n </figure>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;AAoCO,SAAS,SAAA,CAAU;AAAA,EACxB,IAAA;AAAA,EACA,OAAA;AAAA,EACA,KAAA;AAAA,EACA,aAAA;AAAA,EACA,QAAA,GAAW,QAAA;AAAA,EACX,QAAA;AAAA,EACA,IAAA;AAAA,EACA,QAAA,GAAW,MAAA;AAAA,EACX,WAAA;AAAA,EACA,WAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAA,EAAmB;AACjB,EAAA,MAAM,UAAA,GAAa,OAAA,IAAW,OAAA,CAAQ,MAAA,GAAS,CAAA;AAC/C,EAAA,MAAM,OAAA,GAAU,cAAc,QAAA,KAAa,MAAA;AAC3C,EAAA,MAAM,SAAA,GAAY,cAAc,QAAA,KAAa,QAAA;AAC7C,EAAA,MAAM,WAAA,GAAc,UAAU,CAAC,CAAA;AAC/B,EAAA,MAAM,WAAA,GAAc,SAAS,WAAA,EAAa,KAAA;AAE1C,EAAA,uBACE,IAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA;AAAA,QACT,sGAAA;AAAA,QACA;AAAA,OACF;AAAA,MAEC,QAAA,EAAA;AAAA,QAAA,OAAA,IAAW,WAAA,oBACV,GAAA,CAAC,IAAA,EAAA,EAAK,UAAA,EAAY,WAAA,CAAY,OAAO,KAAA,EAAO,WAAA,EAAa,aAAA,EAAe,aAAA,KAAkB,MAAM;AAAA,QAAC,CAAA,CAAA,EAC/F,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,oBAAA,EACb,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,SAAI,SAAA,EAAU,gBAAA,EACb,8BAAC,OAAA,EAAA,EACE,QAAA,EAAA,OAAA,CAAQ,IAAI,CAAA,GAAA,qBACX,GAAA,CAAC,OAAoB,KAAA,EAAO,GAAA,CAAI,OAC7B,QAAA,EAAA,GAAA,CAAI,KAAA,EAAA,EADG,IAAI,KAEd,CACD,GACH,CAAA,EACF,CAAA;AAAA,UACC,OAAA,oBAAW,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gEAAgE,QAAA,EAAA,OAAA,EAAQ;AAAA,SAAA,EACrG,CAAA,EACF,CAAA;AAAA,QAGD,SAAA,IAAa,OAAA,oBACZ,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,0DAAA,EACb,QAAA,EAAA;AAAA,0BAAA,IAAA,CAAC,MAAA,EAAA,EAAO,KAAA,EAAO,WAAA,EAAa,aAAA,EAC1B,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,iBAAc,IAAA,EAAK,IAAA,EAAK,SAAQ,OAAA,EAC/B,QAAA,kBAAA,GAAA,CAAC,eAAY,CAAA,EACf,CAAA;AAAA,4BACA,GAAA,CAAC,aAAA,EAAA,EACE,QAAA,EAAA,OAAA,CAAQ,GAAA,CAAI,yBACX,GAAA,CAAC,UAAA,EAAA,EAA2B,KAAA,EAAO,GAAA,CAAI,OACpC,QAAA,EAAA,GAAA,CAAI,KAAA,EAAA,EADU,GAAA,CAAI,KAErB,CACD,CAAA,EACH;AAAA,WAAA,EACF,CAAA;AAAA,UACC,OAAA,oBAAW,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,6BAA6B,QAAA,EAAA,OAAA,EAAQ;AAAA,SAAA,EAClE,CAAA;AAAA,QAGD,CAAC,UAAA,IAAc,QAAA,oBACd,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,wDAAA,EACb,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,YAAA,EAAA,EAAW,SAAA,EAAU,oCAAA,EAAsC,QAAA,EAAA,QAAA,EAAS,CAAA;AAAA,UACpE,OAAA,oBAAW,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,6BAA6B,QAAA,EAAA,OAAA,EAAQ;AAAA,SAAA,EAClE,CAAA;AAAA,QAGD,CAAC,cAAc,CAAC,QAAA,IAAY,2BAC3B,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,sEAAA,EAAwE,QAAA,EAAA,OAAA,EAAQ,CAAA;AAAA,wBAGjG,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,UAAA,EACb,QAAA,EAAA;AAAA,0BAAA,GAAA;AAAA,YAAC,IAAA;AAAA,YAAA;AAAA,cACC,IAAA;AAAA,cACA,IAAA;AAAA,cACA,SAAA,EAAW,EAAA;AAAA,gBACT,8CAAA;AAAA,gBACA,QAAA,KAAa,WAAW,gCAAA,GAAmC;AAAA;AAC7D;AAAA,WACF;AAAA,0BACA,GAAA;AAAA,YAAC,UAAA;AAAA,YAAA;AAAA,cACC,OAAA,EAAS,IAAA;AAAA,cACT,WAAA;AAAA,cACA,OAAA,EAAS,WAAA;AAAA,cACT,IAAA,EAAK,IAAA;AAAA,cACL,SAAA,EAAW,EAAA;AAAA,gBACT,kHAAA;AAAA,gBACA,WAAA,CAAY;AAAA;AACd;AAAA;AACF,SAAA,EACF;AAAA;AAAA;AAAA,GACF;AAEJ;;;;"}
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
4
 
5
- const code = require('../code-FZwLnf_f.cjs');
5
+ const code = require('../code-BJMC6T9D.cjs');
6
6
 
7
7
 
8
8
 
@@ -1,2 +1,2 @@
1
- export { C as Code } from '../code-Cj09LVys.js';
1
+ export { C as Code } from '../code-DRGJVroV.js';
2
2
  //# sourceMappingURL=Code.es.js.map
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
4
 
5
- const codeBlock = require('../code-block-Dn0K3DkE.cjs');
5
+ const codeBlock = require('../code-block-BZUY8Fj9.cjs');
6
6
 
7
7
 
8
8
 
@@ -1,2 +1,2 @@
1
- export { C as CodeBlock } from '../code-block-DqKXZajq.js';
1
+ export { C as CodeBlock } from '../code-block-V4wpmbud.js';
2
2
  //# sourceMappingURL=CodeBlock.es.js.map
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
4
 
5
- const markdownRenderer = require('../markdown-renderer-D1vSFfp9.cjs');
5
+ const markdownRenderer = require('../markdown-renderer-DvJfqb-D.cjs');
6
6
 
7
7
 
8
8
 
@@ -1,2 +1,2 @@
1
- export { M as MarkdownRenderer } from '../markdown-renderer-DmYYQHxu.js';
1
+ export { M as MarkdownRenderer } from '../markdown-renderer-CB2WMnTG.js';
2
2
  //# sourceMappingURL=MarkdownRenderer.es.js.map
@@ -7,7 +7,7 @@ const lucideReact = require('lucide-react');
7
7
  const React = require('react');
8
8
  const Badge = require('../../Badge-BlJpI3fY.cjs');
9
9
  const Button = require('../../Button-B4Ixj2aW.cjs');
10
- const markdownRenderer = require('../../markdown-renderer-D1vSFfp9.cjs');
10
+ const markdownRenderer = require('../../markdown-renderer-DvJfqb-D.cjs');
11
11
  const Txt = require('../../Txt-I5lK8zy7.cjs');
12
12
  const icons_Icon = require('../../icons/Icon.cjs.js');
13
13
  const hooks_useCopyToClipboard = require('../../hooks/use-copy-to-clipboard.cjs.js');
@@ -3,7 +3,7 @@ import { CheckIcon, CopyIcon, Minimize2, Maximize2, ClipboardList } from 'lucide
3
3
  import { useState, createContext, useContext } from 'react';
4
4
  import { B as Badge } from '../../Badge-woV6OD8k.js';
5
5
  import { B as Button } from '../../Button-C-9Pzy-Z.js';
6
- import { M as MarkdownRenderer } from '../../markdown-renderer-DmYYQHxu.js';
6
+ import { M as MarkdownRenderer } from '../../markdown-renderer-CB2WMnTG.js';
7
7
  import { T as Txt } from '../../Txt-Df42XG5p.js';
8
8
  import { Icon } from '../../icons/Icon.es.js';
9
9
  import { useCopyToClipboard } from '../../hooks/use-copy-to-clipboard.es.js';
@@ -1,10 +1,15 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
+ import { memo } from 'react';
2
3
  import Markdown from 'react-markdown';
3
4
  import remarkGfm from 'remark-gfm';
4
- import { C as CodeBlock } from './code-block-DqKXZajq.js';
5
+ import { C as CodeBlock } from './code-block-V4wpmbud.js';
5
6
  import { c as cn } from './cn-BakJzhuv.js';
6
7
 
7
- import './markdown-renderer.css';function MarkdownRenderer({ children, className, externalLinkTarget = "tab" }) {
8
+ import './markdown-renderer.css';const MarkdownRenderer = memo(function MarkdownRenderer2({
9
+ children,
10
+ className,
11
+ externalLinkTarget = "tab"
12
+ }) {
8
13
  return /* @__PURE__ */ jsx(
9
14
  Markdown,
10
15
  {
@@ -14,7 +19,7 @@ import './markdown-renderer.css';function MarkdownRenderer({ children, className
14
19
  children: decodeEscapedNewlines(children)
15
20
  }
16
21
  );
17
- }
22
+ });
18
23
  function decodeEscapedNewlines(text) {
19
24
  return text.includes("\n") ? text : text.replace(/\\n/g, "\n");
20
25
  }
@@ -81,4 +86,4 @@ const WINDOW_COMPONENTS = {
81
86
  };
82
87
 
83
88
  export { MarkdownRenderer as M };
84
- //# sourceMappingURL=markdown-renderer-DmYYQHxu.js.map
89
+ //# sourceMappingURL=markdown-renderer-CB2WMnTG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown-renderer-CB2WMnTG.js","sources":["../src/ds/components/MarkdownRenderer/markdown-renderer.tsx"],"sourcesContent":["import { memo } from 'react';\nimport type { MouseEvent, MouseEventHandler, ReactNode } from 'react';\nimport Markdown from 'react-markdown';\nimport type { Components, ExtraProps } from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\n\nimport { CodeBlock } from '@/ds/components/CodeBlock';\nimport { cn } from '@/lib/utils';\n\nimport './markdown-renderer.css';\n\nexport type MarkdownExternalLinkTarget = 'tab' | 'window';\n\nexport interface MarkdownRendererProps {\n children: string;\n className?: string;\n externalLinkTarget?: MarkdownExternalLinkTarget;\n}\n\n/**\n * Renders a markdown string. Agent output can carry attacker-influenced text\n * (file contents, tool output, web pages): react-markdown escapes raw HTML and\n * drops dangerous link schemes, so nothing here reaches the DOM as markup.\n *\n * Memoized because react-markdown re-parses on every render and a streaming\n * reply re-renders its whole transcript on every delta: without this, each\n * chunk re-parses every settled message on the page as well as the live one.\n */\nexport const MarkdownRenderer = memo(function MarkdownRenderer({\n children,\n className,\n externalLinkTarget = 'tab',\n}: MarkdownRendererProps) {\n return (\n <Markdown\n remarkPlugins={[remarkGfm]}\n components={externalLinkTarget === 'window' ? WINDOW_COMPONENTS : COMPONENTS}\n className={cn('mastra-markdown', className)}\n >\n {decodeEscapedNewlines(children)}\n </Markdown>\n );\n});\n\n// Agent networks emit their text with literal `\\n`. Only unescape when the text\n// has no real newline, otherwise a `\"a\\nb\"` inside a code fence gets shredded.\nfunction decodeEscapedNewlines(text: string): string {\n return text.includes('\\n') ? text : text.replace(/\\\\n/g, '\\n');\n}\n\ntype MarkdownNode = NonNullable<ExtraProps['node']>;\n\nfunction languageOf(node: MarkdownNode): string | undefined {\n const classNames = node.properties.className;\n if (!Array.isArray(classNames)) return undefined;\n\n const language = classNames.find(entry => typeof entry === 'string' && entry.startsWith('language-'));\n return typeof language === 'string' ? language.slice('language-'.length) : undefined;\n}\n\nfunction fencedCode(node: MarkdownNode | undefined): { code: string; language?: string } | undefined {\n const child = node?.children.find(entry => entry.type === 'element' && entry.tagName === 'code');\n if (child?.type !== 'element') return undefined;\n\n const code = child.children.map(entry => (entry.type === 'text' ? entry.value : '')).join('');\n return { code: code.replace(/\\n$/, ''), language: languageOf(child) };\n}\n\nfunction MarkdownCodeBlock({ node, children }: { node?: MarkdownNode; children?: ReactNode }) {\n const fenced = fencedCode(node);\n if (!fenced) return <pre>{children}</pre>;\n\n return (\n <CodeBlock\n code={fenced.code}\n lang={fenced.language}\n overflow=\"scroll\"\n className=\"bg-surface1 my-3\"\n copyMessage=\"Copied code to clipboard\"\n />\n );\n}\n\nconst POPUP_WINDOW_FEATURES = 'popup=yes,width=720,height=800,resizable=yes,scrollbars=yes';\n\nfunction isPlainLeftClick(event: MouseEvent): boolean {\n return event.button === 0 && !event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey;\n}\n\nfunction markdownLink(externalLinkTarget: MarkdownExternalLinkTarget): NonNullable<Components['a']> {\n return function MarkdownLink({ href, title, children }) {\n const isExternal = /^https?:\\/\\//i.test(href ?? '');\n\n const openInPopup: MouseEventHandler<HTMLAnchorElement> = event => {\n if (!isExternal || externalLinkTarget !== 'window' || !isPlainLeftClick(event)) return;\n\n const popup = window.open(href, '_blank', POPUP_WINDOW_FEATURES);\n if (!popup) return;\n\n popup.opener = null;\n event.preventDefault();\n };\n\n return (\n <a\n href={href}\n title={title}\n onClick={openInPopup}\n target={isExternal ? '_blank' : undefined}\n rel={isExternal ? 'noopener noreferrer' : undefined}\n >\n {children}\n </a>\n );\n };\n}\n\n// Elements are listed one by one: react-markdown also passes its `node`, which\n// React would forward to the DOM as a stray attribute. Everything else is\n// styled from markdown-renderer.css.\nconst COMPONENTS: Components = {\n pre: MarkdownCodeBlock,\n a: markdownLink('tab'),\n};\n\nconst WINDOW_COMPONENTS: Components = {\n ...COMPONENTS,\n a: markdownLink('window'),\n};\n"],"names":["MarkdownRenderer"],"mappings":";;;;;;;AA4BO,MAAM,gBAAA,GAAmB,IAAA,CAAK,SAASA,iBAAAA,CAAiB;AAAA,EAC7D,QAAA;AAAA,EACA,SAAA;AAAA,EACA,kBAAA,GAAqB;AACvB,CAAA,EAA0B;AACxB,EAAA,uBACE,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,aAAA,EAAe,CAAC,SAAS,CAAA;AAAA,MACzB,UAAA,EAAY,kBAAA,KAAuB,QAAA,GAAW,iBAAA,GAAoB,UAAA;AAAA,MAClE,SAAA,EAAW,EAAA,CAAG,iBAAA,EAAmB,SAAS,CAAA;AAAA,MAEzC,gCAAsB,QAAQ;AAAA;AAAA,GACjC;AAEJ,CAAC;AAID,SAAS,sBAAsB,IAAA,EAAsB;AACnD,EAAA,OAAO,IAAA,CAAK,SAAS,IAAI,CAAA,GAAI,OAAO,IAAA,CAAK,OAAA,CAAQ,QAAQ,IAAI,CAAA;AAC/D;AAIA,SAAS,WAAW,IAAA,EAAwC;AAC1D,EAAA,MAAM,UAAA,GAAa,KAAK,UAAA,CAAW,SAAA;AACnC,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,UAAU,GAAG,OAAO,MAAA;AAEvC,EAAA,MAAM,QAAA,GAAW,UAAA,CAAW,IAAA,CAAK,CAAA,KAAA,KAAS,OAAO,UAAU,QAAA,IAAY,KAAA,CAAM,UAAA,CAAW,WAAW,CAAC,CAAA;AACpG,EAAA,OAAO,OAAO,QAAA,KAAa,QAAA,GAAW,SAAS,KAAA,CAAM,WAAA,CAAY,MAAM,CAAA,GAAI,MAAA;AAC7E;AAEA,SAAS,WAAW,IAAA,EAAiF;AACnG,EAAA,MAAM,KAAA,GAAQ,IAAA,EAAM,QAAA,CAAS,IAAA,CAAK,CAAA,KAAA,KAAS,MAAM,IAAA,KAAS,SAAA,IAAa,KAAA,CAAM,OAAA,KAAY,MAAM,CAAA;AAC/F,EAAA,IAAI,KAAA,EAAO,IAAA,KAAS,SAAA,EAAW,OAAO,MAAA;AAEtC,EAAA,MAAM,IAAA,GAAO,KAAA,CAAM,QAAA,CAAS,GAAA,CAAI,CAAA,KAAA,KAAU,KAAA,CAAM,IAAA,KAAS,MAAA,GAAS,KAAA,CAAM,KAAA,GAAQ,EAAG,CAAA,CAAE,KAAK,EAAE,CAAA;AAC5F,EAAA,OAAO,EAAE,IAAA,EAAM,IAAA,CAAK,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA,EAAG,QAAA,EAAU,UAAA,CAAW,KAAK,CAAA,EAAE;AACtE;AAEA,SAAS,iBAAA,CAAkB,EAAE,IAAA,EAAM,QAAA,EAAS,EAAkD;AAC5F,EAAA,MAAM,MAAA,GAAS,WAAW,IAAI,CAAA;AAC9B,EAAA,IAAI,CAAC,MAAA,EAAQ,uBAAO,GAAA,CAAC,SAAK,QAAA,EAAS,CAAA;AAEnC,EAAA,uBACE,GAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACC,MAAM,MAAA,CAAO,IAAA;AAAA,MACb,MAAM,MAAA,CAAO,QAAA;AAAA,MACb,QAAA,EAAS,QAAA;AAAA,MACT,SAAA,EAAU,kBAAA;AAAA,MACV,WAAA,EAAY;AAAA;AAAA,GACd;AAEJ;AAEA,MAAM,qBAAA,GAAwB,6DAAA;AAE9B,SAAS,iBAAiB,KAAA,EAA4B;AACpD,EAAA,OAAO,KAAA,CAAM,MAAA,KAAW,CAAA,IAAK,CAAC,KAAA,CAAM,OAAA,IAAW,CAAC,KAAA,CAAM,OAAA,IAAW,CAAC,KAAA,CAAM,QAAA,IAAY,CAAC,KAAA,CAAM,MAAA;AAC7F;AAEA,SAAS,aAAa,kBAAA,EAA8E;AAClG,EAAA,OAAO,SAAS,YAAA,CAAa,EAAE,IAAA,EAAM,KAAA,EAAO,UAAS,EAAG;AACtD,IAAA,MAAM,UAAA,GAAa,eAAA,CAAgB,IAAA,CAAK,IAAA,IAAQ,EAAE,CAAA;AAElD,IAAA,MAAM,cAAoD,CAAA,KAAA,KAAS;AACjE,MAAA,IAAI,CAAC,UAAA,IAAc,kBAAA,KAAuB,YAAY,CAAC,gBAAA,CAAiB,KAAK,CAAA,EAAG;AAEhF,MAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,IAAA,CAAK,IAAA,EAAM,UAAU,qBAAqB,CAAA;AAC/D,MAAA,IAAI,CAAC,KAAA,EAAO;AAEZ,MAAA,KAAA,CAAM,MAAA,GAAS,IAAA;AACf,MAAA,KAAA,CAAM,cAAA,EAAe;AAAA,IACvB,CAAA;AAEA,IAAA,uBACE,GAAA;AAAA,MAAC,GAAA;AAAA,MAAA;AAAA,QACC,IAAA;AAAA,QACA,KAAA;AAAA,QACA,OAAA,EAAS,WAAA;AAAA,QACT,MAAA,EAAQ,aAAa,QAAA,GAAW,MAAA;AAAA,QAChC,GAAA,EAAK,aAAa,qBAAA,GAAwB,MAAA;AAAA,QAEzC;AAAA;AAAA,KACH;AAAA,EAEJ,CAAA;AACF;AAKA,MAAM,UAAA,GAAyB;AAAA,EAC7B,GAAA,EAAK,iBAAA;AAAA,EACL,CAAA,EAAG,aAAa,KAAK;AACvB,CAAA;AAEA,MAAM,iBAAA,GAAgC;AAAA,EACpC,GAAG,UAAA;AAAA,EACH,CAAA,EAAG,aAAa,QAAQ;AAC1B,CAAA;;;;"}
@@ -1,12 +1,17 @@
1
1
  'use strict';
2
2
 
3
3
  require('./markdown-renderer.css');const jsxRuntime = require('react/jsx-runtime');
4
+ const React = require('react');
4
5
  const Markdown = require('react-markdown');
5
6
  const remarkGfm = require('remark-gfm');
6
- const codeBlock = require('./code-block-Dn0K3DkE.cjs');
7
+ const codeBlock = require('./code-block-BZUY8Fj9.cjs');
7
8
  const utils_cn = require('./cn-vA5sWo9W.cjs');
8
9
 
9
- function MarkdownRenderer({ children, className, externalLinkTarget = "tab" }) {
10
+ const MarkdownRenderer = React.memo(function MarkdownRenderer2({
11
+ children,
12
+ className,
13
+ externalLinkTarget = "tab"
14
+ }) {
10
15
  return /* @__PURE__ */ jsxRuntime.jsx(
11
16
  Markdown,
12
17
  {
@@ -16,7 +21,7 @@ function MarkdownRenderer({ children, className, externalLinkTarget = "tab" }) {
16
21
  children: decodeEscapedNewlines(children)
17
22
  }
18
23
  );
19
- }
24
+ });
20
25
  function decodeEscapedNewlines(text) {
21
26
  return text.includes("\n") ? text : text.replace(/\\n/g, "\n");
22
27
  }
@@ -83,4 +88,4 @@ const WINDOW_COMPONENTS = {
83
88
  };
84
89
 
85
90
  exports.MarkdownRenderer = MarkdownRenderer;
86
- //# sourceMappingURL=markdown-renderer-D1vSFfp9.cjs.map
91
+ //# sourceMappingURL=markdown-renderer-DvJfqb-D.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown-renderer-DvJfqb-D.cjs","sources":["../src/ds/components/MarkdownRenderer/markdown-renderer.tsx"],"sourcesContent":["import { memo } from 'react';\nimport type { MouseEvent, MouseEventHandler, ReactNode } from 'react';\nimport Markdown from 'react-markdown';\nimport type { Components, ExtraProps } from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\n\nimport { CodeBlock } from '@/ds/components/CodeBlock';\nimport { cn } from '@/lib/utils';\n\nimport './markdown-renderer.css';\n\nexport type MarkdownExternalLinkTarget = 'tab' | 'window';\n\nexport interface MarkdownRendererProps {\n children: string;\n className?: string;\n externalLinkTarget?: MarkdownExternalLinkTarget;\n}\n\n/**\n * Renders a markdown string. Agent output can carry attacker-influenced text\n * (file contents, tool output, web pages): react-markdown escapes raw HTML and\n * drops dangerous link schemes, so nothing here reaches the DOM as markup.\n *\n * Memoized because react-markdown re-parses on every render and a streaming\n * reply re-renders its whole transcript on every delta: without this, each\n * chunk re-parses every settled message on the page as well as the live one.\n */\nexport const MarkdownRenderer = memo(function MarkdownRenderer({\n children,\n className,\n externalLinkTarget = 'tab',\n}: MarkdownRendererProps) {\n return (\n <Markdown\n remarkPlugins={[remarkGfm]}\n components={externalLinkTarget === 'window' ? WINDOW_COMPONENTS : COMPONENTS}\n className={cn('mastra-markdown', className)}\n >\n {decodeEscapedNewlines(children)}\n </Markdown>\n );\n});\n\n// Agent networks emit their text with literal `\\n`. Only unescape when the text\n// has no real newline, otherwise a `\"a\\nb\"` inside a code fence gets shredded.\nfunction decodeEscapedNewlines(text: string): string {\n return text.includes('\\n') ? text : text.replace(/\\\\n/g, '\\n');\n}\n\ntype MarkdownNode = NonNullable<ExtraProps['node']>;\n\nfunction languageOf(node: MarkdownNode): string | undefined {\n const classNames = node.properties.className;\n if (!Array.isArray(classNames)) return undefined;\n\n const language = classNames.find(entry => typeof entry === 'string' && entry.startsWith('language-'));\n return typeof language === 'string' ? language.slice('language-'.length) : undefined;\n}\n\nfunction fencedCode(node: MarkdownNode | undefined): { code: string; language?: string } | undefined {\n const child = node?.children.find(entry => entry.type === 'element' && entry.tagName === 'code');\n if (child?.type !== 'element') return undefined;\n\n const code = child.children.map(entry => (entry.type === 'text' ? entry.value : '')).join('');\n return { code: code.replace(/\\n$/, ''), language: languageOf(child) };\n}\n\nfunction MarkdownCodeBlock({ node, children }: { node?: MarkdownNode; children?: ReactNode }) {\n const fenced = fencedCode(node);\n if (!fenced) return <pre>{children}</pre>;\n\n return (\n <CodeBlock\n code={fenced.code}\n lang={fenced.language}\n overflow=\"scroll\"\n className=\"bg-surface1 my-3\"\n copyMessage=\"Copied code to clipboard\"\n />\n );\n}\n\nconst POPUP_WINDOW_FEATURES = 'popup=yes,width=720,height=800,resizable=yes,scrollbars=yes';\n\nfunction isPlainLeftClick(event: MouseEvent): boolean {\n return event.button === 0 && !event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey;\n}\n\nfunction markdownLink(externalLinkTarget: MarkdownExternalLinkTarget): NonNullable<Components['a']> {\n return function MarkdownLink({ href, title, children }) {\n const isExternal = /^https?:\\/\\//i.test(href ?? '');\n\n const openInPopup: MouseEventHandler<HTMLAnchorElement> = event => {\n if (!isExternal || externalLinkTarget !== 'window' || !isPlainLeftClick(event)) return;\n\n const popup = window.open(href, '_blank', POPUP_WINDOW_FEATURES);\n if (!popup) return;\n\n popup.opener = null;\n event.preventDefault();\n };\n\n return (\n <a\n href={href}\n title={title}\n onClick={openInPopup}\n target={isExternal ? '_blank' : undefined}\n rel={isExternal ? 'noopener noreferrer' : undefined}\n >\n {children}\n </a>\n );\n };\n}\n\n// Elements are listed one by one: react-markdown also passes its `node`, which\n// React would forward to the DOM as a stray attribute. Everything else is\n// styled from markdown-renderer.css.\nconst COMPONENTS: Components = {\n pre: MarkdownCodeBlock,\n a: markdownLink('tab'),\n};\n\nconst WINDOW_COMPONENTS: Components = {\n ...COMPONENTS,\n a: markdownLink('window'),\n};\n"],"names":["memo","MarkdownRenderer","jsx","cn","CodeBlock"],"mappings":"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"}
@@ -10,5 +10,10 @@ export interface CodeProps extends React.HTMLAttributes<HTMLPreElement> {
10
10
  * the `.dark` root class, so theme switching is pure CSS — no ThemeProvider
11
11
  * required. Renders plain text while highlighting is pending or when the
12
12
  * language is missing/unknown.
13
+ *
14
+ * A streaming fence re-renders on every delta while highlighting stays a frame
15
+ * behind. Dropping the previous tokens each time would strobe the whole block
16
+ * between colored and plain, so the settled prefix keeps its colors and only
17
+ * the newly arrived tail waits, uncolored, for the next pass.
13
18
  */
14
19
  export declare const Code: React.MemoExoticComponent<({ code, lang, ...props }: CodeProps) => React.JSX.Element>;
@@ -8,5 +8,9 @@ export interface MarkdownRendererProps {
8
8
  * Renders a markdown string. Agent output can carry attacker-influenced text
9
9
  * (file contents, tool output, web pages): react-markdown escapes raw HTML and
10
10
  * drops dangerous link schemes, so nothing here reaches the DOM as markup.
11
+ *
12
+ * Memoized because react-markdown re-parses on every render and a streaming
13
+ * reply re-renders its whole transcript on every delta: without this, each
14
+ * chunk re-parses every settled message on the page as well as the live one.
11
15
  */
12
- export declare function MarkdownRenderer({ children, className, externalLinkTarget }: MarkdownRendererProps): import("react").JSX.Element;
16
+ export declare const MarkdownRenderer: import('react').MemoExoticComponent<({ children, className, externalLinkTarget, }: MarkdownRendererProps) => import("react").JSX.Element>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mastra/playground-ui",
3
3
  "type": "module",
4
- "version": "49.0.0-alpha.3",
4
+ "version": "49.0.0-alpha.4",
5
5
  "description": "Mastra Playground components",
6
6
  "sideEffects": [
7
7
  "**/*.css"
@@ -150,8 +150,8 @@
150
150
  "react": ">=19.0.0",
151
151
  "react-dom": ">=19.0.0",
152
152
  "tailwindcss": "^4.0.0",
153
- "@mastra/client-js": "^1.40.0-alpha.3",
154
- "@mastra/react": "1.4.3-alpha.3"
153
+ "@mastra/client-js": "^1.40.0-alpha.4",
154
+ "@mastra/react": "1.4.3-alpha.4"
155
155
  },
156
156
  "devDependencies": {
157
157
  "@storybook/addon-a11y": "^10.4.1",
@@ -190,10 +190,10 @@
190
190
  "vite-plugin-lib-inject-css": "^2.2.2",
191
191
  "vitest": "4.1.10",
192
192
  "@internal/lint": "0.0.122",
193
- "@mastra/client-js": "^1.40.0-alpha.3",
194
- "@mastra/core": "1.59.0-alpha.3",
195
- "@mastra/react": "1.4.3-alpha.3",
196
- "@mastra/memory": "1.26.2-alpha.1"
193
+ "@mastra/memory": "1.26.2-alpha.1",
194
+ "@mastra/core": "1.59.0-alpha.4",
195
+ "@mastra/react": "1.4.3-alpha.4",
196
+ "@mastra/client-js": "^1.40.0-alpha.4"
197
197
  },
198
198
  "homepage": "https://mastra.ai",
199
199
  "repository": {
@@ -1,47 +0,0 @@
1
- import { jsx, jsxs } from 'react/jsx-runtime';
2
- import * as React from 'react';
3
- import { h as highlight } from './highlight-CSJjjoqh.js';
4
-
5
- function tokenStyle(token) {
6
- if (token.htmlStyle && typeof token.htmlStyle === "object") {
7
- return token.htmlStyle;
8
- }
9
- return token.color ? { color: token.color } : void 0;
10
- }
11
- const Code = React.memo(function Code2({ code, lang, ...props }) {
12
- const [tokens, setTokens] = React.useState(null);
13
- React.useEffect(() => {
14
- setTokens(null);
15
- if (!lang) return;
16
- let cancelled = false;
17
- void highlight(code, lang).then((result) => {
18
- if (!cancelled) setTokens(result);
19
- }).catch(() => {
20
- if (!cancelled) setTokens(null);
21
- });
22
- return () => {
23
- cancelled = true;
24
- };
25
- }, [code, lang]);
26
- if (!tokens?.length) {
27
- return /* @__PURE__ */ jsx("pre", { ...props, children: code });
28
- }
29
- let codeOffset = 0;
30
- return /* @__PURE__ */ jsx("pre", { ...props, children: /* @__PURE__ */ jsx("code", { children: tokens.map((line, lineIndex) => {
31
- const lineOffset = codeOffset;
32
- let tokenOffset = lineOffset;
33
- const tokenSpans = line.map((token) => {
34
- const key = tokenOffset;
35
- tokenOffset += token.content.length;
36
- return /* @__PURE__ */ jsx("span", { className: "shiki-token", style: tokenStyle(token), children: token.content }, key);
37
- });
38
- codeOffset = tokenOffset + 1;
39
- return /* @__PURE__ */ jsxs(React.Fragment, { children: [
40
- /* @__PURE__ */ jsx("span", { children: tokenSpans }),
41
- lineIndex !== tokens.length - 1 && "\n"
42
- ] }, lineOffset);
43
- }) }) });
44
- });
45
-
46
- export { Code as C };
47
- //# sourceMappingURL=code-Cj09LVys.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"code-Cj09LVys.js","sources":["../src/ds/components/Code/code.tsx"],"sourcesContent":["import * as React from 'react';\nimport type { ThemedToken } from 'shiki/core';\n\nimport { highlight } from '../CodeEditor/highlight';\n\nexport interface CodeProps extends React.HTMLAttributes<HTMLPreElement> {\n code: string;\n lang?: string;\n}\n\nfunction tokenStyle(token: ThemedToken): React.CSSProperties | undefined {\n if (token.htmlStyle && typeof token.htmlStyle === 'object') {\n return token.htmlStyle as React.CSSProperties;\n }\n\n return token.color ? { color: token.color } : undefined;\n}\n\n/**\n * Low-level shiki token renderer shared by `CodeBlock` and `MarkdownRenderer`.\n * Dual-theme colors stay as `--shiki-light` / `--shiki-dark` CSS variables on\n * each token span; the `.shiki-token` class (index.css) picks the variant from\n * the `.dark` root class, so theme switching is pure CSS — no ThemeProvider\n * required. Renders plain text while highlighting is pending or when the\n * language is missing/unknown.\n */\nexport const Code = React.memo(function Code({ code, lang, ...props }: CodeProps) {\n const [tokens, setTokens] = React.useState<ThemedToken[][] | null>(null);\n\n React.useEffect(() => {\n setTokens(null);\n if (!lang) return;\n\n let cancelled = false;\n\n void highlight(code, lang)\n .then(result => {\n if (!cancelled) setTokens(result);\n })\n .catch(() => {\n if (!cancelled) setTokens(null);\n });\n\n return () => {\n cancelled = true;\n };\n }, [code, lang]);\n\n if (!tokens?.length) {\n return <pre {...props}>{code}</pre>;\n }\n\n let codeOffset = 0;\n\n return (\n <pre {...props}>\n <code>\n {tokens.map((line, lineIndex) => {\n const lineOffset = codeOffset;\n let tokenOffset = lineOffset;\n const tokenSpans = line.map(token => {\n const key = tokenOffset;\n tokenOffset += token.content.length;\n\n return (\n <span key={key} className=\"shiki-token\" style={tokenStyle(token)}>\n {token.content}\n </span>\n );\n });\n\n codeOffset = tokenOffset + 1;\n\n return (\n <React.Fragment key={lineOffset}>\n <span>{tokenSpans}</span>\n {lineIndex !== tokens.length - 1 && '\\n'}\n </React.Fragment>\n );\n })}\n </code>\n </pre>\n );\n});\n"],"names":["Code"],"mappings":";;;;AAUA,SAAS,WAAW,KAAA,EAAqD;AACvE,EAAA,IAAI,KAAA,CAAM,SAAA,IAAa,OAAO,KAAA,CAAM,cAAc,QAAA,EAAU;AAC1D,IAAA,OAAO,KAAA,CAAM,SAAA;AAAA,EACf;AAEA,EAAA,OAAO,MAAM,KAAA,GAAQ,EAAE,KAAA,EAAO,KAAA,CAAM,OAAM,GAAI,MAAA;AAChD;AAUO,MAAM,IAAA,GAAO,KAAA,CAAM,IAAA,CAAK,SAASA,KAAAA,CAAK,EAAE,IAAA,EAAM,IAAA,EAAM,GAAG,KAAA,EAAM,EAAc;AAChF,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,KAAA,CAAM,SAAiC,IAAI,CAAA;AAEvE,EAAA,KAAA,CAAM,UAAU,MAAM;AACpB,IAAA,SAAA,CAAU,IAAI,CAAA;AACd,IAAA,IAAI,CAAC,IAAA,EAAM;AAEX,IAAA,IAAI,SAAA,GAAY,KAAA;AAEhB,IAAA,KAAK,SAAA,CAAU,IAAA,EAAM,IAAI,CAAA,CACtB,KAAK,CAAA,MAAA,KAAU;AACd,MAAA,IAAI,CAAC,SAAA,EAAW,SAAA,CAAU,MAAM,CAAA;AAAA,IAClC,CAAC,CAAA,CACA,KAAA,CAAM,MAAM;AACX,MAAA,IAAI,CAAC,SAAA,EAAW,SAAA,CAAU,IAAI,CAAA;AAAA,IAChC,CAAC,CAAA;AAEH,IAAA,OAAO,MAAM;AACX,MAAA,SAAA,GAAY,IAAA;AAAA,IACd,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,IAAA,EAAM,IAAI,CAAC,CAAA;AAEf,EAAA,IAAI,CAAC,QAAQ,MAAA,EAAQ;AACnB,IAAA,uBAAO,GAAA,CAAC,KAAA,EAAA,EAAK,GAAG,KAAA,EAAQ,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,EAC/B;AAEA,EAAA,IAAI,UAAA,GAAa,CAAA;AAEjB,EAAA,uBACE,GAAA,CAAC,KAAA,EAAA,EAAK,GAAG,KAAA,EACP,QAAA,kBAAA,GAAA,CAAC,UACE,QAAA,EAAA,MAAA,CAAO,GAAA,CAAI,CAAC,IAAA,EAAM,SAAA,KAAc;AAC/B,IAAA,MAAM,UAAA,GAAa,UAAA;AACnB,IAAA,IAAI,WAAA,GAAc,UAAA;AAClB,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,GAAA,CAAI,CAAA,KAAA,KAAS;AACnC,MAAA,MAAM,GAAA,GAAM,WAAA;AACZ,MAAA,WAAA,IAAe,MAAM,OAAA,CAAQ,MAAA;AAE7B,MAAA,uBACE,GAAA,CAAC,MAAA,EAAA,EAAe,SAAA,EAAU,aAAA,EAAc,KAAA,EAAO,WAAW,KAAK,CAAA,EAC5D,QAAA,EAAA,KAAA,CAAM,OAAA,EAAA,EADE,GAEX,CAAA;AAAA,IAEJ,CAAC,CAAA;AAED,IAAA,UAAA,GAAa,WAAA,GAAc,CAAA;AAE3B,IAAA,uBACE,IAAA,CAAC,KAAA,CAAM,QAAA,EAAN,EACC,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,UAAM,QAAA,EAAA,UAAA,EAAW,CAAA;AAAA,MACjB,SAAA,KAAc,MAAA,CAAO,MAAA,GAAS,CAAA,IAAK;AAAA,KAAA,EAAA,EAFjB,UAGrB,CAAA;AAAA,EAEJ,CAAC,GACH,CAAA,EACF,CAAA;AAEJ,CAAC;;;;"}
@@ -1,68 +0,0 @@
1
- 'use strict';
2
-
3
- const jsxRuntime = require('react/jsx-runtime');
4
- const React = require('react');
5
- const highlight = require('./highlight-CEt2vhD8.cjs');
6
-
7
- function _interopNamespaceDefault(e) {
8
- const n = Object.create(null, { [Symbol.toStringTag]: { value: 'Module' } });
9
- if (e) {
10
- for (const k in e) {
11
- if (k !== 'default') {
12
- const d = Object.getOwnPropertyDescriptor(e, k);
13
- Object.defineProperty(n, k, d.get ? d : {
14
- enumerable: true,
15
- get: () => e[k]
16
- });
17
- }
18
- }
19
- }
20
- n.default = e;
21
- return Object.freeze(n);
22
- }
23
-
24
- const React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
25
-
26
- function tokenStyle(token) {
27
- if (token.htmlStyle && typeof token.htmlStyle === "object") {
28
- return token.htmlStyle;
29
- }
30
- return token.color ? { color: token.color } : void 0;
31
- }
32
- const Code = React__namespace.memo(function Code2({ code, lang, ...props }) {
33
- const [tokens, setTokens] = React__namespace.useState(null);
34
- React__namespace.useEffect(() => {
35
- setTokens(null);
36
- if (!lang) return;
37
- let cancelled = false;
38
- void highlight.highlight(code, lang).then((result) => {
39
- if (!cancelled) setTokens(result);
40
- }).catch(() => {
41
- if (!cancelled) setTokens(null);
42
- });
43
- return () => {
44
- cancelled = true;
45
- };
46
- }, [code, lang]);
47
- if (!tokens?.length) {
48
- return /* @__PURE__ */ jsxRuntime.jsx("pre", { ...props, children: code });
49
- }
50
- let codeOffset = 0;
51
- return /* @__PURE__ */ jsxRuntime.jsx("pre", { ...props, children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: tokens.map((line, lineIndex) => {
52
- const lineOffset = codeOffset;
53
- let tokenOffset = lineOffset;
54
- const tokenSpans = line.map((token) => {
55
- const key = tokenOffset;
56
- tokenOffset += token.content.length;
57
- return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shiki-token", style: tokenStyle(token), children: token.content }, key);
58
- });
59
- codeOffset = tokenOffset + 1;
60
- return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
61
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: tokenSpans }),
62
- lineIndex !== tokens.length - 1 && "\n"
63
- ] }, lineOffset);
64
- }) }) });
65
- });
66
-
67
- exports.Code = Code;
68
- //# sourceMappingURL=code-FZwLnf_f.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"code-FZwLnf_f.cjs","sources":["../src/ds/components/Code/code.tsx"],"sourcesContent":["import * as React from 'react';\nimport type { ThemedToken } from 'shiki/core';\n\nimport { highlight } from '../CodeEditor/highlight';\n\nexport interface CodeProps extends React.HTMLAttributes<HTMLPreElement> {\n code: string;\n lang?: string;\n}\n\nfunction tokenStyle(token: ThemedToken): React.CSSProperties | undefined {\n if (token.htmlStyle && typeof token.htmlStyle === 'object') {\n return token.htmlStyle as React.CSSProperties;\n }\n\n return token.color ? { color: token.color } : undefined;\n}\n\n/**\n * Low-level shiki token renderer shared by `CodeBlock` and `MarkdownRenderer`.\n * Dual-theme colors stay as `--shiki-light` / `--shiki-dark` CSS variables on\n * each token span; the `.shiki-token` class (index.css) picks the variant from\n * the `.dark` root class, so theme switching is pure CSS — no ThemeProvider\n * required. Renders plain text while highlighting is pending or when the\n * language is missing/unknown.\n */\nexport const Code = React.memo(function Code({ code, lang, ...props }: CodeProps) {\n const [tokens, setTokens] = React.useState<ThemedToken[][] | null>(null);\n\n React.useEffect(() => {\n setTokens(null);\n if (!lang) return;\n\n let cancelled = false;\n\n void highlight(code, lang)\n .then(result => {\n if (!cancelled) setTokens(result);\n })\n .catch(() => {\n if (!cancelled) setTokens(null);\n });\n\n return () => {\n cancelled = true;\n };\n }, [code, lang]);\n\n if (!tokens?.length) {\n return <pre {...props}>{code}</pre>;\n }\n\n let codeOffset = 0;\n\n return (\n <pre {...props}>\n <code>\n {tokens.map((line, lineIndex) => {\n const lineOffset = codeOffset;\n let tokenOffset = lineOffset;\n const tokenSpans = line.map(token => {\n const key = tokenOffset;\n tokenOffset += token.content.length;\n\n return (\n <span key={key} className=\"shiki-token\" style={tokenStyle(token)}>\n {token.content}\n </span>\n );\n });\n\n codeOffset = tokenOffset + 1;\n\n return (\n <React.Fragment key={lineOffset}>\n <span>{tokenSpans}</span>\n {lineIndex !== tokens.length - 1 && '\\n'}\n </React.Fragment>\n );\n })}\n </code>\n </pre>\n );\n});\n"],"names":["React","Code","highlight","jsx","jsxs"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAUA,SAAS,WAAW,KAAA,EAAqD;AACvE,EAAA,IAAI,KAAA,CAAM,SAAA,IAAa,OAAO,KAAA,CAAM,cAAc,QAAA,EAAU;AAC1D,IAAA,OAAO,KAAA,CAAM,SAAA;AAAA,EACf;AAEA,EAAA,OAAO,MAAM,KAAA,GAAQ,EAAE,KAAA,EAAO,KAAA,CAAM,OAAM,GAAI,MAAA;AAChD;AAUO,MAAM,IAAA,GAAOA,gBAAA,CAAM,IAAA,CAAK,SAASC,KAAAA,CAAK,EAAE,IAAA,EAAM,IAAA,EAAM,GAAG,KAAA,EAAM,EAAc;AAChF,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAID,gBAAA,CAAM,SAAiC,IAAI,CAAA;AAEvE,EAAAA,gBAAA,CAAM,UAAU,MAAM;AACpB,IAAA,SAAA,CAAU,IAAI,CAAA;AACd,IAAA,IAAI,CAAC,IAAA,EAAM;AAEX,IAAA,IAAI,SAAA,GAAY,KAAA;AAEhB,IAAA,KAAKE,mBAAA,CAAU,IAAA,EAAM,IAAI,CAAA,CACtB,KAAK,CAAA,MAAA,KAAU;AACd,MAAA,IAAI,CAAC,SAAA,EAAW,SAAA,CAAU,MAAM,CAAA;AAAA,IAClC,CAAC,CAAA,CACA,KAAA,CAAM,MAAM;AACX,MAAA,IAAI,CAAC,SAAA,EAAW,SAAA,CAAU,IAAI,CAAA;AAAA,IAChC,CAAC,CAAA;AAEH,IAAA,OAAO,MAAM;AACX,MAAA,SAAA,GAAY,IAAA;AAAA,IACd,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,IAAA,EAAM,IAAI,CAAC,CAAA;AAEf,EAAA,IAAI,CAAC,QAAQ,MAAA,EAAQ;AACnB,IAAA,uBAAOC,cAAA,CAAC,KAAA,EAAA,EAAK,GAAG,KAAA,EAAQ,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,EAC/B;AAEA,EAAA,IAAI,UAAA,GAAa,CAAA;AAEjB,EAAA,uBACEA,cAAA,CAAC,KAAA,EAAA,EAAK,GAAG,KAAA,EACP,QAAA,kBAAAA,cAAA,CAAC,UACE,QAAA,EAAA,MAAA,CAAO,GAAA,CAAI,CAAC,IAAA,EAAM,SAAA,KAAc;AAC/B,IAAA,MAAM,UAAA,GAAa,UAAA;AACnB,IAAA,IAAI,WAAA,GAAc,UAAA;AAClB,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,GAAA,CAAI,CAAA,KAAA,KAAS;AACnC,MAAA,MAAM,GAAA,GAAM,WAAA;AACZ,MAAA,WAAA,IAAe,MAAM,OAAA,CAAQ,MAAA;AAE7B,MAAA,uBACEA,cAAA,CAAC,MAAA,EAAA,EAAe,SAAA,EAAU,aAAA,EAAc,KAAA,EAAO,WAAW,KAAK,CAAA,EAC5D,QAAA,EAAA,KAAA,CAAM,OAAA,EAAA,EADE,GAEX,CAAA;AAAA,IAEJ,CAAC,CAAA;AAED,IAAA,UAAA,GAAa,WAAA,GAAc,CAAA;AAE3B,IAAA,uBACEC,eAAA,CAACJ,gBAAA,CAAM,QAAA,EAAN,EACC,QAAA,EAAA;AAAA,sBAAAG,cAAA,CAAC,UAAM,QAAA,EAAA,UAAA,EAAW,CAAA;AAAA,MACjB,SAAA,KAAc,MAAA,CAAO,MAAA,GAAS,CAAA,IAAK;AAAA,KAAA,EAAA,EAFjB,UAGrB,CAAA;AAAA,EAEJ,CAAC,GACH,CAAA,EACF,CAAA;AAEJ,CAAC;;;;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"markdown-renderer-D1vSFfp9.cjs","sources":["../src/ds/components/MarkdownRenderer/markdown-renderer.tsx"],"sourcesContent":["import type { MouseEvent, MouseEventHandler, ReactNode } from 'react';\nimport Markdown from 'react-markdown';\nimport type { Components, ExtraProps } from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\n\nimport { CodeBlock } from '@/ds/components/CodeBlock';\nimport { cn } from '@/lib/utils';\n\nimport './markdown-renderer.css';\n\nexport type MarkdownExternalLinkTarget = 'tab' | 'window';\n\nexport interface MarkdownRendererProps {\n children: string;\n className?: string;\n externalLinkTarget?: MarkdownExternalLinkTarget;\n}\n\n/**\n * Renders a markdown string. Agent output can carry attacker-influenced text\n * (file contents, tool output, web pages): react-markdown escapes raw HTML and\n * drops dangerous link schemes, so nothing here reaches the DOM as markup.\n */\nexport function MarkdownRenderer({ children, className, externalLinkTarget = 'tab' }: MarkdownRendererProps) {\n return (\n <Markdown\n remarkPlugins={[remarkGfm]}\n components={externalLinkTarget === 'window' ? WINDOW_COMPONENTS : COMPONENTS}\n className={cn('mastra-markdown', className)}\n >\n {decodeEscapedNewlines(children)}\n </Markdown>\n );\n}\n\n// Agent networks emit their text with literal `\\n`. Only unescape when the text\n// has no real newline, otherwise a `\"a\\nb\"` inside a code fence gets shredded.\nfunction decodeEscapedNewlines(text: string): string {\n return text.includes('\\n') ? text : text.replace(/\\\\n/g, '\\n');\n}\n\ntype MarkdownNode = NonNullable<ExtraProps['node']>;\n\nfunction languageOf(node: MarkdownNode): string | undefined {\n const classNames = node.properties.className;\n if (!Array.isArray(classNames)) return undefined;\n\n const language = classNames.find(entry => typeof entry === 'string' && entry.startsWith('language-'));\n return typeof language === 'string' ? language.slice('language-'.length) : undefined;\n}\n\nfunction fencedCode(node: MarkdownNode | undefined): { code: string; language?: string } | undefined {\n const child = node?.children.find(entry => entry.type === 'element' && entry.tagName === 'code');\n if (child?.type !== 'element') return undefined;\n\n const code = child.children.map(entry => (entry.type === 'text' ? entry.value : '')).join('');\n return { code: code.replace(/\\n$/, ''), language: languageOf(child) };\n}\n\nfunction MarkdownCodeBlock({ node, children }: { node?: MarkdownNode; children?: ReactNode }) {\n const fenced = fencedCode(node);\n if (!fenced) return <pre>{children}</pre>;\n\n return (\n <CodeBlock\n code={fenced.code}\n lang={fenced.language}\n overflow=\"scroll\"\n className=\"bg-surface1 my-3\"\n copyMessage=\"Copied code to clipboard\"\n />\n );\n}\n\nconst POPUP_WINDOW_FEATURES = 'popup=yes,width=720,height=800,resizable=yes,scrollbars=yes';\n\nfunction isPlainLeftClick(event: MouseEvent): boolean {\n return event.button === 0 && !event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey;\n}\n\nfunction markdownLink(externalLinkTarget: MarkdownExternalLinkTarget): NonNullable<Components['a']> {\n return function MarkdownLink({ href, title, children }) {\n const isExternal = /^https?:\\/\\//i.test(href ?? '');\n\n const openInPopup: MouseEventHandler<HTMLAnchorElement> = event => {\n if (!isExternal || externalLinkTarget !== 'window' || !isPlainLeftClick(event)) return;\n\n const popup = window.open(href, '_blank', POPUP_WINDOW_FEATURES);\n if (!popup) return;\n\n popup.opener = null;\n event.preventDefault();\n };\n\n return (\n <a\n href={href}\n title={title}\n onClick={openInPopup}\n target={isExternal ? '_blank' : undefined}\n rel={isExternal ? 'noopener noreferrer' : undefined}\n >\n {children}\n </a>\n );\n };\n}\n\n// Elements are listed one by one: react-markdown also passes its `node`, which\n// React would forward to the DOM as a stray attribute. Everything else is\n// styled from markdown-renderer.css.\nconst COMPONENTS: Components = {\n pre: MarkdownCodeBlock,\n a: markdownLink('tab'),\n};\n\nconst WINDOW_COMPONENTS: Components = {\n ...COMPONENTS,\n a: markdownLink('window'),\n};\n"],"names":["jsx","cn","CodeBlock"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"markdown-renderer-DmYYQHxu.js","sources":["../src/ds/components/MarkdownRenderer/markdown-renderer.tsx"],"sourcesContent":["import type { MouseEvent, MouseEventHandler, ReactNode } from 'react';\nimport Markdown from 'react-markdown';\nimport type { Components, ExtraProps } from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\n\nimport { CodeBlock } from '@/ds/components/CodeBlock';\nimport { cn } from '@/lib/utils';\n\nimport './markdown-renderer.css';\n\nexport type MarkdownExternalLinkTarget = 'tab' | 'window';\n\nexport interface MarkdownRendererProps {\n children: string;\n className?: string;\n externalLinkTarget?: MarkdownExternalLinkTarget;\n}\n\n/**\n * Renders a markdown string. Agent output can carry attacker-influenced text\n * (file contents, tool output, web pages): react-markdown escapes raw HTML and\n * drops dangerous link schemes, so nothing here reaches the DOM as markup.\n */\nexport function MarkdownRenderer({ children, className, externalLinkTarget = 'tab' }: MarkdownRendererProps) {\n return (\n <Markdown\n remarkPlugins={[remarkGfm]}\n components={externalLinkTarget === 'window' ? WINDOW_COMPONENTS : COMPONENTS}\n className={cn('mastra-markdown', className)}\n >\n {decodeEscapedNewlines(children)}\n </Markdown>\n );\n}\n\n// Agent networks emit their text with literal `\\n`. Only unescape when the text\n// has no real newline, otherwise a `\"a\\nb\"` inside a code fence gets shredded.\nfunction decodeEscapedNewlines(text: string): string {\n return text.includes('\\n') ? text : text.replace(/\\\\n/g, '\\n');\n}\n\ntype MarkdownNode = NonNullable<ExtraProps['node']>;\n\nfunction languageOf(node: MarkdownNode): string | undefined {\n const classNames = node.properties.className;\n if (!Array.isArray(classNames)) return undefined;\n\n const language = classNames.find(entry => typeof entry === 'string' && entry.startsWith('language-'));\n return typeof language === 'string' ? language.slice('language-'.length) : undefined;\n}\n\nfunction fencedCode(node: MarkdownNode | undefined): { code: string; language?: string } | undefined {\n const child = node?.children.find(entry => entry.type === 'element' && entry.tagName === 'code');\n if (child?.type !== 'element') return undefined;\n\n const code = child.children.map(entry => (entry.type === 'text' ? entry.value : '')).join('');\n return { code: code.replace(/\\n$/, ''), language: languageOf(child) };\n}\n\nfunction MarkdownCodeBlock({ node, children }: { node?: MarkdownNode; children?: ReactNode }) {\n const fenced = fencedCode(node);\n if (!fenced) return <pre>{children}</pre>;\n\n return (\n <CodeBlock\n code={fenced.code}\n lang={fenced.language}\n overflow=\"scroll\"\n className=\"bg-surface1 my-3\"\n copyMessage=\"Copied code to clipboard\"\n />\n );\n}\n\nconst POPUP_WINDOW_FEATURES = 'popup=yes,width=720,height=800,resizable=yes,scrollbars=yes';\n\nfunction isPlainLeftClick(event: MouseEvent): boolean {\n return event.button === 0 && !event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey;\n}\n\nfunction markdownLink(externalLinkTarget: MarkdownExternalLinkTarget): NonNullable<Components['a']> {\n return function MarkdownLink({ href, title, children }) {\n const isExternal = /^https?:\\/\\//i.test(href ?? '');\n\n const openInPopup: MouseEventHandler<HTMLAnchorElement> = event => {\n if (!isExternal || externalLinkTarget !== 'window' || !isPlainLeftClick(event)) return;\n\n const popup = window.open(href, '_blank', POPUP_WINDOW_FEATURES);\n if (!popup) return;\n\n popup.opener = null;\n event.preventDefault();\n };\n\n return (\n <a\n href={href}\n title={title}\n onClick={openInPopup}\n target={isExternal ? '_blank' : undefined}\n rel={isExternal ? 'noopener noreferrer' : undefined}\n >\n {children}\n </a>\n );\n };\n}\n\n// Elements are listed one by one: react-markdown also passes its `node`, which\n// React would forward to the DOM as a stray attribute. Everything else is\n// styled from markdown-renderer.css.\nconst COMPONENTS: Components = {\n pre: MarkdownCodeBlock,\n a: markdownLink('tab'),\n};\n\nconst WINDOW_COMPONENTS: Components = {\n ...COMPONENTS,\n a: markdownLink('window'),\n};\n"],"names":[],"mappings":"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"}