import { cn } from "@openstatus/ui/lib/utils"; import type { UIMessage } from "ai"; import NextLink from "next/link"; import type { AnchorHTMLAttributes, ComponentProps, HTMLAttributes, } from "react"; import { Fragment, createElement, useDeferredValue, useMemo } from "react"; import { jsx, jsxs } from "react/jsx-runtime"; import rehypeReact from "rehype-react"; import remarkGfm from "remark-gfm"; import remarkParse from "remark-parse"; import remarkRehype from "remark-rehype"; import { unified } from "unified"; type MessageProps = HTMLAttributes & { from: UIMessage["role"]; }; export function Message({ className, from, ...props }: MessageProps) { return (
); } export function MessageContent({ className, children, ...props }: ComponentProps<"div"> & { from?: UIMessage["role"] }) { return (
{children}
); } const processor = unified() .use(remarkParse) .use(remarkGfm) .use(remarkRehype) .use(rehypeReact, { createElement, Fragment, jsx, jsxs, components: { a: ({ href, ...props }: AnchorHTMLAttributes) => { if (href?.startsWith("/")) { return ; } return ( ); }, code: (props: HTMLAttributes) => ( ), pre: (props: HTMLAttributes) => (
      ),
    } as { [key: string]: React.ComponentType },
  });

export function MessageMarkdown({ children }: { children: string }) {
  // Defer the parse so streaming token updates don't block the main thread.
  // Each chunk-driven re-render runs at high priority with the stale value;
  // the parse re-runs in a low-priority pass that React can interrupt.
  const deferred = useDeferredValue(children);
  const rendered = useMemo(
    () => processor.processSync(deferred).result,
    [deferred],
  );
  return (
    
{rendered}
); }