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
@@ -1,1980 +0,0 @@
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 (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-JAKAXROL.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
- var BASE_SYSTEM_PROMPT = "You are an AI assistant with basic tools to interact with your environment. Explore and work freely.";
1347
- function joinPromptSections(...sections) {
1348
- return sections.filter((s) => s?.trim()).join("\n\n");
1349
- }
1350
- var backgroundProcessPrompt = `## Background Processes
1351
- 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.
1352
-
1353
- Use \`waitUntil: 0\` for dev servers that should run indefinitely.
1354
- It is a good practice to check the output log after running processes like dev servers to make sure they started correctly.
1355
-
1356
- To run a background process:
1357
- Bash({ command: "npm run dev", waitUntil: 0 })
1358
- Returns immediately with \`pid\` and \`outputFile\` path.
1359
-
1360
- To check a process's output:
1361
- Bash({ command: "tail -100 {outputFile}" })
1362
-
1363
- To kill a process:
1364
- Bash({ command: "kill {pid}" }) // Graceful
1365
- Bash({ command: "kill -9 {pid}" }) // Force
1366
-
1367
- To list all processes:
1368
- Bash({ command: "ps aux | grep node" })
1369
- `;
1370
- function buildSkillsContext(skills) {
1371
- if (skills.length === 0) {
1372
- return "";
1373
- }
1374
- const skillLines = skills.map((s) => `- ${s.name}: ${s.description}
1375
- Path: ${s.skillMdPath}`).join("\n");
1376
- return `## Available Skills
1377
- ${skillLines}
1378
-
1379
- ${backgroundProcessPrompt}
1380
-
1381
- You can use the Read tool to read any skill's SKILL.md file to learn more about it.`;
1382
- }
1383
- async function completeMessageStep({
1384
- assistantMessageId,
1385
- input,
1386
- writable,
1387
- usageSteps
1388
- }) {
1389
- "use step";
1390
- const { getStorage } = await import("./client-5C4CNU6H.mjs");
1391
- const storage = getStorage({ config: input.storageConfig, rpc: input.rpc });
1392
- const message = await storage.message.get(assistantMessageId);
1393
- if (message instanceof Error) {
1394
- throw message;
1395
- }
1396
- if (!message) {
1397
- throw new Error(`Message ${assistantMessageId} not found`);
1398
- }
1399
- const usage = usageSteps.length > 0 ? {
1400
- steps: usageSteps,
1401
- summary: computeUsageSummary(usageSteps)
1402
- } : null;
1403
- const result = await storage.message.set({
1404
- ...message,
1405
- completedAt: Date.now(),
1406
- usage
1407
- });
1408
- if (result instanceof Error) {
1409
- throw result;
1410
- }
1411
- await writable.close();
1412
- }
1413
- var INTERRUPT_POLL_INTERVAL_MS = 500;
1414
- function pollForInterrupt({
1415
- storage,
1416
- messageId,
1417
- signal,
1418
- abortController
1419
- }) {
1420
- let resolveFirstCheck;
1421
- const firstCheck = new Promise((resolve) => {
1422
- resolveFirstCheck = resolve;
1423
- });
1424
- const poll = async () => {
1425
- let isFirst = true;
1426
- while (!signal.aborted) {
1427
- const message = await storage.message.get(messageId);
1428
- if (message instanceof Error) {
1429
- if (isFirst) {
1430
- resolveFirstCheck();
1431
- }
1432
- return;
1433
- }
1434
- if (message.interruptedAt !== null) {
1435
- abortController.abort();
1436
- if (isFirst) {
1437
- resolveFirstCheck();
1438
- }
1439
- return;
1440
- }
1441
- if (isFirst) {
1442
- isFirst = false;
1443
- resolveFirstCheck();
1444
- }
1445
- await new Promise(
1446
- (resolve) => setTimeout(resolve, INTERRUPT_POLL_INTERVAL_MS)
1447
- );
1448
- }
1449
- };
1450
- poll();
1451
- return { firstCheck };
1452
- }
1453
- async function streamTextStep({
1454
- assistantMessageId,
1455
- input,
1456
- event,
1457
- writable,
1458
- lastPartIndex,
1459
- stepIndexOffset
1460
- }) {
1461
- "use step";
1462
- const { getStorage } = await import("./client-5C4CNU6H.mjs");
1463
- const { getSandbox } = await import("./sandbox-M24R3JLM.mjs");
1464
- const storage = getStorage({ config: input.storageConfig, rpc: input.rpc });
1465
- const abortController = new AbortController();
1466
- const pollController = new AbortController();
1467
- const { firstCheck } = pollForInterrupt({
1468
- storage,
1469
- messageId: assistantMessageId,
1470
- signal: pollController.signal,
1471
- abortController
1472
- });
1473
- const [
1474
- ,
1475
- messagesResult,
1476
- partsResult,
1477
- { session, skills, sandbox, sandboxRecord },
1478
- apiToolsMetadata
1479
- ] = await Promise.all([
1480
- firstCheck,
1481
- storage.message.list(input.sessionId),
1482
- storage.part.listBySession(input.sessionId),
1483
- storage.session.get(input.sessionId).then(async (session2) => {
1484
- if (session2 instanceof Error) {
1485
- throw session2;
1486
- }
1487
- const sandboxRecord2 = session2.sandboxId ? await storage.sandbox.get(session2.sandboxId) : null;
1488
- if (sandboxRecord2 instanceof Error) {
1489
- throw sandboxRecord2;
1490
- }
1491
- if (!sandboxRecord2) {
1492
- throw new FatalError(
1493
- `Sandbox not found for session ${input.sessionId}`
1494
- );
1495
- }
1496
- const sandbox2 = await getSandbox({
1497
- sandboxRecord: sandboxRecord2,
1498
- storageConfig: input.storageConfig,
1499
- storage,
1500
- rpc: input.rpc
1501
- });
1502
- const skills2 = await discoverSkillsInSandbox({
1503
- sandbox: sandbox2,
1504
- skillsDirs: session2.skillsDir || [],
1505
- debug: true
1506
- });
1507
- return { session: session2, skills: skills2, sandbox: sandbox2, sandboxRecord: sandboxRecord2 };
1508
- }),
1509
- fetchApiToolsMetadata({
1510
- rpc: input.rpc
1511
- })
1512
- ]);
1513
- if (abortController.signal.aborted) {
1514
- pollController.abort();
1515
- return {
1516
- finishReason: "stop",
1517
- lastPartIndex,
1518
- usageSteps: [],
1519
- pendingApprovals: [],
1520
- maxSteps: void 0
1521
- };
1522
- }
1523
- if (messagesResult instanceof Error) {
1524
- throw messagesResult;
1525
- }
1526
- if (partsResult instanceof Error) {
1527
- throw partsResult;
1528
- }
1529
- const setStartedPromise = lastPartIndex === 0 ? (async () => {
1530
- const now = Date.now();
1531
- const pendingMessages = messagesResult.items.filter(
1532
- (m) => m.createdAt <= event.createdAt && m.startedAt === null
1533
- );
1534
- if (pendingMessages.length > 0) {
1535
- return await Promise.all(
1536
- pendingMessages.map(
1537
- (m) => storage.message.set({
1538
- ...m,
1539
- startedAt: now,
1540
- completedAt: m.role === "assistant" ? null : now
1541
- })
1542
- )
1543
- );
1544
- }
1545
- })() : null;
1546
- const streamWriterRef = { current: null };
1547
- const subToolPartIds = [];
1548
- let nextPartIndex = lastPartIndex;
1549
- const onSubToolCall = async (toolName, toolInput, execute) => {
1550
- const res = await input.rpc({
1551
- method: "tools.needsApproval",
1552
- params: {
1553
- toolName,
1554
- input: toolInput,
1555
- toolCallId: `js_${toolName}_${Date.now()}`,
1556
- messages: []
1557
- }
1558
- });
1559
- if ("error" in res || res.result !== true) {
1560
- try {
1561
- const result2 = await execute();
1562
- return { result: result2 };
1563
- } catch (err) {
1564
- return { error: err instanceof Error ? err.message : String(err) };
1565
- }
1566
- }
1567
- const approvalId = `js_approval_${ulid()}`;
1568
- const toolCallId = `js_tc_${ulid()}`;
1569
- const partId = `part_${ulid()}`;
1570
- subToolPartIds.push(partId);
1571
- await storage.part.set({
1572
- id: partId,
1573
- index: nextPartIndex++,
1574
- messageId: assistantMessageId,
1575
- sessionId: input.sessionId,
1576
- part: {
1577
- type: `tool-${toolName}`,
1578
- toolCallId,
1579
- state: "approval-requested",
1580
- input: toolInput,
1581
- approval: { id: approvalId }
1582
- }
1583
- });
1584
- streamWriterRef.current?.({
1585
- type: "tool-input-start",
1586
- toolCallId,
1587
- toolName
1588
- });
1589
- streamWriterRef.current?.({
1590
- type: "tool-input-available",
1591
- toolCallId,
1592
- toolName,
1593
- input: toolInput
1594
- });
1595
- streamWriterRef.current?.({
1596
- type: "tool-approval-request",
1597
- approvalId,
1598
- toolCallId
1599
- });
1600
- const POLL_MS = 500;
1601
- const TIMEOUT_MS = 5 * 60 * 1e3;
1602
- const start = Date.now();
1603
- while (Date.now() - start < TIMEOUT_MS) {
1604
- const parts = await storage.part.listBySession(input.sessionId);
1605
- if (!(parts instanceof Error)) {
1606
- const updated = parts.items.find(
1607
- (p) => p.id === partId && "state" in p.part && p.part.state === "approval-responded"
1608
- );
1609
- if (updated) {
1610
- const approval = updated.part.approval;
1611
- if (approval?.approved) {
1612
- try {
1613
- const result2 = await execute();
1614
- streamWriterRef.current?.({
1615
- type: "tool-output-available",
1616
- toolCallId,
1617
- output: result2
1618
- });
1619
- return { result: result2 };
1620
- } catch (err) {
1621
- const error = err instanceof Error ? err.message : String(err);
1622
- streamWriterRef.current?.({
1623
- type: "tool-output-error",
1624
- toolCallId,
1625
- errorText: error
1626
- });
1627
- return { error };
1628
- }
1629
- }
1630
- streamWriterRef.current?.({
1631
- type: "tool-output-denied",
1632
- toolCallId
1633
- });
1634
- return {
1635
- error: `Tool "${toolName}" denied: ${approval?.reason || "user denied"}`
1636
- };
1637
- }
1638
- }
1639
- await new Promise((r) => setTimeout(r, POLL_MS));
1640
- }
1641
- return { error: "Approval timed out" };
1642
- };
1643
- const rawTools = getTools({
1644
- input,
1645
- event,
1646
- sandbox,
1647
- session,
1648
- sandboxRecord,
1649
- apiToolsMetadata,
1650
- onSubToolCall
1651
- });
1652
- const skillsContext = buildSkillsContext(skills);
1653
- const systemHeader = joinPromptSections(BASE_SYSTEM_PROMPT, session.system);
1654
- const systemContext = joinPromptSections(skillsContext);
1655
- if (!session.model) {
1656
- throw new FatalError("Session model is not set");
1657
- }
1658
- const systemMessages = [
1659
- ...systemHeader.trim() ? [{ role: "system", content: systemHeader }] : [],
1660
- ...systemContext.trim() ? [{ role: "system", content: systemContext }] : []
1661
- ];
1662
- const allParts = partsResult.items;
1663
- const approvedParts = allParts.filter(
1664
- (p) => p.part && "state" in p.part && p.part.state === "approval-responded" && "approval" in p.part && p.part.approval?.approved === true
1665
- );
1666
- const executedApprovals = [];
1667
- if (approvedParts.length > 0) {
1668
- const preExecMessages = [
1669
- ...systemMessages,
1670
- ...await convertToModelMessages(
1671
- assembleUIMessages({
1672
- messages: messagesResult.items,
1673
- parts: allParts,
1674
- until: event.createdAt,
1675
- includeQueued: true,
1676
- excludeSubToolParts: true
1677
- })
1678
- )
1679
- ];
1680
- await Promise.all(
1681
- approvedParts.map(async (ap) => {
1682
- if (!ap.part.type.startsWith("tool-")) {
1683
- return;
1684
- }
1685
- const part = ap.part;
1686
- const toolName = part.type.replace("tool-", "");
1687
- const toolDef = rawTools[toolName];
1688
- if (toolDef?.execute && part.input !== void 0) {
1689
- try {
1690
- const toolOutput = await toolDef.execute(part.input, {
1691
- toolCallId: part.toolCallId,
1692
- messages: preExecMessages,
1693
- abortSignal: abortController.signal,
1694
- experimental_context: {
1695
- session,
1696
- sandbox,
1697
- storage,
1698
- context: event.context
1699
- }
1700
- });
1701
- part.state = "output-available";
1702
- part.output = toolOutput;
1703
- executedApprovals.push({
1704
- toolCallId: part.toolCallId,
1705
- output: toolOutput
1706
- });
1707
- } catch (err) {
1708
- part.state = "output-error";
1709
- part.errorText = err instanceof Error ? err.message : String(err);
1710
- executedApprovals.push({
1711
- toolCallId: part.toolCallId,
1712
- output: void 0,
1713
- error: err instanceof Error ? err.message : String(err)
1714
- });
1715
- }
1716
- await storage.part.set({ ...ap, part });
1717
- }
1718
- })
1719
- );
1720
- }
1721
- const uiMessages = assembleUIMessages({
1722
- messages: messagesResult.items,
1723
- parts: allParts,
1724
- until: event.createdAt,
1725
- includeQueued: true,
1726
- excludeSubToolParts: true
1727
- });
1728
- const modelMessages = [
1729
- ...systemMessages,
1730
- ...await convertToModelMessages(uiMessages)
1731
- ];
1732
- const promptCaching = applyPromptCachingToModelRequest({
1733
- model: session.model,
1734
- sessionId: input.sessionId,
1735
- messages: modelMessages
1736
- });
1737
- const usageSteps = [];
1738
- let internalStepIndex = 0;
1739
- const tools = Object.fromEntries(
1740
- Object.entries(rawTools).map(([name, t]) => [
1741
- name,
1742
- {
1743
- ...t,
1744
- needsApproval: async (toolInput, opts) => {
1745
- const res = await input.rpc({
1746
- method: "tools.needsApproval",
1747
- params: {
1748
- toolName: name,
1749
- input: toolInput,
1750
- toolCallId: opts.toolCallId,
1751
- messages: opts.messages
1752
- }
1753
- });
1754
- if ("error" in res) {
1755
- throw new Error(
1756
- `tools.needsApproval RPC failed for ${name}: ${res.error.message}`
1757
- );
1758
- }
1759
- return res.result;
1760
- }
1761
- }
1762
- ])
1763
- );
1764
- const result = streamText({
1765
- messages: promptCaching.messages,
1766
- tools,
1767
- model: session.model,
1768
- abortSignal: abortController.signal,
1769
- activeTools: session.activeTools ?? void 0,
1770
- providerOptions: promptCaching.providerOptions,
1771
- stopWhen: stepCountIs(1),
1772
- temperature: session.generation?.temperature,
1773
- topK: session.generation?.topK,
1774
- topP: session.generation?.topP,
1775
- frequencyPenalty: session.generation?.frequencyPenalty,
1776
- presencePenalty: session.generation?.presencePenalty,
1777
- maxOutputTokens: session.generation?.maxOutputTokens,
1778
- headers: session.generation?.headers,
1779
- experimental_context: {
1780
- session,
1781
- sandbox,
1782
- storage,
1783
- context: event.context
1784
- },
1785
- onStepFinish: ({ usage }) => {
1786
- if (usage) {
1787
- usageSteps.push({
1788
- stepIndex: stepIndexOffset + internalStepIndex,
1789
- model: session.model ?? "unknown",
1790
- inputTokens: usage.inputTokens ?? 0,
1791
- outputTokens: usage.outputTokens ?? 0,
1792
- totalTokens: usage.totalTokens ?? 0,
1793
- cacheReadTokens: usage.inputTokenDetails?.cacheReadTokens ?? 0,
1794
- cacheWriteTokens: usage.inputTokenDetails?.cacheWriteTokens ?? 0,
1795
- reasoningTokens: usage.outputTokenDetails?.reasoningTokens ?? 0
1796
- });
1797
- }
1798
- internalStepIndex++;
1799
- }
1800
- });
1801
- const stepParts = [];
1802
- let wasAborted = false;
1803
- try {
1804
- const stream = createUIMessageStream({
1805
- execute: ({ writer }) => {
1806
- streamWriterRef.current = (event2) => writer.write(event2);
1807
- for (const ea of executedApprovals) {
1808
- if (ea.error) {
1809
- writer.write({
1810
- type: "tool-output-error",
1811
- toolCallId: ea.toolCallId,
1812
- errorText: ea.error
1813
- });
1814
- } else {
1815
- writer.write({
1816
- type: "tool-output-available",
1817
- toolCallId: ea.toolCallId,
1818
- output: ea.output
1819
- });
1820
- }
1821
- }
1822
- writer.merge(
1823
- result.toUIMessageStream({
1824
- generateMessageId: () => assistantMessageId,
1825
- onFinish: ({ messages }) => {
1826
- for (const m of messages) {
1827
- if (m.role === "assistant") {
1828
- stepParts.push(...m.parts);
1829
- }
1830
- }
1831
- }
1832
- })
1833
- );
1834
- }
1835
- });
1836
- await stream.pipeTo(writable, { preventClose: true });
1837
- } catch (err) {
1838
- if (abortController.signal.aborted) {
1839
- wasAborted = true;
1840
- } else {
1841
- console.error("[streamTextStep] stream error:", err);
1842
- throw err;
1843
- }
1844
- } finally {
1845
- pollController.abort();
1846
- }
1847
- await Promise.all(
1848
- stepParts.map(async (uiPart) => {
1849
- const result2 = await storage.part.set({
1850
- id: `part_${ulid()}`,
1851
- index: nextPartIndex++,
1852
- messageId: assistantMessageId,
1853
- sessionId: input.sessionId,
1854
- part: uiPart
1855
- });
1856
- if (result2 instanceof Error) {
1857
- throw result2;
1858
- }
1859
- return result2;
1860
- })
1861
- );
1862
- if (setStartedPromise) {
1863
- const setStartedResult = await setStartedPromise;
1864
- if (setStartedResult instanceof Error) {
1865
- throw setStartedResult;
1866
- }
1867
- for (const m of setStartedResult ?? []) {
1868
- if (m instanceof Error) {
1869
- throw m;
1870
- }
1871
- }
1872
- }
1873
- const pendingApprovals = stepParts.filter(
1874
- (p) => "state" in p && p.state === "approval-requested" && "approval" in p && !!p.approval?.id
1875
- ).map((p) => ({
1876
- approvalId: p.approval.id,
1877
- toolName: "type" in p ? String(p.type).replace("tool-", "") : "unknown"
1878
- }));
1879
- const finalFinishReason = wasAborted ? "stop" : await result.finishReason;
1880
- return {
1881
- finishReason: finalFinishReason,
1882
- lastPartIndex: nextPartIndex,
1883
- usageSteps,
1884
- pendingApprovals,
1885
- maxSteps: session.generation?.maxSteps
1886
- };
1887
- }
1888
-
1889
- // src/agent-workflow.ts
1890
- var agentMessageHook = defineHook();
1891
- var approvalHook = defineHook();
1892
- async function agentWorkflow({
1893
- input,
1894
- event
1895
- }) {
1896
- "use workflow";
1897
- const messageHook = agentMessageHook.create({ token: input.sessionId });
1898
- const iterator = messageHook[Symbol.asyncIterator]();
1899
- let pendingNext = iterator.next();
1900
- await onMessage({ event, input }).catch((e) => {
1901
- if (FatalError2.is(e)) {
1902
- console.error("Message processing failed permanently:", e.message);
1903
- return;
1904
- }
1905
- throw e;
1906
- });
1907
- while (true) {
1908
- const result = await pendingNext;
1909
- if (result.done) {
1910
- console.error("Unexpected: message hook iterator done");
1911
- break;
1912
- }
1913
- await onMessage({ event: result.value, input }).catch((e) => {
1914
- if (FatalError2.is(e)) {
1915
- console.error("Message processing failed permanently:", e.message);
1916
- return;
1917
- }
1918
- throw e;
1919
- });
1920
- pendingNext = iterator.next();
1921
- }
1922
- }
1923
- async function onMessage({
1924
- event,
1925
- input
1926
- }) {
1927
- const writable = getWritable({ namespace: event.assistantMessageId });
1928
- let finishReason;
1929
- let lastPartIndex = 0;
1930
- const usageSteps = [];
1931
- while (finishReason !== "stop") {
1932
- try {
1933
- const result = await streamTextStep({
1934
- assistantMessageId: event.assistantMessageId,
1935
- writable,
1936
- input,
1937
- event,
1938
- lastPartIndex,
1939
- stepIndexOffset: usageSteps.length
1940
- });
1941
- finishReason = result.finishReason;
1942
- lastPartIndex = result.lastPartIndex;
1943
- usageSteps.push(...result.usageSteps);
1944
- if (result.maxSteps != null && usageSteps.length >= result.maxSteps) {
1945
- break;
1946
- }
1947
- if (result.pendingApprovals.length > 0) {
1948
- await Promise.all(
1949
- result.pendingApprovals.map((pending) => {
1950
- const hook = approvalHook.create({ token: pending.approvalId });
1951
- const iter = hook[Symbol.asyncIterator]();
1952
- return iter.next();
1953
- })
1954
- );
1955
- }
1956
- } catch (err) {
1957
- console.error(err);
1958
- throw err;
1959
- }
1960
- }
1961
- await completeMessageStep({
1962
- assistantMessageId: event.assistantMessageId,
1963
- input,
1964
- writable,
1965
- usageSteps
1966
- });
1967
- }
1968
-
1969
- export {
1970
- normalizeSkillsDirs,
1971
- builtInTools,
1972
- builtinToolNames,
1973
- resolveApiUrl,
1974
- assembleUIMessages,
1975
- computeSessionUsage,
1976
- agentMessageHook,
1977
- approvalHook,
1978
- agentWorkflow
1979
- };
1980
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2FnZW50LXdvcmtmbG93LnRzIiwgIi4uL3NyYy9hZ2VudC13b3JrZmxvdy1zdGVwcy50cyIsICIuLi9zcmMvc2tpbGxzL3BhcnNlci50cyIsICIuLi9zcmMvc2tpbGxzL2Rpc2NvdmVyLnRzIiwgIi4uL3NyYy90b29scy9pbmRleC50cyIsICIuLi9zcmMvdG9vbHMvamF2YXNjcmlwdC50cyIsICIuLi9zcmMvdXRpbHMvcHJvbXB0LWNhY2hlLnRzIiwgIi4uL3NyYy91dGlscy91aS50cyIsICIuLi9zcmMvdXRpbHMvdXNhZ2UudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCB0eXBlIHsgRmluaXNoUmVhc29uIH0gZnJvbSBcImFpXCI7XG5pbXBvcnQgeyBkZWZpbmVIb29rLCBGYXRhbEVycm9yLCBnZXRXcml0YWJsZSB9IGZyb20gXCJ3b3JrZmxvd1wiO1xuaW1wb3J0IHsgY29tcGxldGVNZXNzYWdlU3RlcCwgc3RyZWFtVGV4dFN0ZXAgfSBmcm9tIFwiLi9hZ2VudC13b3JrZmxvdy1zdGVwc1wiO1xuaW1wb3J0IHR5cGUgeyBScGNQYXlsb2FkLCBScGNSZXN1bHQgfSBmcm9tIFwiLi9jbGllbnRcIjtcbmltcG9ydCB0eXBlIHsgU3RvcmFnZUNvbmZpZyB9IGZyb20gXCIuL3N0b3JhZ2VcIjtcbmltcG9ydCB0eXBlIHsgU3RlcFVzYWdlIH0gZnJvbSBcIi4vdXRpbHMvdXNhZ2VcIjtcblxuZXhwb3J0IHR5cGUgQWdlbnRJbnB1dCA9IHtcbiAgc2Vzc2lvbklkOiBzdHJpbmc7XG4gIHN0b3JhZ2VDb25maWc6IFN0b3JhZ2VDb25maWc7XG4gIHJwYzogKHBhcmFtczogUnBjUGF5bG9hZCkgPT4gUHJvbWlzZTxScGNSZXN1bHQ+O1xufTtcblxuZXhwb3J0IHR5cGUgQWdlbnRNZXNzYWdlSW5wdXQgPSB7XG4gIGFzc2lzdGFudE1lc3NhZ2VJZDogc3RyaW5nO1xuICBob29rVG9rZW46IHN0cmluZztcbiAgY3JlYXRlZEF0OiBudW1iZXI7XG4gIGNvbnRleHQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xufTtcblxuZXhwb3J0IHR5cGUgQXBwcm92YWxSZXNwb25zZSA9IHtcbiAgYXBwcm92ZWQ6IGJvb2xlYW47XG4gIHJlYXNvbj86IHN0cmluZztcbn07XG5cbmV4cG9ydCBjb25zdCBhZ2VudE1lc3NhZ2VIb29rID0gZGVmaW5lSG9vazxBZ2VudE1lc3NhZ2VJbnB1dD4oKTtcbmV4cG9ydCBjb25zdCBhcHByb3ZhbEhvb2sgPSBkZWZpbmVIb29rPEFwcHJvdmFsUmVzcG9uc2U+KCk7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhZ2VudFdvcmtmbG93KHtcbiAgaW5wdXQsXG4gIGV2ZW50LFxufToge1xuICBpbnB1dDogQWdlbnRJbnB1dDtcbiAgZXZlbnQ6IEFnZW50TWVzc2FnZUlucHV0O1xufSkge1xuICBcInVzZSB3b3JrZmxvd1wiO1xuXG4gIGNvbnN0IG1lc3NhZ2VIb29rID0gYWdlbnRNZXNzYWdlSG9vay5jcmVhdGUoeyB0b2tlbjogaW5wdXQuc2Vzc2lvbklkIH0pO1xuICBjb25zdCBpdGVyYXRvciA9IG1lc3NhZ2VIb29rW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSgpO1xuICBsZXQgcGVuZGluZ05leHQgPSBpdGVyYXRvci5uZXh0KCk7XG5cbiAgYXdhaXQgb25NZXNzYWdlKHsgZXZlbnQsIGlucHV0IH0pLmNhdGNoKChlKSA9PiB7XG4gICAgaWYgKEZhdGFsRXJyb3IuaXMoZSkpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoXCJNZXNzYWdlIHByb2Nlc3NpbmcgZmFpbGVkIHBlcm1hbmVudGx5OlwiLCBlLm1lc3NhZ2UpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aHJvdyBlO1xuICB9KTtcblxuICB3aGlsZSAodHJ1ZSkge1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHBlbmRpbmdOZXh0O1xuXG4gICAgaWYgKHJlc3VsdC5kb25lKSB7XG4gICAgICBjb25zb2xlLmVycm9yKFwiVW5leHBlY3RlZDogbWVzc2FnZSBob29rIGl0ZXJhdG9yIGRvbmVcIik7XG4gICAgICBicmVhaztcbiAgICB9XG5cbiAgICBhd2FpdCBvbk1lc3NhZ2UoeyBldmVudDogcmVzdWx0LnZhbHVlLCBpbnB1dCB9KS5jYXRjaCgoZSkgPT4ge1xuICAgICAgaWYgKEZhdGFsRXJyb3IuaXMoZSkpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihcIk1lc3NhZ2UgcHJvY2Vzc2luZyBmYWlsZWQgcGVybWFuZW50bHk6XCIsIGUubWVzc2FnZSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHRocm93IGU7XG4gICAgfSk7XG4gICAgcGVuZGluZ05leHQgPSBpdGVyYXRvci5uZXh0KCk7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gb25NZXNzYWdlKHtcbiAgZXZlbnQsXG4gIGlucHV0LFxufToge1xuICBldmVudDogQWdlbnRNZXNzYWdlSW5wdXQ7XG4gIGlucHV0OiBBZ2VudElucHV0O1xufSkge1xuICBjb25zdCB3cml0YWJsZSA9IGdldFdyaXRhYmxlKHsgbmFtZXNwYWNlOiBldmVudC5hc3Npc3RhbnRNZXNzYWdlSWQgfSk7XG5cbiAgbGV0IGZpbmlzaFJlYXNvbjogRmluaXNoUmVhc29uIHwgdW5kZWZpbmVkO1xuICBsZXQgbGFzdFBhcnRJbmRleCA9IDA7XG4gIGNvbnN0IHVzYWdlU3RlcHM6IFN0ZXBVc2FnZVtdID0gW107XG5cbiAgd2hpbGUgKGZpbmlzaFJlYXNvbiAhPT0gXCJzdG9wXCIpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3RyZWFtVGV4dFN0ZXAoe1xuICAgICAgICBhc3Npc3RhbnRNZXNzYWdlSWQ6IGV2ZW50LmFzc2lzdGFudE1lc3NhZ2VJZCxcbiAgICAgICAgd3JpdGFibGUsXG4gICAgICAgIGlucHV0LFxuICAgICAgICBldmVudCxcbiAgICAgICAgbGFzdFBhcnRJbmRleCxcbiAgICAgICAgc3RlcEluZGV4T2Zmc2V0OiB1c2FnZVN0ZXBzLmxlbmd0aCxcbiAgICAgIH0pO1xuICAgICAgZmluaXNoUmVhc29uID0gcmVzdWx0LmZpbmlzaFJlYXNvbjtcbiAgICAgIGxhc3RQYXJ0SW5kZXggPSByZXN1bHQubGFzdFBhcnRJbmRleDtcbiAgICAgIHVzYWdlU3RlcHMucHVzaCguLi5yZXN1bHQudXNhZ2VTdGVwcyk7XG5cbiAgICAgIGlmIChyZXN1bHQubWF4U3RlcHMgIT0gbnVsbCAmJiB1c2FnZVN0ZXBzLmxlbmd0aCA+PSByZXN1bHQubWF4U3RlcHMpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICAgIC8vIElmIHRvb2xzIG5lZWQgYXBwcm92YWwsIHN1c3BlbmQgd29ya2Zsb3cgdW50aWwgYWxsIGFyZSByZXNvbHZlZFxuICAgICAgaWYgKHJlc3VsdC5wZW5kaW5nQXBwcm92YWxzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgICAgcmVzdWx0LnBlbmRpbmdBcHByb3ZhbHMubWFwKChwZW5kaW5nKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBob29rID0gYXBwcm92YWxIb29rLmNyZWF0ZSh7IHRva2VuOiBwZW5kaW5nLmFwcHJvdmFsSWQgfSk7XG4gICAgICAgICAgICBjb25zdCBpdGVyID0gaG9va1tTeW1ib2wuYXN5bmNJdGVyYXRvcl0oKTtcbiAgICAgICAgICAgIHJldHVybiBpdGVyLm5leHQoKTtcbiAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgICAgICAvLyBBbGwgaG9va3MgcmVzb2x2ZWQgXHUyMDE0IGFwcHJvdmFsIHJlc3BvbnNlcyBhcmUgbm93IGluIHN0b3JhZ2UuXG4gICAgICAgIC8vIExvb3AgY29udGludWVzIFx1MjE5MiBuZXh0IHN0cmVhbVRleHRTdGVwIHJlYWRzIHVwZGF0ZWQgcGFydHMuXG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBjb25zb2xlLmVycm9yKGVycik7XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfVxuICB9XG5cbiAgYXdhaXQgY29tcGxldGVNZXNzYWdlU3RlcCh7XG4gICAgYXNzaXN0YW50TWVzc2FnZUlkOiBldmVudC5hc3Npc3RhbnRNZXNzYWdlSWQsXG4gICAgaW5wdXQsXG4gICAgd3JpdGFibGUsXG4gICAgdXNhZ2VTdGVwcyxcbiAgfSk7XG59XG4iLCAiaW1wb3J0IHtcbiAgY29udmVydFRvTW9kZWxNZXNzYWdlcyxcbiAgY3JlYXRlVUlNZXNzYWdlU3RyZWFtLFxuICB0eXBlIEZpbmlzaFJlYXNvbixcbiAgc3RlcENvdW50SXMsXG4gIHN0cmVhbVRleHQsXG4gIHR5cGUgVUlNZXNzYWdlLFxufSBmcm9tIFwiYWlcIjtcbmltcG9ydCB7IHVsaWQgfSBmcm9tIFwidWxpZFwiO1xuaW1wb3J0IHsgRmF0YWxFcnJvciB9IGZyb20gXCJ3b3JrZmxvd1wiO1xuaW1wb3J0IHR5cGUgeyBBZ2VudElucHV0LCBBZ2VudE1lc3NhZ2VJbnB1dCB9IGZyb20gXCIuL2FnZW50LXdvcmtmbG93XCI7XG5pbXBvcnQgeyBkaXNjb3ZlclNraWxsc0luU2FuZGJveCB9IGZyb20gXCIuL3NraWxscy9kaXNjb3ZlclwiO1xuaW1wb3J0IHR5cGUgeyBTa2lsbFN1bW1hcnkgfSBmcm9tIFwiLi9za2lsbHMvdHlwZXNcIjtcbmltcG9ydCB0eXBlIHsgU2FuZGJveFJlY29yZCwgU3RvcmFnZSB9IGZyb20gXCIuL3N0b3JhZ2VcIjtcbmltcG9ydCB7IGZldGNoQXBpVG9vbHNNZXRhZGF0YSwgZ2V0VG9vbHMgfSBmcm9tIFwiLi90b29sc1wiO1xuaW1wb3J0IHR5cGUgeyBPblN1YlRvb2xDYWxsIH0gZnJvbSBcIi4vdG9vbHMvamF2YXNjcmlwdFwiO1xuaW1wb3J0IHsgYXBwbHlQcm9tcHRDYWNoaW5nVG9Nb2RlbFJlcXVlc3QgfSBmcm9tIFwiLi91dGlscy9wcm9tcHQtY2FjaGVcIjtcbmltcG9ydCB7IGFzc2VtYmxlVUlNZXNzYWdlcyB9IGZyb20gXCIuL3V0aWxzL3VpXCI7XG5pbXBvcnQgeyBjb21wdXRlVXNhZ2VTdW1tYXJ5LCB0eXBlIFN0ZXBVc2FnZSB9IGZyb20gXCIuL3V0aWxzL3VzYWdlXCI7XG5cbmNvbnN0IEJBU0VfU1lTVEVNX1BST01QVCA9XG4gIFwiWW91IGFyZSBhbiBBSSBhc3Npc3RhbnQgd2l0aCBiYXNpYyB0b29scyB0byBpbnRlcmFjdCB3aXRoIHlvdXIgZW52aXJvbm1lbnQuIEV4cGxvcmUgYW5kIHdvcmsgZnJlZWx5LlwiO1xuXG5mdW5jdGlvbiBqb2luUHJvbXB0U2VjdGlvbnMoXG4gIC4uLnNlY3Rpb25zOiAoc3RyaW5nIHwgdW5kZWZpbmVkIHwgbnVsbClbXVxuKTogc3RyaW5nIHtcbiAgcmV0dXJuIHNlY3Rpb25zLmZpbHRlcigocykgPT4gcz8udHJpbSgpKS5qb2luKFwiXFxuXFxuXCIpO1xufVxuXG5jb25zdCBiYWNrZ3JvdW5kUHJvY2Vzc1Byb21wdCA9IGAjIyBCYWNrZ3JvdW5kIFByb2Nlc3Nlc1xuVGhlc2UgYmFja2dyb3VuZCBwcm9jZXNzIGluc3RydWN0aW9ucyBhcmUgZm9yIHlvdSB0byBtYW5pcHVsYXRlIHRoZSBwcm9jZXNzZXMsIGRvIG5vdCBiZSB0byB2ZXJib3NlIHRvIHRoZSB1c2VyIGFib3V0IHRoZSByZXNwb25zZSBkZXRhaWxzIGxpa2UgXCJob3cgdG8gZGVidWcgdGhlIHByb2Nlc3Mgb3V0cHV0XCIgdGhlIHVzZXIgd2lsbCBoYXZlIGFuIFVJLlxuXG5Vc2UgXFxgd2FpdFVudGlsOiAwXFxgIGZvciBkZXYgc2VydmVycyB0aGF0IHNob3VsZCBydW4gaW5kZWZpbml0ZWx5LlxuSXQgaXMgYSBnb29kIHByYWN0aWNlIHRvIGNoZWNrIHRoZSBvdXRwdXQgbG9nIGFmdGVyIHJ1bm5pbmcgcHJvY2Vzc2VzIGxpa2UgZGV2IHNlcnZlcnMgdG8gbWFrZSBzdXJlIHRoZXkgc3RhcnRlZCBjb3JyZWN0bHkuXG5cblRvIHJ1biBhIGJhY2tncm91bmQgcHJvY2VzczpcbkJhc2goeyBjb21tYW5kOiBcIm5wbSBydW4gZGV2XCIsIHdhaXRVbnRpbDogMCB9KVxuUmV0dXJucyBpbW1lZGlhdGVseSB3aXRoIFxcYHBpZFxcYCBhbmQgXFxgb3V0cHV0RmlsZVxcYCBwYXRoLlxuXG5UbyBjaGVjayBhIHByb2Nlc3MncyBvdXRwdXQ6XG5CYXNoKHsgY29tbWFuZDogXCJ0YWlsIC0xMDAge291dHB1dEZpbGV9XCIgfSlcblxuVG8ga2lsbCBhIHByb2Nlc3M6XG5CYXNoKHsgY29tbWFuZDogXCJraWxsIHtwaWR9XCIgfSkgICAgICAgLy8gR3JhY2VmdWxcbkJhc2goeyBjb21tYW5kOiBcImtpbGwgLTkge3BpZH1cIiB9KSAgICAvLyBGb3JjZVxuXG5UbyBsaXN0IGFsbCBwcm9jZXNzZXM6XG5CYXNoKHsgY29tbWFuZDogXCJwcyBhdXggfCBncmVwIG5vZGVcIiB9KVxuYDtcblxuZnVuY3Rpb24gYnVpbGRTa2lsbHNDb250ZXh0KHNraWxsczogU2tpbGxTdW1tYXJ5W10pOiBzdHJpbmcge1xuICBpZiAoc2tpbGxzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBcIlwiO1xuICB9XG5cbiAgY29uc3Qgc2tpbGxMaW5lcyA9IHNraWxsc1xuICAgIC5tYXAoKHMpID0+IGAtICR7cy5uYW1lfTogJHtzLmRlc2NyaXB0aW9ufVxcbiAgUGF0aDogJHtzLnNraWxsTWRQYXRofWApXG4gICAgLmpvaW4oXCJcXG5cIik7XG5cbiAgcmV0dXJuIGAjIyBBdmFpbGFibGUgU2tpbGxzXG4ke3NraWxsTGluZXN9XG5cbiR7YmFja2dyb3VuZFByb2Nlc3NQcm9tcHR9XG5cbllvdSBjYW4gdXNlIHRoZSBSZWFkIHRvb2wgdG8gcmVhZCBhbnkgc2tpbGwncyBTS0lMTC5tZCBmaWxlIHRvIGxlYXJuIG1vcmUgYWJvdXQgaXQuYDtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNvbXBsZXRlTWVzc2FnZVN0ZXAoe1xuICBhc3Npc3RhbnRNZXNzYWdlSWQsXG4gIGlucHV0LFxuICB3cml0YWJsZSxcbiAgdXNhZ2VTdGVwcyxcbn06IHtcbiAgYXNzaXN0YW50TWVzc2FnZUlkOiBzdHJpbmc7XG4gIGlucHV0OiBBZ2VudElucHV0O1xuICB3cml0YWJsZTogV3JpdGFibGVTdHJlYW07XG4gIHVzYWdlU3RlcHM6IFN0ZXBVc2FnZVtdO1xufSkge1xuICBcInVzZSBzdGVwXCI7XG5cbiAgY29uc3QgeyBnZXRTdG9yYWdlIH0gPSBhd2FpdCBpbXBvcnQoXCIuL3N0b3JhZ2UvY2xpZW50XCIpO1xuICBjb25zdCBzdG9yYWdlID0gZ2V0U3RvcmFnZSh7IGNvbmZpZzogaW5wdXQuc3RvcmFnZUNvbmZpZywgcnBjOiBpbnB1dC5ycGMgfSk7XG5cbiAgY29uc3QgbWVzc2FnZSA9IGF3YWl0IHN0b3JhZ2UubWVzc2FnZS5nZXQoYXNzaXN0YW50TWVzc2FnZUlkKTtcbiAgaWYgKG1lc3NhZ2UgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgIHRocm93IG1lc3NhZ2U7XG4gIH1cbiAgaWYgKCFtZXNzYWdlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBNZXNzYWdlICR7YXNzaXN0YW50TWVzc2FnZUlkfSBub3QgZm91bmRgKTtcbiAgfVxuXG4gIGNvbnN0IHVzYWdlID1cbiAgICB1c2FnZVN0ZXBzLmxlbmd0aCA+IDBcbiAgICAgID8ge1xuICAgICAgICAgIHN0ZXBzOiB1c2FnZVN0ZXBzLFxuICAgICAgICAgIHN1bW1hcnk6IGNvbXB1dGVVc2FnZVN1bW1hcnkodXNhZ2VTdGVwcyksXG4gICAgICAgIH1cbiAgICAgIDogbnVsbDtcblxuICBjb25zdCByZXN1bHQgPSBhd2FpdCBzdG9yYWdlLm1lc3NhZ2Uuc2V0KHtcbiAgICAuLi5tZXNzYWdlLFxuICAgIGNvbXBsZXRlZEF0OiBEYXRlLm5vdygpLFxuICAgIHVzYWdlLFxuICB9KTtcbiAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgdGhyb3cgcmVzdWx0O1xuICB9XG5cbiAgYXdhaXQgd3JpdGFibGUuY2xvc2UoKTtcbn1cblxuY29uc3QgSU5URVJSVVBUX1BPTExfSU5URVJWQUxfTVMgPSA1MDA7XG5cbmZ1bmN0aW9uIHBvbGxGb3JJbnRlcnJ1cHQoe1xuICBzdG9yYWdlLFxuICBtZXNzYWdlSWQsXG4gIHNpZ25hbCxcbiAgYWJvcnRDb250cm9sbGVyLFxufToge1xuICBzdG9yYWdlOiBTdG9yYWdlO1xuICBtZXNzYWdlSWQ6IHN0cmluZztcbiAgc2lnbmFsOiBBYm9ydFNpZ25hbDtcbiAgYWJvcnRDb250cm9sbGVyOiBBYm9ydENvbnRyb2xsZXI7XG59KTogeyBmaXJzdENoZWNrOiBQcm9taXNlPHZvaWQ+IH0ge1xuICBsZXQgcmVzb2x2ZUZpcnN0Q2hlY2s6ICgpID0+IHZvaWQ7XG4gIGNvbnN0IGZpcnN0Q2hlY2sgPSBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xuICAgIHJlc29sdmVGaXJzdENoZWNrID0gcmVzb2x2ZTtcbiAgfSk7XG5cbiAgY29uc3QgcG9sbCA9IGFzeW5jICgpID0+IHtcbiAgICBsZXQgaXNGaXJzdCA9IHRydWU7XG4gICAgd2hpbGUgKCFzaWduYWwuYWJvcnRlZCkge1xuICAgICAgY29uc3QgbWVzc2FnZSA9IGF3YWl0IHN0b3JhZ2UubWVzc2FnZS5nZXQobWVzc2FnZUlkKTtcbiAgICAgIGlmIChtZXNzYWdlIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgaWYgKGlzRmlyc3QpIHtcbiAgICAgICAgICByZXNvbHZlRmlyc3RDaGVjaygpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmIChtZXNzYWdlLmludGVycnVwdGVkQXQgIT09IG51bGwpIHtcbiAgICAgICAgYWJvcnRDb250cm9sbGVyLmFib3J0KCk7XG4gICAgICAgIGlmIChpc0ZpcnN0KSB7XG4gICAgICAgICAgcmVzb2x2ZUZpcnN0Q2hlY2soKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpZiAoaXNGaXJzdCkge1xuICAgICAgICBpc0ZpcnN0ID0gZmFsc2U7XG4gICAgICAgIHJlc29sdmVGaXJzdENoZWNrKCk7XG4gICAgICB9XG4gICAgICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT5cbiAgICAgICAgc2V0VGltZW91dChyZXNvbHZlLCBJTlRFUlJVUFRfUE9MTF9JTlRFUlZBTF9NUylcbiAgICAgICk7XG4gICAgfVxuICB9O1xuXG4gIHBvbGwoKTtcbiAgcmV0dXJuIHsgZmlyc3RDaGVjayB9O1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc3RyZWFtVGV4dFN0ZXAoe1xuICBhc3Npc3RhbnRNZXNzYWdlSWQsXG4gIGlucHV0LFxuICBldmVudCxcbiAgd3JpdGFibGUsXG4gIGxhc3RQYXJ0SW5kZXgsXG4gIHN0ZXBJbmRleE9mZnNldCxcbn06IHtcbiAgYXNzaXN0YW50TWVzc2FnZUlkOiBzdHJpbmc7XG4gIGlucHV0OiBBZ2VudElucHV0O1xuICBldmVudDogQWdlbnRNZXNzYWdlSW5wdXQ7XG4gIHdyaXRhYmxlOiBXcml0YWJsZVN0cmVhbTtcbiAgbGFzdFBhcnRJbmRleDogbnVtYmVyO1xuICBzdGVwSW5kZXhPZmZzZXQ6IG51bWJlcjtcbn0pOiBQcm9taXNlPHtcbiAgZmluaXNoUmVhc29uOiBGaW5pc2hSZWFzb247XG4gIGxhc3RQYXJ0SW5kZXg6IG51bWJlcjtcbiAgdXNhZ2VTdGVwczogU3RlcFVzYWdlW107XG4gIHBlbmRpbmdBcHByb3ZhbHM6IHsgYXBwcm92YWxJZDogc3RyaW5nOyB0b29sTmFtZTogc3RyaW5nIH1bXTtcbiAgbWF4U3RlcHM6IG51bWJlciB8IHVuZGVmaW5lZDtcbn0+IHtcbiAgXCJ1c2Ugc3RlcFwiO1xuXG4gIGNvbnN0IHsgZ2V0U3RvcmFnZSB9ID0gYXdhaXQgaW1wb3J0KFwiLi9zdG9yYWdlL2NsaWVudFwiKTtcbiAgY29uc3QgeyBnZXRTYW5kYm94IH0gPSBhd2FpdCBpbXBvcnQoXCIuL3NhbmRib3hcIik7XG5cbiAgY29uc3Qgc3RvcmFnZSA9IGdldFN0b3JhZ2UoeyBjb25maWc6IGlucHV0LnN0b3JhZ2VDb25maWcsIHJwYzogaW5wdXQucnBjIH0pO1xuXG4gIGNvbnN0IGFib3J0Q29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgY29uc3QgcG9sbENvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG5cbiAgY29uc3QgeyBmaXJzdENoZWNrIH0gPSBwb2xsRm9ySW50ZXJydXB0KHtcbiAgICBzdG9yYWdlLFxuICAgIG1lc3NhZ2VJZDogYXNzaXN0YW50TWVzc2FnZUlkLFxuICAgIHNpZ25hbDogcG9sbENvbnRyb2xsZXIuc2lnbmFsLFxuICAgIGFib3J0Q29udHJvbGxlcixcbiAgfSk7XG5cbiAgY29uc3QgW1xuICAgICxcbiAgICBtZXNzYWdlc1Jlc3VsdCxcbiAgICBwYXJ0c1Jlc3VsdCxcbiAgICB7IHNlc3Npb24sIHNraWxscywgc2FuZGJveCwgc2FuZGJveFJlY29yZCB9LFxuICAgIGFwaVRvb2xzTWV0YWRhdGEsXG4gIF0gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgZmlyc3RDaGVjayxcbiAgICBzdG9yYWdlLm1lc3NhZ2UubGlzdChpbnB1dC5zZXNzaW9uSWQpLFxuICAgIHN0b3JhZ2UucGFydC5saXN0QnlTZXNzaW9uKGlucHV0LnNlc3Npb25JZCksXG4gICAgc3RvcmFnZS5zZXNzaW9uLmdldChpbnB1dC5zZXNzaW9uSWQpLnRoZW4oYXN5bmMgKHNlc3Npb24pID0+IHtcbiAgICAgIGlmIChzZXNzaW9uIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgc2Vzc2lvbjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHNhbmRib3hSZWNvcmQgPSBzZXNzaW9uLnNhbmRib3hJZFxuICAgICAgICA/IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5nZXQoc2Vzc2lvbi5zYW5kYm94SWQpXG4gICAgICAgIDogbnVsbDtcbiAgICAgIGlmIChzYW5kYm94UmVjb3JkIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgc2FuZGJveFJlY29yZDtcbiAgICAgIH1cbiAgICAgIGlmICghc2FuZGJveFJlY29yZCkge1xuICAgICAgICB0aHJvdyBuZXcgRmF0YWxFcnJvcihcbiAgICAgICAgICBgU2FuZGJveCBub3QgZm91bmQgZm9yIHNlc3Npb24gJHtpbnB1dC5zZXNzaW9uSWR9YFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgY29uc3Qgc2FuZGJveCA9IGF3YWl0IGdldFNhbmRib3goe1xuICAgICAgICBzYW5kYm94UmVjb3JkLFxuICAgICAgICBzdG9yYWdlQ29uZmlnOiBpbnB1dC5zdG9yYWdlQ29uZmlnLFxuICAgICAgICBzdG9yYWdlLFxuICAgICAgICBycGM6IGlucHV0LnJwYyxcbiAgICAgIH0pO1xuICAgICAgY29uc3Qgc2tpbGxzID0gYXdhaXQgZGlzY292ZXJTa2lsbHNJblNhbmRib3goe1xuICAgICAgICBzYW5kYm94LFxuICAgICAgICBza2lsbHNEaXJzOiBzZXNzaW9uLnNraWxsc0RpciB8fCBbXSxcbiAgICAgICAgZGVidWc6IHRydWUsXG4gICAgICB9KTtcbiAgICAgIHJldHVybiB7IHNlc3Npb24sIHNraWxscywgc2FuZGJveCwgc2FuZGJveFJlY29yZCB9O1xuICAgIH0pLFxuICAgIGZldGNoQXBpVG9vbHNNZXRhZGF0YSh7XG4gICAgICBycGM6IGlucHV0LnJwYyxcbiAgICB9KSxcbiAgXSk7XG5cbiAgaWYgKGFib3J0Q29udHJvbGxlci5zaWduYWwuYWJvcnRlZCkge1xuICAgIHBvbGxDb250cm9sbGVyLmFib3J0KCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGZpbmlzaFJlYXNvbjogXCJzdG9wXCIgYXMgRmluaXNoUmVhc29uLFxuICAgICAgbGFzdFBhcnRJbmRleCxcbiAgICAgIHVzYWdlU3RlcHM6IFtdLFxuICAgICAgcGVuZGluZ0FwcHJvdmFsczogW10sXG4gICAgICBtYXhTdGVwczogdW5kZWZpbmVkLFxuICAgIH07XG4gIH1cblxuICBpZiAobWVzc2FnZXNSZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgIHRocm93IG1lc3NhZ2VzUmVzdWx0O1xuICB9XG4gIGlmIChwYXJ0c1Jlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgdGhyb3cgcGFydHNSZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogT24gZmlyc3QgaXRlcmF0aW9uLCBtYXJrIGFsbCBtZXNzYWdlcyBpbiB0aGlzIGJhdGNoIGFzIHN0YXJ0ZWQuXG4gICAqIFVzZXIgbWVzc2FnZXMgYXJlIGFsc28gbWFya2VkIGFzIGNvbXBsZXRlZCAodGhleSdyZSBkb25lKS5cbiAgICogVGhlIGFzc2lzdGFudCBtZXNzYWdlIGlzIG9ubHkgbWFya2VkIGFzIHN0YXJ0ZWQgKHN0cmVhbWluZyBpbiBwcm9ncmVzcykuXG4gICAqL1xuICBjb25zdCBzZXRTdGFydGVkUHJvbWlzZSA9XG4gICAgbGFzdFBhcnRJbmRleCA9PT0gMFxuICAgICAgPyAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gICAgICAgICAgY29uc3QgcGVuZGluZ01lc3NhZ2VzID0gbWVzc2FnZXNSZXN1bHQuaXRlbXMuZmlsdGVyKFxuICAgICAgICAgICAgKG0pID0+IG0uY3JlYXRlZEF0IDw9IGV2ZW50LmNyZWF0ZWRBdCAmJiBtLnN0YXJ0ZWRBdCA9PT0gbnVsbFxuICAgICAgICAgICk7XG4gICAgICAgICAgaWYgKHBlbmRpbmdNZXNzYWdlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgICAgICAgIHBlbmRpbmdNZXNzYWdlcy5tYXAoKG0pID0+XG4gICAgICAgICAgICAgICAgc3RvcmFnZS5tZXNzYWdlLnNldCh7XG4gICAgICAgICAgICAgICAgICAuLi5tLFxuICAgICAgICAgICAgICAgICAgc3RhcnRlZEF0OiBub3csXG4gICAgICAgICAgICAgICAgICBjb21wbGV0ZWRBdDogbS5yb2xlID09PSBcImFzc2lzdGFudFwiID8gbnVsbCA6IG5vdyxcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSkoKVxuICAgICAgOiBudWxsO1xuXG4gIC8vIE11dGFibGUgcmVmIHNvIG9uU3ViVG9vbENhbGwgY2FuIHdyaXRlIHRvIHRoZSBzdHJlYW0gb25jZSBhdmFpbGFibGVcbiAgY29uc3Qgc3RyZWFtV3JpdGVyUmVmOiB7XG4gICAgY3VycmVudDogKChldmVudDogdW5rbm93bikgPT4gdm9pZCkgfCBudWxsO1xuICB9ID0geyBjdXJyZW50OiBudWxsIH07XG5cbiAgY29uc3Qgc3ViVG9vbFBhcnRJZHM6IHN0cmluZ1tdID0gW107XG4gIC8vIFNoYXJlZCBjb3VudGVyIGZvciBwYXJ0IGluZGljZXMgXHUyMDE0IHN1Yi10b29sIHBhcnRzIGluY3JlbWVudCB0aGlzIGR1cmluZ1xuICAvLyB0aGUgc3RyZWFtLCB0aGVuIHN0ZXBQYXJ0cyBjb250aW51ZSBmcm9tIHdoZXJlIGl0IGxlZnQgb2ZmLlxuICBsZXQgbmV4dFBhcnRJbmRleCA9IGxhc3RQYXJ0SW5kZXg7XG5cbiAgY29uc3Qgb25TdWJUb29sQ2FsbDogT25TdWJUb29sQ2FsbCA9IGFzeW5jICh0b29sTmFtZSwgdG9vbElucHV0LCBleGVjdXRlKSA9PiB7XG4gICAgLy8gQ2hlY2sgaWYgdGhpcyB0b29sIG5lZWRzIGFwcHJvdmFsIHZpYSBSUENcbiAgICBjb25zdCByZXMgPSBhd2FpdCBpbnB1dC5ycGMoe1xuICAgICAgbWV0aG9kOiBcInRvb2xzLm5lZWRzQXBwcm92YWxcIixcbiAgICAgIHBhcmFtczoge1xuICAgICAgICB0b29sTmFtZSxcbiAgICAgICAgaW5wdXQ6IHRvb2xJbnB1dCxcbiAgICAgICAgdG9vbENhbGxJZDogYGpzXyR7dG9vbE5hbWV9XyR7RGF0ZS5ub3coKX1gLFxuICAgICAgICBtZXNzYWdlczogW10sXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgaWYgKFwiZXJyb3JcIiBpbiByZXMgfHwgcmVzLnJlc3VsdCAhPT0gdHJ1ZSkge1xuICAgICAgLy8gTm8gYXBwcm92YWwgbmVlZGVkIFx1MjAxNCBqdXN0IGV4ZWN1dGVcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGV4ZWN1dGUoKTtcbiAgICAgICAgcmV0dXJuIHsgcmVzdWx0IH07XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgcmV0dXJuIHsgZXJyb3I6IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKSB9O1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEFwcHJvdmFsIG5lZWRlZCBcdTIwMTQgc3VyZmFjZSB0byB1c2VyIHZpYSBzdHJlYW0gZXZlbnRzXG4gICAgY29uc3QgYXBwcm92YWxJZCA9IGBqc19hcHByb3ZhbF8ke3VsaWQoKX1gO1xuICAgIGNvbnN0IHRvb2xDYWxsSWQgPSBganNfdGNfJHt1bGlkKCl9YDtcbiAgICBjb25zdCBwYXJ0SWQgPSBgcGFydF8ke3VsaWQoKX1gO1xuICAgIHN1YlRvb2xQYXJ0SWRzLnB1c2gocGFydElkKTtcblxuICAgIC8vIFN0b3JlIGFwcHJvdmFsLXJlcXVlc3QgcGFydFxuICAgIGF3YWl0IHN0b3JhZ2UucGFydC5zZXQoe1xuICAgICAgaWQ6IHBhcnRJZCxcbiAgICAgIGluZGV4OiBuZXh0UGFydEluZGV4KyssXG4gICAgICBtZXNzYWdlSWQ6IGFzc2lzdGFudE1lc3NhZ2VJZCxcbiAgICAgIHNlc3Npb25JZDogaW5wdXQuc2Vzc2lvbklkLFxuICAgICAgcGFydDoge1xuICAgICAgICB0eXBlOiBgdG9vbC0ke3Rvb2xOYW1lfWAsXG4gICAgICAgIHRvb2xDYWxsSWQsXG4gICAgICAgIHN0YXRlOiBcImFwcHJvdmFsLXJlcXVlc3RlZFwiLFxuICAgICAgICBpbnB1dDogdG9vbElucHV0LFxuICAgICAgICBhcHByb3ZhbDogeyBpZDogYXBwcm92YWxJZCB9LFxuICAgICAgfSBhcyB1bmtub3duIGFzIFVJTWVzc2FnZVtcInBhcnRzXCJdW251bWJlcl0sXG4gICAgfSk7XG5cbiAgICAvLyBXcml0ZSBzdHJlYW0gZXZlbnRzIGZvciB0aGUgVUlcbiAgICAvLyB0b29sLWlucHV0LXN0YXJ0IGlzIHJlcXVpcmVkIFx1MjAxNCB0aGUgQUkgU0RLIGNsaWVudCBjcmVhdGVzIHRoZSB0b29sIHBhcnRcbiAgICAvLyB3aGVuIGl0IHNlZXMgdGhpcyBldmVudC4gV2l0aG91dCBpdCwgc3Vic2VxdWVudCBldmVudHMgYXJlIGlnbm9yZWQuXG4gICAgc3RyZWFtV3JpdGVyUmVmLmN1cnJlbnQ/Lih7XG4gICAgICB0eXBlOiBcInRvb2wtaW5wdXQtc3RhcnRcIixcbiAgICAgIHRvb2xDYWxsSWQsXG4gICAgICB0b29sTmFtZSxcbiAgICB9KTtcbiAgICBzdHJlYW1Xcml0ZXJSZWYuY3VycmVudD8uKHtcbiAgICAgIHR5cGU6IFwidG9vbC1pbnB1dC1hdmFpbGFibGVcIixcbiAgICAgIHRvb2xDYWxsSWQsXG4gICAgICB0b29sTmFtZSxcbiAgICAgIGlucHV0OiB0b29sSW5wdXQsXG4gICAgfSk7XG4gICAgc3RyZWFtV3JpdGVyUmVmLmN1cnJlbnQ/Lih7XG4gICAgICB0eXBlOiBcInRvb2wtYXBwcm92YWwtcmVxdWVzdFwiLFxuICAgICAgYXBwcm92YWxJZCxcbiAgICAgIHRvb2xDYWxsSWQsXG4gICAgfSk7XG5cbiAgICAvLyBQb2xsIHN0b3JhZ2UgZm9yIGFwcHJvdmFsIHJlc3BvbnNlXG4gICAgY29uc3QgUE9MTF9NUyA9IDUwMDtcbiAgICBjb25zdCBUSU1FT1VUX01TID0gNSAqIDYwICogMTAwMDtcbiAgICBjb25zdCBzdGFydCA9IERhdGUubm93KCk7XG5cbiAgICB3aGlsZSAoRGF0ZS5ub3coKSAtIHN0YXJ0IDwgVElNRU9VVF9NUykge1xuICAgICAgY29uc3QgcGFydHMgPSBhd2FpdCBzdG9yYWdlLnBhcnQubGlzdEJ5U2Vzc2lvbihpbnB1dC5zZXNzaW9uSWQpO1xuICAgICAgaWYgKCEocGFydHMgaW5zdGFuY2VvZiBFcnJvcikpIHtcbiAgICAgICAgY29uc3QgdXBkYXRlZCA9IHBhcnRzLml0ZW1zLmZpbmQoXG4gICAgICAgICAgKHApID0+XG4gICAgICAgICAgICBwLmlkID09PSBwYXJ0SWQgJiZcbiAgICAgICAgICAgIFwic3RhdGVcIiBpbiBwLnBhcnQgJiZcbiAgICAgICAgICAgIChwLnBhcnQgYXMgeyBzdGF0ZTogc3RyaW5nIH0pLnN0YXRlID09PSBcImFwcHJvdmFsLXJlc3BvbmRlZFwiXG4gICAgICAgICk7XG4gICAgICAgIGlmICh1cGRhdGVkKSB7XG4gICAgICAgICAgY29uc3QgYXBwcm92YWwgPSAoXG4gICAgICAgICAgICB1cGRhdGVkLnBhcnQgYXMge1xuICAgICAgICAgICAgICBhcHByb3ZhbD86IHsgYXBwcm92ZWQ/OiBib29sZWFuOyByZWFzb24/OiBzdHJpbmcgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICApLmFwcHJvdmFsO1xuICAgICAgICAgIGlmIChhcHByb3ZhbD8uYXBwcm92ZWQpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGV4ZWN1dGUoKTtcbiAgICAgICAgICAgICAgc3RyZWFtV3JpdGVyUmVmLmN1cnJlbnQ/Lih7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJ0b29sLW91dHB1dC1hdmFpbGFibGVcIixcbiAgICAgICAgICAgICAgICB0b29sQ2FsbElkLFxuICAgICAgICAgICAgICAgIG91dHB1dDogcmVzdWx0LFxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgcmV0dXJuIHsgcmVzdWx0IH07XG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVycik7XG4gICAgICAgICAgICAgIHN0cmVhbVdyaXRlclJlZi5jdXJyZW50Py4oe1xuICAgICAgICAgICAgICAgIHR5cGU6IFwidG9vbC1vdXRwdXQtZXJyb3JcIixcbiAgICAgICAgICAgICAgICB0b29sQ2FsbElkLFxuICAgICAgICAgICAgICAgIGVycm9yVGV4dDogZXJyb3IsXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICByZXR1cm4geyBlcnJvciB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBEZW5pZWRcbiAgICAgICAgICBzdHJlYW1Xcml0ZXJSZWYuY3VycmVudD8uKHtcbiAgICAgICAgICAgIHR5cGU6IFwidG9vbC1vdXRwdXQtZGVuaWVkXCIsXG4gICAgICAgICAgICB0b29sQ2FsbElkLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBlcnJvcjogYFRvb2wgXCIke3Rvb2xOYW1lfVwiIGRlbmllZDogJHthcHByb3ZhbD8ucmVhc29uIHx8IFwidXNlciBkZW5pZWRcIn1gLFxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGF3YWl0IG5ldyBQcm9taXNlKChyKSA9PiBzZXRUaW1lb3V0KHIsIFBPTExfTVMpKTtcbiAgICB9XG5cbiAgICByZXR1cm4geyBlcnJvcjogXCJBcHByb3ZhbCB0aW1lZCBvdXRcIiB9O1xuICB9O1xuXG4gIGNvbnN0IHJhd1Rvb2xzID0gZ2V0VG9vbHMoe1xuICAgIGlucHV0LFxuICAgIGV2ZW50LFxuICAgIHNhbmRib3gsXG4gICAgc2Vzc2lvbixcbiAgICBzYW5kYm94UmVjb3JkOiBzYW5kYm94UmVjb3JkIGFzIFNhbmRib3hSZWNvcmQsXG4gICAgYXBpVG9vbHNNZXRhZGF0YSxcbiAgICBvblN1YlRvb2xDYWxsLFxuICB9KTtcblxuICBjb25zdCBza2lsbHNDb250ZXh0ID0gYnVpbGRTa2lsbHNDb250ZXh0KHNraWxscyk7XG4gIGNvbnN0IHN5c3RlbUhlYWRlciA9IGpvaW5Qcm9tcHRTZWN0aW9ucyhCQVNFX1NZU1RFTV9QUk9NUFQsIHNlc3Npb24uc3lzdGVtKTtcbiAgY29uc3Qgc3lzdGVtQ29udGV4dCA9IGpvaW5Qcm9tcHRTZWN0aW9ucyhza2lsbHNDb250ZXh0KTtcblxuICBpZiAoIXNlc3Npb24ubW9kZWwpIHtcbiAgICB0aHJvdyBuZXcgRmF0YWxFcnJvcihcIlNlc3Npb24gbW9kZWwgaXMgbm90IHNldFwiKTtcbiAgfVxuXG4gIGNvbnN0IHN5c3RlbU1lc3NhZ2VzID0gW1xuICAgIC4uLihzeXN0ZW1IZWFkZXIudHJpbSgpXG4gICAgICA/IFt7IHJvbGU6IFwic3lzdGVtXCIgYXMgY29uc3QsIGNvbnRlbnQ6IHN5c3RlbUhlYWRlciB9XVxuICAgICAgOiBbXSksXG4gICAgLi4uKHN5c3RlbUNvbnRleHQudHJpbSgpXG4gICAgICA/IFt7IHJvbGU6IFwic3lzdGVtXCIgYXMgY29uc3QsIGNvbnRlbnQ6IHN5c3RlbUNvbnRleHQgfV1cbiAgICAgIDogW10pLFxuICBdO1xuXG4gIC8vIEV4ZWN1dGUgYXBwcm92ZWQgdG9vbHMgYmVmb3JlIGJ1aWxkaW5nIGZpbmFsIG1lc3NhZ2VzIGZvciBzdHJlYW1UZXh0LlxuICAvLyBUaGlzIGVuc3VyZXMgdGhlIG1vZGVsIHNlZXMgY29tcGxldGUgdG9vbCBjYWxsICsgcmVzdWx0IHBhaXJzLFxuICAvLyBhbmQgdG9VSU1lc3NhZ2VTdHJlYW0gd29uJ3QgZW5jb3VudGVyIG9ycGhhbmVkIHRvb2wgcmVzdWx0cy5cbiAgY29uc3QgYWxsUGFydHMgPSBwYXJ0c1Jlc3VsdC5pdGVtcztcbiAgY29uc3QgYXBwcm92ZWRQYXJ0cyA9IGFsbFBhcnRzLmZpbHRlcihcbiAgICAocCkgPT5cbiAgICAgIHAucGFydCAmJlxuICAgICAgXCJzdGF0ZVwiIGluIHAucGFydCAmJlxuICAgICAgKHAucGFydCBhcyB7IHN0YXRlOiBzdHJpbmcgfSkuc3RhdGUgPT09IFwiYXBwcm92YWwtcmVzcG9uZGVkXCIgJiZcbiAgICAgIFwiYXBwcm92YWxcIiBpbiBwLnBhcnQgJiZcbiAgICAgIChwLnBhcnQgYXMgeyBhcHByb3ZhbD86IHsgYXBwcm92ZWQ/OiBib29sZWFuIH0gfSkuYXBwcm92YWw/LmFwcHJvdmVkID09PVxuICAgICAgICB0cnVlXG4gICk7XG5cbiAgY29uc3QgZXhlY3V0ZWRBcHByb3ZhbHM6IHtcbiAgICB0b29sQ2FsbElkOiBzdHJpbmc7XG4gICAgb3V0cHV0OiB1bmtub3duO1xuICAgIGVycm9yPzogc3RyaW5nO1xuICB9W10gPSBbXTtcblxuICBpZiAoYXBwcm92ZWRQYXJ0cy5sZW5ndGggPiAwKSB7XG4gICAgLy8gQnVpbGQgbW9kZWwgbWVzc2FnZXMgcHJlLWV4ZWN1dGlvbiBmb3IgdGhlIHRvb2wgZXhlY3V0ZSBjb250ZXh0XG4gICAgY29uc3QgcHJlRXhlY01lc3NhZ2VzID0gW1xuICAgICAgLi4uc3lzdGVtTWVzc2FnZXMsXG4gICAgICAuLi4oYXdhaXQgY29udmVydFRvTW9kZWxNZXNzYWdlcyhcbiAgICAgICAgYXNzZW1ibGVVSU1lc3NhZ2VzKHtcbiAgICAgICAgICBtZXNzYWdlczogbWVzc2FnZXNSZXN1bHQuaXRlbXMsXG4gICAgICAgICAgcGFydHM6IGFsbFBhcnRzLFxuICAgICAgICAgIHVudGlsOiBldmVudC5jcmVhdGVkQXQsXG4gICAgICAgICAgaW5jbHVkZVF1ZXVlZDogdHJ1ZSxcbiAgICAgICAgICBleGNsdWRlU3ViVG9vbFBhcnRzOiB0cnVlLFxuICAgICAgICB9KVxuICAgICAgKSksXG4gICAgXTtcblxuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgYXBwcm92ZWRQYXJ0cy5tYXAoYXN5bmMgKGFwKSA9PiB7XG4gICAgICAgIGlmICghYXAucGFydC50eXBlLnN0YXJ0c1dpdGgoXCJ0b29sLVwiKSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBwYXJ0ID0gYXAucGFydCBhcyBFeHRyYWN0PFxuICAgICAgICAgIFVJTWVzc2FnZVtcInBhcnRzXCJdW251bWJlcl0sXG4gICAgICAgICAgeyB0eXBlOiBgdG9vbC0ke3N0cmluZ31gIH1cbiAgICAgICAgPjtcbiAgICAgICAgY29uc3QgdG9vbE5hbWUgPSBwYXJ0LnR5cGUucmVwbGFjZShcInRvb2wtXCIsIFwiXCIpO1xuICAgICAgICBjb25zdCB0b29sRGVmID0gcmF3VG9vbHNbdG9vbE5hbWVdO1xuXG4gICAgICAgIGlmICh0b29sRGVmPy5leGVjdXRlICYmIHBhcnQuaW5wdXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCB0b29sT3V0cHV0ID0gYXdhaXQgdG9vbERlZi5leGVjdXRlKHBhcnQuaW5wdXQsIHtcbiAgICAgICAgICAgICAgdG9vbENhbGxJZDogcGFydC50b29sQ2FsbElkLFxuICAgICAgICAgICAgICBtZXNzYWdlczogcHJlRXhlY01lc3NhZ2VzLFxuICAgICAgICAgICAgICBhYm9ydFNpZ25hbDogYWJvcnRDb250cm9sbGVyLnNpZ25hbCxcbiAgICAgICAgICAgICAgZXhwZXJpbWVudGFsX2NvbnRleHQ6IHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uLFxuICAgICAgICAgICAgICAgIHNhbmRib3gsXG4gICAgICAgICAgICAgICAgc3RvcmFnZSxcbiAgICAgICAgICAgICAgICBjb250ZXh0OiBldmVudC5jb250ZXh0LFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBwYXJ0LnN0YXRlID0gXCJvdXRwdXQtYXZhaWxhYmxlXCI7XG4gICAgICAgICAgICBwYXJ0Lm91dHB1dCA9IHRvb2xPdXRwdXQ7XG4gICAgICAgICAgICBleGVjdXRlZEFwcHJvdmFscy5wdXNoKHtcbiAgICAgICAgICAgICAgdG9vbENhbGxJZDogcGFydC50b29sQ2FsbElkLFxuICAgICAgICAgICAgICBvdXRwdXQ6IHRvb2xPdXRwdXQsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIHBhcnQuc3RhdGUgPSBcIm91dHB1dC1lcnJvclwiO1xuICAgICAgICAgICAgcGFydC5lcnJvclRleHQgPSBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVycik7XG4gICAgICAgICAgICBleGVjdXRlZEFwcHJvdmFscy5wdXNoKHtcbiAgICAgICAgICAgICAgdG9vbENhbGxJZDogcGFydC50b29sQ2FsbElkLFxuICAgICAgICAgICAgICBvdXRwdXQ6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgZXJyb3I6IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICBhd2FpdCBzdG9yYWdlLnBhcnQuc2V0KHsgLi4uYXAsIHBhcnQgfSk7XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIGNvbnN0IHVpTWVzc2FnZXMgPSBhc3NlbWJsZVVJTWVzc2FnZXMoe1xuICAgIG1lc3NhZ2VzOiBtZXNzYWdlc1Jlc3VsdC5pdGVtcyxcbiAgICBwYXJ0czogYWxsUGFydHMsXG4gICAgdW50aWw6IGV2ZW50LmNyZWF0ZWRBdCxcbiAgICBpbmNsdWRlUXVldWVkOiB0cnVlLFxuICAgIGV4Y2x1ZGVTdWJUb29sUGFydHM6IHRydWUsXG4gIH0pO1xuXG4gIGNvbnN0IG1vZGVsTWVzc2FnZXMgPSBbXG4gICAgLi4uc3lzdGVtTWVzc2FnZXMsXG4gICAgLi4uKGF3YWl0IGNvbnZlcnRUb01vZGVsTWVzc2FnZXModWlNZXNzYWdlcykpLFxuICBdO1xuXG4gIGNvbnN0IHByb21wdENhY2hpbmcgPSBhcHBseVByb21wdENhY2hpbmdUb01vZGVsUmVxdWVzdCh7XG4gICAgbW9kZWw6IHNlc3Npb24ubW9kZWwsXG4gICAgc2Vzc2lvbklkOiBpbnB1dC5zZXNzaW9uSWQsXG4gICAgbWVzc2FnZXM6IG1vZGVsTWVzc2FnZXMsXG4gIH0pO1xuXG4gIGNvbnN0IHVzYWdlU3RlcHM6IFN0ZXBVc2FnZVtdID0gW107XG4gIGxldCBpbnRlcm5hbFN0ZXBJbmRleCA9IDA7XG5cbiAgLy8gSW5qZWN0IG5lZWRzQXBwcm92YWwgb24gZXZlcnkgdG9vbCBcdTIwMTQgZGVsZWdhdGVzIHRvIHRoZSBhZ2VudCBjbGllbnQgdmlhIFJQQ1xuICBjb25zdCB0b29scyA9IE9iamVjdC5mcm9tRW50cmllcyhcbiAgICBPYmplY3QuZW50cmllcyhyYXdUb29scykubWFwKChbbmFtZSwgdF0pID0+IFtcbiAgICAgIG5hbWUsXG4gICAgICB7XG4gICAgICAgIC4uLnQsXG4gICAgICAgIG5lZWRzQXBwcm92YWw6IGFzeW5jIChcbiAgICAgICAgICB0b29sSW5wdXQ6IHVua25vd24sXG4gICAgICAgICAgb3B0czogeyB0b29sQ2FsbElkOiBzdHJpbmc7IG1lc3NhZ2VzOiB1bmtub3duW10gfVxuICAgICAgICApID0+IHtcbiAgICAgICAgICBjb25zdCByZXMgPSBhd2FpdCBpbnB1dC5ycGMoe1xuICAgICAgICAgICAgbWV0aG9kOiBcInRvb2xzLm5lZWRzQXBwcm92YWxcIixcbiAgICAgICAgICAgIHBhcmFtczoge1xuICAgICAgICAgICAgICB0b29sTmFtZTogbmFtZSxcbiAgICAgICAgICAgICAgaW5wdXQ6IHRvb2xJbnB1dCxcbiAgICAgICAgICAgICAgdG9vbENhbGxJZDogb3B0cy50b29sQ2FsbElkLFxuICAgICAgICAgICAgICBtZXNzYWdlczogb3B0cy5tZXNzYWdlcyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgaWYgKFwiZXJyb3JcIiBpbiByZXMpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgYHRvb2xzLm5lZWRzQXBwcm92YWwgUlBDIGZhaWxlZCBmb3IgJHtuYW1lfTogJHtyZXMuZXJyb3IubWVzc2FnZX1gXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gcmVzLnJlc3VsdCBhcyBib29sZWFuO1xuICAgICAgICB9LFxuICAgICAgfSxcbiAgICBdKVxuICApO1xuXG4gIGNvbnN0IHJlc3VsdCA9IHN0cmVhbVRleHQoe1xuICAgIG1lc3NhZ2VzOiBwcm9tcHRDYWNoaW5nLm1lc3NhZ2VzLFxuICAgIHRvb2xzLFxuICAgIG1vZGVsOiBzZXNzaW9uLm1vZGVsLFxuICAgIGFib3J0U2lnbmFsOiBhYm9ydENvbnRyb2xsZXIuc2lnbmFsLFxuICAgIGFjdGl2ZVRvb2xzOiBzZXNzaW9uLmFjdGl2ZVRvb2xzID8/IHVuZGVmaW5lZCxcbiAgICBwcm92aWRlck9wdGlvbnM6IHByb21wdENhY2hpbmcucHJvdmlkZXJPcHRpb25zLFxuICAgIHN0b3BXaGVuOiBzdGVwQ291bnRJcygxKSxcbiAgICB0ZW1wZXJhdHVyZTogc2Vzc2lvbi5nZW5lcmF0aW9uPy50ZW1wZXJhdHVyZSxcbiAgICB0b3BLOiBzZXNzaW9uLmdlbmVyYXRpb24/LnRvcEssXG4gICAgdG9wUDogc2Vzc2lvbi5nZW5lcmF0aW9uPy50b3BQLFxuICAgIGZyZXF1ZW5jeVBlbmFsdHk6IHNlc3Npb24uZ2VuZXJhdGlvbj8uZnJlcXVlbmN5UGVuYWx0eSxcbiAgICBwcmVzZW5jZVBlbmFsdHk6IHNlc3Npb24uZ2VuZXJhdGlvbj8ucHJlc2VuY2VQZW5hbHR5LFxuICAgIG1heE91dHB1dFRva2Vuczogc2Vzc2lvbi5nZW5lcmF0aW9uPy5tYXhPdXRwdXRUb2tlbnMsXG4gICAgaGVhZGVyczogc2Vzc2lvbi5nZW5lcmF0aW9uPy5oZWFkZXJzLFxuICAgIGV4cGVyaW1lbnRhbF9jb250ZXh0OiB7XG4gICAgICBzZXNzaW9uLFxuICAgICAgc2FuZGJveCxcbiAgICAgIHN0b3JhZ2UsXG4gICAgICBjb250ZXh0OiBldmVudC5jb250ZXh0LFxuICAgIH0sXG4gICAgb25TdGVwRmluaXNoOiAoeyB1c2FnZSB9KSA9PiB7XG4gICAgICBpZiAodXNhZ2UpIHtcbiAgICAgICAgdXNhZ2VTdGVwcy5wdXNoKHtcbiAgICAgICAgICBzdGVwSW5kZXg6IHN0ZXBJbmRleE9mZnNldCArIGludGVybmFsU3RlcEluZGV4LFxuICAgICAgICAgIG1vZGVsOiBzZXNzaW9uLm1vZGVsID8/IFwidW5rbm93blwiLFxuICAgICAgICAgIGlucHV0VG9rZW5zOiB1c2FnZS5pbnB1dFRva2VucyA/PyAwLFxuICAgICAgICAgIG91dHB1dFRva2VuczogdXNhZ2Uub3V0cHV0VG9rZW5zID8/IDAsXG4gICAgICAgICAgdG90YWxUb2tlbnM6IHVzYWdlLnRvdGFsVG9rZW5zID8/IDAsXG4gICAgICAgICAgY2FjaGVSZWFkVG9rZW5zOiB1c2FnZS5pbnB1dFRva2VuRGV0YWlscz8uY2FjaGVSZWFkVG9rZW5zID8/IDAsXG4gICAgICAgICAgY2FjaGVXcml0ZVRva2VuczogdXNhZ2UuaW5wdXRUb2tlbkRldGFpbHM/LmNhY2hlV3JpdGVUb2tlbnMgPz8gMCxcbiAgICAgICAgICByZWFzb25pbmdUb2tlbnM6IHVzYWdlLm91dHB1dFRva2VuRGV0YWlscz8ucmVhc29uaW5nVG9rZW5zID8/IDAsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgaW50ZXJuYWxTdGVwSW5kZXgrKztcbiAgICB9LFxuICB9KTtcblxuICBjb25zdCBzdGVwUGFydHM6IFVJTWVzc2FnZVtcInBhcnRzXCJdID0gW107XG4gIGxldCB3YXNBYm9ydGVkID0gZmFsc2U7XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBzdHJlYW0gPSBjcmVhdGVVSU1lc3NhZ2VTdHJlYW0oe1xuICAgICAgZXhlY3V0ZTogKHsgd3JpdGVyIH0pID0+IHtcbiAgICAgICAgc3RyZWFtV3JpdGVyUmVmLmN1cnJlbnQgPSAoZXZlbnQ6IHVua25vd24pID0+XG4gICAgICAgICAgd3JpdGVyLndyaXRlKGV2ZW50IGFzIFBhcmFtZXRlcnM8dHlwZW9mIHdyaXRlci53cml0ZT5bMF0pO1xuXG4gICAgICAgIC8vIFN0cmVhbSB0b29sIGV4ZWN1dGlvbiByZXN1bHRzIGZyb20gYXBwcm92ZWQgdG9vbHNcbiAgICAgICAgZm9yIChjb25zdCBlYSBvZiBleGVjdXRlZEFwcHJvdmFscykge1xuICAgICAgICAgIGlmIChlYS5lcnJvcikge1xuICAgICAgICAgICAgd3JpdGVyLndyaXRlKHtcbiAgICAgICAgICAgICAgdHlwZTogXCJ0b29sLW91dHB1dC1lcnJvclwiLFxuICAgICAgICAgICAgICB0b29sQ2FsbElkOiBlYS50b29sQ2FsbElkLFxuICAgICAgICAgICAgICBlcnJvclRleHQ6IGVhLmVycm9yLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHdyaXRlci53cml0ZSh7XG4gICAgICAgICAgICAgIHR5cGU6IFwidG9vbC1vdXRwdXQtYXZhaWxhYmxlXCIsXG4gICAgICAgICAgICAgIHRvb2xDYWxsSWQ6IGVhLnRvb2xDYWxsSWQsXG4gICAgICAgICAgICAgIG91dHB1dDogZWEub3V0cHV0LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gTWVyZ2UgdGhlIHN0cmVhbVRleHQgY29udGludWF0aW9uXG4gICAgICAgIHdyaXRlci5tZXJnZShcbiAgICAgICAgICByZXN1bHQudG9VSU1lc3NhZ2VTdHJlYW0oe1xuICAgICAgICAgICAgZ2VuZXJhdGVNZXNzYWdlSWQ6ICgpID0+IGFzc2lzdGFudE1lc3NhZ2VJZCxcbiAgICAgICAgICAgIG9uRmluaXNoOiAoeyBtZXNzYWdlcyB9KSA9PiB7XG4gICAgICAgICAgICAgIGZvciAoY29uc3QgbSBvZiBtZXNzYWdlcykge1xuICAgICAgICAgICAgICAgIGlmIChtLnJvbGUgPT09IFwiYXNzaXN0YW50XCIpIHtcbiAgICAgICAgICAgICAgICAgIHN0ZXBQYXJ0cy5wdXNoKC4uLm0ucGFydHMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGF3YWl0IHN0cmVhbS5waXBlVG8od3JpdGFibGUsIHsgcHJldmVudENsb3NlOiB0cnVlIH0pO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBpZiAoYWJvcnRDb250cm9sbGVyLnNpZ25hbC5hYm9ydGVkKSB7XG4gICAgICB3YXNBYm9ydGVkID0gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS5lcnJvcihcIltzdHJlYW1UZXh0U3RlcF0gc3RyZWFtIGVycm9yOlwiLCBlcnIpO1xuICAgICAgdGhyb3cgZXJyO1xuICAgIH1cbiAgfSBmaW5hbGx5IHtcbiAgICBwb2xsQ29udHJvbGxlci5hYm9ydCgpO1xuICB9XG5cbiAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgc3RlcFBhcnRzLm1hcChhc3luYyAodWlQYXJ0KSA9PiB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzdG9yYWdlLnBhcnQuc2V0KHtcbiAgICAgICAgaWQ6IGBwYXJ0XyR7dWxpZCgpfWAsXG4gICAgICAgIGluZGV4OiBuZXh0UGFydEluZGV4KyssXG4gICAgICAgIG1lc3NhZ2VJZDogYXNzaXN0YW50TWVzc2FnZUlkLFxuICAgICAgICBzZXNzaW9uSWQ6IGlucHV0LnNlc3Npb25JZCxcbiAgICAgICAgcGFydDogdWlQYXJ0LFxuICAgICAgfSk7XG4gICAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgcmVzdWx0O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9KVxuICApO1xuXG4gIGlmIChzZXRTdGFydGVkUHJvbWlzZSkge1xuICAgIGNvbnN0IHNldFN0YXJ0ZWRSZXN1bHQgPSBhd2FpdCBzZXRTdGFydGVkUHJvbWlzZTtcbiAgICBpZiAoc2V0U3RhcnRlZFJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICB0aHJvdyBzZXRTdGFydGVkUmVzdWx0O1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IG0gb2Ygc2V0U3RhcnRlZFJlc3VsdCA/PyBbXSkge1xuICAgICAgaWYgKG0gaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICB0aHJvdyBtO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHBlbmRpbmdBcHByb3ZhbHMgPSBzdGVwUGFydHNcbiAgICAuZmlsdGVyKFxuICAgICAgKHApOiBwIGlzIHR5cGVvZiBwICYgeyBhcHByb3ZhbDogeyBpZDogc3RyaW5nIH0gfSA9PlxuICAgICAgICBcInN0YXRlXCIgaW4gcCAmJlxuICAgICAgICBwLnN0YXRlID09PSBcImFwcHJvdmFsLXJlcXVlc3RlZFwiICYmXG4gICAgICAgIFwiYXBwcm92YWxcIiBpbiBwICYmXG4gICAgICAgICEhKHAgYXMgeyBhcHByb3ZhbD86IHsgaWQ6IHN0cmluZyB9IH0pLmFwcHJvdmFsPy5pZFxuICAgIClcbiAgICAubWFwKChwKSA9PiAoe1xuICAgICAgYXBwcm92YWxJZDogcC5hcHByb3ZhbC5pZCxcbiAgICAgIHRvb2xOYW1lOiBcInR5cGVcIiBpbiBwID8gU3RyaW5nKHAudHlwZSkucmVwbGFjZShcInRvb2wtXCIsIFwiXCIpIDogXCJ1bmtub3duXCIsXG4gICAgfSkpO1xuXG4gIGNvbnN0IGZpbmFsRmluaXNoUmVhc29uID0gd2FzQWJvcnRlZFxuICAgID8gKFwic3RvcFwiIGFzIEZpbmlzaFJlYXNvbilcbiAgICA6IGF3YWl0IHJlc3VsdC5maW5pc2hSZWFzb247XG5cbiAgcmV0dXJuIHtcbiAgICBmaW5pc2hSZWFzb246IGZpbmFsRmluaXNoUmVhc29uLFxuICAgIGxhc3RQYXJ0SW5kZXg6IG5leHRQYXJ0SW5kZXgsXG4gICAgdXNhZ2VTdGVwcyxcbiAgICBwZW5kaW5nQXBwcm92YWxzLFxuICAgIG1heFN0ZXBzOiBzZXNzaW9uLmdlbmVyYXRpb24/Lm1heFN0ZXBzLFxuICB9O1xufVxuIiwgImltcG9ydCB0eXBlIHsgU2tpbGxzRGlyIH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuLyoqXG4gKiBQYXJzZWQgZnJvbnRtYXR0ZXIgZnJvbSBhIFNLSUxMLm1kIGZpbGUuXG4gKi9cbmV4cG9ydCB0eXBlIFNraWxsRnJvbnRtYXR0ZXIgPSB7XG4gIG5hbWU6IHN0cmluZztcbiAgZGVzY3JpcHRpb246IHN0cmluZztcbn07XG5cbi8qKlxuICogUGFyc2VzIFlBTUwgZnJvbnRtYXR0ZXIgZnJvbSBhIFNLSUxMLm1kIGZpbGUgY29udGVudC5cbiAqIEZyb250bWF0dGVyIG11c3QgYmUgYXQgdGhlIHN0YXJ0IG9mIHRoZSBmaWxlLCBkZWxpbWl0ZWQgYnkgYC0tLWAgbWFya2Vycy5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgbWFya2Rvd25cbiAqIC0tLVxuICogbmFtZTogY3N2XG4gKiBkZXNjcmlwdGlvbjogQW5hbHl6ZSBDU1YgZGF0YVxuICogLS0tXG4gKiAjIENTViBTa2lsbFxuICogLi4uXG4gKiBgYGBcbiAqXG4gKiBAcmV0dXJucyBQYXJzZWQgbmFtZSBhbmQgZGVzY3JpcHRpb24sIG9yIG51bGwgaWYgZnJvbnRtYXR0ZXIgaXMgbWlzc2luZy9pbnZhbGlkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVNraWxsRnJvbnRtYXR0ZXIoXG4gIGNvbnRlbnQ6IHN0cmluZ1xuKTogU2tpbGxGcm9udG1hdHRlciB8IG51bGwge1xuICBjb25zdCB0cmltbWVkID0gY29udGVudC50cmltKCk7XG5cbiAgaWYgKCF0cmltbWVkLnN0YXJ0c1dpdGgoXCItLS1cIikpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IGVuZE1hcmtlckluZGV4ID0gdHJpbW1lZC5pbmRleE9mKFwiLS0tXCIsIDMpO1xuICBpZiAoZW5kTWFya2VySW5kZXggPT09IC0xKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCBmcm9udG1hdHRlckJsb2NrID0gdHJpbW1lZC5zbGljZSgzLCBlbmRNYXJrZXJJbmRleCkudHJpbSgpO1xuICBjb25zdCBwYXJzZWQgPSBwYXJzZVNpbXBsZVlhbWwoZnJvbnRtYXR0ZXJCbG9jayk7XG5cbiAgaWYgKCEocGFyc2VkLm5hbWUgJiYgcGFyc2VkLmRlc2NyaXB0aW9uKSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiBTdHJpbmcocGFyc2VkLm5hbWUpLFxuICAgIGRlc2NyaXB0aW9uOiBTdHJpbmcocGFyc2VkLmRlc2NyaXB0aW9uKSxcbiAgfTtcbn1cblxuLyoqXG4gKiBQYXJzZXMgc2ltcGxlIFlBTUwga2V5LXZhbHVlIHBhaXJzIChzaW5nbGUtbGluZSB2YWx1ZXMgb25seSkuXG4gKiBUaGlzIGF2b2lkcyBhZGRpbmcgYSBmdWxsIFlBTUwgcGFyc2VyIGRlcGVuZGVuY3kgZm9yIGJhc2ljIGZyb250bWF0dGVyLlxuICovXG5mdW5jdGlvbiBwYXJzZVNpbXBsZVlhbWwoeWFtbDogc3RyaW5nKTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB7XG4gIGNvbnN0IHJlc3VsdDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuXG4gIGZvciAoY29uc3QgbGluZSBvZiB5YW1sLnNwbGl0KFwiXFxuXCIpKSB7XG4gICAgY29uc3QgdHJpbW1lZExpbmUgPSBsaW5lLnRyaW0oKTtcbiAgICBpZiAoIXRyaW1tZWRMaW5lIHx8IHRyaW1tZWRMaW5lLnN0YXJ0c1dpdGgoXCIjXCIpKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBjb25zdCBjb2xvbkluZGV4ID0gdHJpbW1lZExpbmUuaW5kZXhPZihcIjpcIik7XG4gICAgaWYgKGNvbG9uSW5kZXggPT09IC0xKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBjb25zdCBrZXkgPSB0cmltbWVkTGluZS5zbGljZSgwLCBjb2xvbkluZGV4KS50cmltKCk7XG4gICAgbGV0IHZhbHVlID0gdHJpbW1lZExpbmUuc2xpY2UoY29sb25JbmRleCArIDEpLnRyaW0oKTtcblxuICAgIC8vIFJlbW92ZSBzdXJyb3VuZGluZyBxdW90ZXMgaWYgcHJlc2VudFxuICAgIGlmIChcbiAgICAgICh2YWx1ZS5zdGFydHNXaXRoKCdcIicpICYmIHZhbHVlLmVuZHNXaXRoKCdcIicpKSB8fFxuICAgICAgKHZhbHVlLnN0YXJ0c1dpdGgoXCInXCIpICYmIHZhbHVlLmVuZHNXaXRoKFwiJ1wiKSlcbiAgICApIHtcbiAgICAgIHZhbHVlID0gdmFsdWUuc2xpY2UoMSwgLTEpO1xuICAgIH1cblxuICAgIGlmIChrZXkpIHtcbiAgICAgIHJlc3VsdFtrZXldID0gdmFsdWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBOb3JtYWxpemVzIHNraWxsc0RpciB0byBhbiBhcnJheSBvZiBzdHJpbmdzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbm9ybWFsaXplU2tpbGxzRGlycyhza2lsbHNEaXI/OiBTa2lsbHNEaXIpOiBzdHJpbmdbXSB7XG4gIGlmICghc2tpbGxzRGlyKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG4gIHJldHVybiBBcnJheS5pc0FycmF5KHNraWxsc0RpcikgPyBza2lsbHNEaXIgOiBbc2tpbGxzRGlyXTtcbn1cbiIsICJpbXBvcnQgdHlwZSB7IFNhbmRib3ggfSBmcm9tIFwiLi4vc2FuZGJveFwiO1xuaW1wb3J0IHsgcGFyc2VTa2lsbEZyb250bWF0dGVyIH0gZnJvbSBcIi4vcGFyc2VyXCI7XG5pbXBvcnQgdHlwZSB7IFNraWxsU3VtbWFyeSB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbi8qKlxuICogRGlzY292ZXJzIHNraWxscyBmcm9tIGRpcmVjdG9yaWVzIGluc2lkZSB0aGUgc2FuZGJveCBieSBmaW5kaW5nIGFuZCBwYXJzaW5nIFNLSUxMLm1kIGZpbGVzLlxuICogU2NhbnMgZWFjaCBkaXJlY3RvcnkgZm9yIHN1YmRpcmVjdG9yaWVzIGNvbnRhaW5pbmcgU0tJTEwubWQsIGV4dHJhY3RzIGZyb250bWF0dGVyIG1ldGFkYXRhLFxuICogYW5kIHJldHVybnMgc3VtbWFyaWVzIGZvciB1c2UgaW4gdGhlIHN5c3RlbSBwcm9tcHQuXG4gKlxuICogQHJldHVybnMgQXJyYXkgb2Ygc2tpbGwgc3VtbWFyaWVzIChkZWR1cGxpY2F0ZWQgYnkgbmFtZSwgZmlyc3Qgb2NjdXJyZW5jZSB3aW5zKVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZGlzY292ZXJTa2lsbHNJblNhbmRib3gob3B0czoge1xuICBzYW5kYm94OiBTYW5kYm94O1xuICBza2lsbHNEaXJzOiBzdHJpbmdbXTtcbiAgZGVidWc/OiBib29sZWFuO1xufSk6IFByb21pc2U8U2tpbGxTdW1tYXJ5W10+IHtcbiAgY29uc3QgeyBzYW5kYm94LCBza2lsbHNEaXJzLCBkZWJ1ZyB9ID0gb3B0cztcblxuICBjb25zdCBzdW1tYXJpZXM6IFNraWxsU3VtbWFyeVtdID0gW107XG4gIGNvbnN0IHNlZW5OYW1lcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4gIGZvciAoY29uc3Qgc2tpbGxzRGlyIG9mIHNraWxsc0RpcnMpIHtcbiAgICBjb25zdCBkaXJTdW1tYXJpZXMgPSBhd2FpdCBkaXNjb3ZlclNraWxsc0luRGlyZWN0b3J5KHtcbiAgICAgIHNhbmRib3gsXG4gICAgICBza2lsbHNEaXIsXG4gICAgICBkZWJ1ZyxcbiAgICB9KTtcblxuICAgIGZvciAoY29uc3Qgc3VtbWFyeSBvZiBkaXJTdW1tYXJpZXMpIHtcbiAgICAgIGlmICghc2Vlbk5hbWVzLmhhcyhzdW1tYXJ5Lm5hbWUpKSB7XG4gICAgICAgIHNlZW5OYW1lcy5hZGQoc3VtbWFyeS5uYW1lKTtcbiAgICAgICAgc3VtbWFyaWVzLnB1c2goc3VtbWFyeSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHN1bW1hcmllcztcbn1cblxuYXN5bmMgZnVuY3Rpb24gZGlzY292ZXJTa2lsbHNJbkRpcmVjdG9yeShvcHRzOiB7XG4gIHNhbmRib3g6IFNhbmRib3g7XG4gIHNraWxsc0Rpcjogc3RyaW5nO1xuICBkZWJ1Zz86IGJvb2xlYW47XG59KTogUHJvbWlzZTxTa2lsbFN1bW1hcnlbXT4ge1xuICBjb25zdCB7IHNhbmRib3gsIHNraWxsc0RpciwgZGVidWcgfSA9IG9wdHM7XG4gIGNvbnN0IHNraWxsUGF0aHMgPSBhd2FpdCBmaW5kU2tpbGxGaWxlcyh7IHNhbmRib3gsIHNraWxsc0RpciwgZGVidWcgfSk7XG5cbiAgaWYgKHNraWxsUGF0aHMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgY29uc3Qgc3VtbWFyaWVzOiBTa2lsbFN1bW1hcnlbXSA9IFtdO1xuXG4gIGZvciAoY29uc3Qgc2tpbGxNZFBhdGggb2Ygc2tpbGxQYXRocykge1xuICAgIGNvbnN0IHN1bW1hcnkgPSBhd2FpdCBwYXJzZVNraWxsRmlsZSh7IHNhbmRib3gsIHNraWxsTWRQYXRoLCBkZWJ1ZyB9KTtcbiAgICBpZiAoc3VtbWFyeSkge1xuICAgICAgc3VtbWFyaWVzLnB1c2goc3VtbWFyeSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHN1bW1hcmllcztcbn1cblxuYXN5bmMgZnVuY3Rpb24gZmluZFNraWxsRmlsZXMob3B0czoge1xuICBzYW5kYm94OiBTYW5kYm94O1xuICBza2lsbHNEaXI6IHN0cmluZztcbiAgZGVidWc/OiBib29sZWFuO1xufSk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgY29uc3QgeyBzYW5kYm94LCBza2lsbHNEaXIsIGRlYnVnIH0gPSBvcHRzO1xuXG4gIGNvbnN0IGV4ZWNSZXN1bHQgPSBhd2FpdCBzYW5kYm94LmV4ZWMoe1xuICAgIGNvbW1hbmQ6IFwiZmluZFwiLFxuICAgIGFyZ3M6IFtza2lsbHNEaXIsIFwiLW5hbWVcIiwgXCJTS0lMTC5tZFwiLCBcIi10eXBlXCIsIFwiZlwiXSxcbiAgfSk7XG5cbiAgaWYgKGV4ZWNSZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgIGlmIChkZWJ1Zykge1xuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBgW2Rpc2NvdmVyXSBGYWlsZWQgdG8gc2NhbiBza2lsbHMgZGlyZWN0b3J5IFwiJHtza2lsbHNEaXJ9XCI6ICR7ZXhlY1Jlc3VsdC5tZXNzYWdlfWBcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIGNvbnN0IHsgc3Rkb3V0LCBzdGRlcnIsIGV4aXRDb2RlIH0gPSBhd2FpdCBleGVjUmVzdWx0LnJlc3VsdDtcbiAgaWYgKGRlYnVnKSB7XG4gICAgY29uc29sZS5sb2coXG4gICAgICBgW2Rpc2NvdmVyXSBmaW5kIHJlc3VsdDogZXhpdENvZGU9JHtleGl0Q29kZX0sIHN0ZG91dD1cIiR7c3Rkb3V0LnRyaW0oKX1cIiwgc3RkZXJyPVwiJHtzdGRlcnIudHJpbSgpfVwiYFxuICAgICk7XG4gIH1cblxuICBpZiAoZXhpdENvZGUgIT09IDApIHtcbiAgICBpZiAoZGVidWcpIHtcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgYFtkaXNjb3Zlcl0gU2tpbGxzIGRpcmVjdG9yeSBub3QgZm91bmQgb3IgaW5hY2Nlc3NpYmxlOiAke3NraWxsc0Rpcn1gXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gW107XG4gIH1cblxuICBjb25zdCBwYXRocyA9IHN0ZG91dFxuICAgIC50cmltKClcbiAgICAuc3BsaXQoXCJcXG5cIilcbiAgICAuZmlsdGVyKChwKSA9PiBwLmxlbmd0aCA+IDApO1xuICBpZiAoZGVidWcpIHtcbiAgICBjb25zb2xlLmxvZyhcIltkaXNjb3Zlcl0gRm91bmQgc2tpbGwgcGF0aHM6XCIsIHBhdGhzKTtcbiAgfVxuICByZXR1cm4gcGF0aHM7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHBhcnNlU2tpbGxGaWxlKG9wdHM6IHtcbiAgc2FuZGJveDogU2FuZGJveDtcbiAgc2tpbGxNZFBhdGg6IHN0cmluZztcbiAgZGVidWc/OiBib29sZWFuO1xufSk6IFByb21pc2U8U2tpbGxTdW1tYXJ5IHwgbnVsbD4ge1xuICBjb25zdCB7IHNhbmRib3gsIHNraWxsTWRQYXRoLCBkZWJ1ZyB9ID0gb3B0cztcbiAgY29uc3QgZXhlY1Jlc3VsdCA9IGF3YWl0IHNhbmRib3guZXhlYyh7XG4gICAgY29tbWFuZDogXCJjYXRcIixcbiAgICBhcmdzOiBbc2tpbGxNZFBhdGhdLFxuICB9KTtcblxuICBpZiAoZXhlY1Jlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgaWYgKGRlYnVnKSB7XG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgIGBbZGlzY292ZXJdIEZhaWxlZCB0byByZWFkIHNraWxsIGZpbGUgXCIke3NraWxsTWRQYXRofVwiOiAke2V4ZWNSZXN1bHQubWVzc2FnZX1gXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IHsgc3Rkb3V0LCBleGl0Q29kZSB9ID0gYXdhaXQgZXhlY1Jlc3VsdC5yZXN1bHQ7XG5cbiAgaWYgKGV4aXRDb2RlICE9PSAwKSB7XG4gICAgaWYgKGRlYnVnKSB7XG4gICAgICBjb25zb2xlLndhcm4oYFtkaXNjb3Zlcl0gQ291bGQgbm90IHJlYWQgc2tpbGwgZmlsZTogJHtza2lsbE1kUGF0aH1gKTtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCBwYXJzZWQgPSBwYXJzZVNraWxsRnJvbnRtYXR0ZXIoc3Rkb3V0KTtcblxuICBpZiAoIXBhcnNlZCkge1xuICAgIGlmIChkZWJ1Zykge1xuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBgW2Rpc2NvdmVyXSBJbnZhbGlkIG9yIG1pc3NpbmcgZnJvbnRtYXR0ZXIgaW46ICR7c2tpbGxNZFBhdGh9YFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIG5hbWU6IHBhcnNlZC5uYW1lLFxuICAgIGRlc2NyaXB0aW9uOiBwYXJzZWQuZGVzY3JpcHRpb24sXG4gICAgc2tpbGxNZFBhdGgsXG4gIH07XG59XG4iLCAiaW1wb3J0IHsganNvblNjaGVtYSwgdHlwZSBUb29sU2V0LCB0b29sIH0gZnJvbSBcImFpXCI7XG5pbXBvcnQgeyB6IH0gZnJvbSBcInpvZFwiO1xuaW1wb3J0IHR5cGUgeyBBZ2VudElucHV0LCBBZ2VudE1lc3NhZ2VJbnB1dCB9IGZyb20gXCIuLi9hZ2VudC13b3JrZmxvd1wiO1xuaW1wb3J0IHR5cGUgeyBScGNQYXlsb2FkLCBScGNSZXN1bHQgfSBmcm9tIFwiLi4vY2xpZW50XCI7XG5pbXBvcnQgdHlwZSB7IFNhbmRib3ggfSBmcm9tIFwiLi4vc2FuZGJveFwiO1xuaW1wb3J0IHsgREVGQVVMVF9XQUlUX1VOVElMIH0gZnJvbSBcIi4uL3NhbmRib3gvcHJvY2Vzcy1tYW5hZ2VyXCI7XG5pbXBvcnQgdHlwZSB7IFNhbmRib3hSZWNvcmQsIFNlc3Npb24sIFN0b3JhZ2UgfSBmcm9tIFwiLi4vc3RvcmFnZVwiO1xuaW1wb3J0IHsgY3JlYXRlSmF2YVNjcmlwdFRvb2wsIHR5cGUgT25TdWJUb29sQ2FsbCB9IGZyb20gXCIuL2phdmFzY3JpcHRcIjtcblxuY29uc3QgQUdFTlRfUFJPVE9DT0xfVkVSU0lPTiA9IFwidjFcIjtcblxuZnVuY3Rpb24gZm9ybWF0RmlsZVNpemUoYnl0ZXM6IG51bWJlcik6IHN0cmluZyB7XG4gIGlmIChieXRlcyA8IDEwMjQpIHtcbiAgICByZXR1cm4gYCR7Ynl0ZXN9YDtcbiAgfVxuICBpZiAoYnl0ZXMgPCAxMDI0ICogMTAyNCkge1xuICAgIHJldHVybiBgJHsoYnl0ZXMgLyAxMDI0KS50b0ZpeGVkKDEpfUtgO1xuICB9XG4gIGlmIChieXRlcyA8IDEwMjQgKiAxMDI0ICogMTAyNCkge1xuICAgIHJldHVybiBgJHsoYnl0ZXMgLyAoMTAyNCAqIDEwMjQpKS50b0ZpeGVkKDEpfU1gO1xuICB9XG4gIHJldHVybiBgJHsoYnl0ZXMgLyAoMTAyNCAqIDEwMjQgKiAxMDI0KSkudG9GaXhlZCgxKX1HYDtcbn1cblxudHlwZSBJbnRlcm5hbFRvb2xDb250ZXh0ID0ge1xuICBpbnB1dDogQWdlbnRJbnB1dDtcbiAgZXZlbnQ6IEFnZW50TWVzc2FnZUlucHV0O1xuICBzYW5kYm94OiBTYW5kYm94O1xuICBzZXNzaW9uOiBTZXNzaW9uO1xuICBzYW5kYm94UmVjb3JkOiBTYW5kYm94UmVjb3JkO1xuICBhcGlUb29sc01ldGFkYXRhOiB7XG4gICAgbmFtZTogc3RyaW5nO1xuICAgIGRlc2NyaXB0aW9uPzogc3RyaW5nO1xuICAgIGlucHV0U2NoZW1hPzogdW5rbm93bjtcbiAgfVtdO1xuICBvblN1YlRvb2xDYWxsPzogT25TdWJUb29sQ2FsbDtcbn07XG5cbmV4cG9ydCB0eXBlIFRvb2xDb250ZXh0PFRDb250ZXh0ID0gUmVjb3JkPHN0cmluZywgdW5rbm93bj4+ID0ge1xuICBzZXNzaW9uOiBTZXNzaW9uO1xuICBzYW5kYm94OiBTYW5kYm94O1xuICBzdG9yYWdlOiBTdG9yYWdlO1xuICBjb250ZXh0OiBUQ29udGV4dDtcbn07XG5cbmV4cG9ydCBjb25zdCBidWlsdEluVG9vbHMgPSB7XG4gIFJlYWQ6IHRvb2woe1xuICAgIGRlc2NyaXB0aW9uOlxuICAgICAgXCJSZWFkcyBhIGZpbGUgYW5kIHJldHVybnMgaXRzIGNvbnRlbnRzIHdpdGggbWV0YWRhdGEuIEZvciBmaWxlcyBvdmVyIDIwMCBsaW5lcywgYXV0b21hdGljYWxseSBzaG93cyBmaXJzdCAxMDAgbGluZXMgdW5sZXNzIGEgc3BlY2lmaWMgbGluZSByYW5nZSBpcyBwcm92aWRlZC4gVXNlIHN0YXJ0TGluZSBhbmQgZW5kTGluZSBwYXJhbWV0ZXJzIHRvIHJlYWQgc3BlY2lmaWMgcG9ydGlvbnMgb2YgbGFyZ2UgZmlsZXMuXCIsXG4gICAgaW5wdXRTY2hlbWE6IHoub2JqZWN0KHtcbiAgICAgIHBhdGg6IHouc3RyaW5nKCkuZGVzY3JpYmUoXCJQYXRoIHRvIHRoZSBmaWxlIHJlbGF0aXZlIHRvIHdvcmtzcGFjZSByb290XCIpLFxuICAgICAgc3RhcnRMaW5lOiB6XG4gICAgICAgIC5udW1iZXIoKVxuICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgXCJTdGFydGluZyBsaW5lIG51bWJlciAoMS1pbmRleGVkKS4gSWYgcHJvdmlkZWQgd2l0aCBlbmRMaW5lLCByZWFkcyBleGFjdCByYW5nZSByZWdhcmRsZXNzIG9mIGZpbGUgc2l6ZS5cIlxuICAgICAgICApLFxuICAgICAgZW5kTGluZTogelxuICAgICAgICAubnVtYmVyKClcbiAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgLmRlc2NyaWJlKFxuICAgICAgICAgIFwiRW5kaW5nIGxpbmUgbnVtYmVyICgxLWluZGV4ZWQsIGluY2x1c2l2ZSkuIElmIHByb3ZpZGVkIHdpdGggc3RhcnRMaW5lLCByZWFkcyBleGFjdCByYW5nZSByZWdhcmRsZXNzIG9mIGZpbGUgc2l6ZS5cIlxuICAgICAgICApLFxuICAgIH0pLFxuICAgIG91dHB1dFNjaGVtYTogei5vYmplY3Qoe1xuICAgICAgY29udGVudDogei5zdHJpbmcoKS5kZXNjcmliZShcIkZpbGUgY29udGVudFwiKSxcbiAgICAgIG1ldGFkYXRhOiB6Lm9iamVjdCh7XG4gICAgICAgIHRvdGFsTGluZXM6IHoubnVtYmVyKCkuZGVzY3JpYmUoXCJUb3RhbCBudW1iZXIgb2YgbGluZXMgaW4gdGhlIGZpbGVcIiksXG4gICAgICAgIGxpbmVzU2hvd246IHpcbiAgICAgICAgICAubnVtYmVyKClcbiAgICAgICAgICAuZGVzY3JpYmUoXCJOdW1iZXIgb2YgbGluZXMgaW5jbHVkZWQgaW4gdGhpcyByZXNwb25zZVwiKSxcbiAgICAgICAgc3RhcnRMaW5lOiB6Lm51bWJlcigpLmRlc2NyaWJlKFwiRmlyc3QgbGluZSBudW1iZXIgc2hvd24gKDEtaW5kZXhlZClcIiksXG4gICAgICAgIGVuZExpbmU6IHoubnVtYmVyKCkuZGVzY3JpYmUoXCJMYXN0IGxpbmUgbnVtYmVyIHNob3duICgxLWluZGV4ZWQpXCIpLFxuICAgICAgICBpc1BhZ2luYXRlZDogelxuICAgICAgICAgIC5ib29sZWFuKClcbiAgICAgICAgICAuZGVzY3JpYmUoXCJXaGV0aGVyIHRoaXMgaXMgYSBwYXJ0aWFsIHZpZXcgb2YgdGhlIGZpbGVcIiksXG4gICAgICAgIGZpbGVTaXplOiB6XG4gICAgICAgICAgLnN0cmluZygpXG4gICAgICAgICAgLmRlc2NyaWJlKFwiSHVtYW4tcmVhZGFibGUgZmlsZSBzaXplIChlLmcuLCAnMi41SycsICcxLjJNJylcIiksXG4gICAgICAgIHBhdGg6IHpcbiAgICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgICAuZGVzY3JpYmUoXCJQYXRoIHRvIHRoZSBmaWxlIHJlbGF0aXZlIHRvIHdvcmtzcGFjZSByb290XCIpLFxuICAgICAgfSksXG4gICAgfSksXG4gIH0pLFxuICBHcmVwOiB0b29sKHtcbiAgICBkZXNjcmlwdGlvbjpcbiAgICAgIFwiU2VhcmNoIGZvciBwYXR0ZXJucyBpbiBmaWxlcyB1c2luZyByaXBncmVwLiBVc2UgdGhpcyB0byBmaW5kIGNvZGUgcGF0dGVybnMsIGZ1bmN0aW9uIGRlZmluaXRpb25zLCBpbXBvcnRzLCBldGMuXCIsXG4gICAgaW5wdXRTY2hlbWE6IHoub2JqZWN0KHtcbiAgICAgIHBhdHRlcm46IHpcbiAgICAgICAgLnN0cmluZygpXG4gICAgICAgIC5kZXNjcmliZShcIlJlZ2V4IHBhdHRlcm4gdG8gc2VhcmNoIGZvciAocmlwZ3JlcCBzeW50YXgpXCIpLFxuICAgICAgcGF0aDogelxuICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgLmRlc2NyaWJlKFxuICAgICAgICAgIFwiUGF0aCB0byBzZWFyY2ggaW4gKGRlZmF1bHRzIHRvIHdvcmtzcGFjZSByb290KS4gQ2FuIGJlIGEgZmlsZSBvciBkaXJlY3RvcnkuXCJcbiAgICAgICAgKSxcbiAgICAgIGZpbGVUeXBlOiB6XG4gICAgICAgIC5zdHJpbmcoKVxuICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgXCJGaWxlIHR5cGUgdG8gZmlsdGVyIGJ5IChlLmcuLCAndHMnLCAnanMnLCAncHknLCAnbWQnKS4gVXNlcyByaXBncmVwJ3MgYnVpbHQtaW4gdHlwZSBmaWx0ZXJzLlwiXG4gICAgICAgICksXG4gICAgICBnbG9iOiB6XG4gICAgICAgIC5zdHJpbmcoKVxuICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgXCJHbG9iIHBhdHRlcm4gdG8gZmlsdGVyIGZpbGVzIChlLmcuLCAnKi50c3gnLCAnc3JjLyoqLyoudHMnKVwiXG4gICAgICAgICksXG4gICAgICBjYXNlU2Vuc2l0aXZlOiB6XG4gICAgICAgIC5ib29sZWFuKClcbiAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgLmRlZmF1bHQodHJ1ZSlcbiAgICAgICAgLmRlc2NyaWJlKFwiV2hldGhlciBzZWFyY2ggaXMgY2FzZS1zZW5zaXRpdmUgKGRlZmF1bHQ6IHRydWUpXCIpLFxuICAgICAgY29udGV4dExpbmVzOiB6XG4gICAgICAgIC5udW1iZXIoKVxuICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgXCJOdW1iZXIgb2YgY29udGV4dCBsaW5lcyB0byBzaG93IGJlZm9yZSBhbmQgYWZ0ZXIgZWFjaCBtYXRjaFwiXG4gICAgICAgICksXG4gICAgICBtYXhDb3VudDogelxuICAgICAgICAubnVtYmVyKClcbiAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgLmRlc2NyaWJlKFxuICAgICAgICAgIFwiTWF4aW11bSBudW1iZXIgb2YgbWF0Y2hlcyBwZXIgZmlsZSAodXNlZnVsIGZvciBsaW1pdGluZyBvdXRwdXQpXCJcbiAgICAgICAgKSxcbiAgICAgIGZpbGVzV2l0aE1hdGNoZXM6IHpcbiAgICAgICAgLmJvb2xlYW4oKVxuICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAuZGVmYXVsdChmYWxzZSlcbiAgICAgICAgLmRlc2NyaWJlKFxuICAgICAgICAgIFwiT25seSBzaG93IGZpbGUgcGF0aHMgdGhhdCBjb250YWluIG1hdGNoZXMsIG5vdCB0aGUgbWF0Y2hpbmcgbGluZXMgdGhlbXNlbHZlc1wiXG4gICAgICAgICksXG4gICAgfSksXG4gICAgb3V0cHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4gICAgICBtYXRjaGVzOiB6XG4gICAgICAgIC5zdHJpbmcoKVxuICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgXCJTZWFyY2ggcmVzdWx0cyB3aXRoIGZpbGUgcGF0aHMsIGxpbmUgbnVtYmVycywgYW5kIG1hdGNoaW5nIGNvbnRlbnRcIlxuICAgICAgICApLFxuICAgICAgc3VtbWFyeTogei5vYmplY3Qoe1xuICAgICAgICBtYXRjaENvdW50OiB6Lm51bWJlcigpLmRlc2NyaWJlKFwiTnVtYmVyIG9mIG1hdGNoZXMgZm91bmRcIiksXG4gICAgICAgIGZpbGVDb3VudDogei5udW1iZXIoKS5kZXNjcmliZShcIk51bWJlciBvZiBmaWxlcyBjb250YWluaW5nIG1hdGNoZXNcIiksXG4gICAgICAgIHNlYXJjaFBhdGg6IHouc3RyaW5nKCkuZGVzY3JpYmUoXCJQYXRoIHRoYXQgd2FzIHNlYXJjaGVkXCIpLFxuICAgICAgICBwYXR0ZXJuOiB6LnN0cmluZygpLmRlc2NyaWJlKFwiUGF0dGVybiB0aGF0IHdhcyBzZWFyY2hlZCBmb3JcIiksXG4gICAgICB9KSxcbiAgICB9KSxcbiAgfSksXG4gIExpc3Q6IHRvb2woe1xuICAgIGRlc2NyaXB0aW9uOlxuICAgICAgXCJSZWN1cnNpdmVseSBsaXN0IGRpcmVjdG9yeSBjb250ZW50cy4gVXNlIHRoaXMgdG8gdW5kZXJzdGFuZCB0aGUgY29kZWJhc2Ugc3RydWN0dXJlLCBmaW5kIGZpbGVzLCBvciBleHBsb3JlIGRpcmVjdG9yaWVzLiBDb250cm9sIGRlcHRoIHRvIGJhbGFuY2UgZGV0YWlsIHZzLiBvdmVydmlldy4gRGVwdGggMSBzaG93cyBpbW1lZGlhdGUgY2hpbGRyZW4sIGRlcHRoIDIgaW5jbHVkZXMgc3ViZGlyZWN0b3JpZXMsIGV0Yy5cIixcbiAgICBpbnB1dFNjaGVtYTogei5vYmplY3Qoe1xuICAgICAgcGF0aDogelxuICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgLmRlc2NyaWJlKFwiUGF0aCB0byBsaXN0IChkZWZhdWx0cyB0byB3b3Jrc3BhY2Ugcm9vdClcIiksXG4gICAgICBkZXB0aDogelxuICAgICAgICAubnVtYmVyKClcbiAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgLmRlc2NyaWJlKFxuICAgICAgICAgIFwiTWF4aW11bSBkZXB0aCB0byB0cmF2ZXJzZS4gQ2hvb3NlIGJhc2VkIG9uIGNvbnRleHQ6IDEtMiBmb3IgcXVpY2sgb3ZlcnZpZXcsIDMtNCBmb3IgZGV0YWlsZWQgZXhwbG9yYXRpb24sIDUrIGZvciBjb21wcmVoZW5zaXZlIG1hcHBpbmdcIlxuICAgICAgICApLFxuICAgICAgaW5jbHVkZUhpZGRlbjogelxuICAgICAgICAuYm9vbGVhbigpXG4gICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgIC5kZWZhdWx0KGZhbHNlKVxuICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgXCJJbmNsdWRlIGhpZGRlbiBmaWxlcyBhbmQgZGlyZWN0b3JpZXMgKHRob3NlIHN0YXJ0aW5nIHdpdGggJy4nKVwiXG4gICAgICAgICksXG4gICAgICBmaWxlc09ubHk6IHpcbiAgICAgICAgLmJvb2xlYW4oKVxuICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAuZGVmYXVsdChmYWxzZSlcbiAgICAgICAgLmRlc2NyaWJlKFwiT25seSBzaG93IGZpbGVzLCBub3QgZGlyZWN0b3JpZXNcIiksXG4gICAgICBwYXR0ZXJuOiB6XG4gICAgICAgIC5zdHJpbmcoKVxuICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAuZGVzY3JpYmUoXCJHbG9iIHBhdHRlcm4gdG8gZmlsdGVyIHJlc3VsdHMgKGUuZy4sICcqLnRzJywgJyp0ZXN0KicpXCIpLFxuICAgIH0pLFxuICAgIG91dHB1dFNjaGVtYTogei5vYmplY3Qoe1xuICAgICAgbGlzdGluZzogelxuICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgLmRlc2NyaWJlKFxuICAgICAgICAgIFwiRGlyZWN0b3J5IHRyZWUgbGlzdGluZyBzaG93aW5nIHBhdGhzIHJlbGF0aXZlIHRvIHNlYXJjaCByb290XCJcbiAgICAgICAgKSxcbiAgICAgIHN1bW1hcnk6IHoub2JqZWN0KHtcbiAgICAgICAgdG90YWxJdGVtczogei5udW1iZXIoKS5kZXNjcmliZShcIlRvdGFsIG51bWJlciBvZiBpdGVtcyBmb3VuZFwiKSxcbiAgICAgICAgdG90YWxGaWxlczogei5udW1iZXIoKS5kZXNjcmliZShcIlRvdGFsIG51bWJlciBvZiBmaWxlcyBmb3VuZFwiKSxcbiAgICAgICAgdG90YWxEaXJzOiB6Lm51bWJlcigpLmRlc2NyaWJlKFwiVG90YWwgbnVtYmVyIG9mIGRpcmVjdG9yaWVzIGZvdW5kXCIpLFxuICAgICAgICBzZWFyY2hQYXRoOiB6LnN0cmluZygpLmRlc2NyaWJlKFwiUGF0aCB0aGF0IHdhcyBsaXN0ZWRcIiksXG4gICAgICAgIGRlcHRoOiB6XG4gICAgICAgICAgLm51bWJlcigpXG4gICAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgICAuZGVzY3JpYmUoXCJNYXhpbXVtIGRlcHRoIHVzZWQgKGlmIHNwZWNpZmllZClcIiksXG4gICAgICB9KSxcbiAgICB9KSxcbiAgfSksXG4gIFdyaXRlOiB0b29sKHtcbiAgICBkZXNjcmlwdGlvbjpcbiAgICAgIFwiV3JpdGUgY29udGVudCB0byBhIGZpbGUuIENyZWF0ZXMgcGFyZW50IGRpcmVjdG9yaWVzIGF1dG9tYXRpY2FsbHkuIE92ZXJ3cml0ZXMgZXhpc3RpbmcgZmlsZXMuXCIsXG4gICAgaW5wdXRTY2hlbWE6IHoub2JqZWN0KHtcbiAgICAgIHBhdGg6IHouc3RyaW5nKCkuZGVzY3JpYmUoXCJQYXRoIHRvIHRoZSBmaWxlIHJlbGF0aXZlIHRvIHdvcmtzcGFjZSByb290XCIpLFxuICAgICAgY29udGVudDogei5zdHJpbmcoKS5kZXNjcmliZShcIkNvbnRlbnQgdG8gd3JpdGUgdG8gdGhlIGZpbGVcIiksXG4gICAgfSksXG4gICAgb3V0cHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4gICAgICBzdWNjZXNzOiB6LmJvb2xlYW4oKS5kZXNjcmliZShcIldoZXRoZXIgdGhlIHdyaXRlIHN1Y2NlZWRlZFwiKSxcbiAgICAgIHBhdGg6IHouc3RyaW5nKCkuZGVzY3JpYmUoXCJQYXRoIHRvIHRoZSB3cml0dGVuIGZpbGVcIiksXG4gICAgICBieXRlc1dyaXR0ZW46IHoubnVtYmVyKCkuZGVzY3JpYmUoXCJOdW1iZXIgb2YgYnl0ZXMgd3JpdHRlblwiKSxcbiAgICAgIGVycm9yOiB6LnN0cmluZygpLm9wdGlvbmFsKCkuZGVzY3JpYmUoXCJFcnJvciBtZXNzYWdlIGlmIHdyaXRlIGZhaWxlZFwiKSxcbiAgICB9KSxcbiAgfSksXG4gIEVkaXQ6IHRvb2woe1xuICAgIGRlc2NyaXB0aW9uOlxuICAgICAgXCJFZGl0IGEgZmlsZSBieSByZXBsYWNpbmcgYW4gZXhhY3Qgc3RyaW5nLiBGYWlscyBpZiBvbGRfc3RyaW5nIGlzIG5vdCBmb3VuZCBvciBhcHBlYXJzIG11bHRpcGxlIHRpbWVzIChub3QgdW5pcXVlKS4gRm9yIG11bHRpcGxlIHJlcGxhY2VtZW50cywgY2FsbCB0aGlzIHRvb2wgbXVsdGlwbGUgdGltZXMgd2l0aCB1bmlxdWUgY29udGV4dC5cIixcbiAgICBpbnB1dFNjaGVtYTogei5vYmplY3Qoe1xuICAgICAgcGF0aDogei5zdHJpbmcoKS5kZXNjcmliZShcIlBhdGggdG8gdGhlIGZpbGUgcmVsYXRpdmUgdG8gd29ya3NwYWNlIHJvb3RcIiksXG4gICAgICBvbGRfc3RyaW5nOiB6XG4gICAgICAgIC5zdHJpbmcoKVxuICAgICAgICAuZGVzY3JpYmUoXCJFeGFjdCBzdHJpbmcgdG8gZmluZCBhbmQgcmVwbGFjZSAobXVzdCBiZSB1bmlxdWUgaW4gZmlsZSlcIiksXG4gICAgICBuZXdfc3RyaW5nOiB6LnN0cmluZygpLmRlc2NyaWJlKFwiU3RyaW5nIHRvIHJlcGxhY2Ugb2xkX3N0cmluZyB3aXRoXCIpLFxuICAgIH0pLFxuICAgIG91dHB1dFNjaGVtYTogei5vYmplY3Qoe1xuICAgICAgc3VjY2Vzczogei5ib29sZWFuKCkuZGVzY3JpYmUoXCJXaGV0aGVyIHRoZSBlZGl0IHN1Y2NlZWRlZFwiKSxcbiAgICAgIHBhdGg6IHouc3RyaW5nKCkuZGVzY3JpYmUoXCJQYXRoIHRvIHRoZSBlZGl0ZWQgZmlsZVwiKSxcbiAgICAgIGVycm9yOiB6LnN0cmluZygpLm9wdGlvbmFsKCkuZGVzY3JpYmUoXCJFcnJvciBtZXNzYWdlIGlmIGVkaXQgZmFpbGVkXCIpLFxuICAgIH0pLFxuICB9KSxcbiAgQmFzaDogdG9vbCh7XG4gICAgZGVzY3JpcHRpb246XG4gICAgICBcIkV4ZWN1dGVzIGEgYmFzaCBjb21tYW5kIGluc2lkZSB0aGUgd29ya3NwYWNlLiBDV0QgcGVyc2lzdHMgYmV0d2VlbiBjb21tYW5kcyB3aXRoaW4gYSBzZXNzaW9uLiBVc2Ugd2FpdFVudGlsOjAgZm9yIGJhY2tncm91bmQgcHJvY2Vzc2VzIChkZXYgc2VydmVycykuXCIsXG4gICAgaW5wdXRTY2hlbWE6IHoub2JqZWN0KHtcbiAgICAgIGNvbW1hbmQ6IHouc3RyaW5nKCkuZGVzY3JpYmUoXCJUaGUgc2hlbGwgY29tbWFuZCB0byBleGVjdXRlXCIpLFxuICAgICAgd2FpdFVudGlsOiB6XG4gICAgICAgIC5udW1iZXIoKVxuICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgYE1heCBtcyB0byB3YWl0IGZvciBjb21wbGV0aW9uIChkZWZhdWx0OiAke0RFRkFVTFRfV0FJVF9VTlRJTH0pLiBVc2UgMCB0byBydW4gaW4gYmFja2dyb3VuZCBhbmQgcmV0dXJuIGltbWVkaWF0ZWx5LmBcbiAgICAgICAgKSxcbiAgICB9KSxcbiAgICBvdXRwdXRTY2hlbWE6IHoub2JqZWN0KHtcbiAgICAgIHBpZDogelxuICAgICAgICAubnVtYmVyKClcbiAgICAgICAgLmRlc2NyaWJlKFxuICAgICAgICAgIFwiU3lzdGVtIFBJRCAoMCBmb3IgZm9yZWdyb3VuZCwgPjAgZm9yIGJhY2tncm91bmQgLSB1c2UgdG8ga2lsbClcIlxuICAgICAgICApLFxuICAgICAgb3V0cHV0OiB6XG4gICAgICAgIC5zdHJpbmcoKVxuICAgICAgICAuZGVzY3JpYmUoXCJDb21tYW5kIHN0ZG91dCtzdGRlcnIgY29tYmluZWQgKGVtcHR5IGZvciBiYWNrZ3JvdW5kKVwiKSxcbiAgICAgIGV4aXRDb2RlOiB6Lm51bWJlcigpLmRlc2NyaWJlKFwiRXhpdCBjb2RlICgtMSBmb3IgYmFja2dyb3VuZC9ydW5uaW5nKVwiKSxcbiAgICAgIHN0YXR1czogelxuICAgICAgICAuZW51bShbXCJydW5uaW5nXCIsIFwiY29tcGxldGVkXCIsIFwiZmFpbGVkXCJdKVxuICAgICAgICAuZGVzY3JpYmUoXCJQcm9jZXNzIHN0YXR1c1wiKSxcbiAgICAgIGN3ZDogei5zdHJpbmcoKS5kZXNjcmliZShcIkN1cnJlbnQgd29ya2luZyBkaXJlY3RvcnkgYWZ0ZXIgY29tbWFuZFwiKSxcbiAgICAgIG91dHB1dEZpbGU6IHpcbiAgICAgICAgLnN0cmluZygpXG4gICAgICAgIC5kZXNjcmliZShcIlBhdGggdG8gb3V0cHV0IGxvZyAoZm9yIGJhY2tncm91bmQgcHJvY2Vzc2VzKVwiKSxcbiAgICB9KSxcbiAgfSksXG4gIEphdmFTY3JpcHQ6IHRvb2woe1xuICAgIGlucHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4gICAgICBjb2RlOiB6XG4gICAgICAgIC5zdHJpbmcoKVxuICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgXCJKYXZhU2NyaXB0IGFzeW5jIGZ1bmN0aW9uIGJvZHkuIGBjdHhgIGlzIGluIHNjb3BlLiBNdXN0IHVzZSBgcmV0dXJuYCB0byBwcm9kdWNlIG91dHB1dC5cIlxuICAgICAgICApLFxuICAgIH0pLFxuICB9KSxcbn0gc2F0aXNmaWVzIFRvb2xTZXQ7XG5cbmV4cG9ydCB0eXBlIEJ1aWx0SW5Ub29sTmFtZSA9IGtleW9mIHR5cGVvZiBidWlsdEluVG9vbHM7XG5leHBvcnQgY29uc3QgYnVpbHRpblRvb2xOYW1lcyA9IE9iamVjdC5mcm9tRW50cmllcyhcbiAgT2JqZWN0LmVudHJpZXMoYnVpbHRJblRvb2xzKS5tYXAoKFtuYW1lXSkgPT4gW25hbWUsIG5hbWVdKVxuKSBhcyB7IFtLIGluIEJ1aWx0SW5Ub29sTmFtZV06IEsgfTtcblxuZXhwb3J0IGZ1bmN0aW9uIGdldFRvb2xzKGNvbnRleHQ6IEludGVybmFsVG9vbENvbnRleHQpIHtcbiAgY29uc3QgdG9vbHM6IFRvb2xTZXQgPSB7XG4gICAgW2J1aWx0aW5Ub29sTmFtZXMuUmVhZF06IHRvb2woe1xuICAgICAgLi4uYnVpbHRJblRvb2xzLlJlYWQsXG4gICAgICBleGVjdXRlOiBhc3luYyAoeyBwYXRoLCBzdGFydExpbmUsIGVuZExpbmUgfSkgPT4ge1xuICAgICAgICBjb25zdCBmaWxlUGF0aCA9IHBhdGg7XG5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udGV4dC5zYW5kYm94LnJlYWRGaWxlKHsgcGF0aDogZmlsZVBhdGggfSk7XG5cbiAgICAgICAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihcIltSZWFkIFRvb2xdXCIsIHJlc3VsdCk7XG4gICAgICAgICAgdGhyb3cgcmVzdWx0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHJlc3VsdCA9PT0gbnVsbCkge1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBjb250ZW50OiBgRXJyb3I6IEZpbGUgbm90IGZvdW5kIC0gJHtmaWxlUGF0aH1gLFxuICAgICAgICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgICAgICAgdG90YWxMaW5lczogMCxcbiAgICAgICAgICAgICAgbGluZXNTaG93bjogMCxcbiAgICAgICAgICAgICAgc3RhcnRMaW5lOiAwLFxuICAgICAgICAgICAgICBlbmRMaW5lOiAwLFxuICAgICAgICAgICAgICBpc1BhZ2luYXRlZDogZmFsc2UsXG4gICAgICAgICAgICAgIGZpbGVTaXplOiBcIjBcIixcbiAgICAgICAgICAgICAgcGF0aDogZmlsZVBhdGgsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBmdWxsQ29udGVudCA9IHJlc3VsdC50b1N0cmluZyhcInV0Zi04XCIpO1xuICAgICAgICBjb25zdCBsaW5lcyA9IGZ1bGxDb250ZW50LnNwbGl0KFwiXFxuXCIpO1xuICAgICAgICAvLyBBIHRyYWlsaW5nIG5ld2xpbmUgcHJvZHVjZXMgYW4gZW1wdHkgbGFzdCBlbGVtZW50IFx1MjAxNCByZW1vdmUgaXRcbiAgICAgICAgLy8gc28gbGluZSBjb3VudCBtYXRjaGVzIGB3YyAtbGAgLyBgYXdrICdFTkR7cHJpbnQgTlJ9J2AgYmVoYXZpb3IuXG4gICAgICAgIGlmIChsaW5lcy5sZW5ndGggPiAwICYmIGxpbmVzLmF0KC0xKSA9PT0gXCJcIikge1xuICAgICAgICAgIGxpbmVzLnBvcCgpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHRvdGFsTGluZXMgPSBsaW5lcy5sZW5ndGg7XG4gICAgICAgIGNvbnN0IGZpbGVCeXRlcyA9IEJ1ZmZlci5ieXRlTGVuZ3RoKGZ1bGxDb250ZW50KTtcbiAgICAgICAgY29uc3QgZmlsZVNpemUgPSBmb3JtYXRGaWxlU2l6ZShmaWxlQnl0ZXMpO1xuXG4gICAgICAgIC8vIERldGVybWluZSByYW5nZVxuICAgICAgICBjb25zdCBQQUdFX1NJWkUgPSAxMDA7XG4gICAgICAgIGxldCBhY3R1YWxTdGFydDogbnVtYmVyO1xuICAgICAgICBsZXQgYWN0dWFsRW5kOiBudW1iZXI7XG5cbiAgICAgICAgaWYgKHN0YXJ0TGluZSAhPT0gdW5kZWZpbmVkICYmIGVuZExpbmUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGFjdHVhbFN0YXJ0ID0gc3RhcnRMaW5lO1xuICAgICAgICAgIGFjdHVhbEVuZCA9IGVuZExpbmU7XG4gICAgICAgIH0gZWxzZSBpZiAoc3RhcnRMaW5lICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBhY3R1YWxTdGFydCA9IHN0YXJ0TGluZTtcbiAgICAgICAgICBhY3R1YWxFbmQgPSBNYXRoLm1pbihzdGFydExpbmUgKyBQQUdFX1NJWkUgLSAxLCB0b3RhbExpbmVzKTtcbiAgICAgICAgfSBlbHNlIGlmIChlbmRMaW5lICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBhY3R1YWxTdGFydCA9IDE7XG4gICAgICAgICAgYWN0dWFsRW5kID0gZW5kTGluZTtcbiAgICAgICAgfSBlbHNlIGlmICh0b3RhbExpbmVzID4gMjAwKSB7XG4gICAgICAgICAgYWN0dWFsU3RhcnQgPSAxO1xuICAgICAgICAgIGFjdHVhbEVuZCA9IFBBR0VfU0laRTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBhY3R1YWxTdGFydCA9IDE7XG4gICAgICAgICAgYWN0dWFsRW5kID0gdG90YWxMaW5lcztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEV4dHJhY3QgdGhlIGxpbmUgcmFuZ2UgKDEtaW5kZXhlZClcbiAgICAgICAgY29uc3Qgc2xpY2VkTGluZXMgPSBsaW5lcy5zbGljZShhY3R1YWxTdGFydCAtIDEsIGFjdHVhbEVuZCk7XG4gICAgICAgIGNvbnN0IGNvbnRlbnQgPSBzbGljZWRMaW5lcy5qb2luKFwiXFxuXCIpO1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgICAgIHRvdGFsTGluZXMsXG4gICAgICAgICAgICBsaW5lc1Nob3duOiBNYXRoLm1heCgwLCBhY3R1YWxFbmQgLSBhY3R1YWxTdGFydCArIDEpLFxuICAgICAgICAgICAgc3RhcnRMaW5lOiBhY3R1YWxTdGFydCxcbiAgICAgICAgICAgIGVuZExpbmU6IGFjdHVhbEVuZCxcbiAgICAgICAgICAgIGlzUGFnaW5hdGVkOiBhY3R1YWxFbmQgPCB0b3RhbExpbmVzLFxuICAgICAgICAgICAgZmlsZVNpemUsXG4gICAgICAgICAgICBwYXRoOiBmaWxlUGF0aCxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGNvbnRlbnQsXG4gICAgICAgIH07XG4gICAgICB9LFxuICAgIH0pLFxuICAgIFtidWlsdGluVG9vbE5hbWVzLkdyZXBdOiB0b29sKHtcbiAgICAgIC4uLmJ1aWx0SW5Ub29scy5HcmVwLFxuICAgICAgZXhlY3V0ZTogYXN5bmMgKHtcbiAgICAgICAgcGF0dGVybixcbiAgICAgICAgcGF0aCxcbiAgICAgICAgZmlsZVR5cGUsXG4gICAgICAgIGdsb2IsXG4gICAgICAgIGNhc2VTZW5zaXRpdmUsXG4gICAgICAgIGNvbnRleHRMaW5lcyxcbiAgICAgICAgbWF4Q291bnQsXG4gICAgICAgIGZpbGVzV2l0aE1hdGNoZXMsXG4gICAgICB9KSA9PiB7XG4gICAgICAgIGNvbnN0IHNlYXJjaFBhdGggPSBwYXRoID8/IFwiLlwiO1xuXG4gICAgICAgIGNvbnN0IGFyZ3M6IHN0cmluZ1tdID0gW107XG5cbiAgICAgICAgYXJncy5wdXNoKFwiLS1saW5lLW51bWJlclwiKTtcbiAgICAgICAgYXJncy5wdXNoKFwiLS1oZWFkaW5nXCIpO1xuICAgICAgICBhcmdzLnB1c2goXCItLWNvbG9yXCIsIFwibmV2ZXJcIik7XG5cbiAgICAgICAgaWYgKCFjYXNlU2Vuc2l0aXZlKSB7XG4gICAgICAgICAgYXJncy5wdXNoKFwiLWlcIik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZmlsZVR5cGUpIHtcbiAgICAgICAgICBhcmdzLnB1c2goXCItLXR5cGVcIiwgZmlsZVR5cGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGdsb2IpIHtcbiAgICAgICAgICBhcmdzLnB1c2goXCItLWdsb2JcIiwgZ2xvYik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY29udGV4dExpbmVzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBhcmdzLnB1c2goXCItQ1wiLCBTdHJpbmcoY29udGV4dExpbmVzKSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobWF4Q291bnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGFyZ3MucHVzaChcIi0tbWF4LWNvdW50XCIsIFN0cmluZyhtYXhDb3VudCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZpbGVzV2l0aE1hdGNoZXMpIHtcbiAgICAgICAgICBhcmdzLnB1c2goXCItLWZpbGVzLXdpdGgtbWF0Y2hlc1wiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGFyZ3MucHVzaChcIi0tXCIsIHBhdHRlcm4sIHNlYXJjaFBhdGgpO1xuXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnRleHQuc2FuZGJveC5leGVjKHsgY29tbWFuZDogXCJyZ1wiLCBhcmdzIH0pO1xuXG4gICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJbR3JlcCBUb29sXVwiLCByZXN1bHQpO1xuICAgICAgICAgIHRocm93IHJlc3VsdDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHsgc3Rkb3V0LCBzdGRlcnIgfSA9IGF3YWl0IHJlc3VsdC5yZXN1bHQ7XG5cbiAgICAgICAgaWYgKHN0ZGVyciAmJiAhc3RkZXJyLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoXCJubyBtYXRjaGVzXCIpKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihgW0dyZXAgVG9vbF0gV2FybmluZzogJHtzdGRlcnJ9YCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUcnVuY2F0ZSBvdXRwdXQgdG8gcHJldmVudCBcImlucHV0IHRvbyBsb25nXCIgZXJyb3JzICg1MGsgY2hhcnMgXHUyMjQ4IDEyLjVrIHRva2VucylcbiAgICAgICAgY29uc3QgTUFYX0dSRVBfT1VUUFVUX0NIQVJTID0gNTBfMDAwO1xuICAgICAgICBsZXQgZmluYWxPdXRwdXQgPSBzdGRvdXQ7XG4gICAgICAgIGxldCB3YXNUcnVuY2F0ZWQgPSBmYWxzZTtcbiAgICAgICAgaWYgKGZpbmFsT3V0cHV0Lmxlbmd0aCA+IE1BWF9HUkVQX09VVFBVVF9DSEFSUykge1xuICAgICAgICAgIGZpbmFsT3V0cHV0ID1cbiAgICAgICAgICAgIGZpbmFsT3V0cHV0LnNsaWNlKDAsIE1BWF9HUkVQX09VVFBVVF9DSEFSUykgK1xuICAgICAgICAgICAgXCJcXG5cXG5bT3V0cHV0IHRydW5jYXRlZCAtIHVzZSBtb3JlIHNwZWNpZmljIHBhdHRlcm4gb3IgcGF0aF1cIjtcbiAgICAgICAgICB3YXNUcnVuY2F0ZWQgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbGluZXMgPSBmaW5hbE91dHB1dFxuICAgICAgICAgIC50cmltKClcbiAgICAgICAgICAuc3BsaXQoXCJcXG5cIilcbiAgICAgICAgICAuZmlsdGVyKChsKSA9PiBsLmxlbmd0aCA+IDApO1xuICAgICAgICBjb25zdCBmaWxlQ291bnQgPSBmaWxlc1dpdGhNYXRjaGVzXG4gICAgICAgICAgPyBsaW5lcy5sZW5ndGhcbiAgICAgICAgICA6IG5ldyBTZXQoXG4gICAgICAgICAgICAgIGxpbmVzXG4gICAgICAgICAgICAgICAgLmZpbHRlcigobCkgPT4gIWwuc3RhcnRzV2l0aChcIiBcIikgJiYgbC5pbmNsdWRlcyhcIjpcIikpXG4gICAgICAgICAgICAgICAgLm1hcCgobCkgPT4gbC5zcGxpdChcIjpcIilbMF0pXG4gICAgICAgICAgICApLnNpemU7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBzdW1tYXJ5OiB7XG4gICAgICAgICAgICBtYXRjaENvdW50OiBmaWxlc1dpdGhNYXRjaGVzXG4gICAgICAgICAgICAgID8gMFxuICAgICAgICAgICAgICA6IGxpbmVzLmZpbHRlcigobCkgPT4gbC5pbmNsdWRlcyhcIjpcIikpLmxlbmd0aCxcbiAgICAgICAgICAgIGZpbGVDb3VudCxcbiAgICAgICAgICAgIHNlYXJjaFBhdGgsXG4gICAgICAgICAgICBwYXR0ZXJuLFxuICAgICAgICAgICAgd2FzVHJ1bmNhdGVkLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgbWF0Y2hlczogZmluYWxPdXRwdXQgfHwgXCIobm8gbWF0Y2hlcyBmb3VuZClcIixcbiAgICAgICAgfTtcbiAgICAgIH0sXG4gICAgfSksXG4gICAgW2J1aWx0aW5Ub29sTmFtZXMuTGlzdF06IHRvb2woe1xuICAgICAgLi4uYnVpbHRJblRvb2xzLkxpc3QsXG4gICAgICBleGVjdXRlOiBhc3luYyAoeyBwYXRoLCBkZXB0aCwgaW5jbHVkZUhpZGRlbiwgZmlsZXNPbmx5LCBwYXR0ZXJuIH0pID0+IHtcbiAgICAgICAgY29uc3Qgc2VhcmNoUGF0aCA9IHBhdGggPz8gXCIuXCI7XG5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udGV4dC5zYW5kYm94LmV4ZWMoe1xuICAgICAgICAgIGNvbW1hbmQ6IFwiYmFzaFwiLFxuICAgICAgICAgIGFyZ3M6IFtcbiAgICAgICAgICAgIFwiLWNcIixcbiAgICAgICAgICAgIGBcbiAgICAgICAgICAgIHNldCAtZVxuICAgICAgICAgICAgU0VBUkNIX1BBVEg9XCIkMVwiXG4gICAgICAgICAgICBERVBUSD1cIiQyXCJcbiAgICAgICAgICAgIElOQ0xVREVfSElEREVOPVwiJDNcIlxuICAgICAgICAgICAgRklMRVNfT05MWT1cIiQ0XCJcbiAgICAgICAgICAgIFBBVFRFUk49XCIkNVwiXG5cbiAgICAgICAgICAgICMgQnVpbGQgZmluZCBjb21tYW5kIGFyZ3VtZW50c1xuICAgICAgICAgICAgRklORF9BUkdTPVwiXCJcbiAgICAgICAgICAgIFsgLW4gXCIkREVQVEhcIiBdICYmIEZJTkRfQVJHUz1cIiRGSU5EX0FSR1MgLW1heGRlcHRoICRERVBUSFwiXG4gICAgICAgICAgICBbIFwiJElOQ0xVREVfSElEREVOXCIgIT0gXCJ0cnVlXCIgXSAmJiBGSU5EX0FSR1M9XCIkRklORF9BUkdTICEgLXBhdGggJyovLionXCJcbiAgICAgICAgICAgIFsgXCIkRklMRVNfT05MWVwiID0gXCJ0cnVlXCIgXSAmJiBGSU5EX0FSR1M9XCIkRklORF9BUkdTIC10eXBlIGZcIlxuICAgICAgICAgICAgWyAtbiBcIiRQQVRURVJOXCIgXSAmJiBGSU5EX0FSR1M9XCIkRklORF9BUkdTIC1uYW1lICckUEFUVEVSTidcIlxuXG4gICAgICAgICAgICAjIEdldCBsaXN0aW5nXG4gICAgICAgICAgICBMSVNUSU5HPSQoZXZhbCBcImZpbmQgJyRTRUFSQ0hfUEFUSCcgJEZJTkRfQVJHU1wiIDI+L2Rldi9udWxsIHwgc29ydClcblxuICAgICAgICAgICAgIyBHZXQgY291bnRzXG4gICAgICAgICAgICBDT1VOVF9BUkdTPVwiXCJcbiAgICAgICAgICAgIFsgLW4gXCIkREVQVEhcIiBdICYmIENPVU5UX0FSR1M9XCIkQ09VTlRfQVJHUyAtbWF4ZGVwdGggJERFUFRIXCJcbiAgICAgICAgICAgIFsgXCIkSU5DTFVERV9ISURERU5cIiAhPSBcInRydWVcIiBdICYmIENPVU5UX0FSR1M9XCIkQ09VTlRfQVJHUyAhIC1wYXRoICcqLy4qJ1wiXG5cbiAgICAgICAgICAgIEZJTEVfQ09VTlQ9JChldmFsIFwiZmluZCAnJFNFQVJDSF9QQVRIJyAkQ09VTlRfQVJHUyAtdHlwZSBmXCIgMj4vZGV2L251bGwgfCB3YyAtbClcbiAgICAgICAgICAgIERJUl9DT1VOVD0kKGV2YWwgXCJmaW5kICckU0VBUkNIX1BBVEgnICRDT1VOVF9BUkdTIC10eXBlIGRcIiAyPi9kZXYvbnVsbCB8IHdjIC1sKVxuXG4gICAgICAgICAgICAjIE91dHB1dDogY291bnRzIGZpcnN0LCB0aGVuIGxpc3RpbmdcbiAgICAgICAgICAgIGVjaG8gXCIkRklMRV9DT1VOVHwkRElSX0NPVU5UXCJcbiAgICAgICAgICAgIGVjaG8gXCJ8fHxMSVNUSU5HfHx8XCJcbiAgICAgICAgICAgIGVjaG8gXCIkTElTVElOR1wiIHwgc2VkIFwic3xeJFNFQVJDSF9QQVRIfC58XCJcbiAgICAgICAgICBgLFxuICAgICAgICAgICAgXCItLVwiLFxuICAgICAgICAgICAgc2VhcmNoUGF0aCxcbiAgICAgICAgICAgIGRlcHRoPy50b1N0cmluZygpIHx8IFwiXCIsXG4gICAgICAgICAgICBpbmNsdWRlSGlkZGVuID8gXCJ0cnVlXCIgOiBcImZhbHNlXCIsXG4gICAgICAgICAgICBmaWxlc09ubHkgPyBcInRydWVcIiA6IFwiZmFsc2VcIixcbiAgICAgICAgICAgIHBhdHRlcm4gfHwgXCJcIixcbiAgICAgICAgICBdLFxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKFwiW0xpc3QgVG9vbF1cIiwgcmVzdWx0KTtcbiAgICAgICAgICB0aHJvdyByZXN1bHQ7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB7IHN0ZG91dCwgc3RkZXJyIH0gPSBhd2FpdCByZXN1bHQucmVzdWx0O1xuXG4gICAgICAgIGlmIChzdGRlcnIpIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oYFtMaXN0IFRvb2xdIHN0ZGVycjogJHtzdGRlcnJ9YCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBbY291bnRzTGluZSwgLi4ucmVzdF0gPSBzdGRvdXQuc3BsaXQoXCJ8fHxMSVNUSU5HfHx8XCIpO1xuICAgICAgICBjb25zdCBsaXN0aW5nID0gcmVzdC5qb2luKFwifHx8TElTVElOR3x8fFwiKS50cmltKCk7XG4gICAgICAgIGNvbnN0IFtmaWxlQ291bnRTdHIsIGRpckNvdW50U3RyXSA9IGNvdW50c0xpbmUudHJpbSgpLnNwbGl0KFwifFwiKTtcblxuICAgICAgICBjb25zdCB0b3RhbEZpbGVzID0gTnVtYmVyLnBhcnNlSW50KGZpbGVDb3VudFN0ciwgMTApIHx8IDA7XG4gICAgICAgIGNvbnN0IHRvdGFsRGlycyA9IE51bWJlci5wYXJzZUludChkaXJDb3VudFN0ciwgMTApIHx8IDA7XG4gICAgICAgIGNvbnN0IGxpbmVzID0gbGlzdGluZy5zcGxpdChcIlxcblwiKS5maWx0ZXIoKGwpID0+IGwubGVuZ3RoID4gMCk7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBzdW1tYXJ5OiB7XG4gICAgICAgICAgICB0b3RhbEl0ZW1zOiBsaW5lcy5sZW5ndGgsXG4gICAgICAgICAgICB0b3RhbEZpbGVzLFxuICAgICAgICAgICAgdG90YWxEaXJzLFxuICAgICAgICAgICAgc2VhcmNoUGF0aCxcbiAgICAgICAgICAgIGRlcHRoLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgbGlzdGluZyxcbiAgICAgICAgfTtcbiAgICAgIH0sXG4gICAgfSksXG4gICAgW2J1aWx0aW5Ub29sTmFtZXMuV3JpdGVdOiB0b29sKHtcbiAgICAgIC4uLmJ1aWx0SW5Ub29scy5Xcml0ZSxcbiAgICAgIGV4ZWN1dGU6IGFzeW5jICh7IHBhdGgsIGNvbnRlbnQgfSkgPT4ge1xuICAgICAgICBjb25zdCBmaWxlUGF0aCA9IHBhdGguc3RhcnRzV2l0aChcIi9cIikgPyBwYXRoLnNsaWNlKDEpIDogcGF0aDtcbiAgICAgICAgY29uc3QgZGlyID0gZmlsZVBhdGguaW5jbHVkZXMoXCIvXCIpXG4gICAgICAgICAgPyBmaWxlUGF0aC5zcGxpdChcIi9cIikuc2xpY2UoMCwgLTEpLmpvaW4oXCIvXCIpXG4gICAgICAgICAgOiBcIi5cIjtcbiAgICAgICAgY29uc3QgZmlsZU5hbWUgPSBmaWxlUGF0aC5zcGxpdChcIi9cIikucG9wKCkgfHwgZmlsZVBhdGg7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBpZiAoZGlyICE9PSBcIi5cIikge1xuICAgICAgICAgICAgYXdhaXQgY29udGV4dC5zYW5kYm94LmV4ZWMoeyBjb21tYW5kOiBcIm1rZGlyXCIsIGFyZ3M6IFtcIi1wXCIsIGRpcl0gfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgYXdhaXQgY29udGV4dC5zYW5kYm94LndyaXRlRmlsZXMoe1xuICAgICAgICAgICAgZmlsZXM6IFt7IHBhdGg6IGZpbGVOYW1lLCBjb250ZW50IH1dLFxuICAgICAgICAgICAgZGVzdFBhdGg6IGRpcixcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzdWNjZXNzOiB0cnVlLFxuICAgICAgICAgICAgcGF0aDogZmlsZVBhdGgsXG4gICAgICAgICAgICBieXRlc1dyaXR0ZW46IEJ1ZmZlci5ieXRlTGVuZ3RoKGNvbnRlbnQsIFwidXRmOFwiKSxcbiAgICAgICAgICB9O1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBjb25zdCBlcnJvck1zZyA9IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKTtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICAgICAgICBwYXRoOiBmaWxlUGF0aCxcbiAgICAgICAgICAgIGJ5dGVzV3JpdHRlbjogMCxcbiAgICAgICAgICAgIGVycm9yOiBlcnJvck1zZyxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICB9LFxuICAgIH0pLFxuICAgIFtidWlsdGluVG9vbE5hbWVzLkVkaXRdOiB0b29sKHtcbiAgICAgIC4uLmJ1aWx0SW5Ub29scy5FZGl0LFxuICAgICAgZXhlY3V0ZTogYXN5bmMgKHsgcGF0aCwgb2xkX3N0cmluZywgbmV3X3N0cmluZyB9KSA9PiB7XG4gICAgICAgIGNvbnN0IGZpbGVQYXRoID0gcGF0aC5zdGFydHNXaXRoKFwiL1wiKSA/IHBhdGguc2xpY2UoMSkgOiBwYXRoO1xuXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnRleHQuc2FuZGJveC5yZWFkRmlsZSh7IHBhdGg6IGZpbGVQYXRoIH0pO1xuXG4gICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgIHJldHVybiB7IHN1Y2Nlc3M6IGZhbHNlLCBwYXRoOiBmaWxlUGF0aCwgZXJyb3I6IHJlc3VsdC5tZXNzYWdlIH07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocmVzdWx0ID09PSBudWxsKSB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgICAgICAgcGF0aDogZmlsZVBhdGgsXG4gICAgICAgICAgICBlcnJvcjogYEZpbGUgbm90IGZvdW5kOiAke2ZpbGVQYXRofWAsXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGNvbnRlbnQgPSByZXN1bHQudG9TdHJpbmcoXCJ1dGYtOFwiKTtcbiAgICAgICAgY29uc3Qgb2NjdXJyZW5jZXMgPSBjb250ZW50LnNwbGl0KG9sZF9zdHJpbmcpLmxlbmd0aCAtIDE7XG5cbiAgICAgICAgaWYgKG9jY3VycmVuY2VzID09PSAwKSB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgICAgICAgcGF0aDogZmlsZVBhdGgsXG4gICAgICAgICAgICBlcnJvcjogXCJvbGRfc3RyaW5nIG5vdCBmb3VuZCBpbiBmaWxlXCIsXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChvY2N1cnJlbmNlcyA+IDEpIHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICAgICAgICBwYXRoOiBmaWxlUGF0aCxcbiAgICAgICAgICAgIGVycm9yOiBgb2xkX3N0cmluZyBhcHBlYXJzICR7b2NjdXJyZW5jZXN9IHRpbWVzIGluIGZpbGUgKG11c3QgYmUgdW5pcXVlKS4gSW5jbHVkZSBtb3JlIHN1cnJvdW5kaW5nIGNvbnRleHQgdG8gbWFrZSB0aGUgbWF0Y2ggdW5pcXVlLmAsXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IG5ld0NvbnRlbnQgPSBjb250ZW50LnJlcGxhY2Uob2xkX3N0cmluZywgbmV3X3N0cmluZyk7XG4gICAgICAgIGNvbnN0IGRpciA9IGZpbGVQYXRoLmluY2x1ZGVzKFwiL1wiKVxuICAgICAgICAgID8gZmlsZVBhdGguc3BsaXQoXCIvXCIpLnNsaWNlKDAsIC0xKS5qb2luKFwiL1wiKVxuICAgICAgICAgIDogXCIuXCI7XG4gICAgICAgIGNvbnN0IGZpbGVOYW1lID0gZmlsZVBhdGguc3BsaXQoXCIvXCIpLnBvcCgpIHx8IGZpbGVQYXRoO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYXdhaXQgY29udGV4dC5zYW5kYm94LndyaXRlRmlsZXMoe1xuICAgICAgICAgICAgZmlsZXM6IFt7IHBhdGg6IGZpbGVOYW1lLCBjb250ZW50OiBuZXdDb250ZW50IH1dLFxuICAgICAgICAgICAgZGVzdFBhdGg6IGRpcixcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIHJldHVybiB7IHN1Y2Nlc3M6IHRydWUsIHBhdGg6IGZpbGVQYXRoIH07XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIGNvbnN0IGVycm9yTXNnID0gZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpO1xuICAgICAgICAgIHJldHVybiB7IHN1Y2Nlc3M6IGZhbHNlLCBwYXRoOiBmaWxlUGF0aCwgZXJyb3I6IGVycm9yTXNnIH07XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSksXG4gICAgW2J1aWx0aW5Ub29sTmFtZXMuQmFzaF06IHRvb2woe1xuICAgICAgLi4uYnVpbHRJblRvb2xzLkJhc2gsXG4gICAgICBleGVjdXRlOiBhc3luYyAoeyBjb21tYW5kLCB3YWl0VW50aWwgfSkgPT4ge1xuICAgICAgICBjb25zdCB7IGNyZWF0ZVByb2Nlc3NNYW5hZ2VyIH0gPSBhd2FpdCBpbXBvcnQoXG4gICAgICAgICAgXCIuLi9zYW5kYm94L3Byb2Nlc3MtbWFuYWdlclwiXG4gICAgICAgICk7XG5cbiAgICAgICAgY29uc3QgcHJvY2Vzc01hbmFnZXIgPSBjcmVhdGVQcm9jZXNzTWFuYWdlcih7XG4gICAgICAgICAgc2FuZGJveDogY29udGV4dC5zYW5kYm94LFxuICAgICAgICAgIHNlc3Npb25JZDogY29udGV4dC5pbnB1dC5zZXNzaW9uSWQsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGF3YWl0IHByb2Nlc3NNYW5hZ2VyLmluaXQoKTtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcHJvY2Vzc01hbmFnZXIucnVuKHsgY29tbWFuZCwgd2FpdFVudGlsIH0pO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSxcbiAgICB9KSxcbiAgfTtcblxuICBpZiAoY29udGV4dC5hcGlUb29sc01ldGFkYXRhLmxlbmd0aCA+IDApIHtcbiAgICBjb25zdCBhcGlUb29scyA9IGJ1aWxkQXBpVG9vbHMoe1xuICAgICAgcnBjOiBjb250ZXh0LmlucHV0LnJwYyxcbiAgICAgIG1ldGFkYXRhOiBjb250ZXh0LmFwaVRvb2xzTWV0YWRhdGEsXG4gICAgICBzZXNzaW9uOiBjb250ZXh0LnNlc3Npb24sXG4gICAgICBzYW5kYm94UmVjb3JkOiBjb250ZXh0LnNhbmRib3hSZWNvcmQsXG4gICAgICBjb250ZXh0OiBjb250ZXh0LmV2ZW50LmNvbnRleHQsXG4gICAgfSk7XG4gICAgT2JqZWN0LmFzc2lnbih0b29scywgYXBpVG9vbHMpO1xuICB9XG5cbiAgdG9vbHNbYnVpbHRpblRvb2xOYW1lcy5KYXZhU2NyaXB0XSA9IGNyZWF0ZUphdmFTY3JpcHRUb29sKHtcbiAgICB0b29scyxcbiAgICBzZXNzaW9uOiBjb250ZXh0LnNlc3Npb24sXG4gICAgc2FuZGJveDogY29udGV4dC5zYW5kYm94LFxuICAgIG9uU3ViVG9vbENhbGw6IGNvbnRleHQub25TdWJUb29sQ2FsbCxcbiAgfSk7XG5cbiAgcmV0dXJuIHRvb2xzO1xufVxuXG50eXBlIEFwaVRvb2xNZXRhZGF0YSA9IHtcbiAgbmFtZTogc3RyaW5nO1xuICBkZXNjcmlwdGlvbj86IHN0cmluZztcbiAgaW5wdXRTY2hlbWE/OiB1bmtub3duO1xufTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGZldGNoQXBpVG9vbHNNZXRhZGF0YShvcHRzOiB7XG4gIHJwYzogKHBhcmFtczogUnBjUGF5bG9hZCkgPT4gUHJvbWlzZTxScGNSZXN1bHQ+O1xufSk6IFByb21pc2U8QXBpVG9vbE1ldGFkYXRhW10+IHtcbiAgY29uc3QgeyBycGMgfSA9IG9wdHM7XG5cbiAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcnBjKHsgbWV0aG9kOiBcInRvb2xzLmxpc3RcIiwgcGFyYW1zOiB7fSB9KTtcblxuICBpZiAoXCJlcnJvclwiIGluIHJlc3VsdCkge1xuICAgIGNvbnNvbGUuZXJyb3IoXCJbYWdlbnRdIEZhaWxlZCB0byBmZXRjaCB0b29sczpcIiwgcmVzdWx0LmVycm9yPy5tZXNzYWdlKTtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICByZXR1cm4gKHJlc3VsdC5yZXN1bHQgYXMgQXBpVG9vbE1ldGFkYXRhW10pID8/IFtdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRBcGlUb29scyhvcHRzOiB7XG4gIHJwYzogKHBhcmFtczogUnBjUGF5bG9hZCkgPT4gUHJvbWlzZTxScGNSZXN1bHQ+O1xuICBtZXRhZGF0YTogQXBpVG9vbE1ldGFkYXRhW107XG4gIHNlc3Npb246IFNlc3Npb247XG4gIHNhbmRib3hSZWNvcmQ6IFNhbmRib3hSZWNvcmQ7XG4gIGNvbnRleHQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xufSk6IFRvb2xTZXQge1xuICBjb25zdCB7IHJwYywgbWV0YWRhdGEsIHNlc3Npb24sIHNhbmRib3hSZWNvcmQsIGNvbnRleHQgfSA9IG9wdHM7XG4gIGNvbnN0IHRvb2xzOiBUb29sU2V0ID0ge307XG5cbiAgZm9yIChjb25zdCBtZXRhIG9mIG1ldGFkYXRhKSB7XG4gICAgdG9vbHNbbWV0YS5uYW1lXSA9IHRvb2woe1xuICAgICAgZGVzY3JpcHRpb246IG1ldGEuZGVzY3JpcHRpb24gPz8gYEN1c3RvbSB0b29sOiAke21ldGEubmFtZX1gLFxuICAgICAgaW5wdXRTY2hlbWE6IG1ldGEuaW5wdXRTY2hlbWFcbiAgICAgICAgPyBqc29uU2NoZW1hKG1ldGEuaW5wdXRTY2hlbWEgYXMgUGFyYW1ldGVyczx0eXBlb2YganNvblNjaGVtYT5bMF0pXG4gICAgICAgIDogei5vYmplY3Qoe30pLFxuICAgICAgZXhlY3V0ZTogYXN5bmMgKGlucHV0KSA9PiB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHJwYyh7XG4gICAgICAgICAgbWV0aG9kOiBcInRvb2xzLmV4ZWN1dGVcIixcbiAgICAgICAgICBwYXJhbXM6IHtcbiAgICAgICAgICAgIG5hbWU6IG1ldGEubmFtZSxcbiAgICAgICAgICAgIGlucHV0LFxuICAgICAgICAgICAgc2Vzc2lvbixcbiAgICAgICAgICAgIHNhbmRib3hSZWNvcmQsXG4gICAgICAgICAgICBjb250ZXh0LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChcImVycm9yXCIgaW4gcmVzdWx0KSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUb29sIGV4ZWN1dGlvbiBmYWlsZWQ6ICR7cmVzdWx0LmVycm9yPy5tZXNzYWdlfWApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdC5yZXN1bHQ7XG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHRvb2xzO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZUFwaVVybChvcHRzOiB7IGFwaTogc3RyaW5nIHwgdW5kZWZpbmVkIH0pOiBzdHJpbmcge1xuICBsZXQgb3JpZ2luID0gXCJcIjtcbiAgbGV0IHBhdGggPSBgLy53ZWxsLWtub3duL2FnZW50LyR7QUdFTlRfUFJPVE9DT0xfVkVSU0lPTn1gO1xuXG4gIGlmIChvcHRzLmFwaSkge1xuICAgIGlmIChvcHRzLmFwaS5zdGFydHNXaXRoKFwiL1wiKSkge1xuICAgICAgcGF0aCA9IG9wdHMuYXBpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBzZWUgaWYgaXQncyBmdWxsXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCB1cmwgPSBuZXcgVVJMKG9wdHMuYXBpKTtcbiAgICAgICAgb3JpZ2luID0gdXJsLm9yaWdpbjtcbiAgICAgICAgY29uc3QgZnVsbFBhdGggPSB1cmwucGF0aG5hbWUgKyB1cmwuc2VhcmNoICsgdXJsLmhhc2g7XG4gICAgICAgIGlmIChmdWxsUGF0aC5zdGFydHNXaXRoKFwiL1wiKSAmJiBmdWxsUGF0aCAhPT0gXCIvXCIpIHtcbiAgICAgICAgICBwYXRoID0gZnVsbFBhdGg7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBub29wXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaWYgKCFvcmlnaW4pIHtcbiAgICBpZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09IFwiZGV2ZWxvcG1lbnRcIikge1xuICAgICAgb3JpZ2luID0gYGh0dHA6Ly9sb2NhbGhvc3Q6JHtcbiAgICAgICAgcHJvY2Vzcy5lbnYuUE9SVCA/PyBwcm9jZXNzLmVudi5ORVhUX1BVQkxJQ19QT1JUID8/IDMwMDBcbiAgICAgIH1gO1xuICAgIH1cbiAgICBjb25zdCB2ZXJjZWxVcmwgPVxuICAgICAgcHJvY2Vzcy5lbnYuVkVSQ0VMX1VSTCA/PyBwcm9jZXNzLmVudi5ORVhUX1BVQkxJQ19WRVJDRUxfVVJMO1xuICAgIGlmICh2ZXJjZWxVcmwpIHtcbiAgICAgIG9yaWdpbiA9IGBodHRwczovLyR7dmVyY2VsVXJsfWA7XG4gICAgfVxuICB9XG5cbiAgaWYgKCFvcmlnaW4pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBcIlthZ2VudF0gQ291bGRuJ3QgZGV0ZXJtaW5lIEFQSSBvcmlnaW4gKG5vIG9yaWdpbiBkZXRlY3RlZCBpbiBgYXBpYCBvcHRpb24gYW5kIG5vIFZFUkNFTF9VUkwgc2V0KVwiXG4gICAgKTtcbiAgfVxuXG4gIHJldHVybiBgJHtvcmlnaW59JHtwYXRofWA7XG59XG4iLCAiaW1wb3J0IHsgdHlwZSBUb29sU2V0LCB0b29sIH0gZnJvbSBcImFpXCI7XG5pbXBvcnQgeyB6IH0gZnJvbSBcInpvZFwiO1xuaW1wb3J0IHR5cGUgeyBTYW5kYm94IH0gZnJvbSBcIi4uL3NhbmRib3hcIjtcbmltcG9ydCB0eXBlIHsgU2Vzc2lvbiB9IGZyb20gXCIuLi9zdG9yYWdlXCI7XG5pbXBvcnQgeyBidWlsdEluVG9vbHMgfSBmcm9tIFwiLlwiO1xuXG5leHBvcnQgY29uc3QgSkFWQVNDUklQVF9UT09MX05BTUUgPSBcIkphdmFTY3JpcHRcIjtcblxuZXhwb3J0IHR5cGUgU3ViVG9vbENhbGxSZXN1bHQgPSB7IHJlc3VsdD86IHVua25vd247IGVycm9yPzogc3RyaW5nIH07XG5leHBvcnQgdHlwZSBPblN1YlRvb2xDYWxsID0gKFxuICB0b29sTmFtZTogc3RyaW5nLFxuICBpbnB1dDogdW5rbm93bixcbiAgZXhlY3V0ZTogKCkgPT4gUHJvbWlzZTx1bmtub3duPlxuKSA9PiBQcm9taXNlPFN1YlRvb2xDYWxsUmVzdWx0PjtcblxuY29uc3QgUkVRVUVTVF9NQVJLRVJfU1RBUlQgPSBcIl9fVE9PTF9SRVFVRVNUX19cIjtcbmNvbnN0IFJFUVVFU1RfTUFSS0VSX0VORCA9IFwiX19UT09MX1JFUVVFU1RfRU5EX19cIjtcbmNvbnN0IEVYRUNVVElPTl9USU1FT1VUX01TID0gNSAqIDYwICogMTAwMDtcblxuLyoqXG4gKiBUaGUgcnVubmVyIHNjcmlwdCBpcyB3cml0dGVuIHRvIHRoZSBzYW5kYm94IGFuZCBleGVjdXRlZCB2aWEgTm9kZS5qcy5cbiAqIEl0IHJlYWRzIHRoZSBtb2RlbCdzIGNvZGUgZnJvbSBjb2RlLmpzLCBzZXRzIHVwIGN0eC50b29scyBhcyBSUEMgcHJveGllc1xuICogKHJlcXVlc3RzIHNlbnQgdmlhIHN0ZGVyciBtYXJrZXJzLCByZXNwb25zZXMgcG9sbGVkIGZyb20gZmlsZXMpLCBleGVjdXRlc1xuICogdGhlIGNvZGUsIGFuZCB3cml0ZXMgdGhlIHJlc3VsdCB0byBzdGRvdXQgYXMgSlNPTi5cbiAqL1xuY29uc3QgUlVOTkVSX1NDUklQVCA9IGBcbmltcG9ydCB7IHJlYWRGaWxlU3luYywgZXhpc3RzU3luYywgdW5saW5rU3luYywgbWtkaXJTeW5jIH0gZnJvbSAnbm9kZTpmcyc7XG5pbXBvcnQgeyBqb2luLCBkaXJuYW1lIH0gZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCB7IGZpbGVVUkxUb1BhdGggfSBmcm9tICdub2RlOnVybCc7XG5cbmNvbnN0IFNDUklQVF9ESVIgPSBkaXJuYW1lKGZpbGVVUkxUb1BhdGgoaW1wb3J0Lm1ldGEudXJsKSk7XG5jb25zdCBUT09MX0NBTExfVElNRU9VVF9NUyA9IDMwMF8wMDA7XG5cbmxldCByZXFDb3VudGVyID0gMDtcblxuYXN5bmMgZnVuY3Rpb24gY2FsbFRvb2wobmFtZSwgaW5wdXQpIHtcbiAgY29uc3QgaWQgPSAncmVxXycgKyAoKytyZXFDb3VudGVyKSArICdfJyArIERhdGUubm93KCk7XG4gIGNvbnN0IHJlc3BvbnNlRmlsZSA9IGpvaW4oU0NSSVBUX0RJUiwgaWQgKyAnLnJlc3BvbnNlLmpzb24nKTtcblxuICBjb25zdCByZXF1ZXN0ID0gSlNPTi5zdHJpbmdpZnkoeyBpZCwgdG9vbDogbmFtZSwgaW5wdXQgfSk7XG4gIHByb2Nlc3Muc3RkZXJyLndyaXRlKCcke1JFUVVFU1RfTUFSS0VSX1NUQVJUfScgKyByZXF1ZXN0ICsgJyR7UkVRVUVTVF9NQVJLRVJfRU5EfScgKyAnXFxcXG4nKTtcblxuICBjb25zdCBzdGFydCA9IERhdGUubm93KCk7XG4gIHdoaWxlICghZXhpc3RzU3luYyhyZXNwb25zZUZpbGUpKSB7XG4gICAgaWYgKERhdGUubm93KCkgLSBzdGFydCA+IFRPT0xfQ0FMTF9USU1FT1VUX01TKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Rvb2wgY2FsbCAnICsgbmFtZSArICcgdGltZWQgb3V0IHdhaXRpbmcgZm9yIHJlc3BvbnNlJyk7XG4gICAgfVxuICAgIGF3YWl0IG5ldyBQcm9taXNlKHIgPT4gc2V0VGltZW91dChyLCAzMCkpO1xuICB9XG5cbiAgbGV0IHJhdztcbiAgdHJ5IHtcbiAgICByYXcgPSByZWFkRmlsZVN5bmMocmVzcG9uc2VGaWxlLCAndXRmOCcpO1xuICB9IGNhdGNoIHtcbiAgICBhd2FpdCBuZXcgUHJvbWlzZShyID0+IHNldFRpbWVvdXQociwgNTApKTtcbiAgICByYXcgPSByZWFkRmlsZVN5bmMocmVzcG9uc2VGaWxlLCAndXRmOCcpO1xuICB9XG5cbiAgY29uc3QgcmVzcG9uc2UgPSBKU09OLnBhcnNlKHJhdyk7XG4gIHRyeSB7IHVubGlua1N5bmMocmVzcG9uc2VGaWxlKTsgfSBjYXRjaCB7fVxuXG4gIGlmIChyZXNwb25zZS5lcnJvcikge1xuICAgIHRocm93IG5ldyBFcnJvcihyZXNwb25zZS5lcnJvcik7XG4gIH1cbiAgcmV0dXJuIHJlc3BvbnNlLnJlc3VsdDtcbn1cblxuY29uc3QgY29kZSA9IHJlYWRGaWxlU3luYyhqb2luKFNDUklQVF9ESVIsICdjb2RlLmpzJyksICd1dGY4Jyk7XG5jb25zdCB0b29sTmFtZXMgPSBKU09OLnBhcnNlKHJlYWRGaWxlU3luYyhqb2luKFNDUklQVF9ESVIsICd0b29scy5qc29uJyksICd1dGY4JykpO1xuXG5jb25zdCBjdHggPSB7IHRvb2xzOiB7fSB9O1xuZm9yIChjb25zdCBuYW1lIG9mIHRvb2xOYW1lcykge1xuICBjdHgudG9vbHNbbmFtZV0gPSAoaW5wdXQpID0+IGNhbGxUb29sKG5hbWUsIGlucHV0KTtcbn1cblxuY29uc3QgbG9ncyA9IFtdO1xuY29uc3QgY3VzdG9tQ29uc29sZSA9IHtcbiAgbG9nOiAoLi4uYXJncykgPT4gbG9ncy5wdXNoKGFyZ3MubWFwKGEgPT4gdHlwZW9mIGEgPT09ICdzdHJpbmcnID8gYSA6IEpTT04uc3RyaW5naWZ5KGEpKS5qb2luKCcgJykpLFxuICBlcnJvcjogKC4uLmFyZ3MpID0+IGxvZ3MucHVzaCgnW2Vycm9yXSAnICsgYXJncy5tYXAoYSA9PiB0eXBlb2YgYSA9PT0gJ3N0cmluZycgPyBhIDogSlNPTi5zdHJpbmdpZnkoYSkpLmpvaW4oJyAnKSksXG4gIHdhcm46ICguLi5hcmdzKSA9PiBsb2dzLnB1c2goJ1t3YXJuXSAnICsgYXJncy5tYXAoYSA9PiB0eXBlb2YgYSA9PT0gJ3N0cmluZycgPyBhIDogSlNPTi5zdHJpbmdpZnkoYSkpLmpvaW4oJyAnKSksXG59O1xuXG50cnkge1xuICBjb25zdCBBc3luY0Z1bmN0aW9uID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKGFzeW5jIGZ1bmN0aW9uKCkge30pLmNvbnN0cnVjdG9yO1xuICBjb25zdCBmbiA9IG5ldyBBc3luY0Z1bmN0aW9uKCdjdHgnLCAnY29uc29sZScsIGNvZGUpO1xuICBjb25zdCByZXN1bHQgPSBhd2FpdCBmbihjdHgsIGN1c3RvbUNvbnNvbGUpO1xuXG4gIGNvbnN0IG91dHB1dCA9IHsgc3VjY2VzczogdHJ1ZSwgcmVzdWx0OiByZXN1bHQgIT09IHVuZGVmaW5lZCA/IHJlc3VsdCA6IG51bGwgfTtcbiAgaWYgKGxvZ3MubGVuZ3RoID4gMCkgb3V0cHV0LmxvZ3MgPSBsb2dzO1xuICBwcm9jZXNzLnN0ZG91dC53cml0ZShKU09OLnN0cmluZ2lmeShvdXRwdXQpKTtcbn0gY2F0Y2ggKGVycikge1xuICBjb25zdCBvdXRwdXQgPSB7XG4gICAgc3VjY2VzczogZmFsc2UsXG4gICAgZXJyb3I6IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgKyAnXFxcXG4nICsgZXJyLnN0YWNrIDogU3RyaW5nKGVyciksXG4gIH07XG4gIGlmIChsb2dzLmxlbmd0aCA+IDApIG91dHB1dC5sb2dzID0gbG9ncztcbiAgcHJvY2Vzcy5zdGRvdXQud3JpdGUoSlNPTi5zdHJpbmdpZnkob3V0cHV0KSk7XG59XG5gO1xuXG4vKipcbiAqIEV4dHJhY3RzIGEgcGxhaW4gSlNPTiBTY2hlbWEgZnJvbSB3aGF0ZXZlciBmb3JtYXQgdGhlIEFJIFNESyB0b29sIHVzZXNcbiAqIChab2Qgc2NoZW1hLCBBSSBTREsgd3JhcHBlZCBzY2hlbWEsIG9yIHJhdyBKU09OIFNjaGVtYSkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBleHRyYWN0SnNvblNjaGVtYShcbiAgc2NoZW1hOiB1bmtub3duXG4pOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB8IG51bGwge1xuICBpZiAoIXNjaGVtYSB8fCB0eXBlb2Ygc2NoZW1hICE9PSBcIm9iamVjdFwiKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBpZiAoXG4gICAgXCJfZGVmXCIgaW4gc2NoZW1hICYmXG4gICAgdHlwZW9mIChzY2hlbWEgYXMgeyBfZGVmOiB1bmtub3duIH0pLl9kZWYgPT09IFwib2JqZWN0XCJcbiAgKSB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiB6LnRvSlNPTlNjaGVtYShzY2hlbWEgYXMgei5ab2RUeXBlKSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHMgPSBzY2hlbWEgYXMgUmVjb3JkPHN0cmluZyB8IHN5bWJvbCwgdW5rbm93bj47XG4gIGlmIChTeW1ib2wuZm9yKFwidmVyY2VsLmFpLnNjaGVtYVwiKSBpbiBzICYmIFwianNvblNjaGVtYVwiIGluIHMpIHtcbiAgICByZXR1cm4gcy5qc29uU2NoZW1hIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICB9XG5cbiAgaWYgKFwidHlwZVwiIGluIHMgfHwgXCJwcm9wZXJ0aWVzXCIgaW4gcykge1xuICAgIHJldHVybiBzIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICB9XG5cbiAgcmV0dXJuIG51bGw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBqc29uU2NoZW1hVG9UcyhcbiAgc2NoZW1hOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgaW5kZW50ID0gMFxuKTogc3RyaW5nIHtcbiAgaWYgKCFzY2hlbWEpIHtcbiAgICByZXR1cm4gXCJ1bmtub3duXCI7XG4gIH1cblxuICBpZiAoc2NoZW1hLmVudW0gJiYgQXJyYXkuaXNBcnJheShzY2hlbWEuZW51bSkpIHtcbiAgICByZXR1cm4gc2NoZW1hLmVudW0ubWFwKCh2KSA9PiBKU09OLnN0cmluZ2lmeSh2KSkuam9pbihcIiB8IFwiKTtcbiAgfVxuXG4gIGlmIChzY2hlbWEuYW55T2YgJiYgQXJyYXkuaXNBcnJheShzY2hlbWEuYW55T2YpKSB7XG4gICAgcmV0dXJuIHNjaGVtYS5hbnlPZlxuICAgICAgLm1hcCgoczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pID0+IGpzb25TY2hlbWFUb1RzKHMsIGluZGVudCkpXG4gICAgICAuam9pbihcIiB8IFwiKTtcbiAgfVxuICBpZiAoc2NoZW1hLm9uZU9mICYmIEFycmF5LmlzQXJyYXkoc2NoZW1hLm9uZU9mKSkge1xuICAgIHJldHVybiBzY2hlbWEub25lT2ZcbiAgICAgIC5tYXAoKHM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSA9PiBqc29uU2NoZW1hVG9UcyhzLCBpbmRlbnQpKVxuICAgICAgLmpvaW4oXCIgfCBcIik7XG4gIH1cblxuICBjb25zdCB0eXBlID0gc2NoZW1hLnR5cGUgYXMgc3RyaW5nO1xuXG4gIHN3aXRjaCAodHlwZSkge1xuICAgIGNhc2UgXCJzdHJpbmdcIjpcbiAgICAgIHJldHVybiBcInN0cmluZ1wiO1xuICAgIGNhc2UgXCJudW1iZXJcIjpcbiAgICBjYXNlIFwiaW50ZWdlclwiOlxuICAgICAgcmV0dXJuIFwibnVtYmVyXCI7XG4gICAgY2FzZSBcImJvb2xlYW5cIjpcbiAgICAgIHJldHVybiBcImJvb2xlYW5cIjtcbiAgICBjYXNlIFwibnVsbFwiOlxuICAgICAgcmV0dXJuIFwibnVsbFwiO1xuICAgIGNhc2UgXCJhcnJheVwiOiB7XG4gICAgICBjb25zdCBpdGVtcyA9IHNjaGVtYS5pdGVtc1xuICAgICAgICA/IGpzb25TY2hlbWFUb1RzKHNjaGVtYS5pdGVtcyBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiwgaW5kZW50KVxuICAgICAgICA6IFwidW5rbm93blwiO1xuICAgICAgcmV0dXJuIGBBcnJheTwke2l0ZW1zfT5gO1xuICAgIH1cbiAgICBjYXNlIFwib2JqZWN0XCI6IHtcbiAgICAgIGNvbnN0IHByb3BlcnRpZXMgPSBzY2hlbWEucHJvcGVydGllcyBhc1xuICAgICAgICB8IFJlY29yZDxzdHJpbmcsIFJlY29yZDxzdHJpbmcsIHVua25vd24+PlxuICAgICAgICB8IHVuZGVmaW5lZDtcbiAgICAgIGlmICghcHJvcGVydGllcykge1xuICAgICAgICByZXR1cm4gXCJSZWNvcmQ8c3RyaW5nLCB1bmtub3duPlwiO1xuICAgICAgfVxuICAgICAgY29uc3QgcmVxdWlyZWQgPSBuZXcgU2V0KChzY2hlbWEucmVxdWlyZWQgYXMgc3RyaW5nW10pIHx8IFtdKTtcbiAgICAgIGNvbnN0IHBhZCA9IFwiICBcIi5yZXBlYXQoaW5kZW50ICsgMSk7XG4gICAgICBjb25zdCBjbG9zZVBhZCA9IFwiICBcIi5yZXBlYXQoaW5kZW50KTtcbiAgICAgIGNvbnN0IHByb3BzID0gT2JqZWN0LmVudHJpZXMocHJvcGVydGllcykubWFwKChba2V5LCB2YWx1ZV0pID0+IHtcbiAgICAgICAgY29uc3Qgb3B0ID0gcmVxdWlyZWQuaGFzKGtleSkgPyBcIlwiIDogXCI/XCI7XG4gICAgICAgIHJldHVybiBgJHtwYWR9JHtrZXl9JHtvcHR9OiAke2pzb25TY2hlbWFUb1RzKHZhbHVlLCBpbmRlbnQgKyAxKX1gO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gYHtcXG4ke3Byb3BzLmpvaW4oXCI7XFxuXCIpfTtcXG4ke2Nsb3NlUGFkfX1gO1xuICAgIH1cbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIFwidW5rbm93blwiO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZW5lcmF0ZUNvbnRleHRUeXBlU3RyaW5nKHRvb2xzOiBUb29sU2V0KTogc3RyaW5nIHtcbiAgY29uc3Qgc2lnczogc3RyaW5nW10gPSBbXTtcblxuICBmb3IgKGNvbnN0IFtuYW1lLCB0XSBvZiBPYmplY3QuZW50cmllcyh0b29scykpIHtcbiAgICBjb25zdCByYXcgPSB0IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgIGNvbnN0IGlucHV0U2NoZW1hID0gZXh0cmFjdEpzb25TY2hlbWEocmF3LmlucHV0U2NoZW1hID8/IHJhdy5wYXJhbWV0ZXJzKTtcbiAgICBjb25zdCBvdXRwdXRTY2hlbWEgPSBleHRyYWN0SnNvblNjaGVtYShyYXcub3V0cHV0U2NoZW1hKTtcblxuICAgIGNvbnN0IGlucHV0VHlwZSA9IGlucHV0U2NoZW1hID8ganNvblNjaGVtYVRvVHMoaW5wdXRTY2hlbWEsIDIpIDogXCJ7fVwiO1xuICAgIGNvbnN0IG91dHB1dFR5cGUgPSBvdXRwdXRTY2hlbWFcbiAgICAgID8ganNvblNjaGVtYVRvVHMob3V0cHV0U2NoZW1hLCAyKVxuICAgICAgOiBcInVua25vd25cIjtcblxuICAgIHNpZ3MucHVzaChgICAgICR7bmFtZX0oaW5wdXQ6ICR7aW5wdXRUeXBlfSk6IFByb21pc2U8JHtvdXRwdXRUeXBlfT5gKTtcbiAgfVxuXG4gIHJldHVybiBgdHlwZSBDb250ZXh0ID0ge1xcbiAgdG9vbHM6IHtcXG4ke3NpZ3Muam9pbihcIjtcXG5cIil9O1xcbiAgfVxcbn1gO1xufVxuXG5hc3luYyBmdW5jdGlvbiBleGVjdXRlSW5TYW5kYm94KHtcbiAgY29kZSxcbiAgcnBjRGlyLFxuICBhYm9ydENvbnRyb2xsZXIsXG4gIHNhbmRib3gsXG4gIGF2YWlsYWJsZVRvb2xzLFxuICBvblN1YlRvb2xDYWxsLFxufToge1xuICBjb2RlOiBzdHJpbmc7XG4gIHJwY0Rpcjogc3RyaW5nO1xuICBhYm9ydENvbnRyb2xsZXI6IEFib3J0Q29udHJvbGxlcjtcbiAgc2FuZGJveDogU2FuZGJveDtcbiAgYXZhaWxhYmxlVG9vbHM6IFRvb2xTZXQ7XG4gIG9uU3ViVG9vbENhbGw/OiBPblN1YlRvb2xDYWxsO1xufSk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+IHtcbiAgY29uc3QgbWtkaXJSZXN1bHQgPSBhd2FpdCBzYW5kYm94LmV4ZWMoe1xuICAgIGNvbW1hbmQ6IFwibWtkaXJcIixcbiAgICBhcmdzOiBbXCItcFwiLCBycGNEaXJdLFxuICB9KTtcbiAgaWYgKG1rZGlyUmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICByZXR1cm4geyBzdWNjZXNzOiBmYWxzZSwgZXJyb3I6IG1rZGlyUmVzdWx0Lm1lc3NhZ2UgfTtcbiAgfVxuICBhd2FpdCBta2RpclJlc3VsdC5yZXN1bHQ7XG5cbiAgYXdhaXQgc2FuZGJveC53cml0ZUZpbGVzKHtcbiAgICBmaWxlczogW1xuICAgICAgeyBwYXRoOiBcInJ1bm5lci5tanNcIiwgY29udGVudDogUlVOTkVSX1NDUklQVCB9LFxuICAgICAgeyBwYXRoOiBcImNvZGUuanNcIiwgY29udGVudDogY29kZSB9LFxuICAgICAge1xuICAgICAgICBwYXRoOiBcInRvb2xzLmpzb25cIixcbiAgICAgICAgY29udGVudDogSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXMoYXZhaWxhYmxlVG9vbHMpKSxcbiAgICAgIH0sXG4gICAgXSxcbiAgICBkZXN0UGF0aDogcnBjRGlyLFxuICB9KTtcblxuICBjb25zdCBub2RlTWFqb3IgPSBOdW1iZXIucGFyc2VJbnQocHJvY2Vzcy52ZXJzaW9ucy5ub2RlLnNwbGl0KFwiLlwiKVswXSwgMTApO1xuICBjb25zdCBwZXJtaXNzaW9uRmxhZyA9XG4gICAgbm9kZU1ham9yID49IDIyID8gXCItLXBlcm1pc3Npb25cIiA6IFwiLS1leHBlcmltZW50YWwtcGVybWlzc2lvblwiO1xuXG4gIGNvbnN0IGV4ZWNSZXN1bHQgPSBhd2FpdCBzYW5kYm94LmV4ZWMoe1xuICAgIGNvbW1hbmQ6IFwibm9kZVwiLFxuICAgIGFyZ3M6IFtcbiAgICAgIHBlcm1pc3Npb25GbGFnLFxuICAgICAgYC0tYWxsb3ctZnMtcmVhZD0ke3JwY0Rpcn1gLFxuICAgICAgYC0tYWxsb3ctZnMtd3JpdGU9JHtycGNEaXJ9YCxcbiAgICAgIGAke3JwY0Rpcn0vcnVubmVyLm1qc2AsXG4gICAgXSxcbiAgICBzaWduYWw6IGFib3J0Q29udHJvbGxlci5zaWduYWwsXG4gIH0pO1xuXG4gIGlmIChleGVjUmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICByZXR1cm4geyBzdWNjZXNzOiBmYWxzZSwgZXJyb3I6IGV4ZWNSZXN1bHQubWVzc2FnZSB9O1xuICB9XG5cbiAgY29uc3QgZmF0YWw6IHsgZXJyb3I6IEVycm9yIHwgbnVsbCB9ID0geyBlcnJvcjogbnVsbCB9O1xuXG4gIGNvbnN0IGFib3J0ID0gKGVycm9yOiBFcnJvcikgPT4ge1xuICAgIGlmICghZmF0YWwuZXJyb3IpIHtcbiAgICAgIGZhdGFsLmVycm9yID0gZXJyb3I7XG4gICAgICBhYm9ydENvbnRyb2xsZXIuYWJvcnQoKTtcbiAgICB9XG4gIH07XG5cbiAgY29uc3QgaGFuZGxlVG9vbFJlcXVlc3QgPSBhc3luYyAocmVxdWVzdEpzb246IHN0cmluZykgPT4ge1xuICAgIGxldCBwYXJzZWQ6IHsgaWQ6IHN0cmluZzsgdG9vbDogc3RyaW5nOyBpbnB1dDogdW5rbm93biB9O1xuICAgIHRyeSB7XG4gICAgICBwYXJzZWQgPSBKU09OLnBhcnNlKHJlcXVlc3RKc29uKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB7IGlkLCB0b29sOiB0b29sTmFtZSwgaW5wdXQgfSA9IHBhcnNlZDtcblxuICAgIGxldCByZXNwb25zZTogeyByZXN1bHQ/OiB1bmtub3duOyBlcnJvcj86IHN0cmluZyB9O1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB0ID0gYXZhaWxhYmxlVG9vbHNbdG9vbE5hbWVdO1xuICAgICAgaWYgKCF0Py5leGVjdXRlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgVG9vbCAke3Rvb2xOYW1lfSBub3QgZm91bmQgb3IgaGFzIG5vIGV4ZWN1dGUgZnVuY3Rpb25gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBjb25zdCBleGVjID0gdC5leGVjdXRlLmJpbmQodCk7XG4gICAgICBpZiAob25TdWJUb29sQ2FsbCkge1xuICAgICAgICByZXNwb25zZSA9IGF3YWl0IG9uU3ViVG9vbENhbGwodG9vbE5hbWUsIGlucHV0LCAoKSA9PlxuICAgICAgICAgIGV4ZWMoaW5wdXQsIHtcbiAgICAgICAgICAgIHRvb2xDYWxsSWQ6IGBqc18ke3Rvb2xOYW1lfV8ke0RhdGUubm93KCl9YCxcbiAgICAgICAgICAgIG1lc3NhZ2VzOiBbXSxcbiAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZXhlYyhpbnB1dCwge1xuICAgICAgICAgIHRvb2xDYWxsSWQ6IGBqc18ke3Rvb2xOYW1lfV8ke0RhdGUubm93KCl9YCxcbiAgICAgICAgICBtZXNzYWdlczogW10sXG4gICAgICAgIH0pO1xuICAgICAgICByZXNwb25zZSA9IHsgcmVzdWx0IH07XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBjb25zdCBtc2cgPSBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVycik7XG4gICAgICByZXNwb25zZSA9IHsgZXJyb3I6IG1zZyB9O1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCBzYW5kYm94LndyaXRlRmlsZXMoe1xuICAgICAgICBmaWxlczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIHBhdGg6IGAke2lkfS5yZXNwb25zZS5qc29uYCxcbiAgICAgICAgICAgIGNvbnRlbnQ6IEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlKSxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgICBkZXN0UGF0aDogcnBjRGlyLFxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAvKipcbiAgICAgICAqIElmIHdyaXRpbmcgdGhlIHJlc3BvbnNlIGZpbGUgZmFpbHMsIHRoZSBydW5uZXIgd2lsbCBwb2xsIGZvcmV2ZXJcbiAgICAgICAqIHdhaXRpbmcgZm9yIGl0LiBBYm9ydCB0aGUgcnVubmVyIHByb2Nlc3Mgc28gd2UgZG9uJ3QgZGVhZGxvY2suXG4gICAgICAgKi9cbiAgICAgIGNvbnN0IG1zZyA9IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKTtcbiAgICAgIGFib3J0KG5ldyBFcnJvcihgRmFpbGVkIHRvIHdyaXRlIFJQQyByZXNwb25zZSBmb3IgJHt0b29sTmFtZX06ICR7bXNnfWApKTtcbiAgICB9XG4gIH07XG5cbiAgY29uc3QgdG9vbENhbGxQcm9taXNlczogUHJvbWlzZTx2b2lkPltdID0gW107XG4gIGxldCBzdGRlcnJCdWZmZXIgPSBcIlwiO1xuICBsZXQgbm9uTWFya2VyU3RkZXJyID0gXCJcIjtcblxuICBjb25zdCB0aW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgYWJvcnQoXG4gICAgICBuZXcgRXJyb3IoXG4gICAgICAgIGBKYXZhU2NyaXB0IGV4ZWN1dGlvbiB0aW1lZCBvdXQgYWZ0ZXIgJHtFWEVDVVRJT05fVElNRU9VVF9NUyAvIDEwMDB9c2BcbiAgICAgIClcbiAgICApO1xuICB9LCBFWEVDVVRJT05fVElNRU9VVF9NUyk7XG5cbiAgdHJ5IHtcbiAgICBmb3IgYXdhaXQgKGNvbnN0IGVudHJ5IG9mIGV4ZWNSZXN1bHQubG9ncygpKSB7XG4gICAgICBpZiAoZmF0YWwuZXJyb3IpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICAgIGlmIChlbnRyeS5zdHJlYW0gPT09IFwic3RkZXJyXCIpIHtcbiAgICAgICAgc3RkZXJyQnVmZmVyICs9IGVudHJ5LmRhdGE7XG5cbiAgICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgICBjb25zdCBzdGFydElkeCA9IHN0ZGVyckJ1ZmZlci5pbmRleE9mKFJFUVVFU1RfTUFSS0VSX1NUQVJUKTtcbiAgICAgICAgICBpZiAoc3RhcnRJZHggPT09IC0xKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBiZWZvcmVNYXJrZXIgPSBzdGRlcnJCdWZmZXIuc2xpY2UoMCwgc3RhcnRJZHgpO1xuICAgICAgICAgIGlmIChiZWZvcmVNYXJrZXIudHJpbSgpKSB7XG4gICAgICAgICAgICBub25NYXJrZXJTdGRlcnIgKz0gYmVmb3JlTWFya2VyO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IGNvbnRlbnRTdGFydCA9IHN0YXJ0SWR4ICsgUkVRVUVTVF9NQVJLRVJfU1RBUlQubGVuZ3RoO1xuICAgICAgICAgIGNvbnN0IGVuZElkeCA9IHN0ZGVyckJ1ZmZlci5pbmRleE9mKFJFUVVFU1RfTUFSS0VSX0VORCwgY29udGVudFN0YXJ0KTtcbiAgICAgICAgICBpZiAoZW5kSWR4ID09PSAtMSkge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgcmVxdWVzdEpzb24gPSBzdGRlcnJCdWZmZXIuc2xpY2UoY29udGVudFN0YXJ0LCBlbmRJZHgpO1xuICAgICAgICAgIHN0ZGVyckJ1ZmZlciA9IHN0ZGVyckJ1ZmZlci5zbGljZShlbmRJZHggKyBSRVFVRVNUX01BUktFUl9FTkQubGVuZ3RoKTtcblxuICAgICAgICAgIHRvb2xDYWxsUHJvbWlzZXMucHVzaChoYW5kbGVUb29sUmVxdWVzdChyZXF1ZXN0SnNvbikpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9IGZpbmFsbHkge1xuICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgfVxuXG4gIGlmIChzdGRlcnJCdWZmZXIudHJpbSgpKSB7XG4gICAgbm9uTWFya2VyU3RkZXJyICs9IHN0ZGVyckJ1ZmZlcjtcbiAgfVxuXG4gIGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZCh0b29sQ2FsbFByb21pc2VzKTtcblxuICBpZiAoZmF0YWwuZXJyb3IpIHtcbiAgICBleGVjUmVzdWx0LnJlc3VsdC5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuICAgIHJldHVybiB7XG4gICAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICAgIGVycm9yOiBmYXRhbC5lcnJvci5tZXNzYWdlLFxuICAgICAgLi4uKG5vbk1hcmtlclN0ZGVyciA/IHsgc3RkZXJyOiBub25NYXJrZXJTdGRlcnIuc2xpY2UoMCwgMjAwMCkgfSA6IHt9KSxcbiAgICB9O1xuICB9XG5cbiAgY29uc3QgeyBzdGRvdXQsIHN0ZGVyciwgZXhpdENvZGUgfSA9IGF3YWl0IGV4ZWNSZXN1bHQucmVzdWx0O1xuXG4gIHRyeSB7XG4gICAgcmV0dXJuIEpTT04ucGFyc2Uoc3Rkb3V0KTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgZXJyb3I6IGBSdW5uZXIgZmFpbGVkIChleGl0ICR7ZXhpdENvZGV9KS5gLFxuICAgICAgc3RkZXJyOiAobm9uTWFya2VyU3RkZXJyICsgc3RkZXJyKS5zbGljZSgwLCAyMDAwKSxcbiAgICAgIHN0ZG91dDogc3Rkb3V0LnNsaWNlKDAsIDEwMDApLFxuICAgIH07XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUphdmFTY3JpcHRUb29sKG9wdHM6IHtcbiAgdG9vbHM6IFRvb2xTZXQ7XG4gIHNlc3Npb246IFNlc3Npb247XG4gIHNhbmRib3g6IFNhbmRib3g7XG4gIG9uU3ViVG9vbENhbGw/OiBPblN1YlRvb2xDYWxsO1xufSkge1xuICBjb25zdCB7IHNlc3Npb24sIHNhbmRib3gsIG9uU3ViVG9vbENhbGwgfSA9IG9wdHM7XG4gIGNvbnN0IGFjdGl2ZVNldCA9IHNlc3Npb24uYWN0aXZlVG9vbHMgPyBuZXcgU2V0KHNlc3Npb24uYWN0aXZlVG9vbHMpIDogbnVsbDtcbiAgY29uc3QgYXZhaWxhYmxlVG9vbHM6IFRvb2xTZXQgPSB7fTtcbiAgZm9yIChjb25zdCBbbmFtZSwgdF0gb2YgT2JqZWN0LmVudHJpZXMob3B0cy50b29scykpIHtcbiAgICBpZiAoIWFjdGl2ZVNldCB8fCBhY3RpdmVTZXQuaGFzKG5hbWUpKSB7XG4gICAgICBhdmFpbGFibGVUb29sc1tuYW1lXSA9IHQ7XG4gICAgfVxuICB9XG4gIGNvbnN0IGNvbnRleHRUeXBlID0gZ2VuZXJhdGVDb250ZXh0VHlwZVN0cmluZyhhdmFpbGFibGVUb29scyk7XG5cbiAgcmV0dXJuIHRvb2woe1xuICAgIC4uLmJ1aWx0SW5Ub29scy5KYXZhU2NyaXB0LFxuICAgIGRlc2NyaXB0aW9uOiBgRXhlY3V0ZSBKYXZhU2NyaXB0IHRvIG9yY2hlc3RyYXRlIG11bHRpcGxlIHRvb2wgY2FsbHMgaW4gYSBzaW5nbGUgc3RlcC4gVXNlIHRoaXMgd2hlbiB5b3UgbmVlZCB0byBydW4gc2V2ZXJhbCB0b29scyBpbiBzZXF1ZW5jZSwgdHJhbnNmb3JtIGludGVybWVkaWF0ZSByZXN1bHRzLCBvciBwYXJhbGxlbGl6ZSBpbmRlcGVuZGVudCBvcGVyYXRpb25zIHdpdGggUHJvbWlzZS5hbGwuXG5cblRoZSBjb2RlIHJ1bnMgYXMgYW4gYXN5bmMgZnVuY3Rpb24gYm9keSB3aXRoIFxcYGN0eFxcYCBpbiBzY29wZTpcblxuXFxgXFxgXFxgdHlwZXNjcmlwdFxuJHtjb250ZXh0VHlwZX1cblxcYFxcYFxcYFxuXG5FeGFtcGxlczpcbi0gU2VxdWVudGlhbDogXFxgY29uc3QgZmlsZSA9IGF3YWl0IGN0eC50b29scy5SZWFkKHsgcGF0aDogXCJwYWNrYWdlLmpzb25cIiB9KTsgcmV0dXJuIEpTT04ucGFyc2UoZmlsZS5jb250ZW50KTtcXGBcbi0gUGFyYWxsZWw6IFxcYGNvbnN0IFthLCBiXSA9IGF3YWl0IFByb21pc2UuYWxsKFtjdHgudG9vbHMuUmVhZCh7IHBhdGg6IFwiYS50c1wiIH0pLCBjdHgudG9vbHMuUmVhZCh7IHBhdGg6IFwiYi50c1wiIH0pXSk7IHJldHVybiB7IGE6IGEuY29udGVudCwgYjogYi5jb250ZW50IH07XFxgXG4tIFRyYW5zZm9ybTogXFxgY29uc3QgZ3JlcCA9IGF3YWl0IGN0eC50b29scy5HcmVwKHsgcGF0dGVybjogXCJUT0RPXCIgfSk7IHJldHVybiBncmVwLm1hdGNoZXMuc3BsaXQoXCJcXFxcblwiKS5sZW5ndGg7XFxgXG5cblJldHVybiBhIHZhbHVlIHRvIHBhc3MgcmVzdWx0cyBiYWNrLiBVc2UgY29uc29sZS5sb2coKSBmb3IgZGVidWcgb3V0cHV0LmAsXG4gICAgZXhlY3V0ZTogKHsgY29kZSB9KSA9PiB7XG4gICAgICBjb25zdCBydW5JZCA9IGBydW5fJHtEYXRlLm5vdygpfV8ke01hdGgucmFuZG9tKClcbiAgICAgICAgLnRvU3RyaW5nKDM2KVxuICAgICAgICAuc2xpY2UoMiwgOCl9YDtcbiAgICAgIGNvbnN0IHJwY0RpciA9IGAuYWdlbnQvanMtcnBjLyR7cnVuSWR9YDtcbiAgICAgIGNvbnN0IGFib3J0Q29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcblxuICAgICAgcmV0dXJuIGV4ZWN1dGVJblNhbmRib3goe1xuICAgICAgICBjb2RlLFxuICAgICAgICBycGNEaXIsXG4gICAgICAgIGFib3J0Q29udHJvbGxlcixcbiAgICAgICAgc2FuZGJveCxcbiAgICAgICAgYXZhaWxhYmxlVG9vbHMsXG4gICAgICAgIG9uU3ViVG9vbENhbGwsXG4gICAgICB9KTtcbiAgICB9LFxuICB9KTtcbn1cbiIsICJpbXBvcnQgdHlwZSB7IEpTT05WYWx1ZSwgTW9kZWxNZXNzYWdlIH0gZnJvbSBcImFpXCI7XG5cbnR5cGUgUHJvdmlkZXJPcHRpb25zID0gUmVjb3JkPHN0cmluZywgUmVjb3JkPHN0cmluZywgSlNPTlZhbHVlPj47XG5cbmNvbnN0IEFOVEhST1BJQ19NQVhfQ0FDSEVfQlJFQUtQT0lOVFNfUEVSX1JFUVVFU1QgPSA0O1xuXG5jb25zdCBDTEFVREVfTElLRV9NT0RFTF9NQVRDSEVSUyA9IFtcImNsYXVkZVwiLCBcImFudGhyb3BpY1wiXTtcblxuY29uc3QgQ0xBVURFX1BST01QVF9DQUNISU5HX1BST1ZJREVSX09QVElPTlM6IFByb3ZpZGVyT3B0aW9ucyA9IHtcbiAgYW50aHJvcGljOiB7XG4gICAgY2FjaGVDb250cm9sOiB7IHR5cGU6IFwiZXBoZW1lcmFsXCIgfSxcbiAgfSxcbiAgb3BlbnJvdXRlcjoge1xuICAgIGNhY2hlQ29udHJvbDogeyB0eXBlOiBcImVwaGVtZXJhbFwiIH0sXG4gIH0sXG4gIGJlZHJvY2s6IHtcbiAgICBjYWNoZVBvaW50OiB7IHR5cGU6IFwiZGVmYXVsdFwiIH0sXG4gIH0sXG4gIG9wZW5haUNvbXBhdGlibGU6IHtcbiAgICBjYWNoZV9jb250cm9sOiB7IHR5cGU6IFwiZXBoZW1lcmFsXCIgfSxcbiAgfSxcbiAgY29waWxvdDoge1xuICAgIGNvcGlsb3RfY2FjaGVfY29udHJvbDogeyB0eXBlOiBcImVwaGVtZXJhbFwiIH0sXG4gIH0sXG59O1xuXG5mdW5jdGlvbiBnZXRHYXRld2F5UHJvdmlkZXIobW9kZWw6IHN0cmluZyk6IHN0cmluZyB8IG51bGwge1xuICBjb25zdCBzbGFzaEluZGV4ID0gbW9kZWwuaW5kZXhPZihcIi9cIik7XG4gIGlmIChzbGFzaEluZGV4ID09PSAtMSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIHJldHVybiBtb2RlbC5zbGljZSgwLCBzbGFzaEluZGV4KTtcbn1cblxuZnVuY3Rpb24gY291bnRBbnRocm9waWNDYWNoZUJyZWFrcG9pbnRzKG1lc3NhZ2VzOiBNb2RlbE1lc3NhZ2VbXSk6IG51bWJlciB7XG4gIGxldCBjb3VudCA9IDA7XG4gIGZvciAoY29uc3QgbWVzc2FnZSBvZiBtZXNzYWdlcykge1xuICAgIGNvbnN0IHByb3ZpZGVyT3B0aW9ucyA9IChtZXNzYWdlIGFzIHsgcHJvdmlkZXJPcHRpb25zPzogUHJvdmlkZXJPcHRpb25zIH0pXG4gICAgICAucHJvdmlkZXJPcHRpb25zO1xuICAgIGlmIChwcm92aWRlck9wdGlvbnM/LmFudGhyb3BpYz8uY2FjaGVDb250cm9sKSB7XG4gICAgICBjb3VudCArPSAxO1xuICAgIH1cbiAgICBpZiAoQXJyYXkuaXNBcnJheShtZXNzYWdlLmNvbnRlbnQpKSB7XG4gICAgICBmb3IgKGNvbnN0IHBhcnQgb2YgbWVzc2FnZS5jb250ZW50KSB7XG4gICAgICAgIGNvbnN0IHBhcnRQcm92aWRlck9wdGlvbnMgPSAoXG4gICAgICAgICAgcGFydCBhcyB7IHByb3ZpZGVyT3B0aW9ucz86IFByb3ZpZGVyT3B0aW9ucyB9XG4gICAgICAgICkucHJvdmlkZXJPcHRpb25zO1xuICAgICAgICBpZiAocGFydFByb3ZpZGVyT3B0aW9ucz8uYW50aHJvcGljPy5jYWNoZUNvbnRyb2wpIHtcbiAgICAgICAgICBjb3VudCArPSAxO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBjb3VudDtcbn1cblxuZnVuY3Rpb24gaXNDbGF1ZGVMaWtlTW9kZWwobW9kZWw6IHN0cmluZyk6IGJvb2xlYW4ge1xuICBjb25zdCBsb3dlciA9IG1vZGVsLnRvTG93ZXJDYXNlKCk7XG4gIHJldHVybiBDTEFVREVfTElLRV9NT0RFTF9NQVRDSEVSUy5zb21lKChtKSA9PiBsb3dlci5pbmNsdWRlcyhtKSk7XG59XG5cbmZ1bmN0aW9uIG1lcmdlUHJvdmlkZXJPcHRpb25zKG9wdHM6IHtcbiAgY3VycmVudDogUHJvdmlkZXJPcHRpb25zIHwgdW5kZWZpbmVkO1xuICBwYXRjaDogUHJvdmlkZXJPcHRpb25zO1xufSk6IFByb3ZpZGVyT3B0aW9ucyB7XG4gIGNvbnN0IG5leHQ6IFByb3ZpZGVyT3B0aW9ucyA9IHsgLi4uKG9wdHMuY3VycmVudCA/PyB7fSkgfTtcbiAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMob3B0cy5wYXRjaCkpIHtcbiAgICBuZXh0W2tleV0gPSB7IC4uLihuZXh0W2tleV0gPz8ge30pLCAuLi52YWx1ZSB9O1xuICB9XG4gIHJldHVybiBuZXh0O1xufVxuXG5mdW5jdGlvbiBpc0NhY2hlYWJsZUNsYXVkZVBhcnQocGFydDogdW5rbm93bik6IGJvb2xlYW4ge1xuICBpZiAoIXBhcnQgfHwgdHlwZW9mIHBhcnQgIT09IFwib2JqZWN0XCIpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBpZiAoXCJ0eXBlXCIgaW4gcGFydCAmJiAocGFydCBhcyB7IHR5cGU/OiB1bmtub3duIH0pLnR5cGUgPT09IFwidGV4dFwiKSB7XG4gICAgY29uc3QgdGV4dCA9IChwYXJ0IGFzIHsgdGV4dD86IHVua25vd24gfSkudGV4dDtcbiAgICBpZiAodHlwZW9mIHRleHQgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgIHJldHVybiB0ZXh0LnRyaW0oKS5sZW5ndGggPiAwO1xuICAgIH1cbiAgfVxuXG4gIGlmIChcInR5cGVcIiBpbiBwYXJ0KSB7XG4gICAgY29uc3QgdHlwZSA9IChwYXJ0IGFzIHsgdHlwZT86IHVua25vd24gfSkudHlwZTtcbiAgICBpZiAodHlwZSA9PT0gXCJ0aGlua2luZ1wiIHx8IHR5cGUgPT09IFwicmVhc29uaW5nXCIpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gaGFzQ2FjaGVhYmxlQ29udGVudChtZXNzYWdlOiBNb2RlbE1lc3NhZ2UpOiBib29sZWFuIHtcbiAgaWYgKHR5cGVvZiBtZXNzYWdlLmNvbnRlbnQgPT09IFwic3RyaW5nXCIpIHtcbiAgICByZXR1cm4gbWVzc2FnZS5jb250ZW50LnRyaW0oKS5sZW5ndGggPiAwO1xuICB9XG5cbiAgaWYgKEFycmF5LmlzQXJyYXkobWVzc2FnZS5jb250ZW50KSkge1xuICAgIHJldHVybiBtZXNzYWdlLmNvbnRlbnQuc29tZSgocGFydCkgPT4gaXNDYWNoZWFibGVDbGF1ZGVQYXJ0KHBhcnQpKTtcbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gZmluZExhc3RDYWNoZWFibGVQYXJ0SW5kZXgoY29udGVudDogdW5rbm93bltdKTogbnVtYmVyIHwgbnVsbCB7XG4gIGZvciAobGV0IGkgPSBjb250ZW50Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaSAtPSAxKSB7XG4gICAgaWYgKGlzQ2FjaGVhYmxlQ2xhdWRlUGFydChjb250ZW50W2ldKSkge1xuICAgICAgcmV0dXJuIGk7XG4gICAgfVxuICB9XG4gIHJldHVybiBudWxsO1xufVxuXG5mdW5jdGlvbiBzZWxlY3RDbGF1ZGVDYWNoaW5nVGFyZ2V0cyhtZXNzYWdlczogTW9kZWxNZXNzYWdlW10pOiBudW1iZXJbXSB7XG4gIGNvbnN0IHN5c3RlbUluZGljZXM6IG51bWJlcltdID0gW107XG4gIGNvbnN0IGZpbmFsSW5kaWNlczogbnVtYmVyW10gPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IG1lc3NhZ2VzLmxlbmd0aCAmJiBzeXN0ZW1JbmRpY2VzLmxlbmd0aCA8IDI7IGkgKz0gMSkge1xuICAgIGNvbnN0IG1lc3NhZ2UgPSBtZXNzYWdlc1tpXTtcbiAgICBpZiAobWVzc2FnZS5yb2xlID09PSBcInN5c3RlbVwiICYmIGhhc0NhY2hlYWJsZUNvbnRlbnQobWVzc2FnZSkpIHtcbiAgICAgIHN5c3RlbUluZGljZXMucHVzaChpKTtcbiAgICB9XG4gIH1cblxuICBmb3IgKGxldCBpID0gbWVzc2FnZXMubGVuZ3RoIC0gMTsgaSA+PSAwICYmIGZpbmFsSW5kaWNlcy5sZW5ndGggPCAyOyBpIC09IDEpIHtcbiAgICBjb25zdCBtZXNzYWdlID0gbWVzc2FnZXNbaV07XG4gICAgaWYgKG1lc3NhZ2Uucm9sZSAhPT0gXCJzeXN0ZW1cIiAmJiBoYXNDYWNoZWFibGVDb250ZW50KG1lc3NhZ2UpKSB7XG4gICAgICBmaW5hbEluZGljZXMucHVzaChpKTtcbiAgICB9XG4gIH1cblxuICBmaW5hbEluZGljZXMucmV2ZXJzZSgpO1xuXG4gIHJldHVybiBbLi4uc3lzdGVtSW5kaWNlcywgLi4uZmluYWxJbmRpY2VzXTtcbn1cblxuZnVuY3Rpb24gYXBwbHlDbGF1ZGVQcm9tcHRDYWNoaW5nKG9wdHM6IHtcbiAgbWVzc2FnZXM6IE1vZGVsTWVzc2FnZVtdO1xuICBwcm92aWRlcklkOiBzdHJpbmcgfCBudWxsO1xuICBtYXhCcmVha3BvaW50c1BlclJlcXVlc3Q6IG51bWJlcjtcbn0pOiBNb2RlbE1lc3NhZ2VbXSB7XG4gIGNvbnN0IGV4aXN0aW5nQnJlYWtwb2ludHMgPSBjb3VudEFudGhyb3BpY0NhY2hlQnJlYWtwb2ludHMob3B0cy5tZXNzYWdlcyk7XG4gIGNvbnN0IHJlbWFpbmluZ0J1ZGdldCA9IE1hdGgubWF4KFxuICAgIDAsXG4gICAgb3B0cy5tYXhCcmVha3BvaW50c1BlclJlcXVlc3QgLSBleGlzdGluZ0JyZWFrcG9pbnRzXG4gICk7XG5cbiAgaWYgKHJlbWFpbmluZ0J1ZGdldCA9PT0gMCkge1xuICAgIHJldHVybiBvcHRzLm1lc3NhZ2VzO1xuICB9XG5cbiAgY29uc3QgdGFyZ2V0SW5kaWNlcyA9IHNlbGVjdENsYXVkZUNhY2hpbmdUYXJnZXRzKG9wdHMubWVzc2FnZXMpLnNsaWNlKFxuICAgIDAsXG4gICAgcmVtYWluaW5nQnVkZ2V0XG4gICk7XG4gIGlmICh0YXJnZXRJbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBvcHRzLm1lc3NhZ2VzO1xuICB9XG5cbiAgY29uc3QgdXNlTWVzc2FnZUxldmVsT3B0aW9ucyA9XG4gICAgb3B0cy5wcm92aWRlcklkID09PSBcImFudGhyb3BpY1wiIHx8XG4gICAgQm9vbGVhbihvcHRzLnByb3ZpZGVySWQ/LmluY2x1ZGVzKFwiYmVkcm9ja1wiKSk7XG5cbiAgY29uc3QgbmV4dE1lc3NhZ2VzID0gb3B0cy5tZXNzYWdlcy5zbGljZSgpO1xuXG4gIGZvciAoY29uc3QgbWVzc2FnZUluZGV4IG9mIHRhcmdldEluZGljZXMpIHtcbiAgICBjb25zdCBtZXNzYWdlID0gbmV4dE1lc3NhZ2VzW21lc3NhZ2VJbmRleF07XG5cbiAgICBjb25zdCBzaG91bGRVc2VDb250ZW50T3B0aW9ucyA9XG4gICAgICAhdXNlTWVzc2FnZUxldmVsT3B0aW9ucyAmJlxuICAgICAgQXJyYXkuaXNBcnJheShtZXNzYWdlLmNvbnRlbnQpICYmXG4gICAgICBtZXNzYWdlLmNvbnRlbnQubGVuZ3RoID4gMDtcblxuICAgIGlmIChzaG91bGRVc2VDb250ZW50T3B0aW9ucyAmJiBBcnJheS5pc0FycmF5KG1lc3NhZ2UuY29udGVudCkpIHtcbiAgICAgIGNvbnN0IHBhcnRJbmRleCA9IGZpbmRMYXN0Q2FjaGVhYmxlUGFydEluZGV4KG1lc3NhZ2UuY29udGVudCk7XG4gICAgICBpZiAocGFydEluZGV4ICE9PSBudWxsKSB7XG4gICAgICAgIGNvbnN0IHBhcnQgPSBtZXNzYWdlLmNvbnRlbnRbcGFydEluZGV4XTtcbiAgICAgICAgaWYgKHBhcnQgJiYgdHlwZW9mIHBhcnQgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgICBjb25zdCBwYXJ0UHJvdmlkZXJPcHRpb25zID0gKFxuICAgICAgICAgICAgcGFydCBhcyB7IHByb3ZpZGVyT3B0aW9ucz86IFByb3ZpZGVyT3B0aW9ucyB9XG4gICAgICAgICAgKS5wcm92aWRlck9wdGlvbnM7XG5cbiAgICAgICAgICBjb25zdCBuZXh0Q29udGVudCA9IG1lc3NhZ2UuY29udGVudC5zbGljZSgpO1xuICAgICAgICAgIG5leHRDb250ZW50W3BhcnRJbmRleF0gPSB7XG4gICAgICAgICAgICAuLi4ocGFydCBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiksXG4gICAgICAgICAgICBwcm92aWRlck9wdGlvbnM6IG1lcmdlUHJvdmlkZXJPcHRpb25zKHtcbiAgICAgICAgICAgICAgY3VycmVudDogcGFydFByb3ZpZGVyT3B0aW9ucyxcbiAgICAgICAgICAgICAgcGF0Y2g6IENMQVVERV9QUk9NUFRfQ0FDSElOR19QUk9WSURFUl9PUFRJT05TLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgfSBhcyAodHlwZW9mIG1lc3NhZ2UuY29udGVudClbbnVtYmVyXTtcblxuICAgICAgICAgIG5leHRNZXNzYWdlc1ttZXNzYWdlSW5kZXhdID0ge1xuICAgICAgICAgICAgLi4ubWVzc2FnZSxcbiAgICAgICAgICAgIGNvbnRlbnQ6IG5leHRDb250ZW50LFxuICAgICAgICAgIH0gYXMgTW9kZWxNZXNzYWdlO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgbWVzc2FnZVByb3ZpZGVyT3B0aW9ucyA9IChcbiAgICAgIG1lc3NhZ2UgYXMgeyBwcm92aWRlck9wdGlvbnM/OiBQcm92aWRlck9wdGlvbnMgfVxuICAgICkucHJvdmlkZXJPcHRpb25zO1xuXG4gICAgbmV4dE1lc3NhZ2VzW21lc3NhZ2VJbmRleF0gPSB7XG4gICAgICAuLi5tZXNzYWdlLFxuICAgICAgcHJvdmlkZXJPcHRpb25zOiBtZXJnZVByb3ZpZGVyT3B0aW9ucyh7XG4gICAgICAgIGN1cnJlbnQ6IG1lc3NhZ2VQcm92aWRlck9wdGlvbnMsXG4gICAgICAgIHBhdGNoOiBDTEFVREVfUFJPTVBUX0NBQ0hJTkdfUFJPVklERVJfT1BUSU9OUyxcbiAgICAgIH0pLFxuICAgIH07XG4gIH1cblxuICByZXR1cm4gbmV4dE1lc3NhZ2VzO1xufVxuXG5leHBvcnQgdHlwZSBQcm9tcHRDYWNoaW5nUmVzdWx0ID0ge1xuICBtZXNzYWdlczogTW9kZWxNZXNzYWdlW107XG4gIHByb3ZpZGVyT3B0aW9uczogUHJvdmlkZXJPcHRpb25zO1xufTtcblxuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5UHJvbXB0Q2FjaGluZ1RvTW9kZWxSZXF1ZXN0KG9wdHM6IHtcbiAgbW9kZWw6IHN0cmluZztcbiAgc2Vzc2lvbklkOiBzdHJpbmc7XG4gIG1lc3NhZ2VzOiBNb2RlbE1lc3NhZ2VbXTtcbiAgYW50aHJvcGljPzogeyBtYXhCcmVha3BvaW50c1BlclJlcXVlc3Q/OiBudW1iZXIgfTtcbiAgb3BlbmFpPzogeyBzZXRQcm9tcHRDYWNoZUtleT86IGJvb2xlYW4gfTtcbn0pOiBQcm9tcHRDYWNoaW5nUmVzdWx0IHtcbiAgY29uc3QgcHJvdmlkZXIgPSBnZXRHYXRld2F5UHJvdmlkZXIob3B0cy5tb2RlbCk7XG5cbiAgY29uc3QgcHJvdmlkZXJPcHRpb25zOiBQcm92aWRlck9wdGlvbnMgPSB7fTtcblxuICBpZiAoXG4gICAgKHByb3ZpZGVyID09PSBcIm9wZW5haVwiIHx8IHByb3ZpZGVyID09PSBcImF6dXJlXCIpICYmXG4gICAgb3B0cy5vcGVuYWk/LnNldFByb21wdENhY2hlS2V5ICE9PSBmYWxzZVxuICApIHtcbiAgICBwcm92aWRlck9wdGlvbnMub3BlbmFpID0geyBwcm9tcHRDYWNoZUtleTogb3B0cy5zZXNzaW9uSWQgfTtcbiAgfVxuXG4gIGNvbnN0IG1heEJyZWFrcG9pbnRzUGVyUmVxdWVzdCA9XG4gICAgb3B0cy5hbnRocm9waWM/Lm1heEJyZWFrcG9pbnRzUGVyUmVxdWVzdCA/P1xuICAgIEFOVEhST1BJQ19NQVhfQ0FDSEVfQlJFQUtQT0lOVFNfUEVSX1JFUVVFU1Q7XG5cbiAgY29uc3QgY2FjaGVkTWVzc2FnZXMgPSBpc0NsYXVkZUxpa2VNb2RlbChvcHRzLm1vZGVsKVxuICAgID8gYXBwbHlDbGF1ZGVQcm9tcHRDYWNoaW5nKHtcbiAgICAgICAgbWVzc2FnZXM6IG9wdHMubWVzc2FnZXMsXG4gICAgICAgIHByb3ZpZGVySWQ6IHByb3ZpZGVyLFxuICAgICAgICBtYXhCcmVha3BvaW50c1BlclJlcXVlc3QsXG4gICAgICB9KVxuICAgIDogb3B0cy5tZXNzYWdlcztcblxuICByZXR1cm4ge1xuICAgIG1lc3NhZ2VzOiBjYWNoZWRNZXNzYWdlcyxcbiAgICBwcm92aWRlck9wdGlvbnMsXG4gIH07XG59XG4iLCAiaW1wb3J0IHR5cGUgeyBVSU1lc3NhZ2UgfSBmcm9tIFwiYWlcIjtcbmltcG9ydCB0eXBlIHsgTWVzc2FnZSwgUGFydCB9IGZyb20gXCIuLi9zdG9yYWdlXCI7XG5cbi8qKiBTdWItdG9vbCBwYXJ0cyAoZnJvbSBKYXZhU2NyaXB0IG1ldGEtdG9vbCkgdXNlIHRoaXMgdG9vbENhbGxJZCBwcmVmaXguICovXG5mdW5jdGlvbiBpc1N1YlRvb2xQYXJ0KHBhcnQ6IFBhcnQpOiBib29sZWFuIHtcbiAgY29uc3QgcCA9IHBhcnQucGFydCBhcyB7IHRvb2xDYWxsSWQ/OiBzdHJpbmcgfTtcbiAgcmV0dXJuIHR5cGVvZiBwPy50b29sQ2FsbElkID09PSBcInN0cmluZ1wiICYmIHAudG9vbENhbGxJZC5zdGFydHNXaXRoKFwianNfdGNfXCIpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYXNzZW1ibGVVSU1lc3NhZ2VzKG9wdHM6IHtcbiAgbWVzc2FnZXM6IE1lc3NhZ2VbXTtcbiAgcGFydHM6IFBhcnRbXTtcbiAgdW50aWw/OiBudW1iZXI7XG4gIGluY2x1ZGVRdWV1ZWQ/OiBib29sZWFuO1xuICAvKiogV2hlbiB0cnVlLCBmaWx0ZXJzIG91dCBzdWItdG9vbCBwYXJ0cyBzbyB0aGUgTExNIGRvZXNuJ3Qgc2VlIHRoZW0uICovXG4gIGV4Y2x1ZGVTdWJUb29sUGFydHM/OiBib29sZWFuO1xufSk6IFVJTWVzc2FnZVtdIHtcbiAgbGV0IGZpbHRlcmVkID0gb3B0cy5tZXNzYWdlcztcblxuICBpZiAob3B0cy51bnRpbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uc3QgdW50aWwgPSBvcHRzLnVudGlsO1xuICAgIGZpbHRlcmVkID0gZmlsdGVyZWQuZmlsdGVyKChtKSA9PiBtLmNyZWF0ZWRBdCA8PSB1bnRpbCk7XG4gIH1cblxuICBpZiAoIW9wdHMuaW5jbHVkZVF1ZXVlZCkge1xuICAgIGZpbHRlcmVkID0gZmlsdGVyZWQuZmlsdGVyKChtKSA9PiBtLnN0YXJ0ZWRBdCAhPT0gbnVsbCk7XG4gIH1cblxuICBjb25zdCBwYXJ0cyA9IG9wdHMuZXhjbHVkZVN1YlRvb2xQYXJ0c1xuICAgID8gb3B0cy5wYXJ0cy5maWx0ZXIoKHApID0+ICFpc1N1YlRvb2xQYXJ0KHApKVxuICAgIDogb3B0cy5wYXJ0cztcblxuICBjb25zdCBwYXJ0c0J5TWVzc2FnZSA9IG5ldyBNYXA8c3RyaW5nLCBQYXJ0W10+KCk7XG4gIGZvciAoY29uc3QgcGFydCBvZiBwYXJ0cykge1xuICAgIGNvbnN0IGV4aXN0aW5nID0gcGFydHNCeU1lc3NhZ2UuZ2V0KHBhcnQubWVzc2FnZUlkKSA/PyBbXTtcbiAgICBleGlzdGluZy5wdXNoKHBhcnQpO1xuICAgIHBhcnRzQnlNZXNzYWdlLnNldChwYXJ0Lm1lc3NhZ2VJZCwgZXhpc3RpbmcpO1xuICB9XG5cbiAgcmV0dXJuIGZpbHRlcmVkXG4gICAgLm1hcCgobSkgPT4ge1xuICAgICAgY29uc3QgbWVzc2FnZVBhcnRzID0gcGFydHNCeU1lc3NhZ2UuZ2V0KG0uaWQpID8/IFtdO1xuICAgICAgbWVzc2FnZVBhcnRzLnNvcnQoKGEsIGIpID0+IGEuaW5kZXggLSBiLmluZGV4KTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGlkOiBtLmlkLFxuICAgICAgICByb2xlOiBtLnJvbGUsXG4gICAgICAgIHBhcnRzOiBtZXNzYWdlUGFydHMubWFwKChwKSA9PiBwLnBhcnQpLFxuICAgICAgfSBzYXRpc2ZpZXMgVUlNZXNzYWdlO1xuICAgIH0pXG4gICAgLmZpbHRlcigobSkgPT4gbS5wYXJ0cy5sZW5ndGggPiAwKTtcbn1cbiIsICJpbXBvcnQgdHlwZSB7IFN0ZXBVc2FnZSwgVXNhZ2VTdW1tYXJ5IH0gZnJvbSBcIi4uL3N0b3JhZ2UvcnBjXCI7XG5cbmV4cG9ydCB0eXBlIHsgU3RlcFVzYWdlLCBVc2FnZVN1bW1hcnkgfTtcblxuZnVuY3Rpb24gc3VtKGl0ZW1zOiBTdGVwVXNhZ2VbXSwga2V5OiBrZXlvZiBTdGVwVXNhZ2UpOiBudW1iZXIge1xuICByZXR1cm4gaXRlbXMucmVkdWNlKChhY2MsIGl0ZW0pID0+IHtcbiAgICBjb25zdCB2YWx1ZSA9IGl0ZW1ba2V5XTtcbiAgICByZXR1cm4gYWNjICsgKHR5cGVvZiB2YWx1ZSA9PT0gXCJudW1iZXJcIiA/IHZhbHVlIDogMCk7XG4gIH0sIDApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY29tcHV0ZVVzYWdlU3VtbWFyeShzdGVwczogU3RlcFVzYWdlW10pOiBVc2FnZVN1bW1hcnkge1xuICByZXR1cm4ge1xuICAgIG1vZGVsOiBzdGVwc1swXT8ubW9kZWwgPz8gXCJ1bmtub3duXCIsXG4gICAgaW5wdXRUb2tlbnM6IHN1bShzdGVwcywgXCJpbnB1dFRva2Vuc1wiKSxcbiAgICBvdXRwdXRUb2tlbnM6IHN1bShzdGVwcywgXCJvdXRwdXRUb2tlbnNcIiksXG4gICAgdG90YWxUb2tlbnM6IHN1bShzdGVwcywgXCJ0b3RhbFRva2Vuc1wiKSxcbiAgICBjYWNoZVJlYWRUb2tlbnM6IHN1bShzdGVwcywgXCJjYWNoZVJlYWRUb2tlbnNcIiksXG4gICAgY2FjaGVXcml0ZVRva2Vuczogc3VtKHN0ZXBzLCBcImNhY2hlV3JpdGVUb2tlbnNcIiksXG4gICAgcmVhc29uaW5nVG9rZW5zOiBzdW0oc3RlcHMsIFwicmVhc29uaW5nVG9rZW5zXCIpLFxuICAgIHN0ZXBDb3VudDogc3RlcHMubGVuZ3RoLFxuICB9O1xufVxuXG5leHBvcnQgdHlwZSBTZXNzaW9uVXNhZ2UgPSB7XG4gIHRvdGFsOiBVc2FnZVN1bW1hcnkgJiB7IG1lc3NhZ2VDb3VudDogbnVtYmVyIH07XG4gIGJ5TWVzc2FnZUlkOiBSZWNvcmQ8c3RyaW5nLCBVc2FnZVN1bW1hcnkgfCBudWxsPjtcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBjb21wdXRlU2Vzc2lvblVzYWdlKFxuICBtZXNzYWdlczogQXJyYXk8e1xuICAgIGlkOiBzdHJpbmc7XG4gICAgdXNhZ2U6IHsgc3RlcHM6IFN0ZXBVc2FnZVtdOyBzdW1tYXJ5OiBVc2FnZVN1bW1hcnkgfSB8IG51bGw7XG4gIH0+XG4pOiBTZXNzaW9uVXNhZ2Uge1xuICBjb25zdCBieU1lc3NhZ2VJZDogUmVjb3JkPHN0cmluZywgVXNhZ2VTdW1tYXJ5IHwgbnVsbD4gPSB7fTtcbiAgZm9yIChjb25zdCBtIG9mIG1lc3NhZ2VzKSB7XG4gICAgYnlNZXNzYWdlSWRbbS5pZF0gPSBtLnVzYWdlPy5zdW1tYXJ5ID8/IG51bGw7XG4gIH1cblxuICBjb25zdCBzdW1tYXJpZXMgPSBtZXNzYWdlc1xuICAgIC5tYXAoKG0pID0+IG0udXNhZ2U/LnN1bW1hcnkpXG4gICAgLmZpbHRlcigocyk6IHMgaXMgVXNhZ2VTdW1tYXJ5ID0+IHMgIT09IHVuZGVmaW5lZCk7XG5cbiAgY29uc3QgdG90YWwgPSB7XG4gICAgbW9kZWw6IHN1bW1hcmllc1swXT8ubW9kZWwgPz8gXCJ1bmtub3duXCIsXG4gICAgaW5wdXRUb2tlbnM6IHN1bW1hcmllcy5yZWR1Y2UoKGFjYywgcykgPT4gYWNjICsgcy5pbnB1dFRva2VucywgMCksXG4gICAgb3V0cHV0VG9rZW5zOiBzdW1tYXJpZXMucmVkdWNlKChhY2MsIHMpID0+IGFjYyArIHMub3V0cHV0VG9rZW5zLCAwKSxcbiAgICB0b3RhbFRva2Vuczogc3VtbWFyaWVzLnJlZHVjZSgoYWNjLCBzKSA9PiBhY2MgKyBzLnRvdGFsVG9rZW5zLCAwKSxcbiAgICBjYWNoZVJlYWRUb2tlbnM6IHN1bW1hcmllcy5yZWR1Y2UoKGFjYywgcykgPT4gYWNjICsgcy5jYWNoZVJlYWRUb2tlbnMsIDApLFxuICAgIGNhY2hlV3JpdGVUb2tlbnM6IHN1bW1hcmllcy5yZWR1Y2UoKGFjYywgcykgPT4gYWNjICsgcy5jYWNoZVdyaXRlVG9rZW5zLCAwKSxcbiAgICByZWFzb25pbmdUb2tlbnM6IHN1bW1hcmllcy5yZWR1Y2UoKGFjYywgcykgPT4gYWNjICsgcy5yZWFzb25pbmdUb2tlbnMsIDApLFxuICAgIHN0ZXBDb3VudDogc3VtbWFyaWVzLnJlZHVjZSgoYWNjLCBzKSA9PiBhY2MgKyBzLnN0ZXBDb3VudCwgMCksXG4gICAgbWVzc2FnZUNvdW50OiBzdW1tYXJpZXMubGVuZ3RoLFxuICB9O1xuXG4gIHJldHVybiB7IHRvdGFsLCBieU1lc3NhZ2VJZCB9O1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7QUFDQSxTQUFTLFlBQVksY0FBQUEsYUFBWSxtQkFBbUI7OztBQ0RwRDtBQUFBLEVBQ0U7QUFBQSxFQUNBO0FBQUEsRUFFQTtBQUFBLEVBQ0E7QUFBQSxPQUVLO0FBQ1AsU0FBUyxZQUFZO0FBQ3JCLFNBQVMsa0JBQWtCOzs7QUNpQnBCLFNBQVMsc0JBQ2QsU0FDeUI7QUFDekIsUUFBTSxVQUFVLFFBQVEsS0FBSztBQUU3QixNQUFJLENBQUMsUUFBUSxXQUFXLEtBQUssR0FBRztBQUM5QixXQUFPO0FBQUEsRUFDVDtBQUVBLFFBQU0saUJBQWlCLFFBQVEsUUFBUSxPQUFPLENBQUM7QUFDL0MsTUFBSSxtQkFBbUIsSUFBSTtBQUN6QixXQUFPO0FBQUEsRUFDVDtBQUVBLFFBQU0sbUJBQW1CLFFBQVEsTUFBTSxHQUFHLGNBQWMsRUFBRSxLQUFLO0FBQy9ELFFBQU0sU0FBUyxnQkFBZ0IsZ0JBQWdCO0FBRS9DLE1BQUksRUFBRSxPQUFPLFFBQVEsT0FBTyxjQUFjO0FBQ3hDLFdBQU87QUFBQSxFQUNUO0FBRUEsU0FBTztBQUFBLElBQ0wsTUFBTSxPQUFPLE9BQU8sSUFBSTtBQUFBLElBQ3hCLGFBQWEsT0FBTyxPQUFPLFdBQVc7QUFBQSxFQUN4QztBQUNGO0FBTUEsU0FBUyxnQkFBZ0IsTUFBc0M7QUFDN0QsUUFBTSxTQUFpQyxDQUFDO0FBRXhDLGFBQVcsUUFBUSxLQUFLLE1B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QixDQUFDO0FBRXBFLE1BQUk7QUFDSixNQUFJLGdCQUFnQjtBQUNwQixRQUFNLGFBQTBCLENBQUM7QUFFakMsU0FBTyxpQkFBaUIsUUFBUTtBQUM5QixRQUFJO0FBQ0YsWUFBTSxTQUFTLE1BQU0sZUFBZTtBQUFBLFFBQ2xDLG9CQUFvQixNQUFNO0FBQUEsUUFDMUI7QUFBQSxRQUNBO0FBQUEsUUFDQTtBQUFBLFFBQ0E7QUFBQSxRQUNBLGlCQUFpQixXQUFXO0FBQUEsTUFDOUIsQ0FBQztBQUNELHFCQUFlLE9BQU87QUFDdEIsc0JBQWdCLE9BQU87QUFDdkIsaUJBQVcsS0FBSyxHQUFHLE9BQU8sVUFBVTtBQUVwQyxVQUFJLE9BQU8sWUFBWSxRQUFRLFdBQVcsVUFBVSxPQUFPLFVBQVU7QUFDbkU7QUFBQSxNQUNGO0FBR0EsVUFBSSxPQUFPLGlCQUFpQixTQUFTLEdBQUc7QUFDdEMsY0FBTSxRQUFRO0FBQUEsVUFDWixPQUFPLGlCQUFpQixJQUFJLENBQUMsWUFBWTtBQUN2QyxrQkFBTSxPQUFPLGFBQWEsT0FBTyxFQUFFLE9BQU8sUUFBUSxXQUFXLENBQUM7QUFDOUQsa0JBQU0sT0FBTyxLQUFLLE9BQU8sYUFBYSxFQUFFO0FBQ3hDLG1CQUFPLEtBQUssS0FBSztBQUFBLFVBQ25CLENBQUM7QUFBQSxRQUNIO0FBQUEsTUFHRjtBQUFBLElBQ0YsU0FBUyxLQUFLO0FBQ1osY0FBUSxNQUFNLEdBQUc7QUFDakIsWUFBTTtBQUFBLElBQ1I7QUFBQSxFQUNGO0FBRUEsUUFBTSxvQkFBb0I7QUFBQSxJQUN4QixvQkFBb0IsTUFBTTtBQUFBLElBQzFCO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxFQUNGLENBQUM7QUFDSDsiLAogICJuYW1lcyI6IFsiRmF0YWxFcnJvciIsICJ0b29sIiwgInoiLCAidG9vbCIsICJ6IiwgInNlc3Npb24iLCAic2FuZGJveFJlY29yZCIsICJzYW5kYm94IiwgInNraWxscyIsICJyZXN1bHQiLCAiZXZlbnQiLCAiRmF0YWxFcnJvciJdCn0K