added react-markdown
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import React, { useState, useEffect, useCallback } from 'react';
|
import React, { useState, useEffect, useCallback } from 'react';
|
||||||
import { getEpisodes, deleteEpisode } from '../api/orchestration';
|
import { getEpisodes, deleteEpisode } from '../api/orchestration';
|
||||||
|
import ReactMarkdown from 'react-markdown';
|
||||||
|
|
||||||
const PAGE_SIZE = 20;
|
const PAGE_SIZE = 20;
|
||||||
|
|
||||||
@@ -41,6 +42,8 @@ export default function MemoryView({ onNavigate }) {
|
|||||||
load();
|
load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const totalPages = Math.ceil(total / PAGE_SIZE);
|
const totalPages = Math.ceil(total / PAGE_SIZE);
|
||||||
const currentPage = Math.floor(offset / PAGE_SIZE) + 1;
|
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 }) {
|
function EpisodeCard({ episode, expanded, onToggle, onDelete }) {
|
||||||
const date = new Date(episode.created_at * 1000).toLocaleString();
|
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 (
|
return (
|
||||||
<div style={{
|
<div style={{
|
||||||
@@ -156,12 +170,25 @@ function EpisodeCard({ episode, expanded, onToggle, onDelete }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function MessageBlock({ label, content, color }) {
|
function MessageBlock({ label, content, color }) {
|
||||||
|
const isAI = label === 'NexusAI';
|
||||||
return (
|
return (
|
||||||
<div style={{ marginTop: 12 }}>
|
<div style={{ marginTop: 12 }}>
|
||||||
<p style={{ fontSize: 11, fontWeight: 600, color, marginBottom: 4, textTransform: 'uppercase', letterSpacing: '0.05em' }}>
|
<p style={{ fontSize: 11, fontWeight: 600, color, marginBottom: 4, textTransform: 'uppercase', letterSpacing: '0.05em' }}>
|
||||||
{label}
|
{label}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-sm" style={{ whiteSpace: 'pre-wrap', lineHeight: 1.6 }}>{content}</p>
|
<ReactMarkdown
|
||||||
|
components={{
|
||||||
|
p: ({children}) => <p style={{ margin: '0 0 8px', lineHeight: 1.6, fontSize: 13 }}>{children}</p>,
|
||||||
|
ul: ({children}) => <ul style={{ margin: '0 0 8px', paddingLeft: '20px' }}>{children}</ul>,
|
||||||
|
ol: ({children}) => <ol style={{ margin: '0 0 8px', paddingLeft: '20px' }}>{children}</ol>,
|
||||||
|
li: ({children}) => <li style={{ marginBottom: '2px', fontSize: 13 }}>{children}</li>,
|
||||||
|
code: ({inline, children}) => inline
|
||||||
|
? <code style={{ background: 'var(--bg-elevated)', padding: '1px 5px', borderRadius: 'var(--radius-sm)', fontSize: 12, fontFamily: 'monospace' }}>{children}</code>
|
||||||
|
: <pre style={{ background: 'var(--bg-elevated)', padding: '10px 12px', borderRadius: 'var(--radius-md)', overflowX: 'auto', fontSize: 12, fontFamily: 'monospace' }}><code>{children}</code></pre>,
|
||||||
|
strong: ({children}) => <strong style={{ fontWeight: 600, color: 'var(--text-primary)' }}>{children}</strong>,
|
||||||
|
}}
|
||||||
|
>{content}</ReactMarkdown>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -34,22 +34,20 @@ export default function MessageBubble({ message }) {
|
|||||||
border: isUser ? 'none' : '1px solid var(--border)',
|
border: isUser ? 'none' : '1px solid var(--border)',
|
||||||
wordBreak: 'break-word',
|
wordBreak: 'break-word',
|
||||||
}}>
|
}}>
|
||||||
{isUser
|
<ReactMarkdown
|
||||||
? message.text
|
components={{
|
||||||
: <ReactMarkdown
|
// Tighten up default spacing so it fits the bubble style
|
||||||
components={{
|
p: ({ children }) => <p style={{ margin: '0 0 8px', lineHeight: 1.6 }}>{children}</p>,
|
||||||
// Tighten up default spacing so it fits the bubble style
|
ul: ({ children }) => <ul style={{ margin: '0 0 8px', paddingLeft: '20px' }}>{children}</ul>,
|
||||||
p: ({children}) => <p style={{ margin: '0 0 8px', lineHeight: 1.6 }}>{children}</p>,
|
ol: ({ children }) => <ol style={{ margin: '0 0 8px', paddingLeft: '20px' }}>{children}</ol>,
|
||||||
ul: ({children}) => <ul style={{ margin: '0 0 8px', paddingLeft: '20px' }}>{children}</ul>,
|
li: ({ children }) => <li style={{ marginBottom: '2px' }}>{children}</li>,
|
||||||
ol: ({children}) => <ol style={{ margin: '0 0 8px', paddingLeft: '20px' }}>{children}</ol>,
|
code: ({ inline, children }) => inline
|
||||||
li: ({children}) => <li style={{ marginBottom: '2px' }}>{children}</li>,
|
? <code style={{ background: 'var(--bg-elevated)', padding: '1px 5px', borderRadius: 'var(--radius-sm)', fontSize: '12px', fontFamily: 'monospace' }}>{children}</code>
|
||||||
code: ({inline, children}) => inline
|
: <pre style={{ background: 'var(--bg-elevated)', padding: '10px 12px', borderRadius: 'var(--radius-md)', overflowX: 'auto', fontSize: '12px', fontFamily: 'monospace' }}><code>{children}</code></pre>,
|
||||||
? <code style={{ background: 'var(--bg-elevated)', padding: '1px 5px', borderRadius: 'var(--radius-sm)', fontSize: '12px', fontFamily: 'monospace' }}>{children}</code>
|
strong: ({ children }) => <strong style={{ fontWeight: 600, color: 'var(--text-primary)' }}>{children}</strong>,
|
||||||
: <pre style={{ background: 'var(--bg-elevated)', padding: '10px 12px', borderRadius: 'var(--radius-md)', overflowX: 'auto', fontSize: '12px', fontFamily: 'monospace' }}><code>{children}</code></pre>,
|
}}
|
||||||
strong: ({children}) => <strong style={{ fontWeight: 600, color: 'var(--text-primary)' }}>{children}</strong>,
|
>{message.text}</ReactMarkdown>
|
||||||
}}
|
|
||||||
>{message.text}</ReactMarkdown>
|
|
||||||
}
|
|
||||||
{message.streaming && (
|
{message.streaming && (
|
||||||
<span style={{
|
<span style={{
|
||||||
display: 'inline-block',
|
display: 'inline-block',
|
||||||
|
|||||||
Reference in New Issue
Block a user