-
Notifications
You must be signed in to change notification settings - Fork 8.5k
[Security Solution] [Elastic AI Assistant] Adds support for plugin feature registration #174317
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
cd30788
Adds ability to register features with plugin server
spong 1673ad5
Merge branch 'main' of github.com:elastic/kibana into register-features
spong 4728d2d
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine f78a0bf
Fixes tests and moves capabilities to common package
spong 42ab68d
Use default features in assistant context
spong 30a9701
Merge branch 'main' of github.com:elastic/kibana into register-features
spong 03ce782
Merge branch 'main' into register-features
kibanamachine e55e676
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine 50e6e57
Merge branch 'main' of github.com:elastic/kibana into register-features
spong 2eba0bc
Fixes OpenAPI generation and bundling
spong 064ccfe
Adds tests for feature registration
spong 9f8e21d
Merge branch 'main' of github.com:elastic/kibana into register-features
spong be35f65
Merge branch 'main' into register-features
kibanamachine a4743cf
Merge branch 'main' of github.com:elastic/kibana into register-features
spong e7ab3e9
Increases test coverage, and updates server mocks to work with versio…
spong f0a7dae
Merge branch 'main' of github.com:elastic/kibana into register-features
spong 99f535b
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine 6f17d5e
Allows partial feature registration, and adds docs
spong 7014764
Merge branch 'main' of github.com:elastic/kibana into register-features
spong 45cd452
Fix codeblock in docs
spong 125109d
Rename assistantFeatures to defaultAssistantFeatures
spong File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
.buildkite/scripts/steps/code_generation/elastic_assistant_codegen.sh
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| set -euo pipefail | ||
|
|
||
| source .buildkite/scripts/common/util.sh | ||
|
|
||
| echo --- Elastic Assistant OpenAPI Code Generation | ||
|
|
||
| (cd x-pack/plugins/elastic_assistant && yarn openapi:generate) | ||
| check_for_changed_files "yarn openapi:generate" true |
51 changes: 51 additions & 0 deletions
51
x-pack/packages/kbn-elastic-assistant-common/impl/capabilities/README.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| ### Feature Capabilities | ||
|
|
||
| Feature capabilities are an object describing specific capabilities of the assistant, like whether a feature like streaming is enabled, and are defined in the sibling `./index.ts` file within this `kbn-elastic-assistant-common` package. These capabilities can be registered for a given plugin through the assistant server, and so do not need to be plumbed through the `ElasticAssistantProvider`. | ||
|
|
||
| Storage and accessor functions are made available via the `AppContextService`, and exposed to clients via the`/internal/elastic_assistant/capabilities` route, which can be fetched by clients using the `useCapabilities()` UI hook. | ||
|
|
||
| ### Registering Capabilities | ||
|
|
||
| To register a capability on plugin start, add the following in the consuming plugin's `start()`, specifying any number of capabilities you would like to explicitly declare: | ||
|
|
||
| ```ts | ||
| plugins.elasticAssistant.registerFeatures(APP_UI_ID, { | ||
| assistantModelEvaluation: config.experimentalFeatures.assistantModelEvaluation, | ||
| assistantStreamingEnabled: config.experimentalFeatures.assistantStreamingEnabled, | ||
| }); | ||
| ``` | ||
|
|
||
| ### Declaring Feature Capabilities | ||
| Default feature capabilities are declared in `x-pack/packages/kbn-elastic-assistant-common/impl/capabilities/index.ts`: | ||
|
|
||
| ```ts | ||
| export type AssistantFeatures = { [K in keyof typeof defaultAssistantFeatures]: boolean }; | ||
|
|
||
| export const defaultAssistantFeatures = Object.freeze({ | ||
| assistantModelEvaluation: false, | ||
| assistantStreamingEnabled: false, | ||
| }); | ||
| ``` | ||
|
|
||
| ### Using Capabilities Client Side | ||
| Capabilities can be fetched client side using the `useCapabilities()` hook ala: | ||
|
|
||
| ```ts | ||
| const { data: capabilities } = useCapabilities({ http, toasts }); | ||
| const { assistantModelEvaluation: modelEvaluatorEnabled, assistantStreamingEnabled } = capabilities ?? defaultAssistantFeatures; | ||
| ``` | ||
|
|
||
| ### Using Capabilities Server Side | ||
| Or server side within a route (or elsewhere) via the `assistantContext`: | ||
|
|
||
| ```ts | ||
| const assistantContext = await context.elasticAssistant; | ||
| const pluginName = getPluginNameFromRequest({ request, logger }); | ||
| const registeredFeatures = assistantContext.getRegisteredFeatures(pluginName); | ||
| if (!registeredFeatures.assistantModelEvaluation) { | ||
| return response.notFound(); | ||
| } | ||
| ``` | ||
|
|
||
| > [!NOTE] | ||
| > Note, just as with [registering arbitrary tools](https://github.com/elastic/kibana/pull/172234), features are registered for a specific plugin, where the plugin name that corresponds to your application is defined in the `x-kbn-context` header of requests made from your application, which may be different than your plugin's registered `APP_ID`. |
19 changes: 19 additions & 0 deletions
19
x-pack/packages/kbn-elastic-assistant-common/impl/capabilities/index.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| /* | ||
| * 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. | ||
| */ | ||
|
|
||
| /** | ||
| * Interface for features available to the elastic assistant | ||
| */ | ||
| export type AssistantFeatures = { [K in keyof typeof defaultAssistantFeatures]: boolean }; | ||
|
|
||
| /** | ||
| * Default features available to the elastic assistant | ||
| */ | ||
| export const defaultAssistantFeatures = Object.freeze({ | ||
| assistantModelEvaluation: false, | ||
| assistantStreamingEnabled: false, | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 43 additions & 0 deletions
43
x-pack/packages/kbn-elastic-assistant/impl/assistant/api/capabilities/capabilities.test.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| /* | ||
| * 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 { HttpSetup } from '@kbn/core-http-browser'; | ||
|
|
||
| import { getCapabilities } from './capabilities'; | ||
| import { API_ERROR } from '../../translations'; | ||
|
|
||
| jest.mock('@kbn/core-http-browser'); | ||
|
|
||
| const mockHttp = { | ||
| fetch: jest.fn(), | ||
| } as unknown as HttpSetup; | ||
|
|
||
| describe('Capabilities API tests', () => { | ||
| beforeEach(() => { | ||
| jest.clearAllMocks(); | ||
| }); | ||
|
|
||
| describe('getCapabilities', () => { | ||
| it('calls the internal assistant API for fetching assistant capabilities', async () => { | ||
| await getCapabilities({ http: mockHttp }); | ||
|
|
||
| expect(mockHttp.fetch).toHaveBeenCalledWith('/internal/elastic_assistant/capabilities', { | ||
| method: 'GET', | ||
| signal: undefined, | ||
| version: '1', | ||
| }); | ||
| }); | ||
|
|
||
| it('returns API_ERROR when the response status is error', async () => { | ||
| (mockHttp.fetch as jest.Mock).mockResolvedValue({ status: API_ERROR }); | ||
|
|
||
| const result = await getCapabilities({ http: mockHttp }); | ||
|
|
||
| expect(result).toEqual({ status: API_ERROR }); | ||
| }); | ||
| }); | ||
| }); |
44 changes: 44 additions & 0 deletions
44
x-pack/packages/kbn-elastic-assistant/impl/assistant/api/capabilities/capabilities.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| /* | ||
| * 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 { HttpSetup, IHttpFetchError } from '@kbn/core-http-browser'; | ||
| import { AssistantFeatures } from '@kbn/elastic-assistant-common'; | ||
|
|
||
| export interface GetCapabilitiesParams { | ||
| http: HttpSetup; | ||
| signal?: AbortSignal | undefined; | ||
| } | ||
|
|
||
| export type GetCapabilitiesResponse = AssistantFeatures; | ||
|
|
||
| /** | ||
| * API call for fetching assistant capabilities | ||
| * | ||
| * @param {Object} options - The options object. | ||
| * @param {HttpSetup} options.http - HttpSetup | ||
| * @param {AbortSignal} [options.signal] - AbortSignal | ||
| * | ||
| * @returns {Promise<GetCapabilitiesResponse | IHttpFetchError>} | ||
| */ | ||
| export const getCapabilities = async ({ | ||
| http, | ||
| signal, | ||
| }: GetCapabilitiesParams): Promise<GetCapabilitiesResponse | IHttpFetchError> => { | ||
| try { | ||
| const path = `/internal/elastic_assistant/capabilities`; | ||
|
|
||
| const response = await http.fetch(path, { | ||
| method: 'GET', | ||
| signal, | ||
| version: '1', | ||
| }); | ||
|
|
||
| return response as GetCapabilitiesResponse; | ||
| } catch (error) { | ||
| return error as IHttpFetchError; | ||
| } | ||
| }; |
49 changes: 49 additions & 0 deletions
49
.../packages/kbn-elastic-assistant/impl/assistant/api/capabilities/use_capabilities.test.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| /* | ||
| * 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 { renderHook } from '@testing-library/react-hooks'; | ||
|
|
||
| import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; | ||
| import type { ReactNode } from 'react'; | ||
| import React from 'react'; | ||
| import { useCapabilities, UseCapabilitiesParams } from './use_capabilities'; | ||
|
|
||
| const statusResponse = { assistantModelEvaluation: true, assistantStreamingEnabled: false }; | ||
|
|
||
| const http = { | ||
| fetch: jest.fn().mockResolvedValue(statusResponse), | ||
| }; | ||
| const toasts = { | ||
| addError: jest.fn(), | ||
| }; | ||
| const defaultProps = { http, toasts } as unknown as UseCapabilitiesParams; | ||
|
|
||
| const createWrapper = () => { | ||
| const queryClient = new QueryClient(); | ||
| // eslint-disable-next-line react/display-name | ||
| return ({ children }: { children: ReactNode }) => ( | ||
| <QueryClientProvider client={queryClient}>{children}</QueryClientProvider> | ||
| ); | ||
| }; | ||
|
|
||
| describe('useFetchRelatedCases', () => { | ||
| it(`should make http request to fetch capabilities`, () => { | ||
| renderHook(() => useCapabilities(defaultProps), { | ||
| wrapper: createWrapper(), | ||
| }); | ||
|
|
||
| expect(defaultProps.http.fetch).toHaveBeenCalledWith( | ||
| '/internal/elastic_assistant/capabilities', | ||
| { | ||
| method: 'GET', | ||
| version: '1', | ||
| signal: new AbortController().signal, | ||
| } | ||
| ); | ||
| expect(toasts.addError).not.toHaveBeenCalled(); | ||
| }); | ||
| }); |
52 changes: 52 additions & 0 deletions
52
x-pack/packages/kbn-elastic-assistant/impl/assistant/api/capabilities/use_capabilities.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| /* | ||
| * 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 type { UseQueryResult } from '@tanstack/react-query'; | ||
| import { useQuery } from '@tanstack/react-query'; | ||
| import type { HttpSetup, IHttpFetchError, ResponseErrorBody } from '@kbn/core-http-browser'; | ||
| import type { IToasts } from '@kbn/core-notifications-browser'; | ||
| import { i18n } from '@kbn/i18n'; | ||
| import { getCapabilities, GetCapabilitiesResponse } from './capabilities'; | ||
|
|
||
| const CAPABILITIES_QUERY_KEY = ['elastic-assistant', 'capabilities']; | ||
|
|
||
| export interface UseCapabilitiesParams { | ||
| http: HttpSetup; | ||
| toasts?: IToasts; | ||
| } | ||
| /** | ||
| * Hook for getting the feature capabilities of the assistant | ||
| * | ||
| * @param {Object} options - The options object. | ||
| * @param {HttpSetup} options.http - HttpSetup | ||
| * @param {IToasts} options.toasts - IToasts | ||
| * | ||
| * @returns {useQuery} hook for getting the status of the Knowledge Base | ||
| */ | ||
| export const useCapabilities = ({ | ||
| http, | ||
| toasts, | ||
| }: UseCapabilitiesParams): UseQueryResult<GetCapabilitiesResponse, IHttpFetchError> => { | ||
| return useQuery({ | ||
| queryKey: CAPABILITIES_QUERY_KEY, | ||
| queryFn: async ({ signal }) => { | ||
| return getCapabilities({ http, signal }); | ||
| }, | ||
| retry: false, | ||
| keepPreviousData: true, | ||
| // Deprecated, hoist to `queryCache` w/in `QueryClient. See: https://stackoverflow.com/a/76961109 | ||
| onError: (error: IHttpFetchError<ResponseErrorBody>) => { | ||
| if (error.name !== 'AbortError') { | ||
| toasts?.addError(error.body && error.body.message ? new Error(error.body.message) : error, { | ||
| title: i18n.translate('xpack.elasticAssistant.capabilities.statusError', { | ||
| defaultMessage: 'Error fetching capabilities', | ||
| }), | ||
| }); | ||
| } | ||
| }, | ||
| }); | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.