UNPKG

cozy-search

Version:

UI components about search bar and IA assistant

271 lines (219 loc) 10.7 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.createCozyRealtimeChatAdapter = void 0; var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _awaitAsyncGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/awaitAsyncGenerator")); var _wrapAsyncGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/wrapAsyncGenerator")); var _cozyMinilog = _interopRequireDefault(require("cozy-minilog")); var _helpers = require("../helpers"); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } function _asyncIterator(iterable) { var method, async, sync, retry = 2; for ("undefined" != typeof Symbol && (async = Symbol.asyncIterator, sync = Symbol.iterator); retry--;) { if (async && null != (method = iterable[async])) return method.call(iterable); if (sync && null != (method = iterable[sync])) return new AsyncFromSyncIterator(method.call(iterable)); async = "@@asyncIterator", sync = "@@iterator"; } throw new TypeError("Object is not async iterable"); } function AsyncFromSyncIterator(s) { function AsyncFromSyncIteratorContinuation(r) { if (Object(r) !== r) return Promise.reject(new TypeError(r + " is not an object.")); var done = r.done; return Promise.resolve(r.value).then(function (value) { return { value: value, done: done }; }); } return AsyncFromSyncIterator = function AsyncFromSyncIterator(s) { this.s = s, this.n = s.next; }, AsyncFromSyncIterator.prototype = { s: null, n: null, next: function next() { return AsyncFromSyncIteratorContinuation(this.n.apply(this.s, arguments)); }, return: function _return(value) { var ret = this.s.return; return void 0 === ret ? Promise.resolve({ value: value, done: !0 }) : AsyncFromSyncIteratorContinuation(ret.apply(this.s, arguments)); }, throw: function _throw(value) { var thr = this.s.return; return void 0 === thr ? Promise.reject(value) : AsyncFromSyncIteratorContinuation(thr.apply(this.s, arguments)); } }, new AsyncFromSyncIterator(s); } var log = (0, _cozyMinilog.default)('🔍 [CozyRealtimeChatAdapter]'); /** * Finds the user query to send to the backend. * For new messages: gets the last user message * For reload: finds the last user message (may need to skip assistant messages) */ var findUserQuery = function findUserQuery(messages) { for (var i = messages.length - 1; i >= 0; i--) { var msg = messages[i]; if (msg.role === 'user') { var textContent = msg.content.find(function (part) { return part.type === 'text'; }); if (textContent && textContent.type === 'text') { return textContent.text; } } } return null; }; /** * Creates a ChatModelAdapter that integrates with Cozy's backend. * The adapter posts messages to the backend and yields streaming responses * from the WebSocket via StreamBridge. */ var createCozyRealtimeChatAdapter = function createCozyRealtimeChatAdapter(options, t, streamBridgeRef) { return { run: function run(_ref) { var messages = _ref.messages, abortSignal = _ref.abortSignal; return (0, _wrapAsyncGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() { var client, conversationId, assistantId, websearchEnabled, streamBridge, userQuery, stream, fullText, wasAborted, _iteratorAbruptCompletion, _didIteratorError, _iteratorError, _iterator, _step, chunk, sanitizedText, finalText, sources; return _regenerator.default.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: client = options.client, conversationId = options.conversationId, assistantId = options.assistantId, websearchEnabled = options.websearchEnabled; streamBridge = streamBridgeRef.current; userQuery = findUserQuery(messages); if (userQuery) { _context.next = 6; break; } log.error('No user message found in:', messages); return _context.abrupt("return"); case 6: stream = streamBridge.createStream(conversationId); if (!(abortSignal !== null && abortSignal !== void 0 && abortSignal.aborted)) { _context.next = 10; break; } streamBridge.cleanup(conversationId); return _context.abrupt("return"); case 10: _context.prev = 10; _context.next = 13; return { content: [{ type: 'text', text: '' }], status: { type: 'requires-action', reason: 'tool-calls' } }; case 13: _context.next = 15; return (0, _awaitAsyncGenerator2.default)(client.stackClient.fetchJSON('POST', "/ai/chat/conversations/".concat(conversationId), _objectSpread({ q: userQuery, assistantID: assistantId }, websearchEnabled && { websearch: true }))); case 15: fullText = ''; wasAborted = false; _iteratorAbruptCompletion = false; _didIteratorError = false; _context.prev = 19; _iterator = _asyncIterator(stream); case 21: _context.next = 23; return (0, _awaitAsyncGenerator2.default)(_iterator.next()); case 23: if (!(_iteratorAbruptCompletion = !(_step = _context.sent).done)) { _context.next = 36; break; } chunk = _step.value; if (!(abortSignal !== null && abortSignal !== void 0 && abortSignal.aborted)) { _context.next = 29; break; } wasAborted = true; streamBridge.cleanup(conversationId); return _context.abrupt("break", 36); case 29: fullText += chunk; sanitizedText = (0, _helpers.sanitizeChatContent)(fullText); _context.next = 33; return { content: [{ type: 'text', text: sanitizedText }], status: { type: 'running' } }; case 33: _iteratorAbruptCompletion = false; _context.next = 21; break; case 36: _context.next = 42; break; case 38: _context.prev = 38; _context.t0 = _context["catch"](19); _didIteratorError = true; _iteratorError = _context.t0; case 42: _context.prev = 42; _context.prev = 43; if (!(_iteratorAbruptCompletion && _iterator.return != null)) { _context.next = 47; break; } _context.next = 47; return (0, _awaitAsyncGenerator2.default)(_iterator.return()); case 47: _context.prev = 47; if (!_didIteratorError) { _context.next = 50; break; } throw _iteratorError; case 50: return _context.finish(47); case 51: return _context.finish(42); case 52: if (wasAborted) { _context.next = 58; break; } finalText = (0, _helpers.sanitizeChatContent)(fullText); sources = streamBridge.getSources(conversationId); _context.next = 57; return _objectSpread({ content: [{ type: 'text', text: finalText }], status: { type: 'complete', reason: 'stop' } }, sources ? { metadata: { custom: { sources: sources } } } : {}); case 57: streamBridge.cleanup(conversationId); case 58: _context.next = 66; break; case 60: _context.prev = 60; _context.t1 = _context["catch"](10); log.error('Error:', _context.t1); streamBridge.cleanup(conversationId); _context.next = 66; return { content: [{ type: 'text', text: t('assistant.default_error') }], status: { type: 'incomplete', reason: 'error' }, metadata: { custom: { isError: true } } }; case 66: case "end": return _context.stop(); } } }, _callee, null, [[10, 60], [19, 38, 42, 52], [43,, 47, 51]]); }))(); } }; }; exports.createCozyRealtimeChatAdapter = createCozyRealtimeChatAdapter;