fmode-ng 0.0.41 → 0.0.43

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 (102) hide show
  1. package/LICENSE.md +8 -0
  2. package/esm2022/fmode-ng.mjs +10 -5
  3. package/esm2022/lib/aigc/agent/agent.prompt.mjs +10 -122
  4. package/esm2022/lib/aigc/agent/index.mjs +10 -2
  5. package/esm2022/lib/aigc/avatar/avatar.module.mjs +10 -45
  6. package/esm2022/lib/aigc/avatar/comp-avatar-particle/avatar.role.mjs +10 -2
  7. package/esm2022/lib/aigc/avatar/comp-avatar-particle/comp-avatar-particle.component.mjs +10 -315
  8. package/esm2022/lib/aigc/avatar/comp-avatar-particle/index.mjs +10 -3
  9. package/esm2022/lib/aigc/avatar/comp-avatar-particle/role-points.class.mjs +10 -57
  10. package/esm2022/lib/aigc/avatar/comp-avatar-role-image/comp-avatar-role-image.component.mjs +10 -97
  11. package/esm2022/lib/aigc/avatar/comp-avatar-role-video/comp-avatar-role-video.component.mjs +10 -104
  12. package/esm2022/lib/aigc/avatar/comp-avatar-talk/comp-avatar-talk.component.mjs +10 -111
  13. package/esm2022/lib/aigc/avatar/index.mjs +10 -8
  14. package/esm2022/lib/aigc/avatar/interface-avatar-role.mjs +10 -2
  15. package/esm2022/lib/aigc/avatar/modal-chat-voice-input/modal-chat-voice-input.component.mjs +8 -166
  16. package/esm2022/lib/aigc/chat/chat-header-area/comp-header-area.component.mjs +10 -36
  17. package/esm2022/lib/aigc/chat/chat-header-area/index.mjs +10 -2
  18. package/esm2022/lib/aigc/chat/chat-list/chat-list.component.mjs +8 -141
  19. package/esm2022/lib/aigc/chat/chat-list/index.mjs +10 -2
  20. package/esm2022/lib/aigc/chat/chat-message-area/comp-message-area.component.mjs +10 -40
  21. package/esm2022/lib/aigc/chat/chat-message-area/index.mjs +10 -2
  22. package/esm2022/lib/aigc/chat/chat-message-card/comp-message-card.component.mjs +10 -92
  23. package/esm2022/lib/aigc/chat/chat-message-card/index.mjs +10 -2
  24. package/esm2022/lib/aigc/chat/chat-modal-input/index.mjs +10 -2
  25. package/esm2022/lib/aigc/chat/chat-modal-input/modal-audio-message/modal-audio-message.component.mjs +8 -207
  26. package/esm2022/lib/aigc/chat/chat-modal-input/modal-input.component.mjs +10 -236
  27. package/esm2022/lib/aigc/chat/chat-panel/chat-panel.component.mjs +10 -137
  28. package/esm2022/lib/aigc/chat/comp-role-prompt/comp-role-prompt.component.mjs +10 -69
  29. package/esm2022/lib/aigc/chat/comp-role-prompt/index.mjs +10 -2
  30. package/esm2022/lib/aigc/chat/index.mjs +10 -8
  31. package/esm2022/lib/aigc/comp-markdown-preview/clipboard.service.mjs +10 -82
  32. package/esm2022/lib/aigc/comp-markdown-preview/markdown-parse.mjs +8 -269
  33. package/esm2022/lib/aigc/comp-markdown-preview/markdown-preview.component.mjs +10 -51
  34. package/esm2022/lib/aigc/comp-markdown-preview/markdown-preview.module.mjs +10 -24
  35. package/esm2022/lib/aigc/comp-markdown-preview/plugins/md-mathjax/index.mjs +10 -94
  36. package/esm2022/lib/aigc/index.mjs +10 -13
  37. package/esm2022/lib/aigc/service-fmai/fmai.service.mjs +10 -21
  38. package/esm2022/lib/aigc/service-fmai/service-chat/chat-class.mjs +8 -736
  39. package/esm2022/lib/aigc/service-fmai/service-chat/chat.service.mjs +8 -181
  40. package/esm2022/lib/aigc/service-fmai/service-chat/index.mjs +10 -7
  41. package/esm2022/lib/aigc/service-fmai/service-chat/mask-list.mjs +9 -194
  42. package/esm2022/lib/aigc/service-fmai/service-chat/pipes/chat-content.pipe.mjs +10 -27
  43. package/esm2022/lib/aigc/service-fmai/service-chat/pipes/hidexml.pipe.mjs +10 -27
  44. package/esm2022/lib/aigc/service-fmai/service-chat/utilnow.pipe.mjs +10 -68
  45. package/esm2022/lib/aigc/service-fmai/service-imagine/imagine.service.mjs +8 -229
  46. package/esm2022/lib/aigc/service-fmai/service-imagine/index.mjs +10 -2
  47. package/esm2022/lib/aigc/voice/audio.player.mjs +10 -52
  48. package/esm2022/lib/aigc/voice/class-asr.mjs +8 -79
  49. package/esm2022/lib/aigc/voice/fmode-voice.service.mjs +8 -501
  50. package/esm2022/lib/aigc/voice/index.mjs +10 -3
  51. package/esm2022/lib/aigc/voice/lib/pcm2wav.mjs +10 -38
  52. package/esm2022/lib/aigc/voice/lib/resample.mjs +10 -34
  53. package/esm2022/lib/aigc/voice/stream.player.mjs +10 -0
  54. package/esm2022/lib/aigc/voice/tts/fmode-tts-class.mjs +8 -233
  55. package/esm2022/lib/aigc/voice/tts/index.mjs +10 -2
  56. package/esm2022/lib/map/comp-poi-picker/comp-poi-picker.component.mjs +10 -190
  57. package/esm2022/lib/map/comp-poi-picker/comp-poi-picker.module.mjs +10 -33
  58. package/esm2022/lib/map/index.mjs +10 -4
  59. package/esm2022/lib/map/map.module.mjs +10 -61
  60. package/esm2022/lib/map/page-loca-scatter/page-loca-scatter.component.mjs +10 -110
  61. package/esm2022/lib/map/page-map.start/page-map.start.component.mjs +8 -98
  62. package/esm2022/lib/map/page-plan-route/page-plan-route.component.mjs +8 -100
  63. package/esm2022/lib/nova-cloud/index.mjs +10 -2
  64. package/esm2022/lib/nova-cloud/nova-cloud.service.mjs +10 -148
  65. package/esm2022/lib/platform/cross.service.mjs +10 -63
  66. package/esm2022/lib/platform/index.mjs +10 -2
  67. package/esm2022/lib/social/index.mjs +10 -2
  68. package/esm2022/lib/social/wechat/wechat-jssdk.service.mjs +8 -236
  69. package/esm2022/lib/storage/comp-hwobs-manager/hwobs-manager.component.mjs +10 -59
  70. package/esm2022/lib/storage/index.mjs +10 -5
  71. package/esm2022/lib/storage/service-hwobs/hwobs.service.mjs +8 -130
  72. package/esm2022/lib/storage/service-upload/index.mjs +10 -2
  73. package/esm2022/lib/storage/service-upload/nova-upload.service.mjs +8 -462
  74. package/esm2022/lib/storage/service-upload/util-file-md5.mjs +10 -28
  75. package/esm2022/lib/storage/storage.module.mjs +10 -41
  76. package/esm2022/lib/user/account/account.service.mjs +10 -221
  77. package/esm2022/lib/user/captcha/captcha.component.mjs +10 -135
  78. package/esm2022/lib/user/comp-user-avatar/comp-user-avatar.component.mjs +10 -62
  79. package/esm2022/lib/user/index.mjs +10 -17
  80. package/esm2022/lib/user/login/auth.guard.mjs +10 -28
  81. package/esm2022/lib/user/login/auth.service.mjs +8 -373
  82. package/esm2022/lib/user/login/login.component.mjs +10 -913
  83. package/esm2022/lib/user/modal-user-login/modal-user-login.component.mjs +10 -273
  84. package/esm2022/lib/user/profile/auth-profile.guard.mjs +10 -27
  85. package/esm2022/lib/user/profile/auth-profile.service.mjs +10 -122
  86. package/esm2022/lib/user/profile/profile-bind/profile-bind.component.mjs +10 -115
  87. package/esm2022/lib/user/profile/profile.module.mjs +10 -57
  88. package/esm2022/lib/user/staff/index.mjs +10 -4
  89. package/esm2022/lib/user/staff/staff.guard.mjs +10 -26
  90. package/esm2022/lib/user/staff/staff.module.mjs +10 -18
  91. package/esm2022/lib/user/staff/staff.service.mjs +10 -85
  92. package/esm2022/lib/user/user-name.pipe.mjs +10 -29
  93. package/esm2022/lib/user/user.module.mjs +10 -106
  94. package/esm2022/lib/video/fm-video/fm-video.component.mjs +10 -67
  95. package/esm2022/lib/video/index.mjs +10 -2
  96. package/esm2022/public-api.mjs +10 -13
  97. package/fesm2022/fmode-ng.mjs +7 -8895
  98. package/fesm2022/fmode-ng.mjs.map +1 -1
  99. package/lib/aigc/voice/fmode-voice.service.d.ts +18 -1
  100. package/lib/aigc/voice/stream.player.d.ts +10 -0
  101. package/lib/aigc/voice/tts/fmode-tts-class.d.ts +2 -2
  102. package/package.json +1 -1
@@ -1,738 +1,10 @@
1
- import { bufferTime, concatMap, Observable, delay, finalize } from "rxjs";
2
- // var bufferTime:any, concatMap:any, Observable:any, Observer:any,delay:any, finalize:any,Observer:any
3
- import Parse from "parse";
4
- import { AgentPrompt } from "../../agent";
5
- import { FmodeTTS } from "../../voice/tts";
6
- import { PromptTemplate } from "@langchain/core/prompts";
7
- // var Parse:any = {}
8
- // const API_BASE:string = "http://127.0.0.1:7337/api/apig/aigc/gpt"
9
- const API_BASE = "https://server.fmode.cn/api/apig/aigc/gpt";
10
- // const API_BASE:string = "https://test.fmode.cn/api/apig/aigc/gpt"
11
- const agentPrompt = new AgentPrompt();
12
- const PromptTplTalkSSMLOutputCode = "talk-ssml-output-tpl";
13
- const PromptTplTalkTextSSMLCode = "talk-text-ssml-tpl";
14
- export function getMessageContentText(content) {
15
- let text = "";
16
- if (typeof content == "string")
17
- text = content;
18
- if (typeof content == "object")
19
- text = content?.find(item => item?.text)?.text || "";
20
- return text;
21
- }
22
- export function getMessageImageUrl(content) {
23
- if (typeof content == "object")
24
- return content?.find(item => item?.image_url)?.image_url?.url || "";
25
- return null;
26
- }
27
- /**
28
- * FmodeChat 聊天对话类
29
- * @public
30
- */
31
- export class FmodeChat {
32
- showAvatar() {
33
- this.avatarConfig = this.role?.get("avatarConfig");
34
- if (this.avatarConfig) {
35
- this.isAvatarShow = true;
36
- if (this.avatarConfig?.image) {
37
- this.avatarConfig.image.waiting = this.avatarConfig.image.waiting || this.role?.get("thumb") || this.role?.get("avatar");
38
- this.avatarMode = "image";
39
- }
40
- if (this.avatarConfig?.video) {
41
- this.avatarConfig.video.waiting = this.avatarConfig.video.waiting;
42
- this.avatarMode = "video";
43
- }
44
- }
45
- }
46
- constructor(sessionId, role, chatSession, chatServ, navCtrl, ncloud, uploadServ) {
47
- this.ChatSession = Parse.Object.extend("ChatSession");
48
- this.messageList = [{ role: "system", content: "系统提示:AI仅供参考" }];
49
- this.latestAIResponse = ``;
50
- this.userInput = ``;
51
- this.userImage = ``;
52
- this.isDirect = false;
53
- /**
54
- * 虚拟形象展示状态
55
- */
56
- this.isAvatarShow = false;
57
- this.avatarMode = "";
58
- /**
59
- * 预置提示词弹窗是否展示
60
- */
61
- this.isPromptModalOpen = false;
62
- this.isPromptMessageAreaShow = true;
63
- this.promptList = [];
64
- this.leftButtons = [
65
- // 提示 当角色配置预设提示词时 显示
66
- { title: "灵感", icon: "color-wand-outline", onClick: () => {
67
- this.isPromptModalOpen = true;
68
- }, show: () => {
69
- return this?.promptList?.length;
70
- } },
71
- { title: "角色", icon: "people-outline", onClick: () => {
72
- this.navCtrl?.navigateRoot("/chat/pro/mask");
73
- }, show: () => { return true; } },
74
- { title: "呼叫", icon: "call-outline", onClick: () => {
75
- this.chatServ?.callRole(this.role);
76
- }, show: () => {
77
- return this?.role?.get('voiceConfig');
78
- } },
79
- ];
80
- /**
81
- * 是否开启语音消息模式(单次)
82
- */
83
- this.isVoiceInputMode = false;
84
- this.isTexting = false;
85
- this.isTalkMode = false;
86
- this.SSMLRoleVoice = "zh-CN-XiaoxiaoNeural";
87
- /**
88
- * 会话Avatar控制
89
- */
90
- this.playAnimation = (animName) => {
91
- console.log(animName);
92
- return;
93
- };
94
- this.welcome = async () => {
95
- let msglist = this.messageList?.filter(item => item?.role == "assistant");
96
- if (msglist?.length)
97
- return; // 已有对话不开场问候
98
- let user = Parse.User.current();
99
- let person = await this.loadSelf("Person", "userVerify");
100
- let profile = await this.loadSelf("Profile", "user");
101
- let name = user?.get("realname") || profile?.get("name") || person?.get("name") || user?.get("nickname") || user?.get("name");
102
- // 问候语/首个话题
103
- let tpl = this.role.get("voiceConfig")?.welcome?.prompt;
104
- if (!tpl)
105
- return; // 无模板则返回
106
- let welcomeContent = await PromptTemplate.fromTemplate(tpl, {
107
- templateFormat: "mustache"
108
- }).format({
109
- name: name,
110
- timeOfDay: this.getTimeOfDay()
111
- });
112
- // let callName = name?`${name},`:"";
113
- // let callTime = `${this.getTimeOfDay()}好`;
114
- // let welcomeContent = `${callName}${callTime},期待聆听您的人生故事,想和我聊些什么呢?`;
115
- // 生成ChatVoice并播放
116
- let voice = await this.getVoiceByContentText(welcomeContent);
117
- let message = {
118
- role: "assistant",
119
- voice: voice,
120
- content: welcomeContent,
121
- complete: true
122
- };
123
- this.voiceMap[voice?.id];
124
- this.playChatVoice(this.voiceMap[voice?.id]);
125
- this.messageList.push(message);
126
- };
127
- this.self = {};
128
- this.voiceMap = {};
129
- this.chatServ = chatServ;
130
- this.role = role;
131
- this.sessionId = sessionId;
132
- this.navCtrl = navCtrl;
133
- this.ncloud = ncloud;
134
- this.uploadServ = uploadServ;
135
- if (chatSession?.id) {
136
- this.chatSession = chatSession;
137
- this.messageList = this.chatSession.get("messageList");
138
- this.sessionId = chatSession?.id;
139
- }
140
- if (this.role?.id) {
141
- this.voiceConfig = this.role?.get("voiceConfig");
142
- if (this.voiceConfig?.autoTalk) {
143
- this.isTalkMode = true;
144
- this.isDirect = true;
145
- }
146
- }
147
- }
148
- getTimeOfDay() {
149
- const now = new Date();
150
- const hours = now.getHours();
151
- if (hours >= 5 && hours < 12) {
152
- return "早上";
153
- }
154
- else if (hours >= 12 && hours < 14) {
155
- return "中午";
156
- }
157
- else if (hours >= 14 && hours < 18) {
158
- return "下午";
159
- }
160
- else {
161
- return "晚上";
162
- }
163
- }
164
- async loadSelf(className, userKey) {
165
- if (this.self[className])
166
- return this.self[className];
167
- let user = Parse.User.current();
168
- let query = new Parse.Query(className);
169
- query.equalTo(userKey, user?.id);
170
- this.self[className] = await query.first();
171
- }
1
+
172
2
  /**
173
- * 对话模型提示词
3
+ * @copyright © 未来飞马 © 未来全栈 www.fmode.cn
4
+ * 版权所有 © 未来飞马 © 江西脑控科技有限公司 Copyright © Fmode Technology Co., Ltd.
5
+ * 保留所有权利 All Rights Reserved.
6
+ * /home/ryan/workspace/nova/nova-admin/dist/fmode-ng/esm2022/lib/aigc/service-fmai/service-chat/chat-class.mjs
174
7
  */
175
- async loadTalkSystemPrompt(role) {
176
- if (!this.isTalkMode)
177
- return;
178
- if (!role)
179
- return;
180
- // 加载声音模型:默认为晓晓
181
- if (role?.get('gender') == '男') {
182
- this.SSMLRoleVoice = "zh-CN-YunyeNeural";
183
- }
184
- else {
185
- this.SSMLRoleVoice = "zh-CN-XiaoxiaoNeural";
186
- }
187
- this.SSMLRoleVoice = role?.get("voiceConfig")?.voice || this.SSMLRoleVoice;
188
- let SSMLPromptTemplate = await agentPrompt.getFormatTpl(PromptTplTalkSSMLOutputCode, {
189
- SSMLRoleVoice: this.SSMLRoleVoice, // SSML
190
- });
191
- let prompt = role.get("prompt") || "请你扮演飞码AI的人工智能专家。";
192
- prompt += SSMLPromptTemplate;
193
- let promptMsg = { role: "user", content: prompt, hidden: true };
194
- // 查重
195
- let content = this.messageList?.map(item => item?.content).join();
196
- if (content.indexOf(prompt) > -1) {
197
- // 提示词已经存在
198
- return;
199
- }
200
- // 补全提示词
201
- let systemIndex = this.messageList?.findIndex(item => item?.role == "system");
202
- let insertIndex = systemIndex + 1;
203
- this.messageList.splice(insertIndex, 0, promptMsg);
204
- return;
205
- }
206
- /**
207
- * 角色提示词
208
- * @returns
209
- */
210
- loadRolePrompt() {
211
- // 角色提示
212
- let prompt = this.role?.get("prompt");
213
- let promptMsg = { role: "user", content: prompt, hidden: true };
214
- if (!prompt)
215
- return; // 无提示词无需添加
216
- // 内容检查
217
- let content = this.messageList?.map(item => item?.content).join();
218
- if (content.indexOf(prompt) > -1) {
219
- // 提示词已经存在
220
- return;
221
- }
222
- // 补全提示词
223
- let systemIndex = this.messageList?.findIndex(item => item?.role == "system");
224
- let insertIndex = systemIndex + 1;
225
- this.messageList.splice(insertIndex, 0, promptMsg);
226
- // console.log(this.messageList)
227
- }
228
- /**
229
- * 发送消息
230
- * @param message
231
- * @param imageUrl
232
- */
233
- async sendMessage(message = "FmodeAiTest测试问题", imageUrl, onComplete, eventMap, voice) {
234
- // 为消息列表补全提示词
235
- // await this.loadTalkSystemPrompt(this.role);
236
- this.isPromptMessageAreaShow = false; // 发送第一条消息后,关闭提示看板
237
- this.loadRolePrompt();
238
- // 用户输入消息,添加到历史消息清单中
239
- if (!imageUrl) { // 纯文本
240
- // console.log("纯文本")
241
- let msg = {
242
- role: "user",
243
- content: message,
244
- complete: true,
245
- createdAt: new Date()
246
- };
247
- if (voice) {
248
- msg.voice = { id: voice?.id, duration: voice?.duration };
249
- }
250
- this.messageList.push(msg);
251
- }
252
- else { // 带图片
253
- let msg = {
254
- "role": "user",
255
- "content": [
256
- {
257
- "type": "image_url",
258
- "image_url": { "url": imageUrl },
259
- },
260
- {
261
- "type": "text",
262
- "text": message
263
- },
264
- ],
265
- complete: true,
266
- createdAt: new Date()
267
- };
268
- if (voice) {
269
- msg.voice = { id: voice?.id };
270
- }
271
- this.messageList.push({
272
- "role": "user",
273
- "content": [
274
- {
275
- "type": "image_url",
276
- "image_url": { "url": imageUrl },
277
- },
278
- {
279
- "type": "text",
280
- "text": message
281
- },
282
- ],
283
- complete: true,
284
- createdAt: new Date()
285
- });
286
- }
287
- // 创建并发起一条新的消息补全
288
- // console.log("send",this.messageList)
289
- let completion = new FmodeChatCompletion(this.fixMessageList(this.messageList), {
290
- model: this.chatServ?.currentModel?.get("code") || "fmode-4.5-128k"
291
- });
292
- this.userInput = "";
293
- this.userImage = "";
294
- // console.log(this.chatServ?.currentModel?.toJSON())
295
- // 持续更新事件推送的消息体内容至消息列表
296
- let isDirect = this.isDirect || false;
297
- if (this.isTalkMode) {
298
- isDirect = true;
299
- }
300
- let send$ = completion.sendCompletion({
301
- isDirect: isDirect,
302
- onComplete: onComplete || null
303
- }).pipe(finalize(async () => {
304
- if (this.isTalkMode) {
305
- let content = this.messageList[completion.indexOfList]?.content;
306
- let voice = await this.getVoiceByContentText(content, eventMap);
307
- eventMap?.onSSMLComplete && eventMap?.onSSMLComplete(voice);
308
- this.messageList[completion.indexOfList].voice = voice;
309
- this.playChatVoice(this.voiceMap[voice?.id]);
310
- }
311
- this.messageList[completion.indexOfList].complete = true;
312
- })).subscribe(message => {
313
- this.messageList[completion.indexOfList] = message;
314
- this.latestAIResponse = this.getContentText(message?.content);
315
- let savedList = this.chatSession?.get("messageList")?.length;
316
- // 生命周期:会话创建后,有新消息时,创建保存会话
317
- if (this.messageList?.length > savedList) {
318
- // console.log("cycle新会话")
319
- this.saveChatSession();
320
- }
321
- if (message?.complete) {
322
- // 生命周期:消息发送完成后,保存聊天记录
323
- this.saveChatSession();
324
- send$.unsubscribe();
325
- }
326
- // console.log(message)
327
- });
328
- }
329
- getVoiceByContentText(content, eventMap, promptEnabled = false) {
330
- let contentText = this.getContentText(content);
331
- let ChatVoice = Parse.Object.extend("ChatVoice");
332
- let chatVoice = new ChatVoice();
333
- let contentSSML = ``;
334
- this.SSMLRoleVoice = this.role?.get("voiceConfig")?.voice || this.SSMLRoleVoice;
335
- return new Promise(async (resolve, reject) => {
336
- let resolveChatVoice = async () => {
337
- chatVoice.set("content", contentText);
338
- chatVoice.set("ssml", contentSSML);
339
- chatVoice.set("role", "assistant");
340
- let company = localStorage.getItem("company");
341
- company && chatVoice.set("company", { __type: "Pointer", className: "Company", objectId: company });
342
- Parse.User.current()?.id && chatVoice.set("user", Parse.User.current().toPointer());
343
- this.chatSession?.id && chatVoice.set("session", this.chatSession?.toPointer());
344
- chatVoice = await chatVoice.save();
345
- this.voiceMap[chatVoice?.id] = chatVoice;
346
- resolve({
347
- id: chatVoice?.id,
348
- });
349
- };
350
- /**
351
- * 方法一:高级语音直接读文本,速度快,但细节情绪标记不足。
352
- */
353
- if (promptEnabled == false) {
354
- contentSSML = `<speak xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="http://www.w3.org/2001/mstts" xmlns:emo="http://www.w3.org/2009/10/emotionml" version="1.0" xml:lang="zh-CN"><voice name="${this.SSMLRoleVoice}">${contentText}</voice></speak>`;
355
- resolveChatVoice();
356
- }
357
- /**
358
- * promptEnabled == true
359
- * 方法二:通过大模型再次拼接SSML脚本,实现更优质的语音标记,但是生成时间太慢
360
- */
361
- if (promptEnabled == true) {
362
- // 拼接Prompt
363
- let TextSSMLPrompt = await agentPrompt.getFormatTpl(PromptTplTalkTextSSMLCode, {
364
- content: contentText, // 文本内容
365
- SSMLRoleVoice: this.SSMLRoleVoice, // SSML 演说者
366
- });
367
- // 生成SSML
368
- let completion = new FmodeChatCompletion(this.fixMessageList([{
369
- role: "user",
370
- content: TextSSMLPrompt
371
- }]), {
372
- model: this.chatServ?.currentModel?.get("code") || "fmode-4.5-128k"
373
- });
374
- let send$ = completion.sendCompletion({
375
- isDirect: true,
376
- }).subscribe(async (message) => {
377
- if (message?.complete) {
378
- contentSSML = this.getContentText(message?.content);
379
- resolveChatVoice();
380
- }
381
- });
382
- }
383
- });
384
- }
385
- getContentText(content) {
386
- if (typeof content == "string") {
387
- return content;
388
- }
389
- else {
390
- return content?.[0]?.text || ``;
391
- }
392
- }
393
- async initTTS() {
394
- // if(this.tts) return // 待明确sts有效期和次数进行优化,避免每次重复获取
395
- let config = await this.ncloud.apig("voice/tts/token", { company: localStorage.getItem("company") });
396
- // 有TTS资源,使用情绪合成
397
- console.log(config);
398
- if (config?.token) {
399
- let tts = new FmodeTTS(config, this.uploadServ);
400
- this.tts = tts;
401
- }
402
- }
403
- async playChatVoice(voice, eventMap) {
404
- await this.initTTS();
405
- // console.log(this.tts)
406
- if (this.tts) {
407
- try {
408
- // console.log(textOrSSML)
409
- // 完整的消息,通过TTS合成进行讲话
410
- this.playAnimation("talking"); // Talking动画,暂时用wating代替
411
- await this.tts.speakAsync(voice?.get("ssml"), voice, {
412
- onLoaded: (audio) => {
413
- eventMap?.onLoaded && eventMap?.onLoaded(audio); // 事件传递
414
- },
415
- onStop: () => {
416
- eventMap?.onStop && eventMap?.onStop(); // 事件传递
417
- this.playAnimation("waiting"); // Talking动画,暂时用wating代替
418
- }
419
- });
420
- }
421
- catch (ttserr) {
422
- console.error(ttserr);
423
- }
424
- }
425
- // 无TSS资源,调用Edge Speech
426
- }
427
- /**
428
- * 保存单次会话
429
- */
430
- async saveChatSession() {
431
- if (this.sessionId == "new") {
432
- this.chatSession = new this.ChatSession();
433
- }
434
- this.chatSession.set("title", this.genTitle());
435
- this.chatSession.set("role", this.role?.toPointer());
436
- this.chatSession.set("messageList", this.messageList);
437
- this.chatSession.set("user", Parse.User.current()?.toPointer());
438
- this.chatSession = await this.chatSession.save();
439
- this.sessionId = this.chatSession?.id;
440
- if (this.sessionId) {
441
- // 修改URL地址为sessionId,方便分享或切换 角色页面 => 会话页面
442
- let newHref = `${window.location.origin}/chat/pro/chat/${this.sessionId}`;
443
- if (window.location?.pathname?.indexOf("chat/session") > -1) {
444
- newHref = `${window.location.origin}/chat/session/chat/${this.sessionId}`;
445
- }
446
- newHref = this.getInviteUrl(newHref);
447
- window.history.replaceState(null, null, newHref + window.location.search);
448
- // 修改最新条chatList数据
449
- let newChat = {
450
- sid: this.chatSession?.id,
451
- rid: this.role?.id,
452
- name: this.role?.get('name'),
453
- message: this.chatSession?.get('messageList')?.[this.chatSession?.get('messageList')?.length - 1]?.content?.slice(0, 20),
454
- latest: this.chatSession?.createdAt
455
- };
456
- if (!this.chatServ?.chatList?.length)
457
- this.chatServ.chatList = [];
458
- let index = this.chatServ?.chatList?.find(item => item?.sid == newChat?.sid);
459
- if (index > -1) {
460
- this.chatServ.chatList[index] = newChat;
461
- }
462
- else {
463
- this.chatServ?.chatList.unshift(newChat);
464
- }
465
- }
466
- }
467
- getInviteUrl(url) {
468
- // 判断是否有参数
469
- let connectChar = "?";
470
- if (url?.indexOf("?") > -1) {
471
- connectChar = "&";
472
- }
473
- else {
474
- connectChar = "?";
475
- }
476
- // 附加invite参数
477
- let id = Parse.User?.current()?.id;
478
- if (url?.indexOf("invite=" + id) == -1) {
479
- if (!id)
480
- return url;
481
- url += connectChar + 'invite=' + id;
482
- }
483
- return url;
484
- }
485
- // 根据聊天内容及问题,生成标题
486
- genTitle() {
487
- if (this.title)
488
- return this.title;
489
- let content = this.messageList.find(item => item.role == "user")?.content;
490
- if (typeof content == "string") { // 截图文本内容文字部分
491
- this.title = content?.slice(0, 15) || "";
492
- }
493
- if (typeof content == "object") { // 截图复合内容文字部分
494
- this.title = content?.find(item => item?.text)?.text || "";
495
- }
496
- return this.title;
497
- }
498
- fixMessageList(messages) {
499
- return messages.map(msg => { return { role: msg.role, content: msg.content }; });
500
- }
501
- nowStr() {
502
- let now = new Date();
503
- return `${now.getFullYear()}/${now.getMonth() + 1}/${now.getDate()} ${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`;
504
- }
505
- }
506
- /**
507
- * FmodeChatCompletion 文本补全类
508
- * @public
509
- */
510
- export class FmodeChatCompletion {
511
- constructor(messages, options) {
512
- this.content = ""; // 本次接收消息结果
513
- this.contentBuffer = [];
514
- this.isCompleted = false;
515
- this.indexOfList = Number(messages.length);
516
- this.messages = messages;
517
- this.model = options?.model || "fmode-4.5-128k";
518
- }
519
- /**
520
- * @param options
521
- * @param options.isDirect 是否不等待逐字获取,直接完成内容推送
522
- * @param options.intTime 是否不等待逐字获取,直接完成内容推送
523
- * @returns
524
- */
525
- sendCompletion(options = {}) {
526
- options.intTime = options?.intTime || 50; // 按毫秒逐字推送
527
- options.isDirect = options?.isDirect || false;
528
- if (options?.isDirect)
529
- options.intTime = 1;
530
- let that = this;
531
- let opts = {
532
- "messages": this.messages,
533
- "stream": true,
534
- "model": this.model,
535
- "temperature": 0.5,
536
- "presence_penalty": 0,
537
- "frequency_penalty": 0
538
- };
539
- // console.log(opts)
540
- let $messageReceiver = new Observable((observer) => {
541
- let subscription = RequestFmodeChatApi("/v1/chat/completions", opts)
542
- .subscribe(data => {
543
- // Handle each chunk of data
544
- /** Chunk文本数据格式如下:
545
- 正常消息:
546
- 'data: {"id":"chatcmpl-y2PLKqPDnwAFJIj2L5aqdH5TWK9Yv","object":"chat.completion.chunk","created":1696770162,"model":"gpt-3.5-turbo-0613","choices":[{"index":0,"delta":{"content":"本提示词仅用于测试。"},"finish_reason":null}]}',
547
- 终止原因:
548
- 'data: {"id":"chatcmpl-y2PLKqPDnwAFJIj2L5aqdH5TWK9Yv","object":"chat.completion.chunk","created":1696770162,"model":"gpt-3.5-turbo-0613","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}',
549
- 结束消息:
550
- 'data: [DONE]'
551
- */
552
- let chunk = String(data);
553
- // Check if the completion message is received
554
- // console.log(chunk)
555
- if (chunk == 'data: [DONE]') {
556
- this.isCompleted = true; // 标记完成 => 等待interval推送
557
- // console.log(options?.isDirect,this.isCompleted)
558
- if (options?.isDirect && this.isCompleted) {
559
- observer.next({
560
- role: "assistant",
561
- // cid:chunkjson?.['id'],
562
- content: this.content,
563
- complete: true, // 推送完成
564
- createdAt: new Date()
565
- });
566
- subscription.unsubscribe(); // Unsubscribe when done
567
- options?.onComplete && options.onComplete({
568
- role: "assistant",
569
- // cid:chunkjson?.['id'],
570
- content: this.content,
571
- complete: true, // 推送完成
572
- createdAt: new Date()
573
- });
574
- observer.complete();
575
- }
576
- }
577
- // console.log(chunk)
578
- if (chunk.indexOf("data:\ {") > -1) {
579
- let chunkjson = chunkToJson(chunk);
580
- // console.log(chunk)
581
- // console.log(chunkjson?.choices?.[0]?.delta)
582
- let words = chunkjson?.choices?.[0]?.delta?.content || "";
583
- this.contentBuffer.push(words);
584
- // 消息返回模式:定时器推送,模拟逐字输出
585
- if (options?.isDirect) {
586
- this.content += (words || "");
587
- // 默认累加消息结果
588
- if (!this.isCompleted) {
589
- observer.next({
590
- role: "assistant",
591
- cid: chunkjson?.['id'],
592
- content: this.content,
593
- createdAt: new Date()
594
- });
595
- }
596
- }
597
- if (!options?.isDirect && !this.contentPusher) {
598
- this.contentPusher = setInterval(() => {
599
- if (this.isCompleted && this.contentBuffer?.length == 0) { // 推送完毕,清除计时器
600
- observer.next({
601
- role: "assistant",
602
- cid: chunkjson?.['id'],
603
- content: this.content,
604
- complete: true, // 推送完成
605
- createdAt: new Date()
606
- });
607
- subscription.unsubscribe(); // Unsubscribe when done
608
- clearInterval(this.contentPusher);
609
- observer.complete();
610
- }
611
- if (this.contentBuffer?.length >= 0) {
612
- if (this.contentBuffer?.length > 0) {
613
- this.content += this.contentBuffer.shift();
614
- }
615
- observer.next({
616
- role: "assistant",
617
- cid: chunkjson?.['id'],
618
- content: this.content,
619
- createdAt: new Date()
620
- });
621
- }
622
- }, options?.intTime);
623
- }
624
- // console.log(this.content)
625
- }
626
- });
627
- });
628
- return $messageReceiver.pipe(bufferTime(100), // 每100ms收集消息
629
- concatMap(messages => messages), // 使用 concatMap 逐个发送消息
630
- delay(200) // 延迟200ms输出每条消息
631
- );
632
- }
633
- }
634
- function chunkToJson(chunk) {
635
- let chunkjson;
636
- try {
637
- chunkjson = JSON.parse(chunk.replaceAll("data:\ ", ""));
638
- }
639
- catch (errdj) {
640
- console.error(errdj);
641
- }
642
- return chunkjson || {};
643
- }
644
- function RequestFmodeChatApi(apipath, body, method = "POST") {
645
- return new Observable((observer) => {
646
- let url = API_BASE + apipath;
647
- let API_TOKEN = Parse.User.current()?.getSessionToken() || localStorage.getItem("FMODE_AI_TOKEN");
648
- // 通过body传递token参数,避免no-cors模式下Authoriztion头部无效
649
- let AUTH_TOKEN = `Bearer ${API_TOKEN}`;
650
- body.token = AUTH_TOKEN;
651
- if (body)
652
- body = JSON.stringify(body);
653
- fetch(url, {
654
- "headers": {
655
- // "Authorization": AUTH_TOKEN,
656
- "Content-Type": "text/plain",
657
- "Cache-Control": "no-cache"
658
- },
659
- "body": body || null,
660
- "method": method,
661
- "credentials": "omit",
662
- "mode": "cors"
663
- }).then(response => {
664
- let isStream = true || response.headers?.get("Content-Type")?.indexOf("text/event-stream") > -1;
665
- let remainingData = ``;
666
- function processData(data) {
667
- let combinedData = remainingData + data;
668
- let messages = combinedData.split('\n');
669
- if (messages?.length > 1) { // 至少分割2条消息时进行处理
670
- // 处理每个完整的消息
671
- for (let i = 0; i < messages.length - 1; i++) {
672
- let message = messages[i];
673
- observer.next(message);
674
- }
675
- // 保存最后一个不完整的消息
676
- remainingData = messages[messages.length - 1];
677
- }
678
- }
679
- if (isStream) {
680
- let greader = response.body?.getReader();
681
- const decoder = new TextDecoder();
682
- let rstream = new ReadableStream({
683
- start(controller) {
684
- function read() {
685
- greader.read().then(({ done, value }) => {
686
- if (done) {
687
- controller.close();
688
- observer.complete(); // Complete the observer when stream processing is done
689
- return;
690
- }
691
- controller.enqueue(value);
692
- read();
693
- });
694
- }
695
- read();
696
- }
697
- });
698
- let reader = rstream.getReader();
699
- function processStream({ done, value }) {
700
- if (done) {
701
- return;
702
- }
703
- let text = decoder.decode(value);
704
- processData(text); // Emit each chunk of data
705
- reader.read().then(processStream);
706
- }
707
- reader.read().then(processStream);
708
- }
709
- })
710
- .catch(error => observer.error(error)); // Handle any errors
711
- // Return the subscription logic
712
- return () => {
713
- // Clean up logic, if needed
714
- };
715
- });
716
- }
717
- function JsonToFormData(json) {
718
- const formData = new FormData();
719
- function appendFormData(data, path = '') {
720
- if (Array.isArray(data)) {
721
- data.forEach((value, index) => {
722
- appendFormData(value, `${path}[${index}]`);
723
- });
724
- }
725
- else if (typeof data === 'object' && data !== null) {
726
- Object.keys(data).forEach(key => {
727
- const newPath = path ? `${path}.${key}` : key;
728
- appendFormData(data[key], newPath);
729
- });
730
- }
731
- else {
732
- formData.append(path, data);
733
- }
734
- }
735
- appendFormData(json);
736
- return formData;
737
- }
738
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhdC1jbGFzcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2Ztb2RlLW5nL3NyYy9saWIvYWlnYy9zZXJ2aWNlLWZtYWkvc2VydmljZS1jaGF0L2NoYXQtY2xhc3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFXLEtBQUssRUFBRSxRQUFRLEVBQUUsTUFBTSxNQUFNLENBQUE7QUFDbEYsdUdBQXVHO0FBQ3ZHLE9BQU8sS0FBSyxNQUFNLE9BQU8sQ0FBQztBQUMxQixPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRTFDLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUczQyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDekQscUJBQXFCO0FBQ3JCLG9FQUFvRTtBQUNwRSxNQUFNLFFBQVEsR0FBVSwyQ0FBMkMsQ0FBQTtBQUNuRSxvRUFBb0U7QUFFcEUsTUFBTSxXQUFXLEdBQUcsSUFBSSxXQUFXLEVBQUUsQ0FBQztBQUN0QyxNQUFNLDJCQUEyQixHQUFHLHNCQUFzQixDQUFDO0FBQzNELE1BQU0seUJBQXlCLEdBQUcsb0JBQW9CLENBQUM7QUFzQnZELE1BQU0sVUFBVSxxQkFBcUIsQ0FBQyxPQUE4QztJQUNoRixJQUFJLElBQUksR0FBRyxFQUFFLENBQUE7SUFDYixJQUFHLE9BQU8sT0FBTyxJQUFJLFFBQVE7UUFBRSxJQUFJLEdBQUcsT0FBTyxDQUFBO0lBQzdDLElBQUcsT0FBTyxPQUFPLElBQUksUUFBUTtRQUFFLElBQUksR0FBRyxPQUFPLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQSxFQUFFLENBQUEsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLElBQUksSUFBSSxFQUFFLENBQUE7SUFDakYsT0FBTyxJQUFJLENBQUE7QUFDZixDQUFDO0FB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QUksRUFBRSxJQUFJLENBQUMsQ0FBQztRQUM5QixDQUFDO0lBQ0gsQ0FBQztJQUVELGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUVyQixPQUFPLFFBQVEsQ0FBQztBQUNsQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgYnVmZmVyVGltZSwgY29uY2F0TWFwLCBPYnNlcnZhYmxlLCBPYnNlcnZlcixkZWxheSwgZmluYWxpemUgfSBmcm9tIFwicnhqc1wiXG4vLyB2YXIgYnVmZmVyVGltZTphbnksIGNvbmNhdE1hcDphbnksIE9ic2VydmFibGU6YW55LCBPYnNlcnZlcjphbnksZGVsYXk6YW55LCBmaW5hbGl6ZTphbnksT2JzZXJ2ZXI6YW55XG5pbXBvcnQgUGFyc2UgZnJvbSBcInBhcnNlXCI7XG5pbXBvcnQgeyBBZ2VudFByb21wdCB9IGZyb20gXCIuLi8uLi9hZ2VudFwiO1xuaW1wb3J0IHsgTmF2Q29udHJvbGxlciB9IGZyb20gXCJAaW9uaWMvYW5ndWxhclwiO1xuaW1wb3J0IHsgRm1vZGVUVFMgfSBmcm9tIFwiLi4vLi4vdm9pY2UvdHRzXCI7XG5pbXBvcnQgeyBOb3ZhQ2xvdWRTZXJ2aWNlIH0gZnJvbSBcIi4uLy4uLy4uL25vdmEtY2xvdWRcIjtcbmltcG9ydCB7IE5vdmFVcGxvYWRTZXJ2aWNlIH0gZnJvbSBcIi4uLy4uLy4uL3N0b3JhZ2Uvc2VydmljZS11cGxvYWQvbm92YS11cGxvYWQuc2VydmljZVwiO1xuaW1wb3J0IHsgUHJvbXB0VGVtcGxhdGUgfSBmcm9tIFwiQGxhbmdjaGFpbi9jb3JlL3Byb21wdHNcIjtcbi8vIHZhciBQYXJzZTphbnkgPSB7fVxuLy8gY29uc3QgQVBJX0JBU0U6c3RyaW5nID0gXCJodHRwOi8vMTI3LjAuMC4xOjczMzcvYXBpL2FwaWcvYWlnYy9ncHRcIlxuY29uc3QgQVBJX0JBU0U6c3RyaW5nID0gXCJodHRwczovL3NlcnZlci5mbW9kZS5jbi9hcGkvYXBpZy9haWdjL2dwdFwiXG4vLyBjb25zdCBBUElfQkFTRTpzdHJpbmcgPSBcImh0dHBzOi8vdGVzdC5mbW9kZS5jbi9hcGkvYXBpZy9haWdjL2dwdFwiXG5cbmNvbnN0IGFnZW50UHJvbXB0ID0gbmV3IEFnZW50UHJvbXB0KCk7XG5jb25zdCBQcm9tcHRUcGxUYWxrU1NNTE91dHB1dENvZGUgPSBcInRhbGstc3NtbC1vdXRwdXQtdHBsXCI7XG5jb25zdCBQcm9tcHRUcGxUYWxrVGV4dFNTTUxDb2RlID0gXCJ0YWxrLXRleHQtc3NtbC10cGxcIjtcbmV4cG9ydCBpbnRlcmZhY2UgRm1vZGVDaGF0TWVzc2FnZVZvaWNle1xuICAgIGlkOnN0cmluZyxcbiAgICBkdXJhdGlvbj86bnVtYmVyLFxuICAgIHNzbWw/OnN0cmluZyxcbiAgICB2b2ljZVVybD86c3RyaW5nLFxufVxuZXhwb3J0IGludGVyZmFjZSBGbW9kZUNoYXRFdmVudE1hcCB7XG4gICAgLy8g5paH5pys6KGl5YWo5LqL5Lu2XG4gICAgb25Db21wbGV0ZT8oRm1vZGVDaGF0TWVzc2FnZSk6dm9pZDtcbiAgICAvLyDor63pn7PlkIjmiJDkuovku7ZcbiAgICBvblNTTUxDb21wbGV0ZT8oRm1vZGVDaGF0TWVzc2FnZVZvaWNlKTp2b2lkOyAvLyBzc21s6ISa5pys5ZCI5oiQXG59IFxuXG5leHBvcnQgaW50ZXJmYWNlIEZtb2RlQ2hhdFZvaWNlQ29uZmlne1xuICAgIHZvaWNlOnN0cmluZyAvLyDlo7Dpn7PmupDop5LoibLku6PnoIFcbiAgICBhdXRvVGFsazpib29sZWFuIC8vIOiHquWKqOivremfs+WbnuWkjVxuICAgIHdlbGNvbWU6e1xuICAgICAgICBlbmFibGVkOnRydWUgLy8g5byA5ZCv5qyi6L+O6K+t6Z+zXG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0TWVzc2FnZUNvbnRlbnRUZXh0KGNvbnRlbnQ6YW55fHN0cmluZ3xBcnJheTxDaGF0SW1hZ2VDb250ZW50SXRlbT4pe1xuICAgIGxldCB0ZXh0ID0gXCJcIlxuICAgIGlmKHR5cGVvZiBjb250ZW50ID09IFwic3RyaW5nXCIpIHRleHQgPSBjb250ZW50XG4gICAgaWYodHlwZW9mIGNvbnRlbnQgPT0gXCJvYmplY3RcIikgdGV4dCA9IGNvbnRlbnQ/LmZpbmQoaXRlbT0+aXRlbT8udGV4dCk/LnRleHQgfHwgXCJcIlxuICAgIHJldHVybiB0ZXh0XG59XG5leHBvcnQgZnVuY3Rpb24gZ2V0TWVzc2FnZUltYWdlVXJsKGNvbnRlbnQ6YW55fHN0cmluZ3xBcnJheTxDaGF0SW1hZ2VDb250ZW50SXRlbT4pe1xuICAgIGlmKHR5cGVvZiBjb250ZW50ID09IFwib2JqZWN0XCIpIHJldHVybiBjb250ZW50Py5maW5kKGl0ZW09Pml0ZW0/LmltYWdlX3VybCk/LmltYWdlX3VybD8udXJsIHx8IFwiXCJcbiAgICByZXR1cm4gbnVsbFxuICB9XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2hhdEltYWdlQ29udGVudEl0ZW17dHlwZTpzdHJpbmcsdGV4dD86c3RyaW5nLGltYWdlX3VybD86e3VybDpzdHJpbmd9fVxuXG5leHBvcnQgaW50ZXJmYWNlIEZtb2RlQ2hhdE1lc3NhZ2V7XG4gICAgcm9sZTpzdHJpbmcgLy8gdXNlciDnlKjmiLcgYXNzaXN0YW50IEFJIHN5c3RlbSDns7vnu59cbiAgICBjb250ZW50OnN0cmluZ3xBcnJheTxDaGF0SW1hZ2VDb250ZW50SXRlbT4gLy8g5raI5oGv5YaF5a65XG4gICAganNvbj86YW55XG4gICAgaGlkZGVuPzpib29sZWFuXG4gICAgY3JlYXRlZEF0PzpEYXRlIC8vIOWIm+W7uuaXtumXtFxuICAgIGNvbXBsZXRlPzpib29sZWFuIC8vIFN0cmVhbea1geW8j+WKoOi9veWujOaIkFxuICAgIHZvaWNlPzpGbW9kZUNoYXRNZXNzYWdlVm9pY2VcbiAgICAvKipBSeWbnuWkjea2iOaBr+Wtl+autSAqL1xuICAgIGNpZD86c3RyaW5nIC8vIEFJ6KGl5YWo5YaF5a6577yM5YyF5ZCrY2lk77yM5oyH5ZCR5pWw5o2u5bqTIGNoYXRjbXBsLXVEZkdGT3dJSHlpNHZNOUxrQjZrVnhjZzRpMURaXG59XG5cbi8qKlxuICogRm1vZGVDaGF0IOiBiuWkqeWvueivneexu1xuICogQHB1YmxpY1xuICovXG5leHBvcnQgY2xhc3MgRm1vZGVDaGF0e1xuXG4gICAgdGl0bGU6c3RyaW5nXG4gICAgc2Vzc2lvbklkOnN0cmluZ1xuICAgIENoYXRTZXNzaW9uID0gUGFyc2UuT2JqZWN0LmV4dGVuZChcIkNoYXRTZXNzaW9uXCIpXG4gICAgY2hhdFNlc3Npb246UGFyc2UuT2JqZWN0XG4gICAgcm9sZTphbnlcbiAgICBtZXNzYWdlTGlzdDpGbW9kZUNoYXRNZXNzYWdlW10gPSBbe3JvbGU6XCJzeXN0ZW1cIixjb250ZW50Olwi57O757uf5o+Q56S677yaQUnku4Xkvpvlj4LogINcIn1dXG4gICAgbGF0ZXN0QUlSZXNwb25zZTpzdHJpbmd8dW5kZWZpbmVkID0gYGBcbiAgICBjaGF0U2VydjphbnlcbiAgICBwdWJsaWMgdXNlcklucHV0OnN0cmluZyA9IGBgO1xuICAgIHB1YmxpYyB1c2VySW1hZ2U6c3RyaW5nID0gYGA7XG4gICAgaXNEaXJlY3Q6Ym9vbGVhbiA9IGZhbHNlO1xuXG5cbiAgICAvKiogXG4gICAgICog6Jma5ouf5b2i6LGh5bGV56S654q25oCBXG4gICAgICovXG4gICAgaXNBdmF0YXJTaG93OmJvb2xlYW4gPSBmYWxzZTtcbiAgICBhdmF0YXJNb2RlOnN0cmluZyA9IFwiXCI7XG4gICAgYXZhdGFyQ29uZmlnOmFueXx1bmRlZmluZWQ7XG4gICAgc2hvd0F2YXRhcigpe1xuICAgICAgICB0aGlzLmF2YXRhckNvbmZpZyA9IHRoaXMucm9sZT8uZ2V0KFwiYXZhdGFyQ29uZmlnXCIpXG4gICAgICAgIGlmKHRoaXMuYXZhdGFyQ29uZmlnKXtcbiAgICAgICAgICAgIHRoaXMuaXNBdmF0YXJTaG93ID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmKHRoaXMuYXZhdGFyQ29uZmlnPy5pbWFnZSl7XG4gICAgICAgICAgICAgICAgdGhpcy5hdmF0YXJDb25maWcuaW1hZ2Uud2FpdGluZyA9IHRoaXMuYXZhdGFyQ29uZmlnLmltYWdlLndhaXRpbmcgfHwgdGhpcy5yb2xlPy5nZXQoXCJ0aHVtYlwiKSB8fCB0aGlzLnJvbGU/LmdldChcImF2YXRhclwiKVxuICAgICAgICAgICAgICAgIHRoaXMuYXZhdGFyTW9kZSA9IFwiaW1hZ2VcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYodGhpcy5hdmF0YXJDb25maWc/LnZpZGVvKXtcbiAgICAgICAgICAgICAgICB0aGlzLmF2YXRhckNvbmZpZy52aWRlby53YWl0aW5nID0gdGhpcy5hdmF0YXJDb25maWcudmlkZW8ud2FpdGluZ1xuICAgICAgICAgICAgICAgIHRoaXMuYXZhdGFyTW9kZSA9IFwidmlkZW9cIlxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog6aKE572u5o+Q56S66K+N5by556qX5piv5ZCm5bGV56S6XG4gICAgICovXG4gICAgaXNQcm9tcHRNb2RhbE9wZW46Ym9vbGVhbiA9IGZhbHNlO1xuICAgIGlzUHJvbXB0TWVzc2FnZUFyZWFTaG93OmJvb2xlYW4gPSB0cnVlO1xuICAgIHByb21wdExpc3Q6YW55ID0gW11cblxuICAgIC8qKlxuICAgICAqIOi+k+WFpeaMiemSruWMuuWfn1xuICAgICAqL1xuICAgIG5hdkN0cmw6TmF2Q29udHJvbGxlclxuICAgICBsZWZ0QnV0dG9uczpBcnJheTxhbnk+ID0gW1xuICAgICAgICAvLyDmj5DnpLog5b2T6KeS6Imy6YWN572u6aKE6K6+5o+Q56S66K+N5pe2IOaYvuekulxuICAgICAgICB7dGl0bGU6XCLngbXmhJ9cIixpY29uOlwiY29sb3Itd2FuZC1vdXRsaW5lXCIsb25DbGljazooKT0+e1xuICAgICAgICAgIHRoaXMuaXNQcm9tcHRNb2RhbE9wZW4gPSB0cnVlXG4gICAgICAgIH0sc2hvdzooKT0+e1xuICAgICAgICAgIHJldHVybiB0aGlzPy5wcm9tcHRMaXN0Py5sZW5ndGhcbiAgICAgICAgfX0sXG4gICAgICAgIHt0aXRsZTpcIuinkuiJslwiLGljb246XCJwZW9wbGUtb3V0bGluZVwiLG9uQ2xpY2s6KCk9PntcbiAgICAgICAgICB0aGlzLm5hdkN0cmw/Lm5hdmlnYXRlUm9vdChcIi9jaGF0L3Byby9tYXNrXCIpO1xuICAgICAgICB9LHNob3c6KCk9PntyZXR1cm4gdHJ1ZX19LFxuICAgICAgICB7dGl0bGU6XCLlkbzlj6tcIixpY29uOlwiY2FsbC1vdXRsaW5lXCIsb25DbGljazooKT0+e1xuICAgICAgICAgICAgdGhpcy5jaGF0U2Vydj8uY2FsbFJvbGUodGhpcy5yb2xlKVxuICAgICAgICB9LHNob3c6KCk9PntcbiAgICAgICAgICByZXR1cm4gdGhpcz8ucm9sZT8uZ2V0KCd2b2ljZUNvbmZpZycpO1xuICAgICAgICB9fSxcbiAgICAgIF1cblxuICAgIC8qKlxuICAgICAqIOaYr+WQpuW8gOWQr+ivremfs+a2iOaBr+aooeW8j++8iOWNleasoe+8iVxuICAgICAqL1xuICAgIGlzVm9pY2VJbnB1dE1vZGU6Ym9vbGVhbiA9IGZhbHNlO1xuICAgIGlzVGV4dGluZzpib29sZWFuID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiDmmK/lkKblvIDlkK/lrp7ml7blr7nor53mqKHlvI/vvIjlrp7ml7bvvIlcbiAgICAgKiBAZGVzY1xuICAgICAqIOW8gOWQr3NzbWwgc3lzdGVt5o+Q56S66K+NXG4gICAgICog5byA5ZCv5Zue562U5paH5pys6ZmkeG1s5pi+56S65qih5byPXG4gICAgICovXG4gICAgdm9pY2VDb25maWc6Rm1vZGVDaGF0Vm9pY2VDb25maWd8dW5kZWZpbmVkXG4gICAgaXNUYWxrTW9kZTpib29sZWFuID0gZmFsc2U7XG4gICAgU1NNTFJvbGVWb2ljZTpzdHJpbmcgPSBcInpoLUNOLVhpYW94aWFvTmV1cmFsXCI7XG5cbiAgICBuY2xvdWQ6Tm92YUNsb3VkU2VydmljZVxuICAgIHVwbG9hZFNlcnY6Tm92YVVwbG9hZFNlcnZpY2VcblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBzZXNzaW9uSWQ6c3RyaW5nLHJvbGU/OlBhcnNlLk9iamVjdCxjaGF0U2Vzc2lvbj86UGFyc2UuT2JqZWN0LGNoYXRTZXJ2PzphbnksXG4gICAgICAgIG5hdkN0cmw/Ok5hdkNvbnRyb2xsZXIsXG4gICAgICAgIG5jbG91ZD86Tm92YUNsb3VkU2VydmljZSxcbiAgICAgICAgdXBsb2FkU2Vydj86Tm92YVVwbG9hZFNlcnZpY2UsXG4gICAgICAgICl7XG4gICAgICAgIHRoaXMuY2hhdFNlcnYgPSBjaGF0U2VydlxuICAgICAgICB0aGlzLnJvbGUgPSByb2xlXG4gICAgICAgIHRoaXMuc2Vzc2lvbklkID0gc2Vzc2lvbklkXG4gICAgICAgIHRoaXMubmF2Q3RybCA9IG5hdkN0cmxcbiAgICAgICAgdGhpcy5uY2xvdWQgPSBuY2xvdWRcbiAgICAgICAgdGhpcy51cGxvYWRTZXJ2ID0gdXBsb2FkU2VydlxuICAgICAgICBpZihjaGF0U2Vzc2lvbj8uaWQpe1xuICAgICAgICAgICAgdGhpcy5jaGF0U2Vzc2lvbiA9IGNoYXRTZXNzaW9uO1xuICAgICAgICAgICAgdGhpcy5tZXNzYWdlTGlzdCA9IHRoaXMuY2hhdFNlc3Npb24uZ2V0KFwibWVzc2FnZUxpc3RcIik7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb25JZCA9IGNoYXRTZXNzaW9uPy5pZDtcbiAgICAgICAgfVxuICAgICAgICBpZih0aGlzLnJvbGU/LmlkKXtcbiAgICAgICAgICAgIHRoaXMudm9pY2VDb25maWcgPSB0aGlzLnJvbGU/LmdldChcInZvaWNlQ29uZmlnXCIpXG4gICAgICAgICAgICBpZih0aGlzLnZvaWNlQ29uZmlnPy5hdXRvVGFsayl7XG4gICAgICAgICAgICAgICAgdGhpcy5pc1RhbGtNb2RlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmlzRGlyZWN0ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiDkvJror51BdmF0YXLmjqfliLZcbiAgICAgKi9cbiAgICBwbGF5QW5pbWF0aW9uID0gKGFuaW1OYW1lOnN0cmluZyk9PntcbiAgICAgICAgY29uc29sZS5sb2coYW5pbU5hbWUpXG4gICAgICAgIHJldHVyblxuICAgIH1cbiAgICB3ZWxjb21lID0gYXN5bmMgKCk9PntcbiAgICAgICAgbGV0IG1zZ2xpc3QgPSB0aGlzLm1lc3NhZ2VMaXN0Py5maWx0ZXIoaXRlbT0+aXRlbT8ucm9sZT09XCJhc3Npc3RhbnRcIik7XG4gICAgICAgIGlmKG1zZ2xpc3Q/Lmxlbmd0aCkgcmV0dXJuIC8vIOW3suacieWvueivneS4jeW8gOWcuumXruWAmVxuXG4gICAgICAgIGxldCB1c2VyID0gUGFyc2UuVXNlci5jdXJyZW50KCk7XG4gICAgICAgIGxldCBwZXJzb24gPSBhd2FpdCB0aGlzLmxvYWRTZWxmKFwiUGVyc29uXCIsXCJ1c2VyVmVyaWZ5XCIpXG4gICAgICAgIGxldCBwcm9maWxlID0gYXdhaXQgdGhpcy5sb2FkU2VsZihcIlByb2ZpbGVcIixcInVzZXJcIilcbiAgICAgICAgbGV0IG5hbWUgPSB1c2VyPy5nZXQoXCJyZWFsbmFtZVwiKSB8fCBwcm9maWxlPy5nZXQoXCJuYW1lXCIpIHx8IHBlcnNvbj8uZ2V0KFwibmFtZVwiKSB8fCB1c2VyPy5nZXQoXCJuaWNrbmFtZVwiKSB8fCB1c2VyPy5nZXQoXCJuYW1lXCIpO1xuXG4gICAgICAgIC8vIOmXruWAmeivrS/pppbkuKror53pophcbiAgICAgICAgbGV0IHRwbCA9IHRoaXMucm9sZS5nZXQoXCJ2b2ljZUNvbmZpZ1wiKT8ud2VsY29tZT8ucHJvbXB0XG4gICAgICAgIGlmKCF0cGwpIHJldHVybiAvLyDml6DmqKHmnb/liJnov5Tlm55cbiAgICAgICAgbGV0IHdlbGNvbWVDb250ZW50ID0gYXdhaXQgUHJvbXB0VGVtcGxhdGUuZnJvbVRlbXBsYXRlKHRwbCx7XG4gICAgICAgICAgICB0ZW1wbGF0ZUZvcm1hdDpcIm11c3RhY2hlXCJcbiAgICAgICAgfSkuZm9ybWF0KHtcbiAgICAgICAgICAgIG5hbWU6bmFtZSxcbiAgICAgICAgICAgIHRpbWVPZkRheTp0aGlzLmdldFRpbWVPZkRheSgpXG4gICAgICAgIH0pXG4gICAgICAgIC8vIGxldCBjYWxsTmFtZSA9IG5hbWU/YCR7bmFtZX3vvIxgOlwiXCI7XG4gICAgICAgIC8vIGxldCBjYWxsVGltZSA9IGAke3RoaXMuZ2V0VGltZU9mRGF5KCl95aW9YDtcbiAgICAgICAgLy8gbGV0IHdlbGNvbWVDb250ZW50ID0gYCR7Y2FsbE5hbWV9JHtjYWxsVGltZX3vvIzmnJ/lvoXogYblkKzmgqjnmoTkurrnlJ/mlYXkuovvvIzmg7PlkozmiJHogYrkupvku4DkuYjlkaLvvJ9gO1xuXG4gICAgICAgIC8vIOeUn+aIkENoYXRWb2ljZeW5tuaSreaUvlxuICAgICAgICBsZXQgdm9pY2UgPSBhd2FpdCB0aGlzLmdldFZvaWNlQnlDb250ZW50VGV4dCh3ZWxjb21lQ29udGVudCk7XG4gICAgICAgIGxldCBtZXNzYWdlID0ge1xuICAgICAgICAgICAgcm9sZTpcImFzc2lzdGFudFwiLFxuICAgICAgICAgICAgdm9pY2U6IHZvaWNlLFxuICAgICAgICAgICAgY29udGVudDp3ZWxjb21lQ29udGVudCxcbiAgICAgICAgICAgIGNvbXBsZXRlOnRydWVcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnZvaWNlTWFwW3ZvaWNlPy5pZF1cbiAgICAgICAgdGhpcy5wbGF5Q2hhdFZvaWNlKHRoaXMudm9pY2VNYXBbdm9pY2U/LmlkXSlcbiAgICAgICAgdGhpcy5tZXNzYWdlTGlzdC5wdXNoKG1lc3NhZ2UpXG4gICAgfVxuICAgIGdldFRpbWVPZkRheSgpIHtcbiAgICAgICAgY29uc3Qgbm93ID0gbmV3IERhdGUoKTtcbiAgICAgICAgY29uc3QgaG91cnMgPSBub3cuZ2V0SG91cnMoKTtcbiAgICAgICAgaWYgKGhvdXJzID49IDUgJiYgaG91cnMgPCAxMikge1xuICAgICAgICAgICAgcmV0dXJuIFwi5pep5LiKXCI7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91cnMgPj0gMTIgJiYgaG91cnMgPCAxNCkge1xuICAgICAgICAgICAgcmV0dXJuIFwi5Lit5Y2IXCI7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91cnMgPj0gMTQgJiYgaG91cnMgPCAxOCkge1xuICAgICAgICAgICAgcmV0dXJuIFwi5LiL5Y2IXCI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gXCLmmZrkuIpcIjtcbiAgICAgICAgfVxuICAgIH1cbiAgICBzZWxmOntcbiAgICAgICAgUGVyc29uPzpQYXJzZS5PYmplY3R8dW5kZWZpbmVkXG4gICAgICAgIFByb2ZpbGU/OlBhcnNlLk9iamVjdHx1bmRlZmluZWRcbiAgICB9ID0ge31cbiAgICBhc3luYyBsb2FkU2VsZihjbGFzc05hbWUsdXNlcktleSl7XG4gICAgICAgIGlmKHRoaXMuc2VsZltjbGFzc05hbWVdKSByZXR1cm4gdGhpcy5zZWxmW2NsYXNzTmFtZV1cbiAgICAgICAgbGV0IHVzZXIgPSBQYXJzZS5Vc2VyLmN1cnJlbnQoKTtcbiAgICAgICAgbGV0IHF1ZXJ5ID0gbmV3IFBhcnNlLlF1ZXJ5KGNsYXNzTmFtZSk7XG4gICAgICAgIHF1ZXJ5LmVxdWFsVG8odXNlcktleSx1c2VyPy5pZCk7XG4gICAgICAgIHRoaXMuc2VsZltjbGFzc05hbWVdID0gYXdhaXQgcXVlcnkuZmlyc3QoKTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIOWvueivneaooeWei+aPkOekuuivjVxuICAgICAqL1xuICAgICBhc3luYyBsb2FkVGFsa1N5c3RlbVByb21wdChyb2xlOlBhcnNlLk9iamVjdCl7XG4gICAgICAgIGlmKCF0aGlzLmlzVGFsa01vZGUpIHJldHVyblxuICAgICAgICBpZighcm9sZSkgcmV0dXJuXG4gICAgICAgIC8vIOWKoOi9veWjsOmfs+aooeWei++8mum7mOiupOS4uuaZk+aZk1xuICAgICAgICBpZihyb2xlPy5nZXQoJ2dlbmRlcicpPT0n55S3Jyl7XG4gICAgICAgICAgdGhpcy5TU01MUm9sZVZvaWNlID0gXCJ6aC1DTi1ZdW55ZU5ldXJhbFwiXG4gICAgICAgIH1lbHNle1xuICAgICAgICAgIHRoaXMuU1NNTFJvbGVWb2ljZSA9IFwiemgtQ04tWGlhb3hpYW9OZXVyYWxcIlxuICAgICAgICB9XG4gICAgICAgIHRoaXMuU1NNTFJvbGVWb2ljZSA9IHJvbGU/LmdldChcInZvaWNlQ29uZmlnXCIpPy52b2ljZSB8fCB0aGlzLlNTTUxSb2xlVm9pY2UgXG4gICAgICAgIGxldCBTU01MUHJvbXB0VGVtcGxhdGUgPSBhd2FpdCBhZ2VudFByb21wdC5nZXRGb3JtYXRUcGwoUHJvbXB0VHBsVGFsa1NTTUxPdXRwdXRDb2RlLHtcbiAgICAgICAgICAgIFNTTUxSb2xlVm9pY2U6IHRoaXMuU1NNTFJvbGVWb2ljZSwgLy8gU1NNTCBcbiAgICAgICAgfSlcblxuICAgICAgICBsZXQgcHJvbXB0ID0gcm9sZS5nZXQoXCJwcm9tcHRcIikgfHwgXCLor7fkvaDmia7mvJTpo57noIFBSeeahOS6uuW3peaZuuiDveS4k+WutuOAglwiXG4gICAgICAgIHByb21wdCArPSBTU01MUHJvbXB0VGVtcGxhdGU7XG4gICAgICAgIGxldCBwcm9tcHRNc2c6Rm1vZGVDaGF0TWVzc2FnZSA9IHtyb2xlOlwidXNlclwiLGNvbnRlbnQ6cHJvbXB0LGhpZGRlbjp0cnVlfVxuXG4gICAgICAgIC8vIOafpemHjVxuICAgICAgICBsZXQgY29udGVudCA9IHRoaXMubWVzc2FnZUxpc3Q/Lm1hcChpdGVtPT5pdGVtPy5jb250ZW50KS5qb2luKClcbiAgICAgICAgaWYoY29udGVudC5pbmRleE9mKHByb21wdCk+LTEpe1xuICAgICAgICAgICAgLy8g5o+Q56S66K+N5bey57uP5a2Y5ZyoXG4gICAgICAgICAgICByZXR1cm5cbiAgICAgICAgfVxuICAgICAgICAvLyDooaXlhajmj5DnpLror41cbiAgICAgICAgbGV0IHN5c3RlbUluZGV4ID0gdGhpcy5tZXNzYWdlTGlzdD8uZmluZEluZGV4KGl0ZW09Pml0ZW0/LnJvbGU9PVwic3lzdGVtXCIpO1xuICAgICAgICBsZXQgaW5zZXJ0SW5kZXggPSBzeXN0ZW1JbmRleCsxXG4gICAgICAgIHRoaXMubWVzc2FnZUxpc3Quc3BsaWNlKGluc2VydEluZGV4LDAscHJvbXB0TXNnKVxuICAgICAgICByZXR1cm4gXG4gICAgfVxuICAgIC8qKlxuICAgICAqIOinkuiJsuaPkOekuuivjVxuICAgICAqIEByZXR1cm5zIFxuICAgICAqL1xuICAgIGxvYWRSb2xlUHJvbXB0KCl7XG4gICAgICAgIC8vIOinkuiJsuaPkOekulxuICAgICAgICBsZXQgcHJvbXB0ID0gdGhpcy5yb2xlPy5nZXQoXCJwcm9tcHRcIilcbiAgICAgICAgbGV0IHByb21wdE1zZzpGbW9kZUNoYXRNZXNzYWdlID0ge3JvbGU6XCJ1c2VyXCIsY29udGVudDpwcm9tcHQsaGlkZGVuOnRydWV9XG4gICAgICAgIGlmKCFwcm9tcHQpIHJldHVybiAvLyDml6Dmj5DnpLror43ml6DpnIDmt7vliqBcbiAgICAgICAgLy8g5YaF5a655qOA5p+lXG4gICAgICAgIGxldCBjb250ZW50ID0gdGhpcy5tZXNzYWdlTGlzdD8ubWFwKGl0ZW09Pml0ZW0/LmNvbnRlbnQpLmpvaW4oKVxuICAgICAgICBpZihjb250ZW50LmluZGV4T2YocHJvbXB0KT4tMSl7XG4gICAgICAgICAgICAvLyDmj5DnpLror43lt7Lnu4/lrZjlnKhcbiAgICAgICAgICAgIHJldHVyblxuICAgICAgICB9XG4gICAgICAgIC8vIOihpeWFqOaPkOekuuivjVxuICAgICAgICBsZXQgc3lzdGVtSW5kZXggPSB0aGlzLm1lc3NhZ2VMaXN0Py5maW5kSW5kZXgoaXRlbT0+aXRlbT8ucm9sZT09XCJzeXN0ZW1cIik7XG4gICAgICAgIGxldCBpbnNlcnRJbmRleCA9IHN5c3RlbUluZGV4KzFcbiAgICAgICAgdGhpcy5tZXNzYWdlTGlzdC5zcGxpY2UoaW5zZXJ0SW5kZXgsMCxwcm9tcHRNc2cpXG4gICAgICAgIC8vIGNvbnNvbGUubG9nKHRoaXMubWVzc2FnZUxpc3QpXG4gICAgfVxuICAgIC8qKlxuICAgICAqIOWPkemAgea2iOaBr1xuICAgICAqIEBwYXJhbSBtZXNzYWdlIFxuICAgICAqIEBwYXJhbSBpbWFnZVVybCBcbiAgICAgKi9cbiAgICBhc3luYyBzZW5kTWVzc2FnZShtZXNzYWdlOnN0cmluZz1cIkZtb2RlQWlUZXN05rWL6K+V6Zeu6aKYXCIsaW1hZ2VVcmw/OnN0cmluZyxvbkNvbXBsZXRlPzpGdW5jdGlvbixldmVudE1hcD86Rm1vZGVDaGF0RXZlbnRNYXAsdm9pY2U/OkZtb2RlQ2hhdE1lc3NhZ2VWb2ljZSl7XG4gICAgICAgIC8vIOS4uua2iOaBr+WIl+ihqOihpeWFqOaPkOekuuivjVxuICAgICAgICAvLyBhd2FpdCB0aGlzLmxvYWRUYWxrU3lzdGVtUHJvbXB0KHRoaXMucm9sZSk7XG4gICAgICAgIHRoaXMuaXNQcm9tcHRNZXNzYWdlQXJlYVNob3cgPSBmYWxzZTsgLy8g5Y+R6YCB56ys5LiA5p2h5raI5oGv5ZCO77yM5YWz6Zet5o+Q56S655yL5p2/XG4gICAgICAgIHRoaXMubG9hZFJvbGVQcm9tcHQoKTtcbiAgICAgICAgLy8g55So5oi36L6T5YWl5raI5oGv77yM5re75Yqg5Yiw5Y6G5Y+y5raI5oGv5riF5Y2V5LitXG4gICAgICAgIGlmKCFpbWFnZVVybCl7IC8vIOe6r+aWh+acrFxuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCLnuq/mlofmnKxcIilcbiAgICAgICAgICAgIGxldCBtc2c6Rm1vZGVDaGF0TWVzc2FnZSA9IHtcbiAgICAgICAgICAgICAgICByb2xlOlwidXNlclwiLFxuICAgICAgICAgICAgICAgIGNvbnRlbnQ6bWVzc2FnZSxcbiAgICAgICAgICAgICAgICBjb21wbGV0ZTp0cnVlLFxuICAgICAgICAgICAgICAgIGNyZWF0ZWRBdDpuZXcgRGF0ZSgpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZih2b2ljZSl7XG4gICAgICAgICAgICAgICAgbXNnLnZvaWNlID0ge2lkOnZvaWNlPy5pZCxkdXJhdGlvbjp2b2ljZT8uZHVyYXRpb259XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLm1lc3NhZ2VMaXN0LnB1c2gobXNnKVxuICAgICAgICB9ZWxzZXsgLy8g5bim5Zu+54mHXG4gICAgICAgICAgICBsZXQgbXNnOkZtb2RlQ2hhdE1lc3NhZ2UgPSB7XG4gICAgICAgICAgICAgICAgXCJyb2xlXCI6IFwidXNlclwiLFxuICAgICAgICAgICAgICAgIFwiY29udGVudFwiOiBbXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIFwidHlwZVwiOiBcImltYWdlX3VybFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgXCJpbWFnZV91cmxcIjoge1widXJsXCI6aW1hZ2VVcmx9LFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBcInR5cGVcIjogXCJ0ZXh0XCIsIFxuICAgICAgICAgICAgICAgICAgICAgICAgXCJ0ZXh0XCI6IG1lc3NhZ2VcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICAgIGNvbXBsZXRlOnRydWUsXG4gICAgICAgICAgICAgICAgY3JlYXRlZEF0Om5ldyBEYXRlKClcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKHZvaWNlKXtcbiAgICAgICAgICAgICAgICBtc2cudm9pY2UgPSB7aWQ6dm9pY2U/LmlkfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5tZXNzYWdlTGlzdC5wdXNoKHtcbiAgICAgICAgICAgICAgICBcInJvbGVcIjogXCJ1c2VyXCIsXG4gICAgICAgICAgICAgICAgXCJjb250ZW50XCI6IFtcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgXCJ0eXBlXCI6IFwiaW1hZ2VfdXJsXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBcImltYWdlX3VybFwiOiB7XCJ1cmxcIjppbWFnZVVybH0sXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIFwidHlwZVwiOiBcInRleHRcIiwgXG4gICAgICAgICAgICAgICAgICAgICAgICBcInRleHRcIjogbWVzc2FnZVxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgY29tcGxldGU6dHJ1ZSxcbiAgICAgICAgICAgICAgICBjcmVhdGVkQXQ6bmV3IERhdGUoKVxuICAgICAgICAgICAgfSlcbiAgICAgICAgfVxuICAgICAgICAvLyDliJvlu7rlubblj5HotbfkuIDmnaHmlrDnmoTmtojmga/ooaXlhahcbiAgICAgICAgLy8gY29uc29sZS5sb2coXCJzZW5kXCIsdGhpcy5tZXNzYWdlTGlzdClcbiAgICAgICAgbGV0IGNvbXBsZXRpb24gPSBuZXcgRm1vZGVDaGF0Q29tcGxldGlvbih0aGlzLmZpeE1lc3NhZ2VMaXN0KHRoaXMubWVzc2FnZUxpc3QpLHtcbiAgICAgICAgICAgIG1vZGVsOnRoaXMuY2hhdFNlcnY/LmN1cnJlbnRNb2RlbD8uZ2V0KFwiY29kZVwiKSB8fCBcImZtb2RlLTQuNS0xMjhrXCJcbiAgICAgICAgfSlcblxuICAgICAgICB0aGlzLnVzZXJJbnB1dCA9IFwiXCI7XG4gICAgICAgIHRoaXMudXNlckltYWdlID0gXCJcIjtcbiAgICAgICAgLy8gY29uc29sZS5sb2codGhpcy5jaGF0U2Vydj8uY3VycmVudE1vZGVsPy50b0pTT04oKSlcbiAgICAgICAgLy8g5oyB57ut5pu05paw5LqL5Lu25o6o6YCB55qE5raI5oGv5L2T5YaF5a656Iez5raI5oGv5YiX6KGoXG4gICAgICAgIGxldCBpc0RpcmVjdCA9IHRoaXMuaXNEaXJlY3QgfHwgZmFsc2VcbiAgICAgICAgaWYodGhpcy5pc1RhbGtNb2RlKXtcbiAgICAgICAgICAgIGlzRGlyZWN0ID0gdHJ1ZVxuICAgICAgICB9XG4gICAgICAgIGxldCBzZW5kJCA9IGNvbXBsZXRpb24uc2VuZENvbXBsZXRpb24oe1xuICAgICAgICAgICAgaXNEaXJlY3Q6aXNEaXJlY3QsXG4gICAgICAgICAgICBvbkNvbXBsZXRlOm9uQ29tcGxldGV8fG51bGxcbiAgICAgICAgfSkucGlwZShmaW5hbGl6ZShhc3luYyAoKT0+eyAvLyDnrqHpgZNmaW5hbGl6Zeabv+S7o+S6huaXp+eJiOeahChjb21wbGV0ZSk9Pnt9XG5cbiAgICAgICAgICAgIGlmKHRoaXMuaXNUYWxrTW9kZSl7XG4gICAgICAgICAgICAgICAgbGV0IGNvbnRlbnQgPSB0aGlzLm1lc3NhZ2VMaXN0W2NvbXBsZXRpb24uaW5kZXhPZkxpc3RdPy5jb250ZW50O1xuICAgICAgICAgICAgICAgIGxldCB2b2ljZSA9IGF3YWl0IHRoaXMuZ2V0Vm9pY2VCeUNvbnRlbnRUZXh0KGNvbnRlbnQsZXZlbnRNYXApO1xuICAgICAgICAgICAgICAgIGV2ZW50TWFwPy5vblNTTUxDb21wbGV0ZSYmZXZlbnRNYXA/Lm9uU1NNTENvbXBsZXRlKHZvaWNlKTtcbiAgICAgICAgICAgICAgICB0aGlzLm1lc3NhZ2VMaXN0W2NvbXBsZXRpb24uaW5kZXhPZkxpc3RdLnZvaWNlID0gdm9pY2U7XG4gICAgICAgICAgICAgICAgdGhpcy5wbGF5Q2hhdFZvaWNlKHRoaXMudm9pY2VNYXBbdm9pY2U/LmlkXSlcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5tZXNzYWdlTGlzdFtjb21wbGV0aW9uLmluZGV4T2ZMaXN0XS5jb21wbGV0ZSA9IHRydWVcbiAgICAgICAgfSkpLnN1YnNjcmliZShtZXNzYWdlPT57XG4gICAgICAgICAgICB0aGlzLm1lc3NhZ2VMaXN0W2NvbXBsZXRpb24uaW5kZXhPZkxpc3RdID0gbWVzc2FnZTtcbiAgICAgICAgICAgIHRoaXMubGF0ZXN0QUlSZXNwb25zZSA9IHRoaXMuZ2V0Q29udGVudFRleHQobWVzc2FnZT8uY29udGVudClcbiAgICAgICAgICAgXG4gICAgICAgICAgICBsZXQgc2F2ZWRMaXN0ID0gdGhpcy5jaGF0U2Vzc2lvbj8uZ2V0KFwibWVzc2FnZUxpc3RcIik/Lmxlbmd0aDtcbiAgICAgICAgICAgICAgICAvLyDnlJ/lkb3lkajmnJ/vvJrkvJror53liJvlu7rlkI7vvIzmnInmlrDmtojmga/ml7bvvIzliJvlu7rkv53lrZjkvJror51cbiAgICAgICAgICAgIGlmKHRoaXMubWVzc2FnZUxpc3Q/Lmxlbmd0aCA+IHNhdmVkTGlzdCl7XG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJjeWNsZeaWsOS8muivnVwiKVxuICAgICAgICAgICAgICAgIHRoaXMuc2F2ZUNoYXRTZXNzaW9uKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKG1lc3NhZ2U/LmNvbXBsZXRlKXtcbiAgICAgICAgICAgICAgICAvLyDnlJ/lkb3lkajmnJ/vvJrmtojmga/lj5HpgIHlrozmiJDlkI7vvIzkv53lrZjogYrlpKnorrDlvZVcbiAgICAgICAgICAgICAgICB0aGlzLnNhdmVDaGF0U2Vzc2lvbigpOyBcbiAgICAgICAgICAgICAgICBzZW5kJC51bnN1YnNjcmliZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gY29uc29sZS5sb2cobWVzc2FnZSlcbiAgICAgICAgfSlcbiAgICB9XG5cbiAgICBnZXRWb2ljZUJ5Q29udGVudFRleHQoY29udGVudDpzdHJpbmd8Q2hhdEltYWdlQ29udGVudEl0ZW1bXSxldmVudE1hcD86Rm1vZGVDaGF0RXZlbnRNYXAscHJvbXB0RW5hYmxlZDpib29sZWFuPWZhbHNlKTpQcm9taXNlPEZtb2RlQ2hhdE1lc3NhZ2VWb2ljZT57XG4gICAgICAgIGxldCBjb250ZW50VGV4dCA9IHRoaXMuZ2V0Q29udGVudFRleHQoY29udGVudCk7XG4gICAgICAgIGxldCBDaGF0Vm9pY2UgPSBQYXJzZS5PYmplY3QuZXh0ZW5kKFwiQ2hhdFZvaWNlXCIpO1xuICAgICAgICBsZXQgY2hhdFZvaWNlID0gbmV3IENoYXRWb2ljZSgpO1xuICAgICAgICBsZXQgY29udGVudFNTTUwgPSBgYDtcbiAgICAgICAgdGhpcy5TU01MUm9sZVZvaWNlID0gdGhpcy5yb2xlPy5nZXQoXCJ2b2ljZUNvbmZpZ1wiKT8udm9pY2UgfHwgdGhpcy5TU01MUm9sZVZvaWNlIFxuXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShhc3luYyAocmVzb2x2ZSxyZWplY3QpPT57XG4gICAgICAgICAgICBsZXQgcmVzb2x2ZUNoYXRWb2ljZSA9IGFzeW5jICgpPT57XG4gICAgICAgICAgICAgICAgY2hhdFZvaWNlLnNldChcImNvbnRlbnRcIixjb250ZW50VGV4dCk7XG4gICAgICAgICAgICAgICAgY2hhdFZvaWNlLnNldChcInNzbWxcIixjb250ZW50U1NNTCk7XG4gICAgICAgICAgICAgICAgY2hhdFZvaWNlLnNldChcInJvbGVcIixcImFzc2lzdGFudFwiKTtcbiAgICAgICAgICAgICAgICBsZXQgY29tcGFueSA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKFwiY29tcGFueVwiKVxuICAgICAgICAgICAgICAgIGNvbXBhbnkmJmNoYXRWb2ljZS5zZXQoXCJjb21wYW55XCIse19fdHlwZTpcIlBvaW50ZXJcIixjbGFzc05hbWU6XCJDb21wYW55XCIsb2JqZWN0SWQ6Y29tcGFueX0pO1xuICAgICAgICAgICAgICAgIFBhcnNlLlVzZXIuY3VycmVudCgpPy5pZCYmY2hhdFZvaWNlLnNldChcInVzZXJcIixQYXJzZS5Vc2VyLmN1cnJlbnQoKS50b1BvaW50ZXIoKSk7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGF0U2Vzc2lvbj8uaWQmJmNoYXRWb2ljZS5zZXQoXCJzZXNzaW9uXCIsdGhpcy5jaGF0U2Vzc2lvbj8udG9Qb2ludGVyKCkpO1xuICAgICAgICAgICAgICAgIGNoYXRWb2ljZSA9IGF3YWl0IGNoYXRWb2ljZS5zYXZlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy52b2ljZU1hcFtjaGF0Vm9pY2U/LmlkXSA9IGNoYXRWb2ljZTtcbiAgICAgICAgICAgICAgICByZXNvbHZlKHtcbiAgICAgICAgICAgICAgICAgICAgaWQ6Y2hhdFZvaWNlPy5pZCxcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiDmlrnms5XkuIDvvJrpq5jnuqfor63pn7Pnm7TmjqXor7vmlofmnKzvvIzpgJ/luqblv6vvvIzkvYbnu4boioLmg4Xnu6rmoIforrDkuI3otrPjgIJcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgIGlmKHByb21wdEVuYWJsZWQ9PWZhbHNlKXtcbiAgICAgICAgICAgICAgICBjb250ZW50U1NNTCA9IGA8c3BlYWsgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3N5bnRoZXNpc1wiIHhtbG5zOm1zdHRzPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMS9tc3R0c1wiIHhtbG5zOmVtbz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDkvMTAvZW1vdGlvbm1sXCIgdmVyc2lvbj1cIjEuMFwiIHhtbDpsYW5nPVwiemgtQ05cIj48dm9pY2UgbmFtZT1cIiR7dGhpcy5TU01MUm9sZVZvaWNlfVwiPiR7Y29udGVudFRleHR9PC92b2ljZT48L3NwZWFrPmBcbiAgICAgICAgICAgICAgICByZXNvbHZlQ2hhdFZvaWNlKClcbiAgICAgICAgICAgICB9XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIHByb21wdEVuYWJsZWQgPT0gdHJ1ZVxuICAgICAgICAgICAgICog5pa55rOV5LqM77ya6YCa6L+H5aSn5qih5Z6L5YaN5qyh5ou85o6lU1NNTOiEmuacrO+8jOWunueOsOabtOS8mOi0qOeahOivremfs+agh+iusO+8jOS9huaYr+eUn+aIkOaXtumXtOWkquaFolxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBpZihwcm9tcHRFbmFibGVkPT10cnVlKXtcbiAgICAgICAgICAgICAgICAvLyDmi7zmjqVQcm9tcHRcbiAgICAgICAgICAgICAgICBsZXQgVGV4dFNTTUxQcm9tcHQgPSBhd2FpdCBhZ2VudFByb21wdC5nZXRGb3JtYXRUcGwoUHJvbXB0VHBsVGFsa1RleHRTU01MQ29kZSx7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRlbnQ6Y29udGVudFRleHQsIC8vIOaWh+acrOWGheWuuVxuICAgICAgICAgICAgICAgICAgICBTU01MUm9sZVZvaWNlOiB0aGlzLlNTTUxSb2xlVm9pY2UsIC8vIFNTTUwg5ryU6K+06ICFXG4gICAgICAgICAgICAgICAgfSlcblxuICAgICAgICAgICAgICAgIC8vIOeUn+aIkFNTTUxcbiAgICAgICAgICAgICAgICBsZXQgY29tcGxldGlvbiA9IG5ldyBGbW9kZUNoYXRDb21wbGV0aW9uKHRoaXMuZml4TWVzc2FnZUxpc3QoW3tcbiAgICAgICAgICAgICAgICAgICAgcm9sZTpcInVzZXJcIixcbiAgICAgICAgICAgICAgICAgICAgY29udGVudDpUZXh0U1NNTFByb21wdFxuICAgICAgICAgICAgICAgIH1dKSx7XG4gICAgICAgICAgICAgICAgICAgIG1vZGVsOnRoaXMuY2hhdFNlcnY/LmN1cnJlbnRNb2RlbD8uZ2V0KFwiY29kZVwiKSB8fCBcImZtb2RlLTQuNS0xMjhrXCJcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIGxldCBzZW5kJCA9IGNvbXBsZXRpb24uc2VuZENvbXBsZXRpb24oe1xuICAgICAgICAgICAgICAgICAgICBpc0RpcmVjdDp0cnVlLFxuICAgICAgICAgICAgICAgIH0pLnN1YnNjcmliZShhc3luYyBtZXNzYWdlPT57XG4gICAgICAgICAgICAgICAgICAgIGlmKG1lc3NhZ2U/LmNvbXBsZXRlKXtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnRTU01MID0gdGhpcy5nZXRDb250ZW50VGV4dChtZXNzYWdlPy5jb250ZW50KVxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZUNoYXRWb2ljZSgpXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgXG4gICAgICAgIH0pXG4gICAgfVxuICAgIGdldENvbnRlbnRUZXh0KGNvbnRlbnQ6c3RyaW5nfENoYXRJbWFnZUNvbnRlbnRJdGVtW10pe1xuICAgICAgICBpZih0eXBlb2YgY29udGVudCA9PSBcInN0cmluZ1wiKXtcbiAgICAgICAgICAgIHJldHVybiBjb250ZW50XG4gICAgICAgIH1lbHNle1xuICAgICAgICAgICAgcmV0dXJuIGNvbnRlbnQ/LlswXT8udGV4dCB8fCBgYFxuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFRUUyAtIOivremfs+WQiOaIkFxuICAgICAqIFxuICAgICAqL1xuICAgIHR0czpGbW9kZVRUU1xuICAgIGFzeW5jIGluaXRUVFMoKXtcbiAgICAvLyBpZih0aGlzLnR0cykgcmV0dXJuIC8vIOW+heaYjuehrnN0c+acieaViOacn+WSjOasoeaVsOi/m+ihjOS8mOWMlu+8jOmBv+WFjeavj+asoemHjeWkjeiOt+WPllxuICAgICAgICBsZXQgY29uZmlnOmFueSA9IGF3YWl0IHRoaXMubmNsb3VkLmFwaWcoXCJ2b2ljZS90dHMvdG9rZW5cIix7Y29tcGFueTpsb2NhbFN0b3JhZ2UuZ2V0SXRlbShcImNvbXBhbnlcIil9KVxuICAgICAgICAvLyDmnIlUVFPotYTmupDvvIzkvb/nlKjmg4Xnu6rlkIjmiJBcbiAgICAgICAgY29uc29sZS5sb2coY29uZmlnKVxuICAgICAgICBpZihjb25maWc/LnRva2VuKXtcbiAgICAgICAgbGV0IHR0cyA9IG5ldyBGbW9kZVRUUyhjb25maWcsdGhpcy51cGxvYWRTZXJ2KTtcbiAgICAgICAgdGhpcy50dHM9dHRzO1xuICAgICAgICB9XG4gICAgfVxuICAgIHZvaWNlTWFwOmFueSA9IHt9XG4gICAgYXN5bmMgcGxheUNoYXRWb2ljZSh2b2ljZTpQYXJzZS5PYmplY3QsZXZlbnRNYXA/OmFueSl7XG4gICAgICAgIGF3YWl0IHRoaXMuaW5pdFRUUygpO1xuICAgICAgICAvLyBjb25zb2xlLmxvZyh0aGlzLnR0cylcbiAgICAgICAgaWYodGhpcy50dHMpe1xuICAgICAgICAgICAgdHJ5e1xuICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKHRleHRPclNTTUwpXG4gICAgICAgICAgICAgICAgLy8g5a6M5pW055qE5raI5oGv77yM6YCa6L+HVFRT5ZCI5oiQ6L+b6KGM6K6y6K+dXG4gICAgICAgICAgICAgICAgdGhpcy5wbGF5QW5pbWF0aW9uKFwidGFsa2luZ1wiKSAvLyBUYWxraW5n5Yqo55S777yM5pqC5pe255Sod2F0aW5n5Luj5pu/XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy50dHMuc3BlYWtBc3luYyh2b2ljZT8uZ2V0KFwic3NtbFwiKSx2b2ljZSx7XG4gICAgICAgICAgICAgICAgICAgIG9uTG9hZGVkOihhdWRpbzphbnkpPT57XG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudE1hcD8ub25Mb2FkZWQmJmV2ZW50TWFwPy5vbkxvYWRlZChhdWRpbyk7IC8vIOS6i+S7tuS8oOmAklxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBvblN0b3A6ICgpPT57XG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudE1hcD8ub25TdG9wJiZldmVudE1hcD8ub25TdG9wKCk7IC8vIOS6i+S7tuS8oOmAklxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wbGF5QW5pbWF0aW9uKFwid2FpdGluZ1wiKSAvLyBUYWxraW5n5Yqo55S777yM5pqC5pe255Sod2F0aW5n5Luj5pu/XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfWNhdGNoKHR0c2Vycil7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcih0dHNlcnIpXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgIC8vIOaXoFRTU+i1hOa6kO+8jOiwg+eUqEVkZ2UgU3BlZWNoXG4gICAgfVxuICAgIC8qKlxuICAgICAqIOS/neWtmOWNleasoeS8muivnVxuICAgICAqL1xuICAgIGFzeW5jIHNhdmVDaGF0U2Vzc2lvbigpe1xuICAgICAgICBpZih0aGlzLnNlc3Npb25JZCA9PSBcIm5ld1wiKXtcbiAgICAgICAgICAgIHRoaXMuY2hhdFNlc3Npb24gPSBuZXcgdGhpcy5DaGF0U2Vzc2lvbigpXG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmNoYXRTZXNzaW9uLnNldChcInRpdGxlXCIsdGhpcy5nZW5UaXRsZSgpKVxuICAgICAgICB0aGlzLmNoYXRTZXNzaW9uLnNldChcInJvbGVcIix0aGlzLnJvbGU/LnRvUG9pbnRlcigpKVxuICAgICAgICB0aGlzLmNoYXRTZXNzaW9uLnNldChcIm1lc3NhZ2VMaXN0XCIsdGhpcy5tZXNzYWdlTGlzdClcbiAgICAgICAgdGhpcy5jaGF0U2Vzc2lvbi5zZXQoXCJ1c2VyXCIsUGFyc2UuVXNlci5jdXJyZW50KCk/LnRvUG9pbnRlcigpKVxuICAgICAgICB0aGlzLmNoYXRTZXNzaW9uID0gYXdhaXQgdGhpcy5jaGF0U2Vzc2lvbi5zYXZlKCk7XG4gICAgICAgIHRoaXMuc2Vzc2lvbklkID0gdGhpcy5jaGF0U2Vzc2lvbj8uaWRcbiAgICAgICAgaWYodGhpcy5zZXNzaW9uSWQpeyBcbiAgICAgICAgICAgIC8vIOS/ruaUuVVSTOWcsOWdgOS4unNlc3Npb25JZO+8jOaWueS+v+WIhuS6q+aIluWIh+aNoiDop5LoibLpobXpnaIgPT4g5Lya6K+d6aG16Z2iXG4gICAgICAgICAgICBsZXQgbmV3SHJlZiA9IGAke3dpbmRvdy5sb2NhdGlvbi5vcmlnaW59L2NoYXQvcHJvL2NoYXQvJHt0aGlzLnNlc3Npb25JZH1gXG4gICAgICAgICAgICBpZih3aW5kb3cubG9jYXRpb24/LnBhdGhuYW1lPy5pbmRleE9mKFwiY2hhdC9zZXNzaW9uXCIpPi0xKXtcbiAgICAgICAgICAgICAgICBuZXdIcmVmID0gYCR7d2luZG93LmxvY2F0aW9uLm9yaWdpbn0vY2hhdC9zZXNzaW9uL2NoYXQvJHt0aGlzLnNlc3Npb25JZH1gXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBuZXdIcmVmID0gdGhpcy5nZXRJbnZpdGVVcmwobmV3SHJlZilcbiAgICAgICAgICAgIHdpbmRvdy5oaXN0b3J5LnJlcGxhY2VTdGF0ZShudWxsLCBudWxsLCBuZXdIcmVmK3dpbmRvdy5sb2NhdGlvbi5zZWFyY2gpO1xuICAgICAgICAgICAgLy8g5L+u5pS55pyA5paw5p2hY2hhdExpc3TmlbDmja5cbiAgICAgICAgICAgIGxldCBuZXdDaGF0ID0ge1xuICAgICAgICAgICAgICAgIHNpZDp0aGlzLmNoYXRTZXNzaW9uPy5pZCxcbiAgICAgICAgICAgICAgICByaWQ6dGhpcy5yb2xlPy5pZCxcbiAgICAgICAgICAgICAgICBuYW1lOnRoaXMucm9sZT8uZ2V0KCduYW1lJyksXG4gICAgICAgICAgICAgICAgbWVzc2FnZTp0aGlzLmNoYXRTZXNzaW9uPy5nZXQoJ21lc3NhZ2VMaXN0Jyk/Llt0aGlzLmNoYXRTZXNzaW9uPy5nZXQoJ21lc3NhZ2VMaXN0Jyk/Lmxlbmd0aC0xXT8uY29udGVudD8uc2xpY2UoMCwyMCksXG4gICAgICAgICAgICAgICAgbGF0ZXN0OnRoaXMuY2hhdFNlc3Npb24/LmNyZWF0ZWRBdFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoIXRoaXMuY2hhdFNlcnY/LmNoYXRMaXN0Py5sZW5ndGgpIHRoaXMuY2hhdFNlcnYuY2hhdExpc3QgPSBbXVxuICAgICAgICAgICAgbGV0IGluZGV4ID0gdGhpcy5jaGF0U2Vydj8uY2hhdExpc3Q/LmZpbmQoaXRlbT0+aXRlbT8uc2lkPT1uZXdDaGF0Py5zaWQpXG4gICAgICAgICAgICBpZihpbmRleD4tMSl7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGF0U2Vydi5jaGF0TGlzdFtpbmRleF0gPSBuZXdDaGF0O1xuICAgICAgICAgICAgfSBlbHNle1xuICAgICAgICAgICAgICAgIHRoaXMuY2hhdFNlcnY/LmNoYXRMaXN0LnVuc2hpZnQobmV3Q2hhdClcbiAgICAgICAgICAgIH1cblxuICAgICAgICB9XG4gICAgfVxuICAgIGdldEludml0ZVVybCh1cmwpe1xuICAgICAgICAvLyDliKTmlq3mmK/lkKbmnInlj4LmlbBcbiAgICAgICAgbGV0IGNvbm5lY3RDaGFyID0gXCI/XCJcbiAgICAgICAgaWYodXJsPy5pbmRleE9mKFwiP1wiKT4tMSl7XG4gICAgICAgICAgY29ubmVjdENoYXIgPSBcIiZcIlxuICAgICAgICB9ZWxzZXtcbiAgICAgICAgICBjb25uZWN0Q2hhciA9IFwiP1wiXG4gICAgICAgIH1cbiAgICAgICAgLy8g6ZmE5YqgaW52aXRl5Y+C5pWwXG4gICAgICAgIGxldCBpZCA9IFBhcnNlLlVzZXI/LmN1cnJlbnQoKT8uaWRcbiAgICAgICAgaWYodXJsPy5pbmRleE9mKFwiaW52aXRlPVwiK2lkKT09LTEpe1xuICAgICAgICAgIGlmKCFpZCkgcmV0dXJuIHVybFxuICAgICAgICAgIHVybCArPSBjb25uZWN0Q2hhcisgJ2ludml0ZT0nICsgaWRcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdXJsXG4gICAgICB9XG4gICAgLy8g5qC55o2u6IGK5aSp5YaF5a655Y+K6Zeu6aKY77yM55Sf5oiQ5qCH6aKYXG4gICAgZ2VuVGl0bGUoKXtcbiAgICAgICAgaWYodGhpcy50aXRsZSkgcmV0dXJuIHRoaXMudGl0bGVcbiAgICAgICAgbGV0IGNvbnRlbnQ6c3RyaW5nfEFycmF5PENoYXRJbWFnZUNvbnRlbnRJdGVtPiA9ICB0aGlzLm1lc3NhZ2VMaXN0LmZpbmQoaXRlbT0+aXRlbS5yb2xlPT1cInVzZXJcIik/LmNvbnRlbnRcbiAgICAgICAgaWYodHlwZW9mIGNvbnRlbnQ9PVwic3RyaW5nXCIpeyAvLyDmiKrlm77mlofmnKzlhoXlrrnmloflrZfpg6jliIZcbiAgICAgICAgICAgIHRoaXMudGl0bGUgPSBjb250ZW50Py5zbGljZSgwLDE1KSB8fCBcIlwiXG4gICAgICAgIH1cbiAgICAgICAgaWYodHlwZW9mIGNvbnRlbnQ9PVwib2JqZWN0XCIpeyAvLyDmiKrlm77lpI3lkIjlhoXlrrnmloflrZfpg6jliIZcbiAgICAgICAgICAgIHRoaXMudGl0bGUgPSBjb250ZW50Py5maW5kKGl0ZW09Pml0ZW0/LnRleHQpPy50ZXh0IHx8IFwiXCJcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy50aXRsZVxuICAgIH1cbiAgICBmaXhNZXNzYWdlTGlzdChtZXNzYWdlczpGbW9kZUNoYXRNZXNzYWdlW10pe1xuICAgICAgICByZXR1cm4gbWVzc2FnZXMubWFwKG1zZz0+e3JldHVybiB7cm9sZTptc2cucm9sZSxjb250ZW50Om1zZy5jb250ZW50fX0pXG4gICAgfVxuXG4gICAgbm93U3RyKCl7XG4gICAgICAgIGxldCBub3cgPSBuZXcgRGF0ZSgpO1xuICAgICAgICByZXR1cm4gYCR7bm93LmdldEZ1bGxZZWFyKCl9LyR7bm93LmdldE1vbnRoKCkrMX0vJHtub3cuZ2V0RGF0ZSgpfSAke25vdy5nZXRIb3VycygpfToke25vdy5nZXRNaW51dGVzKCl9OiR7bm93LmdldFNlY29uZHMoKX1gXG4gICAgfVxuICAgIFxufVxuXG4vKipcbiAqIEZtb2RlQ2hhdENvbXBsZXRpb24g5paH5pys6KGl5YWo57G7XG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjbGFzcyBGbW9kZUNoYXRDb21wbGV0aW9ue1xuICAgIGluZGV4T2ZMaXN0Om51bWJlclxuICAgIG1vZGVsOnN0cmluZ1xuICAgIG1lc3NhZ2VzOkZtb2RlQ2hhdE1lc3NhZ2VbXSAvLyDooaXlhajliY3mj5DnpLror43liJfooahcbiAgICBjb250ZW50OnN0cmluZyA9IFwiXCIgLy8g5pys5qyh5o6l5pS25raI5oGv57uT5p6cXG4gICAgY29udGVudEJ1ZmZlcjpzdHJpbmdbXSA9IFtdXG4gICAgY29udGVudFB1c2hlcjphbnlcbiAgICBpc0NvbXBsZXRlZDpib29sZWFuID0gZmFsc2U7XG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIG1lc3NhZ2VzOkZtb2RlQ2hhdE1lc3NhZ2VbXSxvcHRpb25zPzp7XG4gICAgICAgICAgICBtb2RlbD86c3RyaW5nXG4gICAgICAgIH1cbiAgICApe1xuICAgICAgICB0aGlzLmluZGV4T2ZMaXN0ID0gTnVtYmVyKG1lc3NhZ2VzLmxlbmd0aClcbiAgICAgICAgdGhpcy5tZXNzYWdlcyA9IG1lc3NhZ2VzXG4gICAgICAgIHRoaXMubW9kZWwgPSBvcHRpb25zPy5tb2RlbCB8fCBcImZtb2RlLTQuNS0xMjhrXCJcbiAgICB9XG4gICAgLyoqXG4gICAgICogQHBhcmFtIG9wdGlvbnNcbiAgICAgKiBAcGFyYW0gb3B0aW9ucy5pc0RpcmVjdCDmmK/lkKbkuI3nrYnlvoXpgJDlrZfojrflj5bvvIznm7TmjqXlrozmiJDlhoXlrrnmjqjpgIFcbiAgICAgKiBAcGFyYW0gb3B0aW9ucy5pbnRUaW1lIOaYr+WQpuS4jeetieW+hemAkOWtl+iOt+WPlu+8jOebtOaOpeWujOaIkOWGheWuueaOqOmAgVxuICAgICAqIEByZXR1cm5zIFxuICAgICAqL1xuICAgIHNlbmRDb21wbGV0aW9uKG9wdGlvbnM6e1xuICAgICAgICBpc0RpcmVjdD86Ym9vbGVhbixcbiAgICAgICAgaW50VGltZT86bnVtYmVyLFxuICAgICAgICBvbkNvbXBsZXRlPzpGdW5jdGlvblxuICAgIH09e30pOk9ic2VydmFibGU8Rm1vZGVDaGF0TWVzc2FnZT57XG4gICAgICAgIG9wdGlvbnMuaW50VGltZSA9IG9wdGlvbnM/LmludFRpbWUgfHwgNTAgLy8g5oyJ5q+r56eS6YCQ5a2X5o6o6YCBXG4gICAgICAgIG9wdGlvbnMuaXNEaXJlY3QgPSBvcHRpb25zPy5pc0RpcmVjdCB8fCBmYWxzZVxuICAgICAgICBpZihvcHRpb25zPy5pc0RpcmVjdCkgb3B0aW9ucy5pbnRUaW1lID0gMVxuXG4gICAgICAgIGxldCB0aGF0ID0gdGhpcztcbiAgICAgICAgbGV0IG9wdHMgPSB7XG4gICAgICAgICAgICBcIm1lc3NhZ2VzXCI6dGhpcy5tZXNzYWdlcyxcbiAgICAgICAgICAgIFwic3RyZWFtXCI6dHJ1ZSxcbiAgICAgICAgICAgIFwibW9kZWxcIjp0aGlzLm1vZGVsLFxuICAgICAgICAgICAgXCJ0ZW1wZXJhdHVyZVwiOjAuNSxcbiAgICAgICAgICAgIFwicHJlc2VuY2VfcGVuYWx0eVwiOjAsXG4gICAgICAgICAgICBcImZyZXF1ZW5jeV9wZW5hbHR5XCI6MFxuICAgICAgICB9XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKG9wdHMpXG4gICAgICAgIGxldCAkbWVzc2FnZVJlY2VpdmVyID0gbmV3IE9ic2VydmFibGUoKG9ic2VydmVyOiBPYnNlcnZlcjxGbW9kZUNoYXRNZXNzYWdlPikgPT4ge1xuICAgICAgICAgICAgbGV0IHN1YnNjcmlwdGlvbiA9IFJlcXVlc3RGbW9kZUNoYXRBcGkoXCIvdjEvY2hhdC9jb21wbGV0aW9uc1wiLCBvcHRzKVxuICAgICAgICAgICAgLnN1YnNjcmliZShkYXRhID0+IHtcbiAgICAgICAgICAgICAgICAvLyBIYW5kbGUgZWFjaCBjaHVuayBvZiBkYXRhXG4gICAgICAgICAgICAgICAgLyoqIENodW5r5paH5pys5pWw5o2u5qC85byP5aaC5LiL77yaXG4gICAgICAgICAgICAgICAg5q2j5bi45raI5oGv77yaXG4gICAgICAgICAgICAgICAgJ2RhdGE6IHtcImlkXCI6XCJjaGF0Y21wbC15MlBMS3FQRG53QUZKSWoyTDVhcWRINVRXSzlZdlwiLFwib2JqZWN0XCI6XCJjaGF0LmNvbXBsZXRpb24uY2h1bmtcIixcImNyZWF0ZWRcIjoxNjk2NzcwMTYyLFwibW9kZWxcIjpcImdwdC0zLjUtdHVyYm8tMDYxM1wiLFwiY2hvaWNlc1wiOlt7XCJpbmRleFwiOjAsXCJkZWx0YVwiOntcImNvbnRlbnRcIjpcIuacrOaPkOekuuivjeS7heeUqOS6jua1i+ivleOAglwifSxcImZpbmlzaF9yZWFzb25cIjpudWxsfV19JyxcbiAgICAgICAgICAgICAgICDnu4jmraLljp/lm6DvvJpcbiAgICAgICAgICAgICAgICAnZGF0YToge1wiaWRcIjpcImNoYXRjbXBsLXkyUExLcVBEbndBRkpJajJMNWFxZEg1VFdLOVl2XCIsXCJvYmplY3RcIjpcImNoYXQuY29tcGxldGlvbi5jaHVua1wiLFwiY3JlYXRlZFwiOjE2OTY3NzAxNjIsXCJtb2RlbFwiOlwiZ3B0LTMuNS10dXJiby0wNjEzXCIsXCJjaG9pY2VzXCI6W3tcImluZGV4XCI6MCxcImRlbHRhXCI6e30sXCJmaW5pc2hfcmVhc29uXCI6XCJzdG9wXCJ9XX0nLFxuICAgICAgICAgICAgICAgIOe7k+adn+a2iOaBr++8mlxuICAgICAgICAgICAgICAgICdkYXRhOiBbRE9ORV0nXG4gICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICBsZXQgY2h1bmsgPSBTdHJpbmcoZGF0YSk7XG4gICAgICAgICAgICAgICAgLy8gQ2hlY2sgaWYgdGhlIGNvbXBsZXRpb24gbWVzc2FnZSBpcyByZWNlaXZlZFxuICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKGNodW5rKVxuICAgICAgICAgICAgICAgIGlmIChjaHVuayA9PSAnZGF0YTogW0RPTkVdJykgeyBcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pc0NvbXBsZXRlZCA9IHRydWU7IC8vIOagh+iusOWujOaIkCA9PiDnrYnlvoVpbnRlcnZhbOaOqOmAgVxuICAgICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhvcHRpb25zPy5pc0RpcmVjdCx0aGlzLmlzQ29tcGxldGVkKVxuICAgICAgICAgICAgICAgICAgICBpZihvcHRpb25zPy5pc0RpcmVjdCAmJiB0aGlzLmlzQ29tcGxldGVkKXtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLm5leHQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvbGU6XCJhc3Npc3RhbnRcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBjaWQ6Y2h1bmtqc29uPy5bJ2lkJ10sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGVudDp0aGlzLmNvbnRlbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcGxldGU6dHJ1ZSwgLy8g5o6o6YCB5a6M5oiQXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY3JlYXRlZEF0Om5ldyBEYXRlKClcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICBzdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTsgLy8gVW5zdWJzY3JpYmUgd2hlbiBkb25lXG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zPy5vbkNvbXBsZXRlJiZvcHRpb25zLm9uQ29tcGxldGUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvbGU6XCJhc3Npc3RhbnRcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBjaWQ6Y2h1bmtqc29uPy5bJ2lkJ10sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGVudDp0aGlzLmNvbnRlbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcGxldGU6dHJ1ZSwgLy8g5o6o6YCB5a6M5oiQXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY3JlYXRlZEF0Om5ldyBEYXRlKClcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5jb21wbGV0ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKGNodW5rKVxuICAgICAgICAgICAgICAgIGlmKGNodW5rLmluZGV4T2YoXCJkYXRhOlxcIHtcIik+LTEpe1xuICAgICAgICAgICAgICAgICAgICBsZXQgY2h1bmtqc29uID0gY2h1bmtUb0pzb24oY2h1bmspXG4gICAgICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKGNodW5rKVxuICAgICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhjaHVua2pzb24/LmNob2ljZXM/LlswXT8uZGVsdGEpXG4gICAgICAgICAgICAgICAgICAgIGxldCB3b3JkcyA9IGNodW5ranNvbj8uY2hvaWNlcz8uWzBdPy5kZWx0YT8uY29udGVudCB8fCBcIlwiXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29udGVudEJ1ZmZlci5wdXNoKHdvcmRzKTtcblxuICAgICAgICAgICAgICAgICAgICAvLyDmtojmga/ov5Tlm57mqKHlvI/vvJrlrprml7blmajmjqjpgIHvvIzmqKHmi5/pgJDlrZfovpPlh7pcbiAgICAgICAgICAgICAgICAgICAgaWYob3B0aW9ucz8uaXNEaXJlY3Qpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29udGVudCArPSAod29yZHMgfHwgXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyDpu5jorqTntK/liqDmtojmga/nu5PmnpxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZighdGhpcy5pc0NvbXBsZXRlZCl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLm5leHQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9sZTpcImFzc2lzdGFudFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2lkOmNodW5ranNvbj8uWydpZCddLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGVudDp0aGlzLmNvbnRlbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjcmVhdGVkQXQ6bmV3IERhdGUoKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZighb3B0aW9ucz8uaXNEaXJlY3QmJiF0aGlzLmNvbnRlbnRQdXNoZXIpe1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb250ZW50UHVzaGVyID0gc2V0SW50ZXJ2YWwoKCk9PntcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZih0aGlzLmlzQ29tcGxldGVkICYmIHRoaXMuY29udGVudEJ1ZmZlcj8ubGVuZ3RoPT0wKXsgLy8g5o6o6YCB5a6M5q+V77yM5riF6Zmk6K6h5pe25ZmoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLm5leHQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9sZTpcImFzc2lzdGFudFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2lkOmNodW5ranNvbj8uWydpZCddLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGVudDp0aGlzLmNvbnRlbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wbGV0ZTp0cnVlLCAvLyDmjqjpgIHlrozmiJBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNyZWF0ZWRBdDpuZXcgRGF0ZSgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpOyAvLyBVbnN1YnNjcmliZSB3aGVuIGRvbmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLmNvbnRlbnRQdXNoZXIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLmNvbXBsZXRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKHRoaXMuY29udGVudEJ1ZmZlcj8ubGVuZ3RoPj0wKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYodGhpcy5jb250ZW50QnVmZmVyPy5sZW5ndGg+MCl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRlbnQgKz0gdGhpcy5jb250ZW50QnVmZmVyLnNoaWZ0KClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvbGU6XCJhc3Npc3RhbnRcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNpZDpjaHVua2pzb24/LlsnaWQnXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnQ6dGhpcy5jb250ZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3JlYXRlZEF0Om5ldyBEYXRlKClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9LG9wdGlvbnM/LmludFRpbWUpXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2codGhpcy5jb250ZW50KVxuICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgICAgICByZXR1cm4gJG1lc3NhZ2VSZWNlaXZlci5waXBlKFxuICAgICAgICAgICAgYnVmZmVyVGltZSgxMDApLCAvLyDmr48xMDBtc+aUtumbhua2iOaBr1xuICAgICAgICAgICAgY29uY2F0TWFwKG1lc3NhZ2VzID0+IG1lc3NhZ2VzKSwgLy8g5L2/55SoIGNvbmNhdE1hcCDpgJDkuKrlj5HpgIHmtojmga9cbiAgICAgICAgICAgIGRlbGF5KDIwMCkgLy8g5bu26L+fMjAwbXPovpPlh7rmr4/mnaHmtojmga9cbiAgICAgICAgKVxuICAgIH1cblxufVxuXG5mdW5jdGlvbiBjaHVua1RvSnNvbihjaHVuayl7XG4gICAgbGV0IGNodW5ranNvbjphbnlcbiAgICB0cnl7XG4gICAgICAgIGNodW5ranNvbiA9IEpTT04ucGFyc2UoY2h1bmsucmVwbGFjZUFsbChcImRhdGE6XFwgXCIsXCJcIikpO1xuICAgIH1jYXRjaChlcnJkail7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyZGopXG4gICAgfVxuICAgIHJldHVybiBjaHVua2pzb24gfHwge31cbn1cbmZ1bmN0aW9uIFJlcXVlc3RGbW9kZUNoYXRBcGkoYXBpcGF0aCwgYm9keSwgbWV0aG9kID0gXCJQT1NUXCIpIHtcbiAgICByZXR1cm4gbmV3IE9ic2VydmFibGUoKG9ic2VydmVyOiBPYnNlcnZlcjxhbnk+KSA9PiB7XG4gICAgICAgIGxldCB1cmwgPSBBUElfQkFTRSArIGFwaXBhdGg7XG4gICAgICAgIGxldCBBUElfVE9LRU4gPSBQYXJzZS5Vc2VyLmN1cnJlbnQoKT8uZ2V0U2Vzc2lvblRva2VuKCkgfHwgbG9jYWxTdG9yYWdlLmdldEl0ZW0oXCJGTU9ERV9BSV9UT0tFTlwiKTtcbiAgICAgICAgICAgIC8vIOmAmui/h2JvZHnkvKDpgJJ0b2tlbuWPguaVsO+8jOmBv+WFjW5vLWNvcnPmqKHlvI/kuItBdXRob3JpenRpb27lpLTpg6jml6DmlYhcbiAgICAgICAgbGV0IEFVVEhfVE9LRU4gPSBgQmVhcmVyICR7QVBJX1RPS0VOfWBcbiAgICAgICAgYm9keS50b2tlbiA9IEFVVEhfVE9LRU47XG4gICAgICAgIGlmKGJvZHkpIGJvZHkgPSBKU09OLnN0cmluZ2lmeShib2R5KVxuICAgICAgICBmZXRjaCh1cmwsIHtcbiAgICAgICAgICAgIFwiaGVhZGVyc1wiOiB7XG4gICAgICAgICAgICAgICAgLy8gXCJBdXRob3JpemF0aW9uXCI6IEFVVEhfVE9LRU4sXG4gICAgICAgICAgICAgICAgXCJDb250ZW50LVR5cGVcIjogXCJ0ZXh0L3BsYWluXCIsXG4gICAgICAgICAgICAgICAgXCJDYWNoZS1Db250cm9sXCI6IFwibm8tY2FjaGVcIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFwiYm9keVwiOiBib2R5IHx8IG51bGwsXG4gICAgICAgICAgICBcIm1ldGhvZFwiOiBtZXRob2QsXG4gICAgICAgICAgICBcImNyZWRlbnRpYWxzXCI6XCJvbWl0XCIsXG4gICAgICAgICAgICBcIm1vZGVcIjogXCJjb3JzXCJcbiAgICAgICAgfSkudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICAgICAgICBsZXQgaXNTdHJlYW0gPSB0cnVlIHx8IHJlc3BvbnNlLmhlYWRlcnM/LmdldChcIkNvbnRlbnQtVHlwZVwiKT8uaW5kZXhPZihcInRleHQvZXZlbnQtc3RyZWFtXCIpID4gLTFcbiAgICAgICAgICAgIGxldCByZW1haW5pbmdEYXRhID0gYGA7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHByb2Nlc3NEYXRhKGRhdGEpIHtcbiAgICAgICAgICAgICAgICBsZXQgY29tYmluZWREYXRhID0gcmVtYWluaW5nRGF0YSArIGRhdGE7XG4gICAgICAgICAgICAgICAgbGV0IG1lc3NhZ2VzID0gY29tYmluZWREYXRhLnNwbGl0KCdcXG4nKTtcbiAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgaWYobWVzc2FnZXM/Lmxlbmd0aD4xKXsgLy8g6Iez5bCR5YiG5YmyMuadoea2iOaBr+aXtui/m+ihjOWkhOeQhlxuICAgICAgICAgICAgICAgICAgICAvLyDlpITnkIbmr4/kuKrlrozmlbTnmoTmtojmga9cbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtZXNzYWdlcy5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBtZXNzYWdlID0gbWVzc2FnZXNbaV07XG4gICAgICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KG1lc3NhZ2UpXG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyDkv53lrZjmnIDlkI7kuIDkuKrkuI3lrozmlbTnmoTmtojmga9cbiAgICAgICAgICAgICAgICAgICAgcmVtYWluaW5nRGF0YSA9IG1lc3NhZ2VzW21lc3NhZ2VzLmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoaXNTdHJlYW0pIHtcbiAgICAgICAgICAgICAgICBsZXQgZ3JlYWRlciA9IHJlc3BvbnNlLmJvZHk/LmdldFJlYWRlcigpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGRlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoKTtcblxuICAgICAgICAgICAgICAgIGxldCByc3RyZWFtID0gbmV3IFJlYWRhYmxlU3RyZWFtKHtcbiAgICAgICAgICAgICAgICAgICAgc3RhcnQoY29udHJvbGxlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gcmVhZCgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBncmVhZGVyLnJlYWQoKS50aGVuKCh7IGRvbmUsIHZhbHVlIH0pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbGxlci5jbG9zZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5jb21wbGV0ZSgpOyAvLyBDb21wbGV0ZSB0aGUgb2JzZXJ2ZXIgd2hlbiBzdHJlYW0gcHJvY2Vzc2luZyBpcyBkb25lXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sbGVyLmVucXVldWUodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFkKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJlYWQoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgbGV0IHJlYWRlciA9IHJzdHJlYW0uZ2V0UmVhZGVyKCk7XG5cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBwcm9jZXNzU3RyZWFtKHsgZG9uZSwgdmFsdWUgfSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZG9uZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbGV0IHRleHQgPSBkZWNvZGVyLmRlY29kZSh2YWx1ZSlcbiAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc0RhdGEodGV4dCkgLy8gRW1pdCBlYWNoIGNodW5rIG9mIGRhdGFcbiAgICAgICAgICAgICAgICAgICAgcmVhZGVyLnJlYWQoKS50aGVuKHByb2Nlc3NTdHJlYW0pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJlYWRlci5yZWFkKCkudGhlbihwcm9jZXNzU3RyZWFtKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4gb2JzZXJ2ZXIuZXJyb3IoZXJyb3IpKTsgLy8gSGFuZGxlIGFueSBlcnJvcnNcblxuICAgICAgICAvLyBSZXR1cm4gdGhlIHN1YnNjcmlwdGlvbiBsb2dpY1xuICAgICAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgICAgICAgLy8gQ2xlYW4gdXAgbG9naWMsIGlmIG5lZWRlZFxuICAgICAgICB9O1xuICAgIH0pO1xuICB9XG4gIFxuICBmdW5jdGlvbiBKc29uVG9Gb3JtRGF0YShqc29uKSB7XG4gICAgY29uc3QgZm9ybURhdGEgPSBuZXcgRm9ybURhdGEoKTtcbiAgXG4gICAgZnVuY3Rpb24gYXBwZW5kRm9ybURhdGEoZGF0YSwgcGF0aCA9ICcnKSB7XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShkYXRhKSkge1xuICAgICAgICBkYXRhLmZvckVhY2goKHZhbHVlLCBpbmRleCkgPT4ge1xuICAgICAgICAgIGFwcGVuZEZvcm1EYXRhKHZhbHVlLCBgJHtwYXRofVske2luZGV4fV1gKTtcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBkYXRhID09PSAnb2JqZWN0JyAmJiBkYXRhICE9PSBudWxsKSB7XG4gICAgICAgIE9iamVjdC5rZXlzKGRhdGEpLmZvckVhY2goa2V5ID0+IHtcbiAgICAgICAgICBjb25zdCBuZXdQYXRoID0gcGF0aCA/IGAke3BhdGh9LiR7a2V5fWAgOiBrZXk7XG4gICAgICAgICAgYXBwZW5kRm9ybURhdGEoZGF0YVtrZXldLCBuZXdQYXRoKTtcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBmb3JtRGF0YS5hcHBlbmQocGF0aCwgZGF0YSk7XG4gICAgICB9XG4gICAgfVxuICBcbiAgICBhcHBlbmRGb3JtRGF0YShqc29uKTtcbiAgXG4gICAgcmV0dXJuIGZvcm1EYXRhO1xuICB9Il19
8
+ import{bufferTime,concatMap,Observable,delay,finalize}from"rxjs";import Parse from"parse";import{AgentPrompt}from"../../agent";import{FmodeTTS}from"../../voice/tts";import{PromptTemplate}from"@langchain/core/prompts";const API_BASE="https://server.fmode.cn/api/apig/aigc/gpt",agentPrompt=new AgentPrompt,PromptTplTalkSSMLOutputCode="talk-ssml-output-tpl",PromptTplTalkTextSSMLCode="talk-text-ssml-tpl";export function getMessageContentText(t){let e="";return"string"==typeof t&&(e=t),"object"==typeof t&&(e=t?.find((t=>t?.text))?.text||""),e}export function getMessageImageUrl(t){return"object"==typeof t?t?.find((t=>t?.image_url))?.image_url?.url||"":null}export class FmodeChat{showAvatar(){this.avatarConfig=this.role?.get("avatarConfig"),this.avatarConfig&&(this.isAvatarShow=!0,this.avatarConfig?.image&&(this.avatarConfig.image.waiting=this.avatarConfig.image.waiting||this.role?.get("thumb")||this.role?.get("avatar"),this.avatarMode="image"),this.avatarConfig?.video&&(this.avatarConfig.video.waiting=this.avatarConfig.video.waiting,this.avatarMode="video"))}constructor(t,e,s,i,o,n,a){this.ChatSession=Parse.Object.extend("ChatSession"),this.messageList=[{role:"system",content:"系统提示:AI仅供参考"}],this.latestAIResponse="",this.userInput="",this.userImage="",this.isDirect=!1,this.isAvatarShow=!1,this.avatarMode="",this.isPromptModalOpen=!1,this.isPromptMessageAreaShow=!0,this.promptList=[],this.leftButtons=[{title:"灵感",icon:"color-wand-outline",onClick:()=>{this.isPromptModalOpen=!0},show:()=>this?.promptList?.length},{title:"角色",icon:"people-outline",onClick:()=>{this.navCtrl?.navigateRoot("/chat/pro/mask")},show:()=>!0},{title:"呼叫",icon:"call-outline",onClick:()=>{this.chatServ?.callRole(this.role)},show:()=>this?.role?.get("voiceConfig")}],this.isVoiceInputMode=!1,this.isTexting=!1,this.isTalkMode=!1,this.SSMLRoleVoice="zh-CN-XiaoxiaoNeural",this.playAnimation=t=>{console.log(t)},this.welcome=async()=>{let t=this.messageList?.filter((t=>"assistant"==t?.role));if(t?.length)return;let e=Parse.User.current(),s=await this.loadSelf("Person","userVerify"),i=await this.loadSelf("Profile","user"),o=e?.get("realname")||i?.get("name")||s?.get("name")||e?.get("nickname")||e?.get("name"),n=this.role.get("voiceConfig")?.welcome?.prompt;if(!n)return;let a=await PromptTemplate.fromTemplate(n,{templateFormat:"mustache"}).format({name:o,timeOfDay:this.getTimeOfDay()}),r=await this.getVoiceByContentText(a),l={role:"assistant",voice:r,content:a,complete:!0};this.voiceMap[r?.id],this.playChatVoice(this.voiceMap[r?.id]),this.messageList.push(l)},this.self={},this.voiceMap={},this.chatServ=i,this.role=e,this.sessionId=t,this.navCtrl=o,this.ncloud=n,this.uploadServ=a,s?.id&&(this.chatSession=s,this.messageList=this.chatSession.get("messageList"),this.sessionId=s?.id),this.role?.id&&(this.voiceConfig=this.role?.get("voiceConfig"),this.voiceConfig?.autoTalk&&(this.isTalkMode=!0,this.isDirect=!0))}getTimeOfDay(){const t=(new Date).getHours();return t>=5&&t<12?"早上":t>=12&&t<14?"中午":t>=14&&t<18?"下午":"晚上"}async loadSelf(t,e){if(this.self[t])return this.self[t];let s=Parse.User.current(),i=new Parse.Query(t);i.equalTo(e,s?.id),this.self[t]=await i.first()}async loadTalkSystemPrompt(t){if(!this.isTalkMode)return;if(!t)return;"男"==t?.get("gender")?this.SSMLRoleVoice="zh-CN-YunyeNeural":this.SSMLRoleVoice="zh-CN-XiaoxiaoNeural",this.SSMLRoleVoice=t?.get("voiceConfig")?.voice||this.SSMLRoleVoice;let e=await agentPrompt.getFormatTpl("talk-ssml-output-tpl",{SSMLRoleVoice:this.SSMLRoleVoice}),s=t.get("prompt")||"请你扮演飞码AI的人工智能专家。";s+=e;let i={role:"user",content:s,hidden:!0},o=this.messageList?.map((t=>t?.content)).join();if(o.indexOf(s)>-1)return;let n=this.messageList?.findIndex((t=>"system"==t?.role)),a=n+1;this.messageList.splice(a,0,i)}loadRolePrompt(){let t=this.role?.get("prompt"),e={role:"user",content:t,hidden:!0};if(!t)return;let s=this.messageList?.map((t=>t?.content)).join();if(s.indexOf(t)>-1)return;let i=this.messageList?.findIndex((t=>"system"==t?.role)),o=i+1;this.messageList.splice(o,0,e)}async sendMessage(t="FmodeAiTest测试问题",e,s,i,o){if(this.isPromptMessageAreaShow=!1,this.loadRolePrompt(),e){let s={role:"user",content:[{type:"image_url",image_url:{url:e}},{type:"text",text:t}],complete:!0,createdAt:new Date};o&&(s.voice={id:o?.id}),this.messageList.push({role:"user",content:[{type:"image_url",image_url:{url:e}},{type:"text",text:t}],complete:!0,createdAt:new Date})}else{let e={role:"user",content:t,complete:!0,createdAt:new Date};o&&(e.voice={id:o?.id,duration:o?.duration}),this.messageList.push(e)}let n=new FmodeChatCompletion(this.fixMessageList(this.messageList),{model:this.chatServ?.currentModel?.get("code")||"fmode-4.5-128k"});this.userInput="",this.userImage="";let a=this.isDirect||!1;this.isTalkMode&&(a=!0);let r=n.sendCompletion({isDirect:a,onComplete:s||null}).pipe(finalize((async()=>{if(this.isTalkMode){let t=this.messageList[n.indexOfList]?.content,e=await this.getVoiceByContentText(t,i);i?.onSSMLComplete&&i?.onSSMLComplete(e),this.messageList[n.indexOfList].voice=e,this.playChatVoice(this.voiceMap[e?.id])}this.messageList[n.indexOfList].complete=!0}))).subscribe((t=>{this.messageList[n.indexOfList]=t,this.latestAIResponse=this.getContentText(t?.content);let e=this.chatSession?.get("messageList")?.length;this.messageList?.length>e&&this.saveChatSession(),t?.complete&&(this.saveChatSession(),r.unsubscribe())}))}getVoiceByContentText(t,e,s=!1){let i=this.getContentText(t),o=new(Parse.Object.extend("ChatVoice")),n="";return this.SSMLRoleVoice=this.role?.get("voiceConfig")?.voice||this.SSMLRoleVoice,new Promise((async(t,e)=>{let resolveChatVoice=async()=>{o.set("content",i),o.set("ssml",n),o.set("role","assistant");let e=localStorage.getItem("company");e&&o.set("company",{__type:"Pointer",className:"Company",objectId:e}),Parse.User.current()?.id&&o.set("user",Parse.User.current().toPointer()),this.chatSession?.id&&o.set("session",this.chatSession?.toPointer()),o=await o.save(),this.voiceMap[o?.id]=o,t({id:o?.id})};if(0==s&&(n=`<speak xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="http://www.w3.org/2001/mstts" xmlns:emo="http://www.w3.org/2009/10/emotionml" version="1.0" xml:lang="zh-CN"><voice name="${this.SSMLRoleVoice}">${i}</voice></speak>`,resolveChatVoice()),1==s){let t=await agentPrompt.getFormatTpl("talk-text-ssml-tpl",{content:i,SSMLRoleVoice:this.SSMLRoleVoice});new FmodeChatCompletion(this.fixMessageList([{role:"user",content:t}]),{model:this.chatServ?.currentModel?.get("code")||"fmode-4.5-128k"}).sendCompletion({isDirect:!0}).subscribe((async t=>{t?.complete&&(n=this.getContentText(t?.content),resolveChatVoice())}))}}))}getContentText(t){return"string"==typeof t?t:t?.[0]?.text||""}async initTTS(){let t=await this.ncloud.apig("voice/tts/token",{company:localStorage.getItem("company")});if(console.log(t),t?.token){let e=new FmodeTTS(t,this.uploadServ);this.tts=e}}async playChatVoice(t,e){if(await this.initTTS(),this.tts)try{this.playAnimation("talking"),await this.tts.speakAsync(t?.get("ssml"),t,{onLoaded:t=>{e?.onLoaded&&e?.onLoaded(t)},onStop:()=>{e?.onStop&&e?.onStop(),this.playAnimation("waiting")}})}catch(t){console.error(t)}}async saveChatSession(){if("new"==this.sessionId&&(this.chatSession=new this.ChatSession),this.chatSession.set("title",this.genTitle()),this.chatSession.set("role",this.role?.toPointer()),this.chatSession.set("messageList",this.messageList),this.chatSession.set("user",Parse.User.current()?.toPointer()),this.chatSession=await this.chatSession.save(),this.sessionId=this.chatSession?.id,this.sessionId){let t=`${window.location.origin}/chat/pro/chat/${this.sessionId}`;window.location?.pathname?.indexOf("chat/session")>-1&&(t=`${window.location.origin}/chat/session/chat/${this.sessionId}`),t=this.getInviteUrl(t),window.history.replaceState(null,null,t+window.location.search);let e={sid:this.chatSession?.id,rid:this.role?.id,name:this.role?.get("name"),message:this.chatSession?.get("messageList")?.[this.chatSession?.get("messageList")?.length-1]?.content?.slice(0,20),latest:this.chatSession?.createdAt};this.chatServ?.chatList?.length||(this.chatServ.chatList=[]);let s=this.chatServ?.chatList?.find((t=>t?.sid==e?.sid));s>-1?this.chatServ.chatList[s]=e:this.chatServ?.chatList.unshift(e)}}getInviteUrl(t){let e="?";e=t?.indexOf("?")>-1?"&":"?";let s=Parse.User?.current()?.id;if(-1==t?.indexOf("invite="+s)){if(!s)return t;t+=e+"invite="+s}return t}genTitle(){if(this.title)return this.title;let t=this.messageList.find((t=>"user"==t.role))?.content;return"string"==typeof t&&(this.title=t?.slice(0,15)||""),"object"==typeof t&&(this.title=t?.find((t=>t?.text))?.text||""),this.title}fixMessageList(t){return t.map((t=>({role:t.role,content:t.content})))}nowStr(){let t=new Date;return`${t.getFullYear()}/${t.getMonth()+1}/${t.getDate()} ${t.getHours()}:${t.getMinutes()}:${t.getSeconds()}`}}export class FmodeChatCompletion{constructor(t,e){this.content="",this.contentBuffer=[],this.isCompleted=!1,this.indexOfList=Number(t.length),this.messages=t,this.model=e?.model||"fmode-4.5-128k"}sendCompletion(t={}){t.intTime=t?.intTime||50,t.isDirect=t?.isDirect||!1,t?.isDirect&&(t.intTime=1);let e={messages:this.messages,stream:!0,model:this.model,temperature:.5,presence_penalty:0,frequency_penalty:0};return new Observable((s=>{let i=RequestFmodeChatApi("/v1/chat/completions",e).subscribe((e=>{let o=String(e);if("data: [DONE]"==o&&(this.isCompleted=!0,t?.isDirect&&this.isCompleted&&(s.next({role:"assistant",content:this.content,complete:!0,createdAt:new Date}),i.unsubscribe(),t?.onComplete&&t.onComplete({role:"assistant",content:this.content,complete:!0,createdAt:new Date}),s.complete())),o.indexOf("data: {")>-1){let e=chunkToJson(o),n=e?.choices?.[0]?.delta?.content||"";this.contentBuffer.push(n),t?.isDirect&&(this.content+=n||"",this.isCompleted||s.next({role:"assistant",cid:e?.id,content:this.content,createdAt:new Date})),t?.isDirect||this.contentPusher||(this.contentPusher=setInterval((()=>{this.isCompleted&&0==this.contentBuffer?.length&&(s.next({role:"assistant",cid:e?.id,content:this.content,complete:!0,createdAt:new Date}),i.unsubscribe(),clearInterval(this.contentPusher),s.complete()),this.contentBuffer?.length>=0&&(this.contentBuffer?.length>0&&(this.content+=this.contentBuffer.shift()),s.next({role:"assistant",cid:e?.id,content:this.content,createdAt:new Date}))}),t?.intTime))}}))})).pipe(bufferTime(100),concatMap((t=>t)),delay(200))}}function chunkToJson(t){let e;try{e=JSON.parse(t.replaceAll("data: ",""))}catch(t){console.error(t)}return e||{}}function RequestFmodeChatApi(t,e,s="POST"){return new Observable((i=>{let o=API_BASE+t,n=`Bearer ${Parse.User.current()?.getSessionToken()||localStorage.getItem("FMODE_AI_TOKEN")}`;return e.token=n,e&&(e=JSON.stringify(e)),fetch(o,{headers:{"Content-Type":"text/plain","Cache-Control":"no-cache"},body:e||null,method:s,credentials:"omit",mode:"cors"}).then((t=>{let e="";{let s=t.body?.getReader();const o=new TextDecoder;let n=new ReadableStream({start(t){!function read(){s.read().then((({done:e,value:s})=>{if(e)return t.close(),void i.complete();t.enqueue(s),read()}))}()}}).getReader();n.read().then((function processStream({done:t,value:s}){if(t)return;!function processData(t){let s=(e+t).split("\n");if(s?.length>1){for(let t=0;t<s.length-1;t++){let e=s[t];i.next(e)}e=s[s.length-1]}}(o.decode(s)),n.read().then(processStream)}))}})).catch((t=>i.error(t))),()=>{}}))}function JsonToFormData(t){const e=new FormData;return function appendFormData(t,s=""){Array.isArray(t)?t.forEach(((t,e)=>{appendFormData(t,`${s}[${e}]`)})):"object"==typeof t&&null!==t?Object.keys(t).forEach((e=>{const i=s?`${s}.${e}`:e;appendFormData(t[e],i)})):e.append(s,t)}(t),e}
9
+ var MODULE_PATH_NEED = `6K+l5paH5Lu25piv5pys6aG555uu55qE5LiA6YOo5YiGIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHRoZSBDb21wb25lbnRzIGluIEZtb2RlIEluYy4KICAgIOeJiOadg+aJgOaciSDCqSDmnKrmnaXpo57pqawgwqkg5rGf6KW/6ISR5o6n56eR5oqA5pyJ6ZmQ5YWs5Y+4IENvcHlyaWdodCDCqSBGbW9kZSBUZWNobm9sb2d5IENvLiwgTHRkLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCiAgICDkuKXnpoHlnKjmnKrnu4/mjojmnYPnmoTmg4XlhrXkuIvvvIzpgJrov4fku7vkvZXlqpLku4vlpI3liLbmraTmlofku7YgVW5hdXRob3JpemVkIGNvcHlpbmcgb2YgdGhpcyBmaWxlLCB2aWEgYW55IG1lZGl1bSBpcyBzdHJpY3RseSBwcm9oaWJpdGVkCiAgICDor6Xmlofku7bmmK/kuJPmnInnmoTmnLrlr4bmlofku7YgUHJvcHJpZXRhcnkgYW5kIGNvbmZpZGVudGlhbAogICAKICAgIENvcHlyaWdodCAyMDIxLW5vdyBGbW9kZSBJbmMuIHN1cHBvcnRAZm1vZGUuY24uIDE4NjA3MDA3MDczLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUEFUSDovaG9tZS9yeWFuL3dvcmtzcGFjZS9ub3ZhL25vdmEtYWRtaW4vZGlzdC9mbW9kZS1uZy9lc20yMDIyL2xpYi9haWdjL3NlcnZpY2UtZm1haS9zZXJ2aWNlLWNoYXQvY2hhdC1jbGFzcy5tanM=`
10
+