experimental-agent 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +243 -0
- package/dist/agent-workflow.d.mts +21 -0
- package/dist/agent-workflow.d.ts +21 -0
- package/dist/agent-workflow.js +2659 -0
- package/dist/agent-workflow.mjs +9 -0
- package/dist/chunk-2YI7MQGZ.mjs +261 -0
- package/dist/chunk-36X6L7SK.mjs +1 -0
- package/dist/chunk-DPPQO7DA.mjs +343 -0
- package/dist/chunk-JQPR6M7D.mjs +649 -0
- package/dist/chunk-MR4UWCJT.mjs +878 -0
- package/dist/client-FCFZYOOB.mjs +9 -0
- package/dist/client-RRX3GDQD.mjs +9 -0
- package/dist/index.d.mts +128 -0
- package/dist/index.d.ts +128 -0
- package/dist/index.js +3078 -0
- package/dist/index.mjs +421 -0
- package/dist/lifecycle-workflow-steps-6BLGTYVB.mjs +20 -0
- package/dist/lifecycle-workflow.d.mts +17 -0
- package/dist/lifecycle-workflow.d.ts +17 -0
- package/dist/lifecycle-workflow.js +1690 -0
- package/dist/lifecycle-workflow.mjs +44 -0
- package/dist/local-J6QFWSWB.mjs +244 -0
- package/dist/process-manager-H2HF6G4G.mjs +153 -0
- package/dist/sandbox-Y3ENCNUA.mjs +10 -0
- package/dist/storage-QSTSE2ZB.mjs +27 -0
- package/dist/types-Lwut_0_u.d.mts +80 -0
- package/dist/types-ctZeJ3iQ.d.ts +80 -0
- package/dist/types-vRxN1Qz1.d.mts +805 -0
- package/dist/types-vRxN1Qz1.d.ts +805 -0
- package/dist/vercel-2CFDMEHB.mjs +18 -0
- package/package.json +59 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,3078 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __esm = (fn, res) => function __init() {
|
|
9
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
10
|
+
};
|
|
11
|
+
var __export = (target, all2) => {
|
|
12
|
+
for (var name in all2)
|
|
13
|
+
__defProp(target, name, { get: all2[name], enumerable: true });
|
|
14
|
+
};
|
|
15
|
+
var __copyProps = (to, from, except, desc) => {
|
|
16
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
17
|
+
for (let key of __getOwnPropNames(from))
|
|
18
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
19
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
20
|
+
}
|
|
21
|
+
return to;
|
|
22
|
+
};
|
|
23
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
24
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
25
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
26
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
27
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
28
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
29
|
+
mod
|
|
30
|
+
));
|
|
31
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
|
+
|
|
33
|
+
// src/sandbox/process-manager.ts
|
|
34
|
+
var process_manager_exports = {};
|
|
35
|
+
__export(process_manager_exports, {
|
|
36
|
+
createProcessManager: () => createProcessManager
|
|
37
|
+
});
|
|
38
|
+
var DEFAULT_WAIT_UNTIL, RUN_SCRIPT, createProcessManager;
|
|
39
|
+
var init_process_manager = __esm({
|
|
40
|
+
"src/sandbox/process-manager.ts"() {
|
|
41
|
+
"use strict";
|
|
42
|
+
DEFAULT_WAIT_UNTIL = 3e4;
|
|
43
|
+
RUN_SCRIPT = `#!/bin/sh
|
|
44
|
+
# Process runner for Agent SDK
|
|
45
|
+
# All parameters passed via environment variables to avoid escaping issues
|
|
46
|
+
# Output is base64 encoded to avoid JSON escaping issues
|
|
47
|
+
|
|
48
|
+
AGENT_DIR="$HOME/.agent"
|
|
49
|
+
CWD_FILE="$AGENT_DIR/cwd/$SESSION_ID"
|
|
50
|
+
|
|
51
|
+
# Get current working directory (per-session)
|
|
52
|
+
if [ -f "$CWD_FILE" ]; then
|
|
53
|
+
CWD=$(cat "$CWD_FILE")
|
|
54
|
+
else
|
|
55
|
+
CWD="$HOME"
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
# Decode command
|
|
59
|
+
CMD=$(echo "$CMD_BASE64" | base64 -d)
|
|
60
|
+
|
|
61
|
+
# Background mode (waitUntil = 0)
|
|
62
|
+
if [ "$WAIT_UNTIL" = "0" ]; then
|
|
63
|
+
cd "$CWD" || cd "$HOME"
|
|
64
|
+
|
|
65
|
+
# Generate a simple numeric ID for output file
|
|
66
|
+
OUTPUT_ID="$(date +%s)$$"
|
|
67
|
+
OUTPUT_FILE="$AGENT_DIR/outputs/$OUTPUT_ID.log"
|
|
68
|
+
|
|
69
|
+
# Double-fork to fully detach the process
|
|
70
|
+
(
|
|
71
|
+
(
|
|
72
|
+
eval "$CMD"
|
|
73
|
+
pwd > "$CWD_FILE" 2>/dev/null
|
|
74
|
+
) > "$OUTPUT_FILE" 2>&1 < /dev/null &
|
|
75
|
+
echo $! > "$AGENT_DIR/pids/$OUTPUT_ID.pid"
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
# Small delay to ensure PID file is written
|
|
79
|
+
sleep 0.05
|
|
80
|
+
|
|
81
|
+
# Read PID
|
|
82
|
+
if [ -f "$AGENT_DIR/pids/$OUTPUT_ID.pid" ]; then
|
|
83
|
+
PID=$(cat "$AGENT_DIR/pids/$OUTPUT_ID.pid")
|
|
84
|
+
else
|
|
85
|
+
PID=0
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
# Output JSON result (no output for background, so no encoding needed)
|
|
89
|
+
printf '{"pid":%d,"outputBase64":"","exitCode":-1,"status":"running","outputFile":"%s","cwd":"%s"}\\n' \\
|
|
90
|
+
"$PID" "$OUTPUT_FILE" "$CWD"
|
|
91
|
+
exit 0
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
# Foreground mode (waitUntil > 0) - run directly and capture output
|
|
95
|
+
cd "$CWD" || cd "$HOME"
|
|
96
|
+
|
|
97
|
+
# Run command, capture output and exit code
|
|
98
|
+
OUTPUT=$(eval "$CMD" 2>&1)
|
|
99
|
+
EXIT_CODE=$?
|
|
100
|
+
|
|
101
|
+
# Update CWD after command
|
|
102
|
+
NEW_CWD=$(pwd)
|
|
103
|
+
echo "$NEW_CWD" > "$CWD_FILE"
|
|
104
|
+
|
|
105
|
+
# Determine status
|
|
106
|
+
if [ $EXIT_CODE -eq 0 ]; then
|
|
107
|
+
STATUS="completed"
|
|
108
|
+
else
|
|
109
|
+
STATUS="failed"
|
|
110
|
+
fi
|
|
111
|
+
|
|
112
|
+
# Base64 encode output to avoid ALL escaping issues
|
|
113
|
+
OUTPUT_BASE64=$(printf '%s' "$OUTPUT" | base64 | tr -d '\\n')
|
|
114
|
+
|
|
115
|
+
# Output JSON result with base64-encoded output
|
|
116
|
+
printf '{"pid":0,"outputBase64":"%s","exitCode":%d,"status":"%s","outputFile":"","cwd":"%s"}\\n' \\
|
|
117
|
+
"$OUTPUT_BASE64" "$EXIT_CODE" "$STATUS" "$NEW_CWD"
|
|
118
|
+
`;
|
|
119
|
+
createProcessManager = (opts) => {
|
|
120
|
+
const { sandbox, sessionId } = opts;
|
|
121
|
+
let initialized = false;
|
|
122
|
+
const init = async () => {
|
|
123
|
+
if (initialized) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const result = await sandbox.exec({
|
|
127
|
+
command: "sh",
|
|
128
|
+
args: [
|
|
129
|
+
"-c",
|
|
130
|
+
`mkdir -p $HOME/.agent/bin $HOME/.agent/pids $HOME/.agent/outputs $HOME/.agent/cwd
|
|
131
|
+
cat > $HOME/.agent/bin/run.sh << 'SCRIPT_EOF'
|
|
132
|
+
${RUN_SCRIPT}
|
|
133
|
+
SCRIPT_EOF
|
|
134
|
+
chmod +x $HOME/.agent/bin/run.sh`
|
|
135
|
+
]
|
|
136
|
+
});
|
|
137
|
+
if (result instanceof Error) {
|
|
138
|
+
throw result;
|
|
139
|
+
}
|
|
140
|
+
await result.result;
|
|
141
|
+
initialized = true;
|
|
142
|
+
};
|
|
143
|
+
const run = async (opts2) => {
|
|
144
|
+
await init();
|
|
145
|
+
const { command, waitUntil = DEFAULT_WAIT_UNTIL } = opts2;
|
|
146
|
+
const cmdBase64 = Buffer.from(command, "utf-8").toString("base64");
|
|
147
|
+
const result = await sandbox.exec({
|
|
148
|
+
command: "sh",
|
|
149
|
+
args: [
|
|
150
|
+
"-c",
|
|
151
|
+
`CMD_BASE64="${cmdBase64}" WAIT_UNTIL="${waitUntil}" SESSION_ID="${sessionId}" $HOME/.agent/bin/run.sh`
|
|
152
|
+
]
|
|
153
|
+
});
|
|
154
|
+
if (result instanceof Error) {
|
|
155
|
+
throw result;
|
|
156
|
+
}
|
|
157
|
+
const { stdout } = await result.result;
|
|
158
|
+
const parsed = JSON.parse(stdout.trim());
|
|
159
|
+
const output = parsed.outputBase64 ? Buffer.from(parsed.outputBase64, "base64").toString("utf-8") : "";
|
|
160
|
+
return {
|
|
161
|
+
pid: parsed.pid,
|
|
162
|
+
output,
|
|
163
|
+
exitCode: parsed.exitCode,
|
|
164
|
+
status: parsed.status,
|
|
165
|
+
cwd: parsed.cwd,
|
|
166
|
+
outputFile: parsed.outputFile
|
|
167
|
+
};
|
|
168
|
+
};
|
|
169
|
+
const getCwd = async () => {
|
|
170
|
+
await init();
|
|
171
|
+
const result = await sandbox.exec({
|
|
172
|
+
command: "sh",
|
|
173
|
+
args: [
|
|
174
|
+
"-c",
|
|
175
|
+
`cat $HOME/.agent/cwd/${sessionId} 2>/dev/null || echo "$HOME"`
|
|
176
|
+
]
|
|
177
|
+
});
|
|
178
|
+
if (result instanceof Error) {
|
|
179
|
+
return process.cwd();
|
|
180
|
+
}
|
|
181
|
+
const { stdout } = await result.result;
|
|
182
|
+
return stdout.trim() || process.cwd();
|
|
183
|
+
};
|
|
184
|
+
return {
|
|
185
|
+
init,
|
|
186
|
+
run,
|
|
187
|
+
getCwd
|
|
188
|
+
};
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// src/errors.ts
|
|
194
|
+
var errore, SessionNotFoundError, SessionError, SandboxNotFoundError, StorageError, SandboxError, MessageNotFoundError;
|
|
195
|
+
var init_errors = __esm({
|
|
196
|
+
"src/errors.ts"() {
|
|
197
|
+
"use strict";
|
|
198
|
+
errore = __toESM(require("errore"));
|
|
199
|
+
SessionNotFoundError = class extends errore.createTaggedError({
|
|
200
|
+
name: "SessionNotFoundError",
|
|
201
|
+
message: "Session $id not found"
|
|
202
|
+
}) {
|
|
203
|
+
};
|
|
204
|
+
SessionError = class extends errore.createTaggedError({
|
|
205
|
+
name: "SessionError",
|
|
206
|
+
message: "Session $id failed: $reason"
|
|
207
|
+
}) {
|
|
208
|
+
};
|
|
209
|
+
SandboxNotFoundError = class extends errore.createTaggedError({
|
|
210
|
+
name: "SandboxNotFoundError",
|
|
211
|
+
message: "Sandbox $id not found"
|
|
212
|
+
}) {
|
|
213
|
+
};
|
|
214
|
+
StorageError = class extends errore.createTaggedError({
|
|
215
|
+
name: "StorageError",
|
|
216
|
+
message: "$reason"
|
|
217
|
+
}) {
|
|
218
|
+
};
|
|
219
|
+
SandboxError = class extends errore.createTaggedError({
|
|
220
|
+
name: "SandboxError",
|
|
221
|
+
message: "$reason"
|
|
222
|
+
}) {
|
|
223
|
+
};
|
|
224
|
+
MessageNotFoundError = class extends errore.createTaggedError({
|
|
225
|
+
name: "MessageNotFoundError",
|
|
226
|
+
message: "Message $id not found"
|
|
227
|
+
}) {
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
// src/utils/paginate.ts
|
|
233
|
+
function paginate(opts) {
|
|
234
|
+
const { items, cursor, limit = 50 } = opts;
|
|
235
|
+
const startIndex = cursor ? items.findIndex((m) => m.id === cursor) + 1 : 0;
|
|
236
|
+
const sliced = items.slice(startIndex, startIndex + limit);
|
|
237
|
+
const nextCursor = startIndex + limit < items.length ? sliced.at(-1)?.id ?? null : null;
|
|
238
|
+
return { items: sliced, nextCursor };
|
|
239
|
+
}
|
|
240
|
+
var init_paginate = __esm({
|
|
241
|
+
"src/utils/paginate.ts"() {
|
|
242
|
+
"use strict";
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
// src/storage/bindings/local-fs-handlers.ts
|
|
247
|
+
function createFilesystemHandlers(basePath) {
|
|
248
|
+
const sessionDir = (0, import_node_path.join)(basePath, "session");
|
|
249
|
+
const messageDir = (0, import_node_path.join)(basePath, "message");
|
|
250
|
+
const partDir = (0, import_node_path.join)(basePath, "part");
|
|
251
|
+
const sandboxDir = (0, import_node_path.join)(basePath, "sandbox");
|
|
252
|
+
const commandDir = (0, import_node_path.join)(basePath, "command");
|
|
253
|
+
async function ensureDir(dir) {
|
|
254
|
+
await (0, import_promises.mkdir)(dir, { recursive: true });
|
|
255
|
+
}
|
|
256
|
+
async function readJson(filePath) {
|
|
257
|
+
try {
|
|
258
|
+
const content = await (0, import_promises.readFile)(filePath, "utf-8");
|
|
259
|
+
return JSON.parse(content);
|
|
260
|
+
} catch {
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
async function writeJsonFile(filePath, data) {
|
|
265
|
+
await ensureDir((0, import_node_path.dirname)(filePath));
|
|
266
|
+
await (0, import_promises.writeFile)(filePath, JSON.stringify(data, null, 2));
|
|
267
|
+
}
|
|
268
|
+
async function readAllFromDir(dir) {
|
|
269
|
+
try {
|
|
270
|
+
const files = await (0, import_promises.readdir)(dir);
|
|
271
|
+
const results = await Promise.all(
|
|
272
|
+
files.filter((f) => f.endsWith(".json")).map((f) => readJson((0, import_node_path.join)(dir, f)))
|
|
273
|
+
);
|
|
274
|
+
return results.filter((r) => r !== null);
|
|
275
|
+
} catch {
|
|
276
|
+
return [];
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return {
|
|
280
|
+
"session.get": async ({ id }) => {
|
|
281
|
+
const session = await readJson((0, import_node_path.join)(sessionDir, `${id}.json`));
|
|
282
|
+
return session ?? null;
|
|
283
|
+
},
|
|
284
|
+
"session.set": async (session) => {
|
|
285
|
+
const now = Date.now();
|
|
286
|
+
const sessionPath = (0, import_node_path.join)(sessionDir, `${session.id}.json`);
|
|
287
|
+
const existing = await readJson(sessionPath);
|
|
288
|
+
const newSession = {
|
|
289
|
+
...session,
|
|
290
|
+
tags: session.tags ?? existing?.tags ?? {},
|
|
291
|
+
createdAt: existing?.createdAt ?? session.createdAt ?? now,
|
|
292
|
+
updatedAt: now
|
|
293
|
+
};
|
|
294
|
+
await writeJsonFile(sessionPath, newSession);
|
|
295
|
+
return newSession;
|
|
296
|
+
},
|
|
297
|
+
"session.list": async ({ tags, cursor, limit }) => {
|
|
298
|
+
const allSessions = await readAllFromDir(sessionDir);
|
|
299
|
+
let filtered = allSessions;
|
|
300
|
+
if (tags && Object.keys(tags).length > 0) {
|
|
301
|
+
filtered = filtered.filter((s) => {
|
|
302
|
+
const sessionTags = s.tags ?? {};
|
|
303
|
+
return Object.entries(tags).every(
|
|
304
|
+
([key, value]) => sessionTags[key] === value
|
|
305
|
+
);
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
filtered.sort((a, b) => a.createdAt - b.createdAt);
|
|
309
|
+
return paginate({ items: filtered, cursor, limit });
|
|
310
|
+
},
|
|
311
|
+
"session.listBySandbox": async ({ sandboxId, tags, cursor, limit }) => {
|
|
312
|
+
const allSessions = await readAllFromDir(sessionDir);
|
|
313
|
+
let filtered = allSessions.filter((s) => s.sandboxId === sandboxId);
|
|
314
|
+
if (tags && Object.keys(tags).length > 0) {
|
|
315
|
+
filtered = filtered.filter((s) => {
|
|
316
|
+
const sessionTags = s.tags ?? {};
|
|
317
|
+
return Object.entries(tags).every(
|
|
318
|
+
([key, value]) => sessionTags[key] === value
|
|
319
|
+
);
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
filtered.sort((a, b) => a.createdAt - b.createdAt);
|
|
323
|
+
return paginate({ items: filtered, cursor, limit });
|
|
324
|
+
},
|
|
325
|
+
"session.tag.set": async ({ sessionId, tags }) => {
|
|
326
|
+
const sessionPath = (0, import_node_path.join)(sessionDir, `${sessionId}.json`);
|
|
327
|
+
const existing = await readJson(sessionPath);
|
|
328
|
+
if (!existing) {
|
|
329
|
+
throw new Error(`Session ${sessionId} not found`);
|
|
330
|
+
}
|
|
331
|
+
const mergedTags = { ...existing.tags, ...tags };
|
|
332
|
+
const now = Date.now();
|
|
333
|
+
const updatedSession = {
|
|
334
|
+
...existing,
|
|
335
|
+
tags: mergedTags,
|
|
336
|
+
updatedAt: now
|
|
337
|
+
};
|
|
338
|
+
await writeJsonFile(sessionPath, updatedSession);
|
|
339
|
+
return updatedSession;
|
|
340
|
+
},
|
|
341
|
+
"message.get": async ({ id }) => {
|
|
342
|
+
return await readJson((0, import_node_path.join)(messageDir, `${id}.json`));
|
|
343
|
+
},
|
|
344
|
+
"message.set": async (message) => {
|
|
345
|
+
await writeJsonFile((0, import_node_path.join)(messageDir, `${message.id}.json`), message);
|
|
346
|
+
return message;
|
|
347
|
+
},
|
|
348
|
+
"message.list": async ({ sessionId, cursor, limit }) => {
|
|
349
|
+
const allMessages = await readAllFromDir(messageDir);
|
|
350
|
+
const filtered = allMessages.filter((m) => m.sessionId === sessionId).sort((a, b) => a.createdAt - b.createdAt);
|
|
351
|
+
return paginate({ items: filtered, cursor, limit });
|
|
352
|
+
},
|
|
353
|
+
"part.listByMessage": async ({ messageId, cursor, limit }) => {
|
|
354
|
+
const allParts = await readAllFromDir(partDir);
|
|
355
|
+
const filtered = allParts.filter((p) => p.messageId === messageId).sort((a, b) => a.index - b.index);
|
|
356
|
+
return paginate({ items: filtered, cursor, limit });
|
|
357
|
+
},
|
|
358
|
+
"part.listBySession": async ({ sessionId, cursor, limit }) => {
|
|
359
|
+
const allParts = await readAllFromDir(partDir);
|
|
360
|
+
const filtered = allParts.filter((p) => p.sessionId === sessionId).sort((a, b) => {
|
|
361
|
+
if (a.messageId !== b.messageId) {
|
|
362
|
+
return a.messageId.localeCompare(b.messageId);
|
|
363
|
+
}
|
|
364
|
+
return a.index - b.index;
|
|
365
|
+
});
|
|
366
|
+
return paginate({ items: filtered, cursor, limit });
|
|
367
|
+
},
|
|
368
|
+
"part.set": async (part) => {
|
|
369
|
+
await writeJsonFile((0, import_node_path.join)(partDir, `${part.id}.json`), part);
|
|
370
|
+
return part;
|
|
371
|
+
},
|
|
372
|
+
"sandbox.get": async ({ key }) => {
|
|
373
|
+
const safeName = Buffer.from(key).toString("base64url");
|
|
374
|
+
const sandboxPath = (0, import_node_path.join)(sandboxDir, `${safeName}.json`);
|
|
375
|
+
const data = await readJson(sandboxPath);
|
|
376
|
+
if (!data) {
|
|
377
|
+
return null;
|
|
378
|
+
}
|
|
379
|
+
return data;
|
|
380
|
+
},
|
|
381
|
+
"sandbox.set": async (record) => {
|
|
382
|
+
const safeName = Buffer.from(record.id).toString("base64url");
|
|
383
|
+
const sandboxPath = (0, import_node_path.join)(sandboxDir, `${safeName}.json`);
|
|
384
|
+
await writeJsonFile(sandboxPath, record);
|
|
385
|
+
},
|
|
386
|
+
"sandbox.getBySession": async ({ sessionId }) => {
|
|
387
|
+
const allSandboxes = await readAllFromDir(sandboxDir);
|
|
388
|
+
const matching = allSandboxes.filter(
|
|
389
|
+
(s) => s.id.startsWith(`${sessionId}-`)
|
|
390
|
+
);
|
|
391
|
+
if (matching.length === 0) {
|
|
392
|
+
return null;
|
|
393
|
+
}
|
|
394
|
+
matching.sort(
|
|
395
|
+
(a, b) => (b.lastActivityAt ?? 0) - (a.lastActivityAt ?? 0)
|
|
396
|
+
);
|
|
397
|
+
return matching[0];
|
|
398
|
+
},
|
|
399
|
+
"command.get": async ({ id }) => {
|
|
400
|
+
return await readJson((0, import_node_path.join)(commandDir, `${id}.json`));
|
|
401
|
+
},
|
|
402
|
+
"command.set": async (command) => {
|
|
403
|
+
await writeJsonFile((0, import_node_path.join)(commandDir, `${command.id}.json`), command);
|
|
404
|
+
return command;
|
|
405
|
+
},
|
|
406
|
+
"command.list": async ({ sessionId, includeFinished, cursor, limit }) => {
|
|
407
|
+
const allCommands = await readAllFromDir(commandDir);
|
|
408
|
+
let filtered = allCommands.filter((c) => c.sessionId === sessionId);
|
|
409
|
+
if (!includeFinished) {
|
|
410
|
+
filtered = filtered.filter((c) => c.status === "running");
|
|
411
|
+
}
|
|
412
|
+
filtered.sort((a, b) => a.startedAt - b.startedAt);
|
|
413
|
+
return paginate({ items: filtered, cursor, limit });
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
var import_promises, import_node_path;
|
|
418
|
+
var init_local_fs_handlers = __esm({
|
|
419
|
+
"src/storage/bindings/local-fs-handlers.ts"() {
|
|
420
|
+
"use strict";
|
|
421
|
+
import_promises = require("fs/promises");
|
|
422
|
+
import_node_path = require("path");
|
|
423
|
+
init_paginate();
|
|
424
|
+
}
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
// src/storage/bindings/local.ts
|
|
428
|
+
var local_exports = {};
|
|
429
|
+
__export(local_exports, {
|
|
430
|
+
startLocalStorage: () => startLocalStorage,
|
|
431
|
+
stopLocalStorage: () => stopLocalStorage
|
|
432
|
+
});
|
|
433
|
+
function startLocalStorage(opts) {
|
|
434
|
+
if (startPromise) {
|
|
435
|
+
return startPromise;
|
|
436
|
+
}
|
|
437
|
+
startPromise = new Promise((resolve) => {
|
|
438
|
+
const handlers = createFilesystemHandlers(
|
|
439
|
+
opts?.path ?? DEFAULT_STORAGE_DIR
|
|
440
|
+
);
|
|
441
|
+
const app = new import_hono.Hono();
|
|
442
|
+
app.post("/", async (c) => {
|
|
443
|
+
const body = await c.req.json();
|
|
444
|
+
const response = await handleStorageRpc(body, handlers);
|
|
445
|
+
return c.json(response);
|
|
446
|
+
});
|
|
447
|
+
const port = opts?.port ?? 0;
|
|
448
|
+
const server = (0, import_node_server.serve)({
|
|
449
|
+
fetch: app.fetch,
|
|
450
|
+
port
|
|
451
|
+
});
|
|
452
|
+
server.on("listening", () => {
|
|
453
|
+
const address = server.address();
|
|
454
|
+
const actualPort = typeof address === "object" ? address?.port : port;
|
|
455
|
+
const url = `http://localhost:${actualPort}`;
|
|
456
|
+
serverInstance = { url, server };
|
|
457
|
+
console.log(`[agent] Local storage server started at ${url}`);
|
|
458
|
+
resolve(url);
|
|
459
|
+
});
|
|
460
|
+
});
|
|
461
|
+
return startPromise;
|
|
462
|
+
}
|
|
463
|
+
function stopLocalStorage() {
|
|
464
|
+
if (serverInstance) {
|
|
465
|
+
serverInstance.server.close();
|
|
466
|
+
serverInstance = null;
|
|
467
|
+
startPromise = null;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
var import_node_server, import_hono, DEFAULT_STORAGE_DIR, startPromise, serverInstance;
|
|
471
|
+
var init_local = __esm({
|
|
472
|
+
"src/storage/bindings/local.ts"() {
|
|
473
|
+
"use strict";
|
|
474
|
+
import_node_server = require("@hono/node-server");
|
|
475
|
+
import_hono = require("hono");
|
|
476
|
+
init_storage();
|
|
477
|
+
init_local_fs_handlers();
|
|
478
|
+
DEFAULT_STORAGE_DIR = ".agent-storage";
|
|
479
|
+
startPromise = null;
|
|
480
|
+
serverInstance = null;
|
|
481
|
+
if (typeof process !== "undefined") {
|
|
482
|
+
process.on("SIGTERM", stopLocalStorage);
|
|
483
|
+
process.on("SIGINT", stopLocalStorage);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
// src/storage/bindings/vercel.ts
|
|
489
|
+
var vercel_exports = {};
|
|
490
|
+
__export(vercel_exports, {
|
|
491
|
+
getVercelStorageConfig: () => getVercelStorageConfig
|
|
492
|
+
});
|
|
493
|
+
async function getVercelStorageConfig() {
|
|
494
|
+
let token = null;
|
|
495
|
+
try {
|
|
496
|
+
const { getVercelOidcToken } = await import("@vercel/oidc");
|
|
497
|
+
token = await getVercelOidcToken();
|
|
498
|
+
} catch {
|
|
499
|
+
}
|
|
500
|
+
return {
|
|
501
|
+
url: VERCEL_STORAGE_URL,
|
|
502
|
+
headers: token ? { Authorization: `Bearer ${token}` } : {}
|
|
503
|
+
};
|
|
504
|
+
}
|
|
505
|
+
var VERCEL_STORAGE_URL;
|
|
506
|
+
var init_vercel = __esm({
|
|
507
|
+
"src/storage/bindings/vercel.ts"() {
|
|
508
|
+
"use strict";
|
|
509
|
+
VERCEL_STORAGE_URL = "https://agent-sdk-storage-nine.labs.vercel.dev/api/storage";
|
|
510
|
+
}
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
// src/storage/client.ts
|
|
514
|
+
var client_exports = {};
|
|
515
|
+
__export(client_exports, {
|
|
516
|
+
getStorage: () => getStorage,
|
|
517
|
+
getStorageClient: () => getStorageClient
|
|
518
|
+
});
|
|
519
|
+
function getStorageClient({ url, headers }) {
|
|
520
|
+
async function rpc(method, params) {
|
|
521
|
+
const res = await fetch(url, {
|
|
522
|
+
method: "POST",
|
|
523
|
+
headers: { "Content-Type": "application/json", ...headers },
|
|
524
|
+
body: JSON.stringify({ method, params })
|
|
525
|
+
});
|
|
526
|
+
if (!res.ok) {
|
|
527
|
+
throw new StorageError({
|
|
528
|
+
reason: `HTTP ${res.status}: ${res.statusText}`
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
const json = await res.json();
|
|
532
|
+
if ("error" in json) {
|
|
533
|
+
throw new StorageError({ reason: json.error.message });
|
|
534
|
+
}
|
|
535
|
+
return json.result;
|
|
536
|
+
}
|
|
537
|
+
return {
|
|
538
|
+
session: {
|
|
539
|
+
get: async (id) => {
|
|
540
|
+
try {
|
|
541
|
+
const result = await rpc("session.get", { id });
|
|
542
|
+
if (result === null) {
|
|
543
|
+
return new SessionNotFoundError({ id });
|
|
544
|
+
}
|
|
545
|
+
return result;
|
|
546
|
+
} catch (e) {
|
|
547
|
+
if (e instanceof StorageError) {
|
|
548
|
+
return e;
|
|
549
|
+
}
|
|
550
|
+
return new StorageError({ reason: String(e), cause: e });
|
|
551
|
+
}
|
|
552
|
+
},
|
|
553
|
+
set: async (session) => {
|
|
554
|
+
try {
|
|
555
|
+
return await rpc("session.set", session);
|
|
556
|
+
} catch (e) {
|
|
557
|
+
if (e instanceof StorageError) {
|
|
558
|
+
return e;
|
|
559
|
+
}
|
|
560
|
+
return new StorageError({ reason: String(e), cause: e });
|
|
561
|
+
}
|
|
562
|
+
},
|
|
563
|
+
list: async (opts) => {
|
|
564
|
+
try {
|
|
565
|
+
return await rpc("session.list", {
|
|
566
|
+
tags: opts?.tags,
|
|
567
|
+
order: opts?.order,
|
|
568
|
+
cursor: opts?.cursor,
|
|
569
|
+
limit: opts?.limit
|
|
570
|
+
});
|
|
571
|
+
} catch (e) {
|
|
572
|
+
if (e instanceof StorageError) {
|
|
573
|
+
return e;
|
|
574
|
+
}
|
|
575
|
+
return new StorageError({ reason: String(e), cause: e });
|
|
576
|
+
}
|
|
577
|
+
},
|
|
578
|
+
tag: {
|
|
579
|
+
set: async ({ sessionId, tags }) => {
|
|
580
|
+
try {
|
|
581
|
+
return await rpc("session.tag.set", { sessionId, tags });
|
|
582
|
+
} catch (e) {
|
|
583
|
+
if (e instanceof StorageError) {
|
|
584
|
+
return e;
|
|
585
|
+
}
|
|
586
|
+
return new StorageError({ reason: String(e), cause: e });
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
},
|
|
591
|
+
message: {
|
|
592
|
+
list: async (sessionId, opts) => {
|
|
593
|
+
try {
|
|
594
|
+
return await rpc("message.list", {
|
|
595
|
+
sessionId,
|
|
596
|
+
cursor: opts?.cursor,
|
|
597
|
+
limit: opts?.limit
|
|
598
|
+
});
|
|
599
|
+
} catch (e) {
|
|
600
|
+
if (e instanceof StorageError) {
|
|
601
|
+
return e;
|
|
602
|
+
}
|
|
603
|
+
return new StorageError({ reason: String(e), cause: e });
|
|
604
|
+
}
|
|
605
|
+
},
|
|
606
|
+
get: async (id) => {
|
|
607
|
+
try {
|
|
608
|
+
const result = await rpc("message.get", { id });
|
|
609
|
+
if (result === null) {
|
|
610
|
+
return new MessageNotFoundError({ id });
|
|
611
|
+
}
|
|
612
|
+
return result;
|
|
613
|
+
} catch (e) {
|
|
614
|
+
if (e instanceof StorageError) {
|
|
615
|
+
return e;
|
|
616
|
+
}
|
|
617
|
+
return new StorageError({ reason: String(e), cause: e });
|
|
618
|
+
}
|
|
619
|
+
},
|
|
620
|
+
set: async (message) => {
|
|
621
|
+
try {
|
|
622
|
+
return await rpc("message.set", message);
|
|
623
|
+
} catch (e) {
|
|
624
|
+
if (e instanceof StorageError) {
|
|
625
|
+
return e;
|
|
626
|
+
}
|
|
627
|
+
return new StorageError({ reason: String(e), cause: e });
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
},
|
|
631
|
+
part: {
|
|
632
|
+
listByMessage: async (messageId, opts) => {
|
|
633
|
+
try {
|
|
634
|
+
const result = await rpc("part.listByMessage", {
|
|
635
|
+
messageId,
|
|
636
|
+
cursor: opts?.cursor,
|
|
637
|
+
limit: opts?.limit
|
|
638
|
+
});
|
|
639
|
+
return result;
|
|
640
|
+
} catch (e) {
|
|
641
|
+
if (e instanceof StorageError) {
|
|
642
|
+
return e;
|
|
643
|
+
}
|
|
644
|
+
return new StorageError({ reason: String(e), cause: e });
|
|
645
|
+
}
|
|
646
|
+
},
|
|
647
|
+
listBySession: async (sessionId, opts) => {
|
|
648
|
+
try {
|
|
649
|
+
const result = await rpc("part.listBySession", {
|
|
650
|
+
sessionId,
|
|
651
|
+
cursor: opts?.cursor,
|
|
652
|
+
limit: opts?.limit
|
|
653
|
+
});
|
|
654
|
+
return result;
|
|
655
|
+
} catch (e) {
|
|
656
|
+
if (e instanceof StorageError) {
|
|
657
|
+
return e;
|
|
658
|
+
}
|
|
659
|
+
return new StorageError({ reason: String(e), cause: e });
|
|
660
|
+
}
|
|
661
|
+
},
|
|
662
|
+
set: async (part) => {
|
|
663
|
+
try {
|
|
664
|
+
return await rpc("part.set", part);
|
|
665
|
+
} catch (e) {
|
|
666
|
+
if (e instanceof StorageError) {
|
|
667
|
+
return e;
|
|
668
|
+
}
|
|
669
|
+
return new StorageError({ reason: String(e), cause: e });
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
},
|
|
673
|
+
sandbox: {
|
|
674
|
+
get: async (key) => {
|
|
675
|
+
try {
|
|
676
|
+
const result = await rpc("sandbox.get", { key });
|
|
677
|
+
if (result === null) {
|
|
678
|
+
return new SandboxNotFoundError({ id: key });
|
|
679
|
+
}
|
|
680
|
+
return result;
|
|
681
|
+
} catch (e) {
|
|
682
|
+
if (e instanceof StorageError) {
|
|
683
|
+
return e;
|
|
684
|
+
}
|
|
685
|
+
return new StorageError({ reason: String(e), cause: e });
|
|
686
|
+
}
|
|
687
|
+
},
|
|
688
|
+
getBySession: async (sessionId) => {
|
|
689
|
+
try {
|
|
690
|
+
const result = await rpc("sandbox.getBySession", { sessionId });
|
|
691
|
+
if (result === null) {
|
|
692
|
+
return new SandboxNotFoundError({ id: sessionId });
|
|
693
|
+
}
|
|
694
|
+
return result;
|
|
695
|
+
} catch (e) {
|
|
696
|
+
if (e instanceof StorageError) {
|
|
697
|
+
return e;
|
|
698
|
+
}
|
|
699
|
+
return new StorageError({ reason: String(e), cause: e });
|
|
700
|
+
}
|
|
701
|
+
},
|
|
702
|
+
set: async (record) => {
|
|
703
|
+
try {
|
|
704
|
+
await rpc("sandbox.set", record);
|
|
705
|
+
return record;
|
|
706
|
+
} catch (e) {
|
|
707
|
+
if (e instanceof StorageError) {
|
|
708
|
+
return e;
|
|
709
|
+
}
|
|
710
|
+
return new StorageError({ reason: String(e), cause: e });
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
},
|
|
714
|
+
command: {
|
|
715
|
+
get: async (id) => {
|
|
716
|
+
try {
|
|
717
|
+
return await rpc("command.get", { id });
|
|
718
|
+
} catch (e) {
|
|
719
|
+
if (e instanceof StorageError) {
|
|
720
|
+
return e;
|
|
721
|
+
}
|
|
722
|
+
return new StorageError({ reason: String(e), cause: e });
|
|
723
|
+
}
|
|
724
|
+
},
|
|
725
|
+
set: async (command) => {
|
|
726
|
+
try {
|
|
727
|
+
return await rpc("command.set", command);
|
|
728
|
+
} catch (e) {
|
|
729
|
+
if (e instanceof StorageError) {
|
|
730
|
+
return e;
|
|
731
|
+
}
|
|
732
|
+
return new StorageError({ reason: String(e), cause: e });
|
|
733
|
+
}
|
|
734
|
+
},
|
|
735
|
+
list: async (sessionId, opts) => {
|
|
736
|
+
try {
|
|
737
|
+
const result = await rpc("command.list", {
|
|
738
|
+
sessionId,
|
|
739
|
+
includeFinished: opts?.includeFinished,
|
|
740
|
+
cursor: opts?.cursor,
|
|
741
|
+
limit: opts?.limit
|
|
742
|
+
});
|
|
743
|
+
return result;
|
|
744
|
+
} catch (e) {
|
|
745
|
+
if (e instanceof StorageError) {
|
|
746
|
+
return e;
|
|
747
|
+
}
|
|
748
|
+
return new StorageError({ reason: String(e), cause: e });
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
async function resolveStorageUrl(config) {
|
|
755
|
+
switch (config.type) {
|
|
756
|
+
case "local": {
|
|
757
|
+
const { startLocalStorage: startLocalStorage2 } = await Promise.resolve().then(() => (init_local(), local_exports));
|
|
758
|
+
return { url: await startLocalStorage2({ path: config.path }) };
|
|
759
|
+
}
|
|
760
|
+
case "vercel": {
|
|
761
|
+
const { getVercelStorageConfig: getVercelStorageConfig2 } = await Promise.resolve().then(() => (init_vercel(), vercel_exports));
|
|
762
|
+
return getVercelStorageConfig2();
|
|
763
|
+
}
|
|
764
|
+
case "custom": {
|
|
765
|
+
return { url: config.url, headers: config.headers };
|
|
766
|
+
}
|
|
767
|
+
default: {
|
|
768
|
+
config;
|
|
769
|
+
throw new Error(
|
|
770
|
+
`Unknown storage type: ${config.type}`
|
|
771
|
+
);
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
function getStorage(storageConfig) {
|
|
776
|
+
let clientPromise = null;
|
|
777
|
+
const getClient = () => {
|
|
778
|
+
if (!clientPromise) {
|
|
779
|
+
clientPromise = resolveStorageUrl(storageConfig).then(
|
|
780
|
+
(resolved) => getStorageClient(resolved)
|
|
781
|
+
);
|
|
782
|
+
}
|
|
783
|
+
return clientPromise;
|
|
784
|
+
};
|
|
785
|
+
return {
|
|
786
|
+
session: {
|
|
787
|
+
get: async (id) => (await getClient()).session.get(id),
|
|
788
|
+
set: async (session) => (await getClient()).session.set(session),
|
|
789
|
+
list: async (opts) => (await getClient()).session.list(opts),
|
|
790
|
+
tag: {
|
|
791
|
+
set: async (opts) => (await getClient()).session.tag.set(opts)
|
|
792
|
+
}
|
|
793
|
+
},
|
|
794
|
+
message: {
|
|
795
|
+
list: async (sessionId, opts) => (await getClient()).message.list(sessionId, opts),
|
|
796
|
+
get: async (id) => (await getClient()).message.get(id),
|
|
797
|
+
set: async (message) => (await getClient()).message.set(message)
|
|
798
|
+
},
|
|
799
|
+
part: {
|
|
800
|
+
listByMessage: async (messageId, opts) => (await getClient()).part.listByMessage(messageId, opts),
|
|
801
|
+
listBySession: async (sessionId, opts) => (await getClient()).part.listBySession(sessionId, opts),
|
|
802
|
+
set: async (part) => (await getClient()).part.set(part)
|
|
803
|
+
},
|
|
804
|
+
sandbox: {
|
|
805
|
+
get: async (key) => (await getClient()).sandbox.get(key),
|
|
806
|
+
set: async (opts) => (await getClient()).sandbox.set(opts),
|
|
807
|
+
getBySession: async (sessionId) => (await getClient()).sandbox.getBySession(sessionId)
|
|
808
|
+
},
|
|
809
|
+
command: {
|
|
810
|
+
get: async (id) => (await getClient()).command.get(id),
|
|
811
|
+
set: async (command) => (await getClient()).command.set(command),
|
|
812
|
+
list: async (sessionId, opts) => (await getClient()).command.list(sessionId, opts)
|
|
813
|
+
}
|
|
814
|
+
};
|
|
815
|
+
}
|
|
816
|
+
var init_client = __esm({
|
|
817
|
+
"src/storage/client.ts"() {
|
|
818
|
+
"use strict";
|
|
819
|
+
init_errors();
|
|
820
|
+
}
|
|
821
|
+
});
|
|
822
|
+
|
|
823
|
+
// src/storage/rpc.ts
|
|
824
|
+
function ListResultSchema(itemSchema) {
|
|
825
|
+
return import_zod2.z.object({
|
|
826
|
+
items: import_zod2.z.array(itemSchema),
|
|
827
|
+
nextCursor: import_zod2.z.string().nullable()
|
|
828
|
+
});
|
|
829
|
+
}
|
|
830
|
+
var import_zod2, VercelLifecycleConfigSchema, SandboxConfigSchema, SessionSchema, MessageSchema, PartSchema, CommandResultSchema, SandboxRecordSchema, CommandBaseSchema, CommandSchema, methods;
|
|
831
|
+
var init_rpc = __esm({
|
|
832
|
+
"src/storage/rpc.ts"() {
|
|
833
|
+
"use strict";
|
|
834
|
+
import_zod2 = require("zod");
|
|
835
|
+
VercelLifecycleConfigSchema = import_zod2.z.object({
|
|
836
|
+
stopAfterInactiveMs: import_zod2.z.number().optional(),
|
|
837
|
+
snapshotBeforeTimeoutMs: import_zod2.z.number().optional(),
|
|
838
|
+
snapshotId: import_zod2.z.string().optional(),
|
|
839
|
+
autoStart: import_zod2.z.boolean().optional()
|
|
840
|
+
});
|
|
841
|
+
SandboxConfigSchema = import_zod2.z.discriminatedUnion("type", [
|
|
842
|
+
import_zod2.z.object({
|
|
843
|
+
type: import_zod2.z.literal("vercel"),
|
|
844
|
+
resources: import_zod2.z.object({ vcpus: import_zod2.z.number() }).optional(),
|
|
845
|
+
ports: import_zod2.z.array(import_zod2.z.number()).optional(),
|
|
846
|
+
lifecycle: VercelLifecycleConfigSchema.optional()
|
|
847
|
+
}),
|
|
848
|
+
import_zod2.z.object({
|
|
849
|
+
type: import_zod2.z.literal("local"),
|
|
850
|
+
path: import_zod2.z.string().optional()
|
|
851
|
+
}),
|
|
852
|
+
import_zod2.z.object({
|
|
853
|
+
type: import_zod2.z.literal("custom"),
|
|
854
|
+
url: import_zod2.z.string(),
|
|
855
|
+
headers: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.string()).optional()
|
|
856
|
+
})
|
|
857
|
+
]);
|
|
858
|
+
SessionSchema = import_zod2.z.object({
|
|
859
|
+
id: import_zod2.z.string(),
|
|
860
|
+
createdAt: import_zod2.z.number(),
|
|
861
|
+
updatedAt: import_zod2.z.number(),
|
|
862
|
+
runId: import_zod2.z.string().nullable(),
|
|
863
|
+
lastMessageId: import_zod2.z.string().nullable(),
|
|
864
|
+
tags: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).nullable(),
|
|
865
|
+
instructions: import_zod2.z.string().nullable(),
|
|
866
|
+
model: import_zod2.z.string().nullable(),
|
|
867
|
+
mcp: import_zod2.z.unknown().nullable(),
|
|
868
|
+
// TODO
|
|
869
|
+
sandboxId: import_zod2.z.string().nullable(),
|
|
870
|
+
skillsDir: import_zod2.z.array(import_zod2.z.string()).nullable(),
|
|
871
|
+
hookToken: import_zod2.z.string().nullable()
|
|
872
|
+
});
|
|
873
|
+
MessageSchema = import_zod2.z.object({
|
|
874
|
+
id: import_zod2.z.string(),
|
|
875
|
+
sessionId: import_zod2.z.string(),
|
|
876
|
+
role: import_zod2.z.enum(["user", "assistant", "system"]),
|
|
877
|
+
createdAt: import_zod2.z.number(),
|
|
878
|
+
completedAt: import_zod2.z.number().nullable(),
|
|
879
|
+
mcpContext: import_zod2.z.unknown().nullable()
|
|
880
|
+
});
|
|
881
|
+
PartSchema = import_zod2.z.object({
|
|
882
|
+
id: import_zod2.z.string(),
|
|
883
|
+
messageId: import_zod2.z.string(),
|
|
884
|
+
sessionId: import_zod2.z.string(),
|
|
885
|
+
index: import_zod2.z.number(),
|
|
886
|
+
part: import_zod2.z.unknown()
|
|
887
|
+
});
|
|
888
|
+
CommandResultSchema = import_zod2.z.object({
|
|
889
|
+
stdout: import_zod2.z.string(),
|
|
890
|
+
stderr: import_zod2.z.string(),
|
|
891
|
+
exitCode: import_zod2.z.number(),
|
|
892
|
+
completedAt: import_zod2.z.number()
|
|
893
|
+
});
|
|
894
|
+
SandboxRecordSchema = import_zod2.z.object({
|
|
895
|
+
id: import_zod2.z.string(),
|
|
896
|
+
config: SandboxConfigSchema,
|
|
897
|
+
createdAt: import_zod2.z.number().nullable(),
|
|
898
|
+
lastActivityAt: import_zod2.z.number().nullable(),
|
|
899
|
+
acquiringLockId: import_zod2.z.string().nullable(),
|
|
900
|
+
acquiringLockAt: import_zod2.z.number().nullable(),
|
|
901
|
+
providerMetadata: import_zod2.z.discriminatedUnion("provider", [
|
|
902
|
+
import_zod2.z.object({
|
|
903
|
+
provider: import_zod2.z.literal("vercel"),
|
|
904
|
+
sandboxId: import_zod2.z.string().nullable(),
|
|
905
|
+
snapshotId: import_zod2.z.string().nullable()
|
|
906
|
+
})
|
|
907
|
+
]).optional()
|
|
908
|
+
});
|
|
909
|
+
CommandBaseSchema = import_zod2.z.object({
|
|
910
|
+
id: import_zod2.z.string(),
|
|
911
|
+
sessionId: import_zod2.z.string(),
|
|
912
|
+
command: import_zod2.z.string(),
|
|
913
|
+
args: import_zod2.z.array(import_zod2.z.string()).optional(),
|
|
914
|
+
startedAt: import_zod2.z.number()
|
|
915
|
+
});
|
|
916
|
+
CommandSchema = import_zod2.z.discriminatedUnion("status", [
|
|
917
|
+
CommandBaseSchema.extend({ status: import_zod2.z.literal("running") }),
|
|
918
|
+
CommandBaseSchema.extend({
|
|
919
|
+
status: import_zod2.z.literal("completed"),
|
|
920
|
+
result: CommandResultSchema
|
|
921
|
+
}),
|
|
922
|
+
CommandBaseSchema.extend({
|
|
923
|
+
status: import_zod2.z.literal("killed"),
|
|
924
|
+
result: CommandResultSchema.optional()
|
|
925
|
+
}),
|
|
926
|
+
CommandBaseSchema.extend({
|
|
927
|
+
status: import_zod2.z.literal("failed"),
|
|
928
|
+
result: CommandResultSchema
|
|
929
|
+
})
|
|
930
|
+
]);
|
|
931
|
+
methods = {
|
|
932
|
+
"session.get": {
|
|
933
|
+
params: import_zod2.z.object({ id: import_zod2.z.string() }),
|
|
934
|
+
result: SessionSchema.nullable()
|
|
935
|
+
},
|
|
936
|
+
"session.set": {
|
|
937
|
+
params: SessionSchema,
|
|
938
|
+
result: SessionSchema
|
|
939
|
+
},
|
|
940
|
+
"session.list": {
|
|
941
|
+
params: import_zod2.z.object({
|
|
942
|
+
tags: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).optional(),
|
|
943
|
+
order: import_zod2.z.enum([
|
|
944
|
+
"createdAt_asc",
|
|
945
|
+
"createdAt_desc",
|
|
946
|
+
"updatedAt_asc",
|
|
947
|
+
"updatedAt_desc"
|
|
948
|
+
]).optional(),
|
|
949
|
+
cursor: import_zod2.z.string().optional(),
|
|
950
|
+
limit: import_zod2.z.number().optional()
|
|
951
|
+
}),
|
|
952
|
+
result: ListResultSchema(SessionSchema)
|
|
953
|
+
},
|
|
954
|
+
"session.listBySandbox": {
|
|
955
|
+
params: import_zod2.z.object({
|
|
956
|
+
sandboxId: import_zod2.z.string(),
|
|
957
|
+
tags: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).optional(),
|
|
958
|
+
order: import_zod2.z.enum([
|
|
959
|
+
"createdAt_asc",
|
|
960
|
+
"createdAt_desc",
|
|
961
|
+
"updatedAt_asc",
|
|
962
|
+
"updatedAt_desc"
|
|
963
|
+
]).optional(),
|
|
964
|
+
cursor: import_zod2.z.string().optional(),
|
|
965
|
+
limit: import_zod2.z.number().optional()
|
|
966
|
+
}),
|
|
967
|
+
result: ListResultSchema(SessionSchema)
|
|
968
|
+
},
|
|
969
|
+
"session.tag.set": {
|
|
970
|
+
params: import_zod2.z.object({
|
|
971
|
+
sessionId: import_zod2.z.string(),
|
|
972
|
+
tags: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown())
|
|
973
|
+
}),
|
|
974
|
+
result: SessionSchema
|
|
975
|
+
},
|
|
976
|
+
"message.get": {
|
|
977
|
+
params: import_zod2.z.object({ id: import_zod2.z.string() }),
|
|
978
|
+
result: MessageSchema.nullable()
|
|
979
|
+
},
|
|
980
|
+
"message.set": {
|
|
981
|
+
params: MessageSchema,
|
|
982
|
+
result: MessageSchema
|
|
983
|
+
},
|
|
984
|
+
"message.list": {
|
|
985
|
+
params: import_zod2.z.object({
|
|
986
|
+
sessionId: import_zod2.z.string(),
|
|
987
|
+
cursor: import_zod2.z.string().optional(),
|
|
988
|
+
limit: import_zod2.z.number().optional()
|
|
989
|
+
}),
|
|
990
|
+
result: ListResultSchema(MessageSchema)
|
|
991
|
+
},
|
|
992
|
+
"part.listByMessage": {
|
|
993
|
+
params: import_zod2.z.object({
|
|
994
|
+
messageId: import_zod2.z.string(),
|
|
995
|
+
cursor: import_zod2.z.string().optional(),
|
|
996
|
+
limit: import_zod2.z.number().optional()
|
|
997
|
+
}),
|
|
998
|
+
result: ListResultSchema(PartSchema)
|
|
999
|
+
},
|
|
1000
|
+
"part.listBySession": {
|
|
1001
|
+
params: import_zod2.z.object({
|
|
1002
|
+
sessionId: import_zod2.z.string(),
|
|
1003
|
+
cursor: import_zod2.z.string().optional(),
|
|
1004
|
+
limit: import_zod2.z.number().optional()
|
|
1005
|
+
}),
|
|
1006
|
+
result: ListResultSchema(PartSchema)
|
|
1007
|
+
},
|
|
1008
|
+
"part.set": {
|
|
1009
|
+
params: PartSchema,
|
|
1010
|
+
result: PartSchema
|
|
1011
|
+
},
|
|
1012
|
+
"sandbox.get": {
|
|
1013
|
+
params: import_zod2.z.object({ key: import_zod2.z.string() }),
|
|
1014
|
+
result: SandboxRecordSchema.nullable()
|
|
1015
|
+
},
|
|
1016
|
+
"sandbox.getBySession": {
|
|
1017
|
+
params: import_zod2.z.object({ sessionId: import_zod2.z.string() }),
|
|
1018
|
+
result: SandboxRecordSchema.nullable()
|
|
1019
|
+
},
|
|
1020
|
+
"sandbox.set": {
|
|
1021
|
+
params: SandboxRecordSchema,
|
|
1022
|
+
result: import_zod2.z.void()
|
|
1023
|
+
},
|
|
1024
|
+
"command.get": {
|
|
1025
|
+
params: import_zod2.z.object({ id: import_zod2.z.string() }),
|
|
1026
|
+
result: CommandSchema.nullable()
|
|
1027
|
+
},
|
|
1028
|
+
"command.set": {
|
|
1029
|
+
params: CommandSchema,
|
|
1030
|
+
result: CommandSchema
|
|
1031
|
+
},
|
|
1032
|
+
"command.list": {
|
|
1033
|
+
params: import_zod2.z.object({
|
|
1034
|
+
sessionId: import_zod2.z.string(),
|
|
1035
|
+
includeFinished: import_zod2.z.boolean().optional(),
|
|
1036
|
+
cursor: import_zod2.z.string().optional(),
|
|
1037
|
+
limit: import_zod2.z.number().optional()
|
|
1038
|
+
}),
|
|
1039
|
+
result: ListResultSchema(CommandSchema)
|
|
1040
|
+
}
|
|
1041
|
+
};
|
|
1042
|
+
}
|
|
1043
|
+
});
|
|
1044
|
+
|
|
1045
|
+
// src/storage/handler.ts
|
|
1046
|
+
async function handleStorageRpc(body, handlers) {
|
|
1047
|
+
const { method, params } = body;
|
|
1048
|
+
if (!(method in methods)) {
|
|
1049
|
+
return {
|
|
1050
|
+
error: { code: "METHOD_NOT_FOUND", message: `Unknown method: ${method}` }
|
|
1051
|
+
};
|
|
1052
|
+
}
|
|
1053
|
+
const methodName = method;
|
|
1054
|
+
const schema = methods[methodName].params;
|
|
1055
|
+
const parsed = schema.safeParse(params);
|
|
1056
|
+
if (!parsed.success) {
|
|
1057
|
+
return {
|
|
1058
|
+
error: {
|
|
1059
|
+
code: "INVALID_PARAMS",
|
|
1060
|
+
message: parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join(", ")
|
|
1061
|
+
}
|
|
1062
|
+
};
|
|
1063
|
+
}
|
|
1064
|
+
try {
|
|
1065
|
+
const handler = handlers[methodName];
|
|
1066
|
+
const result = await handler(parsed.data);
|
|
1067
|
+
return { result };
|
|
1068
|
+
} catch (e) {
|
|
1069
|
+
return {
|
|
1070
|
+
error: {
|
|
1071
|
+
code: "INTERNAL_ERROR",
|
|
1072
|
+
message: e instanceof Error ? e.message : String(e)
|
|
1073
|
+
}
|
|
1074
|
+
};
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
var init_handler = __esm({
|
|
1078
|
+
"src/storage/handler.ts"() {
|
|
1079
|
+
"use strict";
|
|
1080
|
+
init_rpc();
|
|
1081
|
+
}
|
|
1082
|
+
});
|
|
1083
|
+
|
|
1084
|
+
// src/storage/index.ts
|
|
1085
|
+
var storage_exports = {};
|
|
1086
|
+
__export(storage_exports, {
|
|
1087
|
+
CommandResultSchema: () => CommandResultSchema,
|
|
1088
|
+
CommandSchema: () => CommandSchema,
|
|
1089
|
+
MessageSchema: () => MessageSchema,
|
|
1090
|
+
PartSchema: () => PartSchema,
|
|
1091
|
+
SandboxConfigSchema: () => SandboxConfigSchema,
|
|
1092
|
+
SandboxRecordSchema: () => SandboxRecordSchema,
|
|
1093
|
+
SessionSchema: () => SessionSchema,
|
|
1094
|
+
getStorage: () => getStorage,
|
|
1095
|
+
handleStorageRpc: () => handleStorageRpc,
|
|
1096
|
+
methods: () => methods
|
|
1097
|
+
});
|
|
1098
|
+
var init_storage = __esm({
|
|
1099
|
+
"src/storage/index.ts"() {
|
|
1100
|
+
"use strict";
|
|
1101
|
+
init_client();
|
|
1102
|
+
init_handler();
|
|
1103
|
+
init_rpc();
|
|
1104
|
+
}
|
|
1105
|
+
});
|
|
1106
|
+
|
|
1107
|
+
// src/sandbox/write-files.ts
|
|
1108
|
+
async function writeFiles(opts) {
|
|
1109
|
+
const { sandbox, files, destPath } = opts;
|
|
1110
|
+
if (files.length === 0) {
|
|
1111
|
+
return;
|
|
1112
|
+
}
|
|
1113
|
+
const filePaths = files.map((file) => path.posix.join(destPath, file.path));
|
|
1114
|
+
const parentDirs = [...new Set(filePaths.map((p) => path.posix.dirname(p)))];
|
|
1115
|
+
const shellScripts = filePaths.filter((p) => p.endsWith(".sh"));
|
|
1116
|
+
const mkdirResult = await sandbox.exec({
|
|
1117
|
+
command: "mkdir",
|
|
1118
|
+
args: ["-p", ...parentDirs]
|
|
1119
|
+
});
|
|
1120
|
+
if (mkdirResult instanceof Error) {
|
|
1121
|
+
throw mkdirResult;
|
|
1122
|
+
}
|
|
1123
|
+
await mkdirResult.result;
|
|
1124
|
+
const CHUNK_SIZE = 5e4;
|
|
1125
|
+
for (let i = 0; i < files.length; i++) {
|
|
1126
|
+
const file = files[i];
|
|
1127
|
+
const fullPath = filePaths[i];
|
|
1128
|
+
const base64Content = toBase64(file.content);
|
|
1129
|
+
if (base64Content.length < CHUNK_SIZE) {
|
|
1130
|
+
const marker = `EOF_${i}`;
|
|
1131
|
+
const execResult = await sandbox.exec({
|
|
1132
|
+
command: "bash",
|
|
1133
|
+
args: [
|
|
1134
|
+
"-c",
|
|
1135
|
+
`base64 -d > ${quote(fullPath)} << '${marker}'
|
|
1136
|
+
${base64Content}
|
|
1137
|
+
${marker}`
|
|
1138
|
+
]
|
|
1139
|
+
});
|
|
1140
|
+
if (execResult instanceof Error) {
|
|
1141
|
+
throw execResult;
|
|
1142
|
+
}
|
|
1143
|
+
const { exitCode, stderr } = await execResult.result;
|
|
1144
|
+
if (exitCode !== 0) {
|
|
1145
|
+
throw new Error(
|
|
1146
|
+
`writeFiles failed with exit code ${exitCode}: ${stderr}`
|
|
1147
|
+
);
|
|
1148
|
+
}
|
|
1149
|
+
} else {
|
|
1150
|
+
const tempB64 = `/tmp/chunk-${Date.now()}-${i}.b64`;
|
|
1151
|
+
const clearResult = await sandbox.exec({
|
|
1152
|
+
command: "bash",
|
|
1153
|
+
args: ["-c", `> ${quote(tempB64)}`]
|
|
1154
|
+
});
|
|
1155
|
+
if (clearResult instanceof Error) {
|
|
1156
|
+
throw clearResult;
|
|
1157
|
+
}
|
|
1158
|
+
await clearResult.result;
|
|
1159
|
+
for (let offset = 0; offset < base64Content.length; offset += CHUNK_SIZE) {
|
|
1160
|
+
const chunk = base64Content.slice(offset, offset + CHUNK_SIZE);
|
|
1161
|
+
const marker = `CHUNK_${offset}`;
|
|
1162
|
+
const appendResult = await sandbox.exec({
|
|
1163
|
+
command: "bash",
|
|
1164
|
+
args: [
|
|
1165
|
+
"-c",
|
|
1166
|
+
`cat >> ${quote(tempB64)} << '${marker}'
|
|
1167
|
+
${chunk}
|
|
1168
|
+
${marker}`
|
|
1169
|
+
]
|
|
1170
|
+
});
|
|
1171
|
+
if (appendResult instanceof Error) {
|
|
1172
|
+
throw appendResult;
|
|
1173
|
+
}
|
|
1174
|
+
const { exitCode: exitCode2, stderr: stderr2 } = await appendResult.result;
|
|
1175
|
+
if (exitCode2 !== 0) {
|
|
1176
|
+
throw new Error(
|
|
1177
|
+
`writeFiles chunk failed with exit code ${exitCode2}: ${stderr2}`
|
|
1178
|
+
);
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
const decodeResult = await sandbox.exec({
|
|
1182
|
+
command: "bash",
|
|
1183
|
+
args: [
|
|
1184
|
+
"-c",
|
|
1185
|
+
`base64 -d < ${quote(tempB64)} > ${quote(fullPath)} && rm -f ${quote(tempB64)}`
|
|
1186
|
+
]
|
|
1187
|
+
});
|
|
1188
|
+
if (decodeResult instanceof Error) {
|
|
1189
|
+
throw decodeResult;
|
|
1190
|
+
}
|
|
1191
|
+
const { exitCode, stderr } = await decodeResult.result;
|
|
1192
|
+
if (exitCode !== 0) {
|
|
1193
|
+
throw new Error(
|
|
1194
|
+
`writeFiles decode failed with exit code ${exitCode}: ${stderr}`
|
|
1195
|
+
);
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
if (shellScripts.length > 0) {
|
|
1200
|
+
const chmodResult = await sandbox.exec({
|
|
1201
|
+
command: "chmod",
|
|
1202
|
+
args: ["+x", ...shellScripts]
|
|
1203
|
+
});
|
|
1204
|
+
if (chmodResult instanceof Error) {
|
|
1205
|
+
throw chmodResult;
|
|
1206
|
+
}
|
|
1207
|
+
await chmodResult.result;
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
function toBase64(content) {
|
|
1211
|
+
if (typeof content === "string") {
|
|
1212
|
+
return Buffer.from(content).toString("base64");
|
|
1213
|
+
}
|
|
1214
|
+
return content.toString("base64");
|
|
1215
|
+
}
|
|
1216
|
+
function quote(s) {
|
|
1217
|
+
return `'${s.replace(/'/g, "'\\''")}'`;
|
|
1218
|
+
}
|
|
1219
|
+
var path;
|
|
1220
|
+
var init_write_files = __esm({
|
|
1221
|
+
"src/sandbox/write-files.ts"() {
|
|
1222
|
+
"use strict";
|
|
1223
|
+
path = __toESM(require("path"));
|
|
1224
|
+
}
|
|
1225
|
+
});
|
|
1226
|
+
|
|
1227
|
+
// src/sandbox/bindings/local.ts
|
|
1228
|
+
var import_node_child_process, errore2, import_ulid, localSandbox;
|
|
1229
|
+
var init_local2 = __esm({
|
|
1230
|
+
"src/sandbox/bindings/local.ts"() {
|
|
1231
|
+
"use strict";
|
|
1232
|
+
import_node_child_process = require("child_process");
|
|
1233
|
+
errore2 = __toESM(require("errore"));
|
|
1234
|
+
import_ulid = require("ulid");
|
|
1235
|
+
init_errors();
|
|
1236
|
+
init_write_files();
|
|
1237
|
+
localSandbox = ({
|
|
1238
|
+
sandboxRecord
|
|
1239
|
+
}) => {
|
|
1240
|
+
const config = sandboxRecord.config;
|
|
1241
|
+
const basePath = config.path ?? process.cwd();
|
|
1242
|
+
const processes = /* @__PURE__ */ new Map();
|
|
1243
|
+
const sandbox = {
|
|
1244
|
+
id: sandboxRecord.id,
|
|
1245
|
+
config: sandboxRecord.config,
|
|
1246
|
+
exec: ({ command, args, signal }) => {
|
|
1247
|
+
return errore2.tryAsync({
|
|
1248
|
+
try: () => {
|
|
1249
|
+
const commandId = `command_${(0, import_ulid.ulid)()}`;
|
|
1250
|
+
const child = (0, import_node_child_process.spawn)(command, args, {
|
|
1251
|
+
cwd: basePath,
|
|
1252
|
+
signal
|
|
1253
|
+
});
|
|
1254
|
+
processes.set(commandId, child);
|
|
1255
|
+
let stdout = "";
|
|
1256
|
+
let stderr = "";
|
|
1257
|
+
const logQueue = [];
|
|
1258
|
+
let logResolve = null;
|
|
1259
|
+
let closed = false;
|
|
1260
|
+
child.stdout.on("data", (data) => {
|
|
1261
|
+
const str = String(data);
|
|
1262
|
+
stdout += str;
|
|
1263
|
+
logQueue.push({ stream: "stdout", data: str });
|
|
1264
|
+
logResolve?.();
|
|
1265
|
+
});
|
|
1266
|
+
child.stderr.on("data", (data) => {
|
|
1267
|
+
const str = String(data);
|
|
1268
|
+
stderr += str;
|
|
1269
|
+
logQueue.push({ stream: "stderr", data: str });
|
|
1270
|
+
logResolve?.();
|
|
1271
|
+
});
|
|
1272
|
+
const result = new Promise((resolve, reject) => {
|
|
1273
|
+
child.on("error", (err) => {
|
|
1274
|
+
processes.delete(commandId);
|
|
1275
|
+
closed = true;
|
|
1276
|
+
logResolve?.();
|
|
1277
|
+
reject(err);
|
|
1278
|
+
});
|
|
1279
|
+
child.on("close", (code) => {
|
|
1280
|
+
processes.delete(commandId);
|
|
1281
|
+
closed = true;
|
|
1282
|
+
logResolve?.();
|
|
1283
|
+
resolve({ stdout, stderr, exitCode: code ?? 0 });
|
|
1284
|
+
});
|
|
1285
|
+
});
|
|
1286
|
+
async function* logs() {
|
|
1287
|
+
while (!closed || logQueue.length > 0) {
|
|
1288
|
+
const entry = logQueue.shift();
|
|
1289
|
+
if (entry) {
|
|
1290
|
+
yield entry;
|
|
1291
|
+
} else if (!closed) {
|
|
1292
|
+
await new Promise((resolve) => {
|
|
1293
|
+
logResolve = resolve;
|
|
1294
|
+
});
|
|
1295
|
+
logResolve = null;
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
return Promise.resolve({ commandId, logs, result });
|
|
1300
|
+
},
|
|
1301
|
+
catch: (e) => new SandboxError({ reason: String(e), cause: e })
|
|
1302
|
+
});
|
|
1303
|
+
},
|
|
1304
|
+
getDomain: (port) => {
|
|
1305
|
+
return Promise.resolve(`http://localhost:${port}`);
|
|
1306
|
+
},
|
|
1307
|
+
kill: async ({ commandId, storage }) => {
|
|
1308
|
+
const child = processes.get(commandId);
|
|
1309
|
+
if (!child) {
|
|
1310
|
+
return new SandboxError({
|
|
1311
|
+
reason: `Command ${commandId} not found or already finished`
|
|
1312
|
+
});
|
|
1313
|
+
}
|
|
1314
|
+
child.kill("SIGTERM");
|
|
1315
|
+
const cmd = await storage.command.get(commandId);
|
|
1316
|
+
if (cmd instanceof Error) {
|
|
1317
|
+
return new SandboxError({ reason: cmd.message, cause: cmd });
|
|
1318
|
+
}
|
|
1319
|
+
if (cmd && cmd.status === "running") {
|
|
1320
|
+
const result = await storage.command.set({
|
|
1321
|
+
...cmd,
|
|
1322
|
+
status: "killed"
|
|
1323
|
+
});
|
|
1324
|
+
if (result instanceof Error) {
|
|
1325
|
+
return new SandboxError({ reason: result.message, cause: result });
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
},
|
|
1329
|
+
writeFiles: (opts) => writeFiles({ sandbox, ...opts })
|
|
1330
|
+
};
|
|
1331
|
+
return sandbox;
|
|
1332
|
+
};
|
|
1333
|
+
}
|
|
1334
|
+
});
|
|
1335
|
+
|
|
1336
|
+
// src/sandbox/bindings/vercel.ts
|
|
1337
|
+
var errore3, import_sandbox, VERCEL_MAX_TIMEOUT_MS, LOCK_TIMEOUT_MS, LOCK_POLL_INTERVAL_MS, getTestCredentials, createPromises, ACTIVITY_THROTTLE_MS, lastActivitySent, DEFAULT_VCPUS, vercelSandbox;
|
|
1338
|
+
var init_vercel2 = __esm({
|
|
1339
|
+
"src/sandbox/bindings/vercel.ts"() {
|
|
1340
|
+
"use strict";
|
|
1341
|
+
errore3 = __toESM(require("errore"));
|
|
1342
|
+
import_sandbox = require("sandbox");
|
|
1343
|
+
init_errors();
|
|
1344
|
+
init_storage();
|
|
1345
|
+
init_write_files();
|
|
1346
|
+
VERCEL_MAX_TIMEOUT_MS = 5 * 60 * 60 * 1e3;
|
|
1347
|
+
LOCK_TIMEOUT_MS = 3e4;
|
|
1348
|
+
LOCK_POLL_INTERVAL_MS = 200;
|
|
1349
|
+
getTestCredentials = () => process.env.NODE_ENV === "test" ? {
|
|
1350
|
+
token: process.env.TEST_VERCEL_TOKEN,
|
|
1351
|
+
teamId: process.env.TEST_VERCEL_TEAM_ID,
|
|
1352
|
+
projectId: process.env.TEST_VERCEL_PROJECT_ID
|
|
1353
|
+
} : {};
|
|
1354
|
+
createPromises = /* @__PURE__ */ new Map();
|
|
1355
|
+
ACTIVITY_THROTTLE_MS = 1e4;
|
|
1356
|
+
lastActivitySent = /* @__PURE__ */ new Map();
|
|
1357
|
+
DEFAULT_VCPUS = 2;
|
|
1358
|
+
vercelSandbox = ({
|
|
1359
|
+
sandboxRecord,
|
|
1360
|
+
storageConfig,
|
|
1361
|
+
enableLifecycleWorkflow = true,
|
|
1362
|
+
storage: storageOverride
|
|
1363
|
+
}) => {
|
|
1364
|
+
const { id, config } = sandboxRecord;
|
|
1365
|
+
const vcpus = config.resources?.vcpus ?? DEFAULT_VCPUS;
|
|
1366
|
+
const ports = config.ports;
|
|
1367
|
+
const storage = storageOverride ?? getStorage(storageConfig);
|
|
1368
|
+
const initialVercel = sandboxRecord.providerMetadata?.provider === "vercel" ? sandboxRecord.providerMetadata : null;
|
|
1369
|
+
let sandboxPromise = null;
|
|
1370
|
+
async function pollForSandboxId() {
|
|
1371
|
+
const deadline = Date.now() + LOCK_TIMEOUT_MS;
|
|
1372
|
+
while (Date.now() < deadline) {
|
|
1373
|
+
await new Promise((r) => setTimeout(r, LOCK_POLL_INTERVAL_MS));
|
|
1374
|
+
const record = await storage.sandbox.get(id);
|
|
1375
|
+
if (record instanceof Error) {
|
|
1376
|
+
return new SandboxError({ reason: record.message, cause: record });
|
|
1377
|
+
}
|
|
1378
|
+
const vercelSandboxId = record?.providerMetadata?.provider === "vercel" ? record.providerMetadata.sandboxId : null;
|
|
1379
|
+
if (vercelSandboxId) {
|
|
1380
|
+
return vercelSandboxId;
|
|
1381
|
+
}
|
|
1382
|
+
if (!record?.acquiringLockAt) {
|
|
1383
|
+
break;
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
return new SandboxError({
|
|
1387
|
+
reason: "Timed out waiting for sandbox creation by another process"
|
|
1388
|
+
});
|
|
1389
|
+
}
|
|
1390
|
+
async function createSandboxFromSnapshot(snapshotId) {
|
|
1391
|
+
return await errore3.tryAsync({
|
|
1392
|
+
try: async () => {
|
|
1393
|
+
const sandbox2 = await import_sandbox.Sandbox.create({
|
|
1394
|
+
source: { type: "snapshot", snapshotId },
|
|
1395
|
+
resources: { vcpus },
|
|
1396
|
+
timeout: VERCEL_MAX_TIMEOUT_MS,
|
|
1397
|
+
ports,
|
|
1398
|
+
...getTestCredentials()
|
|
1399
|
+
});
|
|
1400
|
+
const now = Date.now();
|
|
1401
|
+
await storage.sandbox.set({
|
|
1402
|
+
id,
|
|
1403
|
+
config,
|
|
1404
|
+
createdAt: now,
|
|
1405
|
+
lastActivityAt: now,
|
|
1406
|
+
acquiringLockId: null,
|
|
1407
|
+
acquiringLockAt: null,
|
|
1408
|
+
providerMetadata: {
|
|
1409
|
+
provider: "vercel",
|
|
1410
|
+
sandboxId: sandbox2.sandboxId,
|
|
1411
|
+
snapshotId
|
|
1412
|
+
}
|
|
1413
|
+
});
|
|
1414
|
+
return sandbox2.sandboxId;
|
|
1415
|
+
},
|
|
1416
|
+
catch: (e) => new SandboxError({ reason: String(e), cause: e })
|
|
1417
|
+
});
|
|
1418
|
+
}
|
|
1419
|
+
async function createFreshSandbox() {
|
|
1420
|
+
return await errore3.tryAsync({
|
|
1421
|
+
try: async () => {
|
|
1422
|
+
const sandbox2 = await import_sandbox.Sandbox.create({
|
|
1423
|
+
resources: { vcpus },
|
|
1424
|
+
timeout: VERCEL_MAX_TIMEOUT_MS,
|
|
1425
|
+
ports,
|
|
1426
|
+
...getTestCredentials()
|
|
1427
|
+
});
|
|
1428
|
+
const now = Date.now();
|
|
1429
|
+
await storage.sandbox.set({
|
|
1430
|
+
id,
|
|
1431
|
+
config,
|
|
1432
|
+
createdAt: now,
|
|
1433
|
+
lastActivityAt: now,
|
|
1434
|
+
acquiringLockId: null,
|
|
1435
|
+
acquiringLockAt: null,
|
|
1436
|
+
providerMetadata: {
|
|
1437
|
+
provider: "vercel",
|
|
1438
|
+
sandboxId: sandbox2.sandboxId,
|
|
1439
|
+
snapshotId: null
|
|
1440
|
+
}
|
|
1441
|
+
});
|
|
1442
|
+
return sandbox2.sandboxId;
|
|
1443
|
+
},
|
|
1444
|
+
catch: (e) => new SandboxError({ reason: String(e), cause: e })
|
|
1445
|
+
});
|
|
1446
|
+
}
|
|
1447
|
+
async function doGetOrCreateSandboxId() {
|
|
1448
|
+
if (initialVercel?.sandboxId) {
|
|
1449
|
+
return initialVercel.sandboxId;
|
|
1450
|
+
}
|
|
1451
|
+
const existing = await storage.sandbox.get(id);
|
|
1452
|
+
if (existing instanceof Error) {
|
|
1453
|
+
return new SandboxError({ reason: existing.message, cause: existing });
|
|
1454
|
+
}
|
|
1455
|
+
const existingVercel = existing?.providerMetadata?.provider === "vercel" ? existing.providerMetadata : null;
|
|
1456
|
+
if (existingVercel?.sandboxId) {
|
|
1457
|
+
return existingVercel.sandboxId;
|
|
1458
|
+
}
|
|
1459
|
+
const hasActiveLock = existing?.acquiringLockId && existing.acquiringLockAt && Date.now() - existing.acquiringLockAt < LOCK_TIMEOUT_MS;
|
|
1460
|
+
if (hasActiveLock) {
|
|
1461
|
+
return pollForSandboxId();
|
|
1462
|
+
}
|
|
1463
|
+
const lockId = crypto.randomUUID();
|
|
1464
|
+
const now = Date.now();
|
|
1465
|
+
await storage.sandbox.set({
|
|
1466
|
+
id,
|
|
1467
|
+
config,
|
|
1468
|
+
createdAt: existing?.createdAt ?? sandboxRecord.createdAt,
|
|
1469
|
+
lastActivityAt: existing?.lastActivityAt ?? sandboxRecord.lastActivityAt,
|
|
1470
|
+
acquiringLockId: lockId,
|
|
1471
|
+
acquiringLockAt: now,
|
|
1472
|
+
providerMetadata: {
|
|
1473
|
+
provider: "vercel",
|
|
1474
|
+
sandboxId: null,
|
|
1475
|
+
snapshotId: existingVercel?.snapshotId ?? initialVercel?.snapshotId ?? null
|
|
1476
|
+
}
|
|
1477
|
+
});
|
|
1478
|
+
const afterLock = await storage.sandbox.get(id);
|
|
1479
|
+
if (afterLock instanceof Error) {
|
|
1480
|
+
return new SandboxError({ reason: afterLock.message, cause: afterLock });
|
|
1481
|
+
}
|
|
1482
|
+
if (afterLock?.acquiringLockId !== lockId) {
|
|
1483
|
+
return pollForSandboxId();
|
|
1484
|
+
}
|
|
1485
|
+
const snapshotId = existingVercel?.snapshotId ?? initialVercel?.snapshotId ?? config.lifecycle?.snapshotId;
|
|
1486
|
+
if (snapshotId) {
|
|
1487
|
+
const result = await createSandboxFromSnapshot(snapshotId);
|
|
1488
|
+
if (!(result instanceof Error)) {
|
|
1489
|
+
return result;
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
return createFreshSandbox();
|
|
1493
|
+
}
|
|
1494
|
+
function getOrCreateSandboxId() {
|
|
1495
|
+
const cached = createPromises.get(id);
|
|
1496
|
+
if (cached) {
|
|
1497
|
+
return cached;
|
|
1498
|
+
}
|
|
1499
|
+
const promise = doGetOrCreateSandboxId().finally(() => {
|
|
1500
|
+
createPromises.delete(id);
|
|
1501
|
+
});
|
|
1502
|
+
createPromises.set(id, promise);
|
|
1503
|
+
return promise;
|
|
1504
|
+
}
|
|
1505
|
+
async function doGetSandbox() {
|
|
1506
|
+
const vercelSandboxId = await getOrCreateSandboxId();
|
|
1507
|
+
if (vercelSandboxId instanceof Error) {
|
|
1508
|
+
return vercelSandboxId;
|
|
1509
|
+
}
|
|
1510
|
+
return errore3.tryAsync({
|
|
1511
|
+
try: () => import_sandbox.Sandbox.get({
|
|
1512
|
+
sandboxId: vercelSandboxId,
|
|
1513
|
+
...getTestCredentials()
|
|
1514
|
+
}),
|
|
1515
|
+
catch: (e) => new SandboxError({ reason: String(e), cause: e })
|
|
1516
|
+
});
|
|
1517
|
+
}
|
|
1518
|
+
function getSandbox2() {
|
|
1519
|
+
if (!sandboxPromise) {
|
|
1520
|
+
sandboxPromise = doGetSandbox();
|
|
1521
|
+
}
|
|
1522
|
+
return sandboxPromise;
|
|
1523
|
+
}
|
|
1524
|
+
async function updateLastActivity() {
|
|
1525
|
+
const now = Date.now();
|
|
1526
|
+
const lastSent = lastActivitySent.get(id);
|
|
1527
|
+
if (lastSent && now - lastSent < ACTIVITY_THROTTLE_MS) {
|
|
1528
|
+
return;
|
|
1529
|
+
}
|
|
1530
|
+
lastActivitySent.set(id, now);
|
|
1531
|
+
const existing = await storage.sandbox.get(id);
|
|
1532
|
+
if (existing instanceof Error || !existing) {
|
|
1533
|
+
return;
|
|
1534
|
+
}
|
|
1535
|
+
const existingVercel = existing.providerMetadata?.provider === "vercel" ? existing.providerMetadata : null;
|
|
1536
|
+
await storage.sandbox.set({
|
|
1537
|
+
id: existing.id,
|
|
1538
|
+
config: existing.config,
|
|
1539
|
+
createdAt: existing.createdAt,
|
|
1540
|
+
lastActivityAt: now,
|
|
1541
|
+
acquiringLockId: null,
|
|
1542
|
+
acquiringLockAt: null,
|
|
1543
|
+
providerMetadata: existingVercel ?? {
|
|
1544
|
+
provider: "vercel",
|
|
1545
|
+
sandboxId: null,
|
|
1546
|
+
snapshotId: null
|
|
1547
|
+
}
|
|
1548
|
+
});
|
|
1549
|
+
if (enableLifecycleWorkflow) {
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
const lifecycle = {
|
|
1553
|
+
start: async () => {
|
|
1554
|
+
const sandbox2 = await getSandbox2();
|
|
1555
|
+
if (sandbox2 instanceof Error) {
|
|
1556
|
+
return sandbox2;
|
|
1557
|
+
}
|
|
1558
|
+
await updateLastActivity();
|
|
1559
|
+
return sandbox2.status;
|
|
1560
|
+
},
|
|
1561
|
+
snapshot: async () => {
|
|
1562
|
+
const sandbox2 = await getSandbox2();
|
|
1563
|
+
if (sandbox2 instanceof Error) {
|
|
1564
|
+
return sandbox2;
|
|
1565
|
+
}
|
|
1566
|
+
return errore3.tryAsync({
|
|
1567
|
+
try: async () => {
|
|
1568
|
+
const existing = await storage.sandbox.get(id);
|
|
1569
|
+
const snapshot = await sandbox2.snapshot();
|
|
1570
|
+
await storage.sandbox.set({
|
|
1571
|
+
id,
|
|
1572
|
+
config,
|
|
1573
|
+
createdAt: existing instanceof Error ? null : existing?.createdAt ?? null,
|
|
1574
|
+
lastActivityAt: existing instanceof Error ? null : existing?.lastActivityAt ?? null,
|
|
1575
|
+
acquiringLockId: null,
|
|
1576
|
+
acquiringLockAt: null,
|
|
1577
|
+
providerMetadata: {
|
|
1578
|
+
provider: "vercel",
|
|
1579
|
+
sandboxId: null,
|
|
1580
|
+
snapshotId: snapshot.snapshotId
|
|
1581
|
+
}
|
|
1582
|
+
});
|
|
1583
|
+
return { snapshotId: snapshot.snapshotId };
|
|
1584
|
+
},
|
|
1585
|
+
catch: (e) => new SandboxError({ reason: String(e), cause: e })
|
|
1586
|
+
});
|
|
1587
|
+
},
|
|
1588
|
+
stop: async () => {
|
|
1589
|
+
const sandbox2 = await getSandbox2();
|
|
1590
|
+
if (sandbox2 instanceof Error) {
|
|
1591
|
+
return sandbox2;
|
|
1592
|
+
}
|
|
1593
|
+
return errore3.tryAsync({
|
|
1594
|
+
try: async () => {
|
|
1595
|
+
await sandbox2.stop();
|
|
1596
|
+
const existing = await storage.sandbox.get(id);
|
|
1597
|
+
if (existing instanceof Error || !existing) {
|
|
1598
|
+
return void 0;
|
|
1599
|
+
}
|
|
1600
|
+
await storage.sandbox.set({
|
|
1601
|
+
id: existing.id,
|
|
1602
|
+
config: existing.config,
|
|
1603
|
+
createdAt: existing.createdAt,
|
|
1604
|
+
lastActivityAt: existing.lastActivityAt,
|
|
1605
|
+
acquiringLockId: null,
|
|
1606
|
+
acquiringLockAt: null,
|
|
1607
|
+
providerMetadata: {
|
|
1608
|
+
provider: "vercel",
|
|
1609
|
+
sandboxId: null,
|
|
1610
|
+
snapshotId: null
|
|
1611
|
+
}
|
|
1612
|
+
});
|
|
1613
|
+
return void 0;
|
|
1614
|
+
},
|
|
1615
|
+
catch: (e) => new SandboxError({ reason: String(e), cause: e })
|
|
1616
|
+
});
|
|
1617
|
+
},
|
|
1618
|
+
getStatus: async () => {
|
|
1619
|
+
const sandbox2 = await getSandbox2();
|
|
1620
|
+
if (sandbox2 instanceof Error) {
|
|
1621
|
+
return sandbox2;
|
|
1622
|
+
}
|
|
1623
|
+
return sandbox2.status;
|
|
1624
|
+
},
|
|
1625
|
+
getCreatedAt: async () => {
|
|
1626
|
+
const sandbox2 = await getSandbox2();
|
|
1627
|
+
if (sandbox2 instanceof Error) {
|
|
1628
|
+
return sandbox2;
|
|
1629
|
+
}
|
|
1630
|
+
return sandbox2.createdAt;
|
|
1631
|
+
},
|
|
1632
|
+
getRemainingTimeout: async () => {
|
|
1633
|
+
const sandbox2 = await getSandbox2();
|
|
1634
|
+
if (sandbox2 instanceof Error) {
|
|
1635
|
+
return sandbox2;
|
|
1636
|
+
}
|
|
1637
|
+
return sandbox2.timeout;
|
|
1638
|
+
}
|
|
1639
|
+
};
|
|
1640
|
+
const sandbox = {
|
|
1641
|
+
id,
|
|
1642
|
+
config,
|
|
1643
|
+
exec: async ({ command, args, signal }) => {
|
|
1644
|
+
const instance = await getSandbox2();
|
|
1645
|
+
if (instance instanceof Error) {
|
|
1646
|
+
return instance;
|
|
1647
|
+
}
|
|
1648
|
+
const updatePromise = updateLastActivity();
|
|
1649
|
+
const execResult = await errore3.tryAsync({
|
|
1650
|
+
try: async () => {
|
|
1651
|
+
const output = await instance.runCommand(command, args, { signal });
|
|
1652
|
+
let stdout = "";
|
|
1653
|
+
let stderr = "";
|
|
1654
|
+
const logBuffer = [];
|
|
1655
|
+
const state = {
|
|
1656
|
+
resolve: null,
|
|
1657
|
+
consumed: false
|
|
1658
|
+
};
|
|
1659
|
+
const consumeLogs = (async () => {
|
|
1660
|
+
for await (const log of output.logs()) {
|
|
1661
|
+
const entry = log.stream === "stdout" ? { stream: "stdout", data: log.data } : { stream: "stderr", data: log.data };
|
|
1662
|
+
if (log.stream === "stdout") {
|
|
1663
|
+
stdout += log.data;
|
|
1664
|
+
} else {
|
|
1665
|
+
stderr += log.data;
|
|
1666
|
+
}
|
|
1667
|
+
logBuffer.push(entry);
|
|
1668
|
+
state.resolve?.();
|
|
1669
|
+
}
|
|
1670
|
+
state.consumed = true;
|
|
1671
|
+
state.resolve?.();
|
|
1672
|
+
})();
|
|
1673
|
+
async function* logs() {
|
|
1674
|
+
let index = 0;
|
|
1675
|
+
while (!state.consumed || index < logBuffer.length) {
|
|
1676
|
+
if (index < logBuffer.length) {
|
|
1677
|
+
yield logBuffer[index++];
|
|
1678
|
+
} else {
|
|
1679
|
+
await new Promise((resolve) => {
|
|
1680
|
+
state.resolve = resolve;
|
|
1681
|
+
});
|
|
1682
|
+
state.resolve = null;
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
const result = consumeLogs.then(() => ({
|
|
1687
|
+
stdout,
|
|
1688
|
+
stderr,
|
|
1689
|
+
exitCode: output.exitCode
|
|
1690
|
+
}));
|
|
1691
|
+
return { commandId: output.cmdId, logs, result };
|
|
1692
|
+
},
|
|
1693
|
+
catch: (e) => new SandboxError({ reason: String(e), cause: e })
|
|
1694
|
+
});
|
|
1695
|
+
await updatePromise;
|
|
1696
|
+
return execResult;
|
|
1697
|
+
},
|
|
1698
|
+
getDomain: async (port) => {
|
|
1699
|
+
const sandbox2 = await getSandbox2();
|
|
1700
|
+
if (sandbox2 instanceof Error) {
|
|
1701
|
+
return sandbox2;
|
|
1702
|
+
}
|
|
1703
|
+
try {
|
|
1704
|
+
return sandbox2.domain(port);
|
|
1705
|
+
} catch (e) {
|
|
1706
|
+
return new SandboxError({ reason: String(e), cause: e });
|
|
1707
|
+
}
|
|
1708
|
+
},
|
|
1709
|
+
kill: async ({ commandId, storage: cmdStorage }) => {
|
|
1710
|
+
const instance = await getSandbox2();
|
|
1711
|
+
if (instance instanceof Error) {
|
|
1712
|
+
return instance;
|
|
1713
|
+
}
|
|
1714
|
+
const cmd = await cmdStorage.command.get(commandId);
|
|
1715
|
+
if (cmd instanceof Error) {
|
|
1716
|
+
return new SandboxError({ reason: cmd.message, cause: cmd });
|
|
1717
|
+
}
|
|
1718
|
+
if (cmd && cmd.status === "running") {
|
|
1719
|
+
const result = await cmdStorage.command.set({
|
|
1720
|
+
...cmd,
|
|
1721
|
+
status: "killed"
|
|
1722
|
+
});
|
|
1723
|
+
if (result instanceof Error) {
|
|
1724
|
+
return new SandboxError({ reason: result.message, cause: result });
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
return void 0;
|
|
1728
|
+
},
|
|
1729
|
+
writeFiles: (opts) => writeFiles({ sandbox, ...opts }),
|
|
1730
|
+
lifecycle
|
|
1731
|
+
};
|
|
1732
|
+
if (config.lifecycle?.autoStart !== false) {
|
|
1733
|
+
sandboxPromise = doGetSandbox();
|
|
1734
|
+
}
|
|
1735
|
+
return sandbox;
|
|
1736
|
+
};
|
|
1737
|
+
}
|
|
1738
|
+
});
|
|
1739
|
+
|
|
1740
|
+
// src/sandbox/client.ts
|
|
1741
|
+
function getSandbox({
|
|
1742
|
+
sandboxRecord,
|
|
1743
|
+
storageConfig
|
|
1744
|
+
}) {
|
|
1745
|
+
const { config } = sandboxRecord;
|
|
1746
|
+
switch (config.type) {
|
|
1747
|
+
case "local":
|
|
1748
|
+
return localSandbox({
|
|
1749
|
+
sandboxRecord,
|
|
1750
|
+
storageConfig
|
|
1751
|
+
});
|
|
1752
|
+
case "vercel":
|
|
1753
|
+
return vercelSandbox({
|
|
1754
|
+
sandboxRecord,
|
|
1755
|
+
storageConfig
|
|
1756
|
+
});
|
|
1757
|
+
case "custom":
|
|
1758
|
+
throw new Error("Custom sandboxes are not supported");
|
|
1759
|
+
default:
|
|
1760
|
+
config;
|
|
1761
|
+
throw new Error(
|
|
1762
|
+
`Unknown sandbox type: ${// biome-ignore lint/suspicious/noExplicitAny: .
|
|
1763
|
+
config.type}`
|
|
1764
|
+
);
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
var init_client2 = __esm({
|
|
1768
|
+
"src/sandbox/client.ts"() {
|
|
1769
|
+
"use strict";
|
|
1770
|
+
init_local2();
|
|
1771
|
+
init_vercel2();
|
|
1772
|
+
}
|
|
1773
|
+
});
|
|
1774
|
+
|
|
1775
|
+
// src/sandbox/index.ts
|
|
1776
|
+
var sandbox_exports = {};
|
|
1777
|
+
__export(sandbox_exports, {
|
|
1778
|
+
getSandbox: () => getSandbox
|
|
1779
|
+
});
|
|
1780
|
+
var init_sandbox = __esm({
|
|
1781
|
+
"src/sandbox/index.ts"() {
|
|
1782
|
+
"use strict";
|
|
1783
|
+
init_client2();
|
|
1784
|
+
}
|
|
1785
|
+
});
|
|
1786
|
+
|
|
1787
|
+
// src/index.ts
|
|
1788
|
+
var src_exports = {};
|
|
1789
|
+
__export(src_exports, {
|
|
1790
|
+
MessageNotFoundError: () => MessageNotFoundError,
|
|
1791
|
+
SandboxError: () => SandboxError,
|
|
1792
|
+
SandboxNotFoundError: () => SandboxNotFoundError,
|
|
1793
|
+
SessionNotFoundError: () => SessionNotFoundError,
|
|
1794
|
+
StorageError: () => StorageError,
|
|
1795
|
+
agent: () => agent,
|
|
1796
|
+
handleStorageRpc: () => handleStorageRpc,
|
|
1797
|
+
mcp: () => mcp
|
|
1798
|
+
});
|
|
1799
|
+
module.exports = __toCommonJS(src_exports);
|
|
1800
|
+
|
|
1801
|
+
// src/client.ts
|
|
1802
|
+
var import_better_all = require("better-all");
|
|
1803
|
+
var errore4 = __toESM(require("errore"));
|
|
1804
|
+
var import_fast_deep_equal = __toESM(require("fast-deep-equal"));
|
|
1805
|
+
var import_ulid3 = require("ulid");
|
|
1806
|
+
var import_api = require("workflow/api");
|
|
1807
|
+
|
|
1808
|
+
// src/agent-workflow.ts
|
|
1809
|
+
var import_workflow2 = require("workflow");
|
|
1810
|
+
|
|
1811
|
+
// src/agent-workflow-steps.ts
|
|
1812
|
+
var import_ai2 = require("ai");
|
|
1813
|
+
var import_ulid2 = require("ulid");
|
|
1814
|
+
var import_workflow = require("workflow");
|
|
1815
|
+
|
|
1816
|
+
// src/skills/parser.ts
|
|
1817
|
+
function parseSkillFrontmatter(content) {
|
|
1818
|
+
const trimmed = content.trim();
|
|
1819
|
+
if (!trimmed.startsWith("---")) {
|
|
1820
|
+
return null;
|
|
1821
|
+
}
|
|
1822
|
+
const endMarkerIndex = trimmed.indexOf("---", 3);
|
|
1823
|
+
if (endMarkerIndex === -1) {
|
|
1824
|
+
return null;
|
|
1825
|
+
}
|
|
1826
|
+
const frontmatterBlock = trimmed.slice(3, endMarkerIndex).trim();
|
|
1827
|
+
const parsed = parseSimpleYaml(frontmatterBlock);
|
|
1828
|
+
if (!(parsed.name && parsed.description)) {
|
|
1829
|
+
return null;
|
|
1830
|
+
}
|
|
1831
|
+
return {
|
|
1832
|
+
name: String(parsed.name),
|
|
1833
|
+
description: String(parsed.description)
|
|
1834
|
+
};
|
|
1835
|
+
}
|
|
1836
|
+
function parseSimpleYaml(yaml) {
|
|
1837
|
+
const result = {};
|
|
1838
|
+
for (const line of yaml.split("\n")) {
|
|
1839
|
+
const trimmedLine = line.trim();
|
|
1840
|
+
if (!trimmedLine || trimmedLine.startsWith("#")) {
|
|
1841
|
+
continue;
|
|
1842
|
+
}
|
|
1843
|
+
const colonIndex = trimmedLine.indexOf(":");
|
|
1844
|
+
if (colonIndex === -1) {
|
|
1845
|
+
continue;
|
|
1846
|
+
}
|
|
1847
|
+
const key = trimmedLine.slice(0, colonIndex).trim();
|
|
1848
|
+
let value = trimmedLine.slice(colonIndex + 1).trim();
|
|
1849
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
1850
|
+
value = value.slice(1, -1);
|
|
1851
|
+
}
|
|
1852
|
+
if (key) {
|
|
1853
|
+
result[key] = value;
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
return result;
|
|
1857
|
+
}
|
|
1858
|
+
function normalizeSkillsDirs(skillsDir) {
|
|
1859
|
+
if (!skillsDir) {
|
|
1860
|
+
return [];
|
|
1861
|
+
}
|
|
1862
|
+
return Array.isArray(skillsDir) ? skillsDir : [skillsDir];
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1865
|
+
// src/skills/discover.ts
|
|
1866
|
+
async function discoverSkillsInSandbox(opts) {
|
|
1867
|
+
const { sandbox, skillsDirs, debug } = opts;
|
|
1868
|
+
const summaries = [];
|
|
1869
|
+
const seenNames = /* @__PURE__ */ new Set();
|
|
1870
|
+
for (const skillsDir of skillsDirs) {
|
|
1871
|
+
const dirSummaries = await discoverSkillsInDirectory({
|
|
1872
|
+
sandbox,
|
|
1873
|
+
skillsDir,
|
|
1874
|
+
debug
|
|
1875
|
+
});
|
|
1876
|
+
for (const summary of dirSummaries) {
|
|
1877
|
+
if (!seenNames.has(summary.name)) {
|
|
1878
|
+
seenNames.add(summary.name);
|
|
1879
|
+
summaries.push(summary);
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
return summaries;
|
|
1884
|
+
}
|
|
1885
|
+
async function discoverSkillsInDirectory(opts) {
|
|
1886
|
+
const { sandbox, skillsDir, debug } = opts;
|
|
1887
|
+
const skillPaths = await findSkillFiles({ sandbox, skillsDir, debug });
|
|
1888
|
+
if (skillPaths.length === 0) {
|
|
1889
|
+
return [];
|
|
1890
|
+
}
|
|
1891
|
+
const summaries = [];
|
|
1892
|
+
for (const skillMdPath of skillPaths) {
|
|
1893
|
+
const summary = await parseSkillFile({ sandbox, skillMdPath, debug });
|
|
1894
|
+
if (summary) {
|
|
1895
|
+
summaries.push(summary);
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1898
|
+
return summaries;
|
|
1899
|
+
}
|
|
1900
|
+
async function findSkillFiles(opts) {
|
|
1901
|
+
const { sandbox, skillsDir, debug } = opts;
|
|
1902
|
+
if (debug) {
|
|
1903
|
+
console.log(`[discover] Finding skills in: ${skillsDir}`);
|
|
1904
|
+
}
|
|
1905
|
+
const execResult = await sandbox.exec({
|
|
1906
|
+
command: "find",
|
|
1907
|
+
args: [skillsDir, "-name", "SKILL.md", "-type", "f"]
|
|
1908
|
+
});
|
|
1909
|
+
if (execResult instanceof Error) {
|
|
1910
|
+
if (debug) {
|
|
1911
|
+
console.warn(
|
|
1912
|
+
`[discover] Failed to scan skills directory "${skillsDir}": ${execResult.message}`
|
|
1913
|
+
);
|
|
1914
|
+
}
|
|
1915
|
+
return [];
|
|
1916
|
+
}
|
|
1917
|
+
const { stdout, stderr, exitCode } = await execResult.result;
|
|
1918
|
+
if (debug) {
|
|
1919
|
+
console.log(
|
|
1920
|
+
`[discover] find result: exitCode=${exitCode}, stdout="${stdout.trim()}", stderr="${stderr.trim()}"`
|
|
1921
|
+
);
|
|
1922
|
+
}
|
|
1923
|
+
if (exitCode !== 0) {
|
|
1924
|
+
if (debug) {
|
|
1925
|
+
console.warn(
|
|
1926
|
+
`[discover] Skills directory not found or inaccessible: ${skillsDir}`
|
|
1927
|
+
);
|
|
1928
|
+
}
|
|
1929
|
+
return [];
|
|
1930
|
+
}
|
|
1931
|
+
const paths = stdout.trim().split("\n").filter((p) => p.length > 0);
|
|
1932
|
+
if (debug) {
|
|
1933
|
+
console.log("[discover] Found skill paths:", paths);
|
|
1934
|
+
}
|
|
1935
|
+
return paths;
|
|
1936
|
+
}
|
|
1937
|
+
async function parseSkillFile(opts) {
|
|
1938
|
+
const { sandbox, skillMdPath, debug } = opts;
|
|
1939
|
+
const execResult = await sandbox.exec({
|
|
1940
|
+
command: "cat",
|
|
1941
|
+
args: [skillMdPath]
|
|
1942
|
+
});
|
|
1943
|
+
if (execResult instanceof Error) {
|
|
1944
|
+
if (debug) {
|
|
1945
|
+
console.warn(
|
|
1946
|
+
`[discover] Failed to read skill file "${skillMdPath}": ${execResult.message}`
|
|
1947
|
+
);
|
|
1948
|
+
}
|
|
1949
|
+
return null;
|
|
1950
|
+
}
|
|
1951
|
+
const { stdout, exitCode } = await execResult.result;
|
|
1952
|
+
if (exitCode !== 0) {
|
|
1953
|
+
if (debug) {
|
|
1954
|
+
console.warn(`[discover] Could not read skill file: ${skillMdPath}`);
|
|
1955
|
+
}
|
|
1956
|
+
return null;
|
|
1957
|
+
}
|
|
1958
|
+
const parsed = parseSkillFrontmatter(stdout);
|
|
1959
|
+
if (!parsed) {
|
|
1960
|
+
if (debug) {
|
|
1961
|
+
console.warn(
|
|
1962
|
+
`[discover] Invalid or missing frontmatter in: ${skillMdPath}`
|
|
1963
|
+
);
|
|
1964
|
+
}
|
|
1965
|
+
return null;
|
|
1966
|
+
}
|
|
1967
|
+
return {
|
|
1968
|
+
name: parsed.name,
|
|
1969
|
+
description: parsed.description,
|
|
1970
|
+
skillMdPath
|
|
1971
|
+
};
|
|
1972
|
+
}
|
|
1973
|
+
|
|
1974
|
+
// src/tools/index.ts
|
|
1975
|
+
var import_ai = require("ai");
|
|
1976
|
+
var import_zod = require("zod");
|
|
1977
|
+
function getTools(context) {
|
|
1978
|
+
return {
|
|
1979
|
+
Read: (0, import_ai.tool)({
|
|
1980
|
+
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.",
|
|
1981
|
+
inputSchema: import_zod.z.object({
|
|
1982
|
+
path: import_zod.z.string().describe("Path to the file relative to workspace root"),
|
|
1983
|
+
startLine: import_zod.z.number().optional().describe(
|
|
1984
|
+
"Starting line number (1-indexed). If provided with endLine, reads exact range regardless of file size."
|
|
1985
|
+
),
|
|
1986
|
+
endLine: import_zod.z.number().optional().describe(
|
|
1987
|
+
"Ending line number (1-indexed, inclusive). If provided with startLine, reads exact range regardless of file size."
|
|
1988
|
+
)
|
|
1989
|
+
}),
|
|
1990
|
+
outputSchema: import_zod.z.object({
|
|
1991
|
+
content: import_zod.z.string().describe("File content"),
|
|
1992
|
+
metadata: import_zod.z.object({
|
|
1993
|
+
totalLines: import_zod.z.number().describe("Total number of lines in the file"),
|
|
1994
|
+
linesShown: import_zod.z.number().describe("Number of lines included in this response"),
|
|
1995
|
+
startLine: import_zod.z.number().describe("First line number shown (1-indexed)"),
|
|
1996
|
+
endLine: import_zod.z.number().describe("Last line number shown (1-indexed)"),
|
|
1997
|
+
isPaginated: import_zod.z.boolean().describe("Whether this is a partial view of the file"),
|
|
1998
|
+
fileSize: import_zod.z.string().describe("Human-readable file size (e.g., '2.5K', '1.2M')"),
|
|
1999
|
+
path: import_zod.z.string().describe("Path to the file relative to workspace root")
|
|
2000
|
+
})
|
|
2001
|
+
}),
|
|
2002
|
+
execute: async ({ path: path2, startLine, endLine }) => {
|
|
2003
|
+
const filePath = path2.startsWith("/") ? path2.slice(1) : path2;
|
|
2004
|
+
const result = await context.sandbox.exec({
|
|
2005
|
+
command: "bash",
|
|
2006
|
+
args: [
|
|
2007
|
+
"-c",
|
|
2008
|
+
`
|
|
2009
|
+
set -e
|
|
2010
|
+
FILE="$1"
|
|
2011
|
+
START_LINE="$2"
|
|
2012
|
+
END_LINE="$3"
|
|
2013
|
+
|
|
2014
|
+
# Resolve symlinks and check file exists
|
|
2015
|
+
if [ -L "$FILE" ]; then
|
|
2016
|
+
RESOLVED=$(readlink -f "$FILE" 2>/dev/null || echo "")
|
|
2017
|
+
if [ -z "$RESOLVED" ] || [ ! -e "$RESOLVED" ]; then
|
|
2018
|
+
echo "Error: Broken symlink - $FILE points to non-existent target" >&2
|
|
2019
|
+
exit 1
|
|
2020
|
+
fi
|
|
2021
|
+
FILE="$RESOLVED"
|
|
2022
|
+
elif [ ! -e "$FILE" ]; then
|
|
2023
|
+
echo "Error: File not found - $FILE" >&2
|
|
2024
|
+
exit 1
|
|
2025
|
+
fi
|
|
2026
|
+
|
|
2027
|
+
# Get metadata (count actual lines, not just newlines)
|
|
2028
|
+
TOTAL_LINES=$(awk 'END{print NR}' "$FILE")
|
|
2029
|
+
FILE_SIZE=$(ls -lh "$FILE" | awk '{print $5}')
|
|
2030
|
+
|
|
2031
|
+
# Determine range
|
|
2032
|
+
PAGE_SIZE=100
|
|
2033
|
+
if [ -n "$START_LINE" ] && [ -n "$END_LINE" ]; then
|
|
2034
|
+
# Both provided - use exact range
|
|
2035
|
+
ACTUAL_START=$START_LINE
|
|
2036
|
+
ACTUAL_END=$END_LINE
|
|
2037
|
+
elif [ -n "$START_LINE" ]; then
|
|
2038
|
+
# Only startLine - read PAGE_SIZE lines from there
|
|
2039
|
+
ACTUAL_START=$START_LINE
|
|
2040
|
+
ACTUAL_END=$((START_LINE + PAGE_SIZE - 1))
|
|
2041
|
+
[ "$ACTUAL_END" -gt "$TOTAL_LINES" ] && ACTUAL_END=$TOTAL_LINES
|
|
2042
|
+
elif [ -n "$END_LINE" ]; then
|
|
2043
|
+
# Only endLine - read from beginning to endLine
|
|
2044
|
+
ACTUAL_START=1
|
|
2045
|
+
ACTUAL_END=$END_LINE
|
|
2046
|
+
elif [ "$TOTAL_LINES" -gt 200 ]; then
|
|
2047
|
+
# No range, large file - paginate
|
|
2048
|
+
ACTUAL_START=1
|
|
2049
|
+
ACTUAL_END=$PAGE_SIZE
|
|
2050
|
+
else
|
|
2051
|
+
# No range, small file - show all
|
|
2052
|
+
ACTUAL_START=1
|
|
2053
|
+
ACTUAL_END=$TOTAL_LINES
|
|
2054
|
+
fi
|
|
2055
|
+
|
|
2056
|
+
# Output metadata first (separated by ||| for parsing)
|
|
2057
|
+
echo "$TOTAL_LINES|$FILE_SIZE|$ACTUAL_START|$ACTUAL_END"
|
|
2058
|
+
echo "|||CONTENT|||"
|
|
2059
|
+
|
|
2060
|
+
# Read content
|
|
2061
|
+
if [ "$ACTUAL_START" -eq 1 ] && [ "$ACTUAL_END" -eq "$TOTAL_LINES" ]; then
|
|
2062
|
+
cat "$FILE"
|
|
2063
|
+
else
|
|
2064
|
+
sed -n "\${ACTUAL_START},\${ACTUAL_END}p" "$FILE"
|
|
2065
|
+
fi
|
|
2066
|
+
`,
|
|
2067
|
+
"--",
|
|
2068
|
+
filePath,
|
|
2069
|
+
startLine?.toString() || "",
|
|
2070
|
+
endLine?.toString() || ""
|
|
2071
|
+
]
|
|
2072
|
+
});
|
|
2073
|
+
if (result instanceof Error) {
|
|
2074
|
+
console.error("[Read Tool]", result);
|
|
2075
|
+
throw result;
|
|
2076
|
+
}
|
|
2077
|
+
const { stdout, stderr } = await result.result;
|
|
2078
|
+
if (stderr) {
|
|
2079
|
+
console.error(`[Read Tool] Error: ${stderr}`);
|
|
2080
|
+
return {
|
|
2081
|
+
content: `Error: ${stderr}`,
|
|
2082
|
+
metadata: {
|
|
2083
|
+
totalLines: 0,
|
|
2084
|
+
linesShown: 0,
|
|
2085
|
+
startLine: 0,
|
|
2086
|
+
endLine: 0,
|
|
2087
|
+
isPaginated: false,
|
|
2088
|
+
fileSize: "0",
|
|
2089
|
+
path: filePath
|
|
2090
|
+
}
|
|
2091
|
+
};
|
|
2092
|
+
}
|
|
2093
|
+
const [metadataLine, ...rest] = stdout.split("|||CONTENT|||");
|
|
2094
|
+
const content = rest.join("|||CONTENT|||").trimStart();
|
|
2095
|
+
const [totalLinesStr, fileSize, actualStartStr, actualEndStr] = metadataLine.trim().split("|");
|
|
2096
|
+
const totalLines = Number.parseInt(totalLinesStr, 10);
|
|
2097
|
+
const actualStart = Number.parseInt(actualStartStr, 10);
|
|
2098
|
+
const actualEnd = Number.parseInt(actualEndStr, 10);
|
|
2099
|
+
if (Number.isNaN(totalLines) || Number.isNaN(actualStart) || Number.isNaN(actualEnd)) {
|
|
2100
|
+
console.error(
|
|
2101
|
+
`[Read Tool] Failed to parse metadata: ${metadataLine}`
|
|
2102
|
+
);
|
|
2103
|
+
return {
|
|
2104
|
+
content: `Error: Failed to parse file metadata. Raw output: ${stdout.slice(
|
|
2105
|
+
0,
|
|
2106
|
+
500
|
|
2107
|
+
)}`,
|
|
2108
|
+
metadata: {
|
|
2109
|
+
totalLines: 0,
|
|
2110
|
+
linesShown: 0,
|
|
2111
|
+
startLine: 0,
|
|
2112
|
+
endLine: 0,
|
|
2113
|
+
isPaginated: false,
|
|
2114
|
+
fileSize: "unknown",
|
|
2115
|
+
path: filePath
|
|
2116
|
+
}
|
|
2117
|
+
};
|
|
2118
|
+
}
|
|
2119
|
+
return {
|
|
2120
|
+
content,
|
|
2121
|
+
metadata: {
|
|
2122
|
+
totalLines,
|
|
2123
|
+
linesShown: Math.max(0, actualEnd - actualStart + 1),
|
|
2124
|
+
startLine: actualStart,
|
|
2125
|
+
endLine: actualEnd,
|
|
2126
|
+
isPaginated: actualEnd < totalLines,
|
|
2127
|
+
fileSize: fileSize || "unknown",
|
|
2128
|
+
path: filePath
|
|
2129
|
+
}
|
|
2130
|
+
};
|
|
2131
|
+
}
|
|
2132
|
+
}),
|
|
2133
|
+
Grep: (0, import_ai.tool)({
|
|
2134
|
+
description: "Search for patterns in files using ripgrep. Supports regex patterns, file type filtering, and context lines. Returns matching lines with file paths and line numbers. Use this to find code patterns, function definitions, imports, etc.",
|
|
2135
|
+
inputSchema: import_zod.z.object({
|
|
2136
|
+
pattern: import_zod.z.string().describe("Regex pattern to search for (ripgrep syntax)"),
|
|
2137
|
+
path: import_zod.z.string().optional().describe(
|
|
2138
|
+
"Path to search in (defaults to workspace root). Can be a file or directory."
|
|
2139
|
+
),
|
|
2140
|
+
fileType: import_zod.z.string().optional().describe(
|
|
2141
|
+
"File type to filter by (e.g., 'ts', 'js', 'py', 'md'). Uses ripgrep's built-in type filters."
|
|
2142
|
+
),
|
|
2143
|
+
glob: import_zod.z.string().optional().describe(
|
|
2144
|
+
"Glob pattern to filter files (e.g., '*.tsx', 'src/**/*.ts')"
|
|
2145
|
+
),
|
|
2146
|
+
caseSensitive: import_zod.z.boolean().optional().default(true).describe("Whether search is case-sensitive (default: true)"),
|
|
2147
|
+
contextLines: import_zod.z.number().optional().describe(
|
|
2148
|
+
"Number of context lines to show before and after each match"
|
|
2149
|
+
),
|
|
2150
|
+
maxCount: import_zod.z.number().optional().describe(
|
|
2151
|
+
"Maximum number of matches per file (useful for limiting output)"
|
|
2152
|
+
),
|
|
2153
|
+
filesWithMatches: import_zod.z.boolean().optional().default(false).describe(
|
|
2154
|
+
"Only show file paths that contain matches, not the matching lines themselves"
|
|
2155
|
+
)
|
|
2156
|
+
}),
|
|
2157
|
+
outputSchema: import_zod.z.object({
|
|
2158
|
+
matches: import_zod.z.string().describe(
|
|
2159
|
+
"Search results with file paths, line numbers, and matching content"
|
|
2160
|
+
),
|
|
2161
|
+
summary: import_zod.z.object({
|
|
2162
|
+
matchCount: import_zod.z.number().describe("Number of matches found"),
|
|
2163
|
+
fileCount: import_zod.z.number().describe("Number of files containing matches"),
|
|
2164
|
+
searchPath: import_zod.z.string().describe("Path that was searched"),
|
|
2165
|
+
pattern: import_zod.z.string().describe("Pattern that was searched for")
|
|
2166
|
+
})
|
|
2167
|
+
}),
|
|
2168
|
+
execute: async ({
|
|
2169
|
+
pattern,
|
|
2170
|
+
path: path2,
|
|
2171
|
+
fileType,
|
|
2172
|
+
glob,
|
|
2173
|
+
caseSensitive,
|
|
2174
|
+
contextLines,
|
|
2175
|
+
maxCount,
|
|
2176
|
+
filesWithMatches
|
|
2177
|
+
}) => {
|
|
2178
|
+
let searchPath = path2 ?? ".";
|
|
2179
|
+
if (searchPath.startsWith("/")) {
|
|
2180
|
+
searchPath = searchPath.slice(1);
|
|
2181
|
+
}
|
|
2182
|
+
const args = [];
|
|
2183
|
+
args.push("--line-number");
|
|
2184
|
+
args.push("--heading");
|
|
2185
|
+
args.push("--color", "never");
|
|
2186
|
+
if (!caseSensitive) {
|
|
2187
|
+
args.push("-i");
|
|
2188
|
+
}
|
|
2189
|
+
if (fileType) {
|
|
2190
|
+
args.push("--type", fileType);
|
|
2191
|
+
}
|
|
2192
|
+
if (glob) {
|
|
2193
|
+
args.push("--glob", glob);
|
|
2194
|
+
}
|
|
2195
|
+
if (contextLines !== void 0) {
|
|
2196
|
+
args.push("-C", String(contextLines));
|
|
2197
|
+
}
|
|
2198
|
+
if (maxCount !== void 0) {
|
|
2199
|
+
args.push("--max-count", String(maxCount));
|
|
2200
|
+
}
|
|
2201
|
+
if (filesWithMatches) {
|
|
2202
|
+
args.push("--files-with-matches");
|
|
2203
|
+
}
|
|
2204
|
+
args.push("--", pattern, searchPath);
|
|
2205
|
+
const result = await context.sandbox.exec({ command: "rg", args });
|
|
2206
|
+
if (result instanceof Error) {
|
|
2207
|
+
console.error("[Grep Tool]", result);
|
|
2208
|
+
throw result;
|
|
2209
|
+
}
|
|
2210
|
+
const { stdout, stderr } = await result.result;
|
|
2211
|
+
if (stderr && !stderr.toLowerCase().includes("no matches")) {
|
|
2212
|
+
console.error(`[Grep Tool] Warning: ${stderr}`);
|
|
2213
|
+
}
|
|
2214
|
+
const MAX_GREP_OUTPUT_CHARS = 5e4;
|
|
2215
|
+
let finalOutput = stdout;
|
|
2216
|
+
let wasTruncated = false;
|
|
2217
|
+
if (finalOutput.length > MAX_GREP_OUTPUT_CHARS) {
|
|
2218
|
+
finalOutput = finalOutput.slice(0, MAX_GREP_OUTPUT_CHARS) + "\n\n[Output truncated - use more specific pattern or path]";
|
|
2219
|
+
wasTruncated = true;
|
|
2220
|
+
}
|
|
2221
|
+
const lines = finalOutput.trim().split("\n").filter((l) => l.length > 0);
|
|
2222
|
+
const fileCount = filesWithMatches ? lines.length : new Set(
|
|
2223
|
+
lines.filter((l) => !l.startsWith(" ") && l.includes(":")).map((l) => l.split(":")[0])
|
|
2224
|
+
).size;
|
|
2225
|
+
return {
|
|
2226
|
+
matches: finalOutput || "(no matches found)",
|
|
2227
|
+
summary: {
|
|
2228
|
+
matchCount: filesWithMatches ? 0 : lines.filter((l) => l.includes(":")).length,
|
|
2229
|
+
fileCount,
|
|
2230
|
+
searchPath,
|
|
2231
|
+
pattern,
|
|
2232
|
+
wasTruncated
|
|
2233
|
+
}
|
|
2234
|
+
};
|
|
2235
|
+
}
|
|
2236
|
+
}),
|
|
2237
|
+
List: (0, import_ai.tool)({
|
|
2238
|
+
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.",
|
|
2239
|
+
inputSchema: import_zod.z.object({
|
|
2240
|
+
path: import_zod.z.string().optional().describe("Path to list (defaults to workspace root)"),
|
|
2241
|
+
depth: import_zod.z.number().optional().describe(
|
|
2242
|
+
"Maximum depth to traverse. Choose based on context: 1-2 for quick overview, 3-4 for detailed exploration, 5+ for comprehensive mapping"
|
|
2243
|
+
),
|
|
2244
|
+
includeHidden: import_zod.z.boolean().optional().default(false).describe(
|
|
2245
|
+
"Include hidden files and directories (those starting with '.')"
|
|
2246
|
+
),
|
|
2247
|
+
filesOnly: import_zod.z.boolean().optional().default(false).describe("Only show files, not directories"),
|
|
2248
|
+
pattern: import_zod.z.string().optional().describe("Glob pattern to filter results (e.g., '*.ts', '*test*')")
|
|
2249
|
+
}),
|
|
2250
|
+
outputSchema: import_zod.z.object({
|
|
2251
|
+
listing: import_zod.z.string().describe(
|
|
2252
|
+
"Directory tree listing showing paths relative to search root"
|
|
2253
|
+
),
|
|
2254
|
+
summary: import_zod.z.object({
|
|
2255
|
+
totalItems: import_zod.z.number().describe("Total number of items found"),
|
|
2256
|
+
totalFiles: import_zod.z.number().describe("Total number of files found"),
|
|
2257
|
+
totalDirs: import_zod.z.number().describe("Total number of directories found"),
|
|
2258
|
+
searchPath: import_zod.z.string().describe("Path that was listed"),
|
|
2259
|
+
depth: import_zod.z.number().optional().describe("Maximum depth used (if specified)")
|
|
2260
|
+
})
|
|
2261
|
+
}),
|
|
2262
|
+
execute: async ({ path: path2, depth, includeHidden, filesOnly, pattern }) => {
|
|
2263
|
+
const searchPath = path2 ?? ".";
|
|
2264
|
+
const result = await context.sandbox.exec({
|
|
2265
|
+
command: "bash",
|
|
2266
|
+
args: [
|
|
2267
|
+
"-c",
|
|
2268
|
+
`
|
|
2269
|
+
set -e
|
|
2270
|
+
SEARCH_PATH="$1"
|
|
2271
|
+
DEPTH="$2"
|
|
2272
|
+
INCLUDE_HIDDEN="$3"
|
|
2273
|
+
FILES_ONLY="$4"
|
|
2274
|
+
PATTERN="$5"
|
|
2275
|
+
|
|
2276
|
+
# Build find command arguments
|
|
2277
|
+
FIND_ARGS=""
|
|
2278
|
+
[ -n "$DEPTH" ] && FIND_ARGS="$FIND_ARGS -maxdepth $DEPTH"
|
|
2279
|
+
[ "$INCLUDE_HIDDEN" != "true" ] && FIND_ARGS="$FIND_ARGS ! -path '*/.*'"
|
|
2280
|
+
[ "$FILES_ONLY" = "true" ] && FIND_ARGS="$FIND_ARGS -type f"
|
|
2281
|
+
[ -n "$PATTERN" ] && FIND_ARGS="$FIND_ARGS -name '$PATTERN'"
|
|
2282
|
+
|
|
2283
|
+
# Get listing
|
|
2284
|
+
LISTING=$(eval "find '$SEARCH_PATH' $FIND_ARGS" 2>/dev/null | sort)
|
|
2285
|
+
|
|
2286
|
+
# Get counts
|
|
2287
|
+
COUNT_ARGS=""
|
|
2288
|
+
[ -n "$DEPTH" ] && COUNT_ARGS="$COUNT_ARGS -maxdepth $DEPTH"
|
|
2289
|
+
[ "$INCLUDE_HIDDEN" != "true" ] && COUNT_ARGS="$COUNT_ARGS ! -path '*/.*'"
|
|
2290
|
+
|
|
2291
|
+
FILE_COUNT=$(eval "find '$SEARCH_PATH' $COUNT_ARGS -type f" 2>/dev/null | wc -l)
|
|
2292
|
+
DIR_COUNT=$(eval "find '$SEARCH_PATH' $COUNT_ARGS -type d" 2>/dev/null | wc -l)
|
|
2293
|
+
|
|
2294
|
+
# Output: counts first, then listing
|
|
2295
|
+
echo "$FILE_COUNT|$DIR_COUNT"
|
|
2296
|
+
echo "|||LISTING|||"
|
|
2297
|
+
echo "$LISTING" | sed "s|^$SEARCH_PATH|.|"
|
|
2298
|
+
`,
|
|
2299
|
+
"--",
|
|
2300
|
+
searchPath,
|
|
2301
|
+
depth?.toString() || "",
|
|
2302
|
+
includeHidden ? "true" : "false",
|
|
2303
|
+
filesOnly ? "true" : "false",
|
|
2304
|
+
pattern || ""
|
|
2305
|
+
]
|
|
2306
|
+
});
|
|
2307
|
+
if (result instanceof Error) {
|
|
2308
|
+
console.error("[List Tool]", result);
|
|
2309
|
+
throw result;
|
|
2310
|
+
}
|
|
2311
|
+
const { stdout, stderr } = await result.result;
|
|
2312
|
+
if (stderr) {
|
|
2313
|
+
console.warn(`[List Tool] stderr: ${stderr}`);
|
|
2314
|
+
}
|
|
2315
|
+
const [countsLine, ...rest] = stdout.split("|||LISTING|||");
|
|
2316
|
+
const listing = rest.join("|||LISTING|||").trim();
|
|
2317
|
+
const [fileCountStr, dirCountStr] = countsLine.trim().split("|");
|
|
2318
|
+
const totalFiles = Number.parseInt(fileCountStr, 10) || 0;
|
|
2319
|
+
const totalDirs = Number.parseInt(dirCountStr, 10) || 0;
|
|
2320
|
+
const lines = listing.split("\n").filter((l) => l.length > 0);
|
|
2321
|
+
return {
|
|
2322
|
+
listing,
|
|
2323
|
+
summary: {
|
|
2324
|
+
totalItems: lines.length,
|
|
2325
|
+
totalFiles,
|
|
2326
|
+
totalDirs,
|
|
2327
|
+
searchPath,
|
|
2328
|
+
depth
|
|
2329
|
+
}
|
|
2330
|
+
};
|
|
2331
|
+
}
|
|
2332
|
+
}),
|
|
2333
|
+
Bash: (0, import_ai.tool)({
|
|
2334
|
+
description: "Executes a bash command inside the workspace. CWD persists between commands within a session. Use waitUntil:0 for background processes (dev servers).",
|
|
2335
|
+
inputSchema: import_zod.z.object({
|
|
2336
|
+
command: import_zod.z.string().describe("The shell command to execute"),
|
|
2337
|
+
waitUntil: import_zod.z.number().optional().describe(
|
|
2338
|
+
"Max ms to wait for completion (default: 30000). Use 0 to run in background and return immediately."
|
|
2339
|
+
)
|
|
2340
|
+
}),
|
|
2341
|
+
outputSchema: import_zod.z.object({
|
|
2342
|
+
pid: import_zod.z.number().describe(
|
|
2343
|
+
"System PID (0 for foreground, >0 for background - use to kill)"
|
|
2344
|
+
),
|
|
2345
|
+
output: import_zod.z.string().describe("Command stdout+stderr combined (empty for background)"),
|
|
2346
|
+
exitCode: import_zod.z.number().describe("Exit code (-1 for background/running)"),
|
|
2347
|
+
status: import_zod.z.enum(["running", "completed", "failed"]).describe("Process status"),
|
|
2348
|
+
cwd: import_zod.z.string().describe("Current working directory after command"),
|
|
2349
|
+
outputFile: import_zod.z.string().describe("Path to output log (for background processes)")
|
|
2350
|
+
}),
|
|
2351
|
+
execute: async ({ command, waitUntil }) => {
|
|
2352
|
+
const { createProcessManager: createProcessManager2 } = await Promise.resolve().then(() => (init_process_manager(), process_manager_exports));
|
|
2353
|
+
const processManager = createProcessManager2({
|
|
2354
|
+
sandbox: context.sandbox,
|
|
2355
|
+
sessionId: context.input.sessionId,
|
|
2356
|
+
generateId: () => crypto.randomUUID()
|
|
2357
|
+
});
|
|
2358
|
+
await processManager.init();
|
|
2359
|
+
return processManager.run({ command, waitUntil });
|
|
2360
|
+
}
|
|
2361
|
+
}),
|
|
2362
|
+
ExecuteMCPTool: (0, import_ai.tool)({
|
|
2363
|
+
description: "Execute a tool from an MCP server. Use this to call custom tools provided by the application.",
|
|
2364
|
+
inputSchema: import_zod.z.object({
|
|
2365
|
+
server: import_zod.z.string().describe("MCP server name"),
|
|
2366
|
+
tool: import_zod.z.string().describe("Tool name to execute"),
|
|
2367
|
+
input: import_zod.z.unknown().describe("Tool input matching the tool's schema")
|
|
2368
|
+
}),
|
|
2369
|
+
outputSchema: import_zod.z.object({
|
|
2370
|
+
result: import_zod.z.unknown().describe("Tool execution result"),
|
|
2371
|
+
truncated: import_zod.z.boolean().optional().describe("Whether the result was truncated due to size"),
|
|
2372
|
+
totalChars: import_zod.z.number().optional().describe("Total characters in full output (only if truncated)"),
|
|
2373
|
+
returnedChars: import_zod.z.number().optional().describe("Characters returned in this response (only if truncated)"),
|
|
2374
|
+
fullOutputPath: import_zod.z.string().optional().describe("Path to full output file if truncated")
|
|
2375
|
+
}),
|
|
2376
|
+
execute: async ({ server, tool: toolName, input }) => {
|
|
2377
|
+
const serverConfig = context.mcp?.find((s) => s.name === server);
|
|
2378
|
+
if (!serverConfig) {
|
|
2379
|
+
throw new Error(`Unknown MCP server: ${server}`);
|
|
2380
|
+
}
|
|
2381
|
+
const parsedInput = typeof input === "string" ? JSON.parse(input) : input;
|
|
2382
|
+
const timestamp = Date.now();
|
|
2383
|
+
const outputDir = `.agent/mcp/${server}/.outputs`;
|
|
2384
|
+
const outputFile = `${outputDir}/${timestamp}-${toolName}.txt`;
|
|
2385
|
+
const [res] = await Promise.all([
|
|
2386
|
+
fetch(serverConfig.url, {
|
|
2387
|
+
method: "POST",
|
|
2388
|
+
headers: { "Content-Type": "application/json" },
|
|
2389
|
+
body: JSON.stringify({
|
|
2390
|
+
server,
|
|
2391
|
+
tool: toolName,
|
|
2392
|
+
input: parsedInput,
|
|
2393
|
+
sessionId: context.input.sessionId,
|
|
2394
|
+
messageId: context.event.assistantMessageId,
|
|
2395
|
+
hookToken: context.event.hookToken
|
|
2396
|
+
})
|
|
2397
|
+
}),
|
|
2398
|
+
context.sandbox.exec({ command: "mkdir", args: ["-p", outputDir] })
|
|
2399
|
+
]);
|
|
2400
|
+
if (!res.ok) {
|
|
2401
|
+
const error = await res.text();
|
|
2402
|
+
throw new Error(`MCP tool call failed: ${error}`);
|
|
2403
|
+
}
|
|
2404
|
+
const json = await res.json();
|
|
2405
|
+
if (json.error) {
|
|
2406
|
+
throw new Error(`MCP tool call failed: ${json.error.message}`);
|
|
2407
|
+
}
|
|
2408
|
+
if (json.result === void 0) {
|
|
2409
|
+
throw new Error("MCP tool call failed: No result in response");
|
|
2410
|
+
}
|
|
2411
|
+
const result = json.result;
|
|
2412
|
+
const MAX_OUTPUT_CHARS = 24e3;
|
|
2413
|
+
const resultStr = JSON.stringify(result, null, 2);
|
|
2414
|
+
if (resultStr.length <= MAX_OUTPUT_CHARS) {
|
|
2415
|
+
return { result };
|
|
2416
|
+
}
|
|
2417
|
+
await context.sandbox.writeFiles({
|
|
2418
|
+
files: [{ path: `${timestamp}-${toolName}.txt`, content: resultStr }],
|
|
2419
|
+
destPath: outputDir
|
|
2420
|
+
});
|
|
2421
|
+
const truncatedResult = resultStr.slice(0, MAX_OUTPUT_CHARS) + `
|
|
2422
|
+
|
|
2423
|
+
[Output truncated at ~6k tokens. Full output saved to: ${outputFile}]`;
|
|
2424
|
+
return {
|
|
2425
|
+
result: truncatedResult,
|
|
2426
|
+
truncated: true,
|
|
2427
|
+
totalChars: resultStr.length,
|
|
2428
|
+
returnedChars: MAX_OUTPUT_CHARS,
|
|
2429
|
+
fullOutputPath: outputFile
|
|
2430
|
+
};
|
|
2431
|
+
}
|
|
2432
|
+
})
|
|
2433
|
+
};
|
|
2434
|
+
}
|
|
2435
|
+
|
|
2436
|
+
// src/utils/ui.ts
|
|
2437
|
+
function assembleUIMessages(opts) {
|
|
2438
|
+
const partsByMessage = /* @__PURE__ */ new Map();
|
|
2439
|
+
for (const part of opts.parts) {
|
|
2440
|
+
const existing = partsByMessage.get(part.messageId) ?? [];
|
|
2441
|
+
existing.push(part);
|
|
2442
|
+
partsByMessage.set(part.messageId, existing);
|
|
2443
|
+
}
|
|
2444
|
+
return opts.messages.map((m) => {
|
|
2445
|
+
const messageParts = partsByMessage.get(m.id) ?? [];
|
|
2446
|
+
messageParts.sort((a, b) => a.index - b.index);
|
|
2447
|
+
return {
|
|
2448
|
+
id: m.id,
|
|
2449
|
+
role: m.role,
|
|
2450
|
+
parts: messageParts.map((p) => p.part)
|
|
2451
|
+
};
|
|
2452
|
+
});
|
|
2453
|
+
}
|
|
2454
|
+
|
|
2455
|
+
// src/agent-workflow-steps.ts
|
|
2456
|
+
var BASE_SYSTEM_PROMPT = "You are an AI assistant with basic tools to interact with your environment. Explore and work freely.";
|
|
2457
|
+
function joinPromptSections(...sections) {
|
|
2458
|
+
return sections.filter((s) => s?.trim()).join("\n\n");
|
|
2459
|
+
}
|
|
2460
|
+
function buildSkillsContext(skills) {
|
|
2461
|
+
if (skills.length === 0) {
|
|
2462
|
+
return "";
|
|
2463
|
+
}
|
|
2464
|
+
const skillLines = skills.map((s) => `- ${s.name}: ${s.description}
|
|
2465
|
+
Path: ${s.skillMdPath}`).join("\n");
|
|
2466
|
+
return `## Available Skills
|
|
2467
|
+
${skillLines}
|
|
2468
|
+
|
|
2469
|
+
You can use the Read tool to read any skill's SKILL.md file to learn more about it.`;
|
|
2470
|
+
}
|
|
2471
|
+
function buildMcpToolsContext(mcp2) {
|
|
2472
|
+
if (!mcp2 || mcp2.length === 0) {
|
|
2473
|
+
return "";
|
|
2474
|
+
}
|
|
2475
|
+
const serverDocs = mcp2.filter(
|
|
2476
|
+
(s) => Array.isArray(s.tools) && s.tools.length > 0
|
|
2477
|
+
).map((server) => {
|
|
2478
|
+
const toolDocs = server.tools.map((t) => {
|
|
2479
|
+
let doc = ` - ${t.name}: ${t.description}
|
|
2480
|
+
Input: ${JSON.stringify(t.inputSchema)}`;
|
|
2481
|
+
if (t.outputSchema) {
|
|
2482
|
+
doc += `
|
|
2483
|
+
Output: ${JSON.stringify(t.outputSchema)}`;
|
|
2484
|
+
}
|
|
2485
|
+
return doc;
|
|
2486
|
+
}).join("\n");
|
|
2487
|
+
return `### ${server.name}
|
|
2488
|
+
${server.description ?? ""}
|
|
2489
|
+
${toolDocs}`;
|
|
2490
|
+
}).join("\n\n");
|
|
2491
|
+
if (!serverDocs) {
|
|
2492
|
+
return "";
|
|
2493
|
+
}
|
|
2494
|
+
return `## MCP Tools
|
|
2495
|
+
Use the ExecuteMCPTool to call these custom tools:
|
|
2496
|
+
|
|
2497
|
+
${serverDocs}`;
|
|
2498
|
+
}
|
|
2499
|
+
async function completeMessageStep({
|
|
2500
|
+
assistantMessageId,
|
|
2501
|
+
input,
|
|
2502
|
+
writable
|
|
2503
|
+
}) {
|
|
2504
|
+
"use step";
|
|
2505
|
+
const { getStorage: getStorage2 } = await Promise.resolve().then(() => (init_storage(), storage_exports));
|
|
2506
|
+
const storage = getStorage2(input.storageConfig);
|
|
2507
|
+
const message = await storage.message.get(assistantMessageId);
|
|
2508
|
+
if (message instanceof Error) {
|
|
2509
|
+
throw message;
|
|
2510
|
+
}
|
|
2511
|
+
if (!message) {
|
|
2512
|
+
throw new Error(`Message ${assistantMessageId} not found`);
|
|
2513
|
+
}
|
|
2514
|
+
const result = await storage.message.set({
|
|
2515
|
+
...message,
|
|
2516
|
+
completedAt: Date.now()
|
|
2517
|
+
});
|
|
2518
|
+
if (result instanceof Error) {
|
|
2519
|
+
throw result;
|
|
2520
|
+
}
|
|
2521
|
+
await writable.close();
|
|
2522
|
+
}
|
|
2523
|
+
async function streamTextStep({
|
|
2524
|
+
assistantMessageId,
|
|
2525
|
+
input,
|
|
2526
|
+
event,
|
|
2527
|
+
writable,
|
|
2528
|
+
lastPartIndex
|
|
2529
|
+
}) {
|
|
2530
|
+
"use step";
|
|
2531
|
+
const { getStorage: getStorage2 } = await Promise.resolve().then(() => (init_client(), client_exports));
|
|
2532
|
+
const { getSandbox: getSandbox2 } = await Promise.resolve().then(() => (init_sandbox(), sandbox_exports));
|
|
2533
|
+
const storage = getStorage2(input.storageConfig);
|
|
2534
|
+
const session = await storage.session.get(input.sessionId);
|
|
2535
|
+
if (session instanceof Error) {
|
|
2536
|
+
throw session;
|
|
2537
|
+
}
|
|
2538
|
+
session;
|
|
2539
|
+
const sandboxRecord = session.sandboxId ? await storage.sandbox.get(session.sandboxId) : null;
|
|
2540
|
+
if (sandboxRecord instanceof Error) {
|
|
2541
|
+
throw sandboxRecord;
|
|
2542
|
+
}
|
|
2543
|
+
if (!sandboxRecord) {
|
|
2544
|
+
throw new import_workflow.FatalError(`Sandbox not found for session ${input.sessionId}`);
|
|
2545
|
+
}
|
|
2546
|
+
const sandbox = getSandbox2({
|
|
2547
|
+
sandboxRecord,
|
|
2548
|
+
storageConfig: input.storageConfig
|
|
2549
|
+
});
|
|
2550
|
+
const [messagesResult, partsResult, skills] = await Promise.all([
|
|
2551
|
+
storage.message.list(input.sessionId),
|
|
2552
|
+
storage.part.listBySession(input.sessionId),
|
|
2553
|
+
session.skillsDir && session.skillsDir.length > 0 ? discoverSkillsInSandbox({ sandbox, skillsDirs: session.skillsDir }) : Promise.resolve([])
|
|
2554
|
+
]);
|
|
2555
|
+
if (messagesResult instanceof Error) {
|
|
2556
|
+
throw messagesResult;
|
|
2557
|
+
}
|
|
2558
|
+
if (partsResult instanceof Error) {
|
|
2559
|
+
throw partsResult;
|
|
2560
|
+
}
|
|
2561
|
+
const uiMessages = assembleUIMessages({
|
|
2562
|
+
messages: messagesResult.items,
|
|
2563
|
+
parts: partsResult.items
|
|
2564
|
+
});
|
|
2565
|
+
const mcp2 = session.mcp;
|
|
2566
|
+
const systemPrompt = joinPromptSections(
|
|
2567
|
+
BASE_SYSTEM_PROMPT,
|
|
2568
|
+
session.instructions,
|
|
2569
|
+
buildSkillsContext(skills),
|
|
2570
|
+
buildMcpToolsContext(mcp2)
|
|
2571
|
+
);
|
|
2572
|
+
if (!session.model) {
|
|
2573
|
+
throw new import_workflow.FatalError("Session model is not set");
|
|
2574
|
+
}
|
|
2575
|
+
const result = (0, import_ai2.streamText)({
|
|
2576
|
+
messages: await (0, import_ai2.convertToModelMessages)(uiMessages),
|
|
2577
|
+
tools: getTools({ input, event, mcp: mcp2, sandbox }),
|
|
2578
|
+
system: systemPrompt,
|
|
2579
|
+
model: session.model
|
|
2580
|
+
});
|
|
2581
|
+
const stepParts = [];
|
|
2582
|
+
await result.toUIMessageStream({
|
|
2583
|
+
generateMessageId: () => assistantMessageId,
|
|
2584
|
+
onFinish: ({ messages }) => {
|
|
2585
|
+
for (const m of messages) {
|
|
2586
|
+
if (m.role === "assistant") {
|
|
2587
|
+
stepParts.push(...m.parts);
|
|
2588
|
+
}
|
|
2589
|
+
}
|
|
2590
|
+
}
|
|
2591
|
+
}).pipeTo(writable, { preventClose: true });
|
|
2592
|
+
await Promise.all(
|
|
2593
|
+
stepParts.map(async (uiPart, index) => {
|
|
2594
|
+
const result2 = await storage.part.set({
|
|
2595
|
+
id: `part_${(0, import_ulid2.ulid)()}`,
|
|
2596
|
+
index: lastPartIndex + index,
|
|
2597
|
+
messageId: assistantMessageId,
|
|
2598
|
+
sessionId: input.sessionId,
|
|
2599
|
+
part: uiPart
|
|
2600
|
+
});
|
|
2601
|
+
if (result2 instanceof Error) {
|
|
2602
|
+
throw result2;
|
|
2603
|
+
}
|
|
2604
|
+
return result2;
|
|
2605
|
+
})
|
|
2606
|
+
);
|
|
2607
|
+
return {
|
|
2608
|
+
finishReason: await result.finishReason,
|
|
2609
|
+
lastPartIndex: lastPartIndex + stepParts.length
|
|
2610
|
+
};
|
|
2611
|
+
}
|
|
2612
|
+
|
|
2613
|
+
// src/agent-workflow.ts
|
|
2614
|
+
var agentMessageHook = (0, import_workflow2.defineHook)();
|
|
2615
|
+
async function agentWorkflow({
|
|
2616
|
+
input,
|
|
2617
|
+
event
|
|
2618
|
+
}) {
|
|
2619
|
+
"use workflow";
|
|
2620
|
+
const messageHook = agentMessageHook.create({ token: input.sessionId });
|
|
2621
|
+
const iterator = messageHook[Symbol.asyncIterator]();
|
|
2622
|
+
let pendingNext = iterator.next();
|
|
2623
|
+
await onMessage({ event, input }).catch((e) => {
|
|
2624
|
+
if (import_workflow2.FatalError.is(e)) {
|
|
2625
|
+
console.error("Message processing failed permanently:", e.message);
|
|
2626
|
+
return;
|
|
2627
|
+
}
|
|
2628
|
+
throw e;
|
|
2629
|
+
});
|
|
2630
|
+
while (true) {
|
|
2631
|
+
const result = await pendingNext;
|
|
2632
|
+
if (result.done) {
|
|
2633
|
+
console.error("Unexpected: message hook iterator done");
|
|
2634
|
+
break;
|
|
2635
|
+
}
|
|
2636
|
+
await onMessage({ event: result.value, input }).catch((e) => {
|
|
2637
|
+
if (import_workflow2.FatalError.is(e)) {
|
|
2638
|
+
console.error("Message processing failed permanently:", e.message);
|
|
2639
|
+
return;
|
|
2640
|
+
}
|
|
2641
|
+
throw e;
|
|
2642
|
+
});
|
|
2643
|
+
pendingNext = iterator.next();
|
|
2644
|
+
}
|
|
2645
|
+
}
|
|
2646
|
+
async function onMessage({
|
|
2647
|
+
event,
|
|
2648
|
+
input
|
|
2649
|
+
}) {
|
|
2650
|
+
const writable = (0, import_workflow2.getWritable)({ namespace: event.assistantMessageId });
|
|
2651
|
+
let finishReason;
|
|
2652
|
+
let lastPartIndex = 0;
|
|
2653
|
+
while (finishReason !== "stop") {
|
|
2654
|
+
try {
|
|
2655
|
+
const result = await streamTextStep({
|
|
2656
|
+
assistantMessageId: event.assistantMessageId,
|
|
2657
|
+
writable,
|
|
2658
|
+
input,
|
|
2659
|
+
event,
|
|
2660
|
+
lastPartIndex
|
|
2661
|
+
});
|
|
2662
|
+
finishReason = result.finishReason;
|
|
2663
|
+
lastPartIndex = result.lastPartIndex;
|
|
2664
|
+
} catch (err) {
|
|
2665
|
+
console.error(err);
|
|
2666
|
+
throw err;
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2669
|
+
await completeMessageStep({
|
|
2670
|
+
assistantMessageId: event.assistantMessageId,
|
|
2671
|
+
input,
|
|
2672
|
+
writable
|
|
2673
|
+
});
|
|
2674
|
+
}
|
|
2675
|
+
|
|
2676
|
+
// src/client.ts
|
|
2677
|
+
init_errors();
|
|
2678
|
+
|
|
2679
|
+
// src/mcp/index.ts
|
|
2680
|
+
var import_zod3 = require("zod");
|
|
2681
|
+
function serializeMcpConfig(mcp2) {
|
|
2682
|
+
return Object.entries(mcp2).map(([name, server]) => ({
|
|
2683
|
+
name,
|
|
2684
|
+
url: server.url,
|
|
2685
|
+
description: server.description,
|
|
2686
|
+
tools: Object.entries(server.tools).map(([toolName, tool2]) => ({
|
|
2687
|
+
name: toolName,
|
|
2688
|
+
description: tool2.description,
|
|
2689
|
+
inputSchema: import_zod3.z.toJSONSchema(tool2.inputSchema),
|
|
2690
|
+
outputSchema: tool2.outputSchema ? import_zod3.z.toJSONSchema(tool2.outputSchema) : void 0
|
|
2691
|
+
}))
|
|
2692
|
+
}));
|
|
2693
|
+
}
|
|
2694
|
+
function mcp(opts) {
|
|
2695
|
+
return opts;
|
|
2696
|
+
}
|
|
2697
|
+
|
|
2698
|
+
// src/client.ts
|
|
2699
|
+
init_sandbox();
|
|
2700
|
+
init_storage();
|
|
2701
|
+
|
|
2702
|
+
// src/utils/message.ts
|
|
2703
|
+
function toMessageAndParts({
|
|
2704
|
+
sessionId,
|
|
2705
|
+
id,
|
|
2706
|
+
input,
|
|
2707
|
+
generateId,
|
|
2708
|
+
defaultRole
|
|
2709
|
+
}) {
|
|
2710
|
+
const messageId = id ?? generateId("message");
|
|
2711
|
+
if (typeof input === "string") {
|
|
2712
|
+
return {
|
|
2713
|
+
message: {
|
|
2714
|
+
id: messageId,
|
|
2715
|
+
sessionId,
|
|
2716
|
+
role: defaultRole,
|
|
2717
|
+
createdAt: Date.now(),
|
|
2718
|
+
completedAt: Date.now(),
|
|
2719
|
+
mcpContext: null
|
|
2720
|
+
},
|
|
2721
|
+
parts: [
|
|
2722
|
+
{
|
|
2723
|
+
sessionId,
|
|
2724
|
+
messageId,
|
|
2725
|
+
id: generateId("part"),
|
|
2726
|
+
index: 0,
|
|
2727
|
+
part: { type: "text", text: input }
|
|
2728
|
+
}
|
|
2729
|
+
]
|
|
2730
|
+
};
|
|
2731
|
+
}
|
|
2732
|
+
return {
|
|
2733
|
+
message: {
|
|
2734
|
+
sessionId,
|
|
2735
|
+
id: messageId,
|
|
2736
|
+
createdAt: Date.now(),
|
|
2737
|
+
completedAt: Date.now(),
|
|
2738
|
+
mcpContext: null,
|
|
2739
|
+
role: input.role ?? defaultRole
|
|
2740
|
+
},
|
|
2741
|
+
parts: input.parts.map((part, index) => ({
|
|
2742
|
+
sessionId,
|
|
2743
|
+
messageId,
|
|
2744
|
+
id: generateId("part"),
|
|
2745
|
+
index,
|
|
2746
|
+
part
|
|
2747
|
+
}))
|
|
2748
|
+
};
|
|
2749
|
+
}
|
|
2750
|
+
|
|
2751
|
+
// src/client.ts
|
|
2752
|
+
var agent = (options) => {
|
|
2753
|
+
const storageConfig = options.storage ?? { type: "vercel" };
|
|
2754
|
+
const storage = getStorage(storageConfig);
|
|
2755
|
+
const generateId = options.generateId ?? ((resource) => `${resource}_${(0, import_ulid3.ulid)()}`);
|
|
2756
|
+
const sandbox = async (sandboxId, config) => {
|
|
2757
|
+
const existingRecord = await storage.sandbox.get(sandboxId);
|
|
2758
|
+
if (existingRecord instanceof Error) {
|
|
2759
|
+
if (!(existingRecord instanceof SandboxNotFoundError)) {
|
|
2760
|
+
throw existingRecord;
|
|
2761
|
+
}
|
|
2762
|
+
const sandboxRecord = await storage.sandbox.set({
|
|
2763
|
+
id: sandboxId,
|
|
2764
|
+
acquiringLockAt: null,
|
|
2765
|
+
acquiringLockId: null,
|
|
2766
|
+
createdAt: Date.now(),
|
|
2767
|
+
lastActivityAt: Date.now(),
|
|
2768
|
+
config: config ?? { type: "vercel" }
|
|
2769
|
+
});
|
|
2770
|
+
if (sandboxRecord instanceof Error) {
|
|
2771
|
+
throw sandboxRecord;
|
|
2772
|
+
}
|
|
2773
|
+
return getSandbox({ storageConfig, sandboxRecord });
|
|
2774
|
+
}
|
|
2775
|
+
const newConfig = config ?? existingRecord.config;
|
|
2776
|
+
if (!(0, import_fast_deep_equal.default)(existingRecord.config, newConfig)) {
|
|
2777
|
+
throw new SandboxError({
|
|
2778
|
+
reason: "sandbox config changes are not supported"
|
|
2779
|
+
});
|
|
2780
|
+
}
|
|
2781
|
+
return getSandbox({ storageConfig, sandboxRecord: existingRecord });
|
|
2782
|
+
};
|
|
2783
|
+
return {
|
|
2784
|
+
session: async (sessionId, sessionOptions) => {
|
|
2785
|
+
let session = await storage.session.get(sessionId);
|
|
2786
|
+
const sandboxInput = sessionOptions?.sandbox ?? options.sandbox;
|
|
2787
|
+
const sandboxId = typeof sandboxInput === "string" ? sandboxInput : (
|
|
2788
|
+
// biome-ignore lint/style/noNestedTernary: ok
|
|
2789
|
+
session instanceof Error ? generateId("sandbox") : session.sandboxId ?? generateId("sandbox")
|
|
2790
|
+
);
|
|
2791
|
+
const sandboxPromise = sandbox(
|
|
2792
|
+
sandboxId,
|
|
2793
|
+
typeof sandboxInput === "string" ? void 0 : sandboxInput
|
|
2794
|
+
);
|
|
2795
|
+
const mcpConfig = options.mcp || sessionOptions?.mcp ? { ...options.mcp, ...sessionOptions?.mcp } : null;
|
|
2796
|
+
const skillsDir = sessionOptions?.skillsDir ?? options.skillsDir ?? null;
|
|
2797
|
+
if (session instanceof Error) {
|
|
2798
|
+
if (session instanceof SessionNotFoundError) {
|
|
2799
|
+
const instructions = sessionOptions?.instructions ?? options.instructions ?? null;
|
|
2800
|
+
const model = sessionOptions?.model ?? options.model ?? null;
|
|
2801
|
+
if (!model) {
|
|
2802
|
+
throw new SessionError({
|
|
2803
|
+
id: sessionId,
|
|
2804
|
+
reason: "Model is not set"
|
|
2805
|
+
});
|
|
2806
|
+
}
|
|
2807
|
+
session = await storage.session.set({
|
|
2808
|
+
id: sessionId,
|
|
2809
|
+
createdAt: Date.now(),
|
|
2810
|
+
updatedAt: Date.now(),
|
|
2811
|
+
lastMessageId: null,
|
|
2812
|
+
runId: null,
|
|
2813
|
+
tags: sessionOptions?.tags ?? null,
|
|
2814
|
+
instructions,
|
|
2815
|
+
model,
|
|
2816
|
+
mcp: mcpConfig ? serializeMcpConfig(mcpConfig) : null,
|
|
2817
|
+
sandboxId,
|
|
2818
|
+
skillsDir: skillsDir ? normalizeSkillsDirs(skillsDir) : null,
|
|
2819
|
+
hookToken: null
|
|
2820
|
+
});
|
|
2821
|
+
} else {
|
|
2822
|
+
throw session;
|
|
2823
|
+
}
|
|
2824
|
+
} else {
|
|
2825
|
+
const updated = {
|
|
2826
|
+
...session,
|
|
2827
|
+
...sessionOptions,
|
|
2828
|
+
mcp: mcpConfig ? serializeMcpConfig(mcpConfig) : session.mcp,
|
|
2829
|
+
sandboxId,
|
|
2830
|
+
skillsDir: skillsDir ? normalizeSkillsDirs(skillsDir) : null
|
|
2831
|
+
};
|
|
2832
|
+
if (!(0, import_fast_deep_equal.default)(updated, session)) {
|
|
2833
|
+
session = await storage.session.set(updated);
|
|
2834
|
+
if (session instanceof Error) {
|
|
2835
|
+
throw session;
|
|
2836
|
+
}
|
|
2837
|
+
}
|
|
2838
|
+
}
|
|
2839
|
+
return {
|
|
2840
|
+
send: async ({
|
|
2841
|
+
input,
|
|
2842
|
+
mcpContext
|
|
2843
|
+
}) => {
|
|
2844
|
+
const newMessages = [];
|
|
2845
|
+
const newParts = [];
|
|
2846
|
+
if (Array.isArray(input)) {
|
|
2847
|
+
for (const i of input) {
|
|
2848
|
+
const { message, parts } = toMessageAndParts({
|
|
2849
|
+
sessionId,
|
|
2850
|
+
input: i,
|
|
2851
|
+
defaultRole: "user",
|
|
2852
|
+
generateId: () => generateId("message")
|
|
2853
|
+
});
|
|
2854
|
+
newMessages.push(message);
|
|
2855
|
+
newParts.push(...parts);
|
|
2856
|
+
}
|
|
2857
|
+
} else {
|
|
2858
|
+
const { message, parts } = toMessageAndParts({
|
|
2859
|
+
sessionId,
|
|
2860
|
+
input,
|
|
2861
|
+
defaultRole: "user",
|
|
2862
|
+
generateId: () => generateId("message")
|
|
2863
|
+
});
|
|
2864
|
+
newMessages.push(message);
|
|
2865
|
+
newParts.push(...parts);
|
|
2866
|
+
}
|
|
2867
|
+
const assistantMessageId = generateId("message");
|
|
2868
|
+
newMessages.push({
|
|
2869
|
+
id: assistantMessageId,
|
|
2870
|
+
sessionId,
|
|
2871
|
+
role: "assistant",
|
|
2872
|
+
createdAt: Date.now(),
|
|
2873
|
+
completedAt: null,
|
|
2874
|
+
mcpContext
|
|
2875
|
+
});
|
|
2876
|
+
const now = Date.now();
|
|
2877
|
+
const session2 = await storage.session.get(sessionId);
|
|
2878
|
+
if (session2 instanceof Error) {
|
|
2879
|
+
throw session2;
|
|
2880
|
+
}
|
|
2881
|
+
const agentInput = {
|
|
2882
|
+
storageConfig,
|
|
2883
|
+
sessionId
|
|
2884
|
+
};
|
|
2885
|
+
const event = {
|
|
2886
|
+
assistantMessageId,
|
|
2887
|
+
hookToken: crypto.randomUUID()
|
|
2888
|
+
};
|
|
2889
|
+
return await errore4.tryAsync({
|
|
2890
|
+
try: async () => {
|
|
2891
|
+
await (0, import_better_all.all)({
|
|
2892
|
+
async saveMessages() {
|
|
2893
|
+
await Promise.all(newMessages.map(storage.message.set));
|
|
2894
|
+
},
|
|
2895
|
+
async saveParts() {
|
|
2896
|
+
await Promise.all(newParts.map(storage.part.set));
|
|
2897
|
+
},
|
|
2898
|
+
async resumeOrStartAgentWorkflow() {
|
|
2899
|
+
if (session2.runId) {
|
|
2900
|
+
await agentMessageHook.resume(sessionId, event);
|
|
2901
|
+
} else {
|
|
2902
|
+
const startResult = await (0, import_api.start)(agentWorkflow, [
|
|
2903
|
+
{ input: agentInput, event }
|
|
2904
|
+
]);
|
|
2905
|
+
session2.runId = startResult.runId;
|
|
2906
|
+
}
|
|
2907
|
+
},
|
|
2908
|
+
async updateSession() {
|
|
2909
|
+
await this.$.resumeOrStartAgentWorkflow;
|
|
2910
|
+
const result = await storage.session.set({
|
|
2911
|
+
...session2,
|
|
2912
|
+
updatedAt: now,
|
|
2913
|
+
lastMessageId: assistantMessageId,
|
|
2914
|
+
hookToken: event.hookToken
|
|
2915
|
+
});
|
|
2916
|
+
if (result instanceof Error) {
|
|
2917
|
+
throw result;
|
|
2918
|
+
}
|
|
2919
|
+
return result;
|
|
2920
|
+
}
|
|
2921
|
+
});
|
|
2922
|
+
},
|
|
2923
|
+
catch: (e) => {
|
|
2924
|
+
if (e instanceof Error) {
|
|
2925
|
+
throw e;
|
|
2926
|
+
}
|
|
2927
|
+
return new SessionError({
|
|
2928
|
+
id: sessionId,
|
|
2929
|
+
reason: `failed to send: ${String(e)}`,
|
|
2930
|
+
cause: e
|
|
2931
|
+
});
|
|
2932
|
+
}
|
|
2933
|
+
});
|
|
2934
|
+
},
|
|
2935
|
+
stream: async (opts) => {
|
|
2936
|
+
const session2 = await storage.session.get(sessionId);
|
|
2937
|
+
if (session2 instanceof Error) {
|
|
2938
|
+
return session2;
|
|
2939
|
+
}
|
|
2940
|
+
const messageId = opts?.messageId ?? session2.lastMessageId;
|
|
2941
|
+
if (!messageId) {
|
|
2942
|
+
return new SessionError({
|
|
2943
|
+
id: sessionId,
|
|
2944
|
+
reason: "No message associated with session"
|
|
2945
|
+
});
|
|
2946
|
+
}
|
|
2947
|
+
if (!session2.runId) {
|
|
2948
|
+
return new SessionError({
|
|
2949
|
+
id: sessionId,
|
|
2950
|
+
reason: "No run associated with session"
|
|
2951
|
+
});
|
|
2952
|
+
}
|
|
2953
|
+
const run = (0, import_api.getRun)(session2.runId);
|
|
2954
|
+
return run.getReadable({ namespace: messageId });
|
|
2955
|
+
},
|
|
2956
|
+
ui: async () => {
|
|
2957
|
+
const [messagesResult, partsResult] = await Promise.all([
|
|
2958
|
+
storage.message.list(sessionId),
|
|
2959
|
+
storage.part.listBySession(sessionId)
|
|
2960
|
+
]);
|
|
2961
|
+
if (messagesResult instanceof Error) {
|
|
2962
|
+
return messagesResult;
|
|
2963
|
+
}
|
|
2964
|
+
if (partsResult instanceof Error) {
|
|
2965
|
+
return partsResult;
|
|
2966
|
+
}
|
|
2967
|
+
const messages = assembleUIMessages({
|
|
2968
|
+
messages: messagesResult.items,
|
|
2969
|
+
parts: partsResult.items
|
|
2970
|
+
});
|
|
2971
|
+
const lastMessage = messagesResult.items.at(-1);
|
|
2972
|
+
const isStreaming = lastMessage?.role === "assistant" && lastMessage.completedAt === null;
|
|
2973
|
+
const streamingMessageId = isStreaming ? lastMessage.id : null;
|
|
2974
|
+
return { messages, streamingMessageId };
|
|
2975
|
+
},
|
|
2976
|
+
tag: {
|
|
2977
|
+
list: async () => {
|
|
2978
|
+
const session2 = await storage.session.get(sessionId);
|
|
2979
|
+
if (session2 instanceof Error) {
|
|
2980
|
+
return session2;
|
|
2981
|
+
}
|
|
2982
|
+
return session2.tags ?? {};
|
|
2983
|
+
},
|
|
2984
|
+
get: async (key) => {
|
|
2985
|
+
const session2 = await storage.session.get(sessionId);
|
|
2986
|
+
if (session2 instanceof Error) {
|
|
2987
|
+
return session2;
|
|
2988
|
+
}
|
|
2989
|
+
return session2.tags?.[key];
|
|
2990
|
+
},
|
|
2991
|
+
set: async (key, value) => {
|
|
2992
|
+
const result = await storage.session.tag.set({
|
|
2993
|
+
sessionId,
|
|
2994
|
+
tags: { [key]: value }
|
|
2995
|
+
});
|
|
2996
|
+
if (result instanceof Error) {
|
|
2997
|
+
return result;
|
|
2998
|
+
}
|
|
2999
|
+
return void 0;
|
|
3000
|
+
},
|
|
3001
|
+
setMany: async (tags) => {
|
|
3002
|
+
const result = await storage.session.tag.set({
|
|
3003
|
+
sessionId,
|
|
3004
|
+
tags
|
|
3005
|
+
});
|
|
3006
|
+
if (result instanceof Error) {
|
|
3007
|
+
return result;
|
|
3008
|
+
}
|
|
3009
|
+
return void 0;
|
|
3010
|
+
}
|
|
3011
|
+
},
|
|
3012
|
+
sandbox: await sandboxPromise
|
|
3013
|
+
};
|
|
3014
|
+
},
|
|
3015
|
+
sandbox,
|
|
3016
|
+
storage,
|
|
3017
|
+
handleMcpToolCall: async (body, handlers) => {
|
|
3018
|
+
const { server, tool: tool2, input, sessionId, messageId, hookToken } = body;
|
|
3019
|
+
const handlerKey = `${server}/${tool2}`;
|
|
3020
|
+
const handler = handlers[handlerKey];
|
|
3021
|
+
if (!handler) {
|
|
3022
|
+
return {
|
|
3023
|
+
error: {
|
|
3024
|
+
code: "HANDLER_NOT_FOUND",
|
|
3025
|
+
message: `No handler for ${handlerKey}`
|
|
3026
|
+
}
|
|
3027
|
+
};
|
|
3028
|
+
}
|
|
3029
|
+
const session = await storage.session.get(sessionId);
|
|
3030
|
+
if (session instanceof Error) {
|
|
3031
|
+
return {
|
|
3032
|
+
error: { code: "SESSION_NOT_FOUND", message: "Session not found" }
|
|
3033
|
+
};
|
|
3034
|
+
}
|
|
3035
|
+
if (!session.hookToken || session.hookToken !== hookToken) {
|
|
3036
|
+
return {
|
|
3037
|
+
error: { code: "INVALID_TOKEN", message: "Invalid hook token" }
|
|
3038
|
+
};
|
|
3039
|
+
}
|
|
3040
|
+
const message = await storage.message.get(messageId);
|
|
3041
|
+
if (message instanceof Error) {
|
|
3042
|
+
return {
|
|
3043
|
+
error: { code: "MESSAGE_NOT_FOUND", message: "Message not found" }
|
|
3044
|
+
};
|
|
3045
|
+
}
|
|
3046
|
+
const mcpContext = message.mcpContext;
|
|
3047
|
+
const serverContext = mcpContext?.[server];
|
|
3048
|
+
const headers = serverContext?.headers ?? {};
|
|
3049
|
+
try {
|
|
3050
|
+
const result = await handler({ input, headers, body });
|
|
3051
|
+
return { result };
|
|
3052
|
+
} catch (e) {
|
|
3053
|
+
return {
|
|
3054
|
+
error: {
|
|
3055
|
+
code: "EXECUTION_ERROR",
|
|
3056
|
+
message: e instanceof Error ? e.message : String(e)
|
|
3057
|
+
}
|
|
3058
|
+
};
|
|
3059
|
+
}
|
|
3060
|
+
}
|
|
3061
|
+
};
|
|
3062
|
+
};
|
|
3063
|
+
|
|
3064
|
+
// src/index.ts
|
|
3065
|
+
init_errors();
|
|
3066
|
+
init_storage();
|
|
3067
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
3068
|
+
0 && (module.exports = {
|
|
3069
|
+
MessageNotFoundError,
|
|
3070
|
+
SandboxError,
|
|
3071
|
+
SandboxNotFoundError,
|
|
3072
|
+
SessionNotFoundError,
|
|
3073
|
+
StorageError,
|
|
3074
|
+
agent,
|
|
3075
|
+
handleStorageRpc,
|
|
3076
|
+
mcp
|
|
3077
|
+
});
|
|
3078
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL3NhbmRib3gvcHJvY2Vzcy1tYW5hZ2VyLnRzIiwgIi4uL3NyYy9lcnJvcnMudHMiLCAiLi4vc3JjL3V0aWxzL3BhZ2luYXRlLnRzIiwgIi4uL3NyYy9zdG9yYWdlL2JpbmRpbmdzL2xvY2FsLWZzLWhhbmRsZXJzLnRzIiwgIi4uL3NyYy9zdG9yYWdlL2JpbmRpbmdzL2xvY2FsLnRzIiwgIi4uL3NyYy9zdG9yYWdlL2JpbmRpbmdzL3ZlcmNlbC50cyIsICIuLi9zcmMvc3RvcmFnZS9jbGllbnQudHMiLCAiLi4vc3JjL3N0b3JhZ2UvcnBjLnRzIiwgIi4uL3NyYy9zdG9yYWdlL2hhbmRsZXIudHMiLCAiLi4vc3JjL3N0b3JhZ2UvaW5kZXgudHMiLCAiLi4vc3JjL3NhbmRib3gvd3JpdGUtZmlsZXMudHMiLCAiLi4vc3JjL3NhbmRib3gvYmluZGluZ3MvbG9jYWwudHMiLCAiLi4vc3JjL3NhbmRib3gvYmluZGluZ3MvdmVyY2VsLnRzIiwgIi4uL3NyYy9zYW5kYm94L2NsaWVudC50cyIsICIuLi9zcmMvc2FuZGJveC9pbmRleC50cyIsICIuLi9zcmMvaW5kZXgudHMiLCAiLi4vc3JjL2NsaWVudC50cyIsICIuLi9zcmMvYWdlbnQtd29ya2Zsb3cudHMiLCAiLi4vc3JjL2FnZW50LXdvcmtmbG93LXN0ZXBzLnRzIiwgIi4uL3NyYy9za2lsbHMvcGFyc2VyLnRzIiwgIi4uL3NyYy9za2lsbHMvZGlzY292ZXIudHMiLCAiLi4vc3JjL3Rvb2xzL2luZGV4LnRzIiwgIi4uL3NyYy91dGlscy91aS50cyIsICIuLi9zcmMvbWNwL2luZGV4LnRzIiwgIi4uL3NyYy91dGlscy9tZXNzYWdlLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJpbXBvcnQgdHlwZSB7IEJhc2hSZXN1bHQsIFNhbmRib3ggfSBmcm9tIFwiLi90eXBlc1wiO1xuXG5jb25zdCBERUZBVUxUX1dBSVRfVU5USUwgPSAzMDAwMDtcblxuLyoqXG4gKiBTaGVsbCBzY3JpcHQgdGhhdCBoYW5kbGVzIGFsbCBwcm9jZXNzIGV4ZWN1dGlvbiBsb2dpYy5cbiAqIEluc3RhbGxlZCB0byB+Ly5hZ2VudC9iaW4vcnVuLnNoIGR1cmluZyBpbml0KCkuXG4gKi9cbmNvbnN0IFJVTl9TQ1JJUFQgPSBgIyEvYmluL3NoXG4jIFByb2Nlc3MgcnVubmVyIGZvciBBZ2VudCBTREtcbiMgQWxsIHBhcmFtZXRlcnMgcGFzc2VkIHZpYSBlbnZpcm9ubWVudCB2YXJpYWJsZXMgdG8gYXZvaWQgZXNjYXBpbmcgaXNzdWVzXG4jIE91dHB1dCBpcyBiYXNlNjQgZW5jb2RlZCB0byBhdm9pZCBKU09OIGVzY2FwaW5nIGlzc3Vlc1xuXG5BR0VOVF9ESVI9XCIkSE9NRS8uYWdlbnRcIlxuQ1dEX0ZJTEU9XCIkQUdFTlRfRElSL2N3ZC8kU0VTU0lPTl9JRFwiXG5cbiMgR2V0IGN1cnJlbnQgd29ya2luZyBkaXJlY3RvcnkgKHBlci1zZXNzaW9uKVxuaWYgWyAtZiBcIiRDV0RfRklMRVwiIF07IHRoZW5cbiAgQ1dEPSQoY2F0IFwiJENXRF9GSUxFXCIpXG5lbHNlXG4gIENXRD1cIiRIT01FXCJcbmZpXG5cbiMgRGVjb2RlIGNvbW1hbmRcbkNNRD0kKGVjaG8gXCIkQ01EX0JBU0U2NFwiIHwgYmFzZTY0IC1kKVxuXG4jIEJhY2tncm91bmQgbW9kZSAod2FpdFVudGlsID0gMClcbmlmIFsgXCIkV0FJVF9VTlRJTFwiID0gXCIwXCIgXTsgdGhlblxuICBjZCBcIiRDV0RcIiB8fCBjZCBcIiRIT01FXCJcblxuICAjIEdlbmVyYXRlIGEgc2ltcGxlIG51bWVyaWMgSUQgZm9yIG91dHB1dCBmaWxlXG4gIE9VVFBVVF9JRD1cIiQoZGF0ZSArJXMpJCRcIlxuICBPVVRQVVRfRklMRT1cIiRBR0VOVF9ESVIvb3V0cHV0cy8kT1VUUFVUX0lELmxvZ1wiXG5cbiAgIyBEb3VibGUtZm9yayB0byBmdWxseSBkZXRhY2ggdGhlIHByb2Nlc3NcbiAgKFxuICAgIChcbiAgICAgIGV2YWwgXCIkQ01EXCJcbiAgICAgIHB3ZCA+IFwiJENXRF9GSUxFXCIgMj4vZGV2L251bGxcbiAgICApID4gXCIkT1VUUFVUX0ZJTEVcIiAyPiYxIDwgL2Rldi9udWxsICZcbiAgICBlY2hvICQhID4gXCIkQUdFTlRfRElSL3BpZHMvJE9VVFBVVF9JRC5waWRcIlxuICApXG5cbiAgIyBTbWFsbCBkZWxheSB0byBlbnN1cmUgUElEIGZpbGUgaXMgd3JpdHRlblxuICBzbGVlcCAwLjA1XG5cbiAgIyBSZWFkIFBJRFxuICBpZiBbIC1mIFwiJEFHRU5UX0RJUi9waWRzLyRPVVRQVVRfSUQucGlkXCIgXTsgdGhlblxuICAgIFBJRD0kKGNhdCBcIiRBR0VOVF9ESVIvcGlkcy8kT1VUUFVUX0lELnBpZFwiKVxuICBlbHNlXG4gICAgUElEPTBcbiAgZmlcblxuICAjIE91dHB1dCBKU09OIHJlc3VsdCAobm8gb3V0cHV0IGZvciBiYWNrZ3JvdW5kLCBzbyBubyBlbmNvZGluZyBuZWVkZWQpXG4gIHByaW50ZiAne1wicGlkXCI6JWQsXCJvdXRwdXRCYXNlNjRcIjpcIlwiLFwiZXhpdENvZGVcIjotMSxcInN0YXR1c1wiOlwicnVubmluZ1wiLFwib3V0cHV0RmlsZVwiOlwiJXNcIixcImN3ZFwiOlwiJXNcIn1cXFxcbicgXFxcXFxuICAgIFwiJFBJRFwiIFwiJE9VVFBVVF9GSUxFXCIgXCIkQ1dEXCJcbiAgZXhpdCAwXG5maVxuXG4jIEZvcmVncm91bmQgbW9kZSAod2FpdFVudGlsID4gMCkgLSBydW4gZGlyZWN0bHkgYW5kIGNhcHR1cmUgb3V0cHV0XG5jZCBcIiRDV0RcIiB8fCBjZCBcIiRIT01FXCJcblxuIyBSdW4gY29tbWFuZCwgY2FwdHVyZSBvdXRwdXQgYW5kIGV4aXQgY29kZVxuT1VUUFVUPSQoZXZhbCBcIiRDTURcIiAyPiYxKVxuRVhJVF9DT0RFPSQ/XG5cbiMgVXBkYXRlIENXRCBhZnRlciBjb21tYW5kXG5ORVdfQ1dEPSQocHdkKVxuZWNobyBcIiRORVdfQ1dEXCIgPiBcIiRDV0RfRklMRVwiXG5cbiMgRGV0ZXJtaW5lIHN0YXR1c1xuaWYgWyAkRVhJVF9DT0RFIC1lcSAwIF07IHRoZW5cbiAgU1RBVFVTPVwiY29tcGxldGVkXCJcbmVsc2VcbiAgU1RBVFVTPVwiZmFpbGVkXCJcbmZpXG5cbiMgQmFzZTY0IGVuY29kZSBvdXRwdXQgdG8gYXZvaWQgQUxMIGVzY2FwaW5nIGlzc3Vlc1xuT1VUUFVUX0JBU0U2ND0kKHByaW50ZiAnJXMnIFwiJE9VVFBVVFwiIHwgYmFzZTY0IHwgdHIgLWQgJ1xcXFxuJylcblxuIyBPdXRwdXQgSlNPTiByZXN1bHQgd2l0aCBiYXNlNjQtZW5jb2RlZCBvdXRwdXRcbnByaW50ZiAne1wicGlkXCI6MCxcIm91dHB1dEJhc2U2NFwiOlwiJXNcIixcImV4aXRDb2RlXCI6JWQsXCJzdGF0dXNcIjpcIiVzXCIsXCJvdXRwdXRGaWxlXCI6XCJcIixcImN3ZFwiOlwiJXNcIn1cXFxcbicgXFxcXFxuICBcIiRPVVRQVVRfQkFTRTY0XCIgXCIkRVhJVF9DT0RFXCIgXCIkU1RBVFVTXCIgXCIkTkVXX0NXRFwiXG5gO1xuXG50eXBlIFJ1bk9wdGlvbnMgPSB7XG4gIGNvbW1hbmQ6IHN0cmluZztcbiAgLyoqXG4gICAqIE1heCBtcyB0byB3YWl0IGZvciBjb21wbGV0aW9uLlxuICAgKiAtIDA6IEJhY2tncm91bmQgbW9kZSAtIHJldHVybiBpbW1lZGlhdGVseSB3aXRoIFBJRFxuICAgKiAtID4wOiBGb3JlZ3JvdW5kIG1vZGUgLSB3YWl0IGZvciBjb21wbGV0aW9uIChkZWZhdWx0OiAzMDAwMClcbiAgICovXG4gIHdhaXRVbnRpbD86IG51bWJlcjtcbn07XG5cbi8qKlxuICogUHJvY2VzcyBtYW5hZ2VyIHRoYXQgdXNlcyBhIHNpbmdsZSBzaGVsbCBzY3JpcHQgdG8gaGFuZGxlIGFsbCBleGVjdXRpb24gbG9naWMuXG4gKiBSZWR1Y2VzIHJvdW5kLXRyaXBzIHRvIHRoZSBzYW5kYm94IGJ5IGRvaW5nIGV2ZXJ5dGhpbmcgaW4gb25lIGV4ZWMgY2FsbC5cbiAqL1xuZXhwb3J0IGNvbnN0IGNyZWF0ZVByb2Nlc3NNYW5hZ2VyID0gKG9wdHM6IHtcbiAgc2FuZGJveDogU2FuZGJveDtcbiAgc2Vzc2lvbklkOiBzdHJpbmc7XG4gIGdlbmVyYXRlSWQ6ICgpID0+IHN0cmluZztcbn0pID0+IHtcbiAgY29uc3QgeyBzYW5kYm94LCBzZXNzaW9uSWQgfSA9IG9wdHM7XG4gIGxldCBpbml0aWFsaXplZCA9IGZhbHNlO1xuXG4gIGNvbnN0IGluaXQgPSBhc3luYyAoKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgaWYgKGluaXRpYWxpemVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc2FuZGJveC5leGVjKHtcbiAgICAgIGNvbW1hbmQ6IFwic2hcIixcbiAgICAgIGFyZ3M6IFtcbiAgICAgICAgXCItY1wiLFxuICAgICAgICBgbWtkaXIgLXAgJEhPTUUvLmFnZW50L2JpbiAkSE9NRS8uYWdlbnQvcGlkcyAkSE9NRS8uYWdlbnQvb3V0cHV0cyAkSE9NRS8uYWdlbnQvY3dkXG5jYXQgPiAkSE9NRS8uYWdlbnQvYmluL3J1bi5zaCA8PCAnU0NSSVBUX0VPRidcbiR7UlVOX1NDUklQVH1cblNDUklQVF9FT0ZcbmNobW9kICt4ICRIT01FLy5hZ2VudC9iaW4vcnVuLnNoYCxcbiAgICAgIF0sXG4gICAgfSk7XG5cbiAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIHRocm93IHJlc3VsdDtcbiAgICB9XG4gICAgYXdhaXQgcmVzdWx0LnJlc3VsdDtcbiAgICBpbml0aWFsaXplZCA9IHRydWU7XG4gIH07XG5cbiAgY29uc3QgcnVuID0gYXN5bmMgKG9wdHM6IFJ1bk9wdGlvbnMpOiBQcm9taXNlPEJhc2hSZXN1bHQ+ID0+IHtcbiAgICBhd2FpdCBpbml0KCk7XG5cbiAgICBjb25zdCB7IGNvbW1hbmQsIHdhaXRVbnRpbCA9IERFRkFVTFRfV0FJVF9VTlRJTCB9ID0gb3B0cztcbiAgICBjb25zdCBjbWRCYXNlNjQgPSBCdWZmZXIuZnJvbShjb21tYW5kLCBcInV0Zi04XCIpLnRvU3RyaW5nKFwiYmFzZTY0XCIpO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc2FuZGJveC5leGVjKHtcbiAgICAgIGNvbW1hbmQ6IFwic2hcIixcbiAgICAgIGFyZ3M6IFtcbiAgICAgICAgXCItY1wiLFxuICAgICAgICBgQ01EX0JBU0U2ND1cIiR7Y21kQmFzZTY0fVwiIFdBSVRfVU5USUw9XCIke3dhaXRVbnRpbH1cIiBTRVNTSU9OX0lEPVwiJHtzZXNzaW9uSWR9XCIgJEhPTUUvLmFnZW50L2Jpbi9ydW4uc2hgLFxuICAgICAgXSxcbiAgICB9KTtcblxuICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgdGhyb3cgcmVzdWx0O1xuICAgIH1cblxuICAgIGNvbnN0IHsgc3Rkb3V0IH0gPSBhd2FpdCByZXN1bHQucmVzdWx0O1xuICAgIGNvbnN0IHBhcnNlZCA9IEpTT04ucGFyc2Uoc3Rkb3V0LnRyaW0oKSkgYXMge1xuICAgICAgcGlkOiBudW1iZXI7XG4gICAgICBvdXRwdXRCYXNlNjQ6IHN0cmluZztcbiAgICAgIGV4aXRDb2RlOiBudW1iZXI7XG4gICAgICBzdGF0dXM6IFwicnVubmluZ1wiIHwgXCJjb21wbGV0ZWRcIiB8IFwiZmFpbGVkXCI7XG4gICAgICBvdXRwdXRGaWxlOiBzdHJpbmc7XG4gICAgICBjd2Q6IHN0cmluZztcbiAgICB9O1xuXG4gICAgLy8gRGVjb2RlIGJhc2U2NCBvdXRwdXRcbiAgICBjb25zdCBvdXRwdXQgPSBwYXJzZWQub3V0cHV0QmFzZTY0XG4gICAgICA/IEJ1ZmZlci5mcm9tKHBhcnNlZC5vdXRwdXRCYXNlNjQsIFwiYmFzZTY0XCIpLnRvU3RyaW5nKFwidXRmLThcIilcbiAgICAgIDogXCJcIjtcblxuICAgIHJldHVybiB7XG4gICAgICBwaWQ6IHBhcnNlZC5waWQsXG4gICAgICBvdXRwdXQsXG4gICAgICBleGl0Q29kZTogcGFyc2VkLmV4aXRDb2RlLFxuICAgICAgc3RhdHVzOiBwYXJzZWQuc3RhdHVzLFxuICAgICAgY3dkOiBwYXJzZWQuY3dkLFxuICAgICAgb3V0cHV0RmlsZTogcGFyc2VkLm91dHB1dEZpbGUsXG4gICAgfTtcbiAgfTtcblxuICBjb25zdCBnZXRDd2QgPSBhc3luYyAoKTogUHJvbWlzZTxzdHJpbmc+ID0+IHtcbiAgICBhd2FpdCBpbml0KCk7XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzYW5kYm94LmV4ZWMoe1xuICAgICAgY29tbWFuZDogXCJzaFwiLFxuICAgICAgYXJnczogW1xuICAgICAgICBcIi1jXCIsXG4gICAgICAgIGBjYXQgJEhPTUUvLmFnZW50L2N3ZC8ke3Nlc3Npb25JZH0gMj4vZGV2L251bGwgfHwgZWNobyBcIiRIT01FXCJgLFxuICAgICAgXSxcbiAgICB9KTtcblxuICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuY3dkKCk7XG4gICAgfVxuXG4gICAgY29uc3QgeyBzdGRvdXQgfSA9IGF3YWl0IHJlc3VsdC5yZXN1bHQ7XG4gICAgcmV0dXJuIHN0ZG91dC50cmltKCkgfHwgcHJvY2Vzcy5jd2QoKTtcbiAgfTtcblxuICByZXR1cm4ge1xuICAgIGluaXQsXG4gICAgcnVuLFxuICAgIGdldEN3ZCxcbiAgfTtcbn07XG5cbmV4cG9ydCB0eXBlIFByb2Nlc3NNYW5hZ2VyID0gUmV0dXJuVHlwZTx0eXBlb2YgY3JlYXRlUHJvY2Vzc01hbmFnZXI+O1xuIiwgImltcG9ydCAqIGFzIGVycm9yZSBmcm9tIFwiZXJyb3JlXCI7XG5cbmV4cG9ydCBjbGFzcyBTZXNzaW9uTm90Rm91bmRFcnJvciBleHRlbmRzIGVycm9yZS5jcmVhdGVUYWdnZWRFcnJvcih7XG4gIG5hbWU6IFwiU2Vzc2lvbk5vdEZvdW5kRXJyb3JcIixcbiAgbWVzc2FnZTogXCJTZXNzaW9uICRpZCBub3QgZm91bmRcIixcbn0pIHt9XG5cbmV4cG9ydCBjbGFzcyBTZXNzaW9uRXJyb3IgZXh0ZW5kcyBlcnJvcmUuY3JlYXRlVGFnZ2VkRXJyb3Ioe1xuICBuYW1lOiBcIlNlc3Npb25FcnJvclwiLFxuICBtZXNzYWdlOiBcIlNlc3Npb24gJGlkIGZhaWxlZDogJHJlYXNvblwiLFxufSkge31cblxuZXhwb3J0IGNsYXNzIFNhbmRib3hOb3RGb3VuZEVycm9yIGV4dGVuZHMgZXJyb3JlLmNyZWF0ZVRhZ2dlZEVycm9yKHtcbiAgbmFtZTogXCJTYW5kYm94Tm90Rm91bmRFcnJvclwiLFxuICBtZXNzYWdlOiBcIlNhbmRib3ggJGlkIG5vdCBmb3VuZFwiLFxufSkge31cblxuZXhwb3J0IGNsYXNzIFN0b3JhZ2VFcnJvciBleHRlbmRzIGVycm9yZS5jcmVhdGVUYWdnZWRFcnJvcih7XG4gIG5hbWU6IFwiU3RvcmFnZUVycm9yXCIsXG4gIG1lc3NhZ2U6IFwiJHJlYXNvblwiLFxufSkge31cblxuZXhwb3J0IGNsYXNzIFNhbmRib3hFcnJvciBleHRlbmRzIGVycm9yZS5jcmVhdGVUYWdnZWRFcnJvcih7XG4gIG5hbWU6IFwiU2FuZGJveEVycm9yXCIsXG4gIG1lc3NhZ2U6IFwiJHJlYXNvblwiLFxufSkge31cblxuZXhwb3J0IGNsYXNzIE1lc3NhZ2VOb3RGb3VuZEVycm9yIGV4dGVuZHMgZXJyb3JlLmNyZWF0ZVRhZ2dlZEVycm9yKHtcbiAgbmFtZTogXCJNZXNzYWdlTm90Rm91bmRFcnJvclwiLFxuICBtZXNzYWdlOiBcIk1lc3NhZ2UgJGlkIG5vdCBmb3VuZFwiLFxufSkge31cbiIsICJpbXBvcnQgdHlwZSB7IExpc3RSZXN1bHQgfSBmcm9tIFwiLi4vc3RvcmFnZVwiO1xuXG5leHBvcnQgZnVuY3Rpb24gcGFnaW5hdGU8VCBleHRlbmRzIHsgaWQ6IHN0cmluZyB9PihvcHRzOiB7XG4gIGl0ZW1zOiBUW107XG4gIGN1cnNvcj86IHN0cmluZztcbiAgbGltaXQ/OiBudW1iZXI7XG59KTogTGlzdFJlc3VsdDxUPiB7XG4gIGNvbnN0IHsgaXRlbXMsIGN1cnNvciwgbGltaXQgPSA1MCB9ID0gb3B0cztcbiAgY29uc3Qgc3RhcnRJbmRleCA9IGN1cnNvciA/IGl0ZW1zLmZpbmRJbmRleCgobSkgPT4gbS5pZCA9PT0gY3Vyc29yKSArIDEgOiAwO1xuICBjb25zdCBzbGljZWQgPSBpdGVtcy5zbGljZShzdGFydEluZGV4LCBzdGFydEluZGV4ICsgbGltaXQpO1xuICBjb25zdCBuZXh0Q3Vyc29yID1cbiAgICBzdGFydEluZGV4ICsgbGltaXQgPCBpdGVtcy5sZW5ndGggPyAoc2xpY2VkLmF0KC0xKT8uaWQgPz8gbnVsbCkgOiBudWxsO1xuICByZXR1cm4geyBpdGVtczogc2xpY2VkLCBuZXh0Q3Vyc29yIH07XG59XG4iLCAiaW1wb3J0IHsgbWtkaXIsIHJlYWRkaXIsIHJlYWRGaWxlLCB3cml0ZUZpbGUgfSBmcm9tIFwibm9kZTpmcy9wcm9taXNlc1wiO1xuaW1wb3J0IHsgZGlybmFtZSwgam9pbiB9IGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCB7IHBhZ2luYXRlIH0gZnJvbSBcIi4uLy4uL3V0aWxzL3BhZ2luYXRlXCI7XG5pbXBvcnQgdHlwZSB7XG4gIENvbW1hbmQsXG4gIEhhbmRsZXJzLFxuICBNZXNzYWdlLFxuICBQYXJ0LFxuICBTYW5kYm94UmVjb3JkLFxuICBTZXNzaW9uLFxufSBmcm9tIFwiLi5cIjtcblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUZpbGVzeXN0ZW1IYW5kbGVycyhiYXNlUGF0aDogc3RyaW5nKTogSGFuZGxlcnMge1xuICBjb25zdCBzZXNzaW9uRGlyID0gam9pbihiYXNlUGF0aCwgXCJzZXNzaW9uXCIpO1xuICBjb25zdCBtZXNzYWdlRGlyID0gam9pbihiYXNlUGF0aCwgXCJtZXNzYWdlXCIpO1xuICBjb25zdCBwYXJ0RGlyID0gam9pbihiYXNlUGF0aCwgXCJwYXJ0XCIpO1xuICBjb25zdCBzYW5kYm94RGlyID0gam9pbihiYXNlUGF0aCwgXCJzYW5kYm94XCIpO1xuICBjb25zdCBjb21tYW5kRGlyID0gam9pbihiYXNlUGF0aCwgXCJjb21tYW5kXCIpO1xuXG4gIGFzeW5jIGZ1bmN0aW9uIGVuc3VyZURpcihkaXI6IHN0cmluZykge1xuICAgIGF3YWl0IG1rZGlyKGRpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiByZWFkSnNvbjxUPihmaWxlUGF0aDogc3RyaW5nKTogUHJvbWlzZTxUIHwgbnVsbD4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBjb250ZW50ID0gYXdhaXQgcmVhZEZpbGUoZmlsZVBhdGgsIFwidXRmLThcIik7XG4gICAgICByZXR1cm4gSlNPTi5wYXJzZShjb250ZW50KSBhcyBUO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gd3JpdGVKc29uRmlsZShmaWxlUGF0aDogc3RyaW5nLCBkYXRhOiB1bmtub3duKSB7XG4gICAgYXdhaXQgZW5zdXJlRGlyKGRpcm5hbWUoZmlsZVBhdGgpKTtcbiAgICBhd2FpdCB3cml0ZUZpbGUoZmlsZVBhdGgsIEpTT04uc3RyaW5naWZ5KGRhdGEsIG51bGwsIDIpKTtcbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIHJlYWRBbGxGcm9tRGlyPFQ+KGRpcjogc3RyaW5nKTogUHJvbWlzZTxUW10+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgZmlsZXMgPSBhd2FpdCByZWFkZGlyKGRpcik7XG4gICAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgIGZpbGVzXG4gICAgICAgICAgLmZpbHRlcigoZikgPT4gZi5lbmRzV2l0aChcIi5qc29uXCIpKVxuICAgICAgICAgIC5tYXAoKGYpID0+IHJlYWRKc29uPFQ+KGpvaW4oZGlyLCBmKSkpXG4gICAgICApO1xuICAgICAgcmV0dXJuIHJlc3VsdHMuZmlsdGVyKChyKTogciBpcyBOb25OdWxsYWJsZTx0eXBlb2Ygcj4gPT4gciAhPT0gbnVsbCk7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBcInNlc3Npb24uZ2V0XCI6IGFzeW5jICh7IGlkIH0pID0+IHtcbiAgICAgIGNvbnN0IHNlc3Npb24gPSBhd2FpdCByZWFkSnNvbjxTZXNzaW9uPihqb2luKHNlc3Npb25EaXIsIGAke2lkfS5qc29uYCkpO1xuICAgICAgcmV0dXJuIHNlc3Npb24gPz8gbnVsbDtcbiAgICB9LFxuXG4gICAgXCJzZXNzaW9uLnNldFwiOiBhc3luYyAoc2Vzc2lvbikgPT4ge1xuICAgICAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgIGNvbnN0IHNlc3Npb25QYXRoID0gam9pbihzZXNzaW9uRGlyLCBgJHtzZXNzaW9uLmlkfS5qc29uYCk7XG4gICAgICBjb25zdCBleGlzdGluZyA9IGF3YWl0IHJlYWRKc29uPFNlc3Npb24+KHNlc3Npb25QYXRoKTtcbiAgICAgIGNvbnN0IG5ld1Nlc3Npb246IFNlc3Npb24gPSB7XG4gICAgICAgIC4uLnNlc3Npb24sXG4gICAgICAgIHRhZ3M6IHNlc3Npb24udGFncyA/PyBleGlzdGluZz8udGFncyA/PyB7fSxcbiAgICAgICAgY3JlYXRlZEF0OiBleGlzdGluZz8uY3JlYXRlZEF0ID8/IHNlc3Npb24uY3JlYXRlZEF0ID8/IG5vdyxcbiAgICAgICAgdXBkYXRlZEF0OiBub3csXG4gICAgICB9O1xuICAgICAgYXdhaXQgd3JpdGVKc29uRmlsZShzZXNzaW9uUGF0aCwgbmV3U2Vzc2lvbik7XG4gICAgICByZXR1cm4gbmV3U2Vzc2lvbjtcbiAgICB9LFxuXG4gICAgXCJzZXNzaW9uLmxpc3RcIjogYXN5bmMgKHsgdGFncywgY3Vyc29yLCBsaW1pdCB9KSA9PiB7XG4gICAgICBjb25zdCBhbGxTZXNzaW9ucyA9IGF3YWl0IHJlYWRBbGxGcm9tRGlyPFNlc3Npb24+KHNlc3Npb25EaXIpO1xuICAgICAgbGV0IGZpbHRlcmVkID0gYWxsU2Vzc2lvbnM7XG4gICAgICBpZiAodGFncyAmJiBPYmplY3Qua2V5cyh0YWdzKS5sZW5ndGggPiAwKSB7XG4gICAgICAgIGZpbHRlcmVkID0gZmlsdGVyZWQuZmlsdGVyKChzKSA9PiB7XG4gICAgICAgICAgY29uc3Qgc2Vzc2lvblRhZ3MgPSBzLnRhZ3MgPz8ge307XG4gICAgICAgICAgcmV0dXJuIE9iamVjdC5lbnRyaWVzKHRhZ3MpLmV2ZXJ5KFxuICAgICAgICAgICAgKFtrZXksIHZhbHVlXSkgPT4gc2Vzc2lvblRhZ3Nba2V5XSA9PT0gdmFsdWVcbiAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIGZpbHRlcmVkLnNvcnQoKGEsIGIpID0+IGEuY3JlYXRlZEF0IC0gYi5jcmVhdGVkQXQpO1xuICAgICAgcmV0dXJuIHBhZ2luYXRlKHsgaXRlbXM6IGZpbHRlcmVkLCBjdXJzb3IsIGxpbWl0IH0pO1xuICAgIH0sXG5cbiAgICBcInNlc3Npb24ubGlzdEJ5U2FuZGJveFwiOiBhc3luYyAoeyBzYW5kYm94SWQsIHRhZ3MsIGN1cnNvciwgbGltaXQgfSkgPT4ge1xuICAgICAgY29uc3QgYWxsU2Vzc2lvbnMgPSBhd2FpdCByZWFkQWxsRnJvbURpcjxTZXNzaW9uPihzZXNzaW9uRGlyKTtcbiAgICAgIGxldCBmaWx0ZXJlZCA9IGFsbFNlc3Npb25zLmZpbHRlcigocykgPT4gcy5zYW5kYm94SWQgPT09IHNhbmRib3hJZCk7XG4gICAgICBpZiAodGFncyAmJiBPYmplY3Qua2V5cyh0YWdzKS5sZW5ndGggPiAwKSB7XG4gICAgICAgIGZpbHRlcmVkID0gZmlsdGVyZWQuZmlsdGVyKChzKSA9PiB7XG4gICAgICAgICAgY29uc3Qgc2Vzc2lvblRhZ3MgPSBzLnRhZ3MgPz8ge307XG4gICAgICAgICAgcmV0dXJuIE9iamVjdC5lbnRyaWVzKHRhZ3MpLmV2ZXJ5KFxuICAgICAgICAgICAgKFtrZXksIHZhbHVlXSkgPT4gc2Vzc2lvblRhZ3Nba2V5XSA9PT0gdmFsdWVcbiAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIGZpbHRlcmVkLnNvcnQoKGEsIGIpID0+IGEuY3JlYXRlZEF0IC0gYi5jcmVhdGVkQXQpO1xuICAgICAgcmV0dXJuIHBhZ2luYXRlKHsgaXRlbXM6IGZpbHRlcmVkLCBjdXJzb3IsIGxpbWl0IH0pO1xuICAgIH0sXG5cbiAgICBcInNlc3Npb24udGFnLnNldFwiOiBhc3luYyAoeyBzZXNzaW9uSWQsIHRhZ3MgfSkgPT4ge1xuICAgICAgY29uc3Qgc2Vzc2lvblBhdGggPSBqb2luKHNlc3Npb25EaXIsIGAke3Nlc3Npb25JZH0uanNvbmApO1xuICAgICAgY29uc3QgZXhpc3RpbmcgPSBhd2FpdCByZWFkSnNvbjxTZXNzaW9uPihzZXNzaW9uUGF0aCk7XG4gICAgICBpZiAoIWV4aXN0aW5nKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgU2Vzc2lvbiAke3Nlc3Npb25JZH0gbm90IGZvdW5kYCk7XG4gICAgICB9XG4gICAgICBjb25zdCBtZXJnZWRUYWdzID0geyAuLi5leGlzdGluZy50YWdzLCAuLi50YWdzIH07XG4gICAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgY29uc3QgdXBkYXRlZFNlc3Npb246IFNlc3Npb24gPSB7XG4gICAgICAgIC4uLmV4aXN0aW5nLFxuICAgICAgICB0YWdzOiBtZXJnZWRUYWdzLFxuICAgICAgICB1cGRhdGVkQXQ6IG5vdyxcbiAgICAgIH07XG4gICAgICBhd2FpdCB3cml0ZUpzb25GaWxlKHNlc3Npb25QYXRoLCB1cGRhdGVkU2Vzc2lvbik7XG4gICAgICByZXR1cm4gdXBkYXRlZFNlc3Npb247XG4gICAgfSxcblxuICAgIFwibWVzc2FnZS5nZXRcIjogYXN5bmMgKHsgaWQgfSkgPT4ge1xuICAgICAgcmV0dXJuIGF3YWl0IHJlYWRKc29uPE1lc3NhZ2U+KGpvaW4obWVzc2FnZURpciwgYCR7aWR9Lmpzb25gKSk7XG4gICAgfSxcblxuICAgIFwibWVzc2FnZS5zZXRcIjogYXN5bmMgKG1lc3NhZ2UpID0+IHtcbiAgICAgIGF3YWl0IHdyaXRlSnNvbkZpbGUoam9pbihtZXNzYWdlRGlyLCBgJHttZXNzYWdlLmlkfS5qc29uYCksIG1lc3NhZ2UpO1xuICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgfSxcblxuICAgIFwibWVzc2FnZS5saXN0XCI6IGFzeW5jICh7IHNlc3Npb25JZCwgY3Vyc29yLCBsaW1pdCB9KSA9PiB7XG4gICAgICBjb25zdCBhbGxNZXNzYWdlcyA9IGF3YWl0IHJlYWRBbGxGcm9tRGlyPE1lc3NhZ2U+KG1lc3NhZ2VEaXIpO1xuICAgICAgY29uc3QgZmlsdGVyZWQgPSBhbGxNZXNzYWdlc1xuICAgICAgICAuZmlsdGVyKChtKSA9PiBtLnNlc3Npb25JZCA9PT0gc2Vzc2lvbklkKVxuICAgICAgICAuc29ydCgoYSwgYikgPT4gYS5jcmVhdGVkQXQgLSBiLmNyZWF0ZWRBdCk7XG4gICAgICByZXR1cm4gcGFnaW5hdGUoeyBpdGVtczogZmlsdGVyZWQsIGN1cnNvciwgbGltaXQgfSk7XG4gICAgfSxcblxuICAgIFwicGFydC5saXN0QnlNZXNzYWdlXCI6IGFzeW5jICh7IG1lc3NhZ2VJZCwgY3Vyc29yLCBsaW1pdCB9KSA9PiB7XG4gICAgICBjb25zdCBhbGxQYXJ0cyA9IGF3YWl0IHJlYWRBbGxGcm9tRGlyPFBhcnQ+KHBhcnREaXIpO1xuICAgICAgY29uc3QgZmlsdGVyZWQgPSBhbGxQYXJ0c1xuICAgICAgICAuZmlsdGVyKChwKSA9PiBwLm1lc3NhZ2VJZCA9PT0gbWVzc2FnZUlkKVxuICAgICAgICAuc29ydCgoYSwgYikgPT4gYS5pbmRleCAtIGIuaW5kZXgpO1xuICAgICAgcmV0dXJuIHBhZ2luYXRlKHsgaXRlbXM6IGZpbHRlcmVkLCBjdXJzb3IsIGxpbWl0IH0pO1xuICAgIH0sXG5cbiAgICBcInBhcnQubGlzdEJ5U2Vzc2lvblwiOiBhc3luYyAoeyBzZXNzaW9uSWQsIGN1cnNvciwgbGltaXQgfSkgPT4ge1xuICAgICAgY29uc3QgYWxsUGFydHMgPSBhd2FpdCByZWFkQWxsRnJvbURpcjxQYXJ0PihwYXJ0RGlyKTtcbiAgICAgIGNvbnN0IGZpbHRlcmVkID0gYWxsUGFydHNcbiAgICAgICAgLmZpbHRlcigocCkgPT4gcC5zZXNzaW9uSWQgPT09IHNlc3Npb25JZClcbiAgICAgICAgLnNvcnQoKGEsIGIpID0+IHtcbiAgICAgICAgICBpZiAoYS5tZXNzYWdlSWQgIT09IGIubWVzc2FnZUlkKSB7XG4gICAgICAgICAgICByZXR1cm4gYS5tZXNzYWdlSWQubG9jYWxlQ29tcGFyZShiLm1lc3NhZ2VJZCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBhLmluZGV4IC0gYi5pbmRleDtcbiAgICAgICAgfSk7XG4gICAgICByZXR1cm4gcGFnaW5hdGUoeyBpdGVtczogZmlsdGVyZWQsIGN1cnNvciwgbGltaXQgfSk7XG4gICAgfSxcblxuICAgIFwicGFydC5zZXRcIjogYXN5bmMgKHBhcnQpID0+IHtcbiAgICAgIGF3YWl0IHdyaXRlSnNvbkZpbGUoam9pbihwYXJ0RGlyLCBgJHtwYXJ0LmlkfS5qc29uYCksIHBhcnQpO1xuICAgICAgcmV0dXJuIHBhcnQ7XG4gICAgfSxcblxuICAgIFwic2FuZGJveC5nZXRcIjogYXN5bmMgKHsga2V5IH0pID0+IHtcbiAgICAgIGNvbnN0IHNhZmVOYW1lID0gQnVmZmVyLmZyb20oa2V5KS50b1N0cmluZyhcImJhc2U2NHVybFwiKTtcbiAgICAgIGNvbnN0IHNhbmRib3hQYXRoID0gam9pbihzYW5kYm94RGlyLCBgJHtzYWZlTmFtZX0uanNvbmApO1xuICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IHJlYWRKc29uPFNhbmRib3hSZWNvcmQ+KHNhbmRib3hQYXRoKTtcbiAgICAgIGlmICghZGF0YSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBkYXRhO1xuICAgIH0sXG5cbiAgICBcInNhbmRib3guc2V0XCI6IGFzeW5jIChyZWNvcmQpID0+IHtcbiAgICAgIGNvbnN0IHNhZmVOYW1lID0gQnVmZmVyLmZyb20ocmVjb3JkLmlkKS50b1N0cmluZyhcImJhc2U2NHVybFwiKTtcbiAgICAgIGNvbnN0IHNhbmRib3hQYXRoID0gam9pbihzYW5kYm94RGlyLCBgJHtzYWZlTmFtZX0uanNvbmApO1xuICAgICAgYXdhaXQgd3JpdGVKc29uRmlsZShzYW5kYm94UGF0aCwgcmVjb3JkKTtcbiAgICB9LFxuXG4gICAgXCJzYW5kYm94LmdldEJ5U2Vzc2lvblwiOiBhc3luYyAoeyBzZXNzaW9uSWQgfSkgPT4ge1xuICAgICAgY29uc3QgYWxsU2FuZGJveGVzID0gYXdhaXQgcmVhZEFsbEZyb21EaXI8U2FuZGJveFJlY29yZD4oc2FuZGJveERpcik7XG4gICAgICBjb25zdCBtYXRjaGluZyA9IGFsbFNhbmRib3hlcy5maWx0ZXIoKHMpID0+XG4gICAgICAgIHMuaWQuc3RhcnRzV2l0aChgJHtzZXNzaW9uSWR9LWApXG4gICAgICApO1xuICAgICAgaWYgKG1hdGNoaW5nLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIG1hdGNoaW5nLnNvcnQoXG4gICAgICAgIChhLCBiKSA9PiAoYi5sYXN0QWN0aXZpdHlBdCA/PyAwKSAtIChhLmxhc3RBY3Rpdml0eUF0ID8/IDApXG4gICAgICApO1xuICAgICAgcmV0dXJuIG1hdGNoaW5nWzBdO1xuICAgIH0sXG5cbiAgICBcImNvbW1hbmQuZ2V0XCI6IGFzeW5jICh7IGlkIH0pID0+IHtcbiAgICAgIHJldHVybiBhd2FpdCByZWFkSnNvbjxDb21tYW5kPihqb2luKGNvbW1hbmREaXIsIGAke2lkfS5qc29uYCkpO1xuICAgIH0sXG5cbiAgICBcImNvbW1hbmQuc2V0XCI6IGFzeW5jIChjb21tYW5kKSA9PiB7XG4gICAgICBhd2FpdCB3cml0ZUpzb25GaWxlKGpvaW4oY29tbWFuZERpciwgYCR7Y29tbWFuZC5pZH0uanNvbmApLCBjb21tYW5kKTtcbiAgICAgIHJldHVybiBjb21tYW5kO1xuICAgIH0sXG5cbiAgICBcImNvbW1hbmQubGlzdFwiOiBhc3luYyAoeyBzZXNzaW9uSWQsIGluY2x1ZGVGaW5pc2hlZCwgY3Vyc29yLCBsaW1pdCB9KSA9PiB7XG4gICAgICBjb25zdCBhbGxDb21tYW5kcyA9IGF3YWl0IHJlYWRBbGxGcm9tRGlyPENvbW1hbmQ+KGNvbW1hbmREaXIpO1xuICAgICAgbGV0IGZpbHRlcmVkID0gYWxsQ29tbWFuZHMuZmlsdGVyKChjKSA9PiBjLnNlc3Npb25JZCA9PT0gc2Vzc2lvbklkKTtcbiAgICAgIGlmICghaW5jbHVkZUZpbmlzaGVkKSB7XG4gICAgICAgIGZpbHRlcmVkID0gZmlsdGVyZWQuZmlsdGVyKChjKSA9PiBjLnN0YXR1cyA9PT0gXCJydW5uaW5nXCIpO1xuICAgICAgfVxuICAgICAgZmlsdGVyZWQuc29ydCgoYSwgYikgPT4gYS5zdGFydGVkQXQgLSBiLnN0YXJ0ZWRBdCk7XG4gICAgICByZXR1cm4gcGFnaW5hdGUoeyBpdGVtczogZmlsdGVyZWQsIGN1cnNvciwgbGltaXQgfSk7XG4gICAgfSxcbiAgfTtcbn1cbiIsICJpbXBvcnQgeyB0eXBlIFNlcnZlclR5cGUsIHNlcnZlIH0gZnJvbSBcIkBob25vL25vZGUtc2VydmVyXCI7XG5pbXBvcnQgeyBIb25vIH0gZnJvbSBcImhvbm9cIjtcbmltcG9ydCB7IGhhbmRsZVN0b3JhZ2VScGMgfSBmcm9tIFwiLi5cIjtcbmltcG9ydCB7IGNyZWF0ZUZpbGVzeXN0ZW1IYW5kbGVycyB9IGZyb20gXCIuL2xvY2FsLWZzLWhhbmRsZXJzXCI7XG5cbmNvbnN0IERFRkFVTFRfU1RPUkFHRV9ESVIgPSBcIi5hZ2VudC1zdG9yYWdlXCI7XG5cbmxldCBzdGFydFByb21pc2U6IFByb21pc2U8c3RyaW5nPiB8IG51bGwgPSBudWxsO1xubGV0IHNlcnZlckluc3RhbmNlOiB7IHVybDogc3RyaW5nOyBzZXJ2ZXI6IFNlcnZlclR5cGUgfSB8IG51bGwgPSBudWxsO1xuXG5leHBvcnQgZnVuY3Rpb24gc3RhcnRMb2NhbFN0b3JhZ2Uob3B0cz86IHtcbiAgcGF0aD86IHN0cmluZztcbiAgcG9ydD86IG51bWJlcjtcbn0pOiBQcm9taXNlPHN0cmluZz4ge1xuICBpZiAoc3RhcnRQcm9taXNlKSB7XG4gICAgcmV0dXJuIHN0YXJ0UHJvbWlzZTtcbiAgfVxuXG4gIHN0YXJ0UHJvbWlzZSA9IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgY29uc3QgaGFuZGxlcnMgPSBjcmVhdGVGaWxlc3lzdGVtSGFuZGxlcnMoXG4gICAgICBvcHRzPy5wYXRoID8/IERFRkFVTFRfU1RPUkFHRV9ESVJcbiAgICApO1xuICAgIGNvbnN0IGFwcCA9IG5ldyBIb25vKCk7XG5cbiAgICBhcHAucG9zdChcIi9cIiwgYXN5bmMgKGMpID0+IHtcbiAgICAgIGNvbnN0IGJvZHkgPSBhd2FpdCBjLnJlcS5qc29uKCk7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGhhbmRsZVN0b3JhZ2VScGMoYm9keSwgaGFuZGxlcnMpO1xuICAgICAgcmV0dXJuIGMuanNvbihyZXNwb25zZSk7XG4gICAgfSk7XG5cbiAgICBjb25zdCBwb3J0ID0gb3B0cz8ucG9ydCA/PyAwO1xuICAgIGNvbnN0IHNlcnZlciA9IHNlcnZlKHtcbiAgICAgIGZldGNoOiBhcHAuZmV0Y2gsXG4gICAgICBwb3J0LFxuICAgIH0pO1xuXG4gICAgc2VydmVyLm9uKFwibGlzdGVuaW5nXCIsICgpID0+IHtcbiAgICAgIGNvbnN0IGFkZHJlc3MgPSBzZXJ2ZXIuYWRkcmVzcygpO1xuICAgICAgY29uc3QgYWN0dWFsUG9ydCA9IHR5cGVvZiBhZGRyZXNzID09PSBcIm9iamVjdFwiID8gYWRkcmVzcz8ucG9ydCA6IHBvcnQ7XG4gICAgICBjb25zdCB1cmwgPSBgaHR0cDovL2xvY2FsaG9zdDoke2FjdHVhbFBvcnR9YDtcblxuICAgICAgc2VydmVySW5zdGFuY2UgPSB7IHVybCwgc2VydmVyIH07XG4gICAgICBjb25zb2xlLmxvZyhgW2FnZW50XSBMb2NhbCBzdG9yYWdlIHNlcnZlciBzdGFydGVkIGF0ICR7dXJsfWApO1xuICAgICAgcmVzb2x2ZSh1cmwpO1xuICAgIH0pO1xuICB9KTtcblxuICByZXR1cm4gc3RhcnRQcm9taXNlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc3RvcExvY2FsU3RvcmFnZSgpOiB2b2lkIHtcbiAgaWYgKHNlcnZlckluc3RhbmNlKSB7XG4gICAgc2VydmVySW5zdGFuY2Uuc2VydmVyLmNsb3NlKCk7XG4gICAgc2VydmVySW5zdGFuY2UgPSBudWxsO1xuICAgIHN0YXJ0UHJvbWlzZSA9IG51bGw7XG4gIH1cbn1cblxuaWYgKHR5cGVvZiBwcm9jZXNzICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gIHByb2Nlc3Mub24oXCJTSUdURVJNXCIsIHN0b3BMb2NhbFN0b3JhZ2UpO1xuICBwcm9jZXNzLm9uKFwiU0lHSU5UXCIsIHN0b3BMb2NhbFN0b3JhZ2UpO1xufVxuIiwgImNvbnN0IFZFUkNFTF9TVE9SQUdFX1VSTCA9XG4gIFwiaHR0cHM6Ly9hZ2VudC1zZGstc3RvcmFnZS1uaW5lLmxhYnMudmVyY2VsLmRldi9hcGkvc3RvcmFnZVwiO1xuXG5leHBvcnQgdHlwZSBWZXJjZWxTdG9yYWdlQ29uZmlnID0ge1xuICB1cmw6IHN0cmluZztcbiAgaGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbn07XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRWZXJjZWxTdG9yYWdlQ29uZmlnKCk6IFByb21pc2U8VmVyY2VsU3RvcmFnZUNvbmZpZz4ge1xuICBsZXQgdG9rZW46IHN0cmluZyB8IG51bGwgPSBudWxsO1xuXG4gIHRyeSB7XG4gICAgY29uc3QgeyBnZXRWZXJjZWxPaWRjVG9rZW4gfSA9IGF3YWl0IGltcG9ydChcIkB2ZXJjZWwvb2lkY1wiKTtcbiAgICB0b2tlbiA9IGF3YWl0IGdldFZlcmNlbE9pZGNUb2tlbigpO1xuICB9IGNhdGNoIHtcbiAgICAvLyBPSURDIG5vdCBhdmFpbGFibGUgKGxvY2FsIGRldiwgbm9uLVZlcmNlbCBlbnZpcm9ubWVudClcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgdXJsOiBWRVJDRUxfU1RPUkFHRV9VUkwsXG4gICAgaGVhZGVyczogdG9rZW4gPyB7IEF1dGhvcml6YXRpb246IGBCZWFyZXIgJHt0b2tlbn1gIH0gOiB7fSxcbiAgfTtcbn1cbiIsICJpbXBvcnQgdHlwZSB7IHogfSBmcm9tIFwiem9kXCI7XG5pbXBvcnQge1xuICBNZXNzYWdlTm90Rm91bmRFcnJvcixcbiAgU2FuZGJveE5vdEZvdW5kRXJyb3IsXG4gIFNlc3Npb25Ob3RGb3VuZEVycm9yLFxuICBTdG9yYWdlRXJyb3IsXG59IGZyb20gXCIuLi9lcnJvcnNcIjtcbmltcG9ydCB0eXBlIHsgU3RvcmFnZU1ldGhvZHMgfSBmcm9tIFwiLi9ycGNcIjtcbmltcG9ydCB0eXBlIHtcbiAgQ29tbWFuZCxcbiAgTGlzdFJlc3VsdCxcbiAgUGFydCxcbiAgUmVzb2x2ZWRTdG9yYWdlLFxuICBTdG9yYWdlLFxuICBTdG9yYWdlQ29uZmlnLFxufSBmcm9tIFwiLi90eXBlc1wiO1xuXG50eXBlIFJwY1Jlc3BvbnNlPFQ+ID1cbiAgfCB7IHJlc3VsdDogVCB9XG4gIHwgeyBlcnJvcjogeyBjb2RlOiBzdHJpbmc7IG1lc3NhZ2U6IHN0cmluZyB9IH07XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTdG9yYWdlQ2xpZW50KHsgdXJsLCBoZWFkZXJzIH06IFJlc29sdmVkU3RvcmFnZSk6IFN0b3JhZ2Uge1xuICBhc3luYyBmdW5jdGlvbiBycGM8TSBleHRlbmRzIGtleW9mIFN0b3JhZ2VNZXRob2RzPihcbiAgICBtZXRob2Q6IE0sXG4gICAgcGFyYW1zOiB6LmluZmVyPFN0b3JhZ2VNZXRob2RzW01dW1wicGFyYW1zXCJdPlxuICApOiBQcm9taXNlPHouaW5mZXI8U3RvcmFnZU1ldGhvZHNbTV1bXCJyZXN1bHRcIl0+PiB7XG4gICAgY29uc3QgcmVzID0gYXdhaXQgZmV0Y2godXJsLCB7XG4gICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgaGVhZGVyczogeyBcIkNvbnRlbnQtVHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb25cIiwgLi4uaGVhZGVycyB9LFxuICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoeyBtZXRob2QsIHBhcmFtcyB9KSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzLm9rKSB7XG4gICAgICB0aHJvdyBuZXcgU3RvcmFnZUVycm9yKHtcbiAgICAgICAgcmVhc29uOiBgSFRUUCAke3Jlcy5zdGF0dXN9OiAke3Jlcy5zdGF0dXNUZXh0fWAsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBjb25zdCBqc29uID0gKGF3YWl0IHJlcy5qc29uKCkpIGFzIFJwY1Jlc3BvbnNlPFxuICAgICAgei5pbmZlcjxTdG9yYWdlTWV0aG9kc1tNXVtcInJlc3VsdFwiXT5cbiAgICA+O1xuXG4gICAgaWYgKFwiZXJyb3JcIiBpbiBqc29uKSB7XG4gICAgICB0aHJvdyBuZXcgU3RvcmFnZUVycm9yKHsgcmVhc29uOiBqc29uLmVycm9yLm1lc3NhZ2UgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGpzb24ucmVzdWx0O1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBzZXNzaW9uOiB7XG4gICAgICBnZXQ6IGFzeW5jIChpZCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHJwYyhcInNlc3Npb24uZ2V0XCIsIHsgaWQgfSk7XG4gICAgICAgICAgaWYgKHJlc3VsdCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBTZXNzaW9uTm90Rm91bmRFcnJvcih7IGlkIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiBTdG9yYWdlRXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybiBlO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gbmV3IFN0b3JhZ2VFcnJvcih7IHJlYXNvbjogU3RyaW5nKGUpLCBjYXVzZTogZSB9KTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIHNldDogYXN5bmMgKHNlc3Npb24pID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXR1cm4gYXdhaXQgcnBjKFwic2Vzc2lvbi5zZXRcIiwgc2Vzc2lvbik7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIFN0b3JhZ2VFcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIGU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBuZXcgU3RvcmFnZUVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgbGlzdDogYXN5bmMgKG9wdHMpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXR1cm4gYXdhaXQgcnBjKFwic2Vzc2lvbi5saXN0XCIsIHtcbiAgICAgICAgICAgIHRhZ3M6IG9wdHM/LnRhZ3MsXG4gICAgICAgICAgICBvcmRlcjogb3B0cz8ub3JkZXIsXG4gICAgICAgICAgICBjdXJzb3I6IG9wdHM/LmN1cnNvcixcbiAgICAgICAgICAgIGxpbWl0OiBvcHRzPy5saW1pdCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGlmIChlIGluc3RhbmNlb2YgU3RvcmFnZUVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG5ldyBTdG9yYWdlRXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICB0YWc6IHtcbiAgICAgICAgc2V0OiBhc3luYyAoeyBzZXNzaW9uSWQsIHRhZ3MgfSkgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgcnBjKFwic2Vzc2lvbi50YWcuc2V0XCIsIHsgc2Vzc2lvbklkLCB0YWdzIH0pO1xuICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGlmIChlIGluc3RhbmNlb2YgU3RvcmFnZUVycm9yKSB7XG4gICAgICAgICAgICAgIHJldHVybiBlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBTdG9yYWdlRXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICAgIG1lc3NhZ2U6IHtcbiAgICAgIGxpc3Q6IGFzeW5jIChzZXNzaW9uSWQsIG9wdHMpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXR1cm4gYXdhaXQgcnBjKFwibWVzc2FnZS5saXN0XCIsIHtcbiAgICAgICAgICAgIHNlc3Npb25JZCxcbiAgICAgICAgICAgIGN1cnNvcjogb3B0cz8uY3Vyc29yLFxuICAgICAgICAgICAgbGltaXQ6IG9wdHM/LmxpbWl0LFxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiBTdG9yYWdlRXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybiBlO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gbmV3IFN0b3JhZ2VFcnJvcih7IHJlYXNvbjogU3RyaW5nKGUpLCBjYXVzZTogZSB9KTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIGdldDogYXN5bmMgKGlkKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcnBjKFwibWVzc2FnZS5nZXRcIiwgeyBpZCB9KTtcbiAgICAgICAgICBpZiAocmVzdWx0ID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IE1lc3NhZ2VOb3RGb3VuZEVycm9yKHsgaWQgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIFN0b3JhZ2VFcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIGU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBuZXcgU3RvcmFnZUVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgc2V0OiBhc3luYyAobWVzc2FnZSkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIHJldHVybiBhd2FpdCBycGMoXCJtZXNzYWdlLnNldFwiLCBtZXNzYWdlKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGlmIChlIGluc3RhbmNlb2YgU3RvcmFnZUVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG5ldyBTdG9yYWdlRXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSxcbiAgICBwYXJ0OiB7XG4gICAgICBsaXN0QnlNZXNzYWdlOiBhc3luYyAobWVzc2FnZUlkLCBvcHRzKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcnBjKFwicGFydC5saXN0QnlNZXNzYWdlXCIsIHtcbiAgICAgICAgICAgIG1lc3NhZ2VJZCxcbiAgICAgICAgICAgIGN1cnNvcjogb3B0cz8uY3Vyc29yLFxuICAgICAgICAgICAgbGltaXQ6IG9wdHM/LmxpbWl0LFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHJldHVybiByZXN1bHQgYXMgTGlzdFJlc3VsdDxQYXJ0PjtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGlmIChlIGluc3RhbmNlb2YgU3RvcmFnZUVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG5ldyBTdG9yYWdlRXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBsaXN0QnlTZXNzaW9uOiBhc3luYyAoc2Vzc2lvbklkLCBvcHRzKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcnBjKFwicGFydC5saXN0QnlTZXNzaW9uXCIsIHtcbiAgICAgICAgICAgIHNlc3Npb25JZCxcbiAgICAgICAgICAgIGN1cnNvcjogb3B0cz8uY3Vyc29yLFxuICAgICAgICAgICAgbGltaXQ6IG9wdHM/LmxpbWl0LFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHJldHVybiByZXN1bHQgYXMgTGlzdFJlc3VsdDxQYXJ0PjtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGlmIChlIGluc3RhbmNlb2YgU3RvcmFnZUVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG5ldyBTdG9yYWdlRXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBzZXQ6IGFzeW5jIChwYXJ0KSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmV0dXJuIChhd2FpdCBycGMoXCJwYXJ0LnNldFwiLCBwYXJ0KSkgYXMgUGFydDtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGlmIChlIGluc3RhbmNlb2YgU3RvcmFnZUVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG5ldyBTdG9yYWdlRXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSxcbiAgICBzYW5kYm94OiB7XG4gICAgICBnZXQ6IGFzeW5jIChrZXkpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBycGMoXCJzYW5kYm94LmdldFwiLCB7IGtleSB9KTtcbiAgICAgICAgICBpZiAocmVzdWx0ID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFNhbmRib3hOb3RGb3VuZEVycm9yKHsgaWQ6IGtleSB9KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGlmIChlIGluc3RhbmNlb2YgU3RvcmFnZUVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG5ldyBTdG9yYWdlRXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBnZXRCeVNlc3Npb246IGFzeW5jIChzZXNzaW9uSWQpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBycGMoXCJzYW5kYm94LmdldEJ5U2Vzc2lvblwiLCB7IHNlc3Npb25JZCB9KTtcbiAgICAgICAgICBpZiAocmVzdWx0ID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFNhbmRib3hOb3RGb3VuZEVycm9yKHsgaWQ6IHNlc3Npb25JZCB9KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGlmIChlIGluc3RhbmNlb2YgU3RvcmFnZUVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG5ldyBTdG9yYWdlRXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBzZXQ6IGFzeW5jIChyZWNvcmQpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCBycGMoXCJzYW5kYm94LnNldFwiLCByZWNvcmQpO1xuICAgICAgICAgIHJldHVybiByZWNvcmQ7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIFN0b3JhZ2VFcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIGU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBuZXcgU3RvcmFnZUVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgIH0sXG4gICAgY29tbWFuZDoge1xuICAgICAgZ2V0OiBhc3luYyAoaWQpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXR1cm4gKGF3YWl0IHJwYyhcImNvbW1hbmQuZ2V0XCIsIHsgaWQgfSkpIGFzIENvbW1hbmQgfCBudWxsO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiBTdG9yYWdlRXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybiBlO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gbmV3IFN0b3JhZ2VFcnJvcih7IHJlYXNvbjogU3RyaW5nKGUpLCBjYXVzZTogZSB9KTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIHNldDogYXN5bmMgKGNvbW1hbmQpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXR1cm4gKGF3YWl0IHJwYyhcImNvbW1hbmQuc2V0XCIsIGNvbW1hbmQpKSBhcyBDb21tYW5kO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiBTdG9yYWdlRXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybiBlO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gbmV3IFN0b3JhZ2VFcnJvcih7IHJlYXNvbjogU3RyaW5nKGUpLCBjYXVzZTogZSB9KTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIGxpc3Q6IGFzeW5jIChzZXNzaW9uSWQsIG9wdHMpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBycGMoXCJjb21tYW5kLmxpc3RcIiwge1xuICAgICAgICAgICAgc2Vzc2lvbklkLFxuICAgICAgICAgICAgaW5jbHVkZUZpbmlzaGVkOiBvcHRzPy5pbmNsdWRlRmluaXNoZWQsXG4gICAgICAgICAgICBjdXJzb3I6IG9wdHM/LmN1cnNvcixcbiAgICAgICAgICAgIGxpbWl0OiBvcHRzPy5saW1pdCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXR1cm4gcmVzdWx0IGFzIExpc3RSZXN1bHQ8Q29tbWFuZD47XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIFN0b3JhZ2VFcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIGU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBuZXcgU3RvcmFnZUVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgIH0sXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlc29sdmVTdG9yYWdlVXJsKFxuICBjb25maWc6IFN0b3JhZ2VDb25maWdcbik6IFByb21pc2U8UmVzb2x2ZWRTdG9yYWdlPiB7XG4gIHN3aXRjaCAoY29uZmlnLnR5cGUpIHtcbiAgICBjYXNlIFwibG9jYWxcIjoge1xuICAgICAgY29uc3QgeyBzdGFydExvY2FsU3RvcmFnZSB9ID0gYXdhaXQgaW1wb3J0KFwiLi9iaW5kaW5ncy9sb2NhbFwiKTtcbiAgICAgIHJldHVybiB7IHVybDogYXdhaXQgc3RhcnRMb2NhbFN0b3JhZ2UoeyBwYXRoOiBjb25maWcucGF0aCB9KSB9O1xuICAgIH1cbiAgICBjYXNlIFwidmVyY2VsXCI6IHtcbiAgICAgIGNvbnN0IHsgZ2V0VmVyY2VsU3RvcmFnZUNvbmZpZyB9ID0gYXdhaXQgaW1wb3J0KFwiLi9iaW5kaW5ncy92ZXJjZWxcIik7XG4gICAgICByZXR1cm4gZ2V0VmVyY2VsU3RvcmFnZUNvbmZpZygpO1xuICAgIH1cbiAgICBjYXNlIFwiY3VzdG9tXCI6IHtcbiAgICAgIHJldHVybiB7IHVybDogY29uZmlnLnVybCwgaGVhZGVyczogY29uZmlnLmhlYWRlcnMgfTtcbiAgICB9XG4gICAgZGVmYXVsdDoge1xuICAgICAgY29uZmlnIHNhdGlzZmllcyBuZXZlcjtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFVua25vd24gc3RvcmFnZSB0eXBlOiAkeyhjb25maWcgYXMgeyB0eXBlOiBzdHJpbmcgfSkudHlwZX1gXG4gICAgICApO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0U3RvcmFnZShzdG9yYWdlQ29uZmlnOiBTdG9yYWdlQ29uZmlnKTogU3RvcmFnZSB7XG4gIGxldCBjbGllbnRQcm9taXNlOiBQcm9taXNlPFN0b3JhZ2U+IHwgbnVsbCA9IG51bGw7XG4gIGNvbnN0IGdldENsaWVudCA9ICgpID0+IHtcbiAgICBpZiAoIWNsaWVudFByb21pc2UpIHtcbiAgICAgIGNsaWVudFByb21pc2UgPSByZXNvbHZlU3RvcmFnZVVybChzdG9yYWdlQ29uZmlnKS50aGVuKChyZXNvbHZlZCkgPT5cbiAgICAgICAgZ2V0U3RvcmFnZUNsaWVudChyZXNvbHZlZClcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBjbGllbnRQcm9taXNlO1xuICB9O1xuXG4gIHJldHVybiB7XG4gICAgc2Vzc2lvbjoge1xuICAgICAgZ2V0OiBhc3luYyAoaWQpID0+IChhd2FpdCBnZXRDbGllbnQoKSkuc2Vzc2lvbi5nZXQoaWQpLFxuICAgICAgc2V0OiBhc3luYyAoc2Vzc2lvbikgPT4gKGF3YWl0IGdldENsaWVudCgpKS5zZXNzaW9uLnNldChzZXNzaW9uKSxcbiAgICAgIGxpc3Q6IGFzeW5jIChvcHRzKSA9PiAoYXdhaXQgZ2V0Q2xpZW50KCkpLnNlc3Npb24ubGlzdChvcHRzKSxcbiAgICAgIHRhZzoge1xuICAgICAgICBzZXQ6IGFzeW5jIChvcHRzKSA9PiAoYXdhaXQgZ2V0Q2xpZW50KCkpLnNlc3Npb24udGFnLnNldChvcHRzKSxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBtZXNzYWdlOiB7XG4gICAgICBsaXN0OiBhc3luYyAoc2Vzc2lvbklkLCBvcHRzKSA9PlxuICAgICAgICAoYXdhaXQgZ2V0Q2xpZW50KCkpLm1lc3NhZ2UubGlzdChzZXNzaW9uSWQsIG9wdHMpLFxuICAgICAgZ2V0OiBhc3luYyAoaWQpID0+IChhd2FpdCBnZXRDbGllbnQoKSkubWVzc2FnZS5nZXQoaWQpLFxuICAgICAgc2V0OiBhc3luYyAobWVzc2FnZSkgPT4gKGF3YWl0IGdldENsaWVudCgpKS5tZXNzYWdlLnNldChtZXNzYWdlKSxcbiAgICB9LFxuICAgIHBhcnQ6IHtcbiAgICAgIGxpc3RCeU1lc3NhZ2U6IGFzeW5jIChtZXNzYWdlSWQsIG9wdHMpID0+XG4gICAgICAgIChhd2FpdCBnZXRDbGllbnQoKSkucGFydC5saXN0QnlNZXNzYWdlKG1lc3NhZ2VJZCwgb3B0cyksXG4gICAgICBsaXN0QnlTZXNzaW9uOiBhc3luYyAoc2Vzc2lvbklkLCBvcHRzKSA9PlxuICAgICAgICAoYXdhaXQgZ2V0Q2xpZW50KCkpLnBhcnQubGlzdEJ5U2Vzc2lvbihzZXNzaW9uSWQsIG9wdHMpLFxuICAgICAgc2V0OiBhc3luYyAocGFydCkgPT4gKGF3YWl0IGdldENsaWVudCgpKS5wYXJ0LnNldChwYXJ0KSxcbiAgICB9LFxuICAgIHNhbmRib3g6IHtcbiAgICAgIGdldDogYXN5bmMgKGtleSkgPT4gKGF3YWl0IGdldENsaWVudCgpKS5zYW5kYm94LmdldChrZXkpLFxuICAgICAgc2V0OiBhc3luYyAob3B0cykgPT4gKGF3YWl0IGdldENsaWVudCgpKS5zYW5kYm94LnNldChvcHRzKSxcbiAgICAgIGdldEJ5U2Vzc2lvbjogYXN5bmMgKHNlc3Npb25JZCkgPT5cbiAgICAgICAgKGF3YWl0IGdldENsaWVudCgpKS5zYW5kYm94LmdldEJ5U2Vzc2lvbihzZXNzaW9uSWQpLFxuICAgIH0sXG4gICAgY29tbWFuZDoge1xuICAgICAgZ2V0OiBhc3luYyAoaWQpID0+IChhd2FpdCBnZXRDbGllbnQoKSkuY29tbWFuZC5nZXQoaWQpLFxuICAgICAgc2V0OiBhc3luYyAoY29tbWFuZCkgPT4gKGF3YWl0IGdldENsaWVudCgpKS5jb21tYW5kLnNldChjb21tYW5kKSxcbiAgICAgIGxpc3Q6IGFzeW5jIChzZXNzaW9uSWQsIG9wdHMpID0+XG4gICAgICAgIChhd2FpdCBnZXRDbGllbnQoKSkuY29tbWFuZC5saXN0KHNlc3Npb25JZCwgb3B0cyksXG4gICAgfSxcbiAgfTtcbn1cbiIsICJpbXBvcnQgeyB6IH0gZnJvbSBcInpvZFwiO1xuXG5jb25zdCBWZXJjZWxMaWZlY3ljbGVDb25maWdTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIHN0b3BBZnRlckluYWN0aXZlTXM6IHoubnVtYmVyKCkub3B0aW9uYWwoKSxcbiAgc25hcHNob3RCZWZvcmVUaW1lb3V0TXM6IHoubnVtYmVyKCkub3B0aW9uYWwoKSxcbiAgc25hcHNob3RJZDogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuICBhdXRvU3RhcnQ6IHouYm9vbGVhbigpLm9wdGlvbmFsKCksXG59KTtcblxuZXhwb3J0IGNvbnN0IFNhbmRib3hDb25maWdTY2hlbWEgPSB6LmRpc2NyaW1pbmF0ZWRVbmlvbihcInR5cGVcIiwgW1xuICB6Lm9iamVjdCh7XG4gICAgdHlwZTogei5saXRlcmFsKFwidmVyY2VsXCIpLFxuICAgIHJlc291cmNlczogei5vYmplY3QoeyB2Y3B1czogei5udW1iZXIoKSB9KS5vcHRpb25hbCgpLFxuICAgIHBvcnRzOiB6LmFycmF5KHoubnVtYmVyKCkpLm9wdGlvbmFsKCksXG4gICAgbGlmZWN5Y2xlOiBWZXJjZWxMaWZlY3ljbGVDb25maWdTY2hlbWEub3B0aW9uYWwoKSxcbiAgfSksXG4gIHoub2JqZWN0KHtcbiAgICB0eXBlOiB6LmxpdGVyYWwoXCJsb2NhbFwiKSxcbiAgICBwYXRoOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG4gIH0pLFxuICB6Lm9iamVjdCh7XG4gICAgdHlwZTogei5saXRlcmFsKFwiY3VzdG9tXCIpLFxuICAgIHVybDogei5zdHJpbmcoKSxcbiAgICBoZWFkZXJzOiB6LnJlY29yZCh6LnN0cmluZygpLCB6LnN0cmluZygpKS5vcHRpb25hbCgpLFxuICB9KSxcbl0pO1xuXG5leHBvcnQgdHlwZSBTYW5kYm94Q29uZmlnID0gei5pbmZlcjx0eXBlb2YgU2FuZGJveENvbmZpZ1NjaGVtYT47XG5cbmV4cG9ydCBjb25zdCBTZXNzaW9uU2NoZW1hID0gei5vYmplY3Qoe1xuICBpZDogei5zdHJpbmcoKSxcbiAgY3JlYXRlZEF0OiB6Lm51bWJlcigpLFxuICB1cGRhdGVkQXQ6IHoubnVtYmVyKCksXG4gIHJ1bklkOiB6LnN0cmluZygpLm51bGxhYmxlKCksXG4gIGxhc3RNZXNzYWdlSWQ6IHouc3RyaW5nKCkubnVsbGFibGUoKSxcbiAgdGFnczogei5yZWNvcmQoei5zdHJpbmcoKSwgei51bmtub3duKCkpLm51bGxhYmxlKCksXG4gIGluc3RydWN0aW9uczogei5zdHJpbmcoKS5udWxsYWJsZSgpLFxuICBtb2RlbDogei5zdHJpbmcoKS5udWxsYWJsZSgpLFxuICBtY3A6IHoudW5rbm93bigpLm51bGxhYmxlKCksIC8vIFRPRE9cbiAgc2FuZGJveElkOiB6LnN0cmluZygpLm51bGxhYmxlKCksXG4gIHNraWxsc0Rpcjogei5hcnJheSh6LnN0cmluZygpKS5udWxsYWJsZSgpLFxuICBob29rVG9rZW46IHouc3RyaW5nKCkubnVsbGFibGUoKSxcbn0pO1xuXG5leHBvcnQgY29uc3QgTWVzc2FnZVNjaGVtYSA9IHoub2JqZWN0KHtcbiAgaWQ6IHouc3RyaW5nKCksXG4gIHNlc3Npb25JZDogei5zdHJpbmcoKSxcbiAgcm9sZTogei5lbnVtKFtcInVzZXJcIiwgXCJhc3Npc3RhbnRcIiwgXCJzeXN0ZW1cIl0pLFxuICBjcmVhdGVkQXQ6IHoubnVtYmVyKCksXG4gIGNvbXBsZXRlZEF0OiB6Lm51bWJlcigpLm51bGxhYmxlKCksXG4gIG1jcENvbnRleHQ6IHoudW5rbm93bigpLm51bGxhYmxlKCksXG59KTtcblxuLyoqXG4gKiBUaGUgYHBhcnRgIGZpZWxkIGNvcnJlc3BvbmRzIHRvIGBVSU1lc3NhZ2VbXCJwYXJ0c1wiXVtudW1iZXJdYCBmcm9tIHRoZSBgYWlgIHBhY2thZ2UuXG4gKiBXZSB1c2UgYHoudW5rbm93bigpYCBiZWNhdXNlIHRoZSBleGFjdCBzaGFwZSB2YXJpZXMgYnkgcGFydCB0eXBlICh0ZXh0LCB0b29sLWNhbGwsXG4gKiB0b29sLXJlc3VsdCwgZXRjLikgYW5kIG1heSBldm9sdmUgd2l0aCB0aGUgQUkgU0RLLiBUaGUgUlBDIGxheWVyIGp1c3QgcGFzc2VzIGl0IHRocm91Z2guXG4gKi9cbmV4cG9ydCBjb25zdCBQYXJ0U2NoZW1hID0gei5vYmplY3Qoe1xuICBpZDogei5zdHJpbmcoKSxcbiAgbWVzc2FnZUlkOiB6LnN0cmluZygpLFxuICBzZXNzaW9uSWQ6IHouc3RyaW5nKCksXG4gIGluZGV4OiB6Lm51bWJlcigpLFxuICBwYXJ0OiB6LnVua25vd24oKSxcbn0pO1xuXG5leHBvcnQgY29uc3QgQ29tbWFuZFJlc3VsdFNjaGVtYSA9IHoub2JqZWN0KHtcbiAgc3Rkb3V0OiB6LnN0cmluZygpLFxuICBzdGRlcnI6IHouc3RyaW5nKCksXG4gIGV4aXRDb2RlOiB6Lm51bWJlcigpLFxuICBjb21wbGV0ZWRBdDogei5udW1iZXIoKSxcbn0pO1xuXG5leHBvcnQgY29uc3QgU2FuZGJveFJlY29yZFNjaGVtYSA9IHoub2JqZWN0KHtcbiAgaWQ6IHouc3RyaW5nKCksXG4gIGNvbmZpZzogU2FuZGJveENvbmZpZ1NjaGVtYSxcbiAgY3JlYXRlZEF0OiB6Lm51bWJlcigpLm51bGxhYmxlKCksXG4gIGxhc3RBY3Rpdml0eUF0OiB6Lm51bWJlcigpLm51bGxhYmxlKCksXG4gIGFjcXVpcmluZ0xvY2tJZDogei5zdHJpbmcoKS5udWxsYWJsZSgpLFxuICBhY3F1aXJpbmdMb2NrQXQ6IHoubnVtYmVyKCkubnVsbGFibGUoKSxcbiAgcHJvdmlkZXJNZXRhZGF0YTogelxuICAgIC5kaXNjcmltaW5hdGVkVW5pb24oXCJwcm92aWRlclwiLCBbXG4gICAgICB6Lm9iamVjdCh7XG4gICAgICAgIHByb3ZpZGVyOiB6LmxpdGVyYWwoXCJ2ZXJjZWxcIiksXG4gICAgICAgIHNhbmRib3hJZDogei5zdHJpbmcoKS5udWxsYWJsZSgpLFxuICAgICAgICBzbmFwc2hvdElkOiB6LnN0cmluZygpLm51bGxhYmxlKCksXG4gICAgICB9KSxcbiAgICBdKVxuICAgIC5vcHRpb25hbCgpLFxufSk7XG5cbmNvbnN0IENvbW1hbmRCYXNlU2NoZW1hID0gei5vYmplY3Qoe1xuICBpZDogei5zdHJpbmcoKSxcbiAgc2Vzc2lvbklkOiB6LnN0cmluZygpLFxuICBjb21tYW5kOiB6LnN0cmluZygpLFxuICBhcmdzOiB6LmFycmF5KHouc3RyaW5nKCkpLm9wdGlvbmFsKCksXG4gIHN0YXJ0ZWRBdDogei5udW1iZXIoKSxcbn0pO1xuXG5leHBvcnQgY29uc3QgQ29tbWFuZFNjaGVtYSA9IHouZGlzY3JpbWluYXRlZFVuaW9uKFwic3RhdHVzXCIsIFtcbiAgQ29tbWFuZEJhc2VTY2hlbWEuZXh0ZW5kKHsgc3RhdHVzOiB6LmxpdGVyYWwoXCJydW5uaW5nXCIpIH0pLFxuICBDb21tYW5kQmFzZVNjaGVtYS5leHRlbmQoe1xuICAgIHN0YXR1czogei5saXRlcmFsKFwiY29tcGxldGVkXCIpLFxuICAgIHJlc3VsdDogQ29tbWFuZFJlc3VsdFNjaGVtYSxcbiAgfSksXG4gIENvbW1hbmRCYXNlU2NoZW1hLmV4dGVuZCh7XG4gICAgc3RhdHVzOiB6LmxpdGVyYWwoXCJraWxsZWRcIiksXG4gICAgcmVzdWx0OiBDb21tYW5kUmVzdWx0U2NoZW1hLm9wdGlvbmFsKCksXG4gIH0pLFxuICBDb21tYW5kQmFzZVNjaGVtYS5leHRlbmQoe1xuICAgIHN0YXR1czogei5saXRlcmFsKFwiZmFpbGVkXCIpLFxuICAgIHJlc3VsdDogQ29tbWFuZFJlc3VsdFNjaGVtYSxcbiAgfSksXG5dKTtcblxuZnVuY3Rpb24gTGlzdFJlc3VsdFNjaGVtYTxUIGV4dGVuZHMgei5ab2RUeXBlQW55PihpdGVtU2NoZW1hOiBUKSB7XG4gIHJldHVybiB6Lm9iamVjdCh7XG4gICAgaXRlbXM6IHouYXJyYXkoaXRlbVNjaGVtYSksXG4gICAgbmV4dEN1cnNvcjogei5zdHJpbmcoKS5udWxsYWJsZSgpLFxuICB9KTtcbn1cblxuZXhwb3J0IGNvbnN0IG1ldGhvZHMgPSB7XG4gIFwic2Vzc2lvbi5nZXRcIjoge1xuICAgIHBhcmFtczogei5vYmplY3QoeyBpZDogei5zdHJpbmcoKSB9KSxcbiAgICByZXN1bHQ6IFNlc3Npb25TY2hlbWEubnVsbGFibGUoKSxcbiAgfSxcbiAgXCJzZXNzaW9uLnNldFwiOiB7XG4gICAgcGFyYW1zOiBTZXNzaW9uU2NoZW1hLFxuICAgIHJlc3VsdDogU2Vzc2lvblNjaGVtYSxcbiAgfSxcbiAgXCJzZXNzaW9uLmxpc3RcIjoge1xuICAgIHBhcmFtczogei5vYmplY3Qoe1xuICAgICAgdGFnczogei5yZWNvcmQoei5zdHJpbmcoKSwgei51bmtub3duKCkpLm9wdGlvbmFsKCksXG4gICAgICBvcmRlcjogelxuICAgICAgICAuZW51bShbXG4gICAgICAgICAgXCJjcmVhdGVkQXRfYXNjXCIsXG4gICAgICAgICAgXCJjcmVhdGVkQXRfZGVzY1wiLFxuICAgICAgICAgIFwidXBkYXRlZEF0X2FzY1wiLFxuICAgICAgICAgIFwidXBkYXRlZEF0X2Rlc2NcIixcbiAgICAgICAgXSlcbiAgICAgICAgLm9wdGlvbmFsKCksXG4gICAgICBjdXJzb3I6IHouc3RyaW5nKCkub3B0aW9uYWwoKSxcbiAgICAgIGxpbWl0OiB6Lm51bWJlcigpLm9wdGlvbmFsKCksXG4gICAgfSksXG4gICAgcmVzdWx0OiBMaXN0UmVzdWx0U2NoZW1hKFNlc3Npb25TY2hlbWEpLFxuICB9LFxuICBcInNlc3Npb24ubGlzdEJ5U2FuZGJveFwiOiB7XG4gICAgcGFyYW1zOiB6Lm9iamVjdCh7XG4gICAgICBzYW5kYm94SWQ6IHouc3RyaW5nKCksXG4gICAgICB0YWdzOiB6LnJlY29yZCh6LnN0cmluZygpLCB6LnVua25vd24oKSkub3B0aW9uYWwoKSxcbiAgICAgIG9yZGVyOiB6XG4gICAgICAgIC5lbnVtKFtcbiAgICAgICAgICBcImNyZWF0ZWRBdF9hc2NcIixcbiAgICAgICAgICBcImNyZWF0ZWRBdF9kZXNjXCIsXG4gICAgICAgICAgXCJ1cGRhdGVkQXRfYXNjXCIsXG4gICAgICAgICAgXCJ1cGRhdGVkQXRfZGVzY1wiLFxuICAgICAgICBdKVxuICAgICAgICAub3B0aW9uYWwoKSxcbiAgICAgIGN1cnNvcjogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuICAgICAgbGltaXQ6IHoubnVtYmVyKCkub3B0aW9uYWwoKSxcbiAgICB9KSxcbiAgICByZXN1bHQ6IExpc3RSZXN1bHRTY2hlbWEoU2Vzc2lvblNjaGVtYSksXG4gIH0sXG4gIFwic2Vzc2lvbi50YWcuc2V0XCI6IHtcbiAgICBwYXJhbXM6IHoub2JqZWN0KHtcbiAgICAgIHNlc3Npb25JZDogei5zdHJpbmcoKSxcbiAgICAgIHRhZ3M6IHoucmVjb3JkKHouc3RyaW5nKCksIHoudW5rbm93bigpKSxcbiAgICB9KSxcbiAgICByZXN1bHQ6IFNlc3Npb25TY2hlbWEsXG4gIH0sXG4gIFwibWVzc2FnZS5nZXRcIjoge1xuICAgIHBhcmFtczogei5vYmplY3QoeyBpZDogei5zdHJpbmcoKSB9KSxcbiAgICByZXN1bHQ6IE1lc3NhZ2VTY2hlbWEubnVsbGFibGUoKSxcbiAgfSxcbiAgXCJtZXNzYWdlLnNldFwiOiB7XG4gICAgcGFyYW1zOiBNZXNzYWdlU2NoZW1hLFxuICAgIHJlc3VsdDogTWVzc2FnZVNjaGVtYSxcbiAgfSxcbiAgXCJtZXNzYWdlLmxpc3RcIjoge1xuICAgIHBhcmFtczogei5vYmplY3Qoe1xuICAgICAgc2Vzc2lvbklkOiB6LnN0cmluZygpLFxuICAgICAgY3Vyc29yOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG4gICAgICBsaW1pdDogei5udW1iZXIoKS5vcHRpb25hbCgpLFxuICAgIH0pLFxuICAgIHJlc3VsdDogTGlzdFJlc3VsdFNjaGVtYShNZXNzYWdlU2NoZW1hKSxcbiAgfSxcbiAgXCJwYXJ0Lmxpc3RCeU1lc3NhZ2VcIjoge1xuICAgIHBhcmFtczogei5vYmplY3Qoe1xuICAgICAgbWVzc2FnZUlkOiB6LnN0cmluZygpLFxuICAgICAgY3Vyc29yOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG4gICAgICBsaW1pdDogei5udW1iZXIoKS5vcHRpb25hbCgpLFxuICAgIH0pLFxuICAgIHJlc3VsdDogTGlzdFJlc3VsdFNjaGVtYShQYXJ0U2NoZW1hKSxcbiAgfSxcbiAgXCJwYXJ0Lmxpc3RCeVNlc3Npb25cIjoge1xuICAgIHBhcmFtczogei5vYmplY3Qoe1xuICAgICAgc2Vzc2lvbklkOiB6LnN0cmluZygpLFxuICAgICAgY3Vyc29yOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG4gICAgICBsaW1pdDogei5udW1iZXIoKS5vcHRpb25hbCgpLFxuICAgIH0pLFxuICAgIHJlc3VsdDogTGlzdFJlc3VsdFNjaGVtYShQYXJ0U2NoZW1hKSxcbiAgfSxcbiAgXCJwYXJ0LnNldFwiOiB7XG4gICAgcGFyYW1zOiBQYXJ0U2NoZW1hLFxuICAgIHJlc3VsdDogUGFydFNjaGVtYSxcbiAgfSxcbiAgXCJzYW5kYm94LmdldFwiOiB7XG4gICAgcGFyYW1zOiB6Lm9iamVjdCh7IGtleTogei5zdHJpbmcoKSB9KSxcbiAgICByZXN1bHQ6IFNhbmRib3hSZWNvcmRTY2hlbWEubnVsbGFibGUoKSxcbiAgfSxcbiAgXCJzYW5kYm94LmdldEJ5U2Vzc2lvblwiOiB7XG4gICAgcGFyYW1zOiB6Lm9iamVjdCh7IHNlc3Npb25JZDogei5zdHJpbmcoKSB9KSxcbiAgICByZXN1bHQ6IFNhbmRib3hSZWNvcmRTY2hlbWEubnVsbGFibGUoKSxcbiAgfSxcbiAgXCJzYW5kYm94LnNldFwiOiB7XG4gICAgcGFyYW1zOiBTYW5kYm94UmVjb3JkU2NoZW1hLFxuICAgIHJlc3VsdDogei52b2lkKCksXG4gIH0sXG4gIFwiY29tbWFuZC5nZXRcIjoge1xuICAgIHBhcmFtczogei5vYmplY3QoeyBpZDogei5zdHJpbmcoKSB9KSxcbiAgICByZXN1bHQ6IENvbW1hbmRTY2hlbWEubnVsbGFibGUoKSxcbiAgfSxcbiAgXCJjb21tYW5kLnNldFwiOiB7XG4gICAgcGFyYW1zOiBDb21tYW5kU2NoZW1hLFxuICAgIHJlc3VsdDogQ29tbWFuZFNjaGVtYSxcbiAgfSxcbiAgXCJjb21tYW5kLmxpc3RcIjoge1xuICAgIHBhcmFtczogei5vYmplY3Qoe1xuICAgICAgc2Vzc2lvbklkOiB6LnN0cmluZygpLFxuICAgICAgaW5jbHVkZUZpbmlzaGVkOiB6LmJvb2xlYW4oKS5vcHRpb25hbCgpLFxuICAgICAgY3Vyc29yOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG4gICAgICBsaW1pdDogei5udW1iZXIoKS5vcHRpb25hbCgpLFxuICAgIH0pLFxuICAgIHJlc3VsdDogTGlzdFJlc3VsdFNjaGVtYShDb21tYW5kU2NoZW1hKSxcbiAgfSxcbn0gYXMgY29uc3Q7XG5cbmV4cG9ydCB0eXBlIFN0b3JhZ2VNZXRob2RzID0gdHlwZW9mIG1ldGhvZHM7XG5leHBvcnQgdHlwZSBNZXRob2ROYW1lID0ga2V5b2YgU3RvcmFnZU1ldGhvZHM7XG4iLCAiaW1wb3J0IHR5cGUgeyB6IH0gZnJvbSBcInpvZFwiO1xuaW1wb3J0IHsgdHlwZSBNZXRob2ROYW1lLCBtZXRob2RzLCB0eXBlIFN0b3JhZ2VNZXRob2RzIH0gZnJvbSBcIi4vcnBjXCI7XG5cbmV4cG9ydCB0eXBlIEhhbmRsZXJzID0ge1xuICBbSyBpbiBNZXRob2ROYW1lXTogKFxuICAgIHBhcmFtczogei5pbmZlcjxTdG9yYWdlTWV0aG9kc1tLXVtcInBhcmFtc1wiXT5cbiAgKSA9PiBQcm9taXNlPHouaW5mZXI8U3RvcmFnZU1ldGhvZHNbS11bXCJyZXN1bHRcIl0+Pjtcbn07XG5cbmV4cG9ydCB0eXBlIFJwY1JlcXVlc3QgPSB7XG4gIG1ldGhvZDogc3RyaW5nO1xuICBwYXJhbXM6IHVua25vd247XG59O1xuXG5leHBvcnQgdHlwZSBScGNTdWNjZXNzUmVzcG9uc2U8VCA9IHVua25vd24+ID0ge1xuICByZXN1bHQ6IFQ7XG59O1xuXG5leHBvcnQgdHlwZSBScGNFcnJvclJlc3BvbnNlID0ge1xuICBlcnJvcjogeyBjb2RlOiBzdHJpbmc7IG1lc3NhZ2U6IHN0cmluZyB9O1xufTtcblxuZXhwb3J0IHR5cGUgUnBjUmVzcG9uc2U8VCA9IHVua25vd24+ID0gUnBjU3VjY2Vzc1Jlc3BvbnNlPFQ+IHwgUnBjRXJyb3JSZXNwb25zZTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZVN0b3JhZ2VScGMoXG4gIGJvZHk6IFJwY1JlcXVlc3QsXG4gIGhhbmRsZXJzOiBIYW5kbGVyc1xuKTogUHJvbWlzZTxScGNSZXNwb25zZT4ge1xuICBjb25zdCB7IG1ldGhvZCwgcGFyYW1zIH0gPSBib2R5O1xuXG4gIGlmICghKG1ldGhvZCBpbiBtZXRob2RzKSkge1xuICAgIHJldHVybiB7XG4gICAgICBlcnJvcjogeyBjb2RlOiBcIk1FVEhPRF9OT1RfRk9VTkRcIiwgbWVzc2FnZTogYFVua25vd24gbWV0aG9kOiAke21ldGhvZH1gIH0sXG4gICAgfTtcbiAgfVxuXG4gIGNvbnN0IG1ldGhvZE5hbWUgPSBtZXRob2QgYXMgTWV0aG9kTmFtZTtcbiAgY29uc3Qgc2NoZW1hID0gbWV0aG9kc1ttZXRob2ROYW1lXS5wYXJhbXM7XG4gIGNvbnN0IHBhcnNlZCA9IHNjaGVtYS5zYWZlUGFyc2UocGFyYW1zKTtcblxuICBpZiAoIXBhcnNlZC5zdWNjZXNzKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGVycm9yOiB7XG4gICAgICAgIGNvZGU6IFwiSU5WQUxJRF9QQVJBTVNcIixcbiAgICAgICAgbWVzc2FnZTogcGFyc2VkLmVycm9yLmlzc3Vlc1xuICAgICAgICAgIC5tYXAoKGkpID0+IGAke2kucGF0aC5qb2luKFwiLlwiKX06ICR7aS5tZXNzYWdlfWApXG4gICAgICAgICAgLmpvaW4oXCIsIFwiKSxcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgY29uc3QgaGFuZGxlciA9IGhhbmRsZXJzW21ldGhvZE5hbWVdIGFzIChcbiAgICAgIHBhcmFtczogdW5rbm93blxuICAgICkgPT4gUHJvbWlzZTx1bmtub3duPjtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBoYW5kbGVyKHBhcnNlZC5kYXRhKTtcbiAgICByZXR1cm4geyByZXN1bHQgfTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiB7XG4gICAgICBlcnJvcjoge1xuICAgICAgICBjb2RlOiBcIklOVEVSTkFMX0VSUk9SXCIsXG4gICAgICAgIG1lc3NhZ2U6IGUgaW5zdGFuY2VvZiBFcnJvciA/IGUubWVzc2FnZSA6IFN0cmluZyhlKSxcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxufVxuIiwgImV4cG9ydCB7IGdldFN0b3JhZ2UgfSBmcm9tIFwiLi9jbGllbnRcIjtcbmV4cG9ydCB7XG4gIHR5cGUgSGFuZGxlcnMsXG4gIGhhbmRsZVN0b3JhZ2VScGMsXG4gIHR5cGUgUnBjRXJyb3JSZXNwb25zZSxcbiAgdHlwZSBScGNSZXF1ZXN0LFxuICB0eXBlIFJwY1Jlc3BvbnNlLFxuICB0eXBlIFJwY1N1Y2Nlc3NSZXNwb25zZSxcbn0gZnJvbSBcIi4vaGFuZGxlclwiO1xuZXhwb3J0IHtcbiAgQ29tbWFuZFJlc3VsdFNjaGVtYSxcbiAgQ29tbWFuZFNjaGVtYSxcbiAgTWVzc2FnZVNjaGVtYSxcbiAgdHlwZSBNZXRob2ROYW1lLFxuICBtZXRob2RzLFxuICBQYXJ0U2NoZW1hLFxuICB0eXBlIFNhbmRib3hDb25maWcsXG4gIFNhbmRib3hDb25maWdTY2hlbWEsXG4gIFNhbmRib3hSZWNvcmRTY2hlbWEsXG4gIFNlc3Npb25TY2hlbWEsXG4gIHR5cGUgU3RvcmFnZU1ldGhvZHMsXG59IGZyb20gXCIuL3JwY1wiO1xuZXhwb3J0IHR5cGUge1xuICBDb21tYW5kLFxuICBMaXN0UmVzdWx0LFxuICBNZXNzYWdlLFxuICBQYXJ0LFxuICBSZXNvbHZlZFN0b3JhZ2UsXG4gIFNhbmRib3hSZWNvcmQsXG4gIFNlc3Npb24sXG4gIFN0b3JhZ2UsXG4gIFN0b3JhZ2VDb25maWcsXG59IGZyb20gXCIuL3R5cGVzXCI7XG4iLCAiaW1wb3J0ICogYXMgcGF0aCBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgdHlwZSB7IFVwbG9hZGFibGVGaWxlIH0gZnJvbSBcIi4uL3NraWxscy90eXBlc1wiO1xuaW1wb3J0IHR5cGUgeyBTYW5kYm94IH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuLyoqXG4gKiBXcml0ZXMgZmlsZXMgdG8gYSBzYW5kYm94IGF0IHRoZSBzcGVjaWZpZWQgZGVzdGluYXRpb24gcGF0aC5cbiAqIFNoZWxsIHNjcmlwdHMgKC5zaCBmaWxlcykgYXJlIGF1dG9tYXRpY2FsbHkgbWFkZSBleGVjdXRhYmxlLlxuICpcbiAqIEZvciBzbWFsbCBmaWxlcyAoPDEwMEtCIHRvdGFsKSwgdXNlcyBzaW5nbGUgZXhlYyB3aXRoIGhlcmVkb2MuXG4gKiBGb3IgbGFyZ2UgZmlsZXMsIHdyaXRlcyBiYXNlNjQgY2h1bmtzIHRoZW4gZGVjb2RlcyB0byBhdm9pZCBBUkdfTUFYIGxpbWl0cy5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHdyaXRlRmlsZXMob3B0czoge1xuICBzYW5kYm94OiBQaWNrPFNhbmRib3gsIFwiZXhlY1wiPjtcbiAgZmlsZXM6IFVwbG9hZGFibGVGaWxlW107XG4gIGRlc3RQYXRoOiBzdHJpbmc7XG59KTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHsgc2FuZGJveCwgZmlsZXMsIGRlc3RQYXRoIH0gPSBvcHRzO1xuXG4gIGlmIChmaWxlcy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCBmaWxlUGF0aHMgPSBmaWxlcy5tYXAoKGZpbGUpID0+IHBhdGgucG9zaXguam9pbihkZXN0UGF0aCwgZmlsZS5wYXRoKSk7XG4gIGNvbnN0IHBhcmVudERpcnMgPSBbLi4ubmV3IFNldChmaWxlUGF0aHMubWFwKChwKSA9PiBwYXRoLnBvc2l4LmRpcm5hbWUocCkpKV07XG4gIGNvbnN0IHNoZWxsU2NyaXB0cyA9IGZpbGVQYXRocy5maWx0ZXIoKHApID0+IHAuZW5kc1dpdGgoXCIuc2hcIikpO1xuXG4gIGNvbnN0IG1rZGlyUmVzdWx0ID0gYXdhaXQgc2FuZGJveC5leGVjKHtcbiAgICBjb21tYW5kOiBcIm1rZGlyXCIsXG4gICAgYXJnczogW1wiLXBcIiwgLi4ucGFyZW50RGlyc10sXG4gIH0pO1xuICBpZiAobWtkaXJSZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgIHRocm93IG1rZGlyUmVzdWx0O1xuICB9XG4gIGF3YWl0IG1rZGlyUmVzdWx0LnJlc3VsdDtcblxuICBjb25zdCBDSFVOS19TSVpFID0gNTBfMDAwO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgZmlsZXMubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBmaWxlID0gZmlsZXNbaV07XG4gICAgY29uc3QgZnVsbFBhdGggPSBmaWxlUGF0aHNbaV07XG4gICAgY29uc3QgYmFzZTY0Q29udGVudCA9IHRvQmFzZTY0KGZpbGUuY29udGVudCk7XG5cbiAgICBpZiAoYmFzZTY0Q29udGVudC5sZW5ndGggPCBDSFVOS19TSVpFKSB7XG4gICAgICBjb25zdCBtYXJrZXIgPSBgRU9GXyR7aX1gO1xuICAgICAgY29uc3QgZXhlY1Jlc3VsdCA9IGF3YWl0IHNhbmRib3guZXhlYyh7XG4gICAgICAgIGNvbW1hbmQ6IFwiYmFzaFwiLFxuICAgICAgICBhcmdzOiBbXG4gICAgICAgICAgXCItY1wiLFxuICAgICAgICAgIGBiYXNlNjQgLWQgPiAke3F1b3RlKGZ1bGxQYXRoKX0gPDwgJyR7bWFya2VyfSdcbiR7YmFzZTY0Q29udGVudH1cbiR7bWFya2VyfWAsXG4gICAgICAgIF0sXG4gICAgICB9KTtcblxuICAgICAgaWYgKGV4ZWNSZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICB0aHJvdyBleGVjUmVzdWx0O1xuICAgICAgfVxuXG4gICAgICBjb25zdCB7IGV4aXRDb2RlLCBzdGRlcnIgfSA9IGF3YWl0IGV4ZWNSZXN1bHQucmVzdWx0O1xuICAgICAgaWYgKGV4aXRDb2RlICE9PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgd3JpdGVGaWxlcyBmYWlsZWQgd2l0aCBleGl0IGNvZGUgJHtleGl0Q29kZX06ICR7c3RkZXJyfWBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgdGVtcEI2NCA9IGAvdG1wL2NodW5rLSR7RGF0ZS5ub3coKX0tJHtpfS5iNjRgO1xuXG4gICAgICBjb25zdCBjbGVhclJlc3VsdCA9IGF3YWl0IHNhbmRib3guZXhlYyh7XG4gICAgICAgIGNvbW1hbmQ6IFwiYmFzaFwiLFxuICAgICAgICBhcmdzOiBbXCItY1wiLCBgPiAke3F1b3RlKHRlbXBCNjQpfWBdLFxuICAgICAgfSk7XG4gICAgICBpZiAoY2xlYXJSZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICB0aHJvdyBjbGVhclJlc3VsdDtcbiAgICAgIH1cbiAgICAgIGF3YWl0IGNsZWFyUmVzdWx0LnJlc3VsdDtcblxuICAgICAgZm9yIChsZXQgb2Zmc2V0ID0gMDsgb2Zmc2V0IDwgYmFzZTY0Q29udGVudC5sZW5ndGg7IG9mZnNldCArPSBDSFVOS19TSVpFKSB7XG4gICAgICAgIGNvbnN0IGNodW5rID0gYmFzZTY0Q29udGVudC5zbGljZShvZmZzZXQsIG9mZnNldCArIENIVU5LX1NJWkUpO1xuICAgICAgICBjb25zdCBtYXJrZXIgPSBgQ0hVTktfJHtvZmZzZXR9YDtcbiAgICAgICAgY29uc3QgYXBwZW5kUmVzdWx0ID0gYXdhaXQgc2FuZGJveC5leGVjKHtcbiAgICAgICAgICBjb21tYW5kOiBcImJhc2hcIixcbiAgICAgICAgICBhcmdzOiBbXG4gICAgICAgICAgICBcIi1jXCIsXG4gICAgICAgICAgICBgY2F0ID4+ICR7cXVvdGUodGVtcEI2NCl9IDw8ICcke21hcmtlcn0nXG4ke2NodW5rfVxuJHttYXJrZXJ9YCxcbiAgICAgICAgICBdLFxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAoYXBwZW5kUmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyBhcHBlbmRSZXN1bHQ7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB7IGV4aXRDb2RlLCBzdGRlcnIgfSA9IGF3YWl0IGFwcGVuZFJlc3VsdC5yZXN1bHQ7XG4gICAgICAgIGlmIChleGl0Q29kZSAhPT0gMCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGB3cml0ZUZpbGVzIGNodW5rIGZhaWxlZCB3aXRoIGV4aXQgY29kZSAke2V4aXRDb2RlfTogJHtzdGRlcnJ9YFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3QgZGVjb2RlUmVzdWx0ID0gYXdhaXQgc2FuZGJveC5leGVjKHtcbiAgICAgICAgY29tbWFuZDogXCJiYXNoXCIsXG4gICAgICAgIGFyZ3M6IFtcbiAgICAgICAgICBcIi1jXCIsXG4gICAgICAgICAgYGJhc2U2NCAtZCA8ICR7cXVvdGUodGVtcEI2NCl9ID4gJHtxdW90ZShmdWxsUGF0aCl9ICYmIHJtIC1mICR7cXVvdGUodGVtcEI2NCl9YCxcbiAgICAgICAgXSxcbiAgICAgIH0pO1xuXG4gICAgICBpZiAoZGVjb2RlUmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgZGVjb2RlUmVzdWx0O1xuICAgICAgfVxuXG4gICAgICBjb25zdCB7IGV4aXRDb2RlLCBzdGRlcnIgfSA9IGF3YWl0IGRlY29kZVJlc3VsdC5yZXN1bHQ7XG4gICAgICBpZiAoZXhpdENvZGUgIT09IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGB3cml0ZUZpbGVzIGRlY29kZSBmYWlsZWQgd2l0aCBleGl0IGNvZGUgJHtleGl0Q29kZX06ICR7c3RkZXJyfWBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBpZiAoc2hlbGxTY3JpcHRzLmxlbmd0aCA+IDApIHtcbiAgICBjb25zdCBjaG1vZFJlc3VsdCA9IGF3YWl0IHNhbmRib3guZXhlYyh7XG4gICAgICBjb21tYW5kOiBcImNobW9kXCIsXG4gICAgICBhcmdzOiBbXCIreFwiLCAuLi5zaGVsbFNjcmlwdHNdLFxuICAgIH0pO1xuICAgIGlmIChjaG1vZFJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICB0aHJvdyBjaG1vZFJlc3VsdDtcbiAgICB9XG4gICAgYXdhaXQgY2htb2RSZXN1bHQucmVzdWx0O1xuICB9XG59XG5cbmZ1bmN0aW9uIHRvQmFzZTY0KGNvbnRlbnQ6IHN0cmluZyB8IEJ1ZmZlcik6IHN0cmluZyB7XG4gIGlmICh0eXBlb2YgY29udGVudCA9PT0gXCJzdHJpbmdcIikge1xuICAgIHJldHVybiBCdWZmZXIuZnJvbShjb250ZW50KS50b1N0cmluZyhcImJhc2U2NFwiKTtcbiAgfVxuICByZXR1cm4gY29udGVudC50b1N0cmluZyhcImJhc2U2NFwiKTtcbn1cblxuZnVuY3Rpb24gcXVvdGUoczogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGAnJHtzLnJlcGxhY2UoLycvZywgXCInXFxcXCcnXCIpfSdgO1xufVxuIiwgImltcG9ydCB0eXBlIHsgQ2hpbGRQcm9jZXNzIH0gZnJvbSBcIm5vZGU6Y2hpbGRfcHJvY2Vzc1wiO1xuaW1wb3J0IHsgc3Bhd24gfSBmcm9tIFwibm9kZTpjaGlsZF9wcm9jZXNzXCI7XG5pbXBvcnQgKiBhcyBlcnJvcmUgZnJvbSBcImVycm9yZVwiO1xuaW1wb3J0IHsgdWxpZCB9IGZyb20gXCJ1bGlkXCI7XG5pbXBvcnQgeyBTYW5kYm94RXJyb3IgfSBmcm9tIFwiLi4vLi4vZXJyb3JzXCI7XG5pbXBvcnQgdHlwZSB7IFNhbmRib3hSZWNvcmQsIFN0b3JhZ2VDb25maWcgfSBmcm9tIFwiLi4vLi4vc3RvcmFnZS90eXBlc1wiO1xuaW1wb3J0IHR5cGUgeyBMb2dFbnRyeSwgU2FuZGJveCB9IGZyb20gXCIuLi90eXBlc1wiO1xuaW1wb3J0IHsgd3JpdGVGaWxlcyB9IGZyb20gXCIuLi93cml0ZS1maWxlc1wiO1xuXG5leHBvcnQgY29uc3QgbG9jYWxTYW5kYm94ID0gKHtcbiAgc2FuZGJveFJlY29yZCxcbn06IHtcbiAgc2FuZGJveFJlY29yZDogU2FuZGJveFJlY29yZCAmIHsgY29uZmlnOiB7IHR5cGU6IFwibG9jYWxcIiB9IH07XG4gIHN0b3JhZ2VDb25maWc6IFN0b3JhZ2VDb25maWc7XG59KTogU2FuZGJveCA9PiB7XG4gIGNvbnN0IGNvbmZpZyA9IHNhbmRib3hSZWNvcmQuY29uZmlnO1xuICBjb25zdCBiYXNlUGF0aCA9IGNvbmZpZy5wYXRoID8/IHByb2Nlc3MuY3dkKCk7XG4gIGNvbnN0IHByb2Nlc3NlcyA9IG5ldyBNYXA8c3RyaW5nLCBDaGlsZFByb2Nlc3M+KCk7XG5cbiAgY29uc3Qgc2FuZGJveDogU2FuZGJveCA9IHtcbiAgICBpZDogc2FuZGJveFJlY29yZC5pZCxcbiAgICBjb25maWc6IHNhbmRib3hSZWNvcmQuY29uZmlnLFxuICAgIGV4ZWM6ICh7IGNvbW1hbmQsIGFyZ3MsIHNpZ25hbCB9KSA9PiB7XG4gICAgICByZXR1cm4gZXJyb3JlLnRyeUFzeW5jKHtcbiAgICAgICAgdHJ5OiAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgY29tbWFuZElkID0gYGNvbW1hbmRfJHt1bGlkKCl9YDtcblxuICAgICAgICAgIGNvbnN0IGNoaWxkID0gc3Bhd24oY29tbWFuZCwgYXJncywge1xuICAgICAgICAgICAgY3dkOiBiYXNlUGF0aCxcbiAgICAgICAgICAgIHNpZ25hbCxcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIHByb2Nlc3Nlcy5zZXQoY29tbWFuZElkLCBjaGlsZCk7XG5cbiAgICAgICAgICBsZXQgc3Rkb3V0ID0gXCJcIjtcbiAgICAgICAgICBsZXQgc3RkZXJyID0gXCJcIjtcbiAgICAgICAgICBjb25zdCBsb2dRdWV1ZTogTG9nRW50cnlbXSA9IFtdO1xuICAgICAgICAgIGxldCBsb2dSZXNvbHZlOiAoKCkgPT4gdm9pZCkgfCBudWxsID0gbnVsbDtcbiAgICAgICAgICBsZXQgY2xvc2VkID0gZmFsc2U7XG5cbiAgICAgICAgICBjaGlsZC5zdGRvdXQub24oXCJkYXRhXCIsIChkYXRhOiBzdHJpbmcgfCBCdWZmZXIpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN0ciA9IFN0cmluZyhkYXRhKTtcbiAgICAgICAgICAgIHN0ZG91dCArPSBzdHI7XG4gICAgICAgICAgICBsb2dRdWV1ZS5wdXNoKHsgc3RyZWFtOiBcInN0ZG91dFwiLCBkYXRhOiBzdHIgfSk7XG4gICAgICAgICAgICBsb2dSZXNvbHZlPy4oKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGNoaWxkLnN0ZGVyci5vbihcImRhdGFcIiwgKGRhdGE6IHN0cmluZyB8IEJ1ZmZlcikgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc3RyID0gU3RyaW5nKGRhdGEpO1xuICAgICAgICAgICAgc3RkZXJyICs9IHN0cjtcbiAgICAgICAgICAgIGxvZ1F1ZXVlLnB1c2goeyBzdHJlYW06IFwic3RkZXJyXCIsIGRhdGE6IHN0ciB9KTtcbiAgICAgICAgICAgIGxvZ1Jlc29sdmU/LigpO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgY29uc3QgcmVzdWx0ID0gbmV3IFByb21pc2U8e1xuICAgICAgICAgICAgc3Rkb3V0OiBzdHJpbmc7XG4gICAgICAgICAgICBzdGRlcnI6IHN0cmluZztcbiAgICAgICAgICAgIGV4aXRDb2RlOiBudW1iZXI7XG4gICAgICAgICAgfT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY2hpbGQub24oXCJlcnJvclwiLCAoZXJyKSA9PiB7XG4gICAgICAgICAgICAgIHByb2Nlc3Nlcy5kZWxldGUoY29tbWFuZElkKTtcbiAgICAgICAgICAgICAgY2xvc2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgbG9nUmVzb2x2ZT8uKCk7XG4gICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGNoaWxkLm9uKFwiY2xvc2VcIiwgKGNvZGU6IG51bWJlciB8IG51bGwpID0+IHtcbiAgICAgICAgICAgICAgcHJvY2Vzc2VzLmRlbGV0ZShjb21tYW5kSWQpO1xuICAgICAgICAgICAgICBjbG9zZWQgPSB0cnVlO1xuICAgICAgICAgICAgICBsb2dSZXNvbHZlPy4oKTtcbiAgICAgICAgICAgICAgcmVzb2x2ZSh7IHN0ZG91dCwgc3RkZXJyLCBleGl0Q29kZTogY29kZSA/PyAwIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBhc3luYyBmdW5jdGlvbiogbG9ncygpOiBBc3luY0l0ZXJhYmxlPExvZ0VudHJ5PiB7XG4gICAgICAgICAgICB3aGlsZSAoIWNsb3NlZCB8fCBsb2dRdWV1ZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGVudHJ5ID0gbG9nUXVldWUuc2hpZnQoKTtcbiAgICAgICAgICAgICAgaWYgKGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgeWllbGQgZW50cnk7XG4gICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWNsb3NlZCkge1xuICAgICAgICAgICAgICAgIGF3YWl0IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlKSA9PiB7XG4gICAgICAgICAgICAgICAgICBsb2dSZXNvbHZlID0gcmVzb2x2ZTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBsb2dSZXNvbHZlID0gbnVsbDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoeyBjb21tYW5kSWQsIGxvZ3MsIHJlc3VsdCB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgY2F0Y2g6IChlOiB1bmtub3duKSA9PlxuICAgICAgICAgIG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSksXG4gICAgICB9KTtcbiAgICB9LFxuXG4gICAgZ2V0RG9tYWluOiAocG9ydCkgPT4ge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShgaHR0cDovL2xvY2FsaG9zdDoke3BvcnR9YCk7XG4gICAgfSxcblxuICAgIGtpbGw6IGFzeW5jICh7IGNvbW1hbmRJZCwgc3RvcmFnZSB9KSA9PiB7XG4gICAgICBjb25zdCBjaGlsZCA9IHByb2Nlc3Nlcy5nZXQoY29tbWFuZElkKTtcbiAgICAgIGlmICghY2hpbGQpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBTYW5kYm94RXJyb3Ioe1xuICAgICAgICAgIHJlYXNvbjogYENvbW1hbmQgJHtjb21tYW5kSWR9IG5vdCBmb3VuZCBvciBhbHJlYWR5IGZpbmlzaGVkYCxcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGNoaWxkLmtpbGwoXCJTSUdURVJNXCIpO1xuXG4gICAgICBjb25zdCBjbWQgPSBhd2FpdCBzdG9yYWdlLmNvbW1hbmQuZ2V0KGNvbW1hbmRJZCk7XG4gICAgICBpZiAoY21kIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IGNtZC5tZXNzYWdlLCBjYXVzZTogY21kIH0pO1xuICAgICAgfVxuICAgICAgaWYgKGNtZCAmJiBjbWQuc3RhdHVzID09PSBcInJ1bm5pbmdcIikge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzdG9yYWdlLmNvbW1hbmQuc2V0KHtcbiAgICAgICAgICAuLi5jbWQsXG4gICAgICAgICAgc3RhdHVzOiBcImtpbGxlZFwiLFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IHJlc3VsdC5tZXNzYWdlLCBjYXVzZTogcmVzdWx0IH0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcblxuICAgIHdyaXRlRmlsZXM6IChvcHRzKSA9PiB3cml0ZUZpbGVzKHsgc2FuZGJveCwgLi4ub3B0cyB9KSxcbiAgfTtcblxuICByZXR1cm4gc2FuZGJveDtcbn07XG4iLCAiaW1wb3J0ICogYXMgZXJyb3JlIGZyb20gXCJlcnJvcmVcIjtcbmltcG9ydCB7IFNhbmRib3ggYXMgVmVyY2VsU2FuZGJveFNESyB9IGZyb20gXCJzYW5kYm94XCI7XG5pbXBvcnQgeyBTYW5kYm94RXJyb3IgfSBmcm9tIFwiLi4vLi4vZXJyb3JzXCI7XG5pbXBvcnQge1xuICBnZXRTdG9yYWdlLFxuICB0eXBlIFNhbmRib3hSZWNvcmQsXG4gIHR5cGUgU3RvcmFnZSxcbiAgdHlwZSBTdG9yYWdlQ29uZmlnLFxufSBmcm9tIFwiLi4vLi4vc3RvcmFnZVwiO1xuaW1wb3J0IHR5cGUge1xuICBMb2dFbnRyeSxcbiAgU2FuZGJveCxcbiAgU2FuZGJveExpZmVjeWNsZSxcbiAgU2FuZGJveFN0YXR1cyxcbn0gZnJvbSBcIi4uL3R5cGVzXCI7XG5pbXBvcnQgeyB3cml0ZUZpbGVzIH0gZnJvbSBcIi4uL3dyaXRlLWZpbGVzXCI7XG5cbmV4cG9ydCB0eXBlIFZlcmNlbFNhbmRib3hDcmVhdGVPcHRpb25zID0gRXh0cmFjdDxcbiAgUGFyYW1ldGVyczx0eXBlb2YgVmVyY2VsU2FuZGJveFNESy5jcmVhdGU+WzBdLFxuICAvLyBiaW9tZS1pZ25vcmUgbGludC9jb21wbGV4aXR5L25vQmFubmVkVHlwZXM6IC5cbiAge31cbj47XG5cbmV4cG9ydCBjb25zdCBWRVJDRUxfTUFYX1RJTUVPVVRfTVMgPSA1ICogNjAgKiA2MCAqIDEwMDA7IC8vIDUgaG91cnNcbmNvbnN0IExPQ0tfVElNRU9VVF9NUyA9IDMwXzAwMDsgLy8gMzAgc2Vjb25kcyAtIGlmIGxvY2sgb2xkZXIgdGhhbiB0aGlzLCBjb25zaWRlciBpdCBzdGFsZVxuY29uc3QgTE9DS19QT0xMX0lOVEVSVkFMX01TID0gMjAwO1xuXG5jb25zdCBnZXRUZXN0Q3JlZGVudGlhbHMgPSAoKSA9PlxuICBwcm9jZXNzLmVudi5OT0RFX0VOViA9PT0gXCJ0ZXN0XCJcbiAgICA/IHtcbiAgICAgICAgdG9rZW46IHByb2Nlc3MuZW52LlRFU1RfVkVSQ0VMX1RPS0VOLFxuICAgICAgICB0ZWFtSWQ6IHByb2Nlc3MuZW52LlRFU1RfVkVSQ0VMX1RFQU1fSUQsXG4gICAgICAgIHByb2plY3RJZDogcHJvY2Vzcy5lbnYuVEVTVF9WRVJDRUxfUFJPSkVDVF9JRCxcbiAgICAgIH1cbiAgICA6IHt9O1xuXG4vKipcbiAqIE1vZHVsZS1sZXZlbCBjYWNoZSBmb3IgaW4tZmxpZ2h0IHNhbmRib3ggY3JlYXRpb24gcHJvbWlzZXMuXG4gKiBQcmV2ZW50cyBwYXJhbGxlbCByZXF1ZXN0cyB3aXRoaW4gdGhlIHNhbWUgcHJvY2VzcyBmcm9tIGNyZWF0aW5nIGR1cGxpY2F0ZSBzYW5kYm94ZXMuXG4gKi9cbmNvbnN0IGNyZWF0ZVByb21pc2VzID0gbmV3IE1hcDxzdHJpbmcsIFByb21pc2U8U2FuZGJveEVycm9yIHwgc3RyaW5nPj4oKTtcblxuY29uc3QgQUNUSVZJVFlfVEhST1RUTEVfTVMgPSAxMF8wMDA7XG5jb25zdCBsYXN0QWN0aXZpdHlTZW50ID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKTtcblxuY29uc3QgREVGQVVMVF9WQ1BVUyA9IDI7XG5cbmV4cG9ydCBjb25zdCB2ZXJjZWxTYW5kYm94ID0gKHtcbiAgc2FuZGJveFJlY29yZCxcbiAgc3RvcmFnZUNvbmZpZyxcbiAgZW5hYmxlTGlmZWN5Y2xlV29ya2Zsb3cgPSB0cnVlLFxuICBzdG9yYWdlOiBzdG9yYWdlT3ZlcnJpZGUsXG59OiB7XG4gIHNhbmRib3hSZWNvcmQ6IFNhbmRib3hSZWNvcmQgJiB7IGNvbmZpZzogeyB0eXBlOiBcInZlcmNlbFwiIH0gfTtcbiAgc3RvcmFnZUNvbmZpZzogU3RvcmFnZUNvbmZpZztcbiAgZW5hYmxlTGlmZWN5Y2xlV29ya2Zsb3c/OiBib29sZWFuO1xuICBzdG9yYWdlPzogU3RvcmFnZTtcbn0pOiBTYW5kYm94ID0+IHtcbiAgY29uc3QgeyBpZCwgY29uZmlnIH0gPSBzYW5kYm94UmVjb3JkO1xuICBjb25zdCB2Y3B1cyA9IGNvbmZpZy5yZXNvdXJjZXM/LnZjcHVzID8/IERFRkFVTFRfVkNQVVM7XG4gIGNvbnN0IHBvcnRzID0gY29uZmlnLnBvcnRzO1xuICBjb25zdCBzdG9yYWdlID0gc3RvcmFnZU92ZXJyaWRlID8/IGdldFN0b3JhZ2Uoc3RvcmFnZUNvbmZpZyk7XG4gIGNvbnN0IGluaXRpYWxWZXJjZWwgPVxuICAgIHNhbmRib3hSZWNvcmQucHJvdmlkZXJNZXRhZGF0YT8ucHJvdmlkZXIgPT09IFwidmVyY2VsXCJcbiAgICAgID8gc2FuZGJveFJlY29yZC5wcm92aWRlck1ldGFkYXRhXG4gICAgICA6IG51bGw7XG5cbiAgdHlwZSBTYW5kYm94SW5zdGFuY2UgPSBBd2FpdGVkPFJldHVyblR5cGU8dHlwZW9mIFZlcmNlbFNhbmRib3hTREsuZ2V0Pj47XG4gIGxldCBzYW5kYm94UHJvbWlzZTogUHJvbWlzZTxTYW5kYm94RXJyb3IgfCBTYW5kYm94SW5zdGFuY2U+IHwgbnVsbCA9IG51bGw7XG5cbiAgYXN5bmMgZnVuY3Rpb24gcG9sbEZvclNhbmRib3hJZCgpOiBQcm9taXNlPFNhbmRib3hFcnJvciB8IHN0cmluZz4ge1xuICAgIGNvbnN0IGRlYWRsaW5lID0gRGF0ZS5ub3coKSArIExPQ0tfVElNRU9VVF9NUztcbiAgICB3aGlsZSAoRGF0ZS5ub3coKSA8IGRlYWRsaW5lKSB7XG4gICAgICBhd2FpdCBuZXcgUHJvbWlzZSgocikgPT4gc2V0VGltZW91dChyLCBMT0NLX1BPTExfSU5URVJWQUxfTVMpKTtcbiAgICAgIGNvbnN0IHJlY29yZCA9IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5nZXQoaWQpO1xuICAgICAgaWYgKHJlY29yZCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHJldHVybiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiByZWNvcmQubWVzc2FnZSwgY2F1c2U6IHJlY29yZCB9KTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHZlcmNlbFNhbmRib3hJZCA9XG4gICAgICAgIHJlY29yZD8ucHJvdmlkZXJNZXRhZGF0YT8ucHJvdmlkZXIgPT09IFwidmVyY2VsXCJcbiAgICAgICAgICA/IHJlY29yZC5wcm92aWRlck1ldGFkYXRhLnNhbmRib3hJZFxuICAgICAgICAgIDogbnVsbDtcbiAgICAgIGlmICh2ZXJjZWxTYW5kYm94SWQpIHtcbiAgICAgICAgcmV0dXJuIHZlcmNlbFNhbmRib3hJZDtcbiAgICAgIH1cbiAgICAgIGlmICghcmVjb3JkPy5hY3F1aXJpbmdMb2NrQXQpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBuZXcgU2FuZGJveEVycm9yKHtcbiAgICAgIHJlYXNvbjogXCJUaW1lZCBvdXQgd2FpdGluZyBmb3Igc2FuZGJveCBjcmVhdGlvbiBieSBhbm90aGVyIHByb2Nlc3NcIixcbiAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVNhbmRib3hGcm9tU25hcHNob3QoXG4gICAgc25hcHNob3RJZDogc3RyaW5nXG4gICk6IFByb21pc2U8U2FuZGJveEVycm9yIHwgc3RyaW5nPiB7XG4gICAgcmV0dXJuIGF3YWl0IGVycm9yZS50cnlBc3luYyh7XG4gICAgICB0cnk6IGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc3Qgc2FuZGJveCA9IGF3YWl0IFZlcmNlbFNhbmRib3hTREsuY3JlYXRlKHtcbiAgICAgICAgICBzb3VyY2U6IHsgdHlwZTogXCJzbmFwc2hvdFwiLCBzbmFwc2hvdElkIH0sXG4gICAgICAgICAgcmVzb3VyY2VzOiB7IHZjcHVzIH0sXG4gICAgICAgICAgdGltZW91dDogVkVSQ0VMX01BWF9USU1FT1VUX01TLFxuICAgICAgICAgIHBvcnRzLFxuICAgICAgICAgIC4uLmdldFRlc3RDcmVkZW50aWFscygpLFxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgYXdhaXQgc3RvcmFnZS5zYW5kYm94LnNldCh7XG4gICAgICAgICAgaWQsXG4gICAgICAgICAgY29uZmlnLFxuICAgICAgICAgIGNyZWF0ZWRBdDogbm93LFxuICAgICAgICAgIGxhc3RBY3Rpdml0eUF0OiBub3csXG4gICAgICAgICAgYWNxdWlyaW5nTG9ja0lkOiBudWxsLFxuICAgICAgICAgIGFjcXVpcmluZ0xvY2tBdDogbnVsbCxcbiAgICAgICAgICBwcm92aWRlck1ldGFkYXRhOiB7XG4gICAgICAgICAgICBwcm92aWRlcjogXCJ2ZXJjZWxcIixcbiAgICAgICAgICAgIHNhbmRib3hJZDogc2FuZGJveC5zYW5kYm94SWQsXG4gICAgICAgICAgICBzbmFwc2hvdElkLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gc2FuZGJveC5zYW5kYm94SWQ7XG4gICAgICB9LFxuICAgICAgY2F0Y2g6IChlKSA9PiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pLFxuICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gY3JlYXRlRnJlc2hTYW5kYm94KCk6IFByb21pc2U8U2FuZGJveEVycm9yIHwgc3RyaW5nPiB7XG4gICAgcmV0dXJuIGF3YWl0IGVycm9yZS50cnlBc3luYyh7XG4gICAgICB0cnk6IGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc3Qgc2FuZGJveCA9IGF3YWl0IFZlcmNlbFNhbmRib3hTREsuY3JlYXRlKHtcbiAgICAgICAgICByZXNvdXJjZXM6IHsgdmNwdXMgfSxcbiAgICAgICAgICB0aW1lb3V0OiBWRVJDRUxfTUFYX1RJTUVPVVRfTVMsXG4gICAgICAgICAgcG9ydHMsXG4gICAgICAgICAgLi4uZ2V0VGVzdENyZWRlbnRpYWxzKCksXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgICBhd2FpdCBzdG9yYWdlLnNhbmRib3guc2V0KHtcbiAgICAgICAgICBpZCxcbiAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgY3JlYXRlZEF0OiBub3csXG4gICAgICAgICAgbGFzdEFjdGl2aXR5QXQ6IG5vdyxcbiAgICAgICAgICBhY3F1aXJpbmdMb2NrSWQ6IG51bGwsXG4gICAgICAgICAgYWNxdWlyaW5nTG9ja0F0OiBudWxsLFxuICAgICAgICAgIHByb3ZpZGVyTWV0YWRhdGE6IHtcbiAgICAgICAgICAgIHByb3ZpZGVyOiBcInZlcmNlbFwiLFxuICAgICAgICAgICAgc2FuZGJveElkOiBzYW5kYm94LnNhbmRib3hJZCxcbiAgICAgICAgICAgIHNuYXBzaG90SWQ6IG51bGwsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBzYW5kYm94LnNhbmRib3hJZDtcbiAgICAgIH0sXG4gICAgICBjYXRjaDogKGUpID0+IG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSksXG4gICAgfSk7XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBkb0dldE9yQ3JlYXRlU2FuZGJveElkKCk6IFByb21pc2U8U2FuZGJveEVycm9yIHwgc3RyaW5nPiB7XG4gICAgaWYgKGluaXRpYWxWZXJjZWw/LnNhbmRib3hJZCkge1xuICAgICAgcmV0dXJuIGluaXRpYWxWZXJjZWwuc2FuZGJveElkO1xuICAgIH1cblxuICAgIGNvbnN0IGV4aXN0aW5nID0gYXdhaXQgc3RvcmFnZS5zYW5kYm94LmdldChpZCk7XG4gICAgaWYgKGV4aXN0aW5nIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIHJldHVybiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBleGlzdGluZy5tZXNzYWdlLCBjYXVzZTogZXhpc3RpbmcgfSk7XG4gICAgfVxuXG4gICAgY29uc3QgZXhpc3RpbmdWZXJjZWwgPVxuICAgICAgZXhpc3Rpbmc/LnByb3ZpZGVyTWV0YWRhdGE/LnByb3ZpZGVyID09PSBcInZlcmNlbFwiXG4gICAgICAgID8gZXhpc3RpbmcucHJvdmlkZXJNZXRhZGF0YVxuICAgICAgICA6IG51bGw7XG5cbiAgICBpZiAoZXhpc3RpbmdWZXJjZWw/LnNhbmRib3hJZCkge1xuICAgICAgcmV0dXJuIGV4aXN0aW5nVmVyY2VsLnNhbmRib3hJZDtcbiAgICB9XG5cbiAgICBjb25zdCBoYXNBY3RpdmVMb2NrID1cbiAgICAgIGV4aXN0aW5nPy5hY3F1aXJpbmdMb2NrSWQgJiZcbiAgICAgIGV4aXN0aW5nLmFjcXVpcmluZ0xvY2tBdCAmJlxuICAgICAgRGF0ZS5ub3coKSAtIGV4aXN0aW5nLmFjcXVpcmluZ0xvY2tBdCA8IExPQ0tfVElNRU9VVF9NUztcblxuICAgIGlmIChoYXNBY3RpdmVMb2NrKSB7XG4gICAgICByZXR1cm4gcG9sbEZvclNhbmRib3hJZCgpO1xuICAgIH1cblxuICAgIGNvbnN0IGxvY2tJZCA9IGNyeXB0by5yYW5kb21VVUlEKCk7XG4gICAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgICBhd2FpdCBzdG9yYWdlLnNhbmRib3guc2V0KHtcbiAgICAgIGlkLFxuICAgICAgY29uZmlnLFxuICAgICAgY3JlYXRlZEF0OiBleGlzdGluZz8uY3JlYXRlZEF0ID8/IHNhbmRib3hSZWNvcmQuY3JlYXRlZEF0LFxuICAgICAgbGFzdEFjdGl2aXR5QXQ6IGV4aXN0aW5nPy5sYXN0QWN0aXZpdHlBdCA/PyBzYW5kYm94UmVjb3JkLmxhc3RBY3Rpdml0eUF0LFxuICAgICAgYWNxdWlyaW5nTG9ja0lkOiBsb2NrSWQsXG4gICAgICBhY3F1aXJpbmdMb2NrQXQ6IG5vdyxcbiAgICAgIHByb3ZpZGVyTWV0YWRhdGE6IHtcbiAgICAgICAgcHJvdmlkZXI6IFwidmVyY2VsXCIsXG4gICAgICAgIHNhbmRib3hJZDogbnVsbCxcbiAgICAgICAgc25hcHNob3RJZDpcbiAgICAgICAgICBleGlzdGluZ1ZlcmNlbD8uc25hcHNob3RJZCA/PyBpbml0aWFsVmVyY2VsPy5zbmFwc2hvdElkID8/IG51bGwsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgY29uc3QgYWZ0ZXJMb2NrID0gYXdhaXQgc3RvcmFnZS5zYW5kYm94LmdldChpZCk7XG4gICAgaWYgKGFmdGVyTG9jayBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICByZXR1cm4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogYWZ0ZXJMb2NrLm1lc3NhZ2UsIGNhdXNlOiBhZnRlckxvY2sgfSk7XG4gICAgfVxuICAgIGlmIChhZnRlckxvY2s/LmFjcXVpcmluZ0xvY2tJZCAhPT0gbG9ja0lkKSB7XG4gICAgICByZXR1cm4gcG9sbEZvclNhbmRib3hJZCgpO1xuICAgIH1cblxuICAgIGNvbnN0IHNuYXBzaG90SWQgPVxuICAgICAgZXhpc3RpbmdWZXJjZWw/LnNuYXBzaG90SWQgPz9cbiAgICAgIGluaXRpYWxWZXJjZWw/LnNuYXBzaG90SWQgPz9cbiAgICAgIGNvbmZpZy5saWZlY3ljbGU/LnNuYXBzaG90SWQ7XG4gICAgaWYgKHNuYXBzaG90SWQpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNyZWF0ZVNhbmRib3hGcm9tU25hcHNob3Qoc25hcHNob3RJZCk7XG4gICAgICBpZiAoIShyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikpIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY3JlYXRlRnJlc2hTYW5kYm94KCk7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRPckNyZWF0ZVNhbmRib3hJZCgpOiBQcm9taXNlPFNhbmRib3hFcnJvciB8IHN0cmluZz4ge1xuICAgIGNvbnN0IGNhY2hlZCA9IGNyZWF0ZVByb21pc2VzLmdldChpZCk7XG4gICAgaWYgKGNhY2hlZCkge1xuICAgICAgcmV0dXJuIGNhY2hlZDtcbiAgICB9XG5cbiAgICBjb25zdCBwcm9taXNlID0gZG9HZXRPckNyZWF0ZVNhbmRib3hJZCgpLmZpbmFsbHkoKCkgPT4ge1xuICAgICAgY3JlYXRlUHJvbWlzZXMuZGVsZXRlKGlkKTtcbiAgICB9KTtcbiAgICBjcmVhdGVQcm9taXNlcy5zZXQoaWQsIHByb21pc2UpO1xuICAgIHJldHVybiBwcm9taXNlO1xuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gZG9HZXRTYW5kYm94KCk6IFByb21pc2U8U2FuZGJveEVycm9yIHwgU2FuZGJveEluc3RhbmNlPiB7XG4gICAgY29uc3QgdmVyY2VsU2FuZGJveElkID0gYXdhaXQgZ2V0T3JDcmVhdGVTYW5kYm94SWQoKTtcbiAgICBpZiAodmVyY2VsU2FuZGJveElkIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIHJldHVybiB2ZXJjZWxTYW5kYm94SWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGVycm9yZS50cnlBc3luYyh7XG4gICAgICB0cnk6ICgpID0+XG4gICAgICAgIFZlcmNlbFNhbmRib3hTREsuZ2V0KHtcbiAgICAgICAgICBzYW5kYm94SWQ6IHZlcmNlbFNhbmRib3hJZCxcbiAgICAgICAgICAuLi5nZXRUZXN0Q3JlZGVudGlhbHMoKSxcbiAgICAgICAgfSksXG4gICAgICBjYXRjaDogKGUpID0+IG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSksXG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRTYW5kYm94KCk6IFByb21pc2U8U2FuZGJveEVycm9yIHwgU2FuZGJveEluc3RhbmNlPiB7XG4gICAgaWYgKCFzYW5kYm94UHJvbWlzZSkge1xuICAgICAgc2FuZGJveFByb21pc2UgPSBkb0dldFNhbmRib3goKTtcbiAgICB9XG4gICAgcmV0dXJuIHNhbmRib3hQcm9taXNlO1xuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gdXBkYXRlTGFzdEFjdGl2aXR5KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gICAgY29uc3QgbGFzdFNlbnQgPSBsYXN0QWN0aXZpdHlTZW50LmdldChpZCk7XG4gICAgaWYgKGxhc3RTZW50ICYmIG5vdyAtIGxhc3RTZW50IDwgQUNUSVZJVFlfVEhST1RUTEVfTVMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgbGFzdEFjdGl2aXR5U2VudC5zZXQoaWQsIG5vdyk7XG5cbiAgICBjb25zdCBleGlzdGluZyA9IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5nZXQoaWQpO1xuICAgIGlmIChleGlzdGluZyBpbnN0YW5jZW9mIEVycm9yIHx8ICFleGlzdGluZykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBleGlzdGluZ1ZlcmNlbCA9XG4gICAgICBleGlzdGluZy5wcm92aWRlck1ldGFkYXRhPy5wcm92aWRlciA9PT0gXCJ2ZXJjZWxcIlxuICAgICAgICA/IGV4aXN0aW5nLnByb3ZpZGVyTWV0YWRhdGFcbiAgICAgICAgOiBudWxsO1xuICAgIGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5zZXQoe1xuICAgICAgaWQ6IGV4aXN0aW5nLmlkLFxuICAgICAgY29uZmlnOiBleGlzdGluZy5jb25maWcsXG4gICAgICBjcmVhdGVkQXQ6IGV4aXN0aW5nLmNyZWF0ZWRBdCxcbiAgICAgIGxhc3RBY3Rpdml0eUF0OiBub3csXG4gICAgICBhY3F1aXJpbmdMb2NrSWQ6IG51bGwsXG4gICAgICBhY3F1aXJpbmdMb2NrQXQ6IG51bGwsXG4gICAgICBwcm92aWRlck1ldGFkYXRhOiBleGlzdGluZ1ZlcmNlbCA/PyB7XG4gICAgICAgIHByb3ZpZGVyOiBcInZlcmNlbFwiLFxuICAgICAgICBzYW5kYm94SWQ6IG51bGwsXG4gICAgICAgIHNuYXBzaG90SWQ6IG51bGwsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgaWYgKGVuYWJsZUxpZmVjeWNsZVdvcmtmbG93KSB7XG4gICAgICAvLyB0b2RvIHJlLWVuYWJsZSBvbmNlIHdlIGZpZ3VyZSBvdXQgd2h5IHdvcmtmbG93IHRocm93cyBhIGJ1bmNoIG9mIGVycm9ycyBpbiBkZXZcbiAgICAgIC8vIGNvbnN0IGxpZmVjeWNsZUlucHV0OiBTYW5kYm94TGlmZWN5Y2xlSW5wdXQgPSB7XG4gICAgICAvLyAgIGlkLFxuICAgICAgLy8gICBzdG9yYWdlQ29uZmlnLFxuICAgICAgLy8gICBpbml0aWFsQ29uZmlnOiBjb25maWcsXG4gICAgICAvLyB9O1xuICAgICAgLy8gdHJ5IHtcbiAgICAgIC8vICAgYXdhaXQgc2FuZGJveEFjdGl2aXR5SG9vay5yZXN1bWUoaWQsIHtcbiAgICAgIC8vICAgICB0eXBlOiBcImFjdGl2aXR5XCIsXG4gICAgICAvLyAgICAgbmV3Q29uZmlnOiBjb25maWcsXG4gICAgICAvLyAgIH0pO1xuICAgICAgLy8gfSBjYXRjaCB7XG4gICAgICAvLyAgIGF3YWl0IHN0YXJ0KHNhbmRib3hMaWZlY3ljbGVXb3JrZmxvdywgW3sgaW5wdXQ6IGxpZmVjeWNsZUlucHV0IH1dKTtcbiAgICAgIC8vIH1cbiAgICB9XG4gIH1cblxuICBjb25zdCBsaWZlY3ljbGU6IFNhbmRib3hMaWZlY3ljbGUgPSB7XG4gICAgc3RhcnQ6IGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHNhbmRib3ggPSBhd2FpdCBnZXRTYW5kYm94KCk7XG4gICAgICBpZiAoc2FuZGJveCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHJldHVybiBzYW5kYm94O1xuICAgICAgfVxuICAgICAgYXdhaXQgdXBkYXRlTGFzdEFjdGl2aXR5KCk7XG4gICAgICByZXR1cm4gc2FuZGJveC5zdGF0dXMgYXMgU2FuZGJveFN0YXR1cztcbiAgICB9LFxuXG4gICAgc25hcHNob3Q6IGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHNhbmRib3ggPSBhd2FpdCBnZXRTYW5kYm94KCk7XG4gICAgICBpZiAoc2FuZGJveCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHJldHVybiBzYW5kYm94O1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gZXJyb3JlLnRyeUFzeW5jKHtcbiAgICAgICAgdHJ5OiBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgZXhpc3RpbmcgPSBhd2FpdCBzdG9yYWdlLnNhbmRib3guZ2V0KGlkKTtcbiAgICAgICAgICBjb25zdCBzbmFwc2hvdCA9IGF3YWl0IHNhbmRib3guc25hcHNob3QoKTtcbiAgICAgICAgICBhd2FpdCBzdG9yYWdlLnNhbmRib3guc2V0KHtcbiAgICAgICAgICAgIGlkLFxuICAgICAgICAgICAgY29uZmlnLFxuICAgICAgICAgICAgY3JlYXRlZEF0OlxuICAgICAgICAgICAgICBleGlzdGluZyBpbnN0YW5jZW9mIEVycm9yID8gbnVsbCA6IGV4aXN0aW5nPy5jcmVhdGVkQXQgPz8gbnVsbCxcbiAgICAgICAgICAgIGxhc3RBY3Rpdml0eUF0OlxuICAgICAgICAgICAgICBleGlzdGluZyBpbnN0YW5jZW9mIEVycm9yXG4gICAgICAgICAgICAgICAgPyBudWxsXG4gICAgICAgICAgICAgICAgOiBleGlzdGluZz8ubGFzdEFjdGl2aXR5QXQgPz8gbnVsbCxcbiAgICAgICAgICAgIGFjcXVpcmluZ0xvY2tJZDogbnVsbCxcbiAgICAgICAgICAgIGFjcXVpcmluZ0xvY2tBdDogbnVsbCxcbiAgICAgICAgICAgIHByb3ZpZGVyTWV0YWRhdGE6IHtcbiAgICAgICAgICAgICAgcHJvdmlkZXI6IFwidmVyY2VsXCIsXG4gICAgICAgICAgICAgIHNhbmRib3hJZDogbnVsbCxcbiAgICAgICAgICAgICAgc25hcHNob3RJZDogc25hcHNob3Quc25hcHNob3RJZCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuIHsgc25hcHNob3RJZDogc25hcHNob3Quc25hcHNob3RJZCB9O1xuICAgICAgICB9LFxuICAgICAgICBjYXRjaDogKGUpID0+IG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSksXG4gICAgICB9KTtcbiAgICB9LFxuXG4gICAgc3RvcDogYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qgc2FuZGJveCA9IGF3YWl0IGdldFNhbmRib3goKTtcbiAgICAgIGlmIChzYW5kYm94IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIHNhbmRib3g7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBlcnJvcmUudHJ5QXN5bmMoe1xuICAgICAgICB0cnk6IGFzeW5jICgpID0+IHtcbiAgICAgICAgICBhd2FpdCBzYW5kYm94LnN0b3AoKTtcbiAgICAgICAgICBjb25zdCBleGlzdGluZyA9IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5nZXQoaWQpO1xuICAgICAgICAgIGlmIChleGlzdGluZyBpbnN0YW5jZW9mIEVycm9yIHx8ICFleGlzdGluZykge1xuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICB9XG4gICAgICAgICAgYXdhaXQgc3RvcmFnZS5zYW5kYm94LnNldCh7XG4gICAgICAgICAgICBpZDogZXhpc3RpbmcuaWQsXG4gICAgICAgICAgICBjb25maWc6IGV4aXN0aW5nLmNvbmZpZyxcbiAgICAgICAgICAgIGNyZWF0ZWRBdDogZXhpc3RpbmcuY3JlYXRlZEF0LFxuICAgICAgICAgICAgbGFzdEFjdGl2aXR5QXQ6IGV4aXN0aW5nLmxhc3RBY3Rpdml0eUF0LFxuICAgICAgICAgICAgYWNxdWlyaW5nTG9ja0lkOiBudWxsLFxuICAgICAgICAgICAgYWNxdWlyaW5nTG9ja0F0OiBudWxsLFxuICAgICAgICAgICAgcHJvdmlkZXJNZXRhZGF0YToge1xuICAgICAgICAgICAgICBwcm92aWRlcjogXCJ2ZXJjZWxcIixcbiAgICAgICAgICAgICAgc2FuZGJveElkOiBudWxsLFxuICAgICAgICAgICAgICBzbmFwc2hvdElkOiBudWxsLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB9LFxuICAgICAgICBjYXRjaDogKGUpID0+IG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSksXG4gICAgICB9KTtcbiAgICB9LFxuXG4gICAgZ2V0U3RhdHVzOiBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzYW5kYm94ID0gYXdhaXQgZ2V0U2FuZGJveCgpO1xuICAgICAgaWYgKHNhbmRib3ggaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICByZXR1cm4gc2FuZGJveDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBzYW5kYm94LnN0YXR1cyBhcyBTYW5kYm94U3RhdHVzO1xuICAgIH0sXG5cbiAgICBnZXRDcmVhdGVkQXQ6IGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHNhbmRib3ggPSBhd2FpdCBnZXRTYW5kYm94KCk7XG4gICAgICBpZiAoc2FuZGJveCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHJldHVybiBzYW5kYm94O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHNhbmRib3guY3JlYXRlZEF0O1xuICAgIH0sXG5cbiAgICBnZXRSZW1haW5pbmdUaW1lb3V0OiBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzYW5kYm94ID0gYXdhaXQgZ2V0U2FuZGJveCgpO1xuICAgICAgaWYgKHNhbmRib3ggaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICByZXR1cm4gc2FuZGJveDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBzYW5kYm94LnRpbWVvdXQ7XG4gICAgfSxcbiAgfTtcblxuICBjb25zdCBzYW5kYm94OiBTYW5kYm94ID0ge1xuICAgIGlkLFxuICAgIGNvbmZpZyxcbiAgICBleGVjOiBhc3luYyAoeyBjb21tYW5kLCBhcmdzLCBzaWduYWwgfSkgPT4ge1xuICAgICAgY29uc3QgaW5zdGFuY2UgPSBhd2FpdCBnZXRTYW5kYm94KCk7XG4gICAgICBpZiAoaW5zdGFuY2UgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICByZXR1cm4gaW5zdGFuY2U7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHVwZGF0ZVByb21pc2UgPSB1cGRhdGVMYXN0QWN0aXZpdHkoKTtcblxuICAgICAgY29uc3QgZXhlY1Jlc3VsdCA9IGF3YWl0IGVycm9yZS50cnlBc3luYyh7XG4gICAgICAgIHRyeTogYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IG91dHB1dCA9IGF3YWl0IGluc3RhbmNlLnJ1bkNvbW1hbmQoY29tbWFuZCwgYXJncywgeyBzaWduYWwgfSk7XG5cbiAgICAgICAgICBsZXQgc3Rkb3V0ID0gXCJcIjtcbiAgICAgICAgICBsZXQgc3RkZXJyID0gXCJcIjtcbiAgICAgICAgICBjb25zdCBsb2dCdWZmZXI6IExvZ0VudHJ5W10gPSBbXTtcbiAgICAgICAgICBjb25zdCBzdGF0ZSA9IHtcbiAgICAgICAgICAgIHJlc29sdmU6IG51bGwgYXMgKCgpID0+IHZvaWQpIHwgbnVsbCxcbiAgICAgICAgICAgIGNvbnN1bWVkOiBmYWxzZSxcbiAgICAgICAgICB9O1xuXG4gICAgICAgICAgY29uc3QgY29uc3VtZUxvZ3MgPSAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgZm9yIGF3YWl0IChjb25zdCBsb2cgb2Ygb3V0cHV0LmxvZ3MoKSkge1xuICAgICAgICAgICAgICBjb25zdCBlbnRyeTogTG9nRW50cnkgPVxuICAgICAgICAgICAgICAgIGxvZy5zdHJlYW0gPT09IFwic3Rkb3V0XCJcbiAgICAgICAgICAgICAgICAgID8geyBzdHJlYW06IFwic3Rkb3V0XCIsIGRhdGE6IGxvZy5kYXRhIH1cbiAgICAgICAgICAgICAgICAgIDogeyBzdHJlYW06IFwic3RkZXJyXCIsIGRhdGE6IGxvZy5kYXRhIH07XG5cbiAgICAgICAgICAgICAgaWYgKGxvZy5zdHJlYW0gPT09IFwic3Rkb3V0XCIpIHtcbiAgICAgICAgICAgICAgICBzdGRvdXQgKz0gbG9nLmRhdGE7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc3RkZXJyICs9IGxvZy5kYXRhO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgbG9nQnVmZmVyLnB1c2goZW50cnkpO1xuICAgICAgICAgICAgICBzdGF0ZS5yZXNvbHZlPy4oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHN0YXRlLmNvbnN1bWVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHN0YXRlLnJlc29sdmU/LigpO1xuICAgICAgICAgIH0pKCk7XG5cbiAgICAgICAgICBhc3luYyBmdW5jdGlvbiogbG9ncygpOiBBc3luY0l0ZXJhYmxlPExvZ0VudHJ5PiB7XG4gICAgICAgICAgICBsZXQgaW5kZXggPSAwO1xuICAgICAgICAgICAgd2hpbGUgKCFzdGF0ZS5jb25zdW1lZCB8fCBpbmRleCA8IGxvZ0J1ZmZlci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgaWYgKGluZGV4IDwgbG9nQnVmZmVyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHlpZWxkIGxvZ0J1ZmZlcltpbmRleCsrXTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgc3RhdGUucmVzb2x2ZSA9IHJlc29sdmU7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgc3RhdGUucmVzb2x2ZSA9IG51bGw7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCByZXN1bHQgPSBjb25zdW1lTG9ncy50aGVuKCgpID0+ICh7XG4gICAgICAgICAgICBzdGRvdXQsXG4gICAgICAgICAgICBzdGRlcnIsXG4gICAgICAgICAgICBleGl0Q29kZTogb3V0cHV0LmV4aXRDb2RlLFxuICAgICAgICAgIH0pKTtcblxuICAgICAgICAgIHJldHVybiB7IGNvbW1hbmRJZDogb3V0cHV0LmNtZElkLCBsb2dzLCByZXN1bHQgfTtcbiAgICAgICAgfSxcbiAgICAgICAgY2F0Y2g6IChlKSA9PiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pLFxuICAgICAgfSk7XG5cbiAgICAgIGF3YWl0IHVwZGF0ZVByb21pc2U7XG4gICAgICByZXR1cm4gZXhlY1Jlc3VsdDtcbiAgICB9LFxuXG4gICAgZ2V0RG9tYWluOiBhc3luYyAocG9ydCkgPT4ge1xuICAgICAgY29uc3Qgc2FuZGJveCA9IGF3YWl0IGdldFNhbmRib3goKTtcbiAgICAgIGlmIChzYW5kYm94IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIHNhbmRib3g7XG4gICAgICB9XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBzYW5kYm94LmRvbWFpbihwb3J0KTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSk7XG4gICAgICB9XG4gICAgfSxcblxuICAgIGtpbGw6IGFzeW5jICh7IGNvbW1hbmRJZCwgc3RvcmFnZTogY21kU3RvcmFnZSB9KSA9PiB7XG4gICAgICBjb25zdCBpbnN0YW5jZSA9IGF3YWl0IGdldFNhbmRib3goKTtcbiAgICAgIGlmIChpbnN0YW5jZSBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHJldHVybiBpbnN0YW5jZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY21kID0gYXdhaXQgY21kU3RvcmFnZS5jb21tYW5kLmdldChjb21tYW5kSWQpO1xuICAgICAgaWYgKGNtZCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHJldHVybiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBjbWQubWVzc2FnZSwgY2F1c2U6IGNtZCB9KTtcbiAgICAgIH1cbiAgICAgIGlmIChjbWQgJiYgY21kLnN0YXR1cyA9PT0gXCJydW5uaW5nXCIpIHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY21kU3RvcmFnZS5jb21tYW5kLnNldCh7XG4gICAgICAgICAgLi4uY21kLFxuICAgICAgICAgIHN0YXR1czogXCJraWxsZWRcIixcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgIHJldHVybiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiByZXN1bHQubWVzc2FnZSwgY2F1c2U6IHJlc3VsdCB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9LFxuXG4gICAgd3JpdGVGaWxlczogKG9wdHMpID0+IHdyaXRlRmlsZXMoeyBzYW5kYm94LCAuLi5vcHRzIH0pLFxuXG4gICAgbGlmZWN5Y2xlLFxuICB9O1xuXG4gIGlmIChjb25maWcubGlmZWN5Y2xlPy5hdXRvU3RhcnQgIT09IGZhbHNlKSB7XG4gICAgc2FuZGJveFByb21pc2UgPSBkb0dldFNhbmRib3goKTtcbiAgfVxuXG4gIHJldHVybiBzYW5kYm94O1xufTtcbiIsICJpbXBvcnQgdHlwZSB7IFNhbmRib3hSZWNvcmQsIFN0b3JhZ2VDb25maWcgfSBmcm9tIFwiLi4vc3RvcmFnZVwiO1xuaW1wb3J0IHsgbG9jYWxTYW5kYm94IH0gZnJvbSBcIi4vYmluZGluZ3MvbG9jYWxcIjtcbmltcG9ydCB7IHZlcmNlbFNhbmRib3ggfSBmcm9tIFwiLi9iaW5kaW5ncy92ZXJjZWxcIjtcbmltcG9ydCB0eXBlIHsgU2FuZGJveCB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTYW5kYm94KHtcbiAgc2FuZGJveFJlY29yZCxcbiAgc3RvcmFnZUNvbmZpZyxcbn06IHtcbiAgc3RvcmFnZUNvbmZpZzogU3RvcmFnZUNvbmZpZztcbiAgc2FuZGJveFJlY29yZDogU2FuZGJveFJlY29yZDtcbn0pOiBTYW5kYm94IHtcbiAgY29uc3QgeyBjb25maWcgfSA9IHNhbmRib3hSZWNvcmQ7XG4gIHN3aXRjaCAoY29uZmlnLnR5cGUpIHtcbiAgICBjYXNlIFwibG9jYWxcIjpcbiAgICAgIHJldHVybiBsb2NhbFNhbmRib3goe1xuICAgICAgICBzYW5kYm94UmVjb3JkOiBzYW5kYm94UmVjb3JkIGFzIFNhbmRib3hSZWNvcmQgJiB7XG4gICAgICAgICAgY29uZmlnOiB7IHR5cGU6IFwibG9jYWxcIiB9O1xuICAgICAgICB9LFxuICAgICAgICBzdG9yYWdlQ29uZmlnLFxuICAgICAgfSk7XG4gICAgY2FzZSBcInZlcmNlbFwiOlxuICAgICAgcmV0dXJuIHZlcmNlbFNhbmRib3goe1xuICAgICAgICBzYW5kYm94UmVjb3JkOiBzYW5kYm94UmVjb3JkIGFzIFNhbmRib3hSZWNvcmQgJiB7XG4gICAgICAgICAgY29uZmlnOiB7IHR5cGU6IFwidmVyY2VsXCIgfTtcbiAgICAgICAgfSxcbiAgICAgICAgc3RvcmFnZUNvbmZpZyxcbiAgICAgIH0pO1xuICAgIGNhc2UgXCJjdXN0b21cIjpcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkN1c3RvbSBzYW5kYm94ZXMgYXJlIG5vdCBzdXBwb3J0ZWRcIik7XG4gICAgZGVmYXVsdDpcbiAgICAgIGNvbmZpZyBzYXRpc2ZpZXMgbmV2ZXI7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBVbmtub3duIHNhbmRib3ggdHlwZTogJHtcbiAgICAgICAgICAvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL25vRXhwbGljaXRBbnk6IC5cbiAgICAgICAgICAoY29uZmlnIGFzIGFueSkudHlwZVxuICAgICAgICB9YFxuICAgICAgKTtcbiAgfVxufVxuIiwgImV4cG9ydCB7IGdldFNhbmRib3ggfSBmcm9tIFwiLi9jbGllbnRcIjtcbmV4cG9ydCB0eXBlIHtcbiAgRXhlY1Jlc3VsdCxcbiAgTG9nRW50cnksXG4gIFNhbmRib3gsXG4gIFNhbmRib3hMaWZlY3ljbGUsXG4gIFNhbmRib3hMaWZlY3ljbGVJbnB1dCxcbiAgU2FuZGJveFN0YXR1cyxcbiAgVGVybWluYWwsXG4gIFRlcm1pbmFsTWV0YWRhdGEsXG4gIFZlcmNlbFNhbmRib3hMaWZlY3ljbGVDb25maWcsXG59IGZyb20gXCIuL3R5cGVzXCI7XG4iLCAiZXhwb3J0IHtcbiAgdHlwZSBBZ2VudE9wdGlvbnMsXG4gIGFnZW50LFxuICB0eXBlIFNlbmRJbnB1dCxcbiAgdHlwZSBUYWdzU2NoZW1hLFxufSBmcm9tIFwiLi9jbGllbnRcIjtcbmV4cG9ydCB7XG4gIE1lc3NhZ2VOb3RGb3VuZEVycm9yLFxuICBTYW5kYm94RXJyb3IsXG4gIFNhbmRib3hOb3RGb3VuZEVycm9yLFxuICBTZXNzaW9uTm90Rm91bmRFcnJvcixcbiAgU3RvcmFnZUVycm9yLFxufSBmcm9tIFwiLi9lcnJvcnNcIjtcbmV4cG9ydCB7IG1jcCB9IGZyb20gXCIuL21jcFwiO1xuZXhwb3J0IHR5cGUgeyBFeGVjUmVzdWx0LCBTYW5kYm94IH0gZnJvbSBcIi4vc2FuZGJveFwiO1xuZXhwb3J0IHR5cGUgeyBTa2lsbFN1bW1hcnksIFVwbG9hZGFibGVGaWxlIH0gZnJvbSBcIi4vc2tpbGxzL3R5cGVzXCI7XG5leHBvcnQge1xuICB0eXBlIEhhbmRsZXJzLFxuICBoYW5kbGVTdG9yYWdlUnBjLFxuICB0eXBlIExpc3RSZXN1bHQsXG4gIHR5cGUgTWVzc2FnZSxcbiAgdHlwZSBQYXJ0LFxuICB0eXBlIFJlc29sdmVkU3RvcmFnZSxcbiAgdHlwZSBScGNSZXF1ZXN0LFxuICB0eXBlIFJwY1Jlc3BvbnNlLFxuICB0eXBlIFNhbmRib3hDb25maWcsXG4gIHR5cGUgU2FuZGJveFJlY29yZCxcbiAgdHlwZSBTZXNzaW9uLFxuICB0eXBlIFN0b3JhZ2VDb25maWcsXG59IGZyb20gXCIuL3N0b3JhZ2VcIjtcbiIsICJpbXBvcnQgdHlwZSB7IEdhdGV3YXlNb2RlbElkLCBVSU1lc3NhZ2UgfSBmcm9tIFwiYWlcIjtcbmltcG9ydCB7IGFsbCB9IGZyb20gXCJiZXR0ZXItYWxsXCI7XG5pbXBvcnQgKiBhcyBlcnJvcmUgZnJvbSBcImVycm9yZVwiO1xuaW1wb3J0IGVxdWFsIGZyb20gXCJmYXN0LWRlZXAtZXF1YWxcIjtcbmltcG9ydCB7IHVsaWQgfSBmcm9tIFwidWxpZFwiO1xuaW1wb3J0IHsgZ2V0UnVuLCBzdGFydCB9IGZyb20gXCJ3b3JrZmxvdy9hcGlcIjtcbmltcG9ydCB7XG4gIHR5cGUgQWdlbnRJbnB1dCxcbiAgdHlwZSBBZ2VudE1lc3NhZ2VJbnB1dCxcbiAgYWdlbnRNZXNzYWdlSG9vayxcbiAgYWdlbnRXb3JrZmxvdyxcbn0gZnJvbSBcIi4vYWdlbnQtd29ya2Zsb3dcIjtcbmltcG9ydCB7XG4gIFNhbmRib3hFcnJvcixcbiAgU2FuZGJveE5vdEZvdW5kRXJyb3IsXG4gIFNlc3Npb25FcnJvcixcbiAgU2Vzc2lvbk5vdEZvdW5kRXJyb3IsXG59IGZyb20gXCIuL2Vycm9yc1wiO1xuaW1wb3J0IHsgdHlwZSBNY3BDb25maWcsIHR5cGUgTWNwU2VuZE9wdGlvbnMsIHNlcmlhbGl6ZU1jcENvbmZpZyB9IGZyb20gXCIuL21jcFwiO1xuaW1wb3J0IHsgZ2V0U2FuZGJveCB9IGZyb20gXCIuL3NhbmRib3hcIjtcbmltcG9ydCB7IG5vcm1hbGl6ZVNraWxsc0RpcnMgfSBmcm9tIFwiLi9za2lsbHMvcGFyc2VyXCI7XG5pbXBvcnQgdHlwZSB7IFNraWxsc0RpciB9IGZyb20gXCIuL3NraWxscy90eXBlc1wiO1xuaW1wb3J0IHtcbiAgZ2V0U3RvcmFnZSxcbiAgdHlwZSBNZXNzYWdlLFxuICB0eXBlIFBhcnQsXG4gIHR5cGUgU2Vzc2lvbixcbiAgdHlwZSBTdG9yYWdlQ29uZmlnLFxufSBmcm9tIFwiLi9zdG9yYWdlXCI7XG5pbXBvcnQgdHlwZSB7IFNhbmRib3hDb25maWcgfSBmcm9tIFwiLi9zdG9yYWdlL3JwY1wiO1xuaW1wb3J0IHsgdG9NZXNzYWdlQW5kUGFydHMgfSBmcm9tIFwiLi91dGlscy9tZXNzYWdlXCI7XG5pbXBvcnQgeyBhc3NlbWJsZVVJTWVzc2FnZXMgfSBmcm9tIFwiLi91dGlscy91aVwiO1xuXG5leHBvcnQgdHlwZSBTZW5kSW5wdXQgPVxuICB8IHN0cmluZ1xuICB8IHsgcm9sZT86IFVJTWVzc2FnZVtcInJvbGVcIl07IHBhcnRzOiBVSU1lc3NhZ2VbXCJwYXJ0c1wiXTsgaWQ/OiBzdHJpbmcgfTtcblxudHlwZSBTZXNzaW9uT3B0aW9uczxcbiAgLy8gYmlvbWUtaWdub3JlIGxpbnQvY29tcGxleGl0eS9ub0Jhbm5lZFR5cGVzOiBuZWVkZWQgZm9yIGdlbmVyaWMgZGVmYXVsdFxuICBUTWNwIGV4dGVuZHMgTWNwQ29uZmlnID0ge30sXG4gIFRUYWdzIGV4dGVuZHMgVGFnc1NjaGVtYSA9IFRhZ3NTY2hlbWFcbj4gPSB7XG4gIG1vZGVsPzogR2F0ZXdheU1vZGVsSWQ7XG4gIGluc3RydWN0aW9ucz86IHN0cmluZztcbiAgc2FuZGJveD86IFNhbmRib3hDb25maWcgfCBzdHJpbmc7XG4gIHRhZ3M/OiBUVGFncztcbiAgc2tpbGxzRGlyPzogU2tpbGxzRGlyO1xuICBtY3A/OiBUTWNwO1xufTtcblxuZXhwb3J0IHR5cGUgTWNwVG9vbENhbGxCb2R5ID0ge1xuICBzZXJ2ZXI6IHN0cmluZztcbiAgdG9vbDogc3RyaW5nO1xuICBpbnB1dDogdW5rbm93bjtcbiAgc2Vzc2lvbklkOiBzdHJpbmc7XG4gIG1lc3NhZ2VJZDogc3RyaW5nO1xuICBob29rVG9rZW46IHN0cmluZztcbn07XG5cbi8vIGJpb21lLWlnbm9yZSBsaW50L2NvbXBsZXhpdHkvbm9CYW5uZWRUeXBlczogbmVlZGVkIGZvciBnZW5lcmljIGRlZmF1bHRcbmV4cG9ydCB0eXBlIEFnZW50T3B0aW9uczxUTWNwIGV4dGVuZHMgTWNwQ29uZmlnID0ge30+ID0ge1xuICBzdG9yYWdlPzogU3RvcmFnZUNvbmZpZztcbiAgZ2VuZXJhdGVJZD86IChcbiAgICByZXNvdXJjZTogXCJzZXNzaW9uXCIgfCBcIm1lc3NhZ2VcIiB8IFwicGFydFwiIHwgXCJzYW5kYm94XCIgfCBcImNvbW1hbmRcIlxuICApID0+IHN0cmluZztcbn0gJiBTZXNzaW9uT3B0aW9uczxUTWNwPjtcblxuZXhwb3J0IHR5cGUgVGFnc1NjaGVtYSA9IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuXG4vLyBiaW9tZS1pZ25vcmUgbGludC9jb21wbGV4aXR5L25vQmFubmVkVHlwZXM6IG5lZWRlZCBmb3IgZ2VuZXJpYyBkZWZhdWx0XG5leHBvcnQgY29uc3QgYWdlbnQgPSA8VE1jcCBleHRlbmRzIE1jcENvbmZpZyA9IHt9PihcbiAgb3B0aW9uczogQWdlbnRPcHRpb25zPFRNY3A+XG4pID0+IHtcbiAgY29uc3Qgc3RvcmFnZUNvbmZpZyA9IG9wdGlvbnMuc3RvcmFnZSA/PyB7IHR5cGU6IFwidmVyY2VsXCIgfTtcbiAgY29uc3Qgc3RvcmFnZSA9IGdldFN0b3JhZ2Uoc3RvcmFnZUNvbmZpZyk7XG4gIGNvbnN0IGdlbmVyYXRlSWQgPVxuICAgIG9wdGlvbnMuZ2VuZXJhdGVJZCA/PyAoKHJlc291cmNlKSA9PiBgJHtyZXNvdXJjZX1fJHt1bGlkKCl9YCk7XG5cbiAgY29uc3Qgc2FuZGJveCA9IGFzeW5jIChzYW5kYm94SWQ6IHN0cmluZywgY29uZmlnPzogU2FuZGJveENvbmZpZykgPT4ge1xuICAgIGNvbnN0IGV4aXN0aW5nUmVjb3JkID0gYXdhaXQgc3RvcmFnZS5zYW5kYm94LmdldChzYW5kYm94SWQpO1xuXG4gICAgaWYgKGV4aXN0aW5nUmVjb3JkIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIGlmICghKGV4aXN0aW5nUmVjb3JkIGluc3RhbmNlb2YgU2FuZGJveE5vdEZvdW5kRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGV4aXN0aW5nUmVjb3JkO1xuICAgICAgfVxuICAgICAgY29uc3Qgc2FuZGJveFJlY29yZCA9IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5zZXQoe1xuICAgICAgICBpZDogc2FuZGJveElkLFxuICAgICAgICBhY3F1aXJpbmdMb2NrQXQ6IG51bGwsXG4gICAgICAgIGFjcXVpcmluZ0xvY2tJZDogbnVsbCxcbiAgICAgICAgY3JlYXRlZEF0OiBEYXRlLm5vdygpLFxuICAgICAgICBsYXN0QWN0aXZpdHlBdDogRGF0ZS5ub3coKSxcbiAgICAgICAgY29uZmlnOiBjb25maWcgPz8geyB0eXBlOiBcInZlcmNlbFwiIH0sXG4gICAgICB9KTtcbiAgICAgIGlmIChzYW5kYm94UmVjb3JkIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgc2FuZGJveFJlY29yZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBnZXRTYW5kYm94KHsgc3RvcmFnZUNvbmZpZywgc2FuZGJveFJlY29yZCB9KTtcbiAgICB9XG5cbiAgICBjb25zdCBuZXdDb25maWcgPSBjb25maWcgPz8gZXhpc3RpbmdSZWNvcmQuY29uZmlnO1xuICAgIGlmICghZXF1YWwoZXhpc3RpbmdSZWNvcmQuY29uZmlnLCBuZXdDb25maWcpKSB7XG4gICAgICB0aHJvdyBuZXcgU2FuZGJveEVycm9yKHtcbiAgICAgICAgcmVhc29uOiBcInNhbmRib3ggY29uZmlnIGNoYW5nZXMgYXJlIG5vdCBzdXBwb3J0ZWRcIixcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBnZXRTYW5kYm94KHsgc3RvcmFnZUNvbmZpZywgc2FuZGJveFJlY29yZDogZXhpc3RpbmdSZWNvcmQgfSk7XG4gIH07XG5cbiAgcmV0dXJuIHtcbiAgICBzZXNzaW9uOiBhc3luYyA8XG4gICAgICBUVGFncyBleHRlbmRzIFRhZ3NTY2hlbWEgPSBUYWdzU2NoZW1hLFxuICAgICAgLy8gYmlvbWUtaWdub3JlIGxpbnQvY29tcGxleGl0eS9ub0Jhbm5lZFR5cGVzOiBuZWVkZWQgZm9yIGdlbmVyaWMgZGVmYXVsdFxuICAgICAgVE1jcE92ZXJyaWRlIGV4dGVuZHMgTWNwQ29uZmlnID0ge31cbiAgICA+KFxuICAgICAgc2Vzc2lvbklkOiBzdHJpbmcsXG4gICAgICBzZXNzaW9uT3B0aW9ucz86IFNlc3Npb25PcHRpb25zPFRNY3AgJiBUTWNwT3ZlcnJpZGUsIFRUYWdzPlxuICAgICkgPT4ge1xuICAgICAgbGV0IHNlc3Npb24gPSBhd2FpdCBzdG9yYWdlLnNlc3Npb24uZ2V0KHNlc3Npb25JZCk7XG5cbiAgICAgIC8qKlxuICAgICAgICogbm9ybWFsaXplIHNhbmRib3ggaW5wdXQgdG8gYSBzYW5kYm94IElEIGFuZCBjb25maWdcbiAgICAgICAqL1xuICAgICAgY29uc3Qgc2FuZGJveElucHV0ID0gc2Vzc2lvbk9wdGlvbnM/LnNhbmRib3ggPz8gb3B0aW9ucy5zYW5kYm94O1xuICAgICAgY29uc3Qgc2FuZGJveElkID1cbiAgICAgICAgdHlwZW9mIHNhbmRib3hJbnB1dCA9PT0gXCJzdHJpbmdcIlxuICAgICAgICAgID8gc2FuZGJveElucHV0XG4gICAgICAgICAgOiAvLyBiaW9tZS1pZ25vcmUgbGludC9zdHlsZS9ub05lc3RlZFRlcm5hcnk6IG9rXG4gICAgICAgICAgc2Vzc2lvbiBpbnN0YW5jZW9mIEVycm9yXG4gICAgICAgICAgPyBnZW5lcmF0ZUlkKFwic2FuZGJveFwiKVxuICAgICAgICAgIDogc2Vzc2lvbi5zYW5kYm94SWQgPz8gZ2VuZXJhdGVJZChcInNhbmRib3hcIik7XG4gICAgICBjb25zdCBzYW5kYm94UHJvbWlzZSA9IHNhbmRib3goXG4gICAgICAgIHNhbmRib3hJZCxcbiAgICAgICAgdHlwZW9mIHNhbmRib3hJbnB1dCA9PT0gXCJzdHJpbmdcIiA/IHVuZGVmaW5lZCA6IHNhbmRib3hJbnB1dFxuICAgICAgKTtcblxuICAgICAgY29uc3QgbWNwQ29uZmlnID1cbiAgICAgICAgb3B0aW9ucy5tY3AgfHwgc2Vzc2lvbk9wdGlvbnM/Lm1jcFxuICAgICAgICAgID8geyAuLi5vcHRpb25zLm1jcCwgLi4uc2Vzc2lvbk9wdGlvbnM/Lm1jcCB9XG4gICAgICAgICAgOiBudWxsO1xuICAgICAgY29uc3Qgc2tpbGxzRGlyID0gc2Vzc2lvbk9wdGlvbnM/LnNraWxsc0RpciA/PyBvcHRpb25zLnNraWxsc0RpciA/PyBudWxsO1xuXG4gICAgICBpZiAoc2Vzc2lvbiBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIGlmIChzZXNzaW9uIGluc3RhbmNlb2YgU2Vzc2lvbk5vdEZvdW5kRXJyb3IpIHtcbiAgICAgICAgICBjb25zdCBpbnN0cnVjdGlvbnMgPVxuICAgICAgICAgICAgc2Vzc2lvbk9wdGlvbnM/Lmluc3RydWN0aW9ucyA/PyBvcHRpb25zLmluc3RydWN0aW9ucyA/PyBudWxsO1xuICAgICAgICAgIGNvbnN0IG1vZGVsID0gc2Vzc2lvbk9wdGlvbnM/Lm1vZGVsID8/IG9wdGlvbnMubW9kZWwgPz8gbnVsbDtcbiAgICAgICAgICBpZiAoIW1vZGVsKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgU2Vzc2lvbkVycm9yKHtcbiAgICAgICAgICAgICAgaWQ6IHNlc3Npb25JZCxcbiAgICAgICAgICAgICAgcmVhc29uOiBcIk1vZGVsIGlzIG5vdCBzZXRcIixcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzZXNzaW9uID0gYXdhaXQgc3RvcmFnZS5zZXNzaW9uLnNldCh7XG4gICAgICAgICAgICBpZDogc2Vzc2lvbklkLFxuICAgICAgICAgICAgY3JlYXRlZEF0OiBEYXRlLm5vdygpLFxuICAgICAgICAgICAgdXBkYXRlZEF0OiBEYXRlLm5vdygpLFxuICAgICAgICAgICAgbGFzdE1lc3NhZ2VJZDogbnVsbCxcbiAgICAgICAgICAgIHJ1bklkOiBudWxsLFxuICAgICAgICAgICAgdGFnczogc2Vzc2lvbk9wdGlvbnM/LnRhZ3MgPz8gbnVsbCxcbiAgICAgICAgICAgIGluc3RydWN0aW9ucyxcbiAgICAgICAgICAgIG1vZGVsLFxuICAgICAgICAgICAgbWNwOiBtY3BDb25maWcgPyBzZXJpYWxpemVNY3BDb25maWcobWNwQ29uZmlnKSA6IG51bGwsXG4gICAgICAgICAgICBzYW5kYm94SWQsXG4gICAgICAgICAgICBza2lsbHNEaXI6IHNraWxsc0RpciA/IG5vcm1hbGl6ZVNraWxsc0RpcnMoc2tpbGxzRGlyKSA6IG51bGwsXG4gICAgICAgICAgICBob29rVG9rZW46IG51bGwsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgc2Vzc2lvbjtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIHRoaXMgaXMgYW4gZXhpc3Rpbmcgc2Vzc2lvbi4gd2UgY29tcGFyZSB0aGUgb3B0aW9ucyBhbmQgdXBkYXRlIHRoZSBzZXNzaW9uIGlmIG5lY2Vzc2FyeS5cbiAgICAgICAgICovXG4gICAgICAgIGNvbnN0IHVwZGF0ZWQ6IFNlc3Npb24gPSB7XG4gICAgICAgICAgLi4uc2Vzc2lvbixcbiAgICAgICAgICAuLi5zZXNzaW9uT3B0aW9ucyxcbiAgICAgICAgICBtY3A6IG1jcENvbmZpZyA/IHNlcmlhbGl6ZU1jcENvbmZpZyhtY3BDb25maWcpIDogc2Vzc2lvbi5tY3AsXG4gICAgICAgICAgc2FuZGJveElkLFxuICAgICAgICAgIHNraWxsc0Rpcjogc2tpbGxzRGlyID8gbm9ybWFsaXplU2tpbGxzRGlycyhza2lsbHNEaXIpIDogbnVsbCxcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKCFlcXVhbCh1cGRhdGVkLCBzZXNzaW9uKSkge1xuICAgICAgICAgIHNlc3Npb24gPSBhd2FpdCBzdG9yYWdlLnNlc3Npb24uc2V0KHVwZGF0ZWQpO1xuICAgICAgICAgIGlmIChzZXNzaW9uIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICAgIHRocm93IHNlc3Npb247XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIHNlbmQ6IGFzeW5jICh7XG4gICAgICAgICAgaW5wdXQsXG4gICAgICAgICAgbWNwQ29udGV4dCxcbiAgICAgICAgfToge1xuICAgICAgICAgIGlucHV0OiBTZW5kSW5wdXQgfCBTZW5kSW5wdXRbXTtcbiAgICAgICAgICBtY3BDb250ZXh0PzogTWNwU2VuZE9wdGlvbnM8VE1jcCAmIFRNY3BPdmVycmlkZT47XG4gICAgICAgIH0pID0+IHtcbiAgICAgICAgICBjb25zdCBuZXdNZXNzYWdlczogTWVzc2FnZVtdID0gW107XG4gICAgICAgICAgY29uc3QgbmV3UGFydHM6IFBhcnRbXSA9IFtdO1xuICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KGlucHV0KSkge1xuICAgICAgICAgICAgZm9yIChjb25zdCBpIG9mIGlucHV0KSB7XG4gICAgICAgICAgICAgIGNvbnN0IHsgbWVzc2FnZSwgcGFydHMgfSA9IHRvTWVzc2FnZUFuZFBhcnRzKHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uSWQsXG4gICAgICAgICAgICAgICAgaW5wdXQ6IGksXG4gICAgICAgICAgICAgICAgZGVmYXVsdFJvbGU6IFwidXNlclwiLFxuICAgICAgICAgICAgICAgIGdlbmVyYXRlSWQ6ICgpID0+IGdlbmVyYXRlSWQoXCJtZXNzYWdlXCIpLFxuICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICBuZXdNZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgICAgICAgICAgICBuZXdQYXJ0cy5wdXNoKC4uLnBhcnRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgeyBtZXNzYWdlLCBwYXJ0cyB9ID0gdG9NZXNzYWdlQW5kUGFydHMoe1xuICAgICAgICAgICAgICBzZXNzaW9uSWQsXG4gICAgICAgICAgICAgIGlucHV0LFxuICAgICAgICAgICAgICBkZWZhdWx0Um9sZTogXCJ1c2VyXCIsXG4gICAgICAgICAgICAgIGdlbmVyYXRlSWQ6ICgpID0+IGdlbmVyYXRlSWQoXCJtZXNzYWdlXCIpLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBuZXdNZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgICAgICAgICAgbmV3UGFydHMucHVzaCguLi5wYXJ0cyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8qKlxuICAgICAgICAgICAqIHdlIGFsc28gcHJlLWNyZWF0ZSB0aGUgYXNzaXN0YW50IG1lc3NhZ2VcbiAgICAgICAgICAgKi9cbiAgICAgICAgICBjb25zdCBhc3Npc3RhbnRNZXNzYWdlSWQgPSBnZW5lcmF0ZUlkKFwibWVzc2FnZVwiKTtcbiAgICAgICAgICBuZXdNZXNzYWdlcy5wdXNoKHtcbiAgICAgICAgICAgIGlkOiBhc3Npc3RhbnRNZXNzYWdlSWQsXG4gICAgICAgICAgICBzZXNzaW9uSWQsXG4gICAgICAgICAgICByb2xlOiBcImFzc2lzdGFudFwiLFxuICAgICAgICAgICAgY3JlYXRlZEF0OiBEYXRlLm5vdygpLFxuICAgICAgICAgICAgY29tcGxldGVkQXQ6IG51bGwsXG4gICAgICAgICAgICBtY3BDb250ZXh0LFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICBjb25zdCBzZXNzaW9uMiA9IGF3YWl0IHN0b3JhZ2Uuc2Vzc2lvbi5nZXQoc2Vzc2lvbklkKTtcbiAgICAgICAgICBpZiAoc2Vzc2lvbjIgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgc2Vzc2lvbjI7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgYWdlbnRJbnB1dDogQWdlbnRJbnB1dCA9IHtcbiAgICAgICAgICAgIHN0b3JhZ2VDb25maWcsXG4gICAgICAgICAgICBzZXNzaW9uSWQsXG4gICAgICAgICAgfTtcbiAgICAgICAgICBjb25zdCBldmVudDogQWdlbnRNZXNzYWdlSW5wdXQgPSB7XG4gICAgICAgICAgICBhc3Npc3RhbnRNZXNzYWdlSWQsXG4gICAgICAgICAgICBob29rVG9rZW46IGNyeXB0by5yYW5kb21VVUlEKCksXG4gICAgICAgICAgfTtcblxuICAgICAgICAgIHJldHVybiBhd2FpdCBlcnJvcmUudHJ5QXN5bmMoe1xuICAgICAgICAgICAgdHJ5OiBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgIGF3YWl0IGFsbCh7XG4gICAgICAgICAgICAgICAgYXN5bmMgc2F2ZU1lc3NhZ2VzKCkge1xuICAgICAgICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwobmV3TWVzc2FnZXMubWFwKHN0b3JhZ2UubWVzc2FnZS5zZXQpKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGFzeW5jIHNhdmVQYXJ0cygpIHtcbiAgICAgICAgICAgICAgICAgIGF3YWl0IFByb21pc2UuYWxsKG5ld1BhcnRzLm1hcChzdG9yYWdlLnBhcnQuc2V0KSk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBhc3luYyByZXN1bWVPclN0YXJ0QWdlbnRXb3JrZmxvdygpIHtcbiAgICAgICAgICAgICAgICAgIGlmIChzZXNzaW9uMi5ydW5JZCkge1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCBhZ2VudE1lc3NhZ2VIb29rLnJlc3VtZShzZXNzaW9uSWQsIGV2ZW50KTtcbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0YXJ0UmVzdWx0ID0gYXdhaXQgc3RhcnQoYWdlbnRXb3JrZmxvdywgW1xuICAgICAgICAgICAgICAgICAgICAgIHsgaW5wdXQ6IGFnZW50SW5wdXQsIGV2ZW50IH0sXG4gICAgICAgICAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgICAgICAgICBzZXNzaW9uMi5ydW5JZCA9IHN0YXJ0UmVzdWx0LnJ1bklkO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgYXN5bmMgdXBkYXRlU2Vzc2lvbigpIHtcbiAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuJC5yZXN1bWVPclN0YXJ0QWdlbnRXb3JrZmxvdztcbiAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHN0b3JhZ2Uuc2Vzc2lvbi5zZXQoe1xuICAgICAgICAgICAgICAgICAgICAuLi5zZXNzaW9uMixcbiAgICAgICAgICAgICAgICAgICAgdXBkYXRlZEF0OiBub3csXG4gICAgICAgICAgICAgICAgICAgIGxhc3RNZXNzYWdlSWQ6IGFzc2lzdGFudE1lc3NhZ2VJZCxcbiAgICAgICAgICAgICAgICAgICAgaG9va1Rva2VuOiBldmVudC5ob29rVG9rZW4sXG4gICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyByZXN1bHQ7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNhdGNoOiAoZSkgPT4ge1xuICAgICAgICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZXR1cm4gbmV3IFNlc3Npb25FcnJvcih7XG4gICAgICAgICAgICAgICAgaWQ6IHNlc3Npb25JZCxcbiAgICAgICAgICAgICAgICByZWFzb246IGBmYWlsZWQgdG8gc2VuZDogJHtTdHJpbmcoZSl9YCxcbiAgICAgICAgICAgICAgICBjYXVzZTogZSxcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuXG4gICAgICAgIHN0cmVhbTogYXN5bmMgKG9wdHM/OiB7IG1lc3NhZ2VJZD86IHN0cmluZyB9KSA9PiB7XG4gICAgICAgICAgY29uc3Qgc2Vzc2lvbiA9IGF3YWl0IHN0b3JhZ2Uuc2Vzc2lvbi5nZXQoc2Vzc2lvbklkKTtcbiAgICAgICAgICBpZiAoc2Vzc2lvbiBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gc2Vzc2lvbjtcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3QgbWVzc2FnZUlkID0gb3B0cz8ubWVzc2FnZUlkID8/IHNlc3Npb24ubGFzdE1lc3NhZ2VJZDtcbiAgICAgICAgICBpZiAoIW1lc3NhZ2VJZCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBTZXNzaW9uRXJyb3Ioe1xuICAgICAgICAgICAgICBpZDogc2Vzc2lvbklkLFxuICAgICAgICAgICAgICByZWFzb246IFwiTm8gbWVzc2FnZSBhc3NvY2lhdGVkIHdpdGggc2Vzc2lvblwiLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghc2Vzc2lvbi5ydW5JZCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBTZXNzaW9uRXJyb3Ioe1xuICAgICAgICAgICAgICBpZDogc2Vzc2lvbklkLFxuICAgICAgICAgICAgICByZWFzb246IFwiTm8gcnVuIGFzc29jaWF0ZWQgd2l0aCBzZXNzaW9uXCIsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3QgcnVuID0gZ2V0UnVuKHNlc3Npb24ucnVuSWQpO1xuICAgICAgICAgIHJldHVybiBydW4uZ2V0UmVhZGFibGUoeyBuYW1lc3BhY2U6IG1lc3NhZ2VJZCB9KTtcbiAgICAgICAgfSxcblxuICAgICAgICB1aTogYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IFttZXNzYWdlc1Jlc3VsdCwgcGFydHNSZXN1bHRdID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgICAgICAgc3RvcmFnZS5tZXNzYWdlLmxpc3Qoc2Vzc2lvbklkKSxcbiAgICAgICAgICAgIHN0b3JhZ2UucGFydC5saXN0QnlTZXNzaW9uKHNlc3Npb25JZCksXG4gICAgICAgICAgXSk7XG5cbiAgICAgICAgICBpZiAobWVzc2FnZXNSZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIG1lc3NhZ2VzUmVzdWx0O1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAocGFydHNSZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIHBhcnRzUmVzdWx0O1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IG1lc3NhZ2VzID0gYXNzZW1ibGVVSU1lc3NhZ2VzKHtcbiAgICAgICAgICAgIG1lc3NhZ2VzOiBtZXNzYWdlc1Jlc3VsdC5pdGVtcyxcbiAgICAgICAgICAgIHBhcnRzOiBwYXJ0c1Jlc3VsdC5pdGVtcyxcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGNvbnN0IGxhc3RNZXNzYWdlID0gbWVzc2FnZXNSZXN1bHQuaXRlbXMuYXQoLTEpO1xuICAgICAgICAgIGNvbnN0IGlzU3RyZWFtaW5nID1cbiAgICAgICAgICAgIGxhc3RNZXNzYWdlPy5yb2xlID09PSBcImFzc2lzdGFudFwiICYmXG4gICAgICAgICAgICBsYXN0TWVzc2FnZS5jb21wbGV0ZWRBdCA9PT0gbnVsbDtcbiAgICAgICAgICBjb25zdCBzdHJlYW1pbmdNZXNzYWdlSWQgPSBpc1N0cmVhbWluZyA/IGxhc3RNZXNzYWdlLmlkIDogbnVsbDtcblxuICAgICAgICAgIHJldHVybiB7IG1lc3NhZ2VzLCBzdHJlYW1pbmdNZXNzYWdlSWQgfTtcbiAgICAgICAgfSxcbiAgICAgICAgdGFnOiB7XG4gICAgICAgICAgbGlzdDogYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc2Vzc2lvbiA9IGF3YWl0IHN0b3JhZ2Uuc2Vzc2lvbi5nZXQoc2Vzc2lvbklkKTtcbiAgICAgICAgICAgIGlmIChzZXNzaW9uIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHNlc3Npb247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gKHNlc3Npb24udGFncyA/PyB7fSkgYXMgVFRhZ3M7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBnZXQ6IGFzeW5jIChrZXk6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc2Vzc2lvbiA9IGF3YWl0IHN0b3JhZ2Uuc2Vzc2lvbi5nZXQoc2Vzc2lvbklkKTtcbiAgICAgICAgICAgIGlmIChzZXNzaW9uIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHNlc3Npb247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gc2Vzc2lvbi50YWdzPy5ba2V5IGFzIHN0cmluZ10gYXNcbiAgICAgICAgICAgICAgfCBUVGFnc1t0eXBlb2Yga2V5XVxuICAgICAgICAgICAgICB8IHVuZGVmaW5lZDtcbiAgICAgICAgICB9LFxuICAgICAgICAgIHNldDogYXN5bmMgKGtleTogc3RyaW5nLCB2YWx1ZTogdW5rbm93bikgPT4ge1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3RvcmFnZS5zZXNzaW9uLnRhZy5zZXQoe1xuICAgICAgICAgICAgICBzZXNzaW9uSWQsXG4gICAgICAgICAgICAgIHRhZ3M6IHsgW2tleV06IHZhbHVlIH0gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICB9LFxuICAgICAgICAgIHNldE1hbnk6IGFzeW5jICh0YWdzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikgPT4ge1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3RvcmFnZS5zZXNzaW9uLnRhZy5zZXQoe1xuICAgICAgICAgICAgICBzZXNzaW9uSWQsXG4gICAgICAgICAgICAgIHRhZ3M6IHRhZ3MgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICBzYW5kYm94OiBhd2FpdCBzYW5kYm94UHJvbWlzZSxcbiAgICAgIH07XG4gICAgfSxcbiAgICBzYW5kYm94LFxuICAgIHN0b3JhZ2UsXG4gICAgaGFuZGxlTWNwVG9vbENhbGw6IGFzeW5jIChcbiAgICAgIGJvZHk6IE1jcFRvb2xDYWxsQm9keSxcbiAgICAgIGhhbmRsZXJzOiBSZWNvcmQ8XG4gICAgICAgIHN0cmluZyxcbiAgICAgICAgKG9wdHM6IHtcbiAgICAgICAgICBpbnB1dDogdW5rbm93bjtcbiAgICAgICAgICBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICAgICAgICAgIGJvZHk6IE1jcFRvb2xDYWxsQm9keTtcbiAgICAgICAgfSkgPT4gUHJvbWlzZTx1bmtub3duPlxuICAgICAgPlxuICAgICk6IFByb21pc2U8XG4gICAgICB7IHJlc3VsdDogdW5rbm93biB9IHwgeyBlcnJvcjogeyBjb2RlOiBzdHJpbmc7IG1lc3NhZ2U6IHN0cmluZyB9IH1cbiAgICA+ID0+IHtcbiAgICAgIGNvbnN0IHsgc2VydmVyLCB0b29sLCBpbnB1dCwgc2Vzc2lvbklkLCBtZXNzYWdlSWQsIGhvb2tUb2tlbiB9ID0gYm9keTtcblxuICAgICAgY29uc3QgaGFuZGxlcktleSA9IGAke3NlcnZlcn0vJHt0b29sfWA7XG4gICAgICBjb25zdCBoYW5kbGVyID0gaGFuZGxlcnNbaGFuZGxlcktleV07XG4gICAgICBpZiAoIWhhbmRsZXIpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBlcnJvcjoge1xuICAgICAgICAgICAgY29kZTogXCJIQU5ETEVSX05PVF9GT1VORFwiLFxuICAgICAgICAgICAgbWVzc2FnZTogYE5vIGhhbmRsZXIgZm9yICR7aGFuZGxlcktleX1gLFxuICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHNlc3Npb24gPSBhd2FpdCBzdG9yYWdlLnNlc3Npb24uZ2V0KHNlc3Npb25JZCk7XG4gICAgICBpZiAoc2Vzc2lvbiBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgZXJyb3I6IHsgY29kZTogXCJTRVNTSU9OX05PVF9GT1VORFwiLCBtZXNzYWdlOiBcIlNlc3Npb24gbm90IGZvdW5kXCIgfSxcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFzZXNzaW9uLmhvb2tUb2tlbiB8fCBzZXNzaW9uLmhvb2tUb2tlbiAhPT0gaG9va1Rva2VuKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgZXJyb3I6IHsgY29kZTogXCJJTlZBTElEX1RPS0VOXCIsIG1lc3NhZ2U6IFwiSW52YWxpZCBob29rIHRva2VuXCIgfSxcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbWVzc2FnZSA9IGF3YWl0IHN0b3JhZ2UubWVzc2FnZS5nZXQobWVzc2FnZUlkKTtcbiAgICAgIGlmIChtZXNzYWdlIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBlcnJvcjogeyBjb2RlOiBcIk1FU1NBR0VfTk9UX0ZPVU5EXCIsIG1lc3NhZ2U6IFwiTWVzc2FnZSBub3QgZm91bmRcIiB9LFxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICBjb25zdCBtY3BDb250ZXh0ID0gbWVzc2FnZS5tY3BDb250ZXh0IGFzIE1jcFNlbmRPcHRpb25zPFRNY3A+IHwgdW5kZWZpbmVkO1xuICAgICAgY29uc3Qgc2VydmVyQ29udGV4dCA9IG1jcENvbnRleHQ/LltzZXJ2ZXIgYXMga2V5b2YgdHlwZW9mIG1jcENvbnRleHRdO1xuICAgICAgY29uc3QgaGVhZGVycyA9IChzZXJ2ZXJDb250ZXh0Py5oZWFkZXJzID8/IHt9KSBhcyBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBoYW5kbGVyKHsgaW5wdXQsIGhlYWRlcnMsIGJvZHkgfSk7XG4gICAgICAgIHJldHVybiB7IHJlc3VsdCB9O1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGVycm9yOiB7XG4gICAgICAgICAgICBjb2RlOiBcIkVYRUNVVElPTl9FUlJPUlwiLFxuICAgICAgICAgICAgbWVzc2FnZTogZSBpbnN0YW5jZW9mIEVycm9yID8gZS5tZXNzYWdlIDogU3RyaW5nKGUpLFxuICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfSxcbiAgfTtcbn07XG4iLCAiaW1wb3J0IHR5cGUgeyBGaW5pc2hSZWFzb24gfSBmcm9tIFwiYWlcIjtcbmltcG9ydCB7IGRlZmluZUhvb2ssIEZhdGFsRXJyb3IsIGdldFdyaXRhYmxlIH0gZnJvbSBcIndvcmtmbG93XCI7XG5pbXBvcnQgeyBjb21wbGV0ZU1lc3NhZ2VTdGVwLCBzdHJlYW1UZXh0U3RlcCB9IGZyb20gXCIuL2FnZW50LXdvcmtmbG93LXN0ZXBzXCI7XG5pbXBvcnQgdHlwZSB7IFN0b3JhZ2VDb25maWcgfSBmcm9tIFwiLi9zdG9yYWdlXCI7XG5cbmV4cG9ydCB0eXBlIEFnZW50SW5wdXQgPSB7XG4gIHNlc3Npb25JZDogc3RyaW5nO1xuICBzdG9yYWdlQ29uZmlnOiBTdG9yYWdlQ29uZmlnO1xufTtcblxuZXhwb3J0IHR5cGUgQWdlbnRNZXNzYWdlSW5wdXQgPSB7XG4gIGFzc2lzdGFudE1lc3NhZ2VJZDogc3RyaW5nO1xuICBob29rVG9rZW46IHN0cmluZztcbn07XG5cbmV4cG9ydCBjb25zdCBhZ2VudE1lc3NhZ2VIb29rID0gZGVmaW5lSG9vazxBZ2VudE1lc3NhZ2VJbnB1dD4oKTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGFnZW50V29ya2Zsb3coe1xuICBpbnB1dCxcbiAgZXZlbnQsXG59OiB7XG4gIGlucHV0OiBBZ2VudElucHV0O1xuICBldmVudDogQWdlbnRNZXNzYWdlSW5wdXQ7XG59KSB7XG4gIFwidXNlIHdvcmtmbG93XCI7XG5cbiAgY29uc3QgbWVzc2FnZUhvb2sgPSBhZ2VudE1lc3NhZ2VIb29rLmNyZWF0ZSh7IHRva2VuOiBpbnB1dC5zZXNzaW9uSWQgfSk7XG4gIGNvbnN0IGl0ZXJhdG9yID0gbWVzc2FnZUhvb2tbU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCk7XG4gIGxldCBwZW5kaW5nTmV4dCA9IGl0ZXJhdG9yLm5leHQoKTtcblxuICBhd2FpdCBvbk1lc3NhZ2UoeyBldmVudCwgaW5wdXQgfSkuY2F0Y2goKGUpID0+IHtcbiAgICBpZiAoRmF0YWxFcnJvci5pcyhlKSkge1xuICAgICAgY29uc29sZS5lcnJvcihcIk1lc3NhZ2UgcHJvY2Vzc2luZyBmYWlsZWQgcGVybWFuZW50bHk6XCIsIGUubWVzc2FnZSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRocm93IGU7XG4gIH0pO1xuXG4gIHdoaWxlICh0cnVlKSB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcGVuZGluZ05leHQ7XG5cbiAgICBpZiAocmVzdWx0LmRvbmUpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoXCJVbmV4cGVjdGVkOiBtZXNzYWdlIGhvb2sgaXRlcmF0b3IgZG9uZVwiKTtcbiAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIGF3YWl0IG9uTWVzc2FnZSh7IGV2ZW50OiByZXN1bHQudmFsdWUsIGlucHV0IH0pLmNhdGNoKChlKSA9PiB7XG4gICAgICBpZiAoRmF0YWxFcnJvci5pcyhlKSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKFwiTWVzc2FnZSBwcm9jZXNzaW5nIGZhaWxlZCBwZXJtYW5lbnRseTpcIiwgZS5tZXNzYWdlKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhyb3cgZTtcbiAgICB9KTtcbiAgICBwZW5kaW5nTmV4dCA9IGl0ZXJhdG9yLm5leHQoKTtcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBvbk1lc3NhZ2Uoe1xuICBldmVudCxcbiAgaW5wdXQsXG59OiB7XG4gIGV2ZW50OiBBZ2VudE1lc3NhZ2VJbnB1dDtcbiAgaW5wdXQ6IEFnZW50SW5wdXQ7XG59KSB7XG4gIGNvbnN0IHdyaXRhYmxlID0gZ2V0V3JpdGFibGUoeyBuYW1lc3BhY2U6IGV2ZW50LmFzc2lzdGFudE1lc3NhZ2VJZCB9KTtcblxuICBsZXQgZmluaXNoUmVhc29uOiBGaW5pc2hSZWFzb24gfCB1bmRlZmluZWQ7XG4gIGxldCBsYXN0UGFydEluZGV4ID0gMDtcblxuICB3aGlsZSAoZmluaXNoUmVhc29uICE9PSBcInN0b3BcIikge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzdHJlYW1UZXh0U3RlcCh7XG4gICAgICAgIGFzc2lzdGFudE1lc3NhZ2VJZDogZXZlbnQuYXNzaXN0YW50TWVzc2FnZUlkLFxuICAgICAgICB3cml0YWJsZSxcbiAgICAgICAgaW5wdXQsXG4gICAgICAgIGV2ZW50LFxuICAgICAgICBsYXN0UGFydEluZGV4LFxuICAgICAgfSk7XG4gICAgICBmaW5pc2hSZWFzb24gPSByZXN1bHQuZmluaXNoUmVhc29uO1xuICAgICAgbGFzdFBhcnRJbmRleCA9IHJlc3VsdC5sYXN0UGFydEluZGV4O1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY29uc29sZS5lcnJvcihlcnIpO1xuICAgICAgdGhyb3cgZXJyO1xuICAgIH1cbiAgfVxuXG4gIGF3YWl0IGNvbXBsZXRlTWVzc2FnZVN0ZXAoe1xuICAgIGFzc2lzdGFudE1lc3NhZ2VJZDogZXZlbnQuYXNzaXN0YW50TWVzc2FnZUlkLFxuICAgIGlucHV0LFxuICAgIHdyaXRhYmxlLFxuICB9KTtcbn1cbiIsICJpbXBvcnQge1xuICBjb252ZXJ0VG9Nb2RlbE1lc3NhZ2VzLFxuICB0eXBlIEZpbmlzaFJlYXNvbixcbiAgc3RyZWFtVGV4dCxcbiAgdHlwZSBVSU1lc3NhZ2UsXG59IGZyb20gXCJhaVwiO1xuaW1wb3J0IHsgdWxpZCB9IGZyb20gXCJ1bGlkXCI7XG5pbXBvcnQgeyBGYXRhbEVycm9yIH0gZnJvbSBcIndvcmtmbG93XCI7XG5pbXBvcnQgdHlwZSB7IE1jcFNlcnZlclNjaGVtYSB9IGZyb20gXCIuL21jcFwiO1xuaW1wb3J0IHsgZGlzY292ZXJTa2lsbHNJblNhbmRib3ggfSBmcm9tIFwiLi9za2lsbHMvZGlzY292ZXJcIjtcbmltcG9ydCB0eXBlIHsgU2tpbGxTdW1tYXJ5IH0gZnJvbSBcIi4vc2tpbGxzL3R5cGVzXCI7XG5pbXBvcnQgdHlwZSB7IFN0b3JhZ2VDb25maWcgfSBmcm9tIFwiLi9zdG9yYWdlXCI7XG5pbXBvcnQgeyBnZXRUb29scyB9IGZyb20gXCIuL3Rvb2xzXCI7XG5pbXBvcnQgeyBhc3NlbWJsZVVJTWVzc2FnZXMgfSBmcm9tIFwiLi91dGlscy91aVwiO1xuXG5jb25zdCBCQVNFX1NZU1RFTV9QUk9NUFQgPVxuICBcIllvdSBhcmUgYW4gQUkgYXNzaXN0YW50IHdpdGggYmFzaWMgdG9vbHMgdG8gaW50ZXJhY3Qgd2l0aCB5b3VyIGVudmlyb25tZW50LiBFeHBsb3JlIGFuZCB3b3JrIGZyZWVseS5cIjtcblxuZnVuY3Rpb24gam9pblByb21wdFNlY3Rpb25zKFxuICAuLi5zZWN0aW9uczogKHN0cmluZyB8IHVuZGVmaW5lZCB8IG51bGwpW11cbik6IHN0cmluZyB7XG4gIHJldHVybiBzZWN0aW9ucy5maWx0ZXIoKHMpID0+IHM/LnRyaW0oKSkuam9pbihcIlxcblxcblwiKTtcbn1cblxuZnVuY3Rpb24gYnVpbGRTa2lsbHNDb250ZXh0KHNraWxsczogU2tpbGxTdW1tYXJ5W10pOiBzdHJpbmcge1xuICBpZiAoc2tpbGxzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBcIlwiO1xuICB9XG5cbiAgY29uc3Qgc2tpbGxMaW5lcyA9IHNraWxsc1xuICAgIC5tYXAoKHMpID0+IGAtICR7cy5uYW1lfTogJHtzLmRlc2NyaXB0aW9ufVxcbiAgUGF0aDogJHtzLnNraWxsTWRQYXRofWApXG4gICAgLmpvaW4oXCJcXG5cIik7XG5cbiAgcmV0dXJuIGAjIyBBdmFpbGFibGUgU2tpbGxzXG4ke3NraWxsTGluZXN9XG5cbllvdSBjYW4gdXNlIHRoZSBSZWFkIHRvb2wgdG8gcmVhZCBhbnkgc2tpbGwncyBTS0lMTC5tZCBmaWxlIHRvIGxlYXJuIG1vcmUgYWJvdXQgaXQuYDtcbn1cblxuZnVuY3Rpb24gYnVpbGRNY3BUb29sc0NvbnRleHQobWNwOiBNY3BTZXJ2ZXJTY2hlbWFbXSB8IG51bGwgfCB1bmRlZmluZWQpOiBzdHJpbmcge1xuICBpZiAoIW1jcCB8fCBtY3AubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIFwiXCI7XG4gIH1cblxuICBjb25zdCBzZXJ2ZXJEb2NzID0gbWNwXG4gICAgLmZpbHRlcihcbiAgICAgIChcbiAgICAgICAgc1xuICAgICAgKTogcyBpcyBNY3BTZXJ2ZXJTY2hlbWEgJiB7XG4gICAgICAgIHRvb2xzOiBOb25OdWxsYWJsZTxNY3BTZXJ2ZXJTY2hlbWFbXCJ0b29sc1wiXT47XG4gICAgICB9ID0+IEFycmF5LmlzQXJyYXkocy50b29scykgJiYgcy50b29scy5sZW5ndGggPiAwXG4gICAgKVxuICAgIC5tYXAoKHNlcnZlcikgPT4ge1xuICAgICAgY29uc3QgdG9vbERvY3MgPSBzZXJ2ZXIudG9vbHNcbiAgICAgICAgLm1hcCgodCkgPT4ge1xuICAgICAgICAgIGxldCBkb2MgPSBgICAtICR7dC5uYW1lfTogJHtcbiAgICAgICAgICAgIHQuZGVzY3JpcHRpb25cbiAgICAgICAgICB9XFxuICAgIElucHV0OiAke0pTT04uc3RyaW5naWZ5KHQuaW5wdXRTY2hlbWEpfWA7XG4gICAgICAgICAgaWYgKHQub3V0cHV0U2NoZW1hKSB7XG4gICAgICAgICAgICBkb2MgKz0gYFxcbiAgICBPdXRwdXQ6ICR7SlNPTi5zdHJpbmdpZnkodC5vdXRwdXRTY2hlbWEpfWA7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBkb2M7XG4gICAgICAgIH0pXG4gICAgICAgIC5qb2luKFwiXFxuXCIpO1xuICAgICAgcmV0dXJuIGAjIyMgJHtzZXJ2ZXIubmFtZX1cXG4ke3NlcnZlci5kZXNjcmlwdGlvbiA/PyBcIlwifVxcbiR7dG9vbERvY3N9YDtcbiAgICB9KVxuICAgIC5qb2luKFwiXFxuXFxuXCIpO1xuXG4gIGlmICghc2VydmVyRG9jcykge1xuICAgIHJldHVybiBcIlwiO1xuICB9XG5cbiAgcmV0dXJuIGAjIyBNQ1AgVG9vbHNcblVzZSB0aGUgRXhlY3V0ZU1DUFRvb2wgdG8gY2FsbCB0aGVzZSBjdXN0b20gdG9vbHM6XG5cbiR7c2VydmVyRG9jc31gO1xufVxuXG5leHBvcnQgdHlwZSBBZ2VudElucHV0ID0ge1xuICBzZXNzaW9uSWQ6IHN0cmluZztcbiAgc3RvcmFnZUNvbmZpZzogU3RvcmFnZUNvbmZpZztcbn07XG5cbmV4cG9ydCB0eXBlIEFnZW50TWVzc2FnZUlucHV0ID0ge1xuICBhc3Npc3RhbnRNZXNzYWdlSWQ6IHN0cmluZztcbiAgaG9va1Rva2VuOiBzdHJpbmc7XG59O1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY29tcGxldGVNZXNzYWdlU3RlcCh7XG4gIGFzc2lzdGFudE1lc3NhZ2VJZCxcbiAgaW5wdXQsXG4gIHdyaXRhYmxlLFxufToge1xuICBhc3Npc3RhbnRNZXNzYWdlSWQ6IHN0cmluZztcbiAgaW5wdXQ6IEFnZW50SW5wdXQ7XG4gIHdyaXRhYmxlOiBXcml0YWJsZVN0cmVhbTtcbn0pIHtcbiAgXCJ1c2Ugc3RlcFwiO1xuXG4gIGNvbnN0IHsgZ2V0U3RvcmFnZSB9ID0gYXdhaXQgaW1wb3J0KFwiLi9zdG9yYWdlXCIpO1xuICBjb25zdCBzdG9yYWdlID0gZ2V0U3RvcmFnZShpbnB1dC5zdG9yYWdlQ29uZmlnKTtcblxuICBjb25zdCBtZXNzYWdlID0gYXdhaXQgc3RvcmFnZS5tZXNzYWdlLmdldChhc3Npc3RhbnRNZXNzYWdlSWQpO1xuICBpZiAobWVzc2FnZSBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgdGhyb3cgbWVzc2FnZTtcbiAgfVxuICBpZiAoIW1lc3NhZ2UpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYE1lc3NhZ2UgJHthc3Npc3RhbnRNZXNzYWdlSWR9IG5vdCBmb3VuZGApO1xuICB9XG5cbiAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3RvcmFnZS5tZXNzYWdlLnNldCh7XG4gICAgLi4ubWVzc2FnZSxcbiAgICBjb21wbGV0ZWRBdDogRGF0ZS5ub3coKSxcbiAgfSk7XG4gIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgIHRocm93IHJlc3VsdDtcbiAgfVxuXG4gIGF3YWl0IHdyaXRhYmxlLmNsb3NlKCk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzdHJlYW1UZXh0U3RlcCh7XG4gIGFzc2lzdGFudE1lc3NhZ2VJZCxcbiAgaW5wdXQsXG4gIGV2ZW50LFxuICB3cml0YWJsZSxcbiAgbGFzdFBhcnRJbmRleCxcbn06IHtcbiAgYXNzaXN0YW50TWVzc2FnZUlkOiBzdHJpbmc7XG4gIGlucHV0OiBBZ2VudElucHV0O1xuICBldmVudDogQWdlbnRNZXNzYWdlSW5wdXQ7XG4gIHdyaXRhYmxlOiBXcml0YWJsZVN0cmVhbTtcbiAgbGFzdFBhcnRJbmRleDogbnVtYmVyO1xufSk6IFByb21pc2U8eyBmaW5pc2hSZWFzb246IEZpbmlzaFJlYXNvbjsgbGFzdFBhcnRJbmRleDogbnVtYmVyIH0+IHtcbiAgXCJ1c2Ugc3RlcFwiO1xuXG4gIGNvbnN0IHsgZ2V0U3RvcmFnZSB9ID0gYXdhaXQgaW1wb3J0KFwiLi9zdG9yYWdlL2NsaWVudFwiKTtcbiAgY29uc3QgeyBnZXRTYW5kYm94IH0gPSBhd2FpdCBpbXBvcnQoXCIuL3NhbmRib3hcIik7XG5cbiAgY29uc3Qgc3RvcmFnZSA9IGdldFN0b3JhZ2UoaW5wdXQuc3RvcmFnZUNvbmZpZyk7XG4gIGNvbnN0IHNlc3Npb24gPSBhd2FpdCBzdG9yYWdlLnNlc3Npb24uZ2V0KGlucHV0LnNlc3Npb25JZCk7XG5cbiAgaWYgKHNlc3Npb24gaW5zdGFuY2VvZiBFcnJvcikge1xuICAgIHRocm93IHNlc3Npb247XG4gIH1cbiAgc2Vzc2lvbjtcblxuICBjb25zdCBzYW5kYm94UmVjb3JkID0gc2Vzc2lvbi5zYW5kYm94SWRcbiAgICA/IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5nZXQoc2Vzc2lvbi5zYW5kYm94SWQpXG4gICAgOiBudWxsO1xuICBpZiAoc2FuZGJveFJlY29yZCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgdGhyb3cgc2FuZGJveFJlY29yZDtcbiAgfVxuICBpZiAoIXNhbmRib3hSZWNvcmQpIHtcbiAgICB0aHJvdyBuZXcgRmF0YWxFcnJvcihgU2FuZGJveCBub3QgZm91bmQgZm9yIHNlc3Npb24gJHtpbnB1dC5zZXNzaW9uSWR9YCk7XG4gIH1cblxuICBjb25zdCBzYW5kYm94ID0gZ2V0U2FuZGJveCh7XG4gICAgc2FuZGJveFJlY29yZCxcbiAgICBzdG9yYWdlQ29uZmlnOiBpbnB1dC5zdG9yYWdlQ29uZmlnLFxuICB9KTtcblxuICBjb25zdCBbbWVzc2FnZXNSZXN1bHQsIHBhcnRzUmVzdWx0LCBza2lsbHNdID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgIHN0b3JhZ2UubWVzc2FnZS5saXN0KGlucHV0LnNlc3Npb25JZCksXG4gICAgc3RvcmFnZS5wYXJ0Lmxpc3RCeVNlc3Npb24oaW5wdXQuc2Vzc2lvbklkKSxcbiAgICBzZXNzaW9uLnNraWxsc0RpciAmJiBzZXNzaW9uLnNraWxsc0Rpci5sZW5ndGggPiAwXG4gICAgICA/IGRpc2NvdmVyU2tpbGxzSW5TYW5kYm94KHsgc2FuZGJveCwgc2tpbGxzRGlyczogc2Vzc2lvbi5za2lsbHNEaXIgfSlcbiAgICAgIDogUHJvbWlzZS5yZXNvbHZlKFtdKSxcbiAgXSk7XG5cbiAgaWYgKG1lc3NhZ2VzUmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICB0aHJvdyBtZXNzYWdlc1Jlc3VsdDtcbiAgfVxuICBpZiAocGFydHNSZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgIHRocm93IHBhcnRzUmVzdWx0O1xuICB9XG5cbiAgY29uc3QgdWlNZXNzYWdlcyA9IGFzc2VtYmxlVUlNZXNzYWdlcyh7XG4gICAgbWVzc2FnZXM6IG1lc3NhZ2VzUmVzdWx0Lml0ZW1zLFxuICAgIHBhcnRzOiBwYXJ0c1Jlc3VsdC5pdGVtcyxcbiAgfSk7XG5cbiAgY29uc3QgbWNwID0gc2Vzc2lvbi5tY3AgYXMgTWNwU2VydmVyU2NoZW1hW10gfCBudWxsO1xuXG4gIGNvbnN0IHN5c3RlbVByb21wdCA9IGpvaW5Qcm9tcHRTZWN0aW9ucyhcbiAgICBCQVNFX1NZU1RFTV9QUk9NUFQsXG4gICAgc2Vzc2lvbi5pbnN0cnVjdGlvbnMsXG4gICAgYnVpbGRTa2lsbHNDb250ZXh0KHNraWxscyksXG4gICAgYnVpbGRNY3BUb29sc0NvbnRleHQobWNwKVxuICApO1xuXG4gIGlmICghc2Vzc2lvbi5tb2RlbCkge1xuICAgIHRocm93IG5ldyBGYXRhbEVycm9yKFwiU2Vzc2lvbiBtb2RlbCBpcyBub3Qgc2V0XCIpO1xuICB9XG5cbiAgY29uc3QgcmVzdWx0ID0gc3RyZWFtVGV4dCh7XG4gICAgbWVzc2FnZXM6IGF3YWl0IGNvbnZlcnRUb01vZGVsTWVzc2FnZXModWlNZXNzYWdlcyksXG4gICAgdG9vbHM6IGdldFRvb2xzKHsgaW5wdXQsIGV2ZW50LCBtY3AsIHNhbmRib3ggfSksXG4gICAgc3lzdGVtOiBzeXN0ZW1Qcm9tcHQsXG4gICAgbW9kZWw6IHNlc3Npb24ubW9kZWwsXG4gIH0pO1xuXG4gIGNvbnN0IHN0ZXBQYXJ0czogVUlNZXNzYWdlW1wicGFydHNcIl0gPSBbXTtcbiAgYXdhaXQgcmVzdWx0XG4gICAgLnRvVUlNZXNzYWdlU3RyZWFtKHtcbiAgICAgIGdlbmVyYXRlTWVzc2FnZUlkOiAoKSA9PiBhc3Npc3RhbnRNZXNzYWdlSWQsXG4gICAgICBvbkZpbmlzaDogKHsgbWVzc2FnZXMgfSkgPT4ge1xuICAgICAgICBmb3IgKGNvbnN0IG0gb2YgbWVzc2FnZXMpIHtcbiAgICAgICAgICBpZiAobS5yb2xlID09PSBcImFzc2lzdGFudFwiKSB7XG4gICAgICAgICAgICBzdGVwUGFydHMucHVzaCguLi5tLnBhcnRzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSlcbiAgICAucGlwZVRvKHdyaXRhYmxlLCB7IHByZXZlbnRDbG9zZTogdHJ1ZSB9KTtcblxuICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICBzdGVwUGFydHMubWFwKGFzeW5jICh1aVBhcnQsIGluZGV4KSA9PiB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzdG9yYWdlLnBhcnQuc2V0KHtcbiAgICAgICAgaWQ6IGBwYXJ0XyR7dWxpZCgpfWAsXG4gICAgICAgIGluZGV4OiBsYXN0UGFydEluZGV4ICsgaW5kZXgsXG4gICAgICAgIG1lc3NhZ2VJZDogYXNzaXN0YW50TWVzc2FnZUlkLFxuICAgICAgICBzZXNzaW9uSWQ6IGlucHV0LnNlc3Npb25JZCxcbiAgICAgICAgcGFydDogdWlQYXJ0LFxuICAgICAgfSk7XG4gICAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgcmVzdWx0O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9KVxuICApO1xuXG4gIHJldHVybiB7XG4gICAgZmluaXNoUmVhc29uOiBhd2FpdCByZXN1bHQuZmluaXNoUmVhc29uLFxuICAgIGxhc3RQYXJ0SW5kZXg6IGxhc3RQYXJ0SW5kZXggKyBzdGVwUGFydHMubGVuZ3RoLFxuICB9O1xufVxuIiwgImltcG9ydCB0eXBlIHsgU2tpbGxzRGlyIH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuLyoqXG4gKiBQYXJzZWQgZnJvbnRtYXR0ZXIgZnJvbSBhIFNLSUxMLm1kIGZpbGUuXG4gKi9cbmV4cG9ydCB0eXBlIFNraWxsRnJvbnRtYXR0ZXIgPSB7XG4gIG5hbWU6IHN0cmluZztcbiAgZGVzY3JpcHRpb246IHN0cmluZztcbn07XG5cbi8qKlxuICogUGFyc2VzIFlBTUwgZnJvbnRtYXR0ZXIgZnJvbSBhIFNLSUxMLm1kIGZpbGUgY29udGVudC5cbiAqIEZyb250bWF0dGVyIG11c3QgYmUgYXQgdGhlIHN0YXJ0IG9mIHRoZSBmaWxlLCBkZWxpbWl0ZWQgYnkgYC0tLWAgbWFya2Vycy5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgbWFya2Rvd25cbiAqIC0tLVxuICogbmFtZTogY3N2XG4gKiBkZXNjcmlwdGlvbjogQW5hbHl6ZSBDU1YgZGF0YVxuICogLS0tXG4gKiAjIENTViBTa2lsbFxuICogLi4uXG4gKiBgYGBcbiAqXG4gKiBAcmV0dXJucyBQYXJzZWQgbmFtZSBhbmQgZGVzY3JpcHRpb24sIG9yIG51bGwgaWYgZnJvbnRtYXR0ZXIgaXMgbWlzc2luZy9pbnZhbGlkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVNraWxsRnJvbnRtYXR0ZXIoXG4gIGNvbnRlbnQ6IHN0cmluZ1xuKTogU2tpbGxGcm9udG1hdHRlciB8IG51bGwge1xuICBjb25zdCB0cmltbWVkID0gY29udGVudC50cmltKCk7XG5cbiAgaWYgKCF0cmltbWVkLnN0YXJ0c1dpdGgoXCItLS1cIikpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IGVuZE1hcmtlckluZGV4ID0gdHJpbW1lZC5pbmRleE9mKFwiLS0tXCIsIDMpO1xuICBpZiAoZW5kTWFya2VySW5kZXggPT09IC0xKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCBmcm9udG1hdHRlckJsb2NrID0gdHJpbW1lZC5zbGljZSgzLCBlbmRNYXJrZXJJbmRleCkudHJpbSgpO1xuICBjb25zdCBwYXJzZWQgPSBwYXJzZVNpbXBsZVlhbWwoZnJvbnRtYXR0ZXJCbG9jayk7XG5cbiAgaWYgKCEocGFyc2VkLm5hbWUgJiYgcGFyc2VkLmRlc2NyaXB0aW9uKSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiBTdHJpbmcocGFyc2VkLm5hbWUpLFxuICAgIGRlc2NyaXB0aW9uOiBTdHJpbmcocGFyc2VkLmRlc2NyaXB0aW9uKSxcbiAgfTtcbn1cblxuLyoqXG4gKiBQYXJzZXMgc2ltcGxlIFlBTUwga2V5LXZhbHVlIHBhaXJzIChzaW5nbGUtbGluZSB2YWx1ZXMgb25seSkuXG4gKiBUaGlzIGF2b2lkcyBhZGRpbmcgYSBmdWxsIFlBTUwgcGFyc2VyIGRlcGVuZGVuY3kgZm9yIGJhc2ljIGZyb250bWF0dGVyLlxuICovXG5mdW5jdGlvbiBwYXJzZVNpbXBsZVlhbWwoeWFtbDogc3RyaW5nKTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB7XG4gIGNvbnN0IHJlc3VsdDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuXG4gIGZvciAoY29uc3QgbGluZSBvZiB5YW1sLnNwbGl0KFwiXFxuXCIpKSB7XG4gICAgY29uc3QgdHJpbW1lZExpbmUgPSBsaW5lLnRyaW0oKTtcbiAgICBpZiAoIXRyaW1tZWRMaW5lIHx8IHRyaW1tZWRMaW5lLnN0YXJ0c1dpdGgoXCIjXCIpKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBjb25zdCBjb2xvbkluZGV4ID0gdHJpbW1lZExpbmUuaW5kZXhPZihcIjpcIik7XG4gICAgaWYgKGNvbG9uSW5kZXggPT09IC0xKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBjb25zdCBrZXkgPSB0cmltbWVkTGluZS5zbGljZSgwLCBjb2xvbkluZGV4KS50cmltKCk7XG4gICAgbGV0IHZhbHVlID0gdHJpbW1lZExpbmUuc2xpY2UoY29sb25JbmRleCArIDEpLnRyaW0oKTtcblxuICAgIC8vIFJlbW92ZSBzdXJyb3VuZGluZyBxdW90ZXMgaWYgcHJlc2VudFxuICAgIGlmIChcbiAgICAgICh2YWx1ZS5zdGFydHNXaXRoKCdcIicpICYmIHZhbHVlLmVuZHNXaXRoKCdcIicpKSB8fFxuICAgICAgKHZhbHVlLnN0YXJ0c1dpdGgoXCInXCIpICYmIHZhbHVlLmVuZHNXaXRoKFwiJ1wiKSlcbiAgICApIHtcbiAgICAgIHZhbHVlID0gdmFsdWUuc2xpY2UoMSwgLTEpO1xuICAgIH1cblxuICAgIGlmIChrZXkpIHtcbiAgICAgIHJlc3VsdFtrZXldID0gdmFsdWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBOb3JtYWxpemVzIHNraWxsc0RpciB0byBhbiBhcnJheSBvZiBzdHJpbmdzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbm9ybWFsaXplU2tpbGxzRGlycyhza2lsbHNEaXI/OiBTa2lsbHNEaXIpOiBzdHJpbmdbXSB7XG4gIGlmICghc2tpbGxzRGlyKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG4gIHJldHVybiBBcnJheS5pc0FycmF5KHNraWxsc0RpcikgPyBza2lsbHNEaXIgOiBbc2tpbGxzRGlyXTtcbn1cbiIsICJpbXBvcnQgdHlwZSB7IFNhbmRib3ggfSBmcm9tIFwiLi4vc2FuZGJveFwiO1xuaW1wb3J0IHsgcGFyc2VTa2lsbEZyb250bWF0dGVyIH0gZnJvbSBcIi4vcGFyc2VyXCI7XG5pbXBvcnQgdHlwZSB7IFNraWxsU3VtbWFyeSB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbi8qKlxuICogRGlzY292ZXJzIHNraWxscyBmcm9tIGRpcmVjdG9yaWVzIGluc2lkZSB0aGUgc2FuZGJveCBieSBmaW5kaW5nIGFuZCBwYXJzaW5nIFNLSUxMLm1kIGZpbGVzLlxuICogU2NhbnMgZWFjaCBkaXJlY3RvcnkgZm9yIHN1YmRpcmVjdG9yaWVzIGNvbnRhaW5pbmcgU0tJTEwubWQsIGV4dHJhY3RzIGZyb250bWF0dGVyIG1ldGFkYXRhLFxuICogYW5kIHJldHVybnMgc3VtbWFyaWVzIGZvciB1c2UgaW4gdGhlIHN5c3RlbSBwcm9tcHQuXG4gKlxuICogQHJldHVybnMgQXJyYXkgb2Ygc2tpbGwgc3VtbWFyaWVzIChkZWR1cGxpY2F0ZWQgYnkgbmFtZSwgZmlyc3Qgb2NjdXJyZW5jZSB3aW5zKVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZGlzY292ZXJTa2lsbHNJblNhbmRib3gob3B0czoge1xuICBzYW5kYm94OiBTYW5kYm94O1xuICBza2lsbHNEaXJzOiBzdHJpbmdbXTtcbiAgZGVidWc/OiBib29sZWFuO1xufSk6IFByb21pc2U8U2tpbGxTdW1tYXJ5W10+IHtcbiAgY29uc3QgeyBzYW5kYm94LCBza2lsbHNEaXJzLCBkZWJ1ZyB9ID0gb3B0cztcbiAgY29uc3Qgc3VtbWFyaWVzOiBTa2lsbFN1bW1hcnlbXSA9IFtdO1xuICBjb25zdCBzZWVuTmFtZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcblxuICBmb3IgKGNvbnN0IHNraWxsc0RpciBvZiBza2lsbHNEaXJzKSB7XG4gICAgY29uc3QgZGlyU3VtbWFyaWVzID0gYXdhaXQgZGlzY292ZXJTa2lsbHNJbkRpcmVjdG9yeSh7XG4gICAgICBzYW5kYm94LFxuICAgICAgc2tpbGxzRGlyLFxuICAgICAgZGVidWcsXG4gICAgfSk7XG5cbiAgICBmb3IgKGNvbnN0IHN1bW1hcnkgb2YgZGlyU3VtbWFyaWVzKSB7XG4gICAgICBpZiAoIXNlZW5OYW1lcy5oYXMoc3VtbWFyeS5uYW1lKSkge1xuICAgICAgICBzZWVuTmFtZXMuYWRkKHN1bW1hcnkubmFtZSk7XG4gICAgICAgIHN1bW1hcmllcy5wdXNoKHN1bW1hcnkpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBzdW1tYXJpZXM7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGRpc2NvdmVyU2tpbGxzSW5EaXJlY3Rvcnkob3B0czoge1xuICBzYW5kYm94OiBTYW5kYm94O1xuICBza2lsbHNEaXI6IHN0cmluZztcbiAgZGVidWc/OiBib29sZWFuO1xufSk6IFByb21pc2U8U2tpbGxTdW1tYXJ5W10+IHtcbiAgY29uc3QgeyBzYW5kYm94LCBza2lsbHNEaXIsIGRlYnVnIH0gPSBvcHRzO1xuICBjb25zdCBza2lsbFBhdGhzID0gYXdhaXQgZmluZFNraWxsRmlsZXMoeyBzYW5kYm94LCBza2lsbHNEaXIsIGRlYnVnIH0pO1xuXG4gIGlmIChza2lsbFBhdGhzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIGNvbnN0IHN1bW1hcmllczogU2tpbGxTdW1tYXJ5W10gPSBbXTtcblxuICBmb3IgKGNvbnN0IHNraWxsTWRQYXRoIG9mIHNraWxsUGF0aHMpIHtcbiAgICBjb25zdCBzdW1tYXJ5ID0gYXdhaXQgcGFyc2VTa2lsbEZpbGUoeyBzYW5kYm94LCBza2lsbE1kUGF0aCwgZGVidWcgfSk7XG4gICAgaWYgKHN1bW1hcnkpIHtcbiAgICAgIHN1bW1hcmllcy5wdXNoKHN1bW1hcnkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBzdW1tYXJpZXM7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGZpbmRTa2lsbEZpbGVzKG9wdHM6IHtcbiAgc2FuZGJveDogU2FuZGJveDtcbiAgc2tpbGxzRGlyOiBzdHJpbmc7XG4gIGRlYnVnPzogYm9vbGVhbjtcbn0pOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gIGNvbnN0IHsgc2FuZGJveCwgc2tpbGxzRGlyLCBkZWJ1ZyB9ID0gb3B0cztcbiAgaWYgKGRlYnVnKSB7XG4gICAgY29uc29sZS5sb2coYFtkaXNjb3Zlcl0gRmluZGluZyBza2lsbHMgaW46ICR7c2tpbGxzRGlyfWApO1xuICB9XG4gIGNvbnN0IGV4ZWNSZXN1bHQgPSBhd2FpdCBzYW5kYm94LmV4ZWMoe1xuICAgIGNvbW1hbmQ6IFwiZmluZFwiLFxuICAgIGFyZ3M6IFtza2lsbHNEaXIsIFwiLW5hbWVcIiwgXCJTS0lMTC5tZFwiLCBcIi10eXBlXCIsIFwiZlwiXSxcbiAgfSk7XG5cbiAgaWYgKGV4ZWNSZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgIGlmIChkZWJ1Zykge1xuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBgW2Rpc2NvdmVyXSBGYWlsZWQgdG8gc2NhbiBza2lsbHMgZGlyZWN0b3J5IFwiJHtza2lsbHNEaXJ9XCI6ICR7ZXhlY1Jlc3VsdC5tZXNzYWdlfWBcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIGNvbnN0IHsgc3Rkb3V0LCBzdGRlcnIsIGV4aXRDb2RlIH0gPSBhd2FpdCBleGVjUmVzdWx0LnJlc3VsdDtcbiAgaWYgKGRlYnVnKSB7XG4gICAgY29uc29sZS5sb2coXG4gICAgICBgW2Rpc2NvdmVyXSBmaW5kIHJlc3VsdDogZXhpdENvZGU9JHtleGl0Q29kZX0sIHN0ZG91dD1cIiR7c3Rkb3V0LnRyaW0oKX1cIiwgc3RkZXJyPVwiJHtzdGRlcnIudHJpbSgpfVwiYFxuICAgICk7XG4gIH1cblxuICBpZiAoZXhpdENvZGUgIT09IDApIHtcbiAgICBpZiAoZGVidWcpIHtcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgYFtkaXNjb3Zlcl0gU2tpbGxzIGRpcmVjdG9yeSBub3QgZm91bmQgb3IgaW5hY2Nlc3NpYmxlOiAke3NraWxsc0Rpcn1gXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gW107XG4gIH1cblxuICBjb25zdCBwYXRocyA9IHN0ZG91dFxuICAgIC50cmltKClcbiAgICAuc3BsaXQoXCJcXG5cIilcbiAgICAuZmlsdGVyKChwKSA9PiBwLmxlbmd0aCA+IDApO1xuICBpZiAoZGVidWcpIHtcbiAgICBjb25zb2xlLmxvZyhcIltkaXNjb3Zlcl0gRm91bmQgc2tpbGwgcGF0aHM6XCIsIHBhdGhzKTtcbiAgfVxuICByZXR1cm4gcGF0aHM7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHBhcnNlU2tpbGxGaWxlKG9wdHM6IHtcbiAgc2FuZGJveDogU2FuZGJveDtcbiAgc2tpbGxNZFBhdGg6IHN0cmluZztcbiAgZGVidWc/OiBib29sZWFuO1xufSk6IFByb21pc2U8U2tpbGxTdW1tYXJ5IHwgbnVsbD4ge1xuICBjb25zdCB7IHNhbmRib3gsIHNraWxsTWRQYXRoLCBkZWJ1ZyB9ID0gb3B0cztcbiAgY29uc3QgZXhlY1Jlc3VsdCA9IGF3YWl0IHNhbmRib3guZXhlYyh7XG4gICAgY29tbWFuZDogXCJjYXRcIixcbiAgICBhcmdzOiBbc2tpbGxNZFBhdGhdLFxuICB9KTtcblxuICBpZiAoZXhlY1Jlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgaWYgKGRlYnVnKSB7XG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgIGBbZGlzY292ZXJdIEZhaWxlZCB0byByZWFkIHNraWxsIGZpbGUgXCIke3NraWxsTWRQYXRofVwiOiAke2V4ZWNSZXN1bHQubWVzc2FnZX1gXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IHsgc3Rkb3V0LCBleGl0Q29kZSB9ID0gYXdhaXQgZXhlY1Jlc3VsdC5yZXN1bHQ7XG5cbiAgaWYgKGV4aXRDb2RlICE9PSAwKSB7XG4gICAgaWYgKGRlYnVnKSB7XG4gICAgICBjb25zb2xlLndhcm4oYFtkaXNjb3Zlcl0gQ291bGQgbm90IHJlYWQgc2tpbGwgZmlsZTogJHtza2lsbE1kUGF0aH1gKTtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCBwYXJzZWQgPSBwYXJzZVNraWxsRnJvbnRtYXR0ZXIoc3Rkb3V0KTtcblxuICBpZiAoIXBhcnNlZCkge1xuICAgIGlmIChkZWJ1Zykge1xuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBgW2Rpc2NvdmVyXSBJbnZhbGlkIG9yIG1pc3NpbmcgZnJvbnRtYXR0ZXIgaW46ICR7c2tpbGxNZFBhdGh9YFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIG5hbWU6IHBhcnNlZC5uYW1lLFxuICAgIGRlc2NyaXB0aW9uOiBwYXJzZWQuZGVzY3JpcHRpb24sXG4gICAgc2tpbGxNZFBhdGgsXG4gIH07XG59XG4iLCAiaW1wb3J0IHsgdHlwZSBUb29sU2V0LCB0b29sIH0gZnJvbSBcImFpXCI7XG5pbXBvcnQgeyB6IH0gZnJvbSBcInpvZFwiO1xuaW1wb3J0IHR5cGUgeyBBZ2VudElucHV0LCBBZ2VudE1lc3NhZ2VJbnB1dCB9IGZyb20gXCIuLi9hZ2VudC13b3JrZmxvd1wiO1xuaW1wb3J0IHR5cGUgeyBNY3BTZXJ2ZXJTY2hlbWEgfSBmcm9tIFwiLi4vbWNwXCI7XG5pbXBvcnQgdHlwZSB7IFNhbmRib3ggfSBmcm9tIFwiLi4vc2FuZGJveFwiO1xuXG5leHBvcnQgdHlwZSBUb29sQ29udGV4dCA9IHtcbiAgaW5wdXQ6IEFnZW50SW5wdXQ7XG4gIGV2ZW50OiBBZ2VudE1lc3NhZ2VJbnB1dDtcbiAgbWNwOiBNY3BTZXJ2ZXJTY2hlbWFbXSB8IG51bGw7XG4gIHNhbmRib3g6IFNhbmRib3g7XG4gIHdhaXRVbnRpbD86IChwcm9taXNlOiBQcm9taXNlPHVua25vd24+KSA9PiB2b2lkO1xufTtcblxuZXhwb3J0IGZ1bmN0aW9uIGdldFRvb2xzKGNvbnRleHQ6IFRvb2xDb250ZXh0KSB7XG4gIHJldHVybiB7XG4gICAgUmVhZDogdG9vbCh7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgXCJSZWFkcyBhIGZpbGUgYW5kIHJldHVybnMgaXRzIGNvbnRlbnRzIHdpdGggbWV0YWRhdGEuIEZvciBmaWxlcyBvdmVyIDIwMCBsaW5lcywgYXV0b21hdGljYWxseSBzaG93cyBmaXJzdCAxMDAgbGluZXMgdW5sZXNzIGEgc3BlY2lmaWMgbGluZSByYW5nZSBpcyBwcm92aWRlZC4gVXNlIHN0YXJ0TGluZSBhbmQgZW5kTGluZSBwYXJhbWV0ZXJzIHRvIHJlYWQgc3BlY2lmaWMgcG9ydGlvbnMgb2YgbGFyZ2UgZmlsZXMuXCIsXG4gICAgICBpbnB1dFNjaGVtYTogei5vYmplY3Qoe1xuICAgICAgICBwYXRoOiB6XG4gICAgICAgICAgLnN0cmluZygpXG4gICAgICAgICAgLmRlc2NyaWJlKFwiUGF0aCB0byB0aGUgZmlsZSByZWxhdGl2ZSB0byB3b3Jrc3BhY2Ugcm9vdFwiKSxcbiAgICAgICAgc3RhcnRMaW5lOiB6XG4gICAgICAgICAgLm51bWJlcigpXG4gICAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgICBcIlN0YXJ0aW5nIGxpbmUgbnVtYmVyICgxLWluZGV4ZWQpLiBJZiBwcm92aWRlZCB3aXRoIGVuZExpbmUsIHJlYWRzIGV4YWN0IHJhbmdlIHJlZ2FyZGxlc3Mgb2YgZmlsZSBzaXplLlwiXG4gICAgICAgICAgKSxcbiAgICAgICAgZW5kTGluZTogelxuICAgICAgICAgIC5udW1iZXIoKVxuICAgICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgICAgLmRlc2NyaWJlKFxuICAgICAgICAgICAgXCJFbmRpbmcgbGluZSBudW1iZXIgKDEtaW5kZXhlZCwgaW5jbHVzaXZlKS4gSWYgcHJvdmlkZWQgd2l0aCBzdGFydExpbmUsIHJlYWRzIGV4YWN0IHJhbmdlIHJlZ2FyZGxlc3Mgb2YgZmlsZSBzaXplLlwiXG4gICAgICAgICAgKSxcbiAgICAgIH0pLFxuICAgICAgb3V0cHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4gICAgICAgIGNvbnRlbnQ6IHouc3RyaW5nKCkuZGVzY3JpYmUoXCJGaWxlIGNvbnRlbnRcIiksXG4gICAgICAgIG1ldGFkYXRhOiB6Lm9iamVjdCh7XG4gICAgICAgICAgdG90YWxMaW5lczogei5udW1iZXIoKS5kZXNjcmliZShcIlRvdGFsIG51bWJlciBvZiBsaW5lcyBpbiB0aGUgZmlsZVwiKSxcbiAgICAgICAgICBsaW5lc1Nob3duOiB6XG4gICAgICAgICAgICAubnVtYmVyKClcbiAgICAgICAgICAgIC5kZXNjcmliZShcIk51bWJlciBvZiBsaW5lcyBpbmNsdWRlZCBpbiB0aGlzIHJlc3BvbnNlXCIpLFxuICAgICAgICAgIHN0YXJ0TGluZTogei5udW1iZXIoKS5kZXNjcmliZShcIkZpcnN0IGxpbmUgbnVtYmVyIHNob3duICgxLWluZGV4ZWQpXCIpLFxuICAgICAgICAgIGVuZExpbmU6IHoubnVtYmVyKCkuZGVzY3JpYmUoXCJMYXN0IGxpbmUgbnVtYmVyIHNob3duICgxLWluZGV4ZWQpXCIpLFxuICAgICAgICAgIGlzUGFnaW5hdGVkOiB6XG4gICAgICAgICAgICAuYm9vbGVhbigpXG4gICAgICAgICAgICAuZGVzY3JpYmUoXCJXaGV0aGVyIHRoaXMgaXMgYSBwYXJ0aWFsIHZpZXcgb2YgdGhlIGZpbGVcIiksXG4gICAgICAgICAgZmlsZVNpemU6IHpcbiAgICAgICAgICAgIC5zdHJpbmcoKVxuICAgICAgICAgICAgLmRlc2NyaWJlKFwiSHVtYW4tcmVhZGFibGUgZmlsZSBzaXplIChlLmcuLCAnMi41SycsICcxLjJNJylcIiksXG4gICAgICAgICAgcGF0aDogelxuICAgICAgICAgICAgLnN0cmluZygpXG4gICAgICAgICAgICAuZGVzY3JpYmUoXCJQYXRoIHRvIHRoZSBmaWxlIHJlbGF0aXZlIHRvIHdvcmtzcGFjZSByb290XCIpLFxuICAgICAgICB9KSxcbiAgICAgIH0pLFxuICAgICAgZXhlY3V0ZTogYXN5bmMgKHsgcGF0aCwgc3RhcnRMaW5lLCBlbmRMaW5lIH0pID0+IHtcbiAgICAgICAgY29uc3QgZmlsZVBhdGggPSBwYXRoLnN0YXJ0c1dpdGgoXCIvXCIpID8gcGF0aC5zbGljZSgxKSA6IHBhdGg7XG5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udGV4dC5zYW5kYm94LmV4ZWMoe1xuICAgICAgICAgIGNvbW1hbmQ6IFwiYmFzaFwiLFxuICAgICAgICAgIGFyZ3M6IFtcbiAgICAgICAgICAgIFwiLWNcIixcbiAgICAgICAgICAgIGBcbiAgICAgICAgICAgIHNldCAtZVxuICAgICAgICAgICAgRklMRT1cIiQxXCJcbiAgICAgICAgICAgIFNUQVJUX0xJTkU9XCIkMlwiXG4gICAgICAgICAgICBFTkRfTElORT1cIiQzXCJcblxuICAgICAgICAgICAgIyBSZXNvbHZlIHN5bWxpbmtzIGFuZCBjaGVjayBmaWxlIGV4aXN0c1xuICAgICAgICAgICAgaWYgWyAtTCBcIiRGSUxFXCIgXTsgdGhlblxuICAgICAgICAgICAgICBSRVNPTFZFRD0kKHJlYWRsaW5rIC1mIFwiJEZJTEVcIiAyPi9kZXYvbnVsbCB8fCBlY2hvIFwiXCIpXG4gICAgICAgICAgICAgIGlmIFsgLXogXCIkUkVTT0xWRURcIiBdIHx8IFsgISAtZSBcIiRSRVNPTFZFRFwiIF07IHRoZW5cbiAgICAgICAgICAgICAgICBlY2hvIFwiRXJyb3I6IEJyb2tlbiBzeW1saW5rIC0gJEZJTEUgcG9pbnRzIHRvIG5vbi1leGlzdGVudCB0YXJnZXRcIiA+JjJcbiAgICAgICAgICAgICAgICBleGl0IDFcbiAgICAgICAgICAgICAgZmlcbiAgICAgICAgICAgICAgRklMRT1cIiRSRVNPTFZFRFwiXG4gICAgICAgICAgICBlbGlmIFsgISAtZSBcIiRGSUxFXCIgXTsgdGhlblxuICAgICAgICAgICAgICBlY2hvIFwiRXJyb3I6IEZpbGUgbm90IGZvdW5kIC0gJEZJTEVcIiA+JjJcbiAgICAgICAgICAgICAgZXhpdCAxXG4gICAgICAgICAgICBmaVxuXG4gICAgICAgICAgICAjIEdldCBtZXRhZGF0YSAoY291bnQgYWN0dWFsIGxpbmVzLCBub3QganVzdCBuZXdsaW5lcylcbiAgICAgICAgICAgIFRPVEFMX0xJTkVTPSQoYXdrICdFTkR7cHJpbnQgTlJ9JyBcIiRGSUxFXCIpXG4gICAgICAgICAgICBGSUxFX1NJWkU9JChscyAtbGggXCIkRklMRVwiIHwgYXdrICd7cHJpbnQgJDV9JylcblxuICAgICAgICAgICAgIyBEZXRlcm1pbmUgcmFuZ2VcbiAgICAgICAgICAgIFBBR0VfU0laRT0xMDBcbiAgICAgICAgICAgIGlmIFsgLW4gXCIkU1RBUlRfTElORVwiIF0gJiYgWyAtbiBcIiRFTkRfTElORVwiIF07IHRoZW5cbiAgICAgICAgICAgICAgIyBCb3RoIHByb3ZpZGVkIC0gdXNlIGV4YWN0IHJhbmdlXG4gICAgICAgICAgICAgIEFDVFVBTF9TVEFSVD0kU1RBUlRfTElORVxuICAgICAgICAgICAgICBBQ1RVQUxfRU5EPSRFTkRfTElORVxuICAgICAgICAgICAgZWxpZiBbIC1uIFwiJFNUQVJUX0xJTkVcIiBdOyB0aGVuXG4gICAgICAgICAgICAgICMgT25seSBzdGFydExpbmUgLSByZWFkIFBBR0VfU0laRSBsaW5lcyBmcm9tIHRoZXJlXG4gICAgICAgICAgICAgIEFDVFVBTF9TVEFSVD0kU1RBUlRfTElORVxuICAgICAgICAgICAgICBBQ1RVQUxfRU5EPSQoKFNUQVJUX0xJTkUgKyBQQUdFX1NJWkUgLSAxKSlcbiAgICAgICAgICAgICAgWyBcIiRBQ1RVQUxfRU5EXCIgLWd0IFwiJFRPVEFMX0xJTkVTXCIgXSAmJiBBQ1RVQUxfRU5EPSRUT1RBTF9MSU5FU1xuICAgICAgICAgICAgZWxpZiBbIC1uIFwiJEVORF9MSU5FXCIgXTsgdGhlblxuICAgICAgICAgICAgICAjIE9ubHkgZW5kTGluZSAtIHJlYWQgZnJvbSBiZWdpbm5pbmcgdG8gZW5kTGluZVxuICAgICAgICAgICAgICBBQ1RVQUxfU1RBUlQ9MVxuICAgICAgICAgICAgICBBQ1RVQUxfRU5EPSRFTkRfTElORVxuICAgICAgICAgICAgZWxpZiBbIFwiJFRPVEFMX0xJTkVTXCIgLWd0IDIwMCBdOyB0aGVuXG4gICAgICAgICAgICAgICMgTm8gcmFuZ2UsIGxhcmdlIGZpbGUgLSBwYWdpbmF0ZVxuICAgICAgICAgICAgICBBQ1RVQUxfU1RBUlQ9MVxuICAgICAgICAgICAgICBBQ1RVQUxfRU5EPSRQQUdFX1NJWkVcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgIyBObyByYW5nZSwgc21hbGwgZmlsZSAtIHNob3cgYWxsXG4gICAgICAgICAgICAgIEFDVFVBTF9TVEFSVD0xXG4gICAgICAgICAgICAgIEFDVFVBTF9FTkQ9JFRPVEFMX0xJTkVTXG4gICAgICAgICAgICBmaVxuXG4gICAgICAgICAgICAjIE91dHB1dCBtZXRhZGF0YSBmaXJzdCAoc2VwYXJhdGVkIGJ5IHx8fCBmb3IgcGFyc2luZylcbiAgICAgICAgICAgIGVjaG8gXCIkVE9UQUxfTElORVN8JEZJTEVfU0laRXwkQUNUVUFMX1NUQVJUfCRBQ1RVQUxfRU5EXCJcbiAgICAgICAgICAgIGVjaG8gXCJ8fHxDT05URU5UfHx8XCJcblxuICAgICAgICAgICAgIyBSZWFkIGNvbnRlbnRcbiAgICAgICAgICAgIGlmIFsgXCIkQUNUVUFMX1NUQVJUXCIgLWVxIDEgXSAmJiBbIFwiJEFDVFVBTF9FTkRcIiAtZXEgXCIkVE9UQUxfTElORVNcIiBdOyB0aGVuXG4gICAgICAgICAgICAgIGNhdCBcIiRGSUxFXCJcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgc2VkIC1uIFwiXFwke0FDVFVBTF9TVEFSVH0sXFwke0FDVFVBTF9FTkR9cFwiIFwiJEZJTEVcIlxuICAgICAgICAgICAgZmlcbiAgICAgICAgICBgLFxuICAgICAgICAgICAgXCItLVwiLFxuICAgICAgICAgICAgZmlsZVBhdGgsXG4gICAgICAgICAgICBzdGFydExpbmU/LnRvU3RyaW5nKCkgfHwgXCJcIixcbiAgICAgICAgICAgIGVuZExpbmU/LnRvU3RyaW5nKCkgfHwgXCJcIixcbiAgICAgICAgICBdLFxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKFwiW1JlYWQgVG9vbF1cIiwgcmVzdWx0KTtcbiAgICAgICAgICB0aHJvdyByZXN1bHQ7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB7IHN0ZG91dCwgc3RkZXJyIH0gPSBhd2FpdCByZXN1bHQucmVzdWx0O1xuXG4gICAgICAgIGlmIChzdGRlcnIpIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKGBbUmVhZCBUb29sXSBFcnJvcjogJHtzdGRlcnJ9YCk7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGNvbnRlbnQ6IGBFcnJvcjogJHtzdGRlcnJ9YCxcbiAgICAgICAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgICAgICAgIHRvdGFsTGluZXM6IDAsXG4gICAgICAgICAgICAgIGxpbmVzU2hvd246IDAsXG4gICAgICAgICAgICAgIHN0YXJ0TGluZTogMCxcbiAgICAgICAgICAgICAgZW5kTGluZTogMCxcbiAgICAgICAgICAgICAgaXNQYWdpbmF0ZWQ6IGZhbHNlLFxuICAgICAgICAgICAgICBmaWxlU2l6ZTogXCIwXCIsXG4gICAgICAgICAgICAgIHBhdGg6IGZpbGVQYXRoLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgW21ldGFkYXRhTGluZSwgLi4ucmVzdF0gPSBzdGRvdXQuc3BsaXQoXCJ8fHxDT05URU5UfHx8XCIpO1xuICAgICAgICBjb25zdCBjb250ZW50ID0gcmVzdC5qb2luKFwifHx8Q09OVEVOVHx8fFwiKS50cmltU3RhcnQoKTtcbiAgICAgICAgY29uc3QgW3RvdGFsTGluZXNTdHIsIGZpbGVTaXplLCBhY3R1YWxTdGFydFN0ciwgYWN0dWFsRW5kU3RyXSA9XG4gICAgICAgICAgbWV0YWRhdGFMaW5lLnRyaW0oKS5zcGxpdChcInxcIik7XG5cbiAgICAgICAgY29uc3QgdG90YWxMaW5lcyA9IE51bWJlci5wYXJzZUludCh0b3RhbExpbmVzU3RyLCAxMCk7XG4gICAgICAgIGNvbnN0IGFjdHVhbFN0YXJ0ID0gTnVtYmVyLnBhcnNlSW50KGFjdHVhbFN0YXJ0U3RyLCAxMCk7XG4gICAgICAgIGNvbnN0IGFjdHVhbEVuZCA9IE51bWJlci5wYXJzZUludChhY3R1YWxFbmRTdHIsIDEwKTtcblxuICAgICAgICBpZiAoXG4gICAgICAgICAgTnVtYmVyLmlzTmFOKHRvdGFsTGluZXMpIHx8XG4gICAgICAgICAgTnVtYmVyLmlzTmFOKGFjdHVhbFN0YXJ0KSB8fFxuICAgICAgICAgIE51bWJlci5pc05hTihhY3R1YWxFbmQpXG4gICAgICAgICkge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgICAgICBgW1JlYWQgVG9vbF0gRmFpbGVkIHRvIHBhcnNlIG1ldGFkYXRhOiAke21ldGFkYXRhTGluZX1gXG4gICAgICAgICAgKTtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgY29udGVudDogYEVycm9yOiBGYWlsZWQgdG8gcGFyc2UgZmlsZSBtZXRhZGF0YS4gUmF3IG91dHB1dDogJHtzdGRvdXQuc2xpY2UoXG4gICAgICAgICAgICAgIDAsXG4gICAgICAgICAgICAgIDUwMFxuICAgICAgICAgICAgKX1gLFxuICAgICAgICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgICAgICAgdG90YWxMaW5lczogMCxcbiAgICAgICAgICAgICAgbGluZXNTaG93bjogMCxcbiAgICAgICAgICAgICAgc3RhcnRMaW5lOiAwLFxuICAgICAgICAgICAgICBlbmRMaW5lOiAwLFxuICAgICAgICAgICAgICBpc1BhZ2luYXRlZDogZmFsc2UsXG4gICAgICAgICAgICAgIGZpbGVTaXplOiBcInVua25vd25cIixcbiAgICAgICAgICAgICAgcGF0aDogZmlsZVBhdGgsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGNvbnRlbnQsXG4gICAgICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgICAgIHRvdGFsTGluZXMsXG4gICAgICAgICAgICBsaW5lc1Nob3duOiBNYXRoLm1heCgwLCBhY3R1YWxFbmQgLSBhY3R1YWxTdGFydCArIDEpLFxuICAgICAgICAgICAgc3RhcnRMaW5lOiBhY3R1YWxTdGFydCxcbiAgICAgICAgICAgIGVuZExpbmU6IGFjdHVhbEVuZCxcbiAgICAgICAgICAgIGlzUGFnaW5hdGVkOiBhY3R1YWxFbmQgPCB0b3RhbExpbmVzLFxuICAgICAgICAgICAgZmlsZVNpemU6IGZpbGVTaXplIHx8IFwidW5rbm93blwiLFxuICAgICAgICAgICAgcGF0aDogZmlsZVBhdGgsXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICAgIH0sXG4gICAgfSksXG4gICAgR3JlcDogdG9vbCh7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgXCJTZWFyY2ggZm9yIHBhdHRlcm5zIGluIGZpbGVzIHVzaW5nIHJpcGdyZXAuIFN1cHBvcnRzIHJlZ2V4IHBhdHRlcm5zLCBmaWxlIHR5cGUgZmlsdGVyaW5nLCBhbmQgY29udGV4dCBsaW5lcy4gUmV0dXJucyBtYXRjaGluZyBsaW5lcyB3aXRoIGZpbGUgcGF0aHMgYW5kIGxpbmUgbnVtYmVycy4gVXNlIHRoaXMgdG8gZmluZCBjb2RlIHBhdHRlcm5zLCBmdW5jdGlvbiBkZWZpbml0aW9ucywgaW1wb3J0cywgZXRjLlwiLFxuICAgICAgaW5wdXRTY2hlbWE6IHoub2JqZWN0KHtcbiAgICAgICAgcGF0dGVybjogelxuICAgICAgICAgIC5zdHJpbmcoKVxuICAgICAgICAgIC5kZXNjcmliZShcIlJlZ2V4IHBhdHRlcm4gdG8gc2VhcmNoIGZvciAocmlwZ3JlcCBzeW50YXgpXCIpLFxuICAgICAgICBwYXRoOiB6XG4gICAgICAgICAgLnN0cmluZygpXG4gICAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgICBcIlBhdGggdG8gc2VhcmNoIGluIChkZWZhdWx0cyB0byB3b3Jrc3BhY2Ugcm9vdCkuIENhbiBiZSBhIGZpbGUgb3IgZGlyZWN0b3J5LlwiXG4gICAgICAgICAgKSxcbiAgICAgICAgZmlsZVR5cGU6IHpcbiAgICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAgIC5kZXNjcmliZShcbiAgICAgICAgICAgIFwiRmlsZSB0eXBlIHRvIGZpbHRlciBieSAoZS5nLiwgJ3RzJywgJ2pzJywgJ3B5JywgJ21kJykuIFVzZXMgcmlwZ3JlcCdzIGJ1aWx0LWluIHR5cGUgZmlsdGVycy5cIlxuICAgICAgICAgICksXG4gICAgICAgIGdsb2I6IHpcbiAgICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAgIC5kZXNjcmliZShcbiAgICAgICAgICAgIFwiR2xvYiBwYXR0ZXJuIHRvIGZpbHRlciBmaWxlcyAoZS5nLiwgJyoudHN4JywgJ3NyYy8qKi8qLnRzJylcIlxuICAgICAgICAgICksXG4gICAgICAgIGNhc2VTZW5zaXRpdmU6IHpcbiAgICAgICAgICAuYm9vbGVhbigpXG4gICAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgICAuZGVmYXVsdCh0cnVlKVxuICAgICAgICAgIC5kZXNjcmliZShcIldoZXRoZXIgc2VhcmNoIGlzIGNhc2Utc2Vuc2l0aXZlIChkZWZhdWx0OiB0cnVlKVwiKSxcbiAgICAgICAgY29udGV4dExpbmVzOiB6XG4gICAgICAgICAgLm51bWJlcigpXG4gICAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgICBcIk51bWJlciBvZiBjb250ZXh0IGxpbmVzIHRvIHNob3cgYmVmb3JlIGFuZCBhZnRlciBlYWNoIG1hdGNoXCJcbiAgICAgICAgICApLFxuICAgICAgICBtYXhDb3VudDogelxuICAgICAgICAgIC5udW1iZXIoKVxuICAgICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgICAgLmRlc2NyaWJlKFxuICAgICAgICAgICAgXCJNYXhpbXVtIG51bWJlciBvZiBtYXRjaGVzIHBlciBmaWxlICh1c2VmdWwgZm9yIGxpbWl0aW5nIG91dHB1dClcIlxuICAgICAgICAgICksXG4gICAgICAgIGZpbGVzV2l0aE1hdGNoZXM6IHpcbiAgICAgICAgICAuYm9vbGVhbigpXG4gICAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgICAuZGVmYXVsdChmYWxzZSlcbiAgICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgICBcIk9ubHkgc2hvdyBmaWxlIHBhdGhzIHRoYXQgY29udGFpbiBtYXRjaGVzLCBub3QgdGhlIG1hdGNoaW5nIGxpbmVzIHRoZW1zZWx2ZXNcIlxuICAgICAgICAgICksXG4gICAgICB9KSxcbiAgICAgIG91dHB1dFNjaGVtYTogei5vYmplY3Qoe1xuICAgICAgICBtYXRjaGVzOiB6XG4gICAgICAgICAgLnN0cmluZygpXG4gICAgICAgICAgLmRlc2NyaWJlKFxuICAgICAgICAgICAgXCJTZWFyY2ggcmVzdWx0cyB3aXRoIGZpbGUgcGF0aHMsIGxpbmUgbnVtYmVycywgYW5kIG1hdGNoaW5nIGNvbnRlbnRcIlxuICAgICAgICAgICksXG4gICAgICAgIHN1bW1hcnk6IHoub2JqZWN0KHtcbiAgICAgICAgICBtYXRjaENvdW50OiB6Lm51bWJlcigpLmRlc2NyaWJlKFwiTnVtYmVyIG9mIG1hdGNoZXMgZm91bmRcIiksXG4gICAgICAgICAgZmlsZUNvdW50OiB6Lm51bWJlcigpLmRlc2NyaWJlKFwiTnVtYmVyIG9mIGZpbGVzIGNvbnRhaW5pbmcgbWF0Y2hlc1wiKSxcbiAgICAgICAgICBzZWFyY2hQYXRoOiB6LnN0cmluZygpLmRlc2NyaWJlKFwiUGF0aCB0aGF0IHdhcyBzZWFyY2hlZFwiKSxcbiAgICAgICAgICBwYXR0ZXJuOiB6LnN0cmluZygpLmRlc2NyaWJlKFwiUGF0dGVybiB0aGF0IHdhcyBzZWFyY2hlZCBmb3JcIiksXG4gICAgICAgIH0pLFxuICAgICAgfSksXG4gICAgICBleGVjdXRlOiBhc3luYyAoe1xuICAgICAgICBwYXR0ZXJuLFxuICAgICAgICBwYXRoLFxuICAgICAgICBmaWxlVHlwZSxcbiAgICAgICAgZ2xvYixcbiAgICAgICAgY2FzZVNlbnNpdGl2ZSxcbiAgICAgICAgY29udGV4dExpbmVzLFxuICAgICAgICBtYXhDb3VudCxcbiAgICAgICAgZmlsZXNXaXRoTWF0Y2hlcyxcbiAgICAgIH0pID0+IHtcbiAgICAgICAgbGV0IHNlYXJjaFBhdGggPSBwYXRoID8/IFwiLlwiO1xuICAgICAgICBpZiAoc2VhcmNoUGF0aC5zdGFydHNXaXRoKFwiL1wiKSkge1xuICAgICAgICAgIHNlYXJjaFBhdGggPSBzZWFyY2hQYXRoLnNsaWNlKDEpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYXJnczogc3RyaW5nW10gPSBbXTtcblxuICAgICAgICBhcmdzLnB1c2goXCItLWxpbmUtbnVtYmVyXCIpO1xuICAgICAgICBhcmdzLnB1c2goXCItLWhlYWRpbmdcIik7XG4gICAgICAgIGFyZ3MucHVzaChcIi0tY29sb3JcIiwgXCJuZXZlclwiKTtcblxuICAgICAgICBpZiAoIWNhc2VTZW5zaXRpdmUpIHtcbiAgICAgICAgICBhcmdzLnB1c2goXCItaVwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmaWxlVHlwZSkge1xuICAgICAgICAgIGFyZ3MucHVzaChcIi0tdHlwZVwiLCBmaWxlVHlwZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZ2xvYikge1xuICAgICAgICAgIGFyZ3MucHVzaChcIi0tZ2xvYlwiLCBnbG9iKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjb250ZXh0TGluZXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGFyZ3MucHVzaChcIi1DXCIsIFN0cmluZyhjb250ZXh0TGluZXMpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChtYXhDb3VudCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgYXJncy5wdXNoKFwiLS1tYXgtY291bnRcIiwgU3RyaW5nKG1heENvdW50KSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZmlsZXNXaXRoTWF0Y2hlcykge1xuICAgICAgICAgIGFyZ3MucHVzaChcIi0tZmlsZXMtd2l0aC1tYXRjaGVzXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgYXJncy5wdXNoKFwiLS1cIiwgcGF0dGVybiwgc2VhcmNoUGF0aCk7XG5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udGV4dC5zYW5kYm94LmV4ZWMoeyBjb21tYW5kOiBcInJnXCIsIGFyZ3MgfSk7XG5cbiAgICAgICAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihcIltHcmVwIFRvb2xdXCIsIHJlc3VsdCk7XG4gICAgICAgICAgdGhyb3cgcmVzdWx0O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgeyBzdGRvdXQsIHN0ZGVyciB9ID0gYXdhaXQgcmVzdWx0LnJlc3VsdDtcblxuICAgICAgICBpZiAoc3RkZXJyICYmICFzdGRlcnIudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyhcIm5vIG1hdGNoZXNcIikpIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKGBbR3JlcCBUb29sXSBXYXJuaW5nOiAke3N0ZGVycn1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRydW5jYXRlIG91dHB1dCB0byBwcmV2ZW50IFwiaW5wdXQgdG9vIGxvbmdcIiBlcnJvcnMgKDUwayBjaGFycyBcdTIyNDggMTIuNWsgdG9rZW5zKVxuICAgICAgICBjb25zdCBNQVhfR1JFUF9PVVRQVVRfQ0hBUlMgPSA1MF8wMDA7XG4gICAgICAgIGxldCBmaW5hbE91dHB1dCA9IHN0ZG91dDtcbiAgICAgICAgbGV0IHdhc1RydW5jYXRlZCA9IGZhbHNlO1xuICAgICAgICBpZiAoZmluYWxPdXRwdXQubGVuZ3RoID4gTUFYX0dSRVBfT1VUUFVUX0NIQVJTKSB7XG4gICAgICAgICAgZmluYWxPdXRwdXQgPVxuICAgICAgICAgICAgZmluYWxPdXRwdXQuc2xpY2UoMCwgTUFYX0dSRVBfT1VUUFVUX0NIQVJTKSArXG4gICAgICAgICAgICBcIlxcblxcbltPdXRwdXQgdHJ1bmNhdGVkIC0gdXNlIG1vcmUgc3BlY2lmaWMgcGF0dGVybiBvciBwYXRoXVwiO1xuICAgICAgICAgIHdhc1RydW5jYXRlZCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBsaW5lcyA9IGZpbmFsT3V0cHV0XG4gICAgICAgICAgLnRyaW0oKVxuICAgICAgICAgIC5zcGxpdChcIlxcblwiKVxuICAgICAgICAgIC5maWx0ZXIoKGwpID0+IGwubGVuZ3RoID4gMCk7XG4gICAgICAgIGNvbnN0IGZpbGVDb3VudCA9IGZpbGVzV2l0aE1hdGNoZXNcbiAgICAgICAgICA/IGxpbmVzLmxlbmd0aFxuICAgICAgICAgIDogbmV3IFNldChcbiAgICAgICAgICAgICAgbGluZXNcbiAgICAgICAgICAgICAgICAuZmlsdGVyKChsKSA9PiAhbC5zdGFydHNXaXRoKFwiIFwiKSAmJiBsLmluY2x1ZGVzKFwiOlwiKSlcbiAgICAgICAgICAgICAgICAubWFwKChsKSA9PiBsLnNwbGl0KFwiOlwiKVswXSlcbiAgICAgICAgICAgICkuc2l6ZTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIG1hdGNoZXM6IGZpbmFsT3V0cHV0IHx8IFwiKG5vIG1hdGNoZXMgZm91bmQpXCIsXG4gICAgICAgICAgc3VtbWFyeToge1xuICAgICAgICAgICAgbWF0Y2hDb3VudDogZmlsZXNXaXRoTWF0Y2hlc1xuICAgICAgICAgICAgICA/IDBcbiAgICAgICAgICAgICAgOiBsaW5lcy5maWx0ZXIoKGwpID0+IGwuaW5jbHVkZXMoXCI6XCIpKS5sZW5ndGgsXG4gICAgICAgICAgICBmaWxlQ291bnQsXG4gICAgICAgICAgICBzZWFyY2hQYXRoLFxuICAgICAgICAgICAgcGF0dGVybixcbiAgICAgICAgICAgIHdhc1RydW5jYXRlZCxcbiAgICAgICAgICB9LFxuICAgICAgICB9O1xuICAgICAgfSxcbiAgICB9KSxcbiAgICBMaXN0OiB0b29sKHtcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICBcIlJlY3Vyc2l2ZWx5IGxpc3QgZGlyZWN0b3J5IGNvbnRlbnRzLiBVc2UgdGhpcyB0byB1bmRlcnN0YW5kIHRoZSBjb2RlYmFzZSBzdHJ1Y3R1cmUsIGZpbmQgZmlsZXMsIG9yIGV4cGxvcmUgZGlyZWN0b3JpZXMuIENvbnRyb2wgZGVwdGggdG8gYmFsYW5jZSBkZXRhaWwgdnMuIG92ZXJ2aWV3LiBEZXB0aCAxIHNob3dzIGltbWVkaWF0ZSBjaGlsZHJlbiwgZGVwdGggMiBpbmNsdWRlcyBzdWJkaXJlY3RvcmllcywgZXRjLlwiLFxuICAgICAgaW5wdXRTY2hlbWE6IHoub2JqZWN0KHtcbiAgICAgICAgcGF0aDogelxuICAgICAgICAgIC5zdHJpbmcoKVxuICAgICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgICAgLmRlc2NyaWJlKFwiUGF0aCB0byBsaXN0IChkZWZhdWx0cyB0byB3b3Jrc3BhY2Ugcm9vdClcIiksXG4gICAgICAgIGRlcHRoOiB6XG4gICAgICAgICAgLm51bWJlcigpXG4gICAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgICBcIk1heGltdW0gZGVwdGggdG8gdHJhdmVyc2UuIENob29zZSBiYXNlZCBvbiBjb250ZXh0OiAxLTIgZm9yIHF1aWNrIG92ZXJ2aWV3LCAzLTQgZm9yIGRldGFpbGVkIGV4cGxvcmF0aW9uLCA1KyBmb3IgY29tcHJlaGVuc2l2ZSBtYXBwaW5nXCJcbiAgICAgICAgICApLFxuICAgICAgICBpbmNsdWRlSGlkZGVuOiB6XG4gICAgICAgICAgLmJvb2xlYW4oKVxuICAgICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgICAgLmRlZmF1bHQoZmFsc2UpXG4gICAgICAgICAgLmRlc2NyaWJlKFxuICAgICAgICAgICAgXCJJbmNsdWRlIGhpZGRlbiBmaWxlcyBhbmQgZGlyZWN0b3JpZXMgKHRob3NlIHN0YXJ0aW5nIHdpdGggJy4nKVwiXG4gICAgICAgICAgKSxcbiAgICAgICAgZmlsZXNPbmx5OiB6XG4gICAgICAgICAgLmJvb2xlYW4oKVxuICAgICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgICAgLmRlZmF1bHQoZmFsc2UpXG4gICAgICAgICAgLmRlc2NyaWJlKFwiT25seSBzaG93IGZpbGVzLCBub3QgZGlyZWN0b3JpZXNcIiksXG4gICAgICAgIHBhdHRlcm46IHpcbiAgICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAgIC5kZXNjcmliZShcIkdsb2IgcGF0dGVybiB0byBmaWx0ZXIgcmVzdWx0cyAoZS5nLiwgJyoudHMnLCAnKnRlc3QqJylcIiksXG4gICAgICB9KSxcbiAgICAgIG91dHB1dFNjaGVtYTogei5vYmplY3Qoe1xuICAgICAgICBsaXN0aW5nOiB6XG4gICAgICAgICAgLnN0cmluZygpXG4gICAgICAgICAgLmRlc2NyaWJlKFxuICAgICAgICAgICAgXCJEaXJlY3RvcnkgdHJlZSBsaXN0aW5nIHNob3dpbmcgcGF0aHMgcmVsYXRpdmUgdG8gc2VhcmNoIHJvb3RcIlxuICAgICAgICAgICksXG4gICAgICAgIHN1bW1hcnk6IHoub2JqZWN0KHtcbiAgICAgICAgICB0b3RhbEl0ZW1zOiB6Lm51bWJlcigpLmRlc2NyaWJlKFwiVG90YWwgbnVtYmVyIG9mIGl0ZW1zIGZvdW5kXCIpLFxuICAgICAgICAgIHRvdGFsRmlsZXM6IHoubnVtYmVyKCkuZGVzY3JpYmUoXCJUb3RhbCBudW1iZXIgb2YgZmlsZXMgZm91bmRcIiksXG4gICAgICAgICAgdG90YWxEaXJzOiB6Lm51bWJlcigpLmRlc2NyaWJlKFwiVG90YWwgbnVtYmVyIG9mIGRpcmVjdG9yaWVzIGZvdW5kXCIpLFxuICAgICAgICAgIHNlYXJjaFBhdGg6IHouc3RyaW5nKCkuZGVzY3JpYmUoXCJQYXRoIHRoYXQgd2FzIGxpc3RlZFwiKSxcbiAgICAgICAgICBkZXB0aDogelxuICAgICAgICAgICAgLm51bWJlcigpXG4gICAgICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAgICAgLmRlc2NyaWJlKFwiTWF4aW11bSBkZXB0aCB1c2VkIChpZiBzcGVjaWZpZWQpXCIpLFxuICAgICAgICB9KSxcbiAgICAgIH0pLFxuICAgICAgZXhlY3V0ZTogYXN5bmMgKHsgcGF0aCwgZGVwdGgsIGluY2x1ZGVIaWRkZW4sIGZpbGVzT25seSwgcGF0dGVybiB9KSA9PiB7XG4gICAgICAgIGNvbnN0IHNlYXJjaFBhdGggPSBwYXRoID8/IFwiLlwiO1xuXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnRleHQuc2FuZGJveC5leGVjKHtcbiAgICAgICAgICBjb21tYW5kOiBcImJhc2hcIixcbiAgICAgICAgICBhcmdzOiBbXG4gICAgICAgICAgICBcIi1jXCIsXG4gICAgICAgICAgICBgXG4gICAgICAgICAgICBzZXQgLWVcbiAgICAgICAgICAgIFNFQVJDSF9QQVRIPVwiJDFcIlxuICAgICAgICAgICAgREVQVEg9XCIkMlwiXG4gICAgICAgICAgICBJTkNMVURFX0hJRERFTj1cIiQzXCJcbiAgICAgICAgICAgIEZJTEVTX09OTFk9XCIkNFwiXG4gICAgICAgICAgICBQQVRURVJOPVwiJDVcIlxuXG4gICAgICAgICAgICAjIEJ1aWxkIGZpbmQgY29tbWFuZCBhcmd1bWVudHNcbiAgICAgICAgICAgIEZJTkRfQVJHUz1cIlwiXG4gICAgICAgICAgICBbIC1uIFwiJERFUFRIXCIgXSAmJiBGSU5EX0FSR1M9XCIkRklORF9BUkdTIC1tYXhkZXB0aCAkREVQVEhcIlxuICAgICAgICAgICAgWyBcIiRJTkNMVURFX0hJRERFTlwiICE9IFwidHJ1ZVwiIF0gJiYgRklORF9BUkdTPVwiJEZJTkRfQVJHUyAhIC1wYXRoICcqLy4qJ1wiXG4gICAgICAgICAgICBbIFwiJEZJTEVTX09OTFlcIiA9IFwidHJ1ZVwiIF0gJiYgRklORF9BUkdTPVwiJEZJTkRfQVJHUyAtdHlwZSBmXCJcbiAgICAgICAgICAgIFsgLW4gXCIkUEFUVEVSTlwiIF0gJiYgRklORF9BUkdTPVwiJEZJTkRfQVJHUyAtbmFtZSAnJFBBVFRFUk4nXCJcblxuICAgICAgICAgICAgIyBHZXQgbGlzdGluZ1xuICAgICAgICAgICAgTElTVElORz0kKGV2YWwgXCJmaW5kICckU0VBUkNIX1BBVEgnICRGSU5EX0FSR1NcIiAyPi9kZXYvbnVsbCB8IHNvcnQpXG5cbiAgICAgICAgICAgICMgR2V0IGNvdW50c1xuICAgICAgICAgICAgQ09VTlRfQVJHUz1cIlwiXG4gICAgICAgICAgICBbIC1uIFwiJERFUFRIXCIgXSAmJiBDT1VOVF9BUkdTPVwiJENPVU5UX0FSR1MgLW1heGRlcHRoICRERVBUSFwiXG4gICAgICAgICAgICBbIFwiJElOQ0xVREVfSElEREVOXCIgIT0gXCJ0cnVlXCIgXSAmJiBDT1VOVF9BUkdTPVwiJENPVU5UX0FSR1MgISAtcGF0aCAnKi8uKidcIlxuXG4gICAgICAgICAgICBGSUxFX0NPVU5UPSQoZXZhbCBcImZpbmQgJyRTRUFSQ0hfUEFUSCcgJENPVU5UX0FSR1MgLXR5cGUgZlwiIDI+L2Rldi9udWxsIHwgd2MgLWwpXG4gICAgICAgICAgICBESVJfQ09VTlQ9JChldmFsIFwiZmluZCAnJFNFQVJDSF9QQVRIJyAkQ09VTlRfQVJHUyAtdHlwZSBkXCIgMj4vZGV2L251bGwgfCB3YyAtbClcblxuICAgICAgICAgICAgIyBPdXRwdXQ6IGNvdW50cyBmaXJzdCwgdGhlbiBsaXN0aW5nXG4gICAgICAgICAgICBlY2hvIFwiJEZJTEVfQ09VTlR8JERJUl9DT1VOVFwiXG4gICAgICAgICAgICBlY2hvIFwifHx8TElTVElOR3x8fFwiXG4gICAgICAgICAgICBlY2hvIFwiJExJU1RJTkdcIiB8IHNlZCBcInN8XiRTRUFSQ0hfUEFUSHwufFwiXG4gICAgICAgICAgYCxcbiAgICAgICAgICAgIFwiLS1cIixcbiAgICAgICAgICAgIHNlYXJjaFBhdGgsXG4gICAgICAgICAgICBkZXB0aD8udG9TdHJpbmcoKSB8fCBcIlwiLFxuICAgICAgICAgICAgaW5jbHVkZUhpZGRlbiA/IFwidHJ1ZVwiIDogXCJmYWxzZVwiLFxuICAgICAgICAgICAgZmlsZXNPbmx5ID8gXCJ0cnVlXCIgOiBcImZhbHNlXCIsXG4gICAgICAgICAgICBwYXR0ZXJuIHx8IFwiXCIsXG4gICAgICAgICAgXSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihcIltMaXN0IFRvb2xdXCIsIHJlc3VsdCk7XG4gICAgICAgICAgdGhyb3cgcmVzdWx0O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgeyBzdGRvdXQsIHN0ZGVyciB9ID0gYXdhaXQgcmVzdWx0LnJlc3VsdDtcblxuICAgICAgICBpZiAoc3RkZXJyKSB7XG4gICAgICAgICAgY29uc29sZS53YXJuKGBbTGlzdCBUb29sXSBzdGRlcnI6ICR7c3RkZXJyfWApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgW2NvdW50c0xpbmUsIC4uLnJlc3RdID0gc3Rkb3V0LnNwbGl0KFwifHx8TElTVElOR3x8fFwiKTtcbiAgICAgICAgY29uc3QgbGlzdGluZyA9IHJlc3Quam9pbihcInx8fExJU1RJTkd8fHxcIikudHJpbSgpO1xuICAgICAgICBjb25zdCBbZmlsZUNvdW50U3RyLCBkaXJDb3VudFN0cl0gPSBjb3VudHNMaW5lLnRyaW0oKS5zcGxpdChcInxcIik7XG5cbiAgICAgICAgY29uc3QgdG90YWxGaWxlcyA9IE51bWJlci5wYXJzZUludChmaWxlQ291bnRTdHIsIDEwKSB8fCAwO1xuICAgICAgICBjb25zdCB0b3RhbERpcnMgPSBOdW1iZXIucGFyc2VJbnQoZGlyQ291bnRTdHIsIDEwKSB8fCAwO1xuICAgICAgICBjb25zdCBsaW5lcyA9IGxpc3Rpbmcuc3BsaXQoXCJcXG5cIikuZmlsdGVyKChsKSA9PiBsLmxlbmd0aCA+IDApO1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgbGlzdGluZyxcbiAgICAgICAgICBzdW1tYXJ5OiB7XG4gICAgICAgICAgICB0b3RhbEl0ZW1zOiBsaW5lcy5sZW5ndGgsXG4gICAgICAgICAgICB0b3RhbEZpbGVzLFxuICAgICAgICAgICAgdG90YWxEaXJzLFxuICAgICAgICAgICAgc2VhcmNoUGF0aCxcbiAgICAgICAgICAgIGRlcHRoLFxuICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICB9LFxuICAgIH0pLFxuICAgIEJhc2g6IHRvb2woe1xuICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgIFwiRXhlY3V0ZXMgYSBiYXNoIGNvbW1hbmQgaW5zaWRlIHRoZSB3b3Jrc3BhY2UuIENXRCBwZXJzaXN0cyBiZXR3ZWVuIGNvbW1hbmRzIHdpdGhpbiBhIHNlc3Npb24uIFVzZSB3YWl0VW50aWw6MCBmb3IgYmFja2dyb3VuZCBwcm9jZXNzZXMgKGRldiBzZXJ2ZXJzKS5cIixcbiAgICAgIGlucHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4gICAgICAgIGNvbW1hbmQ6IHouc3RyaW5nKCkuZGVzY3JpYmUoXCJUaGUgc2hlbGwgY29tbWFuZCB0byBleGVjdXRlXCIpLFxuICAgICAgICB3YWl0VW50aWw6IHpcbiAgICAgICAgICAubnVtYmVyKClcbiAgICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAgIC5kZXNjcmliZShcbiAgICAgICAgICAgIFwiTWF4IG1zIHRvIHdhaXQgZm9yIGNvbXBsZXRpb24gKGRlZmF1bHQ6IDMwMDAwKS4gVXNlIDAgdG8gcnVuIGluIGJhY2tncm91bmQgYW5kIHJldHVybiBpbW1lZGlhdGVseS5cIlxuICAgICAgICAgICksXG4gICAgICB9KSxcbiAgICAgIG91dHB1dFNjaGVtYTogei5vYmplY3Qoe1xuICAgICAgICBwaWQ6IHpcbiAgICAgICAgICAubnVtYmVyKClcbiAgICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgICBcIlN5c3RlbSBQSUQgKDAgZm9yIGZvcmVncm91bmQsID4wIGZvciBiYWNrZ3JvdW5kIC0gdXNlIHRvIGtpbGwpXCJcbiAgICAgICAgICApLFxuICAgICAgICBvdXRwdXQ6IHpcbiAgICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgICAuZGVzY3JpYmUoXCJDb21tYW5kIHN0ZG91dCtzdGRlcnIgY29tYmluZWQgKGVtcHR5IGZvciBiYWNrZ3JvdW5kKVwiKSxcbiAgICAgICAgZXhpdENvZGU6IHoubnVtYmVyKCkuZGVzY3JpYmUoXCJFeGl0IGNvZGUgKC0xIGZvciBiYWNrZ3JvdW5kL3J1bm5pbmcpXCIpLFxuICAgICAgICBzdGF0dXM6IHpcbiAgICAgICAgICAuZW51bShbXCJydW5uaW5nXCIsIFwiY29tcGxldGVkXCIsIFwiZmFpbGVkXCJdKVxuICAgICAgICAgIC5kZXNjcmliZShcIlByb2Nlc3Mgc3RhdHVzXCIpLFxuICAgICAgICBjd2Q6IHouc3RyaW5nKCkuZGVzY3JpYmUoXCJDdXJyZW50IHdvcmtpbmcgZGlyZWN0b3J5IGFmdGVyIGNvbW1hbmRcIiksXG4gICAgICAgIG91dHB1dEZpbGU6IHpcbiAgICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgICAuZGVzY3JpYmUoXCJQYXRoIHRvIG91dHB1dCBsb2cgKGZvciBiYWNrZ3JvdW5kIHByb2Nlc3NlcylcIiksXG4gICAgICB9KSxcbiAgICAgIGV4ZWN1dGU6IGFzeW5jICh7IGNvbW1hbmQsIHdhaXRVbnRpbCB9KSA9PiB7XG4gICAgICAgIGNvbnN0IHsgY3JlYXRlUHJvY2Vzc01hbmFnZXIgfSA9IGF3YWl0IGltcG9ydChcbiAgICAgICAgICBcIi4uL3NhbmRib3gvcHJvY2Vzcy1tYW5hZ2VyXCJcbiAgICAgICAgKTtcblxuICAgICAgICBjb25zdCBwcm9jZXNzTWFuYWdlciA9IGNyZWF0ZVByb2Nlc3NNYW5hZ2VyKHtcbiAgICAgICAgICBzYW5kYm94OiBjb250ZXh0LnNhbmRib3gsXG4gICAgICAgICAgc2Vzc2lvbklkOiBjb250ZXh0LmlucHV0LnNlc3Npb25JZCxcbiAgICAgICAgICBnZW5lcmF0ZUlkOiAoKSA9PiBjcnlwdG8ucmFuZG9tVVVJRCgpLFxuICAgICAgICB9KTtcblxuICAgICAgICBhd2FpdCBwcm9jZXNzTWFuYWdlci5pbml0KCk7XG4gICAgICAgIHJldHVybiBwcm9jZXNzTWFuYWdlci5ydW4oeyBjb21tYW5kLCB3YWl0VW50aWwgfSk7XG4gICAgICB9LFxuICAgIH0pLFxuICAgIEV4ZWN1dGVNQ1BUb29sOiB0b29sKHtcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICBcIkV4ZWN1dGUgYSB0b29sIGZyb20gYW4gTUNQIHNlcnZlci4gVXNlIHRoaXMgdG8gY2FsbCBjdXN0b20gdG9vbHMgcHJvdmlkZWQgYnkgdGhlIGFwcGxpY2F0aW9uLlwiLFxuICAgICAgaW5wdXRTY2hlbWE6IHoub2JqZWN0KHtcbiAgICAgICAgc2VydmVyOiB6LnN0cmluZygpLmRlc2NyaWJlKFwiTUNQIHNlcnZlciBuYW1lXCIpLFxuICAgICAgICB0b29sOiB6LnN0cmluZygpLmRlc2NyaWJlKFwiVG9vbCBuYW1lIHRvIGV4ZWN1dGVcIiksXG4gICAgICAgIGlucHV0OiB6LnVua25vd24oKS5kZXNjcmliZShcIlRvb2wgaW5wdXQgbWF0Y2hpbmcgdGhlIHRvb2wncyBzY2hlbWFcIiksXG4gICAgICB9KSxcbiAgICAgIG91dHB1dFNjaGVtYTogei5vYmplY3Qoe1xuICAgICAgICByZXN1bHQ6IHoudW5rbm93bigpLmRlc2NyaWJlKFwiVG9vbCBleGVjdXRpb24gcmVzdWx0XCIpLFxuICAgICAgICB0cnVuY2F0ZWQ6IHpcbiAgICAgICAgICAuYm9vbGVhbigpXG4gICAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgICAuZGVzY3JpYmUoXCJXaGV0aGVyIHRoZSByZXN1bHQgd2FzIHRydW5jYXRlZCBkdWUgdG8gc2l6ZVwiKSxcbiAgICAgICAgdG90YWxDaGFyczogelxuICAgICAgICAgIC5udW1iZXIoKVxuICAgICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgICAgLmRlc2NyaWJlKFwiVG90YWwgY2hhcmFjdGVycyBpbiBmdWxsIG91dHB1dCAob25seSBpZiB0cnVuY2F0ZWQpXCIpLFxuICAgICAgICByZXR1cm5lZENoYXJzOiB6XG4gICAgICAgICAgLm51bWJlcigpXG4gICAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgICAuZGVzY3JpYmUoXCJDaGFyYWN0ZXJzIHJldHVybmVkIGluIHRoaXMgcmVzcG9uc2UgKG9ubHkgaWYgdHJ1bmNhdGVkKVwiKSxcbiAgICAgICAgZnVsbE91dHB1dFBhdGg6IHpcbiAgICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAgIC5kZXNjcmliZShcIlBhdGggdG8gZnVsbCBvdXRwdXQgZmlsZSBpZiB0cnVuY2F0ZWRcIiksXG4gICAgICB9KSxcbiAgICAgIGV4ZWN1dGU6IGFzeW5jICh7IHNlcnZlciwgdG9vbDogdG9vbE5hbWUsIGlucHV0IH0pID0+IHtcbiAgICAgICAgY29uc3Qgc2VydmVyQ29uZmlnID0gY29udGV4dC5tY3A/LmZpbmQoKHMpID0+IHMubmFtZSA9PT0gc2VydmVyKTtcbiAgICAgICAgaWYgKCFzZXJ2ZXJDb25maWcpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gTUNQIHNlcnZlcjogJHtzZXJ2ZXJ9YCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBwYXJzZWRJbnB1dCA9XG4gICAgICAgICAgdHlwZW9mIGlucHV0ID09PSBcInN0cmluZ1wiID8gSlNPTi5wYXJzZShpbnB1dCkgOiBpbnB1dDtcblxuICAgICAgICBjb25zdCB0aW1lc3RhbXAgPSBEYXRlLm5vdygpO1xuICAgICAgICBjb25zdCBvdXRwdXREaXIgPSBgLmFnZW50L21jcC8ke3NlcnZlcn0vLm91dHB1dHNgO1xuICAgICAgICBjb25zdCBvdXRwdXRGaWxlID0gYCR7b3V0cHV0RGlyfS8ke3RpbWVzdGFtcH0tJHt0b29sTmFtZX0udHh0YDtcblxuICAgICAgICBjb25zdCBbcmVzXSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgICAgICBmZXRjaChzZXJ2ZXJDb25maWcudXJsLCB7XG4gICAgICAgICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgICAgICAgaGVhZGVyczogeyBcIkNvbnRlbnQtVHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb25cIiB9LFxuICAgICAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICBzZXJ2ZXIsXG4gICAgICAgICAgICAgIHRvb2w6IHRvb2xOYW1lLFxuICAgICAgICAgICAgICBpbnB1dDogcGFyc2VkSW5wdXQsXG4gICAgICAgICAgICAgIHNlc3Npb25JZDogY29udGV4dC5pbnB1dC5zZXNzaW9uSWQsXG4gICAgICAgICAgICAgIG1lc3NhZ2VJZDogY29udGV4dC5ldmVudC5hc3Npc3RhbnRNZXNzYWdlSWQsXG4gICAgICAgICAgICAgIGhvb2tUb2tlbjogY29udGV4dC5ldmVudC5ob29rVG9rZW4sXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgICBjb250ZXh0LnNhbmRib3guZXhlYyh7IGNvbW1hbmQ6IFwibWtkaXJcIiwgYXJnczogW1wiLXBcIiwgb3V0cHV0RGlyXSB9KSxcbiAgICAgICAgXSk7XG5cbiAgICAgICAgaWYgKCFyZXMub2spIHtcbiAgICAgICAgICBjb25zdCBlcnJvciA9IGF3YWl0IHJlcy50ZXh0KCk7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBNQ1AgdG9vbCBjYWxsIGZhaWxlZDogJHtlcnJvcn1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGpzb24gPSAoYXdhaXQgcmVzLmpzb24oKSkgYXMge1xuICAgICAgICAgIHJlc3VsdD86IHVua25vd247XG4gICAgICAgICAgZXJyb3I/OiB7IGNvZGU6IHN0cmluZzsgbWVzc2FnZTogc3RyaW5nIH07XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKGpzb24uZXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE1DUCB0b29sIGNhbGwgZmFpbGVkOiAke2pzb24uZXJyb3IubWVzc2FnZX1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChqc29uLnJlc3VsdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTUNQIHRvb2wgY2FsbCBmYWlsZWQ6IE5vIHJlc3VsdCBpbiByZXNwb25zZVwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGpzb24ucmVzdWx0O1xuICAgICAgICBjb25zdCBNQVhfT1VUUFVUX0NIQVJTID0gMjRfMDAwO1xuICAgICAgICBjb25zdCByZXN1bHRTdHIgPSBKU09OLnN0cmluZ2lmeShyZXN1bHQsIG51bGwsIDIpO1xuXG4gICAgICAgIGlmIChyZXN1bHRTdHIubGVuZ3RoIDw9IE1BWF9PVVRQVVRfQ0hBUlMpIHtcbiAgICAgICAgICByZXR1cm4geyByZXN1bHQgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGF3YWl0IGNvbnRleHQuc2FuZGJveC53cml0ZUZpbGVzKHtcbiAgICAgICAgICBmaWxlczogW3sgcGF0aDogYCR7dGltZXN0YW1wfS0ke3Rvb2xOYW1lfS50eHRgLCBjb250ZW50OiByZXN1bHRTdHIgfV0sXG4gICAgICAgICAgZGVzdFBhdGg6IG91dHB1dERpcixcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgdHJ1bmNhdGVkUmVzdWx0ID1cbiAgICAgICAgICByZXN1bHRTdHIuc2xpY2UoMCwgTUFYX09VVFBVVF9DSEFSUykgK1xuICAgICAgICAgIGBcXG5cXG5bT3V0cHV0IHRydW5jYXRlZCBhdCB+NmsgdG9rZW5zLiBGdWxsIG91dHB1dCBzYXZlZCB0bzogJHtvdXRwdXRGaWxlfV1gO1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgcmVzdWx0OiB0cnVuY2F0ZWRSZXN1bHQsXG4gICAgICAgICAgdHJ1bmNhdGVkOiB0cnVlLFxuICAgICAgICAgIHRvdGFsQ2hhcnM6IHJlc3VsdFN0ci5sZW5ndGgsXG4gICAgICAgICAgcmV0dXJuZWRDaGFyczogTUFYX09VVFBVVF9DSEFSUyxcbiAgICAgICAgICBmdWxsT3V0cHV0UGF0aDogb3V0cHV0RmlsZSxcbiAgICAgICAgfTtcbiAgICAgIH0sXG4gICAgfSksXG4gIH0gc2F0aXNmaWVzIFRvb2xTZXQ7XG59XG5cbmV4cG9ydCB0eXBlIEFnZW50VG9vbHMgPSBSZXR1cm5UeXBlPHR5cGVvZiBnZXRUb29scz47XG5leHBvcnQgdHlwZSBBZ2VudFRvb2xOYW1lID0ga2V5b2YgQWdlbnRUb29scztcbiIsICJpbXBvcnQgdHlwZSB7IFVJTWVzc2FnZSB9IGZyb20gXCJhaVwiO1xuaW1wb3J0IHR5cGUgeyBNZXNzYWdlLCBQYXJ0IH0gZnJvbSBcIi4uL3N0b3JhZ2VcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIGFzc2VtYmxlVUlNZXNzYWdlcyhvcHRzOiB7XG4gIG1lc3NhZ2VzOiBNZXNzYWdlW107XG4gIHBhcnRzOiBQYXJ0W107XG59KTogVUlNZXNzYWdlW10ge1xuICBjb25zdCBwYXJ0c0J5TWVzc2FnZSA9IG5ldyBNYXA8c3RyaW5nLCBQYXJ0W10+KCk7XG4gIGZvciAoY29uc3QgcGFydCBvZiBvcHRzLnBhcnRzKSB7XG4gICAgY29uc3QgZXhpc3RpbmcgPSBwYXJ0c0J5TWVzc2FnZS5nZXQocGFydC5tZXNzYWdlSWQpID8/IFtdO1xuICAgIGV4aXN0aW5nLnB1c2gocGFydCk7XG4gICAgcGFydHNCeU1lc3NhZ2Uuc2V0KHBhcnQubWVzc2FnZUlkLCBleGlzdGluZyk7XG4gIH1cblxuICByZXR1cm4gb3B0cy5tZXNzYWdlcy5tYXAoKG0pID0+IHtcbiAgICBjb25zdCBtZXNzYWdlUGFydHMgPSBwYXJ0c0J5TWVzc2FnZS5nZXQobS5pZCkgPz8gW107XG4gICAgbWVzc2FnZVBhcnRzLnNvcnQoKGEsIGIpID0+IGEuaW5kZXggLSBiLmluZGV4KTtcbiAgICByZXR1cm4ge1xuICAgICAgaWQ6IG0uaWQsXG4gICAgICByb2xlOiBtLnJvbGUsXG4gICAgICBwYXJ0czogbWVzc2FnZVBhcnRzLm1hcCgocCkgPT4gcC5wYXJ0KSxcbiAgICB9IHNhdGlzZmllcyBVSU1lc3NhZ2U7XG4gIH0pO1xufVxuIiwgImltcG9ydCB7IHogfSBmcm9tIFwiem9kXCI7XG5cbmV4cG9ydCB0eXBlIE1jcFRvb2xEZWYgPSB7XG4gIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG4gIGlucHV0U2NoZW1hOiB6LlpvZFR5cGU7XG4gIG91dHB1dFNjaGVtYT86IHouWm9kVHlwZTtcbn07XG5cbmV4cG9ydCB0eXBlIE1jcFNlcnZlckRlZjxcbiAgVFRvb2xzIGV4dGVuZHMgUmVjb3JkPHN0cmluZywgTWNwVG9vbERlZj4gPSBSZWNvcmQ8c3RyaW5nLCBNY3BUb29sRGVmPixcbiAgVEhlYWRlcnMgZXh0ZW5kcyB6LlpvZFR5cGUgPSB6LlpvZFR5cGUsXG4+ID0ge1xuICB1cmw6IHN0cmluZztcbiAgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG4gIGhlYWRlcnNTY2hlbWE/OiBUSGVhZGVycztcbiAgdG9vbHM6IFRUb29scztcbn07XG5cbmV4cG9ydCB0eXBlIE1jcENvbmZpZyA9IFJlY29yZDxzdHJpbmcsIE1jcFNlcnZlckRlZj47XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXJpYWxpemVNY3BDb25maWcobWNwOiBNY3BDb25maWcpOiBNY3BTZXJ2ZXJTY2hlbWFbXSB7XG4gIHJldHVybiBPYmplY3QuZW50cmllcyhtY3ApLm1hcCgoW25hbWUsIHNlcnZlcl0pID0+ICh7XG4gICAgbmFtZSxcbiAgICB1cmw6IHNlcnZlci51cmwsXG4gICAgZGVzY3JpcHRpb246IHNlcnZlci5kZXNjcmlwdGlvbixcbiAgICB0b29sczogT2JqZWN0LmVudHJpZXMoc2VydmVyLnRvb2xzKS5tYXAoKFt0b29sTmFtZSwgdG9vbF0pID0+ICh7XG4gICAgICBuYW1lOiB0b29sTmFtZSxcbiAgICAgIGRlc2NyaXB0aW9uOiB0b29sLmRlc2NyaXB0aW9uLFxuICAgICAgaW5wdXRTY2hlbWE6IHoudG9KU09OU2NoZW1hKHRvb2wuaW5wdXRTY2hlbWEpLFxuICAgICAgb3V0cHV0U2NoZW1hOiB0b29sLm91dHB1dFNjaGVtYVxuICAgICAgICA/IHoudG9KU09OU2NoZW1hKHRvb2wub3V0cHV0U2NoZW1hKVxuICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICB9KSksXG4gIH0pKTtcbn1cblxuZXhwb3J0IHR5cGUgTWNwVG9vbFNjaGVtYSA9IHtcbiAgbmFtZTogc3RyaW5nO1xuICBkZXNjcmlwdGlvbjogc3RyaW5nO1xuICBpbnB1dFNjaGVtYTogdW5rbm93bjtcbiAgb3V0cHV0U2NoZW1hPzogdW5rbm93bjtcbn07XG5cbmV4cG9ydCB0eXBlIE1jcFNlcnZlclNjaGVtYSA9IHtcbiAgbmFtZTogc3RyaW5nO1xuICB1cmw6IHN0cmluZztcbiAgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG4gIHRvb2xzOiBNY3BUb29sU2NoZW1hW107XG59O1xuXG50eXBlIEV4dHJhY3RIZWFkZXJzPFQ+ID1cbiAgVCBleHRlbmRzIE1jcFNlcnZlckRlZjxpbmZlciBfVFRvb2xzLCBpbmZlciBUSGVhZGVycz5cbiAgICA/IFRIZWFkZXJzIGV4dGVuZHMgei5ab2RUeXBlXG4gICAgICA/IHouaW5mZXI8VEhlYWRlcnM+XG4gICAgICA6IFJlY29yZDxzdHJpbmcsIHN0cmluZz5cbiAgICA6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG5cbnR5cGUgSGFzUmVxdWlyZWRIZWFkZXJzPFQgZXh0ZW5kcyBNY3BTZXJ2ZXJEZWY+ID0gVCBleHRlbmRzIHtcbiAgaGVhZGVyc1NjaGVtYTogei5ab2RUeXBlO1xufVxuICA/IHRydWVcbiAgOiBmYWxzZTtcblxudHlwZSBTZXJ2ZXJTZW5kT3B0aW9uczxUIGV4dGVuZHMgTWNwU2VydmVyRGVmPiA9XG4gIEhhc1JlcXVpcmVkSGVhZGVyczxUPiBleHRlbmRzIHRydWVcbiAgICA/XG4gICAgICAgIHwgeyBoZWFkZXJzOiBFeHRyYWN0SGVhZGVyczxUPjsgZGlzYWJsZWQ/OiBmYWxzZSB9XG4gICAgICAgIHwgeyBkaXNhYmxlZDogdHJ1ZTsgaGVhZGVycz86IEV4dHJhY3RIZWFkZXJzPFQ+IH1cbiAgICA6IHsgaGVhZGVycz86IEV4dHJhY3RIZWFkZXJzPFQ+OyBkaXNhYmxlZD86IGJvb2xlYW4gfTtcblxuZXhwb3J0IHR5cGUgTWNwU2VuZE9wdGlvbnM8VE1jcCBleHRlbmRzIE1jcENvbmZpZz4gPSB7XG4gIFtLIGluIGtleW9mIFRNY3BdPzogU2VydmVyU2VuZE9wdGlvbnM8VE1jcFtLXT47XG59O1xuXG5leHBvcnQgdHlwZSBNY3BUb29sQ2FsbFJlcXVlc3QgPSB7XG4gIHNlcnZlcjogc3RyaW5nO1xuICB0b29sOiBzdHJpbmc7XG4gIGlucHV0OiB1bmtub3duO1xuICBtZXNzYWdlSWQ6IHN0cmluZztcbiAgbWNwVG9rZW46IHN0cmluZztcbn07XG5cbmV4cG9ydCB0eXBlIE1jcFRvb2xDYWxsU3VjY2Vzc1Jlc3BvbnNlPFQgPSB1bmtub3duPiA9IHtcbiAgcmVzdWx0OiBUO1xufTtcblxuZXhwb3J0IHR5cGUgTWNwVG9vbENhbGxFcnJvclJlc3BvbnNlID0ge1xuICBlcnJvcjogeyBjb2RlOiBzdHJpbmc7IG1lc3NhZ2U6IHN0cmluZyB9O1xufTtcblxuZXhwb3J0IHR5cGUgTWNwVG9vbENhbGxSZXNwb25zZTxUID0gdW5rbm93bj4gPVxuICB8IE1jcFRvb2xDYWxsU3VjY2Vzc1Jlc3BvbnNlPFQ+XG4gIHwgTWNwVG9vbENhbGxFcnJvclJlc3BvbnNlO1xuXG50eXBlIEV4dHJhY3RJbnB1dDxUIGV4dGVuZHMgTWNwVG9vbERlZj4gPSBUIGV4dGVuZHMgeyBpbnB1dFNjaGVtYTogaW5mZXIgUyB9XG4gID8gUyBleHRlbmRzIHouWm9kVHlwZVxuICAgID8gei5pbmZlcjxTPlxuICAgIDogdW5rbm93blxuICA6IHVua25vd247XG5cbnR5cGUgSGFuZGxlckZvclRvb2w8XG4gIFRTZXJ2ZXIgZXh0ZW5kcyBNY3BTZXJ2ZXJEZWYsXG4gIFRUb29sIGV4dGVuZHMgTWNwVG9vbERlZixcbj4gPSAob3B0czoge1xuICBpbnB1dDogRXh0cmFjdElucHV0PFRUb29sPjtcbiAgaGVhZGVyczogRXh0cmFjdEhlYWRlcnM8VFNlcnZlcj47XG59KSA9PiBQcm9taXNlPHVua25vd24+O1xuXG50eXBlIEJ1aWxkSGFuZGxlcnM8VE1jcCBleHRlbmRzIE1jcENvbmZpZz4gPSB7XG4gIFtLIGluIGtleW9mIFRNY3AgJiBzdHJpbmddOiB7XG4gICAgW1QgaW4ga2V5b2YgVE1jcFtLXVtcInRvb2xzXCJdICYgc3RyaW5nXToge1xuICAgICAga2V5OiBgJHtLfS8ke1R9YDtcbiAgICAgIGhhbmRsZXI6IEhhbmRsZXJGb3JUb29sPFRNY3BbS10sIFRNY3BbS11bXCJ0b29sc1wiXVtUXT47XG4gICAgfTtcbiAgfVtrZXlvZiBUTWNwW0tdW1widG9vbHNcIl0gJiBzdHJpbmddO1xufVtrZXlvZiBUTWNwICYgc3RyaW5nXTtcblxudHlwZSBVbmlvblRvSW50ZXJzZWN0aW9uPFU+ID0gKFxuICBVIGV4dGVuZHMgdW5rbm93blxuICAgID8gKGs6IFUpID0+IHZvaWRcbiAgICA6IG5ldmVyXG4pIGV4dGVuZHMgKGs6IGluZmVyIEkpID0+IHZvaWRcbiAgPyBJXG4gIDogbmV2ZXI7XG5cbnR5cGUgSGFuZGxlcnNGcm9tVW5pb248VT4gPSBVbmlvblRvSW50ZXJzZWN0aW9uPFxuICBVIGV4dGVuZHMgeyBrZXk6IGluZmVyIEs7IGhhbmRsZXI6IGluZmVyIEggfVxuICAgID8gSyBleHRlbmRzIHN0cmluZ1xuICAgICAgPyB7IFtQIGluIEtdOiBIIH1cbiAgICAgIDogbmV2ZXJcbiAgICA6IG5ldmVyXG4+O1xuXG5leHBvcnQgdHlwZSBNY3BUb29sQ2FsbEhhbmRsZXJzPFRNY3AgZXh0ZW5kcyBNY3BDb25maWc+ID0gSGFuZGxlcnNGcm9tVW5pb248XG4gIEJ1aWxkSGFuZGxlcnM8VE1jcD5cbj47XG5cbmV4cG9ydCBmdW5jdGlvbiBtY3A8XG4gIFRIZWFkZXJzIGV4dGVuZHMgei5ab2RUeXBlLFxuICBUVG9vbHMgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCBNY3BUb29sRGVmPixcbj4ob3B0czoge1xuICB1cmw6IHN0cmluZztcbiAgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG4gIGhlYWRlcnNTY2hlbWE/OiBUSGVhZGVycztcbiAgdG9vbHM6IFRUb29scztcbn0pOiBNY3BTZXJ2ZXJEZWY8VFRvb2xzLCBUSGVhZGVycz4ge1xuICByZXR1cm4gb3B0cztcbn1cbiIsICJpbXBvcnQgdHlwZSB7IFVJTWVzc2FnZSB9IGZyb20gXCJhaVwiO1xuaW1wb3J0IHR5cGUgeyBBZ2VudE9wdGlvbnMsIFNlbmRJbnB1dCB9IGZyb20gXCIuLi9jbGllbnRcIjtcbmltcG9ydCB0eXBlIHsgTWVzc2FnZSwgUGFydCB9IGZyb20gXCIuLi9zdG9yYWdlXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiB0b01lc3NhZ2VBbmRQYXJ0cyh7XG4gIHNlc3Npb25JZCxcbiAgaWQsXG4gIGlucHV0LFxuICBnZW5lcmF0ZUlkLFxuICBkZWZhdWx0Um9sZSxcbn06IHtcbiAgc2Vzc2lvbklkOiBzdHJpbmc7XG4gIGlkPzogc3RyaW5nO1xuICBpbnB1dDogU2VuZElucHV0O1xuICBnZW5lcmF0ZUlkOiBOb25OdWxsYWJsZTxBZ2VudE9wdGlvbnNbXCJnZW5lcmF0ZUlkXCJdPjtcbiAgZGVmYXVsdFJvbGU6IFVJTWVzc2FnZVtcInJvbGVcIl07XG59KTogeyBtZXNzYWdlOiBNZXNzYWdlOyBwYXJ0czogUGFydFtdIH0ge1xuICBjb25zdCBtZXNzYWdlSWQgPSBpZCA/PyBnZW5lcmF0ZUlkKFwibWVzc2FnZVwiKTtcbiAgaWYgKHR5cGVvZiBpbnB1dCA9PT0gXCJzdHJpbmdcIikge1xuICAgIHJldHVybiB7XG4gICAgICBtZXNzYWdlOiB7XG4gICAgICAgIGlkOiBtZXNzYWdlSWQsXG4gICAgICAgIHNlc3Npb25JZCxcbiAgICAgICAgcm9sZTogZGVmYXVsdFJvbGUsXG4gICAgICAgIGNyZWF0ZWRBdDogRGF0ZS5ub3coKSxcbiAgICAgICAgY29tcGxldGVkQXQ6IERhdGUubm93KCksXG4gICAgICAgIG1jcENvbnRleHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgcGFydHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIHNlc3Npb25JZCxcbiAgICAgICAgICBtZXNzYWdlSWQsXG4gICAgICAgICAgaWQ6IGdlbmVyYXRlSWQoXCJwYXJ0XCIpLFxuICAgICAgICAgIGluZGV4OiAwLFxuICAgICAgICAgIHBhcnQ6IHsgdHlwZTogXCJ0ZXh0XCIsIHRleHQ6IGlucHV0IH0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH07XG4gIH1cbiAgcmV0dXJuIHtcbiAgICBtZXNzYWdlOiB7XG4gICAgICBzZXNzaW9uSWQsXG4gICAgICBpZDogbWVzc2FnZUlkLFxuICAgICAgY3JlYXRlZEF0OiBEYXRlLm5vdygpLFxuICAgICAgY29tcGxldGVkQXQ6IERhdGUubm93KCksXG4gICAgICBtY3BDb250ZXh0OiBudWxsLFxuICAgICAgcm9sZTogaW5wdXQucm9sZSA/PyBkZWZhdWx0Um9sZSxcbiAgICB9LFxuICAgIHBhcnRzOiBpbnB1dC5wYXJ0cy5tYXAoKHBhcnQsIGluZGV4KSA9PiAoe1xuICAgICAgc2Vzc2lvbklkLFxuICAgICAgbWVzc2FnZUlkLFxuICAgICAgaWQ6IGdlbmVyYXRlSWQoXCJwYXJ0XCIpLFxuICAgICAgaW5kZXgsXG4gICAgICBwYXJ0LFxuICAgIH0pKSxcbiAgfTtcbn1cbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsSUFFTSxvQkFNQSxZQTJGTztBQW5HYjtBQUFBO0FBQUE7QUFFQSxJQUFNLHFCQUFxQjtBQU0zQixJQUFNLGFBQWE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FB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LENBQUMsU0FBUztBQUNaLGVBQU87QUFBQSxVQUNMLE9BQU87QUFBQSxZQUNMLE1BQU07QUFBQSxZQUNOLFNBQVMsa0JBQWtCLFVBQVU7QUFBQSxVQUN2QztBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBRUEsWUFBTSxVQUFVLE1BQU0sUUFBUSxRQUFRLElBQUksU0FBUztBQUNuRCxVQUFJLG1CQUFtQixPQUFPO0FBQzVCLGVBQU87QUFBQSxVQUNMLE9BQU8sRUFBRSxNQUFNLHFCQUFxQixTQUFTLG9CQUFvQjtBQUFBLFFBQ25FO0FBQUEsTUFDRjtBQUVBLFVBQUksQ0FBQyxRQUFRLGFBQWEsUUFBUSxjQUFjLFdBQVc7QUFDekQsZUFBTztBQUFBLFVBQ0wsT0FBTyxFQUFFLE1BQU0saUJBQWlCLFNBQVMscUJBQXFCO0FBQUEsUUFDaEU7QUFBQSxNQUNGO0FBRUEsWUFBTSxVQUFVLE1BQU0sUUFBUSxRQUFRLElBQUksU0FBUztBQUNuRCxVQUFJLG1CQUFtQixPQUFPO0FBQzVCLGVBQU87QUFBQSxVQUNMLE9BQU8sRUFBRSxNQUFNLHFCQUFxQixTQUFTLG9CQUFvQjtBQUFBLFFBQ25FO0FBQUEsTUFDRjtBQUVBLFlBQU0sYUFBYSxRQUFRO0FBQzNCLFlBQU0sZ0JBQWdCLGFBQWEsTUFBaUM7QUFDcEUsWUFBTSxVQUFXLGVBQWUsV0FBVyxDQUFDO0FBRTVDLFVBQUk7QUFDRixjQUFNLFNBQVMsTUFBTSxRQUFRLEVBQUUsT0FBTyxTQUFTLEtBQUssQ0FBQztBQUNyRCxlQUFPLEVBQUUsT0FBTztBQUFBLE1BQ2xCLFNBQVMsR0FBRztBQUNWLGVBQU87QUFBQSxVQUNMLE9BQU87QUFBQSxZQUNMLE1BQU07QUFBQSxZQUNOLFNBQVMsYUFBYSxRQUFRLEVBQUUsVUFBVSxPQUFPLENBQUM7QUFBQSxVQUNwRDtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBQUEsSUFDRjtBQUFBLEVBQ0Y7QUFDRjs7O0FENWJBO0FBVUE7IiwKICAibmFtZXMiOiBbIm9wdHMiLCAic3RhcnRMb2NhbFN0b3JhZ2UiLCAiZ2V0VmVyY2VsU3RvcmFnZUNvbmZpZyIsICJpbXBvcnRfem9kIiwgImV4aXRDb2RlIiwgInN0ZGVyciIsICJlcnJvcmUiLCAiaW5pdF9sb2NhbCIsICJlcnJvcmUiLCAiaW5pdF92ZXJjZWwiLCAic2FuZGJveCIsICJWZXJjZWxTYW5kYm94U0RLIiwgImdldFNhbmRib3giLCAiaW5pdF9jbGllbnQiLCAiaW5pdF9sb2NhbCIsICJpbml0X3ZlcmNlbCIsICJpbml0X2NsaWVudCIsICJlcnJvcmUiLCAiaW1wb3J0X3VsaWQiLCAiaW1wb3J0X3dvcmtmbG93IiwgImltcG9ydF9haSIsICJpbXBvcnRfdWxpZCIsICJwYXRoIiwgImNyZWF0ZVByb2Nlc3NNYW5hZ2VyIiwgIm1jcCIsICJnZXRTdG9yYWdlIiwgImdldFNhbmRib3giLCAicmVzdWx0IiwgImltcG9ydF96b2QiLCAibWNwIiwgInRvb2wiLCAiZXF1YWwiLCAic2Vzc2lvbiIsICJ0b29sIl0KfQo=
|