experimental-agent 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/agent-workflow.d.mts +3 -2
  2. package/dist/agent-workflow.d.ts +3 -2
  3. package/dist/agent-workflow.js +29 -29
  4. package/dist/agent-workflow.mjs +1 -2
  5. package/dist/{chunk-GJETDXOU.mjs → chunk-2SPAJ777.mjs} +5 -1
  6. package/dist/chunk-6J462JGP.mjs +1267 -0
  7. package/dist/{chunk-T2UUL6VC.mjs → chunk-E7TOPGHY.mjs} +3 -3
  8. package/dist/chunk-ILPVXRI5.mjs +2026 -0
  9. package/dist/chunk-ORE6LK2L.mjs +344 -0
  10. package/dist/chunk-W4SSZPDX.mjs +106 -0
  11. package/dist/{types-DuTc4UQW.d.mts → client-CKLwB-ES.d.mts} +730 -3
  12. package/dist/{types-DuTc4UQW.d.ts → client-CKLwB-ES.d.ts} +730 -3
  13. package/dist/{client-66JIQLSA.mjs → client-YUU54ZZH.mjs} +1 -1
  14. package/dist/{handler-BQY5SOI2.mjs → handler-LDFBSCRA.mjs} +1 -1
  15. package/dist/index.d.mts +4 -18
  16. package/dist/index.d.ts +4 -18
  17. package/dist/index.js +67 -40
  18. package/dist/index.mjs +21 -16
  19. package/dist/lifecycle-workflow.d.mts +2 -3
  20. package/dist/lifecycle-workflow.d.ts +2 -3
  21. package/dist/lifecycle-workflow.js +19 -15
  22. package/dist/lifecycle-workflow.mjs +1 -2
  23. package/dist/local-fs-handlers-SY2RDXZE.mjs +314 -0
  24. package/dist/next/loader.js +3 -3
  25. package/dist/next/loader.mjs +1 -1
  26. package/dist/next.js +3 -5
  27. package/dist/next.mjs +2 -4
  28. package/dist/{sandbox-27X2DSE3.mjs → sandbox-GPCA35PJ.mjs} +2 -3
  29. package/dist/{storage-KQYV42J4.mjs → storage-LL6IA24R.mjs} +2 -2
  30. package/package.json +2 -2
  31. package/dist/chunk-2IIWVPZB.mjs +0 -334
  32. package/dist/chunk-A63YU65A.mjs +0 -20
  33. package/dist/chunk-RDKDLHXM.mjs +0 -2031
  34. package/dist/chunk-VGJISV6O.mjs +0 -108
  35. package/dist/chunk-VS7U6SXN.mjs +0 -1261
  36. package/dist/client-DjcE0ATp.d.mts +0 -710
  37. package/dist/client-DwrDzn4_.d.ts +0 -710
  38. package/dist/local-fs-handlers-Q5W52DKV.mjs +0 -290
@@ -1,2031 +0,0 @@
1
- import {
2
- resolveRpc
3
- } from "./chunk-A63YU65A.mjs";
4
- import {
5
- DEFAULT_WAIT_UNTIL
6
- } from "./chunk-64THY7Y7.mjs";
7
-
8
- // src/agent-workflow.ts
9
- import { defineHook, FatalError as FatalError2, getWritable } from "workflow";
10
-
11
- // src/agent-workflow-steps.ts
12
- import {
13
- convertToModelMessages,
14
- createUIMessageStream,
15
- stepCountIs,
16
- streamText
17
- } from "ai";
18
- import { ulid } from "ulid";
19
- import { FatalError } from "workflow";
20
-
21
- // src/skills/parser.ts
22
- function parseSkillFrontmatter(content) {
23
- const trimmed = content.trim();
24
- if (!trimmed.startsWith("---")) {
25
- return null;
26
- }
27
- const endMarkerIndex = trimmed.indexOf("---", 3);
28
- if (endMarkerIndex === -1) {
29
- return null;
30
- }
31
- const frontmatterBlock = trimmed.slice(3, endMarkerIndex).trim();
32
- const parsed = parseSimpleYaml(frontmatterBlock);
33
- if (!(parsed.name && parsed.description)) {
34
- return null;
35
- }
36
- return {
37
- name: String(parsed.name),
38
- description: String(parsed.description)
39
- };
40
- }
41
- function parseSimpleYaml(yaml) {
42
- const result = {};
43
- for (const line of yaml.split("\n")) {
44
- const trimmedLine = line.trim();
45
- if (!trimmedLine || trimmedLine.startsWith("#")) {
46
- continue;
47
- }
48
- const colonIndex = trimmedLine.indexOf(":");
49
- if (colonIndex === -1) {
50
- continue;
51
- }
52
- const key = trimmedLine.slice(0, colonIndex).trim();
53
- let value = trimmedLine.slice(colonIndex + 1).trim();
54
- if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
55
- value = value.slice(1, -1);
56
- }
57
- if (key) {
58
- result[key] = value;
59
- }
60
- }
61
- return result;
62
- }
63
- function normalizeSkillsDirs(skillsDir) {
64
- if (!skillsDir) {
65
- return [];
66
- }
67
- return Array.isArray(skillsDir) ? skillsDir : [skillsDir];
68
- }
69
-
70
- // src/skills/discover.ts
71
- async function discoverSkillsInSandbox(opts) {
72
- const { sandbox, skillsDirs, debug } = opts;
73
- const summaries = [];
74
- const seenNames = /* @__PURE__ */ new Set();
75
- for (const skillsDir of skillsDirs) {
76
- const dirSummaries = await discoverSkillsInDirectory({
77
- sandbox,
78
- skillsDir,
79
- debug
80
- });
81
- for (const summary of dirSummaries) {
82
- if (!seenNames.has(summary.name)) {
83
- seenNames.add(summary.name);
84
- summaries.push(summary);
85
- }
86
- }
87
- }
88
- return summaries;
89
- }
90
- async function discoverSkillsInDirectory(opts) {
91
- const { sandbox, skillsDir, debug } = opts;
92
- const skillPaths = await findSkillFiles({ sandbox, skillsDir, debug });
93
- if (skillPaths.length === 0) {
94
- return [];
95
- }
96
- const summaries = [];
97
- for (const skillMdPath of skillPaths) {
98
- const summary = await parseSkillFile({ sandbox, skillMdPath, debug });
99
- if (summary) {
100
- summaries.push(summary);
101
- }
102
- }
103
- return summaries;
104
- }
105
- async function findSkillFiles(opts) {
106
- const { sandbox, skillsDir, debug } = opts;
107
- const execResult = await sandbox.exec({
108
- command: "find",
109
- args: [skillsDir, "-name", "SKILL.md", "-type", "f"]
110
- });
111
- if (execResult instanceof Error) {
112
- if (debug) {
113
- console.warn(
114
- `[discover] Failed to scan skills directory "${skillsDir}": ${execResult.message}`
115
- );
116
- }
117
- return [];
118
- }
119
- const { stdout, stderr, exitCode } = await execResult.result;
120
- if (debug) {
121
- console.log(
122
- `[discover] find result: exitCode=${exitCode}, stdout="${stdout.trim()}", stderr="${stderr.trim()}"`
123
- );
124
- }
125
- if (exitCode !== 0) {
126
- if (debug) {
127
- console.warn(
128
- `[discover] Skills directory not found or inaccessible: ${skillsDir}`
129
- );
130
- }
131
- return [];
132
- }
133
- const paths = stdout.trim().split("\n").filter((p) => p.length > 0);
134
- if (debug) {
135
- console.log("[discover] Found skill paths:", paths);
136
- }
137
- return paths;
138
- }
139
- async function parseSkillFile(opts) {
140
- const { sandbox, skillMdPath, debug } = opts;
141
- const execResult = await sandbox.exec({
142
- command: "cat",
143
- args: [skillMdPath]
144
- });
145
- if (execResult instanceof Error) {
146
- if (debug) {
147
- console.warn(
148
- `[discover] Failed to read skill file "${skillMdPath}": ${execResult.message}`
149
- );
150
- }
151
- return null;
152
- }
153
- const { stdout, exitCode } = await execResult.result;
154
- if (exitCode !== 0) {
155
- if (debug) {
156
- console.warn(`[discover] Could not read skill file: ${skillMdPath}`);
157
- }
158
- return null;
159
- }
160
- const parsed = parseSkillFrontmatter(stdout);
161
- if (!parsed) {
162
- if (debug) {
163
- console.warn(
164
- `[discover] Invalid or missing frontmatter in: ${skillMdPath}`
165
- );
166
- }
167
- return null;
168
- }
169
- return {
170
- name: parsed.name,
171
- description: parsed.description,
172
- skillMdPath
173
- };
174
- }
175
-
176
- // src/tools/index.ts
177
- import { jsonSchema, tool as tool2 } from "ai";
178
- import { z as z2 } from "zod";
179
-
180
- // src/tools/javascript.ts
181
- import { tool } from "ai";
182
- import { z } from "zod";
183
- var REQUEST_MARKER_START = "__TOOL_REQUEST__";
184
- var REQUEST_MARKER_END = "__TOOL_REQUEST_END__";
185
- var EXECUTION_TIMEOUT_MS = 5 * 60 * 1e3;
186
- var RUNNER_SCRIPT = `
187
- import { readFileSync, existsSync, unlinkSync, mkdirSync } from 'node:fs';
188
- import { join, dirname } from 'node:path';
189
- import { fileURLToPath } from 'node:url';
190
-
191
- const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url));
192
- const TOOL_CALL_TIMEOUT_MS = 300_000;
193
-
194
- let reqCounter = 0;
195
-
196
- async function callTool(name, input) {
197
- const id = 'req_' + (++reqCounter) + '_' + Date.now();
198
- const responseFile = join(SCRIPT_DIR, id + '.response.json');
199
-
200
- const request = JSON.stringify({ id, tool: name, input });
201
- process.stderr.write('${REQUEST_MARKER_START}' + request + '${REQUEST_MARKER_END}' + '\\n');
202
-
203
- const start = Date.now();
204
- while (!existsSync(responseFile)) {
205
- if (Date.now() - start > TOOL_CALL_TIMEOUT_MS) {
206
- throw new Error('Tool call ' + name + ' timed out waiting for response');
207
- }
208
- await new Promise(r => setTimeout(r, 30));
209
- }
210
-
211
- let raw;
212
- try {
213
- raw = readFileSync(responseFile, 'utf8');
214
- } catch {
215
- await new Promise(r => setTimeout(r, 50));
216
- raw = readFileSync(responseFile, 'utf8');
217
- }
218
-
219
- const response = JSON.parse(raw);
220
- try { unlinkSync(responseFile); } catch {}
221
-
222
- if (response.error) {
223
- throw new Error(response.error);
224
- }
225
- return response.result;
226
- }
227
-
228
- const code = readFileSync(join(SCRIPT_DIR, 'code.js'), 'utf8');
229
- const toolNames = JSON.parse(readFileSync(join(SCRIPT_DIR, 'tools.json'), 'utf8'));
230
-
231
- const ctx = { tools: {} };
232
- for (const name of toolNames) {
233
- ctx.tools[name] = (input) => callTool(name, input);
234
- }
235
-
236
- const logs = [];
237
- const customConsole = {
238
- log: (...args) => logs.push(args.map(a => typeof a === 'string' ? a : JSON.stringify(a)).join(' ')),
239
- error: (...args) => logs.push('[error] ' + args.map(a => typeof a === 'string' ? a : JSON.stringify(a)).join(' ')),
240
- warn: (...args) => logs.push('[warn] ' + args.map(a => typeof a === 'string' ? a : JSON.stringify(a)).join(' ')),
241
- };
242
-
243
- try {
244
- const AsyncFunction = Object.getPrototypeOf(async function() {}).constructor;
245
- const fn = new AsyncFunction('ctx', 'console', code);
246
- const result = await fn(ctx, customConsole);
247
-
248
- const output = { success: true, result: result !== undefined ? result : null };
249
- if (logs.length > 0) output.logs = logs;
250
- process.stdout.write(JSON.stringify(output));
251
- } catch (err) {
252
- const output = {
253
- success: false,
254
- error: err instanceof Error ? err.message + '\\n' + err.stack : String(err),
255
- };
256
- if (logs.length > 0) output.logs = logs;
257
- process.stdout.write(JSON.stringify(output));
258
- }
259
- `;
260
- function extractJsonSchema(schema) {
261
- if (!schema || typeof schema !== "object") {
262
- return null;
263
- }
264
- if ("_def" in schema && typeof schema._def === "object") {
265
- try {
266
- return z.toJSONSchema(schema);
267
- } catch {
268
- return null;
269
- }
270
- }
271
- const s = schema;
272
- if (/* @__PURE__ */ Symbol.for("vercel.ai.schema") in s && "jsonSchema" in s) {
273
- return s.jsonSchema;
274
- }
275
- if ("type" in s || "properties" in s) {
276
- return s;
277
- }
278
- return null;
279
- }
280
- function jsonSchemaToTs(schema, indent = 0) {
281
- if (!schema) {
282
- return "unknown";
283
- }
284
- if (schema.enum && Array.isArray(schema.enum)) {
285
- return schema.enum.map((v) => JSON.stringify(v)).join(" | ");
286
- }
287
- if (schema.anyOf && Array.isArray(schema.anyOf)) {
288
- return schema.anyOf.map((s) => jsonSchemaToTs(s, indent)).join(" | ");
289
- }
290
- if (schema.oneOf && Array.isArray(schema.oneOf)) {
291
- return schema.oneOf.map((s) => jsonSchemaToTs(s, indent)).join(" | ");
292
- }
293
- const type = schema.type;
294
- switch (type) {
295
- case "string":
296
- return "string";
297
- case "number":
298
- case "integer":
299
- return "number";
300
- case "boolean":
301
- return "boolean";
302
- case "null":
303
- return "null";
304
- case "array": {
305
- const items = schema.items ? jsonSchemaToTs(schema.items, indent) : "unknown";
306
- return `Array<${items}>`;
307
- }
308
- case "object": {
309
- const properties = schema.properties;
310
- if (!properties) {
311
- return "Record<string, unknown>";
312
- }
313
- const required = new Set(schema.required || []);
314
- const pad = " ".repeat(indent + 1);
315
- const closePad = " ".repeat(indent);
316
- const props = Object.entries(properties).map(([key, value]) => {
317
- const opt = required.has(key) ? "" : "?";
318
- return `${pad}${key}${opt}: ${jsonSchemaToTs(value, indent + 1)}`;
319
- });
320
- return `{
321
- ${props.join(";\n")};
322
- ${closePad}}`;
323
- }
324
- default:
325
- return "unknown";
326
- }
327
- }
328
- function generateContextTypeString(tools) {
329
- const sigs = [];
330
- for (const [name, t] of Object.entries(tools)) {
331
- const raw = t;
332
- const inputSchema = extractJsonSchema(raw.inputSchema ?? raw.parameters);
333
- const outputSchema = extractJsonSchema(raw.outputSchema);
334
- const inputType = inputSchema ? jsonSchemaToTs(inputSchema, 2) : "{}";
335
- const outputType = outputSchema ? jsonSchemaToTs(outputSchema, 2) : "unknown";
336
- sigs.push(` ${name}(input: ${inputType}): Promise<${outputType}>`);
337
- }
338
- return `type Context = {
339
- tools: {
340
- ${sigs.join(";\n")};
341
- }
342
- }`;
343
- }
344
- async function executeInSandbox({
345
- code,
346
- rpcDir,
347
- abortController,
348
- sandbox,
349
- availableTools,
350
- onSubToolCall
351
- }) {
352
- const mkdirResult = await sandbox.exec({
353
- command: "mkdir",
354
- args: ["-p", rpcDir]
355
- });
356
- if (mkdirResult instanceof Error) {
357
- return { success: false, error: mkdirResult.message };
358
- }
359
- await mkdirResult.result;
360
- await sandbox.writeFiles({
361
- files: [
362
- { path: "runner.mjs", content: RUNNER_SCRIPT },
363
- { path: "code.js", content: code },
364
- {
365
- path: "tools.json",
366
- content: JSON.stringify(Object.keys(availableTools))
367
- }
368
- ],
369
- destPath: rpcDir
370
- });
371
- const nodeMajor = Number.parseInt(process.versions.node.split(".")[0], 10);
372
- const permissionFlag = nodeMajor >= 22 ? "--permission" : "--experimental-permission";
373
- const execResult = await sandbox.exec({
374
- command: "node",
375
- args: [
376
- permissionFlag,
377
- `--allow-fs-read=${rpcDir}`,
378
- `--allow-fs-write=${rpcDir}`,
379
- `${rpcDir}/runner.mjs`
380
- ],
381
- signal: abortController.signal
382
- });
383
- if (execResult instanceof Error) {
384
- return { success: false, error: execResult.message };
385
- }
386
- const fatal = { error: null };
387
- const abort = (error) => {
388
- if (!fatal.error) {
389
- fatal.error = error;
390
- abortController.abort();
391
- }
392
- };
393
- const handleToolRequest = async (requestJson) => {
394
- let parsed;
395
- try {
396
- parsed = JSON.parse(requestJson);
397
- } catch {
398
- return;
399
- }
400
- const { id, tool: toolName, input } = parsed;
401
- let response;
402
- try {
403
- const t = availableTools[toolName];
404
- if (!t?.execute) {
405
- throw new Error(
406
- `Tool ${toolName} not found or has no execute function`
407
- );
408
- }
409
- const exec = t.execute.bind(t);
410
- if (onSubToolCall) {
411
- response = await onSubToolCall(
412
- toolName,
413
- input,
414
- () => exec(input, {
415
- toolCallId: `js_${toolName}_${Date.now()}`,
416
- messages: []
417
- })
418
- );
419
- } else {
420
- const result = await exec(input, {
421
- toolCallId: `js_${toolName}_${Date.now()}`,
422
- messages: []
423
- });
424
- response = { result };
425
- }
426
- } catch (err) {
427
- const msg = err instanceof Error ? err.message : String(err);
428
- response = { error: msg };
429
- }
430
- try {
431
- await sandbox.writeFiles({
432
- files: [
433
- {
434
- path: `${id}.response.json`,
435
- content: JSON.stringify(response)
436
- }
437
- ],
438
- destPath: rpcDir
439
- });
440
- } catch (err) {
441
- const msg = err instanceof Error ? err.message : String(err);
442
- abort(new Error(`Failed to write RPC response for ${toolName}: ${msg}`));
443
- }
444
- };
445
- const toolCallPromises = [];
446
- let stderrBuffer = "";
447
- let nonMarkerStderr = "";
448
- const timeout = setTimeout(() => {
449
- abort(
450
- new Error(
451
- `JavaScript execution timed out after ${EXECUTION_TIMEOUT_MS / 1e3}s`
452
- )
453
- );
454
- }, EXECUTION_TIMEOUT_MS);
455
- try {
456
- for await (const entry of execResult.logs()) {
457
- if (fatal.error) {
458
- break;
459
- }
460
- if (entry.stream === "stderr") {
461
- stderrBuffer += entry.data;
462
- while (true) {
463
- const startIdx = stderrBuffer.indexOf(REQUEST_MARKER_START);
464
- if (startIdx === -1) {
465
- break;
466
- }
467
- const beforeMarker = stderrBuffer.slice(0, startIdx);
468
- if (beforeMarker.trim()) {
469
- nonMarkerStderr += beforeMarker;
470
- }
471
- const contentStart = startIdx + REQUEST_MARKER_START.length;
472
- const endIdx = stderrBuffer.indexOf(REQUEST_MARKER_END, contentStart);
473
- if (endIdx === -1) {
474
- break;
475
- }
476
- const requestJson = stderrBuffer.slice(contentStart, endIdx);
477
- stderrBuffer = stderrBuffer.slice(endIdx + REQUEST_MARKER_END.length);
478
- toolCallPromises.push(handleToolRequest(requestJson));
479
- }
480
- }
481
- }
482
- } finally {
483
- clearTimeout(timeout);
484
- }
485
- if (stderrBuffer.trim()) {
486
- nonMarkerStderr += stderrBuffer;
487
- }
488
- await Promise.allSettled(toolCallPromises);
489
- if (fatal.error) {
490
- execResult.result.catch(() => void 0);
491
- return {
492
- success: false,
493
- error: fatal.error.message,
494
- ...nonMarkerStderr ? { stderr: nonMarkerStderr.slice(0, 2e3) } : {}
495
- };
496
- }
497
- const { stdout, stderr, exitCode } = await execResult.result;
498
- try {
499
- return JSON.parse(stdout);
500
- } catch {
501
- return {
502
- success: false,
503
- error: `Runner failed (exit ${exitCode}).`,
504
- stderr: (nonMarkerStderr + stderr).slice(0, 2e3),
505
- stdout: stdout.slice(0, 1e3)
506
- };
507
- }
508
- }
509
- function createJavaScriptTool(opts) {
510
- const { session, sandbox, onSubToolCall } = opts;
511
- const activeSet = session.activeTools ? new Set(session.activeTools) : null;
512
- const availableTools = {};
513
- for (const [name, t] of Object.entries(opts.tools)) {
514
- if (!activeSet || activeSet.has(name)) {
515
- availableTools[name] = t;
516
- }
517
- }
518
- const contextType = generateContextTypeString(availableTools);
519
- return tool({
520
- ...builtInTools.JavaScript,
521
- description: `Execute JavaScript to orchestrate multiple tool calls in a single step. Use this when you need to run several tools in sequence, transform intermediate results, or parallelize independent operations with Promise.all.
522
-
523
- The code runs as an async function body with \`ctx\` in scope:
524
-
525
- \`\`\`typescript
526
- ${contextType}
527
- \`\`\`
528
-
529
- Examples:
530
- - Sequential: \`const file = await ctx.tools.Read({ path: "package.json" }); return JSON.parse(file.content);\`
531
- - Parallel: \`const [a, b] = await Promise.all([ctx.tools.Read({ path: "a.ts" }), ctx.tools.Read({ path: "b.ts" })]); return { a: a.content, b: b.content };\`
532
- - Transform: \`const grep = await ctx.tools.Grep({ pattern: "TODO" }); return grep.matches.split("\\n").length;\`
533
-
534
- Return a value to pass results back. Use console.log() for debug output.`,
535
- execute: ({ code }) => {
536
- const runId = `run_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
537
- const rpcDir = `.agent/js-rpc/${runId}`;
538
- const abortController = new AbortController();
539
- return executeInSandbox({
540
- code,
541
- rpcDir,
542
- abortController,
543
- sandbox,
544
- availableTools,
545
- onSubToolCall
546
- });
547
- }
548
- });
549
- }
550
-
551
- // src/tools/index.ts
552
- var AGENT_PROTOCOL_VERSION = "v1";
553
- function formatFileSize(bytes) {
554
- if (bytes < 1024) {
555
- return `${bytes}`;
556
- }
557
- if (bytes < 1024 * 1024) {
558
- return `${(bytes / 1024).toFixed(1)}K`;
559
- }
560
- if (bytes < 1024 * 1024 * 1024) {
561
- return `${(bytes / (1024 * 1024)).toFixed(1)}M`;
562
- }
563
- return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)}G`;
564
- }
565
- var builtInTools = {
566
- Read: tool2({
567
- description: "Reads a file and returns its contents with metadata. For files over 200 lines, automatically shows first 100 lines unless a specific line range is provided. Use startLine and endLine parameters to read specific portions of large files.",
568
- inputSchema: z2.object({
569
- path: z2.string().describe("Path to the file relative to workspace root"),
570
- startLine: z2.number().optional().describe(
571
- "Starting line number (1-indexed). If provided with endLine, reads exact range regardless of file size."
572
- ),
573
- endLine: z2.number().optional().describe(
574
- "Ending line number (1-indexed, inclusive). If provided with startLine, reads exact range regardless of file size."
575
- )
576
- }),
577
- outputSchema: z2.object({
578
- content: z2.string().describe("File content"),
579
- metadata: z2.object({
580
- totalLines: z2.number().describe("Total number of lines in the file"),
581
- linesShown: z2.number().describe("Number of lines included in this response"),
582
- startLine: z2.number().describe("First line number shown (1-indexed)"),
583
- endLine: z2.number().describe("Last line number shown (1-indexed)"),
584
- isPaginated: z2.boolean().describe("Whether this is a partial view of the file"),
585
- fileSize: z2.string().describe("Human-readable file size (e.g., '2.5K', '1.2M')"),
586
- path: z2.string().describe("Path to the file relative to workspace root")
587
- })
588
- })
589
- }),
590
- Grep: tool2({
591
- description: "Search for patterns in files using ripgrep. Use this to find code patterns, function definitions, imports, etc.",
592
- inputSchema: z2.object({
593
- pattern: z2.string().describe("Regex pattern to search for (ripgrep syntax)"),
594
- path: z2.string().optional().describe(
595
- "Path to search in (defaults to workspace root). Can be a file or directory."
596
- ),
597
- fileType: z2.string().optional().describe(
598
- "File type to filter by (e.g., 'ts', 'js', 'py', 'md'). Uses ripgrep's built-in type filters."
599
- ),
600
- glob: z2.string().optional().describe(
601
- "Glob pattern to filter files (e.g., '*.tsx', 'src/**/*.ts')"
602
- ),
603
- caseSensitive: z2.boolean().optional().default(true).describe("Whether search is case-sensitive (default: true)"),
604
- contextLines: z2.number().optional().describe(
605
- "Number of context lines to show before and after each match"
606
- ),
607
- maxCount: z2.number().optional().describe(
608
- "Maximum number of matches per file (useful for limiting output)"
609
- ),
610
- filesWithMatches: z2.boolean().optional().default(false).describe(
611
- "Only show file paths that contain matches, not the matching lines themselves"
612
- )
613
- }),
614
- outputSchema: z2.object({
615
- matches: z2.string().describe(
616
- "Search results with file paths, line numbers, and matching content"
617
- ),
618
- summary: z2.object({
619
- matchCount: z2.number().describe("Number of matches found"),
620
- fileCount: z2.number().describe("Number of files containing matches"),
621
- searchPath: z2.string().describe("Path that was searched"),
622
- pattern: z2.string().describe("Pattern that was searched for")
623
- })
624
- })
625
- }),
626
- List: tool2({
627
- description: "Recursively list directory contents. Use this to understand the codebase structure, find files, or explore directories. Control depth to balance detail vs. overview. Depth 1 shows immediate children, depth 2 includes subdirectories, etc.",
628
- inputSchema: z2.object({
629
- path: z2.string().optional().describe("Path to list (defaults to workspace root)"),
630
- depth: z2.number().optional().describe(
631
- "Maximum depth to traverse. Choose based on context: 1-2 for quick overview, 3-4 for detailed exploration, 5+ for comprehensive mapping"
632
- ),
633
- includeHidden: z2.boolean().optional().default(false).describe(
634
- "Include hidden files and directories (those starting with '.')"
635
- ),
636
- filesOnly: z2.boolean().optional().default(false).describe("Only show files, not directories"),
637
- pattern: z2.string().optional().describe("Glob pattern to filter results (e.g., '*.ts', '*test*')")
638
- }),
639
- outputSchema: z2.object({
640
- listing: z2.string().describe(
641
- "Directory tree listing showing paths relative to search root"
642
- ),
643
- summary: z2.object({
644
- totalItems: z2.number().describe("Total number of items found"),
645
- totalFiles: z2.number().describe("Total number of files found"),
646
- totalDirs: z2.number().describe("Total number of directories found"),
647
- searchPath: z2.string().describe("Path that was listed"),
648
- depth: z2.number().optional().describe("Maximum depth used (if specified)")
649
- })
650
- })
651
- }),
652
- Write: tool2({
653
- description: "Write content to a file. Creates parent directories automatically. Overwrites existing files.",
654
- inputSchema: z2.object({
655
- path: z2.string().describe("Path to the file relative to workspace root"),
656
- content: z2.string().describe("Content to write to the file")
657
- }),
658
- outputSchema: z2.object({
659
- success: z2.boolean().describe("Whether the write succeeded"),
660
- path: z2.string().describe("Path to the written file"),
661
- bytesWritten: z2.number().describe("Number of bytes written"),
662
- error: z2.string().optional().describe("Error message if write failed")
663
- })
664
- }),
665
- Edit: tool2({
666
- description: "Edit a file by replacing an exact string. Fails if old_string is not found or appears multiple times (not unique). For multiple replacements, call this tool multiple times with unique context.",
667
- inputSchema: z2.object({
668
- path: z2.string().describe("Path to the file relative to workspace root"),
669
- old_string: z2.string().describe("Exact string to find and replace (must be unique in file)"),
670
- new_string: z2.string().describe("String to replace old_string with")
671
- }),
672
- outputSchema: z2.object({
673
- success: z2.boolean().describe("Whether the edit succeeded"),
674
- path: z2.string().describe("Path to the edited file"),
675
- error: z2.string().optional().describe("Error message if edit failed")
676
- })
677
- }),
678
- Bash: tool2({
679
- description: "Executes a bash command inside the workspace. CWD persists between commands within a session. Use waitUntil:0 for background processes (dev servers).",
680
- inputSchema: z2.object({
681
- command: z2.string().describe("The shell command to execute"),
682
- waitUntil: z2.number().optional().describe(
683
- `Max ms to wait for completion (default: ${DEFAULT_WAIT_UNTIL}). Use 0 to run in background and return immediately.`
684
- )
685
- }),
686
- outputSchema: z2.object({
687
- pid: z2.number().describe(
688
- "System PID (0 for foreground, >0 for background - use to kill)"
689
- ),
690
- output: z2.string().describe("Command stdout+stderr combined (empty for background)"),
691
- exitCode: z2.number().describe("Exit code (-1 for background/running)"),
692
- status: z2.enum(["running", "completed", "failed"]).describe("Process status"),
693
- cwd: z2.string().describe("Current working directory after command"),
694
- outputFile: z2.string().describe("Path to output log (for background processes)")
695
- })
696
- }),
697
- JavaScript: tool2({
698
- inputSchema: z2.object({
699
- code: z2.string().describe(
700
- "JavaScript async function body. `ctx` is in scope. Must use `return` to produce output."
701
- )
702
- })
703
- })
704
- };
705
- var builtinToolNames = Object.fromEntries(
706
- Object.entries(builtInTools).map(([name]) => [name, name])
707
- );
708
- function getTools(context) {
709
- const tools = {
710
- [builtinToolNames.Read]: tool2({
711
- ...builtInTools.Read,
712
- execute: async ({ path, startLine, endLine }) => {
713
- const filePath = path;
714
- const result = await context.sandbox.readFile({ path: filePath });
715
- if (result instanceof Error) {
716
- console.error("[Read Tool]", result);
717
- throw result;
718
- }
719
- if (result === null) {
720
- return {
721
- content: `Error: File not found - ${filePath}`,
722
- metadata: {
723
- totalLines: 0,
724
- linesShown: 0,
725
- startLine: 0,
726
- endLine: 0,
727
- isPaginated: false,
728
- fileSize: "0",
729
- path: filePath
730
- }
731
- };
732
- }
733
- const fullContent = result.toString("utf-8");
734
- const lines = fullContent.split("\n");
735
- if (lines.length > 0 && lines.at(-1) === "") {
736
- lines.pop();
737
- }
738
- const totalLines = lines.length;
739
- const fileBytes = Buffer.byteLength(fullContent);
740
- const fileSize = formatFileSize(fileBytes);
741
- const PAGE_SIZE = 100;
742
- let actualStart;
743
- let actualEnd;
744
- if (startLine !== void 0 && endLine !== void 0) {
745
- actualStart = startLine;
746
- actualEnd = endLine;
747
- } else if (startLine !== void 0) {
748
- actualStart = startLine;
749
- actualEnd = Math.min(startLine + PAGE_SIZE - 1, totalLines);
750
- } else if (endLine !== void 0) {
751
- actualStart = 1;
752
- actualEnd = endLine;
753
- } else if (totalLines > 200) {
754
- actualStart = 1;
755
- actualEnd = PAGE_SIZE;
756
- } else {
757
- actualStart = 1;
758
- actualEnd = totalLines;
759
- }
760
- const slicedLines = lines.slice(actualStart - 1, actualEnd);
761
- const content = slicedLines.join("\n");
762
- return {
763
- metadata: {
764
- totalLines,
765
- linesShown: Math.max(0, actualEnd - actualStart + 1),
766
- startLine: actualStart,
767
- endLine: actualEnd,
768
- isPaginated: actualEnd < totalLines,
769
- fileSize,
770
- path: filePath
771
- },
772
- content
773
- };
774
- }
775
- }),
776
- [builtinToolNames.Grep]: tool2({
777
- ...builtInTools.Grep,
778
- execute: async ({
779
- pattern,
780
- path,
781
- fileType,
782
- glob,
783
- caseSensitive,
784
- contextLines,
785
- maxCount,
786
- filesWithMatches
787
- }) => {
788
- const searchPath = path ?? ".";
789
- const args = [];
790
- args.push("--line-number");
791
- args.push("--heading");
792
- args.push("--color", "never");
793
- if (!caseSensitive) {
794
- args.push("-i");
795
- }
796
- if (fileType) {
797
- args.push("--type", fileType);
798
- }
799
- if (glob) {
800
- args.push("--glob", glob);
801
- }
802
- if (contextLines !== void 0) {
803
- args.push("-C", String(contextLines));
804
- }
805
- if (maxCount !== void 0) {
806
- args.push("--max-count", String(maxCount));
807
- }
808
- if (filesWithMatches) {
809
- args.push("--files-with-matches");
810
- }
811
- args.push("--", pattern, searchPath);
812
- const result = await context.sandbox.exec({ command: "rg", args });
813
- if (result instanceof Error) {
814
- console.error("[Grep Tool]", result);
815
- throw result;
816
- }
817
- const { stdout, stderr } = await result.result;
818
- if (stderr && !stderr.toLowerCase().includes("no matches")) {
819
- console.error(`[Grep Tool] Warning: ${stderr}`);
820
- }
821
- const MAX_GREP_OUTPUT_CHARS = 5e4;
822
- let finalOutput = stdout;
823
- let wasTruncated = false;
824
- if (finalOutput.length > MAX_GREP_OUTPUT_CHARS) {
825
- finalOutput = finalOutput.slice(0, MAX_GREP_OUTPUT_CHARS) + "\n\n[Output truncated - use more specific pattern or path]";
826
- wasTruncated = true;
827
- }
828
- const lines = finalOutput.trim().split("\n").filter((l) => l.length > 0);
829
- const fileCount = filesWithMatches ? lines.length : new Set(
830
- lines.filter((l) => !l.startsWith(" ") && l.includes(":")).map((l) => l.split(":")[0])
831
- ).size;
832
- return {
833
- summary: {
834
- matchCount: filesWithMatches ? 0 : lines.filter((l) => l.includes(":")).length,
835
- fileCount,
836
- searchPath,
837
- pattern,
838
- wasTruncated
839
- },
840
- matches: finalOutput || "(no matches found)"
841
- };
842
- }
843
- }),
844
- [builtinToolNames.List]: tool2({
845
- ...builtInTools.List,
846
- execute: async ({ path, depth, includeHidden, filesOnly, pattern }) => {
847
- const searchPath = path ?? ".";
848
- const result = await context.sandbox.exec({
849
- command: "bash",
850
- args: [
851
- "-c",
852
- `
853
- set -e
854
- SEARCH_PATH="$1"
855
- DEPTH="$2"
856
- INCLUDE_HIDDEN="$3"
857
- FILES_ONLY="$4"
858
- PATTERN="$5"
859
-
860
- # Build find command arguments
861
- FIND_ARGS=""
862
- [ -n "$DEPTH" ] && FIND_ARGS="$FIND_ARGS -maxdepth $DEPTH"
863
- [ "$INCLUDE_HIDDEN" != "true" ] && FIND_ARGS="$FIND_ARGS ! -path '*/.*'"
864
- [ "$FILES_ONLY" = "true" ] && FIND_ARGS="$FIND_ARGS -type f"
865
- [ -n "$PATTERN" ] && FIND_ARGS="$FIND_ARGS -name '$PATTERN'"
866
-
867
- # Get listing
868
- LISTING=$(eval "find '$SEARCH_PATH' $FIND_ARGS" 2>/dev/null | sort)
869
-
870
- # Get counts
871
- COUNT_ARGS=""
872
- [ -n "$DEPTH" ] && COUNT_ARGS="$COUNT_ARGS -maxdepth $DEPTH"
873
- [ "$INCLUDE_HIDDEN" != "true" ] && COUNT_ARGS="$COUNT_ARGS ! -path '*/.*'"
874
-
875
- FILE_COUNT=$(eval "find '$SEARCH_PATH' $COUNT_ARGS -type f" 2>/dev/null | wc -l)
876
- DIR_COUNT=$(eval "find '$SEARCH_PATH' $COUNT_ARGS -type d" 2>/dev/null | wc -l)
877
-
878
- # Output: counts first, then listing
879
- echo "$FILE_COUNT|$DIR_COUNT"
880
- echo "|||LISTING|||"
881
- echo "$LISTING" | sed "s|^$SEARCH_PATH|.|"
882
- `,
883
- "--",
884
- searchPath,
885
- depth?.toString() || "",
886
- includeHidden ? "true" : "false",
887
- filesOnly ? "true" : "false",
888
- pattern || ""
889
- ]
890
- });
891
- if (result instanceof Error) {
892
- console.error("[List Tool]", result);
893
- throw result;
894
- }
895
- const { stdout, stderr } = await result.result;
896
- if (stderr) {
897
- console.warn(`[List Tool] stderr: ${stderr}`);
898
- }
899
- const [countsLine, ...rest] = stdout.split("|||LISTING|||");
900
- const listing = rest.join("|||LISTING|||").trim();
901
- const [fileCountStr, dirCountStr] = countsLine.trim().split("|");
902
- const totalFiles = Number.parseInt(fileCountStr, 10) || 0;
903
- const totalDirs = Number.parseInt(dirCountStr, 10) || 0;
904
- const lines = listing.split("\n").filter((l) => l.length > 0);
905
- return {
906
- summary: {
907
- totalItems: lines.length,
908
- totalFiles,
909
- totalDirs,
910
- searchPath,
911
- depth
912
- },
913
- listing
914
- };
915
- }
916
- }),
917
- [builtinToolNames.Write]: tool2({
918
- ...builtInTools.Write,
919
- execute: async ({ path, content }) => {
920
- const filePath = path.startsWith("/") ? path.slice(1) : path;
921
- const dir = filePath.includes("/") ? filePath.split("/").slice(0, -1).join("/") : ".";
922
- const fileName = filePath.split("/").pop() || filePath;
923
- try {
924
- if (dir !== ".") {
925
- await context.sandbox.exec({ command: "mkdir", args: ["-p", dir] });
926
- }
927
- await context.sandbox.writeFiles({
928
- files: [{ path: fileName, content }],
929
- destPath: dir
930
- });
931
- return {
932
- success: true,
933
- path: filePath,
934
- bytesWritten: Buffer.byteLength(content, "utf8")
935
- };
936
- } catch (err) {
937
- const errorMsg = err instanceof Error ? err.message : String(err);
938
- return {
939
- success: false,
940
- path: filePath,
941
- bytesWritten: 0,
942
- error: errorMsg
943
- };
944
- }
945
- }
946
- }),
947
- [builtinToolNames.Edit]: tool2({
948
- ...builtInTools.Edit,
949
- execute: async ({ path, old_string, new_string }) => {
950
- const filePath = path.startsWith("/") ? path.slice(1) : path;
951
- const result = await context.sandbox.readFile({ path: filePath });
952
- if (result instanceof Error) {
953
- return { success: false, path: filePath, error: result.message };
954
- }
955
- if (result === null) {
956
- return {
957
- success: false,
958
- path: filePath,
959
- error: `File not found: ${filePath}`
960
- };
961
- }
962
- const content = result.toString("utf-8");
963
- const occurrences = content.split(old_string).length - 1;
964
- if (occurrences === 0) {
965
- return {
966
- success: false,
967
- path: filePath,
968
- error: "old_string not found in file"
969
- };
970
- }
971
- if (occurrences > 1) {
972
- return {
973
- success: false,
974
- path: filePath,
975
- error: `old_string appears ${occurrences} times in file (must be unique). Include more surrounding context to make the match unique.`
976
- };
977
- }
978
- const newContent = content.replace(old_string, new_string);
979
- const dir = filePath.includes("/") ? filePath.split("/").slice(0, -1).join("/") : ".";
980
- const fileName = filePath.split("/").pop() || filePath;
981
- try {
982
- await context.sandbox.writeFiles({
983
- files: [{ path: fileName, content: newContent }],
984
- destPath: dir
985
- });
986
- return { success: true, path: filePath };
987
- } catch (err) {
988
- const errorMsg = err instanceof Error ? err.message : String(err);
989
- return { success: false, path: filePath, error: errorMsg };
990
- }
991
- }
992
- }),
993
- [builtinToolNames.Bash]: tool2({
994
- ...builtInTools.Bash,
995
- execute: async ({ command, waitUntil }) => {
996
- const { createProcessManager } = await import("./process-manager-ZCET3VD2.mjs");
997
- const processManager = createProcessManager({
998
- sandbox: context.sandbox,
999
- sessionId: context.input.sessionId
1000
- });
1001
- await processManager.init();
1002
- const result = await processManager.run({ command, waitUntil });
1003
- return result;
1004
- }
1005
- })
1006
- };
1007
- if (context.apiToolsMetadata.length > 0) {
1008
- const apiTools = buildApiTools({
1009
- rpc: context.rpc,
1010
- metadata: context.apiToolsMetadata,
1011
- session: context.session,
1012
- sandboxRecord: context.sandboxRecord,
1013
- context: context.event.context
1014
- });
1015
- Object.assign(tools, apiTools);
1016
- }
1017
- tools[builtinToolNames.JavaScript] = createJavaScriptTool({
1018
- tools,
1019
- session: context.session,
1020
- sandbox: context.sandbox,
1021
- onSubToolCall: context.onSubToolCall
1022
- });
1023
- return tools;
1024
- }
1025
- async function fetchApiToolsMetadata(opts) {
1026
- const { rpc } = opts;
1027
- const result = await rpc({ method: "tools.list", params: {} });
1028
- if ("error" in result) {
1029
- console.error("[agent] Failed to fetch tools:", result.error?.message);
1030
- return [];
1031
- }
1032
- return result.result ?? [];
1033
- }
1034
- function buildApiTools(opts) {
1035
- const { rpc, metadata, session, sandboxRecord, context } = opts;
1036
- const tools = {};
1037
- for (const meta of metadata) {
1038
- tools[meta.name] = tool2({
1039
- description: meta.description ?? `Custom tool: ${meta.name}`,
1040
- inputSchema: meta.inputSchema ? jsonSchema(meta.inputSchema) : z2.object({}),
1041
- execute: async (input) => {
1042
- const result = await rpc({
1043
- method: "tools.execute",
1044
- params: {
1045
- name: meta.name,
1046
- input,
1047
- session,
1048
- sandboxRecord,
1049
- context
1050
- }
1051
- });
1052
- if ("error" in result) {
1053
- throw new Error(`Tool execution failed: ${result.error?.message}`);
1054
- }
1055
- return result.result;
1056
- }
1057
- });
1058
- }
1059
- return tools;
1060
- }
1061
- function resolveApiUrl(opts) {
1062
- let origin = "";
1063
- let path = `/.well-known/agent/${AGENT_PROTOCOL_VERSION}`;
1064
- if (opts.api) {
1065
- if (opts.api.startsWith("/")) {
1066
- path = opts.api;
1067
- } else {
1068
- try {
1069
- const url = new URL(opts.api);
1070
- origin = url.origin;
1071
- const fullPath = url.pathname + url.search + url.hash;
1072
- if (fullPath.startsWith("/") && fullPath !== "/") {
1073
- path = fullPath;
1074
- }
1075
- } catch {
1076
- }
1077
- }
1078
- }
1079
- if (!origin) {
1080
- if (process.env.NODE_ENV === "development") {
1081
- origin = `http://localhost:${process.env.PORT ?? process.env.NEXT_PUBLIC_PORT ?? 3e3}`;
1082
- }
1083
- const vercelUrl = process.env.VERCEL_URL ?? process.env.NEXT_PUBLIC_VERCEL_URL;
1084
- if (vercelUrl) {
1085
- origin = `https://${vercelUrl}`;
1086
- }
1087
- }
1088
- if (!origin) {
1089
- throw new Error(
1090
- "[agent] Couldn't determine API origin (no origin detected in `api` option and no VERCEL_URL set)"
1091
- );
1092
- }
1093
- return `${origin}${path}`;
1094
- }
1095
-
1096
- // src/utils/prompt-cache.ts
1097
- var ANTHROPIC_MAX_CACHE_BREAKPOINTS_PER_REQUEST = 4;
1098
- var CLAUDE_LIKE_MODEL_MATCHERS = ["claude", "anthropic"];
1099
- var CLAUDE_PROMPT_CACHING_PROVIDER_OPTIONS = {
1100
- anthropic: {
1101
- cacheControl: { type: "ephemeral" }
1102
- },
1103
- openrouter: {
1104
- cacheControl: { type: "ephemeral" }
1105
- },
1106
- bedrock: {
1107
- cachePoint: { type: "default" }
1108
- },
1109
- openaiCompatible: {
1110
- cache_control: { type: "ephemeral" }
1111
- },
1112
- copilot: {
1113
- copilot_cache_control: { type: "ephemeral" }
1114
- }
1115
- };
1116
- function getGatewayProvider(model) {
1117
- const slashIndex = model.indexOf("/");
1118
- if (slashIndex === -1) {
1119
- return null;
1120
- }
1121
- return model.slice(0, slashIndex);
1122
- }
1123
- function countAnthropicCacheBreakpoints(messages) {
1124
- let count = 0;
1125
- for (const message of messages) {
1126
- const providerOptions = message.providerOptions;
1127
- if (providerOptions?.anthropic?.cacheControl) {
1128
- count += 1;
1129
- }
1130
- if (Array.isArray(message.content)) {
1131
- for (const part of message.content) {
1132
- const partProviderOptions = part.providerOptions;
1133
- if (partProviderOptions?.anthropic?.cacheControl) {
1134
- count += 1;
1135
- }
1136
- }
1137
- }
1138
- }
1139
- return count;
1140
- }
1141
- function isClaudeLikeModel(model) {
1142
- const lower = model.toLowerCase();
1143
- return CLAUDE_LIKE_MODEL_MATCHERS.some((m) => lower.includes(m));
1144
- }
1145
- function mergeProviderOptions(opts) {
1146
- const next = { ...opts.current ?? {} };
1147
- for (const [key, value] of Object.entries(opts.patch)) {
1148
- next[key] = { ...next[key] ?? {}, ...value };
1149
- }
1150
- return next;
1151
- }
1152
- function isCacheableClaudePart(part) {
1153
- if (!part || typeof part !== "object") {
1154
- return false;
1155
- }
1156
- if ("type" in part && part.type === "text") {
1157
- const text = part.text;
1158
- if (typeof text === "string") {
1159
- return text.trim().length > 0;
1160
- }
1161
- }
1162
- if ("type" in part) {
1163
- const type = part.type;
1164
- if (type === "thinking" || type === "reasoning") {
1165
- return false;
1166
- }
1167
- }
1168
- return true;
1169
- }
1170
- function hasCacheableContent(message) {
1171
- if (typeof message.content === "string") {
1172
- return message.content.trim().length > 0;
1173
- }
1174
- if (Array.isArray(message.content)) {
1175
- return message.content.some((part) => isCacheableClaudePart(part));
1176
- }
1177
- return false;
1178
- }
1179
- function findLastCacheablePartIndex(content) {
1180
- for (let i = content.length - 1; i >= 0; i -= 1) {
1181
- if (isCacheableClaudePart(content[i])) {
1182
- return i;
1183
- }
1184
- }
1185
- return null;
1186
- }
1187
- function selectClaudeCachingTargets(messages) {
1188
- const systemIndices = [];
1189
- const finalIndices = [];
1190
- for (let i = 0; i < messages.length && systemIndices.length < 2; i += 1) {
1191
- const message = messages[i];
1192
- if (message.role === "system" && hasCacheableContent(message)) {
1193
- systemIndices.push(i);
1194
- }
1195
- }
1196
- for (let i = messages.length - 1; i >= 0 && finalIndices.length < 2; i -= 1) {
1197
- const message = messages[i];
1198
- if (message.role !== "system" && hasCacheableContent(message)) {
1199
- finalIndices.push(i);
1200
- }
1201
- }
1202
- finalIndices.reverse();
1203
- return [...systemIndices, ...finalIndices];
1204
- }
1205
- function applyClaudePromptCaching(opts) {
1206
- const existingBreakpoints = countAnthropicCacheBreakpoints(opts.messages);
1207
- const remainingBudget = Math.max(
1208
- 0,
1209
- opts.maxBreakpointsPerRequest - existingBreakpoints
1210
- );
1211
- if (remainingBudget === 0) {
1212
- return opts.messages;
1213
- }
1214
- const targetIndices = selectClaudeCachingTargets(opts.messages).slice(
1215
- 0,
1216
- remainingBudget
1217
- );
1218
- if (targetIndices.length === 0) {
1219
- return opts.messages;
1220
- }
1221
- const useMessageLevelOptions = opts.providerId === "anthropic" || Boolean(opts.providerId?.includes("bedrock"));
1222
- const nextMessages = opts.messages.slice();
1223
- for (const messageIndex of targetIndices) {
1224
- const message = nextMessages[messageIndex];
1225
- const shouldUseContentOptions = !useMessageLevelOptions && Array.isArray(message.content) && message.content.length > 0;
1226
- if (shouldUseContentOptions && Array.isArray(message.content)) {
1227
- const partIndex = findLastCacheablePartIndex(message.content);
1228
- if (partIndex !== null) {
1229
- const part = message.content[partIndex];
1230
- if (part && typeof part === "object") {
1231
- const partProviderOptions = part.providerOptions;
1232
- const nextContent = message.content.slice();
1233
- nextContent[partIndex] = {
1234
- ...part,
1235
- providerOptions: mergeProviderOptions({
1236
- current: partProviderOptions,
1237
- patch: CLAUDE_PROMPT_CACHING_PROVIDER_OPTIONS
1238
- })
1239
- };
1240
- nextMessages[messageIndex] = {
1241
- ...message,
1242
- content: nextContent
1243
- };
1244
- continue;
1245
- }
1246
- }
1247
- }
1248
- const messageProviderOptions = message.providerOptions;
1249
- nextMessages[messageIndex] = {
1250
- ...message,
1251
- providerOptions: mergeProviderOptions({
1252
- current: messageProviderOptions,
1253
- patch: CLAUDE_PROMPT_CACHING_PROVIDER_OPTIONS
1254
- })
1255
- };
1256
- }
1257
- return nextMessages;
1258
- }
1259
- function applyPromptCachingToModelRequest(opts) {
1260
- const provider = getGatewayProvider(opts.model);
1261
- const providerOptions = {};
1262
- if ((provider === "openai" || provider === "azure") && opts.openai?.setPromptCacheKey !== false) {
1263
- providerOptions.openai = { promptCacheKey: opts.sessionId };
1264
- }
1265
- const maxBreakpointsPerRequest = opts.anthropic?.maxBreakpointsPerRequest ?? ANTHROPIC_MAX_CACHE_BREAKPOINTS_PER_REQUEST;
1266
- const cachedMessages = isClaudeLikeModel(opts.model) ? applyClaudePromptCaching({
1267
- messages: opts.messages,
1268
- providerId: provider,
1269
- maxBreakpointsPerRequest
1270
- }) : opts.messages;
1271
- return {
1272
- messages: cachedMessages,
1273
- providerOptions
1274
- };
1275
- }
1276
-
1277
- // src/utils/ui.ts
1278
- function isSubToolPart(part) {
1279
- const p = part.part;
1280
- return typeof p?.toolCallId === "string" && p.toolCallId.startsWith("js_tc_");
1281
- }
1282
- function assembleUIMessages(opts) {
1283
- let filtered = opts.messages;
1284
- if (opts.until !== void 0) {
1285
- const until = opts.until;
1286
- filtered = filtered.filter((m) => m.createdAt <= until);
1287
- }
1288
- if (!opts.includeQueued) {
1289
- filtered = filtered.filter((m) => m.startedAt !== null);
1290
- }
1291
- const parts = opts.excludeSubToolParts ? opts.parts.filter((p) => !isSubToolPart(p)) : opts.parts;
1292
- const partsByMessage = /* @__PURE__ */ new Map();
1293
- for (const part of parts) {
1294
- const existing = partsByMessage.get(part.messageId) ?? [];
1295
- existing.push(part);
1296
- partsByMessage.set(part.messageId, existing);
1297
- }
1298
- return filtered.map((m) => {
1299
- const messageParts = partsByMessage.get(m.id) ?? [];
1300
- messageParts.sort((a, b) => a.index - b.index);
1301
- return {
1302
- id: m.id,
1303
- role: m.role,
1304
- parts: messageParts.map((p) => p.part)
1305
- };
1306
- }).filter((m) => m.parts.length > 0);
1307
- }
1308
-
1309
- // src/utils/usage.ts
1310
- function sum(items, key) {
1311
- return items.reduce((acc, item) => {
1312
- const value = item[key];
1313
- return acc + (typeof value === "number" ? value : 0);
1314
- }, 0);
1315
- }
1316
- function computeUsageSummary(steps) {
1317
- return {
1318
- model: steps[0]?.model ?? "unknown",
1319
- inputTokens: sum(steps, "inputTokens"),
1320
- outputTokens: sum(steps, "outputTokens"),
1321
- totalTokens: sum(steps, "totalTokens"),
1322
- cacheReadTokens: sum(steps, "cacheReadTokens"),
1323
- cacheWriteTokens: sum(steps, "cacheWriteTokens"),
1324
- reasoningTokens: sum(steps, "reasoningTokens"),
1325
- stepCount: steps.length
1326
- };
1327
- }
1328
- function computeSessionUsage(messages) {
1329
- const byMessageId = {};
1330
- for (const m of messages) {
1331
- byMessageId[m.id] = m.usage?.summary ?? null;
1332
- }
1333
- const summaries = messages.map((m) => m.usage?.summary).filter((s) => s !== void 0);
1334
- const total = {
1335
- model: summaries[0]?.model ?? "unknown",
1336
- inputTokens: summaries.reduce((acc, s) => acc + s.inputTokens, 0),
1337
- outputTokens: summaries.reduce((acc, s) => acc + s.outputTokens, 0),
1338
- totalTokens: summaries.reduce((acc, s) => acc + s.totalTokens, 0),
1339
- cacheReadTokens: summaries.reduce((acc, s) => acc + s.cacheReadTokens, 0),
1340
- cacheWriteTokens: summaries.reduce((acc, s) => acc + s.cacheWriteTokens, 0),
1341
- reasoningTokens: summaries.reduce((acc, s) => acc + s.reasoningTokens, 0),
1342
- stepCount: summaries.reduce((acc, s) => acc + s.stepCount, 0),
1343
- messageCount: summaries.length
1344
- };
1345
- return { total, byMessageId };
1346
- }
1347
-
1348
- // src/agent-workflow-steps.ts
1349
- function emitStatus({
1350
- writer,
1351
- status,
1352
- rpc
1353
- }) {
1354
- writer?.({ type: "data-status", data: status, transient: true });
1355
- rpc({ method: "hook.status", params: { status } }).catch(() => {
1356
- });
1357
- }
1358
- var BASE_SYSTEM_PROMPT = "You are an AI assistant with basic tools to interact with your environment. Explore and work freely.";
1359
- function joinPromptSections(...sections) {
1360
- return sections.filter((s) => s?.trim()).join("\n\n");
1361
- }
1362
- var backgroundProcessPrompt = `## Background Processes
1363
- These background process instructions are for you to manipulate the processes, do not be to verbose to the user about the response details like "how to debug the process output" the user will have an UI.
1364
-
1365
- Use \`waitUntil: 0\` for dev servers that should run indefinitely.
1366
- It is a good practice to check the output log after running processes like dev servers to make sure they started correctly.
1367
-
1368
- To run a background process:
1369
- Bash({ command: "npm run dev", waitUntil: 0 })
1370
- Returns immediately with \`pid\` and \`outputFile\` path.
1371
-
1372
- To check a process's output:
1373
- Bash({ command: "tail -100 {outputFile}" })
1374
-
1375
- To kill a process:
1376
- Bash({ command: "kill {pid}" }) // Graceful
1377
- Bash({ command: "kill -9 {pid}" }) // Force
1378
-
1379
- To list all processes:
1380
- Bash({ command: "ps aux | grep node" })
1381
- `;
1382
- function buildSkillsContext(skills) {
1383
- if (skills.length === 0) {
1384
- return "";
1385
- }
1386
- const skillLines = skills.map((s) => `- ${s.name}: ${s.description}
1387
- Path: ${s.skillMdPath}`).join("\n");
1388
- return `## Available Skills
1389
- ${skillLines}
1390
-
1391
- ${backgroundProcessPrompt}
1392
-
1393
- You can use the Read tool to read any skill's SKILL.md file to learn more about it.`;
1394
- }
1395
- async function completeMessageStep({
1396
- assistantMessageId,
1397
- input,
1398
- writable,
1399
- usageSteps
1400
- }) {
1401
- "use step";
1402
- const { getStorage } = await import("./client-66JIQLSA.mjs");
1403
- const rpc = resolveRpc(input.storageConfig.name ?? "default");
1404
- const storage = getStorage({ config: input.storageConfig, rpc });
1405
- const message = await storage.message.get(assistantMessageId);
1406
- if (message instanceof Error) {
1407
- throw message;
1408
- }
1409
- if (!message) {
1410
- throw new Error(`Message ${assistantMessageId} not found`);
1411
- }
1412
- const usage = usageSteps.length > 0 ? {
1413
- steps: usageSteps,
1414
- summary: computeUsageSummary(usageSteps)
1415
- } : null;
1416
- const result = await storage.message.set({
1417
- ...message,
1418
- completedAt: Date.now(),
1419
- usage
1420
- });
1421
- if (result instanceof Error) {
1422
- throw result;
1423
- }
1424
- await writable.close();
1425
- }
1426
- var INTERRUPT_POLL_INTERVAL_MS = 500;
1427
- function pollForInterrupt({
1428
- storage,
1429
- messageId,
1430
- signal,
1431
- abortController
1432
- }) {
1433
- let resolveFirstCheck;
1434
- const firstCheck = new Promise((resolve) => {
1435
- resolveFirstCheck = resolve;
1436
- });
1437
- const poll = async () => {
1438
- let isFirst = true;
1439
- while (!signal.aborted) {
1440
- const message = await storage.message.get(messageId);
1441
- if (message instanceof Error) {
1442
- if (isFirst) {
1443
- resolveFirstCheck();
1444
- }
1445
- return;
1446
- }
1447
- if (message.interruptedAt !== null) {
1448
- abortController.abort();
1449
- if (isFirst) {
1450
- resolveFirstCheck();
1451
- }
1452
- return;
1453
- }
1454
- if (isFirst) {
1455
- isFirst = false;
1456
- resolveFirstCheck();
1457
- }
1458
- await new Promise(
1459
- (resolve) => setTimeout(resolve, INTERRUPT_POLL_INTERVAL_MS)
1460
- );
1461
- }
1462
- };
1463
- poll();
1464
- return { firstCheck };
1465
- }
1466
- async function streamTextStep({
1467
- assistantMessageId,
1468
- input,
1469
- event,
1470
- writable,
1471
- lastPartIndex,
1472
- stepIndexOffset
1473
- }) {
1474
- "use step";
1475
- const { getStorage } = await import("./client-66JIQLSA.mjs");
1476
- const { getSandbox } = await import("./sandbox-27X2DSE3.mjs");
1477
- const rpc = resolveRpc(input.storageConfig.name ?? "default");
1478
- const storage = getStorage({ config: input.storageConfig, rpc });
1479
- const abortController = new AbortController();
1480
- const pollController = new AbortController();
1481
- const { firstCheck } = pollForInterrupt({
1482
- storage,
1483
- messageId: assistantMessageId,
1484
- signal: pollController.signal,
1485
- abortController
1486
- });
1487
- const [
1488
- ,
1489
- messagesResult,
1490
- partsResult,
1491
- { session, sandbox, sandboxRecord },
1492
- apiToolsMetadata
1493
- ] = await Promise.all([
1494
- firstCheck,
1495
- storage.message.list(input.sessionId),
1496
- storage.part.listBySession(input.sessionId),
1497
- storage.session.get(input.sessionId).then(async (session2) => {
1498
- if (session2 instanceof Error) {
1499
- throw session2;
1500
- }
1501
- const sandboxRecord2 = session2.sandboxId ? await storage.sandbox.get(session2.sandboxId) : null;
1502
- if (sandboxRecord2 instanceof Error) {
1503
- throw sandboxRecord2;
1504
- }
1505
- if (!sandboxRecord2) {
1506
- throw new FatalError(
1507
- `Sandbox not found for session ${input.sessionId}`
1508
- );
1509
- }
1510
- const sandbox2 = getSandbox({
1511
- sandboxRecord: sandboxRecord2,
1512
- storageConfig: input.storageConfig,
1513
- storage
1514
- });
1515
- return { session: session2, sandbox: sandbox2, sandboxRecord: sandboxRecord2 };
1516
- }),
1517
- fetchApiToolsMetadata({
1518
- rpc
1519
- })
1520
- ]);
1521
- if (abortController.signal.aborted) {
1522
- pollController.abort();
1523
- return {
1524
- finishReason: "stop",
1525
- lastPartIndex,
1526
- usageSteps: [],
1527
- pendingApprovals: [],
1528
- maxSteps: void 0
1529
- };
1530
- }
1531
- if (messagesResult instanceof Error) {
1532
- throw messagesResult;
1533
- }
1534
- if (partsResult instanceof Error) {
1535
- throw partsResult;
1536
- }
1537
- const setStartedPromise = lastPartIndex === 0 ? (async () => {
1538
- const now = Date.now();
1539
- const pendingMessages = messagesResult.items.filter(
1540
- (m) => m.createdAt <= event.createdAt && m.startedAt === null
1541
- );
1542
- if (pendingMessages.length > 0) {
1543
- return await Promise.all(
1544
- pendingMessages.map(
1545
- (m) => storage.message.set({
1546
- ...m,
1547
- startedAt: now,
1548
- completedAt: m.role === "assistant" ? null : now
1549
- })
1550
- )
1551
- );
1552
- }
1553
- })() : null;
1554
- const streamWriterRef = { current: null };
1555
- const subToolPartIds = [];
1556
- let nextPartIndex = lastPartIndex;
1557
- const onSubToolCall = async (toolName, toolInput, execute) => {
1558
- const res = await rpc({
1559
- method: "tools.needsApproval",
1560
- params: {
1561
- toolName,
1562
- input: toolInput,
1563
- toolCallId: `js_${toolName}_${Date.now()}`,
1564
- messages: []
1565
- }
1566
- });
1567
- if ("error" in res || res.result !== true) {
1568
- try {
1569
- const result2 = await execute();
1570
- return { result: result2 };
1571
- } catch (err) {
1572
- return { error: err instanceof Error ? err.message : String(err) };
1573
- }
1574
- }
1575
- const approvalId = `js_approval_${ulid()}`;
1576
- const toolCallId = `js_tc_${ulid()}`;
1577
- const partId = `part_${ulid()}`;
1578
- subToolPartIds.push(partId);
1579
- await storage.part.set({
1580
- id: partId,
1581
- index: nextPartIndex++,
1582
- messageId: assistantMessageId,
1583
- sessionId: input.sessionId,
1584
- part: {
1585
- type: `tool-${toolName}`,
1586
- toolCallId,
1587
- state: "approval-requested",
1588
- input: toolInput,
1589
- approval: { id: approvalId }
1590
- }
1591
- });
1592
- streamWriterRef.current?.({
1593
- type: "tool-input-start",
1594
- toolCallId,
1595
- toolName
1596
- });
1597
- streamWriterRef.current?.({
1598
- type: "tool-input-available",
1599
- toolCallId,
1600
- toolName,
1601
- input: toolInput
1602
- });
1603
- streamWriterRef.current?.({
1604
- type: "tool-approval-request",
1605
- approvalId,
1606
- toolCallId
1607
- });
1608
- const POLL_MS = 500;
1609
- const TIMEOUT_MS = 5 * 60 * 1e3;
1610
- const start = Date.now();
1611
- while (Date.now() - start < TIMEOUT_MS) {
1612
- const parts = await storage.part.listBySession(input.sessionId);
1613
- if (!(parts instanceof Error)) {
1614
- const updated = parts.items.find(
1615
- (p) => p.id === partId && "state" in p.part && p.part.state === "approval-responded"
1616
- );
1617
- if (updated) {
1618
- const approval = updated.part.approval;
1619
- if (approval?.approved) {
1620
- try {
1621
- const result2 = await execute();
1622
- streamWriterRef.current?.({
1623
- type: "tool-output-available",
1624
- toolCallId,
1625
- output: result2
1626
- });
1627
- return { result: result2 };
1628
- } catch (err) {
1629
- const error = err instanceof Error ? err.message : String(err);
1630
- streamWriterRef.current?.({
1631
- type: "tool-output-error",
1632
- toolCallId,
1633
- errorText: error
1634
- });
1635
- return { error };
1636
- }
1637
- }
1638
- streamWriterRef.current?.({
1639
- type: "tool-output-denied",
1640
- toolCallId
1641
- });
1642
- return {
1643
- error: `Tool "${toolName}" denied: ${approval?.reason || "user denied"}`
1644
- };
1645
- }
1646
- }
1647
- await new Promise((r) => setTimeout(r, POLL_MS));
1648
- }
1649
- return { error: "Approval timed out" };
1650
- };
1651
- const rawTools = getTools({
1652
- input,
1653
- rpc,
1654
- event,
1655
- sandbox,
1656
- session,
1657
- sandboxRecord,
1658
- apiToolsMetadata,
1659
- onSubToolCall
1660
- });
1661
- if (!session.model) {
1662
- throw new FatalError("Session model is not set");
1663
- }
1664
- const allParts = partsResult.items;
1665
- const usageSteps = [];
1666
- let internalStepIndex = 0;
1667
- const tools = Object.fromEntries(
1668
- Object.entries(rawTools).map(([name, t]) => [
1669
- name,
1670
- {
1671
- ...t,
1672
- needsApproval: async (toolInput, opts) => {
1673
- const res = await rpc({
1674
- method: "tools.needsApproval",
1675
- params: {
1676
- toolName: name,
1677
- input: toolInput,
1678
- toolCallId: opts.toolCallId,
1679
- messages: opts.messages
1680
- }
1681
- });
1682
- if ("error" in res) {
1683
- throw new Error(
1684
- `tools.needsApproval RPC failed for ${name}: ${res.error.message}`
1685
- );
1686
- }
1687
- return res.result;
1688
- }
1689
- }
1690
- ])
1691
- );
1692
- let skillsRef = [];
1693
- const result = streamText({
1694
- // Placeholder to pass validation — prepareStep replaces messages entirely.
1695
- messages: [{ role: "user", content: "." }],
1696
- tools,
1697
- model: session.model,
1698
- abortSignal: abortController.signal,
1699
- activeTools: session.activeTools ?? void 0,
1700
- stopWhen: stepCountIs(1),
1701
- temperature: session.generation?.temperature,
1702
- topK: session.generation?.topK,
1703
- topP: session.generation?.topP,
1704
- frequencyPenalty: session.generation?.frequencyPenalty,
1705
- presencePenalty: session.generation?.presencePenalty,
1706
- maxOutputTokens: session.generation?.maxOutputTokens,
1707
- headers: session.generation?.headers,
1708
- experimental_context: {
1709
- session,
1710
- sandbox,
1711
- storage,
1712
- context: event.context
1713
- },
1714
- prepareStep: async ({ model }) => {
1715
- if (lastPartIndex === 0) {
1716
- if (sandbox._setupMeta) {
1717
- const meta = await sandbox._setupMeta;
1718
- emitStatus({
1719
- writer: streamWriterRef.current,
1720
- status: meta.needsSetupRun ? { type: "sandbox-setup-cold" } : { type: "sandbox-setup" },
1721
- rpc
1722
- });
1723
- }
1724
- if (sandbox._onReady) {
1725
- await sandbox._onReady;
1726
- }
1727
- emitStatus({
1728
- writer: streamWriterRef.current,
1729
- status: { type: "loading-skills" },
1730
- rpc
1731
- });
1732
- const skills = await discoverSkillsInSandbox({
1733
- sandbox,
1734
- skillsDirs: session.skillsDir || [],
1735
- debug: true
1736
- });
1737
- skillsRef = skills;
1738
- }
1739
- const approvedParts = allParts.filter(
1740
- (p) => p.part && "state" in p.part && p.part.state === "approval-responded" && "approval" in p.part && p.part.approval?.approved === true
1741
- );
1742
- if (approvedParts.length > 0) {
1743
- emitStatus({
1744
- writer: streamWriterRef.current,
1745
- status: { type: "processing-approvals" },
1746
- rpc
1747
- });
1748
- const preExecMessages = await convertToModelMessages(
1749
- assembleUIMessages({
1750
- messages: messagesResult.items,
1751
- parts: allParts,
1752
- until: event.createdAt,
1753
- includeQueued: true,
1754
- excludeSubToolParts: true
1755
- }),
1756
- { ignoreIncompleteToolCalls: true }
1757
- );
1758
- await Promise.all(
1759
- approvedParts.map(async (ap) => {
1760
- if (!ap.part.type.startsWith("tool-")) {
1761
- return;
1762
- }
1763
- const part = ap.part;
1764
- const toolName = part.type.replace("tool-", "");
1765
- const toolDef = rawTools[toolName];
1766
- if (toolDef?.execute && part.input !== void 0) {
1767
- try {
1768
- const toolOutput = await toolDef.execute(part.input, {
1769
- toolCallId: part.toolCallId,
1770
- messages: preExecMessages,
1771
- abortSignal: abortController.signal,
1772
- experimental_context: {
1773
- session,
1774
- sandbox,
1775
- storage,
1776
- context: event.context
1777
- }
1778
- });
1779
- part.state = "output-available";
1780
- part.output = toolOutput;
1781
- streamWriterRef.current?.({
1782
- type: "tool-output-available",
1783
- toolCallId: part.toolCallId,
1784
- output: toolOutput
1785
- });
1786
- } catch (err) {
1787
- part.state = "output-error";
1788
- part.errorText = err instanceof Error ? err.message : String(err);
1789
- streamWriterRef.current?.({
1790
- type: "tool-output-error",
1791
- toolCallId: part.toolCallId,
1792
- errorText: part.errorText
1793
- });
1794
- }
1795
- await storage.part.set({ ...ap, part });
1796
- }
1797
- })
1798
- );
1799
- }
1800
- emitStatus({
1801
- writer: streamWriterRef.current,
1802
- status: { type: "thinking" },
1803
- rpc
1804
- });
1805
- const skillsContext = buildSkillsContext(skillsRef);
1806
- const systemHeader = joinPromptSections(
1807
- BASE_SYSTEM_PROMPT,
1808
- session.system
1809
- );
1810
- const systemContext = joinPromptSections(skillsContext);
1811
- const systemMessages = [
1812
- ...systemHeader.trim() ? [{ role: "system", content: systemHeader }] : [],
1813
- ...systemContext.trim() ? [{ role: "system", content: systemContext }] : []
1814
- ];
1815
- const uiMessages = assembleUIMessages({
1816
- messages: messagesResult.items,
1817
- parts: allParts,
1818
- until: event.createdAt,
1819
- includeQueued: true,
1820
- excludeSubToolParts: true
1821
- });
1822
- const modelMessages = [
1823
- ...systemMessages,
1824
- ...await convertToModelMessages(uiMessages, {
1825
- ignoreIncompleteToolCalls: true
1826
- })
1827
- ];
1828
- const promptCaching = applyPromptCachingToModelRequest({
1829
- model: typeof model === "string" ? model : model.modelId,
1830
- sessionId: input.sessionId,
1831
- messages: modelMessages
1832
- });
1833
- return {
1834
- messages: promptCaching.messages,
1835
- providerOptions: promptCaching.providerOptions
1836
- };
1837
- },
1838
- onStepFinish: ({ usage }) => {
1839
- if (usage) {
1840
- usageSteps.push({
1841
- stepIndex: stepIndexOffset + internalStepIndex,
1842
- model: session.model ?? "unknown",
1843
- inputTokens: usage.inputTokens ?? 0,
1844
- outputTokens: usage.outputTokens ?? 0,
1845
- totalTokens: usage.totalTokens ?? 0,
1846
- cacheReadTokens: usage.inputTokenDetails?.cacheReadTokens ?? 0,
1847
- cacheWriteTokens: usage.inputTokenDetails?.cacheWriteTokens ?? 0,
1848
- reasoningTokens: usage.outputTokenDetails?.reasoningTokens ?? 0
1849
- });
1850
- }
1851
- internalStepIndex++;
1852
- }
1853
- });
1854
- const stepParts = [];
1855
- let wasAborted = false;
1856
- try {
1857
- const stream = createUIMessageStream({
1858
- execute: ({ writer }) => {
1859
- streamWriterRef.current = (event2) => writer.write(event2);
1860
- writer.merge(
1861
- result.toUIMessageStream({
1862
- generateMessageId: () => assistantMessageId,
1863
- onFinish: ({ messages }) => {
1864
- let hasApprovals = false;
1865
- for (const m of messages) {
1866
- if (m.role === "assistant") {
1867
- stepParts.push(...m.parts);
1868
- for (const p of m.parts) {
1869
- if ("state" in p && p.state === "approval-requested") {
1870
- hasApprovals = true;
1871
- }
1872
- }
1873
- }
1874
- }
1875
- if (hasApprovals) {
1876
- emitStatus({
1877
- writer: streamWriterRef.current,
1878
- status: { type: "needs-approval" },
1879
- rpc
1880
- });
1881
- }
1882
- }
1883
- })
1884
- );
1885
- }
1886
- });
1887
- await stream.pipeTo(writable, { preventClose: true });
1888
- } catch (err) {
1889
- if (abortController.signal.aborted) {
1890
- wasAborted = true;
1891
- } else {
1892
- console.error("[streamTextStep] stream error:", err);
1893
- throw err;
1894
- }
1895
- } finally {
1896
- pollController.abort();
1897
- }
1898
- await Promise.all(
1899
- stepParts.map(async (uiPart) => {
1900
- const result2 = await storage.part.set({
1901
- id: `part_${ulid()}`,
1902
- index: nextPartIndex++,
1903
- messageId: assistantMessageId,
1904
- sessionId: input.sessionId,
1905
- part: uiPart
1906
- });
1907
- if (result2 instanceof Error) {
1908
- throw result2;
1909
- }
1910
- return result2;
1911
- })
1912
- );
1913
- if (setStartedPromise) {
1914
- const setStartedResult = await setStartedPromise;
1915
- if (setStartedResult instanceof Error) {
1916
- throw setStartedResult;
1917
- }
1918
- for (const m of setStartedResult ?? []) {
1919
- if (m instanceof Error) {
1920
- throw m;
1921
- }
1922
- }
1923
- }
1924
- const pendingApprovals = stepParts.filter(
1925
- (p) => "state" in p && p.state === "approval-requested" && "approval" in p && !!p.approval?.id
1926
- ).map((p) => ({
1927
- approvalId: p.approval.id,
1928
- toolName: "type" in p ? String(p.type).replace("tool-", "") : "unknown"
1929
- }));
1930
- const finalFinishReason = wasAborted ? "stop" : await result.finishReason;
1931
- return {
1932
- finishReason: finalFinishReason,
1933
- lastPartIndex: nextPartIndex,
1934
- usageSteps,
1935
- pendingApprovals,
1936
- maxSteps: session.generation?.maxSteps
1937
- };
1938
- }
1939
-
1940
- // src/agent-workflow.ts
1941
- var agentMessageHook = defineHook();
1942
- var approvalHook = defineHook();
1943
- async function agentWorkflow({
1944
- input,
1945
- event
1946
- }) {
1947
- "use workflow";
1948
- const messageHook = agentMessageHook.create({ token: input.sessionId });
1949
- const iterator = messageHook[Symbol.asyncIterator]();
1950
- let pendingNext = iterator.next();
1951
- await onMessage({ event, input }).catch((e) => {
1952
- if (FatalError2.is(e)) {
1953
- console.error("Message processing failed permanently:", e.message);
1954
- return;
1955
- }
1956
- throw e;
1957
- });
1958
- while (true) {
1959
- const result = await pendingNext;
1960
- if (result.done) {
1961
- console.error("Unexpected: message hook iterator done");
1962
- break;
1963
- }
1964
- await onMessage({ event: result.value, input }).catch((e) => {
1965
- if (FatalError2.is(e)) {
1966
- console.error("Message processing failed permanently:", e.message);
1967
- return;
1968
- }
1969
- throw e;
1970
- });
1971
- pendingNext = iterator.next();
1972
- }
1973
- }
1974
- async function onMessage({
1975
- event,
1976
- input
1977
- }) {
1978
- const writable = getWritable({ namespace: event.assistantMessageId });
1979
- let finishReason;
1980
- let lastPartIndex = 0;
1981
- const usageSteps = [];
1982
- while (finishReason !== "stop") {
1983
- try {
1984
- const result = await streamTextStep({
1985
- assistantMessageId: event.assistantMessageId,
1986
- writable,
1987
- input,
1988
- event,
1989
- lastPartIndex,
1990
- stepIndexOffset: usageSteps.length
1991
- });
1992
- finishReason = result.finishReason;
1993
- lastPartIndex = result.lastPartIndex;
1994
- usageSteps.push(...result.usageSteps);
1995
- if (result.maxSteps != null && usageSteps.length >= result.maxSteps) {
1996
- break;
1997
- }
1998
- if (result.pendingApprovals.length > 0) {
1999
- await Promise.all(
2000
- result.pendingApprovals.map((pending) => {
2001
- const hook = approvalHook.create({ token: pending.approvalId });
2002
- const iter = hook[Symbol.asyncIterator]();
2003
- return iter.next();
2004
- })
2005
- );
2006
- }
2007
- } catch (err) {
2008
- console.error(err);
2009
- throw err;
2010
- }
2011
- }
2012
- await completeMessageStep({
2013
- assistantMessageId: event.assistantMessageId,
2014
- input,
2015
- writable,
2016
- usageSteps
2017
- });
2018
- }
2019
-
2020
- export {
2021
- normalizeSkillsDirs,
2022
- builtInTools,
2023
- builtinToolNames,
2024
- resolveApiUrl,
2025
- assembleUIMessages,
2026
- computeSessionUsage,
2027
- agentMessageHook,
2028
- approvalHook,
2029
- agentWorkflow
2030
- };
2031
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2FnZW50LXdvcmtmbG93LnRzIiwgIi4uL3NyYy9hZ2VudC13b3JrZmxvdy1zdGVwcy50cyIsICIuLi9zcmMvc2tpbGxzL3BhcnNlci50cyIsICIuLi9zcmMvc2tpbGxzL2Rpc2NvdmVyLnRzIiwgIi4uL3NyYy90b29scy9pbmRleC50cyIsICIuLi9zcmMvdG9vbHMvamF2YXNjcmlwdC50cyIsICIuLi9zcmMvdXRpbHMvcHJvbXB0LWNhY2hlLnRzIiwgIi4uL3NyYy91dGlscy91aS50cyIsICIuLi9zcmMvdXRpbHMvdXNhZ2UudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCB0eXBlIHsgRmluaXNoUmVhc29uIH0gZnJvbSBcImFpXCI7XG5pbXBvcnQgeyBkZWZpbmVIb29rLCBGYXRhbEVycm9yLCBnZXRXcml0YWJsZSB9IGZyb20gXCJ3b3JrZmxvd1wiO1xuaW1wb3J0IHsgY29tcGxldGVNZXNzYWdlU3RlcCwgc3RyZWFtVGV4dFN0ZXAgfSBmcm9tIFwiLi9hZ2VudC13b3JrZmxvdy1zdGVwc1wiO1xuaW1wb3J0IHR5cGUgeyBTdG9yYWdlQ29uZmlnIH0gZnJvbSBcIi4vc3RvcmFnZVwiO1xuaW1wb3J0IHR5cGUgeyBTdGVwVXNhZ2UgfSBmcm9tIFwiLi91dGlscy91c2FnZVwiO1xuXG5leHBvcnQgdHlwZSBBZ2VudElucHV0ID0ge1xuICBzZXNzaW9uSWQ6IHN0cmluZztcbiAgc3RvcmFnZUNvbmZpZzogU3RvcmFnZUNvbmZpZztcbn07XG5cbmV4cG9ydCB0eXBlIEFnZW50TWVzc2FnZUlucHV0ID0ge1xuICBhc3Npc3RhbnRNZXNzYWdlSWQ6IHN0cmluZztcbiAgaG9va1Rva2VuOiBzdHJpbmc7XG4gIGNyZWF0ZWRBdDogbnVtYmVyO1xuICBjb250ZXh0OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbn07XG5cbmV4cG9ydCB0eXBlIEFwcHJvdmFsUmVzcG9uc2UgPSB7XG4gIGFwcHJvdmVkOiBib29sZWFuO1xuICByZWFzb24/OiBzdHJpbmc7XG59O1xuXG5leHBvcnQgY29uc3QgYWdlbnRNZXNzYWdlSG9vayA9IGRlZmluZUhvb2s8QWdlbnRNZXNzYWdlSW5wdXQ+KCk7XG5leHBvcnQgY29uc3QgYXBwcm92YWxIb29rID0gZGVmaW5lSG9vazxBcHByb3ZhbFJlc3BvbnNlPigpO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYWdlbnRXb3JrZmxvdyh7XG4gIGlucHV0LFxuICBldmVudCxcbn06IHtcbiAgaW5wdXQ6IEFnZW50SW5wdXQ7XG4gIGV2ZW50OiBBZ2VudE1lc3NhZ2VJbnB1dDtcbn0pIHtcbiAgXCJ1c2Ugd29ya2Zsb3dcIjtcblxuICBjb25zdCBtZXNzYWdlSG9vayA9IGFnZW50TWVzc2FnZUhvb2suY3JlYXRlKHsgdG9rZW46IGlucHV0LnNlc3Npb25JZCB9KTtcbiAgY29uc3QgaXRlcmF0b3IgPSBtZXNzYWdlSG9va1tTeW1ib2wuYXN5bmNJdGVyYXRvcl0oKTtcbiAgbGV0IHBlbmRpbmdOZXh0ID0gaXRlcmF0b3IubmV4dCgpO1xuXG4gIGF3YWl0IG9uTWVzc2FnZSh7IGV2ZW50LCBpbnB1dCB9KS5jYXRjaCgoZSkgPT4ge1xuICAgIGlmIChGYXRhbEVycm9yLmlzKGUpKSB7XG4gICAgICBjb25zb2xlLmVycm9yKFwiTWVzc2FnZSBwcm9jZXNzaW5nIGZhaWxlZCBwZXJtYW5lbnRseTpcIiwgZS5tZXNzYWdlKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhyb3cgZTtcbiAgfSk7XG5cbiAgd2hpbGUgKHRydWUpIHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBwZW5kaW5nTmV4dDtcblxuICAgIGlmIChyZXN1bHQuZG9uZSkge1xuICAgICAgY29uc29sZS5lcnJvcihcIlVuZXhwZWN0ZWQ6IG1lc3NhZ2UgaG9vayBpdGVyYXRvciBkb25lXCIpO1xuICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgYXdhaXQgb25NZXNzYWdlKHsgZXZlbnQ6IHJlc3VsdC52YWx1ZSwgaW5wdXQgfSkuY2F0Y2goKGUpID0+IHtcbiAgICAgIGlmIChGYXRhbEVycm9yLmlzKGUpKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXCJNZXNzYWdlIHByb2Nlc3NpbmcgZmFpbGVkIHBlcm1hbmVudGx5OlwiLCBlLm1lc3NhZ2UpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB0aHJvdyBlO1xuICAgIH0pO1xuICAgIHBlbmRpbmdOZXh0ID0gaXRlcmF0b3IubmV4dCgpO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG9uTWVzc2FnZSh7XG4gIGV2ZW50LFxuICBpbnB1dCxcbn06IHtcbiAgZXZlbnQ6IEFnZW50TWVzc2FnZUlucHV0O1xuICBpbnB1dDogQWdlbnRJbnB1dDtcbn0pIHtcbiAgY29uc3Qgd3JpdGFibGUgPSBnZXRXcml0YWJsZSh7IG5hbWVzcGFjZTogZXZlbnQuYXNzaXN0YW50TWVzc2FnZUlkIH0pO1xuXG4gIGxldCBmaW5pc2hSZWFzb246IEZpbmlzaFJlYXNvbiB8IHVuZGVmaW5lZDtcbiAgbGV0IGxhc3RQYXJ0SW5kZXggPSAwO1xuICBjb25zdCB1c2FnZVN0ZXBzOiBTdGVwVXNhZ2VbXSA9IFtdO1xuXG4gIHdoaWxlIChmaW5pc2hSZWFzb24gIT09IFwic3RvcFwiKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHN0cmVhbVRleHRTdGVwKHtcbiAgICAgICAgYXNzaXN0YW50TWVzc2FnZUlkOiBldmVudC5hc3Npc3RhbnRNZXNzYWdlSWQsXG4gICAgICAgIHdyaXRhYmxlLFxuICAgICAgICBpbnB1dCxcbiAgICAgICAgZXZlbnQsXG4gICAgICAgIGxhc3RQYXJ0SW5kZXgsXG4gICAgICAgIHN0ZXBJbmRleE9mZnNldDogdXNhZ2VTdGVwcy5sZW5ndGgsXG4gICAgICB9KTtcbiAgICAgIGZpbmlzaFJlYXNvbiA9IHJlc3VsdC5maW5pc2hSZWFzb247XG4gICAgICBsYXN0UGFydEluZGV4ID0gcmVzdWx0Lmxhc3RQYXJ0SW5kZXg7XG4gICAgICB1c2FnZVN0ZXBzLnB1c2goLi4ucmVzdWx0LnVzYWdlU3RlcHMpO1xuXG4gICAgICBpZiAocmVzdWx0Lm1heFN0ZXBzICE9IG51bGwgJiYgdXNhZ2VTdGVwcy5sZW5ndGggPj0gcmVzdWx0Lm1heFN0ZXBzKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgICAvLyBJZiB0b29scyBuZWVkIGFwcHJvdmFsLCBzdXNwZW5kIHdvcmtmbG93IHVudGlsIGFsbCBhcmUgcmVzb2x2ZWRcbiAgICAgIGlmIChyZXN1bHQucGVuZGluZ0FwcHJvdmFscy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICAgIHJlc3VsdC5wZW5kaW5nQXBwcm92YWxzLm1hcCgocGVuZGluZykgPT4ge1xuICAgICAgICAgICAgY29uc3QgaG9vayA9IGFwcHJvdmFsSG9vay5jcmVhdGUoeyB0b2tlbjogcGVuZGluZy5hcHByb3ZhbElkIH0pO1xuICAgICAgICAgICAgY29uc3QgaXRlciA9IGhvb2tbU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCk7XG4gICAgICAgICAgICByZXR1cm4gaXRlci5uZXh0KCk7XG4gICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICAgICAgLy8gQWxsIGhvb2tzIHJlc29sdmVkIFx1MjAxNCBhcHByb3ZhbCByZXNwb25zZXMgYXJlIG5vdyBpbiBzdG9yYWdlLlxuICAgICAgICAvLyBMb29wIGNvbnRpbnVlcyBcdTIxOTIgbmV4dCBzdHJlYW1UZXh0U3RlcCByZWFkcyB1cGRhdGVkIHBhcnRzLlxuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY29uc29sZS5lcnJvcihlcnIpO1xuICAgICAgdGhyb3cgZXJyO1xuICAgIH1cbiAgfVxuXG4gIGF3YWl0IGNvbXBsZXRlTWVzc2FnZVN0ZXAoe1xuICAgIGFzc2lzdGFudE1lc3NhZ2VJZDogZXZlbnQuYXNzaXN0YW50TWVzc2FnZUlkLFxuICAgIGlucHV0LFxuICAgIHdyaXRhYmxlLFxuICAgIHVzYWdlU3RlcHMsXG4gIH0pO1xufVxuIiwgImltcG9ydCB7XG4gIGNvbnZlcnRUb01vZGVsTWVzc2FnZXMsXG4gIGNyZWF0ZVVJTWVzc2FnZVN0cmVhbSxcbiAgdHlwZSBGaW5pc2hSZWFzb24sXG4gIHN0ZXBDb3VudElzLFxuICBzdHJlYW1UZXh0LFxuICB0eXBlIFVJTWVzc2FnZSxcbn0gZnJvbSBcImFpXCI7XG5pbXBvcnQgeyB1bGlkIH0gZnJvbSBcInVsaWRcIjtcbmltcG9ydCB7IEZhdGFsRXJyb3IgfSBmcm9tIFwid29ya2Zsb3dcIjtcbmltcG9ydCB0eXBlIHsgQWdlbnRJbnB1dCwgQWdlbnRNZXNzYWdlSW5wdXQgfSBmcm9tIFwiLi9hZ2VudC13b3JrZmxvd1wiO1xuaW1wb3J0IHR5cGUgeyBBZ2VudFN0YXR1cywgUnBjUGF5bG9hZCwgUnBjUmVzdWx0IH0gZnJvbSBcIi4vY2xpZW50XCI7XG5pbXBvcnQgeyByZXNvbHZlUnBjIH0gZnJvbSBcIi4vcnBjLXJlZ2lzdHJ5XCI7XG5pbXBvcnQgeyBkaXNjb3ZlclNraWxsc0luU2FuZGJveCB9IGZyb20gXCIuL3NraWxscy9kaXNjb3ZlclwiO1xuaW1wb3J0IHR5cGUgeyBTa2lsbFN1bW1hcnkgfSBmcm9tIFwiLi9za2lsbHMvdHlwZXNcIjtcbmltcG9ydCB0eXBlIHsgU2FuZGJveFJlY29yZCwgU3RvcmFnZSB9IGZyb20gXCIuL3N0b3JhZ2VcIjtcbmltcG9ydCB7IGZldGNoQXBpVG9vbHNNZXRhZGF0YSwgZ2V0VG9vbHMgfSBmcm9tIFwiLi90b29sc1wiO1xuaW1wb3J0IHR5cGUgeyBPblN1YlRvb2xDYWxsIH0gZnJvbSBcIi4vdG9vbHMvamF2YXNjcmlwdFwiO1xuaW1wb3J0IHsgYXBwbHlQcm9tcHRDYWNoaW5nVG9Nb2RlbFJlcXVlc3QgfSBmcm9tIFwiLi91dGlscy9wcm9tcHQtY2FjaGVcIjtcbmltcG9ydCB7IGFzc2VtYmxlVUlNZXNzYWdlcyB9IGZyb20gXCIuL3V0aWxzL3VpXCI7XG5pbXBvcnQgeyBjb21wdXRlVXNhZ2VTdW1tYXJ5LCB0eXBlIFN0ZXBVc2FnZSB9IGZyb20gXCIuL3V0aWxzL3VzYWdlXCI7XG5cbi8qKlxuICogRmlyZS1hbmQtZm9yZ2V0IHN0YXR1cyBlbWlzc2lvbi4gV3JpdGVzIGEgdHJhbnNpZW50IGBkYXRhLXN0YXR1c2AgY2h1bmtcbiAqIHRvIHRoZSBzdHJlYW0gYW5kIGNhbGxzIHRoZSBgaG9vay5zdGF0dXNgIFJQQy4gTmVpdGhlciBibG9ja3MgdGhlIGNhbGxlci5cbiAqL1xuZnVuY3Rpb24gZW1pdFN0YXR1cyh7XG4gIHdyaXRlcixcbiAgc3RhdHVzLFxuICBycGMsXG59OiB7XG4gIHdyaXRlcjogKChldmVudDogdW5rbm93bikgPT4gdm9pZCkgfCBudWxsO1xuICBzdGF0dXM6IEFnZW50U3RhdHVzO1xuICBycGM6IChwYXJhbXM6IFJwY1BheWxvYWQpID0+IFByb21pc2U8UnBjUmVzdWx0Pjtcbn0pIHtcbiAgd3JpdGVyPy4oeyB0eXBlOiBcImRhdGEtc3RhdHVzXCIsIGRhdGE6IHN0YXR1cywgdHJhbnNpZW50OiB0cnVlIH0pO1xuICAvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL25vRW1wdHlCbG9ja1N0YXRlbWVudHM6IGZpcmUtYW5kLWZvcmdldFxuICBycGMoeyBtZXRob2Q6IFwiaG9vay5zdGF0dXNcIiwgcGFyYW1zOiB7IHN0YXR1cyB9IH0pLmNhdGNoKCgpID0+IHt9KTtcbn1cblxuY29uc3QgQkFTRV9TWVNURU1fUFJPTVBUID1cbiAgXCJZb3UgYXJlIGFuIEFJIGFzc2lzdGFudCB3aXRoIGJhc2ljIHRvb2xzIHRvIGludGVyYWN0IHdpdGggeW91ciBlbnZpcm9ubWVudC4gRXhwbG9yZSBhbmQgd29yayBmcmVlbHkuXCI7XG5cbmZ1bmN0aW9uIGpvaW5Qcm9tcHRTZWN0aW9ucyhcbiAgLi4uc2VjdGlvbnM6IChzdHJpbmcgfCB1bmRlZmluZWQgfCBudWxsKVtdXG4pOiBzdHJpbmcge1xuICByZXR1cm4gc2VjdGlvbnMuZmlsdGVyKChzKSA9PiBzPy50cmltKCkpLmpvaW4oXCJcXG5cXG5cIik7XG59XG5cbmNvbnN0IGJhY2tncm91bmRQcm9jZXNzUHJvbXB0ID0gYCMjIEJhY2tncm91bmQgUHJvY2Vzc2VzXG5UaGVzZSBiYWNrZ3JvdW5kIHByb2Nlc3MgaW5zdHJ1Y3Rpb25zIGFyZSBmb3IgeW91IHRvIG1hbmlwdWxhdGUgdGhlIHByb2Nlc3NlcywgZG8gbm90IGJlIHRvIHZlcmJvc2UgdG8gdGhlIHVzZXIgYWJvdXQgdGhlIHJlc3BvbnNlIGRldGFpbHMgbGlrZSBcImhvdyB0byBkZWJ1ZyB0aGUgcHJvY2VzcyBvdXRwdXRcIiB0aGUgdXNlciB3aWxsIGhhdmUgYW4gVUkuXG5cblVzZSBcXGB3YWl0VW50aWw6IDBcXGAgZm9yIGRldiBzZXJ2ZXJzIHRoYXQgc2hvdWxkIHJ1biBpbmRlZmluaXRlbHkuXG5JdCBpcyBhIGdvb2QgcHJhY3RpY2UgdG8gY2hlY2sgdGhlIG91dHB1dCBsb2cgYWZ0ZXIgcnVubmluZyBwcm9jZXNzZXMgbGlrZSBkZXYgc2VydmVycyB0byBtYWtlIHN1cmUgdGhleSBzdGFydGVkIGNvcnJlY3RseS5cblxuVG8gcnVuIGEgYmFja2dyb3VuZCBwcm9jZXNzOlxuQmFzaCh7IGNvbW1hbmQ6IFwibnBtIHJ1biBkZXZcIiwgd2FpdFVudGlsOiAwIH0pXG5SZXR1cm5zIGltbWVkaWF0ZWx5IHdpdGggXFxgcGlkXFxgIGFuZCBcXGBvdXRwdXRGaWxlXFxgIHBhdGguXG5cblRvIGNoZWNrIGEgcHJvY2VzcydzIG91dHB1dDpcbkJhc2goeyBjb21tYW5kOiBcInRhaWwgLTEwMCB7b3V0cHV0RmlsZX1cIiB9KVxuXG5UbyBraWxsIGEgcHJvY2VzczpcbkJhc2goeyBjb21tYW5kOiBcImtpbGwge3BpZH1cIiB9KSAgICAgICAvLyBHcmFjZWZ1bFxuQmFzaCh7IGNvbW1hbmQ6IFwia2lsbCAtOSB7cGlkfVwiIH0pICAgIC8vIEZvcmNlXG5cblRvIGxpc3QgYWxsIHByb2Nlc3NlczpcbkJhc2goeyBjb21tYW5kOiBcInBzIGF1eCB8IGdyZXAgbm9kZVwiIH0pXG5gO1xuXG5mdW5jdGlvbiBidWlsZFNraWxsc0NvbnRleHQoc2tpbGxzOiBTa2lsbFN1bW1hcnlbXSk6IHN0cmluZyB7XG4gIGlmIChza2lsbHMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIFwiXCI7XG4gIH1cblxuICBjb25zdCBza2lsbExpbmVzID0gc2tpbGxzXG4gICAgLm1hcCgocykgPT4gYC0gJHtzLm5hbWV9OiAke3MuZGVzY3JpcHRpb259XFxuICBQYXRoOiAke3Muc2tpbGxNZFBhdGh9YClcbiAgICAuam9pbihcIlxcblwiKTtcblxuICByZXR1cm4gYCMjIEF2YWlsYWJsZSBTa2lsbHNcbiR7c2tpbGxMaW5lc31cblxuJHtiYWNrZ3JvdW5kUHJvY2Vzc1Byb21wdH1cblxuWW91IGNhbiB1c2UgdGhlIFJlYWQgdG9vbCB0byByZWFkIGFueSBza2lsbCdzIFNLSUxMLm1kIGZpbGUgdG8gbGVhcm4gbW9yZSBhYm91dCBpdC5gO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY29tcGxldGVNZXNzYWdlU3RlcCh7XG4gIGFzc2lzdGFudE1lc3NhZ2VJZCxcbiAgaW5wdXQsXG4gIHdyaXRhYmxlLFxuICB1c2FnZVN0ZXBzLFxufToge1xuICBhc3Npc3RhbnRNZXNzYWdlSWQ6IHN0cmluZztcbiAgaW5wdXQ6IEFnZW50SW5wdXQ7XG4gIHdyaXRhYmxlOiBXcml0YWJsZVN0cmVhbTtcbiAgdXNhZ2VTdGVwczogU3RlcFVzYWdlW107XG59KSB7XG4gIFwidXNlIHN0ZXBcIjtcblxuICBjb25zdCB7IGdldFN0b3JhZ2UgfSA9IGF3YWl0IGltcG9ydChcIi4vc3RvcmFnZS9jbGllbnRcIik7XG4gIGNvbnN0IHJwYyA9IHJlc29sdmVScGMoaW5wdXQuc3RvcmFnZUNvbmZpZy5uYW1lID8/IFwiZGVmYXVsdFwiKTtcbiAgY29uc3Qgc3RvcmFnZSA9IGdldFN0b3JhZ2UoeyBjb25maWc6IGlucHV0LnN0b3JhZ2VDb25maWcsIHJwYyB9KTtcblxuICBjb25zdCBtZXNzYWdlID0gYXdhaXQgc3RvcmFnZS5tZXNzYWdlLmdldChhc3Npc3RhbnRNZXNzYWdlSWQpO1xuICBpZiAobWVzc2FnZSBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgdGhyb3cgbWVzc2FnZTtcbiAgfVxuICBpZiAoIW1lc3NhZ2UpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYE1lc3NhZ2UgJHthc3Npc3RhbnRNZXNzYWdlSWR9IG5vdCBmb3VuZGApO1xuICB9XG5cbiAgY29uc3QgdXNhZ2UgPVxuICAgIHVzYWdlU3RlcHMubGVuZ3RoID4gMFxuICAgICAgPyB7XG4gICAgICAgICAgc3RlcHM6IHVzYWdlU3RlcHMsXG4gICAgICAgICAgc3VtbWFyeTogY29tcHV0ZVVzYWdlU3VtbWFyeSh1c2FnZVN0ZXBzKSxcbiAgICAgICAgfVxuICAgICAgOiBudWxsO1xuXG4gIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHN0b3JhZ2UubWVzc2FnZS5zZXQoe1xuICAgIC4uLm1lc3NhZ2UsXG4gICAgY29tcGxldGVkQXQ6IERhdGUubm93KCksXG4gICAgdXNhZ2UsXG4gIH0pO1xuICBpZiAocmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICB0aHJvdyByZXN1bHQ7XG4gIH1cblxuICBhd2FpdCB3cml0YWJsZS5jbG9zZSgpO1xufVxuXG5jb25zdCBJTlRFUlJVUFRfUE9MTF9JTlRFUlZBTF9NUyA9IDUwMDtcblxuZnVuY3Rpb24gcG9sbEZvckludGVycnVwdCh7XG4gIHN0b3JhZ2UsXG4gIG1lc3NhZ2VJZCxcbiAgc2lnbmFsLFxuICBhYm9ydENvbnRyb2xsZXIsXG59OiB7XG4gIHN0b3JhZ2U6IFN0b3JhZ2U7XG4gIG1lc3NhZ2VJZDogc3RyaW5nO1xuICBzaWduYWw6IEFib3J0U2lnbmFsO1xuICBhYm9ydENvbnRyb2xsZXI6IEFib3J0Q29udHJvbGxlcjtcbn0pOiB7IGZpcnN0Q2hlY2s6IFByb21pc2U8dm9pZD4gfSB7XG4gIGxldCByZXNvbHZlRmlyc3RDaGVjazogKCkgPT4gdm9pZDtcbiAgY29uc3QgZmlyc3RDaGVjayA9IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlKSA9PiB7XG4gICAgcmVzb2x2ZUZpcnN0Q2hlY2sgPSByZXNvbHZlO1xuICB9KTtcblxuICBjb25zdCBwb2xsID0gYXN5bmMgKCkgPT4ge1xuICAgIGxldCBpc0ZpcnN0ID0gdHJ1ZTtcbiAgICB3aGlsZSAoIXNpZ25hbC5hYm9ydGVkKSB7XG4gICAgICBjb25zdCBtZXNzYWdlID0gYXdhaXQgc3RvcmFnZS5tZXNzYWdlLmdldChtZXNzYWdlSWQpO1xuICAgICAgaWYgKG1lc3NhZ2UgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICBpZiAoaXNGaXJzdCkge1xuICAgICAgICAgIHJlc29sdmVGaXJzdENoZWNrKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKG1lc3NhZ2UuaW50ZXJydXB0ZWRBdCAhPT0gbnVsbCkge1xuICAgICAgICBhYm9ydENvbnRyb2xsZXIuYWJvcnQoKTtcbiAgICAgICAgaWYgKGlzRmlyc3QpIHtcbiAgICAgICAgICByZXNvbHZlRmlyc3RDaGVjaygpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmIChpc0ZpcnN0KSB7XG4gICAgICAgIGlzRmlyc3QgPSBmYWxzZTtcbiAgICAgICAgcmVzb2x2ZUZpcnN0Q2hlY2soKTtcbiAgICAgIH1cbiAgICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PlxuICAgICAgICBzZXRUaW1lb3V0KHJlc29sdmUsIElOVEVSUlVQVF9QT0xMX0lOVEVSVkFMX01TKVxuICAgICAgKTtcbiAgICB9XG4gIH07XG5cbiAgcG9sbCgpO1xuICByZXR1cm4geyBmaXJzdENoZWNrIH07XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzdHJlYW1UZXh0U3RlcCh7XG4gIGFzc2lzdGFudE1lc3NhZ2VJZCxcbiAgaW5wdXQsXG4gIGV2ZW50LFxuICB3cml0YWJsZSxcbiAgbGFzdFBhcnRJbmRleCxcbiAgc3RlcEluZGV4T2Zmc2V0LFxufToge1xuICBhc3Npc3RhbnRNZXNzYWdlSWQ6IHN0cmluZztcbiAgaW5wdXQ6IEFnZW50SW5wdXQ7XG4gIGV2ZW50OiBBZ2VudE1lc3NhZ2VJbnB1dDtcbiAgd3JpdGFibGU6IFdyaXRhYmxlU3RyZWFtO1xuICBsYXN0UGFydEluZGV4OiBudW1iZXI7XG4gIHN0ZXBJbmRleE9mZnNldDogbnVtYmVyO1xufSk6IFByb21pc2U8e1xuICBmaW5pc2hSZWFzb246IEZpbmlzaFJlYXNvbjtcbiAgbGFzdFBhcnRJbmRleDogbnVtYmVyO1xuICB1c2FnZVN0ZXBzOiBTdGVwVXNhZ2VbXTtcbiAgcGVuZGluZ0FwcHJvdmFsczogeyBhcHByb3ZhbElkOiBzdHJpbmc7IHRvb2xOYW1lOiBzdHJpbmcgfVtdO1xuICBtYXhTdGVwczogbnVtYmVyIHwgdW5kZWZpbmVkO1xufT4ge1xuICBcInVzZSBzdGVwXCI7XG5cbiAgY29uc3QgeyBnZXRTdG9yYWdlIH0gPSBhd2FpdCBpbXBvcnQoXCIuL3N0b3JhZ2UvY2xpZW50XCIpO1xuICBjb25zdCB7IGdldFNhbmRib3ggfSA9IGF3YWl0IGltcG9ydChcIi4vc2FuZGJveFwiKTtcblxuICBjb25zdCBycGMgPSByZXNvbHZlUnBjKGlucHV0LnN0b3JhZ2VDb25maWcubmFtZSA/PyBcImRlZmF1bHRcIik7XG4gIGNvbnN0IHN0b3JhZ2UgPSBnZXRTdG9yYWdlKHsgY29uZmlnOiBpbnB1dC5zdG9yYWdlQ29uZmlnLCBycGMgfSk7XG5cbiAgY29uc3QgYWJvcnRDb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICBjb25zdCBwb2xsQ29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcblxuICBjb25zdCB7IGZpcnN0Q2hlY2sgfSA9IHBvbGxGb3JJbnRlcnJ1cHQoe1xuICAgIHN0b3JhZ2UsXG4gICAgbWVzc2FnZUlkOiBhc3Npc3RhbnRNZXNzYWdlSWQsXG4gICAgc2lnbmFsOiBwb2xsQ29udHJvbGxlci5zaWduYWwsXG4gICAgYWJvcnRDb250cm9sbGVyLFxuICB9KTtcblxuICBjb25zdCBbXG4gICAgLFxuICAgIG1lc3NhZ2VzUmVzdWx0LFxuICAgIHBhcnRzUmVzdWx0LFxuICAgIHsgc2Vzc2lvbiwgc2FuZGJveCwgc2FuZGJveFJlY29yZCB9LFxuICAgIGFwaVRvb2xzTWV0YWRhdGEsXG4gIF0gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgZmlyc3RDaGVjayxcbiAgICBzdG9yYWdlLm1lc3NhZ2UubGlzdChpbnB1dC5zZXNzaW9uSWQpLFxuICAgIHN0b3JhZ2UucGFydC5saXN0QnlTZXNzaW9uKGlucHV0LnNlc3Npb25JZCksXG4gICAgc3RvcmFnZS5zZXNzaW9uLmdldChpbnB1dC5zZXNzaW9uSWQpLnRoZW4oYXN5bmMgKHNlc3Npb24pID0+IHtcbiAgICAgIGlmIChzZXNzaW9uIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgc2Vzc2lvbjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHNhbmRib3hSZWNvcmQgPSBzZXNzaW9uLnNhbmRib3hJZFxuICAgICAgICA/IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5nZXQoc2Vzc2lvbi5zYW5kYm94SWQpXG4gICAgICAgIDogbnVsbDtcbiAgICAgIGlmIChzYW5kYm94UmVjb3JkIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgc2FuZGJveFJlY29yZDtcbiAgICAgIH1cbiAgICAgIGlmICghc2FuZGJveFJlY29yZCkge1xuICAgICAgICB0aHJvdyBuZXcgRmF0YWxFcnJvcihcbiAgICAgICAgICBgU2FuZGJveCBub3QgZm91bmQgZm9yIHNlc3Npb24gJHtpbnB1dC5zZXNzaW9uSWR9YFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgY29uc3Qgc2FuZGJveCA9IGdldFNhbmRib3goe1xuICAgICAgICBzYW5kYm94UmVjb3JkLFxuICAgICAgICBzdG9yYWdlQ29uZmlnOiBpbnB1dC5zdG9yYWdlQ29uZmlnLFxuICAgICAgICBzdG9yYWdlLFxuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiB7IHNlc3Npb24sIHNhbmRib3gsIHNhbmRib3hSZWNvcmQgfTtcbiAgICB9KSxcbiAgICBmZXRjaEFwaVRvb2xzTWV0YWRhdGEoe1xuICAgICAgcnBjLFxuICAgIH0pLFxuICBdKTtcblxuICBpZiAoYWJvcnRDb250cm9sbGVyLnNpZ25hbC5hYm9ydGVkKSB7XG4gICAgcG9sbENvbnRyb2xsZXIuYWJvcnQoKTtcbiAgICByZXR1cm4ge1xuICAgICAgZmluaXNoUmVhc29uOiBcInN0b3BcIiBhcyBGaW5pc2hSZWFzb24sXG4gICAgICBsYXN0UGFydEluZGV4LFxuICAgICAgdXNhZ2VTdGVwczogW10sXG4gICAgICBwZW5kaW5nQXBwcm92YWxzOiBbXSxcbiAgICAgIG1heFN0ZXBzOiB1bmRlZmluZWQsXG4gICAgfTtcbiAgfVxuXG4gIGlmIChtZXNzYWdlc1Jlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgdGhyb3cgbWVzc2FnZXNSZXN1bHQ7XG4gIH1cbiAgaWYgKHBhcnRzUmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICB0aHJvdyBwYXJ0c1Jlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBPbiBmaXJzdCBpdGVyYXRpb24sIG1hcmsgYWxsIG1lc3NhZ2VzIGluIHRoaXMgYmF0Y2ggYXMgc3RhcnRlZC5cbiAgICogVXNlciBtZXNzYWdlcyBhcmUgYWxzbyBtYXJrZWQgYXMgY29tcGxldGVkICh0aGV5J3JlIGRvbmUpLlxuICAgKiBUaGUgYXNzaXN0YW50IG1lc3NhZ2UgaXMgb25seSBtYXJrZWQgYXMgc3RhcnRlZCAoc3RyZWFtaW5nIGluIHByb2dyZXNzKS5cbiAgICovXG4gIGNvbnN0IHNldFN0YXJ0ZWRQcm9taXNlID1cbiAgICBsYXN0UGFydEluZGV4ID09PSAwXG4gICAgICA/IChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICBjb25zdCBwZW5kaW5nTWVzc2FnZXMgPSBtZXNzYWdlc1Jlc3VsdC5pdGVtcy5maWx0ZXIoXG4gICAgICAgICAgICAobSkgPT4gbS5jcmVhdGVkQXQgPD0gZXZlbnQuY3JlYXRlZEF0ICYmIG0uc3RhcnRlZEF0ID09PSBudWxsXG4gICAgICAgICAgKTtcbiAgICAgICAgICBpZiAocGVuZGluZ01lc3NhZ2VzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHJldHVybiBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgICAgICAgcGVuZGluZ01lc3NhZ2VzLm1hcCgobSkgPT5cbiAgICAgICAgICAgICAgICBzdG9yYWdlLm1lc3NhZ2Uuc2V0KHtcbiAgICAgICAgICAgICAgICAgIC4uLm0sXG4gICAgICAgICAgICAgICAgICBzdGFydGVkQXQ6IG5vdyxcbiAgICAgICAgICAgICAgICAgIGNvbXBsZXRlZEF0OiBtLnJvbGUgPT09IFwiYXNzaXN0YW50XCIgPyBudWxsIDogbm93LFxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9KSgpXG4gICAgICA6IG51bGw7XG5cbiAgLy8gTXV0YWJsZSByZWYgc28gb25TdWJUb29sQ2FsbCBjYW4gd3JpdGUgdG8gdGhlIHN0cmVhbSBvbmNlIGF2YWlsYWJsZVxuICBjb25zdCBzdHJlYW1Xcml0ZXJSZWY6IHtcbiAgICBjdXJyZW50OiAoKGV2ZW50OiB1bmtub3duKSA9PiB2b2lkKSB8IG51bGw7XG4gIH0gPSB7IGN1cnJlbnQ6IG51bGwgfTtcblxuICBjb25zdCBzdWJUb29sUGFydElkczogc3RyaW5nW10gPSBbXTtcbiAgLy8gU2hhcmVkIGNvdW50ZXIgZm9yIHBhcnQgaW5kaWNlcyBcdTIwMTQgc3ViLXRvb2wgcGFydHMgaW5jcmVtZW50IHRoaXMgZHVyaW5nXG4gIC8vIHRoZSBzdHJlYW0sIHRoZW4gc3RlcFBhcnRzIGNvbnRpbnVlIGZyb20gd2hlcmUgaXQgbGVmdCBvZmYuXG4gIGxldCBuZXh0UGFydEluZGV4ID0gbGFzdFBhcnRJbmRleDtcblxuICBjb25zdCBvblN1YlRvb2xDYWxsOiBPblN1YlRvb2xDYWxsID0gYXN5bmMgKHRvb2xOYW1lLCB0b29sSW5wdXQsIGV4ZWN1dGUpID0+IHtcbiAgICAvLyBDaGVjayBpZiB0aGlzIHRvb2wgbmVlZHMgYXBwcm92YWwgdmlhIFJQQ1xuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHJwYyh7XG4gICAgICBtZXRob2Q6IFwidG9vbHMubmVlZHNBcHByb3ZhbFwiLFxuICAgICAgcGFyYW1zOiB7XG4gICAgICAgIHRvb2xOYW1lLFxuICAgICAgICBpbnB1dDogdG9vbElucHV0LFxuICAgICAgICB0b29sQ2FsbElkOiBganNfJHt0b29sTmFtZX1fJHtEYXRlLm5vdygpfWAsXG4gICAgICAgIG1lc3NhZ2VzOiBbXSxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICBpZiAoXCJlcnJvclwiIGluIHJlcyB8fCByZXMucmVzdWx0ICE9PSB0cnVlKSB7XG4gICAgICAvLyBObyBhcHByb3ZhbCBuZWVkZWQgXHUyMDE0IGp1c3QgZXhlY3V0ZVxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZXhlY3V0ZSgpO1xuICAgICAgICByZXR1cm4geyByZXN1bHQgfTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICByZXR1cm4geyBlcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpIH07XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQXBwcm92YWwgbmVlZGVkIFx1MjAxNCBzdXJmYWNlIHRvIHVzZXIgdmlhIHN0cmVhbSBldmVudHNcbiAgICBjb25zdCBhcHByb3ZhbElkID0gYGpzX2FwcHJvdmFsXyR7dWxpZCgpfWA7XG4gICAgY29uc3QgdG9vbENhbGxJZCA9IGBqc190Y18ke3VsaWQoKX1gO1xuICAgIGNvbnN0IHBhcnRJZCA9IGBwYXJ0XyR7dWxpZCgpfWA7XG4gICAgc3ViVG9vbFBhcnRJZHMucHVzaChwYXJ0SWQpO1xuXG4gICAgLy8gU3RvcmUgYXBwcm92YWwtcmVxdWVzdCBwYXJ0XG4gICAgYXdhaXQgc3RvcmFnZS5wYXJ0LnNldCh7XG4gICAgICBpZDogcGFydElkLFxuICAgICAgaW5kZXg6IG5leHRQYXJ0SW5kZXgrKyxcbiAgICAgIG1lc3NhZ2VJZDogYXNzaXN0YW50TWVzc2FnZUlkLFxuICAgICAgc2Vzc2lvbklkOiBpbnB1dC5zZXNzaW9uSWQsXG4gICAgICBwYXJ0OiB7XG4gICAgICAgIHR5cGU6IGB0b29sLSR7dG9vbE5hbWV9YCxcbiAgICAgICAgdG9vbENhbGxJZCxcbiAgICAgICAgc3RhdGU6IFwiYXBwcm92YWwtcmVxdWVzdGVkXCIsXG4gICAgICAgIGlucHV0OiB0b29sSW5wdXQsXG4gICAgICAgIGFwcHJvdmFsOiB7IGlkOiBhcHByb3ZhbElkIH0sXG4gICAgICB9IGFzIHVua25vd24gYXMgVUlNZXNzYWdlW1wicGFydHNcIl1bbnVtYmVyXSxcbiAgICB9KTtcblxuICAgIC8vIFdyaXRlIHN0cmVhbSBldmVudHMgZm9yIHRoZSBVSVxuICAgIC8vIHRvb2wtaW5wdXQtc3RhcnQgaXMgcmVxdWlyZWQgXHUyMDE0IHRoZSBBSSBTREsgY2xpZW50IGNyZWF0ZXMgdGhlIHRvb2wgcGFydFxuICAgIC8vIHdoZW4gaXQgc2VlcyB0aGlzIGV2ZW50LiBXaXRob3V0IGl0LCBzdWJzZXF1ZW50IGV2ZW50cyBhcmUgaWdub3JlZC5cbiAgICBzdHJlYW1Xcml0ZXJSZWYuY3VycmVudD8uKHtcbiAgICAgIHR5cGU6IFwidG9vbC1pbnB1dC1zdGFydFwiLFxuICAgICAgdG9vbENhbGxJZCxcbiAgICAgIHRvb2xOYW1lLFxuICAgIH0pO1xuICAgIHN0cmVhbVdyaXRlclJlZi5jdXJyZW50Py4oe1xuICAgICAgdHlwZTogXCJ0b29sLWlucHV0LWF2YWlsYWJsZVwiLFxuICAgICAgdG9vbENhbGxJZCxcbiAgICAgIHRvb2xOYW1lLFxuICAgICAgaW5wdXQ6IHRvb2xJbnB1dCxcbiAgICB9KTtcbiAgICBzdHJlYW1Xcml0ZXJSZWYuY3VycmVudD8uKHtcbiAgICAgIHR5cGU6IFwidG9vbC1hcHByb3ZhbC1yZXF1ZXN0XCIsXG4gICAgICBhcHByb3ZhbElkLFxuICAgICAgdG9vbENhbGxJZCxcbiAgICB9KTtcblxuICAgIC8vIFBvbGwgc3RvcmFnZSBmb3IgYXBwcm92YWwgcmVzcG9uc2VcbiAgICBjb25zdCBQT0xMX01TID0gNTAwO1xuICAgIGNvbnN0IFRJTUVPVVRfTVMgPSA1ICogNjAgKiAxMDAwO1xuICAgIGNvbnN0IHN0YXJ0ID0gRGF0ZS5ub3coKTtcblxuICAgIHdoaWxlIChEYXRlLm5vdygpIC0gc3RhcnQgPCBUSU1FT1VUX01TKSB7XG4gICAgICBjb25zdCBwYXJ0cyA9IGF3YWl0IHN0b3JhZ2UucGFydC5saXN0QnlTZXNzaW9uKGlucHV0LnNlc3Npb25JZCk7XG4gICAgICBpZiAoIShwYXJ0cyBpbnN0YW5jZW9mIEVycm9yKSkge1xuICAgICAgICBjb25zdCB1cGRhdGVkID0gcGFydHMuaXRlbXMuZmluZChcbiAgICAgICAgICAocCkgPT5cbiAgICAgICAgICAgIHAuaWQgPT09IHBhcnRJZCAmJlxuICAgICAgICAgICAgXCJzdGF0ZVwiIGluIHAucGFydCAmJlxuICAgICAgICAgICAgKHAucGFydCBhcyB7IHN0YXRlOiBzdHJpbmcgfSkuc3RhdGUgPT09IFwiYXBwcm92YWwtcmVzcG9uZGVkXCJcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKHVwZGF0ZWQpIHtcbiAgICAgICAgICBjb25zdCBhcHByb3ZhbCA9IChcbiAgICAgICAgICAgIHVwZGF0ZWQucGFydCBhcyB7XG4gICAgICAgICAgICAgIGFwcHJvdmFsPzogeyBhcHByb3ZlZD86IGJvb2xlYW47IHJlYXNvbj86IHN0cmluZyB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICkuYXBwcm92YWw7XG4gICAgICAgICAgaWYgKGFwcHJvdmFsPy5hcHByb3ZlZCkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZXhlY3V0ZSgpO1xuICAgICAgICAgICAgICBzdHJlYW1Xcml0ZXJSZWYuY3VycmVudD8uKHtcbiAgICAgICAgICAgICAgICB0eXBlOiBcInRvb2wtb3V0cHV0LWF2YWlsYWJsZVwiLFxuICAgICAgICAgICAgICAgIHRvb2xDYWxsSWQsXG4gICAgICAgICAgICAgICAgb3V0cHV0OiByZXN1bHQsXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICByZXR1cm4geyByZXN1bHQgfTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKTtcbiAgICAgICAgICAgICAgc3RyZWFtV3JpdGVyUmVmLmN1cnJlbnQ/Lih7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJ0b29sLW91dHB1dC1lcnJvclwiLFxuICAgICAgICAgICAgICAgIHRvb2xDYWxsSWQsXG4gICAgICAgICAgICAgICAgZXJyb3JUZXh0OiBlcnJvcixcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIHJldHVybiB7IGVycm9yIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIERlbmllZFxuICAgICAgICAgIHN0cmVhbVdyaXRlclJlZi5jdXJyZW50Py4oe1xuICAgICAgICAgICAgdHlwZTogXCJ0b29sLW91dHB1dC1kZW5pZWRcIixcbiAgICAgICAgICAgIHRvb2xDYWxsSWQsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGVycm9yOiBgVG9vbCBcIiR7dG9vbE5hbWV9XCIgZGVuaWVkOiAke2FwcHJvdmFsPy5yZWFzb24gfHwgXCJ1c2VyIGRlbmllZFwifWAsXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgYXdhaXQgbmV3IFByb21pc2UoKHIpID0+IHNldFRpbWVvdXQociwgUE9MTF9NUykpO1xuICAgIH1cblxuICAgIHJldHVybiB7IGVycm9yOiBcIkFwcHJvdmFsIHRpbWVkIG91dFwiIH07XG4gIH07XG5cbiAgY29uc3QgcmF3VG9vbHMgPSBnZXRUb29scyh7XG4gICAgaW5wdXQsXG4gICAgcnBjLFxuICAgIGV2ZW50LFxuICAgIHNhbmRib3gsXG4gICAgc2Vzc2lvbixcbiAgICBzYW5kYm94UmVjb3JkOiBzYW5kYm94UmVjb3JkIGFzIFNhbmRib3hSZWNvcmQsXG4gICAgYXBpVG9vbHNNZXRhZGF0YSxcbiAgICBvblN1YlRvb2xDYWxsLFxuICB9KTtcblxuICBpZiAoIXNlc3Npb24ubW9kZWwpIHtcbiAgICB0aHJvdyBuZXcgRmF0YWxFcnJvcihcIlNlc3Npb24gbW9kZWwgaXMgbm90IHNldFwiKTtcbiAgfVxuXG4gIGNvbnN0IGFsbFBhcnRzID0gcGFydHNSZXN1bHQuaXRlbXM7XG4gIGNvbnN0IHVzYWdlU3RlcHM6IFN0ZXBVc2FnZVtdID0gW107XG4gIGxldCBpbnRlcm5hbFN0ZXBJbmRleCA9IDA7XG5cbiAgY29uc3QgdG9vbHMgPSBPYmplY3QuZnJvbUVudHJpZXMoXG4gICAgT2JqZWN0LmVudHJpZXMocmF3VG9vbHMpLm1hcCgoW25hbWUsIHRdKSA9PiBbXG4gICAgICBuYW1lLFxuICAgICAge1xuICAgICAgICAuLi50LFxuICAgICAgICBuZWVkc0FwcHJvdmFsOiBhc3luYyAoXG4gICAgICAgICAgdG9vbElucHV0OiB1bmtub3duLFxuICAgICAgICAgIG9wdHM6IHsgdG9vbENhbGxJZDogc3RyaW5nOyBtZXNzYWdlczogdW5rbm93bltdIH1cbiAgICAgICAgKSA9PiB7XG4gICAgICAgICAgY29uc3QgcmVzID0gYXdhaXQgcnBjKHtcbiAgICAgICAgICAgIG1ldGhvZDogXCJ0b29scy5uZWVkc0FwcHJvdmFsXCIsXG4gICAgICAgICAgICBwYXJhbXM6IHtcbiAgICAgICAgICAgICAgdG9vbE5hbWU6IG5hbWUsXG4gICAgICAgICAgICAgIGlucHV0OiB0b29sSW5wdXQsXG4gICAgICAgICAgICAgIHRvb2xDYWxsSWQ6IG9wdHMudG9vbENhbGxJZCxcbiAgICAgICAgICAgICAgbWVzc2FnZXM6IG9wdHMubWVzc2FnZXMsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGlmIChcImVycm9yXCIgaW4gcmVzKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgIGB0b29scy5uZWVkc0FwcHJvdmFsIFJQQyBmYWlsZWQgZm9yICR7bmFtZX06ICR7cmVzLmVycm9yLm1lc3NhZ2V9YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHJlcy5yZXN1bHQgYXMgYm9vbGVhbjtcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgXSlcbiAgKTtcblxuICBsZXQgc2tpbGxzUmVmOiBTa2lsbFN1bW1hcnlbXSA9IFtdO1xuXG4gIGNvbnN0IHJlc3VsdCA9IHN0cmVhbVRleHQoe1xuICAgIC8vIFBsYWNlaG9sZGVyIHRvIHBhc3MgdmFsaWRhdGlvbiBcdTIwMTQgcHJlcGFyZVN0ZXAgcmVwbGFjZXMgbWVzc2FnZXMgZW50aXJlbHkuXG4gICAgbWVzc2FnZXM6IFt7IHJvbGU6IFwidXNlclwiIGFzIGNvbnN0LCBjb250ZW50OiBcIi5cIiB9XSxcbiAgICB0b29scyxcbiAgICBtb2RlbDogc2Vzc2lvbi5tb2RlbCxcbiAgICBhYm9ydFNpZ25hbDogYWJvcnRDb250cm9sbGVyLnNpZ25hbCxcbiAgICBhY3RpdmVUb29sczogc2Vzc2lvbi5hY3RpdmVUb29scyA/PyB1bmRlZmluZWQsXG4gICAgc3RvcFdoZW46IHN0ZXBDb3VudElzKDEpLFxuICAgIHRlbXBlcmF0dXJlOiBzZXNzaW9uLmdlbmVyYXRpb24/LnRlbXBlcmF0dXJlLFxuICAgIHRvcEs6IHNlc3Npb24uZ2VuZXJhdGlvbj8udG9wSyxcbiAgICB0b3BQOiBzZXNzaW9uLmdlbmVyYXRpb24/LnRvcFAsXG4gICAgZnJlcXVlbmN5UGVuYWx0eTogc2Vzc2lvbi5nZW5lcmF0aW9uPy5mcmVxdWVuY3lQZW5hbHR5LFxuICAgIHByZXNlbmNlUGVuYWx0eTogc2Vzc2lvbi5nZW5lcmF0aW9uPy5wcmVzZW5jZVBlbmFsdHksXG4gICAgbWF4T3V0cHV0VG9rZW5zOiBzZXNzaW9uLmdlbmVyYXRpb24/Lm1heE91dHB1dFRva2VucyxcbiAgICBoZWFkZXJzOiBzZXNzaW9uLmdlbmVyYXRpb24/LmhlYWRlcnMsXG4gICAgZXhwZXJpbWVudGFsX2NvbnRleHQ6IHtcbiAgICAgIHNlc3Npb24sXG4gICAgICBzYW5kYm94LFxuICAgICAgc3RvcmFnZSxcbiAgICAgIGNvbnRleHQ6IGV2ZW50LmNvbnRleHQsXG4gICAgfSxcbiAgICBwcmVwYXJlU3RlcDogYXN5bmMgKHsgbW9kZWwgfSkgPT4ge1xuICAgICAgLy8gT24gdGhlIGZpcnN0IHN0ZXAsIGVtaXQgc2FuZGJveCBzdGF0dXMsIGF3YWl0IHNldHVwLCBhbmQgbG9hZCBza2lsbHMuXG4gICAgICAvLyBzdHJlYW1Xcml0ZXJSZWYgaXMgc2V0IGJ5IHRoZSBjcmVhdGVVSU1lc3NhZ2VTdHJlYW0gZXhlY3V0b3JcbiAgICAgIC8vIHdoaWNoIHJ1bnMgYmVmb3JlIHByZXBhcmVTdGVwIChhZnRlciBgc3RhcnRgIGlzIHdyaXR0ZW4pLlxuICAgICAgaWYgKGxhc3RQYXJ0SW5kZXggPT09IDApIHtcbiAgICAgICAgaWYgKHNhbmRib3guX3NldHVwTWV0YSkge1xuICAgICAgICAgIGNvbnN0IG1ldGEgPSBhd2FpdCBzYW5kYm94Ll9zZXR1cE1ldGE7XG4gICAgICAgICAgZW1pdFN0YXR1cyh7XG4gICAgICAgICAgICB3cml0ZXI6IHN0cmVhbVdyaXRlclJlZi5jdXJyZW50LFxuICAgICAgICAgICAgc3RhdHVzOiBtZXRhLm5lZWRzU2V0dXBSdW5cbiAgICAgICAgICAgICAgPyB7IHR5cGU6IFwic2FuZGJveC1zZXR1cC1jb2xkXCIgfVxuICAgICAgICAgICAgICA6IHsgdHlwZTogXCJzYW5kYm94LXNldHVwXCIgfSxcbiAgICAgICAgICAgIHJwYyxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc2FuZGJveC5fb25SZWFkeSkge1xuICAgICAgICAgIGF3YWl0IHNhbmRib3guX29uUmVhZHk7XG4gICAgICAgIH1cblxuICAgICAgICBlbWl0U3RhdHVzKHtcbiAgICAgICAgICB3cml0ZXI6IHN0cmVhbVdyaXRlclJlZi5jdXJyZW50LFxuICAgICAgICAgIHN0YXR1czogeyB0eXBlOiBcImxvYWRpbmctc2tpbGxzXCIgfSxcbiAgICAgICAgICBycGMsXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBza2lsbHMgPSBhd2FpdCBkaXNjb3ZlclNraWxsc0luU2FuZGJveCh7XG4gICAgICAgICAgc2FuZGJveCxcbiAgICAgICAgICBza2lsbHNEaXJzOiBzZXNzaW9uLnNraWxsc0RpciB8fCBbXSxcbiAgICAgICAgICBkZWJ1ZzogdHJ1ZSxcbiAgICAgICAgfSk7XG4gICAgICAgIHNraWxsc1JlZiA9IHNraWxscztcbiAgICAgIH1cblxuICAgICAgLy8gRXhlY3V0ZSBhcHByb3ZlZCB0b29scyBzbyB0aGUgbW9kZWwgc2VlcyBjb21wbGV0ZSB0b29sIGNhbGwgKyByZXN1bHRcbiAgICAgIC8vIHBhaXJzLiBUaGlzIHJ1bnMgb3V0c2lkZSB0aGUgbGFzdFBhcnRJbmRleCA9PT0gMCBnYXRlIGJlY2F1c2VcbiAgICAgIC8vIGFwcHJvdmFscyBhcnJpdmUgb24gc3Vic2VxdWVudCBtZXNzYWdlcyAobGFzdFBhcnRJbmRleCA+IDApLlxuICAgICAgY29uc3QgYXBwcm92ZWRQYXJ0cyA9IGFsbFBhcnRzLmZpbHRlcihcbiAgICAgICAgKHApID0+XG4gICAgICAgICAgcC5wYXJ0ICYmXG4gICAgICAgICAgXCJzdGF0ZVwiIGluIHAucGFydCAmJlxuICAgICAgICAgIChwLnBhcnQgYXMgeyBzdGF0ZTogc3RyaW5nIH0pLnN0YXRlID09PSBcImFwcHJvdmFsLXJlc3BvbmRlZFwiICYmXG4gICAgICAgICAgXCJhcHByb3ZhbFwiIGluIHAucGFydCAmJlxuICAgICAgICAgIChwLnBhcnQgYXMgeyBhcHByb3ZhbD86IHsgYXBwcm92ZWQ/OiBib29sZWFuIH0gfSkuYXBwcm92YWxcbiAgICAgICAgICAgID8uYXBwcm92ZWQgPT09IHRydWVcbiAgICAgICk7XG5cbiAgICAgIGlmIChhcHByb3ZlZFBhcnRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgZW1pdFN0YXR1cyh7XG4gICAgICAgICAgd3JpdGVyOiBzdHJlYW1Xcml0ZXJSZWYuY3VycmVudCxcbiAgICAgICAgICBzdGF0dXM6IHsgdHlwZTogXCJwcm9jZXNzaW5nLWFwcHJvdmFsc1wiIH0sXG4gICAgICAgICAgcnBjLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBCdWlsZCBjb250ZXh0IG1lc3NhZ2VzIGZvciB0b29sIGV4ZWN1dGUgKGluY29tcGxldGUgY2FsbHMgZmlsdGVyZWQgb3V0KS5cbiAgICAgICAgY29uc3QgcHJlRXhlY01lc3NhZ2VzID0gYXdhaXQgY29udmVydFRvTW9kZWxNZXNzYWdlcyhcbiAgICAgICAgICBhc3NlbWJsZVVJTWVzc2FnZXMoe1xuICAgICAgICAgICAgbWVzc2FnZXM6IG1lc3NhZ2VzUmVzdWx0Lml0ZW1zLFxuICAgICAgICAgICAgcGFydHM6IGFsbFBhcnRzLFxuICAgICAgICAgICAgdW50aWw6IGV2ZW50LmNyZWF0ZWRBdCxcbiAgICAgICAgICAgIGluY2x1ZGVRdWV1ZWQ6IHRydWUsXG4gICAgICAgICAgICBleGNsdWRlU3ViVG9vbFBhcnRzOiB0cnVlLFxuICAgICAgICAgIH0pLFxuICAgICAgICAgIHsgaWdub3JlSW5jb21wbGV0ZVRvb2xDYWxsczogdHJ1ZSB9XG4gICAgICAgICk7XG5cbiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgICAgYXBwcm92ZWRQYXJ0cy5tYXAoYXN5bmMgKGFwKSA9PiB7XG4gICAgICAgICAgICBpZiAoIWFwLnBhcnQudHlwZS5zdGFydHNXaXRoKFwidG9vbC1cIikpIHtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcGFydCA9IGFwLnBhcnQgYXMgRXh0cmFjdDxcbiAgICAgICAgICAgICAgVUlNZXNzYWdlW1wicGFydHNcIl1bbnVtYmVyXSxcbiAgICAgICAgICAgICAgeyB0eXBlOiBgdG9vbC0ke3N0cmluZ31gIH1cbiAgICAgICAgICAgID47XG4gICAgICAgICAgICBjb25zdCB0b29sTmFtZSA9IHBhcnQudHlwZS5yZXBsYWNlKFwidG9vbC1cIiwgXCJcIik7XG4gICAgICAgICAgICBjb25zdCB0b29sRGVmID0gcmF3VG9vbHNbdG9vbE5hbWVdO1xuXG4gICAgICAgICAgICBpZiAodG9vbERlZj8uZXhlY3V0ZSAmJiBwYXJ0LmlucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBjb25zdCB0b29sT3V0cHV0ID0gYXdhaXQgdG9vbERlZi5leGVjdXRlKHBhcnQuaW5wdXQsIHtcbiAgICAgICAgICAgICAgICAgIHRvb2xDYWxsSWQ6IHBhcnQudG9vbENhbGxJZCxcbiAgICAgICAgICAgICAgICAgIG1lc3NhZ2VzOiBwcmVFeGVjTWVzc2FnZXMsXG4gICAgICAgICAgICAgICAgICBhYm9ydFNpZ25hbDogYWJvcnRDb250cm9sbGVyLnNpZ25hbCxcbiAgICAgICAgICAgICAgICAgIGV4cGVyaW1lbnRhbF9jb250ZXh0OiB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24sXG4gICAgICAgICAgICAgICAgICAgIHNhbmRib3gsXG4gICAgICAgICAgICAgICAgICAgIHN0b3JhZ2UsXG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHQ6IGV2ZW50LmNvbnRleHQsXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHBhcnQuc3RhdGUgPSBcIm91dHB1dC1hdmFpbGFibGVcIjtcbiAgICAgICAgICAgICAgICBwYXJ0Lm91dHB1dCA9IHRvb2xPdXRwdXQ7XG4gICAgICAgICAgICAgICAgc3RyZWFtV3JpdGVyUmVmLmN1cnJlbnQ/Lih7XG4gICAgICAgICAgICAgICAgICB0eXBlOiBcInRvb2wtb3V0cHV0LWF2YWlsYWJsZVwiLFxuICAgICAgICAgICAgICAgICAgdG9vbENhbGxJZDogcGFydC50b29sQ2FsbElkLFxuICAgICAgICAgICAgICAgICAgb3V0cHV0OiB0b29sT3V0cHV0LFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICBwYXJ0LnN0YXRlID0gXCJvdXRwdXQtZXJyb3JcIjtcbiAgICAgICAgICAgICAgICBwYXJ0LmVycm9yVGV4dCA9XG4gICAgICAgICAgICAgICAgICBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVycik7XG4gICAgICAgICAgICAgICAgc3RyZWFtV3JpdGVyUmVmLmN1cnJlbnQ/Lih7XG4gICAgICAgICAgICAgICAgICB0eXBlOiBcInRvb2wtb3V0cHV0LWVycm9yXCIsXG4gICAgICAgICAgICAgICAgICB0b29sQ2FsbElkOiBwYXJ0LnRvb2xDYWxsSWQsXG4gICAgICAgICAgICAgICAgICBlcnJvclRleHQ6IHBhcnQuZXJyb3JUZXh0LFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGF3YWl0IHN0b3JhZ2UucGFydC5zZXQoeyAuLi5hcCwgcGFydCB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBlbWl0U3RhdHVzKHtcbiAgICAgICAgd3JpdGVyOiBzdHJlYW1Xcml0ZXJSZWYuY3VycmVudCxcbiAgICAgICAgc3RhdHVzOiB7IHR5cGU6IFwidGhpbmtpbmdcIiB9LFxuICAgICAgICBycGMsXG4gICAgICB9KTtcblxuICAgICAgY29uc3Qgc2tpbGxzQ29udGV4dCA9IGJ1aWxkU2tpbGxzQ29udGV4dChza2lsbHNSZWYpO1xuICAgICAgY29uc3Qgc3lzdGVtSGVhZGVyID0gam9pblByb21wdFNlY3Rpb25zKFxuICAgICAgICBCQVNFX1NZU1RFTV9QUk9NUFQsXG4gICAgICAgIHNlc3Npb24uc3lzdGVtXG4gICAgICApO1xuICAgICAgY29uc3Qgc3lzdGVtQ29udGV4dCA9IGpvaW5Qcm9tcHRTZWN0aW9ucyhza2lsbHNDb250ZXh0KTtcbiAgICAgIGNvbnN0IHN5c3RlbU1lc3NhZ2VzID0gW1xuICAgICAgICAuLi4oc3lzdGVtSGVhZGVyLnRyaW0oKVxuICAgICAgICAgID8gW3sgcm9sZTogXCJzeXN0ZW1cIiBhcyBjb25zdCwgY29udGVudDogc3lzdGVtSGVhZGVyIH1dXG4gICAgICAgICAgOiBbXSksXG4gICAgICAgIC4uLihzeXN0ZW1Db250ZXh0LnRyaW0oKVxuICAgICAgICAgID8gW3sgcm9sZTogXCJzeXN0ZW1cIiBhcyBjb25zdCwgY29udGVudDogc3lzdGVtQ29udGV4dCB9XVxuICAgICAgICAgIDogW10pLFxuICAgICAgXTtcblxuICAgICAgY29uc3QgdWlNZXNzYWdlcyA9IGFzc2VtYmxlVUlNZXNzYWdlcyh7XG4gICAgICAgIG1lc3NhZ2VzOiBtZXNzYWdlc1Jlc3VsdC5pdGVtcyxcbiAgICAgICAgcGFydHM6IGFsbFBhcnRzLFxuICAgICAgICB1bnRpbDogZXZlbnQuY3JlYXRlZEF0LFxuICAgICAgICBpbmNsdWRlUXVldWVkOiB0cnVlLFxuICAgICAgICBleGNsdWRlU3ViVG9vbFBhcnRzOiB0cnVlLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IG1vZGVsTWVzc2FnZXMgPSBbXG4gICAgICAgIC4uLnN5c3RlbU1lc3NhZ2VzLFxuICAgICAgICAuLi4oYXdhaXQgY29udmVydFRvTW9kZWxNZXNzYWdlcyh1aU1lc3NhZ2VzLCB7XG4gICAgICAgICAgaWdub3JlSW5jb21wbGV0ZVRvb2xDYWxsczogdHJ1ZSxcbiAgICAgICAgfSkpLFxuICAgICAgXTtcblxuICAgICAgY29uc3QgcHJvbXB0Q2FjaGluZyA9IGFwcGx5UHJvbXB0Q2FjaGluZ1RvTW9kZWxSZXF1ZXN0KHtcbiAgICAgICAgbW9kZWw6IHR5cGVvZiBtb2RlbCA9PT0gXCJzdHJpbmdcIiA/IG1vZGVsIDogbW9kZWwubW9kZWxJZCxcbiAgICAgICAgc2Vzc2lvbklkOiBpbnB1dC5zZXNzaW9uSWQsXG4gICAgICAgIG1lc3NhZ2VzOiBtb2RlbE1lc3NhZ2VzLFxuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIG1lc3NhZ2VzOiBwcm9tcHRDYWNoaW5nLm1lc3NhZ2VzLFxuICAgICAgICBwcm92aWRlck9wdGlvbnM6IHByb21wdENhY2hpbmcucHJvdmlkZXJPcHRpb25zLFxuICAgICAgfTtcbiAgICB9LFxuICAgIG9uU3RlcEZpbmlzaDogKHsgdXNhZ2UgfSkgPT4ge1xuICAgICAgaWYgKHVzYWdlKSB7XG4gICAgICAgIHVzYWdlU3RlcHMucHVzaCh7XG4gICAgICAgICAgc3RlcEluZGV4OiBzdGVwSW5kZXhPZmZzZXQgKyBpbnRlcm5hbFN0ZXBJbmRleCxcbiAgICAgICAgICBtb2RlbDogc2Vzc2lvbi5tb2RlbCA/PyBcInVua25vd25cIixcbiAgICAgICAgICBpbnB1dFRva2VuczogdXNhZ2UuaW5wdXRUb2tlbnMgPz8gMCxcbiAgICAgICAgICBvdXRwdXRUb2tlbnM6IHVzYWdlLm91dHB1dFRva2VucyA/PyAwLFxuICAgICAgICAgIHRvdGFsVG9rZW5zOiB1c2FnZS50b3RhbFRva2VucyA/PyAwLFxuICAgICAgICAgIGNhY2hlUmVhZFRva2VuczogdXNhZ2UuaW5wdXRUb2tlbkRldGFpbHM/LmNhY2hlUmVhZFRva2VucyA/PyAwLFxuICAgICAgICAgIGNhY2hlV3JpdGVUb2tlbnM6IHVzYWdlLmlucHV0VG9rZW5EZXRhaWxzPy5jYWNoZVdyaXRlVG9rZW5zID8/IDAsXG4gICAgICAgICAgcmVhc29uaW5nVG9rZW5zOiB1c2FnZS5vdXRwdXRUb2tlbkRldGFpbHM/LnJlYXNvbmluZ1Rva2VucyA/PyAwLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIGludGVybmFsU3RlcEluZGV4Kys7XG4gICAgfSxcbiAgfSk7XG5cbiAgY29uc3Qgc3RlcFBhcnRzOiBVSU1lc3NhZ2VbXCJwYXJ0c1wiXSA9IFtdO1xuICBsZXQgd2FzQWJvcnRlZCA9IGZhbHNlO1xuXG4gIHRyeSB7XG4gICAgY29uc3Qgc3RyZWFtID0gY3JlYXRlVUlNZXNzYWdlU3RyZWFtKHtcbiAgICAgIGV4ZWN1dGU6ICh7IHdyaXRlciB9KSA9PiB7XG4gICAgICAgIHN0cmVhbVdyaXRlclJlZi5jdXJyZW50ID0gKGV2ZW50OiB1bmtub3duKSA9PlxuICAgICAgICAgIHdyaXRlci53cml0ZShldmVudCBhcyBQYXJhbWV0ZXJzPHR5cGVvZiB3cml0ZXIud3JpdGU+WzBdKTtcblxuICAgICAgICAvLyBNZXJnZSB0aGUgc3RyZWFtVGV4dCBzdHJlYW0uIHByZXBhcmVTdGVwIGhhbmRsZXMgc2FuZGJveCBzZXR1cCxcbiAgICAgICAgLy8gc2tpbGxzIGxvYWRpbmcsIGFwcHJvdmFsIGV4ZWN1dGlvbiwgYW5kIHN0YXR1cyBlbWlzc2lvbiBiZWZvcmVcbiAgICAgICAgLy8gdGhlIG1vZGVsIHN0YXJ0cyBnZW5lcmF0aW5nLlxuICAgICAgICB3cml0ZXIubWVyZ2UoXG4gICAgICAgICAgcmVzdWx0LnRvVUlNZXNzYWdlU3RyZWFtKHtcbiAgICAgICAgICAgIGdlbmVyYXRlTWVzc2FnZUlkOiAoKSA9PiBhc3Npc3RhbnRNZXNzYWdlSWQsXG4gICAgICAgICAgICBvbkZpbmlzaDogKHsgbWVzc2FnZXMgfSkgPT4ge1xuICAgICAgICAgICAgICBsZXQgaGFzQXBwcm92YWxzID0gZmFsc2U7XG4gICAgICAgICAgICAgIGZvciAoY29uc3QgbSBvZiBtZXNzYWdlcykge1xuICAgICAgICAgICAgICAgIGlmIChtLnJvbGUgPT09IFwiYXNzaXN0YW50XCIpIHtcbiAgICAgICAgICAgICAgICAgIHN0ZXBQYXJ0cy5wdXNoKC4uLm0ucGFydHMpO1xuICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBwIG9mIG0ucGFydHMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwic3RhdGVcIiBpbiBwICYmIHAuc3RhdGUgPT09IFwiYXBwcm92YWwtcmVxdWVzdGVkXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICBoYXNBcHByb3ZhbHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmIChoYXNBcHByb3ZhbHMpIHtcbiAgICAgICAgICAgICAgICBlbWl0U3RhdHVzKHtcbiAgICAgICAgICAgICAgICAgIHdyaXRlcjogc3RyZWFtV3JpdGVyUmVmLmN1cnJlbnQsXG4gICAgICAgICAgICAgICAgICBzdGF0dXM6IHsgdHlwZTogXCJuZWVkcy1hcHByb3ZhbFwiIH0sXG4gICAgICAgICAgICAgICAgICBycGMsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICBhd2FpdCBzdHJlYW0ucGlwZVRvKHdyaXRhYmxlLCB7IHByZXZlbnRDbG9zZTogdHJ1ZSB9KTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgaWYgKGFib3J0Q29udHJvbGxlci5zaWduYWwuYWJvcnRlZCkge1xuICAgICAgd2FzQWJvcnRlZCA9IHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoXCJbc3RyZWFtVGV4dFN0ZXBdIHN0cmVhbSBlcnJvcjpcIiwgZXJyKTtcbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gIH0gZmluYWxseSB7XG4gICAgcG9sbENvbnRyb2xsZXIuYWJvcnQoKTtcbiAgfVxuXG4gIGF3YWl0IFByb21pc2UuYWxsKFxuICAgIHN0ZXBQYXJ0cy5tYXAoYXN5bmMgKHVpUGFydCkgPT4ge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3RvcmFnZS5wYXJ0LnNldCh7XG4gICAgICAgIGlkOiBgcGFydF8ke3VsaWQoKX1gLFxuICAgICAgICBpbmRleDogbmV4dFBhcnRJbmRleCsrLFxuICAgICAgICBtZXNzYWdlSWQ6IGFzc2lzdGFudE1lc3NhZ2VJZCxcbiAgICAgICAgc2Vzc2lvbklkOiBpbnB1dC5zZXNzaW9uSWQsXG4gICAgICAgIHBhcnQ6IHVpUGFydCxcbiAgICAgIH0pO1xuICAgICAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHRocm93IHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSlcbiAgKTtcblxuICBpZiAoc2V0U3RhcnRlZFByb21pc2UpIHtcbiAgICBjb25zdCBzZXRTdGFydGVkUmVzdWx0ID0gYXdhaXQgc2V0U3RhcnRlZFByb21pc2U7XG4gICAgaWYgKHNldFN0YXJ0ZWRSZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgdGhyb3cgc2V0U3RhcnRlZFJlc3VsdDtcbiAgICB9XG4gICAgZm9yIChjb25zdCBtIG9mIHNldFN0YXJ0ZWRSZXN1bHQgPz8gW10pIHtcbiAgICAgIGlmIChtIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgbTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBjb25zdCBwZW5kaW5nQXBwcm92YWxzID0gc3RlcFBhcnRzXG4gICAgLmZpbHRlcihcbiAgICAgIChwKTogcCBpcyB0eXBlb2YgcCAmIHsgYXBwcm92YWw6IHsgaWQ6IHN0cmluZyB9IH0gPT5cbiAgICAgICAgXCJzdGF0ZVwiIGluIHAgJiZcbiAgICAgICAgcC5zdGF0ZSA9PT0gXCJhcHByb3ZhbC1yZXF1ZXN0ZWRcIiAmJlxuICAgICAgICBcImFwcHJvdmFsXCIgaW4gcCAmJlxuICAgICAgICAhIShwIGFzIHsgYXBwcm92YWw/OiB7IGlkOiBzdHJpbmcgfSB9KS5hcHByb3ZhbD8uaWRcbiAgICApXG4gICAgLm1hcCgocCkgPT4gKHtcbiAgICAgIGFwcHJvdmFsSWQ6IHAuYXBwcm92YWwuaWQsXG4gICAgICB0b29sTmFtZTogXCJ0eXBlXCIgaW4gcCA/IFN0cmluZyhwLnR5cGUpLnJlcGxhY2UoXCJ0b29sLVwiLCBcIlwiKSA6IFwidW5rbm93blwiLFxuICAgIH0pKTtcblxuICBjb25zdCBmaW5hbEZpbmlzaFJlYXNvbiA9IHdhc0Fib3J0ZWRcbiAgICA/IChcInN0b3BcIiBhcyBGaW5pc2hSZWFzb24pXG4gICAgOiBhd2FpdCByZXN1bHQuZmluaXNoUmVhc29uO1xuXG4gIHJldHVybiB7XG4gICAgZmluaXNoUmVhc29uOiBmaW5hbEZpbmlzaFJlYXNvbixcbiAgICBsYXN0UGFydEluZGV4OiBuZXh0UGFydEluZGV4LFxuICAgIHVzYWdlU3RlcHMsXG4gICAgcGVuZGluZ0FwcHJvdmFscyxcbiAgICBtYXhTdGVwczogc2Vzc2lvbi5nZW5lcmF0aW9uPy5tYXhTdGVwcyxcbiAgfTtcbn1cbiIsICJpbXBvcnQgdHlwZSB7IFNraWxsc0RpciB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbi8qKlxuICogUGFyc2VkIGZyb250bWF0dGVyIGZyb20gYSBTS0lMTC5tZCBmaWxlLlxuICovXG5leHBvcnQgdHlwZSBTa2lsbEZyb250bWF0dGVyID0ge1xuICBuYW1lOiBzdHJpbmc7XG4gIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG59O1xuXG4vKipcbiAqIFBhcnNlcyBZQU1MIGZyb250bWF0dGVyIGZyb20gYSBTS0lMTC5tZCBmaWxlIGNvbnRlbnQuXG4gKiBGcm9udG1hdHRlciBtdXN0IGJlIGF0IHRoZSBzdGFydCBvZiB0aGUgZmlsZSwgZGVsaW1pdGVkIGJ5IGAtLS1gIG1hcmtlcnMuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYG1hcmtkb3duXG4gKiAtLS1cbiAqIG5hbWU6IGNzdlxuICogZGVzY3JpcHRpb246IEFuYWx5emUgQ1NWIGRhdGFcbiAqIC0tLVxuICogIyBDU1YgU2tpbGxcbiAqIC4uLlxuICogYGBgXG4gKlxuICogQHJldHVybnMgUGFyc2VkIG5hbWUgYW5kIGRlc2NyaXB0aW9uLCBvciBudWxsIGlmIGZyb250bWF0dGVyIGlzIG1pc3NpbmcvaW52YWxpZFxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VTa2lsbEZyb250bWF0dGVyKFxuICBjb250ZW50OiBzdHJpbmdcbik6IFNraWxsRnJvbnRtYXR0ZXIgfCBudWxsIHtcbiAgY29uc3QgdHJpbW1lZCA9IGNvbnRlbnQudHJpbSgpO1xuXG4gIGlmICghdHJpbW1lZC5zdGFydHNXaXRoKFwiLS0tXCIpKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCBlbmRNYXJrZXJJbmRleCA9IHRyaW1tZWQuaW5kZXhPZihcIi0tLVwiLCAzKTtcbiAgaWYgKGVuZE1hcmtlckluZGV4ID09PSAtMSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgZnJvbnRtYXR0ZXJCbG9jayA9IHRyaW1tZWQuc2xpY2UoMywgZW5kTWFya2VySW5kZXgpLnRyaW0oKTtcbiAgY29uc3QgcGFyc2VkID0gcGFyc2VTaW1wbGVZYW1sKGZyb250bWF0dGVyQmxvY2spO1xuXG4gIGlmICghKHBhcnNlZC5uYW1lICYmIHBhcnNlZC5kZXNjcmlwdGlvbikpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgbmFtZTogU3RyaW5nKHBhcnNlZC5uYW1lKSxcbiAgICBkZXNjcmlwdGlvbjogU3RyaW5nKHBhcnNlZC5kZXNjcmlwdGlvbiksXG4gIH07XG59XG5cbi8qKlxuICogUGFyc2VzIHNpbXBsZSBZQU1MIGtleS12YWx1ZSBwYWlycyAoc2luZ2xlLWxpbmUgdmFsdWVzIG9ubHkpLlxuICogVGhpcyBhdm9pZHMgYWRkaW5nIGEgZnVsbCBZQU1MIHBhcnNlciBkZXBlbmRlbmN5IGZvciBiYXNpYyBmcm9udG1hdHRlci5cbiAqL1xuZnVuY3Rpb24gcGFyc2VTaW1wbGVZYW1sKHlhbWw6IHN0cmluZyk6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4ge1xuICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcblxuICBmb3IgKGNvbnN0IGxpbmUgb2YgeWFtbC5zcGxpdChcIlxcblwiKSkge1xuICAgIGNvbnN0IHRyaW1tZWRMaW5lID0gbGluZS50cmltKCk7XG4gICAgaWYgKCF0cmltbWVkTGluZSB8fCB0cmltbWVkTGluZS5zdGFydHNXaXRoKFwiI1wiKSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgY29uc3QgY29sb25JbmRleCA9IHRyaW1tZWRMaW5lLmluZGV4T2YoXCI6XCIpO1xuICAgIGlmIChjb2xvbkluZGV4ID09PSAtMSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgY29uc3Qga2V5ID0gdHJpbW1lZExpbmUuc2xpY2UoMCwgY29sb25JbmRleCkudHJpbSgpO1xuICAgIGxldCB2YWx1ZSA9IHRyaW1tZWRMaW5lLnNsaWNlKGNvbG9uSW5kZXggKyAxKS50cmltKCk7XG5cbiAgICAvLyBSZW1vdmUgc3Vycm91bmRpbmcgcXVvdGVzIGlmIHByZXNlbnRcbiAgICBpZiAoXG4gICAgICAodmFsdWUuc3RhcnRzV2l0aCgnXCInKSAmJiB2YWx1ZS5lbmRzV2l0aCgnXCInKSkgfHxcbiAgICAgICh2YWx1ZS5zdGFydHNXaXRoKFwiJ1wiKSAmJiB2YWx1ZS5lbmRzV2l0aChcIidcIikpXG4gICAgKSB7XG4gICAgICB2YWx1ZSA9IHZhbHVlLnNsaWNlKDEsIC0xKTtcbiAgICB9XG5cbiAgICBpZiAoa2V5KSB7XG4gICAgICByZXN1bHRba2V5XSA9IHZhbHVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogTm9ybWFsaXplcyBza2lsbHNEaXIgdG8gYW4gYXJyYXkgb2Ygc3RyaW5ncy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG5vcm1hbGl6ZVNraWxsc0RpcnMoc2tpbGxzRGlyPzogU2tpbGxzRGlyKTogc3RyaW5nW10ge1xuICBpZiAoIXNraWxsc0Rpcikge1xuICAgIHJldHVybiBbXTtcbiAgfVxuICByZXR1cm4gQXJyYXkuaXNBcnJheShza2lsbHNEaXIpID8gc2tpbGxzRGlyIDogW3NraWxsc0Rpcl07XG59XG4iLCAiaW1wb3J0IHR5cGUgeyBTYW5kYm94IH0gZnJvbSBcIi4uL3NhbmRib3hcIjtcbmltcG9ydCB7IHBhcnNlU2tpbGxGcm9udG1hdHRlciB9IGZyb20gXCIuL3BhcnNlclwiO1xuaW1wb3J0IHR5cGUgeyBTa2lsbFN1bW1hcnkgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG4vKipcbiAqIERpc2NvdmVycyBza2lsbHMgZnJvbSBkaXJlY3RvcmllcyBpbnNpZGUgdGhlIHNhbmRib3ggYnkgZmluZGluZyBhbmQgcGFyc2luZyBTS0lMTC5tZCBmaWxlcy5cbiAqIFNjYW5zIGVhY2ggZGlyZWN0b3J5IGZvciBzdWJkaXJlY3RvcmllcyBjb250YWluaW5nIFNLSUxMLm1kLCBleHRyYWN0cyBmcm9udG1hdHRlciBtZXRhZGF0YSxcbiAqIGFuZCByZXR1cm5zIHN1bW1hcmllcyBmb3IgdXNlIGluIHRoZSBzeXN0ZW0gcHJvbXB0LlxuICpcbiAqIEByZXR1cm5zIEFycmF5IG9mIHNraWxsIHN1bW1hcmllcyAoZGVkdXBsaWNhdGVkIGJ5IG5hbWUsIGZpcnN0IG9jY3VycmVuY2Ugd2lucylcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRpc2NvdmVyU2tpbGxzSW5TYW5kYm94KG9wdHM6IHtcbiAgc2FuZGJveDogU2FuZGJveDtcbiAgc2tpbGxzRGlyczogc3RyaW5nW107XG4gIGRlYnVnPzogYm9vbGVhbjtcbn0pOiBQcm9taXNlPFNraWxsU3VtbWFyeVtdPiB7XG4gIGNvbnN0IHsgc2FuZGJveCwgc2tpbGxzRGlycywgZGVidWcgfSA9IG9wdHM7XG5cbiAgY29uc3Qgc3VtbWFyaWVzOiBTa2lsbFN1bW1hcnlbXSA9IFtdO1xuICBjb25zdCBzZWVuTmFtZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcblxuICBmb3IgKGNvbnN0IHNraWxsc0RpciBvZiBza2lsbHNEaXJzKSB7XG4gICAgY29uc3QgZGlyU3VtbWFyaWVzID0gYXdhaXQgZGlzY292ZXJTa2lsbHNJbkRpcmVjdG9yeSh7XG4gICAgICBzYW5kYm94LFxuICAgICAgc2tpbGxzRGlyLFxuICAgICAgZGVidWcsXG4gICAgfSk7XG5cbiAgICBmb3IgKGNvbnN0IHN1bW1hcnkgb2YgZGlyU3VtbWFyaWVzKSB7XG4gICAgICBpZiAoIXNlZW5OYW1lcy5oYXMoc3VtbWFyeS5uYW1lKSkge1xuICAgICAgICBzZWVuTmFtZXMuYWRkKHN1bW1hcnkubmFtZSk7XG4gICAgICAgIHN1bW1hcmllcy5wdXNoKHN1bW1hcnkpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBzdW1tYXJpZXM7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGRpc2NvdmVyU2tpbGxzSW5EaXJlY3Rvcnkob3B0czoge1xuICBzYW5kYm94OiBTYW5kYm94O1xuICBza2lsbHNEaXI6IHN0cmluZztcbiAgZGVidWc/OiBib29sZWFuO1xufSk6IFByb21pc2U8U2tpbGxTdW1tYXJ5W10+IHtcbiAgY29uc3QgeyBzYW5kYm94LCBza2lsbHNEaXIsIGRlYnVnIH0gPSBvcHRzO1xuICBjb25zdCBza2lsbFBhdGhzID0gYXdhaXQgZmluZFNraWxsRmlsZXMoeyBzYW5kYm94LCBza2lsbHNEaXIsIGRlYnVnIH0pO1xuXG4gIGlmIChza2lsbFBhdGhzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIGNvbnN0IHN1bW1hcmllczogU2tpbGxTdW1tYXJ5W10gPSBbXTtcblxuICBmb3IgKGNvbnN0IHNraWxsTWRQYXRoIG9mIHNraWxsUGF0aHMpIHtcbiAgICBjb25zdCBzdW1tYXJ5ID0gYXdhaXQgcGFyc2VTa2lsbEZpbGUoeyBzYW5kYm94LCBza2lsbE1kUGF0aCwgZGVidWcgfSk7XG4gICAgaWYgKHN1bW1hcnkpIHtcbiAgICAgIHN1bW1hcmllcy5wdXNoKHN1bW1hcnkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBzdW1tYXJpZXM7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGZpbmRTa2lsbEZpbGVzKG9wdHM6IHtcbiAgc2FuZGJveDogU2FuZGJveDtcbiAgc2tpbGxzRGlyOiBzdHJpbmc7XG4gIGRlYnVnPzogYm9vbGVhbjtcbn0pOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gIGNvbnN0IHsgc2FuZGJveCwgc2tpbGxzRGlyLCBkZWJ1ZyB9ID0gb3B0cztcblxuICBjb25zdCBleGVjUmVzdWx0ID0gYXdhaXQgc2FuZGJveC5leGVjKHtcbiAgICBjb21tYW5kOiBcImZpbmRcIixcbiAgICBhcmdzOiBbc2tpbGxzRGlyLCBcIi1uYW1lXCIsIFwiU0tJTEwubWRcIiwgXCItdHlwZVwiLCBcImZcIl0sXG4gIH0pO1xuXG4gIGlmIChleGVjUmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICBpZiAoZGVidWcpIHtcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgYFtkaXNjb3Zlcl0gRmFpbGVkIHRvIHNjYW4gc2tpbGxzIGRpcmVjdG9yeSBcIiR7c2tpbGxzRGlyfVwiOiAke2V4ZWNSZXN1bHQubWVzc2FnZX1gXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gW107XG4gIH1cblxuICBjb25zdCB7IHN0ZG91dCwgc3RkZXJyLCBleGl0Q29kZSB9ID0gYXdhaXQgZXhlY1Jlc3VsdC5yZXN1bHQ7XG4gIGlmIChkZWJ1Zykge1xuICAgIGNvbnNvbGUubG9nKFxuICAgICAgYFtkaXNjb3Zlcl0gZmluZCByZXN1bHQ6IGV4aXRDb2RlPSR7ZXhpdENvZGV9LCBzdGRvdXQ9XCIke3N0ZG91dC50cmltKCl9XCIsIHN0ZGVycj1cIiR7c3RkZXJyLnRyaW0oKX1cImBcbiAgICApO1xuICB9XG5cbiAgaWYgKGV4aXRDb2RlICE9PSAwKSB7XG4gICAgaWYgKGRlYnVnKSB7XG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgIGBbZGlzY292ZXJdIFNraWxscyBkaXJlY3Rvcnkgbm90IGZvdW5kIG9yIGluYWNjZXNzaWJsZTogJHtza2lsbHNEaXJ9YFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgY29uc3QgcGF0aHMgPSBzdGRvdXRcbiAgICAudHJpbSgpXG4gICAgLnNwbGl0KFwiXFxuXCIpXG4gICAgLmZpbHRlcigocCkgPT4gcC5sZW5ndGggPiAwKTtcbiAgaWYgKGRlYnVnKSB7XG4gICAgY29uc29sZS5sb2coXCJbZGlzY292ZXJdIEZvdW5kIHNraWxsIHBhdGhzOlwiLCBwYXRocyk7XG4gIH1cbiAgcmV0dXJuIHBhdGhzO1xufVxuXG5hc3luYyBmdW5jdGlvbiBwYXJzZVNraWxsRmlsZShvcHRzOiB7XG4gIHNhbmRib3g6IFNhbmRib3g7XG4gIHNraWxsTWRQYXRoOiBzdHJpbmc7XG4gIGRlYnVnPzogYm9vbGVhbjtcbn0pOiBQcm9taXNlPFNraWxsU3VtbWFyeSB8IG51bGw+IHtcbiAgY29uc3QgeyBzYW5kYm94LCBza2lsbE1kUGF0aCwgZGVidWcgfSA9IG9wdHM7XG4gIGNvbnN0IGV4ZWNSZXN1bHQgPSBhd2FpdCBzYW5kYm94LmV4ZWMoe1xuICAgIGNvbW1hbmQ6IFwiY2F0XCIsXG4gICAgYXJnczogW3NraWxsTWRQYXRoXSxcbiAgfSk7XG5cbiAgaWYgKGV4ZWNSZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgIGlmIChkZWJ1Zykge1xuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBgW2Rpc2NvdmVyXSBGYWlsZWQgdG8gcmVhZCBza2lsbCBmaWxlIFwiJHtza2lsbE1kUGF0aH1cIjogJHtleGVjUmVzdWx0Lm1lc3NhZ2V9YFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCB7IHN0ZG91dCwgZXhpdENvZGUgfSA9IGF3YWl0IGV4ZWNSZXN1bHQucmVzdWx0O1xuXG4gIGlmIChleGl0Q29kZSAhPT0gMCkge1xuICAgIGlmIChkZWJ1Zykge1xuICAgICAgY29uc29sZS53YXJuKGBbZGlzY292ZXJdIENvdWxkIG5vdCByZWFkIHNraWxsIGZpbGU6ICR7c2tpbGxNZFBhdGh9YCk7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgcGFyc2VkID0gcGFyc2VTa2lsbEZyb250bWF0dGVyKHN0ZG91dCk7XG5cbiAgaWYgKCFwYXJzZWQpIHtcbiAgICBpZiAoZGVidWcpIHtcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgYFtkaXNjb3Zlcl0gSW52YWxpZCBvciBtaXNzaW5nIGZyb250bWF0dGVyIGluOiAke3NraWxsTWRQYXRofWBcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiBwYXJzZWQubmFtZSxcbiAgICBkZXNjcmlwdGlvbjogcGFyc2VkLmRlc2NyaXB0aW9uLFxuICAgIHNraWxsTWRQYXRoLFxuICB9O1xufVxuIiwgImltcG9ydCB7IGpzb25TY2hlbWEsIHR5cGUgVG9vbFNldCwgdG9vbCB9IGZyb20gXCJhaVwiO1xuaW1wb3J0IHsgeiB9IGZyb20gXCJ6b2RcIjtcbmltcG9ydCB0eXBlIHsgQWdlbnRJbnB1dCwgQWdlbnRNZXNzYWdlSW5wdXQgfSBmcm9tIFwiLi4vYWdlbnQtd29ya2Zsb3dcIjtcbmltcG9ydCB0eXBlIHsgUnBjUGF5bG9hZCwgUnBjUmVzdWx0IH0gZnJvbSBcIi4uL2NsaWVudFwiO1xuaW1wb3J0IHR5cGUgeyBTYW5kYm94IH0gZnJvbSBcIi4uL3NhbmRib3hcIjtcbmltcG9ydCB7IERFRkFVTFRfV0FJVF9VTlRJTCB9IGZyb20gXCIuLi9zYW5kYm94L3Byb2Nlc3MtbWFuYWdlclwiO1xuaW1wb3J0IHR5cGUgeyBTYW5kYm94UmVjb3JkLCBTZXNzaW9uLCBTdG9yYWdlIH0gZnJvbSBcIi4uL3N0b3JhZ2VcIjtcbmltcG9ydCB7IGNyZWF0ZUphdmFTY3JpcHRUb29sLCB0eXBlIE9uU3ViVG9vbENhbGwgfSBmcm9tIFwiLi9qYXZhc2NyaXB0XCI7XG5cbmNvbnN0IEFHRU5UX1BST1RPQ09MX1ZFUlNJT04gPSBcInYxXCI7XG5cbmZ1bmN0aW9uIGZvcm1hdEZpbGVTaXplKGJ5dGVzOiBudW1iZXIpOiBzdHJpbmcge1xuICBpZiAoYnl0ZXMgPCAxMDI0KSB7XG4gICAgcmV0dXJuIGAke2J5dGVzfWA7XG4gIH1cbiAgaWYgKGJ5dGVzIDwgMTAyNCAqIDEwMjQpIHtcbiAgICByZXR1cm4gYCR7KGJ5dGVzIC8gMTAyNCkudG9GaXhlZCgxKX1LYDtcbiAgfVxuICBpZiAoYnl0ZXMgPCAxMDI0ICogMTAyNCAqIDEwMjQpIHtcbiAgICByZXR1cm4gYCR7KGJ5dGVzIC8gKDEwMjQgKiAxMDI0KSkudG9GaXhlZCgxKX1NYDtcbiAgfVxuICByZXR1cm4gYCR7KGJ5dGVzIC8gKDEwMjQgKiAxMDI0ICogMTAyNCkpLnRvRml4ZWQoMSl9R2A7XG59XG5cbnR5cGUgSW50ZXJuYWxUb29sQ29udGV4dCA9IHtcbiAgaW5wdXQ6IEFnZW50SW5wdXQ7XG4gIHJwYzogKHBhcmFtczogUnBjUGF5bG9hZCkgPT4gUHJvbWlzZTxScGNSZXN1bHQ+O1xuICBldmVudDogQWdlbnRNZXNzYWdlSW5wdXQ7XG4gIHNhbmRib3g6IFNhbmRib3g7XG4gIHNlc3Npb246IFNlc3Npb247XG4gIHNhbmRib3hSZWNvcmQ6IFNhbmRib3hSZWNvcmQ7XG4gIGFwaVRvb2xzTWV0YWRhdGE6IHtcbiAgICBuYW1lOiBzdHJpbmc7XG4gICAgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG4gICAgaW5wdXRTY2hlbWE/OiB1bmtub3duO1xuICB9W107XG4gIG9uU3ViVG9vbENhbGw/OiBPblN1YlRvb2xDYWxsO1xufTtcblxuZXhwb3J0IHR5cGUgVG9vbENvbnRleHQ8VENvbnRleHQgPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4gPSB7XG4gIHNlc3Npb246IFNlc3Npb247XG4gIHNhbmRib3g6IFNhbmRib3g7XG4gIHN0b3JhZ2U6IFN0b3JhZ2U7XG4gIGNvbnRleHQ6IFRDb250ZXh0O1xufTtcblxuZXhwb3J0IGNvbnN0IGJ1aWx0SW5Ub29scyA9IHtcbiAgUmVhZDogdG9vbCh7XG4gICAgZGVzY3JpcHRpb246XG4gICAgICBcIlJlYWRzIGEgZmlsZSBhbmQgcmV0dXJucyBpdHMgY29udGVudHMgd2l0aCBtZXRhZGF0YS4gRm9yIGZpbGVzIG92ZXIgMjAwIGxpbmVzLCBhdXRvbWF0aWNhbGx5IHNob3dzIGZpcnN0IDEwMCBsaW5lcyB1bmxlc3MgYSBzcGVjaWZpYyBsaW5lIHJhbmdlIGlzIHByb3ZpZGVkLiBVc2Ugc3RhcnRMaW5lIGFuZCBlbmRMaW5lIHBhcmFtZXRlcnMgdG8gcmVhZCBzcGVjaWZpYyBwb3J0aW9ucyBvZiBsYXJnZSBmaWxlcy5cIixcbiAgICBpbnB1dFNjaGVtYTogei5vYmplY3Qoe1xuICAgICAgcGF0aDogei5zdHJpbmcoKS5kZXNjcmliZShcIlBhdGggdG8gdGhlIGZpbGUgcmVsYXRpdmUgdG8gd29ya3NwYWNlIHJvb3RcIiksXG4gICAgICBzdGFydExpbmU6IHpcbiAgICAgICAgLm51bWJlcigpXG4gICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgIC5kZXNjcmliZShcbiAgICAgICAgICBcIlN0YXJ0aW5nIGxpbmUgbnVtYmVyICgxLWluZGV4ZWQpLiBJZiBwcm92aWRlZCB3aXRoIGVuZExpbmUsIHJlYWRzIGV4YWN0IHJhbmdlIHJlZ2FyZGxlc3Mgb2YgZmlsZSBzaXplLlwiXG4gICAgICAgICksXG4gICAgICBlbmRMaW5lOiB6XG4gICAgICAgIC5udW1iZXIoKVxuICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgXCJFbmRpbmcgbGluZSBudW1iZXIgKDEtaW5kZXhlZCwgaW5jbHVzaXZlKS4gSWYgcHJvdmlkZWQgd2l0aCBzdGFydExpbmUsIHJlYWRzIGV4YWN0IHJhbmdlIHJlZ2FyZGxlc3Mgb2YgZmlsZSBzaXplLlwiXG4gICAgICAgICksXG4gICAgfSksXG4gICAgb3V0cHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4gICAgICBjb250ZW50OiB6LnN0cmluZygpLmRlc2NyaWJlKFwiRmlsZSBjb250ZW50XCIpLFxuICAgICAgbWV0YWRhdGE6IHoub2JqZWN0KHtcbiAgICAgICAgdG90YWxMaW5lczogei5udW1iZXIoKS5kZXNjcmliZShcIlRvdGFsIG51bWJlciBvZiBsaW5lcyBpbiB0aGUgZmlsZVwiKSxcbiAgICAgICAgbGluZXNTaG93bjogelxuICAgICAgICAgIC5udW1iZXIoKVxuICAgICAgICAgIC5kZXNjcmliZShcIk51bWJlciBvZiBsaW5lcyBpbmNsdWRlZCBpbiB0aGlzIHJlc3BvbnNlXCIpLFxuICAgICAgICBzdGFydExpbmU6IHoubnVtYmVyKCkuZGVzY3JpYmUoXCJGaXJzdCBsaW5lIG51bWJlciBzaG93biAoMS1pbmRleGVkKVwiKSxcbiAgICAgICAgZW5kTGluZTogei5udW1iZXIoKS5kZXNjcmliZShcIkxhc3QgbGluZSBudW1iZXIgc2hvd24gKDEtaW5kZXhlZClcIiksXG4gICAgICAgIGlzUGFnaW5hdGVkOiB6XG4gICAgICAgICAgLmJvb2xlYW4oKVxuICAgICAgICAgIC5kZXNjcmliZShcIldoZXRoZXIgdGhpcyBpcyBhIHBhcnRpYWwgdmlldyBvZiB0aGUgZmlsZVwiKSxcbiAgICAgICAgZmlsZVNpemU6IHpcbiAgICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgICAuZGVzY3JpYmUoXCJIdW1hbi1yZWFkYWJsZSBmaWxlIHNpemUgKGUuZy4sICcyLjVLJywgJzEuMk0nKVwiKSxcbiAgICAgICAgcGF0aDogelxuICAgICAgICAgIC5zdHJpbmcoKVxuICAgICAgICAgIC5kZXNjcmliZShcIlBhdGggdG8gdGhlIGZpbGUgcmVsYXRpdmUgdG8gd29ya3NwYWNlIHJvb3RcIiksXG4gICAgICB9KSxcbiAgICB9KSxcbiAgfSksXG4gIEdyZXA6IHRvb2woe1xuICAgIGRlc2NyaXB0aW9uOlxuICAgICAgXCJTZWFyY2ggZm9yIHBhdHRlcm5zIGluIGZpbGVzIHVzaW5nIHJpcGdyZXAuIFVzZSB0aGlzIHRvIGZpbmQgY29kZSBwYXR0ZXJucywgZnVuY3Rpb24gZGVmaW5pdGlvbnMsIGltcG9ydHMsIGV0Yy5cIixcbiAgICBpbnB1dFNjaGVtYTogei5vYmplY3Qoe1xuICAgICAgcGF0dGVybjogelxuICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgLmRlc2NyaWJlKFwiUmVnZXggcGF0dGVybiB0byBzZWFyY2ggZm9yIChyaXBncmVwIHN5bnRheClcIiksXG4gICAgICBwYXRoOiB6XG4gICAgICAgIC5zdHJpbmcoKVxuICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgXCJQYXRoIHRvIHNlYXJjaCBpbiAoZGVmYXVsdHMgdG8gd29ya3NwYWNlIHJvb3QpLiBDYW4gYmUgYSBmaWxlIG9yIGRpcmVjdG9yeS5cIlxuICAgICAgICApLFxuICAgICAgZmlsZVR5cGU6IHpcbiAgICAgICAgLnN0cmluZygpXG4gICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgIC5kZXNjcmliZShcbiAgICAgICAgICBcIkZpbGUgdHlwZSB0byBmaWx0ZXIgYnkgKGUuZy4sICd0cycsICdqcycsICdweScsICdtZCcpLiBVc2VzIHJpcGdyZXAncyBidWlsdC1pbiB0eXBlIGZpbHRlcnMuXCJcbiAgICAgICAgKSxcbiAgICAgIGdsb2I6IHpcbiAgICAgICAgLnN0cmluZygpXG4gICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgIC5kZXNjcmliZShcbiAgICAgICAgICBcIkdsb2IgcGF0dGVybiB0byBmaWx0ZXIgZmlsZXMgKGUuZy4sICcqLnRzeCcsICdzcmMvKiovKi50cycpXCJcbiAgICAgICAgKSxcbiAgICAgIGNhc2VTZW5zaXRpdmU6IHpcbiAgICAgICAgLmJvb2xlYW4oKVxuICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAuZGVmYXVsdCh0cnVlKVxuICAgICAgICAuZGVzY3JpYmUoXCJXaGV0aGVyIHNlYXJjaCBpcyBjYXNlLXNlbnNpdGl2ZSAoZGVmYXVsdDogdHJ1ZSlcIiksXG4gICAgICBjb250ZXh0TGluZXM6IHpcbiAgICAgICAgLm51bWJlcigpXG4gICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgIC5kZXNjcmliZShcbiAgICAgICAgICBcIk51bWJlciBvZiBjb250ZXh0IGxpbmVzIHRvIHNob3cgYmVmb3JlIGFuZCBhZnRlciBlYWNoIG1hdGNoXCJcbiAgICAgICAgKSxcbiAgICAgIG1heENvdW50OiB6XG4gICAgICAgIC5udW1iZXIoKVxuICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgXCJNYXhpbXVtIG51bWJlciBvZiBtYXRjaGVzIHBlciBmaWxlICh1c2VmdWwgZm9yIGxpbWl0aW5nIG91dHB1dClcIlxuICAgICAgICApLFxuICAgICAgZmlsZXNXaXRoTWF0Y2hlczogelxuICAgICAgICAuYm9vbGVhbigpXG4gICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgIC5kZWZhdWx0KGZhbHNlKVxuICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgXCJPbmx5IHNob3cgZmlsZSBwYXRocyB0aGF0IGNvbnRhaW4gbWF0Y2hlcywgbm90IHRoZSBtYXRjaGluZyBsaW5lcyB0aGVtc2VsdmVzXCJcbiAgICAgICAgKSxcbiAgICB9KSxcbiAgICBvdXRwdXRTY2hlbWE6IHoub2JqZWN0KHtcbiAgICAgIG1hdGNoZXM6IHpcbiAgICAgICAgLnN0cmluZygpXG4gICAgICAgIC5kZXNjcmliZShcbiAgICAgICAgICBcIlNlYXJjaCByZXN1bHRzIHdpdGggZmlsZSBwYXRocywgbGluZSBudW1iZXJzLCBhbmQgbWF0Y2hpbmcgY29udGVudFwiXG4gICAgICAgICksXG4gICAgICBzdW1tYXJ5OiB6Lm9iamVjdCh7XG4gICAgICAgIG1hdGNoQ291bnQ6IHoubnVtYmVyKCkuZGVzY3JpYmUoXCJOdW1iZXIgb2YgbWF0Y2hlcyBmb3VuZFwiKSxcbiAgICAgICAgZmlsZUNvdW50OiB6Lm51bWJlcigpLmRlc2NyaWJlKFwiTnVtYmVyIG9mIGZpbGVzIGNvbnRhaW5pbmcgbWF0Y2hlc1wiKSxcbiAgICAgICAgc2VhcmNoUGF0aDogei5zdHJpbmcoKS5kZXNjcmliZShcIlBhdGggdGhhdCB3YXMgc2VhcmNoZWRcIiksXG4gICAgICAgIHBhdHRlcm46IHouc3RyaW5nKCkuZGVzY3JpYmUoXCJQYXR0ZXJuIHRoYXQgd2FzIHNlYXJjaGVkIGZvclwiKSxcbiAgICAgIH0pLFxuICAgIH0pLFxuICB9KSxcbiAgTGlzdDogdG9vbCh7XG4gICAgZGVzY3JpcHRpb246XG4gICAgICBcIlJlY3Vyc2l2ZWx5IGxpc3QgZGlyZWN0b3J5IGNvbnRlbnRzLiBVc2UgdGhpcyB0byB1bmRlcnN0YW5kIHRoZSBjb2RlYmFzZSBzdHJ1Y3R1cmUsIGZpbmQgZmlsZXMsIG9yIGV4cGxvcmUgZGlyZWN0b3JpZXMuIENvbnRyb2wgZGVwdGggdG8gYmFsYW5jZSBkZXRhaWwgdnMuIG92ZXJ2aWV3LiBEZXB0aCAxIHNob3dzIGltbWVkaWF0ZSBjaGlsZHJlbiwgZGVwdGggMiBpbmNsdWRlcyBzdWJkaXJlY3RvcmllcywgZXRjLlwiLFxuICAgIGlucHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4gICAgICBwYXRoOiB6XG4gICAgICAgIC5zdHJpbmcoKVxuICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAuZGVzY3JpYmUoXCJQYXRoIHRvIGxpc3QgKGRlZmF1bHRzIHRvIHdvcmtzcGFjZSByb290KVwiKSxcbiAgICAgIGRlcHRoOiB6XG4gICAgICAgIC5udW1iZXIoKVxuICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgXCJNYXhpbXVtIGRlcHRoIHRvIHRyYXZlcnNlLiBDaG9vc2UgYmFzZWQgb24gY29udGV4dDogMS0yIGZvciBxdWljayBvdmVydmlldywgMy00IGZvciBkZXRhaWxlZCBleHBsb3JhdGlvbiwgNSsgZm9yIGNvbXByZWhlbnNpdmUgbWFwcGluZ1wiXG4gICAgICAgICksXG4gICAgICBpbmNsdWRlSGlkZGVuOiB6XG4gICAgICAgIC5ib29sZWFuKClcbiAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgLmRlZmF1bHQoZmFsc2UpXG4gICAgICAgIC5kZXNjcmliZShcbiAgICAgICAgICBcIkluY2x1ZGUgaGlkZGVuIGZpbGVzIGFuZCBkaXJlY3RvcmllcyAodGhvc2Ugc3RhcnRpbmcgd2l0aCAnLicpXCJcbiAgICAgICAgKSxcbiAgICAgIGZpbGVzT25seTogelxuICAgICAgICAuYm9vbGVhbigpXG4gICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgIC5kZWZhdWx0KGZhbHNlKVxuICAgICAgICAuZGVzY3JpYmUoXCJPbmx5IHNob3cgZmlsZXMsIG5vdCBkaXJlY3Rvcmllc1wiKSxcbiAgICAgIHBhdHRlcm46IHpcbiAgICAgICAgLnN0cmluZygpXG4gICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgIC5kZXNjcmliZShcIkdsb2IgcGF0dGVybiB0byBmaWx0ZXIgcmVzdWx0cyAoZS5nLiwgJyoudHMnLCAnKnRlc3QqJylcIiksXG4gICAgfSksXG4gICAgb3V0cHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4gICAgICBsaXN0aW5nOiB6XG4gICAgICAgIC5zdHJpbmcoKVxuICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgXCJEaXJlY3RvcnkgdHJlZSBsaXN0aW5nIHNob3dpbmcgcGF0aHMgcmVsYXRpdmUgdG8gc2VhcmNoIHJvb3RcIlxuICAgICAgICApLFxuICAgICAgc3VtbWFyeTogei5vYmplY3Qoe1xuICAgICAgICB0b3RhbEl0ZW1zOiB6Lm51bWJlcigpLmRlc2NyaWJlKFwiVG90YWwgbnVtYmVyIG9mIGl0ZW1zIGZvdW5kXCIpLFxuICAgICAgICB0b3RhbEZpbGVzOiB6Lm51bWJlcigpLmRlc2NyaWJlKFwiVG90YWwgbnVtYmVyIG9mIGZpbGVzIGZvdW5kXCIpLFxuICAgICAgICB0b3RhbERpcnM6IHoubnVtYmVyKCkuZGVzY3JpYmUoXCJUb3RhbCBudW1iZXIgb2YgZGlyZWN0b3JpZXMgZm91bmRcIiksXG4gICAgICAgIHNlYXJjaFBhdGg6IHouc3RyaW5nKCkuZGVzY3JpYmUoXCJQYXRoIHRoYXQgd2FzIGxpc3RlZFwiKSxcbiAgICAgICAgZGVwdGg6IHpcbiAgICAgICAgICAubnVtYmVyKClcbiAgICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAgIC5kZXNjcmliZShcIk1heGltdW0gZGVwdGggdXNlZCAoaWYgc3BlY2lmaWVkKVwiKSxcbiAgICAgIH0pLFxuICAgIH0pLFxuICB9KSxcbiAgV3JpdGU6IHRvb2woe1xuICAgIGRlc2NyaXB0aW9uOlxuICAgICAgXCJXcml0ZSBjb250ZW50IHRvIGEgZmlsZS4gQ3JlYXRlcyBwYXJlbnQgZGlyZWN0b3JpZXMgYXV0b21hdGljYWxseS4gT3ZlcndyaXRlcyBleGlzdGluZyBmaWxlcy5cIixcbiAgICBpbnB1dFNjaGVtYTogei5vYmplY3Qoe1xuICAgICAgcGF0aDogei5zdHJpbmcoKS5kZXNjcmliZShcIlBhdGggdG8gdGhlIGZpbGUgcmVsYXRpdmUgdG8gd29ya3NwYWNlIHJvb3RcIiksXG4gICAgICBjb250ZW50OiB6LnN0cmluZygpLmRlc2NyaWJlKFwiQ29udGVudCB0byB3cml0ZSB0byB0aGUgZmlsZVwiKSxcbiAgICB9KSxcbiAgICBvdXRwdXRTY2hlbWE6IHoub2JqZWN0KHtcbiAgICAgIHN1Y2Nlc3M6IHouYm9vbGVhbigpLmRlc2NyaWJlKFwiV2hldGhlciB0aGUgd3JpdGUgc3VjY2VlZGVkXCIpLFxuICAgICAgcGF0aDogei5zdHJpbmcoKS5kZXNjcmliZShcIlBhdGggdG8gdGhlIHdyaXR0ZW4gZmlsZVwiKSxcbiAgICAgIGJ5dGVzV3JpdHRlbjogei5udW1iZXIoKS5kZXNjcmliZShcIk51bWJlciBvZiBieXRlcyB3cml0dGVuXCIpLFxuICAgICAgZXJyb3I6IHouc3RyaW5nKCkub3B0aW9uYWwoKS5kZXNjcmliZShcIkVycm9yIG1lc3NhZ2UgaWYgd3JpdGUgZmFpbGVkXCIpLFxuICAgIH0pLFxuICB9KSxcbiAgRWRpdDogdG9vbCh7XG4gICAgZGVzY3JpcHRpb246XG4gICAgICBcIkVkaXQgYSBmaWxlIGJ5IHJlcGxhY2luZyBhbiBleGFjdCBzdHJpbmcuIEZhaWxzIGlmIG9sZF9zdHJpbmcgaXMgbm90IGZvdW5kIG9yIGFwcGVhcnMgbXVsdGlwbGUgdGltZXMgKG5vdCB1bmlxdWUpLiBGb3IgbXVsdGlwbGUgcmVwbGFjZW1lbnRzLCBjYWxsIHRoaXMgdG9vbCBtdWx0aXBsZSB0aW1lcyB3aXRoIHVuaXF1ZSBjb250ZXh0LlwiLFxuICAgIGlucHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4gICAgICBwYXRoOiB6LnN0cmluZygpLmRlc2NyaWJlKFwiUGF0aCB0byB0aGUgZmlsZSByZWxhdGl2ZSB0byB3b3Jrc3BhY2Ugcm9vdFwiKSxcbiAgICAgIG9sZF9zdHJpbmc6IHpcbiAgICAgICAgLnN0cmluZygpXG4gICAgICAgIC5kZXNjcmliZShcIkV4YWN0IHN0cmluZyB0byBmaW5kIGFuZCByZXBsYWNlIChtdXN0IGJlIHVuaXF1ZSBpbiBmaWxlKVwiKSxcbiAgICAgIG5ld19zdHJpbmc6IHouc3RyaW5nKCkuZGVzY3JpYmUoXCJTdHJpbmcgdG8gcmVwbGFjZSBvbGRfc3RyaW5nIHdpdGhcIiksXG4gICAgfSksXG4gICAgb3V0cHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4gICAgICBzdWNjZXNzOiB6LmJvb2xlYW4oKS5kZXNjcmliZShcIldoZXRoZXIgdGhlIGVkaXQgc3VjY2VlZGVkXCIpLFxuICAgICAgcGF0aDogei5zdHJpbmcoKS5kZXNjcmliZShcIlBhdGggdG8gdGhlIGVkaXRlZCBmaWxlXCIpLFxuICAgICAgZXJyb3I6IHouc3RyaW5nKCkub3B0aW9uYWwoKS5kZXNjcmliZShcIkVycm9yIG1lc3NhZ2UgaWYgZWRpdCBmYWlsZWRcIiksXG4gICAgfSksXG4gIH0pLFxuICBCYXNoOiB0b29sKHtcbiAgICBkZXNjcmlwdGlvbjpcbiAgICAgIFwiRXhlY3V0ZXMgYSBiYXNoIGNvbW1hbmQgaW5zaWRlIHRoZSB3b3Jrc3BhY2UuIENXRCBwZXJzaXN0cyBiZXR3ZWVuIGNvbW1hbmRzIHdpdGhpbiBhIHNlc3Npb24uIFVzZSB3YWl0VW50aWw6MCBmb3IgYmFja2dyb3VuZCBwcm9jZXNzZXMgKGRldiBzZXJ2ZXJzKS5cIixcbiAgICBpbnB1dFNjaGVtYTogei5vYmplY3Qoe1xuICAgICAgY29tbWFuZDogei5zdHJpbmcoKS5kZXNjcmliZShcIlRoZSBzaGVsbCBjb21tYW5kIHRvIGV4ZWN1dGVcIiksXG4gICAgICB3YWl0VW50aWw6IHpcbiAgICAgICAgLm51bWJlcigpXG4gICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgIC5kZXNjcmliZShcbiAgICAgICAgICBgTWF4IG1zIHRvIHdhaXQgZm9yIGNvbXBsZXRpb24gKGRlZmF1bHQ6ICR7REVGQVVMVF9XQUlUX1VOVElMfSkuIFVzZSAwIHRvIHJ1biBpbiBiYWNrZ3JvdW5kIGFuZCByZXR1cm4gaW1tZWRpYXRlbHkuYFxuICAgICAgICApLFxuICAgIH0pLFxuICAgIG91dHB1dFNjaGVtYTogei5vYmplY3Qoe1xuICAgICAgcGlkOiB6XG4gICAgICAgIC5udW1iZXIoKVxuICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgXCJTeXN0ZW0gUElEICgwIGZvciBmb3JlZ3JvdW5kLCA+MCBmb3IgYmFja2dyb3VuZCAtIHVzZSB0byBraWxsKVwiXG4gICAgICAgICksXG4gICAgICBvdXRwdXQ6IHpcbiAgICAgICAgLnN0cmluZygpXG4gICAgICAgIC5kZXNjcmliZShcIkNvbW1hbmQgc3Rkb3V0K3N0ZGVyciBjb21iaW5lZCAoZW1wdHkgZm9yIGJhY2tncm91bmQpXCIpLFxuICAgICAgZXhpdENvZGU6IHoubnVtYmVyKCkuZGVzY3JpYmUoXCJFeGl0IGNvZGUgKC0xIGZvciBiYWNrZ3JvdW5kL3J1bm5pbmcpXCIpLFxuICAgICAgc3RhdHVzOiB6XG4gICAgICAgIC5lbnVtKFtcInJ1bm5pbmdcIiwgXCJjb21wbGV0ZWRcIiwgXCJmYWlsZWRcIl0pXG4gICAgICAgIC5kZXNjcmliZShcIlByb2Nlc3Mgc3RhdHVzXCIpLFxuICAgICAgY3dkOiB6LnN0cmluZygpLmRlc2NyaWJlKFwiQ3VycmVudCB3b3JraW5nIGRpcmVjdG9yeSBhZnRlciBjb21tYW5kXCIpLFxuICAgICAgb3V0cHV0RmlsZTogelxuICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgLmRlc2NyaWJlKFwiUGF0aCB0byBvdXRwdXQgbG9nIChmb3IgYmFja2dyb3VuZCBwcm9jZXNzZXMpXCIpLFxuICAgIH0pLFxuICB9KSxcbiAgSmF2YVNjcmlwdDogdG9vbCh7XG4gICAgaW5wdXRTY2hlbWE6IHoub2JqZWN0KHtcbiAgICAgIGNvZGU6IHpcbiAgICAgICAgLnN0cmluZygpXG4gICAgICAgIC5kZXNjcmliZShcbiAgICAgICAgICBcIkphdmFTY3JpcHQgYXN5bmMgZnVuY3Rpb24gYm9keS4gYGN0eGAgaXMgaW4gc2NvcGUuIE11c3QgdXNlIGByZXR1cm5gIHRvIHByb2R1Y2Ugb3V0cHV0LlwiXG4gICAgICAgICksXG4gICAgfSksXG4gIH0pLFxufSBzYXRpc2ZpZXMgVG9vbFNldDtcblxuZXhwb3J0IHR5cGUgQnVpbHRJblRvb2xOYW1lID0ga2V5b2YgdHlwZW9mIGJ1aWx0SW5Ub29scztcbmV4cG9ydCBjb25zdCBidWlsdGluVG9vbE5hbWVzID0gT2JqZWN0LmZyb21FbnRyaWVzKFxuICBPYmplY3QuZW50cmllcyhidWlsdEluVG9vbHMpLm1hcCgoW25hbWVdKSA9PiBbbmFtZSwgbmFtZV0pXG4pIGFzIHsgW0sgaW4gQnVpbHRJblRvb2xOYW1lXTogSyB9O1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0VG9vbHMoY29udGV4dDogSW50ZXJuYWxUb29sQ29udGV4dCkge1xuICBjb25zdCB0b29sczogVG9vbFNldCA9IHtcbiAgICBbYnVpbHRpblRvb2xOYW1lcy5SZWFkXTogdG9vbCh7XG4gICAgICAuLi5idWlsdEluVG9vbHMuUmVhZCxcbiAgICAgIGV4ZWN1dGU6IGFzeW5jICh7IHBhdGgsIHN0YXJ0TGluZSwgZW5kTGluZSB9KSA9PiB7XG4gICAgICAgIGNvbnN0IGZpbGVQYXRoID0gcGF0aDtcblxuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb250ZXh0LnNhbmRib3gucmVhZEZpbGUoeyBwYXRoOiBmaWxlUGF0aCB9KTtcblxuICAgICAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKFwiW1JlYWQgVG9vbF1cIiwgcmVzdWx0KTtcbiAgICAgICAgICB0aHJvdyByZXN1bHQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocmVzdWx0ID09PSBudWxsKSB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGNvbnRlbnQ6IGBFcnJvcjogRmlsZSBub3QgZm91bmQgLSAke2ZpbGVQYXRofWAsXG4gICAgICAgICAgICBtZXRhZGF0YToge1xuICAgICAgICAgICAgICB0b3RhbExpbmVzOiAwLFxuICAgICAgICAgICAgICBsaW5lc1Nob3duOiAwLFxuICAgICAgICAgICAgICBzdGFydExpbmU6IDAsXG4gICAgICAgICAgICAgIGVuZExpbmU6IDAsXG4gICAgICAgICAgICAgIGlzUGFnaW5hdGVkOiBmYWxzZSxcbiAgICAgICAgICAgICAgZmlsZVNpemU6IFwiMFwiLFxuICAgICAgICAgICAgICBwYXRoOiBmaWxlUGF0aCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGZ1bGxDb250ZW50ID0gcmVzdWx0LnRvU3RyaW5nKFwidXRmLThcIik7XG4gICAgICAgIGNvbnN0IGxpbmVzID0gZnVsbENvbnRlbnQuc3BsaXQoXCJcXG5cIik7XG4gICAgICAgIC8vIEEgdHJhaWxpbmcgbmV3bGluZSBwcm9kdWNlcyBhbiBlbXB0eSBsYXN0IGVsZW1lbnQgXHUyMDE0IHJlbW92ZSBpdFxuICAgICAgICAvLyBzbyBsaW5lIGNvdW50IG1hdGNoZXMgYHdjIC1sYCAvIGBhd2sgJ0VORHtwcmludCBOUn0nYCBiZWhhdmlvci5cbiAgICAgICAgaWYgKGxpbmVzLmxlbmd0aCA+IDAgJiYgbGluZXMuYXQoLTEpID09PSBcIlwiKSB7XG4gICAgICAgICAgbGluZXMucG9wKCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgdG90YWxMaW5lcyA9IGxpbmVzLmxlbmd0aDtcbiAgICAgICAgY29uc3QgZmlsZUJ5dGVzID0gQnVmZmVyLmJ5dGVMZW5ndGgoZnVsbENvbnRlbnQpO1xuICAgICAgICBjb25zdCBmaWxlU2l6ZSA9IGZvcm1hdEZpbGVTaXplKGZpbGVCeXRlcyk7XG5cbiAgICAgICAgLy8gRGV0ZXJtaW5lIHJhbmdlXG4gICAgICAgIGNvbnN0IFBBR0VfU0laRSA9IDEwMDtcbiAgICAgICAgbGV0IGFjdHVhbFN0YXJ0OiBudW1iZXI7XG4gICAgICAgIGxldCBhY3R1YWxFbmQ6IG51bWJlcjtcblxuICAgICAgICBpZiAoc3RhcnRMaW5lICE9PSB1bmRlZmluZWQgJiYgZW5kTGluZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgYWN0dWFsU3RhcnQgPSBzdGFydExpbmU7XG4gICAgICAgICAgYWN0dWFsRW5kID0gZW5kTGluZTtcbiAgICAgICAgfSBlbHNlIGlmIChzdGFydExpbmUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGFjdHVhbFN0YXJ0ID0gc3RhcnRMaW5lO1xuICAgICAgICAgIGFjdHVhbEVuZCA9IE1hdGgubWluKHN0YXJ0TGluZSArIFBBR0VfU0laRSAtIDEsIHRvdGFsTGluZXMpO1xuICAgICAgICB9IGVsc2UgaWYgKGVuZExpbmUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGFjdHVhbFN0YXJ0ID0gMTtcbiAgICAgICAgICBhY3R1YWxFbmQgPSBlbmRMaW5lO1xuICAgICAgICB9IGVsc2UgaWYgKHRvdGFsTGluZXMgPiAyMDApIHtcbiAgICAgICAgICBhY3R1YWxTdGFydCA9IDE7XG4gICAgICAgICAgYWN0dWFsRW5kID0gUEFHRV9TSVpFO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGFjdHVhbFN0YXJ0ID0gMTtcbiAgICAgICAgICBhY3R1YWxFbmQgPSB0b3RhbExpbmVzO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRXh0cmFjdCB0aGUgbGluZSByYW5nZSAoMS1pbmRleGVkKVxuICAgICAgICBjb25zdCBzbGljZWRMaW5lcyA9IGxpbmVzLnNsaWNlKGFjdHVhbFN0YXJ0IC0gMSwgYWN0dWFsRW5kKTtcbiAgICAgICAgY29uc3QgY29udGVudCA9IHNsaWNlZExpbmVzLmpvaW4oXCJcXG5cIik7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBtZXRhZGF0YToge1xuICAgICAgICAgICAgdG90YWxMaW5lcyxcbiAgICAgICAgICAgIGxpbmVzU2hvd246IE1hdGgubWF4KDAsIGFjdHVhbEVuZCAtIGFjdHVhbFN0YXJ0ICsgMSksXG4gICAgICAgICAgICBzdGFydExpbmU6IGFjdHVhbFN0YXJ0LFxuICAgICAgICAgICAgZW5kTGluZTogYWN0dWFsRW5kLFxuICAgICAgICAgICAgaXNQYWdpbmF0ZWQ6IGFjdHVhbEVuZCA8IHRvdGFsTGluZXMsXG4gICAgICAgICAgICBmaWxlU2l6ZSxcbiAgICAgICAgICAgIHBhdGg6IGZpbGVQYXRoLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgY29udGVudCxcbiAgICAgICAgfTtcbiAgICAgIH0sXG4gICAgfSksXG4gICAgW2J1aWx0aW5Ub29sTmFtZXMuR3JlcF06IHRvb2woe1xuICAgICAgLi4uYnVpbHRJblRvb2xzLkdyZXAsXG4gICAgICBleGVjdXRlOiBhc3luYyAoe1xuICAgICAgICBwYXR0ZXJuLFxuICAgICAgICBwYXRoLFxuICAgICAgICBmaWxlVHlwZSxcbiAgICAgICAgZ2xvYixcbiAgICAgICAgY2FzZVNlbnNpdGl2ZSxcbiAgICAgICAgY29udGV4dExpbmVzLFxuICAgICAgICBtYXhDb3VudCxcbiAgICAgICAgZmlsZXNXaXRoTWF0Y2hlcyxcbiAgICAgIH0pID0+IHtcbiAgICAgICAgY29uc3Qgc2VhcmNoUGF0aCA9IHBhdGggPz8gXCIuXCI7XG5cbiAgICAgICAgY29uc3QgYXJnczogc3RyaW5nW10gPSBbXTtcblxuICAgICAgICBhcmdzLnB1c2goXCItLWxpbmUtbnVtYmVyXCIpO1xuICAgICAgICBhcmdzLnB1c2goXCItLWhlYWRpbmdcIik7XG4gICAgICAgIGFyZ3MucHVzaChcIi0tY29sb3JcIiwgXCJuZXZlclwiKTtcblxuICAgICAgICBpZiAoIWNhc2VTZW5zaXRpdmUpIHtcbiAgICAgICAgICBhcmdzLnB1c2goXCItaVwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmaWxlVHlwZSkge1xuICAgICAgICAgIGFyZ3MucHVzaChcIi0tdHlwZVwiLCBmaWxlVHlwZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZ2xvYikge1xuICAgICAgICAgIGFyZ3MucHVzaChcIi0tZ2xvYlwiLCBnbG9iKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjb250ZXh0TGluZXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGFyZ3MucHVzaChcIi1DXCIsIFN0cmluZyhjb250ZXh0TGluZXMpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChtYXhDb3VudCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgYXJncy5wdXNoKFwiLS1tYXgtY291bnRcIiwgU3RyaW5nKG1heENvdW50KSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZmlsZXNXaXRoTWF0Y2hlcykge1xuICAgICAgICAgIGFyZ3MucHVzaChcIi0tZmlsZXMtd2l0aC1tYXRjaGVzXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgYXJncy5wdXNoKFwiLS1cIiwgcGF0dGVybiwgc2VhcmNoUGF0aCk7XG5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udGV4dC5zYW5kYm94LmV4ZWMoeyBjb21tYW5kOiBcInJnXCIsIGFyZ3MgfSk7XG5cbiAgICAgICAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihcIltHcmVwIFRvb2xdXCIsIHJlc3VsdCk7XG4gICAgICAgICAgdGhyb3cgcmVzdWx0O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgeyBzdGRvdXQsIHN0ZGVyciB9ID0gYXdhaXQgcmVzdWx0LnJlc3VsdDtcblxuICAgICAgICBpZiAoc3RkZXJyICYmICFzdGRlcnIudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyhcIm5vIG1hdGNoZXNcIikpIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKGBbR3JlcCBUb29sXSBXYXJuaW5nOiAke3N0ZGVycn1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRydW5jYXRlIG91dHB1dCB0byBwcmV2ZW50IFwiaW5wdXQgdG9vIGxvbmdcIiBlcnJvcnMgKDUwayBjaGFycyBcdTIyNDggMTIuNWsgdG9rZW5zKVxuICAgICAgICBjb25zdCBNQVhfR1JFUF9PVVRQVVRfQ0hBUlMgPSA1MF8wMDA7XG4gICAgICAgIGxldCBmaW5hbE91dHB1dCA9IHN0ZG91dDtcbiAgICAgICAgbGV0IHdhc1RydW5jYXRlZCA9IGZhbHNlO1xuICAgICAgICBpZiAoZmluYWxPdXRwdXQubGVuZ3RoID4gTUFYX0dSRVBfT1VUUFVUX0NIQVJTKSB7XG4gICAgICAgICAgZmluYWxPdXRwdXQgPVxuICAgICAgICAgICAgZmluYWxPdXRwdXQuc2xpY2UoMCwgTUFYX0dSRVBfT1VUUFVUX0NIQVJTKSArXG4gICAgICAgICAgICBcIlxcblxcbltPdXRwdXQgdHJ1bmNhdGVkIC0gdXNlIG1vcmUgc3BlY2lmaWMgcGF0dGVybiBvciBwYXRoXVwiO1xuICAgICAgICAgIHdhc1RydW5jYXRlZCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBsaW5lcyA9IGZpbmFsT3V0cHV0XG4gICAgICAgICAgLnRyaW0oKVxuICAgICAgICAgIC5zcGxpdChcIlxcblwiKVxuICAgICAgICAgIC5maWx0ZXIoKGwpID0+IGwubGVuZ3RoID4gMCk7XG4gICAgICAgIGNvbnN0IGZpbGVDb3VudCA9IGZpbGVzV2l0aE1hdGNoZXNcbiAgICAgICAgICA/IGxpbmVzLmxlbmd0aFxuICAgICAgICAgIDogbmV3IFNldChcbiAgICAgICAgICAgICAgbGluZXNcbiAgICAgICAgICAgICAgICAuZmlsdGVyKChsKSA9PiAhbC5zdGFydHNXaXRoKFwiIFwiKSAmJiBsLmluY2x1ZGVzKFwiOlwiKSlcbiAgICAgICAgICAgICAgICAubWFwKChsKSA9PiBsLnNwbGl0KFwiOlwiKVswXSlcbiAgICAgICAgICAgICkuc2l6ZTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHN1bW1hcnk6IHtcbiAgICAgICAgICAgIG1hdGNoQ291bnQ6IGZpbGVzV2l0aE1hdGNoZXNcbiAgICAgICAgICAgICAgPyAwXG4gICAgICAgICAgICAgIDogbGluZXMuZmlsdGVyKChsKSA9PiBsLmluY2x1ZGVzKFwiOlwiKSkubGVuZ3RoLFxuICAgICAgICAgICAgZmlsZUNvdW50LFxuICAgICAgICAgICAgc2VhcmNoUGF0aCxcbiAgICAgICAgICAgIHBhdHRlcm4sXG4gICAgICAgICAgICB3YXNUcnVuY2F0ZWQsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBtYXRjaGVzOiBmaW5hbE91dHB1dCB8fCBcIihubyBtYXRjaGVzIGZvdW5kKVwiLFxuICAgICAgICB9O1xuICAgICAgfSxcbiAgICB9KSxcbiAgICBbYnVpbHRpblRvb2xOYW1lcy5MaXN0XTogdG9vbCh7XG4gICAgICAuLi5idWlsdEluVG9vbHMuTGlzdCxcbiAgICAgIGV4ZWN1dGU6IGFzeW5jICh7IHBhdGgsIGRlcHRoLCBpbmNsdWRlSGlkZGVuLCBmaWxlc09ubHksIHBhdHRlcm4gfSkgPT4ge1xuICAgICAgICBjb25zdCBzZWFyY2hQYXRoID0gcGF0aCA/PyBcIi5cIjtcblxuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb250ZXh0LnNhbmRib3guZXhlYyh7XG4gICAgICAgICAgY29tbWFuZDogXCJiYXNoXCIsXG4gICAgICAgICAgYXJnczogW1xuICAgICAgICAgICAgXCItY1wiLFxuICAgICAgICAgICAgYFxuICAgICAgICAgICAgc2V0IC1lXG4gICAgICAgICAgICBTRUFSQ0hfUEFUSD1cIiQxXCJcbiAgICAgICAgICAgIERFUFRIPVwiJDJcIlxuICAgICAgICAgICAgSU5DTFVERV9ISURERU49XCIkM1wiXG4gICAgICAgICAgICBGSUxFU19PTkxZPVwiJDRcIlxuICAgICAgICAgICAgUEFUVEVSTj1cIiQ1XCJcblxuICAgICAgICAgICAgIyBCdWlsZCBmaW5kIGNvbW1hbmQgYXJndW1lbnRzXG4gICAgICAgICAgICBGSU5EX0FSR1M9XCJcIlxuICAgICAgICAgICAgWyAtbiBcIiRERVBUSFwiIF0gJiYgRklORF9BUkdTPVwiJEZJTkRfQVJHUyAtbWF4ZGVwdGggJERFUFRIXCJcbiAgICAgICAgICAgIFsgXCIkSU5DTFVERV9ISURERU5cIiAhPSBcInRydWVcIiBdICYmIEZJTkRfQVJHUz1cIiRGSU5EX0FSR1MgISAtcGF0aCAnKi8uKidcIlxuICAgICAgICAgICAgWyBcIiRGSUxFU19PTkxZXCIgPSBcInRydWVcIiBdICYmIEZJTkRfQVJHUz1cIiRGSU5EX0FSR1MgLXR5cGUgZlwiXG4gICAgICAgICAgICBbIC1uIFwiJFBBVFRFUk5cIiBdICYmIEZJTkRfQVJHUz1cIiRGSU5EX0FSR1MgLW5hbWUgJyRQQVRURVJOJ1wiXG5cbiAgICAgICAgICAgICMgR2V0IGxpc3RpbmdcbiAgICAgICAgICAgIExJU1RJTkc9JChldmFsIFwiZmluZCAnJFNFQVJDSF9QQVRIJyAkRklORF9BUkdTXCIgMj4vZGV2L251bGwgfCBzb3J0KVxuXG4gICAgICAgICAgICAjIEdldCBjb3VudHNcbiAgICAgICAgICAgIENPVU5UX0FSR1M9XCJcIlxuICAgICAgICAgICAgWyAtbiBcIiRERVBUSFwiIF0gJiYgQ09VTlRfQVJHUz1cIiRDT1VOVF9BUkdTIC1tYXhkZXB0aCAkREVQVEhcIlxuICAgICAgICAgICAgWyBcIiRJTkNMVURFX0hJRERFTlwiICE9IFwidHJ1ZVwiIF0gJiYgQ09VTlRfQVJHUz1cIiRDT1VOVF9BUkdTICEgLXBhdGggJyovLionXCJcblxuICAgICAgICAgICAgRklMRV9DT1VOVD0kKGV2YWwgXCJmaW5kICckU0VBUkNIX1BBVEgnICRDT1VOVF9BUkdTIC10eXBlIGZcIiAyPi9kZXYvbnVsbCB8IHdjIC1sKVxuICAgICAgICAgICAgRElSX0NPVU5UPSQoZXZhbCBcImZpbmQgJyRTRUFSQ0hfUEFUSCcgJENPVU5UX0FSR1MgLXR5cGUgZFwiIDI+L2Rldi9udWxsIHwgd2MgLWwpXG5cbiAgICAgICAgICAgICMgT3V0cHV0OiBjb3VudHMgZmlyc3QsIHRoZW4gbGlzdGluZ1xuICAgICAgICAgICAgZWNobyBcIiRGSUxFX0NPVU5UfCRESVJfQ09VTlRcIlxuICAgICAgICAgICAgZWNobyBcInx8fExJU1RJTkd8fHxcIlxuICAgICAgICAgICAgZWNobyBcIiRMSVNUSU5HXCIgfCBzZWQgXCJzfF4kU0VBUkNIX1BBVEh8LnxcIlxuICAgICAgICAgIGAsXG4gICAgICAgICAgICBcIi0tXCIsXG4gICAgICAgICAgICBzZWFyY2hQYXRoLFxuICAgICAgICAgICAgZGVwdGg/LnRvU3RyaW5nKCkgfHwgXCJcIixcbiAgICAgICAgICAgIGluY2x1ZGVIaWRkZW4gPyBcInRydWVcIiA6IFwiZmFsc2VcIixcbiAgICAgICAgICAgIGZpbGVzT25seSA/IFwidHJ1ZVwiIDogXCJmYWxzZVwiLFxuICAgICAgICAgICAgcGF0dGVybiB8fCBcIlwiLFxuICAgICAgICAgIF0sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJbTGlzdCBUb29sXVwiLCByZXN1bHQpO1xuICAgICAgICAgIHRocm93IHJlc3VsdDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHsgc3Rkb3V0LCBzdGRlcnIgfSA9IGF3YWl0IHJlc3VsdC5yZXN1bHQ7XG5cbiAgICAgICAgaWYgKHN0ZGVycikge1xuICAgICAgICAgIGNvbnNvbGUud2FybihgW0xpc3QgVG9vbF0gc3RkZXJyOiAke3N0ZGVycn1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IFtjb3VudHNMaW5lLCAuLi5yZXN0XSA9IHN0ZG91dC5zcGxpdChcInx8fExJU1RJTkd8fHxcIik7XG4gICAgICAgIGNvbnN0IGxpc3RpbmcgPSByZXN0LmpvaW4oXCJ8fHxMSVNUSU5HfHx8XCIpLnRyaW0oKTtcbiAgICAgICAgY29uc3QgW2ZpbGVDb3VudFN0ciwgZGlyQ291bnRTdHJdID0gY291bnRzTGluZS50cmltKCkuc3BsaXQoXCJ8XCIpO1xuXG4gICAgICAgIGNvbnN0IHRvdGFsRmlsZXMgPSBOdW1iZXIucGFyc2VJbnQoZmlsZUNvdW50U3RyLCAxMCkgfHwgMDtcbiAgICAgICAgY29uc3QgdG90YWxEaXJzID0gTnVtYmVyLnBhcnNlSW50KGRpckNvdW50U3RyLCAxMCkgfHwgMDtcbiAgICAgICAgY29uc3QgbGluZXMgPSBsaXN0aW5nLnNwbGl0KFwiXFxuXCIpLmZpbHRlcigobCkgPT4gbC5sZW5ndGggPiAwKTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHN1bW1hcnk6IHtcbiAgICAgICAgICAgIHRvdGFsSXRlbXM6IGxpbmVzLmxlbmd0aCxcbiAgICAgICAgICAgIHRvdGFsRmlsZXMsXG4gICAgICAgICAgICB0b3RhbERpcnMsXG4gICAgICAgICAgICBzZWFyY2hQYXRoLFxuICAgICAgICAgICAgZGVwdGgsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBsaXN0aW5nLFxuICAgICAgICB9O1xuICAgICAgfSxcbiAgICB9KSxcbiAgICBbYnVpbHRpblRvb2xOYW1lcy5Xcml0ZV06IHRvb2woe1xuICAgICAgLi4uYnVpbHRJblRvb2xzLldyaXRlLFxuICAgICAgZXhlY3V0ZTogYXN5bmMgKHsgcGF0aCwgY29udGVudCB9KSA9PiB7XG4gICAgICAgIGNvbnN0IGZpbGVQYXRoID0gcGF0aC5zdGFydHNXaXRoKFwiL1wiKSA/IHBhdGguc2xpY2UoMSkgOiBwYXRoO1xuICAgICAgICBjb25zdCBkaXIgPSBmaWxlUGF0aC5pbmNsdWRlcyhcIi9cIilcbiAgICAgICAgICA/IGZpbGVQYXRoLnNwbGl0KFwiL1wiKS5zbGljZSgwLCAtMSkuam9pbihcIi9cIilcbiAgICAgICAgICA6IFwiLlwiO1xuICAgICAgICBjb25zdCBmaWxlTmFtZSA9IGZpbGVQYXRoLnNwbGl0KFwiL1wiKS5wb3AoKSB8fCBmaWxlUGF0aDtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgIGlmIChkaXIgIT09IFwiLlwiKSB7XG4gICAgICAgICAgICBhd2FpdCBjb250ZXh0LnNhbmRib3guZXhlYyh7IGNvbW1hbmQ6IFwibWtkaXJcIiwgYXJnczogW1wiLXBcIiwgZGlyXSB9KTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBhd2FpdCBjb250ZXh0LnNhbmRib3gud3JpdGVGaWxlcyh7XG4gICAgICAgICAgICBmaWxlczogW3sgcGF0aDogZmlsZU5hbWUsIGNvbnRlbnQgfV0sXG4gICAgICAgICAgICBkZXN0UGF0aDogZGlyLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHN1Y2Nlc3M6IHRydWUsXG4gICAgICAgICAgICBwYXRoOiBmaWxlUGF0aCxcbiAgICAgICAgICAgIGJ5dGVzV3JpdHRlbjogQnVmZmVyLmJ5dGVMZW5ndGgoY29udGVudCwgXCJ1dGY4XCIpLFxuICAgICAgICAgIH07XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIGNvbnN0IGVycm9yTXNnID0gZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpO1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICAgICAgICAgIHBhdGg6IGZpbGVQYXRoLFxuICAgICAgICAgICAgYnl0ZXNXcml0dGVuOiAwLFxuICAgICAgICAgICAgZXJyb3I6IGVycm9yTXNnLFxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSksXG4gICAgW2J1aWx0aW5Ub29sTmFtZXMuRWRpdF06IHRvb2woe1xuICAgICAgLi4uYnVpbHRJblRvb2xzLkVkaXQsXG4gICAgICBleGVjdXRlOiBhc3luYyAoeyBwYXRoLCBvbGRfc3RyaW5nLCBuZXdfc3RyaW5nIH0pID0+IHtcbiAgICAgICAgY29uc3QgZmlsZVBhdGggPSBwYXRoLnN0YXJ0c1dpdGgoXCIvXCIpID8gcGF0aC5zbGljZSgxKSA6IHBhdGg7XG5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udGV4dC5zYW5kYm94LnJlYWRGaWxlKHsgcGF0aDogZmlsZVBhdGggfSk7XG5cbiAgICAgICAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIHsgc3VjY2VzczogZmFsc2UsIHBhdGg6IGZpbGVQYXRoLCBlcnJvcjogcmVzdWx0Lm1lc3NhZ2UgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChyZXN1bHQgPT09IG51bGwpIHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICAgICAgICBwYXRoOiBmaWxlUGF0aCxcbiAgICAgICAgICAgIGVycm9yOiBgRmlsZSBub3QgZm91bmQ6ICR7ZmlsZVBhdGh9YCxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY29udGVudCA9IHJlc3VsdC50b1N0cmluZyhcInV0Zi04XCIpO1xuICAgICAgICBjb25zdCBvY2N1cnJlbmNlcyA9IGNvbnRlbnQuc3BsaXQob2xkX3N0cmluZykubGVuZ3RoIC0gMTtcblxuICAgICAgICBpZiAob2NjdXJyZW5jZXMgPT09IDApIHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICAgICAgICBwYXRoOiBmaWxlUGF0aCxcbiAgICAgICAgICAgIGVycm9yOiBcIm9sZF9zdHJpbmcgbm90IGZvdW5kIGluIGZpbGVcIixcbiAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG9jY3VycmVuY2VzID4gMSkge1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICAgICAgICAgIHBhdGg6IGZpbGVQYXRoLFxuICAgICAgICAgICAgZXJyb3I6IGBvbGRfc3RyaW5nIGFwcGVhcnMgJHtvY2N1cnJlbmNlc30gdGltZXMgaW4gZmlsZSAobXVzdCBiZSB1bmlxdWUpLiBJbmNsdWRlIG1vcmUgc3Vycm91bmRpbmcgY29udGV4dCB0byBtYWtlIHRoZSBtYXRjaCB1bmlxdWUuYCxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbmV3Q29udGVudCA9IGNvbnRlbnQucmVwbGFjZShvbGRfc3RyaW5nLCBuZXdfc3RyaW5nKTtcbiAgICAgICAgY29uc3QgZGlyID0gZmlsZVBhdGguaW5jbHVkZXMoXCIvXCIpXG4gICAgICAgICAgPyBmaWxlUGF0aC5zcGxpdChcIi9cIikuc2xpY2UoMCwgLTEpLmpvaW4oXCIvXCIpXG4gICAgICAgICAgOiBcIi5cIjtcbiAgICAgICAgY29uc3QgZmlsZU5hbWUgPSBmaWxlUGF0aC5zcGxpdChcIi9cIikucG9wKCkgfHwgZmlsZVBhdGg7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCBjb250ZXh0LnNhbmRib3gud3JpdGVGaWxlcyh7XG4gICAgICAgICAgICBmaWxlczogW3sgcGF0aDogZmlsZU5hbWUsIGNvbnRlbnQ6IG5ld0NvbnRlbnQgfV0sXG4gICAgICAgICAgICBkZXN0UGF0aDogZGlyLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgcmV0dXJuIHsgc3VjY2VzczogdHJ1ZSwgcGF0aDogZmlsZVBhdGggfTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgY29uc3QgZXJyb3JNc2cgPSBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVycik7XG4gICAgICAgICAgcmV0dXJuIHsgc3VjY2VzczogZmFsc2UsIHBhdGg6IGZpbGVQYXRoLCBlcnJvcjogZXJyb3JNc2cgfTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICB9KSxcbiAgICBbYnVpbHRpblRvb2xOYW1lcy5CYXNoXTogdG9vbCh7XG4gICAgICAuLi5idWlsdEluVG9vbHMuQmFzaCxcbiAgICAgIGV4ZWN1dGU6IGFzeW5jICh7IGNvbW1hbmQsIHdhaXRVbnRpbCB9KSA9PiB7XG4gICAgICAgIGNvbnN0IHsgY3JlYXRlUHJvY2Vzc01hbmFnZXIgfSA9IGF3YWl0IGltcG9ydChcbiAgICAgICAgICBcIi4uL3NhbmRib3gvcHJvY2Vzcy1tYW5hZ2VyXCJcbiAgICAgICAgKTtcblxuICAgICAgICBjb25zdCBwcm9jZXNzTWFuYWdlciA9IGNyZWF0ZVByb2Nlc3NNYW5hZ2VyKHtcbiAgICAgICAgICBzYW5kYm94OiBjb250ZXh0LnNhbmRib3gsXG4gICAgICAgICAgc2Vzc2lvbklkOiBjb250ZXh0LmlucHV0LnNlc3Npb25JZCxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgYXdhaXQgcHJvY2Vzc01hbmFnZXIuaW5pdCgpO1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBwcm9jZXNzTWFuYWdlci5ydW4oeyBjb21tYW5kLCB3YWl0VW50aWwgfSk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9LFxuICAgIH0pLFxuICB9O1xuXG4gIGlmIChjb250ZXh0LmFwaVRvb2xzTWV0YWRhdGEubGVuZ3RoID4gMCkge1xuICAgIGNvbnN0IGFwaVRvb2xzID0gYnVpbGRBcGlUb29scyh7XG4gICAgICBycGM6IGNvbnRleHQucnBjLFxuICAgICAgbWV0YWRhdGE6IGNvbnRleHQuYXBpVG9vbHNNZXRhZGF0YSxcbiAgICAgIHNlc3Npb246IGNvbnRleHQuc2Vzc2lvbixcbiAgICAgIHNhbmRib3hSZWNvcmQ6IGNvbnRleHQuc2FuZGJveFJlY29yZCxcbiAgICAgIGNvbnRleHQ6IGNvbnRleHQuZXZlbnQuY29udGV4dCxcbiAgICB9KTtcbiAgICBPYmplY3QuYXNzaWduKHRvb2xzLCBhcGlUb29scyk7XG4gIH1cblxuICB0b29sc1tidWlsdGluVG9vbE5hbWVzLkphdmFTY3JpcHRdID0gY3JlYXRlSmF2YVNjcmlwdFRvb2woe1xuICAgIHRvb2xzLFxuICAgIHNlc3Npb246IGNvbnRleHQuc2Vzc2lvbixcbiAgICBzYW5kYm94OiBjb250ZXh0LnNhbmRib3gsXG4gICAgb25TdWJUb29sQ2FsbDogY29udGV4dC5vblN1YlRvb2xDYWxsLFxuICB9KTtcblxuICByZXR1cm4gdG9vbHM7XG59XG5cbnR5cGUgQXBpVG9vbE1ldGFkYXRhID0ge1xuICBuYW1lOiBzdHJpbmc7XG4gIGRlc2NyaXB0aW9uPzogc3RyaW5nO1xuICBpbnB1dFNjaGVtYT86IHVua25vd247XG59O1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZmV0Y2hBcGlUb29sc01ldGFkYXRhKG9wdHM6IHtcbiAgcnBjOiAocGFyYW1zOiBScGNQYXlsb2FkKSA9PiBQcm9taXNlPFJwY1Jlc3VsdD47XG59KTogUHJvbWlzZTxBcGlUb29sTWV0YWRhdGFbXT4ge1xuICBjb25zdCB7IHJwYyB9ID0gb3B0cztcblxuICBjb25zdCByZXN1bHQgPSBhd2FpdCBycGMoeyBtZXRob2Q6IFwidG9vbHMubGlzdFwiLCBwYXJhbXM6IHt9IH0pO1xuXG4gIGlmIChcImVycm9yXCIgaW4gcmVzdWx0KSB7XG4gICAgY29uc29sZS5lcnJvcihcIlthZ2VudF0gRmFpbGVkIHRvIGZldGNoIHRvb2xzOlwiLCByZXN1bHQuZXJyb3I/Lm1lc3NhZ2UpO1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIHJldHVybiAocmVzdWx0LnJlc3VsdCBhcyBBcGlUb29sTWV0YWRhdGFbXSkgPz8gW107XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBidWlsZEFwaVRvb2xzKG9wdHM6IHtcbiAgcnBjOiAocGFyYW1zOiBScGNQYXlsb2FkKSA9PiBQcm9taXNlPFJwY1Jlc3VsdD47XG4gIG1ldGFkYXRhOiBBcGlUb29sTWV0YWRhdGFbXTtcbiAgc2Vzc2lvbjogU2Vzc2lvbjtcbiAgc2FuZGJveFJlY29yZDogU2FuZGJveFJlY29yZDtcbiAgY29udGV4dDogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG59KTogVG9vbFNldCB7XG4gIGNvbnN0IHsgcnBjLCBtZXRhZGF0YSwgc2Vzc2lvbiwgc2FuZGJveFJlY29yZCwgY29udGV4dCB9ID0gb3B0cztcbiAgY29uc3QgdG9vbHM6IFRvb2xTZXQgPSB7fTtcblxuICBmb3IgKGNvbnN0IG1ldGEgb2YgbWV0YWRhdGEpIHtcbiAgICB0b29sc1ttZXRhLm5hbWVdID0gdG9vbCh7XG4gICAgICBkZXNjcmlwdGlvbjogbWV0YS5kZXNjcmlwdGlvbiA/PyBgQ3VzdG9tIHRvb2w6ICR7bWV0YS5uYW1lfWAsXG4gICAgICBpbnB1dFNjaGVtYTogbWV0YS5pbnB1dFNjaGVtYVxuICAgICAgICA/IGpzb25TY2hlbWEobWV0YS5pbnB1dFNjaGVtYSBhcyBQYXJhbWV0ZXJzPHR5cGVvZiBqc29uU2NoZW1hPlswXSlcbiAgICAgICAgOiB6Lm9iamVjdCh7fSksXG4gICAgICBleGVjdXRlOiBhc3luYyAoaW5wdXQpID0+IHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcnBjKHtcbiAgICAgICAgICBtZXRob2Q6IFwidG9vbHMuZXhlY3V0ZVwiLFxuICAgICAgICAgIHBhcmFtczoge1xuICAgICAgICAgICAgbmFtZTogbWV0YS5uYW1lLFxuICAgICAgICAgICAgaW5wdXQsXG4gICAgICAgICAgICBzZXNzaW9uLFxuICAgICAgICAgICAgc2FuZGJveFJlY29yZCxcbiAgICAgICAgICAgIGNvbnRleHQsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKFwiZXJyb3JcIiBpbiByZXN1bHQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFRvb2wgZXhlY3V0aW9uIGZhaWxlZDogJHtyZXN1bHQuZXJyb3I/Lm1lc3NhZ2V9YCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0LnJlc3VsdDtcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gdG9vbHM7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlQXBpVXJsKG9wdHM6IHsgYXBpOiBzdHJpbmcgfCB1bmRlZmluZWQgfSk6IHN0cmluZyB7XG4gIGxldCBvcmlnaW4gPSBcIlwiO1xuICBsZXQgcGF0aCA9IGAvLndlbGwta25vd24vYWdlbnQvJHtBR0VOVF9QUk9UT0NPTF9WRVJTSU9OfWA7XG5cbiAgaWYgKG9wdHMuYXBpKSB7XG4gICAgaWYgKG9wdHMuYXBpLnN0YXJ0c1dpdGgoXCIvXCIpKSB7XG4gICAgICBwYXRoID0gb3B0cy5hcGk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIHNlZSBpZiBpdCdzIGZ1bGxcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHVybCA9IG5ldyBVUkwob3B0cy5hcGkpO1xuICAgICAgICBvcmlnaW4gPSB1cmwub3JpZ2luO1xuICAgICAgICBjb25zdCBmdWxsUGF0aCA9IHVybC5wYXRobmFtZSArIHVybC5zZWFyY2ggKyB1cmwuaGFzaDtcbiAgICAgICAgaWYgKGZ1bGxQYXRoLnN0YXJ0c1dpdGgoXCIvXCIpICYmIGZ1bGxQYXRoICE9PSBcIi9cIikge1xuICAgICAgICAgIHBhdGggPSBmdWxsUGF0aDtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIG5vb3BcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBpZiAoIW9yaWdpbikge1xuICAgIGlmIChwcm9jZXNzLmVudi5OT0RFX0VOViA9PT0gXCJkZXZlbG9wbWVudFwiKSB7XG4gICAgICBvcmlnaW4gPSBgaHR0cDovL2xvY2FsaG9zdDoke1xuICAgICAgICBwcm9jZXNzLmVudi5QT1JUID8/IHByb2Nlc3MuZW52Lk5FWFRfUFVCTElDX1BPUlQgPz8gMzAwMFxuICAgICAgfWA7XG4gICAgfVxuICAgIGNvbnN0IHZlcmNlbFVybCA9XG4gICAgICBwcm9jZXNzLmVudi5WRVJDRUxfVVJMID8/IHByb2Nlc3MuZW52Lk5FWFRfUFVCTElDX1ZFUkNFTF9VUkw7XG4gICAgaWYgKHZlcmNlbFVybCkge1xuICAgICAgb3JpZ2luID0gYGh0dHBzOi8vJHt2ZXJjZWxVcmx9YDtcbiAgICB9XG4gIH1cblxuICBpZiAoIW9yaWdpbikge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIFwiW2FnZW50XSBDb3VsZG4ndCBkZXRlcm1pbmUgQVBJIG9yaWdpbiAobm8gb3JpZ2luIGRldGVjdGVkIGluIGBhcGlgIG9wdGlvbiBhbmQgbm8gVkVSQ0VMX1VSTCBzZXQpXCJcbiAgICApO1xuICB9XG5cbiAgcmV0dXJuIGAke29yaWdpbn0ke3BhdGh9YDtcbn1cbiIsICJpbXBvcnQgeyB0eXBlIFRvb2xTZXQsIHRvb2wgfSBmcm9tIFwiYWlcIjtcbmltcG9ydCB7IHogfSBmcm9tIFwiem9kXCI7XG5pbXBvcnQgdHlwZSB7IFNhbmRib3ggfSBmcm9tIFwiLi4vc2FuZGJveFwiO1xuaW1wb3J0IHR5cGUgeyBTZXNzaW9uIH0gZnJvbSBcIi4uL3N0b3JhZ2VcIjtcbmltcG9ydCB7IGJ1aWx0SW5Ub29scyB9IGZyb20gXCIuXCI7XG5cbmV4cG9ydCBjb25zdCBKQVZBU0NSSVBUX1RPT0xfTkFNRSA9IFwiSmF2YVNjcmlwdFwiO1xuXG5leHBvcnQgdHlwZSBTdWJUb29sQ2FsbFJlc3VsdCA9IHsgcmVzdWx0PzogdW5rbm93bjsgZXJyb3I/OiBzdHJpbmcgfTtcbmV4cG9ydCB0eXBlIE9uU3ViVG9vbENhbGwgPSAoXG4gIHRvb2xOYW1lOiBzdHJpbmcsXG4gIGlucHV0OiB1bmtub3duLFxuICBleGVjdXRlOiAoKSA9PiBQcm9taXNlPHVua25vd24+XG4pID0+IFByb21pc2U8U3ViVG9vbENhbGxSZXN1bHQ+O1xuXG5jb25zdCBSRVFVRVNUX01BUktFUl9TVEFSVCA9IFwiX19UT09MX1JFUVVFU1RfX1wiO1xuY29uc3QgUkVRVUVTVF9NQVJLRVJfRU5EID0gXCJfX1RPT0xfUkVRVUVTVF9FTkRfX1wiO1xuY29uc3QgRVhFQ1VUSU9OX1RJTUVPVVRfTVMgPSA1ICogNjAgKiAxMDAwO1xuXG4vKipcbiAqIFRoZSBydW5uZXIgc2NyaXB0IGlzIHdyaXR0ZW4gdG8gdGhlIHNhbmRib3ggYW5kIGV4ZWN1dGVkIHZpYSBOb2RlLmpzLlxuICogSXQgcmVhZHMgdGhlIG1vZGVsJ3MgY29kZSBmcm9tIGNvZGUuanMsIHNldHMgdXAgY3R4LnRvb2xzIGFzIFJQQyBwcm94aWVzXG4gKiAocmVxdWVzdHMgc2VudCB2aWEgc3RkZXJyIG1hcmtlcnMsIHJlc3BvbnNlcyBwb2xsZWQgZnJvbSBmaWxlcyksIGV4ZWN1dGVzXG4gKiB0aGUgY29kZSwgYW5kIHdyaXRlcyB0aGUgcmVzdWx0IHRvIHN0ZG91dCBhcyBKU09OLlxuICovXG5jb25zdCBSVU5ORVJfU0NSSVBUID0gYFxuaW1wb3J0IHsgcmVhZEZpbGVTeW5jLCBleGlzdHNTeW5jLCB1bmxpbmtTeW5jLCBta2RpclN5bmMgfSBmcm9tICdub2RlOmZzJztcbmltcG9ydCB7IGpvaW4sIGRpcm5hbWUgfSBmcm9tICdub2RlOnBhdGgnO1xuaW1wb3J0IHsgZmlsZVVSTFRvUGF0aCB9IGZyb20gJ25vZGU6dXJsJztcblxuY29uc3QgU0NSSVBUX0RJUiA9IGRpcm5hbWUoZmlsZVVSTFRvUGF0aChpbXBvcnQubWV0YS51cmwpKTtcbmNvbnN0IFRPT0xfQ0FMTF9USU1FT1VUX01TID0gMzAwXzAwMDtcblxubGV0IHJlcUNvdW50ZXIgPSAwO1xuXG5hc3luYyBmdW5jdGlvbiBjYWxsVG9vbChuYW1lLCBpbnB1dCkge1xuICBjb25zdCBpZCA9ICdyZXFfJyArICgrK3JlcUNvdW50ZXIpICsgJ18nICsgRGF0ZS5ub3coKTtcbiAgY29uc3QgcmVzcG9uc2VGaWxlID0gam9pbihTQ1JJUFRfRElSLCBpZCArICcucmVzcG9uc2UuanNvbicpO1xuXG4gIGNvbnN0IHJlcXVlc3QgPSBKU09OLnN0cmluZ2lmeSh7IGlkLCB0b29sOiBuYW1lLCBpbnB1dCB9KTtcbiAgcHJvY2Vzcy5zdGRlcnIud3JpdGUoJyR7UkVRVUVTVF9NQVJLRVJfU1RBUlR9JyArIHJlcXVlc3QgKyAnJHtSRVFVRVNUX01BUktFUl9FTkR9JyArICdcXFxcbicpO1xuXG4gIGNvbnN0IHN0YXJ0ID0gRGF0ZS5ub3coKTtcbiAgd2hpbGUgKCFleGlzdHNTeW5jKHJlc3BvbnNlRmlsZSkpIHtcbiAgICBpZiAoRGF0ZS5ub3coKSAtIHN0YXJ0ID4gVE9PTF9DQUxMX1RJTUVPVVRfTVMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVG9vbCBjYWxsICcgKyBuYW1lICsgJyB0aW1lZCBvdXQgd2FpdGluZyBmb3IgcmVzcG9uc2UnKTtcbiAgICB9XG4gICAgYXdhaXQgbmV3IFByb21pc2UociA9PiBzZXRUaW1lb3V0KHIsIDMwKSk7XG4gIH1cblxuICBsZXQgcmF3O1xuICB0cnkge1xuICAgIHJhdyA9IHJlYWRGaWxlU3luYyhyZXNwb25zZUZpbGUsICd1dGY4Jyk7XG4gIH0gY2F0Y2gge1xuICAgIGF3YWl0IG5ldyBQcm9taXNlKHIgPT4gc2V0VGltZW91dChyLCA1MCkpO1xuICAgIHJhdyA9IHJlYWRGaWxlU3luYyhyZXNwb25zZUZpbGUsICd1dGY4Jyk7XG4gIH1cblxuICBjb25zdCByZXNwb25zZSA9IEpTT04ucGFyc2UocmF3KTtcbiAgdHJ5IHsgdW5saW5rU3luYyhyZXNwb25zZUZpbGUpOyB9IGNhdGNoIHt9XG5cbiAgaWYgKHJlc3BvbnNlLmVycm9yKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKHJlc3BvbnNlLmVycm9yKTtcbiAgfVxuICByZXR1cm4gcmVzcG9uc2UucmVzdWx0O1xufVxuXG5jb25zdCBjb2RlID0gcmVhZEZpbGVTeW5jKGpvaW4oU0NSSVBUX0RJUiwgJ2NvZGUuanMnKSwgJ3V0ZjgnKTtcbmNvbnN0IHRvb2xOYW1lcyA9IEpTT04ucGFyc2UocmVhZEZpbGVTeW5jKGpvaW4oU0NSSVBUX0RJUiwgJ3Rvb2xzLmpzb24nKSwgJ3V0ZjgnKSk7XG5cbmNvbnN0IGN0eCA9IHsgdG9vbHM6IHt9IH07XG5mb3IgKGNvbnN0IG5hbWUgb2YgdG9vbE5hbWVzKSB7XG4gIGN0eC50b29sc1tuYW1lXSA9IChpbnB1dCkgPT4gY2FsbFRvb2wobmFtZSwgaW5wdXQpO1xufVxuXG5jb25zdCBsb2dzID0gW107XG5jb25zdCBjdXN0b21Db25zb2xlID0ge1xuICBsb2c6ICguLi5hcmdzKSA9PiBsb2dzLnB1c2goYXJncy5tYXAoYSA9PiB0eXBlb2YgYSA9PT0gJ3N0cmluZycgPyBhIDogSlNPTi5zdHJpbmdpZnkoYSkpLmpvaW4oJyAnKSksXG4gIGVycm9yOiAoLi4uYXJncykgPT4gbG9ncy5wdXNoKCdbZXJyb3JdICcgKyBhcmdzLm1hcChhID0+IHR5cGVvZiBhID09PSAnc3RyaW5nJyA/IGEgOiBKU09OLnN0cmluZ2lmeShhKSkuam9pbignICcpKSxcbiAgd2FybjogKC4uLmFyZ3MpID0+IGxvZ3MucHVzaCgnW3dhcm5dICcgKyBhcmdzLm1hcChhID0+IHR5cGVvZiBhID09PSAnc3RyaW5nJyA/IGEgOiBKU09OLnN0cmluZ2lmeShhKSkuam9pbignICcpKSxcbn07XG5cbnRyeSB7XG4gIGNvbnN0IEFzeW5jRnVuY3Rpb24gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YoYXN5bmMgZnVuY3Rpb24oKSB7fSkuY29uc3RydWN0b3I7XG4gIGNvbnN0IGZuID0gbmV3IEFzeW5jRnVuY3Rpb24oJ2N0eCcsICdjb25zb2xlJywgY29kZSk7XG4gIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGZuKGN0eCwgY3VzdG9tQ29uc29sZSk7XG5cbiAgY29uc3Qgb3V0cHV0ID0geyBzdWNjZXNzOiB0cnVlLCByZXN1bHQ6IHJlc3VsdCAhPT0gdW5kZWZpbmVkID8gcmVzdWx0IDogbnVsbCB9O1xuICBpZiAobG9ncy5sZW5ndGggPiAwKSBvdXRwdXQubG9ncyA9IGxvZ3M7XG4gIHByb2Nlc3Muc3Rkb3V0LndyaXRlKEpTT04uc3RyaW5naWZ5KG91dHB1dCkpO1xufSBjYXRjaCAoZXJyKSB7XG4gIGNvbnN0IG91dHB1dCA9IHtcbiAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICBlcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSArICdcXFxcbicgKyBlcnIuc3RhY2sgOiBTdHJpbmcoZXJyKSxcbiAgfTtcbiAgaWYgKGxvZ3MubGVuZ3RoID4gMCkgb3V0cHV0LmxvZ3MgPSBsb2dzO1xuICBwcm9jZXNzLnN0ZG91dC53cml0ZShKU09OLnN0cmluZ2lmeShvdXRwdXQpKTtcbn1cbmA7XG5cbi8qKlxuICogRXh0cmFjdHMgYSBwbGFpbiBKU09OIFNjaGVtYSBmcm9tIHdoYXRldmVyIGZvcm1hdCB0aGUgQUkgU0RLIHRvb2wgdXNlc1xuICogKFpvZCBzY2hlbWEsIEFJIFNESyB3cmFwcGVkIHNjaGVtYSwgb3IgcmF3IEpTT04gU2NoZW1hKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4dHJhY3RKc29uU2NoZW1hKFxuICBzY2hlbWE6IHVua25vd25cbik6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgbnVsbCB7XG4gIGlmICghc2NoZW1hIHx8IHR5cGVvZiBzY2hlbWEgIT09IFwib2JqZWN0XCIpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGlmIChcbiAgICBcIl9kZWZcIiBpbiBzY2hlbWEgJiZcbiAgICB0eXBlb2YgKHNjaGVtYSBhcyB7IF9kZWY6IHVua25vd24gfSkuX2RlZiA9PT0gXCJvYmplY3RcIlxuICApIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIHoudG9KU09OU2NoZW1hKHNjaGVtYSBhcyB6LlpvZFR5cGUpIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgY29uc3QgcyA9IHNjaGVtYSBhcyBSZWNvcmQ8c3RyaW5nIHwgc3ltYm9sLCB1bmtub3duPjtcbiAgaWYgKFN5bWJvbC5mb3IoXCJ2ZXJjZWwuYWkuc2NoZW1hXCIpIGluIHMgJiYgXCJqc29uU2NoZW1hXCIgaW4gcykge1xuICAgIHJldHVybiBzLmpzb25TY2hlbWEgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIH1cblxuICBpZiAoXCJ0eXBlXCIgaW4gcyB8fCBcInByb3BlcnRpZXNcIiBpbiBzKSB7XG4gICAgcmV0dXJuIHMgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIH1cblxuICByZXR1cm4gbnVsbDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGpzb25TY2hlbWFUb1RzKFxuICBzY2hlbWE6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICBpbmRlbnQgPSAwXG4pOiBzdHJpbmcge1xuICBpZiAoIXNjaGVtYSkge1xuICAgIHJldHVybiBcInVua25vd25cIjtcbiAgfVxuXG4gIGlmIChzY2hlbWEuZW51bSAmJiBBcnJheS5pc0FycmF5KHNjaGVtYS5lbnVtKSkge1xuICAgIHJldHVybiBzY2hlbWEuZW51bS5tYXAoKHYpID0+IEpTT04uc3RyaW5naWZ5KHYpKS5qb2luKFwiIHwgXCIpO1xuICB9XG5cbiAgaWYgKHNjaGVtYS5hbnlPZiAmJiBBcnJheS5pc0FycmF5KHNjaGVtYS5hbnlPZikpIHtcbiAgICByZXR1cm4gc2NoZW1hLmFueU9mXG4gICAgICAubWFwKChzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikgPT4ganNvblNjaGVtYVRvVHMocywgaW5kZW50KSlcbiAgICAgIC5qb2luKFwiIHwgXCIpO1xuICB9XG4gIGlmIChzY2hlbWEub25lT2YgJiYgQXJyYXkuaXNBcnJheShzY2hlbWEub25lT2YpKSB7XG4gICAgcmV0dXJuIHNjaGVtYS5vbmVPZlxuICAgICAgLm1hcCgoczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pID0+IGpzb25TY2hlbWFUb1RzKHMsIGluZGVudCkpXG4gICAgICAuam9pbihcIiB8IFwiKTtcbiAgfVxuXG4gIGNvbnN0IHR5cGUgPSBzY2hlbWEudHlwZSBhcyBzdHJpbmc7XG5cbiAgc3dpdGNoICh0eXBlKSB7XG4gICAgY2FzZSBcInN0cmluZ1wiOlxuICAgICAgcmV0dXJuIFwic3RyaW5nXCI7XG4gICAgY2FzZSBcIm51bWJlclwiOlxuICAgIGNhc2UgXCJpbnRlZ2VyXCI6XG4gICAgICByZXR1cm4gXCJudW1iZXJcIjtcbiAgICBjYXNlIFwiYm9vbGVhblwiOlxuICAgICAgcmV0dXJuIFwiYm9vbGVhblwiO1xuICAgIGNhc2UgXCJudWxsXCI6XG4gICAgICByZXR1cm4gXCJudWxsXCI7XG4gICAgY2FzZSBcImFycmF5XCI6IHtcbiAgICAgIGNvbnN0IGl0ZW1zID0gc2NoZW1hLml0ZW1zXG4gICAgICAgID8ganNvblNjaGVtYVRvVHMoc2NoZW1hLml0ZW1zIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+LCBpbmRlbnQpXG4gICAgICAgIDogXCJ1bmtub3duXCI7XG4gICAgICByZXR1cm4gYEFycmF5PCR7aXRlbXN9PmA7XG4gICAgfVxuICAgIGNhc2UgXCJvYmplY3RcIjoge1xuICAgICAgY29uc3QgcHJvcGVydGllcyA9IHNjaGVtYS5wcm9wZXJ0aWVzIGFzXG4gICAgICAgIHwgUmVjb3JkPHN0cmluZywgUmVjb3JkPHN0cmluZywgdW5rbm93bj4+XG4gICAgICAgIHwgdW5kZWZpbmVkO1xuICAgICAgaWYgKCFwcm9wZXJ0aWVzKSB7XG4gICAgICAgIHJldHVybiBcIlJlY29yZDxzdHJpbmcsIHVua25vd24+XCI7XG4gICAgICB9XG4gICAgICBjb25zdCByZXF1aXJlZCA9IG5ldyBTZXQoKHNjaGVtYS5yZXF1aXJlZCBhcyBzdHJpbmdbXSkgfHwgW10pO1xuICAgICAgY29uc3QgcGFkID0gXCIgIFwiLnJlcGVhdChpbmRlbnQgKyAxKTtcbiAgICAgIGNvbnN0IGNsb3NlUGFkID0gXCIgIFwiLnJlcGVhdChpbmRlbnQpO1xuICAgICAgY29uc3QgcHJvcHMgPSBPYmplY3QuZW50cmllcyhwcm9wZXJ0aWVzKS5tYXAoKFtrZXksIHZhbHVlXSkgPT4ge1xuICAgICAgICBjb25zdCBvcHQgPSByZXF1aXJlZC5oYXMoa2V5KSA/IFwiXCIgOiBcIj9cIjtcbiAgICAgICAgcmV0dXJuIGAke3BhZH0ke2tleX0ke29wdH06ICR7anNvblNjaGVtYVRvVHModmFsdWUsIGluZGVudCArIDEpfWA7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBge1xcbiR7cHJvcHMuam9pbihcIjtcXG5cIil9O1xcbiR7Y2xvc2VQYWR9fWA7XG4gICAgfVxuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gXCJ1bmtub3duXCI7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdlbmVyYXRlQ29udGV4dFR5cGVTdHJpbmcodG9vbHM6IFRvb2xTZXQpOiBzdHJpbmcge1xuICBjb25zdCBzaWdzOiBzdHJpbmdbXSA9IFtdO1xuXG4gIGZvciAoY29uc3QgW25hbWUsIHRdIG9mIE9iamVjdC5lbnRyaWVzKHRvb2xzKSkge1xuICAgIGNvbnN0IHJhdyA9IHQgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgY29uc3QgaW5wdXRTY2hlbWEgPSBleHRyYWN0SnNvblNjaGVtYShyYXcuaW5wdXRTY2hlbWEgPz8gcmF3LnBhcmFtZXRlcnMpO1xuICAgIGNvbnN0IG91dHB1dFNjaGVtYSA9IGV4dHJhY3RKc29uU2NoZW1hKHJhdy5vdXRwdXRTY2hlbWEpO1xuXG4gICAgY29uc3QgaW5wdXRUeXBlID0gaW5wdXRTY2hlbWEgPyBqc29uU2NoZW1hVG9UcyhpbnB1dFNjaGVtYSwgMikgOiBcInt9XCI7XG4gICAgY29uc3Qgb3V0cHV0VHlwZSA9IG91dHB1dFNjaGVtYVxuICAgICAgPyBqc29uU2NoZW1hVG9UcyhvdXRwdXRTY2hlbWEsIDIpXG4gICAgICA6IFwidW5rbm93blwiO1xuXG4gICAgc2lncy5wdXNoKGAgICAgJHtuYW1lfShpbnB1dDogJHtpbnB1dFR5cGV9KTogUHJvbWlzZTwke291dHB1dFR5cGV9PmApO1xuICB9XG5cbiAgcmV0dXJuIGB0eXBlIENvbnRleHQgPSB7XFxuICB0b29sczoge1xcbiR7c2lncy5qb2luKFwiO1xcblwiKX07XFxuICB9XFxufWA7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGV4ZWN1dGVJblNhbmRib3goe1xuICBjb2RlLFxuICBycGNEaXIsXG4gIGFib3J0Q29udHJvbGxlcixcbiAgc2FuZGJveCxcbiAgYXZhaWxhYmxlVG9vbHMsXG4gIG9uU3ViVG9vbENhbGwsXG59OiB7XG4gIGNvZGU6IHN0cmluZztcbiAgcnBjRGlyOiBzdHJpbmc7XG4gIGFib3J0Q29udHJvbGxlcjogQWJvcnRDb250cm9sbGVyO1xuICBzYW5kYm94OiBTYW5kYm94O1xuICBhdmFpbGFibGVUb29sczogVG9vbFNldDtcbiAgb25TdWJUb29sQ2FsbD86IE9uU3ViVG9vbENhbGw7XG59KTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4ge1xuICBjb25zdCBta2RpclJlc3VsdCA9IGF3YWl0IHNhbmRib3guZXhlYyh7XG4gICAgY29tbWFuZDogXCJta2RpclwiLFxuICAgIGFyZ3M6IFtcIi1wXCIsIHJwY0Rpcl0sXG4gIH0pO1xuICBpZiAobWtkaXJSZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgIHJldHVybiB7IHN1Y2Nlc3M6IGZhbHNlLCBlcnJvcjogbWtkaXJSZXN1bHQubWVzc2FnZSB9O1xuICB9XG4gIGF3YWl0IG1rZGlyUmVzdWx0LnJlc3VsdDtcblxuICBhd2FpdCBzYW5kYm94LndyaXRlRmlsZXMoe1xuICAgIGZpbGVzOiBbXG4gICAgICB7IHBhdGg6IFwicnVubmVyLm1qc1wiLCBjb250ZW50OiBSVU5ORVJfU0NSSVBUIH0sXG4gICAgICB7IHBhdGg6IFwiY29kZS5qc1wiLCBjb250ZW50OiBjb2RlIH0sXG4gICAgICB7XG4gICAgICAgIHBhdGg6IFwidG9vbHMuanNvblwiLFxuICAgICAgICBjb250ZW50OiBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyhhdmFpbGFibGVUb29scykpLFxuICAgICAgfSxcbiAgICBdLFxuICAgIGRlc3RQYXRoOiBycGNEaXIsXG4gIH0pO1xuXG4gIGNvbnN0IG5vZGVNYWpvciA9IE51bWJlci5wYXJzZUludChwcm9jZXNzLnZlcnNpb25zLm5vZGUuc3BsaXQoXCIuXCIpWzBdLCAxMCk7XG4gIGNvbnN0IHBlcm1pc3Npb25GbGFnID1cbiAgICBub2RlTWFqb3IgPj0gMjIgPyBcIi0tcGVybWlzc2lvblwiIDogXCItLWV4cGVyaW1lbnRhbC1wZXJtaXNzaW9uXCI7XG5cbiAgY29uc3QgZXhlY1Jlc3VsdCA9IGF3YWl0IHNhbmRib3guZXhlYyh7XG4gICAgY29tbWFuZDogXCJub2RlXCIsXG4gICAgYXJnczogW1xuICAgICAgcGVybWlzc2lvbkZsYWcsXG4gICAgICBgLS1hbGxvdy1mcy1yZWFkPSR7cnBjRGlyfWAsXG4gICAgICBgLS1hbGxvdy1mcy13cml0ZT0ke3JwY0Rpcn1gLFxuICAgICAgYCR7cnBjRGlyfS9ydW5uZXIubWpzYCxcbiAgICBdLFxuICAgIHNpZ25hbDogYWJvcnRDb250cm9sbGVyLnNpZ25hbCxcbiAgfSk7XG5cbiAgaWYgKGV4ZWNSZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgIHJldHVybiB7IHN1Y2Nlc3M6IGZhbHNlLCBlcnJvcjogZXhlY1Jlc3VsdC5tZXNzYWdlIH07XG4gIH1cblxuICBjb25zdCBmYXRhbDogeyBlcnJvcjogRXJyb3IgfCBudWxsIH0gPSB7IGVycm9yOiBudWxsIH07XG5cbiAgY29uc3QgYWJvcnQgPSAoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgaWYgKCFmYXRhbC5lcnJvcikge1xuICAgICAgZmF0YWwuZXJyb3IgPSBlcnJvcjtcbiAgICAgIGFib3J0Q29udHJvbGxlci5hYm9ydCgpO1xuICAgIH1cbiAgfTtcblxuICBjb25zdCBoYW5kbGVUb29sUmVxdWVzdCA9IGFzeW5jIChyZXF1ZXN0SnNvbjogc3RyaW5nKSA9PiB7XG4gICAgbGV0IHBhcnNlZDogeyBpZDogc3RyaW5nOyB0b29sOiBzdHJpbmc7IGlucHV0OiB1bmtub3duIH07XG4gICAgdHJ5IHtcbiAgICAgIHBhcnNlZCA9IEpTT04ucGFyc2UocmVxdWVzdEpzb24pO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHsgaWQsIHRvb2w6IHRvb2xOYW1lLCBpbnB1dCB9ID0gcGFyc2VkO1xuXG4gICAgbGV0IHJlc3BvbnNlOiB7IHJlc3VsdD86IHVua25vd247IGVycm9yPzogc3RyaW5nIH07XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHQgPSBhdmFpbGFibGVUb29sc1t0b29sTmFtZV07XG4gICAgICBpZiAoIXQ/LmV4ZWN1dGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBUb29sICR7dG9vbE5hbWV9IG5vdCBmb3VuZCBvciBoYXMgbm8gZXhlY3V0ZSBmdW5jdGlvbmBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGV4ZWMgPSB0LmV4ZWN1dGUuYmluZCh0KTtcbiAgICAgIGlmIChvblN1YlRvb2xDYWxsKSB7XG4gICAgICAgIHJlc3BvbnNlID0gYXdhaXQgb25TdWJUb29sQ2FsbCh0b29sTmFtZSwgaW5wdXQsICgpID0+XG4gICAgICAgICAgZXhlYyhpbnB1dCwge1xuICAgICAgICAgICAgdG9vbENhbGxJZDogYGpzXyR7dG9vbE5hbWV9XyR7RGF0ZS5ub3coKX1gLFxuICAgICAgICAgICAgbWVzc2FnZXM6IFtdLFxuICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBleGVjKGlucHV0LCB7XG4gICAgICAgICAgdG9vbENhbGxJZDogYGpzXyR7dG9vbE5hbWV9XyR7RGF0ZS5ub3coKX1gLFxuICAgICAgICAgIG1lc3NhZ2VzOiBbXSxcbiAgICAgICAgfSk7XG4gICAgICAgIHJlc3BvbnNlID0geyByZXN1bHQgfTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGNvbnN0IG1zZyA9IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKTtcbiAgICAgIHJlc3BvbnNlID0geyBlcnJvcjogbXNnIH07XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHNhbmRib3gud3JpdGVGaWxlcyh7XG4gICAgICAgIGZpbGVzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgcGF0aDogYCR7aWR9LnJlc3BvbnNlLmpzb25gLFxuICAgICAgICAgICAgY29udGVudDogSlNPTi5zdHJpbmdpZnkocmVzcG9uc2UpLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICAgIGRlc3RQYXRoOiBycGNEaXIsXG4gICAgICB9KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIC8qKlxuICAgICAgICogSWYgd3JpdGluZyB0aGUgcmVzcG9uc2UgZmlsZSBmYWlscywgdGhlIHJ1bm5lciB3aWxsIHBvbGwgZm9yZXZlclxuICAgICAgICogd2FpdGluZyBmb3IgaXQuIEFib3J0IHRoZSBydW5uZXIgcHJvY2VzcyBzbyB3ZSBkb24ndCBkZWFkbG9jay5cbiAgICAgICAqL1xuICAgICAgY29uc3QgbXNnID0gZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpO1xuICAgICAgYWJvcnQobmV3IEVycm9yKGBGYWlsZWQgdG8gd3JpdGUgUlBDIHJlc3BvbnNlIGZvciAke3Rvb2xOYW1lfTogJHttc2d9YCkpO1xuICAgIH1cbiAgfTtcblxuICBjb25zdCB0b29sQ2FsbFByb21pc2VzOiBQcm9taXNlPHZvaWQ+W10gPSBbXTtcbiAgbGV0IHN0ZGVyckJ1ZmZlciA9IFwiXCI7XG4gIGxldCBub25NYXJrZXJTdGRlcnIgPSBcIlwiO1xuXG4gIGNvbnN0IHRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICBhYm9ydChcbiAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgYEphdmFTY3JpcHQgZXhlY3V0aW9uIHRpbWVkIG91dCBhZnRlciAke0VYRUNVVElPTl9USU1FT1VUX01TIC8gMTAwMH1zYFxuICAgICAgKVxuICAgICk7XG4gIH0sIEVYRUNVVElPTl9USU1FT1VUX01TKTtcblxuICB0cnkge1xuICAgIGZvciBhd2FpdCAoY29uc3QgZW50cnkgb2YgZXhlY1Jlc3VsdC5sb2dzKCkpIHtcbiAgICAgIGlmIChmYXRhbC5lcnJvcikge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgaWYgKGVudHJ5LnN0cmVhbSA9PT0gXCJzdGRlcnJcIikge1xuICAgICAgICBzdGRlcnJCdWZmZXIgKz0gZW50cnkuZGF0YTtcblxuICAgICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICAgIGNvbnN0IHN0YXJ0SWR4ID0gc3RkZXJyQnVmZmVyLmluZGV4T2YoUkVRVUVTVF9NQVJLRVJfU1RBUlQpO1xuICAgICAgICAgIGlmIChzdGFydElkeCA9PT0gLTEpIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IGJlZm9yZU1hcmtlciA9IHN0ZGVyckJ1ZmZlci5zbGljZSgwLCBzdGFydElkeCk7XG4gICAgICAgICAgaWYgKGJlZm9yZU1hcmtlci50cmltKCkpIHtcbiAgICAgICAgICAgIG5vbk1hcmtlclN0ZGVyciArPSBiZWZvcmVNYXJrZXI7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgY29udGVudFN0YXJ0ID0gc3RhcnRJZHggKyBSRVFVRVNUX01BUktFUl9TVEFSVC5sZW5ndGg7XG4gICAgICAgICAgY29uc3QgZW5kSWR4ID0gc3RkZXJyQnVmZmVyLmluZGV4T2YoUkVRVUVTVF9NQVJLRVJfRU5ELCBjb250ZW50U3RhcnQpO1xuICAgICAgICAgIGlmIChlbmRJZHggPT09IC0xKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCByZXF1ZXN0SnNvbiA9IHN0ZGVyckJ1ZmZlci5zbGljZShjb250ZW50U3RhcnQsIGVuZElkeCk7XG4gICAgICAgICAgc3RkZXJyQnVmZmVyID0gc3RkZXJyQnVmZmVyLnNsaWNlKGVuZElkeCArIFJFUVVFU1RfTUFSS0VSX0VORC5sZW5ndGgpO1xuXG4gICAgICAgICAgdG9vbENhbGxQcm9taXNlcy5wdXNoKGhhbmRsZVRvb2xSZXF1ZXN0KHJlcXVlc3RKc29uKSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH0gZmluYWxseSB7XG4gICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuICB9XG5cbiAgaWYgKHN0ZGVyckJ1ZmZlci50cmltKCkpIHtcbiAgICBub25NYXJrZXJTdGRlcnIgKz0gc3RkZXJyQnVmZmVyO1xuICB9XG5cbiAgYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKHRvb2xDYWxsUHJvbWlzZXMpO1xuXG4gIGlmIChmYXRhbC5lcnJvcikge1xuICAgIGV4ZWNSZXN1bHQucmVzdWx0LmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgZXJyb3I6IGZhdGFsLmVycm9yLm1lc3NhZ2UsXG4gICAgICAuLi4obm9uTWFya2VyU3RkZXJyID8geyBzdGRlcnI6IG5vbk1hcmtlclN0ZGVyci5zbGljZSgwLCAyMDAwKSB9IDoge30pLFxuICAgIH07XG4gIH1cblxuICBjb25zdCB7IHN0ZG91dCwgc3RkZXJyLCBleGl0Q29kZSB9ID0gYXdhaXQgZXhlY1Jlc3VsdC5yZXN1bHQ7XG5cbiAgdHJ5IHtcbiAgICByZXR1cm4gSlNPTi5wYXJzZShzdGRvdXQpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4ge1xuICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICBlcnJvcjogYFJ1bm5lciBmYWlsZWQgKGV4aXQgJHtleGl0Q29kZX0pLmAsXG4gICAgICBzdGRlcnI6IChub25NYXJrZXJTdGRlcnIgKyBzdGRlcnIpLnNsaWNlKDAsIDIwMDApLFxuICAgICAgc3Rkb3V0OiBzdGRvdXQuc2xpY2UoMCwgMTAwMCksXG4gICAgfTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlSmF2YVNjcmlwdFRvb2wob3B0czoge1xuICB0b29sczogVG9vbFNldDtcbiAgc2Vzc2lvbjogU2Vzc2lvbjtcbiAgc2FuZGJveDogU2FuZGJveDtcbiAgb25TdWJUb29sQ2FsbD86IE9uU3ViVG9vbENhbGw7XG59KSB7XG4gIGNvbnN0IHsgc2Vzc2lvbiwgc2FuZGJveCwgb25TdWJUb29sQ2FsbCB9ID0gb3B0cztcbiAgY29uc3QgYWN0aXZlU2V0ID0gc2Vzc2lvbi5hY3RpdmVUb29scyA/IG5ldyBTZXQoc2Vzc2lvbi5hY3RpdmVUb29scykgOiBudWxsO1xuICBjb25zdCBhdmFpbGFibGVUb29sczogVG9vbFNldCA9IHt9O1xuICBmb3IgKGNvbnN0IFtuYW1lLCB0XSBvZiBPYmplY3QuZW50cmllcyhvcHRzLnRvb2xzKSkge1xuICAgIGlmICghYWN0aXZlU2V0IHx8IGFjdGl2ZVNldC5oYXMobmFtZSkpIHtcbiAgICAgIGF2YWlsYWJsZVRvb2xzW25hbWVdID0gdDtcbiAgICB9XG4gIH1cbiAgY29uc3QgY29udGV4dFR5cGUgPSBnZW5lcmF0ZUNvbnRleHRUeXBlU3RyaW5nKGF2YWlsYWJsZVRvb2xzKTtcblxuICByZXR1cm4gdG9vbCh7XG4gICAgLi4uYnVpbHRJblRvb2xzLkphdmFTY3JpcHQsXG4gICAgZGVzY3JpcHRpb246IGBFeGVjdXRlIEphdmFTY3JpcHQgdG8gb3JjaGVzdHJhdGUgbXVsdGlwbGUgdG9vbCBjYWxscyBpbiBhIHNpbmdsZSBzdGVwLiBVc2UgdGhpcyB3aGVuIHlvdSBuZWVkIHRvIHJ1biBzZXZlcmFsIHRvb2xzIGluIHNlcXVlbmNlLCB0cmFuc2Zvcm0gaW50ZXJtZWRpYXRlIHJlc3VsdHMsIG9yIHBhcmFsbGVsaXplIGluZGVwZW5kZW50IG9wZXJhdGlvbnMgd2l0aCBQcm9taXNlLmFsbC5cblxuVGhlIGNvZGUgcnVucyBhcyBhbiBhc3luYyBmdW5jdGlvbiBib2R5IHdpdGggXFxgY3R4XFxgIGluIHNjb3BlOlxuXG5cXGBcXGBcXGB0eXBlc2NyaXB0XG4ke2NvbnRleHRUeXBlfVxuXFxgXFxgXFxgXG5cbkV4YW1wbGVzOlxuLSBTZXF1ZW50aWFsOiBcXGBjb25zdCBmaWxlID0gYXdhaXQgY3R4LnRvb2xzLlJlYWQoeyBwYXRoOiBcInBhY2thZ2UuanNvblwiIH0pOyByZXR1cm4gSlNPTi5wYXJzZShmaWxlLmNvbnRlbnQpO1xcYFxuLSBQYXJhbGxlbDogXFxgY29uc3QgW2EsIGJdID0gYXdhaXQgUHJvbWlzZS5hbGwoW2N0eC50b29scy5SZWFkKHsgcGF0aDogXCJhLnRzXCIgfSksIGN0eC50b29scy5SZWFkKHsgcGF0aDogXCJiLnRzXCIgfSldKTsgcmV0dXJuIHsgYTogYS5jb250ZW50LCBiOiBiLmNvbnRlbnQgfTtcXGBcbi0gVHJhbnNmb3JtOiBcXGBjb25zdCBncmVwID0gYXdhaXQgY3R4LnRvb2xzLkdyZXAoeyBwYXR0ZXJuOiBcIlRPRE9cIiB9KTsgcmV0dXJuIGdyZXAubWF0Y2hlcy5zcGxpdChcIlxcXFxuXCIpLmxlbmd0aDtcXGBcblxuUmV0dXJuIGEgdmFsdWUgdG8gcGFzcyByZXN1bHRzIGJhY2suIFVzZSBjb25zb2xlLmxvZygpIGZvciBkZWJ1ZyBvdXRwdXQuYCxcbiAgICBleGVjdXRlOiAoeyBjb2RlIH0pID0+IHtcbiAgICAgIGNvbnN0IHJ1bklkID0gYHJ1bl8ke0RhdGUubm93KCl9XyR7TWF0aC5yYW5kb20oKVxuICAgICAgICAudG9TdHJpbmcoMzYpXG4gICAgICAgIC5zbGljZSgyLCA4KX1gO1xuICAgICAgY29uc3QgcnBjRGlyID0gYC5hZ2VudC9qcy1ycGMvJHtydW5JZH1gO1xuICAgICAgY29uc3QgYWJvcnRDb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuXG4gICAgICByZXR1cm4gZXhlY3V0ZUluU2FuZGJveCh7XG4gICAgICAgIGNvZGUsXG4gICAgICAgIHJwY0RpcixcbiAgICAgICAgYWJvcnRDb250cm9sbGVyLFxuICAgICAgICBzYW5kYm94LFxuICAgICAgICBhdmFpbGFibGVUb29scyxcbiAgICAgICAgb25TdWJUb29sQ2FsbCxcbiAgICAgIH0pO1xuICAgIH0sXG4gIH0pO1xufVxuIiwgImltcG9ydCB0eXBlIHsgSlNPTlZhbHVlLCBNb2RlbE1lc3NhZ2UgfSBmcm9tIFwiYWlcIjtcblxudHlwZSBQcm92aWRlck9wdGlvbnMgPSBSZWNvcmQ8c3RyaW5nLCBSZWNvcmQ8c3RyaW5nLCBKU09OVmFsdWU+PjtcblxuY29uc3QgQU5USFJPUElDX01BWF9DQUNIRV9CUkVBS1BPSU5UU19QRVJfUkVRVUVTVCA9IDQ7XG5cbmNvbnN0IENMQVVERV9MSUtFX01PREVMX01BVENIRVJTID0gW1wiY2xhdWRlXCIsIFwiYW50aHJvcGljXCJdO1xuXG5jb25zdCBDTEFVREVfUFJPTVBUX0NBQ0hJTkdfUFJPVklERVJfT1BUSU9OUzogUHJvdmlkZXJPcHRpb25zID0ge1xuICBhbnRocm9waWM6IHtcbiAgICBjYWNoZUNvbnRyb2w6IHsgdHlwZTogXCJlcGhlbWVyYWxcIiB9LFxuICB9LFxuICBvcGVucm91dGVyOiB7XG4gICAgY2FjaGVDb250cm9sOiB7IHR5cGU6IFwiZXBoZW1lcmFsXCIgfSxcbiAgfSxcbiAgYmVkcm9jazoge1xuICAgIGNhY2hlUG9pbnQ6IHsgdHlwZTogXCJkZWZhdWx0XCIgfSxcbiAgfSxcbiAgb3BlbmFpQ29tcGF0aWJsZToge1xuICAgIGNhY2hlX2NvbnRyb2w6IHsgdHlwZTogXCJlcGhlbWVyYWxcIiB9LFxuICB9LFxuICBjb3BpbG90OiB7XG4gICAgY29waWxvdF9jYWNoZV9jb250cm9sOiB7IHR5cGU6IFwiZXBoZW1lcmFsXCIgfSxcbiAgfSxcbn07XG5cbmZ1bmN0aW9uIGdldEdhdGV3YXlQcm92aWRlcihtb2RlbDogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB7XG4gIGNvbnN0IHNsYXNoSW5kZXggPSBtb2RlbC5pbmRleE9mKFwiL1wiKTtcbiAgaWYgKHNsYXNoSW5kZXggPT09IC0xKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgcmV0dXJuIG1vZGVsLnNsaWNlKDAsIHNsYXNoSW5kZXgpO1xufVxuXG5mdW5jdGlvbiBjb3VudEFudGhyb3BpY0NhY2hlQnJlYWtwb2ludHMobWVzc2FnZXM6IE1vZGVsTWVzc2FnZVtdKTogbnVtYmVyIHtcbiAgbGV0IGNvdW50ID0gMDtcbiAgZm9yIChjb25zdCBtZXNzYWdlIG9mIG1lc3NhZ2VzKSB7XG4gICAgY29uc3QgcHJvdmlkZXJPcHRpb25zID0gKG1lc3NhZ2UgYXMgeyBwcm92aWRlck9wdGlvbnM/OiBQcm92aWRlck9wdGlvbnMgfSlcbiAgICAgIC5wcm92aWRlck9wdGlvbnM7XG4gICAgaWYgKHByb3ZpZGVyT3B0aW9ucz8uYW50aHJvcGljPy5jYWNoZUNvbnRyb2wpIHtcbiAgICAgIGNvdW50ICs9IDE7XG4gICAgfVxuICAgIGlmIChBcnJheS5pc0FycmF5KG1lc3NhZ2UuY29udGVudCkpIHtcbiAgICAgIGZvciAoY29uc3QgcGFydCBvZiBtZXNzYWdlLmNvbnRlbnQpIHtcbiAgICAgICAgY29uc3QgcGFydFByb3ZpZGVyT3B0aW9ucyA9IChcbiAgICAgICAgICBwYXJ0IGFzIHsgcHJvdmlkZXJPcHRpb25zPzogUHJvdmlkZXJPcHRpb25zIH1cbiAgICAgICAgKS5wcm92aWRlck9wdGlvbnM7XG4gICAgICAgIGlmIChwYXJ0UHJvdmlkZXJPcHRpb25zPy5hbnRocm9waWM/LmNhY2hlQ29udHJvbCkge1xuICAgICAgICAgIGNvdW50ICs9IDE7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIGNvdW50O1xufVxuXG5mdW5jdGlvbiBpc0NsYXVkZUxpa2VNb2RlbChtb2RlbDogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGNvbnN0IGxvd2VyID0gbW9kZWwudG9Mb3dlckNhc2UoKTtcbiAgcmV0dXJuIENMQVVERV9MSUtFX01PREVMX01BVENIRVJTLnNvbWUoKG0pID0+IGxvd2VyLmluY2x1ZGVzKG0pKTtcbn1cblxuZnVuY3Rpb24gbWVyZ2VQcm92aWRlck9wdGlvbnMob3B0czoge1xuICBjdXJyZW50OiBQcm92aWRlck9wdGlvbnMgfCB1bmRlZmluZWQ7XG4gIHBhdGNoOiBQcm92aWRlck9wdGlvbnM7XG59KTogUHJvdmlkZXJPcHRpb25zIHtcbiAgY29uc3QgbmV4dDogUHJvdmlkZXJPcHRpb25zID0geyAuLi4ob3B0cy5jdXJyZW50ID8/IHt9KSB9O1xuICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhvcHRzLnBhdGNoKSkge1xuICAgIG5leHRba2V5XSA9IHsgLi4uKG5leHRba2V5XSA/PyB7fSksIC4uLnZhbHVlIH07XG4gIH1cbiAgcmV0dXJuIG5leHQ7XG59XG5cbmZ1bmN0aW9uIGlzQ2FjaGVhYmxlQ2xhdWRlUGFydChwYXJ0OiB1bmtub3duKTogYm9vbGVhbiB7XG4gIGlmICghcGFydCB8fCB0eXBlb2YgcGFydCAhPT0gXCJvYmplY3RcIikge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmIChcInR5cGVcIiBpbiBwYXJ0ICYmIChwYXJ0IGFzIHsgdHlwZT86IHVua25vd24gfSkudHlwZSA9PT0gXCJ0ZXh0XCIpIHtcbiAgICBjb25zdCB0ZXh0ID0gKHBhcnQgYXMgeyB0ZXh0PzogdW5rbm93biB9KS50ZXh0O1xuICAgIGlmICh0eXBlb2YgdGV4dCA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgcmV0dXJuIHRleHQudHJpbSgpLmxlbmd0aCA+IDA7XG4gICAgfVxuICB9XG5cbiAgaWYgKFwidHlwZVwiIGluIHBhcnQpIHtcbiAgICBjb25zdCB0eXBlID0gKHBhcnQgYXMgeyB0eXBlPzogdW5rbm93biB9KS50eXBlO1xuICAgIGlmICh0eXBlID09PSBcInRoaW5raW5nXCIgfHwgdHlwZSA9PT0gXCJyZWFzb25pbmdcIikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBoYXNDYWNoZWFibGVDb250ZW50KG1lc3NhZ2U6IE1vZGVsTWVzc2FnZSk6IGJvb2xlYW4ge1xuICBpZiAodHlwZW9mIG1lc3NhZ2UuY29udGVudCA9PT0gXCJzdHJpbmdcIikge1xuICAgIHJldHVybiBtZXNzYWdlLmNvbnRlbnQudHJpbSgpLmxlbmd0aCA+IDA7XG4gIH1cblxuICBpZiAoQXJyYXkuaXNBcnJheShtZXNzYWdlLmNvbnRlbnQpKSB7XG4gICAgcmV0dXJuIG1lc3NhZ2UuY29udGVudC5zb21lKChwYXJ0KSA9PiBpc0NhY2hlYWJsZUNsYXVkZVBhcnQocGFydCkpO1xuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBmaW5kTGFzdENhY2hlYWJsZVBhcnRJbmRleChjb250ZW50OiB1bmtub3duW10pOiBudW1iZXIgfCBudWxsIHtcbiAgZm9yIChsZXQgaSA9IGNvbnRlbnQubGVuZ3RoIC0gMTsgaSA+PSAwOyBpIC09IDEpIHtcbiAgICBpZiAoaXNDYWNoZWFibGVDbGF1ZGVQYXJ0KGNvbnRlbnRbaV0pKSB7XG4gICAgICByZXR1cm4gaTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG51bGw7XG59XG5cbmZ1bmN0aW9uIHNlbGVjdENsYXVkZUNhY2hpbmdUYXJnZXRzKG1lc3NhZ2VzOiBNb2RlbE1lc3NhZ2VbXSk6IG51bWJlcltdIHtcbiAgY29uc3Qgc3lzdGVtSW5kaWNlczogbnVtYmVyW10gPSBbXTtcbiAgY29uc3QgZmluYWxJbmRpY2VzOiBudW1iZXJbXSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbWVzc2FnZXMubGVuZ3RoICYmIHN5c3RlbUluZGljZXMubGVuZ3RoIDwgMjsgaSArPSAxKSB7XG4gICAgY29uc3QgbWVzc2FnZSA9IG1lc3NhZ2VzW2ldO1xuICAgIGlmIChtZXNzYWdlLnJvbGUgPT09IFwic3lzdGVtXCIgJiYgaGFzQ2FjaGVhYmxlQ29udGVudChtZXNzYWdlKSkge1xuICAgICAgc3lzdGVtSW5kaWNlcy5wdXNoKGkpO1xuICAgIH1cbiAgfVxuXG4gIGZvciAobGV0IGkgPSBtZXNzYWdlcy5sZW5ndGggLSAxOyBpID49IDAgJiYgZmluYWxJbmRpY2VzLmxlbmd0aCA8IDI7IGkgLT0gMSkge1xuICAgIGNvbnN0IG1lc3NhZ2UgPSBtZXNzYWdlc1tpXTtcbiAgICBpZiAobWVzc2FnZS5yb2xlICE9PSBcInN5c3RlbVwiICYmIGhhc0NhY2hlYWJsZUNvbnRlbnQobWVzc2FnZSkpIHtcbiAgICAgIGZpbmFsSW5kaWNlcy5wdXNoKGkpO1xuICAgIH1cbiAgfVxuXG4gIGZpbmFsSW5kaWNlcy5yZXZlcnNlKCk7XG5cbiAgcmV0dXJuIFsuLi5zeXN0ZW1JbmRpY2VzLCAuLi5maW5hbEluZGljZXNdO1xufVxuXG5mdW5jdGlvbiBhcHBseUNsYXVkZVByb21wdENhY2hpbmcob3B0czoge1xuICBtZXNzYWdlczogTW9kZWxNZXNzYWdlW107XG4gIHByb3ZpZGVySWQ6IHN0cmluZyB8IG51bGw7XG4gIG1heEJyZWFrcG9pbnRzUGVyUmVxdWVzdDogbnVtYmVyO1xufSk6IE1vZGVsTWVzc2FnZVtdIHtcbiAgY29uc3QgZXhpc3RpbmdCcmVha3BvaW50cyA9IGNvdW50QW50aHJvcGljQ2FjaGVCcmVha3BvaW50cyhvcHRzLm1lc3NhZ2VzKTtcbiAgY29uc3QgcmVtYWluaW5nQnVkZ2V0ID0gTWF0aC5tYXgoXG4gICAgMCxcbiAgICBvcHRzLm1heEJyZWFrcG9pbnRzUGVyUmVxdWVzdCAtIGV4aXN0aW5nQnJlYWtwb2ludHNcbiAgKTtcblxuICBpZiAocmVtYWluaW5nQnVkZ2V0ID09PSAwKSB7XG4gICAgcmV0dXJuIG9wdHMubWVzc2FnZXM7XG4gIH1cblxuICBjb25zdCB0YXJnZXRJbmRpY2VzID0gc2VsZWN0Q2xhdWRlQ2FjaGluZ1RhcmdldHMob3B0cy5tZXNzYWdlcykuc2xpY2UoXG4gICAgMCxcbiAgICByZW1haW5pbmdCdWRnZXRcbiAgKTtcbiAgaWYgKHRhcmdldEluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIG9wdHMubWVzc2FnZXM7XG4gIH1cblxuICBjb25zdCB1c2VNZXNzYWdlTGV2ZWxPcHRpb25zID1cbiAgICBvcHRzLnByb3ZpZGVySWQgPT09IFwiYW50aHJvcGljXCIgfHxcbiAgICBCb29sZWFuKG9wdHMucHJvdmlkZXJJZD8uaW5jbHVkZXMoXCJiZWRyb2NrXCIpKTtcblxuICBjb25zdCBuZXh0TWVzc2FnZXMgPSBvcHRzLm1lc3NhZ2VzLnNsaWNlKCk7XG5cbiAgZm9yIChjb25zdCBtZXNzYWdlSW5kZXggb2YgdGFyZ2V0SW5kaWNlcykge1xuICAgIGNvbnN0IG1lc3NhZ2UgPSBuZXh0TWVzc2FnZXNbbWVzc2FnZUluZGV4XTtcblxuICAgIGNvbnN0IHNob3VsZFVzZUNvbnRlbnRPcHRpb25zID1cbiAgICAgICF1c2VNZXNzYWdlTGV2ZWxPcHRpb25zICYmXG4gICAgICBBcnJheS5pc0FycmF5KG1lc3NhZ2UuY29udGVudCkgJiZcbiAgICAgIG1lc3NhZ2UuY29udGVudC5sZW5ndGggPiAwO1xuXG4gICAgaWYgKHNob3VsZFVzZUNvbnRlbnRPcHRpb25zICYmIEFycmF5LmlzQXJyYXkobWVzc2FnZS5jb250ZW50KSkge1xuICAgICAgY29uc3QgcGFydEluZGV4ID0gZmluZExhc3RDYWNoZWFibGVQYXJ0SW5kZXgobWVzc2FnZS5jb250ZW50KTtcbiAgICAgIGlmIChwYXJ0SW5kZXggIT09IG51bGwpIHtcbiAgICAgICAgY29uc3QgcGFydCA9IG1lc3NhZ2UuY29udGVudFtwYXJ0SW5kZXhdO1xuICAgICAgICBpZiAocGFydCAmJiB0eXBlb2YgcGFydCA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICAgIGNvbnN0IHBhcnRQcm92aWRlck9wdGlvbnMgPSAoXG4gICAgICAgICAgICBwYXJ0IGFzIHsgcHJvdmlkZXJPcHRpb25zPzogUHJvdmlkZXJPcHRpb25zIH1cbiAgICAgICAgICApLnByb3ZpZGVyT3B0aW9ucztcblxuICAgICAgICAgIGNvbnN0IG5leHRDb250ZW50ID0gbWVzc2FnZS5jb250ZW50LnNsaWNlKCk7XG4gICAgICAgICAgbmV4dENvbnRlbnRbcGFydEluZGV4XSA9IHtcbiAgICAgICAgICAgIC4uLihwYXJ0IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KSxcbiAgICAgICAgICAgIHByb3ZpZGVyT3B0aW9uczogbWVyZ2VQcm92aWRlck9wdGlvbnMoe1xuICAgICAgICAgICAgICBjdXJyZW50OiBwYXJ0UHJvdmlkZXJPcHRpb25zLFxuICAgICAgICAgICAgICBwYXRjaDogQ0xBVURFX1BST01QVF9DQUNISU5HX1BST1ZJREVSX09QVElPTlMsXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICB9IGFzICh0eXBlb2YgbWVzc2FnZS5jb250ZW50KVtudW1iZXJdO1xuXG4gICAgICAgICAgbmV4dE1lc3NhZ2VzW21lc3NhZ2VJbmRleF0gPSB7XG4gICAgICAgICAgICAuLi5tZXNzYWdlLFxuICAgICAgICAgICAgY29udGVudDogbmV4dENvbnRlbnQsXG4gICAgICAgICAgfSBhcyBNb2RlbE1lc3NhZ2U7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBtZXNzYWdlUHJvdmlkZXJPcHRpb25zID0gKFxuICAgICAgbWVzc2FnZSBhcyB7IHByb3ZpZGVyT3B0aW9ucz86IFByb3ZpZGVyT3B0aW9ucyB9XG4gICAgKS5wcm92aWRlck9wdGlvbnM7XG5cbiAgICBuZXh0TWVzc2FnZXNbbWVzc2FnZUluZGV4XSA9IHtcbiAgICAgIC4uLm1lc3NhZ2UsXG4gICAgICBwcm92aWRlck9wdGlvbnM6IG1lcmdlUHJvdmlkZXJPcHRpb25zKHtcbiAgICAgICAgY3VycmVudDogbWVzc2FnZVByb3ZpZGVyT3B0aW9ucyxcbiAgICAgICAgcGF0Y2g6IENMQVVERV9QUk9NUFRfQ0FDSElOR19QUk9WSURFUl9PUFRJT05TLFxuICAgICAgfSksXG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiBuZXh0TWVzc2FnZXM7XG59XG5cbmV4cG9ydCB0eXBlIFByb21wdENhY2hpbmdSZXN1bHQgPSB7XG4gIG1lc3NhZ2VzOiBNb2RlbE1lc3NhZ2VbXTtcbiAgcHJvdmlkZXJPcHRpb25zOiBQcm92aWRlck9wdGlvbnM7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gYXBwbHlQcm9tcHRDYWNoaW5nVG9Nb2RlbFJlcXVlc3Qob3B0czoge1xuICBtb2RlbDogc3RyaW5nO1xuICBzZXNzaW9uSWQ6IHN0cmluZztcbiAgbWVzc2FnZXM6IE1vZGVsTWVzc2FnZVtdO1xuICBhbnRocm9waWM/OiB7IG1heEJyZWFrcG9pbnRzUGVyUmVxdWVzdD86IG51bWJlciB9O1xuICBvcGVuYWk/OiB7IHNldFByb21wdENhY2hlS2V5PzogYm9vbGVhbiB9O1xufSk6IFByb21wdENhY2hpbmdSZXN1bHQge1xuICBjb25zdCBwcm92aWRlciA9IGdldEdhdGV3YXlQcm92aWRlcihvcHRzLm1vZGVsKTtcblxuICBjb25zdCBwcm92aWRlck9wdGlvbnM6IFByb3ZpZGVyT3B0aW9ucyA9IHt9O1xuXG4gIGlmIChcbiAgICAocHJvdmlkZXIgPT09IFwib3BlbmFpXCIgfHwgcHJvdmlkZXIgPT09IFwiYXp1cmVcIikgJiZcbiAgICBvcHRzLm9wZW5haT8uc2V0UHJvbXB0Q2FjaGVLZXkgIT09IGZhbHNlXG4gICkge1xuICAgIHByb3ZpZGVyT3B0aW9ucy5vcGVuYWkgPSB7IHByb21wdENhY2hlS2V5OiBvcHRzLnNlc3Npb25JZCB9O1xuICB9XG5cbiAgY29uc3QgbWF4QnJlYWtwb2ludHNQZXJSZXF1ZXN0ID1cbiAgICBvcHRzLmFudGhyb3BpYz8ubWF4QnJlYWtwb2ludHNQZXJSZXF1ZXN0ID8/XG4gICAgQU5USFJPUElDX01BWF9DQUNIRV9CUkVBS1BPSU5UU19QRVJfUkVRVUVTVDtcblxuICBjb25zdCBjYWNoZWRNZXNzYWdlcyA9IGlzQ2xhdWRlTGlrZU1vZGVsKG9wdHMubW9kZWwpXG4gICAgPyBhcHBseUNsYXVkZVByb21wdENhY2hpbmcoe1xuICAgICAgICBtZXNzYWdlczogb3B0cy5tZXNzYWdlcyxcbiAgICAgICAgcHJvdmlkZXJJZDogcHJvdmlkZXIsXG4gICAgICAgIG1heEJyZWFrcG9pbnRzUGVyUmVxdWVzdCxcbiAgICAgIH0pXG4gICAgOiBvcHRzLm1lc3NhZ2VzO1xuXG4gIHJldHVybiB7XG4gICAgbWVzc2FnZXM6IGNhY2hlZE1lc3NhZ2VzLFxuICAgIHByb3ZpZGVyT3B0aW9ucyxcbiAgfTtcbn1cbiIsICJpbXBvcnQgdHlwZSB7IFVJTWVzc2FnZSB9IGZyb20gXCJhaVwiO1xuaW1wb3J0IHR5cGUgeyBNZXNzYWdlLCBQYXJ0IH0gZnJvbSBcIi4uL3N0b3JhZ2VcIjtcblxuLyoqIFN1Yi10b29sIHBhcnRzIChmcm9tIEphdmFTY3JpcHQgbWV0YS10b29sKSB1c2UgdGhpcyB0b29sQ2FsbElkIHByZWZpeC4gKi9cbmZ1bmN0aW9uIGlzU3ViVG9vbFBhcnQocGFydDogUGFydCk6IGJvb2xlYW4ge1xuICBjb25zdCBwID0gcGFydC5wYXJ0IGFzIHsgdG9vbENhbGxJZD86IHN0cmluZyB9O1xuICByZXR1cm4gdHlwZW9mIHA/LnRvb2xDYWxsSWQgPT09IFwic3RyaW5nXCIgJiYgcC50b29sQ2FsbElkLnN0YXJ0c1dpdGgoXCJqc190Y19cIik7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhc3NlbWJsZVVJTWVzc2FnZXMob3B0czoge1xuICBtZXNzYWdlczogTWVzc2FnZVtdO1xuICBwYXJ0czogUGFydFtdO1xuICB1bnRpbD86IG51bWJlcjtcbiAgaW5jbHVkZVF1ZXVlZD86IGJvb2xlYW47XG4gIC8qKiBXaGVuIHRydWUsIGZpbHRlcnMgb3V0IHN1Yi10b29sIHBhcnRzIHNvIHRoZSBMTE0gZG9lc24ndCBzZWUgdGhlbS4gKi9cbiAgZXhjbHVkZVN1YlRvb2xQYXJ0cz86IGJvb2xlYW47XG59KTogVUlNZXNzYWdlW10ge1xuICBsZXQgZmlsdGVyZWQgPSBvcHRzLm1lc3NhZ2VzO1xuXG4gIGlmIChvcHRzLnVudGlsICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25zdCB1bnRpbCA9IG9wdHMudW50aWw7XG4gICAgZmlsdGVyZWQgPSBmaWx0ZXJlZC5maWx0ZXIoKG0pID0+IG0uY3JlYXRlZEF0IDw9IHVudGlsKTtcbiAgfVxuXG4gIGlmICghb3B0cy5pbmNsdWRlUXVldWVkKSB7XG4gICAgZmlsdGVyZWQgPSBmaWx0ZXJlZC5maWx0ZXIoKG0pID0+IG0uc3RhcnRlZEF0ICE9PSBudWxsKTtcbiAgfVxuXG4gIGNvbnN0IHBhcnRzID0gb3B0cy5leGNsdWRlU3ViVG9vbFBhcnRzXG4gICAgPyBvcHRzLnBhcnRzLmZpbHRlcigocCkgPT4gIWlzU3ViVG9vbFBhcnQocCkpXG4gICAgOiBvcHRzLnBhcnRzO1xuXG4gIGNvbnN0IHBhcnRzQnlNZXNzYWdlID0gbmV3IE1hcDxzdHJpbmcsIFBhcnRbXT4oKTtcbiAgZm9yIChjb25zdCBwYXJ0IG9mIHBhcnRzKSB7XG4gICAgY29uc3QgZXhpc3RpbmcgPSBwYXJ0c0J5TWVzc2FnZS5nZXQocGFydC5tZXNzYWdlSWQpID8/IFtdO1xuICAgIGV4aXN0aW5nLnB1c2gocGFydCk7XG4gICAgcGFydHNCeU1lc3NhZ2Uuc2V0KHBhcnQubWVzc2FnZUlkLCBleGlzdGluZyk7XG4gIH1cblxuICByZXR1cm4gZmlsdGVyZWRcbiAgICAubWFwKChtKSA9PiB7XG4gICAgICBjb25zdCBtZXNzYWdlUGFydHMgPSBwYXJ0c0J5TWVzc2FnZS5nZXQobS5pZCkgPz8gW107XG4gICAgICBtZXNzYWdlUGFydHMuc29ydCgoYSwgYikgPT4gYS5pbmRleCAtIGIuaW5kZXgpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaWQ6IG0uaWQsXG4gICAgICAgIHJvbGU6IG0ucm9sZSxcbiAgICAgICAgcGFydHM6IG1lc3NhZ2VQYXJ0cy5tYXAoKHApID0+IHAucGFydCksXG4gICAgICB9IHNhdGlzZmllcyBVSU1lc3NhZ2U7XG4gICAgfSlcbiAgICAuZmlsdGVyKChtKSA9PiBtLnBhcnRzLmxlbmd0aCA+IDApO1xufVxuIiwgImltcG9ydCB0eXBlIHsgU3RlcFVzYWdlLCBVc2FnZVN1bW1hcnkgfSBmcm9tIFwiLi4vc3RvcmFnZS9ycGNcIjtcblxuZXhwb3J0IHR5cGUgeyBTdGVwVXNhZ2UsIFVzYWdlU3VtbWFyeSB9O1xuXG5mdW5jdGlvbiBzdW0oaXRlbXM6IFN0ZXBVc2FnZVtdLCBrZXk6IGtleW9mIFN0ZXBVc2FnZSk6IG51bWJlciB7XG4gIHJldHVybiBpdGVtcy5yZWR1Y2UoKGFjYywgaXRlbSkgPT4ge1xuICAgIGNvbnN0IHZhbHVlID0gaXRlbVtrZXldO1xuICAgIHJldHVybiBhY2MgKyAodHlwZW9mIHZhbHVlID09PSBcIm51bWJlclwiID8gdmFsdWUgOiAwKTtcbiAgfSwgMCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjb21wdXRlVXNhZ2VTdW1tYXJ5KHN0ZXBzOiBTdGVwVXNhZ2VbXSk6IFVzYWdlU3VtbWFyeSB7XG4gIHJldHVybiB7XG4gICAgbW9kZWw6IHN0ZXBzWzBdPy5tb2RlbCA/PyBcInVua25vd25cIixcbiAgICBpbnB1dFRva2Vuczogc3VtKHN0ZXBzLCBcImlucHV0VG9rZW5zXCIpLFxuICAgIG91dHB1dFRva2Vuczogc3VtKHN0ZXBzLCBcIm91dHB1dFRva2Vuc1wiKSxcbiAgICB0b3RhbFRva2Vuczogc3VtKHN0ZXBzLCBcInRvdGFsVG9rZW5zXCIpLFxuICAgIGNhY2hlUmVhZFRva2Vuczogc3VtKHN0ZXBzLCBcImNhY2hlUmVhZFRva2Vuc1wiKSxcbiAgICBjYWNoZVdyaXRlVG9rZW5zOiBzdW0oc3RlcHMsIFwiY2FjaGVXcml0ZVRva2Vuc1wiKSxcbiAgICByZWFzb25pbmdUb2tlbnM6IHN1bShzdGVwcywgXCJyZWFzb25pbmdUb2tlbnNcIiksXG4gICAgc3RlcENvdW50OiBzdGVwcy5sZW5ndGgsXG4gIH07XG59XG5cbmV4cG9ydCB0eXBlIFNlc3Npb25Vc2FnZSA9IHtcbiAgdG90YWw6IFVzYWdlU3VtbWFyeSAmIHsgbWVzc2FnZUNvdW50OiBudW1iZXIgfTtcbiAgYnlNZXNzYWdlSWQ6IFJlY29yZDxzdHJpbmcsIFVzYWdlU3VtbWFyeSB8IG51bGw+O1xufTtcblxuZXhwb3J0IGZ1bmN0aW9uIGNvbXB1dGVTZXNzaW9uVXNhZ2UoXG4gIG1lc3NhZ2VzOiBBcnJheTx7XG4gICAgaWQ6IHN0cmluZztcbiAgICB1c2FnZTogeyBzdGVwczogU3RlcFVzYWdlW107IHN1bW1hcnk6IFVzYWdlU3VtbWFyeSB9IHwgbnVsbDtcbiAgfT5cbik6IFNlc3Npb25Vc2FnZSB7XG4gIGNvbnN0IGJ5TWVzc2FnZUlkOiBSZWNvcmQ8c3RyaW5nLCBVc2FnZVN1bW1hcnkgfCBudWxsPiA9IHt9O1xuICBmb3IgKGNvbnN0IG0gb2YgbWVzc2FnZXMpIHtcbiAgICBieU1lc3NhZ2VJZFttLmlkXSA9IG0udXNhZ2U/LnN1bW1hcnkgPz8gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IHN1bW1hcmllcyA9IG1lc3NhZ2VzXG4gICAgLm1hcCgobSkgPT4gbS51c2FnZT8uc3VtbWFyeSlcbiAgICAuZmlsdGVyKChzKTogcyBpcyBVc2FnZVN1bW1hcnkgPT4gcyAhPT0gdW5kZWZpbmVkKTtcblxuICBjb25zdCB0b3RhbCA9IHtcbiAgICBtb2RlbDogc3VtbWFyaWVzWzBdPy5tb2RlbCA/PyBcInVua25vd25cIixcbiAgICBpbnB1dFRva2Vuczogc3VtbWFyaWVzLnJlZHVjZSgoYWNjLCBzKSA9PiBhY2MgKyBzLmlucHV0VG9rZW5zLCAwKSxcbiAgICBvdXRwdXRUb2tlbnM6IHN1bW1hcmllcy5yZWR1Y2UoKGFjYywgcykgPT4gYWNjICsgcy5vdXRwdXRUb2tlbnMsIDApLFxuICAgIHRvdGFsVG9rZW5zOiBzdW1tYXJpZXMucmVkdWNlKChhY2MsIHMpID0+IGFjYyArIHMudG90YWxUb2tlbnMsIDApLFxuICAgIGNhY2hlUmVhZFRva2Vuczogc3VtbWFyaWVzLnJlZHVjZSgoYWNjLCBzKSA9PiBhY2MgKyBzLmNhY2hlUmVhZFRva2VucywgMCksXG4gICAgY2FjaGVXcml0ZVRva2Vuczogc3VtbWFyaWVzLnJlZHVjZSgoYWNjLCBzKSA9PiBhY2MgKyBzLmNhY2hlV3JpdGVUb2tlbnMsIDApLFxuICAgIHJlYXNvbmluZ1Rva2Vuczogc3VtbWFyaWVzLnJlZHVjZSgoYWNjLCBzKSA9PiBhY2MgKyBzLnJlYXNvbmluZ1Rva2VucywgMCksXG4gICAgc3RlcENvdW50OiBzdW1tYXJpZXMucmVkdWNlKChhY2MsIHMpID0+IGFjYyArIHMuc3RlcENvdW50LCAwKSxcbiAgICBtZXNzYWdlQ291bnQ6IHN1bW1hcmllcy5sZW5ndGgsXG4gIH07XG5cbiAgcmV0dXJuIHsgdG90YWwsIGJ5TWVzc2FnZUlkIH07XG59XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7OztBQUNBLFNBQVMsWUFBWSxjQUFBQSxhQUFZLG1CQUFtQjs7O0FDRHBEO0FBQUEsRUFDRTtBQUFBLEVBQ0E7QUFBQSxFQUVBO0FBQUEsRUFDQTtBQUFBLE9BRUs7QUFDUCxTQUFTLFlBQVk7QUFDckIsU0FBUyxrQkFBa0I7OztBQ2lCcEIsU0FBUyxzQkFDZCxTQUN5QjtBQUN6QixRQUFNLFVBQVUsUUFBUSxLQUFLO0FBRTdCLE1BQUksQ0FBQyxRQUFRLFdBQVcsS0FBSyxHQUFHO0FBQzlCLFdBQU87QUFBQSxFQUNUO0FBRUEsUUFBTSxpQkFBaUIsUUFBUSxRQUFRLE9BQU8sQ0FBQztBQUMvQyxNQUFJLG1CQUFtQixJQUFJO0FBQ3pCLFdBQU87QUFBQSxFQUNUO0FBRUEsUUFBTSxtQkFBbUIsUUFBUSxNQUFNLEdBQUcsY0FBYyxFQUFFLEtBQUs7QUFDL0QsUUFBTSxTQUFTLGdCQUFnQixnQkFBZ0I7QUFFL0MsTUFBSSxFQUFFLE9BQU8sUUFBUSxPQUFPLGNBQWM7QUFDeEMsV0FBTztBQUFBLEVBQ1Q7QUFFQSxTQUFPO0FBQUEsSUFDTCxNQUFNLE9BQU8sT0FBTyxJQUFJO0FBQUEsSUFDeEIsYUFBYSxPQUFPLE9BQU8sV0FBVztBQUFBLEVBQ3hDO0FBQ0Y7QUFNQSxTQUFTLGdCQUFnQixNQUFzQztBQUM3RCxRQUFNLFNBQWlDLENBQUM7QUFFeEMsYUFBVyxRQUFRLEtBQUssTUFBTSxJQUFJLEdBQUc7QUFDbkMsVUFBTSxjQUFjLEtBQUssS0FBSztBQUM5QixRQUFJLENBQUMsZUFBZSxZQUFZLFdBQVcsR0FBRyxHQUFHO0FBQy9DO0FBQUEsSUFDRjtBQUVBLFVBQU0sYUFBYSxZQUFZLFFBQVEsR0FB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QUFNLGVBQWU7QUFBQSxRQUNsQyxvQkFBb0IsTUFBTTtBQUFBLFFBQzFCO0FBQUEsUUFDQTtBQUFBLFFBQ0E7QUFBQSxRQUNBO0FBQUEsUUFDQSxpQkFBaUIsV0FBVztBQUFBLE1BQzlCLENBQUM7QUFDRCxxQkFBZSxPQUFPO0FBQ3RCLHNCQUFnQixPQUFPO0FBQ3ZCLGlCQUFXLEtBQUssR0FBRyxPQUFPLFVBQVU7QUFFcEMsVUFBSSxPQUFPLFlBQVksUUFBUSxXQUFXLFVBQVUsT0FBTyxVQUFVO0FBQ25FO0FBQUEsTUFDRjtBQUdBLFVBQUksT0FBTyxpQkFBaUIsU0FBUyxHQUFHO0FBQ3RDLGNBQU0sUUFBUTtBQUFBLFVBQ1osT0FBTyxpQkFBaUIsSUFBSSxDQUFDLFlBQVk7QUFDdkMsa0JBQU0sT0FBTyxhQUFhLE9BQU8sRUFBRSxPQUFPLFFBQVEsV0FBVyxDQUFDO0FBQzlELGtCQUFNLE9BQU8sS0FBSyxPQUFPLGFBQWEsRUFBRTtBQUN4QyxtQkFBTyxLQUFLLEtBQUs7QUFBQSxVQUNuQixDQUFDO0FBQUEsUUFDSDtBQUFBLE1BR0Y7QUFBQSxJQUNGLFNBQVMsS0FBSztBQUNaLGNBQVEsTUFBTSxHQUFHO0FBQ2pCLFlBQU07QUFBQSxJQUNSO0FBQUEsRUFDRjtBQUVBLFFBQU0sb0JBQW9CO0FBQUEsSUFDeEIsb0JBQW9CLE1BQU07QUFBQSxJQUMxQjtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsRUFDRixDQUFDO0FBQ0g7IiwKICAibmFtZXMiOiBbIkZhdGFsRXJyb3IiLCAidG9vbCIsICJ6IiwgInRvb2wiLCAieiIsICJzZXNzaW9uIiwgInNhbmRib3hSZWNvcmQiLCAic2FuZGJveCIsICJyZXN1bHQiLCAiZXZlbnQiLCAiRmF0YWxFcnJvciJdCn0K