diff --git a/client/src/hooks/Messages/useCopyToClipboard.spec.ts b/client/src/hooks/Messages/useCopyToClipboard.spec.ts index b5059a4fd1..638e5bc9ed 100644 --- a/client/src/hooks/Messages/useCopyToClipboard.spec.ts +++ b/client/src/hooks/Messages/useCopyToClipboard.spec.ts @@ -64,7 +64,7 @@ describe('useCopyToClipboard', () => { }); }); - it('copies errors and tool input and output with surrounding text', () => { + it('copies only response text and skips tools, errors, and thinking', () => { const content = [ { type: ContentTypes.TEXT, text: 'I checked the deployment.' }, { @@ -76,7 +76,9 @@ describe('useCopyToClipboard', () => { output: '{"status":"failed"}', }, }, + { type: ContentTypes.THINK, think: 'Let me reason about this' }, { type: ContentTypes.ERROR, error: 'Deployment lookup failed' }, + { type: ContentTypes.TEXT, text: 'The service is down.' }, ] as TMessageContentParts[]; const { result } = renderHook(() => useCopyToClipboard({ content })); @@ -85,12 +87,9 @@ describe('useCopyToClipboard', () => { result.current(mockSetIsCopied); }); - const copiedText = mockCopy.mock.calls[0]?.[0]; - expect(copiedText).toContain('I checked the deployment.'); - expect(copiedText).toContain('get_deployment'); - expect(copiedText).toContain('service'); - expect(copiedText).toContain('status'); - expect(copiedText).toContain('Deployment lookup failed'); + expect(mockCopy).toHaveBeenCalledWith('I checked the deployment.\nThe service is down.', { + format: 'text/plain', + }); }); it('should reset isCopied after timeout', () => { diff --git a/client/src/hooks/Messages/useCopyToClipboard.ts b/client/src/hooks/Messages/useCopyToClipboard.ts index c0cd2aebbd..adc3d6fd54 100644 --- a/client/src/hooks/Messages/useCopyToClipboard.ts +++ b/client/src/hooks/Messages/useCopyToClipboard.ts @@ -1,8 +1,7 @@ import { useCallback, useEffect, useRef } from 'react'; import copy from 'copy-to-clipboard'; -import { SearchResultData } from 'librechat-data-provider'; +import { ContentTypes, SearchResultData } from 'librechat-data-provider'; import type { TMessage } from 'librechat-data-provider'; -import type { LocalizeFunction } from '~/common'; import { SPAN_REGEX, CLEANUP_REGEX, @@ -10,8 +9,6 @@ import { STANDALONE_PATTERN, INVALID_CITATION_REGEX, } from '~/utils/citations'; -import { formatMessageContent } from '~/hooks/Conversations/format'; -import useLocalize from '~/hooks/useLocalize'; type Source = { link: string; @@ -33,30 +30,18 @@ const refTypeMap: Record = { export function serializeMessageForClipboard({ text, content, - localize, -}: Partial> & { localize: LocalizeFunction }): string { +}: Partial>): string { if (!Array.isArray(content) || content.length === 0) { return text ?? ''; } - return content - .filter((part) => part != null) - .map((part) => { - const formatted = formatMessageContent({ - sender: '', - content: part, - format: 'text', - localize, - }); - if (formatted.length === 0) { - return ''; - } - - const [label, value] = formatted; - return label ? `${label}:\n${value}` : value; - }) - .filter((value) => value.trim().length > 0) - .join('\n'); + return content.reduce((acc, curr, i) => { + if (curr?.type === ContentTypes.TEXT) { + const partText = typeof curr.text === 'string' ? curr.text : (curr.text?.value ?? ''); + return acc + partText + (i === content.length - 1 ? '' : '\n'); + } + return acc; + }, ''); } export default function useCopyToClipboard({ @@ -66,7 +51,6 @@ export default function useCopyToClipboard({ }: Partial> & { searchResults?: { [key: string]: SearchResultData }; }) { - const localize = useLocalize(); const copyTimeoutRef = useRef(null); useEffect(() => { @@ -84,7 +68,7 @@ export default function useCopyToClipboard({ } setIsCopied(true); - const messageText = serializeMessageForClipboard({ text, content, localize }); + const messageText = serializeMessageForClipboard({ text, content }); // Early return if no search data if (!searchResults || Object.keys(searchResults).length === 0) { @@ -123,7 +107,7 @@ export default function useCopyToClipboard({ setIsCopied(false); }, 3000); }, - [text, content, searchResults, localize], + [text, content, searchResults], ); return copyToClipboard;