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
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ interface UseChatComplete {
// useChatComplete uses the same api as useSendMessage (post_actions_connector_execute) but without requiring conversationId/apiConfig
// it is meant to be used for one-off messages that don't require a conversation
export const useChatComplete = ({ connectorId }: { connectorId: string }): UseChatComplete => {
const { alertsIndexPattern, http, traceOptions } = useAssistantContext();
const { alertsIndexPattern, http, traceOptions, settings } = useAssistantContext();
const [isLoading, setIsLoading] = useState(false);
const abortController = useRef(new AbortController());
const { data: connectors } = useLoadConnectors({ http, inferenceEnabled: true });
const { data: connectors } = useLoadConnectors({ http, inferenceEnabled: true, settings });
const actionTypeId = useMemo(
() => connectors?.find(({ id }) => id === connectorId)?.actionTypeId ?? '.gen-ai',
[connectors, connectorId]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
ConversationSharedState,
} from '@kbn/elastic-assistant-common';
import { ShareSelect } from '../../share_conversation/share_select';
import type { Conversation } from '../../../..';
import { useAssistantContext, type Conversation } from '../../../..';
import * as i18n from './translations';
import * as i18nModel from '../../../connectorland/models/model_selector/translations';

Expand Down Expand Up @@ -57,8 +57,10 @@ export const ConversationSettingsEditor: React.FC<ConversationSettingsEditorProp
selectedConversation,
setConversationsSettingsBulkActions,
}) => {
const { settings } = useAssistantContext();
const { data: connectors, isSuccess: areConnectorsFetched } = useLoadConnectors({
http,
settings,
});
const [conversationUpdates, setConversationUpdates] =
useState<Conversation>(selectedConversation);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

import { getDefaultConnector, getOptionalRequestParams } from './helpers';
import type { AIConnector } from '../connectorland/connector_selector';
import type { SettingsStart } from '@kbn/core-ui-settings-browser';
import { GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR } from '@kbn/management-settings-ids';

describe('helpers', () => {
describe('getDefaultConnector', () => {
Expand All @@ -25,41 +27,97 @@ describe('helpers', () => {
apiUrl: 'https://api.openai.com/v1/chat/completions',
},
};

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion to define another connector here with the overrides

const anotherConnector =  {
          ...defaultConnector,
          id: 'c7f91dc0-2197-11ee-aded-897192c5d633',
          name: 'OpenAI',
          config: {
            apiProvider: 'OpenAI 2',
            apiUrl: 'https://api.openai.com/v1/chat/completions',
          },
        }

here and use it for the tests below for readability. So below you can do:

const connectors: AIConnector[] = [anotherConnector, defaultConnector]

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added in ddacd02

const connector2: AIConnector = {
...defaultConnector,
id: 'c7f91dc0-2197-11ee-aded-897192c5d633',
name: 'OpenAI',
config: {
apiProvider: 'OpenAI 2',
apiUrl: 'https://api.openai.com/v1/chat/completions',
},
};

const clientGet = jest.fn();

const settings = {
client: {
get: clientGet,
},
} as unknown as SettingsStart;

beforeEach(() => {
jest.clearAllMocks();
clientGet.mockImplementation((key: string) => {
return undefined;
});
});

it('should return undefined if connectors array is undefined', () => {
const connectors = undefined;
const result = getDefaultConnector(connectors);
const result = getDefaultConnector(connectors, settings);

expect(result).toBeUndefined();
});

it('should return undefined if connectors array is empty', () => {
const connectors: AIConnector[] = [];
const result = getDefaultConnector(connectors);
const result = getDefaultConnector(connectors, settings);

expect(result).toBeUndefined();
});

it('should return the connector id if there is only one connector', () => {
it('should return the first connector if there is only one connector available', () => {
const connectors: AIConnector[] = [defaultConnector];
const result = getDefaultConnector(connectors);
const result = getDefaultConnector(connectors, settings);

expect(result).toBe(connectors[0]);
});

it('should return the connector id if there are multiple connectors', () => {
const connectors: AIConnector[] = [
defaultConnector,
{
...defaultConnector,
id: 'c7f91dc0-2197-11ee-aded-897192c5d633',
name: 'OpenAI',
config: {
apiProvider: 'OpenAI 2',
apiUrl: 'https://api.openai.com/v1/chat/completions',
},
},
];
const result = getDefaultConnector(connectors);
it('should return the default connector if there are multiple connectors and default connector is defined', () => {
clientGet.mockImplementation((key: string) => {
if (key === GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR) {
return defaultConnector.id;
}
return undefined;
});
const connectors: AIConnector[] = [defaultConnector, connector2];
const result = getDefaultConnector(connectors, settings);
expect(result).toBe(defaultConnector);
});

it('should return the default connector if there are multiple connectors and default connector is defined but they are in a different order', () => {
clientGet.mockImplementation((key: string) => {
if (key === GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR) {
return defaultConnector.id;
}
return undefined;
});
const connectors: AIConnector[] = [connector2, defaultConnector];
const result = getDefaultConnector(connectors, settings);
expect(result).toBe(defaultConnector);
});

it('should return the first connector if there are multiple connectors and no default connector is defined', () => {
clientGet.mockImplementation(() => {
return undefined;
});

const connectors: AIConnector[] = [connector2, defaultConnector];
const result = getDefaultConnector(connectors, settings);
expect(result).toBe(connectors[0]);
});

it('should return the first connector if there are multiple connectors and a default connector is defined but it does not exist', () => {
clientGet.mockImplementation((key: string) => {
if (key === GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR) {
return 'randomConnectorIdThatDoesNotExist';
}
return undefined;
});

const connectors: AIConnector[] = [connector2, defaultConnector];
const result = getDefaultConnector(connectors, settings);
expect(result).toBe(connectors[0]);
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
* 2.0.
*/

import type { SettingsStart } from '@kbn/core-ui-settings-browser';
import { GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR } from '@kbn/management-settings-ids';
import type { AIConnector } from '../connectorland/connector_selector';
import type { FetchConnectorExecuteResponse } from './api';
import type { ClientMessage } from '../assistant_context/types';
Expand Down Expand Up @@ -40,13 +42,30 @@ export const getMessageFromRawResponse = (
* @param connectors
*/
export const getDefaultConnector = (
connectors: AIConnector[] | undefined
connectors: AIConnector[] | undefined,
settings: SettingsStart
): AIConnector | undefined => {
const defaultAiConnectorId = settings.client.get<string>(
GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR,
undefined
);

const validConnectors = connectors?.filter((connector) => !connector.isMissingSecrets);
const defaultConnector = validConnectors?.find(
(connector) => connector.id === defaultAiConnectorId
);

if (defaultConnector) {
// If the user has set a default connector setting, and that connector exists, use it
return defaultConnector;
}

if (validConnectors?.length) {
// In case the default connector is not set or is invalid, return the first valid connector
return validConnectors[0];
}

// If no valid connectors are available, return undefined
return undefined;
};
Comment on lines 44 to 70
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One of the main changes in this PR


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ const AssistantComponent: React.FC<Props> = ({
showAnonymizedValues,
setContentReferencesVisible,
setShowAnonymizedValues,
settings,
} = useAssistantContext();

const [selectedPromptContexts, setSelectedPromptContexts] = useState<
Expand Down Expand Up @@ -123,8 +124,12 @@ const AssistantComponent: React.FC<Props> = ({
// Connector details
const { data: connectors, isFetchedAfterMount: isFetchedConnectors } = useLoadConnectors({
http,
settings,
});
const defaultConnector = useMemo(() => getDefaultConnector(connectors), [connectors]);
const defaultConnector = useMemo(
() => getDefaultConnector(connectors, settings),
[connectors, settings]
);
const spaceId = useAssistantSpaceId();
const { getLastConversation, setLastConversation } = useAssistantLastConversation({ spaceId });
const lastConversationFromLocalStorage = useMemo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export const AssistantSettings: React.FC<Props> = React.memo(
selectedSettingsTab,
setSelectedSettingsTab,
toasts,
settings,
} = useAssistantContext();

useEffect(() => {
Expand All @@ -81,6 +82,7 @@ export const AssistantSettings: React.FC<Props> = React.memo(

const { data: connectors } = useLoadConnectors({
http,
settings,
});
const {
conversationsSettingsBulkActions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ import {
SYSTEM_PROMPTS_TAB,
} from './const';
import type { DataViewsContract } from '@kbn/data-views-plugin/public';
import {
GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR,
GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR_DEFAULT_ONLY,
} from '@kbn/management-settings-ids';

const mockSetSelectedSettingsTab = jest.fn();

Expand All @@ -38,6 +42,19 @@ const mockContext = {
isAssistantManagementEnabled: true,
hasConnectorsAllPrivilege: true,
},
settings: {
client: {
get: jest.fn((key) => {
if (key === GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR) {
return 'c5f91dc0-2197-11ee-aded-897192c5d6f5';
}
if (key === GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR_DEFAULT_ONLY) {
return false;
}
return undefined;
}),
},
},
selectedSettingsTab: null,
setSelectedSettingsTab: mockSetSelectedSettingsTab,
navigateToApp: jest.fn(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export const AssistantSettingsManagement: React.FC<Props> = React.memo(
setSelectedSettingsTab,
navigateToApp,
assistantAvailability: { isAssistantManagementEnabled, hasConnectorsAllPrivilege },
settings,
} = useAssistantContext();

useEffect(() => {
Expand All @@ -68,8 +69,12 @@ export const AssistantSettingsManagement: React.FC<Props> = React.memo(

const { data: connectors } = useLoadConnectors({
http,
settings,
});
const defaultConnector = useMemo(() => getDefaultConnector(connectors), [connectors]);
const defaultConnector = useMemo(
() => getDefaultConnector(connectors, settings),
[connectors, settings]
);

const { euiTheme } = useEuiTheme();
const headerIconShadow = useEuiShadow('s');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,9 @@ const AS_PLAIN_TEXT: EuiComboBoxSingleSelectionShape = { asPlainText: true };
* Evaluation Settings -- development-only feature for evaluating models
*/
export const EvaluationSettings: React.FC = React.memo(() => {
const { actionTypeRegistry, http, setTraceOptions, toasts, traceOptions } = useAssistantContext();
const { data: connectors } = useLoadConnectors({ http, inferenceEnabled: true });
const { actionTypeRegistry, http, setTraceOptions, toasts, traceOptions, settings } =
useAssistantContext();
const { data: connectors } = useLoadConnectors({ http, inferenceEnabled: true, settings });
const { mutate: performEvaluation, isLoading: isPerformingEvaluation } = usePerformEvaluation({
http,
toasts,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ import {
SYSTEM_PROMPTS_TAB,
} from './const';
import type { DataViewsContract } from '@kbn/data-views-plugin/public';
import {
GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR,
GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR_DEFAULT_ONLY,
} from '@kbn/management-settings-ids';

const mockContext = {
basePromptContexts: MOCK_QUICK_PROMPTS,
Expand All @@ -34,6 +38,19 @@ const mockContext = {
assistantAvailability: {
isAssistantEnabled: true,
},
settings: {
client: {
get: jest.fn((key) => {
if (key === GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR) {
return 'c5f91dc0-2197-11ee-aded-897192c5d6f5';
}
if (key === GEN_AI_SETTINGS_DEFAULT_AI_CONNECTOR_DEFAULT_ONLY) {
return false;
}
return undefined;
}),
},
},
};

const mockDataViews = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export const SearchAILakeConfigurationsSettingsManagement: React.FC<Props> = Rea
http,
selectedSettingsTab,
setSelectedSettingsTab,
settings,
} = useAssistantContext();

useEffect(() => {
Expand All @@ -66,8 +67,12 @@ export const SearchAILakeConfigurationsSettingsManagement: React.FC<Props> = Rea

const { data: connectors } = useLoadConnectors({
http,
settings,
});
const defaultConnector = useMemo(() => getDefaultConnector(connectors), [connectors]);
const defaultConnector = useMemo(
() => getDefaultConnector(connectors, settings),
[connectors, settings]
);

const { euiTheme } = useEuiTheme();

Expand Down
Loading