@apia/ai 3.0.21 → 3.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4,10 +4,10 @@ import { useRef, useCallback, useState } from 'react';
4
4
  import { IconButton, AutogrowTextarea, ApiaUtil, SimpleButton, SortableList, SortableListItem } from '@apia/components';
5
5
  import { getLabel, noNaN, AudioRecorder, EventEmitter } from '@apia/util';
6
6
  import { makeObservable, observable, action, toJS, makeAutoObservable } from 'mobx';
7
+ import { observer } from 'mobx-react-lite';
7
8
  import { CollectorField, Collector } from '@apia/validations';
8
9
  import { uniqueId } from '@apia/notifications';
9
10
  import { FileIcon } from '@apia/icons';
10
- import { observer } from 'mobx-react-lite';
11
11
  import axios from 'axios';
12
12
  import { makeApiaUrl, parseSuccessfulResponse, ApiaApi } from '@apia/api';
13
13
 
@@ -193,42 +193,50 @@ function useHandleFileUpload({
193
193
  return { progress, handleFileUpload };
194
194
  }
195
195
 
196
- var __defProp$7 = Object.defineProperty;
197
- var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
198
- var __publicField$7 = (obj, key, value) => {
199
- __defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
196
+ var __defProp$a = Object.defineProperty;
197
+ var __defNormalProp$a = (obj, key, value) => key in obj ? __defProp$a(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
198
+ var __publicField$a = (obj, key, value) => {
199
+ __defNormalProp$a(obj, typeof key !== "symbol" ? key + "" : key, value);
200
200
  return value;
201
201
  };
202
202
  let maxId = 0;
203
203
  class ChatMessage {
204
- constructor(message = "", messageType = "user", attachments = []) {
204
+ constructor(message = "", messageType = "user", attachments = [], reference = null) {
205
205
  this.message = message;
206
206
  this.messageType = messageType;
207
207
  this.attachments = attachments;
208
- __publicField$7(this, "id");
209
- __publicField$7(this, "copy", () => new ChatMessage(this.message, this.messageType, this.attachments));
210
- __publicField$7(this, "Component", () => {
211
- const gapAmount = this.attachments.length > 0 && this.message ? "12px" : "0";
208
+ this.reference = reference;
209
+ __publicField$a(this, "id");
210
+ __publicField$a(this, "clone", () => new ChatMessage(
211
+ this.message,
212
+ this.messageType,
213
+ [...this.attachments],
214
+ this.reference
215
+ ));
216
+ __publicField$a(this, "Component", observer(({ className }) => {
212
217
  return /* @__PURE__ */ jsxs(
213
218
  Box,
214
219
  {
215
220
  as: "pre",
216
- className: `history__message ${this.messageType}`,
217
- sx: { gap: gapAmount },
221
+ className: `history_message ${className || ""} ${this.messageType}`,
218
222
  children: [
219
223
  /* @__PURE__ */ jsx(
220
224
  Box,
221
225
  {
222
- className: "text_wrapper",
226
+ className: "history_message__content",
223
227
  ...typeof this.message === "string" ? { dangerouslySetInnerHTML: { __html: this.message } } : { children: this.message }
224
228
  }
225
229
  ),
226
- /* @__PURE__ */ jsx(Box, { className: "additionalContent_wrapper", children: this.attachments.map((x) => /* @__PURE__ */ jsx(x.Component, {}, x.getId())) })
230
+ this.attachments.length > 0 && /* @__PURE__ */ jsx(Box, { className: "history_message__attachments", children: this.attachments.map((x) => {
231
+ const a = x;
232
+ return /* @__PURE__ */ jsx(a.Component, {}, x.id);
233
+ }) }),
234
+ this.reference && /* @__PURE__ */ jsx(Box, { className: "history_message__references", children: this.reference })
227
235
  ]
228
236
  },
229
237
  this.id
230
238
  );
231
- });
239
+ }));
232
240
  this.id = maxId++;
233
241
  if (messageType === "response")
234
242
  this.messageType = "system";
@@ -237,7 +245,8 @@ class ChatMessage {
237
245
  makeObservable(this, {
238
246
  attachments: observable,
239
247
  message: observable,
240
- messageType: observable
248
+ messageType: observable,
249
+ reference: observable
241
250
  });
242
251
  }
243
252
  parseMessage(message) {
@@ -246,21 +255,24 @@ class ChatMessage {
246
255
  result = result.replaceAll("[/strong]", "</strong>");
247
256
  return result;
248
257
  }
258
+ removeAttachment(idx) {
259
+ this.attachments = this.attachments.filter((_, i) => i !== idx);
260
+ }
249
261
  }
250
262
 
251
- var __defProp$6 = Object.defineProperty;
252
- var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
253
- var __publicField$6 = (obj, key, value) => {
254
- __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
263
+ var __defProp$9 = Object.defineProperty;
264
+ var __defNormalProp$9 = (obj, key, value) => key in obj ? __defProp$9(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
265
+ var __publicField$9 = (obj, key, value) => {
266
+ __defNormalProp$9(obj, typeof key !== "symbol" ? key + "" : key, value);
255
267
  return value;
256
268
  };
257
269
  class AIContent extends CollectorField {
258
270
  constructor(content) {
259
271
  super(uniqueId(), "");
260
- __publicField$6(this, "type", "aiContent");
261
- __publicField$6(this, "content");
272
+ __publicField$9(this, "type", "aiContent");
273
+ __publicField$9(this, "content");
262
274
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
263
- __publicField$6(this, "Component", (props) => {
275
+ __publicField$9(this, "Component", (props) => {
264
276
  return /* @__PURE__ */ jsx(Box, { variant: "layout.common.components.aiMessage.textBox", children: /* @__PURE__ */ jsx(Box, { variant: "layout.common.components.aiMessage.textSnippet", children: this.content }) });
265
277
  });
266
278
  this.content = content;
@@ -296,29 +308,30 @@ var AIMessageRole = /* @__PURE__ */ ((AIMessageRole2) => {
296
308
  return AIMessageRole2;
297
309
  })(AIMessageRole || {});
298
310
 
299
- var __defProp$5 = Object.defineProperty;
300
- var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
301
- var __publicField$5 = (obj, key, value) => {
302
- __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
311
+ var __defProp$8 = Object.defineProperty;
312
+ var __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
313
+ var __publicField$8 = (obj, key, value) => {
314
+ __defNormalProp$8(obj, typeof key !== "symbol" ? key + "" : key, value);
303
315
  return value;
304
316
  };
305
317
  const _AIFileContent = class _AIFileContent extends AIContent {
306
318
  constructor(fileUrl, fileName, f, error) {
307
319
  const extension = _AIFileContent.getExtensionFromFileName(fileName);
308
320
  super();
309
- __publicField$5(this, "type");
310
- __publicField$5(this, "fileUrl");
311
- __publicField$5(this, "fileName");
312
- __publicField$5(this, "extension");
313
- __publicField$5(this, "__file");
314
- __publicField$5(this, "__error");
315
- __publicField$5(this, "overrideSize");
316
- __publicField$5(this, "id", uniqueId());
317
- __publicField$5(this, "getId", () => this.id);
318
- __publicField$5(this, "inferContent", () => {
321
+ __publicField$8(this, "type");
322
+ __publicField$8(this, "fileUrl");
323
+ __publicField$8(this, "fileName");
324
+ __publicField$8(this, "extension");
325
+ __publicField$8(this, "__file");
326
+ __publicField$8(this, "__error");
327
+ __publicField$8(this, "overrideSize");
328
+ __publicField$8(this, "id", uniqueId());
329
+ __publicField$8(this, "value", "");
330
+ __publicField$8(this, "getId", () => this.id);
331
+ __publicField$8(this, "inferContent", () => {
319
332
  return `You must collect information contained in this ${this.type} as help to build your tool choice.`;
320
333
  });
321
- __publicField$5(this, "inferExtension", (extension) => {
334
+ __publicField$8(this, "inferExtension", (extension) => {
322
335
  switch (extension) {
323
336
  case AIFileContentAllowedExtensions.jpg:
324
337
  case AIFileContentAllowedExtensions.jpeg:
@@ -346,7 +359,7 @@ const _AIFileContent = class _AIFileContent extends AIContent {
346
359
  }
347
360
  });
348
361
  // COMPONENT METHODS
349
- __publicField$5(this, "Component", (props) => {
362
+ __publicField$8(this, "Component", (props) => {
350
363
  return /* @__PURE__ */ jsx(
351
364
  Box,
352
365
  {
@@ -457,12 +470,12 @@ ${Object.keys(AIFileContentAllowedExtensions)}`;
457
470
  }
458
471
  };
459
472
  // STATIC METHODS
460
- __publicField$5(_AIFileContent, "isValidExtension", (extension) => {
473
+ __publicField$8(_AIFileContent, "isValidExtension", (extension) => {
461
474
  return Object.values(
462
475
  AIFileContentAllowedExtensions
463
476
  ).includes(extension);
464
477
  });
465
- __publicField$5(_AIFileContent, "blobToBase64", async (blob) => {
478
+ __publicField$8(_AIFileContent, "blobToBase64", async (blob) => {
466
479
  return await ((blob2) => new Promise((resolve, reject) => {
467
480
  const reader = new FileReader();
468
481
  reader.onloadend = () => {
@@ -473,7 +486,7 @@ __publicField$5(_AIFileContent, "blobToBase64", async (blob) => {
473
486
  reader.readAsDataURL(blob2);
474
487
  }))(blob);
475
488
  });
476
- __publicField$5(_AIFileContent, "fromFile", async (f, error) => {
489
+ __publicField$8(_AIFileContent, "fromFile", async (f, error) => {
477
490
  const fileUrl = await ((f2) => new Promise((resolve, reject) => {
478
491
  const reader = new FileReader();
479
492
  reader.readAsDataURL(f2);
@@ -484,21 +497,23 @@ __publicField$5(_AIFileContent, "fromFile", async (f, error) => {
484
497
  });
485
498
  let AIFileContent = _AIFileContent;
486
499
 
487
- var __defProp$4 = Object.defineProperty;
488
- var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
489
- var __publicField$4 = (obj, key, value) => {
490
- __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
500
+ var __defProp$7 = Object.defineProperty;
501
+ var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
502
+ var __publicField$7 = (obj, key, value) => {
503
+ __defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
491
504
  return value;
492
505
  };
493
506
  class AIMessageAttachments {
494
507
  constructor(role, content, close) {
495
508
  this.close = close;
496
- __publicField$4(this, "role");
497
- __publicField$4(this, "content");
498
- __publicField$4(this, "id", uniqueId());
499
- __publicField$4(this, "customDescription", false);
500
- __publicField$4(this, "getId", () => this.id);
501
- __publicField$4(this, "addDescription", async () => {
509
+ __publicField$7(this, "role");
510
+ __publicField$7(this, "content");
511
+ __publicField$7(this, "id", uniqueId());
512
+ __publicField$7(this, "customDescription", false);
513
+ __publicField$7(this, "getId", () => this.id);
514
+ __publicField$7(this, "name", this.id);
515
+ __publicField$7(this, "value", "");
516
+ __publicField$7(this, "addDescription", async () => {
502
517
  const collector = new Collector();
503
518
  const collected = await collector.add(this.content).add(
504
519
  new collector.fields.textarea(
@@ -522,7 +537,7 @@ class AIMessageAttachments {
522
537
  this.customDescription = false;
523
538
  }
524
539
  });
525
- __publicField$4(this, "Component", (props) => /* @__PURE__ */ jsx(Box, { ...getVariant("layout.common.components.aiMessage"), children: /* @__PURE__ */ jsx(
540
+ __publicField$7(this, "Component", (props) => /* @__PURE__ */ jsx(Box, { ...getVariant("layout.common.components.aiMessage"), children: /* @__PURE__ */ jsx(
526
541
  this.content.Component,
527
542
  {
528
543
  onClose: props.closeButton ? this.close : void 0,
@@ -558,9 +573,6 @@ const handleFileUploadAsMessage = async (fileInputElement, chatController) => {
558
573
  }
559
574
  };
560
575
 
561
- function isMobile() {
562
- return /Mobi|Android|iPhone|iPad|iPod/i.test(navigator.userAgent);
563
- }
564
576
  const makeTextarea = (chatController) => {
565
577
  const NewTextarea = observer(
566
578
  ({
@@ -637,6 +649,7 @@ const makeTextarea = (chatController) => {
637
649
  ev.preventDefault();
638
650
  setDragging(true);
639
651
  };
652
+ const inputFileRef = useRef(null);
640
653
  const additionalButtons = [];
641
654
  additionalButtons.push({
642
655
  key: "prev",
@@ -665,20 +678,6 @@ const makeTextarea = (chatController) => {
665
678
  children: getLabel("btnAiDeleteMessages").text
666
679
  });
667
680
  }
668
- if (isMobile()) {
669
- additionalButtons.push({
670
- key: "camera",
671
- children: getLabel("btnOpenMobileCamera").text,
672
- onClick: () => {
673
- const gptUploadFile = document.getElementById(
674
- `gptUploadFile__${chatController.id}`
675
- );
676
- if (gptUploadFile) {
677
- gptUploadFile.click();
678
- }
679
- }
680
- });
681
- }
682
681
  return /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", flexDirection: "column", width: "100%" }, children: [
683
682
  /* @__PURE__ */ jsx(
684
683
  Box,
@@ -692,6 +691,7 @@ const makeTextarea = (chatController) => {
692
691
  paddingBottom: "6px",
693
692
  gap: spacing(3)
694
693
  },
694
+ ...getVariant("layout.common.chat.attachments"),
695
695
  children: chatController.attachments.getComponents()
696
696
  }
697
697
  ),
@@ -805,9 +805,9 @@ const makeTextarea = (chatController) => {
805
805
  variant: "icon-outline",
806
806
  isLoading: actualIsLoading,
807
807
  onClick: () => {
808
- document.getElementById(
809
- `gptUploadFile__${chatController.id}`
810
- ).click();
808
+ if (inputFileRef.current) {
809
+ inputFileRef.current.click();
810
+ }
811
811
  },
812
812
  icon: "Attach",
813
813
  id: "fileUpload",
@@ -835,9 +835,10 @@ const makeTextarea = (chatController) => {
835
835
  "input",
836
836
  {
837
837
  type: "file",
838
+ ref: inputFileRef,
838
839
  className: "gptUploadFile",
839
840
  multiple: true,
840
- capture: isMobile() ? "environment" : void 0,
841
+ accept: "image/*",
841
842
  id: `gptUploadFile__${chatController.id}`,
842
843
  onChange: (ev) => {
843
844
  if (1 == noNaN("a"))
@@ -871,10 +872,10 @@ const makeTextarea = (chatController) => {
871
872
  return NewTextarea;
872
873
  };
873
874
 
874
- var __defProp$3 = Object.defineProperty;
875
- var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
876
- var __publicField$3 = (obj, key, value) => {
877
- __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
875
+ var __defProp$6 = Object.defineProperty;
876
+ var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
877
+ var __publicField$6 = (obj, key, value) => {
878
+ __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
878
879
  return value;
879
880
  };
880
881
  var __accessCheck = (obj, member, msg) => {
@@ -899,22 +900,22 @@ var _promptsHistory, _internalAudioRecorder;
899
900
  class ChatController {
900
901
  constructor(id, welcomeMessage) {
901
902
  this.id = id;
902
- __publicField$3(this, "state", {
903
+ __publicField$6(this, "state", {
903
904
  current: new ChatMessage(),
904
905
  messages: []
905
906
  });
906
- __publicField$3(this, "components", {
907
+ __publicField$6(this, "components", {
907
908
  MessageHistory: observer(() => {
908
909
  return /* @__PURE__ */ jsx(Box, { ...getVariant("layout.common.chat.history"), className: "history", children: /* @__PURE__ */ jsx(AutoscrollContainer, { children: this.state.messages.map((current) => /* @__PURE__ */ jsx(current.Component, {}, current.id)) }) });
909
910
  }),
910
911
  Textarea: makeTextarea(this)
911
912
  });
912
913
  __privateAdd(this, _promptsHistory, []);
913
- __publicField$3(this, "currentHistoryIndex", -1);
914
+ __publicField$6(this, "currentHistoryIndex", -1);
914
915
  __privateAdd(this, _internalAudioRecorder, new AudioRecorder());
915
- __publicField$3(this, "audioBlob", new Promise(() => {
916
+ __publicField$6(this, "audioBlob", new Promise(() => {
916
917
  }));
917
- __publicField$3(this, "audioRecorder", {
918
+ __publicField$6(this, "audioRecorder", {
918
919
  start: () => {
919
920
  this.audioBlob = __privateGet(this, _internalAudioRecorder).start();
920
921
  },
@@ -936,7 +937,7 @@ class ChatController {
936
937
  record: 0,
937
938
  state: __privateGet(this, _internalAudioRecorder).state
938
939
  });
939
- __publicField$3(this, "history", {
940
+ __publicField$6(this, "history", {
940
941
  add: (message) => {
941
942
  this.currentHistoryIndex = -1;
942
943
  if (message === __privateGet(this, _promptsHistory)[__privateGet(this, _promptsHistory).length]) {
@@ -952,7 +953,7 @@ class ChatController {
952
953
  next: () => {
953
954
  let message = new ChatMessage();
954
955
  if (__privateGet(this, _promptsHistory)[this.currentHistoryIndex - 1])
955
- message = __privateGet(this, _promptsHistory)[--this.currentHistoryIndex].copy();
956
+ message = __privateGet(this, _promptsHistory)[--this.currentHistoryIndex].clone();
956
957
  else {
957
958
  this.currentHistoryIndex = -1;
958
959
  }
@@ -961,7 +962,7 @@ class ChatController {
961
962
  previous: () => {
962
963
  if (__privateGet(this, _promptsHistory)[this.currentHistoryIndex + 1]) {
963
964
  this.history.updateState(
964
- __privateGet(this, _promptsHistory)[++this.currentHistoryIndex].copy()
965
+ __privateGet(this, _promptsHistory)[++this.currentHistoryIndex].clone()
965
966
  );
966
967
  }
967
968
  },
@@ -973,7 +974,7 @@ class ChatController {
973
974
  },
974
975
  size: () => this.state.messages.length
975
976
  });
976
- __publicField$3(this, "messages", {
977
+ __publicField$6(this, "messages", {
977
978
  add: (message, idx) => {
978
979
  if (idx !== void 0 && idx !== null) {
979
980
  this.state.messages.splice(idx, 0, message);
@@ -985,7 +986,7 @@ class ChatController {
985
986
  this.state.messages = [];
986
987
  }
987
988
  });
988
- __publicField$3(this, "attachments", {
989
+ __publicField$6(this, "attachments", {
989
990
  add: (...aiMessage) => {
990
991
  this.state.current.attachments.push(...aiMessage);
991
992
  },
@@ -997,7 +998,10 @@ class ChatController {
997
998
  if (!this.state.current.message && this.attachments.size() < 1)
998
999
  this.currentHistoryIndex = -1;
999
1000
  },
1000
- getComponents: () => this.state.current.attachments.map((x) => /* @__PURE__ */ jsx(x.Component, { closeButton: true, canAddDescription: true }, x.getId())),
1001
+ getComponents: () => this.state.current.attachments.map((x) => {
1002
+ const c = x;
1003
+ return /* @__PURE__ */ jsx(c.Component, { closeButton: true, canAddDescription: true }, x.id);
1004
+ }),
1001
1005
  get: () => this.state.current.attachments,
1002
1006
  size: () => this.state.current.attachments.length
1003
1007
  });
@@ -1038,6 +1042,673 @@ class MultipleChoiceMessage extends ChatMessage {
1038
1042
  }
1039
1043
  }
1040
1044
 
1045
+ const FileAttachment = observer(
1046
+ ({
1047
+ attachment,
1048
+ onRemove
1049
+ }) => {
1050
+ return /* @__PURE__ */ jsxs(Box, { className: "file_box", children: [
1051
+ /* @__PURE__ */ jsx(FileIcon, { className: "file_box__icon", docName: attachment.name }),
1052
+ /* @__PURE__ */ jsx(Box, { className: "file_box__name", title: attachment.name, children: attachment.name }),
1053
+ onRemove && /* @__PURE__ */ jsx(
1054
+ IconButton,
1055
+ {
1056
+ icon: "Close",
1057
+ className: "file_box__remove",
1058
+ onClick: onRemove,
1059
+ variant: "icon-only"
1060
+ }
1061
+ )
1062
+ ] });
1063
+ }
1064
+ );
1065
+
1066
+ const Attachments = observer(
1067
+ ({
1068
+ attachments,
1069
+ onRemove
1070
+ }) => {
1071
+ if (!attachments.length)
1072
+ return null;
1073
+ return /* @__PURE__ */ jsx(
1074
+ Box,
1075
+ {
1076
+ className: "attachments",
1077
+ ...getVariant("layout.common.newChat.attachments"),
1078
+ children: attachments.map((x) => /* @__PURE__ */ jsx(
1079
+ FileAttachment,
1080
+ {
1081
+ attachment: x,
1082
+ onRemove: onRemove ? () => onRemove(x) : void 0
1083
+ },
1084
+ x.id
1085
+ ))
1086
+ }
1087
+ );
1088
+ }
1089
+ );
1090
+
1091
+ const Message = observer(
1092
+ ({
1093
+ className,
1094
+ type,
1095
+ id,
1096
+ message,
1097
+ attachments,
1098
+ reference
1099
+ }) => {
1100
+ return /* @__PURE__ */ jsxs(
1101
+ Box,
1102
+ {
1103
+ as: "pre",
1104
+ className: `history_message ${className || ""} ${type}`,
1105
+ children: [
1106
+ /* @__PURE__ */ jsx(
1107
+ Box,
1108
+ {
1109
+ className: "history_message__content",
1110
+ ...typeof message === "string" ? { dangerouslySetInnerHTML: { __html: message } } : { children: message }
1111
+ }
1112
+ ),
1113
+ attachments.length > 0 && /* @__PURE__ */ jsx(Attachments, { attachments }),
1114
+ reference && /* @__PURE__ */ jsx(Box, { className: "history_message__references", children: reference })
1115
+ ]
1116
+ },
1117
+ id
1118
+ );
1119
+ }
1120
+ );
1121
+
1122
+ const History = observer(({ messages }) => {
1123
+ let currentType = "";
1124
+ return /* @__PURE__ */ jsx(AutoscrollContainer, { children: /* @__PURE__ */ jsx(
1125
+ Box,
1126
+ {
1127
+ ...getVariant("layout.common.newChat.history"),
1128
+ className: "chat_history",
1129
+ children: messages.map((current, i) => {
1130
+ let first = false;
1131
+ let last = false;
1132
+ if (currentType !== current.messageType) {
1133
+ currentType = current.messageType;
1134
+ first = true;
1135
+ }
1136
+ if (i === messages.length - 1 || messages[i + 1].messageType !== current.messageType) {
1137
+ last = true;
1138
+ }
1139
+ return /* @__PURE__ */ jsx(
1140
+ Message,
1141
+ {
1142
+ className: first ? "first" : last ? "last" : void 0,
1143
+ type: current.messageType,
1144
+ id: String(current.id),
1145
+ attachments: current.attachments,
1146
+ reference: current.reference,
1147
+ message: current.message
1148
+ }
1149
+ );
1150
+ })
1151
+ }
1152
+ ) });
1153
+ });
1154
+
1155
+ function getBase64FromFile(f) {
1156
+ return ((f2) => new Promise((resolve, reject) => {
1157
+ const reader = new FileReader();
1158
+ reader.readAsDataURL(f2);
1159
+ reader.onload = () => resolve(reader.result);
1160
+ reader.onerror = () => reject();
1161
+ }))(f);
1162
+ }
1163
+ function getBase64FromBlob(b) {
1164
+ return ((blob) => new Promise((resolve, reject) => {
1165
+ const reader = new FileReader();
1166
+ reader.onloadend = () => {
1167
+ const base64String = reader.result;
1168
+ resolve(base64String);
1169
+ };
1170
+ reader.onerror = reject;
1171
+ reader.readAsDataURL(blob);
1172
+ }))(b);
1173
+ }
1174
+
1175
+ const TextArea = observer(
1176
+ ({
1177
+ isLoading,
1178
+ isRecording,
1179
+ onSubmit,
1180
+ onChange,
1181
+ onClearHistory,
1182
+ onClearAttachments,
1183
+ onClearMessage,
1184
+ onAttach,
1185
+ onRecord,
1186
+ onVideoRecord,
1187
+ onPrev,
1188
+ onNext,
1189
+ hideDeleteButton,
1190
+ value,
1191
+ id
1192
+ }) => {
1193
+ const fileInputRef = useRef(null);
1194
+ const searchControlsRef = useRef(null);
1195
+ const recordButton = /* @__PURE__ */ jsx(
1196
+ IconButton,
1197
+ {
1198
+ variant: "icon-only",
1199
+ onClick: onRecord,
1200
+ disabled: isLoading && !isRecording,
1201
+ sx: {
1202
+ color: isRecording ? "red" : void 0
1203
+ },
1204
+ icon: isRecording ? "Stop" : "Microphone",
1205
+ id: "transcribeAudio",
1206
+ iconSize: "Sm",
1207
+ title: getLabel("lblAiRecordAudio").text
1208
+ }
1209
+ );
1210
+ const handleAttachments = async (ev) => {
1211
+ if (ev.target.files) {
1212
+ for await (const f of ev.target.files) {
1213
+ const base64 = await getBase64FromFile(f);
1214
+ onAttach({
1215
+ value: base64,
1216
+ name: f.name,
1217
+ id: f.name
1218
+ });
1219
+ }
1220
+ }
1221
+ };
1222
+ const iconsList = [
1223
+ {
1224
+ icon: "ArrowLeft",
1225
+ children: getLabel("btnAiPrevious").text,
1226
+ title: getLabel("btnAiPrevious").text,
1227
+ onClick: onPrev,
1228
+ key: "0"
1229
+ },
1230
+ {
1231
+ icon: "ArrowRight",
1232
+ children: getLabel("btnAiNext").text,
1233
+ title: getLabel("btnAiNext").text,
1234
+ onClick: onNext,
1235
+ key: "1"
1236
+ },
1237
+ {
1238
+ children: getLabel("btnUpload").text,
1239
+ title: getLabel("btnUpload").text,
1240
+ icon: "File",
1241
+ onClick: () => fileInputRef.current?.click(),
1242
+ key: "2"
1243
+ },
1244
+ {
1245
+ title: getLabel("lblOpenCamera").text,
1246
+ children: getLabel("lblOpenCamera").text,
1247
+ icon: "Camera",
1248
+ onClick: onVideoRecord,
1249
+ key: "3"
1250
+ },
1251
+ {
1252
+ title: getLabel("lblAiRecordAudio").text,
1253
+ children: getLabel("lblAiRecordAudio").text,
1254
+ key: "4",
1255
+ onClick: (event) => onRecord(event),
1256
+ icon: isRecording ? "Stop" : "Microphone"
1257
+ },
1258
+ ...hideDeleteButton ? [] : [
1259
+ {
1260
+ icon: "Trash",
1261
+ onClick: onClearHistory,
1262
+ key: "5",
1263
+ children: getLabel("btnAiDeleteMessages").text,
1264
+ title: getLabel("btnAiDeleteMessages").text
1265
+ },
1266
+ {
1267
+ icon: "Erase",
1268
+ title: getLabel("btnAiDelete").text,
1269
+ children: getLabel("btnAiDelete").text,
1270
+ onClick: () => {
1271
+ onClearMessage();
1272
+ onClearAttachments();
1273
+ },
1274
+ key: "6"
1275
+ }
1276
+ ]
1277
+ ];
1278
+ return /* @__PURE__ */ jsxs(
1279
+ Form,
1280
+ {
1281
+ id,
1282
+ onSubmit: (ev) => {
1283
+ ev.preventDefault();
1284
+ onSubmit();
1285
+ },
1286
+ className: "search_controls",
1287
+ ...getVariant("layout.common.newChat.form"),
1288
+ children: [
1289
+ /* @__PURE__ */ jsx(
1290
+ Textarea,
1291
+ {
1292
+ ref: searchControlsRef,
1293
+ "aria-label": (
1294
+ /** TODO: Crear etiqueta para búsqueda */
1295
+ "Frase de b\xFAsqueda"
1296
+ ),
1297
+ value,
1298
+ className: "searchTextArea",
1299
+ onChange: (ev) => onChange(ev.target.value),
1300
+ onKeyDown: (ev) => {
1301
+ if (ev.code === "Enter" && !ev.shiftKey) {
1302
+ ev.preventDefault();
1303
+ ev.target.closest("form").querySelector('[type="submit"]').click();
1304
+ }
1305
+ }
1306
+ }
1307
+ ),
1308
+ isRecording && recordButton,
1309
+ /* @__PURE__ */ jsx(
1310
+ "input",
1311
+ {
1312
+ ref: fileInputRef,
1313
+ id: "invisible__attach__file",
1314
+ type: "file",
1315
+ multiple: true,
1316
+ onChange: handleAttachments,
1317
+ sx: { display: "none" }
1318
+ }
1319
+ ),
1320
+ /* @__PURE__ */ jsx(
1321
+ IconButton,
1322
+ {
1323
+ disabled: isLoading,
1324
+ icon: "Ellipsis",
1325
+ variant: "icon-only",
1326
+ iconSize: "Sm",
1327
+ onClick: (ev) => {
1328
+ ApiaUtil.instance.menu.open({
1329
+ menuProps: {
1330
+ anchorPoint: { x: ev.clientX, y: ev.clientY }
1331
+ },
1332
+ items: iconsList
1333
+ });
1334
+ }
1335
+ }
1336
+ ),
1337
+ /* @__PURE__ */ jsx(
1338
+ IconButton,
1339
+ {
1340
+ className: "SearchButton",
1341
+ isLoading,
1342
+ icon: "ArrowRight",
1343
+ variant: "icon-only",
1344
+ iconSize: "Sm",
1345
+ title: getLabel("btnBus").title,
1346
+ type: "submit"
1347
+ }
1348
+ )
1349
+ ]
1350
+ }
1351
+ );
1352
+ }
1353
+ );
1354
+
1355
+ var __defProp$5 = Object.defineProperty;
1356
+ var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1357
+ var __publicField$5 = (obj, key, value) => {
1358
+ __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
1359
+ return value;
1360
+ };
1361
+ class CameraController {
1362
+ constructor() {
1363
+ __publicField$5(this, "state", {
1364
+ videoStream: null,
1365
+ isOpen: false
1366
+ });
1367
+ __publicField$5(this, "currentCapture", null);
1368
+ __publicField$5(this, "videoElement");
1369
+ __publicField$5(this, "Component", () => {
1370
+ return /* @__PURE__ */ jsx(
1371
+ "video",
1372
+ {
1373
+ ref: (el) => {
1374
+ if (el) {
1375
+ el.srcObject = this.videoElement.srcObject;
1376
+ el.autoplay = true;
1377
+ el.playsInline = true;
1378
+ }
1379
+ },
1380
+ style: { width: "100%", height: "auto" }
1381
+ }
1382
+ );
1383
+ });
1384
+ makeObservable(this, {
1385
+ state: observable,
1386
+ openCamera: action,
1387
+ closeCamera: action
1388
+ });
1389
+ this.videoElement = document.createElement("video");
1390
+ this.videoElement.autoplay = true;
1391
+ this.videoElement.playsInline = true;
1392
+ }
1393
+ async openCamera() {
1394
+ try {
1395
+ const stream = await navigator.mediaDevices.getUserMedia({ video: true });
1396
+ this.state.videoStream = stream;
1397
+ this.videoElement.srcObject = stream;
1398
+ this.state.isOpen = true;
1399
+ ApiaUtil.instance.modals.open({
1400
+ children: /* @__PURE__ */ jsx(this.Component, {}),
1401
+ onConfirm: () => {
1402
+ this.closeCamera();
1403
+ },
1404
+ onClose: () => {
1405
+ this.state.isOpen = false;
1406
+ this.closeCamera();
1407
+ }
1408
+ });
1409
+ } catch (error) {
1410
+ console.error("Error while accessing the camera:", error);
1411
+ this.state.isOpen = false;
1412
+ this.closeCamera();
1413
+ }
1414
+ }
1415
+ async closeCamera() {
1416
+ if (!this.videoElement.srcObject)
1417
+ return null;
1418
+ const canvas = document.createElement("canvas");
1419
+ canvas.width = this.videoElement.videoWidth;
1420
+ canvas.height = this.videoElement.videoHeight;
1421
+ const ctx = canvas.getContext("2d");
1422
+ if (ctx)
1423
+ ctx.drawImage(this.videoElement, 0, 0, canvas.width, canvas.height);
1424
+ this.currentCapture = await new Promise((resolve) => {
1425
+ canvas.toBlob((blob) => {
1426
+ if (blob) {
1427
+ const file = new File([blob], "captured_image.jpg", {
1428
+ type: "image/jpeg"
1429
+ });
1430
+ resolve(file);
1431
+ } else {
1432
+ resolve(null);
1433
+ }
1434
+ }, "image/jpeg");
1435
+ }).finally(() => {
1436
+ this.state.videoStream?.getTracks().forEach((track) => track.stop());
1437
+ this.state.videoStream = null;
1438
+ this.videoElement.srcObject = null;
1439
+ this.state.isOpen = false;
1440
+ });
1441
+ }
1442
+ pop() {
1443
+ const returnFile = this.currentCapture;
1444
+ this.currentCapture = null;
1445
+ return returnFile;
1446
+ }
1447
+ }
1448
+
1449
+ var __defProp$4 = Object.defineProperty;
1450
+ var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1451
+ var __publicField$4 = (obj, key, value) => {
1452
+ __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
1453
+ return value;
1454
+ };
1455
+ class ChatController2 {
1456
+ constructor(props, onMessageSubmit, id, onMessageResponse) {
1457
+ this.onMessageSubmit = onMessageSubmit;
1458
+ this.id = id;
1459
+ this.onMessageResponse = onMessageResponse;
1460
+ __publicField$4(this, "currentIndex", 0);
1461
+ __publicField$4(this, "state", {
1462
+ isVisible: false,
1463
+ isLoading: false,
1464
+ canRecord: true,
1465
+ canAttach: true,
1466
+ canAddSystemMessage: true,
1467
+ canAddUserMessage: true,
1468
+ canShowSystemMessage: true,
1469
+ canShowUserMessage: true,
1470
+ hideDeleteButton: false,
1471
+ maxAttachmentsSize: 100,
1472
+ messages: [],
1473
+ currentMessage: new ChatMessage("", "user")
1474
+ });
1475
+ __publicField$4(this, "internalAudioRecorder", new AudioRecorder());
1476
+ __publicField$4(this, "internalCameraRecorder", new CameraController());
1477
+ __publicField$4(this, "maxId", 0);
1478
+ __publicField$4(this, "audioRecorder", {
1479
+ start: () => {
1480
+ this.internalAudioRecorder.start().then(async (blob) => {
1481
+ this.state.currentMessage.attachments.push({
1482
+ id: String(this.maxId++),
1483
+ name: `userRecord_${this.audioRecorder.record++}.wav`,
1484
+ value: await getBase64FromBlob(blob)
1485
+ });
1486
+ });
1487
+ },
1488
+ stop: async () => {
1489
+ this.internalAudioRecorder.stop();
1490
+ },
1491
+ record: 0,
1492
+ state: this.internalAudioRecorder.state
1493
+ });
1494
+ __publicField$4(this, "History", observer(() => /* @__PURE__ */ jsx(History, { messages: this.state.messages })));
1495
+ __publicField$4(this, "Attachments", observer(() => /* @__PURE__ */ jsx(
1496
+ Attachments,
1497
+ {
1498
+ attachments: this.state.currentMessage.attachments,
1499
+ onRemove: (a) => {
1500
+ this.removeAttachment(a);
1501
+ }
1502
+ }
1503
+ )));
1504
+ __publicField$4(this, "TextArea", observer(() => /* @__PURE__ */ jsx(
1505
+ TextArea,
1506
+ {
1507
+ id: this.id,
1508
+ value: this.state.currentMessage.message,
1509
+ isLoading: this.state.isLoading,
1510
+ isRecording: this.internalAudioRecorder.state.recording,
1511
+ onChange: (ev) => {
1512
+ this.state.currentMessage.message = ev;
1513
+ },
1514
+ onSubmit: async () => {
1515
+ if (this.state.currentMessage.message || this.state.currentMessage.attachments.length > 0) {
1516
+ this.state.isLoading = true;
1517
+ if (this.state.canAddUserMessage) {
1518
+ this.addMessage(this.state.currentMessage);
1519
+ }
1520
+ const response = await this.onMessageSubmit({
1521
+ message: this.state.currentMessage
1522
+ });
1523
+ if (this.onMessageResponse) {
1524
+ await this.onMessageResponse(response);
1525
+ }
1526
+ this.state.isLoading = false;
1527
+ if (this.state.canAddSystemMessage && response.responseMessage) {
1528
+ this.addMessage(response.responseMessage);
1529
+ }
1530
+ this.state.currentMessage = new ChatMessage("", "user");
1531
+ }
1532
+ },
1533
+ onClearHistory: () => {
1534
+ this.clearHistory();
1535
+ },
1536
+ onClearAttachments: () => {
1537
+ this.state.currentMessage.attachments = [];
1538
+ },
1539
+ onClearMessage: () => {
1540
+ this.clearMessage();
1541
+ },
1542
+ onAttach: async (ev) => {
1543
+ this.state.currentMessage.attachments.push({
1544
+ ...ev,
1545
+ id: String(this.maxId++)
1546
+ });
1547
+ },
1548
+ onRecord: () => {
1549
+ !this.internalAudioRecorder.state.recording ? this.audioRecorder.start() : this.audioRecorder.stop();
1550
+ },
1551
+ onVideoRecord: async () => {
1552
+ !this.internalCameraRecorder.state.isOpen && await this.internalCameraRecorder.openCamera();
1553
+ await new Promise((resolve, _) => {
1554
+ const checkCapture = async () => {
1555
+ if (!this.internalCameraRecorder.state.isOpen) {
1556
+ const capture = this.internalCameraRecorder.pop();
1557
+ if (capture) {
1558
+ this.state.currentMessage.attachments.push({
1559
+ id: String(this.maxId++),
1560
+ name: capture.name,
1561
+ value: await getBase64FromFile(capture)
1562
+ });
1563
+ return resolve();
1564
+ }
1565
+ } else {
1566
+ requestAnimationFrame(checkCapture);
1567
+ }
1568
+ };
1569
+ checkCapture();
1570
+ });
1571
+ },
1572
+ onPrev: () => {
1573
+ this.prevMessage();
1574
+ },
1575
+ onNext: () => {
1576
+ this.nextMessage();
1577
+ },
1578
+ hideDeleteButton: this.state.hideDeleteButton,
1579
+ attachments: []
1580
+ }
1581
+ )));
1582
+ __publicField$4(this, "Renderer", () => /* @__PURE__ */ jsxs(
1583
+ Box,
1584
+ {
1585
+ ...getVariant("layout.common.chat.controller"),
1586
+ className: "chat_controller",
1587
+ children: [
1588
+ /* @__PURE__ */ jsx(this.History, {}),
1589
+ /* @__PURE__ */ jsx(this.Attachments, {}),
1590
+ /* @__PURE__ */ jsx(this.TextArea, {})
1591
+ ]
1592
+ }
1593
+ ));
1594
+ this.state = Object.assign({}, this.state, props);
1595
+ makeObservable(this, { state: observable });
1596
+ }
1597
+ removeMessage(idx) {
1598
+ this.state.messages = this.state.messages.filter((_, i) => i !== idx);
1599
+ }
1600
+ addMessage(message) {
1601
+ this.state.messages.push(message);
1602
+ }
1603
+ clearHistory() {
1604
+ this.state.messages = [];
1605
+ }
1606
+ clearMessage() {
1607
+ this.state.currentMessage = new ChatMessage("", "user");
1608
+ }
1609
+ removeAttachment(attachment) {
1610
+ this.state.currentMessage.attachments = this.state.currentMessage.attachments.filter((x) => x !== attachment);
1611
+ }
1612
+ isValidToShow(message) {
1613
+ return message && (message.messageType === "system" && this.state.canShowSystemMessage || message.messageType === "user" && this.state.canShowUserMessage);
1614
+ }
1615
+ nextMessage() {
1616
+ let newCurrentMessage = void 0;
1617
+ let i = this.currentIndex;
1618
+ const n = this.state.messages.length;
1619
+ if (n === 0) {
1620
+ return;
1621
+ }
1622
+ while (!newCurrentMessage) {
1623
+ if (i === -1 || i === n - 1) {
1624
+ newCurrentMessage = this.state.messages[0];
1625
+ i = 0;
1626
+ } else if (i < n - 1) {
1627
+ newCurrentMessage = this.state.messages[i + 1];
1628
+ i++;
1629
+ }
1630
+ if (this.isValidToShow(newCurrentMessage)) {
1631
+ this.state.currentMessage = newCurrentMessage.clone();
1632
+ break;
1633
+ } else {
1634
+ newCurrentMessage = void 0;
1635
+ }
1636
+ if (i === this.currentIndex) {
1637
+ break;
1638
+ }
1639
+ }
1640
+ this.currentIndex = i;
1641
+ }
1642
+ prevMessage() {
1643
+ let newCurrentMessage = void 0;
1644
+ let i = this.currentIndex;
1645
+ const n = this.state.messages.length;
1646
+ if (n === 0) {
1647
+ return;
1648
+ }
1649
+ while (!newCurrentMessage) {
1650
+ if (i === -1 || i === 0) {
1651
+ newCurrentMessage = this.state.messages[n - 1];
1652
+ i = n - 1;
1653
+ } else if (i > 0) {
1654
+ newCurrentMessage = this.state.messages[i - 1];
1655
+ i--;
1656
+ }
1657
+ if (this.isValidToShow(newCurrentMessage)) {
1658
+ this.state.currentMessage = newCurrentMessage.clone();
1659
+ break;
1660
+ } else {
1661
+ newCurrentMessage = void 0;
1662
+ }
1663
+ if (i === this.currentIndex) {
1664
+ break;
1665
+ }
1666
+ }
1667
+ this.currentIndex = i;
1668
+ }
1669
+ }
1670
+
1671
+ var __defProp$3 = Object.defineProperty;
1672
+ var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1673
+ var __publicField$3 = (obj, key, value) => {
1674
+ __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
1675
+ return value;
1676
+ };
1677
+ class FloatingChatController extends ChatController2 {
1678
+ constructor(props, onMessageSubmit, id, onMessageResponse) {
1679
+ super(props, onMessageSubmit, id, onMessageResponse);
1680
+ __publicField$3(this, "Window", observer(() => {
1681
+ return /* @__PURE__ */ jsx(
1682
+ IconButton,
1683
+ {
1684
+ icon: "Magic",
1685
+ size: "Md",
1686
+ variant: "icon-outline",
1687
+ onClick: () => {
1688
+ this.state.isVisible = true;
1689
+ this.open();
1690
+ }
1691
+ }
1692
+ );
1693
+ }));
1694
+ makeObservable({ open: action });
1695
+ }
1696
+ open() {
1697
+ ApiaUtil.instance.modals.open({
1698
+ variant: "layout.common.chat.assistant.floatingAssistant",
1699
+ defaultPosition: {
1700
+ bottom: "10px",
1701
+ right: "50px"
1702
+ },
1703
+ draggable: true,
1704
+ children: /* @__PURE__ */ jsx(this.Renderer, {}),
1705
+ onClose: () => {
1706
+ this.state.isVisible = false;
1707
+ }
1708
+ });
1709
+ }
1710
+ }
1711
+
1041
1712
  var __defProp$2 = Object.defineProperty;
1042
1713
  var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1043
1714
  var __publicField$2 = (obj, key, value) => {
@@ -1504,5 +2175,5 @@ function getImagesWithDescription({
1504
2175
  });
1505
2176
  }
1506
2177
 
1507
- export { AIMessageAttachments, AutoscrollContainer, ChatController, ChatMessage, DashboardsRoutinesGeneration, MultipleChoiceMessage, ResponseStream, RoutinesGeneration, getImageFromDisk, getImagesFromDisk, getImagesWithDescription };
2178
+ export { AIFileContent, AIMessageAttachments, AutoscrollContainer, ChatController, ChatController2, ChatMessage, DashboardsRoutinesGeneration, FloatingChatController, MultipleChoiceMessage, ResponseStream, RoutinesGeneration, getImageFromDisk, getImagesFromDisk, getImagesWithDescription };
1508
2179
  //# sourceMappingURL=index.js.map