experimental-agent 0.0.5 → 0.1.2

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