From 8b1664b1000dc3f0d081fbc679add1a1e058b877 Mon Sep 17 00:00:00 2001 From: gagik Date: Thu, 4 Sep 2025 11:54:16 +0200 Subject: [PATCH 1/6] chore(compass-assistant): warn about non-genuine hosts COMPASS-9675 --- .../src/assistant-chat.spec.tsx | 120 +++++++++++++++++- .../compass-assistant/src/assistant-chat.tsx | 33 ++++- .../src/compass-assistant-provider.spec.tsx | 91 ++++++++++--- .../src/compass-assistant-provider.tsx | 8 +- .../compass-assistant/src/preset-messages.ts | 17 +++ 5 files changed, 247 insertions(+), 22 deletions(-) create mode 100644 packages/compass-assistant/src/preset-messages.ts diff --git a/packages/compass-assistant/src/assistant-chat.spec.tsx b/packages/compass-assistant/src/assistant-chat.spec.tsx index 768f338c799..bd0eae1b25a 100644 --- a/packages/compass-assistant/src/assistant-chat.spec.tsx +++ b/packages/compass-assistant/src/assistant-chat.spec.tsx @@ -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, @@ -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 @@ -60,7 +62,10 @@ describe('AssistantChat', function () { const result = render( - + , + { + connections, + } ); return { result, @@ -180,8 +185,115 @@ describe('AssistantChat', function () { ); }); - it('calls ensureOptInAndSend when form is submitted', async function () { - const { ensureOptInAndSendStub, result } = renderWithChat([]); + describe('non-genuine MongoDB host handling', function () { + const nonGenuineConnectionInfo: ConnectionInfo = { + id: 'test-connection-non-genuine', + connectionOptions: { + connectionString: 'mongodb://docdb-elastic.amazonaws.com:27017', + }, + favorite: { name: 'Test Connection Non-Genuine' }, + savedConnectionType: 'recent', + }; + const genuineConnectionInfo: ConnectionInfo = { + id: 'test-connection-genuine', + connectionOptions: { + connectionString: 'mongodb://localhost:27017', // localhost is detected as genuine + }, + favorite: { name: 'Test Connection Genuine' }, + savedConnectionType: 'recent', + }; + + it('shows warning message in chat when connected to non-genuine MongoDB', async function () { + const chat = createMockChat({ messages: [] }); + render(, { + connections: [nonGenuineConnectionInfo], + }); + + await waitFor(() => { + 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(, { + connections: [genuineConnectionInfo], + }); + + const warningMessage = screen.queryByText( + /MongoDB Assistant will not provide accurate guidance for non-genuine hosts/ + ); + expect(warningMessage).to.not.exist; + }); + + it('does not show warning message when no connections are active', function () { + render(, { + connections: [], + }); + + const warningMessage = screen.queryByText( + /MongoDB Assistant will not provide accurate guidance for non-genuine hosts/ + ); + expect(warningMessage).to.not.exist; + }); + + it('shows warning message when connections are changed to non-genuine', async function () { + const chat = createMockChat({ messages: [] }); + const { connectionsStore } = render(, { + connections: [genuineConnectionInfo], + }); + + expect( + screen.queryByText( + /MongoDB Assistant will not provide accurate guidance for non-genuine hosts/ + ) + ).to.not.exist; + + await connectionsStore.actions.saveAndConnect(nonGenuineConnectionInfo); + + await waitFor(() => { + expect(chat.messages).to.have.length(1); + expect(chat.messages[0].id).to.equal('non-genuine-warning'); + expect( + screen.queryByText( + /MongoDB Assistant will not provide accurate guidance for non-genuine hosts/ + ) + ).to.exist; + }); + }); + + it('warning message is removed when connections are changed to genuine', async function () { + const chat = createMockChat({ messages: [] }); + const { connectionsStore } = render(, { + connections: [genuineConnectionInfo, nonGenuineConnectionInfo], + }); + + expect( + screen.getByText( + /MongoDB Assistant will not provide accurate guidance for non-genuine hosts/ + ) + ).to.exist; + + // Remove the non-genuine connection + connectionsStore.actions.removeConnection(nonGenuineConnectionInfo.id); + + 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' diff --git a/packages/compass-assistant/src/assistant-chat.tsx b/packages/compass-assistant/src/assistant-chat.tsx index ab33c111d21..c7c4f26487b 100644 --- a/packages/compass-assistant/src/assistant-chat.tsx +++ b/packages/compass-assistant/src/assistant-chat.tsx @@ -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'; @@ -20,6 +20,9 @@ import { Link, } from '@mongodb-js/compass-components'; import { useTelemetry } from '@mongodb-js/compass-telemetry/provider'; +import { useConnectionsList } from '@mongodb-js/compass-connections/provider'; +import { getGenuineMongoDB } from 'mongodb-build-info'; +import { NON_GENUINE_WARNING_MESSAGE } from './preset-messages'; const { DisclaimerText } = LgChatChatDisclaimer; const { ChatWindow } = LgChatChatWindow; @@ -130,8 +133,9 @@ export const AssistantChat: React.FunctionComponent = ({ }) => { 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', () => ({ @@ -140,6 +144,31 @@ export const AssistantChat: React.FunctionComponent = ({ }, }); + // Check for non-genuine connections + const hasNonGenuineConnections = + useConnectionsList( + (conn) => + getGenuineMongoDB(conn.info.connectionOptions.connectionString) + .isGenuine === false + ).length > 0; + + useEffect(() => { + const nonGenuineWarningIndex = chat.messages.findIndex( + (message) => message.id === 'non-genuine-warning' + ); + if (hasNonGenuineConnections && nonGenuineWarningIndex === -1) { + setMessages((messages) => { + messages.push(NON_GENUINE_WARNING_MESSAGE); + return messages; + }); + } else if (nonGenuineWarningIndex !== -1 && !hasNonGenuineConnections) { + setMessages((messages) => { + messages.splice(nonGenuineWarningIndex, 1); + return messages; + }); + } + }, [chat, hasNonGenuineConnections, 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 diff --git a/packages/compass-assistant/src/compass-assistant-provider.spec.tsx b/packages/compass-assistant/src/compass-assistant-provider.spec.tsx index 16c9abb9145..caf4f6f648f 100644 --- a/packages/compass-assistant/src/compass-assistant-provider.spec.tsx +++ b/packages/compass-assistant/src/compass-assistant-provider.spec.tsx @@ -25,7 +25,8 @@ import type { AtlasAuthService } from '@mongodb-js/atlas-service/provider'; import type { AtlasService } from '@mongodb-js/atlas-service/provider'; import { CompassAssistantDrawer } from './compass-assistant-drawer'; import { createMockChat } from '../test/utils'; -import { type AtlasAiService } from '@mongodb-js/compass-generative-ai/provider'; +import type { ConnectionInfo } from '@mongodb-js/connection-info'; +import type { AtlasAiService } from '@mongodb-js/compass-generative-ai/provider'; function createMockProvider({ mockAtlasService, @@ -249,13 +250,19 @@ describe('CompassAssistantProvider', function () { }); async function renderOpenAssistantDrawer( - mockChat: Chat, - mockAtlasAiService?: any + { + chat, + atlastAiService, + }: { + chat: Chat; + atlastAiService?: Partial; + }, + { connections }: { connections?: ConnectionInfo[] } = {} ): Promise> { const result = render( , { @@ -265,6 +272,7 @@ describe('CompassAssistantProvider', function () { enableGenAIFeaturesAtlasOrg: true, cloudFeatureRolloutAccess: { GEN_AI_COMPASS: true }, }, + connections, } ); @@ -278,7 +286,7 @@ describe('CompassAssistantProvider', function () { it('displays messages in the chat feed', async function () { const mockChat = createMockChat({ messages: mockMessages }); - await renderOpenAssistantDrawer(mockChat); + await renderOpenAssistantDrawer({ chat: mockChat }); // ensureAiFeatureAccess is async await waitFor(() => { @@ -309,7 +317,7 @@ describe('CompassAssistantProvider', function () { const sendMessageSpy = sinon.spy(mockChat, 'sendMessage'); - await renderOpenAssistantDrawer(mockChat); + await renderOpenAssistantDrawer({ chat: mockChat }); const input = screen.getByPlaceholderText( 'Ask MongoDB Assistant a question' @@ -348,7 +356,7 @@ describe('CompassAssistantProvider', function () { const sendMessageSpy = sinon.spy(mockChat, 'sendMessage'); - await renderOpenAssistantDrawer(mockChat); + await renderOpenAssistantDrawer({ chat: mockChat }); userEvent.type( screen.getByPlaceholderText('Ask MongoDB Assistant a question'), @@ -367,7 +375,7 @@ describe('CompassAssistantProvider', function () { }); it('will not send new messages if the user does not opt in', async function () { - const mockChat = new Chat({ + const chat = new Chat({ messages: [ { id: 'assistant', @@ -385,13 +393,13 @@ describe('CompassAssistantProvider', function () { }, }); - const mockAtlasAiService = { + const atlastAiService = { ensureAiFeatureAccess: sinon.stub().rejects(), }; - const sendMessageSpy = sinon.spy(mockChat, 'sendMessage'); + const sendMessageSpy = sinon.spy(chat, 'sendMessage'); - await renderOpenAssistantDrawer(mockChat, mockAtlasAiService); + await renderOpenAssistantDrawer({ chat, atlastAiService }); userEvent.type( screen.getByPlaceholderText('Ask MongoDB Assistant a question'), @@ -400,7 +408,7 @@ describe('CompassAssistantProvider', function () { userEvent.click(screen.getByLabelText('Send message')); await waitFor(() => { - expect(mockAtlasAiService.ensureAiFeatureAccess.calledOnce).to.be.true; + expect(atlastAiService.ensureAiFeatureAccess.calledOnce).to.be.true; expect(sendMessageSpy.called).to.be.false; }); expect(screen.queryByText('Hello assistant!')).to.not.exist; @@ -410,7 +418,7 @@ describe('CompassAssistantProvider', function () { it('clears the chat when the user clicks and confirms', async function () { const mockChat = createMockChat({ messages: mockMessages }); - await renderOpenAssistantDrawer(mockChat); + await renderOpenAssistantDrawer({ chat: mockChat }); const clearButton = screen.getByTestId('assistant-clear-chat'); userEvent.click(clearButton); @@ -440,7 +448,7 @@ describe('CompassAssistantProvider', function () { it('does not clear the chat when the user clicks the button and cancels', async function () { const mockChat = createMockChat({ messages: mockMessages }); - await renderOpenAssistantDrawer(mockChat); + await renderOpenAssistantDrawer({ chat: mockChat }); const clearButton = screen.getByTestId('assistant-clear-chat'); userEvent.click(clearButton); @@ -466,6 +474,59 @@ describe('CompassAssistantProvider', function () { expect(screen.getByTestId('assistant-message-1')).to.exist; expect(screen.getByTestId('assistant-message-2')).to.exist; }); + + it('should persist permanent warning messages when clearing chat', async function () { + const chat = createMockChat({ messages: [] }); + // Non-genuine host warning message should be permanent + await renderOpenAssistantDrawer( + { chat }, + { + connections: [ + { + id: 'genuine', + connectionOptions: { + connectionString: 'mongodb://localhost:27017', + }, + }, + { + id: 'non-genuine', + connectionOptions: { + connectionString: + 'mongodb://docdb-elastic.amazonaws.com:27017', + }, + }, + ], + } + ); + + expect(chat.messages).to.have.length(1); + expect(chat.messages[0].id).to.equal('non-genuine-warning'); + + expect( + screen.getByText( + /MongoDB Assistant will not provide accurate guidance for non-genuine hosts/ + ) + ).to.exist; + + // Click and confirm the clear chat + const clearButton = screen.getByTestId('assistant-clear-chat'); + userEvent.click(clearButton); + + await waitFor(() => { + expect(screen.getByTestId('assistant-confirm-clear-chat-modal')).to + .exist; + }); + + const modal = screen.getByTestId('assistant-confirm-clear-chat-modal'); + const confirmButton = within(modal).getByText('Clear chat'); + userEvent.click(confirmButton); + + expect( + screen.getByText( + /MongoDB Assistant will not provide accurate guidance for non-genuine hosts/ + ) + ).to.exist; + }); }); }); diff --git a/packages/compass-assistant/src/compass-assistant-provider.tsx b/packages/compass-assistant/src/compass-assistant-provider.tsx index bd9a7058346..c99073534a2 100644 --- a/packages/compass-assistant/src/compass-assistant-provider.tsx +++ b/packages/compass-assistant/src/compass-assistant-provider.tsx @@ -35,6 +35,10 @@ export type AssistantMessage = UIMessage & { metadata?: { /** The text to display instead of the message text. */ displayText?: string; + /** Whether to persist the message after chat clearing. + * Used for warning messages in cases like using non-genuine MongoDB. + */ + isPermanent?: boolean; }; }; @@ -188,7 +192,9 @@ export const AssistantProvider: React.FunctionComponent< buildProactiveInsightsPrompt ), clearChat: () => { - chat.messages = []; + chat.messages = chat.messages.filter( + (message) => message.metadata?.isPermanent + ); }, ensureOptInAndSend: async ( message: SendMessage, diff --git a/packages/compass-assistant/src/preset-messages.ts b/packages/compass-assistant/src/preset-messages.ts new file mode 100644 index 00000000000..06b8bdf0642 --- /dev/null +++ b/packages/compass-assistant/src/preset-messages.ts @@ -0,0 +1,17 @@ +import type { AssistantMessage } from './compass-assistant-provider'; + +export const NON_GENUINE_WARNING_MESSAGE: AssistantMessage = { + id: 'non-genuine-warning', + parts: [ + { + type: 'text', + text: 'The user is connected to a non-genuine MongoDB server. This causes many features to work differently or not work at all, make sure to always warn the user about this.', + }, + ], + metadata: { + displayText: + 'You are connected to **a non-genuine MongoDB server**. MongoDB Assistant will not provide accurate guidance for non-genuine hosts, and we encourage users to use real MongoDB deployments to take full advantage of our developer tools.', + isPermanent: true, + }, + role: 'assistant', +}; From 126d5c6abb8e571bdc4b9b61888b917e132b3268 Mon Sep 17 00:00:00 2001 From: gagik Date: Thu, 4 Sep 2025 13:26:56 +0200 Subject: [PATCH 2/6] chore: only check for active connections, add deps --- package-lock.json | 5 ++ packages/compass-assistant/package.json | 8 ++- .../src/assistant-chat.spec.tsx | 27 ++++++-- .../compass-assistant/src/assistant-chat.tsx | 30 ++++----- .../src/compass-assistant-provider.spec.tsx | 66 +++++++++---------- 5 files changed, 78 insertions(+), 58 deletions(-) diff --git a/package-lock.json b/package-lock.json index cfe9f31f248..7b8a64ef28e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33772,6 +33772,7 @@ "version": "1.7.2", "resolved": "https://registry.npmjs.org/mongodb-build-info/-/mongodb-build-info-1.7.2.tgz", "integrity": "sha512-eoLFZvCIjcwijYJdxvYupj1c+55VAVm0o4gBJjrcDxxmmpm+bC4Ix9ayZbyhQdVXDZAGDi03NA0GghXjBVXnxg==", + "license": "Apache-2.0", "dependencies": { "mongodb-connection-string-url": "^3.0.0" } @@ -47176,12 +47177,14 @@ "@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-connections": "^1.71.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", "ai": "^5.0.26", "compass-preferences-model": "^2.51.0", + "mongodb-build-info": "^1.7.2", "mongodb-connection-string-url": "^3.0.1", "react": "^17.0.2", "throttleit": "^2.1.0", @@ -60584,6 +60587,7 @@ "@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-connections": "^1.71.0", "@mongodb-js/compass-generative-ai": "^0.51.0", "@mongodb-js/compass-logging": "^1.7.12", "@mongodb-js/compass-telemetry": "^1.14.0", @@ -60606,6 +60610,7 @@ "compass-preferences-model": "^2.51.0", "depcheck": "^1.4.1", "mocha": "^10.2.0", + "mongodb-build-info": "^1.7.2", "mongodb-connection-string-url": "^3.0.1", "nyc": "^15.1.0", "openai": "^4.104.0", diff --git a/packages/compass-assistant/package.json b/packages/compass-assistant/package.json index 39b5b420f2d..c22580cda63 100644 --- a/packages/compass-assistant/package.json +++ b/packages/compass-assistant/package.json @@ -53,13 +53,15 @@ "@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-connections": "^1.71.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-build-info": "^1.7.2", + "mongodb-connection-string-url": "^3.0.1", "react": "^17.0.2", "throttleit": "^2.1.0", "use-sync-external-store": "^1.5.0" diff --git a/packages/compass-assistant/src/assistant-chat.spec.tsx b/packages/compass-assistant/src/assistant-chat.spec.tsx index bd0eae1b25a..ed009b36b81 100644 --- a/packages/compass-assistant/src/assistant-chat.spec.tsx +++ b/packages/compass-assistant/src/assistant-chat.spec.tsx @@ -205,10 +205,21 @@ describe('AssistantChat', function () { it('shows warning message in chat when connected to non-genuine MongoDB', async function () { const chat = createMockChat({ messages: [] }); - render(, { + const { connectionsStore } = render(, { connections: [nonGenuineConnectionInfo], }); + // Not connected yet, so no warning message + expect(chat.messages).to.have.length(0); + expect( + screen.queryByText( + /MongoDB Assistant will not provide accurate guidance for non-genuine hosts/ + ) + ).to.not.exist; + + // Connect to the non-genuine connection + await connectionsStore.actions.connect(nonGenuineConnectionInfo); + await waitFor(() => { expect(chat.messages).to.have.length(1); expect(chat.messages[0].id).to.equal('non-genuine-warning'); @@ -220,12 +231,14 @@ describe('AssistantChat', function () { expect(warningMessage).to.exist; }); - it('does not show warning message when all connections are genuine', function () { + it('does not show warning message when all connections are genuine', async function () { const chat = createMockChat({ messages: [] }); - render(, { + const { connectionsStore } = render(, { connections: [genuineConnectionInfo], }); + await connectionsStore.actions.connect(genuineConnectionInfo); + const warningMessage = screen.queryByText( /MongoDB Assistant will not provide accurate guidance for non-genuine hosts/ ); @@ -268,12 +281,16 @@ describe('AssistantChat', function () { }); }); - it('warning message is removed when connections are changed to genuine', async function () { + it('warning message is removed when all active connections are changed to genuine', async function () { const chat = createMockChat({ messages: [] }); const { connectionsStore } = render(, { connections: [genuineConnectionInfo, nonGenuineConnectionInfo], }); + // Connect to the genuine and non-genuine connections + await connectionsStore.actions.connect(genuineConnectionInfo); + await connectionsStore.actions.connect(nonGenuineConnectionInfo); + expect( screen.getByText( /MongoDB Assistant will not provide accurate guidance for non-genuine hosts/ @@ -281,7 +298,7 @@ describe('AssistantChat', function () { ).to.exist; // Remove the non-genuine connection - connectionsStore.actions.removeConnection(nonGenuineConnectionInfo.id); + connectionsStore.actions.disconnect(nonGenuineConnectionInfo.id); await waitFor(() => { const warningMessage = screen.queryByText( diff --git a/packages/compass-assistant/src/assistant-chat.tsx b/packages/compass-assistant/src/assistant-chat.tsx index c7c4f26487b..0d367114e97 100644 --- a/packages/compass-assistant/src/assistant-chat.tsx +++ b/packages/compass-assistant/src/assistant-chat.tsx @@ -20,7 +20,7 @@ import { Link, } from '@mongodb-js/compass-components'; import { useTelemetry } from '@mongodb-js/compass-telemetry/provider'; -import { useConnectionsList } from '@mongodb-js/compass-connections/provider'; +import { useConnectionIds } from '@mongodb-js/compass-connections/provider'; import { getGenuineMongoDB } from 'mongodb-build-info'; import { NON_GENUINE_WARNING_MESSAGE } from './preset-messages'; @@ -145,29 +145,29 @@ export const AssistantChat: React.FunctionComponent = ({ }); // Check for non-genuine connections - const hasNonGenuineConnections = - useConnectionsList( - (conn) => - getGenuineMongoDB(conn.info.connectionOptions.connectionString) - .isGenuine === false - ).length > 0; + const activeConnectionIds = useConnectionIds( + (conn) => + getGenuineMongoDB(conn.info.connectionOptions.connectionString) + .isGenuine === false && conn.status === 'connected' + ); useEffect(() => { - const nonGenuineWarningIndex = chat.messages.findIndex( + const hasNonGenuineConnections = activeConnectionIds.length > 0; + const hasExistingNonGenuineWarning = chat.messages.some( (message) => message.id === 'non-genuine-warning' ); - if (hasNonGenuineConnections && nonGenuineWarningIndex === -1) { + if (hasNonGenuineConnections && !hasExistingNonGenuineWarning) { setMessages((messages) => { - messages.push(NON_GENUINE_WARNING_MESSAGE); - return messages; + return [NON_GENUINE_WARNING_MESSAGE, ...messages]; }); - } else if (nonGenuineWarningIndex !== -1 && !hasNonGenuineConnections) { + } else if (hasExistingNonGenuineWarning && !hasNonGenuineConnections) { setMessages((messages) => { - messages.splice(nonGenuineWarningIndex, 1); - return messages; + return messages.filter( + (message) => message.id !== 'non-genuine-warning' + ); }); } - }, [chat, hasNonGenuineConnections, setMessages]); + }, [activeConnectionIds, 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. diff --git a/packages/compass-assistant/src/compass-assistant-provider.spec.tsx b/packages/compass-assistant/src/compass-assistant-provider.spec.tsx index caf4f6f648f..d2b98d9c49b 100644 --- a/packages/compass-assistant/src/compass-assistant-provider.spec.tsx +++ b/packages/compass-assistant/src/compass-assistant-provider.spec.tsx @@ -476,39 +476,24 @@ describe('CompassAssistantProvider', function () { }); it('should persist permanent warning messages when clearing chat', async function () { - const chat = createMockChat({ messages: [] }); - // Non-genuine host warning message should be permanent - await renderOpenAssistantDrawer( - { chat }, - { - connections: [ - { - id: 'genuine', - connectionOptions: { - connectionString: 'mongodb://localhost:27017', - }, - }, - { - id: 'non-genuine', - connectionOptions: { - connectionString: - 'mongodb://docdb-elastic.amazonaws.com:27017', - }, - }, - ], - } + const mockChat = createMockChat({ messages: mockMessages }); + const nonGenuineConnectionInfo = { + id: 'non-genuine', + connectionOptions: { + connectionString: 'mongodb://docdb-elastic.amazonaws.com:27017', + }, + }; + const { connectionsStore } = await renderOpenAssistantDrawer( + { chat: mockChat }, + { connections: [nonGenuineConnectionInfo] } ); + await connectionsStore.actions.connect(nonGenuineConnectionInfo); - expect(chat.messages).to.have.length(1); - expect(chat.messages[0].id).to.equal('non-genuine-warning'); - - expect( - screen.getByText( - /MongoDB Assistant will not provide accurate guidance for non-genuine hosts/ - ) - ).to.exist; + // Click on the confirm button to close the non-genuine warning modal + userEvent.click( + screen.getByTestId('lg-confirmation_modal-footer-confirm_button') + ); - // Click and confirm the clear chat const clearButton = screen.getByTestId('assistant-clear-chat'); userEvent.click(clearButton); @@ -517,15 +502,26 @@ describe('CompassAssistantProvider', function () { .exist; }); + // There should be messages in the chat + expect(screen.getByTestId('assistant-message-1')).to.exist; + expect(screen.getByTestId('assistant-message-2')).to.exist; + expect(screen.getByTestId('assistant-message-non-genuine-warning')).to + .exist; + const modal = screen.getByTestId('assistant-confirm-clear-chat-modal'); const confirmButton = within(modal).getByText('Clear chat'); userEvent.click(confirmButton); - expect( - screen.getByText( - /MongoDB Assistant will not provide accurate guidance for non-genuine hosts/ - ) - ).to.exist; + await waitForElementToBeRemoved(() => + screen.getByTestId('assistant-confirm-clear-chat-modal') + ); + + // The non-genuine warning message should still be in the chat + expect(screen.getByTestId('assistant-message-non-genuine-warning')).to + .exist; + // The user messages should be gone + expect(screen.queryByTestId('assistant-message-1')).to.not.exist; + expect(screen.queryByTestId('assistant-message-2')).to.not.exist; }); }); }); From 5f234f1b340ccaf7795d76f8ccdae3924618c8ee Mon Sep 17 00:00:00 2001 From: gagik Date: Thu, 4 Sep 2025 13:58:59 +0200 Subject: [PATCH 3/6] chore: add cleanup step --- packages/compass-assistant/package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/compass-assistant/package.json b/packages/compass-assistant/package.json index c22580cda63..527c43e686a 100644 --- a/packages/compass-assistant/package.json +++ b/packages/compass-assistant/package.json @@ -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", From 05934864e910d6638e4f8880d147543ba8c67a0c Mon Sep 17 00:00:00 2001 From: gagik Date: Thu, 4 Sep 2025 15:57:03 +0200 Subject: [PATCH 4/6] chore: wrap outside the assistant component --- package-lock.json | 2 - packages/compass-assistant/package.json | 1 - .../src/assistant-chat.spec.tsx | 98 +++---------------- .../compass-assistant/src/assistant-chat.tsx | 14 +-- .../src/compass-assistant-drawer.tsx | 8 +- .../src/compass-assistant-provider.spec.tsx | 49 ++++------ .../src/compass-assistant-drawer.tsx | 21 ++++ packages/compass-web/src/entrypoint.tsx | 8 +- .../components/compass-assistant-drawer.tsx | 21 ++++ .../compass/src/app/components/workspace.tsx | 4 +- 10 files changed, 88 insertions(+), 138 deletions(-) create mode 100644 packages/compass-web/src/compass-assistant-drawer.tsx create mode 100644 packages/compass/src/app/components/compass-assistant-drawer.tsx diff --git a/package-lock.json b/package-lock.json index 7b8a64ef28e..3586133b1c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -47177,7 +47177,6 @@ "@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-connections": "^1.71.0", "@mongodb-js/compass-generative-ai": "^0.51.0", "@mongodb-js/compass-logging": "^1.7.12", "@mongodb-js/compass-telemetry": "^1.14.0", @@ -60587,7 +60586,6 @@ "@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-connections": "^1.71.0", "@mongodb-js/compass-generative-ai": "^0.51.0", "@mongodb-js/compass-logging": "^1.7.12", "@mongodb-js/compass-telemetry": "^1.14.0", diff --git a/packages/compass-assistant/package.json b/packages/compass-assistant/package.json index 527c43e686a..f4244de6d79 100644 --- a/packages/compass-assistant/package.json +++ b/packages/compass-assistant/package.json @@ -55,7 +55,6 @@ "@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-connections": "^1.71.0", "@mongodb-js/compass-generative-ai": "^0.51.0", "@mongodb-js/compass-logging": "^1.7.12", "@mongodb-js/compass-telemetry": "^1.14.0", diff --git a/packages/compass-assistant/src/assistant-chat.spec.tsx b/packages/compass-assistant/src/assistant-chat.spec.tsx index ed009b36b81..c4111c8882a 100644 --- a/packages/compass-assistant/src/assistant-chat.spec.tsx +++ b/packages/compass-assistant/src/assistant-chat.spec.tsx @@ -61,7 +61,7 @@ describe('AssistantChat', function () { }; const result = render( - + , { connections, @@ -186,44 +186,12 @@ describe('AssistantChat', function () { }); describe('non-genuine MongoDB host handling', function () { - const nonGenuineConnectionInfo: ConnectionInfo = { - id: 'test-connection-non-genuine', - connectionOptions: { - connectionString: 'mongodb://docdb-elastic.amazonaws.com:27017', - }, - favorite: { name: 'Test Connection Non-Genuine' }, - savedConnectionType: 'recent', - }; - const genuineConnectionInfo: ConnectionInfo = { - id: 'test-connection-genuine', - connectionOptions: { - connectionString: 'mongodb://localhost:27017', // localhost is detected as genuine - }, - favorite: { name: 'Test Connection Genuine' }, - savedConnectionType: 'recent', - }; - - it('shows warning message in chat when connected to non-genuine MongoDB', async function () { + it('shows warning message in chat when connected to non-genuine MongoDB', function () { const chat = createMockChat({ messages: [] }); - const { connectionsStore } = render(, { - connections: [nonGenuineConnectionInfo], - }); - - // Not connected yet, so no warning message - expect(chat.messages).to.have.length(0); - expect( - screen.queryByText( - /MongoDB Assistant will not provide accurate guidance for non-genuine hosts/ - ) - ).to.not.exist; + render(); - // Connect to the non-genuine connection - await connectionsStore.actions.connect(nonGenuineConnectionInfo); - - await waitFor(() => { - expect(chat.messages).to.have.length(1); - expect(chat.messages[0].id).to.equal('non-genuine-warning'); - }); + 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/ @@ -231,22 +199,9 @@ describe('AssistantChat', function () { expect(warningMessage).to.exist; }); - it('does not show warning message when all connections are genuine', async function () { + it('does not show warning message when all connections are genuine', function () { const chat = createMockChat({ messages: [] }); - const { connectionsStore } = render(, { - connections: [genuineConnectionInfo], - }); - - await connectionsStore.actions.connect(genuineConnectionInfo); - - const warningMessage = screen.queryByText( - /MongoDB Assistant will not provide accurate guidance for non-genuine hosts/ - ); - expect(warningMessage).to.not.exist; - }); - - it('does not show warning message when no connections are active', function () { - render(, { + render(, { connections: [], }); @@ -256,40 +211,12 @@ describe('AssistantChat', function () { expect(warningMessage).to.not.exist; }); - it('shows warning message when connections are changed to non-genuine', async function () { - const chat = createMockChat({ messages: [] }); - const { connectionsStore } = render(, { - connections: [genuineConnectionInfo], - }); - - expect( - screen.queryByText( - /MongoDB Assistant will not provide accurate guidance for non-genuine hosts/ - ) - ).to.not.exist; - - await connectionsStore.actions.saveAndConnect(nonGenuineConnectionInfo); - - await waitFor(() => { - expect(chat.messages).to.have.length(1); - expect(chat.messages[0].id).to.equal('non-genuine-warning'); - expect( - screen.queryByText( - /MongoDB Assistant will not provide accurate guidance for non-genuine hosts/ - ) - ).to.exist; - }); - }); - it('warning message is removed when all active connections are changed to genuine', async function () { const chat = createMockChat({ messages: [] }); - const { connectionsStore } = render(, { - connections: [genuineConnectionInfo, nonGenuineConnectionInfo], - }); - - // Connect to the genuine and non-genuine connections - await connectionsStore.actions.connect(genuineConnectionInfo); - await connectionsStore.actions.connect(nonGenuineConnectionInfo); + const { rerender } = render( + , + {} + ); expect( screen.getByText( @@ -297,8 +224,7 @@ describe('AssistantChat', function () { ) ).to.exist; - // Remove the non-genuine connection - connectionsStore.actions.disconnect(nonGenuineConnectionInfo.id); + rerender(); await waitFor(() => { const warningMessage = screen.queryByText( diff --git a/packages/compass-assistant/src/assistant-chat.tsx b/packages/compass-assistant/src/assistant-chat.tsx index 0d367114e97..3f41eb287b0 100644 --- a/packages/compass-assistant/src/assistant-chat.tsx +++ b/packages/compass-assistant/src/assistant-chat.tsx @@ -20,8 +20,6 @@ import { Link, } from '@mongodb-js/compass-components'; import { useTelemetry } from '@mongodb-js/compass-telemetry/provider'; -import { useConnectionIds } from '@mongodb-js/compass-connections/provider'; -import { getGenuineMongoDB } from 'mongodb-build-info'; import { NON_GENUINE_WARNING_MESSAGE } from './preset-messages'; const { DisclaimerText } = LgChatChatDisclaimer; @@ -35,6 +33,7 @@ const GEN_AI_FAQ_LINK = 'https://www.mongodb.com/docs/generative-ai-faq/'; interface AssistantChatProps { chat: Chat; + hasNonGenuineConnections: boolean; } const assistantChatStyles = css({ @@ -130,6 +129,7 @@ const errorBannerWrapperStyles = css({ export const AssistantChat: React.FunctionComponent = ({ chat, + hasNonGenuineConnections, }) => { const track = useTelemetry(); const darkMode = useDarkMode(); @@ -144,15 +144,7 @@ export const AssistantChat: React.FunctionComponent = ({ }, }); - // Check for non-genuine connections - const activeConnectionIds = useConnectionIds( - (conn) => - getGenuineMongoDB(conn.info.connectionOptions.connectionString) - .isGenuine === false && conn.status === 'connected' - ); - useEffect(() => { - const hasNonGenuineConnections = activeConnectionIds.length > 0; const hasExistingNonGenuineWarning = chat.messages.some( (message) => message.id === 'non-genuine-warning' ); @@ -167,7 +159,7 @@ export const AssistantChat: React.FunctionComponent = ({ ); }); } - }, [activeConnectionIds, chat, setMessages]); + }, [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. diff --git a/packages/compass-assistant/src/compass-assistant-drawer.tsx b/packages/compass-assistant/src/compass-assistant-drawer.tsx index 5201f1ba5d3..618de0d6569 100644 --- a/packages/compass-assistant/src/compass-assistant-drawer.tsx +++ b/packages/compass-assistant/src/compass-assistant-drawer.tsx @@ -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); @@ -88,7 +89,10 @@ export const CompassAssistantDrawer: React.FunctionComponent<{ glyph="Sparkle" autoOpen={autoOpen} > - + ); }; diff --git a/packages/compass-assistant/src/compass-assistant-provider.spec.tsx b/packages/compass-assistant/src/compass-assistant-provider.spec.tsx index d2b98d9c49b..9514e191998 100644 --- a/packages/compass-assistant/src/compass-assistant-provider.spec.tsx +++ b/packages/compass-assistant/src/compass-assistant-provider.spec.tsx @@ -25,7 +25,6 @@ import type { AtlasAuthService } from '@mongodb-js/atlas-service/provider'; import type { AtlasService } from '@mongodb-js/atlas-service/provider'; import { CompassAssistantDrawer } from './compass-assistant-drawer'; import { createMockChat } from '../test/utils'; -import type { ConnectionInfo } from '@mongodb-js/connection-info'; import type { AtlasAiService } from '@mongodb-js/compass-generative-ai/provider'; function createMockProvider({ @@ -69,12 +68,14 @@ const TestComponent: React.FunctionComponent<{ mockAtlasService?: any; mockAtlasAiService?: any; mockAtlasAuthService?: any; + hasNonGenuineConnections?: boolean; }> = ({ chat, autoOpen, mockAtlasService, mockAtlasAiService, mockAtlasAuthService, + hasNonGenuineConnections, }) => { const MockedProvider = createMockProvider({ mockAtlasService: mockAtlasService as unknown as AtlasService, @@ -87,7 +88,10 @@ const TestComponent: React.FunctionComponent<{
Provider children
- +
@@ -249,21 +253,21 @@ describe('CompassAssistantProvider', function () { } }); - async function renderOpenAssistantDrawer( - { - chat, - atlastAiService, - }: { - chat: Chat; - atlastAiService?: Partial; - }, - { connections }: { connections?: ConnectionInfo[] } = {} - ): Promise> { + async function renderOpenAssistantDrawer({ + chat, + atlastAiService, + hasNonGenuineConnections, + }: { + chat: Chat; + atlastAiService?: Partial; + hasNonGenuineConnections?: boolean; + }): Promise> { const result = render( , { preferences: { @@ -272,7 +276,6 @@ describe('CompassAssistantProvider', function () { enableGenAIFeaturesAtlasOrg: true, cloudFeatureRolloutAccess: { GEN_AI_COMPASS: true }, }, - connections, } ); @@ -477,22 +480,10 @@ describe('CompassAssistantProvider', function () { it('should persist permanent warning messages when clearing chat', async function () { const mockChat = createMockChat({ messages: mockMessages }); - const nonGenuineConnectionInfo = { - id: 'non-genuine', - connectionOptions: { - connectionString: 'mongodb://docdb-elastic.amazonaws.com:27017', - }, - }; - const { connectionsStore } = await renderOpenAssistantDrawer( - { chat: mockChat }, - { connections: [nonGenuineConnectionInfo] } - ); - await connectionsStore.actions.connect(nonGenuineConnectionInfo); - - // Click on the confirm button to close the non-genuine warning modal - userEvent.click( - screen.getByTestId('lg-confirmation_modal-footer-confirm_button') - ); + await renderOpenAssistantDrawer({ + chat: mockChat, + hasNonGenuineConnections: true, + }); const clearButton = screen.getByTestId('assistant-clear-chat'); userEvent.click(clearButton); diff --git a/packages/compass-web/src/compass-assistant-drawer.tsx b/packages/compass-web/src/compass-assistant-drawer.tsx new file mode 100644 index 00000000000..b09ac7683c0 --- /dev/null +++ b/packages/compass-web/src/compass-assistant-drawer.tsx @@ -0,0 +1,21 @@ +import { useConnectionIds } from '@mongodb-js/compass-connections/provider'; +import { getGenuineMongoDB } from 'mongodb-build-info'; +import React from 'react'; +import { CompassAssistantDrawer } from '@mongodb-js/compass-assistant'; + +// TODO(COMPASS-7830): This is a temporary solution to pass the +// hasNonGenuineConnections prop to the CompassAssistantDrawer as otherwise +// we end up with a circular dependency. +export function CompassAssistantDrawerWithConnections() { + // Check for non-genuine connections + const activeConnectionIds = useConnectionIds( + (conn) => + getGenuineMongoDB(conn.info.connectionOptions.connectionString) + .isGenuine === false && conn.status === 'connected' + ); + return ( + 0} + /> + ); +} diff --git a/packages/compass-web/src/entrypoint.tsx b/packages/compass-web/src/entrypoint.tsx index 8198dd81337..4845a208fb3 100644 --- a/packages/compass-web/src/entrypoint.tsx +++ b/packages/compass-web/src/entrypoint.tsx @@ -62,10 +62,8 @@ import { WebWorkspaceTab as WelcomeWorkspaceTab } from '@mongodb-js/compass-welc import { useCompassWebPreferences } from './preferences'; import { DataModelingWorkspaceTab as DataModelingWorkspace } from '@mongodb-js/compass-data-modeling'; import { DataModelStorageServiceProviderInMemory } from '@mongodb-js/compass-data-modeling/web'; -import { - CompassAssistantDrawer, - CompassAssistantProvider, -} from '@mongodb-js/compass-assistant'; +import { CompassAssistantProvider } from '@mongodb-js/compass-assistant'; +import { CompassAssistantDrawerWithConnections } from './compass-assistant-drawer'; /** @public */ export type TrackFunction = ( @@ -229,7 +227,7 @@ function CompassWorkspace({ - + ); }} diff --git a/packages/compass/src/app/components/compass-assistant-drawer.tsx b/packages/compass/src/app/components/compass-assistant-drawer.tsx new file mode 100644 index 00000000000..b09ac7683c0 --- /dev/null +++ b/packages/compass/src/app/components/compass-assistant-drawer.tsx @@ -0,0 +1,21 @@ +import { useConnectionIds } from '@mongodb-js/compass-connections/provider'; +import { getGenuineMongoDB } from 'mongodb-build-info'; +import React from 'react'; +import { CompassAssistantDrawer } from '@mongodb-js/compass-assistant'; + +// TODO(COMPASS-7830): This is a temporary solution to pass the +// hasNonGenuineConnections prop to the CompassAssistantDrawer as otherwise +// we end up with a circular dependency. +export function CompassAssistantDrawerWithConnections() { + // Check for non-genuine connections + const activeConnectionIds = useConnectionIds( + (conn) => + getGenuineMongoDB(conn.info.connectionOptions.connectionString) + .isGenuine === false && conn.status === 'connected' + ); + return ( + 0} + /> + ); +} diff --git a/packages/compass/src/app/components/workspace.tsx b/packages/compass/src/app/components/workspace.tsx index fc152693c52..e53a87fe1ae 100644 --- a/packages/compass/src/app/components/workspace.tsx +++ b/packages/compass/src/app/components/workspace.tsx @@ -40,7 +40,7 @@ import updateTitle from '../utils/update-title'; import { getConnectionTitle } from '@mongodb-js/connection-info'; import { useConnectionsListRef } from '@mongodb-js/compass-connections/provider'; import { DataModelingWorkspaceTab } from '@mongodb-js/compass-data-modeling'; -import { CompassAssistantDrawer } from '@mongodb-js/compass-assistant'; +import { CompassAssistantDrawerWithConnections } from './compass-assistant-drawer'; export default function Workspace({ appName, @@ -112,7 +112,7 @@ export default function Workspace({ - + )} > From b5d7b0d41ed4962aa7a9bf5a0917ea98024ce3f6 Mon Sep 17 00:00:00 2001 From: gagik Date: Thu, 4 Sep 2025 15:58:45 +0200 Subject: [PATCH 5/6] chore: remove build info --- package-lock.json | 2 -- packages/compass-assistant/package.json | 1 - 2 files changed, 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3586133b1c7..b6aed81ecfe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -47183,7 +47183,6 @@ "@mongodb-js/connection-info": "^0.17.1", "ai": "^5.0.26", "compass-preferences-model": "^2.51.0", - "mongodb-build-info": "^1.7.2", "mongodb-connection-string-url": "^3.0.1", "react": "^17.0.2", "throttleit": "^2.1.0", @@ -60608,7 +60607,6 @@ "compass-preferences-model": "^2.51.0", "depcheck": "^1.4.1", "mocha": "^10.2.0", - "mongodb-build-info": "^1.7.2", "mongodb-connection-string-url": "^3.0.1", "nyc": "^15.1.0", "openai": "^4.104.0", diff --git a/packages/compass-assistant/package.json b/packages/compass-assistant/package.json index f4244de6d79..8cb59c19a67 100644 --- a/packages/compass-assistant/package.json +++ b/packages/compass-assistant/package.json @@ -61,7 +61,6 @@ "@mongodb-js/connection-info": "^0.17.1", "ai": "^5.0.26", "compass-preferences-model": "^2.51.0", - "mongodb-build-info": "^1.7.2", "mongodb-connection-string-url": "^3.0.1", "react": "^17.0.2", "throttleit": "^2.1.0", From 4f6268d165d32f58c11c968a5b47bfaee6e1d19d Mon Sep 17 00:00:00 2001 From: gagik Date: Thu, 4 Sep 2025 16:04:27 +0200 Subject: [PATCH 6/6] chore: fix compass-web deps --- package-lock.json | 2 ++ packages/compass-web/package.json | 1 + 2 files changed, 3 insertions(+) diff --git a/package-lock.json b/package-lock.json index b6aed81ecfe..bbcde5668d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -51319,6 +51319,7 @@ "lodash": "^4.17.21", "mocha": "^10.2.0", "mongodb": "^6.19.0", + "mongodb-build-info": "^1.7.2", "mongodb-data-service": "^22.30.2", "mongodb-log-writer": "^2.3.4", "mongodb-ns": "^2.4.2", @@ -63804,6 +63805,7 @@ "lodash": "^4.17.21", "mocha": "^10.2.0", "mongodb": "^6.19.0", + "mongodb-build-info": "^1.7.2", "mongodb-data-service": "^22.30.2", "mongodb-log-writer": "^2.3.4", "mongodb-ns": "^2.4.2", diff --git a/packages/compass-web/package.json b/packages/compass-web/package.json index dc4f6211d2c..2aab43139fc 100644 --- a/packages/compass-web/package.json +++ b/packages/compass-web/package.json @@ -128,6 +128,7 @@ "lodash": "^4.17.21", "mocha": "^10.2.0", "mongodb": "^6.19.0", + "mongodb-build-info": "^1.7.2", "mongodb-data-service": "^22.30.2", "mongodb-log-writer": "^2.3.4", "mongodb-ns": "^2.4.2",