cozy-search
Version:
UI components about search bar and IA assistant
271 lines (219 loc) • 10.7 kB
JavaScript
;
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;