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