experimental-agent 0.1.4 → 0.2.1

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-AML2VCQS.mjs +1287 -0
  6. package/dist/chunk-FQ67QZOI.mjs +75 -0
  7. package/dist/chunk-NO7RHGTH.mjs +2367 -0
  8. package/dist/{chunk-24UDM5XV.mjs → chunk-NXDVNJRS.mjs} +1 -1
  9. package/dist/chunk-OZZVS6L5.mjs +139 -0
  10. package/dist/{chunk-GYOBANFH.mjs → chunk-QRWGDFFY.mjs} +3 -7
  11. package/dist/{chunk-2ZXHR6T6.mjs → chunk-SJVFFE5D.mjs} +18 -17
  12. package/dist/chunk-TGNVXSMX.mjs +399 -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-CEeSFGva.d.mts} +159 -123
  16. package/dist/{client-Bkuq-Dfa.d.ts → client-CEeSFGva.d.ts} +159 -123
  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 +1554 -593
  22. package/dist/index.mjs +139 -33
  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 +15 -12
  29. package/dist/next/loader.mjs +14 -7
  30. package/dist/next.d.mts +1 -1
  31. package/dist/next.d.ts +1 -1
  32. package/dist/next.js +15 -10
  33. package/dist/next.mjs +14 -5
  34. package/dist/{process-manager-ZCET3VD2.mjs → process-manager-JDUJDYGU.mjs} +1 -1
  35. package/dist/sandbox-UENKQV3T.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
@@ -0,0 +1,595 @@
1
+ import {
2
+ createLogger
3
+ } from "./chunk-OZZVS6L5.mjs";
4
+ import {
5
+ SandboxError
6
+ } from "./chunk-YRYXN7W4.mjs";
7
+
8
+ // src/sandbox/bindings/docker.ts
9
+ import { execSync, spawn } from "child_process";
10
+ import * as fs from "fs/promises";
11
+ import * as os from "os";
12
+ import * as path2 from "path";
13
+ import * as errore from "errore";
14
+ import { ulid } from "ulid";
15
+
16
+ // src/sandbox/setup-poll.ts
17
+ var log = createLogger({ subsystem: "sandbox:setup" });
18
+ var SETUP_POLL_TIMEOUT_MS = 5 * 60 * 1e3;
19
+ var SETUP_POLL_INTERVAL_MS = 50;
20
+ async function pollForSetupCompletion({
21
+ storage,
22
+ sandboxId,
23
+ setupKey
24
+ }) {
25
+ const deadline = Date.now() + SETUP_POLL_TIMEOUT_MS;
26
+ const done = log.time(
27
+ "waiting for setup completion",
28
+ { sandboxId, setupKey },
29
+ { logOnStart: true }
30
+ );
31
+ while (Date.now() < deadline) {
32
+ const record = await storage.sandbox.get(sandboxId);
33
+ if (!(record instanceof Error) && record) {
34
+ if (record.setupCompletedAt && record.setupKey === setupKey) {
35
+ done();
36
+ return;
37
+ }
38
+ if (!record.setupKey) {
39
+ throw new Error(
40
+ `Setup was reset for sandbox "${sandboxId}" (setupKey cleared). Will retry on next operation.`
41
+ );
42
+ }
43
+ }
44
+ await new Promise((r) => setTimeout(r, SETUP_POLL_INTERVAL_MS));
45
+ }
46
+ throw new Error(
47
+ `Timed out waiting for sandbox setup to complete (sandbox="${sandboxId}")`
48
+ );
49
+ }
50
+ async function markSetupComplete({
51
+ storage,
52
+ sandboxId,
53
+ setupKey
54
+ }) {
55
+ const result = await storage.sandbox.update({
56
+ id: sandboxId,
57
+ setupKey,
58
+ setupCompletedAt: Date.now()
59
+ });
60
+ if (result instanceof Error) {
61
+ throw result;
62
+ }
63
+ }
64
+ async function resetSetupState({
65
+ storage,
66
+ sandboxId,
67
+ setupKey
68
+ }) {
69
+ await storage.sandbox.update({
70
+ id: sandboxId,
71
+ setupKey: null,
72
+ setupCompletedAt: null
73
+ }).catch((e) => {
74
+ log.warn("failed to clear setupKey", { sandboxId, error: String(e) });
75
+ });
76
+ await storage.setup.delete(setupKey).catch((e) => {
77
+ log.warn("failed to delete setup record", { setupKey, error: String(e) });
78
+ });
79
+ }
80
+
81
+ // src/sandbox/write-files.ts
82
+ import * as path from "path";
83
+ var MAX_RETRIES = 2;
84
+ var RETRY_BASE_MS = 500;
85
+ async function execChecked(sandbox, opts, errorLabel) {
86
+ for (let attempt = 0; ; attempt++) {
87
+ const execResult = await sandbox.exec(opts);
88
+ if (execResult instanceof Error) {
89
+ throw execResult;
90
+ }
91
+ const result = await execResult.result;
92
+ if (result.exitCode === 0) {
93
+ return result;
94
+ }
95
+ const isTransient = result.exitCode === 255 && !result.stderr.trim();
96
+ if (isTransient && attempt < MAX_RETRIES) {
97
+ await new Promise((r) => setTimeout(r, RETRY_BASE_MS * (attempt + 1)));
98
+ continue;
99
+ }
100
+ throw new Error(
101
+ `${errorLabel} with exit code ${result.exitCode}: ${result.stderr}`
102
+ );
103
+ }
104
+ }
105
+ async function writeFiles(opts) {
106
+ const { sandbox, files, destPath } = opts;
107
+ if (files.length === 0) {
108
+ return;
109
+ }
110
+ const filePaths = files.map((file) => path.posix.join(destPath, file.path));
111
+ const parentDirs = Array.from(
112
+ new Set(filePaths.map((p) => path.posix.dirname(p)))
113
+ );
114
+ const shellScripts = filePaths.filter((p) => p.endsWith(".sh"));
115
+ const mkdirResult = await sandbox.exec({
116
+ command: "mkdir",
117
+ args: ["-p", ...parentDirs]
118
+ });
119
+ if (mkdirResult instanceof Error) {
120
+ throw mkdirResult;
121
+ }
122
+ await mkdirResult.result;
123
+ const CHUNK_SIZE = 5e4;
124
+ for (let i = 0; i < files.length; i++) {
125
+ const file = files[i];
126
+ const fullPath = filePaths[i];
127
+ const base64Content = toBase64(file.content);
128
+ if (base64Content.length < CHUNK_SIZE) {
129
+ const marker = `EOF_${i}`;
130
+ await execChecked(
131
+ sandbox,
132
+ {
133
+ command: "bash",
134
+ args: [
135
+ "-c",
136
+ `base64 -d > ${quote(fullPath)} << '${marker}'
137
+ ${base64Content}
138
+ ${marker}`
139
+ ]
140
+ },
141
+ "writeFiles failed"
142
+ );
143
+ } else {
144
+ const tempB64 = `/tmp/chunk-${Date.now()}-${i}.b64`;
145
+ const clearResult = await sandbox.exec({
146
+ command: "bash",
147
+ args: ["-c", `> ${quote(tempB64)}`]
148
+ });
149
+ if (clearResult instanceof Error) {
150
+ throw clearResult;
151
+ }
152
+ await clearResult.result;
153
+ for (let offset = 0; offset < base64Content.length; offset += CHUNK_SIZE) {
154
+ const chunk = base64Content.slice(offset, offset + CHUNK_SIZE);
155
+ const marker = `CHUNK_${offset}`;
156
+ await execChecked(
157
+ sandbox,
158
+ {
159
+ command: "bash",
160
+ args: [
161
+ "-c",
162
+ `cat >> ${quote(tempB64)} << '${marker}'
163
+ ${chunk}
164
+ ${marker}`
165
+ ]
166
+ },
167
+ "writeFiles chunk failed"
168
+ );
169
+ }
170
+ await execChecked(
171
+ sandbox,
172
+ {
173
+ command: "bash",
174
+ args: [
175
+ "-c",
176
+ `base64 -d < ${quote(tempB64)} > ${quote(fullPath)} && rm -f ${quote(tempB64)}`
177
+ ]
178
+ },
179
+ "writeFiles decode failed"
180
+ );
181
+ }
182
+ }
183
+ if (shellScripts.length > 0) {
184
+ const chmodResult = await sandbox.exec({
185
+ command: "chmod",
186
+ args: ["+x", ...shellScripts]
187
+ });
188
+ if (chmodResult instanceof Error) {
189
+ throw chmodResult;
190
+ }
191
+ await chmodResult.result;
192
+ }
193
+ }
194
+ function toBase64(content) {
195
+ if (typeof content === "string") {
196
+ return Buffer.from(content).toString("base64");
197
+ }
198
+ return content.toString("base64");
199
+ }
200
+ function quote(s) {
201
+ return `'${s.replace(/'/g, "'\\''")}'`;
202
+ }
203
+
204
+ // src/sandbox/bindings/docker.ts
205
+ var dockerAvailable = null;
206
+ async function isDockerSandboxAvailable() {
207
+ if (dockerAvailable !== null) {
208
+ return dockerAvailable;
209
+ }
210
+ try {
211
+ const result = await execDocker(["version"], { timeoutMs: 5e3 });
212
+ dockerAvailable = result.exitCode === 0;
213
+ } catch {
214
+ dockerAvailable = false;
215
+ }
216
+ return dockerAvailable;
217
+ }
218
+ function execDocker(args, opts) {
219
+ return new Promise((resolve, reject) => {
220
+ const child = spawn("docker", ["sandbox", ...args], {
221
+ signal: opts?.signal
222
+ });
223
+ let stdout = "";
224
+ let stderr = "";
225
+ child.stdout.on("data", (data) => {
226
+ stdout += data.toString();
227
+ });
228
+ child.stderr.on("data", (data) => {
229
+ stderr += data.toString();
230
+ });
231
+ const timeoutId = opts?.timeoutMs ? setTimeout(() => {
232
+ child.kill("SIGTERM");
233
+ reject(new Error(`docker sandbox ${args[0]} timed out`));
234
+ }, opts.timeoutMs) : void 0;
235
+ child.on("error", (err) => {
236
+ if (timeoutId) {
237
+ clearTimeout(timeoutId);
238
+ }
239
+ reject(err);
240
+ });
241
+ child.on("close", (code) => {
242
+ if (timeoutId) {
243
+ clearTimeout(timeoutId);
244
+ }
245
+ resolve({ stdout, stderr, exitCode: code ?? 0 });
246
+ });
247
+ });
248
+ }
249
+ var ensurePromises = /* @__PURE__ */ new Map();
250
+ var activeSandboxes = /* @__PURE__ */ new Set();
251
+ var cleanupRegistered = false;
252
+ function registerCleanup() {
253
+ if (cleanupRegistered) {
254
+ return;
255
+ }
256
+ cleanupRegistered = true;
257
+ const cleanup = () => {
258
+ for (const name of Array.from(activeSandboxes)) {
259
+ try {
260
+ execSync(`docker sandbox stop ${name}`, {
261
+ timeout: 1e4,
262
+ stdio: "pipe"
263
+ });
264
+ } catch {
265
+ }
266
+ }
267
+ };
268
+ process.on("exit", cleanup);
269
+ process.on("SIGINT", () => {
270
+ cleanup();
271
+ process.exit(130);
272
+ });
273
+ process.on("SIGTERM", () => {
274
+ cleanup();
275
+ process.exit(143);
276
+ });
277
+ }
278
+ async function ensureSandbox(sandboxId) {
279
+ const existing = ensurePromises.get(sandboxId);
280
+ if (existing) {
281
+ return existing;
282
+ }
283
+ const promise = (async () => {
284
+ const ls = await execDocker(["ls", "-q"], { timeoutMs: 1e4 });
285
+ const existingNames = ls.exitCode === 0 ? ls.stdout.split("\n").map((s) => s.trim()).filter(Boolean) : [];
286
+ if (existingNames.includes(sandboxId)) {
287
+ activeSandboxes.add(sandboxId);
288
+ registerCleanup();
289
+ return;
290
+ }
291
+ const workspaceDir = path2.join(
292
+ os.tmpdir(),
293
+ "agent-docker-sandbox",
294
+ sandboxId
295
+ );
296
+ await fs.mkdir(workspaceDir, { recursive: true });
297
+ const create = await execDocker(
298
+ ["create", "--name", sandboxId, "shell", workspaceDir],
299
+ { timeoutMs: 6e4 }
300
+ );
301
+ if (create.exitCode !== 0) {
302
+ if (create.stderr.includes("already exists")) {
303
+ activeSandboxes.add(sandboxId);
304
+ registerCleanup();
305
+ return;
306
+ }
307
+ throw new Error(
308
+ `Failed to create docker sandbox "${sandboxId}": ${create.stderr}`
309
+ );
310
+ }
311
+ activeSandboxes.add(sandboxId);
312
+ registerCleanup();
313
+ })();
314
+ ensurePromises.set(sandboxId, promise);
315
+ try {
316
+ await promise;
317
+ } catch (e) {
318
+ ensurePromises.delete(sandboxId);
319
+ throw e;
320
+ }
321
+ }
322
+ var dockerSandbox = ({
323
+ sandboxRecord,
324
+ storage,
325
+ setup,
326
+ onRestart
327
+ }) => {
328
+ const sandboxName = sandboxRecord.id;
329
+ const cwd = sandboxRecord.config.cwd ?? "/home/agent/workspace";
330
+ const processes = /* @__PURE__ */ new Map();
331
+ let startPromise = null;
332
+ const sandbox = {
333
+ id: sandboxRecord.id,
334
+ config: sandboxRecord.config,
335
+ cwd,
336
+ exec: ({ command, args, cwd: cwd2, env, signal, sudo }) => {
337
+ return errore.tryAsync({
338
+ try: async () => {
339
+ await ensureSandbox(sandboxName);
340
+ const commandId = `command_${ulid()}`;
341
+ const envFlags = env === void 0 ? [] : Object.entries(env).flatMap(([k, v]) => ["-e", `${k}=${v}`]);
342
+ const cwdFlags = cwd2 ? ["-w", cwd2] : [];
343
+ const baseCmd = sudo ? ["sudo", command, ...args ?? []] : args ? [command, ...args] : [command];
344
+ const fullCmd = baseCmd;
345
+ const child = spawn(
346
+ "docker",
347
+ [
348
+ "sandbox",
349
+ "exec",
350
+ ...envFlags,
351
+ ...cwdFlags,
352
+ sandboxName,
353
+ ...fullCmd
354
+ ],
355
+ { signal }
356
+ );
357
+ processes.set(commandId, child);
358
+ let stdout = "";
359
+ let stderr = "";
360
+ const logQueue = [];
361
+ let logResolve = null;
362
+ let closed = false;
363
+ child.stdout.on("data", (data) => {
364
+ const str = String(data);
365
+ stdout += str;
366
+ logQueue.push({ stream: "stdout", data: str });
367
+ logResolve?.();
368
+ });
369
+ child.stderr.on("data", (data) => {
370
+ const str = String(data);
371
+ stderr += str;
372
+ logQueue.push({ stream: "stderr", data: str });
373
+ logResolve?.();
374
+ });
375
+ const result = new Promise((resolve, reject) => {
376
+ child.on("error", (err) => {
377
+ processes.delete(commandId);
378
+ closed = true;
379
+ logResolve?.();
380
+ reject(err);
381
+ });
382
+ child.on("close", (code) => {
383
+ processes.delete(commandId);
384
+ closed = true;
385
+ logResolve?.();
386
+ resolve({ stdout, stderr, exitCode: code ?? 0 });
387
+ });
388
+ });
389
+ async function* logs() {
390
+ while (!closed || logQueue.length > 0) {
391
+ const entry = logQueue.shift();
392
+ if (entry) {
393
+ yield entry;
394
+ } else if (!closed) {
395
+ await new Promise((resolve) => {
396
+ logResolve = resolve;
397
+ });
398
+ logResolve = null;
399
+ }
400
+ }
401
+ }
402
+ return { commandId, logs, result };
403
+ },
404
+ catch: (e) => new SandboxError({ reason: String(e), cause: e })
405
+ });
406
+ },
407
+ getDomain: (port) => {
408
+ return Promise.resolve(`http://localhost:${port}`);
409
+ },
410
+ kill: async ({ commandId, storage: storage2 }) => {
411
+ const child = processes.get(commandId);
412
+ if (!child) {
413
+ return new SandboxError({
414
+ reason: `Command ${commandId} not found or already finished`
415
+ });
416
+ }
417
+ child.kill("SIGTERM");
418
+ const cmd = await storage2.command.get(commandId);
419
+ if (cmd instanceof Error) {
420
+ return new SandboxError({ reason: cmd.message, cause: cmd });
421
+ }
422
+ if (cmd && cmd.status === "running") {
423
+ const result = await storage2.command.set({
424
+ ...cmd,
425
+ status: "killed"
426
+ });
427
+ if (result instanceof Error) {
428
+ return new SandboxError({ reason: result.message, cause: result });
429
+ }
430
+ }
431
+ },
432
+ readFile: async ({ path: filePath }) => {
433
+ try {
434
+ await ensureSandbox(sandboxName);
435
+ const result = await execDocker(
436
+ [
437
+ "exec",
438
+ sandboxName,
439
+ "bash",
440
+ "-c",
441
+ `base64 '${filePath.replace(/'/g, "'\\''")}'`
442
+ ],
443
+ { timeoutMs: 3e4 }
444
+ );
445
+ if (result.exitCode !== 0) {
446
+ if (result.stderr.includes("No such file") || result.stderr.includes("ENOENT")) {
447
+ return null;
448
+ }
449
+ return new SandboxError({
450
+ reason: `readFile failed: ${result.stderr}`
451
+ });
452
+ }
453
+ return Buffer.from(result.stdout.trim(), "base64");
454
+ } catch (e) {
455
+ return new SandboxError({ reason: String(e), cause: e });
456
+ }
457
+ },
458
+ writeFiles: (opts) => writeFiles({ sandbox, ...opts }),
459
+ updateNetworkPolicy: () => Promise.resolve(
460
+ new SandboxError({
461
+ reason: "updateNetworkPolicy is not yet available for Docker sandboxes"
462
+ })
463
+ ),
464
+ lifecycle: {
465
+ start: () => {
466
+ if (startPromise) {
467
+ return startPromise;
468
+ }
469
+ startPromise = (async () => {
470
+ await ensureSandbox(sandboxName);
471
+ if (!setup && sandboxRecord.setupKey) {
472
+ await pollForSetupCompletion({
473
+ storage,
474
+ sandboxId: sandboxRecord.id,
475
+ setupKey: sandboxRecord.setupKey
476
+ });
477
+ }
478
+ if (setup) {
479
+ const existing = await storage.setup.get(setup.key);
480
+ if (existing instanceof Error || !existing) {
481
+ try {
482
+ await setup.run(sandbox);
483
+ await storage.setup.set({
484
+ key: setup.key,
485
+ snapshotId: null,
486
+ createdAt: Date.now(),
487
+ lastUsedAt: null,
488
+ acquiringLockId: null,
489
+ acquiringLockAt: null
490
+ });
491
+ await markSetupComplete({
492
+ storage,
493
+ sandboxId: sandboxRecord.id,
494
+ setupKey: setup.key
495
+ });
496
+ } catch (e) {
497
+ await resetSetupState({
498
+ storage,
499
+ sandboxId: sandboxRecord.id,
500
+ setupKey: setup.key
501
+ });
502
+ throw e;
503
+ }
504
+ }
505
+ }
506
+ if (onRestart) {
507
+ await onRestart(sandbox);
508
+ }
509
+ return void 0;
510
+ })().catch((e) => {
511
+ startPromise = null;
512
+ throw e;
513
+ });
514
+ return startPromise;
515
+ },
516
+ snapshot: () => Promise.resolve(
517
+ new SandboxError({
518
+ reason: "snapshot is not supported for Docker sandboxes"
519
+ })
520
+ ),
521
+ stop: async () => {
522
+ try {
523
+ await execDocker(["stop", sandboxName], { timeoutMs: 3e4 });
524
+ activeSandboxes.delete(sandboxName);
525
+ ensurePromises.delete(sandboxName);
526
+ return void 0;
527
+ } catch (e) {
528
+ return new SandboxError({ reason: String(e), cause: e });
529
+ }
530
+ },
531
+ getStatus: () => Promise.resolve(
532
+ new SandboxError({
533
+ reason: "getStatus is not supported for Docker sandboxes"
534
+ })
535
+ ),
536
+ getCreatedAt: () => Promise.resolve(
537
+ new SandboxError({
538
+ reason: "getCreatedAt is not supported for Docker sandboxes"
539
+ })
540
+ ),
541
+ getRemainingTimeout: () => Promise.resolve(
542
+ new SandboxError({
543
+ reason: "getRemainingTimeout is not supported for Docker sandboxes"
544
+ })
545
+ )
546
+ },
547
+ tag: {
548
+ list: async () => {
549
+ const sandboxRecord2 = await storage.sandbox.get(sandbox.id);
550
+ if (sandboxRecord2 instanceof Error) {
551
+ return sandboxRecord2;
552
+ }
553
+ return sandboxRecord2.tags ?? {};
554
+ },
555
+ get: async (key) => {
556
+ const sandboxRecord2 = await storage.sandbox.get(sandbox.id);
557
+ if (sandboxRecord2 instanceof Error) {
558
+ return sandboxRecord2;
559
+ }
560
+ return sandboxRecord2.tags?.[key];
561
+ },
562
+ set: async (key, value) => {
563
+ const result = await storage.sandbox.tag.set({
564
+ sandboxId: sandbox.id,
565
+ tags: { [key]: value }
566
+ });
567
+ if (result instanceof Error) {
568
+ return result;
569
+ }
570
+ return void 0;
571
+ },
572
+ setMany: async (tags) => {
573
+ const result = await storage.sandbox.tag.set({
574
+ sandboxId: sandbox.id,
575
+ tags
576
+ });
577
+ if (result instanceof Error) {
578
+ return result;
579
+ }
580
+ return void 0;
581
+ }
582
+ }
583
+ };
584
+ return sandbox;
585
+ };
586
+
587
+ export {
588
+ pollForSetupCompletion,
589
+ markSetupComplete,
590
+ resetSetupState,
591
+ writeFiles,
592
+ isDockerSandboxAvailable,
593
+ dockerSandbox
594
+ };
595
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL3NhbmRib3gvYmluZGluZ3MvZG9ja2VyLnRzIiwgIi4uL3NyYy9zYW5kYm94L3NldHVwLXBvbGwudHMiLCAiLi4vc3JjL3NhbmRib3gvd3JpdGUtZmlsZXMudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCB0eXBlIHsgQ2hpbGRQcm9jZXNzIH0gZnJvbSBcIm5vZGU6Y2hpbGRfcHJvY2Vzc1wiO1xuaW1wb3J0IHsgZXhlY1N5bmMsIHNwYXduIH0gZnJvbSBcIm5vZGU6Y2hpbGRfcHJvY2Vzc1wiO1xuaW1wb3J0ICogYXMgZnMgZnJvbSBcIm5vZGU6ZnMvcHJvbWlzZXNcIjtcbmltcG9ydCAqIGFzIG9zIGZyb20gXCJub2RlOm9zXCI7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCAqIGFzIGVycm9yZSBmcm9tIFwiZXJyb3JlXCI7XG5pbXBvcnQgeyB1bGlkIH0gZnJvbSBcInVsaWRcIjtcbmltcG9ydCB7IFNhbmRib3hFcnJvciB9IGZyb20gXCIuLi8uLi9lcnJvcnNcIjtcbmltcG9ydCB0eXBlIHsgVGFnc1NjaGVtYSB9IGZyb20gXCIuLi8uLi9pbmRleFwiO1xuaW1wb3J0IHR5cGUgeyBTYW5kYm94UmVjb3JkLCBTdG9yYWdlIH0gZnJvbSBcIi4uLy4uL3N0b3JhZ2VcIjtcbmltcG9ydCB7XG4gIG1hcmtTZXR1cENvbXBsZXRlLFxuICBwb2xsRm9yU2V0dXBDb21wbGV0aW9uLFxuICByZXNldFNldHVwU3RhdGUsXG59IGZyb20gXCIuLi9zZXR1cC1wb2xsXCI7XG5pbXBvcnQgdHlwZSB7IExvZ0VudHJ5LCBPblJlc3RhcnQsIFNhbmRib3gsIFNhbmRib3hTZXR1cCB9IGZyb20gXCIuLi90eXBlc1wiO1xuaW1wb3J0IHsgd3JpdGVGaWxlcyB9IGZyb20gXCIuLi93cml0ZS1maWxlc1wiO1xuXG4vKipcbiAqIENoZWNrIHdoZXRoZXIgYGRvY2tlciBzYW5kYm94YCBDTEkgaXMgYXZhaWxhYmxlLlxuICogQ2FjaGVzIHRoZSByZXN1bHQgZm9yIHRoZSBsaWZldGltZSBvZiB0aGUgcHJvY2Vzcy5cbiAqL1xubGV0IGRvY2tlckF2YWlsYWJsZTogYm9vbGVhbiB8IG51bGwgPSBudWxsO1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGlzRG9ja2VyU2FuZGJveEF2YWlsYWJsZSgpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgaWYgKGRvY2tlckF2YWlsYWJsZSAhPT0gbnVsbCkge1xuICAgIHJldHVybiBkb2NrZXJBdmFpbGFibGU7XG4gIH1cbiAgdHJ5IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBleGVjRG9ja2VyKFtcInZlcnNpb25cIl0sIHsgdGltZW91dE1zOiA1XzAwMCB9KTtcbiAgICBkb2NrZXJBdmFpbGFibGUgPSByZXN1bHQuZXhpdENvZGUgPT09IDA7XG4gIH0gY2F0Y2gge1xuICAgIGRvY2tlckF2YWlsYWJsZSA9IGZhbHNlO1xuICB9XG4gIHJldHVybiBkb2NrZXJBdmFpbGFibGU7XG59XG5cbi8qKlxuICogUnVuIGEgYGRvY2tlciBzYW5kYm94YCBDTEkgY29tbWFuZCBhbmQgcmV0dXJuIGl0cyBvdXRwdXQuXG4gKi9cbmZ1bmN0aW9uIGV4ZWNEb2NrZXIoXG4gIGFyZ3M6IHN0cmluZ1tdLFxuICBvcHRzPzogeyB0aW1lb3V0TXM/OiBudW1iZXI7IHNpZ25hbD86IEFib3J0U2lnbmFsIH1cbik6IFByb21pc2U8eyBzdGRvdXQ6IHN0cmluZzsgc3RkZXJyOiBzdHJpbmc7IGV4aXRDb2RlOiBudW1iZXIgfT4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIGNvbnN0IGNoaWxkID0gc3Bhd24oXCJkb2NrZXJcIiwgW1wic2FuZGJveFwiLCAuLi5hcmdzXSwge1xuICAgICAgc2lnbmFsOiBvcHRzPy5zaWduYWwsXG4gICAgfSk7XG5cbiAgICBsZXQgc3Rkb3V0ID0gXCJcIjtcbiAgICBsZXQgc3RkZXJyID0gXCJcIjtcblxuICAgIGNoaWxkLnN0ZG91dC5vbihcImRhdGFcIiwgKGRhdGE6IEJ1ZmZlcikgPT4ge1xuICAgICAgc3Rkb3V0ICs9IGRhdGEudG9TdHJpbmcoKTtcbiAgICB9KTtcbiAgICBjaGlsZC5zdGRlcnIub24oXCJkYXRhXCIsIChkYXRhOiBCdWZmZXIpID0+IHtcbiAgICAgIHN0ZGVyciArPSBkYXRhLnRvU3RyaW5nKCk7XG4gICAgfSk7XG5cbiAgICBjb25zdCB0aW1lb3V0SWQgPSBvcHRzPy50aW1lb3V0TXNcbiAgICAgID8gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgY2hpbGQua2lsbChcIlNJR1RFUk1cIik7XG4gICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihgZG9ja2VyIHNhbmRib3ggJHthcmdzWzBdfSB0aW1lZCBvdXRgKSk7XG4gICAgICAgIH0sIG9wdHMudGltZW91dE1zKVxuICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICBjaGlsZC5vbihcImVycm9yXCIsIChlcnIpID0+IHtcbiAgICAgIGlmICh0aW1lb3V0SWQpIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXRJZCk7XG4gICAgICB9XG4gICAgICByZWplY3QoZXJyKTtcbiAgICB9KTtcblxuICAgIGNoaWxkLm9uKFwiY2xvc2VcIiwgKGNvZGUpID0+IHtcbiAgICAgIGlmICh0aW1lb3V0SWQpIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXRJZCk7XG4gICAgICB9XG4gICAgICByZXNvbHZlKHsgc3Rkb3V0LCBzdGRlcnIsIGV4aXRDb2RlOiBjb2RlID8/IDAgfSk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG4vKipcbiAqIFRyYWNrIHdoaWNoIHNhbmRib3hlcyBoYXZlIGJlZW4gdmVyaWZpZWQgdG8gZXhpc3QgaW4gdGhpcyBwcm9jZXNzLlxuICogTWFwcyBzYW5kYm94IG5hbWUgLT4gUHJvbWlzZSBzbyBjb25jdXJyZW50IGNhbGxlcnMgd2FpdCBvbiB0aGUgc2FtZSBjaGVjay5cbiAqL1xuY29uc3QgZW5zdXJlUHJvbWlzZXMgPSBuZXcgTWFwPHN0cmluZywgUHJvbWlzZTx2b2lkPj4oKTtcblxuLyoqXG4gKiBTYW5kYm94ZXMgdGhhdCB0aGlzIHByb2Nlc3MgaGFzIHVzZWQuIFN0b3BwZWQgb24gcHJvY2VzcyBleGl0LlxuICovXG5jb25zdCBhY3RpdmVTYW5kYm94ZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcblxubGV0IGNsZWFudXBSZWdpc3RlcmVkID0gZmFsc2U7XG5mdW5jdGlvbiByZWdpc3RlckNsZWFudXAoKSB7XG4gIGlmIChjbGVhbnVwUmVnaXN0ZXJlZCkge1xuICAgIHJldHVybjtcbiAgfVxuICBjbGVhbnVwUmVnaXN0ZXJlZCA9IHRydWU7XG5cbiAgY29uc3QgY2xlYW51cCA9ICgpID0+IHtcbiAgICBmb3IgKGNvbnN0IG5hbWUgb2YgQXJyYXkuZnJvbShhY3RpdmVTYW5kYm94ZXMpKSB7XG4gICAgICB0cnkge1xuICAgICAgICAvLyBleGVjU3luYyBpcyB0aGUgb25seSBvcHRpb24gaW4gZXhpdC9zaWduYWwgaGFuZGxlcnNcbiAgICAgICAgZXhlY1N5bmMoYGRvY2tlciBzYW5kYm94IHN0b3AgJHtuYW1lfWAsIHtcbiAgICAgICAgICB0aW1lb3V0OiAxMF8wMDAsXG4gICAgICAgICAgc3RkaW86IFwicGlwZVwiLFxuICAgICAgICB9KTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBCZXN0LWVmZm9ydCBcdTIwMTQgc2FuZGJveCBtYXkgYWxyZWFkeSBiZSBzdG9wcGVkXG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIHByb2Nlc3Mub24oXCJleGl0XCIsIGNsZWFudXApO1xuICBwcm9jZXNzLm9uKFwiU0lHSU5UXCIsICgpID0+IHtcbiAgICBjbGVhbnVwKCk7XG4gICAgcHJvY2Vzcy5leGl0KDEzMCk7XG4gIH0pO1xuICBwcm9jZXNzLm9uKFwiU0lHVEVSTVwiLCAoKSA9PiB7XG4gICAgY2xlYW51cCgpO1xuICAgIHByb2Nlc3MuZXhpdCgxNDMpO1xuICB9KTtcbn1cblxuLyoqXG4gKiBFbnN1cmUgYSBEb2NrZXIgc2FuZGJveCBleGlzdHMgZm9yIHRoZSBnaXZlbiBJRC5cbiAqIElmIGl0IGFscmVhZHkgZXhpc3RzIChmcm9tIGEgcHJldmlvdXMgcHJvY2VzcyksIHJldXNlcyBpdC5cbiAqIElmIGl0IGRvZXNuJ3QgZXhpc3QsIGNyZWF0ZXMgaXQuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGVuc3VyZVNhbmRib3goc2FuZGJveElkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgZXhpc3RpbmcgPSBlbnN1cmVQcm9taXNlcy5nZXQoc2FuZGJveElkKTtcbiAgaWYgKGV4aXN0aW5nKSB7XG4gICAgcmV0dXJuIGV4aXN0aW5nO1xuICB9XG5cbiAgY29uc3QgcHJvbWlzZSA9IChhc3luYyAoKSA9PiB7XG4gICAgLy8gQ2hlY2sgaWYgc2FuZGJveCBhbHJlYWR5IGV4aXN0cyB2aWEgbHMgLXEgKHN1cnZpdmVzIHByb2Nlc3MgcmVzdGFydHMpXG4gICAgY29uc3QgbHMgPSBhd2FpdCBleGVjRG9ja2VyKFtcImxzXCIsIFwiLXFcIl0sIHsgdGltZW91dE1zOiAxMF8wMDAgfSk7XG4gICAgY29uc3QgZXhpc3RpbmdOYW1lcyA9XG4gICAgICBscy5leGl0Q29kZSA9PT0gMFxuICAgICAgICA/IGxzLnN0ZG91dFxuICAgICAgICAgICAgLnNwbGl0KFwiXFxuXCIpXG4gICAgICAgICAgICAubWFwKChzKSA9PiBzLnRyaW0oKSlcbiAgICAgICAgICAgIC5maWx0ZXIoQm9vbGVhbilcbiAgICAgICAgOiBbXTtcblxuICAgIGlmIChleGlzdGluZ05hbWVzLmluY2x1ZGVzKHNhbmRib3hJZCkpIHtcbiAgICAgIGFjdGl2ZVNhbmRib3hlcy5hZGQoc2FuZGJveElkKTtcbiAgICAgIHJlZ2lzdGVyQ2xlYW51cCgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIENyZWF0ZSBhIHRlbXAgd29ya3NwYWNlIGRpcmVjdG9yeSBvbiB0aGUgaG9zdCB0byBtb3VudCBpbnRvIHRoZSBzYW5kYm94LlxuICAgIC8vIEVhY2ggc2FuZGJveCBnZXRzIGl0cyBvd24gZGlyZWN0b3J5IGZvciBmaWxlc3lzdGVtIGlzb2xhdGlvbi5cbiAgICBjb25zdCB3b3Jrc3BhY2VEaXIgPSBwYXRoLmpvaW4oXG4gICAgICBvcy50bXBkaXIoKSxcbiAgICAgIFwiYWdlbnQtZG9ja2VyLXNhbmRib3hcIixcbiAgICAgIHNhbmRib3hJZFxuICAgICk7XG4gICAgYXdhaXQgZnMubWtkaXIod29ya3NwYWNlRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcblxuICAgIGNvbnN0IGNyZWF0ZSA9IGF3YWl0IGV4ZWNEb2NrZXIoXG4gICAgICBbXCJjcmVhdGVcIiwgXCItLW5hbWVcIiwgc2FuZGJveElkLCBcInNoZWxsXCIsIHdvcmtzcGFjZURpcl0sXG4gICAgICB7IHRpbWVvdXRNczogNjBfMDAwIH1cbiAgICApO1xuXG4gICAgaWYgKGNyZWF0ZS5leGl0Q29kZSAhPT0gMCkge1xuICAgICAgLy8gQW5vdGhlciBwcm9jZXNzIG1heSBoYXZlIGNyZWF0ZWQgaXQgYmV0d2VlbiBpbnNwZWN0IGFuZCBjcmVhdGVcbiAgICAgIGlmIChjcmVhdGUuc3RkZXJyLmluY2x1ZGVzKFwiYWxyZWFkeSBleGlzdHNcIikpIHtcbiAgICAgICAgYWN0aXZlU2FuZGJveGVzLmFkZChzYW5kYm94SWQpO1xuICAgICAgICByZWdpc3RlckNsZWFudXAoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgRmFpbGVkIHRvIGNyZWF0ZSBkb2NrZXIgc2FuZGJveCBcIiR7c2FuZGJveElkfVwiOiAke2NyZWF0ZS5zdGRlcnJ9YFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBhY3RpdmVTYW5kYm94ZXMuYWRkKHNhbmRib3hJZCk7XG4gICAgcmVnaXN0ZXJDbGVhbnVwKCk7XG4gIH0pKCk7XG5cbiAgZW5zdXJlUHJvbWlzZXMuc2V0KHNhbmRib3hJZCwgcHJvbWlzZSk7XG5cbiAgdHJ5IHtcbiAgICBhd2FpdCBwcm9taXNlO1xuICB9IGNhdGNoIChlKSB7XG4gICAgLy8gQWxsb3cgcmV0cnkgb24gZmFpbHVyZVxuICAgIGVuc3VyZVByb21pc2VzLmRlbGV0ZShzYW5kYm94SWQpO1xuICAgIHRocm93IGU7XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IGRvY2tlclNhbmRib3ggPSA8VFRhZ3MgZXh0ZW5kcyBUYWdzU2NoZW1hID0gVGFnc1NjaGVtYT4oe1xuICBzYW5kYm94UmVjb3JkLFxuICBzdG9yYWdlLFxuICBzZXR1cCxcbiAgb25SZXN0YXJ0LFxufToge1xuICBzYW5kYm94UmVjb3JkOiBTYW5kYm94UmVjb3JkICYgeyBjb25maWc6IHsgdHlwZTogXCJkb2NrZXJcIiB9IH07XG4gIHN0b3JhZ2U6IFN0b3JhZ2U7XG4gIHNldHVwPzogU2FuZGJveFNldHVwO1xuICBvblJlc3RhcnQ/OiBPblJlc3RhcnQ7XG59KTogU2FuZGJveDxUVGFncz4gPT4ge1xuICBjb25zdCBzYW5kYm94TmFtZSA9IHNhbmRib3hSZWNvcmQuaWQ7XG4gIGNvbnN0IGN3ZCA9IHNhbmRib3hSZWNvcmQuY29uZmlnLmN3ZCA/PyBcIi9ob21lL2FnZW50L3dvcmtzcGFjZVwiO1xuICBjb25zdCBwcm9jZXNzZXMgPSBuZXcgTWFwPHN0cmluZywgQ2hpbGRQcm9jZXNzPigpO1xuXG4gIGxldCBzdGFydFByb21pc2U6IFByb21pc2U8U2FuZGJveEVycm9yIHwgdW5kZWZpbmVkPiB8IG51bGwgPSBudWxsO1xuXG4gIGNvbnN0IHNhbmRib3g6IFNhbmRib3g8VFRhZ3M+ID0ge1xuICAgIGlkOiBzYW5kYm94UmVjb3JkLmlkLFxuICAgIGNvbmZpZzogc2FuZGJveFJlY29yZC5jb25maWcsXG4gICAgY3dkLFxuXG4gICAgZXhlYzogKHsgY29tbWFuZCwgYXJncywgY3dkLCBlbnYsIHNpZ25hbCwgc3VkbyB9KSA9PiB7XG4gICAgICByZXR1cm4gZXJyb3JlLnRyeUFzeW5jKHtcbiAgICAgICAgdHJ5OiBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgYXdhaXQgZW5zdXJlU2FuZGJveChzYW5kYm94TmFtZSk7XG5cbiAgICAgICAgICBjb25zdCBjb21tYW5kSWQgPSBgY29tbWFuZF8ke3VsaWQoKX1gO1xuICAgICAgICAgIGNvbnN0IGVudkZsYWdzID1cbiAgICAgICAgICAgIGVudiA9PT0gdW5kZWZpbmVkXG4gICAgICAgICAgICAgID8gW11cbiAgICAgICAgICAgICAgOiBPYmplY3QuZW50cmllcyhlbnYpLmZsYXRNYXAoKFtrLCB2XSkgPT4gW1wiLWVcIiwgYCR7a309JHt2fWBdKTtcbiAgICAgICAgICBjb25zdCBjd2RGbGFncyA9IGN3ZCA/IFtcIi13XCIsIGN3ZF0gOiBbXTtcbiAgICAgICAgICBjb25zdCBiYXNlQ21kID0gc3Vkb1xuICAgICAgICAgICAgPyBbXCJzdWRvXCIsIGNvbW1hbmQsIC4uLihhcmdzID8/IFtdKV1cbiAgICAgICAgICAgIDogYXJnc1xuICAgICAgICAgICAgICA/IFtjb21tYW5kLCAuLi5hcmdzXVxuICAgICAgICAgICAgICA6IFtjb21tYW5kXTtcbiAgICAgICAgICBjb25zdCBmdWxsQ21kID0gYmFzZUNtZDtcblxuICAgICAgICAgIGNvbnN0IGNoaWxkID0gc3Bhd24oXG4gICAgICAgICAgICBcImRvY2tlclwiLFxuICAgICAgICAgICAgW1xuICAgICAgICAgICAgICBcInNhbmRib3hcIixcbiAgICAgICAgICAgICAgXCJleGVjXCIsXG4gICAgICAgICAgICAgIC4uLmVudkZsYWdzLFxuICAgICAgICAgICAgICAuLi5jd2RGbGFncyxcbiAgICAgICAgICAgICAgc2FuZGJveE5hbWUsXG4gICAgICAgICAgICAgIC4uLmZ1bGxDbWQsXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgeyBzaWduYWwgfVxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBwcm9jZXNzZXMuc2V0KGNvbW1hbmRJZCwgY2hpbGQpO1xuXG4gICAgICAgICAgbGV0IHN0ZG91dCA9IFwiXCI7XG4gICAgICAgICAgbGV0IHN0ZGVyciA9IFwiXCI7XG4gICAgICAgICAgY29uc3QgbG9nUXVldWU6IExvZ0VudHJ5W10gPSBbXTtcbiAgICAgICAgICBsZXQgbG9nUmVzb2x2ZTogKCgpID0+IHZvaWQpIHwgbnVsbCA9IG51bGw7XG4gICAgICAgICAgbGV0IGNsb3NlZCA9IGZhbHNlO1xuXG4gICAgICAgICAgY2hpbGQuc3Rkb3V0Lm9uKFwiZGF0YVwiLCAoZGF0YTogc3RyaW5nIHwgQnVmZmVyKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBzdHIgPSBTdHJpbmcoZGF0YSk7XG4gICAgICAgICAgICBzdGRvdXQgKz0gc3RyO1xuICAgICAgICAgICAgbG9nUXVldWUucHVzaCh7IHN0cmVhbTogXCJzdGRvdXRcIiwgZGF0YTogc3RyIH0pO1xuICAgICAgICAgICAgbG9nUmVzb2x2ZT8uKCk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBjaGlsZC5zdGRlcnIub24oXCJkYXRhXCIsIChkYXRhOiBzdHJpbmcgfCBCdWZmZXIpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN0ciA9IFN0cmluZyhkYXRhKTtcbiAgICAgICAgICAgIHN0ZGVyciArPSBzdHI7XG4gICAgICAgICAgICBsb2dRdWV1ZS5wdXNoKHsgc3RyZWFtOiBcInN0ZGVyclwiLCBkYXRhOiBzdHIgfSk7XG4gICAgICAgICAgICBsb2dSZXNvbHZlPy4oKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBQcm9taXNlPHtcbiAgICAgICAgICAgIHN0ZG91dDogc3RyaW5nO1xuICAgICAgICAgICAgc3RkZXJyOiBzdHJpbmc7XG4gICAgICAgICAgICBleGl0Q29kZTogbnVtYmVyO1xuICAgICAgICAgIH0+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNoaWxkLm9uKFwiZXJyb3JcIiwgKGVycikgPT4ge1xuICAgICAgICAgICAgICBwcm9jZXNzZXMuZGVsZXRlKGNvbW1hbmRJZCk7XG4gICAgICAgICAgICAgIGNsb3NlZCA9IHRydWU7XG4gICAgICAgICAgICAgIGxvZ1Jlc29sdmU/LigpO1xuICAgICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBjaGlsZC5vbihcImNsb3NlXCIsIChjb2RlOiBudW1iZXIgfCBudWxsKSA9PiB7XG4gICAgICAgICAgICAgIHByb2Nlc3Nlcy5kZWxldGUoY29tbWFuZElkKTtcbiAgICAgICAgICAgICAgY2xvc2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgbG9nUmVzb2x2ZT8uKCk7XG4gICAgICAgICAgICAgIHJlc29sdmUoeyBzdGRvdXQsIHN0ZGVyciwgZXhpdENvZGU6IGNvZGUgPz8gMCB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgYXN5bmMgZnVuY3Rpb24qIGxvZ3MoKTogQXN5bmNJdGVyYWJsZTxMb2dFbnRyeT4ge1xuICAgICAgICAgICAgd2hpbGUgKCFjbG9zZWQgfHwgbG9nUXVldWUubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICBjb25zdCBlbnRyeSA9IGxvZ1F1ZXVlLnNoaWZ0KCk7XG4gICAgICAgICAgICAgIGlmIChlbnRyeSkge1xuICAgICAgICAgICAgICAgIHlpZWxkIGVudHJ5O1xuICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFjbG9zZWQpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgbG9nUmVzb2x2ZSA9IHJlc29sdmU7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgbG9nUmVzb2x2ZSA9IG51bGw7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4geyBjb21tYW5kSWQsIGxvZ3MsIHJlc3VsdCB9O1xuICAgICAgICB9LFxuICAgICAgICBjYXRjaDogKGU6IHVua25vd24pID0+XG4gICAgICAgICAgbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogU3RyaW5nKGUpLCBjYXVzZTogZSB9KSxcbiAgICAgIH0pO1xuICAgIH0sXG5cbiAgICBnZXREb21haW46IChwb3J0KSA9PiB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGBodHRwOi8vbG9jYWxob3N0OiR7cG9ydH1gKTtcbiAgICB9LFxuXG4gICAga2lsbDogYXN5bmMgKHsgY29tbWFuZElkLCBzdG9yYWdlIH0pID0+IHtcbiAgICAgIGNvbnN0IGNoaWxkID0gcHJvY2Vzc2VzLmdldChjb21tYW5kSWQpO1xuICAgICAgaWYgKCFjaGlsZCkge1xuICAgICAgICByZXR1cm4gbmV3IFNhbmRib3hFcnJvcih7XG4gICAgICAgICAgcmVhc29uOiBgQ29tbWFuZCAke2NvbW1hbmRJZH0gbm90IGZvdW5kIG9yIGFscmVhZHkgZmluaXNoZWRgLFxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgY2hpbGQua2lsbChcIlNJR1RFUk1cIik7XG5cbiAgICAgIGNvbnN0IGNtZCA9IGF3YWl0IHN0b3JhZ2UuY29tbWFuZC5nZXQoY29tbWFuZElkKTtcbiAgICAgIGlmIChjbWQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICByZXR1cm4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogY21kLm1lc3NhZ2UsIGNhdXNlOiBjbWQgfSk7XG4gICAgICB9XG4gICAgICBpZiAoY21kICYmIGNtZC5zdGF0dXMgPT09IFwicnVubmluZ1wiKSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHN0b3JhZ2UuY29tbWFuZC5zZXQoe1xuICAgICAgICAgIC4uLmNtZCxcbiAgICAgICAgICBzdGF0dXM6IFwia2lsbGVkXCIsXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICByZXR1cm4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogcmVzdWx0Lm1lc3NhZ2UsIGNhdXNlOiByZXN1bHQgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LFxuXG4gICAgcmVhZEZpbGU6IGFzeW5jICh7IHBhdGg6IGZpbGVQYXRoIH0pID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGVuc3VyZVNhbmRib3goc2FuZGJveE5hbWUpO1xuXG4gICAgICAgIC8vIFVzZSBkb2NrZXIgc2FuZGJveCBleGVjIHRvIGNhdCB0aGUgZmlsZSBhbmQgZ2V0IGl0cyBiYXNlNjQgY29udGVudFxuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBleGVjRG9ja2VyKFxuICAgICAgICAgIFtcbiAgICAgICAgICAgIFwiZXhlY1wiLFxuICAgICAgICAgICAgc2FuZGJveE5hbWUsXG4gICAgICAgICAgICBcImJhc2hcIixcbiAgICAgICAgICAgIFwiLWNcIixcbiAgICAgICAgICAgIGBiYXNlNjQgJyR7ZmlsZVBhdGgucmVwbGFjZSgvJy9nLCBcIidcXFxcJydcIil9J2AsXG4gICAgICAgICAgXSxcbiAgICAgICAgICB7IHRpbWVvdXRNczogMzBfMDAwIH1cbiAgICAgICAgKTtcblxuICAgICAgICBpZiAocmVzdWx0LmV4aXRDb2RlICE9PSAwKSB7XG4gICAgICAgICAgLy8gRmlsZSBub3QgZm91bmRcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICByZXN1bHQuc3RkZXJyLmluY2x1ZGVzKFwiTm8gc3VjaCBmaWxlXCIpIHx8XG4gICAgICAgICAgICByZXN1bHQuc3RkZXJyLmluY2x1ZGVzKFwiRU5PRU5UXCIpXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG5ldyBTYW5kYm94RXJyb3Ioe1xuICAgICAgICAgICAgcmVhc29uOiBgcmVhZEZpbGUgZmFpbGVkOiAke3Jlc3VsdC5zdGRlcnJ9YCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBCdWZmZXIuZnJvbShyZXN1bHQuc3Rkb3V0LnRyaW0oKSwgXCJiYXNlNjRcIik7XG4gICAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICAgIHJldHVybiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pO1xuICAgICAgfVxuICAgIH0sXG5cbiAgICB3cml0ZUZpbGVzOiAob3B0cykgPT4gd3JpdGVGaWxlcyh7IHNhbmRib3gsIC4uLm9wdHMgfSksXG5cbiAgICB1cGRhdGVOZXR3b3JrUG9saWN5OiAoKSA9PlxuICAgICAgUHJvbWlzZS5yZXNvbHZlKFxuICAgICAgICBuZXcgU2FuZGJveEVycm9yKHtcbiAgICAgICAgICByZWFzb246XG4gICAgICAgICAgICBcInVwZGF0ZU5ldHdvcmtQb2xpY3kgaXMgbm90IHlldCBhdmFpbGFibGUgZm9yIERvY2tlciBzYW5kYm94ZXNcIixcbiAgICAgICAgfSlcbiAgICAgICksXG5cbiAgICBsaWZlY3ljbGU6IHtcbiAgICAgIHN0YXJ0OiAoKSA9PiB7XG4gICAgICAgIGlmIChzdGFydFByb21pc2UpIHtcbiAgICAgICAgICByZXR1cm4gc3RhcnRQcm9taXNlO1xuICAgICAgICB9XG4gICAgICAgIHN0YXJ0UHJvbWlzZSA9IChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgYXdhaXQgZW5zdXJlU2FuZGJveChzYW5kYm94TmFtZSk7XG5cbiAgICAgICAgICBpZiAoIXNldHVwICYmIHNhbmRib3hSZWNvcmQuc2V0dXBLZXkpIHtcbiAgICAgICAgICAgIGF3YWl0IHBvbGxGb3JTZXR1cENvbXBsZXRpb24oe1xuICAgICAgICAgICAgICBzdG9yYWdlLFxuICAgICAgICAgICAgICBzYW5kYm94SWQ6IHNhbmRib3hSZWNvcmQuaWQsXG4gICAgICAgICAgICAgIHNldHVwS2V5OiBzYW5kYm94UmVjb3JkLnNldHVwS2V5LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHNldHVwKSB7XG4gICAgICAgICAgICBjb25zdCBleGlzdGluZyA9IGF3YWl0IHN0b3JhZ2Uuc2V0dXAuZ2V0KHNldHVwLmtleSk7XG4gICAgICAgICAgICBpZiAoZXhpc3RpbmcgaW5zdGFuY2VvZiBFcnJvciB8fCAhZXhpc3RpbmcpIHtcbiAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBhd2FpdCBzZXR1cC5ydW4oc2FuZGJveCk7XG4gICAgICAgICAgICAgICAgYXdhaXQgc3RvcmFnZS5zZXR1cC5zZXQoe1xuICAgICAgICAgICAgICAgICAga2V5OiBzZXR1cC5rZXksXG4gICAgICAgICAgICAgICAgICBzbmFwc2hvdElkOiBudWxsLFxuICAgICAgICAgICAgICAgICAgY3JlYXRlZEF0OiBEYXRlLm5vdygpLFxuICAgICAgICAgICAgICAgICAgbGFzdFVzZWRBdDogbnVsbCxcbiAgICAgICAgICAgICAgICAgIGFjcXVpcmluZ0xvY2tJZDogbnVsbCxcbiAgICAgICAgICAgICAgICAgIGFjcXVpcmluZ0xvY2tBdDogbnVsbCxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBhd2FpdCBtYXJrU2V0dXBDb21wbGV0ZSh7XG4gICAgICAgICAgICAgICAgICBzdG9yYWdlLFxuICAgICAgICAgICAgICAgICAgc2FuZGJveElkOiBzYW5kYm94UmVjb3JkLmlkLFxuICAgICAgICAgICAgICAgICAgc2V0dXBLZXk6IHNldHVwLmtleSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIGF3YWl0IHJlc2V0U2V0dXBTdGF0ZSh7XG4gICAgICAgICAgICAgICAgICBzdG9yYWdlLFxuICAgICAgICAgICAgICAgICAgc2FuZGJveElkOiBzYW5kYm94UmVjb3JkLmlkLFxuICAgICAgICAgICAgICAgICAgc2V0dXBLZXk6IHNldHVwLmtleSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKG9uUmVzdGFydCkge1xuICAgICAgICAgICAgYXdhaXQgb25SZXN0YXJ0KHNhbmRib3gpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB9KSgpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgc3RhcnRQcm9taXNlID0gbnVsbDtcbiAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHN0YXJ0UHJvbWlzZTtcbiAgICAgIH0sXG4gICAgICBzbmFwc2hvdDogKCkgPT5cbiAgICAgICAgUHJvbWlzZS5yZXNvbHZlKFxuICAgICAgICAgIG5ldyBTYW5kYm94RXJyb3Ioe1xuICAgICAgICAgICAgcmVhc29uOiBcInNuYXBzaG90IGlzIG5vdCBzdXBwb3J0ZWQgZm9yIERvY2tlciBzYW5kYm94ZXNcIixcbiAgICAgICAgICB9KVxuICAgICAgICApLFxuICAgICAgc3RvcDogYXN5bmMgKCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IGV4ZWNEb2NrZXIoW1wic3RvcFwiLCBzYW5kYm94TmFtZV0sIHsgdGltZW91dE1zOiAzMF8wMDAgfSk7XG4gICAgICAgICAgYWN0aXZlU2FuZGJveGVzLmRlbGV0ZShzYW5kYm94TmFtZSk7XG4gICAgICAgICAgZW5zdXJlUHJvbWlzZXMuZGVsZXRlKHNhbmRib3hOYW1lKTtcbiAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgcmV0dXJuIG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBnZXRTdGF0dXM6ICgpID0+XG4gICAgICAgIFByb21pc2UucmVzb2x2ZShcbiAgICAgICAgICBuZXcgU2FuZGJveEVycm9yKHtcbiAgICAgICAgICAgIHJlYXNvbjogXCJnZXRTdGF0dXMgaXMgbm90IHN1cHBvcnRlZCBmb3IgRG9ja2VyIHNhbmRib3hlc1wiLFxuICAgICAgICAgIH0pXG4gICAgICAgICksXG4gICAgICBnZXRDcmVhdGVkQXQ6ICgpID0+XG4gICAgICAgIFByb21pc2UucmVzb2x2ZShcbiAgICAgICAgICBuZXcgU2FuZGJveEVycm9yKHtcbiAgICAgICAgICAgIHJlYXNvbjogXCJnZXRDcmVhdGVkQXQgaXMgbm90IHN1cHBvcnRlZCBmb3IgRG9ja2VyIHNhbmRib3hlc1wiLFxuICAgICAgICAgIH0pXG4gICAgICAgICksXG4gICAgICBnZXRSZW1haW5pbmdUaW1lb3V0OiAoKSA9PlxuICAgICAgICBQcm9taXNlLnJlc29sdmUoXG4gICAgICAgICAgbmV3IFNhbmRib3hFcnJvcih7XG4gICAgICAgICAgICByZWFzb246IFwiZ2V0UmVtYWluaW5nVGltZW91dCBpcyBub3Qgc3VwcG9ydGVkIGZvciBEb2NrZXIgc2FuZGJveGVzXCIsXG4gICAgICAgICAgfSlcbiAgICAgICAgKSxcbiAgICB9LFxuXG4gICAgdGFnOiB7XG4gICAgICBsaXN0OiBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHNhbmRib3hSZWNvcmQgPSBhd2FpdCBzdG9yYWdlLnNhbmRib3guZ2V0KHNhbmRib3guaWQpO1xuICAgICAgICBpZiAoc2FuZGJveFJlY29yZCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIHNhbmRib3hSZWNvcmQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIChzYW5kYm94UmVjb3JkLnRhZ3MgPz8ge30pIGFzIFRUYWdzO1xuICAgICAgfSxcbiAgICAgIGdldDogYXN5bmMgKGtleTogc3RyaW5nKSA9PiB7XG4gICAgICAgIGNvbnN0IHNhbmRib3hSZWNvcmQgPSBhd2FpdCBzdG9yYWdlLnNhbmRib3guZ2V0KHNhbmRib3guaWQpO1xuICAgICAgICBpZiAoc2FuZGJveFJlY29yZCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIHNhbmRib3hSZWNvcmQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNhbmRib3hSZWNvcmQudGFncz8uW2tleSBhcyBzdHJpbmddIGFzXG4gICAgICAgICAgfCBUVGFnc1t0eXBlb2Yga2V5XVxuICAgICAgICAgIHwgdW5kZWZpbmVkO1xuICAgICAgfSxcbiAgICAgIHNldDogYXN5bmMgKGtleTogc3RyaW5nLCB2YWx1ZTogdW5rbm93bikgPT4ge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzdG9yYWdlLnNhbmRib3gudGFnLnNldCh7XG4gICAgICAgICAgc2FuZGJveElkOiBzYW5kYm94LmlkLFxuICAgICAgICAgIHRhZ3M6IHsgW2tleV06IHZhbHVlIH0gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9LFxuICAgICAgc2V0TWFueTogYXN5bmMgKHRhZ3M6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSA9PiB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC50YWcuc2V0KHtcbiAgICAgICAgICBzYW5kYm94SWQ6IHNhbmRib3guaWQsXG4gICAgICAgICAgdGFnczogdGFncyBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH0sXG4gICAgfSxcbiAgfTtcblxuICByZXR1cm4gc2FuZGJveDtcbn07XG4iLCAiaW1wb3J0IHR5cGUgeyBTdG9yYWdlIH0gZnJvbSBcIi4uL3N0b3JhZ2VcIjtcbmltcG9ydCB7IGNyZWF0ZUxvZ2dlciB9IGZyb20gXCIuLi91dGlscy9sb2dnZXJcIjtcblxuY29uc3QgbG9nID0gY3JlYXRlTG9nZ2VyKHsgc3Vic3lzdGVtOiBcInNhbmRib3g6c2V0dXBcIiB9KTtcblxuY29uc3QgU0VUVVBfUE9MTF9USU1FT1VUX01TID0gNSAqIDYwICogMTAwMDtcbmNvbnN0IFNFVFVQX1BPTExfSU5URVJWQUxfTVMgPSA1MDtcblxuLyoqXG4gKiBQb2xscyBzdG9yYWdlIHVudGlsIHNldHVwQ29tcGxldGVkQXQgaXMgd3JpdHRlbiBmb3IgdGhlIGdpdmVuIHNhbmRib3gra2V5LlxuICogVXNlZCBieSBjb2xkLXN0YXJ0IHdvcmtlcnMgdGhhdCBkb24ndCBoYXZlIHRoZSBzZXR1cCBmdW5jdGlvbiAoaXQncyBub3RcbiAqIHNlcmlhbGl6YWJsZSkgYnV0IG5lZWQgdG8gd2FpdCB1bnRpbCB0aGUgc2Vzc2lvbiB3b3JrZXIgZmluaXNoZXMgc2V0dXBcbiAqIGJlZm9yZSBleGVjdXRpbmcgY29tbWFuZHMuXG4gKlxuICogQWxzbyBkZXRlY3RzIHdoZW4gc2V0dXBLZXkgaXMgY2xlYXJlZCAoc2V0dXAgZmFpbGVkIGFuZCBzdGF0ZSB3YXMgcmVzZXQpLFxuICogdGhyb3dpbmcgaW1tZWRpYXRlbHkgc28gdGhlIGNhbGxlciBjYW4gcmV0cnkgaW5zdGVhZCBvZiBwb2xsaW5nIHRvIHRpbWVvdXQuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwb2xsRm9yU2V0dXBDb21wbGV0aW9uKHtcbiAgc3RvcmFnZSxcbiAgc2FuZGJveElkLFxuICBzZXR1cEtleSxcbn06IHtcbiAgc3RvcmFnZTogU3RvcmFnZTtcbiAgc2FuZGJveElkOiBzdHJpbmc7XG4gIHNldHVwS2V5OiBzdHJpbmc7XG59KTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IGRlYWRsaW5lID0gRGF0ZS5ub3coKSArIFNFVFVQX1BPTExfVElNRU9VVF9NUztcbiAgY29uc3QgZG9uZSA9IGxvZy50aW1lKFxuICAgIFwid2FpdGluZyBmb3Igc2V0dXAgY29tcGxldGlvblwiLFxuICAgIHsgc2FuZGJveElkLCBzZXR1cEtleSB9LFxuICAgIHsgbG9nT25TdGFydDogdHJ1ZSB9XG4gICk7XG5cbiAgd2hpbGUgKERhdGUubm93KCkgPCBkZWFkbGluZSkge1xuICAgIGNvbnN0IHJlY29yZCA9IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5nZXQoc2FuZGJveElkKTtcbiAgICBpZiAoIShyZWNvcmQgaW5zdGFuY2VvZiBFcnJvcikgJiYgcmVjb3JkKSB7XG4gICAgICBpZiAocmVjb3JkLnNldHVwQ29tcGxldGVkQXQgJiYgcmVjb3JkLnNldHVwS2V5ID09PSBzZXR1cEtleSkge1xuICAgICAgICBkb25lKCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmICghcmVjb3JkLnNldHVwS2V5KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgU2V0dXAgd2FzIHJlc2V0IGZvciBzYW5kYm94IFwiJHtzYW5kYm94SWR9XCIgKHNldHVwS2V5IGNsZWFyZWQpLiBXaWxsIHJldHJ5IG9uIG5leHQgb3BlcmF0aW9uLmBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgYXdhaXQgbmV3IFByb21pc2UoKHIpID0+IHNldFRpbWVvdXQociwgU0VUVVBfUE9MTF9JTlRFUlZBTF9NUykpO1xuICB9XG4gIHRocm93IG5ldyBFcnJvcihcbiAgICBgVGltZWQgb3V0IHdhaXRpbmcgZm9yIHNhbmRib3ggc2V0dXAgdG8gY29tcGxldGUgKHNhbmRib3g9XCIke3NhbmRib3hJZH1cIilgXG4gICk7XG59XG5cbi8qKlxuICogV3JpdGVzIHNldHVwQ29tcGxldGVkQXQgdG8gdGhlIHNhbmRib3ggcmVjb3JkIHNvIGNvbGQtc3RhcnQgd29ya2Vyc1xuICogcG9sbGluZyBmb3Igc2V0dXAgY29tcGxldGlvbiBrbm93IGl0J3Mgc2FmZSB0byBwcm9jZWVkLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbWFya1NldHVwQ29tcGxldGUoe1xuICBzdG9yYWdlLFxuICBzYW5kYm94SWQsXG4gIHNldHVwS2V5LFxufToge1xuICBzdG9yYWdlOiBTdG9yYWdlO1xuICBzYW5kYm94SWQ6IHN0cmluZztcbiAgc2V0dXBLZXk6IHN0cmluZztcbn0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3RvcmFnZS5zYW5kYm94LnVwZGF0ZSh7XG4gICAgaWQ6IHNhbmRib3hJZCxcbiAgICBzZXR1cEtleSxcbiAgICBzZXR1cENvbXBsZXRlZEF0OiBEYXRlLm5vdygpLFxuICB9KTtcbiAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgdGhyb3cgcmVzdWx0O1xuICB9XG59XG5cbi8qKlxuICogUmVzZXRzIHNldHVwLXJlbGF0ZWQgc3RhdGUgb24gdGhlIHNhbmRib3ggcmVjb3JkIGFuZCBkZWxldGVzIHRoZSBzZXR1cFxuICogcmVjb3JkLiBDYWxsZWQgd2hlbiBzZXR1cCBmYWlscyBzbyB0aGF0OlxuICogMS4gQ29sZC1zdGFydCB3b3JrZXJzIGRldGVjdCB0aGUgY2xlYXJlZCBzZXR1cEtleSBhbmQgc3RvcCBwb2xsaW5nXG4gKiAyLiBBbnkgd29ya2VyIHJldHJ5aW5nIHdpbGwgc2VlIG5vIHNldHVwIHJlY29yZCBhbmQgcmUtcnVuIHNldHVwXG4gKlxuICogQmVzdC1lZmZvcnQ6IGZhaWx1cmVzIGFyZSBsb2dnZWQgYnV0IG5vdCB0aHJvd24sIHNpbmNlIHdlJ3JlIGFscmVhZHlcbiAqIGluIGFuIGVycm9yIHBhdGggYW5kIHRoZSBvcmlnaW5hbCBlcnJvciBtYXR0ZXJzIG1vcmUuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXNldFNldHVwU3RhdGUoe1xuICBzdG9yYWdlLFxuICBzYW5kYm94SWQsXG4gIHNldHVwS2V5LFxufToge1xuICBzdG9yYWdlOiBTdG9yYWdlO1xuICBzYW5kYm94SWQ6IHN0cmluZztcbiAgc2V0dXBLZXk6IHN0cmluZztcbn0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgYXdhaXQgc3RvcmFnZS5zYW5kYm94XG4gICAgLnVwZGF0ZSh7XG4gICAgICBpZDogc2FuZGJveElkLFxuICAgICAgc2V0dXBLZXk6IG51bGwsXG4gICAgICBzZXR1cENvbXBsZXRlZEF0OiBudWxsLFxuICAgIH0pXG4gICAgLmNhdGNoKChlKSA9PiB7XG4gICAgICBsb2cud2FybihcImZhaWxlZCB0byBjbGVhciBzZXR1cEtleVwiLCB7IHNhbmRib3hJZCwgZXJyb3I6IFN0cmluZyhlKSB9KTtcbiAgICB9KTtcblxuICBhd2FpdCBzdG9yYWdlLnNldHVwLmRlbGV0ZShzZXR1cEtleSkuY2F0Y2goKGUpID0+IHtcbiAgICBsb2cud2FybihcImZhaWxlZCB0byBkZWxldGUgc2V0dXAgcmVjb3JkXCIsIHsgc2V0dXBLZXksIGVycm9yOiBTdHJpbmcoZSkgfSk7XG4gIH0pO1xufVxuIiwgImltcG9ydCAqIGFzIHBhdGggZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHR5cGUgeyBVcGxvYWRhYmxlRmlsZSB9IGZyb20gXCIuLi9za2lsbHMvdHlwZXNcIjtcbmltcG9ydCB0eXBlIHsgU2FuZGJveCB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbmNvbnN0IE1BWF9SRVRSSUVTID0gMjtcbmNvbnN0IFJFVFJZX0JBU0VfTVMgPSA1MDA7XG5cbi8qKlxuICogRXhlYyBhIGNvbW1hbmQgYW5kIGFzc2VydCBleGl0IGNvZGUgMC4gUmV0cmllcyBvbiB0cmFuc2llbnQgZmFpbHVyZXNcbiAqIChleGl0IGNvZGUgMjU1IHdpdGggZW1wdHkgc3RkZXJyIFx1MjAxNCB0eXBpY2FsbHkgYSBzYW5kYm94IHByb2Nlc3Mga2lsbGVkXG4gKiBiZWZvcmUgaXQgY291bGQgcHJvZHVjZSBvdXRwdXQpLlxuICovXG5hc3luYyBmdW5jdGlvbiBleGVjQ2hlY2tlZChcbiAgc2FuZGJveDogUGljazxTYW5kYm94LCBcImV4ZWNcIj4sXG4gIG9wdHM6IHsgY29tbWFuZDogc3RyaW5nOyBhcmdzPzogc3RyaW5nW10gfSxcbiAgZXJyb3JMYWJlbDogc3RyaW5nXG4pOiBQcm9taXNlPHsgc3Rkb3V0OiBzdHJpbmc7IHN0ZGVycjogc3RyaW5nOyBleGl0Q29kZTogbnVtYmVyIH0+IHtcbiAgZm9yIChsZXQgYXR0ZW1wdCA9IDA7IDsgYXR0ZW1wdCsrKSB7XG4gICAgY29uc3QgZXhlY1Jlc3VsdCA9IGF3YWl0IHNhbmRib3guZXhlYyhvcHRzKTtcbiAgICBpZiAoZXhlY1Jlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICB0aHJvdyBleGVjUmVzdWx0O1xuICAgIH1cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBleGVjUmVzdWx0LnJlc3VsdDtcbiAgICBpZiAocmVzdWx0LmV4aXRDb2RlID09PSAwKSB7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIGNvbnN0IGlzVHJhbnNpZW50ID0gcmVzdWx0LmV4aXRDb2RlID09PSAyNTUgJiYgIXJlc3VsdC5zdGRlcnIudHJpbSgpO1xuICAgIGlmIChpc1RyYW5zaWVudCAmJiBhdHRlbXB0IDwgTUFYX1JFVFJJRVMpIHtcbiAgICAgIGF3YWl0IG5ldyBQcm9taXNlKChyKSA9PiBzZXRUaW1lb3V0KHIsIFJFVFJZX0JBU0VfTVMgKiAoYXR0ZW1wdCArIDEpKSk7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgJHtlcnJvckxhYmVsfSB3aXRoIGV4aXQgY29kZSAke3Jlc3VsdC5leGl0Q29kZX06ICR7cmVzdWx0LnN0ZGVycn1gXG4gICAgKTtcbiAgfVxufVxuXG4vKipcbiAqIFdyaXRlcyBmaWxlcyB0byBhIHNhbmRib3ggYXQgdGhlIHNwZWNpZmllZCBkZXN0aW5hdGlvbiBwYXRoLlxuICogU2hlbGwgc2NyaXB0cyAoLnNoIGZpbGVzKSBhcmUgYXV0b21hdGljYWxseSBtYWRlIGV4ZWN1dGFibGUuXG4gKlxuICogRm9yIHNtYWxsIGZpbGVzICg8MTAwS0IgdG90YWwpLCB1c2VzIHNpbmdsZSBleGVjIHdpdGggaGVyZWRvYy5cbiAqIEZvciBsYXJnZSBmaWxlcywgd3JpdGVzIGJhc2U2NCBjaHVua3MgdGhlbiBkZWNvZGVzIHRvIGF2b2lkIEFSR19NQVggbGltaXRzLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gd3JpdGVGaWxlcyhvcHRzOiB7XG4gIHNhbmRib3g6IFBpY2s8U2FuZGJveCwgXCJleGVjXCI+O1xuICBmaWxlczogVXBsb2FkYWJsZUZpbGVbXTtcbiAgZGVzdFBhdGg6IHN0cmluZztcbn0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgeyBzYW5kYm94LCBmaWxlcywgZGVzdFBhdGggfSA9IG9wdHM7XG5cbiAgaWYgKGZpbGVzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IGZpbGVQYXRocyA9IGZpbGVzLm1hcCgoZmlsZSkgPT4gcGF0aC5wb3NpeC5qb2luKGRlc3RQYXRoLCBmaWxlLnBhdGgpKTtcbiAgY29uc3QgcGFyZW50RGlycyA9IEFycmF5LmZyb20oXG4gICAgbmV3IFNldChmaWxlUGF0aHMubWFwKChwKSA9PiBwYXRoLnBvc2l4LmRpcm5hbWUocCkpKVxuICApO1xuICBjb25zdCBzaGVsbFNjcmlwdHMgPSBmaWxlUGF0aHMuZmlsdGVyKChwKSA9PiBwLmVuZHNXaXRoKFwiLnNoXCIpKTtcblxuICBjb25zdCBta2RpclJlc3VsdCA9IGF3YWl0IHNhbmRib3guZXhlYyh7XG4gICAgY29tbWFuZDogXCJta2RpclwiLFxuICAgIGFyZ3M6IFtcIi1wXCIsIC4uLnBhcmVudERpcnNdLFxuICB9KTtcbiAgaWYgKG1rZGlyUmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICB0aHJvdyBta2RpclJlc3VsdDtcbiAgfVxuICBhd2FpdCBta2RpclJlc3VsdC5yZXN1bHQ7XG5cbiAgY29uc3QgQ0hVTktfU0laRSA9IDUwXzAwMDtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGZpbGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3QgZmlsZSA9IGZpbGVzW2ldO1xuICAgIGNvbnN0IGZ1bGxQYXRoID0gZmlsZVBhdGhzW2ldO1xuICAgIGNvbnN0IGJhc2U2NENvbnRlbnQgPSB0b0Jhc2U2NChmaWxlLmNvbnRlbnQpO1xuXG4gICAgaWYgKGJhc2U2NENvbnRlbnQubGVuZ3RoIDwgQ0hVTktfU0laRSkge1xuICAgICAgY29uc3QgbWFya2VyID0gYEVPRl8ke2l9YDtcbiAgICAgIGF3YWl0IGV4ZWNDaGVja2VkKFxuICAgICAgICBzYW5kYm94LFxuICAgICAgICB7XG4gICAgICAgICAgY29tbWFuZDogXCJiYXNoXCIsXG4gICAgICAgICAgYXJnczogW1xuICAgICAgICAgICAgXCItY1wiLFxuICAgICAgICAgICAgYGJhc2U2NCAtZCA+ICR7cXVvdGUoZnVsbFBhdGgpfSA8PCAnJHttYXJrZXJ9J1xuJHtiYXNlNjRDb250ZW50fVxuJHttYXJrZXJ9YCxcbiAgICAgICAgICBdLFxuICAgICAgICB9LFxuICAgICAgICBcIndyaXRlRmlsZXMgZmFpbGVkXCJcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHRlbXBCNjQgPSBgL3RtcC9jaHVuay0ke0RhdGUubm93KCl9LSR7aX0uYjY0YDtcblxuICAgICAgY29uc3QgY2xlYXJSZXN1bHQgPSBhd2FpdCBzYW5kYm94LmV4ZWMoe1xuICAgICAgICBjb21tYW5kOiBcImJhc2hcIixcbiAgICAgICAgYXJnczogW1wiLWNcIiwgYD4gJHtxdW90ZSh0ZW1wQjY0KX1gXSxcbiAgICAgIH0pO1xuICAgICAgaWYgKGNsZWFyUmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgY2xlYXJSZXN1bHQ7XG4gICAgICB9XG4gICAgICBhd2FpdCBjbGVhclJlc3VsdC5yZXN1bHQ7XG5cbiAgICAgIGZvciAoXG4gICAgICAgIGxldCBvZmZzZXQgPSAwO1xuICAgICAgICBvZmZzZXQgPCBiYXNlNjRDb250ZW50Lmxlbmd0aDtcbiAgICAgICAgb2Zmc2V0ICs9IENIVU5LX1NJWkVcbiAgICAgICkge1xuICAgICAgICBjb25zdCBjaHVuayA9IGJhc2U2NENvbnRlbnQuc2xpY2Uob2Zmc2V0LCBvZmZzZXQgKyBDSFVOS19TSVpFKTtcbiAgICAgICAgY29uc3QgbWFya2VyID0gYENIVU5LXyR7b2Zmc2V0fWA7XG4gICAgICAgIGF3YWl0IGV4ZWNDaGVja2VkKFxuICAgICAgICAgIHNhbmRib3gsXG4gICAgICAgICAge1xuICAgICAgICAgICAgY29tbWFuZDogXCJiYXNoXCIsXG4gICAgICAgICAgICBhcmdzOiBbXG4gICAgICAgICAgICAgIFwiLWNcIixcbiAgICAgICAgICAgICAgYGNhdCA+PiAke3F1b3RlKHRlbXBCNjQpfSA8PCAnJHttYXJrZXJ9J1xuJHtjaHVua31cbiR7bWFya2VyfWAsXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ3cml0ZUZpbGVzIGNodW5rIGZhaWxlZFwiXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGF3YWl0IGV4ZWNDaGVja2VkKFxuICAgICAgICBzYW5kYm94LFxuICAgICAgICB7XG4gICAgICAgICAgY29tbWFuZDogXCJiYXNoXCIsXG4gICAgICAgICAgYXJnczogW1xuICAgICAgICAgICAgXCItY1wiLFxuICAgICAgICAgICAgYGJhc2U2NCAtZCA8ICR7cXVvdGUodGVtcEI2NCl9ID4gJHtxdW90ZShmdWxsUGF0aCl9ICYmIHJtIC1mICR7cXVvdGUodGVtcEI2NCl9YCxcbiAgICAgICAgICBdLFxuICAgICAgICB9LFxuICAgICAgICBcIndyaXRlRmlsZXMgZGVjb2RlIGZhaWxlZFwiXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIGlmIChzaGVsbFNjcmlwdHMubGVuZ3RoID4gMCkge1xuICAgIGNvbnN0IGNobW9kUmVzdWx0ID0gYXdhaXQgc2FuZGJveC5leGVjKHtcbiAgICAgIGNvbW1hbmQ6IFwiY2htb2RcIixcbiAgICAgIGFyZ3M6IFtcIit4XCIsIC4uLnNoZWxsU2NyaXB0c10sXG4gICAgfSk7XG4gICAgaWYgKGNobW9kUmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIHRocm93IGNobW9kUmVzdWx0O1xuICAgIH1cbiAgICBhd2FpdCBjaG1vZFJlc3VsdC5yZXN1bHQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gdG9CYXNlNjQoY29udGVudDogc3RyaW5nIHwgQnVmZmVyKTogc3RyaW5nIHtcbiAgaWYgKHR5cGVvZiBjb250ZW50ID09PSBcInN0cmluZ1wiKSB7XG4gICAgcmV0dXJuIEJ1ZmZlci5mcm9tKGNvbnRlbnQpLnRvU3RyaW5nKFwiYmFzZTY0XCIpO1xuICB9XG4gIHJldHVybiBjb250ZW50LnRvU3RyaW5nKFwiYmFzZTY0XCIpO1xufVxuXG5mdW5jdGlvbiBxdW90ZShzOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gYCcke3MucmVwbGFjZSgvJy9nLCBcIidcXFxcJydcIil9J2A7XG59XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7OztBQUNBLFNBQVMsVUFBVSxhQUFhO0FBQ2hDLFlBQVksUUFBUTtBQUNwQixZQUFZLFFBQVE7QUFDcEIsWUFBWUEsV0FBVTtBQUN0QixZQUFZLFlBQVk7QUFDeEIsU0FBUyxZQUFZOzs7QUNIckIsSUFBTSxNQUFNLGFBQWEsRUFBRSxXQUFXLGdCQUFnQixDQUFDO0FBRXZELElBQU0sd0JBQXdCLElBQUksS0FBSztBQUN2QyxJQUFNLHlCQUF5QjtBQVcvQixlQUFzQix1QkFBdUI7QUFBQSxFQUMzQztBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQ0YsR0FJa0I7QUFDaEIsUUFBTSxXQUFXLEtBQUssSUFBSSxJQUFJO0FBQzlCLFFBQU0sT0FBTyxJQUFJO0FBQUEsSUFDZjtBQUFBLElBQ0EsRUFBRSxXQUFXLFNBQVM7QUFBQSxJQUN0QixFQUFFLFlBQVksS0FBSztBQUFBLEVBQ3JCO0FBRUEsU0FBTyxLQUFLLElBQUksSUFBSSxVQUFVO0FBQzVCLFVBQU0sU0FBUyxNQUFNLFFBQVEsUUFBUSxJQUFJLFNBQVM7QUFDbEQs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WUFBSUEsMEJBQXlCLE9BQU87QUFDbEMsaUJBQU9BO0FBQUEsUUFDVDtBQUNBLGVBQU9BLGVBQWMsT0FBTyxHQUFhO0FBQUEsTUFHM0M7QUFBQSxNQUNBLEtBQUssT0FBTyxLQUFhLFVBQW1CO0FBQzFDLGNBQU0sU0FBUyxNQUFNLFFBQVEsUUFBUSxJQUFJLElBQUk7QUFBQSxVQUMzQyxXQUFXLFFBQVE7QUFBQSxVQUNuQixNQUFNLEVBQUUsQ0FBQyxHQUFHLEdBQUcsTUFBTTtBQUFBLFFBQ3ZCLENBQUM7QUFDRCxZQUFJLGtCQUFrQixPQUFPO0FBQzNCLGlCQUFPO0FBQUEsUUFDVDtBQUNBLGVBQU87QUFBQSxNQUNUO0FBQUEsTUFDQSxTQUFTLE9BQU8sU0FBa0M7QUFDaEQsY0FBTSxTQUFTLE1BQU0sUUFBUSxRQUFRLElBQUksSUFBSTtBQUFBLFVBQzNDLFdBQVcsUUFBUTtBQUFBLFVBQ25CO0FBQUEsUUFDRixDQUFDO0FBQ0QsWUFBSSxrQkFBa0IsT0FBTztBQUMzQixpQkFBTztBQUFBLFFBQ1Q7QUFDQSxlQUFPO0FBQUEsTUFDVDtBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBRUEsU0FBTztBQUNUOyIsCiAgIm5hbWVzIjogWyJwYXRoIiwgImN3ZCIsICJzdG9yYWdlIiwgInNhbmRib3hSZWNvcmQiXQp9Cg==