[9.0] SKA: Relocate ai assistant management (#218129) (#218555)

# Backport

This will backport the following commits from `main` to `9.0`:
- [SKA: Relocate ai assistant management
(#218129)](https://github.com/elastic/kibana/pull/218129)

<!--- Backport version: 9.6.6 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sorenlouv/backport)

<!--BACKPORT [{"author":{"name":"Gerard
Soldevila","email":"gerard.soldevila@elastic.co"},"sourceCommit":{"committedDate":"2025-04-17T11:55:02Z","message":"SKA:
Relocate ai assistant management (#218129)\n\n##
Summary\n\nPre-requisite for
https://github.com/elastic/kibana/pull/216088, as the\n`AI Assistant
Management` configuration settings should be available for\nSearch
too.\n\n---------\n\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>","sha":"cf94c2fe0f572e52edf379b91a61128a33912c17","branchLabelMapping":{"^v9.1.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Team:Core","release_note:skip","backport:prev-minor","v9.1.0"],"title":"SKA:
Relocate ai assistant
management","number":218129,"url":"https://github.com/elastic/kibana/pull/218129","mergeCommit":{"message":"SKA:
Relocate ai assistant management (#218129)\n\n##
Summary\n\nPre-requisite for
https://github.com/elastic/kibana/pull/216088, as the\n`AI Assistant
Management` configuration settings should be available for\nSearch
too.\n\n---------\n\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>","sha":"cf94c2fe0f572e52edf379b91a61128a33912c17"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/218129","number":218129,"mergeCommit":{"message":"SKA:
Relocate ai assistant management (#218129)\n\n##
Summary\n\nPre-requisite for
https://github.com/elastic/kibana/pull/216088, as the\n`AI Assistant
Management` configuration settings should be available for\nSearch
too.\n\n---------\n\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>","sha":"cf94c2fe0f572e52edf379b91a61128a33912c17"}}]}]
BACKPORT-->

Co-authored-by: Gerard Soldevila <gerard.soldevila@elastic.co>
Co-authored-by: Viduni Wickramarachchi <viduni.wickramarachchi@elastic.co>
This commit is contained in:
Kibana Machine 2025-04-18 16:09:54 +02:00 committed by GitHub
parent 3fdbb83968
commit 02dc9ab14e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
57 changed files with 269 additions and 18 deletions

2
.github/CODEOWNERS vendored
View file

@ -859,6 +859,7 @@ x-pack/platform/plugins/private/license_api_guard @elastic/kibana-management
x-pack/platform/plugins/private/logstash @elastic/logstash
x-pack/platform/plugins/private/monitoring @elastic/stack-monitoring
x-pack/platform/plugins/private/monitoring_collection @elastic/stack-monitoring
x-pack/platform/plugins/private/observability_ai_assistant_management @elastic/obs-ai-assistant
x-pack/platform/plugins/private/painless_lab @elastic/kibana-management
x-pack/platform/plugins/private/remote_clusters @elastic/kibana-management
x-pack/platform/plugins/private/reporting @elastic/response-ops
@ -944,7 +945,6 @@ x-pack/solutions/observability/plugins/logs_explorer @elastic/obs-ux-logs-team
x-pack/solutions/observability/plugins/metrics_data_access @elastic/obs-ux-infra_services-team
x-pack/solutions/observability/plugins/observability @elastic/obs-ux-management-team
x-pack/solutions/observability/plugins/observability_ai_assistant_app @elastic/obs-ai-assistant
x-pack/solutions/observability/plugins/observability_ai_assistant_management @elastic/obs-ai-assistant
x-pack/solutions/observability/plugins/observability_logs_explorer @elastic/obs-ux-logs-team
x-pack/solutions/observability/plugins/observability_onboarding @elastic/obs-ux-logs-team
x-pack/solutions/observability/plugins/observability_shared @elastic/observability-ui

View file

@ -183,7 +183,7 @@ mapped_pages:
| [observability](https://github.com/elastic/kibana/blob/main/x-pack/solutions/observability/plugins/observability/README.md) | This plugin provides shared components and services for use across observability solutions, as well as the observability landing page UI. |
| [observabilityAIAssistant](https://github.com/elastic/kibana/blob/main/x-pack/platform/plugins/shared/observability_ai_assistant/README.md) | This document gives an overview of the features of the Observability AI Assistant at the time of writing, and how to use them. At a high level, the Observability AI Assistant offers contextual insights, and a chat functionality that we enrich with function calling, allowing the LLM to hook into the user's data. We also allow the LLM to store things it considers new information as embeddings into Elasticsearch, and query this knowledge base when it decides it needs more information, using ELSER. |
| [observabilityAIAssistantApp](https://github.com/elastic/kibana/blob/main/x-pack/solutions/observability/plugins/observability_ai_assistant_app/README.md) | This app registers defaults functions. It exists as a separate plugin to avoid cyclical dependencies. |
| [observabilityAiAssistantManagement](https://github.com/elastic/kibana/blob/main/x-pack/solutions/observability/plugins/observability_ai_assistant_management/README.md) | The observabilityAiAssistantManagement plugin manages the Ai Assistant for Observability and Search management section. |
| [observabilityAiAssistantManagement](https://github.com/elastic/kibana/blob/main/x-pack/platform/plugins/private/observability_ai_assistant_management/README.md) | The observabilityAiAssistantManagement plugin manages the Ai Assistant for Observability and Search management section. |
| [observabilityLogsExplorer](https://github.com/elastic/kibana/blob/main/x-pack/solutions/observability/plugins/observability_logs_explorer/README.md) | This plugin provides an app based on the LogsExplorer component from the logs_explorer plugin, but adds observability-specific affordances. |
| [observabilityOnboarding](https://github.com/elastic/kibana/blob/main/x-pack/solutions/observability/plugins/observability_onboarding/README.md) | This plugin provides an onboarding framework for observability solutions: Logs and APM. |
| [observabilityShared](https://github.com/elastic/kibana/blob/main/x-pack/solutions/observability/plugins/observability_shared/README.md) | A plugin that contains components and utilities shared by all Observability plugins. |

View file

@ -704,7 +704,7 @@
"@kbn/object-versioning": "link:src/platform/packages/shared/kbn-object-versioning",
"@kbn/object-versioning-utils": "link:src/platform/packages/shared/kbn-object-versioning-utils",
"@kbn/observability-ai-assistant-app-plugin": "link:x-pack/solutions/observability/plugins/observability_ai_assistant_app",
"@kbn/observability-ai-assistant-management-plugin": "link:x-pack/solutions/observability/plugins/observability_ai_assistant_management",
"@kbn/observability-ai-assistant-management-plugin": "link:x-pack/platform/plugins/private/observability_ai_assistant_management",
"@kbn/observability-ai-assistant-plugin": "link:x-pack/platform/plugins/shared/observability_ai_assistant",
"@kbn/observability-ai-common": "link:x-pack/solutions/observability/packages/observability-ai/observability-ai-common",
"@kbn/observability-ai-server": "link:x-pack/solutions/observability/packages/observability-ai/observability-ai-server",

View file

@ -1338,8 +1338,8 @@
"@kbn/object-versioning-utils/*": ["src/platform/packages/shared/kbn-object-versioning-utils/*"],
"@kbn/observability-ai-assistant-app-plugin": ["x-pack/solutions/observability/plugins/observability_ai_assistant_app"],
"@kbn/observability-ai-assistant-app-plugin/*": ["x-pack/solutions/observability/plugins/observability_ai_assistant_app/*"],
"@kbn/observability-ai-assistant-management-plugin": ["x-pack/solutions/observability/plugins/observability_ai_assistant_management"],
"@kbn/observability-ai-assistant-management-plugin/*": ["x-pack/solutions/observability/plugins/observability_ai_assistant_management/*"],
"@kbn/observability-ai-assistant-management-plugin": ["x-pack/platform/plugins/private/observability_ai_assistant_management"],
"@kbn/observability-ai-assistant-management-plugin/*": ["x-pack/platform/plugins/private/observability_ai_assistant_management/*"],
"@kbn/observability-ai-assistant-plugin": ["x-pack/platform/plugins/shared/observability_ai_assistant"],
"@kbn/observability-ai-assistant-plugin/*": ["x-pack/platform/plugins/shared/observability_ai_assistant/*"],
"@kbn/observability-ai-common": ["x-pack/solutions/observability/packages/observability-ai/observability-ai-common"],

View file

@ -106,7 +106,7 @@
"platform/plugins/shared/observability_ai_assistant",
"solutions/observability/plugins/observability_ai_assistant_app"
],
"xpack.observabilityAiAssistantManagement": "solutions/observability/plugins/observability_ai_assistant_management",
"xpack.observabilityAiAssistantManagement": "platform/plugins/private/observability_ai_assistant_management",
"xpack.observabilityLogsExplorer": "solutions/observability/plugins/observability_logs_explorer",
"xpack.observability_onboarding": "solutions/observability/plugins/observability_onboarding",
"xpack.observabilityShared": "solutions/observability/plugins/observability_shared",

View file

@ -8,9 +8,9 @@
module.exports = {
preset: '@kbn/test',
rootDir: '../../../../..',
roots: ['<rootDir>/x-pack/solutions/observability/plugins/observability_ai_assistant_management'],
roots: ['<rootDir>/x-pack/platform/plugins/private/observability_ai_assistant_management'],
coverageReporters: ['text', 'html'],
collectCoverageFrom: [
'<rootDir>/x-pack/solutions/observability/plugins/observability_ai_assistant_management/{common,public,server}/**/*.{js,ts,tsx}',
'<rootDir>/x-pack/platform/plugins/private/observability_ai_assistant_management/{common,public,server}/**/*.{js,ts,tsx}',
],
};

View file

@ -2,7 +2,7 @@
"type": "plugin",
"id": "@kbn/observability-ai-assistant-management-plugin",
"owner": "@elastic/obs-ai-assistant",
"group": "observability",
"group": "platform",
"visibility": "private",
"plugin": {
"id": "observabilityAiAssistantManagement",
@ -16,7 +16,6 @@
"actions",
"management",
"observabilityAIAssistant",
"observabilityShared",
"ml",
],
"optionalPlugins": [

View file

@ -0,0 +1,133 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { useKibana } from '@kbn/kibana-react-plugin/public';
import React, { useMemo, useState } from 'react';
import { IUiSettingsClient, UiSettingsType } from '@kbn/core/public';
import { isEmpty } from 'lodash';
import { getFieldDefinition } from '@kbn/management-settings-field-definition';
import type {
FieldDefinition,
OnFieldChangeFn,
UiSettingMetadata,
UnsavedFieldChange,
} from '@kbn/management-settings-types';
import { normalizeSettings } from '@kbn/management-settings-utilities';
function getSettingsFields({
settingsKeys,
uiSettings,
}: {
settingsKeys: string[];
uiSettings?: IUiSettingsClient;
}) {
if (!uiSettings) {
return {};
}
const uiSettingsDefinition = uiSettings.getAll();
const normalizedSettings = normalizeSettings(uiSettingsDefinition);
const fields: Record<string, FieldDefinition> = {};
settingsKeys.forEach((key) => {
const setting: UiSettingMetadata = normalizedSettings[key];
if (setting) {
const field = getFieldDefinition({
id: key,
setting,
params: { isCustom: uiSettings.isCustom(key), isOverridden: uiSettings.isOverridden(key) },
});
fields[key] = field;
}
});
return fields;
}
export function useEditableSettings(settingsKeys: string[]) {
const {
services: { settings },
} = useKibana();
const [isSaving, setIsSaving] = useState(false);
const [forceReloadSettings, setForceReloadSettings] = useState(0);
const [unsavedChanges, setUnsavedChanges] = React.useState<Record<string, UnsavedFieldChange>>(
{}
);
const fields = useMemo(
() => {
return getSettingsFields({ settingsKeys, uiSettings: settings?.client });
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[settings, settingsKeys, forceReloadSettings]
);
const handleFieldChange: OnFieldChangeFn = (id, change) => {
if (!change) {
const { [id]: unsavedChange, ...rest } = unsavedChanges;
setUnsavedChanges(rest);
return;
}
setUnsavedChanges((changes) => ({ ...changes, [id]: change }));
};
function cleanUnsavedChanges() {
setUnsavedChanges({});
}
async function saveAll() {
if (settings && !isEmpty(unsavedChanges)) {
let updateErrorOccurred = false;
const subscription = settings.client.getUpdateErrors$().subscribe((error) => {
updateErrorOccurred = true;
});
try {
setIsSaving(true);
const arr = Object.entries(unsavedChanges).map(([key, value]) =>
settings.client.set(key, value.unsavedValue)
);
await Promise.all(arr);
setForceReloadSettings((state) => ++state);
cleanUnsavedChanges();
if (updateErrorOccurred) {
throw new Error('One or more settings updates failed');
}
} catch (e) {
throw e;
} finally {
setIsSaving(false);
if (subscription) {
subscription.unsubscribe();
}
}
}
}
async function saveSingleSetting(
id: string,
change: UnsavedFieldChange<UiSettingsType>['unsavedValue']
) {
if (settings) {
try {
setIsSaving(true);
await settings.client.set(id, change);
setForceReloadSettings((state) => ++state);
} finally {
setIsSaving(false);
}
}
}
return {
fields,
unsavedChanges,
handleFieldChange,
saveAll,
isSaving,
cleanUnsavedChanges,
saveSingleSetting,
};
}

View file

@ -0,0 +1,107 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import {
EuiBottomBar,
EuiButton,
EuiButtonEmpty,
EuiFlexGroup,
EuiFlexItem,
EuiHealth,
EuiText,
EuiToolTip,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React from 'react';
interface Props {
unsavedChangesCount: number;
isLoading: boolean;
onDiscardChanges: () => void;
onSave: () => void;
saveLabel: string;
appTestSubj: string;
areChangesInvalid?: boolean;
}
export const BottomBarActions = ({
isLoading,
onDiscardChanges,
onSave,
unsavedChangesCount,
saveLabel,
appTestSubj,
areChangesInvalid = false,
}: Props) => {
return (
<EuiBottomBar paddingSize="s">
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center">
<EuiFlexItem
grow={false}
css={{
flexDirection: 'row',
alignItems: 'center',
}}
>
<EuiHealth color="warning" />
<EuiText>
{i18n.translate(
'xpack.observabilityAiAssistantManagement.bottomBarActions.unsavedChanges',
{
defaultMessage:
'{unsavedChangesCount, plural, =0{0 unsaved changes} one {1 unsaved change} other {# unsaved changes}} ',
values: { unsavedChangesCount },
}
)}
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiFlexGroup justifyContent="flexEnd">
<EuiFlexItem grow={false}>
<EuiButtonEmpty
data-test-subj={`${appTestSubj}BottomBarActionsDiscardChangesButton`}
color="text"
onClick={onDiscardChanges}
>
{i18n.translate(
'xpack.observabilityAiAssistantManagement.bottomBarActions.discardChangesButton',
{
defaultMessage: 'Discard changes',
}
)}
</EuiButtonEmpty>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiToolTip
content={
areChangesInvalid &&
i18n.translate(
'xpack.observabilityAiAssistantManagement.bottomBarActions.saveButtonTooltipWithInvalidChanges',
{
defaultMessage: 'Fix invalid settings before saving.',
}
)
}
>
<EuiButton
disabled={areChangesInvalid}
data-test-subj={`${appTestSubj}BottomBarActionsButton`}
onClick={onSave}
fill
isLoading={isLoading}
color="success"
iconType="check"
>
{saveLabel}
</EuiButton>
</EuiToolTip>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>
</EuiBottomBar>
);
};

View file

@ -6,7 +6,6 @@
*/
import React from 'react';
import { BottomBarActions, useEditableSettings } from '@kbn/observability-shared-plugin/public';
import {
aiAssistantLogsIndexPattern,
aiAssistantSimulatedFunctionCalling,
@ -19,8 +18,10 @@ import { isEmpty } from 'lodash';
import { i18n } from '@kbn/i18n';
import { LogSourcesSettingSynchronisationInfo } from '@kbn/logs-data-access-plugin/public';
import { useKnowledgeBase } from '@kbn/ai-assistant';
import { useEditableSettings } from '../../../hooks/use_editable_settings';
import { useAppContext } from '../../../hooks/use_app_context';
import { useKibana } from '../../../hooks/use_kibana';
import { BottomBarActions } from '../bottom_bar_actions/bottom_bar_actions';
export function UISettings() {
const {

View file

@ -20,7 +20,6 @@
"@kbn/observability-ai-assistant-plugin",
"@kbn/serverless",
"@kbn/management-settings-components-field-row",
"@kbn/observability-shared-plugin",
"@kbn/config-schema",
"@kbn/core-ui-settings-common",
"@kbn/logs-data-access-plugin",
@ -29,7 +28,10 @@
"@kbn/core-plugins-server",
"@kbn/product-doc-base-plugin",
"@kbn/ai-assistant-icon",
"@kbn/ml-plugin"
"@kbn/ml-plugin",
"@kbn/management-settings-field-definition",
"@kbn/management-settings-types",
"@kbn/management-settings-utilities"
],
"exclude": [
"target/**/*"

View file

@ -33147,6 +33147,9 @@
"xpack.observabilityAiAssistantManagement.app.description": "Gérez votre assistant dIA pour Observability et Search.",
"xpack.observabilityAiAssistantManagement.app.title": "Assistant dIA pour Observability et Search",
"xpack.observabilityAiAssistantManagement.app.titleBar": "Assistant dIA pour les paramètres d'Observability et de Search",
"xpack.observabilityAiAssistantManagement.bottomBarActions.discardChangesButton": "Abandonner les modifications",
"xpack.observabilityAiAssistantManagement.bottomBarActions.saveButtonTooltipWithInvalidChanges": "Corrigez les paramètres non valides avant d'enregistrer.",
"xpack.observabilityAiAssistantManagement.bottomBarActions.unsavedChanges": "{unsavedChangesCount, plural, =0{0 modification non enregistrée} one {1 modification non enregistrée} other {# modifications non enregistrées}}",
"xpack.observabilityAiAssistantManagement.breadcrumb.index": "Assistants d'IA",
"xpack.observabilityAiAssistantManagement.breadcrumb.observability": "Observabilité",
"xpack.observabilityAiAssistantManagement.breadcrumb.serverless.observability": "Assistant dIA pour les paramètres d'Observability et de Search",

View file

@ -33125,6 +33125,9 @@
"xpack.observabilityAiAssistantManagement.app.description": "AI Assistant for Observability and Searchを管理します。",
"xpack.observabilityAiAssistantManagement.app.title": "AI Assistant for Observability and Search",
"xpack.observabilityAiAssistantManagement.app.titleBar": "AI Assistant for Observability and Search設定",
"xpack.observabilityAiAssistantManagement.bottomBarActions.discardChangesButton": "変更を破棄",
"xpack.observabilityAiAssistantManagement.bottomBarActions.saveButtonTooltipWithInvalidChanges": "保存前に無効な設定を修正してください。",
"xpack.observabilityAiAssistantManagement.bottomBarActions.unsavedChanges": "{unsavedChangesCount, plural, other {# 未保存変更}}",
"xpack.observabilityAiAssistantManagement.breadcrumb.index": "AI Assistant",
"xpack.observabilityAiAssistantManagement.breadcrumb.observability": "Observability",
"xpack.observabilityAiAssistantManagement.breadcrumb.serverless.observability": "AI Assistant for Observability and Search設定",

View file

@ -33182,6 +33182,9 @@
"xpack.observabilityAiAssistantManagement.app.description": "管理适用于 Observability 和 Search 的 AI 助手。",
"xpack.observabilityAiAssistantManagement.app.title": "适用于 Observability 和 Search 的 AI 助手",
"xpack.observabilityAiAssistantManagement.app.titleBar": "适用于 Observability 和 Search 的 AI 助手设置",
"xpack.observabilityAiAssistantManagement.bottomBarActions.discardChangesButton": "放弃更改",
"xpack.observabilityAiAssistantManagement.bottomBarActions.saveButtonTooltipWithInvalidChanges": "保存前请修复无效的设置。",
"xpack.observabilityAiAssistantManagement.bottomBarActions.unsavedChanges": "{unsavedChangesCount, plural, =0{0 个未保存更改} one {1 个未保存更改} other {# 个未保存更改}}",
"xpack.observabilityAiAssistantManagement.breadcrumb.index": "AI 助手",
"xpack.observabilityAiAssistantManagement.breadcrumb.observability": "Observability",
"xpack.observabilityAiAssistantManagement.breadcrumb.serverless.observability": "适用于 Observability 和 Search 的 AI 助手设置",

View file

@ -4,8 +4,8 @@
"owner": [
"@elastic/observability-ui"
],
"group": "observability",
"visibility": "private",
"group": "platform",
"visibility": "shared",
"plugin": {
"id": "observabilityShared",
"browser": true,

View file

@ -3,7 +3,7 @@
"id": "@kbn/enterprise-search-plugin",
"owner": "@elastic/search-kibana",
// TODO this is currently used from Observability too, must be refactored before solution-specific builds
// see x-pack/solutions/observability/plugins/observability_ai_assistant_management/public/routes/components/search_connector_tab.tsx
// see x-pack/platform/plugins/private/observability_ai_assistant_management/public/routes/components/search_connector_tab.tsx
// cc sphilipse
"group": "search",
"visibility": "private",

View file

@ -3,7 +3,7 @@
"id": "@kbn/search-connectors-plugin",
"owner": "@elastic/search-kibana",
// TODO this is currently used from Observability too, must be refactored before solution-specific builds
// see x-pack/solutions/observability/plugins/observability_ai_assistant_management/public/routes/components/search_connector_tab.tsx
// see x-pack/platform/plugins/private/observability_ai_assistant_management/public/routes/components/search_connector_tab.tsx
// cc sphilipse
"group": "search",
"visibility": "private",

View file

@ -6345,7 +6345,7 @@
version "0.0.0"
uid ""
"@kbn/observability-ai-assistant-management-plugin@link:x-pack/solutions/observability/plugins/observability_ai_assistant_management":
"@kbn/observability-ai-assistant-management-plugin@link:x-pack/platform/plugins/private/observability_ai_assistant_management":
version "0.0.0"
uid ""