experimental-agent 0.1.1 → 0.1.2
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.
- package/dist/agent-workflow.d.mts +3 -2
- package/dist/agent-workflow.d.ts +3 -2
- package/dist/agent-workflow.js +29 -29
- package/dist/agent-workflow.mjs +1 -2
- package/dist/{chunk-GJETDXOU.mjs → chunk-2SPAJ777.mjs} +5 -1
- package/dist/chunk-6J462JGP.mjs +1267 -0
- package/dist/{chunk-T2UUL6VC.mjs → chunk-E7TOPGHY.mjs} +3 -3
- package/dist/chunk-ILPVXRI5.mjs +2026 -0
- package/dist/chunk-ORE6LK2L.mjs +344 -0
- package/dist/chunk-W4SSZPDX.mjs +106 -0
- package/dist/{types-DuTc4UQW.d.mts → client-CKLwB-ES.d.mts} +730 -3
- package/dist/{types-DuTc4UQW.d.ts → client-CKLwB-ES.d.ts} +730 -3
- package/dist/{client-66JIQLSA.mjs → client-YUU54ZZH.mjs} +1 -1
- package/dist/{handler-BQY5SOI2.mjs → handler-LDFBSCRA.mjs} +1 -1
- package/dist/index.d.mts +4 -18
- package/dist/index.d.ts +4 -18
- package/dist/index.js +67 -40
- package/dist/index.mjs +21 -16
- package/dist/lifecycle-workflow.d.mts +2 -3
- package/dist/lifecycle-workflow.d.ts +2 -3
- package/dist/lifecycle-workflow.js +19 -15
- package/dist/lifecycle-workflow.mjs +1 -2
- package/dist/local-fs-handlers-SY2RDXZE.mjs +314 -0
- package/dist/next/loader.js +3 -3
- package/dist/next/loader.mjs +1 -1
- package/dist/next.js +3 -5
- package/dist/next.mjs +2 -4
- package/dist/{sandbox-27X2DSE3.mjs → sandbox-GPCA35PJ.mjs} +2 -3
- package/dist/{storage-KQYV42J4.mjs → storage-LL6IA24R.mjs} +2 -2
- package/package.json +2 -2
- package/dist/chunk-2IIWVPZB.mjs +0 -334
- package/dist/chunk-A63YU65A.mjs +0 -20
- package/dist/chunk-RDKDLHXM.mjs +0 -2031
- package/dist/chunk-VGJISV6O.mjs +0 -108
- package/dist/chunk-VS7U6SXN.mjs +0 -1261
- package/dist/client-DjcE0ATp.d.mts +0 -710
- package/dist/client-DwrDzn4_.d.ts +0 -710
- package/dist/local-fs-handlers-Q5W52DKV.mjs +0 -290
package/dist/chunk-VS7U6SXN.mjs
DELETED
|
@@ -1,1261 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
sandboxLifecycleWorkflow
|
|
3
|
-
} from "./chunk-VGJISV6O.mjs";
|
|
4
|
-
import {
|
|
5
|
-
SandboxError,
|
|
6
|
-
SandboxNotFoundError
|
|
7
|
-
} from "./chunk-HJGPUEFC.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
|
-
setup,
|
|
381
|
-
onRestart
|
|
382
|
-
}) => {
|
|
383
|
-
const { id, config } = sandboxRecord;
|
|
384
|
-
const vcpus = config.resources?.vcpus ?? DEFAULT_VCPUS;
|
|
385
|
-
const ports = config.ports;
|
|
386
|
-
const networkPolicy = config.networkPolicy;
|
|
387
|
-
const initialVercel = sandboxRecord.providerMetadata?.provider === "vercel" ? sandboxRecord.providerMetadata : null;
|
|
388
|
-
let sandboxPromise = null;
|
|
389
|
-
let recoveredFromStale = false;
|
|
390
|
-
let createdFromSnapshot = false;
|
|
391
|
-
let needsSetupRun = false;
|
|
392
|
-
const HOME_DIR = "/home/vercel-sandbox";
|
|
393
|
-
async function pollForSandboxId() {
|
|
394
|
-
const deadline = Date.now() + LOCK_TIMEOUT_MS;
|
|
395
|
-
while (Date.now() < deadline) {
|
|
396
|
-
await new Promise((r) => setTimeout(r, LOCK_POLL_INTERVAL_MS));
|
|
397
|
-
const record = await storage.sandbox.get(id);
|
|
398
|
-
if (record instanceof Error) {
|
|
399
|
-
return new SandboxError({ reason: record.message, cause: record });
|
|
400
|
-
}
|
|
401
|
-
const vercelSandboxId = record?.providerMetadata?.provider === "vercel" ? record.providerMetadata.sandboxId : null;
|
|
402
|
-
if (vercelSandboxId) {
|
|
403
|
-
return vercelSandboxId;
|
|
404
|
-
}
|
|
405
|
-
if (!record?.acquiringLockAt) {
|
|
406
|
-
const finalCheck = await storage.sandbox.get(id);
|
|
407
|
-
if (finalCheck instanceof Error) {
|
|
408
|
-
return new SandboxError({
|
|
409
|
-
reason: finalCheck.message,
|
|
410
|
-
cause: finalCheck
|
|
411
|
-
});
|
|
412
|
-
}
|
|
413
|
-
const finalVercelSandboxId = finalCheck?.providerMetadata?.provider === "vercel" ? finalCheck.providerMetadata.sandboxId : null;
|
|
414
|
-
if (finalVercelSandboxId) {
|
|
415
|
-
return finalVercelSandboxId;
|
|
416
|
-
}
|
|
417
|
-
return doGetOrCreateSandboxId();
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
return new SandboxError({
|
|
421
|
-
reason: "Timed out waiting for sandbox creation by another process"
|
|
422
|
-
});
|
|
423
|
-
}
|
|
424
|
-
async function startLifecycleWorkflow(vercelSandboxId) {
|
|
425
|
-
if (!enableLifecycleWorkflow) {
|
|
426
|
-
return;
|
|
427
|
-
}
|
|
428
|
-
const lifecycleInput = {
|
|
429
|
-
id,
|
|
430
|
-
vercelSandboxId,
|
|
431
|
-
storageConfig
|
|
432
|
-
};
|
|
433
|
-
await start(sandboxLifecycleWorkflow, [{ input: lifecycleInput }]).catch(
|
|
434
|
-
// biome-ignore lint/suspicious/noEmptyBlockStatements: intentionally ignored - workflow start is fire-and-forget
|
|
435
|
-
() => {
|
|
436
|
-
}
|
|
437
|
-
);
|
|
438
|
-
}
|
|
439
|
-
async function createSandboxFromSnapshot(snapshotId) {
|
|
440
|
-
return await errore2.tryAsync({
|
|
441
|
-
try: async () => {
|
|
442
|
-
const sandbox2 = await VercelSandboxSDK.create({
|
|
443
|
-
source: { type: "snapshot", snapshotId },
|
|
444
|
-
resources: { vcpus },
|
|
445
|
-
timeout: VERCEL_MAX_TIMEOUT_MS,
|
|
446
|
-
ports,
|
|
447
|
-
networkPolicy,
|
|
448
|
-
...getTestCredentials()
|
|
449
|
-
});
|
|
450
|
-
const now = Date.now();
|
|
451
|
-
await storage.sandbox.set({
|
|
452
|
-
id,
|
|
453
|
-
config,
|
|
454
|
-
tags: sandboxRecord.tags,
|
|
455
|
-
createdAt: now,
|
|
456
|
-
lastActivityAt: now,
|
|
457
|
-
acquiringLockId: null,
|
|
458
|
-
acquiringLockAt: null,
|
|
459
|
-
providerMetadata: {
|
|
460
|
-
provider: "vercel",
|
|
461
|
-
sandboxId: sandbox2.sandboxId,
|
|
462
|
-
snapshotId
|
|
463
|
-
}
|
|
464
|
-
});
|
|
465
|
-
await startLifecycleWorkflow(sandbox2.sandboxId);
|
|
466
|
-
return sandbox2.sandboxId;
|
|
467
|
-
},
|
|
468
|
-
catch: (e) => new SandboxError({ reason: String(e), cause: e })
|
|
469
|
-
});
|
|
470
|
-
}
|
|
471
|
-
async function createFreshSandbox() {
|
|
472
|
-
return await errore2.tryAsync({
|
|
473
|
-
try: async () => {
|
|
474
|
-
const sandbox2 = await VercelSandboxSDK.create({
|
|
475
|
-
resources: { vcpus },
|
|
476
|
-
timeout: VERCEL_MAX_TIMEOUT_MS,
|
|
477
|
-
ports,
|
|
478
|
-
networkPolicy,
|
|
479
|
-
...getTestCredentials()
|
|
480
|
-
});
|
|
481
|
-
const now = Date.now();
|
|
482
|
-
await storage.sandbox.set({
|
|
483
|
-
id,
|
|
484
|
-
config,
|
|
485
|
-
tags: sandboxRecord.tags,
|
|
486
|
-
createdAt: now,
|
|
487
|
-
lastActivityAt: now,
|
|
488
|
-
acquiringLockId: null,
|
|
489
|
-
acquiringLockAt: null,
|
|
490
|
-
providerMetadata: {
|
|
491
|
-
provider: "vercel",
|
|
492
|
-
sandboxId: sandbox2.sandboxId,
|
|
493
|
-
snapshotId: null
|
|
494
|
-
}
|
|
495
|
-
});
|
|
496
|
-
await startLifecycleWorkflow(sandbox2.sandboxId);
|
|
497
|
-
return sandbox2.sandboxId;
|
|
498
|
-
},
|
|
499
|
-
catch: (e) => new SandboxError({ reason: String(e), cause: e })
|
|
500
|
-
});
|
|
501
|
-
}
|
|
502
|
-
function execOnInstance(instance, {
|
|
503
|
-
command,
|
|
504
|
-
args,
|
|
505
|
-
signal
|
|
506
|
-
}) {
|
|
507
|
-
return errore2.tryAsync({
|
|
508
|
-
try: async () => {
|
|
509
|
-
const output = await instance.runCommand({
|
|
510
|
-
cwd: HOME_DIR,
|
|
511
|
-
args,
|
|
512
|
-
cmd: command,
|
|
513
|
-
signal,
|
|
514
|
-
detached: true
|
|
515
|
-
});
|
|
516
|
-
let stdout = "";
|
|
517
|
-
let stderr = "";
|
|
518
|
-
const logBuffer = [];
|
|
519
|
-
const state = {
|
|
520
|
-
resolve: null,
|
|
521
|
-
consumed: false
|
|
522
|
-
};
|
|
523
|
-
const consumeLogs = (async () => {
|
|
524
|
-
try {
|
|
525
|
-
for await (const log of output.logs()) {
|
|
526
|
-
const entry = log.stream === "stdout" ? { stream: "stdout", data: log.data } : { stream: "stderr", data: log.data };
|
|
527
|
-
if (log.stream === "stdout") {
|
|
528
|
-
stdout += log.data;
|
|
529
|
-
} else {
|
|
530
|
-
stderr += log.data;
|
|
531
|
-
}
|
|
532
|
-
logBuffer.push(entry);
|
|
533
|
-
state.resolve?.();
|
|
534
|
-
}
|
|
535
|
-
} catch {
|
|
536
|
-
}
|
|
537
|
-
state.consumed = true;
|
|
538
|
-
state.resolve?.();
|
|
539
|
-
})();
|
|
540
|
-
async function* logs() {
|
|
541
|
-
let index = 0;
|
|
542
|
-
while (!state.consumed || index < logBuffer.length) {
|
|
543
|
-
if (index < logBuffer.length) {
|
|
544
|
-
yield logBuffer[index++];
|
|
545
|
-
} else {
|
|
546
|
-
await new Promise((resolve) => {
|
|
547
|
-
state.resolve = resolve;
|
|
548
|
-
});
|
|
549
|
-
state.resolve = null;
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
const result = consumeLogs.then(async () => {
|
|
554
|
-
try {
|
|
555
|
-
const finished = await output.wait();
|
|
556
|
-
return {
|
|
557
|
-
stdout,
|
|
558
|
-
stderr,
|
|
559
|
-
exitCode: finished.exitCode
|
|
560
|
-
};
|
|
561
|
-
} catch (e) {
|
|
562
|
-
if (isSandboxGoneError(e)) {
|
|
563
|
-
return { stdout, stderr, exitCode: 1 };
|
|
564
|
-
}
|
|
565
|
-
throw e;
|
|
566
|
-
}
|
|
567
|
-
});
|
|
568
|
-
return { commandId: output.cmdId, logs, result };
|
|
569
|
-
},
|
|
570
|
-
catch: (e) => new SandboxError({ reason: String(e), cause: e })
|
|
571
|
-
});
|
|
572
|
-
}
|
|
573
|
-
function readFileOnInstance(instance, { path: path4 }) {
|
|
574
|
-
return errore2.tryAsync({
|
|
575
|
-
try: () => instance.readFileToBuffer({ path: path4, cwd: HOME_DIR }),
|
|
576
|
-
catch: (e) => new SandboxError({ reason: String(e), cause: e })
|
|
577
|
-
});
|
|
578
|
-
}
|
|
579
|
-
async function writeFilesOnInstance(instance, opts) {
|
|
580
|
-
const { files, destPath } = opts;
|
|
581
|
-
if (files.length === 0) {
|
|
582
|
-
return;
|
|
583
|
-
}
|
|
584
|
-
const nativeFiles = files.map((file) => {
|
|
585
|
-
const filePath = path3.posix.join(destPath, file.path);
|
|
586
|
-
const absolutePath = path3.posix.isAbsolute(filePath) ? filePath : path3.posix.join(HOME_DIR, filePath);
|
|
587
|
-
return {
|
|
588
|
-
path: absolutePath,
|
|
589
|
-
content: typeof file.content === "string" ? Buffer.from(file.content) : file.content
|
|
590
|
-
};
|
|
591
|
-
});
|
|
592
|
-
await instance.writeFiles(nativeFiles);
|
|
593
|
-
const shellScripts = nativeFiles.filter((f) => f.path.endsWith(".sh"));
|
|
594
|
-
if (shellScripts.length > 0) {
|
|
595
|
-
const chmodResult = await execOnInstance(instance, {
|
|
596
|
-
command: "chmod",
|
|
597
|
-
args: ["+x", ...shellScripts.map((f) => f.path)]
|
|
598
|
-
});
|
|
599
|
-
if (chmodResult instanceof Error) {
|
|
600
|
-
throw chmodResult;
|
|
601
|
-
}
|
|
602
|
-
await chmodResult.result;
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
function createTempSandbox(instance) {
|
|
606
|
-
const tempSandbox = {
|
|
607
|
-
id: `__setup_temp_${Date.now()}`,
|
|
608
|
-
config,
|
|
609
|
-
exec: (opts) => execOnInstance(instance, opts),
|
|
610
|
-
readFile: (opts) => readFileOnInstance(instance, opts),
|
|
611
|
-
getDomain: () => Promise.resolve(
|
|
612
|
-
new SandboxError({ reason: "not available during setup" })
|
|
613
|
-
),
|
|
614
|
-
kill: () => Promise.resolve(
|
|
615
|
-
new SandboxError({ reason: "not available during setup" })
|
|
616
|
-
),
|
|
617
|
-
writeFiles: (opts) => writeFilesOnInstance(instance, opts),
|
|
618
|
-
updateNetworkPolicy: (policy) => errore2.tryAsync({
|
|
619
|
-
try: () => instance.updateNetworkPolicy(policy),
|
|
620
|
-
catch: (e) => new SandboxError({ reason: String(e), cause: e })
|
|
621
|
-
}),
|
|
622
|
-
tag: {
|
|
623
|
-
list: async () => ({}),
|
|
624
|
-
get: async () => void 0,
|
|
625
|
-
set: async () => void 0,
|
|
626
|
-
setMany: async () => void 0
|
|
627
|
-
}
|
|
628
|
-
};
|
|
629
|
-
return tempSandbox;
|
|
630
|
-
}
|
|
631
|
-
async function pollForSetupSnapshot(key) {
|
|
632
|
-
const deadline = Date.now() + LOCK_TIMEOUT_MS;
|
|
633
|
-
while (Date.now() < deadline) {
|
|
634
|
-
await new Promise((r) => setTimeout(r, LOCK_POLL_INTERVAL_MS));
|
|
635
|
-
const record = await storage.setup.get(key);
|
|
636
|
-
if (record instanceof Error) {
|
|
637
|
-
return null;
|
|
638
|
-
}
|
|
639
|
-
if (record?.snapshotId) {
|
|
640
|
-
return record.snapshotId;
|
|
641
|
-
}
|
|
642
|
-
if (!record?.acquiringLockId) {
|
|
643
|
-
return null;
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
return null;
|
|
647
|
-
}
|
|
648
|
-
async function createSetupSnapshot(opts) {
|
|
649
|
-
if (!setup) {
|
|
650
|
-
return;
|
|
651
|
-
}
|
|
652
|
-
const setupKey = setup.key;
|
|
653
|
-
if (!opts?.force) {
|
|
654
|
-
const existing = await storage.setup.get(setupKey);
|
|
655
|
-
if (!(existing instanceof Error) && existing?.snapshotId) {
|
|
656
|
-
return;
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
debug(`[sandbox:setup] acquiring lock for setup key "${setupKey}"`);
|
|
660
|
-
const lockId = crypto.randomUUID();
|
|
661
|
-
const locked = await storage.setup.acquireLock(
|
|
662
|
-
setupKey,
|
|
663
|
-
lockId,
|
|
664
|
-
LOCK_TIMEOUT_MS
|
|
665
|
-
);
|
|
666
|
-
if (locked instanceof Error || !locked) {
|
|
667
|
-
debug(
|
|
668
|
-
`[sandbox:setup] lock not acquired for key "${setupKey}" (another process holds it)`
|
|
669
|
-
);
|
|
670
|
-
return;
|
|
671
|
-
}
|
|
672
|
-
if (!opts?.force && locked.snapshotId) {
|
|
673
|
-
debug(
|
|
674
|
-
`[sandbox:setup] snapshot already exists after lock for key "${setupKey}", skipping`
|
|
675
|
-
);
|
|
676
|
-
return;
|
|
677
|
-
}
|
|
678
|
-
let tempInstance = null;
|
|
679
|
-
try {
|
|
680
|
-
debug(
|
|
681
|
-
`[sandbox:setup] creating temp sandbox for snapshot (key="${setupKey}")`
|
|
682
|
-
);
|
|
683
|
-
tempInstance = await VercelSandboxSDK.create({
|
|
684
|
-
resources: { vcpus },
|
|
685
|
-
timeout: VERCEL_MAX_TIMEOUT_MS,
|
|
686
|
-
ports,
|
|
687
|
-
networkPolicy,
|
|
688
|
-
...getTestCredentials()
|
|
689
|
-
});
|
|
690
|
-
const tempSandbox = createTempSandbox(
|
|
691
|
-
tempInstance
|
|
692
|
-
);
|
|
693
|
-
await setup.run(tempSandbox);
|
|
694
|
-
debug(
|
|
695
|
-
`[sandbox:setup] setup.run complete, snapshotting (key="${setupKey}")`
|
|
696
|
-
);
|
|
697
|
-
const snapshot = await tempInstance.snapshot();
|
|
698
|
-
await storage.setup.set({
|
|
699
|
-
key: setupKey,
|
|
700
|
-
snapshotId: snapshot.snapshotId,
|
|
701
|
-
createdAt: locked.createdAt,
|
|
702
|
-
lastUsedAt: null,
|
|
703
|
-
acquiringLockId: null,
|
|
704
|
-
acquiringLockAt: null
|
|
705
|
-
});
|
|
706
|
-
debug(
|
|
707
|
-
`[sandbox:setup] snapshot stored: ${snapshot.snapshotId} (key="${setupKey}")`
|
|
708
|
-
);
|
|
709
|
-
await tempInstance.stop().catch(() => void 0);
|
|
710
|
-
} catch (e) {
|
|
711
|
-
console.error(
|
|
712
|
-
`[sandbox:setup] failed to create setup snapshot (key="${setupKey}"):`,
|
|
713
|
-
e
|
|
714
|
-
);
|
|
715
|
-
if (tempInstance) {
|
|
716
|
-
await tempInstance.stop().catch(() => void 0);
|
|
717
|
-
}
|
|
718
|
-
await storage.setup.set({
|
|
719
|
-
key: setupKey,
|
|
720
|
-
snapshotId: null,
|
|
721
|
-
createdAt: locked.createdAt,
|
|
722
|
-
lastUsedAt: null,
|
|
723
|
-
acquiringLockId: null,
|
|
724
|
-
acquiringLockAt: null
|
|
725
|
-
}).catch(() => void 0);
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
async function doGetOrCreateSandboxId() {
|
|
729
|
-
if (initialVercel?.sandboxId && !recoveredFromStale) {
|
|
730
|
-
return initialVercel.sandboxId;
|
|
731
|
-
}
|
|
732
|
-
const existing = await storage.sandbox.get(id);
|
|
733
|
-
if (existing instanceof Error) {
|
|
734
|
-
if (existing instanceof SandboxNotFoundError) {
|
|
735
|
-
} else {
|
|
736
|
-
return new SandboxError({ reason: existing.message, cause: existing });
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
const existingRecord = existing instanceof SandboxNotFoundError ? null : existing;
|
|
740
|
-
const existingVercel = existingRecord?.providerMetadata?.provider === "vercel" ? existingRecord.providerMetadata : null;
|
|
741
|
-
if (existingVercel?.sandboxId) {
|
|
742
|
-
return existingVercel.sandboxId;
|
|
743
|
-
}
|
|
744
|
-
const hasActiveLock = existingRecord?.acquiringLockId && existingRecord.acquiringLockAt && Date.now() - existingRecord.acquiringLockAt < LOCK_TIMEOUT_MS;
|
|
745
|
-
if (hasActiveLock) {
|
|
746
|
-
return pollForSandboxId();
|
|
747
|
-
}
|
|
748
|
-
const lockId = crypto.randomUUID();
|
|
749
|
-
const now = Date.now();
|
|
750
|
-
const locked = await storage.sandbox.acquireLock(
|
|
751
|
-
{
|
|
752
|
-
id,
|
|
753
|
-
config,
|
|
754
|
-
tags: existingRecord?.tags ?? sandboxRecord.tags,
|
|
755
|
-
createdAt: existingRecord?.createdAt ?? sandboxRecord.createdAt,
|
|
756
|
-
lastActivityAt: existingRecord?.lastActivityAt ?? sandboxRecord.lastActivityAt,
|
|
757
|
-
acquiringLockId: lockId,
|
|
758
|
-
acquiringLockAt: now,
|
|
759
|
-
providerMetadata: {
|
|
760
|
-
provider: "vercel",
|
|
761
|
-
sandboxId: null,
|
|
762
|
-
snapshotId: existingVercel?.snapshotId ?? initialVercel?.snapshotId ?? null
|
|
763
|
-
}
|
|
764
|
-
},
|
|
765
|
-
LOCK_TIMEOUT_MS
|
|
766
|
-
);
|
|
767
|
-
if (locked instanceof Error) {
|
|
768
|
-
return new SandboxError({ reason: locked.message, cause: locked });
|
|
769
|
-
}
|
|
770
|
-
if (!locked) {
|
|
771
|
-
return pollForSandboxId();
|
|
772
|
-
}
|
|
773
|
-
const lockedRecord = locked;
|
|
774
|
-
async function releaseSandboxLock() {
|
|
775
|
-
await storage.sandbox.set({
|
|
776
|
-
...lockedRecord,
|
|
777
|
-
acquiringLockId: null,
|
|
778
|
-
acquiringLockAt: null
|
|
779
|
-
}).catch(() => void 0);
|
|
780
|
-
}
|
|
781
|
-
const lockedVercel = lockedRecord.providerMetadata?.provider === "vercel" ? lockedRecord.providerMetadata : null;
|
|
782
|
-
if (lockedVercel?.sandboxId) {
|
|
783
|
-
await releaseSandboxLock();
|
|
784
|
-
return lockedVercel.sandboxId;
|
|
785
|
-
}
|
|
786
|
-
const snapshotId = lockedVercel?.snapshotId ?? initialVercel?.snapshotId ?? config.lifecycle?.snapshotId;
|
|
787
|
-
if (snapshotId) {
|
|
788
|
-
const result = await createSandboxFromSnapshot(snapshotId);
|
|
789
|
-
if (!(result instanceof Error)) {
|
|
790
|
-
createdFromSnapshot = true;
|
|
791
|
-
return result;
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
if (setup) {
|
|
795
|
-
let forceRecreateSnapshot = false;
|
|
796
|
-
const setupRecord = await storage.setup.get(setup.key);
|
|
797
|
-
if (!(setupRecord instanceof Error) && setupRecord) {
|
|
798
|
-
if (setupRecord.snapshotId) {
|
|
799
|
-
debug(
|
|
800
|
-
`[sandbox:setup] found setup snapshot ${setupRecord.snapshotId} for key "${setup.key}"`
|
|
801
|
-
);
|
|
802
|
-
const result = await createSandboxFromSnapshot(
|
|
803
|
-
setupRecord.snapshotId
|
|
804
|
-
);
|
|
805
|
-
if (!(result instanceof Error)) {
|
|
806
|
-
createdFromSnapshot = true;
|
|
807
|
-
storage.setup.set({
|
|
808
|
-
...setupRecord,
|
|
809
|
-
lastUsedAt: Date.now()
|
|
810
|
-
}).catch(() => void 0);
|
|
811
|
-
return result;
|
|
812
|
-
}
|
|
813
|
-
debug(
|
|
814
|
-
`[sandbox:setup] snapshot ${setupRecord.snapshotId} failed (expired?), will recreate`
|
|
815
|
-
);
|
|
816
|
-
forceRecreateSnapshot = true;
|
|
817
|
-
} else if (setupRecord.acquiringLockId && setupRecord.acquiringLockAt && Date.now() - setupRecord.acquiringLockAt < LOCK_TIMEOUT_MS) {
|
|
818
|
-
debug(
|
|
819
|
-
`[sandbox:setup] snapshot in progress for key "${setup.key}", waiting...`
|
|
820
|
-
);
|
|
821
|
-
const snapshotId2 = await pollForSetupSnapshot(setup.key);
|
|
822
|
-
if (snapshotId2) {
|
|
823
|
-
debug(
|
|
824
|
-
`[sandbox:setup] snapshot ready: ${snapshotId2} for key "${setup.key}"`
|
|
825
|
-
);
|
|
826
|
-
const result = await createSandboxFromSnapshot(snapshotId2);
|
|
827
|
-
if (!(result instanceof Error)) {
|
|
828
|
-
createdFromSnapshot = true;
|
|
829
|
-
return result;
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
}
|
|
833
|
-
}
|
|
834
|
-
debug(
|
|
835
|
-
`[sandbox:setup] no snapshot for key "${setup.key}", will run setup on this sandbox`
|
|
836
|
-
);
|
|
837
|
-
needsSetupRun = true;
|
|
838
|
-
createSetupSnapshot({ force: forceRecreateSnapshot }).catch((e) => {
|
|
839
|
-
console.error(
|
|
840
|
-
"[sandbox:setup] failed to create background snapshot:",
|
|
841
|
-
e
|
|
842
|
-
);
|
|
843
|
-
});
|
|
844
|
-
}
|
|
845
|
-
const freshResult = await createFreshSandbox();
|
|
846
|
-
if (freshResult instanceof Error) {
|
|
847
|
-
await releaseSandboxLock();
|
|
848
|
-
}
|
|
849
|
-
return freshResult;
|
|
850
|
-
}
|
|
851
|
-
function getOrCreateSandboxId() {
|
|
852
|
-
const cached = createPromises.get(id);
|
|
853
|
-
if (cached) {
|
|
854
|
-
return cached;
|
|
855
|
-
}
|
|
856
|
-
const promise = doGetOrCreateSandboxId().finally(() => {
|
|
857
|
-
createPromises.delete(id);
|
|
858
|
-
});
|
|
859
|
-
createPromises.set(id, promise);
|
|
860
|
-
return promise;
|
|
861
|
-
}
|
|
862
|
-
async function doGetSandbox() {
|
|
863
|
-
const vercelSandboxId = await getOrCreateSandboxId();
|
|
864
|
-
if (vercelSandboxId instanceof Error) {
|
|
865
|
-
return vercelSandboxId;
|
|
866
|
-
}
|
|
867
|
-
return errore2.tryAsync({
|
|
868
|
-
try: () => VercelSandboxSDK.get({
|
|
869
|
-
sandboxId: vercelSandboxId,
|
|
870
|
-
...getTestCredentials()
|
|
871
|
-
}),
|
|
872
|
-
catch: (e) => new SandboxError({ reason: String(e), cause: e })
|
|
873
|
-
});
|
|
874
|
-
}
|
|
875
|
-
function getSandbox2() {
|
|
876
|
-
if (!sandboxPromise) {
|
|
877
|
-
sandboxPromise = doGetSandbox();
|
|
878
|
-
}
|
|
879
|
-
return sandboxPromise;
|
|
880
|
-
}
|
|
881
|
-
async function recoverFromStaleSandbox() {
|
|
882
|
-
sandboxPromise = null;
|
|
883
|
-
recoveredFromStale = true;
|
|
884
|
-
const existing = await storage.sandbox.get(id);
|
|
885
|
-
if (existing instanceof Error || !existing) {
|
|
886
|
-
return;
|
|
887
|
-
}
|
|
888
|
-
const existingVercel = existing.providerMetadata?.provider === "vercel" ? existing.providerMetadata : null;
|
|
889
|
-
if (existingVercel?.sandboxId) {
|
|
890
|
-
await storage.sandbox.set({
|
|
891
|
-
id: existing.id,
|
|
892
|
-
config: existing.config,
|
|
893
|
-
tags: existing.tags,
|
|
894
|
-
createdAt: existing.createdAt,
|
|
895
|
-
lastActivityAt: existing.lastActivityAt,
|
|
896
|
-
acquiringLockId: null,
|
|
897
|
-
acquiringLockAt: null,
|
|
898
|
-
providerMetadata: {
|
|
899
|
-
provider: "vercel",
|
|
900
|
-
sandboxId: null,
|
|
901
|
-
snapshotId: existingVercel.snapshotId
|
|
902
|
-
}
|
|
903
|
-
});
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
async function updateLastActivity() {
|
|
907
|
-
const now = Date.now();
|
|
908
|
-
const lastSent = lastActivitySent.get(id);
|
|
909
|
-
if (lastSent && now - lastSent < ACTIVITY_THROTTLE_MS) {
|
|
910
|
-
return;
|
|
911
|
-
}
|
|
912
|
-
lastActivitySent.set(id, now);
|
|
913
|
-
const existing = await storage.sandbox.get(id);
|
|
914
|
-
if (existing instanceof Error || !existing) {
|
|
915
|
-
return;
|
|
916
|
-
}
|
|
917
|
-
const existingVercel = existing.providerMetadata?.provider === "vercel" ? existing.providerMetadata : null;
|
|
918
|
-
await storage.sandbox.set({
|
|
919
|
-
id: existing.id,
|
|
920
|
-
config: existing.config,
|
|
921
|
-
tags: existing.tags,
|
|
922
|
-
createdAt: existing.createdAt,
|
|
923
|
-
lastActivityAt: now,
|
|
924
|
-
acquiringLockId: null,
|
|
925
|
-
acquiringLockAt: null,
|
|
926
|
-
providerMetadata: existingVercel ?? {
|
|
927
|
-
provider: "vercel",
|
|
928
|
-
sandboxId: null,
|
|
929
|
-
snapshotId: null
|
|
930
|
-
}
|
|
931
|
-
});
|
|
932
|
-
}
|
|
933
|
-
const lifecycle = {
|
|
934
|
-
start: async () => {
|
|
935
|
-
const sandbox2 = await getSandbox2();
|
|
936
|
-
if (sandbox2 instanceof Error) {
|
|
937
|
-
return sandbox2;
|
|
938
|
-
}
|
|
939
|
-
await updateLastActivity();
|
|
940
|
-
return sandbox2.status;
|
|
941
|
-
},
|
|
942
|
-
snapshot: async () => {
|
|
943
|
-
const sandbox2 = await getSandbox2();
|
|
944
|
-
if (sandbox2 instanceof Error) {
|
|
945
|
-
return sandbox2;
|
|
946
|
-
}
|
|
947
|
-
return errore2.tryAsync({
|
|
948
|
-
try: async () => {
|
|
949
|
-
const existing = await storage.sandbox.get(id);
|
|
950
|
-
const snapshot = await sandbox2.snapshot();
|
|
951
|
-
await storage.sandbox.set({
|
|
952
|
-
id,
|
|
953
|
-
config,
|
|
954
|
-
tags: existing instanceof Error ? null : existing?.tags ?? null,
|
|
955
|
-
createdAt: existing instanceof Error ? null : existing?.createdAt ?? null,
|
|
956
|
-
lastActivityAt: existing instanceof Error ? null : existing?.lastActivityAt ?? null,
|
|
957
|
-
acquiringLockId: null,
|
|
958
|
-
acquiringLockAt: null,
|
|
959
|
-
providerMetadata: {
|
|
960
|
-
provider: "vercel",
|
|
961
|
-
sandboxId: null,
|
|
962
|
-
snapshotId: snapshot.snapshotId
|
|
963
|
-
}
|
|
964
|
-
});
|
|
965
|
-
return { snapshotId: snapshot.snapshotId };
|
|
966
|
-
},
|
|
967
|
-
catch: (e) => new SandboxError({ reason: String(e), cause: e })
|
|
968
|
-
});
|
|
969
|
-
},
|
|
970
|
-
stop: async () => {
|
|
971
|
-
const sandbox2 = await getSandbox2();
|
|
972
|
-
if (sandbox2 instanceof Error) {
|
|
973
|
-
return sandbox2;
|
|
974
|
-
}
|
|
975
|
-
return errore2.tryAsync({
|
|
976
|
-
try: async () => {
|
|
977
|
-
await sandbox2.stop();
|
|
978
|
-
const existing = await storage.sandbox.get(id);
|
|
979
|
-
if (existing instanceof Error || !existing) {
|
|
980
|
-
return void 0;
|
|
981
|
-
}
|
|
982
|
-
await storage.sandbox.set({
|
|
983
|
-
id: existing.id,
|
|
984
|
-
config: existing.config,
|
|
985
|
-
tags: existing.tags,
|
|
986
|
-
createdAt: existing.createdAt,
|
|
987
|
-
lastActivityAt: existing.lastActivityAt,
|
|
988
|
-
acquiringLockId: null,
|
|
989
|
-
acquiringLockAt: null,
|
|
990
|
-
providerMetadata: {
|
|
991
|
-
provider: "vercel",
|
|
992
|
-
sandboxId: null,
|
|
993
|
-
snapshotId: null
|
|
994
|
-
}
|
|
995
|
-
});
|
|
996
|
-
return void 0;
|
|
997
|
-
},
|
|
998
|
-
catch: (e) => new SandboxError({ reason: String(e), cause: e })
|
|
999
|
-
});
|
|
1000
|
-
},
|
|
1001
|
-
getStatus: async () => {
|
|
1002
|
-
const sandbox2 = await getSandbox2();
|
|
1003
|
-
if (sandbox2 instanceof Error) {
|
|
1004
|
-
return sandbox2;
|
|
1005
|
-
}
|
|
1006
|
-
return sandbox2.status;
|
|
1007
|
-
},
|
|
1008
|
-
getCreatedAt: async () => {
|
|
1009
|
-
const sandbox2 = await getSandbox2();
|
|
1010
|
-
if (sandbox2 instanceof Error) {
|
|
1011
|
-
return sandbox2;
|
|
1012
|
-
}
|
|
1013
|
-
return sandbox2.createdAt;
|
|
1014
|
-
},
|
|
1015
|
-
getRemainingTimeout: async () => {
|
|
1016
|
-
const sandbox2 = await getSandbox2();
|
|
1017
|
-
if (sandbox2 instanceof Error) {
|
|
1018
|
-
return sandbox2;
|
|
1019
|
-
}
|
|
1020
|
-
return sandbox2.timeout;
|
|
1021
|
-
}
|
|
1022
|
-
};
|
|
1023
|
-
async function doExec(opts) {
|
|
1024
|
-
const instance = await getSandbox2();
|
|
1025
|
-
if (instance instanceof Error) {
|
|
1026
|
-
return instance;
|
|
1027
|
-
}
|
|
1028
|
-
const updatePromise = updateLastActivity();
|
|
1029
|
-
const execResult = await execOnInstance(instance, opts);
|
|
1030
|
-
await updatePromise;
|
|
1031
|
-
return execResult;
|
|
1032
|
-
}
|
|
1033
|
-
const sandbox = {
|
|
1034
|
-
id,
|
|
1035
|
-
config,
|
|
1036
|
-
exec: async (opts) => {
|
|
1037
|
-
const result = await doExec(opts);
|
|
1038
|
-
if (result instanceof SandboxError && isSandboxGoneError(result.cause)) {
|
|
1039
|
-
await recoverFromStaleSandbox();
|
|
1040
|
-
return await doExec(opts);
|
|
1041
|
-
}
|
|
1042
|
-
return result;
|
|
1043
|
-
},
|
|
1044
|
-
getDomain: async (port) => {
|
|
1045
|
-
const sandbox2 = await getSandbox2();
|
|
1046
|
-
if (sandbox2 instanceof Error) {
|
|
1047
|
-
return sandbox2;
|
|
1048
|
-
}
|
|
1049
|
-
try {
|
|
1050
|
-
return sandbox2.domain(port);
|
|
1051
|
-
} catch (e) {
|
|
1052
|
-
return new SandboxError({ reason: String(e), cause: e });
|
|
1053
|
-
}
|
|
1054
|
-
},
|
|
1055
|
-
kill: async ({ commandId, storage: cmdStorage }) => {
|
|
1056
|
-
const instance = await getSandbox2();
|
|
1057
|
-
if (instance instanceof Error) {
|
|
1058
|
-
return instance;
|
|
1059
|
-
}
|
|
1060
|
-
const cmd = await cmdStorage.command.get(commandId);
|
|
1061
|
-
if (cmd instanceof Error) {
|
|
1062
|
-
return new SandboxError({ reason: cmd.message, cause: cmd });
|
|
1063
|
-
}
|
|
1064
|
-
if (cmd && cmd.status === "running") {
|
|
1065
|
-
const result = await cmdStorage.command.set({
|
|
1066
|
-
...cmd,
|
|
1067
|
-
status: "killed"
|
|
1068
|
-
});
|
|
1069
|
-
if (result instanceof Error) {
|
|
1070
|
-
return new SandboxError({ reason: result.message, cause: result });
|
|
1071
|
-
}
|
|
1072
|
-
}
|
|
1073
|
-
return void 0;
|
|
1074
|
-
},
|
|
1075
|
-
readFile: async (opts) => {
|
|
1076
|
-
const instance = await getSandbox2();
|
|
1077
|
-
if (instance instanceof Error) {
|
|
1078
|
-
return instance;
|
|
1079
|
-
}
|
|
1080
|
-
return readFileOnInstance(instance, opts);
|
|
1081
|
-
},
|
|
1082
|
-
writeFiles: async (opts) => {
|
|
1083
|
-
const instance = await getSandbox2();
|
|
1084
|
-
if (instance instanceof Error) {
|
|
1085
|
-
throw instance;
|
|
1086
|
-
}
|
|
1087
|
-
return writeFilesOnInstance(instance, opts);
|
|
1088
|
-
},
|
|
1089
|
-
lifecycle,
|
|
1090
|
-
updateNetworkPolicy: async (policy) => {
|
|
1091
|
-
const instance = await getSandbox2();
|
|
1092
|
-
if (instance instanceof Error) {
|
|
1093
|
-
return instance;
|
|
1094
|
-
}
|
|
1095
|
-
return errore2.tryAsync({
|
|
1096
|
-
try: () => instance.updateNetworkPolicy(policy),
|
|
1097
|
-
catch: (e) => new SandboxError({ reason: String(e), cause: e })
|
|
1098
|
-
});
|
|
1099
|
-
},
|
|
1100
|
-
tag: {
|
|
1101
|
-
list: async () => {
|
|
1102
|
-
const sandboxRecord2 = await storage.sandbox.get(id);
|
|
1103
|
-
if (sandboxRecord2 instanceof Error) {
|
|
1104
|
-
return sandboxRecord2;
|
|
1105
|
-
}
|
|
1106
|
-
return sandboxRecord2.tags ?? {};
|
|
1107
|
-
},
|
|
1108
|
-
get: async (key) => {
|
|
1109
|
-
const sandboxRecord2 = await storage.sandbox.get(id);
|
|
1110
|
-
if (sandboxRecord2 instanceof Error) {
|
|
1111
|
-
return sandboxRecord2;
|
|
1112
|
-
}
|
|
1113
|
-
return sandboxRecord2.tags?.[key];
|
|
1114
|
-
},
|
|
1115
|
-
set: async (key, value) => {
|
|
1116
|
-
const result = await storage.sandbox.tag.set({
|
|
1117
|
-
sandboxId: id,
|
|
1118
|
-
tags: { [key]: value }
|
|
1119
|
-
});
|
|
1120
|
-
if (result instanceof Error) {
|
|
1121
|
-
return result;
|
|
1122
|
-
}
|
|
1123
|
-
return void 0;
|
|
1124
|
-
},
|
|
1125
|
-
setMany: async (tags) => {
|
|
1126
|
-
const result = await storage.sandbox.tag.set({
|
|
1127
|
-
sandboxId: id,
|
|
1128
|
-
tags
|
|
1129
|
-
});
|
|
1130
|
-
if (result instanceof Error) {
|
|
1131
|
-
return result;
|
|
1132
|
-
}
|
|
1133
|
-
return void 0;
|
|
1134
|
-
}
|
|
1135
|
-
}
|
|
1136
|
-
};
|
|
1137
|
-
let onReadyPromise = Promise.resolve();
|
|
1138
|
-
let setupMetaPromise = Promise.resolve({
|
|
1139
|
-
needsSetupRun: false,
|
|
1140
|
-
createdFromSnapshot: false
|
|
1141
|
-
});
|
|
1142
|
-
if (config.lifecycle?.autoStart !== false) {
|
|
1143
|
-
sandboxPromise = doGetSandbox();
|
|
1144
|
-
setupMetaPromise = sandboxPromise.then(() => ({
|
|
1145
|
-
needsSetupRun,
|
|
1146
|
-
createdFromSnapshot
|
|
1147
|
-
}));
|
|
1148
|
-
onReadyPromise = sandboxPromise.then(async (instance) => {
|
|
1149
|
-
if (instance instanceof Error) {
|
|
1150
|
-
return;
|
|
1151
|
-
}
|
|
1152
|
-
if (needsSetupRun && setup) {
|
|
1153
|
-
debug(
|
|
1154
|
-
`[sandbox:setup] running setup.run on session sandbox (key="${setup.key}")`
|
|
1155
|
-
);
|
|
1156
|
-
await setup.run(sandbox);
|
|
1157
|
-
debug("[sandbox:setup] setup.run complete on session sandbox");
|
|
1158
|
-
}
|
|
1159
|
-
if (createdFromSnapshot && onRestart) {
|
|
1160
|
-
debug("[sandbox:setup] running onRestart (created from snapshot)");
|
|
1161
|
-
await onRestart(sandbox);
|
|
1162
|
-
}
|
|
1163
|
-
});
|
|
1164
|
-
}
|
|
1165
|
-
sandbox._onReady = onReadyPromise;
|
|
1166
|
-
sandbox._setupMeta = setupMetaPromise;
|
|
1167
|
-
return sandbox;
|
|
1168
|
-
};
|
|
1169
|
-
|
|
1170
|
-
// src/sandbox/client.ts
|
|
1171
|
-
var sandboxCache = /* @__PURE__ */ new Map();
|
|
1172
|
-
function getSandbox({
|
|
1173
|
-
sandboxRecord,
|
|
1174
|
-
storageConfig,
|
|
1175
|
-
storage,
|
|
1176
|
-
enableLifecycleWorkflow = true,
|
|
1177
|
-
setup,
|
|
1178
|
-
onRestart
|
|
1179
|
-
}) {
|
|
1180
|
-
const cached = sandboxCache.get(sandboxRecord.id);
|
|
1181
|
-
if (cached) {
|
|
1182
|
-
debug("[getSandbox] cache hit for", sandboxRecord.id);
|
|
1183
|
-
return cached;
|
|
1184
|
-
}
|
|
1185
|
-
const sbx = createSandbox({
|
|
1186
|
-
sandboxRecord,
|
|
1187
|
-
storageConfig,
|
|
1188
|
-
storage,
|
|
1189
|
-
enableLifecycleWorkflow,
|
|
1190
|
-
setup,
|
|
1191
|
-
onRestart
|
|
1192
|
-
});
|
|
1193
|
-
sandboxCache.set(sandboxRecord.id, sbx);
|
|
1194
|
-
return sbx;
|
|
1195
|
-
}
|
|
1196
|
-
function createSandbox({
|
|
1197
|
-
sandboxRecord,
|
|
1198
|
-
storageConfig,
|
|
1199
|
-
storage,
|
|
1200
|
-
enableLifecycleWorkflow = true,
|
|
1201
|
-
setup,
|
|
1202
|
-
onRestart
|
|
1203
|
-
}) {
|
|
1204
|
-
let sbx;
|
|
1205
|
-
switch (sandboxRecord.config.type) {
|
|
1206
|
-
case "local":
|
|
1207
|
-
sbx = localSandbox({
|
|
1208
|
-
sandboxRecord,
|
|
1209
|
-
storage,
|
|
1210
|
-
setup,
|
|
1211
|
-
onRestart
|
|
1212
|
-
});
|
|
1213
|
-
break;
|
|
1214
|
-
case "vercel":
|
|
1215
|
-
sbx = vercelSandbox({
|
|
1216
|
-
sandboxRecord,
|
|
1217
|
-
storageConfig,
|
|
1218
|
-
storage,
|
|
1219
|
-
enableLifecycleWorkflow,
|
|
1220
|
-
setup,
|
|
1221
|
-
onRestart
|
|
1222
|
-
});
|
|
1223
|
-
break;
|
|
1224
|
-
case "custom":
|
|
1225
|
-
throw new Error("Custom sandboxes are not supported");
|
|
1226
|
-
default:
|
|
1227
|
-
sandboxRecord.config;
|
|
1228
|
-
throw new Error(
|
|
1229
|
-
`Unknown sandbox type: ${// biome-ignore lint/suspicious/noExplicitAny: .
|
|
1230
|
-
sandboxRecord.config.type}`
|
|
1231
|
-
);
|
|
1232
|
-
}
|
|
1233
|
-
if (!sbx._onReady) {
|
|
1234
|
-
return sbx;
|
|
1235
|
-
}
|
|
1236
|
-
const onReady = sbx._onReady;
|
|
1237
|
-
return {
|
|
1238
|
-
...sbx,
|
|
1239
|
-
exec: async (opts) => {
|
|
1240
|
-
await onReady;
|
|
1241
|
-
return sbx.exec(opts);
|
|
1242
|
-
},
|
|
1243
|
-
getDomain: async (port) => {
|
|
1244
|
-
await onReady;
|
|
1245
|
-
return sbx.getDomain(port);
|
|
1246
|
-
},
|
|
1247
|
-
readFile: async (opts) => {
|
|
1248
|
-
await onReady;
|
|
1249
|
-
return sbx.readFile(opts);
|
|
1250
|
-
},
|
|
1251
|
-
writeFiles: async (opts) => {
|
|
1252
|
-
await onReady;
|
|
1253
|
-
return sbx.writeFiles(opts);
|
|
1254
|
-
}
|
|
1255
|
-
};
|
|
1256
|
-
}
|
|
1257
|
-
|
|
1258
|
-
export {
|
|
1259
|
-
getSandbox
|
|
1260
|
-
};
|
|
1261
|
-
//# 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+IDApIHtcbiAgICBjb25zdCBjaG1vZFJlc3VsdCA9IGF3YWl0IHNhbmRib3guZXhlYyh7XG4gICAgICBjb21tYW5kOiBcImNobW9kXCIsXG4gICAgICBhcmdzOiBbXCIreFwiLCAuLi5zaGVsbFNjcmlwdHNdLFxuICAgIH0pO1xuICAgIGlmIChjaG1vZFJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICB0aHJvdyBjaG1vZFJlc3VsdDtcbiAgICB9XG4gICAgYXdhaXQgY2htb2RSZXN1bHQucmVzdWx0O1xuICB9XG59XG5cbmZ1bmN0aW9uIHRvQmFzZTY0KGNvbnRlbnQ6IHN0cmluZyB8IEJ1ZmZlcik6IHN0cmluZyB7XG4gIGlmICh0eXBlb2YgY29udGVudCA9PT0gXCJzdHJpbmdcIikge1xuICAgIHJldHVybiBCdWZmZXIuZnJvbShjb250ZW50KS50b1N0cmluZyhcImJhc2U2NFwiKTtcbiAgfVxuICByZXR1cm4gY29udGVudC50b1N0cmluZyhcImJhc2U2NFwiKTtcbn1cblxuZnVuY3Rpb24gcXVvdGUoczogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGAnJHtzLnJlcGxhY2UoLycvZywgXCInXFxcXCcnXCIpfSdgO1xufVxuIiwgImltcG9ydCAqIGFzIHBhdGggZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHsgU2FuZGJveCBhcyBWZXJjZWxTYW5kYm94U0RLIH0gZnJvbSBcIkB2ZXJjZWwvc2FuZGJveFwiO1xuaW1wb3J0ICogYXMgZXJyb3JlIGZyb20gXCJlcnJvcmVcIjtcbmltcG9ydCB7IHN0YXJ0IH0gZnJvbSBcIndvcmtmbG93L2FwaVwiO1xuaW1wb3J0IHsgU2FuZGJveEVycm9yLCBTYW5kYm94Tm90Rm91bmRFcnJvciB9IGZyb20gXCIuLi8uLi9lcnJvcnNcIjtcbmltcG9ydCB0eXBlIHsgVGFnc1NjaGVtYSB9IGZyb20gXCIuLi8uLi9pbmRleFwiO1xuaW1wb3J0IHR5cGUgeyBTYW5kYm94UmVjb3JkLCBTdG9yYWdlLCBTdG9yYWdlQ29uZmlnIH0gZnJvbSBcIi4uLy4uL3N0b3JhZ2VcIjtcbmltcG9ydCB7IGRlYnVnIH0gZnJvbSBcIi4uLy4uL3V0aWxzL2RlYnVnXCI7XG5pbXBvcnQgdHlwZSB7IFNhbmRib3hTZXR1cE1ldGEgfSBmcm9tIFwiLi4vY2xpZW50XCI7XG5pbXBvcnQgdHlwZSB7XG4gIExvZ0VudHJ5LFxuICBPblJlc3RhcnQsXG4gIFNhbmRib3gsXG4gIFNhbmRib3hMaWZlY3ljbGUsXG4gIFNhbmRib3hMaWZlY3ljbGVJbnB1dCxcbiAgU2FuZGJveFNldHVwLFxuICBTYW5kYm94U3RhdHVzLFxufSBmcm9tIFwiLi4vdHlwZXNcIjtcbmltcG9ydCB7IHNhbmRib3hMaWZlY3ljbGVXb3JrZmxvdyB9IGZyb20gXCIuL2xpZmVjeWNsZS13b3JrZmxvd1wiO1xuXG5leHBvcnQgdHlwZSBWZXJjZWxTYW5kYm94Q3JlYXRlT3B0aW9ucyA9IEV4dHJhY3Q8XG4gIFBhcmFtZXRlcnM8dHlwZW9mIFZlcmNlbFNhbmRib3hTREsuY3JlYXRlPlswXSxcbiAgLy8gYmlvbWUtaWdub3JlIGxpbnQvY29tcGxleGl0eS9ub0Jhbm5lZFR5cGVzOiAuXG4gIHt9XG4+O1xuXG5leHBvcnQgY29uc3QgVkVSQ0VMX01BWF9USU1FT1VUX01TID0gNSAqIDYwICogNjAgKiAxMDAwOyAvLyA1IGhvdXJzXG5jb25zdCBMT0NLX1RJTUVPVVRfTVMgPSA1ICogNjAgKiAxMDAwOyAvLyA1IG1pbnV0ZXMgLSBpZiBsb2NrIG9sZGVyIHRoYW4gdGhpcywgY29uc2lkZXIgaXQgc3RhbGVcbmNvbnN0IExPQ0tfUE9MTF9JTlRFUlZBTF9NUyA9IDIwMDtcblxuY29uc3QgZ2V0VGVzdENyZWRlbnRpYWxzID0gKCkgPT5cbiAgcHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09IFwidGVzdFwiXG4gICAgPyB7XG4gICAgICAgIHRva2VuOiBwcm9jZXNzLmVudi5URVNUX1ZFUkNFTF9UT0tFTixcbiAgICAgICAgdGVhbUlkOiBwcm9jZXNzLmVudi5URVNUX1ZFUkNFTF9URUFNX0lELFxuICAgICAgICBwcm9qZWN0SWQ6IHByb2Nlc3MuZW52LlRFU1RfVkVSQ0VMX1BST0pFQ1RfSUQsXG4gICAgICB9XG4gICAgOiB7fTtcblxuLyoqXG4gKiBNb2R1bGUtbGV2ZWwgY2FjaGUgZm9yIGluLWZsaWdodCBzYW5kYm94IGNyZWF0aW9uIHByb21pc2VzLlxuICogUHJldmVudHMgcGFyYWxsZWwgcmVxdWVzdHMgd2l0aGluIHRoZSBzYW1lIHByb2Nlc3MgZnJvbSBjcmVhdGluZyBkdXBsaWNhdGUgc2FuZGJveGVzLlxuICovXG5jb25zdCBjcmVhdGVQcm9taXNlcyA9IG5ldyBNYXA8c3RyaW5nLCBQcm9taXNlPFNhbmRib3hFcnJvciB8IHN0cmluZz4+KCk7XG5cbmNvbnN0IEFDVElWSVRZX1RIUk9UVExFX01TID0gMTBfMDAwO1xuY29uc3QgbGFzdEFjdGl2aXR5U2VudCA9IG5ldyBNYXA8c3RyaW5nLCBudW1iZXI+KCk7XG5cbmNvbnN0IERFRkFVTFRfVkNQVVMgPSAyO1xuXG5mdW5jdGlvbiBpc1NhbmRib3hHb25lRXJyb3IoZTogdW5rbm93bik6IGJvb2xlYW4ge1xuICBpZiAoIShlIGluc3RhbmNlb2YgRXJyb3IpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgY29uc3QgZXJyb3JXaXRoUmVzcG9uc2UgPSBlIGFzIHsgcmVzcG9uc2U/OiB7IHN0YXR1cz86IG51bWJlciB9IH07XG4gIGNvbnN0IGVycm9yV2l0aENhdXNlID0gZSBhcyB7IGNhdXNlPzogeyByZXNwb25zZT86IHsgc3RhdHVzPzogbnVtYmVyIH0gfSB9O1xuXG4gIGNvbnN0IHN0YXR1cyA9XG4gICAgZXJyb3JXaXRoUmVzcG9uc2UucmVzcG9uc2U/LnN0YXR1cyA/P1xuICAgIGVycm9yV2l0aENhdXNlLmNhdXNlPy5yZXNwb25zZT8uc3RhdHVzO1xuXG4gIGlmIChzdGF0dXMgPT09IDQxMCB8fCBzdGF0dXMgPT09IDQyMikge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgY29uc3QgbWVzc2FnZSA9IGUubWVzc2FnZSB8fCBTdHJpbmcoZSk7XG4gIGlmIChcbiAgICBtZXNzYWdlLmluY2x1ZGVzKFwiRXhwZWN0ZWQgYSBzdHJlYW0gb2YgY29tbWFuZCBkYXRhXCIpIHx8XG4gICAgbWVzc2FnZS5pbmNsdWRlcyhcIkV4cGVjdGVkIGEgc3RyZWFtIG9mIGxvZ3NcIilcbiAgKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmV4cG9ydCBjb25zdCB2ZXJjZWxTYW5kYm94ID0gPFRUYWdzIGV4dGVuZHMgVGFnc1NjaGVtYSA9IFRhZ3NTY2hlbWE+KHtcbiAgc2FuZGJveFJlY29yZCxcbiAgc3RvcmFnZUNvbmZpZyxcbiAgZW5hYmxlTGlmZWN5Y2xlV29ya2Zsb3csXG4gIHN0b3JhZ2UsXG4gIHNldHVwLFxuICBvblJlc3RhcnQsXG59OiB7XG4gIHNhbmRib3hSZWNvcmQ6IFNhbmRib3hSZWNvcmQgJiB7IGNvbmZpZzogeyB0eXBlOiBcInZlcmNlbFwiIH0gfTtcbiAgc3RvcmFnZUNvbmZpZzogU3RvcmFnZUNvbmZpZztcbiAgZW5hYmxlTGlmZWN5Y2xlV29ya2Zsb3c6IGJvb2xlYW47XG4gIHN0b3JhZ2U6IFN0b3JhZ2U7XG4gIHNldHVwPzogU2FuZGJveFNldHVwO1xuICBvblJlc3RhcnQ/OiBPblJlc3RhcnQ7XG59KTogU2FuZGJveDxUVGFncz4gJiB7XG4gIF9vblJlYWR5PzogUHJvbWlzZTx2b2lkPjtcbiAgX3NldHVwTWV0YT86IFByb21pc2U8U2FuZGJveFNldHVwTWV0YT47XG59ID0+IHtcbiAgY29uc3QgeyBpZCwgY29uZmlnIH0gPSBzYW5kYm94UmVjb3JkO1xuICBjb25zdCB2Y3B1cyA9IGNvbmZpZy5yZXNvdXJjZXM/LnZjcHVzID8/IERFRkFVTFRfVkNQVVM7XG4gIGNvbnN0IHBvcnRzID0gY29uZmlnLnBvcnRzO1xuICBjb25zdCBuZXR3b3JrUG9saWN5ID0gY29uZmlnLm5ldHdvcmtQb2xpY3k7XG4gIGNvbnN0IGluaXRpYWxWZXJjZWwgPVxuICAgIHNhbmRib3hSZWNvcmQucHJvdmlkZXJNZXRhZGF0YT8ucHJvdmlkZXIgPT09IFwidmVyY2VsXCJcbiAgICAgID8gc2FuZGJveFJlY29yZC5wcm92aWRlck1ldGFkYXRhXG4gICAgICA6IG51bGw7XG5cbiAgdHlwZSBTYW5kYm94SW5zdGFuY2UgPSBBd2FpdGVkPFJldHVyblR5cGU8dHlwZW9mIFZlcmNlbFNhbmRib3hTREsuZ2V0Pj47XG4gIGxldCBzYW5kYm94UHJvbWlzZTogUHJvbWlzZTxTYW5kYm94RXJyb3IgfCBTYW5kYm94SW5zdGFuY2U+IHwgbnVsbCA9IG51bGw7XG4gIGxldCByZWNvdmVyZWRGcm9tU3RhbGUgPSBmYWxzZTtcbiAgbGV0IGNyZWF0ZWRGcm9tU25hcHNob3QgPSBmYWxzZTtcbiAgbGV0IG5lZWRzU2V0dXBSdW4gPSBmYWxzZTtcbiAgY29uc3QgSE9NRV9ESVIgPSBcIi9ob21lL3ZlcmNlbC1zYW5kYm94XCI7XG5cbiAgYXN5bmMgZnVuY3Rpb24gcG9sbEZvclNhbmRib3hJZCgpOiBQcm9taXNlPFNhbmRib3hFcnJvciB8IHN0cmluZz4ge1xuICAgIGNvbnN0IGRlYWRsaW5lID0gRGF0ZS5ub3coKSArIExPQ0tfVElNRU9VVF9NUztcbiAgICB3aGlsZSAoRGF0ZS5ub3coKSA8IGRlYWRsaW5lKSB7XG4gICAgICBhd2FpdCBuZXcgUHJvbWlzZSgocikgPT4gc2V0VGltZW91dChyLCBMT0NLX1BPTExfSU5URVJWQUxfTVMpKTtcbiAgICAgIGNvbnN0IHJlY29yZCA9IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5nZXQoaWQpO1xuICAgICAgaWYgKHJlY29yZCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHJldHVybiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiByZWNvcmQubWVzc2FnZSwgY2F1c2U6IHJlY29yZCB9KTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHZlcmNlbFNhbmRib3hJZCA9XG4gICAgICAgIHJlY29yZD8ucHJvdmlkZXJNZXRhZGF0YT8ucHJvdmlkZXIgPT09IFwidmVyY2VsXCJcbiAgICAgICAgICA/IHJlY29yZC5wcm92aWRlck1ldGFkYXRhLnNhbmRib3hJZFxuICAgICAgICAgIDogbnVsbDtcbiAgICAgIGlmICh2ZXJjZWxTYW5kYm94SWQpIHtcbiAgICAgICAgcmV0dXJuIHZlcmNlbFNhbmRib3hJZDtcbiAgICAgIH1cbiAgICAgIGlmICghcmVjb3JkPy5hY3F1aXJpbmdMb2NrQXQpIHtcbiAgICAgICAgY29uc3QgZmluYWxDaGVjayA9IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5nZXQoaWQpO1xuICAgICAgICBpZiAoZmluYWxDaGVjayBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIG5ldyBTYW5kYm94RXJyb3Ioe1xuICAgICAgICAgICAgcmVhc29uOiBmaW5hbENoZWNrLm1lc3NhZ2UsXG4gICAgICAgICAgICBjYXVzZTogZmluYWxDaGVjayxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBmaW5hbFZlcmNlbFNhbmRib3hJZCA9XG4gICAgICAgICAgZmluYWxDaGVjaz8ucHJvdmlkZXJNZXRhZGF0YT8ucHJvdmlkZXIgPT09IFwidmVyY2VsXCJcbiAgICAgICAgICAgID8gZmluYWxDaGVjay5wcm92aWRlck1ldGFkYXRhLnNhbmRib3hJZFxuICAgICAgICAgICAgOiBudWxsO1xuICAgICAgICBpZiAoZmluYWxWZXJjZWxTYW5kYm94SWQpIHtcbiAgICAgICAgICByZXR1cm4gZmluYWxWZXJjZWxTYW5kYm94SWQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRvR2V0T3JDcmVhdGVTYW5kYm94SWQoKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG5ldyBTYW5kYm94RXJyb3Ioe1xuICAgICAgcmVhc29uOiBcIlRpbWVkIG91dCB3YWl0aW5nIGZvciBzYW5kYm94IGNyZWF0aW9uIGJ5IGFub3RoZXIgcHJvY2Vzc1wiLFxuICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gc3RhcnRMaWZlY3ljbGVXb3JrZmxvdyhcbiAgICB2ZXJjZWxTYW5kYm94SWQ6IHN0cmluZ1xuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIWVuYWJsZUxpZmVjeWNsZVdvcmtmbG93KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGxpZmVjeWNsZUlucHV0OiBTYW5kYm94TGlmZWN5Y2xlSW5wdXQgPSB7XG4gICAgICBpZCxcbiAgICAgIHZlcmNlbFNhbmRib3hJZCxcbiAgICAgIHN0b3JhZ2VDb25maWcsXG4gICAgfTtcbiAgICBhd2FpdCBzdGFydChzYW5kYm94TGlmZWN5Y2xlV29ya2Zsb3csIFt7IGlucHV0OiBsaWZlY3ljbGVJbnB1dCB9XSkuY2F0Y2goXG4gICAgICAvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL25vRW1wdHlCbG9ja1N0YXRlbWVudHM6IGludGVudGlvbmFsbHkgaWdub3JlZCAtIHdvcmtmbG93IHN0YXJ0IGlzIGZpcmUtYW5kLWZvcmdldFxuICAgICAgKCkgPT4ge31cbiAgICApO1xuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gY3JlYXRlU2FuZGJveEZyb21TbmFwc2hvdChcbiAgICBzbmFwc2hvdElkOiBzdHJpbmdcbiAgKTogUHJvbWlzZTxTYW5kYm94RXJyb3IgfCBzdHJpbmc+IHtcbiAgICByZXR1cm4gYXdhaXQgZXJyb3JlLnRyeUFzeW5jKHtcbiAgICAgIHRyeTogYXN5bmMgKCkgPT4ge1xuICAgICAgICBjb25zdCBzYW5kYm94ID0gYXdhaXQgVmVyY2VsU2FuZGJveFNESy5jcmVhdGUoe1xuICAgICAgICAgIHNvdXJjZTogeyB0eXBlOiBcInNuYXBzaG90XCIsIHNuYXBzaG90SWQgfSxcbiAgICAgICAgICByZXNvdXJjZXM6IHsgdmNwdXMgfSxcbiAgICAgICAgICB0aW1lb3V0OiBWRVJDRUxfTUFYX1RJTUVPVVRfTVMsXG4gICAgICAgICAgcG9ydHMsXG4gICAgICAgICAgbmV0d29ya1BvbGljeSxcbiAgICAgICAgICAuLi5nZXRUZXN0Q3JlZGVudGlhbHMoKSxcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gICAgICAgIGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5zZXQoe1xuICAgICAgICAgIGlkLFxuICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICB0YWdzOiBzYW5kYm94UmVjb3JkLnRhZ3MsXG4gICAgICAgICAgY3JlYXRlZEF0OiBub3csXG4gICAgICAgICAgbGFzdEFjdGl2aXR5QXQ6IG5vdyxcbiAgICAgICAgICBhY3F1aXJpbmdMb2NrSWQ6IG51bGwsXG4gICAgICAgICAgYWNxdWlyaW5nTG9ja0F0OiBudWxsLFxuICAgICAgICAgIHByb3ZpZGVyTWV0YWRhdGE6IHtcbiAgICAgICAgICAgIHByb3ZpZGVyOiBcInZlcmNlbFwiLFxuICAgICAgICAgICAgc2FuZGJveElkOiBzYW5kYm94LnNhbmRib3hJZCxcbiAgICAgICAgICAgIHNuYXBzaG90SWQsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICAgIGF3YWl0IHN0YXJ0TGlmZWN5Y2xlV29ya2Zsb3coc2FuZGJveC5zYW5kYm94SWQpO1xuICAgICAgICByZXR1cm4gc2FuZGJveC5zYW5kYm94SWQ7XG4gICAgICB9LFxuICAgICAgY2F0Y2g6IChlKSA9PiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pLFxuICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gY3JlYXRlRnJlc2hTYW5kYm94KCk6IFByb21pc2U8U2FuZGJveEVycm9yIHwgc3RyaW5nPiB7XG4gICAgcmV0dXJuIGF3YWl0IGVycm9yZS50cnlBc3luYyh7XG4gICAgICB0cnk6IGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc3Qgc2FuZGJveCA9IGF3YWl0IFZlcmNlbFNhbmRib3hTREsuY3JlYXRlKHtcbiAgICAgICAgICByZXNvdXJjZXM6IHsgdmNwdXMgfSxcbiAgICAgICAgICB0aW1lb3V0OiBWRVJDRUxfTUFYX1RJTUVPVVRfTVMsXG4gICAgICAgICAgcG9ydHMsXG4gICAgICAgICAgbmV0d29ya1BvbGljeSxcbiAgICAgICAgICAuLi5nZXRUZXN0Q3JlZGVudGlhbHMoKSxcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gICAgICAgIGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5zZXQoe1xuICAgICAgICAgIGlkLFxuICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICB0YWdzOiBzYW5kYm94UmVjb3JkLnRhZ3MsXG4gICAgICAgICAgY3JlYXRlZEF0OiBub3csXG4gICAgICAgICAgbGFzdEFjdGl2aXR5QXQ6IG5vdyxcbiAgICAgICAgICBhY3F1aXJpbmdMb2NrSWQ6IG51bGwsXG4gICAgICAgICAgYWNxdWlyaW5nTG9ja0F0OiBudWxsLFxuICAgICAgICAgIHByb3ZpZGVyTWV0YWRhdGE6IHtcbiAgICAgICAgICAgIHByb3ZpZGVyOiBcInZlcmNlbFwiLFxuICAgICAgICAgICAgc2FuZGJveElkOiBzYW5kYm94LnNhbmRib3hJZCxcbiAgICAgICAgICAgIHNuYXBzaG90SWQ6IG51bGwsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICAgIGF3YWl0IHN0YXJ0TGlmZWN5Y2xlV29ya2Zsb3coc2FuZGJveC5zYW5kYm94SWQpO1xuICAgICAgICByZXR1cm4gc2FuZGJveC5zYW5kYm94SWQ7XG4gICAgICB9LFxuICAgICAgY2F0Y2g6IChlKSA9PiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENvcmUgZXhlYyBsb2dpYyBhZ2FpbnN0IGEgcmF3IFZlcmNlbCBTREsgaW5zdGFuY2UuXG4gICAqIFNoYXJlZCBiZXR3ZWVuIHRoZSBtYWluIHNhbmRib3ggd3JhcHBlciBhbmQgdGVtcG9yYXJ5IHNldHVwIHNhbmRib3hlcy5cbiAgICovXG4gIGZ1bmN0aW9uIGV4ZWNPbkluc3RhbmNlKFxuICAgIGluc3RhbmNlOiBTYW5kYm94SW5zdGFuY2UsXG4gICAge1xuICAgICAgY29tbWFuZCxcbiAgICAgIGFyZ3MsXG4gICAgICBzaWduYWwsXG4gICAgfTogeyBjb21tYW5kOiBzdHJpbmc7IGFyZ3M/OiBzdHJpbmdbXTsgc2lnbmFsPzogQWJvcnRTaWduYWwgfVxuICApOiBQcm9taXNlPFxuICAgIHwgU2FuZGJveEVycm9yXG4gICAgfCB7XG4gICAgICAgIGNvbW1hbmRJZDogc3RyaW5nO1xuICAgICAgICBsb2dzOiAoKSA9PiBBc3luY0l0ZXJhYmxlPExvZ0VudHJ5PjtcbiAgICAgICAgcmVzdWx0OiBQcm9taXNlPHsgc3Rkb3V0OiBzdHJpbmc7IHN0ZGVycjogc3RyaW5nOyBleGl0Q29kZTogbnVtYmVyIH0+O1xuICAgICAgfVxuICA+IHtcbiAgICByZXR1cm4gZXJyb3JlLnRyeUFzeW5jKHtcbiAgICAgIHRyeTogYXN5bmMgKCkgPT4ge1xuICAgICAgICBjb25zdCBvdXRwdXQgPSBhd2FpdCBpbnN0YW5jZS5ydW5Db21tYW5kKHtcbiAgICAgICAgICBjd2Q6IEhPTUVfRElSLFxuICAgICAgICAgIGFyZ3MsXG4gICAgICAgICAgY21kOiBjb21tYW5kLFxuICAgICAgICAgIHNpZ25hbCxcbiAgICAgICAgICBkZXRhY2hlZDogdHJ1ZSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgbGV0IHN0ZG91dCA9IFwiXCI7XG4gICAgICAgIGxldCBzdGRlcnIgPSBcIlwiO1xuICAgICAgICBjb25zdCBsb2dCdWZmZXI6IExvZ0VudHJ5W10gPSBbXTtcbiAgICAgICAgY29uc3Qgc3RhdGUgPSB7XG4gICAgICAgICAgcmVzb2x2ZTogbnVsbCBhcyAoKCkgPT4gdm9pZCkgfCBudWxsLFxuICAgICAgICAgIGNvbnN1bWVkOiBmYWxzZSxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBjb25zdW1lTG9ncyA9IChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGZvciBhd2FpdCAoY29uc3QgbG9nIG9mIG91dHB1dC5sb2dzKCkpIHtcbiAgICAgICAgICAgICAgY29uc3QgZW50cnk6IExvZ0VudHJ5ID1cbiAgICAgICAgICAgICAgICBsb2cuc3RyZWFtID09PSBcInN0ZG91dFwiXG4gICAgICAgICAgICAgICAgICA/IHsgc3RyZWFtOiBcInN0ZG91dFwiLCBkYXRhOiBsb2cuZGF0YSB9XG4gICAgICAgICAgICAgICAgICA6IHsgc3RyZWFtOiBcInN0ZGVyclwiLCBkYXRhOiBsb2cuZGF0YSB9O1xuXG4gICAgICAgICAgICAgIGlmIChsb2cuc3RyZWFtID09PSBcInN0ZG91dFwiKSB7XG4gICAgICAgICAgICAgICAgc3Rkb3V0ICs9IGxvZy5kYXRhO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHN0ZGVyciArPSBsb2cuZGF0YTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGxvZ0J1ZmZlci5wdXNoKGVudHJ5KTtcbiAgICAgICAgICAgICAgc3RhdGUucmVzb2x2ZT8uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICAvLyBTYW5kYm94IG1heSBoYXZlIGJlZW4gc3RvcHBlZCAtIGxvZ3MgZW5kcG9pbnQgcmV0dXJucyA0MjJcbiAgICAgICAgICB9XG4gICAgICAgICAgc3RhdGUuY29uc3VtZWQgPSB0cnVlO1xuICAgICAgICAgIHN0YXRlLnJlc29sdmU/LigpO1xuICAgICAgICB9KSgpO1xuXG4gICAgICAgIGFzeW5jIGZ1bmN0aW9uKiBsb2dzKCk6IEFzeW5jSXRlcmFibGU8TG9nRW50cnk+IHtcbiAgICAgICAgICBsZXQgaW5kZXggPSAwO1xuICAgICAgICAgIHdoaWxlICghc3RhdGUuY29uc3VtZWQgfHwgaW5kZXggPCBsb2dCdWZmZXIubGVuZ3RoKSB7XG4gICAgICAgICAgICBpZiAoaW5kZXggPCBsb2dCdWZmZXIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgIHlpZWxkIGxvZ0J1ZmZlcltpbmRleCsrXTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGF3YWl0IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlKSA9PiB7XG4gICAgICAgICAgICAgICAgc3RhdGUucmVzb2x2ZSA9IHJlc29sdmU7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICBzdGF0ZS5yZXNvbHZlID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZXN1bHQgPSBjb25zdW1lTG9ncy50aGVuKGFzeW5jICgpID0+IHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgZmluaXNoZWQgPSBhd2FpdCBvdXRwdXQud2FpdCgpO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgc3Rkb3V0LFxuICAgICAgICAgICAgICBzdGRlcnIsXG4gICAgICAgICAgICAgIGV4aXRDb2RlOiBmaW5pc2hlZC5leGl0Q29kZSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgaWYgKGlzU2FuZGJveEdvbmVFcnJvcihlKSkge1xuICAgICAgICAgICAgICByZXR1cm4geyBzdGRvdXQsIHN0ZGVyciwgZXhpdENvZGU6IDEgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IGU7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4geyBjb21tYW5kSWQ6IG91dHB1dC5jbWRJZCwgbG9ncywgcmVzdWx0IH07XG4gICAgICB9LFxuICAgICAgY2F0Y2g6IChlKSA9PiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pLFxuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gcmVhZEZpbGVPbkluc3RhbmNlKFxuICAgIGluc3RhbmNlOiBTYW5kYm94SW5zdGFuY2UsXG4gICAgeyBwYXRoIH06IHsgcGF0aDogc3RyaW5nIH1cbiAgKTogUHJvbWlzZTxTYW5kYm94RXJyb3IgfCBCdWZmZXIgfCBudWxsPiB7XG4gICAgcmV0dXJuIGVycm9yZS50cnlBc3luYyh7XG4gICAgICB0cnk6ICgpID0+IGluc3RhbmNlLnJlYWRGaWxlVG9CdWZmZXIoeyBwYXRoLCBjd2Q6IEhPTUVfRElSIH0pLFxuICAgICAgY2F0Y2g6IChlKSA9PiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pLFxuICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gd3JpdGVGaWxlc09uSW5zdGFuY2UoXG4gICAgaW5zdGFuY2U6IFNhbmRib3hJbnN0YW5jZSxcbiAgICBvcHRzOiB7XG4gICAgICBmaWxlczogeyBwYXRoOiBzdHJpbmc7IGNvbnRlbnQ6IHN0cmluZyB8IEJ1ZmZlciB9W107XG4gICAgICBkZXN0UGF0aDogc3RyaW5nO1xuICAgIH1cbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgeyBmaWxlcywgZGVzdFBhdGggfSA9IG9wdHM7XG4gICAgaWYgKGZpbGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IG5hdGl2ZUZpbGVzID0gZmlsZXMubWFwKChmaWxlKSA9PiB7XG4gICAgICBjb25zdCBmaWxlUGF0aCA9IHBhdGgucG9zaXguam9pbihkZXN0UGF0aCwgZmlsZS5wYXRoKTtcbiAgICAgIGNvbnN0IGFic29sdXRlUGF0aCA9IHBhdGgucG9zaXguaXNBYnNvbHV0ZShmaWxlUGF0aClcbiAgICAgICAgPyBmaWxlUGF0aFxuICAgICAgICA6IHBhdGgucG9zaXguam9pbihIT01FX0RJUiwgZmlsZVBhdGgpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgcGF0aDogYWJzb2x1dGVQYXRoLFxuICAgICAgICBjb250ZW50OlxuICAgICAgICAgIHR5cGVvZiBmaWxlLmNvbnRlbnQgPT09IFwic3RyaW5nXCJcbiAgICAgICAgICAgID8gQnVmZmVyLmZyb20oZmlsZS5jb250ZW50KVxuICAgICAgICAgICAgOiBmaWxlLmNvbnRlbnQsXG4gICAgICB9O1xuICAgIH0pO1xuXG4gICAgYXdhaXQgaW5zdGFuY2Uud3JpdGVGaWxlcyhuYXRpdmVGaWxlcyk7XG5cbiAgICBjb25zdCBzaGVsbFNjcmlwdHMgPSBuYXRpdmVGaWxlcy5maWx0ZXIoKGYpID0+IGYucGF0aC5lbmRzV2l0aChcIi5zaFwiKSk7XG4gICAgaWYgKHNoZWxsU2NyaXB0cy5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCBjaG1vZFJlc3VsdCA9IGF3YWl0IGV4ZWNPbkluc3RhbmNlKGluc3RhbmNlLCB7XG4gICAgICAgIGNvbW1hbmQ6IFwiY2htb2RcIixcbiAgICAgICAgYXJnczogW1wiK3hcIiwgLi4uc2hlbGxTY3JpcHRzLm1hcCgoZikgPT4gZi5wYXRoKV0sXG4gICAgICB9KTtcbiAgICAgIGlmIChjaG1vZFJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHRocm93IGNobW9kUmVzdWx0O1xuICAgICAgfVxuICAgICAgYXdhaXQgY2htb2RSZXN1bHQucmVzdWx0O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbWluaW1hbCBTYW5kYm94IHdyYXBwZXIgYXJvdW5kIGEgcmF3IFZlcmNlbCBTREsgaW5zdGFuY2UuXG4gICAqIFVzZWQgZm9yIHJ1bm5pbmcgc2V0dXAucnVuKCkgb24gYSB0ZW1wb3Jhcnkgc2FuZGJveCBmb3Igc25hcHNob3QgY3JlYXRpb24uXG4gICAqL1xuICBmdW5jdGlvbiBjcmVhdGVUZW1wU2FuZGJveChpbnN0YW5jZTogU2FuZGJveEluc3RhbmNlKTogU2FuZGJveCB7XG4gICAgY29uc3QgdGVtcFNhbmRib3g6IFNhbmRib3ggPSB7XG4gICAgICBpZDogYF9fc2V0dXBfdGVtcF8ke0RhdGUubm93KCl9YCxcbiAgICAgIGNvbmZpZyxcbiAgICAgIGV4ZWM6IChvcHRzKSA9PiBleGVjT25JbnN0YW5jZShpbnN0YW5jZSwgb3B0cyksXG4gICAgICByZWFkRmlsZTogKG9wdHMpID0+IHJlYWRGaWxlT25JbnN0YW5jZShpbnN0YW5jZSwgb3B0cyksXG4gICAgICBnZXREb21haW46ICgpID0+XG4gICAgICAgIFByb21pc2UucmVzb2x2ZShcbiAgICAgICAgICBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBcIm5vdCBhdmFpbGFibGUgZHVyaW5nIHNldHVwXCIgfSlcbiAgICAgICAgKSxcbiAgICAgIGtpbGw6ICgpID0+XG4gICAgICAgIFByb21pc2UucmVzb2x2ZShcbiAgICAgICAgICBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBcIm5vdCBhdmFpbGFibGUgZHVyaW5nIHNldHVwXCIgfSlcbiAgICAgICAgKSxcbiAgICAgIHdyaXRlRmlsZXM6IChvcHRzKSA9PiB3cml0ZUZpbGVzT25JbnN0YW5jZShpbnN0YW5jZSwgb3B0cyksXG4gICAgICB1cGRhdGVOZXR3b3JrUG9saWN5OiAocG9saWN5KSA9PlxuICAgICAgICBlcnJvcmUudHJ5QXN5bmMoe1xuICAgICAgICAgIHRyeTogKCkgPT4gaW5zdGFuY2UudXBkYXRlTmV0d29ya1BvbGljeShwb2xpY3kpLFxuICAgICAgICAgIGNhdGNoOiAoZSkgPT4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogU3RyaW5nKGUpLCBjYXVzZTogZSB9KSxcbiAgICAgICAgfSksXG4gICAgICB0YWc6IHtcbiAgICAgICAgbGlzdDogYXN5bmMgKCkgPT4gKHt9KSBhcyBUVGFncyxcbiAgICAgICAgZ2V0OiBhc3luYyAoKSA9PiB1bmRlZmluZWQsXG4gICAgICAgIHNldDogYXN5bmMgKCkgPT4gdW5kZWZpbmVkLFxuICAgICAgICBzZXRNYW55OiBhc3luYyAoKSA9PiB1bmRlZmluZWQsXG4gICAgICB9LFxuICAgIH07XG4gICAgcmV0dXJuIHRlbXBTYW5kYm94O1xuICB9XG5cbiAgLyoqXG4gICAqIFBvbGxzIGZvciBhIHNldHVwIHNuYXBzaG90IHRvIGJlY29tZSBhdmFpbGFibGUuIFJldHVybnMgdGhlIHNuYXBzaG90SWRcbiAgICogaWYgb25lIGFwcGVhcnMgYmVmb3JlIHRoZSBsb2NrIHRpbWVzIG91dCwgb3IgbnVsbCBpZiBpdCBkb2Vzbid0LlxuICAgKi9cbiAgYXN5bmMgZnVuY3Rpb24gcG9sbEZvclNldHVwU25hcHNob3Qoa2V5OiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZyB8IG51bGw+IHtcbiAgICBjb25zdCBkZWFkbGluZSA9IERhdGUubm93KCkgKyBMT0NLX1RJTUVPVVRfTVM7XG4gICAgd2hpbGUgKERhdGUubm93KCkgPCBkZWFkbGluZSkge1xuICAgICAgYXdhaXQgbmV3IFByb21pc2UoKHIpID0+IHNldFRpbWVvdXQociwgTE9DS19QT0xMX0lOVEVSVkFMX01TKSk7XG4gICAgICBjb25zdCByZWNvcmQgPSBhd2FpdCBzdG9yYWdlLnNldHVwLmdldChrZXkpO1xuICAgICAgaWYgKHJlY29yZCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgaWYgKHJlY29yZD8uc25hcHNob3RJZCkge1xuICAgICAgICByZXR1cm4gcmVjb3JkLnNuYXBzaG90SWQ7XG4gICAgICB9XG4gICAgICAvLyBMb2NrIHJlbGVhc2VkIGJ1dCBubyBzbmFwc2hvdCBcdTIwMTQgY3JlYXRpb24gZmFpbGVkXG4gICAgICBpZiAoIXJlY29yZD8uYWNxdWlyaW5nTG9ja0lkKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgYmFja2dyb3VuZCBzYW5kYm94LCBydW5zIHNldHVwLCBzbmFwc2hvdHMgaXQsIGFuZCBzdG9yZXMgdGhlXG4gICAqIHNuYXBzaG90IElELiBVc2VzIGF0b21pYyBsb2NraW5nIHRvIGVuc3VyZSBvbmx5IG9uZSBwcm9jZXNzIGNyZWF0ZXMgaXQuXG4gICAqXG4gICAqIEBwYXJhbSBmb3JjZSAtIFNraXAgdGhlIFwic25hcHNob3QgYWxyZWFkeSBleGlzdHNcIiBlYXJseSBleGl0LiBVc2VkIHdoZW5cbiAgICogICB0aGUgY2FsbGVyIGtub3dzIHRoZSBleGlzdGluZyBzbmFwc2hvdCBpcyBzdGFsZS9leHBpcmVkLlxuICAgKi9cbiAgYXN5bmMgZnVuY3Rpb24gY3JlYXRlU2V0dXBTbmFwc2hvdChvcHRzPzoge1xuICAgIGZvcmNlPzogYm9vbGVhbjtcbiAgfSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghc2V0dXApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3Qgc2V0dXBLZXkgPSBzZXR1cC5rZXk7XG5cbiAgICAvLyBDaGVjayBpZiBzbmFwc2hvdCBhbHJlYWR5IGV4aXN0cyAoZmFzdCBwYXRoIFx1MjAxNCBhdm9pZHMgbG9jayBhdHRlbXB0KVxuICAgIGlmICghb3B0cz8uZm9yY2UpIHtcbiAgICAgIGNvbnN0IGV4aXN0aW5nID0gYXdhaXQgc3RvcmFnZS5zZXR1cC5nZXQoc2V0dXBLZXkpO1xuICAgICAgaWYgKCEoZXhpc3RpbmcgaW5zdGFuY2VvZiBFcnJvcikgJiYgZXhpc3Rpbmc/LnNuYXBzaG90SWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEF0b21pY2FsbHkgYWNxdWlyZSBsb2NrIChoYW5kbGVzIGFjdGl2ZS1sb2NrIGRldGVjdGlvbiBpbnRlcm5hbGx5KVxuICAgIGRlYnVnKGBbc2FuZGJveDpzZXR1cF0gYWNxdWlyaW5nIGxvY2sgZm9yIHNldHVwIGtleSBcIiR7c2V0dXBLZXl9XCJgKTtcbiAgICBjb25zdCBsb2NrSWQgPSBjcnlwdG8ucmFuZG9tVVVJRCgpO1xuICAgIGNvbnN0IGxvY2tlZCA9IGF3YWl0IHN0b3JhZ2Uuc2V0dXAuYWNxdWlyZUxvY2soXG4gICAgICBzZXR1cEtleSxcbiAgICAgIGxvY2tJZCxcbiAgICAgIExPQ0tfVElNRU9VVF9NU1xuICAgICk7XG4gICAgaWYgKGxvY2tlZCBpbnN0YW5jZW9mIEVycm9yIHx8ICFsb2NrZWQpIHtcbiAgICAgIGRlYnVnKFxuICAgICAgICBgW3NhbmRib3g6c2V0dXBdIGxvY2sgbm90IGFjcXVpcmVkIGZvciBrZXkgXCIke3NldHVwS2V5fVwiIChhbm90aGVyIHByb2Nlc3MgaG9sZHMgaXQpYFxuICAgICAgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBSZS1jaGVjazogYW5vdGhlciB3b3JrZXIgbWF5IGhhdmUgY3JlYXRlZCB0aGUgc25hcHNob3QgYmV0d2VlbiBvdXJcbiAgICAvLyBwcmUtY2hlY2sgYW5kIGxvY2sgYWNxdWlzaXRpb24uIElmIHNvLCBza2lwIHVubGVzcyBmb3JjZSAoc3RhbGUgc25hcHNob3QpLlxuICAgIGlmICghb3B0cz8uZm9yY2UgJiYgbG9ja2VkLnNuYXBzaG90SWQpIHtcbiAgICAgIGRlYnVnKFxuICAgICAgICBgW3NhbmRib3g6c2V0dXBdIHNuYXBzaG90IGFscmVhZHkgZXhpc3RzIGFmdGVyIGxvY2sgZm9yIGtleSBcIiR7c2V0dXBLZXl9XCIsIHNraXBwaW5nYFxuICAgICAgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsZXQgdGVtcEluc3RhbmNlOiBBd2FpdGVkPFxuICAgICAgUmV0dXJuVHlwZTx0eXBlb2YgVmVyY2VsU2FuZGJveFNESy5jcmVhdGU+XG4gICAgPiB8IG51bGwgPSBudWxsO1xuICAgIHRyeSB7XG4gICAgICAvLyBDcmVhdGUgYSB0ZW1wb3Jhcnkgc2FuZGJveCBmb3Igc25hcHNob3R0aW5nLlxuICAgICAgZGVidWcoXG4gICAgICAgIGBbc2FuZGJveDpzZXR1cF0gY3JlYXRpbmcgdGVtcCBzYW5kYm94IGZvciBzbmFwc2hvdCAoa2V5PVwiJHtzZXR1cEtleX1cIilgXG4gICAgICApO1xuICAgICAgdGVtcEluc3RhbmNlID0gYXdhaXQgVmVyY2VsU2FuZGJveFNESy5jcmVhdGUoe1xuICAgICAgICByZXNvdXJjZXM6IHsgdmNwdXMgfSxcbiAgICAgICAgdGltZW91dDogVkVSQ0VMX01BWF9USU1FT1VUX01TLFxuICAgICAgICBwb3J0cyxcbiAgICAgICAgbmV0d29ya1BvbGljeSxcbiAgICAgICAgLi4uZ2V0VGVzdENyZWRlbnRpYWxzKCksXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdGVtcFNhbmRib3ggPSBjcmVhdGVUZW1wU2FuZGJveChcbiAgICAgICAgdGVtcEluc3RhbmNlIGFzIHVua25vd24gYXMgU2FuZGJveEluc3RhbmNlXG4gICAgICApO1xuICAgICAgYXdhaXQgc2V0dXAucnVuKHRlbXBTYW5kYm94KTtcbiAgICAgIGRlYnVnKFxuICAgICAgICBgW3NhbmRib3g6c2V0dXBdIHNldHVwLnJ1biBjb21wbGV0ZSwgc25hcHNob3R0aW5nIChrZXk9XCIke3NldHVwS2V5fVwiKWBcbiAgICAgICk7XG4gICAgICBjb25zdCBzbmFwc2hvdCA9IGF3YWl0IHRlbXBJbnN0YW5jZS5zbmFwc2hvdCgpO1xuXG4gICAgICBhd2FpdCBzdG9yYWdlLnNldHVwLnNldCh7XG4gICAgICAgIGtleTogc2V0dXBLZXksXG4gICAgICAgIHNuYXBzaG90SWQ6IHNuYXBzaG90LnNuYXBzaG90SWQsXG4gICAgICAgIGNyZWF0ZWRBdDogbG9ja2VkLmNyZWF0ZWRBdCxcbiAgICAgICAgbGFzdFVzZWRBdDogbnVsbCxcbiAgICAgICAgYWNxdWlyaW5nTG9ja0lkOiBudWxsLFxuICAgICAgICBhY3F1aXJpbmdMb2NrQXQ6IG51bGwsXG4gICAgICB9KTtcbiAgICAgIGRlYnVnKFxuICAgICAgICBgW3NhbmRib3g6c2V0dXBdIHNuYXBzaG90IHN0b3JlZDogJHtzbmFwc2hvdC5zbmFwc2hvdElkfSAoa2V5PVwiJHtzZXR1cEtleX1cIilgXG4gICAgICApO1xuXG4gICAgICAvLyBTdG9wIHRoZSB0ZW1wIHNhbmRib3ggXHUyMDE0IG5vIGxvbmdlciBuZWVkZWQgYWZ0ZXIgc25hcHNob3R0aW5nXG4gICAgICBhd2FpdCB0ZW1wSW5zdGFuY2Uuc3RvcCgpLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgY29uc29sZS5lcnJvcihcbiAgICAgICAgYFtzYW5kYm94OnNldHVwXSBmYWlsZWQgdG8gY3JlYXRlIHNldHVwIHNuYXBzaG90IChrZXk9XCIke3NldHVwS2V5fVwiKTpgLFxuICAgICAgICBlXG4gICAgICApO1xuICAgICAgLy8gU3RvcCB0aGUgdGVtcCBzYW5kYm94IG9uIGZhaWx1cmVcbiAgICAgIGlmICh0ZW1wSW5zdGFuY2UpIHtcbiAgICAgICAgYXdhaXQgdGVtcEluc3RhbmNlLnN0b3AoKS5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuICAgICAgfVxuICAgICAgLy8gQ2xlYW4gdXAgbG9jayBvbiBmYWlsdXJlXG4gICAgICBhd2FpdCBzdG9yYWdlLnNldHVwXG4gICAgICAgIC5zZXQoe1xuICAgICAgICAgIGtleTogc2V0dXBLZXksXG4gICAgICAgICAgc25hcHNob3RJZDogbnVsbCxcbiAgICAgICAgICBjcmVhdGVkQXQ6IGxvY2tlZC5jcmVhdGVkQXQsXG4gICAgICAgICAgbGFzdFVzZWRBdDogbnVsbCxcbiAgICAgICAgICBhY3F1aXJpbmdMb2NrSWQ6IG51bGwsXG4gICAgICAgICAgYWNxdWlyaW5nTG9ja0F0OiBudWxsLFxuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBkb0dldE9yQ3JlYXRlU2FuZGJveElkKCk6IFByb21pc2U8U2FuZGJveEVycm9yIHwgc3RyaW5nPiB7XG4gICAgaWYgKGluaXRpYWxWZXJjZWw/LnNhbmRib3hJZCAmJiAhcmVjb3ZlcmVkRnJvbVN0YWxlKSB7XG4gICAgICByZXR1cm4gaW5pdGlhbFZlcmNlbC5zYW5kYm94SWQ7XG4gICAgfVxuXG4gICAgY29uc3QgZXhpc3RpbmcgPSBhd2FpdCBzdG9yYWdlLnNhbmRib3guZ2V0KGlkKTtcbiAgICBpZiAoZXhpc3RpbmcgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgaWYgKGV4aXN0aW5nIGluc3RhbmNlb2YgU2FuZGJveE5vdEZvdW5kRXJyb3IpIHtcbiAgICAgICAgLy8gU2FuZGJveCBkb2Vzbid0IGV4aXN0IHlldCwgY29udGludWUgd2l0aCBjcmVhdGlvblxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IGV4aXN0aW5nLm1lc3NhZ2UsIGNhdXNlOiBleGlzdGluZyB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBleGlzdGluZ1JlY29yZCA9XG4gICAgICBleGlzdGluZyBpbnN0YW5jZW9mIFNhbmRib3hOb3RGb3VuZEVycm9yID8gbnVsbCA6IGV4aXN0aW5nO1xuICAgIGNvbnN0IGV4aXN0aW5nVmVyY2VsID1cbiAgICAgIGV4aXN0aW5nUmVjb3JkPy5wcm92aWRlck1ldGFkYXRhPy5wcm92aWRlciA9PT0gXCJ2ZXJjZWxcIlxuICAgICAgICA/IGV4aXN0aW5nUmVjb3JkLnByb3ZpZGVyTWV0YWRhdGFcbiAgICAgICAgOiBudWxsO1xuXG4gICAgaWYgKGV4aXN0aW5nVmVyY2VsPy5zYW5kYm94SWQpIHtcbiAgICAgIHJldHVybiBleGlzdGluZ1ZlcmNlbC5zYW5kYm94SWQ7XG4gICAgfVxuXG4gICAgY29uc3QgaGFzQWN0aXZlTG9jayA9XG4gICAgICBleGlzdGluZ1JlY29yZD8uYWNxdWlyaW5nTG9ja0lkICYmXG4gICAgICBleGlzdGluZ1JlY29yZC5hY3F1aXJpbmdMb2NrQXQgJiZcbiAgICAgIERhdGUubm93KCkgLSBleGlzdGluZ1JlY29yZC5hY3F1aXJpbmdMb2NrQXQgPCBMT0NLX1RJTUVPVVRfTVM7XG5cbiAgICBpZiAoaGFzQWN0aXZlTG9jaykge1xuICAgICAgcmV0dXJuIHBvbGxGb3JTYW5kYm94SWQoKTtcbiAgICB9XG5cbiAgICBjb25zdCBsb2NrSWQgPSBjcnlwdG8ucmFuZG9tVVVJRCgpO1xuICAgIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gICAgY29uc3QgbG9ja2VkID0gYXdhaXQgc3RvcmFnZS5zYW5kYm94LmFjcXVpcmVMb2NrKFxuICAgICAge1xuICAgICAgICBpZCxcbiAgICAgICAgY29uZmlnLFxuICAgICAgICB0YWdzOiBleGlzdGluZ1JlY29yZD8udGFncyA/PyBzYW5kYm94UmVjb3JkLnRhZ3MsXG4gICAgICAgIGNyZWF0ZWRBdDogZXhpc3RpbmdSZWNvcmQ/LmNyZWF0ZWRBdCA/PyBzYW5kYm94UmVjb3JkLmNyZWF0ZWRBdCxcbiAgICAgICAgbGFzdEFjdGl2aXR5QXQ6XG4gICAgICAgICAgZXhpc3RpbmdSZWNvcmQ/Lmxhc3RBY3Rpdml0eUF0ID8/IHNhbmRib3hSZWNvcmQubGFzdEFjdGl2aXR5QXQsXG4gICAgICAgIGFjcXVpcmluZ0xvY2tJZDogbG9ja0lkLFxuICAgICAgICBhY3F1aXJpbmdMb2NrQXQ6IG5vdyxcbiAgICAgICAgcHJvdmlkZXJNZXRhZGF0YToge1xuICAgICAgICAgIHByb3ZpZGVyOiBcInZlcmNlbFwiLFxuICAgICAgICAgIHNhbmRib3hJZDogbnVsbCxcbiAgICAgICAgICBzbmFwc2hvdElkOlxuICAgICAgICAgICAgZXhpc3RpbmdWZXJjZWw/LnNuYXBzaG90SWQgPz8gaW5pdGlhbFZlcmNlbD8uc25hcHNob3RJZCA/PyBudWxsLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIExPQ0tfVElNRU9VVF9NU1xuICAgICk7XG5cbiAgICBpZiAobG9ja2VkIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIHJldHVybiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBsb2NrZWQubWVzc2FnZSwgY2F1c2U6IGxvY2tlZCB9KTtcbiAgICB9XG4gICAgaWYgKCFsb2NrZWQpIHtcbiAgICAgIHJldHVybiBwb2xsRm9yU2FuZGJveElkKCk7XG4gICAgfVxuXG4gICAgLy8gQ2FwdHVyZSB0aGUgbG9ja2VkIHJlY29yZCBmb3IgdXNlIGluIHRoZSByZWxlYXNlIGhlbHBlci5cbiAgICAvLyBUUyBjYW4ndCBuYXJyb3cgYGxvY2tlZGAgaW5zaWRlIG5lc3RlZCBmdW5jdGlvbnMsIHNvIHdlIGJpbmQgaXQgaGVyZS5cbiAgICBjb25zdCBsb2NrZWRSZWNvcmQgPSBsb2NrZWQ7XG5cbiAgICAvLyBSZWxlYXNlIHRoZSBzYW5kYm94IGxvY2sgc28gb3RoZXIgd29ya2VycyBjYW4gcmV0cnkgcXVpY2tseVxuICAgIC8vIGluc3RlYWQgb2Ygd2FpdGluZyBmb3IgbG9jayB0aW1lb3V0LlxuICAgIGFzeW5jIGZ1bmN0aW9uIHJlbGVhc2VTYW5kYm94TG9jaygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgIGF3YWl0IHN0b3JhZ2Uuc2FuZGJveFxuICAgICAgICAuc2V0KHtcbiAgICAgICAgICAuLi5sb2NrZWRSZWNvcmQsXG4gICAgICAgICAgYWNxdWlyaW5nTG9ja0lkOiBudWxsLFxuICAgICAgICAgIGFjcXVpcmluZ0xvY2tBdDogbnVsbCxcbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgfVxuXG4gICAgLy8gUmUtY2hlY2sgYWZ0ZXIgbG9jazogYW5vdGhlciB3b3JrZXIgbWF5IGhhdmUgY3JlYXRlZCB0aGUgc2FuZGJveFxuICAgIC8vIGJldHdlZW4gb3VyIGluaXRpYWwgY2hlY2sgYW5kIGxvY2sgYWNxdWlzaXRpb24uXG4gICAgY29uc3QgbG9ja2VkVmVyY2VsID1cbiAgICAgIGxvY2tlZFJlY29yZC5wcm92aWRlck1ldGFkYXRhPy5wcm92aWRlciA9PT0gXCJ2ZXJjZWxcIlxuICAgICAgICA/IGxvY2tlZFJlY29yZC5wcm92aWRlck1ldGFkYXRhXG4gICAgICAgIDogbnVsbDtcbiAgICBpZiAobG9ja2VkVmVyY2VsPy5zYW5kYm94SWQpIHtcbiAgICAgIGF3YWl0IHJlbGVhc2VTYW5kYm94TG9jaygpO1xuICAgICAgcmV0dXJuIGxvY2tlZFZlcmNlbC5zYW5kYm94SWQ7XG4gICAgfVxuXG4gICAgY29uc3Qgc25hcHNob3RJZCA9XG4gICAgICBsb2NrZWRWZXJjZWw/LnNuYXBzaG90SWQgPz9cbiAgICAgIGluaXRpYWxWZXJjZWw/LnNuYXBzaG90SWQgPz9cbiAgICAgIGNvbmZpZy5saWZlY3ljbGU/LnNuYXBzaG90SWQ7XG4gICAgaWYgKHNuYXBzaG90SWQpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNyZWF0ZVNhbmRib3hGcm9tU25hcHNob3Qoc25hcHNob3RJZCk7XG4gICAgICBpZiAoIShyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikpIHtcbiAgICAgICAgY3JlYXRlZEZyb21TbmFwc2hvdCA9IHRydWU7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIHNldHVwIHNuYXBzaG90XG4gICAgaWYgKHNldHVwKSB7XG4gICAgICBsZXQgZm9yY2VSZWNyZWF0ZVNuYXBzaG90ID0gZmFsc2U7XG4gICAgICBjb25zdCBzZXR1cFJlY29yZCA9IGF3YWl0IHN0b3JhZ2Uuc2V0dXAuZ2V0KHNldHVwLmtleSk7XG4gICAgICBpZiAoIShzZXR1cFJlY29yZCBpbnN0YW5jZW9mIEVycm9yKSAmJiBzZXR1cFJlY29yZCkge1xuICAgICAgICBpZiAoc2V0dXBSZWNvcmQuc25hcHNob3RJZCkge1xuICAgICAgICAgIGRlYnVnKFxuICAgICAgICAgICAgYFtzYW5kYm94OnNldHVwXSBmb3VuZCBzZXR1cCBzbmFwc2hvdCAke3NldHVwUmVjb3JkLnNuYXBzaG90SWR9IGZvciBrZXkgXCIke3NldHVwLmtleX1cImBcbiAgICAgICAgICApO1xuICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNyZWF0ZVNhbmRib3hGcm9tU25hcHNob3QoXG4gICAgICAgICAgICBzZXR1cFJlY29yZC5zbmFwc2hvdElkXG4gICAgICAgICAgKTtcbiAgICAgICAgICBpZiAoIShyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikpIHtcbiAgICAgICAgICAgIGNyZWF0ZWRGcm9tU25hcHNob3QgPSB0cnVlO1xuICAgICAgICAgICAgLy8gVXBkYXRlIGxhc3RVc2VkQXQgKGZpcmUtYW5kLWZvcmdldClcbiAgICAgICAgICAgIHN0b3JhZ2Uuc2V0dXBcbiAgICAgICAgICAgICAgLnNldCh7XG4gICAgICAgICAgICAgICAgLi4uc2V0dXBSZWNvcmQsXG4gICAgICAgICAgICAgICAgbGFzdFVzZWRBdDogRGF0ZS5ub3coKSxcbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBTbmFwc2hvdCBpcyBzdGFsZS9leHBpcmVkIFx1MjAxNCBmb3JjZSBiYWNrZ3JvdW5kIHRvIG92ZXJ3cml0ZSBpdFxuICAgICAgICAgIGRlYnVnKFxuICAgICAgICAgICAgYFtzYW5kYm94OnNldHVwXSBzbmFwc2hvdCAke3NldHVwUmVjb3JkLnNuYXBzaG90SWR9IGZhaWxlZCAoZXhwaXJlZD8pLCB3aWxsIHJlY3JlYXRlYFxuICAgICAgICAgICk7XG4gICAgICAgICAgZm9yY2VSZWNyZWF0ZVNuYXBzaG90ID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICBzZXR1cFJlY29yZC5hY3F1aXJpbmdMb2NrSWQgJiZcbiAgICAgICAgICBzZXR1cFJlY29yZC5hY3F1aXJpbmdMb2NrQXQgJiZcbiAgICAgICAgICBEYXRlLm5vdygpIC0gc2V0dXBSZWNvcmQuYWNxdWlyaW5nTG9ja0F0IDwgTE9DS19USU1FT1VUX01TXG4gICAgICAgICkge1xuICAgICAgICAgIC8vIEFub3RoZXIgcHJvY2VzcyBpcyBjcmVhdGluZyB0aGUgc2V0dXAgc25hcHNob3QgXHUyMDE0IHdhaXQgZm9yIGl0XG4gICAgICAgICAgZGVidWcoXG4gICAgICAgICAgICBgW3NhbmRib3g6c2V0dXBdIHNuYXBzaG90IGluIHByb2dyZXNzIGZvciBrZXkgXCIke3NldHVwLmtleX1cIiwgd2FpdGluZy4uLmBcbiAgICAgICAgICApO1xuICAgICAgICAgIGNvbnN0IHNuYXBzaG90SWQgPSBhd2FpdCBwb2xsRm9yU2V0dXBTbmFwc2hvdChzZXR1cC5rZXkpO1xuICAgICAgICAgIGlmIChzbmFwc2hvdElkKSB7XG4gICAgICAgICAgICBkZWJ1ZyhcbiAgICAgICAgICAgICAgYFtzYW5kYm94OnNldHVwXSBzbmFwc2hvdCByZWFkeTogJHtzbmFwc2hvdElkfSBmb3Iga2V5IFwiJHtzZXR1cC5rZXl9XCJgXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY3JlYXRlU2FuZGJveEZyb21TbmFwc2hvdChzbmFwc2hvdElkKTtcbiAgICAgICAgICAgIGlmICghKHJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSkge1xuICAgICAgICAgICAgICBjcmVhdGVkRnJvbVNuYXBzaG90ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gUG9sbCBmYWlsZWQgb3Igc25hcHNob3QgY3JlYXRpb24gZmFpbGVkIFx1MjAxNCBmYWxsIHRocm91Z2ggdG8gY29sZCBwYXRoXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIE5vIHNldHVwIHNuYXBzaG90IGF2YWlsYWJsZSBcdTIwMTQgY3JlYXRlIGZyZXNoIGFuZCBydW4gc2V0dXAgbGF0ZXIuXG4gICAgICAvLyBLaWNrIG9mZiBiYWNrZ3JvdW5kIHNuYXBzaG90IGltbWVkaWF0ZWx5IHNvIGl0IHJ1bnMgaW4gcGFyYWxsZWxcbiAgICAgIC8vIHdpdGggc2V0dXAucnVuIG9uIHRoZSBzZXNzaW9uIHNhbmRib3guXG4gICAgICBkZWJ1ZyhcbiAgICAgICAgYFtzYW5kYm94OnNldHVwXSBubyBzbmFwc2hvdCBmb3Iga2V5IFwiJHtzZXR1cC5rZXl9XCIsIHdpbGwgcnVuIHNldHVwIG9uIHRoaXMgc2FuZGJveGBcbiAgICAgICk7XG4gICAgICBuZWVkc1NldHVwUnVuID0gdHJ1ZTtcbiAgICAgIGNyZWF0ZVNldHVwU25hcHNob3QoeyBmb3JjZTogZm9yY2VSZWNyZWF0ZVNuYXBzaG90IH0pLmNhdGNoKChlKSA9PiB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgICAgXCJbc2FuZGJveDpzZXR1cF0gZmFpbGVkIHRvIGNyZWF0ZSBiYWNrZ3JvdW5kIHNuYXBzaG90OlwiLFxuICAgICAgICAgIGVcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGNvbnN0IGZyZXNoUmVzdWx0ID0gYXdhaXQgY3JlYXRlRnJlc2hTYW5kYm94KCk7XG4gICAgaWYgKGZyZXNoUmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIGF3YWl0IHJlbGVhc2VTYW5kYm94TG9jaygpO1xuICAgIH1cbiAgICByZXR1cm4gZnJlc2hSZXN1bHQ7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRPckNyZWF0ZVNhbmRib3hJZCgpOiBQcm9taXNlPFNhbmRib3hFcnJvciB8IHN0cmluZz4ge1xuICAgIGNvbnN0IGNhY2hlZCA9IGNyZWF0ZVByb21pc2VzLmdldChpZCk7XG4gICAgaWYgKGNhY2hlZCkge1xuICAgICAgcmV0dXJuIGNhY2hlZDtcbiAgICB9XG5cbiAgICBjb25zdCBwcm9taXNlID0gZG9HZXRPckNyZWF0ZVNhbmRib3hJZCgpLmZpbmFsbHkoKCkgPT4ge1xuICAgICAgY3JlYXRlUHJvbWlzZXMuZGVsZXRlKGlkKTtcbiAgICB9KTtcbiAgICBjcmVhdGVQcm9taXNlcy5zZXQoaWQsIHByb21pc2UpO1xuICAgIHJldHVybiBwcm9taXNlO1xuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gZG9HZXRTYW5kYm94KCk6IFByb21pc2U8U2FuZGJveEVycm9yIHwgU2FuZGJveEluc3RhbmNlPiB7XG4gICAgY29uc3QgdmVyY2VsU2FuZGJveElkID0gYXdhaXQgZ2V0T3JDcmVhdGVTYW5kYm94SWQoKTtcbiAgICBpZiAodmVyY2VsU2FuZGJveElkIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIHJldHVybiB2ZXJjZWxTYW5kYm94SWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGVycm9yZS50cnlBc3luYyh7XG4gICAgICB0cnk6ICgpID0+XG4gICAgICAgIFZlcmNlbFNhbmRib3hTREsuZ2V0KHtcbiAgICAgICAgICBzYW5kYm94SWQ6IHZlcmNlbFNhbmRib3hJZCxcbiAgICAgICAgICAuLi5nZXRUZXN0Q3JlZGVudGlhbHMoKSxcbiAgICAgICAgfSksXG4gICAgICBjYXRjaDogKGUpID0+IG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSksXG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRTYW5kYm94KCk6IFByb21pc2U8U2FuZGJveEVycm9yIHwgU2FuZGJveEluc3RhbmNlPiB7XG4gICAgaWYgKCFzYW5kYm94UHJvbWlzZSkge1xuICAgICAgc2FuZGJveFByb21pc2UgPSBkb0dldFNhbmRib3goKTtcbiAgICB9XG4gICAgcmV0dXJuIHNhbmRib3hQcm9taXNlO1xuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gcmVjb3ZlckZyb21TdGFsZVNhbmRib3goKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgc2FuZGJveFByb21pc2UgPSBudWxsO1xuICAgIHJlY292ZXJlZEZyb21TdGFsZSA9IHRydWU7XG5cbiAgICBjb25zdCBleGlzdGluZyA9IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5nZXQoaWQpO1xuICAgIGlmIChleGlzdGluZyBpbnN0YW5jZW9mIEVycm9yIHx8ICFleGlzdGluZykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGV4aXN0aW5nVmVyY2VsID1cbiAgICAgIGV4aXN0aW5nLnByb3ZpZGVyTWV0YWRhdGE/LnByb3ZpZGVyID09PSBcInZlcmNlbFwiXG4gICAgICAgID8gZXhpc3RpbmcucHJvdmlkZXJNZXRhZGF0YVxuICAgICAgICA6IG51bGw7XG5cbiAgICBpZiAoZXhpc3RpbmdWZXJjZWw/LnNhbmRib3hJZCkge1xuICAgICAgYXdhaXQgc3RvcmFnZS5zYW5kYm94LnNldCh7XG4gICAgICAgIGlkOiBleGlzdGluZy5pZCxcbiAgICAgICAgY29uZmlnOiBleGlzdGluZy5jb25maWcsXG4gICAgICAgIHRhZ3M6IGV4aXN0aW5nLnRhZ3MsXG4gICAgICAgIGNyZWF0ZWRBdDogZXhpc3RpbmcuY3JlYXRlZEF0LFxuICAgICAgICBsYXN0QWN0aXZpdHlBdDogZXhpc3RpbmcubGFzdEFjdGl2aXR5QXQsXG4gICAgICAgIGFjcXVpcmluZ0xvY2tJZDogbnVsbCxcbiAgICAgICAgYWNxdWlyaW5nTG9ja0F0OiBudWxsLFxuICAgICAgICBwcm92aWRlck1ldGFkYXRhOiB7XG4gICAgICAgICAgcHJvdmlkZXI6IFwidmVyY2VsXCIsXG4gICAgICAgICAgc2FuZGJveElkOiBudWxsLFxuICAgICAgICAgIHNuYXBzaG90SWQ6IGV4aXN0aW5nVmVyY2VsLnNuYXBzaG90SWQsXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiB1cGRhdGVMYXN0QWN0aXZpdHkoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgICBjb25zdCBsYXN0U2VudCA9IGxhc3RBY3Rpdml0eVNlbnQuZ2V0KGlkKTtcbiAgICBpZiAobGFzdFNlbnQgJiYgbm93IC0gbGFzdFNlbnQgPCBBQ1RJVklUWV9USFJPVFRMRV9NUykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBsYXN0QWN0aXZpdHlTZW50LnNldChpZCwgbm93KTtcblxuICAgIGNvbnN0IGV4aXN0aW5nID0gYXdhaXQgc3RvcmFnZS5zYW5kYm94LmdldChpZCk7XG4gICAgaWYgKGV4aXN0aW5nIGluc3RhbmNlb2YgRXJyb3IgfHwgIWV4aXN0aW5nKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGV4aXN0aW5nVmVyY2VsID1cbiAgICAgIGV4aXN0aW5nLnByb3ZpZGVyTWV0YWRhdGE/LnByb3ZpZGVyID09PSBcInZlcmNlbFwiXG4gICAgICAgID8gZXhpc3RpbmcucHJvdmlkZXJNZXRhZGF0YVxuICAgICAgICA6IG51bGw7XG4gICAgYXdhaXQgc3RvcmFnZS5zYW5kYm94LnNldCh7XG4gICAgICBpZDogZXhpc3RpbmcuaWQsXG4gICAgICBjb25maWc6IGV4aXN0aW5nLmNvbmZpZyxcbiAgICAgIHRhZ3M6IGV4aXN0aW5nLnRhZ3MsXG4gICAgICBjcmVhdGVkQXQ6IGV4aXN0aW5nLmNyZWF0ZWRBdCxcbiAgICAgIGxhc3RBY3Rpdml0eUF0OiBub3csXG4gICAgICBhY3F1aXJpbmdMb2NrSWQ6IG51bGwsXG4gICAgICBhY3F1aXJpbmdMb2NrQXQ6IG51bGwsXG4gICAgICBwcm92aWRlck1ldGFkYXRhOiBleGlzdGluZ1ZlcmNlbCA/PyB7XG4gICAgICAgIHByb3ZpZGVyOiBcInZlcmNlbFwiLFxuICAgICAgICBzYW5kYm94SWQ6IG51bGwsXG4gICAgICAgIHNuYXBzaG90SWQ6IG51bGwsXG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgY29uc3QgbGlmZWN5Y2xlOiBTYW5kYm94TGlmZWN5Y2xlID0ge1xuICAgIHN0YXJ0OiBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzYW5kYm94ID0gYXdhaXQgZ2V0U2FuZGJveCgpO1xuICAgICAgaWYgKHNhbmRib3ggaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICByZXR1cm4gc2FuZGJveDtcbiAgICAgIH1cbiAgICAgIGF3YWl0IHVwZGF0ZUxhc3RBY3Rpdml0eSgpO1xuICAgICAgcmV0dXJuIHNhbmRib3guc3RhdHVzIGFzIFNhbmRib3hTdGF0dXM7XG4gICAgfSxcblxuICAgIHNuYXBzaG90OiBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzYW5kYm94ID0gYXdhaXQgZ2V0U2FuZGJveCgpO1xuICAgICAgaWYgKHNhbmRib3ggaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICByZXR1cm4gc2FuZGJveDtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGVycm9yZS50cnlBc3luYyh7XG4gICAgICAgIHRyeTogYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IGV4aXN0aW5nID0gYXdhaXQgc3RvcmFnZS5zYW5kYm94LmdldChpZCk7XG4gICAgICAgICAgY29uc3Qgc25hcHNob3QgPSBhd2FpdCBzYW5kYm94LnNuYXBzaG90KCk7XG4gICAgICAgICAgYXdhaXQgc3RvcmFnZS5zYW5kYm94LnNldCh7XG4gICAgICAgICAgICBpZCxcbiAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgIHRhZ3M6IGV4aXN0aW5nIGluc3RhbmNlb2YgRXJyb3IgPyBudWxsIDogKGV4aXN0aW5nPy50YWdzID8/IG51bGwpLFxuICAgICAgICAgICAgY3JlYXRlZEF0OlxuICAgICAgICAgICAgICBleGlzdGluZyBpbnN0YW5jZW9mIEVycm9yID8gbnVsbCA6IChleGlzdGluZz8uY3JlYXRlZEF0ID8/IG51bGwpLFxuICAgICAgICAgICAgbGFzdEFjdGl2aXR5QXQ6XG4gICAgICAgICAgICAgIGV4aXN0aW5nIGluc3RhbmNlb2YgRXJyb3JcbiAgICAgICAgICAgICAgICA/IG51bGxcbiAgICAgICAgICAgICAgICA6IChleGlzdGluZz8ubGFzdEFjdGl2aXR5QXQgPz8gbnVsbCksXG4gICAgICAgICAgICBhY3F1aXJpbmdMb2NrSWQ6IG51bGwsXG4gICAgICAgICAgICBhY3F1aXJpbmdMb2NrQXQ6IG51bGwsXG4gICAgICAgICAgICBwcm92aWRlck1ldGFkYXRhOiB7XG4gICAgICAgICAgICAgIHByb3ZpZGVyOiBcInZlcmNlbFwiLFxuICAgICAgICAgICAgICBzYW5kYm94SWQ6IG51bGwsXG4gICAgICAgICAgICAgIHNuYXBzaG90SWQ6IHNuYXBzaG90LnNuYXBzaG90SWQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHJldHVybiB7IHNuYXBzaG90SWQ6IHNuYXBzaG90LnNuYXBzaG90SWQgfTtcbiAgICAgICAgfSxcbiAgICAgICAgY2F0Y2g6IChlKSA9PiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pLFxuICAgICAgfSk7XG4gICAgfSxcblxuICAgIHN0b3A6IGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHNhbmRib3ggPSBhd2FpdCBnZXRTYW5kYm94KCk7XG4gICAgICBpZiAoc2FuZGJveCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHJldHVybiBzYW5kYm94O1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gZXJyb3JlLnRyeUFzeW5jKHtcbiAgICAgICAgdHJ5OiBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgYXdhaXQgc2FuZGJveC5zdG9wKCk7XG4gICAgICAgICAgY29uc3QgZXhpc3RpbmcgPSBhd2FpdCBzdG9yYWdlLnNhbmRib3guZ2V0KGlkKTtcbiAgICAgICAgICBpZiAoZXhpc3RpbmcgaW5zdGFuY2VvZiBFcnJvciB8fCAhZXhpc3RpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgICAgfVxuICAgICAgICAgIGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5zZXQoe1xuICAgICAgICAgICAgaWQ6IGV4aXN0aW5nLmlkLFxuICAgICAgICAgICAgY29uZmlnOiBleGlzdGluZy5jb25maWcsXG4gICAgICAgICAgICB0YWdzOiBleGlzdGluZy50YWdzLFxuICAgICAgICAgICAgY3JlYXRlZEF0OiBleGlzdGluZy5jcmVhdGVkQXQsXG4gICAgICAgICAgICBsYXN0QWN0aXZpdHlBdDogZXhpc3RpbmcubGFzdEFjdGl2aXR5QXQsXG4gICAgICAgICAgICBhY3F1aXJpbmdMb2NrSWQ6IG51bGwsXG4gICAgICAgICAgICBhY3F1aXJpbmdMb2NrQXQ6IG51bGwsXG4gICAgICAgICAgICBwcm92aWRlck1ldGFkYXRhOiB7XG4gICAgICAgICAgICAgIHByb3ZpZGVyOiBcInZlcmNlbFwiLFxuICAgICAgICAgICAgICBzYW5kYm94SWQ6IG51bGwsXG4gICAgICAgICAgICAgIHNuYXBzaG90SWQ6IG51bGwsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIH0sXG4gICAgICAgIGNhdGNoOiAoZSkgPT4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogU3RyaW5nKGUpLCBjYXVzZTogZSB9KSxcbiAgICAgIH0pO1xuICAgIH0sXG5cbiAgICBnZXRTdGF0dXM6IGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHNhbmRib3ggPSBhd2FpdCBnZXRTYW5kYm94KCk7XG4gICAgICBpZiAoc2FuZGJveCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHJldHVybiBzYW5kYm94O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHNhbmRib3guc3RhdHVzIGFzIFNhbmRib3hTdGF0dXM7XG4gICAgfSxcblxuICAgIGdldENyZWF0ZWRBdDogYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qgc2FuZGJveCA9IGF3YWl0IGdldFNhbmRib3goKTtcbiAgICAgIGlmIChzYW5kYm94IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIHNhbmRib3g7XG4gICAgICB9XG4gICAgICByZXR1cm4gc2FuZGJveC5jcmVhdGVkQXQ7XG4gICAgfSxcblxuICAgIGdldFJlbWFpbmluZ1RpbWVvdXQ6IGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHNhbmRib3ggPSBhd2FpdCBnZXRTYW5kYm94KCk7XG4gICAgICBpZiAoc2FuZGJveCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHJldHVybiBzYW5kYm94O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHNhbmRib3gudGltZW91dDtcbiAgICB9LFxuICB9O1xuXG4gIGFzeW5jIGZ1bmN0aW9uIGRvRXhlYyhvcHRzOiB7XG4gICAgY29tbWFuZDogc3RyaW5nO1xuICAgIGFyZ3M/OiBzdHJpbmdbXTtcbiAgICBzaWduYWw/OiBBYm9ydFNpZ25hbDtcbiAgfSkge1xuICAgIGNvbnN0IGluc3RhbmNlID0gYXdhaXQgZ2V0U2FuZGJveCgpO1xuICAgIGlmIChpbnN0YW5jZSBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICByZXR1cm4gaW5zdGFuY2U7XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUHJvbWlzZSA9IHVwZGF0ZUxhc3RBY3Rpdml0eSgpO1xuICAgIGNvbnN0IGV4ZWNSZXN1bHQgPSBhd2FpdCBleGVjT25JbnN0YW5jZShpbnN0YW5jZSwgb3B0cyk7XG4gICAgYXdhaXQgdXBkYXRlUHJvbWlzZTtcbiAgICByZXR1cm4gZXhlY1Jlc3VsdDtcbiAgfVxuXG4gIGNvbnN0IHNhbmRib3g6IFNhbmRib3g8VFRhZ3M+ICYge1xuICAgIF9vblJlYWR5PzogUHJvbWlzZTx2b2lkPjtcbiAgICBfc2V0dXBNZXRhPzogUHJvbWlzZTxTYW5kYm94U2V0dXBNZXRhPjtcbiAgfSA9IHtcbiAgICBpZCxcbiAgICBjb25maWcsXG4gICAgZXhlYzogYXN5bmMgKG9wdHMpID0+IHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGRvRXhlYyhvcHRzKTtcblxuICAgICAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIFNhbmRib3hFcnJvciAmJiBpc1NhbmRib3hHb25lRXJyb3IocmVzdWx0LmNhdXNlKSkge1xuICAgICAgICBhd2FpdCByZWNvdmVyRnJvbVN0YWxlU2FuZGJveCgpO1xuICAgICAgICByZXR1cm4gYXdhaXQgZG9FeGVjKG9wdHMpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0sXG5cbiAgICBnZXREb21haW46IGFzeW5jIChwb3J0KSA9PiB7XG4gICAgICBjb25zdCBzYW5kYm94ID0gYXdhaXQgZ2V0U2FuZGJveCgpO1xuICAgICAgaWYgKHNhbmRib3ggaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICByZXR1cm4gc2FuZGJveDtcbiAgICAgIH1cblxuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIHNhbmRib3guZG9tYWluKHBvcnQpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZXR1cm4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogU3RyaW5nKGUpLCBjYXVzZTogZSB9KTtcbiAgICAgIH1cbiAgICB9LFxuXG4gICAga2lsbDogYXN5bmMgKHsgY29tbWFuZElkLCBzdG9yYWdlOiBjbWRTdG9yYWdlIH0pID0+IHtcbiAgICAgIGNvbnN0IGluc3RhbmNlID0gYXdhaXQgZ2V0U2FuZGJveCgpO1xuICAgICAgaWYgKGluc3RhbmNlIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIGluc3RhbmNlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBjbWQgPSBhd2FpdCBjbWRTdG9yYWdlLmNvbW1hbmQuZ2V0KGNvbW1hbmRJZCk7XG4gICAgICBpZiAoY21kIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IGNtZC5tZXNzYWdlLCBjYXVzZTogY21kIH0pO1xuICAgICAgfVxuICAgICAgaWYgKGNtZCAmJiBjbWQuc3RhdHVzID09PSBcInJ1bm5pbmdcIikge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjbWRTdG9yYWdlLmNvbW1hbmQuc2V0KHtcbiAgICAgICAgICAuLi5jbWQsXG4gICAgICAgICAgc3RhdHVzOiBcImtpbGxlZFwiLFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IHJlc3VsdC5tZXNzYWdlLCBjYXVzZTogcmVzdWx0IH0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH0sXG5cbiAgICByZWFkRmlsZTogYXN5bmMgKG9wdHMpID0+IHtcbiAgICAgIGNvbnN0IGluc3RhbmNlID0gYXdhaXQgZ2V0U2FuZGJveCgpO1xuICAgICAgaWYgKGluc3RhbmNlIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIGluc3RhbmNlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlYWRGaWxlT25JbnN0YW5jZShpbnN0YW5jZSwgb3B0cyk7XG4gICAgfSxcblxuICAgIHdyaXRlRmlsZXM6IGFzeW5jIChvcHRzKSA9PiB7XG4gICAgICBjb25zdCBpbnN0YW5jZSA9IGF3YWl0IGdldFNhbmRib3goKTtcbiAgICAgIGlmIChpbnN0YW5jZSBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHRocm93IGluc3RhbmNlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHdyaXRlRmlsZXNPbkluc3RhbmNlKGluc3RhbmNlLCBvcHRzKTtcbiAgICB9LFxuXG4gICAgbGlmZWN5Y2xlLFxuXG4gICAgdXBkYXRlTmV0d29ya1BvbGljeTogYXN5bmMgKHBvbGljeSkgPT4ge1xuICAgICAgY29uc3QgaW5zdGFuY2UgPSBhd2FpdCBnZXRTYW5kYm94KCk7XG4gICAgICBpZiAoaW5zdGFuY2UgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICByZXR1cm4gaW5zdGFuY2U7XG4gICAgICB9XG4gICAgICByZXR1cm4gZXJyb3JlLnRyeUFzeW5jKHtcbiAgICAgICAgdHJ5OiAoKSA9PiBpbnN0YW5jZS51cGRhdGVOZXR3b3JrUG9saWN5KHBvbGljeSksXG4gICAgICAgIGNhdGNoOiAoZSkgPT4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogU3RyaW5nKGUpLCBjYXVzZTogZSB9KSxcbiAgICAgIH0pO1xuICAgIH0sXG5cbiAgICB0YWc6IHtcbiAgICAgIGxpc3Q6IGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc3Qgc2FuZGJveFJlY29yZCA9IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5nZXQoaWQpO1xuICAgICAgICBpZiAoc2FuZGJveFJlY29yZCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIHNhbmRib3hSZWNvcmQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIChzYW5kYm94UmVjb3JkLnRhZ3MgPz8ge30pIGFzIFRUYWdzO1xuICAgICAgfSxcbiAgICAgIGdldDogYXN5bmMgKGtleTogc3RyaW5nKSA9PiB7XG4gICAgICAgIGNvbnN0IHNhbmRib3hSZWNvcmQgPSBhd2FpdCBzdG9yYWdlLnNhbmRib3guZ2V0KGlkKTtcbiAgICAgICAgaWYgKHNhbmRib3hSZWNvcmQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgIHJldHVybiBzYW5kYm94UmVjb3JkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzYW5kYm94UmVjb3JkLnRhZ3M/LltrZXkgYXMgc3RyaW5nXSBhc1xuICAgICAgICAgIHwgVFRhZ3NbdHlwZW9mIGtleV1cbiAgICAgICAgICB8IHVuZGVmaW5lZDtcbiAgICAgIH0sXG4gICAgICBzZXQ6IGFzeW5jIChrZXk6IHN0cmluZywgdmFsdWU6IHVua25vd24pID0+IHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3RvcmFnZS5zYW5kYm94LnRhZy5zZXQoe1xuICAgICAgICAgIHNhbmRib3hJZDogaWQsXG4gICAgICAgICAgdGFnczogeyBba2V5XTogdmFsdWUgfSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH0sXG4gICAgICBzZXRNYW55OiBhc3luYyAodGFnczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pID0+IHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3RvcmFnZS5zYW5kYm94LnRhZy5zZXQoe1xuICAgICAgICAgIHNhbmRib3hJZDogaWQsXG4gICAgICAgICAgdGFnczogdGFncyBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH0sXG4gICAgfSxcbiAgfTtcblxuICBsZXQgb25SZWFkeVByb21pc2U6IFByb21pc2U8dm9pZD4gPSBQcm9taXNlLnJlc29sdmUoKTtcbiAgbGV0IHNldHVwTWV0YVByb21pc2U6IFByb21pc2U8U2FuZGJveFNldHVwTWV0YT4gPSBQcm9taXNlLnJlc29sdmUoe1xuICAgIG5lZWRzU2V0dXBSdW46IGZhbHNlLFxuICAgIGNyZWF0ZWRGcm9tU25hcHNob3Q6IGZhbHNlLFxuICB9KTtcblxuICBpZiAoY29uZmlnLmxpZmVjeWNsZT8uYXV0b1N0YXJ0ICE9PSBmYWxzZSkge1xuICAgIHNhbmRib3hQcm9taXNlID0gZG9HZXRTYW5kYm94KCk7XG5cbiAgICAvLyBSZXNvbHZlIHNldHVwIG1ldGFkYXRhIGFzIHNvb24gYXMgdGhlIHNhbmRib3ggaW5zdGFuY2UgaXMgcmVhZHlcbiAgICAvLyAoYmVmb3JlIF9vblJlYWR5IHJ1bnMgc2V0dXApLiBUaGUgd29ya2Zsb3cgcmVhZHMgdGhpcyB0byBjaG9vc2UgdGhlIHN0YXR1cyBpbmRpY2F0b3IuXG4gICAgc2V0dXBNZXRhUHJvbWlzZSA9IHNhbmRib3hQcm9taXNlLnRoZW4oKCkgPT4gKHtcbiAgICAgIG5lZWRzU2V0dXBSdW4sXG4gICAgICBjcmVhdGVkRnJvbVNuYXBzaG90LFxuICAgIH0pKTtcblxuICAgIC8vIEFmdGVyIHNhbmRib3ggaW5zdGFuY2UgaXMgcmVhZHksIHJ1biBzZXR1cCBhbmQvb3Igb25SZXN0YXJ0LlxuICAgIC8vIHNhbmRib3hQcm9taXNlIGlzIGFscmVhZHkgcmVzb2x2ZWQgYnkgdGhlIHRpbWUgLnRoZW4oKSBydW5zLFxuICAgIC8vIHNvIHNldHVwLnJ1biAvIG9uUmVzdGFydCBjYWxsaW5nIHNhbmRib3guZXhlYygpIHdvbid0IGRlYWRsb2NrLlxuICAgIG9uUmVhZHlQcm9taXNlID0gc2FuZGJveFByb21pc2UudGhlbihhc3luYyAoaW5zdGFuY2UpID0+IHtcbiAgICAgIGlmIChpbnN0YW5jZSBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKG5lZWRzU2V0dXBSdW4gJiYgc2V0dXApIHtcbiAgICAgICAgZGVidWcoXG4gICAgICAgICAgYFtzYW5kYm94OnNldHVwXSBydW5uaW5nIHNldHVwLnJ1biBvbiBzZXNzaW9uIHNhbmRib3ggKGtleT1cIiR7c2V0dXAua2V5fVwiKWBcbiAgICAgICAgKTtcbiAgICAgICAgYXdhaXQgc2V0dXAucnVuKHNhbmRib3gpO1xuICAgICAgICBkZWJ1ZyhcIltzYW5kYm94OnNldHVwXSBzZXR1cC5ydW4gY29tcGxldGUgb24gc2Vzc2lvbiBzYW5kYm94XCIpO1xuICAgICAgfVxuXG4gICAgICBpZiAoY3JlYXRlZEZyb21TbmFwc2hvdCAmJiBvblJlc3RhcnQpIHtcbiAgICAgICAgZGVidWcoXCJbc2FuZGJveDpzZXR1cF0gcnVubmluZyBvblJlc3RhcnQgKGNyZWF0ZWQgZnJvbSBzbmFwc2hvdClcIik7XG4gICAgICAgIGF3YWl0IG9uUmVzdGFydChzYW5kYm94KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHNhbmRib3guX29uUmVhZHkgPSBvblJlYWR5UHJvbWlzZTtcbiAgc2FuZGJveC5fc2V0dXBNZXRhID0gc2V0dXBNZXRhUHJvbWlzZTtcbiAgcmV0dXJuIHNhbmRib3g7XG59O1xuIiwgImltcG9ydCB0eXBlIHsgVGFnc1NjaGVtYSB9IGZyb20gXCIuLi9pbmRleFwiO1xuaW1wb3J0IHR5cGUgeyBTYW5kYm94UmVjb3JkLCBTdG9yYWdlLCBTdG9yYWdlQ29uZmlnIH0gZnJvbSBcIi4uL3N0b3JhZ2VcIjtcbmltcG9ydCB7IGRlYnVnIH0gZnJvbSBcIi4uL3V0aWxzL2RlYnVnXCI7XG5pbXBvcnQgeyBsb2NhbFNhbmRib3ggfSBmcm9tIFwiLi9iaW5kaW5ncy9sb2NhbFwiO1xuaW1wb3J0IHsgdmVyY2VsU2FuZGJveCB9IGZyb20gXCIuL2JpbmRpbmdzL3ZlcmNlbFwiO1xuaW1wb3J0IHR5cGUgeyBPblJlc3RhcnQsIFNhbmRib3gsIFNhbmRib3hTZXR1cCB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbi8qKlxuICogTWV0YWRhdGEgYWJvdXQgaG93IHRoZSBzYW5kYm94IHdhcyBzZXQgdXAuXG4gKiBVc2VkIGJ5IHRoZSB3b3JrZmxvdyB0byBlbWl0IHRoZSBjb3JyZWN0IHN0YXR1cyBpbmRpY2F0b3IuXG4gKiBSZXR1cm5lZCBhcyBhIHByb21pc2UgYmVjYXVzZSB0aGUgbWV0YWRhdGEgaXMgZGV0ZXJtaW5lZCBhc3luY2hyb25vdXNseVxuICogZHVyaW5nIHNhbmRib3ggY3JlYXRpb24sIGJlZm9yZSBfb25SZWFkeSBydW5zIHNldHVwLlxuICovXG5leHBvcnQgdHlwZSBTYW5kYm94U2V0dXBNZXRhID0ge1xuICAvKiogV2hldGhlciBzZXR1cC5ydW4oKSBuZWVkcyB0byBleGVjdXRlIChjb2xkIHN0YXJ0LCBubyBzbmFwc2hvdCkuICovXG4gIG5lZWRzU2V0dXBSdW46IGJvb2xlYW47XG4gIC8qKiBXaGV0aGVyIHRoZSBzYW5kYm94IHdhcyBjcmVhdGVkIGZyb20gYSBzbmFwc2hvdC4gKi9cbiAgY3JlYXRlZEZyb21TbmFwc2hvdDogYm9vbGVhbjtcbn07XG5cbnR5cGUgU2FuZGJveFdpdGhNZXRhPFRUYWdzIGV4dGVuZHMgVGFnc1NjaGVtYSA9IFRhZ3NTY2hlbWE+ID0gU2FuZGJveDxUVGFncz4gJiB7XG4gIF9vblJlYWR5PzogUHJvbWlzZTx2b2lkPjtcbiAgX3NldHVwTWV0YT86IFByb21pc2U8U2FuZGJveFNldHVwTWV0YT47XG59O1xuXG4vKipcbiAqIE1vZHVsZS1sZXZlbCBjYWNoZSBmb3Igc2FuZGJveCBpbnN0YW5jZXMga2V5ZWQgYnkgc2FuZGJveCByZWNvcmQgSUQuXG4gKlxuICogQ2FjaGVzIGFsbCBzYW5kYm94IGluc3RhbmNlcyBzbyB0aGF0IHRoZSB3b3JrZmxvdyAod2hpY2ggY2FsbHMgZ2V0U2FuZGJveFxuICogd2l0aG91dCBzZXR1cC9vblJlc3RhcnQpIHJldXNlcyB0aGUgc2FtZSBpbnN0YW5jZSBjcmVhdGVkIGR1cmluZyBzZXNzaW9uKCksXG4gKiBpbmNsdWRpbmcgaXRzIF9vblJlYWR5IHByb21pc2UgYW5kIHNldHVwIG1ldGFkYXRhLlxuICovXG5jb25zdCBzYW5kYm94Q2FjaGUgPSBuZXcgTWFwPHN0cmluZywgU2FuZGJveFdpdGhNZXRhPigpO1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0U2FuZGJveDxUVGFncyBleHRlbmRzIFRhZ3NTY2hlbWEgPSBUYWdzU2NoZW1hPih7XG4gIHNhbmRib3hSZWNvcmQsXG4gIHN0b3JhZ2VDb25maWcsXG4gIHN0b3JhZ2UsXG4gIGVuYWJsZUxpZmVjeWNsZVdvcmtmbG93ID0gdHJ1ZSxcbiAgc2V0dXAsXG4gIG9uUmVzdGFydCxcbn06IHtcbiAgc3RvcmFnZUNvbmZpZzogU3RvcmFnZUNvbmZpZztcbiAgc2FuZGJveFJlY29yZDogU2FuZGJveFJlY29yZDtcbiAgc3RvcmFnZTogU3RvcmFnZTtcbiAgZW5hYmxlTGlmZWN5Y2xlV29ya2Zsb3c/OiBib29sZWFuO1xuICBzZXR1cD86IFNhbmRib3hTZXR1cDtcbiAgb25SZXN0YXJ0PzogT25SZXN0YXJ0O1xufSk6IFNhbmRib3hXaXRoTWV0YTxUVGFncz4ge1xuICBjb25zdCBjYWNoZWQgPSBzYW5kYm94Q2FjaGUuZ2V0KHNhbmRib3hSZWNvcmQuaWQpO1xuICBpZiAoY2FjaGVkKSB7XG4gICAgZGVidWcoXCJbZ2V0U2FuZGJveF0gY2FjaGUgaGl0IGZvclwiLCBzYW5kYm94UmVjb3JkLmlkKTtcbiAgICByZXR1cm4gY2FjaGVkIGFzIFNhbmRib3hXaXRoTWV0YTxUVGFncz47XG4gIH1cblxuICBjb25zdCBzYnggPSBjcmVhdGVTYW5kYm94PFRUYWdzPih7XG4gICAgc2FuZGJveFJlY29yZCxcbiAgICBzdG9yYWdlQ29uZmlnLFxuICAgIHN0b3JhZ2UsXG4gICAgZW5hYmxlTGlmZWN5Y2xlV29ya2Zsb3csXG4gICAgc2V0dXAsXG4gICAgb25SZXN0YXJ0LFxuICB9KTtcblxuICBzYW5kYm94Q2FjaGUuc2V0KHNhbmRib3hSZWNvcmQuaWQsIHNieCBhcyBTYW5kYm94V2l0aE1ldGEpO1xuXG4gIHJldHVybiBzYng7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVNhbmRib3g8VFRhZ3MgZXh0ZW5kcyBUYWdzU2NoZW1hID0gVGFnc1NjaGVtYT4oe1xuICBzYW5kYm94UmVjb3JkLFxuICBzdG9yYWdlQ29uZmlnLFxuICBzdG9yYWdlLFxuICBlbmFibGVMaWZlY3ljbGVXb3JrZmxvdyA9IHRydWUsXG4gIHNldHVwLFxuICBvblJlc3RhcnQsXG59OiB7XG4gIHN0b3JhZ2VDb25maWc6IFN0b3JhZ2VDb25maWc7XG4gIHNhbmRib3hSZWNvcmQ6IFNhbmRib3hSZWNvcmQ7XG4gIHN0b3JhZ2U6IFN0b3JhZ2U7XG4gIGVuYWJsZUxpZmVjeWNsZVdvcmtmbG93PzogYm9vbGVhbjtcbiAgc2V0dXA/OiBTYW5kYm94U2V0dXA7XG4gIG9uUmVzdGFydD86IE9uUmVzdGFydDtcbn0pOiBTYW5kYm94V2l0aE1ldGE8VFRhZ3M+IHtcbiAgbGV0IHNieDogU2FuZGJveFdpdGhNZXRhPFRUYWdzPjtcblxuICBzd2l0Y2ggKHNhbmRib3hSZWNvcmQuY29uZmlnLnR5cGUpIHtcbiAgICBjYXNlIFwibG9jYWxcIjpcbiAgICAgIHNieCA9IGxvY2FsU2FuZGJveDxUVGFncz4oe1xuICAgICAgICBzYW5kYm94UmVjb3JkOiBzYW5kYm94UmVjb3JkIGFzIFNhbmRib3hSZWNvcmQgJiB7XG4gICAgICAgICAgY29uZmlnOiB7IHR5cGU6IFwibG9jYWxcIiB9O1xuICAgICAgICB9LFxuICAgICAgICBzdG9yYWdlLFxuICAgICAgICBzZXR1cCxcbiAgICAgICAgb25SZXN0YXJ0LFxuICAgICAgfSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIFwidmVyY2VsXCI6XG4gICAgICBzYnggPSB2ZXJjZWxTYW5kYm94PFRUYWdzPih7XG4gICAgICAgIHNhbmRib3hSZWNvcmQ6IHNhbmRib3hSZWNvcmQgYXMgU2FuZGJveFJlY29yZCAmIHtcbiAgICAgICAgICBjb25maWc6IHsgdHlwZTogXCJ2ZXJjZWxcIiB9O1xuICAgICAgICB9LFxuICAgICAgICBzdG9yYWdlQ29uZmlnLFxuICAgICAgICBzdG9yYWdlLFxuICAgICAgICBlbmFibGVMaWZlY3ljbGVXb3JrZmxvdyxcbiAgICAgICAgc2V0dXAsXG4gICAgICAgIG9uUmVzdGFydCxcbiAgICAgIH0pO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcImN1c3RvbVwiOlxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ3VzdG9tIHNhbmRib3hlcyBhcmUgbm90IHN1cHBvcnRlZFwiKTtcbiAgICBkZWZhdWx0OlxuICAgICAgc2FuZGJveFJlY29yZC5jb25maWcgc2F0aXNmaWVzIG5ldmVyO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgVW5rbm93biBzYW5kYm94IHR5cGU6ICR7XG4gICAgICAgICAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiAuXG4gICAgICAgICAgKHNhbmRib3hSZWNvcmQuY29uZmlnIGFzIGFueSkudHlwZVxuICAgICAgICB9YFxuICAgICAgKTtcbiAgfVxuXG4gIC8vIERvbid0IGF3YWl0IF9vblJlYWR5IGhlcmUgXHUyMDE0IGxldCB0aGUgd29ya2Zsb3cgYXdhaXQgaXQgc28gaXQgY2FuIGVtaXRcbiAgLy8gc3RhdHVzIGluZGljYXRvcnMgb3ZlciB0aGUgc3RyZWFtIHdoaWxlIHNldHVwIHJ1bnMuXG4gIC8vIEluc3RlYWQsIHdyYXAgc2FuZGJveCBtZXRob2RzIHNvIGFueSBvcGVyYXRpb24gb24gdGhlIHNhbmRib3ggaW1wbGljaXRseVxuICAvLyB3YWl0cyBmb3Igc2V0dXAgdG8gY29tcGxldGUuIFdlIHJldHVybiBhIE5FVyBvYmplY3Qgc28gdGhhdCBzZXR1cC5ydW4oKSxcbiAgLy8gd2hpY2ggaG9sZHMgdGhlIG9yaWdpbmFsIGBzYnhgIHZpYSBjbG9zdXJlLCBjYWxscyB1bndyYXBwZWQgbWV0aG9kcyBhbmRcbiAgLy8gYXZvaWRzIGEgZGVhZGxvY2suXG4gIGlmICghc2J4Ll9vblJlYWR5KSB7XG4gICAgcmV0dXJuIHNieDtcbiAgfVxuXG4gIGNvbnN0IG9uUmVhZHkgPSBzYnguX29uUmVhZHk7XG4gIHJldHVybiB7XG4gICAgLi4uc2J4LFxuICAgIGV4ZWM6IGFzeW5jIChvcHRzKSA9PiB7XG4gICAgICBhd2FpdCBvblJlYWR5O1xuICAgICAgcmV0dXJuIHNieC5leGVjKG9wdHMpO1xuICAgIH0sXG4gICAgZ2V0RG9tYWluOiBhc3luYyAocG9ydCkgPT4ge1xuICAgICAgYXdhaXQgb25SZWFkeTtcbiAgICAgIHJldHVybiBzYnguZ2V0RG9tYWluKHBvcnQpO1xuICAgIH0sXG4gICAgcmVhZEZpbGU6IGFzeW5jIChvcHRzKSA9PiB7XG4gICAgICBhd2FpdCBvblJlYWR5O1xuICAgICAgcmV0dXJuIHNieC5yZWFkRmlsZShvcHRzKTtcbiAgICB9LFxuICAgIHdyaXRlRmlsZXM6IGFzeW5jIChvcHRzKSA9PiB7XG4gICAgICBhd2FpdCBvblJlYWR5O1xuICAgICAgcmV0dXJuIHNieC53cml0ZUZpbGVzKG9wdHMpO1xuICAgIH0sXG4gIH07XG59XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7QUFBQSxJQUFNLFVBQ0osUUFBUSxJQUFJLGdCQUFnQixPQUFPLFFBQVEsSUFBSSxnQkFBZ0I7QUFFMUQsU0FBUyxTQUFTLE1BQWlCO0FBQ3hDLE1BQUksU0FBUztBQUNYLFlBQVEsSUFBSSxHQUFHLElBQUk7QUFBQSxFQUNyQjtBQUNGOzs7QUNOQSxTQUFTLGFBQWE7QUFDdEIsWUFBWSxRQUFRO0FBQ3BCLFlBQVlBLFdBQVU7QUFDdEIsWUFBWSxZQUFZO0FBQ3hCLFNBQVMsWUFBWTs7O0FDTHJCLFlBQVksVUFBVTtBQUl0QixJQUFNLGNBQWM7QUFDcEIsSUFBTSxnQkFBZ0I7QUFPdEIsZUFBZSxZQUNiLFNBQ0EsTUFDQSxZQUMrRDtBQUMvRCxXQUFTLFVBQVUsS0FBSyxXQUFXO0FBQ2pDLFVBQU0sYUFBYSxNQUFNLFFBQVEsS0FBSyxJQUFJO0FBQzFDLFFBQUksc0JBQXNCLE9BQU87QUFDL0IsWUFBTTtBQUFBLElBQ1I7QUFDQSxVQUFNLFNBQVMsTUFBTSxXQUFXO0FBQ2hDLFFBQUksT0FBTyxhQUFhLEdBQUc7QUFDekIsYUFBTztBQUFBLElBQ1Q7QUFF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VDtBQUVBLFFBQU0sTUFBTSxjQUFxQjtBQUFBLElBQy9CO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxFQUNGLENBQUM7QUFFRCxlQUFhLElBQUksY0FBYyxJQUFJLEdBQXNCO0FBRXpELFNBQU87QUFDVDtBQUVBLFNBQVMsY0FBcUQ7QUFBQSxFQUM1RDtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQUEsRUFDQSwwQkFBMEI7QUFBQSxFQUMxQjtBQUFBLEVBQ0E7QUFDRixHQU8yQjtBQUN6QixNQUFJO0FBRUosVUFBUSxjQUFjLE9BQU8sTUFBTTtBQUFBLElBQ2pDLEtBQUs7QUFDSCxZQUFNLGFBQW9CO0FBQUEsUUFDeEI7QUFBQSxRQUdBO0FBQUEsUUFDQTtBQUFBLFFBQ0E7QUFBQSxNQUNGLENBQUM7QUFDRDtBQUFBLElBQ0YsS0FBSztBQUNILFlBQU0sY0FBcUI7QUFBQSxRQUN6QjtBQUFBLFFBR0E7QUFBQSxRQUNBO0FBQUEsUUFDQTtBQUFBLFFBQ0E7QUFBQSxRQUNBO0FBQUEsTUFDRixDQUFDO0FBQ0Q7QUFBQSxJQUNGLEtBQUs7QUFDSCxZQUFNLElBQUksTUFBTSxvQ0FBb0M7QUFBQSxJQUN0RDtBQUNFLG9CQUFjO0FBQ2QsWUFBTSxJQUFJO0FBQUEsUUFDUjtBQUFBLFFBRUcsY0FBYyxPQUFlLElBQ2hDO0FBQUEsTUFDRjtBQUFBLEVBQ0o7QUFRQSxNQUFJLENBQUMsSUFBSSxVQUFVO0FBQ2pCLFdBQU87QUFBQSxFQUNUO0FBRUEsUUFBTSxVQUFVLElBQUk7QUFDcEIsU0FBTztBQUFBLElBQ0wsR0FBRztBQUFBLElBQ0gsTUFBTSxPQUFPLFNBQVM7QUFDcEIsWUFBTTtBQUNOLGFBQU8sSUFBSSxLQUFLLElBQUk7QUFBQSxJQUN0QjtBQUFBLElBQ0EsV0FBVyxPQUFPLFNBQVM7QUFDekIsWUFBTTtBQUNOLGFBQU8sSUFBSSxVQUFVLElBQUk7QUFBQSxJQUMzQjtBQUFBLElBQ0EsVUFBVSxPQUFPLFNBQVM7QUFDeEIsWUFBTTtBQUNOLGFBQU8sSUFBSSxTQUFTLElBQUk7QUFBQSxJQUMxQjtBQUFBLElBQ0EsWUFBWSxPQUFPLFNBQVM7QUFDMUIsWUFBTTtBQUNOLGFBQU8sSUFBSSxXQUFXLElBQUk7QUFBQSxJQUM1QjtBQUFBLEVBQ0Y7QUFDRjsiLAogICJuYW1lcyI6IFsicGF0aCIsICJyZXN1bHQiLCAic3RvcmFnZSIsICJzYW5kYm94UmVjb3JkIiwgInBhdGgiLCAiZXJyb3JlIiwgInNhbmRib3giLCAicGF0aCIsICJzbmFwc2hvdElkIiwgImdldFNhbmRib3giLCAic2FuZGJveFJlY29yZCJdCn0K
|