"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.ObservabilityAIAssistantService = exports.INDEX_QUEUED_DOCUMENTS_TASK_TYPE = exports.INDEX_QUEUED_DOCUMENTS_TASK_ID = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var Boom = _interopRequireWildcard(require("@hapi/boom")); var _server = require("@kbn/alerting-plugin/server"); var _common = require("@kbn/spaces-plugin/common"); var _lodash = require("lodash"); var _client = require("./client"); var _conversation_component_template = require("./conversation_component_template"); var _kb_component_template = require("./kb_component_template"); var _kb_service = require("./kb_service"); var _split_kb_text = require("./util/split_kb_text"); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } /* * 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. */ function getResourceName(resource) { return `.kibana-observability-ai-assistant-${resource}`; } const INDEX_QUEUED_DOCUMENTS_TASK_ID = 'observabilityAIAssistant:indexQueuedDocumentsTask'; exports.INDEX_QUEUED_DOCUMENTS_TASK_ID = INDEX_QUEUED_DOCUMENTS_TASK_ID; const INDEX_QUEUED_DOCUMENTS_TASK_TYPE = INDEX_QUEUED_DOCUMENTS_TASK_ID + 'Type'; exports.INDEX_QUEUED_DOCUMENTS_TASK_TYPE = INDEX_QUEUED_DOCUMENTS_TASK_TYPE; class ObservabilityAIAssistantService { constructor({ logger, core, taskManager }) { (0, _defineProperty2.default)(this, "core", void 0); (0, _defineProperty2.default)(this, "logger", void 0); (0, _defineProperty2.default)(this, "kbService", void 0); (0, _defineProperty2.default)(this, "resourceNames", { componentTemplate: { conversations: getResourceName('component-template-conversations'), kb: getResourceName('component-template-kb') }, aliases: { conversations: getResourceName('conversations'), kb: getResourceName('kb') }, indexPatterns: { conversations: getResourceName('conversations*'), kb: getResourceName('kb*') }, indexTemplate: { conversations: getResourceName('index-template-conversations'), kb: getResourceName('index-template-kb') }, ilmPolicy: { conversations: getResourceName('ilm-policy-conversations') }, pipelines: { kb: getResourceName('kb-ingest-pipeline') } }); (0, _defineProperty2.default)(this, "init", (0, _lodash.once)(async () => { try { const [coreStart, pluginsStart] = await this.core.getStartServices(); const esClient = coreStart.elasticsearch.client.asInternalUser; await esClient.cluster.putComponentTemplate({ create: false, name: this.resourceNames.componentTemplate.conversations, template: _conversation_component_template.conversationComponentTemplate }); await esClient.ilm.putLifecycle({ name: this.resourceNames.ilmPolicy.conversations, policy: { phases: { hot: { min_age: '0s', actions: { rollover: { max_age: '90d', max_primary_shard_size: '50gb' } } } } } }); await esClient.indices.putIndexTemplate({ name: this.resourceNames.indexTemplate.conversations, composed_of: [this.resourceNames.componentTemplate.conversations], create: false, index_patterns: [this.resourceNames.indexPatterns.conversations], template: { settings: { number_of_shards: 1, auto_expand_replicas: '0-1', refresh_interval: '1s' } } }); const conversationAliasName = this.resourceNames.aliases.conversations; await (0, _server.createConcreteWriteIndex)({ esClient, logger: this.logger, totalFieldsLimit: 10000, indexPatterns: { alias: conversationAliasName, pattern: `${conversationAliasName}*`, basePattern: `${conversationAliasName}*`, name: `${conversationAliasName}-000001`, template: this.resourceNames.indexTemplate.conversations } }); await esClient.cluster.putComponentTemplate({ create: false, name: this.resourceNames.componentTemplate.kb, template: _kb_component_template.kbComponentTemplate }); await esClient.ingest.putPipeline({ id: this.resourceNames.pipelines.kb, processors: [{ inference: { model_id: '.elser_model_1', target_field: 'ml', field_map: { text: 'text_field' }, inference_config: { // @ts-expect-error text_expansion: { results_field: 'tokens' } } } }] }); await esClient.indices.putIndexTemplate({ name: this.resourceNames.indexTemplate.kb, composed_of: [this.resourceNames.componentTemplate.kb], create: false, index_patterns: [this.resourceNames.indexPatterns.kb], template: { settings: { number_of_shards: 1, auto_expand_replicas: '0-1', refresh_interval: '1s' } } }); const kbAliasName = this.resourceNames.aliases.kb; await (0, _server.createConcreteWriteIndex)({ esClient, logger: this.logger, totalFieldsLimit: 10000, indexPatterns: { alias: kbAliasName, pattern: `${kbAliasName}*`, basePattern: `${kbAliasName}*`, name: `${kbAliasName}-000001`, template: this.resourceNames.indexTemplate.kb } }); this.kbService = new _kb_service.KnowledgeBaseService({ logger: this.logger.get('kb'), esClient, resources: this.resourceNames, taskManagerStart: pluginsStart.taskManager }); this.logger.info('Successfully set up index assets'); } catch (error) { this.logger.error(`Failed to initialize service: ${error.message}`); this.logger.debug(error); throw error; } })); this.core = core; this.logger = logger; taskManager.registerTaskDefinitions({ [INDEX_QUEUED_DOCUMENTS_TASK_TYPE]: { title: 'Index queued KB articles', description: 'Indexes previously registered entries into the knowledge base when it is ready', timeout: '30m', maxAttempts: 2, createTaskRunner: context => { return { run: async () => { if (this.kbService) { await this.kbService.processQueue(); } } }; } } }); } async getClient({ request }) { const [_, [coreStart, plugins]] = await Promise.all([this.init(), this.core.getStartServices()]); const user = plugins.security.authc.getCurrentUser(request); if (!user) { throw Boom.forbidden(`User not found for current request`); } const basePath = coreStart.http.basePath.get(request); const { spaceId } = (0, _common.getSpaceIdFromPath)(basePath, coreStart.http.basePath.serverBasePath); return new _client.ObservabilityAIAssistantClient({ actionsClient: await plugins.actions.getActionsClientWithRequest(request), namespace: spaceId, esClient: coreStart.elasticsearch.client.asInternalUser, resources: this.resourceNames, logger: this.logger, user: { id: user.profile_uid, name: user.username }, knowledgeBaseService: this.kbService }); } addToKnowledgeBase(entries) { this.init().then(() => { this.kbService.queue(entries.flatMap(entry => { const entryWithSystemProperties = { ...entry, '@timestamp': new Date().toISOString(), public: true, confidence: 'high', is_correction: false, labels: { document_id: entry.id } }; const operations = 'texts' in entryWithSystemProperties ? (0, _split_kb_text.splitKbText)(entryWithSystemProperties) : [{ type: _kb_service.KnowledgeBaseEntryOperationType.Index, document: entryWithSystemProperties }]; return operations; })); }).catch(error => { this.logger.error(`Could not index ${entries.length} entries because of an initialisation error`); this.logger.error(error); }); } } exports.ObservabilityAIAssistantService = ObservabilityAIAssistantService;