experimental-agent 0.2.1 → 0.3.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 +55 -254
- package/dist/adapter-BigchkkI.d.mts +201 -0
- package/dist/adapter-BigchkkI.d.ts +201 -0
- package/dist/chunk-BFFNCESS.mjs +302 -0
- package/dist/chunk-C4VSUEY2.mjs +72 -0
- package/dist/chunk-DOD4MC5D.mjs +196 -0
- package/dist/chunk-ELWIUJUK.mjs +96 -0
- package/dist/chunk-GKASMIBR.mjs +50 -0
- package/dist/chunk-JO3JDCH5.mjs +107 -0
- package/dist/chunk-MSWINCCM.mjs +128 -0
- package/dist/chunk-RT72C52I.mjs +324 -0
- package/dist/chunk-ZUFJJYC4.mjs +150 -0
- package/dist/{handler-FRUPZ4LX.mjs → docker-QPCLWLYR.mjs} +3 -4
- package/dist/entry-BmQ8FO-5.d.ts +36 -0
- package/dist/entry-CZd9aAwn.d.mts +36 -0
- package/dist/index.d.mts +415 -18
- package/dist/index.d.ts +415 -18
- package/dist/index.js +3036 -5494
- package/dist/index.mjs +3264 -1142
- package/dist/lifecycle-workflow-steps.d.mts +5 -0
- package/dist/lifecycle-workflow-steps.d.ts +5 -0
- package/dist/lifecycle-workflow-steps.js +263 -0
- package/dist/lifecycle-workflow-steps.mjs +9 -0
- package/dist/lifecycle-workflow.d.mts +6 -6
- package/dist/lifecycle-workflow.d.ts +6 -6
- package/dist/lifecycle-workflow.js +192 -905
- package/dist/lifecycle-workflow.mjs +3 -1
- package/dist/local-KJ3BSIFJ.mjs +8 -0
- package/dist/next/loader.d.mts +1 -0
- package/dist/next/loader.d.ts +1 -0
- package/dist/next/loader.js +44 -18
- package/dist/next/loader.mjs +18 -13
- package/dist/next.js +32 -9
- package/dist/next.mjs +6 -4
- package/dist/{process-manager-JDUJDYGU.mjs → process-manager-WQHAIVRB.mjs} +1 -1
- package/dist/sandbox.d.mts +6 -0
- package/dist/sandbox.d.ts +6 -0
- package/dist/sandbox.js +1070 -0
- package/dist/sandbox.mjs +19 -0
- package/dist/steps-BnkRQKlc.d.ts +173 -0
- package/dist/steps-u-mGDbP_.d.mts +173 -0
- package/dist/storage.d.mts +11 -0
- package/dist/storage.d.ts +11 -0
- package/dist/storage.js +234 -0
- package/dist/storage.mjs +12 -0
- package/dist/vercel-QZ6INPMV.mjs +11 -0
- package/package.json +26 -5
- package/dist/agent-workflow.d.mts +0 -30
- package/dist/agent-workflow.d.ts +0 -30
- package/dist/agent-workflow.js +0 -5433
- package/dist/agent-workflow.mjs +0 -14
- package/dist/chunk-AML2VCQS.mjs +0 -1287
- package/dist/chunk-FQ67QZOI.mjs +0 -75
- package/dist/chunk-NO7RHGTH.mjs +0 -2367
- package/dist/chunk-NXDVNJRS.mjs +0 -106
- package/dist/chunk-OZZVS6L5.mjs +0 -139
- package/dist/chunk-QRWGDFFY.mjs +0 -75
- package/dist/chunk-SJVFFE5D.mjs +0 -402
- package/dist/chunk-TAXLUVIC.mjs +0 -1
- package/dist/chunk-TGNVXSMX.mjs +0 -399
- package/dist/chunk-YRYXN7W4.mjs +0 -48
- package/dist/chunk-ZIAHPXOJ.mjs +0 -595
- package/dist/client-BKA7XBGW.mjs +0 -15
- package/dist/client-CEeSFGva.d.mts +0 -2376
- package/dist/client-CEeSFGva.d.ts +0 -2376
- package/dist/docker-FB2MJTHJ.mjs +0 -12
- package/dist/local-fs-handlers-SYOCKTPN.mjs +0 -447
- package/dist/sandbox-UENKQV3T.mjs +0 -21
- package/dist/storage-LSDMRW73.mjs +0 -20
- package/dist/vercel-SD3JTECG.mjs +0 -20
- package/dist/vercel-sdk-I6A4MVAN.mjs +0 -8
package/dist/sandbox.js
ADDED
|
@@ -0,0 +1,1070 @@
|
|
|
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 __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/sandbox/entry.ts
|
|
31
|
+
var entry_exports = {};
|
|
32
|
+
__export(entry_exports, {
|
|
33
|
+
dockerSandbox: () => dockerSandbox,
|
|
34
|
+
localSandbox: () => localSandbox,
|
|
35
|
+
vercelSandbox: () => vercelSandbox
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(entry_exports);
|
|
38
|
+
|
|
39
|
+
// src/sandbox/bindings/docker.ts
|
|
40
|
+
var import_ulid = require("ulid");
|
|
41
|
+
async function execDocker(args, opts) {
|
|
42
|
+
const { spawn } = await import("child_process");
|
|
43
|
+
return new Promise((resolve, reject) => {
|
|
44
|
+
const child = spawn("docker", ["sandbox", ...args], {
|
|
45
|
+
signal: opts?.signal
|
|
46
|
+
});
|
|
47
|
+
let stdout = "";
|
|
48
|
+
let stderr = "";
|
|
49
|
+
child.stdout.on("data", (data) => {
|
|
50
|
+
stdout += data.toString();
|
|
51
|
+
});
|
|
52
|
+
child.stderr.on("data", (data) => {
|
|
53
|
+
stderr += data.toString();
|
|
54
|
+
});
|
|
55
|
+
const timeoutId = opts?.timeoutMs ? setTimeout(() => {
|
|
56
|
+
child.kill("SIGTERM");
|
|
57
|
+
reject(new Error(`docker sandbox ${args[0]} timed out`));
|
|
58
|
+
}, opts.timeoutMs) : void 0;
|
|
59
|
+
child.on("error", (err) => {
|
|
60
|
+
if (timeoutId) {
|
|
61
|
+
clearTimeout(timeoutId);
|
|
62
|
+
}
|
|
63
|
+
reject(err);
|
|
64
|
+
});
|
|
65
|
+
child.on("close", (code) => {
|
|
66
|
+
if (timeoutId) {
|
|
67
|
+
clearTimeout(timeoutId);
|
|
68
|
+
}
|
|
69
|
+
resolve({ stdout, stderr, exitCode: code ?? 0 });
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
var ensurePromises = /* @__PURE__ */ new Map();
|
|
74
|
+
var activeSandboxes = /* @__PURE__ */ new Set();
|
|
75
|
+
var cleanupRegistered = false;
|
|
76
|
+
var _execSync = null;
|
|
77
|
+
async function registerCleanup() {
|
|
78
|
+
if (cleanupRegistered) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
cleanupRegistered = true;
|
|
82
|
+
const cp = await import("child_process");
|
|
83
|
+
_execSync = cp.execSync;
|
|
84
|
+
const cleanup = () => {
|
|
85
|
+
if (!_execSync) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
for (const name of Array.from(activeSandboxes)) {
|
|
89
|
+
try {
|
|
90
|
+
_execSync(`docker sandbox stop ${name}`, {
|
|
91
|
+
timeout: 1e4,
|
|
92
|
+
stdio: "pipe"
|
|
93
|
+
});
|
|
94
|
+
} catch {
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
process.on("exit", cleanup);
|
|
99
|
+
process.on("SIGINT", () => {
|
|
100
|
+
cleanup();
|
|
101
|
+
process.exit(130);
|
|
102
|
+
});
|
|
103
|
+
process.on("SIGTERM", () => {
|
|
104
|
+
cleanup();
|
|
105
|
+
process.exit(143);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
async function ensureSandbox(sandboxName) {
|
|
109
|
+
const existing = ensurePromises.get(sandboxName);
|
|
110
|
+
if (existing) {
|
|
111
|
+
return existing;
|
|
112
|
+
}
|
|
113
|
+
const promise = (async () => {
|
|
114
|
+
const ls = await execDocker(["ls", "-q"], { timeoutMs: 1e4 });
|
|
115
|
+
const existingNames = ls.exitCode === 0 ? ls.stdout.split("\n").map((s) => s.trim()).filter(Boolean) : [];
|
|
116
|
+
if (existingNames.includes(sandboxName)) {
|
|
117
|
+
activeSandboxes.add(sandboxName);
|
|
118
|
+
registerCleanup();
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const path = await import("path");
|
|
122
|
+
const os = await import("os");
|
|
123
|
+
const fs = await import("fs/promises");
|
|
124
|
+
const workspaceDir = path.join(
|
|
125
|
+
os.tmpdir(),
|
|
126
|
+
"agent-docker-sandbox",
|
|
127
|
+
sandboxName
|
|
128
|
+
);
|
|
129
|
+
await fs.mkdir(workspaceDir, { recursive: true });
|
|
130
|
+
const create = await execDocker(
|
|
131
|
+
["create", "--name", sandboxName, "shell", workspaceDir],
|
|
132
|
+
{ timeoutMs: 6e4 }
|
|
133
|
+
);
|
|
134
|
+
if (create.exitCode !== 0) {
|
|
135
|
+
if (create.stderr.includes("already exists")) {
|
|
136
|
+
activeSandboxes.add(sandboxName);
|
|
137
|
+
registerCleanup();
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
throw new Error(
|
|
141
|
+
`Failed to create docker sandbox "${sandboxName}": ${create.stderr}`
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
activeSandboxes.add(sandboxName);
|
|
145
|
+
registerCleanup();
|
|
146
|
+
})();
|
|
147
|
+
ensurePromises.set(sandboxName, promise);
|
|
148
|
+
try {
|
|
149
|
+
await promise;
|
|
150
|
+
} catch (e) {
|
|
151
|
+
ensurePromises.delete(sandboxName);
|
|
152
|
+
throw e;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
var DEFAULT_DOCKER_CWD = "/home/agent/workspace";
|
|
156
|
+
var DockerSandboxInstance = class {
|
|
157
|
+
cwd;
|
|
158
|
+
sandboxName;
|
|
159
|
+
processes = /* @__PURE__ */ new Map();
|
|
160
|
+
constructor(sandboxName, cwd) {
|
|
161
|
+
this.sandboxName = sandboxName;
|
|
162
|
+
this.cwd = cwd ?? DEFAULT_DOCKER_CWD;
|
|
163
|
+
}
|
|
164
|
+
async exec(opts) {
|
|
165
|
+
await ensureSandbox(this.sandboxName);
|
|
166
|
+
const { spawn } = await import("child_process");
|
|
167
|
+
const commandId = `command_${(0, import_ulid.ulid)()}`;
|
|
168
|
+
const envFlags = opts.env ? Object.entries(opts.env).flatMap(([k, v]) => ["-e", `${k}=${v}`]) : [];
|
|
169
|
+
const cwdFlags = opts.cwd ? ["-w", opts.cwd] : [];
|
|
170
|
+
const baseCmd = opts.sudo ? ["sudo", opts.command, ...opts.args ?? []] : opts.args ? [opts.command, ...opts.args] : [opts.command];
|
|
171
|
+
const fullCmd = baseCmd;
|
|
172
|
+
const child = spawn(
|
|
173
|
+
"docker",
|
|
174
|
+
[
|
|
175
|
+
"sandbox",
|
|
176
|
+
"exec",
|
|
177
|
+
...envFlags,
|
|
178
|
+
...cwdFlags,
|
|
179
|
+
this.sandboxName,
|
|
180
|
+
...fullCmd
|
|
181
|
+
],
|
|
182
|
+
{ signal: opts.signal }
|
|
183
|
+
);
|
|
184
|
+
this.processes.set(commandId, child);
|
|
185
|
+
let stdout = "";
|
|
186
|
+
let stderr = "";
|
|
187
|
+
const logQueue = [];
|
|
188
|
+
let logResolve = null;
|
|
189
|
+
let closed = false;
|
|
190
|
+
child.stdout.on("data", (data) => {
|
|
191
|
+
const str = String(data);
|
|
192
|
+
stdout += str;
|
|
193
|
+
logQueue.push({ stream: "stdout", data: str });
|
|
194
|
+
logResolve?.();
|
|
195
|
+
});
|
|
196
|
+
child.stderr.on("data", (data) => {
|
|
197
|
+
const str = String(data);
|
|
198
|
+
stderr += str;
|
|
199
|
+
logQueue.push({ stream: "stderr", data: str });
|
|
200
|
+
logResolve?.();
|
|
201
|
+
});
|
|
202
|
+
const result = new Promise((resolve, reject) => {
|
|
203
|
+
child.on("error", (err) => {
|
|
204
|
+
this.processes.delete(commandId);
|
|
205
|
+
closed = true;
|
|
206
|
+
logResolve?.();
|
|
207
|
+
reject(err);
|
|
208
|
+
});
|
|
209
|
+
child.on("close", (code) => {
|
|
210
|
+
this.processes.delete(commandId);
|
|
211
|
+
closed = true;
|
|
212
|
+
logResolve?.();
|
|
213
|
+
resolve({ stdout, stderr, exitCode: code ?? 0 });
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
async function* logs() {
|
|
217
|
+
while (!closed || logQueue.length > 0) {
|
|
218
|
+
const entry = logQueue.shift();
|
|
219
|
+
if (entry) {
|
|
220
|
+
yield entry;
|
|
221
|
+
} else if (!closed) {
|
|
222
|
+
await new Promise((r) => {
|
|
223
|
+
logResolve = r;
|
|
224
|
+
});
|
|
225
|
+
logResolve = null;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return { commandId, logs, result };
|
|
230
|
+
}
|
|
231
|
+
async readFile(opts) {
|
|
232
|
+
await ensureSandbox(this.sandboxName);
|
|
233
|
+
const result = await execDocker(
|
|
234
|
+
[
|
|
235
|
+
"exec",
|
|
236
|
+
this.sandboxName,
|
|
237
|
+
"bash",
|
|
238
|
+
"-c",
|
|
239
|
+
`base64 '${opts.path.replace(/'/g, "'\\''")}'`
|
|
240
|
+
],
|
|
241
|
+
{ timeoutMs: 3e4, signal: opts.signal }
|
|
242
|
+
);
|
|
243
|
+
if (result.exitCode !== 0) {
|
|
244
|
+
if (result.stderr.includes("No such file") || result.stderr.includes("ENOENT")) {
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
throw new Error(`readFile failed: ${result.stderr}`);
|
|
248
|
+
}
|
|
249
|
+
return Buffer.from(result.stdout.trim(), "base64");
|
|
250
|
+
}
|
|
251
|
+
async writeFiles(opts) {
|
|
252
|
+
await ensureSandbox(this.sandboxName);
|
|
253
|
+
for (const file of opts.files) {
|
|
254
|
+
const fullPath = opts.destPath ? `${opts.destPath}/${file.path}` : file.path;
|
|
255
|
+
const parentDir = fullPath.substring(0, fullPath.lastIndexOf("/"));
|
|
256
|
+
if (parentDir) {
|
|
257
|
+
await execDocker(["exec", this.sandboxName, "mkdir", "-p", parentDir], {
|
|
258
|
+
signal: opts.signal
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
const b64 = typeof file.content === "string" ? Buffer.from(file.content).toString("base64") : file.content.toString("base64");
|
|
262
|
+
await execDocker(
|
|
263
|
+
[
|
|
264
|
+
"exec",
|
|
265
|
+
this.sandboxName,
|
|
266
|
+
"bash",
|
|
267
|
+
"-c",
|
|
268
|
+
`echo '${b64}' | base64 -d > '${fullPath.replace(/'/g, "'\\''")}'`
|
|
269
|
+
],
|
|
270
|
+
{ signal: opts.signal }
|
|
271
|
+
);
|
|
272
|
+
if (file.path.endsWith(".sh")) {
|
|
273
|
+
await execDocker(["exec", this.sandboxName, "chmod", "+x", fullPath], {
|
|
274
|
+
signal: opts.signal
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
// biome-ignore lint/suspicious/useAwait: .
|
|
280
|
+
async getDomain(opts) {
|
|
281
|
+
return `http://localhost:${opts.port}`;
|
|
282
|
+
}
|
|
283
|
+
// biome-ignore lint/suspicious/useAwait: .
|
|
284
|
+
async kill(opts) {
|
|
285
|
+
const child = this.processes.get(opts.commandId);
|
|
286
|
+
if (child) {
|
|
287
|
+
child.kill("SIGTERM");
|
|
288
|
+
this.processes.delete(opts.commandId);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
// biome-ignore lint/suspicious/useAwait: .
|
|
292
|
+
async getStatus() {
|
|
293
|
+
return "running";
|
|
294
|
+
}
|
|
295
|
+
async start() {
|
|
296
|
+
await ensureSandbox(this.sandboxName);
|
|
297
|
+
}
|
|
298
|
+
async stop() {
|
|
299
|
+
await execDocker(["stop", this.sandboxName], { timeoutMs: 3e4 });
|
|
300
|
+
activeSandboxes.delete(this.sandboxName);
|
|
301
|
+
ensurePromises.delete(this.sandboxName);
|
|
302
|
+
}
|
|
303
|
+
// biome-ignore lint/suspicious/useAwait: .
|
|
304
|
+
async snapshot() {
|
|
305
|
+
throw new Error("snapshot is not supported for docker sandboxes");
|
|
306
|
+
}
|
|
307
|
+
// biome-ignore lint/suspicious/useAwait: .
|
|
308
|
+
async updateNetworkPolicy() {
|
|
309
|
+
throw new Error(
|
|
310
|
+
"updateNetworkPolicy is not supported for docker sandboxes"
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
function dockerSandbox() {
|
|
315
|
+
return {
|
|
316
|
+
type: "docker",
|
|
317
|
+
async create(opts) {
|
|
318
|
+
const sandboxName = `agent-${(0, import_ulid.ulid)()}`;
|
|
319
|
+
const cwd = opts.setup?.config?.cwd;
|
|
320
|
+
await ensureSandbox(sandboxName);
|
|
321
|
+
const instance = new DockerSandboxInstance(sandboxName, cwd);
|
|
322
|
+
if (opts.setup?.run) {
|
|
323
|
+
await opts.setup.run(instance);
|
|
324
|
+
}
|
|
325
|
+
return {
|
|
326
|
+
instance,
|
|
327
|
+
metadata: { sandboxName }
|
|
328
|
+
};
|
|
329
|
+
},
|
|
330
|
+
// biome-ignore lint/suspicious/useAwait: .
|
|
331
|
+
async connect(opts) {
|
|
332
|
+
return new DockerSandboxInstance(opts.metadata.sandboxName);
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// src/sandbox/bindings/local.ts
|
|
338
|
+
var import_ulid2 = require("ulid");
|
|
339
|
+
var LocalSandboxInstance = class {
|
|
340
|
+
cwd;
|
|
341
|
+
basePath;
|
|
342
|
+
processes = /* @__PURE__ */ new Map();
|
|
343
|
+
constructor(basePath) {
|
|
344
|
+
this.basePath = basePath;
|
|
345
|
+
this.cwd = basePath;
|
|
346
|
+
}
|
|
347
|
+
async exec(opts) {
|
|
348
|
+
const { spawn } = await import("child_process");
|
|
349
|
+
const path = await import("path");
|
|
350
|
+
const commandId = `command_${(0, import_ulid2.ulid)()}`;
|
|
351
|
+
const finalCmd = opts.sudo ? "sudo" : opts.command;
|
|
352
|
+
const finalArgs = opts.sudo ? [opts.command, ...opts.args ?? []] : opts.args ?? [];
|
|
353
|
+
const child = spawn(finalCmd, finalArgs, {
|
|
354
|
+
cwd: opts.cwd ? path.resolve(this.basePath, opts.cwd) : this.basePath,
|
|
355
|
+
env: opts.env ? { ...process.env, ...opts.env } : void 0,
|
|
356
|
+
signal: opts.signal
|
|
357
|
+
});
|
|
358
|
+
this.processes.set(commandId, child);
|
|
359
|
+
let stdout = "";
|
|
360
|
+
let stderr = "";
|
|
361
|
+
const logQueue = [];
|
|
362
|
+
let logResolve = null;
|
|
363
|
+
let closed = false;
|
|
364
|
+
child.stdout.on("data", (data) => {
|
|
365
|
+
const str = String(data);
|
|
366
|
+
stdout += str;
|
|
367
|
+
logQueue.push({ stream: "stdout", data: str });
|
|
368
|
+
logResolve?.();
|
|
369
|
+
});
|
|
370
|
+
child.stderr.on("data", (data) => {
|
|
371
|
+
const str = String(data);
|
|
372
|
+
stderr += str;
|
|
373
|
+
logQueue.push({ stream: "stderr", data: str });
|
|
374
|
+
logResolve?.();
|
|
375
|
+
});
|
|
376
|
+
const result = new Promise((resolve, reject) => {
|
|
377
|
+
child.on("error", (err) => {
|
|
378
|
+
this.processes.delete(commandId);
|
|
379
|
+
closed = true;
|
|
380
|
+
logResolve?.();
|
|
381
|
+
reject(err);
|
|
382
|
+
});
|
|
383
|
+
child.on("close", (code) => {
|
|
384
|
+
this.processes.delete(commandId);
|
|
385
|
+
closed = true;
|
|
386
|
+
logResolve?.();
|
|
387
|
+
resolve({ stdout, stderr, exitCode: code ?? 0 });
|
|
388
|
+
});
|
|
389
|
+
});
|
|
390
|
+
async function* logs() {
|
|
391
|
+
while (!closed || logQueue.length > 0) {
|
|
392
|
+
const entry = logQueue.shift();
|
|
393
|
+
if (entry) {
|
|
394
|
+
yield entry;
|
|
395
|
+
} else if (!closed) {
|
|
396
|
+
await new Promise((r) => {
|
|
397
|
+
logResolve = r;
|
|
398
|
+
});
|
|
399
|
+
logResolve = null;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
return { commandId, logs, result };
|
|
404
|
+
}
|
|
405
|
+
async readFile(opts) {
|
|
406
|
+
const fs = await import("fs/promises");
|
|
407
|
+
const path = await import("path");
|
|
408
|
+
const fullPath = path.resolve(this.basePath, opts.path);
|
|
409
|
+
try {
|
|
410
|
+
return await fs.readFile(fullPath);
|
|
411
|
+
} catch (e) {
|
|
412
|
+
if (e instanceof Error && "code" in e && e.code === "ENOENT") {
|
|
413
|
+
return null;
|
|
414
|
+
}
|
|
415
|
+
throw e;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
async writeFiles(opts) {
|
|
419
|
+
const fs = await import("fs/promises");
|
|
420
|
+
const pathMod = await import("path");
|
|
421
|
+
for (const file of opts.files) {
|
|
422
|
+
const fullPath = pathMod.resolve(this.basePath, opts.destPath, file.path);
|
|
423
|
+
await fs.mkdir(pathMod.dirname(fullPath), { recursive: true });
|
|
424
|
+
await fs.writeFile(fullPath, file.content);
|
|
425
|
+
if (file.path.endsWith(".sh")) {
|
|
426
|
+
await fs.chmod(fullPath, 493);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
// biome-ignore lint/suspicious/useAwait: .
|
|
431
|
+
async getDomain(opts) {
|
|
432
|
+
return `http://localhost:${opts.port}`;
|
|
433
|
+
}
|
|
434
|
+
// biome-ignore lint/suspicious/useAwait: .
|
|
435
|
+
async kill(opts) {
|
|
436
|
+
const child = this.processes.get(opts.commandId);
|
|
437
|
+
if (child) {
|
|
438
|
+
child.kill("SIGTERM");
|
|
439
|
+
this.processes.delete(opts.commandId);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
// biome-ignore lint/suspicious/useAwait: .
|
|
443
|
+
async getStatus() {
|
|
444
|
+
return "running";
|
|
445
|
+
}
|
|
446
|
+
async start() {
|
|
447
|
+
}
|
|
448
|
+
// biome-ignore lint/suspicious/useAwait: .
|
|
449
|
+
async stop() {
|
|
450
|
+
throw new Error("stop is not supported for local sandboxes");
|
|
451
|
+
}
|
|
452
|
+
// biome-ignore lint/suspicious/useAwait: .
|
|
453
|
+
async snapshot() {
|
|
454
|
+
throw new Error("snapshot is not supported for local sandboxes");
|
|
455
|
+
}
|
|
456
|
+
// biome-ignore lint/suspicious/useAwait: .
|
|
457
|
+
async updateNetworkPolicy() {
|
|
458
|
+
throw new Error("updateNetworkPolicy is not supported for local sandboxes");
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
function localSandbox() {
|
|
462
|
+
return {
|
|
463
|
+
type: "local",
|
|
464
|
+
async create(opts) {
|
|
465
|
+
const basePath = opts.setup.config?.cwd ?? process.cwd();
|
|
466
|
+
const instance = new LocalSandboxInstance(basePath);
|
|
467
|
+
if (opts.setup?.run) {
|
|
468
|
+
await opts.setup.run(instance);
|
|
469
|
+
}
|
|
470
|
+
return {
|
|
471
|
+
instance,
|
|
472
|
+
metadata: { basePath, pid: process.pid }
|
|
473
|
+
};
|
|
474
|
+
},
|
|
475
|
+
// biome-ignore lint/suspicious/useAwait: .
|
|
476
|
+
async connect(opts) {
|
|
477
|
+
const basePath = opts.metadata.basePath;
|
|
478
|
+
return new LocalSandboxInstance(basePath);
|
|
479
|
+
}
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// src/sandbox/bindings/vercel.ts
|
|
484
|
+
var import_api = require("workflow/api");
|
|
485
|
+
|
|
486
|
+
// src/sandbox/bindings/vercel-lifecycle/workflow.ts
|
|
487
|
+
var import_workflow = require("workflow");
|
|
488
|
+
|
|
489
|
+
// src/utils/logger.ts
|
|
490
|
+
var LOG_LEVEL_PRIORITY = {
|
|
491
|
+
info: 0,
|
|
492
|
+
warn: 1,
|
|
493
|
+
error: 2,
|
|
494
|
+
silent: 3
|
|
495
|
+
};
|
|
496
|
+
function getLevel(config) {
|
|
497
|
+
return config.level ?? "warn";
|
|
498
|
+
}
|
|
499
|
+
function getPrefix(config) {
|
|
500
|
+
return config.prefix ?? "agent";
|
|
501
|
+
}
|
|
502
|
+
function shouldLog(config, level) {
|
|
503
|
+
return LOG_LEVEL_PRIORITY[level] >= LOG_LEVEL_PRIORITY[getLevel(config)];
|
|
504
|
+
}
|
|
505
|
+
function formatTag(config, subsystem) {
|
|
506
|
+
return `[${getPrefix(config)}:${config.name}:${subsystem}]`;
|
|
507
|
+
}
|
|
508
|
+
function formatData(context, extra) {
|
|
509
|
+
const merged = { ...context, ...extra };
|
|
510
|
+
const entries = Object.entries(merged).filter(
|
|
511
|
+
([, v]) => v !== void 0 && v !== null
|
|
512
|
+
);
|
|
513
|
+
if (entries.length === 0) {
|
|
514
|
+
return void 0;
|
|
515
|
+
}
|
|
516
|
+
return Object.fromEntries(entries);
|
|
517
|
+
}
|
|
518
|
+
var Logger = class _Logger {
|
|
519
|
+
subsystem;
|
|
520
|
+
config;
|
|
521
|
+
context;
|
|
522
|
+
constructor({
|
|
523
|
+
subsystem,
|
|
524
|
+
config,
|
|
525
|
+
context
|
|
526
|
+
}) {
|
|
527
|
+
this.subsystem = subsystem;
|
|
528
|
+
this.config = config;
|
|
529
|
+
this.context = context ?? {};
|
|
530
|
+
}
|
|
531
|
+
child({
|
|
532
|
+
subsystem,
|
|
533
|
+
context
|
|
534
|
+
}) {
|
|
535
|
+
return new _Logger({
|
|
536
|
+
config: this.config,
|
|
537
|
+
subsystem: subsystem ? `${this.subsystem}:${subsystem}` : this.subsystem,
|
|
538
|
+
context: { ...this.context, ...context }
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
withContext(context) {
|
|
542
|
+
return new _Logger({
|
|
543
|
+
config: this.config,
|
|
544
|
+
subsystem: this.subsystem,
|
|
545
|
+
context: { ...this.context, ...context }
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
info(message, data) {
|
|
549
|
+
if (!shouldLog(this.config, "info")) {
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
const d = formatData(this.context, data);
|
|
553
|
+
if (d) {
|
|
554
|
+
console.info(formatTag(this.config, this.subsystem), message, d);
|
|
555
|
+
} else {
|
|
556
|
+
console.info(formatTag(this.config, this.subsystem), message);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
warn(message, data) {
|
|
560
|
+
if (!shouldLog(this.config, "warn")) {
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
const d = formatData(this.context, data);
|
|
564
|
+
if (d) {
|
|
565
|
+
console.warn(formatTag(this.config, this.subsystem), message, d);
|
|
566
|
+
} else {
|
|
567
|
+
console.warn(formatTag(this.config, this.subsystem), message);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
error(message, data) {
|
|
571
|
+
if (!shouldLog(this.config, "error")) {
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
574
|
+
const d = formatData(this.context, data);
|
|
575
|
+
if (d) {
|
|
576
|
+
console.error(formatTag(this.config, this.subsystem), message, d);
|
|
577
|
+
} else {
|
|
578
|
+
console.error(formatTag(this.config, this.subsystem), message);
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Returns a function that, when called, logs the elapsed time at info level.
|
|
583
|
+
* Pass `logOnStart: true` to also log when the timer begins.
|
|
584
|
+
*
|
|
585
|
+
* @example
|
|
586
|
+
* const done = log.time("sandbox setup", { sandboxId }, { logOnStart: true });
|
|
587
|
+
* await setup();
|
|
588
|
+
* done(); // start: [agent:default:sandbox] sandbox setup { sandboxId: '...' }
|
|
589
|
+
* // end: [agent:default:sandbox] sandbox setup { sandboxId: '...', durationMs: 123 }
|
|
590
|
+
*/
|
|
591
|
+
time(message, data, opts) {
|
|
592
|
+
if (opts?.logOnStart) {
|
|
593
|
+
this.info(`[start] ${message}`, data);
|
|
594
|
+
}
|
|
595
|
+
const t0 = Date.now();
|
|
596
|
+
return (endData) => {
|
|
597
|
+
this.info(opts?.logOnStart ? `[end] ${message}` : message, {
|
|
598
|
+
...data,
|
|
599
|
+
...endData,
|
|
600
|
+
durationMs: Date.now() - t0
|
|
601
|
+
});
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
};
|
|
605
|
+
function createLogger({
|
|
606
|
+
config,
|
|
607
|
+
subsystem,
|
|
608
|
+
context
|
|
609
|
+
}) {
|
|
610
|
+
return new Logger({ config, subsystem, context });
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// src/sandbox/bindings/vercel-lifecycle/steps.ts
|
|
614
|
+
async function loadSandboxSDK() {
|
|
615
|
+
return (await import("@vercel/sandbox")).Sandbox;
|
|
616
|
+
}
|
|
617
|
+
var DEFAULT_POLL_INTERVAL_MS = 2 * 60 * 1e3;
|
|
618
|
+
var DEFAULT_IDLE_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
619
|
+
var SNAPSHOT_BEFORE_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
620
|
+
var getTestCredentials = () => process.env.NODE_ENV === "test" ? {
|
|
621
|
+
token: process.env.TEST_VERCEL_TOKEN,
|
|
622
|
+
teamId: process.env.TEST_VERCEL_TEAM_ID,
|
|
623
|
+
projectId: process.env.TEST_VERCEL_PROJECT_ID
|
|
624
|
+
} : {};
|
|
625
|
+
async function checkAndSnapshotStep(input) {
|
|
626
|
+
"use step";
|
|
627
|
+
const storage = input.agent.storage;
|
|
628
|
+
const log = createLogger({
|
|
629
|
+
config: { ...input.agent.options.logging, name: input.agent.name },
|
|
630
|
+
subsystem: "sandbox:lifecycle",
|
|
631
|
+
context: { sandboxId: input.sandboxId }
|
|
632
|
+
});
|
|
633
|
+
log.info("lifecycle check started", {
|
|
634
|
+
vercelSandboxId: input.vercelSandboxId
|
|
635
|
+
});
|
|
636
|
+
const record = await storage.sandbox.get(input.sandboxId);
|
|
637
|
+
if (!record) {
|
|
638
|
+
log.warn("sandbox record not found, exiting lifecycle");
|
|
639
|
+
return { action: "exit", reason: "not_found" };
|
|
640
|
+
}
|
|
641
|
+
const metadata = record.setup?.metadata;
|
|
642
|
+
const currentSandboxId = metadata?.sandboxId ?? null;
|
|
643
|
+
if (currentSandboxId !== input.vercelSandboxId) {
|
|
644
|
+
log.info("sandbox ID changed, exiting lifecycle", {
|
|
645
|
+
expected: input.vercelSandboxId,
|
|
646
|
+
actual: currentSandboxId
|
|
647
|
+
});
|
|
648
|
+
return { action: "exit", reason: "sandboxId_changed" };
|
|
649
|
+
}
|
|
650
|
+
if (!currentSandboxId) {
|
|
651
|
+
log.warn("no current sandbox ID in metadata, exiting lifecycle");
|
|
652
|
+
return { action: "exit", reason: "not_found" };
|
|
653
|
+
}
|
|
654
|
+
const pollIntervalMs = input.config?.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
655
|
+
const idleTimeoutMs = input.config?.stopAfterInactiveMs ?? DEFAULT_IDLE_TIMEOUT_MS;
|
|
656
|
+
const snapshotBeforeTimeoutMs = input.config?.snapshotBeforeTimeoutMs ?? SNAPSHOT_BEFORE_TIMEOUT_MS;
|
|
657
|
+
const now = Date.now();
|
|
658
|
+
const lastActivity = record.lastActiveAt ?? record.createdAt ?? now;
|
|
659
|
+
const idleDuration = now - lastActivity;
|
|
660
|
+
const shouldSnapshotDueToIdle = idleDuration > idleTimeoutMs;
|
|
661
|
+
let shouldSnapshotDueToTimeout = false;
|
|
662
|
+
try {
|
|
663
|
+
const SandboxSDK = await loadSandboxSDK();
|
|
664
|
+
const sandbox = await SandboxSDK.get({
|
|
665
|
+
sandboxId: currentSandboxId,
|
|
666
|
+
...getTestCredentials()
|
|
667
|
+
});
|
|
668
|
+
if (sandbox.timeout < snapshotBeforeTimeoutMs) {
|
|
669
|
+
shouldSnapshotDueToTimeout = true;
|
|
670
|
+
}
|
|
671
|
+
} catch {
|
|
672
|
+
log.warn("failed to get sandbox from SDK, exiting lifecycle", {
|
|
673
|
+
vercelSandboxId: currentSandboxId
|
|
674
|
+
});
|
|
675
|
+
return { action: "exit", reason: "not_found" };
|
|
676
|
+
}
|
|
677
|
+
if (shouldSnapshotDueToIdle || shouldSnapshotDueToTimeout) {
|
|
678
|
+
const reason = shouldSnapshotDueToIdle ? "idle" : "timeout";
|
|
679
|
+
log.info("snapshotting sandbox before exit", {
|
|
680
|
+
reason,
|
|
681
|
+
idleDurationMs: idleDuration,
|
|
682
|
+
vercelSandboxId: currentSandboxId
|
|
683
|
+
});
|
|
684
|
+
try {
|
|
685
|
+
const SandboxSDK = await loadSandboxSDK();
|
|
686
|
+
const sandbox = await SandboxSDK.get({
|
|
687
|
+
sandboxId: currentSandboxId,
|
|
688
|
+
...getTestCredentials()
|
|
689
|
+
});
|
|
690
|
+
const snapshot = await sandbox.snapshot();
|
|
691
|
+
log.info("snapshot created", { snapshotId: snapshot.snapshotId });
|
|
692
|
+
await storage.sandbox.update(input.sandboxId, {
|
|
693
|
+
setup: {
|
|
694
|
+
...record.setup,
|
|
695
|
+
metadata: { sandboxId: null, snapshotId: snapshot.snapshotId }
|
|
696
|
+
}
|
|
697
|
+
});
|
|
698
|
+
log.info("sandbox record updated with snapshot");
|
|
699
|
+
} catch (e) {
|
|
700
|
+
log.error("failed to snapshot sandbox", { cause: e });
|
|
701
|
+
return e instanceof Error ? e : new Error(String(e));
|
|
702
|
+
}
|
|
703
|
+
return { action: "exit", reason };
|
|
704
|
+
}
|
|
705
|
+
log.info("sandbox still active, continuing lifecycle", {
|
|
706
|
+
idleDurationMs: idleDuration,
|
|
707
|
+
nextPollMs: pollIntervalMs
|
|
708
|
+
});
|
|
709
|
+
return { action: "continue", nextPollMs: pollIntervalMs };
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
// src/sandbox/bindings/vercel-lifecycle/workflow.ts
|
|
713
|
+
var DEFAULT_POLL_MS = 2 * 60 * 1e3;
|
|
714
|
+
async function sandboxLifecycleWorkflow({
|
|
715
|
+
input
|
|
716
|
+
}) {
|
|
717
|
+
"use workflow";
|
|
718
|
+
let nextPollMs = input.config?.pollIntervalMs ?? DEFAULT_POLL_MS;
|
|
719
|
+
const log = createLogger({
|
|
720
|
+
config: { ...input.agent.options.logging, name: input.agent.name },
|
|
721
|
+
subsystem: "sandbox:lifecycle",
|
|
722
|
+
context: { sandboxId: input.sandboxId }
|
|
723
|
+
});
|
|
724
|
+
log.info("lifecycle workflow started", {
|
|
725
|
+
sandboxId: input.sandboxId,
|
|
726
|
+
vercelSandboxId: input.vercelSandboxId,
|
|
727
|
+
pollMs: nextPollMs
|
|
728
|
+
});
|
|
729
|
+
while (true) {
|
|
730
|
+
await (0, import_workflow.sleep)(nextPollMs);
|
|
731
|
+
const result = await checkAndSnapshotStep(input);
|
|
732
|
+
if (result instanceof Error) {
|
|
733
|
+
log.error("lifecycle step failed", {
|
|
734
|
+
sandboxId: input.sandboxId,
|
|
735
|
+
error: result.message
|
|
736
|
+
});
|
|
737
|
+
break;
|
|
738
|
+
}
|
|
739
|
+
if (result.action === "exit") {
|
|
740
|
+
log.info("lifecycle workflow exiting", {
|
|
741
|
+
sandboxId: input.sandboxId,
|
|
742
|
+
reason: result.reason
|
|
743
|
+
});
|
|
744
|
+
break;
|
|
745
|
+
}
|
|
746
|
+
nextPollMs = result.nextPollMs;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
// src/sandbox/bindings/vercel.ts
|
|
751
|
+
async function loadSandboxSDK2() {
|
|
752
|
+
return (await import("@vercel/sandbox")).Sandbox;
|
|
753
|
+
}
|
|
754
|
+
var MAX_TIMEOUT_MS = 5 * 60 * 60 * 1e3;
|
|
755
|
+
var HOME_DIR = "/home/vercel-sandbox";
|
|
756
|
+
var DEFAULT_VCPUS = 2;
|
|
757
|
+
function isSandboxGoneError(e) {
|
|
758
|
+
if (!(e instanceof Error)) {
|
|
759
|
+
return false;
|
|
760
|
+
}
|
|
761
|
+
const status = e.response?.status ?? e.cause?.response?.status;
|
|
762
|
+
if (status === 410 || status === 422) {
|
|
763
|
+
return true;
|
|
764
|
+
}
|
|
765
|
+
const msg = e.message || String(e);
|
|
766
|
+
return msg.includes("Expected a stream of command data") || msg.includes("Expected a stream of logs");
|
|
767
|
+
}
|
|
768
|
+
var getTestCredentials2 = () => process.env.NODE_ENV === "test" ? {
|
|
769
|
+
token: process.env.TEST_VERCEL_TOKEN,
|
|
770
|
+
teamId: process.env.TEST_VERCEL_TEAM_ID,
|
|
771
|
+
projectId: process.env.TEST_VERCEL_PROJECT_ID
|
|
772
|
+
} : {};
|
|
773
|
+
async function createSdk({
|
|
774
|
+
resources,
|
|
775
|
+
ports,
|
|
776
|
+
networkPolicy,
|
|
777
|
+
snapshotId
|
|
778
|
+
}) {
|
|
779
|
+
const SandboxSDK = await loadSandboxSDK2();
|
|
780
|
+
const base = {
|
|
781
|
+
resources,
|
|
782
|
+
timeout: MAX_TIMEOUT_MS,
|
|
783
|
+
...ports ? { ports } : {},
|
|
784
|
+
...networkPolicy ? { networkPolicy } : {},
|
|
785
|
+
...getTestCredentials2()
|
|
786
|
+
};
|
|
787
|
+
if (snapshotId) {
|
|
788
|
+
return SandboxSDK.create({
|
|
789
|
+
...base,
|
|
790
|
+
source: { type: "snapshot", snapshotId }
|
|
791
|
+
});
|
|
792
|
+
}
|
|
793
|
+
return SandboxSDK.create(base);
|
|
794
|
+
}
|
|
795
|
+
async function createSetupSnapshot({
|
|
796
|
+
sandboxOpts,
|
|
797
|
+
run,
|
|
798
|
+
storage,
|
|
799
|
+
snapshotVersion,
|
|
800
|
+
log
|
|
801
|
+
}) {
|
|
802
|
+
let tempSdk = null;
|
|
803
|
+
try {
|
|
804
|
+
tempSdk = await createSdk(sandboxOpts);
|
|
805
|
+
const tempInstance = new VercelSandboxInstance(tempSdk);
|
|
806
|
+
await run(tempInstance);
|
|
807
|
+
const snapshot = await tempSdk.snapshot();
|
|
808
|
+
await storage.setup.set(snapshotVersion, {
|
|
809
|
+
version: snapshotVersion,
|
|
810
|
+
snapshotId: snapshot.snapshotId,
|
|
811
|
+
createdAt: Date.now(),
|
|
812
|
+
lastUsedAt: null
|
|
813
|
+
});
|
|
814
|
+
await tempSdk.stop().catch(() => void 0);
|
|
815
|
+
} catch (error) {
|
|
816
|
+
log.error("failed to create setup snapshot", {
|
|
817
|
+
snapshotVersion,
|
|
818
|
+
cause: error
|
|
819
|
+
});
|
|
820
|
+
if (tempSdk) {
|
|
821
|
+
await tempSdk.stop().catch(() => void 0);
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
var VercelSandboxInstance = class {
|
|
826
|
+
sdk;
|
|
827
|
+
cwd;
|
|
828
|
+
constructor(sdk, cwd) {
|
|
829
|
+
this.sdk = sdk;
|
|
830
|
+
this.cwd = cwd ?? HOME_DIR;
|
|
831
|
+
}
|
|
832
|
+
async exec({
|
|
833
|
+
command,
|
|
834
|
+
args,
|
|
835
|
+
cwd,
|
|
836
|
+
env,
|
|
837
|
+
sudo,
|
|
838
|
+
signal
|
|
839
|
+
}) {
|
|
840
|
+
const output = await this.sdk.runCommand({
|
|
841
|
+
cmd: command,
|
|
842
|
+
args,
|
|
843
|
+
cwd: cwd ?? this.cwd,
|
|
844
|
+
env,
|
|
845
|
+
sudo,
|
|
846
|
+
signal,
|
|
847
|
+
detached: true
|
|
848
|
+
});
|
|
849
|
+
let stdout = "";
|
|
850
|
+
let stderr = "";
|
|
851
|
+
const logBuffer = [];
|
|
852
|
+
const state = {
|
|
853
|
+
resolve: null,
|
|
854
|
+
consumed: false
|
|
855
|
+
};
|
|
856
|
+
const consumeLogs = (async () => {
|
|
857
|
+
try {
|
|
858
|
+
for await (const entry of output.logs()) {
|
|
859
|
+
if (entry.stream === "stdout") {
|
|
860
|
+
stdout += entry.data;
|
|
861
|
+
} else {
|
|
862
|
+
stderr += entry.data;
|
|
863
|
+
}
|
|
864
|
+
logBuffer.push(entry);
|
|
865
|
+
state.resolve?.();
|
|
866
|
+
}
|
|
867
|
+
} catch {
|
|
868
|
+
}
|
|
869
|
+
state.consumed = true;
|
|
870
|
+
state.resolve?.();
|
|
871
|
+
})();
|
|
872
|
+
async function* logs() {
|
|
873
|
+
let index = 0;
|
|
874
|
+
while (!state.consumed || index < logBuffer.length) {
|
|
875
|
+
if (index < logBuffer.length) {
|
|
876
|
+
yield logBuffer[index++];
|
|
877
|
+
} else {
|
|
878
|
+
await new Promise((r) => {
|
|
879
|
+
state.resolve = r;
|
|
880
|
+
});
|
|
881
|
+
state.resolve = null;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
const result = consumeLogs.then(async () => {
|
|
886
|
+
try {
|
|
887
|
+
const finished = await output.wait();
|
|
888
|
+
return { stdout, stderr, exitCode: finished.exitCode };
|
|
889
|
+
} catch (e) {
|
|
890
|
+
if (isSandboxGoneError(e)) {
|
|
891
|
+
return { stdout, stderr, exitCode: 1 };
|
|
892
|
+
}
|
|
893
|
+
throw e;
|
|
894
|
+
}
|
|
895
|
+
});
|
|
896
|
+
return { commandId: output.cmdId, logs, result };
|
|
897
|
+
}
|
|
898
|
+
async readFile({
|
|
899
|
+
path: filePath
|
|
900
|
+
}) {
|
|
901
|
+
try {
|
|
902
|
+
return await this.sdk.readFileToBuffer({ path: filePath, cwd: this.cwd });
|
|
903
|
+
} catch {
|
|
904
|
+
return null;
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
async writeFiles({
|
|
908
|
+
files,
|
|
909
|
+
destPath
|
|
910
|
+
}) {
|
|
911
|
+
if (files.length === 0) {
|
|
912
|
+
return;
|
|
913
|
+
}
|
|
914
|
+
const path = await import("path");
|
|
915
|
+
const nativeFiles = files.map((file) => {
|
|
916
|
+
const filePath = path.posix.join(destPath, file.path);
|
|
917
|
+
const absolutePath = path.posix.isAbsolute(filePath) ? filePath : path.posix.join(this.cwd, filePath);
|
|
918
|
+
return {
|
|
919
|
+
path: absolutePath,
|
|
920
|
+
content: typeof file.content === "string" ? Buffer.from(file.content) : file.content
|
|
921
|
+
};
|
|
922
|
+
});
|
|
923
|
+
await this.sdk.writeFiles(nativeFiles);
|
|
924
|
+
const shellScripts = nativeFiles.filter((f) => f.path.endsWith(".sh"));
|
|
925
|
+
if (shellScripts.length > 0) {
|
|
926
|
+
const result = await this.exec({
|
|
927
|
+
command: "chmod",
|
|
928
|
+
args: ["+x", ...shellScripts.map((f) => f.path)]
|
|
929
|
+
});
|
|
930
|
+
await result.result;
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
// biome-ignore lint/suspicious/useAwait: synchronous SDK call
|
|
934
|
+
async getDomain({
|
|
935
|
+
port
|
|
936
|
+
}) {
|
|
937
|
+
return this.sdk.domain(port);
|
|
938
|
+
}
|
|
939
|
+
async kill({
|
|
940
|
+
commandId
|
|
941
|
+
}) {
|
|
942
|
+
const cmd = await this.sdk.getCommand(commandId);
|
|
943
|
+
await cmd.kill();
|
|
944
|
+
}
|
|
945
|
+
// biome-ignore lint/suspicious/useAwait: synchronous SDK getter
|
|
946
|
+
async getStatus() {
|
|
947
|
+
const status = this.sdk.status;
|
|
948
|
+
if (status === "snapshotting") {
|
|
949
|
+
return "stopping";
|
|
950
|
+
}
|
|
951
|
+
if (status === "aborted") {
|
|
952
|
+
return "failed";
|
|
953
|
+
}
|
|
954
|
+
return status;
|
|
955
|
+
}
|
|
956
|
+
async start() {
|
|
957
|
+
const result = await this.exec({ command: "true" });
|
|
958
|
+
await result.result;
|
|
959
|
+
}
|
|
960
|
+
async stop() {
|
|
961
|
+
await this.sdk.stop();
|
|
962
|
+
}
|
|
963
|
+
async snapshot() {
|
|
964
|
+
const snap = await this.sdk.snapshot();
|
|
965
|
+
return { snapshotId: snap.snapshotId };
|
|
966
|
+
}
|
|
967
|
+
async updateNetworkPolicy({
|
|
968
|
+
policy
|
|
969
|
+
}) {
|
|
970
|
+
return await this.sdk.updateNetworkPolicy(policy);
|
|
971
|
+
}
|
|
972
|
+
};
|
|
973
|
+
function vercelSandbox() {
|
|
974
|
+
return {
|
|
975
|
+
type: "vercel",
|
|
976
|
+
async create({ agent, setup, record, signal: _signal, log }) {
|
|
977
|
+
const storage = agent.storage;
|
|
978
|
+
const config = setup.config ?? {};
|
|
979
|
+
const cwd = config.cwd;
|
|
980
|
+
const resources = config.resources ?? { vcpus: DEFAULT_VCPUS };
|
|
981
|
+
const ports = config.ports;
|
|
982
|
+
const networkPolicy = config.networkPolicy ?? setup.networkPolicy ?? void 0;
|
|
983
|
+
const sandboxOpts = {
|
|
984
|
+
resources,
|
|
985
|
+
ports,
|
|
986
|
+
networkPolicy,
|
|
987
|
+
snapshotId: config.snapshotId
|
|
988
|
+
};
|
|
989
|
+
const _startLifecycle = (vercelSandboxId) => {
|
|
990
|
+
if (!record) {
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
993
|
+
(0, import_api.start)(sandboxLifecycleWorkflow, [
|
|
994
|
+
{
|
|
995
|
+
input: {
|
|
996
|
+
agent,
|
|
997
|
+
sandboxId: record.id,
|
|
998
|
+
vercelSandboxId,
|
|
999
|
+
config: config.lifecycle
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
]).catch((e) => {
|
|
1003
|
+
log.error("failed to start lifecycle workflow", { cause: e });
|
|
1004
|
+
});
|
|
1005
|
+
};
|
|
1006
|
+
if (setup.version) {
|
|
1007
|
+
const existing = await storage.setup.get(setup.version);
|
|
1008
|
+
if (existing?.snapshotId) {
|
|
1009
|
+
const sdk2 = await createSdk({
|
|
1010
|
+
...sandboxOpts,
|
|
1011
|
+
snapshotId: existing.snapshotId
|
|
1012
|
+
});
|
|
1013
|
+
const instance2 = new VercelSandboxInstance(sdk2, cwd);
|
|
1014
|
+
storage.setup.set(setup.version, {
|
|
1015
|
+
...existing,
|
|
1016
|
+
version: setup.version,
|
|
1017
|
+
lastUsedAt: Date.now()
|
|
1018
|
+
}).catch(() => void 0);
|
|
1019
|
+
return {
|
|
1020
|
+
instance: instance2,
|
|
1021
|
+
metadata: { sandboxId: sdk2.sandboxId }
|
|
1022
|
+
};
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
if (setup.run) {
|
|
1026
|
+
if (!setup.version) {
|
|
1027
|
+
log.error("setup.run provided without setup.version", { setup });
|
|
1028
|
+
throw new Error("setup.run provided without setup.version");
|
|
1029
|
+
}
|
|
1030
|
+
createSetupSnapshot({
|
|
1031
|
+
sandboxOpts,
|
|
1032
|
+
run: setup.run,
|
|
1033
|
+
storage,
|
|
1034
|
+
snapshotVersion: setup.version,
|
|
1035
|
+
log
|
|
1036
|
+
}).catch((error) => {
|
|
1037
|
+
log.error("background setup snapshot failed", { cause: error });
|
|
1038
|
+
});
|
|
1039
|
+
const sdk2 = await createSdk(sandboxOpts);
|
|
1040
|
+
const instance2 = new VercelSandboxInstance(sdk2, cwd);
|
|
1041
|
+
await setup.run(instance2);
|
|
1042
|
+
return {
|
|
1043
|
+
instance: instance2,
|
|
1044
|
+
metadata: { sandboxId: sdk2.sandboxId }
|
|
1045
|
+
};
|
|
1046
|
+
}
|
|
1047
|
+
const sdk = await createSdk(sandboxOpts);
|
|
1048
|
+
const instance = new VercelSandboxInstance(sdk, cwd);
|
|
1049
|
+
return {
|
|
1050
|
+
instance,
|
|
1051
|
+
metadata: { sandboxId: sdk.sandboxId }
|
|
1052
|
+
};
|
|
1053
|
+
},
|
|
1054
|
+
async connect({ metadata }) {
|
|
1055
|
+
const SandboxSDK = await loadSandboxSDK2();
|
|
1056
|
+
const sdk = await SandboxSDK.get({
|
|
1057
|
+
sandboxId: metadata.sandboxId,
|
|
1058
|
+
...getTestCredentials2()
|
|
1059
|
+
});
|
|
1060
|
+
return new VercelSandboxInstance(sdk);
|
|
1061
|
+
}
|
|
1062
|
+
};
|
|
1063
|
+
}
|
|
1064
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1065
|
+
0 && (module.exports = {
|
|
1066
|
+
dockerSandbox,
|
|
1067
|
+
localSandbox,
|
|
1068
|
+
vercelSandbox
|
|
1069
|
+
});
|
|
1070
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL3NhbmRib3gvZW50cnkudHMiLCAiLi4vc3JjL3NhbmRib3gvYmluZGluZ3MvZG9ja2VyLnRzIiwgIi4uL3NyYy9zYW5kYm94L2JpbmRpbmdzL2xvY2FsLnRzIiwgIi4uL3NyYy9zYW5kYm94L2JpbmRpbmdzL3ZlcmNlbC50cyIsICIuLi9zcmMvc2FuZGJveC9iaW5kaW5ncy92ZXJjZWwtbGlmZWN5Y2xlL3dvcmtmbG93LnRzIiwgIi4uL3NyYy91dGlscy9sb2dnZXIudHMiLCAiLi4vc3JjL3NhbmRib3gvYmluZGluZ3MvdmVyY2VsLWxpZmVjeWNsZS9zdGVwcy50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiZXhwb3J0IHR5cGUge1xuICBFeGVjUmVzdWx0LFxuICBTYW5kYm94QWdlbnRSZWYsXG4gIFNhbmRib3hCaW5kaW5nLFxuICBTYW5kYm94SW5zdGFuY2UsXG4gIFNhbmRib3hTZXR1cEZpZWxkcyxcbiAgVXBsb2FkYWJsZUZpbGUsXG59IGZyb20gXCIuL2FkYXB0ZXJcIjtcbmV4cG9ydCB7IGRvY2tlclNhbmRib3ggfSBmcm9tIFwiLi9iaW5kaW5ncy9kb2NrZXJcIjtcbmV4cG9ydCB7IGxvY2FsU2FuZGJveCB9IGZyb20gXCIuL2JpbmRpbmdzL2xvY2FsXCI7XG5leHBvcnQgeyB2ZXJjZWxTYW5kYm94IH0gZnJvbSBcIi4vYmluZGluZ3MvdmVyY2VsXCI7XG4iLCAiaW1wb3J0IHsgdWxpZCB9IGZyb20gXCJ1bGlkXCI7XG5pbXBvcnQgdHlwZSB7IEV4ZWNSZXN1bHQsIFNhbmRib3hCaW5kaW5nLCBTYW5kYm94SW5zdGFuY2UgfSBmcm9tIFwiLi4vYWRhcHRlclwiO1xuXG5leHBvcnQgdHlwZSBEb2NrZXJCaW5kaW5nQ29uZmlnID0ge1xuICBjd2Q/OiBzdHJpbmc7XG59O1xuXG5leHBvcnQgdHlwZSBEb2NrZXJCaW5kaW5nTWV0YWRhdGEgPSB7XG4gIHNhbmRib3hOYW1lOiBzdHJpbmc7XG59O1xuXG4vKipcbiAqIFJ1biBhIGBkb2NrZXIgc2FuZGJveGAgQ0xJIGNvbW1hbmQgYW5kIHJldHVybiBpdHMgb3V0cHV0LlxuICovXG5hc3luYyBmdW5jdGlvbiBleGVjRG9ja2VyKFxuICBhcmdzOiBzdHJpbmdbXSxcbiAgb3B0cz86IHsgdGltZW91dE1zPzogbnVtYmVyOyBzaWduYWw/OiBBYm9ydFNpZ25hbCB9XG4pOiBQcm9taXNlPHsgc3Rkb3V0OiBzdHJpbmc7IHN0ZGVycjogc3RyaW5nOyBleGl0Q29kZTogbnVtYmVyIH0+IHtcbiAgY29uc3QgeyBzcGF3biB9ID0gYXdhaXQgaW1wb3J0KFwibm9kZTpjaGlsZF9wcm9jZXNzXCIpO1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIGNvbnN0IGNoaWxkID0gc3Bhd24oXCJkb2NrZXJcIiwgW1wic2FuZGJveFwiLCAuLi5hcmdzXSwge1xuICAgICAgc2lnbmFsOiBvcHRzPy5zaWduYWwsXG4gICAgfSk7XG5cbiAgICBsZXQgc3Rkb3V0ID0gXCJcIjtcbiAgICBsZXQgc3RkZXJyID0gXCJcIjtcblxuICAgIGNoaWxkLnN0ZG91dC5vbihcImRhdGFcIiwgKGRhdGE6IEJ1ZmZlcikgPT4ge1xuICAgICAgc3Rkb3V0ICs9IGRhdGEudG9TdHJpbmcoKTtcbiAgICB9KTtcbiAgICBjaGlsZC5zdGRlcnIub24oXCJkYXRhXCIsIChkYXRhOiBCdWZmZXIpID0+IHtcbiAgICAgIHN0ZGVyciArPSBkYXRhLnRvU3RyaW5nKCk7XG4gICAgfSk7XG5cbiAgICBjb25zdCB0aW1lb3V0SWQgPSBvcHRzPy50aW1lb3V0TXNcbiAgICAgID8gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgY2hpbGQua2lsbChcIlNJR1RFUk1cIik7XG4gICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihgZG9ja2VyIHNhbmRib3ggJHthcmdzWzBdfSB0aW1lZCBvdXRgKSk7XG4gICAgICAgIH0sIG9wdHMudGltZW91dE1zKVxuICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICBjaGlsZC5vbihcImVycm9yXCIsIChlcnIpID0+IHtcbiAgICAgIGlmICh0aW1lb3V0SWQpIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXRJZCk7XG4gICAgICB9XG4gICAgICByZWplY3QoZXJyKTtcbiAgICB9KTtcblxuICAgIGNoaWxkLm9uKFwiY2xvc2VcIiwgKGNvZGUpID0+IHtcbiAgICAgIGlmICh0aW1lb3V0SWQpIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXRJZCk7XG4gICAgICB9XG4gICAgICByZXNvbHZlKHsgc3Rkb3V0LCBzdGRlcnIsIGV4aXRDb2RlOiBjb2RlID8/IDAgfSk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG4vKipcbiAqIFRyYWNrIHdoaWNoIHNhbmRib3hlcyBoYXZlIGJlZW4gdmVyaWZpZWQgdG8gZXhpc3QgaW4gdGhpcyBwcm9jZXNzLlxuICogTWFwcyBzYW5kYm94IG5hbWUgLT4gUHJvbWlzZSBzbyBjb25jdXJyZW50IGNhbGxlcnMgd2FpdCBvbiB0aGUgc2FtZSBjaGVjay5cbiAqL1xuY29uc3QgZW5zdXJlUHJvbWlzZXMgPSBuZXcgTWFwPHN0cmluZywgUHJvbWlzZTx2b2lkPj4oKTtcblxuLyoqXG4gKiBTYW5kYm94ZXMgdGhhdCB0aGlzIHByb2Nlc3MgaGFzIHVzZWQuIFN0b3BwZWQgb24gcHJvY2VzcyBleGl0LlxuICovXG5jb25zdCBhY3RpdmVTYW5kYm94ZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcblxubGV0IGNsZWFudXBSZWdpc3RlcmVkID0gZmFsc2U7XG5sZXQgX2V4ZWNTeW5jOiB0eXBlb2YgaW1wb3J0KFwibm9kZTpjaGlsZF9wcm9jZXNzXCIpLmV4ZWNTeW5jIHwgbnVsbCA9IG51bGw7XG5cbmFzeW5jIGZ1bmN0aW9uIHJlZ2lzdGVyQ2xlYW51cCgpIHtcbiAgaWYgKGNsZWFudXBSZWdpc3RlcmVkKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGNsZWFudXBSZWdpc3RlcmVkID0gdHJ1ZTtcblxuICAvLyBQcmUtbG9hZCBleGVjU3luYyBzbyB0aGUgc3luY2hyb25vdXMgZXhpdCBoYW5kbGVyIGNhbiB1c2UgaXQuXG4gIGNvbnN0IGNwID0gYXdhaXQgaW1wb3J0KFwibm9kZTpjaGlsZF9wcm9jZXNzXCIpO1xuICBfZXhlY1N5bmMgPSBjcC5leGVjU3luYztcblxuICBjb25zdCBjbGVhbnVwID0gKCkgPT4ge1xuICAgIGlmICghX2V4ZWNTeW5jKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGZvciAoY29uc3QgbmFtZSBvZiBBcnJheS5mcm9tKGFjdGl2ZVNhbmRib3hlcykpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIF9leGVjU3luYyhgZG9ja2VyIHNhbmRib3ggc3RvcCAke25hbWV9YCwge1xuICAgICAgICAgIHRpbWVvdXQ6IDEwXzAwMCxcbiAgICAgICAgICBzdGRpbzogXCJwaXBlXCIsXG4gICAgICAgIH0pO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIEJlc3QtZWZmb3J0IFx1MjAxNCBzYW5kYm94IG1heSBhbHJlYWR5IGJlIHN0b3BwZWRcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgcHJvY2Vzcy5vbihcImV4aXRcIiwgY2xlYW51cCk7XG4gIHByb2Nlc3Mub24oXCJTSUdJTlRcIiwgKCkgPT4ge1xuICAgIGNsZWFudXAoKTtcbiAgICBwcm9jZXNzLmV4aXQoMTMwKTtcbiAgfSk7XG4gIHByb2Nlc3Mub24oXCJTSUdURVJNXCIsICgpID0+IHtcbiAgICBjbGVhbnVwKCk7XG4gICAgcHJvY2Vzcy5leGl0KDE0Myk7XG4gIH0pO1xufVxuXG4vKipcbiAqIEVuc3VyZSBhIERvY2tlciBzYW5kYm94IGV4aXN0cyBmb3IgdGhlIGdpdmVuIG5hbWUuXG4gKiBJZiBpdCBhbHJlYWR5IGV4aXN0cyAoZnJvbSBhIHByZXZpb3VzIHByb2Nlc3MpLCByZXVzZXMgaXQuXG4gKiBJZiBpdCBkb2Vzbid0IGV4aXN0LCBjcmVhdGVzIGl0LlxuICovXG5hc3luYyBmdW5jdGlvbiBlbnN1cmVTYW5kYm94KHNhbmRib3hOYW1lOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgZXhpc3RpbmcgPSBlbnN1cmVQcm9taXNlcy5nZXQoc2FuZGJveE5hbWUpO1xuICBpZiAoZXhpc3RpbmcpIHtcbiAgICByZXR1cm4gZXhpc3Rpbmc7XG4gIH1cblxuICBjb25zdCBwcm9taXNlID0gKGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBscyA9IGF3YWl0IGV4ZWNEb2NrZXIoW1wibHNcIiwgXCItcVwiXSwgeyB0aW1lb3V0TXM6IDEwXzAwMCB9KTtcbiAgICBjb25zdCBleGlzdGluZ05hbWVzID1cbiAgICAgIGxzLmV4aXRDb2RlID09PSAwXG4gICAgICAgID8gbHMuc3Rkb3V0XG4gICAgICAgICAgICAuc3BsaXQoXCJcXG5cIilcbiAgICAgICAgICAgIC5tYXAoKHMpID0+IHMudHJpbSgpKVxuICAgICAgICAgICAgLmZpbHRlcihCb29sZWFuKVxuICAgICAgICA6IFtdO1xuXG4gICAgaWYgKGV4aXN0aW5nTmFtZXMuaW5jbHVkZXMoc2FuZGJveE5hbWUpKSB7XG4gICAgICBhY3RpdmVTYW5kYm94ZXMuYWRkKHNhbmRib3hOYW1lKTtcbiAgICAgIHJlZ2lzdGVyQ2xlYW51cCgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHBhdGggPSBhd2FpdCBpbXBvcnQoXCJub2RlOnBhdGhcIik7XG4gICAgY29uc3Qgb3MgPSBhd2FpdCBpbXBvcnQoXCJub2RlOm9zXCIpO1xuICAgIGNvbnN0IGZzID0gYXdhaXQgaW1wb3J0KFwibm9kZTpmcy9wcm9taXNlc1wiKTtcblxuICAgIGNvbnN0IHdvcmtzcGFjZURpciA9IHBhdGguam9pbihcbiAgICAgIG9zLnRtcGRpcigpLFxuICAgICAgXCJhZ2VudC1kb2NrZXItc2FuZGJveFwiLFxuICAgICAgc2FuZGJveE5hbWVcbiAgICApO1xuICAgIGF3YWl0IGZzLm1rZGlyKHdvcmtzcGFjZURpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgICBjb25zdCBjcmVhdGUgPSBhd2FpdCBleGVjRG9ja2VyKFxuICAgICAgW1wiY3JlYXRlXCIsIFwiLS1uYW1lXCIsIHNhbmRib3hOYW1lLCBcInNoZWxsXCIsIHdvcmtzcGFjZURpcl0sXG4gICAgICB7IHRpbWVvdXRNczogNjBfMDAwIH1cbiAgICApO1xuXG4gICAgaWYgKGNyZWF0ZS5leGl0Q29kZSAhPT0gMCkge1xuICAgICAgaWYgKGNyZWF0ZS5zdGRlcnIuaW5jbHVkZXMoXCJhbHJlYWR5IGV4aXN0c1wiKSkge1xuICAgICAgICBhY3RpdmVTYW5kYm94ZXMuYWRkKHNhbmRib3hOYW1lKTtcbiAgICAgICAgcmVnaXN0ZXJDbGVhbnVwKCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYEZhaWxlZCB0byBjcmVhdGUgZG9ja2VyIHNhbmRib3ggXCIke3NhbmRib3hOYW1lfVwiOiAke2NyZWF0ZS5zdGRlcnJ9YFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBhY3RpdmVTYW5kYm94ZXMuYWRkKHNhbmRib3hOYW1lKTtcbiAgICByZWdpc3RlckNsZWFudXAoKTtcbiAgfSkoKTtcblxuICBlbnN1cmVQcm9taXNlcy5zZXQoc2FuZGJveE5hbWUsIHByb21pc2UpO1xuXG4gIHRyeSB7XG4gICAgYXdhaXQgcHJvbWlzZTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGVuc3VyZVByb21pc2VzLmRlbGV0ZShzYW5kYm94TmFtZSk7XG4gICAgdGhyb3cgZTtcbiAgfVxufVxuXG5jb25zdCBERUZBVUxUX0RPQ0tFUl9DV0QgPSBcIi9ob21lL2FnZW50L3dvcmtzcGFjZVwiO1xuXG5jbGFzcyBEb2NrZXJTYW5kYm94SW5zdGFuY2UgaW1wbGVtZW50cyBTYW5kYm94SW5zdGFuY2Uge1xuICByZWFkb25seSBjd2Q6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBzYW5kYm94TmFtZTogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IHByb2Nlc3NlcyA9IG5ldyBNYXA8XG4gICAgc3RyaW5nLFxuICAgIGltcG9ydChcIm5vZGU6Y2hpbGRfcHJvY2Vzc1wiKS5DaGlsZFByb2Nlc3NcbiAgPigpO1xuXG4gIGNvbnN0cnVjdG9yKHNhbmRib3hOYW1lOiBzdHJpbmcsIGN3ZD86IHN0cmluZykge1xuICAgIHRoaXMuc2FuZGJveE5hbWUgPSBzYW5kYm94TmFtZTtcbiAgICB0aGlzLmN3ZCA9IGN3ZCA/PyBERUZBVUxUX0RPQ0tFUl9DV0Q7XG4gIH1cblxuICBhc3luYyBleGVjKG9wdHM6IHtcbiAgICBjb21tYW5kOiBzdHJpbmc7XG4gICAgYXJncz86IHN0cmluZ1tdO1xuICAgIGN3ZD86IHN0cmluZztcbiAgICBlbnY/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICAgIHN1ZG8/OiBib29sZWFuO1xuICAgIHNpZ25hbD86IEFib3J0U2lnbmFsO1xuICB9KTogUHJvbWlzZTxFeGVjUmVzdWx0PiB7XG4gICAgYXdhaXQgZW5zdXJlU2FuZGJveCh0aGlzLnNhbmRib3hOYW1lKTtcblxuICAgIGNvbnN0IHsgc3Bhd24gfSA9IGF3YWl0IGltcG9ydChcIm5vZGU6Y2hpbGRfcHJvY2Vzc1wiKTtcbiAgICBjb25zdCBjb21tYW5kSWQgPSBgY29tbWFuZF8ke3VsaWQoKX1gO1xuICAgIGNvbnN0IGVudkZsYWdzID0gb3B0cy5lbnZcbiAgICAgID8gT2JqZWN0LmVudHJpZXMob3B0cy5lbnYpLmZsYXRNYXAoKFtrLCB2XSkgPT4gW1wiLWVcIiwgYCR7a309JHt2fWBdKVxuICAgICAgOiBbXTtcbiAgICBjb25zdCBjd2RGbGFncyA9IG9wdHMuY3dkID8gW1wiLXdcIiwgb3B0cy5jd2RdIDogW107XG4gICAgY29uc3QgYmFzZUNtZCA9IG9wdHMuc3Vkb1xuICAgICAgPyBbXCJzdWRvXCIsIG9wdHMuY29tbWFuZCwgLi4uKG9wdHMuYXJncyA/PyBbXSldXG4gICAgICA6IG9wdHMuYXJnc1xuICAgICAgICA/IFtvcHRzLmNvbW1hbmQsIC4uLm9wdHMuYXJnc11cbiAgICAgICAgOiBbb3B0cy5jb21tYW5kXTtcbiAgICBjb25zdCBmdWxsQ21kID0gYmFzZUNtZDtcblxuICAgIGNvbnN0IGNoaWxkID0gc3Bhd24oXG4gICAgICBcImRvY2tlclwiLFxuICAgICAgW1xuICAgICAgICBcInNhbmRib3hcIixcbiAgICAgICAgXCJleGVjXCIsXG4gICAgICAgIC4uLmVudkZsYWdzLFxuICAgICAgICAuLi5jd2RGbGFncyxcbiAgICAgICAgdGhpcy5zYW5kYm94TmFtZSxcbiAgICAgICAgLi4uZnVsbENtZCxcbiAgICAgIF0sXG4gICAgICB7IHNpZ25hbDogb3B0cy5zaWduYWwgfVxuICAgICk7XG5cbiAgICB0aGlzLnByb2Nlc3Nlcy5zZXQoY29tbWFuZElkLCBjaGlsZCk7XG5cbiAgICBsZXQgc3Rkb3V0ID0gXCJcIjtcbiAgICBsZXQgc3RkZXJyID0gXCJcIjtcbiAgICBjb25zdCBsb2dRdWV1ZTogeyBzdHJlYW06IFwic3Rkb3V0XCIgfCBcInN0ZGVyclwiOyBkYXRhOiBzdHJpbmcgfVtdID0gW107XG4gICAgbGV0IGxvZ1Jlc29sdmU6ICgoKSA9PiB2b2lkKSB8IG51bGwgPSBudWxsO1xuICAgIGxldCBjbG9zZWQgPSBmYWxzZTtcblxuICAgIGNoaWxkLnN0ZG91dC5vbihcImRhdGFcIiwgKGRhdGE6IHN0cmluZyB8IEJ1ZmZlcikgPT4ge1xuICAgICAgY29uc3Qgc3RyID0gU3RyaW5nKGRhdGEpO1xuICAgICAgc3Rkb3V0ICs9IHN0cjtcbiAgICAgIGxvZ1F1ZXVlLnB1c2goeyBzdHJlYW06IFwic3Rkb3V0XCIsIGRhdGE6IHN0ciB9KTtcbiAgICAgIGxvZ1Jlc29sdmU/LigpO1xuICAgIH0pO1xuXG4gICAgY2hpbGQuc3RkZXJyLm9uKFwiZGF0YVwiLCAoZGF0YTogc3RyaW5nIHwgQnVmZmVyKSA9PiB7XG4gICAgICBjb25zdCBzdHIgPSBTdHJpbmcoZGF0YSk7XG4gICAgICBzdGRlcnIgKz0gc3RyO1xuICAgICAgbG9nUXVldWUucHVzaCh7IHN0cmVhbTogXCJzdGRlcnJcIiwgZGF0YTogc3RyIH0pO1xuICAgICAgbG9nUmVzb2x2ZT8uKCk7XG4gICAgfSk7XG5cbiAgICBjb25zdCByZXN1bHQgPSBuZXcgUHJvbWlzZTx7XG4gICAgICBzdGRvdXQ6IHN0cmluZztcbiAgICAgIHN0ZGVycjogc3RyaW5nO1xuICAgICAgZXhpdENvZGU6IG51bWJlcjtcbiAgICB9PigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjaGlsZC5vbihcImVycm9yXCIsIChlcnIpID0+IHtcbiAgICAgICAgdGhpcy5wcm9jZXNzZXMuZGVsZXRlKGNvbW1hbmRJZCk7XG4gICAgICAgIGNsb3NlZCA9IHRydWU7XG4gICAgICAgIGxvZ1Jlc29sdmU/LigpO1xuICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgIH0pO1xuXG4gICAgICBjaGlsZC5vbihcImNsb3NlXCIsIChjb2RlOiBudW1iZXIgfCBudWxsKSA9PiB7XG4gICAgICAgIHRoaXMucHJvY2Vzc2VzLmRlbGV0ZShjb21tYW5kSWQpO1xuICAgICAgICBjbG9zZWQgPSB0cnVlO1xuICAgICAgICBsb2dSZXNvbHZlPy4oKTtcbiAgICAgICAgcmVzb2x2ZSh7IHN0ZG91dCwgc3RkZXJyLCBleGl0Q29kZTogY29kZSA/PyAwIH0pO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBhc3luYyBmdW5jdGlvbiogbG9ncygpOiBBc3luY0l0ZXJhYmxlPHtcbiAgICAgIHN0cmVhbTogXCJzdGRvdXRcIiB8IFwic3RkZXJyXCI7XG4gICAgICBkYXRhOiBzdHJpbmc7XG4gICAgfT4ge1xuICAgICAgd2hpbGUgKCFjbG9zZWQgfHwgbG9nUXVldWUubGVuZ3RoID4gMCkge1xuICAgICAgICBjb25zdCBlbnRyeSA9IGxvZ1F1ZXVlLnNoaWZ0KCk7XG4gICAgICAgIGlmIChlbnRyeSkge1xuICAgICAgICAgIHlpZWxkIGVudHJ5O1xuICAgICAgICB9IGVsc2UgaWYgKCFjbG9zZWQpIHtcbiAgICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocikgPT4ge1xuICAgICAgICAgICAgbG9nUmVzb2x2ZSA9IHI7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgbG9nUmVzb2x2ZSA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4geyBjb21tYW5kSWQsIGxvZ3MsIHJlc3VsdCB9O1xuICB9XG5cbiAgYXN5bmMgcmVhZEZpbGUob3B0czoge1xuICAgIHBhdGg6IHN0cmluZztcbiAgICBzaWduYWw/OiBBYm9ydFNpZ25hbDtcbiAgfSk6IFByb21pc2U8QnVmZmVyIHwgbnVsbD4ge1xuICAgIGF3YWl0IGVuc3VyZVNhbmRib3godGhpcy5zYW5kYm94TmFtZSk7XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBleGVjRG9ja2VyKFxuICAgICAgW1xuICAgICAgICBcImV4ZWNcIixcbiAgICAgICAgdGhpcy5zYW5kYm94TmFtZSxcbiAgICAgICAgXCJiYXNoXCIsXG4gICAgICAgIFwiLWNcIixcbiAgICAgICAgYGJhc2U2NCAnJHtvcHRzLnBhdGgucmVwbGFjZSgvJy9nLCBcIidcXFxcJydcIil9J2AsXG4gICAgICBdLFxuICAgICAgeyB0aW1lb3V0TXM6IDMwXzAwMCwgc2lnbmFsOiBvcHRzLnNpZ25hbCB9XG4gICAgKTtcblxuICAgIGlmIChyZXN1bHQuZXhpdENvZGUgIT09IDApIHtcbiAgICAgIGlmIChcbiAgICAgICAgcmVzdWx0LnN0ZGVyci5pbmNsdWRlcyhcIk5vIHN1Y2ggZmlsZVwiKSB8fFxuICAgICAgICByZXN1bHQuc3RkZXJyLmluY2x1ZGVzKFwiRU5PRU5UXCIpXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHJlYWRGaWxlIGZhaWxlZDogJHtyZXN1bHQuc3RkZXJyfWApO1xuICAgIH1cblxuICAgIHJldHVybiBCdWZmZXIuZnJvbShyZXN1bHQuc3Rkb3V0LnRyaW0oKSwgXCJiYXNlNjRcIik7XG4gIH1cblxuICBhc3luYyB3cml0ZUZpbGVzKG9wdHM6IHtcbiAgICBmaWxlczogeyBwYXRoOiBzdHJpbmc7IGNvbnRlbnQ6IHN0cmluZyB8IEJ1ZmZlciB9W107XG4gICAgZGVzdFBhdGg6IHN0cmluZztcbiAgICBzaWduYWw/OiBBYm9ydFNpZ25hbDtcbiAgfSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IGVuc3VyZVNhbmRib3godGhpcy5zYW5kYm94TmFtZSk7XG5cbiAgICBmb3IgKGNvbnN0IGZpbGUgb2Ygb3B0cy5maWxlcykge1xuICAgICAgY29uc3QgZnVsbFBhdGggPSBvcHRzLmRlc3RQYXRoXG4gICAgICAgID8gYCR7b3B0cy5kZXN0UGF0aH0vJHtmaWxlLnBhdGh9YFxuICAgICAgICA6IGZpbGUucGF0aDtcblxuICAgICAgLy8gRW5zdXJlIHBhcmVudCBkaXJlY3RvcnkgZXhpc3RzXG4gICAgICBjb25zdCBwYXJlbnREaXIgPSBmdWxsUGF0aC5zdWJzdHJpbmcoMCwgZnVsbFBhdGgubGFzdEluZGV4T2YoXCIvXCIpKTtcbiAgICAgIGlmIChwYXJlbnREaXIpIHtcbiAgICAgICAgYXdhaXQgZXhlY0RvY2tlcihbXCJleGVjXCIsIHRoaXMuc2FuZGJveE5hbWUsIFwibWtkaXJcIiwgXCItcFwiLCBwYXJlbnREaXJdLCB7XG4gICAgICAgICAgc2lnbmFsOiBvcHRzLnNpZ25hbCxcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIC8vIFdyaXRlIHZpYSBiYXNlNjQgdG8gaGFuZGxlIGJvdGggdGV4dCBhbmQgYmluYXJ5IGNvbnRlbnRcbiAgICAgIGNvbnN0IGI2NCA9XG4gICAgICAgIHR5cGVvZiBmaWxlLmNvbnRlbnQgPT09IFwic3RyaW5nXCJcbiAgICAgICAgICA/IEJ1ZmZlci5mcm9tKGZpbGUuY29udGVudCkudG9TdHJpbmcoXCJiYXNlNjRcIilcbiAgICAgICAgICA6IGZpbGUuY29udGVudC50b1N0cmluZyhcImJhc2U2NFwiKTtcblxuICAgICAgYXdhaXQgZXhlY0RvY2tlcihcbiAgICAgICAgW1xuICAgICAgICAgIFwiZXhlY1wiLFxuICAgICAgICAgIHRoaXMuc2FuZGJveE5hbWUsXG4gICAgICAgICAgXCJiYXNoXCIsXG4gICAgICAgICAgXCItY1wiLFxuICAgICAgICAgIGBlY2hvICcke2I2NH0nIHwgYmFzZTY0IC1kID4gJyR7ZnVsbFBhdGgucmVwbGFjZSgvJy9nLCBcIidcXFxcJydcIil9J2AsXG4gICAgICAgIF0sXG4gICAgICAgIHsgc2lnbmFsOiBvcHRzLnNpZ25hbCB9XG4gICAgICApO1xuXG4gICAgICBpZiAoZmlsZS5wYXRoLmVuZHNXaXRoKFwiLnNoXCIpKSB7XG4gICAgICAgIGF3YWl0IGV4ZWNEb2NrZXIoW1wiZXhlY1wiLCB0aGlzLnNhbmRib3hOYW1lLCBcImNobW9kXCIsIFwiK3hcIiwgZnVsbFBhdGhdLCB7XG4gICAgICAgICAgc2lnbmFsOiBvcHRzLnNpZ25hbCxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy91c2VBd2FpdDogLlxuICBhc3luYyBnZXREb21haW4ob3B0czoge1xuICAgIHBvcnQ6IG51bWJlcjtcbiAgICBzaWduYWw/OiBBYm9ydFNpZ25hbDtcbiAgfSk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgcmV0dXJuIGBodHRwOi8vbG9jYWxob3N0OiR7b3B0cy5wb3J0fWA7XG4gIH1cblxuICAvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL3VzZUF3YWl0OiAuXG4gIGFzeW5jIGtpbGwob3B0czogeyBjb21tYW5kSWQ6IHN0cmluZzsgc2lnbmFsPzogQWJvcnRTaWduYWwgfSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGNoaWxkID0gdGhpcy5wcm9jZXNzZXMuZ2V0KG9wdHMuY29tbWFuZElkKTtcbiAgICBpZiAoY2hpbGQpIHtcbiAgICAgIGNoaWxkLmtpbGwoXCJTSUdURVJNXCIpO1xuICAgICAgdGhpcy5wcm9jZXNzZXMuZGVsZXRlKG9wdHMuY29tbWFuZElkKTtcbiAgICB9XG4gIH1cblxuICAvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL3VzZUF3YWl0OiAuXG4gIGFzeW5jIGdldFN0YXR1cygpOiBQcm9taXNlPFxuICAgIFwicGVuZGluZ1wiIHwgXCJydW5uaW5nXCIgfCBcInN0b3BwaW5nXCIgfCBcInN0b3BwZWRcIiB8IFwiZmFpbGVkXCJcbiAgPiB7XG4gICAgLy8gZG9ja2VyIHNhbmRib3ggQ0xJIGRvZXNuJ3QgZXhwb3NlIHN0YXR1cyBcdTIwMTQgYXNzdW1lIHJ1bm5pbmcgaWYgZW5zdXJlZFxuICAgIHJldHVybiBcInJ1bm5pbmdcIjtcbiAgfVxuXG4gIGFzeW5jIHN0YXJ0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IGVuc3VyZVNhbmRib3godGhpcy5zYW5kYm94TmFtZSk7XG4gIH1cblxuICBhc3luYyBzdG9wKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IGV4ZWNEb2NrZXIoW1wic3RvcFwiLCB0aGlzLnNhbmRib3hOYW1lXSwgeyB0aW1lb3V0TXM6IDMwXzAwMCB9KTtcbiAgICBhY3RpdmVTYW5kYm94ZXMuZGVsZXRlKHRoaXMuc2FuZGJveE5hbWUpO1xuICAgIGVuc3VyZVByb21pc2VzLmRlbGV0ZSh0aGlzLnNhbmRib3hOYW1lKTtcbiAgfVxuXG4gIC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvdXNlQXdhaXQ6IC5cbiAgYXN5bmMgc25hcHNob3QoKTogUHJvbWlzZTx7IHNuYXBzaG90SWQ6IHN0cmluZyB9PiB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwic25hcHNob3QgaXMgbm90IHN1cHBvcnRlZCBmb3IgZG9ja2VyIHNhbmRib3hlc1wiKTtcbiAgfVxuXG4gIC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvdXNlQXdhaXQ6IC5cbiAgYXN5bmMgdXBkYXRlTmV0d29ya1BvbGljeSgpOiBQcm9taXNlPG5ldmVyPiB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgXCJ1cGRhdGVOZXR3b3JrUG9saWN5IGlzIG5vdCBzdXBwb3J0ZWQgZm9yIGRvY2tlciBzYW5kYm94ZXNcIlxuICAgICk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGRvY2tlclNhbmRib3goKTogU2FuZGJveEJpbmRpbmc8XG4gIFwiZG9ja2VyXCIsXG4gIERvY2tlckJpbmRpbmdDb25maWcsXG4gIERvY2tlckJpbmRpbmdNZXRhZGF0YVxuPiB7XG4gIHJldHVybiB7XG4gICAgdHlwZTogXCJkb2NrZXJcIixcbiAgICBhc3luYyBjcmVhdGUob3B0cykge1xuICAgICAgY29uc3Qgc2FuZGJveE5hbWUgPSBgYWdlbnQtJHt1bGlkKCl9YDtcbiAgICAgIGNvbnN0IGN3ZCA9IG9wdHMuc2V0dXA/LmNvbmZpZz8uY3dkO1xuXG4gICAgICBhd2FpdCBlbnN1cmVTYW5kYm94KHNhbmRib3hOYW1lKTtcblxuICAgICAgY29uc3QgaW5zdGFuY2UgPSBuZXcgRG9ja2VyU2FuZGJveEluc3RhbmNlKHNhbmRib3hOYW1lLCBjd2QpO1xuXG4gICAgICBpZiAob3B0cy5zZXR1cD8ucnVuKSB7XG4gICAgICAgIGF3YWl0IG9wdHMuc2V0dXAucnVuKGluc3RhbmNlKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaW5zdGFuY2UsXG4gICAgICAgIG1ldGFkYXRhOiB7IHNhbmRib3hOYW1lIH0sXG4gICAgICB9O1xuICAgIH0sXG5cbiAgICAvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL3VzZUF3YWl0OiAuXG4gICAgYXN5bmMgY29ubmVjdChvcHRzKSB7XG4gICAgICByZXR1cm4gbmV3IERvY2tlclNhbmRib3hJbnN0YW5jZShvcHRzLm1ldGFkYXRhLnNhbmRib3hOYW1lKTtcbiAgICB9LFxuICB9O1xufVxuIiwgImltcG9ydCB7IHVsaWQgfSBmcm9tIFwidWxpZFwiO1xuaW1wb3J0IHR5cGUgeyBFeGVjUmVzdWx0LCBTYW5kYm94QmluZGluZywgU2FuZGJveEluc3RhbmNlIH0gZnJvbSBcIi4uL2FkYXB0ZXJcIjtcblxuZXhwb3J0IHR5cGUgTG9jYWxCaW5kaW5nQ29uZmlnID0ge1xuICBjd2Q/OiBzdHJpbmc7XG59O1xuXG5leHBvcnQgdHlwZSBMb2NhbEJpbmRpbmdNZXRhZGF0YSA9IHtcbiAgYmFzZVBhdGg6IHN0cmluZztcbiAgcGlkOiBudW1iZXI7XG59O1xuXG5jbGFzcyBMb2NhbFNhbmRib3hJbnN0YW5jZSBpbXBsZW1lbnRzIFNhbmRib3hJbnN0YW5jZSB7XG4gIHJlYWRvbmx5IGN3ZDogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IGJhc2VQYXRoOiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgcHJvY2Vzc2VzID0gbmV3IE1hcDxcbiAgICBzdHJpbmcsXG4gICAgaW1wb3J0KFwibm9kZTpjaGlsZF9wcm9jZXNzXCIpLkNoaWxkUHJvY2Vzc1xuICA+KCk7XG5cbiAgY29uc3RydWN0b3IoYmFzZVBhdGg6IHN0cmluZykge1xuICAgIHRoaXMuYmFzZVBhdGggPSBiYXNlUGF0aDtcbiAgICB0aGlzLmN3ZCA9IGJhc2VQYXRoO1xuICB9XG5cbiAgYXN5bmMgZXhlYyhvcHRzOiB7XG4gICAgY29tbWFuZDogc3RyaW5nO1xuICAgIGFyZ3M/OiBzdHJpbmdbXTtcbiAgICBjd2Q/OiBzdHJpbmc7XG4gICAgZW52PzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbiAgICBzdWRvPzogYm9vbGVhbjtcbiAgICBzaWduYWw/OiBBYm9ydFNpZ25hbDtcbiAgfSk6IFByb21pc2U8RXhlY1Jlc3VsdD4ge1xuICAgIGNvbnN0IHsgc3Bhd24gfSA9IGF3YWl0IGltcG9ydChcIm5vZGU6Y2hpbGRfcHJvY2Vzc1wiKTtcbiAgICBjb25zdCBwYXRoID0gYXdhaXQgaW1wb3J0KFwibm9kZTpwYXRoXCIpO1xuICAgIGNvbnN0IGNvbW1hbmRJZCA9IGBjb21tYW5kXyR7dWxpZCgpfWA7XG5cbiAgICBjb25zdCBmaW5hbENtZCA9IG9wdHMuc3VkbyA/IFwic3Vkb1wiIDogb3B0cy5jb21tYW5kO1xuICAgIGNvbnN0IGZpbmFsQXJncyA9IG9wdHMuc3Vkb1xuICAgICAgPyBbb3B0cy5jb21tYW5kLCAuLi4ob3B0cy5hcmdzID8/IFtdKV1cbiAgICAgIDogKG9wdHMuYXJncyA/PyBbXSk7XG5cbiAgICBjb25zdCBjaGlsZCA9IHNwYXduKGZpbmFsQ21kLCBmaW5hbEFyZ3MsIHtcbiAgICAgIGN3ZDogb3B0cy5jd2QgPyBwYXRoLnJlc29sdmUodGhpcy5iYXNlUGF0aCwgb3B0cy5jd2QpIDogdGhpcy5iYXNlUGF0aCxcbiAgICAgIGVudjogb3B0cy5lbnYgPyB7IC4uLnByb2Nlc3MuZW52LCAuLi5vcHRzLmVudiB9IDogdW5kZWZpbmVkLFxuICAgICAgc2lnbmFsOiBvcHRzLnNpZ25hbCxcbiAgICB9KTtcblxuICAgIHRoaXMucHJvY2Vzc2VzLnNldChjb21tYW5kSWQsIGNoaWxkKTtcblxuICAgIGxldCBzdGRvdXQgPSBcIlwiO1xuICAgIGxldCBzdGRlcnIgPSBcIlwiO1xuICAgIGNvbnN0IGxvZ1F1ZXVlOiB7IHN0cmVhbTogXCJzdGRvdXRcIiB8IFwic3RkZXJyXCI7IGRhdGE6IHN0cmluZyB9W10gPSBbXTtcbiAgICBsZXQgbG9nUmVzb2x2ZTogKCgpID0+IHZvaWQpIHwgbnVsbCA9IG51bGw7XG4gICAgbGV0IGNsb3NlZCA9IGZhbHNlO1xuXG4gICAgY2hpbGQuc3Rkb3V0Lm9uKFwiZGF0YVwiLCAoZGF0YTogc3RyaW5nIHwgQnVmZmVyKSA9PiB7XG4gICAgICBjb25zdCBzdHIgPSBTdHJpbmcoZGF0YSk7XG4gICAgICBzdGRvdXQgKz0gc3RyO1xuICAgICAgbG9nUXVldWUucHVzaCh7IHN0cmVhbTogXCJzdGRvdXRcIiwgZGF0YTogc3RyIH0pO1xuICAgICAgbG9nUmVzb2x2ZT8uKCk7XG4gICAgfSk7XG5cbiAgICBjaGlsZC5zdGRlcnIub24oXCJkYXRhXCIsIChkYXRhOiBzdHJpbmcgfCBCdWZmZXIpID0+IHtcbiAgICAgIGNvbnN0IHN0ciA9IFN0cmluZyhkYXRhKTtcbiAgICAgIHN0ZGVyciArPSBzdHI7XG4gICAgICBsb2dRdWV1ZS5wdXNoKHsgc3RyZWFtOiBcInN0ZGVyclwiLCBkYXRhOiBzdHIgfSk7XG4gICAgICBsb2dSZXNvbHZlPy4oKTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBQcm9taXNlPHtcbiAgICAgIHN0ZG91dDogc3RyaW5nO1xuICAgICAgc3RkZXJyOiBzdHJpbmc7XG4gICAgICBleGl0Q29kZTogbnVtYmVyO1xuICAgIH0+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNoaWxkLm9uKFwiZXJyb3JcIiwgKGVycikgPT4ge1xuICAgICAgICB0aGlzLnByb2Nlc3Nlcy5kZWxldGUoY29tbWFuZElkKTtcbiAgICAgICAgY2xvc2VkID0gdHJ1ZTtcbiAgICAgICAgbG9nUmVzb2x2ZT8uKCk7XG4gICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgfSk7XG5cbiAgICAgIGNoaWxkLm9uKFwiY2xvc2VcIiwgKGNvZGU6IG51bWJlciB8IG51bGwpID0+IHtcbiAgICAgICAgdGhpcy5wcm9jZXNzZXMuZGVsZXRlKGNvbW1hbmRJZCk7XG4gICAgICAgIGNsb3NlZCA9IHRydWU7XG4gICAgICAgIGxvZ1Jlc29sdmU/LigpO1xuICAgICAgICByZXNvbHZlKHsgc3Rkb3V0LCBzdGRlcnIsIGV4aXRDb2RlOiBjb2RlID8/IDAgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGFzeW5jIGZ1bmN0aW9uKiBsb2dzKCk6IEFzeW5jSXRlcmFibGU8e1xuICAgICAgc3RyZWFtOiBcInN0ZG91dFwiIHwgXCJzdGRlcnJcIjtcbiAgICAgIGRhdGE6IHN0cmluZztcbiAgICB9PiB7XG4gICAgICB3aGlsZSAoIWNsb3NlZCB8fCBsb2dRdWV1ZS5sZW5ndGggPiAwKSB7XG4gICAgICAgIGNvbnN0IGVudHJ5ID0gbG9nUXVldWUuc2hpZnQoKTtcbiAgICAgICAgaWYgKGVudHJ5KSB7XG4gICAgICAgICAgeWllbGQgZW50cnk7XG4gICAgICAgIH0gZWxzZSBpZiAoIWNsb3NlZCkge1xuICAgICAgICAgIGF3YWl0IG5ldyBQcm9taXNlPHZvaWQ+KChyKSA9PiB7XG4gICAgICAgICAgICBsb2dSZXNvbHZlID0gcjtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBsb2dSZXNvbHZlID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7IGNvbW1hbmRJZCwgbG9ncywgcmVzdWx0IH07XG4gIH1cblxuICBhc3luYyByZWFkRmlsZShvcHRzOiB7XG4gICAgcGF0aDogc3RyaW5nO1xuICAgIHNpZ25hbD86IEFib3J0U2lnbmFsO1xuICB9KTogUHJvbWlzZTxCdWZmZXIgfCBudWxsPiB7XG4gICAgY29uc3QgZnMgPSBhd2FpdCBpbXBvcnQoXCJub2RlOmZzL3Byb21pc2VzXCIpO1xuICAgIGNvbnN0IHBhdGggPSBhd2FpdCBpbXBvcnQoXCJub2RlOnBhdGhcIik7XG4gICAgY29uc3QgZnVsbFBhdGggPSBwYXRoLnJlc29sdmUodGhpcy5iYXNlUGF0aCwgb3B0cy5wYXRoKTtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGF3YWl0IGZzLnJlYWRGaWxlKGZ1bGxQYXRoKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICBpZiAoXG4gICAgICAgIGUgaW5zdGFuY2VvZiBFcnJvciAmJlxuICAgICAgICBcImNvZGVcIiBpbiBlICYmXG4gICAgICAgIChlIGFzIE5vZGVKUy5FcnJub0V4Y2VwdGlvbikuY29kZSA9PT0gXCJFTk9FTlRcIlxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgdGhyb3cgZTtcbiAgICB9XG4gIH1cblxuICBhc3luYyB3cml0ZUZpbGVzKG9wdHM6IHtcbiAgICBmaWxlczogeyBwYXRoOiBzdHJpbmc7IGNvbnRlbnQ6IHN0cmluZyB8IEJ1ZmZlciB9W107XG4gICAgZGVzdFBhdGg6IHN0cmluZztcbiAgICBzaWduYWw/OiBBYm9ydFNpZ25hbDtcbiAgfSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGZzID0gYXdhaXQgaW1wb3J0KFwibm9kZTpmcy9wcm9taXNlc1wiKTtcbiAgICBjb25zdCBwYXRoTW9kID0gYXdhaXQgaW1wb3J0KFwibm9kZTpwYXRoXCIpO1xuICAgIGZvciAoY29uc3QgZmlsZSBvZiBvcHRzLmZpbGVzKSB7XG4gICAgICBjb25zdCBmdWxsUGF0aCA9IHBhdGhNb2QucmVzb2x2ZSh0aGlzLmJhc2VQYXRoLCBvcHRzLmRlc3RQYXRoLCBmaWxlLnBhdGgpO1xuICAgICAgYXdhaXQgZnMubWtkaXIocGF0aE1vZC5kaXJuYW1lKGZ1bGxQYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgICBhd2FpdCBmcy53cml0ZUZpbGUoZnVsbFBhdGgsIGZpbGUuY29udGVudCk7XG4gICAgICBpZiAoZmlsZS5wYXRoLmVuZHNXaXRoKFwiLnNoXCIpKSB7XG4gICAgICAgIGF3YWl0IGZzLmNobW9kKGZ1bGxQYXRoLCAwbzc1NSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy91c2VBd2FpdDogLlxuICBhc3luYyBnZXREb21haW4ob3B0czoge1xuICAgIHBvcnQ6IG51bWJlcjtcbiAgICBzaWduYWw/OiBBYm9ydFNpZ25hbDtcbiAgfSk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgcmV0dXJuIGBodHRwOi8vbG9jYWxob3N0OiR7b3B0cy5wb3J0fWA7XG4gIH1cblxuICAvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL3VzZUF3YWl0OiAuXG4gIGFzeW5jIGtpbGwob3B0czogeyBjb21tYW5kSWQ6IHN0cmluZzsgc2lnbmFsPzogQWJvcnRTaWduYWwgfSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGNoaWxkID0gdGhpcy5wcm9jZXNzZXMuZ2V0KG9wdHMuY29tbWFuZElkKTtcbiAgICBpZiAoY2hpbGQpIHtcbiAgICAgIGNoaWxkLmtpbGwoXCJTSUdURVJNXCIpO1xuICAgICAgdGhpcy5wcm9jZXNzZXMuZGVsZXRlKG9wdHMuY29tbWFuZElkKTtcbiAgICB9XG4gIH1cblxuICAvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL3VzZUF3YWl0OiAuXG4gIGFzeW5jIGdldFN0YXR1cygpOiBQcm9taXNlPFwicnVubmluZ1wiPiB7XG4gICAgcmV0dXJuIFwicnVubmluZ1wiO1xuICB9XG5cbiAgYXN5bmMgc3RhcnQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgLy8gbm8tb3A6IGxvY2FsIHNhbmRib3ggaXMgYWx3YXlzIHN0YXJ0ZWRcbiAgfVxuXG4gIC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvdXNlQXdhaXQ6IC5cbiAgYXN5bmMgc3RvcCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJzdG9wIGlzIG5vdCBzdXBwb3J0ZWQgZm9yIGxvY2FsIHNhbmRib3hlc1wiKTtcbiAgfVxuXG4gIC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvdXNlQXdhaXQ6IC5cbiAgYXN5bmMgc25hcHNob3QoKTogUHJvbWlzZTx7IHNuYXBzaG90SWQ6IHN0cmluZyB9PiB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwic25hcHNob3QgaXMgbm90IHN1cHBvcnRlZCBmb3IgbG9jYWwgc2FuZGJveGVzXCIpO1xuICB9XG5cbiAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy91c2VBd2FpdDogLlxuICBhc3luYyB1cGRhdGVOZXR3b3JrUG9saWN5KCk6IFByb21pc2U8bmV2ZXI+IHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJ1cGRhdGVOZXR3b3JrUG9saWN5IGlzIG5vdCBzdXBwb3J0ZWQgZm9yIGxvY2FsIHNhbmRib3hlc1wiKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gbG9jYWxTYW5kYm94KCk6IFNhbmRib3hCaW5kaW5nPFxuICBcImxvY2FsXCIsXG4gIExvY2FsQmluZGluZ0NvbmZpZyxcbiAgTG9jYWxCaW5kaW5nTWV0YWRhdGFcbj4ge1xuICByZXR1cm4ge1xuICAgIHR5cGU6IFwibG9jYWxcIixcbiAgICBhc3luYyBjcmVhdGUob3B0cykge1xuICAgICAgY29uc3QgYmFzZVBhdGggPSBvcHRzLnNldHVwLmNvbmZpZz8uY3dkID8/IHByb2Nlc3MuY3dkKCk7XG4gICAgICBjb25zdCBpbnN0YW5jZSA9IG5ldyBMb2NhbFNhbmRib3hJbnN0YW5jZShiYXNlUGF0aCk7XG5cbiAgICAgIGlmIChvcHRzLnNldHVwPy5ydW4pIHtcbiAgICAgICAgYXdhaXQgb3B0cy5zZXR1cC5ydW4oaW5zdGFuY2UpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBpbnN0YW5jZSxcbiAgICAgICAgbWV0YWRhdGE6IHsgYmFzZVBhdGgsIHBpZDogcHJvY2Vzcy5waWQgfSxcbiAgICAgIH07XG4gICAgfSxcblxuICAgIC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvdXNlQXdhaXQ6IC5cbiAgICBhc3luYyBjb25uZWN0KG9wdHMpIHtcbiAgICAgIGNvbnN0IGJhc2VQYXRoID0gb3B0cy5tZXRhZGF0YS5iYXNlUGF0aDtcbiAgICAgIHJldHVybiBuZXcgTG9jYWxTYW5kYm94SW5zdGFuY2UoYmFzZVBhdGgpO1xuICAgIH0sXG4gIH07XG59XG4iLCAiaW1wb3J0IHsgc3RhcnQgYXMgc3RhcnRXb3JrZmxvdyB9IGZyb20gXCJ3b3JrZmxvdy9hcGlcIjtcbmltcG9ydCB0eXBlIHsgU3RvcmFnZSB9IGZyb20gXCIuLi8uLi9zdG9yYWdlXCI7XG5pbXBvcnQgdHlwZSB7IExvZ2dlciB9IGZyb20gXCIuLi8uLi91dGlscy9sb2dnZXJcIjtcbmltcG9ydCB0eXBlIHsgRXhlY1Jlc3VsdCwgU2FuZGJveEJpbmRpbmcsIFNhbmRib3hJbnN0YW5jZSB9IGZyb20gXCIuLi9hZGFwdGVyXCI7XG5pbXBvcnQgdHlwZSB7IExpZmVjeWNsZUNvbmZpZyB9IGZyb20gXCIuL3ZlcmNlbC1saWZlY3ljbGUvc3RlcHNcIjtcbmltcG9ydCB7IHNhbmRib3hMaWZlY3ljbGVXb3JrZmxvdyB9IGZyb20gXCIuL3ZlcmNlbC1saWZlY3ljbGUvd29ya2Zsb3dcIjtcblxuYXN5bmMgZnVuY3Rpb24gbG9hZFNhbmRib3hTREsoKSB7XG4gIHJldHVybiAoYXdhaXQgaW1wb3J0KFwiQHZlcmNlbC9zYW5kYm94XCIpKS5TYW5kYm94O1xufVxuXG5jb25zdCBNQVhfVElNRU9VVF9NUyA9IDUgKiA2MCAqIDYwICogMTAwMDsgLy8gNSBob3Vyc1xuY29uc3QgSE9NRV9ESVIgPSBcIi9ob21lL3ZlcmNlbC1zYW5kYm94XCI7XG5jb25zdCBERUZBVUxUX1ZDUFVTID0gMjtcblxuZXhwb3J0IHR5cGUgVmVyY2VsQmluZGluZ0NvbmZpZyA9IHtcbiAgY3dkPzogc3RyaW5nO1xuICByZXNvdXJjZXM/OiB7IHZjcHVzOiBudW1iZXIgfTtcbiAgcG9ydHM/OiBudW1iZXJbXTtcbiAgbmV0d29ya1BvbGljeT86IGltcG9ydChcIkB2ZXJjZWwvc2FuZGJveFwiKS5OZXR3b3JrUG9saWN5O1xuICBzbmFwc2hvdElkPzogc3RyaW5nO1xuICBsaWZlY3ljbGU/OiBMaWZlY3ljbGVDb25maWc7XG59O1xuXG5leHBvcnQgdHlwZSBWZXJjZWxCaW5kaW5nTWV0YWRhdGEgPSB7XG4gIHNhbmRib3hJZDogc3RyaW5nO1xufTtcblxudHlwZSBDcmVhdGVTYW5kYm94T3B0cyA9IHtcbiAgcmVzb3VyY2VzOiB7IHZjcHVzOiBudW1iZXIgfTtcbiAgcG9ydHM/OiBudW1iZXJbXTtcbiAgbmV0d29ya1BvbGljeT86IGltcG9ydChcIkB2ZXJjZWwvc2FuZGJveFwiKS5OZXR3b3JrUG9saWN5O1xuICBzbmFwc2hvdElkPzogc3RyaW5nO1xufTtcblxuZnVuY3Rpb24gaXNTYW5kYm94R29uZUVycm9yKGU6IHVua25vd24pOiBib29sZWFuIHtcbiAgaWYgKCEoZSBpbnN0YW5jZW9mIEVycm9yKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGNvbnN0IHN0YXR1cyA9XG4gICAgKGUgYXMgeyByZXNwb25zZT86IHsgc3RhdHVzPzogbnVtYmVyIH0gfSkucmVzcG9uc2U/LnN0YXR1cyA/P1xuICAgIChlIGFzIHsgY2F1c2U/OiB7IHJlc3BvbnNlPzogeyBzdGF0dXM/OiBudW1iZXIgfSB9IH0pLmNhdXNlPy5yZXNwb25zZVxuICAgICAgPy5zdGF0dXM7XG5cbiAgaWYgKHN0YXR1cyA9PT0gNDEwIHx8IHN0YXR1cyA9PT0gNDIyKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBjb25zdCBtc2cgPSBlLm1lc3NhZ2UgfHwgU3RyaW5nKGUpO1xuICByZXR1cm4gKFxuICAgIG1zZy5pbmNsdWRlcyhcIkV4cGVjdGVkIGEgc3RyZWFtIG9mIGNvbW1hbmQgZGF0YVwiKSB8fFxuICAgIG1zZy5pbmNsdWRlcyhcIkV4cGVjdGVkIGEgc3RyZWFtIG9mIGxvZ3NcIilcbiAgKTtcbn1cblxuY29uc3QgZ2V0VGVzdENyZWRlbnRpYWxzID0gKCkgPT5cbiAgcHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09IFwidGVzdFwiXG4gICAgPyB7XG4gICAgICAgIHRva2VuOiBwcm9jZXNzLmVudi5URVNUX1ZFUkNFTF9UT0tFTixcbiAgICAgICAgdGVhbUlkOiBwcm9jZXNzLmVudi5URVNUX1ZFUkNFTF9URUFNX0lELFxuICAgICAgICBwcm9qZWN0SWQ6IHByb2Nlc3MuZW52LlRFU1RfVkVSQ0VMX1BST0pFQ1RfSUQsXG4gICAgICB9XG4gICAgOiB7fTtcblxuYXN5bmMgZnVuY3Rpb24gY3JlYXRlU2RrKHtcbiAgcmVzb3VyY2VzLFxuICBwb3J0cyxcbiAgbmV0d29ya1BvbGljeSxcbiAgc25hcHNob3RJZCxcbn06IENyZWF0ZVNhbmRib3hPcHRzKSB7XG4gIGNvbnN0IFNhbmRib3hTREsgPSBhd2FpdCBsb2FkU2FuZGJveFNESygpO1xuICBjb25zdCBiYXNlID0ge1xuICAgIHJlc291cmNlcyxcbiAgICB0aW1lb3V0OiBNQVhfVElNRU9VVF9NUyxcbiAgICAuLi4ocG9ydHMgPyB7IHBvcnRzIH0gOiB7fSksXG4gICAgLi4uKG5ldHdvcmtQb2xpY3kgPyB7IG5ldHdvcmtQb2xpY3kgfSA6IHt9KSxcbiAgICAuLi5nZXRUZXN0Q3JlZGVudGlhbHMoKSxcbiAgfTtcblxuICBpZiAoc25hcHNob3RJZCkge1xuICAgIHJldHVybiBTYW5kYm94U0RLLmNyZWF0ZSh7XG4gICAgICAuLi5iYXNlLFxuICAgICAgc291cmNlOiB7IHR5cGU6IFwic25hcHNob3RcIiBhcyBjb25zdCwgc25hcHNob3RJZCB9LFxuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIFNhbmRib3hTREsuY3JlYXRlKGJhc2UpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBjcmVhdGVTZXR1cFNuYXBzaG90KHtcbiAgc2FuZGJveE9wdHMsXG4gIHJ1bixcbiAgc3RvcmFnZSxcbiAgc25hcHNob3RWZXJzaW9uLFxuICBsb2csXG59OiB7XG4gIHNhbmRib3hPcHRzOiBDcmVhdGVTYW5kYm94T3B0cztcbiAgcnVuOiAoc2FuZGJveDogU2FuZGJveEluc3RhbmNlKSA9PiBQcm9taXNlPHZvaWQ+O1xuICBzdG9yYWdlOiBTdG9yYWdlO1xuICBzbmFwc2hvdFZlcnNpb246IHN0cmluZztcbiAgbG9nOiBMb2dnZXI7XG59KTogUHJvbWlzZTx2b2lkPiB7XG4gIGxldCB0ZW1wU2RrOiBBd2FpdGVkPFJldHVyblR5cGU8dHlwZW9mIGNyZWF0ZVNkaz4+IHwgbnVsbCA9IG51bGw7XG4gIHRyeSB7XG4gICAgdGVtcFNkayA9IGF3YWl0IGNyZWF0ZVNkayhzYW5kYm94T3B0cyk7XG4gICAgY29uc3QgdGVtcEluc3RhbmNlID0gbmV3IFZlcmNlbFNhbmRib3hJbnN0YW5jZSh0ZW1wU2RrKTtcbiAgICBhd2FpdCBydW4odGVtcEluc3RhbmNlKTtcbiAgICBjb25zdCBzbmFwc2hvdCA9IGF3YWl0IHRlbXBTZGsuc25hcHNob3QoKTtcbiAgICBhd2FpdCBzdG9yYWdlLnNldHVwLnNldChzbmFwc2hvdFZlcnNpb24sIHtcbiAgICAgIHZlcnNpb246IHNuYXBzaG90VmVyc2lvbixcbiAgICAgIHNuYXBzaG90SWQ6IHNuYXBzaG90LnNuYXBzaG90SWQsXG4gICAgICBjcmVhdGVkQXQ6IERhdGUubm93KCksXG4gICAgICBsYXN0VXNlZEF0OiBudWxsLFxuICAgIH0pO1xuICAgIGF3YWl0IHRlbXBTZGsuc3RvcCgpLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgbG9nLmVycm9yKFwiZmFpbGVkIHRvIGNyZWF0ZSBzZXR1cCBzbmFwc2hvdFwiLCB7XG4gICAgICBzbmFwc2hvdFZlcnNpb24sXG4gICAgICBjYXVzZTogZXJyb3IsXG4gICAgfSk7XG4gICAgaWYgKHRlbXBTZGspIHtcbiAgICAgIGF3YWl0IHRlbXBTZGsuc3RvcCgpLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgfVxuICB9XG59XG5cbmNsYXNzIFZlcmNlbFNhbmRib3hJbnN0YW5jZSBpbXBsZW1lbnRzIFNhbmRib3hJbnN0YW5jZSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgc2RrOiBpbXBvcnQoXCJAdmVyY2VsL3NhbmRib3hcIikuU2FuZGJveDtcbiAgcmVhZG9ubHkgY3dkOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3Ioc2RrOiBpbXBvcnQoXCJAdmVyY2VsL3NhbmRib3hcIikuU2FuZGJveCwgY3dkPzogc3RyaW5nKSB7XG4gICAgdGhpcy5zZGsgPSBzZGs7XG4gICAgdGhpcy5jd2QgPSBjd2QgPz8gSE9NRV9ESVI7XG4gIH1cblxuICBhc3luYyBleGVjKHtcbiAgICBjb21tYW5kLFxuICAgIGFyZ3MsXG4gICAgY3dkLFxuICAgIGVudixcbiAgICBzdWRvLFxuICAgIHNpZ25hbCxcbiAgfToge1xuICAgIGNvbW1hbmQ6IHN0cmluZztcbiAgICBhcmdzPzogc3RyaW5nW107XG4gICAgY3dkPzogc3RyaW5nO1xuICAgIGVudj86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gICAgc3Vkbz86IGJvb2xlYW47XG4gICAgc2lnbmFsPzogQWJvcnRTaWduYWw7XG4gIH0pOiBQcm9taXNlPEV4ZWNSZXN1bHQ+IHtcbiAgICBjb25zdCBvdXRwdXQgPSBhd2FpdCB0aGlzLnNkay5ydW5Db21tYW5kKHtcbiAgICAgIGNtZDogY29tbWFuZCxcbiAgICAgIGFyZ3MsXG4gICAgICBjd2Q6IGN3ZCA/PyB0aGlzLmN3ZCxcbiAgICAgIGVudixcbiAgICAgIHN1ZG8sXG4gICAgICBzaWduYWwsXG4gICAgICBkZXRhY2hlZDogdHJ1ZSxcbiAgICB9KTtcblxuICAgIGxldCBzdGRvdXQgPSBcIlwiO1xuICAgIGxldCBzdGRlcnIgPSBcIlwiO1xuICAgIGNvbnN0IGxvZ0J1ZmZlcjogeyBzdHJlYW06IFwic3Rkb3V0XCIgfCBcInN0ZGVyclwiOyBkYXRhOiBzdHJpbmcgfVtdID0gW107XG4gICAgY29uc3Qgc3RhdGUgPSB7XG4gICAgICByZXNvbHZlOiBudWxsIGFzICgoKSA9PiB2b2lkKSB8IG51bGwsXG4gICAgICBjb25zdW1lZDogZmFsc2UsXG4gICAgfTtcblxuICAgIGNvbnN0IGNvbnN1bWVMb2dzID0gKGFzeW5jICgpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGZvciBhd2FpdCAoY29uc3QgZW50cnkgb2Ygb3V0cHV0LmxvZ3MoKSkge1xuICAgICAgICAgIGlmIChlbnRyeS5zdHJlYW0gPT09IFwic3Rkb3V0XCIpIHtcbiAgICAgICAgICAgIHN0ZG91dCArPSBlbnRyeS5kYXRhO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzdGRlcnIgKz0gZW50cnkuZGF0YTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBsb2dCdWZmZXIucHVzaChlbnRyeSk7XG4gICAgICAgICAgc3RhdGUucmVzb2x2ZT8uKCk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBTYW5kYm94IG1heSBoYXZlIGJlZW4gc3RvcHBlZCBcdTIwMTQgbG9ncyBlbmRwb2ludCByZXR1cm5zIDQyMlxuICAgICAgfVxuICAgICAgc3RhdGUuY29uc3VtZWQgPSB0cnVlO1xuICAgICAgc3RhdGUucmVzb2x2ZT8uKCk7XG4gICAgfSkoKTtcblxuICAgIGFzeW5jIGZ1bmN0aW9uKiBsb2dzKCk6IEFzeW5jSXRlcmFibGU8e1xuICAgICAgc3RyZWFtOiBcInN0ZG91dFwiIHwgXCJzdGRlcnJcIjtcbiAgICAgIGRhdGE6IHN0cmluZztcbiAgICB9PiB7XG4gICAgICBsZXQgaW5kZXggPSAwO1xuICAgICAgd2hpbGUgKCFzdGF0ZS5jb25zdW1lZCB8fCBpbmRleCA8IGxvZ0J1ZmZlci5sZW5ndGgpIHtcbiAgICAgICAgaWYgKGluZGV4IDwgbG9nQnVmZmVyLmxlbmd0aCkge1xuICAgICAgICAgIHlpZWxkIGxvZ0J1ZmZlcltpbmRleCsrXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocikgPT4ge1xuICAgICAgICAgICAgc3RhdGUucmVzb2x2ZSA9IHI7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgc3RhdGUucmVzb2x2ZSA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCByZXN1bHQgPSBjb25zdW1lTG9ncy50aGVuKGFzeW5jICgpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGZpbmlzaGVkID0gYXdhaXQgb3V0cHV0LndhaXQoKTtcbiAgICAgICAgcmV0dXJuIHsgc3Rkb3V0LCBzdGRlcnIsIGV4aXRDb2RlOiBmaW5pc2hlZC5leGl0Q29kZSB9O1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoaXNTYW5kYm94R29uZUVycm9yKGUpKSB7XG4gICAgICAgICAgcmV0dXJuIHsgc3Rkb3V0LCBzdGRlcnIsIGV4aXRDb2RlOiAxIH07XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiB7IGNvbW1hbmRJZDogb3V0cHV0LmNtZElkLCBsb2dzLCByZXN1bHQgfTtcbiAgfVxuXG4gIGFzeW5jIHJlYWRGaWxlKHtcbiAgICBwYXRoOiBmaWxlUGF0aCxcbiAgfToge1xuICAgIHBhdGg6IHN0cmluZztcbiAgICBzaWduYWw/OiBBYm9ydFNpZ25hbDtcbiAgfSk6IFByb21pc2U8QnVmZmVyIHwgbnVsbD4ge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5zZGsucmVhZEZpbGVUb0J1ZmZlcih7IHBhdGg6IGZpbGVQYXRoLCBjd2Q6IHRoaXMuY3dkIH0pO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgd3JpdGVGaWxlcyh7XG4gICAgZmlsZXMsXG4gICAgZGVzdFBhdGgsXG4gIH06IHtcbiAgICBmaWxlczogeyBwYXRoOiBzdHJpbmc7IGNvbnRlbnQ6IHN0cmluZyB8IEJ1ZmZlciB9W107XG4gICAgZGVzdFBhdGg6IHN0cmluZztcbiAgICBzaWduYWw/OiBBYm9ydFNpZ25hbDtcbiAgfSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmIChmaWxlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBwYXRoID0gYXdhaXQgaW1wb3J0KFwibm9kZTpwYXRoXCIpO1xuICAgIGNvbnN0IG5hdGl2ZUZpbGVzID0gZmlsZXMubWFwKChmaWxlKSA9PiB7XG4gICAgICBjb25zdCBmaWxlUGF0aCA9IHBhdGgucG9zaXguam9pbihkZXN0UGF0aCwgZmlsZS5wYXRoKTtcbiAgICAgIGNvbnN0IGFic29sdXRlUGF0aCA9IHBhdGgucG9zaXguaXNBYnNvbHV0ZShmaWxlUGF0aClcbiAgICAgICAgPyBmaWxlUGF0aFxuICAgICAgICA6IHBhdGgucG9zaXguam9pbih0aGlzLmN3ZCwgZmlsZVBhdGgpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgcGF0aDogYWJzb2x1dGVQYXRoLFxuICAgICAgICBjb250ZW50OlxuICAgICAgICAgIHR5cGVvZiBmaWxlLmNvbnRlbnQgPT09IFwic3RyaW5nXCJcbiAgICAgICAgICAgID8gQnVmZmVyLmZyb20oZmlsZS5jb250ZW50KVxuICAgICAgICAgICAgOiBmaWxlLmNvbnRlbnQsXG4gICAgICB9O1xuICAgIH0pO1xuXG4gICAgYXdhaXQgdGhpcy5zZGsud3JpdGVGaWxlcyhuYXRpdmVGaWxlcyk7XG5cbiAgICBjb25zdCBzaGVsbFNjcmlwdHMgPSBuYXRpdmVGaWxlcy5maWx0ZXIoKGYpID0+IGYucGF0aC5lbmRzV2l0aChcIi5zaFwiKSk7XG4gICAgaWYgKHNoZWxsU2NyaXB0cy5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmV4ZWMoe1xuICAgICAgICBjb21tYW5kOiBcImNobW9kXCIsXG4gICAgICAgIGFyZ3M6IFtcIit4XCIsIC4uLnNoZWxsU2NyaXB0cy5tYXAoKGYpID0+IGYucGF0aCldLFxuICAgICAgfSk7XG4gICAgICBhd2FpdCByZXN1bHQucmVzdWx0O1xuICAgIH1cbiAgfVxuXG4gIC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvdXNlQXdhaXQ6IHN5bmNocm9ub3VzIFNESyBjYWxsXG4gIGFzeW5jIGdldERvbWFpbih7XG4gICAgcG9ydCxcbiAgfToge1xuICAgIHBvcnQ6IG51bWJlcjtcbiAgICBzaWduYWw/OiBBYm9ydFNpZ25hbDtcbiAgfSk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgcmV0dXJuIHRoaXMuc2RrLmRvbWFpbihwb3J0KTtcbiAgfVxuXG4gIGFzeW5jIGtpbGwoe1xuICAgIGNvbW1hbmRJZCxcbiAgfToge1xuICAgIGNvbW1hbmRJZDogc3RyaW5nO1xuICAgIHNpZ25hbD86IEFib3J0U2lnbmFsO1xuICB9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY21kID0gYXdhaXQgdGhpcy5zZGsuZ2V0Q29tbWFuZChjb21tYW5kSWQpO1xuICAgIGF3YWl0IGNtZC5raWxsKCk7XG4gIH1cblxuICAvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL3VzZUF3YWl0OiBzeW5jaHJvbm91cyBTREsgZ2V0dGVyXG4gIGFzeW5jIGdldFN0YXR1cygpOiBQcm9taXNlPFxuICAgIFwicGVuZGluZ1wiIHwgXCJydW5uaW5nXCIgfCBcInN0b3BwaW5nXCIgfCBcInN0b3BwZWRcIiB8IFwiZmFpbGVkXCJcbiAgPiB7XG4gICAgY29uc3Qgc3RhdHVzID0gdGhpcy5zZGsuc3RhdHVzO1xuICAgIC8vIE1hcCBTREstb25seSBzdGF0dXNlcyB0byBvdXIgaW50ZXJmYWNlJ3MgdW5pb25cbiAgICBpZiAoc3RhdHVzID09PSBcInNuYXBzaG90dGluZ1wiKSB7XG4gICAgICByZXR1cm4gXCJzdG9wcGluZ1wiO1xuICAgIH1cbiAgICBpZiAoc3RhdHVzID09PSBcImFib3J0ZWRcIikge1xuICAgICAgcmV0dXJuIFwiZmFpbGVkXCI7XG4gICAgfVxuICAgIHJldHVybiBzdGF0dXM7XG4gIH1cblxuICBhc3luYyBzdGFydCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBUaGUgVmVyY2VsIFNESyBkb2Vzbid0IGhhdmUgYSByZXN1bWUgbWV0aG9kLlxuICAgIC8vIFJ1biBhIG5vLW9wIGNvbW1hbmQgdG8gdmVyaWZ5IHRoZSBzYW5kYm94IGlzIHJlYWNoYWJsZS5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmV4ZWMoeyBjb21tYW5kOiBcInRydWVcIiB9KTtcbiAgICBhd2FpdCByZXN1bHQucmVzdWx0O1xuICB9XG5cbiAgYXN5bmMgc3RvcCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLnNkay5zdG9wKCk7XG4gIH1cblxuICBhc3luYyBzbmFwc2hvdCgpOiBQcm9taXNlPHsgc25hcHNob3RJZDogc3RyaW5nIH0+IHtcbiAgICBjb25zdCBzbmFwID0gYXdhaXQgdGhpcy5zZGsuc25hcHNob3QoKTtcbiAgICByZXR1cm4geyBzbmFwc2hvdElkOiBzbmFwLnNuYXBzaG90SWQgfTtcbiAgfVxuXG4gIGFzeW5jIHVwZGF0ZU5ldHdvcmtQb2xpY3koe1xuICAgIHBvbGljeSxcbiAgfToge1xuICAgIHBvbGljeTogaW1wb3J0KFwiQHZlcmNlbC9zYW5kYm94XCIpLk5ldHdvcmtQb2xpY3k7XG4gICAgc2lnbmFsPzogQWJvcnRTaWduYWw7XG4gIH0pOiBQcm9taXNlPGltcG9ydChcIkB2ZXJjZWwvc2FuZGJveFwiKS5OZXR3b3JrUG9saWN5PiB7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuc2RrLnVwZGF0ZU5ldHdvcmtQb2xpY3kocG9saWN5KTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdmVyY2VsU2FuZGJveCgpOiBTYW5kYm94QmluZGluZzxcbiAgXCJ2ZXJjZWxcIixcbiAgVmVyY2VsQmluZGluZ0NvbmZpZyxcbiAgVmVyY2VsQmluZGluZ01ldGFkYXRhXG4+IHtcbiAgcmV0dXJuIHtcbiAgICB0eXBlOiBcInZlcmNlbFwiLFxuICAgIGFzeW5jIGNyZWF0ZSh7IGFnZW50LCBzZXR1cCwgcmVjb3JkLCBzaWduYWw6IF9zaWduYWwsIGxvZyB9KSB7XG4gICAgICBjb25zdCBzdG9yYWdlID0gYWdlbnQuc3RvcmFnZTtcbiAgICAgIGNvbnN0IGNvbmZpZyA9IHNldHVwLmNvbmZpZyA/PyB7fTtcbiAgICAgIGNvbnN0IGN3ZCA9IGNvbmZpZy5jd2Q7XG4gICAgICBjb25zdCByZXNvdXJjZXMgPSBjb25maWcucmVzb3VyY2VzID8/IHsgdmNwdXM6IERFRkFVTFRfVkNQVVMgfTtcbiAgICAgIGNvbnN0IHBvcnRzID0gY29uZmlnLnBvcnRzO1xuICAgICAgY29uc3QgbmV0d29ya1BvbGljeSA9XG4gICAgICAgIGNvbmZpZy5uZXR3b3JrUG9saWN5ID8/IHNldHVwLm5ldHdvcmtQb2xpY3kgPz8gdW5kZWZpbmVkO1xuXG4gICAgICBjb25zdCBzYW5kYm94T3B0czogQ3JlYXRlU2FuZGJveE9wdHMgPSB7XG4gICAgICAgIHJlc291cmNlcyxcbiAgICAgICAgcG9ydHMsXG4gICAgICAgIG5ldHdvcmtQb2xpY3ksXG4gICAgICAgIHNuYXBzaG90SWQ6IGNvbmZpZy5zbmFwc2hvdElkLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgX3N0YXJ0TGlmZWN5Y2xlID0gKHZlcmNlbFNhbmRib3hJZDogc3RyaW5nKSA9PiB7XG4gICAgICAgIGlmICghcmVjb3JkKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHN0YXJ0V29ya2Zsb3coc2FuZGJveExpZmVjeWNsZVdvcmtmbG93LCBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgaW5wdXQ6IHtcbiAgICAgICAgICAgICAgYWdlbnQsXG4gICAgICAgICAgICAgIHNhbmRib3hJZDogcmVjb3JkLmlkLFxuICAgICAgICAgICAgICB2ZXJjZWxTYW5kYm94SWQsXG4gICAgICAgICAgICAgIGNvbmZpZzogY29uZmlnLmxpZmVjeWNsZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgXSkuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICBsb2cuZXJyb3IoXCJmYWlsZWQgdG8gc3RhcnQgbGlmZWN5Y2xlIHdvcmtmbG93XCIsIHsgY2F1c2U6IGUgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgaWYgKHNldHVwLnZlcnNpb24pIHtcbiAgICAgICAgY29uc3QgZXhpc3RpbmcgPSBhd2FpdCBzdG9yYWdlLnNldHVwLmdldChzZXR1cC52ZXJzaW9uKTtcbiAgICAgICAgaWYgKGV4aXN0aW5nPy5zbmFwc2hvdElkKSB7XG4gICAgICAgICAgY29uc3Qgc2RrID0gYXdhaXQgY3JlYXRlU2RrKHtcbiAgICAgICAgICAgIC4uLnNhbmRib3hPcHRzLFxuICAgICAgICAgICAgc25hcHNob3RJZDogZXhpc3Rpbmcuc25hcHNob3RJZCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBjb25zdCBpbnN0YW5jZSA9IG5ldyBWZXJjZWxTYW5kYm94SW5zdGFuY2Uoc2RrLCBjd2QpO1xuXG4gICAgICAgICAgc3RvcmFnZS5zZXR1cFxuICAgICAgICAgICAgLnNldChzZXR1cC52ZXJzaW9uLCB7XG4gICAgICAgICAgICAgIC4uLmV4aXN0aW5nLFxuICAgICAgICAgICAgICB2ZXJzaW9uOiBzZXR1cC52ZXJzaW9uLFxuICAgICAgICAgICAgICBsYXN0VXNlZEF0OiBEYXRlLm5vdygpLFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuXG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGluc3RhbmNlLFxuICAgICAgICAgICAgbWV0YWRhdGE6IHsgc2FuZGJveElkOiBzZGsuc2FuZGJveElkIH0sXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoc2V0dXAucnVuKSB7XG4gICAgICAgIGlmICghc2V0dXAudmVyc2lvbikge1xuICAgICAgICAgIGxvZy5lcnJvcihcInNldHVwLnJ1biBwcm92aWRlZCB3aXRob3V0IHNldHVwLnZlcnNpb25cIiwgeyBzZXR1cCB9KTtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJzZXR1cC5ydW4gcHJvdmlkZWQgd2l0aG91dCBzZXR1cC52ZXJzaW9uXCIpO1xuICAgICAgICB9XG4gICAgICAgIGNyZWF0ZVNldHVwU25hcHNob3Qoe1xuICAgICAgICAgIHNhbmRib3hPcHRzLFxuICAgICAgICAgIHJ1bjogc2V0dXAucnVuLFxuICAgICAgICAgIHN0b3JhZ2UsXG4gICAgICAgICAgc25hcHNob3RWZXJzaW9uOiBzZXR1cC52ZXJzaW9uLFxuICAgICAgICAgIGxvZyxcbiAgICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgICAgbG9nLmVycm9yKFwiYmFja2dyb3VuZCBzZXR1cCBzbmFwc2hvdCBmYWlsZWRcIiwgeyBjYXVzZTogZXJyb3IgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IHNkayA9IGF3YWl0IGNyZWF0ZVNkayhzYW5kYm94T3B0cyk7XG4gICAgICAgIGNvbnN0IGluc3RhbmNlID0gbmV3IFZlcmNlbFNhbmRib3hJbnN0YW5jZShzZGssIGN3ZCk7XG4gICAgICAgIGF3YWl0IHNldHVwLnJ1bihpbnN0YW5jZSk7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBpbnN0YW5jZSxcbiAgICAgICAgICBtZXRhZGF0YTogeyBzYW5kYm94SWQ6IHNkay5zYW5kYm94SWQgfSxcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc2RrID0gYXdhaXQgY3JlYXRlU2RrKHNhbmRib3hPcHRzKTtcbiAgICAgIGNvbnN0IGluc3RhbmNlID0gbmV3IFZlcmNlbFNhbmRib3hJbnN0YW5jZShzZGssIGN3ZCk7XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGluc3RhbmNlLFxuICAgICAgICBtZXRhZGF0YTogeyBzYW5kYm94SWQ6IHNkay5zYW5kYm94SWQgfSxcbiAgICAgIH07XG4gICAgfSxcblxuICAgIGFzeW5jIGNvbm5lY3QoeyBtZXRhZGF0YSB9KSB7XG4gICAgICBjb25zdCBTYW5kYm94U0RLID0gYXdhaXQgbG9hZFNhbmRib3hTREsoKTtcbiAgICAgIGNvbnN0IHNkayA9IGF3YWl0IFNhbmRib3hTREsuZ2V0KHtcbiAgICAgICAgc2FuZGJveElkOiBtZXRhZGF0YS5zYW5kYm94SWQsXG4gICAgICAgIC4uLmdldFRlc3RDcmVkZW50aWFscygpLFxuICAgICAgfSk7XG4gICAgICByZXR1cm4gbmV3IFZlcmNlbFNhbmRib3hJbnN0YW5jZShzZGspO1xuICAgIH0sXG4gIH07XG59XG4iLCAiaW1wb3J0IHsgc2xlZXAgfSBmcm9tIFwid29ya2Zsb3dcIjtcbmltcG9ydCB7IGNyZWF0ZUxvZ2dlciB9IGZyb20gXCIuLi8uLi8uLi91dGlscy9sb2dnZXJcIjtcbmltcG9ydCB7IGNoZWNrQW5kU25hcHNob3RTdGVwLCB0eXBlIExpZmVjeWNsZUlucHV0IH0gZnJvbSBcIi4vc3RlcHNcIjtcblxuZXhwb3J0IHR5cGUgeyBMaWZlY3ljbGVJbnB1dCB9O1xuXG5jb25zdCBERUZBVUxUX1BPTExfTVMgPSAyICogNjAgKiAxMDAwO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2FuZGJveExpZmVjeWNsZVdvcmtmbG93KHtcbiAgaW5wdXQsXG59OiB7XG4gIGlucHV0OiBMaWZlY3ljbGVJbnB1dDtcbn0pIHtcbiAgXCJ1c2Ugd29ya2Zsb3dcIjtcblxuICBsZXQgbmV4dFBvbGxNcyA9IGlucHV0LmNvbmZpZz8ucG9sbEludGVydmFsTXMgPz8gREVGQVVMVF9QT0xMX01TO1xuICBjb25zdCBsb2cgPSBjcmVhdGVMb2dnZXIoe1xuICAgIGNvbmZpZzogeyAuLi5pbnB1dC5hZ2VudC5vcHRpb25zLmxvZ2dpbmcsIG5hbWU6IGlucHV0LmFnZW50Lm5hbWUgfSxcbiAgICBzdWJzeXN0ZW06IFwic2FuZGJveDpsaWZlY3ljbGVcIixcbiAgICBjb250ZXh0OiB7IHNhbmRib3hJZDogaW5wdXQuc2FuZGJveElkIH0sXG4gIH0pO1xuXG4gIGxvZy5pbmZvKFwibGlmZWN5Y2xlIHdvcmtmbG93IHN0YXJ0ZWRcIiwge1xuICAgIHNhbmRib3hJZDogaW5wdXQuc2FuZGJveElkLFxuICAgIHZlcmNlbFNhbmRib3hJZDogaW5wdXQudmVyY2VsU2FuZGJveElkLFxuICAgIHBvbGxNczogbmV4dFBvbGxNcyxcbiAgfSk7XG5cbiAgd2hpbGUgKHRydWUpIHtcbiAgICBhd2FpdCBzbGVlcChuZXh0UG9sbE1zKTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNoZWNrQW5kU25hcHNob3RTdGVwKGlucHV0KTtcblxuICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgbG9nLmVycm9yKFwibGlmZWN5Y2xlIHN0ZXAgZmFpbGVkXCIsIHtcbiAgICAgICAgc2FuZGJveElkOiBpbnB1dC5zYW5kYm94SWQsXG4gICAgICAgIGVycm9yOiByZXN1bHQubWVzc2FnZSxcbiAgICAgIH0pO1xuICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgaWYgKHJlc3VsdC5hY3Rpb24gPT09IFwiZXhpdFwiKSB7XG4gICAgICBsb2cuaW5mbyhcImxpZmVjeWNsZSB3b3JrZmxvdyBleGl0aW5nXCIsIHtcbiAgICAgICAgc2FuZGJveElkOiBpbnB1dC5zYW5kYm94SWQsXG4gICAgICAgIHJlYXNvbjogcmVzdWx0LnJlYXNvbixcbiAgICAgIH0pO1xuICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgbmV4dFBvbGxNcyA9IHJlc3VsdC5uZXh0UG9sbE1zO1xuICB9XG59XG4iLCAiZXhwb3J0IHR5cGUgTG9nTGV2ZWwgPSBcImluZm9cIiB8IFwid2FyblwiIHwgXCJlcnJvclwiIHwgXCJzaWxlbnRcIjtcblxuY29uc3QgTE9HX0xFVkVMX1BSSU9SSVRZOiBSZWNvcmQ8TG9nTGV2ZWwsIG51bWJlcj4gPSB7XG4gIGluZm86IDAsXG4gIHdhcm46IDEsXG4gIGVycm9yOiAyLFxuICBzaWxlbnQ6IDMsXG59O1xuXG5leHBvcnQgdHlwZSBMb2dDb250ZXh0ID0ge1xuICBzZXNzaW9uSWQ/OiBzdHJpbmc7XG4gIG1lc3NhZ2VJZD86IHN0cmluZztcbiAgc2FuZGJveElkPzogc3RyaW5nO1xuICBba2V5OiBzdHJpbmddOiB1bmtub3duO1xufTtcblxuZXhwb3J0IHR5cGUgTG9nZ2luZ0NvbmZpZyA9IHtcbiAgbGV2ZWw/OiBMb2dMZXZlbDtcbiAgLyoqXG4gICAqIFRvcC1sZXZlbCBsYWJlbCBmb3IgYWxsIGxvZyBsaW5lcy5cbiAgICogQGRlZmF1bHQgXCJhZ2VudFwiXG4gICAqIEBleGFtcGxlIFwibXktYXBwXCIgXHUyMTkyIFtteS1hcHA6ZGVmYXVsdDp3b3JrZmxvd11cbiAgICovXG4gIHByZWZpeD86IHN0cmluZztcbiAgbmFtZT86IHN0cmluZztcbn07XG5cbmZ1bmN0aW9uIGdldExldmVsKGNvbmZpZzogTG9nZ2luZ0NvbmZpZyk6IExvZ0xldmVsIHtcbiAgcmV0dXJuIGNvbmZpZy5sZXZlbCA/PyBcIndhcm5cIjtcbn1cblxuZnVuY3Rpb24gZ2V0UHJlZml4KGNvbmZpZzogTG9nZ2luZ0NvbmZpZyk6IHN0cmluZyB7XG4gIHJldHVybiBjb25maWcucHJlZml4ID8/IFwiYWdlbnRcIjtcbn1cblxuZnVuY3Rpb24gc2hvdWxkTG9nKGNvbmZpZzogTG9nZ2luZ0NvbmZpZywgbGV2ZWw6IExvZ0xldmVsKTogYm9vbGVhbiB7XG4gIHJldHVybiBMT0dfTEVWRUxfUFJJT1JJVFlbbGV2ZWxdID49IExPR19MRVZFTF9QUklPUklUWVtnZXRMZXZlbChjb25maWcpXTtcbn1cblxuZnVuY3Rpb24gZm9ybWF0VGFnKGNvbmZpZzogTG9nZ2luZ0NvbmZpZywgc3Vic3lzdGVtOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gYFske2dldFByZWZpeChjb25maWcpfToke2NvbmZpZy5uYW1lfToke3N1YnN5c3RlbX1dYDtcbn1cblxuZnVuY3Rpb24gZm9ybWF0RGF0YShcbiAgY29udGV4dDogTG9nQ29udGV4dCxcbiAgZXh0cmE/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPlxuKTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfCB1bmRlZmluZWQge1xuICBjb25zdCBtZXJnZWQgPSB7IC4uLmNvbnRleHQsIC4uLmV4dHJhIH07XG4gIGNvbnN0IGVudHJpZXMgPSBPYmplY3QuZW50cmllcyhtZXJnZWQpLmZpbHRlcihcbiAgICAoWywgdl0pID0+IHYgIT09IHVuZGVmaW5lZCAmJiB2ICE9PSBudWxsXG4gICk7XG4gIGlmIChlbnRyaWVzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbiAgcmV0dXJuIE9iamVjdC5mcm9tRW50cmllcyhlbnRyaWVzKTtcbn1cblxuZXhwb3J0IGNsYXNzIExvZ2dlciB7XG4gIHJlYWRvbmx5IHN1YnN5c3RlbTogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IGNvbmZpZzogTG9nZ2luZ0NvbmZpZztcbiAgcHJpdmF0ZSByZWFkb25seSBjb250ZXh0OiBMb2dDb250ZXh0O1xuXG4gIGNvbnN0cnVjdG9yKHtcbiAgICBzdWJzeXN0ZW0sXG4gICAgY29uZmlnLFxuICAgIGNvbnRleHQsXG4gIH06IHtcbiAgICBzdWJzeXN0ZW06IHN0cmluZztcbiAgICBjb25maWc6IExvZ2dpbmdDb25maWc7XG4gICAgY29udGV4dD86IExvZ0NvbnRleHQ7XG4gIH0pIHtcbiAgICB0aGlzLnN1YnN5c3RlbSA9IHN1YnN5c3RlbTtcbiAgICB0aGlzLmNvbmZpZyA9IGNvbmZpZztcbiAgICB0aGlzLmNvbnRleHQgPSBjb250ZXh0ID8/IHt9O1xuICB9XG5cbiAgY2hpbGQoe1xuICAgIHN1YnN5c3RlbSxcbiAgICBjb250ZXh0LFxuICB9OiB7XG4gICAgc3Vic3lzdGVtPzogc3RyaW5nO1xuICAgIGNvbnRleHQ/OiBMb2dDb250ZXh0O1xuICB9KTogTG9nZ2VyIHtcbiAgICByZXR1cm4gbmV3IExvZ2dlcih7XG4gICAgICBjb25maWc6IHRoaXMuY29uZmlnLFxuICAgICAgc3Vic3lzdGVtOiBzdWJzeXN0ZW0gPyBgJHt0aGlzLnN1YnN5c3RlbX06JHtzdWJzeXN0ZW19YCA6IHRoaXMuc3Vic3lzdGVtLFxuICAgICAgY29udGV4dDogeyAuLi50aGlzLmNvbnRleHQsIC4uLmNvbnRleHQgfSxcbiAgICB9KTtcbiAgfVxuXG4gIHdpdGhDb250ZXh0KGNvbnRleHQ6IExvZ0NvbnRleHQpOiBMb2dnZXIge1xuICAgIHJldHVybiBuZXcgTG9nZ2VyKHtcbiAgICAgIGNvbmZpZzogdGhpcy5jb25maWcsXG4gICAgICBzdWJzeXN0ZW06IHRoaXMuc3Vic3lzdGVtLFxuICAgICAgY29udGV4dDogeyAuLi50aGlzLmNvbnRleHQsIC4uLmNvbnRleHQgfSxcbiAgICB9KTtcbiAgfVxuXG4gIGluZm8obWVzc2FnZTogc3RyaW5nLCBkYXRhPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiB2b2lkIHtcbiAgICBpZiAoIXNob3VsZExvZyh0aGlzLmNvbmZpZywgXCJpbmZvXCIpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGQgPSBmb3JtYXREYXRhKHRoaXMuY29udGV4dCwgZGF0YSk7XG4gICAgaWYgKGQpIHtcbiAgICAgIGNvbnNvbGUuaW5mbyhmb3JtYXRUYWcodGhpcy5jb25maWcsIHRoaXMuc3Vic3lzdGVtKSwgbWVzc2FnZSwgZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnNvbGUuaW5mbyhmb3JtYXRUYWcodGhpcy5jb25maWcsIHRoaXMuc3Vic3lzdGVtKSwgbWVzc2FnZSk7XG4gICAgfVxuICB9XG5cbiAgd2FybihtZXNzYWdlOiBzdHJpbmcsIGRhdGE/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IHZvaWQge1xuICAgIGlmICghc2hvdWxkTG9nKHRoaXMuY29uZmlnLCBcIndhcm5cIikpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgZCA9IGZvcm1hdERhdGEodGhpcy5jb250ZXh0LCBkYXRhKTtcbiAgICBpZiAoZCkge1xuICAgICAgY29uc29sZS53YXJuKGZvcm1hdFRhZyh0aGlzLmNvbmZpZywgdGhpcy5zdWJzeXN0ZW0pLCBtZXNzYWdlLCBkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS53YXJuKGZvcm1hdFRhZyh0aGlzLmNvbmZpZywgdGhpcy5zdWJzeXN0ZW0pLCBtZXNzYWdlKTtcbiAgICB9XG4gIH1cblxuICBlcnJvcihtZXNzYWdlOiBzdHJpbmcsIGRhdGE/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IHZvaWQge1xuICAgIGlmICghc2hvdWxkTG9nKHRoaXMuY29uZmlnLCBcImVycm9yXCIpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGQgPSBmb3JtYXREYXRhKHRoaXMuY29udGV4dCwgZGF0YSk7XG4gICAgaWYgKGQpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoZm9ybWF0VGFnKHRoaXMuY29uZmlnLCB0aGlzLnN1YnN5c3RlbSksIG1lc3NhZ2UsIGQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zb2xlLmVycm9yKGZvcm1hdFRhZyh0aGlzLmNvbmZpZywgdGhpcy5zdWJzeXN0ZW0pLCBtZXNzYWdlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQsIHdoZW4gY2FsbGVkLCBsb2dzIHRoZSBlbGFwc2VkIHRpbWUgYXQgaW5mbyBsZXZlbC5cbiAgICogUGFzcyBgbG9nT25TdGFydDogdHJ1ZWAgdG8gYWxzbyBsb2cgd2hlbiB0aGUgdGltZXIgYmVnaW5zLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBjb25zdCBkb25lID0gbG9nLnRpbWUoXCJzYW5kYm94IHNldHVwXCIsIHsgc2FuZGJveElkIH0sIHsgbG9nT25TdGFydDogdHJ1ZSB9KTtcbiAgICogYXdhaXQgc2V0dXAoKTtcbiAgICogZG9uZSgpOyAvLyBzdGFydDogW2FnZW50OmRlZmF1bHQ6c2FuZGJveF0gc2FuZGJveCBzZXR1cCB7IHNhbmRib3hJZDogJy4uLicgfVxuICAgKiAgICAgICAgIC8vIGVuZDogICBbYWdlbnQ6ZGVmYXVsdDpzYW5kYm94XSBzYW5kYm94IHNldHVwIHsgc2FuZGJveElkOiAnLi4uJywgZHVyYXRpb25NczogMTIzIH1cbiAgICovXG4gIHRpbWUoXG4gICAgbWVzc2FnZTogc3RyaW5nLFxuICAgIGRhdGE/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgICBvcHRzPzogeyBsb2dPblN0YXJ0PzogYm9vbGVhbiB9XG4gICk6IChlbmREYXRhPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pID0+IHZvaWQge1xuICAgIGlmIChvcHRzPy5sb2dPblN0YXJ0KSB7XG4gICAgICB0aGlzLmluZm8oYFtzdGFydF0gJHttZXNzYWdlfWAsIGRhdGEpO1xuICAgIH1cbiAgICBjb25zdCB0MCA9IERhdGUubm93KCk7XG4gICAgcmV0dXJuIChlbmREYXRhPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pID0+IHtcbiAgICAgIHRoaXMuaW5mbyhvcHRzPy5sb2dPblN0YXJ0ID8gYFtlbmRdICR7bWVzc2FnZX1gIDogbWVzc2FnZSwge1xuICAgICAgICAuLi5kYXRhLFxuICAgICAgICAuLi5lbmREYXRhLFxuICAgICAgICBkdXJhdGlvbk1zOiBEYXRlLm5vdygpIC0gdDAsXG4gICAgICB9KTtcbiAgICB9O1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVMb2dnZXIoe1xuICBjb25maWcsXG4gIHN1YnN5c3RlbSxcbiAgY29udGV4dCxcbn06IHtcbiAgY29uZmlnOiBMb2dnaW5nQ29uZmlnO1xuICBzdWJzeXN0ZW06IHN0cmluZztcbiAgY29udGV4dD86IExvZ0NvbnRleHQ7XG59KTogTG9nZ2VyIHtcbiAgcmV0dXJuIG5ldyBMb2dnZXIoeyBjb25maWcsIHN1YnN5c3RlbSwgY29udGV4dCB9KTtcbn1cbiIsICJpbXBvcnQgdHlwZSB7IFNhbmRib3ggYXMgVmVyY2VsU2FuZGJveFNESyB9IGZyb20gXCJAdmVyY2VsL3NhbmRib3hcIjtcbmltcG9ydCB7IGNyZWF0ZUxvZ2dlciB9IGZyb20gXCIuLi8uLi8uLi91dGlscy9sb2dnZXJcIjtcbmltcG9ydCB0eXBlIHsgU2FuZGJveEFnZW50UmVmIH0gZnJvbSBcIi4uLy4uL2FkYXB0ZXJcIjtcbmltcG9ydCB0eXBlIHsgVmVyY2VsQmluZGluZ01ldGFkYXRhIH0gZnJvbSBcIi4uL3ZlcmNlbFwiO1xuXG5hc3luYyBmdW5jdGlvbiBsb2FkU2FuZGJveFNESygpOiBQcm9taXNlPHR5cGVvZiBWZXJjZWxTYW5kYm94U0RLPiB7XG4gIHJldHVybiAoYXdhaXQgaW1wb3J0KFwiQHZlcmNlbC9zYW5kYm94XCIpKS5TYW5kYm94O1xufVxuXG5jb25zdCBERUZBVUxUX1BPTExfSU5URVJWQUxfTVMgPSAyICogNjAgKiAxMDAwO1xuY29uc3QgREVGQVVMVF9JRExFX1RJTUVPVVRfTVMgPSA1ICogNjAgKiAxMDAwO1xuY29uc3QgU05BUFNIT1RfQkVGT1JFX1RJTUVPVVRfTVMgPSAxMCAqIDYwICogMTAwMDtcblxuY29uc3QgZ2V0VGVzdENyZWRlbnRpYWxzID0gKCkgPT5cbiAgcHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09IFwidGVzdFwiXG4gICAgPyB7XG4gICAgICAgIHRva2VuOiBwcm9jZXNzLmVudi5URVNUX1ZFUkNFTF9UT0tFTixcbiAgICAgICAgdGVhbUlkOiBwcm9jZXNzLmVudi5URVNUX1ZFUkNFTF9URUFNX0lELFxuICAgICAgICBwcm9qZWN0SWQ6IHByb2Nlc3MuZW52LlRFU1RfVkVSQ0VMX1BST0pFQ1RfSUQsXG4gICAgICB9XG4gICAgOiB7fTtcblxuZXhwb3J0IHR5cGUgTGlmZWN5Y2xlU3RlcFJlc3VsdCA9XG4gIHwgeyBhY3Rpb246IFwiY29udGludWVcIjsgbmV4dFBvbGxNczogbnVtYmVyIH1cbiAgfCB7XG4gICAgICBhY3Rpb246IFwiZXhpdFwiO1xuICAgICAgcmVhc29uOiBcInNhbmRib3hJZF9jaGFuZ2VkXCIgfCBcImlkbGVcIiB8IFwidGltZW91dFwiIHwgXCJub3RfZm91bmRcIjtcbiAgICB9O1xuXG5leHBvcnQgdHlwZSBMaWZlY3ljbGVDb25maWcgPSB7XG4gIHBvbGxJbnRlcnZhbE1zPzogbnVtYmVyO1xuICBzdG9wQWZ0ZXJJbmFjdGl2ZU1zPzogbnVtYmVyO1xuICBzbmFwc2hvdEJlZm9yZVRpbWVvdXRNcz86IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIExpZmVjeWNsZUlucHV0ID0ge1xuICBhZ2VudDogU2FuZGJveEFnZW50UmVmO1xuICBzYW5kYm94SWQ6IHN0cmluZztcbiAgdmVyY2VsU2FuZGJveElkOiBzdHJpbmc7XG4gIGNvbmZpZz86IExpZmVjeWNsZUNvbmZpZztcbn07XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjaGVja0FuZFNuYXBzaG90U3RlcChcbiAgaW5wdXQ6IExpZmVjeWNsZUlucHV0XG4pOiBQcm9taXNlPEVycm9yIHwgTGlmZWN5Y2xlU3RlcFJlc3VsdD4ge1xuICBcInVzZSBzdGVwXCI7XG5cbiAgY29uc3Qgc3RvcmFnZSA9IGlucHV0LmFnZW50LnN0b3JhZ2U7XG4gIGNvbnN0IGxvZyA9IGNyZWF0ZUxvZ2dlcih7XG4gICAgY29uZmlnOiB7IC4uLmlucHV0LmFnZW50Lm9wdGlvbnMubG9nZ2luZywgbmFtZTogaW5wdXQuYWdlbnQubmFtZSB9LFxuICAgIHN1YnN5c3RlbTogXCJzYW5kYm94OmxpZmVjeWNsZVwiLFxuICAgIGNvbnRleHQ6IHsgc2FuZGJveElkOiBpbnB1dC5zYW5kYm94SWQgfSxcbiAgfSk7XG5cbiAgbG9nLmluZm8oXCJsaWZlY3ljbGUgY2hlY2sgc3RhcnRlZFwiLCB7XG4gICAgdmVyY2VsU2FuZGJveElkOiBpbnB1dC52ZXJjZWxTYW5kYm94SWQsXG4gIH0pO1xuXG4gIGNvbnN0IHJlY29yZCA9IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5nZXQoaW5wdXQuc2FuZGJveElkKTtcbiAgaWYgKCFyZWNvcmQpIHtcbiAgICBsb2cud2FybihcInNhbmRib3ggcmVjb3JkIG5vdCBmb3VuZCwgZXhpdGluZyBsaWZlY3ljbGVcIik7XG4gICAgcmV0dXJuIHsgYWN0aW9uOiBcImV4aXRcIiwgcmVhc29uOiBcIm5vdF9mb3VuZFwiIH07XG4gIH1cblxuICBjb25zdCBtZXRhZGF0YSA9IHJlY29yZC5zZXR1cD8ubWV0YWRhdGEgYXMgVmVyY2VsQmluZGluZ01ldGFkYXRhIHwgbnVsbDtcbiAgY29uc3QgY3VycmVudFNhbmRib3hJZCA9IG1ldGFkYXRhPy5zYW5kYm94SWQgPz8gbnVsbDtcblxuICBpZiAoY3VycmVudFNhbmRib3hJZCAhPT0gaW5wdXQudmVyY2VsU2FuZGJveElkKSB7XG4gICAgbG9nLmluZm8oXCJzYW5kYm94IElEIGNoYW5nZWQsIGV4aXRpbmcgbGlmZWN5Y2xlXCIsIHtcbiAgICAgIGV4cGVjdGVkOiBpbnB1dC52ZXJjZWxTYW5kYm94SWQsXG4gICAgICBhY3R1YWw6IGN1cnJlbnRTYW5kYm94SWQsXG4gICAgfSk7XG4gICAgcmV0dXJuIHsgYWN0aW9uOiBcImV4aXRcIiwgcmVhc29uOiBcInNhbmRib3hJZF9jaGFuZ2VkXCIgfTtcbiAgfVxuXG4gIGlmICghY3VycmVudFNhbmRib3hJZCkge1xuICAgIGxvZy53YXJuKFwibm8gY3VycmVudCBzYW5kYm94IElEIGluIG1ldGFkYXRhLCBleGl0aW5nIGxpZmVjeWNsZVwiKTtcbiAgICByZXR1cm4geyBhY3Rpb246IFwiZXhpdFwiLCByZWFzb246IFwibm90X2ZvdW5kXCIgfTtcbiAgfVxuXG4gIGNvbnN0IHBvbGxJbnRlcnZhbE1zID1cbiAgICBpbnB1dC5jb25maWc/LnBvbGxJbnRlcnZhbE1zID8/IERFRkFVTFRfUE9MTF9JTlRFUlZBTF9NUztcbiAgY29uc3QgaWRsZVRpbWVvdXRNcyA9XG4gICAgaW5wdXQuY29uZmlnPy5zdG9wQWZ0ZXJJbmFjdGl2ZU1zID8/IERFRkFVTFRfSURMRV9USU1FT1VUX01TO1xuICBjb25zdCBzbmFwc2hvdEJlZm9yZVRpbWVvdXRNcyA9XG4gICAgaW5wdXQuY29uZmlnPy5zbmFwc2hvdEJlZm9yZVRpbWVvdXRNcyA/PyBTTkFQU0hPVF9CRUZPUkVfVElNRU9VVF9NUztcblxuICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICBjb25zdCBsYXN0QWN0aXZpdHkgPSByZWNvcmQubGFzdEFjdGl2ZUF0ID8/IHJlY29yZC5jcmVhdGVkQXQgPz8gbm93O1xuICBjb25zdCBpZGxlRHVyYXRpb24gPSBub3cgLSBsYXN0QWN0aXZpdHk7XG4gIGNvbnN0IHNob3VsZFNuYXBzaG90RHVlVG9JZGxlID0gaWRsZUR1cmF0aW9uID4gaWRsZVRpbWVvdXRNcztcblxuICBsZXQgc2hvdWxkU25hcHNob3REdWVUb1RpbWVvdXQgPSBmYWxzZTtcbiAgdHJ5IHtcbiAgICBjb25zdCBTYW5kYm94U0RLID0gYXdhaXQgbG9hZFNhbmRib3hTREsoKTtcbiAgICBjb25zdCBzYW5kYm94ID0gYXdhaXQgU2FuZGJveFNESy5nZXQoe1xuICAgICAgc2FuZGJveElkOiBjdXJyZW50U2FuZGJveElkLFxuICAgICAgLi4uZ2V0VGVzdENyZWRlbnRpYWxzKCksXG4gICAgfSk7XG4gICAgaWYgKHNhbmRib3gudGltZW91dCA8IHNuYXBzaG90QmVmb3JlVGltZW91dE1zKSB7XG4gICAgICBzaG91bGRTbmFwc2hvdER1ZVRvVGltZW91dCA9IHRydWU7XG4gICAgfVxuICB9IGNhdGNoIHtcbiAgICBsb2cud2FybihcImZhaWxlZCB0byBnZXQgc2FuZGJveCBmcm9tIFNESywgZXhpdGluZyBsaWZlY3ljbGVcIiwge1xuICAgICAgdmVyY2VsU2FuZGJveElkOiBjdXJyZW50U2FuZGJveElkLFxuICAgIH0pO1xuICAgIHJldHVybiB7IGFjdGlvbjogXCJleGl0XCIsIHJlYXNvbjogXCJub3RfZm91bmRcIiB9O1xuICB9XG5cbiAgaWYgKHNob3VsZFNuYXBzaG90RHVlVG9JZGxlIHx8IHNob3VsZFNuYXBzaG90RHVlVG9UaW1lb3V0KSB7XG4gICAgY29uc3QgcmVhc29uID0gc2hvdWxkU25hcHNob3REdWVUb0lkbGUgPyBcImlkbGVcIiA6IFwidGltZW91dFwiO1xuICAgIGxvZy5pbmZvKFwic25hcHNob3R0aW5nIHNhbmRib3ggYmVmb3JlIGV4aXRcIiwge1xuICAgICAgcmVhc29uLFxuICAgICAgaWRsZUR1cmF0aW9uTXM6IGlkbGVEdXJhdGlvbixcbiAgICAgIHZlcmNlbFNhbmRib3hJZDogY3VycmVudFNhbmRib3hJZCxcbiAgICB9KTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBTYW5kYm94U0RLID0gYXdhaXQgbG9hZFNhbmRib3hTREsoKTtcbiAgICAgIGNvbnN0IHNhbmRib3ggPSBhd2FpdCBTYW5kYm94U0RLLmdldCh7XG4gICAgICAgIHNhbmRib3hJZDogY3VycmVudFNhbmRib3hJZCxcbiAgICAgICAgLi4uZ2V0VGVzdENyZWRlbnRpYWxzKCksXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IHNuYXBzaG90ID0gYXdhaXQgc2FuZGJveC5zbmFwc2hvdCgpO1xuICAgICAgbG9nLmluZm8oXCJzbmFwc2hvdCBjcmVhdGVkXCIsIHsgc25hcHNob3RJZDogc25hcHNob3Quc25hcHNob3RJZCB9KTtcblxuICAgICAgYXdhaXQgc3RvcmFnZS5zYW5kYm94LnVwZGF0ZShpbnB1dC5zYW5kYm94SWQsIHtcbiAgICAgICAgc2V0dXA6IHtcbiAgICAgICAgICAuLi5yZWNvcmQuc2V0dXAsXG4gICAgICAgICAgbWV0YWRhdGE6IHsgc2FuZGJveElkOiBudWxsLCBzbmFwc2hvdElkOiBzbmFwc2hvdC5zbmFwc2hvdElkIH0sXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICAgIGxvZy5pbmZvKFwic2FuZGJveCByZWNvcmQgdXBkYXRlZCB3aXRoIHNuYXBzaG90XCIpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxvZy5lcnJvcihcImZhaWxlZCB0byBzbmFwc2hvdCBzYW5kYm94XCIsIHsgY2F1c2U6IGUgfSk7XG4gICAgICByZXR1cm4gZSBpbnN0YW5jZW9mIEVycm9yID8gZSA6IG5ldyBFcnJvcihTdHJpbmcoZSkpO1xuICAgIH1cbiAgICByZXR1cm4geyBhY3Rpb246IFwiZXhpdFwiLCByZWFzb24gfTtcbiAgfVxuXG4gIGxvZy5pbmZvKFwic2FuZGJveCBzdGlsbCBhY3RpdmUsIGNvbnRpbnVpbmcgbGlmZWN5Y2xlXCIsIHtcbiAgICBpZGxlRHVyYXRpb25NczogaWRsZUR1cmF0aW9uLFxuICAgIG5leHRQb2xsTXM6IHBvbGxJbnRlcnZhbE1zLFxuICB9KTtcbiAgcmV0dXJuIHsgYWN0aW9uOiBcImNvbnRpbnVlXCIsIG5leHRQb2xsTXM6IHBvbGxJbnRlcnZhbE1zIH07XG59XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTs7O0FDQUEsa0JBQXFCO0FBY3JCLGVBQWUsV0FDYixNQUNBLE1BQytEO0FBQy9ELFFBQU0sRUFBRSxNQUFNLElBQUksTUFBTSxPQUFPLGVBQW9CO0FBQ25ELFNBQU8sSUFBSSxRQUFRLENBQUMsU0FBUyxXQUFXO0FBQ3RDLFVBQU0sUUFBUSxNQUFNLFVBQVUsQ0FBQyxXQUFXLEdBQUcsSUFBSSxHQUFHO0FBQUEsTUFDbEQsUUFBUSxNQUFNO0FBQUEsSUFDaEIsQ0FBQztBQUVELFFBQUksU0FBUztBQUNiLFFBQUksU0FBUztBQUViLFVBQU0sT0FBTyxHQUFHLFFBQVEsQ0FB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LFFBQVEsTUFBTSxJQUFJLE1BQU0sT0FBTztBQUN0RCxZQUFJLFVBQVUsWUFBWTtBQUN4QixnQkFBTUMsT0FBTSxNQUFNLFVBQVU7QUFBQSxZQUMxQixHQUFHO0FBQUEsWUFDSCxZQUFZLFNBQVM7QUFBQSxVQUN2QixDQUFDO0FBQ0QsZ0JBQU1DLFlBQVcsSUFBSSxzQkFBc0JELE1BQUssR0FBRztBQUVuRCxrQkFBUSxNQUNMLElBQUksTUFBTSxTQUFTO0FBQUEsWUFDbEIsR0FBRztBQUFBLFlBQ0gsU0FBUyxNQUFNO0FBQUEsWUFDZixZQUFZLEtBQUssSUFBSTtBQUFBLFVBQ3ZCLENBQUMsRUFDQSxNQUFNLE1BQU0sTUFBUztBQUV4QixpQkFBTztBQUFBLFlBQ0wsVUFBQUM7QUFBQSxZQUNBLFVBQVUsRUFBRSxXQUFXRCxLQUFJLFVBQVU7QUFBQSxVQUN2QztBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBRUEsVUFBSSxNQUFNLEtBQUs7QUFDYixZQUFJLENBQUMsTUFBTSxTQUFTO0FBQ2xCLGNBQUksTUFBTSw0Q0FBNEMsRUFBRSxNQUFNLENBQUM7QUFDL0QsZ0JBQU0sSUFBSSxNQUFNLDBDQUEwQztBQUFBLFFBQzVEO0FBQ0EsNEJBQW9CO0FBQUEsVUFDbEI7QUFBQSxVQUNBLEtBQUssTUFBTTtBQUFBLFVBQ1g7QUFBQSxVQUNBLGlCQUFpQixNQUFNO0FBQUEsVUFDdkI7QUFBQSxRQUNGLENBQUMsRUFBRSxNQUFNLENBQUMsVUFBVTtBQUNsQixjQUFJLE1BQU0sb0NBQW9DLEVBQUUsT0FBTyxNQUFNLENBQUM7QUFBQSxRQUNoRSxDQUFDO0FBRUQsY0FBTUEsT0FBTSxNQUFNLFVBQVUsV0FBVztBQUN2QyxjQUFNQyxZQUFXLElBQUksc0JBQXNCRCxNQUFLLEdBQUc7QUFDbkQsY0FBTSxNQUFNLElBQUlDLFNBQVE7QUFFeEIsZUFBTztBQUFBLFVBQ0wsVUFBQUE7QUFBQSxVQUNBLFVBQVUsRUFBRSxXQUFXRCxLQUFJLFVBQVU7QUFBQSxRQUN2QztBQUFBLE1BQ0Y7QUFFQSxZQUFNLE1BQU0sTUFBTSxVQUFVLFdBQVc7QUFDdkMsWUFBTSxXQUFXLElBQUksc0JBQXNCLEtBQUssR0FBRztBQUVuRCxhQUFPO0FBQUEsUUFDTDtBQUFBLFFBQ0EsVUFBVSxFQUFFLFdBQVcsSUFBSSxVQUFVO0FBQUEsTUFDdkM7QUFBQSxJQUNGO0FBQUEsSUFFQSxNQUFNLFFBQVEsRUFBRSxTQUFTLEdBQUc7QUFDMUIsWUFBTSxhQUFhLE1BQU1ILGdCQUFlO0FBQ3hDLFlBQU0sTUFBTSxNQUFNLFdBQVcsSUFBSTtBQUFBLFFBQy9CLFdBQVcsU0FBUztBQUFBLFFBQ3BCLEdBQUdDLG9CQUFtQjtBQUFBLE1BQ3hCLENBQUM7QUFDRCxhQUFPLElBQUksc0JBQXNCLEdBQUc7QUFBQSxJQUN0QztBQUFBLEVBQ0Y7QUFDRjsiLAogICJuYW1lcyI6IFsiaW1wb3J0X3VsaWQiLCAibG9hZFNhbmRib3hTREsiLCAiZ2V0VGVzdENyZWRlbnRpYWxzIiwgInN0YXJ0V29ya2Zsb3ciLCAic2RrIiwgImluc3RhbmNlIl0KfQo=
|