feat(ai): add markdown in ai chat (#13402)
This commit is contained in:
@@ -5,6 +5,7 @@ import { Avatar, IconDotsVertical, IconSparkles } from 'twenty-ui/display';
|
||||
import { LightCopyIconButton } from '@/object-record/record-field/components/LightCopyIconButton';
|
||||
import { AgentChatFilePreview } from '@/ai/components/internal/AgentChatFilePreview';
|
||||
import { AgentChatMessageRole } from '@/ai/constants/agent-chat-message-role';
|
||||
import { LazyMarkdownRenderer } from '@/ai/components/LazyMarkdownRenderer';
|
||||
|
||||
import { AgentChatMessage } from '~/generated/graphql';
|
||||
import { beautifyPastDateRelativeToNow } from '~/utils/date-utils';
|
||||
@@ -124,13 +125,17 @@ export const AIChatMessage = ({
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
|
||||
const markdownRender = (text: string) => {
|
||||
return <LazyMarkdownRenderer text={text} />;
|
||||
};
|
||||
|
||||
const getAssistantMessageContent = (message: AgentChatMessage) => {
|
||||
if (message.content !== '') {
|
||||
return message.content;
|
||||
return markdownRender(message.content);
|
||||
}
|
||||
|
||||
if (agentStreamingMessage.streamingText !== '') {
|
||||
return agentStreamingMessage.streamingText;
|
||||
return markdownRender(agentStreamingMessage.streamingText);
|
||||
}
|
||||
|
||||
if (agentStreamingMessage.toolCall !== '') {
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
import { lazy, Suspense } from 'react';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
|
||||
import { SKELETON_LOADER_HEIGHT_SIZES } from '@/activities/components/SkeletonLoader';
|
||||
|
||||
const MarkdownRenderer = lazy(async () => {
|
||||
const [{ default: Markdown }, { default: remarkGfm }] = await Promise.all([
|
||||
import('react-markdown'),
|
||||
import('remark-gfm'),
|
||||
]);
|
||||
|
||||
return {
|
||||
default: ({ children }: { children: string }) => (
|
||||
<Markdown remarkPlugins={[remarkGfm]}>{children}</Markdown>
|
||||
),
|
||||
};
|
||||
});
|
||||
|
||||
const StyledSkeletonContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const LoadingSkeleton = () => {
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<SkeletonTheme
|
||||
baseColor={theme.background.tertiary}
|
||||
highlightColor={theme.background.transparent.lighter}
|
||||
borderRadius={theme.border.radius.sm}
|
||||
>
|
||||
<StyledSkeletonContainer>
|
||||
<Skeleton
|
||||
width="70%"
|
||||
height={SKELETON_LOADER_HEIGHT_SIZES.standard.m}
|
||||
/>
|
||||
|
||||
<Skeleton height={SKELETON_LOADER_HEIGHT_SIZES.standard.s} />
|
||||
<Skeleton height={SKELETON_LOADER_HEIGHT_SIZES.standard.s} />
|
||||
<Skeleton
|
||||
width="90%"
|
||||
height={SKELETON_LOADER_HEIGHT_SIZES.standard.s}
|
||||
/>
|
||||
|
||||
<Skeleton
|
||||
width="85%"
|
||||
height={SKELETON_LOADER_HEIGHT_SIZES.standard.s}
|
||||
/>
|
||||
<Skeleton
|
||||
width="80%"
|
||||
height={SKELETON_LOADER_HEIGHT_SIZES.standard.s}
|
||||
/>
|
||||
</StyledSkeletonContainer>
|
||||
</SkeletonTheme>
|
||||
);
|
||||
};
|
||||
|
||||
export const LazyMarkdownRenderer = ({ text }: { text: string }) => {
|
||||
return (
|
||||
<Suspense fallback={<LoadingSkeleton />}>
|
||||
<MarkdownRenderer>{text}</MarkdownRenderer>
|
||||
</Suspense>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user