+
+
Rendered from streamed “MDX tree”
+
{rendered}
+
+
+ {messages.map(message => (
+
+ {message.role === 'user' ? 'User: ' : 'AI: '}
+ {message.parts.map((part, index) => {
+ if (part.type === 'text') {
+ return
{part.text};
+ }
+ if (part.type === 'data-mdxTree') {
+ return (
+
+ {JSON.stringify(part.data.tree, null, 2)}
+
+ );
+ }
+ return null;
+ })}
+
+ ))}
+
+ {(status === 'submitted' || status === 'streaming') && (
+
+ {status === 'submitted' &&
Loading...
}
+
+
+ )}
+
+ {error && (
+
+
An error occurred.
+
+
+ )}
+
+ {messages.length > 0 && (
+
+ Finish reason: {String(lastFinishReason)}
+
+ )}
+
+
sendMessage({ text })} />
+
+ );
+}
diff --git a/packages/ai/src/ui/convert-remark-mdx-to-mdx-tree.ts b/packages/ai/src/ui/convert-remark-mdx-to-mdx-tree.ts
new file mode 100644
index 000000000000..f827a5fd9b30
--- /dev/null
+++ b/packages/ai/src/ui/convert-remark-mdx-to-mdx-tree.ts
@@ -0,0 +1,190 @@
+import type { MdxTree, MdxTreeElementNode, MdxTreeNode } from './mdx-tree';
+
+/**
+ * Converts a remark/MDX AST (mdast) into the AI SDK's JSON-serializable `MdxTree`.
+ *
+ * This helper intentionally does **not** depend on remark/unified packages.
+ * It accepts `unknown` input and converts common mdast node shapes by convention.
+ *
+ * Typical server usage:
+ *
+ * - Parse markdown/MDX with your preferred remark pipeline (e.g. unified + remark-parse + remark-mdx)
+ * - Convert the resulting mdast into `MdxTree` with this function
+ * - Stream `data-mdxTree` snapshots / `data-mdxPatch` patches to clients
+ */
+export function convertRemarkMdxToMdxTree(input: unknown): MdxTree {
+ return convertNode(input);
+}
+
+type AnyRecord = Record