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