From 52c65b78fc41d999ebf94bf06cbf755eedd4459e Mon Sep 17 00:00:00 2001 From: Dario Gieselaar Date: Mon, 8 Apr 2024 20:26:23 +0200 Subject: [PATCH] [AI Assistant] Add setting for preferred type (#179233) Adds a setting in the `aiAssistantManagementSelection` plugin that allows users to set the preferred Assistant type. The allowed values are: - `default`: the status quo, which is: show the Observability AI Assistant in Observability apps, the Security AI Assistant in Security solution apps, and none in the other apps. - `never`: Never show any AI Assistant. - `observability`: Show the Observability AI Assistant everywhere, except for Security solution apps. - `security`: ~Show the Security AI Assistant everywhere, except for Observability apps.~ it is up to the solutions to respect the setting. See [x-pack/plugins/observability_solution/observability_ai_assistant_app/public/hooks/is_nav_control_visible.tsx](https://github.com/elastic/kibana/pull/179233/files#diff-753a9aae298da45c5bd96bc2cacaa437ac53e165069ad6323973dd3c2879d4ae) for an example. It should also be set in the specific Serverless config: [config/serverless.oblt.yml](https://github.com/elastic/kibana/pull/179233/files#diff-358680d2b72268283dca4f3efb976cd924b7b5bce822e07c8871d061b4bb339e). Update: this is now labeled as an Observability-only setting. ![CleanShot 2024-04-05 at 09 28 32@2x](https://github.com/elastic/kibana/assets/352732/fa6edeea-eaca-4ec3-86ec-f00effa95f93) --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- config/serverless.oblt.yml | 3 + .../selection/common/ai_assistant_type.ts | 13 +++ .../selection/common/ui_setting_keys.ts | 9 ++ .../selection/kibana.jsonc | 9 +- .../selection/public/index.ts | 23 +++-- .../management_section/mount_section.tsx | 8 +- .../selection/public/plugin.ts | 46 ++++++---- .../selection/public/types.ts | 13 +++ .../selection/server/config.ts | 32 +++++++ .../selection/server/index.ts | 16 ++++ .../selection/server/plugin.ts | 90 +++++++++++++++++++ .../selection/server/types.ts | 18 ++++ .../selection/tsconfig.json | 4 +- .../server/collectors/management/schema.ts | 4 + .../server/collectors/management/types.ts | 1 + src/plugins/telemetry/schema/oss_plugins.json | 6 ++ .../test_suites/core_plugins/rendering.ts | 1 + .../kibana.jsonc | 1 + .../public/components/nav_control/index.tsx | 4 +- .../public/hooks/is_nav_control_visible.tsx | 41 +++++++-- .../public/types.ts | 6 ++ .../tsconfig.json | 1 + 22 files changed, 308 insertions(+), 41 deletions(-) create mode 100644 src/plugins/ai_assistant_management/selection/common/ai_assistant_type.ts create mode 100644 src/plugins/ai_assistant_management/selection/common/ui_setting_keys.ts create mode 100644 src/plugins/ai_assistant_management/selection/public/types.ts create mode 100644 src/plugins/ai_assistant_management/selection/server/config.ts create mode 100644 src/plugins/ai_assistant_management/selection/server/index.ts create mode 100644 src/plugins/ai_assistant_management/selection/server/plugin.ts create mode 100644 src/plugins/ai_assistant_management/selection/server/types.ts diff --git a/config/serverless.oblt.yml b/config/serverless.oblt.yml index a2e7d8d4eeb97..35d63ac5a49ef 100644 --- a/config/serverless.oblt.yml +++ b/config/serverless.oblt.yml @@ -81,6 +81,9 @@ xpack.apm.featureFlags.migrationToFleetAvailable: false xpack.apm.featureFlags.sourcemapApiAvailable: false xpack.apm.featureFlags.storageExplorerAvailable: false +## Set the AI Assistant type +aiAssistantManagementSelection.preferredAIAssistantType: "observability" + # Specify in telemetry the project type telemetry.labels.serverless: observability diff --git a/src/plugins/ai_assistant_management/selection/common/ai_assistant_type.ts b/src/plugins/ai_assistant_management/selection/common/ai_assistant_type.ts new file mode 100644 index 0000000000000..55c44b2ca76fd --- /dev/null +++ b/src/plugins/ai_assistant_management/selection/common/ai_assistant_type.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export enum AIAssistantType { + Observability = 'observability', + Default = 'default', + Never = 'never', +} diff --git a/src/plugins/ai_assistant_management/selection/common/ui_setting_keys.ts b/src/plugins/ai_assistant_management/selection/common/ui_setting_keys.ts new file mode 100644 index 0000000000000..99a1a5859c06c --- /dev/null +++ b/src/plugins/ai_assistant_management/selection/common/ui_setting_keys.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export const PREFERRED_AI_ASSISTANT_TYPE_SETTING_KEY = 'aiAssistant:preferredAIAssistantType'; diff --git a/src/plugins/ai_assistant_management/selection/kibana.jsonc b/src/plugins/ai_assistant_management/selection/kibana.jsonc index 7db0b04b877d6..369cb0c626f04 100644 --- a/src/plugins/ai_assistant_management/selection/kibana.jsonc +++ b/src/plugins/ai_assistant_management/selection/kibana.jsonc @@ -4,10 +4,13 @@ "owner": "@elastic/obs-knowledge-team", "plugin": { "id": "aiAssistantManagementSelection", - "server": false, + "server": true, "browser": true, "requiredPlugins": ["management"], "optionalPlugins": ["home", "serverless"], - "requiredBundles": ["kibanaReact"] - } + "requiredBundles": ["kibanaReact"], + "configPath": [ + "aiAssistantManagementSelection" + ], + }, } diff --git a/src/plugins/ai_assistant_management/selection/public/index.ts b/src/plugins/ai_assistant_management/selection/public/index.ts index 54d13961ca017..46a20ceb7ffc8 100644 --- a/src/plugins/ai_assistant_management/selection/public/index.ts +++ b/src/plugins/ai_assistant_management/selection/public/index.ts @@ -6,13 +6,22 @@ * Side Public License, v 1. */ -import { AiAssistantManagementPlugin } from './plugin'; +import type { PluginInitializer } from '@kbn/core/public'; +import { AIAssistantManagementPlugin } from './plugin'; -export type { - AiAssistantManagementSelectionPluginSetup, - AiAssistantManagementSelectionPluginStart, +import type { + AIAssistantManagementSelectionPluginPublicSetup, + AIAssistantManagementSelectionPluginPublicStart, } from './plugin'; -export function plugin() { - return new AiAssistantManagementPlugin(); -} +export { AIAssistantType } from '../common/ai_assistant_type'; + +export type { + AIAssistantManagementSelectionPluginPublicSetup, + AIAssistantManagementSelectionPluginPublicStart, +}; + +export const plugin: PluginInitializer< + AIAssistantManagementSelectionPluginPublicSetup, + AIAssistantManagementSelectionPluginPublicStart +> = () => new AIAssistantManagementPlugin(); diff --git a/src/plugins/ai_assistant_management/selection/public/management_section/mount_section.tsx b/src/plugins/ai_assistant_management/selection/public/management_section/mount_section.tsx index 9a957d862bd71..a1bb4e19f2265 100644 --- a/src/plugins/ai_assistant_management/selection/public/management_section/mount_section.tsx +++ b/src/plugins/ai_assistant_management/selection/public/management_section/mount_section.tsx @@ -11,16 +11,16 @@ import ReactDOM from 'react-dom'; import { RouteRenderer, RouterProvider } from '@kbn/typed-react-router-config'; import { I18nProvider } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; -import { CoreSetup } from '@kbn/core/public'; +import type { CoreSetup } from '@kbn/core/public'; import { wrapWithTheme } from '@kbn/kibana-react-plugin/public'; -import { ManagementAppMountParams } from '@kbn/management-plugin/public'; -import { StartDependencies, AiAssistantManagementSelectionPluginStart } from '../plugin'; +import type { ManagementAppMountParams } from '@kbn/management-plugin/public'; +import type { StartDependencies, AIAssistantManagementSelectionPluginPublicStart } from '../plugin'; import { aIAssistantManagementSelectionRouter } from '../routes/config'; import { RedirectToHomeIfUnauthorized } from '../routes/components/redirect_to_home_if_unauthorized'; import { AppContextProvider } from '../app_context'; interface MountParams { - core: CoreSetup; + core: CoreSetup; mountParams: ManagementAppMountParams; } diff --git a/src/plugins/ai_assistant_management/selection/public/plugin.ts b/src/plugins/ai_assistant_management/selection/public/plugin.ts index 4658c9ec8795d..612f03b94423b 100644 --- a/src/plugins/ai_assistant_management/selection/public/plugin.ts +++ b/src/plugins/ai_assistant_management/selection/public/plugin.ts @@ -7,16 +7,20 @@ */ import { i18n } from '@kbn/i18n'; -import { CoreSetup, Plugin } from '@kbn/core/public'; -import { ManagementSetup } from '@kbn/management-plugin/public'; -import { HomePublicPluginSetup } from '@kbn/home-plugin/public'; -import { ServerlessPluginSetup } from '@kbn/serverless/public'; +import { type CoreSetup, Plugin, type CoreStart } from '@kbn/core/public'; +import type { ManagementSetup } from '@kbn/management-plugin/public'; +import type { HomePublicPluginSetup } from '@kbn/home-plugin/public'; +import type { ServerlessPluginSetup } from '@kbn/serverless/public'; +import { BehaviorSubject, Observable } from 'rxjs'; +import { AIAssistantType } from '../common/ai_assistant_type'; +import { PREFERRED_AI_ASSISTANT_TYPE_SETTING_KEY } from '../common/ui_setting_keys'; // eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface AiAssistantManagementSelectionPluginSetup {} +export interface AIAssistantManagementSelectionPluginPublicSetup {} -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface AiAssistantManagementSelectionPluginStart {} +export interface AIAssistantManagementSelectionPluginPublicStart { + aiAssistantType$: Observable; +} export interface SetupDependencies { management: ManagementSetup; @@ -27,20 +31,24 @@ export interface SetupDependencies { // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface StartDependencies {} -export class AiAssistantManagementPlugin +export class AIAssistantManagementPlugin implements Plugin< - AiAssistantManagementSelectionPluginSetup, - AiAssistantManagementSelectionPluginStart, + AIAssistantManagementSelectionPluginPublicSetup, + AIAssistantManagementSelectionPluginPublicStart, SetupDependencies, StartDependencies > { + constructor() {} + public setup( - core: CoreSetup, + core: CoreSetup, { home, management, serverless }: SetupDependencies - ): AiAssistantManagementSelectionPluginSetup { - if (serverless) return {}; + ): AIAssistantManagementSelectionPluginPublicSetup { + if (serverless) { + return {}; + } if (home) { home.featureCatalogue.register({ @@ -77,7 +85,15 @@ export class AiAssistantManagementPlugin return {}; } - public start() { - return {}; + public start(coreStart: CoreStart) { + const preferredAIAssistantType: AIAssistantType = coreStart.uiSettings.get( + PREFERRED_AI_ASSISTANT_TYPE_SETTING_KEY + ); + + const aiAssistantType$ = new BehaviorSubject(preferredAIAssistantType); + + return { + aiAssistantType$: aiAssistantType$.asObservable(), + }; } } diff --git a/src/plugins/ai_assistant_management/selection/public/types.ts b/src/plugins/ai_assistant_management/selection/public/types.ts new file mode 100644 index 0000000000000..94f7b5dde0bb8 --- /dev/null +++ b/src/plugins/ai_assistant_management/selection/public/types.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { AIAssistantType } from '../common/ai_assistant_type'; + +export interface ConfigSchema { + preferredAIAssistantType: AIAssistantType; +} diff --git a/src/plugins/ai_assistant_management/selection/server/config.ts b/src/plugins/ai_assistant_management/selection/server/config.ts new file mode 100644 index 0000000000000..d27815aa3ca96 --- /dev/null +++ b/src/plugins/ai_assistant_management/selection/server/config.ts @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { schema, TypeOf } from '@kbn/config-schema'; +import { PluginConfigDescriptor } from '@kbn/core-plugins-server'; +import { AIAssistantType } from '../common/ai_assistant_type'; + +const configSchema = schema.object({ + enabled: schema.boolean({ defaultValue: true }), + preferredAIAssistantType: schema.oneOf( + [ + schema.literal(AIAssistantType.Default), + schema.literal(AIAssistantType.Never), + schema.literal(AIAssistantType.Observability), + ], + { defaultValue: AIAssistantType.Default } + ), +}); + +export type AIAssistantManagementSelectionConfig = TypeOf; + +export const config: PluginConfigDescriptor = { + schema: configSchema, + exposeToBrowser: { + preferredAIAssistantType: true, + }, +}; diff --git a/src/plugins/ai_assistant_management/selection/server/index.ts b/src/plugins/ai_assistant_management/selection/server/index.ts new file mode 100644 index 0000000000000..3dbcc15473731 --- /dev/null +++ b/src/plugins/ai_assistant_management/selection/server/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { PluginInitializerContext } from '@kbn/core/server'; + +export { config } from './config'; + +export const plugin = async (initContext: PluginInitializerContext) => { + const { AIAssistantManagementSelectionPlugin } = await import('./plugin'); + return new AIAssistantManagementSelectionPlugin(initContext); +}; diff --git a/src/plugins/ai_assistant_management/selection/server/plugin.ts b/src/plugins/ai_assistant_management/selection/server/plugin.ts new file mode 100644 index 0000000000000..c81b40f1ff9b2 --- /dev/null +++ b/src/plugins/ai_assistant_management/selection/server/plugin.ts @@ -0,0 +1,90 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import { i18n } from '@kbn/i18n'; + +import { + PluginInitializerContext, + CoreSetup, + CoreStart, + Plugin, + DEFAULT_APP_CATEGORIES, +} from '@kbn/core/server'; +import { schema } from '@kbn/config-schema'; +import type { AIAssistantManagementSelectionConfig } from './config'; +import type { + AIAssistantManagementSelectionPluginServerSetup, + AIAssistantManagementSelectionPluginServerStart, +} from './types'; +import { AIAssistantType } from '../common/ai_assistant_type'; +import { PREFERRED_AI_ASSISTANT_TYPE_SETTING_KEY } from '../common/ui_setting_keys'; + +export class AIAssistantManagementSelectionPlugin + implements + Plugin< + AIAssistantManagementSelectionPluginServerSetup, + AIAssistantManagementSelectionPluginServerStart + > +{ + private readonly config: AIAssistantManagementSelectionConfig; + + constructor(initializerContext: PluginInitializerContext) { + this.config = initializerContext.config.get(); + } + + public setup(core: CoreSetup) { + core.uiSettings.register({ + [PREFERRED_AI_ASSISTANT_TYPE_SETTING_KEY]: { + name: i18n.translate('aiAssistantManagementSelection.preferredAIAssistantTypeSettingName', { + defaultMessage: 'Observability AI Assistant scope', + }), + category: [DEFAULT_APP_CATEGORIES.observability.id], + value: this.config.preferredAIAssistantType, + description: i18n.translate( + 'aiAssistantManagementSelection.preferredAIAssistantTypeSettingDescription', + { + defaultMessage: + '[technical preview] Whether to show the Observability AI Assistant menu item in Observability, everywhere, or nowhere.', + } + ), + schema: schema.oneOf( + [ + schema.literal(AIAssistantType.Default), + schema.literal(AIAssistantType.Observability), + schema.literal(AIAssistantType.Never), + ], + { defaultValue: this.config.preferredAIAssistantType } + ), + options: [AIAssistantType.Default, AIAssistantType.Observability, AIAssistantType.Never], + type: 'select', + optionLabels: { + [AIAssistantType.Default]: i18n.translate( + 'aiAssistantManagementSelection.preferredAIAssistantTypeSettingValueDefault', + { defaultMessage: 'Observability only (default)' } + ), + [AIAssistantType.Observability]: i18n.translate( + 'aiAssistantManagementSelection.preferredAIAssistantTypeSettingValueObservability', + { defaultMessage: 'Everywhere' } + ), + [AIAssistantType.Never]: i18n.translate( + 'aiAssistantManagementSelection.preferredAIAssistantTypeSettingValueNever', + { defaultMessage: 'Nowhere' } + ), + }, + requiresPageReload: true, + }, + }); + + return {}; + } + + public start(core: CoreStart) { + return {}; + } + + public stop() {} +} diff --git a/src/plugins/ai_assistant_management/selection/server/types.ts b/src/plugins/ai_assistant_management/selection/server/types.ts new file mode 100644 index 0000000000000..c956023781d75 --- /dev/null +++ b/src/plugins/ai_assistant_management/selection/server/types.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface AIAssistantManagementSelectionPluginServerDependenciesStart {} + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface AIAssistantManagementSelectionPluginServerDependenciesSetup {} + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface AIAssistantManagementSelectionPluginServerStart {} +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface AIAssistantManagementSelectionPluginServerSetup {} diff --git a/src/plugins/ai_assistant_management/selection/tsconfig.json b/src/plugins/ai_assistant_management/selection/tsconfig.json index 2c287b2ee77de..e6658bdfc6efb 100644 --- a/src/plugins/ai_assistant_management/selection/tsconfig.json +++ b/src/plugins/ai_assistant_management/selection/tsconfig.json @@ -13,7 +13,9 @@ "@kbn/i18n-react", "@kbn/core-chrome-browser", "@kbn/typed-react-router-config", - "@kbn/serverless" + "@kbn/serverless", + "@kbn/config-schema", + "@kbn/core-plugins-server" ], "exclude": ["target/**/*"] } diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts index 97f6a21ce0931..ad4ef03237e4d 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts @@ -655,4 +655,8 @@ export const stackManagementSchema: MakeSchemaFrom = { type: 'boolean', _meta: { description: 'Non-default value of setting.' }, }, + 'aiAssistant:preferredAIAssistantType': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, }; diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/types.ts b/src/plugins/kibana_usage_collection/server/collectors/management/types.ts index c4463f4bad96f..80384cc22e03c 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/types.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/types.ts @@ -172,4 +172,5 @@ export interface UsageStats { 'data_views:fields_excluded_data_tiers': string; 'observability:apmEnableTransactionProfiling': boolean; 'devTools:enablePersistentConsole': boolean; + 'aiAssistant:preferredAIAssistantType': string; } diff --git a/src/plugins/telemetry/schema/oss_plugins.json b/src/plugins/telemetry/schema/oss_plugins.json index 99de63e50abe9..c727356a8f5ea 100644 --- a/src/plugins/telemetry/schema/oss_plugins.json +++ b/src/plugins/telemetry/schema/oss_plugins.json @@ -10427,6 +10427,12 @@ "_meta": { "description": "Non-default value of setting." } + }, + "aiAssistant:preferredAIAssistantType": { + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } } } }, diff --git a/test/plugin_functional/test_suites/core_plugins/rendering.ts b/test/plugin_functional/test_suites/core_plugins/rendering.ts index ca06f8a6a731d..d6277fbaf394c 100644 --- a/test/plugin_functional/test_suites/core_plugins/rendering.ts +++ b/test/plugin_functional/test_suites/core_plugins/rendering.ts @@ -340,6 +340,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) { 'xpack.observability_onboarding.ui.enabled (boolean)', 'xpack.observabilityLogsExplorer.navigation.showAppLink (any)', // conditional, is actually a boolean 'share.new_version.enabled (boolean)', + 'aiAssistantManagementSelection.preferredAIAssistantType (alternatives)', /** * Rule form V2 feature flags */ diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant_app/kibana.jsonc b/x-pack/plugins/observability_solution/observability_ai_assistant_app/kibana.jsonc index 1a172d51a514b..713132ab2f7a7 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant_app/kibana.jsonc +++ b/x-pack/plugins/observability_solution/observability_ai_assistant_app/kibana.jsonc @@ -8,6 +8,7 @@ "browser": true, "configPath": ["xpack", "observabilityAIAssistantApp"], "requiredPlugins": [ + "aiAssistantManagementSelection", "observabilityAIAssistant", "observabilityShared", "actions", diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant_app/public/components/nav_control/index.tsx b/x-pack/plugins/observability_solution/observability_ai_assistant_app/public/components/nav_control/index.tsx index b9f44142e946b..cf8a5cd9dffe7 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant_app/public/components/nav_control/index.tsx +++ b/x-pack/plugins/observability_solution/observability_ai_assistant_app/public/components/nav_control/index.tsx @@ -6,7 +6,7 @@ */ import React, { useEffect, useRef, useState } from 'react'; import { AssistantAvatar, useAbortableAsync } from '@kbn/observability-ai-assistant-plugin/public'; -import { EuiButton } from '@elastic/eui'; +import { EuiButton, EuiLoadingSpinner } from '@elastic/eui'; import { css } from '@emotion/react'; import { v4 } from 'uuid'; import useObservable from 'react-use/lib/useObservable'; @@ -114,7 +114,7 @@ export function NavControl({}: {}) { fullWidth={false} minWidth={0} > - + {chatService.loading ? : } {chatService.value ? ( diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant_app/public/hooks/is_nav_control_visible.tsx b/x-pack/plugins/observability_solution/observability_ai_assistant_app/public/hooks/is_nav_control_visible.tsx index 1ceed342f37ae..c8386991eebbf 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant_app/public/hooks/is_nav_control_visible.tsx +++ b/x-pack/plugins/observability_solution/observability_ai_assistant_app/public/hooks/is_nav_control_visible.tsx @@ -7,31 +7,54 @@ import { useEffect, useState } from 'react'; import { combineLatest } from 'rxjs'; -import { DEFAULT_APP_CATEGORIES } from '@kbn/core/public'; +import { DEFAULT_APP_CATEGORIES, type PublicAppInfo } from '@kbn/core/public'; +import { AIAssistantType } from '@kbn/ai-assistant-management-plugin/public'; import { useKibana } from './use_kibana'; +function getVisibility( + appId: string | undefined, + applications: ReadonlyMap, + preferredAssistantType: AIAssistantType +) { + if (preferredAssistantType === AIAssistantType.Never) { + return false; + } + + const categoryId = + (appId && applications.get(appId)?.category?.id) || DEFAULT_APP_CATEGORIES.kibana.id; + + if (preferredAssistantType === AIAssistantType.Observability) { + return categoryId !== DEFAULT_APP_CATEGORIES.security.id; + } + + return categoryId === DEFAULT_APP_CATEGORIES.observability.id; +} + export function useIsNavControlVisible() { const [isVisible, setIsVisible] = useState(false); const { services: { application: { currentAppId$, applications$ }, + plugins: { + start: { aiAssistantManagementSelection }, + }, }, } = useKibana(); useEffect(() => { - const appSubscription = combineLatest([currentAppId$, applications$]).subscribe({ - next: ([appId, applications]) => { - const isObservabilityApp = - appId && - applications.get(appId)?.category?.id === DEFAULT_APP_CATEGORIES.observability.id; - - setIsVisible(!!isObservabilityApp); + const appSubscription = combineLatest([ + currentAppId$, + applications$, + aiAssistantManagementSelection.aiAssistantType$, + ]).subscribe({ + next: ([appId, applications, preferredAssistantType]) => { + setIsVisible(getVisibility(appId, applications, preferredAssistantType)); }, }); return appSubscription.unsubscribe; - }, [currentAppId$, applications$]); + }, [currentAppId$, applications$, aiAssistantManagementSelection.aiAssistantType$]); return { isVisible, diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant_app/public/types.ts b/x-pack/plugins/observability_solution/observability_ai_assistant_app/public/types.ts index 2876ddaf3332d..d6235da273839 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant_app/public/types.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant_app/public/types.ts @@ -28,6 +28,10 @@ import type { TriggersAndActionsUIPublicPluginStart, } from '@kbn/triggers-actions-ui-plugin/public'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; +import type { + AIAssistantManagementSelectionPluginPublicStart, + AIAssistantManagementSelectionPluginPublicSetup, +} from '@kbn/ai-assistant-management-plugin/public'; // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface ObservabilityAIAssistantAppPublicStart {} @@ -46,6 +50,7 @@ export interface ObservabilityAIAssistantAppPluginStartDependencies { ml: MlPluginStart; triggersActionsUi: TriggersAndActionsUIPublicPluginStart; data: DataPublicPluginStart; + aiAssistantManagementSelection: AIAssistantManagementSelectionPluginPublicStart; } export interface ObservabilityAIAssistantAppPluginSetupDependencies { @@ -59,4 +64,5 @@ export interface ObservabilityAIAssistantAppPluginSetupDependencies { observabilityShared: ObservabilitySharedPluginSetup; ml: MlPluginSetup; triggersActionsUi: TriggersAndActionsUIPublicPluginSetup; + aiAssistantManagementSelection: AIAssistantManagementSelectionPluginPublicSetup; } diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant_app/tsconfig.json b/x-pack/plugins/observability_solution/observability_ai_assistant_app/tsconfig.json index 75e260a4c05de..83ea29b55734e 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant_app/tsconfig.json +++ b/x-pack/plugins/observability_solution/observability_ai_assistant_app/tsconfig.json @@ -50,6 +50,7 @@ "@kbn/shared-ux-link-redirect-app", "@kbn/shared-ux-utility", "@kbn/data-plugin", + "@kbn/ai-assistant-management-plugin", "@kbn/deeplinks-observability" ], "exclude": ["target/**/*"]