genassist-chat-react 1.0.38-rc.0 → 1.0.39

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.
Files changed (40) hide show
  1. package/README.md +26 -4
  2. package/dist/components/AudioPlayer.d.ts +11 -0
  3. package/dist/components/AudioPlayer.js +199 -0
  4. package/dist/components/ChatBubble.d.ts +1 -0
  5. package/dist/components/ChatBubble.js +4 -4
  6. package/dist/components/ChatMessage.d.ts +3 -0
  7. package/dist/components/ChatMessage.js +10 -5
  8. package/dist/components/GenAgentChat.js +279 -845
  9. package/dist/components/LiveCallControl.d.ts +25 -0
  10. package/dist/components/LiveCallControl.js +83 -0
  11. package/dist/components/MarkdownMessage.js +23 -1
  12. package/dist/components/VoiceInput.d.ts +1 -3
  13. package/dist/components/VoiceInput.js +262 -48
  14. package/dist/genassist-chat.es.js +16915 -0
  15. package/dist/genassist-chat.umd.js +91 -0
  16. package/dist/hooks/useAudioRecorder.d.ts +8 -0
  17. package/dist/hooks/useAudioRecorder.js +196 -0
  18. package/dist/hooks/useChat.d.ts +4 -0
  19. package/dist/hooks/useChat.js +60 -13
  20. package/dist/hooks/useFileAttachments.d.ts +16 -0
  21. package/dist/hooks/useFileAttachments.js +183 -0
  22. package/dist/hooks/useLiveVoice.d.ts +32 -0
  23. package/dist/hooks/useLiveVoice.js +292 -0
  24. package/dist/hooks/useScrollManagement.d.ts +15 -0
  25. package/dist/hooks/useScrollManagement.js +124 -0
  26. package/dist/hooks/useThinkingAnimation.d.ts +12 -0
  27. package/dist/hooks/useThinkingAnimation.js +53 -0
  28. package/dist/hooks/useViewportManager.d.ts +20 -0
  29. package/dist/hooks/useViewportManager.js +100 -0
  30. package/dist/services/chatService.d.ts +1 -0
  31. package/dist/services/chatService.js +76 -17
  32. package/dist/styles/genAgentChatStyles.d.ts +82 -0
  33. package/dist/styles/genAgentChatStyles.js +441 -0
  34. package/dist/types/index.d.ts +7 -0
  35. package/dist/types/index.js +1 -1
  36. package/package.json +2 -2
  37. package/dist/components/AttachmentPreview.d.ts +0 -8
  38. package/dist/components/AttachmentPreview.js +0 -77
  39. package/dist/utils/urlUtil.d.ts +0 -2
  40. package/dist/utils/urlUtil.js +0 -7
@@ -0,0 +1,183 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
13
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
14
+ return new (P || (P = Promise))(function (resolve, reject) {
15
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
16
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
17
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
18
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
19
+ });
20
+ };
21
+ var __generator = (this && this.__generator) || function (thisArg, body) {
22
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
23
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
24
+ function verb(n) { return function (v) { return step([n, v]); }; }
25
+ function step(op) {
26
+ if (f) throw new TypeError("Generator is already executing.");
27
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
28
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
29
+ if (y = 0, t) op = [op[0] & 2, t.value];
30
+ switch (op[0]) {
31
+ case 0: case 1: t = op; break;
32
+ case 4: _.label++; return { value: op[1], done: false };
33
+ case 5: _.label++; y = op[1]; op = [0]; continue;
34
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
35
+ default:
36
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
37
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
38
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
39
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
40
+ if (t[2]) _.ops.pop();
41
+ _.trys.pop(); continue;
42
+ }
43
+ op = body.call(thisArg, _);
44
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
45
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
46
+ }
47
+ };
48
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
49
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
50
+ if (ar || !(i in from)) {
51
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
52
+ ar[i] = from[i];
53
+ }
54
+ }
55
+ return to.concat(ar || Array.prototype.slice.call(from));
56
+ };
57
+ import { useState, useRef, useEffect } from 'react';
58
+ export function useFileAttachments(_a) {
59
+ var _this = this;
60
+ var uploadFile = _a.uploadFile, t = _a.t;
61
+ var _b = useState([]), attachments = _b[0], setAttachments = _b[1];
62
+ var _c = useState(new Set()), uploadingFiles = _c[0], setUploadingFiles = _c[1];
63
+ var _d = useState(null), fileErrorToast = _d[0], setFileErrorToast = _d[1];
64
+ var fileErrorToastTimeoutRef = useRef(null);
65
+ var fileInputRef = useRef(null);
66
+ useEffect(function () {
67
+ return function () {
68
+ if (fileErrorToastTimeoutRef.current) {
69
+ clearTimeout(fileErrorToastTimeoutRef.current);
70
+ }
71
+ };
72
+ }, []);
73
+ var handleFileChange = function (e) { return __awaiter(_this, void 0, void 0, function () {
74
+ var newFiles_1, newAttachments_1, newUploadingFiles_1, settled, fileToAttachmentMap_1, failedFileKeys_1, hasFailedUploads, error_1, finalUploadingFiles_1;
75
+ var _this = this;
76
+ return __generator(this, function (_a) {
77
+ switch (_a.label) {
78
+ case 0:
79
+ if (!(e.target.files && e.target.files.length > 0)) return [3 /*break*/, 5];
80
+ newFiles_1 = Array.from(e.target.files);
81
+ newAttachments_1 = newFiles_1.map(function (file) { return ({ file: file, attachment: null }); });
82
+ setAttachments(function (prev) { return __spreadArray(__spreadArray([], prev, true), newAttachments_1, true); });
83
+ newUploadingFiles_1 = new Set(uploadingFiles);
84
+ newFiles_1.forEach(function (file) { return newUploadingFiles_1.add(file.name); });
85
+ setUploadingFiles(newUploadingFiles_1);
86
+ _a.label = 1;
87
+ case 1:
88
+ _a.trys.push([1, 3, 4, 5]);
89
+ return [4 /*yield*/, Promise.allSettled(newFiles_1.map(function (file) { return __awaiter(_this, void 0, void 0, function () {
90
+ var _a;
91
+ return __generator(this, function (_b) {
92
+ switch (_b.label) {
93
+ case 0:
94
+ _a = { file: file };
95
+ return [4 /*yield*/, uploadFile(file)];
96
+ case 1: return [2 /*return*/, (_a.attachment = _b.sent(), _a)];
97
+ }
98
+ });
99
+ }); }))];
100
+ case 2:
101
+ settled = _a.sent();
102
+ fileToAttachmentMap_1 = new Map();
103
+ failedFileKeys_1 = new Set();
104
+ settled.forEach(function (result, index) {
105
+ var file = newFiles_1[index];
106
+ if (!file)
107
+ return;
108
+ var fileKey = "".concat(file.name, ":").concat(file.size, ":").concat(file.lastModified);
109
+ if (result.status === 'rejected') {
110
+ fileToAttachmentMap_1.set(fileKey, null);
111
+ failedFileKeys_1.add(fileKey);
112
+ return;
113
+ }
114
+ var attachment = result.value.attachment;
115
+ fileToAttachmentMap_1.set(fileKey, attachment);
116
+ if (attachment === null) {
117
+ failedFileKeys_1.add(fileKey);
118
+ }
119
+ });
120
+ hasFailedUploads = failedFileKeys_1.size > 0;
121
+ setAttachments(function (prev) {
122
+ return prev
123
+ .filter(function (att) {
124
+ var fileKey = "".concat(att.file.name, ":").concat(att.file.size, ":").concat(att.file.lastModified);
125
+ return !failedFileKeys_1.has(fileKey);
126
+ })
127
+ .map(function (att) {
128
+ var fileKey = "".concat(att.file.name, ":").concat(att.file.size, ":").concat(att.file.lastModified);
129
+ var uploadedAttachment = fileToAttachmentMap_1.get(fileKey);
130
+ if (uploadedAttachment !== undefined) {
131
+ return __assign(__assign({}, att), { attachment: uploadedAttachment });
132
+ }
133
+ return att;
134
+ });
135
+ });
136
+ if (hasFailedUploads) {
137
+ if (fileErrorToastTimeoutRef.current) {
138
+ clearTimeout(fileErrorToastTimeoutRef.current);
139
+ }
140
+ setFileErrorToast(t('fileUpload.fileTypeNotSupported', 'This file type is not supported.'));
141
+ fileErrorToastTimeoutRef.current = setTimeout(function () {
142
+ setFileErrorToast(null);
143
+ fileErrorToastTimeoutRef.current = null;
144
+ }, 4000);
145
+ }
146
+ return [3 /*break*/, 5];
147
+ case 3:
148
+ error_1 = _a.sent();
149
+ console.error('Error uploading file', error_1);
150
+ return [3 /*break*/, 5];
151
+ case 4:
152
+ finalUploadingFiles_1 = new Set(uploadingFiles);
153
+ newFiles_1.forEach(function (file) { return finalUploadingFiles_1.delete(file.name); });
154
+ setUploadingFiles(finalUploadingFiles_1);
155
+ if (fileInputRef.current) {
156
+ fileInputRef.current.value = '';
157
+ }
158
+ return [7 /*endfinally*/];
159
+ case 5: return [2 /*return*/];
160
+ }
161
+ });
162
+ }); };
163
+ var handleRemoveAttachment = function (fileName) {
164
+ setAttachments(function (prev) { return prev.filter(function (att) { return att.file.name !== fileName; }); });
165
+ };
166
+ var clearAttachments = function () {
167
+ setAttachments([]);
168
+ if (fileInputRef.current) {
169
+ fileInputRef.current.value = '';
170
+ }
171
+ };
172
+ return {
173
+ attachments: attachments,
174
+ setAttachments: setAttachments,
175
+ uploadingFiles: uploadingFiles,
176
+ fileErrorToast: fileErrorToast,
177
+ fileInputRef: fileInputRef,
178
+ handleFileChange: handleFileChange,
179
+ handleRemoveAttachment: handleRemoveAttachment,
180
+ clearAttachments: clearAttachments,
181
+ };
182
+ }
183
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlRmlsZUF0dGFjaG1lbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2hvb2tzL3VzZUZpbGVBdHRhY2htZW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLE9BQU8sQ0FBQztBQVFwRCxNQUFNLFVBQVUsa0JBQWtCLENBQUMsRUFBNEM7SUFBL0UsaUJBK0dDO1FBL0dvQyxVQUFVLGdCQUFBLEVBQUUsQ0FBQyxPQUFBO0lBQzFDLElBQUEsS0FBZ0MsUUFBUSxDQUF1QixFQUFFLENBQUMsRUFBakUsV0FBVyxRQUFBLEVBQUUsY0FBYyxRQUFzQyxDQUFDO0lBQ25FLElBQUEsS0FBc0MsUUFBUSxDQUFjLElBQUksR0FBRyxFQUFFLENBQUMsRUFBckUsY0FBYyxRQUFBLEVBQUUsaUJBQWlCLFFBQW9DLENBQUM7SUFDdkUsSUFBQSxLQUFzQyxRQUFRLENBQWdCLElBQUksQ0FBQyxFQUFsRSxjQUFjLFFBQUEsRUFBRSxpQkFBaUIsUUFBaUMsQ0FBQztJQUMxRSxJQUFNLHdCQUF3QixHQUFHLE1BQU0sQ0FBdUMsSUFBSSxDQUFDLENBQUM7SUFDcEYsSUFBTSxZQUFZLEdBQUcsTUFBTSxDQUFtQixJQUFJLENBQUMsQ0FBQztJQUVwRCxTQUFTLENBQUM7UUFDUixPQUFPO1lBQ0wsSUFBSSx3QkFBd0IsQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDckMsWUFBWSxDQUFDLHdCQUF3QixDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ2pELENBQUM7UUFDSCxDQUFDLENBQUM7SUFDSixDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFFUCxJQUFNLGdCQUFnQixHQUFHLFVBQU8sQ0FBc0M7Ozs7Ozt5QkFDaEUsQ0FBQSxDQUFDLENBQUMsTUFBTSxDQUFDLEtB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QyxPQUFPLEVBQUUsQ0FBQzt3QkFDekIsWUFBWSxDQUFDLE9BQVEsQ0FBQyxLQUFLLEdBQUcsRUFBRSxDQUFDO29CQUNuQyxDQUFDOzs7OztTQUdOLENBQUM7SUFFRixJQUFNLHNCQUFzQixHQUFHLFVBQUMsUUFBZ0I7UUFDOUMsY0FBYyxDQUFDLFVBQUEsSUFBSSxJQUFJLE9BQUEsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFBLEdBQUcsSUFBSSxPQUFBLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxLQUFLLFFBQVEsRUFBMUIsQ0FBMEIsQ0FBQyxFQUE5QyxDQUE4QyxDQUFDLENBQUM7SUFDekUsQ0FBQyxDQUFDO0lBRUYsSUFBTSxnQkFBZ0IsR0FBRztRQUN2QixjQUFjLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDbkIsSUFBSSxZQUFZLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDekIsWUFBWSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEdBQUcsRUFBRSxDQUFDO1FBQ2xDLENBQUM7SUFDSCxDQUFDLENBQUM7SUFFRixPQUFPO1FBQ0wsV0FBVyxhQUFBO1FBQ1gsY0FBYyxnQkFBQTtRQUNkLGNBQWMsZ0JBQUE7UUFDZCxjQUFjLGdCQUFBO1FBQ2QsWUFBWSxjQUFBO1FBQ1osZ0JBQWdCLGtCQUFBO1FBQ2hCLHNCQUFzQix3QkFBQTtRQUN0QixnQkFBZ0Isa0JBQUE7S0FDakIsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyB1c2VTdGF0ZSwgdXNlUmVmLCB1c2VFZmZlY3QgfSBmcm9tICdyZWFjdCc7XG5pbXBvcnQgeyBBdHRhY2htZW50LCBBdHRhY2htZW50V2l0aEZpbGUgfSBmcm9tICcuLi90eXBlcyc7XG5cbmludGVyZmFjZSBVc2VGaWxlQXR0YWNobWVudHNPcHRpb25zIHtcbiAgdXBsb2FkRmlsZTogKGZpbGU6IEZpbGUpID0+IFByb21pc2U8QXR0YWNobWVudCB8IG51bGw+O1xuICB0OiAoa2V5OiBzdHJpbmcsIGZhbGxiYWNrPzogc3RyaW5nKSA9PiBzdHJpbmc7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB1c2VGaWxlQXR0YWNobWVudHMoeyB1cGxvYWRGaWxlLCB0IH06IFVzZUZpbGVBdHRhY2htZW50c09wdGlvbnMpIHtcbiAgY29uc3QgW2F0dGFjaG1lbnRzLCBzZXRBdHRhY2htZW50c10gPSB1c2VTdGF0ZTxBdHRhY2htZW50V2l0aEZpbGVbXT4oW10pO1xuICBjb25zdCBbdXBsb2FkaW5nRmlsZXMsIHNldFVwbG9hZGluZ0ZpbGVzXSA9IHVzZVN0YXRlPFNldDxzdHJpbmc+PihuZXcgU2V0KCkpO1xuICBjb25zdCBbZmlsZUVycm9yVG9hc3QsIHNldEZpbGVFcnJvclRvYXN0XSA9IHVzZVN0YXRlPHN0cmluZyB8IG51bGw+KG51bGwpO1xuICBjb25zdCBmaWxlRXJyb3JUb2FzdFRpbWVvdXRSZWYgPSB1c2VSZWY8UmV0dXJuVHlwZTx0eXBlb2Ygc2V0VGltZW91dD4gfCBudWxsPihudWxsKTtcbiAgY29uc3QgZmlsZUlucHV0UmVmID0gdXNlUmVmPEhUTUxJbnB1dEVsZW1lbnQ+KG51bGwpO1xuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgIGlmIChmaWxlRXJyb3JUb2FzdFRpbWVvdXRSZWYuY3VycmVudCkge1xuICAgICAgICBjbGVhclRpbWVvdXQoZmlsZUVycm9yVG9hc3RUaW1lb3V0UmVmLmN1cnJlbnQpO1xuICAgICAgfVxuICAgIH07XG4gIH0sIFtdKTtcblxuICBjb25zdCBoYW5kbGVGaWxlQ2hhbmdlID0gYXN5bmMgKGU6IFJlYWN0LkNoYW5nZUV2ZW50PEhUTUxJbnB1dEVsZW1lbnQ+KSA9PiB7XG4gICAgaWYgKGUudGFyZ2V0LmZpbGVzICYmIGUudGFyZ2V0LmZpbGVzLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IG5ld0ZpbGVzID0gQXJyYXkuZnJvbShlLnRhcmdldC5maWxlcyk7XG5cbiAgICAgIGNvbnN0IG5ld0F0dGFjaG1lbnRzOiBBdHRhY2htZW50V2l0aEZpbGVbXSA9IG5ld0ZpbGVzLm1hcChmaWxlID0+ICh7IGZpbGUsIGF0dGFjaG1lbnQ6IG51bGwgfSkpO1xuICAgICAgc2V0QXR0YWNobWVudHMocHJldiA9PiBbLi4ucHJldiwgLi4ubmV3QXR0YWNobWVudHNdKTtcblxuICAgICAgY29uc3QgbmV3VXBsb2FkaW5nRmlsZXMgPSBuZXcgU2V0KHVwbG9hZGluZ0ZpbGVzKTtcbiAgICAgIG5ld0ZpbGVzLmZvckVhY2goZmlsZSA9PiBuZXdVcGxvYWRpbmdGaWxlcy5hZGQoZmlsZS5uYW1lKSk7XG4gICAgICBzZXRVcGxvYWRpbmdGaWxlcyhuZXdVcGxvYWRpbmdGaWxlcyk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHNldHRsZWQgPSBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQoXG4gICAgICAgICAgbmV3RmlsZXMubWFwKGFzeW5jIChmaWxlKSA9PiAoeyBmaWxlLCBhdHRhY2htZW50OiBhd2FpdCB1cGxvYWRGaWxlKGZpbGUpIH0pKVxuICAgICAgICApO1xuXG4gICAgICAgIGNvbnN0IGZpbGVUb0F0dGFjaG1lbnRNYXAgPSBuZXcgTWFwPHN0cmluZywgQXR0YWNobWVudCB8IG51bGw+KCk7XG4gICAgICAgIGNvbnN0IGZhaWxlZEZpbGVLZXlzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgICAgIHNldHRsZWQuZm9yRWFjaCgocmVzdWx0LCBpbmRleCkgPT4ge1xuICAgICAgICAgIGNvbnN0IGZpbGUgPSBuZXdGaWxlc1tpbmRleF07XG4gICAgICAgICAgaWYgKCFmaWxlKSByZXR1cm47XG4gICAgICAgICAgY29uc3QgZmlsZUtleSA9IGAke2ZpbGUubmFtZX06JHtmaWxlLnNpemV9OiR7ZmlsZS5sYXN0TW9kaWZpZWR9YDtcbiAgICAgICAgICBpZiAocmVzdWx0LnN0YXR1cyA9PT0gJ3JlamVjdGVkJykge1xuICAgICAgICAgICAgZmlsZVRvQXR0YWNobWVudE1hcC5zZXQoZmlsZUtleSwgbnVsbCk7XG4gICAgICAgICAgICBmYWlsZWRGaWxlS2V5cy5hZGQoZmlsZUtleSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IHsgYXR0YWNobWVudCB9ID0gcmVzdWx0LnZhbHVlO1xuICAgICAgICAgIGZpbGVUb0F0dGFjaG1lbnRNYXAuc2V0KGZpbGVLZXksIGF0dGFjaG1lbnQpO1xuICAgICAgICAgIGlmIChhdHRhY2htZW50ID09PSBudWxsKSB7XG4gICAgICAgICAgICBmYWlsZWRGaWxlS2V5cy5hZGQoZmlsZUtleSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCBoYXNGYWlsZWRVcGxvYWRzID0gZmFpbGVkRmlsZUtleXMuc2l6ZSA+IDA7XG5cbiAgICAgICAgc2V0QXR0YWNobWVudHMocHJldiA9PiB7XG4gICAgICAgICAgcmV0dXJuIHByZXZcbiAgICAgICAgICAgIC5maWx0ZXIoYXR0ID0+IHtcbiAgICAgICAgICAgICAgY29uc3QgZmlsZUtleSA9IGAke2F0dC5maWxlLm5hbWV9OiR7YXR0LmZpbGUuc2l6ZX06JHthdHQuZmlsZS5sYXN0TW9kaWZpZWR9YDtcbiAgICAgICAgICAgICAgcmV0dXJuICFmYWlsZWRGaWxlS2V5cy5oYXMoZmlsZUtleSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLm1hcChhdHQgPT4ge1xuICAgICAgICAgICAgICBjb25zdCBmaWxlS2V5ID0gYCR7YXR0LmZpbGUubmFtZX06JHthdHQuZmlsZS5zaXplfToke2F0dC5maWxlLmxhc3RNb2RpZmllZH1gO1xuICAgICAgICAgICAgICBjb25zdCB1cGxvYWRlZEF0dGFjaG1lbnQgPSBmaWxlVG9BdHRhY2htZW50TWFwLmdldChmaWxlS2V5KTtcbiAgICAgICAgICAgICAgaWYgKHVwbG9hZGVkQXR0YWNobWVudCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgLi4uYXR0LCBhdHRhY2htZW50OiB1cGxvYWRlZEF0dGFjaG1lbnQgfTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZXR1cm4gYXR0O1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChoYXNGYWlsZWRVcGxvYWRzKSB7XG4gICAgICAgICAgaWYgKGZpbGVFcnJvclRvYXN0VGltZW91dFJlZi5jdXJyZW50KSB7XG4gICAgICAgICAgICBjbGVhclRpbWVvdXQoZmlsZUVycm9yVG9hc3RUaW1lb3V0UmVmLmN1cnJlbnQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzZXRGaWxlRXJyb3JUb2FzdCh0KCdmaWxlVXBsb2FkLmZpbGVUeXBlTm90U3VwcG9ydGVkJywgJ1RoaXMgZmlsZSB0eXBlIGlzIG5vdCBzdXBwb3J0ZWQuJykpO1xuICAgICAgICAgIGZpbGVFcnJvclRvYXN0VGltZW91dFJlZi5jdXJyZW50ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICBzZXRGaWxlRXJyb3JUb2FzdChudWxsKTtcbiAgICAgICAgICAgIGZpbGVFcnJvclRvYXN0VGltZW91dFJlZi5jdXJyZW50ID0gbnVsbDtcbiAgICAgICAgICB9LCA0MDAwKTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgdXBsb2FkaW5nIGZpbGUnLCBlcnJvcik7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBjb25zdCBmaW5hbFVwbG9hZGluZ0ZpbGVzID0gbmV3IFNldCh1cGxvYWRpbmdGaWxlcyk7XG4gICAgICAgIG5ld0ZpbGVzLmZvckVhY2goZmlsZSA9PiBmaW5hbFVwbG9hZGluZ0ZpbGVzLmRlbGV0ZShmaWxlLm5hbWUpKTtcbiAgICAgICAgc2V0VXBsb2FkaW5nRmlsZXMoZmluYWxVcGxvYWRpbmdGaWxlcyk7XG4gICAgICAgIGlmIChmaWxlSW5wdXRSZWYuY3VycmVudCkge1xuICAgICAgICAgIGZpbGVJbnB1dFJlZi5jdXJyZW50IS52YWx1ZSA9ICcnO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIGNvbnN0IGhhbmRsZVJlbW92ZUF0dGFjaG1lbnQgPSAoZmlsZU5hbWU6IHN0cmluZykgPT4ge1xuICAgIHNldEF0dGFjaG1lbnRzKHByZXYgPT4gcHJldi5maWx0ZXIoYXR0ID0+IGF0dC5maWxlLm5hbWUgIT09IGZpbGVOYW1lKSk7XG4gIH07XG5cbiAgY29uc3QgY2xlYXJBdHRhY2htZW50cyA9ICgpID0+IHtcbiAgICBzZXRBdHRhY2htZW50cyhbXSk7XG4gICAgaWYgKGZpbGVJbnB1dFJlZi5jdXJyZW50KSB7XG4gICAgICBmaWxlSW5wdXRSZWYuY3VycmVudC52YWx1ZSA9ICcnO1xuICAgIH1cbiAgfTtcblxuICByZXR1cm4ge1xuICAgIGF0dGFjaG1lbnRzLFxuICAgIHNldEF0dGFjaG1lbnRzLFxuICAgIHVwbG9hZGluZ0ZpbGVzLFxuICAgIGZpbGVFcnJvclRvYXN0LFxuICAgIGZpbGVJbnB1dFJlZixcbiAgICBoYW5kbGVGaWxlQ2hhbmdlLFxuICAgIGhhbmRsZVJlbW92ZUF0dGFjaG1lbnQsXG4gICAgY2xlYXJBdHRhY2htZW50cyxcbiAgfTtcbn1cbiJdfQ==
@@ -0,0 +1,32 @@
1
+ export type LiveVoiceStatus = 'idle' | 'connecting' | 'listening' | 'speaking' | 'error';
2
+ interface UseLiveVoiceOptions {
3
+ baseUrl: string;
4
+ apiKey: string;
5
+ guestToken?: string | null;
6
+ tenant?: string;
7
+ agentId?: string | null;
8
+ conversationId?: string | null;
9
+ language?: string;
10
+ onError?: (error: Error) => void;
11
+ onInputTranscript?: (text: string) => void;
12
+ onOutputTranscript?: (text: string) => void;
13
+ onTurnComplete?: (turn: {
14
+ transcript: string;
15
+ response: string;
16
+ }) => void;
17
+ }
18
+ interface UseLiveVoiceReturn {
19
+ isActive: boolean;
20
+ status: LiveVoiceStatus;
21
+ start: () => Promise<void>;
22
+ stop: () => void;
23
+ }
24
+ /**
25
+ * Continuous, two-way voice conversation with a Voice Agent node.
26
+ *
27
+ * Streams 16 kHz mic PCM up a WebSocket to a persistent Gemini Live session and
28
+ * plays the 24 kHz reply audio back as it arrives (no record/stop/send). Supports
29
+ * barge-in: when the agent is interrupted, queued playback is flushed instantly.
30
+ */
31
+ export declare function useLiveVoice(opts: UseLiveVoiceOptions): UseLiveVoiceReturn;
32
+ export {};
@@ -0,0 +1,292 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ var __generator = (this && this.__generator) || function (thisArg, body) {
11
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
12
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13
+ function verb(n) { return function (v) { return step([n, v]); }; }
14
+ function step(op) {
15
+ if (f) throw new TypeError("Generator is already executing.");
16
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
17
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
18
+ if (y = 0, t) op = [op[0] & 2, t.value];
19
+ switch (op[0]) {
20
+ case 0: case 1: t = op; break;
21
+ case 4: _.label++; return { value: op[1], done: false };
22
+ case 5: _.label++; y = op[1]; op = [0]; continue;
23
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
24
+ default:
25
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29
+ if (t[2]) _.ops.pop();
30
+ _.trys.pop(); continue;
31
+ }
32
+ op = body.call(thisArg, _);
33
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35
+ }
36
+ };
37
+ import { useCallback, useEffect, useRef, useState } from 'react';
38
+ import { createWebSocket } from '../utils/websocket';
39
+ var LIVE_INPUT_SAMPLE_RATE = 16000; // Gemini Live expects 16 kHz mono PCM in
40
+ var LIVE_OUTPUT_SAMPLE_RATE = 24000; // Gemini Live emits 24 kHz mono PCM out
41
+ var CAPTURE_BUFFER_SIZE = 4096;
42
+ /** Downsample a mono Float32 buffer to 16 kHz Int16 PCM (little-endian). */
43
+ function floatTo16kPcm(input, inputRate) {
44
+ var ratio = inputRate / LIVE_INPUT_SAMPLE_RATE;
45
+ var outLength = Math.floor(input.length / ratio);
46
+ var out = new Int16Array(outLength);
47
+ for (var i = 0; i < outLength; i++) {
48
+ var sample = input[Math.floor(i * ratio)] || 0;
49
+ var clamped = Math.max(-1, Math.min(1, sample));
50
+ out[i] = clamped < 0 ? clamped * 0x8000 : clamped * 0x7fff;
51
+ }
52
+ return out.buffer;
53
+ }
54
+ function buildLiveUrl(opts, threadId) {
55
+ // Live voice is a stateful 1:1 audio stream held by the backend, so the plugin
56
+ // connects directly to the backend (not the fan-out websocket service).
57
+ var wsBase = opts.baseUrl.replace(/^http/, 'ws').replace(/\/$/, '');
58
+ var auth = opts.guestToken
59
+ ? "access_token=".concat(encodeURIComponent(opts.guestToken))
60
+ : "api_key=".concat(encodeURIComponent(opts.apiKey));
61
+ var params = [auth, "thread_id=".concat(encodeURIComponent(threadId))];
62
+ if (opts.tenant)
63
+ params.push("x-tenant-id=".concat(encodeURIComponent(opts.tenant)));
64
+ if (opts.language)
65
+ params.push("lang=".concat(encodeURIComponent(opts.language)));
66
+ return "".concat(wsBase, "/api/voice/live/").concat(opts.agentId, "?").concat(params.join('&'));
67
+ }
68
+ /**
69
+ * Continuous, two-way voice conversation with a Voice Agent node.
70
+ *
71
+ * Streams 16 kHz mic PCM up a WebSocket to a persistent Gemini Live session and
72
+ * plays the 24 kHz reply audio back as it arrives (no record/stop/send). Supports
73
+ * barge-in: when the agent is interrupted, queued playback is flushed instantly.
74
+ */
75
+ export function useLiveVoice(opts) {
76
+ var _this = this;
77
+ var _a = useState(false), isActive = _a[0], setIsActive = _a[1];
78
+ var _b = useState('idle'), status = _b[0], setStatus = _b[1];
79
+ var wsRef = useRef(null);
80
+ var streamRef = useRef(null);
81
+ var captureCtxRef = useRef(null);
82
+ var processorRef = useRef(null);
83
+ var playbackCtxRef = useRef(null);
84
+ var playheadRef = useRef(0);
85
+ var sourcesRef = useRef([]);
86
+ var speakingTimerRef = useRef(null);
87
+ // Mirror `isActive` into a ref so async callbacks (e.g. the speaking timer)
88
+ // can read the latest value without being re-created.
89
+ var isActiveRef = useRef(false);
90
+ isActiveRef.current = isActive;
91
+ // Keep the latest callbacks without re-creating start/stop.
92
+ var optsRef = useRef(opts);
93
+ optsRef.current = opts;
94
+ var flushPlayback = useCallback(function () {
95
+ sourcesRef.current.forEach(function (src) {
96
+ try {
97
+ src.stop();
98
+ }
99
+ catch (_a) {
100
+ /* already stopped */
101
+ }
102
+ });
103
+ sourcesRef.current = [];
104
+ if (playbackCtxRef.current) {
105
+ playheadRef.current = playbackCtxRef.current.currentTime;
106
+ }
107
+ }, []);
108
+ var stop = useCallback(function () {
109
+ var _a, _b, _c, _d;
110
+ if (speakingTimerRef.current)
111
+ clearTimeout(speakingTimerRef.current);
112
+ flushPlayback();
113
+ (_a = processorRef.current) === null || _a === void 0 ? void 0 : _a.disconnect();
114
+ processorRef.current = null;
115
+ (_b = streamRef.current) === null || _b === void 0 ? void 0 : _b.getTracks().forEach(function (t) { return t.stop(); });
116
+ streamRef.current = null;
117
+ (_c = captureCtxRef.current) === null || _c === void 0 ? void 0 : _c.close().catch(function () { return undefined; });
118
+ captureCtxRef.current = null;
119
+ (_d = playbackCtxRef.current) === null || _d === void 0 ? void 0 : _d.close().catch(function () { return undefined; });
120
+ playbackCtxRef.current = null;
121
+ if (wsRef.current) {
122
+ wsRef.current.onclose = null;
123
+ try {
124
+ wsRef.current.close();
125
+ }
126
+ catch (_e) {
127
+ /* noop */
128
+ }
129
+ wsRef.current = null;
130
+ }
131
+ setIsActive(false);
132
+ setStatus('idle');
133
+ }, [flushPlayback]);
134
+ var playPcmChunk = useCallback(function (pcm) {
135
+ var ctx = playbackCtxRef.current;
136
+ if (!ctx)
137
+ return;
138
+ var ints = new Int16Array(pcm);
139
+ if (ints.length === 0)
140
+ return;
141
+ var floats = new Float32Array(ints.length);
142
+ for (var i = 0; i < ints.length; i++)
143
+ floats[i] = ints[i] / 0x8000;
144
+ var buffer = ctx.createBuffer(1, floats.length, LIVE_OUTPUT_SAMPLE_RATE);
145
+ buffer.copyToChannel(floats, 0);
146
+ var source = ctx.createBufferSource();
147
+ source.buffer = buffer;
148
+ source.connect(ctx.destination);
149
+ var startAt = Math.max(ctx.currentTime, playheadRef.current);
150
+ source.start(startAt);
151
+ playheadRef.current = startAt + buffer.duration;
152
+ sourcesRef.current.push(source);
153
+ source.onended = function () {
154
+ sourcesRef.current = sourcesRef.current.filter(function (s) { return s !== source; });
155
+ };
156
+ // Reflect "speaking" until the scheduled audio drains.
157
+ setStatus('speaking');
158
+ if (speakingTimerRef.current)
159
+ clearTimeout(speakingTimerRef.current);
160
+ var remainingMs = (playheadRef.current - ctx.currentTime) * 1000 + 150;
161
+ speakingTimerRef.current = setTimeout(function () {
162
+ if (isActiveRef.current)
163
+ setStatus('listening');
164
+ }, remainingMs);
165
+ }, []);
166
+ var handleEvent = useCallback(function (data) {
167
+ var _a, _b, _c, _d, _e, _f, _g;
168
+ var cb = optsRef.current;
169
+ switch (data.type) {
170
+ case 'ready':
171
+ setStatus('listening');
172
+ break;
173
+ case 'input_transcript':
174
+ if (typeof data.text === 'string')
175
+ (_a = cb.onInputTranscript) === null || _a === void 0 ? void 0 : _a.call(cb, data.text);
176
+ break;
177
+ case 'output_transcript':
178
+ if (typeof data.text === 'string')
179
+ (_b = cb.onOutputTranscript) === null || _b === void 0 ? void 0 : _b.call(cb, data.text);
180
+ break;
181
+ case 'interrupted':
182
+ flushPlayback();
183
+ setStatus('listening');
184
+ break;
185
+ case 'turn_complete':
186
+ (_c = cb.onTurnComplete) === null || _c === void 0 ? void 0 : _c.call(cb, {
187
+ transcript: String((_d = data.transcript) !== null && _d !== void 0 ? _d : ''),
188
+ response: String((_e = data.response) !== null && _e !== void 0 ? _e : ''),
189
+ });
190
+ break;
191
+ case 'error':
192
+ (_f = cb.onError) === null || _f === void 0 ? void 0 : _f.call(cb, new Error(String((_g = data.message) !== null && _g !== void 0 ? _g : 'Live voice error')));
193
+ setStatus('error');
194
+ break;
195
+ default:
196
+ break;
197
+ }
198
+ }, [flushPlayback]);
199
+ var start = useCallback(function () { return __awaiter(_this, void 0, void 0, function () {
200
+ var cb, threadId, stream_1, AudioCtx, captureCtx_1, ws_1, err_1;
201
+ var _a, _b;
202
+ return __generator(this, function (_c) {
203
+ switch (_c.label) {
204
+ case 0:
205
+ cb = optsRef.current;
206
+ if (!cb.agentId) {
207
+ (_a = cb.onError) === null || _a === void 0 ? void 0 : _a.call(cb, new Error('Live voice unavailable: agent is still loading'));
208
+ return [2 /*return*/];
209
+ }
210
+ if (wsRef.current)
211
+ return [2 /*return*/]; // already active
212
+ setStatus('connecting');
213
+ // Persistence (transcript/dashboard) keys off an existing conversation UUID.
214
+ // Without one the call still works, but the backend skips saving the turns.
215
+ if (!cb.conversationId) {
216
+ console.warn('[useLiveVoice] No conversationId yet — the live call will run but its ' +
217
+ 'transcripts will not be persisted.');
218
+ }
219
+ threadId = cb.conversationId ||
220
+ (typeof crypto !== 'undefined' && 'randomUUID' in crypto
221
+ ? crypto.randomUUID()
222
+ : "live-".concat(Date.now()));
223
+ _c.label = 1;
224
+ case 1:
225
+ _c.trys.push([1, 3, , 4]);
226
+ return [4 /*yield*/, navigator.mediaDevices.getUserMedia({
227
+ audio: { channelCount: 1, echoCancellation: true, noiseSuppression: true },
228
+ })];
229
+ case 2:
230
+ stream_1 = _c.sent();
231
+ streamRef.current = stream_1;
232
+ AudioCtx = window.AudioContext ||
233
+ window.webkitAudioContext;
234
+ captureCtx_1 = new AudioCtx();
235
+ captureCtxRef.current = captureCtx_1;
236
+ playbackCtxRef.current = new AudioCtx();
237
+ playheadRef.current = playbackCtxRef.current.currentTime;
238
+ ws_1 = createWebSocket(buildLiveUrl(cb, threadId));
239
+ ws_1.binaryType = 'arraybuffer';
240
+ wsRef.current = ws_1;
241
+ ws_1.onopen = function () {
242
+ var source = captureCtx_1.createMediaStreamSource(stream_1);
243
+ // TODO: migrate to AudioWorklet — ScriptProcessorNode is deprecated and
244
+ // runs the downsample on the main thread (can jank on slow devices).
245
+ var processor = captureCtx_1.createScriptProcessor(CAPTURE_BUFFER_SIZE, 1, 1);
246
+ processorRef.current = processor;
247
+ processor.onaudioprocess = function (e) {
248
+ if (ws_1.readyState !== ws_1.OPEN)
249
+ return;
250
+ var pcm = floatTo16kPcm(e.inputBuffer.getChannelData(0), captureCtx_1.sampleRate);
251
+ ws_1.send(pcm);
252
+ };
253
+ source.connect(processor);
254
+ processor.connect(captureCtx_1.destination); // required to drive onaudioprocess
255
+ setIsActive(true);
256
+ setStatus('listening');
257
+ };
258
+ ws_1.onmessage = function (event) {
259
+ if (event.data instanceof ArrayBuffer) {
260
+ playPcmChunk(event.data);
261
+ }
262
+ else if (typeof event.data === 'string') {
263
+ try {
264
+ handleEvent(JSON.parse(event.data));
265
+ }
266
+ catch (_a) {
267
+ /* ignore malformed event */
268
+ }
269
+ }
270
+ };
271
+ ws_1.onerror = function () {
272
+ var _a;
273
+ (_a = cb.onError) === null || _a === void 0 ? void 0 : _a.call(cb, new Error('Live voice connection error'));
274
+ };
275
+ ws_1.onclose = function () {
276
+ stop();
277
+ };
278
+ return [3 /*break*/, 4];
279
+ case 3:
280
+ err_1 = _c.sent();
281
+ (_b = cb.onError) === null || _b === void 0 ? void 0 : _b.call(cb, err_1 instanceof Error ? err_1 : new Error(String(err_1)));
282
+ stop();
283
+ return [3 /*break*/, 4];
284
+ case 4: return [2 /*return*/];
285
+ }
286
+ });
287
+ }); }, [handleEvent, playPcmChunk, stop]);
288
+ // Tear down on unmount.
289
+ useEffect(function () { return function () { return stop(); }; }, [stop]);
290
+ return { isActive: isActive, status: status, start: start, stop: stop };
291
+ }
292
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlTGl2ZVZvaWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2hvb2tzL3VzZUxpdmVWb2ljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxPQUFPLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLE1BQU0sT0FBTyxDQUFDO0FBQ2pFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUVyRCxJQUFNLHNCQUFzQixHQUFHLEtBQUssQ0FBQyxDQUFDLHlDQUF5QztBQUMvRSxJQUFNLHVCQUF1QixHQUFHLEtBQUssQ0FBQyxDQUFDLHdDQUF3QztBQUMvRSxJQUFNLG1CQUFtQixHQUFHLElBQUksQ0FBQztBQWlDakMsNEVBQTRFO0FBQzVFLFNBQVMsYUFBYSxDQUFDLEtBQW1CLEVBQUUsU0FBaUI7SUFDM0QsSUFBTSxLQUFLLEdBQUcsU0FBUyxHQUFHLHNCQUFzQixDQUFDO0lBQ2pELElBQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUMsQ0FBQztJQUNuRCxJQUFNLEdBQUcsR0FBRyxJQUFJLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUN0QyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsU0FBUyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDbkMsSUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2pELElBQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztRQUNsRCxHQUFH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T0FBQSxFQUFFLElBQUksTUFBQSxFQUFFLENBQUM7QUFDM0MsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHVzZUNhbGxiYWNrLCB1c2VFZmZlY3QsIHVzZVJlZiwgdXNlU3RhdGUgfSBmcm9tICdyZWFjdCc7XG5pbXBvcnQgeyBjcmVhdGVXZWJTb2NrZXQgfSBmcm9tICcuLi91dGlscy93ZWJzb2NrZXQnO1xuXG5jb25zdCBMSVZFX0lOUFVUX1NBTVBMRV9SQVRFID0gMTYwMDA7IC8vIEdlbWluaSBMaXZlIGV4cGVjdHMgMTYga0h6IG1vbm8gUENNIGluXG5jb25zdCBMSVZFX09VVFBVVF9TQU1QTEVfUkFURSA9IDI0MDAwOyAvLyBHZW1pbmkgTGl2ZSBlbWl0cyAyNCBrSHogbW9ubyBQQ00gb3V0XG5jb25zdCBDQVBUVVJFX0JVRkZFUl9TSVpFID0gNDA5NjtcblxuZXhwb3J0IHR5cGUgTGl2ZVZvaWNlU3RhdHVzID1cbiAgfCAnaWRsZSdcbiAgfCAnY29ubmVjdGluZydcbiAgfCAnbGlzdGVuaW5nJ1xuICB8ICdzcGVha2luZydcbiAgfCAnZXJyb3InO1xuXG5pbnRlcmZhY2UgVXNlTGl2ZVZvaWNlT3B0aW9ucyB7XG4gIC8vIEJhY2tlbmQgYmFzZSBVUkwgKGh0dHAvaHR0cHMpLiBMaXZlIHZvaWNlIGlzIGEgc3RhdGVmdWwgMToxIGF1ZGlvIHN0cmVhbVxuICAvLyBoZWxkIGJ5IHRoZSBiYWNrZW5kLCBzbyB0aGUgcGx1Z2luIGNvbm5lY3RzIHRoZXJlIGRpcmVjdGx5ICh0aGUgZmFuLW91dFxuICAvLyB3ZWJzb2NrZXQgc2VydmljZSBpcyBub3QgaW52b2x2ZWQpLlxuICBiYXNlVXJsOiBzdHJpbmc7XG4gIGFwaUtleTogc3RyaW5nO1xuICBndWVzdFRva2VuPzogc3RyaW5nIHwgbnVsbDtcbiAgdGVuYW50Pzogc3RyaW5nO1xuICBhZ2VudElkPzogc3RyaW5nIHwgbnVsbDtcbiAgY29udmVyc2F0aW9uSWQ/OiBzdHJpbmcgfCBudWxsO1xuICBsYW5ndWFnZT86IHN0cmluZztcbiAgb25FcnJvcj86IChlcnJvcjogRXJyb3IpID0+IHZvaWQ7XG4gIG9uSW5wdXRUcmFuc2NyaXB0PzogKHRleHQ6IHN0cmluZykgPT4gdm9pZDtcbiAgb25PdXRwdXRUcmFuc2NyaXB0PzogKHRleHQ6IHN0cmluZykgPT4gdm9pZDtcbiAgb25UdXJuQ29tcGxldGU/OiAodHVybjogeyB0cmFuc2NyaXB0OiBzdHJpbmc7IHJlc3BvbnNlOiBzdHJpbmcgfSkgPT4gdm9pZDtcbn1cblxuaW50ZXJmYWNlIFVzZUxpdmVWb2ljZVJldHVybiB7XG4gIGlzQWN0aXZlOiBib29sZWFuO1xuICBzdGF0dXM6IExpdmVWb2ljZVN0YXR1cztcbiAgc3RhcnQ6ICgpID0+IFByb21pc2U8dm9pZD47XG4gIHN0b3A6ICgpID0+IHZvaWQ7XG59XG5cbi8qKiBEb3duc2FtcGxlIGEgbW9ubyBGbG9hdDMyIGJ1ZmZlciB0byAxNiBrSHogSW50MTYgUENNIChsaXR0bGUtZW5kaWFuKS4gKi9cbmZ1bmN0aW9uIGZsb2F0VG8xNmtQY20oaW5wdXQ6IEZsb2F0MzJBcnJheSwgaW5wdXRSYXRlOiBudW1iZXIpOiBBcnJheUJ1ZmZlciB7XG4gIGNvbnN0IHJhdGlvID0gaW5wdXRSYXRlIC8gTElWRV9JTlBVVF9TQU1QTEVfUkFURTtcbiAgY29uc3Qgb3V0TGVuZ3RoID0gTWF0aC5mbG9vcihpbnB1dC5sZW5ndGggLyByYXRpbyk7XG4gIGNvbnN0IG91dCA9IG5ldyBJbnQxNkFycmF5KG91dExlbmd0aCk7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgb3V0TGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBzYW1wbGUgPSBpbnB1dFtNYXRoLmZsb29yKGkgKiByYXRpbyldIHx8IDA7XG4gICAgY29uc3QgY2xhbXBlZCA9IE1hdGgubWF4KC0xLCBNYXRoLm1pbigxLCBzYW1wbGUpKTtcbiAgICBvdXRbaV0gPSBjbGFtcGVkIDwgMCA/IGNsYW1wZWQgKiAweDgwMDAgOiBjbGFtcGVkICogMHg3ZmZmO1xuICB9XG4gIHJldHVybiBvdXQuYnVmZmVyO1xufVxuXG5mdW5jdGlvbiBidWlsZExpdmVVcmwob3B0czogVXNlTGl2ZVZvaWNlT3B0aW9ucywgdGhyZWFkSWQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIC8vIExpdmUgdm9pY2UgaXMgYSBzdGF0ZWZ1bCAxOjEgYXVkaW8gc3RyZWFtIGhlbGQgYnkgdGhlIGJhY2tlbmQsIHNvIHRoZSBwbHVnaW5cbiAgLy8gY29ubmVjdHMgZGlyZWN0bHkgdG8gdGhlIGJhY2tlbmQgKG5vdCB0aGUgZmFuLW91dCB3ZWJzb2NrZXQgc2VydmljZSkuXG4gIGNvbnN0IHdzQmFzZSA9IG9wdHMuYmFzZVVybC5yZXBsYWNlKC9eaHR0cC8sICd3cycpLnJlcGxhY2UoL1xcLyQvLCAnJyk7XG4gIGNvbnN0IGF1dGggPSBvcHRzLmd1ZXN0VG9rZW5cbiAgICA/IGBhY2Nlc3NfdG9rZW49JHtlbmNvZGVVUklDb21wb25lbnQob3B0cy5ndWVzdFRva2VuKX1gXG4gICAgOiBgYXBpX2tleT0ke2VuY29kZVVSSUNvbXBvbmVudChvcHRzLmFwaUtleSl9YDtcbiAgY29uc3QgcGFyYW1zID0gW2F1dGgsIGB0aHJlYWRfaWQ9JHtlbmNvZGVVUklDb21wb25lbnQodGhyZWFkSWQpfWBdO1xuICBpZiAob3B0cy50ZW5hbnQpIHBhcmFtcy5wdXNoKGB4LXRlbmFudC1pZD0ke2VuY29kZVVSSUNvbXBvbmVudChvcHRzLnRlbmFudCl9YCk7XG4gIGlmIChvcHRzLmxhbmd1YWdlKSBwYXJhbXMucHVzaChgbGFuZz0ke2VuY29kZVVSSUNvbXBvbmVudChvcHRzLmxhbmd1YWdlKX1gKTtcbiAgcmV0dXJuIGAke3dzQmFzZX0vYXBpL3ZvaWNlL2xpdmUvJHtvcHRzLmFnZW50SWR9PyR7cGFyYW1zLmpvaW4oJyYnKX1gO1xufVxuXG4vKipcbiAqIENvbnRpbnVvdXMsIHR3by13YXkgdm9pY2UgY29udmVyc2F0aW9uIHdpdGggYSBWb2ljZSBBZ2VudCBub2RlLlxuICpcbiAqIFN0cmVhbXMgMTYga0h6IG1pYyBQQ00gdXAgYSBXZWJTb2NrZXQgdG8gYSBwZXJzaXN0ZW50IEdlbWluaSBMaXZlIHNlc3Npb24gYW5kXG4gKiBwbGF5cyB0aGUgMjQga0h6IHJlcGx5IGF1ZGlvIGJhY2sgYXMgaXQgYXJyaXZlcyAobm8gcmVjb3JkL3N0b3Avc2VuZCkuIFN1cHBvcnRzXG4gKiBiYXJnZS1pbjogd2hlbiB0aGUgYWdlbnQgaXMgaW50ZXJydXB0ZWQsIHF1ZXVlZCBwbGF5YmFjayBpcyBmbHVzaGVkIGluc3RhbnRseS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVzZUxpdmVWb2ljZShvcHRzOiBVc2VMaXZlVm9pY2VPcHRpb25zKTogVXNlTGl2ZVZvaWNlUmV0dXJuIHtcbiAgY29uc3QgW2lzQWN0aXZlLCBzZXRJc0FjdGl2ZV0gPSB1c2VTdGF0ZShmYWxzZSk7XG4gIGNvbnN0IFtzdGF0dXMsIHNldFN0YXR1c10gPSB1c2VTdGF0ZTxMaXZlVm9pY2VTdGF0dXM+KCdpZGxlJyk7XG5cbiAgY29uc3Qgd3NSZWYgPSB1c2VSZWY8V2ViU29ja2V0IHwgbnVsbD4obnVsbCk7XG4gIGNvbnN0IHN0cmVhbVJlZiA9IHVzZVJlZjxNZWRpYVN0cmVhbSB8IG51bGw+KG51bGwpO1xuICBjb25zdCBjYXB0dXJlQ3R4UmVmID0gdXNlUmVmPEF1ZGlvQ29udGV4dCB8IG51bGw+KG51bGwpO1xuICBjb25zdCBwcm9jZXNzb3JSZWYgPSB1c2VSZWY8U2NyaXB0UHJvY2Vzc29yTm9kZSB8IG51bGw+KG51bGwpO1xuICBjb25zdCBwbGF5YmFja0N0eFJlZiA9IHVzZVJlZjxBdWRpb0NvbnRleHQgfCBudWxsPihudWxsKTtcbiAgY29uc3QgcGxheWhlYWRSZWYgPSB1c2VSZWY8bnVtYmVyPigwKTtcbiAgY29uc3Qgc291cmNlc1JlZiA9IHVzZVJlZjxBdWRpb0J1ZmZlclNvdXJjZU5vZGVbXT4oW10pO1xuICBjb25zdCBzcGVha2luZ1RpbWVyUmVmID0gdXNlUmVmPFJldHVyblR5cGU8dHlwZW9mIHNldFRpbWVvdXQ+IHwgbnVsbD4obnVsbCk7XG5cbiAgLy8gTWlycm9yIGBpc0FjdGl2ZWAgaW50byBhIHJlZiBzbyBhc3luYyBjYWxsYmFja3MgKGUuZy4gdGhlIHNwZWFraW5nIHRpbWVyKVxuICAvLyBjYW4gcmVhZCB0aGUgbGF0ZXN0IHZhbHVlIHdpdGhvdXQgYmVpbmcgcmUtY3JlYXRlZC5cbiAgY29uc3QgaXNBY3RpdmVSZWYgPSB1c2VSZWYoZmFsc2UpO1xuICBpc0FjdGl2ZVJlZi5jdXJyZW50ID0gaXNBY3RpdmU7XG5cbiAgLy8gS2VlcCB0aGUgbGF0ZXN0IGNhbGxiYWNrcyB3aXRob3V0IHJlLWNyZWF0aW5nIHN0YXJ0L3N0b3AuXG4gIGNvbnN0IG9wdHNSZWYgPSB1c2VSZWYob3B0cyk7XG4gIG9wdHNSZWYuY3VycmVudCA9IG9wdHM7XG5cbiAgY29uc3QgZmx1c2hQbGF5YmFjayA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICBzb3VyY2VzUmVmLmN1cnJlbnQuZm9yRWFjaCgoc3JjKSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICBzcmMuc3RvcCgpO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8qIGFscmVhZHkgc3RvcHBlZCAqL1xuICAgICAgfVxuICAgIH0pO1xuICAgIHNvdXJjZXNSZWYuY3VycmVudCA9IFtdO1xuICAgIGlmIChwbGF5YmFja0N0eFJlZi5jdXJyZW50KSB7XG4gICAgICBwbGF5aGVhZFJlZi5jdXJyZW50ID0gcGxheWJhY2tDdHhSZWYuY3VycmVudC5jdXJyZW50VGltZTtcbiAgICB9XG4gIH0sIFtdKTtcblxuICBjb25zdCBzdG9wID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIGlmIChzcGVha2luZ1RpbWVyUmVmLmN1cnJlbnQpIGNsZWFyVGltZW91dChzcGVha2luZ1RpbWVyUmVmLmN1cnJlbnQpO1xuICAgIGZsdXNoUGxheWJhY2soKTtcbiAgICBwcm9jZXNzb3JSZWYuY3VycmVudD8uZGlzY29ubmVjdCgpO1xuICAgIHByb2Nlc3NvclJlZi5jdXJyZW50ID0gbnVsbDtcbiAgICBzdHJlYW1SZWYuY3VycmVudD8uZ2V0VHJhY2tzKCkuZm9yRWFjaCgodCkgPT4gdC5zdG9wKCkpO1xuICAgIHN0cmVhbVJlZi5jdXJyZW50ID0gbnVsbDtcbiAgICBjYXB0dXJlQ3R4UmVmLmN1cnJlbnQ/LmNsb3NlKCkuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICBjYXB0dXJlQ3R4UmVmLmN1cnJlbnQgPSBudWxsO1xuICAgIHBsYXliYWNrQ3R4UmVmLmN1cnJlbnQ/LmNsb3NlKCkuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICBwbGF5YmFja0N0eFJlZi5jdXJyZW50ID0gbnVsbDtcbiAgICBpZiAod3NSZWYuY3VycmVudCkge1xuICAgICAgd3NSZWYuY3VycmVudC5vbmNsb3NlID0gbnVsbDtcbiAgICAgIHRyeSB7XG4gICAgICAgIHdzUmVmLmN1cnJlbnQuY2xvc2UoKTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvKiBub29wICovXG4gICAgICB9XG4gICAgICB3c1JlZi5jdXJyZW50ID0gbnVsbDtcbiAgICB9XG4gICAgc2V0SXNBY3RpdmUoZmFsc2UpO1xuICAgIHNldFN0YXR1cygnaWRsZScpO1xuICB9LCBbZmx1c2hQbGF5YmFja10pO1xuXG4gIGNvbnN0IHBsYXlQY21DaHVuayA9IHVzZUNhbGxiYWNrKChwY206IEFycmF5QnVmZmVyKSA9PiB7XG4gICAgY29uc3QgY3R4ID0gcGxheWJhY2tDdHhSZWYuY3VycmVudDtcbiAgICBpZiAoIWN0eCkgcmV0dXJuO1xuICAgIGNvbnN0IGludHMgPSBuZXcgSW50MTZBcnJheShwY20pO1xuICAgIGlmIChpbnRzLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xuICAgIGNvbnN0IGZsb2F0cyA9IG5ldyBGbG9hdDMyQXJyYXkoaW50cy5sZW5ndGgpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW50cy5sZW5ndGg7IGkrKykgZmxvYXRzW2ldID0gaW50c1tpXSAvIDB4ODAwMDtcblxuICAgIGNvbnN0IGJ1ZmZlciA9IGN0eC5jcmVhdGVCdWZmZXIoMSwgZmxvYXRzLmxlbmd0aCwgTElWRV9PVVRQVVRfU0FNUExFX1JBVEUpO1xuICAgIGJ1ZmZlci5jb3B5VG9DaGFubmVsKGZsb2F0cywgMCk7XG4gICAgY29uc3Qgc291cmNlID0gY3R4LmNyZWF0ZUJ1ZmZlclNvdXJjZSgpO1xuICAgIHNvdXJjZS5idWZmZXIgPSBidWZmZXI7XG4gICAgc291cmNlLmNvbm5lY3QoY3R4LmRlc3RpbmF0aW9uKTtcblxuICAgIGNvbnN0IHN0YXJ0QXQgPSBNYXRoLm1heChjdHguY3VycmVudFRpbWUsIHBsYXloZWFkUmVmLmN1cnJlbnQpO1xuICAgIHNvdXJjZS5zdGFydChzdGFydEF0KTtcbiAgICBwbGF5aGVhZFJlZi5jdXJyZW50ID0gc3RhcnRBdCArIGJ1ZmZlci5kdXJhdGlvbjtcbiAgICBzb3VyY2VzUmVmLmN1cnJlbnQucHVzaChzb3VyY2UpO1xuICAgIHNvdXJjZS5vbmVuZGVkID0gKCkgPT4ge1xuICAgICAgc291cmNlc1JlZi5jdXJyZW50ID0gc291cmNlc1JlZi5jdXJyZW50LmZpbHRlcigocykgPT4gcyAhPT0gc291cmNlKTtcbiAgICB9O1xuXG4gICAgLy8gUmVmbGVjdCBcInNwZWFraW5nXCIgdW50aWwgdGhlIHNjaGVkdWxlZCBhdWRpbyBkcmFpbnMuXG4gICAgc2V0U3RhdHVzKCdzcGVha2luZycpO1xuICAgIGlmIChzcGVha2luZ1RpbWVyUmVmLmN1cnJlbnQpIGNsZWFyVGltZW91dChzcGVha2luZ1RpbWVyUmVmLmN1cnJlbnQpO1xuICAgIGNvbnN0IHJlbWFpbmluZ01zID0gKHBsYXloZWFkUmVmLmN1cnJlbnQgLSBjdHguY3VycmVudFRpbWUpICogMTAwMCArIDE1MDtcbiAgICBzcGVha2luZ1RpbWVyUmVmLmN1cnJlbnQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIGlmIChpc0FjdGl2ZVJlZi5jdXJyZW50KSBzZXRTdGF0dXMoJ2xpc3RlbmluZycpO1xuICAgIH0sIHJlbWFpbmluZ01zKTtcbiAgfSwgW10pO1xuXG4gIGNvbnN0IGhhbmRsZUV2ZW50ID0gdXNlQ2FsbGJhY2soKGRhdGE6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSA9PiB7XG4gICAgY29uc3QgY2IgPSBvcHRzUmVmLmN1cnJlbnQ7XG4gICAgc3dpdGNoIChkYXRhLnR5cGUpIHtcbiAgICAgIGNhc2UgJ3JlYWR5JzpcbiAgICAgICAgc2V0U3RhdHVzKCdsaXN0ZW5pbmcnKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdpbnB1dF90cmFuc2NyaXB0JzpcbiAgICAgICAgaWYgKHR5cGVvZiBkYXRhLnRleHQgPT09ICdzdHJpbmcnKSBjYi5vbklucHV0VHJhbnNjcmlwdD8uKGRhdGEudGV4dCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnb3V0cHV0X3RyYW5zY3JpcHQnOlxuICAgICAgICBpZiAodHlwZW9mIGRhdGEudGV4dCA9PT0gJ3N0cmluZycpIGNiLm9uT3V0cHV0VHJhbnNjcmlwdD8uKGRhdGEudGV4dCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnaW50ZXJydXB0ZWQnOlxuICAgICAgICBmbHVzaFBsYXliYWNrKCk7XG4gICAgICAgIHNldFN0YXR1cygnbGlzdGVuaW5nJyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAndHVybl9jb21wbGV0ZSc6XG4gICAgICAgIGNiLm9uVHVybkNvbXBsZXRlPy4oe1xuICAgICAgICAgIHRyYW5zY3JpcHQ6IFN0cmluZyhkYXRhLnRyYW5zY3JpcHQgPz8gJycpLFxuICAgICAgICAgIHJlc3BvbnNlOiBTdHJpbmcoZGF0YS5yZXNwb25zZSA/PyAnJyksXG4gICAgICAgIH0pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2Vycm9yJzpcbiAgICAgICAgY2Iub25FcnJvcj8uKG5ldyBFcnJvcihTdHJpbmcoZGF0YS5tZXNzYWdlID8/ICdMaXZlIHZvaWNlIGVycm9yJykpKTtcbiAgICAgICAgc2V0U3RhdHVzKCdlcnJvcicpO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfSwgW2ZsdXNoUGxheWJhY2tdKTtcblxuICBjb25zdCBzdGFydCA9IHVzZUNhbGxiYWNrKGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBjYiA9IG9wdHNSZWYuY3VycmVudDtcbiAgICBpZiAoIWNiLmFnZW50SWQpIHtcbiAgICAgIGNiLm9uRXJyb3I/LihuZXcgRXJyb3IoJ0xpdmUgdm9pY2UgdW5hdmFpbGFibGU6IGFnZW50IGlzIHN0aWxsIGxvYWRpbmcnKSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICh3c1JlZi5jdXJyZW50KSByZXR1cm47IC8vIGFscmVhZHkgYWN0aXZlXG5cbiAgICBzZXRTdGF0dXMoJ2Nvbm5lY3RpbmcnKTtcbiAgICAvLyBQZXJzaXN0ZW5jZSAodHJhbnNjcmlwdC9kYXNoYm9hcmQpIGtleXMgb2ZmIGFuIGV4aXN0aW5nIGNvbnZlcnNhdGlvbiBVVUlELlxuICAgIC8vIFdpdGhvdXQgb25lIHRoZSBjYWxsIHN0aWxsIHdvcmtzLCBidXQgdGhlIGJhY2tlbmQgc2tpcHMgc2F2aW5nIHRoZSB0dXJucy5cbiAgICBpZiAoIWNiLmNvbnZlcnNhdGlvbklkKSB7XG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICdbdXNlTGl2ZVZvaWNlXSBObyBjb252ZXJzYXRpb25JZCB5ZXQg4oCUIHRoZSBsaXZlIGNhbGwgd2lsbCBydW4gYnV0IGl0cyAnICtcbiAgICAgICAgICAndHJhbnNjcmlwdHMgd2lsbCBub3QgYmUgcGVyc2lzdGVkLicsXG4gICAgICApO1xuICAgIH1cbiAgICBjb25zdCB0aHJlYWRJZCA9XG4gICAgICBjYi5jb252ZXJzYXRpb25JZCB8fFxuICAgICAgKHR5cGVvZiBjcnlwdG8gIT09ICd1bmRlZmluZWQnICYmICdyYW5kb21VVUlEJyBpbiBjcnlwdG9cbiAgICAgICAgPyBjcnlwdG8ucmFuZG9tVVVJRCgpXG4gICAgICAgIDogYGxpdmUtJHtEYXRlLm5vdygpfWApO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHN0cmVhbSA9IGF3YWl0IG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKHtcbiAgICAgICAgYXVkaW86IHsgY2hhbm5lbENvdW50OiAxLCBlY2hvQ2FuY2VsbGF0aW9uOiB0cnVlLCBub2lzZVN1cHByZXNzaW9uOiB0cnVlIH0sXG4gICAgICB9KTtcbiAgICAgIHN0cmVhbVJlZi5jdXJyZW50ID0gc3RyZWFtO1xuXG4gICAgICBjb25zdCBBdWRpb0N0eCA9XG4gICAgICAgIHdpbmRvdy5BdWRpb0NvbnRleHQgfHxcbiAgICAgICAgKHdpbmRvdyBhcyB1bmtub3duIGFzIHsgd2Via2l0QXVkaW9Db250ZXh0OiB0eXBlb2YgQXVkaW9Db250ZXh0IH0pLndlYmtpdEF1ZGlvQ29udGV4dDtcbiAgICAgIGNvbnN0IGNhcHR1cmVDdHggPSBuZXcgQXVkaW9DdHgoKTtcbiAgICAgIGNhcHR1cmVDdHhSZWYuY3VycmVudCA9IGNhcHR1cmVDdHg7XG4gICAgICBwbGF5YmFja0N0eFJlZi5jdXJyZW50ID0gbmV3IEF1ZGlvQ3R4KCk7XG4gICAgICBwbGF5aGVhZFJlZi5jdXJyZW50ID0gcGxheWJhY2tDdHhSZWYuY3VycmVudC5jdXJyZW50VGltZTtcblxuICAgICAgY29uc3Qgd3MgPSBjcmVhdGVXZWJTb2NrZXQoYnVpbGRMaXZlVXJsKGNiLCB0aHJlYWRJZCkpO1xuICAgICAgd3MuYmluYXJ5VHlwZSA9ICdhcnJheWJ1ZmZlcic7XG4gICAgICB3c1JlZi5jdXJyZW50ID0gd3M7XG5cbiAgICAgIHdzLm9ub3BlbiA9ICgpID0+IHtcbiAgICAgICAgY29uc3Qgc291cmNlID0gY2FwdHVyZUN0eC5jcmVhdGVNZWRpYVN0cmVhbVNvdXJjZShzdHJlYW0pO1xuICAgICAgICAvLyBUT0RPOiBtaWdyYXRlIHRvIEF1ZGlvV29ya2xldCDigJQgU2NyaXB0UHJvY2Vzc29yTm9kZSBpcyBkZXByZWNhdGVkIGFuZFxuICAgICAgICAvLyBydW5zIHRoZSBkb3duc2FtcGxlIG9uIHRoZSBtYWluIHRocmVhZCAoY2FuIGphbmsgb24gc2xvdyBkZXZpY2VzKS5cbiAgICAgICAgY29uc3QgcHJvY2Vzc29yID0gY2FwdHVyZUN0eC5jcmVhdGVTY3JpcHRQcm9jZXNzb3IoQ0FQVFVSRV9CVUZGRVJfU0laRSwgMSwgMSk7XG4gICAgICAgIHByb2Nlc3NvclJlZi5jdXJyZW50ID0gcHJvY2Vzc29yO1xuICAgICAgICBwcm9jZXNzb3Iub25hdWRpb3Byb2Nlc3MgPSAoZSkgPT4ge1xuICAgICAgICAgIGlmICh3cy5yZWFkeVN0YXRlICE9PSB3cy5PUEVOKSByZXR1cm47XG4gICAgICAgICAgY29uc3QgcGNtID0gZmxvYXRUbzE2a1BjbShlLmlucHV0QnVmZmVyLmdldENoYW5uZWxEYXRhKDApLCBjYXB0dXJlQ3R4LnNhbXBsZVJhdGUpO1xuICAgICAgICAgIHdzLnNlbmQocGNtKTtcbiAgICAgICAgfTtcbiAgICAgICAgc291cmNlLmNvbm5lY3QocHJvY2Vzc29yKTtcbiAgICAgICAgcHJvY2Vzc29yLmNvbm5lY3QoY2FwdHVyZUN0eC5kZXN0aW5hdGlvbik7IC8vIHJlcXVpcmVkIHRvIGRyaXZlIG9uYXVkaW9wcm9jZXNzXG4gICAgICAgIHNldElzQWN0aXZlKHRydWUpO1xuICAgICAgICBzZXRTdGF0dXMoJ2xpc3RlbmluZycpO1xuICAgICAgfTtcblxuICAgICAgd3Mub25tZXNzYWdlID0gKGV2ZW50OiBNZXNzYWdlRXZlbnQpID0+IHtcbiAgICAgICAgaWYgKGV2ZW50LmRhdGEgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikge1xuICAgICAgICAgIHBsYXlQY21DaHVuayhldmVudC5kYXRhKTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgZXZlbnQuZGF0YSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgaGFuZGxlRXZlbnQoSlNPTi5wYXJzZShldmVudC5kYXRhKSk7XG4gICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICAvKiBpZ25vcmUgbWFsZm9ybWVkIGV2ZW50ICovXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICB3cy5vbmVycm9yID0gKCkgPT4ge1xuICAgICAgICBjYi5vbkVycm9yPy4obmV3IEVycm9yKCdMaXZlIHZvaWNlIGNvbm5lY3Rpb24gZXJyb3InKSk7XG4gICAgICB9O1xuXG4gICAgICB3cy5vbmNsb3NlID0gKCkgPT4ge1xuICAgICAgICBzdG9wKCk7XG4gICAgICB9O1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY2Iub25FcnJvcj8uKGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyIDogbmV3IEVycm9yKFN0cmluZyhlcnIpKSk7XG4gICAgICBzdG9wKCk7XG4gICAgfVxuICB9LCBbaGFuZGxlRXZlbnQsIHBsYXlQY21DaHVuaywgc3RvcF0pO1xuXG4gIC8vIFRlYXIgZG93biBvbiB1bm1vdW50LlxuICB1c2VFZmZlY3QoKCkgPT4gKCkgPT4gc3RvcCgpLCBbc3RvcF0pO1xuXG4gIHJldHVybiB7IGlzQWN0aXZlLCBzdGF0dXMsIHN0YXJ0LCBzdG9wIH07XG59XG4iXX0=
@@ -0,0 +1,15 @@
1
+ import { ChatMessage } from '../types';
2
+ interface UseScrollManagementOptions {
3
+ messages: ChatMessage[];
4
+ isAgentTyping: boolean;
5
+ currentThinkingPartIndex: number;
6
+ currentThinkingPartsLength: number;
7
+ conversationId: string | null | undefined;
8
+ isFloatingOpen: boolean;
9
+ mode: string;
10
+ }
11
+ export declare function useScrollManagement({ messages, isAgentTyping, currentThinkingPartIndex, currentThinkingPartsLength, conversationId, isFloatingOpen, mode, }: UseScrollManagementOptions): {
12
+ messagesEndRef: import("react").RefObject<HTMLDivElement>;
13
+ chatContainerRef: import("react").RefObject<HTMLDivElement>;
14
+ };
15
+ export {};