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
|
@@ -0,0 +1,2659 @@
|
|
|
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, all) => {
|
|
12
|
+
for (var name in all)
|
|
13
|
+
__defProp(target, name, { get: all[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/agent-workflow.ts
|
|
1788
|
+
var agent_workflow_exports = {};
|
|
1789
|
+
__export(agent_workflow_exports, {
|
|
1790
|
+
agentMessageHook: () => agentMessageHook,
|
|
1791
|
+
agentWorkflow: () => agentWorkflow
|
|
1792
|
+
});
|
|
1793
|
+
module.exports = __toCommonJS(agent_workflow_exports);
|
|
1794
|
+
var import_workflow2 = require("workflow");
|
|
1795
|
+
|
|
1796
|
+
// src/agent-workflow-steps.ts
|
|
1797
|
+
var import_ai2 = require("ai");
|
|
1798
|
+
var import_ulid2 = require("ulid");
|
|
1799
|
+
var import_workflow = require("workflow");
|
|
1800
|
+
|
|
1801
|
+
// src/skills/parser.ts
|
|
1802
|
+
function parseSkillFrontmatter(content) {
|
|
1803
|
+
const trimmed = content.trim();
|
|
1804
|
+
if (!trimmed.startsWith("---")) {
|
|
1805
|
+
return null;
|
|
1806
|
+
}
|
|
1807
|
+
const endMarkerIndex = trimmed.indexOf("---", 3);
|
|
1808
|
+
if (endMarkerIndex === -1) {
|
|
1809
|
+
return null;
|
|
1810
|
+
}
|
|
1811
|
+
const frontmatterBlock = trimmed.slice(3, endMarkerIndex).trim();
|
|
1812
|
+
const parsed = parseSimpleYaml(frontmatterBlock);
|
|
1813
|
+
if (!(parsed.name && parsed.description)) {
|
|
1814
|
+
return null;
|
|
1815
|
+
}
|
|
1816
|
+
return {
|
|
1817
|
+
name: String(parsed.name),
|
|
1818
|
+
description: String(parsed.description)
|
|
1819
|
+
};
|
|
1820
|
+
}
|
|
1821
|
+
function parseSimpleYaml(yaml) {
|
|
1822
|
+
const result = {};
|
|
1823
|
+
for (const line of yaml.split("\n")) {
|
|
1824
|
+
const trimmedLine = line.trim();
|
|
1825
|
+
if (!trimmedLine || trimmedLine.startsWith("#")) {
|
|
1826
|
+
continue;
|
|
1827
|
+
}
|
|
1828
|
+
const colonIndex = trimmedLine.indexOf(":");
|
|
1829
|
+
if (colonIndex === -1) {
|
|
1830
|
+
continue;
|
|
1831
|
+
}
|
|
1832
|
+
const key = trimmedLine.slice(0, colonIndex).trim();
|
|
1833
|
+
let value = trimmedLine.slice(colonIndex + 1).trim();
|
|
1834
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
1835
|
+
value = value.slice(1, -1);
|
|
1836
|
+
}
|
|
1837
|
+
if (key) {
|
|
1838
|
+
result[key] = value;
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
return result;
|
|
1842
|
+
}
|
|
1843
|
+
|
|
1844
|
+
// src/skills/discover.ts
|
|
1845
|
+
async function discoverSkillsInSandbox(opts) {
|
|
1846
|
+
const { sandbox, skillsDirs, debug } = opts;
|
|
1847
|
+
const summaries = [];
|
|
1848
|
+
const seenNames = /* @__PURE__ */ new Set();
|
|
1849
|
+
for (const skillsDir of skillsDirs) {
|
|
1850
|
+
const dirSummaries = await discoverSkillsInDirectory({
|
|
1851
|
+
sandbox,
|
|
1852
|
+
skillsDir,
|
|
1853
|
+
debug
|
|
1854
|
+
});
|
|
1855
|
+
for (const summary of dirSummaries) {
|
|
1856
|
+
if (!seenNames.has(summary.name)) {
|
|
1857
|
+
seenNames.add(summary.name);
|
|
1858
|
+
summaries.push(summary);
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
return summaries;
|
|
1863
|
+
}
|
|
1864
|
+
async function discoverSkillsInDirectory(opts) {
|
|
1865
|
+
const { sandbox, skillsDir, debug } = opts;
|
|
1866
|
+
const skillPaths = await findSkillFiles({ sandbox, skillsDir, debug });
|
|
1867
|
+
if (skillPaths.length === 0) {
|
|
1868
|
+
return [];
|
|
1869
|
+
}
|
|
1870
|
+
const summaries = [];
|
|
1871
|
+
for (const skillMdPath of skillPaths) {
|
|
1872
|
+
const summary = await parseSkillFile({ sandbox, skillMdPath, debug });
|
|
1873
|
+
if (summary) {
|
|
1874
|
+
summaries.push(summary);
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
return summaries;
|
|
1878
|
+
}
|
|
1879
|
+
async function findSkillFiles(opts) {
|
|
1880
|
+
const { sandbox, skillsDir, debug } = opts;
|
|
1881
|
+
if (debug) {
|
|
1882
|
+
console.log(`[discover] Finding skills in: ${skillsDir}`);
|
|
1883
|
+
}
|
|
1884
|
+
const execResult = await sandbox.exec({
|
|
1885
|
+
command: "find",
|
|
1886
|
+
args: [skillsDir, "-name", "SKILL.md", "-type", "f"]
|
|
1887
|
+
});
|
|
1888
|
+
if (execResult instanceof Error) {
|
|
1889
|
+
if (debug) {
|
|
1890
|
+
console.warn(
|
|
1891
|
+
`[discover] Failed to scan skills directory "${skillsDir}": ${execResult.message}`
|
|
1892
|
+
);
|
|
1893
|
+
}
|
|
1894
|
+
return [];
|
|
1895
|
+
}
|
|
1896
|
+
const { stdout, stderr, exitCode } = await execResult.result;
|
|
1897
|
+
if (debug) {
|
|
1898
|
+
console.log(
|
|
1899
|
+
`[discover] find result: exitCode=${exitCode}, stdout="${stdout.trim()}", stderr="${stderr.trim()}"`
|
|
1900
|
+
);
|
|
1901
|
+
}
|
|
1902
|
+
if (exitCode !== 0) {
|
|
1903
|
+
if (debug) {
|
|
1904
|
+
console.warn(
|
|
1905
|
+
`[discover] Skills directory not found or inaccessible: ${skillsDir}`
|
|
1906
|
+
);
|
|
1907
|
+
}
|
|
1908
|
+
return [];
|
|
1909
|
+
}
|
|
1910
|
+
const paths = stdout.trim().split("\n").filter((p) => p.length > 0);
|
|
1911
|
+
if (debug) {
|
|
1912
|
+
console.log("[discover] Found skill paths:", paths);
|
|
1913
|
+
}
|
|
1914
|
+
return paths;
|
|
1915
|
+
}
|
|
1916
|
+
async function parseSkillFile(opts) {
|
|
1917
|
+
const { sandbox, skillMdPath, debug } = opts;
|
|
1918
|
+
const execResult = await sandbox.exec({
|
|
1919
|
+
command: "cat",
|
|
1920
|
+
args: [skillMdPath]
|
|
1921
|
+
});
|
|
1922
|
+
if (execResult instanceof Error) {
|
|
1923
|
+
if (debug) {
|
|
1924
|
+
console.warn(
|
|
1925
|
+
`[discover] Failed to read skill file "${skillMdPath}": ${execResult.message}`
|
|
1926
|
+
);
|
|
1927
|
+
}
|
|
1928
|
+
return null;
|
|
1929
|
+
}
|
|
1930
|
+
const { stdout, exitCode } = await execResult.result;
|
|
1931
|
+
if (exitCode !== 0) {
|
|
1932
|
+
if (debug) {
|
|
1933
|
+
console.warn(`[discover] Could not read skill file: ${skillMdPath}`);
|
|
1934
|
+
}
|
|
1935
|
+
return null;
|
|
1936
|
+
}
|
|
1937
|
+
const parsed = parseSkillFrontmatter(stdout);
|
|
1938
|
+
if (!parsed) {
|
|
1939
|
+
if (debug) {
|
|
1940
|
+
console.warn(
|
|
1941
|
+
`[discover] Invalid or missing frontmatter in: ${skillMdPath}`
|
|
1942
|
+
);
|
|
1943
|
+
}
|
|
1944
|
+
return null;
|
|
1945
|
+
}
|
|
1946
|
+
return {
|
|
1947
|
+
name: parsed.name,
|
|
1948
|
+
description: parsed.description,
|
|
1949
|
+
skillMdPath
|
|
1950
|
+
};
|
|
1951
|
+
}
|
|
1952
|
+
|
|
1953
|
+
// src/tools/index.ts
|
|
1954
|
+
var import_ai = require("ai");
|
|
1955
|
+
var import_zod = require("zod");
|
|
1956
|
+
function getTools(context) {
|
|
1957
|
+
return {
|
|
1958
|
+
Read: (0, import_ai.tool)({
|
|
1959
|
+
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.",
|
|
1960
|
+
inputSchema: import_zod.z.object({
|
|
1961
|
+
path: import_zod.z.string().describe("Path to the file relative to workspace root"),
|
|
1962
|
+
startLine: import_zod.z.number().optional().describe(
|
|
1963
|
+
"Starting line number (1-indexed). If provided with endLine, reads exact range regardless of file size."
|
|
1964
|
+
),
|
|
1965
|
+
endLine: import_zod.z.number().optional().describe(
|
|
1966
|
+
"Ending line number (1-indexed, inclusive). If provided with startLine, reads exact range regardless of file size."
|
|
1967
|
+
)
|
|
1968
|
+
}),
|
|
1969
|
+
outputSchema: import_zod.z.object({
|
|
1970
|
+
content: import_zod.z.string().describe("File content"),
|
|
1971
|
+
metadata: import_zod.z.object({
|
|
1972
|
+
totalLines: import_zod.z.number().describe("Total number of lines in the file"),
|
|
1973
|
+
linesShown: import_zod.z.number().describe("Number of lines included in this response"),
|
|
1974
|
+
startLine: import_zod.z.number().describe("First line number shown (1-indexed)"),
|
|
1975
|
+
endLine: import_zod.z.number().describe("Last line number shown (1-indexed)"),
|
|
1976
|
+
isPaginated: import_zod.z.boolean().describe("Whether this is a partial view of the file"),
|
|
1977
|
+
fileSize: import_zod.z.string().describe("Human-readable file size (e.g., '2.5K', '1.2M')"),
|
|
1978
|
+
path: import_zod.z.string().describe("Path to the file relative to workspace root")
|
|
1979
|
+
})
|
|
1980
|
+
}),
|
|
1981
|
+
execute: async ({ path: path2, startLine, endLine }) => {
|
|
1982
|
+
const filePath = path2.startsWith("/") ? path2.slice(1) : path2;
|
|
1983
|
+
const result = await context.sandbox.exec({
|
|
1984
|
+
command: "bash",
|
|
1985
|
+
args: [
|
|
1986
|
+
"-c",
|
|
1987
|
+
`
|
|
1988
|
+
set -e
|
|
1989
|
+
FILE="$1"
|
|
1990
|
+
START_LINE="$2"
|
|
1991
|
+
END_LINE="$3"
|
|
1992
|
+
|
|
1993
|
+
# Resolve symlinks and check file exists
|
|
1994
|
+
if [ -L "$FILE" ]; then
|
|
1995
|
+
RESOLVED=$(readlink -f "$FILE" 2>/dev/null || echo "")
|
|
1996
|
+
if [ -z "$RESOLVED" ] || [ ! -e "$RESOLVED" ]; then
|
|
1997
|
+
echo "Error: Broken symlink - $FILE points to non-existent target" >&2
|
|
1998
|
+
exit 1
|
|
1999
|
+
fi
|
|
2000
|
+
FILE="$RESOLVED"
|
|
2001
|
+
elif [ ! -e "$FILE" ]; then
|
|
2002
|
+
echo "Error: File not found - $FILE" >&2
|
|
2003
|
+
exit 1
|
|
2004
|
+
fi
|
|
2005
|
+
|
|
2006
|
+
# Get metadata (count actual lines, not just newlines)
|
|
2007
|
+
TOTAL_LINES=$(awk 'END{print NR}' "$FILE")
|
|
2008
|
+
FILE_SIZE=$(ls -lh "$FILE" | awk '{print $5}')
|
|
2009
|
+
|
|
2010
|
+
# Determine range
|
|
2011
|
+
PAGE_SIZE=100
|
|
2012
|
+
if [ -n "$START_LINE" ] && [ -n "$END_LINE" ]; then
|
|
2013
|
+
# Both provided - use exact range
|
|
2014
|
+
ACTUAL_START=$START_LINE
|
|
2015
|
+
ACTUAL_END=$END_LINE
|
|
2016
|
+
elif [ -n "$START_LINE" ]; then
|
|
2017
|
+
# Only startLine - read PAGE_SIZE lines from there
|
|
2018
|
+
ACTUAL_START=$START_LINE
|
|
2019
|
+
ACTUAL_END=$((START_LINE + PAGE_SIZE - 1))
|
|
2020
|
+
[ "$ACTUAL_END" -gt "$TOTAL_LINES" ] && ACTUAL_END=$TOTAL_LINES
|
|
2021
|
+
elif [ -n "$END_LINE" ]; then
|
|
2022
|
+
# Only endLine - read from beginning to endLine
|
|
2023
|
+
ACTUAL_START=1
|
|
2024
|
+
ACTUAL_END=$END_LINE
|
|
2025
|
+
elif [ "$TOTAL_LINES" -gt 200 ]; then
|
|
2026
|
+
# No range, large file - paginate
|
|
2027
|
+
ACTUAL_START=1
|
|
2028
|
+
ACTUAL_END=$PAGE_SIZE
|
|
2029
|
+
else
|
|
2030
|
+
# No range, small file - show all
|
|
2031
|
+
ACTUAL_START=1
|
|
2032
|
+
ACTUAL_END=$TOTAL_LINES
|
|
2033
|
+
fi
|
|
2034
|
+
|
|
2035
|
+
# Output metadata first (separated by ||| for parsing)
|
|
2036
|
+
echo "$TOTAL_LINES|$FILE_SIZE|$ACTUAL_START|$ACTUAL_END"
|
|
2037
|
+
echo "|||CONTENT|||"
|
|
2038
|
+
|
|
2039
|
+
# Read content
|
|
2040
|
+
if [ "$ACTUAL_START" -eq 1 ] && [ "$ACTUAL_END" -eq "$TOTAL_LINES" ]; then
|
|
2041
|
+
cat "$FILE"
|
|
2042
|
+
else
|
|
2043
|
+
sed -n "\${ACTUAL_START},\${ACTUAL_END}p" "$FILE"
|
|
2044
|
+
fi
|
|
2045
|
+
`,
|
|
2046
|
+
"--",
|
|
2047
|
+
filePath,
|
|
2048
|
+
startLine?.toString() || "",
|
|
2049
|
+
endLine?.toString() || ""
|
|
2050
|
+
]
|
|
2051
|
+
});
|
|
2052
|
+
if (result instanceof Error) {
|
|
2053
|
+
console.error("[Read Tool]", result);
|
|
2054
|
+
throw result;
|
|
2055
|
+
}
|
|
2056
|
+
const { stdout, stderr } = await result.result;
|
|
2057
|
+
if (stderr) {
|
|
2058
|
+
console.error(`[Read Tool] Error: ${stderr}`);
|
|
2059
|
+
return {
|
|
2060
|
+
content: `Error: ${stderr}`,
|
|
2061
|
+
metadata: {
|
|
2062
|
+
totalLines: 0,
|
|
2063
|
+
linesShown: 0,
|
|
2064
|
+
startLine: 0,
|
|
2065
|
+
endLine: 0,
|
|
2066
|
+
isPaginated: false,
|
|
2067
|
+
fileSize: "0",
|
|
2068
|
+
path: filePath
|
|
2069
|
+
}
|
|
2070
|
+
};
|
|
2071
|
+
}
|
|
2072
|
+
const [metadataLine, ...rest] = stdout.split("|||CONTENT|||");
|
|
2073
|
+
const content = rest.join("|||CONTENT|||").trimStart();
|
|
2074
|
+
const [totalLinesStr, fileSize, actualStartStr, actualEndStr] = metadataLine.trim().split("|");
|
|
2075
|
+
const totalLines = Number.parseInt(totalLinesStr, 10);
|
|
2076
|
+
const actualStart = Number.parseInt(actualStartStr, 10);
|
|
2077
|
+
const actualEnd = Number.parseInt(actualEndStr, 10);
|
|
2078
|
+
if (Number.isNaN(totalLines) || Number.isNaN(actualStart) || Number.isNaN(actualEnd)) {
|
|
2079
|
+
console.error(
|
|
2080
|
+
`[Read Tool] Failed to parse metadata: ${metadataLine}`
|
|
2081
|
+
);
|
|
2082
|
+
return {
|
|
2083
|
+
content: `Error: Failed to parse file metadata. Raw output: ${stdout.slice(
|
|
2084
|
+
0,
|
|
2085
|
+
500
|
|
2086
|
+
)}`,
|
|
2087
|
+
metadata: {
|
|
2088
|
+
totalLines: 0,
|
|
2089
|
+
linesShown: 0,
|
|
2090
|
+
startLine: 0,
|
|
2091
|
+
endLine: 0,
|
|
2092
|
+
isPaginated: false,
|
|
2093
|
+
fileSize: "unknown",
|
|
2094
|
+
path: filePath
|
|
2095
|
+
}
|
|
2096
|
+
};
|
|
2097
|
+
}
|
|
2098
|
+
return {
|
|
2099
|
+
content,
|
|
2100
|
+
metadata: {
|
|
2101
|
+
totalLines,
|
|
2102
|
+
linesShown: Math.max(0, actualEnd - actualStart + 1),
|
|
2103
|
+
startLine: actualStart,
|
|
2104
|
+
endLine: actualEnd,
|
|
2105
|
+
isPaginated: actualEnd < totalLines,
|
|
2106
|
+
fileSize: fileSize || "unknown",
|
|
2107
|
+
path: filePath
|
|
2108
|
+
}
|
|
2109
|
+
};
|
|
2110
|
+
}
|
|
2111
|
+
}),
|
|
2112
|
+
Grep: (0, import_ai.tool)({
|
|
2113
|
+
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.",
|
|
2114
|
+
inputSchema: import_zod.z.object({
|
|
2115
|
+
pattern: import_zod.z.string().describe("Regex pattern to search for (ripgrep syntax)"),
|
|
2116
|
+
path: import_zod.z.string().optional().describe(
|
|
2117
|
+
"Path to search in (defaults to workspace root). Can be a file or directory."
|
|
2118
|
+
),
|
|
2119
|
+
fileType: import_zod.z.string().optional().describe(
|
|
2120
|
+
"File type to filter by (e.g., 'ts', 'js', 'py', 'md'). Uses ripgrep's built-in type filters."
|
|
2121
|
+
),
|
|
2122
|
+
glob: import_zod.z.string().optional().describe(
|
|
2123
|
+
"Glob pattern to filter files (e.g., '*.tsx', 'src/**/*.ts')"
|
|
2124
|
+
),
|
|
2125
|
+
caseSensitive: import_zod.z.boolean().optional().default(true).describe("Whether search is case-sensitive (default: true)"),
|
|
2126
|
+
contextLines: import_zod.z.number().optional().describe(
|
|
2127
|
+
"Number of context lines to show before and after each match"
|
|
2128
|
+
),
|
|
2129
|
+
maxCount: import_zod.z.number().optional().describe(
|
|
2130
|
+
"Maximum number of matches per file (useful for limiting output)"
|
|
2131
|
+
),
|
|
2132
|
+
filesWithMatches: import_zod.z.boolean().optional().default(false).describe(
|
|
2133
|
+
"Only show file paths that contain matches, not the matching lines themselves"
|
|
2134
|
+
)
|
|
2135
|
+
}),
|
|
2136
|
+
outputSchema: import_zod.z.object({
|
|
2137
|
+
matches: import_zod.z.string().describe(
|
|
2138
|
+
"Search results with file paths, line numbers, and matching content"
|
|
2139
|
+
),
|
|
2140
|
+
summary: import_zod.z.object({
|
|
2141
|
+
matchCount: import_zod.z.number().describe("Number of matches found"),
|
|
2142
|
+
fileCount: import_zod.z.number().describe("Number of files containing matches"),
|
|
2143
|
+
searchPath: import_zod.z.string().describe("Path that was searched"),
|
|
2144
|
+
pattern: import_zod.z.string().describe("Pattern that was searched for")
|
|
2145
|
+
})
|
|
2146
|
+
}),
|
|
2147
|
+
execute: async ({
|
|
2148
|
+
pattern,
|
|
2149
|
+
path: path2,
|
|
2150
|
+
fileType,
|
|
2151
|
+
glob,
|
|
2152
|
+
caseSensitive,
|
|
2153
|
+
contextLines,
|
|
2154
|
+
maxCount,
|
|
2155
|
+
filesWithMatches
|
|
2156
|
+
}) => {
|
|
2157
|
+
let searchPath = path2 ?? ".";
|
|
2158
|
+
if (searchPath.startsWith("/")) {
|
|
2159
|
+
searchPath = searchPath.slice(1);
|
|
2160
|
+
}
|
|
2161
|
+
const args = [];
|
|
2162
|
+
args.push("--line-number");
|
|
2163
|
+
args.push("--heading");
|
|
2164
|
+
args.push("--color", "never");
|
|
2165
|
+
if (!caseSensitive) {
|
|
2166
|
+
args.push("-i");
|
|
2167
|
+
}
|
|
2168
|
+
if (fileType) {
|
|
2169
|
+
args.push("--type", fileType);
|
|
2170
|
+
}
|
|
2171
|
+
if (glob) {
|
|
2172
|
+
args.push("--glob", glob);
|
|
2173
|
+
}
|
|
2174
|
+
if (contextLines !== void 0) {
|
|
2175
|
+
args.push("-C", String(contextLines));
|
|
2176
|
+
}
|
|
2177
|
+
if (maxCount !== void 0) {
|
|
2178
|
+
args.push("--max-count", String(maxCount));
|
|
2179
|
+
}
|
|
2180
|
+
if (filesWithMatches) {
|
|
2181
|
+
args.push("--files-with-matches");
|
|
2182
|
+
}
|
|
2183
|
+
args.push("--", pattern, searchPath);
|
|
2184
|
+
const result = await context.sandbox.exec({ command: "rg", args });
|
|
2185
|
+
if (result instanceof Error) {
|
|
2186
|
+
console.error("[Grep Tool]", result);
|
|
2187
|
+
throw result;
|
|
2188
|
+
}
|
|
2189
|
+
const { stdout, stderr } = await result.result;
|
|
2190
|
+
if (stderr && !stderr.toLowerCase().includes("no matches")) {
|
|
2191
|
+
console.error(`[Grep Tool] Warning: ${stderr}`);
|
|
2192
|
+
}
|
|
2193
|
+
const MAX_GREP_OUTPUT_CHARS = 5e4;
|
|
2194
|
+
let finalOutput = stdout;
|
|
2195
|
+
let wasTruncated = false;
|
|
2196
|
+
if (finalOutput.length > MAX_GREP_OUTPUT_CHARS) {
|
|
2197
|
+
finalOutput = finalOutput.slice(0, MAX_GREP_OUTPUT_CHARS) + "\n\n[Output truncated - use more specific pattern or path]";
|
|
2198
|
+
wasTruncated = true;
|
|
2199
|
+
}
|
|
2200
|
+
const lines = finalOutput.trim().split("\n").filter((l) => l.length > 0);
|
|
2201
|
+
const fileCount = filesWithMatches ? lines.length : new Set(
|
|
2202
|
+
lines.filter((l) => !l.startsWith(" ") && l.includes(":")).map((l) => l.split(":")[0])
|
|
2203
|
+
).size;
|
|
2204
|
+
return {
|
|
2205
|
+
matches: finalOutput || "(no matches found)",
|
|
2206
|
+
summary: {
|
|
2207
|
+
matchCount: filesWithMatches ? 0 : lines.filter((l) => l.includes(":")).length,
|
|
2208
|
+
fileCount,
|
|
2209
|
+
searchPath,
|
|
2210
|
+
pattern,
|
|
2211
|
+
wasTruncated
|
|
2212
|
+
}
|
|
2213
|
+
};
|
|
2214
|
+
}
|
|
2215
|
+
}),
|
|
2216
|
+
List: (0, import_ai.tool)({
|
|
2217
|
+
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.",
|
|
2218
|
+
inputSchema: import_zod.z.object({
|
|
2219
|
+
path: import_zod.z.string().optional().describe("Path to list (defaults to workspace root)"),
|
|
2220
|
+
depth: import_zod.z.number().optional().describe(
|
|
2221
|
+
"Maximum depth to traverse. Choose based on context: 1-2 for quick overview, 3-4 for detailed exploration, 5+ for comprehensive mapping"
|
|
2222
|
+
),
|
|
2223
|
+
includeHidden: import_zod.z.boolean().optional().default(false).describe(
|
|
2224
|
+
"Include hidden files and directories (those starting with '.')"
|
|
2225
|
+
),
|
|
2226
|
+
filesOnly: import_zod.z.boolean().optional().default(false).describe("Only show files, not directories"),
|
|
2227
|
+
pattern: import_zod.z.string().optional().describe("Glob pattern to filter results (e.g., '*.ts', '*test*')")
|
|
2228
|
+
}),
|
|
2229
|
+
outputSchema: import_zod.z.object({
|
|
2230
|
+
listing: import_zod.z.string().describe(
|
|
2231
|
+
"Directory tree listing showing paths relative to search root"
|
|
2232
|
+
),
|
|
2233
|
+
summary: import_zod.z.object({
|
|
2234
|
+
totalItems: import_zod.z.number().describe("Total number of items found"),
|
|
2235
|
+
totalFiles: import_zod.z.number().describe("Total number of files found"),
|
|
2236
|
+
totalDirs: import_zod.z.number().describe("Total number of directories found"),
|
|
2237
|
+
searchPath: import_zod.z.string().describe("Path that was listed"),
|
|
2238
|
+
depth: import_zod.z.number().optional().describe("Maximum depth used (if specified)")
|
|
2239
|
+
})
|
|
2240
|
+
}),
|
|
2241
|
+
execute: async ({ path: path2, depth, includeHidden, filesOnly, pattern }) => {
|
|
2242
|
+
const searchPath = path2 ?? ".";
|
|
2243
|
+
const result = await context.sandbox.exec({
|
|
2244
|
+
command: "bash",
|
|
2245
|
+
args: [
|
|
2246
|
+
"-c",
|
|
2247
|
+
`
|
|
2248
|
+
set -e
|
|
2249
|
+
SEARCH_PATH="$1"
|
|
2250
|
+
DEPTH="$2"
|
|
2251
|
+
INCLUDE_HIDDEN="$3"
|
|
2252
|
+
FILES_ONLY="$4"
|
|
2253
|
+
PATTERN="$5"
|
|
2254
|
+
|
|
2255
|
+
# Build find command arguments
|
|
2256
|
+
FIND_ARGS=""
|
|
2257
|
+
[ -n "$DEPTH" ] && FIND_ARGS="$FIND_ARGS -maxdepth $DEPTH"
|
|
2258
|
+
[ "$INCLUDE_HIDDEN" != "true" ] && FIND_ARGS="$FIND_ARGS ! -path '*/.*'"
|
|
2259
|
+
[ "$FILES_ONLY" = "true" ] && FIND_ARGS="$FIND_ARGS -type f"
|
|
2260
|
+
[ -n "$PATTERN" ] && FIND_ARGS="$FIND_ARGS -name '$PATTERN'"
|
|
2261
|
+
|
|
2262
|
+
# Get listing
|
|
2263
|
+
LISTING=$(eval "find '$SEARCH_PATH' $FIND_ARGS" 2>/dev/null | sort)
|
|
2264
|
+
|
|
2265
|
+
# Get counts
|
|
2266
|
+
COUNT_ARGS=""
|
|
2267
|
+
[ -n "$DEPTH" ] && COUNT_ARGS="$COUNT_ARGS -maxdepth $DEPTH"
|
|
2268
|
+
[ "$INCLUDE_HIDDEN" != "true" ] && COUNT_ARGS="$COUNT_ARGS ! -path '*/.*'"
|
|
2269
|
+
|
|
2270
|
+
FILE_COUNT=$(eval "find '$SEARCH_PATH' $COUNT_ARGS -type f" 2>/dev/null | wc -l)
|
|
2271
|
+
DIR_COUNT=$(eval "find '$SEARCH_PATH' $COUNT_ARGS -type d" 2>/dev/null | wc -l)
|
|
2272
|
+
|
|
2273
|
+
# Output: counts first, then listing
|
|
2274
|
+
echo "$FILE_COUNT|$DIR_COUNT"
|
|
2275
|
+
echo "|||LISTING|||"
|
|
2276
|
+
echo "$LISTING" | sed "s|^$SEARCH_PATH|.|"
|
|
2277
|
+
`,
|
|
2278
|
+
"--",
|
|
2279
|
+
searchPath,
|
|
2280
|
+
depth?.toString() || "",
|
|
2281
|
+
includeHidden ? "true" : "false",
|
|
2282
|
+
filesOnly ? "true" : "false",
|
|
2283
|
+
pattern || ""
|
|
2284
|
+
]
|
|
2285
|
+
});
|
|
2286
|
+
if (result instanceof Error) {
|
|
2287
|
+
console.error("[List Tool]", result);
|
|
2288
|
+
throw result;
|
|
2289
|
+
}
|
|
2290
|
+
const { stdout, stderr } = await result.result;
|
|
2291
|
+
if (stderr) {
|
|
2292
|
+
console.warn(`[List Tool] stderr: ${stderr}`);
|
|
2293
|
+
}
|
|
2294
|
+
const [countsLine, ...rest] = stdout.split("|||LISTING|||");
|
|
2295
|
+
const listing = rest.join("|||LISTING|||").trim();
|
|
2296
|
+
const [fileCountStr, dirCountStr] = countsLine.trim().split("|");
|
|
2297
|
+
const totalFiles = Number.parseInt(fileCountStr, 10) || 0;
|
|
2298
|
+
const totalDirs = Number.parseInt(dirCountStr, 10) || 0;
|
|
2299
|
+
const lines = listing.split("\n").filter((l) => l.length > 0);
|
|
2300
|
+
return {
|
|
2301
|
+
listing,
|
|
2302
|
+
summary: {
|
|
2303
|
+
totalItems: lines.length,
|
|
2304
|
+
totalFiles,
|
|
2305
|
+
totalDirs,
|
|
2306
|
+
searchPath,
|
|
2307
|
+
depth
|
|
2308
|
+
}
|
|
2309
|
+
};
|
|
2310
|
+
}
|
|
2311
|
+
}),
|
|
2312
|
+
Bash: (0, import_ai.tool)({
|
|
2313
|
+
description: "Executes a bash command inside the workspace. CWD persists between commands within a session. Use waitUntil:0 for background processes (dev servers).",
|
|
2314
|
+
inputSchema: import_zod.z.object({
|
|
2315
|
+
command: import_zod.z.string().describe("The shell command to execute"),
|
|
2316
|
+
waitUntil: import_zod.z.number().optional().describe(
|
|
2317
|
+
"Max ms to wait for completion (default: 30000). Use 0 to run in background and return immediately."
|
|
2318
|
+
)
|
|
2319
|
+
}),
|
|
2320
|
+
outputSchema: import_zod.z.object({
|
|
2321
|
+
pid: import_zod.z.number().describe(
|
|
2322
|
+
"System PID (0 for foreground, >0 for background - use to kill)"
|
|
2323
|
+
),
|
|
2324
|
+
output: import_zod.z.string().describe("Command stdout+stderr combined (empty for background)"),
|
|
2325
|
+
exitCode: import_zod.z.number().describe("Exit code (-1 for background/running)"),
|
|
2326
|
+
status: import_zod.z.enum(["running", "completed", "failed"]).describe("Process status"),
|
|
2327
|
+
cwd: import_zod.z.string().describe("Current working directory after command"),
|
|
2328
|
+
outputFile: import_zod.z.string().describe("Path to output log (for background processes)")
|
|
2329
|
+
}),
|
|
2330
|
+
execute: async ({ command, waitUntil }) => {
|
|
2331
|
+
const { createProcessManager: createProcessManager2 } = await Promise.resolve().then(() => (init_process_manager(), process_manager_exports));
|
|
2332
|
+
const processManager = createProcessManager2({
|
|
2333
|
+
sandbox: context.sandbox,
|
|
2334
|
+
sessionId: context.input.sessionId,
|
|
2335
|
+
generateId: () => crypto.randomUUID()
|
|
2336
|
+
});
|
|
2337
|
+
await processManager.init();
|
|
2338
|
+
return processManager.run({ command, waitUntil });
|
|
2339
|
+
}
|
|
2340
|
+
}),
|
|
2341
|
+
ExecuteMCPTool: (0, import_ai.tool)({
|
|
2342
|
+
description: "Execute a tool from an MCP server. Use this to call custom tools provided by the application.",
|
|
2343
|
+
inputSchema: import_zod.z.object({
|
|
2344
|
+
server: import_zod.z.string().describe("MCP server name"),
|
|
2345
|
+
tool: import_zod.z.string().describe("Tool name to execute"),
|
|
2346
|
+
input: import_zod.z.unknown().describe("Tool input matching the tool's schema")
|
|
2347
|
+
}),
|
|
2348
|
+
outputSchema: import_zod.z.object({
|
|
2349
|
+
result: import_zod.z.unknown().describe("Tool execution result"),
|
|
2350
|
+
truncated: import_zod.z.boolean().optional().describe("Whether the result was truncated due to size"),
|
|
2351
|
+
totalChars: import_zod.z.number().optional().describe("Total characters in full output (only if truncated)"),
|
|
2352
|
+
returnedChars: import_zod.z.number().optional().describe("Characters returned in this response (only if truncated)"),
|
|
2353
|
+
fullOutputPath: import_zod.z.string().optional().describe("Path to full output file if truncated")
|
|
2354
|
+
}),
|
|
2355
|
+
execute: async ({ server, tool: toolName, input }) => {
|
|
2356
|
+
const serverConfig = context.mcp?.find((s) => s.name === server);
|
|
2357
|
+
if (!serverConfig) {
|
|
2358
|
+
throw new Error(`Unknown MCP server: ${server}`);
|
|
2359
|
+
}
|
|
2360
|
+
const parsedInput = typeof input === "string" ? JSON.parse(input) : input;
|
|
2361
|
+
const timestamp = Date.now();
|
|
2362
|
+
const outputDir = `.agent/mcp/${server}/.outputs`;
|
|
2363
|
+
const outputFile = `${outputDir}/${timestamp}-${toolName}.txt`;
|
|
2364
|
+
const [res] = await Promise.all([
|
|
2365
|
+
fetch(serverConfig.url, {
|
|
2366
|
+
method: "POST",
|
|
2367
|
+
headers: { "Content-Type": "application/json" },
|
|
2368
|
+
body: JSON.stringify({
|
|
2369
|
+
server,
|
|
2370
|
+
tool: toolName,
|
|
2371
|
+
input: parsedInput,
|
|
2372
|
+
sessionId: context.input.sessionId,
|
|
2373
|
+
messageId: context.event.assistantMessageId,
|
|
2374
|
+
hookToken: context.event.hookToken
|
|
2375
|
+
})
|
|
2376
|
+
}),
|
|
2377
|
+
context.sandbox.exec({ command: "mkdir", args: ["-p", outputDir] })
|
|
2378
|
+
]);
|
|
2379
|
+
if (!res.ok) {
|
|
2380
|
+
const error = await res.text();
|
|
2381
|
+
throw new Error(`MCP tool call failed: ${error}`);
|
|
2382
|
+
}
|
|
2383
|
+
const json = await res.json();
|
|
2384
|
+
if (json.error) {
|
|
2385
|
+
throw new Error(`MCP tool call failed: ${json.error.message}`);
|
|
2386
|
+
}
|
|
2387
|
+
if (json.result === void 0) {
|
|
2388
|
+
throw new Error("MCP tool call failed: No result in response");
|
|
2389
|
+
}
|
|
2390
|
+
const result = json.result;
|
|
2391
|
+
const MAX_OUTPUT_CHARS = 24e3;
|
|
2392
|
+
const resultStr = JSON.stringify(result, null, 2);
|
|
2393
|
+
if (resultStr.length <= MAX_OUTPUT_CHARS) {
|
|
2394
|
+
return { result };
|
|
2395
|
+
}
|
|
2396
|
+
await context.sandbox.writeFiles({
|
|
2397
|
+
files: [{ path: `${timestamp}-${toolName}.txt`, content: resultStr }],
|
|
2398
|
+
destPath: outputDir
|
|
2399
|
+
});
|
|
2400
|
+
const truncatedResult = resultStr.slice(0, MAX_OUTPUT_CHARS) + `
|
|
2401
|
+
|
|
2402
|
+
[Output truncated at ~6k tokens. Full output saved to: ${outputFile}]`;
|
|
2403
|
+
return {
|
|
2404
|
+
result: truncatedResult,
|
|
2405
|
+
truncated: true,
|
|
2406
|
+
totalChars: resultStr.length,
|
|
2407
|
+
returnedChars: MAX_OUTPUT_CHARS,
|
|
2408
|
+
fullOutputPath: outputFile
|
|
2409
|
+
};
|
|
2410
|
+
}
|
|
2411
|
+
})
|
|
2412
|
+
};
|
|
2413
|
+
}
|
|
2414
|
+
|
|
2415
|
+
// src/utils/ui.ts
|
|
2416
|
+
function assembleUIMessages(opts) {
|
|
2417
|
+
const partsByMessage = /* @__PURE__ */ new Map();
|
|
2418
|
+
for (const part of opts.parts) {
|
|
2419
|
+
const existing = partsByMessage.get(part.messageId) ?? [];
|
|
2420
|
+
existing.push(part);
|
|
2421
|
+
partsByMessage.set(part.messageId, existing);
|
|
2422
|
+
}
|
|
2423
|
+
return opts.messages.map((m) => {
|
|
2424
|
+
const messageParts = partsByMessage.get(m.id) ?? [];
|
|
2425
|
+
messageParts.sort((a, b) => a.index - b.index);
|
|
2426
|
+
return {
|
|
2427
|
+
id: m.id,
|
|
2428
|
+
role: m.role,
|
|
2429
|
+
parts: messageParts.map((p) => p.part)
|
|
2430
|
+
};
|
|
2431
|
+
});
|
|
2432
|
+
}
|
|
2433
|
+
|
|
2434
|
+
// src/agent-workflow-steps.ts
|
|
2435
|
+
var BASE_SYSTEM_PROMPT = "You are an AI assistant with basic tools to interact with your environment. Explore and work freely.";
|
|
2436
|
+
function joinPromptSections(...sections) {
|
|
2437
|
+
return sections.filter((s) => s?.trim()).join("\n\n");
|
|
2438
|
+
}
|
|
2439
|
+
function buildSkillsContext(skills) {
|
|
2440
|
+
if (skills.length === 0) {
|
|
2441
|
+
return "";
|
|
2442
|
+
}
|
|
2443
|
+
const skillLines = skills.map((s) => `- ${s.name}: ${s.description}
|
|
2444
|
+
Path: ${s.skillMdPath}`).join("\n");
|
|
2445
|
+
return `## Available Skills
|
|
2446
|
+
${skillLines}
|
|
2447
|
+
|
|
2448
|
+
You can use the Read tool to read any skill's SKILL.md file to learn more about it.`;
|
|
2449
|
+
}
|
|
2450
|
+
function buildMcpToolsContext(mcp) {
|
|
2451
|
+
if (!mcp || mcp.length === 0) {
|
|
2452
|
+
return "";
|
|
2453
|
+
}
|
|
2454
|
+
const serverDocs = mcp.filter(
|
|
2455
|
+
(s) => Array.isArray(s.tools) && s.tools.length > 0
|
|
2456
|
+
).map((server) => {
|
|
2457
|
+
const toolDocs = server.tools.map((t) => {
|
|
2458
|
+
let doc = ` - ${t.name}: ${t.description}
|
|
2459
|
+
Input: ${JSON.stringify(t.inputSchema)}`;
|
|
2460
|
+
if (t.outputSchema) {
|
|
2461
|
+
doc += `
|
|
2462
|
+
Output: ${JSON.stringify(t.outputSchema)}`;
|
|
2463
|
+
}
|
|
2464
|
+
return doc;
|
|
2465
|
+
}).join("\n");
|
|
2466
|
+
return `### ${server.name}
|
|
2467
|
+
${server.description ?? ""}
|
|
2468
|
+
${toolDocs}`;
|
|
2469
|
+
}).join("\n\n");
|
|
2470
|
+
if (!serverDocs) {
|
|
2471
|
+
return "";
|
|
2472
|
+
}
|
|
2473
|
+
return `## MCP Tools
|
|
2474
|
+
Use the ExecuteMCPTool to call these custom tools:
|
|
2475
|
+
|
|
2476
|
+
${serverDocs}`;
|
|
2477
|
+
}
|
|
2478
|
+
async function completeMessageStep({
|
|
2479
|
+
assistantMessageId,
|
|
2480
|
+
input,
|
|
2481
|
+
writable
|
|
2482
|
+
}) {
|
|
2483
|
+
"use step";
|
|
2484
|
+
const { getStorage: getStorage2 } = await Promise.resolve().then(() => (init_storage(), storage_exports));
|
|
2485
|
+
const storage = getStorage2(input.storageConfig);
|
|
2486
|
+
const message = await storage.message.get(assistantMessageId);
|
|
2487
|
+
if (message instanceof Error) {
|
|
2488
|
+
throw message;
|
|
2489
|
+
}
|
|
2490
|
+
if (!message) {
|
|
2491
|
+
throw new Error(`Message ${assistantMessageId} not found`);
|
|
2492
|
+
}
|
|
2493
|
+
const result = await storage.message.set({
|
|
2494
|
+
...message,
|
|
2495
|
+
completedAt: Date.now()
|
|
2496
|
+
});
|
|
2497
|
+
if (result instanceof Error) {
|
|
2498
|
+
throw result;
|
|
2499
|
+
}
|
|
2500
|
+
await writable.close();
|
|
2501
|
+
}
|
|
2502
|
+
async function streamTextStep({
|
|
2503
|
+
assistantMessageId,
|
|
2504
|
+
input,
|
|
2505
|
+
event,
|
|
2506
|
+
writable,
|
|
2507
|
+
lastPartIndex
|
|
2508
|
+
}) {
|
|
2509
|
+
"use step";
|
|
2510
|
+
const { getStorage: getStorage2 } = await Promise.resolve().then(() => (init_client(), client_exports));
|
|
2511
|
+
const { getSandbox: getSandbox2 } = await Promise.resolve().then(() => (init_sandbox(), sandbox_exports));
|
|
2512
|
+
const storage = getStorage2(input.storageConfig);
|
|
2513
|
+
const session = await storage.session.get(input.sessionId);
|
|
2514
|
+
if (session instanceof Error) {
|
|
2515
|
+
throw session;
|
|
2516
|
+
}
|
|
2517
|
+
session;
|
|
2518
|
+
const sandboxRecord = session.sandboxId ? await storage.sandbox.get(session.sandboxId) : null;
|
|
2519
|
+
if (sandboxRecord instanceof Error) {
|
|
2520
|
+
throw sandboxRecord;
|
|
2521
|
+
}
|
|
2522
|
+
if (!sandboxRecord) {
|
|
2523
|
+
throw new import_workflow.FatalError(`Sandbox not found for session ${input.sessionId}`);
|
|
2524
|
+
}
|
|
2525
|
+
const sandbox = getSandbox2({
|
|
2526
|
+
sandboxRecord,
|
|
2527
|
+
storageConfig: input.storageConfig
|
|
2528
|
+
});
|
|
2529
|
+
const [messagesResult, partsResult, skills] = await Promise.all([
|
|
2530
|
+
storage.message.list(input.sessionId),
|
|
2531
|
+
storage.part.listBySession(input.sessionId),
|
|
2532
|
+
session.skillsDir && session.skillsDir.length > 0 ? discoverSkillsInSandbox({ sandbox, skillsDirs: session.skillsDir }) : Promise.resolve([])
|
|
2533
|
+
]);
|
|
2534
|
+
if (messagesResult instanceof Error) {
|
|
2535
|
+
throw messagesResult;
|
|
2536
|
+
}
|
|
2537
|
+
if (partsResult instanceof Error) {
|
|
2538
|
+
throw partsResult;
|
|
2539
|
+
}
|
|
2540
|
+
const uiMessages = assembleUIMessages({
|
|
2541
|
+
messages: messagesResult.items,
|
|
2542
|
+
parts: partsResult.items
|
|
2543
|
+
});
|
|
2544
|
+
const mcp = session.mcp;
|
|
2545
|
+
const systemPrompt = joinPromptSections(
|
|
2546
|
+
BASE_SYSTEM_PROMPT,
|
|
2547
|
+
session.instructions,
|
|
2548
|
+
buildSkillsContext(skills),
|
|
2549
|
+
buildMcpToolsContext(mcp)
|
|
2550
|
+
);
|
|
2551
|
+
if (!session.model) {
|
|
2552
|
+
throw new import_workflow.FatalError("Session model is not set");
|
|
2553
|
+
}
|
|
2554
|
+
const result = (0, import_ai2.streamText)({
|
|
2555
|
+
messages: await (0, import_ai2.convertToModelMessages)(uiMessages),
|
|
2556
|
+
tools: getTools({ input, event, mcp, sandbox }),
|
|
2557
|
+
system: systemPrompt,
|
|
2558
|
+
model: session.model
|
|
2559
|
+
});
|
|
2560
|
+
const stepParts = [];
|
|
2561
|
+
await result.toUIMessageStream({
|
|
2562
|
+
generateMessageId: () => assistantMessageId,
|
|
2563
|
+
onFinish: ({ messages }) => {
|
|
2564
|
+
for (const m of messages) {
|
|
2565
|
+
if (m.role === "assistant") {
|
|
2566
|
+
stepParts.push(...m.parts);
|
|
2567
|
+
}
|
|
2568
|
+
}
|
|
2569
|
+
}
|
|
2570
|
+
}).pipeTo(writable, { preventClose: true });
|
|
2571
|
+
await Promise.all(
|
|
2572
|
+
stepParts.map(async (uiPart, index) => {
|
|
2573
|
+
const result2 = await storage.part.set({
|
|
2574
|
+
id: `part_${(0, import_ulid2.ulid)()}`,
|
|
2575
|
+
index: lastPartIndex + index,
|
|
2576
|
+
messageId: assistantMessageId,
|
|
2577
|
+
sessionId: input.sessionId,
|
|
2578
|
+
part: uiPart
|
|
2579
|
+
});
|
|
2580
|
+
if (result2 instanceof Error) {
|
|
2581
|
+
throw result2;
|
|
2582
|
+
}
|
|
2583
|
+
return result2;
|
|
2584
|
+
})
|
|
2585
|
+
);
|
|
2586
|
+
return {
|
|
2587
|
+
finishReason: await result.finishReason,
|
|
2588
|
+
lastPartIndex: lastPartIndex + stepParts.length
|
|
2589
|
+
};
|
|
2590
|
+
}
|
|
2591
|
+
|
|
2592
|
+
// src/agent-workflow.ts
|
|
2593
|
+
var agentMessageHook = (0, import_workflow2.defineHook)();
|
|
2594
|
+
async function agentWorkflow({
|
|
2595
|
+
input,
|
|
2596
|
+
event
|
|
2597
|
+
}) {
|
|
2598
|
+
"use workflow";
|
|
2599
|
+
const messageHook = agentMessageHook.create({ token: input.sessionId });
|
|
2600
|
+
const iterator = messageHook[Symbol.asyncIterator]();
|
|
2601
|
+
let pendingNext = iterator.next();
|
|
2602
|
+
await onMessage({ event, input }).catch((e) => {
|
|
2603
|
+
if (import_workflow2.FatalError.is(e)) {
|
|
2604
|
+
console.error("Message processing failed permanently:", e.message);
|
|
2605
|
+
return;
|
|
2606
|
+
}
|
|
2607
|
+
throw e;
|
|
2608
|
+
});
|
|
2609
|
+
while (true) {
|
|
2610
|
+
const result = await pendingNext;
|
|
2611
|
+
if (result.done) {
|
|
2612
|
+
console.error("Unexpected: message hook iterator done");
|
|
2613
|
+
break;
|
|
2614
|
+
}
|
|
2615
|
+
await onMessage({ event: result.value, input }).catch((e) => {
|
|
2616
|
+
if (import_workflow2.FatalError.is(e)) {
|
|
2617
|
+
console.error("Message processing failed permanently:", e.message);
|
|
2618
|
+
return;
|
|
2619
|
+
}
|
|
2620
|
+
throw e;
|
|
2621
|
+
});
|
|
2622
|
+
pendingNext = iterator.next();
|
|
2623
|
+
}
|
|
2624
|
+
}
|
|
2625
|
+
async function onMessage({
|
|
2626
|
+
event,
|
|
2627
|
+
input
|
|
2628
|
+
}) {
|
|
2629
|
+
const writable = (0, import_workflow2.getWritable)({ namespace: event.assistantMessageId });
|
|
2630
|
+
let finishReason;
|
|
2631
|
+
let lastPartIndex = 0;
|
|
2632
|
+
while (finishReason !== "stop") {
|
|
2633
|
+
try {
|
|
2634
|
+
const result = await streamTextStep({
|
|
2635
|
+
assistantMessageId: event.assistantMessageId,
|
|
2636
|
+
writable,
|
|
2637
|
+
input,
|
|
2638
|
+
event,
|
|
2639
|
+
lastPartIndex
|
|
2640
|
+
});
|
|
2641
|
+
finishReason = result.finishReason;
|
|
2642
|
+
lastPartIndex = result.lastPartIndex;
|
|
2643
|
+
} catch (err) {
|
|
2644
|
+
console.error(err);
|
|
2645
|
+
throw err;
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
await completeMessageStep({
|
|
2649
|
+
assistantMessageId: event.assistantMessageId,
|
|
2650
|
+
input,
|
|
2651
|
+
writable
|
|
2652
|
+
});
|
|
2653
|
+
}
|
|
2654
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
2655
|
+
0 && (module.exports = {
|
|
2656
|
+
agentMessageHook,
|
|
2657
|
+
agentWorkflow
|
|
2658
|
+
});
|
|
2659
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL3NhbmRib3gvcHJvY2Vzcy1tYW5hZ2VyLnRzIiwgIi4uL3NyYy9lcnJvcnMudHMiLCAiLi4vc3JjL3V0aWxzL3BhZ2luYXRlLnRzIiwgIi4uL3NyYy9zdG9yYWdlL2JpbmRpbmdzL2xvY2FsLWZzLWhhbmRsZXJzLnRzIiwgIi4uL3NyYy9zdG9yYWdlL2JpbmRpbmdzL2xvY2FsLnRzIiwgIi4uL3NyYy9zdG9yYWdlL2JpbmRpbmdzL3ZlcmNlbC50cyIsICIuLi9zcmMvc3RvcmFnZS9jbGllbnQudHMiLCAiLi4vc3JjL3N0b3JhZ2UvcnBjLnRzIiwgIi4uL3NyYy9zdG9yYWdlL2hhbmRsZXIudHMiLCAiLi4vc3JjL3N0b3JhZ2UvaW5kZXgudHMiLCAiLi4vc3JjL3NhbmRib3gvd3JpdGUtZmlsZXMudHMiLCAiLi4vc3JjL3NhbmRib3gvYmluZGluZ3MvbG9jYWwudHMiLCAiLi4vc3JjL3NhbmRib3gvYmluZGluZ3MvdmVyY2VsLnRzIiwgIi4uL3NyYy9zYW5kYm94L2NsaWVudC50cyIsICIuLi9zcmMvc2FuZGJveC9pbmRleC50cyIsICIuLi9zcmMvYWdlbnQtd29ya2Zsb3cudHMiLCAiLi4vc3JjL2FnZW50LXdvcmtmbG93LXN0ZXBzLnRzIiwgIi4uL3NyYy9za2lsbHMvcGFyc2VyLnRzIiwgIi4uL3NyYy9za2lsbHMvZGlzY292ZXIudHMiLCAiLi4vc3JjL3Rvb2xzL2luZGV4LnRzIiwgIi4uL3NyYy91dGlscy91aS50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiaW1wb3J0IHR5cGUgeyBCYXNoUmVzdWx0LCBTYW5kYm94IH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuY29uc3QgREVGQVVMVF9XQUlUX1VOVElMID0gMzAwMDA7XG5cbi8qKlxuICogU2hlbGwgc2NyaXB0IHRoYXQgaGFuZGxlcyBhbGwgcHJvY2VzcyBleGVjdXRpb24gbG9naWMuXG4gKiBJbnN0YWxsZWQgdG8gfi8uYWdlbnQvYmluL3J1bi5zaCBkdXJpbmcgaW5pdCgpLlxuICovXG5jb25zdCBSVU5fU0NSSVBUID0gYCMhL2Jpbi9zaFxuIyBQcm9jZXNzIHJ1bm5lciBmb3IgQWdlbnQgU0RLXG4jIEFsbCBwYXJhbWV0ZXJzIHBhc3NlZCB2aWEgZW52aXJvbm1lbnQgdmFyaWFibGVzIHRvIGF2b2lkIGVzY2FwaW5nIGlzc3Vlc1xuIyBPdXRwdXQgaXMgYmFzZTY0IGVuY29kZWQgdG8gYXZvaWQgSlNPTiBlc2NhcGluZyBpc3N1ZXNcblxuQUdFTlRfRElSPVwiJEhPTUUvLmFnZW50XCJcbkNXRF9GSUxFPVwiJEFHRU5UX0RJUi9jd2QvJFNFU1NJT05fSURcIlxuXG4jIEdldCBjdXJyZW50IHdvcmtpbmcgZGlyZWN0b3J5IChwZXItc2Vzc2lvbilcbmlmIFsgLWYgXCIkQ1dEX0ZJTEVcIiBdOyB0aGVuXG4gIENXRD0kKGNhdCBcIiRDV0RfRklMRVwiKVxuZWxzZVxuICBDV0Q9XCIkSE9NRVwiXG5maVxuXG4jIERlY29kZSBjb21tYW5kXG5DTUQ9JChlY2hvIFwiJENNRF9CQVNFNjRcIiB8IGJhc2U2NCAtZClcblxuIyBCYWNrZ3JvdW5kIG1vZGUgKHdhaXRVbnRpbCA9IDApXG5pZiBbIFwiJFdBSVRfVU5USUxcIiA9IFwiMFwiIF07IHRoZW5cbiAgY2QgXCIkQ1dEXCIgfHwgY2QgXCIkSE9NRVwiXG5cbiAgIyBHZW5lcmF0ZSBhIHNpbXBsZSBudW1lcmljIElEIGZvciBvdXRwdXQgZmlsZVxuICBPVVRQVVRfSUQ9XCIkKGRhdGUgKyVzKSQkXCJcbiAgT1VUUFVUX0ZJTEU9XCIkQUdFTlRfRElSL291dHB1dHMvJE9VVFBVVF9JRC5sb2dcIlxuXG4gICMgRG91YmxlLWZvcmsgdG8gZnVsbHkgZGV0YWNoIHRoZSBwcm9jZXNzXG4gIChcbiAgICAoXG4gICAgICBldmFsIFwiJENNRFwiXG4gICAgICBwd2QgPiBcIiRDV0RfRklMRVwiIDI+L2Rldi9udWxsXG4gICAgKSA+IFwiJE9VVFBVVF9GSUxFXCIgMj4mMSA8IC9kZXYvbnVsbCAmXG4gICAgZWNobyAkISA+IFwiJEFHRU5UX0RJUi9waWRzLyRPVVRQVVRfSUQucGlkXCJcbiAgKVxuXG4gICMgU21hbGwgZGVsYXkgdG8gZW5zdXJlIFBJRCBmaWxlIGlzIHdyaXR0ZW5cbiAgc2xlZXAgMC4wNVxuXG4gICMgUmVhZCBQSURcbiAgaWYgWyAtZiBcIiRBR0VOVF9ESVIvcGlkcy8kT1VUUFVUX0lELnBpZFwiIF07IHRoZW5cbiAgICBQSUQ9JChjYXQgXCIkQUdFTlRfRElSL3BpZHMvJE9VVFBVVF9JRC5waWRcIilcbiAgZWxzZVxuICAgIFBJRD0wXG4gIGZpXG5cbiAgIyBPdXRwdXQgSlNPTiByZXN1bHQgKG5vIG91dHB1dCBmb3IgYmFja2dyb3VuZCwgc28gbm8gZW5jb2RpbmcgbmVlZGVkKVxuICBwcmludGYgJ3tcInBpZFwiOiVkLFwib3V0cHV0QmFzZTY0XCI6XCJcIixcImV4aXRDb2RlXCI6LTEsXCJzdGF0dXNcIjpcInJ1bm5pbmdcIixcIm91dHB1dEZpbGVcIjpcIiVzXCIsXCJjd2RcIjpcIiVzXCJ9XFxcXG4nIFxcXFxcbiAgICBcIiRQSURcIiBcIiRPVVRQVVRfRklMRVwiIFwiJENXRFwiXG4gIGV4aXQgMFxuZmlcblxuIyBGb3JlZ3JvdW5kIG1vZGUgKHdhaXRVbnRpbCA+IDApIC0gcnVuIGRpcmVjdGx5IGFuZCBjYXB0dXJlIG91dHB1dFxuY2QgXCIkQ1dEXCIgfHwgY2QgXCIkSE9NRVwiXG5cbiMgUnVuIGNvbW1hbmQsIGNhcHR1cmUgb3V0cHV0IGFuZCBleGl0IGNvZGVcbk9VVFBVVD0kKGV2YWwgXCIkQ01EXCIgMj4mMSlcbkVYSVRfQ09ERT0kP1xuXG4jIFVwZGF0ZSBDV0QgYWZ0ZXIgY29tbWFuZFxuTkVXX0NXRD0kKHB3ZClcbmVjaG8gXCIkTkVXX0NXRFwiID4gXCIkQ1dEX0ZJTEVcIlxuXG4jIERldGVybWluZSBzdGF0dXNcbmlmIFsgJEVYSVRfQ09ERSAtZXEgMCBdOyB0aGVuXG4gIFNUQVRVUz1cImNvbXBsZXRlZFwiXG5lbHNlXG4gIFNUQVRVUz1cImZhaWxlZFwiXG5maVxuXG4jIEJhc2U2NCBlbmNvZGUgb3V0cHV0IHRvIGF2b2lkIEFMTCBlc2NhcGluZyBpc3N1ZXNcbk9VVFBVVF9CQVNFNjQ9JChwcmludGYgJyVzJyBcIiRPVVRQVVRcIiB8IGJhc2U2NCB8IHRyIC1kICdcXFxcbicpXG5cbiMgT3V0cHV0IEpTT04gcmVzdWx0IHdpdGggYmFzZTY0LWVuY29kZWQgb3V0cHV0XG5wcmludGYgJ3tcInBpZFwiOjAsXCJvdXRwdXRCYXNlNjRcIjpcIiVzXCIsXCJleGl0Q29kZVwiOiVkLFwic3RhdHVzXCI6XCIlc1wiLFwib3V0cHV0RmlsZVwiOlwiXCIsXCJjd2RcIjpcIiVzXCJ9XFxcXG4nIFxcXFxcbiAgXCIkT1VUUFVUX0JBU0U2NFwiIFwiJEVYSVRfQ09ERVwiIFwiJFNUQVRVU1wiIFwiJE5FV19DV0RcIlxuYDtcblxudHlwZSBSdW5PcHRpb25zID0ge1xuICBjb21tYW5kOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBNYXggbXMgdG8gd2FpdCBmb3IgY29tcGxldGlvbi5cbiAgICogLSAwOiBCYWNrZ3JvdW5kIG1vZGUgLSByZXR1cm4gaW1tZWRpYXRlbHkgd2l0aCBQSURcbiAgICogLSA+MDogRm9yZWdyb3VuZCBtb2RlIC0gd2FpdCBmb3IgY29tcGxldGlvbiAoZGVmYXVsdDogMzAwMDApXG4gICAqL1xuICB3YWl0VW50aWw/OiBudW1iZXI7XG59O1xuXG4vKipcbiAqIFByb2Nlc3MgbWFuYWdlciB0aGF0IHVzZXMgYSBzaW5nbGUgc2hlbGwgc2NyaXB0IHRvIGhhbmRsZSBhbGwgZXhlY3V0aW9uIGxvZ2ljLlxuICogUmVkdWNlcyByb3VuZC10cmlwcyB0byB0aGUgc2FuZGJveCBieSBkb2luZyBldmVyeXRoaW5nIGluIG9uZSBleGVjIGNhbGwuXG4gKi9cbmV4cG9ydCBjb25zdCBjcmVhdGVQcm9jZXNzTWFuYWdlciA9IChvcHRzOiB7XG4gIHNhbmRib3g6IFNhbmRib3g7XG4gIHNlc3Npb25JZDogc3RyaW5nO1xuICBnZW5lcmF0ZUlkOiAoKSA9PiBzdHJpbmc7XG59KSA9PiB7XG4gIGNvbnN0IHsgc2FuZGJveCwgc2Vzc2lvbklkIH0gPSBvcHRzO1xuICBsZXQgaW5pdGlhbGl6ZWQgPSBmYWxzZTtcblxuICBjb25zdCBpbml0ID0gYXN5bmMgKCk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgIGlmIChpbml0aWFsaXplZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHNhbmRib3guZXhlYyh7XG4gICAgICBjb21tYW5kOiBcInNoXCIsXG4gICAgICBhcmdzOiBbXG4gICAgICAgIFwiLWNcIixcbiAgICAgICAgYG1rZGlyIC1wICRIT01FLy5hZ2VudC9iaW4gJEhPTUUvLmFnZW50L3BpZHMgJEhPTUUvLmFnZW50L291dHB1dHMgJEhPTUUvLmFnZW50L2N3ZFxuY2F0ID4gJEhPTUUvLmFnZW50L2Jpbi9ydW4uc2ggPDwgJ1NDUklQVF9FT0YnXG4ke1JVTl9TQ1JJUFR9XG5TQ1JJUFRfRU9GXG5jaG1vZCAreCAkSE9NRS8uYWdlbnQvYmluL3J1bi5zaGAsXG4gICAgICBdLFxuICAgIH0pO1xuXG4gICAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICB0aHJvdyByZXN1bHQ7XG4gICAgfVxuICAgIGF3YWl0IHJlc3VsdC5yZXN1bHQ7XG4gICAgaW5pdGlhbGl6ZWQgPSB0cnVlO1xuICB9O1xuXG4gIGNvbnN0IHJ1biA9IGFzeW5jIChvcHRzOiBSdW5PcHRpb25zKTogUHJvbWlzZTxCYXNoUmVzdWx0PiA9PiB7XG4gICAgYXdhaXQgaW5pdCgpO1xuXG4gICAgY29uc3QgeyBjb21tYW5kLCB3YWl0VW50aWwgPSBERUZBVUxUX1dBSVRfVU5USUwgfSA9IG9wdHM7XG4gICAgY29uc3QgY21kQmFzZTY0ID0gQnVmZmVyLmZyb20oY29tbWFuZCwgXCJ1dGYtOFwiKS50b1N0cmluZyhcImJhc2U2NFwiKTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHNhbmRib3guZXhlYyh7XG4gICAgICBjb21tYW5kOiBcInNoXCIsXG4gICAgICBhcmdzOiBbXG4gICAgICAgIFwiLWNcIixcbiAgICAgICAgYENNRF9CQVNFNjQ9XCIke2NtZEJhc2U2NH1cIiBXQUlUX1VOVElMPVwiJHt3YWl0VW50aWx9XCIgU0VTU0lPTl9JRD1cIiR7c2Vzc2lvbklkfVwiICRIT01FLy5hZ2VudC9iaW4vcnVuLnNoYCxcbiAgICAgIF0sXG4gICAgfSk7XG5cbiAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIHRocm93IHJlc3VsdDtcbiAgICB9XG5cbiAgICBjb25zdCB7IHN0ZG91dCB9ID0gYXdhaXQgcmVzdWx0LnJlc3VsdDtcbiAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKHN0ZG91dC50cmltKCkpIGFzIHtcbiAgICAgIHBpZDogbnVtYmVyO1xuICAgICAgb3V0cHV0QmFzZTY0OiBzdHJpbmc7XG4gICAgICBleGl0Q29kZTogbnVtYmVyO1xuICAgICAgc3RhdHVzOiBcInJ1bm5pbmdcIiB8IFwiY29tcGxldGVkXCIgfCBcImZhaWxlZFwiO1xuICAgICAgb3V0cHV0RmlsZTogc3RyaW5nO1xuICAgICAgY3dkOiBzdHJpbmc7XG4gICAgfTtcblxuICAgIC8vIERlY29kZSBiYXNlNjQgb3V0cHV0XG4gICAgY29uc3Qgb3V0cHV0ID0gcGFyc2VkLm91dHB1dEJhc2U2NFxuICAgICAgPyBCdWZmZXIuZnJvbShwYXJzZWQub3V0cHV0QmFzZTY0LCBcImJhc2U2NFwiKS50b1N0cmluZyhcInV0Zi04XCIpXG4gICAgICA6IFwiXCI7XG5cbiAgICByZXR1cm4ge1xuICAgICAgcGlkOiBwYXJzZWQucGlkLFxuICAgICAgb3V0cHV0LFxuICAgICAgZXhpdENvZGU6IHBhcnNlZC5leGl0Q29kZSxcbiAgICAgIHN0YXR1czogcGFyc2VkLnN0YXR1cyxcbiAgICAgIGN3ZDogcGFyc2VkLmN3ZCxcbiAgICAgIG91dHB1dEZpbGU6IHBhcnNlZC5vdXRwdXRGaWxlLFxuICAgIH07XG4gIH07XG5cbiAgY29uc3QgZ2V0Q3dkID0gYXN5bmMgKCk6IFByb21pc2U8c3RyaW5nPiA9PiB7XG4gICAgYXdhaXQgaW5pdCgpO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc2FuZGJveC5leGVjKHtcbiAgICAgIGNvbW1hbmQ6IFwic2hcIixcbiAgICAgIGFyZ3M6IFtcbiAgICAgICAgXCItY1wiLFxuICAgICAgICBgY2F0ICRIT01FLy5hZ2VudC9jd2QvJHtzZXNzaW9uSWR9IDI+L2Rldi9udWxsIHx8IGVjaG8gXCIkSE9NRVwiYCxcbiAgICAgIF0sXG4gICAgfSk7XG5cbiAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmN3ZCgpO1xuICAgIH1cblxuICAgIGNvbnN0IHsgc3Rkb3V0IH0gPSBhd2FpdCByZXN1bHQucmVzdWx0O1xuICAgIHJldHVybiBzdGRvdXQudHJpbSgpIHx8IHByb2Nlc3MuY3dkKCk7XG4gIH07XG5cbiAgcmV0dXJuIHtcbiAgICBpbml0LFxuICAgIHJ1bixcbiAgICBnZXRDd2QsXG4gIH07XG59O1xuXG5leHBvcnQgdHlwZSBQcm9jZXNzTWFuYWdlciA9IFJldHVyblR5cGU8dHlwZW9mIGNyZWF0ZVByb2Nlc3NNYW5hZ2VyPjtcbiIsICJpbXBvcnQgKiBhcyBlcnJvcmUgZnJvbSBcImVycm9yZVwiO1xuXG5leHBvcnQgY2xhc3MgU2Vzc2lvbk5vdEZvdW5kRXJyb3IgZXh0ZW5kcyBlcnJvcmUuY3JlYXRlVGFnZ2VkRXJyb3Ioe1xuICBuYW1lOiBcIlNlc3Npb25Ob3RGb3VuZEVycm9yXCIsXG4gIG1lc3NhZ2U6IFwiU2Vzc2lvbiAkaWQgbm90IGZvdW5kXCIsXG59KSB7fVxuXG5leHBvcnQgY2xhc3MgU2Vzc2lvbkVycm9yIGV4dGVuZHMgZXJyb3JlLmNyZWF0ZVRhZ2dlZEVycm9yKHtcbiAgbmFtZTogXCJTZXNzaW9uRXJyb3JcIixcbiAgbWVzc2FnZTogXCJTZXNzaW9uICRpZCBmYWlsZWQ6ICRyZWFzb25cIixcbn0pIHt9XG5cbmV4cG9ydCBjbGFzcyBTYW5kYm94Tm90Rm91bmRFcnJvciBleHRlbmRzIGVycm9yZS5jcmVhdGVUYWdnZWRFcnJvcih7XG4gIG5hbWU6IFwiU2FuZGJveE5vdEZvdW5kRXJyb3JcIixcbiAgbWVzc2FnZTogXCJTYW5kYm94ICRpZCBub3QgZm91bmRcIixcbn0pIHt9XG5cbmV4cG9ydCBjbGFzcyBTdG9yYWdlRXJyb3IgZXh0ZW5kcyBlcnJvcmUuY3JlYXRlVGFnZ2VkRXJyb3Ioe1xuICBuYW1lOiBcIlN0b3JhZ2VFcnJvclwiLFxuICBtZXNzYWdlOiBcIiRyZWFzb25cIixcbn0pIHt9XG5cbmV4cG9ydCBjbGFzcyBTYW5kYm94RXJyb3IgZXh0ZW5kcyBlcnJvcmUuY3JlYXRlVGFnZ2VkRXJyb3Ioe1xuICBuYW1lOiBcIlNhbmRib3hFcnJvclwiLFxuICBtZXNzYWdlOiBcIiRyZWFzb25cIixcbn0pIHt9XG5cbmV4cG9ydCBjbGFzcyBNZXNzYWdlTm90Rm91bmRFcnJvciBleHRlbmRzIGVycm9yZS5jcmVhdGVUYWdnZWRFcnJvcih7XG4gIG5hbWU6IFwiTWVzc2FnZU5vdEZvdW5kRXJyb3JcIixcbiAgbWVzc2FnZTogXCJNZXNzYWdlICRpZCBub3QgZm91bmRcIixcbn0pIHt9XG4iLCAiaW1wb3J0IHR5cGUgeyBMaXN0UmVzdWx0IH0gZnJvbSBcIi4uL3N0b3JhZ2VcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIHBhZ2luYXRlPFQgZXh0ZW5kcyB7IGlkOiBzdHJpbmcgfT4ob3B0czoge1xuICBpdGVtczogVFtdO1xuICBjdXJzb3I/OiBzdHJpbmc7XG4gIGxpbWl0PzogbnVtYmVyO1xufSk6IExpc3RSZXN1bHQ8VD4ge1xuICBjb25zdCB7IGl0ZW1zLCBjdXJzb3IsIGxpbWl0ID0gNTAgfSA9IG9wdHM7XG4gIGNvbnN0IHN0YXJ0SW5kZXggPSBjdXJzb3IgPyBpdGVtcy5maW5kSW5kZXgoKG0pID0+IG0uaWQgPT09IGN1cnNvcikgKyAxIDogMDtcbiAgY29uc3Qgc2xpY2VkID0gaXRlbXMuc2xpY2Uoc3RhcnRJbmRleCwgc3RhcnRJbmRleCArIGxpbWl0KTtcbiAgY29uc3QgbmV4dEN1cnNvciA9XG4gICAgc3RhcnRJbmRleCArIGxpbWl0IDwgaXRlbXMubGVuZ3RoID8gKHNsaWNlZC5hdCgtMSk/LmlkID8/IG51bGwpIDogbnVsbDtcbiAgcmV0dXJuIHsgaXRlbXM6IHNsaWNlZCwgbmV4dEN1cnNvciB9O1xufVxuIiwgImltcG9ydCB7IG1rZGlyLCByZWFkZGlyLCByZWFkRmlsZSwgd3JpdGVGaWxlIH0gZnJvbSBcIm5vZGU6ZnMvcHJvbWlzZXNcIjtcbmltcG9ydCB7IGRpcm5hbWUsIGpvaW4gfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgeyBwYWdpbmF0ZSB9IGZyb20gXCIuLi8uLi91dGlscy9wYWdpbmF0ZVwiO1xuaW1wb3J0IHR5cGUge1xuICBDb21tYW5kLFxuICBIYW5kbGVycyxcbiAgTWVzc2FnZSxcbiAgUGFydCxcbiAgU2FuZGJveFJlY29yZCxcbiAgU2Vzc2lvbixcbn0gZnJvbSBcIi4uXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVGaWxlc3lzdGVtSGFuZGxlcnMoYmFzZVBhdGg6IHN0cmluZyk6IEhhbmRsZXJzIHtcbiAgY29uc3Qgc2Vzc2lvbkRpciA9IGpvaW4oYmFzZVBhdGgsIFwic2Vzc2lvblwiKTtcbiAgY29uc3QgbWVzc2FnZURpciA9IGpvaW4oYmFzZVBhdGgsIFwibWVzc2FnZVwiKTtcbiAgY29uc3QgcGFydERpciA9IGpvaW4oYmFzZVBhdGgsIFwicGFydFwiKTtcbiAgY29uc3Qgc2FuZGJveERpciA9IGpvaW4oYmFzZVBhdGgsIFwic2FuZGJveFwiKTtcbiAgY29uc3QgY29tbWFuZERpciA9IGpvaW4oYmFzZVBhdGgsIFwiY29tbWFuZFwiKTtcblxuICBhc3luYyBmdW5jdGlvbiBlbnN1cmVEaXIoZGlyOiBzdHJpbmcpIHtcbiAgICBhd2FpdCBta2RpcihkaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gcmVhZEpzb248VD4oZmlsZVBhdGg6IHN0cmluZyk6IFByb21pc2U8VCB8IG51bGw+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgY29udGVudCA9IGF3YWl0IHJlYWRGaWxlKGZpbGVQYXRoLCBcInV0Zi04XCIpO1xuICAgICAgcmV0dXJuIEpTT04ucGFyc2UoY29udGVudCkgYXMgVDtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIHdyaXRlSnNvbkZpbGUoZmlsZVBhdGg6IHN0cmluZywgZGF0YTogdW5rbm93bikge1xuICAgIGF3YWl0IGVuc3VyZURpcihkaXJuYW1lKGZpbGVQYXRoKSk7XG4gICAgYXdhaXQgd3JpdGVGaWxlKGZpbGVQYXRoLCBKU09OLnN0cmluZ2lmeShkYXRhLCBudWxsLCAyKSk7XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiByZWFkQWxsRnJvbURpcjxUPihkaXI6IHN0cmluZyk6IFByb21pc2U8VFtdPiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGZpbGVzID0gYXdhaXQgcmVhZGRpcihkaXIpO1xuICAgICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICBmaWxlc1xuICAgICAgICAgIC5maWx0ZXIoKGYpID0+IGYuZW5kc1dpdGgoXCIuanNvblwiKSlcbiAgICAgICAgICAubWFwKChmKSA9PiByZWFkSnNvbjxUPihqb2luKGRpciwgZikpKVxuICAgICAgKTtcbiAgICAgIHJldHVybiByZXN1bHRzLmZpbHRlcigocik6IHIgaXMgTm9uTnVsbGFibGU8dHlwZW9mIHI+ID0+IHIgIT09IG51bGwpO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgXCJzZXNzaW9uLmdldFwiOiBhc3luYyAoeyBpZCB9KSA9PiB7XG4gICAgICBjb25zdCBzZXNzaW9uID0gYXdhaXQgcmVhZEpzb248U2Vzc2lvbj4oam9pbihzZXNzaW9uRGlyLCBgJHtpZH0uanNvbmApKTtcbiAgICAgIHJldHVybiBzZXNzaW9uID8/IG51bGw7XG4gICAgfSxcblxuICAgIFwic2Vzc2lvbi5zZXRcIjogYXN5bmMgKHNlc3Npb24pID0+IHtcbiAgICAgIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gICAgICBjb25zdCBzZXNzaW9uUGF0aCA9IGpvaW4oc2Vzc2lvbkRpciwgYCR7c2Vzc2lvbi5pZH0uanNvbmApO1xuICAgICAgY29uc3QgZXhpc3RpbmcgPSBhd2FpdCByZWFkSnNvbjxTZXNzaW9uPihzZXNzaW9uUGF0aCk7XG4gICAgICBjb25zdCBuZXdTZXNzaW9uOiBTZXNzaW9uID0ge1xuICAgICAgICAuLi5zZXNzaW9uLFxuICAgICAgICB0YWdzOiBzZXNzaW9uLnRhZ3MgPz8gZXhpc3Rpbmc/LnRhZ3MgPz8ge30sXG4gICAgICAgIGNyZWF0ZWRBdDogZXhpc3Rpbmc/LmNyZWF0ZWRBdCA/PyBzZXNzaW9uLmNyZWF0ZWRBdCA/PyBub3csXG4gICAgICAgIHVwZGF0ZWRBdDogbm93LFxuICAgICAgfTtcbiAgICAgIGF3YWl0IHdyaXRlSnNvbkZpbGUoc2Vzc2lvblBhdGgsIG5ld1Nlc3Npb24pO1xuICAgICAgcmV0dXJuIG5ld1Nlc3Npb247XG4gICAgfSxcblxuICAgIFwic2Vzc2lvbi5saXN0XCI6IGFzeW5jICh7IHRhZ3MsIGN1cnNvciwgbGltaXQgfSkgPT4ge1xuICAgICAgY29uc3QgYWxsU2Vzc2lvbnMgPSBhd2FpdCByZWFkQWxsRnJvbURpcjxTZXNzaW9uPihzZXNzaW9uRGlyKTtcbiAgICAgIGxldCBmaWx0ZXJlZCA9IGFsbFNlc3Npb25zO1xuICAgICAgaWYgKHRhZ3MgJiYgT2JqZWN0LmtleXModGFncykubGVuZ3RoID4gMCkge1xuICAgICAgICBmaWx0ZXJlZCA9IGZpbHRlcmVkLmZpbHRlcigocykgPT4ge1xuICAgICAgICAgIGNvbnN0IHNlc3Npb25UYWdzID0gcy50YWdzID8/IHt9O1xuICAgICAgICAgIHJldHVybiBPYmplY3QuZW50cmllcyh0YWdzKS5ldmVyeShcbiAgICAgICAgICAgIChba2V5LCB2YWx1ZV0pID0+IHNlc3Npb25UYWdzW2tleV0gPT09IHZhbHVlXG4gICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICBmaWx0ZXJlZC5zb3J0KChhLCBiKSA9PiBhLmNyZWF0ZWRBdCAtIGIuY3JlYXRlZEF0KTtcbiAgICAgIHJldHVybiBwYWdpbmF0ZSh7IGl0ZW1zOiBmaWx0ZXJlZCwgY3Vyc29yLCBsaW1pdCB9KTtcbiAgICB9LFxuXG4gICAgXCJzZXNzaW9uLmxpc3RCeVNhbmRib3hcIjogYXN5bmMgKHsgc2FuZGJveElkLCB0YWdzLCBjdXJzb3IsIGxpbWl0IH0pID0+IHtcbiAgICAgIGNvbnN0IGFsbFNlc3Npb25zID0gYXdhaXQgcmVhZEFsbEZyb21EaXI8U2Vzc2lvbj4oc2Vzc2lvbkRpcik7XG4gICAgICBsZXQgZmlsdGVyZWQgPSBhbGxTZXNzaW9ucy5maWx0ZXIoKHMpID0+IHMuc2FuZGJveElkID09PSBzYW5kYm94SWQpO1xuICAgICAgaWYgKHRhZ3MgJiYgT2JqZWN0LmtleXModGFncykubGVuZ3RoID4gMCkge1xuICAgICAgICBmaWx0ZXJlZCA9IGZpbHRlcmVkLmZpbHRlcigocykgPT4ge1xuICAgICAgICAgIGNvbnN0IHNlc3Npb25UYWdzID0gcy50YWdzID8/IHt9O1xuICAgICAgICAgIHJldHVybiBPYmplY3QuZW50cmllcyh0YWdzKS5ldmVyeShcbiAgICAgICAgICAgIChba2V5LCB2YWx1ZV0pID0+IHNlc3Npb25UYWdzW2tleV0gPT09IHZhbHVlXG4gICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICBmaWx0ZXJlZC5zb3J0KChhLCBiKSA9PiBhLmNyZWF0ZWRBdCAtIGIuY3JlYXRlZEF0KTtcbiAgICAgIHJldHVybiBwYWdpbmF0ZSh7IGl0ZW1zOiBmaWx0ZXJlZCwgY3Vyc29yLCBsaW1pdCB9KTtcbiAgICB9LFxuXG4gICAgXCJzZXNzaW9uLnRhZy5zZXRcIjogYXN5bmMgKHsgc2Vzc2lvbklkLCB0YWdzIH0pID0+IHtcbiAgICAgIGNvbnN0IHNlc3Npb25QYXRoID0gam9pbihzZXNzaW9uRGlyLCBgJHtzZXNzaW9uSWR9Lmpzb25gKTtcbiAgICAgIGNvbnN0IGV4aXN0aW5nID0gYXdhaXQgcmVhZEpzb248U2Vzc2lvbj4oc2Vzc2lvblBhdGgpO1xuICAgICAgaWYgKCFleGlzdGluZykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFNlc3Npb24gJHtzZXNzaW9uSWR9IG5vdCBmb3VuZGApO1xuICAgICAgfVxuICAgICAgY29uc3QgbWVyZ2VkVGFncyA9IHsgLi4uZXhpc3RpbmcudGFncywgLi4udGFncyB9O1xuICAgICAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgIGNvbnN0IHVwZGF0ZWRTZXNzaW9uOiBTZXNzaW9uID0ge1xuICAgICAgICAuLi5leGlzdGluZyxcbiAgICAgICAgdGFnczogbWVyZ2VkVGFncyxcbiAgICAgICAgdXBkYXRlZEF0OiBub3csXG4gICAgICB9O1xuICAgICAgYXdhaXQgd3JpdGVKc29uRmlsZShzZXNzaW9uUGF0aCwgdXBkYXRlZFNlc3Npb24pO1xuICAgICAgcmV0dXJuIHVwZGF0ZWRTZXNzaW9uO1xuICAgIH0sXG5cbiAgICBcIm1lc3NhZ2UuZ2V0XCI6IGFzeW5jICh7IGlkIH0pID0+IHtcbiAgICAgIHJldHVybiBhd2FpdCByZWFkSnNvbjxNZXNzYWdlPihqb2luKG1lc3NhZ2VEaXIsIGAke2lkfS5qc29uYCkpO1xuICAgIH0sXG5cbiAgICBcIm1lc3NhZ2Uuc2V0XCI6IGFzeW5jIChtZXNzYWdlKSA9PiB7XG4gICAgICBhd2FpdCB3cml0ZUpzb25GaWxlKGpvaW4obWVzc2FnZURpciwgYCR7bWVzc2FnZS5pZH0uanNvbmApLCBtZXNzYWdlKTtcbiAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgIH0sXG5cbiAgICBcIm1lc3NhZ2UubGlzdFwiOiBhc3luYyAoeyBzZXNzaW9uSWQsIGN1cnNvciwgbGltaXQgfSkgPT4ge1xuICAgICAgY29uc3QgYWxsTWVzc2FnZXMgPSBhd2FpdCByZWFkQWxsRnJvbURpcjxNZXNzYWdlPihtZXNzYWdlRGlyKTtcbiAgICAgIGNvbnN0IGZpbHRlcmVkID0gYWxsTWVzc2FnZXNcbiAgICAgICAgLmZpbHRlcigobSkgPT4gbS5zZXNzaW9uSWQgPT09IHNlc3Npb25JZClcbiAgICAgICAgLnNvcnQoKGEsIGIpID0+IGEuY3JlYXRlZEF0IC0gYi5jcmVhdGVkQXQpO1xuICAgICAgcmV0dXJuIHBhZ2luYXRlKHsgaXRlbXM6IGZpbHRlcmVkLCBjdXJzb3IsIGxpbWl0IH0pO1xuICAgIH0sXG5cbiAgICBcInBhcnQubGlzdEJ5TWVzc2FnZVwiOiBhc3luYyAoeyBtZXNzYWdlSWQsIGN1cnNvciwgbGltaXQgfSkgPT4ge1xuICAgICAgY29uc3QgYWxsUGFydHMgPSBhd2FpdCByZWFkQWxsRnJvbURpcjxQYXJ0PihwYXJ0RGlyKTtcbiAgICAgIGNvbnN0IGZpbHRlcmVkID0gYWxsUGFydHNcbiAgICAgICAgLmZpbHRlcigocCkgPT4gcC5tZXNzYWdlSWQgPT09IG1lc3NhZ2VJZClcbiAgICAgICAgLnNvcnQoKGEsIGIpID0+IGEuaW5kZXggLSBiLmluZGV4KTtcbiAgICAgIHJldHVybiBwYWdpbmF0ZSh7IGl0ZW1zOiBmaWx0ZXJlZCwgY3Vyc29yLCBsaW1pdCB9KTtcbiAgICB9LFxuXG4gICAgXCJwYXJ0Lmxpc3RCeVNlc3Npb25cIjogYXN5bmMgKHsgc2Vzc2lvbklkLCBjdXJzb3IsIGxpbWl0IH0pID0+IHtcbiAgICAgIGNvbnN0IGFsbFBhcnRzID0gYXdhaXQgcmVhZEFsbEZyb21EaXI8UGFydD4ocGFydERpcik7XG4gICAgICBjb25zdCBmaWx0ZXJlZCA9IGFsbFBhcnRzXG4gICAgICAgIC5maWx0ZXIoKHApID0+IHAuc2Vzc2lvbklkID09PSBzZXNzaW9uSWQpXG4gICAgICAgIC5zb3J0KChhLCBiKSA9PiB7XG4gICAgICAgICAgaWYgKGEubWVzc2FnZUlkICE9PSBiLm1lc3NhZ2VJZCkge1xuICAgICAgICAgICAgcmV0dXJuIGEubWVzc2FnZUlkLmxvY2FsZUNvbXBhcmUoYi5tZXNzYWdlSWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gYS5pbmRleCAtIGIuaW5kZXg7XG4gICAgICAgIH0pO1xuICAgICAgcmV0dXJuIHBhZ2luYXRlKHsgaXRlbXM6IGZpbHRlcmVkLCBjdXJzb3IsIGxpbWl0IH0pO1xuICAgIH0sXG5cbiAgICBcInBhcnQuc2V0XCI6IGFzeW5jIChwYXJ0KSA9PiB7XG4gICAgICBhd2FpdCB3cml0ZUpzb25GaWxlKGpvaW4ocGFydERpciwgYCR7cGFydC5pZH0uanNvbmApLCBwYXJ0KTtcbiAgICAgIHJldHVybiBwYXJ0O1xuICAgIH0sXG5cbiAgICBcInNhbmRib3guZ2V0XCI6IGFzeW5jICh7IGtleSB9KSA9PiB7XG4gICAgICBjb25zdCBzYWZlTmFtZSA9IEJ1ZmZlci5mcm9tKGtleSkudG9TdHJpbmcoXCJiYXNlNjR1cmxcIik7XG4gICAgICBjb25zdCBzYW5kYm94UGF0aCA9IGpvaW4oc2FuZGJveERpciwgYCR7c2FmZU5hbWV9Lmpzb25gKTtcbiAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCByZWFkSnNvbjxTYW5kYm94UmVjb3JkPihzYW5kYm94UGF0aCk7XG4gICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICByZXR1cm4gZGF0YTtcbiAgICB9LFxuXG4gICAgXCJzYW5kYm94LnNldFwiOiBhc3luYyAocmVjb3JkKSA9PiB7XG4gICAgICBjb25zdCBzYWZlTmFtZSA9IEJ1ZmZlci5mcm9tKHJlY29yZC5pZCkudG9TdHJpbmcoXCJiYXNlNjR1cmxcIik7XG4gICAgICBjb25zdCBzYW5kYm94UGF0aCA9IGpvaW4oc2FuZGJveERpciwgYCR7c2FmZU5hbWV9Lmpzb25gKTtcbiAgICAgIGF3YWl0IHdyaXRlSnNvbkZpbGUoc2FuZGJveFBhdGgsIHJlY29yZCk7XG4gICAgfSxcblxuICAgIFwic2FuZGJveC5nZXRCeVNlc3Npb25cIjogYXN5bmMgKHsgc2Vzc2lvbklkIH0pID0+IHtcbiAgICAgIGNvbnN0IGFsbFNhbmRib3hlcyA9IGF3YWl0IHJlYWRBbGxGcm9tRGlyPFNhbmRib3hSZWNvcmQ+KHNhbmRib3hEaXIpO1xuICAgICAgY29uc3QgbWF0Y2hpbmcgPSBhbGxTYW5kYm94ZXMuZmlsdGVyKChzKSA9PlxuICAgICAgICBzLmlkLnN0YXJ0c1dpdGgoYCR7c2Vzc2lvbklkfS1gKVxuICAgICAgKTtcbiAgICAgIGlmIChtYXRjaGluZy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICBtYXRjaGluZy5zb3J0KFxuICAgICAgICAoYSwgYikgPT4gKGIubGFzdEFjdGl2aXR5QXQgPz8gMCkgLSAoYS5sYXN0QWN0aXZpdHlBdCA/PyAwKVxuICAgICAgKTtcbiAgICAgIHJldHVybiBtYXRjaGluZ1swXTtcbiAgICB9LFxuXG4gICAgXCJjb21tYW5kLmdldFwiOiBhc3luYyAoeyBpZCB9KSA9PiB7XG4gICAgICByZXR1cm4gYXdhaXQgcmVhZEpzb248Q29tbWFuZD4oam9pbihjb21tYW5kRGlyLCBgJHtpZH0uanNvbmApKTtcbiAgICB9LFxuXG4gICAgXCJjb21tYW5kLnNldFwiOiBhc3luYyAoY29tbWFuZCkgPT4ge1xuICAgICAgYXdhaXQgd3JpdGVKc29uRmlsZShqb2luKGNvbW1hbmREaXIsIGAke2NvbW1hbmQuaWR9Lmpzb25gKSwgY29tbWFuZCk7XG4gICAgICByZXR1cm4gY29tbWFuZDtcbiAgICB9LFxuXG4gICAgXCJjb21tYW5kLmxpc3RcIjogYXN5bmMgKHsgc2Vzc2lvbklkLCBpbmNsdWRlRmluaXNoZWQsIGN1cnNvciwgbGltaXQgfSkgPT4ge1xuICAgICAgY29uc3QgYWxsQ29tbWFuZHMgPSBhd2FpdCByZWFkQWxsRnJvbURpcjxDb21tYW5kPihjb21tYW5kRGlyKTtcbiAgICAgIGxldCBmaWx0ZXJlZCA9IGFsbENvbW1hbmRzLmZpbHRlcigoYykgPT4gYy5zZXNzaW9uSWQgPT09IHNlc3Npb25JZCk7XG4gICAgICBpZiAoIWluY2x1ZGVGaW5pc2hlZCkge1xuICAgICAgICBmaWx0ZXJlZCA9IGZpbHRlcmVkLmZpbHRlcigoYykgPT4gYy5zdGF0dXMgPT09IFwicnVubmluZ1wiKTtcbiAgICAgIH1cbiAgICAgIGZpbHRlcmVkLnNvcnQoKGEsIGIpID0+IGEuc3RhcnRlZEF0IC0gYi5zdGFydGVkQXQpO1xuICAgICAgcmV0dXJuIHBhZ2luYXRlKHsgaXRlbXM6IGZpbHRlcmVkLCBjdXJzb3IsIGxpbWl0IH0pO1xuICAgIH0sXG4gIH07XG59XG4iLCAiaW1wb3J0IHsgdHlwZSBTZXJ2ZXJUeXBlLCBzZXJ2ZSB9IGZyb20gXCJAaG9uby9ub2RlLXNlcnZlclwiO1xuaW1wb3J0IHsgSG9ubyB9IGZyb20gXCJob25vXCI7XG5pbXBvcnQgeyBoYW5kbGVTdG9yYWdlUnBjIH0gZnJvbSBcIi4uXCI7XG5pbXBvcnQgeyBjcmVhdGVGaWxlc3lzdGVtSGFuZGxlcnMgfSBmcm9tIFwiLi9sb2NhbC1mcy1oYW5kbGVyc1wiO1xuXG5jb25zdCBERUZBVUxUX1NUT1JBR0VfRElSID0gXCIuYWdlbnQtc3RvcmFnZVwiO1xuXG5sZXQgc3RhcnRQcm9taXNlOiBQcm9taXNlPHN0cmluZz4gfCBudWxsID0gbnVsbDtcbmxldCBzZXJ2ZXJJbnN0YW5jZTogeyB1cmw6IHN0cmluZzsgc2VydmVyOiBTZXJ2ZXJUeXBlIH0gfCBudWxsID0gbnVsbDtcblxuZXhwb3J0IGZ1bmN0aW9uIHN0YXJ0TG9jYWxTdG9yYWdlKG9wdHM/OiB7XG4gIHBhdGg/OiBzdHJpbmc7XG4gIHBvcnQ/OiBudW1iZXI7XG59KTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgaWYgKHN0YXJ0UHJvbWlzZSkge1xuICAgIHJldHVybiBzdGFydFByb21pc2U7XG4gIH1cblxuICBzdGFydFByb21pc2UgPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgIGNvbnN0IGhhbmRsZXJzID0gY3JlYXRlRmlsZXN5c3RlbUhhbmRsZXJzKFxuICAgICAgb3B0cz8ucGF0aCA/PyBERUZBVUxUX1NUT1JBR0VfRElSXG4gICAgKTtcbiAgICBjb25zdCBhcHAgPSBuZXcgSG9ubygpO1xuXG4gICAgYXBwLnBvc3QoXCIvXCIsIGFzeW5jIChjKSA9PiB7XG4gICAgICBjb25zdCBib2R5ID0gYXdhaXQgYy5yZXEuanNvbigpO1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBoYW5kbGVTdG9yYWdlUnBjKGJvZHksIGhhbmRsZXJzKTtcbiAgICAgIHJldHVybiBjLmpzb24ocmVzcG9uc2UpO1xuICAgIH0pO1xuXG4gICAgY29uc3QgcG9ydCA9IG9wdHM/LnBvcnQgPz8gMDtcbiAgICBjb25zdCBzZXJ2ZXIgPSBzZXJ2ZSh7XG4gICAgICBmZXRjaDogYXBwLmZldGNoLFxuICAgICAgcG9ydCxcbiAgICB9KTtcblxuICAgIHNlcnZlci5vbihcImxpc3RlbmluZ1wiLCAoKSA9PiB7XG4gICAgICBjb25zdCBhZGRyZXNzID0gc2VydmVyLmFkZHJlc3MoKTtcbiAgICAgIGNvbnN0IGFjdHVhbFBvcnQgPSB0eXBlb2YgYWRkcmVzcyA9PT0gXCJvYmplY3RcIiA/IGFkZHJlc3M/LnBvcnQgOiBwb3J0O1xuICAgICAgY29uc3QgdXJsID0gYGh0dHA6Ly9sb2NhbGhvc3Q6JHthY3R1YWxQb3J0fWA7XG5cbiAgICAgIHNlcnZlckluc3RhbmNlID0geyB1cmwsIHNlcnZlciB9O1xuICAgICAgY29uc29sZS5sb2coYFthZ2VudF0gTG9jYWwgc3RvcmFnZSBzZXJ2ZXIgc3RhcnRlZCBhdCAke3VybH1gKTtcbiAgICAgIHJlc29sdmUodXJsKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgcmV0dXJuIHN0YXJ0UHJvbWlzZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHN0b3BMb2NhbFN0b3JhZ2UoKTogdm9pZCB7XG4gIGlmIChzZXJ2ZXJJbnN0YW5jZSkge1xuICAgIHNlcnZlckluc3RhbmNlLnNlcnZlci5jbG9zZSgpO1xuICAgIHNlcnZlckluc3RhbmNlID0gbnVsbDtcbiAgICBzdGFydFByb21pc2UgPSBudWxsO1xuICB9XG59XG5cbmlmICh0eXBlb2YgcHJvY2VzcyAhPT0gXCJ1bmRlZmluZWRcIikge1xuICBwcm9jZXNzLm9uKFwiU0lHVEVSTVwiLCBzdG9wTG9jYWxTdG9yYWdlKTtcbiAgcHJvY2Vzcy5vbihcIlNJR0lOVFwiLCBzdG9wTG9jYWxTdG9yYWdlKTtcbn1cbiIsICJjb25zdCBWRVJDRUxfU1RPUkFHRV9VUkwgPVxuICBcImh0dHBzOi8vYWdlbnQtc2RrLXN0b3JhZ2UtbmluZS5sYWJzLnZlcmNlbC5kZXYvYXBpL3N0b3JhZ2VcIjtcblxuZXhwb3J0IHR5cGUgVmVyY2VsU3RvcmFnZUNvbmZpZyA9IHtcbiAgdXJsOiBzdHJpbmc7XG4gIGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG59O1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0VmVyY2VsU3RvcmFnZUNvbmZpZygpOiBQcm9taXNlPFZlcmNlbFN0b3JhZ2VDb25maWc+IHtcbiAgbGV0IHRva2VuOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcblxuICB0cnkge1xuICAgIGNvbnN0IHsgZ2V0VmVyY2VsT2lkY1Rva2VuIH0gPSBhd2FpdCBpbXBvcnQoXCJAdmVyY2VsL29pZGNcIik7XG4gICAgdG9rZW4gPSBhd2FpdCBnZXRWZXJjZWxPaWRjVG9rZW4oKTtcbiAgfSBjYXRjaCB7XG4gICAgLy8gT0lEQyBub3QgYXZhaWxhYmxlIChsb2NhbCBkZXYsIG5vbi1WZXJjZWwgZW52aXJvbm1lbnQpXG4gIH1cblxuICByZXR1cm4ge1xuICAgIHVybDogVkVSQ0VMX1NUT1JBR0VfVVJMLFxuICAgIGhlYWRlcnM6IHRva2VuID8geyBBdXRob3JpemF0aW9uOiBgQmVhcmVyICR7dG9rZW59YCB9IDoge30sXG4gIH07XG59XG4iLCAiaW1wb3J0IHR5cGUgeyB6IH0gZnJvbSBcInpvZFwiO1xuaW1wb3J0IHtcbiAgTWVzc2FnZU5vdEZvdW5kRXJyb3IsXG4gIFNhbmRib3hOb3RGb3VuZEVycm9yLFxuICBTZXNzaW9uTm90Rm91bmRFcnJvcixcbiAgU3RvcmFnZUVycm9yLFxufSBmcm9tIFwiLi4vZXJyb3JzXCI7XG5pbXBvcnQgdHlwZSB7IFN0b3JhZ2VNZXRob2RzIH0gZnJvbSBcIi4vcnBjXCI7XG5pbXBvcnQgdHlwZSB7XG4gIENvbW1hbmQsXG4gIExpc3RSZXN1bHQsXG4gIFBhcnQsXG4gIFJlc29sdmVkU3RvcmFnZSxcbiAgU3RvcmFnZSxcbiAgU3RvcmFnZUNvbmZpZyxcbn0gZnJvbSBcIi4vdHlwZXNcIjtcblxudHlwZSBScGNSZXNwb25zZTxUPiA9XG4gIHwgeyByZXN1bHQ6IFQgfVxuICB8IHsgZXJyb3I6IHsgY29kZTogc3RyaW5nOyBtZXNzYWdlOiBzdHJpbmcgfSB9O1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0U3RvcmFnZUNsaWVudCh7IHVybCwgaGVhZGVycyB9OiBSZXNvbHZlZFN0b3JhZ2UpOiBTdG9yYWdlIHtcbiAgYXN5bmMgZnVuY3Rpb24gcnBjPE0gZXh0ZW5kcyBrZXlvZiBTdG9yYWdlTWV0aG9kcz4oXG4gICAgbWV0aG9kOiBNLFxuICAgIHBhcmFtczogei5pbmZlcjxTdG9yYWdlTWV0aG9kc1tNXVtcInBhcmFtc1wiXT5cbiAgKTogUHJvbWlzZTx6LmluZmVyPFN0b3JhZ2VNZXRob2RzW01dW1wicmVzdWx0XCJdPj4ge1xuICAgIGNvbnN0IHJlcyA9IGF3YWl0IGZldGNoKHVybCwge1xuICAgICAgbWV0aG9kOiBcIlBPU1RcIixcbiAgICAgIGhlYWRlcnM6IHsgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIsIC4uLmhlYWRlcnMgfSxcbiAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHsgbWV0aG9kLCBwYXJhbXMgfSksXG4gICAgfSk7XG5cbiAgICBpZiAoIXJlcy5vaykge1xuICAgICAgdGhyb3cgbmV3IFN0b3JhZ2VFcnJvcih7XG4gICAgICAgIHJlYXNvbjogYEhUVFAgJHtyZXMuc3RhdHVzfTogJHtyZXMuc3RhdHVzVGV4dH1gLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgY29uc3QganNvbiA9IChhd2FpdCByZXMuanNvbigpKSBhcyBScGNSZXNwb25zZTxcbiAgICAgIHouaW5mZXI8U3RvcmFnZU1ldGhvZHNbTV1bXCJyZXN1bHRcIl0+XG4gICAgPjtcblxuICAgIGlmIChcImVycm9yXCIgaW4ganNvbikge1xuICAgICAgdGhyb3cgbmV3IFN0b3JhZ2VFcnJvcih7IHJlYXNvbjoganNvbi5lcnJvci5tZXNzYWdlIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBqc29uLnJlc3VsdDtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgc2Vzc2lvbjoge1xuICAgICAgZ2V0OiBhc3luYyAoaWQpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBycGMoXCJzZXNzaW9uLmdldFwiLCB7IGlkIH0pO1xuICAgICAgICAgIGlmIChyZXN1bHQgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgU2Vzc2lvbk5vdEZvdW5kRXJyb3IoeyBpZCB9KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGlmIChlIGluc3RhbmNlb2YgU3RvcmFnZUVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG5ldyBTdG9yYWdlRXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBzZXQ6IGFzeW5jIChzZXNzaW9uKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmV0dXJuIGF3YWl0IHJwYyhcInNlc3Npb24uc2V0XCIsIHNlc3Npb24pO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiBTdG9yYWdlRXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybiBlO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gbmV3IFN0b3JhZ2VFcnJvcih7IHJlYXNvbjogU3RyaW5nKGUpLCBjYXVzZTogZSB9KTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIGxpc3Q6IGFzeW5jIChvcHRzKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmV0dXJuIGF3YWl0IHJwYyhcInNlc3Npb24ubGlzdFwiLCB7XG4gICAgICAgICAgICB0YWdzOiBvcHRzPy50YWdzLFxuICAgICAgICAgICAgb3JkZXI6IG9wdHM/Lm9yZGVyLFxuICAgICAgICAgICAgY3Vyc29yOiBvcHRzPy5jdXJzb3IsXG4gICAgICAgICAgICBsaW1pdDogb3B0cz8ubGltaXQsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIFN0b3JhZ2VFcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIGU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBuZXcgU3RvcmFnZUVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgdGFnOiB7XG4gICAgICAgIHNldDogYXN5bmMgKHsgc2Vzc2lvbklkLCB0YWdzIH0pID0+IHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHJwYyhcInNlc3Npb24udGFnLnNldFwiLCB7IHNlc3Npb25JZCwgdGFncyB9KTtcbiAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIFN0b3JhZ2VFcnJvcikge1xuICAgICAgICAgICAgICByZXR1cm4gZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuZXcgU3RvcmFnZUVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBtZXNzYWdlOiB7XG4gICAgICBsaXN0OiBhc3luYyAoc2Vzc2lvbklkLCBvcHRzKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmV0dXJuIGF3YWl0IHJwYyhcIm1lc3NhZ2UubGlzdFwiLCB7XG4gICAgICAgICAgICBzZXNzaW9uSWQsXG4gICAgICAgICAgICBjdXJzb3I6IG9wdHM/LmN1cnNvcixcbiAgICAgICAgICAgIGxpbWl0OiBvcHRzPy5saW1pdCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGlmIChlIGluc3RhbmNlb2YgU3RvcmFnZUVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG5ldyBTdG9yYWdlRXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBnZXQ6IGFzeW5jIChpZCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHJwYyhcIm1lc3NhZ2UuZ2V0XCIsIHsgaWQgfSk7XG4gICAgICAgICAgaWYgKHJlc3VsdCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBNZXNzYWdlTm90Rm91bmRFcnJvcih7IGlkIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiBTdG9yYWdlRXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybiBlO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gbmV3IFN0b3JhZ2VFcnJvcih7IHJlYXNvbjogU3RyaW5nKGUpLCBjYXVzZTogZSB9KTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIHNldDogYXN5bmMgKG1lc3NhZ2UpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXR1cm4gYXdhaXQgcnBjKFwibWVzc2FnZS5zZXRcIiwgbWVzc2FnZSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIFN0b3JhZ2VFcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIGU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBuZXcgU3RvcmFnZUVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgIH0sXG4gICAgcGFydDoge1xuICAgICAgbGlzdEJ5TWVzc2FnZTogYXN5bmMgKG1lc3NhZ2VJZCwgb3B0cykgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHJwYyhcInBhcnQubGlzdEJ5TWVzc2FnZVwiLCB7XG4gICAgICAgICAgICBtZXNzYWdlSWQsXG4gICAgICAgICAgICBjdXJzb3I6IG9wdHM/LmN1cnNvcixcbiAgICAgICAgICAgIGxpbWl0OiBvcHRzPy5saW1pdCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXR1cm4gcmVzdWx0IGFzIExpc3RSZXN1bHQ8UGFydD47XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIFN0b3JhZ2VFcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIGU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBuZXcgU3RvcmFnZUVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgbGlzdEJ5U2Vzc2lvbjogYXN5bmMgKHNlc3Npb25JZCwgb3B0cykgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHJwYyhcInBhcnQubGlzdEJ5U2Vzc2lvblwiLCB7XG4gICAgICAgICAgICBzZXNzaW9uSWQsXG4gICAgICAgICAgICBjdXJzb3I6IG9wdHM/LmN1cnNvcixcbiAgICAgICAgICAgIGxpbWl0OiBvcHRzPy5saW1pdCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXR1cm4gcmVzdWx0IGFzIExpc3RSZXN1bHQ8UGFydD47XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIFN0b3JhZ2VFcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIGU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBuZXcgU3RvcmFnZUVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgc2V0OiBhc3luYyAocGFydCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIHJldHVybiAoYXdhaXQgcnBjKFwicGFydC5zZXRcIiwgcGFydCkpIGFzIFBhcnQ7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIFN0b3JhZ2VFcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIGU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBuZXcgU3RvcmFnZUVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgIH0sXG4gICAgc2FuZGJveDoge1xuICAgICAgZ2V0OiBhc3luYyAoa2V5KSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcnBjKFwic2FuZGJveC5nZXRcIiwgeyBrZXkgfSk7XG4gICAgICAgICAgaWYgKHJlc3VsdCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBTYW5kYm94Tm90Rm91bmRFcnJvcih7IGlkOiBrZXkgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIFN0b3JhZ2VFcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIGU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBuZXcgU3RvcmFnZUVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgZ2V0QnlTZXNzaW9uOiBhc3luYyAoc2Vzc2lvbklkKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcnBjKFwic2FuZGJveC5nZXRCeVNlc3Npb25cIiwgeyBzZXNzaW9uSWQgfSk7XG4gICAgICAgICAgaWYgKHJlc3VsdCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBTYW5kYm94Tm90Rm91bmRFcnJvcih7IGlkOiBzZXNzaW9uSWQgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIFN0b3JhZ2VFcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIGU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBuZXcgU3RvcmFnZUVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgc2V0OiBhc3luYyAocmVjb3JkKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYXdhaXQgcnBjKFwic2FuZGJveC5zZXRcIiwgcmVjb3JkKTtcbiAgICAgICAgICByZXR1cm4gcmVjb3JkO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiBTdG9yYWdlRXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybiBlO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gbmV3IFN0b3JhZ2VFcnJvcih7IHJlYXNvbjogU3RyaW5nKGUpLCBjYXVzZTogZSB9KTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICB9LFxuICAgIGNvbW1hbmQ6IHtcbiAgICAgIGdldDogYXN5bmMgKGlkKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmV0dXJuIChhd2FpdCBycGMoXCJjb21tYW5kLmdldFwiLCB7IGlkIH0pKSBhcyBDb21tYW5kIHwgbnVsbDtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGlmIChlIGluc3RhbmNlb2YgU3RvcmFnZUVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG5ldyBTdG9yYWdlRXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBzZXQ6IGFzeW5jIChjb21tYW5kKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmV0dXJuIChhd2FpdCBycGMoXCJjb21tYW5kLnNldFwiLCBjb21tYW5kKSkgYXMgQ29tbWFuZDtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGlmIChlIGluc3RhbmNlb2YgU3RvcmFnZUVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG5ldyBTdG9yYWdlRXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBsaXN0OiBhc3luYyAoc2Vzc2lvbklkLCBvcHRzKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcnBjKFwiY29tbWFuZC5saXN0XCIsIHtcbiAgICAgICAgICAgIHNlc3Npb25JZCxcbiAgICAgICAgICAgIGluY2x1ZGVGaW5pc2hlZDogb3B0cz8uaW5jbHVkZUZpbmlzaGVkLFxuICAgICAgICAgICAgY3Vyc29yOiBvcHRzPy5jdXJzb3IsXG4gICAgICAgICAgICBsaW1pdDogb3B0cz8ubGltaXQsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdCBhcyBMaXN0UmVzdWx0PENvbW1hbmQ+O1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiBTdG9yYWdlRXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybiBlO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gbmV3IFN0b3JhZ2VFcnJvcih7IHJlYXNvbjogU3RyaW5nKGUpLCBjYXVzZTogZSB9KTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICB9LFxuICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiByZXNvbHZlU3RvcmFnZVVybChcbiAgY29uZmlnOiBTdG9yYWdlQ29uZmlnXG4pOiBQcm9taXNlPFJlc29sdmVkU3RvcmFnZT4ge1xuICBzd2l0Y2ggKGNvbmZpZy50eXBlKSB7XG4gICAgY2FzZSBcImxvY2FsXCI6IHtcbiAgICAgIGNvbnN0IHsgc3RhcnRMb2NhbFN0b3JhZ2UgfSA9IGF3YWl0IGltcG9ydChcIi4vYmluZGluZ3MvbG9jYWxcIik7XG4gICAgICByZXR1cm4geyB1cmw6IGF3YWl0IHN0YXJ0TG9jYWxTdG9yYWdlKHsgcGF0aDogY29uZmlnLnBhdGggfSkgfTtcbiAgICB9XG4gICAgY2FzZSBcInZlcmNlbFwiOiB7XG4gICAgICBjb25zdCB7IGdldFZlcmNlbFN0b3JhZ2VDb25maWcgfSA9IGF3YWl0IGltcG9ydChcIi4vYmluZGluZ3MvdmVyY2VsXCIpO1xuICAgICAgcmV0dXJuIGdldFZlcmNlbFN0b3JhZ2VDb25maWcoKTtcbiAgICB9XG4gICAgY2FzZSBcImN1c3RvbVwiOiB7XG4gICAgICByZXR1cm4geyB1cmw6IGNvbmZpZy51cmwsIGhlYWRlcnM6IGNvbmZpZy5oZWFkZXJzIH07XG4gICAgfVxuICAgIGRlZmF1bHQ6IHtcbiAgICAgIGNvbmZpZyBzYXRpc2ZpZXMgbmV2ZXI7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBVbmtub3duIHN0b3JhZ2UgdHlwZTogJHsoY29uZmlnIGFzIHsgdHlwZTogc3RyaW5nIH0pLnR5cGV9YFxuICAgICAgKTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFN0b3JhZ2Uoc3RvcmFnZUNvbmZpZzogU3RvcmFnZUNvbmZpZyk6IFN0b3JhZ2Uge1xuICBsZXQgY2xpZW50UHJvbWlzZTogUHJvbWlzZTxTdG9yYWdlPiB8IG51bGwgPSBudWxsO1xuICBjb25zdCBnZXRDbGllbnQgPSAoKSA9PiB7XG4gICAgaWYgKCFjbGllbnRQcm9taXNlKSB7XG4gICAgICBjbGllbnRQcm9taXNlID0gcmVzb2x2ZVN0b3JhZ2VVcmwoc3RvcmFnZUNvbmZpZykudGhlbigocmVzb2x2ZWQpID0+XG4gICAgICAgIGdldFN0b3JhZ2VDbGllbnQocmVzb2x2ZWQpXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gY2xpZW50UHJvbWlzZTtcbiAgfTtcblxuICByZXR1cm4ge1xuICAgIHNlc3Npb246IHtcbiAgICAgIGdldDogYXN5bmMgKGlkKSA9PiAoYXdhaXQgZ2V0Q2xpZW50KCkpLnNlc3Npb24uZ2V0KGlkKSxcbiAgICAgIHNldDogYXN5bmMgKHNlc3Npb24pID0+IChhd2FpdCBnZXRDbGllbnQoKSkuc2Vzc2lvbi5zZXQoc2Vzc2lvbiksXG4gICAgICBsaXN0OiBhc3luYyAob3B0cykgPT4gKGF3YWl0IGdldENsaWVudCgpKS5zZXNzaW9uLmxpc3Qob3B0cyksXG4gICAgICB0YWc6IHtcbiAgICAgICAgc2V0OiBhc3luYyAob3B0cykgPT4gKGF3YWl0IGdldENsaWVudCgpKS5zZXNzaW9uLnRhZy5zZXQob3B0cyksXG4gICAgICB9LFxuICAgIH0sXG4gICAgbWVzc2FnZToge1xuICAgICAgbGlzdDogYXN5bmMgKHNlc3Npb25JZCwgb3B0cykgPT5cbiAgICAgICAgKGF3YWl0IGdldENsaWVudCgpKS5tZXNzYWdlLmxpc3Qoc2Vzc2lvbklkLCBvcHRzKSxcbiAgICAgIGdldDogYXN5bmMgKGlkKSA9PiAoYXdhaXQgZ2V0Q2xpZW50KCkpLm1lc3NhZ2UuZ2V0KGlkKSxcbiAgICAgIHNldDogYXN5bmMgKG1lc3NhZ2UpID0+IChhd2FpdCBnZXRDbGllbnQoKSkubWVzc2FnZS5zZXQobWVzc2FnZSksXG4gICAgfSxcbiAgICBwYXJ0OiB7XG4gICAgICBsaXN0QnlNZXNzYWdlOiBhc3luYyAobWVzc2FnZUlkLCBvcHRzKSA9PlxuICAgICAgICAoYXdhaXQgZ2V0Q2xpZW50KCkpLnBhcnQubGlzdEJ5TWVzc2FnZShtZXNzYWdlSWQsIG9wdHMpLFxuICAgICAgbGlzdEJ5U2Vzc2lvbjogYXN5bmMgKHNlc3Npb25JZCwgb3B0cykgPT5cbiAgICAgICAgKGF3YWl0IGdldENsaWVudCgpKS5wYXJ0Lmxpc3RCeVNlc3Npb24oc2Vzc2lvbklkLCBvcHRzKSxcbiAgICAgIHNldDogYXN5bmMgKHBhcnQpID0+IChhd2FpdCBnZXRDbGllbnQoKSkucGFydC5zZXQocGFydCksXG4gICAgfSxcbiAgICBzYW5kYm94OiB7XG4gICAgICBnZXQ6IGFzeW5jIChrZXkpID0+IChhd2FpdCBnZXRDbGllbnQoKSkuc2FuZGJveC5nZXQoa2V5KSxcbiAgICAgIHNldDogYXN5bmMgKG9wdHMpID0+IChhd2FpdCBnZXRDbGllbnQoKSkuc2FuZGJveC5zZXQob3B0cyksXG4gICAgICBnZXRCeVNlc3Npb246IGFzeW5jIChzZXNzaW9uSWQpID0+XG4gICAgICAgIChhd2FpdCBnZXRDbGllbnQoKSkuc2FuZGJveC5nZXRCeVNlc3Npb24oc2Vzc2lvbklkKSxcbiAgICB9LFxuICAgIGNvbW1hbmQ6IHtcbiAgICAgIGdldDogYXN5bmMgKGlkKSA9PiAoYXdhaXQgZ2V0Q2xpZW50KCkpLmNvbW1hbmQuZ2V0KGlkKSxcbiAgICAgIHNldDogYXN5bmMgKGNvbW1hbmQpID0+IChhd2FpdCBnZXRDbGllbnQoKSkuY29tbWFuZC5zZXQoY29tbWFuZCksXG4gICAgICBsaXN0OiBhc3luYyAoc2Vzc2lvbklkLCBvcHRzKSA9PlxuICAgICAgICAoYXdhaXQgZ2V0Q2xpZW50KCkpLmNvbW1hbmQubGlzdChzZXNzaW9uSWQsIG9wdHMpLFxuICAgIH0sXG4gIH07XG59XG4iLCAiaW1wb3J0IHsgeiB9IGZyb20gXCJ6b2RcIjtcblxuY29uc3QgVmVyY2VsTGlmZWN5Y2xlQ29uZmlnU2NoZW1hID0gei5vYmplY3Qoe1xuICBzdG9wQWZ0ZXJJbmFjdGl2ZU1zOiB6Lm51bWJlcigpLm9wdGlvbmFsKCksXG4gIHNuYXBzaG90QmVmb3JlVGltZW91dE1zOiB6Lm51bWJlcigpLm9wdGlvbmFsKCksXG4gIHNuYXBzaG90SWQ6IHouc3RyaW5nKCkub3B0aW9uYWwoKSxcbiAgYXV0b1N0YXJ0OiB6LmJvb2xlYW4oKS5vcHRpb25hbCgpLFxufSk7XG5cbmV4cG9ydCBjb25zdCBTYW5kYm94Q29uZmlnU2NoZW1hID0gei5kaXNjcmltaW5hdGVkVW5pb24oXCJ0eXBlXCIsIFtcbiAgei5vYmplY3Qoe1xuICAgIHR5cGU6IHoubGl0ZXJhbChcInZlcmNlbFwiKSxcbiAgICByZXNvdXJjZXM6IHoub2JqZWN0KHsgdmNwdXM6IHoubnVtYmVyKCkgfSkub3B0aW9uYWwoKSxcbiAgICBwb3J0czogei5hcnJheSh6Lm51bWJlcigpKS5vcHRpb25hbCgpLFxuICAgIGxpZmVjeWNsZTogVmVyY2VsTGlmZWN5Y2xlQ29uZmlnU2NoZW1hLm9wdGlvbmFsKCksXG4gIH0pLFxuICB6Lm9iamVjdCh7XG4gICAgdHlwZTogei5saXRlcmFsKFwibG9jYWxcIiksXG4gICAgcGF0aDogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuICB9KSxcbiAgei5vYmplY3Qoe1xuICAgIHR5cGU6IHoubGl0ZXJhbChcImN1c3RvbVwiKSxcbiAgICB1cmw6IHouc3RyaW5nKCksXG4gICAgaGVhZGVyczogei5yZWNvcmQoei5zdHJpbmcoKSwgei5zdHJpbmcoKSkub3B0aW9uYWwoKSxcbiAgfSksXG5dKTtcblxuZXhwb3J0IHR5cGUgU2FuZGJveENvbmZpZyA9IHouaW5mZXI8dHlwZW9mIFNhbmRib3hDb25maWdTY2hlbWE+O1xuXG5leHBvcnQgY29uc3QgU2Vzc2lvblNjaGVtYSA9IHoub2JqZWN0KHtcbiAgaWQ6IHouc3RyaW5nKCksXG4gIGNyZWF0ZWRBdDogei5udW1iZXIoKSxcbiAgdXBkYXRlZEF0OiB6Lm51bWJlcigpLFxuICBydW5JZDogei5zdHJpbmcoKS5udWxsYWJsZSgpLFxuICBsYXN0TWVzc2FnZUlkOiB6LnN0cmluZygpLm51bGxhYmxlKCksXG4gIHRhZ3M6IHoucmVjb3JkKHouc3RyaW5nKCksIHoudW5rbm93bigpKS5udWxsYWJsZSgpLFxuICBpbnN0cnVjdGlvbnM6IHouc3RyaW5nKCkubnVsbGFibGUoKSxcbiAgbW9kZWw6IHouc3RyaW5nKCkubnVsbGFibGUoKSxcbiAgbWNwOiB6LnVua25vd24oKS5udWxsYWJsZSgpLCAvLyBUT0RPXG4gIHNhbmRib3hJZDogei5zdHJpbmcoKS5udWxsYWJsZSgpLFxuICBza2lsbHNEaXI6IHouYXJyYXkoei5zdHJpbmcoKSkubnVsbGFibGUoKSxcbiAgaG9va1Rva2VuOiB6LnN0cmluZygpLm51bGxhYmxlKCksXG59KTtcblxuZXhwb3J0IGNvbnN0IE1lc3NhZ2VTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIGlkOiB6LnN0cmluZygpLFxuICBzZXNzaW9uSWQ6IHouc3RyaW5nKCksXG4gIHJvbGU6IHouZW51bShbXCJ1c2VyXCIsIFwiYXNzaXN0YW50XCIsIFwic3lzdGVtXCJdKSxcbiAgY3JlYXRlZEF0OiB6Lm51bWJlcigpLFxuICBjb21wbGV0ZWRBdDogei5udW1iZXIoKS5udWxsYWJsZSgpLFxuICBtY3BDb250ZXh0OiB6LnVua25vd24oKS5udWxsYWJsZSgpLFxufSk7XG5cbi8qKlxuICogVGhlIGBwYXJ0YCBmaWVsZCBjb3JyZXNwb25kcyB0byBgVUlNZXNzYWdlW1wicGFydHNcIl1bbnVtYmVyXWAgZnJvbSB0aGUgYGFpYCBwYWNrYWdlLlxuICogV2UgdXNlIGB6LnVua25vd24oKWAgYmVjYXVzZSB0aGUgZXhhY3Qgc2hhcGUgdmFyaWVzIGJ5IHBhcnQgdHlwZSAodGV4dCwgdG9vbC1jYWxsLFxuICogdG9vbC1yZXN1bHQsIGV0Yy4pIGFuZCBtYXkgZXZvbHZlIHdpdGggdGhlIEFJIFNESy4gVGhlIFJQQyBsYXllciBqdXN0IHBhc3NlcyBpdCB0aHJvdWdoLlxuICovXG5leHBvcnQgY29uc3QgUGFydFNjaGVtYSA9IHoub2JqZWN0KHtcbiAgaWQ6IHouc3RyaW5nKCksXG4gIG1lc3NhZ2VJZDogei5zdHJpbmcoKSxcbiAgc2Vzc2lvbklkOiB6LnN0cmluZygpLFxuICBpbmRleDogei5udW1iZXIoKSxcbiAgcGFydDogei51bmtub3duKCksXG59KTtcblxuZXhwb3J0IGNvbnN0IENvbW1hbmRSZXN1bHRTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIHN0ZG91dDogei5zdHJpbmcoKSxcbiAgc3RkZXJyOiB6LnN0cmluZygpLFxuICBleGl0Q29kZTogei5udW1iZXIoKSxcbiAgY29tcGxldGVkQXQ6IHoubnVtYmVyKCksXG59KTtcblxuZXhwb3J0IGNvbnN0IFNhbmRib3hSZWNvcmRTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIGlkOiB6LnN0cmluZygpLFxuICBjb25maWc6IFNhbmRib3hDb25maWdTY2hlbWEsXG4gIGNyZWF0ZWRBdDogei5udW1iZXIoKS5udWxsYWJsZSgpLFxuICBsYXN0QWN0aXZpdHlBdDogei5udW1iZXIoKS5udWxsYWJsZSgpLFxuICBhY3F1aXJpbmdMb2NrSWQ6IHouc3RyaW5nKCkubnVsbGFibGUoKSxcbiAgYWNxdWlyaW5nTG9ja0F0OiB6Lm51bWJlcigpLm51bGxhYmxlKCksXG4gIHByb3ZpZGVyTWV0YWRhdGE6IHpcbiAgICAuZGlzY3JpbWluYXRlZFVuaW9uKFwicHJvdmlkZXJcIiwgW1xuICAgICAgei5vYmplY3Qoe1xuICAgICAgICBwcm92aWRlcjogei5saXRlcmFsKFwidmVyY2VsXCIpLFxuICAgICAgICBzYW5kYm94SWQ6IHouc3RyaW5nKCkubnVsbGFibGUoKSxcbiAgICAgICAgc25hcHNob3RJZDogei5zdHJpbmcoKS5udWxsYWJsZSgpLFxuICAgICAgfSksXG4gICAgXSlcbiAgICAub3B0aW9uYWwoKSxcbn0pO1xuXG5jb25zdCBDb21tYW5kQmFzZVNjaGVtYSA9IHoub2JqZWN0KHtcbiAgaWQ6IHouc3RyaW5nKCksXG4gIHNlc3Npb25JZDogei5zdHJpbmcoKSxcbiAgY29tbWFuZDogei5zdHJpbmcoKSxcbiAgYXJnczogei5hcnJheSh6LnN0cmluZygpKS5vcHRpb25hbCgpLFxuICBzdGFydGVkQXQ6IHoubnVtYmVyKCksXG59KTtcblxuZXhwb3J0IGNvbnN0IENvbW1hbmRTY2hlbWEgPSB6LmRpc2NyaW1pbmF0ZWRVbmlvbihcInN0YXR1c1wiLCBbXG4gIENvbW1hbmRCYXNlU2NoZW1hLmV4dGVuZCh7IHN0YXR1czogei5saXRlcmFsKFwicnVubmluZ1wiKSB9KSxcbiAgQ29tbWFuZEJhc2VTY2hlbWEuZXh0ZW5kKHtcbiAgICBzdGF0dXM6IHoubGl0ZXJhbChcImNvbXBsZXRlZFwiKSxcbiAgICByZXN1bHQ6IENvbW1hbmRSZXN1bHRTY2hlbWEsXG4gIH0pLFxuICBDb21tYW5kQmFzZVNjaGVtYS5leHRlbmQoe1xuICAgIHN0YXR1czogei5saXRlcmFsKFwia2lsbGVkXCIpLFxuICAgIHJlc3VsdDogQ29tbWFuZFJlc3VsdFNjaGVtYS5vcHRpb25hbCgpLFxuICB9KSxcbiAgQ29tbWFuZEJhc2VTY2hlbWEuZXh0ZW5kKHtcbiAgICBzdGF0dXM6IHoubGl0ZXJhbChcImZhaWxlZFwiKSxcbiAgICByZXN1bHQ6IENvbW1hbmRSZXN1bHRTY2hlbWEsXG4gIH0pLFxuXSk7XG5cbmZ1bmN0aW9uIExpc3RSZXN1bHRTY2hlbWE8VCBleHRlbmRzIHouWm9kVHlwZUFueT4oaXRlbVNjaGVtYTogVCkge1xuICByZXR1cm4gei5vYmplY3Qoe1xuICAgIGl0ZW1zOiB6LmFycmF5KGl0ZW1TY2hlbWEpLFxuICAgIG5leHRDdXJzb3I6IHouc3RyaW5nKCkubnVsbGFibGUoKSxcbiAgfSk7XG59XG5cbmV4cG9ydCBjb25zdCBtZXRob2RzID0ge1xuICBcInNlc3Npb24uZ2V0XCI6IHtcbiAgICBwYXJhbXM6IHoub2JqZWN0KHsgaWQ6IHouc3RyaW5nKCkgfSksXG4gICAgcmVzdWx0OiBTZXNzaW9uU2NoZW1hLm51bGxhYmxlKCksXG4gIH0sXG4gIFwic2Vzc2lvbi5zZXRcIjoge1xuICAgIHBhcmFtczogU2Vzc2lvblNjaGVtYSxcbiAgICByZXN1bHQ6IFNlc3Npb25TY2hlbWEsXG4gIH0sXG4gIFwic2Vzc2lvbi5saXN0XCI6IHtcbiAgICBwYXJhbXM6IHoub2JqZWN0KHtcbiAgICAgIHRhZ3M6IHoucmVjb3JkKHouc3RyaW5nKCksIHoudW5rbm93bigpKS5vcHRpb25hbCgpLFxuICAgICAgb3JkZXI6IHpcbiAgICAgICAgLmVudW0oW1xuICAgICAgICAgIFwiY3JlYXRlZEF0X2FzY1wiLFxuICAgICAgICAgIFwiY3JlYXRlZEF0X2Rlc2NcIixcbiAgICAgICAgICBcInVwZGF0ZWRBdF9hc2NcIixcbiAgICAgICAgICBcInVwZGF0ZWRBdF9kZXNjXCIsXG4gICAgICAgIF0pXG4gICAgICAgIC5vcHRpb25hbCgpLFxuICAgICAgY3Vyc29yOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG4gICAgICBsaW1pdDogei5udW1iZXIoKS5vcHRpb25hbCgpLFxuICAgIH0pLFxuICAgIHJlc3VsdDogTGlzdFJlc3VsdFNjaGVtYShTZXNzaW9uU2NoZW1hKSxcbiAgfSxcbiAgXCJzZXNzaW9uLmxpc3RCeVNhbmRib3hcIjoge1xuICAgIHBhcmFtczogei5vYmplY3Qoe1xuICAgICAgc2FuZGJveElkOiB6LnN0cmluZygpLFxuICAgICAgdGFnczogei5yZWNvcmQoei5zdHJpbmcoKSwgei51bmtub3duKCkpLm9wdGlvbmFsKCksXG4gICAgICBvcmRlcjogelxuICAgICAgICAuZW51bShbXG4gICAgICAgICAgXCJjcmVhdGVkQXRfYXNjXCIsXG4gICAgICAgICAgXCJjcmVhdGVkQXRfZGVzY1wiLFxuICAgICAgICAgIFwidXBkYXRlZEF0X2FzY1wiLFxuICAgICAgICAgIFwidXBkYXRlZEF0X2Rlc2NcIixcbiAgICAgICAgXSlcbiAgICAgICAgLm9wdGlvbmFsKCksXG4gICAgICBjdXJzb3I6IHouc3RyaW5nKCkub3B0aW9uYWwoKSxcbiAgICAgIGxpbWl0OiB6Lm51bWJlcigpLm9wdGlvbmFsKCksXG4gICAgfSksXG4gICAgcmVzdWx0OiBMaXN0UmVzdWx0U2NoZW1hKFNlc3Npb25TY2hlbWEpLFxuICB9LFxuICBcInNlc3Npb24udGFnLnNldFwiOiB7XG4gICAgcGFyYW1zOiB6Lm9iamVjdCh7XG4gICAgICBzZXNzaW9uSWQ6IHouc3RyaW5nKCksXG4gICAgICB0YWdzOiB6LnJlY29yZCh6LnN0cmluZygpLCB6LnVua25vd24oKSksXG4gICAgfSksXG4gICAgcmVzdWx0OiBTZXNzaW9uU2NoZW1hLFxuICB9LFxuICBcIm1lc3NhZ2UuZ2V0XCI6IHtcbiAgICBwYXJhbXM6IHoub2JqZWN0KHsgaWQ6IHouc3RyaW5nKCkgfSksXG4gICAgcmVzdWx0OiBNZXNzYWdlU2NoZW1hLm51bGxhYmxlKCksXG4gIH0sXG4gIFwibWVzc2FnZS5zZXRcIjoge1xuICAgIHBhcmFtczogTWVzc2FnZVNjaGVtYSxcbiAgICByZXN1bHQ6IE1lc3NhZ2VTY2hlbWEsXG4gIH0sXG4gIFwibWVzc2FnZS5saXN0XCI6IHtcbiAgICBwYXJhbXM6IHoub2JqZWN0KHtcbiAgICAgIHNlc3Npb25JZDogei5zdHJpbmcoKSxcbiAgICAgIGN1cnNvcjogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuICAgICAgbGltaXQ6IHoubnVtYmVyKCkub3B0aW9uYWwoKSxcbiAgICB9KSxcbiAgICByZXN1bHQ6IExpc3RSZXN1bHRTY2hlbWEoTWVzc2FnZVNjaGVtYSksXG4gIH0sXG4gIFwicGFydC5saXN0QnlNZXNzYWdlXCI6IHtcbiAgICBwYXJhbXM6IHoub2JqZWN0KHtcbiAgICAgIG1lc3NhZ2VJZDogei5zdHJpbmcoKSxcbiAgICAgIGN1cnNvcjogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuICAgICAgbGltaXQ6IHoubnVtYmVyKCkub3B0aW9uYWwoKSxcbiAgICB9KSxcbiAgICByZXN1bHQ6IExpc3RSZXN1bHRTY2hlbWEoUGFydFNjaGVtYSksXG4gIH0sXG4gIFwicGFydC5saXN0QnlTZXNzaW9uXCI6IHtcbiAgICBwYXJhbXM6IHoub2JqZWN0KHtcbiAgICAgIHNlc3Npb25JZDogei5zdHJpbmcoKSxcbiAgICAgIGN1cnNvcjogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuICAgICAgbGltaXQ6IHoubnVtYmVyKCkub3B0aW9uYWwoKSxcbiAgICB9KSxcbiAgICByZXN1bHQ6IExpc3RSZXN1bHRTY2hlbWEoUGFydFNjaGVtYSksXG4gIH0sXG4gIFwicGFydC5zZXRcIjoge1xuICAgIHBhcmFtczogUGFydFNjaGVtYSxcbiAgICByZXN1bHQ6IFBhcnRTY2hlbWEsXG4gIH0sXG4gIFwic2FuZGJveC5nZXRcIjoge1xuICAgIHBhcmFtczogei5vYmplY3QoeyBrZXk6IHouc3RyaW5nKCkgfSksXG4gICAgcmVzdWx0OiBTYW5kYm94UmVjb3JkU2NoZW1hLm51bGxhYmxlKCksXG4gIH0sXG4gIFwic2FuZGJveC5nZXRCeVNlc3Npb25cIjoge1xuICAgIHBhcmFtczogei5vYmplY3QoeyBzZXNzaW9uSWQ6IHouc3RyaW5nKCkgfSksXG4gICAgcmVzdWx0OiBTYW5kYm94UmVjb3JkU2NoZW1hLm51bGxhYmxlKCksXG4gIH0sXG4gIFwic2FuZGJveC5zZXRcIjoge1xuICAgIHBhcmFtczogU2FuZGJveFJlY29yZFNjaGVtYSxcbiAgICByZXN1bHQ6IHoudm9pZCgpLFxuICB9LFxuICBcImNvbW1hbmQuZ2V0XCI6IHtcbiAgICBwYXJhbXM6IHoub2JqZWN0KHsgaWQ6IHouc3RyaW5nKCkgfSksXG4gICAgcmVzdWx0OiBDb21tYW5kU2NoZW1hLm51bGxhYmxlKCksXG4gIH0sXG4gIFwiY29tbWFuZC5zZXRcIjoge1xuICAgIHBhcmFtczogQ29tbWFuZFNjaGVtYSxcbiAgICByZXN1bHQ6IENvbW1hbmRTY2hlbWEsXG4gIH0sXG4gIFwiY29tbWFuZC5saXN0XCI6IHtcbiAgICBwYXJhbXM6IHoub2JqZWN0KHtcbiAgICAgIHNlc3Npb25JZDogei5zdHJpbmcoKSxcbiAgICAgIGluY2x1ZGVGaW5pc2hlZDogei5ib29sZWFuKCkub3B0aW9uYWwoKSxcbiAgICAgIGN1cnNvcjogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuICAgICAgbGltaXQ6IHoubnVtYmVyKCkub3B0aW9uYWwoKSxcbiAgICB9KSxcbiAgICByZXN1bHQ6IExpc3RSZXN1bHRTY2hlbWEoQ29tbWFuZFNjaGVtYSksXG4gIH0sXG59IGFzIGNvbnN0O1xuXG5leHBvcnQgdHlwZSBTdG9yYWdlTWV0aG9kcyA9IHR5cGVvZiBtZXRob2RzO1xuZXhwb3J0IHR5cGUgTWV0aG9kTmFtZSA9IGtleW9mIFN0b3JhZ2VNZXRob2RzO1xuIiwgImltcG9ydCB0eXBlIHsgeiB9IGZyb20gXCJ6b2RcIjtcbmltcG9ydCB7IHR5cGUgTWV0aG9kTmFtZSwgbWV0aG9kcywgdHlwZSBTdG9yYWdlTWV0aG9kcyB9IGZyb20gXCIuL3JwY1wiO1xuXG5leHBvcnQgdHlwZSBIYW5kbGVycyA9IHtcbiAgW0sgaW4gTWV0aG9kTmFtZV06IChcbiAgICBwYXJhbXM6IHouaW5mZXI8U3RvcmFnZU1ldGhvZHNbS11bXCJwYXJhbXNcIl0+XG4gICkgPT4gUHJvbWlzZTx6LmluZmVyPFN0b3JhZ2VNZXRob2RzW0tdW1wicmVzdWx0XCJdPj47XG59O1xuXG5leHBvcnQgdHlwZSBScGNSZXF1ZXN0ID0ge1xuICBtZXRob2Q6IHN0cmluZztcbiAgcGFyYW1zOiB1bmtub3duO1xufTtcblxuZXhwb3J0IHR5cGUgUnBjU3VjY2Vzc1Jlc3BvbnNlPFQgPSB1bmtub3duPiA9IHtcbiAgcmVzdWx0OiBUO1xufTtcblxuZXhwb3J0IHR5cGUgUnBjRXJyb3JSZXNwb25zZSA9IHtcbiAgZXJyb3I6IHsgY29kZTogc3RyaW5nOyBtZXNzYWdlOiBzdHJpbmcgfTtcbn07XG5cbmV4cG9ydCB0eXBlIFJwY1Jlc3BvbnNlPFQgPSB1bmtub3duPiA9IFJwY1N1Y2Nlc3NSZXNwb25zZTxUPiB8IFJwY0Vycm9yUmVzcG9uc2U7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYW5kbGVTdG9yYWdlUnBjKFxuICBib2R5OiBScGNSZXF1ZXN0LFxuICBoYW5kbGVyczogSGFuZGxlcnNcbik6IFByb21pc2U8UnBjUmVzcG9uc2U+IHtcbiAgY29uc3QgeyBtZXRob2QsIHBhcmFtcyB9ID0gYm9keTtcblxuICBpZiAoIShtZXRob2QgaW4gbWV0aG9kcykpIHtcbiAgICByZXR1cm4ge1xuICAgICAgZXJyb3I6IHsgY29kZTogXCJNRVRIT0RfTk9UX0ZPVU5EXCIsIG1lc3NhZ2U6IGBVbmtub3duIG1ldGhvZDogJHttZXRob2R9YCB9LFxuICAgIH07XG4gIH1cblxuICBjb25zdCBtZXRob2ROYW1lID0gbWV0aG9kIGFzIE1ldGhvZE5hbWU7XG4gIGNvbnN0IHNjaGVtYSA9IG1ldGhvZHNbbWV0aG9kTmFtZV0ucGFyYW1zO1xuICBjb25zdCBwYXJzZWQgPSBzY2hlbWEuc2FmZVBhcnNlKHBhcmFtcyk7XG5cbiAgaWYgKCFwYXJzZWQuc3VjY2Vzcykge1xuICAgIHJldHVybiB7XG4gICAgICBlcnJvcjoge1xuICAgICAgICBjb2RlOiBcIklOVkFMSURfUEFSQU1TXCIsXG4gICAgICAgIG1lc3NhZ2U6IHBhcnNlZC5lcnJvci5pc3N1ZXNcbiAgICAgICAgICAubWFwKChpKSA9PiBgJHtpLnBhdGguam9pbihcIi5cIil9OiAke2kubWVzc2FnZX1gKVxuICAgICAgICAgIC5qb2luKFwiLCBcIiksXG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICB0cnkge1xuICAgIGNvbnN0IGhhbmRsZXIgPSBoYW5kbGVyc1ttZXRob2ROYW1lXSBhcyAoXG4gICAgICBwYXJhbXM6IHVua25vd25cbiAgICApID0+IFByb21pc2U8dW5rbm93bj47XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgaGFuZGxlcihwYXJzZWQuZGF0YSk7XG4gICAgcmV0dXJuIHsgcmVzdWx0IH07XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4ge1xuICAgICAgZXJyb3I6IHtcbiAgICAgICAgY29kZTogXCJJTlRFUk5BTF9FUlJPUlwiLFxuICAgICAgICBtZXNzYWdlOiBlIGluc3RhbmNlb2YgRXJyb3IgPyBlLm1lc3NhZ2UgOiBTdHJpbmcoZSksXG4gICAgICB9LFxuICAgIH07XG4gIH1cbn1cbiIsICJleHBvcnQgeyBnZXRTdG9yYWdlIH0gZnJvbSBcIi4vY2xpZW50XCI7XG5leHBvcnQge1xuICB0eXBlIEhhbmRsZXJzLFxuICBoYW5kbGVTdG9yYWdlUnBjLFxuICB0eXBlIFJwY0Vycm9yUmVzcG9uc2UsXG4gIHR5cGUgUnBjUmVxdWVzdCxcbiAgdHlwZSBScGNSZXNwb25zZSxcbiAgdHlwZSBScGNTdWNjZXNzUmVzcG9uc2UsXG59IGZyb20gXCIuL2hhbmRsZXJcIjtcbmV4cG9ydCB7XG4gIENvbW1hbmRSZXN1bHRTY2hlbWEsXG4gIENvbW1hbmRTY2hlbWEsXG4gIE1lc3NhZ2VTY2hlbWEsXG4gIHR5cGUgTWV0aG9kTmFtZSxcbiAgbWV0aG9kcyxcbiAgUGFydFNjaGVtYSxcbiAgdHlwZSBTYW5kYm94Q29uZmlnLFxuICBTYW5kYm94Q29uZmlnU2NoZW1hLFxuICBTYW5kYm94UmVjb3JkU2NoZW1hLFxuICBTZXNzaW9uU2NoZW1hLFxuICB0eXBlIFN0b3JhZ2VNZXRob2RzLFxufSBmcm9tIFwiLi9ycGNcIjtcbmV4cG9ydCB0eXBlIHtcbiAgQ29tbWFuZCxcbiAgTGlzdFJlc3VsdCxcbiAgTWVzc2FnZSxcbiAgUGFydCxcbiAgUmVzb2x2ZWRTdG9yYWdlLFxuICBTYW5kYm94UmVjb3JkLFxuICBTZXNzaW9uLFxuICBTdG9yYWdlLFxuICBTdG9yYWdlQ29uZmlnLFxufSBmcm9tIFwiLi90eXBlc1wiO1xuIiwgImltcG9ydCAqIGFzIHBhdGggZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHR5cGUgeyBVcGxvYWRhYmxlRmlsZSB9IGZyb20gXCIuLi9za2lsbHMvdHlwZXNcIjtcbmltcG9ydCB0eXBlIHsgU2FuZGJveCB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbi8qKlxuICogV3JpdGVzIGZpbGVzIHRvIGEgc2FuZGJveCBhdCB0aGUgc3BlY2lmaWVkIGRlc3RpbmF0aW9uIHBhdGguXG4gKiBTaGVsbCBzY3JpcHRzICguc2ggZmlsZXMpIGFyZSBhdXRvbWF0aWNhbGx5IG1hZGUgZXhlY3V0YWJsZS5cbiAqXG4gKiBGb3Igc21hbGwgZmlsZXMgKDwxMDBLQiB0b3RhbCksIHVzZXMgc2luZ2xlIGV4ZWMgd2l0aCBoZXJlZG9jLlxuICogRm9yIGxhcmdlIGZpbGVzLCB3cml0ZXMgYmFzZTY0IGNodW5rcyB0aGVuIGRlY29kZXMgdG8gYXZvaWQgQVJHX01BWCBsaW1pdHMuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB3cml0ZUZpbGVzKG9wdHM6IHtcbiAgc2FuZGJveDogUGljazxTYW5kYm94LCBcImV4ZWNcIj47XG4gIGZpbGVzOiBVcGxvYWRhYmxlRmlsZVtdO1xuICBkZXN0UGF0aDogc3RyaW5nO1xufSk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCB7IHNhbmRib3gsIGZpbGVzLCBkZXN0UGF0aCB9ID0gb3B0cztcblxuICBpZiAoZmlsZXMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgZmlsZVBhdGhzID0gZmlsZXMubWFwKChmaWxlKSA9PiBwYXRoLnBvc2l4LmpvaW4oZGVzdFBhdGgsIGZpbGUucGF0aCkpO1xuICBjb25zdCBwYXJlbnREaXJzID0gWy4uLm5ldyBTZXQoZmlsZVBhdGhzLm1hcCgocCkgPT4gcGF0aC5wb3NpeC5kaXJuYW1lKHApKSldO1xuICBjb25zdCBzaGVsbFNjcmlwdHMgPSBmaWxlUGF0aHMuZmlsdGVyKChwKSA9PiBwLmVuZHNXaXRoKFwiLnNoXCIpKTtcblxuICBjb25zdCBta2RpclJlc3VsdCA9IGF3YWl0IHNhbmRib3guZXhlYyh7XG4gICAgY29tbWFuZDogXCJta2RpclwiLFxuICAgIGFyZ3M6IFtcIi1wXCIsIC4uLnBhcmVudERpcnNdLFxuICB9KTtcbiAgaWYgKG1rZGlyUmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICB0aHJvdyBta2RpclJlc3VsdDtcbiAgfVxuICBhd2FpdCBta2RpclJlc3VsdC5yZXN1bHQ7XG5cbiAgY29uc3QgQ0hVTktfU0laRSA9IDUwXzAwMDtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGZpbGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3QgZmlsZSA9IGZpbGVzW2ldO1xuICAgIGNvbnN0IGZ1bGxQYXRoID0gZmlsZVBhdGhzW2ldO1xuICAgIGNvbnN0IGJhc2U2NENvbnRlbnQgPSB0b0Jhc2U2NChmaWxlLmNvbnRlbnQpO1xuXG4gICAgaWYgKGJhc2U2NENvbnRlbnQubGVuZ3RoIDwgQ0hVTktfU0laRSkge1xuICAgICAgY29uc3QgbWFya2VyID0gYEVPRl8ke2l9YDtcbiAgICAgIGNvbnN0IGV4ZWNSZXN1bHQgPSBhd2FpdCBzYW5kYm94LmV4ZWMoe1xuICAgICAgICBjb21tYW5kOiBcImJhc2hcIixcbiAgICAgICAgYXJnczogW1xuICAgICAgICAgIFwiLWNcIixcbiAgICAgICAgICBgYmFzZTY0IC1kID4gJHtxdW90ZShmdWxsUGF0aCl9IDw8ICcke21hcmtlcn0nXG4ke2Jhc2U2NENvbnRlbnR9XG4ke21hcmtlcn1gLFxuICAgICAgICBdLFxuICAgICAgfSk7XG5cbiAgICAgIGlmIChleGVjUmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgZXhlY1Jlc3VsdDtcbiAgICAgIH1cblxuICAgICAgY29uc3QgeyBleGl0Q29kZSwgc3RkZXJyIH0gPSBhd2FpdCBleGVjUmVzdWx0LnJlc3VsdDtcbiAgICAgIGlmIChleGl0Q29kZSAhPT0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYHdyaXRlRmlsZXMgZmFpbGVkIHdpdGggZXhpdCBjb2RlICR7ZXhpdENvZGV9OiAke3N0ZGVycn1gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHRlbXBCNjQgPSBgL3RtcC9jaHVuay0ke0RhdGUubm93KCl9LSR7aX0uYjY0YDtcblxuICAgICAgY29uc3QgY2xlYXJSZXN1bHQgPSBhd2FpdCBzYW5kYm94LmV4ZWMoe1xuICAgICAgICBjb21tYW5kOiBcImJhc2hcIixcbiAgICAgICAgYXJnczogW1wiLWNcIiwgYD4gJHtxdW90ZSh0ZW1wQjY0KX1gXSxcbiAgICAgIH0pO1xuICAgICAgaWYgKGNsZWFyUmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgY2xlYXJSZXN1bHQ7XG4gICAgICB9XG4gICAgICBhd2FpdCBjbGVhclJlc3VsdC5yZXN1bHQ7XG5cbiAgICAgIGZvciAobGV0IG9mZnNldCA9IDA7IG9mZnNldCA8IGJhc2U2NENvbnRlbnQubGVuZ3RoOyBvZmZzZXQgKz0gQ0hVTktfU0laRSkge1xuICAgICAgICBjb25zdCBjaHVuayA9IGJhc2U2NENvbnRlbnQuc2xpY2Uob2Zmc2V0LCBvZmZzZXQgKyBDSFVOS19TSVpFKTtcbiAgICAgICAgY29uc3QgbWFya2VyID0gYENIVU5LXyR7b2Zmc2V0fWA7XG4gICAgICAgIGNvbnN0IGFwcGVuZFJlc3VsdCA9IGF3YWl0IHNhbmRib3guZXhlYyh7XG4gICAgICAgICAgY29tbWFuZDogXCJiYXNoXCIsXG4gICAgICAgICAgYXJnczogW1xuICAgICAgICAgICAgXCItY1wiLFxuICAgICAgICAgICAgYGNhdCA+PiAke3F1b3RlKHRlbXBCNjQpfSA8PCAnJHttYXJrZXJ9J1xuJHtjaHVua31cbiR7bWFya2VyfWAsXG4gICAgICAgICAgXSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKGFwcGVuZFJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgYXBwZW5kUmVzdWx0O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgeyBleGl0Q29kZSwgc3RkZXJyIH0gPSBhd2FpdCBhcHBlbmRSZXN1bHQucmVzdWx0O1xuICAgICAgICBpZiAoZXhpdENvZGUgIT09IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgd3JpdGVGaWxlcyBjaHVuayBmYWlsZWQgd2l0aCBleGl0IGNvZGUgJHtleGl0Q29kZX06ICR7c3RkZXJyfWBcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGRlY29kZVJlc3VsdCA9IGF3YWl0IHNhbmRib3guZXhlYyh7XG4gICAgICAgIGNvbW1hbmQ6IFwiYmFzaFwiLFxuICAgICAgICBhcmdzOiBbXG4gICAgICAgICAgXCItY1wiLFxuICAgICAgICAgIGBiYXNlNjQgLWQgPCAke3F1b3RlKHRlbXBCNjQpfSA+ICR7cXVvdGUoZnVsbFBhdGgpfSAmJiBybSAtZiAke3F1b3RlKHRlbXBCNjQpfWAsXG4gICAgICAgIF0sXG4gICAgICB9KTtcblxuICAgICAgaWYgKGRlY29kZVJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHRocm93IGRlY29kZVJlc3VsdDtcbiAgICAgIH1cblxuICAgICAgY29uc3QgeyBleGl0Q29kZSwgc3RkZXJyIH0gPSBhd2FpdCBkZWNvZGVSZXN1bHQucmVzdWx0O1xuICAgICAgaWYgKGV4aXRDb2RlICE9PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgd3JpdGVGaWxlcyBkZWNvZGUgZmFpbGVkIHdpdGggZXhpdCBjb2RlICR7ZXhpdENvZGV9OiAke3N0ZGVycn1gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaWYgKHNoZWxsU2NyaXB0cy5sZW5ndGggPiAwKSB7XG4gICAgY29uc3QgY2htb2RSZXN1bHQgPSBhd2FpdCBzYW5kYm94LmV4ZWMoe1xuICAgICAgY29tbWFuZDogXCJjaG1vZFwiLFxuICAgICAgYXJnczogW1wiK3hcIiwgLi4uc2hlbGxTY3JpcHRzXSxcbiAgICB9KTtcbiAgICBpZiAoY2htb2RSZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgdGhyb3cgY2htb2RSZXN1bHQ7XG4gICAgfVxuICAgIGF3YWl0IGNobW9kUmVzdWx0LnJlc3VsdDtcbiAgfVxufVxuXG5mdW5jdGlvbiB0b0Jhc2U2NChjb250ZW50OiBzdHJpbmcgfCBCdWZmZXIpOiBzdHJpbmcge1xuICBpZiAodHlwZW9mIGNvbnRlbnQgPT09IFwic3RyaW5nXCIpIHtcbiAgICByZXR1cm4gQnVmZmVyLmZyb20oY29udGVudCkudG9TdHJpbmcoXCJiYXNlNjRcIik7XG4gIH1cbiAgcmV0dXJuIGNvbnRlbnQudG9TdHJpbmcoXCJiYXNlNjRcIik7XG59XG5cbmZ1bmN0aW9uIHF1b3RlKHM6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgJyR7cy5yZXBsYWNlKC8nL2csIFwiJ1xcXFwnJ1wiKX0nYDtcbn1cbiIsICJpbXBvcnQgdHlwZSB7IENoaWxkUHJvY2VzcyB9IGZyb20gXCJub2RlOmNoaWxkX3Byb2Nlc3NcIjtcbmltcG9ydCB7IHNwYXduIH0gZnJvbSBcIm5vZGU6Y2hpbGRfcHJvY2Vzc1wiO1xuaW1wb3J0ICogYXMgZXJyb3JlIGZyb20gXCJlcnJvcmVcIjtcbmltcG9ydCB7IHVsaWQgfSBmcm9tIFwidWxpZFwiO1xuaW1wb3J0IHsgU2FuZGJveEVycm9yIH0gZnJvbSBcIi4uLy4uL2Vycm9yc1wiO1xuaW1wb3J0IHR5cGUgeyBTYW5kYm94UmVjb3JkLCBTdG9yYWdlQ29uZmlnIH0gZnJvbSBcIi4uLy4uL3N0b3JhZ2UvdHlwZXNcIjtcbmltcG9ydCB0eXBlIHsgTG9nRW50cnksIFNhbmRib3ggfSBmcm9tIFwiLi4vdHlwZXNcIjtcbmltcG9ydCB7IHdyaXRlRmlsZXMgfSBmcm9tIFwiLi4vd3JpdGUtZmlsZXNcIjtcblxuZXhwb3J0IGNvbnN0IGxvY2FsU2FuZGJveCA9ICh7XG4gIHNhbmRib3hSZWNvcmQsXG59OiB7XG4gIHNhbmRib3hSZWNvcmQ6IFNhbmRib3hSZWNvcmQgJiB7IGNvbmZpZzogeyB0eXBlOiBcImxvY2FsXCIgfSB9O1xuICBzdG9yYWdlQ29uZmlnOiBTdG9yYWdlQ29uZmlnO1xufSk6IFNhbmRib3ggPT4ge1xuICBjb25zdCBjb25maWcgPSBzYW5kYm94UmVjb3JkLmNvbmZpZztcbiAgY29uc3QgYmFzZVBhdGggPSBjb25maWcucGF0aCA/PyBwcm9jZXNzLmN3ZCgpO1xuICBjb25zdCBwcm9jZXNzZXMgPSBuZXcgTWFwPHN0cmluZywgQ2hpbGRQcm9jZXNzPigpO1xuXG4gIGNvbnN0IHNhbmRib3g6IFNhbmRib3ggPSB7XG4gICAgaWQ6IHNhbmRib3hSZWNvcmQuaWQsXG4gICAgY29uZmlnOiBzYW5kYm94UmVjb3JkLmNvbmZpZyxcbiAgICBleGVjOiAoeyBjb21tYW5kLCBhcmdzLCBzaWduYWwgfSkgPT4ge1xuICAgICAgcmV0dXJuIGVycm9yZS50cnlBc3luYyh7XG4gICAgICAgIHRyeTogKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IGNvbW1hbmRJZCA9IGBjb21tYW5kXyR7dWxpZCgpfWA7XG5cbiAgICAgICAgICBjb25zdCBjaGlsZCA9IHNwYXduKGNvbW1hbmQsIGFyZ3MsIHtcbiAgICAgICAgICAgIGN3ZDogYmFzZVBhdGgsXG4gICAgICAgICAgICBzaWduYWwsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBwcm9jZXNzZXMuc2V0KGNvbW1hbmRJZCwgY2hpbGQpO1xuXG4gICAgICAgICAgbGV0IHN0ZG91dCA9IFwiXCI7XG4gICAgICAgICAgbGV0IHN0ZGVyciA9IFwiXCI7XG4gICAgICAgICAgY29uc3QgbG9nUXVldWU6IExvZ0VudHJ5W10gPSBbXTtcbiAgICAgICAgICBsZXQgbG9nUmVzb2x2ZTogKCgpID0+IHZvaWQpIHwgbnVsbCA9IG51bGw7XG4gICAgICAgICAgbGV0IGNsb3NlZCA9IGZhbHNlO1xuXG4gICAgICAgICAgY2hpbGQuc3Rkb3V0Lm9uKFwiZGF0YVwiLCAoZGF0YTogc3RyaW5nIHwgQnVmZmVyKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBzdHIgPSBTdHJpbmcoZGF0YSk7XG4gICAgICAgICAgICBzdGRvdXQgKz0gc3RyO1xuICAgICAgICAgICAgbG9nUXVldWUucHVzaCh7IHN0cmVhbTogXCJzdGRvdXRcIiwgZGF0YTogc3RyIH0pO1xuICAgICAgICAgICAgbG9nUmVzb2x2ZT8uKCk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBjaGlsZC5zdGRlcnIub24oXCJkYXRhXCIsIChkYXRhOiBzdHJpbmcgfCBCdWZmZXIpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN0ciA9IFN0cmluZyhkYXRhKTtcbiAgICAgICAgICAgIHN0ZGVyciArPSBzdHI7XG4gICAgICAgICAgICBsb2dRdWV1ZS5wdXNoKHsgc3RyZWFtOiBcInN0ZGVyclwiLCBkYXRhOiBzdHIgfSk7XG4gICAgICAgICAgICBsb2dSZXNvbHZlPy4oKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBQcm9taXNlPHtcbiAgICAgICAgICAgIHN0ZG91dDogc3RyaW5nO1xuICAgICAgICAgICAgc3RkZXJyOiBzdHJpbmc7XG4gICAgICAgICAgICBleGl0Q29kZTogbnVtYmVyO1xuICAgICAgICAgIH0+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNoaWxkLm9uKFwiZXJyb3JcIiwgKGVycikgPT4ge1xuICAgICAgICAgICAgICBwcm9jZXNzZXMuZGVsZXRlKGNvbW1hbmRJZCk7XG4gICAgICAgICAgICAgIGNsb3NlZCA9IHRydWU7XG4gICAgICAgICAgICAgIGxvZ1Jlc29sdmU/LigpO1xuICAgICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBjaGlsZC5vbihcImNsb3NlXCIsIChjb2RlOiBudW1iZXIgfCBudWxsKSA9PiB7XG4gICAgICAgICAgICAgIHByb2Nlc3Nlcy5kZWxldGUoY29tbWFuZElkKTtcbiAgICAgICAgICAgICAgY2xvc2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgbG9nUmVzb2x2ZT8uKCk7XG4gICAgICAgICAgICAgIHJlc29sdmUoeyBzdGRvdXQsIHN0ZGVyciwgZXhpdENvZGU6IGNvZGUgPz8gMCB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgYXN5bmMgZnVuY3Rpb24qIGxvZ3MoKTogQXN5bmNJdGVyYWJsZTxMb2dFbnRyeT4ge1xuICAgICAgICAgICAgd2hpbGUgKCFjbG9zZWQgfHwgbG9nUXVldWUubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICBjb25zdCBlbnRyeSA9IGxvZ1F1ZXVlLnNoaWZ0KCk7XG4gICAgICAgICAgICAgIGlmIChlbnRyeSkge1xuICAgICAgICAgICAgICAgIHlpZWxkIGVudHJ5O1xuICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFjbG9zZWQpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgbG9nUmVzb2x2ZSA9IHJlc29sdmU7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgbG9nUmVzb2x2ZSA9IG51bGw7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHsgY29tbWFuZElkLCBsb2dzLCByZXN1bHQgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIGNhdGNoOiAoZTogdW5rbm93bikgPT5cbiAgICAgICAgICBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pLFxuICAgICAgfSk7XG4gICAgfSxcblxuICAgIGdldERvbWFpbjogKHBvcnQpID0+IHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoYGh0dHA6Ly9sb2NhbGhvc3Q6JHtwb3J0fWApO1xuICAgIH0sXG5cbiAgICBraWxsOiBhc3luYyAoeyBjb21tYW5kSWQsIHN0b3JhZ2UgfSkgPT4ge1xuICAgICAgY29uc3QgY2hpbGQgPSBwcm9jZXNzZXMuZ2V0KGNvbW1hbmRJZCk7XG4gICAgICBpZiAoIWNoaWxkKSB7XG4gICAgICAgIHJldHVybiBuZXcgU2FuZGJveEVycm9yKHtcbiAgICAgICAgICByZWFzb246IGBDb21tYW5kICR7Y29tbWFuZElkfSBub3QgZm91bmQgb3IgYWxyZWFkeSBmaW5pc2hlZGAsXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBjaGlsZC5raWxsKFwiU0lHVEVSTVwiKTtcblxuICAgICAgY29uc3QgY21kID0gYXdhaXQgc3RvcmFnZS5jb21tYW5kLmdldChjb21tYW5kSWQpO1xuICAgICAgaWYgKGNtZCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHJldHVybiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBjbWQubWVzc2FnZSwgY2F1c2U6IGNtZCB9KTtcbiAgICAgIH1cbiAgICAgIGlmIChjbWQgJiYgY21kLnN0YXR1cyA9PT0gXCJydW5uaW5nXCIpIHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3RvcmFnZS5jb21tYW5kLnNldCh7XG4gICAgICAgICAgLi4uY21kLFxuICAgICAgICAgIHN0YXR1czogXCJraWxsZWRcIixcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgIHJldHVybiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiByZXN1bHQubWVzc2FnZSwgY2F1c2U6IHJlc3VsdCB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sXG5cbiAgICB3cml0ZUZpbGVzOiAob3B0cykgPT4gd3JpdGVGaWxlcyh7IHNhbmRib3gsIC4uLm9wdHMgfSksXG4gIH07XG5cbiAgcmV0dXJuIHNhbmRib3g7XG59O1xuIiwgImltcG9ydCAqIGFzIGVycm9yZSBmcm9tIFwiZXJyb3JlXCI7XG5pbXBvcnQgeyBTYW5kYm94IGFzIFZlcmNlbFNhbmRib3hTREsgfSBmcm9tIFwic2FuZGJveFwiO1xuaW1wb3J0IHsgU2FuZGJveEVycm9yIH0gZnJvbSBcIi4uLy4uL2Vycm9yc1wiO1xuaW1wb3J0IHtcbiAgZ2V0U3RvcmFnZSxcbiAgdHlwZSBTYW5kYm94UmVjb3JkLFxuICB0eXBlIFN0b3JhZ2UsXG4gIHR5cGUgU3RvcmFnZUNvbmZpZyxcbn0gZnJvbSBcIi4uLy4uL3N0b3JhZ2VcIjtcbmltcG9ydCB0eXBlIHtcbiAgTG9nRW50cnksXG4gIFNhbmRib3gsXG4gIFNhbmRib3hMaWZlY3ljbGUsXG4gIFNhbmRib3hTdGF0dXMsXG59IGZyb20gXCIuLi90eXBlc1wiO1xuaW1wb3J0IHsgd3JpdGVGaWxlcyB9IGZyb20gXCIuLi93cml0ZS1maWxlc1wiO1xuXG5leHBvcnQgdHlwZSBWZXJjZWxTYW5kYm94Q3JlYXRlT3B0aW9ucyA9IEV4dHJhY3Q8XG4gIFBhcmFtZXRlcnM8dHlwZW9mIFZlcmNlbFNhbmRib3hTREsuY3JlYXRlPlswXSxcbiAgLy8gYmlvbWUtaWdub3JlIGxpbnQvY29tcGxleGl0eS9ub0Jhbm5lZFR5cGVzOiAuXG4gIHt9XG4+O1xuXG5leHBvcnQgY29uc3QgVkVSQ0VMX01BWF9USU1FT1VUX01TID0gNSAqIDYwICogNjAgKiAxMDAwOyAvLyA1IGhvdXJzXG5jb25zdCBMT0NLX1RJTUVPVVRfTVMgPSAzMF8wMDA7IC8vIDMwIHNlY29uZHMgLSBpZiBsb2NrIG9sZGVyIHRoYW4gdGhpcywgY29uc2lkZXIgaXQgc3RhbGVcbmNvbnN0IExPQ0tfUE9MTF9JTlRFUlZBTF9NUyA9IDIwMDtcblxuY29uc3QgZ2V0VGVzdENyZWRlbnRpYWxzID0gKCkgPT5cbiAgcHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09IFwidGVzdFwiXG4gICAgPyB7XG4gICAgICAgIHRva2VuOiBwcm9jZXNzLmVudi5URVNUX1ZFUkNFTF9UT0tFTixcbiAgICAgICAgdGVhbUlkOiBwcm9jZXNzLmVudi5URVNUX1ZFUkNFTF9URUFNX0lELFxuICAgICAgICBwcm9qZWN0SWQ6IHByb2Nlc3MuZW52LlRFU1RfVkVSQ0VMX1BST0pFQ1RfSUQsXG4gICAgICB9XG4gICAgOiB7fTtcblxuLyoqXG4gKiBNb2R1bGUtbGV2ZWwgY2FjaGUgZm9yIGluLWZsaWdodCBzYW5kYm94IGNyZWF0aW9uIHByb21pc2VzLlxuICogUHJldmVudHMgcGFyYWxsZWwgcmVxdWVzdHMgd2l0aGluIHRoZSBzYW1lIHByb2Nlc3MgZnJvbSBjcmVhdGluZyBkdXBsaWNhdGUgc2FuZGJveGVzLlxuICovXG5jb25zdCBjcmVhdGVQcm9taXNlcyA9IG5ldyBNYXA8c3RyaW5nLCBQcm9taXNlPFNhbmRib3hFcnJvciB8IHN0cmluZz4+KCk7XG5cbmNvbnN0IEFDVElWSVRZX1RIUk9UVExFX01TID0gMTBfMDAwO1xuY29uc3QgbGFzdEFjdGl2aXR5U2VudCA9IG5ldyBNYXA8c3RyaW5nLCBudW1iZXI+KCk7XG5cbmNvbnN0IERFRkFVTFRfVkNQVVMgPSAyO1xuXG5leHBvcnQgY29uc3QgdmVyY2VsU2FuZGJveCA9ICh7XG4gIHNhbmRib3hSZWNvcmQsXG4gIHN0b3JhZ2VDb25maWcsXG4gIGVuYWJsZUxpZmVjeWNsZVdvcmtmbG93ID0gdHJ1ZSxcbiAgc3RvcmFnZTogc3RvcmFnZU92ZXJyaWRlLFxufToge1xuICBzYW5kYm94UmVjb3JkOiBTYW5kYm94UmVjb3JkICYgeyBjb25maWc6IHsgdHlwZTogXCJ2ZXJjZWxcIiB9IH07XG4gIHN0b3JhZ2VDb25maWc6IFN0b3JhZ2VDb25maWc7XG4gIGVuYWJsZUxpZmVjeWNsZVdvcmtmbG93PzogYm9vbGVhbjtcbiAgc3RvcmFnZT86IFN0b3JhZ2U7XG59KTogU2FuZGJveCA9PiB7XG4gIGNvbnN0IHsgaWQsIGNvbmZpZyB9ID0gc2FuZGJveFJlY29yZDtcbiAgY29uc3QgdmNwdXMgPSBjb25maWcucmVzb3VyY2VzPy52Y3B1cyA/PyBERUZBVUxUX1ZDUFVTO1xuICBjb25zdCBwb3J0cyA9IGNvbmZpZy5wb3J0cztcbiAgY29uc3Qgc3RvcmFnZSA9IHN0b3JhZ2VPdmVycmlkZSA/PyBnZXRTdG9yYWdlKHN0b3JhZ2VDb25maWcpO1xuICBjb25zdCBpbml0aWFsVmVyY2VsID1cbiAgICBzYW5kYm94UmVjb3JkLnByb3ZpZGVyTWV0YWRhdGE/LnByb3ZpZGVyID09PSBcInZlcmNlbFwiXG4gICAgICA/IHNhbmRib3hSZWNvcmQucHJvdmlkZXJNZXRhZGF0YVxuICAgICAgOiBudWxsO1xuXG4gIHR5cGUgU2FuZGJveEluc3RhbmNlID0gQXdhaXRlZDxSZXR1cm5UeXBlPHR5cGVvZiBWZXJjZWxTYW5kYm94U0RLLmdldD4+O1xuICBsZXQgc2FuZGJveFByb21pc2U6IFByb21pc2U8U2FuZGJveEVycm9yIHwgU2FuZGJveEluc3RhbmNlPiB8IG51bGwgPSBudWxsO1xuXG4gIGFzeW5jIGZ1bmN0aW9uIHBvbGxGb3JTYW5kYm94SWQoKTogUHJvbWlzZTxTYW5kYm94RXJyb3IgfCBzdHJpbmc+IHtcbiAgICBjb25zdCBkZWFkbGluZSA9IERhdGUubm93KCkgKyBMT0NLX1RJTUVPVVRfTVM7XG4gICAgd2hpbGUgKERhdGUubm93KCkgPCBkZWFkbGluZSkge1xuICAgICAgYXdhaXQgbmV3IFByb21pc2UoKHIpID0+IHNldFRpbWVvdXQociwgTE9DS19QT0xMX0lOVEVSVkFMX01TKSk7XG4gICAgICBjb25zdCByZWNvcmQgPSBhd2FpdCBzdG9yYWdlLnNhbmRib3guZ2V0KGlkKTtcbiAgICAgIGlmIChyZWNvcmQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICByZXR1cm4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogcmVjb3JkLm1lc3NhZ2UsIGNhdXNlOiByZWNvcmQgfSk7XG4gICAgICB9XG4gICAgICBjb25zdCB2ZXJjZWxTYW5kYm94SWQgPVxuICAgICAgICByZWNvcmQ/LnByb3ZpZGVyTWV0YWRhdGE/LnByb3ZpZGVyID09PSBcInZlcmNlbFwiXG4gICAgICAgICAgPyByZWNvcmQucHJvdmlkZXJNZXRhZGF0YS5zYW5kYm94SWRcbiAgICAgICAgICA6IG51bGw7XG4gICAgICBpZiAodmVyY2VsU2FuZGJveElkKSB7XG4gICAgICAgIHJldHVybiB2ZXJjZWxTYW5kYm94SWQ7XG4gICAgICB9XG4gICAgICBpZiAoIXJlY29yZD8uYWNxdWlyaW5nTG9ja0F0KSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbmV3IFNhbmRib3hFcnJvcih7XG4gICAgICByZWFzb246IFwiVGltZWQgb3V0IHdhaXRpbmcgZm9yIHNhbmRib3ggY3JlYXRpb24gYnkgYW5vdGhlciBwcm9jZXNzXCIsXG4gICAgfSk7XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBjcmVhdGVTYW5kYm94RnJvbVNuYXBzaG90KFxuICAgIHNuYXBzaG90SWQ6IHN0cmluZ1xuICApOiBQcm9taXNlPFNhbmRib3hFcnJvciB8IHN0cmluZz4ge1xuICAgIHJldHVybiBhd2FpdCBlcnJvcmUudHJ5QXN5bmMoe1xuICAgICAgdHJ5OiBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHNhbmRib3ggPSBhd2FpdCBWZXJjZWxTYW5kYm94U0RLLmNyZWF0ZSh7XG4gICAgICAgICAgc291cmNlOiB7IHR5cGU6IFwic25hcHNob3RcIiwgc25hcHNob3RJZCB9LFxuICAgICAgICAgIHJlc291cmNlczogeyB2Y3B1cyB9LFxuICAgICAgICAgIHRpbWVvdXQ6IFZFUkNFTF9NQVhfVElNRU9VVF9NUyxcbiAgICAgICAgICBwb3J0cyxcbiAgICAgICAgICAuLi5nZXRUZXN0Q3JlZGVudGlhbHMoKSxcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gICAgICAgIGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5zZXQoe1xuICAgICAgICAgIGlkLFxuICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICBjcmVhdGVkQXQ6IG5vdyxcbiAgICAgICAgICBsYXN0QWN0aXZpdHlBdDogbm93LFxuICAgICAgICAgIGFjcXVpcmluZ0xvY2tJZDogbnVsbCxcbiAgICAgICAgICBhY3F1aXJpbmdMb2NrQXQ6IG51bGwsXG4gICAgICAgICAgcHJvdmlkZXJNZXRhZGF0YToge1xuICAgICAgICAgICAgcHJvdmlkZXI6IFwidmVyY2VsXCIsXG4gICAgICAgICAgICBzYW5kYm94SWQ6IHNhbmRib3guc2FuZGJveElkLFxuICAgICAgICAgICAgc25hcHNob3RJZCxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHNhbmRib3guc2FuZGJveElkO1xuICAgICAgfSxcbiAgICAgIGNhdGNoOiAoZSkgPT4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogU3RyaW5nKGUpLCBjYXVzZTogZSB9KSxcbiAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZUZyZXNoU2FuZGJveCgpOiBQcm9taXNlPFNhbmRib3hFcnJvciB8IHN0cmluZz4ge1xuICAgIHJldHVybiBhd2FpdCBlcnJvcmUudHJ5QXN5bmMoe1xuICAgICAgdHJ5OiBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHNhbmRib3ggPSBhd2FpdCBWZXJjZWxTYW5kYm94U0RLLmNyZWF0ZSh7XG4gICAgICAgICAgcmVzb3VyY2VzOiB7IHZjcHVzIH0sXG4gICAgICAgICAgdGltZW91dDogVkVSQ0VMX01BWF9USU1FT1VUX01TLFxuICAgICAgICAgIHBvcnRzLFxuICAgICAgICAgIC4uLmdldFRlc3RDcmVkZW50aWFscygpLFxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgYXdhaXQgc3RvcmFnZS5zYW5kYm94LnNldCh7XG4gICAgICAgICAgaWQsXG4gICAgICAgICAgY29uZmlnLFxuICAgICAgICAgIGNyZWF0ZWRBdDogbm93LFxuICAgICAgICAgIGxhc3RBY3Rpdml0eUF0OiBub3csXG4gICAgICAgICAgYWNxdWlyaW5nTG9ja0lkOiBudWxsLFxuICAgICAgICAgIGFjcXVpcmluZ0xvY2tBdDogbnVsbCxcbiAgICAgICAgICBwcm92aWRlck1ldGFkYXRhOiB7XG4gICAgICAgICAgICBwcm92aWRlcjogXCJ2ZXJjZWxcIixcbiAgICAgICAgICAgIHNhbmRib3hJZDogc2FuZGJveC5zYW5kYm94SWQsXG4gICAgICAgICAgICBzbmFwc2hvdElkOiBudWxsLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gc2FuZGJveC5zYW5kYm94SWQ7XG4gICAgICB9LFxuICAgICAgY2F0Y2g6IChlKSA9PiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pLFxuICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gZG9HZXRPckNyZWF0ZVNhbmRib3hJZCgpOiBQcm9taXNlPFNhbmRib3hFcnJvciB8IHN0cmluZz4ge1xuICAgIGlmIChpbml0aWFsVmVyY2VsPy5zYW5kYm94SWQpIHtcbiAgICAgIHJldHVybiBpbml0aWFsVmVyY2VsLnNhbmRib3hJZDtcbiAgICB9XG5cbiAgICBjb25zdCBleGlzdGluZyA9IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5nZXQoaWQpO1xuICAgIGlmIChleGlzdGluZyBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICByZXR1cm4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogZXhpc3RpbmcubWVzc2FnZSwgY2F1c2U6IGV4aXN0aW5nIH0pO1xuICAgIH1cblxuICAgIGNvbnN0IGV4aXN0aW5nVmVyY2VsID1cbiAgICAgIGV4aXN0aW5nPy5wcm92aWRlck1ldGFkYXRhPy5wcm92aWRlciA9PT0gXCJ2ZXJjZWxcIlxuICAgICAgICA/IGV4aXN0aW5nLnByb3ZpZGVyTWV0YWRhdGFcbiAgICAgICAgOiBudWxsO1xuXG4gICAgaWYgKGV4aXN0aW5nVmVyY2VsPy5zYW5kYm94SWQpIHtcbiAgICAgIHJldHVybiBleGlzdGluZ1ZlcmNlbC5zYW5kYm94SWQ7XG4gICAgfVxuXG4gICAgY29uc3QgaGFzQWN0aXZlTG9jayA9XG4gICAgICBleGlzdGluZz8uYWNxdWlyaW5nTG9ja0lkICYmXG4gICAgICBleGlzdGluZy5hY3F1aXJpbmdMb2NrQXQgJiZcbiAgICAgIERhdGUubm93KCkgLSBleGlzdGluZy5hY3F1aXJpbmdMb2NrQXQgPCBMT0NLX1RJTUVPVVRfTVM7XG5cbiAgICBpZiAoaGFzQWN0aXZlTG9jaykge1xuICAgICAgcmV0dXJuIHBvbGxGb3JTYW5kYm94SWQoKTtcbiAgICB9XG5cbiAgICBjb25zdCBsb2NrSWQgPSBjcnlwdG8ucmFuZG9tVVVJRCgpO1xuICAgIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gICAgYXdhaXQgc3RvcmFnZS5zYW5kYm94LnNldCh7XG4gICAgICBpZCxcbiAgICAgIGNvbmZpZyxcbiAgICAgIGNyZWF0ZWRBdDogZXhpc3Rpbmc/LmNyZWF0ZWRBdCA/PyBzYW5kYm94UmVjb3JkLmNyZWF0ZWRBdCxcbiAgICAgIGxhc3RBY3Rpdml0eUF0OiBleGlzdGluZz8ubGFzdEFjdGl2aXR5QXQgPz8gc2FuZGJveFJlY29yZC5sYXN0QWN0aXZpdHlBdCxcbiAgICAgIGFjcXVpcmluZ0xvY2tJZDogbG9ja0lkLFxuICAgICAgYWNxdWlyaW5nTG9ja0F0OiBub3csXG4gICAgICBwcm92aWRlck1ldGFkYXRhOiB7XG4gICAgICAgIHByb3ZpZGVyOiBcInZlcmNlbFwiLFxuICAgICAgICBzYW5kYm94SWQ6IG51bGwsXG4gICAgICAgIHNuYXBzaG90SWQ6XG4gICAgICAgICAgZXhpc3RpbmdWZXJjZWw/LnNuYXBzaG90SWQgPz8gaW5pdGlhbFZlcmNlbD8uc25hcHNob3RJZCA/PyBudWxsLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGNvbnN0IGFmdGVyTG9jayA9IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5nZXQoaWQpO1xuICAgIGlmIChhZnRlckxvY2sgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgcmV0dXJuIG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IGFmdGVyTG9jay5tZXNzYWdlLCBjYXVzZTogYWZ0ZXJMb2NrIH0pO1xuICAgIH1cbiAgICBpZiAoYWZ0ZXJMb2NrPy5hY3F1aXJpbmdMb2NrSWQgIT09IGxvY2tJZCkge1xuICAgICAgcmV0dXJuIHBvbGxGb3JTYW5kYm94SWQoKTtcbiAgICB9XG5cbiAgICBjb25zdCBzbmFwc2hvdElkID1cbiAgICAgIGV4aXN0aW5nVmVyY2VsPy5zbmFwc2hvdElkID8/XG4gICAgICBpbml0aWFsVmVyY2VsPy5zbmFwc2hvdElkID8/XG4gICAgICBjb25maWcubGlmZWN5Y2xlPy5zbmFwc2hvdElkO1xuICAgIGlmIChzbmFwc2hvdElkKSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjcmVhdGVTYW5kYm94RnJvbVNuYXBzaG90KHNuYXBzaG90SWQpO1xuICAgICAgaWYgKCEocmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNyZWF0ZUZyZXNoU2FuZGJveCgpO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0T3JDcmVhdGVTYW5kYm94SWQoKTogUHJvbWlzZTxTYW5kYm94RXJyb3IgfCBzdHJpbmc+IHtcbiAgICBjb25zdCBjYWNoZWQgPSBjcmVhdGVQcm9taXNlcy5nZXQoaWQpO1xuICAgIGlmIChjYWNoZWQpIHtcbiAgICAgIHJldHVybiBjYWNoZWQ7XG4gICAgfVxuXG4gICAgY29uc3QgcHJvbWlzZSA9IGRvR2V0T3JDcmVhdGVTYW5kYm94SWQoKS5maW5hbGx5KCgpID0+IHtcbiAgICAgIGNyZWF0ZVByb21pc2VzLmRlbGV0ZShpZCk7XG4gICAgfSk7XG4gICAgY3JlYXRlUHJvbWlzZXMuc2V0KGlkLCBwcm9taXNlKTtcbiAgICByZXR1cm4gcHJvbWlzZTtcbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIGRvR2V0U2FuZGJveCgpOiBQcm9taXNlPFNhbmRib3hFcnJvciB8IFNhbmRib3hJbnN0YW5jZT4ge1xuICAgIGNvbnN0IHZlcmNlbFNhbmRib3hJZCA9IGF3YWl0IGdldE9yQ3JlYXRlU2FuZGJveElkKCk7XG4gICAgaWYgKHZlcmNlbFNhbmRib3hJZCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICByZXR1cm4gdmVyY2VsU2FuZGJveElkO1xuICAgIH1cblxuICAgIHJldHVybiBlcnJvcmUudHJ5QXN5bmMoe1xuICAgICAgdHJ5OiAoKSA9PlxuICAgICAgICBWZXJjZWxTYW5kYm94U0RLLmdldCh7XG4gICAgICAgICAgc2FuZGJveElkOiB2ZXJjZWxTYW5kYm94SWQsXG4gICAgICAgICAgLi4uZ2V0VGVzdENyZWRlbnRpYWxzKCksXG4gICAgICAgIH0pLFxuICAgICAgY2F0Y2g6IChlKSA9PiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pLFxuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0U2FuZGJveCgpOiBQcm9taXNlPFNhbmRib3hFcnJvciB8IFNhbmRib3hJbnN0YW5jZT4ge1xuICAgIGlmICghc2FuZGJveFByb21pc2UpIHtcbiAgICAgIHNhbmRib3hQcm9taXNlID0gZG9HZXRTYW5kYm94KCk7XG4gICAgfVxuICAgIHJldHVybiBzYW5kYm94UHJvbWlzZTtcbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIHVwZGF0ZUxhc3RBY3Rpdml0eSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgIGNvbnN0IGxhc3RTZW50ID0gbGFzdEFjdGl2aXR5U2VudC5nZXQoaWQpO1xuICAgIGlmIChsYXN0U2VudCAmJiBub3cgLSBsYXN0U2VudCA8IEFDVElWSVRZX1RIUk9UVExFX01TKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGxhc3RBY3Rpdml0eVNlbnQuc2V0KGlkLCBub3cpO1xuXG4gICAgY29uc3QgZXhpc3RpbmcgPSBhd2FpdCBzdG9yYWdlLnNhbmRib3guZ2V0KGlkKTtcbiAgICBpZiAoZXhpc3RpbmcgaW5zdGFuY2VvZiBFcnJvciB8fCAhZXhpc3RpbmcpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgZXhpc3RpbmdWZXJjZWwgPVxuICAgICAgZXhpc3RpbmcucHJvdmlkZXJNZXRhZGF0YT8ucHJvdmlkZXIgPT09IFwidmVyY2VsXCJcbiAgICAgICAgPyBleGlzdGluZy5wcm92aWRlck1ldGFkYXRhXG4gICAgICAgIDogbnVsbDtcbiAgICBhd2FpdCBzdG9yYWdlLnNhbmRib3guc2V0KHtcbiAgICAgIGlkOiBleGlzdGluZy5pZCxcbiAgICAgIGNvbmZpZzogZXhpc3RpbmcuY29uZmlnLFxuICAgICAgY3JlYXRlZEF0OiBleGlzdGluZy5jcmVhdGVkQXQsXG4gICAgICBsYXN0QWN0aXZpdHlBdDogbm93LFxuICAgICAgYWNxdWlyaW5nTG9ja0lkOiBudWxsLFxuICAgICAgYWNxdWlyaW5nTG9ja0F0OiBudWxsLFxuICAgICAgcHJvdmlkZXJNZXRhZGF0YTogZXhpc3RpbmdWZXJjZWwgPz8ge1xuICAgICAgICBwcm92aWRlcjogXCJ2ZXJjZWxcIixcbiAgICAgICAgc2FuZGJveElkOiBudWxsLFxuICAgICAgICBzbmFwc2hvdElkOiBudWxsLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGlmIChlbmFibGVMaWZlY3ljbGVXb3JrZmxvdykge1xuICAgICAgLy8gdG9kbyByZS1lbmFibGUgb25jZSB3ZSBmaWd1cmUgb3V0IHdoeSB3b3JrZmxvdyB0aHJvd3MgYSBidW5jaCBvZiBlcnJvcnMgaW4gZGV2XG4gICAgICAvLyBjb25zdCBsaWZlY3ljbGVJbnB1dDogU2FuZGJveExpZmVjeWNsZUlucHV0ID0ge1xuICAgICAgLy8gICBpZCxcbiAgICAgIC8vICAgc3RvcmFnZUNvbmZpZyxcbiAgICAgIC8vICAgaW5pdGlhbENvbmZpZzogY29uZmlnLFxuICAgICAgLy8gfTtcbiAgICAgIC8vIHRyeSB7XG4gICAgICAvLyAgIGF3YWl0IHNhbmRib3hBY3Rpdml0eUhvb2sucmVzdW1lKGlkLCB7XG4gICAgICAvLyAgICAgdHlwZTogXCJhY3Rpdml0eVwiLFxuICAgICAgLy8gICAgIG5ld0NvbmZpZzogY29uZmlnLFxuICAgICAgLy8gICB9KTtcbiAgICAgIC8vIH0gY2F0Y2gge1xuICAgICAgLy8gICBhd2FpdCBzdGFydChzYW5kYm94TGlmZWN5Y2xlV29ya2Zsb3csIFt7IGlucHV0OiBsaWZlY3ljbGVJbnB1dCB9XSk7XG4gICAgICAvLyB9XG4gICAgfVxuICB9XG5cbiAgY29uc3QgbGlmZWN5Y2xlOiBTYW5kYm94TGlmZWN5Y2xlID0ge1xuICAgIHN0YXJ0OiBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzYW5kYm94ID0gYXdhaXQgZ2V0U2FuZGJveCgpO1xuICAgICAgaWYgKHNhbmRib3ggaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICByZXR1cm4gc2FuZGJveDtcbiAgICAgIH1cbiAgICAgIGF3YWl0IHVwZGF0ZUxhc3RBY3Rpdml0eSgpO1xuICAgICAgcmV0dXJuIHNhbmRib3guc3RhdHVzIGFzIFNhbmRib3hTdGF0dXM7XG4gICAgfSxcblxuICAgIHNuYXBzaG90OiBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzYW5kYm94ID0gYXdhaXQgZ2V0U2FuZGJveCgpO1xuICAgICAgaWYgKHNhbmRib3ggaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICByZXR1cm4gc2FuZGJveDtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGVycm9yZS50cnlBc3luYyh7XG4gICAgICAgIHRyeTogYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IGV4aXN0aW5nID0gYXdhaXQgc3RvcmFnZS5zYW5kYm94LmdldChpZCk7XG4gICAgICAgICAgY29uc3Qgc25hcHNob3QgPSBhd2FpdCBzYW5kYm94LnNuYXBzaG90KCk7XG4gICAgICAgICAgYXdhaXQgc3RvcmFnZS5zYW5kYm94LnNldCh7XG4gICAgICAgICAgICBpZCxcbiAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgIGNyZWF0ZWRBdDpcbiAgICAgICAgICAgICAgZXhpc3RpbmcgaW5zdGFuY2VvZiBFcnJvciA/IG51bGwgOiBleGlzdGluZz8uY3JlYXRlZEF0ID8/IG51bGwsXG4gICAgICAgICAgICBsYXN0QWN0aXZpdHlBdDpcbiAgICAgICAgICAgICAgZXhpc3RpbmcgaW5zdGFuY2VvZiBFcnJvclxuICAgICAgICAgICAgICAgID8gbnVsbFxuICAgICAgICAgICAgICAgIDogZXhpc3Rpbmc/Lmxhc3RBY3Rpdml0eUF0ID8/IG51bGwsXG4gICAgICAgICAgICBhY3F1aXJpbmdMb2NrSWQ6IG51bGwsXG4gICAgICAgICAgICBhY3F1aXJpbmdMb2NrQXQ6IG51bGwsXG4gICAgICAgICAgICBwcm92aWRlck1ldGFkYXRhOiB7XG4gICAgICAgICAgICAgIHByb3ZpZGVyOiBcInZlcmNlbFwiLFxuICAgICAgICAgICAgICBzYW5kYm94SWQ6IG51bGwsXG4gICAgICAgICAgICAgIHNuYXBzaG90SWQ6IHNuYXBzaG90LnNuYXBzaG90SWQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHJldHVybiB7IHNuYXBzaG90SWQ6IHNuYXBzaG90LnNuYXBzaG90SWQgfTtcbiAgICAgICAgfSxcbiAgICAgICAgY2F0Y2g6IChlKSA9PiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pLFxuICAgICAgfSk7XG4gICAgfSxcblxuICAgIHN0b3A6IGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHNhbmRib3ggPSBhd2FpdCBnZXRTYW5kYm94KCk7XG4gICAgICBpZiAoc2FuZGJveCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHJldHVybiBzYW5kYm94O1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gZXJyb3JlLnRyeUFzeW5jKHtcbiAgICAgICAgdHJ5OiBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgYXdhaXQgc2FuZGJveC5zdG9wKCk7XG4gICAgICAgICAgY29uc3QgZXhpc3RpbmcgPSBhd2FpdCBzdG9yYWdlLnNhbmRib3guZ2V0KGlkKTtcbiAgICAgICAgICBpZiAoZXhpc3RpbmcgaW5zdGFuY2VvZiBFcnJvciB8fCAhZXhpc3RpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgICAgfVxuICAgICAgICAgIGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5zZXQoe1xuICAgICAgICAgICAgaWQ6IGV4aXN0aW5nLmlkLFxuICAgICAgICAgICAgY29uZmlnOiBleGlzdGluZy5jb25maWcsXG4gICAgICAgICAgICBjcmVhdGVkQXQ6IGV4aXN0aW5nLmNyZWF0ZWRBdCxcbiAgICAgICAgICAgIGxhc3RBY3Rpdml0eUF0OiBleGlzdGluZy5sYXN0QWN0aXZpdHlBdCxcbiAgICAgICAgICAgIGFjcXVpcmluZ0xvY2tJZDogbnVsbCxcbiAgICAgICAgICAgIGFjcXVpcmluZ0xvY2tBdDogbnVsbCxcbiAgICAgICAgICAgIHByb3ZpZGVyTWV0YWRhdGE6IHtcbiAgICAgICAgICAgICAgcHJvdmlkZXI6IFwidmVyY2VsXCIsXG4gICAgICAgICAgICAgIHNhbmRib3hJZDogbnVsbCxcbiAgICAgICAgICAgICAgc25hcHNob3RJZDogbnVsbCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfSxcbiAgICAgICAgY2F0Y2g6IChlKSA9PiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pLFxuICAgICAgfSk7XG4gICAgfSxcblxuICAgIGdldFN0YXR1czogYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qgc2FuZGJveCA9IGF3YWl0IGdldFNhbmRib3goKTtcbiAgICAgIGlmIChzYW5kYm94IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIHNhbmRib3g7XG4gICAgICB9XG4gICAgICByZXR1cm4gc2FuZGJveC5zdGF0dXMgYXMgU2FuZGJveFN0YXR1cztcbiAgICB9LFxuXG4gICAgZ2V0Q3JlYXRlZEF0OiBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzYW5kYm94ID0gYXdhaXQgZ2V0U2FuZGJveCgpO1xuICAgICAgaWYgKHNhbmRib3ggaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICByZXR1cm4gc2FuZGJveDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBzYW5kYm94LmNyZWF0ZWRBdDtcbiAgICB9LFxuXG4gICAgZ2V0UmVtYWluaW5nVGltZW91dDogYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qgc2FuZGJveCA9IGF3YWl0IGdldFNhbmRib3goKTtcbiAgICAgIGlmIChzYW5kYm94IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIHNhbmRib3g7XG4gICAgICB9XG4gICAgICByZXR1cm4gc2FuZGJveC50aW1lb3V0O1xuICAgIH0sXG4gIH07XG5cbiAgY29uc3Qgc2FuZGJveDogU2FuZGJveCA9IHtcbiAgICBpZCxcbiAgICBjb25maWcsXG4gICAgZXhlYzogYXN5bmMgKHsgY29tbWFuZCwgYXJncywgc2lnbmFsIH0pID0+IHtcbiAgICAgIGNvbnN0IGluc3RhbmNlID0gYXdhaXQgZ2V0U2FuZGJveCgpO1xuICAgICAgaWYgKGluc3RhbmNlIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIGluc3RhbmNlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB1cGRhdGVQcm9taXNlID0gdXBkYXRlTGFzdEFjdGl2aXR5KCk7XG5cbiAgICAgIGNvbnN0IGV4ZWNSZXN1bHQgPSBhd2FpdCBlcnJvcmUudHJ5QXN5bmMoe1xuICAgICAgICB0cnk6IGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCBvdXRwdXQgPSBhd2FpdCBpbnN0YW5jZS5ydW5Db21tYW5kKGNvbW1hbmQsIGFyZ3MsIHsgc2lnbmFsIH0pO1xuXG4gICAgICAgICAgbGV0IHN0ZG91dCA9IFwiXCI7XG4gICAgICAgICAgbGV0IHN0ZGVyciA9IFwiXCI7XG4gICAgICAgICAgY29uc3QgbG9nQnVmZmVyOiBMb2dFbnRyeVtdID0gW107XG4gICAgICAgICAgY29uc3Qgc3RhdGUgPSB7XG4gICAgICAgICAgICByZXNvbHZlOiBudWxsIGFzICgoKSA9PiB2b2lkKSB8IG51bGwsXG4gICAgICAgICAgICBjb25zdW1lZDogZmFsc2UsXG4gICAgICAgICAgfTtcblxuICAgICAgICAgIGNvbnN0IGNvbnN1bWVMb2dzID0gKGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGZvciBhd2FpdCAoY29uc3QgbG9nIG9mIG91dHB1dC5sb2dzKCkpIHtcbiAgICAgICAgICAgICAgY29uc3QgZW50cnk6IExvZ0VudHJ5ID1cbiAgICAgICAgICAgICAgICBsb2cuc3RyZWFtID09PSBcInN0ZG91dFwiXG4gICAgICAgICAgICAgICAgICA/IHsgc3RyZWFtOiBcInN0ZG91dFwiLCBkYXRhOiBsb2cuZGF0YSB9XG4gICAgICAgICAgICAgICAgICA6IHsgc3RyZWFtOiBcInN0ZGVyclwiLCBkYXRhOiBsb2cuZGF0YSB9O1xuXG4gICAgICAgICAgICAgIGlmIChsb2cuc3RyZWFtID09PSBcInN0ZG91dFwiKSB7XG4gICAgICAgICAgICAgICAgc3Rkb3V0ICs9IGxvZy5kYXRhO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHN0ZGVyciArPSBsb2cuZGF0YTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGxvZ0J1ZmZlci5wdXNoKGVudHJ5KTtcbiAgICAgICAgICAgICAgc3RhdGUucmVzb2x2ZT8uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzdGF0ZS5jb25zdW1lZCA9IHRydWU7XG4gICAgICAgICAgICBzdGF0ZS5yZXNvbHZlPy4oKTtcbiAgICAgICAgICB9KSgpO1xuXG4gICAgICAgICAgYXN5bmMgZnVuY3Rpb24qIGxvZ3MoKTogQXN5bmNJdGVyYWJsZTxMb2dFbnRyeT4ge1xuICAgICAgICAgICAgbGV0IGluZGV4ID0gMDtcbiAgICAgICAgICAgIHdoaWxlICghc3RhdGUuY29uc3VtZWQgfHwgaW5kZXggPCBsb2dCdWZmZXIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgIGlmIChpbmRleCA8IGxvZ0J1ZmZlci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB5aWVsZCBsb2dCdWZmZXJbaW5kZXgrK107XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUpID0+IHtcbiAgICAgICAgICAgICAgICAgIHN0YXRlLnJlc29sdmUgPSByZXNvbHZlO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHN0YXRlLnJlc29sdmUgPSBudWxsO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgcmVzdWx0ID0gY29uc3VtZUxvZ3MudGhlbigoKSA9PiAoe1xuICAgICAgICAgICAgc3Rkb3V0LFxuICAgICAgICAgICAgc3RkZXJyLFxuICAgICAgICAgICAgZXhpdENvZGU6IG91dHB1dC5leGl0Q29kZSxcbiAgICAgICAgICB9KSk7XG5cbiAgICAgICAgICByZXR1cm4geyBjb21tYW5kSWQ6IG91dHB1dC5jbWRJZCwgbG9ncywgcmVzdWx0IH07XG4gICAgICAgIH0sXG4gICAgICAgIGNhdGNoOiAoZSkgPT4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogU3RyaW5nKGUpLCBjYXVzZTogZSB9KSxcbiAgICAgIH0pO1xuXG4gICAgICBhd2FpdCB1cGRhdGVQcm9taXNlO1xuICAgICAgcmV0dXJuIGV4ZWNSZXN1bHQ7XG4gICAgfSxcblxuICAgIGdldERvbWFpbjogYXN5bmMgKHBvcnQpID0+IHtcbiAgICAgIGNvbnN0IHNhbmRib3ggPSBhd2FpdCBnZXRTYW5kYm94KCk7XG4gICAgICBpZiAoc2FuZGJveCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHJldHVybiBzYW5kYm94O1xuICAgICAgfVxuXG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gc2FuZGJveC5kb21haW4ocG9ydCk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHJldHVybiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pO1xuICAgICAgfVxuICAgIH0sXG5cbiAgICBraWxsOiBhc3luYyAoeyBjb21tYW5kSWQsIHN0b3JhZ2U6IGNtZFN0b3JhZ2UgfSkgPT4ge1xuICAgICAgY29uc3QgaW5zdGFuY2UgPSBhd2FpdCBnZXRTYW5kYm94KCk7XG4gICAgICBpZiAoaW5zdGFuY2UgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICByZXR1cm4gaW5zdGFuY2U7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNtZCA9IGF3YWl0IGNtZFN0b3JhZ2UuY29tbWFuZC5nZXQoY29tbWFuZElkKTtcbiAgICAgIGlmIChjbWQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICByZXR1cm4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogY21kLm1lc3NhZ2UsIGNhdXNlOiBjbWQgfSk7XG4gICAgICB9XG4gICAgICBpZiAoY21kICYmIGNtZC5zdGF0dXMgPT09IFwicnVubmluZ1wiKSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNtZFN0b3JhZ2UuY29tbWFuZC5zZXQoe1xuICAgICAgICAgIC4uLmNtZCxcbiAgICAgICAgICBzdGF0dXM6IFwia2lsbGVkXCIsXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICByZXR1cm4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogcmVzdWx0Lm1lc3NhZ2UsIGNhdXNlOiByZXN1bHQgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfSxcblxuICAgIHdyaXRlRmlsZXM6IChvcHRzKSA9PiB3cml0ZUZpbGVzKHsgc2FuZGJveCwgLi4ub3B0cyB9KSxcblxuICAgIGxpZmVjeWNsZSxcbiAgfTtcblxuICBpZiAoY29uZmlnLmxpZmVjeWNsZT8uYXV0b1N0YXJ0ICE9PSBmYWxzZSkge1xuICAgIHNhbmRib3hQcm9taXNlID0gZG9HZXRTYW5kYm94KCk7XG4gIH1cblxuICByZXR1cm4gc2FuZGJveDtcbn07XG4iLCAiaW1wb3J0IHR5cGUgeyBTYW5kYm94UmVjb3JkLCBTdG9yYWdlQ29uZmlnIH0gZnJvbSBcIi4uL3N0b3JhZ2VcIjtcbmltcG9ydCB7IGxvY2FsU2FuZGJveCB9IGZyb20gXCIuL2JpbmRpbmdzL2xvY2FsXCI7XG5pbXBvcnQgeyB2ZXJjZWxTYW5kYm94IH0gZnJvbSBcIi4vYmluZGluZ3MvdmVyY2VsXCI7XG5pbXBvcnQgdHlwZSB7IFNhbmRib3ggfSBmcm9tIFwiLi90eXBlc1wiO1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0U2FuZGJveCh7XG4gIHNhbmRib3hSZWNvcmQsXG4gIHN0b3JhZ2VDb25maWcsXG59OiB7XG4gIHN0b3JhZ2VDb25maWc6IFN0b3JhZ2VDb25maWc7XG4gIHNhbmRib3hSZWNvcmQ6IFNhbmRib3hSZWNvcmQ7XG59KTogU2FuZGJveCB7XG4gIGNvbnN0IHsgY29uZmlnIH0gPSBzYW5kYm94UmVjb3JkO1xuICBzd2l0Y2ggKGNvbmZpZy50eXBlKSB7XG4gICAgY2FzZSBcImxvY2FsXCI6XG4gICAgICByZXR1cm4gbG9jYWxTYW5kYm94KHtcbiAgICAgICAgc2FuZGJveFJlY29yZDogc2FuZGJveFJlY29yZCBhcyBTYW5kYm94UmVjb3JkICYge1xuICAgICAgICAgIGNvbmZpZzogeyB0eXBlOiBcImxvY2FsXCIgfTtcbiAgICAgICAgfSxcbiAgICAgICAgc3RvcmFnZUNvbmZpZyxcbiAgICAgIH0pO1xuICAgIGNhc2UgXCJ2ZXJjZWxcIjpcbiAgICAgIHJldHVybiB2ZXJjZWxTYW5kYm94KHtcbiAgICAgICAgc2FuZGJveFJlY29yZDogc2FuZGJveFJlY29yZCBhcyBTYW5kYm94UmVjb3JkICYge1xuICAgICAgICAgIGNvbmZpZzogeyB0eXBlOiBcInZlcmNlbFwiIH07XG4gICAgICAgIH0sXG4gICAgICAgIHN0b3JhZ2VDb25maWcsXG4gICAgICB9KTtcbiAgICBjYXNlIFwiY3VzdG9tXCI6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDdXN0b20gc2FuZGJveGVzIGFyZSBub3Qgc3VwcG9ydGVkXCIpO1xuICAgIGRlZmF1bHQ6XG4gICAgICBjb25maWcgc2F0aXNmaWVzIG5ldmVyO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgVW5rbm93biBzYW5kYm94IHR5cGU6ICR7XG4gICAgICAgICAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiAuXG4gICAgICAgICAgKGNvbmZpZyBhcyBhbnkpLnR5cGVcbiAgICAgICAgfWBcbiAgICAgICk7XG4gIH1cbn1cbiIsICJleHBvcnQgeyBnZXRTYW5kYm94IH0gZnJvbSBcIi4vY2xpZW50XCI7XG5leHBvcnQgdHlwZSB7XG4gIEV4ZWNSZXN1bHQsXG4gIExvZ0VudHJ5LFxuICBTYW5kYm94LFxuICBTYW5kYm94TGlmZWN5Y2xlLFxuICBTYW5kYm94TGlmZWN5Y2xlSW5wdXQsXG4gIFNhbmRib3hTdGF0dXMsXG4gIFRlcm1pbmFsLFxuICBUZXJtaW5hbE1ldGFkYXRhLFxuICBWZXJjZWxTYW5kYm94TGlmZWN5Y2xlQ29uZmlnLFxufSBmcm9tIFwiLi90eXBlc1wiO1xuIiwgImltcG9ydCB0eXBlIHsgRmluaXNoUmVhc29uIH0gZnJvbSBcImFpXCI7XG5pbXBvcnQgeyBkZWZpbmVIb29rLCBGYXRhbEVycm9yLCBnZXRXcml0YWJsZSB9IGZyb20gXCJ3b3JrZmxvd1wiO1xuaW1wb3J0IHsgY29tcGxldGVNZXNzYWdlU3RlcCwgc3RyZWFtVGV4dFN0ZXAgfSBmcm9tIFwiLi9hZ2VudC13b3JrZmxvdy1zdGVwc1wiO1xuaW1wb3J0IHR5cGUgeyBTdG9yYWdlQ29uZmlnIH0gZnJvbSBcIi4vc3RvcmFnZVwiO1xuXG5leHBvcnQgdHlwZSBBZ2VudElucHV0ID0ge1xuICBzZXNzaW9uSWQ6IHN0cmluZztcbiAgc3RvcmFnZUNvbmZpZzogU3RvcmFnZUNvbmZpZztcbn07XG5cbmV4cG9ydCB0eXBlIEFnZW50TWVzc2FnZUlucHV0ID0ge1xuICBhc3Npc3RhbnRNZXNzYWdlSWQ6IHN0cmluZztcbiAgaG9va1Rva2VuOiBzdHJpbmc7XG59O1xuXG5leHBvcnQgY29uc3QgYWdlbnRNZXNzYWdlSG9vayA9IGRlZmluZUhvb2s8QWdlbnRNZXNzYWdlSW5wdXQ+KCk7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhZ2VudFdvcmtmbG93KHtcbiAgaW5wdXQsXG4gIGV2ZW50LFxufToge1xuICBpbnB1dDogQWdlbnRJbnB1dDtcbiAgZXZlbnQ6IEFnZW50TWVzc2FnZUlucHV0O1xufSkge1xuICBcInVzZSB3b3JrZmxvd1wiO1xuXG4gIGNvbnN0IG1lc3NhZ2VIb29rID0gYWdlbnRNZXNzYWdlSG9vay5jcmVhdGUoeyB0b2tlbjogaW5wdXQuc2Vzc2lvbklkIH0pO1xuICBjb25zdCBpdGVyYXRvciA9IG1lc3NhZ2VIb29rW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSgpO1xuICBsZXQgcGVuZGluZ05leHQgPSBpdGVyYXRvci5uZXh0KCk7XG5cbiAgYXdhaXQgb25NZXNzYWdlKHsgZXZlbnQsIGlucHV0IH0pLmNhdGNoKChlKSA9PiB7XG4gICAgaWYgKEZhdGFsRXJyb3IuaXMoZSkpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoXCJNZXNzYWdlIHByb2Nlc3NpbmcgZmFpbGVkIHBlcm1hbmVudGx5OlwiLCBlLm1lc3NhZ2UpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aHJvdyBlO1xuICB9KTtcblxuICB3aGlsZSAodHJ1ZSkge1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHBlbmRpbmdOZXh0O1xuXG4gICAgaWYgKHJlc3VsdC5kb25lKSB7XG4gICAgICBjb25zb2xlLmVycm9yKFwiVW5leHBlY3RlZDogbWVzc2FnZSBob29rIGl0ZXJhdG9yIGRvbmVcIik7XG4gICAgICBicmVhaztcbiAgICB9XG5cbiAgICBhd2FpdCBvbk1lc3NhZ2UoeyBldmVudDogcmVzdWx0LnZhbHVlLCBpbnB1dCB9KS5jYXRjaCgoZSkgPT4ge1xuICAgICAgaWYgKEZhdGFsRXJyb3IuaXMoZSkpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihcIk1lc3NhZ2UgcHJvY2Vzc2luZyBmYWlsZWQgcGVybWFuZW50bHk6XCIsIGUubWVzc2FnZSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHRocm93IGU7XG4gICAgfSk7XG4gICAgcGVuZGluZ05leHQgPSBpdGVyYXRvci5uZXh0KCk7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gb25NZXNzYWdlKHtcbiAgZXZlbnQsXG4gIGlucHV0LFxufToge1xuICBldmVudDogQWdlbnRNZXNzYWdlSW5wdXQ7XG4gIGlucHV0OiBBZ2VudElucHV0O1xufSkge1xuICBjb25zdCB3cml0YWJsZSA9IGdldFdyaXRhYmxlKHsgbmFtZXNwYWNlOiBldmVudC5hc3Npc3RhbnRNZXNzYWdlSWQgfSk7XG5cbiAgbGV0IGZpbmlzaFJlYXNvbjogRmluaXNoUmVhc29uIHwgdW5kZWZpbmVkO1xuICBsZXQgbGFzdFBhcnRJbmRleCA9IDA7XG5cbiAgd2hpbGUgKGZpbmlzaFJlYXNvbiAhPT0gXCJzdG9wXCIpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3RyZWFtVGV4dFN0ZXAoe1xuICAgICAgICBhc3Npc3RhbnRNZXNzYWdlSWQ6IGV2ZW50LmFzc2lzdGFudE1lc3NhZ2VJZCxcbiAgICAgICAgd3JpdGFibGUsXG4gICAgICAgIGlucHV0LFxuICAgICAgICBldmVudCxcbiAgICAgICAgbGFzdFBhcnRJbmRleCxcbiAgICAgIH0pO1xuICAgICAgZmluaXNoUmVhc29uID0gcmVzdWx0LmZpbmlzaFJlYXNvbjtcbiAgICAgIGxhc3RQYXJ0SW5kZXggPSByZXN1bHQubGFzdFBhcnRJbmRleDtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoZXJyKTtcbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gIH1cblxuICBhd2FpdCBjb21wbGV0ZU1lc3NhZ2VTdGVwKHtcbiAgICBhc3Npc3RhbnRNZXNzYWdlSWQ6IGV2ZW50LmFzc2lzdGFudE1lc3NhZ2VJZCxcbiAgICBpbnB1dCxcbiAgICB3cml0YWJsZSxcbiAgfSk7XG59XG4iLCAiaW1wb3J0IHtcbiAgY29udmVydFRvTW9kZWxNZXNzYWdlcyxcbiAgdHlwZSBGaW5pc2hSZWFzb24sXG4gIHN0cmVhbVRleHQsXG4gIHR5cGUgVUlNZXNzYWdlLFxufSBmcm9tIFwiYWlcIjtcbmltcG9ydCB7IHVsaWQgfSBmcm9tIFwidWxpZFwiO1xuaW1wb3J0IHsgRmF0YWxFcnJvciB9IGZyb20gXCJ3b3JrZmxvd1wiO1xuaW1wb3J0IHR5cGUgeyBNY3BTZXJ2ZXJTY2hlbWEgfSBmcm9tIFwiLi9tY3BcIjtcbmltcG9ydCB7IGRpc2NvdmVyU2tpbGxzSW5TYW5kYm94IH0gZnJvbSBcIi4vc2tpbGxzL2Rpc2NvdmVyXCI7XG5pbXBvcnQgdHlwZSB7IFNraWxsU3VtbWFyeSB9IGZyb20gXCIuL3NraWxscy90eXBlc1wiO1xuaW1wb3J0IHR5cGUgeyBTdG9yYWdlQ29uZmlnIH0gZnJvbSBcIi4vc3RvcmFnZVwiO1xuaW1wb3J0IHsgZ2V0VG9vbHMgfSBmcm9tIFwiLi90b29sc1wiO1xuaW1wb3J0IHsgYXNzZW1ibGVVSU1lc3NhZ2VzIH0gZnJvbSBcIi4vdXRpbHMvdWlcIjtcblxuY29uc3QgQkFTRV9TWVNURU1fUFJPTVBUID1cbiAgXCJZb3UgYXJlIGFuIEFJIGFzc2lzdGFudCB3aXRoIGJhc2ljIHRvb2xzIHRvIGludGVyYWN0IHdpdGggeW91ciBlbnZpcm9ubWVudC4gRXhwbG9yZSBhbmQgd29yayBmcmVlbHkuXCI7XG5cbmZ1bmN0aW9uIGpvaW5Qcm9tcHRTZWN0aW9ucyhcbiAgLi4uc2VjdGlvbnM6IChzdHJpbmcgfCB1bmRlZmluZWQgfCBudWxsKVtdXG4pOiBzdHJpbmcge1xuICByZXR1cm4gc2VjdGlvbnMuZmlsdGVyKChzKSA9PiBzPy50cmltKCkpLmpvaW4oXCJcXG5cXG5cIik7XG59XG5cbmZ1bmN0aW9uIGJ1aWxkU2tpbGxzQ29udGV4dChza2lsbHM6IFNraWxsU3VtbWFyeVtdKTogc3RyaW5nIHtcbiAgaWYgKHNraWxscy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gXCJcIjtcbiAgfVxuXG4gIGNvbnN0IHNraWxsTGluZXMgPSBza2lsbHNcbiAgICAubWFwKChzKSA9PiBgLSAke3MubmFtZX06ICR7cy5kZXNjcmlwdGlvbn1cXG4gIFBhdGg6ICR7cy5za2lsbE1kUGF0aH1gKVxuICAgIC5qb2luKFwiXFxuXCIpO1xuXG4gIHJldHVybiBgIyMgQXZhaWxhYmxlIFNraWxsc1xuJHtza2lsbExpbmVzfVxuXG5Zb3UgY2FuIHVzZSB0aGUgUmVhZCB0b29sIHRvIHJlYWQgYW55IHNraWxsJ3MgU0tJTEwubWQgZmlsZSB0byBsZWFybiBtb3JlIGFib3V0IGl0LmA7XG59XG5cbmZ1bmN0aW9uIGJ1aWxkTWNwVG9vbHNDb250ZXh0KG1jcDogTWNwU2VydmVyU2NoZW1hW10gfCBudWxsIHwgdW5kZWZpbmVkKTogc3RyaW5nIHtcbiAgaWYgKCFtY3AgfHwgbWNwLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBcIlwiO1xuICB9XG5cbiAgY29uc3Qgc2VydmVyRG9jcyA9IG1jcFxuICAgIC5maWx0ZXIoXG4gICAgICAoXG4gICAgICAgIHNcbiAgICAgICk6IHMgaXMgTWNwU2VydmVyU2NoZW1hICYge1xuICAgICAgICB0b29sczogTm9uTnVsbGFibGU8TWNwU2VydmVyU2NoZW1hW1widG9vbHNcIl0+O1xuICAgICAgfSA9PiBBcnJheS5pc0FycmF5KHMudG9vbHMpICYmIHMudG9vbHMubGVuZ3RoID4gMFxuICAgIClcbiAgICAubWFwKChzZXJ2ZXIpID0+IHtcbiAgICAgIGNvbnN0IHRvb2xEb2NzID0gc2VydmVyLnRvb2xzXG4gICAgICAgIC5tYXAoKHQpID0+IHtcbiAgICAgICAgICBsZXQgZG9jID0gYCAgLSAke3QubmFtZX06ICR7XG4gICAgICAgICAgICB0LmRlc2NyaXB0aW9uXG4gICAgICAgICAgfVxcbiAgICBJbnB1dDogJHtKU09OLnN0cmluZ2lmeSh0LmlucHV0U2NoZW1hKX1gO1xuICAgICAgICAgIGlmICh0Lm91dHB1dFNjaGVtYSkge1xuICAgICAgICAgICAgZG9jICs9IGBcXG4gICAgT3V0cHV0OiAke0pTT04uc3RyaW5naWZ5KHQub3V0cHV0U2NoZW1hKX1gO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gZG9jO1xuICAgICAgICB9KVxuICAgICAgICAuam9pbihcIlxcblwiKTtcbiAgICAgIHJldHVybiBgIyMjICR7c2VydmVyLm5hbWV9XFxuJHtzZXJ2ZXIuZGVzY3JpcHRpb24gPz8gXCJcIn1cXG4ke3Rvb2xEb2NzfWA7XG4gICAgfSlcbiAgICAuam9pbihcIlxcblxcblwiKTtcblxuICBpZiAoIXNlcnZlckRvY3MpIHtcbiAgICByZXR1cm4gXCJcIjtcbiAgfVxuXG4gIHJldHVybiBgIyMgTUNQIFRvb2xzXG5Vc2UgdGhlIEV4ZWN1dGVNQ1BUb29sIHRvIGNhbGwgdGhlc2UgY3VzdG9tIHRvb2xzOlxuXG4ke3NlcnZlckRvY3N9YDtcbn1cblxuZXhwb3J0IHR5cGUgQWdlbnRJbnB1dCA9IHtcbiAgc2Vzc2lvbklkOiBzdHJpbmc7XG4gIHN0b3JhZ2VDb25maWc6IFN0b3JhZ2VDb25maWc7XG59O1xuXG5leHBvcnQgdHlwZSBBZ2VudE1lc3NhZ2VJbnB1dCA9IHtcbiAgYXNzaXN0YW50TWVzc2FnZUlkOiBzdHJpbmc7XG4gIGhvb2tUb2tlbjogc3RyaW5nO1xufTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNvbXBsZXRlTWVzc2FnZVN0ZXAoe1xuICBhc3Npc3RhbnRNZXNzYWdlSWQsXG4gIGlucHV0LFxuICB3cml0YWJsZSxcbn06IHtcbiAgYXNzaXN0YW50TWVzc2FnZUlkOiBzdHJpbmc7XG4gIGlucHV0OiBBZ2VudElucHV0O1xuICB3cml0YWJsZTogV3JpdGFibGVTdHJlYW07XG59KSB7XG4gIFwidXNlIHN0ZXBcIjtcblxuICBjb25zdCB7IGdldFN0b3JhZ2UgfSA9IGF3YWl0IGltcG9ydChcIi4vc3RvcmFnZVwiKTtcbiAgY29uc3Qgc3RvcmFnZSA9IGdldFN0b3JhZ2UoaW5wdXQuc3RvcmFnZUNvbmZpZyk7XG5cbiAgY29uc3QgbWVzc2FnZSA9IGF3YWl0IHN0b3JhZ2UubWVzc2FnZS5nZXQoYXNzaXN0YW50TWVzc2FnZUlkKTtcbiAgaWYgKG1lc3NhZ2UgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgIHRocm93IG1lc3NhZ2U7XG4gIH1cbiAgaWYgKCFtZXNzYWdlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBNZXNzYWdlICR7YXNzaXN0YW50TWVzc2FnZUlkfSBub3QgZm91bmRgKTtcbiAgfVxuXG4gIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHN0b3JhZ2UubWVzc2FnZS5zZXQoe1xuICAgIC4uLm1lc3NhZ2UsXG4gICAgY29tcGxldGVkQXQ6IERhdGUubm93KCksXG4gIH0pO1xuICBpZiAocmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICB0aHJvdyByZXN1bHQ7XG4gIH1cblxuICBhd2FpdCB3cml0YWJsZS5jbG9zZSgpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc3RyZWFtVGV4dFN0ZXAoe1xuICBhc3Npc3RhbnRNZXNzYWdlSWQsXG4gIGlucHV0LFxuICBldmVudCxcbiAgd3JpdGFibGUsXG4gIGxhc3RQYXJ0SW5kZXgsXG59OiB7XG4gIGFzc2lzdGFudE1lc3NhZ2VJZDogc3RyaW5nO1xuICBpbnB1dDogQWdlbnRJbnB1dDtcbiAgZXZlbnQ6IEFnZW50TWVzc2FnZUlucHV0O1xuICB3cml0YWJsZTogV3JpdGFibGVTdHJlYW07XG4gIGxhc3RQYXJ0SW5kZXg6IG51bWJlcjtcbn0pOiBQcm9taXNlPHsgZmluaXNoUmVhc29uOiBGaW5pc2hSZWFzb247IGxhc3RQYXJ0SW5kZXg6IG51bWJlciB9PiB7XG4gIFwidXNlIHN0ZXBcIjtcblxuICBjb25zdCB7IGdldFN0b3JhZ2UgfSA9IGF3YWl0IGltcG9ydChcIi4vc3RvcmFnZS9jbGllbnRcIik7XG4gIGNvbnN0IHsgZ2V0U2FuZGJveCB9ID0gYXdhaXQgaW1wb3J0KFwiLi9zYW5kYm94XCIpO1xuXG4gIGNvbnN0IHN0b3JhZ2UgPSBnZXRTdG9yYWdlKGlucHV0LnN0b3JhZ2VDb25maWcpO1xuICBjb25zdCBzZXNzaW9uID0gYXdhaXQgc3RvcmFnZS5zZXNzaW9uLmdldChpbnB1dC5zZXNzaW9uSWQpO1xuXG4gIGlmIChzZXNzaW9uIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICB0aHJvdyBzZXNzaW9uO1xuICB9XG4gIHNlc3Npb247XG5cbiAgY29uc3Qgc2FuZGJveFJlY29yZCA9IHNlc3Npb24uc2FuZGJveElkXG4gICAgPyBhd2FpdCBzdG9yYWdlLnNhbmRib3guZ2V0KHNlc3Npb24uc2FuZGJveElkKVxuICAgIDogbnVsbDtcbiAgaWYgKHNhbmRib3hSZWNvcmQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgIHRocm93IHNhbmRib3hSZWNvcmQ7XG4gIH1cbiAgaWYgKCFzYW5kYm94UmVjb3JkKSB7XG4gICAgdGhyb3cgbmV3IEZhdGFsRXJyb3IoYFNhbmRib3ggbm90IGZvdW5kIGZvciBzZXNzaW9uICR7aW5wdXQuc2Vzc2lvbklkfWApO1xuICB9XG5cbiAgY29uc3Qgc2FuZGJveCA9IGdldFNhbmRib3goe1xuICAgIHNhbmRib3hSZWNvcmQsXG4gICAgc3RvcmFnZUNvbmZpZzogaW5wdXQuc3RvcmFnZUNvbmZpZyxcbiAgfSk7XG5cbiAgY29uc3QgW21lc3NhZ2VzUmVzdWx0LCBwYXJ0c1Jlc3VsdCwgc2tpbGxzXSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICBzdG9yYWdlLm1lc3NhZ2UubGlzdChpbnB1dC5zZXNzaW9uSWQpLFxuICAgIHN0b3JhZ2UucGFydC5saXN0QnlTZXNzaW9uKGlucHV0LnNlc3Npb25JZCksXG4gICAgc2Vzc2lvbi5za2lsbHNEaXIgJiYgc2Vzc2lvbi5za2lsbHNEaXIubGVuZ3RoID4gMFxuICAgICAgPyBkaXNjb3ZlclNraWxsc0luU2FuZGJveCh7IHNhbmRib3gsIHNraWxsc0RpcnM6IHNlc3Npb24uc2tpbGxzRGlyIH0pXG4gICAgICA6IFByb21pc2UucmVzb2x2ZShbXSksXG4gIF0pO1xuXG4gIGlmIChtZXNzYWdlc1Jlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgdGhyb3cgbWVzc2FnZXNSZXN1bHQ7XG4gIH1cbiAgaWYgKHBhcnRzUmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICB0aHJvdyBwYXJ0c1Jlc3VsdDtcbiAgfVxuXG4gIGNvbnN0IHVpTWVzc2FnZXMgPSBhc3NlbWJsZVVJTWVzc2FnZXMoe1xuICAgIG1lc3NhZ2VzOiBtZXNzYWdlc1Jlc3VsdC5pdGVtcyxcbiAgICBwYXJ0czogcGFydHNSZXN1bHQuaXRlbXMsXG4gIH0pO1xuXG4gIGNvbnN0IG1jcCA9IHNlc3Npb24ubWNwIGFzIE1jcFNlcnZlclNjaGVtYVtdIHwgbnVsbDtcblxuICBjb25zdCBzeXN0ZW1Qcm9tcHQgPSBqb2luUHJvbXB0U2VjdGlvbnMoXG4gICAgQkFTRV9TWVNURU1fUFJPTVBULFxuICAgIHNlc3Npb24uaW5zdHJ1Y3Rpb25zLFxuICAgIGJ1aWxkU2tpbGxzQ29udGV4dChza2lsbHMpLFxuICAgIGJ1aWxkTWNwVG9vbHNDb250ZXh0KG1jcClcbiAgKTtcblxuICBpZiAoIXNlc3Npb24ubW9kZWwpIHtcbiAgICB0aHJvdyBuZXcgRmF0YWxFcnJvcihcIlNlc3Npb24gbW9kZWwgaXMgbm90IHNldFwiKTtcbiAgfVxuXG4gIGNvbnN0IHJlc3VsdCA9IHN0cmVhbVRleHQoe1xuICAgIG1lc3NhZ2VzOiBhd2FpdCBjb252ZXJ0VG9Nb2RlbE1lc3NhZ2VzKHVpTWVzc2FnZXMpLFxuICAgIHRvb2xzOiBnZXRUb29scyh7IGlucHV0LCBldmVudCwgbWNwLCBzYW5kYm94IH0pLFxuICAgIHN5c3RlbTogc3lzdGVtUHJvbXB0LFxuICAgIG1vZGVsOiBzZXNzaW9uLm1vZGVsLFxuICB9KTtcblxuICBjb25zdCBzdGVwUGFydHM6IFVJTWVzc2FnZVtcInBhcnRzXCJdID0gW107XG4gIGF3YWl0IHJlc3VsdFxuICAgIC50b1VJTWVzc2FnZVN0cmVhbSh7XG4gICAgICBnZW5lcmF0ZU1lc3NhZ2VJZDogKCkgPT4gYXNzaXN0YW50TWVzc2FnZUlkLFxuICAgICAgb25GaW5pc2g6ICh7IG1lc3NhZ2VzIH0pID0+IHtcbiAgICAgICAgZm9yIChjb25zdCBtIG9mIG1lc3NhZ2VzKSB7XG4gICAgICAgICAgaWYgKG0ucm9sZSA9PT0gXCJhc3Npc3RhbnRcIikge1xuICAgICAgICAgICAgc3RlcFBhcnRzLnB1c2goLi4ubS5wYXJ0cyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9LFxuICAgIH0pXG4gICAgLnBpcGVUbyh3cml0YWJsZSwgeyBwcmV2ZW50Q2xvc2U6IHRydWUgfSk7XG5cbiAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgc3RlcFBhcnRzLm1hcChhc3luYyAodWlQYXJ0LCBpbmRleCkgPT4ge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3RvcmFnZS5wYXJ0LnNldCh7XG4gICAgICAgIGlkOiBgcGFydF8ke3VsaWQoKX1gLFxuICAgICAgICBpbmRleDogbGFzdFBhcnRJbmRleCArIGluZGV4LFxuICAgICAgICBtZXNzYWdlSWQ6IGFzc2lzdGFudE1lc3NhZ2VJZCxcbiAgICAgICAgc2Vzc2lvbklkOiBpbnB1dC5zZXNzaW9uSWQsXG4gICAgICAgIHBhcnQ6IHVpUGFydCxcbiAgICAgIH0pO1xuICAgICAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHRocm93IHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSlcbiAgKTtcblxuICByZXR1cm4ge1xuICAgIGZpbmlzaFJlYXNvbjogYXdhaXQgcmVzdWx0LmZpbmlzaFJlYXNvbixcbiAgICBsYXN0UGFydEluZGV4OiBsYXN0UGFydEluZGV4ICsgc3RlcFBhcnRzLmxlbmd0aCxcbiAgfTtcbn1cbiIsICJpbXBvcnQgdHlwZSB7IFNraWxsc0RpciB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbi8qKlxuICogUGFyc2VkIGZyb250bWF0dGVyIGZyb20gYSBTS0lMTC5tZCBmaWxlLlxuICovXG5leHBvcnQgdHlwZSBTa2lsbEZyb250bWF0dGVyID0ge1xuICBuYW1lOiBzdHJpbmc7XG4gIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG59O1xuXG4vKipcbiAqIFBhcnNlcyBZQU1MIGZyb250bWF0dGVyIGZyb20gYSBTS0lMTC5tZCBmaWxlIGNvbnRlbnQuXG4gKiBGcm9udG1hdHRlciBtdXN0IGJlIGF0IHRoZSBzdGFydCBvZiB0aGUgZmlsZSwgZGVsaW1pdGVkIGJ5IGAtLS1gIG1hcmtlcnMuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYG1hcmtkb3duXG4gKiAtLS1cbiAqIG5hbWU6IGNzdlxuICogZGVzY3JpcHRpb246IEFuYWx5emUgQ1NWIGRhdGFcbiAqIC0tLVxuICogIyBDU1YgU2tpbGxcbiAqIC4uLlxuICogYGBgXG4gKlxuICogQHJldHVybnMgUGFyc2VkIG5hbWUgYW5kIGRlc2NyaXB0aW9uLCBvciBudWxsIGlmIGZyb250bWF0dGVyIGlzIG1pc3NpbmcvaW52YWxpZFxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VTa2lsbEZyb250bWF0dGVyKFxuICBjb250ZW50OiBzdHJpbmdcbik6IFNraWxsRnJvbnRtYXR0ZXIgfCBudWxsIHtcbiAgY29uc3QgdHJpbW1lZCA9IGNvbnRlbnQudHJpbSgpO1xuXG4gIGlmICghdHJpbW1lZC5zdGFydHNXaXRoKFwiLS0tXCIpKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCBlbmRNYXJrZXJJbmRleCA9IHRyaW1tZWQuaW5kZXhPZihcIi0tLVwiLCAzKTtcbiAgaWYgKGVuZE1hcmtlckluZGV4ID09PSAtMSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgZnJvbnRtYXR0ZXJCbG9jayA9IHRyaW1tZWQuc2xpY2UoMywgZW5kTWFya2VySW5kZXgpLnRyaW0oKTtcbiAgY29uc3QgcGFyc2VkID0gcGFyc2VTaW1wbGVZYW1sKGZyb250bWF0dGVyQmxvY2spO1xuXG4gIGlmICghKHBhcnNlZC5uYW1lICYmIHBhcnNlZC5kZXNjcmlwdGlvbikpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgbmFtZTogU3RyaW5nKHBhcnNlZC5uYW1lKSxcbiAgICBkZXNjcmlwdGlvbjogU3RyaW5nKHBhcnNlZC5kZXNjcmlwdGlvbiksXG4gIH07XG59XG5cbi8qKlxuICogUGFyc2VzIHNpbXBsZSBZQU1MIGtleS12YWx1ZSBwYWlycyAoc2luZ2xlLWxpbmUgdmFsdWVzIG9ubHkpLlxuICogVGhpcyBhdm9pZHMgYWRkaW5nIGEgZnVsbCBZQU1MIHBhcnNlciBkZXBlbmRlbmN5IGZvciBiYXNpYyBmcm9udG1hdHRlci5cbiAqL1xuZnVuY3Rpb24gcGFyc2VTaW1wbGVZYW1sKHlhbWw6IHN0cmluZyk6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4ge1xuICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcblxuICBmb3IgKGNvbnN0IGxpbmUgb2YgeWFtbC5zcGxpdChcIlxcblwiKSkge1xuICAgIGNvbnN0IHRyaW1tZWRMaW5lID0gbGluZS50cmltKCk7XG4gICAgaWYgKCF0cmltbWVkTGluZSB8fCB0cmltbWVkTGluZS5zdGFydHNXaXRoKFwiI1wiKSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgY29uc3QgY29sb25JbmRleCA9IHRyaW1tZWRMaW5lLmluZGV4T2YoXCI6XCIpO1xuICAgIGlmIChjb2xvbkluZGV4ID09PSAtMSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgY29uc3Qga2V5ID0gdHJpbW1lZExpbmUuc2xpY2UoMCwgY29sb25JbmRleCkudHJpbSgpO1xuICAgIGxldCB2YWx1ZSA9IHRyaW1tZWRMaW5lLnNsaWNlKGNvbG9uSW5kZXggKyAxKS50cmltKCk7XG5cbiAgICAvLyBSZW1vdmUgc3Vycm91bmRpbmcgcXVvdGVzIGlmIHByZXNlbnRcbiAgICBpZiAoXG4gICAgICAodmFsdWUuc3RhcnRzV2l0aCgnXCInKSAmJiB2YWx1ZS5lbmRzV2l0aCgnXCInKSkgfHxcbiAgICAgICh2YWx1ZS5zdGFydHNXaXRoKFwiJ1wiKSAmJiB2YWx1ZS5lbmRzV2l0aChcIidcIikpXG4gICAgKSB7XG4gICAgICB2YWx1ZSA9IHZhbHVlLnNsaWNlKDEsIC0xKTtcbiAgICB9XG5cbiAgICBpZiAoa2V5KSB7XG4gICAgICByZXN1bHRba2V5XSA9IHZhbHVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogTm9ybWFsaXplcyBza2lsbHNEaXIgdG8gYW4gYXJyYXkgb2Ygc3RyaW5ncy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG5vcm1hbGl6ZVNraWxsc0RpcnMoc2tpbGxzRGlyPzogU2tpbGxzRGlyKTogc3RyaW5nW10ge1xuICBpZiAoIXNraWxsc0Rpcikge1xuICAgIHJldHVybiBbXTtcbiAgfVxuICByZXR1cm4gQXJyYXkuaXNBcnJheShza2lsbHNEaXIpID8gc2tpbGxzRGlyIDogW3NraWxsc0Rpcl07XG59XG4iLCAiaW1wb3J0IHR5cGUgeyBTYW5kYm94IH0gZnJvbSBcIi4uL3NhbmRib3hcIjtcbmltcG9ydCB7IHBhcnNlU2tpbGxGcm9udG1hdHRlciB9IGZyb20gXCIuL3BhcnNlclwiO1xuaW1wb3J0IHR5cGUgeyBTa2lsbFN1bW1hcnkgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG4vKipcbiAqIERpc2NvdmVycyBza2lsbHMgZnJvbSBkaXJlY3RvcmllcyBpbnNpZGUgdGhlIHNhbmRib3ggYnkgZmluZGluZyBhbmQgcGFyc2luZyBTS0lMTC5tZCBmaWxlcy5cbiAqIFNjYW5zIGVhY2ggZGlyZWN0b3J5IGZvciBzdWJkaXJlY3RvcmllcyBjb250YWluaW5nIFNLSUxMLm1kLCBleHRyYWN0cyBmcm9udG1hdHRlciBtZXRhZGF0YSxcbiAqIGFuZCByZXR1cm5zIHN1bW1hcmllcyBmb3IgdXNlIGluIHRoZSBzeXN0ZW0gcHJvbXB0LlxuICpcbiAqIEByZXR1cm5zIEFycmF5IG9mIHNraWxsIHN1bW1hcmllcyAoZGVkdXBsaWNhdGVkIGJ5IG5hbWUsIGZpcnN0IG9jY3VycmVuY2Ugd2lucylcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRpc2NvdmVyU2tpbGxzSW5TYW5kYm94KG9wdHM6IHtcbiAgc2FuZGJveDogU2FuZGJveDtcbiAgc2tpbGxzRGlyczogc3RyaW5nW107XG4gIGRlYnVnPzogYm9vbGVhbjtcbn0pOiBQcm9taXNlPFNraWxsU3VtbWFyeVtdPiB7XG4gIGNvbnN0IHsgc2FuZGJveCwgc2tpbGxzRGlycywgZGVidWcgfSA9IG9wdHM7XG4gIGNvbnN0IHN1bW1hcmllczogU2tpbGxTdW1tYXJ5W10gPSBbXTtcbiAgY29uc3Qgc2Vlbk5hbWVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgZm9yIChjb25zdCBza2lsbHNEaXIgb2Ygc2tpbGxzRGlycykge1xuICAgIGNvbnN0IGRpclN1bW1hcmllcyA9IGF3YWl0IGRpc2NvdmVyU2tpbGxzSW5EaXJlY3Rvcnkoe1xuICAgICAgc2FuZGJveCxcbiAgICAgIHNraWxsc0RpcixcbiAgICAgIGRlYnVnLFxuICAgIH0pO1xuXG4gICAgZm9yIChjb25zdCBzdW1tYXJ5IG9mIGRpclN1bW1hcmllcykge1xuICAgICAgaWYgKCFzZWVuTmFtZXMuaGFzKHN1bW1hcnkubmFtZSkpIHtcbiAgICAgICAgc2Vlbk5hbWVzLmFkZChzdW1tYXJ5Lm5hbWUpO1xuICAgICAgICBzdW1tYXJpZXMucHVzaChzdW1tYXJ5KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gc3VtbWFyaWVzO1xufVxuXG5hc3luYyBmdW5jdGlvbiBkaXNjb3ZlclNraWxsc0luRGlyZWN0b3J5KG9wdHM6IHtcbiAgc2FuZGJveDogU2FuZGJveDtcbiAgc2tpbGxzRGlyOiBzdHJpbmc7XG4gIGRlYnVnPzogYm9vbGVhbjtcbn0pOiBQcm9taXNlPFNraWxsU3VtbWFyeVtdPiB7XG4gIGNvbnN0IHsgc2FuZGJveCwgc2tpbGxzRGlyLCBkZWJ1ZyB9ID0gb3B0cztcbiAgY29uc3Qgc2tpbGxQYXRocyA9IGF3YWl0IGZpbmRTa2lsbEZpbGVzKHsgc2FuZGJveCwgc2tpbGxzRGlyLCBkZWJ1ZyB9KTtcblxuICBpZiAoc2tpbGxQYXRocy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBjb25zdCBzdW1tYXJpZXM6IFNraWxsU3VtbWFyeVtdID0gW107XG5cbiAgZm9yIChjb25zdCBza2lsbE1kUGF0aCBvZiBza2lsbFBhdGhzKSB7XG4gICAgY29uc3Qgc3VtbWFyeSA9IGF3YWl0IHBhcnNlU2tpbGxGaWxlKHsgc2FuZGJveCwgc2tpbGxNZFBhdGgsIGRlYnVnIH0pO1xuICAgIGlmIChzdW1tYXJ5KSB7XG4gICAgICBzdW1tYXJpZXMucHVzaChzdW1tYXJ5KTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gc3VtbWFyaWVzO1xufVxuXG5hc3luYyBmdW5jdGlvbiBmaW5kU2tpbGxGaWxlcyhvcHRzOiB7XG4gIHNhbmRib3g6IFNhbmRib3g7XG4gIHNraWxsc0Rpcjogc3RyaW5nO1xuICBkZWJ1Zz86IGJvb2xlYW47XG59KTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICBjb25zdCB7IHNhbmRib3gsIHNraWxsc0RpciwgZGVidWcgfSA9IG9wdHM7XG4gIGlmIChkZWJ1Zykge1xuICAgIGNvbnNvbGUubG9nKGBbZGlzY292ZXJdIEZpbmRpbmcgc2tpbGxzIGluOiAke3NraWxsc0Rpcn1gKTtcbiAgfVxuICBjb25zdCBleGVjUmVzdWx0ID0gYXdhaXQgc2FuZGJveC5leGVjKHtcbiAgICBjb21tYW5kOiBcImZpbmRcIixcbiAgICBhcmdzOiBbc2tpbGxzRGlyLCBcIi1uYW1lXCIsIFwiU0tJTEwubWRcIiwgXCItdHlwZVwiLCBcImZcIl0sXG4gIH0pO1xuXG4gIGlmIChleGVjUmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICBpZiAoZGVidWcpIHtcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgYFtkaXNjb3Zlcl0gRmFpbGVkIHRvIHNjYW4gc2tpbGxzIGRpcmVjdG9yeSBcIiR7c2tpbGxzRGlyfVwiOiAke2V4ZWNSZXN1bHQubWVzc2FnZX1gXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gW107XG4gIH1cblxuICBjb25zdCB7IHN0ZG91dCwgc3RkZXJyLCBleGl0Q29kZSB9ID0gYXdhaXQgZXhlY1Jlc3VsdC5yZXN1bHQ7XG4gIGlmIChkZWJ1Zykge1xuICAgIGNvbnNvbGUubG9nKFxuICAgICAgYFtkaXNjb3Zlcl0gZmluZCByZXN1bHQ6IGV4aXRDb2RlPSR7ZXhpdENvZGV9LCBzdGRvdXQ9XCIke3N0ZG91dC50cmltKCl9XCIsIHN0ZGVycj1cIiR7c3RkZXJyLnRyaW0oKX1cImBcbiAgICApO1xuICB9XG5cbiAgaWYgKGV4aXRDb2RlICE9PSAwKSB7XG4gICAgaWYgKGRlYnVnKSB7XG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgIGBbZGlzY292ZXJdIFNraWxscyBkaXJlY3Rvcnkgbm90IGZvdW5kIG9yIGluYWNjZXNzaWJsZTogJHtza2lsbHNEaXJ9YFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgY29uc3QgcGF0aHMgPSBzdGRvdXRcbiAgICAudHJpbSgpXG4gICAgLnNwbGl0KFwiXFxuXCIpXG4gICAgLmZpbHRlcigocCkgPT4gcC5sZW5ndGggPiAwKTtcbiAgaWYgKGRlYnVnKSB7XG4gICAgY29uc29sZS5sb2coXCJbZGlzY292ZXJdIEZvdW5kIHNraWxsIHBhdGhzOlwiLCBwYXRocyk7XG4gIH1cbiAgcmV0dXJuIHBhdGhzO1xufVxuXG5hc3luYyBmdW5jdGlvbiBwYXJzZVNraWxsRmlsZShvcHRzOiB7XG4gIHNhbmRib3g6IFNhbmRib3g7XG4gIHNraWxsTWRQYXRoOiBzdHJpbmc7XG4gIGRlYnVnPzogYm9vbGVhbjtcbn0pOiBQcm9taXNlPFNraWxsU3VtbWFyeSB8IG51bGw+IHtcbiAgY29uc3QgeyBzYW5kYm94LCBza2lsbE1kUGF0aCwgZGVidWcgfSA9IG9wdHM7XG4gIGNvbnN0IGV4ZWNSZXN1bHQgPSBhd2FpdCBzYW5kYm94LmV4ZWMoe1xuICAgIGNvbW1hbmQ6IFwiY2F0XCIsXG4gICAgYXJnczogW3NraWxsTWRQYXRoXSxcbiAgfSk7XG5cbiAgaWYgKGV4ZWNSZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgIGlmIChkZWJ1Zykge1xuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBgW2Rpc2NvdmVyXSBGYWlsZWQgdG8gcmVhZCBza2lsbCBmaWxlIFwiJHtza2lsbE1kUGF0aH1cIjogJHtleGVjUmVzdWx0Lm1lc3NhZ2V9YFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCB7IHN0ZG91dCwgZXhpdENvZGUgfSA9IGF3YWl0IGV4ZWNSZXN1bHQucmVzdWx0O1xuXG4gIGlmIChleGl0Q29kZSAhPT0gMCkge1xuICAgIGlmIChkZWJ1Zykge1xuICAgICAgY29uc29sZS53YXJuKGBbZGlzY292ZXJdIENvdWxkIG5vdCByZWFkIHNraWxsIGZpbGU6ICR7c2tpbGxNZFBhdGh9YCk7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgcGFyc2VkID0gcGFyc2VTa2lsbEZyb250bWF0dGVyKHN0ZG91dCk7XG5cbiAgaWYgKCFwYXJzZWQpIHtcbiAgICBpZiAoZGVidWcpIHtcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgYFtkaXNjb3Zlcl0gSW52YWxpZCBvciBtaXNzaW5nIGZyb250bWF0dGVyIGluOiAke3NraWxsTWRQYXRofWBcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiBwYXJzZWQubmFtZSxcbiAgICBkZXNjcmlwdGlvbjogcGFyc2VkLmRlc2NyaXB0aW9uLFxuICAgIHNraWxsTWRQYXRoLFxuICB9O1xufVxuIiwgImltcG9ydCB7IHR5cGUgVG9vbFNldCwgdG9vbCB9IGZyb20gXCJhaVwiO1xuaW1wb3J0IHsgeiB9IGZyb20gXCJ6b2RcIjtcbmltcG9ydCB0eXBlIHsgQWdlbnRJbnB1dCwgQWdlbnRNZXNzYWdlSW5wdXQgfSBmcm9tIFwiLi4vYWdlbnQtd29ya2Zsb3dcIjtcbmltcG9ydCB0eXBlIHsgTWNwU2VydmVyU2NoZW1hIH0gZnJvbSBcIi4uL21jcFwiO1xuaW1wb3J0IHR5cGUgeyBTYW5kYm94IH0gZnJvbSBcIi4uL3NhbmRib3hcIjtcblxuZXhwb3J0IHR5cGUgVG9vbENvbnRleHQgPSB7XG4gIGlucHV0OiBBZ2VudElucHV0O1xuICBldmVudDogQWdlbnRNZXNzYWdlSW5wdXQ7XG4gIG1jcDogTWNwU2VydmVyU2NoZW1hW10gfCBudWxsO1xuICBzYW5kYm94OiBTYW5kYm94O1xuICB3YWl0VW50aWw/OiAocHJvbWlzZTogUHJvbWlzZTx1bmtub3duPikgPT4gdm9pZDtcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRUb29scyhjb250ZXh0OiBUb29sQ29udGV4dCkge1xuICByZXR1cm4ge1xuICAgIFJlYWQ6IHRvb2woe1xuICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgIFwiUmVhZHMgYSBmaWxlIGFuZCByZXR1cm5zIGl0cyBjb250ZW50cyB3aXRoIG1ldGFkYXRhLiBGb3IgZmlsZXMgb3ZlciAyMDAgbGluZXMsIGF1dG9tYXRpY2FsbHkgc2hvd3MgZmlyc3QgMTAwIGxpbmVzIHVubGVzcyBhIHNwZWNpZmljIGxpbmUgcmFuZ2UgaXMgcHJvdmlkZWQuIFVzZSBzdGFydExpbmUgYW5kIGVuZExpbmUgcGFyYW1ldGVycyB0byByZWFkIHNwZWNpZmljIHBvcnRpb25zIG9mIGxhcmdlIGZpbGVzLlwiLFxuICAgICAgaW5wdXRTY2hlbWE6IHoub2JqZWN0KHtcbiAgICAgICAgcGF0aDogelxuICAgICAgICAgIC5zdHJpbmcoKVxuICAgICAgICAgIC5kZXNjcmliZShcIlBhdGggdG8gdGhlIGZpbGUgcmVsYXRpdmUgdG8gd29ya3NwYWNlIHJvb3RcIiksXG4gICAgICAgIHN0YXJ0TGluZTogelxuICAgICAgICAgIC5udW1iZXIoKVxuICAgICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgICAgLmRlc2NyaWJlKFxuICAgICAgICAgICAgXCJTdGFydGluZyBsaW5lIG51bWJlciAoMS1pbmRleGVkKS4gSWYgcHJvdmlkZWQgd2l0aCBlbmRMaW5lLCByZWFkcyBleGFjdCByYW5nZSByZWdhcmRsZXNzIG9mIGZpbGUgc2l6ZS5cIlxuICAgICAgICAgICksXG4gICAgICAgIGVuZExpbmU6IHpcbiAgICAgICAgICAubnVtYmVyKClcbiAgICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAgIC5kZXNjcmliZShcbiAgICAgICAgICAgIFwiRW5kaW5nIGxpbmUgbnVtYmVyICgxLWluZGV4ZWQsIGluY2x1c2l2ZSkuIElmIHByb3ZpZGVkIHdpdGggc3RhcnRMaW5lLCByZWFkcyBleGFjdCByYW5nZSByZWdhcmRsZXNzIG9mIGZpbGUgc2l6ZS5cIlxuICAgICAgICAgICksXG4gICAgICB9KSxcbiAgICAgIG91dHB1dFNjaGVtYTogei5vYmplY3Qoe1xuICAgICAgICBjb250ZW50OiB6LnN0cmluZygpLmRlc2NyaWJlKFwiRmlsZSBjb250ZW50XCIpLFxuICAgICAgICBtZXRhZGF0YTogei5vYmplY3Qoe1xuICAgICAgICAgIHRvdGFsTGluZXM6IHoubnVtYmVyKCkuZGVzY3JpYmUoXCJUb3RhbCBudW1iZXIgb2YgbGluZXMgaW4gdGhlIGZpbGVcIiksXG4gICAgICAgICAgbGluZXNTaG93bjogelxuICAgICAgICAgICAgLm51bWJlcigpXG4gICAgICAgICAgICAuZGVzY3JpYmUoXCJOdW1iZXIgb2YgbGluZXMgaW5jbHVkZWQgaW4gdGhpcyByZXNwb25zZVwiKSxcbiAgICAgICAgICBzdGFydExpbmU6IHoubnVtYmVyKCkuZGVzY3JpYmUoXCJGaXJzdCBsaW5lIG51bWJlciBzaG93biAoMS1pbmRleGVkKVwiKSxcbiAgICAgICAgICBlbmRMaW5lOiB6Lm51bWJlcigpLmRlc2NyaWJlKFwiTGFzdCBsaW5lIG51bWJlciBzaG93biAoMS1pbmRleGVkKVwiKSxcbiAgICAgICAgICBpc1BhZ2luYXRlZDogelxuICAgICAgICAgICAgLmJvb2xlYW4oKVxuICAgICAgICAgICAgLmRlc2NyaWJlKFwiV2hldGhlciB0aGlzIGlzIGEgcGFydGlhbCB2aWV3IG9mIHRoZSBmaWxlXCIpLFxuICAgICAgICAgIGZpbGVTaXplOiB6XG4gICAgICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgICAgIC5kZXNjcmliZShcIkh1bWFuLXJlYWRhYmxlIGZpbGUgc2l6ZSAoZS5nLiwgJzIuNUsnLCAnMS4yTScpXCIpLFxuICAgICAgICAgIHBhdGg6IHpcbiAgICAgICAgICAgIC5zdHJpbmcoKVxuICAgICAgICAgICAgLmRlc2NyaWJlKFwiUGF0aCB0byB0aGUgZmlsZSByZWxhdGl2ZSB0byB3b3Jrc3BhY2Ugcm9vdFwiKSxcbiAgICAgICAgfSksXG4gICAgICB9KSxcbiAgICAgIGV4ZWN1dGU6IGFzeW5jICh7IHBhdGgsIHN0YXJ0TGluZSwgZW5kTGluZSB9KSA9PiB7XG4gICAgICAgIGNvbnN0IGZpbGVQYXRoID0gcGF0aC5zdGFydHNXaXRoKFwiL1wiKSA/IHBhdGguc2xpY2UoMSkgOiBwYXRoO1xuXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnRleHQuc2FuZGJveC5leGVjKHtcbiAgICAgICAgICBjb21tYW5kOiBcImJhc2hcIixcbiAgICAgICAgICBhcmdzOiBbXG4gICAgICAgICAgICBcIi1jXCIsXG4gICAgICAgICAgICBgXG4gICAgICAgICAgICBzZXQgLWVcbiAgICAgICAgICAgIEZJTEU9XCIkMVwiXG4gICAgICAgICAgICBTVEFSVF9MSU5FPVwiJDJcIlxuICAgICAgICAgICAgRU5EX0xJTkU9XCIkM1wiXG5cbiAgICAgICAgICAgICMgUmVzb2x2ZSBzeW1saW5rcyBhbmQgY2hlY2sgZmlsZSBleGlzdHNcbiAgICAgICAgICAgIGlmIFsgLUwgXCIkRklMRVwiIF07IHRoZW5cbiAgICAgICAgICAgICAgUkVTT0xWRUQ9JChyZWFkbGluayAtZiBcIiRGSUxFXCIgMj4vZGV2L251bGwgfHwgZWNobyBcIlwiKVxuICAgICAgICAgICAgICBpZiBbIC16IFwiJFJFU09MVkVEXCIgXSB8fCBbICEgLWUgXCIkUkVTT0xWRURcIiBdOyB0aGVuXG4gICAgICAgICAgICAgICAgZWNobyBcIkVycm9yOiBCcm9rZW4gc3ltbGluayAtICRGSUxFIHBvaW50cyB0byBub24tZXhpc3RlbnQgdGFyZ2V0XCIgPiYyXG4gICAgICAgICAgICAgICAgZXhpdCAxXG4gICAgICAgICAgICAgIGZpXG4gICAgICAgICAgICAgIEZJTEU9XCIkUkVTT0xWRURcIlxuICAgICAgICAgICAgZWxpZiBbICEgLWUgXCIkRklMRVwiIF07IHRoZW5cbiAgICAgICAgICAgICAgZWNobyBcIkVycm9yOiBGaWxlIG5vdCBmb3VuZCAtICRGSUxFXCIgPiYyXG4gICAgICAgICAgICAgIGV4aXQgMVxuICAgICAgICAgICAgZmlcblxuICAgICAgICAgICAgIyBHZXQgbWV0YWRhdGEgKGNvdW50IGFjdHVhbCBsaW5lcywgbm90IGp1c3QgbmV3bGluZXMpXG4gICAgICAgICAgICBUT1RBTF9MSU5FUz0kKGF3ayAnRU5Ee3ByaW50IE5SfScgXCIkRklMRVwiKVxuICAgICAgICAgICAgRklMRV9TSVpFPSQobHMgLWxoIFwiJEZJTEVcIiB8IGF3ayAne3ByaW50ICQ1fScpXG5cbiAgICAgICAgICAgICMgRGV0ZXJtaW5lIHJhbmdlXG4gICAgICAgICAgICBQQUdFX1NJWkU9MTAwXG4gICAgICAgICAgICBpZiBbIC1uIFwiJFNUQVJUX0xJTkVcIiBdICYmIFsgLW4gXCIkRU5EX0xJTkVcIiBdOyB0aGVuXG4gICAgICAgICAgICAgICMgQm90aCBwcm92aWRlZCAtIHVzZSBleGFjdCByYW5nZVxuICAgICAgICAgICAgICBBQ1RVQUxfU1RBUlQ9JFNUQVJUX0xJTkVcbiAgICAgICAgICAgICAgQUNUVUFMX0VORD0kRU5EX0xJTkVcbiAgICAgICAgICAgIGVsaWYgWyAtbiBcIiRTVEFSVF9MSU5FXCIgXTsgdGhlblxuICAgICAgICAgICAgICAjIE9ubHkgc3RhcnRMaW5lIC0gcmVhZCBQQUdFX1NJWkUgbGluZXMgZnJvbSB0aGVyZVxuICAgICAgICAgICAgICBBQ1RVQUxfU1RBUlQ9JFNUQVJUX0xJTkVcbiAgICAgICAgICAgICAgQUNUVUFMX0VORD0kKChTVEFSVF9MSU5FICsgUEFHRV9TSVpFIC0gMSkpXG4gICAgICAgICAgICAgIFsgXCIkQUNUVUFMX0VORFwiIC1ndCBcIiRUT1RBTF9MSU5FU1wiIF0gJiYgQUNUVUFMX0VORD0kVE9UQUxfTElORVNcbiAgICAgICAgICAgIGVsaWYgWyAtbiBcIiRFTkRfTElORVwiIF07IHRoZW5cbiAgICAgICAgICAgICAgIyBPbmx5IGVuZExpbmUgLSByZWFkIGZyb20gYmVnaW5uaW5nIHRvIGVuZExpbmVcbiAgICAgICAgICAgICAgQUNUVUFMX1NUQVJUPTFcbiAgICAgICAgICAgICAgQUNUVUFMX0VORD0kRU5EX0xJTkVcbiAgICAgICAgICAgIGVsaWYgWyBcIiRUT1RBTF9MSU5FU1wiIC1ndCAyMDAgXTsgdGhlblxuICAgICAgICAgICAgICAjIE5vIHJhbmdlLCBsYXJnZSBmaWxlIC0gcGFnaW5hdGVcbiAgICAgICAgICAgICAgQUNUVUFMX1NUQVJUPTFcbiAgICAgICAgICAgICAgQUNUVUFMX0VORD0kUEFHRV9TSVpFXG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICMgTm8gcmFuZ2UsIHNtYWxsIGZpbGUgLSBzaG93IGFsbFxuICAgICAgICAgICAgICBBQ1RVQUxfU1RBUlQ9MVxuICAgICAgICAgICAgICBBQ1RVQUxfRU5EPSRUT1RBTF9MSU5FU1xuICAgICAgICAgICAgZmlcblxuICAgICAgICAgICAgIyBPdXRwdXQgbWV0YWRhdGEgZmlyc3QgKHNlcGFyYXRlZCBieSB8fHwgZm9yIHBhcnNpbmcpXG4gICAgICAgICAgICBlY2hvIFwiJFRPVEFMX0xJTkVTfCRGSUxFX1NJWkV8JEFDVFVBTF9TVEFSVHwkQUNUVUFMX0VORFwiXG4gICAgICAgICAgICBlY2hvIFwifHx8Q09OVEVOVHx8fFwiXG5cbiAgICAgICAgICAgICMgUmVhZCBjb250ZW50XG4gICAgICAgICAgICBpZiBbIFwiJEFDVFVBTF9TVEFSVFwiIC1lcSAxIF0gJiYgWyBcIiRBQ1RVQUxfRU5EXCIgLWVxIFwiJFRPVEFMX0xJTkVTXCIgXTsgdGhlblxuICAgICAgICAgICAgICBjYXQgXCIkRklMRVwiXG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgIHNlZCAtbiBcIlxcJHtBQ1RVQUxfU1RBUlR9LFxcJHtBQ1RVQUxfRU5EfXBcIiBcIiRGSUxFXCJcbiAgICAgICAgICAgIGZpXG4gICAgICAgICAgYCxcbiAgICAgICAgICAgIFwiLS1cIixcbiAgICAgICAgICAgIGZpbGVQYXRoLFxuICAgICAgICAgICAgc3RhcnRMaW5lPy50b1N0cmluZygpIHx8IFwiXCIsXG4gICAgICAgICAgICBlbmRMaW5lPy50b1N0cmluZygpIHx8IFwiXCIsXG4gICAgICAgICAgXSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihcIltSZWFkIFRvb2xdXCIsIHJlc3VsdCk7XG4gICAgICAgICAgdGhyb3cgcmVzdWx0O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgeyBzdGRvdXQsIHN0ZGVyciB9ID0gYXdhaXQgcmVzdWx0LnJlc3VsdDtcblxuICAgICAgICBpZiAoc3RkZXJyKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihgW1JlYWQgVG9vbF0gRXJyb3I6ICR7c3RkZXJyfWApO1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBjb250ZW50OiBgRXJyb3I6ICR7c3RkZXJyfWAsXG4gICAgICAgICAgICBtZXRhZGF0YToge1xuICAgICAgICAgICAgICB0b3RhbExpbmVzOiAwLFxuICAgICAgICAgICAgICBsaW5lc1Nob3duOiAwLFxuICAgICAgICAgICAgICBzdGFydExpbmU6IDAsXG4gICAgICAgICAgICAgIGVuZExpbmU6IDAsXG4gICAgICAgICAgICAgIGlzUGFnaW5hdGVkOiBmYWxzZSxcbiAgICAgICAgICAgICAgZmlsZVNpemU6IFwiMFwiLFxuICAgICAgICAgICAgICBwYXRoOiBmaWxlUGF0aCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IFttZXRhZGF0YUxpbmUsIC4uLnJlc3RdID0gc3Rkb3V0LnNwbGl0KFwifHx8Q09OVEVOVHx8fFwiKTtcbiAgICAgICAgY29uc3QgY29udGVudCA9IHJlc3Quam9pbihcInx8fENPTlRFTlR8fHxcIikudHJpbVN0YXJ0KCk7XG4gICAgICAgIGNvbnN0IFt0b3RhbExpbmVzU3RyLCBmaWxlU2l6ZSwgYWN0dWFsU3RhcnRTdHIsIGFjdHVhbEVuZFN0cl0gPVxuICAgICAgICAgIG1ldGFkYXRhTGluZS50cmltKCkuc3BsaXQoXCJ8XCIpO1xuXG4gICAgICAgIGNvbnN0IHRvdGFsTGluZXMgPSBOdW1iZXIucGFyc2VJbnQodG90YWxMaW5lc1N0ciwgMTApO1xuICAgICAgICBjb25zdCBhY3R1YWxTdGFydCA9IE51bWJlci5wYXJzZUludChhY3R1YWxTdGFydFN0ciwgMTApO1xuICAgICAgICBjb25zdCBhY3R1YWxFbmQgPSBOdW1iZXIucGFyc2VJbnQoYWN0dWFsRW5kU3RyLCAxMCk7XG5cbiAgICAgICAgaWYgKFxuICAgICAgICAgIE51bWJlci5pc05hTih0b3RhbExpbmVzKSB8fFxuICAgICAgICAgIE51bWJlci5pc05hTihhY3R1YWxTdGFydCkgfHxcbiAgICAgICAgICBOdW1iZXIuaXNOYU4oYWN0dWFsRW5kKVxuICAgICAgICApIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKFxuICAgICAgICAgICAgYFtSZWFkIFRvb2xdIEZhaWxlZCB0byBwYXJzZSBtZXRhZGF0YTogJHttZXRhZGF0YUxpbmV9YFxuICAgICAgICAgICk7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGNvbnRlbnQ6IGBFcnJvcjogRmFpbGVkIHRvIHBhcnNlIGZpbGUgbWV0YWRhdGEuIFJhdyBvdXRwdXQ6ICR7c3Rkb3V0LnNsaWNlKFxuICAgICAgICAgICAgICAwLFxuICAgICAgICAgICAgICA1MDBcbiAgICAgICAgICAgICl9YCxcbiAgICAgICAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgICAgICAgIHRvdGFsTGluZXM6IDAsXG4gICAgICAgICAgICAgIGxpbmVzU2hvd246IDAsXG4gICAgICAgICAgICAgIHN0YXJ0TGluZTogMCxcbiAgICAgICAgICAgICAgZW5kTGluZTogMCxcbiAgICAgICAgICAgICAgaXNQYWdpbmF0ZWQ6IGZhbHNlLFxuICAgICAgICAgICAgICBmaWxlU2l6ZTogXCJ1bmtub3duXCIsXG4gICAgICAgICAgICAgIHBhdGg6IGZpbGVQYXRoLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBjb250ZW50LFxuICAgICAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgICAgICB0b3RhbExpbmVzLFxuICAgICAgICAgICAgbGluZXNTaG93bjogTWF0aC5tYXgoMCwgYWN0dWFsRW5kIC0gYWN0dWFsU3RhcnQgKyAxKSxcbiAgICAgICAgICAgIHN0YXJ0TGluZTogYWN0dWFsU3RhcnQsXG4gICAgICAgICAgICBlbmRMaW5lOiBhY3R1YWxFbmQsXG4gICAgICAgICAgICBpc1BhZ2luYXRlZDogYWN0dWFsRW5kIDwgdG90YWxMaW5lcyxcbiAgICAgICAgICAgIGZpbGVTaXplOiBmaWxlU2l6ZSB8fCBcInVua25vd25cIixcbiAgICAgICAgICAgIHBhdGg6IGZpbGVQYXRoLFxuICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICB9LFxuICAgIH0pLFxuICAgIEdyZXA6IHRvb2woe1xuICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgIFwiU2VhcmNoIGZvciBwYXR0ZXJucyBpbiBmaWxlcyB1c2luZyByaXBncmVwLiBTdXBwb3J0cyByZWdleCBwYXR0ZXJucywgZmlsZSB0eXBlIGZpbHRlcmluZywgYW5kIGNvbnRleHQgbGluZXMuIFJldHVybnMgbWF0Y2hpbmcgbGluZXMgd2l0aCBmaWxlIHBhdGhzIGFuZCBsaW5lIG51bWJlcnMuIFVzZSB0aGlzIHRvIGZpbmQgY29kZSBwYXR0ZXJucywgZnVuY3Rpb24gZGVmaW5pdGlvbnMsIGltcG9ydHMsIGV0Yy5cIixcbiAgICAgIGlucHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4gICAgICAgIHBhdHRlcm46IHpcbiAgICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgICAuZGVzY3JpYmUoXCJSZWdleCBwYXR0ZXJuIHRvIHNlYXJjaCBmb3IgKHJpcGdyZXAgc3ludGF4KVwiKSxcbiAgICAgICAgcGF0aDogelxuICAgICAgICAgIC5zdHJpbmcoKVxuICAgICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgICAgLmRlc2NyaWJlKFxuICAgICAgICAgICAgXCJQYXRoIHRvIHNlYXJjaCBpbiAoZGVmYXVsdHMgdG8gd29ya3NwYWNlIHJvb3QpLiBDYW4gYmUgYSBmaWxlIG9yIGRpcmVjdG9yeS5cIlxuICAgICAgICAgICksXG4gICAgICAgIGZpbGVUeXBlOiB6XG4gICAgICAgICAgLnN0cmluZygpXG4gICAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgICBcIkZpbGUgdHlwZSB0byBmaWx0ZXIgYnkgKGUuZy4sICd0cycsICdqcycsICdweScsICdtZCcpLiBVc2VzIHJpcGdyZXAncyBidWlsdC1pbiB0eXBlIGZpbHRlcnMuXCJcbiAgICAgICAgICApLFxuICAgICAgICBnbG9iOiB6XG4gICAgICAgICAgLnN0cmluZygpXG4gICAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgICBcIkdsb2IgcGF0dGVybiB0byBmaWx0ZXIgZmlsZXMgKGUuZy4sICcqLnRzeCcsICdzcmMvKiovKi50cycpXCJcbiAgICAgICAgICApLFxuICAgICAgICBjYXNlU2Vuc2l0aXZlOiB6XG4gICAgICAgICAgLmJvb2xlYW4oKVxuICAgICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgICAgLmRlZmF1bHQodHJ1ZSlcbiAgICAgICAgICAuZGVzY3JpYmUoXCJXaGV0aGVyIHNlYXJjaCBpcyBjYXNlLXNlbnNpdGl2ZSAoZGVmYXVsdDogdHJ1ZSlcIiksXG4gICAgICAgIGNvbnRleHRMaW5lczogelxuICAgICAgICAgIC5udW1iZXIoKVxuICAgICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgICAgLmRlc2NyaWJlKFxuICAgICAgICAgICAgXCJOdW1iZXIgb2YgY29udGV4dCBsaW5lcyB0byBzaG93IGJlZm9yZSBhbmQgYWZ0ZXIgZWFjaCBtYXRjaFwiXG4gICAgICAgICAgKSxcbiAgICAgICAgbWF4Q291bnQ6IHpcbiAgICAgICAgICAubnVtYmVyKClcbiAgICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAgIC5kZXNjcmliZShcbiAgICAgICAgICAgIFwiTWF4aW11bSBudW1iZXIgb2YgbWF0Y2hlcyBwZXIgZmlsZSAodXNlZnVsIGZvciBsaW1pdGluZyBvdXRwdXQpXCJcbiAgICAgICAgICApLFxuICAgICAgICBmaWxlc1dpdGhNYXRjaGVzOiB6XG4gICAgICAgICAgLmJvb2xlYW4oKVxuICAgICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgICAgLmRlZmF1bHQoZmFsc2UpXG4gICAgICAgICAgLmRlc2NyaWJlKFxuICAgICAgICAgICAgXCJPbmx5IHNob3cgZmlsZSBwYXRocyB0aGF0IGNvbnRhaW4gbWF0Y2hlcywgbm90IHRoZSBtYXRjaGluZyBsaW5lcyB0aGVtc2VsdmVzXCJcbiAgICAgICAgICApLFxuICAgICAgfSksXG4gICAgICBvdXRwdXRTY2hlbWE6IHoub2JqZWN0KHtcbiAgICAgICAgbWF0Y2hlczogelxuICAgICAgICAgIC5zdHJpbmcoKVxuICAgICAgICAgIC5kZXNjcmliZShcbiAgICAgICAgICAgIFwiU2VhcmNoIHJlc3VsdHMgd2l0aCBmaWxlIHBhdGhzLCBsaW5lIG51bWJlcnMsIGFuZCBtYXRjaGluZyBjb250ZW50XCJcbiAgICAgICAgICApLFxuICAgICAgICBzdW1tYXJ5OiB6Lm9iamVjdCh7XG4gICAgICAgICAgbWF0Y2hDb3VudDogei5udW1iZXIoKS5kZXNjcmliZShcIk51bWJlciBvZiBtYXRjaGVzIGZvdW5kXCIpLFxuICAgICAgICAgIGZpbGVDb3VudDogei5udW1iZXIoKS5kZXNjcmliZShcIk51bWJlciBvZiBmaWxlcyBjb250YWluaW5nIG1hdGNoZXNcIiksXG4gICAgICAgICAgc2VhcmNoUGF0aDogei5zdHJpbmcoKS5kZXNjcmliZShcIlBhdGggdGhhdCB3YXMgc2VhcmNoZWRcIiksXG4gICAgICAgICAgcGF0dGVybjogei5zdHJpbmcoKS5kZXNjcmliZShcIlBhdHRlcm4gdGhhdCB3YXMgc2VhcmNoZWQgZm9yXCIpLFxuICAgICAgICB9KSxcbiAgICAgIH0pLFxuICAgICAgZXhlY3V0ZTogYXN5bmMgKHtcbiAgICAgICAgcGF0dGVybixcbiAgICAgICAgcGF0aCxcbiAgICAgICAgZmlsZVR5cGUsXG4gICAgICAgIGdsb2IsXG4gICAgICAgIGNhc2VTZW5zaXRpdmUsXG4gICAgICAgIGNvbnRleHRMaW5lcyxcbiAgICAgICAgbWF4Q291bnQsXG4gICAgICAgIGZpbGVzV2l0aE1hdGNoZXMsXG4gICAgICB9KSA9PiB7XG4gICAgICAgIGxldCBzZWFyY2hQYXRoID0gcGF0aCA/PyBcIi5cIjtcbiAgICAgICAgaWYgKHNlYXJjaFBhdGguc3RhcnRzV2l0aChcIi9cIikpIHtcbiAgICAgICAgICBzZWFyY2hQYXRoID0gc2VhcmNoUGF0aC5zbGljZSgxKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGFyZ3M6IHN0cmluZ1tdID0gW107XG5cbiAgICAgICAgYXJncy5wdXNoKFwiLS1saW5lLW51bWJlclwiKTtcbiAgICAgICAgYXJncy5wdXNoKFwiLS1oZWFkaW5nXCIpO1xuICAgICAgICBhcmdzLnB1c2goXCItLWNvbG9yXCIsIFwibmV2ZXJcIik7XG5cbiAgICAgICAgaWYgKCFjYXNlU2Vuc2l0aXZlKSB7XG4gICAgICAgICAgYXJncy5wdXNoKFwiLWlcIik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZmlsZVR5cGUpIHtcbiAgICAgICAgICBhcmdzLnB1c2goXCItLXR5cGVcIiwgZmlsZVR5cGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGdsb2IpIHtcbiAgICAgICAgICBhcmdzLnB1c2goXCItLWdsb2JcIiwgZ2xvYik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY29udGV4dExpbmVzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBhcmdzLnB1c2goXCItQ1wiLCBTdHJpbmcoY29udGV4dExpbmVzKSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobWF4Q291bnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGFyZ3MucHVzaChcIi0tbWF4LWNvdW50XCIsIFN0cmluZyhtYXhDb3VudCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZpbGVzV2l0aE1hdGNoZXMpIHtcbiAgICAgICAgICBhcmdzLnB1c2goXCItLWZpbGVzLXdpdGgtbWF0Y2hlc1wiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGFyZ3MucHVzaChcIi0tXCIsIHBhdHRlcm4sIHNlYXJjaFBhdGgpO1xuXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnRleHQuc2FuZGJveC5leGVjKHsgY29tbWFuZDogXCJyZ1wiLCBhcmdzIH0pO1xuXG4gICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJbR3JlcCBUb29sXVwiLCByZXN1bHQpO1xuICAgICAgICAgIHRocm93IHJlc3VsdDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHsgc3Rkb3V0LCBzdGRlcnIgfSA9IGF3YWl0IHJlc3VsdC5yZXN1bHQ7XG5cbiAgICAgICAgaWYgKHN0ZGVyciAmJiAhc3RkZXJyLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoXCJubyBtYXRjaGVzXCIpKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihgW0dyZXAgVG9vbF0gV2FybmluZzogJHtzdGRlcnJ9YCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUcnVuY2F0ZSBvdXRwdXQgdG8gcHJldmVudCBcImlucHV0IHRvbyBsb25nXCIgZXJyb3JzICg1MGsgY2hhcnMgXHUyMjQ4IDEyLjVrIHRva2VucylcbiAgICAgICAgY29uc3QgTUFYX0dSRVBfT1VUUFVUX0NIQVJTID0gNTBfMDAwO1xuICAgICAgICBsZXQgZmluYWxPdXRwdXQgPSBzdGRvdXQ7XG4gICAgICAgIGxldCB3YXNUcnVuY2F0ZWQgPSBmYWxzZTtcbiAgICAgICAgaWYgKGZpbmFsT3V0cHV0Lmxlbmd0aCA+IE1BWF9HUkVQX09VVFBVVF9DSEFSUykge1xuICAgICAgICAgIGZpbmFsT3V0cHV0ID1cbiAgICAgICAgICAgIGZpbmFsT3V0cHV0LnNsaWNlKDAsIE1BWF9HUkVQX09VVFBVVF9DSEFSUykgK1xuICAgICAgICAgICAgXCJcXG5cXG5bT3V0cHV0IHRydW5jYXRlZCAtIHVzZSBtb3JlIHNwZWNpZmljIHBhdHRlcm4gb3IgcGF0aF1cIjtcbiAgICAgICAgICB3YXNUcnVuY2F0ZWQgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbGluZXMgPSBmaW5hbE91dHB1dFxuICAgICAgICAgIC50cmltKClcbiAgICAgICAgICAuc3BsaXQoXCJcXG5cIilcbiAgICAgICAgICAuZmlsdGVyKChsKSA9PiBsLmxlbmd0aCA+IDApO1xuICAgICAgICBjb25zdCBmaWxlQ291bnQgPSBmaWxlc1dpdGhNYXRjaGVzXG4gICAgICAgICAgPyBsaW5lcy5sZW5ndGhcbiAgICAgICAgICA6IG5ldyBTZXQoXG4gICAgICAgICAgICAgIGxpbmVzXG4gICAgICAgICAgICAgICAgLmZpbHRlcigobCkgPT4gIWwuc3RhcnRzV2l0aChcIiBcIikgJiYgbC5pbmNsdWRlcyhcIjpcIikpXG4gICAgICAgICAgICAgICAgLm1hcCgobCkgPT4gbC5zcGxpdChcIjpcIilbMF0pXG4gICAgICAgICAgICApLnNpemU7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBtYXRjaGVzOiBmaW5hbE91dHB1dCB8fCBcIihubyBtYXRjaGVzIGZvdW5kKVwiLFxuICAgICAgICAgIHN1bW1hcnk6IHtcbiAgICAgICAgICAgIG1hdGNoQ291bnQ6IGZpbGVzV2l0aE1hdGNoZXNcbiAgICAgICAgICAgICAgPyAwXG4gICAgICAgICAgICAgIDogbGluZXMuZmlsdGVyKChsKSA9PiBsLmluY2x1ZGVzKFwiOlwiKSkubGVuZ3RoLFxuICAgICAgICAgICAgZmlsZUNvdW50LFxuICAgICAgICAgICAgc2VhcmNoUGF0aCxcbiAgICAgICAgICAgIHBhdHRlcm4sXG4gICAgICAgICAgICB3YXNUcnVuY2F0ZWQsXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICAgIH0sXG4gICAgfSksXG4gICAgTGlzdDogdG9vbCh7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgXCJSZWN1cnNpdmVseSBsaXN0IGRpcmVjdG9yeSBjb250ZW50cy4gVXNlIHRoaXMgdG8gdW5kZXJzdGFuZCB0aGUgY29kZWJhc2Ugc3RydWN0dXJlLCBmaW5kIGZpbGVzLCBvciBleHBsb3JlIGRpcmVjdG9yaWVzLiBDb250cm9sIGRlcHRoIHRvIGJhbGFuY2UgZGV0YWlsIHZzLiBvdmVydmlldy4gRGVwdGggMSBzaG93cyBpbW1lZGlhdGUgY2hpbGRyZW4sIGRlcHRoIDIgaW5jbHVkZXMgc3ViZGlyZWN0b3JpZXMsIGV0Yy5cIixcbiAgICAgIGlucHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4gICAgICAgIHBhdGg6IHpcbiAgICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAgIC5kZXNjcmliZShcIlBhdGggdG8gbGlzdCAoZGVmYXVsdHMgdG8gd29ya3NwYWNlIHJvb3QpXCIpLFxuICAgICAgICBkZXB0aDogelxuICAgICAgICAgIC5udW1iZXIoKVxuICAgICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgICAgLmRlc2NyaWJlKFxuICAgICAgICAgICAgXCJNYXhpbXVtIGRlcHRoIHRvIHRyYXZlcnNlLiBDaG9vc2UgYmFzZWQgb24gY29udGV4dDogMS0yIGZvciBxdWljayBvdmVydmlldywgMy00IGZvciBkZXRhaWxlZCBleHBsb3JhdGlvbiwgNSsgZm9yIGNvbXByZWhlbnNpdmUgbWFwcGluZ1wiXG4gICAgICAgICAgKSxcbiAgICAgICAgaW5jbHVkZUhpZGRlbjogelxuICAgICAgICAgIC5ib29sZWFuKClcbiAgICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAgIC5kZWZhdWx0KGZhbHNlKVxuICAgICAgICAgIC5kZXNjcmliZShcbiAgICAgICAgICAgIFwiSW5jbHVkZSBoaWRkZW4gZmlsZXMgYW5kIGRpcmVjdG9yaWVzICh0aG9zZSBzdGFydGluZyB3aXRoICcuJylcIlxuICAgICAgICAgICksXG4gICAgICAgIGZpbGVzT25seTogelxuICAgICAgICAgIC5ib29sZWFuKClcbiAgICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAgIC5kZWZhdWx0KGZhbHNlKVxuICAgICAgICAgIC5kZXNjcmliZShcIk9ubHkgc2hvdyBmaWxlcywgbm90IGRpcmVjdG9yaWVzXCIpLFxuICAgICAgICBwYXR0ZXJuOiB6XG4gICAgICAgICAgLnN0cmluZygpXG4gICAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgICAuZGVzY3JpYmUoXCJHbG9iIHBhdHRlcm4gdG8gZmlsdGVyIHJlc3VsdHMgKGUuZy4sICcqLnRzJywgJyp0ZXN0KicpXCIpLFxuICAgICAgfSksXG4gICAgICBvdXRwdXRTY2hlbWE6IHoub2JqZWN0KHtcbiAgICAgICAgbGlzdGluZzogelxuICAgICAgICAgIC5zdHJpbmcoKVxuICAgICAgICAgIC5kZXNjcmliZShcbiAgICAgICAgICAgIFwiRGlyZWN0b3J5IHRyZWUgbGlzdGluZyBzaG93aW5nIHBhdGhzIHJlbGF0aXZlIHRvIHNlYXJjaCByb290XCJcbiAgICAgICAgICApLFxuICAgICAgICBzdW1tYXJ5OiB6Lm9iamVjdCh7XG4gICAgICAgICAgdG90YWxJdGVtczogei5udW1iZXIoKS5kZXNjcmliZShcIlRvdGFsIG51bWJlciBvZiBpdGVtcyBmb3VuZFwiKSxcbiAgICAgICAgICB0b3RhbEZpbGVzOiB6Lm51bWJlcigpLmRlc2NyaWJlKFwiVG90YWwgbnVtYmVyIG9mIGZpbGVzIGZvdW5kXCIpLFxuICAgICAgICAgIHRvdGFsRGlyczogei5udW1iZXIoKS5kZXNjcmliZShcIlRvdGFsIG51bWJlciBvZiBkaXJlY3RvcmllcyBmb3VuZFwiKSxcbiAgICAgICAgICBzZWFyY2hQYXRoOiB6LnN0cmluZygpLmRlc2NyaWJlKFwiUGF0aCB0aGF0IHdhcyBsaXN0ZWRcIiksXG4gICAgICAgICAgZGVwdGg6IHpcbiAgICAgICAgICAgIC5udW1iZXIoKVxuICAgICAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgICAgIC5kZXNjcmliZShcIk1heGltdW0gZGVwdGggdXNlZCAoaWYgc3BlY2lmaWVkKVwiKSxcbiAgICAgICAgfSksXG4gICAgICB9KSxcbiAgICAgIGV4ZWN1dGU6IGFzeW5jICh7IHBhdGgsIGRlcHRoLCBpbmNsdWRlSGlkZGVuLCBmaWxlc09ubHksIHBhdHRlcm4gfSkgPT4ge1xuICAgICAgICBjb25zdCBzZWFyY2hQYXRoID0gcGF0aCA/PyBcIi5cIjtcblxuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb250ZXh0LnNhbmRib3guZXhlYyh7XG4gICAgICAgICAgY29tbWFuZDogXCJiYXNoXCIsXG4gICAgICAgICAgYXJnczogW1xuICAgICAgICAgICAgXCItY1wiLFxuICAgICAgICAgICAgYFxuICAgICAgICAgICAgc2V0IC1lXG4gICAgICAgICAgICBTRUFSQ0hfUEFUSD1cIiQxXCJcbiAgICAgICAgICAgIERFUFRIPVwiJDJcIlxuICAgICAgICAgICAgSU5DTFVERV9ISURERU49XCIkM1wiXG4gICAgICAgICAgICBGSUxFU19PTkxZPVwiJDRcIlxuICAgICAgICAgICAgUEFUVEVSTj1cIiQ1XCJcblxuICAgICAgICAgICAgIyBCdWlsZCBmaW5kIGNvbW1hbmQgYXJndW1lbnRzXG4gICAgICAgICAgICBGSU5EX0FSR1M9XCJcIlxuICAgICAgICAgICAgWyAtbiBcIiRERVBUSFwiIF0gJiYgRklORF9BUkdTPVwiJEZJTkRfQVJHUyAtbWF4ZGVwdGggJERFUFRIXCJcbiAgICAgICAgICAgIFsgXCIkSU5DTFVERV9ISURERU5cIiAhPSBcInRydWVcIiBdICYmIEZJTkRfQVJHUz1cIiRGSU5EX0FSR1MgISAtcGF0aCAnKi8uKidcIlxuICAgICAgICAgICAgWyBcIiRGSUxFU19PTkxZXCIgPSBcInRydWVcIiBdICYmIEZJTkRfQVJHUz1cIiRGSU5EX0FSR1MgLXR5cGUgZlwiXG4gICAgICAgICAgICBbIC1uIFwiJFBBVFRFUk5cIiBdICYmIEZJTkRfQVJHUz1cIiRGSU5EX0FSR1MgLW5hbWUgJyRQQVRURVJOJ1wiXG5cbiAgICAgICAgICAgICMgR2V0IGxpc3RpbmdcbiAgICAgICAgICAgIExJU1RJTkc9JChldmFsIFwiZmluZCAnJFNFQVJDSF9QQVRIJyAkRklORF9BUkdTXCIgMj4vZGV2L251bGwgfCBzb3J0KVxuXG4gICAgICAgICAgICAjIEdldCBjb3VudHNcbiAgICAgICAgICAgIENPVU5UX0FSR1M9XCJcIlxuICAgICAgICAgICAgWyAtbiBcIiRERVBUSFwiIF0gJiYgQ09VTlRfQVJHUz1cIiRDT1VOVF9BUkdTIC1tYXhkZXB0aCAkREVQVEhcIlxuICAgICAgICAgICAgWyBcIiRJTkNMVURFX0hJRERFTlwiICE9IFwidHJ1ZVwiIF0gJiYgQ09VTlRfQVJHUz1cIiRDT1VOVF9BUkdTICEgLXBhdGggJyovLionXCJcblxuICAgICAgICAgICAgRklMRV9DT1VOVD0kKGV2YWwgXCJmaW5kICckU0VBUkNIX1BBVEgnICRDT1VOVF9BUkdTIC10eXBlIGZcIiAyPi9kZXYvbnVsbCB8IHdjIC1sKVxuICAgICAgICAgICAgRElSX0NPVU5UPSQoZXZhbCBcImZpbmQgJyRTRUFSQ0hfUEFUSCcgJENPVU5UX0FSR1MgLXR5cGUgZFwiIDI+L2Rldi9udWxsIHwgd2MgLWwpXG5cbiAgICAgICAgICAgICMgT3V0cHV0OiBjb3VudHMgZmlyc3QsIHRoZW4gbGlzdGluZ1xuICAgICAgICAgICAgZWNobyBcIiRGSUxFX0NPVU5UfCRESVJfQ09VTlRcIlxuICAgICAgICAgICAgZWNobyBcInx8fExJU1RJTkd8fHxcIlxuICAgICAgICAgICAgZWNobyBcIiRMSVNUSU5HXCIgfCBzZWQgXCJzfF4kU0VBUkNIX1BBVEh8LnxcIlxuICAgICAgICAgIGAsXG4gICAgICAgICAgICBcIi0tXCIsXG4gICAgICAgICAgICBzZWFyY2hQYXRoLFxuICAgICAgICAgICAgZGVwdGg/LnRvU3RyaW5nKCkgfHwgXCJcIixcbiAgICAgICAgICAgIGluY2x1ZGVIaWRkZW4gPyBcInRydWVcIiA6IFwiZmFsc2VcIixcbiAgICAgICAgICAgIGZpbGVzT25seSA/IFwidHJ1ZVwiIDogXCJmYWxzZVwiLFxuICAgICAgICAgICAgcGF0dGVybiB8fCBcIlwiLFxuICAgICAgICAgIF0sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJbTGlzdCBUb29sXVwiLCByZXN1bHQpO1xuICAgICAgICAgIHRocm93IHJlc3VsdDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHsgc3Rkb3V0LCBzdGRlcnIgfSA9IGF3YWl0IHJlc3VsdC5yZXN1bHQ7XG5cbiAgICAgICAgaWYgKHN0ZGVycikge1xuICAgICAgICAgIGNvbnNvbGUud2FybihgW0xpc3QgVG9vbF0gc3RkZXJyOiAke3N0ZGVycn1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IFtjb3VudHNMaW5lLCAuLi5yZXN0XSA9IHN0ZG91dC5zcGxpdChcInx8fExJU1RJTkd8fHxcIik7XG4gICAgICAgIGNvbnN0IGxpc3RpbmcgPSByZXN0LmpvaW4oXCJ8fHxMSVNUSU5HfHx8XCIpLnRyaW0oKTtcbiAgICAgICAgY29uc3QgW2ZpbGVDb3VudFN0ciwgZGlyQ291bnRTdHJdID0gY291bnRzTGluZS50cmltKCkuc3BsaXQoXCJ8XCIpO1xuXG4gICAgICAgIGNvbnN0IHRvdGFsRmlsZXMgPSBOdW1iZXIucGFyc2VJbnQoZmlsZUNvdW50U3RyLCAxMCkgfHwgMDtcbiAgICAgICAgY29uc3QgdG90YWxEaXJzID0gTnVtYmVyLnBhcnNlSW50KGRpckNvdW50U3RyLCAxMCkgfHwgMDtcbiAgICAgICAgY29uc3QgbGluZXMgPSBsaXN0aW5nLnNwbGl0KFwiXFxuXCIpLmZpbHRlcigobCkgPT4gbC5sZW5ndGggPiAwKTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGxpc3RpbmcsXG4gICAgICAgICAgc3VtbWFyeToge1xuICAgICAgICAgICAgdG90YWxJdGVtczogbGluZXMubGVuZ3RoLFxuICAgICAgICAgICAgdG90YWxGaWxlcyxcbiAgICAgICAgICAgIHRvdGFsRGlycyxcbiAgICAgICAgICAgIHNlYXJjaFBhdGgsXG4gICAgICAgICAgICBkZXB0aCxcbiAgICAgICAgICB9LFxuICAgICAgICB9O1xuICAgICAgfSxcbiAgICB9KSxcbiAgICBCYXNoOiB0b29sKHtcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICBcIkV4ZWN1dGVzIGEgYmFzaCBjb21tYW5kIGluc2lkZSB0aGUgd29ya3NwYWNlLiBDV0QgcGVyc2lzdHMgYmV0d2VlbiBjb21tYW5kcyB3aXRoaW4gYSBzZXNzaW9uLiBVc2Ugd2FpdFVudGlsOjAgZm9yIGJhY2tncm91bmQgcHJvY2Vzc2VzIChkZXYgc2VydmVycykuXCIsXG4gICAgICBpbnB1dFNjaGVtYTogei5vYmplY3Qoe1xuICAgICAgICBjb21tYW5kOiB6LnN0cmluZygpLmRlc2NyaWJlKFwiVGhlIHNoZWxsIGNvbW1hbmQgdG8gZXhlY3V0ZVwiKSxcbiAgICAgICAgd2FpdFVudGlsOiB6XG4gICAgICAgICAgLm51bWJlcigpXG4gICAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgICBcIk1heCBtcyB0byB3YWl0IGZvciBjb21wbGV0aW9uIChkZWZhdWx0OiAzMDAwMCkuIFVzZSAwIHRvIHJ1biBpbiBiYWNrZ3JvdW5kIGFuZCByZXR1cm4gaW1tZWRpYXRlbHkuXCJcbiAgICAgICAgICApLFxuICAgICAgfSksXG4gICAgICBvdXRwdXRTY2hlbWE6IHoub2JqZWN0KHtcbiAgICAgICAgcGlkOiB6XG4gICAgICAgICAgLm51bWJlcigpXG4gICAgICAgICAgLmRlc2NyaWJlKFxuICAgICAgICAgICAgXCJTeXN0ZW0gUElEICgwIGZvciBmb3JlZ3JvdW5kLCA+MCBmb3IgYmFja2dyb3VuZCAtIHVzZSB0byBraWxsKVwiXG4gICAgICAgICAgKSxcbiAgICAgICAgb3V0cHV0OiB6XG4gICAgICAgICAgLnN0cmluZygpXG4gICAgICAgICAgLmRlc2NyaWJlKFwiQ29tbWFuZCBzdGRvdXQrc3RkZXJyIGNvbWJpbmVkIChlbXB0eSBmb3IgYmFja2dyb3VuZClcIiksXG4gICAgICAgIGV4aXRDb2RlOiB6Lm51bWJlcigpLmRlc2NyaWJlKFwiRXhpdCBjb2RlICgtMSBmb3IgYmFja2dyb3VuZC9ydW5uaW5nKVwiKSxcbiAgICAgICAgc3RhdHVzOiB6XG4gICAgICAgICAgLmVudW0oW1wicnVubmluZ1wiLCBcImNvbXBsZXRlZFwiLCBcImZhaWxlZFwiXSlcbiAgICAgICAgICAuZGVzY3JpYmUoXCJQcm9jZXNzIHN0YXR1c1wiKSxcbiAgICAgICAgY3dkOiB6LnN0cmluZygpLmRlc2NyaWJlKFwiQ3VycmVudCB3b3JraW5nIGRpcmVjdG9yeSBhZnRlciBjb21tYW5kXCIpLFxuICAgICAgICBvdXRwdXRGaWxlOiB6XG4gICAgICAgICAgLnN0cmluZygpXG4gICAgICAgICAgLmRlc2NyaWJlKFwiUGF0aCB0byBvdXRwdXQgbG9nIChmb3IgYmFja2dyb3VuZCBwcm9jZXNzZXMpXCIpLFxuICAgICAgfSksXG4gICAgICBleGVjdXRlOiBhc3luYyAoeyBjb21tYW5kLCB3YWl0VW50aWwgfSkgPT4ge1xuICAgICAgICBjb25zdCB7IGNyZWF0ZVByb2Nlc3NNYW5hZ2VyIH0gPSBhd2FpdCBpbXBvcnQoXG4gICAgICAgICAgXCIuLi9zYW5kYm94L3Byb2Nlc3MtbWFuYWdlclwiXG4gICAgICAgICk7XG5cbiAgICAgICAgY29uc3QgcHJvY2Vzc01hbmFnZXIgPSBjcmVhdGVQcm9jZXNzTWFuYWdlcih7XG4gICAgICAgICAgc2FuZGJveDogY29udGV4dC5zYW5kYm94LFxuICAgICAgICAgIHNlc3Npb25JZDogY29udGV4dC5pbnB1dC5zZXNzaW9uSWQsXG4gICAgICAgICAgZ2VuZXJhdGVJZDogKCkgPT4gY3J5cHRvLnJhbmRvbVVVSUQoKSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgYXdhaXQgcHJvY2Vzc01hbmFnZXIuaW5pdCgpO1xuICAgICAgICByZXR1cm4gcHJvY2Vzc01hbmFnZXIucnVuKHsgY29tbWFuZCwgd2FpdFVudGlsIH0pO1xuICAgICAgfSxcbiAgICB9KSxcbiAgICBFeGVjdXRlTUNQVG9vbDogdG9vbCh7XG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgXCJFeGVjdXRlIGEgdG9vbCBmcm9tIGFuIE1DUCBzZXJ2ZXIuIFVzZSB0aGlzIHRvIGNhbGwgY3VzdG9tIHRvb2xzIHByb3ZpZGVkIGJ5IHRoZSBhcHBsaWNhdGlvbi5cIixcbiAgICAgIGlucHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4gICAgICAgIHNlcnZlcjogei5zdHJpbmcoKS5kZXNjcmliZShcIk1DUCBzZXJ2ZXIgbmFtZVwiKSxcbiAgICAgICAgdG9vbDogei5zdHJpbmcoKS5kZXNjcmliZShcIlRvb2wgbmFtZSB0byBleGVjdXRlXCIpLFxuICAgICAgICBpbnB1dDogei51bmtub3duKCkuZGVzY3JpYmUoXCJUb29sIGlucHV0IG1hdGNoaW5nIHRoZSB0b29sJ3Mgc2NoZW1hXCIpLFxuICAgICAgfSksXG4gICAgICBvdXRwdXRTY2hlbWE6IHoub2JqZWN0KHtcbiAgICAgICAgcmVzdWx0OiB6LnVua25vd24oKS5kZXNjcmliZShcIlRvb2wgZXhlY3V0aW9uIHJlc3VsdFwiKSxcbiAgICAgICAgdHJ1bmNhdGVkOiB6XG4gICAgICAgICAgLmJvb2xlYW4oKVxuICAgICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgICAgLmRlc2NyaWJlKFwiV2hldGhlciB0aGUgcmVzdWx0IHdhcyB0cnVuY2F0ZWQgZHVlIHRvIHNpemVcIiksXG4gICAgICAgIHRvdGFsQ2hhcnM6IHpcbiAgICAgICAgICAubnVtYmVyKClcbiAgICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAgIC5kZXNjcmliZShcIlRvdGFsIGNoYXJhY3RlcnMgaW4gZnVsbCBvdXRwdXQgKG9ubHkgaWYgdHJ1bmNhdGVkKVwiKSxcbiAgICAgICAgcmV0dXJuZWRDaGFyczogelxuICAgICAgICAgIC5udW1iZXIoKVxuICAgICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgICAgLmRlc2NyaWJlKFwiQ2hhcmFjdGVycyByZXR1cm5lZCBpbiB0aGlzIHJlc3BvbnNlIChvbmx5IGlmIHRydW5jYXRlZClcIiksXG4gICAgICAgIGZ1bGxPdXRwdXRQYXRoOiB6XG4gICAgICAgICAgLnN0cmluZygpXG4gICAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgICAuZGVzY3JpYmUoXCJQYXRoIHRvIGZ1bGwgb3V0cHV0IGZpbGUgaWYgdHJ1bmNhdGVkXCIpLFxuICAgICAgfSksXG4gICAgICBleGVjdXRlOiBhc3luYyAoeyBzZXJ2ZXIsIHRvb2w6IHRvb2xOYW1lLCBpbnB1dCB9KSA9PiB7XG4gICAgICAgIGNvbnN0IHNlcnZlckNvbmZpZyA9IGNvbnRleHQubWNwPy5maW5kKChzKSA9PiBzLm5hbWUgPT09IHNlcnZlcik7XG4gICAgICAgIGlmICghc2VydmVyQ29uZmlnKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIE1DUCBzZXJ2ZXI6ICR7c2VydmVyfWApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcGFyc2VkSW5wdXQgPVxuICAgICAgICAgIHR5cGVvZiBpbnB1dCA9PT0gXCJzdHJpbmdcIiA/IEpTT04ucGFyc2UoaW5wdXQpIDogaW5wdXQ7XG5cbiAgICAgICAgY29uc3QgdGltZXN0YW1wID0gRGF0ZS5ub3coKTtcbiAgICAgICAgY29uc3Qgb3V0cHV0RGlyID0gYC5hZ2VudC9tY3AvJHtzZXJ2ZXJ9Ly5vdXRwdXRzYDtcbiAgICAgICAgY29uc3Qgb3V0cHV0RmlsZSA9IGAke291dHB1dERpcn0vJHt0aW1lc3RhbXB9LSR7dG9vbE5hbWV9LnR4dGA7XG5cbiAgICAgICAgY29uc3QgW3Jlc10gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICAgICAgZmV0Y2goc2VydmVyQ29uZmlnLnVybCwge1xuICAgICAgICAgICAgbWV0aG9kOiBcIlBPU1RcIixcbiAgICAgICAgICAgIGhlYWRlcnM6IHsgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIgfSxcbiAgICAgICAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgICAgc2VydmVyLFxuICAgICAgICAgICAgICB0b29sOiB0b29sTmFtZSxcbiAgICAgICAgICAgICAgaW5wdXQ6IHBhcnNlZElucHV0LFxuICAgICAgICAgICAgICBzZXNzaW9uSWQ6IGNvbnRleHQuaW5wdXQuc2Vzc2lvbklkLFxuICAgICAgICAgICAgICBtZXNzYWdlSWQ6IGNvbnRleHQuZXZlbnQuYXNzaXN0YW50TWVzc2FnZUlkLFxuICAgICAgICAgICAgICBob29rVG9rZW46IGNvbnRleHQuZXZlbnQuaG9va1Rva2VuLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgfSksXG4gICAgICAgICAgY29udGV4dC5zYW5kYm94LmV4ZWMoeyBjb21tYW5kOiBcIm1rZGlyXCIsIGFyZ3M6IFtcIi1wXCIsIG91dHB1dERpcl0gfSksXG4gICAgICAgIF0pO1xuXG4gICAgICAgIGlmICghcmVzLm9rKSB7XG4gICAgICAgICAgY29uc3QgZXJyb3IgPSBhd2FpdCByZXMudGV4dCgpO1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgTUNQIHRvb2wgY2FsbCBmYWlsZWQ6ICR7ZXJyb3J9YCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBqc29uID0gKGF3YWl0IHJlcy5qc29uKCkpIGFzIHtcbiAgICAgICAgICByZXN1bHQ/OiB1bmtub3duO1xuICAgICAgICAgIGVycm9yPzogeyBjb2RlOiBzdHJpbmc7IG1lc3NhZ2U6IHN0cmluZyB9O1xuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChqc29uLmVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBNQ1AgdG9vbCBjYWxsIGZhaWxlZDogJHtqc29uLmVycm9yLm1lc3NhZ2V9YCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoanNvbi5yZXN1bHQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk1DUCB0b29sIGNhbGwgZmFpbGVkOiBObyByZXN1bHQgaW4gcmVzcG9uc2VcIik7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZXN1bHQgPSBqc29uLnJlc3VsdDtcbiAgICAgICAgY29uc3QgTUFYX09VVFBVVF9DSEFSUyA9IDI0XzAwMDtcbiAgICAgICAgY29uc3QgcmVzdWx0U3RyID0gSlNPTi5zdHJpbmdpZnkocmVzdWx0LCBudWxsLCAyKTtcblxuICAgICAgICBpZiAocmVzdWx0U3RyLmxlbmd0aCA8PSBNQVhfT1VUUFVUX0NIQVJTKSB7XG4gICAgICAgICAgcmV0dXJuIHsgcmVzdWx0IH07XG4gICAgICAgIH1cblxuICAgICAgICBhd2FpdCBjb250ZXh0LnNhbmRib3gud3JpdGVGaWxlcyh7XG4gICAgICAgICAgZmlsZXM6IFt7IHBhdGg6IGAke3RpbWVzdGFtcH0tJHt0b29sTmFtZX0udHh0YCwgY29udGVudDogcmVzdWx0U3RyIH1dLFxuICAgICAgICAgIGRlc3RQYXRoOiBvdXRwdXREaXIsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IHRydW5jYXRlZFJlc3VsdCA9XG4gICAgICAgICAgcmVzdWx0U3RyLnNsaWNlKDAsIE1BWF9PVVRQVVRfQ0hBUlMpICtcbiAgICAgICAgICBgXFxuXFxuW091dHB1dCB0cnVuY2F0ZWQgYXQgfjZrIHRva2Vucy4gRnVsbCBvdXRwdXQgc2F2ZWQgdG86ICR7b3V0cHV0RmlsZX1dYDtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHJlc3VsdDogdHJ1bmNhdGVkUmVzdWx0LFxuICAgICAgICAgIHRydW5jYXRlZDogdHJ1ZSxcbiAgICAgICAgICB0b3RhbENoYXJzOiByZXN1bHRTdHIubGVuZ3RoLFxuICAgICAgICAgIHJldHVybmVkQ2hhcnM6IE1BWF9PVVRQVVRfQ0hBUlMsXG4gICAgICAgICAgZnVsbE91dHB1dFBhdGg6IG91dHB1dEZpbGUsXG4gICAgICAgIH07XG4gICAgICB9LFxuICAgIH0pLFxuICB9IHNhdGlzZmllcyBUb29sU2V0O1xufVxuXG5leHBvcnQgdHlwZSBBZ2VudFRvb2xzID0gUmV0dXJuVHlwZTx0eXBlb2YgZ2V0VG9vbHM+O1xuZXhwb3J0IHR5cGUgQWdlbnRUb29sTmFtZSA9IGtleW9mIEFnZW50VG9vbHM7XG4iLCAiaW1wb3J0IHR5cGUgeyBVSU1lc3NhZ2UgfSBmcm9tIFwiYWlcIjtcbmltcG9ydCB0eXBlIHsgTWVzc2FnZSwgUGFydCB9IGZyb20gXCIuLi9zdG9yYWdlXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBhc3NlbWJsZVVJTWVzc2FnZXMob3B0czoge1xuICBtZXNzYWdlczogTWVzc2FnZVtdO1xuICBwYXJ0czogUGFydFtdO1xufSk6IFVJTWVzc2FnZVtdIHtcbiAgY29uc3QgcGFydHNCeU1lc3NhZ2UgPSBuZXcgTWFwPHN0cmluZywgUGFydFtdPigpO1xuICBmb3IgKGNvbnN0IHBhcnQgb2Ygb3B0cy5wYXJ0cykge1xuICAgIGNvbnN0IGV4aXN0aW5nID0gcGFydHNCeU1lc3NhZ2UuZ2V0KHBhcnQubWVzc2FnZUlkKSA/PyBbXTtcbiAgICBleGlzdGluZy5wdXNoKHBhcnQpO1xuICAgIHBhcnRzQnlNZXNzYWdlLnNldChwYXJ0Lm1lc3NhZ2VJZCwgZXhpc3RpbmcpO1xuICB9XG5cbiAgcmV0dXJuIG9wdHMubWVzc2FnZXMubWFwKChtKSA9PiB7XG4gICAgY29uc3QgbWVzc2FnZVBhcnRzID0gcGFydHNCeU1lc3NhZ2UuZ2V0KG0uaWQpID8/IFtdO1xuICAgIG1lc3NhZ2VQYXJ0cy5zb3J0KChhLCBiKSA9PiBhLmluZGV4IC0gYi5pbmRleCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGlkOiBtLmlkLFxuICAgICAgcm9sZTogbS5yb2xlLFxuICAgICAgcGFydHM6IG1lc3NhZ2VQYXJ0cy5tYXAoKHApID0+IHAucGFydCksXG4gICAgfSBzYXRpc2ZpZXMgVUlNZXNzYWdlO1xuICB9KTtcbn1cbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsSUFFTSxvQkFNQSxZQTJGTztBQW5HYjtBQUFBO0FBQUE7QUFFQSxJQUFNLHFCQUFxQjtB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O0FBQUEsSUFDekIsU0FBUyxLQUFLO0FBQ1osY0FBUSxNQUFNLEdBQUc7QUFDakIsWUFBTTtBQUFBLElBQ1I7QUFBQSxFQUNGO0FBRUEsUUFBTSxvQkFBb0I7QUFBQSxJQUN4QixvQkFBb0IsTUFBTTtBQUFBLElBQzFCO0FBQUEsSUFDQTtBQUFBLEVBQ0YsQ0FBQztBQUNIOyIsCiAgIm5hbWVzIjogWyJvcHRzIiwgInN0YXJ0TG9jYWxTdG9yYWdlIiwgImdldFZlcmNlbFN0b3JhZ2VDb25maWciLCAiaW1wb3J0X3pvZCIsICJleGl0Q29kZSIsICJzdGRlcnIiLCAiZXJyb3JlIiwgImluaXRfbG9jYWwiLCAiZXJyb3JlIiwgImluaXRfdmVyY2VsIiwgInNhbmRib3giLCAiVmVyY2VsU2FuZGJveFNESyIsICJnZXRTYW5kYm94IiwgImluaXRfY2xpZW50IiwgImluaXRfbG9jYWwiLCAiaW5pdF92ZXJjZWwiLCAiaW5pdF9jbGllbnQiLCAiaW1wb3J0X3dvcmtmbG93IiwgImltcG9ydF9haSIsICJpbXBvcnRfdWxpZCIsICJwYXRoIiwgImNyZWF0ZVByb2Nlc3NNYW5hZ2VyIiwgImdldFN0b3JhZ2UiLCAiZ2V0U2FuZGJveCIsICJyZXN1bHQiXQp9Cg==
|