Skip to content

Commit

Permalink
[AI Assistant] Add setting for preferred type (#179233)
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
dgieselaar and kibanamachine authored Apr 8, 2024
1 parent 826f7cb commit 52c65b7
Show file tree
Hide file tree
Showing 22 changed files with 308 additions and 41 deletions.
3 changes: 3 additions & 0 deletions config/serverless.oblt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
@@ -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',
}
Original file line number Diff line number Diff line change
@@ -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';
9 changes: 6 additions & 3 deletions src/plugins/ai_assistant_management/selection/kibana.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
],
},
}
23 changes: 16 additions & 7 deletions src/plugins/ai_assistant_management/selection/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Original file line number Diff line number Diff line change
Expand Up @@ -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<StartDependencies, AiAssistantManagementSelectionPluginStart>;
core: CoreSetup<StartDependencies, AIAssistantManagementSelectionPluginPublicStart>;
mountParams: ManagementAppMountParams;
}

Expand Down
46 changes: 31 additions & 15 deletions src/plugins/ai_assistant_management/selection/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<AIAssistantType>;
}

export interface SetupDependencies {
management: ManagementSetup;
Expand All @@ -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<StartDependencies, AiAssistantManagementSelectionPluginStart>,
core: CoreSetup<StartDependencies, AIAssistantManagementSelectionPluginPublicStart>,
{ home, management, serverless }: SetupDependencies
): AiAssistantManagementSelectionPluginSetup {
if (serverless) return {};
): AIAssistantManagementSelectionPluginPublicSetup {
if (serverless) {
return {};
}

if (home) {
home.featureCatalogue.register({
Expand Down Expand Up @@ -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(),
};
}
}
13 changes: 13 additions & 0 deletions src/plugins/ai_assistant_management/selection/public/types.ts
Original file line number Diff line number Diff line change
@@ -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;
}
32 changes: 32 additions & 0 deletions src/plugins/ai_assistant_management/selection/server/config.ts
Original file line number Diff line number Diff line change
@@ -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<typeof configSchema>;

export const config: PluginConfigDescriptor<AIAssistantManagementSelectionConfig> = {
schema: configSchema,
exposeToBrowser: {
preferredAIAssistantType: true,
},
};
16 changes: 16 additions & 0 deletions src/plugins/ai_assistant_management/selection/server/index.ts
Original file line number Diff line number Diff line change
@@ -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);
};
90 changes: 90 additions & 0 deletions src/plugins/ai_assistant_management/selection/server/plugin.ts
Original file line number Diff line number Diff line change
@@ -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:
'<em>[technical preview]</em> 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() {}
}
18 changes: 18 additions & 0 deletions src/plugins/ai_assistant_management/selection/server/types.ts
Original file line number Diff line number Diff line change
@@ -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 {}
4 changes: 3 additions & 1 deletion src/plugins/ai_assistant_management/selection/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -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/**/*"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -655,4 +655,8 @@ export const stackManagementSchema: MakeSchemaFrom<UsageStats> = {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'aiAssistant:preferredAIAssistantType': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -172,4 +172,5 @@ export interface UsageStats {
'data_views:fields_excluded_data_tiers': string;
'observability:apmEnableTransactionProfiling': boolean;
'devTools:enablePersistentConsole': boolean;
'aiAssistant:preferredAIAssistantType': string;
}
6 changes: 6 additions & 0 deletions src/plugins/telemetry/schema/oss_plugins.json
Original file line number Diff line number Diff line change
Expand Up @@ -10427,6 +10427,12 @@
"_meta": {
"description": "Non-default value of setting."
}
},
"aiAssistant:preferredAIAssistantType": {
"type": "keyword",
"_meta": {
"description": "Non-default value of setting."
}
}
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down
Loading

0 comments on commit 52c65b7

Please sign in to comment.