- [breaking] replace the question/response
Conversationmodel with a flat, role-basedMessagelist to support agentic workflows - [breaking]
SessionMessagepropconversationrenamed tomessage; rendering is now driven bymessage.role - [breaking]
SessionMessagesrender prop now receivesMessage[]instead ofConversation[] - [breaking]
MessageActionspropsquestion/responsereplaced by a singlemessage - [breaking] theme keys
messages.message.question/.responserenamed to.user/.assistant - [breaking]
useAgUihelpersaddConversationToSession/updateConversationInSessionrenamed toaddMessageToSession/updateMessageInSession - [feature] new
MessageandMessageRoletypes —user,assistant,system,tooland custom role strings - [feature] new theme keys
messages.message.systemandmessages.message.tool - [feature]
useAgUipreserves AG-UI text-message IDs and boundaries, records pending tool calls asrole: 'tool'activity, and replaces their content withTOOL_CALL_RESULTdata before including them in later history - [feature] new
conversationsToMessages()andgetSessionMessages()utilities for normalizing session data - [feature] multi-user / multi-agent sessions — new
MessageAuthortype and optionalMessage.author;SessionMessagerenders an avatar + name header via the newMessageAuthorBadgecomponent (opt out withshowAuthor={false}) - [feature] new theme key
messages.message.author(base,avatar,name) for the author header - [feature] custom message roles are now fully assistant-like — they render the
MessageActionsfooter and the streaming cursor, not just the assistant theme class - [deprecation]
Conversation,Session.conversations,MessageQuestionandMessageResponseare deprecated but still work
The legacy conversations array is still accepted and converted internally, so
existing apps that only pass session data keep working without changes. The
breaking parts are the component props and theme keys.
| Before | After |
|---|---|
session.conversations: Conversation[] |
session.messages: Message[] (legacy conversations still accepted, auto-converted) |
{ question, response } |
two messages: { role: 'user', content } and { role: 'assistant', content } |
<SessionMessages>{convos => ...}</SessionMessages> |
<SessionMessages>{messages => ...}</SessionMessages> |
<SessionMessage conversation={c} /> |
<SessionMessage message={m} /> |
<MessageActions question={q} response={r} /> |
<MessageActions message={m} /> |
<MessageQuestion question={q} /> / <MessageResponse response={r} /> |
<SessionMessage message={m} /> (wrappers kept, deprecated) |
theme.messages.message.question / .response |
theme.messages.message.user / .assistant (plus new system, tool) |
addConversationToSession / updateConversationInSession |
addMessageToSession / updateMessageInSession |
Do nothing and rely on the deprecated auto-conversion:
// Still works — converted via getSessionMessages() internally
const sessions = [
{
id: '1',
title: 'Weather',
conversations: [
{
id: 'c1',
createdAt: new Date(),
question: 'What is the weather?',
response: 'Sunny and 72°F.'
}
]
}
];Or move to messages:
import type { Session } from 'reachat';
const sessions: Session[] = [
{
id: '1',
title: 'Weather',
messages: [
{
id: 'm1',
role: 'user',
content: 'What is the weather?',
createdAt: new Date()
},
{
id: 'm2',
role: 'assistant',
content: 'Sunny and 72°F.',
createdAt: new Date()
}
]
}
];To convert stored data up front, use the exported helpers:
import { conversationsToMessages, getSessionMessages } from 'reachat';
// Convert a legacy conversation array
const converted = conversationsToMessages(session.conversations);
// Or normalize any session, new or legacy, into a Message[]
const messages = getSessionMessages(session);getSessionMessages() returns session.messages when present and falls back to
converting session.conversations. Prefer it anywhere you read messages off a
session.
// Before
<SessionMessages>
{conversations =>
conversations.map((conversation, i) => (
<SessionMessage
key={conversation.id}
conversation={conversation}
isLast={i === conversations.length - 1}
/>
))
}
</SessionMessages>
// After
<SessionMessages>
{messages =>
messages.map((message, i) => (
<SessionMessage
key={message.id}
message={message}
isLast={i === messages.length - 1}
/>
))
}
</SessionMessages>Each message renders in its own card, so a session is now a stream of message
cards rather than question/response pair cards. SessionMessage picks its
presentation from message.role: user renders files plus the expandable
markdown content, assistant renders markdown with sources, actions and the
loading cursor, and system/tool/custom roles use assistant-style content
with their own theme class.
// Before
const theme = {
messages: { message: { question: '...', response: '...' } }
};
// After
const theme = {
messages: {
message: {
user: '...',
assistant: '...',
system: '...', // new — muted, centered informational style
tool: '...' // new — compact style for tool activity
}
}
};useAgUi's public API (sessions, sendMessage, stopMessage, …) is
unchanged, but the sessions it produces are now message-based and tool calls
appear as role: 'tool' messages:
[
{ id: '…', role: 'user', content: 'Weather in Paris?' },
{ id: '…', role: 'assistant', content: 'Let me check.' },
{
id: '…',
role: 'tool',
content: '18°C and sunny',
metadata: {
toolCallId: 'call_1',
toolCallName: 'get_weather',
args: '{"location":"Paris"}',
toolCallStatus: 'complete'
}
},
{ id: '…', role: 'assistant', content: 'It is 18°C and sunny.' }
]Text events are grouped by their AG-UI messageId, so a single run can produce
multiple consecutive assistant messages without collapsing their boundaries.
Pending tool activity is displayed immediately but omitted from later AG-UI
history until TOOL_CALL_RESULT supplies the actual content. The module-level
helpers addConversationToSession/updateConversationInSession were renamed to
addMessageToSession/updateMessageInSession; the old names are removed. See
src/useAgUi/README.md for details.
- [chore] improve
Markdownto supply its own defaults rather than rely onChatto provide them
- [chore] decouple
MarkdownfromChatContextandChatThemeso it can live on its own.
- [breaking] Remove UMD build (ESM-only) and modernize build tooling — Vite 8/Rolldown, ESLint 9 flat config, TypeScript 6, Vitest 4 #100
- [chore] improve docs
- [chore] upgrade depedencies
- [feature] Add onMessageChange callback to ChatInput #96
- [fix] Fix remarkCve to produce valid inline link nodes #97
- [fix] Add className prop to ChatInput component #95
- [feature] Add autoScroll for SessionMessages #93
- [feature] Add multi-file support #91
- [feature] Extend Markdown theme and CodeHighlighter functionality #90
- [fix] export PartialChatTheme #94
- [fix] Misc Improvements #92
- [breaking] upgrade reablocks to v10 (Button
startAdornment/endAdornmentrenamed tostart/end) - [breaking] upgrade React to v19
- [breaking] upgrade Storybook to v10
- [breaking] upgrade Vite to v7
- [chore] upgrade react-markdown to v10
- [chore] upgrade vitest to v3
- [chore] upgrade TypeScript to v5.9
- [chore] upgrade @vitejs/plugin-react to v5
- [chore] switch tsconfig moduleResolution to bundler
- [chore] add @tiptap/suggestion and @tiptap/extensions as dependencies
- [chore] remove deprecated @types/classnames
- [chore] remove consolidated Storybook packages (addon-essentials, addon-mdx-gfm, addon-storysource, manager-api, preview-api, theming)
- [chore] update CI workflows to Node.js 22
- [feature] add visual regression testing with @storybook/test-runner
- [feature] implement component catalog for dynamic components
- [breaking] update charts components to leverage new component library
- [chore] upgrade typescript
- [feature] ag-ui protocol adapter
- [feature] redact plugin and support for other plugins
- [improvement] improve performance and rendering
- [fix] bump vuln package
- [fix] improve lodash import for esm
- [feature] Add RichTextInput component with Tiptap v3 integration #78
- [feature] Add @mentions support with floating suggestion popup
- [feature] Add /slash commands support with keyboard navigation
- [feature] Add MentionList component for autocomplete suggestions
- [feature] Add SuggestionConfig type for dynamic/async search
- [feature] Add Floating UI integration for smart popup positioning
- [feature] Add ARIA accessibility attributes to suggestion popups
- [feature] Add ChartRenderer component with 7 chart types support #73
- [feature] Add bar, line, area, pie, radialBar, radialArea, and sparkline charts
- [feature] Add remarkChart plugin for markdown chart rendering
- [feature] Add ChartError component for validation and error handling
- [feature] Add chart theme customization support
- [feature] Add data validation for chart configurations
- [feature] Add reaviz integration for chart visualizations
- [feature] Add markdownComponents prop to Chat for custom component overrides
- [feature] Add ChatSuggestions component for clickable suggestion chips
- [feature] Add custom render support for suggestion items
- [feature] Add MessageStatus component with loading/complete/error states
- [feature] Add multi-step status display with animated transitions
- [feature] Add MessageStatusItem and StatusIcon for status visualization
- [chore] Export stories for docs website #56
- [feature] Update ChatBubble component
- [feature] Tailwind 4 Upgrade
- [feature] export styles
-
[feature] Add ChatBubble component
- [feature] Tailwind 4 Upgrade
- [fix] fix ChatBubble global export
- [feature] Add AppBar component for customizable headers
- [feature] Add Templates support to predefined user prompts
- [feature] Add ChatBubble component for floating chat interfaces
- [chore] chore: update dependencies and fix vulnerabilities #44
- [feature] Add CSV Viewer to MessageFiles #42
- [chore] Update motion lib
- [chore] fix broken images
- [chore] update reablocks
- [feature] add masonary grid on image uploads
- [fix] fix katex failing next builds
- [fix] fix focus on session change
- [feature] simplify code setup
- [chore] Update theme
- [chore] First publish