experimental-agent 0.1.4 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-workflow.d.mts +2 -1
- package/dist/agent-workflow.d.ts +2 -1
- package/dist/agent-workflow.js +1382 -552
- package/dist/agent-workflow.mjs +3 -2
- package/dist/chunk-AML2VCQS.mjs +1287 -0
- package/dist/chunk-FQ67QZOI.mjs +75 -0
- package/dist/chunk-NO7RHGTH.mjs +2367 -0
- package/dist/{chunk-24UDM5XV.mjs → chunk-NXDVNJRS.mjs} +1 -1
- package/dist/chunk-OZZVS6L5.mjs +139 -0
- package/dist/{chunk-GYOBANFH.mjs → chunk-QRWGDFFY.mjs} +3 -7
- package/dist/{chunk-2ZXHR6T6.mjs → chunk-SJVFFE5D.mjs} +18 -17
- package/dist/chunk-TGNVXSMX.mjs +399 -0
- package/dist/chunk-ZIAHPXOJ.mjs +595 -0
- package/dist/{client-SNN3XDKO.mjs → client-BKA7XBGW.mjs} +1 -1
- package/dist/{client-Bkuq-Dfa.d.mts → client-CEeSFGva.d.mts} +159 -123
- package/dist/{client-Bkuq-Dfa.d.ts → client-CEeSFGva.d.ts} +159 -123
- package/dist/{sandbox-IFK5MVRM.mjs → docker-FB2MJTHJ.mjs} +6 -4
- package/dist/{handler-WFNQWR6V.mjs → handler-FRUPZ4LX.mjs} +1 -1
- package/dist/index.d.mts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1554 -593
- package/dist/index.mjs +139 -33
- package/dist/lifecycle-workflow.d.mts +2 -1
- package/dist/lifecycle-workflow.d.ts +2 -1
- package/dist/lifecycle-workflow.js +29 -18
- package/dist/lifecycle-workflow.mjs +1 -1
- package/dist/{local-fs-handlers-ESZBRAWK.mjs → local-fs-handlers-SYOCKTPN.mjs} +10 -2
- package/dist/next/loader.js +15 -12
- package/dist/next/loader.mjs +14 -7
- package/dist/next.d.mts +1 -1
- package/dist/next.d.ts +1 -1
- package/dist/next.js +15 -10
- package/dist/next.mjs +14 -5
- package/dist/{process-manager-ZCET3VD2.mjs → process-manager-JDUJDYGU.mjs} +1 -1
- package/dist/sandbox-UENKQV3T.mjs +21 -0
- package/dist/{storage-FCSHTDLC.mjs → storage-LSDMRW73.mjs} +2 -2
- package/package.json +2 -6
- package/dist/chunk-4WDKWMVB.mjs +0 -389
- package/dist/chunk-64THY7Y7.mjs +0 -155
- package/dist/chunk-IACG26TC.mjs +0 -2212
- package/dist/chunk-NGLND33F.mjs +0 -1247
|
@@ -0,0 +1,1287 @@
|
|
|
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+IHwgbnVsbCA9IG51bGw7XG5cbiAgY29uc3Qgc2FuZGJveDogU2FuZGJveDxUVGFncz4gPSB7XG4gICAgaWQ6IHNhbmRib3hSZWNvcmQuaWQsXG4gICAgY29uZmlnOiBzYW5kYm94UmVjb3JkLmNvbmZpZyxcbiAgICBjd2Q6IGJhc2VQYXRoLFxuICAgIGV4ZWM6ICh7IGNvbW1hbmQsIGFyZ3MsIGN3ZCwgZW52LCBzaWduYWwsIHN1ZG8gfSkgPT4ge1xuICAgICAgcmV0dXJuIGVycm9yZS50cnlBc3luYyh7XG4gICAgICAgIHRyeTogKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IGNvbW1hbmRJZCA9IGBjb21tYW5kXyR7dWxpZCgpfWA7XG4gICAgICAgICAgY29uc3QgZmluYWxDbWQgPSBzdWRvID8gXCJzdWRvXCIgOiBjb21tYW5kO1xuICAgICAgICAgIGNvbnN0IGZpbmFsQXJncyA9IHN1ZG8gPyBbY29tbWFuZCwgLi4uKGFyZ3MgPz8gW10pXSA6IChhcmdzID8/IFtdKTtcblxuICAgICAgICAgIGNvbnN0IGNoaWxkID0gc3Bhd24oZmluYWxDbWQsIGZpbmFsQXJncywge1xuICAgICAgICAgICAgY3dkOiBjd2QgPyBwYXRoLnJlc29sdmUoYmFzZVBhdGgsIGN3ZCkgOiBiYXNlUGF0aCxcbiAgICAgICAgICAgIGVudjogZW52ID8geyAuLi5wcm9jZXNzLmVudiwgLi4uZW52IH0gOiB1bmRlZmluZWQsXG4gICAgICAgICAgICBzaWduYWwsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBwcm9jZXNzZXMuc2V0KGNvbW1hbmRJZCwgY2hpbGQpO1xuXG4gICAgICAgICAgbGV0IHN0ZG91dCA9IFwiXCI7XG4gICAgICAgICAgbGV0IHN0ZGVyciA9IFwiXCI7XG4gICAgICAgICAgY29uc3QgbG9nUXVldWU6IExvZ0VudHJ5W10gPSBbXTtcbiAgICAgICAgICBsZXQgbG9nUmVzb2x2ZTogKCgpID0+IHZvaWQpIHwgbnVsbCA9IG51bGw7XG4gICAgICAgICAgbGV0IGNsb3NlZCA9IGZhbHNlO1xuXG4gICAgICAgICAgY2hpbGQuc3Rkb3V0Lm9uKFwiZGF0YVwiLCAoZGF0YTogc3RyaW5nIHwgQnVmZmVyKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBzdHIgPSBTdHJpbmcoZGF0YSk7XG4gICAgICAgICAgICBzdGRvdXQgKz0gc3RyO1xuICAgICAgICAgICAgbG9nUXVldWUucHVzaCh7IHN0cmVhbTogXCJzdGRvdXRcIiwgZGF0YTogc3RyIH0pO1xuICAgICAgICAgICAgbG9nUmVzb2x2ZT8uKCk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBjaGlsZC5zdGRlcnIub24oXCJkYXRhXCIsIChkYXRhOiBzdHJpbmcgfCBCdWZmZXIpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN0ciA9IFN0cmluZyhkYXRhKTtcbiAgICAgICAgICAgIHN0ZGVyciArPSBzdHI7XG4gICAgICAgICAgICBsb2dRdWV1ZS5wdXNoKHsgc3RyZWFtOiBcInN0ZGVyclwiLCBkYXRhOiBzdHIgfSk7XG4gICAgICAgICAgICBsb2dSZXNvbHZlPy4oKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBQcm9taXNlPHtcbiAgICAgICAgICAgIHN0ZG91dDogc3RyaW5nO1xuICAgICAgICAgICAgc3RkZXJyOiBzdHJpbmc7XG4gICAgICAgICAgICBleGl0Q29kZTogbnVtYmVyO1xuICAgICAgICAgIH0+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNoaWxkLm9uKFwiZXJyb3JcIiwgKGVycikgPT4ge1xuICAgICAgICAgICAgICBwcm9jZXNzZXMuZGVsZXRlKGNvbW1hbmRJZCk7XG4gICAgICAgICAgICAgIGNsb3NlZCA9IHRydWU7XG4gICAgICAgICAgICAgIGxvZ1Jlc29sdmU/LigpO1xuICAgICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBjaGlsZC5vbihcImNsb3NlXCIsIChjb2RlOiBudW1iZXIgfCBudWxsKSA9PiB7XG4gICAgICAgICAgICAgIHByb2Nlc3Nlcy5kZWxldGUoY29tbWFuZElkKTtcbiAgICAgICAgICAgICAgY2xvc2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgbG9nUmVzb2x2ZT8uKCk7XG4gICAgICAgICAgICAgIHJlc29sdmUoeyBzdGRvdXQsIHN0ZGVyciwgZXhpdENvZGU6IGNvZGUgPz8gMCB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgYXN5bmMgZnVuY3Rpb24qIGxvZ3MoKTogQXN5bmNJdGVyYWJsZTxMb2dFbnRyeT4ge1xuICAgICAgICAgICAgd2hpbGUgKCFjbG9zZWQgfHwgbG9nUXVldWUubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICBjb25zdCBlbnRyeSA9IGxvZ1F1ZXVlLnNoaWZ0KCk7XG4gICAgICAgICAgICAgIGlmIChlbnRyeSkge1xuICAgICAgICAgICAgICAgIHlpZWxkIGVudHJ5O1xuICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFjbG9zZWQpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgbG9nUmVzb2x2ZSA9IHJlc29sdmU7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgbG9nUmVzb2x2ZSA9IG51bGw7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHsgY29tbWFuZElkLCBsb2dzLCByZXN1bHQgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIGNhdGNoOiAoZTogdW5rbm93bikgPT5cbiAgICAgICAgICBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pLFxuICAgICAgfSk7XG4gICAgfSxcblxuICAgIGdldERvbWFpbjogKHBvcnQpID0+IHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoYGh0dHA6Ly9sb2NhbGhvc3Q6JHtwb3J0fWApO1xuICAgIH0sXG5cbiAgICBraWxsOiBhc3luYyAoeyBjb21tYW5kSWQsIHN0b3JhZ2UgfSkgPT4ge1xuICAgICAgY29uc3QgY2hpbGQgPSBwcm9jZXNzZXMuZ2V0KGNvbW1hbmRJZCk7XG4gICAgICBpZiAoIWNoaWxkKSB7XG4gICAgICAgIHJldHVybiBuZXcgU2FuZGJveEVycm9yKHtcbiAgICAgICAgICByZWFzb246IGBDb21tYW5kICR7Y29tbWFuZElkfSBub3QgZm91bmQgb3IgYWxyZWFkeSBmaW5pc2hlZGAsXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBjaGlsZC5raWxsKFwiU0lHVEVSTVwiKTtcblxuICAgICAgY29uc3QgY21kID0gYXdhaXQgc3RvcmFnZS5jb21tYW5kLmdldChjb21tYW5kSWQpO1xuICAgICAgaWYgKGNtZCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHJldHVybiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBjbWQubWVzc2FnZSwgY2F1c2U6IGNtZCB9KTtcbiAgICAgIH1cbiAgICAgIGlmIChjbWQgJiYgY21kLnN0YXR1cyA9PT0gXCJydW5uaW5nXCIpIHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3RvcmFnZS5jb21tYW5kLnNldCh7XG4gICAgICAgICAgLi4uY21kLFxuICAgICAgICAgIHN0YXR1czogXCJraWxsZWRcIixcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgIHJldHVybiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiByZXN1bHQubWVzc2FnZSwgY2F1c2U6IHJlc3VsdCB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sXG5cbiAgICByZWFkRmlsZTogYXN5bmMgKHsgcGF0aDogZmlsZVBhdGggfSkgPT4ge1xuICAgICAgY29uc3QgZnVsbFBhdGggPSBwYXRoLmpvaW4oYmFzZVBhdGgsIGZpbGVQYXRoKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBhd2FpdCBmcy5yZWFkRmlsZShmdWxsUGF0aCk7XG4gICAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICBlIGluc3RhbmNlb2YgRXJyb3IgJiZcbiAgICAgICAgICBcImNvZGVcIiBpbiBlICYmXG4gICAgICAgICAgKGUgYXMgTm9kZUpTLkVycm5vRXhjZXB0aW9uKS5jb2RlID09PSBcIkVOT0VOVFwiXG4gICAgICAgICkge1xuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pO1xuICAgICAgfVxuICAgIH0sXG5cbiAgICB3cml0ZUZpbGVzOiAob3B0cykgPT4gd3JpdGVGaWxlcyh7IHNhbmRib3gsIC4uLm9wdHMgfSksXG5cbiAgICB1cGRhdGVOZXR3b3JrUG9saWN5OiAoKSA9PlxuICAgICAgUHJvbWlzZS5yZXNvbHZlKFxuICAgICAgICBuZXcgU2FuZGJveEVycm9yKHtcbiAgICAgICAgICByZWFzb246IFwidXBkYXRlTmV0d29ya1BvbGljeSBpcyBvbmx5IGF2YWlsYWJsZSBmb3IgVmVyY2VsIHNhbmRib3hlc1wiLFxuICAgICAgICB9KVxuICAgICAgKSxcblxuICAgIGxpZmVjeWNsZToge1xuICAgICAgc3RhcnQ6ICgpID0+IHtcbiAgICAgICAgaWYgKHN0YXJ0UHJvbWlzZSkge1xuICAgICAgICAgIHJldHVybiBzdGFydFByb21pc2U7XG4gICAgICAgIH1cbiAgICAgICAgc3RhcnRQcm9taXNlID0gKGFzeW5jICgpID0+IHtcbiAgICAgICAgICBpZiAoIXNldHVwICYmIHNhbmRib3hSZWNvcmQuc2V0dXBLZXkpIHtcbiAgICAgICAgICAgIGF3YWl0IHBvbGxGb3JTZXR1cENvbXBsZXRpb24oe1xuICAgICAgICAgICAgICBzdG9yYWdlLFxuICAgICAgICAgICAgICBzYW5kYm94SWQ6IHNhbmRib3hSZWNvcmQuaWQsXG4gICAgICAgICAgICAgIHNldHVwS2V5OiBzYW5kYm94UmVjb3JkLnNldHVwS2V5LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHNldHVwKSB7XG4gICAgICAgICAgICBjb25zdCBleGlzdGluZyA9IGF3YWl0IHN0b3JhZ2Uuc2V0dXAuZ2V0KHNldHVwLmtleSk7XG4gICAgICAgICAgICBpZiAoZXhpc3RpbmcgaW5zdGFuY2VvZiBFcnJvciB8fCAhZXhpc3RpbmcpIHtcbiAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBhd2FpdCBzZXR1cC5ydW4oc2FuZGJveCk7XG4gICAgICAgICAgICAgICAgYXdhaXQgc3RvcmFnZS5zZXR1cC5zZXQoe1xuICAgICAgICAgICAgICAgICAga2V5OiBzZXR1cC5rZXksXG4gICAgICAgICAgICAgICAgICBzbmFwc2hvdElkOiBudWxsLFxuICAgICAgICAgICAgICAgICAgY3JlYXRlZEF0OiBEYXRlLm5vdygpLFxuICAgICAgICAgICAgICAgICAgbGFzdFVzZWRBdDogbnVsbCxcbiAgICAgICAgICAgICAgICAgIGFjcXVpcmluZ0xvY2tJZDogbnVsbCxcbiAgICAgICAgICAgICAgICAgIGFjcXVpcmluZ0xvY2tBdDogbnVsbCxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBhd2FpdCBtYXJrU2V0dXBDb21wbGV0ZSh7XG4gICAgICAgICAgICAgICAgICBzdG9yYWdlLFxuICAgICAgICAgICAgICAgICAgc2FuZGJveElkOiBzYW5kYm94UmVjb3JkLmlkLFxuICAgICAgICAgICAgICAgICAgc2V0dXBLZXk6IHNldHVwLmtleSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIGF3YWl0IHJlc2V0U2V0dXBTdGF0ZSh7XG4gICAgICAgICAgICAgICAgICBzdG9yYWdlLFxuICAgICAgICAgICAgICAgICAgc2FuZGJveElkOiBzYW5kYm94UmVjb3JkLmlkLFxuICAgICAgICAgICAgICAgICAgc2V0dXBLZXk6IHNldHVwLmtleSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKG9uUmVzdGFydCkge1xuICAgICAgICAgICAgYXdhaXQgb25SZXN0YXJ0KHNhbmRib3gpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB9KSgpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgc3RhcnRQcm9taXNlID0gbnVsbDtcbiAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHN0YXJ0UHJvbWlzZTtcbiAgICAgIH0sXG4gICAgICBzbmFwc2hvdDogKCkgPT5cbiAgICAgICAgUHJvbWlzZS5yZXNvbHZlKFxuICAgICAgICAgIG5ldyBTYW5kYm94RXJyb3Ioe1xuICAgICAgICAgICAgcmVhc29uOiBcInNuYXBzaG90IGlzIG5vdCBzdXBwb3J0ZWQgZm9yIGxvY2FsIHNhbmRib3hlc1wiLFxuICAgICAgICAgIH0pXG4gICAgICAgICksXG4gICAgICBzdG9wOiAoKSA9PlxuICAgICAgICBQcm9taXNlLnJlc29sdmUoXG4gICAgICAgICAgbmV3IFNhbmRib3hFcnJvcih7XG4gICAgICAgICAgICByZWFzb246IFwic3RvcCBpcyBub3Qgc3VwcG9ydGVkIGZvciBsb2NhbCBzYW5kYm94ZXNcIixcbiAgICAgICAgICB9KVxuICAgICAgICApLFxuICAgICAgZ2V0U3RhdHVzOiAoKSA9PlxuICAgICAgICBQcm9taXNlLnJlc29sdmUoXG4gICAgICAgICAgbmV3IFNhbmRib3hFcnJvcih7XG4gICAgICAgICAgICByZWFzb246IFwiZ2V0U3RhdHVzIGlzIG5vdCBzdXBwb3J0ZWQgZm9yIGxvY2FsIHNhbmRib3hlc1wiLFxuICAgICAgICAgIH0pXG4gICAgICAgICksXG4gICAgICBnZXRDcmVhdGVkQXQ6ICgpID0+XG4gICAgICAgIFByb21pc2UucmVzb2x2ZShcbiAgICAgICAgICBuZXcgU2FuZGJveEVycm9yKHtcbiAgICAgICAgICAgIHJlYXNvbjogXCJnZXRDcmVhdGVkQXQgaXMgbm90IHN1cHBvcnRlZCBmb3IgbG9jYWwgc2FuZGJveGVzXCIsXG4gICAgICAgICAgfSlcbiAgICAgICAgKSxcbiAgICAgIGdldFJlbWFpbmluZ1RpbWVvdXQ6ICgpID0+XG4gICAgICAgIFByb21pc2UucmVzb2x2ZShcbiAgICAgICAgICBuZXcgU2FuZGJveEVycm9yKHtcbiAgICAgICAgICAgIHJlYXNvbjogXCJnZXRSZW1haW5pbmdUaW1lb3V0IGlzIG5vdCBzdXBwb3J0ZWQgZm9yIGxvY2FsIHNhbmRib3hlc1wiLFxuICAgICAgICAgIH0pXG4gICAgICAgICksXG4gICAgfSxcblxuICAgIHRhZzoge1xuICAgICAgbGlzdDogYXN5bmMgKCkgPT4ge1xuICAgICAgICBjb25zdCBzYW5kYm94UmVjb3JkID0gYXdhaXQgc3RvcmFnZS5zYW5kYm94LmdldChzYW5kYm94LmlkKTtcbiAgICAgICAgaWYgKHNhbmRib3hSZWNvcmQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgIHJldHVybiBzYW5kYm94UmVjb3JkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAoc2FuZGJveFJlY29yZC50YWdzID8/IHt9KSBhcyBUVGFncztcbiAgICAgIH0sXG4gICAgICBnZXQ6IGFzeW5jIChrZXk6IHN0cmluZykgPT4ge1xuICAgICAgICBjb25zdCBzYW5kYm94UmVjb3JkID0gYXdhaXQgc3RvcmFnZS5zYW5kYm94LmdldChzYW5kYm94LmlkKTtcbiAgICAgICAgaWYgKHNhbmRib3hSZWNvcmQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgIHJldHVybiBzYW5kYm94UmVjb3JkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzYW5kYm94UmVjb3JkLnRhZ3M/LltrZXkgYXMgc3RyaW5nXSBhc1xuICAgICAgICAgIHwgVFRhZ3NbdHlwZW9mIGtleV1cbiAgICAgICAgICB8IHVuZGVmaW5lZDtcbiAgICAgIH0sXG4gICAgICBzZXQ6IGFzeW5jIChrZXk6IHN0cmluZywgdmFsdWU6IHVua25vd24pID0+IHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3RvcmFnZS5zYW5kYm94LnRhZy5zZXQoe1xuICAgICAgICAgIHNhbmRib3hJZDogc2FuZGJveC5pZCxcbiAgICAgICAgICB0YWdzOiB7IFtrZXldOiB2YWx1ZSB9IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfSxcbiAgICAgIHNldE1hbnk6IGFzeW5jICh0YWdzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikgPT4ge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzdG9yYWdlLnNhbmRib3gudGFnLnNldCh7XG4gICAgICAgICAgc2FuZGJveElkOiBzYW5kYm94LmlkLFxuICAgICAgICAgIHRhZ3M6IHRhZ3MgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9LFxuICAgIH0sXG4gIH07XG5cbiAgcmV0dXJuIHNhbmRib3g7XG59O1xuIiwgImltcG9ydCAqIGFzIHBhdGggZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHsgU2FuZGJveCBhcyBWZXJjZWxTYW5kYm94U0RLIH0gZnJvbSBcIkB2ZXJjZWwvc2FuZGJveFwiO1xuaW1wb3J0ICogYXMgZXJyb3JlIGZyb20gXCJlcnJvcmVcIjtcbmltcG9ydCB7IHN0YXJ0IH0gZnJvbSBcIndvcmtmbG93L2FwaVwiO1xuaW1wb3J0IHsgU2FuZGJveEVycm9yLCBTYW5kYm94Tm90Rm91bmRFcnJvciB9IGZyb20gXCIuLi8uLi9lcnJvcnNcIjtcbmltcG9ydCB0eXBlIHsgVGFnc1NjaGVtYSB9IGZyb20gXCIuLi8uLi9pbmRleFwiO1xuaW1wb3J0IHtcbiAgZ2V0U3RvcmFnZSxcbiAgdHlwZSBScGNGbixcbiAgdHlwZSBTYW5kYm94UmVjb3JkLFxuICB0eXBlIFN0b3JhZ2UsXG4gIHR5cGUgU3RvcmFnZUNvbmZpZyxcbn0gZnJvbSBcIi4uLy4uL3N0b3JhZ2VcIjtcbmltcG9ydCB7IGNyZWF0ZUxvZ2dlciB9IGZyb20gXCIuLi8uLi91dGlscy9sb2dnZXJcIjtcbmltcG9ydCB7XG4gIG1hcmtTZXR1cENvbXBsZXRlLFxuICBwb2xsRm9yU2V0dXBDb21wbGV0aW9uLFxuICByZXNldFNldHVwU3RhdGUsXG59IGZyb20gXCIuLi9zZXR1cC1wb2xsXCI7XG5pbXBvcnQgdHlwZSB7XG4gIExvZ0VudHJ5LFxuICBPblJlc3RhcnQsXG4gIFNhbmRib3gsXG4gIFNhbmRib3hMaWZlY3ljbGUsXG4gIFNhbmRib3hMaWZlY3ljbGVJbnB1dCxcbiAgU2FuZGJveFNldHVwLFxuICBTYW5kYm94U3RhdHVzLFxufSBmcm9tIFwiLi4vdHlwZXNcIjtcbmltcG9ydCB7IHNhbmRib3hMaWZlY3ljbGVXb3JrZmxvdyB9IGZyb20gXCIuL2xpZmVjeWNsZS13b3JrZmxvd1wiO1xuXG5jb25zdCBzZXR1cExvZyA9IGNyZWF0ZUxvZ2dlcih7IHN1YnN5c3RlbTogXCJzYW5kYm94OnNldHVwXCIgfSk7XG5cbmV4cG9ydCB0eXBlIFZlcmNlbFNhbmRib3hDcmVhdGVPcHRpb25zID0gRXh0cmFjdDxcbiAgUGFyYW1ldGVyczx0eXBlb2YgVmVyY2VsU2FuZGJveFNESy5jcmVhdGU+WzBdLFxuICAvLyBiaW9tZS1pZ25vcmUgbGludC9jb21wbGV4aXR5L25vQmFubmVkVHlwZXM6IC5cbiAge31cbj47XG5cbmV4cG9ydCBjb25zdCBWRVJDRUxfTUFYX1RJTUVPVVRfTVMgPSA1ICogNjAgKiA2MCAqIDEwMDA7IC8vIDUgaG91cnNcbmNvbnN0IExPQ0tfVElNRU9VVF9NUyA9IDUgKiA2MCAqIDEwMDA7IC8vIDUgbWludXRlcyAtIGlmIGxvY2sgb2xkZXIgdGhhbiB0aGlzLCBjb25zaWRlciBpdCBzdGFsZVxuY29uc3QgTE9DS19QT0xMX0lOVEVSVkFMX01TID0gMjAwO1xuXG5jb25zdCBnZXRUZXN0Q3JlZGVudGlhbHMgPSAoKSA9PlxuICBwcm9jZXNzLmVudi5OT0RFX0VOViA9PT0gXCJ0ZXN0XCJcbiAgICA/IHtcbiAgICAgICAgdG9rZW46IHByb2Nlc3MuZW52LlRFU1RfVkVSQ0VMX1RPS0VOLFxuICAgICAgICB0ZWFtSWQ6IHByb2Nlc3MuZW52LlRFU1RfVkVSQ0VMX1RFQU1fSUQsXG4gICAgICAgIHByb2plY3RJZDogcHJvY2Vzcy5lbnYuVEVTVF9WRVJDRUxfUFJPSkVDVF9JRCxcbiAgICAgIH1cbiAgICA6IHt9O1xuXG4vKipcbiAqIE1vZHVsZS1sZXZlbCBjYWNoZSBmb3IgaW4tZmxpZ2h0IHNhbmRib3ggY3JlYXRpb24gcHJvbWlzZXMuXG4gKiBQcmV2ZW50cyBwYXJhbGxlbCByZXF1ZXN0cyB3aXRoaW4gdGhlIHNhbWUgcHJvY2VzcyBmcm9tIGNyZWF0aW5nIGR1cGxpY2F0ZSBzYW5kYm94ZXMuXG4gKi9cbmNvbnN0IGNyZWF0ZVByb21pc2VzID0gbmV3IE1hcDxcbiAgc3RyaW5nLFxuICBQcm9taXNlPFxuICAgIHwgU2FuZGJveEVycm9yXG4gICAgfCB7XG4gICAgICAgIHNhbmRib3hJZDogc3RyaW5nO1xuICAgICAgICBuZWVkc1NldHVwUnVuOiBib29sZWFuO1xuICAgICAgICBjcmVhdGVkRnJvbVNuYXBzaG90OiBib29sZWFuO1xuICAgICAgfVxuICA+XG4+KCk7XG5cbmNvbnN0IEFDVElWSVRZX1RIUk9UVExFX01TID0gMTBfMDAwO1xuY29uc3QgbGFzdEFjdGl2aXR5U2VudCA9IG5ldyBNYXA8c3RyaW5nLCBudW1iZXI+KCk7XG5cbmNvbnN0IERFRkFVTFRfVkNQVVMgPSAyO1xuXG5mdW5jdGlvbiBpc1NhbmRib3hHb25lRXJyb3IoZTogdW5rbm93bik6IGJvb2xlYW4ge1xuICBpZiAoIShlIGluc3RhbmNlb2YgRXJyb3IpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgY29uc3QgZXJyb3JXaXRoUmVzcG9uc2UgPSBlIGFzIHsgcmVzcG9uc2U/OiB7IHN0YXR1cz86IG51bWJlciB9IH07XG4gIGNvbnN0IGVycm9yV2l0aENhdXNlID0gZSBhcyB7IGNhdXNlPzogeyByZXNwb25zZT86IHsgc3RhdHVzPzogbnVtYmVyIH0gfSB9O1xuXG4gIGNvbnN0IHN0YXR1cyA9XG4gICAgZXJyb3JXaXRoUmVzcG9uc2UucmVzcG9uc2U/LnN0YXR1cyA/P1xuICAgIGVycm9yV2l0aENhdXNlLmNhdXNlPy5yZXNwb25zZT8uc3RhdHVzO1xuXG4gIGlmIChzdGF0dXMgPT09IDQxMCB8fCBzdGF0dXMgPT09IDQyMikge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgY29uc3QgbWVzc2FnZSA9IGUubWVzc2FnZSB8fCBTdHJpbmcoZSk7XG4gIGlmIChcbiAgICBtZXNzYWdlLmluY2x1ZGVzKFwiRXhwZWN0ZWQgYSBzdHJlYW0gb2YgY29tbWFuZCBkYXRhXCIpIHx8XG4gICAgbWVzc2FnZS5pbmNsdWRlcyhcIkV4cGVjdGVkIGEgc3RyZWFtIG9mIGxvZ3NcIilcbiAgKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmV4cG9ydCBjb25zdCB2ZXJjZWxTYW5kYm94ID0gPFRUYWdzIGV4dGVuZHMgVGFnc1NjaGVtYSA9IFRhZ3NTY2hlbWE+KHtcbiAgc2FuZGJveFJlY29yZCxcbiAgc3RvcmFnZUNvbmZpZyxcbiAgZW5hYmxlTGlmZWN5Y2xlV29ya2Zsb3csXG4gIHN0b3JhZ2UsXG4gIHJwYyxcbiAgc2V0dXAsXG4gIG9uUmVzdGFydCxcbn06IHtcbiAgc2FuZGJveFJlY29yZDogU2FuZGJveFJlY29yZCAmIHsgY29uZmlnOiB7IHR5cGU6IFwidmVyY2VsXCIgfSB9O1xuICBzdG9yYWdlQ29uZmlnOiBTdG9yYWdlQ29uZmlnO1xuICBlbmFibGVMaWZlY3ljbGVXb3JrZmxvdzogYm9vbGVhbjtcbiAgc3RvcmFnZTogU3RvcmFnZTtcbiAgcnBjOiBScGNGbjtcbiAgc2V0dXA/OiBTYW5kYm94U2V0dXA7XG4gIG9uUmVzdGFydD86IE9uUmVzdGFydDtcbn0pOiBTYW5kYm94PFRUYWdzPiA9PiB7XG4gIGNvbnN0IHsgaWQsIGNvbmZpZyB9ID0gc2FuZGJveFJlY29yZDtcbiAgY29uc3QgdmNwdXMgPSBjb25maWcucmVzb3VyY2VzPy52Y3B1cyA/PyBERUZBVUxUX1ZDUFVTO1xuICBjb25zdCBwb3J0cyA9IGNvbmZpZy5wb3J0cztcbiAgY29uc3QgbmV0d29ya1BvbGljeSA9IGNvbmZpZy5uZXR3b3JrUG9saWN5O1xuICBjb25zdCBpbml0aWFsVmVyY2VsID1cbiAgICBzYW5kYm94UmVjb3JkLnByb3ZpZGVyTWV0YWRhdGE/LnByb3ZpZGVyID09PSBcInZlcmNlbFwiXG4gICAgICA/IHNhbmRib3hSZWNvcmQucHJvdmlkZXJNZXRhZGF0YVxuICAgICAgOiBudWxsO1xuXG4gIHR5cGUgU2FuZGJveEluc3RhbmNlID0gQXdhaXRlZDxSZXR1cm5UeXBlPHR5cGVvZiBWZXJjZWxTYW5kYm94U0RLLmdldD4+O1xuICBsZXQgcmVjb3ZlcmVkRnJvbVN0YWxlID0gZmFsc2U7XG4gIGNvbnN0IEhPTUVfRElSID0gXCIvaG9tZS92ZXJjZWwtc2FuZGJveFwiO1xuICBjb25zdCBjd2QgPSBjb25maWcuY3dkID8/IEhPTUVfRElSO1xuXG4gIGNvbnN0IHBvbGxTdG9yYWdlID0gZ2V0U3RvcmFnZSh7XG4gICAgY29uZmlnOiBzdG9yYWdlQ29uZmlnLFxuICAgIHJwYzogKHApID0+IHJwYyh7IC4uLnAsIF9xdWlldDogdHJ1ZSB9KSxcbiAgfSk7XG5cbiAgdHlwZSBDcmVhdGVSZXN1bHQgPSB7XG4gICAgc2FuZGJveElkOiBzdHJpbmc7XG4gICAgbmVlZHNTZXR1cFJ1bjogYm9vbGVhbjtcbiAgICBjcmVhdGVkRnJvbVNuYXBzaG90OiBib29sZWFuO1xuICB9O1xuXG4gIGFzeW5jIGZ1bmN0aW9uIHBvbGxGb3JTYW5kYm94SWQoKTogUHJvbWlzZTxTYW5kYm94RXJyb3IgfCBDcmVhdGVSZXN1bHQ+IHtcbiAgICBjb25zdCBkb25lID0gc2V0dXBMb2cudGltZShcbiAgICAgIFwid2FpdGluZyBmb3Igc2FuZGJveCBsb2NrXCIsXG4gICAgICB7IHNhbmRib3hJZDogaWQgfSxcbiAgICAgIHsgbG9nT25TdGFydDogdHJ1ZSB9XG4gICAgKTtcbiAgICBjb25zdCBkZWFkbGluZSA9IERhdGUubm93KCkgKyBMT0NLX1RJTUVPVVRfTVM7XG4gICAgd2hpbGUgKERhdGUubm93KCkgPCBkZWFkbGluZSkge1xuICAgICAgYXdhaXQgbmV3IFByb21pc2UoKHIpID0+IHNldFRpbWVvdXQociwgTE9DS19QT0xMX0lOVEVSVkFMX01TKSk7XG4gICAgICBjb25zdCByZWNvcmQgPSBhd2FpdCBwb2xsU3RvcmFnZS5zYW5kYm94LmdldChpZCk7XG4gICAgICBpZiAocmVjb3JkIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IHJlY29yZC5tZXNzYWdlLCBjYXVzZTogcmVjb3JkIH0pO1xuICAgICAgfVxuICAgICAgY29uc3QgdmVyY2VsU2FuZGJveElkID1cbiAgICAgICAgcmVjb3JkPy5wcm92aWRlck1ldGFkYXRhPy5wcm92aWRlciA9PT0gXCJ2ZXJjZWxcIlxuICAgICAgICAgID8gcmVjb3JkLnByb3ZpZGVyTWV0YWRhdGEuc2FuZGJveElkXG4gICAgICAgICAgOiBudWxsO1xuICAgICAgaWYgKHZlcmNlbFNhbmRib3hJZCkge1xuICAgICAgICBkb25lKCk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgc2FuZGJveElkOiB2ZXJjZWxTYW5kYm94SWQsXG4gICAgICAgICAgbmVlZHNTZXR1cFJ1bjogZmFsc2UsXG4gICAgICAgICAgY3JlYXRlZEZyb21TbmFwc2hvdDogZmFsc2UsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCBsb2NrU3RhbGUgPVxuICAgICAgICByZWNvcmQ/LmFjcXVpcmluZ0xvY2tBdCAmJlxuICAgICAgICBEYXRlLm5vdygpIC0gcmVjb3JkLmFjcXVpcmluZ0xvY2tBdCA+PSBMT0NLX1RJTUVPVVRfTVM7XG4gICAgICBpZiAoIXJlY29yZD8uYWNxdWlyaW5nTG9ja0F0IHx8IGxvY2tTdGFsZSkge1xuICAgICAgICBpZiAobG9ja1N0YWxlKSB7XG4gICAgICAgICAgc2V0dXBMb2cud2FybihcInNhbmRib3ggbG9jayBpcyBzdGFsZSwgdGFraW5nIG92ZXJcIiwge1xuICAgICAgICAgICAgc2FuZGJveElkOiBpZCxcbiAgICAgICAgICAgIGxvY2tBZ2U6IERhdGUubm93KCkgLSByZWNvcmQhLmFjcXVpcmluZ0xvY2tBdCEsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZG9uZSh7IHN0YWxlTG9jazogISFsb2NrU3RhbGUgfSk7XG4gICAgICAgIHJldHVybiBkb0dldE9yQ3JlYXRlU2FuZGJveElkKCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBuZXcgU2FuZGJveEVycm9yKHtcbiAgICAgIHJlYXNvbjogXCJUaW1lZCBvdXQgd2FpdGluZyBmb3Igc2FuZGJveCBjcmVhdGlvbiBieSBhbm90aGVyIHByb2Nlc3NcIixcbiAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIHN0YXJ0TGlmZWN5Y2xlV29ya2Zsb3coXG4gICAgdmVyY2VsU2FuZGJveElkOiBzdHJpbmdcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCFlbmFibGVMaWZlY3ljbGVXb3JrZmxvdykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBsaWZlY3ljbGVJbnB1dDogU2FuZGJveExpZmVjeWNsZUlucHV0ID0ge1xuICAgICAgaWQsXG4gICAgICB2ZXJjZWxTYW5kYm94SWQsXG4gICAgICBzdG9yYWdlQ29uZmlnLFxuICAgICAgcnBjLFxuICAgIH07XG4gICAgYXdhaXQgc3RhcnQoc2FuZGJveExpZmVjeWNsZVdvcmtmbG93LCBbeyBpbnB1dDogbGlmZWN5Y2xlSW5wdXQgfV0pLmNhdGNoKFxuICAgICAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0VtcHR5QmxvY2tTdGF0ZW1lbnRzOiBpbnRlbnRpb25hbGx5IGlnbm9yZWQgLSB3b3JrZmxvdyBzdGFydCBpcyBmaXJlLWFuZC1mb3JnZXRcbiAgICAgICgpID0+IHt9XG4gICAgKTtcbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVNhbmRib3hGcm9tU25hcHNob3QoXG4gICAgc25hcHNob3RJZDogc3RyaW5nXG4gICk6IFByb21pc2U8U2FuZGJveEVycm9yIHwgc3RyaW5nPiB7XG4gICAgcmV0dXJuIGF3YWl0IGVycm9yZS50cnlBc3luYyh7XG4gICAgICB0cnk6IGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc3Qgc2FuZGJveCA9IGF3YWl0IFZlcmNlbFNhbmRib3hTREsuY3JlYXRlKHtcbiAgICAgICAgICBzb3VyY2U6IHsgdHlwZTogXCJzbmFwc2hvdFwiLCBzbmFwc2hvdElkIH0sXG4gICAgICAgICAgcmVzb3VyY2VzOiB7IHZjcHVzIH0sXG4gICAgICAgICAgdGltZW91dDogVkVSQ0VMX01BWF9USU1FT1VUX01TLFxuICAgICAgICAgIHBvcnRzLFxuICAgICAgICAgIG5ldHdvcmtQb2xpY3ksXG4gICAgICAgICAgLi4uZ2V0VGVzdENyZWRlbnRpYWxzKCksXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgICBhd2FpdCBzdG9yYWdlLnNhbmRib3guc2V0KHtcbiAgICAgICAgICBpZCxcbiAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgdGFnczogc2FuZGJveFJlY29yZC50YWdzLFxuICAgICAgICAgIGNyZWF0ZWRBdDogbm93LFxuICAgICAgICAgIGxhc3RBY3Rpdml0eUF0OiBub3csXG4gICAgICAgICAgYWNxdWlyaW5nTG9ja0lkOiBudWxsLFxuICAgICAgICAgIGFjcXVpcmluZ0xvY2tBdDogbnVsbCxcbiAgICAgICAgICBzZXR1cEtleTogc2FuZGJveFJlY29yZC5zZXR1cEtleSxcbiAgICAgICAgICBwcm92aWRlck1ldGFkYXRhOiB7XG4gICAgICAgICAgICBwcm92aWRlcjogXCJ2ZXJjZWxcIixcbiAgICAgICAgICAgIHNhbmRib3hJZDogc2FuZGJveC5zYW5kYm94SWQsXG4gICAgICAgICAgICBzbmFwc2hvdElkLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgICBhd2FpdCBzdGFydExpZmVjeWNsZVdvcmtmbG93KHNhbmRib3guc2FuZGJveElkKTtcbiAgICAgICAgcmV0dXJuIHNhbmRib3guc2FuZGJveElkO1xuICAgICAgfSxcbiAgICAgIGNhdGNoOiAoZSkgPT4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogU3RyaW5nKGUpLCBjYXVzZTogZSB9KSxcbiAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZUZyZXNoU2FuZGJveCgpOiBQcm9taXNlPFNhbmRib3hFcnJvciB8IHN0cmluZz4ge1xuICAgIHJldHVybiBhd2FpdCBlcnJvcmUudHJ5QXN5bmMoe1xuICAgICAgdHJ5OiBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHNhbmRib3ggPSBhd2FpdCBWZXJjZWxTYW5kYm94U0RLLmNyZWF0ZSh7XG4gICAgICAgICAgcmVzb3VyY2VzOiB7IHZjcHVzIH0sXG4gICAgICAgICAgdGltZW91dDogVkVSQ0VMX01BWF9USU1FT1VUX01TLFxuICAgICAgICAgIHBvcnRzLFxuICAgICAgICAgIG5ldHdvcmtQb2xpY3ksXG4gICAgICAgICAgLi4uZ2V0VGVzdENyZWRlbnRpYWxzKCksXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgICBhd2FpdCBzdG9yYWdlLnNhbmRib3guc2V0KHtcbiAgICAgICAgICBpZCxcbiAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgdGFnczogc2FuZGJveFJlY29yZC50YWdzLFxuICAgICAgICAgIGNyZWF0ZWRBdDogbm93LFxuICAgICAgICAgIGxhc3RBY3Rpdml0eUF0OiBub3csXG4gICAgICAgICAgYWNxdWlyaW5nTG9ja0lkOiBudWxsLFxuICAgICAgICAgIGFjcXVpcmluZ0xvY2tBdDogbnVsbCxcbiAgICAgICAgICBzZXR1cEtleTogc2FuZGJveFJlY29yZC5zZXR1cEtleSxcbiAgICAgICAgICBwcm92aWRlck1ldGFkYXRhOiB7XG4gICAgICAgICAgICBwcm92aWRlcjogXCJ2ZXJjZWxcIixcbiAgICAgICAgICAgIHNhbmRib3hJZDogc2FuZGJveC5zYW5kYm94SWQsXG4gICAgICAgICAgICBzbmFwc2hvdElkOiBudWxsLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgICBhd2FpdCBzdGFydExpZmVjeWNsZVdvcmtmbG93KHNhbmRib3guc2FuZGJveElkKTtcbiAgICAgICAgcmV0dXJuIHNhbmRib3guc2FuZGJveElkO1xuICAgICAgfSxcbiAgICAgIGNhdGNoOiAoZSkgPT4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogU3RyaW5nKGUpLCBjYXVzZTogZSB9KSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb3JlIGV4ZWMgbG9naWMgYWdhaW5zdCBhIHJhdyBWZXJjZWwgU0RLIGluc3RhbmNlLlxuICAgKiBTaGFyZWQgYmV0d2VlbiB0aGUgbWFpbiBzYW5kYm94IHdyYXBwZXIgYW5kIHRlbXBvcmFyeSBzZXR1cCBzYW5kYm94ZXMuXG4gICAqL1xuICBmdW5jdGlvbiBleGVjT25JbnN0YW5jZShcbiAgICBpbnN0YW5jZTogU2FuZGJveEluc3RhbmNlLFxuICAgIHtcbiAgICAgIGNvbW1hbmQsXG4gICAgICBhcmdzLFxuICAgICAgY3dkOiBleGVjQ3dkLFxuICAgICAgZW52LFxuICAgICAgc2lnbmFsLFxuICAgICAgc3VkbyxcbiAgICB9OiB7XG4gICAgICBjb21tYW5kOiBzdHJpbmc7XG4gICAgICBhcmdzPzogc3RyaW5nW107XG4gICAgICBjd2Q/OiBzdHJpbmc7XG4gICAgICBlbnY/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICAgICAgc2lnbmFsPzogQWJvcnRTaWduYWw7XG4gICAgICBzdWRvPzogYm9vbGVhbjtcbiAgICB9XG4gICk6IFByb21pc2U8XG4gICAgfCBTYW5kYm94RXJyb3JcbiAgICB8IHtcbiAgICAgICAgY29tbWFuZElkOiBzdHJpbmc7XG4gICAgICAgIGxvZ3M6ICgpID0+IEFzeW5jSXRlcmFibGU8TG9nRW50cnk+O1xuICAgICAgICByZXN1bHQ6IFByb21pc2U8eyBzdGRvdXQ6IHN0cmluZzsgc3RkZXJyOiBzdHJpbmc7IGV4aXRDb2RlOiBudW1iZXIgfT47XG4gICAgICB9XG4gID4ge1xuICAgIHJldHVybiBlcnJvcmUudHJ5QXN5bmMoe1xuICAgICAgdHJ5OiBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGZpbmFsQ21kID0gc3VkbyA/IFwic3Vkb1wiIDogY29tbWFuZDtcbiAgICAgICAgY29uc3QgZmluYWxBcmdzID0gc3VkbyA/IFtjb21tYW5kLCAuLi4oYXJncyA/PyBbXSldIDogYXJncztcbiAgICAgICAgY29uc3Qgb3V0cHV0ID0gYXdhaXQgaW5zdGFuY2UucnVuQ29tbWFuZCh7XG4gICAgICAgICAgY3dkOiBleGVjQ3dkID8/IGN3ZCxcbiAgICAgICAgICBhcmdzOiBmaW5hbEFyZ3MsXG4gICAgICAgICAgZW52LFxuICAgICAgICAgIGNtZDogZmluYWxDbWQsXG4gICAgICAgICAgc2lnbmFsLFxuICAgICAgICAgIGRldGFjaGVkOiB0cnVlLFxuICAgICAgICB9KTtcblxuICAgICAgICBsZXQgc3Rkb3V0ID0gXCJcIjtcbiAgICAgICAgbGV0IHN0ZGVyciA9IFwiXCI7XG4gICAgICAgIGNvbnN0IGxvZ0J1ZmZlcjogTG9nRW50cnlbXSA9IFtdO1xuICAgICAgICBjb25zdCBzdGF0ZSA9IHtcbiAgICAgICAgICByZXNvbHZlOiBudWxsIGFzICgoKSA9PiB2b2lkKSB8IG51bGwsXG4gICAgICAgICAgY29uc3VtZWQ6IGZhbHNlLFxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IGNvbnN1bWVMb2dzID0gKGFzeW5jICgpID0+IHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgZm9yIGF3YWl0IChjb25zdCBsb2cgb2Ygb3V0cHV0LmxvZ3MoKSkge1xuICAgICAgICAgICAgICBjb25zdCBlbnRyeTogTG9nRW50cnkgPVxuICAgICAgICAgICAgICAgIGxvZy5zdHJlYW0gPT09IFwic3Rkb3V0XCJcbiAgICAgICAgICAgICAgICAgID8geyBzdHJlYW06IFwic3Rkb3V0XCIsIGRhdGE6IGxvZy5kYXRhIH1cbiAgICAgICAgICAgICAgICAgIDogeyBzdHJlYW06IFwic3RkZXJyXCIsIGRhdGE6IGxvZy5kYXRhIH07XG5cbiAgICAgICAgICAgICAgaWYgKGxvZy5zdHJlYW0gPT09IFwic3Rkb3V0XCIpIHtcbiAgICAgICAgICAgICAgICBzdGRvdXQgKz0gbG9nLmRhdGE7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc3RkZXJyICs9IGxvZy5kYXRhO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgbG9nQnVmZmVyLnB1c2goZW50cnkpO1xuICAgICAgICAgICAgICBzdGF0ZS5yZXNvbHZlPy4oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIC8vIFNhbmRib3ggbWF5IGhhdmUgYmVlbiBzdG9wcGVkIC0gbG9ncyBlbmRwb2ludCByZXR1cm5zIDQyMlxuICAgICAgICAgIH1cbiAgICAgICAgICBzdGF0ZS5jb25zdW1lZCA9IHRydWU7XG4gICAgICAgICAgc3RhdGUucmVzb2x2ZT8uKCk7XG4gICAgICAgIH0pKCk7XG5cbiAgICAgICAgYXN5bmMgZnVuY3Rpb24qIGxvZ3MoKTogQXN5bmNJdGVyYWJsZTxMb2dFbnRyeT4ge1xuICAgICAgICAgIGxldCBpbmRleCA9IDA7XG4gICAgICAgICAgd2hpbGUgKCFzdGF0ZS5jb25zdW1lZCB8fCBpbmRleCA8IGxvZ0J1ZmZlci5sZW5ndGgpIHtcbiAgICAgICAgICAgIGlmIChpbmRleCA8IGxvZ0J1ZmZlci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgeWllbGQgbG9nQnVmZmVyW2luZGV4KytdO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgYXdhaXQgbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUpID0+IHtcbiAgICAgICAgICAgICAgICBzdGF0ZS5yZXNvbHZlID0gcmVzb2x2ZTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIHN0YXRlLnJlc29sdmUgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGNvbnN1bWVMb2dzLnRoZW4oYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBmaW5pc2hlZCA9IGF3YWl0IG91dHB1dC53YWl0KCk7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBzdGRvdXQsXG4gICAgICAgICAgICAgIHN0ZGVycixcbiAgICAgICAgICAgICAgZXhpdENvZGU6IGZpbmlzaGVkLmV4aXRDb2RlLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBpZiAoaXNTYW5kYm94R29uZUVycm9yKGUpKSB7XG4gICAgICAgICAgICAgIHJldHVybiB7IHN0ZG91dCwgc3RkZXJyLCBleGl0Q29kZTogMSB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiB7IGNvbW1hbmRJZDogb3V0cHV0LmNtZElkLCBsb2dzLCByZXN1bHQgfTtcbiAgICAgIH0sXG4gICAgICBjYXRjaDogKGUpID0+IG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSksXG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiByZWFkRmlsZU9uSW5zdGFuY2UoXG4gICAgaW5zdGFuY2U6IFNhbmRib3hJbnN0YW5jZSxcbiAgICB7IHBhdGggfTogeyBwYXRoOiBzdHJpbmcgfVxuICApOiBQcm9taXNlPFNhbmRib3hFcnJvciB8IEJ1ZmZlciB8IG51bGw+IHtcbiAgICByZXR1cm4gZXJyb3JlLnRyeUFzeW5jKHtcbiAgICAgIHRyeTogKCkgPT4gaW5zdGFuY2UucmVhZEZpbGVUb0J1ZmZlcih7IHBhdGgsIGN3ZCB9KSxcbiAgICAgIGNhdGNoOiAoZSkgPT4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogU3RyaW5nKGUpLCBjYXVzZTogZSB9KSxcbiAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIHdyaXRlRmlsZXNPbkluc3RhbmNlKFxuICAgIGluc3RhbmNlOiBTYW5kYm94SW5zdGFuY2UsXG4gICAgb3B0czoge1xuICAgICAgZmlsZXM6IHsgcGF0aDogc3RyaW5nOyBjb250ZW50OiBzdHJpbmcgfCBCdWZmZXIgfVtdO1xuICAgICAgZGVzdFBhdGg6IHN0cmluZztcbiAgICB9XG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHsgZmlsZXMsIGRlc3RQYXRoIH0gPSBvcHRzO1xuICAgIGlmIChmaWxlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBuYXRpdmVGaWxlcyA9IGZpbGVzLm1hcCgoZmlsZSkgPT4ge1xuICAgICAgY29uc3QgZmlsZVBhdGggPSBwYXRoLnBvc2l4LmpvaW4oZGVzdFBhdGgsIGZpbGUucGF0aCk7XG4gICAgICBjb25zdCBhYnNvbHV0ZVBhdGggPSBwYXRoLnBvc2l4LmlzQWJzb2x1dGUoZmlsZVBhdGgpXG4gICAgICAgID8gZmlsZVBhdGhcbiAgICAgICAgOiBwYXRoLnBvc2l4LmpvaW4oY3dkLCBmaWxlUGF0aCk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBwYXRoOiBhYnNvbHV0ZVBhdGgsXG4gICAgICAgIGNvbnRlbnQ6XG4gICAgICAgICAgdHlwZW9mIGZpbGUuY29udGVudCA9PT0gXCJzdHJpbmdcIlxuICAgICAgICAgICAgPyBCdWZmZXIuZnJvbShmaWxlLmNvbnRlbnQpXG4gICAgICAgICAgICA6IGZpbGUuY29udGVudCxcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICBhd2FpdCBpbnN0YW5jZS53cml0ZUZpbGVzKG5hdGl2ZUZpbGVzKTtcblxuICAgIGNvbnN0IHNoZWxsU2NyaXB0cyA9IG5hdGl2ZUZpbGVzLmZpbHRlcigoZikgPT4gZi5wYXRoLmVuZHNXaXRoKFwiLnNoXCIpKTtcbiAgICBpZiAoc2hlbGxTY3JpcHRzLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IGNobW9kUmVzdWx0ID0gYXdhaXQgZXhlY09uSW5zdGFuY2UoaW5zdGFuY2UsIHtcbiAgICAgICAgY29tbWFuZDogXCJjaG1vZFwiLFxuICAgICAgICBhcmdzOiBbXCIreFwiLCAuLi5zaGVsbFNjcmlwdHMubWFwKChmKSA9PiBmLnBhdGgpXSxcbiAgICAgIH0pO1xuICAgICAgaWYgKGNobW9kUmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgY2htb2RSZXN1bHQ7XG4gICAgICB9XG4gICAgICBhd2FpdCBjaG1vZFJlc3VsdC5yZXN1bHQ7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBtaW5pbWFsIFNhbmRib3ggd3JhcHBlciBhcm91bmQgYSByYXcgVmVyY2VsIFNESyBpbnN0YW5jZS5cbiAgICogVXNlZCBmb3IgcnVubmluZyBzZXR1cC5ydW4oKSBvbiBhIHRlbXBvcmFyeSBzYW5kYm94IGZvciBzbmFwc2hvdCBjcmVhdGlvbi5cbiAgICovXG4gIGZ1bmN0aW9uIGNyZWF0ZVRlbXBTYW5kYm94KGluc3RhbmNlOiBTYW5kYm94SW5zdGFuY2UpOiBTYW5kYm94IHtcbiAgICBjb25zdCBub3RBdmFpbGFibGUgPSAoKSA9PlxuICAgICAgUHJvbWlzZS5yZXNvbHZlKFxuICAgICAgICBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBcIm5vdCBhdmFpbGFibGUgZHVyaW5nIHNldHVwXCIgfSlcbiAgICAgICk7XG4gICAgY29uc3QgdGVtcFNhbmRib3g6IFNhbmRib3ggPSB7XG4gICAgICBpZDogYF9fc2V0dXBfdGVtcF8ke0RhdGUubm93KCl9YCxcbiAgICAgIGNvbmZpZyxcbiAgICAgIGN3ZCxcbiAgICAgIGV4ZWM6IChvcHRzKSA9PiBleGVjT25JbnN0YW5jZShpbnN0YW5jZSwgb3B0cyksXG4gICAgICByZWFkRmlsZTogKG9wdHMpID0+IHJlYWRGaWxlT25JbnN0YW5jZShpbnN0YW5jZSwgb3B0cyksXG4gICAgICBnZXREb21haW46ICgpID0+IG5vdEF2YWlsYWJsZSgpLFxuICAgICAga2lsbDogKCkgPT4gbm90QXZhaWxhYmxlKCksXG4gICAgICB3cml0ZUZpbGVzOiAob3B0cykgPT4gd3JpdGVGaWxlc09uSW5zdGFuY2UoaW5zdGFuY2UsIG9wdHMpLFxuICAgICAgdXBkYXRlTmV0d29ya1BvbGljeTogKHBvbGljeSkgPT5cbiAgICAgICAgZXJyb3JlLnRyeUFzeW5jKHtcbiAgICAgICAgICB0cnk6ICgpID0+IGluc3RhbmNlLnVwZGF0ZU5ldHdvcmtQb2xpY3kocG9saWN5KSxcbiAgICAgICAgICBjYXRjaDogKGUpID0+IG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSksXG4gICAgICAgIH0pLFxuICAgICAgbGlmZWN5Y2xlOiB7XG4gICAgICAgIHN0YXJ0OiAoKSA9PiBub3RBdmFpbGFibGUoKSxcbiAgICAgICAgc25hcHNob3Q6ICgpID0+IG5vdEF2YWlsYWJsZSgpLFxuICAgICAgICBzdG9wOiAoKSA9PiBub3RBdmFpbGFibGUoKSxcbiAgICAgICAgZ2V0U3RhdHVzOiAoKSA9PiBub3RBdmFpbGFibGUoKSxcbiAgICAgICAgZ2V0Q3JlYXRlZEF0OiAoKSA9PiBub3RBdmFpbGFibGUoKSxcbiAgICAgICAgZ2V0UmVtYWluaW5nVGltZW91dDogKCkgPT4gbm90QXZhaWxhYmxlKCksXG4gICAgICB9LFxuICAgICAgdGFnOiB7XG4gICAgICAgIGxpc3Q6IGFzeW5jICgpID0+ICh7fSkgYXMgVFRhZ3MsXG4gICAgICAgIGdldDogYXN5bmMgKCkgPT4gdW5kZWZpbmVkLFxuICAgICAgICBzZXQ6IGFzeW5jICgpID0+IHVuZGVmaW5lZCxcbiAgICAgICAgc2V0TWFueTogYXN5bmMgKCkgPT4gdW5kZWZpbmVkLFxuICAgICAgfSxcbiAgICB9O1xuICAgIHJldHVybiB0ZW1wU2FuZGJveDtcbiAgfVxuXG4gIC8qKlxuICAgKiBQb2xscyBmb3IgYSBzZXR1cCBzbmFwc2hvdCB0byBiZWNvbWUgYXZhaWxhYmxlLiBSZXR1cm5zIHRoZSBzbmFwc2hvdElkXG4gICAqIGlmIG9uZSBhcHBlYXJzIGJlZm9yZSB0aGUgbG9jayB0aW1lcyBvdXQsIG9yIG51bGwgaWYgaXQgZG9lc24ndC5cbiAgICovXG4gIGFzeW5jIGZ1bmN0aW9uIHBvbGxGb3JTZXR1cFNuYXBzaG90KGtleTogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPiB7XG4gICAgY29uc3QgZG9uZSA9IHNldHVwTG9nLnRpbWUoXG4gICAgICBcIndhaXRpbmcgZm9yIHNldHVwIHNuYXBzaG90XCIsXG4gICAgICB7IHNldHVwS2V5OiBrZXkgfSxcbiAgICAgIHsgbG9nT25TdGFydDogdHJ1ZSB9XG4gICAgKTtcbiAgICBjb25zdCBkZWFkbGluZSA9IERhdGUubm93KCkgKyBMT0NLX1RJTUVPVVRfTVM7XG4gICAgd2hpbGUgKERhdGUubm93KCkgPCBkZWFkbGluZSkge1xuICAgICAgYXdhaXQgbmV3IFByb21pc2UoKHIpID0+IHNldFRpbWVvdXQociwgTE9DS19QT0xMX0lOVEVSVkFMX01TKSk7XG4gICAgICBjb25zdCByZWNvcmQgPSBhd2FpdCBwb2xsU3RvcmFnZS5zZXR1cC5nZXQoa2V5KTtcbiAgICAgIGlmIChyZWNvcmQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIGlmIChyZWNvcmQ/LnNuYXBzaG90SWQpIHtcbiAgICAgICAgZG9uZSgpO1xuICAgICAgICByZXR1cm4gcmVjb3JkLnNuYXBzaG90SWQ7XG4gICAgICB9XG4gICAgICBjb25zdCBsb2NrU3RhbGUgPVxuICAgICAgICByZWNvcmQ/LmFjcXVpcmluZ0xvY2tBdCAmJlxuICAgICAgICBEYXRlLm5vdygpIC0gcmVjb3JkLmFjcXVpcmluZ0xvY2tBdCA+PSBMT0NLX1RJTUVPVVRfTVM7XG4gICAgICBpZiAoIXJlY29yZD8uYWNxdWlyaW5nTG9ja0lkIHx8IGxvY2tTdGFsZSkge1xuICAgICAgICBpZiAobG9ja1N0YWxlKSB7XG4gICAgICAgICAgc2V0dXBMb2cud2FybihcInNldHVwIGxvY2sgaXMgc3RhbGUsIGdpdmluZyB1cCBwb2xsXCIsIHtcbiAgICAgICAgICAgIHNldHVwS2V5OiBrZXksXG4gICAgICAgICAgICBsb2NrQWdlOiBEYXRlLm5vdygpIC0gcmVjb3JkIS5hY3F1aXJpbmdMb2NrQXQhLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGRvbmUoeyBzdGFsZUxvY2s6ICEhbG9ja1N0YWxlLCBmb3VuZDogZmFsc2UgfSk7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgIH1cbiAgICBkb25lKHsgdGltZWRPdXQ6IHRydWUgfSk7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIGJhY2tncm91bmQgc2FuZGJveCwgcnVucyBzZXR1cCwgc25hcHNob3RzIGl0LCBhbmQgc3RvcmVzIHRoZVxuICAgKiBzbmFwc2hvdCBJRC4gVXNlcyBhdG9taWMgbG9ja2luZyB0byBlbnN1cmUgb25seSBvbmUgcHJvY2VzcyBjcmVhdGVzIGl0LlxuICAgKlxuICAgKiBAcGFyYW0gZm9yY2UgLSBTa2lwIHRoZSBcInNuYXBzaG90IGFscmVhZHkgZXhpc3RzXCIgZWFybHkgZXhpdC4gVXNlZCB3aGVuXG4gICAqICAgdGhlIGNhbGxlciBrbm93cyB0aGUgZXhpc3Rpbmcgc25hcHNob3QgaXMgc3RhbGUvZXhwaXJlZC5cbiAgICovXG4gIGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVNldHVwU25hcHNob3Qob3B0cz86IHtcbiAgICBmb3JjZT86IGJvb2xlYW47XG4gIH0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIXNldHVwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHNldHVwS2V5ID0gc2V0dXAua2V5O1xuXG4gICAgLy8gQ2hlY2sgaWYgc25hcHNob3QgYWxyZWFkeSBleGlzdHMgKGZhc3QgcGF0aCBcdTIwMTQgYXZvaWRzIGxvY2sgYXR0ZW1wdClcbiAgICBpZiAoIW9wdHM/LmZvcmNlKSB7XG4gICAgICBjb25zdCBleGlzdGluZyA9IGF3YWl0IHN0b3JhZ2Uuc2V0dXAuZ2V0KHNldHVwS2V5KTtcbiAgICAgIGlmICghKGV4aXN0aW5nIGluc3RhbmNlb2YgRXJyb3IpICYmIGV4aXN0aW5nPy5zbmFwc2hvdElkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBBdG9taWNhbGx5IGFjcXVpcmUgbG9jayAoaGFuZGxlcyBhY3RpdmUtbG9jayBkZXRlY3Rpb24gaW50ZXJuYWxseSlcbiAgICBjb25zdCBsb2NrSWQgPSBjcnlwdG8ucmFuZG9tVVVJRCgpO1xuICAgIGNvbnN0IGxvY2tlZCA9IGF3YWl0IHN0b3JhZ2Uuc2V0dXAuYWNxdWlyZUxvY2soXG4gICAgICBzZXR1cEtleSxcbiAgICAgIGxvY2tJZCxcbiAgICAgIExPQ0tfVElNRU9VVF9NU1xuICAgICk7XG4gICAgaWYgKGxvY2tlZCBpbnN0YW5jZW9mIEVycm9yIHx8ICFsb2NrZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBSZS1jaGVjazogYW5vdGhlciB3b3JrZXIgbWF5IGhhdmUgY3JlYXRlZCB0aGUgc25hcHNob3QgYmV0d2VlbiBvdXJcbiAgICAvLyBwcmUtY2hlY2sgYW5kIGxvY2sgYWNxdWlzaXRpb24uIElmIHNvLCBza2lwIHVubGVzcyBmb3JjZSAoc3RhbGUgc25hcHNob3QpLlxuICAgIGlmICghb3B0cz8uZm9yY2UgJiYgbG9ja2VkLnNuYXBzaG90SWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsZXQgdGVtcEluc3RhbmNlOiBBd2FpdGVkPFxuICAgICAgUmV0dXJuVHlwZTx0eXBlb2YgVmVyY2VsU2FuZGJveFNESy5jcmVhdGU+XG4gICAgPiB8IG51bGwgPSBudWxsO1xuICAgIHRyeSB7XG4gICAgICAvLyBDcmVhdGUgYSB0ZW1wb3Jhcnkgc2FuZGJveCBmb3Igc25hcHNob3R0aW5nLlxuICAgICAgdGVtcEluc3RhbmNlID0gYXdhaXQgVmVyY2VsU2FuZGJveFNESy5jcmVhdGUoe1xuICAgICAgICByZXNvdXJjZXM6IHsgdmNwdXMgfSxcbiAgICAgICAgdGltZW91dDogVkVSQ0VMX01BWF9USU1FT1VUX01TLFxuICAgICAgICBwb3J0cyxcbiAgICAgICAgbmV0d29ya1BvbGljeSxcbiAgICAgICAgLi4uZ2V0VGVzdENyZWRlbnRpYWxzKCksXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdGVtcFNhbmRib3ggPSBjcmVhdGVUZW1wU2FuZGJveChcbiAgICAgICAgdGVtcEluc3RhbmNlIGFzIHVua25vd24gYXMgU2FuZGJveEluc3RhbmNlXG4gICAgICApO1xuICAgICAgYXdhaXQgc2V0dXAucnVuKHRlbXBTYW5kYm94KTtcbiAgICAgIGNvbnN0IHNuYXBzaG90ID0gYXdhaXQgdGVtcEluc3RhbmNlLnNuYXBzaG90KCk7XG5cbiAgICAgIGF3YWl0IHN0b3JhZ2Uuc2V0dXAuc2V0KHtcbiAgICAgICAga2V5OiBzZXR1cEtleSxcbiAgICAgICAgc25hcHNob3RJZDogc25hcHNob3Quc25hcHNob3RJZCxcbiAgICAgICAgY3JlYXRlZEF0OiBsb2NrZWQuY3JlYXRlZEF0LFxuICAgICAgICBsYXN0VXNlZEF0OiBudWxsLFxuICAgICAgICBhY3F1aXJpbmdMb2NrSWQ6IG51bGwsXG4gICAgICAgIGFjcXVpcmluZ0xvY2tBdDogbnVsbCxcbiAgICAgIH0pO1xuXG4gICAgICAvLyBTdG9wIHRoZSB0ZW1wIHNhbmRib3ggXHUyMDE0IG5vIGxvbmdlciBuZWVkZWQgYWZ0ZXIgc25hcHNob3R0aW5nXG4gICAgICBhd2FpdCB0ZW1wSW5zdGFuY2Uuc3RvcCgpLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgc2V0dXBMb2cuZXJyb3IoXCJmYWlsZWQgdG8gY3JlYXRlIHNldHVwIHNuYXBzaG90XCIsIHsgc2V0dXBLZXksIGNhdXNlOiBlIH0pO1xuICAgICAgLy8gU3RvcCB0aGUgdGVtcCBzYW5kYm94IG9uIGZhaWx1cmVcbiAgICAgIGlmICh0ZW1wSW5zdGFuY2UpIHtcbiAgICAgICAgYXdhaXQgdGVtcEluc3RhbmNlLnN0b3AoKS5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuICAgICAgfVxuICAgICAgLy8gQ2xlYW4gdXAgbG9jayBvbiBmYWlsdXJlXG4gICAgICBhd2FpdCBzdG9yYWdlLnNldHVwXG4gICAgICAgIC5zZXQoe1xuICAgICAgICAgIGtleTogc2V0dXBLZXksXG4gICAgICAgICAgc25hcHNob3RJZDogbnVsbCxcbiAgICAgICAgICBjcmVhdGVkQXQ6IGxvY2tlZC5jcmVhdGVkQXQsXG4gICAgICAgICAgbGFzdFVzZWRBdDogbnVsbCxcbiAgICAgICAgICBhY3F1aXJpbmdMb2NrSWQ6IG51bGwsXG4gICAgICAgICAgYWNxdWlyaW5nTG9ja0F0OiBudWxsLFxuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBkb0dldE9yQ3JlYXRlU2FuZGJveElkKCk6IFByb21pc2U8XG4gICAgU2FuZGJveEVycm9yIHwgQ3JlYXRlUmVzdWx0XG4gID4ge1xuICAgIGNvbnN0IGRvbmUgPSBzZXR1cExvZy50aW1lKFwiZG9HZXRPckNyZWF0ZVNhbmRib3hJZFwiLCB7IHNhbmRib3hJZDogaWQgfSk7XG5cbiAgICBpZiAoaW5pdGlhbFZlcmNlbD8uc2FuZGJveElkICYmICFyZWNvdmVyZWRGcm9tU3RhbGUpIHtcbiAgICAgIGRvbmUoeyBwYXRoOiBcImNhY2hlLWhpdFwiIH0pO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc2FuZGJveElkOiBpbml0aWFsVmVyY2VsLnNhbmRib3hJZCxcbiAgICAgICAgbmVlZHNTZXR1cFJ1bjogZmFsc2UsXG4gICAgICAgIGNyZWF0ZWRGcm9tU25hcHNob3Q6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICBjb25zdCBleGlzdGluZyA9IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5nZXQoaWQpO1xuICAgIGlmIChleGlzdGluZyBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICBpZiAoZXhpc3RpbmcgaW5zdGFuY2VvZiBTYW5kYm94Tm90Rm91bmRFcnJvcikge1xuICAgICAgICAvLyBTYW5kYm94IGRvZXNuJ3QgZXhpc3QgeWV0LCBjb250aW51ZSB3aXRoIGNyZWF0aW9uXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogZXhpc3RpbmcubWVzc2FnZSwgY2F1c2U6IGV4aXN0aW5nIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGV4aXN0aW5nUmVjb3JkID1cbiAgICAgIGV4aXN0aW5nIGluc3RhbmNlb2YgU2FuZGJveE5vdEZvdW5kRXJyb3IgPyBudWxsIDogZXhpc3Rpbmc7XG4gICAgY29uc3QgZXhpc3RpbmdWZXJjZWwgPVxuICAgICAgZXhpc3RpbmdSZWNvcmQ/LnByb3ZpZGVyTWV0YWRhdGE/LnByb3ZpZGVyID09PSBcInZlcmNlbFwiXG4gICAgICAgID8gZXhpc3RpbmdSZWNvcmQucHJvdmlkZXJNZXRhZGF0YVxuICAgICAgICA6IG51bGw7XG5cbiAgICBpZiAoZXhpc3RpbmdWZXJjZWw/LnNhbmRib3hJZCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc2FuZGJveElkOiBleGlzdGluZ1ZlcmNlbC5zYW5kYm94SWQsXG4gICAgICAgIG5lZWRzU2V0dXBSdW46IGZhbHNlLFxuICAgICAgICBjcmVhdGVkRnJvbVNuYXBzaG90OiBmYWxzZSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgY29uc3QgaGFzQWN0aXZlTG9jayA9XG4gICAgICBleGlzdGluZ1JlY29yZD8uYWNxdWlyaW5nTG9ja0lkICYmXG4gICAgICBleGlzdGluZ1JlY29yZC5hY3F1aXJpbmdMb2NrQXQgJiZcbiAgICAgIERhdGUubm93KCkgLSBleGlzdGluZ1JlY29yZC5hY3F1aXJpbmdMb2NrQXQgPCBMT0NLX1RJTUVPVVRfTVM7XG5cbiAgICBpZiAoaGFzQWN0aXZlTG9jaykge1xuICAgICAgcmV0dXJuIHBvbGxGb3JTYW5kYm94SWQoKTtcbiAgICB9XG5cbiAgICBjb25zdCBsb2NrSWQgPSBjcnlwdG8ucmFuZG9tVVVJRCgpO1xuICAgIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gICAgY29uc3QgbG9ja2VkID0gYXdhaXQgc3RvcmFnZS5zYW5kYm94LmFjcXVpcmVMb2NrKFxuICAgICAge1xuICAgICAgICBpZCxcbiAgICAgICAgY29uZmlnLFxuICAgICAgICB0YWdzOiBleGlzdGluZ1JlY29yZD8udGFncyA/PyBzYW5kYm94UmVjb3JkLnRhZ3MsXG4gICAgICAgIGNyZWF0ZWRBdDogZXhpc3RpbmdSZWNvcmQ/LmNyZWF0ZWRBdCA/PyBzYW5kYm94UmVjb3JkLmNyZWF0ZWRBdCxcbiAgICAgICAgbGFzdEFjdGl2aXR5QXQ6XG4gICAgICAgICAgZXhpc3RpbmdSZWNvcmQ/Lmxhc3RBY3Rpdml0eUF0ID8/IHNhbmRib3hSZWNvcmQubGFzdEFjdGl2aXR5QXQsXG4gICAgICAgIGFjcXVpcmluZ0xvY2tJZDogbG9ja0lkLFxuICAgICAgICBhY3F1aXJpbmdMb2NrQXQ6IG5vdyxcbiAgICAgICAgc2V0dXBLZXk6IHNhbmRib3hSZWNvcmQuc2V0dXBLZXksXG4gICAgICAgIHByb3ZpZGVyTWV0YWRhdGE6IHtcbiAgICAgICAgICBwcm92aWRlcjogXCJ2ZXJjZWxcIixcbiAgICAgICAgICBzYW5kYm94SWQ6IG51bGwsXG4gICAgICAgICAgc25hcHNob3RJZDpcbiAgICAgICAgICAgIGV4aXN0aW5nVmVyY2VsPy5zbmFwc2hvdElkID8/IGluaXRpYWxWZXJjZWw/LnNuYXBzaG90SWQgPz8gbnVsbCxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBMT0NLX1RJTUVPVVRfTVNcbiAgICApO1xuXG4gICAgaWYgKGxvY2tlZCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICByZXR1cm4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogbG9ja2VkLm1lc3NhZ2UsIGNhdXNlOiBsb2NrZWQgfSk7XG4gICAgfVxuICAgIGlmICghbG9ja2VkKSB7XG4gICAgICByZXR1cm4gcG9sbEZvclNhbmRib3hJZCgpO1xuICAgIH1cblxuICAgIGNvbnN0IGxvY2tlZFJlY29yZCA9IGxvY2tlZDtcblxuICAgIGFzeW5jIGZ1bmN0aW9uIHJlbGVhc2VTYW5kYm94TG9jaygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgIGF3YWl0IHN0b3JhZ2Uuc2FuZGJveFxuICAgICAgICAudXBkYXRlKHtcbiAgICAgICAgICBpZDogbG9ja2VkUmVjb3JkLmlkLFxuICAgICAgICAgIGFjcXVpcmluZ0xvY2tJZDogbnVsbCxcbiAgICAgICAgICBhY3F1aXJpbmdMb2NrQXQ6IG51bGwsXG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuICAgIH1cblxuICAgIGNvbnN0IGxvY2tlZFZlcmNlbCA9XG4gICAgICBsb2NrZWRSZWNvcmQucHJvdmlkZXJNZXRhZGF0YT8ucHJvdmlkZXIgPT09IFwidmVyY2VsXCJcbiAgICAgICAgPyBsb2NrZWRSZWNvcmQucHJvdmlkZXJNZXRhZGF0YVxuICAgICAgICA6IG51bGw7XG4gICAgaWYgKGxvY2tlZFZlcmNlbD8uc2FuZGJveElkKSB7XG4gICAgICBhd2FpdCByZWxlYXNlU2FuZGJveExvY2soKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHNhbmRib3hJZDogbG9ja2VkVmVyY2VsLnNhbmRib3hJZCxcbiAgICAgICAgbmVlZHNTZXR1cFJ1bjogZmFsc2UsXG4gICAgICAgIGNyZWF0ZWRGcm9tU25hcHNob3Q6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICBjb25zdCBzbmFwc2hvdElkID1cbiAgICAgIGxvY2tlZFZlcmNlbD8uc25hcHNob3RJZCA/P1xuICAgICAgaW5pdGlhbFZlcmNlbD8uc25hcHNob3RJZCA/P1xuICAgICAgY29uZmlnLmxpZmVjeWNsZT8uc25hcHNob3RJZDtcbiAgICBpZiAoc25hcHNob3RJZCkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY3JlYXRlU2FuZGJveEZyb21TbmFwc2hvdChzbmFwc2hvdElkKTtcbiAgICAgIGlmICghKHJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSkge1xuICAgICAgICBkb25lKHsgcGF0aDogXCJjb25maWctc25hcHNob3RcIiB9KTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBzYW5kYm94SWQ6IHJlc3VsdCxcbiAgICAgICAgICBuZWVkc1NldHVwUnVuOiBmYWxzZSxcbiAgICAgICAgICBjcmVhdGVkRnJvbVNuYXBzaG90OiB0cnVlLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChzZXR1cCkge1xuICAgICAgbGV0IGZvcmNlUmVjcmVhdGVTbmFwc2hvdCA9IGZhbHNlO1xuICAgICAgY29uc3Qgc2V0dXBSZWNvcmQgPSBhd2FpdCBzdG9yYWdlLnNldHVwLmdldChzZXR1cC5rZXkpO1xuICAgICAgaWYgKCEoc2V0dXBSZWNvcmQgaW5zdGFuY2VvZiBFcnJvcikgJiYgc2V0dXBSZWNvcmQpIHtcbiAgICAgICAgaWYgKHNldHVwUmVjb3JkLnNuYXBzaG90SWQpIHtcbiAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjcmVhdGVTYW5kYm94RnJvbVNuYXBzaG90KFxuICAgICAgICAgICAgc2V0dXBSZWNvcmQuc25hcHNob3RJZFxuICAgICAgICAgICk7XG4gICAgICAgICAgaWYgKCEocmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpKSB7XG4gICAgICAgICAgICBzdG9yYWdlLnNldHVwXG4gICAgICAgICAgICAgIC5zZXQoe1xuICAgICAgICAgICAgICAgIC4uLnNldHVwUmVjb3JkLFxuICAgICAgICAgICAgICAgIGxhc3RVc2VkQXQ6IERhdGUubm93KCksXG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgIC5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuICAgICAgICAgICAgZG9uZSh7IHBhdGg6IFwic2V0dXAtc25hcHNob3RcIiB9KTtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIHNhbmRib3hJZDogcmVzdWx0LFxuICAgICAgICAgICAgICBuZWVkc1NldHVwUnVuOiBmYWxzZSxcbiAgICAgICAgICAgICAgY3JlYXRlZEZyb21TbmFwc2hvdDogdHJ1ZSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICAgIGZvcmNlUmVjcmVhdGVTbmFwc2hvdCA9IHRydWU7XG4gICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgc2V0dXBSZWNvcmQuYWNxdWlyaW5nTG9ja0lkICYmXG4gICAgICAgICAgc2V0dXBSZWNvcmQuYWNxdWlyaW5nTG9ja0F0ICYmXG4gICAgICAgICAgRGF0ZS5ub3coKSAtIHNldHVwUmVjb3JkLmFjcXVpcmluZ0xvY2tBdCA8IExPQ0tfVElNRU9VVF9NU1xuICAgICAgICApIHtcbiAgICAgICAgICBjb25zdCBwb2xsZWRTbmFwc2hvdElkID0gYXdhaXQgcG9sbEZvclNldHVwU25hcHNob3Qoc2V0dXAua2V5KTtcbiAgICAgICAgICBpZiAocG9sbGVkU25hcHNob3RJZCkge1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY3JlYXRlU2FuZGJveEZyb21TbmFwc2hvdChwb2xsZWRTbmFwc2hvdElkKTtcbiAgICAgICAgICAgIGlmICghKHJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSkge1xuICAgICAgICAgICAgICBkb25lKHsgcGF0aDogXCJwb2xsZWQtc25hcHNob3RcIiB9KTtcbiAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBzYW5kYm94SWQ6IHJlc3VsdCxcbiAgICAgICAgICAgICAgICBuZWVkc1NldHVwUnVuOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBjcmVhdGVkRnJvbVNuYXBzaG90OiB0cnVlLFxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjcmVhdGVTZXR1cFNuYXBzaG90KHsgZm9yY2U6IGZvcmNlUmVjcmVhdGVTbmFwc2hvdCB9KS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICBzZXR1cExvZy5lcnJvcihcImZhaWxlZCB0byBjcmVhdGUgYmFja2dyb3VuZCBzbmFwc2hvdFwiLCB7IGNhdXNlOiBlIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IGZyZXNoUmVzdWx0ID0gYXdhaXQgY3JlYXRlRnJlc2hTYW5kYm94KCk7XG4gICAgICBpZiAoZnJlc2hSZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICBhd2FpdCByZWxlYXNlU2FuZGJveExvY2soKTtcbiAgICAgICAgcmV0dXJuIGZyZXNoUmVzdWx0O1xuICAgICAgfVxuICAgICAgZG9uZSh7IHBhdGg6IFwiZnJlc2gtd2l0aC1zZXR1cFwiIH0pO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc2FuZGJveElkOiBmcmVzaFJlc3VsdCxcbiAgICAgICAgbmVlZHNTZXR1cFJ1bjogdHJ1ZSxcbiAgICAgICAgY3JlYXRlZEZyb21TbmFwc2hvdDogZmFsc2UsXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IGZyZXNoUmVzdWx0ID0gYXdhaXQgY3JlYXRlRnJlc2hTYW5kYm94KCk7XG4gICAgaWYgKGZyZXNoUmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIGF3YWl0IHJlbGVhc2VTYW5kYm94TG9jaygpO1xuICAgICAgcmV0dXJuIGZyZXNoUmVzdWx0O1xuICAgIH1cbiAgICBkb25lKHsgcGF0aDogXCJmcmVzaFwiIH0pO1xuICAgIHJldHVybiB7XG4gICAgICBzYW5kYm94SWQ6IGZyZXNoUmVzdWx0LFxuICAgICAgbmVlZHNTZXR1cFJ1bjogZmFsc2UsXG4gICAgICBjcmVhdGVkRnJvbVNuYXBzaG90OiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0T3JDcmVhdGVTYW5kYm94SWQoKTogUHJvbWlzZTxTYW5kYm94RXJyb3IgfCBDcmVhdGVSZXN1bHQ+IHtcbiAgICBjb25zdCBjYWNoZWQgPSBjcmVhdGVQcm9taXNlcy5nZXQoaWQpO1xuICAgIGlmIChjYWNoZWQpIHtcbiAgICAgIHJldHVybiBjYWNoZWQ7XG4gICAgfVxuXG4gICAgY29uc3QgcHJvbWlzZSA9IGRvR2V0T3JDcmVhdGVTYW5kYm94SWQoKS5maW5hbGx5KCgpID0+IHtcbiAgICAgIGNyZWF0ZVByb21pc2VzLmRlbGV0ZShpZCk7XG4gICAgfSk7XG4gICAgY3JlYXRlUHJvbWlzZXMuc2V0KGlkLCBwcm9taXNlKTtcbiAgICByZXR1cm4gcHJvbWlzZTtcbiAgfVxuXG4gIHR5cGUgR2V0U2FuZGJveFJlc3VsdCA9IHtcbiAgICBpbnN0YW5jZTogU2FuZGJveEluc3RhbmNlO1xuICAgIG5lZWRzU2V0dXBSdW46IGJvb2xlYW47XG4gICAgY3JlYXRlZEZyb21TbmFwc2hvdDogYm9vbGVhbjtcbiAgfTtcblxuICBhc3luYyBmdW5jdGlvbiBkb0dldFNhbmRib3goKTogUHJvbWlzZTxTYW5kYm94RXJyb3IgfCBHZXRTYW5kYm94UmVzdWx0PiB7XG4gICAgY29uc3QgY3JlYXRlUmVzdWx0ID0gYXdhaXQgZ2V0T3JDcmVhdGVTYW5kYm94SWQoKTtcbiAgICBpZiAoY3JlYXRlUmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIHJldHVybiBjcmVhdGVSZXN1bHQ7XG4gICAgfVxuXG4gICAgY29uc3QgaW5zdGFuY2UgPSBhd2FpdCBlcnJvcmUudHJ5QXN5bmMoe1xuICAgICAgdHJ5OiAoKSA9PlxuICAgICAgICBWZXJjZWxTYW5kYm94U0RLLmdldCh7XG4gICAgICAgICAgc2FuZGJveElkOiBjcmVhdGVSZXN1bHQuc2FuZGJveElkLFxuICAgICAgICAgIC4uLmdldFRlc3RDcmVkZW50aWFscygpLFxuICAgICAgICB9KSxcbiAgICAgIGNhdGNoOiAoZSkgPT4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogU3RyaW5nKGUpLCBjYXVzZTogZSB9KSxcbiAgICB9KTtcblxuICAgIGlmIChpbnN0YW5jZSBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICByZXR1cm4gaW5zdGFuY2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGluc3RhbmNlLFxuICAgICAgbmVlZHNTZXR1cFJ1bjogY3JlYXRlUmVzdWx0Lm5lZWRzU2V0dXBSdW4sXG4gICAgICBjcmVhdGVkRnJvbVNuYXBzaG90OiBjcmVhdGVSZXN1bHQuY3JlYXRlZEZyb21TbmFwc2hvdCxcbiAgICB9O1xuICB9XG5cbiAgbGV0IGdldFNhbmRib3hQcm9taXNlOiBQcm9taXNlPFNhbmRib3hFcnJvciB8IEdldFNhbmRib3hSZXN1bHQ+IHwgbnVsbCA9IG51bGw7XG5cbiAgZnVuY3Rpb24gZ2V0U2FuZGJveFJlc3VsdCgpOiBQcm9taXNlPFNhbmRib3hFcnJvciB8IEdldFNhbmRib3hSZXN1bHQ+IHtcbiAgICBpZiAoIWdldFNhbmRib3hQcm9taXNlKSB7XG4gICAgICBnZXRTYW5kYm94UHJvbWlzZSA9IGRvR2V0U2FuZGJveCgpO1xuICAgIH1cbiAgICByZXR1cm4gZ2V0U2FuZGJveFByb21pc2U7XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBnZXRTYW5kYm94SW5zdGFuY2UoKTogUHJvbWlzZTxTYW5kYm94RXJyb3IgfCBTYW5kYm94SW5zdGFuY2U+IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBnZXRTYW5kYm94UmVzdWx0KCk7XG4gICAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0Lmluc3RhbmNlO1xuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gcmVjb3ZlckZyb21TdGFsZVNhbmRib3goKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgZ2V0U2FuZGJveFByb21pc2UgPSBudWxsO1xuICAgIHJlY292ZXJlZEZyb21TdGFsZSA9IHRydWU7XG5cbiAgICBjb25zdCBleGlzdGluZyA9IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5nZXQoaWQpO1xuICAgIGlmIChleGlzdGluZyBpbnN0YW5jZW9mIEVycm9yIHx8ICFleGlzdGluZykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGV4aXN0aW5nVmVyY2VsID1cbiAgICAgIGV4aXN0aW5nLnByb3ZpZGVyTWV0YWRhdGE/LnByb3ZpZGVyID09PSBcInZlcmNlbFwiXG4gICAgICAgID8gZXhpc3RpbmcucHJvdmlkZXJNZXRhZGF0YVxuICAgICAgICA6IG51bGw7XG5cbiAgICBpZiAoZXhpc3RpbmdWZXJjZWw/LnNhbmRib3hJZCkge1xuICAgICAgYXdhaXQgc3RvcmFnZS5zYW5kYm94LnVwZGF0ZSh7XG4gICAgICAgIGlkOiBleGlzdGluZy5pZCxcbiAgICAgICAgYWNxdWlyaW5nTG9ja0lkOiBudWxsLFxuICAgICAgICBhY3F1aXJpbmdMb2NrQXQ6IG51bGwsXG4gICAgICAgIHByb3ZpZGVyTWV0YWRhdGE6IHtcbiAgICAgICAgICBwcm92aWRlcjogXCJ2ZXJjZWxcIixcbiAgICAgICAgICBzYW5kYm94SWQ6IG51bGwsXG4gICAgICAgICAgc25hcHNob3RJZDogZXhpc3RpbmdWZXJjZWwuc25hcHNob3RJZCxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIHVwZGF0ZUxhc3RBY3Rpdml0eSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgIGNvbnN0IGxhc3RTZW50ID0gbGFzdEFjdGl2aXR5U2VudC5nZXQoaWQpO1xuICAgIGlmIChsYXN0U2VudCAmJiBub3cgLSBsYXN0U2VudCA8IEFDVElWSVRZX1RIUk9UVExFX01TKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGxhc3RBY3Rpdml0eVNlbnQuc2V0KGlkLCBub3cpO1xuXG4gICAgY29uc3QgZXhpc3RpbmcgPSBhd2FpdCBzdG9yYWdlLnNhbmRib3guZ2V0KGlkKTtcbiAgICBpZiAoZXhpc3RpbmcgaW5zdGFuY2VvZiBFcnJvciB8fCAhZXhpc3RpbmcpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgZXhpc3RpbmdWZXJjZWwgPVxuICAgICAgZXhpc3RpbmcucHJvdmlkZXJNZXRhZGF0YT8ucHJvdmlkZXIgPT09IFwidmVyY2VsXCJcbiAgICAgICAgPyBleGlzdGluZy5wcm92aWRlck1ldGFkYXRhXG4gICAgICAgIDogbnVsbDtcbiAgICBhd2FpdCBzdG9yYWdlLnNhbmRib3gudXBkYXRlKHtcbiAgICAgIGlkOiBleGlzdGluZy5pZCxcbiAgICAgIGxhc3RBY3Rpdml0eUF0OiBub3csXG4gICAgICBhY3F1aXJpbmdMb2NrSWQ6IG51bGwsXG4gICAgICBhY3F1aXJpbmdMb2NrQXQ6IG51bGwsXG4gICAgICBwcm92aWRlck1ldGFkYXRhOiBleGlzdGluZ1ZlcmNlbCA/PyB7XG4gICAgICAgIHByb3ZpZGVyOiBcInZlcmNlbFwiLFxuICAgICAgICBzYW5kYm94SWQ6IG51bGwsXG4gICAgICAgIHNuYXBzaG90SWQ6IG51bGwsXG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgbGV0IHN0YXJ0UHJvbWlzZTogUHJvbWlzZTxTYW5kYm94RXJyb3IgfCB1bmRlZmluZWQ+IHwgbnVsbCA9IG51bGw7XG5cbiAgY29uc3QgbGlmZWN5Y2xlOiBTYW5kYm94TGlmZWN5Y2xlID0ge1xuICAgIHN0YXJ0OiAoKSA9PiB7XG4gICAgICBpZiAoc3RhcnRQcm9taXNlKSB7XG4gICAgICAgIHJldHVybiBzdGFydFByb21pc2U7XG4gICAgICB9XG4gICAgICBzdGFydFByb21pc2UgPSAoYXN5bmMgKCkgPT4ge1xuICAgICAgICBpZiAoIXNldHVwICYmIHNhbmRib3hSZWNvcmQuc2V0dXBLZXkpIHtcbiAgICAgICAgICBhd2FpdCBwb2xsRm9yU2V0dXBDb21wbGV0aW9uKHtcbiAgICAgICAgICAgIHN0b3JhZ2U6IHBvbGxTdG9yYWdlLFxuICAgICAgICAgICAgc2FuZGJveElkOiBzYW5kYm94UmVjb3JkLmlkLFxuICAgICAgICAgICAgc2V0dXBLZXk6IHNhbmRib3hSZWNvcmQuc2V0dXBLZXksXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBnZXRTYW5kYm94UmVzdWx0KCk7XG4gICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgIHN0YXJ0UHJvbWlzZSA9IG51bGw7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCB1cGRhdGVMYXN0QWN0aXZpdHkoKTtcblxuICAgICAgICBpZiAocmVzdWx0Lm5lZWRzU2V0dXBSdW4gJiYgc2V0dXApIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgc2V0dXAucnVuKHNhbmRib3gpO1xuICAgICAgICAgICAgYXdhaXQgbWFya1NldHVwQ29tcGxldGUoe1xuICAgICAgICAgICAgICBzdG9yYWdlLFxuICAgICAgICAgICAgICBzYW5kYm94SWQ6IHNhbmRib3hSZWNvcmQuaWQsXG4gICAgICAgICAgICAgIHNldHVwS2V5OiBzZXR1cC5rZXksXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBhd2FpdCByZXNldFNldHVwU3RhdGUoe1xuICAgICAgICAgICAgICBzdG9yYWdlLFxuICAgICAgICAgICAgICBzYW5kYm94SWQ6IHNhbmRib3hSZWNvcmQuaWQsXG4gICAgICAgICAgICAgIHNldHVwS2V5OiBzZXR1cC5rZXksXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRocm93IGU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHJlc3VsdC5jcmVhdGVkRnJvbVNuYXBzaG90ICYmIG9uUmVzdGFydCkge1xuICAgICAgICAgIGF3YWl0IG9uUmVzdGFydChzYW5kYm94KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9KSgpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgIHN0YXJ0UHJvbWlzZSA9IG51bGw7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBzdGFydFByb21pc2U7XG4gICAgfSxcblxuICAgIHNuYXBzaG90OiBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzYW5kYm94ID0gYXdhaXQgZ2V0U2FuZGJveEluc3RhbmNlKCk7XG4gICAgICBpZiAoc2FuZGJveCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHJldHVybiBzYW5kYm94O1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gZXJyb3JlLnRyeUFzeW5jKHtcbiAgICAgICAgdHJ5OiBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgY29uc3Qgc25hcHNob3QgPSBhd2FpdCBzYW5kYm94LnNuYXBzaG90KCk7XG4gICAgICAgICAgYXdhaXQgc3RvcmFnZS5zYW5kYm94LnVwZGF0ZSh7XG4gICAgICAgICAgICBpZCxcbiAgICAgICAgICAgIGFjcXVpcmluZ0xvY2tJZDogbnVsbCxcbiAgICAgICAgICAgIGFjcXVpcmluZ0xvY2tBdDogbnVsbCxcbiAgICAgICAgICAgIHByb3ZpZGVyTWV0YWRhdGE6IHtcbiAgICAgICAgICAgICAgcHJvdmlkZXI6IFwidmVyY2VsXCIsXG4gICAgICAgICAgICAgIHNhbmRib3hJZDogbnVsbCxcbiAgICAgICAgICAgICAgc25hcHNob3RJZDogc25hcHNob3Quc25hcHNob3RJZCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuIHsgc25hcHNob3RJZDogc25hcHNob3Quc25hcHNob3RJZCB9O1xuICAgICAgICB9LFxuICAgICAgICBjYXRjaDogKGUpID0+IG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSksXG4gICAgICB9KTtcbiAgICB9LFxuXG4gICAgc3RvcDogYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qgc2FuZGJveCA9IGF3YWl0IGdldFNhbmRib3hJbnN0YW5jZSgpO1xuICAgICAgaWYgKHNhbmRib3ggaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICByZXR1cm4gc2FuZGJveDtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGVycm9yZS50cnlBc3luYyh7XG4gICAgICAgIHRyeTogYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGF3YWl0IHNhbmRib3guc3RvcCgpO1xuICAgICAgICAgIGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC51cGRhdGUoe1xuICAgICAgICAgICAgaWQsXG4gICAgICAgICAgICBhY3F1aXJpbmdMb2NrSWQ6IG51bGwsXG4gICAgICAgICAgICBhY3F1aXJpbmdMb2NrQXQ6IG51bGwsXG4gICAgICAgICAgICBwcm92aWRlck1ldGFkYXRhOiB7XG4gICAgICAgICAgICAgIHByb3ZpZGVyOiBcInZlcmNlbFwiLFxuICAgICAgICAgICAgICBzYW5kYm94SWQ6IG51bGwsXG4gICAgICAgICAgICAgIHNuYXBzaG90SWQ6IG51bGwsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIH0sXG4gICAgICAgIGNhdGNoOiAoZSkgPT4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogU3RyaW5nKGUpLCBjYXVzZTogZSB9KSxcbiAgICAgIH0pO1xuICAgIH0sXG5cbiAgICBnZXRTdGF0dXM6IGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHNhbmRib3ggPSBhd2FpdCBnZXRTYW5kYm94SW5zdGFuY2UoKTtcbiAgICAgIGlmIChzYW5kYm94IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIHNhbmRib3g7XG4gICAgICB9XG4gICAgICByZXR1cm4gc2FuZGJveC5zdGF0dXMgYXMgU2FuZGJveFN0YXR1cztcbiAgICB9LFxuXG4gICAgZ2V0Q3JlYXRlZEF0OiBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzYW5kYm94ID0gYXdhaXQgZ2V0U2FuZGJveEluc3RhbmNlKCk7XG4gICAgICBpZiAoc2FuZGJveCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHJldHVybiBzYW5kYm94O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHNhbmRib3guY3JlYXRlZEF0O1xuICAgIH0sXG5cbiAgICBnZXRSZW1haW5pbmdUaW1lb3V0OiBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzYW5kYm94ID0gYXdhaXQgZ2V0U2FuZGJveEluc3RhbmNlKCk7XG4gICAgICBpZiAoc2FuZGJveCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHJldHVybiBzYW5kYm94O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHNhbmRib3gudGltZW91dDtcbiAgICB9LFxuICB9O1xuXG4gIGFzeW5jIGZ1bmN0aW9uIGRvRXhlYyhvcHRzOiB7XG4gICAgY29tbWFuZDogc3RyaW5nO1xuICAgIGFyZ3M/OiBzdHJpbmdbXTtcbiAgICBjd2Q/OiBzdHJpbmc7XG4gICAgZW52PzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbiAgICBzaWduYWw/OiBBYm9ydFNpZ25hbDtcbiAgICBzdWRvPzogYm9vbGVhbjtcbiAgfSkge1xuICAgIGNvbnN0IGluc3RhbmNlID0gYXdhaXQgZ2V0U2FuZGJveEluc3RhbmNlKCk7XG4gICAgaWYgKGluc3RhbmNlIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIHJldHVybiBpbnN0YW5jZTtcbiAgICB9XG5cbiAgICBjb25zdCB1cGRhdGVQcm9taXNlID0gdXBkYXRlTGFzdEFjdGl2aXR5KCk7XG4gICAgY29uc3QgZXhlY1Jlc3VsdCA9IGF3YWl0IGV4ZWNPbkluc3RhbmNlKGluc3RhbmNlLCBvcHRzKTtcbiAgICBhd2FpdCB1cGRhdGVQcm9taXNlO1xuICAgIHJldHVybiBleGVjUmVzdWx0O1xuICB9XG5cbiAgY29uc3Qgc2FuZGJveDogU2FuZGJveDxUVGFncz4gPSB7XG4gICAgaWQsXG4gICAgY29uZmlnLFxuICAgIGN3ZCxcbiAgICBleGVjOiBhc3luYyAob3B0cykgPT4ge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZG9FeGVjKG9wdHMpO1xuXG4gICAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgU2FuZGJveEVycm9yICYmIGlzU2FuZGJveEdvbmVFcnJvcihyZXN1bHQuY2F1c2UpKSB7XG4gICAgICAgIGF3YWl0IHJlY292ZXJGcm9tU3RhbGVTYW5kYm94KCk7XG4gICAgICAgIHJldHVybiBhd2FpdCBkb0V4ZWMob3B0cyk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSxcblxuICAgIGdldERvbWFpbjogYXN5bmMgKHBvcnQpID0+IHtcbiAgICAgIGNvbnN0IHNhbmRib3ggPSBhd2FpdCBnZXRTYW5kYm94SW5zdGFuY2UoKTtcbiAgICAgIGlmIChzYW5kYm94IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIHNhbmRib3g7XG4gICAgICB9XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBzYW5kYm94LmRvbWFpbihwb3J0KTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSk7XG4gICAgICB9XG4gICAgfSxcblxuICAgIGtpbGw6IGFzeW5jICh7IGNvbW1hbmRJZCwgc3RvcmFnZTogY21kU3RvcmFnZSB9KSA9PiB7XG4gICAgICBjb25zdCBpbnN0YW5jZSA9IGF3YWl0IGdldFNhbmRib3hJbnN0YW5jZSgpO1xuICAgICAgaWYgKGluc3RhbmNlIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIGluc3RhbmNlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBjbWQgPSBhd2FpdCBjbWRTdG9yYWdlLmNvbW1hbmQuZ2V0KGNvbW1hbmRJZCk7XG4gICAgICBpZiAoY21kIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IGNtZC5tZXNzYWdlLCBjYXVzZTogY21kIH0pO1xuICAgICAgfVxuICAgICAgaWYgKGNtZCAmJiBjbWQuc3RhdHVzID09PSBcInJ1bm5pbmdcIikge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjbWRTdG9yYWdlLmNvbW1hbmQuc2V0KHtcbiAgICAgICAgICAuLi5jbWQsXG4gICAgICAgICAgc3RhdHVzOiBcImtpbGxlZFwiLFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IHJlc3VsdC5tZXNzYWdlLCBjYXVzZTogcmVzdWx0IH0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH0sXG5cbiAgICByZWFkRmlsZTogYXN5bmMgKG9wdHMpID0+IHtcbiAgICAgIGNvbnN0IGluc3RhbmNlID0gYXdhaXQgZ2V0U2FuZGJveEluc3RhbmNlKCk7XG4gICAgICBpZiAoaW5zdGFuY2UgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICByZXR1cm4gaW5zdGFuY2U7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVhZEZpbGVPbkluc3RhbmNlKGluc3RhbmNlLCBvcHRzKTtcbiAgICB9LFxuXG4gICAgd3JpdGVGaWxlczogYXN5bmMgKG9wdHMpID0+IHtcbiAgICAgIGNvbnN0IGluc3RhbmNlID0gYXdhaXQgZ2V0U2FuZGJveEluc3RhbmNlKCk7XG4gICAgICBpZiAoaW5zdGFuY2UgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICB0aHJvdyBpbnN0YW5jZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB3cml0ZUZpbGVzT25JbnN0YW5jZShpbnN0YW5jZSwgb3B0cyk7XG4gICAgfSxcblxuICAgIGxpZmVjeWNsZSxcblxuICAgIHVwZGF0ZU5ldHdvcmtQb2xpY3k6IGFzeW5jIChwb2xpY3kpID0+IHtcbiAgICAgIGNvbnN0IGluc3RhbmNlID0gYXdhaXQgZ2V0U2FuZGJveEluc3RhbmNlKCk7XG4gICAgICBpZiAoaW5zdGFuY2UgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICByZXR1cm4gaW5zdGFuY2U7XG4gICAgICB9XG4gICAgICByZXR1cm4gZXJyb3JlLnRyeUFzeW5jKHtcbiAgICAgICAgdHJ5OiAoKSA9PiBpbnN0YW5jZS51cGRhdGVOZXR3b3JrUG9saWN5KHBvbGljeSksXG4gICAgICAgIGNhdGNoOiAoZSkgPT4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogU3RyaW5nKGUpLCBjYXVzZTogZSB9KSxcbiAgICAgIH0pO1xuICAgIH0sXG5cbiAgICB0YWc6IHtcbiAgICAgIGxpc3Q6IGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc3Qgc2FuZGJveFJlY29yZCA9IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5nZXQoaWQpO1xuICAgICAgICBpZiAoc2FuZGJveFJlY29yZCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIHNhbmRib3hSZWNvcmQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIChzYW5kYm94UmVjb3JkLnRhZ3MgPz8ge30pIGFzIFRUYWdzO1xuICAgICAgfSxcbiAgICAgIGdldDogYXN5bmMgKGtleTogc3RyaW5nKSA9PiB7XG4gICAgICAgIGNvbnN0IHNhbmRib3hSZWNvcmQgPSBhd2FpdCBzdG9yYWdlLnNhbmRib3guZ2V0KGlkKTtcbiAgICAgICAgaWYgKHNhbmRib3hSZWNvcmQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgIHJldHVybiBzYW5kYm94UmVjb3JkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzYW5kYm94UmVjb3JkLnRhZ3M/LltrZXkgYXMgc3RyaW5nXSBhc1xuICAgICAgICAgIHwgVFRhZ3NbdHlwZW9mIGtleV1cbiAgICAgICAgICB8IHVuZGVmaW5lZDtcbiAgICAgIH0sXG4gICAgICBzZXQ6IGFzeW5jIChrZXk6IHN0cmluZywgdmFsdWU6IHVua25vd24pID0+IHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3RvcmFnZS5zYW5kYm94LnRhZy5zZXQoe1xuICAgICAgICAgIHNhbmRib3hJZDogaWQsXG4gICAgICAgICAgdGFnczogeyBba2V5XTogdmFsdWUgfSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH0sXG4gICAgICBzZXRNYW55OiBhc3luYyAodGFnczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pID0+IHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3RvcmFnZS5zYW5kYm94LnRhZy5zZXQoe1xuICAgICAgICAgIHNhbmRib3hJZDogaWQsXG4gICAgICAgICAgdGFnczogdGFncyBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH0sXG4gICAgfSxcbiAgfTtcblxuICByZXR1cm4gc2FuZGJveDtcbn07XG4iLCAiaW1wb3J0IHR5cGUgeyBUYWdzU2NoZW1hIH0gZnJvbSBcIi4uL2luZGV4XCI7XG5pbXBvcnQgdHlwZSB7IFJwY0ZuLCBTYW5kYm94UmVjb3JkLCBTdG9yYWdlLCBTdG9yYWdlQ29uZmlnIH0gZnJvbSBcIi4uL3N0b3JhZ2VcIjtcbmltcG9ydCB7IGNyZWF0ZUxvZ2dlciB9IGZyb20gXCIuLi91dGlscy9sb2dnZXJcIjtcbmltcG9ydCB7IGRvY2tlclNhbmRib3ggfSBmcm9tIFwiLi9iaW5kaW5ncy9kb2NrZXJcIjtcbmltcG9ydCB7IGxvY2FsU2FuZGJveCB9IGZyb20gXCIuL2JpbmRpbmdzL2xvY2FsXCI7XG5pbXBvcnQgeyB2ZXJjZWxTYW5kYm94IH0gZnJvbSBcIi4vYmluZGluZ3MvdmVyY2VsXCI7XG5pbXBvcnQgdHlwZSB7IE9uUmVzdGFydCwgU2FuZGJveCwgU2FuZGJveFNldHVwIH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuY29uc3QgbG9nID0gY3JlYXRlTG9nZ2VyKHsgc3Vic3lzdGVtOiBcInNhbmRib3hcIiB9KTtcblxudHlwZSBTYW5kYm94V2l0aE1ldGE8VFRhZ3MgZXh0ZW5kcyBUYWdzU2NoZW1hID0gVGFnc1NjaGVtYT4gPSBTYW5kYm94PFRUYWdzPiAmIHtcbiAgX29uUmVhZHk/OiBQcm9taXNlPHZvaWQ+O1xufTtcblxuLyoqXG4gKiBNb2R1bGUtbGV2ZWwgY2FjaGUgZm9yIHNhbmRib3ggaW5zdGFuY2VzIGtleWVkIGJ5IHNhbmRib3ggcmVjb3JkIElELlxuICpcbiAqIENhY2hlcyBhbGwgc2FuZGJveCBpbnN0YW5jZXMgc28gdGhhdCB0aGUgd29ya2Zsb3cgKHdoaWNoIGNhbGxzIGdldFNhbmRib3hcbiAqIHdpdGhvdXQgc2V0dXAvb25SZXN0YXJ0KSByZXVzZXMgdGhlIHNhbWUgaW5zdGFuY2UgY3JlYXRlZCBkdXJpbmcgc2Vzc2lvbigpLFxuICogaW5jbHVkaW5nIGl0cyBfb25SZWFkeSBwcm9taXNlLlxuICovXG5jb25zdCBzYW5kYm94Q2FjaGUgPSBuZXcgTWFwPHN0cmluZywgU2FuZGJveFdpdGhNZXRhPigpO1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0U2FuZGJveDxUVGFncyBleHRlbmRzIFRhZ3NTY2hlbWEgPSBUYWdzU2NoZW1hPih7XG4gIHNhbmRib3hSZWNvcmQsXG4gIHN0b3JhZ2VDb25maWcsXG4gIHN0b3JhZ2UsXG4gIHJwYyxcbiAgZW5hYmxlTGlmZWN5Y2xlV29ya2Zsb3cgPSB0cnVlLFxuICBzZXR1cCxcbiAgb25SZXN0YXJ0LFxufToge1xuICBzdG9yYWdlQ29uZmlnOiBTdG9yYWdlQ29uZmlnO1xuICBzYW5kYm94UmVjb3JkOiBTYW5kYm94UmVjb3JkO1xuICBzdG9yYWdlOiBTdG9yYWdlO1xuICBycGM6IFJwY0ZuO1xuICBlbmFibGVMaWZlY3ljbGVXb3JrZmxvdz86IGJvb2xlYW47XG4gIHNldHVwPzogU2FuZGJveFNldHVwO1xuICBvblJlc3RhcnQ/OiBPblJlc3RhcnQ7XG59KTogU2FuZGJveFdpdGhNZXRhPFRUYWdzPiB7XG4gIGNvbnN0IGNhY2hlZCA9IHNhbmRib3hDYWNoZS5nZXQoc2FuZGJveFJlY29yZC5pZCk7XG4gIGlmIChjYWNoZWQpIHtcbiAgICByZXR1cm4gY2FjaGVkIGFzIFNhbmRib3hXaXRoTWV0YTxUVGFncz47XG4gIH1cblxuICBjb25zdCBzYnggPSBjcmVhdGVTYW5kYm94PFRUYWdzPih7XG4gICAgc2FuZGJveFJlY29yZCxcbiAgICBzdG9yYWdlQ29uZmlnLFxuICAgIHN0b3JhZ2UsXG4gICAgcnBjLFxuICAgIGVuYWJsZUxpZmVjeWNsZVdvcmtmbG93LFxuICAgIHNldHVwLFxuICAgIG9uUmVzdGFydCxcbiAgfSk7XG5cbiAgY2FjaGVTYW5kYm94KHNhbmRib3hSZWNvcmQuaWQsIHNieCk7XG5cbiAgcmV0dXJuIHNieDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGV2aWN0U2FuZGJveChpZDogc3RyaW5nKTogdm9pZCB7XG4gIHNhbmRib3hDYWNoZS5kZWxldGUoaWQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY2FjaGVTYW5kYm94KGlkOiBzdHJpbmcsIHNhbmRib3g6IFNhbmRib3gpOiB2b2lkIHtcbiAgc2FuZGJveENhY2hlLnNldChpZCwgc2FuZGJveCBhcyBTYW5kYm94V2l0aE1ldGEpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU2FuZGJveDxUVGFncyBleHRlbmRzIFRhZ3NTY2hlbWEgPSBUYWdzU2NoZW1hPih7XG4gIHNhbmRib3hSZWNvcmQsXG4gIHN0b3JhZ2VDb25maWcsXG4gIHN0b3JhZ2UsXG4gIHJwYyxcbiAgZW5hYmxlTGlmZWN5Y2xlV29ya2Zsb3cgPSB0cnVlLFxuICBzZXR1cCxcbiAgb25SZXN0YXJ0LFxufToge1xuICBzdG9yYWdlQ29uZmlnOiBTdG9yYWdlQ29uZmlnO1xuICBzYW5kYm94UmVjb3JkOiBTYW5kYm94UmVjb3JkO1xuICBzdG9yYWdlOiBTdG9yYWdlO1xuICBycGM6IFJwY0ZuO1xuICBlbmFibGVMaWZlY3ljbGVXb3JrZmxvdz86IGJvb2xlYW47XG4gIHNldHVwPzogU2FuZGJveFNldHVwO1xuICBvblJlc3RhcnQ/OiBPblJlc3RhcnQ7XG59KTogU2FuZGJveFdpdGhNZXRhPFRUYWdzPiB7XG4gIGxldCBzYng6IFNhbmRib3g8VFRhZ3M+O1xuXG4gIC8vIFNjb3BlIHNldHVwIGtleSBieSBzYW5kYm94IHR5cGUgc28gYSBzZXR1cCBjb21wbGV0ZWQgb24gb25lIHByb3ZpZGVyXG4gIC8vIChlLmcuIFwibG9jYWxcIikgZG9lc24ndCBjb3VudCBhcyBkb25lIGZvciBhbm90aGVyIChlLmcuIFwiZG9ja2VyXCIpLlxuICBjb25zdCBzY29wZWRTZXR1cDogU2FuZGJveFNldHVwIHwgdW5kZWZpbmVkID0gc2V0dXBcbiAgICA/IHtcbiAgICAgICAgLi4uc2V0dXAsXG4gICAgICAgIGtleTogYCR7c2FuZGJveFJlY29yZC5jb25maWcudHlwZX06JHtzZXR1cC5rZXl9YCxcbiAgICAgIH1cbiAgICA6IHVuZGVmaW5lZDtcblxuICBjb25zdCByZWNvcmRXaXRoU2V0dXBLZXkgPSBzY29wZWRTZXR1cFxuICAgID8geyAuLi5zYW5kYm94UmVjb3JkLCBzZXR1cEtleTogc2NvcGVkU2V0dXAua2V5IH1cbiAgICA6IHNhbmRib3hSZWNvcmQ7XG5cbiAgc3dpdGNoIChzYW5kYm94UmVjb3JkLmNvbmZpZy50eXBlKSB7XG4gICAgY2FzZSBcImxvY2FsXCI6XG4gICAgICBzYnggPSBsb2NhbFNhbmRib3g8VFRhZ3M+KHtcbiAgICAgICAgc2FuZGJveFJlY29yZDogcmVjb3JkV2l0aFNldHVwS2V5IGFzIFNhbmRib3hSZWNvcmQgJiB7XG4gICAgICAgICAgY29uZmlnOiB7IHR5cGU6IFwibG9jYWxcIiB9O1xuICAgICAgICB9LFxuICAgICAgICBzdG9yYWdlLFxuICAgICAgICBzZXR1cDogc2NvcGVkU2V0dXAsXG4gICAgICAgIG9uUmVzdGFydCxcbiAgICAgIH0pO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcImRvY2tlclwiOlxuICAgICAgc2J4ID0gZG9ja2VyU2FuZGJveDxUVGFncz4oe1xuICAgICAgICBzYW5kYm94UmVjb3JkOiByZWNvcmRXaXRoU2V0dXBLZXkgYXMgU2FuZGJveFJlY29yZCAmIHtcbiAgICAgICAgICBjb25maWc6IHsgdHlwZTogXCJkb2NrZXJcIiB9O1xuICAgICAgICB9LFxuICAgICAgICBzdG9yYWdlLFxuICAgICAgICBzZXR1cDogc2NvcGVkU2V0dXAsXG4gICAgICAgIG9uUmVzdGFydCxcbiAgICAgIH0pO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcInZlcmNlbFwiOlxuICAgICAgc2J4ID0gdmVyY2VsU2FuZGJveDxUVGFncz4oe1xuICAgICAgICBzYW5kYm94UmVjb3JkOiByZWNvcmRXaXRoU2V0dXBLZXkgYXMgU2FuZGJveFJlY29yZCAmIHtcbiAgICAgICAgICBjb25maWc6IHsgdHlwZTogXCJ2ZXJjZWxcIiB9O1xuICAgICAgICB9LFxuICAgICAgICBzdG9yYWdlQ29uZmlnLFxuICAgICAgICBzdG9yYWdlLFxuICAgICAgICBycGMsXG4gICAgICAgIGVuYWJsZUxpZmVjeWNsZVdvcmtmbG93LFxuICAgICAgICBzZXR1cDogc2NvcGVkU2V0dXAsXG4gICAgICAgIG9uUmVzdGFydCxcbiAgICAgIH0pO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcImN1c3RvbVwiOlxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ3VzdG9tIHNhbmRib3hlcyBhcmUgbm90IHN1cHBvcnRlZFwiKTtcbiAgICBkZWZhdWx0OlxuICAgICAgc2FuZGJveFJlY29yZC5jb25maWcgc2F0aXNmaWVzIG5ldmVyO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgVW5rbm93biBzYW5kYm94IHR5cGU6ICR7XG4gICAgICAgICAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiAuXG4gICAgICAgICAgKHNhbmRib3hSZWNvcmQuY29uZmlnIGFzIGFueSkudHlwZVxuICAgICAgICB9YFxuICAgICAgKTtcbiAgfVxuXG4gIGxldCByZWFkeVByb21pc2U6IFByb21pc2U8dm9pZD4gfCBudWxsID0gbnVsbDtcbiAgbGV0IHB1YmxpY09uUmVhZHk6IFByb21pc2U8dm9pZD4gfCB1bmRlZmluZWQ7XG5cbiAgZnVuY3Rpb24gZW5zdXJlUmVhZHkoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHJlYWR5UHJvbWlzZSkge1xuICAgICAgcmV0dXJuIHJlYWR5UHJvbWlzZTtcbiAgICB9XG4gICAgcmVhZHlQcm9taXNlID0gKGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGRvbmUgPSBsb2cudGltZShcImVuc3VyZVJlYWR5IC8gbGlmZWN5Y2xlLnN0YXJ0XCIsIHtcbiAgICAgICAgc2FuZGJveElkOiBzYW5kYm94UmVjb3JkLmlkLFxuICAgICAgfSk7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzYngubGlmZWN5Y2xlLnN0YXJ0KCk7XG4gICAgICBkb25lKCk7XG4gICAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgcmVzdWx0O1xuICAgICAgfVxuICAgIH0pKCkuY2F0Y2goKGUpID0+IHtcbiAgICAgIHJlYWR5UHJvbWlzZSA9IG51bGw7XG4gICAgICBwdWJsaWNPblJlYWR5ID0gdW5kZWZpbmVkO1xuICAgICAgdGhyb3cgZTtcbiAgICB9KTtcbiAgICBwdWJsaWNPblJlYWR5ID0gcmVhZHlQcm9taXNlO1xuICAgIHJldHVybiByZWFkeVByb21pc2U7XG4gIH1cblxuICAvKipcbiAgICogRWFnZXJseSBraWNrIG9mZiBzdGFydCB1bmxlc3MgYXV0b1N0YXJ0IGlzIGZhbHNlLlxuICAgKiBUaGUgdmVyY2VsIGJpbmRpbmcgYWxzbyBwcmUtd2FybXMgdGhlIHNhbmRib3ggcHJvbWlzZSBpbnRlcm5hbGx5XG4gICAqIHdoZW4gYXV0b1N0YXJ0ICE9PSBmYWxzZSwgc28gdGhpcyBqdXN0IGxheWVycyBzZXR1cC9jb2xkLXN0YXJ0IG9uIHRvcC5cbiAgICovXG4gIGNvbnN0IGF1dG9TdGFydCA9XG4gICAgc2FuZGJveFJlY29yZC5jb25maWcudHlwZSA9PT0gXCJ2ZXJjZWxcIlxuICAgICAgPyBzYW5kYm94UmVjb3JkLmNvbmZpZy5saWZlY3ljbGU/LmF1dG9TdGFydCAhPT0gZmFsc2VcbiAgICAgIDogdHJ1ZTtcblxuICBpZiAoYXV0b1N0YXJ0KSB7XG4gICAgZW5zdXJlUmVhZHkoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBXcmFwIHNhbmRib3ggbWV0aG9kcyBzbyBhbnkgb3BlcmF0aW9uIGltcGxpY2l0bHkgd2FpdHMgZm9yIHN0YXJ0LlxuICAgKiBXZSByZXR1cm4gYSBORVcgb2JqZWN0IHNvIHRoYXQgc2V0dXAucnVuKCksIHdoaWNoIGhvbGRzIHRoZSBvcmlnaW5hbFxuICAgKiBgc2J4YCB2aWEgY2xvc3VyZSwgY2FsbHMgdW53cmFwcGVkIG1ldGhvZHMgYW5kIGF2b2lkcyBhIGRlYWRsb2NrLlxuICAgKlxuICAgKiBfb25SZWFkeSBpcyBhIHBhc3NpdmUgZ2V0dGVyOiBpdCByZXR1cm5zIHRoZSBjdXJyZW50IGluLWZsaWdodCBwcm9taXNlXG4gICAqIChvciB1bmRlZmluZWQpIHdpdGhvdXQgdHJpZ2dlcmluZyBzdGFydHVwLiBPbmx5IGVuc3VyZVJlYWR5KCkgYW5kIHRoZVxuICAgKiB3cmFwcGVkIG1ldGhvZHMgdHJpZ2dlciBzdGFydHVwLiBUaGlzIHByZXNlcnZlcyBhdXRvU3RhcnQ6IGZhbHNlXG4gICAqIHNlbWFudGljcyBcdTIwMTQgcmVhZGluZyBfb25SZWFkeSBmb3Igc3RhdHVzIGRpc3BsYXkgbmV2ZXIgc3RhcnRzIHRoZSBzYW5kYm94LlxuICAgKi9cbiAgcmV0dXJuIHtcbiAgICAuLi5zYngsXG4gICAgZ2V0IF9vblJlYWR5KCkge1xuICAgICAgcmV0dXJuIHB1YmxpY09uUmVhZHk7XG4gICAgfSxcbiAgICBleGVjOiBhc3luYyAob3B0cykgPT4ge1xuICAgICAgYXdhaXQgZW5zdXJlUmVhZHkoKTtcbiAgICAgIHJldHVybiBzYnguZXhlYyhvcHRzKTtcbiAgICB9LFxuICAgIGdldERvbWFpbjogYXN5bmMgKHBvcnQpID0+IHtcbiAgICAgIGF3YWl0IGVuc3VyZVJlYWR5KCk7XG4gICAgICByZXR1cm4gc2J4LmdldERvbWFpbihwb3J0KTtcbiAgICB9LFxuICAgIHJlYWRGaWxlOiBhc3luYyAob3B0cykgPT4ge1xuICAgICAgYXdhaXQgZW5zdXJlUmVhZHkoKTtcbiAgICAgIHJldHVybiBzYngucmVhZEZpbGUob3B0cyk7XG4gICAgfSxcbiAgICB3cml0ZUZpbGVzOiBhc3luYyAob3B0cykgPT4ge1xuICAgICAgYXdhaXQgZW5zdXJlUmVhZHkoKTtcbiAgICAgIHJldHVybiBzYngud3JpdGVGaWxlcyhvcHRzKTtcbiAgICB9LFxuICB9O1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUNBLFNBQVMsYUFBYTtBQUN0QixZQUFZLFFBQVE7QUFDcEIsWUFBWSxVQUFVO0FBQ3RCLFlBQVksWUFBWTtBQUN4QixTQUFTLFlBQVk7QUFZZCxJQUFNLGVBQWUsQ0FBd0M7QUFBQSxFQUNsRTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUNGLE1BS3NCO0FBQ3BCLFFBQU0sU0FBUyxjQUFjO0FBQzdCLFFBQU0s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VSxNQUFNO0FBQ3pDLFdBQUs7QUFDTCxVQUFJLGtCQUFrQixPQUFPO0FBQzNCLGNBQU07QUFBQSxNQUNSO0FBQUEsSUFDRixHQUFHLEVBQUUsTUFBTSxDQUFDLE1BQU07QUFDaEIscUJBQWU7QUFDZixzQkFBZ0I7QUFDaEIsWUFBTTtBQUFBLElBQ1IsQ0FBQztBQUNELG9CQUFnQjtBQUNoQixXQUFPO0FBQUEsRUFDVDtBQU9BLFFBQU0sWUFDSixjQUFjLE9BQU8sU0FBUyxXQUMxQixjQUFjLE9BQU8sV0FBVyxjQUFjLFFBQzlDO0FBRU4sTUFBSSxXQUFXO0FBQ2IsZ0JBQVk7QUFBQSxFQUNkO0FBWUEsU0FBTztBQUFBLElBQ0wsR0FBRztBQUFBLElBQ0gsSUFBSSxXQUFXO0FBQ2IsYUFBTztBQUFBLElBQ1Q7QUFBQSxJQUNBLE1BQU0sT0FBTyxTQUFTO0FBQ3BCLFlBQU0sWUFBWTtBQUNsQixhQUFPLElBQUksS0FBSyxJQUFJO0FBQUEsSUFDdEI7QUFBQSxJQUNBLFdBQVcsT0FBTyxTQUFTO0FBQ3pCLFlBQU0sWUFBWTtBQUNsQixhQUFPLElBQUksVUFBVSxJQUFJO0FBQUEsSUFDM0I7QUFBQSxJQUNBLFVBQVUsT0FBTyxTQUFTO0FBQ3hCLFlBQU0sWUFBWTtBQUNsQixhQUFPLElBQUksU0FBUyxJQUFJO0FBQUEsSUFDMUI7QUFBQSxJQUNBLFlBQVksT0FBTyxTQUFTO0FBQzFCLFlBQU0sWUFBWTtBQUNsQixhQUFPLElBQUksV0FBVyxJQUFJO0FBQUEsSUFDNUI7QUFBQSxFQUNGO0FBQ0Y7IiwKICAibmFtZXMiOiBbInJlc29sdmUiLCAic3RvcmFnZSIsICJzYW5kYm94UmVjb3JkIiwgInBhdGgiLCAiZXJyb3JlIiwgInNhbmRib3giLCAibG9nIiwgInJlc29sdmUiLCAicGF0aCIsICJmcmVzaFJlc3VsdCIsICJzYW5kYm94UmVjb3JkIl0KfQo=
|