@dbx-tools/appkit-mastra 0.9.118 → 0.9.119

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.
@@ -1,461 +0,0 @@
1
- /**
2
- * Databricks Sandbox adapter for Mastra workspaces.
3
- *
4
- * Implements Mastra's foreground command surface over the Databricks Sandbox
5
- * REST API. Sandboxes are created lazily, retain their home directory across
6
- * inactivity stops, and execute untrusted shell commands outside the App
7
- * container.
8
- *
9
- * @module
10
- */
11
- import { databricks } from "@dbx-tools/appkit";
12
- import { asyncUtils, errorUtils, log, stringUtils } from "@dbx-tools/shared-core";
13
- import { z } from "zod";
14
- import { MontySandbox } from "./monty-sandbox.js";
15
- const SANDBOX_API_PATH = "/api/2.0/sandboxes";
16
- const SANDBOX_EXEC_API_PATH = "/api/2.0/sandbox-exec/sandboxes";
17
- const DEFAULT_INACTIVITY_TIMEOUT = "900s";
18
- const DEFAULT_STARTUP_TIMEOUT_MS = 120_000;
19
- const DEFAULT_COMMAND_TIMEOUT_MS = 30_000;
20
- const SANDBOX_POLL_INTERVAL_MS = 500;
21
- const logger = log.logger("mastra/sandbox");
22
- const SandboxStateSchema = z.object({
23
- state: z.string().optional(),
24
- });
25
- const SandboxResponseSchema = z.object({
26
- name: z.string(),
27
- display_name: z.string().optional(),
28
- create_time: z.string().optional(),
29
- update_time: z.string().optional(),
30
- status: SandboxStateSchema.optional(),
31
- });
32
- const ExecuteResponseSchema = z.object({
33
- exit_code: z.number().int().optional(),
34
- status: z.string(),
35
- stdout: z.string().optional(),
36
- stderr: z.string().optional(),
37
- command_id: z.string().optional(),
38
- truncated: z.boolean().optional(),
39
- });
40
- /** Mastra sandbox backed by Databricks serverless Sandbox compute. */
41
- export class DatabricksSandbox {
42
- id;
43
- name;
44
- status = "pending";
45
- error;
46
- client;
47
- displayName;
48
- inactivityTimeout;
49
- startupTimeoutMs;
50
- commandTimeoutMs;
51
- fallbackConfig;
52
- createdAt = new Date();
53
- remoteCreatedAt;
54
- lastUsedAt;
55
- activeFallback;
56
- fallbackPromise;
57
- startPromise;
58
- constructor(options) {
59
- const id = stringUtils.trimToNull(options.sandboxId.replace(/^sandboxes\//, ""));
60
- if (!id)
61
- throw new TypeError("Databricks sandbox id must not be blank");
62
- this.id = id;
63
- this.name = options.displayName?.trim() || `Mastra sandbox ${id}`;
64
- this.client = options.client;
65
- this.displayName = this.name;
66
- this.inactivityTimeout = options.inactivityTimeout ?? DEFAULT_INACTIVITY_TIMEOUT;
67
- this.startupTimeoutMs = options.startupTimeoutMs ?? DEFAULT_STARTUP_TIMEOUT_MS;
68
- this.commandTimeoutMs = options.commandTimeoutMs ?? DEFAULT_COMMAND_TIMEOUT_MS;
69
- this.fallbackConfig = options.fallback ?? false;
70
- }
71
- get provider() {
72
- return this.activeFallback?.provider ?? "databricks";
73
- }
74
- /** Ensure the remote sandbox exists and has reached its running state. */
75
- async start() {
76
- await this.startWithSignal();
77
- }
78
- async startWithSignal(signal) {
79
- if (this.status === "running")
80
- return;
81
- if (this.startPromise) {
82
- await this.startPromise;
83
- return;
84
- }
85
- const pending = this.performStart(signal);
86
- this.startPromise = pending;
87
- try {
88
- await pending;
89
- }
90
- finally {
91
- if (this.startPromise === pending)
92
- this.startPromise = undefined;
93
- }
94
- }
95
- async performStart(signal) {
96
- if (this.activeFallback) {
97
- await this.activeFallback.start?.();
98
- this.status = this.activeFallback.status;
99
- return;
100
- }
101
- this.status = "starting";
102
- this.error = undefined;
103
- try {
104
- let sandbox = await this.getOrCreate(signal);
105
- if (sandbox.status?.state === "SANDBOX_STATE_STOPPED") {
106
- sandbox = await this.mutate("start", signal);
107
- }
108
- if (sandbox.status?.state === "SANDBOX_STATE_STOPPING") {
109
- await this.waitForState("SANDBOX_STATE_STOPPED", signal);
110
- sandbox = await this.mutate("start", signal);
111
- }
112
- if (sandbox.status?.state !== "SANDBOX_STATE_RUNNING") {
113
- await this.waitForState("SANDBOX_STATE_RUNNING", signal);
114
- }
115
- this.status = "running";
116
- this.lastUsedAt = new Date();
117
- }
118
- catch (caught) {
119
- if (this.fallbackConfig !== false && isDatabricksSandboxUnavailable(caught)) {
120
- await this.activateFallback(caught);
121
- return;
122
- }
123
- this.status = "error";
124
- this.error = errorUtils.errorMessage(caught);
125
- throw caught;
126
- }
127
- }
128
- /** Databricks home persistence is not a cloneable Mastra checkpoint. */
129
- async snapshot() {
130
- await this.activeFallback?.snapshot();
131
- }
132
- get supportsCheckpoints() {
133
- return this.activeFallback?.supportsCheckpoints ?? false;
134
- }
135
- /** Stop compute while preserving the sandbox home directory. */
136
- async stop() {
137
- if (this.activeFallback) {
138
- await this.activeFallback.stop?.();
139
- this.status = this.activeFallback.status;
140
- return;
141
- }
142
- if (this.status === "stopped" || this.status === "destroyed")
143
- return;
144
- this.status = "stopping";
145
- try {
146
- await this.mutate("stop");
147
- this.status = "stopped";
148
- }
149
- catch (caught) {
150
- if (isStatus(caught, 404)) {
151
- this.status = "stopped";
152
- return;
153
- }
154
- this.status = "error";
155
- this.error = errorUtils.errorMessage(caught);
156
- throw caught;
157
- }
158
- }
159
- /** Permanently delete the sandbox and its persisted home directory. */
160
- async destroy() {
161
- if (this.activeFallback) {
162
- await this.activeFallback.destroy?.();
163
- this.status = this.activeFallback.status;
164
- return;
165
- }
166
- if (this.status === "destroyed")
167
- return;
168
- this.status = "destroying";
169
- try {
170
- await this.request(`${this.resourcePath}`, "DELETE", z.object({}).passthrough());
171
- this.status = "destroyed";
172
- }
173
- catch (caught) {
174
- if (isStatus(caught, 404)) {
175
- this.status = "destroyed";
176
- return;
177
- }
178
- this.status = "error";
179
- this.error = errorUtils.errorMessage(caught);
180
- throw caught;
181
- }
182
- }
183
- /** Execute one foreground shell command in the remote sandbox. */
184
- async executeCommand(command, args = [], options = {}) {
185
- await this.startWithSignal(options.abortSignal);
186
- if (this.activeFallback) {
187
- return this.executeFallback(command, args, options);
188
- }
189
- const timeout = options.timeout ?? this.commandTimeoutMs;
190
- const script = commandScript(command, args, options.cwd);
191
- const started = performance.now();
192
- let response;
193
- try {
194
- response = await this.request(`${SANDBOX_EXEC_API_PATH}/${encodeURIComponent(this.id)}/exec-sync`, "POST", ExecuteResponseSchema, {
195
- payload: {
196
- cmd: "/bin/bash",
197
- args: ["-lc", script],
198
- envs: definedEnvironment(options.env),
199
- execution_timeout: `${Math.max(1, Math.ceil(timeout / 1_000))}s`,
200
- },
201
- signal: options.abortSignal,
202
- });
203
- }
204
- catch (caught) {
205
- if (this.fallbackConfig === false || !isDatabricksSandboxUnavailable(caught))
206
- throw caught;
207
- await this.activateFallback(caught);
208
- return this.executeFallback(command, args, options);
209
- }
210
- const stdout = response.stdout ?? "";
211
- const stderr = response.stderr ?? "";
212
- options.onStdout?.(stdout);
213
- options.onStderr?.(stderr);
214
- this.lastUsedAt = new Date();
215
- const timedOut = response.status === "EXECUTE_COMMAND_STATUS_TIMED_OUT";
216
- const exitCode = response.exit_code ?? -1;
217
- return {
218
- command,
219
- args,
220
- success: response.status === "EXECUTE_COMMAND_STATUS_COMPLETED" && exitCode === 0,
221
- exitCode,
222
- stdout,
223
- stderr,
224
- executionTimeMs: performance.now() - started,
225
- ...(timedOut ? { timedOut: true, killed: true } : {}),
226
- ...(response.truncated
227
- ? {
228
- stdoutTruncated: true,
229
- stderrTruncated: true,
230
- }
231
- : {}),
232
- };
233
- }
234
- /** Activate the configured fallback once across concurrent command failures. */
235
- async activateFallback(caught) {
236
- if (this.activeFallback)
237
- return;
238
- if (this.fallbackPromise) {
239
- await this.fallbackPromise;
240
- return;
241
- }
242
- const pending = this.startFallback(caught);
243
- this.fallbackPromise = pending;
244
- try {
245
- await pending;
246
- }
247
- finally {
248
- if (this.fallbackPromise === pending)
249
- this.fallbackPromise = undefined;
250
- }
251
- }
252
- /** Start and publish the configured fallback after rechecking active state. */
253
- async startFallback(caught) {
254
- if (this.activeFallback)
255
- return;
256
- if (this.fallbackConfig === false)
257
- throw caught;
258
- const fallback = resolveFallback(this.fallbackConfig);
259
- logger.warn("Databricks Sandbox unavailable; using fallback", {
260
- sandboxId: this.id,
261
- fallback: fallback.provider,
262
- error: errorUtils.errorMessage(caught),
263
- });
264
- await fallback.start?.();
265
- this.activeFallback = fallback;
266
- this.status = fallback.status;
267
- this.error = fallback.error;
268
- }
269
- /** Execute through the active fallback or return an unsupported result. */
270
- executeFallback(command, args, options) {
271
- const fallback = this.activeFallback;
272
- if (!fallback)
273
- throw new Error("Fallback sandbox is not active");
274
- if (fallback.executeCommand)
275
- return fallback.executeCommand(command, args, options);
276
- return Promise.resolve({
277
- command,
278
- args,
279
- success: false,
280
- exitCode: 1,
281
- stdout: "",
282
- stderr: `Fallback sandbox ${fallback.provider} does not support command execution.`,
283
- executionTimeMs: 0,
284
- });
285
- }
286
- /** Whether the adapter currently knows the remote sandbox to be running. */
287
- async isReady() {
288
- if (this.activeFallback) {
289
- return this.activeFallback.isReady?.() ?? this.activeFallback.status === "running";
290
- }
291
- if (this.status === "running")
292
- return true;
293
- try {
294
- const sandbox = await this.get();
295
- this.status =
296
- sandbox.status?.state === "SANDBOX_STATE_RUNNING" ? "running" : remoteStatus(sandbox);
297
- return this.status === "running";
298
- }
299
- catch (caught) {
300
- if (isStatus(caught, 404))
301
- return false;
302
- throw caught;
303
- }
304
- }
305
- /** Report Mastra-facing sandbox metadata. */
306
- async getInfo() {
307
- if (this.activeFallback) {
308
- return ((await this.activeFallback.getInfo?.()) ?? {
309
- id: this.activeFallback.id,
310
- name: this.activeFallback.name,
311
- provider: this.activeFallback.provider,
312
- status: this.activeFallback.status,
313
- createdAt: this.createdAt,
314
- });
315
- }
316
- const sandbox = await this.get();
317
- this.status = remoteStatus(sandbox);
318
- return {
319
- id: this.id,
320
- name: sandbox.display_name ?? this.name,
321
- provider: this.provider,
322
- status: this.status,
323
- createdAt: this.remoteCreatedAt ?? this.createdAt,
324
- ...(this.lastUsedAt ? { lastUsedAt: this.lastUsedAt } : {}),
325
- metadata: {
326
- resourceName: sandbox.name,
327
- remoteState: sandbox.status?.state,
328
- updateTime: sandbox.update_time,
329
- },
330
- };
331
- }
332
- /** Explain the Databricks execution boundary to the agent. */
333
- getInstructions() {
334
- return [
335
- "Commands run in a persistent Databricks serverless sandbox, not in the App container.",
336
- "Use shell commands normally. The sandbox home directory survives inactivity stops.",
337
- "If Databricks Sandbox is unavailable, commands fall back to Pydantic Monty and must be Python source.",
338
- "Databricks Workspace filesystem mounts remain separate unless a command copies data explicitly.",
339
- ].join(" ");
340
- }
341
- get resourcePath() {
342
- return `${SANDBOX_API_PATH}/${encodeURIComponent(this.id)}`;
343
- }
344
- async getOrCreate(signal) {
345
- try {
346
- return await this.get(signal);
347
- }
348
- catch (caught) {
349
- if (!isStatus(caught, 404))
350
- throw caught;
351
- }
352
- try {
353
- const sandbox = await this.request(SANDBOX_API_PATH, "POST", SandboxResponseSchema, {
354
- query: { sandbox_id: this.id },
355
- payload: {
356
- display_name: this.displayName,
357
- spec: {
358
- compute: {
359
- inactivity_timeout: this.inactivityTimeout,
360
- },
361
- },
362
- },
363
- signal,
364
- });
365
- this.rememberCreatedAt(sandbox.create_time);
366
- return sandbox;
367
- }
368
- catch (caught) {
369
- if (!isStatus(caught, 409))
370
- throw caught;
371
- return this.get(signal);
372
- }
373
- }
374
- async get(signal) {
375
- const sandbox = await this.request(this.resourcePath, "GET", SandboxResponseSchema, {
376
- signal,
377
- });
378
- this.rememberCreatedAt(sandbox.create_time);
379
- return sandbox;
380
- }
381
- mutate(operation, signal) {
382
- return this.request(`${this.resourcePath}/${operation}`, "POST", SandboxResponseSchema, {
383
- signal,
384
- });
385
- }
386
- async waitForState(expected, signal) {
387
- const deadline = Date.now() + this.startupTimeoutMs;
388
- while (Date.now() < deadline) {
389
- const sandbox = await this.get(signal);
390
- if (sandbox.status?.state === expected)
391
- return sandbox;
392
- await asyncUtils.sleep(SANDBOX_POLL_INTERVAL_MS, signal);
393
- }
394
- throw new Error(`Databricks sandbox ${this.id} did not reach ${expected} within ${this.startupTimeoutMs}ms`);
395
- }
396
- rememberCreatedAt(value) {
397
- if (!value)
398
- return;
399
- const parsed = new Date(value);
400
- if (!Number.isNaN(parsed.getTime()))
401
- this.remoteCreatedAt = parsed;
402
- }
403
- async request(path, method, schema, options = {}) {
404
- const response = await this.client.apiClient.request({
405
- path,
406
- method,
407
- query: options.query,
408
- headers: new Headers({
409
- Accept: "application/json",
410
- ...(options.payload === undefined ? {} : { "Content-Type": "application/json" }),
411
- }),
412
- raw: false,
413
- ...(options.payload === undefined ? {} : { payload: options.payload }),
414
- }, options.signal ? databricks.toContext(options.signal) : undefined);
415
- return schema.parse(response);
416
- }
417
- }
418
- function commandScript(command, args, cwd) {
419
- const invocation = args.length ? [command, ...args].map(shellQuote).join(" ") : command;
420
- return cwd ? `cd -- ${shellQuote(cwd)} && ${invocation}` : invocation;
421
- }
422
- function shellQuote(value) {
423
- return `'${value.replaceAll("'", "'\\''")}'`;
424
- }
425
- function definedEnvironment(input) {
426
- return Object.fromEntries(Object.entries(input ?? {}).filter((entry) => entry[1] !== undefined));
427
- }
428
- function isStatus(caught, status) {
429
- return errorUtils.errorContext(caught).statusCode === status;
430
- }
431
- function remoteStatus(sandbox) {
432
- switch (sandbox.status?.state) {
433
- case "SANDBOX_STATE_RUNNING":
434
- return "running";
435
- case "SANDBOX_STATE_STOPPED":
436
- return "stopped";
437
- case "SANDBOX_STATE_STOPPING":
438
- return "stopping";
439
- case "SANDBOX_STATE_PENDING":
440
- return "starting";
441
- default:
442
- return "pending";
443
- }
444
- }
445
- function resolveFallback(configured) {
446
- if (typeof configured === "object" && "provider" in configured && "status" in configured) {
447
- return configured;
448
- }
449
- return new MontySandbox(configured === "monty" ? {} : configured);
450
- }
451
- function isDatabricksSandboxUnavailable(caught) {
452
- const context = errorUtils.errorContext(caught);
453
- return (context.statusCode === 404 ||
454
- context.hasMessage("requested", "api", "not", "available") ||
455
- context.hasMessage("feature", "disabled") ||
456
- context.hasMessage("sandbox", "not", "enabled") ||
457
- context.hasMessage("preview", "not", "enabled") ||
458
- context.hasMessage("preview", "unavailable") ||
459
- context.hasMessage("preview", "disabled"));
460
- }
461
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2FuZGJveC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zYW5kYm94LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7R0FTRztBQUdILE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxHQUFHLEVBQUUsV0FBVyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFTbEYsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLEtBQUssQ0FBQztBQUN4QixPQUFPLEVBQUUsWUFBWSxFQUE0QixNQUFNLG9CQUFvQixDQUFDO0FBRTVFLE1BQU0sZ0JBQWdCLEdBQUcsb0JBQW9CLENBQUM7QUFDOUMsTUFBTSxxQkFBcUIsR0FBRyxpQ0FBaUMsQ0FBQztBQUNoRSxNQUFNLDBCQUEwQixHQUFHLE1BQU0sQ0FBQztBQUMxQyxNQUFNLDBCQUEwQixHQUFHLE9BQU8sQ0FBQztBQUMzQyxNQUFNLDBCQUEwQixHQUFHLE1BQU0sQ0FBQztBQUMxQyxNQUFNLHdCQUF3QixHQUFHLEdBQUcsQ0FBQztBQUNyQyxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUM7QUFFNUMsTUFBTSxrQkFBa0IsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDO0lBQ2xDLEtBQUssRUFBRSxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxFQUFFO0NBQzdCLENBQUMsQ0FBQztBQUVILE1BQU0scUJBQXFCLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQztJQUNyQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRTtJQUNoQixZQUFZLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRTtJQUNuQyxXQUFXLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRTtJQUNsQyxXQUFXLEVBQUUsQ0FBQyxDQUFD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QUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQztBQUNwRSxDQUFDO0FBRUQsU0FBUyw4QkFBOEIsQ0FBQyxNQUFlO0lBQ3JELE1BQU0sT0FBTyxHQUFHLFVBQVUsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDaEQsT0FBTyxDQUNMLE9BQU8sQ0FBQyxVQUFVLEtBQUssR0FBRztRQUMxQixPQUFPLENBQUMsVUFBVSxDQUFDLFdBQVcsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLFdBQVcsQ0FBQztRQUMxRCxPQUFPLENBQUMsVUFBVSxDQUFDLFNBQVMsRUFBRSxVQUFVLENBQUM7UUFDekMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxTQUFTLEVBQUUsS0FBSyxFQUFFLFNBQVMsQ0FBQztRQUMvQyxPQUFPLENBQUMsVUFBVSxDQUFDLFNBQVMsRUFBRSxLQUFLLEVBQUUsU0FBUyxDQUFDO1FBQy9DLE9BQU8sQ0FBQyxVQUFVLENBQUMsU0FBUyxFQUFFLGFBQWEsQ0FBQztRQUM1QyxPQUFPLENBQUMsVUFBVSxDQUFDLFNBQVMsRUFBRSxVQUFVLENBQUMsQ0FDMUMsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIERhdGFicmlja3MgU2FuZGJveCBhZGFwdGVyIGZvciBNYXN0cmEgd29ya3NwYWNlcy5cbiAqXG4gKiBJbXBsZW1lbnRzIE1hc3RyYSdzIGZvcmVncm91bmQgY29tbWFuZCBzdXJmYWNlIG92ZXIgdGhlIERhdGFicmlja3MgU2FuZGJveFxuICogUkVTVCBBUEkuIFNhbmRib3hlcyBhcmUgY3JlYXRlZCBsYXppbHksIHJldGFpbiB0aGVpciBob21lIGRpcmVjdG9yeSBhY3Jvc3NcbiAqIGluYWN0aXZpdHkgc3RvcHMsIGFuZCBleGVjdXRlIHVudHJ1c3RlZCBzaGVsbCBjb21tYW5kcyBvdXRzaWRlIHRoZSBBcHBcbiAqIGNvbnRhaW5lci5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHR5cGUgeyBXb3Jrc3BhY2VDbGllbnQgfSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0XCI7XG5pbXBvcnQgeyBkYXRhYnJpY2tzIH0gZnJvbSBcIkBkYngtdG9vbHMvYXBwa2l0XCI7XG5pbXBvcnQgeyBhc3luY1V0aWxzLCBlcnJvclV0aWxzLCBsb2csIHN0cmluZ1V0aWxzIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB0eXBlIHsgUmVxdWVzdENvbnRleHQgfSBmcm9tIFwiQG1hc3RyYS9jb3JlL3JlcXVlc3QtY29udGV4dFwiO1xuaW1wb3J0IHR5cGUge1xuICBDb21tYW5kUmVzdWx0LFxuICBFeGVjdXRlQ29tbWFuZE9wdGlvbnMsXG4gIFByb3ZpZGVyU3RhdHVzLFxuICBTYW5kYm94SW5mbyxcbiAgV29ya3NwYWNlU2FuZGJveCxcbn0gZnJvbSBcIkBtYXN0cmEvY29yZS93b3Jrc3BhY2VcIjtcbmltcG9ydCB7IHogfSBmcm9tIFwiem9kXCI7XG5pbXBvcnQgeyBNb250eVNhbmRib3gsIHR5cGUgTW9udHlTYW5kYm94T3B0aW9ucyB9IGZyb20gXCIuL21vbnR5LXNhbmRib3gudHNcIjtcblxuY29uc3QgU0FOREJPWF9BUElfUEFUSCA9IFwiL2FwaS8yLjAvc2FuZGJveGVzXCI7XG5jb25zdCBTQU5EQk9YX0VYRUNfQVBJX1BBVEggPSBcIi9hcGkvMi4wL3NhbmRib3gtZXhlYy9zYW5kYm94ZXNcIjtcbmNvbnN0IERFRkFVTFRfSU5BQ1RJVklUWV9USU1FT1VUID0gXCI5MDBzXCI7XG5jb25zdCBERUZBVUxUX1NUQVJUVVBfVElNRU9VVF9NUyA9IDEyMF8wMDA7XG5jb25zdCBERUZBVUxUX0NPTU1BTkRfVElNRU9VVF9NUyA9IDMwXzAwMDtcbmNvbnN0IFNBTkRCT1hfUE9MTF9JTlRFUlZBTF9NUyA9IDUwMDtcbmNvbnN0IGxvZ2dlciA9IGxvZy5sb2dnZXIoXCJtYXN0cmEvc2FuZGJveFwiKTtcblxuY29uc3QgU2FuZGJveFN0YXRlU2NoZW1hID0gei5vYmplY3Qoe1xuICBzdGF0ZTogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxufSk7XG5cbmNvbnN0IFNhbmRib3hSZXNwb25zZVNjaGVtYSA9IHoub2JqZWN0KHtcbiAgbmFtZTogei5zdHJpbmcoKSxcbiAgZGlzcGxheV9uYW1lOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG4gIGNyZWF0ZV90aW1lOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG4gIHVwZGF0ZV90aW1lOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG4gIHN0YXR1czogU2FuZGJveFN0YXRlU2NoZW1hLm9wdGlvbmFsKCksXG59KTtcblxuY29uc3QgRXhlY3V0ZVJlc3BvbnNlU2NoZW1hID0gei5vYmplY3Qoe1xuICBleGl0X2NvZGU6IHoubnVtYmVyKCkuaW50KCkub3B0aW9uYWwoKSxcbiAgc3RhdHVzOiB6LnN0cmluZygpLFxuICBzdGRvdXQ6IHouc3RyaW5nKCkub3B0aW9uYWwoKSxcbiAgc3RkZXJyOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG4gIGNvbW1hbmRfaWQ6IHouc3RyaW5nKCkub3B0aW9uYWwoKSxcbiAgdHJ1bmNhdGVkOiB6LmJvb2xlYW4oKS5vcHRpb25hbCgpLFxufSk7XG5cbi8qKiBPcHRpb25zIGZvciBvbmUgRGF0YWJyaWNrcy1iYWNrZWQgTWFzdHJhIHNhbmRib3guICovXG5leHBvcnQgaW50ZXJmYWNlIERhdGFicmlja3NTYW5kYm94T3B0aW9ucyB7XG4gIC8qKiBBcHBLaXQgd29ya3NwYWNlIGNsaWVudCB1c2VkIGZvciBldmVyeSBzYW5kYm94IEFQSSBjYWxsLiAqL1xuICBjbGllbnQ6IFdvcmtzcGFjZUNsaWVudDtcbiAgLyoqIFJlc291cmNlIGlkLCB3aXRoIG9yIHdpdGhvdXQgdGhlIGBzYW5kYm94ZXMvYCBwcmVmaXguICovXG4gIHNhbmRib3hJZDogc3RyaW5nO1xuICAvKiogSHVtYW4tcmVhZGFibGUgRGF0YWJyaWNrcyBsYWJlbC4gKi9cbiAgZGlzcGxheU5hbWU/OiBzdHJpbmc7XG4gIC8qKiBTZXJ2ZXItc2lkZSBpZGxlIHRpbWVvdXQgaW4gcHJvdG9idWYgZHVyYXRpb24gZm9ybS4gRGVmYXVsdHMgdG8gYDkwMHNgLiAqL1xuICBpbmFjdGl2aXR5VGltZW91dD86IHN0cmluZztcbiAgLyoqIE1heGltdW0gdGltZSB0byB3YWl0IGZvciB0aGUgc2FuZGJveCB0byBiZWNvbWUgcnVubmFibGUuICovXG4gIHN0YXJ0dXBUaW1lb3V0TXM/OiBudW1iZXI7XG4gIC8qKiBEZWZhdWx0IGNvbW1hbmQgdGltZW91dC4gUGVyLWNhbGwgYG9wdGlvbnMudGltZW91dGAgd2lucy4gKi9cbiAgY29tbWFuZFRpbWVvdXRNcz86IG51bWJlcjtcbiAgLyoqXG4gICAqIFByb3ZpZGVyIHVzZWQgb25seSB3aGVuIERhdGFicmlja3MgU2FuZGJveCBpcyBkZWZpbml0aXZlbHkgdW5hdmFpbGFibGUuXG4gICAqIERpc2FibGVkIGJ5IGRlZmF1bHQuIFBhc3MgYFwibW9udHlcImAsIE1vbnR5IG9wdGlvbnMsIG9yIGFub3RoZXIgTWFzdHJhXG4gICAqIHNhbmRib3ggdG8gZW5hYmxlIGEgZmFsbGJhY2sgZXhwbGljaXRseS5cbiAgICovXG4gIGZhbGxiYWNrPzogZmFsc2UgfCBcIm1vbnR5XCIgfCBNb250eVNhbmRib3hPcHRpb25zIHwgV29ya3NwYWNlU2FuZGJveDtcbn1cblxuLyoqIERhdGFicmlja3Mgb3B0aW9ucyBhY2NlcHRlZCBieSB0aGUgaGlnaGVyLWxldmVsIHdvcmtzcGFjZSBmYWN0b3J5LiAqL1xuZXhwb3J0IGludGVyZmFjZSBEYXRhYnJpY2tzV29ya3NwYWNlU2FuZGJveE9wdGlvbnMgZXh0ZW5kcyBPbWl0PFxuICBEYXRhYnJpY2tzU2FuZGJveE9wdGlvbnMsXG4gIFwiY2xpZW50XCIgfCBcInNhbmRib3hJZFwiXG4+IHtcbiAgLyoqIFByb3ZpZGVyIGRpc2NyaW1pbmF0b3IuIERlZmF1bHRzIHRvIGBkYXRhYnJpY2tzYC4gKi9cbiAgcHJvdmlkZXI/OiBcImRhdGFicmlja3NcIjtcbiAgLyoqXG4gICAqIENyZWRlbnRpYWwgc291cmNlLiBEZWZhdWx0cyB0byB0aGUgYWN0aXZlIHJlcXVlc3QncyBBcHBLaXQgY2xpZW50LCB3aGljaFxuICAgKiB1c2VzIE9CTyBjcmVkZW50aWFscyB3aGVuIHRoZSB0dXJuIHJ1bnMgaW4gYSB1c2VyIGNvbnRleHQuXG4gICAqL1xuICBjbGllbnQ/OiBXb3Jrc3BhY2VDbGllbnQgfCAoKGNvbnRleHQ6IHsgcmVxdWVzdENvbnRleHQ6IFJlcXVlc3RDb250ZXh0IH0pID0+IFdvcmtzcGFjZUNsaWVudCk7XG4gIC8qKlxuICAgKiBGaXhlZCBpZCBvciBwZXItcmVxdWVzdCByZXNvbHZlci4gT21pdCB0byBkZXJpdmUgYSBzdGFibGUsIG9wYXF1ZSBpZCBmcm9tXG4gICAqIHRoZSB3b3Jrc3BhY2UgYW5kIGF0dHJpYnV0ZWQgdXNlci5cbiAgICovXG4gIHNhbmRib3hJZD86IHN0cmluZyB8ICgoY29udGV4dDogeyByZXF1ZXN0Q29udGV4dDogUmVxdWVzdENvbnRleHQgfSkgPT4gc3RyaW5nKTtcbn1cblxuLyoqIE1hc3RyYSBzYW5kYm94IGJhY2tlZCBieSBEYXRhYnJpY2tzIHNlcnZlcmxlc3MgU2FuZGJveCBjb21wdXRlLiAqL1xuZXhwb3J0IGNsYXNzIERhdGFicmlja3NTYW5kYm94IGltcGxlbWVudHMgV29ya3NwYWNlU2FuZGJveCB7XG4gIHJlYWRvbmx5IGlkOiBzdHJpbmc7XG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgc3RhdHVzOiBQcm92aWRlclN0YXR1cyA9IFwicGVuZGluZ1wiO1xuICBlcnJvcj86IHN0cmluZztcblxuICBwcml2YXRlIHJlYWRvbmx5IGNsaWVudDogV29ya3NwYWNlQ2xpZW50O1xuICBwcml2YXRlIHJlYWRvbmx5IGRpc3BsYXlOYW1lOiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgaW5hY3Rpdml0eVRpbWVvdXQ6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBzdGFydHVwVGltZW91dE1zOiBudW1iZXI7XG4gIHByaXZhdGUgcmVhZG9ubHkgY29tbWFuZFRpbWVvdXRNczogbnVtYmVyO1xuICBwcml2YXRlIHJlYWRvbmx5IGZhbGxiYWNrQ29uZmlnOiBFeGNsdWRlPERhdGFicmlja3NTYW5kYm94T3B0aW9uc1tcImZhbGxiYWNrXCJdLCB1bmRlZmluZWQ+O1xuICBwcml2YXRlIHJlYWRvbmx5IGNyZWF0ZWRBdCA9IG5ldyBEYXRlKCk7XG4gIHByaXZhdGUgcmVtb3RlQ3JlYXRlZEF0PzogRGF0ZTtcbiAgcHJpdmF0ZSBsYXN0VXNlZEF0PzogRGF0ZTtcbiAgcHJpdmF0ZSBhY3RpdmVGYWxsYmFjaz86IFdvcmtzcGFjZVNhbmRib3g7XG4gIHByaXZhdGUgZmFsbGJhY2tQcm9taXNlPzogUHJvbWlzZTx2b2lkPjtcbiAgcHJpdmF0ZSBzdGFydFByb21pc2U/OiBQcm9taXNlPHZvaWQ+O1xuXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IERhdGFicmlja3NTYW5kYm94T3B0aW9ucykge1xuICAgIGNvbnN0IGlkID0gc3RyaW5nVXRpbHMudHJpbVRvTnVsbChvcHRpb25zLnNhbmRib3hJZC5yZXBsYWNlKC9ec2FuZGJveGVzXFwvLywgXCJcIikpO1xuICAgIGlmICghaWQpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJEYXRhYnJpY2tzIHNhbmRib3ggaWQgbXVzdCBub3QgYmUgYmxhbmtcIik7XG4gICAgdGhpcy5pZCA9IGlkO1xuICAgIHRoaXMubmFtZSA9IG9wdGlvbnMuZGlzcGxheU5hbWU/LnRyaW0oKSB8fCBgTWFzdHJhIHNhbmRib3ggJHtpZH1gO1xuICAgIHRoaXMuY2xpZW50ID0gb3B0aW9ucy5jbGllbnQ7XG4gICAgdGhpcy5kaXNwbGF5TmFtZSA9IHRoaXMubmFtZTtcbiAgICB0aGlzLmluYWN0aXZpdHlUaW1lb3V0ID0gb3B0aW9ucy5pbmFjdGl2aXR5VGltZW91dCA/PyBERUZBVUxUX0lOQUNUSVZJVFlfVElNRU9VVDtcbiAgICB0aGlzLnN0YXJ0dXBUaW1lb3V0TXMgPSBvcHRpb25zLnN0YXJ0dXBUaW1lb3V0TXMgPz8gREVGQVVMVF9TVEFSVFVQX1RJTUVPVVRfTVM7XG4gICAgdGhpcy5jb21tYW5kVGltZW91dE1zID0gb3B0aW9ucy5jb21tYW5kVGltZW91dE1zID8/IERFRkFVTFRfQ09NTUFORF9USU1FT1VUX01TO1xuICAgIHRoaXMuZmFsbGJhY2tDb25maWcgPSBvcHRpb25zLmZhbGxiYWNrID8/IGZhbHNlO1xuICB9XG5cbiAgZ2V0IHByb3ZpZGVyKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuYWN0aXZlRmFsbGJhY2s/LnByb3ZpZGVyID8/IFwiZGF0YWJyaWNrc1wiO1xuICB9XG5cbiAgLyoqIEVuc3VyZSB0aGUgcmVtb3RlIHNhbmRib3ggZXhpc3RzIGFuZCBoYXMgcmVhY2hlZCBpdHMgcnVubmluZyBzdGF0ZS4gKi9cbiAgYXN5bmMgc3RhcnQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5zdGFydFdpdGhTaWduYWwoKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgc3RhcnRXaXRoU2lnbmFsKHNpZ25hbD86IEFib3J0U2lnbmFsKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuc3RhdHVzID09PSBcInJ1bm5pbmdcIikgcmV0dXJuO1xuICAgIGlmICh0aGlzLnN0YXJ0UHJvbWlzZSkge1xuICAgICAgYXdhaXQgdGhpcy5zdGFydFByb21pc2U7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHBlbmRpbmcgPSB0aGlzLnBlcmZvcm1TdGFydChzaWduYWwpO1xuICAgIHRoaXMuc3RhcnRQcm9taXNlID0gcGVuZGluZztcbiAgICB0cnkge1xuICAgICAgYXdhaXQgcGVuZGluZztcbiAgICB9IGZpbmFsbHkge1xuICAgICAgaWYgKHRoaXMuc3RhcnRQcm9taXNlID09PSBwZW5kaW5nKSB0aGlzLnN0YXJ0UHJvbWlzZSA9IHVuZGVmaW5lZDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHBlcmZvcm1TdGFydChzaWduYWw/OiBBYm9ydFNpZ25hbCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLmFjdGl2ZUZhbGxiYWNrKSB7XG4gICAgICBhd2FpdCB0aGlzLmFjdGl2ZUZhbGxiYWNrLnN0YXJ0Py4oKTtcbiAgICAgIHRoaXMuc3RhdHVzID0gdGhpcy5hY3RpdmVGYWxsYmFjay5zdGF0dXM7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuc3RhdHVzID0gXCJzdGFydGluZ1wiO1xuICAgIHRoaXMuZXJyb3IgPSB1bmRlZmluZWQ7XG4gICAgdHJ5IHtcbiAgICAgIGxldCBzYW5kYm94ID0gYXdhaXQgdGhpcy5nZXRPckNyZWF0ZShzaWduYWwpO1xuICAgICAgaWYgKHNhbmRib3guc3RhdHVzPy5zdGF0ZSA9PT0gXCJTQU5EQk9YX1NUQVRFX1NUT1BQRURcIikge1xuICAgICAgICBzYW5kYm94ID0gYXdhaXQgdGhpcy5tdXRhdGUoXCJzdGFydFwiLCBzaWduYWwpO1xuICAgICAgfVxuICAgICAgaWYgKHNhbmRib3guc3RhdHVzPy5zdGF0ZSA9PT0gXCJTQU5EQk9YX1NUQVRFX1NUT1BQSU5HXCIpIHtcbiAgICAgICAgYXdhaXQgdGhpcy53YWl0Rm9yU3RhdGUoXCJTQU5EQk9YX1NUQVRFX1NUT1BQRURcIiwgc2lnbmFsKTtcbiAgICAgICAgc2FuZGJveCA9IGF3YWl0IHRoaXMubXV0YXRlKFwic3RhcnRcIiwgc2lnbmFsKTtcbiAgICAgIH1cbiAgICAgIGlmIChzYW5kYm94LnN0YXR1cz8uc3RhdGUgIT09IFwiU0FOREJPWF9TVEFURV9SVU5OSU5HXCIpIHtcbiAgICAgICAgYXdhaXQgdGhpcy53YWl0Rm9yU3RhdGUoXCJTQU5EQk9YX1NUQVRFX1JVTk5JTkdcIiwgc2lnbmFsKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuc3RhdHVzID0gXCJydW5uaW5nXCI7XG4gICAgICB0aGlzLmxhc3RVc2VkQXQgPSBuZXcgRGF0ZSgpO1xuICAgIH0gY2F0Y2ggKGNhdWdodCkge1xuICAgICAgaWYgKHRoaXMuZmFsbGJhY2tDb25maWcgIT09IGZhbHNlICYmIGlzRGF0YWJyaWNrc1NhbmRib3hVbmF2YWlsYWJsZShjYXVnaHQpKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuYWN0aXZhdGVGYWxsYmFjayhjYXVnaHQpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB0aGlzLnN0YXR1cyA9IFwiZXJyb3JcIjtcbiAgICAgIHRoaXMuZXJyb3IgPSBlcnJvclV0aWxzLmVycm9yTWVzc2FnZShjYXVnaHQpO1xuICAgICAgdGhyb3cgY2F1Z2h0O1xuICAgIH1cbiAgfVxuXG4gIC8qKiBEYXRhYnJpY2tzIGhvbWUgcGVyc2lzdGVuY2UgaXMgbm90IGEgY2xvbmVhYmxlIE1hc3RyYSBjaGVja3BvaW50LiAqL1xuICBhc3luYyBzbmFwc2hvdCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLmFjdGl2ZUZhbGxiYWNrPy5zbmFwc2hvdCgpO1xuICB9XG5cbiAgZ2V0IHN1cHBvcnRzQ2hlY2twb2ludHMoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuYWN0aXZlRmFsbGJhY2s/LnN1cHBvcnRzQ2hlY2twb2ludHMgPz8gZmFsc2U7XG4gIH1cblxuICAvKiogU3RvcCBjb21wdXRlIHdoaWxlIHByZXNlcnZpbmcgdGhlIHNhbmRib3ggaG9tZSBkaXJlY3RvcnkuICovXG4gIGFzeW5jIHN0b3AoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuYWN0aXZlRmFsbGJhY2spIHtcbiAgICAgIGF3YWl0IHRoaXMuYWN0aXZlRmFsbGJhY2suc3RvcD8uKCk7XG4gICAgICB0aGlzLnN0YXR1cyA9IHRoaXMuYWN0aXZlRmFsbGJhY2suc3RhdHVzO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAodGhpcy5zdGF0dXMgPT09IFwic3RvcHBlZFwiIHx8IHRoaXMuc3RhdHVzID09PSBcImRlc3Ryb3llZFwiKSByZXR1cm47XG4gICAgdGhpcy5zdGF0dXMgPSBcInN0b3BwaW5nXCI7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMubXV0YXRlKFwic3RvcFwiKTtcbiAgICAgIHRoaXMuc3RhdHVzID0gXCJzdG9wcGVkXCI7XG4gICAgfSBjYXRjaCAoY2F1Z2h0KSB7XG4gICAgICBpZiAoaXNTdGF0dXMoY2F1Z2h0LCA0MDQpKSB7XG4gICAgICAgIHRoaXMuc3RhdHVzID0gXCJzdG9wcGVkXCI7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHRoaXMuc3RhdHVzID0gXCJlcnJvclwiO1xuICAgICAgdGhpcy5lcnJvciA9IGVycm9yVXRpbHMuZXJyb3JNZXNzYWdlKGNhdWdodCk7XG4gICAgICB0aHJvdyBjYXVnaHQ7XG4gICAgfVxuICB9XG5cbiAgLyoqIFBlcm1hbmVudGx5IGRlbGV0ZSB0aGUgc2FuZGJveCBhbmQgaXRzIHBlcnNpc3RlZCBob21lIGRpcmVjdG9yeS4gKi9cbiAgYXN5bmMgZGVzdHJveSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5hY3RpdmVGYWxsYmFjaykge1xuICAgICAgYXdhaXQgdGhpcy5hY3RpdmVGYWxsYmFjay5kZXN0cm95Py4oKTtcbiAgICAgIHRoaXMuc3RhdHVzID0gdGhpcy5hY3RpdmVGYWxsYmFjay5zdGF0dXM7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICh0aGlzLnN0YXR1cyA9PT0gXCJkZXN0cm95ZWRcIikgcmV0dXJuO1xuICAgIHRoaXMuc3RhdHVzID0gXCJkZXN0cm95aW5nXCI7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMucmVxdWVzdChgJHt0aGlzLnJlc291cmNlUGF0aH1gLCBcIkRFTEVURVwiLCB6Lm9iamVjdCh7fSkucGFzc3Rocm91Z2goKSk7XG4gICAgICB0aGlzLnN0YXR1cyA9IFwiZGVzdHJveWVkXCI7XG4gICAgfSBjYXRjaCAoY2F1Z2h0KSB7XG4gICAgICBpZiAoaXNTdGF0dXMoY2F1Z2h0LCA0MDQpKSB7XG4gICAgICAgIHRoaXMuc3RhdHVzID0gXCJkZXN0cm95ZWRcIjtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhpcy5zdGF0dXMgPSBcImVycm9yXCI7XG4gICAgICB0aGlzLmVycm9yID0gZXJyb3JVdGlscy5lcnJvck1lc3NhZ2UoY2F1Z2h0KTtcbiAgICAgIHRocm93IGNhdWdodDtcbiAgICB9XG4gIH1cblxuICAvKiogRXhlY3V0ZSBvbmUgZm9yZWdyb3VuZCBzaGVsbCBjb21tYW5kIGluIHRoZSByZW1vdGUgc2FuZGJveC4gKi9cbiAgYXN5bmMgZXhlY3V0ZUNvbW1hbmQoXG4gICAgY29tbWFuZDogc3RyaW5nLFxuICAgIGFyZ3M6IHN0cmluZ1tdID0gW10sXG4gICAgb3B0aW9uczogRXhlY3V0ZUNvbW1hbmRPcHRpb25zID0ge30sXG4gICk6IFByb21pc2U8Q29tbWFuZFJlc3VsdD4ge1xuICAgIGF3YWl0IHRoaXMuc3RhcnRXaXRoU2lnbmFsKG9wdGlvbnMuYWJvcnRTaWduYWwpO1xuICAgIGlmICh0aGlzLmFjdGl2ZUZhbGxiYWNrKSB7XG4gICAgICByZXR1cm4gdGhpcy5leGVjdXRlRmFsbGJhY2soY29tbWFuZCwgYXJncywgb3B0aW9ucyk7XG4gICAgfVxuICAgIGNvbnN0IHRpbWVvdXQgPSBvcHRpb25zLnRpbWVvdXQgPz8gdGhpcy5jb21tYW5kVGltZW91dE1zO1xuICAgIGNvbnN0IHNjcmlwdCA9IGNvbW1hbmRTY3JpcHQoY29tbWFuZCwgYXJncywgb3B0aW9ucy5jd2QpO1xuICAgIGNvbnN0IHN0YXJ0ZWQgPSBwZXJmb3JtYW5jZS5ub3coKTtcbiAgICBsZXQgcmVzcG9uc2U6IHouaW5mZXI8dHlwZW9mIEV4ZWN1dGVSZXNwb25zZVNjaGVtYT47XG4gICAgdHJ5IHtcbiAgICAgIHJlc3BvbnNlID0gYXdhaXQgdGhpcy5yZXF1ZXN0KFxuICAgICAgICBgJHtTQU5EQk9YX0VYRUNfQVBJX1BBVEh9LyR7ZW5jb2RlVVJJQ29tcG9uZW50KHRoaXMuaWQpfS9leGVjLXN5bmNgLFxuICAgICAgICBcIlBPU1RcIixcbiAgICAgICAgRXhlY3V0ZVJlc3BvbnNlU2NoZW1hLFxuICAgICAgICB7XG4gICAgICAgICAgcGF5bG9hZDoge1xuICAgICAgICAgICAgY21kOiBcIi9iaW4vYmFzaFwiLFxuICAgICAgICAgICAgYXJnczogW1wiLWxjXCIsIHNjcmlwdF0sXG4gICAgICAgICAgICBlbnZzOiBkZWZpbmVkRW52aXJvbm1lbnQob3B0aW9ucy5lbnYpLFxuICAgICAgICAgICAgZXhlY3V0aW9uX3RpbWVvdXQ6IGAke01hdGgubWF4KDEsIE1hdGguY2VpbCh0aW1lb3V0IC8gMV8wMDApKX1zYCxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHNpZ25hbDogb3B0aW9ucy5hYm9ydFNpZ25hbCxcbiAgICAgICAgfSxcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoY2F1Z2h0KSB7XG4gICAgICBpZiAodGhpcy5mYWxsYmFja0NvbmZpZyA9PT0gZmFsc2UgfHwgIWlzRGF0YWJyaWNrc1NhbmRib3hVbmF2YWlsYWJsZShjYXVnaHQpKSB0aHJvdyBjYXVnaHQ7XG4gICAgICBhd2FpdCB0aGlzLmFjdGl2YXRlRmFsbGJhY2soY2F1Z2h0KTtcbiAgICAgIHJldHVybiB0aGlzLmV4ZWN1dGVGYWxsYmFjayhjb21tYW5kLCBhcmdzLCBvcHRpb25zKTtcbiAgICB9XG4gICAgY29uc3Qgc3Rkb3V0ID0gcmVzcG9uc2Uuc3Rkb3V0ID8/IFwiXCI7XG4gICAgY29uc3Qgc3RkZXJyID0gcmVzcG9uc2Uuc3RkZXJyID8/IFwiXCI7XG4gICAgb3B0aW9ucy5vblN0ZG91dD8uKHN0ZG91dCk7XG4gICAgb3B0aW9ucy5vblN0ZGVycj8uKHN0ZGVycik7XG4gICAgdGhpcy5sYXN0VXNlZEF0ID0gbmV3IERhdGUoKTtcbiAgICBjb25zdCB0aW1lZE91dCA9IHJlc3BvbnNlLnN0YXR1cyA9PT0gXCJFWEVDVVRFX0NPTU1BTkRfU1RBVFVTX1RJTUVEX09VVFwiO1xuICAgIGNvbnN0IGV4aXRDb2RlID0gcmVzcG9uc2UuZXhpdF9jb2RlID8/IC0xO1xuICAgIHJldHVybiB7XG4gICAgICBjb21tYW5kLFxuICAgICAgYXJncyxcbiAgICAgIHN1Y2Nlc3M6IHJlc3BvbnNlLnN0YXR1cyA9PT0gXCJFWEVDVVRFX0NPTU1BTkRfU1RBVFVTX0NPTVBMRVRFRFwiICYmIGV4aXRDb2RlID09PSAwLFxuICAgICAgZXhpdENvZGUsXG4gICAgICBzdGRvdXQsXG4gICAgICBzdGRlcnIsXG4gICAgICBleGVjdXRpb25UaW1lTXM6IHBlcmZvcm1hbmNlLm5vdygpIC0gc3RhcnRlZCxcbiAgICAgIC4uLih0aW1lZE91dCA/IHsgdGltZWRPdXQ6IHRydWUsIGtpbGxlZDogdHJ1ZSB9IDoge30pLFxuICAgICAgLi4uKHJlc3BvbnNlLnRydW5jYXRlZFxuICAgICAgICA/IHtcbiAgICAgICAgICAgIHN0ZG91dFRydW5jYXRlZDogdHJ1ZSxcbiAgICAgICAgICAgIHN0ZGVyclRydW5jYXRlZDogdHJ1ZSxcbiAgICAgICAgICB9XG4gICAgICAgIDoge30pLFxuICAgIH07XG4gIH1cblxuICAvKiogQWN0aXZhdGUgdGhlIGNvbmZpZ3VyZWQgZmFsbGJhY2sgb25jZSBhY3Jvc3MgY29uY3VycmVudCBjb21tYW5kIGZhaWx1cmVzLiAqL1xuICBwcml2YXRlIGFzeW5jIGFjdGl2YXRlRmFsbGJhY2soY2F1Z2h0OiB1bmtub3duKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuYWN0aXZlRmFsbGJhY2spIHJldHVybjtcbiAgICBpZiAodGhpcy5mYWxsYmFja1Byb21pc2UpIHtcbiAgICAgIGF3YWl0IHRoaXMuZmFsbGJhY2tQcm9taXNlO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBwZW5kaW5nID0gdGhpcy5zdGFydEZhbGxiYWNrKGNhdWdodCk7XG4gICAgdGhpcy5mYWxsYmFja1Byb21pc2UgPSBwZW5kaW5nO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBwZW5kaW5nO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBpZiAodGhpcy5mYWxsYmFja1Byb21pc2UgPT09IHBlbmRpbmcpIHRoaXMuZmFsbGJhY2tQcm9taXNlID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBTdGFydCBhbmQgcHVibGlzaCB0aGUgY29uZmlndXJlZCBmYWxsYmFjayBhZnRlciByZWNoZWNraW5nIGFjdGl2ZSBzdGF0ZS4gKi9cbiAgcHJpdmF0ZSBhc3luYyBzdGFydEZhbGxiYWNrKGNhdWdodDogdW5rbm93bik6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLmFjdGl2ZUZhbGxiYWNrKSByZXR1cm47XG4gICAgaWYgKHRoaXMuZmFsbGJhY2tDb25maWcgPT09IGZhbHNlKSB0aHJvdyBjYXVnaHQ7XG4gICAgY29uc3QgZmFsbGJhY2sgPSByZXNvbHZlRmFsbGJhY2sodGhpcy5mYWxsYmFja0NvbmZpZyk7XG4gICAgbG9nZ2VyLndhcm4oXCJEYXRhYnJpY2tzIFNhbmRib3ggdW5hdmFpbGFibGU7IHVzaW5nIGZhbGxiYWNrXCIsIHtcbiAgICAgIHNhbmRib3hJZDogdGhpcy5pZCxcbiAgICAgIGZhbGxiYWNrOiBmYWxsYmFjay5wcm92aWRlcixcbiAgICAgIGVycm9yOiBlcnJvclV0aWxzLmVycm9yTWVzc2FnZShjYXVnaHQpLFxuICAgIH0pO1xuICAgIGF3YWl0IGZhbGxiYWNrLnN0YXJ0Py4oKTtcbiAgICB0aGlzLmFjdGl2ZUZhbGxiYWNrID0gZmFsbGJhY2s7XG4gICAgdGhpcy5zdGF0dXMgPSBmYWxsYmFjay5zdGF0dXM7XG4gICAgdGhpcy5lcnJvciA9IGZhbGxiYWNrLmVycm9yO1xuICB9XG5cbiAgLyoqIEV4ZWN1dGUgdGhyb3VnaCB0aGUgYWN0aXZlIGZhbGxiYWNrIG9yIHJldHVybiBhbiB1bnN1cHBvcnRlZCByZXN1bHQuICovXG4gIHByaXZhdGUgZXhlY3V0ZUZhbGxiYWNrKFxuICAgIGNvbW1hbmQ6IHN0cmluZyxcbiAgICBhcmdzOiBzdHJpbmdbXSxcbiAgICBvcHRpb25zOiBFeGVjdXRlQ29tbWFuZE9wdGlvbnMsXG4gICk6IFByb21pc2U8Q29tbWFuZFJlc3VsdD4ge1xuICAgIGNvbnN0IGZhbGxiYWNrID0gdGhpcy5hY3RpdmVGYWxsYmFjaztcbiAgICBpZiAoIWZhbGxiYWNrKSB0aHJvdyBuZXcgRXJyb3IoXCJGYWxsYmFjayBzYW5kYm94IGlzIG5vdCBhY3RpdmVcIik7XG4gICAgaWYgKGZhbGxiYWNrLmV4ZWN1dGVDb21tYW5kKSByZXR1cm4gZmFsbGJhY2suZXhlY3V0ZUNvbW1hbmQoY29tbWFuZCwgYXJncywgb3B0aW9ucyk7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICBjb21tYW5kLFxuICAgICAgYXJncyxcbiAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgZXhpdENvZGU6IDEsXG4gICAgICBzdGRvdXQ6IFwiXCIsXG4gICAgICBzdGRlcnI6IGBGYWxsYmFjayBzYW5kYm94ICR7ZmFsbGJhY2sucHJvdmlkZXJ9IGRvZXMgbm90IHN1cHBvcnQgY29tbWFuZCBleGVjdXRpb24uYCxcbiAgICAgIGV4ZWN1dGlvblRpbWVNczogMCxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKiBXaGV0aGVyIHRoZSBhZGFwdGVyIGN1cnJlbnRseSBrbm93cyB0aGUgcmVtb3RlIHNhbmRib3ggdG8gYmUgcnVubmluZy4gKi9cbiAgYXN5bmMgaXNSZWFkeSgpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBpZiAodGhpcy5hY3RpdmVGYWxsYmFjaykge1xuICAgICAgcmV0dXJuIHRoaXMuYWN0aXZlRmFsbGJhY2suaXNSZWFkeT8uKCkgPz8gdGhpcy5hY3RpdmVGYWxsYmFjay5zdGF0dXMgPT09IFwicnVubmluZ1wiO1xuICAgIH1cbiAgICBpZiAodGhpcy5zdGF0dXMgPT09IFwicnVubmluZ1wiKSByZXR1cm4gdHJ1ZTtcbiAgICB0cnkge1xuICAgICAgY29uc3Qgc2FuZGJveCA9IGF3YWl0IHRoaXMuZ2V0KCk7XG4gICAgICB0aGlzLnN0YXR1cyA9XG4gICAgICAgIHNhbmRib3guc3RhdHVzPy5zdGF0ZSA9PT0gXCJTQU5EQk9YX1NUQVRFX1JVTk5JTkdcIiA/IFwicnVubmluZ1wiIDogcmVtb3RlU3RhdHVzKHNhbmRib3gpO1xuICAgICAgcmV0dXJuIHRoaXMuc3RhdHVzID09PSBcInJ1bm5pbmdcIjtcbiAgICB9IGNhdGNoIChjYXVnaHQpIHtcbiAgICAgIGlmIChpc1N0YXR1cyhjYXVnaHQsIDQwNCkpIHJldHVybiBmYWxzZTtcbiAgICAgIHRocm93IGNhdWdodDtcbiAgICB9XG4gIH1cblxuICAvKiogUmVwb3J0IE1hc3RyYS1mYWNpbmcgc2FuZGJveCBtZXRhZGF0YS4gKi9cbiAgYXN5bmMgZ2V0SW5mbygpOiBQcm9taXNlPFNhbmRib3hJbmZvPiB7XG4gICAgaWYgKHRoaXMuYWN0aXZlRmFsbGJhY2spIHtcbiAgICAgIHJldHVybiAoXG4gICAgICAgIChhd2FpdCB0aGlzLmFjdGl2ZUZhbGxiYWNrLmdldEluZm8/LigpKSA/PyB7XG4gICAgICAgICAgaWQ6IHRoaXMuYWN0aXZlRmFsbGJhY2suaWQsXG4gICAgICAgICAgbmFtZTogdGhpcy5hY3RpdmVGYWxsYmFjay5uYW1lLFxuICAgICAgICAgIHByb3ZpZGVyOiB0aGlzLmFjdGl2ZUZhbGxiYWNrLnByb3ZpZGVyLFxuICAgICAgICAgIHN0YXR1czogdGhpcy5hY3RpdmVGYWxsYmFjay5zdGF0dXMsXG4gICAgICAgICAgY3JlYXRlZEF0OiB0aGlzLmNyZWF0ZWRBdCxcbiAgICAgICAgfVxuICAgICAgKTtcbiAgICB9XG4gICAgY29uc3Qgc2FuZGJveCA9IGF3YWl0IHRoaXMuZ2V0KCk7XG4gICAgdGhpcy5zdGF0dXMgPSByZW1vdGVTdGF0dXMoc2FuZGJveCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGlkOiB0aGlzLmlkLFxuICAgICAgbmFtZTogc2FuZGJveC5kaXNwbGF5X25hbWUgPz8gdGhpcy5uYW1lLFxuICAgICAgcHJvdmlkZXI6IHRoaXMucHJvdmlkZXIsXG4gICAgICBzdGF0dXM6IHRoaXMuc3RhdHVzLFxuICAgICAgY3JlYXRlZEF0OiB0aGlzLnJlbW90ZUNyZWF0ZWRBdCA/PyB0aGlzLmNyZWF0ZWRBdCxcbiAgICAgIC4uLih0aGlzLmxhc3RVc2VkQXQgPyB7IGxhc3RVc2VkQXQ6IHRoaXMubGFzdFVzZWRBdCB9IDoge30pLFxuICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgcmVzb3VyY2VOYW1lOiBzYW5kYm94Lm5hbWUsXG4gICAgICAgIHJlbW90ZVN0YXRlOiBzYW5kYm94LnN0YXR1cz8uc3RhdGUsXG4gICAgICAgIHVwZGF0ZVRpbWU6IHNhbmRib3gudXBkYXRlX3RpbWUsXG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICAvKiogRXhwbGFpbiB0aGUgRGF0YWJyaWNrcyBleGVjdXRpb24gYm91bmRhcnkgdG8gdGhlIGFnZW50LiAqL1xuICBnZXRJbnN0cnVjdGlvbnMoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gW1xuICAgICAgXCJDb21tYW5kcyBydW4gaW4gYSBwZXJzaXN0ZW50IERhdGFicmlja3Mgc2VydmVybGVzcyBzYW5kYm94LCBub3QgaW4gdGhlIEFwcCBjb250YWluZXIuXCIsXG4gICAgICBcIlVzZSBzaGVsbCBjb21tYW5kcyBub3JtYWxseS4gVGhlIHNhbmRib3ggaG9tZSBkaXJlY3Rvcnkgc3Vydml2ZXMgaW5hY3Rpdml0eSBzdG9wcy5cIixcbiAgICAgIFwiSWYgRGF0YWJyaWNrcyBTYW5kYm94IGlzIHVuYXZhaWxhYmxlLCBjb21tYW5kcyBmYWxsIGJhY2sgdG8gUHlkYW50aWMgTW9udHkgYW5kIG11c3QgYmUgUHl0aG9uIHNvdXJjZS5cIixcbiAgICAgIFwiRGF0YWJyaWNrcyBXb3Jrc3BhY2UgZmlsZXN5c3RlbSBtb3VudHMgcmVtYWluIHNlcGFyYXRlIHVubGVzcyBhIGNvbW1hbmQgY29waWVzIGRhdGEgZXhwbGljaXRseS5cIixcbiAgICBdLmpvaW4oXCIgXCIpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXQgcmVzb3VyY2VQYXRoKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGAke1NBTkRCT1hfQVBJX1BBVEh9LyR7ZW5jb2RlVVJJQ29tcG9uZW50KHRoaXMuaWQpfWA7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGdldE9yQ3JlYXRlKHNpZ25hbD86IEFib3J0U2lnbmFsKSB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLmdldChzaWduYWwpO1xuICAgIH0gY2F0Y2ggKGNhdWdodCkge1xuICAgICAgaWYgKCFpc1N0YXR1cyhjYXVnaHQsIDQwNCkpIHRocm93IGNhdWdodDtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHNhbmRib3ggPSBhd2FpdCB0aGlzLnJlcXVlc3QoU0FOREJPWF9BUElfUEFUSCwgXCJQT1NUXCIsIFNhbmRib3hSZXNwb25zZVNjaGVtYSwge1xuICAgICAgICBxdWVyeTogeyBzYW5kYm94X2lkOiB0aGlzLmlkIH0sXG4gICAgICAgIHBheWxvYWQ6IHtcbiAgICAgICAgICBkaXNwbGF5X25hbWU6IHRoaXMuZGlzcGxheU5hbWUsXG4gICAgICAgICAgc3BlYzoge1xuICAgICAgICAgICAgY29tcHV0ZToge1xuICAgICAgICAgICAgICBpbmFjdGl2aXR5X3RpbWVvdXQ6IHRoaXMuaW5hY3Rpdml0eVRpbWVvdXQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHNpZ25hbCxcbiAgICAgIH0pO1xuICAgICAgdGhpcy5yZW1lbWJlckNyZWF0ZWRBdChzYW5kYm94LmNyZWF0ZV90aW1lKTtcbiAgICAgIHJldHVybiBzYW5kYm94O1xuICAgIH0gY2F0Y2ggKGNhdWdodCkge1xuICAgICAgaWYgKCFpc1N0YXR1cyhjYXVnaHQsIDQwOSkpIHRocm93IGNhdWdodDtcbiAgICAgIHJldHVybiB0aGlzLmdldChzaWduYWwpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZ2V0KHNpZ25hbD86IEFib3J0U2lnbmFsKSB7XG4gICAgY29uc3Qgc2FuZGJveCA9IGF3YWl0IHRoaXMucmVxdWVzdCh0aGlzLnJlc291cmNlUGF0aCwgXCJHRVRcIiwgU2FuZGJveFJlc3BvbnNlU2NoZW1hLCB7XG4gICAgICBzaWduYWwsXG4gICAgfSk7XG4gICAgdGhpcy5yZW1lbWJlckNyZWF0ZWRBdChzYW5kYm94LmNyZWF0ZV90aW1lKTtcbiAgICByZXR1cm4gc2FuZGJveDtcbiAgfVxuXG4gIHByaXZhdGUgbXV0YXRlKG9wZXJhdGlvbjogXCJzdGFydFwiIHwgXCJzdG9wXCIsIHNpZ25hbD86IEFib3J0U2lnbmFsKSB7XG4gICAgcmV0dXJuIHRoaXMucmVxdWVzdChgJHt0aGlzLnJlc291cmNlUGF0aH0vJHtvcGVyYXRpb259YCwgXCJQT1NUXCIsIFNhbmRib3hSZXNwb25zZVNjaGVtYSwge1xuICAgICAgc2lnbmFsLFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB3YWl0Rm9yU3RhdGUoZXhwZWN0ZWQ6IHN0cmluZywgc2lnbmFsPzogQWJvcnRTaWduYWwpIHtcbiAgICBjb25zdCBkZWFkbGluZSA9IERhdGUubm93KCkgKyB0aGlzLnN0YXJ0dXBUaW1lb3V0TXM7XG4gICAgd2hpbGUgKERhdGUubm93KCkgPCBkZWFkbGluZSkge1xuICAgICAgY29uc3Qgc2FuZGJveCA9IGF3YWl0IHRoaXMuZ2V0KHNpZ25hbCk7XG4gICAgICBpZiAoc2FuZGJveC5zdGF0dXM/LnN0YXRlID09PSBleHBlY3RlZCkgcmV0dXJuIHNhbmRib3g7XG4gICAgICBhd2FpdCBhc3luY1V0aWxzLnNsZWVwKFNBTkRCT1hfUE9MTF9JTlRFUlZBTF9NUywgc2lnbmFsKTtcbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYERhdGFicmlja3Mgc2FuZGJveCAke3RoaXMuaWR9IGRpZCBub3QgcmVhY2ggJHtleHBlY3RlZH0gd2l0aGluICR7dGhpcy5zdGFydHVwVGltZW91dE1zfW1zYCxcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSByZW1lbWJlckNyZWF0ZWRBdCh2YWx1ZTogc3RyaW5nIHwgdW5kZWZpbmVkKTogdm9pZCB7XG4gICAgaWYgKCF2YWx1ZSkgcmV0dXJuO1xuICAgIGNvbnN0IHBhcnNlZCA9IG5ldyBEYXRlKHZhbHVlKTtcbiAgICBpZiAoIU51bWJlci5pc05hTihwYXJzZWQuZ2V0VGltZSgpKSkgdGhpcy5yZW1vdGVDcmVhdGVkQXQgPSBwYXJzZWQ7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlcXVlc3Q8VD4oXG4gICAgcGF0aDogc3RyaW5nLFxuICAgIG1ldGhvZDogXCJHRVRcIiB8IFwiUE9TVFwiIHwgXCJERUxFVEVcIixcbiAgICBzY2hlbWE6IHouWm9kVHlwZTxUPixcbiAgICBvcHRpb25zOiB7XG4gICAgICBwYXlsb2FkPzogdW5rbm93bjtcbiAgICAgIHF1ZXJ5PzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbiAgICAgIHNpZ25hbD86IEFib3J0U2lnbmFsO1xuICAgIH0gPSB7fSxcbiAgKTogUHJvbWlzZTxUPiB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmNsaWVudC5hcGlDbGllbnQucmVxdWVzdChcbiAgICAgIHtcbiAgICAgICAgcGF0aCxcbiAgICAgICAgbWV0aG9kLFxuICAgICAgICBxdWVyeTogb3B0aW9ucy5xdWVyeSxcbiAgICAgICAgaGVhZGVyczogbmV3IEhlYWRlcnMoe1xuICAgICAgICAgIEFjY2VwdDogXCJhcHBsaWNhdGlvbi9qc29uXCIsXG4gICAgICAgICAgLi4uKG9wdGlvbnMucGF5bG9hZCA9PT0gdW5kZWZpbmVkID8ge30gOiB7IFwiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24vanNvblwiIH0pLFxuICAgICAgICB9KSxcbiAgICAgICAgcmF3OiBmYWxzZSxcbiAgICAgICAgLi4uKG9wdGlvbnMucGF5bG9hZCA9PT0gdW5kZWZpbmVkID8ge30gOiB7IHBheWxvYWQ6IG9wdGlvbnMucGF5bG9hZCB9KSxcbiAgICAgIH0sXG4gICAgICBvcHRpb25zLnNpZ25hbCA/IGRhdGFicmlja3MudG9Db250ZXh0KG9wdGlvbnMuc2lnbmFsKSA6IHVuZGVmaW5lZCxcbiAgICApO1xuICAgIHJldHVybiBzY2hlbWEucGFyc2UocmVzcG9uc2UpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNvbW1hbmRTY3JpcHQoY29tbWFuZDogc3RyaW5nLCBhcmdzOiByZWFkb25seSBzdHJpbmdbXSwgY3dkOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBzdHJpbmcge1xuICBjb25zdCBpbnZvY2F0aW9uID0gYXJncy5sZW5ndGggPyBbY29tbWFuZCwgLi4uYXJnc10ubWFwKHNoZWxsUXVvdGUpLmpvaW4oXCIgXCIpIDogY29tbWFuZDtcbiAgcmV0dXJuIGN3ZCA/IGBjZCAtLSAke3NoZWxsUXVvdGUoY3dkKX0gJiYgJHtpbnZvY2F0aW9ufWAgOiBpbnZvY2F0aW9uO1xufVxuXG5mdW5jdGlvbiBzaGVsbFF1b3RlKHZhbHVlOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gYCcke3ZhbHVlLnJlcGxhY2VBbGwoXCInXCIsIFwiJ1xcXFwnJ1wiKX0nYDtcbn1cblxuZnVuY3Rpb24gZGVmaW5lZEVudmlyb25tZW50KGlucHV0OiBOb2RlSlMuUHJvY2Vzc0VudiB8IHVuZGVmaW5lZCk6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4ge1xuICByZXR1cm4gT2JqZWN0LmZyb21FbnRyaWVzKFxuICAgIE9iamVjdC5lbnRyaWVzKGlucHV0ID8/IHt9KS5maWx0ZXIoXG4gICAgICAoZW50cnkpOiBlbnRyeSBpcyBbc3RyaW5nLCBzdHJpbmddID0+IGVudHJ5WzFdICE9PSB1bmRlZmluZWQsXG4gICAgKSxcbiAgKTtcbn1cblxuZnVuY3Rpb24gaXNTdGF0dXMoY2F1Z2h0OiB1bmtub3duLCBzdGF0dXM6IG51bWJlcik6IGJvb2xlYW4ge1xuICByZXR1cm4gZXJyb3JVdGlscy5lcnJvckNvbnRleHQoY2F1Z2h0KS5zdGF0dXNDb2RlID09PSBzdGF0dXM7XG59XG5cbmZ1bmN0aW9uIHJlbW90ZVN0YXR1cyhzYW5kYm94OiB6LmluZmVyPHR5cGVvZiBTYW5kYm94UmVzcG9uc2VTY2hlbWE+KTogUHJvdmlkZXJTdGF0dXMge1xuICBzd2l0Y2ggKHNhbmRib3guc3RhdHVzPy5zdGF0ZSkge1xuICAgIGNhc2UgXCJTQU5EQk9YX1NUQVRFX1JVTk5JTkdcIjpcbiAgICAgIHJldHVybiBcInJ1bm5pbmdcIjtcbiAgICBjYXNlIFwiU0FOREJPWF9TVEFURV9TVE9QUEVEXCI6XG4gICAgICByZXR1cm4gXCJzdG9wcGVkXCI7XG4gICAgY2FzZSBcIlNBTkRCT1hfU1RBVEVfU1RPUFBJTkdcIjpcbiAgICAgIHJldHVybiBcInN0b3BwaW5nXCI7XG4gICAgY2FzZSBcIlNBTkRCT1hfU1RBVEVfUEVORElOR1wiOlxuICAgICAgcmV0dXJuIFwic3RhcnRpbmdcIjtcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIFwicGVuZGluZ1wiO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVGYWxsYmFjayhcbiAgY29uZmlndXJlZDogRXhjbHVkZTxEYXRhYnJpY2tzU2FuZGJveE9wdGlvbnNbXCJmYWxsYmFja1wiXSwgZmFsc2UgfCB1bmRlZmluZWQ+LFxuKTogV29ya3NwYWNlU2FuZGJveCB7XG4gIGlmICh0eXBlb2YgY29uZmlndXJlZCA9PT0gXCJvYmplY3RcIiAmJiBcInByb3ZpZGVyXCIgaW4gY29uZmlndXJlZCAmJiBcInN0YXR1c1wiIGluIGNvbmZpZ3VyZWQpIHtcbiAgICByZXR1cm4gY29uZmlndXJlZDtcbiAgfVxuICByZXR1cm4gbmV3IE1vbnR5U2FuZGJveChjb25maWd1cmVkID09PSBcIm1vbnR5XCIgPyB7fSA6IGNvbmZpZ3VyZWQpO1xufVxuXG5mdW5jdGlvbiBpc0RhdGFicmlja3NTYW5kYm94VW5hdmFpbGFibGUoY2F1Z2h0OiB1bmtub3duKTogYm9vbGVhbiB7XG4gIGNvbnN0IGNvbnRleHQgPSBlcnJvclV0aWxzLmVycm9yQ29udGV4dChjYXVnaHQpO1xuICByZXR1cm4gKFxuICAgIGNvbnRleHQuc3RhdHVzQ29kZSA9PT0gNDA0IHx8XG4gICAgY29udGV4dC5oYXNNZXNzYWdlKFwicmVxdWVzdGVkXCIsIFwiYXBpXCIsIFwibm90XCIsIFwiYXZhaWxhYmxlXCIpIHx8XG4gICAgY29udGV4dC5oYXNNZXNzYWdlKFwiZmVhdHVyZVwiLCBcImRpc2FibGVkXCIpIHx8XG4gICAgY29udGV4dC5oYXNNZXNzYWdlKFwic2FuZGJveFwiLCBcIm5vdFwiLCBcImVuYWJsZWRcIikgfHxcbiAgICBjb250ZXh0Lmhhc01lc3NhZ2UoXCJwcmV2aWV3XCIsIFwibm90XCIsIFwiZW5hYmxlZFwiKSB8fFxuICAgIGNvbnRleHQuaGFzTWVzc2FnZShcInByZXZpZXdcIiwgXCJ1bmF2YWlsYWJsZVwiKSB8fFxuICAgIGNvbnRleHQuaGFzTWVzc2FnZShcInByZXZpZXdcIiwgXCJkaXNhYmxlZFwiKVxuICApO1xufVxuIl19