"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.ObservabilityAIAssistantClient = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _boom = require("@hapi/boom"); var _lodash = require("lodash"); var _uuid = require("uuid"); var _types = require("../../../common/types"); var _get_access_query = require("../util/get_access_query"); /* * 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. */ class ObservabilityAIAssistantClient { constructor(dependencies) { (0, _defineProperty2.default)(this, "getConversationWithMetaFields", async conversationId => { const response = await this.dependencies.esClient.search({ index: this.dependencies.resources.aliases.conversations, query: { bool: { filter: [...(0, _get_access_query.getAccessQuery)({ user: this.dependencies.user, namespace: this.dependencies.namespace }), { term: { 'conversation.id': conversationId } }] } }, size: 1, terminate_after: 1 }); return response.hits.hits[0]; }); (0, _defineProperty2.default)(this, "getConversationUpdateValues", now => { return { conversation: { last_updated: now }, user: this.dependencies.user, namespace: this.dependencies.namespace }; }); (0, _defineProperty2.default)(this, "get", async conversationId => { const conversation = await this.getConversationWithMetaFields(conversationId); if (!conversation) { throw (0, _boom.notFound)(); } return conversation._source; }); (0, _defineProperty2.default)(this, "delete", async conversationId => { const conversation = await this.getConversationWithMetaFields(conversationId); if (!conversation) { throw (0, _boom.notFound)(); } await this.dependencies.esClient.delete({ id: conversation._id, index: conversation._index, refresh: 'wait_for' }); }); (0, _defineProperty2.default)(this, "chat", async ({ messages, connectorId, functions, functionCall, stream = true }) => { const messagesForOpenAI = (0, _lodash.compact)(messages.filter(message => { var _message$message$func; return message.message.content || ((_message$message$func = message.message.function_call) === null || _message$message$func === void 0 ? void 0 : _message$message$func.name); }).map(message => { var _message$message$func2; const role = message.message.role === _types.MessageRole.Elastic ? _types.MessageRole.User : message.message.role; return { role, content: message.message.content, function_call: (0, _lodash.isEmpty)((_message$message$func2 = message.message.function_call) === null || _message$message$func2 === void 0 ? void 0 : _message$message$func2.name) ? undefined : (0, _lodash.omit)(message.message.function_call, 'trigger'), name: message.message.name }; })); const functionsForOpenAI = functions; const request = { messages: messagesForOpenAI, stream: true, functions: functionsForOpenAI, temperature: 0, function_call: functionCall ? { name: functionCall } : undefined }; const executeResult = await this.dependencies.actionsClient.execute({ actionId: connectorId, params: { subAction: stream ? 'stream' : 'run', subActionParams: { body: JSON.stringify(request), ...(stream ? { stream: true } : {}) } } }); if (executeResult.status === 'error') { throw (0, _boom.internal)(`${executeResult === null || executeResult === void 0 ? void 0 : executeResult.message} - ${executeResult === null || executeResult === void 0 ? void 0 : executeResult.serviceMessage}`); } return executeResult.data; }); (0, _defineProperty2.default)(this, "find", async options => { const response = await this.dependencies.esClient.search({ index: this.dependencies.resources.aliases.conversations, allow_no_indices: true, query: { bool: { filter: [...(0, _get_access_query.getAccessQuery)({ user: this.dependencies.user, namespace: this.dependencies.namespace })] } }, sort: { '@timestamp': 'desc' }, size: 100 }); return { conversations: response.hits.hits.map(hit => hit._source) }; }); (0, _defineProperty2.default)(this, "update", async conversation => { const document = await this.getConversationWithMetaFields(conversation.conversation.id); if (!document) { throw (0, _boom.notFound)(); } const updatedConversation = (0, _lodash.merge)({}, conversation, this.getConversationUpdateValues(new Date().toISOString())); await this.dependencies.esClient.update({ id: document._id, index: document._index, doc: updatedConversation, refresh: 'wait_for' }); return updatedConversation; }); (0, _defineProperty2.default)(this, "autoTitle", async ({ conversationId, connectorId }) => { const document = await this.getConversationWithMetaFields(conversationId); if (!document) { throw (0, _boom.notFound)(); } const conversation = await this.get(conversationId); if (!conversation) { throw (0, _boom.notFound)(); } const response = await this.chat({ messages: [{ '@timestamp': new Date().toISOString(), message: { role: _types.MessageRole.Assistant, content: conversation.messages.slice(1).reduce((acc, curr) => { return `${acc} ${curr.message.role}: ${curr.message.content}`; }, 'You are a helpful assistant for Elastic Observability. Assume the following message is the start of a conversation between you and a user; give this conversation a title based on this content: ') } }], connectorId, stream: false }); if ('object' in response && response.object === 'chat.completion') { var _response$choices$0$m; const input = ((_response$choices$0$m = response.choices[0].message) === null || _response$choices$0$m === void 0 ? void 0 : _response$choices$0$m.content) || `Conversation on ${conversation['@timestamp']}`; // This regular expression captures a string enclosed in single or double quotes. // It extracts the string content without the quotes. // Example matches: // - "Hello, World!" => Captures: Hello, World! // - 'Another Example' => Captures: Another Example // - JustTextWithoutQuotes => Captures: JustTextWithoutQuotes const match = input.match(/^["']?([^"']+)["']?$/); const title = match ? match[1] : input; const updatedConversation = (0, _lodash.merge)({}, conversation, { conversation: { title } }, this.getConversationUpdateValues(new Date().toISOString())); await this.setTitle({ conversationId, title }); return updatedConversation; } return conversation; }); (0, _defineProperty2.default)(this, "setTitle", async ({ conversationId, title }) => { const document = await this.getConversationWithMetaFields(conversationId); if (!document) { throw (0, _boom.notFound)(); } const conversation = await this.get(conversationId); if (!conversation) { throw (0, _boom.notFound)(); } const updatedConversation = (0, _lodash.merge)({}, conversation, { conversation: { title } }, this.getConversationUpdateValues(new Date().toISOString())); await this.dependencies.esClient.update({ id: document._id, index: document._index, doc: { conversation: { title } }, refresh: 'wait_for' }); return updatedConversation; }); (0, _defineProperty2.default)(this, "create", async conversation => { const now = new Date().toISOString(); const createdConversation = (0, _lodash.merge)({}, conversation, { '@timestamp': now, conversation: { id: (0, _uuid.v4)() } }, this.getConversationUpdateValues(now)); await this.dependencies.esClient.index({ index: this.dependencies.resources.aliases.conversations, document: createdConversation, refresh: 'wait_for' }); return createdConversation; }); (0, _defineProperty2.default)(this, "recall", async queries => { return this.dependencies.knowledgeBaseService.recall({ namespace: this.dependencies.namespace, user: this.dependencies.user, queries }); }); (0, _defineProperty2.default)(this, "summarize", async ({ entry }) => { return this.dependencies.knowledgeBaseService.summarize({ namespace: this.dependencies.namespace, user: this.dependencies.user, entry }); }); (0, _defineProperty2.default)(this, "getKnowledgeBaseStatus", () => { return this.dependencies.knowledgeBaseService.status(); }); (0, _defineProperty2.default)(this, "setupKnowledgeBase", () => { return this.dependencies.knowledgeBaseService.setup(); }); this.dependencies = dependencies; } } exports.ObservabilityAIAssistantClient = ObservabilityAIAssistantClient;