diff --git a/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/additional_options_fields.tsx b/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/additional_options_fields.tsx index fbd0e9642528c..d89ae352957ed 100644 --- a/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/additional_options_fields.tsx +++ b/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/additional_options_fields.tsx @@ -34,7 +34,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { fieldValidators } from '@kbn/es-ui-shared-plugin/static/forms/helpers'; import { ConfigurationFormItems } from './configuration/configuration_form_items'; import * as LABELS from '../translations'; -import { DEFAULT_TASK_TYPE } from '../constants'; +import { DEFAULT_TASK_TYPE, internalProviderKeys } from '../constants'; import { Config, ConfigEntryView } from '../types/types'; import { TaskTypeOption } from '../utils/helpers'; @@ -183,26 +183,25 @@ export const AdditionalOptionsFields: React.FC = ( {optionalProviderFormFields.length > 0 ? ( <> - -

- -

-
- - - - + {internalProviderKeys.includes(config.provider) ? null : ( + <> + +

+ +

+
+ + + + + + )} { + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + + return ( + <> + + + +
+ +
+
+
+ + setIsPopoverOpen(!isPopoverOpen)} + iconType="info" + aria-label={i18n.translate( + 'xpack.inferenceEndpointUICommon.components.adaptiveResourcesAriaLabel', + { + defaultMessage: 'Open adaptive resources information popover', + } + )} + /> + } + isOpen={isPopoverOpen} + closePopover={() => setIsPopoverOpen(false)} + > + + + +
+ +

+ {str}, + }} + /> +

+

+ +

+

+ +

+
+
+
+
+
+ + + + + + ); +}; diff --git a/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/configuration/configuration_field.tsx b/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/configuration/configuration_field.tsx index 69c5b75253399..466ff4a0b0ae1 100644 --- a/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/configuration/configuration_field.tsx +++ b/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/configuration/configuration_field.tsx @@ -11,6 +11,7 @@ import { EuiAccordion, EuiFieldText, EuiFieldPassword, + EuiFormControlLayout, EuiSwitch, EuiTextArea, EuiFieldNumber, @@ -127,18 +128,29 @@ export const ConfigNumberField: React.FC = ({ setInnerValue(!value || value.toString().length === 0 ? defaultValue : value); }, [defaultValue, value]); return ( - { - const newValue = isEmpty(event.target.value) ? '0' : event.target.value; - setInnerValue(newValue); - validateAndSetConfigValue(newValue); + clear={{ + onClick: (e) => { + validateAndSetConfigValue(''); + setInnerValue(''); + }, }} - /> + > + { + const newValue = isEmpty(event.target.value) ? '0' : event.target.value; + setInnerValue(newValue); + validateAndSetConfigValue(newValue); + }} + /> + ); }; diff --git a/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/configuration/configuration_form_items.tsx b/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/configuration/configuration_form_items.tsx index 21811410aabbf..b3e10431f867b 100644 --- a/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/configuration/configuration_form_items.tsx +++ b/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/configuration/configuration_form_items.tsx @@ -19,6 +19,7 @@ import { import { ConfigEntryView } from '../../types/types'; import { ConfigurationField } from './configuration_field'; +import { ConfigFieldTitularComponent } from './titular_component_registry'; import * as LABELS from '../../translations'; interface ConfigurationFormItemsProps { @@ -81,6 +82,7 @@ export const ConfigurationFormItems: React.FC = ({ return ( + = { + [MAX_NUMBER_OF_ALLOCATIONS]: AdaptiveAllocationsTitle, +}; + +export const ConfigFieldTitularComponent = ({ configKey }: { configKey: string }) => { + const Component = titularComponents[configKey]; + + if (!Component) { + return null; + } + return ?? null; +}; diff --git a/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/inference_flyout_wrapper.tsx b/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/inference_flyout_wrapper.tsx index 1093e1cbb92b2..c008488995a43 100644 --- a/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/inference_flyout_wrapper.tsx +++ b/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/inference_flyout_wrapper.tsx @@ -19,7 +19,6 @@ import { useGeneratedHtmlId, } from '@elastic/eui'; import React, { useCallback } from 'react'; - import { HttpSetup, IToasts } from '@kbn/core/public'; import { Form, useForm } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import * as LABELS from '../translations'; @@ -27,11 +26,73 @@ import type { InferenceEndpoint } from '../types/types'; import { InferenceServiceFormFields } from './inference_service_form_fields'; import { useInferenceEndpointMutation } from '../hooks/use_inference_endpoint_mutation'; +const MIN_ALLOCATIONS = 0; +const DEFAULT_NUM_THREADS = 1; + +const formDeserializer = (data: InferenceEndpoint) => { + if ( + data?.config?.providerConfig && + data?.config?.providerConfig['adaptive_allocations.max_number_of_allocations'] + ) { + // remove num_allocations and num_threads from the data as form does not expect it + const { + num_allocations: numAllocations, + num_threads: numThreads, + ...restOfProviderConfig + } = data.config.providerConfig; + return { + ...data, + config: { + ...data.config, + providerConfig: { + ...restOfProviderConfig, + max_number_of_allocations: + restOfProviderConfig['adaptive_allocations.max_number_of_allocations'], + }, + }, + }; + } + + return data; +}; + +// This serializer is used to transform the form data before sending it to the server +const formSerializer = (formData: InferenceEndpoint) => { + if ( + // explicit check to see if this field exists as it only exists in serverless + formData.config?.providerConfig?.max_number_of_allocations !== undefined + ) { + const providerConfig = formData.config?.providerConfig; + const { max_number_of_allocations: maxAllocations, ...restProviderConfig } = + providerConfig || {}; + + return { + ...formData, + config: { + ...formData.config, + providerConfig: { + ...restProviderConfig, + adaptive_allocations: { + enabled: true, + min_number_of_allocations: MIN_ALLOCATIONS, + ...(maxAllocations ? { max_number_of_allocations: maxAllocations } : {}), + }, + // Temporary solution until the endpoint is updated to no longer require it and to set its own default for this value + num_threads: DEFAULT_NUM_THREADS, + }, + }, + }; + } + + return formData; +}; + interface InferenceFlyoutWrapperProps { onFlyoutClose: () => void; http: HttpSetup; toasts: IToasts; isEdit?: boolean; + enforceAdaptiveAllocations?: boolean; onSubmitSuccess?: (inferenceId: string) => void; inferenceEndpoint?: InferenceEndpoint; } @@ -41,6 +102,7 @@ export const InferenceFlyoutWrapper: React.FC = ({ http, toasts, isEdit, + enforceAdaptiveAllocations = false, onSubmitSuccess, inferenceEndpoint, }) => { @@ -68,6 +130,8 @@ export const InferenceFlyoutWrapper: React.FC = ({ providerSecrets: {}, }, }, + serializer: formSerializer, + deserializer: formDeserializer, }); const handleSubmit = useCallback(async () => { const { isValid, data } = await form.submit(); @@ -98,6 +162,7 @@ export const InferenceFlyoutWrapper: React.FC = ({ http={http} toasts={toasts} isEdit={isEdit} + enforceAdaptiveAllocations={enforceAdaptiveAllocations} isPreconfigured={isPreconfigured} /> diff --git a/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/inference_service_form_fields.tsx b/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/inference_service_form_fields.tsx index 6aa1a03263749..d958c74dc6dde 100644 --- a/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/inference_service_form_fields.tsx +++ b/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/inference_service_form_fields.tsx @@ -30,7 +30,7 @@ import { HttpSetup, IToasts } from '@kbn/core/public'; import * as LABELS from '../translations'; import { Config, ConfigEntryView, InferenceProvider, Secrets } from '../types/types'; import { SERVICE_PROVIDERS } from './providers/render_service_provider/service_provider'; -import { DEFAULT_TASK_TYPE, ServiceProviderKeys } from '../constants'; +import { DEFAULT_TASK_TYPE, ServiceProviderKeys, INTERNAL_OVERRIDE_FIELDS } from '../constants'; import { SelectableProvider } from './providers/selectable'; import { TaskTypeOption, @@ -48,6 +48,7 @@ interface InferenceServicesProps { http: HttpSetup; toasts: IToasts; isEdit?: boolean; + enforceAdaptiveAllocations?: boolean; isPreconfigured?: boolean; } @@ -55,6 +56,7 @@ export const InferenceServiceFormFields: React.FC = ({ http, toasts, isEdit, + enforceAdaptiveAllocations, isPreconfigured, }) => { const { data: providers, isLoading } = useProviders(http, toasts); @@ -118,7 +120,11 @@ export const InferenceServiceFormFields: React.FC = ({ (p) => p.service === (config.provider === '' ? providerSelected : config.provider) ); if (newProvider) { - const newProviderSchema: ConfigEntryView[] = mapProviderFields(taskType, newProvider); + const newProviderSchema: ConfigEntryView[] = mapProviderFields( + taskType, + newProvider, + enforceAdaptiveAllocations ? INTERNAL_OVERRIDE_FIELDS[newProvider.service] : undefined + ); setProviderSchema(newProviderSchema); } @@ -155,7 +161,7 @@ export const InferenceServiceFormFields: React.FC = ({ }, }); }, - [config, secrets, updateFieldValues, updatedProviders] + [config, enforceAdaptiveAllocations, secrets, updateFieldValues, updatedProviders] ); const onProviderChange = useCallback( @@ -171,7 +177,11 @@ export const InferenceServiceFormFields: React.FC = ({ const defaultProviderSecrets: Record = {}; const newProviderSchema: ConfigEntryView[] = newProvider - ? mapProviderFields(newProvider.task_types[0], newProvider) + ? mapProviderFields( + newProvider.task_types[0], + newProvider, + enforceAdaptiveAllocations ? INTERNAL_OVERRIDE_FIELDS[newProvider.service] : undefined + ) : []; if (newProvider) { setProviderSchema(newProviderSchema); @@ -205,7 +215,13 @@ export const InferenceServiceFormFields: React.FC = ({ }, }); }, - [config, onTaskTypeOptionsSelect, updateFieldValues, updatedProviders] + [ + config, + enforceAdaptiveAllocations, + onTaskTypeOptionsSelect, + updateFieldValues, + updatedProviders, + ] ); const onSetProviderConfigEntry = useCallback( @@ -303,14 +319,26 @@ export const InferenceServiceFormFields: React.FC = ({ // Update connector providerSchema const newProviderSchema: ConfigEntryView[] = newProvider - ? mapProviderFields(config.taskType, newProvider) + ? mapProviderFields( + config.taskType, + newProvider, + enforceAdaptiveAllocations ? INTERNAL_OVERRIDE_FIELDS[newProvider.service] : undefined + ) : []; if (newProvider) { setProviderSchema(newProviderSchema); } setSelectedTaskType(config.taskType); } - }, [config, config?.provider, config?.taskType, isEdit, selectedTaskType, updatedProviders]); + }, [ + config, + config?.provider, + config?.taskType, + isEdit, + enforceAdaptiveAllocations, + selectedTaskType, + updatedProviders, + ]); useEffect(() => { if (isSubmitting) { diff --git a/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/constants.ts b/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/constants.ts index 8b17cbd634ad8..aa725a39fa8cb 100644 --- a/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/constants.ts +++ b/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/constants.ts @@ -5,6 +5,9 @@ * 2.0. */ +import type { FieldsConfiguration } from './types/types'; +import { FieldType } from './types/types'; + export enum ServiceProviderKeys { 'alibabacloud-ai-search' = 'alibabacloud-ai-search', amazonbedrock = 'amazonbedrock', @@ -27,3 +30,38 @@ export enum ServiceProviderKeys { } export const DEFAULT_TASK_TYPE = 'completion'; +export const internalProviderKeys: Array = [ + ServiceProviderKeys.elasticsearch, +]; + +type ServiceProviderKeysType = keyof typeof ServiceProviderKeys; +type InternalOverrideFieldsType = { + [Key in ServiceProviderKeysType | string]?: { + hidden: string[]; + additional: FieldsConfiguration[]; + }; +}; + +export const MAX_NUMBER_OF_ALLOCATIONS = 'max_number_of_allocations'; + +// This is a temporaray solution to handle the internal overrides for field configurations that have not been updated in the services endpoint +export const INTERNAL_OVERRIDE_FIELDS: InternalOverrideFieldsType = { + [ServiceProviderKeys.elasticsearch]: { + hidden: ['num_allocations', 'num_threads'], + additional: [ + { + [MAX_NUMBER_OF_ALLOCATIONS]: { + default_value: null, + description: + 'Maximum scaling limit available to the endpoint. Max allocations will determine the maximum number of VCUs that the endpoint can scale up to.', + label: 'Max scaling limit (allocations)', + required: false, + sensitive: false, + supported_task_types: ['text_embedding', 'sparse_embedding', 'rerank'], + type: FieldType.INTEGER, + updatable: false, + }, + }, + ], + }, +}; diff --git a/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/types/types.ts b/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/types/types.ts index 17f163cabdb5d..853d1556c223c 100644 --- a/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/types/types.ts +++ b/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/types/types.ts @@ -40,13 +40,6 @@ export interface InferenceProvider { logo?: string; configurations: FieldsConfiguration; } -export interface Config { - taskType: string; - taskTypeConfig?: Record; - inferenceId: string; - provider: string; - providerConfig?: Record; -} export interface Secrets { providerSecrets?: Record; diff --git a/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/utils/helpers.ts b/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/utils/helpers.ts index a12e02f4c58fa..0b36203b3081d 100644 --- a/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/utils/helpers.ts +++ b/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/utils/helpers.ts @@ -8,6 +8,7 @@ import { ValidationFunc } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { isEmpty } from 'lodash/fp'; import { Config, ConfigEntryView, FieldType, InferenceProvider } from '../types/types'; +import type { FieldsConfiguration } from '../types/types'; import * as LABELS from '../translations'; export interface TaskTypeOption { @@ -79,11 +80,25 @@ export const getNonEmptyValidator = ( export const mapProviderFields = ( taskType: string, - newProvider: InferenceProvider + newProvider: InferenceProvider, + fieldOverrides?: { hidden: string[]; additional: FieldsConfiguration[] } ): ConfigEntryView[] => { + // fieldOverrides.additional + // e.g. [ { field: { default_value: 'value', ...}, other_field: { default_value: 'value', ...} } ] + if (fieldOverrides?.additional) { + fieldOverrides?.additional.forEach((additionalField) => { + const fieldKey = Object.keys(additionalField)[0]; + if (!newProvider.configurations[fieldKey]) { + newProvider.configurations[fieldKey] = additionalField[fieldKey]; + } + }); + } + return Object.keys(newProvider.configurations ?? {}) - .filter((pk) => - (newProvider.configurations[pk].supported_task_types ?? [taskType]).includes(taskType) + .filter( + (pk) => + (newProvider.configurations[pk].supported_task_types ?? [taskType]).includes(taskType) && + (fieldOverrides?.hidden ?? []).indexOf(pk) === -1 ) .map( (k): ConfigEntryView => ({ diff --git a/x-pack/platform/plugins/shared/index_management/__jest__/client_integration/index_details_page/select_inference_id.test.tsx b/x-pack/platform/plugins/shared/index_management/__jest__/client_integration/index_details_page/select_inference_id.test.tsx index 6861e3c6cd3ee..2ee618151d994 100644 --- a/x-pack/platform/plugins/shared/index_management/__jest__/client_integration/index_details_page/select_inference_id.test.tsx +++ b/x-pack/platform/plugins/shared/index_management/__jest__/client_integration/index_details_page/select_inference_id.test.tsx @@ -35,6 +35,7 @@ jest.mock('../../../public/application/app_context', () => ({ }, }, }, + config: { enforceAdaptiveAllocations: false }, services: { notificationService: { toasts: {}, diff --git a/x-pack/platform/plugins/shared/index_management/kibana.jsonc b/x-pack/platform/plugins/shared/index_management/kibana.jsonc index 3400b04a51180..5e7f64e5589bc 100644 --- a/x-pack/platform/plugins/shared/index_management/kibana.jsonc +++ b/x-pack/platform/plugins/shared/index_management/kibana.jsonc @@ -18,7 +18,7 @@ "home", "management", "features", - "share" + "share", ], "optionalPlugins": [ "security", diff --git a/x-pack/platform/plugins/shared/index_management/public/application/app_context.tsx b/x-pack/platform/plugins/shared/index_management/public/application/app_context.tsx index 416479e5b5b08..782de76c7832c 100644 --- a/x-pack/platform/plugins/shared/index_management/public/application/app_context.tsx +++ b/x-pack/platform/plugins/shared/index_management/public/application/app_context.tsx @@ -75,6 +75,7 @@ export interface AppDependencies { enableTogglingDataRetention: boolean; enableProjectLevelRetentionChecks: boolean; enableSemanticText: boolean; + enforceAdaptiveAllocations: boolean; }; history: ScopedHistory; setBreadcrumbs: (type: IndexManagementBreadcrumb, additionalBreadcrumb?: EuiBreadcrumb) => void; diff --git a/x-pack/platform/plugins/shared/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.tsx b/x-pack/platform/plugins/shared/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.tsx index 375601420073a..d615f5d698a3c 100644 --- a/x-pack/platform/plugins/shared/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.tsx +++ b/x-pack/platform/plugins/shared/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/select_inference_id.tsx @@ -67,6 +67,7 @@ const SelectInferenceIdContent: React.FC = ({ }) => { const { core: { application, http }, + config: { enforceAdaptiveAllocations }, services: { notificationService: { toasts }, }, @@ -281,6 +282,7 @@ const SelectInferenceIdContent: React.FC = ({ toasts={toasts} isEdit={false} onSubmitSuccess={onSubmitSuccess} + enforceAdaptiveAllocations={enforceAdaptiveAllocations} /> ) : null} diff --git a/x-pack/platform/plugins/shared/index_management/public/plugin.ts b/x-pack/platform/plugins/shared/index_management/public/plugin.ts index 43e8635e279ad..dd4667192d49e 100644 --- a/x-pack/platform/plugins/shared/index_management/public/plugin.ts +++ b/x-pack/platform/plugins/shared/index_management/public/plugin.ts @@ -71,6 +71,7 @@ export class IndexMgmtUIPlugin enableTogglingDataRetention: boolean; enableProjectLevelRetentionChecks: boolean; enableSemanticText: boolean; + enforceAdaptiveAllocations: boolean; }; private canUseSyntheticSource: boolean = false; private licensingSubscription?: Subscription; @@ -107,6 +108,7 @@ export class IndexMgmtUIPlugin enableTogglingDataRetention: enableTogglingDataRetention ?? true, enableProjectLevelRetentionChecks: enableProjectLevelRetentionChecks ?? false, enableSemanticText: enableSemanticText ?? true, + enforceAdaptiveAllocations: ctx.env.packageInfo.buildFlavor === 'serverless', }; } diff --git a/x-pack/platform/plugins/shared/stack_connectors/public/connector_types/inference/connector.tsx b/x-pack/platform/plugins/shared/stack_connectors/public/connector_types/inference/connector.tsx index 261c2d5a34154..e071725780b95 100644 --- a/x-pack/platform/plugins/shared/stack_connectors/public/connector_types/inference/connector.tsx +++ b/x-pack/platform/plugins/shared/stack_connectors/public/connector_types/inference/connector.tsx @@ -9,6 +9,7 @@ import React from 'react'; import { InferenceServiceFormFields } from '@kbn/inference-endpoint-ui-common'; import { type ActionConnectorFieldsProps } from '@kbn/triggers-actions-ui-plugin/public'; import { useKibana } from '@kbn/triggers-actions-ui-plugin/public'; +import { useConnectorContext } from '@kbn/triggers-actions-ui-plugin/public'; const InferenceAPIConnectorFields: React.FunctionComponent = ({ isEdit, @@ -16,9 +17,19 @@ const InferenceAPIConnectorFields: React.FunctionComponent; + return ( + + ); }; // eslint-disable-next-line import/no-default-export diff --git a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/connectors_app.tsx b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/connectors_app.tsx index f66ca07e3e861..a34cf51a9d39a 100644 --- a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/connectors_app.tsx +++ b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/connectors_app.tsx @@ -59,6 +59,7 @@ export interface TriggersAndActionsUiServices extends CoreStart { theme$: Observable; unifiedSearch: UnifiedSearchPublicPluginStart; share: SharePluginStart; + isServerless: boolean; } export const renderApp = (deps: TriggersAndActionsUiServices) => { @@ -91,12 +92,14 @@ export const App = ({ deps }: { deps: TriggersAndActionsUiServices }) => { export const AppWithoutRouter = ({ sectionsRegex }: { sectionsRegex: string }) => { const { actions: { validateEmailAddresses, enabledEmailServices, isWebhookSslWithPfxEnabled }, + isServerless, } = useKibana().services; return ( diff --git a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/context/connector_context.tsx b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/context/connector_context.tsx index 379e75bee8f20..bfd9edf2ae925 100644 --- a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/context/connector_context.tsx +++ b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/context/connector_context.tsx @@ -10,6 +10,7 @@ import { ConnectorServices } from '../../types'; export interface ConnectorContextValue { services: ConnectorServices; + isServerless?: boolean; } export const ConnectorContext = React.createContext(undefined); diff --git a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/rules_app.tsx b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/rules_app.tsx index dba5bf030199d..abfdf0fe9a3dc 100644 --- a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/rules_app.tsx +++ b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/rules_app.tsx @@ -122,10 +122,13 @@ export const AppWithoutRouter = ({ sectionsRegex }: { sectionsRegex: string }) = const { actions: { validateEmailAddresses, enabledEmailServices }, application: { navigateToApp }, + isServerless, } = useKibana().services; return ( - + void; setResetForm?: (value: ResetForm) => void; } + +interface InferenceConnectorProviderConfig { + [key: string]: unknown; + max_number_of_allocations?: number; + adaptive_allocations?: { max_number_of_allocations?: number }; +} /** * The serializer and deserializer are needed to transform the headers of * the webhook connectors. The webhook connector uses the UseArray component @@ -61,6 +70,28 @@ interface Props { // TODO: Remove when https://github.com/elastic/kibana/issues/133107 is resolved const formDeserializer = (data: ConnectorFormSchema): ConnectorFormSchema => { + if ( + data.actionTypeId === '.inference' && + // explicit check to see if this field exists as it only exists in serverless + (data.config?.providerConfig as InferenceConnectorProviderConfig)?.adaptive_allocations + ?.max_number_of_allocations + ) { + return { + ...data, + config: { + ...data.config, + providerConfig: { + ...(data.config.providerConfig as InferenceConnectorProviderConfig), + max_number_of_allocations: ( + data.config.providerConfig as InferenceConnectorProviderConfig + ).adaptive_allocations?.max_number_of_allocations, + // remove the adaptive_allocations from the data config as form does not expect it + adaptive_allocations: undefined, + }, + }, + }; + } + if ( data.actionTypeId !== '.webhook' && data.actionTypeId !== '.cases-webhook' && @@ -86,6 +117,35 @@ const formDeserializer = (data: ConnectorFormSchema): ConnectorFormSchema => { // TODO: Remove when https://github.com/elastic/kibana/issues/133107 is resolved const formSerializer = (formData: ConnectorFormSchema): ConnectorFormSchema => { + // Temp solution for inference - connector framework will be updated with ability for connector to add its own serializer/deserializer + if ( + formData.actionTypeId === '.inference' && + // explicit check to see if this field exists as it only exists in serverless + (formData.config?.providerConfig as InferenceConnectorProviderConfig) + ?.max_number_of_allocations !== undefined + ) { + const providerConfig = formData.config?.providerConfig as InferenceConnectorProviderConfig; + const { max_number_of_allocations: maxAllocations, ...restProviderConfig } = + providerConfig || {}; + + return { + ...formData, + config: { + ...formData.config, + providerConfig: { + ...restProviderConfig, + adaptive_allocations: { + enabled: true, + min_number_of_allocations: MIN_ALLOCATIONS, + ...(maxAllocations ? { max_number_of_allocations: maxAllocations } : {}), + }, + // Temporary solution until the endpoint is updated to no longer require it and to set its own default for this value + num_threads: DEFAULT_NUM_THREADS, + }, + }, + }; + } + if ( formData.actionTypeId !== '.webhook' && formData.actionTypeId !== '.cases-webhook' && diff --git a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/action_connector_form/create_connector_flyout/index.tsx b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/action_connector_form/create_connector_flyout/index.tsx index 7987dd5476c0a..cb85d5aac564a 100644 --- a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/action_connector_form/create_connector_flyout/index.tsx +++ b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/action_connector_form/create_connector_flyout/index.tsx @@ -44,6 +44,7 @@ export interface CreateConnectorFlyoutProps { featureId?: string; onConnectorCreated?: (connector: ActionConnector) => void; onTestConnector?: (connector: ActionConnector) => void; + isServerless?: boolean; } const CreateConnectorFlyoutComponent: React.FC = ({ @@ -156,7 +157,6 @@ const CreateConnectorFlyoutComponent: React.FC = ({ * At this point the form is valid * and there are no pre submit error messages. */ - const { actionTypeId, name, config, secrets } = data; const validConnector = { actionTypeId, diff --git a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx index ecbf87ed655ac..cf7aedaa02a44 100644 --- a/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx +++ b/x-pack/platform/plugins/shared/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx @@ -43,6 +43,7 @@ export interface EditConnectorFlyoutProps { onClose: () => void; tab?: EditConnectorTabs; onConnectorUpdated?: (connector: ActionConnector) => void; + isServerless?: boolean; } const getConnectorWithoutSecrets = ( @@ -177,7 +178,6 @@ const EditConnectorFlyoutComponent: React.FC = ({ * At this point the form is valid * and there are no pre submit error messages. */ - const { name, config, secrets } = data; const validConnector = { id: connector.id, diff --git a/x-pack/platform/plugins/shared/triggers_actions_ui/public/common/get_add_connector_flyout.tsx b/x-pack/platform/plugins/shared/triggers_actions_ui/public/common/get_add_connector_flyout.tsx index 52caaf9d1c767..d42fcc627fa58 100644 --- a/x-pack/platform/plugins/shared/triggers_actions_ui/public/common/get_add_connector_flyout.tsx +++ b/x-pack/platform/plugins/shared/triggers_actions_ui/public/common/get_add_connector_flyout.tsx @@ -19,7 +19,9 @@ export const getAddConnectorFlyoutLazy = ( ) => { return ( - + diff --git a/x-pack/platform/plugins/shared/triggers_actions_ui/public/common/get_edit_connector_flyout.tsx b/x-pack/platform/plugins/shared/triggers_actions_ui/public/common/get_edit_connector_flyout.tsx index c1de095e5338a..0ba2c93ef4b1d 100644 --- a/x-pack/platform/plugins/shared/triggers_actions_ui/public/common/get_edit_connector_flyout.tsx +++ b/x-pack/platform/plugins/shared/triggers_actions_ui/public/common/get_edit_connector_flyout.tsx @@ -18,7 +18,9 @@ export const getEditConnectorFlyoutLazy = ( props: EditConnectorFlyoutProps & { connectorServices: ConnectorServices } ) => { return ( - + diff --git a/x-pack/platform/plugins/shared/triggers_actions_ui/public/plugin.ts b/x-pack/platform/plugins/shared/triggers_actions_ui/public/plugin.ts index 501b584afcd0e..6d2c99e445807 100644 --- a/x-pack/platform/plugins/shared/triggers_actions_ui/public/plugin.ts +++ b/x-pack/platform/plugins/shared/triggers_actions_ui/public/plugin.ts @@ -192,17 +192,20 @@ export class Plugin private config: TriggersActionsUiConfigType; private connectorServices?: ConnectorServices; readonly experimentalFeatures: ExperimentalFeatures; + private readonly isServerless: boolean; constructor(ctx: PluginInitializerContext) { this.actionTypeRegistry = new TypeRegistry(); this.ruleTypeRegistry = new TypeRegistry(); this.config = ctx.config.get(); this.experimentalFeatures = parseExperimentalConfigValue(this.config.enableExperimental || []); + this.isServerless = ctx.env.packageInfo.buildFlavor === 'serverless'; } public setup(core: CoreSetup, plugins: PluginsSetup): TriggersAndActionsUIPublicPluginSetup { const actionTypeRegistry = this.actionTypeRegistry; const ruleTypeRegistry = this.ruleTypeRegistry; + const isServerless = this.isServerless; this.connectorServices = { validateEmailAddresses: plugins.actions.validateEmailAddresses, enabledEmailServices: plugins.actions.enabledEmailServices, @@ -367,6 +370,7 @@ export class Plugin ruleTypeRegistry, share: pluginsStart.share, kibanaFeatures, + isServerless, }); }, }); @@ -413,7 +417,7 @@ export class Plugin kibanaFeatures, licensing: pluginsStart.licensing, expressions: pluginsStart.expressions, - isServerless: !!pluginsStart.serverless, + isServerless, fieldFormats: pluginsStart.fieldFormats, lens: pluginsStart.lens, fieldsMetadata: pluginsStart.fieldsMetadata, @@ -482,6 +486,7 @@ export class Plugin ...props, actionTypeRegistry: this.actionTypeRegistry, connectorServices: this.connectorServices!, + isServerless: !!plugins.serverless, }); }, getEditConnectorFlyout: (props: Omit) => { @@ -489,6 +494,7 @@ export class Plugin ...props, actionTypeRegistry: this.actionTypeRegistry, connectorServices: this.connectorServices!, + isServerless: !!plugins.serverless, }); }, getAlertsSearchBar: (props: AlertsSearchBarProps) => { diff --git a/x-pack/solutions/search/plugins/search_inference_endpoints/public/components/add_inference_endpoints/add_inference_flyout_wrapper.tsx b/x-pack/solutions/search/plugins/search_inference_endpoints/public/components/add_inference_endpoints/add_inference_flyout_wrapper.tsx index d9aa30e042c2e..be618c2765af3 100644 --- a/x-pack/solutions/search/plugins/search_inference_endpoints/public/components/add_inference_endpoints/add_inference_flyout_wrapper.tsx +++ b/x-pack/solutions/search/plugins/search_inference_endpoints/public/components/add_inference_endpoints/add_inference_flyout_wrapper.tsx @@ -23,8 +23,10 @@ export const AddInferenceFlyoutWrapper: React.FC services: { http, notifications: { toasts }, + serverless, }, } = useKibana(); + const onSubmitSuccess = useCallback(() => { reloadFn(); }, [reloadFn]); @@ -33,6 +35,7 @@ export const AddInferenceFlyoutWrapper: React.FC diff --git a/x-pack/solutions/search/plugins/search_inference_endpoints/public/components/edit_inference_endpoints/edit_inference_flyout.tsx b/x-pack/solutions/search/plugins/search_inference_endpoints/public/components/edit_inference_endpoints/edit_inference_flyout.tsx index bdf879a7a65c4..2b96c18a9eb2b 100644 --- a/x-pack/solutions/search/plugins/search_inference_endpoints/public/components/edit_inference_endpoints/edit_inference_flyout.tsx +++ b/x-pack/solutions/search/plugins/search_inference_endpoints/public/components/edit_inference_endpoints/edit_inference_flyout.tsx @@ -25,6 +25,7 @@ export const EditInferenceFlyout: React.FC = ({ services: { http, notifications: { toasts }, + serverless, }, } = useKibana(); const { refetch } = useQueryInferenceEndpoints(); @@ -49,6 +50,7 @@ export const EditInferenceFlyout: React.FC = ({ http={http} toasts={toasts} isEdit={true} + enforceAdaptiveAllocations={!!serverless} onSubmitSuccess={onEditSuccess} inferenceEndpoint={inferenceEndpoint} />