Skip to content
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

[SecuritySolution] Register AI Assistant management settings according to productFeatureKeys #213105

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import { PluginContract } from './plugin_contract';
import { PluginServices } from './plugin_services';
import { getExternalReferenceAttachmentEndpointRegular } from './cases/attachments/external_reference';
import { hasAccessToSecuritySolution } from './helpers_access';
import { ProductFeatureAssistantKey } from '../../../packages/features/src/product_features_keys';

export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, StartPlugins> {
private config: SecuritySolutionUiConfigType;
Expand Down Expand Up @@ -99,6 +100,7 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
this.services.setup(core, plugins);

const { home, usageCollection, management, cases } = plugins;
const { productFeatureKeys$ } = this.contract;

// Lazily instantiate subPlugins and initialize services
const mountDependencies = async (params?: AppMountParameters) => {
Expand Down Expand Up @@ -183,23 +185,33 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
category: 'admin',
});

management?.sections.section.kibana.registerApp({
id: 'securityAiAssistantManagement',
title: ASSISTANT_MANAGEMENT_TITLE,
hideFromSidebar: true,
order: 1,
mount: async (params) => {
const { renderApp, services, store } = await mountDependencies();
const { ManagementSettings } = await this.lazyAssistantSettingsManagement();

return renderApp({
...params,
services,
store,
usageCollection,
children: <ManagementSettings />,
productFeatureKeys$.subscribe((productFeatureKeys) => {
// initial value is null, then it is set as an array in serverless/ess plugin
console.log('productFeatureKeys---',productFeatureKeys);
// This seemed to work with serverless but not sure how to deal with ess productFeatureKeys

const isInProductFeatureKeys = productFeatureKeys && productFeatureKeys.length > 0 && productFeatureKeys.includes(ProductFeatureAssistantKey.assistant);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Running sequence - serverless complete:

Screenshot 2025-03-04 at 14 35 07 Screenshot 2025-03-04 at 14 35 34

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Running sequence - serverless essentials:

Screenshot 2025-03-04 at 14 38 31 Screenshot 2025-03-04 at 14 38 20

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we define the productFeatureKeys$ as a Set<ProductFeatureKeyType>, so we can do:

Suggested change
const isInProductFeatureKeys = productFeatureKeys && productFeatureKeys.length > 0 && productFeatureKeys.includes(ProductFeatureAssistantKey.assistant);
const isInProductFeatureKeys = productFeatureKeys?.has(ProductFeatureAssistantKey.assistant);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to have some control to prevent registering this twice, in case more values are emitted.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (isInProductFeatureKeys) {
console.log('======registering assistant management======');
management?.sections.section.kibana.registerApp({
id: 'securityAiAssistantManagement',
title: ASSISTANT_MANAGEMENT_TITLE,
hideFromSidebar: true,
order: 1,
mount: async (params) => {
const { renderApp, services, store } = await mountDependencies();
const { ManagementSettings } = await this.lazyAssistantSettingsManagement();

return renderApp({
...params,
services,
store,
usageCollection,
children: <ManagementSettings />,
});
},
});
},
}
});

cases?.attachmentFramework.registerExternalReference(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { BehaviorSubject } from 'rxjs';
import { UpsellingService } from '@kbn/security-solution-upselling/service';
import type { CoreStart } from '@kbn/core/public';
Expand All @@ -14,24 +13,31 @@ import { navLinks$, updateNavLinks } from './common/links/nav_links';
import { breadcrumbsNav$ } from './common/breadcrumbs';
import { ContractComponentsService } from './contract_components';
import { OnboardingService } from './onboarding/service';
import { ProductFeatureKeys } from '../../../packages/features/src/types';

export class PluginContract {
public componentsService: ContractComponentsService;
public upsellingService: UpsellingService;
public onboardingService: OnboardingService;
public isSolutionNavigationEnabled$: BehaviorSubject<boolean>;
public productFeatureKeys$: BehaviorSubject<ProductFeatureKeys | null>;

constructor(private readonly experimentalFeatures: ExperimentalFeatures) {
this.onboardingService = new OnboardingService();
this.componentsService = new ContractComponentsService();
this.upsellingService = new UpsellingService();
this.isSolutionNavigationEnabled$ = new BehaviorSubject<boolean>(false); // defaults to classic navigation
this.productFeatureKeys$ = new BehaviorSubject<ProductFeatureKeys | null>(null);
}

public getSetupContract(): PluginSetup {

return {
resolver: lazyResolver,
experimentalFeatures: { ...this.experimentalFeatures },
setProductFeatureKeys: (productFeatureKeys: ProductFeatureKeys) => {
this.productFeatureKeys$.next(productFeatureKeys);
},
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import type { GuidedOnboardingPluginStart } from '@kbn/guided-onboarding-plugin/
import type { DataViewsServicePublic } from '@kbn/data-views-plugin/public';
import type { ContentManagementPublicStart } from '@kbn/content-management-plugin/public';
import type { ExpressionsStart } from '@kbn/expressions-plugin/public';
import type { ProductFeatureKeyType } from '@kbn/security-solution-features/keys';

import type { DiscoverStart } from '@kbn/discover-plugin/public';
import type { ManagementSetup } from '@kbn/management-plugin/public';
Expand Down Expand Up @@ -213,6 +214,7 @@ export type StartRenderServices = Pick<
export interface PluginSetup {
resolver: () => Promise<ResolverPluginSetup>;
experimentalFeatures: ExperimentalFeatures;
setProductFeatureKeys: (productFeatureKeys: ProductFeatureKeyType[]) => void;
}

export interface PluginStart {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ export class SecuritySolutionEssPlugin
_core: CoreSetup,
_setupDeps: SecuritySolutionEssPluginSetupDeps
): SecuritySolutionEssPluginSetup {
const { securitySolution } = _setupDeps;

securitySolution.setProductFeatureKeys([]);

return {};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
} from '../common/experimental_features';
import { setOnboardingSettings } from './onboarding';
import { getAdditionalChargesMessage } from './components/additional_charges_message';
import { getProductProductFeatures } from '../common/pli/pli_features';

export class SecuritySolutionServerlessPlugin
implements
Expand All @@ -47,12 +48,15 @@ export class SecuritySolutionServerlessPlugin
setupDeps: SecuritySolutionServerlessPluginSetupDeps
): SecuritySolutionServerlessPluginSetup {
const { securitySolution } = setupDeps;
const { productTypes } = this.config;

this.experimentalFeatures = parseExperimentalConfigValue(
this.config.enableExperimental,
securitySolution.experimentalFeatures
).features;

console.log('serverless setup: setProductFeatureKeys====== ')
securitySolution.setProductFeatureKeys(getProductProductFeatures(productTypes));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It setProductFeatureKeys correctly for complete and essential tiers.

return {};
}

Expand Down