From 7a1f5418b33bac4320ab3c9dfba136bbd85c586f Mon Sep 17 00:00:00 2001 From: Nate Kelley Date: Mon, 10 Feb 2025 12:24:35 -0700 Subject: [PATCH] adjust file card --- .../chat/chatMessageInterfaces.ts | 2 +- .../ReasoningMessageContainer.tsx | 4 ++ .../ReasoningMessage_File.tsx | 19 ++++++- .../AppMarkdown/AppCodeBlock/AppCodeBlock.tsx | 49 +++++++++++-------- .../text/AppMarkdown/AppCodeBlock/light.ts | 19 ++++--- .../context/Chats/ChatProvider/MOCK_CHAT.ts | 39 ++++++++++++++- 6 files changed, 98 insertions(+), 34 deletions(-) diff --git a/web/src/api/asset_interfaces/chat/chatMessageInterfaces.ts b/web/src/api/asset_interfaces/chat/chatMessageInterfaces.ts index 7e939dd1f..eff73d2f4 100644 --- a/web/src/api/asset_interfaces/chat/chatMessageInterfaces.ts +++ b/web/src/api/asset_interfaces/chat/chatMessageInterfaces.ts @@ -89,5 +89,5 @@ export type BusterChatMessageReasoning_file = { text: string; line_number: number; modified?: boolean; //defaults to true - }; //will be defined if the file has been completed OR on a page refresh + }[]; //will be defined if the file has been completed OR on a page refresh }; diff --git a/web/src/app/app/_controllers/ReasoningController/ReasoningMessageContainer.tsx b/web/src/app/app/_controllers/ReasoningController/ReasoningMessageContainer.tsx index 6ebe31de6..b82914de5 100644 --- a/web/src/app/app/_controllers/ReasoningController/ReasoningMessageContainer.tsx +++ b/web/src/app/app/_controllers/ReasoningController/ReasoningMessageContainer.tsx @@ -68,6 +68,10 @@ const useStyles = createStyles(({ token, css }) => ({ `, fileCard: css` margin-bottom: 4px; + + .vertical-divider { + display: none; + } `, verticalDivider: css` transition: opacity 0.2s ease-in-out; diff --git a/web/src/app/app/_controllers/ReasoningController/ReasoningMessages/ReasoningMessage_File/ReasoningMessage_File.tsx b/web/src/app/app/_controllers/ReasoningController/ReasoningMessages/ReasoningMessage_File/ReasoningMessage_File.tsx index 1a56b9ac3..103f82530 100644 --- a/web/src/app/app/_controllers/ReasoningController/ReasoningMessages/ReasoningMessage_File/ReasoningMessage_File.tsx +++ b/web/src/app/app/_controllers/ReasoningController/ReasoningMessages/ReasoningMessage_File/ReasoningMessage_File.tsx @@ -1,9 +1,24 @@ import React from 'react'; import { ReasoningMessageProps } from '../ReasoningMessageSelector'; +import { BusterChatMessageReasoning_file } from '@/api/asset_interfaces'; +import { AppCodeBlock } from '@/components/text/AppMarkdown/AppCodeBlock'; export const ReasoningMessage_File: React.FC = React.memo( - ({ reasoningMessage }) => { - return
asdf
; + ({ reasoningMessage, isCompletedStream, isLastMessageItem }) => { + const { file, file_name, file_type, file_chunk } = + reasoningMessage as BusterChatMessageReasoning_file; + + const showLoader = !isCompletedStream && isLastMessageItem; + + return ( + + {file?.map((chunk) => chunk.text).join('\n')} + + ); } ); diff --git a/web/src/components/text/AppMarkdown/AppCodeBlock/AppCodeBlock.tsx b/web/src/components/text/AppMarkdown/AppCodeBlock/AppCodeBlock.tsx index 8cb9ffa95..6508f2ca0 100644 --- a/web/src/components/text/AppMarkdown/AppCodeBlock/AppCodeBlock.tsx +++ b/web/src/components/text/AppMarkdown/AppCodeBlock/AppCodeBlock.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useLayoutEffect, useState } from 'react'; +import React, { useLayoutEffect, useState } from 'react'; import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; import { AppMaterialIcons } from '../../../icons'; import { createStyles } from 'antd-style'; @@ -6,7 +6,6 @@ import { Button } from 'antd'; import darkTheme from 'react-syntax-highlighter/dist/cjs/styles/prism/vsc-dark-plus'; import { Text } from '@/components/text'; import { TextPulseLoader } from '../../..'; - import { useAntToken } from '@/styles/useAntToken'; import lightTheme from './light'; import { useMemoizedFn } from 'ahooks'; @@ -20,7 +19,9 @@ export const AppCodeBlock: React.FC<{ style?: React.CSSProperties; showLoader?: boolean; showCopyButton?: boolean; -}> = React.memo((props) => { + title?: string; + buttons?: React.ReactNode; +}> = React.memo(({ title, buttons, ...props }) => { const isDarkMode = useBusterStylesContext((state) => state.isDarkMode); const { children, className = '', language, showLoader, showCopyButton = true, ...rest } = props; const [style, setStyle] = useState<{ @@ -42,17 +43,19 @@ export const AppCodeBlock: React.FC<{
{language ? ( ) : ( @@ -97,9 +100,10 @@ const CodeBlockWrapper: React.FC<{ children: React.ReactNode; isDarkMode: boolean; code: string; - language: string; + language?: string; showCopyButton: boolean; -}> = React.memo(({ children, code, showCopyButton, language }) => { + buttons?: React.ReactNode; +}> = React.memo(({ children, code, showCopyButton, language, buttons }) => { const { cx, styles } = useStyles(); const { openSuccessMessage } = useBusterNotifications(); const token = useAntToken(); @@ -113,21 +117,24 @@ const CodeBlockWrapper: React.FC<{
{language} - {showCopyButton && ( - - )} +
+ {showCopyButton && ( + + )} + {buttons} +
{children} diff --git a/web/src/components/text/AppMarkdown/AppCodeBlock/light.ts b/web/src/components/text/AppMarkdown/AppCodeBlock/light.ts index 5dcfb2cb6..b586495d7 100644 --- a/web/src/components/text/AppMarkdown/AppCodeBlock/light.ts +++ b/web/src/components/text/AppMarkdown/AppCodeBlock/light.ts @@ -1,5 +1,8 @@ import { busterAppStyleConfig } from '@/styles/busterAntDStyleConfig'; import React from 'react'; + +const token = busterAppStyleConfig.token!; + export default { 'code[class*="language-"]': { color: '#393A34', @@ -77,7 +80,7 @@ export default { border: '1px solid #dddddd' }, comment: { - color: '#008000', + color: token.colorTextTertiary, fontStyle: 'italic' }, prolog: { @@ -126,25 +129,25 @@ export default { color: '#36acaa' }, atrule: { - color: busterAppStyleConfig.token?.colorPrimary + color: token.colorPrimary }, keyword: { - color: busterAppStyleConfig.token?.colorPrimary + color: token.colorPrimary }, 'attr-value': { - color: busterAppStyleConfig.token?.colorPrimary + color: token.colorPrimary }, '.language-autohotkey .token.selector': { - color: busterAppStyleConfig.token?.colorPrimary + color: token.colorPrimary }, '.language-json .token.boolean': { - color: busterAppStyleConfig.token?.colorPrimary + color: token.colorPrimary }, '.language-json .token.number': { - color: busterAppStyleConfig.token?.colorPrimary + color: token.colorPrimary }, 'code[class*="language-css"]': { - color: busterAppStyleConfig.token?.colorPrimary + color: token.colorPrimary }, function: { color: '#393A34' diff --git a/web/src/context/Chats/ChatProvider/MOCK_CHAT.ts b/web/src/context/Chats/ChatProvider/MOCK_CHAT.ts index 2d9ef1da9..03712f912 100644 --- a/web/src/context/Chats/ChatProvider/MOCK_CHAT.ts +++ b/web/src/context/Chats/ChatProvider/MOCK_CHAT.ts @@ -5,7 +5,8 @@ import { type BusterChatMessageRequest, BusterChatMessage_fileMetadata, BusterChatMessageReasoning_thought, - BusterChatMessageReasoning_thoughtPill + BusterChatMessageReasoning_thoughtPill, + BusterChatMessageReasoning_file } from '@/api/asset_interfaces'; import { faker } from '@faker-js/faker'; @@ -86,6 +87,37 @@ export const createMockResponseMessageFile = (): BusterChatMessage_file => { }; }; +export const createMockReasoningMessageFile = (): BusterChatMessageReasoning_file => { + return { + id: 'swag', + type: 'file', + file_type: 'metric', + status: 'completed', + file_name: faker.company.name(), + version_number: 1, + version_id: faker.string.uuid(), + file: [ + { + text: 'name: my-service\nversion: 1.0.0\ndescription: A sample service', + line_number: 1, + modified: false + }, + { + text: 'dependencies:\n - name: redis\n version: 6.2.0\n - name: postgres\n version: 13.4', + line_number: 2 + }, + { + text: 'ports:\n - 8080\n - 9000\n - 6379', + line_number: 3 + }, + { + text: 'environment:\n NODE_ENV: production\n LOG_LEVEL: info\n DB_HOST: localhost', + line_number: 4 + } + ] + }; +}; + export const MOCK_CHAT: BusterChat = { id: '0', title: 'Mock Chat', @@ -95,7 +127,10 @@ export const MOCK_CHAT: BusterChat = { id: '123', created_at: '2025-01-01', request_message: createMockUserMessage(), - reasoning: [...Array.from({ length: 1 }, () => createMockResponseMessageThought())], + reasoning: [ + ...Array.from({ length: 1 }, () => createMockResponseMessageThought()), + createMockReasoningMessageFile() + ], response_messages: [ createMockResponseMessageText(), createMockResponseMessageFile(),