@apia/ai 4.0.9 → 4.0.13

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.
@@ -0,0 +1,1898 @@
1
+ import { jsx, jsxs, Fragment } from '@apia/theme/jsx-runtime';
2
+ import { Box, getVariant, useBreakpointIndex, Textarea, Paragraph } from '@apia/theme';
3
+ import { useRef, useCallback, useState, createContext } from 'react';
4
+ import { IconButton, SimpleButton, ApiaUtil, FiltersStore, SortableList, SortableListItem } from '@apia/components';
5
+ import { getLabel, noNaN, AudioRecorder, EventEmitter } from '@apia/util';
6
+ import { makeObservable, observable, action, toJS, makeAutoObservable } from 'mobx';
7
+ import { observer } from 'mobx-react-lite';
8
+ import { CollectorField, Collector } from '@apia/validations';
9
+ import { uniqueId } from '@apia/notifications';
10
+ import { FileIcon } from '@apia/icons';
11
+ import { ApiaApi, makeApiaUrl, parseSuccessfulResponse } from '@apia/api';
12
+ import axios from 'axios';
13
+
14
+ const AutoscrollContainer = ({ children }) => {
15
+ const observer = useRef(null);
16
+ const unsuscribe = useRef(null);
17
+ const isFullScrolled = useRef(false);
18
+ const hasInited = useRef(false);
19
+ const ref = useCallback((el) => {
20
+ if (!el)
21
+ return;
22
+ if (!hasInited.current) {
23
+ hasInited.current = true;
24
+ el.scrollTo({
25
+ top: el.getBoundingClientRect().height,
26
+ behavior: "auto"
27
+ });
28
+ isFullScrolled.current = true;
29
+ }
30
+ observer.current?.disconnect();
31
+ unsuscribe.current?.();
32
+ observer.current = new MutationObserver(([mutation]) => {
33
+ if (mutation && mutation.target instanceof HTMLElement && mutation.target === el) {
34
+ if (isFullScrolled.current && mutation.target.scrollTop !== mutation.target.scrollHeight - mutation.target.offsetHeight) {
35
+ mutation.target.scrollTo({
36
+ top: mutation.target.scrollHeight,
37
+ behavior: "smooth"
38
+ });
39
+ }
40
+ }
41
+ });
42
+ observer.current.observe(el, { childList: true, subtree: true });
43
+ const handleScroll = (ev) => {
44
+ if (ev.target === el && el instanceof HTMLElement) {
45
+ setTimeout(() => {
46
+ isFullScrolled.current = Math.abs(el.scrollTop - (el.scrollHeight - el.offsetHeight)) < 150;
47
+ }, 100);
48
+ }
49
+ };
50
+ el.addEventListener("scroll", handleScroll);
51
+ unsuscribe.current = () => {
52
+ el.removeEventListener("scroll", handleScroll);
53
+ };
54
+ }, []);
55
+ return /* @__PURE__ */ jsx(
56
+ Box,
57
+ {
58
+ ...getVariant("layout.common.components.autoscrollContainer"),
59
+ className: "autoscrollContainer",
60
+ ref,
61
+ children
62
+ }
63
+ );
64
+ };
65
+
66
+ function isImageFile(file) {
67
+ const IMAGE_EXTENSIONS = [
68
+ "jpg",
69
+ "jpeg",
70
+ "png",
71
+ "gif",
72
+ "bmp",
73
+ "webp",
74
+ "tiff",
75
+ "svg",
76
+ "jfif"
77
+ ];
78
+ return IMAGE_EXTENSIONS.includes(file.name.split(".").pop());
79
+ }
80
+ function getImageOcrMaker(lang) {
81
+ return new class ImageOcrMaker {
82
+ async processFile(file, onProgress) {
83
+ const tesseract = await import('tesseract.js');
84
+ const worker = await tesseract.createWorker(lang, 1, {
85
+ logger(arg) {
86
+ onProgress?.(arg.progress * 100);
87
+ }
88
+ });
89
+ const result = (await worker.recognize(file)).data.text;
90
+ return [result];
91
+ }
92
+ willProcessFile(file) {
93
+ return isImageFile(file);
94
+ }
95
+ }();
96
+ }
97
+
98
+ function isPdfFile(file) {
99
+ const IMAGE_EXTENSIONS = ["pdf"];
100
+ return IMAGE_EXTENSIONS.includes(file.name.split(".").pop());
101
+ }
102
+ function getPdfReader() {
103
+ return new class PdfReader {
104
+ async processFile(file, onProgress) {
105
+ onProgress?.(0);
106
+ const { getDocument, GlobalWorkerOptions } = await import('pdfjs-dist');
107
+ async function getPdfTextFromArrayBuffer(buffer) {
108
+ GlobalWorkerOptions.workerSrc = "../includes/pdf.worker.min.js";
109
+ const pdf = await getDocument({ data: buffer }).promise;
110
+ const pages = [];
111
+ for (let i = 1; i <= pdf.numPages; i++) {
112
+ const page = await pdf.getPage(i);
113
+ const textContent = await page.getTextContent();
114
+ pages.push(
115
+ textContent.items.map((item) => item.str).join(" ")
116
+ );
117
+ }
118
+ return pages;
119
+ }
120
+ return new Promise((resolve) => {
121
+ const reader = new FileReader();
122
+ reader.onload = async function(event) {
123
+ if (!event.target?.result) {
124
+ alert("Error al leer el archivo.");
125
+ return;
126
+ }
127
+ const buffer = event.target.result;
128
+ const text = await getPdfTextFromArrayBuffer(buffer);
129
+ onProgress?.(100);
130
+ resolve(text);
131
+ };
132
+ reader.readAsArrayBuffer(file);
133
+ });
134
+ }
135
+ willProcessFile(file) {
136
+ return isPdfFile(file);
137
+ }
138
+ }();
139
+ }
140
+
141
+ class WrongFormatError extends Error {
142
+ constructor(fileName) {
143
+ super(`File format not supported: ${fileName}`);
144
+ }
145
+ }
146
+ function useHandleFileUpload({
147
+ onContent
148
+ }) {
149
+ const [progress, setProgress] = useState(100);
150
+ const handleFileUpload = useCallback(
151
+ async (ev) => {
152
+ setProgress(0);
153
+ const imageProcessor = getImageOcrMaker("spa");
154
+ const pdfProcessor = getPdfReader();
155
+ await (async () => {
156
+ const obtainedText = [];
157
+ const files = ev.target.files;
158
+ const filesLength = ev.target.files?.length ?? 0;
159
+ if (files) {
160
+ for (let i = 0; i < filesLength; i++) {
161
+ const file = files[i];
162
+ if (!isImageFile(file) && !isPdfFile(file)) {
163
+ setProgress(100);
164
+ throw new WrongFormatError(file.name);
165
+ }
166
+ const handleProgress = (progress2) => {
167
+ setProgress(
168
+ i / filesLength * 100 + 1 / filesLength * 100 * (progress2 / 100)
169
+ );
170
+ };
171
+ let result = "";
172
+ if (imageProcessor.willProcessFile(file)) {
173
+ try {
174
+ result = (await imageProcessor.processFile(file, handleProgress))[0];
175
+ } catch (e) {
176
+ console.error(e);
177
+ }
178
+ } else if (pdfProcessor.willProcessFile(file)) {
179
+ result = (await pdfProcessor.processFile(file, handleProgress)).join("\n\n");
180
+ }
181
+ if (result) {
182
+ obtainedText.push(result);
183
+ }
184
+ setProgress((i + 1) / filesLength * 100);
185
+ }
186
+ }
187
+ onContent(obtainedText);
188
+ })();
189
+ ev.target.value = "";
190
+ },
191
+ [onContent]
192
+ );
193
+ return { progress, handleFileUpload };
194
+ }
195
+
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
+ return value;
201
+ };
202
+ let maxId = 0;
203
+ class ChatMessage {
204
+ constructor(message = "", messageType = "user", attachments = [], reference = null) {
205
+ this.message = message;
206
+ this.messageType = messageType;
207
+ this.attachments = attachments;
208
+ this.reference = reference;
209
+ __publicField$a(this, "id");
210
+ __publicField$a(this, "copy", () => new ChatMessage(this.message, this.messageType, this.attachments));
211
+ __publicField$a(this, "Component", observer(() => {
212
+ return /* @__PURE__ */ jsxs(
213
+ Box,
214
+ {
215
+ as: "pre",
216
+ className: `history__message ${this.messageType}`,
217
+ children: [
218
+ /* @__PURE__ */ jsx(
219
+ Box,
220
+ {
221
+ className: "text_wrapper",
222
+ ...typeof this.message === "string" ? { dangerouslySetInnerHTML: { __html: this.message } } : { children: this.message }
223
+ }
224
+ ),
225
+ /* @__PURE__ */ jsx(Box, { className: "additionalContent_wrapper", children: this.attachments.map((x) => /* @__PURE__ */ jsx(x.Component, {}, x.getId())) }),
226
+ this.reference && /* @__PURE__ */ jsx(Box, { children: this.reference })
227
+ ]
228
+ },
229
+ this.id
230
+ );
231
+ }));
232
+ this.id = maxId++;
233
+ if (messageType === "response")
234
+ this.messageType = "system";
235
+ if (typeof message === "string")
236
+ this.message = this.parseMessage(message);
237
+ makeObservable(this, {
238
+ attachments: observable,
239
+ message: observable,
240
+ messageType: observable,
241
+ reference: observable
242
+ });
243
+ }
244
+ parseMessage(message) {
245
+ let result = message;
246
+ result = result.replaceAll("[strong]", "<strong>");
247
+ result = result.replaceAll("[/strong]", "</strong>");
248
+ return result;
249
+ }
250
+ }
251
+
252
+ var __defProp$9 = Object.defineProperty;
253
+ var __defNormalProp$9 = (obj, key, value) => key in obj ? __defProp$9(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
254
+ var __publicField$9 = (obj, key, value) => {
255
+ __defNormalProp$9(obj, typeof key !== "symbol" ? key + "" : key, value);
256
+ return value;
257
+ };
258
+ class AIContent extends CollectorField {
259
+ constructor(content) {
260
+ super(uniqueId(), "");
261
+ __publicField$9(this, "type", "aiContent");
262
+ __publicField$9(this, "content");
263
+ __publicField$9(this, "Component", () => {
264
+ return /* @__PURE__ */ jsx(Box, { variant: "layout.common.components.aiMessage.textBox", children: /* @__PURE__ */ jsx(Box, { variant: "layout.common.components.aiMessage.textSnippet", children: this.content }) });
265
+ });
266
+ this.content = content;
267
+ }
268
+ }
269
+
270
+ const AIFileContentAllowedExtensions = {
271
+ svg: "svg",
272
+ png: "png",
273
+ jpg: "jpg",
274
+ jpeg: "jpeg",
275
+ txt: "txt",
276
+ doc: "doc",
277
+ pdf: "pdf",
278
+ docx: "docx",
279
+ csv: "csv",
280
+ xlsx: "xlsx",
281
+ xls: "xls",
282
+ mp3: "mp3",
283
+ wav: "wav"
284
+ };
285
+ var FileType = /* @__PURE__ */ ((FileType2) => {
286
+ FileType2["DOCUMENT"] = "DOCUMENT";
287
+ FileType2["IMAGE"] = "IMAGE";
288
+ FileType2["AUDIO"] = "AUDIO";
289
+ FileType2["SHEET"] = "SHEET";
290
+ return FileType2;
291
+ })(FileType || {});
292
+ var AIMessageRole = /* @__PURE__ */ ((AIMessageRole2) => {
293
+ AIMessageRole2["USER"] = "USER";
294
+ AIMessageRole2["SYSTEM"] = "SYSTEM";
295
+ return AIMessageRole2;
296
+ })(AIMessageRole || {});
297
+
298
+ var __defProp$8 = Object.defineProperty;
299
+ var __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
300
+ var __publicField$8 = (obj, key, value) => {
301
+ __defNormalProp$8(obj, typeof key !== "symbol" ? key + "" : key, value);
302
+ return value;
303
+ };
304
+ const _AIFileContent = class _AIFileContent extends AIContent {
305
+ constructor(fileUrl, fileName, f, error) {
306
+ const extension = _AIFileContent.getExtensionFromFileName(fileName);
307
+ super();
308
+ __publicField$8(this, "type");
309
+ __publicField$8(this, "fileUrl");
310
+ __publicField$8(this, "fileName");
311
+ __publicField$8(this, "extension");
312
+ __publicField$8(this, "__file");
313
+ __publicField$8(this, "__error");
314
+ __publicField$8(this, "overrideSize");
315
+ __publicField$8(this, "inferContent", () => {
316
+ return `You must collect information contained in this ${this.type} as help to build your tool choice.`;
317
+ });
318
+ __publicField$8(this, "inferExtension", (extension) => {
319
+ switch (extension) {
320
+ case AIFileContentAllowedExtensions.jpg:
321
+ case AIFileContentAllowedExtensions.jpeg:
322
+ case AIFileContentAllowedExtensions.png:
323
+ case AIFileContentAllowedExtensions.svg:
324
+ return FileType.IMAGE;
325
+ case AIFileContentAllowedExtensions.txt:
326
+ case AIFileContentAllowedExtensions.doc:
327
+ case AIFileContentAllowedExtensions.pdf:
328
+ case AIFileContentAllowedExtensions.docx:
329
+ return FileType.DOCUMENT;
330
+ case AIFileContentAllowedExtensions.csv:
331
+ case AIFileContentAllowedExtensions.xlsx:
332
+ case AIFileContentAllowedExtensions.xls:
333
+ return FileType.SHEET;
334
+ case AIFileContentAllowedExtensions.mp3:
335
+ case AIFileContentAllowedExtensions.wav:
336
+ return FileType.AUDIO;
337
+ default:
338
+ this.__throwError(
339
+ new Error(_AIFileContent.__getExtensionErrorMessage(extension)),
340
+ this.__error?.fileExtension
341
+ );
342
+ }
343
+ });
344
+ // COMPONENT METHODS
345
+ __publicField$8(this, "Component", () => /* @__PURE__ */ jsxs(
346
+ Box,
347
+ {
348
+ sx: {
349
+ ...this.overrideSize ? {
350
+ ...this.overrideSize,
351
+ img: {
352
+ width: `${this.overrideSize.width - 20}px`,
353
+ height: `${this.overrideSize.height - 61}px`
354
+ }
355
+ } : {}
356
+ },
357
+ variant: "layout.common.components.aiMessage.fileBox",
358
+ children: [
359
+ FileType.IMAGE === this.type ? /* @__PURE__ */ jsx("img", { src: URL.createObjectURL(this.file), alt: this.fileName }) : /* @__PURE__ */ jsx(FileIcon, { iconSize: "lg", docName: this.fileName }),
360
+ /* @__PURE__ */ jsx(
361
+ Box,
362
+ {
363
+ as: "p",
364
+ variant: "layout.common.components.aiMessage.fileName",
365
+ title: this.fileName,
366
+ children: this.fileName
367
+ }
368
+ )
369
+ ]
370
+ }
371
+ ));
372
+ this.__error = error;
373
+ if (!_AIFileContent.isValidExtension(extension))
374
+ this.__throwError(
375
+ new Error(_AIFileContent.__getExtensionErrorMessage(extension)),
376
+ this.__error?.fileExtension
377
+ );
378
+ this.fileUrl = fileUrl;
379
+ this.extension = extension;
380
+ this.type = this.inferExtension(this.extension);
381
+ this.fileName = fileName;
382
+ this.__file = f;
383
+ this.content = this.inferContent();
384
+ }
385
+ // PUBLIC METHODS
386
+ setOverrideSize(overrideSize) {
387
+ this.overrideSize = overrideSize;
388
+ return this;
389
+ }
390
+ get file() {
391
+ if (!this.__file)
392
+ throw new Error("File is undefined");
393
+ return this.__file;
394
+ }
395
+ static getExtensionFromFileName(fileName) {
396
+ return fileName.split(".", 2).pop();
397
+ }
398
+ // PRIVATE METHODS
399
+ static __getExtensionErrorMessage(extension) {
400
+ return `extension "${extension}" is not included into valid types:
401
+ ${Object.keys(AIFileContentAllowedExtensions)}`;
402
+ }
403
+ __throwError(e, callback) {
404
+ callback && callback();
405
+ throw e;
406
+ }
407
+ getId() {
408
+ return uniqueId();
409
+ }
410
+ };
411
+ // STATIC METHODS
412
+ __publicField$8(_AIFileContent, "isValidExtension", (extension) => {
413
+ return Object.values(
414
+ AIFileContentAllowedExtensions
415
+ ).includes(extension);
416
+ });
417
+ __publicField$8(_AIFileContent, "blobToBase64", async (blob) => {
418
+ return await ((blob2) => new Promise((resolve, reject) => {
419
+ const reader = new FileReader();
420
+ reader.onloadend = () => {
421
+ const base64String = reader.result;
422
+ resolve(base64String);
423
+ };
424
+ reader.onerror = reject;
425
+ reader.readAsDataURL(blob2);
426
+ }))(blob);
427
+ });
428
+ __publicField$8(_AIFileContent, "fromFile", async (f, error) => {
429
+ const fileUrl = await ((f2) => new Promise((resolve, reject) => {
430
+ const reader = new FileReader();
431
+ reader.readAsDataURL(f2);
432
+ reader.onload = () => resolve(reader.result);
433
+ reader.onerror = () => reject();
434
+ }))(f);
435
+ return new _AIFileContent(fileUrl, f.name, f, error);
436
+ });
437
+ let AIFileContent = _AIFileContent;
438
+
439
+ var __defProp$7 = Object.defineProperty;
440
+ var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
441
+ var __publicField$7 = (obj, key, value) => {
442
+ __defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
443
+ return value;
444
+ };
445
+ class AIMessageAttachments {
446
+ constructor(role, content, close) {
447
+ this.close = close;
448
+ __publicField$7(this, "role");
449
+ __publicField$7(this, "content");
450
+ __publicField$7(this, "id", uniqueId());
451
+ __publicField$7(this, "customDescription", false);
452
+ __publicField$7(this, "addDescription", async () => {
453
+ const collector = new Collector();
454
+ const collected = await collector.add(this.content).add(
455
+ new collector.fields.textarea(
456
+ "addCommentTextArea",
457
+ getLabel("lblAiAddImageCo").text.replace(".", ""),
458
+ {
459
+ initialValue: this.content instanceof AIFileContent && this.content.content !== this.content.inferContent() ? this.content.content : ""
460
+ }
461
+ )
462
+ ).show({
463
+ title: getLabel("btnAddComment").text
464
+ }).catch((e) => {
465
+ throw e;
466
+ });
467
+ if (collected?.addCommentTextArea) {
468
+ this.content.content = collected.addCommentTextArea;
469
+ this.customDescription = true;
470
+ } else {
471
+ if (this.content instanceof AIFileContent)
472
+ this.content.content = this.content.inferContent();
473
+ this.customDescription = false;
474
+ }
475
+ });
476
+ __publicField$7(this, "Component", (props) => /* @__PURE__ */ jsxs(Box, { ...getVariant("layout.common.components.aiMessage"), children: [
477
+ props.closeButton ? /* @__PURE__ */ jsx(
478
+ IconButton,
479
+ {
480
+ className: "closeButton",
481
+ size: "Md",
482
+ icon: "Close",
483
+ onClick: this.close,
484
+ title: getLabel("lblDeleteItem").title
485
+ }
486
+ ) : /* @__PURE__ */ jsx(Fragment, {}),
487
+ props?.canAddDescription ? /* @__PURE__ */ jsx(
488
+ IconButton,
489
+ {
490
+ className: "descriptionButton",
491
+ size: "Md",
492
+ icon: "Magic",
493
+ onClick: this.addDescription
494
+ }
495
+ ) : /* @__PURE__ */ jsx(Fragment, {}),
496
+ /* @__PURE__ */ jsx(this.content.Component, {})
497
+ ] }));
498
+ this.role = role;
499
+ this.content = content;
500
+ }
501
+ getId() {
502
+ return this.id;
503
+ }
504
+ }
505
+
506
+ const handleFileUploadAsMessage = async (fileInputElement, chatController) => {
507
+ if (fileInputElement.files) {
508
+ [...fileInputElement.files].forEach(async (f) => {
509
+ const m = new AIMessageAttachments(
510
+ AIMessageRole.USER,
511
+ await AIFileContent.fromFile(f, {
512
+ fileExtension: () => chatController.messages.add(
513
+ new ChatMessage(
514
+ getLabel("msgAiIncorrectFileExtensionError", {
515
+ text: {
516
+ TOK1: `[${Object.keys(AIFileContentAllowedExtensions).join(", ")}]`
517
+ }
518
+ }).text,
519
+ "error"
520
+ )
521
+ )
522
+ }),
523
+ () => chatController.attachments.drop(m)
524
+ );
525
+ chatController.attachments.add(m);
526
+ });
527
+ }
528
+ };
529
+
530
+ const makeTextarea = (chatController) => {
531
+ const NewTextarea = observer(
532
+ ({
533
+ hideDeleteButton,
534
+ isLoading: outIsLoading,
535
+ onSubmit,
536
+ preventAppendUserMessages
537
+ }) => {
538
+ const [isLoading, setIsLoading] = useState(false);
539
+ const breakpoint = useBreakpointIndex();
540
+ const submit = useCallback(() => {
541
+ if (preventAppendUserMessages !== true)
542
+ chatController.messages.add(chatController.state.current);
543
+ chatController.history.add(chatController.state.current);
544
+ onSubmit(chatController.state.current).finally(() => {
545
+ setIsLoading(false);
546
+ chatController.state.current = new ChatMessage();
547
+ });
548
+ }, [onSubmit, preventAppendUserMessages]);
549
+ const handleSubmit = useCallback(
550
+ (ev) => {
551
+ ev.preventDefault();
552
+ if (chatController.state.current.message || chatController.attachments.size() > 0) {
553
+ setIsLoading(true);
554
+ submit();
555
+ }
556
+ const textarea = document.getElementById(
557
+ `GPTMessage${chatController.id}`
558
+ );
559
+ textarea.focus();
560
+ },
561
+ [submit]
562
+ );
563
+ const onKeyDown = useCallback((ev) => {
564
+ if (ev.target.readOnly)
565
+ return;
566
+ if (ev.code === "Enter" && !ev.shiftKey) {
567
+ ev.preventDefault();
568
+ ev.target.closest("form")?.querySelector('button[type="submit"]')?.click();
569
+ }
570
+ }, []);
571
+ const { progress, handleFileUpload } = useHandleFileUpload({
572
+ onContent(content) {
573
+ document.getElementById(
574
+ `GPTMessage${chatController.id}`
575
+ ).value = content.join("\n\n");
576
+ }
577
+ });
578
+ const actualIsLoading = isLoading || progress !== 100 || outIsLoading;
579
+ const [dragging, setDragging] = useState(false);
580
+ const handleDragLeave = (ev) => {
581
+ ev.preventDefault();
582
+ setDragging(false);
583
+ };
584
+ const handleDrop = (ev) => {
585
+ ev.preventDefault();
586
+ setDragging(false);
587
+ const fileElement = document.getElementById(
588
+ `gptUploadFile__${chatController.id}`
589
+ );
590
+ fileElement.files = ev.dataTransfer.files;
591
+ const event = new Event("change", { bubbles: true });
592
+ fileElement.dispatchEvent(event);
593
+ };
594
+ const handleDragOver = (ev) => {
595
+ ev.preventDefault();
596
+ };
597
+ const handleDragEnter = (ev) => {
598
+ ev.preventDefault();
599
+ setDragging(true);
600
+ };
601
+ const additionalButtons = [];
602
+ additionalButtons.push({
603
+ key: "prev",
604
+ children: /* @__PURE__ */ jsx(
605
+ SimpleButton,
606
+ {
607
+ title: getLabel("btnAiPrevious").title,
608
+ variant: "outline",
609
+ type: "button",
610
+ onClick: chatController.history.previous,
611
+ size: "sm",
612
+ children: getLabel("btnAiPrevious").text
613
+ }
614
+ )
615
+ });
616
+ additionalButtons.push({
617
+ key: "next",
618
+ children: /* @__PURE__ */ jsx(
619
+ SimpleButton,
620
+ {
621
+ title: getLabel("btnAiNext").title,
622
+ variant: "outline",
623
+ type: "button",
624
+ onClick: chatController.history.next,
625
+ size: "sm",
626
+ children: getLabel("btnAiNext").text
627
+ }
628
+ )
629
+ });
630
+ if (!hideDeleteButton) {
631
+ additionalButtons.push({
632
+ key: "delete",
633
+ children: /* @__PURE__ */ jsx(
634
+ SimpleButton,
635
+ {
636
+ title: getLabel("btnAiDelete").title,
637
+ variant: "outline",
638
+ type: "button",
639
+ onClick: () => {
640
+ chatController.state.current.message = "";
641
+ chatController.attachments.dropAll();
642
+ chatController.currentHistoryIndex = -1;
643
+ },
644
+ size: "sm",
645
+ children: getLabel("btnAiDelete").text
646
+ }
647
+ )
648
+ });
649
+ additionalButtons.push({
650
+ key: "deleteMessages",
651
+ children: /* @__PURE__ */ jsx(
652
+ SimpleButton,
653
+ {
654
+ title: getLabel("btnAiDeleteMessages").title,
655
+ variant: "outline",
656
+ type: "button",
657
+ onClick: () => chatController.messages.clear(),
658
+ size: "sm",
659
+ children: getLabel("btnAiDeleteMessages").text
660
+ }
661
+ )
662
+ });
663
+ }
664
+ const isPhone = breakpoint < 4;
665
+ let iconButton = /* @__PURE__ */ jsx(Fragment, {});
666
+ if (isPhone) {
667
+ iconButton = /* @__PURE__ */ jsx(
668
+ IconButton,
669
+ {
670
+ ...getVariant("layout.ai.execution.formsAssistant.settingsButton"),
671
+ iconSize: "Md",
672
+ size: "Lg",
673
+ icon: "Ellipsis",
674
+ isLoading: actualIsLoading,
675
+ onClick: () => {
676
+ const util = ApiaUtil.instance;
677
+ const items = [];
678
+ items.push(...additionalButtons);
679
+ if (items.length > 0)
680
+ util.menu.open({
681
+ menuProps: {
682
+ anchorPoint: { x: util.mouse.x, y: util.mouse.y }
683
+ },
684
+ items
685
+ });
686
+ }
687
+ }
688
+ );
689
+ }
690
+ return /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", flexDirection: "column", width: "100%" }, children: [
691
+ /* @__PURE__ */ jsx(
692
+ Box,
693
+ {
694
+ sx: {
695
+ flexWrap: "wrap",
696
+ display: "flex",
697
+ maxHeight: "280px",
698
+ overflowY: "auto",
699
+ paddingTop: "6px",
700
+ paddingBottom: "6px"
701
+ },
702
+ children: chatController.attachments.getComponents()
703
+ }
704
+ ),
705
+ /* @__PURE__ */ jsxs(
706
+ "form",
707
+ {
708
+ onDrop: handleDrop,
709
+ onDragOver: handleDragOver,
710
+ onDragEnter: handleDragEnter,
711
+ onDragLeave: handleDragLeave,
712
+ onSubmit: handleSubmit,
713
+ className: "gpt__form",
714
+ action: "",
715
+ children: [
716
+ dragging ? /* @__PURE__ */ jsx(
717
+ Box,
718
+ {
719
+ sx: {
720
+ height: "150px",
721
+ border: "3px dashed #aaa",
722
+ width: "100%",
723
+ display: "flex",
724
+ alignItems: "center",
725
+ justifyContent: "center"
726
+ },
727
+ children: getLabel("msgAiDragAndDrop").text
728
+ }
729
+ ) : /* @__PURE__ */ jsx(
730
+ Textarea,
731
+ {
732
+ onKeyDown,
733
+ id: `GPTMessage${chatController.id}`,
734
+ readOnly: actualIsLoading,
735
+ value: chatController.state.current.message,
736
+ onChange: (ev) => {
737
+ chatController.state.current.message = ev.target.value;
738
+ if (!chatController.state.current.message && chatController.attachments.size() < 1)
739
+ chatController.currentHistoryIndex = -1;
740
+ }
741
+ }
742
+ ),
743
+ /* @__PURE__ */ jsxs(Box, { className: "gpt__buttonsContainer", children: [
744
+ /* @__PURE__ */ jsx(Box, { sx: { display: "none" }, children: /* @__PURE__ */ jsx(
745
+ "input",
746
+ {
747
+ type: "file",
748
+ className: "gptUploadFile",
749
+ multiple: true,
750
+ id: `gptUploadFile__${chatController.id}`,
751
+ onChange: (ev) => {
752
+ if (1 == noNaN("a"))
753
+ handleFileUpload(ev).catch((e) => {
754
+ if (e instanceof WrongFormatError) {
755
+ setIsLoading(false);
756
+ chatController.messages.add(
757
+ new ChatMessage(
758
+ getLabel("msgAiFileExtensionError").text,
759
+ "error"
760
+ )
761
+ );
762
+ } else {
763
+ throw e;
764
+ }
765
+ });
766
+ else {
767
+ handleFileUploadAsMessage(ev.target, chatController);
768
+ }
769
+ ev.target.value = "";
770
+ }
771
+ }
772
+ ) }),
773
+ /* @__PURE__ */ jsx(
774
+ IconButton,
775
+ {
776
+ variant: "icon-outline",
777
+ onClick: () => !chatController.audioRecorder.state.recording ? chatController.audioRecorder.start() : chatController.audioRecorder.stop(),
778
+ disabled: actualIsLoading && !chatController.audioRecorder.state.recording,
779
+ sx: {
780
+ color: chatController.audioRecorder.state.recording ? "red" : void 0
781
+ },
782
+ icon: chatController.audioRecorder.state.recording ? "Stop" : "Microphone",
783
+ id: "transcribeAudio",
784
+ size: "Lg",
785
+ title: getLabel("lblAiRecordAudio").text
786
+ }
787
+ ),
788
+ /* @__PURE__ */ jsx(
789
+ IconButton,
790
+ {
791
+ title: getLabel("btnUploadFile").text,
792
+ icon: "File",
793
+ variant: "icon-outline",
794
+ disabled: actualIsLoading,
795
+ onClick: () => {
796
+ document.getElementById(
797
+ `gptUploadFile__${chatController.id}`
798
+ ).click();
799
+ },
800
+ size: "Lg"
801
+ }
802
+ ),
803
+ isPhone ? iconButton : /* @__PURE__ */ jsxs(Fragment, { children: [
804
+ ...additionalButtons.map(
805
+ (x) => x.children
806
+ )
807
+ ] }),
808
+ /* @__PURE__ */ jsx(
809
+ SimpleButton,
810
+ {
811
+ title: getLabel("btnAiSend").title,
812
+ isLoading: actualIsLoading,
813
+ type: "submit",
814
+ size: "sm",
815
+ children: getLabel("btnAiSend").text
816
+ }
817
+ )
818
+ ] })
819
+ ]
820
+ }
821
+ )
822
+ ] });
823
+ }
824
+ );
825
+ NewTextarea.displayName = "";
826
+ return NewTextarea;
827
+ };
828
+
829
+ var __defProp$6 = Object.defineProperty;
830
+ var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
831
+ var __publicField$6 = (obj, key, value) => {
832
+ __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
833
+ return value;
834
+ };
835
+ var __accessCheck = (obj, member, msg) => {
836
+ if (!member.has(obj))
837
+ throw TypeError("Cannot " + msg);
838
+ };
839
+ var __privateGet = (obj, member, getter) => {
840
+ __accessCheck(obj, member, "read from private field");
841
+ return getter ? getter.call(obj) : member.get(obj);
842
+ };
843
+ var __privateAdd = (obj, member, value) => {
844
+ if (member.has(obj))
845
+ throw TypeError("Cannot add the same private member more than once");
846
+ member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
847
+ };
848
+ var __privateSet = (obj, member, value, setter) => {
849
+ __accessCheck(obj, member, "write to private field");
850
+ setter ? setter.call(obj, value) : member.set(obj, value);
851
+ return value;
852
+ };
853
+ var _promptsHistory, _internalAudioRecorder;
854
+ class ChatController {
855
+ constructor(id, welcomeMessage) {
856
+ this.id = id;
857
+ __publicField$6(this, "state", {
858
+ current: new ChatMessage(),
859
+ messages: []
860
+ });
861
+ __publicField$6(this, "components", {
862
+ MessageHistory: observer(() => {
863
+ return /* @__PURE__ */ jsx(
864
+ Box,
865
+ {
866
+ ...getVariant("layout.common.components.chat"),
867
+ className: "history",
868
+ children: /* @__PURE__ */ jsx(AutoscrollContainer, { children: this.state.messages.map((current) => /* @__PURE__ */ jsx(current.Component, {}, current.id)) })
869
+ }
870
+ );
871
+ }),
872
+ Textarea: makeTextarea(this)
873
+ });
874
+ __privateAdd(this, _promptsHistory, []);
875
+ __publicField$6(this, "currentHistoryIndex", -1);
876
+ __privateAdd(this, _internalAudioRecorder, new AudioRecorder());
877
+ __publicField$6(this, "audioRecorder", {
878
+ start: () => __privateGet(this, _internalAudioRecorder).start().then(async (blob) => {
879
+ const m = new AIMessageAttachments(
880
+ AIMessageRole.USER,
881
+ new AIFileContent(
882
+ await AIFileContent.blobToBase64(blob),
883
+ `userRecord_${this.audioRecorder.record++}.wav`
884
+ ),
885
+ () => this.attachments.drop(m)
886
+ );
887
+ this.attachments.add(m);
888
+ }),
889
+ stop: async () => {
890
+ __privateGet(this, _internalAudioRecorder).stop();
891
+ },
892
+ record: 0,
893
+ state: __privateGet(this, _internalAudioRecorder).state
894
+ });
895
+ __publicField$6(this, "history", {
896
+ add: (message) => {
897
+ this.currentHistoryIndex = -1;
898
+ if (message === __privateGet(this, _promptsHistory)[__privateGet(this, _promptsHistory).length]) {
899
+ return;
900
+ }
901
+ __privateSet(this, _promptsHistory, [
902
+ message,
903
+ ...__privateGet(this, _promptsHistory).slice(
904
+ Math.max(0, __privateGet(this, _promptsHistory).length - 10)
905
+ )
906
+ ]);
907
+ },
908
+ next: () => {
909
+ let message = new ChatMessage();
910
+ if (__privateGet(this, _promptsHistory)[this.currentHistoryIndex - 1])
911
+ message = __privateGet(this, _promptsHistory)[--this.currentHistoryIndex].copy();
912
+ else {
913
+ this.currentHistoryIndex = -1;
914
+ }
915
+ this.history.updateState(message);
916
+ },
917
+ previous: () => {
918
+ if (__privateGet(this, _promptsHistory)[this.currentHistoryIndex + 1]) {
919
+ this.history.updateState(
920
+ __privateGet(this, _promptsHistory)[++this.currentHistoryIndex].copy()
921
+ );
922
+ }
923
+ },
924
+ updateState: (message) => {
925
+ if (message)
926
+ this.state.current = message;
927
+ else
928
+ this.state.current = new ChatMessage();
929
+ },
930
+ size: () => this.state.messages.length
931
+ });
932
+ __publicField$6(this, "messages", {
933
+ add: (message, idx) => {
934
+ if (idx !== void 0 && idx !== null) {
935
+ this.state.messages.splice(idx, 0, message);
936
+ } else {
937
+ this.state.messages.push(message);
938
+ }
939
+ },
940
+ clear: () => {
941
+ this.state.messages = [];
942
+ }
943
+ });
944
+ __publicField$6(this, "attachments", {
945
+ add: (...aiMessage) => {
946
+ this.state.current.attachments.push(...aiMessage);
947
+ },
948
+ dropAll: () => void (this.state.current.attachments = []),
949
+ drop: (el) => {
950
+ this.state.current.attachments = this.state.current.attachments.filter(
951
+ (c) => c !== el
952
+ );
953
+ if (!this.state.current.message && this.attachments.size() < 1)
954
+ this.currentHistoryIndex = -1;
955
+ },
956
+ getComponents: () => this.state.current.attachments.map((x) => /* @__PURE__ */ jsx(x.Component, { closeButton: true, canAddDescription: true }, x.getId())),
957
+ get: () => this.state.current.attachments,
958
+ size: () => this.state.current.attachments.length
959
+ });
960
+ if (welcomeMessage) {
961
+ this.state.messages.splice(
962
+ 0,
963
+ 0,
964
+ new ChatMessage(welcomeMessage, "system")
965
+ );
966
+ }
967
+ makeObservable(this, { state: observable });
968
+ }
969
+ }
970
+ _promptsHistory = new WeakMap();
971
+ _internalAudioRecorder = new WeakMap();
972
+
973
+ class MultipleChoiceMessage extends ChatMessage {
974
+ constructor(question, options, Renderer) {
975
+ super(
976
+ Renderer ? /* @__PURE__ */ jsxs(Box, { className: "multipleChoiceMessage customRenderer", children: [
977
+ /* @__PURE__ */ jsx(Paragraph, { children: question }),
978
+ options.map((item) => /* @__PURE__ */ jsx(Renderer, { item }, item.url))
979
+ ] }) : /* @__PURE__ */ jsxs(Box, { className: "multipleChoiceMessage", children: [
980
+ /* @__PURE__ */ jsx(Paragraph, { children: question }),
981
+ /* @__PURE__ */ jsx(Box, { as: "ul", children: options.map((current) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
982
+ SimpleButton,
983
+ {
984
+ className: "multipleChoice__option",
985
+ onClick: () => {
986
+ ApiaUtil.instance.tabs.openTab(current.label, current.url);
987
+ },
988
+ children: current.label
989
+ }
990
+ ) }, current.label)) })
991
+ ] }),
992
+ "multipleChoice"
993
+ );
994
+ }
995
+ }
996
+
997
+ const Component = observer(
998
+ (props) => {
999
+ return /* @__PURE__ */ jsxs(Box, { children: [
1000
+ /* @__PURE__ */ jsx("a", { href: props.instance.state.link, children: props.instance.state.title }),
1001
+ /* @__PURE__ */ jsx(Box, { children: props.instance.state.body })
1002
+ ] });
1003
+ }
1004
+ );
1005
+
1006
+ var __defProp$5 = Object.defineProperty;
1007
+ var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1008
+ var __publicField$5 = (obj, key, value) => {
1009
+ __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
1010
+ return value;
1011
+ };
1012
+ class SemanticSearchReference {
1013
+ constructor(props) {
1014
+ __publicField$5(this, "state", { title: "", body: "", link: "" });
1015
+ __publicField$5(this, "Component", () => /* @__PURE__ */ jsxs(Fragment, { children: [
1016
+ "(",
1017
+ /* @__PURE__ */ jsx(Component, { instance: this }),
1018
+ ")"
1019
+ ] }));
1020
+ this.state = props;
1021
+ makeObservable(this, { state: observable });
1022
+ }
1023
+ }
1024
+
1025
+ var __defProp$4 = Object.defineProperty;
1026
+ var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1027
+ var __publicField$4 = (obj, key, value) => {
1028
+ __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
1029
+ return value;
1030
+ };
1031
+ const _SearchController = class _SearchController {
1032
+ constructor() {
1033
+ __publicField$4(this, "state", { queryString: "", results: [], isLoading: false, disabled: false });
1034
+ makeObservable(this, { state: observable });
1035
+ }
1036
+ async search(selectedId) {
1037
+ const filters = await FiltersStore.getFiltersById(
1038
+ Number.parseInt(selectedId)
1039
+ );
1040
+ FiltersStore.setFilters(filters, "U");
1041
+ _SearchController.instance.state.isLoading = true;
1042
+ const response = await ApiaApi.post(
1043
+ makeApiaUrl({
1044
+ action: "search",
1045
+ semSearchId: selectedId
1046
+ }),
1047
+ {
1048
+ postData: {
1049
+ q: _SearchController.instance.state.queryString,
1050
+ filters: JSON.stringify(FiltersStore.getFiltersAsFilterValue("U"))
1051
+ },
1052
+ postDataTreatement: "stringify",
1053
+ stringifyOptions: { arrayFormat: "repeat" }
1054
+ }
1055
+ );
1056
+ if (response?.data?.results) {
1057
+ this.setReferences(response.data.results);
1058
+ }
1059
+ this.state.isLoading = false;
1060
+ }
1061
+ setReferences(results) {
1062
+ if (typeof results === "string" && results) {
1063
+ results = JSON.parse(results);
1064
+ }
1065
+ _SearchController.instance.state.results = results.map(
1066
+ (x) => x instanceof SemanticSearchReference ? x : new SemanticSearchReference(x)
1067
+ );
1068
+ _SearchController.instance.state.disabled = false;
1069
+ }
1070
+ };
1071
+ __publicField$4(_SearchController, "instance", new _SearchController());
1072
+ let SearchController = _SearchController;
1073
+ var SearchController$1 = SearchController;
1074
+
1075
+ var __defProp$3 = Object.defineProperty;
1076
+ var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1077
+ var __publicField$3 = (obj, key, value) => {
1078
+ __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
1079
+ return value;
1080
+ };
1081
+ function isPollProgress(payload) {
1082
+ return payload?.progress !== void 0;
1083
+ }
1084
+ class RoutinesGeneration {
1085
+ constructor() {
1086
+ __publicField$3(this, "audioRecorder", new AudioRecorder());
1087
+ __publicField$3(this, "routineId", "");
1088
+ __publicField$3(this, "state", {
1089
+ isLoading: false,
1090
+ progress: 0
1091
+ });
1092
+ makeObservable(this, {
1093
+ completion: action,
1094
+ state: observable,
1095
+ stop: action,
1096
+ transcribeAudio: action
1097
+ });
1098
+ }
1099
+ checkCanGenerate() {
1100
+ if (this.state.isLoading) {
1101
+ throw new Error("Cannot queue two simultaneous generations");
1102
+ }
1103
+ this.state.isLoading = true;
1104
+ }
1105
+ async pollRoutine(routineId, stream) {
1106
+ this.routineId = routineId;
1107
+ this.state.isLoading = true;
1108
+ return this.internalPollRoutine(stream);
1109
+ }
1110
+ async internalPollRoutine(stream) {
1111
+ while (this.state.isLoading) {
1112
+ const pollResult = await this.callRoutinePoll(this.routineId);
1113
+ if (isPollProgress(pollResult.payload)) {
1114
+ try {
1115
+ const res = JSON.parse(pollResult.payload.debug);
1116
+ if (res.length > 0) {
1117
+ res.forEach((c) => {
1118
+ console.log(JSON.parse(c));
1119
+ });
1120
+ }
1121
+ if (pollResult.payload.streamPart && stream) {
1122
+ stream.emit("part", pollResult.payload.streamPart);
1123
+ }
1124
+ this.state.progress = pollResult.payload.progress;
1125
+ } catch (e) {
1126
+ console.error(e);
1127
+ }
1128
+ } else if (pollResult.status === "FINISHED") {
1129
+ this.resetLoading();
1130
+ return pollResult.payload;
1131
+ } else if (pollResult.status === "ERROR") {
1132
+ this.resetLoading();
1133
+ throw new Error(pollResult.payload);
1134
+ } else {
1135
+ this.resetLoading();
1136
+ throw new Error("Wrong poll response");
1137
+ }
1138
+ }
1139
+ return null;
1140
+ }
1141
+ async callAudioTranscription(audio) {
1142
+ const url = makeApiaUrl({
1143
+ action: "routineStart",
1144
+ routine: "transcription/Transcribe"
1145
+ });
1146
+ const response = await axios.post(url, audio.arrayBuffer(), {
1147
+ headers: {
1148
+ "Content-Type": "application/octet-stream"
1149
+ }
1150
+ });
1151
+ const result = await parseSuccessfulResponse(response, "");
1152
+ if (result?.orchestrator) {
1153
+ return result;
1154
+ }
1155
+ return null;
1156
+ }
1157
+ async callRoutinePoll(routineId) {
1158
+ const result = await ApiaApi.post(
1159
+ makeApiaUrl({
1160
+ action: "routinePoll",
1161
+ routineId
1162
+ })
1163
+ );
1164
+ if (result?.data?.orchestrator) {
1165
+ return JSON.parse(result.data.orchestrator);
1166
+ } else {
1167
+ throw new Error("Poll failed");
1168
+ }
1169
+ }
1170
+ async callRoutineStart(routineName, parameters, images) {
1171
+ const result = await ApiaApi.post(
1172
+ makeApiaUrl({
1173
+ action: "routineStart",
1174
+ routine: routineName
1175
+ }),
1176
+ {
1177
+ postData: {
1178
+ images: JSON.stringify(images),
1179
+ ...parameters
1180
+ },
1181
+ stringifyOptions: {
1182
+ arrayFormat: "repeat"
1183
+ },
1184
+ postDataTreatement: "stringify"
1185
+ }
1186
+ );
1187
+ return result?.data || null;
1188
+ }
1189
+ async executeRoutine(routineName, parameters, images, stream) {
1190
+ this.checkCanGenerate();
1191
+ try {
1192
+ const result = await this.callRoutineStart(
1193
+ routineName,
1194
+ parameters,
1195
+ images
1196
+ );
1197
+ if (result?.orchestrator?.routineId !== void 0) {
1198
+ this.routineId = result?.orchestrator.routineId;
1199
+ return this.internalPollRoutine(stream);
1200
+ } else {
1201
+ throw new Error("Cannot get routine id");
1202
+ }
1203
+ } catch (e) {
1204
+ this.resetLoading();
1205
+ throw e;
1206
+ }
1207
+ }
1208
+ resetLoading() {
1209
+ this.state.isLoading = false;
1210
+ this.state.progress = 0;
1211
+ }
1212
+ async completion(params) {
1213
+ return this.executeRoutine(
1214
+ params.routineName,
1215
+ params.parameters ?? {},
1216
+ params.images ?? [],
1217
+ params.stream
1218
+ );
1219
+ }
1220
+ stop() {
1221
+ this.resetLoading();
1222
+ ApiaApi.get(
1223
+ makeApiaUrl({
1224
+ action: "routineStop",
1225
+ routineId: this.routineId
1226
+ })
1227
+ );
1228
+ }
1229
+ async transcribeAudio(audio) {
1230
+ const result = await this.callAudioTranscription(audio);
1231
+ if (result) {
1232
+ this.state.isLoading = true;
1233
+ if (result?.orchestrator?.routineId) {
1234
+ this.routineId = result?.orchestrator?.routineId;
1235
+ return await this.internalPollRoutine();
1236
+ }
1237
+ }
1238
+ throw new Error("Something went wrong while transcribing the audio");
1239
+ }
1240
+ }
1241
+
1242
+ class DashboardsRoutinesGeneration extends RoutinesGeneration {
1243
+ constructor(dispatcher) {
1244
+ super();
1245
+ this.dispatcher = dispatcher;
1246
+ }
1247
+ blobToBase64(audio) {
1248
+ return new Promise((resolve, reject) => {
1249
+ const reader = new FileReader();
1250
+ reader.onloadend = () => {
1251
+ if (reader.result && typeof reader.result === "string") {
1252
+ const base64 = reader.result.split(",")[1];
1253
+ resolve(base64);
1254
+ } else {
1255
+ reject(new Error("Could not convert Blob to base64"));
1256
+ }
1257
+ };
1258
+ reader.onerror = reject;
1259
+ reader.readAsDataURL(audio);
1260
+ });
1261
+ }
1262
+ async callAudioTranscription(audio) {
1263
+ const audioBase64 = await this.blobToBase64(audio);
1264
+ const result = await this.dispatcher({
1265
+ action: "transcription",
1266
+ audioBase64
1267
+ });
1268
+ return result?.data || null;
1269
+ }
1270
+ async callRoutinePoll(routineId) {
1271
+ const result = await this.dispatcher({
1272
+ action: "routinePoll",
1273
+ routineId
1274
+ });
1275
+ if (result?.data?.orchestrator) {
1276
+ const parsed = JSON.parse(result.data.orchestrator);
1277
+ return parsed;
1278
+ }
1279
+ throw new Error("Poll failed");
1280
+ }
1281
+ async callRoutineStart(routineName, parameters, images) {
1282
+ const result = await this.dispatcher({
1283
+ action: "routineStart",
1284
+ routine: routineName,
1285
+ ...parameters,
1286
+ images
1287
+ });
1288
+ return result?.data || null;
1289
+ }
1290
+ }
1291
+
1292
+ var __defProp$2 = Object.defineProperty;
1293
+ var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1294
+ var __publicField$2 = (obj, key, value) => {
1295
+ __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
1296
+ return value;
1297
+ };
1298
+ class ResponseStream extends EventEmitter {
1299
+ constructor() {
1300
+ super(...arguments);
1301
+ __publicField$2(this, "buffer", "");
1302
+ __publicField$2(this, "isRunning", false);
1303
+ __publicField$2(this, "locked", false);
1304
+ __publicField$2(this, "maxCompletionTime", 2);
1305
+ // s
1306
+ __publicField$2(this, "minPartSize", 2);
1307
+ __publicField$2(this, "partSize", 2);
1308
+ __publicField$2(this, "timing", 5);
1309
+ // ms
1310
+ __publicField$2(this, "waiting", []);
1311
+ }
1312
+ calculatePartSize() {
1313
+ const totalSize = this.buffer.length + this.waiting.reduce((a, b) => a + b.length, 0);
1314
+ this.partSize = Math.max(
1315
+ this.minPartSize,
1316
+ totalSize * this.timing / (this.maxCompletionTime * 1e3)
1317
+ );
1318
+ }
1319
+ emit(_, data) {
1320
+ if (this.locked) {
1321
+ this.waiting.push(data);
1322
+ } else {
1323
+ this.buffer += data;
1324
+ }
1325
+ this.calculatePartSize();
1326
+ this.run();
1327
+ }
1328
+ run() {
1329
+ if (!this.isRunning) {
1330
+ this.isRunning = true;
1331
+ const interval = setInterval(() => {
1332
+ this.locked = true;
1333
+ const choosedSize = Math.min(this.buffer.length, this.partSize);
1334
+ const part = this.buffer.slice(0, choosedSize);
1335
+ this.buffer = this.buffer.slice(choosedSize);
1336
+ while (this.waiting.length > 0) {
1337
+ const part2 = this.waiting.shift();
1338
+ if (part2) {
1339
+ this.buffer += part2;
1340
+ }
1341
+ }
1342
+ this.locked = false;
1343
+ if (part) {
1344
+ super.emit("part", part);
1345
+ } else {
1346
+ this.isRunning = false;
1347
+ clearInterval(interval);
1348
+ }
1349
+ }, this.timing);
1350
+ }
1351
+ }
1352
+ }
1353
+
1354
+ async function getImageFromDisk(inputProps) {
1355
+ return (await getImagesFromDisk({ ...inputProps, multiple: "false" }))[0] ?? null;
1356
+ }
1357
+ function getImagesFromDisk(inputProps) {
1358
+ return new Promise((resolve) => {
1359
+ const input = document.createElement("input");
1360
+ input.accept = "image/*";
1361
+ input.type = "file";
1362
+ input.style.display = "none";
1363
+ Object.assign(input, inputProps);
1364
+ document.body.append(input);
1365
+ input.addEventListener("change", (event) => {
1366
+ const target = event?.target;
1367
+ if (!target?.files)
1368
+ return;
1369
+ const retrievedImages = [];
1370
+ const sources = [...target.files ?? []];
1371
+ const checkResolve = () => {
1372
+ if (sources.length === retrievedImages.length) {
1373
+ resolve(retrievedImages.filter((c) => !!c));
1374
+ }
1375
+ };
1376
+ sources.forEach((file) => {
1377
+ if (file) {
1378
+ const reader = new FileReader();
1379
+ reader.onload = function(e) {
1380
+ const binary = e.target?.result?.split(",")[1];
1381
+ input.remove();
1382
+ retrievedImages.push({
1383
+ base64: binary,
1384
+ path: file.name
1385
+ });
1386
+ checkResolve();
1387
+ };
1388
+ reader.readAsDataURL(file);
1389
+ } else {
1390
+ retrievedImages.push(null);
1391
+ }
1392
+ checkResolve();
1393
+ });
1394
+ });
1395
+ input.click();
1396
+ });
1397
+ }
1398
+
1399
+ const ImageIcon = ({
1400
+ deletable,
1401
+ onClick,
1402
+ onRemove,
1403
+ src
1404
+ }) => {
1405
+ return /* @__PURE__ */ jsxs(Box, { className: "image_preview", children: [
1406
+ deletable && /* @__PURE__ */ jsx(IconButton, { icon: "Close", size: "Xs", iconSize: "Xs", onClick: onRemove }),
1407
+ /* @__PURE__ */ jsx("img", { src, onClick })
1408
+ ] });
1409
+ };
1410
+
1411
+ function getSrcFromBase64(base64) {
1412
+ return `data:image/jpg;base64,${base64}`;
1413
+ }
1414
+
1415
+ var __defProp$1 = Object.defineProperty;
1416
+ var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1417
+ var __publicField$1 = (obj, key, value) => {
1418
+ __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
1419
+ return value;
1420
+ };
1421
+ class ImagesStore {
1422
+ constructor(images, multiple) {
1423
+ this.multiple = multiple;
1424
+ __publicField$1(this, "images", /* @__PURE__ */ new Map());
1425
+ __publicField$1(this, "selectedId", "");
1426
+ this.images = new Map(
1427
+ images.map((c) => {
1428
+ const id = uniqueId();
1429
+ return [id, { ...c, id }];
1430
+ })
1431
+ );
1432
+ this.selectedId = this.images.values().next().value.id;
1433
+ makeAutoObservable(this);
1434
+ }
1435
+ }
1436
+ const GetImagesDescription = observer(({ store }) => {
1437
+ return /* @__PURE__ */ jsxs(
1438
+ Box,
1439
+ {
1440
+ className: "images_description_generator",
1441
+ ...getVariant("layout.design.projectAnalysis.imagesLoader"),
1442
+ children: [
1443
+ /* @__PURE__ */ jsx(Box, { className: "images_sort_wrapper", children: /* @__PURE__ */ jsx(
1444
+ SortableList,
1445
+ {
1446
+ onSortChange: (ev) => {
1447
+ store.images = new Map(
1448
+ ev.map((c) => [
1449
+ c.props.id,
1450
+ c.props.additionalProps
1451
+ ])
1452
+ );
1453
+ },
1454
+ children: [...store.images].map(([k, c]) => /* @__PURE__ */ jsx(SortableListItem, { additionalProps: c, id: c.id, children: /* @__PURE__ */ jsx(
1455
+ ImageIcon,
1456
+ {
1457
+ deletable: store.multiple,
1458
+ onClick: () => {
1459
+ store.selectedId = c.id;
1460
+ },
1461
+ onRemove: () => {
1462
+ store.images.delete(k);
1463
+ },
1464
+ src: getSrcFromBase64(c.base64 ?? "")
1465
+ }
1466
+ ) }, c.id))
1467
+ }
1468
+ ) }),
1469
+ /* @__PURE__ */ jsxs(Box, { className: "image_editor", children: [
1470
+ /* @__PURE__ */ jsx(Box, { className: "image_preview", children: store.images.get(store.selectedId) && /* @__PURE__ */ jsx(
1471
+ "img",
1472
+ {
1473
+ src: getSrcFromBase64(
1474
+ store.images.get(store.selectedId).base64 ?? ""
1475
+ )
1476
+ }
1477
+ ) }),
1478
+ /* @__PURE__ */ jsxs(Box, { className: "image_description", children: [
1479
+ /* @__PURE__ */ jsx(
1480
+ Textarea,
1481
+ {
1482
+ autoFocus: true,
1483
+ disabled: !store.images.get(store.selectedId),
1484
+ onChange: (ev) => {
1485
+ const image = store.images.get(store.selectedId);
1486
+ if (image)
1487
+ image.description = ev.target.value;
1488
+ },
1489
+ value: store.images.get(store.selectedId)?.description
1490
+ }
1491
+ ),
1492
+ store.multiple && /* @__PURE__ */ jsx(
1493
+ IconButton,
1494
+ {
1495
+ icon: "Attach",
1496
+ onClick: () => {
1497
+ getImagesFromDisk({ multiple: "true" }).then((res) => {
1498
+ res.forEach((c) => {
1499
+ const id = uniqueId();
1500
+ store.images.set(id, {
1501
+ base64: c.base64,
1502
+ description: "",
1503
+ id
1504
+ });
1505
+ });
1506
+ });
1507
+ },
1508
+ size: "Md",
1509
+ iconSize: "Sm",
1510
+ variant: "icon-only"
1511
+ }
1512
+ )
1513
+ ] })
1514
+ ] })
1515
+ ]
1516
+ }
1517
+ );
1518
+ });
1519
+ function getImagesWithDescription({
1520
+ multiple
1521
+ }) {
1522
+ return new Promise((resolve) => {
1523
+ getImagesFromDisk({ multiple: multiple ? "true" : void 0 }).then(
1524
+ (images) => {
1525
+ const store = new ImagesStore(
1526
+ images.map((c) => ({
1527
+ base64: c.base64,
1528
+ description: ""
1529
+ })),
1530
+ multiple || false
1531
+ );
1532
+ ApiaUtil.instance.modals.open({
1533
+ children: /* @__PURE__ */ jsx(GetImagesDescription, { store }),
1534
+ initialFocusGetter(modalInnerRef) {
1535
+ return modalInnerRef.querySelector("textarea");
1536
+ },
1537
+ onConfirm: () => {
1538
+ resolve([...toJS(store.images).values()]);
1539
+ },
1540
+ onCancel() {
1541
+ resolve([]);
1542
+ },
1543
+ size: "xxxl-fixed",
1544
+ noHeader: true
1545
+ });
1546
+ }
1547
+ );
1548
+ });
1549
+ }
1550
+
1551
+ const ViewRendererContext = createContext(
1552
+ {}
1553
+ );
1554
+
1555
+ const Attachments = observer(
1556
+ ({ attachments }) => {
1557
+ return /* @__PURE__ */ jsx(Box, { children: attachments.map((x) => /* @__PURE__ */ jsx(x.Component, {})) });
1558
+ }
1559
+ );
1560
+
1561
+ const Header = observer(({ childComponent }) => {
1562
+ return /* @__PURE__ */ jsx(Fragment, { children: childComponent });
1563
+ });
1564
+
1565
+ const History = observer(({ messages }) => {
1566
+ return /* @__PURE__ */ jsx(Box, { ...getVariant("layout.common.components.chat"), className: "history", children: /* @__PURE__ */ jsx(AutoscrollContainer, { children: messages.map((current) => /* @__PURE__ */ jsx(current.Component, {}, current.id)) }) });
1567
+ });
1568
+
1569
+ const TextArea = observer(
1570
+ ({
1571
+ isLoading,
1572
+ isRecording,
1573
+ onSubmit,
1574
+ onChange,
1575
+ onClearHistory,
1576
+ onClearAttachments,
1577
+ onClearMessage,
1578
+ onAttach,
1579
+ onRecord,
1580
+ onPrev,
1581
+ onNext,
1582
+ hideDeleteButton,
1583
+ value,
1584
+ //attachments,
1585
+ id
1586
+ }) => {
1587
+ useBreakpointIndex();
1588
+ const onKeyDown = useCallback((ev) => {
1589
+ if (ev.target.readOnly)
1590
+ return;
1591
+ if (ev.code === "Enter" && !ev.shiftKey) {
1592
+ ev.preventDefault();
1593
+ ev.target.closest("form")?.querySelector('button[type="submit"]')?.click();
1594
+ }
1595
+ }, []);
1596
+ const [dragging, setDragging] = useState(false);
1597
+ const handleDragLeave = (ev) => {
1598
+ ev.preventDefault();
1599
+ setDragging(false);
1600
+ };
1601
+ const handleDrop = (ev) => {
1602
+ ev.preventDefault();
1603
+ setDragging(false);
1604
+ const fileElement = document.getElementById(
1605
+ `chatUploadFile__${id}`
1606
+ );
1607
+ fileElement.files = ev.dataTransfer.files;
1608
+ const event = new Event("change", { bubbles: true });
1609
+ fileElement.dispatchEvent(event);
1610
+ };
1611
+ const handleDragOver = (ev) => {
1612
+ ev.preventDefault();
1613
+ };
1614
+ const handleDragEnter = (ev) => {
1615
+ ev.preventDefault();
1616
+ setDragging(true);
1617
+ };
1618
+ const additionalButtons = [];
1619
+ additionalButtons.push({
1620
+ key: "prev",
1621
+ children: /* @__PURE__ */ jsx(
1622
+ SimpleButton,
1623
+ {
1624
+ title: getLabel("btnAiPrevious").title,
1625
+ variant: "outline",
1626
+ type: "button",
1627
+ onClick: onPrev,
1628
+ size: "sm",
1629
+ children: getLabel("btnAiPrevious").text
1630
+ }
1631
+ )
1632
+ });
1633
+ additionalButtons.push({
1634
+ key: "next",
1635
+ children: /* @__PURE__ */ jsx(
1636
+ SimpleButton,
1637
+ {
1638
+ title: getLabel("btnAiNext").title,
1639
+ variant: "outline",
1640
+ type: "button",
1641
+ onClick: onNext,
1642
+ size: "sm",
1643
+ children: getLabel("btnAiNext").text
1644
+ }
1645
+ )
1646
+ });
1647
+ if (!hideDeleteButton) {
1648
+ additionalButtons.push({
1649
+ key: "delete",
1650
+ children: /* @__PURE__ */ jsx(
1651
+ SimpleButton,
1652
+ {
1653
+ title: getLabel("btnAiDelete").title,
1654
+ variant: "outline",
1655
+ type: "button",
1656
+ onClick: () => {
1657
+ onClearMessage();
1658
+ onClearAttachments();
1659
+ },
1660
+ size: "sm",
1661
+ children: getLabel("btnAiDelete").text
1662
+ }
1663
+ )
1664
+ });
1665
+ additionalButtons.push({
1666
+ key: "deleteMessages",
1667
+ children: /* @__PURE__ */ jsx(
1668
+ SimpleButton,
1669
+ {
1670
+ title: getLabel("btnAiDeleteMessages").title,
1671
+ variant: "outline",
1672
+ type: "button",
1673
+ onClick: onClearHistory,
1674
+ size: "sm",
1675
+ children: getLabel("btnAiDeleteMessages").text
1676
+ }
1677
+ )
1678
+ });
1679
+ }
1680
+ return /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", flexDirection: "column", width: "100%" }, children: [
1681
+ /* @__PURE__ */ jsx(
1682
+ Box,
1683
+ {
1684
+ sx: {
1685
+ flexWrap: "wrap",
1686
+ display: "flex",
1687
+ maxHeight: "280px",
1688
+ overflowY: "auto",
1689
+ paddingTop: "6px",
1690
+ paddingBottom: "6px"
1691
+ }
1692
+ }
1693
+ ),
1694
+ /* @__PURE__ */ jsxs(
1695
+ "form",
1696
+ {
1697
+ onDrop: handleDrop,
1698
+ onDragOver: handleDragOver,
1699
+ onDragEnter: handleDragEnter,
1700
+ onDragLeave: handleDragLeave,
1701
+ onSubmit,
1702
+ className: "gpt__form",
1703
+ action: "",
1704
+ children: [
1705
+ dragging ? /* @__PURE__ */ jsx(
1706
+ Box,
1707
+ {
1708
+ sx: {
1709
+ height: "150px",
1710
+ border: "3px dashed #aaa",
1711
+ width: "100%",
1712
+ display: "flex",
1713
+ alignItems: "center",
1714
+ justifyContent: "center"
1715
+ },
1716
+ children: getLabel("msgAiDragAndDrop").text
1717
+ }
1718
+ ) : /* @__PURE__ */ jsx(
1719
+ Textarea,
1720
+ {
1721
+ onKeyDown,
1722
+ id: `chatMessage${id}`,
1723
+ readOnly: isLoading,
1724
+ value,
1725
+ onChange: (ev) => {
1726
+ onChange(ev.target.value);
1727
+ }
1728
+ }
1729
+ ),
1730
+ /* @__PURE__ */ jsxs(Box, { className: "gpt__buttonsContainer", children: [
1731
+ /* @__PURE__ */ jsx(Box, { sx: { display: "none" }, children: /* @__PURE__ */ jsx(
1732
+ "input",
1733
+ {
1734
+ type: "file",
1735
+ className: "gptUploadFile",
1736
+ multiple: true,
1737
+ id: `chatUploadFile__${id}`,
1738
+ onChange: (ev) => {
1739
+ onAttach(ev);
1740
+ ev.target.value = "";
1741
+ }
1742
+ }
1743
+ ) }),
1744
+ /* @__PURE__ */ jsx(
1745
+ IconButton,
1746
+ {
1747
+ variant: "icon-outline",
1748
+ onClick: onRecord,
1749
+ disabled: isLoading && !isRecording,
1750
+ sx: {
1751
+ color: isRecording ? "red" : void 0
1752
+ },
1753
+ icon: isRecording ? "Stop" : "Microphone",
1754
+ id: "transcribeAudio",
1755
+ size: "Lg",
1756
+ title: getLabel("lblAiRecordAudio").text
1757
+ }
1758
+ ),
1759
+ /* @__PURE__ */ jsx(
1760
+ IconButton,
1761
+ {
1762
+ title: getLabel("btnUploadFile").text,
1763
+ icon: "File",
1764
+ variant: "icon-outline",
1765
+ disabled: isLoading,
1766
+ onClick: () => {
1767
+ document.getElementById(`gptUploadFile__${id}`).click();
1768
+ },
1769
+ size: "Lg"
1770
+ }
1771
+ ),
1772
+ /* @__PURE__ */ jsxs(Fragment, { children: [
1773
+ ...additionalButtons.map(
1774
+ (x) => x.children
1775
+ )
1776
+ ] }),
1777
+ /* @__PURE__ */ jsx(
1778
+ SimpleButton,
1779
+ {
1780
+ title: getLabel("btnAiSend").title,
1781
+ isLoading,
1782
+ type: "submit",
1783
+ size: "sm",
1784
+ children: getLabel("btnAiSend").text
1785
+ }
1786
+ )
1787
+ ] })
1788
+ ]
1789
+ }
1790
+ )
1791
+ ] });
1792
+ }
1793
+ );
1794
+
1795
+ var __defProp = Object.defineProperty;
1796
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1797
+ var __publicField = (obj, key, value) => {
1798
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
1799
+ return value;
1800
+ };
1801
+ class ChatController2 {
1802
+ constructor(props, onMessageSubmit, id) {
1803
+ this.onMessageSubmit = onMessageSubmit;
1804
+ this.id = id;
1805
+ __publicField(this, "state", {
1806
+ isLoading: false,
1807
+ isRecording: false,
1808
+ canRecord: true,
1809
+ canAttach: true,
1810
+ canAddSystemMessage: true,
1811
+ hideDeleteButton: false,
1812
+ canAddUserMessage: true,
1813
+ maxAttachmentsSize: 100,
1814
+ messages: [],
1815
+ attachments: [],
1816
+ currentMessage: ""
1817
+ });
1818
+ __publicField(this, "Header", () => {
1819
+ return /* @__PURE__ */ jsx(Header, { childComponent: "" });
1820
+ });
1821
+ __publicField(this, "History", () => {
1822
+ return /* @__PURE__ */ jsx(History, { messages: this.state.messages });
1823
+ });
1824
+ __publicField(this, "Attachments", () => {
1825
+ return /* @__PURE__ */ jsx(Attachments, { attachments: this.state.attachments });
1826
+ });
1827
+ __publicField(this, "TextArea", observer(() => {
1828
+ return /* @__PURE__ */ jsx(
1829
+ TextArea,
1830
+ {
1831
+ id: this.id,
1832
+ value: this.state.currentMessage,
1833
+ isLoading: this.state.isLoading,
1834
+ isRecording: this.state.isRecording,
1835
+ onChange: (ev) => {
1836
+ this.state.currentMessage = ev;
1837
+ },
1838
+ onSubmit: () => {
1839
+ const message = new ChatMessage(
1840
+ this.state.currentMessage,
1841
+ "user",
1842
+ this.state.attachments
1843
+ );
1844
+ if (this.state.canAddUserMessage) {
1845
+ this.addMessage(message);
1846
+ }
1847
+ this.onMessageSubmit({
1848
+ message,
1849
+ attachments: this.state.attachments
1850
+ });
1851
+ this.state.attachments = [];
1852
+ this.state.currentMessage = "";
1853
+ },
1854
+ onClearHistory: () => {
1855
+ this.state.messages = [];
1856
+ },
1857
+ onClearAttachments: () => {
1858
+ this.state.attachments = [];
1859
+ },
1860
+ onClearMessage: () => {
1861
+ this.state.currentMessage = "";
1862
+ },
1863
+ onAttach: async (ev) => {
1864
+ const attachments = await Promise.all(
1865
+ [...ev.target.files ? ev.target.files : []].map(
1866
+ (x) => AIFileContent.fromFile(x)
1867
+ )
1868
+ );
1869
+ this.state.attachments.push(...attachments);
1870
+ },
1871
+ onRecord: () => {
1872
+ },
1873
+ onPrev: () => {
1874
+ },
1875
+ onNext: () => {
1876
+ },
1877
+ hideDeleteButton: this.state.hideDeleteButton
1878
+ }
1879
+ );
1880
+ }));
1881
+ __publicField(this, "Renderer", observer(() => {
1882
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1883
+ /* @__PURE__ */ jsx(this.Header, {}),
1884
+ /* @__PURE__ */ jsx(this.History, {}),
1885
+ /* @__PURE__ */ jsx(this.Attachments, {}),
1886
+ /* @__PURE__ */ jsx(this.TextArea, {})
1887
+ ] });
1888
+ }));
1889
+ this.state = Object.assign({}, this.state, props);
1890
+ makeObservable(this, { state: observable });
1891
+ }
1892
+ addMessage(message) {
1893
+ this.state.messages.push(message);
1894
+ }
1895
+ }
1896
+
1897
+ export { AIMessageAttachments, AutoscrollContainer, ChatController, ChatController2, ChatMessage, DashboardsRoutinesGeneration, MultipleChoiceMessage, ResponseStream, RoutinesGeneration, SearchController$1 as SearchController, SemanticSearchReference as SemanticSearchResult, ViewRendererContext, getImageFromDisk, getImagesFromDisk, getImagesWithDescription };
1898
+ //# sourceMappingURL=index.js.map