experimental-agent 0.1.4 → 0.2.1
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/dist/agent-workflow.d.mts +2 -1
- package/dist/agent-workflow.d.ts +2 -1
- package/dist/agent-workflow.js +1382 -552
- package/dist/agent-workflow.mjs +3 -2
- package/dist/chunk-AML2VCQS.mjs +1287 -0
- package/dist/chunk-FQ67QZOI.mjs +75 -0
- package/dist/chunk-NO7RHGTH.mjs +2367 -0
- package/dist/{chunk-24UDM5XV.mjs → chunk-NXDVNJRS.mjs} +1 -1
- package/dist/chunk-OZZVS6L5.mjs +139 -0
- package/dist/{chunk-GYOBANFH.mjs → chunk-QRWGDFFY.mjs} +3 -7
- package/dist/{chunk-2ZXHR6T6.mjs → chunk-SJVFFE5D.mjs} +18 -17
- package/dist/chunk-TGNVXSMX.mjs +399 -0
- package/dist/chunk-ZIAHPXOJ.mjs +595 -0
- package/dist/{client-SNN3XDKO.mjs → client-BKA7XBGW.mjs} +1 -1
- package/dist/{client-Bkuq-Dfa.d.mts → client-CEeSFGva.d.mts} +159 -123
- package/dist/{client-Bkuq-Dfa.d.ts → client-CEeSFGva.d.ts} +159 -123
- package/dist/{sandbox-IFK5MVRM.mjs → docker-FB2MJTHJ.mjs} +6 -4
- package/dist/{handler-WFNQWR6V.mjs → handler-FRUPZ4LX.mjs} +1 -1
- package/dist/index.d.mts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1554 -593
- package/dist/index.mjs +139 -33
- package/dist/lifecycle-workflow.d.mts +2 -1
- package/dist/lifecycle-workflow.d.ts +2 -1
- package/dist/lifecycle-workflow.js +29 -18
- package/dist/lifecycle-workflow.mjs +1 -1
- package/dist/{local-fs-handlers-ESZBRAWK.mjs → local-fs-handlers-SYOCKTPN.mjs} +10 -2
- package/dist/next/loader.js +15 -12
- package/dist/next/loader.mjs +14 -7
- package/dist/next.d.mts +1 -1
- package/dist/next.d.ts +1 -1
- package/dist/next.js +15 -10
- package/dist/next.mjs +14 -5
- package/dist/{process-manager-ZCET3VD2.mjs → process-manager-JDUJDYGU.mjs} +1 -1
- package/dist/sandbox-UENKQV3T.mjs +21 -0
- package/dist/{storage-FCSHTDLC.mjs → storage-LSDMRW73.mjs} +2 -2
- package/package.json +2 -6
- package/dist/chunk-4WDKWMVB.mjs +0 -389
- package/dist/chunk-64THY7Y7.mjs +0 -155
- package/dist/chunk-IACG26TC.mjs +0 -2212
- package/dist/chunk-NGLND33F.mjs +0 -1247
|
@@ -0,0 +1,595 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createLogger
|
|
3
|
+
} from "./chunk-OZZVS6L5.mjs";
|
|
4
|
+
import {
|
|
5
|
+
SandboxError
|
|
6
|
+
} from "./chunk-YRYXN7W4.mjs";
|
|
7
|
+
|
|
8
|
+
// src/sandbox/bindings/docker.ts
|
|
9
|
+
import { execSync, spawn } from "child_process";
|
|
10
|
+
import * as fs from "fs/promises";
|
|
11
|
+
import * as os from "os";
|
|
12
|
+
import * as path2 from "path";
|
|
13
|
+
import * as errore from "errore";
|
|
14
|
+
import { ulid } from "ulid";
|
|
15
|
+
|
|
16
|
+
// src/sandbox/setup-poll.ts
|
|
17
|
+
var log = createLogger({ subsystem: "sandbox:setup" });
|
|
18
|
+
var SETUP_POLL_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
19
|
+
var SETUP_POLL_INTERVAL_MS = 50;
|
|
20
|
+
async function pollForSetupCompletion({
|
|
21
|
+
storage,
|
|
22
|
+
sandboxId,
|
|
23
|
+
setupKey
|
|
24
|
+
}) {
|
|
25
|
+
const deadline = Date.now() + SETUP_POLL_TIMEOUT_MS;
|
|
26
|
+
const done = log.time(
|
|
27
|
+
"waiting for setup completion",
|
|
28
|
+
{ sandboxId, setupKey },
|
|
29
|
+
{ logOnStart: true }
|
|
30
|
+
);
|
|
31
|
+
while (Date.now() < deadline) {
|
|
32
|
+
const record = await storage.sandbox.get(sandboxId);
|
|
33
|
+
if (!(record instanceof Error) && record) {
|
|
34
|
+
if (record.setupCompletedAt && record.setupKey === setupKey) {
|
|
35
|
+
done();
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (!record.setupKey) {
|
|
39
|
+
throw new Error(
|
|
40
|
+
`Setup was reset for sandbox "${sandboxId}" (setupKey cleared). Will retry on next operation.`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
await new Promise((r) => setTimeout(r, SETUP_POLL_INTERVAL_MS));
|
|
45
|
+
}
|
|
46
|
+
throw new Error(
|
|
47
|
+
`Timed out waiting for sandbox setup to complete (sandbox="${sandboxId}")`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
async function markSetupComplete({
|
|
51
|
+
storage,
|
|
52
|
+
sandboxId,
|
|
53
|
+
setupKey
|
|
54
|
+
}) {
|
|
55
|
+
const result = await storage.sandbox.update({
|
|
56
|
+
id: sandboxId,
|
|
57
|
+
setupKey,
|
|
58
|
+
setupCompletedAt: Date.now()
|
|
59
|
+
});
|
|
60
|
+
if (result instanceof Error) {
|
|
61
|
+
throw result;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async function resetSetupState({
|
|
65
|
+
storage,
|
|
66
|
+
sandboxId,
|
|
67
|
+
setupKey
|
|
68
|
+
}) {
|
|
69
|
+
await storage.sandbox.update({
|
|
70
|
+
id: sandboxId,
|
|
71
|
+
setupKey: null,
|
|
72
|
+
setupCompletedAt: null
|
|
73
|
+
}).catch((e) => {
|
|
74
|
+
log.warn("failed to clear setupKey", { sandboxId, error: String(e) });
|
|
75
|
+
});
|
|
76
|
+
await storage.setup.delete(setupKey).catch((e) => {
|
|
77
|
+
log.warn("failed to delete setup record", { setupKey, error: String(e) });
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// src/sandbox/write-files.ts
|
|
82
|
+
import * as path from "path";
|
|
83
|
+
var MAX_RETRIES = 2;
|
|
84
|
+
var RETRY_BASE_MS = 500;
|
|
85
|
+
async function execChecked(sandbox, opts, errorLabel) {
|
|
86
|
+
for (let attempt = 0; ; attempt++) {
|
|
87
|
+
const execResult = await sandbox.exec(opts);
|
|
88
|
+
if (execResult instanceof Error) {
|
|
89
|
+
throw execResult;
|
|
90
|
+
}
|
|
91
|
+
const result = await execResult.result;
|
|
92
|
+
if (result.exitCode === 0) {
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
const isTransient = result.exitCode === 255 && !result.stderr.trim();
|
|
96
|
+
if (isTransient && attempt < MAX_RETRIES) {
|
|
97
|
+
await new Promise((r) => setTimeout(r, RETRY_BASE_MS * (attempt + 1)));
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
throw new Error(
|
|
101
|
+
`${errorLabel} with exit code ${result.exitCode}: ${result.stderr}`
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
async function writeFiles(opts) {
|
|
106
|
+
const { sandbox, files, destPath } = opts;
|
|
107
|
+
if (files.length === 0) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const filePaths = files.map((file) => path.posix.join(destPath, file.path));
|
|
111
|
+
const parentDirs = Array.from(
|
|
112
|
+
new Set(filePaths.map((p) => path.posix.dirname(p)))
|
|
113
|
+
);
|
|
114
|
+
const shellScripts = filePaths.filter((p) => p.endsWith(".sh"));
|
|
115
|
+
const mkdirResult = await sandbox.exec({
|
|
116
|
+
command: "mkdir",
|
|
117
|
+
args: ["-p", ...parentDirs]
|
|
118
|
+
});
|
|
119
|
+
if (mkdirResult instanceof Error) {
|
|
120
|
+
throw mkdirResult;
|
|
121
|
+
}
|
|
122
|
+
await mkdirResult.result;
|
|
123
|
+
const CHUNK_SIZE = 5e4;
|
|
124
|
+
for (let i = 0; i < files.length; i++) {
|
|
125
|
+
const file = files[i];
|
|
126
|
+
const fullPath = filePaths[i];
|
|
127
|
+
const base64Content = toBase64(file.content);
|
|
128
|
+
if (base64Content.length < CHUNK_SIZE) {
|
|
129
|
+
const marker = `EOF_${i}`;
|
|
130
|
+
await execChecked(
|
|
131
|
+
sandbox,
|
|
132
|
+
{
|
|
133
|
+
command: "bash",
|
|
134
|
+
args: [
|
|
135
|
+
"-c",
|
|
136
|
+
`base64 -d > ${quote(fullPath)} << '${marker}'
|
|
137
|
+
${base64Content}
|
|
138
|
+
${marker}`
|
|
139
|
+
]
|
|
140
|
+
},
|
|
141
|
+
"writeFiles failed"
|
|
142
|
+
);
|
|
143
|
+
} else {
|
|
144
|
+
const tempB64 = `/tmp/chunk-${Date.now()}-${i}.b64`;
|
|
145
|
+
const clearResult = await sandbox.exec({
|
|
146
|
+
command: "bash",
|
|
147
|
+
args: ["-c", `> ${quote(tempB64)}`]
|
|
148
|
+
});
|
|
149
|
+
if (clearResult instanceof Error) {
|
|
150
|
+
throw clearResult;
|
|
151
|
+
}
|
|
152
|
+
await clearResult.result;
|
|
153
|
+
for (let offset = 0; offset < base64Content.length; offset += CHUNK_SIZE) {
|
|
154
|
+
const chunk = base64Content.slice(offset, offset + CHUNK_SIZE);
|
|
155
|
+
const marker = `CHUNK_${offset}`;
|
|
156
|
+
await execChecked(
|
|
157
|
+
sandbox,
|
|
158
|
+
{
|
|
159
|
+
command: "bash",
|
|
160
|
+
args: [
|
|
161
|
+
"-c",
|
|
162
|
+
`cat >> ${quote(tempB64)} << '${marker}'
|
|
163
|
+
${chunk}
|
|
164
|
+
${marker}`
|
|
165
|
+
]
|
|
166
|
+
},
|
|
167
|
+
"writeFiles chunk failed"
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
await execChecked(
|
|
171
|
+
sandbox,
|
|
172
|
+
{
|
|
173
|
+
command: "bash",
|
|
174
|
+
args: [
|
|
175
|
+
"-c",
|
|
176
|
+
`base64 -d < ${quote(tempB64)} > ${quote(fullPath)} && rm -f ${quote(tempB64)}`
|
|
177
|
+
]
|
|
178
|
+
},
|
|
179
|
+
"writeFiles decode failed"
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
if (shellScripts.length > 0) {
|
|
184
|
+
const chmodResult = await sandbox.exec({
|
|
185
|
+
command: "chmod",
|
|
186
|
+
args: ["+x", ...shellScripts]
|
|
187
|
+
});
|
|
188
|
+
if (chmodResult instanceof Error) {
|
|
189
|
+
throw chmodResult;
|
|
190
|
+
}
|
|
191
|
+
await chmodResult.result;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
function toBase64(content) {
|
|
195
|
+
if (typeof content === "string") {
|
|
196
|
+
return Buffer.from(content).toString("base64");
|
|
197
|
+
}
|
|
198
|
+
return content.toString("base64");
|
|
199
|
+
}
|
|
200
|
+
function quote(s) {
|
|
201
|
+
return `'${s.replace(/'/g, "'\\''")}'`;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// src/sandbox/bindings/docker.ts
|
|
205
|
+
var dockerAvailable = null;
|
|
206
|
+
async function isDockerSandboxAvailable() {
|
|
207
|
+
if (dockerAvailable !== null) {
|
|
208
|
+
return dockerAvailable;
|
|
209
|
+
}
|
|
210
|
+
try {
|
|
211
|
+
const result = await execDocker(["version"], { timeoutMs: 5e3 });
|
|
212
|
+
dockerAvailable = result.exitCode === 0;
|
|
213
|
+
} catch {
|
|
214
|
+
dockerAvailable = false;
|
|
215
|
+
}
|
|
216
|
+
return dockerAvailable;
|
|
217
|
+
}
|
|
218
|
+
function execDocker(args, opts) {
|
|
219
|
+
return new Promise((resolve, reject) => {
|
|
220
|
+
const child = spawn("docker", ["sandbox", ...args], {
|
|
221
|
+
signal: opts?.signal
|
|
222
|
+
});
|
|
223
|
+
let stdout = "";
|
|
224
|
+
let stderr = "";
|
|
225
|
+
child.stdout.on("data", (data) => {
|
|
226
|
+
stdout += data.toString();
|
|
227
|
+
});
|
|
228
|
+
child.stderr.on("data", (data) => {
|
|
229
|
+
stderr += data.toString();
|
|
230
|
+
});
|
|
231
|
+
const timeoutId = opts?.timeoutMs ? setTimeout(() => {
|
|
232
|
+
child.kill("SIGTERM");
|
|
233
|
+
reject(new Error(`docker sandbox ${args[0]} timed out`));
|
|
234
|
+
}, opts.timeoutMs) : void 0;
|
|
235
|
+
child.on("error", (err) => {
|
|
236
|
+
if (timeoutId) {
|
|
237
|
+
clearTimeout(timeoutId);
|
|
238
|
+
}
|
|
239
|
+
reject(err);
|
|
240
|
+
});
|
|
241
|
+
child.on("close", (code) => {
|
|
242
|
+
if (timeoutId) {
|
|
243
|
+
clearTimeout(timeoutId);
|
|
244
|
+
}
|
|
245
|
+
resolve({ stdout, stderr, exitCode: code ?? 0 });
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
var ensurePromises = /* @__PURE__ */ new Map();
|
|
250
|
+
var activeSandboxes = /* @__PURE__ */ new Set();
|
|
251
|
+
var cleanupRegistered = false;
|
|
252
|
+
function registerCleanup() {
|
|
253
|
+
if (cleanupRegistered) {
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
cleanupRegistered = true;
|
|
257
|
+
const cleanup = () => {
|
|
258
|
+
for (const name of Array.from(activeSandboxes)) {
|
|
259
|
+
try {
|
|
260
|
+
execSync(`docker sandbox stop ${name}`, {
|
|
261
|
+
timeout: 1e4,
|
|
262
|
+
stdio: "pipe"
|
|
263
|
+
});
|
|
264
|
+
} catch {
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
process.on("exit", cleanup);
|
|
269
|
+
process.on("SIGINT", () => {
|
|
270
|
+
cleanup();
|
|
271
|
+
process.exit(130);
|
|
272
|
+
});
|
|
273
|
+
process.on("SIGTERM", () => {
|
|
274
|
+
cleanup();
|
|
275
|
+
process.exit(143);
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
async function ensureSandbox(sandboxId) {
|
|
279
|
+
const existing = ensurePromises.get(sandboxId);
|
|
280
|
+
if (existing) {
|
|
281
|
+
return existing;
|
|
282
|
+
}
|
|
283
|
+
const promise = (async () => {
|
|
284
|
+
const ls = await execDocker(["ls", "-q"], { timeoutMs: 1e4 });
|
|
285
|
+
const existingNames = ls.exitCode === 0 ? ls.stdout.split("\n").map((s) => s.trim()).filter(Boolean) : [];
|
|
286
|
+
if (existingNames.includes(sandboxId)) {
|
|
287
|
+
activeSandboxes.add(sandboxId);
|
|
288
|
+
registerCleanup();
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
const workspaceDir = path2.join(
|
|
292
|
+
os.tmpdir(),
|
|
293
|
+
"agent-docker-sandbox",
|
|
294
|
+
sandboxId
|
|
295
|
+
);
|
|
296
|
+
await fs.mkdir(workspaceDir, { recursive: true });
|
|
297
|
+
const create = await execDocker(
|
|
298
|
+
["create", "--name", sandboxId, "shell", workspaceDir],
|
|
299
|
+
{ timeoutMs: 6e4 }
|
|
300
|
+
);
|
|
301
|
+
if (create.exitCode !== 0) {
|
|
302
|
+
if (create.stderr.includes("already exists")) {
|
|
303
|
+
activeSandboxes.add(sandboxId);
|
|
304
|
+
registerCleanup();
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
throw new Error(
|
|
308
|
+
`Failed to create docker sandbox "${sandboxId}": ${create.stderr}`
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
activeSandboxes.add(sandboxId);
|
|
312
|
+
registerCleanup();
|
|
313
|
+
})();
|
|
314
|
+
ensurePromises.set(sandboxId, promise);
|
|
315
|
+
try {
|
|
316
|
+
await promise;
|
|
317
|
+
} catch (e) {
|
|
318
|
+
ensurePromises.delete(sandboxId);
|
|
319
|
+
throw e;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
var dockerSandbox = ({
|
|
323
|
+
sandboxRecord,
|
|
324
|
+
storage,
|
|
325
|
+
setup,
|
|
326
|
+
onRestart
|
|
327
|
+
}) => {
|
|
328
|
+
const sandboxName = sandboxRecord.id;
|
|
329
|
+
const cwd = sandboxRecord.config.cwd ?? "/home/agent/workspace";
|
|
330
|
+
const processes = /* @__PURE__ */ new Map();
|
|
331
|
+
let startPromise = null;
|
|
332
|
+
const sandbox = {
|
|
333
|
+
id: sandboxRecord.id,
|
|
334
|
+
config: sandboxRecord.config,
|
|
335
|
+
cwd,
|
|
336
|
+
exec: ({ command, args, cwd: cwd2, env, signal, sudo }) => {
|
|
337
|
+
return errore.tryAsync({
|
|
338
|
+
try: async () => {
|
|
339
|
+
await ensureSandbox(sandboxName);
|
|
340
|
+
const commandId = `command_${ulid()}`;
|
|
341
|
+
const envFlags = env === void 0 ? [] : Object.entries(env).flatMap(([k, v]) => ["-e", `${k}=${v}`]);
|
|
342
|
+
const cwdFlags = cwd2 ? ["-w", cwd2] : [];
|
|
343
|
+
const baseCmd = sudo ? ["sudo", command, ...args ?? []] : args ? [command, ...args] : [command];
|
|
344
|
+
const fullCmd = baseCmd;
|
|
345
|
+
const child = spawn(
|
|
346
|
+
"docker",
|
|
347
|
+
[
|
|
348
|
+
"sandbox",
|
|
349
|
+
"exec",
|
|
350
|
+
...envFlags,
|
|
351
|
+
...cwdFlags,
|
|
352
|
+
sandboxName,
|
|
353
|
+
...fullCmd
|
|
354
|
+
],
|
|
355
|
+
{ signal }
|
|
356
|
+
);
|
|
357
|
+
processes.set(commandId, child);
|
|
358
|
+
let stdout = "";
|
|
359
|
+
let stderr = "";
|
|
360
|
+
const logQueue = [];
|
|
361
|
+
let logResolve = null;
|
|
362
|
+
let closed = false;
|
|
363
|
+
child.stdout.on("data", (data) => {
|
|
364
|
+
const str = String(data);
|
|
365
|
+
stdout += str;
|
|
366
|
+
logQueue.push({ stream: "stdout", data: str });
|
|
367
|
+
logResolve?.();
|
|
368
|
+
});
|
|
369
|
+
child.stderr.on("data", (data) => {
|
|
370
|
+
const str = String(data);
|
|
371
|
+
stderr += str;
|
|
372
|
+
logQueue.push({ stream: "stderr", data: str });
|
|
373
|
+
logResolve?.();
|
|
374
|
+
});
|
|
375
|
+
const result = new Promise((resolve, reject) => {
|
|
376
|
+
child.on("error", (err) => {
|
|
377
|
+
processes.delete(commandId);
|
|
378
|
+
closed = true;
|
|
379
|
+
logResolve?.();
|
|
380
|
+
reject(err);
|
|
381
|
+
});
|
|
382
|
+
child.on("close", (code) => {
|
|
383
|
+
processes.delete(commandId);
|
|
384
|
+
closed = true;
|
|
385
|
+
logResolve?.();
|
|
386
|
+
resolve({ stdout, stderr, exitCode: code ?? 0 });
|
|
387
|
+
});
|
|
388
|
+
});
|
|
389
|
+
async function* logs() {
|
|
390
|
+
while (!closed || logQueue.length > 0) {
|
|
391
|
+
const entry = logQueue.shift();
|
|
392
|
+
if (entry) {
|
|
393
|
+
yield entry;
|
|
394
|
+
} else if (!closed) {
|
|
395
|
+
await new Promise((resolve) => {
|
|
396
|
+
logResolve = resolve;
|
|
397
|
+
});
|
|
398
|
+
logResolve = null;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
return { commandId, logs, result };
|
|
403
|
+
},
|
|
404
|
+
catch: (e) => new SandboxError({ reason: String(e), cause: e })
|
|
405
|
+
});
|
|
406
|
+
},
|
|
407
|
+
getDomain: (port) => {
|
|
408
|
+
return Promise.resolve(`http://localhost:${port}`);
|
|
409
|
+
},
|
|
410
|
+
kill: async ({ commandId, storage: storage2 }) => {
|
|
411
|
+
const child = processes.get(commandId);
|
|
412
|
+
if (!child) {
|
|
413
|
+
return new SandboxError({
|
|
414
|
+
reason: `Command ${commandId} not found or already finished`
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
child.kill("SIGTERM");
|
|
418
|
+
const cmd = await storage2.command.get(commandId);
|
|
419
|
+
if (cmd instanceof Error) {
|
|
420
|
+
return new SandboxError({ reason: cmd.message, cause: cmd });
|
|
421
|
+
}
|
|
422
|
+
if (cmd && cmd.status === "running") {
|
|
423
|
+
const result = await storage2.command.set({
|
|
424
|
+
...cmd,
|
|
425
|
+
status: "killed"
|
|
426
|
+
});
|
|
427
|
+
if (result instanceof Error) {
|
|
428
|
+
return new SandboxError({ reason: result.message, cause: result });
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
},
|
|
432
|
+
readFile: async ({ path: filePath }) => {
|
|
433
|
+
try {
|
|
434
|
+
await ensureSandbox(sandboxName);
|
|
435
|
+
const result = await execDocker(
|
|
436
|
+
[
|
|
437
|
+
"exec",
|
|
438
|
+
sandboxName,
|
|
439
|
+
"bash",
|
|
440
|
+
"-c",
|
|
441
|
+
`base64 '${filePath.replace(/'/g, "'\\''")}'`
|
|
442
|
+
],
|
|
443
|
+
{ timeoutMs: 3e4 }
|
|
444
|
+
);
|
|
445
|
+
if (result.exitCode !== 0) {
|
|
446
|
+
if (result.stderr.includes("No such file") || result.stderr.includes("ENOENT")) {
|
|
447
|
+
return null;
|
|
448
|
+
}
|
|
449
|
+
return new SandboxError({
|
|
450
|
+
reason: `readFile failed: ${result.stderr}`
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
return Buffer.from(result.stdout.trim(), "base64");
|
|
454
|
+
} catch (e) {
|
|
455
|
+
return new SandboxError({ reason: String(e), cause: e });
|
|
456
|
+
}
|
|
457
|
+
},
|
|
458
|
+
writeFiles: (opts) => writeFiles({ sandbox, ...opts }),
|
|
459
|
+
updateNetworkPolicy: () => Promise.resolve(
|
|
460
|
+
new SandboxError({
|
|
461
|
+
reason: "updateNetworkPolicy is not yet available for Docker sandboxes"
|
|
462
|
+
})
|
|
463
|
+
),
|
|
464
|
+
lifecycle: {
|
|
465
|
+
start: () => {
|
|
466
|
+
if (startPromise) {
|
|
467
|
+
return startPromise;
|
|
468
|
+
}
|
|
469
|
+
startPromise = (async () => {
|
|
470
|
+
await ensureSandbox(sandboxName);
|
|
471
|
+
if (!setup && sandboxRecord.setupKey) {
|
|
472
|
+
await pollForSetupCompletion({
|
|
473
|
+
storage,
|
|
474
|
+
sandboxId: sandboxRecord.id,
|
|
475
|
+
setupKey: sandboxRecord.setupKey
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
if (setup) {
|
|
479
|
+
const existing = await storage.setup.get(setup.key);
|
|
480
|
+
if (existing instanceof Error || !existing) {
|
|
481
|
+
try {
|
|
482
|
+
await setup.run(sandbox);
|
|
483
|
+
await storage.setup.set({
|
|
484
|
+
key: setup.key,
|
|
485
|
+
snapshotId: null,
|
|
486
|
+
createdAt: Date.now(),
|
|
487
|
+
lastUsedAt: null,
|
|
488
|
+
acquiringLockId: null,
|
|
489
|
+
acquiringLockAt: null
|
|
490
|
+
});
|
|
491
|
+
await markSetupComplete({
|
|
492
|
+
storage,
|
|
493
|
+
sandboxId: sandboxRecord.id,
|
|
494
|
+
setupKey: setup.key
|
|
495
|
+
});
|
|
496
|
+
} catch (e) {
|
|
497
|
+
await resetSetupState({
|
|
498
|
+
storage,
|
|
499
|
+
sandboxId: sandboxRecord.id,
|
|
500
|
+
setupKey: setup.key
|
|
501
|
+
});
|
|
502
|
+
throw e;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
if (onRestart) {
|
|
507
|
+
await onRestart(sandbox);
|
|
508
|
+
}
|
|
509
|
+
return void 0;
|
|
510
|
+
})().catch((e) => {
|
|
511
|
+
startPromise = null;
|
|
512
|
+
throw e;
|
|
513
|
+
});
|
|
514
|
+
return startPromise;
|
|
515
|
+
},
|
|
516
|
+
snapshot: () => Promise.resolve(
|
|
517
|
+
new SandboxError({
|
|
518
|
+
reason: "snapshot is not supported for Docker sandboxes"
|
|
519
|
+
})
|
|
520
|
+
),
|
|
521
|
+
stop: async () => {
|
|
522
|
+
try {
|
|
523
|
+
await execDocker(["stop", sandboxName], { timeoutMs: 3e4 });
|
|
524
|
+
activeSandboxes.delete(sandboxName);
|
|
525
|
+
ensurePromises.delete(sandboxName);
|
|
526
|
+
return void 0;
|
|
527
|
+
} catch (e) {
|
|
528
|
+
return new SandboxError({ reason: String(e), cause: e });
|
|
529
|
+
}
|
|
530
|
+
},
|
|
531
|
+
getStatus: () => Promise.resolve(
|
|
532
|
+
new SandboxError({
|
|
533
|
+
reason: "getStatus is not supported for Docker sandboxes"
|
|
534
|
+
})
|
|
535
|
+
),
|
|
536
|
+
getCreatedAt: () => Promise.resolve(
|
|
537
|
+
new SandboxError({
|
|
538
|
+
reason: "getCreatedAt is not supported for Docker sandboxes"
|
|
539
|
+
})
|
|
540
|
+
),
|
|
541
|
+
getRemainingTimeout: () => Promise.resolve(
|
|
542
|
+
new SandboxError({
|
|
543
|
+
reason: "getRemainingTimeout is not supported for Docker sandboxes"
|
|
544
|
+
})
|
|
545
|
+
)
|
|
546
|
+
},
|
|
547
|
+
tag: {
|
|
548
|
+
list: async () => {
|
|
549
|
+
const sandboxRecord2 = await storage.sandbox.get(sandbox.id);
|
|
550
|
+
if (sandboxRecord2 instanceof Error) {
|
|
551
|
+
return sandboxRecord2;
|
|
552
|
+
}
|
|
553
|
+
return sandboxRecord2.tags ?? {};
|
|
554
|
+
},
|
|
555
|
+
get: async (key) => {
|
|
556
|
+
const sandboxRecord2 = await storage.sandbox.get(sandbox.id);
|
|
557
|
+
if (sandboxRecord2 instanceof Error) {
|
|
558
|
+
return sandboxRecord2;
|
|
559
|
+
}
|
|
560
|
+
return sandboxRecord2.tags?.[key];
|
|
561
|
+
},
|
|
562
|
+
set: async (key, value) => {
|
|
563
|
+
const result = await storage.sandbox.tag.set({
|
|
564
|
+
sandboxId: sandbox.id,
|
|
565
|
+
tags: { [key]: value }
|
|
566
|
+
});
|
|
567
|
+
if (result instanceof Error) {
|
|
568
|
+
return result;
|
|
569
|
+
}
|
|
570
|
+
return void 0;
|
|
571
|
+
},
|
|
572
|
+
setMany: async (tags) => {
|
|
573
|
+
const result = await storage.sandbox.tag.set({
|
|
574
|
+
sandboxId: sandbox.id,
|
|
575
|
+
tags
|
|
576
|
+
});
|
|
577
|
+
if (result instanceof Error) {
|
|
578
|
+
return result;
|
|
579
|
+
}
|
|
580
|
+
return void 0;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
};
|
|
584
|
+
return sandbox;
|
|
585
|
+
};
|
|
586
|
+
|
|
587
|
+
export {
|
|
588
|
+
pollForSetupCompletion,
|
|
589
|
+
markSetupComplete,
|
|
590
|
+
resetSetupState,
|
|
591
|
+
writeFiles,
|
|
592
|
+
isDockerSandboxAvailable,
|
|
593
|
+
dockerSandbox
|
|
594
|
+
};
|
|
595
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL3NhbmRib3gvYmluZGluZ3MvZG9ja2VyLnRzIiwgIi4uL3NyYy9zYW5kYm94L3NldHVwLXBvbGwudHMiLCAiLi4vc3JjL3NhbmRib3gvd3JpdGUtZmlsZXMudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCB0eXBlIHsgQ2hpbGRQcm9jZXNzIH0gZnJvbSBcIm5vZGU6Y2hpbGRfcHJvY2Vzc1wiO1xuaW1wb3J0IHsgZXhlY1N5bmMsIHNwYXduIH0gZnJvbSBcIm5vZGU6Y2hpbGRfcHJvY2Vzc1wiO1xuaW1wb3J0ICogYXMgZnMgZnJvbSBcIm5vZGU6ZnMvcHJvbWlzZXNcIjtcbmltcG9ydCAqIGFzIG9zIGZyb20gXCJub2RlOm9zXCI7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCAqIGFzIGVycm9yZSBmcm9tIFwiZXJyb3JlXCI7XG5pbXBvcnQgeyB1bGlkIH0gZnJvbSBcInVsaWRcIjtcbmltcG9ydCB7IFNhbmRib3hFcnJvciB9IGZyb20gXCIuLi8uLi9lcnJvcnNcIjtcbmltcG9ydCB0eXBlIHsgVGFnc1NjaGVtYSB9IGZyb20gXCIuLi8uLi9pbmRleFwiO1xuaW1wb3J0IHR5cGUgeyBTYW5kYm94UmVjb3JkLCBTdG9yYWdlIH0gZnJvbSBcIi4uLy4uL3N0b3JhZ2VcIjtcbmltcG9ydCB7XG4gIG1hcmtTZXR1cENvbXBsZXRlLFxuICBwb2xsRm9yU2V0dXBDb21wbGV0aW9uLFxuICByZXNldFNldHVwU3RhdGUsXG59IGZyb20gXCIuLi9zZXR1cC1wb2xsXCI7XG5pbXBvcnQgdHlwZSB7IExvZ0VudHJ5LCBPblJlc3RhcnQsIFNhbmRib3gsIFNhbmRib3hTZXR1cCB9IGZyb20gXCIuLi90eXBlc1wiO1xuaW1wb3J0IHsgd3JpdGVGaWxlcyB9IGZyb20gXCIuLi93cml0ZS1maWxlc1wiO1xuXG4vKipcbiAqIENoZWNrIHdoZXRoZXIgYGRvY2tlciBzYW5kYm94YCBDTEkgaXMgYXZhaWxhYmxlLlxuICogQ2FjaGVzIHRoZSByZXN1bHQgZm9yIHRoZSBsaWZldGltZSBvZiB0aGUgcHJvY2Vzcy5cbiAqL1xubGV0IGRvY2tlckF2YWlsYWJsZTogYm9vbGVhbiB8IG51bGwgPSBudWxsO1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGlzRG9ja2VyU2FuZGJveEF2YWlsYWJsZSgpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgaWYgKGRvY2tlckF2YWlsYWJsZSAhPT0gbnVsbCkge1xuICAgIHJldHVybiBkb2NrZXJBdmFpbGFibGU7XG4gIH1cbiAgdHJ5IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBleGVjRG9ja2VyKFtcInZlcnNpb25cIl0sIHsgdGltZW91dE1zOiA1XzAwMCB9KTtcbiAgICBkb2NrZXJBdmFpbGFibGUgPSByZXN1bHQuZXhpdENvZGUgPT09IDA7XG4gIH0gY2F0Y2gge1xuICAgIGRvY2tlckF2YWlsYWJsZSA9IGZhbHNlO1xuICB9XG4gIHJldHVybiBkb2NrZXJBdmFpbGFibGU7XG59XG5cbi8qKlxuICogUnVuIGEgYGRvY2tlciBzYW5kYm94YCBDTEkgY29tbWFuZCBhbmQgcmV0dXJuIGl0cyBvdXRwdXQuXG4gKi9cbmZ1bmN0aW9uIGV4ZWNEb2NrZXIoXG4gIGFyZ3M6IHN0cmluZ1tdLFxuICBvcHRzPzogeyB0aW1lb3V0TXM/OiBudW1iZXI7IHNpZ25hbD86IEFib3J0U2lnbmFsIH1cbik6IFByb21pc2U8eyBzdGRvdXQ6IHN0cmluZzsgc3RkZXJyOiBzdHJpbmc7IGV4aXRDb2RlOiBudW1iZXIgfT4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIGNvbnN0IGNoaWxkID0gc3Bhd24oXCJkb2NrZXJcIiwgW1wic2FuZGJveFwiLCAuLi5hcmdzXSwge1xuICAgICAgc2lnbmFsOiBvcHRzPy5zaWduYWwsXG4gICAgfSk7XG5cbiAgICBsZXQgc3Rkb3V0ID0gXCJcIjtcbiAgICBsZXQgc3RkZXJyID0gXCJcIjtcblxuICAgIGNoaWxkLnN0ZG91dC5vbihcImRhdGFcIiwgKGRhdGE6IEJ1ZmZlcikgPT4ge1xuICAgICAgc3Rkb3V0ICs9IGRhdGEudG9TdHJpbmcoKTtcbiAgICB9KTtcbiAgICBjaGlsZC5zdGRlcnIub24oXCJkYXRhXCIsIChkYXRhOiBCdWZmZXIpID0+IHtcbiAgICAgIHN0ZGVyciArPSBkYXRhLnRvU3RyaW5nKCk7XG4gICAgfSk7XG5cbiAgICBjb25zdCB0aW1lb3V0SWQgPSBvcHRzPy50aW1lb3V0TXNcbiAgICAgID8gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgY2hpbGQua2lsbChcIlNJR1RFUk1cIik7XG4gICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihgZG9ja2VyIHNhbmRib3ggJHthcmdzWzBdfSB0aW1lZCBvdXRgKSk7XG4gICAgICAgIH0sIG9wdHMudGltZW91dE1zKVxuICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICBjaGlsZC5vbihcImVycm9yXCIsIChlcnIpID0+IHtcbiAgICAgIGlmICh0aW1lb3V0SWQpIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXRJZCk7XG4gICAgICB9XG4gICAgICByZWplY3QoZXJyKTtcbiAgICB9KTtcblxuICAgIGNoaWxkLm9uKFwiY2xvc2VcIiwgKGNvZGUpID0+IHtcbiAgICAgIGlmICh0aW1lb3V0SWQpIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXRJZCk7XG4gICAgICB9XG4gICAgICByZXNvbHZlKHsgc3Rkb3V0LCBzdGRlcnIsIGV4aXRDb2RlOiBjb2RlID8/IDAgfSk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG4vKipcbiAqIFRyYWNrIHdoaWNoIHNhbmRib3hlcyBoYXZlIGJlZW4gdmVyaWZpZWQgdG8gZXhpc3QgaW4gdGhpcyBwcm9jZXNzLlxuICogTWFwcyBzYW5kYm94IG5hbWUgLT4gUHJvbWlzZSBzbyBjb25jdXJyZW50IGNhbGxlcnMgd2FpdCBvbiB0aGUgc2FtZSBjaGVjay5cbiAqL1xuY29uc3QgZW5zdXJlUHJvbWlzZXMgPSBuZXcgTWFwPHN0cmluZywgUHJvbWlzZTx2b2lkPj4oKTtcblxuLyoqXG4gKiBTYW5kYm94ZXMgdGhhdCB0aGlzIHByb2Nlc3MgaGFzIHVzZWQuIFN0b3BwZWQgb24gcHJvY2VzcyBleGl0LlxuICovXG5jb25zdCBhY3RpdmVTYW5kYm94ZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcblxubGV0IGNsZWFudXBSZWdpc3RlcmVkID0gZmFsc2U7XG5mdW5jdGlvbiByZWdpc3RlckNsZWFudXAoKSB7XG4gIGlmIChjbGVhbnVwUmVnaXN0ZXJlZCkge1xuICAgIHJldHVybjtcbiAgfVxuICBjbGVhbnVwUmVnaXN0ZXJlZCA9IHRydWU7XG5cbiAgY29uc3QgY2xlYW51cCA9ICgpID0+IHtcbiAgICBmb3IgKGNvbnN0IG5hbWUgb2YgQXJyYXkuZnJvbShhY3RpdmVTYW5kYm94ZXMpKSB7XG4gICAgICB0cnkge1xuICAgICAgICAvLyBleGVjU3luYyBpcyB0aGUgb25seSBvcHRpb24gaW4gZXhpdC9zaWduYWwgaGFuZGxlcnNcbiAgICAgICAgZXhlY1N5bmMoYGRvY2tlciBzYW5kYm94IHN0b3AgJHtuYW1lfWAsIHtcbiAgICAgICAgICB0aW1lb3V0OiAxMF8wMDAsXG4gICAgICAgICAgc3RkaW86IFwicGlwZVwiLFxuICAgICAgICB9KTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBCZXN0LWVmZm9ydCBcdTIwMTQgc2FuZGJveCBtYXkgYWxyZWFkeSBiZSBzdG9wcGVkXG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIHByb2Nlc3Mub24oXCJleGl0XCIsIGNsZWFudXApO1xuICBwcm9jZXNzLm9uKFwiU0lHSU5UXCIsICgpID0+IHtcbiAgICBjbGVhbnVwKCk7XG4gICAgcHJvY2Vzcy5leGl0KDEzMCk7XG4gIH0pO1xuICBwcm9jZXNzLm9uKFwiU0lHVEVSTVwiLCAoKSA9PiB7XG4gICAgY2xlYW51cCgpO1xuICAgIHByb2Nlc3MuZXhpdCgxNDMpO1xuICB9KTtcbn1cblxuLyoqXG4gKiBFbnN1cmUgYSBEb2NrZXIgc2FuZGJveCBleGlzdHMgZm9yIHRoZSBnaXZlbiBJRC5cbiAqIElmIGl0IGFscmVhZHkgZXhpc3RzIChmcm9tIGEgcHJldmlvdXMgcHJvY2VzcyksIHJldXNlcyBpdC5cbiAqIElmIGl0IGRvZXNuJ3QgZXhpc3QsIGNyZWF0ZXMgaXQuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGVuc3VyZVNhbmRib3goc2FuZGJveElkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgZXhpc3RpbmcgPSBlbnN1cmVQcm9taXNlcy5nZXQoc2FuZGJveElkKTtcbiAgaWYgKGV4aXN0aW5nKSB7XG4gICAgcmV0dXJuIGV4aXN0aW5nO1xuICB9XG5cbiAgY29uc3QgcHJvbWlzZSA9IChhc3luYyAoKSA9PiB7XG4gICAgLy8gQ2hlY2sgaWYgc2FuZGJveCBhbHJlYWR5IGV4aXN0cyB2aWEgbHMgLXEgKHN1cnZpdmVzIHByb2Nlc3MgcmVzdGFydHMpXG4gICAgY29uc3QgbHMgPSBhd2FpdCBleGVjRG9ja2VyKFtcImxzXCIsIFwiLXFcIl0sIHsgdGltZW91dE1zOiAxMF8wMDAgfSk7XG4gICAgY29uc3QgZXhpc3RpbmdOYW1lcyA9XG4gICAgICBscy5leGl0Q29kZSA9PT0gMFxuICAgICAgICA/IGxzLnN0ZG91dFxuICAgICAgICAgICAgLnNwbGl0KFwiXFxuXCIpXG4gICAgICAgICAgICAubWFwKChzKSA9PiBzLnRyaW0oKSlcbiAgICAgICAgICAgIC5maWx0ZXIoQm9vbGVhbilcbiAgICAgICAgOiBbXTtcblxuICAgIGlmIChleGlzdGluZ05hbWVzLmluY2x1ZGVzKHNhbmRib3hJZCkpIHtcbiAgICAgIGFjdGl2ZVNhbmRib3hlcy5hZGQoc2FuZGJveElkKTtcbiAgICAgIHJlZ2lzdGVyQ2xlYW51cCgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIENyZWF0ZSBhIHRlbXAgd29ya3NwYWNlIGRpcmVjdG9yeSBvbiB0aGUgaG9zdCB0byBtb3VudCBpbnRvIHRoZSBzYW5kYm94LlxuICAgIC8vIEVhY2ggc2FuZGJveCBnZXRzIGl0cyBvd24gZGlyZWN0b3J5IGZvciBmaWxlc3lzdGVtIGlzb2xhdGlvbi5cbiAgICBjb25zdCB3b3Jrc3BhY2VEaXIgPSBwYXRoLmpvaW4oXG4gICAgICBvcy50bXBkaXIoKSxcbiAgICAgIFwiYWdlbnQtZG9ja2VyLXNhbmRib3hcIixcbiAgICAgIHNhbmRib3hJZFxuICAgICk7XG4gICAgYXdhaXQgZnMubWtkaXIod29ya3NwYWNlRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcblxuICAgIGNvbnN0IGNyZWF0ZSA9IGF3YWl0IGV4ZWNEb2NrZXIoXG4gICAgICBbXCJjcmVhdGVcIiwgXCItLW5hbWVcIiwgc2FuZGJveElkLCBcInNoZWxsXCIsIHdvcmtzcGFjZURpcl0sXG4gICAgICB7IHRpbWVvdXRNczogNjBfMDAwIH1cbiAgICApO1xuXG4gICAgaWYgKGNyZWF0ZS5leGl0Q29kZSAhPT0gMCkge1xuICAgICAgLy8gQW5vdGhlciBwcm9jZXNzIG1heSBoYXZlIGNyZWF0ZWQgaXQgYmV0d2VlbiBpbnNwZWN0IGFuZCBjcmVhdGVcbiAgICAgIGlmIChjcmVhdGUuc3RkZXJyLmluY2x1ZGVzKFwiYWxyZWFkeSBleGlzdHNcIikpIHtcbiAgICAgICAgYWN0aXZlU2FuZGJveGVzLmFkZChzYW5kYm94SWQpO1xuICAgICAgICByZWdpc3RlckNsZWFudXAoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgRmFpbGVkIHRvIGNyZWF0ZSBkb2NrZXIgc2FuZGJveCBcIiR7c2FuZGJveElkfVwiOiAke2NyZWF0ZS5zdGRlcnJ9YFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBhY3RpdmVTYW5kYm94ZXMuYWRkKHNhbmRib3hJZCk7XG4gICAgcmVnaXN0ZXJDbGVhbnVwKCk7XG4gIH0pKCk7XG5cbiAgZW5zdXJlUHJvbWlzZXMuc2V0KHNhbmRib3hJZCwgcHJvbWlzZSk7XG5cbiAgdHJ5IHtcbiAgICBhd2FpdCBwcm9taXNlO1xuICB9IGNhdGNoIChlKSB7XG4gICAgLy8gQWxsb3cgcmV0cnkgb24gZmFpbHVyZVxuICAgIGVuc3VyZVByb21pc2VzLmRlbGV0ZShzYW5kYm94SWQpO1xuICAgIHRocm93IGU7XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IGRvY2tlclNhbmRib3ggPSA8VFRhZ3MgZXh0ZW5kcyBUYWdzU2NoZW1hID0gVGFnc1NjaGVtYT4oe1xuICBzYW5kYm94UmVjb3JkLFxuICBzdG9yYWdlLFxuICBzZXR1cCxcbiAgb25SZXN0YXJ0LFxufToge1xuICBzYW5kYm94UmVjb3JkOiBTYW5kYm94UmVjb3JkICYgeyBjb25maWc6IHsgdHlwZTogXCJkb2NrZXJcIiB9IH07XG4gIHN0b3JhZ2U6IFN0b3JhZ2U7XG4gIHNldHVwPzogU2FuZGJveFNldHVwO1xuICBvblJlc3RhcnQ/OiBPblJlc3RhcnQ7XG59KTogU2FuZGJveDxUVGFncz4gPT4ge1xuICBjb25zdCBzYW5kYm94TmFtZSA9IHNhbmRib3hSZWNvcmQuaWQ7XG4gIGNvbnN0IGN3ZCA9IHNhbmRib3hSZWNvcmQuY29uZmlnLmN3ZCA/PyBcIi9ob21lL2FnZW50L3dvcmtzcGFjZVwiO1xuICBjb25zdCBwcm9jZXNzZXMgPSBuZXcgTWFwPHN0cmluZywgQ2hpbGRQcm9jZXNzPigpO1xuXG4gIGxldCBzdGFydFByb21pc2U6IFByb21pc2U8U2FuZGJveEVycm9yIHwgdW5kZWZpbmVkPiB8IG51bGwgPSBudWxsO1xuXG4gIGNvbnN0IHNhbmRib3g6IFNhbmRib3g8VFRhZ3M+ID0ge1xuICAgIGlkOiBzYW5kYm94UmVjb3JkLmlkLFxuICAgIGNvbmZpZzogc2FuZGJveFJlY29yZC5jb25maWcsXG4gICAgY3dkLFxuXG4gICAgZXhlYzogKHsgY29tbWFuZCwgYXJncywgY3dkLCBlbnYsIHNpZ25hbCwgc3VkbyB9KSA9PiB7XG4gICAgICByZXR1cm4gZXJyb3JlLnRyeUFzeW5jKHtcbiAgICAgICAgdHJ5OiBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgYXdhaXQgZW5zdXJlU2FuZGJveChzYW5kYm94TmFtZSk7XG5cbiAgICAgICAgICBjb25zdCBjb21tYW5kSWQgPSBgY29tbWFuZF8ke3VsaWQoKX1gO1xuICAgICAgICAgIGNvbnN0IGVudkZsYWdzID1cbiAgICAgICAgICAgIGVudiA9PT0gdW5kZWZpbmVkXG4gICAgICAgICAgICAgID8gW11cbiAgICAgICAgICAgICAgOiBPYmplY3QuZW50cmllcyhlbnYpLmZsYXRNYXAoKFtrLCB2XSkgPT4gW1wiLWVcIiwgYCR7a309JHt2fWBdKTtcbiAgICAgICAgICBjb25zdCBjd2RGbGFncyA9IGN3ZCA/IFtcIi13XCIsIGN3ZF0gOiBbXTtcbiAgICAgICAgICBjb25zdCBiYXNlQ21kID0gc3Vkb1xuICAgICAgICAgICAgPyBbXCJzdWRvXCIsIGNvbW1hbmQsIC4uLihhcmdzID8/IFtdKV1cbiAgICAgICAgICAgIDogYXJnc1xuICAgICAgICAgICAgICA/IFtjb21tYW5kLCAuLi5hcmdzXVxuICAgICAgICAgICAgICA6IFtjb21tYW5kXTtcbiAgICAgICAgICBjb25zdCBmdWxsQ21kID0gYmFzZUNtZDtcblxuICAgICAgICAgIGNvbnN0IGNoaWxkID0gc3Bhd24oXG4gICAgICAgICAgICBcImRvY2tlclwiLFxuICAgICAgICAgICAgW1xuICAgICAgICAgICAgICBcInNhbmRib3hcIixcbiAgICAgICAgICAgICAgXCJleGVjXCIsXG4gICAgICAgICAgICAgIC4uLmVudkZsYWdzLFxuICAgICAgICAgICAgICAuLi5jd2RGbGFncyxcbiAgICAgICAgICAgICAgc2FuZGJveE5hbWUsXG4gICAgICAgICAgICAgIC4uLmZ1bGxDbWQsXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgeyBzaWduYWwgfVxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBwcm9jZXNzZXMuc2V0KGNvbW1hbmRJZCwgY2hpbGQpO1xuXG4gICAgICAgICAgbGV0IHN0ZG91dCA9IFwiXCI7XG4gICAgICAgICAgbGV0IHN0ZGVyciA9IFwiXCI7XG4gICAgICAgICAgY29uc3QgbG9nUXVldWU6IExvZ0VudHJ5W10gPSBbXTtcbiAgICAgICAgICBsZXQgbG9nUmVzb2x2ZTogKCgpID0+IHZvaWQpIHwgbnVsbCA9IG51bGw7XG4gICAgICAgICAgbGV0IGNsb3NlZCA9IGZhbHNlO1xuXG4gICAgICAgICAgY2hpbGQuc3Rkb3V0Lm9uKFwiZGF0YVwiLCAoZGF0YTogc3RyaW5nIHwgQnVmZmVyKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBzdHIgPSBTdHJpbmcoZGF0YSk7XG4gICAgICAgICAgICBzdGRvdXQgKz0gc3RyO1xuICAgICAgICAgICAgbG9nUXVldWUucHVzaCh7IHN0cmVhbTogXCJzdGRvdXRcIiwgZGF0YTogc3RyIH0pO1xuICAgICAgICAgICAgbG9nUmVzb2x2ZT8uKCk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBjaGlsZC5zdGRlcnIub24oXCJkYXRhXCIsIChkYXRhOiBzdHJpbmcgfCBCdWZmZXIpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN0ciA9IFN0cmluZyhkYXRhKTtcbiAgICAgICAgICAgIHN0ZGVyciArPSBzdHI7XG4gICAgICAgICAgICBsb2dRdWV1ZS5wdXNoKHsgc3RyZWFtOiBcInN0ZGVyclwiLCBkYXRhOiBzdHIgfSk7XG4gICAgICAgICAgICBsb2dSZXNvbHZlPy4oKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBQcm9taXNlPHtcbiAgICAgICAgICAgIHN0ZG91dDogc3RyaW5nO1xuICAgICAgICAgICAgc3RkZXJyOiBzdHJpbmc7XG4gICAgICAgICAgICBleGl0Q29kZTogbnVtYmVyO1xuICAgICAgICAgIH0+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNoaWxkLm9uKFwiZXJyb3JcIiwgKGVycikgPT4ge1xuICAgICAgICAgICAgICBwcm9jZXNzZXMuZGVsZXRlKGNvbW1hbmRJZCk7XG4gICAgICAgICAgICAgIGNsb3NlZCA9IHRydWU7XG4gICAgICAgICAgICAgIGxvZ1Jlc29sdmU/LigpO1xuICAgICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBjaGlsZC5vbihcImNsb3NlXCIsIChjb2RlOiBudW1iZXIgfCBudWxsKSA9PiB7XG4gICAgICAgICAgICAgIHByb2Nlc3Nlcy5kZWxldGUoY29tbWFuZElkKTtcbiAgICAgICAgICAgICAgY2xvc2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgbG9nUmVzb2x2ZT8uKCk7XG4gICAgICAgICAgICAgIHJlc29sdmUoeyBzdGRvdXQsIHN0ZGVyciwgZXhpdENvZGU6IGNvZGUgPz8gMCB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgYXN5bmMgZnVuY3Rpb24qIGxvZ3MoKTogQXN5bmNJdGVyYWJsZTxMb2dFbnRyeT4ge1xuICAgICAgICAgICAgd2hpbGUgKCFjbG9zZWQgfHwgbG9nUXVldWUubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICBjb25zdCBlbnRyeSA9IGxvZ1F1ZXVlLnNoaWZ0KCk7XG4gICAgICAgICAgICAgIGlmIChlbnRyeSkge1xuICAgICAgICAgICAgICAgIHlpZWxkIGVudHJ5O1xuICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFjbG9zZWQpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgbG9nUmVzb2x2ZSA9IHJlc29sdmU7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgbG9nUmVzb2x2ZSA9IG51bGw7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4geyBjb21tYW5kSWQsIGxvZ3MsIHJlc3VsdCB9O1xuICAgICAgICB9LFxuICAgICAgICBjYXRjaDogKGU6IHVua25vd24pID0+XG4gICAgICAgICAgbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogU3RyaW5nKGUpLCBjYXVzZTogZSB9KSxcbiAgICAgIH0pO1xuICAgIH0sXG5cbiAgICBnZXREb21haW46IChwb3J0KSA9PiB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGBodHRwOi8vbG9jYWxob3N0OiR7cG9ydH1gKTtcbiAgICB9LFxuXG4gICAga2lsbDogYXN5bmMgKHsgY29tbWFuZElkLCBzdG9yYWdlIH0pID0+IHtcbiAgICAgIGNvbnN0IGNoaWxkID0gcHJvY2Vzc2VzLmdldChjb21tYW5kSWQpO1xuICAgICAgaWYgKCFjaGlsZCkge1xuICAgICAgICByZXR1cm4gbmV3IFNhbmRib3hFcnJvcih7XG4gICAgICAgICAgcmVhc29uOiBgQ29tbWFuZCAke2NvbW1hbmRJZH0gbm90IGZvdW5kIG9yIGFscmVhZHkgZmluaXNoZWRgLFxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgY2hpbGQua2lsbChcIlNJR1RFUk1cIik7XG5cbiAgICAgIGNvbnN0IGNtZCA9IGF3YWl0IHN0b3JhZ2UuY29tbWFuZC5nZXQoY29tbWFuZElkKTtcbiAgICAgIGlmIChjbWQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICByZXR1cm4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogY21kLm1lc3NhZ2UsIGNhdXNlOiBjbWQgfSk7XG4gICAgICB9XG4gICAgICBpZiAoY21kICYmIGNtZC5zdGF0dXMgPT09IFwicnVubmluZ1wiKSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHN0b3JhZ2UuY29tbWFuZC5zZXQoe1xuICAgICAgICAgIC4uLmNtZCxcbiAgICAgICAgICBzdGF0dXM6IFwia2lsbGVkXCIsXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICByZXR1cm4gbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogcmVzdWx0Lm1lc3NhZ2UsIGNhdXNlOiByZXN1bHQgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LFxuXG4gICAgcmVhZEZpbGU6IGFzeW5jICh7IHBhdGg6IGZpbGVQYXRoIH0pID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGVuc3VyZVNhbmRib3goc2FuZGJveE5hbWUpO1xuXG4gICAgICAgIC8vIFVzZSBkb2NrZXIgc2FuZGJveCBleGVjIHRvIGNhdCB0aGUgZmlsZSBhbmQgZ2V0IGl0cyBiYXNlNjQgY29udGVudFxuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBleGVjRG9ja2VyKFxuICAgICAgICAgIFtcbiAgICAgICAgICAgIFwiZXhlY1wiLFxuICAgICAgICAgICAgc2FuZGJveE5hbWUsXG4gICAgICAgICAgICBcImJhc2hcIixcbiAgICAgICAgICAgIFwiLWNcIixcbiAgICAgICAgICAgIGBiYXNlNjQgJyR7ZmlsZVBhdGgucmVwbGFjZSgvJy9nLCBcIidcXFxcJydcIil9J2AsXG4gICAgICAgICAgXSxcbiAgICAgICAgICB7IHRpbWVvdXRNczogMzBfMDAwIH1cbiAgICAgICAgKTtcblxuICAgICAgICBpZiAocmVzdWx0LmV4aXRDb2RlICE9PSAwKSB7XG4gICAgICAgICAgLy8gRmlsZSBub3QgZm91bmRcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICByZXN1bHQuc3RkZXJyLmluY2x1ZGVzKFwiTm8gc3VjaCBmaWxlXCIpIHx8XG4gICAgICAgICAgICByZXN1bHQuc3RkZXJyLmluY2x1ZGVzKFwiRU5PRU5UXCIpXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG5ldyBTYW5kYm94RXJyb3Ioe1xuICAgICAgICAgICAgcmVhc29uOiBgcmVhZEZpbGUgZmFpbGVkOiAke3Jlc3VsdC5zdGRlcnJ9YCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBCdWZmZXIuZnJvbShyZXN1bHQuc3Rkb3V0LnRyaW0oKSwgXCJiYXNlNjRcIik7XG4gICAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICAgIHJldHVybiBuZXcgU2FuZGJveEVycm9yKHsgcmVhc29uOiBTdHJpbmcoZSksIGNhdXNlOiBlIH0pO1xuICAgICAgfVxuICAgIH0sXG5cbiAgICB3cml0ZUZpbGVzOiAob3B0cykgPT4gd3JpdGVGaWxlcyh7IHNhbmRib3gsIC4uLm9wdHMgfSksXG5cbiAgICB1cGRhdGVOZXR3b3JrUG9saWN5OiAoKSA9PlxuICAgICAgUHJvbWlzZS5yZXNvbHZlKFxuICAgICAgICBuZXcgU2FuZGJveEVycm9yKHtcbiAgICAgICAgICByZWFzb246XG4gICAgICAgICAgICBcInVwZGF0ZU5ldHdvcmtQb2xpY3kgaXMgbm90IHlldCBhdmFpbGFibGUgZm9yIERvY2tlciBzYW5kYm94ZXNcIixcbiAgICAgICAgfSlcbiAgICAgICksXG5cbiAgICBsaWZlY3ljbGU6IHtcbiAgICAgIHN0YXJ0OiAoKSA9PiB7XG4gICAgICAgIGlmIChzdGFydFByb21pc2UpIHtcbiAgICAgICAgICByZXR1cm4gc3RhcnRQcm9taXNlO1xuICAgICAgICB9XG4gICAgICAgIHN0YXJ0UHJvbWlzZSA9IChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgYXdhaXQgZW5zdXJlU2FuZGJveChzYW5kYm94TmFtZSk7XG5cbiAgICAgICAgICBpZiAoIXNldHVwICYmIHNhbmRib3hSZWNvcmQuc2V0dXBLZXkpIHtcbiAgICAgICAgICAgIGF3YWl0IHBvbGxGb3JTZXR1cENvbXBsZXRpb24oe1xuICAgICAgICAgICAgICBzdG9yYWdlLFxuICAgICAgICAgICAgICBzYW5kYm94SWQ6IHNhbmRib3hSZWNvcmQuaWQsXG4gICAgICAgICAgICAgIHNldHVwS2V5OiBzYW5kYm94UmVjb3JkLnNldHVwS2V5LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHNldHVwKSB7XG4gICAgICAgICAgICBjb25zdCBleGlzdGluZyA9IGF3YWl0IHN0b3JhZ2Uuc2V0dXAuZ2V0KHNldHVwLmtleSk7XG4gICAgICAgICAgICBpZiAoZXhpc3RpbmcgaW5zdGFuY2VvZiBFcnJvciB8fCAhZXhpc3RpbmcpIHtcbiAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBhd2FpdCBzZXR1cC5ydW4oc2FuZGJveCk7XG4gICAgICAgICAgICAgICAgYXdhaXQgc3RvcmFnZS5zZXR1cC5zZXQoe1xuICAgICAgICAgICAgICAgICAga2V5OiBzZXR1cC5rZXksXG4gICAgICAgICAgICAgICAgICBzbmFwc2hvdElkOiBudWxsLFxuICAgICAgICAgICAgICAgICAgY3JlYXRlZEF0OiBEYXRlLm5vdygpLFxuICAgICAgICAgICAgICAgICAgbGFzdFVzZWRBdDogbnVsbCxcbiAgICAgICAgICAgICAgICAgIGFjcXVpcmluZ0xvY2tJZDogbnVsbCxcbiAgICAgICAgICAgICAgICAgIGFjcXVpcmluZ0xvY2tBdDogbnVsbCxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBhd2FpdCBtYXJrU2V0dXBDb21wbGV0ZSh7XG4gICAgICAgICAgICAgICAgICBzdG9yYWdlLFxuICAgICAgICAgICAgICAgICAgc2FuZGJveElkOiBzYW5kYm94UmVjb3JkLmlkLFxuICAgICAgICAgICAgICAgICAgc2V0dXBLZXk6IHNldHVwLmtleSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIGF3YWl0IHJlc2V0U2V0dXBTdGF0ZSh7XG4gICAgICAgICAgICAgICAgICBzdG9yYWdlLFxuICAgICAgICAgICAgICAgICAgc2FuZGJveElkOiBzYW5kYm94UmVjb3JkLmlkLFxuICAgICAgICAgICAgICAgICAgc2V0dXBLZXk6IHNldHVwLmtleSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKG9uUmVzdGFydCkge1xuICAgICAgICAgICAgYXdhaXQgb25SZXN0YXJ0KHNhbmRib3gpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB9KSgpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgc3RhcnRQcm9taXNlID0gbnVsbDtcbiAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHN0YXJ0UHJvbWlzZTtcbiAgICAgIH0sXG4gICAgICBzbmFwc2hvdDogKCkgPT5cbiAgICAgICAgUHJvbWlzZS5yZXNvbHZlKFxuICAgICAgICAgIG5ldyBTYW5kYm94RXJyb3Ioe1xuICAgICAgICAgICAgcmVhc29uOiBcInNuYXBzaG90IGlzIG5vdCBzdXBwb3J0ZWQgZm9yIERvY2tlciBzYW5kYm94ZXNcIixcbiAgICAgICAgICB9KVxuICAgICAgICApLFxuICAgICAgc3RvcDogYXN5bmMgKCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IGV4ZWNEb2NrZXIoW1wic3RvcFwiLCBzYW5kYm94TmFtZV0sIHsgdGltZW91dE1zOiAzMF8wMDAgfSk7XG4gICAgICAgICAgYWN0aXZlU2FuZGJveGVzLmRlbGV0ZShzYW5kYm94TmFtZSk7XG4gICAgICAgICAgZW5zdXJlUHJvbWlzZXMuZGVsZXRlKHNhbmRib3hOYW1lKTtcbiAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgcmV0dXJuIG5ldyBTYW5kYm94RXJyb3IoeyByZWFzb246IFN0cmluZyhlKSwgY2F1c2U6IGUgfSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBnZXRTdGF0dXM6ICgpID0+XG4gICAgICAgIFByb21pc2UucmVzb2x2ZShcbiAgICAgICAgICBuZXcgU2FuZGJveEVycm9yKHtcbiAgICAgICAgICAgIHJlYXNvbjogXCJnZXRTdGF0dXMgaXMgbm90IHN1cHBvcnRlZCBmb3IgRG9ja2VyIHNhbmRib3hlc1wiLFxuICAgICAgICAgIH0pXG4gICAgICAgICksXG4gICAgICBnZXRDcmVhdGVkQXQ6ICgpID0+XG4gICAgICAgIFByb21pc2UucmVzb2x2ZShcbiAgICAgICAgICBuZXcgU2FuZGJveEVycm9yKHtcbiAgICAgICAgICAgIHJlYXNvbjogXCJnZXRDcmVhdGVkQXQgaXMgbm90IHN1cHBvcnRlZCBmb3IgRG9ja2VyIHNhbmRib3hlc1wiLFxuICAgICAgICAgIH0pXG4gICAgICAgICksXG4gICAgICBnZXRSZW1haW5pbmdUaW1lb3V0OiAoKSA9PlxuICAgICAgICBQcm9taXNlLnJlc29sdmUoXG4gICAgICAgICAgbmV3IFNhbmRib3hFcnJvcih7XG4gICAgICAgICAgICByZWFzb246IFwiZ2V0UmVtYWluaW5nVGltZW91dCBpcyBub3Qgc3VwcG9ydGVkIGZvciBEb2NrZXIgc2FuZGJveGVzXCIsXG4gICAgICAgICAgfSlcbiAgICAgICAgKSxcbiAgICB9LFxuXG4gICAgdGFnOiB7XG4gICAgICBsaXN0OiBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHNhbmRib3hSZWNvcmQgPSBhd2FpdCBzdG9yYWdlLnNhbmRib3guZ2V0KHNhbmRib3guaWQpO1xuICAgICAgICBpZiAoc2FuZGJveFJlY29yZCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIHNhbmRib3hSZWNvcmQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIChzYW5kYm94UmVjb3JkLnRhZ3MgPz8ge30pIGFzIFRUYWdzO1xuICAgICAgfSxcbiAgICAgIGdldDogYXN5bmMgKGtleTogc3RyaW5nKSA9PiB7XG4gICAgICAgIGNvbnN0IHNhbmRib3hSZWNvcmQgPSBhd2FpdCBzdG9yYWdlLnNhbmRib3guZ2V0KHNhbmRib3guaWQpO1xuICAgICAgICBpZiAoc2FuZGJveFJlY29yZCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIHNhbmRib3hSZWNvcmQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNhbmRib3hSZWNvcmQudGFncz8uW2tleSBhcyBzdHJpbmddIGFzXG4gICAgICAgICAgfCBUVGFnc1t0eXBlb2Yga2V5XVxuICAgICAgICAgIHwgdW5kZWZpbmVkO1xuICAgICAgfSxcbiAgICAgIHNldDogYXN5bmMgKGtleTogc3RyaW5nLCB2YWx1ZTogdW5rbm93bikgPT4ge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzdG9yYWdlLnNhbmRib3gudGFnLnNldCh7XG4gICAgICAgICAgc2FuZGJveElkOiBzYW5kYm94LmlkLFxuICAgICAgICAgIHRhZ3M6IHsgW2tleV06IHZhbHVlIH0gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9LFxuICAgICAgc2V0TWFueTogYXN5bmMgKHRhZ3M6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSA9PiB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC50YWcuc2V0KHtcbiAgICAgICAgICBzYW5kYm94SWQ6IHNhbmRib3guaWQsXG4gICAgICAgICAgdGFnczogdGFncyBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH0sXG4gICAgfSxcbiAgfTtcblxuICByZXR1cm4gc2FuZGJveDtcbn07XG4iLCAiaW1wb3J0IHR5cGUgeyBTdG9yYWdlIH0gZnJvbSBcIi4uL3N0b3JhZ2VcIjtcbmltcG9ydCB7IGNyZWF0ZUxvZ2dlciB9IGZyb20gXCIuLi91dGlscy9sb2dnZXJcIjtcblxuY29uc3QgbG9nID0gY3JlYXRlTG9nZ2VyKHsgc3Vic3lzdGVtOiBcInNhbmRib3g6c2V0dXBcIiB9KTtcblxuY29uc3QgU0VUVVBfUE9MTF9USU1FT1VUX01TID0gNSAqIDYwICogMTAwMDtcbmNvbnN0IFNFVFVQX1BPTExfSU5URVJWQUxfTVMgPSA1MDtcblxuLyoqXG4gKiBQb2xscyBzdG9yYWdlIHVudGlsIHNldHVwQ29tcGxldGVkQXQgaXMgd3JpdHRlbiBmb3IgdGhlIGdpdmVuIHNhbmRib3gra2V5LlxuICogVXNlZCBieSBjb2xkLXN0YXJ0IHdvcmtlcnMgdGhhdCBkb24ndCBoYXZlIHRoZSBzZXR1cCBmdW5jdGlvbiAoaXQncyBub3RcbiAqIHNlcmlhbGl6YWJsZSkgYnV0IG5lZWQgdG8gd2FpdCB1bnRpbCB0aGUgc2Vzc2lvbiB3b3JrZXIgZmluaXNoZXMgc2V0dXBcbiAqIGJlZm9yZSBleGVjdXRpbmcgY29tbWFuZHMuXG4gKlxuICogQWxzbyBkZXRlY3RzIHdoZW4gc2V0dXBLZXkgaXMgY2xlYXJlZCAoc2V0dXAgZmFpbGVkIGFuZCBzdGF0ZSB3YXMgcmVzZXQpLFxuICogdGhyb3dpbmcgaW1tZWRpYXRlbHkgc28gdGhlIGNhbGxlciBjYW4gcmV0cnkgaW5zdGVhZCBvZiBwb2xsaW5nIHRvIHRpbWVvdXQuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwb2xsRm9yU2V0dXBDb21wbGV0aW9uKHtcbiAgc3RvcmFnZSxcbiAgc2FuZGJveElkLFxuICBzZXR1cEtleSxcbn06IHtcbiAgc3RvcmFnZTogU3RvcmFnZTtcbiAgc2FuZGJveElkOiBzdHJpbmc7XG4gIHNldHVwS2V5OiBzdHJpbmc7XG59KTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IGRlYWRsaW5lID0gRGF0ZS5ub3coKSArIFNFVFVQX1BPTExfVElNRU9VVF9NUztcbiAgY29uc3QgZG9uZSA9IGxvZy50aW1lKFxuICAgIFwid2FpdGluZyBmb3Igc2V0dXAgY29tcGxldGlvblwiLFxuICAgIHsgc2FuZGJveElkLCBzZXR1cEtleSB9LFxuICAgIHsgbG9nT25TdGFydDogdHJ1ZSB9XG4gICk7XG5cbiAgd2hpbGUgKERhdGUubm93KCkgPCBkZWFkbGluZSkge1xuICAgIGNvbnN0IHJlY29yZCA9IGF3YWl0IHN0b3JhZ2Uuc2FuZGJveC5nZXQoc2FuZGJveElkKTtcbiAgICBpZiAoIShyZWNvcmQgaW5zdGFuY2VvZiBFcnJvcikgJiYgcmVjb3JkKSB7XG4gICAgICBpZiAocmVjb3JkLnNldHVwQ29tcGxldGVkQXQgJiYgcmVjb3JkLnNldHVwS2V5ID09PSBzZXR1cEtleSkge1xuICAgICAgICBkb25lKCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmICghcmVjb3JkLnNldHVwS2V5KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgU2V0dXAgd2FzIHJlc2V0IGZvciBzYW5kYm94IFwiJHtzYW5kYm94SWR9XCIgKHNldHVwS2V5IGNsZWFyZWQpLiBXaWxsIHJldHJ5IG9uIG5leHQgb3BlcmF0aW9uLmBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgYXdhaXQgbmV3IFByb21pc2UoKHIpID0+IHNldFRpbWVvdXQociwgU0VUVVBfUE9MTF9JTlRFUlZBTF9NUykpO1xuICB9XG4gIHRocm93IG5ldyBFcnJvcihcbiAgICBgVGltZWQgb3V0IHdhaXRpbmcgZm9yIHNhbmRib3ggc2V0dXAgdG8gY29tcGxldGUgKHNhbmRib3g9XCIke3NhbmRib3hJZH1cIilgXG4gICk7XG59XG5cbi8qKlxuICogV3JpdGVzIHNldHVwQ29tcGxldGVkQXQgdG8gdGhlIHNhbmRib3ggcmVjb3JkIHNvIGNvbGQtc3RhcnQgd29ya2Vyc1xuICogcG9sbGluZyBmb3Igc2V0dXAgY29tcGxldGlvbiBrbm93IGl0J3Mgc2FmZSB0byBwcm9jZWVkLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbWFya1NldHVwQ29tcGxldGUoe1xuICBzdG9yYWdlLFxuICBzYW5kYm94SWQsXG4gIHNldHVwS2V5LFxufToge1xuICBzdG9yYWdlOiBTdG9yYWdlO1xuICBzYW5kYm94SWQ6IHN0cmluZztcbiAgc2V0dXBLZXk6IHN0cmluZztcbn0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3RvcmFnZS5zYW5kYm94LnVwZGF0ZSh7XG4gICAgaWQ6IHNhbmRib3hJZCxcbiAgICBzZXR1cEtleSxcbiAgICBzZXR1cENvbXBsZXRlZEF0OiBEYXRlLm5vdygpLFxuICB9KTtcbiAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgdGhyb3cgcmVzdWx0O1xuICB9XG59XG5cbi8qKlxuICogUmVzZXRzIHNldHVwLXJlbGF0ZWQgc3RhdGUgb24gdGhlIHNhbmRib3ggcmVjb3JkIGFuZCBkZWxldGVzIHRoZSBzZXR1cFxuICogcmVjb3JkLiBDYWxsZWQgd2hlbiBzZXR1cCBmYWlscyBzbyB0aGF0OlxuICogMS4gQ29sZC1zdGFydCB3b3JrZXJzIGRldGVjdCB0aGUgY2xlYXJlZCBzZXR1cEtleSBhbmQgc3RvcCBwb2xsaW5nXG4gKiAyLiBBbnkgd29ya2VyIHJldHJ5aW5nIHdpbGwgc2VlIG5vIHNldHVwIHJlY29yZCBhbmQgcmUtcnVuIHNldHVwXG4gKlxuICogQmVzdC1lZmZvcnQ6IGZhaWx1cmVzIGFyZSBsb2dnZWQgYnV0IG5vdCB0aHJvd24sIHNpbmNlIHdlJ3JlIGFscmVhZHlcbiAqIGluIGFuIGVycm9yIHBhdGggYW5kIHRoZSBvcmlnaW5hbCBlcnJvciBtYXR0ZXJzIG1vcmUuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXNldFNldHVwU3RhdGUoe1xuICBzdG9yYWdlLFxuICBzYW5kYm94SWQsXG4gIHNldHVwS2V5LFxufToge1xuICBzdG9yYWdlOiBTdG9yYWdlO1xuICBzYW5kYm94SWQ6IHN0cmluZztcbiAgc2V0dXBLZXk6IHN0cmluZztcbn0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgYXdhaXQgc3RvcmFnZS5zYW5kYm94XG4gICAgLnVwZGF0ZSh7XG4gICAgICBpZDogc2FuZGJveElkLFxuICAgICAgc2V0dXBLZXk6IG51bGwsXG4gICAgICBzZXR1cENvbXBsZXRlZEF0OiBudWxsLFxuICAgIH0pXG4gICAgLmNhdGNoKChlKSA9PiB7XG4gICAgICBsb2cud2FybihcImZhaWxlZCB0byBjbGVhciBzZXR1cEtleVwiLCB7IHNhbmRib3hJZCwgZXJyb3I6IFN0cmluZyhlKSB9KTtcbiAgICB9KTtcblxuICBhd2FpdCBzdG9yYWdlLnNldHVwLmRlbGV0ZShzZXR1cEtleSkuY2F0Y2goKGUpID0+IHtcbiAgICBsb2cud2FybihcImZhaWxlZCB0byBkZWxldGUgc2V0dXAgcmVjb3JkXCIsIHsgc2V0dXBLZXksIGVycm9yOiBTdHJpbmcoZSkgfSk7XG4gIH0pO1xufVxuIiwgImltcG9ydCAqIGFzIHBhdGggZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHR5cGUgeyBVcGxvYWRhYmxlRmlsZSB9IGZyb20gXCIuLi9za2lsbHMvdHlwZXNcIjtcbmltcG9ydCB0eXBlIHsgU2FuZGJveCB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbmNvbnN0IE1BWF9SRVRSSUVTID0gMjtcbmNvbnN0IFJFVFJZX0JBU0VfTVMgPSA1MDA7XG5cbi8qKlxuICogRXhlYyBhIGNvbW1hbmQgYW5kIGFzc2VydCBleGl0IGNvZGUgMC4gUmV0cmllcyBvbiB0cmFuc2llbnQgZmFpbHVyZXNcbiAqIChleGl0IGNvZGUgMjU1IHdpdGggZW1wdHkgc3RkZXJyIFx1MjAxNCB0eXBpY2FsbHkgYSBzYW5kYm94IHByb2Nlc3Mga2lsbGVkXG4gKiBiZWZvcmUgaXQgY291bGQgcHJvZHVjZSBvdXRwdXQpLlxuICovXG5hc3luYyBmdW5jdGlvbiBleGVjQ2hlY2tlZChcbiAgc2FuZGJveDogUGljazxTYW5kYm94LCBcImV4ZWNcIj4sXG4gIG9wdHM6IHsgY29tbWFuZDogc3RyaW5nOyBhcmdzPzogc3RyaW5nW10gfSxcbiAgZXJyb3JMYWJlbDogc3RyaW5nXG4pOiBQcm9taXNlPHsgc3Rkb3V0OiBzdHJpbmc7IHN0ZGVycjogc3RyaW5nOyBleGl0Q29kZTogbnVtYmVyIH0+IHtcbiAgZm9yIChsZXQgYXR0ZW1wdCA9IDA7IDsgYXR0ZW1wdCsrKSB7XG4gICAgY29uc3QgZXhlY1Jlc3VsdCA9IGF3YWl0IHNhbmRib3guZXhlYyhvcHRzKTtcbiAgICBpZiAoZXhlY1Jlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICB0aHJvdyBleGVjUmVzdWx0O1xuICAgIH1cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBleGVjUmVzdWx0LnJlc3VsdDtcbiAgICBpZiAocmVzdWx0LmV4aXRDb2RlID09PSAwKSB7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIGNvbnN0IGlzVHJhbnNpZW50ID0gcmVzdWx0LmV4aXRDb2RlID09PSAyNTUgJiYgIXJlc3VsdC5zdGRlcnIudHJpbSgpO1xuICAgIGlmIChpc1RyYW5zaWVudCAmJiBhdHRlbXB0IDwgTUFYX1JFVFJJRVMpIHtcbiAgICAgIGF3YWl0IG5ldyBQcm9taXNlKChyKSA9PiBzZXRUaW1lb3V0KHIsIFJFVFJZX0JBU0VfTVMgKiAoYXR0ZW1wdCArIDEpKSk7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgJHtlcnJvckxhYmVsfSB3aXRoIGV4aXQgY29kZSAke3Jlc3VsdC5leGl0Q29kZX06ICR7cmVzdWx0LnN0ZGVycn1gXG4gICAgKTtcbiAgfVxufVxuXG4vKipcbiAqIFdyaXRlcyBmaWxlcyB0byBhIHNhbmRib3ggYXQgdGhlIHNwZWNpZmllZCBkZXN0aW5hdGlvbiBwYXRoLlxuICogU2hlbGwgc2NyaXB0cyAoLnNoIGZpbGVzKSBhcmUgYXV0b21hdGljYWxseSBtYWRlIGV4ZWN1dGFibGUuXG4gKlxuICogRm9yIHNtYWxsIGZpbGVzICg8MTAwS0IgdG90YWwpLCB1c2VzIHNpbmdsZSBleGVjIHdpdGggaGVyZWRvYy5cbiAqIEZvciBsYXJnZSBmaWxlcywgd3JpdGVzIGJhc2U2NCBjaHVua3MgdGhlbiBkZWNvZGVzIHRvIGF2b2lkIEFSR19NQVggbGltaXRzLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gd3JpdGVGaWxlcyhvcHRzOiB7XG4gIHNhbmRib3g6IFBpY2s8U2FuZGJveCwgXCJleGVjXCI+O1xuICBmaWxlczogVXBsb2FkYWJsZUZpbGVbXTtcbiAgZGVzdFBhdGg6IHN0cmluZztcbn0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgeyBzYW5kYm94LCBmaWxlcywgZGVzdFBhdGggfSA9IG9wdHM7XG5cbiAgaWYgKGZpbGVzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IGZpbGVQYXRocyA9IGZpbGVzLm1hcCgoZmlsZSkgPT4gcGF0aC5wb3NpeC5qb2luKGRlc3RQYXRoLCBmaWxlLnBhdGgpKTtcbiAgY29uc3QgcGFyZW50RGlycyA9IEFycmF5LmZyb20oXG4gICAgbmV3IFNldChmaWxlUGF0aHMubWFwKChwKSA9PiBwYXRoLnBvc2l4LmRpcm5hbWUocCkpKVxuICApO1xuICBjb25zdCBzaGVsbFNjcmlwdHMgPSBmaWxlUGF0aHMuZmlsdGVyKChwKSA9PiBwLmVuZHNXaXRoKFwiLnNoXCIpKTtcblxuICBjb25zdCBta2RpclJlc3VsdCA9IGF3YWl0IHNhbmRib3guZXhlYyh7XG4gICAgY29tbWFuZDogXCJta2RpclwiLFxuICAgIGFyZ3M6IFtcIi1wXCIsIC4uLnBhcmVudERpcnNdLFxuICB9KTtcbiAgaWYgKG1rZGlyUmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICB0aHJvdyBta2RpclJlc3VsdDtcbiAgfVxuICBhd2FpdCBta2RpclJlc3VsdC5yZXN1bHQ7XG5cbiAgY29uc3QgQ0hVTktfU0laRSA9IDUwXzAwMDtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGZpbGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3QgZmlsZSA9IGZpbGVzW2ldO1xuICAgIGNvbnN0IGZ1bGxQYXRoID0gZmlsZVBhdGhzW2ldO1xuICAgIGNvbnN0IGJhc2U2NENvbnRlbnQgPSB0b0Jhc2U2NChmaWxlLmNvbnRlbnQpO1xuXG4gICAgaWYgKGJhc2U2NENvbnRlbnQubGVuZ3RoIDwgQ0hVTktfU0laRSkge1xuICAgICAgY29uc3QgbWFya2VyID0gYEVPRl8ke2l9YDtcbiAgICAgIGF3YWl0IGV4ZWNDaGVja2VkKFxuICAgICAgICBzYW5kYm94LFxuICAgICAgICB7XG4gICAgICAgICAgY29tbWFuZDogXCJiYXNoXCIsXG4gICAgICAgICAgYXJnczogW1xuICAgICAgICAgICAgXCItY1wiLFxuICAgICAgICAgICAgYGJhc2U2NCAtZCA+ICR7cXVvdGUoZnVsbFBhdGgpfSA8PCAnJHttYXJrZXJ9J1xuJHtiYXNlNjRDb250ZW50fVxuJHttYXJrZXJ9YCxcbiAgICAgICAgICBdLFxuICAgICAgICB9LFxuICAgICAgICBcIndyaXRlRmlsZXMgZmFpbGVkXCJcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHRlbXBCNjQgPSBgL3RtcC9jaHVuay0ke0RhdGUubm93KCl9LSR7aX0uYjY0YDtcblxuICAgICAgY29uc3QgY2xlYXJSZXN1bHQgPSBhd2FpdCBzYW5kYm94LmV4ZWMoe1xuICAgICAgICBjb21tYW5kOiBcImJhc2hcIixcbiAgICAgICAgYXJnczogW1wiLWNcIiwgYD4gJHtxdW90ZSh0ZW1wQjY0KX1gXSxcbiAgICAgIH0pO1xuICAgICAgaWYgKGNsZWFyUmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgY2xlYXJSZXN1bHQ7XG4gICAgICB9XG4gICAgICBhd2FpdCBjbGVhclJlc3VsdC5yZXN1bHQ7XG5cbiAgICAgIGZvciAoXG4gICAgICAgIGxldCBvZmZzZXQgPSAwO1xuICAgICAgICBvZmZzZXQgPCBiYXNlNjRDb250ZW50Lmxlbmd0aDtcbiAgICAgICAgb2Zmc2V0ICs9IENIVU5LX1NJWkVcbiAgICAgICkge1xuICAgICAgICBjb25zdCBjaHVuayA9IGJhc2U2NENvbnRlbnQuc2xpY2Uob2Zmc2V0LCBvZmZzZXQgKyBDSFVOS19TSVpFKTtcbiAgICAgICAgY29uc3QgbWFya2VyID0gYENIVU5LXyR7b2Zmc2V0fWA7XG4gICAgICAgIGF3YWl0IGV4ZWNDaGVja2VkKFxuICAgICAgICAgIHNhbmRib3gsXG4gICAgICAgICAge1xuICAgICAgICAgICAgY29tbWFuZDogXCJiYXNoXCIsXG4gICAgICAgICAgICBhcmdzOiBbXG4gICAgICAgICAgICAgIFwiLWNcIixcbiAgICAgICAgICAgICAgYGNhdCA+PiAke3F1b3RlKHRlbXBCNjQpfSA8PCAnJHttYXJrZXJ9J1xuJHtjaHVua31cbiR7bWFya2VyfWAsXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgXCJ3cml0ZUZpbGVzIGNodW5rIGZhaWxlZFwiXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGF3YWl0IGV4ZWNDaGVja2VkKFxuICAgICAgICBzYW5kYm94LFxuICAgICAgICB7XG4gICAgICAgICAgY29tbWFuZDogXCJiYXNoXCIsXG4gICAgICAgICAgYXJnczogW1xuICAgICAgICAgICAgXCItY1wiLFxuICAgICAgICAgICAgYGJhc2U2NCAtZCA8ICR7cXVvdGUodGVtcEI2NCl9ID4gJHtxdW90ZShmdWxsUGF0aCl9ICYmIHJtIC1mICR7cXVvdGUodGVtcEI2NCl9YCxcbiAgICAgICAgICBdLFxuICAgICAgICB9LFxuICAgICAgICBcIndyaXRlRmlsZXMgZGVjb2RlIGZhaWxlZFwiXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIGlmIChzaGVsbFNjcmlwdHMubGVuZ3RoID4gMCkge1xuICAgIGNvbnN0IGNobW9kUmVzdWx0ID0gYXdhaXQgc2FuZGJveC5leGVjKHtcbiAgICAgIGNvbW1hbmQ6IFwiY2htb2RcIixcbiAgICAgIGFyZ3M6IFtcIit4XCIsIC4uLnNoZWxsU2NyaXB0c10sXG4gICAgfSk7XG4gICAgaWYgKGNobW9kUmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIHRocm93IGNobW9kUmVzdWx0O1xuICAgIH1cbiAgICBhd2FpdCBjaG1vZFJlc3VsdC5yZXN1bHQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gdG9CYXNlNjQoY29udGVudDogc3RyaW5nIHwgQnVmZmVyKTogc3RyaW5nIHtcbiAgaWYgKHR5cGVvZiBjb250ZW50ID09PSBcInN0cmluZ1wiKSB7XG4gICAgcmV0dXJuIEJ1ZmZlci5mcm9tKGNvbnRlbnQpLnRvU3RyaW5nKFwiYmFzZTY0XCIpO1xuICB9XG4gIHJldHVybiBjb250ZW50LnRvU3RyaW5nKFwiYmFzZTY0XCIpO1xufVxuXG5mdW5jdGlvbiBxdW90ZShzOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gYCcke3MucmVwbGFjZSgvJy9nLCBcIidcXFxcJydcIil9J2A7XG59XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7OztBQUNBLFNBQVMsVUFBVSxhQUFhO0FBQ2hDLFlBQVksUUFBUTtBQUNwQixZQUFZLFFBQVE7QUFDcEIsWUFBWUEsV0FBVTtBQUN0QixZQUFZLFlBQVk7QUFDeEIsU0FBUyxZQUFZOzs7QUNIckIsSUFBTSxNQUFNLGFBQWEsRUFBRSxXQUFXLGdCQUFnQixDQUFDO0FBRXZELElBQU0sd0JBQXdCLElBQUksS0FBSztBQUN2QyxJQUFNLHlCQUF5QjtBQVcvQixlQUFzQix1QkFBdUI7QUFBQSxFQUMzQztBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQ0YsR0FJa0I7QUFDaEIsUUFBTSxXQUFXLEtBQUssSUFBSSxJQUFJO0FBQzlCLFFBQU0sT0FBTyxJQUFJO0FBQUEsSUFDZjtBQUFBLElBQ0EsRUFBRSxXQUFXLFNBQVM7QUFBQSxJQUN0QixFQUFFLFlBQVksS0FBSztBQUFBLEVBQ3JCO0FBRUEsU0FBTyxLQUFLLElBQUksSUFBSSxVQUFVO0FBQzVCLFVBQU0sU0FBUyxNQUFNLFFBQVEsUUFBUSxJQUFJLFNBQVM7QUFDbEQs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WUFBSUEsMEJBQXlCLE9BQU87QUFDbEMsaUJBQU9BO0FBQUEsUUFDVDtBQUNBLGVBQU9BLGVBQWMsT0FBTyxHQUFhO0FBQUEsTUFHM0M7QUFBQSxNQUNBLEtBQUssT0FBTyxLQUFhLFVBQW1CO0FBQzFDLGNBQU0sU0FBUyxNQUFNLFFBQVEsUUFBUSxJQUFJLElBQUk7QUFBQSxVQUMzQyxXQUFXLFFBQVE7QUFBQSxVQUNuQixNQUFNLEVBQUUsQ0FBQyxHQUFHLEdBQUcsTUFBTTtBQUFBLFFBQ3ZCLENBQUM7QUFDRCxZQUFJLGtCQUFrQixPQUFPO0FBQzNCLGlCQUFPO0FBQUEsUUFDVDtBQUNBLGVBQU87QUFBQSxNQUNUO0FBQUEsTUFDQSxTQUFTLE9BQU8sU0FBa0M7QUFDaEQsY0FBTSxTQUFTLE1BQU0sUUFBUSxRQUFRLElBQUksSUFBSTtBQUFBLFVBQzNDLFdBQVcsUUFBUTtBQUFBLFVBQ25CO0FBQUEsUUFDRixDQUFDO0FBQ0QsWUFBSSxrQkFBa0IsT0FBTztBQUMzQixpQkFBTztBQUFBLFFBQ1Q7QUFDQSxlQUFPO0FBQUEsTUFDVDtBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBRUEsU0FBTztBQUNUOyIsCiAgIm5hbWVzIjogWyJwYXRoIiwgImN3ZCIsICJzdG9yYWdlIiwgInNhbmRib3hSZWNvcmQiXQp9Cg==
|