diff --git a/src/platform/packages/shared/kbn-doc-links/src/get_doc_links.ts b/src/platform/packages/shared/kbn-doc-links/src/get_doc_links.ts index 83795afa68d2e..3915484152798 100644 --- a/src/platform/packages/shared/kbn-doc-links/src/get_doc_links.ts +++ b/src/platform/packages/shared/kbn-doc-links/src/get_doc_links.ts @@ -1059,6 +1059,7 @@ export const getDocLinks = ({ kibanaBranch, buildFlavor }: GetDocLinkOptions): D mcpServer: `${ELASTIC_DOCS}solutions/search/agent-builder/mcp-server`, a2aServer: `${ELASTIC_DOCS}solutions/search/agent-builder/a2a-server`, limitationsKnownIssues: `${ELASTIC_DOCS}solutions/search/agent-builder/limitations-known-issues`, + learnMore: `${ELASTIC_DOCS}explore-analyze/ai-features/ai-agent-or-ai-assistant`, }, inferenceManagement: { inferenceAPIDocumentation: isServerless diff --git a/src/platform/packages/shared/kbn-doc-links/src/types.ts b/src/platform/packages/shared/kbn-doc-links/src/types.ts index eed57bf4440dc..fc78a41126e3f 100644 --- a/src/platform/packages/shared/kbn-doc-links/src/types.ts +++ b/src/platform/packages/shared/kbn-doc-links/src/types.ts @@ -713,6 +713,7 @@ export interface DocLinks { readonly mcpServer: string; readonly a2aServer: string; readonly limitationsKnownIssues: string; + readonly learnMore: string; }; readonly indexManagement: { readonly componentTemplate: string; diff --git a/src/platform/plugins/shared/ai_assistant_management/selection/public/components/navigation_control/index.tsx b/src/platform/plugins/shared/ai_assistant_management/selection/public/components/navigation_control/index.tsx index fed4b278f8ac0..9d41bf1498fc9 100644 --- a/src/platform/plugins/shared/ai_assistant_management/selection/public/components/navigation_control/index.tsx +++ b/src/platform/plugins/shared/ai_assistant_management/selection/public/components/navigation_control/index.tsx @@ -58,6 +58,7 @@ export const AIAssistantHeaderButton: React.FC = ( const { getUrlForApp } = coreStart.application; const { toasts } = coreStart.notifications; + const { links: docLinks } = coreStart.docLinks; const hasAgentBuilder = coreStart.application.capabilities.agentBuilder?.manageAgents === true; const isAiAgentsEnabled = getIsAiAgentsEnabled(coreStart.featureFlags); @@ -160,9 +161,8 @@ export const AIAssistantHeaderButton: React.FC = ( ), learnMoreLink: ( - // TODO: Update link when documentation is ready @@ -299,6 +299,7 @@ export const AIAssistantHeaderButton: React.FC = ( setConfirmModalOpen(false)} + docLinks={docLinks} /> )} diff --git a/src/platform/plugins/shared/ai_assistant_management/selection/server/plugin.ts b/src/platform/plugins/shared/ai_assistant_management/selection/server/plugin.ts index a477e03f3e2d5..49fa8ac12c14b 100644 --- a/src/platform/plugins/shared/ai_assistant_management/selection/server/plugin.ts +++ b/src/platform/plugins/shared/ai_assistant_management/selection/server/plugin.ts @@ -89,10 +89,9 @@ export class AIAssistantManagementSelectionPlugin getValue: async ({ request }: { request?: KibanaRequest } = {}) => { if (request) { try { - const [coreStart, startServices] = await core.getStartServices(); - // Avoid security exceptions before login - const user = coreStart.security.authc.getCurrentUser(request); - if (startServices.spaces && user) { + const [, startServices] = await core.getStartServices(); + // Avoid security exceptions before login - only check space when authenticated + if (startServices.spaces && request.auth.isAuthenticated) { const activeSpace = await startServices.spaces.spacesService.getActiveSpace( request ); diff --git a/src/platform/plugins/shared/ai_assistant_management/selection/server/src/settings/chat_experience_setting.ts b/src/platform/plugins/shared/ai_assistant_management/selection/server/src/settings/chat_experience_setting.ts index eff7fbb368e63..cfebfdf5576cd 100644 --- a/src/platform/plugins/shared/ai_assistant_management/selection/server/src/settings/chat_experience_setting.ts +++ b/src/platform/plugins/shared/ai_assistant_management/selection/server/src/settings/chat_experience_setting.ts @@ -8,23 +8,17 @@ */ import { i18n } from '@kbn/i18n'; - import { schema } from '@kbn/config-schema'; import type { UiSettingsParams } from '@kbn/core-ui-settings-common'; import { AIChatExperience } from '@kbn/ai-assistant-common'; import { AI_AGENT, CHAT_EXPERIENCE_TITLE, CLASSIC_AI_ASSISTANT } from './translations'; -// Define the chatExperienceSetting with proper typing export const chatExperienceSetting: Omit, 'value'> = { name: CHAT_EXPERIENCE_TITLE, description: i18n.translate( 'aiAssistantManagementSelection.preferredChatExperienceSettingDescription', { - defaultMessage: 'Choose which chat experience to use for everyone in this space. {link}', - values: { - // TODO: add the actual link when available - link: 'Learn more', - }, + defaultMessage: 'Choose which chat experience to use for all users in this space.', } ), schema: schema.oneOf( diff --git a/src/platform/plugins/shared/ai_assistant_management/selection/server/src/settings/translations.ts b/src/platform/plugins/shared/ai_assistant_management/selection/server/src/settings/translations.ts index b79e12edacf8a..2fbb72bb5dba1 100644 --- a/src/platform/plugins/shared/ai_assistant_management/selection/server/src/settings/translations.ts +++ b/src/platform/plugins/shared/ai_assistant_management/selection/server/src/settings/translations.ts @@ -42,9 +42,9 @@ export const CHAT_EXPERIENCE_TITLE = i18n.translate( export const CLASSIC_AI_ASSISTANT = i18n.translate( 'aiAssistantManagementSelection.preferredAIAssistantTypeSettingValueClassic', - { defaultMessage: 'Classic AI Assistant (default)' } + { defaultMessage: 'Classic AI Assistant' } ); export const AI_AGENT = i18n.translate( 'aiAssistantManagementSelection.preferredAIAssistantTypeSettingValueAgent', - { defaultMessage: 'AI Agent' } + { defaultMessage: 'AI Agent (Beta)' } ); diff --git a/x-pack/platform/packages/shared/ai-assistant/ai-agent-confirmation-modal/ai_agent_confirmation_modal.test.tsx b/x-pack/platform/packages/shared/ai-assistant/ai-agent-confirmation-modal/ai_agent_confirmation_modal.test.tsx index ece1a33fd6a65..67d4223a56b63 100644 --- a/x-pack/platform/packages/shared/ai-assistant/ai-agent-confirmation-modal/ai_agent_confirmation_modal.test.tsx +++ b/x-pack/platform/packages/shared/ai-assistant/ai-agent-confirmation-modal/ai_agent_confirmation_modal.test.tsx @@ -10,15 +10,26 @@ import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { AIAgentConfirmationModal } from './ai_agent_confirmation_modal'; import { I18nProvider } from '@kbn/i18n-react'; +import type { DocLinks } from '@kbn/doc-links'; describe('AIAgentConfirmationModal', () => { const mockOnConfirm = jest.fn(); const mockOnCancel = jest.fn(); + const mockDocLinks: DocLinks = { + agentBuilder: { + learnMore: 'https://www.elastic.co/docs/explore-analyze/ai-features/ai-agent-or-ai-assistant', + }, + } as DocLinks; + const renderComponent = () => { return render( - + ); }; diff --git a/x-pack/platform/packages/shared/ai-assistant/ai-agent-confirmation-modal/ai_agent_confirmation_modal.tsx b/x-pack/platform/packages/shared/ai-assistant/ai-agent-confirmation-modal/ai_agent_confirmation_modal.tsx index d26390719cd11..8089a42edb61b 100644 --- a/x-pack/platform/packages/shared/ai-assistant/ai-agent-confirmation-modal/ai_agent_confirmation_modal.tsx +++ b/x-pack/platform/packages/shared/ai-assistant/ai-agent-confirmation-modal/ai_agent_confirmation_modal.tsx @@ -17,18 +17,20 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; +import type { DocLinks } from '@kbn/doc-links'; export interface AIAgentConfirmationModalProps { onConfirm: () => void; onCancel: () => void; + docLinks: DocLinks; } export const AIAgentConfirmationModal: React.FC = ({ onConfirm, onCancel, + docLinks, }) => { const confirmModalTitleId = useGeneratedHtmlId({ prefix: 'aiAgentConfirmModalTitle' }); - return ( = br:
, bold: (str) => {str}, learnMoreLink: ( - // TODO: Update link when documentation is ready diff --git a/x-pack/platform/packages/shared/ai-assistant/ai-agent-confirmation-modal/moon.yml b/x-pack/platform/packages/shared/ai-assistant/ai-agent-confirmation-modal/moon.yml index a30e668d9ddc9..4e09e82cbc271 100644 --- a/x-pack/platform/packages/shared/ai-assistant/ai-agent-confirmation-modal/moon.yml +++ b/x-pack/platform/packages/shared/ai-assistant/ai-agent-confirmation-modal/moon.yml @@ -20,6 +20,7 @@ project: dependsOn: - '@kbn/i18n' - '@kbn/i18n-react' + - '@kbn/doc-links' tags: - shared-browser - package diff --git a/x-pack/platform/packages/shared/ai-assistant/ai-agent-confirmation-modal/tsconfig.json b/x-pack/platform/packages/shared/ai-assistant/ai-agent-confirmation-modal/tsconfig.json index 23c70aae628fa..bf963c629ac2e 100644 --- a/x-pack/platform/packages/shared/ai-assistant/ai-agent-confirmation-modal/tsconfig.json +++ b/x-pack/platform/packages/shared/ai-assistant/ai-agent-confirmation-modal/tsconfig.json @@ -22,5 +22,6 @@ "kbn_references": [ "@kbn/i18n", "@kbn/i18n-react", + "@kbn/doc-links", ] } diff --git a/x-pack/platform/packages/shared/kbn-ai-assistant/src/chat/chat_actions_menu.tsx b/x-pack/platform/packages/shared/kbn-ai-assistant/src/chat/chat_actions_menu.tsx index 7658c5024d14e..a1de83fcad360 100644 --- a/x-pack/platform/packages/shared/kbn-ai-assistant/src/chat/chat_actions_menu.tsx +++ b/x-pack/platform/packages/shared/kbn-ai-assistant/src/chat/chat_actions_menu.tsx @@ -48,7 +48,7 @@ export function ChatActionsMenu({ isConversationApp: boolean; navigateToConnectorsManagementApp: (application: ApplicationStart) => void; }) { - const { application, http, triggersActionsUi } = useKibana().services; + const { application, http, triggersActionsUi, docLinks } = useKibana().services; const knowledgeBase = useKnowledgeBase(); const [isOpen, setIsOpen] = useState(false); const [connectorFlyoutOpen, setConnectorFlyoutOpen] = useState(false); @@ -244,10 +244,11 @@ export function ChatActionsMenu({ /> )} - {isAgentBuilderConfirmationModalOpen && ( + {isAgentBuilderConfirmationModalOpen && docLinks?.links && ( )} diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/settings_context_menu/settings_context_menu.tsx b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/settings_context_menu/settings_context_menu.tsx index fef36da76e606..327b5ae771068 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/settings_context_menu/settings_context_menu.tsx +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant/settings/settings_context_menu/settings_context_menu.tsx @@ -44,6 +44,7 @@ export const AssistantSettingsContextMenu: React.FC = React.memo( showAssistantOverlay, settings, toasts, + docLinks, } = useAssistantContext(); const [isPopoverOpen, setPopover] = useState(false); @@ -281,6 +282,7 @@ export const AssistantSettingsContextMenu: React.FC = React.memo( )} diff --git a/x-pack/platform/plugins/private/gen_ai_settings/public/components/ai_assistant_visibility/ai_assistant_visibility.tsx b/x-pack/platform/plugins/private/gen_ai_settings/public/components/ai_assistant_visibility/ai_assistant_visibility.tsx index 15deb1b6eebbb..a67487e82fc23 100644 --- a/x-pack/platform/plugins/private/gen_ai_settings/public/components/ai_assistant_visibility/ai_assistant_visibility.tsx +++ b/x-pack/platform/plugins/private/gen_ai_settings/public/components/ai_assistant_visibility/ai_assistant_visibility.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; +import { EuiSpacer } from '@elastic/eui'; import { FieldRow, FieldRowProvider } from '@kbn/management-settings-components-field-row'; import { AI_ASSISTANT_PREFERRED_AI_ASSISTANT_TYPE, @@ -49,17 +50,21 @@ export const AIAssistantVisibility: React.FC = () => { const canEditAdvancedSettings = application.capabilities.advancedSettings?.save; return ( - notifications.toasts.addDanger(message)} - validateChange={(key: string, value: any) => settings.client.validateValue(key, value)} - > - - + <> + + + notifications.toasts.addDanger(message)} + validateChange={(key: string, value: any) => settings.client.validateValue(key, value)} + > + + + ); }; diff --git a/x-pack/platform/plugins/private/gen_ai_settings/public/components/chat_experience/chat_experience.tsx b/x-pack/platform/plugins/private/gen_ai_settings/public/components/chat_experience/chat_experience.tsx index e6b723bdd678f..90c3e20fff5b1 100644 --- a/x-pack/platform/plugins/private/gen_ai_settings/public/components/chat_experience/chat_experience.tsx +++ b/x-pack/platform/plugins/private/gen_ai_settings/public/components/chat_experience/chat_experience.tsx @@ -5,7 +5,9 @@ * 2.0. */ -import React, { useState, useCallback } from 'react'; +import React, { useState, useCallback, useMemo } from 'react'; +import { EuiLink, EuiSpacer } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; import { FieldRow, FieldRowProvider } from '@kbn/management-settings-components-field-row'; import { AI_CHAT_EXPERIENCE_TYPE } from '@kbn/management-settings-ids'; import { AIChatExperience } from '@kbn/ai-assistant-common'; @@ -22,8 +24,9 @@ export const ChatExperience: React.FC = () => { const [isConfirmModalOpen, setConfirmModalOpen] = useState(false); const isAiAgentsEnabled = getIsAiAgentsEnabled(featureFlags); + const field = fields[AI_CHAT_EXPERIENCE_TYPE]; + const canEditAdvancedSettings = Boolean(application.capabilities.advancedSettings?.save); - // Show confirmation modal for AI Agents selection const wrappedHandleFieldChange: typeof handleFieldChange = useCallback( (id, change) => { if (id === AI_CHAT_EXPERIENCE_TYPE && change?.unsavedValue === AIChatExperience.Agent) { @@ -44,33 +47,61 @@ export const ChatExperience: React.FC = () => { handleFieldChange(AI_CHAT_EXPERIENCE_TYPE, undefined); }, [handleFieldChange]); - // Don't render if AI Agents feature is disabled - if (!isAiAgentsEnabled) { + const description = useMemo( + () => ( + + + + ), + }} + /> + ), + [docLinks.links.agentBuilder.learnMore] + ); + + if (!isAiAgentsEnabled || !field) { return null; } - const field = fields[AI_CHAT_EXPERIENCE_TYPE]; - if (!field) return null; - - const canEditAdvancedSettings = application.capabilities.advancedSettings?.save; + const fieldWithDescription = { + ...field, + description, + }; return ( <> + notifications.toasts.addDanger(message)} validateChange={(key: string, value: any) => settings.client.validateValue(key, value)} > {isConfirmModalOpen && ( - + )} ); diff --git a/x-pack/platform/plugins/private/gen_ai_settings/public/components/gen_ai_settings_app.tsx b/x-pack/platform/plugins/private/gen_ai_settings/public/components/gen_ai_settings_app.tsx index 784fb87bdb4eb..6825ada941d83 100644 --- a/x-pack/platform/plugins/private/gen_ai_settings/public/components/gen_ai_settings_app.tsx +++ b/x-pack/platform/plugins/private/gen_ai_settings/public/components/gen_ai_settings_app.tsx @@ -64,6 +64,7 @@ export const GenAiSettingsApp: React.FC = ({ setBreadcrum chatExperienceField?.defaultValue ?? AIChatExperience.Classic; const isAgentExperience = currentChatExperience === AIChatExperience.Agent; + const hasAgentBuilderPrivileges = application.capabilities.agentBuilder?.manageAgents === true; const hasConnectorsAllPrivilege = application.capabilities.actions?.show === true && @@ -112,10 +113,9 @@ export const GenAiSettingsApp: React.FC = ({ setBreadcrum

= ({ setBreadcrum /> ), - additionalCostsIncur: ( - // TODO: Update link when documentation is ready - + atAdditionalCost: ( + ), @@ -330,7 +332,7 @@ export const GenAiSettingsApp: React.FC = ({ setBreadcrum ) : ( @@ -367,7 +369,7 @@ export const GenAiSettingsApp: React.FC = ({ setBreadcrum - {isAgentExperience && showChatExperienceSetting && ( + {isAgentExperience && (showChatExperienceSetting || hasAgentBuilderPrivileges) && ( <> diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/tour_callout/ai_agent_tour_callout.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/tour_callout/ai_agent_tour_callout.tsx index 0dc9323ce8f96..665a3946a9e61 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/tour_callout/ai_agent_tour_callout.tsx +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/tour_callout/ai_agent_tour_callout.tsx @@ -151,6 +151,7 @@ export const AIAgentTourCallout = ({ await confirmAgentBuilderOptIn(); }} onCancel={handleCancelInConfirmationModal} + docLinks={docLinks.links} /> )}