'use client' import ReactMarkdown from 'react-markdown' import remarkGfm from 'remark-gfm' import Link from 'next/link' import { isInternalHref } from './markdown-links' /** * Isolated so AgentChat can load the markdown parser (react-markdown + * remark-gfm and their unified/remark dependency tree) via next/dynamic: * the chunk is fetched when the first assistant message renders instead of * being parsed eagerly whenever the chat surface mounts. */ export default function MarkdownMessage({ text }: { text: string }) { return ( {text} ) } /** * Links inside an answer. * * These were plain anchors, so following one the agent had written did a full * document load: the whole app rebooted and the conversation went with it, in * the panel and in /chat alike. Internal links now route client-side, which * keeps the thread alive beside the page the user just opened, which is the * point of docking the panel in the first place. * * External links open in a new tab for the same reason, and carry * rel="noopener noreferrer": the href came out of a model that reads customer * documents, and target="_blank" without it hands the opened page a * window.opener handle back into an authenticated session. */ function MarkdownLink({ href, title, children, }: { href?: string // Markdown carries an optional title: [text](url "title"). Dropping it here // would silently discard something the answer's author wrote. title?: string children?: React.ReactNode }) { if (!href) return <>{children} if (isInternalHref(href)) { return ( {children} ) } return ( {children} ) }