diff --git a/packages/chat-client/src/components/MemoryView.jsx b/packages/chat-client/src/components/MemoryView.jsx index fadc325..8ff20fb 100644 --- a/packages/chat-client/src/components/MemoryView.jsx +++ b/packages/chat-client/src/components/MemoryView.jsx @@ -1,5 +1,6 @@ import React, { useState, useEffect, useCallback } from 'react'; import { getEpisodes, deleteEpisode } from '../api/orchestration'; +import ReactMarkdown from 'react-markdown'; const PAGE_SIZE = 20; @@ -41,6 +42,8 @@ export default function MemoryView({ onNavigate }) { load(); } + + const totalPages = Math.ceil(total / PAGE_SIZE); const currentPage = Math.floor(offset / PAGE_SIZE) + 1; @@ -119,9 +122,20 @@ export default function MemoryView({ onNavigate }) { ); } +function stripMarkdown(text) { + return text + .replace(/\*\*(.*?)\*\*/g, '$1') // bold + .replace(/\*(.*?)\*/g, '$1') // italic + .replace(/`([^`]+)`/g, '$1') // inline code + .replace(/^#{1,6}\s+/gm, '') // headings + .replace(/^\s*[-*+]\s+/gm, '') // list markers + .trim(); +} + function EpisodeCard({ episode, expanded, onToggle, onDelete }) { const date = new Date(episode.created_at * 1000).toLocaleString(); - const preview = episode.user_message.slice(0, 80) + (episode.user_message.length > 80 ? '…' : ''); + const preview = stripMarkdown(episode.user_message).slice(0, 80) + + (episode.user_message.length > 80 ? '…' : ''); return (

{label}

-

{content}

+

{children}

, + ul: ({children}) => , + ol: ({children}) =>
    {children}
, + li: ({children}) =>
  • {children}
  • , + code: ({inline, children}) => inline + ? {children} + :
    {children}
    , + strong: ({children}) => {children}, + }} + >{content}
    +
    ); } \ No newline at end of file diff --git a/packages/chat-client/src/components/MessageBubble.jsx b/packages/chat-client/src/components/MessageBubble.jsx index b543126..618f93c 100644 --- a/packages/chat-client/src/components/MessageBubble.jsx +++ b/packages/chat-client/src/components/MessageBubble.jsx @@ -34,22 +34,20 @@ export default function MessageBubble({ message }) { border: isUser ? 'none' : '1px solid var(--border)', wordBreak: 'break-word', }}> - {isUser - ? message.text - :

    {children}

    , - ul: ({children}) => , - ol: ({children}) =>
      {children}
    , - li: ({children}) =>
  • {children}
  • , - code: ({inline, children}) => inline - ? {children} - :
    {children}
    , - strong: ({children}) => {children}, - }} - >{message.text}
    - } +

    {children}

    , + ul: ({ children }) => , + ol: ({ children }) =>
      {children}
    , + li: ({ children }) =>
  • {children}
  • , + code: ({ inline, children }) => inline + ? {children} + :
    {children}
    , + strong: ({ children }) => {children}, + }} + >{message.text}
    + {message.streaming && (