diff --git a/packages/compass-assistant/src/assistant-chat.spec.tsx b/packages/compass-assistant/src/assistant-chat.spec.tsx index c4111c8882a..00687a84f19 100644 --- a/packages/compass-assistant/src/assistant-chat.spec.tsx +++ b/packages/compass-assistant/src/assistant-chat.spec.tsx @@ -4,6 +4,7 @@ import { screen, userEvent, waitFor, + within, } from '@mongodb-js/testing-library-compass'; import { AssistantChat } from './assistant-chat'; import { expect } from 'chai'; @@ -30,6 +31,12 @@ describe('AssistantChat', function () { type: 'text', text: 'Hello! How can I help you with MongoDB today?', }, + { + type: 'source-url', + title: 'MongoDB', + url: 'https://en.wikipedia.org/wiki/MongoDB', + sourceId: '1', + }, ], }, ]; @@ -471,16 +478,14 @@ describe('AssistantChat', function () { ); // First click thumbs down to potentially open feedback form - const thumbsDownButton = assistantMessage.querySelector( - '[aria-label="Thumbs Down Icon"]' - ) as HTMLElement; + const thumbsDownButton = within(assistantMessage).getByLabelText( + 'Dislike this message' + ); userEvent.click(thumbsDownButton); // Look for feedback text area (the exact implementation depends on LeafyGreen) - const feedbackTextArea = screen.getByTestId( - 'lg-chat-message_actions-feedback_textarea' - ); + const feedbackTextArea = within(assistantMessage).getByRole('textbox'); userEvent.type(feedbackTextArea, 'This response was not helpful'); @@ -527,4 +532,33 @@ describe('AssistantChat', function () { expect(screen.queryByLabelText('Thumbs Down Icon')).to.not.exist; }); }); + + describe('related sources', function () { + it('displays related resources links for assistant messages that include them', async function () { + renderWithChat(mockMessages); + userEvent.click(screen.getByLabelText('Expand Related Resources')); + + // TODO(COMPASS-9860) can't find the links in test-electron on RHEL and Ubuntu. + if ((process as any).type === 'renderer') { + return this.skip(); + } + + await waitFor(() => { + expect(screen.getByRole('link', { name: 'MongoDB' })).to.have.attribute( + 'href', + 'https://en.wikipedia.org/wiki/MongoDB' + ); + }); + }); + + it('does not display related resources section when there are no source-url parts', function () { + const messages = mockMessages.map((message) => ({ + ...message, + parts: message.parts.filter((part) => part.type !== 'source-url'), + })); + renderWithChat(messages); + + expect(screen.queryByLabelText('Expand Related Resources')).to.not.exist; + }); + }); }); diff --git a/packages/compass-assistant/src/assistant-chat.tsx b/packages/compass-assistant/src/assistant-chat.tsx index b727cbc345c..5934c3fea7c 100644 --- a/packages/compass-assistant/src/assistant-chat.tsx +++ b/packages/compass-assistant/src/assistant-chat.tsx @@ -7,7 +7,6 @@ import { LgChatChatWindow, LgChatLeafygreenChatProvider, LgChatMessage, - LgChatMessageActions, LgChatInputBar, spacing, css, @@ -26,7 +25,6 @@ const { DisclaimerText } = LgChatChatDisclaimer; const { ChatWindow } = LgChatChatWindow; const { LeafyGreenChatProvider, Variant } = LgChatLeafygreenChatProvider; const { Message } = LgChatMessage; -const { MessageActions } = LgChatMessageActions; const { InputBar } = LgChatInputBar; const GEN_AI_FAQ_LINK = 'https://www.mongodb.com/docs/generative-ai-faq/'; @@ -141,6 +139,12 @@ const errorBannerWrapperStyles = css({ margin: spacing[400], }); +const messagesWrapStyles = css({ + display: 'flex', + flexDirection: 'column', + gap: spacing[400], +}); + export const AssistantChat: React.FunctionComponent = ({ chat, hasNonGenuineConnections, @@ -185,6 +189,13 @@ export const AssistantChat: React.FunctionComponent = ({ .map((part) => part.text) .join(''), isSender: message.role === 'user', + sources: message.parts + .filter((part) => part.type === 'source-url') + .map((part) => ({ + children: part.title || 'Documentation Link', + href: part.url, + variant: 'Docs', + })), })); const handleMessageSend = useCallback( @@ -247,7 +258,7 @@ export const AssistantChat: React.FunctionComponent = ({ data-testid="assistant-chat-messages" className={messageFeedFixesStyles} > -
+
{lgMessages.map((messageFields) => ( = ({ data-testid={`assistant-message-${messageFields.id}`} > {messageFields.isSender === false && ( - )} + {messageFields.sources.length > 0 && ( + + )} ))}
diff --git a/packages/compass-assistant/src/docs-provider-transport.ts b/packages/compass-assistant/src/docs-provider-transport.ts index 6db18fd0190..1cdc5bc3c1a 100644 --- a/packages/compass-assistant/src/docs-provider-transport.ts +++ b/packages/compass-assistant/src/docs-provider-transport.ts @@ -40,7 +40,7 @@ export class DocsProviderTransport implements ChatTransport { }, }); - return Promise.resolve(result.toUIMessageStream()); + return Promise.resolve(result.toUIMessageStream({ sendSources: true })); } reconnectToStream(): Promise | null> { diff --git a/packages/compass-assistant/src/prompts.ts b/packages/compass-assistant/src/prompts.ts index 8dfaf6dff67..067ea2a29b9 100644 --- a/packages/compass-assistant/src/prompts.ts +++ b/packages/compass-assistant/src/prompts.ts @@ -33,6 +33,8 @@ You CANNOT: 2. Query MongoDB directly or execute code. 3. Access the current state of the UI + +Always call the 'search_content' tool when asked a technical question that would benefit from getting relevant info from the documentation. `; }; diff --git a/packages/compass-assistant/test/assistant.eval.ts b/packages/compass-assistant/test/assistant.eval.ts index c619536613c..64c13e86f6d 100644 --- a/packages/compass-assistant/test/assistant.eval.ts +++ b/packages/compass-assistant/test/assistant.eval.ts @@ -178,7 +178,6 @@ async function makeAssistantCall( const sources = resolvedSources .map((source) => { - console.log(source); return source.url; }) .filter((url) => !!url);