diff --git a/.changeset/quiet-inboxes-link.md b/.changeset/quiet-inboxes-link.md new file mode 100644 index 0000000000..d40cb192d7 --- /dev/null +++ b/.changeset/quiet-inboxes-link.md @@ -0,0 +1,5 @@ +--- +"@electric-ax/agents-server-ui": patch +--- + +Render lightweight markdown links and formatting in inbox messages. diff --git a/packages/agents-server-ui/src/components/UserMessage.module.css b/packages/agents-server-ui/src/components/UserMessage.module.css index 1ccb1d72e5..c6eeed92c4 100644 --- a/packages/agents-server-ui/src/components/UserMessage.module.css +++ b/packages/agents-server-ui/src/components/UserMessage.module.css @@ -80,10 +80,25 @@ .body { font-size: var(--ds-chat-text); line-height: var(--ds-chat-text-lh); - white-space: pre-wrap; overflow-wrap: anywhere; } +/* User-authored text gets Slack/Discord-style lightweight markdown: links + (including bare URLs), emphasis, inline/fenced code, lists and quotes. Keep + it compact inside the message bubble and preserve plain newline behavior so + ordinary chat messages still look like chat, not documents. */ +.body > div > *:first-child { + margin-top: 0; +} + +.body > div > *:last-child { + margin-bottom: 0; +} + +.body p { + white-space: pre-wrap; +} + .attachments { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(176px, 100%), 240px)); diff --git a/packages/agents-server-ui/src/components/UserMessage.tsx b/packages/agents-server-ui/src/components/UserMessage.tsx index 958360d2c1..728eeb6504 100644 --- a/packages/agents-server-ui/src/components/UserMessage.tsx +++ b/packages/agents-server-ui/src/components/UserMessage.tsx @@ -1,4 +1,5 @@ import { memo, useState } from 'react' +import { Streamdown } from 'streamdown' import { Download, File as FileIcon, @@ -8,6 +9,10 @@ import { import type { EntityTimelineSection } from '@electric-ax/agents-runtime/client' import { Icon, Stack, Text } from '../ui' import { downloadAttachment, formatAttachmentSize } from '../lib/attachments' +import { + streamdownComponents, + streamdownControls, +} from '../lib/streamdownConfig' import { AttachmentImagePreviewDialog, useAttachmentObjectUrl, @@ -82,11 +87,7 @@ export const UserMessage = memo(function UserMessage({ ))} )} - {section.text ? ( - - {section.text} - - ) : null} + {section.text ? : null} @@ -105,6 +106,42 @@ export const UserMessage = memo(function UserMessage({ ) }) +const userMessageAllowedMarkdownElements = [ + `p`, + `br`, + `a`, + `strong`, + `em`, + `del`, + `code`, + `pre`, + `blockquote`, + `ul`, + `ol`, + `li`, +] as const + +const UserMessageBody = memo(function UserMessageBody({ + text, +}: { + text: string +}): React.ReactElement { + return ( +
+ + {text} + +
+ ) +}) + function AttachmentPreview({ attachment, }: {