experimental-agent 0.1.3 → 0.2.0

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 (41) hide show
  1. package/dist/agent-workflow.d.mts +2 -1
  2. package/dist/agent-workflow.d.ts +2 -1
  3. package/dist/agent-workflow.js +1382 -552
  4. package/dist/agent-workflow.mjs +3 -2
  5. package/dist/chunk-FQ67QZOI.mjs +75 -0
  6. package/dist/{chunk-RXPVLORL.mjs → chunk-GL7Q3MDU.mjs} +3 -7
  7. package/dist/{chunk-24UDM5XV.mjs → chunk-NXDVNJRS.mjs} +1 -1
  8. package/dist/chunk-OCF5I43X.mjs +2367 -0
  9. package/dist/chunk-OZZVS6L5.mjs +139 -0
  10. package/dist/{chunk-2ZXHR6T6.mjs → chunk-SJVFFE5D.mjs} +18 -17
  11. package/dist/chunk-TGNVXSMX.mjs +399 -0
  12. package/dist/chunk-UCVXI7LW.mjs +1287 -0
  13. package/dist/chunk-ZIAHPXOJ.mjs +595 -0
  14. package/dist/{client-SNN3XDKO.mjs → client-BKA7XBGW.mjs} +1 -1
  15. package/dist/{client-Bkuq-Dfa.d.mts → client-CSTexnLF.d.mts} +158 -122
  16. package/dist/{client-Bkuq-Dfa.d.ts → client-CSTexnLF.d.ts} +158 -122
  17. package/dist/{sandbox-IFK5MVRM.mjs → docker-FB2MJTHJ.mjs} +6 -4
  18. package/dist/{handler-WFNQWR6V.mjs → handler-FRUPZ4LX.mjs} +1 -1
  19. package/dist/index.d.mts +3 -2
  20. package/dist/index.d.ts +3 -2
  21. package/dist/index.js +1555 -596
  22. package/dist/index.mjs +140 -36
  23. package/dist/lifecycle-workflow.d.mts +2 -1
  24. package/dist/lifecycle-workflow.d.ts +2 -1
  25. package/dist/lifecycle-workflow.js +29 -18
  26. package/dist/lifecycle-workflow.mjs +1 -1
  27. package/dist/{local-fs-handlers-ESZBRAWK.mjs → local-fs-handlers-SYOCKTPN.mjs} +10 -2
  28. package/dist/next/loader.js +16 -12
  29. package/dist/next/loader.mjs +15 -7
  30. package/dist/next.d.mts +1 -1
  31. package/dist/next.d.ts +1 -1
  32. package/dist/next.js +3 -10
  33. package/dist/next.mjs +2 -5
  34. package/dist/{process-manager-ZCET3VD2.mjs → process-manager-JDUJDYGU.mjs} +1 -1
  35. package/dist/sandbox-HRGGTEHF.mjs +21 -0
  36. package/dist/{storage-FCSHTDLC.mjs → storage-LSDMRW73.mjs} +2 -2
  37. package/package.json +2 -6
  38. package/dist/chunk-4WDKWMVB.mjs +0 -389
  39. package/dist/chunk-64THY7Y7.mjs +0 -155
  40. package/dist/chunk-IACG26TC.mjs +0 -2212
  41. package/dist/chunk-NGLND33F.mjs +0 -1247
@@ -1,1247 +0,0 @@
1
- import {
2
- sandboxLifecycleWorkflow
3
- } from "./chunk-24UDM5XV.mjs";
4
- import {
5
- SandboxError,
6
- SandboxNotFoundError
7
- } from "./chunk-YRYXN7W4.mjs";
8
-
9
- // src/utils/debug.ts
10
- var enabled = process.env.AGENT_DEBUG === "1" || process.env.AGENT_DEBUG === "true";
11
- function debug(...args) {
12
- if (enabled) {
13
- console.log(...args);
14
- }
15
- }
16
-
17
- // src/sandbox/bindings/local.ts
18
- import { spawn } from "child_process";
19
- import * as fs from "fs/promises";
20
- import * as path2 from "path";
21
- import * as errore from "errore";
22
- import { ulid } from "ulid";
23
-
24
- // src/sandbox/write-files.ts
25
- import * as path from "path";
26
- var MAX_RETRIES = 2;
27
- var RETRY_BASE_MS = 500;
28
- async function execChecked(sandbox, opts, errorLabel) {
29
- for (let attempt = 0; ; attempt++) {
30
- const execResult = await sandbox.exec(opts);
31
- if (execResult instanceof Error) {
32
- throw execResult;
33
- }
34
- const result = await execResult.result;
35
- if (result.exitCode === 0) {
36
- return result;
37
- }
38
- const isTransient = result.exitCode === 255 && !result.stderr.trim();
39
- if (isTransient && attempt < MAX_RETRIES) {
40
- await new Promise((r) => setTimeout(r, RETRY_BASE_MS * (attempt + 1)));
41
- continue;
42
- }
43
- throw new Error(
44
- `${errorLabel} with exit code ${result.exitCode}: ${result.stderr}`
45
- );
46
- }
47
- }
48
- async function writeFiles(opts) {
49
- const { sandbox, files, destPath } = opts;
50
- if (files.length === 0) {
51
- return;
52
- }
53
- const filePaths = files.map((file) => path.posix.join(destPath, file.path));
54
- const parentDirs = Array.from(
55
- new Set(filePaths.map((p) => path.posix.dirname(p)))
56
- );
57
- const shellScripts = filePaths.filter((p) => p.endsWith(".sh"));
58
- const mkdirResult = await sandbox.exec({
59
- command: "mkdir",
60
- args: ["-p", ...parentDirs]
61
- });
62
- if (mkdirResult instanceof Error) {
63
- throw mkdirResult;
64
- }
65
- await mkdirResult.result;
66
- const CHUNK_SIZE = 5e4;
67
- for (let i = 0; i < files.length; i++) {
68
- const file = files[i];
69
- const fullPath = filePaths[i];
70
- const base64Content = toBase64(file.content);
71
- if (base64Content.length < CHUNK_SIZE) {
72
- const marker = `EOF_${i}`;
73
- await execChecked(
74
- sandbox,
75
- {
76
- command: "bash",
77
- args: [
78
- "-c",
79
- `base64 -d > ${quote(fullPath)} << '${marker}'
80
- ${base64Content}
81
- ${marker}`
82
- ]
83
- },
84
- "writeFiles failed"
85
- );
86
- } else {
87
- const tempB64 = `/tmp/chunk-${Date.now()}-${i}.b64`;
88
- const clearResult = await sandbox.exec({
89
- command: "bash",
90
- args: ["-c", `> ${quote(tempB64)}`]
91
- });
92
- if (clearResult instanceof Error) {
93
- throw clearResult;
94
- }
95
- await clearResult.result;
96
- for (let offset = 0; offset < base64Content.length; offset += CHUNK_SIZE) {
97
- const chunk = base64Content.slice(offset, offset + CHUNK_SIZE);
98
- const marker = `CHUNK_${offset}`;
99
- await execChecked(
100
- sandbox,
101
- {
102
- command: "bash",
103
- args: [
104
- "-c",
105
- `cat >> ${quote(tempB64)} << '${marker}'
106
- ${chunk}
107
- ${marker}`
108
- ]
109
- },
110
- "writeFiles chunk failed"
111
- );
112
- }
113
- await execChecked(
114
- sandbox,
115
- {
116
- command: "bash",
117
- args: [
118
- "-c",
119
- `base64 -d < ${quote(tempB64)} > ${quote(fullPath)} && rm -f ${quote(tempB64)}`
120
- ]
121
- },
122
- "writeFiles decode failed"
123
- );
124
- }
125
- }
126
- if (shellScripts.length > 0) {
127
- const chmodResult = await sandbox.exec({
128
- command: "chmod",
129
- args: ["+x", ...shellScripts]
130
- });
131
- if (chmodResult instanceof Error) {
132
- throw chmodResult;
133
- }
134
- await chmodResult.result;
135
- }
136
- }
137
- function toBase64(content) {
138
- if (typeof content === "string") {
139
- return Buffer.from(content).toString("base64");
140
- }
141
- return content.toString("base64");
142
- }
143
- function quote(s) {
144
- return `'${s.replace(/'/g, "'\\''")}'`;
145
- }
146
-
147
- // src/sandbox/bindings/local.ts
148
- var localSandbox = ({
149
- sandboxRecord,
150
- storage,
151
- setup,
152
- onRestart
153
- }) => {
154
- const config = sandboxRecord.config;
155
- const basePath = config.path ?? process.cwd();
156
- const processes = /* @__PURE__ */ new Map();
157
- const sandbox = {
158
- id: sandboxRecord.id,
159
- config: sandboxRecord.config,
160
- exec: ({ command, args, signal }) => {
161
- return errore.tryAsync({
162
- try: () => {
163
- const commandId = `command_${ulid()}`;
164
- const child = spawn(command, args, {
165
- cwd: basePath,
166
- signal
167
- });
168
- processes.set(commandId, child);
169
- let stdout = "";
170
- let stderr = "";
171
- const logQueue = [];
172
- let logResolve = null;
173
- let closed = false;
174
- child.stdout.on("data", (data) => {
175
- const str = String(data);
176
- stdout += str;
177
- logQueue.push({ stream: "stdout", data: str });
178
- logResolve?.();
179
- });
180
- child.stderr.on("data", (data) => {
181
- const str = String(data);
182
- stderr += str;
183
- logQueue.push({ stream: "stderr", data: str });
184
- logResolve?.();
185
- });
186
- const result2 = new Promise((resolve, reject) => {
187
- child.on("error", (err) => {
188
- processes.delete(commandId);
189
- closed = true;
190
- logResolve?.();
191
- reject(err);
192
- });
193
- child.on("close", (code) => {
194
- processes.delete(commandId);
195
- closed = true;
196
- logResolve?.();
197
- resolve({ stdout, stderr, exitCode: code ?? 0 });
198
- });
199
- });
200
- async function* logs() {
201
- while (!closed || logQueue.length > 0) {
202
- const entry = logQueue.shift();
203
- if (entry) {
204
- yield entry;
205
- } else if (!closed) {
206
- await new Promise((resolve) => {
207
- logResolve = resolve;
208
- });
209
- logResolve = null;
210
- }
211
- }
212
- }
213
- return Promise.resolve({ commandId, logs, result: result2 });
214
- },
215
- catch: (e) => new SandboxError({ reason: String(e), cause: e })
216
- });
217
- },
218
- getDomain: (port) => {
219
- return Promise.resolve(`http://localhost:${port}`);
220
- },
221
- kill: async ({ commandId, storage: storage2 }) => {
222
- const child = processes.get(commandId);
223
- if (!child) {
224
- return new SandboxError({
225
- reason: `Command ${commandId} not found or already finished`
226
- });
227
- }
228
- child.kill("SIGTERM");
229
- const cmd = await storage2.command.get(commandId);
230
- if (cmd instanceof Error) {
231
- return new SandboxError({ reason: cmd.message, cause: cmd });
232
- }
233
- if (cmd && cmd.status === "running") {
234
- const result2 = await storage2.command.set({
235
- ...cmd,
236
- status: "killed"
237
- });
238
- if (result2 instanceof Error) {
239
- return new SandboxError({ reason: result2.message, cause: result2 });
240
- }
241
- }
242
- },
243
- readFile: async ({ path: filePath }) => {
244
- const fullPath = path2.join(basePath, filePath);
245
- try {
246
- return await fs.readFile(fullPath);
247
- } catch (e) {
248
- if (e instanceof Error && "code" in e && e.code === "ENOENT") {
249
- return null;
250
- }
251
- return new SandboxError({ reason: String(e), cause: e });
252
- }
253
- },
254
- writeFiles: (opts) => writeFiles({ sandbox, ...opts }),
255
- updateNetworkPolicy: () => Promise.resolve(
256
- new SandboxError({
257
- reason: "updateNetworkPolicy is only available for Vercel sandboxes"
258
- })
259
- ),
260
- tag: {
261
- list: async () => {
262
- const sandboxRecord2 = await storage.sandbox.get(sandbox.id);
263
- if (sandboxRecord2 instanceof Error) {
264
- return sandboxRecord2;
265
- }
266
- return sandboxRecord2.tags ?? {};
267
- },
268
- get: async (key) => {
269
- const sandboxRecord2 = await storage.sandbox.get(sandbox.id);
270
- if (sandboxRecord2 instanceof Error) {
271
- return sandboxRecord2;
272
- }
273
- return sandboxRecord2.tags?.[key];
274
- },
275
- set: async (key, value) => {
276
- const result2 = await storage.sandbox.tag.set({
277
- sandboxId: sandbox.id,
278
- tags: { [key]: value }
279
- });
280
- if (result2 instanceof Error) {
281
- return result2;
282
- }
283
- return void 0;
284
- },
285
- setMany: async (tags) => {
286
- const result2 = await storage.sandbox.tag.set({
287
- sandboxId: sandbox.id,
288
- tags
289
- });
290
- if (result2 instanceof Error) {
291
- return result2;
292
- }
293
- return void 0;
294
- }
295
- }
296
- };
297
- const result = sandbox;
298
- if (setup || onRestart) {
299
- let resolveSetupMeta;
300
- result._setupMeta = new Promise((r) => {
301
- resolveSetupMeta = r;
302
- });
303
- result._onReady = (async () => {
304
- let needsSetupRun = !!setup;
305
- if (setup) {
306
- const existing = await storage.setup.get(setup.key);
307
- if (!(existing instanceof Error) && existing) {
308
- debug(
309
- `[sandbox:setup] setup already complete for key "${setup.key}", skipping`
310
- );
311
- needsSetupRun = false;
312
- }
313
- }
314
- resolveSetupMeta({
315
- needsSetupRun,
316
- createdFromSnapshot: false
317
- });
318
- if (needsSetupRun && setup) {
319
- debug(`[sandbox:setup] running setup.run (local, key="${setup.key}")`);
320
- await setup.run(sandbox);
321
- await storage.setup.set({
322
- key: setup.key,
323
- snapshotId: null,
324
- createdAt: Date.now(),
325
- lastUsedAt: null,
326
- acquiringLockId: null,
327
- acquiringLockAt: null
328
- });
329
- debug(
330
- `[sandbox:setup] setup complete, stored record (key="${setup.key}")`
331
- );
332
- }
333
- if (onRestart) {
334
- debug("[sandbox:setup] running onRestart (local)");
335
- await onRestart(sandbox);
336
- }
337
- })();
338
- }
339
- return result;
340
- };
341
-
342
- // src/sandbox/bindings/vercel.ts
343
- import * as path3 from "path";
344
- import { Sandbox as VercelSandboxSDK } from "@vercel/sandbox";
345
- import * as errore2 from "errore";
346
- import { start } from "workflow/api";
347
- var VERCEL_MAX_TIMEOUT_MS = 5 * 60 * 60 * 1e3;
348
- var LOCK_TIMEOUT_MS = 5 * 60 * 1e3;
349
- var LOCK_POLL_INTERVAL_MS = 200;
350
- var getTestCredentials = () => process.env.NODE_ENV === "test" ? {
351
- token: process.env.TEST_VERCEL_TOKEN,
352
- teamId: process.env.TEST_VERCEL_TEAM_ID,
353
- projectId: process.env.TEST_VERCEL_PROJECT_ID
354
- } : {};
355
- var createPromises = /* @__PURE__ */ new Map();
356
- var ACTIVITY_THROTTLE_MS = 1e4;
357
- var lastActivitySent = /* @__PURE__ */ new Map();
358
- var DEFAULT_VCPUS = 2;
359
- function isSandboxGoneError(e) {
360
- if (!(e instanceof Error)) {
361
- return false;
362
- }
363
- const errorWithResponse = e;
364
- const errorWithCause = e;
365
- const status = errorWithResponse.response?.status ?? errorWithCause.cause?.response?.status;
366
- if (status === 410 || status === 422) {
367
- return true;
368
- }
369
- const message = e.message || String(e);
370
- if (message.includes("Expected a stream of command data") || message.includes("Expected a stream of logs")) {
371
- return true;
372
- }
373
- return false;
374
- }
375
- var vercelSandbox = ({
376
- sandboxRecord,
377
- storageConfig,
378
- enableLifecycleWorkflow,
379
- storage,
380
- rpc,
381
- setup,
382
- onRestart
383
- }) => {
384
- const { id, config } = sandboxRecord;
385
- const vcpus = config.resources?.vcpus ?? DEFAULT_VCPUS;
386
- const ports = config.ports;
387
- const networkPolicy = config.networkPolicy;
388
- const initialVercel = sandboxRecord.providerMetadata?.provider === "vercel" ? sandboxRecord.providerMetadata : null;
389
- let sandboxPromise = null;
390
- let recoveredFromStale = false;
391
- let createdFromSnapshot = false;
392
- let needsSetupRun = false;
393
- const HOME_DIR = "/home/vercel-sandbox";
394
- async function pollForSandboxId() {
395
- const deadline = Date.now() + LOCK_TIMEOUT_MS;
396
- while (Date.now() < deadline) {
397
- await new Promise((r) => setTimeout(r, LOCK_POLL_INTERVAL_MS));
398
- const record = await storage.sandbox.get(id);
399
- if (record instanceof Error) {
400
- return new SandboxError({ reason: record.message, cause: record });
401
- }
402
- const vercelSandboxId = record?.providerMetadata?.provider === "vercel" ? record.providerMetadata.sandboxId : null;
403
- if (vercelSandboxId) {
404
- return vercelSandboxId;
405
- }
406
- if (!record?.acquiringLockAt) {
407
- const finalCheck = await storage.sandbox.get(id);
408
- if (finalCheck instanceof Error) {
409
- return new SandboxError({
410
- reason: finalCheck.message,
411
- cause: finalCheck
412
- });
413
- }
414
- const finalVercelSandboxId = finalCheck?.providerMetadata?.provider === "vercel" ? finalCheck.providerMetadata.sandboxId : null;
415
- if (finalVercelSandboxId) {
416
- return finalVercelSandboxId;
417
- }
418
- return doGetOrCreateSandboxId();
419
- }
420
- }
421
- return new SandboxError({
422
- reason: "Timed out waiting for sandbox creation by another process"
423
- });
424
- }
425
- async function startLifecycleWorkflow(vercelSandboxId) {
426
- if (!enableLifecycleWorkflow) {
427
- return;
428
- }
429
- const lifecycleInput = {
430
- id,
431
- vercelSandboxId,
432
- storageConfig,
433
- rpc
434
- };
435
- await start(sandboxLifecycleWorkflow, [{ input: lifecycleInput }]).catch(
436
- // biome-ignore lint/suspicious/noEmptyBlockStatements: intentionally ignored - workflow start is fire-and-forget
437
- () => {
438
- }
439
- );
440
- }
441
- async function createSandboxFromSnapshot(snapshotId) {
442
- return await errore2.tryAsync({
443
- try: async () => {
444
- const sandbox2 = await VercelSandboxSDK.create({
445
- source: { type: "snapshot", snapshotId },
446
- resources: { vcpus },
447
- timeout: VERCEL_MAX_TIMEOUT_MS,
448
- ports,
449
- networkPolicy,
450
- ...getTestCredentials()
451
- });
452
- const now = Date.now();
453
- await storage.sandbox.set({
454
- id,
455
- config,
456
- tags: sandboxRecord.tags,
457
- createdAt: now,
458
- lastActivityAt: now,
459
- acquiringLockId: null,
460
- acquiringLockAt: null,
461
- providerMetadata: {
462
- provider: "vercel",
463
- sandboxId: sandbox2.sandboxId,
464
- snapshotId
465
- }
466
- });
467
- await startLifecycleWorkflow(sandbox2.sandboxId);
468
- return sandbox2.sandboxId;
469
- },
470
- catch: (e) => new SandboxError({ reason: String(e), cause: e })
471
- });
472
- }
473
- async function createFreshSandbox() {
474
- return await errore2.tryAsync({
475
- try: async () => {
476
- const sandbox2 = await VercelSandboxSDK.create({
477
- resources: { vcpus },
478
- timeout: VERCEL_MAX_TIMEOUT_MS,
479
- ports,
480
- networkPolicy,
481
- ...getTestCredentials()
482
- });
483
- const now = Date.now();
484
- await storage.sandbox.set({
485
- id,
486
- config,
487
- tags: sandboxRecord.tags,
488
- createdAt: now,
489
- lastActivityAt: now,
490
- acquiringLockId: null,
491
- acquiringLockAt: null,
492
- providerMetadata: {
493
- provider: "vercel",
494
- sandboxId: sandbox2.sandboxId,
495
- snapshotId: null
496
- }
497
- });
498
- await startLifecycleWorkflow(sandbox2.sandboxId);
499
- return sandbox2.sandboxId;
500
- },
501
- catch: (e) => new SandboxError({ reason: String(e), cause: e })
502
- });
503
- }
504
- function execOnInstance(instance, {
505
- command,
506
- args,
507
- signal
508
- }) {
509
- return errore2.tryAsync({
510
- try: async () => {
511
- const output = await instance.runCommand({
512
- cwd: HOME_DIR,
513
- args,
514
- cmd: command,
515
- signal,
516
- detached: true
517
- });
518
- let stdout = "";
519
- let stderr = "";
520
- const logBuffer = [];
521
- const state = {
522
- resolve: null,
523
- consumed: false
524
- };
525
- const consumeLogs = (async () => {
526
- try {
527
- for await (const log of output.logs()) {
528
- const entry = log.stream === "stdout" ? { stream: "stdout", data: log.data } : { stream: "stderr", data: log.data };
529
- if (log.stream === "stdout") {
530
- stdout += log.data;
531
- } else {
532
- stderr += log.data;
533
- }
534
- logBuffer.push(entry);
535
- state.resolve?.();
536
- }
537
- } catch {
538
- }
539
- state.consumed = true;
540
- state.resolve?.();
541
- })();
542
- async function* logs() {
543
- let index = 0;
544
- while (!state.consumed || index < logBuffer.length) {
545
- if (index < logBuffer.length) {
546
- yield logBuffer[index++];
547
- } else {
548
- await new Promise((resolve) => {
549
- state.resolve = resolve;
550
- });
551
- state.resolve = null;
552
- }
553
- }
554
- }
555
- const result = consumeLogs.then(async () => {
556
- try {
557
- const finished = await output.wait();
558
- return {
559
- stdout,
560
- stderr,
561
- exitCode: finished.exitCode
562
- };
563
- } catch (e) {
564
- if (isSandboxGoneError(e)) {
565
- return { stdout, stderr, exitCode: 1 };
566
- }
567
- throw e;
568
- }
569
- });
570
- return { commandId: output.cmdId, logs, result };
571
- },
572
- catch: (e) => new SandboxError({ reason: String(e), cause: e })
573
- });
574
- }
575
- function readFileOnInstance(instance, { path: path4 }) {
576
- return errore2.tryAsync({
577
- try: () => instance.readFileToBuffer({ path: path4, cwd: HOME_DIR }),
578
- catch: (e) => new SandboxError({ reason: String(e), cause: e })
579
- });
580
- }
581
- async function writeFilesOnInstance(instance, opts) {
582
- const { files, destPath } = opts;
583
- if (files.length === 0) {
584
- return;
585
- }
586
- const nativeFiles = files.map((file) => {
587
- const filePath = path3.posix.join(destPath, file.path);
588
- const absolutePath = path3.posix.isAbsolute(filePath) ? filePath : path3.posix.join(HOME_DIR, filePath);
589
- return {
590
- path: absolutePath,
591
- content: typeof file.content === "string" ? Buffer.from(file.content) : file.content
592
- };
593
- });
594
- await instance.writeFiles(nativeFiles);
595
- const shellScripts = nativeFiles.filter((f) => f.path.endsWith(".sh"));
596
- if (shellScripts.length > 0) {
597
- const chmodResult = await execOnInstance(instance, {
598
- command: "chmod",
599
- args: ["+x", ...shellScripts.map((f) => f.path)]
600
- });
601
- if (chmodResult instanceof Error) {
602
- throw chmodResult;
603
- }
604
- await chmodResult.result;
605
- }
606
- }
607
- function createTempSandbox(instance) {
608
- const tempSandbox = {
609
- id: `__setup_temp_${Date.now()}`,
610
- config,
611
- exec: (opts) => execOnInstance(instance, opts),
612
- readFile: (opts) => readFileOnInstance(instance, opts),
613
- getDomain: () => Promise.resolve(
614
- new SandboxError({ reason: "not available during setup" })
615
- ),
616
- kill: () => Promise.resolve(
617
- new SandboxError({ reason: "not available during setup" })
618
- ),
619
- writeFiles: (opts) => writeFilesOnInstance(instance, opts),
620
- updateNetworkPolicy: (policy) => errore2.tryAsync({
621
- try: () => instance.updateNetworkPolicy(policy),
622
- catch: (e) => new SandboxError({ reason: String(e), cause: e })
623
- }),
624
- tag: {
625
- list: async () => ({}),
626
- get: async () => void 0,
627
- set: async () => void 0,
628
- setMany: async () => void 0
629
- }
630
- };
631
- return tempSandbox;
632
- }
633
- async function pollForSetupSnapshot(key) {
634
- const deadline = Date.now() + LOCK_TIMEOUT_MS;
635
- while (Date.now() < deadline) {
636
- await new Promise((r) => setTimeout(r, LOCK_POLL_INTERVAL_MS));
637
- const record = await storage.setup.get(key);
638
- if (record instanceof Error) {
639
- return null;
640
- }
641
- if (record?.snapshotId) {
642
- return record.snapshotId;
643
- }
644
- if (!record?.acquiringLockId) {
645
- return null;
646
- }
647
- }
648
- return null;
649
- }
650
- async function createSetupSnapshot(opts) {
651
- if (!setup) {
652
- return;
653
- }
654
- const setupKey = setup.key;
655
- if (!opts?.force) {
656
- const existing = await storage.setup.get(setupKey);
657
- if (!(existing instanceof Error) && existing?.snapshotId) {
658
- return;
659
- }
660
- }
661
- debug(`[sandbox:setup] acquiring lock for setup key "${setupKey}"`);
662
- const lockId = crypto.randomUUID();
663
- const locked = await storage.setup.acquireLock(
664
- setupKey,
665
- lockId,
666
- LOCK_TIMEOUT_MS
667
- );
668
- if (locked instanceof Error || !locked) {
669
- debug(
670
- `[sandbox:setup] lock not acquired for key "${setupKey}" (another process holds it)`
671
- );
672
- return;
673
- }
674
- if (!opts?.force && locked.snapshotId) {
675
- debug(
676
- `[sandbox:setup] snapshot already exists after lock for key "${setupKey}", skipping`
677
- );
678
- return;
679
- }
680
- let tempInstance = null;
681
- try {
682
- debug(
683
- `[sandbox:setup] creating temp sandbox for snapshot (key="${setupKey}")`
684
- );
685
- tempInstance = await VercelSandboxSDK.create({
686
- resources: { vcpus },
687
- timeout: VERCEL_MAX_TIMEOUT_MS,
688
- ports,
689
- networkPolicy,
690
- ...getTestCredentials()
691
- });
692
- const tempSandbox = createTempSandbox(
693
- tempInstance
694
- );
695
- await setup.run(tempSandbox);
696
- debug(
697
- `[sandbox:setup] setup.run complete, snapshotting (key="${setupKey}")`
698
- );
699
- const snapshot = await tempInstance.snapshot();
700
- await storage.setup.set({
701
- key: setupKey,
702
- snapshotId: snapshot.snapshotId,
703
- createdAt: locked.createdAt,
704
- lastUsedAt: null,
705
- acquiringLockId: null,
706
- acquiringLockAt: null
707
- });
708
- debug(
709
- `[sandbox:setup] snapshot stored: ${snapshot.snapshotId} (key="${setupKey}")`
710
- );
711
- await tempInstance.stop().catch(() => void 0);
712
- } catch (e) {
713
- console.error(
714
- `[sandbox:setup] failed to create setup snapshot (key="${setupKey}"):`,
715
- e
716
- );
717
- if (tempInstance) {
718
- await tempInstance.stop().catch(() => void 0);
719
- }
720
- await storage.setup.set({
721
- key: setupKey,
722
- snapshotId: null,
723
- createdAt: locked.createdAt,
724
- lastUsedAt: null,
725
- acquiringLockId: null,
726
- acquiringLockAt: null
727
- }).catch(() => void 0);
728
- }
729
- }
730
- async function doGetOrCreateSandboxId() {
731
- if (initialVercel?.sandboxId && !recoveredFromStale) {
732
- return initialVercel.sandboxId;
733
- }
734
- const existing = await storage.sandbox.get(id);
735
- if (existing instanceof Error) {
736
- if (existing instanceof SandboxNotFoundError) {
737
- } else {
738
- return new SandboxError({ reason: existing.message, cause: existing });
739
- }
740
- }
741
- const existingRecord = existing instanceof SandboxNotFoundError ? null : existing;
742
- const existingVercel = existingRecord?.providerMetadata?.provider === "vercel" ? existingRecord.providerMetadata : null;
743
- if (existingVercel?.sandboxId) {
744
- return existingVercel.sandboxId;
745
- }
746
- const hasActiveLock = existingRecord?.acquiringLockId && existingRecord.acquiringLockAt && Date.now() - existingRecord.acquiringLockAt < LOCK_TIMEOUT_MS;
747
- if (hasActiveLock) {
748
- return pollForSandboxId();
749
- }
750
- const lockId = crypto.randomUUID();
751
- const now = Date.now();
752
- const locked = await storage.sandbox.acquireLock(
753
- {
754
- id,
755
- config,
756
- tags: existingRecord?.tags ?? sandboxRecord.tags,
757
- createdAt: existingRecord?.createdAt ?? sandboxRecord.createdAt,
758
- lastActivityAt: existingRecord?.lastActivityAt ?? sandboxRecord.lastActivityAt,
759
- acquiringLockId: lockId,
760
- acquiringLockAt: now,
761
- providerMetadata: {
762
- provider: "vercel",
763
- sandboxId: null,
764
- snapshotId: existingVercel?.snapshotId ?? initialVercel?.snapshotId ?? null
765
- }
766
- },
767
- LOCK_TIMEOUT_MS
768
- );
769
- if (locked instanceof Error) {
770
- return new SandboxError({ reason: locked.message, cause: locked });
771
- }
772
- if (!locked) {
773
- return pollForSandboxId();
774
- }
775
- const lockedRecord = locked;
776
- async function releaseSandboxLock() {
777
- await storage.sandbox.update({
778
- id: lockedRecord.id,
779
- acquiringLockId: null,
780
- acquiringLockAt: null
781
- }).catch(() => void 0);
782
- }
783
- const lockedVercel = lockedRecord.providerMetadata?.provider === "vercel" ? lockedRecord.providerMetadata : null;
784
- if (lockedVercel?.sandboxId) {
785
- await releaseSandboxLock();
786
- return lockedVercel.sandboxId;
787
- }
788
- const snapshotId = lockedVercel?.snapshotId ?? initialVercel?.snapshotId ?? config.lifecycle?.snapshotId;
789
- if (snapshotId) {
790
- const result = await createSandboxFromSnapshot(snapshotId);
791
- if (!(result instanceof Error)) {
792
- createdFromSnapshot = true;
793
- return result;
794
- }
795
- }
796
- if (setup) {
797
- let forceRecreateSnapshot = false;
798
- const setupRecord = await storage.setup.get(setup.key);
799
- if (!(setupRecord instanceof Error) && setupRecord) {
800
- if (setupRecord.snapshotId) {
801
- debug(
802
- `[sandbox:setup] found setup snapshot ${setupRecord.snapshotId} for key "${setup.key}"`
803
- );
804
- const result = await createSandboxFromSnapshot(
805
- setupRecord.snapshotId
806
- );
807
- if (!(result instanceof Error)) {
808
- createdFromSnapshot = true;
809
- storage.setup.set({
810
- ...setupRecord,
811
- lastUsedAt: Date.now()
812
- }).catch(() => void 0);
813
- return result;
814
- }
815
- debug(
816
- `[sandbox:setup] snapshot ${setupRecord.snapshotId} failed (expired?), will recreate`
817
- );
818
- forceRecreateSnapshot = true;
819
- } else if (setupRecord.acquiringLockId && setupRecord.acquiringLockAt && Date.now() - setupRecord.acquiringLockAt < LOCK_TIMEOUT_MS) {
820
- debug(
821
- `[sandbox:setup] snapshot in progress for key "${setup.key}", waiting...`
822
- );
823
- const snapshotId2 = await pollForSetupSnapshot(setup.key);
824
- if (snapshotId2) {
825
- debug(
826
- `[sandbox:setup] snapshot ready: ${snapshotId2} for key "${setup.key}"`
827
- );
828
- const result = await createSandboxFromSnapshot(snapshotId2);
829
- if (!(result instanceof Error)) {
830
- createdFromSnapshot = true;
831
- return result;
832
- }
833
- }
834
- }
835
- }
836
- debug(
837
- `[sandbox:setup] no snapshot for key "${setup.key}", will run setup on this sandbox`
838
- );
839
- needsSetupRun = true;
840
- createSetupSnapshot({ force: forceRecreateSnapshot }).catch((e) => {
841
- console.error(
842
- "[sandbox:setup] failed to create background snapshot:",
843
- e
844
- );
845
- });
846
- }
847
- const freshResult = await createFreshSandbox();
848
- if (freshResult instanceof Error) {
849
- await releaseSandboxLock();
850
- }
851
- return freshResult;
852
- }
853
- function getOrCreateSandboxId() {
854
- const cached = createPromises.get(id);
855
- if (cached) {
856
- return cached;
857
- }
858
- const promise = doGetOrCreateSandboxId().finally(() => {
859
- createPromises.delete(id);
860
- });
861
- createPromises.set(id, promise);
862
- return promise;
863
- }
864
- async function doGetSandbox() {
865
- const vercelSandboxId = await getOrCreateSandboxId();
866
- if (vercelSandboxId instanceof Error) {
867
- return vercelSandboxId;
868
- }
869
- return errore2.tryAsync({
870
- try: () => VercelSandboxSDK.get({
871
- sandboxId: vercelSandboxId,
872
- ...getTestCredentials()
873
- }),
874
- catch: (e) => new SandboxError({ reason: String(e), cause: e })
875
- });
876
- }
877
- function getSandbox2() {
878
- if (!sandboxPromise) {
879
- sandboxPromise = doGetSandbox();
880
- }
881
- return sandboxPromise;
882
- }
883
- async function recoverFromStaleSandbox() {
884
- sandboxPromise = null;
885
- recoveredFromStale = true;
886
- const existing = await storage.sandbox.get(id);
887
- if (existing instanceof Error || !existing) {
888
- return;
889
- }
890
- const existingVercel = existing.providerMetadata?.provider === "vercel" ? existing.providerMetadata : null;
891
- if (existingVercel?.sandboxId) {
892
- await storage.sandbox.update({
893
- id: existing.id,
894
- acquiringLockId: null,
895
- acquiringLockAt: null,
896
- providerMetadata: {
897
- provider: "vercel",
898
- sandboxId: null,
899
- snapshotId: existingVercel.snapshotId
900
- }
901
- });
902
- }
903
- }
904
- async function updateLastActivity() {
905
- const now = Date.now();
906
- const lastSent = lastActivitySent.get(id);
907
- if (lastSent && now - lastSent < ACTIVITY_THROTTLE_MS) {
908
- return;
909
- }
910
- lastActivitySent.set(id, now);
911
- const existing = await storage.sandbox.get(id);
912
- if (existing instanceof Error || !existing) {
913
- return;
914
- }
915
- const existingVercel = existing.providerMetadata?.provider === "vercel" ? existing.providerMetadata : null;
916
- await storage.sandbox.update({
917
- id: existing.id,
918
- lastActivityAt: now,
919
- acquiringLockId: null,
920
- acquiringLockAt: null,
921
- providerMetadata: existingVercel ?? {
922
- provider: "vercel",
923
- sandboxId: null,
924
- snapshotId: null
925
- }
926
- });
927
- }
928
- const lifecycle = {
929
- start: async () => {
930
- const sandbox2 = await getSandbox2();
931
- if (sandbox2 instanceof Error) {
932
- return sandbox2;
933
- }
934
- await updateLastActivity();
935
- return sandbox2.status;
936
- },
937
- snapshot: async () => {
938
- const sandbox2 = await getSandbox2();
939
- if (sandbox2 instanceof Error) {
940
- return sandbox2;
941
- }
942
- return errore2.tryAsync({
943
- try: async () => {
944
- const snapshot = await sandbox2.snapshot();
945
- await storage.sandbox.update({
946
- id,
947
- acquiringLockId: null,
948
- acquiringLockAt: null,
949
- providerMetadata: {
950
- provider: "vercel",
951
- sandboxId: null,
952
- snapshotId: snapshot.snapshotId
953
- }
954
- });
955
- return { snapshotId: snapshot.snapshotId };
956
- },
957
- catch: (e) => new SandboxError({ reason: String(e), cause: e })
958
- });
959
- },
960
- stop: async () => {
961
- const sandbox2 = await getSandbox2();
962
- if (sandbox2 instanceof Error) {
963
- return sandbox2;
964
- }
965
- return errore2.tryAsync({
966
- try: async () => {
967
- await sandbox2.stop();
968
- await storage.sandbox.update({
969
- id,
970
- acquiringLockId: null,
971
- acquiringLockAt: null,
972
- providerMetadata: {
973
- provider: "vercel",
974
- sandboxId: null,
975
- snapshotId: null
976
- }
977
- });
978
- return void 0;
979
- },
980
- catch: (e) => new SandboxError({ reason: String(e), cause: e })
981
- });
982
- },
983
- getStatus: async () => {
984
- const sandbox2 = await getSandbox2();
985
- if (sandbox2 instanceof Error) {
986
- return sandbox2;
987
- }
988
- return sandbox2.status;
989
- },
990
- getCreatedAt: async () => {
991
- const sandbox2 = await getSandbox2();
992
- if (sandbox2 instanceof Error) {
993
- return sandbox2;
994
- }
995
- return sandbox2.createdAt;
996
- },
997
- getRemainingTimeout: async () => {
998
- const sandbox2 = await getSandbox2();
999
- if (sandbox2 instanceof Error) {
1000
- return sandbox2;
1001
- }
1002
- return sandbox2.timeout;
1003
- }
1004
- };
1005
- async function doExec(opts) {
1006
- const instance = await getSandbox2();
1007
- if (instance instanceof Error) {
1008
- return instance;
1009
- }
1010
- const updatePromise = updateLastActivity();
1011
- const execResult = await execOnInstance(instance, opts);
1012
- await updatePromise;
1013
- return execResult;
1014
- }
1015
- const sandbox = {
1016
- id,
1017
- config,
1018
- exec: async (opts) => {
1019
- const result = await doExec(opts);
1020
- if (result instanceof SandboxError && isSandboxGoneError(result.cause)) {
1021
- await recoverFromStaleSandbox();
1022
- return await doExec(opts);
1023
- }
1024
- return result;
1025
- },
1026
- getDomain: async (port) => {
1027
- const sandbox2 = await getSandbox2();
1028
- if (sandbox2 instanceof Error) {
1029
- return sandbox2;
1030
- }
1031
- try {
1032
- return sandbox2.domain(port);
1033
- } catch (e) {
1034
- return new SandboxError({ reason: String(e), cause: e });
1035
- }
1036
- },
1037
- kill: async ({ commandId, storage: cmdStorage }) => {
1038
- const instance = await getSandbox2();
1039
- if (instance instanceof Error) {
1040
- return instance;
1041
- }
1042
- const cmd = await cmdStorage.command.get(commandId);
1043
- if (cmd instanceof Error) {
1044
- return new SandboxError({ reason: cmd.message, cause: cmd });
1045
- }
1046
- if (cmd && cmd.status === "running") {
1047
- const result = await cmdStorage.command.set({
1048
- ...cmd,
1049
- status: "killed"
1050
- });
1051
- if (result instanceof Error) {
1052
- return new SandboxError({ reason: result.message, cause: result });
1053
- }
1054
- }
1055
- return void 0;
1056
- },
1057
- readFile: async (opts) => {
1058
- const instance = await getSandbox2();
1059
- if (instance instanceof Error) {
1060
- return instance;
1061
- }
1062
- return readFileOnInstance(instance, opts);
1063
- },
1064
- writeFiles: async (opts) => {
1065
- const instance = await getSandbox2();
1066
- if (instance instanceof Error) {
1067
- throw instance;
1068
- }
1069
- return writeFilesOnInstance(instance, opts);
1070
- },
1071
- lifecycle,
1072
- updateNetworkPolicy: async (policy) => {
1073
- const instance = await getSandbox2();
1074
- if (instance instanceof Error) {
1075
- return instance;
1076
- }
1077
- return errore2.tryAsync({
1078
- try: () => instance.updateNetworkPolicy(policy),
1079
- catch: (e) => new SandboxError({ reason: String(e), cause: e })
1080
- });
1081
- },
1082
- tag: {
1083
- list: async () => {
1084
- const sandboxRecord2 = await storage.sandbox.get(id);
1085
- if (sandboxRecord2 instanceof Error) {
1086
- return sandboxRecord2;
1087
- }
1088
- return sandboxRecord2.tags ?? {};
1089
- },
1090
- get: async (key) => {
1091
- const sandboxRecord2 = await storage.sandbox.get(id);
1092
- if (sandboxRecord2 instanceof Error) {
1093
- return sandboxRecord2;
1094
- }
1095
- return sandboxRecord2.tags?.[key];
1096
- },
1097
- set: async (key, value) => {
1098
- const result = await storage.sandbox.tag.set({
1099
- sandboxId: id,
1100
- tags: { [key]: value }
1101
- });
1102
- if (result instanceof Error) {
1103
- return result;
1104
- }
1105
- return void 0;
1106
- },
1107
- setMany: async (tags) => {
1108
- const result = await storage.sandbox.tag.set({
1109
- sandboxId: id,
1110
- tags
1111
- });
1112
- if (result instanceof Error) {
1113
- return result;
1114
- }
1115
- return void 0;
1116
- }
1117
- }
1118
- };
1119
- let onReadyPromise = Promise.resolve();
1120
- let setupMetaPromise = Promise.resolve({
1121
- needsSetupRun: false,
1122
- createdFromSnapshot: false
1123
- });
1124
- if (config.lifecycle?.autoStart !== false) {
1125
- sandboxPromise = doGetSandbox();
1126
- setupMetaPromise = sandboxPromise.then(() => ({
1127
- needsSetupRun,
1128
- createdFromSnapshot
1129
- }));
1130
- onReadyPromise = sandboxPromise.then(async (instance) => {
1131
- if (instance instanceof Error) {
1132
- return;
1133
- }
1134
- if (needsSetupRun && setup) {
1135
- debug(
1136
- `[sandbox:setup] running setup.run on session sandbox (key="${setup.key}")`
1137
- );
1138
- await setup.run(sandbox);
1139
- debug("[sandbox:setup] setup.run complete on session sandbox");
1140
- }
1141
- if (createdFromSnapshot && onRestart) {
1142
- debug("[sandbox:setup] running onRestart (created from snapshot)");
1143
- await onRestart(sandbox);
1144
- }
1145
- });
1146
- }
1147
- sandbox._onReady = onReadyPromise;
1148
- sandbox._setupMeta = setupMetaPromise;
1149
- return sandbox;
1150
- };
1151
-
1152
- // src/sandbox/client.ts
1153
- var sandboxCache = /* @__PURE__ */ new Map();
1154
- function getSandbox({
1155
- sandboxRecord,
1156
- storageConfig,
1157
- storage,
1158
- rpc,
1159
- enableLifecycleWorkflow = true,
1160
- setup,
1161
- onRestart
1162
- }) {
1163
- const cached = sandboxCache.get(sandboxRecord.id);
1164
- if (cached) {
1165
- debug("[getSandbox] cache hit for", sandboxRecord.id);
1166
- return cached;
1167
- }
1168
- const sbx = createSandbox({
1169
- sandboxRecord,
1170
- storageConfig,
1171
- storage,
1172
- rpc,
1173
- enableLifecycleWorkflow,
1174
- setup,
1175
- onRestart
1176
- });
1177
- sandboxCache.set(sandboxRecord.id, sbx);
1178
- return sbx;
1179
- }
1180
- function createSandbox({
1181
- sandboxRecord,
1182
- storageConfig,
1183
- storage,
1184
- rpc,
1185
- enableLifecycleWorkflow = true,
1186
- setup,
1187
- onRestart
1188
- }) {
1189
- let sbx;
1190
- switch (sandboxRecord.config.type) {
1191
- case "local":
1192
- sbx = localSandbox({
1193
- sandboxRecord,
1194
- storage,
1195
- setup,
1196
- onRestart
1197
- });
1198
- break;
1199
- case "vercel":
1200
- sbx = vercelSandbox({
1201
- sandboxRecord,
1202
- storageConfig,
1203
- storage,
1204
- rpc,
1205
- enableLifecycleWorkflow,
1206
- setup,
1207
- onRestart
1208
- });
1209
- break;
1210
- case "custom":
1211
- throw new Error("Custom sandboxes are not supported");
1212
- default:
1213
- sandboxRecord.config;
1214
- throw new Error(
1215
- `Unknown sandbox type: ${// biome-ignore lint/suspicious/noExplicitAny: .
1216
- sandboxRecord.config.type}`
1217
- );
1218
- }
1219
- if (!sbx._onReady) {
1220
- return sbx;
1221
- }
1222
- const onReady = sbx._onReady;
1223
- return {
1224
- ...sbx,
1225
- exec: async (opts) => {
1226
- await onReady;
1227
- return sbx.exec(opts);
1228
- },
1229
- getDomain: async (port) => {
1230
- await onReady;
1231
- return sbx.getDomain(port);
1232
- },
1233
- readFile: async (opts) => {
1234
- await onReady;
1235
- return sbx.readFile(opts);
1236
- },
1237
- writeFiles: async (opts) => {
1238
- await onReady;
1239
- return sbx.writeFiles(opts);
1240
- }
1241
- };
1242
- }
1243
-
1244
- export {
1245
- getSandbox
1246
- };
1247
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL3V0aWxzL2RlYnVnLnRzIiwgIi4uL3NyYy9zYW5kYm94L2JpbmRpbmdzL2xvY2FsLnRzIiwgIi4uL3NyYy9zYW5kYm94L3dyaXRlLWZpbGVzLnRzIiwgIi4uL3NyYy9zYW5kYm94L2JpbmRpbmdzL3ZlcmNlbC50cyIsICIuLi9zcmMvc2FuZGJveC9jbGllbnQudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IGVuYWJsZWQgPVxuICBwcm9jZXNzLmVudi5BR0VOVF9ERUJVRyA9PT0gXCIxXCIgfHwgcHJvY2Vzcy5lbnYuQUdFTlRfREVCVUcgPT09IFwidHJ1ZVwiO1xuXG5leHBvcnQgZnVuY3Rpb24gZGVidWcoLi4uYXJnczogdW5rbm93bltdKSB7XG4gIGlmIChlbmFibGVkKSB7XG4gICAgY29uc29sZS5sb2coLi4uYXJncyk7XG4gIH1cbn1cbiIsICJpbXBvcnQgdHlwZSB7IENoaWxkUHJvY2VzcyB9IGZyb20gXCJub2RlOmNoaWxkX3Byb2Nlc3NcIjtcbmltcG9ydCB7IHNwYXduIH0gZnJvbSBcIm5vZGU6Y2hpbGRfcHJvY2Vzc1wiO1xuaW1wb3J0ICogYXMgZnMgZnJvbSBcIm5vZGU6ZnMvcHJvbWlzZXNcIjtcbmltcG9ydCAqIGFzIHBhdGggZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0ICogYXMgZXJyb3JlIGZyb20gXCJlcnJvcmVcIjtcbmltcG9ydCB7IHVsaWQgfSBmcm9tIFwidWxpZFwiO1xuaW1wb3J0IHsgU2FuZGJveEVycm9yIH0gZnJvbSBcIi4uLy4uL2Vycm9yc1wiO1xuaW1wb3J0IHR5cGUgeyBUYWdzU2NoZW1hIH0gZnJvbSBcIi4uLy4uL2luZGV4XCI7XG5pbXBvcnQgdHlwZSB7IFNhbmRib3hSZWNvcmQsIFN0b3JhZ2UgfSBmcm9tIFwiLi4vLi4vc3RvcmFnZVwiO1xuaW1wb3J0IHsgZGVidWcgfSBmcm9tIFwiLi4vLi4vdXRpbHMvZGVidWdcIjtcbmltcG9ydCB0eXBlIHsgU2FuZGJveFNldHVwTWV0YSB9IGZyb20gXCIuLi9jbGllbnRcIjtcbmltcG9ydCB0eXBlIHsgTG9nRW50cnksIE9uUmVzdGFydCwgU2FuZGJveCwgU2FuZGJveFNldHVwIH0gZnJvbSBcIi4uL3R5cGVzXCI7XG5pbXBvcnQgeyB3cml0ZUZpbGVzIH0gZnJvbSBcIi4uL3dyaXRlLWZpbGVzXCI7XG5cbmV4cG9ydCBjb25zdCBsb2NhbFNhbmRib3ggPSA8VFRhZ3MgZXh0ZW5kcyBUYWdzU2NoZW1hID0gVGFnc1NjaGVtYT4oe1xuICBzYW5kYm94UmVjb3JkLFxuICBzdG9yYWdlLFxuICBzZXR1cCxcbiAgb25SZXN0YXJ0LFxufToge1xuICBzYW5kYm94UmVjb3JkOiBTYW5kYm94UmVjb3JkICYgeyBjb25maWc6IHsgdHlwZTogXCJsb2NhbFwiIH0gfTtcbiAgc3RvcmFnZTogU3RvcmFnZTtcbiAgc2V0dXA/OiBTYW5kYm94U2V0dXA7XG4gIG9uUmVzdGFydD86IE9uUmVzdGFydDtcbn0pOiBTYW5kYm94PFRUYWdzPiAmIHtcbiAgX29uUmVhZHk/OiBQcm9taXNlPHZvaWQ+O1xuICBfc2V0dXBNZXRhPzogUHJvbWlzZTxTYW5kYm94U2V0dXBNZXRhPjtcbn0gPT4ge1xuICBjb25zdCBjb25maWcgPSBzYW5kYm94UmVjb3JkLmNvbmZpZztcbiAgY29uc3QgYmFzZVBhdGggPSBjb25maWcucGF0aCA/PyBwcm9jZXNzLmN3ZCgpO1xuICBjb25zdCBwcm9jZXNzZXMgPSBuZXcgTWFwPHN0cmluZywgQ2hpbGRQcm9jZXNzPigpO1xuXG4gIGNvbnN0IHNhbmRib3g6IFNhbmRib3g8VFRhZ3M+ID0ge1xuICAgIGlkOiBzYW5kYm94UmVjb3JkLmlkLFxuICAgIGNvbmZpZzogc2FuZGJveFJlY29yZC5jb25maWcsXG4gICAgZXhlYzogKHsgY29tbWFuZCwgYXJncywgc2lnbmFsIH0pID0+IHtcbiAgICAgIHJldHVybiBlcnJvcmUudHJ5QXN5bmMoe1xuICAgICAgICB0cnk6ICgpID0+IHtcbiAgICAgICAgICBjb25zdCBjb21tYW5kSWQgPSBgY29tbWFuZF8ke3VsaWQoKX1gO1xuXG4gICAgICAgICAgY29uc3QgY2hpbGQgPSBzcGF3bihjb21tYW5kLCBhcmdzLCB7XG4gICAgICAgICAgICBjd2Q6IGJhc2VQYXRoLFxuICAgICAgICAgICAgc2lnbmFsLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgcHJvY2Vzc2VzLnNldChjb21tYW5kSWQsIGNoaWxkKTtcblxuICAgICAgICAgIGxldCBzdGRvdXQgPSBcIlwiO1xuICAgICAgICAgIGxldCBzdGRlcnIgPSBcIlwiO1xuICAgICAgICAgIGNvbnN0IGxvZ1F1ZXVlOiBMb2dFbnRyeVtdID0gW107XG4gICAgICAgICAgbGV0IGxvZ1Jlc29sdmU6ICgoKSA9PiB2b2lkKSB8IG51bGwgPSBudWxsO1xuICAgICAgICAgIGxldCBjbG9zZWQgPSBmYWxzZTtcblxuICAgICAgICAgIGNoaWxkLnN0ZG91dC5vbihcImRhdGFcIiwgKGRhdGE6IHN0cmluZyB8IEJ1ZmZlcikgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc3RyID0gU3RyaW5nKGRhdGEpO1xuICAgICAgICAgICAgc3Rkb3V0ICs9IHN0cjtcbiAgICAgICAgICAgIGxvZ1F1ZXVlLnB1c2goeyBzdHJlYW06IFwic3Rkb3V0XCIsIGRhdGE6IHN0ciB9KTtcbiAgICAgICAgICAgIGxvZ1Jlc29sdmU/LigpO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgY2hpbGQuc3RkZXJyLm9uKFwiZGF0YVwiLCAoZGF0YTogc3RyaW5nIHwgQnVmZmVyKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBzdHIgPSBTdHJpbmcoZGF0YSk7XG4gICAgICAgICAgICBzdGRlcnIgKz0gc3RyO1xuICAgICAgICAgICAgbG9nUXVldWUucHVzaCh7IHN0cmVhbTogXCJzdGRlcnJcIiwgZGF0YTogc3RyIH0pO1xuICAgICAgICAgICAgbG9nUmVzb2x2ZT8uKCk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBjb25zdCByZXN1bHQgPSBuZXcgUHJvbWlzZTx7XG4gICAgICAgICAgICBzdGRvdXQ6IHN0cmluZztcbiAgICAgICAgICAgIHN0ZGVycjogc3RyaW5nO1xuICAgICAgICAgICAgZXhpdENvZGU6IG51bWJlcjtcbiAgICAgICAgICB9PigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjaGlsZC5vbihcImVycm9yXCIsIChlcnIpID0+IHtcbiAgICAgICAgICAgICAgcHJvY2Vzc2VzLmRlbGV0ZShjb21tYW5kSWQpO1xuICAgICAgICAgICAgICBjbG9zZWQgPSB0cnVlO1xuICAgICAgICAgICAgICBsb2dSZXNvbHZlPy4oKTtcbiAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgY2hpbGQub24oXCJjbG9zZVwiLCAoY29kZTogbnVtYmVyIHwgbnVsbCkgPT4ge1xuICAgICAgICAgICAgICBwcm9jZXNzZXMuZGVsZXRlKGNvbW1hbmRJZCk7XG4gICAgICAgICAgICAgIGNsb3NlZCA9IHRydWU7XG4gICAgICAgICAgICAgIGxvZ1Jlc29sdmU/LigpO1xuICAgICAgICAgICAgICByZXNvbHZlKHsgc3Rkb3V0LCBzdGRlcnIsIGV4aXRDb2RlOiBjb2RlID8/IDAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGFzeW5jIGZ1bmN0aW9uKiBsb2dzKCk6IEFzeW5jSXRlcmFibGU8TG9nRW50cnk+IHtcbiAgICAgICAgICAgIHdoaWxlICghY2xvc2VkIHx8IGxvZ1F1ZXVlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgY29uc3QgZW50cnkgPSBsb2dRdWV1ZS5zaGlmdCgpO1xuICAgICAgICAgICAgICBpZiAoZW50cnkpIHtcbiAgICAgICAgICAgICAgICB5aWVsZCBlbnRyeTtcbiAgICAgICAgICAgICAgfSBlbHNlIGlmICghY2xvc2VkKSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUpID0+IHtcbiAgICAgICAgICAgICAgICAgIGxvZ1Jlc29sdmUgPSByZXNvbHZlO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGxvZ1Jlc29sdmUgPSBudWxsO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7IGNvbW1hbmRJZCwgbG9ncywgcmVzdWx0IH0pO1xuICAgICAgICB9LFxuICAgICAgICBjYXRjaDogKGU6IHVua25vd24pID0+XG4gICAgICAgICAgbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogU3RyaW5nKGUpLCBjYXVzZTogZSB9KSxcbiAgICAgIH0pO1xuICAgIH0sXG5cbiAgICBnZXREb21haW46IChwb3J0KSA9PiB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGBodHRwOi8vbG9jYWxob3N0OiR7cG9ydH1gKTtcbiAgICB9LFxuXG4gICAga2lsbDogYXN5bmMgKHsgY29tbWFuZElkLCBzdG9yYWdlIH0pID0+IHtcbiAgICAgIGNvbnN0IGNoaWxkID0gcHJvY2Vzc2VzLmdldChjb21tYW5kSWQpO1xuICAgICAgaWYgKCFjaGlsZCkge1xuICAgICAgICByZXR1cm4gbmV3IFNhbmRib3hFcnJvcih7XG4gICAgICAgICAgcmVhc29uOiBgQ29tbWFuZCAke2NvbW1hbmRJZH0gbm90IGZvdW5kIG9yIGFscmVhZHkgZmluaXNoZWRgLFxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgY2hpbGQua2lsbChcIlNJR1RFUk1cIik7XG5cbiAgICAgIGNvbnN0IGNtZCA9IGF3YWl0IHN0b3JhZ2UuY29tbWFuZC5nZXQoY29tbWFuZElkKTtcbiAgICAgIGlmIChjbWQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICByZXR1cm4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogY21kLm1lc3NhZ2UsIGNhdXNlOiBjbWQgfSk7XG4gICAgICB9XG4gICAgICBpZiAoY21kICYmIGNtZC5zdGF0dXMgPT09IFwicnVubmluZ1wiKSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHN0b3JhZ2UuY29tbWFuZC5zZXQoe1xuICAgICAgICAgIC4uLmNtZCxcbiAgICAgICAgICBzdGF0dXM6IFwia2lsbGVkXCIsXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICByZXR1cm4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogcmVzdWx0Lm1lc3NhZ2UsIGNhdXNlOiByZXN1bHQgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LFxuXG4gICAgcmVhZEZpbGU6IGFzeW5jICh7IHBhdGg6IGZpbGVQYXRoIH0pID0+IHtcbiAgICAgIGNvbnN0IGZ1bGxQYXRoID0gcGF0aC5qb2luKGJhc2VQYXRoLCBmaWxlUGF0aCk7XG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gYXdhaXQgZnMucmVhZEZpbGUoZnVsbFBhdGgpO1xuICAgICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgZSBpbnN0YW5jZW9mIEVycm9yICYmXG4gICAgICAgICAgXCJjb2RlXCIgaW4gZSAmJlxuICAgICAgICAgIChlIGFzIE5vZGVKUy5FcnJub0V4Y2VwdGlvbikuY29kZSA9PT0gXCJFTk9FTlRcIlxuICAgICAgICApIHtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogU3RyaW5nKGUpLCBjYXVzZTogZSB9KTtcbiAgICAgIH1cbiAgICB9LFxuXG4gICAgd3JpdGVGaWxlczogKG9wdHMpID0+IHdyaXRlRmlsZXMoeyBzYW5kYm94LCAuLi5vcHRzIH0pLFxuXG4gICAgdXBkYXRlTmV0d29ya1BvbGljeTogKCkgPT5cbiAgICAgIFByb21pc2UucmVzb2x2ZShcbiAgICAgICAgbmV3IFNhbmRib3hFcnJvcih7XG4gICAgICAgICAgcmVhc29uOiBcInVwZGF0ZU5ldHdvcmtQb2xpY3kgaXMgb25seSBhdmFpbGFibGUgZm9yIFZlcmNlbCBzYW5kYm94ZXNcIixcbiAgICAgICAgfSlcbiAgICAgICksXG5cbiAgICB0YWc6IHtcbiAgICAgIGxpc3Q6IGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc3Qgc2FuZGJveFJlY29yZCA9IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5nZXQoc2FuZGJveC5pZCk7XG4gICAgICAgIGlmIChzYW5kYm94UmVjb3JkIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICByZXR1cm4gc2FuZGJveFJlY29yZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gKHNhbmRib3hSZWNvcmQudGFncyA/PyB7fSkgYXMgVFRhZ3M7XG4gICAgICB9LFxuICAgICAgZ2V0OiBhc3luYyAoa2V5OiBzdHJpbmcpID0+IHtcbiAgICAgICAgY29uc3Qgc2FuZGJveFJlY29yZCA9IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5nZXQoc2FuZGJveC5pZCk7XG4gICAgICAgIGlmIChzYW5kYm94UmVjb3JkIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICByZXR1cm4gc2FuZGJveFJlY29yZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2FuZGJveFJlY29yZC50YWdzPy5ba2V5IGFzIHN0cmluZ10gYXNcbiAgICAgICAgICB8IFRUYWdzW3R5cGVvZiBrZXldXG4gICAgICAgICAgfCB1bmRlZmluZWQ7XG4gICAgICB9LFxuICAgICAgc2V0OiBhc3luYyAoa2V5OiBzdHJpbmcsIHZhbHVlOiB1bmtub3duKSA9PiB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC50YWcuc2V0KHtcbiAgICAgICAgICBzYW5kYm94SWQ6IHNhbmRib3guaWQsXG4gICAgICAgICAgdGFnczogeyBba2V5XTogdmFsdWUgfSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH0sXG4gICAgICBzZXRNYW55OiBhc3luYyAodGFnczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pID0+IHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3RvcmFnZS5zYW5kYm94LnRhZy5zZXQoe1xuICAgICAgICAgIHNhbmRib3hJZDogc2FuZGJveC5pZCxcbiAgICAgICAgICB0YWdzOiB0YWdzIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfSxcbiAgICB9LFxuICB9O1xuXG4gIGNvbnN0IHJlc3VsdDogU2FuZGJveDxUVGFncz4gJiB7XG4gICAgX29uUmVhZHk/OiBQcm9taXNlPHZvaWQ+O1xuICAgIF9zZXR1cE1ldGE/OiBQcm9taXNlPFNhbmRib3hTZXR1cE1ldGE+O1xuICB9ID0gc2FuZGJveDtcblxuICBpZiAoc2V0dXAgfHwgb25SZXN0YXJ0KSB7XG4gICAgbGV0IHJlc29sdmVTZXR1cE1ldGEhOiAobWV0YTogU2FuZGJveFNldHVwTWV0YSkgPT4gdm9pZDtcbiAgICByZXN1bHQuX3NldHVwTWV0YSA9IG5ldyBQcm9taXNlPFNhbmRib3hTZXR1cE1ldGE+KChyKSA9PiB7XG4gICAgICByZXNvbHZlU2V0dXBNZXRhID0gcjtcbiAgICB9KTtcblxuICAgIHJlc3VsdC5fb25SZWFkeSA9IChhc3luYyAoKSA9PiB7XG4gICAgICBsZXQgbmVlZHNTZXR1cFJ1biA9ICEhc2V0dXA7XG4gICAgICBpZiAoc2V0dXApIHtcbiAgICAgICAgY29uc3QgZXhpc3RpbmcgPSBhd2FpdCBzdG9yYWdlLnNldHVwLmdldChzZXR1cC5rZXkpO1xuICAgICAgICBpZiAoIShleGlzdGluZyBpbnN0YW5jZW9mIEVycm9yKSAmJiBleGlzdGluZykge1xuICAgICAgICAgIGRlYnVnKFxuICAgICAgICAgICAgYFtzYW5kYm94OnNldHVwXSBzZXR1cCBhbHJlYWR5IGNvbXBsZXRlIGZvciBrZXkgXCIke3NldHVwLmtleX1cIiwgc2tpcHBpbmdgXG4gICAgICAgICAgKTtcbiAgICAgICAgICBuZWVkc1NldHVwUnVuID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gUmVzb2x2ZSBzZXR1cCBtZXRhZGF0YSBiZWZvcmUgcnVubmluZyBzZXR1cCBzbyB0aGUgd29ya2Zsb3dcbiAgICAgIC8vIGNhbiBlbWl0IHRoZSBjb3JyZWN0IHN0YXR1cyBpbmRpY2F0b3Igd2hpbGUgc2V0dXAgcnVucy5cbiAgICAgIHJlc29sdmVTZXR1cE1ldGEoe1xuICAgICAgICBuZWVkc1NldHVwUnVuLFxuICAgICAgICBjcmVhdGVkRnJvbVNuYXBzaG90OiBmYWxzZSxcbiAgICAgIH0pO1xuXG4gICAgICBpZiAobmVlZHNTZXR1cFJ1biAmJiBzZXR1cCkge1xuICAgICAgICBkZWJ1ZyhgW3NhbmRib3g6c2V0dXBdIHJ1bm5pbmcgc2V0dXAucnVuIChsb2NhbCwga2V5PVwiJHtzZXR1cC5rZXl9XCIpYCk7XG4gICAgICAgIGF3YWl0IHNldHVwLnJ1bihzYW5kYm94KTtcbiAgICAgICAgYXdhaXQgc3RvcmFnZS5zZXR1cC5zZXQoe1xuICAgICAgICAgIGtleTogc2V0dXAua2V5LFxuICAgICAgICAgIHNuYXBzaG90SWQ6IG51bGwsXG4gICAgICAgICAgY3JlYXRlZEF0OiBEYXRlLm5vdygpLFxuICAgICAgICAgIGxhc3RVc2VkQXQ6IG51bGwsXG4gICAgICAgICAgYWNxdWlyaW5nTG9ja0lkOiBudWxsLFxuICAgICAgICAgIGFjcXVpcmluZ0xvY2tBdDogbnVsbCxcbiAgICAgICAgfSk7XG4gICAgICAgIGRlYnVnKFxuICAgICAgICAgIGBbc2FuZGJveDpzZXR1cF0gc2V0dXAgY29tcGxldGUsIHN0b3JlZCByZWNvcmQgKGtleT1cIiR7c2V0dXAua2V5fVwiKWBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIGlmIChvblJlc3RhcnQpIHtcbiAgICAgICAgZGVidWcoXCJbc2FuZGJveDpzZXR1cF0gcnVubmluZyBvblJlc3RhcnQgKGxvY2FsKVwiKTtcbiAgICAgICAgYXdhaXQgb25SZXN0YXJ0KHNhbmRib3gpO1xuICAgICAgfVxuICAgIH0pKCk7XG4gIH1cblxuICByZXR1cm4gcmVzdWx0O1xufTtcbiIsICJpbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCB0eXBlIHsgVXBsb2FkYWJsZUZpbGUgfSBmcm9tIFwiLi4vc2tpbGxzL3R5cGVzXCI7XG5pbXBvcnQgdHlwZSB7IFNhbmRib3ggfSBmcm9tIFwiLi90eXBlc1wiO1xuXG5jb25zdCBNQVhfUkVUUklFUyA9IDI7XG5jb25zdCBSRVRSWV9CQVNFX01TID0gNTAwO1xuXG4vKipcbiAqIEV4ZWMgYSBjb21tYW5kIGFuZCBhc3NlcnQgZXhpdCBjb2RlIDAuIFJldHJpZXMgb24gdHJhbnNpZW50IGZhaWx1cmVzXG4gKiAoZXhpdCBjb2RlIDI1NSB3aXRoIGVtcHR5IHN0ZGVyciBcdTIwMTQgdHlwaWNhbGx5IGEgc2FuZGJveCBwcm9jZXNzIGtpbGxlZFxuICogYmVmb3JlIGl0IGNvdWxkIHByb2R1Y2Ugb3V0cHV0KS5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gZXhlY0NoZWNrZWQoXG4gIHNhbmRib3g6IFBpY2s8U2FuZGJveCwgXCJleGVjXCI+LFxuICBvcHRzOiB7IGNvbW1hbmQ6IHN0cmluZzsgYXJncz86IHN0cmluZ1tdIH0sXG4gIGVycm9yTGFiZWw6IHN0cmluZ1xuKTogUHJvbWlzZTx7IHN0ZG91dDogc3RyaW5nOyBzdGRlcnI6IHN0cmluZzsgZXhpdENvZGU6IG51bWJlciB9PiB7XG4gIGZvciAobGV0IGF0dGVtcHQgPSAwOyA7IGF0dGVtcHQrKykge1xuICAgIGNvbnN0IGV4ZWNSZXN1bHQgPSBhd2FpdCBzYW5kYm94LmV4ZWMob3B0cyk7XG4gICAgaWYgKGV4ZWNSZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgdGhyb3cgZXhlY1Jlc3VsdDtcbiAgICB9XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZXhlY1Jlc3VsdC5yZXN1bHQ7XG4gICAgaWYgKHJlc3VsdC5leGl0Q29kZSA9PT0gMCkge1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICBjb25zdCBpc1RyYW5zaWVudCA9IHJlc3VsdC5leGl0Q29kZSA9PT0gMjU1ICYmICFyZXN1bHQuc3RkZXJyLnRyaW0oKTtcbiAgICBpZiAoaXNUcmFuc2llbnQgJiYgYXR0ZW1wdCA8IE1BWF9SRVRSSUVTKSB7XG4gICAgICBhd2FpdCBuZXcgUHJvbWlzZSgocikgPT4gc2V0VGltZW91dChyLCBSRVRSWV9CQVNFX01TICogKGF0dGVtcHQgKyAxKSkpO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYCR7ZXJyb3JMYWJlbH0gd2l0aCBleGl0IGNvZGUgJHtyZXN1bHQuZXhpdENvZGV9OiAke3Jlc3VsdC5zdGRlcnJ9YFxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBXcml0ZXMgZmlsZXMgdG8gYSBzYW5kYm94IGF0IHRoZSBzcGVjaWZpZWQgZGVzdGluYXRpb24gcGF0aC5cbiAqIFNoZWxsIHNjcmlwdHMgKC5zaCBmaWxlcykgYXJlIGF1dG9tYXRpY2FsbHkgbWFkZSBleGVjdXRhYmxlLlxuICpcbiAqIEZvciBzbWFsbCBmaWxlcyAoPDEwMEtCIHRvdGFsKSwgdXNlcyBzaW5nbGUgZXhlYyB3aXRoIGhlcmVkb2MuXG4gKiBGb3IgbGFyZ2UgZmlsZXMsIHdyaXRlcyBiYXNlNjQgY2h1bmtzIHRoZW4gZGVjb2RlcyB0byBhdm9pZCBBUkdfTUFYIGxpbWl0cy5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHdyaXRlRmlsZXMob3B0czoge1xuICBzYW5kYm94OiBQaWNrPFNhbmRib3gsIFwiZXhlY1wiPjtcbiAgZmlsZXM6IFVwbG9hZGFibGVGaWxlW107XG4gIGRlc3RQYXRoOiBzdHJpbmc7XG59KTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHsgc2FuZGJveCwgZmlsZXMsIGRlc3RQYXRoIH0gPSBvcHRzO1xuXG4gIGlmIChmaWxlcy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCBmaWxlUGF0aHMgPSBmaWxlcy5tYXAoKGZpbGUpID0+IHBhdGgucG9zaXguam9pbihkZXN0UGF0aCwgZmlsZS5wYXRoKSk7XG4gIGNvbnN0IHBhcmVudERpcnMgPSBBcnJheS5mcm9tKFxuICAgIG5ldyBTZXQoZmlsZVBhdGhzLm1hcCgocCkgPT4gcGF0aC5wb3NpeC5kaXJuYW1lKHApKSlcbiAgKTtcbiAgY29uc3Qgc2hlbGxTY3JpcHRzID0gZmlsZVBhdGhzLmZpbHRlcigocCkgPT4gcC5lbmRzV2l0aChcIi5zaFwiKSk7XG5cbiAgY29uc3QgbWtkaXJSZXN1bHQgPSBhd2FpdCBzYW5kYm94LmV4ZWMoe1xuICAgIGNvbW1hbmQ6IFwibWtkaXJcIixcbiAgICBhcmdzOiBbXCItcFwiLCAuLi5wYXJlbnREaXJzXSxcbiAgfSk7XG4gIGlmIChta2RpclJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgdGhyb3cgbWtkaXJSZXN1bHQ7XG4gIH1cbiAgYXdhaXQgbWtkaXJSZXN1bHQucmVzdWx0O1xuXG4gIGNvbnN0IENIVU5LX1NJWkUgPSA1MF8wMDA7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBmaWxlcy5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IGZpbGUgPSBmaWxlc1tpXTtcbiAgICBjb25zdCBmdWxsUGF0aCA9IGZpbGVQYXRoc1tpXTtcbiAgICBjb25zdCBiYXNlNjRDb250ZW50ID0gdG9CYXNlNjQoZmlsZS5jb250ZW50KTtcblxuICAgIGlmIChiYXNlNjRDb250ZW50Lmxlbmd0aCA8IENIVU5LX1NJWkUpIHtcbiAgICAgIGNvbnN0IG1hcmtlciA9IGBFT0ZfJHtpfWA7XG4gICAgICBhd2FpdCBleGVjQ2hlY2tlZChcbiAgICAgICAgc2FuZGJveCxcbiAgICAgICAge1xuICAgICAgICAgIGNvbW1hbmQ6IFwiYmFzaFwiLFxuICAgICAgICAgIGFyZ3M6IFtcbiAgICAgICAgICAgIFwiLWNcIixcbiAgICAgICAgICAgIGBiYXNlNjQgLWQgPiAke3F1b3RlKGZ1bGxQYXRoKX0gPDwgJyR7bWFya2VyfSdcbiR7YmFzZTY0Q29udGVudH1cbiR7bWFya2VyfWAsXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgICAgXCJ3cml0ZUZpbGVzIGZhaWxlZFwiXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCB0ZW1wQjY0ID0gYC90bXAvY2h1bmstJHtEYXRlLm5vdygpfS0ke2l9LmI2NGA7XG5cbiAgICAgIGNvbnN0IGNsZWFyUmVzdWx0ID0gYXdhaXQgc2FuZGJveC5leGVjKHtcbiAgICAgICAgY29tbWFuZDogXCJiYXNoXCIsXG4gICAgICAgIGFyZ3M6IFtcIi1jXCIsIGA+ICR7cXVvdGUodGVtcEI2NCl9YF0sXG4gICAgICB9KTtcbiAgICAgIGlmIChjbGVhclJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHRocm93IGNsZWFyUmVzdWx0O1xuICAgICAgfVxuICAgICAgYXdhaXQgY2xlYXJSZXN1bHQucmVzdWx0O1xuXG4gICAgICBmb3IgKFxuICAgICAgICBsZXQgb2Zmc2V0ID0gMDtcbiAgICAgICAgb2Zmc2V0IDwgYmFzZTY0Q29udGVudC5sZW5ndGg7XG4gICAgICAgIG9mZnNldCArPSBDSFVOS19TSVpFXG4gICAgICApIHtcbiAgICAgICAgY29uc3QgY2h1bmsgPSBiYXNlNjRDb250ZW50LnNsaWNlKG9mZnNldCwgb2Zmc2V0ICsgQ0hVTktfU0laRSk7XG4gICAgICAgIGNvbnN0IG1hcmtlciA9IGBDSFVOS18ke29mZnNldH1gO1xuICAgICAgICBhd2FpdCBleGVjQ2hlY2tlZChcbiAgICAgICAgICBzYW5kYm94LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGNvbW1hbmQ6IFwiYmFzaFwiLFxuICAgICAgICAgICAgYXJnczogW1xuICAgICAgICAgICAgICBcIi1jXCIsXG4gICAgICAgICAgICAgIGBjYXQgPj4gJHtxdW90ZSh0ZW1wQjY0KX0gPDwgJyR7bWFya2VyfSdcbiR7Y2h1bmt9XG4ke21hcmtlcn1gLFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIFwid3JpdGVGaWxlcyBjaHVuayBmYWlsZWRcIlxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBhd2FpdCBleGVjQ2hlY2tlZChcbiAgICAgICAgc2FuZGJveCxcbiAgICAgICAge1xuICAgICAgICAgIGNvbW1hbmQ6IFwiYmFzaFwiLFxuICAgICAgICAgIGFyZ3M6IFtcbiAgICAgICAgICAgIFwiLWNcIixcbiAgICAgICAgICAgIGBiYXNlNjQgLWQgPCAke3F1b3RlKHRlbXBCNjQpfSA+ICR7cXVvdGUoZnVsbFBhdGgpfSAmJiBybSAtZiAke3F1b3RlKHRlbXBCNjQpfWAsXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgICAgXCJ3cml0ZUZpbGVzIGRlY29kZSBmYWlsZWRcIlxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBpZiAoc2hlbGxTY3JpcHRzLmxlbmd0aCA+IDApIHtcbiAgICBjb25zdCBjaG1vZFJlc3VsdCA9IGF3YWl0IHNhbmRib3guZXhlYyh7XG4gICAgICBjb21tYW5kOiBcImNobW9kXCIsXG4gICAgICBhcmdzOiBbXCIreFwiLCAuLi5zaGVsbFNjcmlwdHNdLFxuICAgIH0pO1xuICAgIGlmIChjaG1vZFJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICB0aHJvdyBjaG1vZFJlc3VsdDtcbiAgICB9XG4gICAgYXdhaXQgY2htb2RSZXN1bHQucmVzdWx0O1xuICB9XG59XG5cbmZ1bmN0aW9uIHRvQmFzZTY0KGNvbnRlbnQ6IHN0cmluZyB8IEJ1ZmZlcik6IHN0cmluZyB7XG4gIGlmICh0eXBlb2YgY29udGVudCA9PT0gXCJzdHJpbmdcIikge1xuICAgIHJldHVybiBCdWZmZXIuZnJvbShjb250ZW50KS50b1N0cmluZyhcImJhc2U2NFwiKTtcbiAgfVxuICByZXR1cm4gY29udGVudC50b1N0cmluZyhcImJhc2U2NFwiKTtcbn1cblxuZnVuY3Rpb24gcXVvdGUoczogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGAnJHtzLnJlcGxhY2UoLycvZywgXCInXFxcXCcnXCIpfSdgO1xufVxuIiwgImltcG9ydCAqIGFzIHBhdGggZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHsgU2FuZGJveCBhcyBWZXJjZWxTYW5kYm94U0RLIH0gZnJvbSBcIkB2ZXJjZWwvc2FuZGJveFwiO1xuaW1wb3J0ICogYXMgZXJyb3JlIGZyb20gXCJlcnJvcmVcIjtcbmltcG9ydCB7IHN0YXJ0IH0gZnJvbSBcIndvcmtmbG93L2FwaVwiO1xuaW1wb3J0IHsgU2FuZGJveEVycm9yLCBTYW5kYm94Tm90Rm91bmRFcnJvciB9IGZyb20gXCIuLi8uLi9lcnJvcnNcIjtcbmltcG9ydCB0eXBlIHsgVGFnc1NjaGVtYSB9IGZyb20gXCIuLi8uLi9pbmRleFwiO1xuaW1wb3J0IHR5cGUge1xuICBScGNGbixcbiAgU2FuZGJveFJlY29yZCxcbiAgU3RvcmFnZSxcbiAgU3RvcmFnZUNvbmZpZyxcbn0gZnJvbSBcIi4uLy4uL3N0b3JhZ2VcIjtcbmltcG9ydCB7IGRlYnVnIH0gZnJvbSBcIi4uLy4uL3V0aWxzL2RlYnVnXCI7XG5pbXBvcnQgdHlwZSB7IFNhbmRib3hTZXR1cE1ldGEgfSBmcm9tIFwiLi4vY2xpZW50XCI7XG5pbXBvcnQgdHlwZSB7XG4gIExvZ0VudHJ5LFxuICBPblJlc3RhcnQsXG4gIFNhbmRib3gsXG4gIFNhbmRib3hMaWZlY3ljbGUsXG4gIFNhbmRib3hMaWZlY3ljbGVJbnB1dCxcbiAgU2FuZGJveFNldHVwLFxuICBTYW5kYm94U3RhdHVzLFxufSBmcm9tIFwiLi4vdHlwZXNcIjtcbmltcG9ydCB7IHNhbmRib3hMaWZlY3ljbGVXb3JrZmxvdyB9IGZyb20gXCIuL2xpZmVjeWNsZS13b3JrZmxvd1wiO1xuXG5leHBvcnQgdHlwZSBWZXJjZWxTYW5kYm94Q3JlYXRlT3B0aW9ucyA9IEV4dHJhY3Q8XG4gIFBhcmFtZXRlcnM8dHlwZW9mIFZlcmNlbFNhbmRib3hTREsuY3JlYXRlPlswXSxcbiAgLy8gYmlvbWUtaWdub3JlIGxpbnQvY29tcGxleGl0eS9ub0Jhbm5lZFR5cGVzOiAuXG4gIHt9XG4+O1xuXG5leHBvcnQgY29uc3QgVkVSQ0VMX01BWF9USU1FT1VUX01TID0gNSAqIDYwICogNjAgKiAxMDAwOyAvLyA1IGhvdXJzXG5jb25zdCBMT0NLX1RJTUVPVVRfTVMgPSA1ICogNjAgKiAxMDAwOyAvLyA1IG1pbnV0ZXMgLSBpZiBsb2NrIG9sZGVyIHRoYW4gdGhpcywgY29uc2lkZXIgaXQgc3RhbGVcbmNvbnN0IExPQ0tfUE9MTF9JTlRFUlZBTF9NUyA9IDIwMDtcblxuY29uc3QgZ2V0VGVzdENyZWRlbnRpYWxzID0gKCkgPT5cbiAgcHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09IFwidGVzdFwiXG4gICAgPyB7XG4gICAgICAgIHRva2VuOiBwcm9jZXNzLmVudi5URVNUX1ZFUkNFTF9UT0tFTixcbiAgICAgICAgdGVhbUlkOiBwcm9jZXNzLmVudi5URVNUX1ZFUkNFTF9URUFNX0lELFxuICAgICAgICBwcm9qZWN0SWQ6IHByb2Nlc3MuZW52LlRFU1RfVkVSQ0VMX1BST0pFQ1RfSUQsXG4gICAgICB9XG4gICAgOiB7fTtcblxuLyoqXG4gKiBNb2R1bGUtbGV2ZWwgY2FjaGUgZm9yIGluLWZsaWdodCBzYW5kYm94IGNyZWF0aW9uIHByb21pc2VzLlxuICogUHJldmVudHMgcGFyYWxsZWwgcmVxdWVzdHMgd2l0aGluIHRoZSBzYW1lIHByb2Nlc3MgZnJvbSBjcmVhdGluZyBkdXBsaWNhdGUgc2FuZGJveGVzLlxuICovXG5jb25zdCBjcmVhdGVQcm9taXNlcyA9IG5ldyBNYXA8c3RyaW5nLCBQcm9taXNlPFNhbmRib3hFcnJvciB8IHN0cmluZz4+KCk7XG5cbmNvbnN0IEFDVElWSVRZX1RIUk9UVExFX01TID0gMTBfMDAwO1xuY29uc3QgbGFzdEFjdGl2aXR5U2VudCA9IG5ldyBNYXA8c3RyaW5nLCBudW1iZXI+KCk7XG5cbmNvbnN0IERFRkFVTFRfVkNQVVMgPSAyO1xuXG5mdW5jdGlvbiBpc1NhbmRib3hHb25lRXJyb3IoZTogdW5rbm93bik6IGJvb2xlYW4ge1xuICBpZiAoIShlIGluc3RhbmNlb2YgRXJyb3IpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgY29uc3QgZXJyb3JXaXRoUmVzcG9uc2UgPSBlIGFzIHsgcmVzcG9uc2U/OiB7IHN0YXR1cz86IG51bWJlciB9IH07XG4gIGNvbnN0IGVycm9yV2l0aENhdXNlID0gZSBhcyB7IGNhdXNlPzogeyByZXNwb25zZT86IHsgc3RhdHVzPzogbnVtYmVyIH0gfSB9O1xuXG4gIGNvbnN0IHN0YXR1cyA9XG4gICAgZXJyb3JXaXRoUmVzcG9uc2UucmVzcG9uc2U/LnN0YXR1cyA/P1xuICAgIGVycm9yV2l0aENhdXNlLmNhdXNlPy5yZXNwb25zZT8uc3RhdHVzO1xuXG4gIGlmIChzdGF0dXMgPT09IDQxMCB8fCBzdGF0dXMgPT09IDQyMikge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgY29uc3QgbWVzc2FnZSA9IGUubWVzc2FnZSB8fCBTdHJpbmcoZSk7XG4gIGlmIChcbiAgICBtZXNzYWdlLmluY2x1ZGVzKFwiRXhwZWN0ZWQgYSBzdHJlYW0gb2YgY29tbWFuZCBkYXRhXCIpIHx8XG4gICAgbWVzc2FnZS5pbmNsdWRlcyhcIkV4cGVjdGVkIGEgc3RyZWFtIG9mIGxvZ3NcIilcbiAgKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmV4cG9ydCBjb25zdCB2ZXJjZWxTYW5kYm94ID0gPFRUYWdzIGV4dGVuZHMgVGFnc1NjaGVtYSA9IFRhZ3NTY2hlbWE+KHtcbiAgc2FuZGJveFJlY29yZCxcbiAgc3RvcmFnZUNvbmZpZyxcbiAgZW5hYmxlTGlmZWN5Y2xlV29ya2Zsb3csXG4gIHN0b3JhZ2UsXG4gIHJwYyxcbiAgc2V0dXAsXG4gIG9uUmVzdGFydCxcbn06IHtcbiAgc2FuZGJveFJlY29yZDogU2FuZGJveFJlY29yZCAmIHsgY29uZmlnOiB7IHR5cGU6IFwidmVyY2VsXCIgfSB9O1xuICBzdG9yYWdlQ29uZmlnOiBTdG9yYWdlQ29uZmlnO1xuICBlbmFibGVMaWZlY3ljbGVXb3JrZmxvdzogYm9vbGVhbjtcbiAgc3RvcmFnZTogU3RvcmFnZTtcbiAgcnBjOiBScGNGbjtcbiAgc2V0dXA/OiBTYW5kYm94U2V0dXA7XG4gIG9uUmVzdGFydD86IE9uUmVzdGFydDtcbn0pOiBTYW5kYm94PFRUYWdzPiAmIHtcbiAgX29uUmVhZHk/OiBQcm9taXNlPHZvaWQ+O1xuICBfc2V0dXBNZXRhPzogUHJvbWlzZTxTYW5kYm94U2V0dXBNZXRhPjtcbn0gPT4ge1xuICBjb25zdCB7IGlkLCBjb25maWcgfSA9IHNhbmRib3hSZWNvcmQ7XG4gIGNvbnN0IHZjcHVzID0gY29uZmlnLnJlc291cmNlcz8udmNwdXMgPz8gREVGQVVMVF9WQ1BVUztcbiAgY29uc3QgcG9ydHMgPSBjb25maWcucG9ydHM7XG4gIGNvbnN0IG5ldHdvcmtQb2xpY3kgPSBjb25maWcubmV0d29ya1BvbGljeTtcbiAgY29uc3QgaW5pdGlhbFZlcmNlbCA9XG4gICAgc2FuZGJveFJlY29yZC5wcm92aWRlck1ldGFkYXRhPy5wcm92aWRlciA9PT0gXCJ2ZXJjZWxcIlxuICAgICAgPyBzYW5kYm94UmVjb3JkLnByb3ZpZGVyTWV0YWRhdGFcbiAgICAgIDogbnVsbDtcblxuICB0eXBlIFNhbmRib3hJbnN0YW5jZSA9IEF3YWl0ZWQ8UmV0dXJuVHlwZTx0eXBlb2YgVmVyY2VsU2FuZGJveFNESy5nZXQ+PjtcbiAgbGV0IHNhbmRib3hQcm9taXNlOiBQcm9taXNlPFNhbmRib3hFcnJvciB8IFNhbmRib3hJbnN0YW5jZT4gfCBudWxsID0gbnVsbDtcbiAgbGV0IHJlY292ZXJlZEZyb21TdGFsZSA9IGZhbHNlO1xuICBsZXQgY3JlYXRlZEZyb21TbmFwc2hvdCA9IGZhbHNlO1xuICBsZXQgbmVlZHNTZXR1cFJ1biA9IGZhbHNlO1xuICBjb25zdCBIT01FX0RJUiA9IFwiL2hvbWUvdmVyY2VsLXNhbmRib3hcIjtcblxuICBhc3luYyBmdW5jdGlvbiBwb2xsRm9yU2FuZGJveElkKCk6IFByb21pc2U8U2FuZGJveEVycm9yIHwgc3RyaW5nPiB7XG4gICAgY29uc3QgZGVhZGxpbmUgPSBEYXRlLm5vdygpICsgTE9DS19USU1FT1VUX01TO1xuICAgIHdoaWxlIChEYXRlLm5vdygpIDwgZGVhZGxpbmUpIHtcbiAgICAgIGF3YWl0IG5ldyBQcm9taXNlKChyKSA9PiBzZXRUaW1lb3V0KHIsIExPQ0tfUE9MTF9JTlRFUlZBTF9NUykpO1xuICAgICAgY29uc3QgcmVjb3JkID0gYXdhaXQgc3RvcmFnZS5zYW5kYm94LmdldChpZCk7XG4gICAgICBpZiAocmVjb3JkIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IHJlY29yZC5tZXNzYWdlLCBjYXVzZTogcmVjb3JkIH0pO1xuICAgICAgfVxuICAgICAgY29uc3QgdmVyY2VsU2FuZGJveElkID1cbiAgICAgICAgcmVjb3JkPy5wcm92aWRlck1ldGFkYXRhPy5wcm92aWRlciA9PT0gXCJ2ZXJjZWxcIlxuICAgICAgICAgID8gcmVjb3JkLnByb3ZpZGVyTWV0YWRhdGEuc2FuZGJveElkXG4gICAgICAgICAgOiBudWxsO1xuICAgICAgaWYgKHZlcmNlbFNhbmRib3hJZCkge1xuICAgICAgICByZXR1cm4gdmVyY2VsU2FuZGJveElkO1xuICAgICAgfVxuICAgICAgaWYgKCFyZWNvcmQ/LmFjcXVpcmluZ0xvY2tBdCkge1xuICAgICAgICBjb25zdCBmaW5hbENoZWNrID0gYXdhaXQgc3RvcmFnZS5zYW5kYm94LmdldChpZCk7XG4gICAgICAgIGlmIChmaW5hbENoZWNrIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICByZXR1cm4gbmV3IFNhbmRib3hFcnJvcih7XG4gICAgICAgICAgICByZWFzb246IGZpbmFsQ2hlY2subWVzc2FnZSxcbiAgICAgICAgICAgIGNhdXNlOiBmaW5hbENoZWNrLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGZpbmFsVmVyY2VsU2FuZGJveElkID1cbiAgICAgICAgICBmaW5hbENoZWNrPy5wcm92aWRlck1ldGFkYXRhPy5wcm92aWRlciA9PT0gXCJ2ZXJjZWxcIlxuICAgICAgICAgICAgPyBmaW5hbENoZWNrLnByb3ZpZGVyTWV0YWRhdGEuc2FuZGJveElkXG4gICAgICAgICAgICA6IG51bGw7XG4gICAgICAgIGlmIChmaW5hbFZlcmNlbFNhbmRib3hJZCkge1xuICAgICAgICAgIHJldHVybiBmaW5hbFZlcmNlbFNhbmRib3hJZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZG9HZXRPckNyZWF0ZVNhbmRib3hJZCgpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbmV3IFNhbmRib3hFcnJvcih7XG4gICAgICByZWFzb246IFwiVGltZWQgb3V0IHdhaXRpbmcgZm9yIHNhbmRib3ggY3JlYXRpb24gYnkgYW5vdGhlciBwcm9jZXNzXCIsXG4gICAgfSk7XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBzdGFydExpZmVjeWNsZVdvcmtmbG93KFxuICAgIHZlcmNlbFNhbmRib3hJZDogc3RyaW5nXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghZW5hYmxlTGlmZWN5Y2xlV29ya2Zsb3cpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgbGlmZWN5Y2xlSW5wdXQ6IFNhbmRib3hMaWZlY3ljbGVJbnB1dCA9IHtcbiAgICAgIGlkLFxuICAgICAgdmVyY2VsU2FuZGJveElkLFxuICAgICAgc3RvcmFnZUNvbmZpZyxcbiAgICAgIHJwYyxcbiAgICB9O1xuICAgIGF3YWl0IHN0YXJ0KHNhbmRib3hMaWZlY3ljbGVXb3JrZmxvdywgW3sgaW5wdXQ6IGxpZmVjeWNsZUlucHV0IH1dKS5jYXRjaChcbiAgICAgIC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FbXB0eUJsb2NrU3RhdGVtZW50czogaW50ZW50aW9uYWxseSBpZ25vcmVkIC0gd29ya2Zsb3cgc3RhcnQgaXMgZmlyZS1hbmQtZm9yZ2V0XG4gICAgICAoKSA9PiB7fVxuICAgICk7XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBjcmVhdGVTYW5kYm94RnJvbVNuYXBzaG90KFxuICAgIHNuYXBzaG90SWQ6IHN0cmluZ1xuICApOiBQcm9taXNlPFNhbmRib3hFcnJvciB8IHN0cmluZz4ge1xuICAgIHJldHVybiBhd2FpdCBlcnJvcmUudHJ5QXN5bmMoe1xuICAgICAgdHJ5OiBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHNhbmRib3ggPSBhd2FpdCBWZXJjZWxTYW5kYm94U0RLLmNyZWF0ZSh7XG4gICAgICAgICAgc291cmNlOiB7IHR5cGU6IFwic25hcHNob3RcIiwgc25hcHNob3RJZCB9LFxuICAgICAgICAgIHJlc291cmNlczogeyB2Y3B1cyB9LFxuICAgICAgICAgIHRpbWVvdXQ6IFZFUkNFTF9NQVhfVElNRU9VVF9NUyxcbiAgICAgICAgICBwb3J0cyxcbiAgICAgICAgICBuZXR3b3JrUG9saWN5LFxuICAgICAgICAgIC4uLmdldFRlc3RDcmVkZW50aWFscygpLFxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgYXdhaXQgc3RvcmFnZS5zYW5kYm94LnNldCh7XG4gICAgICAgICAgaWQsXG4gICAgICAgICAgY29uZmlnLFxuICAgICAgICAgIHRhZ3M6IHNhbmRib3hSZWNvcmQudGFncyxcbiAgICAgICAgICBjcmVhdGVkQXQ6IG5vdyxcbiAgICAgICAgICBsYXN0QWN0aXZpdHlBdDogbm93LFxuICAgICAgICAgIGFjcXVpcmluZ0xvY2tJZDogbnVsbCxcbiAgICAgICAgICBhY3F1aXJpbmdMb2NrQXQ6IG51bGwsXG4gICAgICAgICAgcHJvdmlkZXJNZXRhZGF0YToge1xuICAgICAgICAgICAgcHJvdmlkZXI6IFwidmVyY2VsXCIsXG4gICAgICAgICAgICBzYW5kYm94SWQ6IHNhbmRib3guc2FuZGJveElkLFxuICAgICAgICAgICAgc25hcHNob3RJZCxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgICAgYXdhaXQgc3RhcnRMaWZlY3ljbGVXb3JrZmxvdyhzYW5kYm94LnNhbmRib3hJZCk7XG4gICAgICAgIHJldHVybiBzYW5kYm94LnNhbmRib3hJZDtcbiAgICAgIH0sXG4gICAgICBjYXRjaDogKGUpID0+IG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSksXG4gICAgfSk7XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBjcmVhdGVGcmVzaFNhbmRib3goKTogUHJvbWlzZTxTYW5kYm94RXJyb3IgfCBzdHJpbmc+IHtcbiAgICByZXR1cm4gYXdhaXQgZXJyb3JlLnRyeUFzeW5jKHtcbiAgICAgIHRyeTogYXN5bmMgKCkgPT4ge1xuICAgICAgICBjb25zdCBzYW5kYm94ID0gYXdhaXQgVmVyY2VsU2FuZGJveFNESy5jcmVhdGUoe1xuICAgICAgICAgIHJlc291cmNlczogeyB2Y3B1cyB9LFxuICAgICAgICAgIHRpbWVvdXQ6IFZFUkNFTF9NQVhfVElNRU9VVF9NUyxcbiAgICAgICAgICBwb3J0cyxcbiAgICAgICAgICBuZXR3b3JrUG9saWN5LFxuICAgICAgICAgIC4uLmdldFRlc3RDcmVkZW50aWFscygpLFxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgYXdhaXQgc3RvcmFnZS5zYW5kYm94LnNldCh7XG4gICAgICAgICAgaWQsXG4gICAgICAgICAgY29uZmlnLFxuICAgICAgICAgIHRhZ3M6IHNhbmRib3hSZWNvcmQudGFncyxcbiAgICAgICAgICBjcmVhdGVkQXQ6IG5vdyxcbiAgICAgICAgICBsYXN0QWN0aXZpdHlBdDogbm93LFxuICAgICAgICAgIGFjcXVpcmluZ0xvY2tJZDogbnVsbCxcbiAgICAgICAgICBhY3F1aXJpbmdMb2NrQXQ6IG51bGwsXG4gICAgICAgICAgcHJvdmlkZXJNZXRhZGF0YToge1xuICAgICAgICAgICAgcHJvdmlkZXI6IFwidmVyY2VsXCIsXG4gICAgICAgICAgICBzYW5kYm94SWQ6IHNhbmRib3guc2FuZGJveElkLFxuICAgICAgICAgICAgc25hcHNob3RJZDogbnVsbCxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgICAgYXdhaXQgc3RhcnRMaWZlY3ljbGVXb3JrZmxvdyhzYW5kYm94LnNhbmRib3hJZCk7XG4gICAgICAgIHJldHVybiBzYW5kYm94LnNhbmRib3hJZDtcbiAgICAgIH0sXG4gICAgICBjYXRjaDogKGUpID0+IG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSksXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ29yZSBleGVjIGxvZ2ljIGFnYWluc3QgYSByYXcgVmVyY2VsIFNESyBpbnN0YW5jZS5cbiAgICogU2hhcmVkIGJldHdlZW4gdGhlIG1haW4gc2FuZGJveCB3cmFwcGVyIGFuZCB0ZW1wb3Jhcnkgc2V0dXAgc2FuZGJveGVzLlxuICAgKi9cbiAgZnVuY3Rpb24gZXhlY09uSW5zdGFuY2UoXG4gICAgaW5zdGFuY2U6IFNhbmRib3hJbnN0YW5jZSxcbiAgICB7XG4gICAgICBjb21tYW5kLFxuICAgICAgYXJncyxcbiAgICAgIHNpZ25hbCxcbiAgICB9OiB7IGNvbW1hbmQ6IHN0cmluZzsgYXJncz86IHN0cmluZ1tdOyBzaWduYWw/OiBBYm9ydFNpZ25hbCB9XG4gICk6IFByb21pc2U8XG4gICAgfCBTYW5kYm94RXJyb3JcbiAgICB8IHtcbiAgICAgICAgY29tbWFuZElkOiBzdHJpbmc7XG4gICAgICAgIGxvZ3M6ICgpID0+IEFzeW5jSXRlcmFibGU8TG9nRW50cnk+O1xuICAgICAgICByZXN1bHQ6IFByb21pc2U8eyBzdGRvdXQ6IHN0cmluZzsgc3RkZXJyOiBzdHJpbmc7IGV4aXRDb2RlOiBudW1iZXIgfT47XG4gICAgICB9XG4gID4ge1xuICAgIHJldHVybiBlcnJvcmUudHJ5QXN5bmMoe1xuICAgICAgdHJ5OiBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IG91dHB1dCA9IGF3YWl0IGluc3RhbmNlLnJ1bkNvbW1hbmQoe1xuICAgICAgICAgIGN3ZDogSE9NRV9ESVIsXG4gICAgICAgICAgYXJncyxcbiAgICAgICAgICBjbWQ6IGNvbW1hbmQsXG4gICAgICAgICAgc2lnbmFsLFxuICAgICAgICAgIGRldGFjaGVkOiB0cnVlLFxuICAgICAgICB9KTtcblxuICAgICAgICBsZXQgc3Rkb3V0ID0gXCJcIjtcbiAgICAgICAgbGV0IHN0ZGVyciA9IFwiXCI7XG4gICAgICAgIGNvbnN0IGxvZ0J1ZmZlcjogTG9nRW50cnlbXSA9IFtdO1xuICAgICAgICBjb25zdCBzdGF0ZSA9IHtcbiAgICAgICAgICByZXNvbHZlOiBudWxsIGFzICgoKSA9PiB2b2lkKSB8IG51bGwsXG4gICAgICAgICAgY29uc3VtZWQ6IGZhbHNlLFxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IGNvbnN1bWVMb2dzID0gKGFzeW5jICgpID0+IHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgZm9yIGF3YWl0IChjb25zdCBsb2cgb2Ygb3V0cHV0LmxvZ3MoKSkge1xuICAgICAgICAgICAgICBjb25zdCBlbnRyeTogTG9nRW50cnkgPVxuICAgICAgICAgICAgICAgIGxvZy5zdHJlYW0gPT09IFwic3Rkb3V0XCJcbiAgICAgICAgICAgICAgICAgID8geyBzdHJlYW06IFwic3Rkb3V0XCIsIGRhdGE6IGxvZy5kYXRhIH1cbiAgICAgICAgICAgICAgICAgIDogeyBzdHJlYW06IFwic3RkZXJyXCIsIGRhdGE6IGxvZy5kYXRhIH07XG5cbiAgICAgICAgICAgICAgaWYgKGxvZy5zdHJlYW0gPT09IFwic3Rkb3V0XCIpIHtcbiAgICAgICAgICAgICAgICBzdGRvdXQgKz0gbG9nLmRhdGE7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc3RkZXJyICs9IGxvZy5kYXRhO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgbG9nQnVmZmVyLnB1c2goZW50cnkpO1xuICAgICAgICAgICAgICBzdGF0ZS5yZXNvbHZlPy4oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIC8vIFNhbmRib3ggbWF5IGhhdmUgYmVlbiBzdG9wcGVkIC0gbG9ncyBlbmRwb2ludCByZXR1cm5zIDQyMlxuICAgICAgICAgIH1cbiAgICAgICAgICBzdGF0ZS5jb25zdW1lZCA9IHRydWU7XG4gICAgICAgICAgc3RhdGUucmVzb2x2ZT8uKCk7XG4gICAgICAgIH0pKCk7XG5cbiAgICAgICAgYXN5bmMgZnVuY3Rpb24qIGxvZ3MoKTogQXN5bmNJdGVyYWJsZTxMb2dFbnRyeT4ge1xuICAgICAgICAgIGxldCBpbmRleCA9IDA7XG4gICAgICAgICAgd2hpbGUgKCFzdGF0ZS5jb25zdW1lZCB8fCBpbmRleCA8IGxvZ0J1ZmZlci5sZW5ndGgpIHtcbiAgICAgICAgICAgIGlmIChpbmRleCA8IGxvZ0J1ZmZlci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgeWllbGQgbG9nQnVmZmVyW2luZGV4KytdO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgYXdhaXQgbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUpID0+IHtcbiAgICAgICAgICAgICAgICBzdGF0ZS5yZXNvbHZlID0gcmVzb2x2ZTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIHN0YXRlLnJlc29sdmUgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGNvbnN1bWVMb2dzLnRoZW4oYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBmaW5pc2hlZCA9IGF3YWl0IG91dHB1dC53YWl0KCk7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBzdGRvdXQsXG4gICAgICAgICAgICAgIHN0ZGVycixcbiAgICAgICAgICAgICAgZXhpdENvZGU6IGZpbmlzaGVkLmV4aXRDb2RlLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBpZiAoaXNTYW5kYm94R29uZUVycm9yKGUpKSB7XG4gICAgICAgICAgICAgIHJldHVybiB7IHN0ZG91dCwgc3RkZXJyLCBleGl0Q29kZTogMSB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiB7IGNvbW1hbmRJZDogb3V0cHV0LmNtZElkLCBsb2dzLCByZXN1bHQgfTtcbiAgICAgIH0sXG4gICAgICBjYXRjaDogKGUpID0+IG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSksXG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiByZWFkRmlsZU9uSW5zdGFuY2UoXG4gICAgaW5zdGFuY2U6IFNhbmRib3hJbnN0YW5jZSxcbiAgICB7IHBhdGggfTogeyBwYXRoOiBzdHJpbmcgfVxuICApOiBQcm9taXNlPFNhbmRib3hFcnJvciB8IEJ1ZmZlciB8IG51bGw+IHtcbiAgICByZXR1cm4gZXJyb3JlLnRyeUFzeW5jKHtcbiAgICAgIHRyeTogKCkgPT4gaW5zdGFuY2UucmVhZEZpbGVUb0J1ZmZlcih7IHBhdGgsIGN3ZDogSE9NRV9ESVIgfSksXG4gICAgICBjYXRjaDogKGUpID0+IG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSksXG4gICAgfSk7XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiB3cml0ZUZpbGVzT25JbnN0YW5jZShcbiAgICBpbnN0YW5jZTogU2FuZGJveEluc3RhbmNlLFxuICAgIG9wdHM6IHtcbiAgICAgIGZpbGVzOiB7IHBhdGg6IHN0cmluZzsgY29udGVudDogc3RyaW5nIHwgQnVmZmVyIH1bXTtcbiAgICAgIGRlc3RQYXRoOiBzdHJpbmc7XG4gICAgfVxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB7IGZpbGVzLCBkZXN0UGF0aCB9ID0gb3B0cztcbiAgICBpZiAoZmlsZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgbmF0aXZlRmlsZXMgPSBmaWxlcy5tYXAoKGZpbGUpID0+IHtcbiAgICAgIGNvbnN0IGZpbGVQYXRoID0gcGF0aC5wb3NpeC5qb2luKGRlc3RQYXRoLCBmaWxlLnBhdGgpO1xuICAgICAgY29uc3QgYWJzb2x1dGVQYXRoID0gcGF0aC5wb3NpeC5pc0Fic29sdXRlKGZpbGVQYXRoKVxuICAgICAgICA/IGZpbGVQYXRoXG4gICAgICAgIDogcGF0aC5wb3NpeC5qb2luKEhPTUVfRElSLCBmaWxlUGF0aCk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBwYXRoOiBhYnNvbHV0ZVBhdGgsXG4gICAgICAgIGNvbnRlbnQ6XG4gICAgICAgICAgdHlwZW9mIGZpbGUuY29udGVudCA9PT0gXCJzdHJpbmdcIlxuICAgICAgICAgICAgPyBCdWZmZXIuZnJvbShmaWxlLmNvbnRlbnQpXG4gICAgICAgICAgICA6IGZpbGUuY29udGVudCxcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICBhd2FpdCBpbnN0YW5jZS53cml0ZUZpbGVzKG5hdGl2ZUZpbGVzKTtcblxuICAgIGNvbnN0IHNoZWxsU2NyaXB0cyA9IG5hdGl2ZUZpbGVzLmZpbHRlcigoZikgPT4gZi5wYXRoLmVuZHNXaXRoKFwiLnNoXCIpKTtcbiAgICBpZiAoc2hlbGxTY3JpcHRzLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IGNobW9kUmVzdWx0ID0gYXdhaXQgZXhlY09uSW5zdGFuY2UoaW5zdGFuY2UsIHtcbiAgICAgICAgY29tbWFuZDogXCJjaG1vZFwiLFxuICAgICAgICBhcmdzOiBbXCIreFwiLCAuLi5zaGVsbFNjcmlwdHMubWFwKChmKSA9PiBmLnBhdGgpXSxcbiAgICAgIH0pO1xuICAgICAgaWYgKGNobW9kUmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgY2htb2RSZXN1bHQ7XG4gICAgICB9XG4gICAgICBhd2FpdCBjaG1vZFJlc3VsdC5yZXN1bHQ7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBtaW5pbWFsIFNhbmRib3ggd3JhcHBlciBhcm91bmQgYSByYXcgVmVyY2VsIFNESyBpbnN0YW5jZS5cbiAgICogVXNlZCBmb3IgcnVubmluZyBzZXR1cC5ydW4oKSBvbiBhIHRlbXBvcmFyeSBzYW5kYm94IGZvciBzbmFwc2hvdCBjcmVhdGlvbi5cbiAgICovXG4gIGZ1bmN0aW9uIGNyZWF0ZVRlbXBTYW5kYm94KGluc3RhbmNlOiBTYW5kYm94SW5zdGFuY2UpOiBTYW5kYm94IHtcbiAgICBjb25zdCB0ZW1wU2FuZGJveDogU2FuZGJveCA9IHtcbiAgICAgIGlkOiBgX19zZXR1cF90ZW1wXyR7RGF0ZS5ub3coKX1gLFxuICAgICAgY29uZmlnLFxuICAgICAgZXhlYzogKG9wdHMpID0+IGV4ZWNPbkluc3RhbmNlKGluc3RhbmNlLCBvcHRzKSxcbiAgICAgIHJlYWRGaWxlOiAob3B0cykgPT4gcmVhZEZpbGVPbkluc3RhbmNlKGluc3RhbmNlLCBvcHRzKSxcbiAgICAgIGdldERvbWFpbjogKCkgPT5cbiAgICAgICAgUHJvbWlzZS5yZXNvbHZlKFxuICAgICAgICAgIG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IFwibm90IGF2YWlsYWJsZSBkdXJpbmcgc2V0dXBcIiB9KVxuICAgICAgICApLFxuICAgICAga2lsbDogKCkgPT5cbiAgICAgICAgUHJvbWlzZS5yZXNvbHZlKFxuICAgICAgICAgIG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IFwibm90IGF2YWlsYWJsZSBkdXJpbmcgc2V0dXBcIiB9KVxuICAgICAgICApLFxuICAgICAgd3JpdGVGaWxlczogKG9wdHMpID0+IHdyaXRlRmlsZXNPbkluc3RhbmNlKGluc3RhbmNlLCBvcHRzKSxcbiAgICAgIHVwZGF0ZU5ldHdvcmtQb2xpY3k6IChwb2xpY3kpID0+XG4gICAgICAgIGVycm9yZS50cnlBc3luYyh7XG4gICAgICAgICAgdHJ5OiAoKSA9PiBpbnN0YW5jZS51cGRhdGVOZXR3b3JrUG9saWN5KHBvbGljeSksXG4gICAgICAgICAgY2F0Y2g6IChlKSA9PiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pLFxuICAgICAgICB9KSxcbiAgICAgIHRhZzoge1xuICAgICAgICBsaXN0OiBhc3luYyAoKSA9PiAoe30pIGFzIFRUYWdzLFxuICAgICAgICBnZXQ6IGFzeW5jICgpID0+IHVuZGVmaW5lZCxcbiAgICAgICAgc2V0OiBhc3luYyAoKSA9PiB1bmRlZmluZWQsXG4gICAgICAgIHNldE1hbnk6IGFzeW5jICgpID0+IHVuZGVmaW5lZCxcbiAgICAgIH0sXG4gICAgfTtcbiAgICByZXR1cm4gdGVtcFNhbmRib3g7XG4gIH1cblxuICAvKipcbiAgICogUG9sbHMgZm9yIGEgc2V0dXAgc25hcHNob3QgdG8gYmVjb21lIGF2YWlsYWJsZS4gUmV0dXJucyB0aGUgc25hcHNob3RJZFxuICAgKiBpZiBvbmUgYXBwZWFycyBiZWZvcmUgdGhlIGxvY2sgdGltZXMgb3V0LCBvciBudWxsIGlmIGl0IGRvZXNuJ3QuXG4gICAqL1xuICBhc3luYyBmdW5jdGlvbiBwb2xsRm9yU2V0dXBTbmFwc2hvdChrZXk6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xuICAgIGNvbnN0IGRlYWRsaW5lID0gRGF0ZS5ub3coKSArIExPQ0tfVElNRU9VVF9NUztcbiAgICB3aGlsZSAoRGF0ZS5ub3coKSA8IGRlYWRsaW5lKSB7XG4gICAgICBhd2FpdCBuZXcgUHJvbWlzZSgocikgPT4gc2V0VGltZW91dChyLCBMT0NLX1BPTExfSU5URVJWQUxfTVMpKTtcbiAgICAgIGNvbnN0IHJlY29yZCA9IGF3YWl0IHN0b3JhZ2Uuc2V0dXAuZ2V0KGtleSk7XG4gICAgICBpZiAocmVjb3JkIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICBpZiAocmVjb3JkPy5zbmFwc2hvdElkKSB7XG4gICAgICAgIHJldHVybiByZWNvcmQuc25hcHNob3RJZDtcbiAgICAgIH1cbiAgICAgIC8vIExvY2sgcmVsZWFzZWQgYnV0IG5vIHNuYXBzaG90IFx1MjAxNCBjcmVhdGlvbiBmYWlsZWRcbiAgICAgIGlmICghcmVjb3JkPy5hY3F1aXJpbmdMb2NrSWQpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBiYWNrZ3JvdW5kIHNhbmRib3gsIHJ1bnMgc2V0dXAsIHNuYXBzaG90cyBpdCwgYW5kIHN0b3JlcyB0aGVcbiAgICogc25hcHNob3QgSUQuIFVzZXMgYXRvbWljIGxvY2tpbmcgdG8gZW5zdXJlIG9ubHkgb25lIHByb2Nlc3MgY3JlYXRlcyBpdC5cbiAgICpcbiAgICogQHBhcmFtIGZvcmNlIC0gU2tpcCB0aGUgXCJzbmFwc2hvdCBhbHJlYWR5IGV4aXN0c1wiIGVhcmx5IGV4aXQuIFVzZWQgd2hlblxuICAgKiAgIHRoZSBjYWxsZXIga25vd3MgdGhlIGV4aXN0aW5nIHNuYXBzaG90IGlzIHN0YWxlL2V4cGlyZWQuXG4gICAqL1xuICBhc3luYyBmdW5jdGlvbiBjcmVhdGVTZXR1cFNuYXBzaG90KG9wdHM/OiB7XG4gICAgZm9yY2U/OiBib29sZWFuO1xuICB9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCFzZXR1cCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBzZXR1cEtleSA9IHNldHVwLmtleTtcblxuICAgIC8vIENoZWNrIGlmIHNuYXBzaG90IGFscmVhZHkgZXhpc3RzIChmYXN0IHBhdGggXHUyMDE0IGF2b2lkcyBsb2NrIGF0dGVtcHQpXG4gICAgaWYgKCFvcHRzPy5mb3JjZSkge1xuICAgICAgY29uc3QgZXhpc3RpbmcgPSBhd2FpdCBzdG9yYWdlLnNldHVwLmdldChzZXR1cEtleSk7XG4gICAgICBpZiAoIShleGlzdGluZyBpbnN0YW5jZW9mIEVycm9yKSAmJiBleGlzdGluZz8uc25hcHNob3RJZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQXRvbWljYWxseSBhY3F1aXJlIGxvY2sgKGhhbmRsZXMgYWN0aXZlLWxvY2sgZGV0ZWN0aW9uIGludGVybmFsbHkpXG4gICAgZGVidWcoYFtzYW5kYm94OnNldHVwXSBhY3F1aXJpbmcgbG9jayBmb3Igc2V0dXAga2V5IFwiJHtzZXR1cEtleX1cImApO1xuICAgIGNvbnN0IGxvY2tJZCA9IGNyeXB0by5yYW5kb21VVUlEKCk7XG4gICAgY29uc3QgbG9ja2VkID0gYXdhaXQgc3RvcmFnZS5zZXR1cC5hY3F1aXJlTG9jayhcbiAgICAgIHNldHVwS2V5LFxuICAgICAgbG9ja0lkLFxuICAgICAgTE9DS19USU1FT1VUX01TXG4gICAgKTtcbiAgICBpZiAobG9ja2VkIGluc3RhbmNlb2YgRXJyb3IgfHwgIWxvY2tlZCkge1xuICAgICAgZGVidWcoXG4gICAgICAgIGBbc2FuZGJveDpzZXR1cF0gbG9jayBub3QgYWNxdWlyZWQgZm9yIGtleSBcIiR7c2V0dXBLZXl9XCIgKGFub3RoZXIgcHJvY2VzcyBob2xkcyBpdClgXG4gICAgICApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFJlLWNoZWNrOiBhbm90aGVyIHdvcmtlciBtYXkgaGF2ZSBjcmVhdGVkIHRoZSBzbmFwc2hvdCBiZXR3ZWVuIG91clxuICAgIC8vIHByZS1jaGVjayBhbmQgbG9jayBhY3F1aXNpdGlvbi4gSWYgc28sIHNraXAgdW5sZXNzIGZvcmNlIChzdGFsZSBzbmFwc2hvdCkuXG4gICAgaWYgKCFvcHRzPy5mb3JjZSAmJiBsb2NrZWQuc25hcHNob3RJZCkge1xuICAgICAgZGVidWcoXG4gICAgICAgIGBbc2FuZGJveDpzZXR1cF0gc25hcHNob3QgYWxyZWFkeSBleGlzdHMgYWZ0ZXIgbG9jayBmb3Iga2V5IFwiJHtzZXR1cEtleX1cIiwgc2tpcHBpbmdgXG4gICAgICApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGxldCB0ZW1wSW5zdGFuY2U6IEF3YWl0ZWQ8XG4gICAgICBSZXR1cm5UeXBlPHR5cGVvZiBWZXJjZWxTYW5kYm94U0RLLmNyZWF0ZT5cbiAgICA+IHwgbnVsbCA9IG51bGw7XG4gICAgdHJ5IHtcbiAgICAgIC8vIENyZWF0ZSBhIHRlbXBvcmFyeSBzYW5kYm94IGZvciBzbmFwc2hvdHRpbmcuXG4gICAgICBkZWJ1ZyhcbiAgICAgICAgYFtzYW5kYm94OnNldHVwXSBjcmVhdGluZyB0ZW1wIHNhbmRib3ggZm9yIHNuYXBzaG90IChrZXk9XCIke3NldHVwS2V5fVwiKWBcbiAgICAgICk7XG4gICAgICB0ZW1wSW5zdGFuY2UgPSBhd2FpdCBWZXJjZWxTYW5kYm94U0RLLmNyZWF0ZSh7XG4gICAgICAgIHJlc291cmNlczogeyB2Y3B1cyB9LFxuICAgICAgICB0aW1lb3V0OiBWRVJDRUxfTUFYX1RJTUVPVVRfTVMsXG4gICAgICAgIHBvcnRzLFxuICAgICAgICBuZXR3b3JrUG9saWN5LFxuICAgICAgICAuLi5nZXRUZXN0Q3JlZGVudGlhbHMoKSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB0ZW1wU2FuZGJveCA9IGNyZWF0ZVRlbXBTYW5kYm94KFxuICAgICAgICB0ZW1wSW5zdGFuY2UgYXMgdW5rbm93biBhcyBTYW5kYm94SW5zdGFuY2VcbiAgICAgICk7XG4gICAgICBhd2FpdCBzZXR1cC5ydW4odGVtcFNhbmRib3gpO1xuICAgICAgZGVidWcoXG4gICAgICAgIGBbc2FuZGJveDpzZXR1cF0gc2V0dXAucnVuIGNvbXBsZXRlLCBzbmFwc2hvdHRpbmcgKGtleT1cIiR7c2V0dXBLZXl9XCIpYFxuICAgICAgKTtcbiAgICAgIGNvbnN0IHNuYXBzaG90ID0gYXdhaXQgdGVtcEluc3RhbmNlLnNuYXBzaG90KCk7XG5cbiAgICAgIGF3YWl0IHN0b3JhZ2Uuc2V0dXAuc2V0KHtcbiAgICAgICAga2V5OiBzZXR1cEtleSxcbiAgICAgICAgc25hcHNob3RJZDogc25hcHNob3Quc25hcHNob3RJZCxcbiAgICAgICAgY3JlYXRlZEF0OiBsb2NrZWQuY3JlYXRlZEF0LFxuICAgICAgICBsYXN0VXNlZEF0OiBudWxsLFxuICAgICAgICBhY3F1aXJpbmdMb2NrSWQ6IG51bGwsXG4gICAgICAgIGFjcXVpcmluZ0xvY2tBdDogbnVsbCxcbiAgICAgIH0pO1xuICAgICAgZGVidWcoXG4gICAgICAgIGBbc2FuZGJveDpzZXR1cF0gc25hcHNob3Qgc3RvcmVkOiAke3NuYXBzaG90LnNuYXBzaG90SWR9IChrZXk9XCIke3NldHVwS2V5fVwiKWBcbiAgICAgICk7XG5cbiAgICAgIC8vIFN0b3AgdGhlIHRlbXAgc2FuZGJveCBcdTIwMTQgbm8gbG9uZ2VyIG5lZWRlZCBhZnRlciBzbmFwc2hvdHRpbmdcbiAgICAgIGF3YWl0IHRlbXBJbnN0YW5jZS5zdG9wKCkuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBjb25zb2xlLmVycm9yKFxuICAgICAgICBgW3NhbmRib3g6c2V0dXBdIGZhaWxlZCB0byBjcmVhdGUgc2V0dXAgc25hcHNob3QgKGtleT1cIiR7c2V0dXBLZXl9XCIpOmAsXG4gICAgICAgIGVcbiAgICAgICk7XG4gICAgICAvLyBTdG9wIHRoZSB0ZW1wIHNhbmRib3ggb24gZmFpbHVyZVxuICAgICAgaWYgKHRlbXBJbnN0YW5jZSkge1xuICAgICAgICBhd2FpdCB0ZW1wSW5zdGFuY2Uuc3RvcCgpLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgICB9XG4gICAgICAvLyBDbGVhbiB1cCBsb2NrIG9uIGZhaWx1cmVcbiAgICAgIGF3YWl0IHN0b3JhZ2Uuc2V0dXBcbiAgICAgICAgLnNldCh7XG4gICAgICAgICAga2V5OiBzZXR1cEtleSxcbiAgICAgICAgICBzbmFwc2hvdElkOiBudWxsLFxuICAgICAgICAgIGNyZWF0ZWRBdDogbG9ja2VkLmNyZWF0ZWRBdCxcbiAgICAgICAgICBsYXN0VXNlZEF0OiBudWxsLFxuICAgICAgICAgIGFjcXVpcmluZ0xvY2tJZDogbnVsbCxcbiAgICAgICAgICBhY3F1aXJpbmdMb2NrQXQ6IG51bGwsXG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIGRvR2V0T3JDcmVhdGVTYW5kYm94SWQoKTogUHJvbWlzZTxTYW5kYm94RXJyb3IgfCBzdHJpbmc+IHtcbiAgICBpZiAoaW5pdGlhbFZlcmNlbD8uc2FuZGJveElkICYmICFyZWNvdmVyZWRGcm9tU3RhbGUpIHtcbiAgICAgIHJldHVybiBpbml0aWFsVmVyY2VsLnNhbmRib3hJZDtcbiAgICB9XG5cbiAgICBjb25zdCBleGlzdGluZyA9IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5nZXQoaWQpO1xuICAgIGlmIChleGlzdGluZyBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICBpZiAoZXhpc3RpbmcgaW5zdGFuY2VvZiBTYW5kYm94Tm90Rm91bmRFcnJvcikge1xuICAgICAgICAvLyBTYW5kYm94IGRvZXNuJ3QgZXhpc3QgeWV0LCBjb250aW51ZSB3aXRoIGNyZWF0aW9uXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogZXhpc3RpbmcubWVzc2FnZSwgY2F1c2U6IGV4aXN0aW5nIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGV4aXN0aW5nUmVjb3JkID1cbiAgICAgIGV4aXN0aW5nIGluc3RhbmNlb2YgU2FuZGJveE5vdEZvdW5kRXJyb3IgPyBudWxsIDogZXhpc3Rpbmc7XG4gICAgY29uc3QgZXhpc3RpbmdWZXJjZWwgPVxuICAgICAgZXhpc3RpbmdSZWNvcmQ/LnByb3ZpZGVyTWV0YWRhdGE/LnByb3ZpZGVyID09PSBcInZlcmNlbFwiXG4gICAgICAgID8gZXhpc3RpbmdSZWNvcmQucHJvdmlkZXJNZXRhZGF0YVxuICAgICAgICA6IG51bGw7XG5cbiAgICBpZiAoZXhpc3RpbmdWZXJjZWw/LnNhbmRib3hJZCkge1xuICAgICAgcmV0dXJuIGV4aXN0aW5nVmVyY2VsLnNhbmRib3hJZDtcbiAgICB9XG5cbiAgICBjb25zdCBoYXNBY3RpdmVMb2NrID1cbiAgICAgIGV4aXN0aW5nUmVjb3JkPy5hY3F1aXJpbmdMb2NrSWQgJiZcbiAgICAgIGV4aXN0aW5nUmVjb3JkLmFjcXVpcmluZ0xvY2tBdCAmJlxuICAgICAgRGF0ZS5ub3coKSAtIGV4aXN0aW5nUmVjb3JkLmFjcXVpcmluZ0xvY2tBdCA8IExPQ0tfVElNRU9VVF9NUztcblxuICAgIGlmIChoYXNBY3RpdmVMb2NrKSB7XG4gICAgICByZXR1cm4gcG9sbEZvclNhbmRib3hJZCgpO1xuICAgIH1cblxuICAgIGNvbnN0IGxvY2tJZCA9IGNyeXB0by5yYW5kb21VVUlEKCk7XG4gICAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgICBjb25zdCBsb2NrZWQgPSBhd2FpdCBzdG9yYWdlLnNhbmRib3guYWNxdWlyZUxvY2soXG4gICAgICB7XG4gICAgICAgIGlkLFxuICAgICAgICBjb25maWcsXG4gICAgICAgIHRhZ3M6IGV4aXN0aW5nUmVjb3JkPy50YWdzID8/IHNhbmRib3hSZWNvcmQudGFncyxcbiAgICAgICAgY3JlYXRlZEF0OiBleGlzdGluZ1JlY29yZD8uY3JlYXRlZEF0ID8/IHNhbmRib3hSZWNvcmQuY3JlYXRlZEF0LFxuICAgICAgICBsYXN0QWN0aXZpdHlBdDpcbiAgICAgICAgICBleGlzdGluZ1JlY29yZD8ubGFzdEFjdGl2aXR5QXQgPz8gc2FuZGJveFJlY29yZC5sYXN0QWN0aXZpdHlBdCxcbiAgICAgICAgYWNxdWlyaW5nTG9ja0lkOiBsb2NrSWQsXG4gICAgICAgIGFjcXVpcmluZ0xvY2tBdDogbm93LFxuICAgICAgICBwcm92aWRlck1ldGFkYXRhOiB7XG4gICAgICAgICAgcHJvdmlkZXI6IFwidmVyY2VsXCIsXG4gICAgICAgICAgc2FuZGJveElkOiBudWxsLFxuICAgICAgICAgIHNuYXBzaG90SWQ6XG4gICAgICAgICAgICBleGlzdGluZ1ZlcmNlbD8uc25hcHNob3RJZCA/PyBpbml0aWFsVmVyY2VsPy5zbmFwc2hvdElkID8/IG51bGwsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgTE9DS19USU1FT1VUX01TXG4gICAgKTtcblxuICAgIGlmIChsb2NrZWQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgcmV0dXJuIG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IGxvY2tlZC5tZXNzYWdlLCBjYXVzZTogbG9ja2VkIH0pO1xuICAgIH1cbiAgICBpZiAoIWxvY2tlZCkge1xuICAgICAgcmV0dXJuIHBvbGxGb3JTYW5kYm94SWQoKTtcbiAgICB9XG5cbiAgICAvLyBDYXB0dXJlIHRoZSBsb2NrZWQgcmVjb3JkIGZvciB1c2UgaW4gdGhlIHJlbGVhc2UgaGVscGVyLlxuICAgIC8vIFRTIGNhbid0IG5hcnJvdyBgbG9ja2VkYCBpbnNpZGUgbmVzdGVkIGZ1bmN0aW9ucywgc28gd2UgYmluZCBpdCBoZXJlLlxuICAgIGNvbnN0IGxvY2tlZFJlY29yZCA9IGxvY2tlZDtcblxuICAgIC8vIFJlbGVhc2UgdGhlIHNhbmRib3ggbG9jayBzbyBvdGhlciB3b3JrZXJzIGNhbiByZXRyeSBxdWlja2x5XG4gICAgLy8gaW5zdGVhZCBvZiB3YWl0aW5nIGZvciBsb2NrIHRpbWVvdXQuXG4gICAgYXN5bmMgZnVuY3Rpb24gcmVsZWFzZVNhbmRib3hMb2NrKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgYXdhaXQgc3RvcmFnZS5zYW5kYm94XG4gICAgICAgIC51cGRhdGUoe1xuICAgICAgICAgIGlkOiBsb2NrZWRSZWNvcmQuaWQsXG4gICAgICAgICAgYWNxdWlyaW5nTG9ja0lkOiBudWxsLFxuICAgICAgICAgIGFjcXVpcmluZ0xvY2tBdDogbnVsbCxcbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgfVxuXG4gICAgLy8gUmUtY2hlY2sgYWZ0ZXIgbG9jazogYW5vdGhlciB3b3JrZXIgbWF5IGhhdmUgY3JlYXRlZCB0aGUgc2FuZGJveFxuICAgIC8vIGJldHdlZW4gb3VyIGluaXRpYWwgY2hlY2sgYW5kIGxvY2sgYWNxdWlzaXRpb24uXG4gICAgY29uc3QgbG9ja2VkVmVyY2VsID1cbiAgICAgIGxvY2tlZFJlY29yZC5wcm92aWRlck1ldGFkYXRhPy5wcm92aWRlciA9PT0gXCJ2ZXJjZWxcIlxuICAgICAgICA/IGxvY2tlZFJlY29yZC5wcm92aWRlck1ldGFkYXRhXG4gICAgICAgIDogbnVsbDtcbiAgICBpZiAobG9ja2VkVmVyY2VsPy5zYW5kYm94SWQpIHtcbiAgICAgIGF3YWl0IHJlbGVhc2VTYW5kYm94TG9jaygpO1xuICAgICAgcmV0dXJuIGxvY2tlZFZlcmNlbC5zYW5kYm94SWQ7XG4gICAgfVxuXG4gICAgY29uc3Qgc25hcHNob3RJZCA9XG4gICAgICBsb2NrZWRWZXJjZWw/LnNuYXBzaG90SWQgPz9cbiAgICAgIGluaXRpYWxWZXJjZWw/LnNuYXBzaG90SWQgPz9cbiAgICAgIGNvbmZpZy5saWZlY3ljbGU/LnNuYXBzaG90SWQ7XG4gICAgaWYgKHNuYXBzaG90SWQpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNyZWF0ZVNhbmRib3hGcm9tU25hcHNob3Qoc25hcHNob3RJZCk7XG4gICAgICBpZiAoIShyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikpIHtcbiAgICAgICAgY3JlYXRlZEZyb21TbmFwc2hvdCA9IHRydWU7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIHNldHVwIHNuYXBzaG90XG4gICAgaWYgKHNldHVwKSB7XG4gICAgICBsZXQgZm9yY2VSZWNyZWF0ZVNuYXBzaG90ID0gZmFsc2U7XG4gICAgICBjb25zdCBzZXR1cFJlY29yZCA9IGF3YWl0IHN0b3JhZ2Uuc2V0dXAuZ2V0KHNldHVwLmtleSk7XG4gICAgICBpZiAoIShzZXR1cFJlY29yZCBpbnN0YW5jZW9mIEVycm9yKSAmJiBzZXR1cFJlY29yZCkge1xuICAgICAgICBpZiAoc2V0dXBSZWNvcmQuc25hcHNob3RJZCkge1xuICAgICAgICAgIGRlYnVnKFxuICAgICAgICAgICAgYFtzYW5kYm94OnNldHVwXSBmb3VuZCBzZXR1cCBzbmFwc2hvdCAke3NldHVwUmVjb3JkLnNuYXBzaG90SWR9IGZvciBrZXkgXCIke3NldHVwLmtleX1cImBcbiAgICAgICAgICApO1xuICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNyZWF0ZVNhbmRib3hGcm9tU25hcHNob3QoXG4gICAgICAgICAgICBzZXR1cFJlY29yZC5zbmFwc2hvdElkXG4gICAgICAgICAgKTtcbiAgICAgICAgICBpZiAoIShyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikpIHtcbiAgICAgICAgICAgIGNyZWF0ZWRGcm9tU25hcHNob3QgPSB0cnVlO1xuICAgICAgICAgICAgLy8gVXBkYXRlIGxhc3RVc2VkQXQgKGZpcmUtYW5kLWZvcmdldClcbiAgICAgICAgICAgIHN0b3JhZ2Uuc2V0dXBcbiAgICAgICAgICAgICAgLnNldCh7XG4gICAgICAgICAgICAgICAgLi4uc2V0dXBSZWNvcmQsXG4gICAgICAgICAgICAgICAgbGFzdFVzZWRBdDogRGF0ZS5ub3coKSxcbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBTbmFwc2hvdCBpcyBzdGFsZS9leHBpcmVkIFx1MjAxNCBmb3JjZSBiYWNrZ3JvdW5kIHRvIG92ZXJ3cml0ZSBpdFxuICAgICAgICAgIGRlYnVnKFxuICAgICAgICAgICAgYFtzYW5kYm94OnNldHVwXSBzbmFwc2hvdCAke3NldHVwUmVjb3JkLnNuYXBzaG90SWR9IGZhaWxlZCAoZXhwaXJlZD8pLCB3aWxsIHJlY3JlYXRlYFxuICAgICAgICAgICk7XG4gICAgICAgICAgZm9yY2VSZWNyZWF0ZVNuYXBzaG90ID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICBzZXR1cFJlY29yZC5hY3F1aXJpbmdMb2NrSWQgJiZcbiAgICAgICAgICBzZXR1cFJlY29yZC5hY3F1aXJpbmdMb2NrQXQgJiZcbiAgICAgICAgICBEYXRlLm5vdygpIC0gc2V0dXBSZWNvcmQuYWNxdWlyaW5nTG9ja0F0IDwgTE9DS19USU1FT1VUX01TXG4gICAgICAgICkge1xuICAgICAgICAgIC8vIEFub3RoZXIgcHJvY2VzcyBpcyBjcmVhdGluZyB0aGUgc2V0dXAgc25hcHNob3QgXHUyMDE0IHdhaXQgZm9yIGl0XG4gICAgICAgICAgZGVidWcoXG4gICAgICAgICAgICBgW3NhbmRib3g6c2V0dXBdIHNuYXBzaG90IGluIHByb2dyZXNzIGZvciBrZXkgXCIke3NldHVwLmtleX1cIiwgd2FpdGluZy4uLmBcbiAgICAgICAgICApO1xuICAgICAgICAgIGNvbnN0IHNuYXBzaG90SWQgPSBhd2FpdCBwb2xsRm9yU2V0dXBTbmFwc2hvdChzZXR1cC5rZXkpO1xuICAgICAgICAgIGlmIChzbmFwc2hvdElkKSB7XG4gICAgICAgICAgICBkZWJ1ZyhcbiAgICAgICAgICAgICAgYFtzYW5kYm94OnNldHVwXSBzbmFwc2hvdCByZWFkeTogJHtzbmFwc2hvdElkfSBmb3Iga2V5IFwiJHtzZXR1cC5rZXl9XCJgXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY3JlYXRlU2FuZGJveEZyb21TbmFwc2hvdChzbmFwc2hvdElkKTtcbiAgICAgICAgICAgIGlmICghKHJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSkge1xuICAgICAgICAgICAgICBjcmVhdGVkRnJvbVNuYXBzaG90ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gUG9sbCBmYWlsZWQgb3Igc25hcHNob3QgY3JlYXRpb24gZmFpbGVkIFx1MjAxNCBmYWxsIHRocm91Z2ggdG8gY29sZCBwYXRoXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIE5vIHNldHVwIHNuYXBzaG90IGF2YWlsYWJsZSBcdTIwMTQgY3JlYXRlIGZyZXNoIGFuZCBydW4gc2V0dXAgbGF0ZXIuXG4gICAgICAvLyBLaWNrIG9mZiBiYWNrZ3JvdW5kIHNuYXBzaG90IGltbWVkaWF0ZWx5IHNvIGl0IHJ1bnMgaW4gcGFyYWxsZWxcbiAgICAgIC8vIHdpdGggc2V0dXAucnVuIG9uIHRoZSBzZXNzaW9uIHNhbmRib3guXG4gICAgICBkZWJ1ZyhcbiAgICAgICAgYFtzYW5kYm94OnNldHVwXSBubyBzbmFwc2hvdCBmb3Iga2V5IFwiJHtzZXR1cC5rZXl9XCIsIHdpbGwgcnVuIHNldHVwIG9uIHRoaXMgc2FuZGJveGBcbiAgICAgICk7XG4gICAgICBuZWVkc1NldHVwUnVuID0gdHJ1ZTtcbiAgICAgIGNyZWF0ZVNldHVwU25hcHNob3QoeyBmb3JjZTogZm9yY2VSZWNyZWF0ZVNuYXBzaG90IH0pLmNhdGNoKChlKSA9PiB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgICAgXCJbc2FuZGJveDpzZXR1cF0gZmFpbGVkIHRvIGNyZWF0ZSBiYWNrZ3JvdW5kIHNuYXBzaG90OlwiLFxuICAgICAgICAgIGVcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGNvbnN0IGZyZXNoUmVzdWx0ID0gYXdhaXQgY3JlYXRlRnJlc2hTYW5kYm94KCk7XG4gICAgaWYgKGZyZXNoUmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIGF3YWl0IHJlbGVhc2VTYW5kYm94TG9jaygpO1xuICAgIH1cbiAgICByZXR1cm4gZnJlc2hSZXN1bHQ7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRPckNyZWF0ZVNhbmRib3hJZCgpOiBQcm9taXNlPFNhbmRib3hFcnJvciB8IHN0cmluZz4ge1xuICAgIGNvbnN0IGNhY2hlZCA9IGNyZWF0ZVByb21pc2VzLmdldChpZCk7XG4gICAgaWYgKGNhY2hlZCkge1xuICAgICAgcmV0dXJuIGNhY2hlZDtcbiAgICB9XG5cbiAgICBjb25zdCBwcm9taXNlID0gZG9HZXRPckNyZWF0ZVNhbmRib3hJZCgpLmZpbmFsbHkoKCkgPT4ge1xuICAgICAgY3JlYXRlUHJvbWlzZXMuZGVsZXRlKGlkKTtcbiAgICB9KTtcbiAgICBjcmVhdGVQcm9taXNlcy5zZXQoaWQsIHByb21pc2UpO1xuICAgIHJldHVybiBwcm9taXNlO1xuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gZG9HZXRTYW5kYm94KCk6IFByb21pc2U8U2FuZGJveEVycm9yIHwgU2FuZGJveEluc3RhbmNlPiB7XG4gICAgY29uc3QgdmVyY2VsU2FuZGJveElkID0gYXdhaXQgZ2V0T3JDcmVhdGVTYW5kYm94SWQoKTtcbiAgICBpZiAodmVyY2VsU2FuZGJveElkIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIHJldHVybiB2ZXJjZWxTYW5kYm94SWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGVycm9yZS50cnlBc3luYyh7XG4gICAgICB0cnk6ICgpID0+XG4gICAgICAgIFZlcmNlbFNhbmRib3hTREsuZ2V0KHtcbiAgICAgICAgICBzYW5kYm94SWQ6IHZlcmNlbFNhbmRib3hJZCxcbiAgICAgICAgICAuLi5nZXRUZXN0Q3JlZGVudGlhbHMoKSxcbiAgICAgICAgfSksXG4gICAgICBjYXRjaDogKGUpID0+IG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSksXG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRTYW5kYm94KCk6IFByb21pc2U8U2FuZGJveEVycm9yIHwgU2FuZGJveEluc3RhbmNlPiB7XG4gICAgaWYgKCFzYW5kYm94UHJvbWlzZSkge1xuICAgICAgc2FuZGJveFByb21pc2UgPSBkb0dldFNhbmRib3goKTtcbiAgICB9XG4gICAgcmV0dXJuIHNhbmRib3hQcm9taXNlO1xuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gcmVjb3ZlckZyb21TdGFsZVNhbmRib3goKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgc2FuZGJveFByb21pc2UgPSBudWxsO1xuICAgIHJlY292ZXJlZEZyb21TdGFsZSA9IHRydWU7XG5cbiAgICBjb25zdCBleGlzdGluZyA9IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5nZXQoaWQpO1xuICAgIGlmIChleGlzdGluZyBpbnN0YW5jZW9mIEVycm9yIHx8ICFleGlzdGluZykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGV4aXN0aW5nVmVyY2VsID1cbiAgICAgIGV4aXN0aW5nLnByb3ZpZGVyTWV0YWRhdGE/LnByb3ZpZGVyID09PSBcInZlcmNlbFwiXG4gICAgICAgID8gZXhpc3RpbmcucHJvdmlkZXJNZXRhZGF0YVxuICAgICAgICA6IG51bGw7XG5cbiAgICBpZiAoZXhpc3RpbmdWZXJjZWw/LnNhbmRib3hJZCkge1xuICAgICAgYXdhaXQgc3RvcmFnZS5zYW5kYm94LnVwZGF0ZSh7XG4gICAgICAgIGlkOiBleGlzdGluZy5pZCxcbiAgICAgICAgYWNxdWlyaW5nTG9ja0lkOiBudWxsLFxuICAgICAgICBhY3F1aXJpbmdMb2NrQXQ6IG51bGwsXG4gICAgICAgIHByb3ZpZGVyTWV0YWRhdGE6IHtcbiAgICAgICAgICBwcm92aWRlcjogXCJ2ZXJjZWxcIixcbiAgICAgICAgICBzYW5kYm94SWQ6IG51bGwsXG4gICAgICAgICAgc25hcHNob3RJZDogZXhpc3RpbmdWZXJjZWwuc25hcHNob3RJZCxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIHVwZGF0ZUxhc3RBY3Rpdml0eSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgIGNvbnN0IGxhc3RTZW50ID0gbGFzdEFjdGl2aXR5U2VudC5nZXQoaWQpO1xuICAgIGlmIChsYXN0U2VudCAmJiBub3cgLSBsYXN0U2VudCA8IEFDVElWSVRZX1RIUk9UVExFX01TKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGxhc3RBY3Rpdml0eVNlbnQuc2V0KGlkLCBub3cpO1xuXG4gICAgY29uc3QgZXhpc3RpbmcgPSBhd2FpdCBzdG9yYWdlLnNhbmRib3guZ2V0KGlkKTtcbiAgICBpZiAoZXhpc3RpbmcgaW5zdGFuY2VvZiBFcnJvciB8fCAhZXhpc3RpbmcpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgZXhpc3RpbmdWZXJjZWwgPVxuICAgICAgZXhpc3RpbmcucHJvdmlkZXJNZXRhZGF0YT8ucHJvdmlkZXIgPT09IFwidmVyY2VsXCJcbiAgICAgICAgPyBleGlzdGluZy5wcm92aWRlck1ldGFkYXRhXG4gICAgICAgIDogbnVsbDtcbiAgICBhd2FpdCBzdG9yYWdlLnNhbmRib3gudXBkYXRlKHtcbiAgICAgIGlkOiBleGlzdGluZy5pZCxcbiAgICAgIGxhc3RBY3Rpdml0eUF0OiBub3csXG4gICAgICBhY3F1aXJpbmdMb2NrSWQ6IG51bGwsXG4gICAgICBhY3F1aXJpbmdMb2NrQXQ6IG51bGwsXG4gICAgICBwcm92aWRlck1ldGFkYXRhOiBleGlzdGluZ1ZlcmNlbCA/PyB7XG4gICAgICAgIHByb3ZpZGVyOiBcInZlcmNlbFwiLFxuICAgICAgICBzYW5kYm94SWQ6IG51bGwsXG4gICAgICAgIHNuYXBzaG90SWQ6IG51bGwsXG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgY29uc3QgbGlmZWN5Y2xlOiBTYW5kYm94TGlmZWN5Y2xlID0ge1xuICAgIHN0YXJ0OiBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzYW5kYm94ID0gYXdhaXQgZ2V0U2FuZGJveCgpO1xuICAgICAgaWYgKHNhbmRib3ggaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICByZXR1cm4gc2FuZGJveDtcbiAgICAgIH1cbiAgICAgIGF3YWl0IHVwZGF0ZUxhc3RBY3Rpdml0eSgpO1xuICAgICAgcmV0dXJuIHNhbmRib3guc3RhdHVzIGFzIFNhbmRib3hTdGF0dXM7XG4gICAgfSxcblxuICAgIHNuYXBzaG90OiBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzYW5kYm94ID0gYXdhaXQgZ2V0U2FuZGJveCgpO1xuICAgICAgaWYgKHNhbmRib3ggaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICByZXR1cm4gc2FuZGJveDtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGVycm9yZS50cnlBc3luYyh7XG4gICAgICAgIHRyeTogYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHNuYXBzaG90ID0gYXdhaXQgc2FuZGJveC5zbmFwc2hvdCgpO1xuICAgICAgICAgIGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC51cGRhdGUoe1xuICAgICAgICAgICAgaWQsXG4gICAgICAgICAgICBhY3F1aXJpbmdMb2NrSWQ6IG51bGwsXG4gICAgICAgICAgICBhY3F1aXJpbmdMb2NrQXQ6IG51bGwsXG4gICAgICAgICAgICBwcm92aWRlck1ldGFkYXRhOiB7XG4gICAgICAgICAgICAgIHByb3ZpZGVyOiBcInZlcmNlbFwiLFxuICAgICAgICAgICAgICBzYW5kYm94SWQ6IG51bGwsXG4gICAgICAgICAgICAgIHNuYXBzaG90SWQ6IHNuYXBzaG90LnNuYXBzaG90SWQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHJldHVybiB7IHNuYXBzaG90SWQ6IHNuYXBzaG90LnNuYXBzaG90SWQgfTtcbiAgICAgICAgfSxcbiAgICAgICAgY2F0Y2g6IChlKSA9PiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pLFxuICAgICAgfSk7XG4gICAgfSxcblxuICAgIHN0b3A6IGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHNhbmRib3ggPSBhd2FpdCBnZXRTYW5kYm94KCk7XG4gICAgICBpZiAoc2FuZGJveCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHJldHVybiBzYW5kYm94O1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gZXJyb3JlLnRyeUFzeW5jKHtcbiAgICAgICAgdHJ5OiBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgYXdhaXQgc2FuZGJveC5zdG9wKCk7XG4gICAgICAgICAgYXdhaXQgc3RvcmFnZS5zYW5kYm94LnVwZGF0ZSh7XG4gICAgICAgICAgICBpZCxcbiAgICAgICAgICAgIGFjcXVpcmluZ0xvY2tJZDogbnVsbCxcbiAgICAgICAgICAgIGFjcXVpcmluZ0xvY2tBdDogbnVsbCxcbiAgICAgICAgICAgIHByb3ZpZGVyTWV0YWRhdGE6IHtcbiAgICAgICAgICAgICAgcHJvdmlkZXI6IFwidmVyY2VsXCIsXG4gICAgICAgICAgICAgIHNhbmRib3hJZDogbnVsbCxcbiAgICAgICAgICAgICAgc25hcHNob3RJZDogbnVsbCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfSxcbiAgICAgICAgY2F0Y2g6IChlKSA9PiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pLFxuICAgICAgfSk7XG4gICAgfSxcblxuICAgIGdldFN0YXR1czogYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qgc2FuZGJveCA9IGF3YWl0IGdldFNhbmRib3goKTtcbiAgICAgIGlmIChzYW5kYm94IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIHNhbmRib3g7XG4gICAgICB9XG4gICAgICByZXR1cm4gc2FuZGJveC5zdGF0dXMgYXMgU2FuZGJveFN0YXR1cztcbiAgICB9LFxuXG4gICAgZ2V0Q3JlYXRlZEF0OiBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzYW5kYm94ID0gYXdhaXQgZ2V0U2FuZGJveCgpO1xuICAgICAgaWYgKHNhbmRib3ggaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICByZXR1cm4gc2FuZGJveDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBzYW5kYm94LmNyZWF0ZWRBdDtcbiAgICB9LFxuXG4gICAgZ2V0UmVtYWluaW5nVGltZW91dDogYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qgc2FuZGJveCA9IGF3YWl0IGdldFNhbmRib3goKTtcbiAgICAgIGlmIChzYW5kYm94IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIHNhbmRib3g7XG4gICAgICB9XG4gICAgICByZXR1cm4gc2FuZGJveC50aW1lb3V0O1xuICAgIH0sXG4gIH07XG5cbiAgYXN5bmMgZnVuY3Rpb24gZG9FeGVjKG9wdHM6IHtcbiAgICBjb21tYW5kOiBzdHJpbmc7XG4gICAgYXJncz86IHN0cmluZ1tdO1xuICAgIHNpZ25hbD86IEFib3J0U2lnbmFsO1xuICB9KSB7XG4gICAgY29uc3QgaW5zdGFuY2UgPSBhd2FpdCBnZXRTYW5kYm94KCk7XG4gICAgaWYgKGluc3RhbmNlIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIHJldHVybiBpbnN0YW5jZTtcbiAgICB9XG5cbiAgICBjb25zdCB1cGRhdGVQcm9taXNlID0gdXBkYXRlTGFzdEFjdGl2aXR5KCk7XG4gICAgY29uc3QgZXhlY1Jlc3VsdCA9IGF3YWl0IGV4ZWNPbkluc3RhbmNlKGluc3RhbmNlLCBvcHRzKTtcbiAgICBhd2FpdCB1cGRhdGVQcm9taXNlO1xuICAgIHJldHVybiBleGVjUmVzdWx0O1xuICB9XG5cbiAgY29uc3Qgc2FuZGJveDogU2FuZGJveDxUVGFncz4gJiB7XG4gICAgX29uUmVhZHk/OiBQcm9taXNlPHZvaWQ+O1xuICAgIF9zZXR1cE1ldGE/OiBQcm9taXNlPFNhbmRib3hTZXR1cE1ldGE+O1xuICB9ID0ge1xuICAgIGlkLFxuICAgIGNvbmZpZyxcbiAgICBleGVjOiBhc3luYyAob3B0cykgPT4ge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZG9FeGVjKG9wdHMpO1xuXG4gICAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgU2FuZGJveEVycm9yICYmIGlzU2FuZGJveEdvbmVFcnJvcihyZXN1bHQuY2F1c2UpKSB7XG4gICAgICAgIGF3YWl0IHJlY292ZXJGcm9tU3RhbGVTYW5kYm94KCk7XG4gICAgICAgIHJldHVybiBhd2FpdCBkb0V4ZWMob3B0cyk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSxcblxuICAgIGdldERvbWFpbjogYXN5bmMgKHBvcnQpID0+IHtcbiAgICAgIGNvbnN0IHNhbmRib3ggPSBhd2FpdCBnZXRTYW5kYm94KCk7XG4gICAgICBpZiAoc2FuZGJveCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHJldHVybiBzYW5kYm94O1xuICAgICAgfVxuXG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gc2FuZGJveC5kb21haW4ocG9ydCk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHJldHVybiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pO1xuICAgICAgfVxuICAgIH0sXG5cbiAgICBraWxsOiBhc3luYyAoeyBjb21tYW5kSWQsIHN0b3JhZ2U6IGNtZFN0b3JhZ2UgfSkgPT4ge1xuICAgICAgY29uc3QgaW5zdGFuY2UgPSBhd2FpdCBnZXRTYW5kYm94KCk7XG4gICAgICBpZiAoaW5zdGFuY2UgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICByZXR1cm4gaW5zdGFuY2U7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNtZCA9IGF3YWl0IGNtZFN0b3JhZ2UuY29tbWFuZC5nZXQoY29tbWFuZElkKTtcbiAgICAgIGlmIChjbWQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICByZXR1cm4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogY21kLm1lc3NhZ2UsIGNhdXNlOiBjbWQgfSk7XG4gICAgICB9XG4gICAgICBpZiAoY21kICYmIGNtZC5zdGF0dXMgPT09IFwicnVubmluZ1wiKSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNtZFN0b3JhZ2UuY29tbWFuZC5zZXQoe1xuICAgICAgICAgIC4uLmNtZCxcbiAgICAgICAgICBzdGF0dXM6IFwia2lsbGVkXCIsXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICByZXR1cm4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogcmVzdWx0Lm1lc3NhZ2UsIGNhdXNlOiByZXN1bHQgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfSxcblxuICAgIHJlYWRGaWxlOiBhc3luYyAob3B0cykgPT4ge1xuICAgICAgY29uc3QgaW5zdGFuY2UgPSBhd2FpdCBnZXRTYW5kYm94KCk7XG4gICAgICBpZiAoaW5zdGFuY2UgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICByZXR1cm4gaW5zdGFuY2U7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVhZEZpbGVPbkluc3RhbmNlKGluc3RhbmNlLCBvcHRzKTtcbiAgICB9LFxuXG4gICAgd3JpdGVGaWxlczogYXN5bmMgKG9wdHMpID0+IHtcbiAgICAgIGNvbnN0IGluc3RhbmNlID0gYXdhaXQgZ2V0U2FuZGJveCgpO1xuICAgICAgaWYgKGluc3RhbmNlIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgaW5zdGFuY2U7XG4gICAgICB9XG4gICAgICByZXR1cm4gd3JpdGVGaWxlc09uSW5zdGFuY2UoaW5zdGFuY2UsIG9wdHMpO1xuICAgIH0sXG5cbiAgICBsaWZlY3ljbGUsXG5cbiAgICB1cGRhdGVOZXR3b3JrUG9saWN5OiBhc3luYyAocG9saWN5KSA9PiB7XG4gICAgICBjb25zdCBpbnN0YW5jZSA9IGF3YWl0IGdldFNhbmRib3goKTtcbiAgICAgIGlmIChpbnN0YW5jZSBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHJldHVybiBpbnN0YW5jZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBlcnJvcmUudHJ5QXN5bmMoe1xuICAgICAgICB0cnk6ICgpID0+IGluc3RhbmNlLnVwZGF0ZU5ldHdvcmtQb2xpY3kocG9saWN5KSxcbiAgICAgICAgY2F0Y2g6IChlKSA9PiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pLFxuICAgICAgfSk7XG4gICAgfSxcblxuICAgIHRhZzoge1xuICAgICAgbGlzdDogYXN5bmMgKCkgPT4ge1xuICAgICAgICBjb25zdCBzYW5kYm94UmVjb3JkID0gYXdhaXQgc3RvcmFnZS5zYW5kYm94LmdldChpZCk7XG4gICAgICAgIGlmIChzYW5kYm94UmVjb3JkIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICByZXR1cm4gc2FuZGJveFJlY29yZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gKHNhbmRib3hSZWNvcmQudGFncyA/PyB7fSkgYXMgVFRhZ3M7XG4gICAgICB9LFxuICAgICAgZ2V0OiBhc3luYyAoa2V5OiBzdHJpbmcpID0+IHtcbiAgICAgICAgY29uc3Qgc2FuZGJveFJlY29yZCA9IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5nZXQoaWQpO1xuICAgICAgICBpZiAoc2FuZGJveFJlY29yZCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIHNhbmRib3hSZWNvcmQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNhbmRib3hSZWNvcmQudGFncz8uW2tleSBhcyBzdHJpbmddIGFzXG4gICAgICAgICAgfCBUVGFnc1t0eXBlb2Yga2V5XVxuICAgICAgICAgIHwgdW5kZWZpbmVkO1xuICAgICAgfSxcbiAgICAgIHNldDogYXN5bmMgKGtleTogc3RyaW5nLCB2YWx1ZTogdW5rbm93bikgPT4ge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzdG9yYWdlLnNhbmRib3gudGFnLnNldCh7XG4gICAgICAgICAgc2FuZGJveElkOiBpZCxcbiAgICAgICAgICB0YWdzOiB7IFtrZXldOiB2YWx1ZSB9IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfSxcbiAgICAgIHNldE1hbnk6IGFzeW5jICh0YWdzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikgPT4ge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzdG9yYWdlLnNhbmRib3gudGFnLnNldCh7XG4gICAgICAgICAgc2FuZGJveElkOiBpZCxcbiAgICAgICAgICB0YWdzOiB0YWdzIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfSxcbiAgICB9LFxuICB9O1xuXG4gIGxldCBvblJlYWR5UHJvbWlzZTogUHJvbWlzZTx2b2lkPiA9IFByb21pc2UucmVzb2x2ZSgpO1xuICBsZXQgc2V0dXBNZXRhUHJvbWlzZTogUHJvbWlzZTxTYW5kYm94U2V0dXBNZXRhPiA9IFByb21pc2UucmVzb2x2ZSh7XG4gICAgbmVlZHNTZXR1cFJ1bjogZmFsc2UsXG4gICAgY3JlYXRlZEZyb21TbmFwc2hvdDogZmFsc2UsXG4gIH0pO1xuXG4gIGlmIChjb25maWcubGlmZWN5Y2xlPy5hdXRvU3RhcnQgIT09IGZhbHNlKSB7XG4gICAgc2FuZGJveFByb21pc2UgPSBkb0dldFNhbmRib3goKTtcblxuICAgIC8vIFJlc29sdmUgc2V0dXAgbWV0YWRhdGEgYXMgc29vbiBhcyB0aGUgc2FuZGJveCBpbnN0YW5jZSBpcyByZWFkeVxuICAgIC8vIChiZWZvcmUgX29uUmVhZHkgcnVucyBzZXR1cCkuIFRoZSB3b3JrZmxvdyByZWFkcyB0aGlzIHRvIGNob29zZSB0aGUgc3RhdHVzIGluZGljYXRvci5cbiAgICBzZXR1cE1ldGFQcm9taXNlID0gc2FuZGJveFByb21pc2UudGhlbigoKSA9PiAoe1xuICAgICAgbmVlZHNTZXR1cFJ1bixcbiAgICAgIGNyZWF0ZWRGcm9tU25hcHNob3QsXG4gICAgfSkpO1xuXG4gICAgLy8gQWZ0ZXIgc2FuZGJveCBpbnN0YW5jZSBpcyByZWFkeSwgcnVuIHNldHVwIGFuZC9vciBvblJlc3RhcnQuXG4gICAgLy8gc2FuZGJveFByb21pc2UgaXMgYWxyZWFkeSByZXNvbHZlZCBieSB0aGUgdGltZSAudGhlbigpIHJ1bnMsXG4gICAgLy8gc28gc2V0dXAucnVuIC8gb25SZXN0YXJ0IGNhbGxpbmcgc2FuZGJveC5leGVjKCkgd29uJ3QgZGVhZGxvY2suXG4gICAgb25SZWFkeVByb21pc2UgPSBzYW5kYm94UHJvbWlzZS50aGVuKGFzeW5jIChpbnN0YW5jZSkgPT4ge1xuICAgICAgaWYgKGluc3RhbmNlIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAobmVlZHNTZXR1cFJ1biAmJiBzZXR1cCkge1xuICAgICAgICBkZWJ1ZyhcbiAgICAgICAgICBgW3NhbmRib3g6c2V0dXBdIHJ1bm5pbmcgc2V0dXAucnVuIG9uIHNlc3Npb24gc2FuZGJveCAoa2V5PVwiJHtzZXR1cC5rZXl9XCIpYFxuICAgICAgICApO1xuICAgICAgICBhd2FpdCBzZXR1cC5ydW4oc2FuZGJveCk7XG4gICAgICAgIGRlYnVnKFwiW3NhbmRib3g6c2V0dXBdIHNldHVwLnJ1biBjb21wbGV0ZSBvbiBzZXNzaW9uIHNhbmRib3hcIik7XG4gICAgICB9XG5cbiAgICAgIGlmIChjcmVhdGVkRnJvbVNuYXBzaG90ICYmIG9uUmVzdGFydCkge1xuICAgICAgICBkZWJ1ZyhcIltzYW5kYm94OnNldHVwXSBydW5uaW5nIG9uUmVzdGFydCAoY3JlYXRlZCBmcm9tIHNuYXBzaG90KVwiKTtcbiAgICAgICAgYXdhaXQgb25SZXN0YXJ0KHNhbmRib3gpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgc2FuZGJveC5fb25SZWFkeSA9IG9uUmVhZHlQcm9taXNlO1xuICBzYW5kYm94Ll9zZXR1cE1ldGEgPSBzZXR1cE1ldGFQcm9taXNlO1xuICByZXR1cm4gc2FuZGJveDtcbn07XG4iLCAiaW1wb3J0IHR5cGUgeyBUYWdzU2NoZW1hIH0gZnJvbSBcIi4uL2luZGV4XCI7XG5pbXBvcnQgdHlwZSB7IFJwY0ZuLCBTYW5kYm94UmVjb3JkLCBTdG9yYWdlLCBTdG9yYWdlQ29uZmlnIH0gZnJvbSBcIi4uL3N0b3JhZ2VcIjtcbmltcG9ydCB7IGRlYnVnIH0gZnJvbSBcIi4uL3V0aWxzL2RlYnVnXCI7XG5pbXBvcnQgeyBsb2NhbFNhbmRib3ggfSBmcm9tIFwiLi9iaW5kaW5ncy9sb2NhbFwiO1xuaW1wb3J0IHsgdmVyY2VsU2FuZGJveCB9IGZyb20gXCIuL2JpbmRpbmdzL3ZlcmNlbFwiO1xuaW1wb3J0IHR5cGUgeyBPblJlc3RhcnQsIFNhbmRib3gsIFNhbmRib3hTZXR1cCB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbi8qKlxuICogTWV0YWRhdGEgYWJvdXQgaG93IHRoZSBzYW5kYm94IHdhcyBzZXQgdXAuXG4gKiBVc2VkIGJ5IHRoZSB3b3JrZmxvdyB0byBlbWl0IHRoZSBjb3JyZWN0IHN0YXR1cyBpbmRpY2F0b3IuXG4gKiBSZXR1cm5lZCBhcyBhIHByb21pc2UgYmVjYXVzZSB0aGUgbWV0YWRhdGEgaXMgZGV0ZXJtaW5lZCBhc3luY2hyb25vdXNseVxuICogZHVyaW5nIHNhbmRib3ggY3JlYXRpb24sIGJlZm9yZSBfb25SZWFkeSBydW5zIHNldHVwLlxuICovXG5leHBvcnQgdHlwZSBTYW5kYm94U2V0dXBNZXRhID0ge1xuICAvKiogV2hldGhlciBzZXR1cC5ydW4oKSBuZWVkcyB0byBleGVjdXRlIChjb2xkIHN0YXJ0LCBubyBzbmFwc2hvdCkuICovXG4gIG5lZWRzU2V0dXBSdW46IGJvb2xlYW47XG4gIC8qKiBXaGV0aGVyIHRoZSBzYW5kYm94IHdhcyBjcmVhdGVkIGZyb20gYSBzbmFwc2hvdC4gKi9cbiAgY3JlYXRlZEZyb21TbmFwc2hvdDogYm9vbGVhbjtcbn07XG5cbnR5cGUgU2FuZGJveFdpdGhNZXRhPFRUYWdzIGV4dGVuZHMgVGFnc1NjaGVtYSA9IFRhZ3NTY2hlbWE+ID0gU2FuZGJveDxUVGFncz4gJiB7XG4gIF9vblJlYWR5PzogUHJvbWlzZTx2b2lkPjtcbiAgX3NldHVwTWV0YT86IFByb21pc2U8U2FuZGJveFNldHVwTWV0YT47XG59O1xuXG4vKipcbiAqIE1vZHVsZS1sZXZlbCBjYWNoZSBmb3Igc2FuZGJveCBpbnN0YW5jZXMga2V5ZWQgYnkgc2FuZGJveCByZWNvcmQgSUQuXG4gKlxuICogQ2FjaGVzIGFsbCBzYW5kYm94IGluc3RhbmNlcyBzbyB0aGF0IHRoZSB3b3JrZmxvdyAod2hpY2ggY2FsbHMgZ2V0U2FuZGJveFxuICogd2l0aG91dCBzZXR1cC9vblJlc3RhcnQpIHJldXNlcyB0aGUgc2FtZSBpbnN0YW5jZSBjcmVhdGVkIGR1cmluZyBzZXNzaW9uKCksXG4gKiBpbmNsdWRpbmcgaXRzIF9vblJlYWR5IHByb21pc2UgYW5kIHNldHVwIG1ldGFkYXRhLlxuICovXG5jb25zdCBzYW5kYm94Q2FjaGUgPSBuZXcgTWFwPHN0cmluZywgU2FuZGJveFdpdGhNZXRhPigpO1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0U2FuZGJveDxUVGFncyBleHRlbmRzIFRhZ3NTY2hlbWEgPSBUYWdzU2NoZW1hPih7XG4gIHNhbmRib3hSZWNvcmQsXG4gIHN0b3JhZ2VDb25maWcsXG4gIHN0b3JhZ2UsXG4gIHJwYyxcbiAgZW5hYmxlTGlmZWN5Y2xlV29ya2Zsb3cgPSB0cnVlLFxuICBzZXR1cCxcbiAgb25SZXN0YXJ0LFxufToge1xuICBzdG9yYWdlQ29uZmlnOiBTdG9yYWdlQ29uZmlnO1xuICBzYW5kYm94UmVjb3JkOiBTYW5kYm94UmVjb3JkO1xuICBzdG9yYWdlOiBTdG9yYWdlO1xuICBycGM6IFJwY0ZuO1xuICBlbmFibGVMaWZlY3ljbGVXb3JrZmxvdz86IGJvb2xlYW47XG4gIHNldHVwPzogU2FuZGJveFNldHVwO1xuICBvblJlc3RhcnQ/OiBPblJlc3RhcnQ7XG59KTogU2FuZGJveFdpdGhNZXRhPFRUYWdzPiB7XG4gIGNvbnN0IGNhY2hlZCA9IHNhbmRib3hDYWNoZS5nZXQoc2FuZGJveFJlY29yZC5pZCk7XG4gIGlmIChjYWNoZWQpIHtcbiAgICBkZWJ1ZyhcIltnZXRTYW5kYm94XSBjYWNoZSBoaXQgZm9yXCIsIHNhbmRib3hSZWNvcmQuaWQpO1xuICAgIHJldHVybiBjYWNoZWQgYXMgU2FuZGJveFdpdGhNZXRhPFRUYWdzPjtcbiAgfVxuXG4gIGNvbnN0IHNieCA9IGNyZWF0ZVNhbmRib3g8VFRhZ3M+KHtcbiAgICBzYW5kYm94UmVjb3JkLFxuICAgIHN0b3JhZ2VDb25maWcsXG4gICAgc3RvcmFnZSxcbiAgICBycGMsXG4gICAgZW5hYmxlTGlmZWN5Y2xlV29ya2Zsb3csXG4gICAgc2V0dXAsXG4gICAgb25SZXN0YXJ0LFxuICB9KTtcblxuICBzYW5kYm94Q2FjaGUuc2V0KHNhbmRib3hSZWNvcmQuaWQsIHNieCBhcyBTYW5kYm94V2l0aE1ldGEpO1xuXG4gIHJldHVybiBzYng7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVNhbmRib3g8VFRhZ3MgZXh0ZW5kcyBUYWdzU2NoZW1hID0gVGFnc1NjaGVtYT4oe1xuICBzYW5kYm94UmVjb3JkLFxuICBzdG9yYWdlQ29uZmlnLFxuICBzdG9yYWdlLFxuICBycGMsXG4gIGVuYWJsZUxpZmVjeWNsZVdvcmtmbG93ID0gdHJ1ZSxcbiAgc2V0dXAsXG4gIG9uUmVzdGFydCxcbn06IHtcbiAgc3RvcmFnZUNvbmZpZzogU3RvcmFnZUNvbmZpZztcbiAgc2FuZGJveFJlY29yZDogU2FuZGJveFJlY29yZDtcbiAgc3RvcmFnZTogU3RvcmFnZTtcbiAgcnBjOiBScGNGbjtcbiAgZW5hYmxlTGlmZWN5Y2xlV29ya2Zsb3c/OiBib29sZWFuO1xuICBzZXR1cD86IFNhbmRib3hTZXR1cDtcbiAgb25SZXN0YXJ0PzogT25SZXN0YXJ0O1xufSk6IFNhbmRib3hXaXRoTWV0YTxUVGFncz4ge1xuICBsZXQgc2J4OiBTYW5kYm94V2l0aE1ldGE8VFRhZ3M+O1xuXG4gIHN3aXRjaCAoc2FuZGJveFJlY29yZC5jb25maWcudHlwZSkge1xuICAgIGNhc2UgXCJsb2NhbFwiOlxuICAgICAgc2J4ID0gbG9jYWxTYW5kYm94PFRUYWdzPih7XG4gICAgICAgIHNhbmRib3hSZWNvcmQ6IHNhbmRib3hSZWNvcmQgYXMgU2FuZGJveFJlY29yZCAmIHtcbiAgICAgICAgICBjb25maWc6IHsgdHlwZTogXCJsb2NhbFwiIH07XG4gICAgICAgIH0sXG4gICAgICAgIHN0b3JhZ2UsXG4gICAgICAgIHNldHVwLFxuICAgICAgICBvblJlc3RhcnQsXG4gICAgICB9KTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgXCJ2ZXJjZWxcIjpcbiAgICAgIHNieCA9IHZlcmNlbFNhbmRib3g8VFRhZ3M+KHtcbiAgICAgICAgc2FuZGJveFJlY29yZDogc2FuZGJveFJlY29yZCBhcyBTYW5kYm94UmVjb3JkICYge1xuICAgICAgICAgIGNvbmZpZzogeyB0eXBlOiBcInZlcmNlbFwiIH07XG4gICAgICAgIH0sXG4gICAgICAgIHN0b3JhZ2VDb25maWcsXG4gICAgICAgIHN0b3JhZ2UsXG4gICAgICAgIHJwYyxcbiAgICAgICAgZW5hYmxlTGlmZWN5Y2xlV29ya2Zsb3csXG4gICAgICAgIHNldHVwLFxuICAgICAgICBvblJlc3RhcnQsXG4gICAgICB9KTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgXCJjdXN0b21cIjpcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkN1c3RvbSBzYW5kYm94ZXMgYXJlIG5vdCBzdXBwb3J0ZWRcIik7XG4gICAgZGVmYXVsdDpcbiAgICAgIHNhbmRib3hSZWNvcmQuY29uZmlnIHNhdGlzZmllcyBuZXZlcjtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFVua25vd24gc2FuZGJveCB0eXBlOiAke1xuICAgICAgICAgIC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogLlxuICAgICAgICAgIChzYW5kYm94UmVjb3JkLmNvbmZpZyBhcyBhbnkpLnR5cGVcbiAgICAgICAgfWBcbiAgICAgICk7XG4gIH1cblxuICAvLyBEb24ndCBhd2FpdCBfb25SZWFkeSBoZXJlIFx1MjAxNCBsZXQgdGhlIHdvcmtmbG93IGF3YWl0IGl0IHNvIGl0IGNhbiBlbWl0XG4gIC8vIHN0YXR1cyBpbmRpY2F0b3JzIG92ZXIgdGhlIHN0cmVhbSB3aGlsZSBzZXR1cCBydW5zLlxuICAvLyBJbnN0ZWFkLCB3cmFwIHNhbmRib3ggbWV0aG9kcyBzbyBhbnkgb3BlcmF0aW9uIG9uIHRoZSBzYW5kYm94IGltcGxpY2l0bHlcbiAgLy8gd2FpdHMgZm9yIHNldHVwIHRvIGNvbXBsZXRlLiBXZSByZXR1cm4gYSBORVcgb2JqZWN0IHNvIHRoYXQgc2V0dXAucnVuKCksXG4gIC8vIHdoaWNoIGhvbGRzIHRoZSBvcmlnaW5hbCBgc2J4YCB2aWEgY2xvc3VyZSwgY2FsbHMgdW53cmFwcGVkIG1ldGhvZHMgYW5kXG4gIC8vIGF2b2lkcyBhIGRlYWRsb2NrLlxuICBpZiAoIXNieC5fb25SZWFkeSkge1xuICAgIHJldHVybiBzYng7XG4gIH1cblxuICBjb25zdCBvblJlYWR5ID0gc2J4Ll9vblJlYWR5O1xuICByZXR1cm4ge1xuICAgIC4uLnNieCxcbiAgICBleGVjOiBhc3luYyAob3B0cykgPT4ge1xuICAgICAgYXdhaXQgb25SZWFkeTtcbiAgICAgIHJldHVybiBzYnguZXhlYyhvcHRzKTtcbiAgICB9LFxuICAgIGdldERvbWFpbjogYXN5bmMgKHBvcnQpID0+IHtcbiAgICAgIGF3YWl0IG9uUmVhZHk7XG4gICAgICByZXR1cm4gc2J4LmdldERvbWFpbihwb3J0KTtcbiAgICB9LFxuICAgIHJlYWRGaWxlOiBhc3luYyAob3B0cykgPT4ge1xuICAgICAgYXdhaXQgb25SZWFkeTtcbiAgICAgIHJldHVybiBzYngucmVhZEZpbGUob3B0cyk7XG4gICAgfSxcbiAgICB3cml0ZUZpbGVzOiBhc3luYyAob3B0cykgPT4ge1xuICAgICAgYXdhaXQgb25SZWFkeTtcbiAgICAgIHJldHVybiBzYngud3JpdGVGaWxlcyhvcHRzKTtcbiAgICB9LFxuICB9O1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7O0FBQUEsSUFBTSxVQUNKLFFBQVEsSUFBSSxnQkFBZ0IsT0FBTyxRQUFRLElBQUksZ0JBQWdCO0FBRTFELFNBQVMsU0FBUyxNQUFpQjtBQUN4QyxNQUFJLFNBQVM7QUFDWCxZQUFRLElBQUksR0FBRyxJQUFJO0FBQUEsRUFDckI7QUFDRjs7O0FDTkEsU0FBUyxhQUFhO0FBQ3RCLFlBQVksUUFBUTtBQUNwQixZQUFZQSxXQUFVO0FBQ3RCLFlBQVksWUFBWTtBQUN4QixTQUFTLFlBQVk7OztBQ0xyQixZQUFZLFVBQVU7QUFJdEIsSUFBTSxjQUFjO0FBQ3BCLElBQU0sZ0JBQWdCO0FBT3RCLGVBQWUsWUFDYixTQUNBLE1BQ0EsWUFDK0Q7QUFDL0QsV0FBUyxVQUFVLEtBQUssV0FBVztBQUNqQyxVQUFNLGFBQWEsTUFBTSxRQUFRLEtBQUssSUFBSTtBQUMxQyxRQUFJLHNCQUFzQixPQUFPO0FBQy9CLFlBQU07QUFBQSxJQUNSO0FBQ0EsVUFBTSxTQUFTLE1BQU0sV0FBVztBQUNoQyxR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QUFBLFFBQ0E7QUFBQSxRQUNBO0FBQUEsUUFDQTtBQUFBLFFBQ0E7QUFBQSxRQUNBO0FBQUEsTUFDRixDQUFDO0FBQ0Q7QUFBQSxJQUNGLEtBQUs7QUFDSCxZQUFNLElBQUksTUFBTSxvQ0FBb0M7QUFBQSxJQUN0RDtBQUNFLG9CQUFjO0FBQ2QsWUFBTSxJQUFJO0FBQUEsUUFDUjtBQUFBLFFBRUcsY0FBYyxPQUFlLElBQ2hDO0FBQUEsTUFDRjtBQUFBLEVBQ0o7QUFRQSxNQUFJLENBQUMsSUFBSSxVQUFVO0FBQ2pCLFdBQU87QUFBQSxFQUNUO0FBRUEsUUFBTSxVQUFVLElBQUk7QUFDcEIsU0FBTztBQUFBLElBQ0wsR0FBRztBQUFBLElBQ0gsTUFBTSxPQUFPLFNBQVM7QUFDcEIsWUFBTTtBQUNOLGFBQU8sSUFBSSxLQUFLLElBQUk7QUFBQSxJQUN0QjtBQUFBLElBQ0EsV0FBVyxPQUFPLFNBQVM7QUFDekIsWUFBTTtBQUNOLGFBQU8sSUFBSSxVQUFVLElBQUk7QUFBQSxJQUMzQjtBQUFBLElBQ0EsVUFBVSxPQUFPLFNBQVM7QUFDeEIsWUFBTTtBQUNOLGFBQU8sSUFBSSxTQUFTLElBQUk7QUFBQSxJQUMxQjtBQUFBLElBQ0EsWUFBWSxPQUFPLFNBQVM7QUFDMUIsWUFBTTtBQUNOLGFBQU8sSUFBSSxXQUFXLElBQUk7QUFBQSxJQUM1QjtBQUFBLEVBQ0Y7QUFDRjsiLAogICJuYW1lcyI6IFsicGF0aCIsICJyZXN1bHQiLCAic3RvcmFnZSIsICJzYW5kYm94UmVjb3JkIiwgInBhdGgiLCAiZXJyb3JlIiwgInNhbmRib3giLCAicGF0aCIsICJzbmFwc2hvdElkIiwgImdldFNhbmRib3giLCAic2FuZGJveFJlY29yZCJdCn0K