From 5a9083a39be2dafb7a4d787abd99b9efe7b745e4 Mon Sep 17 00:00:00 2001 From: Le Roux Bodenstein Date: Fri, 22 Aug 2025 16:20:48 +0100 Subject: [PATCH 01/10] connection error entrypoint --- .../src/compass-assistant-provider.tsx | 57 ++++++++++++++- packages/compass-assistant/src/index.tsx | 6 +- packages/compass-assistant/src/prompts.ts | 19 +++++ .../connection-status-notifications.tsx | 54 +++++++++++++++ packages/compass-connections/src/index.tsx | 12 +++- .../src/stores/connections-store-redux.ts | 23 ++++++- packages/compass/src/app/components/home.tsx | 69 +++++++++---------- 7 files changed, 197 insertions(+), 43 deletions(-) diff --git a/packages/compass-assistant/src/compass-assistant-provider.tsx b/packages/compass-assistant/src/compass-assistant-provider.tsx index e63aef9072e..1d820b8d4ab 100644 --- a/packages/compass-assistant/src/compass-assistant-provider.tsx +++ b/packages/compass-assistant/src/compass-assistant-provider.tsx @@ -2,12 +2,16 @@ import React, { type PropsWithChildren, useRef } from 'react'; import { type UIMessage } from './@ai-sdk/react/use-chat'; import { Chat } from './@ai-sdk/react/chat-react'; import { createContext, useContext } from 'react'; -import { registerCompassPlugin } from '@mongodb-js/compass-app-registry'; +import { + createServiceLocator, + registerCompassPlugin, +} from '@mongodb-js/compass-app-registry'; import { atlasServiceLocator } from '@mongodb-js/atlas-service/provider'; import { DocsProviderTransport } from './docs-provider-transport'; import { useDrawerActions } from '@mongodb-js/compass-components'; -import { buildExplainPlanPrompt } from './prompts'; +import { buildConnectionErrorPrompt, buildExplainPlanPrompt } from './prompts'; import { usePreference } from 'compass-preferences-model/provider'; +import type { ConnectionInfo } from '@mongodb-js/connection-info'; export const ASSISTANT_DRAWER_ID = 'compass-assistant-drawer'; @@ -32,10 +36,18 @@ type AssistantActionsContextType = { namespace: string; explainPlan: string; }) => void; + interpretConnectionError: ({ + connectionInfo, + error, + }: { + connectionInfo: ConnectionInfo; + error: Error; + }) => void; }; export const AssistantActionsContext = createContext({ interpretExplainPlan: () => {}, + interpretConnectionError: () => {}, }); export function useAssistantActions(): AssistantActionsContextType & { @@ -49,6 +61,24 @@ export function useAssistantActions(): AssistantActionsContextType & { }; } +export const compassAssistantServiceLocator = createServiceLocator(function () { + const { isAssistantEnabled, ...actions } = useAssistantActions(); + + const assistantEnabledRef = useRef(isAssistantEnabled); + assistantEnabledRef.current = isAssistantEnabled; + + return { + ...actions, + getIsAssistantEnabled() { + return assistantEnabledRef.current; + }, + }; +}, 'compassAssistantLocator'); + +export type CompassAssistantService = ReturnType< + typeof compassAssistantServiceLocator +>; + export const AssistantProvider: React.FunctionComponent< PropsWithChildren<{ chat: Chat; @@ -70,6 +100,29 @@ export const AssistantProvider: React.FunctionComponent< {} ); }, + interpretConnectionError: ({ connectionInfo, error }) => { + openDrawer(ASSISTANT_DRAWER_ID); + + // TODO: redact the connection string + const connectionString = + connectionInfo.connectionOptions.connectionString; + const connectionError = error.toString(); // TODO + console.log({ connectionString, connectionError }); + + const { prompt, displayText } = buildConnectionErrorPrompt({ + connectionString, + connectionError, + }); + void chat.sendMessage( + { + text: prompt, + metadata: { + displayText, + }, + }, + {} + ); + }, }); const { openDrawer } = useDrawerActions(); diff --git a/packages/compass-assistant/src/index.tsx b/packages/compass-assistant/src/index.tsx index d3fd2d72b12..2a7bcb6e5e5 100644 --- a/packages/compass-assistant/src/index.tsx +++ b/packages/compass-assistant/src/index.tsx @@ -1,3 +1,7 @@ export { CompassAssistantProvider } from './compass-assistant-provider'; export { CompassAssistantDrawer } from './compass-assistant-drawer'; -export { useAssistantActions } from './compass-assistant-provider'; +export { + useAssistantActions, + compassAssistantServiceLocator, +} from './compass-assistant-provider'; +export type { CompassAssistantService } from './compass-assistant-provider'; diff --git a/packages/compass-assistant/src/prompts.ts b/packages/compass-assistant/src/prompts.ts index b0981f24c0a..c09516390d9 100644 --- a/packages/compass-assistant/src/prompts.ts +++ b/packages/compass-assistant/src/prompts.ts @@ -11,3 +11,22 @@ ${explainPlan}`, displayText: 'Provide an explanation of this explain plan.', }; }; + +export const buildConnectionErrorPrompt = ({ + connectionString, + connectionError, +}: { + connectionString: string; + connectionError: string; +}) => { + return { + prompt: `Given the error message below, please provide clear instructions to guide the user to debug their connection attempt from MongoDB Compass. If no auth mechanism is specified in the connection string, the default (username/password) is being used: + +Connection string (password redacted): +${connectionString} + +Error message: +${connectionError}`, + displayText: 'Provide an explanation of this connection error.', + }; +}; diff --git a/packages/compass-connections/src/components/connection-status-notifications.tsx b/packages/compass-connections/src/components/connection-status-notifications.tsx index ddb838e88d6..110c2719f65 100644 --- a/packages/compass-connections/src/components/connection-status-notifications.tsx +++ b/packages/compass-connections/src/components/connection-status-notifications.tsx @@ -83,6 +83,37 @@ function ConnectionErrorToastBody({ ); } +type ConnectionDebugToastBodyProps = { + info?: ConnectionInfo | null; + onDebug: () => void; +}; + +function ConnectionDebugToastBody({ + info, + onDebug, +}: ConnectionDebugToastBodyProps): React.ReactElement { + return ( + + + Diagnose the issue and explore solutions with the assistant + + {info && ( + + DEBUG FOR ME + + )} + + ); +} + const deviceAuthModalContentStyles = css({ textAlign: 'center', '& > *:not(:last-child)': { @@ -134,6 +165,8 @@ const openConnectionFailedToast = ( ) => { const failedToastId = connectionInfo?.id ?? 'failed'; + // TODO: close the existing connection toast and make a new one for the + // failure so that the debug toast will appear below the failure one openToast(`connection-status--${failedToastId}`, { title: error.message, description: ( @@ -150,6 +183,26 @@ const openConnectionFailedToast = ( }); }; +const openDebugConnectionErrorToast = ( + connectionInfo: ConnectionInfo, + error: Error, + onDebugClick: () => void +) => { + openToast(`debug-connetion-error--${connectionInfo.id}`, { + title: 'Need help debugging your connection error?', + description: ( + { + closeToast(`debug-connetion-error--${connectionInfo.id}`); + onDebugClick(); + }} + /> + ), + variant: 'note', + }); +}; + const openMaximumConnectionsReachedToast = ( maxConcurrentConnections: number ) => { @@ -214,6 +267,7 @@ export function getNotificationTriggers() { openConnectionStartedToast, openConnectionSucceededToast, openConnectionFailedToast, + openDebugConnectionErrorToast, openMaximumConnectionsReachedToast, closeConnectionStatusToast: (connectionId: string) => { return closeToast(`connection-status--${connectionId}`); diff --git a/packages/compass-connections/src/index.tsx b/packages/compass-connections/src/index.tsx index 299165f51ee..3e821b9bc8a 100644 --- a/packages/compass-connections/src/index.tsx +++ b/packages/compass-connections/src/index.tsx @@ -24,6 +24,7 @@ import { } from './stores/store-context'; export type { ConnectionFeature } from './utils/connection-supports'; export { connectionSupports, connectable } from './utils/connection-supports'; +import { compassAssistantServiceLocator } from '@mongodb-js/compass-assistant'; const ConnectionsComponent: React.FunctionComponent<{ /** @@ -82,7 +83,14 @@ const CompassConnectionsPlugin = registerCompassPlugin( component: ConnectionsComponent, activate( initialProps, - { logger, preferences, connectionStorage, track, globalAppRegistry }, + { + logger, + preferences, + connectionStorage, + track, + globalAppRegistry, + compassAssistant, + }, { addCleanup, cleanup } ) { const store = configureStore(initialProps.preloadStorageConnectionInfos, { @@ -95,6 +103,7 @@ const CompassConnectionsPlugin = registerCompassPlugin( connectFn: initialProps.connectFn, globalAppRegistry, onFailToLoadConnections: initialProps.onFailToLoadConnections, + compassAssistant, }); setTimeout(() => { @@ -128,6 +137,7 @@ const CompassConnectionsPlugin = registerCompassPlugin( preferences: preferencesLocator, connectionStorage: connectionStorageLocator, track: telemetryLocator, + compassAssistant: compassAssistantServiceLocator, } ); diff --git a/packages/compass-connections/src/stores/connections-store-redux.ts b/packages/compass-connections/src/stores/connections-store-redux.ts index eeb259f906f..7d688b5f32d 100644 --- a/packages/compass-connections/src/stores/connections-store-redux.ts +++ b/packages/compass-connections/src/stores/connections-store-redux.ts @@ -41,6 +41,7 @@ import { } from '../utils/end-of-life-server'; import type { ImportConnectionOptions } from '@mongodb-js/connection-storage/provider'; import { getErrorCodeCauseChain } from '../utils/telemetry'; +import type { CompassAssistantService } from '@mongodb-js/compass-assistant'; export type ConnectionsEventMap = { connected: ( @@ -212,6 +213,7 @@ type ThunkExtraArg = { connectFn?: typeof devtoolsConnect; globalAppRegistry: Pick; onFailToLoadConnections: (error: Error) => void; + compassAssistant: CompassAssistantService; }; export type ConnectionsThunkAction< @@ -1263,11 +1265,26 @@ const connectionAttemptError = ( connectionInfo: ConnectionInfo | null, err: any ): ConnectionsThunkAction => { - return (dispatch, _getState, { track, getExtraConnectionData }) => { - const { openConnectionFailedToast } = getNotificationTriggers(); + return ( + dispatch, + _getState, + { track, getExtraConnectionData, compassAssistant } + ) => { + const { openConnectionFailedToast, openDebugConnectionErrorToast } = + getNotificationTriggers(); + + const isAssistanceEnabled = compassAssistant.getIsAssistantEnabled(); + if (isAssistanceEnabled && connectionInfo) { + openDebugConnectionErrorToast(connectionInfo, err, () => { + console.log('compassAssistant.interpretConnectionError()'); + compassAssistant.interpretConnectionError({ + connectionInfo, + error: err, + }); + }); + } const showReviewButton = !!connectionInfo && !connectionInfo.atlasMetadata; - openConnectionFailedToast(connectionInfo, err, showReviewButton, () => { if (connectionInfo) { dispatch(editConnection(connectionInfo.id)); diff --git a/packages/compass/src/app/components/home.tsx b/packages/compass/src/app/components/home.tsx index 3ca5b5cd396..da6b6562f34 100644 --- a/packages/compass/src/app/components/home.tsx +++ b/packages/compass/src/app/components/home.tsx @@ -108,27 +108,22 @@ function Home({ return ( - - -
- - - -
- - - - - - -
-
+ +
+ + + +
+ + + + + + +
); @@ -152,21 +147,23 @@ function HomeWithConnections({ return ( - { - openToast('failed-to-load-connections', { - title: 'Failed to load connections', - description: error.message, - variant: 'warning', - }); - }} - > - - + + { + openToast('failed-to-load-connections', { + title: 'Failed to load connections', + description: error.message, + variant: 'warning', + }); + }} + > + + + ); From c41f147b9c78cc1c4ba2479f9d9f9cdd8c12da7d Mon Sep 17 00:00:00 2001 From: Le Roux Bodenstein Date: Fri, 22 Aug 2025 16:57:43 +0100 Subject: [PATCH 02/10] console.logs, todos --- package-lock.json | 4 ++++ packages/compass-assistant/package.json | 2 ++ .../src/compass-assistant-provider.tsx | 10 +++++----- .../src/stores/connections-store-redux.ts | 1 - 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index dd28eabe03b..856c77cf326 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44150,8 +44150,10 @@ "@mongodb-js/atlas-service": "^0.55.0", "@mongodb-js/compass-app-registry": "^9.4.19", "@mongodb-js/compass-components": "^1.48.0", + "@mongodb-js/connection-info": "^0.17.1", "ai": "^5.0.5", "compass-preferences-model": "^2.50.0", + "mongodb-connection-string-url": "^3.0.1", "react": "^17.0.2", "throttleit": "^2.1.0", "use-sync-external-store": "^1.5.0" @@ -56979,6 +56981,7 @@ "@mongodb-js/atlas-service": "^0.55.0", "@mongodb-js/compass-app-registry": "^9.4.19", "@mongodb-js/compass-components": "^1.48.0", + "@mongodb-js/connection-info": "^0.17.1", "@mongodb-js/eslint-config-compass": "^1.4.6", "@mongodb-js/mocha-config-compass": "^1.7.0", "@mongodb-js/prettier-config-compass": "^1.2.8", @@ -56995,6 +56998,7 @@ "compass-preferences-model": "^2.50.0", "depcheck": "^1.4.1", "mocha": "^10.2.0", + "mongodb-connection-string-url": "^3.0.1", "nyc": "^15.1.0", "react": "^17.0.2", "sinon": "^17.0.1", diff --git a/packages/compass-assistant/package.json b/packages/compass-assistant/package.json index 7d42ef68346..682097a24c4 100644 --- a/packages/compass-assistant/package.json +++ b/packages/compass-assistant/package.json @@ -53,6 +53,8 @@ "@mongodb-js/atlas-service": "^0.55.0", "@mongodb-js/compass-app-registry": "^9.4.19", "@mongodb-js/compass-components": "^1.48.0", + "@mongodb-js/connection-info": "^0.17.1", + "mongodb-connection-string-url": "^3.0.1", "ai": "^5.0.5", "compass-preferences-model": "^2.50.0", "react": "^17.0.2", diff --git a/packages/compass-assistant/src/compass-assistant-provider.tsx b/packages/compass-assistant/src/compass-assistant-provider.tsx index 1d820b8d4ab..f49520fda77 100644 --- a/packages/compass-assistant/src/compass-assistant-provider.tsx +++ b/packages/compass-assistant/src/compass-assistant-provider.tsx @@ -12,6 +12,7 @@ import { useDrawerActions } from '@mongodb-js/compass-components'; import { buildConnectionErrorPrompt, buildExplainPlanPrompt } from './prompts'; import { usePreference } from 'compass-preferences-model/provider'; import type { ConnectionInfo } from '@mongodb-js/connection-info'; +import { redactConnectionString } from 'mongodb-connection-string-url'; export const ASSISTANT_DRAWER_ID = 'compass-assistant-drawer'; @@ -103,11 +104,10 @@ export const AssistantProvider: React.FunctionComponent< interpretConnectionError: ({ connectionInfo, error }) => { openDrawer(ASSISTANT_DRAWER_ID); - // TODO: redact the connection string - const connectionString = - connectionInfo.connectionOptions.connectionString; - const connectionError = error.toString(); // TODO - console.log({ connectionString, connectionError }); + const connectionString = redactConnectionString( + connectionInfo.connectionOptions.connectionString + ); + const connectionError = error.toString(); const { prompt, displayText } = buildConnectionErrorPrompt({ connectionString, diff --git a/packages/compass-connections/src/stores/connections-store-redux.ts b/packages/compass-connections/src/stores/connections-store-redux.ts index 7d688b5f32d..8e592741365 100644 --- a/packages/compass-connections/src/stores/connections-store-redux.ts +++ b/packages/compass-connections/src/stores/connections-store-redux.ts @@ -1276,7 +1276,6 @@ const connectionAttemptError = ( const isAssistanceEnabled = compassAssistant.getIsAssistantEnabled(); if (isAssistanceEnabled && connectionInfo) { openDebugConnectionErrorToast(connectionInfo, err, () => { - console.log('compassAssistant.interpretConnectionError()'); compassAssistant.interpretConnectionError({ connectionInfo, error: err, From d49a82ae2ba18305bdadc597367b18a500da17dd Mon Sep 17 00:00:00 2001 From: Le Roux Bodenstein Date: Fri, 22 Aug 2025 17:14:06 +0100 Subject: [PATCH 03/10] deps, unused code --- package-lock.json | 6 ++++-- .../connection-status-notifications.tsx | 21 +++++++------------ packages/compass-explain-plan/package.json | 2 +- packages/connection-storage/package.json | 1 + 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index e1474128470..4f84c74504d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -47246,7 +47246,7 @@ "license": "SSPL", "dependencies": { "@mongodb-js/compass-app-registry": "^9.4.19", - "@mongodb-js/compass-assistant": "^1.0.0", + "@mongodb-js/compass-assistant": "^1.1.0", "@mongodb-js/compass-collection": "^4.69.0", "@mongodb-js/compass-components": "^1.48.0", "@mongodb-js/compass-connections": "^1.70.0", @@ -50265,6 +50265,7 @@ "license": "SSPL", "dependencies": { "@mongodb-js/compass-app-registry": "^9.4.19", + "@mongodb-js/compass-assistant": "^1.1.0", "@mongodb-js/compass-logging": "^1.7.11", "@mongodb-js/compass-telemetry": "^1.13.0", "@mongodb-js/compass-user-data": "^0.9.0", @@ -59603,7 +59604,7 @@ "version": "file:packages/compass-explain-plan", "requires": { "@mongodb-js/compass-app-registry": "^9.4.19", - "@mongodb-js/compass-assistant": "^1.0.0", + "@mongodb-js/compass-assistant": "^1.1.0", "@mongodb-js/compass-collection": "^4.69.0", "@mongodb-js/compass-components": "^1.48.0", "@mongodb-js/compass-connections": "^1.70.0", @@ -62104,6 +62105,7 @@ "version": "file:packages/connection-storage", "requires": { "@mongodb-js/compass-app-registry": "^9.4.19", + "@mongodb-js/compass-assistant": "^1.1.0", "@mongodb-js/compass-logging": "^1.7.11", "@mongodb-js/compass-telemetry": "^1.13.0", "@mongodb-js/compass-user-data": "^0.9.0", diff --git a/packages/compass-connections/src/components/connection-status-notifications.tsx b/packages/compass-connections/src/components/connection-status-notifications.tsx index 110c2719f65..500eea5c725 100644 --- a/packages/compass-connections/src/components/connection-status-notifications.tsx +++ b/packages/compass-connections/src/components/connection-status-notifications.tsx @@ -84,12 +84,10 @@ function ConnectionErrorToastBody({ } type ConnectionDebugToastBodyProps = { - info?: ConnectionInfo | null; onDebug: () => void; }; function ConnectionDebugToastBody({ - info, onDebug, }: ConnectionDebugToastBodyProps): React.ReactElement { return ( @@ -100,16 +98,14 @@ function ConnectionDebugToastBody({ > Diagnose the issue and explore solutions with the assistant - {info && ( - - DEBUG FOR ME - - )} + + DEBUG FOR ME + ); } @@ -192,7 +188,6 @@ const openDebugConnectionErrorToast = ( title: 'Need help debugging your connection error?', description: ( { closeToast(`debug-connetion-error--${connectionInfo.id}`); onDebugClick(); diff --git a/packages/compass-explain-plan/package.json b/packages/compass-explain-plan/package.json index 034ec86d572..ed824392d1f 100644 --- a/packages/compass-explain-plan/package.json +++ b/packages/compass-explain-plan/package.json @@ -68,7 +68,7 @@ "xvfb-maybe": "^0.2.1" }, "dependencies": { - "@mongodb-js/compass-assistant": "^1.0.0", + "@mongodb-js/compass-assistant": "^1.1.0", "@mongodb-js/compass-app-registry": "^9.4.19", "@mongodb-js/compass-collection": "^4.69.0", "@mongodb-js/compass-components": "^1.48.0", diff --git a/packages/connection-storage/package.json b/packages/connection-storage/package.json index ae2d67607ca..8376806e112 100644 --- a/packages/connection-storage/package.json +++ b/packages/connection-storage/package.json @@ -57,6 +57,7 @@ }, "dependencies": { "@mongodb-js/compass-app-registry": "^9.4.19", + "@mongodb-js/compass-assistant": "^1.1.0", "@mongodb-js/compass-logging": "^1.7.11", "@mongodb-js/compass-telemetry": "^1.13.0", "@mongodb-js/compass-user-data": "^0.9.0", From 7cb33153eb95b50ae05be9ae99b9c5ec3f44d7b9 Mon Sep 17 00:00:00 2001 From: Le Roux Bodenstein Date: Mon, 25 Aug 2025 13:10:35 +0100 Subject: [PATCH 04/10] add a test --- .../connection-status-notifications.tsx | 4 ++-- .../stores/connections-store-redux.spec.tsx | 24 +++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/packages/compass-connections/src/components/connection-status-notifications.tsx b/packages/compass-connections/src/components/connection-status-notifications.tsx index 500eea5c725..73393ed6590 100644 --- a/packages/compass-connections/src/components/connection-status-notifications.tsx +++ b/packages/compass-connections/src/components/connection-status-notifications.tsx @@ -161,8 +161,8 @@ const openConnectionFailedToast = ( ) => { const failedToastId = connectionInfo?.id ?? 'failed'; - // TODO: close the existing connection toast and make a new one for the - // failure so that the debug toast will appear below the failure one + // TODO(COMPASS-9746): close the existing connection toast and make a new one + // for the failure so that the debug toast will appear below the failure one openToast(`connection-status--${failedToastId}`, { title: error.message, description: ( diff --git a/packages/compass-connections/src/stores/connections-store-redux.spec.tsx b/packages/compass-connections/src/stores/connections-store-redux.spec.tsx index 5d476bf6130..062ff51fb84 100644 --- a/packages/compass-connections/src/stores/connections-store-redux.spec.tsx +++ b/packages/compass-connections/src/stores/connections-store-redux.spec.tsx @@ -150,6 +150,30 @@ describe('CompassConnections store', function () { } }); + it('should show debug toast in addition to the connection error toast if connection fails and the assistant is enabled', async function () { + const { connectionsStore } = renderCompassConnections({ + preferences: { + enableAIAssistant: true, + }, + connectFn: sinon + .stub() + .rejects(new Error('Failed to connect to cluster')), + }); + + const connectionInfo = createDefaultConnectionInfo(); + + void connectionsStore.actions.connect(connectionInfo); + + await waitFor(() => { + expect(screen.getByText('Failed to connect to cluster')).to.exist; + }); + + await waitFor(() => { + expect(screen.getByText('Need help debugging your connection error?')) + .to.exist; + }); + }); + it('should show non-genuine modal at the end of connection if non genuine mongodb detected', async function () { const { connectionsStore } = renderCompassConnections({}); From 527077d5d6bba5a429a3d875fc2043dc86092b2a Mon Sep 17 00:00:00 2001 From: Le Roux Bodenstein Date: Mon, 25 Aug 2025 15:14:51 +0100 Subject: [PATCH 05/10] add missing dep --- package-lock.json | 2 ++ packages/compass-connections/package.json | 1 + 2 files changed, 3 insertions(+) diff --git a/package-lock.json b/package-lock.json index 4f84c74504d..8b8a6ad6f27 100644 --- a/package-lock.json +++ b/package-lock.json @@ -46150,6 +46150,7 @@ "license": "SSPL", "dependencies": { "@mongodb-js/compass-app-registry": "^9.4.19", + "@mongodb-js/compass-assistant": "^1.1.0", "@mongodb-js/compass-components": "^1.48.0", "@mongodb-js/compass-logging": "^1.7.11", "@mongodb-js/compass-telemetry": "^1.13.0", @@ -58976,6 +58977,7 @@ "version": "file:packages/compass-connections", "requires": { "@mongodb-js/compass-app-registry": "^9.4.19", + "@mongodb-js/compass-assistant": "^1.1.0", "@mongodb-js/compass-components": "^1.48.0", "@mongodb-js/compass-logging": "^1.7.11", "@mongodb-js/compass-telemetry": "^1.13.0", diff --git a/packages/compass-connections/package.json b/packages/compass-connections/package.json index 55a0ece6922..268ecd3f210 100644 --- a/packages/compass-connections/package.json +++ b/packages/compass-connections/package.json @@ -52,6 +52,7 @@ }, "dependencies": { "@mongodb-js/compass-app-registry": "^9.4.19", + "@mongodb-js/compass-assistant": "^1.1.0", "@mongodb-js/compass-components": "^1.48.0", "@mongodb-js/compass-logging": "^1.7.11", "@mongodb-js/compass-telemetry": "^1.13.0", From 9c698acff9e0fe0f39cae9ddc45552b2c9a8026c Mon Sep 17 00:00:00 2001 From: Le Roux Bodenstein Date: Mon, 25 Aug 2025 15:15:09 +0100 Subject: [PATCH 06/10] remove display text to match the figma design --- .../compass-assistant/src/compass-assistant-provider.tsx | 5 +---- packages/compass-assistant/src/prompts.ts | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/compass-assistant/src/compass-assistant-provider.tsx b/packages/compass-assistant/src/compass-assistant-provider.tsx index 84e94ff3dd6..c4c3cfd5320 100644 --- a/packages/compass-assistant/src/compass-assistant-provider.tsx +++ b/packages/compass-assistant/src/compass-assistant-provider.tsx @@ -111,16 +111,13 @@ export const AssistantProvider: React.FunctionComponent< ); const connectionError = error.toString(); - const { prompt, displayText } = buildConnectionErrorPrompt({ + const { prompt } = buildConnectionErrorPrompt({ connectionString, connectionError, }); void chat.sendMessage( { text: prompt, - metadata: { - displayText, - }, }, {} ); diff --git a/packages/compass-assistant/src/prompts.ts b/packages/compass-assistant/src/prompts.ts index c09516390d9..a421228796b 100644 --- a/packages/compass-assistant/src/prompts.ts +++ b/packages/compass-assistant/src/prompts.ts @@ -27,6 +27,5 @@ ${connectionString} Error message: ${connectionError}`, - displayText: 'Provide an explanation of this connection error.', }; }; From c5288cf5bbe660962320da485e4dc2195f5c3ea2 Mon Sep 17 00:00:00 2001 From: Le Roux Bodenstein Date: Mon, 25 Aug 2025 16:27:00 +0100 Subject: [PATCH 07/10] commented test for when the toast order is swapped --- .../src/compass-assistant-drawer.tsx | 1 + .../src/compass-assistant-provider.spec.tsx | 12 ++++----- .../compass-e2e-tests/helpers/selectors.ts | 8 ++++++ .../tests/connection.test.ts | 26 +++++++++++++++++++ 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/packages/compass-assistant/src/compass-assistant-drawer.tsx b/packages/compass-assistant/src/compass-assistant-drawer.tsx index 09b3ad98503..6af3aa4c51c 100644 --- a/packages/compass-assistant/src/compass-assistant-drawer.tsx +++ b/packages/compass-assistant/src/compass-assistant-drawer.tsx @@ -33,6 +33,7 @@ export const CompassAssistantDrawer: React.FunctionComponent<{ 'The current chat will be cleared, and chat history will not be retrievable.', buttonText: 'Clear chat', variant: 'danger', + 'data-testid': 'confirm-clear-chat-modal', }); if (confirmed) { clearChat(); diff --git a/packages/compass-assistant/src/compass-assistant-provider.spec.tsx b/packages/compass-assistant/src/compass-assistant-provider.spec.tsx index 412526dd846..910ad01fbf3 100644 --- a/packages/compass-assistant/src/compass-assistant-provider.spec.tsx +++ b/packages/compass-assistant/src/compass-assistant-provider.spec.tsx @@ -200,19 +200,19 @@ describe('AssistantProvider', function () { userEvent.click(clearButton); await waitFor(() => { - expect(screen.getByTestId('confirmation-modal')).to.exist; + expect(screen.getByTestId('confirm-clear-chat-modal')).to.exist; }); // There should be messages in the chat expect(screen.getByTestId('assistant-message-1')).to.exist; expect(screen.getByTestId('assistant-message-2')).to.exist; - const modal = screen.getByTestId('confirmation-modal'); + const modal = screen.getByTestId('confirm-clear-chat-modal'); const confirmButton = within(modal).getByText('Clear chat'); userEvent.click(confirmButton); await waitForElementToBeRemoved(() => - screen.getByTestId('confirmation-modal') + screen.getByTestId('confirm-clear-chat-modal') ); expect(mockChat.messages).to.be.empty; @@ -229,19 +229,19 @@ describe('AssistantProvider', function () { userEvent.click(clearButton); await waitFor(() => { - expect(screen.getByTestId('confirmation-modal')).to.exist; + expect(screen.getByTestId('confirm-clear-chat-modal')).to.exist; }); // There should be messages in the chat expect(screen.getByTestId('assistant-message-1')).to.exist; expect(screen.getByTestId('assistant-message-2')).to.exist; - const modal = screen.getByTestId('confirmation-modal'); + const modal = screen.getByTestId('confirm-clear-chat-modal'); const cancelButton = within(modal).getByText('Cancel'); userEvent.click(cancelButton); await waitForElementToBeRemoved(() => - screen.getByTestId('confirmation-modal') + screen.getByTestId('confirm-clear-chat-modal') ); expect(mockChat.messages).to.deep.equal(mockMessages); diff --git a/packages/compass-e2e-tests/helpers/selectors.ts b/packages/compass-e2e-tests/helpers/selectors.ts index 536565c3f18..57b3a84d440 100644 --- a/packages/compass-e2e-tests/helpers/selectors.ts +++ b/packages/compass-e2e-tests/helpers/selectors.ts @@ -242,6 +242,8 @@ export const ConnectionToastErrorReviewButton = '[data-testid="connection-error-review"]'; export const ConenctionToastCancelConnectionButton = '[data-testid="cancel-connection-button"]'; +export const ConnectionToastErrorDebugButton = + '[data-testid="connection-error-debug"]'; // Connections sidebar export const ConnectionsTitle = '[data-testid="connections-header"]'; @@ -1511,3 +1513,9 @@ export const SideDrawer = `[data-testid="${getDrawerIds().root}"]`; export const SideDrawerCloseButton = `[data-testid="${ getDrawerIds().closeButton }"]`; + +// Assistant +export const AssistantChatMessages = '[data-testid="assistant-chat-messages"]'; +export const AssistantClearChatButton = '[data-testid="assistant-clear-chat"]'; +export const ConfirmClearChatModal = '[data-testid="confirm-clear-chat-modal"]'; +export const ConfirmClearChatModalConfirmButton = `${ConfirmClearChatModal} [data-testid="lg-confirmation_modal-footer-confirm_button"]`; diff --git a/packages/compass-e2e-tests/tests/connection.test.ts b/packages/compass-e2e-tests/tests/connection.test.ts index 542ab573466..97687c3b625 100644 --- a/packages/compass-e2e-tests/tests/connection.test.ts +++ b/packages/compass-e2e-tests/tests/connection.test.ts @@ -273,6 +273,9 @@ describe('Connection string', function () { before(async function () { compass = await init(this.test?.fullTitle()); browser = compass.browser; + // TODO(COMPASS-9746) the debug toast obscures the connection toast which + // breaks the connect custom commands and who knows what else + //await browser.setFeature('enableAIAssistant', true) }); beforeEach(async function () { @@ -326,6 +329,29 @@ describe('Connection string', function () { .$(Selectors.ConnectionFormErrorMessage) .getText(); expect(errorText).to.equal('Authentication failed.'); + + // close the modal + await browser.clickVisible(Selectors.ConnectionModalCloseButton); + await browser + .$(Selectors.ConnectionModal) + .waitForDisplayed({ reverse: true }); + + // TODO(COMPASS-9746) the toasts should be swapped around before this can work + /* + await browser.clickVisible(Selectors.ConnectionToastErrorDebugButton); + const messagesElement = browser.$(Selectors.AssistantChatMessages) + await messagesElement.waitForDisplayed(); + // TODO(COMPASS-9744) check the response from the chatbot too + + await browser.waitUntil(async () => { + return (await messagesElement.getText()).includes('Given the error message below,'); + }); + + // clear the chat so that a broken message doesn't break every future message + await browser.clickVisible(Selectors.AssistantClearChatButton); + await browser.clickVisible(Selectors.ConfirmClearChatModalConfirmButton); + await browser.clickVisible(Selectors.SideDrawerCloseButton); + */ }); it('can connect to an Atlas replicaset without srv', async function () { From 2398388177a1bcf08fa3d86afa347097108a776c Mon Sep 17 00:00:00 2001 From: Le Roux Bodenstein Date: Mon, 25 Aug 2025 16:33:18 +0100 Subject: [PATCH 08/10] connection, not connetion --- .../src/components/connection-status-notifications.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/compass-connections/src/components/connection-status-notifications.tsx b/packages/compass-connections/src/components/connection-status-notifications.tsx index 73393ed6590..8679c4ec581 100644 --- a/packages/compass-connections/src/components/connection-status-notifications.tsx +++ b/packages/compass-connections/src/components/connection-status-notifications.tsx @@ -184,12 +184,12 @@ const openDebugConnectionErrorToast = ( error: Error, onDebugClick: () => void ) => { - openToast(`debug-connetion-error--${connectionInfo.id}`, { + openToast(`debug-connection-error--${connectionInfo.id}`, { title: 'Need help debugging your connection error?', description: ( { - closeToast(`debug-connetion-error--${connectionInfo.id}`); + closeToast(`debug-connection-error--${connectionInfo.id}`); onDebugClick(); }} /> From 0f144eed8752aac833288e6093ff844e62e1740e Mon Sep 17 00:00:00 2001 From: Le Roux Bodenstein Date: Tue, 26 Aug 2025 10:32:48 +0100 Subject: [PATCH 09/10] nit --- .../src/compass-assistant-drawer.tsx | 2 +- .../src/compass-assistant-provider.spec.tsx | 14 ++++++++------ packages/compass-e2e-tests/helpers/selectors.ts | 3 ++- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/packages/compass-assistant/src/compass-assistant-drawer.tsx b/packages/compass-assistant/src/compass-assistant-drawer.tsx index 6af3aa4c51c..dee3f70be35 100644 --- a/packages/compass-assistant/src/compass-assistant-drawer.tsx +++ b/packages/compass-assistant/src/compass-assistant-drawer.tsx @@ -33,7 +33,7 @@ export const CompassAssistantDrawer: React.FunctionComponent<{ 'The current chat will be cleared, and chat history will not be retrievable.', buttonText: 'Clear chat', variant: 'danger', - 'data-testid': 'confirm-clear-chat-modal', + 'data-testid': 'assistant-confirm-clear-chat-modal', }); if (confirmed) { clearChat(); diff --git a/packages/compass-assistant/src/compass-assistant-provider.spec.tsx b/packages/compass-assistant/src/compass-assistant-provider.spec.tsx index e5eb2d0cb01..ed2d155e45f 100644 --- a/packages/compass-assistant/src/compass-assistant-provider.spec.tsx +++ b/packages/compass-assistant/src/compass-assistant-provider.spec.tsx @@ -201,19 +201,20 @@ describe('AssistantProvider', function () { userEvent.click(clearButton); await waitFor(() => { - expect(screen.getByTestId('confirm-clear-chat-modal')).to.exist; + expect(screen.getByTestId('assistant-confirm-clear-chat-modal')).to + .exist; }); // There should be messages in the chat expect(screen.getByTestId('assistant-message-1')).to.exist; expect(screen.getByTestId('assistant-message-2')).to.exist; - const modal = screen.getByTestId('confirm-clear-chat-modal'); + const modal = screen.getByTestId('assistant-confirm-clear-chat-modal'); const confirmButton = within(modal).getByText('Clear chat'); userEvent.click(confirmButton); await waitForElementToBeRemoved(() => - screen.getByTestId('confirm-clear-chat-modal') + screen.getByTestId('assistant-confirm-clear-chat-modal') ); expect(mockChat.messages).to.be.empty; @@ -230,19 +231,20 @@ describe('AssistantProvider', function () { userEvent.click(clearButton); await waitFor(() => { - expect(screen.getByTestId('confirm-clear-chat-modal')).to.exist; + expect(screen.getByTestId('assistant-confirm-clear-chat-modal')).to + .exist; }); // There should be messages in the chat expect(screen.getByTestId('assistant-message-1')).to.exist; expect(screen.getByTestId('assistant-message-2')).to.exist; - const modal = screen.getByTestId('confirm-clear-chat-modal'); + const modal = screen.getByTestId('assistant-confirm-clear-chat-modal'); const cancelButton = within(modal).getByText('Cancel'); userEvent.click(cancelButton); await waitForElementToBeRemoved(() => - screen.getByTestId('confirm-clear-chat-modal') + screen.getByTestId('assistant-confirm-clear-chat-modal') ); expect(mockChat.messages).to.deep.equal(mockMessages); diff --git a/packages/compass-e2e-tests/helpers/selectors.ts b/packages/compass-e2e-tests/helpers/selectors.ts index 57b3a84d440..2b646478906 100644 --- a/packages/compass-e2e-tests/helpers/selectors.ts +++ b/packages/compass-e2e-tests/helpers/selectors.ts @@ -1517,5 +1517,6 @@ export const SideDrawerCloseButton = `[data-testid="${ // Assistant export const AssistantChatMessages = '[data-testid="assistant-chat-messages"]'; export const AssistantClearChatButton = '[data-testid="assistant-clear-chat"]'; -export const ConfirmClearChatModal = '[data-testid="confirm-clear-chat-modal"]'; +export const ConfirmClearChatModal = + '[data-testid="assistant-confirm-clear-chat-modal"]'; export const ConfirmClearChatModalConfirmButton = `${ConfirmClearChatModal} [data-testid="lg-confirmation_modal-footer-confirm_button"]`; From 857510964b6a89a0374515fa23ea8df86ba611bf Mon Sep 17 00:00:00 2001 From: Le Roux Bodenstein Date: Tue, 26 Aug 2025 11:21:21 +0100 Subject: [PATCH 10/10] depcheck --- package-lock.json | 2 -- packages/connection-storage/package.json | 1 - 2 files changed, 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index da71fa2d534..f165e509ea6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -51637,7 +51637,6 @@ "license": "SSPL", "dependencies": { "@mongodb-js/compass-app-registry": "^9.4.20", - "@mongodb-js/compass-assistant": "^1.2.0", "@mongodb-js/compass-logging": "^1.7.12", "@mongodb-js/compass-telemetry": "^1.14.0", "@mongodb-js/compass-user-data": "^0.9.1", @@ -63785,7 +63784,6 @@ "version": "file:packages/connection-storage", "requires": { "@mongodb-js/compass-app-registry": "^9.4.20", - "@mongodb-js/compass-assistant": "^1.2.0", "@mongodb-js/compass-logging": "^1.7.12", "@mongodb-js/compass-telemetry": "^1.14.0", "@mongodb-js/compass-user-data": "^0.9.1", diff --git a/packages/connection-storage/package.json b/packages/connection-storage/package.json index 31262a2b904..b4e4231d925 100644 --- a/packages/connection-storage/package.json +++ b/packages/connection-storage/package.json @@ -57,7 +57,6 @@ }, "dependencies": { "@mongodb-js/compass-app-registry": "^9.4.20", - "@mongodb-js/compass-assistant": "^1.2.0", "@mongodb-js/compass-logging": "^1.7.12", "@mongodb-js/compass-telemetry": "^1.14.0", "@mongodb-js/compass-user-data": "^0.9.1",