Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions packages/compass-assistant/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
"types": "./dist/index.d.ts",
"scripts": {
"bootstrap": "npm run compile",
"clean": "node -e \"fs.rmSync('dist', { recursive: true, force: true })\" || true",
"precompile": "npm run clean",
"compile": "tsc -p tsconfig.json",
"typecheck": "tsc -p tsconfig-lint.json --noEmit",
"eslint": "eslint-compass",
Expand All @@ -53,13 +55,13 @@
"@mongodb-js/atlas-service": "^0.56.0",
"@mongodb-js/compass-app-registry": "^9.4.20",
"@mongodb-js/compass-components": "^1.49.0",
"@mongodb-js/compass-generative-ai": "^0.51.0",
"@mongodb-js/compass-logging": "^1.7.12",
"@mongodb-js/compass-telemetry": "^1.14.0",
"@mongodb-js/connection-info": "^0.17.1",
"@mongodb-js/compass-logging": "^1.7.12",
"@mongodb-js/compass-generative-ai": "^0.51.0",
"mongodb-connection-string-url": "^3.0.1",
"ai": "^5.0.26",
"compass-preferences-model": "^2.51.0",
"mongodb-connection-string-url": "^3.0.1",
"react": "^17.0.2",
"throttleit": "^2.1.0",
"use-sync-external-store": "^1.5.0"
Expand Down
65 changes: 60 additions & 5 deletions packages/compass-assistant/src/assistant-chat.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
import { AssistantChat } from './assistant-chat';
import { expect } from 'chai';
import { createMockChat } from '../test/utils';
import type { ConnectionInfo } from '@mongodb-js/connection-info';
import {
AssistantActionsContext,
type AssistantMessage,
Expand Down Expand Up @@ -36,13 +37,14 @@ describe('AssistantChat', function () {
function renderWithChat(
messages: AssistantMessage[],
{
connections,
status,
}: {
connections?: ConnectionInfo[];
status?: 'submitted' | 'streaming';
} = {}
) {
const chat = createMockChat({ messages, status });

// The chat component does not use chat.sendMessage() directly, it uses
// ensureOptInAndSend() via the AssistantActionsContext.
const ensureOptInAndSendStub = sinon
Expand All @@ -59,8 +61,11 @@ describe('AssistantChat', function () {
};
const result = render(
<AssistantActionsContext.Provider value={assistantActionsContext as any}>
<AssistantChat chat={chat} />
</AssistantActionsContext.Provider>
<AssistantChat chat={chat} hasNonGenuineConnections={false} />
</AssistantActionsContext.Provider>,
{
connections,
}
);
return {
result,
Expand Down Expand Up @@ -180,8 +185,58 @@ describe('AssistantChat', function () {
);
});

it('calls ensureOptInAndSend when form is submitted', async function () {
const { ensureOptInAndSendStub, result } = renderWithChat([]);
describe('non-genuine MongoDB host handling', function () {
it('shows warning message in chat when connected to non-genuine MongoDB', function () {
const chat = createMockChat({ messages: [] });
render(<AssistantChat chat={chat} hasNonGenuineConnections={true} />);

expect(chat.messages).to.have.length(1);
expect(chat.messages[0].id).to.equal('non-genuine-warning');

const warningMessage = screen.getByText(
/MongoDB Assistant will not provide accurate guidance for non-genuine hosts/
);
expect(warningMessage).to.exist;
});

it('does not show warning message when all connections are genuine', function () {
const chat = createMockChat({ messages: [] });
render(<AssistantChat chat={chat} hasNonGenuineConnections={false} />, {
connections: [],
});

const warningMessage = screen.queryByText(
/MongoDB Assistant will not provide accurate guidance for non-genuine hosts/
);
expect(warningMessage).to.not.exist;
});

it('warning message is removed when all active connections are changed to genuine', async function () {
const chat = createMockChat({ messages: [] });
const { rerender } = render(
<AssistantChat chat={chat} hasNonGenuineConnections={true} />,
{}
);

expect(
screen.getByText(
/MongoDB Assistant will not provide accurate guidance for non-genuine hosts/
)
).to.exist;

rerender(<AssistantChat chat={chat} hasNonGenuineConnections={false} />);

await waitFor(() => {
const warningMessage = screen.queryByText(
/MongoDB Assistant will not provide accurate guidance for non-genuine hosts/
);
expect(warningMessage).to.not.exist;
});
});
});

it('calls sendMessage when form is submitted', async function () {
const { result, ensureOptInAndSendStub } = renderWithChat([]);
const { track } = result;
const inputField = screen.getByPlaceholderText(
'Ask MongoDB Assistant a question'
Expand Down
25 changes: 23 additions & 2 deletions packages/compass-assistant/src/assistant-chat.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback, useContext } from 'react';
import React, { useCallback, useEffect, useContext } from 'react';
import type { AssistantMessage } from './compass-assistant-provider';
import { AssistantActionsContext } from './compass-assistant-provider';
import type { Chat } from './@ai-sdk/react/chat-react';
Expand All @@ -20,6 +20,7 @@ import {
Link,
} from '@mongodb-js/compass-components';
import { useTelemetry } from '@mongodb-js/compass-telemetry/provider';
import { NON_GENUINE_WARNING_MESSAGE } from './preset-messages';

const { DisclaimerText } = LgChatChatDisclaimer;
const { ChatWindow } = LgChatChatWindow;
Expand All @@ -32,6 +33,7 @@ const GEN_AI_FAQ_LINK = 'https://www.mongodb.com/docs/generative-ai-faq/';

interface AssistantChatProps {
chat: Chat<AssistantMessage>;
hasNonGenuineConnections: boolean;
}

const assistantChatStyles = css({
Expand Down Expand Up @@ -127,11 +129,13 @@ const errorBannerWrapperStyles = css({

export const AssistantChat: React.FunctionComponent<AssistantChatProps> = ({
chat,
hasNonGenuineConnections,
}) => {
const track = useTelemetry();
const darkMode = useDarkMode();

const { ensureOptInAndSend } = useContext(AssistantActionsContext);
const { messages, status, error, clearError } = useChat({
const { messages, status, error, clearError, setMessages } = useChat({
chat,
onError: (error) => {
track('Assistant Response Failed', () => ({
Expand All @@ -140,6 +144,23 @@ export const AssistantChat: React.FunctionComponent<AssistantChatProps> = ({
},
});

useEffect(() => {
const hasExistingNonGenuineWarning = chat.messages.some(
(message) => message.id === 'non-genuine-warning'
);
if (hasNonGenuineConnections && !hasExistingNonGenuineWarning) {
setMessages((messages) => {
return [NON_GENUINE_WARNING_MESSAGE, ...messages];
});
} else if (hasExistingNonGenuineWarning && !hasNonGenuineConnections) {
setMessages((messages) => {
return messages.filter(
(message) => message.id !== 'non-genuine-warning'
);
});
}
}, [hasNonGenuineConnections, chat, setMessages]);

// Transform AI SDK messages to LeafyGreen chat format and reverse the order of the messages
// for displaying it correctly with flex-direction: column-reverse.
const lgMessages = messages
Expand Down
8 changes: 6 additions & 2 deletions packages/compass-assistant/src/compass-assistant-drawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ const assistantTitleTextStyles = css({
*/
export const CompassAssistantDrawer: React.FunctionComponent<{
autoOpen?: boolean;
}> = ({ autoOpen }) => {
hasNonGenuineConnections?: boolean;
}> = ({ autoOpen, hasNonGenuineConnections = false }) => {
const chat = useContext(AssistantContext);
const { clearChat } = useContext(AssistantActionsContext);

Expand Down Expand Up @@ -88,7 +89,10 @@ export const CompassAssistantDrawer: React.FunctionComponent<{
glyph="Sparkle"
autoOpen={autoOpen}
>
<AssistantChat chat={chat} />
<AssistantChat
chat={chat}
hasNonGenuineConnections={hasNonGenuineConnections}
/>
</DrawerSection>
);
};
Loading
Loading