experimental-agent 0.7.1 → 0.8.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-DO4HKPHR.mjs +199 -0
- package/dist/chunk-EH4L2CPW.mjs +3779 -0
- package/dist/chunk-LMYEJDMD.mjs +123 -0
- package/dist/{client-D4AiVqFt.d.ts → client-DIanpEQ_.d.ts} +8 -53
- package/dist/{client-DCtmZCY8.d.mts → client-PuttJd6O.d.mts} +8 -53
- package/dist/framework-DH4Z1NLV.d.ts +61 -0
- package/dist/framework-c9fvEy0o.d.mts +61 -0
- package/dist/framework-runtime.d.mts +37 -0
- package/dist/framework-runtime.d.ts +37 -0
- package/dist/framework-runtime.js +5431 -0
- package/dist/framework-runtime.mjs +107 -0
- package/dist/framework.d.mts +11 -0
- package/dist/framework.d.ts +11 -0
- package/dist/framework.js +235 -0
- package/dist/framework.mjs +8 -0
- package/dist/index.d.mts +30 -7
- package/dist/index.d.ts +30 -7
- package/dist/index.js +50 -4
- package/dist/index.mjs +159 -3863
- package/dist/next/agents.d.mts +43 -0
- package/dist/next/agents.d.ts +43 -0
- package/dist/next/agents.js +364 -0
- package/dist/next/agents.mjs +137 -0
- package/dist/next/loader.js +18 -2
- package/dist/next/loader.mjs +1 -1
- package/dist/next.js +18 -2
- package/dist/next.mjs +1 -1
- package/dist/react.d.mts +2 -1
- package/dist/react.d.ts +2 -1
- package/dist/resolve-BZ26gcyj.d.ts +34 -0
- package/dist/resolve-Cma6YFgx.d.mts +34 -0
- package/dist/sandbox.mjs +2 -2
- package/dist/types-B3lbsOa7.d.mts +53 -0
- package/dist/types-B3lbsOa7.d.ts +53 -0
- package/package.json +29 -13
- package/dist/chunk-ZIXWGYE5.mjs +0 -107
package/dist/index.mjs
CHANGED
|
@@ -1,3892 +1,152 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
} from "./chunk-
|
|
16
|
-
import "./chunk-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
import
|
|
20
|
-
|
|
21
|
-
// src/sandbox/handle.ts
|
|
22
|
-
import { ulid } from "ulid";
|
|
23
|
-
|
|
24
|
-
// src/agent/is-vercel.ts
|
|
25
|
-
var isVercel = async () => {
|
|
26
|
-
try {
|
|
27
|
-
const { getVercelOidcToken } = await import("@vercel/oidc");
|
|
28
|
-
return Boolean(await getVercelOidcToken());
|
|
29
|
-
} catch {
|
|
30
|
-
return false;
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
// src/errors.ts
|
|
35
|
-
import * as errore from "errore";
|
|
36
|
-
var SessionNotFoundError = class extends errore.createTaggedError({
|
|
37
|
-
name: "SessionNotFoundError",
|
|
38
|
-
message: "Session $id not found"
|
|
39
|
-
}) {
|
|
40
|
-
};
|
|
41
|
-
var SessionError = class extends errore.createTaggedError({
|
|
42
|
-
name: "SessionError",
|
|
43
|
-
message: "Session $id failed: $reason"
|
|
44
|
-
}) {
|
|
45
|
-
};
|
|
46
|
-
var SandboxNotFoundError = class extends errore.createTaggedError({
|
|
47
|
-
name: "SandboxNotFoundError",
|
|
48
|
-
message: "Sandbox $id not found"
|
|
49
|
-
}) {
|
|
50
|
-
};
|
|
51
|
-
var StorageError = class extends errore.createTaggedError({
|
|
52
|
-
name: "StorageError",
|
|
53
|
-
message: "$reason"
|
|
54
|
-
}) {
|
|
55
|
-
};
|
|
56
|
-
var StorageConflictError = class extends errore.createTaggedError({
|
|
57
|
-
name: "StorageConflictError",
|
|
58
|
-
message: "$reason"
|
|
59
|
-
}) {
|
|
60
|
-
};
|
|
61
|
-
var SandboxError = class extends errore.createTaggedError({
|
|
62
|
-
name: "SandboxError",
|
|
63
|
-
message: "$reason"
|
|
64
|
-
}) {
|
|
65
|
-
};
|
|
66
|
-
var MessageNotFoundError = class extends errore.createTaggedError({
|
|
67
|
-
name: "MessageNotFoundError",
|
|
68
|
-
message: "Message $id not found"
|
|
69
|
-
}) {
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
// src/sandbox/setup.ts
|
|
73
|
-
var POLL_INTERVAL_MS = 50;
|
|
74
|
-
var POLL_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
75
|
-
function isSingleBinding(sandbox) {
|
|
76
|
-
return !Array.isArray(sandbox);
|
|
77
|
-
}
|
|
78
|
-
async function getDefaultBinding() {
|
|
79
|
-
if (await isVercel()) {
|
|
80
|
-
const { vercelSandbox } = await import("./vercel-7TYF67KD.mjs");
|
|
81
|
-
return vercelSandbox();
|
|
82
|
-
}
|
|
83
|
-
if (await isDockerAvailable()) {
|
|
84
|
-
const { dockerSandbox } = await import("./docker-OBUQX5ZI.mjs");
|
|
85
|
-
return dockerSandbox();
|
|
86
|
-
}
|
|
87
|
-
const { localSandbox } = await import("./local-4C3V4EFS.mjs");
|
|
88
|
-
return localSandbox();
|
|
89
|
-
}
|
|
90
|
-
async function isDockerAvailable() {
|
|
91
|
-
try {
|
|
92
|
-
const { execSync } = await import("child_process");
|
|
93
|
-
execSync("docker sandbox --help", { stdio: "ignore", timeout: 5e3 });
|
|
94
|
-
return true;
|
|
95
|
-
} catch {
|
|
96
|
-
return false;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
async function resolveBinding(sandbox, type) {
|
|
100
|
-
if (!sandbox) {
|
|
101
|
-
const binding = await getDefaultBinding();
|
|
102
|
-
return { binding, bindingName: binding.type };
|
|
103
|
-
}
|
|
104
|
-
if (isSingleBinding(sandbox)) {
|
|
105
|
-
return { binding: sandbox, bindingName: sandbox.type };
|
|
106
|
-
}
|
|
107
|
-
if (type) {
|
|
108
|
-
const match = sandbox.find((b) => b.type === type);
|
|
109
|
-
if (!match) {
|
|
110
|
-
throw new SandboxError({
|
|
111
|
-
reason: `Unknown binding type: "${type}". Available: ${sandbox.map((b) => b.type).join(", ")}`
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
return { binding: match, bindingName: match.type };
|
|
115
|
-
}
|
|
116
|
-
if (sandbox.length === 0) {
|
|
117
|
-
throw new SandboxError({ reason: "No sandbox bindings configured" });
|
|
118
|
-
}
|
|
119
|
-
return { binding: sandbox[0], bindingName: sandbox[0].type };
|
|
120
|
-
}
|
|
121
|
-
async function resolveSandboxId(ctx) {
|
|
122
|
-
if (ctx.sandboxId) {
|
|
123
|
-
return ctx.sandboxId;
|
|
124
|
-
}
|
|
125
|
-
if (!ctx._sessionId) {
|
|
126
|
-
throw new Error(
|
|
127
|
-
"SandboxContext has no sandboxId and no sessionId to resolve from"
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
const record = await ctx.agent.storage.session.get(ctx._sessionId);
|
|
131
|
-
ctx.sandboxId = record?.sandboxId ?? ctx._sessionId;
|
|
132
|
-
return ctx.sandboxId;
|
|
133
|
-
}
|
|
134
|
-
async function setup(ctx, opts) {
|
|
135
|
-
"use step";
|
|
136
|
-
const sandboxId = await resolveSandboxId(ctx);
|
|
137
|
-
if (ctx._pendingSetup) {
|
|
138
|
-
return { done: ctx._pendingSetup };
|
|
139
|
-
}
|
|
140
|
-
const agent2 = ctx.agent;
|
|
141
|
-
const log2 = createLogger({
|
|
142
|
-
config: { ...agent2.options.logging, name: agent2.name },
|
|
143
|
-
subsystem: "sandbox:setup",
|
|
144
|
-
context: { sandboxId }
|
|
145
|
-
});
|
|
146
|
-
const doneResolveBinding = log2.time("resolve binding", {
|
|
147
|
-
requestedType: opts?.type
|
|
148
|
-
});
|
|
149
|
-
const { binding, bindingName } = await resolveBinding(
|
|
150
|
-
agent2.options.sandbox,
|
|
151
|
-
opts?.type
|
|
152
|
-
);
|
|
153
|
-
doneResolveBinding();
|
|
154
|
-
if (opts?.cwd) {
|
|
155
|
-
ctx._cwd = opts.cwd;
|
|
156
|
-
}
|
|
157
|
-
const setupLog = log2.withContext({
|
|
158
|
-
binding: bindingName,
|
|
159
|
-
version: opts?.version ?? binding.defaults?.version
|
|
160
|
-
});
|
|
161
|
-
let resolveBlockingPromise = (value) => value;
|
|
162
|
-
let rejectBlockingPromise = (_reason) => {
|
|
163
|
-
};
|
|
164
|
-
const blockingPromise = new Promise((resolve2, reject) => {
|
|
165
|
-
resolveBlockingPromise = resolve2;
|
|
166
|
-
rejectBlockingPromise = reject;
|
|
167
|
-
});
|
|
168
|
-
ctx._pendingSetup = (async () => {
|
|
169
|
-
let sleepOldInstance;
|
|
170
|
-
const donePendingSetup = setupLog.time("pending setup");
|
|
171
|
-
try {
|
|
172
|
-
const doneStorageGet = setupLog.time("storage.sandbox.get");
|
|
173
|
-
const record = await agent2.storage.sandbox.get(sandboxId);
|
|
174
|
-
doneStorageGet();
|
|
175
|
-
const bindingDefaults = binding.defaults ?? {};
|
|
176
|
-
const effectiveVersion = opts?.version ?? bindingDefaults.version ?? null;
|
|
177
|
-
const effectiveRun = opts?.run ?? bindingDefaults.run;
|
|
178
|
-
const effectiveNetworkPolicy = opts?.networkPolicy ?? bindingDefaults.networkPolicy ?? null;
|
|
179
|
-
const effectiveCwd = ctx._cwd || opts?.cwd || bindingDefaults.cwd || null;
|
|
180
|
-
if (effectiveCwd) {
|
|
181
|
-
ctx._cwd = effectiveCwd;
|
|
182
|
-
}
|
|
183
|
-
const effectiveConfig = {
|
|
184
|
-
...bindingDefaults.config,
|
|
185
|
-
// biome-ignore lint/suspicious/noExplicitAny: opts is a union; config exists on binding-specific branches
|
|
186
|
-
...opts?.config
|
|
187
|
-
};
|
|
188
|
-
if (record) {
|
|
189
|
-
const versionMatches = !effectiveVersion || record.setup?.version === effectiveVersion;
|
|
190
|
-
if (versionMatches && record.setup?.completedAt) {
|
|
191
|
-
resolveBlockingPromise();
|
|
192
|
-
const doneConnectExisting = setupLog.time(
|
|
193
|
-
"connect existing sandbox",
|
|
194
|
-
{
|
|
195
|
-
setupState: "completed"
|
|
196
|
-
}
|
|
197
|
-
);
|
|
198
|
-
const instance = await binding.connect({
|
|
199
|
-
agent: agent2,
|
|
200
|
-
metadata: record.setup.metadata,
|
|
201
|
-
cwd: record.setup.cwd,
|
|
202
|
-
signal: opts?.signal,
|
|
203
|
-
log: setupLog
|
|
204
|
-
});
|
|
205
|
-
doneConnectExisting();
|
|
206
|
-
ctx._cwd = instance.cwd;
|
|
207
|
-
return instance;
|
|
208
|
-
}
|
|
209
|
-
if (versionMatches && !record.setup?.completedAt) {
|
|
210
|
-
resolveBlockingPromise();
|
|
211
|
-
const donePollUntilReady = setupLog.time("poll until ready");
|
|
212
|
-
await pollUntilReady(ctx, opts?.signal);
|
|
213
|
-
donePollUntilReady();
|
|
214
|
-
const doneStorageGetPostPoll = setupLog.time(
|
|
215
|
-
"storage.sandbox.get (post-poll)"
|
|
216
|
-
);
|
|
217
|
-
const ready = await agent2.storage.sandbox.get(sandboxId);
|
|
218
|
-
doneStorageGetPostPoll();
|
|
219
|
-
if (!ready) {
|
|
220
|
-
throw new SandboxNotFoundError({ id: sandboxId });
|
|
221
|
-
}
|
|
222
|
-
const doneConnectExisting = setupLog.time(
|
|
223
|
-
"connect existing sandbox",
|
|
224
|
-
{
|
|
225
|
-
setupState: "post-poll"
|
|
226
|
-
}
|
|
227
|
-
);
|
|
228
|
-
const instance = await binding.connect({
|
|
229
|
-
agent: agent2,
|
|
230
|
-
metadata: ready.setup.metadata,
|
|
231
|
-
cwd: ready.setup.cwd,
|
|
232
|
-
signal: opts?.signal,
|
|
233
|
-
log: setupLog
|
|
234
|
-
});
|
|
235
|
-
doneConnectExisting();
|
|
236
|
-
ctx._cwd = instance.cwd;
|
|
237
|
-
return instance;
|
|
238
|
-
}
|
|
239
|
-
if (record.setup.metadata) {
|
|
240
|
-
const oldInstanceMetadata = record.setup.metadata;
|
|
241
|
-
sleepOldInstance = (async () => {
|
|
242
|
-
const doneStopOldInstance = setupLog.time(
|
|
243
|
-
"stop old sandbox instance"
|
|
244
|
-
);
|
|
245
|
-
try {
|
|
246
|
-
const old = await binding.connect({
|
|
247
|
-
agent: agent2,
|
|
248
|
-
metadata: oldInstanceMetadata,
|
|
249
|
-
log: setupLog
|
|
250
|
-
});
|
|
251
|
-
await old.stop();
|
|
252
|
-
} catch {
|
|
253
|
-
doneStopOldInstance();
|
|
254
|
-
return;
|
|
255
|
-
}
|
|
256
|
-
doneStopOldInstance();
|
|
257
|
-
})();
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
const now = Date.now();
|
|
261
|
-
const setup_ = {
|
|
262
|
-
binding: bindingName,
|
|
263
|
-
version: effectiveVersion ?? record?.setup?.version ?? null,
|
|
264
|
-
networkPolicy: effectiveNetworkPolicy ?? record?.setup?.networkPolicy ?? null,
|
|
265
|
-
completedAt: null,
|
|
266
|
-
metadata: null,
|
|
267
|
-
cwd: null
|
|
268
|
-
};
|
|
269
|
-
const newRecord = {
|
|
270
|
-
id: sandboxId,
|
|
271
|
-
setup: setup_,
|
|
272
|
-
createdAt: record?.createdAt ?? now,
|
|
273
|
-
lastActiveAt: now
|
|
274
|
-
};
|
|
275
|
-
const doneStorageSetPending = setupLog.time(
|
|
276
|
-
"storage.sandbox.set (setup pending)"
|
|
277
|
-
);
|
|
278
|
-
await agent2.storage.sandbox.set(sandboxId, newRecord);
|
|
279
|
-
doneStorageSetPending();
|
|
280
|
-
resolveBlockingPromise();
|
|
281
|
-
const doneBindingCreate = setupLog.time("binding.create");
|
|
282
|
-
const result = await binding.create({
|
|
283
|
-
cwd: ctx._cwd ?? ".",
|
|
284
|
-
agent: agent2,
|
|
285
|
-
setup: {
|
|
286
|
-
...setup_,
|
|
287
|
-
run: effectiveRun,
|
|
288
|
-
config: effectiveConfig
|
|
289
|
-
},
|
|
290
|
-
record: newRecord,
|
|
291
|
-
signal: opts?.signal,
|
|
292
|
-
log: setupLog
|
|
293
|
-
});
|
|
294
|
-
doneBindingCreate();
|
|
295
|
-
setup_.completedAt = Date.now();
|
|
296
|
-
setup_.metadata = result.metadata;
|
|
297
|
-
setup_.cwd = result.instance.cwd;
|
|
298
|
-
const doneStorageUpdateComplete = setupLog.time(
|
|
299
|
-
"storage.sandbox.update (setup complete)"
|
|
300
|
-
);
|
|
301
|
-
await agent2.storage.sandbox.update(sandboxId, {
|
|
302
|
-
setup: setup_,
|
|
303
|
-
lastActiveAt: Date.now()
|
|
304
|
-
});
|
|
305
|
-
doneStorageUpdateComplete();
|
|
306
|
-
ctx._cwd = result.instance.cwd;
|
|
307
|
-
return result.instance;
|
|
308
|
-
} catch (err) {
|
|
309
|
-
ctx._pendingSetup = void 0;
|
|
310
|
-
rejectBlockingPromise(err);
|
|
311
|
-
throw err;
|
|
312
|
-
} finally {
|
|
313
|
-
const doneFinalize = setupLog.time("finalize setup");
|
|
314
|
-
await sleepOldInstance;
|
|
315
|
-
doneFinalize();
|
|
316
|
-
donePendingSetup();
|
|
317
|
-
}
|
|
318
|
-
})();
|
|
319
|
-
const doneWaitForUnblock = setupLog.time("wait for setup unblock");
|
|
320
|
-
await blockingPromise;
|
|
321
|
-
doneWaitForUnblock();
|
|
322
|
-
return { done: ctx._pendingSetup };
|
|
323
|
-
}
|
|
324
|
-
async function resolve(ctx, signal) {
|
|
325
|
-
const sandboxId = await resolveSandboxId(ctx);
|
|
326
|
-
const agent2 = ctx.agent;
|
|
327
|
-
const log2 = createLogger({
|
|
328
|
-
config: { ...agent2.options.logging, name: agent2.name },
|
|
329
|
-
subsystem: "sandbox:resolve",
|
|
330
|
-
context: { sandboxId }
|
|
331
|
-
});
|
|
332
|
-
if (ctx._pendingSetup) {
|
|
333
|
-
return await ctx._pendingSetup;
|
|
334
|
-
}
|
|
335
|
-
let record = await agent2.storage.sandbox.get(sandboxId);
|
|
336
|
-
if (!record) {
|
|
337
|
-
const { done } = await setup(ctx, { signal });
|
|
338
|
-
return await done;
|
|
339
|
-
}
|
|
340
|
-
if (!record.setup?.completedAt) {
|
|
341
|
-
await pollUntilReady(ctx, signal);
|
|
342
|
-
record = await agent2.storage.sandbox.get(sandboxId);
|
|
343
|
-
}
|
|
344
|
-
if (!record) {
|
|
345
|
-
throw new SandboxNotFoundError({ id: sandboxId });
|
|
346
|
-
}
|
|
347
|
-
const { binding } = await resolveBinding(
|
|
348
|
-
ctx.agent.options.sandbox,
|
|
349
|
-
record.setup.binding
|
|
350
|
-
);
|
|
351
|
-
agent2.storage.sandbox.update(sandboxId, { lastActiveAt: Date.now() }).catch((error) => {
|
|
352
|
-
log2.error("Failed to update sandbox lastActiveAt", { error });
|
|
353
|
-
});
|
|
354
|
-
const instance = await binding.connect({
|
|
355
|
-
agent: agent2,
|
|
356
|
-
metadata: record.setup.metadata,
|
|
357
|
-
cwd: record.setup.cwd,
|
|
358
|
-
signal,
|
|
359
|
-
log: log2
|
|
360
|
-
});
|
|
361
|
-
ctx._cwd = instance.cwd;
|
|
362
|
-
return instance;
|
|
363
|
-
}
|
|
364
|
-
async function pollUntilReady(ctx, signal) {
|
|
365
|
-
const id = ctx.sandboxId;
|
|
366
|
-
const deadline = Date.now() + POLL_TIMEOUT_MS;
|
|
367
|
-
while (Date.now() < deadline) {
|
|
368
|
-
signal?.throwIfAborted();
|
|
369
|
-
const record = await ctx.agent.storage.sandbox.get(id);
|
|
370
|
-
if (record?.setup?.completedAt) {
|
|
371
|
-
return;
|
|
372
|
-
}
|
|
373
|
-
await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
|
|
374
|
-
}
|
|
375
|
-
throw new SandboxError({
|
|
376
|
-
reason: `Timed out waiting for sandbox "${id}" setup to complete`
|
|
377
|
-
});
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
// src/sandbox/exec.ts
|
|
381
|
-
async function exec(sandboxContext, ...opts) {
|
|
382
|
-
const sbx = await resolve(sandboxContext);
|
|
383
|
-
return await sbx.exec(...opts);
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
// src/sandbox/get-domain.ts
|
|
387
|
-
async function getDomain(sandboxContext, ...opts) {
|
|
388
|
-
"use step";
|
|
389
|
-
const sbx = await resolve(sandboxContext);
|
|
390
|
-
return await sbx.getDomain(...opts);
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
// src/sandbox/get-status.ts
|
|
394
|
-
async function getStatus(sandboxContext, ...opts) {
|
|
395
|
-
"use step";
|
|
396
|
-
const sbx = await resolve(sandboxContext);
|
|
397
|
-
return await sbx.getStatus(...opts);
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
// src/sandbox/kill.ts
|
|
401
|
-
async function kill(sandboxContext, ...opts) {
|
|
402
|
-
"use step";
|
|
403
|
-
const sbx = await resolve(sandboxContext);
|
|
404
|
-
return await sbx.kill(...opts);
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
// src/sandbox/read-file.ts
|
|
408
|
-
async function readFile(sandboxContext, ...opts) {
|
|
409
|
-
"use step";
|
|
410
|
-
const sbx = await resolve(sandboxContext);
|
|
411
|
-
return await sbx.readFile(...opts);
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
// src/sandbox/snapshot.ts
|
|
415
|
-
async function snapshot(sandboxContext, ...opts) {
|
|
416
|
-
"use step";
|
|
417
|
-
const sbx = await resolve(sandboxContext);
|
|
418
|
-
return await sbx.snapshot(...opts);
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
// src/sandbox/start.ts
|
|
422
|
-
async function start(sandboxContext, ...opts) {
|
|
423
|
-
"use step";
|
|
424
|
-
const sbx = await resolve(sandboxContext);
|
|
425
|
-
return await sbx.start(...opts);
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
// src/sandbox/stop.ts
|
|
429
|
-
async function stop(sandboxContext, ...opts) {
|
|
430
|
-
"use step";
|
|
431
|
-
const sbx = await resolve(sandboxContext);
|
|
432
|
-
return await sbx.stop(...opts);
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
// src/sandbox/update-network-policy.ts
|
|
436
|
-
async function updateNetworkPolicy(sandboxContext, ...opts) {
|
|
437
|
-
"use step";
|
|
438
|
-
const sbx = await resolve(sandboxContext);
|
|
439
|
-
return await sbx.updateNetworkPolicy(...opts);
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
// src/sandbox/write-files.ts
|
|
443
|
-
async function writeFiles(sandboxContext, ...opts) {
|
|
444
|
-
"use step";
|
|
445
|
-
const sbx = await resolve(sandboxContext);
|
|
446
|
-
return await sbx.writeFiles(...opts);
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
// src/sandbox/handle.ts
|
|
450
|
-
function sandboxHandle(agent2, id) {
|
|
451
|
-
const sandboxId = typeof id === "string" ? id : id?.id ?? `sandbox_${ulid()}`;
|
|
452
|
-
const contexts = getSandboxContexts(agent2);
|
|
453
|
-
let sandboxContext = contexts.get(sandboxId);
|
|
454
|
-
if (!sandboxContext) {
|
|
455
|
-
sandboxContext = { agent: agent2, sandboxId };
|
|
456
|
-
contexts.set(sandboxId, sandboxContext);
|
|
457
|
-
}
|
|
458
|
-
return {
|
|
459
|
-
id: sandboxId,
|
|
460
|
-
get cwd() {
|
|
461
|
-
return sandboxContext._cwd ?? ".";
|
|
462
|
-
},
|
|
463
|
-
setup: setup.bind(null, sandboxContext),
|
|
464
|
-
exec: exec.bind(null, sandboxContext),
|
|
465
|
-
readFile: readFile.bind(null, sandboxContext),
|
|
466
|
-
writeFiles: writeFiles.bind(null, sandboxContext),
|
|
467
|
-
getDomain: getDomain.bind(null, sandboxContext),
|
|
468
|
-
updateNetworkPolicy: updateNetworkPolicy.bind(null, sandboxContext),
|
|
469
|
-
start: start.bind(null, sandboxContext),
|
|
470
|
-
stop: stop.bind(null, sandboxContext),
|
|
471
|
-
kill: kill.bind(null, sandboxContext),
|
|
472
|
-
snapshot: snapshot.bind(null, sandboxContext),
|
|
473
|
-
getStatus: getStatus.bind(null, sandboxContext)
|
|
474
|
-
};
|
|
475
|
-
}
|
|
476
|
-
function lazySandboxHandle(agent2, sessionId) {
|
|
477
|
-
const sandboxContext = {
|
|
478
|
-
agent: agent2,
|
|
479
|
-
sandboxId: null,
|
|
480
|
-
_sessionId: sessionId
|
|
481
|
-
};
|
|
482
|
-
return {
|
|
483
|
-
setup: setup.bind(null, sandboxContext),
|
|
484
|
-
exec: exec.bind(null, sandboxContext),
|
|
485
|
-
readFile: readFile.bind(null, sandboxContext),
|
|
486
|
-
writeFiles: writeFiles.bind(null, sandboxContext),
|
|
487
|
-
getDomain: getDomain.bind(null, sandboxContext),
|
|
488
|
-
updateNetworkPolicy: updateNetworkPolicy.bind(null, sandboxContext),
|
|
489
|
-
start: start.bind(null, sandboxContext),
|
|
490
|
-
stop: stop.bind(null, sandboxContext),
|
|
491
|
-
kill: kill.bind(null, sandboxContext),
|
|
492
|
-
snapshot: snapshot.bind(null, sandboxContext),
|
|
493
|
-
getStatus: getStatus.bind(null, sandboxContext)
|
|
494
|
-
};
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
// src/session/handle.ts
|
|
498
|
-
import { ulid as ulid4 } from "ulid";
|
|
499
|
-
|
|
500
|
-
// src/utils/ui.ts
|
|
501
|
-
function isSubToolPart(part) {
|
|
502
|
-
const p = part.part;
|
|
503
|
-
return typeof p?.toolCallId === "string" && p.toolCallId.startsWith("js_tc_");
|
|
504
|
-
}
|
|
505
|
-
function isStreamingContent(part) {
|
|
506
|
-
return typeof part === "object" && part !== null && "type" in part && (part.type === "text" || part.type === "reasoning");
|
|
507
|
-
}
|
|
508
|
-
function applyInterruptCutoff({
|
|
509
|
-
parts,
|
|
510
|
-
lastPart
|
|
511
|
-
}) {
|
|
512
|
-
return parts.filter((p) => p.index <= lastPart.index).map((p) => {
|
|
513
|
-
if (p.index !== lastPart.index) {
|
|
514
|
-
return p;
|
|
515
|
-
}
|
|
516
|
-
if (isStreamingContent(lastPart.part)) {
|
|
517
|
-
return { ...p, part: lastPart.part };
|
|
518
|
-
}
|
|
519
|
-
return p;
|
|
520
|
-
});
|
|
521
|
-
}
|
|
522
|
-
function assembleUIMessages(opts) {
|
|
523
|
-
let filtered = opts.messages;
|
|
524
|
-
if (opts.until !== void 0) {
|
|
525
|
-
const until = opts.until;
|
|
526
|
-
filtered = filtered.filter((m) => m.createdAt <= until);
|
|
527
|
-
}
|
|
528
|
-
if (!opts.includeQueued) {
|
|
529
|
-
filtered = filtered.filter((m) => m.startedAt !== null);
|
|
530
|
-
}
|
|
531
|
-
filtered = [...filtered].sort((a, b) => a.createdAt - b.createdAt);
|
|
532
|
-
const parts = opts.excludeSubToolParts ? opts.parts.filter((p) => !isSubToolPart(p)) : opts.parts;
|
|
533
|
-
const partsByMessage = /* @__PURE__ */ new Map();
|
|
534
|
-
for (const part of parts) {
|
|
535
|
-
const messageId = String(part.messageId);
|
|
536
|
-
const existing = partsByMessage.get(messageId) ?? [];
|
|
537
|
-
existing.push(part);
|
|
538
|
-
partsByMessage.set(messageId, existing);
|
|
539
|
-
}
|
|
540
|
-
return filtered.map((m) => {
|
|
541
|
-
const messageId = String(m.id);
|
|
542
|
-
let messageParts = partsByMessage.get(messageId) ?? [];
|
|
543
|
-
messageParts.sort((a, b) => a.index - b.index);
|
|
544
|
-
if (m.interruptedLastPart != null) {
|
|
545
|
-
messageParts = applyInterruptCutoff({
|
|
546
|
-
parts: messageParts,
|
|
547
|
-
lastPart: m.interruptedLastPart
|
|
548
|
-
});
|
|
549
|
-
}
|
|
550
|
-
return {
|
|
551
|
-
id: messageId,
|
|
552
|
-
role: m.role,
|
|
553
|
-
parts: messageParts.map((p) => p.part),
|
|
554
|
-
...m.metadata != null ? { metadata: m.metadata } : {}
|
|
555
|
-
};
|
|
556
|
-
}).filter((m) => m.parts.length > 0);
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
// src/utils/usage.ts
|
|
560
|
-
function computeSessionUsage(messages) {
|
|
561
|
-
const byMessageId = {};
|
|
562
|
-
for (const m of messages) {
|
|
563
|
-
byMessageId[m.id] = m.usage?.summary ?? null;
|
|
564
|
-
}
|
|
565
|
-
const summaries = messages.map((m) => m.usage?.summary).filter((s) => s !== void 0);
|
|
566
|
-
const total = {
|
|
567
|
-
model: summaries[0]?.model ?? "unknown",
|
|
568
|
-
inputTokens: summaries.reduce((acc, s) => acc + s.inputTokens, 0),
|
|
569
|
-
outputTokens: summaries.reduce((acc, s) => acc + s.outputTokens, 0),
|
|
570
|
-
totalTokens: summaries.reduce((acc, s) => acc + s.totalTokens, 0),
|
|
571
|
-
cacheReadTokens: summaries.reduce((acc, s) => acc + s.cacheReadTokens, 0),
|
|
572
|
-
cacheWriteTokens: summaries.reduce((acc, s) => acc + s.cacheWriteTokens, 0),
|
|
573
|
-
reasoningTokens: summaries.reduce((acc, s) => acc + s.reasoningTokens, 0),
|
|
574
|
-
stepCount: summaries.reduce((acc, s) => acc + s.stepCount, 0),
|
|
575
|
-
messageCount: summaries.length
|
|
576
|
-
};
|
|
577
|
-
return { total, byMessageId };
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
// src/session/history.ts
|
|
581
|
-
async function history(sessionContext) {
|
|
582
|
-
"use step";
|
|
583
|
-
const [session, messages, parts] = await Promise.all([
|
|
584
|
-
sessionContext.agent.storage.session.get(sessionContext.sessionId),
|
|
585
|
-
sessionContext.agent.storage.message.listBySession(
|
|
586
|
-
sessionContext.sessionId
|
|
587
|
-
),
|
|
588
|
-
sessionContext.agent.storage.part.listBySession(sessionContext.sessionId)
|
|
589
|
-
]);
|
|
590
|
-
const lastAssistant = messages.find(
|
|
591
|
-
(m) => m.id === session?.lastMessageId && m.role === "assistant"
|
|
592
|
-
) ?? messages.filter((m) => m.role === "assistant").at(-1);
|
|
593
|
-
const isStreaming = lastAssistant?.completedAt === null && lastAssistant?.interruptedAt === null;
|
|
594
|
-
const streamingMessageId = isStreaming ? lastAssistant.id : null;
|
|
595
|
-
const visibleUntil = lastAssistant?.createdAt;
|
|
596
|
-
const assembled = assembleUIMessages({
|
|
597
|
-
messages,
|
|
598
|
-
parts,
|
|
599
|
-
includeQueued: visibleUntil !== void 0,
|
|
600
|
-
until: visibleUntil
|
|
601
|
-
});
|
|
602
|
-
const usage2 = computeSessionUsage(messages);
|
|
603
|
-
return { messages: assembled, streamingMessageId, usage: usage2 };
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
// src/session/interrupt.ts
|
|
607
|
-
async function interrupt(sessionContext, opts) {
|
|
608
|
-
"use step";
|
|
609
|
-
const messages = await sessionContext.agent.storage.message.listBySession(
|
|
610
|
-
sessionContext.sessionId
|
|
611
|
-
);
|
|
612
|
-
const now = Date.now();
|
|
613
|
-
let pendingAssistantMessages = messages.filter(
|
|
614
|
-
(m) => m.role === "assistant" && m.completedAt === null && m.interruptedAt === null
|
|
615
|
-
);
|
|
616
|
-
if (pendingAssistantMessages.length === 0) {
|
|
617
|
-
const MAX_RETROACTIVE_MS = 5e3;
|
|
618
|
-
const latest = messages.filter(
|
|
619
|
-
(m) => m.role === "assistant" && m.interruptedAt === null && m.completedAt !== null && now - m.completedAt < MAX_RETROACTIVE_MS
|
|
620
|
-
).sort((a, b) => b.createdAt - a.createdAt).at(0);
|
|
621
|
-
if (latest) {
|
|
622
|
-
pendingAssistantMessages = [latest];
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
await Promise.all(
|
|
626
|
-
pendingAssistantMessages.map(
|
|
627
|
-
(m) => sessionContext.agent.storage.message.set(m.id, {
|
|
628
|
-
...m,
|
|
629
|
-
interruptedAt: now,
|
|
630
|
-
interruptedLastPart: opts?.lastPart ?? null
|
|
631
|
-
})
|
|
632
|
-
)
|
|
633
|
-
);
|
|
634
|
-
const messageIds = new Set(pendingAssistantMessages.map((m) => m.id));
|
|
635
|
-
if (messageIds.size === 0) {
|
|
636
|
-
return;
|
|
637
|
-
}
|
|
638
|
-
const allParts = await sessionContext.agent.storage.part.listBySession(
|
|
639
|
-
sessionContext.sessionId
|
|
640
|
-
);
|
|
641
|
-
for (const p of allParts) {
|
|
642
|
-
if (!messageIds.has(p.messageId)) {
|
|
643
|
-
continue;
|
|
644
|
-
}
|
|
645
|
-
if (p.part && "state" in p.part && p.part.state === "approval-requested" && "approval" in p.part) {
|
|
646
|
-
const approval = p.part.approval;
|
|
647
|
-
if (approval?.id) {
|
|
648
|
-
await sessionContext.agent.storage.part.set(p.id, {
|
|
649
|
-
...p,
|
|
650
|
-
part: {
|
|
651
|
-
...p.part,
|
|
652
|
-
state: "output-denied",
|
|
653
|
-
approval: {
|
|
654
|
-
...approval,
|
|
655
|
-
approved: false,
|
|
656
|
-
reason: "interrupted"
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
});
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
// src/session/send.ts
|
|
666
|
-
import { all } from "better-all";
|
|
667
|
-
import * as errore2 from "errore";
|
|
668
|
-
import { ulid as ulid3 } from "ulid";
|
|
669
|
-
|
|
670
|
-
// src/session/ai-loop/stream-text.ts
|
|
671
|
-
import {
|
|
672
|
-
convertToModelMessages,
|
|
673
|
-
createUIMessageStream,
|
|
674
|
-
stepCountIs,
|
|
675
|
-
streamText as streamTextAi
|
|
676
|
-
} from "ai";
|
|
677
|
-
|
|
678
|
-
// src/skills/parser.ts
|
|
679
|
-
function parseSkillFrontmatter(content) {
|
|
680
|
-
const trimmed = content.trim();
|
|
681
|
-
if (!trimmed.startsWith("---")) {
|
|
682
|
-
return null;
|
|
683
|
-
}
|
|
684
|
-
const endMarkerIndex = trimmed.indexOf("---", 3);
|
|
685
|
-
if (endMarkerIndex === -1) {
|
|
686
|
-
return null;
|
|
687
|
-
}
|
|
688
|
-
const frontmatterBlock = trimmed.slice(3, endMarkerIndex).trim();
|
|
689
|
-
const parsed = parseSimpleYaml(frontmatterBlock);
|
|
690
|
-
if (!(parsed.name && parsed.description)) {
|
|
691
|
-
return null;
|
|
692
|
-
}
|
|
693
|
-
return {
|
|
694
|
-
name: String(parsed.name),
|
|
695
|
-
description: String(parsed.description)
|
|
696
|
-
};
|
|
697
|
-
}
|
|
698
|
-
function parseSimpleYaml(yaml) {
|
|
699
|
-
const result = {};
|
|
700
|
-
for (const line of yaml.split("\n")) {
|
|
701
|
-
const trimmedLine = line.trim();
|
|
702
|
-
if (!trimmedLine || trimmedLine.startsWith("#")) {
|
|
703
|
-
continue;
|
|
704
|
-
}
|
|
705
|
-
const colonIndex = trimmedLine.indexOf(":");
|
|
706
|
-
if (colonIndex === -1) {
|
|
707
|
-
continue;
|
|
708
|
-
}
|
|
709
|
-
const key = trimmedLine.slice(0, colonIndex).trim();
|
|
710
|
-
let value = trimmedLine.slice(colonIndex + 1).trim();
|
|
711
|
-
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
712
|
-
value = value.slice(1, -1);
|
|
713
|
-
}
|
|
714
|
-
if (key) {
|
|
715
|
-
result[key] = value;
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
return result;
|
|
719
|
-
}
|
|
720
|
-
function normalizeSkills(skills) {
|
|
721
|
-
if (!skills || skills.length === 0) {
|
|
722
|
-
return [];
|
|
723
|
-
}
|
|
724
|
-
return skills.map((skill) => {
|
|
725
|
-
if (typeof skill !== "object" || skill === null) {
|
|
726
|
-
throw new Error(
|
|
727
|
-
"Invalid skills entry: expected an object with a `type` field."
|
|
728
|
-
);
|
|
729
|
-
}
|
|
730
|
-
if ("type" in skill && skill.type) {
|
|
731
|
-
return skill;
|
|
732
|
-
}
|
|
733
|
-
throw new Error("Invalid skills entry: expected `type`.");
|
|
734
|
-
});
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
// src/skills/discover.ts
|
|
738
|
-
async function discoverSkillsInSandbox(opts) {
|
|
739
|
-
const { agent: agent2, sandbox, skillsDirs, sessionId } = opts;
|
|
740
|
-
const baseLog = createLogger({
|
|
741
|
-
config: { ...agent2.options.logging, name: agent2.name },
|
|
742
|
-
subsystem: "skills"
|
|
743
|
-
});
|
|
744
|
-
const log2 = sessionId ? baseLog.withContext({ sessionId }) : baseLog;
|
|
745
|
-
const done = log2.time("discoverSkillsInSandbox");
|
|
746
|
-
const summaries = [];
|
|
747
|
-
const seenNames = /* @__PURE__ */ new Set();
|
|
748
|
-
for (const skillsDir of skillsDirs) {
|
|
749
|
-
const dirDone = log2.time("scan directory", { dir: skillsDir });
|
|
750
|
-
const dirSummaries = await discoverSkillsInDirectory({
|
|
751
|
-
sandbox,
|
|
752
|
-
skillsDir,
|
|
753
|
-
log: log2
|
|
754
|
-
});
|
|
755
|
-
dirDone({ count: dirSummaries.length });
|
|
756
|
-
for (const summary of dirSummaries) {
|
|
757
|
-
if (!seenNames.has(summary.name)) {
|
|
758
|
-
seenNames.add(summary.name);
|
|
759
|
-
summaries.push(summary);
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
done({ totalSkills: summaries.length });
|
|
764
|
-
return summaries;
|
|
765
|
-
}
|
|
766
|
-
async function discoverSkillsInDirectory(opts) {
|
|
767
|
-
const { sandbox, skillsDir, log: log2 } = opts;
|
|
768
|
-
const skillPaths = await findSkillFiles({ sandbox, skillsDir, log: log2 });
|
|
769
|
-
if (skillPaths.length === 0) {
|
|
770
|
-
return [];
|
|
771
|
-
}
|
|
772
|
-
const summaries = [];
|
|
773
|
-
for (const skillMdPath of skillPaths) {
|
|
774
|
-
const summary = await parseSkillFile({ sandbox, skillMdPath, log: log2 });
|
|
775
|
-
if (summary) {
|
|
776
|
-
summaries.push(summary);
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
return summaries;
|
|
780
|
-
}
|
|
781
|
-
async function findSkillFiles(opts) {
|
|
782
|
-
const { sandbox, skillsDir, log: log2 } = opts;
|
|
783
|
-
const execResult = await sandbox.exec({
|
|
784
|
-
command: "find",
|
|
785
|
-
args: [skillsDir, "-name", "SKILL.md", "-type", "f"]
|
|
786
|
-
});
|
|
787
|
-
if (execResult instanceof Error) {
|
|
788
|
-
log2.warn("failed to scan skills directory", {
|
|
789
|
-
dir: skillsDir,
|
|
790
|
-
error: execResult.message
|
|
791
|
-
});
|
|
792
|
-
return [];
|
|
793
|
-
}
|
|
794
|
-
const { stdout, exitCode } = await execResult.result;
|
|
795
|
-
if (exitCode !== 0) {
|
|
796
|
-
log2.warn("skills directory not found or inaccessible", { dir: skillsDir });
|
|
797
|
-
return [];
|
|
798
|
-
}
|
|
799
|
-
return stdout.trim().split("\n").filter((p) => p.length > 0);
|
|
800
|
-
}
|
|
801
|
-
async function parseSkillFile(opts) {
|
|
802
|
-
const { sandbox, skillMdPath, log: log2 } = opts;
|
|
803
|
-
const execResult = await sandbox.exec({
|
|
804
|
-
command: "cat",
|
|
805
|
-
args: [skillMdPath]
|
|
806
|
-
});
|
|
807
|
-
if (execResult instanceof Error) {
|
|
808
|
-
log2.warn("failed to read skill file", {
|
|
809
|
-
path: skillMdPath,
|
|
810
|
-
error: execResult.message
|
|
811
|
-
});
|
|
812
|
-
return null;
|
|
813
|
-
}
|
|
814
|
-
const { stdout, exitCode } = await execResult.result;
|
|
815
|
-
if (exitCode !== 0) {
|
|
816
|
-
log2.warn("could not read skill file", { path: skillMdPath });
|
|
817
|
-
return null;
|
|
818
|
-
}
|
|
819
|
-
const parsed = parseSkillFrontmatter(stdout);
|
|
820
|
-
if (!parsed) {
|
|
821
|
-
log2.warn("invalid or missing frontmatter", { path: skillMdPath });
|
|
822
|
-
return null;
|
|
823
|
-
}
|
|
824
|
-
return {
|
|
825
|
-
name: parsed.name,
|
|
826
|
-
description: parsed.description,
|
|
827
|
-
skillMdPath
|
|
828
|
-
};
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
// src/skills/resolve-host.ts
|
|
832
|
-
async function collectFiles(opts) {
|
|
833
|
-
const { readdir, readFile: readFile2, stat } = await import("fs/promises");
|
|
834
|
-
const { resolve: resolve2, posix: pathPosix } = await import("path");
|
|
835
|
-
const fileStat = await stat(opts.absolutePath);
|
|
836
|
-
if (fileStat.isFile()) {
|
|
837
|
-
const content = await readFile2(opts.absolutePath);
|
|
838
|
-
return [{ path: opts.relativePrefix ?? "SKILL.md", content }];
|
|
839
|
-
}
|
|
840
|
-
if (!fileStat.isDirectory()) {
|
|
841
|
-
return [];
|
|
842
|
-
}
|
|
843
|
-
const entries = await readdir(opts.absolutePath, { withFileTypes: true });
|
|
844
|
-
const files = [];
|
|
845
|
-
for (const entry of entries) {
|
|
846
|
-
const nextAbs = resolve2(opts.absolutePath, entry.name);
|
|
847
|
-
const nextRel = opts.relativePrefix ? pathPosix.join(opts.relativePrefix, entry.name) : entry.name;
|
|
848
|
-
if (entry.isDirectory()) {
|
|
849
|
-
files.push(
|
|
850
|
-
...await collectFiles({
|
|
851
|
-
absolutePath: nextAbs,
|
|
852
|
-
relativePrefix: nextRel
|
|
853
|
-
})
|
|
854
|
-
);
|
|
855
|
-
continue;
|
|
856
|
-
}
|
|
857
|
-
if (entry.isFile()) {
|
|
858
|
-
files.push({
|
|
859
|
-
path: nextRel,
|
|
860
|
-
content: await readFile2(nextAbs)
|
|
861
|
-
});
|
|
862
|
-
}
|
|
863
|
-
}
|
|
864
|
-
return files;
|
|
865
|
-
}
|
|
866
|
-
async function stableDirName(inputPath) {
|
|
867
|
-
const { createHash } = await import("crypto");
|
|
868
|
-
const hash = createHash("sha1").update(inputPath).digest("hex").slice(0, 10);
|
|
869
|
-
return `host-${hash}`;
|
|
870
|
-
}
|
|
871
|
-
async function resolveHostSkill(opts) {
|
|
872
|
-
const { resolve: resolve2, posix: pathPosix } = await import("path");
|
|
873
|
-
const hostPath = resolve2(process.cwd(), opts.skill.path);
|
|
874
|
-
const files = await collectFiles({ absolutePath: hostPath });
|
|
875
|
-
const dirName = await stableDirName(hostPath);
|
|
876
|
-
const destPath = pathPosix.join(".agent", "skills", ".materialized", dirName);
|
|
877
|
-
if (files.length === 0) {
|
|
878
|
-
return destPath;
|
|
879
|
-
}
|
|
880
|
-
await opts.sandbox.writeFiles({
|
|
881
|
-
files,
|
|
882
|
-
destPath
|
|
883
|
-
});
|
|
884
|
-
return destPath;
|
|
885
|
-
}
|
|
886
|
-
|
|
887
|
-
// src/skills/resolve-inline.ts
|
|
888
|
-
function slugify(value) {
|
|
889
|
-
return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "");
|
|
890
|
-
}
|
|
891
|
-
async function stableInlineDirName(name) {
|
|
892
|
-
const { createHash } = await import("crypto");
|
|
893
|
-
const slug = slugify(name) || "inline-skill";
|
|
894
|
-
const hash = createHash("sha1").update(name).digest("hex").slice(0, 8);
|
|
895
|
-
return `${slug}-${hash}`;
|
|
896
|
-
}
|
|
897
|
-
function buildSkillMarkdown(skill) {
|
|
898
|
-
return `---
|
|
899
|
-
name: ${skill.name}
|
|
900
|
-
description: ${skill.description}
|
|
901
|
-
---
|
|
902
|
-
|
|
903
|
-
${skill.instructions.trim()}
|
|
904
|
-
`;
|
|
905
|
-
}
|
|
906
|
-
async function resolveInlineSkill(opts) {
|
|
907
|
-
const { posix: pathPosix } = await import("path");
|
|
908
|
-
const dirName = await stableInlineDirName(opts.skill.name);
|
|
909
|
-
const destPath = pathPosix.join(".agent", "skills", ".materialized", dirName);
|
|
910
|
-
await opts.sandbox.writeFiles({
|
|
911
|
-
destPath,
|
|
912
|
-
files: [
|
|
913
|
-
{
|
|
914
|
-
path: "SKILL.md",
|
|
915
|
-
content: buildSkillMarkdown(opts.skill)
|
|
916
|
-
}
|
|
917
|
-
]
|
|
918
|
-
});
|
|
919
|
-
return destPath;
|
|
920
|
-
}
|
|
921
|
-
|
|
922
|
-
// src/skills/resolve-remote.ts
|
|
923
|
-
function shellQuote(value) {
|
|
924
|
-
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
925
|
-
}
|
|
926
|
-
async function stableRepoDirName(skill) {
|
|
927
|
-
const { createHash } = await import("crypto");
|
|
928
|
-
const hashInput = `${skill.repo}::${skill.ref ?? "HEAD"}`;
|
|
929
|
-
const hash = createHash("sha1").update(hashInput).digest("hex").slice(0, 12);
|
|
930
|
-
return `git-${hash}`;
|
|
931
|
-
}
|
|
932
|
-
async function resolveRemoteSkill(opts) {
|
|
933
|
-
const { posix: pathPosix } = await import("path");
|
|
934
|
-
const dirName = await stableRepoDirName(opts.skill);
|
|
935
|
-
const cloneDir = pathPosix.join(".agent", "skills", ".materialized", dirName);
|
|
936
|
-
const quotedDir = shellQuote(cloneDir);
|
|
937
|
-
const quotedRepo = shellQuote(opts.skill.repo);
|
|
938
|
-
const quotedRef = shellQuote(opts.skill.ref ?? "HEAD");
|
|
939
|
-
const syncCommand = [
|
|
940
|
-
"set -euo pipefail",
|
|
941
|
-
`if [ ! -d ${quotedDir}/.git ]; then`,
|
|
942
|
-
` rm -rf ${quotedDir}`,
|
|
943
|
-
` mkdir -p ${quotedDir}`,
|
|
944
|
-
` git clone --depth 1 ${quotedRepo} ${quotedDir}`,
|
|
945
|
-
"fi",
|
|
946
|
-
`if [ ${quotedRef} != 'HEAD' ]; then`,
|
|
947
|
-
` git -C ${quotedDir} fetch --depth 1 origin ${quotedRef}`,
|
|
948
|
-
` git -C ${quotedDir} checkout FETCH_HEAD`,
|
|
949
|
-
"fi"
|
|
950
|
-
].join("\n");
|
|
951
|
-
const execResult = await opts.sandbox.exec({
|
|
952
|
-
command: "bash",
|
|
953
|
-
args: ["-lc", syncCommand]
|
|
954
|
-
});
|
|
955
|
-
const { exitCode, stderr } = await execResult.result;
|
|
956
|
-
if (exitCode !== 0) {
|
|
957
|
-
throw new Error(
|
|
958
|
-
`Failed to materialize git skill from ${opts.skill.repo}: ${stderr || "unknown error"}`
|
|
959
|
-
);
|
|
960
|
-
}
|
|
961
|
-
let resolvedDir = cloneDir;
|
|
962
|
-
if (opts.skill.path) {
|
|
963
|
-
resolvedDir = pathPosix.join(resolvedDir, opts.skill.path);
|
|
964
|
-
}
|
|
965
|
-
if (opts.skill.name) {
|
|
966
|
-
resolvedDir = pathPosix.join(resolvedDir, opts.skill.name);
|
|
967
|
-
}
|
|
968
|
-
return resolvedDir;
|
|
969
|
-
}
|
|
970
|
-
|
|
971
|
-
// src/skills/resolve.ts
|
|
972
|
-
async function resolveSkillInputsToSandboxDirs(opts) {
|
|
973
|
-
const baseLog = createLogger({
|
|
974
|
-
config: { ...opts.agent.options.logging, name: opts.agent.name },
|
|
975
|
-
subsystem: "skills"
|
|
976
|
-
});
|
|
977
|
-
const log2 = opts.sessionId ? baseLog.withContext({ sessionId: opts.sessionId }) : baseLog;
|
|
978
|
-
const entries = normalizeSkills(opts.skills);
|
|
979
|
-
const resolved = [];
|
|
980
|
-
for (const entry of entries) {
|
|
981
|
-
if (entry.type === "sandbox") {
|
|
982
|
-
resolved.push(entry.path);
|
|
983
|
-
continue;
|
|
984
|
-
}
|
|
985
|
-
if (entry.type === "host") {
|
|
986
|
-
resolved.push(
|
|
987
|
-
await resolveHostSkill({
|
|
988
|
-
sandbox: opts.sandbox,
|
|
989
|
-
skill: entry
|
|
990
|
-
})
|
|
991
|
-
);
|
|
992
|
-
continue;
|
|
993
|
-
}
|
|
994
|
-
if (entry.type === "git") {
|
|
995
|
-
resolved.push(
|
|
996
|
-
await resolveRemoteSkill({
|
|
997
|
-
sandbox: opts.sandbox,
|
|
998
|
-
skill: entry
|
|
999
|
-
})
|
|
1000
|
-
);
|
|
1001
|
-
continue;
|
|
1002
|
-
}
|
|
1003
|
-
if (entry.type === "inline") {
|
|
1004
|
-
resolved.push(
|
|
1005
|
-
await resolveInlineSkill({
|
|
1006
|
-
sandbox: opts.sandbox,
|
|
1007
|
-
skill: entry
|
|
1008
|
-
})
|
|
1009
|
-
);
|
|
1010
|
-
continue;
|
|
1011
|
-
}
|
|
1012
|
-
log2.warn("unknown skill source entry encountered", { entry });
|
|
1013
|
-
}
|
|
1014
|
-
return resolved;
|
|
1015
|
-
}
|
|
1016
|
-
|
|
1017
|
-
// src/tools/index.ts
|
|
1018
|
-
import {
|
|
1019
|
-
tool as tool3
|
|
1020
|
-
} from "ai";
|
|
1021
|
-
import { ulid as ulid2 } from "ulid";
|
|
1022
|
-
import { z as z2 } from "zod";
|
|
1023
|
-
|
|
1024
|
-
// src/tools/javascript.ts
|
|
1025
|
-
import { tool } from "ai";
|
|
1026
|
-
import { z } from "zod";
|
|
1027
|
-
var REQUEST_MARKER_START = "__TOOL_REQUEST__";
|
|
1028
|
-
var REQUEST_MARKER_END = "__TOOL_REQUEST_END__";
|
|
1029
|
-
var EXECUTION_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
1030
|
-
var RUNNER_SCRIPT = `
|
|
1031
|
-
import { readFileSync, existsSync, unlinkSync, mkdirSync } from 'node:fs';
|
|
1032
|
-
import { join, dirname } from 'node:path';
|
|
1033
|
-
import { fileURLToPath } from 'node:url';
|
|
1034
|
-
|
|
1035
|
-
const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url));
|
|
1036
|
-
const TOOL_CALL_TIMEOUT_MS = 300_000;
|
|
1037
|
-
|
|
1038
|
-
let reqCounter = 0;
|
|
1039
|
-
|
|
1040
|
-
async function callTool(name, input) {
|
|
1041
|
-
const id = 'req_' + (++reqCounter) + '_' + Date.now();
|
|
1042
|
-
const responseFile = join(SCRIPT_DIR, id + '.response.json');
|
|
1043
|
-
|
|
1044
|
-
const request = JSON.stringify({ id, tool: name, input });
|
|
1045
|
-
process.stderr.write('${REQUEST_MARKER_START}' + request + '${REQUEST_MARKER_END}' + '\\n');
|
|
1046
|
-
|
|
1047
|
-
const start = Date.now();
|
|
1048
|
-
while (!existsSync(responseFile)) {
|
|
1049
|
-
if (Date.now() - start > TOOL_CALL_TIMEOUT_MS) {
|
|
1050
|
-
throw new Error('Tool call ' + name + ' timed out waiting for response');
|
|
1051
|
-
}
|
|
1052
|
-
await new Promise(r => setTimeout(r, 30));
|
|
1053
|
-
}
|
|
1054
|
-
|
|
1055
|
-
let raw;
|
|
1056
|
-
try {
|
|
1057
|
-
raw = readFileSync(responseFile, 'utf8');
|
|
1058
|
-
} catch {
|
|
1059
|
-
await new Promise(r => setTimeout(r, 50));
|
|
1060
|
-
raw = readFileSync(responseFile, 'utf8');
|
|
1061
|
-
}
|
|
1062
|
-
|
|
1063
|
-
const response = JSON.parse(raw);
|
|
1064
|
-
try { unlinkSync(responseFile); } catch {}
|
|
1065
|
-
|
|
1066
|
-
if (response.error) {
|
|
1067
|
-
throw new Error(response.error);
|
|
1068
|
-
}
|
|
1069
|
-
return response.result;
|
|
1070
|
-
}
|
|
1071
|
-
|
|
1072
|
-
const code = readFileSync(join(SCRIPT_DIR, 'code.js'), 'utf8');
|
|
1073
|
-
const toolNames = JSON.parse(readFileSync(join(SCRIPT_DIR, 'tools.json'), 'utf8'));
|
|
1074
|
-
|
|
1075
|
-
const ctx = { tools: {} };
|
|
1076
|
-
for (const name of toolNames) {
|
|
1077
|
-
ctx.tools[name] = (input) => callTool(name, input);
|
|
1078
|
-
}
|
|
1079
|
-
|
|
1080
|
-
const logs = [];
|
|
1081
|
-
const customConsole = {
|
|
1082
|
-
log: (...args) => logs.push(args.map(a => typeof a === 'string' ? a : JSON.stringify(a)).join(' ')),
|
|
1083
|
-
error: (...args) => logs.push('[error] ' + args.map(a => typeof a === 'string' ? a : JSON.stringify(a)).join(' ')),
|
|
1084
|
-
warn: (...args) => logs.push('[warn] ' + args.map(a => typeof a === 'string' ? a : JSON.stringify(a)).join(' ')),
|
|
1085
|
-
};
|
|
1086
|
-
|
|
1087
|
-
try {
|
|
1088
|
-
const AsyncFunction = Object.getPrototypeOf(async function() {}).constructor;
|
|
1089
|
-
const fn = new AsyncFunction('ctx', 'console', code);
|
|
1090
|
-
const result = await fn(ctx, customConsole);
|
|
1091
|
-
|
|
1092
|
-
const output = { success: true, result: result !== undefined ? result : null };
|
|
1093
|
-
if (logs.length > 0) output.logs = logs;
|
|
1094
|
-
process.stdout.write(JSON.stringify(output));
|
|
1095
|
-
} catch (err) {
|
|
1096
|
-
const output = {
|
|
1097
|
-
success: false,
|
|
1098
|
-
error: err instanceof Error ? err.message : String(err),
|
|
1099
|
-
};
|
|
1100
|
-
if (logs.length > 0) output.logs = logs;
|
|
1101
|
-
process.stdout.write(JSON.stringify(output));
|
|
1102
|
-
}
|
|
1103
|
-
`;
|
|
1104
|
-
function extractJsonSchema(schema) {
|
|
1105
|
-
if (!schema || typeof schema !== "object") {
|
|
1106
|
-
return null;
|
|
1107
|
-
}
|
|
1108
|
-
if ("_def" in schema && typeof schema._def === "object") {
|
|
1109
|
-
try {
|
|
1110
|
-
return z.toJSONSchema(schema);
|
|
1111
|
-
} catch {
|
|
1112
|
-
return null;
|
|
1113
|
-
}
|
|
1114
|
-
}
|
|
1115
|
-
const s = schema;
|
|
1116
|
-
if (/* @__PURE__ */ Symbol.for("vercel.ai.schema") in s && "jsonSchema" in s) {
|
|
1117
|
-
return s.jsonSchema;
|
|
1118
|
-
}
|
|
1119
|
-
if ("type" in s || "properties" in s) {
|
|
1120
|
-
return s;
|
|
1121
|
-
}
|
|
1122
|
-
return null;
|
|
1123
|
-
}
|
|
1124
|
-
function jsonSchemaToTs(schema, indent = 0) {
|
|
1125
|
-
if (!schema) {
|
|
1126
|
-
return "unknown";
|
|
1127
|
-
}
|
|
1128
|
-
if (schema.enum && Array.isArray(schema.enum)) {
|
|
1129
|
-
return schema.enum.map((v) => JSON.stringify(v)).join(" | ");
|
|
1130
|
-
}
|
|
1131
|
-
if (schema.anyOf && Array.isArray(schema.anyOf)) {
|
|
1132
|
-
return schema.anyOf.map((s) => jsonSchemaToTs(s, indent)).join(" | ");
|
|
1133
|
-
}
|
|
1134
|
-
if (schema.oneOf && Array.isArray(schema.oneOf)) {
|
|
1135
|
-
return schema.oneOf.map((s) => jsonSchemaToTs(s, indent)).join(" | ");
|
|
1136
|
-
}
|
|
1137
|
-
const type = schema.type;
|
|
1138
|
-
switch (type) {
|
|
1139
|
-
case "string":
|
|
1140
|
-
return "string";
|
|
1141
|
-
case "number":
|
|
1142
|
-
case "integer":
|
|
1143
|
-
return "number";
|
|
1144
|
-
case "boolean":
|
|
1145
|
-
return "boolean";
|
|
1146
|
-
case "null":
|
|
1147
|
-
return "null";
|
|
1148
|
-
case "array": {
|
|
1149
|
-
const items = schema.items ? jsonSchemaToTs(schema.items, indent) : "unknown";
|
|
1150
|
-
return `Array<${items}>`;
|
|
1151
|
-
}
|
|
1152
|
-
case "object": {
|
|
1153
|
-
const properties = schema.properties;
|
|
1154
|
-
if (!properties) {
|
|
1155
|
-
return "Record<string, unknown>";
|
|
1156
|
-
}
|
|
1157
|
-
const required = new Set(schema.required || []);
|
|
1158
|
-
const pad = " ".repeat(indent + 1);
|
|
1159
|
-
const closePad = " ".repeat(indent);
|
|
1160
|
-
const props = Object.entries(properties).map(([key, value]) => {
|
|
1161
|
-
const opt = required.has(key) ? "" : "?";
|
|
1162
|
-
return `${pad}${key}${opt}: ${jsonSchemaToTs(value, indent + 1)}`;
|
|
1163
|
-
});
|
|
1164
|
-
return `{
|
|
1165
|
-
${props.join(";\n")};
|
|
1166
|
-
${closePad}}`;
|
|
1167
|
-
}
|
|
1168
|
-
default:
|
|
1169
|
-
return "unknown";
|
|
1170
|
-
}
|
|
1171
|
-
}
|
|
1172
|
-
function generateContextTypeString(tools) {
|
|
1173
|
-
const sigs = [];
|
|
1174
|
-
for (const [name, t] of Object.entries(tools)) {
|
|
1175
|
-
const raw = t;
|
|
1176
|
-
const inputSchema = extractJsonSchema(raw.inputSchema ?? raw.parameters);
|
|
1177
|
-
const outputSchema = extractJsonSchema(raw.outputSchema);
|
|
1178
|
-
const inputType = inputSchema ? jsonSchemaToTs(inputSchema, 2) : "{}";
|
|
1179
|
-
const outputType = outputSchema ? jsonSchemaToTs(outputSchema, 2) : "unknown";
|
|
1180
|
-
sigs.push(` ${name}(input: ${inputType}): Promise<${outputType}>`);
|
|
1181
|
-
}
|
|
1182
|
-
return `type Context = {
|
|
1183
|
-
tools: {
|
|
1184
|
-
${sigs.join(";\n")};
|
|
1185
|
-
}
|
|
1186
|
-
}`;
|
|
1187
|
-
}
|
|
1188
|
-
async function executeInSandbox({
|
|
1189
|
-
code,
|
|
1190
|
-
rpcDir,
|
|
1191
|
-
abortController,
|
|
1192
|
-
sandbox,
|
|
1193
|
-
availableTools,
|
|
1194
|
-
onSubToolCall,
|
|
1195
|
-
toolContext
|
|
1196
|
-
}) {
|
|
1197
|
-
const mkdirResult = await sandbox.exec({
|
|
1198
|
-
command: "mkdir",
|
|
1199
|
-
args: ["-p", rpcDir]
|
|
1200
|
-
});
|
|
1201
|
-
if (mkdirResult instanceof Error) {
|
|
1202
|
-
return { success: false, error: mkdirResult.message };
|
|
1203
|
-
}
|
|
1204
|
-
await mkdirResult.result;
|
|
1205
|
-
await sandbox.writeFiles({
|
|
1206
|
-
files: [
|
|
1207
|
-
{ path: "runner.mjs", content: RUNNER_SCRIPT },
|
|
1208
|
-
{ path: "code.js", content: code },
|
|
1209
|
-
{
|
|
1210
|
-
path: "tools.json",
|
|
1211
|
-
content: JSON.stringify(Object.keys(availableTools))
|
|
1212
|
-
}
|
|
1213
|
-
],
|
|
1214
|
-
destPath: rpcDir
|
|
1215
|
-
});
|
|
1216
|
-
const nodeMajor = Number.parseInt(process.versions.node.split(".")[0], 10);
|
|
1217
|
-
const permissionFlag = nodeMajor >= 22 ? "--permission" : "--experimental-permission";
|
|
1218
|
-
const execResult = await sandbox.exec({
|
|
1219
|
-
command: "node",
|
|
1220
|
-
args: [
|
|
1221
|
-
permissionFlag,
|
|
1222
|
-
`--allow-fs-read=${rpcDir}`,
|
|
1223
|
-
`--allow-fs-write=${rpcDir}`,
|
|
1224
|
-
`${rpcDir}/runner.mjs`
|
|
1225
|
-
],
|
|
1226
|
-
signal: abortController.signal
|
|
1227
|
-
});
|
|
1228
|
-
if (execResult instanceof Error) {
|
|
1229
|
-
return { success: false, error: execResult.message };
|
|
1230
|
-
}
|
|
1231
|
-
const fatal = { error: null };
|
|
1232
|
-
const abort = (error) => {
|
|
1233
|
-
if (!fatal.error) {
|
|
1234
|
-
fatal.error = error;
|
|
1235
|
-
abortController.abort();
|
|
1236
|
-
}
|
|
1237
|
-
};
|
|
1238
|
-
const handleToolRequest = async (requestJson) => {
|
|
1239
|
-
let parsed;
|
|
1240
|
-
try {
|
|
1241
|
-
parsed = JSON.parse(requestJson);
|
|
1242
|
-
} catch {
|
|
1243
|
-
return;
|
|
1244
|
-
}
|
|
1245
|
-
const { id, tool: toolName, input } = parsed;
|
|
1246
|
-
let response;
|
|
1247
|
-
try {
|
|
1248
|
-
const t = availableTools[toolName];
|
|
1249
|
-
if (!t?.execute) {
|
|
1250
|
-
throw new Error(
|
|
1251
|
-
`Tool ${toolName} not found or has no execute function`
|
|
1252
|
-
);
|
|
1253
|
-
}
|
|
1254
|
-
const exec2 = t.execute.bind(t);
|
|
1255
|
-
const execOptions = {
|
|
1256
|
-
toolCallId: `js_${toolName}_${Date.now()}`,
|
|
1257
|
-
messages: [],
|
|
1258
|
-
experimental_context: toolContext
|
|
1259
|
-
};
|
|
1260
|
-
if (onSubToolCall) {
|
|
1261
|
-
response = await onSubToolCall(
|
|
1262
|
-
toolName,
|
|
1263
|
-
input,
|
|
1264
|
-
() => exec2(input, execOptions)
|
|
1265
|
-
);
|
|
1266
|
-
} else {
|
|
1267
|
-
const result = await exec2(input, execOptions);
|
|
1268
|
-
response = { result };
|
|
1269
|
-
}
|
|
1270
|
-
} catch (err) {
|
|
1271
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1272
|
-
response = { error: msg };
|
|
1273
|
-
}
|
|
1274
|
-
try {
|
|
1275
|
-
await sandbox.writeFiles({
|
|
1276
|
-
files: [
|
|
1277
|
-
{
|
|
1278
|
-
path: `${id}.response.json`,
|
|
1279
|
-
content: JSON.stringify(response)
|
|
1280
|
-
}
|
|
1281
|
-
],
|
|
1282
|
-
destPath: rpcDir
|
|
1283
|
-
});
|
|
1284
|
-
} catch (err) {
|
|
1285
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1286
|
-
abort(new Error(`Failed to write RPC response for ${toolName}: ${msg}`));
|
|
1287
|
-
}
|
|
1288
|
-
};
|
|
1289
|
-
const toolCallPromises = [];
|
|
1290
|
-
let stderrBuffer = "";
|
|
1291
|
-
let nonMarkerStderr = "";
|
|
1292
|
-
const timeout = setTimeout(() => {
|
|
1293
|
-
abort(
|
|
1294
|
-
new Error(
|
|
1295
|
-
`JavaScript execution timed out after ${EXECUTION_TIMEOUT_MS / 1e3}s`
|
|
1296
|
-
)
|
|
1297
|
-
);
|
|
1298
|
-
}, EXECUTION_TIMEOUT_MS);
|
|
1299
|
-
try {
|
|
1300
|
-
for await (const entry of execResult.logs()) {
|
|
1301
|
-
if (fatal.error) {
|
|
1302
|
-
break;
|
|
1303
|
-
}
|
|
1304
|
-
if (entry.stream === "stderr") {
|
|
1305
|
-
stderrBuffer += entry.data;
|
|
1306
|
-
while (true) {
|
|
1307
|
-
const startIdx = stderrBuffer.indexOf(REQUEST_MARKER_START);
|
|
1308
|
-
if (startIdx === -1) {
|
|
1309
|
-
break;
|
|
1310
|
-
}
|
|
1311
|
-
const beforeMarker = stderrBuffer.slice(0, startIdx);
|
|
1312
|
-
if (beforeMarker.trim()) {
|
|
1313
|
-
nonMarkerStderr += beforeMarker;
|
|
1314
|
-
}
|
|
1315
|
-
const contentStart = startIdx + REQUEST_MARKER_START.length;
|
|
1316
|
-
const endIdx = stderrBuffer.indexOf(REQUEST_MARKER_END, contentStart);
|
|
1317
|
-
if (endIdx === -1) {
|
|
1318
|
-
break;
|
|
1319
|
-
}
|
|
1320
|
-
const requestJson = stderrBuffer.slice(contentStart, endIdx);
|
|
1321
|
-
stderrBuffer = stderrBuffer.slice(endIdx + REQUEST_MARKER_END.length);
|
|
1322
|
-
toolCallPromises.push(handleToolRequest(requestJson));
|
|
1323
|
-
}
|
|
1324
|
-
}
|
|
1325
|
-
}
|
|
1326
|
-
} finally {
|
|
1327
|
-
clearTimeout(timeout);
|
|
1328
|
-
}
|
|
1329
|
-
if (stderrBuffer.trim()) {
|
|
1330
|
-
nonMarkerStderr += stderrBuffer;
|
|
1331
|
-
}
|
|
1332
|
-
await Promise.allSettled(toolCallPromises);
|
|
1333
|
-
if (fatal.error) {
|
|
1334
|
-
execResult.result.catch(() => void 0);
|
|
1335
|
-
return {
|
|
1336
|
-
success: false,
|
|
1337
|
-
error: fatal.error.message,
|
|
1338
|
-
...nonMarkerStderr ? { stderr: nonMarkerStderr.slice(0, 2e3) } : {}
|
|
1339
|
-
};
|
|
1340
|
-
}
|
|
1341
|
-
const { stdout, stderr, exitCode } = await execResult.result;
|
|
1342
|
-
try {
|
|
1343
|
-
return JSON.parse(stdout);
|
|
1344
|
-
} catch {
|
|
1345
|
-
return {
|
|
1346
|
-
success: false,
|
|
1347
|
-
error: `Runner failed (exit ${exitCode}).`,
|
|
1348
|
-
stderr: (nonMarkerStderr + stderr).slice(0, 2e3),
|
|
1349
|
-
stdout: stdout.slice(0, 1e3)
|
|
1350
|
-
};
|
|
1351
|
-
}
|
|
1352
|
-
}
|
|
1353
|
-
function createJavaScriptTool(opts) {
|
|
1354
|
-
const { sandbox, onSubToolCall } = opts;
|
|
1355
|
-
const activeSet = opts.activeTools ? new Set(opts.activeTools) : null;
|
|
1356
|
-
const availableTools = {};
|
|
1357
|
-
for (const [name, t] of Object.entries(opts.tools)) {
|
|
1358
|
-
if (!activeSet || activeSet.has(name)) {
|
|
1359
|
-
availableTools[name] = t;
|
|
1360
|
-
}
|
|
1361
|
-
}
|
|
1362
|
-
const contextType = generateContextTypeString(availableTools);
|
|
1363
|
-
return tool({
|
|
1364
|
-
...builtInTools.JavaScript,
|
|
1365
|
-
description: `Execute JavaScript to orchestrate multiple tool calls in a single step. Use this when you need to run several tools in sequence, transform intermediate results, or parallelize independent operations with Promise.all.
|
|
1366
|
-
|
|
1367
|
-
The code runs as an async function body with \`ctx\` in scope:
|
|
1368
|
-
|
|
1369
|
-
\`\`\`typescript
|
|
1370
|
-
${contextType}
|
|
1371
|
-
\`\`\`
|
|
1372
|
-
|
|
1373
|
-
Examples:
|
|
1374
|
-
- Sequential: \`const file = await ctx.tools.Read({ path: "package.json" }); return JSON.parse(file.content);\`
|
|
1375
|
-
- Parallel: \`const [a, b] = await Promise.all([ctx.tools.Read({ path: "a.ts" }), ctx.tools.Read({ path: "b.ts" })]); return { a: a.content, b: b.content };\`
|
|
1376
|
-
- Transform: \`const grep = await ctx.tools.Grep({ pattern: "TODO" }); return grep.matches.split("\\n").length;\`
|
|
1377
|
-
- Bash: \`const r = await ctx.tools.Bash({ command: "node -e \\"console.log(JSON.stringify({v:1}))\\"" }); return JSON.parse(r.stdout);\`
|
|
1378
|
-
|
|
1379
|
-
Return a value to pass results back. Use console.log() for debug output.
|
|
1380
|
-
Important: Each tool returns a structured object matching its output schema \u2014 not a raw string. Access the specific field you need (e.g. Bash's result.stdout, Read's result.content) rather than trying to parse the entire result.`,
|
|
1381
|
-
execute: ({ code }) => {
|
|
1382
|
-
const runId = `run_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
1383
|
-
const rpcDir = `.agent/js-rpc/${runId}`;
|
|
1384
|
-
const abortController = new AbortController();
|
|
1385
|
-
return executeInSandbox({
|
|
1386
|
-
code,
|
|
1387
|
-
rpcDir,
|
|
1388
|
-
abortController,
|
|
1389
|
-
sandbox,
|
|
1390
|
-
availableTools,
|
|
1391
|
-
onSubToolCall,
|
|
1392
|
-
toolContext: opts.toolContext
|
|
1393
|
-
});
|
|
1394
|
-
}
|
|
1395
|
-
});
|
|
1396
|
-
}
|
|
1397
|
-
|
|
1398
|
-
// src/tools/needs-approval.ts
|
|
1399
|
-
var builtinNeedsApproval = {};
|
|
1400
|
-
async function checkNeedsApproval({
|
|
1401
|
-
agent: agent2,
|
|
1402
|
-
toolName,
|
|
1403
|
-
input,
|
|
1404
|
-
toolCallId,
|
|
1405
|
-
messages
|
|
1406
|
-
}) {
|
|
1407
|
-
const toolDef = agent2.options.tools?.[toolName];
|
|
1408
|
-
if (toolDef?.needsApproval != null) {
|
|
1409
|
-
if (typeof toolDef.needsApproval === "boolean") {
|
|
1410
|
-
return toolDef.needsApproval;
|
|
1411
|
-
}
|
|
1412
|
-
return await toolDef.needsApproval(input, {
|
|
1413
|
-
toolCallId,
|
|
1414
|
-
messages,
|
|
1415
|
-
experimental_context: void 0
|
|
1416
|
-
});
|
|
1417
|
-
}
|
|
1418
|
-
const agentEntry = agent2.options.needsApproval?.[toolName];
|
|
1419
|
-
if (agentEntry != null) {
|
|
1420
|
-
if (typeof agentEntry === "boolean") {
|
|
1421
|
-
return agentEntry;
|
|
1422
|
-
}
|
|
1423
|
-
return await agentEntry(input, {
|
|
1424
|
-
toolCallId,
|
|
1425
|
-
messages,
|
|
1426
|
-
experimental_context: void 0
|
|
1427
|
-
});
|
|
1428
|
-
}
|
|
1429
|
-
return builtinNeedsApproval[toolName] ?? false;
|
|
1430
|
-
}
|
|
1431
|
-
|
|
1432
|
-
// src/tools/tool.ts
|
|
1433
|
-
import {
|
|
1434
|
-
tool as aiTool
|
|
1435
|
-
} from "ai";
|
|
1436
|
-
function tool2(def) {
|
|
1437
|
-
const { execute, contextSchema, stateSchema, ...rest } = def;
|
|
1438
|
-
const wrappedExecute = execute ? (
|
|
1439
|
-
// biome-ignore lint/suspicious/noExplicitAny: input type erased at runtime
|
|
1440
|
-
(input, options) => {
|
|
1441
|
-
const ctx = options.experimental_context;
|
|
1442
|
-
const context = contextSchema ? contextSchema.parse(ctx.context) : ctx.context;
|
|
1443
|
-
if (stateSchema) {
|
|
1444
|
-
stateSchema.parse(ctx.state);
|
|
1445
|
-
}
|
|
1446
|
-
const state = ctx.state;
|
|
1447
|
-
return execute(input, {
|
|
1448
|
-
toolCallId: options.toolCallId,
|
|
1449
|
-
abortSignal: options.abortSignal,
|
|
1450
|
-
context,
|
|
1451
|
-
state,
|
|
1452
|
-
sessionId: ctx.sessionId,
|
|
1453
|
-
messages: ctx.messages,
|
|
1454
|
-
sandbox: ctx.sandbox
|
|
1455
|
-
});
|
|
1456
|
-
}
|
|
1457
|
-
) : void 0;
|
|
1458
|
-
return wrappedExecute ? aiTool({ ...rest, execute: wrappedExecute }) : (
|
|
1459
|
-
// biome-ignore lint/suspicious/noExplicitAny: no-execute path needs cast
|
|
1460
|
-
aiTool(rest)
|
|
1461
|
-
);
|
|
1462
|
-
}
|
|
1463
|
-
|
|
1464
|
-
// src/tools/index.ts
|
|
1465
|
-
var log = createLogger({ config: { name: "tools" }, subsystem: "tools" });
|
|
1466
|
-
function formatFileSize(bytes) {
|
|
1467
|
-
if (bytes < 1024) {
|
|
1468
|
-
return `${bytes}`;
|
|
1469
|
-
}
|
|
1470
|
-
if (bytes < 1024 * 1024) {
|
|
1471
|
-
return `${(bytes / 1024).toFixed(1)}K`;
|
|
1472
|
-
}
|
|
1473
|
-
if (bytes < 1024 * 1024 * 1024) {
|
|
1474
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)}M`;
|
|
1475
|
-
}
|
|
1476
|
-
return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)}G`;
|
|
1477
|
-
}
|
|
1478
|
-
function isRgNotFoundError(err) {
|
|
1479
|
-
const parts = [err.message];
|
|
1480
|
-
const anyErr = err;
|
|
1481
|
-
if (typeof anyErr.reason === "string") {
|
|
1482
|
-
parts.push(anyErr.reason);
|
|
1483
|
-
}
|
|
1484
|
-
if (anyErr.cause instanceof Error) {
|
|
1485
|
-
parts.push(anyErr.cause.message);
|
|
1486
|
-
const anyCause = anyErr.cause;
|
|
1487
|
-
if (typeof anyCause.text === "string") {
|
|
1488
|
-
parts.push(anyCause.text);
|
|
1489
|
-
}
|
|
1490
|
-
}
|
|
1491
|
-
const msg = parts.join(" ").toLowerCase();
|
|
1492
|
-
return msg.includes("executable file not found") || msg.includes("executable_not_found") || msg.includes("enoent") && msg.includes("rg");
|
|
1493
|
-
}
|
|
1494
|
-
var builtInTools = {
|
|
1495
|
-
Read: tool3({
|
|
1496
|
-
description: "Reads a file and returns its contents with metadata. For files over 200 lines, automatically shows first 100 lines unless a specific line range is provided. Use startLine and endLine parameters to read specific portions of large files.",
|
|
1497
|
-
inputSchema: z2.object({
|
|
1498
|
-
label: z2.string().describe("A label that describes the action being performed"),
|
|
1499
|
-
path: z2.string().describe("Absolute path to the file"),
|
|
1500
|
-
startLine: z2.number().optional().describe(
|
|
1501
|
-
"Starting line number (1-indexed). If provided with endLine, reads exact range regardless of file size."
|
|
1502
|
-
),
|
|
1503
|
-
endLine: z2.number().optional().describe(
|
|
1504
|
-
"Ending line number (1-indexed, inclusive). If provided with startLine, reads exact range regardless of file size."
|
|
1505
|
-
)
|
|
1506
|
-
}),
|
|
1507
|
-
outputSchema: z2.object({
|
|
1508
|
-
content: z2.string().describe("File content"),
|
|
1509
|
-
metadata: z2.object({
|
|
1510
|
-
totalLines: z2.number().describe("Total number of lines in the file"),
|
|
1511
|
-
linesShown: z2.number().describe("Number of lines included in this response"),
|
|
1512
|
-
startLine: z2.number().describe("First line number shown (1-indexed)"),
|
|
1513
|
-
endLine: z2.number().describe("Last line number shown (1-indexed)"),
|
|
1514
|
-
isPaginated: z2.boolean().describe("Whether this is a partial view of the file"),
|
|
1515
|
-
fileSize: z2.string().describe("Human-readable file size (e.g., '2.5K', '1.2M')"),
|
|
1516
|
-
path: z2.string().describe("Absolute path to the file")
|
|
1517
|
-
})
|
|
1518
|
-
})
|
|
1519
|
-
}),
|
|
1520
|
-
Grep: tool3({
|
|
1521
|
-
description: "Search for patterns in files using ripgrep. Use this to find code patterns, function definitions, imports, etc.",
|
|
1522
|
-
inputSchema: z2.object({
|
|
1523
|
-
label: z2.string().describe("A label that describes the action being performed"),
|
|
1524
|
-
pattern: z2.string().describe("Regex pattern to search for (ripgrep syntax)"),
|
|
1525
|
-
path: z2.string().optional().describe(
|
|
1526
|
-
"Absolute path to search in (defaults to working directory). Can be a file or directory."
|
|
1527
|
-
),
|
|
1528
|
-
fileType: z2.string().optional().describe(
|
|
1529
|
-
"File type to filter by (e.g., 'ts', 'js', 'py', 'md'). Uses ripgrep's built-in type filters."
|
|
1530
|
-
),
|
|
1531
|
-
glob: z2.string().optional().describe(
|
|
1532
|
-
"Glob pattern to filter files (e.g., '*.tsx', 'src/**/*.ts')"
|
|
1533
|
-
),
|
|
1534
|
-
caseSensitive: z2.boolean().optional().default(true).describe("Whether search is case-sensitive (default: true)"),
|
|
1535
|
-
contextLines: z2.number().optional().describe(
|
|
1536
|
-
"Number of context lines to show before and after each match"
|
|
1537
|
-
),
|
|
1538
|
-
maxCount: z2.number().optional().describe(
|
|
1539
|
-
"Maximum number of matches per file (useful for limiting output)"
|
|
1540
|
-
),
|
|
1541
|
-
filesWithMatches: z2.boolean().optional().default(false).describe(
|
|
1542
|
-
"Only show file paths that contain matches, not the matching lines themselves"
|
|
1543
|
-
)
|
|
1544
|
-
}),
|
|
1545
|
-
outputSchema: z2.object({
|
|
1546
|
-
matches: z2.string().describe(
|
|
1547
|
-
"Search results with file paths, line numbers, and matching content"
|
|
1548
|
-
),
|
|
1549
|
-
summary: z2.object({
|
|
1550
|
-
matchCount: z2.number().describe("Number of matches found"),
|
|
1551
|
-
fileCount: z2.number().describe("Number of files containing matches"),
|
|
1552
|
-
searchPath: z2.string().describe("Path that was searched"),
|
|
1553
|
-
pattern: z2.string().describe("Pattern that was searched for")
|
|
1554
|
-
})
|
|
1555
|
-
})
|
|
1556
|
-
}),
|
|
1557
|
-
List: tool3({
|
|
1558
|
-
description: "Recursively list directory contents. Use this to understand the codebase structure, find files, or explore directories. Control depth to balance detail vs. overview. Depth 1 shows immediate children, depth 2 includes subdirectories, etc.",
|
|
1559
|
-
inputSchema: z2.object({
|
|
1560
|
-
label: z2.string().describe("A label that describes the action being performed"),
|
|
1561
|
-
path: z2.string().optional().describe("Absolute path to list (defaults to working directory)"),
|
|
1562
|
-
depth: z2.number().optional().describe(
|
|
1563
|
-
"Maximum depth to traverse. Choose based on context: 1-2 for quick overview, 3-4 for detailed exploration, 5+ for comprehensive mapping"
|
|
1564
|
-
),
|
|
1565
|
-
includeHidden: z2.boolean().optional().default(false).describe(
|
|
1566
|
-
"Include hidden files and directories (those starting with '.')"
|
|
1567
|
-
),
|
|
1568
|
-
filesOnly: z2.boolean().optional().default(false).describe("Only show files, not directories"),
|
|
1569
|
-
pattern: z2.string().optional().describe("Glob pattern to filter results (e.g., '*.ts', '*test*')")
|
|
1570
|
-
}),
|
|
1571
|
-
outputSchema: z2.object({
|
|
1572
|
-
listing: z2.string().describe(
|
|
1573
|
-
"Directory tree listing showing paths relative to search root"
|
|
1574
|
-
),
|
|
1575
|
-
summary: z2.object({
|
|
1576
|
-
totalItems: z2.number().describe("Total number of items found"),
|
|
1577
|
-
totalFiles: z2.number().describe("Total number of files found"),
|
|
1578
|
-
totalDirs: z2.number().describe("Total number of directories found"),
|
|
1579
|
-
searchPath: z2.string().describe("Path that was listed"),
|
|
1580
|
-
depth: z2.number().optional().describe("Maximum depth used (if specified)")
|
|
1581
|
-
})
|
|
1582
|
-
})
|
|
1583
|
-
}),
|
|
1584
|
-
Write: tool3({
|
|
1585
|
-
description: "Write content to a file. Creates parent directories automatically. Overwrites existing files.",
|
|
1586
|
-
inputSchema: z2.object({
|
|
1587
|
-
label: z2.string().describe("A label that describes the action being performed"),
|
|
1588
|
-
path: z2.string().describe("Absolute path to the file"),
|
|
1589
|
-
content: z2.string().describe("Content to write to the file")
|
|
1590
|
-
}),
|
|
1591
|
-
outputSchema: z2.object({
|
|
1592
|
-
success: z2.boolean().describe("Whether the write succeeded"),
|
|
1593
|
-
path: z2.string().describe("Path to the written file"),
|
|
1594
|
-
bytesWritten: z2.number().describe("Number of bytes written"),
|
|
1595
|
-
error: z2.string().optional().describe("Error message if write failed")
|
|
1596
|
-
})
|
|
1597
|
-
}),
|
|
1598
|
-
Edit: tool3({
|
|
1599
|
-
description: "Edit a file by replacing an exact string. Fails if old_string is not found or appears multiple times (not unique). For multiple replacements, call this tool multiple times with unique context.",
|
|
1600
|
-
inputSchema: z2.object({
|
|
1601
|
-
label: z2.string().describe("A label that describes the action being performed"),
|
|
1602
|
-
path: z2.string().describe("Absolute path to the file"),
|
|
1603
|
-
old_string: z2.string().describe("Exact string to find and replace (must be unique in file)"),
|
|
1604
|
-
new_string: z2.string().describe("String to replace old_string with")
|
|
1605
|
-
}),
|
|
1606
|
-
outputSchema: z2.object({
|
|
1607
|
-
success: z2.boolean().describe("Whether the edit succeeded"),
|
|
1608
|
-
path: z2.string().describe("Path to the edited file"),
|
|
1609
|
-
error: z2.string().optional().describe("Error message if edit failed")
|
|
1610
|
-
})
|
|
1611
|
-
}),
|
|
1612
|
-
Bash: tool3({
|
|
1613
|
-
description: "Executes a bash command. Returns stdout and stderr separately. Use waitUntil to control how long to wait (0 = return immediately, process keeps running). Large outputs are tail-truncated; full output in outputDir.",
|
|
1614
|
-
inputSchema: z2.object({
|
|
1615
|
-
label: z2.string().describe("A label that describes the action being performed"),
|
|
1616
|
-
command: z2.string().describe("The shell command to execute"),
|
|
1617
|
-
waitUntil: z2.number().optional().describe(
|
|
1618
|
-
`Max ms to wait for completion (default: ${DEFAULT_WAIT_UNTIL}). Use 0 to return immediately while the process keeps running.`
|
|
1619
|
-
)
|
|
1620
|
-
}),
|
|
1621
|
-
outputSchema: z2.object({
|
|
1622
|
-
commandId: z2.string().describe("Command ID. Use to reference or kill running processes."),
|
|
1623
|
-
stdout: z2.string().describe(
|
|
1624
|
-
"Command stdout. Tail-truncated if large; full content in outputDir/stdout.txt."
|
|
1625
|
-
),
|
|
1626
|
-
stderr: z2.string().describe(
|
|
1627
|
-
"Command stderr. Tail-truncated if large; full content in outputDir/stderr.txt."
|
|
1628
|
-
),
|
|
1629
|
-
exitCode: z2.number().describe("Exit code (-1 if still running)"),
|
|
1630
|
-
status: z2.enum(["running", "completed", "failed"]).describe("Process status"),
|
|
1631
|
-
outputDir: z2.string().describe(
|
|
1632
|
-
"Path to output directory containing stdout.txt, stderr.txt, and metadata.json. Empty if still running."
|
|
1633
|
-
)
|
|
1634
|
-
})
|
|
1635
|
-
}),
|
|
1636
|
-
Skill: tool3({
|
|
1637
|
-
description: "Load a skill's full instructions by name. Call this before following a skill.",
|
|
1638
|
-
inputSchema: z2.object({
|
|
1639
|
-
label: z2.string().describe("A label that describes the action being performed"),
|
|
1640
|
-
name: z2.string().describe("Skill name from the Available Skills list")
|
|
1641
|
-
}),
|
|
1642
|
-
outputSchema: z2.object({
|
|
1643
|
-
name: z2.string(),
|
|
1644
|
-
description: z2.string(),
|
|
1645
|
-
content: z2.string().describe("Full SKILL.md content"),
|
|
1646
|
-
path: z2.string().describe("Path to the skill directory in the sandbox")
|
|
1647
|
-
})
|
|
1648
|
-
}),
|
|
1649
|
-
JavaScript: tool3({
|
|
1650
|
-
inputSchema: z2.object({
|
|
1651
|
-
label: z2.string().describe("A label that describes the action being performed"),
|
|
1652
|
-
code: z2.string().describe(
|
|
1653
|
-
"JavaScript async function body. `ctx` is in scope. Must use `return` to produce output."
|
|
1654
|
-
)
|
|
1655
|
-
})
|
|
1656
|
-
})
|
|
1657
|
-
};
|
|
1658
|
-
var builtinToolNames = Object.fromEntries(
|
|
1659
|
-
Object.entries(builtInTools).map(([name]) => [name, name])
|
|
1660
|
-
);
|
|
1661
|
-
var SKILL_MD_SUFFIX = /\/?SKILL\.md$/;
|
|
1662
|
-
function getTools({
|
|
1663
|
-
agent: agent2,
|
|
1664
|
-
sandbox,
|
|
1665
|
-
skillsRef,
|
|
1666
|
-
writer,
|
|
1667
|
-
abortController,
|
|
1668
|
-
nextPartIndexRef,
|
|
1669
|
-
assistantMessageId,
|
|
1670
|
-
sessionId,
|
|
1671
|
-
stepLog,
|
|
1672
|
-
context,
|
|
1673
|
-
state,
|
|
1674
|
-
messages,
|
|
1675
|
-
activeTools
|
|
1676
|
-
}) {
|
|
1677
|
-
const rawTools = {
|
|
1678
|
-
[builtinToolNames.Read]: tool3({
|
|
1679
|
-
...builtInTools.Read,
|
|
1680
|
-
execute: async ({ path, startLine, endLine }) => {
|
|
1681
|
-
const filePath = path;
|
|
1682
|
-
const result = await sandbox.readFile({ path: filePath });
|
|
1683
|
-
if (result instanceof Error) {
|
|
1684
|
-
log.error("Read failed", { error: result.message });
|
|
1685
|
-
throw result;
|
|
1686
|
-
}
|
|
1687
|
-
if (result === null) {
|
|
1688
|
-
return {
|
|
1689
|
-
content: `Error: File not found - ${filePath}`,
|
|
1690
|
-
metadata: {
|
|
1691
|
-
totalLines: 0,
|
|
1692
|
-
linesShown: 0,
|
|
1693
|
-
startLine: 0,
|
|
1694
|
-
endLine: 0,
|
|
1695
|
-
isPaginated: false,
|
|
1696
|
-
fileSize: "0",
|
|
1697
|
-
path: filePath
|
|
1698
|
-
}
|
|
1699
|
-
};
|
|
1700
|
-
}
|
|
1701
|
-
const fullContent = result.toString("utf-8");
|
|
1702
|
-
const lines = fullContent.split("\n");
|
|
1703
|
-
if (lines.length > 0 && lines.at(-1) === "") {
|
|
1704
|
-
lines.pop();
|
|
1705
|
-
}
|
|
1706
|
-
const totalLines = lines.length;
|
|
1707
|
-
const fileBytes = Buffer.byteLength(fullContent);
|
|
1708
|
-
const fileSize = formatFileSize(fileBytes);
|
|
1709
|
-
const PAGE_SIZE = 100;
|
|
1710
|
-
let actualStart;
|
|
1711
|
-
let actualEnd;
|
|
1712
|
-
if (startLine !== void 0 && endLine !== void 0) {
|
|
1713
|
-
actualStart = startLine;
|
|
1714
|
-
actualEnd = endLine;
|
|
1715
|
-
} else if (startLine !== void 0) {
|
|
1716
|
-
actualStart = startLine;
|
|
1717
|
-
actualEnd = Math.min(startLine + PAGE_SIZE - 1, totalLines);
|
|
1718
|
-
} else if (endLine !== void 0) {
|
|
1719
|
-
actualStart = 1;
|
|
1720
|
-
actualEnd = endLine;
|
|
1721
|
-
} else if (totalLines > 200) {
|
|
1722
|
-
actualStart = 1;
|
|
1723
|
-
actualEnd = PAGE_SIZE;
|
|
1724
|
-
} else {
|
|
1725
|
-
actualStart = 1;
|
|
1726
|
-
actualEnd = totalLines;
|
|
1727
|
-
}
|
|
1728
|
-
const slicedLines = lines.slice(actualStart - 1, actualEnd);
|
|
1729
|
-
const content = slicedLines.join("\n");
|
|
1730
|
-
return {
|
|
1731
|
-
metadata: {
|
|
1732
|
-
totalLines,
|
|
1733
|
-
linesShown: Math.max(0, actualEnd - actualStart + 1),
|
|
1734
|
-
startLine: actualStart,
|
|
1735
|
-
endLine: actualEnd,
|
|
1736
|
-
isPaginated: actualEnd < totalLines,
|
|
1737
|
-
fileSize,
|
|
1738
|
-
path: filePath
|
|
1739
|
-
},
|
|
1740
|
-
content
|
|
1741
|
-
};
|
|
1742
|
-
}
|
|
1743
|
-
}),
|
|
1744
|
-
[builtinToolNames.Grep]: tool3({
|
|
1745
|
-
...builtInTools.Grep,
|
|
1746
|
-
execute: async ({
|
|
1747
|
-
pattern,
|
|
1748
|
-
path,
|
|
1749
|
-
fileType,
|
|
1750
|
-
glob,
|
|
1751
|
-
caseSensitive,
|
|
1752
|
-
contextLines,
|
|
1753
|
-
maxCount,
|
|
1754
|
-
filesWithMatches
|
|
1755
|
-
}) => {
|
|
1756
|
-
const searchPath = path ?? ".";
|
|
1757
|
-
const args = [];
|
|
1758
|
-
args.push("--line-number");
|
|
1759
|
-
args.push("--heading");
|
|
1760
|
-
args.push("--color", "never");
|
|
1761
|
-
if (!caseSensitive) {
|
|
1762
|
-
args.push("-i");
|
|
1763
|
-
}
|
|
1764
|
-
if (fileType) {
|
|
1765
|
-
args.push("--type", fileType);
|
|
1766
|
-
}
|
|
1767
|
-
if (glob) {
|
|
1768
|
-
args.push("--glob", glob);
|
|
1769
|
-
}
|
|
1770
|
-
if (contextLines !== void 0) {
|
|
1771
|
-
args.push("-C", String(contextLines));
|
|
1772
|
-
}
|
|
1773
|
-
if (maxCount !== void 0) {
|
|
1774
|
-
args.push("--max-count", String(maxCount));
|
|
1775
|
-
}
|
|
1776
|
-
if (filesWithMatches) {
|
|
1777
|
-
args.push("--files-with-matches");
|
|
1778
|
-
}
|
|
1779
|
-
args.push("--", pattern, searchPath);
|
|
1780
|
-
let result = await sandbox.exec({ command: "rg", args });
|
|
1781
|
-
if (result instanceof Error && isRgNotFoundError(result)) {
|
|
1782
|
-
log.warn("rg not found, installing ripgrep");
|
|
1783
|
-
const installResult = await sandbox.exec({
|
|
1784
|
-
command: "bash",
|
|
1785
|
-
args: [
|
|
1786
|
-
"-c",
|
|
1787
|
-
[
|
|
1788
|
-
"command -v rg >/dev/null 2>&1 && exit 0",
|
|
1789
|
-
"dnf install -y ripgrep 2>/dev/null && exit 0",
|
|
1790
|
-
"(apt-get update -qq && apt-get install -y -qq ripgrep) 2>/dev/null && exit 0",
|
|
1791
|
-
"apk add --no-cache ripgrep 2>/dev/null && exit 0",
|
|
1792
|
-
"curl -sL https://github.com/BurntSushi/ripgrep/releases/download/14.1.1/ripgrep-14.1.1-x86_64-unknown-linux-musl.tar.gz | tar xz -C /tmp && install /tmp/ripgrep-14.1.1-x86_64-unknown-linux-musl/rg /usr/local/bin/rg && rm -rf /tmp/ripgrep-14.1.1-x86_64-unknown-linux-musl"
|
|
1793
|
-
].join("\n")
|
|
1794
|
-
],
|
|
1795
|
-
sudo: true
|
|
1796
|
-
});
|
|
1797
|
-
if (!(installResult instanceof Error)) {
|
|
1798
|
-
const installOutput = await installResult.result;
|
|
1799
|
-
if (installOutput.exitCode !== 0) {
|
|
1800
|
-
log.warn("ripgrep install failed", {
|
|
1801
|
-
stderr: installOutput.stderr
|
|
1802
|
-
});
|
|
1803
|
-
}
|
|
1804
|
-
}
|
|
1805
|
-
result = await sandbox.exec({ command: "rg", args });
|
|
1806
|
-
}
|
|
1807
|
-
if (result instanceof Error && isRgNotFoundError(result)) {
|
|
1808
|
-
log.warn("rg unavailable, falling back to grep");
|
|
1809
|
-
const grepArgs = ["-rn", "--color=never"];
|
|
1810
|
-
if (!caseSensitive) {
|
|
1811
|
-
grepArgs.push("-i");
|
|
1812
|
-
}
|
|
1813
|
-
if (contextLines !== void 0) {
|
|
1814
|
-
grepArgs.push("-C", String(contextLines));
|
|
1815
|
-
}
|
|
1816
|
-
if (maxCount !== void 0) {
|
|
1817
|
-
grepArgs.push("-m", String(maxCount));
|
|
1818
|
-
}
|
|
1819
|
-
if (filesWithMatches) {
|
|
1820
|
-
grepArgs.push("-l");
|
|
1821
|
-
}
|
|
1822
|
-
if (glob) {
|
|
1823
|
-
grepArgs.push(`--include=${glob}`);
|
|
1824
|
-
}
|
|
1825
|
-
if (fileType) {
|
|
1826
|
-
const includeMap = {
|
|
1827
|
-
ts: ["*.ts", "*.tsx", "*.mts", "*.cts"],
|
|
1828
|
-
js: ["*.js", "*.jsx", "*.mjs", "*.cjs"],
|
|
1829
|
-
py: ["*.py"],
|
|
1830
|
-
rust: ["*.rs"],
|
|
1831
|
-
go: ["*.go"],
|
|
1832
|
-
java: ["*.java"],
|
|
1833
|
-
md: ["*.md"],
|
|
1834
|
-
json: ["*.json"],
|
|
1835
|
-
css: ["*.css"],
|
|
1836
|
-
html: ["*.html"],
|
|
1837
|
-
yaml: ["*.yml", "*.yaml"]
|
|
1838
|
-
};
|
|
1839
|
-
for (const ext of includeMap[fileType] ?? [`*.${fileType}`]) {
|
|
1840
|
-
grepArgs.push(`--include=${ext}`);
|
|
1841
|
-
}
|
|
1842
|
-
}
|
|
1843
|
-
grepArgs.push("--", pattern, searchPath);
|
|
1844
|
-
result = await sandbox.exec({
|
|
1845
|
-
command: "grep",
|
|
1846
|
-
args: grepArgs
|
|
1847
|
-
});
|
|
1848
|
-
}
|
|
1849
|
-
if (result instanceof Error) {
|
|
1850
|
-
log.error("Grep failed", { error: result.message });
|
|
1851
|
-
throw result;
|
|
1852
|
-
}
|
|
1853
|
-
const { stdout, stderr } = await result.result;
|
|
1854
|
-
if (stderr && !stderr.toLowerCase().includes("no matches")) {
|
|
1855
|
-
log.warn("Grep stderr", { stderr });
|
|
1856
|
-
}
|
|
1857
|
-
const MAX_GREP_OUTPUT_CHARS = 5e4;
|
|
1858
|
-
let finalOutput = stdout;
|
|
1859
|
-
let wasTruncated = false;
|
|
1860
|
-
if (finalOutput.length > MAX_GREP_OUTPUT_CHARS) {
|
|
1861
|
-
finalOutput = finalOutput.slice(0, MAX_GREP_OUTPUT_CHARS) + "\n\n[Output truncated - use more specific pattern or path]";
|
|
1862
|
-
wasTruncated = true;
|
|
1863
|
-
}
|
|
1864
|
-
const lines = finalOutput.trim().split("\n").filter((l) => l.length > 0);
|
|
1865
|
-
const fileCount = filesWithMatches ? lines.length : new Set(
|
|
1866
|
-
lines.filter((l) => !l.startsWith(" ") && l.includes(":")).map((l) => l.split(":")[0])
|
|
1867
|
-
).size;
|
|
1868
|
-
return {
|
|
1869
|
-
summary: {
|
|
1870
|
-
matchCount: filesWithMatches ? 0 : lines.filter((l) => l.includes(":")).length,
|
|
1871
|
-
fileCount,
|
|
1872
|
-
searchPath,
|
|
1873
|
-
pattern,
|
|
1874
|
-
wasTruncated
|
|
1875
|
-
},
|
|
1876
|
-
matches: finalOutput || "(no matches found)"
|
|
1877
|
-
};
|
|
1878
|
-
}
|
|
1879
|
-
}),
|
|
1880
|
-
[builtinToolNames.List]: tool3({
|
|
1881
|
-
...builtInTools.List,
|
|
1882
|
-
execute: async ({ path, depth, includeHidden, filesOnly, pattern }) => {
|
|
1883
|
-
const searchPath = path ?? ".";
|
|
1884
|
-
const result = await sandbox.exec({
|
|
1885
|
-
command: "bash",
|
|
1886
|
-
args: [
|
|
1887
|
-
"-c",
|
|
1888
|
-
`
|
|
1889
|
-
set -e
|
|
1890
|
-
SEARCH_PATH="$1"
|
|
1891
|
-
DEPTH="$2"
|
|
1892
|
-
INCLUDE_HIDDEN="$3"
|
|
1893
|
-
FILES_ONLY="$4"
|
|
1894
|
-
PATTERN="$5"
|
|
1895
|
-
|
|
1896
|
-
# Build find command arguments
|
|
1897
|
-
FIND_ARGS=""
|
|
1898
|
-
[ -n "$DEPTH" ] && FIND_ARGS="$FIND_ARGS -maxdepth $DEPTH"
|
|
1899
|
-
[ "$INCLUDE_HIDDEN" != "true" ] && FIND_ARGS="$FIND_ARGS ! -path '*/.*'"
|
|
1900
|
-
[ "$FILES_ONLY" = "true" ] && FIND_ARGS="$FIND_ARGS -type f"
|
|
1901
|
-
[ -n "$PATTERN" ] && FIND_ARGS="$FIND_ARGS -name '$PATTERN'"
|
|
1902
|
-
|
|
1903
|
-
# Get listing
|
|
1904
|
-
LISTING=$(eval "find '$SEARCH_PATH' $FIND_ARGS" 2>/dev/null | sort)
|
|
1905
|
-
|
|
1906
|
-
# Get counts
|
|
1907
|
-
COUNT_ARGS=""
|
|
1908
|
-
[ -n "$DEPTH" ] && COUNT_ARGS="$COUNT_ARGS -maxdepth $DEPTH"
|
|
1909
|
-
[ "$INCLUDE_HIDDEN" != "true" ] && COUNT_ARGS="$COUNT_ARGS ! -path '*/.*'"
|
|
1910
|
-
|
|
1911
|
-
FILE_COUNT=$(eval "find '$SEARCH_PATH' $COUNT_ARGS -type f" 2>/dev/null | wc -l)
|
|
1912
|
-
DIR_COUNT=$(eval "find '$SEARCH_PATH' $COUNT_ARGS -type d" 2>/dev/null | wc -l)
|
|
1913
|
-
|
|
1914
|
-
# Output: counts first, then listing
|
|
1915
|
-
echo "$FILE_COUNT|$DIR_COUNT"
|
|
1916
|
-
echo "|||LISTING|||"
|
|
1917
|
-
echo "$LISTING" | sed "s|^$SEARCH_PATH|.|"
|
|
1918
|
-
`,
|
|
1919
|
-
"--",
|
|
1920
|
-
searchPath,
|
|
1921
|
-
depth?.toString() || "",
|
|
1922
|
-
includeHidden ? "true" : "false",
|
|
1923
|
-
filesOnly ? "true" : "false",
|
|
1924
|
-
pattern || ""
|
|
1925
|
-
]
|
|
1926
|
-
});
|
|
1927
|
-
if (result instanceof Error) {
|
|
1928
|
-
log.error("List failed", { error: result.message });
|
|
1929
|
-
throw result;
|
|
1930
|
-
}
|
|
1931
|
-
const { stdout, stderr } = await result.result;
|
|
1932
|
-
if (stderr) {
|
|
1933
|
-
log.warn("List stderr", { stderr });
|
|
1934
|
-
}
|
|
1935
|
-
const [countsLine, ...rest] = stdout.split("|||LISTING|||");
|
|
1936
|
-
const listing = rest.join("|||LISTING|||").trim();
|
|
1937
|
-
const [fileCountStr, dirCountStr] = countsLine.trim().split("|");
|
|
1938
|
-
const totalFiles = Number.parseInt(fileCountStr, 10) || 0;
|
|
1939
|
-
const totalDirs = Number.parseInt(dirCountStr, 10) || 0;
|
|
1940
|
-
const lines = listing.split("\n").filter((l) => l.length > 0);
|
|
1941
|
-
return {
|
|
1942
|
-
summary: {
|
|
1943
|
-
totalItems: lines.length,
|
|
1944
|
-
totalFiles,
|
|
1945
|
-
totalDirs,
|
|
1946
|
-
searchPath,
|
|
1947
|
-
depth
|
|
1948
|
-
},
|
|
1949
|
-
listing
|
|
1950
|
-
};
|
|
1951
|
-
}
|
|
1952
|
-
}),
|
|
1953
|
-
[builtinToolNames.Write]: tool3({
|
|
1954
|
-
...builtInTools.Write,
|
|
1955
|
-
execute: async ({ path, content }) => {
|
|
1956
|
-
const filePath = path;
|
|
1957
|
-
try {
|
|
1958
|
-
await sandbox.writeFiles({
|
|
1959
|
-
files: [{ path: filePath, content }],
|
|
1960
|
-
destPath: "."
|
|
1961
|
-
});
|
|
1962
|
-
return {
|
|
1963
|
-
success: true,
|
|
1964
|
-
path: filePath,
|
|
1965
|
-
bytesWritten: Buffer.byteLength(content, "utf8")
|
|
1966
|
-
};
|
|
1967
|
-
} catch (err) {
|
|
1968
|
-
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
1969
|
-
return {
|
|
1970
|
-
success: false,
|
|
1971
|
-
path: filePath,
|
|
1972
|
-
bytesWritten: 0,
|
|
1973
|
-
error: errorMsg
|
|
1974
|
-
};
|
|
1975
|
-
}
|
|
1976
|
-
}
|
|
1977
|
-
}),
|
|
1978
|
-
[builtinToolNames.Edit]: tool3({
|
|
1979
|
-
...builtInTools.Edit,
|
|
1980
|
-
execute: async ({ path, old_string, new_string }) => {
|
|
1981
|
-
const filePath = path;
|
|
1982
|
-
const result = await sandbox.readFile({ path: filePath });
|
|
1983
|
-
if (result instanceof Error) {
|
|
1984
|
-
return { success: false, path: filePath, error: result.message };
|
|
1985
|
-
}
|
|
1986
|
-
if (result === null) {
|
|
1987
|
-
return {
|
|
1988
|
-
success: false,
|
|
1989
|
-
path: filePath,
|
|
1990
|
-
error: `File not found: ${filePath}`
|
|
1991
|
-
};
|
|
1992
|
-
}
|
|
1993
|
-
const content = result.toString("utf-8");
|
|
1994
|
-
const occurrences = content.split(old_string).length - 1;
|
|
1995
|
-
if (occurrences === 0) {
|
|
1996
|
-
return {
|
|
1997
|
-
success: false,
|
|
1998
|
-
path: filePath,
|
|
1999
|
-
error: "old_string not found in file"
|
|
2000
|
-
};
|
|
2001
|
-
}
|
|
2002
|
-
if (occurrences > 1) {
|
|
2003
|
-
return {
|
|
2004
|
-
success: false,
|
|
2005
|
-
path: filePath,
|
|
2006
|
-
error: `old_string appears ${occurrences} times in file (must be unique). Include more surrounding context to make the match unique.`
|
|
2007
|
-
};
|
|
2008
|
-
}
|
|
2009
|
-
const newContent = content.replace(old_string, new_string);
|
|
2010
|
-
try {
|
|
2011
|
-
await sandbox.writeFiles({
|
|
2012
|
-
files: [{ path: filePath, content: newContent }],
|
|
2013
|
-
destPath: "."
|
|
2014
|
-
});
|
|
2015
|
-
return { success: true, path: filePath };
|
|
2016
|
-
} catch (err) {
|
|
2017
|
-
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
2018
|
-
return { success: false, path: filePath, error: errorMsg };
|
|
2019
|
-
}
|
|
2020
|
-
}
|
|
2021
|
-
}),
|
|
2022
|
-
[builtinToolNames.Bash]: tool3({
|
|
2023
|
-
...builtInTools.Bash,
|
|
2024
|
-
execute: async ({ command, waitUntil }) => {
|
|
2025
|
-
const { createProcessManager } = await import("./process-manager-WQHAIVRB.mjs");
|
|
2026
|
-
const processManager = createProcessManager({ sandbox });
|
|
2027
|
-
const result = await processManager.run({ command, waitUntil });
|
|
2028
|
-
const MAX_STDOUT = 5e4;
|
|
2029
|
-
const MAX_STDERR = 1e4;
|
|
2030
|
-
let { stdout, stderr } = result;
|
|
2031
|
-
if (stdout.length > MAX_STDOUT) {
|
|
2032
|
-
stdout = `[truncated \u2014 showing last ${MAX_STDOUT} chars. Full: ${result.outputDir}/stdout.txt]
|
|
2033
|
-
|
|
2034
|
-
` + stdout.slice(-MAX_STDOUT);
|
|
2035
|
-
}
|
|
2036
|
-
if (stderr.length > MAX_STDERR) {
|
|
2037
|
-
stderr = `[truncated \u2014 showing last ${MAX_STDERR} chars. Full: ${result.outputDir}/stderr.txt]
|
|
2038
|
-
|
|
2039
|
-
` + stderr.slice(-MAX_STDERR);
|
|
2040
|
-
}
|
|
2041
|
-
return { ...result, stdout, stderr };
|
|
2042
|
-
}
|
|
2043
|
-
})
|
|
2044
|
-
};
|
|
2045
|
-
for (const [name, t] of Object.entries(agent2.options.tools ?? {})) {
|
|
2046
|
-
rawTools[name] = t;
|
|
2047
|
-
}
|
|
2048
|
-
if (skillsRef.current.length > 0) {
|
|
2049
|
-
rawTools[builtinToolNames.Skill] = tool3({
|
|
2050
|
-
...builtInTools.Skill,
|
|
2051
|
-
execute: async ({ name }) => {
|
|
2052
|
-
const skills = skillsRef.current;
|
|
2053
|
-
const skill = skills.find(
|
|
2054
|
-
(s) => s.name.toLowerCase() === name.toLowerCase()
|
|
2055
|
-
);
|
|
2056
|
-
if (!skill) {
|
|
2057
|
-
throw new Error(
|
|
2058
|
-
`Skill not found: "${name}". Available: ${skills.map((s) => s.name).join(", ")}`
|
|
2059
|
-
);
|
|
2060
|
-
}
|
|
2061
|
-
const result = await sandbox.readFile({
|
|
2062
|
-
path: skill.skillMdPath
|
|
2063
|
-
});
|
|
2064
|
-
if (result instanceof Error) {
|
|
2065
|
-
throw result;
|
|
2066
|
-
}
|
|
2067
|
-
if (result === null) {
|
|
2068
|
-
throw new Error(`Skill file not found: ${skill.skillMdPath}`);
|
|
2069
|
-
}
|
|
2070
|
-
const raw = typeof result === "string" ? result : result.toString("utf-8");
|
|
2071
|
-
const endMarker = raw.indexOf("---", 3);
|
|
2072
|
-
const content = endMarker === -1 ? raw : raw.slice(endMarker + 3).trim();
|
|
2073
|
-
const skillDir = skill.skillMdPath.replace(SKILL_MD_SUFFIX, "");
|
|
2074
|
-
return {
|
|
2075
|
-
name: skill.name,
|
|
2076
|
-
description: skill.description,
|
|
2077
|
-
content,
|
|
2078
|
-
path: skillDir
|
|
2079
|
-
};
|
|
2080
|
-
}
|
|
2081
|
-
});
|
|
2082
|
-
}
|
|
2083
|
-
const onSubToolCall = async (toolName, toolInput, execute) => {
|
|
2084
|
-
const needsApproval = await checkNeedsApproval({
|
|
2085
|
-
agent: agent2,
|
|
2086
|
-
toolName,
|
|
2087
|
-
input: toolInput,
|
|
2088
|
-
toolCallId: `js_${toolName}_${Date.now()}`,
|
|
2089
|
-
messages: []
|
|
2090
|
-
});
|
|
2091
|
-
if (!needsApproval) {
|
|
2092
|
-
try {
|
|
2093
|
-
const result = await execute();
|
|
2094
|
-
return { result };
|
|
2095
|
-
} catch (err) {
|
|
2096
|
-
return {
|
|
2097
|
-
error: err instanceof Error ? err.message : String(err)
|
|
2098
|
-
};
|
|
2099
|
-
}
|
|
2100
|
-
}
|
|
2101
|
-
const approvalId = `js_approval_${ulid2()}`;
|
|
2102
|
-
const toolCallId = `js_tc_${ulid2()}`;
|
|
2103
|
-
const partId = approvalPartId(approvalId);
|
|
2104
|
-
await agent2.storage.part.set(partId, {
|
|
2105
|
-
id: partId,
|
|
2106
|
-
index: nextPartIndexRef.current++,
|
|
2107
|
-
messageId: assistantMessageId,
|
|
2108
|
-
sessionId,
|
|
2109
|
-
part: {
|
|
2110
|
-
type: `tool-${toolName}`,
|
|
2111
|
-
toolCallId,
|
|
2112
|
-
state: "approval-requested",
|
|
2113
|
-
input: toolInput,
|
|
2114
|
-
approval: { id: approvalId }
|
|
2115
|
-
}
|
|
2116
|
-
});
|
|
2117
|
-
writer.write({
|
|
2118
|
-
type: "tool-input-start",
|
|
2119
|
-
toolCallId,
|
|
2120
|
-
toolName
|
|
2121
|
-
});
|
|
2122
|
-
writer.write({
|
|
2123
|
-
type: "tool-input-available",
|
|
2124
|
-
toolCallId,
|
|
2125
|
-
toolName,
|
|
2126
|
-
input: toolInput
|
|
2127
|
-
});
|
|
2128
|
-
writer.write({
|
|
2129
|
-
type: "tool-approval-request",
|
|
2130
|
-
approvalId,
|
|
2131
|
-
toolCallId
|
|
2132
|
-
});
|
|
2133
|
-
const POLL_MS = 500;
|
|
2134
|
-
const TIMEOUT_MS = 5 * 60 * 1e3;
|
|
2135
|
-
const start2 = Date.now();
|
|
2136
|
-
while (Date.now() - start2 < TIMEOUT_MS && !abortController.signal.aborted) {
|
|
2137
|
-
const updated = await agent2.storage.part.get(partId);
|
|
2138
|
-
if (updated && "state" in updated.part && (updated.part.state === "approval-responded" || updated.part.state === "output-denied")) {
|
|
2139
|
-
const state2 = updated.part.state;
|
|
2140
|
-
if (state2 === "output-denied") {
|
|
2141
|
-
const reason = updated.part.approval?.reason;
|
|
2142
|
-
return {
|
|
2143
|
-
error: `Tool "${toolName}" denied: ${reason || "user denied"}`
|
|
2144
|
-
};
|
|
2145
|
-
}
|
|
2146
|
-
const approval = updated.part.approval;
|
|
2147
|
-
if (approval?.approved) {
|
|
2148
|
-
try {
|
|
2149
|
-
const result = await execute();
|
|
2150
|
-
writer.write({
|
|
2151
|
-
type: "tool-output-available",
|
|
2152
|
-
toolCallId,
|
|
2153
|
-
output: result
|
|
2154
|
-
});
|
|
2155
|
-
return { result };
|
|
2156
|
-
} catch (err) {
|
|
2157
|
-
const error = err instanceof Error ? err.message : String(err);
|
|
2158
|
-
writer.write({
|
|
2159
|
-
type: "tool-output-error",
|
|
2160
|
-
toolCallId,
|
|
2161
|
-
errorText: error
|
|
2162
|
-
});
|
|
2163
|
-
return { error };
|
|
2164
|
-
}
|
|
2165
|
-
}
|
|
2166
|
-
writer.write({
|
|
2167
|
-
type: "tool-output-denied",
|
|
2168
|
-
toolCallId
|
|
2169
|
-
});
|
|
2170
|
-
return {
|
|
2171
|
-
error: `Tool "${toolName}" denied: ${approval?.reason || "user denied"}`
|
|
2172
|
-
};
|
|
2173
|
-
}
|
|
2174
|
-
await new Promise((r) => setTimeout(r, POLL_MS));
|
|
2175
|
-
}
|
|
2176
|
-
return {
|
|
2177
|
-
error: abortController.signal.aborted ? "interrupted" : "Approval timed out"
|
|
2178
|
-
};
|
|
2179
|
-
};
|
|
2180
|
-
const toolContext = {
|
|
2181
|
-
context,
|
|
2182
|
-
state,
|
|
2183
|
-
sessionId,
|
|
2184
|
-
sandbox,
|
|
2185
|
-
messages
|
|
2186
|
-
};
|
|
2187
|
-
rawTools[builtinToolNames.JavaScript] = createJavaScriptTool({
|
|
2188
|
-
tools: rawTools,
|
|
2189
|
-
sandbox,
|
|
2190
|
-
activeTools,
|
|
2191
|
-
onSubToolCall,
|
|
2192
|
-
toolContext
|
|
2193
|
-
});
|
|
2194
|
-
const toolsWithNeedsApproval = Object.fromEntries(
|
|
2195
|
-
Object.entries(rawTools).map(([name, t]) => {
|
|
2196
|
-
const originalExecute = t.execute;
|
|
2197
|
-
const wrappedExecute = originalExecute ? async (...args) => {
|
|
2198
|
-
const done = stepLog.time(`tool:${name}`);
|
|
2199
|
-
try {
|
|
2200
|
-
let toolInput = args[0];
|
|
2201
|
-
if (agent2.hooks["tool.before"]) {
|
|
2202
|
-
const beforeResult = await agent2.hooks["tool.before"]({
|
|
2203
|
-
name,
|
|
2204
|
-
input: toolInput,
|
|
2205
|
-
context: toolContext
|
|
2206
|
-
});
|
|
2207
|
-
if (beforeResult?.input !== void 0) {
|
|
2208
|
-
toolInput = beforeResult.input;
|
|
2209
|
-
args[0] = toolInput;
|
|
2210
|
-
}
|
|
2211
|
-
}
|
|
2212
|
-
let result = await originalExecute(...args);
|
|
2213
|
-
if (agent2.hooks["tool.after"]) {
|
|
2214
|
-
const afterResult = await agent2.hooks["tool.after"]({
|
|
2215
|
-
name,
|
|
2216
|
-
input: toolInput,
|
|
2217
|
-
result,
|
|
2218
|
-
context: toolContext
|
|
2219
|
-
});
|
|
2220
|
-
if (afterResult?.result !== void 0) {
|
|
2221
|
-
result = afterResult.result;
|
|
2222
|
-
}
|
|
2223
|
-
}
|
|
2224
|
-
done();
|
|
2225
|
-
return result;
|
|
2226
|
-
} catch (e) {
|
|
2227
|
-
done({
|
|
2228
|
-
error: e instanceof Error ? e.message : String(e)
|
|
2229
|
-
});
|
|
2230
|
-
throw e;
|
|
2231
|
-
}
|
|
2232
|
-
} : void 0;
|
|
2233
|
-
return [
|
|
2234
|
-
name,
|
|
2235
|
-
{
|
|
2236
|
-
...t,
|
|
2237
|
-
...wrappedExecute ? { execute: wrappedExecute } : {},
|
|
2238
|
-
needsApproval: async (toolInput, opts) => {
|
|
2239
|
-
return await checkNeedsApproval({
|
|
2240
|
-
agent: agent2,
|
|
2241
|
-
toolName: name,
|
|
2242
|
-
input: toolInput,
|
|
2243
|
-
toolCallId: opts.toolCallId,
|
|
2244
|
-
messages: opts.messages
|
|
2245
|
-
});
|
|
2246
|
-
}
|
|
2247
|
-
}
|
|
2248
|
-
];
|
|
2249
|
-
})
|
|
2250
|
-
);
|
|
2251
|
-
return { rawTools, toolsWithNeedsApproval, toolContext };
|
|
2252
|
-
}
|
|
2253
|
-
|
|
2254
|
-
// src/utils/prompt-cache.ts
|
|
2255
|
-
var ANTHROPIC_MAX_CACHE_BREAKPOINTS_PER_REQUEST = 4;
|
|
2256
|
-
var CLAUDE_LIKE_MODEL_MATCHERS = ["claude", "anthropic"];
|
|
2257
|
-
var CLAUDE_PROMPT_CACHING_PROVIDER_OPTIONS = {
|
|
2258
|
-
anthropic: {
|
|
2259
|
-
cacheControl: { type: "ephemeral" }
|
|
2260
|
-
},
|
|
2261
|
-
openrouter: {
|
|
2262
|
-
cacheControl: { type: "ephemeral" }
|
|
2263
|
-
},
|
|
2264
|
-
bedrock: {
|
|
2265
|
-
cachePoint: { type: "default" }
|
|
2266
|
-
},
|
|
2267
|
-
openaiCompatible: {
|
|
2268
|
-
cache_control: { type: "ephemeral" }
|
|
2269
|
-
},
|
|
2270
|
-
copilot: {
|
|
2271
|
-
copilot_cache_control: { type: "ephemeral" }
|
|
2272
|
-
}
|
|
2273
|
-
};
|
|
2274
|
-
function getGatewayProvider(model) {
|
|
2275
|
-
const slashIndex = model.indexOf("/");
|
|
2276
|
-
if (slashIndex === -1) {
|
|
2277
|
-
return null;
|
|
2278
|
-
}
|
|
2279
|
-
return model.slice(0, slashIndex);
|
|
2280
|
-
}
|
|
2281
|
-
function countAnthropicCacheBreakpoints(messages) {
|
|
2282
|
-
let count = 0;
|
|
2283
|
-
for (const message of messages) {
|
|
2284
|
-
const providerOptions = message.providerOptions;
|
|
2285
|
-
if (providerOptions?.anthropic?.cacheControl) {
|
|
2286
|
-
count += 1;
|
|
2287
|
-
}
|
|
2288
|
-
if (Array.isArray(message.content)) {
|
|
2289
|
-
for (const part of message.content) {
|
|
2290
|
-
const partProviderOptions = part.providerOptions;
|
|
2291
|
-
if (partProviderOptions?.anthropic?.cacheControl) {
|
|
2292
|
-
count += 1;
|
|
2293
|
-
}
|
|
2294
|
-
}
|
|
2295
|
-
}
|
|
2296
|
-
}
|
|
2297
|
-
return count;
|
|
2298
|
-
}
|
|
2299
|
-
function isClaudeLikeModel(model) {
|
|
2300
|
-
const lower = model.toLowerCase();
|
|
2301
|
-
return CLAUDE_LIKE_MODEL_MATCHERS.some((m) => lower.includes(m));
|
|
2302
|
-
}
|
|
2303
|
-
function mergeProviderOptions(opts) {
|
|
2304
|
-
const next = { ...opts.current ?? {} };
|
|
2305
|
-
for (const [key, value] of Object.entries(opts.patch)) {
|
|
2306
|
-
next[key] = { ...next[key] ?? {}, ...value };
|
|
2307
|
-
}
|
|
2308
|
-
return next;
|
|
2309
|
-
}
|
|
2310
|
-
function isCacheableClaudePart(part) {
|
|
2311
|
-
if (!part || typeof part !== "object") {
|
|
2312
|
-
return false;
|
|
2313
|
-
}
|
|
2314
|
-
if ("type" in part && part.type === "text") {
|
|
2315
|
-
const text = part.text;
|
|
2316
|
-
if (typeof text === "string") {
|
|
2317
|
-
return text.trim().length > 0;
|
|
2318
|
-
}
|
|
2319
|
-
}
|
|
2320
|
-
if ("type" in part) {
|
|
2321
|
-
const type = part.type;
|
|
2322
|
-
if (type === "thinking" || type === "reasoning") {
|
|
2323
|
-
return false;
|
|
2324
|
-
}
|
|
2325
|
-
}
|
|
2326
|
-
return true;
|
|
2327
|
-
}
|
|
2328
|
-
function hasCacheableContent(message) {
|
|
2329
|
-
if (typeof message.content === "string") {
|
|
2330
|
-
return message.content.trim().length > 0;
|
|
2331
|
-
}
|
|
2332
|
-
if (Array.isArray(message.content)) {
|
|
2333
|
-
return message.content.some((part) => isCacheableClaudePart(part));
|
|
2334
|
-
}
|
|
2335
|
-
return false;
|
|
2336
|
-
}
|
|
2337
|
-
function findLastCacheablePartIndex(content) {
|
|
2338
|
-
for (let i = content.length - 1; i >= 0; i -= 1) {
|
|
2339
|
-
if (isCacheableClaudePart(content[i])) {
|
|
2340
|
-
return i;
|
|
2341
|
-
}
|
|
2342
|
-
}
|
|
2343
|
-
return null;
|
|
2344
|
-
}
|
|
2345
|
-
function selectClaudeCachingTargets(messages) {
|
|
2346
|
-
const systemIndices = [];
|
|
2347
|
-
const finalIndices = [];
|
|
2348
|
-
for (let i = 0; i < messages.length && systemIndices.length < 2; i += 1) {
|
|
2349
|
-
const message = messages[i];
|
|
2350
|
-
if (message.role === "system" && hasCacheableContent(message)) {
|
|
2351
|
-
systemIndices.push(i);
|
|
2352
|
-
}
|
|
2353
|
-
}
|
|
2354
|
-
for (let i = messages.length - 1; i >= 0 && finalIndices.length < 2; i -= 1) {
|
|
2355
|
-
const message = messages[i];
|
|
2356
|
-
if (message.role !== "system" && hasCacheableContent(message)) {
|
|
2357
|
-
finalIndices.push(i);
|
|
2358
|
-
}
|
|
2359
|
-
}
|
|
2360
|
-
finalIndices.reverse();
|
|
2361
|
-
return [...systemIndices, ...finalIndices];
|
|
2362
|
-
}
|
|
2363
|
-
function applyClaudePromptCaching(opts) {
|
|
2364
|
-
const existingBreakpoints = countAnthropicCacheBreakpoints(opts.messages);
|
|
2365
|
-
const remainingBudget = Math.max(
|
|
2366
|
-
0,
|
|
2367
|
-
opts.maxBreakpointsPerRequest - existingBreakpoints
|
|
2368
|
-
);
|
|
2369
|
-
if (remainingBudget === 0) {
|
|
2370
|
-
return opts.messages;
|
|
2371
|
-
}
|
|
2372
|
-
const targetIndices = selectClaudeCachingTargets(opts.messages).slice(
|
|
2373
|
-
0,
|
|
2374
|
-
remainingBudget
|
|
2375
|
-
);
|
|
2376
|
-
if (targetIndices.length === 0) {
|
|
2377
|
-
return opts.messages;
|
|
2378
|
-
}
|
|
2379
|
-
const useMessageLevelOptions = opts.providerId === "anthropic" || Boolean(opts.providerId?.includes("bedrock"));
|
|
2380
|
-
const nextMessages = opts.messages.slice();
|
|
2381
|
-
for (const messageIndex of targetIndices) {
|
|
2382
|
-
const message = nextMessages[messageIndex];
|
|
2383
|
-
const shouldUseContentOptions = !useMessageLevelOptions && Array.isArray(message.content) && message.content.length > 0;
|
|
2384
|
-
if (shouldUseContentOptions && Array.isArray(message.content)) {
|
|
2385
|
-
const partIndex = findLastCacheablePartIndex(message.content);
|
|
2386
|
-
if (partIndex !== null) {
|
|
2387
|
-
const part = message.content[partIndex];
|
|
2388
|
-
if (part && typeof part === "object") {
|
|
2389
|
-
const partProviderOptions = part.providerOptions;
|
|
2390
|
-
const nextContent = message.content.slice();
|
|
2391
|
-
nextContent[partIndex] = {
|
|
2392
|
-
...part,
|
|
2393
|
-
providerOptions: mergeProviderOptions({
|
|
2394
|
-
current: partProviderOptions,
|
|
2395
|
-
patch: CLAUDE_PROMPT_CACHING_PROVIDER_OPTIONS
|
|
2396
|
-
})
|
|
2397
|
-
};
|
|
2398
|
-
nextMessages[messageIndex] = {
|
|
2399
|
-
...message,
|
|
2400
|
-
content: nextContent
|
|
2401
|
-
};
|
|
2402
|
-
continue;
|
|
2403
|
-
}
|
|
2404
|
-
}
|
|
2405
|
-
}
|
|
2406
|
-
const messageProviderOptions = message.providerOptions;
|
|
2407
|
-
nextMessages[messageIndex] = {
|
|
2408
|
-
...message,
|
|
2409
|
-
providerOptions: mergeProviderOptions({
|
|
2410
|
-
current: messageProviderOptions,
|
|
2411
|
-
patch: CLAUDE_PROMPT_CACHING_PROVIDER_OPTIONS
|
|
2412
|
-
})
|
|
2413
|
-
};
|
|
2414
|
-
}
|
|
2415
|
-
return nextMessages;
|
|
2416
|
-
}
|
|
2417
|
-
function applyPromptCachingToModelRequest(opts) {
|
|
2418
|
-
const provider = getGatewayProvider(opts.model);
|
|
2419
|
-
const providerOptions = {};
|
|
2420
|
-
if ((provider === "openai" || provider === "azure") && opts.openai?.setPromptCacheKey !== false) {
|
|
2421
|
-
providerOptions.openai = { promptCacheKey: opts.sessionId };
|
|
2422
|
-
}
|
|
2423
|
-
const maxBreakpointsPerRequest = opts.anthropic?.maxBreakpointsPerRequest ?? ANTHROPIC_MAX_CACHE_BREAKPOINTS_PER_REQUEST;
|
|
2424
|
-
const cachedMessages = isClaudeLikeModel(opts.model) ? applyClaudePromptCaching({
|
|
2425
|
-
messages: opts.messages,
|
|
2426
|
-
providerId: provider,
|
|
2427
|
-
maxBreakpointsPerRequest
|
|
2428
|
-
}) : opts.messages;
|
|
2429
|
-
return {
|
|
2430
|
-
messages: cachedMessages,
|
|
2431
|
-
providerOptions
|
|
2432
|
-
};
|
|
2433
|
-
}
|
|
2434
|
-
|
|
2435
|
-
// src/session/ai-loop/stream-text.ts
|
|
2436
|
-
var INTERRUPT_POLL_INTERVAL_MS = 250;
|
|
2437
|
-
function pollForInterrupt({
|
|
2438
|
-
agent: agent2,
|
|
2439
|
-
messageId,
|
|
2440
|
-
signal,
|
|
2441
|
-
abortController
|
|
2442
|
-
}) {
|
|
2443
|
-
let resolveFirstCheck;
|
|
2444
|
-
const firstCheck = new Promise((resolve2) => {
|
|
2445
|
-
resolveFirstCheck = resolve2;
|
|
2446
|
-
});
|
|
2447
|
-
const interruptedLastPartRef = {
|
|
2448
|
-
current: null
|
|
2449
|
-
};
|
|
2450
|
-
const log2 = createLogger({
|
|
2451
|
-
config: { ...agent2.options.logging, name: agent2.name },
|
|
2452
|
-
subsystem: "ai-loop"
|
|
2453
|
-
});
|
|
2454
|
-
const poll = async () => {
|
|
2455
|
-
let isFirst = true;
|
|
2456
|
-
while (!signal.aborted) {
|
|
2457
|
-
const message = await agent2.storage.message.get(messageId);
|
|
2458
|
-
if (!message) {
|
|
2459
|
-
if (isFirst) {
|
|
2460
|
-
resolveFirstCheck();
|
|
2461
|
-
return;
|
|
2462
|
-
}
|
|
2463
|
-
throw new Error(`Message ${messageId} not found`);
|
|
2464
|
-
}
|
|
2465
|
-
if (message.interruptedAt !== null) {
|
|
2466
|
-
log2.info("interrupt detected", { messageId });
|
|
2467
|
-
interruptedLastPartRef.current = message.interruptedLastPart;
|
|
2468
|
-
abortController.abort();
|
|
2469
|
-
if (isFirst) {
|
|
2470
|
-
resolveFirstCheck();
|
|
2471
|
-
}
|
|
2472
|
-
return;
|
|
2473
|
-
}
|
|
2474
|
-
if (isFirst) {
|
|
2475
|
-
isFirst = false;
|
|
2476
|
-
resolveFirstCheck();
|
|
2477
|
-
}
|
|
2478
|
-
await new Promise(
|
|
2479
|
-
(resolve2) => setTimeout(resolve2, INTERRUPT_POLL_INTERVAL_MS)
|
|
2480
|
-
);
|
|
2481
|
-
}
|
|
2482
|
-
};
|
|
2483
|
-
poll();
|
|
2484
|
-
return { firstCheck, interruptedLastPartRef };
|
|
2485
|
-
}
|
|
2486
|
-
async function streamText({
|
|
2487
|
-
stepThroughput,
|
|
2488
|
-
assistantMessageId,
|
|
2489
|
-
agent: agent2,
|
|
2490
|
-
sessionId,
|
|
2491
|
-
context,
|
|
2492
|
-
state,
|
|
2493
|
-
createdAt,
|
|
2494
|
-
writable,
|
|
2495
|
-
lastPartIndex,
|
|
2496
|
-
stepIndexOffset,
|
|
2497
|
-
discoveredSkills
|
|
2498
|
-
}) {
|
|
2499
|
-
const log2 = createLogger({
|
|
2500
|
-
config: { ...agent2.options.logging, name: agent2.name },
|
|
2501
|
-
subsystem: "ai-loop"
|
|
2502
|
-
});
|
|
2503
|
-
const stepLog = log2.withContext({
|
|
2504
|
-
sessionId,
|
|
2505
|
-
messageId: assistantMessageId
|
|
2506
|
-
});
|
|
2507
|
-
const doneStep = stepLog.time("streamText");
|
|
2508
|
-
const throttledEmitStatus = createThrottledEmitStatus(agent2);
|
|
2509
|
-
const abortController = new AbortController();
|
|
2510
|
-
const pollController = new AbortController();
|
|
2511
|
-
const { firstCheck, interruptedLastPartRef } = pollForInterrupt({
|
|
2512
|
-
agent: agent2,
|
|
2513
|
-
messageId: assistantMessageId,
|
|
2514
|
-
signal: pollController.signal,
|
|
2515
|
-
abortController
|
|
2516
|
-
});
|
|
2517
|
-
const doneLoad = stepLog.time("load session + messages + parts + sandbox");
|
|
2518
|
-
const [, messagesResult, partsResult, { sandbox, sandboxRecord }] = await Promise.all([
|
|
2519
|
-
firstCheck,
|
|
2520
|
-
agent2.storage.message.listBySession(sessionId),
|
|
2521
|
-
agent2.storage.part.listBySession(sessionId),
|
|
2522
|
-
agent2.storage.session.get(sessionId).then(async (session) => {
|
|
2523
|
-
if (!session) {
|
|
2524
|
-
throw new SessionNotFoundError({ id: sessionId });
|
|
2525
|
-
}
|
|
2526
|
-
const sandboxId = session.sandboxId ?? session.id;
|
|
2527
|
-
const sandbox2 = agent2.sandbox(sandboxId);
|
|
2528
|
-
const sandboxRecord2 = await agent2.storage.sandbox.get(sandboxId);
|
|
2529
|
-
return { sandbox: sandbox2, sandboxRecord: sandboxRecord2 };
|
|
2530
|
-
})
|
|
2531
|
-
]);
|
|
2532
|
-
doneLoad();
|
|
2533
|
-
if (abortController.signal.aborted) {
|
|
2534
|
-
pollController.abort();
|
|
2535
|
-
return {
|
|
2536
|
-
finishReason: "stop",
|
|
2537
|
-
lastPartIndex,
|
|
2538
|
-
usageSteps: [],
|
|
2539
|
-
pendingApprovals: [],
|
|
2540
|
-
maxSteps: void 0,
|
|
2541
|
-
discoveredSkills,
|
|
2542
|
-
context
|
|
2543
|
-
};
|
|
2544
|
-
}
|
|
2545
|
-
const setStartedPromise = lastPartIndex === 0 ? (async () => {
|
|
2546
|
-
const now = Date.now();
|
|
2547
|
-
const pendingMessages = messagesResult.filter(
|
|
2548
|
-
(m) => m.createdAt <= createdAt && m.startedAt === null
|
|
2549
|
-
);
|
|
2550
|
-
if (pendingMessages.length > 0) {
|
|
2551
|
-
return await Promise.all(
|
|
2552
|
-
pendingMessages.map(
|
|
2553
|
-
(m) => agent2.storage.message.update(m.id, {
|
|
2554
|
-
startedAt: now,
|
|
2555
|
-
completedAt: m.role === "assistant" ? null : now
|
|
2556
|
-
})
|
|
2557
|
-
)
|
|
2558
|
-
);
|
|
2559
|
-
}
|
|
2560
|
-
})() : null;
|
|
2561
|
-
const allParts = [...partsResult];
|
|
2562
|
-
const nextPartIndexRef = {
|
|
2563
|
-
current: Math.max(
|
|
2564
|
-
lastPartIndex,
|
|
2565
|
-
...allParts.filter((p) => p.messageId === assistantMessageId).map((p) => p.index + 1),
|
|
2566
|
-
0
|
|
2567
|
-
)
|
|
2568
|
-
};
|
|
2569
|
-
const skillsRef = {
|
|
2570
|
-
current: discoveredSkills ?? []
|
|
2571
|
-
};
|
|
2572
|
-
let uiMessages = assembleUIMessages({
|
|
2573
|
-
messages: messagesResult,
|
|
2574
|
-
parts: allParts,
|
|
2575
|
-
until: createdAt,
|
|
2576
|
-
includeQueued: true,
|
|
2577
|
-
excludeSubToolParts: true
|
|
2578
|
-
});
|
|
2579
|
-
const resolvableArgs = {
|
|
2580
|
-
context,
|
|
2581
|
-
state,
|
|
2582
|
-
sessionId,
|
|
2583
|
-
sandbox,
|
|
2584
|
-
get messages() {
|
|
2585
|
-
return uiMessages;
|
|
2586
|
-
}
|
|
2587
|
-
};
|
|
2588
|
-
if (lastPartIndex === 0 && !discoveredSkills) {
|
|
2589
|
-
const resolvedSkills = await resolveOption(
|
|
2590
|
-
agent2.options.skills,
|
|
2591
|
-
resolvableArgs
|
|
2592
|
-
);
|
|
2593
|
-
const skillsDirs = resolvedSkills?.length ? await resolveSkillInputsToSandboxDirs({
|
|
2594
|
-
agent: agent2,
|
|
2595
|
-
sandbox,
|
|
2596
|
-
skills: resolvedSkills,
|
|
2597
|
-
sessionId
|
|
2598
|
-
}) : [];
|
|
2599
|
-
if (skillsDirs.length > 0) {
|
|
2600
|
-
const doneSkills = stepLog.time("discover skills", { skillsDirs });
|
|
2601
|
-
skillsRef.current = await discoverSkillsInSandbox({
|
|
2602
|
-
agent: agent2,
|
|
2603
|
-
sandbox,
|
|
2604
|
-
skillsDirs,
|
|
2605
|
-
sessionId
|
|
2606
|
-
});
|
|
2607
|
-
doneSkills({ count: skillsRef.current.length });
|
|
2608
|
-
}
|
|
2609
|
-
}
|
|
2610
|
-
const usageSteps = [];
|
|
2611
|
-
let internalStepIndex = 0;
|
|
2612
|
-
let loopFinishReason = "unknown";
|
|
2613
|
-
let wasAborted = false;
|
|
2614
|
-
const allPendingApprovals = [];
|
|
2615
|
-
let currentMaxSteps;
|
|
2616
|
-
try {
|
|
2617
|
-
for (let iteration = 0; iteration < stepThroughput; iteration++) {
|
|
2618
|
-
const resolvedModel = await resolveOption(
|
|
2619
|
-
agent2.options.model,
|
|
2620
|
-
resolvableArgs
|
|
2621
|
-
);
|
|
2622
|
-
const resolvedGeneration = await resolveOption(
|
|
2623
|
-
agent2.options.generation,
|
|
2624
|
-
resolvableArgs
|
|
2625
|
-
);
|
|
2626
|
-
const resolvedActiveTools = await resolveOption(
|
|
2627
|
-
agent2.options.activeTools,
|
|
2628
|
-
resolvableArgs
|
|
2629
|
-
);
|
|
2630
|
-
currentMaxSteps = resolvedGeneration?.maxSteps;
|
|
2631
|
-
if (!resolvedModel) {
|
|
2632
|
-
throw new Error("Agent model is not set");
|
|
2633
|
-
}
|
|
2634
|
-
const stepParts = [];
|
|
2635
|
-
let streamTextFinishReason;
|
|
2636
|
-
try {
|
|
2637
|
-
const stream2 = createUIMessageStream({
|
|
2638
|
-
execute: async ({ writer }) => {
|
|
2639
|
-
const { rawTools, toolsWithNeedsApproval, toolContext } = getTools({
|
|
2640
|
-
agent: agent2,
|
|
2641
|
-
sandbox,
|
|
2642
|
-
skillsRef,
|
|
2643
|
-
writer,
|
|
2644
|
-
abortController,
|
|
2645
|
-
nextPartIndexRef,
|
|
2646
|
-
assistantMessageId,
|
|
2647
|
-
sessionId,
|
|
2648
|
-
stepLog,
|
|
2649
|
-
context,
|
|
2650
|
-
state,
|
|
2651
|
-
messages: uiMessages,
|
|
2652
|
-
activeTools: resolvedActiveTools
|
|
2653
|
-
});
|
|
2654
|
-
if (iteration === 0) {
|
|
2655
|
-
await processApprovals({
|
|
2656
|
-
allParts,
|
|
2657
|
-
messagesResult,
|
|
2658
|
-
createdAt,
|
|
2659
|
-
rawTools,
|
|
2660
|
-
abortController,
|
|
2661
|
-
toolContext,
|
|
2662
|
-
agent: agent2,
|
|
2663
|
-
stepLog,
|
|
2664
|
-
throttledEmitStatus,
|
|
2665
|
-
writer
|
|
2666
|
-
});
|
|
2667
|
-
}
|
|
2668
|
-
throttledEmitStatus({
|
|
2669
|
-
writer,
|
|
2670
|
-
status: { type: "thinking" }
|
|
2671
|
-
});
|
|
2672
|
-
const iterResult = streamTextAi({
|
|
2673
|
-
messages: [{ role: "user", content: "." }],
|
|
2674
|
-
tools: toolsWithNeedsApproval,
|
|
2675
|
-
model: resolvedModel,
|
|
2676
|
-
abortSignal: abortController.signal,
|
|
2677
|
-
stopWhen: stepCountIs(1),
|
|
2678
|
-
temperature: resolvedGeneration?.temperature,
|
|
2679
|
-
topK: resolvedGeneration?.topK,
|
|
2680
|
-
topP: resolvedGeneration?.topP,
|
|
2681
|
-
frequencyPenalty: resolvedGeneration?.frequencyPenalty,
|
|
2682
|
-
presencePenalty: resolvedGeneration?.presencePenalty,
|
|
2683
|
-
maxOutputTokens: resolvedGeneration?.maxOutputTokens,
|
|
2684
|
-
headers: resolvedGeneration?.headers,
|
|
2685
|
-
experimental_context: {
|
|
2686
|
-
context,
|
|
2687
|
-
state,
|
|
2688
|
-
sessionId,
|
|
2689
|
-
sandbox,
|
|
2690
|
-
messages: uiMessages
|
|
2691
|
-
},
|
|
2692
|
-
prepareStep: async ({ model }) => {
|
|
2693
|
-
const skillsContext = buildSkillsContext(skillsRef.current);
|
|
2694
|
-
const cwdPrompt = sandboxRecord?.setup?.cwd ? `Your working directory is ${sandboxRecord.setup.cwd}. All file paths should be absolute.` : "All file paths must be absolute.";
|
|
2695
|
-
const resolvedSystem = await resolveSystem(
|
|
2696
|
-
agent2.options.system,
|
|
2697
|
-
resolvableArgs
|
|
2698
|
-
);
|
|
2699
|
-
const systemHeader = joinPromptSections(
|
|
2700
|
-
BASE_SYSTEM_PROMPT,
|
|
2701
|
-
cwdPrompt,
|
|
2702
|
-
resolvedSystem
|
|
2703
|
-
);
|
|
2704
|
-
const systemContext = joinPromptSections(
|
|
2705
|
-
skillsContext,
|
|
2706
|
-
cwdPrompt
|
|
2707
|
-
);
|
|
2708
|
-
const convertedMessages = await convertToModelMessages(
|
|
2709
|
-
uiMessages,
|
|
2710
|
-
{ ignoreIncompleteToolCalls: true }
|
|
2711
|
-
);
|
|
2712
|
-
const modelMessages = [
|
|
2713
|
-
...systemHeader.trim() ? [{ role: "system", content: systemHeader }] : [],
|
|
2714
|
-
...systemContext.trim() ? [{ role: "system", content: systemContext }] : [],
|
|
2715
|
-
...convertedMessages
|
|
2716
|
-
];
|
|
2717
|
-
const promptCaching = applyPromptCachingToModelRequest({
|
|
2718
|
-
model: typeof model === "string" ? model : model.modelId,
|
|
2719
|
-
sessionId,
|
|
2720
|
-
messages: modelMessages
|
|
2721
|
-
});
|
|
2722
|
-
let activeTools = resolvedActiveTools ?? void 0;
|
|
2723
|
-
if (skillsRef.current.length === 0 && activeTools) {
|
|
2724
|
-
activeTools = activeTools.filter(
|
|
2725
|
-
(t) => t !== "Skill"
|
|
2726
|
-
);
|
|
2727
|
-
}
|
|
2728
|
-
return {
|
|
2729
|
-
messages: promptCaching.messages,
|
|
2730
|
-
providerOptions: mergeProviderOptions({
|
|
2731
|
-
current: resolvedGeneration?.providerOptions,
|
|
2732
|
-
patch: promptCaching.providerOptions
|
|
2733
|
-
}),
|
|
2734
|
-
activeTools
|
|
2735
|
-
};
|
|
2736
|
-
},
|
|
2737
|
-
onStepFinish: ({ usage: usage2 }) => {
|
|
2738
|
-
if (usage2) {
|
|
2739
|
-
usageSteps.push({
|
|
2740
|
-
stepIndex: stepIndexOffset + internalStepIndex,
|
|
2741
|
-
model: resolvedModel ?? "unknown",
|
|
2742
|
-
inputTokens: usage2.inputTokens ?? 0,
|
|
2743
|
-
outputTokens: usage2.outputTokens ?? 0,
|
|
2744
|
-
totalTokens: usage2.totalTokens ?? 0,
|
|
2745
|
-
cacheReadTokens: usage2.inputTokenDetails?.cacheReadTokens ?? 0,
|
|
2746
|
-
cacheWriteTokens: usage2.inputTokenDetails?.cacheWriteTokens ?? 0,
|
|
2747
|
-
reasoningTokens: usage2.outputTokenDetails?.reasoningTokens ?? 0
|
|
2748
|
-
});
|
|
2749
|
-
}
|
|
2750
|
-
internalStepIndex++;
|
|
2751
|
-
}
|
|
2752
|
-
});
|
|
2753
|
-
writer.merge(
|
|
2754
|
-
iterResult.toUIMessageStream({
|
|
2755
|
-
generateMessageId: () => assistantMessageId,
|
|
2756
|
-
onFinish: ({ messages }) => {
|
|
2757
|
-
for (const m of messages) {
|
|
2758
|
-
if (m.role === "assistant") {
|
|
2759
|
-
stepParts.push(...m.parts);
|
|
2760
|
-
}
|
|
2761
|
-
}
|
|
2762
|
-
}
|
|
2763
|
-
})
|
|
2764
|
-
);
|
|
2765
|
-
streamTextFinishReason = await iterResult.finishReason;
|
|
2766
|
-
}
|
|
2767
|
-
});
|
|
2768
|
-
await stream2.pipeTo(writable, {
|
|
2769
|
-
preventClose: true,
|
|
2770
|
-
preventAbort: true
|
|
2771
|
-
});
|
|
2772
|
-
} catch (err) {
|
|
2773
|
-
if (abortController.signal.aborted) {
|
|
2774
|
-
wasAborted = true;
|
|
2775
|
-
} else {
|
|
2776
|
-
throw err;
|
|
2777
|
-
}
|
|
2778
|
-
}
|
|
2779
|
-
if (abortController.signal.aborted) {
|
|
2780
|
-
wasAborted = true;
|
|
2781
|
-
}
|
|
2782
|
-
if (wasAborted) {
|
|
2783
|
-
const terminalStates = /* @__PURE__ */ new Set([
|
|
2784
|
-
"output-available",
|
|
2785
|
-
"output-error",
|
|
2786
|
-
"output-denied",
|
|
2787
|
-
"done"
|
|
2788
|
-
]);
|
|
2789
|
-
for (const part of stepParts) {
|
|
2790
|
-
if ("type" in part && typeof part.type === "string" && part.type.startsWith("tool-") && "state" in part && !terminalStates.has(part.state)) {
|
|
2791
|
-
part.state = "output-error";
|
|
2792
|
-
part.errorText = "interrupted";
|
|
2793
|
-
}
|
|
2794
|
-
}
|
|
2795
|
-
}
|
|
2796
|
-
const lastPart = interruptedLastPartRef.current;
|
|
2797
|
-
const newPartRecords = stepParts.map((uiPart, i) => {
|
|
2798
|
-
const index = nextPartIndexRef.current + i;
|
|
2799
|
-
if (lastPart != null && index > lastPart.index) {
|
|
2800
|
-
return null;
|
|
2801
|
-
}
|
|
2802
|
-
const useClientPart = lastPart != null && index === lastPart.index;
|
|
2803
|
-
const content = useClientPart ? lastPart.part : uiPart;
|
|
2804
|
-
const partId = "approval" in content && content.approval?.id ? approvalPartId(content.approval.id) : `part_${assistantMessageId}_${index}`;
|
|
2805
|
-
return {
|
|
2806
|
-
id: partId,
|
|
2807
|
-
index,
|
|
2808
|
-
messageId: assistantMessageId,
|
|
2809
|
-
sessionId,
|
|
2810
|
-
part: content
|
|
2811
|
-
};
|
|
2812
|
-
}).filter((r) => r !== null);
|
|
2813
|
-
const persistPromise = Promise.all([
|
|
2814
|
-
...newPartRecords.map(
|
|
2815
|
-
(record) => agent2.storage.part.set(record.id, record)
|
|
2816
|
-
),
|
|
2817
|
-
agent2.storage.session.update(sessionId, { state })
|
|
2818
|
-
]);
|
|
2819
|
-
nextPartIndexRef.current = lastPart != null ? Math.min(
|
|
2820
|
-
nextPartIndexRef.current + stepParts.length,
|
|
2821
|
-
lastPart.index + 1
|
|
2822
|
-
) : nextPartIndexRef.current + stepParts.length;
|
|
2823
|
-
const iterPendingApprovals = stepParts.filter(
|
|
2824
|
-
(p) => "state" in p && p.state === "approval-requested" && "approval" in p && !!p.approval?.id
|
|
2825
|
-
).map((p) => ({
|
|
2826
|
-
approvalId: p.approval.id,
|
|
2827
|
-
toolName: "type" in p ? String(p.type).replace("tool-", "") : "unknown"
|
|
2828
|
-
}));
|
|
2829
|
-
loopFinishReason = wasAborted ? "stop" : streamTextFinishReason ?? "unknown";
|
|
2830
|
-
const shouldBreak = iterPendingApprovals.length > 0 || loopFinishReason === "stop" || wasAborted || lastPart != null || currentMaxSteps != null && stepIndexOffset + usageSteps.length >= currentMaxSteps || iteration >= stepThroughput - 1;
|
|
2831
|
-
if (shouldBreak) {
|
|
2832
|
-
await persistPromise;
|
|
2833
|
-
allParts.push(...newPartRecords);
|
|
2834
|
-
allPendingApprovals.push(...iterPendingApprovals);
|
|
2835
|
-
break;
|
|
2836
|
-
}
|
|
2837
|
-
await persistPromise;
|
|
2838
|
-
allParts.push(...newPartRecords);
|
|
2839
|
-
uiMessages = assembleUIMessages({
|
|
2840
|
-
messages: messagesResult,
|
|
2841
|
-
parts: allParts,
|
|
2842
|
-
until: createdAt,
|
|
2843
|
-
includeQueued: true,
|
|
2844
|
-
excludeSubToolParts: true
|
|
2845
|
-
});
|
|
2846
|
-
}
|
|
2847
|
-
} finally {
|
|
2848
|
-
pollController.abort();
|
|
2849
|
-
throttledEmitStatus.dispose();
|
|
2850
|
-
}
|
|
2851
|
-
if (setStartedPromise) {
|
|
2852
|
-
await setStartedPromise;
|
|
2853
|
-
}
|
|
2854
|
-
doneStep({
|
|
2855
|
-
finishReason: loopFinishReason,
|
|
2856
|
-
wasAborted,
|
|
2857
|
-
iterations: internalStepIndex,
|
|
2858
|
-
pendingApprovals: allPendingApprovals.length
|
|
2859
|
-
});
|
|
2860
|
-
return {
|
|
2861
|
-
finishReason: loopFinishReason,
|
|
2862
|
-
lastPartIndex: nextPartIndexRef.current,
|
|
2863
|
-
usageSteps,
|
|
2864
|
-
pendingApprovals: allPendingApprovals,
|
|
2865
|
-
maxSteps: currentMaxSteps,
|
|
2866
|
-
discoveredSkills: skillsRef.current,
|
|
2867
|
-
context
|
|
2868
|
-
};
|
|
2869
|
-
}
|
|
2870
|
-
async function streamTextStep(...args) {
|
|
2871
|
-
"use step";
|
|
2872
|
-
return await streamText(...args);
|
|
2873
|
-
}
|
|
2874
|
-
async function processApprovals({
|
|
2875
|
-
allParts,
|
|
2876
|
-
messagesResult,
|
|
2877
|
-
createdAt,
|
|
2878
|
-
rawTools,
|
|
2879
|
-
abortController,
|
|
2880
|
-
toolContext,
|
|
2881
|
-
agent: agent2,
|
|
2882
|
-
stepLog,
|
|
2883
|
-
throttledEmitStatus,
|
|
2884
|
-
writer
|
|
2885
|
-
}) {
|
|
2886
|
-
const approvedParts = allParts.filter(
|
|
2887
|
-
(p) => p.part && "state" in p.part && p.part.state === "approval-responded" && "approval" in p.part && p.part.approval?.approved === true
|
|
2888
|
-
);
|
|
2889
|
-
if (approvedParts.length > 0) {
|
|
2890
|
-
stepLog.info("executing approved tools", {
|
|
2891
|
-
count: approvedParts.length
|
|
2892
|
-
});
|
|
2893
|
-
throttledEmitStatus({
|
|
2894
|
-
writer,
|
|
2895
|
-
status: { type: "processing-approvals" }
|
|
2896
|
-
});
|
|
2897
|
-
const preExecMessages = await convertToModelMessages(
|
|
2898
|
-
assembleUIMessages({
|
|
2899
|
-
messages: messagesResult,
|
|
2900
|
-
parts: allParts,
|
|
2901
|
-
until: createdAt,
|
|
2902
|
-
includeQueued: true,
|
|
2903
|
-
excludeSubToolParts: true
|
|
2904
|
-
}),
|
|
2905
|
-
{ ignoreIncompleteToolCalls: true }
|
|
2906
|
-
);
|
|
2907
|
-
await Promise.all(
|
|
2908
|
-
approvedParts.map(async (ap) => {
|
|
2909
|
-
if (!ap.part.type.startsWith("tool-")) {
|
|
2910
|
-
return;
|
|
2911
|
-
}
|
|
2912
|
-
const part = ap.part;
|
|
2913
|
-
const toolName = part.type.replace("tool-", "");
|
|
2914
|
-
const toolDef = rawTools[toolName];
|
|
2915
|
-
if (toolDef?.execute && part.input !== void 0) {
|
|
2916
|
-
try {
|
|
2917
|
-
const toolOutput = await toolDef.execute(part.input, {
|
|
2918
|
-
toolCallId: part.toolCallId,
|
|
2919
|
-
messages: preExecMessages,
|
|
2920
|
-
abortSignal: abortController.signal,
|
|
2921
|
-
experimental_context: toolContext
|
|
2922
|
-
});
|
|
2923
|
-
part.state = "output-available";
|
|
2924
|
-
part.output = toolOutput;
|
|
2925
|
-
writer.write({
|
|
2926
|
-
type: "tool-output-available",
|
|
2927
|
-
toolCallId: part.toolCallId,
|
|
2928
|
-
output: toolOutput
|
|
2929
|
-
});
|
|
2930
|
-
} catch (err) {
|
|
2931
|
-
part.state = "output-error";
|
|
2932
|
-
part.errorText = err instanceof Error ? err.message : String(err);
|
|
2933
|
-
writer.write({
|
|
2934
|
-
type: "tool-output-error",
|
|
2935
|
-
toolCallId: part.toolCallId,
|
|
2936
|
-
errorText: part.errorText
|
|
2937
|
-
});
|
|
2938
|
-
}
|
|
2939
|
-
await agent2.storage.part.set(ap.id, { ...ap, part });
|
|
2940
|
-
}
|
|
2941
|
-
})
|
|
2942
|
-
);
|
|
2943
|
-
}
|
|
2944
|
-
const pendingApprovalParts = allParts.filter(
|
|
2945
|
-
(p) => p.part.state === "approval-requested"
|
|
2946
|
-
);
|
|
2947
|
-
if (pendingApprovalParts.length > 0) {
|
|
2948
|
-
await Promise.all(
|
|
2949
|
-
pendingApprovalParts.map(async (p) => {
|
|
2950
|
-
const denied = {
|
|
2951
|
-
...p,
|
|
2952
|
-
part: {
|
|
2953
|
-
...p.part,
|
|
2954
|
-
state: "output-denied",
|
|
2955
|
-
approval: {
|
|
2956
|
-
...p.part.approval ?? {},
|
|
2957
|
-
approved: false,
|
|
2958
|
-
reason: "auto-denied: new message sent"
|
|
2959
|
-
}
|
|
2960
|
-
}
|
|
2961
|
-
};
|
|
2962
|
-
Object.assign(p, denied);
|
|
2963
|
-
await agent2.storage.part.set(p.id, denied);
|
|
2964
|
-
})
|
|
2965
|
-
);
|
|
2966
|
-
}
|
|
2967
|
-
}
|
|
2968
|
-
function emitStatus({
|
|
2969
|
-
writer,
|
|
2970
|
-
status,
|
|
2971
|
-
agent: agent2
|
|
2972
|
-
}) {
|
|
2973
|
-
writer.write({ type: "data-status", data: status, transient: true });
|
|
2974
|
-
agent2.hooks?.status?.(status);
|
|
2975
|
-
}
|
|
2976
|
-
var STATUS_THROTTLE_MS = 500;
|
|
2977
|
-
function createThrottledEmitStatus(agent2) {
|
|
2978
|
-
let timer = null;
|
|
2979
|
-
let pending = null;
|
|
2980
|
-
function throttled({
|
|
2981
|
-
writer,
|
|
2982
|
-
status
|
|
2983
|
-
}) {
|
|
2984
|
-
pending = { writer, status };
|
|
2985
|
-
if (timer !== null) {
|
|
2986
|
-
return;
|
|
2987
|
-
}
|
|
2988
|
-
flush();
|
|
2989
|
-
timer = setTimeout(() => {
|
|
2990
|
-
timer = null;
|
|
2991
|
-
if (pending) {
|
|
2992
|
-
flush();
|
|
2993
|
-
}
|
|
2994
|
-
}, STATUS_THROTTLE_MS);
|
|
2995
|
-
}
|
|
2996
|
-
function flush() {
|
|
2997
|
-
if (!pending) {
|
|
2998
|
-
return;
|
|
2999
|
-
}
|
|
3000
|
-
const { writer, status } = pending;
|
|
3001
|
-
pending = null;
|
|
3002
|
-
emitStatus({ writer, status, agent: agent2 });
|
|
3003
|
-
}
|
|
3004
|
-
throttled.dispose = () => {
|
|
3005
|
-
if (timer !== null) {
|
|
3006
|
-
clearTimeout(timer);
|
|
3007
|
-
timer = null;
|
|
3008
|
-
}
|
|
3009
|
-
flush();
|
|
3010
|
-
};
|
|
3011
|
-
return throttled;
|
|
3012
|
-
}
|
|
3013
|
-
async function resolveOption(value, args) {
|
|
3014
|
-
if (value === void 0) {
|
|
3015
|
-
return void 0;
|
|
3016
|
-
}
|
|
3017
|
-
if (typeof value === "function") {
|
|
3018
|
-
return await value(args);
|
|
3019
|
-
}
|
|
3020
|
-
return value;
|
|
3021
|
-
}
|
|
3022
|
-
async function resolveSystem(input, args) {
|
|
3023
|
-
const result = await resolveOption(input, args);
|
|
3024
|
-
if (!result) {
|
|
3025
|
-
return null;
|
|
3026
|
-
}
|
|
3027
|
-
return Array.isArray(result) ? result.filter(Boolean).join("\n") : result;
|
|
3028
|
-
}
|
|
3029
|
-
var BASE_SYSTEM_PROMPT = "You are an AI assistant with basic tools to interact with your environment. Explore and work freely.";
|
|
3030
|
-
function joinPromptSections(...sections) {
|
|
3031
|
-
return sections.filter((s) => s?.trim()).join("\n\n");
|
|
3032
|
-
}
|
|
3033
|
-
var backgroundProcessPrompt = `## Background Processes
|
|
3034
|
-
These background process instructions are for you to manipulate the processes, do not be to verbose to the user about the response details like "how to debug the process output" the user will have an UI.
|
|
3035
|
-
|
|
3036
|
-
Use \`waitUntil: 0\` for dev servers that should run indefinitely.
|
|
3037
|
-
It is a good practice to check the output log after running processes like dev servers to make sure they started correctly.
|
|
3038
|
-
|
|
3039
|
-
To run a background process:
|
|
3040
|
-
Bash({ command: "npm run dev", waitUntil: 0 })
|
|
3041
|
-
Returns immediately with \`commandId\`. The process keeps running in the sandbox.
|
|
3042
|
-
|
|
3043
|
-
To kill a process:
|
|
3044
|
-
Bash({ command: "ps aux | grep node" }) // Find the PID
|
|
3045
|
-
Bash({ command: "kill {pid}" }) // Graceful
|
|
3046
|
-
Bash({ command: "kill -9 {pid}" }) // Force
|
|
3047
|
-
`;
|
|
3048
|
-
function buildSkillsContext(skills) {
|
|
3049
|
-
if (skills.length === 0) {
|
|
3050
|
-
return "";
|
|
3051
|
-
}
|
|
3052
|
-
const skillLines = skills.map((s) => `- ${s.name}: ${s.description}`).join("\n");
|
|
3053
|
-
return `## Available Skills
|
|
3054
|
-
${skillLines}
|
|
3055
|
-
|
|
3056
|
-
${backgroundProcessPrompt}
|
|
3057
|
-
|
|
3058
|
-
Use the Skill tool to load a skill's full instructions before following it.`;
|
|
3059
|
-
}
|
|
3060
|
-
|
|
3061
|
-
// src/session/send.ts
|
|
3062
|
-
var DEFAULT_STEP_THROUGHPUT = 100;
|
|
3063
|
-
var ACTIVE_RUNS_KEY = /* @__PURE__ */ Symbol.for("experimental-agent:activeRuns");
|
|
3064
|
-
function getActiveRuns() {
|
|
3065
|
-
const g = globalThis;
|
|
3066
|
-
if (!g[ACTIVE_RUNS_KEY]) {
|
|
3067
|
-
g[ACTIVE_RUNS_KEY] = /* @__PURE__ */ new Map();
|
|
3068
|
-
}
|
|
3069
|
-
return g[ACTIVE_RUNS_KEY];
|
|
3070
|
-
}
|
|
3071
|
-
async function send(sessionContext, input, opts) {
|
|
3072
|
-
if (opts?.interruptIfStreaming) {
|
|
3073
|
-
const lastPart = typeof opts.interruptIfStreaming === "object" ? opts.interruptIfStreaming.lastPart : void 0;
|
|
3074
|
-
await interrupt(sessionContext, { lastPart });
|
|
3075
|
-
}
|
|
3076
|
-
const {
|
|
3077
|
-
workflowRunId,
|
|
3078
|
-
workflowWritable,
|
|
3079
|
-
existingPartCount,
|
|
3080
|
-
assistantMessageId,
|
|
3081
|
-
assistantMessageCreatedAt,
|
|
3082
|
-
state
|
|
3083
|
-
} = await errore2.tryAsync({
|
|
3084
|
-
try: () => initSessionStep({
|
|
3085
|
-
sessionContext,
|
|
3086
|
-
sessionId: sessionContext.sessionId,
|
|
3087
|
-
sandboxId: opts?.sandboxId,
|
|
3088
|
-
initialState: opts?.initialState,
|
|
3089
|
-
input
|
|
3090
|
-
}),
|
|
3091
|
-
catch: (e) => {
|
|
3092
|
-
if (e instanceof Error) {
|
|
3093
|
-
throw e;
|
|
3094
|
-
}
|
|
3095
|
-
throw new SendError({
|
|
3096
|
-
id: sessionContext.sessionId,
|
|
3097
|
-
reason: String(e),
|
|
3098
|
-
cause: e
|
|
3099
|
-
});
|
|
3100
|
-
}
|
|
3101
|
-
});
|
|
3102
|
-
const loopOpts = {
|
|
3103
|
-
sessionContext,
|
|
3104
|
-
assistantMessageId,
|
|
3105
|
-
createdAt: assistantMessageCreatedAt,
|
|
3106
|
-
context: opts?.context ?? {},
|
|
3107
|
-
state,
|
|
3108
|
-
lastPartIndex: existingPartCount,
|
|
3109
|
-
workflowRunId
|
|
3110
|
-
};
|
|
3111
|
-
if (workflowWritable) {
|
|
3112
|
-
await runLoop({ ...loopOpts, writable: workflowWritable });
|
|
3113
|
-
return { assistantMessageId, done: true };
|
|
3114
|
-
}
|
|
3115
|
-
const chunks = [];
|
|
3116
|
-
let notifyChunk;
|
|
3117
|
-
let onChunk = new Promise((r) => {
|
|
3118
|
-
notifyChunk = r;
|
|
3119
|
-
});
|
|
3120
|
-
const writable = new WritableStream({
|
|
3121
|
-
write(chunk) {
|
|
3122
|
-
chunks.push(chunk);
|
|
3123
|
-
const prev = notifyChunk;
|
|
3124
|
-
onChunk = new Promise((r) => {
|
|
3125
|
-
notifyChunk = r;
|
|
3126
|
-
});
|
|
3127
|
-
prev();
|
|
3128
|
-
}
|
|
3129
|
-
});
|
|
3130
|
-
const done = runLoop({ ...loopOpts, writable });
|
|
3131
|
-
const activeRun = {
|
|
3132
|
-
chunks,
|
|
3133
|
-
writable,
|
|
3134
|
-
done,
|
|
3135
|
-
get onChunk() {
|
|
3136
|
-
return onChunk;
|
|
3137
|
-
}
|
|
3138
|
-
};
|
|
3139
|
-
const activeRuns = getActiveRuns();
|
|
3140
|
-
activeRuns.set(assistantMessageId, activeRun);
|
|
3141
|
-
done.finally(() => activeRuns.delete(assistantMessageId));
|
|
3142
|
-
return { assistantMessageId, done: done.then(() => true) };
|
|
3143
|
-
}
|
|
3144
|
-
async function runLoop({
|
|
3145
|
-
workflowRunId,
|
|
3146
|
-
sessionContext,
|
|
3147
|
-
assistantMessageId,
|
|
3148
|
-
createdAt,
|
|
3149
|
-
context: initialContext,
|
|
3150
|
-
state,
|
|
3151
|
-
writable,
|
|
3152
|
-
lastPartIndex: initialPartIndex
|
|
3153
|
-
}) {
|
|
3154
|
-
const agent2 = sessionContext.agent;
|
|
3155
|
-
const log2 = createLogger({
|
|
3156
|
-
config: { ...agent2.options.logging, name: agent2.name },
|
|
3157
|
-
subsystem: "ai-loop"
|
|
3158
|
-
});
|
|
3159
|
-
const msgLog = log2.withContext({
|
|
3160
|
-
sessionId: sessionContext.sessionId,
|
|
3161
|
-
messageId: assistantMessageId
|
|
3162
|
-
});
|
|
3163
|
-
const doneMessage = msgLog.time("onMessage");
|
|
3164
|
-
let finishReason;
|
|
3165
|
-
let lastPartIndex = initialPartIndex;
|
|
3166
|
-
const usageSteps = [];
|
|
3167
|
-
let discoveredSkills = null;
|
|
3168
|
-
let context = initialContext;
|
|
3169
|
-
try {
|
|
3170
|
-
while (finishReason !== "stop") {
|
|
3171
|
-
const streamTextFn = workflowRunId ? streamTextStep : streamText;
|
|
3172
|
-
const throughput = workflowRunId ? 5 : DEFAULT_STEP_THROUGHPUT;
|
|
3173
|
-
const result = await streamTextFn({
|
|
3174
|
-
stepThroughput: throughput,
|
|
3175
|
-
assistantMessageId,
|
|
3176
|
-
agent: agent2,
|
|
3177
|
-
sessionId: sessionContext.sessionId,
|
|
3178
|
-
context,
|
|
3179
|
-
state,
|
|
3180
|
-
createdAt,
|
|
3181
|
-
writable,
|
|
3182
|
-
lastPartIndex,
|
|
3183
|
-
stepIndexOffset: usageSteps.length,
|
|
3184
|
-
discoveredSkills
|
|
3185
|
-
});
|
|
3186
|
-
finishReason = result.finishReason;
|
|
3187
|
-
lastPartIndex = result.lastPartIndex;
|
|
3188
|
-
usageSteps.push(...result.usageSteps);
|
|
3189
|
-
discoveredSkills = result.discoveredSkills;
|
|
3190
|
-
context = result.context;
|
|
3191
|
-
if (result.maxSteps != null && usageSteps.length >= result.maxSteps) {
|
|
3192
|
-
msgLog.info("reached maxSteps limit", { maxSteps: result.maxSteps });
|
|
3193
|
-
break;
|
|
3194
|
-
}
|
|
3195
|
-
if (result.pendingApprovals.length > 0) {
|
|
3196
|
-
msgLog.info("pending approvals, stopping loop", {
|
|
3197
|
-
count: result.pendingApprovals.length,
|
|
3198
|
-
tools: result.pendingApprovals.map((p) => p.toolName)
|
|
3199
|
-
});
|
|
3200
|
-
break;
|
|
3201
|
-
}
|
|
3202
|
-
}
|
|
3203
|
-
doneMessage({ totalSteps: usageSteps.length });
|
|
3204
|
-
} catch (err) {
|
|
3205
|
-
msgLog.error("AI loop failed", {
|
|
3206
|
-
error: err instanceof Error ? err.message : String(err)
|
|
3207
|
-
});
|
|
3208
|
-
throw err;
|
|
3209
|
-
} finally {
|
|
3210
|
-
await completeMessageStep({
|
|
3211
|
-
assistantMessageId,
|
|
3212
|
-
sessionContext,
|
|
3213
|
-
writable,
|
|
3214
|
-
usageSteps
|
|
3215
|
-
});
|
|
3216
|
-
}
|
|
3217
|
-
}
|
|
3218
|
-
async function initSessionStep({
|
|
3219
|
-
sessionContext,
|
|
3220
|
-
sessionId,
|
|
3221
|
-
sandboxId,
|
|
3222
|
-
initialState,
|
|
3223
|
-
input
|
|
3224
|
-
}) {
|
|
3225
|
-
"use step";
|
|
3226
|
-
let workflowRunId;
|
|
3227
|
-
let workflowWritable;
|
|
3228
|
-
try {
|
|
3229
|
-
const { getWorkflowMetadata, getWritable } = await import("workflow");
|
|
3230
|
-
workflowRunId = getWorkflowMetadata().workflowRunId;
|
|
3231
|
-
workflowWritable = getWritable();
|
|
3232
|
-
} catch {
|
|
3233
|
-
}
|
|
3234
|
-
const newMessages = [];
|
|
3235
|
-
const newParts = [];
|
|
3236
|
-
const newApprovals = [];
|
|
3237
|
-
if (Array.isArray(input)) {
|
|
3238
|
-
for (const i of input) {
|
|
3239
|
-
const { message, parts, approvals } = toMessageAndParts({
|
|
3240
|
-
sessionId: sessionContext.sessionId,
|
|
3241
|
-
input: i,
|
|
3242
|
-
defaultRole: "user"
|
|
3243
|
-
});
|
|
3244
|
-
if (message) {
|
|
3245
|
-
newMessages.push(message);
|
|
3246
|
-
}
|
|
3247
|
-
newParts.push(...parts);
|
|
3248
|
-
newApprovals.push(...approvals);
|
|
3249
|
-
}
|
|
3250
|
-
} else {
|
|
3251
|
-
const { message, parts, approvals } = toMessageAndParts({
|
|
3252
|
-
input,
|
|
3253
|
-
sessionId: sessionContext.sessionId,
|
|
3254
|
-
defaultRole: "user"
|
|
3255
|
-
});
|
|
3256
|
-
if (message) {
|
|
3257
|
-
newMessages.push(message);
|
|
3258
|
-
}
|
|
3259
|
-
newParts.push(...parts);
|
|
3260
|
-
newApprovals.push(...approvals);
|
|
3261
|
-
}
|
|
3262
|
-
const lastNewMessage = newMessages.at(-1);
|
|
3263
|
-
const reuseAssistant = lastNewMessage?.role === "assistant";
|
|
3264
|
-
const assistantMessageId = reuseAssistant ? lastNewMessage.id : `message_${ulid3()}`;
|
|
3265
|
-
const baseTime = Date.now();
|
|
3266
|
-
const assistantMessageCreatedAt = baseTime + newMessages.length;
|
|
3267
|
-
if (!reuseAssistant) {
|
|
3268
|
-
newMessages.push({
|
|
3269
|
-
id: assistantMessageId,
|
|
3270
|
-
sessionId: sessionContext.sessionId,
|
|
3271
|
-
role: "assistant",
|
|
3272
|
-
createdAt: assistantMessageCreatedAt,
|
|
3273
|
-
startedAt: null,
|
|
3274
|
-
completedAt: null,
|
|
3275
|
-
interruptedAt: null,
|
|
3276
|
-
interruptedLastPart: null,
|
|
3277
|
-
usage: null,
|
|
3278
|
-
workflowRunId: null,
|
|
3279
|
-
metadata: null
|
|
3280
|
-
});
|
|
3281
|
-
}
|
|
3282
|
-
const existingPartCount = reuseAssistant ? newParts.filter((p) => p.messageId === assistantMessageId).length : 0;
|
|
3283
|
-
let session = await sessionContext.agent.storage.session.get(sessionId);
|
|
3284
|
-
const now = Date.now();
|
|
3285
|
-
if (!session) {
|
|
3286
|
-
session = {
|
|
3287
|
-
id: sessionId,
|
|
3288
|
-
sandboxId: sandboxId ?? null,
|
|
3289
|
-
lastMessageId: null,
|
|
3290
|
-
createdAt: now,
|
|
3291
|
-
updatedAt: now
|
|
3292
|
-
};
|
|
3293
|
-
await sessionContext.agent.storage.session.set(session.id, session);
|
|
3294
|
-
} else if (sandboxId && sandboxId !== session.sandboxId) {
|
|
3295
|
-
session = { ...session, sandboxId, updatedAt: now };
|
|
3296
|
-
await sessionContext.agent.storage.session.update(session.id, {
|
|
3297
|
-
sandboxId
|
|
3298
|
-
});
|
|
3299
|
-
}
|
|
3300
|
-
await all({
|
|
3301
|
-
async saveMessages() {
|
|
3302
|
-
await Promise.all(
|
|
3303
|
-
newMessages.map(async (m, i) => {
|
|
3304
|
-
const existing = await sessionContext.agent.storage.message.get(m.id);
|
|
3305
|
-
if (existing) {
|
|
3306
|
-
return;
|
|
3307
|
-
}
|
|
3308
|
-
await sessionContext.agent.storage.message.set(m.id, {
|
|
3309
|
-
...m,
|
|
3310
|
-
createdAt: baseTime + i,
|
|
3311
|
-
workflowRunId: m.id === assistantMessageId ? workflowRunId ?? null : m.workflowRunId
|
|
3312
|
-
});
|
|
3313
|
-
})
|
|
3314
|
-
);
|
|
3315
|
-
},
|
|
3316
|
-
async saveParts() {
|
|
3317
|
-
await Promise.all(
|
|
3318
|
-
newParts.map(
|
|
3319
|
-
async (p) => sessionContext.agent.storage.part.set(p.id, p)
|
|
3320
|
-
)
|
|
3321
|
-
);
|
|
3322
|
-
},
|
|
3323
|
-
async resolveApprovals() {
|
|
3324
|
-
await Promise.all(
|
|
3325
|
-
newApprovals.map(async (a) => {
|
|
3326
|
-
const partId = approvalPartId(a.approvalId);
|
|
3327
|
-
const part = await sessionContext.agent.storage.part.get(partId);
|
|
3328
|
-
if (!part) {
|
|
3329
|
-
throw new ApprovalNotFoundError({
|
|
3330
|
-
id: sessionContext.sessionId,
|
|
3331
|
-
approvalId: a.approvalId
|
|
3332
|
-
});
|
|
3333
|
-
}
|
|
3334
|
-
await sessionContext.agent.storage.part.set(partId, {
|
|
3335
|
-
...part,
|
|
3336
|
-
part: {
|
|
3337
|
-
...part.part,
|
|
3338
|
-
state: a.approved ? "approval-responded" : "output-denied",
|
|
3339
|
-
approval: {
|
|
3340
|
-
id: a.approvalId,
|
|
3341
|
-
approved: a.approved,
|
|
3342
|
-
reason: a.reason
|
|
3343
|
-
}
|
|
3344
|
-
}
|
|
3345
|
-
});
|
|
3346
|
-
})
|
|
3347
|
-
);
|
|
3348
|
-
},
|
|
3349
|
-
async updateSession() {
|
|
3350
|
-
await sessionContext.agent.storage.session.set(session.id, {
|
|
3351
|
-
...session,
|
|
3352
|
-
lastMessageId: assistantMessageId,
|
|
3353
|
-
updatedAt: Date.now()
|
|
3354
|
-
});
|
|
3355
|
-
}
|
|
3356
|
-
});
|
|
3357
|
-
const state = session.state ? { ...session.state } : { ...initialState ?? {} };
|
|
3358
|
-
return {
|
|
3359
|
-
workflowRunId,
|
|
3360
|
-
workflowWritable,
|
|
3361
|
-
existingPartCount,
|
|
3362
|
-
assistantMessageId,
|
|
3363
|
-
assistantMessageCreatedAt,
|
|
3364
|
-
state
|
|
3365
|
-
};
|
|
3366
|
-
}
|
|
3367
|
-
async function completeMessageStep({
|
|
3368
|
-
assistantMessageId,
|
|
3369
|
-
sessionContext,
|
|
3370
|
-
writable,
|
|
3371
|
-
usageSteps
|
|
3372
|
-
}) {
|
|
3373
|
-
"use step";
|
|
3374
|
-
const log2 = createLogger({
|
|
3375
|
-
config: {
|
|
3376
|
-
...sessionContext.agent.options.logging,
|
|
3377
|
-
name: sessionContext.agent.name
|
|
3378
|
-
},
|
|
3379
|
-
subsystem: "ai-loop"
|
|
3380
|
-
});
|
|
3381
|
-
const msgLog = log2.withContext({
|
|
3382
|
-
sessionId: sessionContext.sessionId,
|
|
3383
|
-
messageId: assistantMessageId
|
|
3384
|
-
});
|
|
3385
|
-
const usage2 = usageSteps.length > 0 ? {
|
|
3386
|
-
steps: usageSteps,
|
|
3387
|
-
summary: {
|
|
3388
|
-
model: usageSteps[0]?.model ?? "unknown",
|
|
3389
|
-
inputTokens: usageSteps.reduce((a, s) => a + s.inputTokens, 0),
|
|
3390
|
-
outputTokens: usageSteps.reduce((a, s) => a + s.outputTokens, 0),
|
|
3391
|
-
totalTokens: usageSteps.reduce((a, s) => a + s.totalTokens, 0),
|
|
3392
|
-
cacheReadTokens: usageSteps.reduce(
|
|
3393
|
-
(a, s) => a + s.cacheReadTokens,
|
|
3394
|
-
0
|
|
3395
|
-
),
|
|
3396
|
-
cacheWriteTokens: usageSteps.reduce(
|
|
3397
|
-
(a, s) => a + s.cacheWriteTokens,
|
|
3398
|
-
0
|
|
3399
|
-
),
|
|
3400
|
-
reasoningTokens: usageSteps.reduce(
|
|
3401
|
-
(a, s) => a + s.reasoningTokens,
|
|
3402
|
-
0
|
|
3403
|
-
),
|
|
3404
|
-
stepCount: usageSteps.length
|
|
3405
|
-
}
|
|
3406
|
-
} : null;
|
|
3407
|
-
await Promise.all([
|
|
3408
|
-
sessionContext.agent.storage.message.update(assistantMessageId, {
|
|
3409
|
-
completedAt: Date.now(),
|
|
3410
|
-
usage: usage2
|
|
3411
|
-
}),
|
|
3412
|
-
writable.close().catch(() => void 0)
|
|
3413
|
-
]);
|
|
3414
|
-
msgLog.info("message completed", {
|
|
3415
|
-
steps: usageSteps.length,
|
|
3416
|
-
totalTokens: usage2?.summary.totalTokens
|
|
3417
|
-
});
|
|
3418
|
-
}
|
|
3419
|
-
function approvalPartId(approvalId) {
|
|
3420
|
-
return `part_${approvalId}`;
|
|
3421
|
-
}
|
|
3422
|
-
function replayActiveRun(active, startIndex = 0) {
|
|
3423
|
-
let cursor = startIndex;
|
|
3424
|
-
let cancelled = false;
|
|
3425
|
-
return new ReadableStream({
|
|
3426
|
-
async pull(controller) {
|
|
3427
|
-
while (cursor < active.chunks.length) {
|
|
3428
|
-
controller.enqueue(active.chunks[cursor++]);
|
|
3429
|
-
}
|
|
3430
|
-
while (!cancelled && cursor >= active.chunks.length) {
|
|
3431
|
-
const result = await Promise.race([
|
|
3432
|
-
active.onChunk.then(() => "chunk"),
|
|
3433
|
-
active.done.then(() => "done")
|
|
3434
|
-
]);
|
|
3435
|
-
while (cursor < active.chunks.length) {
|
|
3436
|
-
controller.enqueue(active.chunks[cursor++]);
|
|
3437
|
-
}
|
|
3438
|
-
if (result === "done") {
|
|
3439
|
-
controller.close();
|
|
3440
|
-
return;
|
|
3441
|
-
}
|
|
3442
|
-
}
|
|
3443
|
-
},
|
|
3444
|
-
cancel() {
|
|
3445
|
-
cancelled = true;
|
|
3446
|
-
}
|
|
3447
|
-
});
|
|
3448
|
-
}
|
|
3449
|
-
function toMessageAndParts({
|
|
3450
|
-
sessionId,
|
|
3451
|
-
id,
|
|
3452
|
-
input,
|
|
3453
|
-
defaultRole
|
|
3454
|
-
}) {
|
|
3455
|
-
let messageId = id ?? `message_${ulid3()}`;
|
|
3456
|
-
if (typeof input === "string") {
|
|
3457
|
-
const now2 = Date.now();
|
|
3458
|
-
return {
|
|
3459
|
-
approvals: [],
|
|
3460
|
-
message: {
|
|
3461
|
-
id: messageId,
|
|
3462
|
-
sessionId,
|
|
3463
|
-
role: defaultRole,
|
|
3464
|
-
createdAt: now2,
|
|
3465
|
-
startedAt: null,
|
|
3466
|
-
completedAt: null,
|
|
3467
|
-
interruptedAt: null,
|
|
3468
|
-
interruptedLastPart: null,
|
|
3469
|
-
usage: null,
|
|
3470
|
-
workflowRunId: null,
|
|
3471
|
-
metadata: null
|
|
3472
|
-
},
|
|
3473
|
-
parts: [
|
|
3474
|
-
{
|
|
3475
|
-
sessionId,
|
|
3476
|
-
messageId,
|
|
3477
|
-
id: `part_${messageId}_0`,
|
|
3478
|
-
index: 0,
|
|
3479
|
-
part: { type: "text", text: input }
|
|
3480
|
-
}
|
|
3481
|
-
]
|
|
3482
|
-
};
|
|
3483
|
-
}
|
|
3484
|
-
if ("type" in input && input.type === "approval") {
|
|
3485
|
-
return {
|
|
3486
|
-
message: void 0,
|
|
3487
|
-
parts: [],
|
|
3488
|
-
approvals: [input.approval]
|
|
3489
|
-
};
|
|
3490
|
-
}
|
|
3491
|
-
const msg = "type" in input && input.type === "message" ? input.message : input;
|
|
3492
|
-
if ("id" in msg && msg.id) {
|
|
3493
|
-
messageId = msg.id;
|
|
3494
|
-
}
|
|
3495
|
-
const now = Date.now();
|
|
3496
|
-
const metadata = "metadata" in msg && msg.metadata != null ? msg.metadata : null;
|
|
3497
|
-
return {
|
|
3498
|
-
approvals: [],
|
|
3499
|
-
message: {
|
|
3500
|
-
sessionId,
|
|
3501
|
-
id: messageId,
|
|
3502
|
-
createdAt: now,
|
|
3503
|
-
startedAt: null,
|
|
3504
|
-
completedAt: null,
|
|
3505
|
-
interruptedAt: null,
|
|
3506
|
-
interruptedLastPart: null,
|
|
3507
|
-
usage: null,
|
|
3508
|
-
workflowRunId: null,
|
|
3509
|
-
role: msg.role ?? defaultRole,
|
|
3510
|
-
metadata
|
|
3511
|
-
},
|
|
3512
|
-
parts: msg.parts.map((part, index) => {
|
|
3513
|
-
const ap = part;
|
|
3514
|
-
const id2 = ap.approval?.id ? approvalPartId(ap.approval.id) : `part_${messageId}_${index}`;
|
|
3515
|
-
return { sessionId, messageId, id: id2, index, part };
|
|
3516
|
-
})
|
|
3517
|
-
};
|
|
3518
|
-
}
|
|
3519
|
-
var SendError = class extends errore2.createTaggedError({
|
|
3520
|
-
name: "SendError",
|
|
3521
|
-
message: "Send failed for session $id: $reason"
|
|
3522
|
-
}) {
|
|
3523
|
-
};
|
|
3524
|
-
var ApprovalNotFoundError = class extends errore2.createTaggedError({
|
|
3525
|
-
name: "ApprovalNotFoundError",
|
|
3526
|
-
message: "Approval $approvalId not found in session $id"
|
|
3527
|
-
}) {
|
|
3528
|
-
};
|
|
3529
|
-
|
|
3530
|
-
// src/session/stream.ts
|
|
3531
|
-
import * as errore3 from "errore";
|
|
3532
|
-
function isWorkflowRun(arg) {
|
|
3533
|
-
return typeof arg === "object" && arg !== null && "getReadable" in arg && typeof arg.getReadable === "function";
|
|
3534
|
-
}
|
|
3535
|
-
async function stream(sessionContext, runOrOpts) {
|
|
3536
|
-
if (isWorkflowRun(runOrOpts)) {
|
|
3537
|
-
const reader = runOrOpts.getReadable().getReader();
|
|
3538
|
-
await reader.read().catch(() => {
|
|
3539
|
-
throw new StreamError({
|
|
3540
|
-
id: sessionContext.sessionId,
|
|
3541
|
-
reason: "stream() failed to read first chunk from workflow run"
|
|
3542
|
-
});
|
|
3543
|
-
});
|
|
3544
|
-
reader.cancel();
|
|
3545
|
-
return runOrOpts.getReadable();
|
|
3546
|
-
}
|
|
3547
|
-
const opts = runOrOpts;
|
|
3548
|
-
const session = await sessionContext.agent.storage.session.get(
|
|
3549
|
-
sessionContext.sessionId
|
|
3550
|
-
);
|
|
3551
|
-
if (!session) {
|
|
3552
|
-
throw new SessionNotFoundError({ id: sessionContext.sessionId });
|
|
3553
|
-
}
|
|
3554
|
-
const messageId = opts?.messageId ?? session.lastMessageId;
|
|
3555
|
-
if (!messageId) {
|
|
3556
|
-
throw new StreamError({
|
|
3557
|
-
id: sessionContext.sessionId,
|
|
3558
|
-
reason: "No message to stream"
|
|
3559
|
-
});
|
|
3560
|
-
}
|
|
3561
|
-
const activeRuns = getActiveRuns();
|
|
3562
|
-
const active = activeRuns.get(messageId);
|
|
3563
|
-
if (!active) {
|
|
3564
|
-
const message = await sessionContext.agent.storage.message.get(messageId);
|
|
3565
|
-
if (message?.workflowRunId) {
|
|
3566
|
-
const readable = await import("workflow/api").then(({ getRun }) => getRun(message.workflowRunId).getReadable()).catch(() => void 0);
|
|
3567
|
-
if (readable) {
|
|
3568
|
-
return readable;
|
|
3569
|
-
}
|
|
3570
|
-
}
|
|
3571
|
-
throw new StreamError({
|
|
3572
|
-
id: sessionContext.sessionId,
|
|
3573
|
-
reason: `No active run for message ${messageId}`
|
|
3574
|
-
});
|
|
3575
|
-
}
|
|
3576
|
-
return replayActiveRun(active, opts?.startIndex);
|
|
3577
|
-
}
|
|
3578
|
-
var StreamError = class extends errore3.createTaggedError({
|
|
3579
|
-
name: "StreamError",
|
|
3580
|
-
message: "Stream failed for session $id: $reason"
|
|
3581
|
-
}) {
|
|
3582
|
-
};
|
|
3583
|
-
|
|
3584
|
-
// src/session/update.ts
|
|
3585
|
-
async function update(sessionContext, opts) {
|
|
3586
|
-
"use step";
|
|
3587
|
-
const updates = Object.fromEntries(
|
|
3588
|
-
Object.entries(opts).filter(([, value]) => value !== void 0)
|
|
3589
|
-
);
|
|
3590
|
-
if (Object.keys(updates).length === 0) {
|
|
3591
|
-
return;
|
|
3592
|
-
}
|
|
3593
|
-
await sessionContext.agent.storage.session.update(sessionContext.sessionId, {
|
|
3594
|
-
...updates,
|
|
3595
|
-
updatedAt: Date.now()
|
|
3596
|
-
});
|
|
3597
|
-
}
|
|
3598
|
-
|
|
3599
|
-
// src/session/usage.ts
|
|
3600
|
-
async function usage(sessionContext) {
|
|
3601
|
-
"use step";
|
|
3602
|
-
const messages = await sessionContext.agent.storage.message.listBySession(
|
|
3603
|
-
sessionContext.sessionId
|
|
3604
|
-
);
|
|
3605
|
-
return computeSessionUsage(messages);
|
|
3606
|
-
}
|
|
3607
|
-
|
|
3608
|
-
// src/session/handle.ts
|
|
3609
|
-
function sessionHandle(agent2, id) {
|
|
3610
|
-
const sessionId = typeof id === "string" ? id : id?.id ?? `session_${ulid4()}`;
|
|
3611
|
-
const contexts = getSessionContexts(agent2);
|
|
3612
|
-
let sessionContext = contexts.get(sessionId);
|
|
3613
|
-
if (!sessionContext) {
|
|
3614
|
-
sessionContext = { agent: agent2, sessionId };
|
|
3615
|
-
contexts.set(sessionId, sessionContext);
|
|
3616
|
-
}
|
|
3617
|
-
return {
|
|
3618
|
-
id: sessionId,
|
|
3619
|
-
send: send.bind(
|
|
3620
|
-
null,
|
|
3621
|
-
sessionContext
|
|
3622
|
-
),
|
|
3623
|
-
stream: stream.bind(null, sessionContext),
|
|
3624
|
-
history: history.bind(null, sessionContext),
|
|
3625
|
-
interrupt: interrupt.bind(null, sessionContext),
|
|
3626
|
-
usage: usage.bind(null, sessionContext),
|
|
3627
|
-
update: update.bind(null, sessionContext),
|
|
3628
|
-
sandbox: lazySandboxHandle(agent2, sessionId)
|
|
3629
|
-
};
|
|
3630
|
-
}
|
|
3631
|
-
|
|
3632
|
-
// src/agent/registry.ts
|
|
3633
|
-
import * as errore4 from "errore";
|
|
3634
|
-
import { z as z3 } from "zod";
|
|
3635
|
-
var AgentStatus = z3.discriminatedUnion("type", [
|
|
3636
|
-
z3.object({ type: z3.literal("sandbox-setup") }),
|
|
3637
|
-
z3.object({ type: z3.literal("sandbox-setup-cold") }),
|
|
3638
|
-
z3.object({ type: z3.literal("loading-skills") }),
|
|
3639
|
-
z3.object({ type: z3.literal("processing-approvals") }),
|
|
3640
|
-
z3.object({ type: z3.literal("needs-approval") }),
|
|
3641
|
-
z3.object({ type: z3.literal("thinking") }),
|
|
3642
|
-
z3.object({ type: z3.literal("custom"), status: z3.string() })
|
|
3643
|
-
]);
|
|
3644
|
-
var AgentNotFoundError = class extends errore4.createTaggedError({
|
|
3645
|
-
name: "AgentNotFoundError",
|
|
3646
|
-
message: `Agent "$agentName" not found in registry.
|
|
3647
|
-
|
|
3648
|
-
hint: agent() must be called before workflow steps execute.
|
|
3649
|
-
Valid locations: module scope, or inside a "use workflow" body.
|
|
3650
|
-
|
|
3651
|
-
// Module scope (static agents)
|
|
3652
|
-
export const myAgent = agent("$agentName", { ... });
|
|
3653
|
-
|
|
3654
|
-
// Workflow body (dynamic agents)
|
|
3655
|
-
async function myWorkflow({ input }) {
|
|
3656
|
-
"use workflow";
|
|
3657
|
-
const myAgent = agent("$agentName", { ... });
|
|
3658
|
-
...
|
|
3659
|
-
}`
|
|
3660
|
-
}) {
|
|
3661
|
-
};
|
|
3662
|
-
var AGENT_REGISTRY_KEY = /* @__PURE__ */ Symbol.for("experimental-agent-registry");
|
|
3663
|
-
function getAgentRegistry() {
|
|
3664
|
-
const g = globalThis;
|
|
3665
|
-
let registry = g[AGENT_REGISTRY_KEY];
|
|
3666
|
-
if (!registry) {
|
|
3667
|
-
registry = /* @__PURE__ */ new Map();
|
|
3668
|
-
g[AGENT_REGISTRY_KEY] = registry;
|
|
3669
|
-
}
|
|
3670
|
-
return registry;
|
|
3671
|
-
}
|
|
3672
|
-
function registerAgent(name, agent2) {
|
|
3673
|
-
getAgentRegistry().set(name, agent2);
|
|
3674
|
-
}
|
|
3675
|
-
function getAgent(name, required) {
|
|
3676
|
-
const agent2 = getAgentRegistry().get(name);
|
|
3677
|
-
if (required && !agent2) {
|
|
3678
|
-
throw new AgentNotFoundError({ agentName: name });
|
|
3679
|
-
}
|
|
3680
|
-
return agent2;
|
|
3681
|
-
}
|
|
3682
|
-
|
|
3683
|
-
// src/agent/client.ts
|
|
3684
|
-
var sessionContextsMap = /* @__PURE__ */ new WeakMap();
|
|
3685
|
-
var sandboxContextsMap = /* @__PURE__ */ new WeakMap();
|
|
3686
|
-
function getSessionContexts(agent2) {
|
|
3687
|
-
let map = sessionContextsMap.get(agent2);
|
|
3688
|
-
if (!map) {
|
|
3689
|
-
map = /* @__PURE__ */ new Map();
|
|
3690
|
-
sessionContextsMap.set(agent2, map);
|
|
3691
|
-
}
|
|
3692
|
-
return map;
|
|
3693
|
-
}
|
|
3694
|
-
function getSandboxContexts(agent2) {
|
|
3695
|
-
let map = sandboxContextsMap.get(agent2);
|
|
3696
|
-
if (!map) {
|
|
3697
|
-
map = /* @__PURE__ */ new Map();
|
|
3698
|
-
sandboxContextsMap.set(agent2, map);
|
|
3699
|
-
}
|
|
3700
|
-
return map;
|
|
3701
|
-
}
|
|
3702
|
-
var Agent = class {
|
|
3703
|
-
name;
|
|
3704
|
-
options;
|
|
3705
|
-
constructor(name, options) {
|
|
3706
|
-
this.name = name;
|
|
3707
|
-
this.options = options ?? {};
|
|
3708
|
-
this.session = sessionHandle.bind(null, this);
|
|
3709
|
-
this.sandbox = sandboxHandle.bind(
|
|
3710
|
-
null,
|
|
3711
|
-
this
|
|
3712
|
-
);
|
|
3713
|
-
}
|
|
3714
|
-
static [WORKFLOW_SERIALIZE](instance) {
|
|
3715
|
-
return { name: instance.name };
|
|
3716
|
-
}
|
|
3717
|
-
static [WORKFLOW_DESERIALIZE](data) {
|
|
3718
|
-
return getAgent(data.name, true);
|
|
3719
|
-
}
|
|
3720
|
-
_resolvedStorage;
|
|
3721
|
-
get storage() {
|
|
3722
|
-
if (this._resolvedStorage) {
|
|
3723
|
-
return this._resolvedStorage;
|
|
3724
|
-
}
|
|
3725
|
-
if (this.options.storage) {
|
|
3726
|
-
this._resolvedStorage = toStorage(this.options.storage);
|
|
3727
|
-
return this._resolvedStorage;
|
|
3728
|
-
}
|
|
3729
|
-
const log2 = createLogger({
|
|
3730
|
-
config: { ...this.options.logging, name: this.name },
|
|
3731
|
-
subsystem: "storage"
|
|
3732
|
-
});
|
|
3733
|
-
if (shouldFallbackToKV2()) {
|
|
3734
|
-
log2.info(
|
|
3735
|
-
`No storage adapter configured \u2014 using KV2 (namespace: "${this.name}").`
|
|
3736
|
-
);
|
|
3737
|
-
this._resolvedStorage = toStorage(
|
|
3738
|
-
kvStorageFallback({ prefix: this.name })
|
|
3739
|
-
);
|
|
3740
|
-
return this._resolvedStorage;
|
|
3741
|
-
}
|
|
3742
|
-
log2.warn(
|
|
3743
|
-
"No storage adapter configured \u2014 using localStorage(). Data will not persist across restarts."
|
|
3744
|
-
);
|
|
3745
|
-
this._resolvedStorage = toStorage(localStorage());
|
|
3746
|
-
return this._resolvedStorage;
|
|
3747
|
-
}
|
|
3748
|
-
get tools() {
|
|
3749
|
-
return { ...builtInTools, ...this.options.tools };
|
|
3750
|
-
}
|
|
3751
|
-
get hooks() {
|
|
3752
|
-
return this.options.hooks ?? {};
|
|
3753
|
-
}
|
|
3754
|
-
session;
|
|
3755
|
-
sandbox;
|
|
3756
|
-
};
|
|
3757
|
-
function agent(name, options) {
|
|
3758
|
-
const instance = new Agent(name, options);
|
|
3759
|
-
registerAgent(name, instance);
|
|
3760
|
-
return instance;
|
|
3761
|
-
}
|
|
2
|
+
AgentStatus,
|
|
3
|
+
MessageNotFoundError,
|
|
4
|
+
SandboxError,
|
|
5
|
+
SandboxNotFoundError,
|
|
6
|
+
SessionNotFoundError,
|
|
7
|
+
StorageConflictError,
|
|
8
|
+
StorageError,
|
|
9
|
+
agent,
|
|
10
|
+
builtinToolNames,
|
|
11
|
+
tool
|
|
12
|
+
} from "./chunk-EH4L2CPW.mjs";
|
|
13
|
+
import {
|
|
14
|
+
basePathForAgent
|
|
15
|
+
} from "./chunk-PH2FXKOU.mjs";
|
|
16
|
+
import "./chunk-C4VSUEY2.mjs";
|
|
17
|
+
import "./chunk-CS2SEUAA.mjs";
|
|
18
|
+
import "./chunk-MSWINCCM.mjs";
|
|
19
|
+
import "./chunk-BJTO5JO5.mjs";
|
|
3762
20
|
|
|
3763
21
|
// src/rpc/rpc.ts
|
|
22
|
+
import { openapi } from "@elysiajs/openapi";
|
|
3764
23
|
import { createUIMessageStreamResponse } from "ai";
|
|
3765
24
|
import Elysia from "elysia";
|
|
25
|
+
import z3 from "zod";
|
|
3766
26
|
|
|
3767
27
|
// src/rpc/agentContract.ts
|
|
3768
|
-
import
|
|
28
|
+
import z2 from "zod";
|
|
3769
29
|
|
|
3770
30
|
// src/rpc/schemas.ts
|
|
3771
|
-
import { z
|
|
3772
|
-
var TextPart =
|
|
3773
|
-
type:
|
|
3774
|
-
text:
|
|
31
|
+
import { z } from "zod";
|
|
32
|
+
var TextPart = z.object({
|
|
33
|
+
type: z.literal("text"),
|
|
34
|
+
text: z.string()
|
|
3775
35
|
});
|
|
3776
|
-
var ReasoningPart =
|
|
3777
|
-
type:
|
|
3778
|
-
text:
|
|
36
|
+
var ReasoningPart = z.object({
|
|
37
|
+
type: z.literal("reasoning"),
|
|
38
|
+
text: z.string()
|
|
3779
39
|
});
|
|
3780
|
-
var FilePart =
|
|
3781
|
-
type:
|
|
3782
|
-
mediaType:
|
|
3783
|
-
url:
|
|
3784
|
-
filename:
|
|
40
|
+
var FilePart = z.object({
|
|
41
|
+
type: z.literal("file"),
|
|
42
|
+
mediaType: z.string(),
|
|
43
|
+
url: z.string(),
|
|
44
|
+
filename: z.string().optional()
|
|
3785
45
|
});
|
|
3786
|
-
var SourceUrlPart =
|
|
3787
|
-
type:
|
|
3788
|
-
sourceId:
|
|
3789
|
-
url:
|
|
3790
|
-
title:
|
|
46
|
+
var SourceUrlPart = z.object({
|
|
47
|
+
type: z.literal("source-url"),
|
|
48
|
+
sourceId: z.string(),
|
|
49
|
+
url: z.string(),
|
|
50
|
+
title: z.string().optional()
|
|
3791
51
|
});
|
|
3792
|
-
var StepStartPart =
|
|
3793
|
-
type:
|
|
52
|
+
var StepStartPart = z.object({
|
|
53
|
+
type: z.literal("step-start")
|
|
3794
54
|
});
|
|
3795
|
-
function toolPartSchemas(name,
|
|
3796
|
-
const input =
|
|
3797
|
-
const output =
|
|
3798
|
-
const type =
|
|
3799
|
-
const approvalId =
|
|
55
|
+
function toolPartSchemas(name, tool2) {
|
|
56
|
+
const input = tool2.inputSchema ?? z.unknown();
|
|
57
|
+
const output = tool2.outputSchema ?? z.unknown();
|
|
58
|
+
const type = z.literal(`tool-${name}`);
|
|
59
|
+
const approvalId = z.object({ id: z.string() });
|
|
3800
60
|
const approvalApproved = approvalId.extend({
|
|
3801
|
-
approved:
|
|
3802
|
-
reason:
|
|
61
|
+
approved: z.literal(true),
|
|
62
|
+
reason: z.string().optional()
|
|
3803
63
|
});
|
|
3804
64
|
const approvalDenied = approvalId.extend({
|
|
3805
|
-
approved:
|
|
3806
|
-
reason:
|
|
65
|
+
approved: z.literal(false),
|
|
66
|
+
reason: z.string().optional()
|
|
3807
67
|
});
|
|
3808
68
|
const approvalResponse = approvalId.extend({
|
|
3809
|
-
approved:
|
|
3810
|
-
reason:
|
|
69
|
+
approved: z.boolean(),
|
|
70
|
+
reason: z.string().optional()
|
|
3811
71
|
});
|
|
3812
72
|
return [
|
|
3813
|
-
|
|
73
|
+
z.object({
|
|
3814
74
|
type,
|
|
3815
|
-
toolCallId:
|
|
3816
|
-
state:
|
|
3817
|
-
input:
|
|
75
|
+
toolCallId: z.string(),
|
|
76
|
+
state: z.literal("input-streaming"),
|
|
77
|
+
input: z.unknown()
|
|
3818
78
|
}),
|
|
3819
|
-
|
|
79
|
+
z.object({
|
|
3820
80
|
type,
|
|
3821
|
-
toolCallId:
|
|
3822
|
-
state:
|
|
81
|
+
toolCallId: z.string(),
|
|
82
|
+
state: z.literal("input-available"),
|
|
3823
83
|
input
|
|
3824
84
|
}),
|
|
3825
|
-
|
|
85
|
+
z.object({
|
|
3826
86
|
type,
|
|
3827
|
-
toolCallId:
|
|
3828
|
-
state:
|
|
87
|
+
toolCallId: z.string(),
|
|
88
|
+
state: z.literal("approval-requested"),
|
|
3829
89
|
input,
|
|
3830
90
|
approval: approvalId
|
|
3831
91
|
}),
|
|
3832
|
-
|
|
92
|
+
z.object({
|
|
3833
93
|
type,
|
|
3834
|
-
toolCallId:
|
|
3835
|
-
state:
|
|
94
|
+
toolCallId: z.string(),
|
|
95
|
+
state: z.literal("approval-responded"),
|
|
3836
96
|
input,
|
|
3837
97
|
approval: approvalResponse
|
|
3838
98
|
}),
|
|
3839
|
-
|
|
99
|
+
z.object({
|
|
3840
100
|
type,
|
|
3841
|
-
toolCallId:
|
|
3842
|
-
state:
|
|
101
|
+
toolCallId: z.string(),
|
|
102
|
+
state: z.literal("output-available"),
|
|
3843
103
|
input,
|
|
3844
104
|
output,
|
|
3845
105
|
approval: approvalApproved.optional()
|
|
3846
106
|
}),
|
|
3847
|
-
|
|
107
|
+
z.object({
|
|
3848
108
|
type,
|
|
3849
|
-
toolCallId:
|
|
3850
|
-
state:
|
|
109
|
+
toolCallId: z.string(),
|
|
110
|
+
state: z.literal("output-error"),
|
|
3851
111
|
input,
|
|
3852
|
-
errorText:
|
|
112
|
+
errorText: z.string(),
|
|
3853
113
|
approval: approvalApproved.optional()
|
|
3854
114
|
}),
|
|
3855
|
-
|
|
115
|
+
z.object({
|
|
3856
116
|
type,
|
|
3857
|
-
toolCallId:
|
|
3858
|
-
state:
|
|
117
|
+
toolCallId: z.string(),
|
|
118
|
+
state: z.literal("output-denied"),
|
|
3859
119
|
input,
|
|
3860
120
|
approval: approvalDenied
|
|
3861
121
|
})
|
|
3862
122
|
];
|
|
3863
123
|
}
|
|
3864
|
-
var UsageSummary =
|
|
3865
|
-
model:
|
|
3866
|
-
inputTokens:
|
|
3867
|
-
outputTokens:
|
|
3868
|
-
totalTokens:
|
|
3869
|
-
cacheReadTokens:
|
|
3870
|
-
cacheWriteTokens:
|
|
3871
|
-
reasoningTokens:
|
|
3872
|
-
stepCount:
|
|
124
|
+
var UsageSummary = z.object({
|
|
125
|
+
model: z.string(),
|
|
126
|
+
inputTokens: z.number(),
|
|
127
|
+
outputTokens: z.number(),
|
|
128
|
+
totalTokens: z.number(),
|
|
129
|
+
cacheReadTokens: z.number(),
|
|
130
|
+
cacheWriteTokens: z.number(),
|
|
131
|
+
reasoningTokens: z.number(),
|
|
132
|
+
stepCount: z.number()
|
|
3873
133
|
});
|
|
3874
|
-
var SessionUsage =
|
|
3875
|
-
total: UsageSummary.extend({ messageCount:
|
|
3876
|
-
byMessageId:
|
|
134
|
+
var SessionUsage = z.object({
|
|
135
|
+
total: UsageSummary.extend({ messageCount: z.number() }),
|
|
136
|
+
byMessageId: z.record(z.string(), UsageSummary.nullable())
|
|
3877
137
|
});
|
|
3878
138
|
function buildSessionHistorySchema(agent2) {
|
|
3879
|
-
return
|
|
3880
|
-
messages:
|
|
3881
|
-
streamingMessageId:
|
|
139
|
+
return z.object({
|
|
140
|
+
messages: z.array(buildUIMessageSchema(agent2.tools)),
|
|
141
|
+
streamingMessageId: z.string().nullable(),
|
|
3882
142
|
usage: SessionUsage
|
|
3883
143
|
});
|
|
3884
144
|
}
|
|
3885
145
|
function buildUIMessagePartSchema(tools) {
|
|
3886
146
|
const toolParts = Object.entries(tools).flatMap(
|
|
3887
|
-
([name,
|
|
147
|
+
([name, tool2]) => toolPartSchemas(name, tool2)
|
|
3888
148
|
);
|
|
3889
|
-
const
|
|
149
|
+
const all = [
|
|
3890
150
|
TextPart,
|
|
3891
151
|
ReasoningPart,
|
|
3892
152
|
FilePart,
|
|
@@ -3894,13 +154,13 @@ function buildUIMessagePartSchema(tools) {
|
|
|
3894
154
|
StepStartPart,
|
|
3895
155
|
...toolParts
|
|
3896
156
|
];
|
|
3897
|
-
return
|
|
157
|
+
return z.union(all);
|
|
3898
158
|
}
|
|
3899
159
|
function buildUIMessageSchema(tools) {
|
|
3900
|
-
return
|
|
3901
|
-
id:
|
|
3902
|
-
role:
|
|
3903
|
-
parts:
|
|
160
|
+
return z.object({
|
|
161
|
+
id: z.string(),
|
|
162
|
+
role: z.enum(["system", "user", "assistant"]),
|
|
163
|
+
parts: z.array(buildUIMessagePartSchema(tools))
|
|
3904
164
|
});
|
|
3905
165
|
}
|
|
3906
166
|
|
|
@@ -3908,36 +168,36 @@ function buildUIMessageSchema(tools) {
|
|
|
3908
168
|
function agentContract(agent2) {
|
|
3909
169
|
const contract = {
|
|
3910
170
|
"session.get": {
|
|
3911
|
-
params:
|
|
3912
|
-
sessionId:
|
|
171
|
+
params: z2.object({
|
|
172
|
+
sessionId: z2.string()
|
|
3913
173
|
}),
|
|
3914
174
|
response: buildSessionHistorySchema(agent2)
|
|
3915
175
|
},
|
|
3916
176
|
"session.post": {
|
|
3917
|
-
params:
|
|
3918
|
-
sessionId:
|
|
177
|
+
params: z2.object({
|
|
178
|
+
sessionId: z2.string()
|
|
3919
179
|
}),
|
|
3920
|
-
body:
|
|
3921
|
-
response:
|
|
180
|
+
body: z2.union([z2.string(), buildUIMessageSchema(agent2.tools)]),
|
|
181
|
+
response: z2.any()
|
|
3922
182
|
},
|
|
3923
183
|
"reconnect.get": {
|
|
3924
|
-
params:
|
|
3925
|
-
sessionId:
|
|
184
|
+
params: z2.object({
|
|
185
|
+
sessionId: z2.string()
|
|
3926
186
|
}),
|
|
3927
|
-
response:
|
|
187
|
+
response: z2.any()
|
|
3928
188
|
},
|
|
3929
189
|
"interrupt.post": {
|
|
3930
|
-
params:
|
|
3931
|
-
sessionId:
|
|
190
|
+
params: z2.object({
|
|
191
|
+
sessionId: z2.string()
|
|
3932
192
|
}),
|
|
3933
|
-
body:
|
|
3934
|
-
lastPart:
|
|
3935
|
-
index:
|
|
193
|
+
body: z2.object({
|
|
194
|
+
lastPart: z2.object({
|
|
195
|
+
index: z2.number(),
|
|
3936
196
|
part: buildUIMessagePartSchema(agent2.tools)
|
|
3937
197
|
}).optional()
|
|
3938
198
|
}).optional(),
|
|
3939
|
-
response:
|
|
3940
|
-
success:
|
|
199
|
+
response: z2.object({
|
|
200
|
+
success: z2.boolean()
|
|
3941
201
|
})
|
|
3942
202
|
}
|
|
3943
203
|
};
|
|
@@ -3948,7 +208,37 @@ function agentContract(agent2) {
|
|
|
3948
208
|
function handleRequest(agent2, options = {}) {
|
|
3949
209
|
const { basePath = basePathForAgent(agent2.name), workflow } = options;
|
|
3950
210
|
const contract = agentContract(agent2);
|
|
3951
|
-
const router = new Elysia({ prefix: basePath }).
|
|
211
|
+
const router = new Elysia({ prefix: basePath }).use(
|
|
212
|
+
openapi({
|
|
213
|
+
provider: null,
|
|
214
|
+
specPath: "/openapi.json",
|
|
215
|
+
exclude: { staticFile: false },
|
|
216
|
+
documentation: {
|
|
217
|
+
info: {
|
|
218
|
+
title: `${agent2.name} API`,
|
|
219
|
+
version: "1.0.0"
|
|
220
|
+
},
|
|
221
|
+
components: {
|
|
222
|
+
schemas: {
|
|
223
|
+
// @ts-expect-error - elysia is annoying
|
|
224
|
+
AgentStatus: z3.toJSONSchema(AgentStatus, {
|
|
225
|
+
target: "openapi-3.0"
|
|
226
|
+
})
|
|
227
|
+
},
|
|
228
|
+
securitySchemes: {
|
|
229
|
+
bearerAuth: {
|
|
230
|
+
type: "http",
|
|
231
|
+
scheme: "bearer",
|
|
232
|
+
bearerFormat: "JWT"
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
mapJsonSchema: {
|
|
238
|
+
zod: (schema) => z3.toJSONSchema(schema, { target: "openapi-3.0" })
|
|
239
|
+
}
|
|
240
|
+
})
|
|
241
|
+
).get(
|
|
3952
242
|
"/:sessionId",
|
|
3953
243
|
async ({ params }) => {
|
|
3954
244
|
const next = async () => {
|
|
@@ -3975,14 +265,20 @@ function handleRequest(agent2, options = {}) {
|
|
|
3975
265
|
const next = async () => {
|
|
3976
266
|
const session = agent2.session(params.sessionId);
|
|
3977
267
|
if (workflow) {
|
|
3978
|
-
const { start
|
|
3979
|
-
const result = await
|
|
3980
|
-
|
|
3981
|
-
|
|
268
|
+
const { start } = await import("workflow/api");
|
|
269
|
+
const result = await start(
|
|
270
|
+
// for some reason, start() requires SessionSendArgs<AnyAgent>
|
|
271
|
+
// to avoid blowing up types
|
|
272
|
+
// we want to put the typeguard here so consumers of handleRequest still work fine
|
|
273
|
+
workflow,
|
|
274
|
+
[params.sessionId, body]
|
|
275
|
+
);
|
|
276
|
+
const stream2 = await session.stream(result);
|
|
277
|
+
return createUIMessageStreamResponse({ stream: stream2 });
|
|
3982
278
|
}
|
|
3983
279
|
await session.send(body);
|
|
3984
|
-
const
|
|
3985
|
-
return createUIMessageStreamResponse({ stream
|
|
280
|
+
const stream = await session.stream();
|
|
281
|
+
return createUIMessageStreamResponse({ stream });
|
|
3986
282
|
};
|
|
3987
283
|
const override = options.overrides?.["session.post"];
|
|
3988
284
|
if (override) {
|
|
@@ -3996,8 +292,8 @@ function handleRequest(agent2, options = {}) {
|
|
|
3996
292
|
async ({ params }) => {
|
|
3997
293
|
const next = async () => {
|
|
3998
294
|
const session = agent2.session(params.sessionId);
|
|
3999
|
-
const
|
|
4000
|
-
return createUIMessageStreamResponse({ stream
|
|
295
|
+
const stream = await session.stream();
|
|
296
|
+
return createUIMessageStreamResponse({ stream });
|
|
4001
297
|
};
|
|
4002
298
|
const override = options.overrides?.["reconnect.get"];
|
|
4003
299
|
if (override) {
|
|
@@ -4035,6 +331,6 @@ export {
|
|
|
4035
331
|
agent,
|
|
4036
332
|
builtinToolNames,
|
|
4037
333
|
handleRequest,
|
|
4038
|
-
|
|
334
|
+
tool
|
|
4039
335
|
};
|
|
4040
|
-
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2FnZW50L2NsaWVudC50cyIsICIuLi9zcmMvc2FuZGJveC9oYW5kbGUudHMiLCAiLi4vc3JjL2FnZW50L2lzLXZlcmNlbC50cyIsICIuLi9zcmMvZXJyb3JzLnRzIiwgIi4uL3NyYy9zYW5kYm94L3NldHVwLnRzIiwgIi4uL3NyYy9zYW5kYm94L2V4ZWMudHMiLCAiLi4vc3JjL3NhbmRib3gvZ2V0LWRvbWFpbi50cyIsICIuLi9zcmMvc2FuZGJveC9nZXQtc3RhdHVzLnRzIiwgIi4uL3NyYy9zYW5kYm94L2tpbGwudHMiLCAiLi4vc3JjL3NhbmRib3gvcmVhZC1maWxlLnRzIiwgIi4uL3NyYy9zYW5kYm94L3NuYXBzaG90LnRzIiwgIi4uL3NyYy9zYW5kYm94L3N0YXJ0LnRzIiwgIi4uL3NyYy9zYW5kYm94L3N0b3AudHMiLCAiLi4vc3JjL3NhbmRib3gvdXBkYXRlLW5ldHdvcmstcG9saWN5LnRzIiwgIi4uL3NyYy9zYW5kYm94L3dyaXRlLWZpbGVzLnRzIiwgIi4uL3NyYy9zZXNzaW9uL2hhbmRsZS50cyIsICIuLi9zcmMvdXRpbHMvdWkudHMiLCAiLi4vc3JjL3V0aWxzL3VzYWdlLnRzIiwgIi4uL3NyYy9zZXNzaW9uL2hpc3RvcnkudHMiLCAiLi4vc3JjL3Nlc3Npb24vaW50ZXJydXB0LnRzIiwgIi4uL3NyYy9zZXNzaW9uL3NlbmQudHMiLCAiLi4vc3JjL3Nlc3Npb24vYWktbG9vcC9zdHJlYW0tdGV4dC50cyIsICIuLi9zcmMvc2tpbGxzL3BhcnNlci50cyIsICIuLi9zcmMvc2tpbGxzL2Rpc2NvdmVyLnRzIiwgIi4uL3NyYy9za2lsbHMvcmVzb2x2ZS1ob3N0LnRzIiwgIi4uL3NyYy9za2lsbHMvcmVzb2x2ZS1pbmxpbmUudHMiLCAiLi4vc3JjL3NraWxscy9yZXNvbHZlLXJlbW90ZS50cyIsICIuLi9zcmMvc2tpbGxzL3Jlc29sdmUudHMiLCAiLi4vc3JjL3Rvb2xzL2luZGV4LnRzIiwgIi4uL3NyYy90b29scy9qYXZhc2NyaXB0LnRzIiwgIi4uL3NyYy90b29scy9uZWVkcy1hcHByb3ZhbC50cyIsICIuLi9zcmMvdG9vbHMvdG9vbC50cyIsICIuLi9zcmMvdXRpbHMvcHJvbXB0LWNhY2hlLnRzIiwgIi4uL3NyYy9zZXNzaW9uL3N0cmVhbS50cyIsICIuLi9zcmMvc2Vzc2lvbi91cGRhdGUudHMiLCAiLi4vc3JjL3Nlc3Npb24vdXNhZ2UudHMiLCAiLi4vc3JjL2FnZW50L3JlZ2lzdHJ5LnRzIiwgIi4uL3NyYy9ycGMvcnBjLnRzIiwgIi4uL3NyYy9ycGMvYWdlbnRDb250cmFjdC50cyIsICIuLi9zcmMvcnBjL3NjaGVtYXMudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCB7IFdPUktGTE9XX0RFU0VSSUFMSVpFLCBXT1JLRkxPV19TRVJJQUxJWkUgfSBmcm9tIFwiQHdvcmtmbG93L3NlcmRlXCI7XG5pbXBvcnQgdHlwZSB7IEdhdGV3YXlNb2RlbElkLCBJbmZlclVJVG9vbHMsIFRvb2xTZXQsIFVJTWVzc2FnZSB9IGZyb20gXCJhaVwiO1xuaW1wb3J0IHR5cGUgeyB6IH0gZnJvbSBcInpvZFwiO1xuaW1wb3J0IHR5cGUgeyBTYW5kYm94QmluZGluZywgU2FuZGJveEluc3RhbmNlIH0gZnJvbSBcIi4uL3NhbmRib3gvYWRhcHRlclwiO1xuaW1wb3J0IHR5cGUgeyBTYW5kYm94Q29udGV4dCB9IGZyb20gXCIuLi9zYW5kYm94L2hhbmRsZVwiO1xuaW1wb3J0IHsgc2FuZGJveEhhbmRsZSB9IGZyb20gXCIuLi9zYW5kYm94L2hhbmRsZVwiO1xuaW1wb3J0IHsgdHlwZSBTZXNzaW9uQ29udGV4dCwgc2Vzc2lvbkhhbmRsZSB9IGZyb20gXCIuLi9zZXNzaW9uL2hhbmRsZVwiO1xuaW1wb3J0IHR5cGUgeyBTa2lsbElucHV0IH0gZnJvbSBcIi4uL3NraWxscy90eXBlc1wiO1xuaW1wb3J0IHsgdHlwZSBTdG9yYWdlLCB0eXBlIFN0b3JhZ2VJbnB1dCwgdG9TdG9yYWdlIH0gZnJvbSBcIi4uL3N0b3JhZ2UvYWRhcHRlclwiO1xuaW1wb3J0IHsga3ZTdG9yYWdlRmFsbGJhY2sgfSBmcm9tIFwiLi4vc3RvcmFnZS9iaW5kaW5ncy9rdlwiO1xuaW1wb3J0IHsgbG9jYWxTdG9yYWdlIH0gZnJvbSBcIi4uL3N0b3JhZ2UvZW50cnlcIjtcbmltcG9ydCB7IHNob3VsZEZhbGxiYWNrVG9LVjIgfSBmcm9tIFwiLi4vc3RvcmFnZS9zaG91bGQtZmFsbGJhY2sta3YyXCI7XG5pbXBvcnQgdHlwZSB7IEdlbmVyYXRpb25PcHRpb25zIH0gZnJvbSBcIi4uL3N0b3JhZ2UvdHlwZXNcIjtcbmltcG9ydCB7IHR5cGUgQnVpbHRJblRvb2xOYW1lLCBidWlsdEluVG9vbHMgfSBmcm9tIFwiLi4vdG9vbHNcIjtcbmltcG9ydCB0eXBlIHsgTG9nZ2luZ0NvbmZpZyB9IGZyb20gXCIuLi91dGlscy9sb2dnZXJcIjtcbmltcG9ydCB7IGNyZWF0ZUxvZ2dlciB9IGZyb20gXCIuLi91dGlscy9sb2dnZXJcIjtcbmltcG9ydCB7XG4gIHR5cGUgQWdlbnREYXRhVHlwZXMsXG4gIHR5cGUgQWdlbnRIb29rcyxcbiAgZ2V0QWdlbnQsXG4gIHR5cGUgTmVlZHNBcHByb3ZhbE1hcCxcbiAgcmVnaXN0ZXJBZ2VudCxcbn0gZnJvbSBcIi4vcmVnaXN0cnlcIjtcblxuLy8gXHUyNTAwXHUyNTAwXHUyNTAwIFJlc29sdmFibGUgXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXG5cbmV4cG9ydCB0eXBlIFJlc29sdmFibGVBcmdzPFxuICBUQ29udGV4dCA9IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICBUb29scyBleHRlbmRzIFRvb2xTZXQgPSBUb29sU2V0LFxuICBUU3RhdGUgPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbj4gPSB7XG4gIGNvbnRleHQ6IFRDb250ZXh0O1xuICBzZXNzaW9uSWQ6IHN0cmluZztcbiAgc2FuZGJveDogU2FuZGJveEluc3RhbmNlO1xuICBtZXNzYWdlczogVUlNZXNzYWdlPHVua25vd24sIEFnZW50RGF0YVR5cGVzLCBJbmZlclVJVG9vbHM8VG9vbHM+PltdO1xuICBzdGF0ZTogUmVhZG9ubHk8VFN0YXRlPjtcbn07XG5cbmV4cG9ydCB0eXBlIFJlc29sdmFibGU8XG4gIFQsXG4gIFRDb250ZXh0ID0gUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gIFRvb2xzIGV4dGVuZHMgVG9vbFNldCA9IFRvb2xTZXQsXG4gIFRTdGF0ZSA9IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuPiA9IFQgfCAoKGFyZ3M6IFJlc29sdmFibGVBcmdzPFRDb250ZXh0LCBUb29scywgVFN0YXRlPikgPT4gVCB8IFByb21pc2U8VD4pO1xuXG4vLyBcdTI1MDBcdTI1MDBcdTI1MDAgU2Vzc2lvbiBEZWZhdWx0cyBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcblxuZXhwb3J0IHR5cGUgU2Vzc2lvbkRlZmF1bHRzPFxuICBUb29scyBleHRlbmRzIFRvb2xTZXQgPSBUb29sU2V0LFxuICBUQ29udGV4dCBleHRlbmRzIFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0gUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gIFRTdGF0ZSBleHRlbmRzIFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0gUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4+ID0ge1xuICBtb2RlbD86IFJlc29sdmFibGU8R2F0ZXdheU1vZGVsSWQgfCB1bmRlZmluZWQsIFRDb250ZXh0LCBUb29scywgVFN0YXRlPjtcbiAgc3lzdGVtPzogUmVzb2x2YWJsZTxzdHJpbmcgfCBzdHJpbmdbXSB8IHVuZGVmaW5lZCwgVENvbnRleHQsIFRvb2xzLCBUU3RhdGU+O1xuICBnZW5lcmF0aW9uPzogUmVzb2x2YWJsZTxcbiAgICBHZW5lcmF0aW9uT3B0aW9ucyB8IHVuZGVmaW5lZCxcbiAgICBUQ29udGV4dCxcbiAgICBUb29scyxcbiAgICBUU3RhdGVcbiAgPjtcbiAgYWN0aXZlVG9vbHM/OiBSZXNvbHZhYmxlPFxuICAgIHJlYWRvbmx5IChFeHRyYWN0PGtleW9mIFRvb2xzLCBzdHJpbmc+IHwgQnVpbHRJblRvb2xOYW1lKVtdIHwgdW5kZWZpbmVkLFxuICAgIFRDb250ZXh0LFxuICAgIFRvb2xzLFxuICAgIFRTdGF0ZVxuICA+O1xuICBza2lsbHM/OiBSZXNvbHZhYmxlPFNraWxsSW5wdXRbXSB8IHVuZGVmaW5lZCwgVENvbnRleHQsIFRvb2xzLCBUU3RhdGU+O1xufTtcblxuLy8gXHUyNTAwXHUyNTAwXHUyNTAwIEFnZW50IE9wdGlvbnMgXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXG5cbmV4cG9ydCB0eXBlIEFnZW50T3B0aW9uczxcbiAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiBkZWZhdWx0IGFsbG93cyB0eXBlLWVyYXNlZCB1c2FnZVxuICBUb29scyBleHRlbmRzIFRvb2xTZXQgPSBhbnksXG4gIFRTYW5kYm94QmluZGluZ3MgZXh0ZW5kcyBTYW5kYm94QmluZGluZyB8IFNhbmRib3hCaW5kaW5nW10gPSBTYW5kYm94QmluZGluZyxcbiAgVENvbnRleHQgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IFJlY29yZDxzdHJpbmcsIG5ldmVyPixcbiAgVFN0YXRlIGV4dGVuZHMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgVE1lc3NhZ2VNZXRhZGF0YSA9IHVua25vd24sXG4+ID0gU2Vzc2lvbkRlZmF1bHRzPFRvb2xzLCBUQ29udGV4dCwgVFN0YXRlPiAmIHtcbiAgc3RvcmFnZT86IFN0b3JhZ2VJbnB1dDtcbiAgc2FuZGJveD86IFRTYW5kYm94QmluZGluZ3M7XG4gIHRvb2xzPzogVG9vbHM7XG4gIGhvb2tzPzogQWdlbnRIb29rcztcbiAgbmVlZHNBcHByb3ZhbD86IE5lZWRzQXBwcm92YWxNYXA8VG9vbHM+O1xuICBjb250ZXh0U2NoZW1hPzogei5ab2RUeXBlPFRDb250ZXh0PjtcbiAgc3RhdGVTY2hlbWE/OiB6LlpvZFR5cGU8VFN0YXRlPjtcbiAgbWVzc2FnZU1ldGFkYXRhU2NoZW1hPzogei5ab2RUeXBlPFRNZXNzYWdlTWV0YWRhdGE+O1xuICBsb2dnaW5nPzogT21pdDxMb2dnaW5nQ29uZmlnLCBcIm5hbWVcIj47XG59O1xuXG4vLyBcdTI1MDBcdTI1MDBcdTI1MDAgSW50ZXJuYWwgY29udGV4dCBjYWNoZXMgKGhpZGRlbiBmcm9tIHB1YmxpYyBBUEkpIFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFxuXG5jb25zdCBzZXNzaW9uQ29udGV4dHNNYXAgPSBuZXcgV2Vha01hcDxvYmplY3QsIE1hcDxzdHJpbmcsIFNlc3Npb25Db250ZXh0Pj4oKTtcbmNvbnN0IHNhbmRib3hDb250ZXh0c01hcCA9IG5ldyBXZWFrTWFwPG9iamVjdCwgTWFwPHN0cmluZywgU2FuZGJveENvbnRleHQ+PigpO1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0U2Vzc2lvbkNvbnRleHRzKFxuICBhZ2VudDogQW55QWdlbnRcbik6IE1hcDxzdHJpbmcsIFNlc3Npb25Db250ZXh0PiB7XG4gIGxldCBtYXAgPSBzZXNzaW9uQ29udGV4dHNNYXAuZ2V0KGFnZW50KTtcbiAgaWYgKCFtYXApIHtcbiAgICBtYXAgPSBuZXcgTWFwKCk7XG4gICAgc2Vzc2lvbkNvbnRleHRzTWFwLnNldChhZ2VudCwgbWFwKTtcbiAgfVxuICByZXR1cm4gbWFwO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0U2FuZGJveENvbnRleHRzKFxuICBhZ2VudDogQW55QWdlbnRcbik6IE1hcDxzdHJpbmcsIFNhbmRib3hDb250ZXh0PiB7XG4gIGxldCBtYXAgPSBzYW5kYm94Q29udGV4dHNNYXAuZ2V0KGFnZW50KTtcbiAgaWYgKCFtYXApIHtcbiAgICBtYXAgPSBuZXcgTWFwKCk7XG4gICAgc2FuZGJveENvbnRleHRzTWFwLnNldChhZ2VudCwgbWFwKTtcbiAgfVxuICByZXR1cm4gbWFwO1xufVxuXG4vLyBcdTI1MDBcdTI1MDBcdTI1MDAgQWdlbnQgQ2xhc3MgXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXG5cbi8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogaW50ZW50aW9uYWxseSBlcmFzZWQgXHUyMDEzIHVzaW5nIGBhbnlgIGF2b2lkcyBjb250cmF2YXJpYW5jZSBpc3N1ZXMgd2l0aCB0b29sLXR5cGVkIG1ldGhvZHMgbGlrZSBgc2VuZGBcbmV4cG9ydCB0eXBlIEFueUFnZW50ID0gQWdlbnQ8YW55LCBhbnksIGFueSwgYW55LCBhbnk+O1xuXG5leHBvcnQgdHlwZSBJbmZlclNlc3Npb248QWdlbnQgZXh0ZW5kcyBBbnlBZ2VudCA9IEFueUFnZW50PiA9IFJldHVyblR5cGU8XG4gIEFnZW50W1wic2Vzc2lvblwiXVxuPjtcbmV4cG9ydCB0eXBlIFNlc3Npb25TZW5kQXJnczxcbiAgQWdlbnQgZXh0ZW5kcyBBbnlBZ2VudCxcbiAgU2Vzc2lvbiBleHRlbmRzIEluZmVyU2Vzc2lvbjxBZ2VudD4gPSBJbmZlclNlc3Npb248QWdlbnQ+LFxuPiA9IFBhcmFtZXRlcnM8U2Vzc2lvbltcInNlbmRcIl0+O1xuXG5leHBvcnQgY2xhc3MgQWdlbnQ8XG4gIFRNZXNzYWdlTWV0YWRhdGEgPSB1bmtub3duLFxuICBUb29scyBleHRlbmRzIFRvb2xTZXQgPSBUb29sU2V0LFxuICBUU2FuZGJveEJpbmRpbmdzIGV4dGVuZHMgU2FuZGJveEJpbmRpbmcgfCBTYW5kYm94QmluZGluZ1tdID0gU2FuZGJveEJpbmRpbmcsXG4gIFRDb250ZXh0IGV4dGVuZHMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSBSZWNvcmQ8c3RyaW5nLCBuZXZlcj4sXG4gIFRTdGF0ZSBleHRlbmRzIFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0gUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4+IHtcbiAgcmVhZG9ubHkgbmFtZTogc3RyaW5nO1xuICBvcHRpb25zOiBBZ2VudE9wdGlvbnM8XG4gICAgVG9vbHMsXG4gICAgVFNhbmRib3hCaW5kaW5ncyxcbiAgICBUQ29udGV4dCxcbiAgICBUU3RhdGUsXG4gICAgVE1lc3NhZ2VNZXRhZGF0YVxuICA+O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBvcHRpb25zPzogQWdlbnRPcHRpb25zPFxuICAgICAgVG9vbHMsXG4gICAgICBUU2FuZGJveEJpbmRpbmdzLFxuICAgICAgVENvbnRleHQsXG4gICAgICBUU3RhdGUsXG4gICAgICBUTWVzc2FnZU1ldGFkYXRhXG4gICAgPlxuICApIHtcbiAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnMgPz8ge307XG4gICAgdGhpcy5zZXNzaW9uID0gKHNlc3Npb25IYW5kbGU8XG4gICAgICBUb29scyxcbiAgICAgIFRDb250ZXh0LFxuICAgICAgVFNhbmRib3hCaW5kaW5ncyxcbiAgICAgIFRNZXNzYWdlTWV0YWRhdGEsXG4gICAgICBUU3RhdGVcbiAgICA+KS5iaW5kKG51bGwsIHRoaXMgYXMgdW5rbm93biBhcyBBbnlBZ2VudCk7XG4gICAgdGhpcy5zYW5kYm94ID0gKHNhbmRib3hIYW5kbGU8VFNhbmRib3hCaW5kaW5ncz4pLmJpbmQoXG4gICAgICBudWxsLFxuICAgICAgdGhpcyBhcyB1bmtub3duIGFzIEFueUFnZW50XG4gICAgKTtcbiAgfVxuXG4gIHN0YXRpYyBbV09SS0ZMT1dfU0VSSUFMSVpFXShpbnN0YW5jZTogQW55QWdlbnQpIHtcbiAgICByZXR1cm4geyBuYW1lOiBpbnN0YW5jZS5uYW1lIH07XG4gIH1cblxuICBzdGF0aWMgW1dPUktGTE9XX0RFU0VSSUFMSVpFXShkYXRhOiB7IG5hbWU6IHN0cmluZyB9KSB7XG4gICAgcmV0dXJuIGdldEFnZW50KGRhdGEubmFtZSwgdHJ1ZSk7XG4gIH1cblxuICBwcml2YXRlIF9yZXNvbHZlZFN0b3JhZ2U6IFN0b3JhZ2UgfCB1bmRlZmluZWQ7XG5cbiAgZ2V0IHN0b3JhZ2UoKTogU3RvcmFnZSB7XG4gICAgaWYgKHRoaXMuX3Jlc29sdmVkU3RvcmFnZSkge1xuICAgICAgcmV0dXJuIHRoaXMuX3Jlc29sdmVkU3RvcmFnZTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5vcHRpb25zLnN0b3JhZ2UpIHtcbiAgICAgIHRoaXMuX3Jlc29sdmVkU3RvcmFnZSA9IHRvU3RvcmFnZSh0aGlzLm9wdGlvbnMuc3RvcmFnZSk7XG4gICAgICByZXR1cm4gdGhpcy5fcmVzb2x2ZWRTdG9yYWdlO1xuICAgIH1cblxuICAgIGNvbnN0IGxvZyA9IGNyZWF0ZUxvZ2dlcih7XG4gICAgICBjb25maWc6IHsgLi4udGhpcy5vcHRpb25zLmxvZ2dpbmcsIG5hbWU6IHRoaXMubmFtZSB9LFxuICAgICAgc3Vic3lzdGVtOiBcInN0b3JhZ2VcIixcbiAgICB9KTtcblxuICAgIGlmIChzaG91bGRGYWxsYmFja1RvS1YyKCkpIHtcbiAgICAgIGxvZy5pbmZvKFxuICAgICAgICBgTm8gc3RvcmFnZSBhZGFwdGVyIGNvbmZpZ3VyZWQgXHUyMDE0IHVzaW5nIEtWMiAobmFtZXNwYWNlOiBcIiR7dGhpcy5uYW1lfVwiKS5gXG4gICAgICApO1xuICAgICAgdGhpcy5fcmVzb2x2ZWRTdG9yYWdlID0gdG9TdG9yYWdlKFxuICAgICAgICBrdlN0b3JhZ2VGYWxsYmFjayh7IHByZWZpeDogdGhpcy5uYW1lIH0pXG4gICAgICApO1xuICAgICAgcmV0dXJuIHRoaXMuX3Jlc29sdmVkU3RvcmFnZTtcbiAgICB9XG5cbiAgICBsb2cud2FybihcbiAgICAgIFwiTm8gc3RvcmFnZSBhZGFwdGVyIGNvbmZpZ3VyZWQgXHUyMDE0IHVzaW5nIGxvY2FsU3RvcmFnZSgpLiBEYXRhIHdpbGwgbm90IHBlcnNpc3QgYWNyb3NzIHJlc3RhcnRzLlwiXG4gICAgKTtcbiAgICB0aGlzLl9yZXNvbHZlZFN0b3JhZ2UgPSB0b1N0b3JhZ2UobG9jYWxTdG9yYWdlKCkpO1xuICAgIHJldHVybiB0aGlzLl9yZXNvbHZlZFN0b3JhZ2U7XG4gIH1cblxuICBnZXQgdG9vbHMoKSB7XG4gICAgcmV0dXJuIHsgLi4uYnVpbHRJblRvb2xzLCAuLi50aGlzLm9wdGlvbnMudG9vbHMgfSBhcyB0eXBlb2YgYnVpbHRJblRvb2xzICZcbiAgICAgIFRvb2xzO1xuICB9XG5cbiAgZ2V0IGhvb2tzKCk6IEFnZW50SG9va3Mge1xuICAgIHJldHVybiB0aGlzLm9wdGlvbnMuaG9va3MgPz8ge307XG4gIH1cblxuICByZWFkb25seSBzZXNzaW9uO1xuXG4gIHJlYWRvbmx5IHNhbmRib3g7XG5cbiAgLyoqIFBoYW50b20gcHJvcGVydHkgZm9yIHR5cGUgaW5mZXJlbmNlLiBVc2UgYHR5cGVvZiBteUFnZW50LiRVSU1lc3NhZ2VgIHRvIGdldCB0aGUgdHlwZWQgVUlNZXNzYWdlLiAqL1xuICBkZWNsYXJlIHJlYWRvbmx5ICRVSU1lc3NhZ2U6IFVJTWVzc2FnZTxcbiAgICBUTWVzc2FnZU1ldGFkYXRhLFxuICAgIEFnZW50RGF0YVR5cGVzLFxuICAgIEluZmVyVUlUb29sczx0eXBlb2YgYnVpbHRJblRvb2xzICYgVG9vbHM+XG4gID47XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhZ2VudDxcbiAgVG9vbHMgZXh0ZW5kcyBUb29sU2V0ID0gVG9vbFNldCxcbiAgVFNhbmRib3hCaW5kaW5ncyBleHRlbmRzIFNhbmRib3hCaW5kaW5nIHwgU2FuZGJveEJpbmRpbmdbXSA9IFNhbmRib3hCaW5kaW5nLFxuICBUQ29udGV4dCBleHRlbmRzIFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0gUmVjb3JkPHN0cmluZywgbmV2ZXI+LFxuICBUU3RhdGUgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICBUTWVzc2FnZU1ldGFkYXRhID0gdW5rbm93bixcbj4oXG4gIG5hbWU6IHN0cmluZyxcbiAgb3B0aW9ucz86IEFnZW50T3B0aW9uczxcbiAgICBUb29scyxcbiAgICBUU2FuZGJveEJpbmRpbmdzLFxuICAgIFRDb250ZXh0LFxuICAgIFRTdGF0ZSxcbiAgICBUTWVzc2FnZU1ldGFkYXRhXG4gID5cbikge1xuICBjb25zdCBpbnN0YW5jZSA9IG5ldyBBZ2VudDxcbiAgICBUTWVzc2FnZU1ldGFkYXRhLFxuICAgIFRvb2xzLFxuICAgIFRTYW5kYm94QmluZGluZ3MsXG4gICAgVENvbnRleHQsXG4gICAgVFN0YXRlXG4gID4obmFtZSwgb3B0aW9ucyk7XG4gIHJlZ2lzdGVyQWdlbnQobmFtZSwgaW5zdGFuY2UpO1xuICByZXR1cm4gaW5zdGFuY2U7XG59XG5cbi8vIFJlLWV4cG9ydCBldmVyeXRoaW5nIGZyb20gcmVnaXN0cnkgc28gZXhpc3RpbmcgaW1wb3J0cyBmcm9tIFwiLi9hZ2VudC9jbGllbnRcIiBrZWVwIHdvcmtpbmcuXG5leHBvcnQge1xuICB0eXBlIEFnZW50RGF0YVR5cGVzLFxuICB0eXBlIEFnZW50SG9va3MsXG4gIEFnZW50U3RhdHVzLFxuICBnZXRBZ2VudCxcbiAgdHlwZSBJbmZlclVJTWVzc2FnZSxcbiAgdHlwZSBOZWVkc0FwcHJvdmFsTWFwLFxuICByZWdpc3RlckFnZW50LFxuICB0eXBlIFR5cGVkVUlNZXNzYWdlLFxufSBmcm9tIFwiLi9yZWdpc3RyeVwiO1xuIiwgImltcG9ydCB7IHVsaWQgfSBmcm9tIFwidWxpZFwiO1xuaW1wb3J0IHR5cGUgeyBBbnlBZ2VudCB9IGZyb20gXCIuLi9hZ2VudC9jbGllbnRcIjtcbmltcG9ydCB7IGdldFNhbmRib3hDb250ZXh0cyB9IGZyb20gXCIuLi9hZ2VudC9jbGllbnRcIjtcbmltcG9ydCB0eXBlIHsgU2FuZGJveEJpbmRpbmcsIFNhbmRib3hJbnN0YW5jZSB9IGZyb20gXCIuL2FkYXB0ZXJcIjtcbmltcG9ydCB7IGV4ZWMgfSBmcm9tIFwiLi9leGVjXCI7XG5pbXBvcnQgeyBnZXREb21haW4gfSBmcm9tIFwiLi9nZXQtZG9tYWluXCI7XG5pbXBvcnQgeyBnZXRTdGF0dXMgfSBmcm9tIFwiLi9nZXQtc3RhdHVzXCI7XG5pbXBvcnQgeyBraWxsIH0gZnJvbSBcIi4va2lsbFwiO1xuaW1wb3J0IHsgcmVhZEZpbGUgfSBmcm9tIFwiLi9yZWFkLWZpbGVcIjtcbmltcG9ydCB7IHNldHVwIH0gZnJvbSBcIi4vc2V0dXBcIjtcbmltcG9ydCB7IHNuYXBzaG90IH0gZnJvbSBcIi4vc25hcHNob3RcIjtcbmltcG9ydCB7IHN0YXJ0IH0gZnJvbSBcIi4vc3RhcnRcIjtcbmltcG9ydCB7IHN0b3AgfSBmcm9tIFwiLi9zdG9wXCI7XG5pbXBvcnQgeyB1cGRhdGVOZXR3b3JrUG9saWN5IH0gZnJvbSBcIi4vdXBkYXRlLW5ldHdvcmstcG9saWN5XCI7XG5pbXBvcnQgeyB3cml0ZUZpbGVzIH0gZnJvbSBcIi4vd3JpdGUtZmlsZXNcIjtcblxuZXhwb3J0IHR5cGUgU2FuZGJveENvbnRleHQgPSB7XG4gIGFnZW50OiBBbnlBZ2VudDtcbiAgc2FuZGJveElkOiBzdHJpbmcgfCBudWxsO1xuICBfcGVuZGluZ1NldHVwPzogUHJvbWlzZTxTYW5kYm94SW5zdGFuY2U+O1xuICBfY3dkPzogc3RyaW5nO1xuICBfc2Vzc2lvbklkPzogc3RyaW5nO1xufTtcblxuZXhwb3J0IHR5cGUgU2FuZGJveE9wdGlvbnMgPSB7XG4gIGlkPzogc3RyaW5nO1xufTtcblxuZXhwb3J0IHR5cGUgU2FuZGJveEhhbmRsZTxcbiAgVFNhbmRib3hCaW5kaW5ncyBleHRlbmRzIFNhbmRib3hCaW5kaW5nIHwgU2FuZGJveEJpbmRpbmdbXSA9IFNhbmRib3hCaW5kaW5nLFxuPiA9IFJldHVyblR5cGU8dHlwZW9mIHNhbmRib3hIYW5kbGU8VFNhbmRib3hCaW5kaW5ncz4+O1xuXG5leHBvcnQgZnVuY3Rpb24gc2FuZGJveEhhbmRsZTxcbiAgVFNhbmRib3hCaW5kaW5ncyBleHRlbmRzIFNhbmRib3hCaW5kaW5nIHwgU2FuZGJveEJpbmRpbmdbXSxcbj4oYWdlbnQ6IEFueUFnZW50LCBpZD86IHN0cmluZyB8IFNhbmRib3hPcHRpb25zKSB7XG4gIGNvbnN0IHNhbmRib3hJZCA9XG4gICAgdHlwZW9mIGlkID09PSBcInN0cmluZ1wiID8gaWQgOiAoaWQ/LmlkID8/IGBzYW5kYm94XyR7dWxpZCgpfWApO1xuXG4gIGNvbnN0IGNvbnRleHRzID0gZ2V0U2FuZGJveENvbnRleHRzKGFnZW50KTtcbiAgbGV0IHNhbmRib3hDb250ZXh0ID0gY29udGV4dHMuZ2V0KHNhbmRib3hJZCk7XG4gIGlmICghc2FuZGJveENvbnRleHQpIHtcbiAgICBzYW5kYm94Q29udGV4dCA9IHsgYWdlbnQsIHNhbmRib3hJZCB9O1xuICAgIGNvbnRleHRzLnNldChzYW5kYm94SWQsIHNhbmRib3hDb250ZXh0KTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgaWQ6IHNhbmRib3hJZCxcbiAgICBnZXQgY3dkKCkge1xuICAgICAgcmV0dXJuIHNhbmRib3hDb250ZXh0IS5fY3dkID8/IFwiLlwiO1xuICAgIH0sXG4gICAgc2V0dXA6IChzZXR1cDxUU2FuZGJveEJpbmRpbmdzPikuYmluZChudWxsLCBzYW5kYm94Q29udGV4dCksXG4gICAgZXhlYzogZXhlYy5iaW5kKG51bGwsIHNhbmRib3hDb250ZXh0KSxcbiAgICByZWFkRmlsZTogcmVhZEZpbGUuYmluZChudWxsLCBzYW5kYm94Q29udGV4dCksXG4gICAgd3JpdGVGaWxlczogd3JpdGVGaWxlcy5iaW5kKG51bGwsIHNhbmRib3hDb250ZXh0KSxcbiAgICBnZXREb21haW46IGdldERvbWFpbi5iaW5kKG51bGwsIHNhbmRib3hDb250ZXh0KSxcbiAgICB1cGRhdGVOZXR3b3JrUG9saWN5OiB1cGRhdGVOZXR3b3JrUG9saWN5LmJpbmQobnVsbCwgc2FuZGJveENvbnRleHQpLFxuICAgIHN0YXJ0OiBzdGFydC5iaW5kKG51bGwsIHNhbmRib3hDb250ZXh0KSxcbiAgICBzdG9wOiBzdG9wLmJpbmQobnVsbCwgc2FuZGJveENvbnRleHQpLFxuICAgIGtpbGw6IGtpbGwuYmluZChudWxsLCBzYW5kYm94Q29udGV4dCksXG4gICAgc25hcHNob3Q6IHNuYXBzaG90LmJpbmQobnVsbCwgc2FuZGJveENvbnRleHQpLFxuICAgIGdldFN0YXR1czogZ2V0U3RhdHVzLmJpbmQobnVsbCwgc2FuZGJveENvbnRleHQpLFxuICB9O1xufVxuXG50eXBlIFNhbmRib3hNZXRob2RzPFxuICBUU2FuZGJveEJpbmRpbmdzIGV4dGVuZHMgU2FuZGJveEJpbmRpbmcgfCBTYW5kYm94QmluZGluZ1tdLFxuPiA9IE9taXQ8U2FuZGJveEhhbmRsZTxUU2FuZGJveEJpbmRpbmdzPiwgXCJpZFwiIHwgXCJjd2RcIj47XG5cbmV4cG9ydCBmdW5jdGlvbiBsYXp5U2FuZGJveEhhbmRsZTxcbiAgVFNhbmRib3hCaW5kaW5ncyBleHRlbmRzIFNhbmRib3hCaW5kaW5nIHwgU2FuZGJveEJpbmRpbmdbXSxcbj4oXG4gIGFnZW50OiBBbnlBZ2VudCxcbiAgc2Vzc2lvbklkOiBzdHJpbmdcbik6IFNhbmRib3hNZXRob2RzPFRTYW5kYm94QmluZGluZ3M+IHtcbiAgY29uc3Qgc2FuZGJveENvbnRleHQ6IFNhbmRib3hDb250ZXh0ID0ge1xuICAgIGFnZW50LFxuICAgIHNhbmRib3hJZDogbnVsbCxcbiAgICBfc2Vzc2lvbklkOiBzZXNzaW9uSWQsXG4gIH07XG5cbiAgcmV0dXJuIHtcbiAgICBzZXR1cDogKHNldHVwPFRTYW5kYm94QmluZGluZ3M+KS5iaW5kKG51bGwsIHNhbmRib3hDb250ZXh0KSxcbiAgICBleGVjOiBleGVjLmJpbmQobnVsbCwgc2FuZGJveENvbnRleHQpLFxuICAgIHJlYWRGaWxlOiByZWFkRmlsZS5iaW5kKG51bGwsIHNhbmRib3hDb250ZXh0KSxcbiAgICB3cml0ZUZpbGVzOiB3cml0ZUZpbGVzLmJpbmQobnVsbCwgc2FuZGJveENvbnRleHQpLFxuICAgIGdldERvbWFpbjogZ2V0RG9tYWluLmJpbmQobnVsbCwgc2FuZGJveENvbnRleHQpLFxuICAgIHVwZGF0ZU5ldHdvcmtQb2xpY3k6IHVwZGF0ZU5ldHdvcmtQb2xpY3kuYmluZChudWxsLCBzYW5kYm94Q29udGV4dCksXG4gICAgc3RhcnQ6IHN0YXJ0LmJpbmQobnVsbCwgc2FuZGJveENvbnRleHQpLFxuICAgIHN0b3A6IHN0b3AuYmluZChudWxsLCBzYW5kYm94Q29udGV4dCksXG4gICAga2lsbDoga2lsbC5iaW5kKG51bGwsIHNhbmRib3hDb250ZXh0KSxcbiAgICBzbmFwc2hvdDogc25hcHNob3QuYmluZChudWxsLCBzYW5kYm94Q29udGV4dCksXG4gICAgZ2V0U3RhdHVzOiBnZXRTdGF0dXMuYmluZChudWxsLCBzYW5kYm94Q29udGV4dCksXG4gIH07XG59XG4iLCAiZXhwb3J0IGNvbnN0IGlzVmVyY2VsID0gYXN5bmMgKCkgPT4ge1xuICB0cnkge1xuICAgIGNvbnN0IHsgZ2V0VmVyY2VsT2lkY1Rva2VuIH0gPSBhd2FpdCBpbXBvcnQoXCJAdmVyY2VsL29pZGNcIik7XG4gICAgcmV0dXJuIEJvb2xlYW4oYXdhaXQgZ2V0VmVyY2VsT2lkY1Rva2VuKCkpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn07XG4iLCAiaW1wb3J0ICogYXMgZXJyb3JlIGZyb20gXCJlcnJvcmVcIjtcblxuZXhwb3J0IGNsYXNzIFNlc3Npb25Ob3RGb3VuZEVycm9yIGV4dGVuZHMgZXJyb3JlLmNyZWF0ZVRhZ2dlZEVycm9yKHtcbiAgbmFtZTogXCJTZXNzaW9uTm90Rm91bmRFcnJvclwiLFxuICBtZXNzYWdlOiBcIlNlc3Npb24gJGlkIG5vdCBmb3VuZFwiLFxufSkge31cblxuZXhwb3J0IGNsYXNzIFNlc3Npb25FcnJvciBleHRlbmRzIGVycm9yZS5jcmVhdGVUYWdnZWRFcnJvcih7XG4gIG5hbWU6IFwiU2Vzc2lvbkVycm9yXCIsXG4gIG1lc3NhZ2U6IFwiU2Vzc2lvbiAkaWQgZmFpbGVkOiAkcmVhc29uXCIsXG59KSB7fVxuXG5leHBvcnQgY2xhc3MgU2FuZGJveE5vdEZvdW5kRXJyb3IgZXh0ZW5kcyBlcnJvcmUuY3JlYXRlVGFnZ2VkRXJyb3Ioe1xuICBuYW1lOiBcIlNhbmRib3hOb3RGb3VuZEVycm9yXCIsXG4gIG1lc3NhZ2U6IFwiU2FuZGJveCAkaWQgbm90IGZvdW5kXCIsXG59KSB7fVxuXG5leHBvcnQgY2xhc3MgU3RvcmFnZUVycm9yIGV4dGVuZHMgZXJyb3JlLmNyZWF0ZVRhZ2dlZEVycm9yKHtcbiAgbmFtZTogXCJTdG9yYWdlRXJyb3JcIixcbiAgbWVzc2FnZTogXCIkcmVhc29uXCIsXG59KSB7fVxuXG5leHBvcnQgY2xhc3MgU3RvcmFnZUNvbmZsaWN0RXJyb3IgZXh0ZW5kcyBlcnJvcmUuY3JlYXRlVGFnZ2VkRXJyb3Ioe1xuICBuYW1lOiBcIlN0b3JhZ2VDb25mbGljdEVycm9yXCIsXG4gIG1lc3NhZ2U6IFwiJHJlYXNvblwiLFxufSkge31cblxuZXhwb3J0IGNsYXNzIFNhbmRib3hFcnJvciBleHRlbmRzIGVycm9yZS5jcmVhdGVUYWdnZWRFcnJvcih7XG4gIG5hbWU6IFwiU2FuZGJveEVycm9yXCIsXG4gIG1lc3NhZ2U6IFwiJHJlYXNvblwiLFxufSkge31cblxuZXhwb3J0IGNsYXNzIE1lc3NhZ2VOb3RGb3VuZEVycm9yIGV4dGVuZHMgZXJyb3JlLmNyZWF0ZVRhZ2dlZEVycm9yKHtcbiAgbmFtZTogXCJNZXNzYWdlTm90Rm91bmRFcnJvclwiLFxuICBtZXNzYWdlOiBcIk1lc3NhZ2UgJGlkIG5vdCBmb3VuZFwiLFxufSkge31cbiIsICJpbXBvcnQgeyBpc1ZlcmNlbCB9IGZyb20gXCIuLi9hZ2VudC9pcy12ZXJjZWxcIjtcbmltcG9ydCB7IFNhbmRib3hFcnJvciwgU2FuZGJveE5vdEZvdW5kRXJyb3IgfSBmcm9tIFwiLi4vZXJyb3JzXCI7XG5pbXBvcnQgdHlwZSB7IFNhbmRib3ggfSBmcm9tIFwiLi4vc3RvcmFnZS90eXBlc1wiO1xuaW1wb3J0IHsgY3JlYXRlTG9nZ2VyIH0gZnJvbSBcIi4uL3V0aWxzL2xvZ2dlclwiO1xuaW1wb3J0IHR5cGUge1xuICBTYW5kYm94QmluZGluZyxcbiAgU2FuZGJveEluc3RhbmNlLFxuICBTYW5kYm94U2V0dXBGaWVsZHMsXG4gIFdpdGhDb25maWcsXG59IGZyb20gXCIuL2FkYXB0ZXJcIjtcbmltcG9ydCB0eXBlIHsgQnVpbHRJbkJpbmRpbmdzIH0gZnJvbSBcIi4vYmluZGluZ3NcIjtcbmltcG9ydCB0eXBlIHsgU2FuZGJveENvbnRleHQgfSBmcm9tIFwiLi9oYW5kbGVcIjtcblxuY29uc3QgUE9MTF9JTlRFUlZBTF9NUyA9IDUwO1xuY29uc3QgUE9MTF9USU1FT1VUX01TID0gNSAqIDYwICogMTAwMDtcblxudHlwZSBTZXR1cENvbW1vbkZpZWxkcyA9IFBhcnRpYWw8U2FuZGJveFNldHVwRmllbGRzPiAmIHtcbiAgY3dkPzogc3RyaW5nO1xuICBydW4/OiAoc2FuZGJveDogU2FuZGJveEluc3RhbmNlKSA9PiBQcm9taXNlPHZvaWQ+O1xuICBzaWduYWw/OiBBYm9ydFNpZ25hbDtcbn07XG5cbnR5cGUgVG9CaW5kaW5nVW5pb248VCBleHRlbmRzIFNhbmRib3hCaW5kaW5nIHwgU2FuZGJveEJpbmRpbmdbXT4gPVxuICBUIGV4dGVuZHMgU2FuZGJveEJpbmRpbmdbXSA/IFRbbnVtYmVyXSA6IFQ7XG5cbnR5cGUgU2V0dXBPcHRzRm9yQmluZGluZzxCIGV4dGVuZHMgU2FuZGJveEJpbmRpbmc+ID1cbiAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiAuXG4gIEIgZXh0ZW5kcyBTYW5kYm94QmluZGluZzxpbmZlciBULCBpbmZlciBDLCBhbnk+XG4gICAgPyB7IHR5cGU6IFQgfSAmIFNldHVwQ29tbW9uRmllbGRzICYgV2l0aENvbmZpZzxDPlxuICAgIDogbmV2ZXI7XG5cbnR5cGUgSXNEZWZhdWx0PFQgZXh0ZW5kcyBTYW5kYm94QmluZGluZyB8IFNhbmRib3hCaW5kaW5nW10+ID1cbiAgU2FuZGJveEJpbmRpbmcgZXh0ZW5kcyBUID8gdHJ1ZSA6IGZhbHNlO1xuXG5leHBvcnQgdHlwZSBTZXR1cE9wdHM8XG4gIFRTYW5kYm94QmluZGluZ3MgZXh0ZW5kcyBTYW5kYm94QmluZGluZyB8IFNhbmRib3hCaW5kaW5nW10sXG4+ID1cbiAgfCBTZXR1cE9wdHNGb3JCaW5kaW5nPFxuICAgICAgSXNEZWZhdWx0PFRTYW5kYm94QmluZGluZ3M+IGV4dGVuZHMgdHJ1ZVxuICAgICAgICA/IEJ1aWx0SW5CaW5kaW5nc1xuICAgICAgICA6IFRvQmluZGluZ1VuaW9uPFRTYW5kYm94QmluZGluZ3M+XG4gICAgPlxuICB8IChTZXR1cENvbW1vbkZpZWxkcyAmIHsgdHlwZT86IG5ldmVyIH0pO1xuXG5leHBvcnQgdHlwZSBTZXR1cFJlc3VsdCA9IHtcbiAgZG9uZTogUHJvbWlzZTxTYW5kYm94SW5zdGFuY2U+O1xufTtcblxuZnVuY3Rpb24gaXNTaW5nbGVCaW5kaW5nKFxuICBzYW5kYm94OiBTYW5kYm94QmluZGluZyB8IFNhbmRib3hCaW5kaW5nW11cbik6IHNhbmRib3ggaXMgU2FuZGJveEJpbmRpbmcge1xuICByZXR1cm4gIUFycmF5LmlzQXJyYXkoc2FuZGJveCk7XG59XG5cbi8qKiBBdXRvLWRldGVjdCB0aGUgZGVmYXVsdCBiaW5kaW5nOiB2ZXJjZWwgXHUyMTkyIGRvY2tlciBcdTIxOTIgbG9jYWwgY2FzY2FkZS4gKi9cbmFzeW5jIGZ1bmN0aW9uIGdldERlZmF1bHRCaW5kaW5nKCk6IFByb21pc2U8U2FuZGJveEJpbmRpbmc+IHtcbiAgaWYgKGF3YWl0IGlzVmVyY2VsKCkpIHtcbiAgICBjb25zdCB7IHZlcmNlbFNhbmRib3ggfSA9IGF3YWl0IGltcG9ydChcIi4vYmluZGluZ3MvdmVyY2VsXCIpO1xuICAgIHJldHVybiB2ZXJjZWxTYW5kYm94KCk7XG4gIH1cblxuICBpZiAoYXdhaXQgaXNEb2NrZXJBdmFpbGFibGUoKSkge1xuICAgIGNvbnN0IHsgZG9ja2VyU2FuZGJveCB9ID0gYXdhaXQgaW1wb3J0KFwiLi9iaW5kaW5ncy9kb2NrZXJcIik7XG4gICAgcmV0dXJuIGRvY2tlclNhbmRib3goKTtcbiAgfVxuXG4gIGNvbnN0IHsgbG9jYWxTYW5kYm94IH0gPSBhd2FpdCBpbXBvcnQoXCIuL2JpbmRpbmdzL2xvY2FsXCIpO1xuICByZXR1cm4gbG9jYWxTYW5kYm94KCk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGlzRG9ja2VyQXZhaWxhYmxlKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICB0cnkge1xuICAgIGNvbnN0IHsgZXhlY1N5bmMgfSA9IGF3YWl0IGltcG9ydChcIm5vZGU6Y2hpbGRfcHJvY2Vzc1wiKTtcbiAgICBleGVjU3luYyhcImRvY2tlciBzYW5kYm94IC0taGVscFwiLCB7IHN0ZGlvOiBcImlnbm9yZVwiLCB0aW1lb3V0OiA1MDAwIH0pO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZUJpbmRpbmcoXG4gIHNhbmRib3g6IFNhbmRib3hCaW5kaW5nIHwgU2FuZGJveEJpbmRpbmdbXSB8IHVuZGVmaW5lZCxcbiAgdHlwZT86IHN0cmluZ1xuKTogUHJvbWlzZTx7IGJpbmRpbmc6IFNhbmRib3hCaW5kaW5nOyBiaW5kaW5nTmFtZTogc3RyaW5nIH0+IHtcbiAgaWYgKCFzYW5kYm94KSB7XG4gICAgY29uc3QgYmluZGluZyA9IGF3YWl0IGdldERlZmF1bHRCaW5kaW5nKCk7XG4gICAgcmV0dXJuIHsgYmluZGluZywgYmluZGluZ05hbWU6IGJpbmRpbmcudHlwZSB9O1xuICB9XG4gIGlmIChpc1NpbmdsZUJpbmRpbmcoc2FuZGJveCkpIHtcbiAgICByZXR1cm4geyBiaW5kaW5nOiBzYW5kYm94LCBiaW5kaW5nTmFtZTogc2FuZGJveC50eXBlIH07XG4gIH1cbiAgaWYgKHR5cGUpIHtcbiAgICBjb25zdCBtYXRjaCA9IHNhbmRib3guZmluZCgoYikgPT4gYi50eXBlID09PSB0eXBlKTtcbiAgICBpZiAoIW1hdGNoKSB7XG4gICAgICB0aHJvdyBuZXcgU2FuZGJveEVycm9yKHtcbiAgICAgICAgcmVhc29uOiBgVW5rbm93biBiaW5kaW5nIHR5cGU6IFwiJHt0eXBlfVwiLiBBdmFpbGFibGU6ICR7c2FuZGJveC5tYXAoKGIpID0+IGIudHlwZSkuam9pbihcIiwgXCIpfWAsXG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHsgYmluZGluZzogbWF0Y2gsIGJpbmRpbmdOYW1lOiBtYXRjaC50eXBlIH07XG4gIH1cbiAgaWYgKHNhbmRib3gubGVuZ3RoID09PSAwKSB7XG4gICAgdGhyb3cgbmV3IFNhbmRib3hFcnJvcih7IHJlYXNvbjogXCJObyBzYW5kYm94IGJpbmRpbmdzIGNvbmZpZ3VyZWRcIiB9KTtcbiAgfVxuICByZXR1cm4geyBiaW5kaW5nOiBzYW5kYm94WzBdLCBiaW5kaW5nTmFtZTogc2FuZGJveFswXS50eXBlIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlc29sdmVTYW5kYm94SWQoY3R4OiBTYW5kYm94Q29udGV4dCk6IFByb21pc2U8c3RyaW5nPiB7XG4gIGlmIChjdHguc2FuZGJveElkKSB7XG4gICAgcmV0dXJuIGN0eC5zYW5kYm94SWQ7XG4gIH1cbiAgaWYgKCFjdHguX3Nlc3Npb25JZCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIFwiU2FuZGJveENvbnRleHQgaGFzIG5vIHNhbmRib3hJZCBhbmQgbm8gc2Vzc2lvbklkIHRvIHJlc29sdmUgZnJvbVwiXG4gICAgKTtcbiAgfVxuICBjb25zdCByZWNvcmQgPSBhd2FpdCBjdHguYWdlbnQuc3RvcmFnZS5zZXNzaW9uLmdldChjdHguX3Nlc3Npb25JZCk7XG4gIGN0eC5zYW5kYm94SWQgPSByZWNvcmQ/LnNhbmRib3hJZCA/PyBjdHguX3Nlc3Npb25JZDtcbiAgcmV0dXJuIGN0eC5zYW5kYm94SWQ7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZXR1cDxcbiAgVFNhbmRib3hCaW5kaW5ncyBleHRlbmRzIFNhbmRib3hCaW5kaW5nIHwgU2FuZGJveEJpbmRpbmdbXSxcbj4oXG4gIGN0eDogU2FuZGJveENvbnRleHQsXG4gIG9wdHM/OiBTZXR1cE9wdHM8VFNhbmRib3hCaW5kaW5ncz5cbik6IFByb21pc2U8U2V0dXBSZXN1bHQ+IHtcbiAgXCJ1c2Ugc3RlcFwiO1xuICBjb25zdCBzYW5kYm94SWQgPSBhd2FpdCByZXNvbHZlU2FuZGJveElkKGN0eCk7XG4gIGlmIChjdHguX3BlbmRpbmdTZXR1cCkge1xuICAgIHJldHVybiB7IGRvbmU6IGN0eC5fcGVuZGluZ1NldHVwIH07XG4gIH1cblxuICBjb25zdCBhZ2VudCA9IGN0eC5hZ2VudDtcbiAgY29uc3QgbG9nID0gY3JlYXRlTG9nZ2VyKHtcbiAgICBjb25maWc6IHsgLi4uYWdlbnQub3B0aW9ucy5sb2dnaW5nLCBuYW1lOiBhZ2VudC5uYW1lIH0sXG4gICAgc3Vic3lzdGVtOiBcInNhbmRib3g6c2V0dXBcIixcbiAgICBjb250ZXh0OiB7IHNhbmRib3hJZCB9LFxuICB9KTtcblxuICBjb25zdCBkb25lUmVzb2x2ZUJpbmRpbmcgPSBsb2cudGltZShcInJlc29sdmUgYmluZGluZ1wiLCB7XG4gICAgcmVxdWVzdGVkVHlwZTogb3B0cz8udHlwZSxcbiAgfSk7XG4gIGNvbnN0IHsgYmluZGluZywgYmluZGluZ05hbWUgfSA9IGF3YWl0IHJlc29sdmVCaW5kaW5nKFxuICAgIGFnZW50Lm9wdGlvbnMuc2FuZGJveCxcbiAgICBvcHRzPy50eXBlXG4gICk7XG4gIGRvbmVSZXNvbHZlQmluZGluZygpO1xuXG4gIGlmIChvcHRzPy5jd2QpIHtcbiAgICBjdHguX2N3ZCA9IG9wdHMuY3dkO1xuICB9XG5cbiAgY29uc3Qgc2V0dXBMb2cgPSBsb2cud2l0aENvbnRleHQoe1xuICAgIGJpbmRpbmc6IGJpbmRpbmdOYW1lLFxuICAgIHZlcnNpb246IG9wdHM/LnZlcnNpb24gPz8gYmluZGluZy5kZWZhdWx0cz8udmVyc2lvbixcbiAgfSk7XG5cbiAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0NvbmZ1c2luZ1ZvaWRUeXBlOiAuXG4gIGxldCByZXNvbHZlQmxvY2tpbmdQcm9taXNlID0gKHZhbHVlOiB2b2lkKSA9PiB2YWx1ZTtcbiAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiAuXG4gIC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FbXB0eUJsb2NrU3RhdGVtZW50czogLlxuICBsZXQgcmVqZWN0QmxvY2tpbmdQcm9taXNlID0gKF9yZWFzb24/OiBhbnkpID0+IHt9O1xuICBjb25zdCBibG9ja2luZ1Byb21pc2UgPSBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgcmVzb2x2ZUJsb2NraW5nUHJvbWlzZSA9IHJlc29sdmU7XG4gICAgcmVqZWN0QmxvY2tpbmdQcm9taXNlID0gcmVqZWN0O1xuICB9KTtcblxuICBjdHguX3BlbmRpbmdTZXR1cCA9IChhc3luYyAoKSA9PiB7XG4gICAgbGV0IHNsZWVwT2xkSW5zdGFuY2U6IFByb21pc2U8dm9pZD4gfCB1bmRlZmluZWQ7XG4gICAgY29uc3QgZG9uZVBlbmRpbmdTZXR1cCA9IHNldHVwTG9nLnRpbWUoXCJwZW5kaW5nIHNldHVwXCIpO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGRvbmVTdG9yYWdlR2V0ID0gc2V0dXBMb2cudGltZShcInN0b3JhZ2Uuc2FuZGJveC5nZXRcIik7XG4gICAgICBjb25zdCByZWNvcmQgPSBhd2FpdCBhZ2VudC5zdG9yYWdlLnNhbmRib3guZ2V0KHNhbmRib3hJZCk7XG4gICAgICBkb25lU3RvcmFnZUdldCgpO1xuXG4gICAgICBjb25zdCBiaW5kaW5nRGVmYXVsdHMgPSBiaW5kaW5nLmRlZmF1bHRzID8/IHt9O1xuICAgICAgY29uc3QgZWZmZWN0aXZlVmVyc2lvbiA9IG9wdHM/LnZlcnNpb24gPz8gYmluZGluZ0RlZmF1bHRzLnZlcnNpb24gPz8gbnVsbDtcbiAgICAgIGNvbnN0IGVmZmVjdGl2ZVJ1biA9IG9wdHM/LnJ1biA/PyBiaW5kaW5nRGVmYXVsdHMucnVuO1xuICAgICAgY29uc3QgZWZmZWN0aXZlTmV0d29ya1BvbGljeSA9XG4gICAgICAgIG9wdHM/Lm5ldHdvcmtQb2xpY3kgPz8gYmluZGluZ0RlZmF1bHRzLm5ldHdvcmtQb2xpY3kgPz8gbnVsbDtcbiAgICAgIGNvbnN0IGVmZmVjdGl2ZUN3ZCA9XG4gICAgICAgIGN0eC5fY3dkIHx8IG9wdHM/LmN3ZCB8fCBiaW5kaW5nRGVmYXVsdHMuY3dkIHx8IG51bGw7XG4gICAgICBpZiAoZWZmZWN0aXZlQ3dkKSB7XG4gICAgICAgIGN0eC5fY3dkID0gZWZmZWN0aXZlQ3dkO1xuICAgICAgfVxuICAgICAgY29uc3QgZWZmZWN0aXZlQ29uZmlnID0ge1xuICAgICAgICAuLi5iaW5kaW5nRGVmYXVsdHMuY29uZmlnLFxuICAgICAgICAvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL25vRXhwbGljaXRBbnk6IG9wdHMgaXMgYSB1bmlvbjsgY29uZmlnIGV4aXN0cyBvbiBiaW5kaW5nLXNwZWNpZmljIGJyYW5jaGVzXG4gICAgICAgIC4uLihvcHRzIGFzIGFueSk/LmNvbmZpZyxcbiAgICAgIH07XG5cbiAgICAgIGlmIChyZWNvcmQpIHtcbiAgICAgICAgY29uc3QgdmVyc2lvbk1hdGNoZXMgPVxuICAgICAgICAgICFlZmZlY3RpdmVWZXJzaW9uIHx8IHJlY29yZC5zZXR1cD8udmVyc2lvbiA9PT0gZWZmZWN0aXZlVmVyc2lvbjtcblxuICAgICAgICBpZiAodmVyc2lvbk1hdGNoZXMgJiYgcmVjb3JkLnNldHVwPy5jb21wbGV0ZWRBdCkge1xuICAgICAgICAgIHJlc29sdmVCbG9ja2luZ1Byb21pc2UoKTtcbiAgICAgICAgICBjb25zdCBkb25lQ29ubmVjdEV4aXN0aW5nID0gc2V0dXBMb2cudGltZShcbiAgICAgICAgICAgIFwiY29ubmVjdCBleGlzdGluZyBzYW5kYm94XCIsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHNldHVwU3RhdGU6IFwiY29tcGxldGVkXCIsXG4gICAgICAgICAgICB9XG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb25zdCBpbnN0YW5jZSA9IGF3YWl0IGJpbmRpbmcuY29ubmVjdCh7XG4gICAgICAgICAgICBhZ2VudCxcbiAgICAgICAgICAgIG1ldGFkYXRhOiByZWNvcmQuc2V0dXAubWV0YWRhdGEsXG4gICAgICAgICAgICBjd2Q6IHJlY29yZC5zZXR1cC5jd2QsXG4gICAgICAgICAgICBzaWduYWw6IG9wdHM/LnNpZ25hbCxcbiAgICAgICAgICAgIGxvZzogc2V0dXBMb2csXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgZG9uZUNvbm5lY3RFeGlzdGluZygpO1xuICAgICAgICAgIGN0eC5fY3dkID0gaW5zdGFuY2UuY3dkO1xuICAgICAgICAgIHJldHVybiBpbnN0YW5jZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh2ZXJzaW9uTWF0Y2hlcyAmJiAhcmVjb3JkLnNldHVwPy5jb21wbGV0ZWRBdCkge1xuICAgICAgICAgIHJlc29sdmVCbG9ja2luZ1Byb21pc2UoKTtcbiAgICAgICAgICBjb25zdCBkb25lUG9sbFVudGlsUmVhZHkgPSBzZXR1cExvZy50aW1lKFwicG9sbCB1bnRpbCByZWFkeVwiKTtcbiAgICAgICAgICBhd2FpdCBwb2xsVW50aWxSZWFkeShjdHgsIG9wdHM/LnNpZ25hbCk7XG4gICAgICAgICAgZG9uZVBvbGxVbnRpbFJlYWR5KCk7XG5cbiAgICAgICAgICBjb25zdCBkb25lU3RvcmFnZUdldFBvc3RQb2xsID0gc2V0dXBMb2cudGltZShcbiAgICAgICAgICAgIFwic3RvcmFnZS5zYW5kYm94LmdldCAocG9zdC1wb2xsKVwiXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb25zdCByZWFkeSA9IGF3YWl0IGFnZW50LnN0b3JhZ2Uuc2FuZGJveC5nZXQoc2FuZGJveElkKTtcbiAgICAgICAgICBkb25lU3RvcmFnZUdldFBvc3RQb2xsKCk7XG5cbiAgICAgICAgICBpZiAoIXJlYWR5KSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgU2FuZGJveE5vdEZvdW5kRXJyb3IoeyBpZDogc2FuZGJveElkIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCBkb25lQ29ubmVjdEV4aXN0aW5nID0gc2V0dXBMb2cudGltZShcbiAgICAgICAgICAgIFwiY29ubmVjdCBleGlzdGluZyBzYW5kYm94XCIsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHNldHVwU3RhdGU6IFwicG9zdC1wb2xsXCIsXG4gICAgICAgICAgICB9XG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb25zdCBpbnN0YW5jZSA9IGF3YWl0IGJpbmRpbmcuY29ubmVjdCh7XG4gICAgICAgICAgICBhZ2VudCxcbiAgICAgICAgICAgIG1ldGFkYXRhOiByZWFkeS5zZXR1cC5tZXRhZGF0YSxcbiAgICAgICAgICAgIGN3ZDogcmVhZHkuc2V0dXAuY3dkLFxuICAgICAgICAgICAgc2lnbmFsOiBvcHRzPy5zaWduYWwsXG4gICAgICAgICAgICBsb2c6IHNldHVwTG9nLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGRvbmVDb25uZWN0RXhpc3RpbmcoKTtcbiAgICAgICAgICBjdHguX2N3ZCA9IGluc3RhbmNlLmN3ZDtcbiAgICAgICAgICByZXR1cm4gaW5zdGFuY2U7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocmVjb3JkLnNldHVwLm1ldGFkYXRhKSB7XG4gICAgICAgICAgY29uc3Qgb2xkSW5zdGFuY2VNZXRhZGF0YSA9IHJlY29yZC5zZXR1cC5tZXRhZGF0YTtcbiAgICAgICAgICBzbGVlcE9sZEluc3RhbmNlID0gKGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGRvbmVTdG9wT2xkSW5zdGFuY2UgPSBzZXR1cExvZy50aW1lKFxuICAgICAgICAgICAgICBcInN0b3Agb2xkIHNhbmRib3ggaW5zdGFuY2VcIlxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIGNvbnN0IG9sZCA9IGF3YWl0IGJpbmRpbmcuY29ubmVjdCh7XG4gICAgICAgICAgICAgICAgYWdlbnQsXG4gICAgICAgICAgICAgICAgbWV0YWRhdGE6IG9sZEluc3RhbmNlTWV0YWRhdGEsXG4gICAgICAgICAgICAgICAgbG9nOiBzZXR1cExvZyxcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIGF3YWl0IG9sZC5zdG9wKCk7XG4gICAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgICAgZG9uZVN0b3BPbGRJbnN0YW5jZSgpO1xuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkb25lU3RvcE9sZEluc3RhbmNlKCk7XG4gICAgICAgICAgfSkoKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgY29uc3Qgc2V0dXBfOiBTYW5kYm94W1wic2V0dXBcIl0gPSB7XG4gICAgICAgIGJpbmRpbmc6IGJpbmRpbmdOYW1lLFxuICAgICAgICB2ZXJzaW9uOiBlZmZlY3RpdmVWZXJzaW9uID8/IHJlY29yZD8uc2V0dXA/LnZlcnNpb24gPz8gbnVsbCxcbiAgICAgICAgbmV0d29ya1BvbGljeTpcbiAgICAgICAgICBlZmZlY3RpdmVOZXR3b3JrUG9saWN5ID8/IHJlY29yZD8uc2V0dXA/Lm5ldHdvcmtQb2xpY3kgPz8gbnVsbCxcbiAgICAgICAgY29tcGxldGVkQXQ6IG51bGwsXG4gICAgICAgIG1ldGFkYXRhOiBudWxsLFxuICAgICAgICBjd2Q6IG51bGwsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBuZXdSZWNvcmQ6IFNhbmRib3ggPSB7XG4gICAgICAgIGlkOiBzYW5kYm94SWQsXG4gICAgICAgIHNldHVwOiBzZXR1cF8sXG4gICAgICAgIGNyZWF0ZWRBdDogcmVjb3JkPy5jcmVhdGVkQXQgPz8gbm93LFxuICAgICAgICBsYXN0QWN0aXZlQXQ6IG5vdyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGRvbmVTdG9yYWdlU2V0UGVuZGluZyA9IHNldHVwTG9nLnRpbWUoXG4gICAgICAgIFwic3RvcmFnZS5zYW5kYm94LnNldCAoc2V0dXAgcGVuZGluZylcIlxuICAgICAgKTtcbiAgICAgIGF3YWl0IGFnZW50LnN0b3JhZ2Uuc2FuZGJveC5zZXQoc2FuZGJveElkLCBuZXdSZWNvcmQpO1xuICAgICAgZG9uZVN0b3JhZ2VTZXRQZW5kaW5nKCk7XG5cbiAgICAgIHJlc29sdmVCbG9ja2luZ1Byb21pc2UoKTtcblxuICAgICAgY29uc3QgZG9uZUJpbmRpbmdDcmVhdGUgPSBzZXR1cExvZy50aW1lKFwiYmluZGluZy5jcmVhdGVcIik7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBiaW5kaW5nLmNyZWF0ZSh7XG4gICAgICAgIGN3ZDogY3R4Ll9jd2QgPz8gXCIuXCIsXG4gICAgICAgIGFnZW50LFxuICAgICAgICBzZXR1cDoge1xuICAgICAgICAgIC4uLnNldHVwXyxcbiAgICAgICAgICBydW46IGVmZmVjdGl2ZVJ1bixcbiAgICAgICAgICBjb25maWc6IGVmZmVjdGl2ZUNvbmZpZyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVjb3JkOiBuZXdSZWNvcmQsXG4gICAgICAgIHNpZ25hbDogb3B0cz8uc2lnbmFsLFxuICAgICAgICBsb2c6IHNldHVwTG9nLFxuICAgICAgfSk7XG4gICAgICBkb25lQmluZGluZ0NyZWF0ZSgpO1xuXG4gICAgICBzZXR1cF8uY29tcGxldGVkQXQgPSBEYXRlLm5vdygpO1xuICAgICAgc2V0dXBfLm1ldGFkYXRhID0gcmVzdWx0Lm1ldGFkYXRhO1xuICAgICAgc2V0dXBfLmN3ZCA9IHJlc3VsdC5pbnN0YW5jZS5jd2Q7XG5cbiAgICAgIGNvbnN0IGRvbmVTdG9yYWdlVXBkYXRlQ29tcGxldGUgPSBzZXR1cExvZy50aW1lKFxuICAgICAgICBcInN0b3JhZ2Uuc2FuZGJveC51cGRhdGUgKHNldHVwIGNvbXBsZXRlKVwiXG4gICAgICApO1xuICAgICAgYXdhaXQgYWdlbnQuc3RvcmFnZS5zYW5kYm94LnVwZGF0ZShzYW5kYm94SWQsIHtcbiAgICAgICAgc2V0dXA6IHNldHVwXyxcbiAgICAgICAgbGFzdEFjdGl2ZUF0OiBEYXRlLm5vdygpLFxuICAgICAgfSk7XG4gICAgICBkb25lU3RvcmFnZVVwZGF0ZUNvbXBsZXRlKCk7XG5cbiAgICAgIGN0eC5fY3dkID0gcmVzdWx0Lmluc3RhbmNlLmN3ZDtcbiAgICAgIHJldHVybiByZXN1bHQuaW5zdGFuY2U7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBjdHguX3BlbmRpbmdTZXR1cCA9IHVuZGVmaW5lZDtcbiAgICAgIHJlamVjdEJsb2NraW5nUHJvbWlzZShlcnIpO1xuICAgICAgdGhyb3cgZXJyO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBjb25zdCBkb25lRmluYWxpemUgPSBzZXR1cExvZy50aW1lKFwiZmluYWxpemUgc2V0dXBcIik7XG4gICAgICBhd2FpdCBzbGVlcE9sZEluc3RhbmNlO1xuICAgICAgZG9uZUZpbmFsaXplKCk7XG4gICAgICBkb25lUGVuZGluZ1NldHVwKCk7XG4gICAgfVxuICB9KSgpO1xuXG4gIGNvbnN0IGRvbmVXYWl0Rm9yVW5ibG9jayA9IHNldHVwTG9nLnRpbWUoXCJ3YWl0IGZvciBzZXR1cCB1bmJsb2NrXCIpO1xuICBhd2FpdCBibG9ja2luZ1Byb21pc2U7XG4gIGRvbmVXYWl0Rm9yVW5ibG9jaygpO1xuICByZXR1cm4geyBkb25lOiBjdHguX3BlbmRpbmdTZXR1cCB9O1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZShcbiAgY3R4OiBTYW5kYm94Q29udGV4dCxcbiAgc2lnbmFsPzogQWJvcnRTaWduYWxcbik6IFByb21pc2U8U2FuZGJveEluc3RhbmNlPiB7XG4gIGNvbnN0IHNhbmRib3hJZCA9IGF3YWl0IHJlc29sdmVTYW5kYm94SWQoY3R4KTtcbiAgY29uc3QgYWdlbnQgPSBjdHguYWdlbnQ7XG4gIGNvbnN0IGxvZyA9IGNyZWF0ZUxvZ2dlcih7XG4gICAgY29uZmlnOiB7IC4uLmFnZW50Lm9wdGlvbnMubG9nZ2luZywgbmFtZTogYWdlbnQubmFtZSB9LFxuICAgIHN1YnN5c3RlbTogXCJzYW5kYm94OnJlc29sdmVcIixcbiAgICBjb250ZXh0OiB7IHNhbmRib3hJZCB9LFxuICB9KTtcblxuICBpZiAoY3R4Ll9wZW5kaW5nU2V0dXApIHtcbiAgICByZXR1cm4gYXdhaXQgY3R4Ll9wZW5kaW5nU2V0dXA7XG4gIH1cblxuICBsZXQgcmVjb3JkID0gYXdhaXQgYWdlbnQuc3RvcmFnZS5zYW5kYm94LmdldChzYW5kYm94SWQpO1xuXG4gIGlmICghcmVjb3JkKSB7XG4gICAgY29uc3QgeyBkb25lIH0gPSBhd2FpdCBzZXR1cChjdHgsIHsgc2lnbmFsIH0pO1xuICAgIHJldHVybiBhd2FpdCBkb25lO1xuICB9XG5cbiAgaWYgKCFyZWNvcmQuc2V0dXA/LmNvbXBsZXRlZEF0KSB7XG4gICAgYXdhaXQgcG9sbFVudGlsUmVhZHkoY3R4LCBzaWduYWwpO1xuICAgIHJlY29yZCA9IGF3YWl0IGFnZW50LnN0b3JhZ2Uuc2FuZGJveC5nZXQoc2FuZGJveElkKTtcbiAgfVxuXG4gIGlmICghcmVjb3JkKSB7XG4gICAgdGhyb3cgbmV3IFNhbmRib3hOb3RGb3VuZEVycm9yKHsgaWQ6IHNhbmRib3hJZCB9KTtcbiAgfVxuXG4gIGNvbnN0IHsgYmluZGluZyB9ID0gYXdhaXQgcmVzb2x2ZUJpbmRpbmcoXG4gICAgY3R4LmFnZW50Lm9wdGlvbnMuc2FuZGJveCxcbiAgICByZWNvcmQuc2V0dXAuYmluZGluZ1xuICApO1xuXG4gIGFnZW50LnN0b3JhZ2Uuc2FuZGJveFxuICAgIC51cGRhdGUoc2FuZGJveElkLCB7IGxhc3RBY3RpdmVBdDogRGF0ZS5ub3coKSB9KVxuICAgIC5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgIGxvZy5lcnJvcihcIkZhaWxlZCB0byB1cGRhdGUgc2FuZGJveCBsYXN0QWN0aXZlQXRcIiwgeyBlcnJvciB9KTtcbiAgICB9KTtcblxuICBjb25zdCBpbnN0YW5jZSA9IGF3YWl0IGJpbmRpbmcuY29ubmVjdCh7XG4gICAgYWdlbnQsXG4gICAgbWV0YWRhdGE6IHJlY29yZC5zZXR1cC5tZXRhZGF0YSxcbiAgICBjd2Q6IHJlY29yZC5zZXR1cC5jd2QsXG4gICAgc2lnbmFsLFxuICAgIGxvZyxcbiAgfSk7XG4gIGN0eC5fY3dkID0gaW5zdGFuY2UuY3dkO1xuICByZXR1cm4gaW5zdGFuY2U7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHBvbGxVbnRpbFJlYWR5KFxuICBjdHg6IFNhbmRib3hDb250ZXh0LFxuICBzaWduYWw/OiBBYm9ydFNpZ25hbFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IGlkID0gY3R4LnNhbmRib3hJZCE7XG4gIGNvbnN0IGRlYWRsaW5lID0gRGF0ZS5ub3coKSArIFBPTExfVElNRU9VVF9NUztcblxuICB3aGlsZSAoRGF0ZS5ub3coKSA8IGRlYWRsaW5lKSB7XG4gICAgc2lnbmFsPy50aHJvd0lmQWJvcnRlZCgpO1xuXG4gICAgY29uc3QgcmVjb3JkID0gYXdhaXQgY3R4LmFnZW50LnN0b3JhZ2Uuc2FuZGJveC5nZXQoaWQpO1xuICAgIGlmIChyZWNvcmQ/LnNldHVwPy5jb21wbGV0ZWRBdCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGF3YWl0IG5ldyBQcm9taXNlKChyKSA9PiBzZXRUaW1lb3V0KHIsIFBPTExfSU5URVJWQUxfTVMpKTtcbiAgfVxuXG4gIHRocm93IG5ldyBTYW5kYm94RXJyb3Ioe1xuICAgIHJlYXNvbjogYFRpbWVkIG91dCB3YWl0aW5nIGZvciBzYW5kYm94IFwiJHtpZH1cIiBzZXR1cCB0byBjb21wbGV0ZWAsXG4gIH0pO1xufVxuIiwgImltcG9ydCB0eXBlIHsgU2FuZGJveEluc3RhbmNlIH0gZnJvbSBcIi4vYWRhcHRlclwiO1xuaW1wb3J0IHR5cGUgeyBTYW5kYm94Q29udGV4dCB9IGZyb20gXCIuL2hhbmRsZVwiO1xuaW1wb3J0IHsgcmVzb2x2ZSB9IGZyb20gXCIuL3NldHVwXCI7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBleGVjKFxuICBzYW5kYm94Q29udGV4dDogU2FuZGJveENvbnRleHQsXG4gIC4uLm9wdHM6IFBhcmFtZXRlcnM8U2FuZGJveEluc3RhbmNlW1wiZXhlY1wiXT5cbikge1xuICAvLyBub3RlOiAuZXhlYyBjYW4ndCBiZSBhIHN0ZXAgYmVjYXVzZSBpdCByZXR1cm5zIGxvZ3MgYW5kIGEgcmVzdWx0IHByb21pc2Ugd2hpY2ggY2FuJ3QgYmUgc2VyaWFsaXplZFxuICBjb25zdCBzYnggPSBhd2FpdCByZXNvbHZlKHNhbmRib3hDb250ZXh0KTtcbiAgcmV0dXJuIGF3YWl0IHNieC5leGVjKC4uLm9wdHMpO1xufVxuIiwgImltcG9ydCB0eXBlIHsgU2FuZGJveEluc3RhbmNlIH0gZnJvbSBcIi4vYWRhcHRlclwiO1xuaW1wb3J0IHR5cGUgeyBTYW5kYm94Q29udGV4dCB9IGZyb20gXCIuL2hhbmRsZVwiO1xuaW1wb3J0IHsgcmVzb2x2ZSB9IGZyb20gXCIuL3NldHVwXCI7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXREb21haW4oXG4gIHNhbmRib3hDb250ZXh0OiBTYW5kYm94Q29udGV4dCxcbiAgLi4ub3B0czogUGFyYW1ldGVyczxTYW5kYm94SW5zdGFuY2VbXCJnZXREb21haW5cIl0+XG4pIHtcbiAgXCJ1c2Ugc3RlcFwiO1xuICBjb25zdCBzYnggPSBhd2FpdCByZXNvbHZlKHNhbmRib3hDb250ZXh0KTtcbiAgcmV0dXJuIGF3YWl0IHNieC5nZXREb21haW4oLi4ub3B0cyk7XG59XG4iLCAiaW1wb3J0IHR5cGUgeyBTYW5kYm94SW5zdGFuY2UgfSBmcm9tIFwiLi9hZGFwdGVyXCI7XG5pbXBvcnQgdHlwZSB7IFNhbmRib3hDb250ZXh0IH0gZnJvbSBcIi4vaGFuZGxlXCI7XG5pbXBvcnQgeyByZXNvbHZlIH0gZnJvbSBcIi4vc2V0dXBcIjtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldFN0YXR1cyhcbiAgc2FuZGJveENvbnRleHQ6IFNhbmRib3hDb250ZXh0LFxuICAuLi5vcHRzOiBQYXJhbWV0ZXJzPFNhbmRib3hJbnN0YW5jZVtcImdldFN0YXR1c1wiXT5cbikge1xuICBcInVzZSBzdGVwXCI7XG4gIGNvbnN0IHNieCA9IGF3YWl0IHJlc29sdmUoc2FuZGJveENvbnRleHQpO1xuICByZXR1cm4gYXdhaXQgc2J4LmdldFN0YXR1cyguLi5vcHRzKTtcbn1cbiIsICJpbXBvcnQgdHlwZSB7IFNhbmRib3hJbnN0YW5jZSB9IGZyb20gXCIuL2FkYXB0ZXJcIjtcbmltcG9ydCB0eXBlIHsgU2FuZGJveENvbnRleHQgfSBmcm9tIFwiLi9oYW5kbGVcIjtcbmltcG9ydCB7IHJlc29sdmUgfSBmcm9tIFwiLi9zZXR1cFwiO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24ga2lsbChcbiAgc2FuZGJveENvbnRleHQ6IFNhbmRib3hDb250ZXh0LFxuICAuLi5vcHRzOiBQYXJhbWV0ZXJzPFNhbmRib3hJbnN0YW5jZVtcImtpbGxcIl0+XG4pIHtcbiAgXCJ1c2Ugc3RlcFwiO1xuICBjb25zdCBzYnggPSBhd2FpdCByZXNvbHZlKHNhbmRib3hDb250ZXh0KTtcbiAgcmV0dXJuIGF3YWl0IHNieC5raWxsKC4uLm9wdHMpO1xufVxuIiwgImltcG9ydCB0eXBlIHsgU2FuZGJveEluc3RhbmNlIH0gZnJvbSBcIi4vYWRhcHRlclwiO1xuaW1wb3J0IHR5cGUgeyBTYW5kYm94Q29udGV4dCB9IGZyb20gXCIuL2hhbmRsZVwiO1xuaW1wb3J0IHsgcmVzb2x2ZSB9IGZyb20gXCIuL3NldHVwXCI7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWFkRmlsZShcbiAgc2FuZGJveENvbnRleHQ6IFNhbmRib3hDb250ZXh0LFxuICAuLi5vcHRzOiBQYXJhbWV0ZXJzPFNhbmRib3hJbnN0YW5jZVtcInJlYWRGaWxlXCJdPlxuKSB7XG4gIFwidXNlIHN0ZXBcIjtcbiAgY29uc3Qgc2J4ID0gYXdhaXQgcmVzb2x2ZShzYW5kYm94Q29udGV4dCk7XG4gIHJldHVybiBhd2FpdCBzYngucmVhZEZpbGUoLi4ub3B0cyk7XG59XG4iLCAiaW1wb3J0IHR5cGUgeyBTYW5kYm94SW5zdGFuY2UgfSBmcm9tIFwiLi9hZGFwdGVyXCI7XG5pbXBvcnQgdHlwZSB7IFNhbmRib3hDb250ZXh0IH0gZnJvbSBcIi4vaGFuZGxlXCI7XG5pbXBvcnQgeyByZXNvbHZlIH0gZnJvbSBcIi4vc2V0dXBcIjtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNuYXBzaG90KFxuICBzYW5kYm94Q29udGV4dDogU2FuZGJveENvbnRleHQsXG4gIC4uLm9wdHM6IFBhcmFtZXRlcnM8U2FuZGJveEluc3RhbmNlW1wic25hcHNob3RcIl0+XG4pIHtcbiAgXCJ1c2Ugc3RlcFwiO1xuICBjb25zdCBzYnggPSBhd2FpdCByZXNvbHZlKHNhbmRib3hDb250ZXh0KTtcbiAgcmV0dXJuIGF3YWl0IHNieC5zbmFwc2hvdCguLi5vcHRzKTtcbn1cbiIsICJpbXBvcnQgdHlwZSB7IFNhbmRib3hJbnN0YW5jZSB9IGZyb20gXCIuL2FkYXB0ZXJcIjtcbmltcG9ydCB0eXBlIHsgU2FuZGJveENvbnRleHQgfSBmcm9tIFwiLi9oYW5kbGVcIjtcbmltcG9ydCB7IHJlc29sdmUgfSBmcm9tIFwiLi9zZXR1cFwiO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc3RhcnQoXG4gIHNhbmRib3hDb250ZXh0OiBTYW5kYm94Q29udGV4dCxcbiAgLi4ub3B0czogUGFyYW1ldGVyczxTYW5kYm94SW5zdGFuY2VbXCJzdGFydFwiXT5cbikge1xuICBcInVzZSBzdGVwXCI7XG4gIGNvbnN0IHNieCA9IGF3YWl0IHJlc29sdmUoc2FuZGJveENvbnRleHQpO1xuICByZXR1cm4gYXdhaXQgc2J4LnN0YXJ0KC4uLm9wdHMpO1xufVxuIiwgImltcG9ydCB0eXBlIHsgU2FuZGJveEluc3RhbmNlIH0gZnJvbSBcIi4vYWRhcHRlclwiO1xuaW1wb3J0IHR5cGUgeyBTYW5kYm94Q29udGV4dCB9IGZyb20gXCIuL2hhbmRsZVwiO1xuaW1wb3J0IHsgcmVzb2x2ZSB9IGZyb20gXCIuL3NldHVwXCI7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzdG9wKFxuICBzYW5kYm94Q29udGV4dDogU2FuZGJveENvbnRleHQsXG4gIC4uLm9wdHM6IFBhcmFtZXRlcnM8U2FuZGJveEluc3RhbmNlW1wic3RvcFwiXT5cbikge1xuICBcInVzZSBzdGVwXCI7XG4gIGNvbnN0IHNieCA9IGF3YWl0IHJlc29sdmUoc2FuZGJveENvbnRleHQpO1xuICByZXR1cm4gYXdhaXQgc2J4LnN0b3AoLi4ub3B0cyk7XG59XG4iLCAiaW1wb3J0IHR5cGUgeyBTYW5kYm94SW5zdGFuY2UgfSBmcm9tIFwiLi9hZGFwdGVyXCI7XG5pbXBvcnQgdHlwZSB7IFNhbmRib3hDb250ZXh0IH0gZnJvbSBcIi4vaGFuZGxlXCI7XG5pbXBvcnQgeyByZXNvbHZlIH0gZnJvbSBcIi4vc2V0dXBcIjtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHVwZGF0ZU5ldHdvcmtQb2xpY3koXG4gIHNhbmRib3hDb250ZXh0OiBTYW5kYm94Q29udGV4dCxcbiAgLi4ub3B0czogUGFyYW1ldGVyczxTYW5kYm94SW5zdGFuY2VbXCJ1cGRhdGVOZXR3b3JrUG9saWN5XCJdPlxuKSB7XG4gIFwidXNlIHN0ZXBcIjtcbiAgY29uc3Qgc2J4ID0gYXdhaXQgcmVzb2x2ZShzYW5kYm94Q29udGV4dCk7XG4gIHJldHVybiBhd2FpdCBzYngudXBkYXRlTmV0d29ya1BvbGljeSguLi5vcHRzKTtcbn1cbiIsICJpbXBvcnQgdHlwZSB7IFNhbmRib3hJbnN0YW5jZSB9IGZyb20gXCIuL2FkYXB0ZXJcIjtcbmltcG9ydCB0eXBlIHsgU2FuZGJveENvbnRleHQgfSBmcm9tIFwiLi9oYW5kbGVcIjtcbmltcG9ydCB7IHJlc29sdmUgfSBmcm9tIFwiLi9zZXR1cFwiO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gd3JpdGVGaWxlcyhcbiAgc2FuZGJveENvbnRleHQ6IFNhbmRib3hDb250ZXh0LFxuICAuLi5vcHRzOiBQYXJhbWV0ZXJzPFNhbmRib3hJbnN0YW5jZVtcIndyaXRlRmlsZXNcIl0+XG4pIHtcbiAgXCJ1c2Ugc3RlcFwiO1xuICBjb25zdCBzYnggPSBhd2FpdCByZXNvbHZlKHNhbmRib3hDb250ZXh0KTtcbiAgcmV0dXJuIGF3YWl0IHNieC53cml0ZUZpbGVzKC4uLm9wdHMpO1xufVxuIiwgImltcG9ydCB0eXBlIHsgVG9vbFNldCB9IGZyb20gXCJhaVwiO1xuaW1wb3J0IHsgdWxpZCB9IGZyb20gXCJ1bGlkXCI7XG5pbXBvcnQgdHlwZSB7IEFueUFnZW50IH0gZnJvbSBcIi4uL2FnZW50L2NsaWVudFwiO1xuaW1wb3J0IHsgZ2V0U2Vzc2lvbkNvbnRleHRzIH0gZnJvbSBcIi4uL2FnZW50L2NsaWVudFwiO1xuaW1wb3J0IHR5cGUgeyBTYW5kYm94QmluZGluZyB9IGZyb20gXCIuLi9zYW5kYm94L2FkYXB0ZXJcIjtcbmltcG9ydCB7IGxhenlTYW5kYm94SGFuZGxlIH0gZnJvbSBcIi4uL3NhbmRib3gvaGFuZGxlXCI7XG5pbXBvcnQgeyBoaXN0b3J5IH0gZnJvbSBcIi4vaGlzdG9yeVwiO1xuaW1wb3J0IHsgaW50ZXJydXB0IH0gZnJvbSBcIi4vaW50ZXJydXB0XCI7XG5pbXBvcnQgeyBzZW5kIH0gZnJvbSBcIi4vc2VuZFwiO1xuaW1wb3J0IHsgc3RyZWFtIH0gZnJvbSBcIi4vc3RyZWFtXCI7XG5pbXBvcnQgeyB1cGRhdGUgfSBmcm9tIFwiLi91cGRhdGVcIjtcbmltcG9ydCB7IHVzYWdlIH0gZnJvbSBcIi4vdXNhZ2VcIjtcblxudHlwZSBTZXNzaW9uT3B0aW9ucyA9IHtcbiAgaWQ/OiBzdHJpbmc7XG59O1xuXG5leHBvcnQgdHlwZSBTZXNzaW9uQ29udGV4dCA9IHtcbiAgYWdlbnQ6IEFueUFnZW50O1xuICBzZXNzaW9uSWQ6IHN0cmluZztcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXNzaW9uSGFuZGxlPFxuICBUb29scyBleHRlbmRzIFRvb2xTZXQsXG4gIFRDb250ZXh0LFxuICBUU2FuZGJveEJpbmRpbmdzIGV4dGVuZHMgU2FuZGJveEJpbmRpbmcgfCBTYW5kYm94QmluZGluZ1tdID0gU2FuZGJveEJpbmRpbmcsXG4gIFRNZXNzYWdlTWV0YWRhdGEgPSB1bmtub3duLFxuICBUU3RhdGUgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuPihhZ2VudDogQW55QWdlbnQsIGlkPzogc3RyaW5nIHwgU2Vzc2lvbk9wdGlvbnMpIHtcbiAgY29uc3Qgc2Vzc2lvbklkID1cbiAgICB0eXBlb2YgaWQgPT09IFwic3RyaW5nXCIgPyBpZCA6IChpZD8uaWQgPz8gYHNlc3Npb25fJHt1bGlkKCl9YCk7XG5cbiAgY29uc3QgY29udGV4dHMgPSBnZXRTZXNzaW9uQ29udGV4dHMoYWdlbnQpO1xuICBsZXQgc2Vzc2lvbkNvbnRleHQgPSBjb250ZXh0cy5nZXQoc2Vzc2lvbklkKTtcbiAgaWYgKCFzZXNzaW9uQ29udGV4dCkge1xuICAgIHNlc3Npb25Db250ZXh0ID0geyBhZ2VudCwgc2Vzc2lvbklkIH07XG4gICAgY29udGV4dHMuc2V0KHNlc3Npb25JZCwgc2Vzc2lvbkNvbnRleHQpO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBpZDogc2Vzc2lvbklkLFxuICAgIHNlbmQ6IChzZW5kPFRvb2xzLCBUQ29udGV4dCwgVE1lc3NhZ2VNZXRhZGF0YSwgVFN0YXRlPikuYmluZChcbiAgICAgIG51bGwsXG4gICAgICBzZXNzaW9uQ29udGV4dFxuICAgICksXG4gICAgc3RyZWFtOiBzdHJlYW0uYmluZChudWxsLCBzZXNzaW9uQ29udGV4dCksXG4gICAgaGlzdG9yeTogKGhpc3Rvcnk8VG9vbHM+KS5iaW5kKG51bGwsIHNlc3Npb25Db250ZXh0KSxcbiAgICBpbnRlcnJ1cHQ6IGludGVycnVwdC5iaW5kKG51bGwsIHNlc3Npb25Db250ZXh0KSxcbiAgICB1c2FnZTogdXNhZ2UuYmluZChudWxsLCBzZXNzaW9uQ29udGV4dCksXG4gICAgdXBkYXRlOiAodXBkYXRlPFRTdGF0ZT4pLmJpbmQobnVsbCwgc2Vzc2lvbkNvbnRleHQpLFxuICAgIHNhbmRib3g6IGxhenlTYW5kYm94SGFuZGxlPFRTYW5kYm94QmluZGluZ3M+KGFnZW50LCBzZXNzaW9uSWQpLFxuICB9O1xufVxuIiwgImltcG9ydCB0eXBlIHtcbiAgSW5mZXJVSVRvb2xzLFxuICBSZWFzb25pbmdVSVBhcnQsXG4gIFRleHRVSVBhcnQsXG4gIFRvb2xTZXQsXG4gIFVJTWVzc2FnZSxcbn0gZnJvbSBcImFpXCI7XG5pbXBvcnQgdHlwZSB7IEFnZW50RGF0YVR5cGVzIH0gZnJvbSBcIi4uL2FnZW50L3JlZ2lzdHJ5XCI7XG5pbXBvcnQgdHlwZSB7IE1lc3NhZ2UsIFBhcnQgfSBmcm9tIFwiLi4vc3RvcmFnZVwiO1xuXG4vKiogU3ViLXRvb2wgcGFydHMgKGZyb20gSmF2YVNjcmlwdCBtZXRhLXRvb2wpIHVzZSB0aGlzIHRvb2xDYWxsSWQgcHJlZml4LiAqL1xuZnVuY3Rpb24gaXNTdWJUb29sUGFydChwYXJ0OiBQYXJ0KTogYm9vbGVhbiB7XG4gIGNvbnN0IHAgPSBwYXJ0LnBhcnQgYXMgeyB0b29sQ2FsbElkPzogc3RyaW5nIH07XG4gIHJldHVybiB0eXBlb2YgcD8udG9vbENhbGxJZCA9PT0gXCJzdHJpbmdcIiAmJiBwLnRvb2xDYWxsSWQuc3RhcnRzV2l0aChcImpzX3RjX1wiKTtcbn1cblxuZnVuY3Rpb24gaXNTdHJlYW1pbmdDb250ZW50KFxuICBwYXJ0OiB1bmtub3duXG4pOiBwYXJ0IGlzIFRleHRVSVBhcnQgfCBSZWFzb25pbmdVSVBhcnQge1xuICByZXR1cm4gKFxuICAgIHR5cGVvZiBwYXJ0ID09PSBcIm9iamVjdFwiICYmXG4gICAgcGFydCAhPT0gbnVsbCAmJlxuICAgIFwidHlwZVwiIGluIHBhcnQgJiZcbiAgICAocGFydC50eXBlID09PSBcInRleHRcIiB8fCBwYXJ0LnR5cGUgPT09IFwicmVhc29uaW5nXCIpXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhcHBseUludGVycnVwdEN1dG9mZih7XG4gIHBhcnRzLFxuICBsYXN0UGFydCxcbn06IHtcbiAgcGFydHM6IFBhcnRbXTtcbiAgbGFzdFBhcnQ6IHsgaW5kZXg6IG51bWJlcjsgcGFydDogdW5rbm93biB9O1xufSk6IFBhcnRbXSB7XG4gIHJldHVybiBwYXJ0c1xuICAgIC5maWx0ZXIoKHApID0+IHAuaW5kZXggPD0gbGFzdFBhcnQuaW5kZXgpXG4gICAgLm1hcCgocCkgPT4ge1xuICAgICAgaWYgKHAuaW5kZXggIT09IGxhc3RQYXJ0LmluZGV4KSB7XG4gICAgICAgIHJldHVybiBwO1xuICAgICAgfVxuICAgICAgLyoqXG4gICAgICAgKiBPbmx5IHJlcGxhY2UgY29udGVudCBmb3Igc3RyZWFtaW5nIHBhcnRzICh0ZXh0LCByZWFzb25pbmcpIHdoZXJlIHRoZVxuICAgICAgICogY2xpZW50J3MgdHJ1bmNhdGVkIHZlcnNpb24gaXMgbW9yZSBhY2N1cmF0ZSB0aGFuIHRoZSBzZXJ2ZXIncyBmdWxsXG4gICAgICAgKiB2ZXJzaW9uLiBGb3Igc3RhdGVmdWwgcGFydHMgKHRvb2xzKSwgdGhlIHNlcnZlcidzIHZlcnNpb24gaXNcbiAgICAgICAqIGF1dGhvcml0YXRpdmUgXHUyMDE0IGl0IG1heSBoYXZlIGV2b2x2ZWQgKGUuZy4gYXBwcm92YWwtcmVxdWVzdGVkIFx1MjE5MlxuICAgICAgICogb3V0cHV0LWRlbmllZCkgYWZ0ZXIgdGhlIGNsaWVudCBzbmFwc2hvdCB3YXMgdGFrZW4uXG4gICAgICAgKi9cbiAgICAgIGlmIChpc1N0cmVhbWluZ0NvbnRlbnQobGFzdFBhcnQucGFydCkpIHtcbiAgICAgICAgcmV0dXJuIHsgLi4ucCwgcGFydDogbGFzdFBhcnQucGFydCB9IGFzIFBhcnQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gcDtcbiAgICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFzc2VtYmxlVUlNZXNzYWdlczxUb29scyBleHRlbmRzIFRvb2xTZXQ+KG9wdHM6IHtcbiAgbWVzc2FnZXM6IE1lc3NhZ2VbXTtcbiAgcGFydHM6IFBhcnRbXTtcbiAgdW50aWw/OiBudW1iZXI7XG4gIGluY2x1ZGVRdWV1ZWQ/OiBib29sZWFuO1xuICAvKiogV2hlbiB0cnVlLCBmaWx0ZXJzIG91dCBzdWItdG9vbCBwYXJ0cyBzbyB0aGUgTExNIGRvZXNuJ3Qgc2VlIHRoZW0uICovXG4gIGV4Y2x1ZGVTdWJUb29sUGFydHM/OiBib29sZWFuO1xufSkge1xuICB0eXBlIFR5cGVkVUlNZXNzYWdlID0gVUlNZXNzYWdlPHVua25vd24sIEFnZW50RGF0YVR5cGVzLCBJbmZlclVJVG9vbHM8VG9vbHM+PjtcblxuICBsZXQgZmlsdGVyZWQgPSBvcHRzLm1lc3NhZ2VzO1xuXG4gIGlmIChvcHRzLnVudGlsICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25zdCB1bnRpbCA9IG9wdHMudW50aWw7XG4gICAgZmlsdGVyZWQgPSBmaWx0ZXJlZC5maWx0ZXIoKG0pID0+IG0uY3JlYXRlZEF0IDw9IHVudGlsKTtcbiAgfVxuXG4gIGlmICghb3B0cy5pbmNsdWRlUXVldWVkKSB7XG4gICAgZmlsdGVyZWQgPSBmaWx0ZXJlZC5maWx0ZXIoKG0pID0+IG0uc3RhcnRlZEF0ICE9PSBudWxsKTtcbiAgfVxuXG4gIC8vIFNvcnQgYnkgY3JlYXRlZEF0IHNvIG1lc3NhZ2VzIGFyZSBpbiBjaHJvbm9sb2dpY2FsIG9yZGVyIHJlZ2FyZGxlc3Mgb2ZcbiAgLy8gaG93IHRoZSBzdG9yYWdlIGxheWVyIHJldHVybnMgdGhlbSAoZS5nLiBsb2NhbCBGUyByZWFkcyBpbiByZWFkZGlyIG9yZGVyKS5cbiAgZmlsdGVyZWQgPSBbLi4uZmlsdGVyZWRdLnNvcnQoKGEsIGIpID0+IGEuY3JlYXRlZEF0IC0gYi5jcmVhdGVkQXQpO1xuXG4gIGNvbnN0IHBhcnRzID0gb3B0cy5leGNsdWRlU3ViVG9vbFBhcnRzXG4gICAgPyBvcHRzLnBhcnRzLmZpbHRlcigocCkgPT4gIWlzU3ViVG9vbFBhcnQocCkpXG4gICAgOiBvcHRzLnBhcnRzO1xuXG4gIGNvbnN0IHBhcnRzQnlNZXNzYWdlID0gbmV3IE1hcDxzdHJpbmcsIFBhcnRbXT4oKTtcbiAgZm9yIChjb25zdCBwYXJ0IG9mIHBhcnRzKSB7XG4gICAgY29uc3QgbWVzc2FnZUlkID0gU3RyaW5nKHBhcnQubWVzc2FnZUlkKTtcbiAgICBjb25zdCBleGlzdGluZyA9IHBhcnRzQnlNZXNzYWdlLmdldChtZXNzYWdlSWQpID8/IFtdO1xuICAgIGV4aXN0aW5nLnB1c2gocGFydCk7XG4gICAgcGFydHNCeU1lc3NhZ2Uuc2V0KG1lc3NhZ2VJZCwgZXhpc3RpbmcpO1xuICB9XG5cbiAgcmV0dXJuIGZpbHRlcmVkXG4gICAgLm1hcCgobSkgPT4ge1xuICAgICAgY29uc3QgbWVzc2FnZUlkID0gU3RyaW5nKG0uaWQpO1xuICAgICAgbGV0IG1lc3NhZ2VQYXJ0cyA9IHBhcnRzQnlNZXNzYWdlLmdldChtZXNzYWdlSWQpID8/IFtdO1xuICAgICAgbWVzc2FnZVBhcnRzLnNvcnQoKGEsIGIpID0+IGEuaW5kZXggLSBiLmluZGV4KTtcblxuICAgICAgaWYgKG0uaW50ZXJydXB0ZWRMYXN0UGFydCAhPSBudWxsKSB7XG4gICAgICAgIG1lc3NhZ2VQYXJ0cyA9IGFwcGx5SW50ZXJydXB0Q3V0b2ZmKHtcbiAgICAgICAgICBwYXJ0czogbWVzc2FnZVBhcnRzLFxuICAgICAgICAgIGxhc3RQYXJ0OiBtLmludGVycnVwdGVkTGFzdFBhcnQsXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBpZDogbWVzc2FnZUlkLFxuICAgICAgICByb2xlOiBtLnJvbGUsXG4gICAgICAgIHBhcnRzOiBtZXNzYWdlUGFydHMubWFwKChwKSA9PiBwLnBhcnQpLFxuICAgICAgICAuLi4obS5tZXRhZGF0YSAhPSBudWxsID8geyBtZXRhZGF0YTogbS5tZXRhZGF0YSB9IDoge30pLFxuICAgICAgfSBhcyBUeXBlZFVJTWVzc2FnZTtcbiAgICB9KVxuICAgIC5maWx0ZXIoKG0pID0+IG0ucGFydHMubGVuZ3RoID4gMCk7XG59XG4iLCAiZXhwb3J0IHR5cGUgU3RlcFVzYWdlID0ge1xuICBzdGVwSW5kZXg6IG51bWJlcjtcbiAgbW9kZWw6IHN0cmluZztcbiAgaW5wdXRUb2tlbnM6IG51bWJlcjtcbiAgb3V0cHV0VG9rZW5zOiBudW1iZXI7XG4gIHRvdGFsVG9rZW5zOiBudW1iZXI7XG4gIGNhY2hlUmVhZFRva2VuczogbnVtYmVyO1xuICBjYWNoZVdyaXRlVG9rZW5zOiBudW1iZXI7XG4gIHJlYXNvbmluZ1Rva2VuczogbnVtYmVyO1xufTtcblxuZXhwb3J0IHR5cGUgVXNhZ2VTdW1tYXJ5ID0ge1xuICBtb2RlbDogc3RyaW5nO1xuICBpbnB1dFRva2VuczogbnVtYmVyO1xuICBvdXRwdXRUb2tlbnM6IG51bWJlcjtcbiAgdG90YWxUb2tlbnM6IG51bWJlcjtcbiAgY2FjaGVSZWFkVG9rZW5zOiBudW1iZXI7XG4gIGNhY2hlV3JpdGVUb2tlbnM6IG51bWJlcjtcbiAgcmVhc29uaW5nVG9rZW5zOiBudW1iZXI7XG4gIHN0ZXBDb3VudDogbnVtYmVyO1xufTtcblxuZXhwb3J0IHR5cGUgU2Vzc2lvblVzYWdlID0ge1xuICB0b3RhbDogVXNhZ2VTdW1tYXJ5ICYgeyBtZXNzYWdlQ291bnQ6IG51bWJlciB9O1xuICBieU1lc3NhZ2VJZDogUmVjb3JkPHN0cmluZywgVXNhZ2VTdW1tYXJ5IHwgbnVsbD47XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gY29tcHV0ZVNlc3Npb25Vc2FnZShcbiAgbWVzc2FnZXM6IEFycmF5PHtcbiAgICBpZDogc3RyaW5nO1xuICAgIHVzYWdlOiB7IHN0ZXBzOiBTdGVwVXNhZ2VbXTsgc3VtbWFyeTogVXNhZ2VTdW1tYXJ5IH0gfCBudWxsO1xuICB9PlxuKTogU2Vzc2lvblVzYWdlIHtcbiAgY29uc3QgYnlNZXNzYWdlSWQ6IFJlY29yZDxzdHJpbmcsIFVzYWdlU3VtbWFyeSB8IG51bGw+ID0ge307XG4gIGZvciAoY29uc3QgbSBvZiBtZXNzYWdlcykge1xuICAgIGJ5TWVzc2FnZUlkW20uaWRdID0gbS51c2FnZT8uc3VtbWFyeSA/PyBudWxsO1xuICB9XG5cbiAgY29uc3Qgc3VtbWFyaWVzID0gbWVzc2FnZXNcbiAgICAubWFwKChtKSA9PiBtLnVzYWdlPy5zdW1tYXJ5KVxuICAgIC5maWx0ZXIoKHMpOiBzIGlzIFVzYWdlU3VtbWFyeSA9PiBzICE9PSB1bmRlZmluZWQpO1xuXG4gIGNvbnN0IHRvdGFsID0ge1xuICAgIG1vZGVsOiBzdW1tYXJpZXNbMF0/Lm1vZGVsID8/IFwidW5rbm93blwiLFxuICAgIGlucHV0VG9rZW5zOiBzdW1tYXJpZXMucmVkdWNlKChhY2MsIHMpID0+IGFjYyArIHMuaW5wdXRUb2tlbnMsIDApLFxuICAgIG91dHB1dFRva2Vuczogc3VtbWFyaWVzLnJlZHVjZSgoYWNjLCBzKSA9PiBhY2MgKyBzLm91dHB1dFRva2VucywgMCksXG4gICAgdG90YWxUb2tlbnM6IHN1bW1hcmllcy5yZWR1Y2UoKGFjYywgcykgPT4gYWNjICsgcy50b3RhbFRva2VucywgMCksXG4gICAgY2FjaGVSZWFkVG9rZW5zOiBzdW1tYXJpZXMucmVkdWNlKChhY2MsIHMpID0+IGFjYyArIHMuY2FjaGVSZWFkVG9rZW5zLCAwKSxcbiAgICBjYWNoZVdyaXRlVG9rZW5zOiBzdW1tYXJpZXMucmVkdWNlKChhY2MsIHMpID0+IGFjYyArIHMuY2FjaGVXcml0ZVRva2VucywgMCksXG4gICAgcmVhc29uaW5nVG9rZW5zOiBzdW1tYXJpZXMucmVkdWNlKChhY2MsIHMpID0+IGFjYyArIHMucmVhc29uaW5nVG9rZW5zLCAwKSxcbiAgICBzdGVwQ291bnQ6IHN1bW1hcmllcy5yZWR1Y2UoKGFjYywgcykgPT4gYWNjICsgcy5zdGVwQ291bnQsIDApLFxuICAgIG1lc3NhZ2VDb3VudDogc3VtbWFyaWVzLmxlbmd0aCxcbiAgfTtcblxuICByZXR1cm4geyB0b3RhbCwgYnlNZXNzYWdlSWQgfTtcbn1cbiIsICJpbXBvcnQgdHlwZSB7IFRvb2xTZXQgfSBmcm9tIFwiYWlcIjtcbmltcG9ydCB7IGFzc2VtYmxlVUlNZXNzYWdlcyB9IGZyb20gXCIuLi91dGlscy91aVwiO1xuaW1wb3J0IHsgY29tcHV0ZVNlc3Npb25Vc2FnZSwgdHlwZSBTZXNzaW9uVXNhZ2UgfSBmcm9tIFwiLi4vdXRpbHMvdXNhZ2VcIjtcbmltcG9ydCB0eXBlIHsgU2Vzc2lvbkNvbnRleHQgfSBmcm9tIFwiLi9oYW5kbGVcIjtcblxuZXhwb3J0IHR5cGUgSGlzdG9yeVJlc3VsdCA9IHtcbiAgbWVzc2FnZXM6IFJldHVyblR5cGU8dHlwZW9mIGFzc2VtYmxlVUlNZXNzYWdlcz47XG4gIHN0cmVhbWluZ01lc3NhZ2VJZDogc3RyaW5nIHwgbnVsbDtcbiAgdXNhZ2U6IFNlc3Npb25Vc2FnZTtcbn07XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoaXN0b3J5PFRvb2xzIGV4dGVuZHMgVG9vbFNldD4oXG4gIHNlc3Npb25Db250ZXh0OiBTZXNzaW9uQ29udGV4dFxuKSB7XG4gIFwidXNlIHN0ZXBcIjtcbiAgY29uc3QgW3Nlc3Npb24sIG1lc3NhZ2VzLCBwYXJ0c10gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgc2Vzc2lvbkNvbnRleHQuYWdlbnQuc3RvcmFnZS5zZXNzaW9uLmdldChzZXNzaW9uQ29udGV4dC5zZXNzaW9uSWQpLFxuICAgIHNlc3Npb25Db250ZXh0LmFnZW50LnN0b3JhZ2UubWVzc2FnZS5saXN0QnlTZXNzaW9uKFxuICAgICAgc2Vzc2lvbkNvbnRleHQuc2Vzc2lvbklkXG4gICAgKSxcbiAgICBzZXNzaW9uQ29udGV4dC5hZ2VudC5zdG9yYWdlLnBhcnQubGlzdEJ5U2Vzc2lvbihzZXNzaW9uQ29udGV4dC5zZXNzaW9uSWQpLFxuICBdKTtcblxuICBjb25zdCBsYXN0QXNzaXN0YW50ID1cbiAgICBtZXNzYWdlcy5maW5kKFxuICAgICAgKG0pID0+IG0uaWQgPT09IHNlc3Npb24/Lmxhc3RNZXNzYWdlSWQgJiYgbS5yb2xlID09PSBcImFzc2lzdGFudFwiXG4gICAgKSA/PyBtZXNzYWdlcy5maWx0ZXIoKG0pID0+IG0ucm9sZSA9PT0gXCJhc3Npc3RhbnRcIikuYXQoLTEpO1xuXG4gIGNvbnN0IGlzU3RyZWFtaW5nID1cbiAgICBsYXN0QXNzaXN0YW50Py5jb21wbGV0ZWRBdCA9PT0gbnVsbCAmJlxuICAgIGxhc3RBc3Npc3RhbnQ/LmludGVycnVwdGVkQXQgPT09IG51bGw7XG4gIGNvbnN0IHN0cmVhbWluZ01lc3NhZ2VJZCA9IGlzU3RyZWFtaW5nID8gbGFzdEFzc2lzdGFudC5pZCA6IG51bGw7XG4gIGNvbnN0IHZpc2libGVVbnRpbCA9IGxhc3RBc3Npc3RhbnQ/LmNyZWF0ZWRBdDtcblxuICBjb25zdCBhc3NlbWJsZWQgPSBhc3NlbWJsZVVJTWVzc2FnZXM8VG9vbHM+KHtcbiAgICBtZXNzYWdlcyxcbiAgICBwYXJ0cyxcbiAgICBpbmNsdWRlUXVldWVkOiB2aXNpYmxlVW50aWwgIT09IHVuZGVmaW5lZCxcbiAgICB1bnRpbDogdmlzaWJsZVVudGlsLFxuICB9KTtcblxuICBjb25zdCB1c2FnZSA9IGNvbXB1dGVTZXNzaW9uVXNhZ2UobWVzc2FnZXMpO1xuXG4gIHJldHVybiB7IG1lc3NhZ2VzOiBhc3NlbWJsZWQsIHN0cmVhbWluZ01lc3NhZ2VJZCwgdXNhZ2UgfTtcbn1cbiIsICJpbXBvcnQgdHlwZSB7IFVJTWVzc2FnZSB9IGZyb20gXCJhaVwiO1xuaW1wb3J0IHR5cGUgeyBTZXNzaW9uQ29udGV4dCB9IGZyb20gXCIuL2hhbmRsZVwiO1xuXG5leHBvcnQgdHlwZSBJbnRlcnJ1cHRPcHRpb25zID0ge1xuICBsYXN0UGFydD86IHtcbiAgICBpbmRleDogbnVtYmVyO1xuICAgIHBhcnQ6IHVua25vd247XG4gIH07XG59O1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaW50ZXJydXB0KFxuICBzZXNzaW9uQ29udGV4dDogU2Vzc2lvbkNvbnRleHQsXG4gIG9wdHM/OiBJbnRlcnJ1cHRPcHRpb25zXG4pIHtcbiAgXCJ1c2Ugc3RlcFwiO1xuICBjb25zdCBtZXNzYWdlcyA9IGF3YWl0IHNlc3Npb25Db250ZXh0LmFnZW50LnN0b3JhZ2UubWVzc2FnZS5saXN0QnlTZXNzaW9uKFxuICAgIHNlc3Npb25Db250ZXh0LnNlc3Npb25JZFxuICApO1xuXG4gIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gIGxldCBwZW5kaW5nQXNzaXN0YW50TWVzc2FnZXMgPSBtZXNzYWdlcy5maWx0ZXIoXG4gICAgKG0pID0+XG4gICAgICBtLnJvbGUgPT09IFwiYXNzaXN0YW50XCIgJiZcbiAgICAgIG0uY29tcGxldGVkQXQgPT09IG51bGwgJiZcbiAgICAgIG0uaW50ZXJydXB0ZWRBdCA9PT0gbnVsbFxuICApO1xuXG4gIGlmIChwZW5kaW5nQXNzaXN0YW50TWVzc2FnZXMubGVuZ3RoID09PSAwKSB7XG4gICAgY29uc3QgTUFYX1JFVFJPQUNUSVZFX01TID0gNV8wMDA7XG4gICAgY29uc3QgbGF0ZXN0ID0gbWVzc2FnZXNcbiAgICAgIC5maWx0ZXIoXG4gICAgICAgIChtKSA9PlxuICAgICAgICAgIG0ucm9sZSA9PT0gXCJhc3Npc3RhbnRcIiAmJlxuICAgICAgICAgIG0uaW50ZXJydXB0ZWRBdCA9PT0gbnVsbCAmJlxuICAgICAgICAgIG0uY29tcGxldGVkQXQgIT09IG51bGwgJiZcbiAgICAgICAgICBub3cgLSBtLmNvbXBsZXRlZEF0IDwgTUFYX1JFVFJPQUNUSVZFX01TXG4gICAgICApXG4gICAgICAuc29ydCgoYSwgYikgPT4gYi5jcmVhdGVkQXQgLSBhLmNyZWF0ZWRBdClcbiAgICAgIC5hdCgwKTtcbiAgICBpZiAobGF0ZXN0KSB7XG4gICAgICBwZW5kaW5nQXNzaXN0YW50TWVzc2FnZXMgPSBbbGF0ZXN0XTtcbiAgICB9XG4gIH1cblxuICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICBwZW5kaW5nQXNzaXN0YW50TWVzc2FnZXMubWFwKChtKSA9PlxuICAgICAgc2Vzc2lvbkNvbnRleHQuYWdlbnQuc3RvcmFnZS5tZXNzYWdlLnNldChtLmlkLCB7XG4gICAgICAgIC4uLm0sXG4gICAgICAgIGludGVycnVwdGVkQXQ6IG5vdyxcbiAgICAgICAgaW50ZXJydXB0ZWRMYXN0UGFydDogb3B0cz8ubGFzdFBhcnQgPz8gbnVsbCxcbiAgICAgIH0pXG4gICAgKVxuICApO1xuXG4gIGNvbnN0IG1lc3NhZ2VJZHMgPSBuZXcgU2V0KHBlbmRpbmdBc3Npc3RhbnRNZXNzYWdlcy5tYXAoKG0pID0+IG0uaWQpKTtcbiAgaWYgKG1lc3NhZ2VJZHMuc2l6ZSA9PT0gMCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IGFsbFBhcnRzID0gYXdhaXQgc2Vzc2lvbkNvbnRleHQuYWdlbnQuc3RvcmFnZS5wYXJ0Lmxpc3RCeVNlc3Npb24oXG4gICAgc2Vzc2lvbkNvbnRleHQuc2Vzc2lvbklkXG4gICk7XG5cbiAgZm9yIChjb25zdCBwIG9mIGFsbFBhcnRzKSB7XG4gICAgaWYgKCFtZXNzYWdlSWRzLmhhcyhwLm1lc3NhZ2VJZCkpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBpZiAoXG4gICAgICBwLnBhcnQgJiZcbiAgICAgIFwic3RhdGVcIiBpbiBwLnBhcnQgJiZcbiAgICAgIChwLnBhcnQgYXMgeyBzdGF0ZTogc3RyaW5nIH0pLnN0YXRlID09PSBcImFwcHJvdmFsLXJlcXVlc3RlZFwiICYmXG4gICAgICBcImFwcHJvdmFsXCIgaW4gcC5wYXJ0XG4gICAgKSB7XG4gICAgICBjb25zdCBhcHByb3ZhbCA9IChwLnBhcnQgYXMgeyBhcHByb3ZhbD86IHsgaWQ6IHN0cmluZyB9IH0pLmFwcHJvdmFsO1xuICAgICAgaWYgKGFwcHJvdmFsPy5pZCkge1xuICAgICAgICBhd2FpdCBzZXNzaW9uQ29udGV4dC5hZ2VudC5zdG9yYWdlLnBhcnQuc2V0KHAuaWQsIHtcbiAgICAgICAgICAuLi5wLFxuICAgICAgICAgIHBhcnQ6IHtcbiAgICAgICAgICAgIC4uLnAucGFydCxcbiAgICAgICAgICAgIHN0YXRlOiBcIm91dHB1dC1kZW5pZWRcIixcbiAgICAgICAgICAgIGFwcHJvdmFsOiB7XG4gICAgICAgICAgICAgIC4uLmFwcHJvdmFsLFxuICAgICAgICAgICAgICBhcHByb3ZlZDogZmFsc2UsXG4gICAgICAgICAgICAgIHJlYXNvbjogXCJpbnRlcnJ1cHRlZFwiLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9IGFzIFVJTWVzc2FnZVtcInBhcnRzXCJdW251bWJlcl0sXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuIiwgImltcG9ydCB0eXBlIHsgRmluaXNoUmVhc29uLCBUb29sU2V0LCBVSU1lc3NhZ2UsIFVJTWVzc2FnZUNodW5rIH0gZnJvbSBcImFpXCI7XG5pbXBvcnQgeyBhbGwgfSBmcm9tIFwiYmV0dGVyLWFsbFwiO1xuaW1wb3J0ICogYXMgZXJyb3JlIGZyb20gXCJlcnJvcmVcIjtcbmltcG9ydCB7IHVsaWQgfSBmcm9tIFwidWxpZFwiO1xuaW1wb3J0IHR5cGUgeyBUeXBlZFVJTWVzc2FnZSB9IGZyb20gXCIuLi9hZ2VudC9yZWdpc3RyeVwiO1xuaW1wb3J0IHR5cGUgeyBTa2lsbFN1bW1hcnkgfSBmcm9tIFwiLi4vc2tpbGxzL3R5cGVzXCI7XG5pbXBvcnQgdHlwZSB7IE1lc3NhZ2UsIFBhcnQgfSBmcm9tIFwiLi4vc3RvcmFnZS90eXBlc1wiO1xuaW1wb3J0IHsgY3JlYXRlTG9nZ2VyIH0gZnJvbSBcIi4uL3V0aWxzL2xvZ2dlclwiO1xuaW1wb3J0IHR5cGUgeyBTdGVwVXNhZ2UgfSBmcm9tIFwiLi4vdXRpbHMvdXNhZ2VcIjtcbmltcG9ydCB7XG4gIHR5cGUgU3RyZWFtVGV4dFJlc3VsdCxcbiAgc3RyZWFtVGV4dCxcbiAgc3RyZWFtVGV4dFN0ZXAsXG59IGZyb20gXCIuL2FpLWxvb3Avc3RyZWFtLXRleHRcIjtcbmltcG9ydCB0eXBlIHsgU2Vzc2lvbkNvbnRleHQgfSBmcm9tIFwiLi9oYW5kbGVcIjtcbmltcG9ydCB7IGludGVycnVwdCB9IGZyb20gXCIuL2ludGVycnVwdFwiO1xuXG5jb25zdCBERUZBVUxUX1NURVBfVEhST1VHSFBVVCA9IDEwMDtcblxuZXhwb3J0IHR5cGUgQXBwcm92YWxEYXRhID0ge1xuICBhcHByb3ZhbElkOiBzdHJpbmc7XG4gIGFwcHJvdmVkOiBib29sZWFuO1xuICByZWFzb24/OiBzdHJpbmc7XG59O1xuXG50eXBlIE1lc3NhZ2VEYXRhPFRvb2xzIGV4dGVuZHMgVG9vbFNldCwgVE1lc3NhZ2VNZXRhZGF0YSA9IHVua25vd24+ID1cbiAgfCBVSU1lc3NhZ2U8VE1lc3NhZ2VNZXRhZGF0YT5cbiAgfCB7XG4gICAgICByb2xlPzogVHlwZWRVSU1lc3NhZ2U8dW5rbm93biwgVG9vbHM+W1wicm9sZVwiXTtcbiAgICAgIHBhcnRzOiBUeXBlZFVJTWVzc2FnZTx1bmtub3duLCBUb29scz5bXCJwYXJ0c1wiXTtcbiAgICAgIG1ldGFkYXRhPzogVE1lc3NhZ2VNZXRhZGF0YSB8IG51bGw7XG4gICAgICBpZD86IHN0cmluZztcbiAgICB9O1xuXG5leHBvcnQgdHlwZSBTZW5kSW5wdXQ8VG9vbHMgZXh0ZW5kcyBUb29sU2V0LCBUTWVzc2FnZU1ldGFkYXRhID0gdW5rbm93bj4gPVxuICB8IHN0cmluZ1xuICB8IE1lc3NhZ2VEYXRhPFRvb2xzLCBUTWVzc2FnZU1ldGFkYXRhPlxuICB8IHsgdHlwZTogXCJtZXNzYWdlXCI7IG1lc3NhZ2U6IE1lc3NhZ2VEYXRhPFRvb2xzLCBUTWVzc2FnZU1ldGFkYXRhPiB9XG4gIHwgeyB0eXBlOiBcImFwcHJvdmFsXCI7IGFwcHJvdmFsOiBBcHByb3ZhbERhdGEgfTtcblxuZXhwb3J0IHR5cGUgU2VuZE9wdGlvbnM8VENvbnRleHQsIFRTdGF0ZSA9IHVua25vd24+ID0ge1xuICBpbnRlcnJ1cHRJZlN0cmVhbWluZz86XG4gICAgfCBib29sZWFuXG4gICAgfCB7IGxhc3RQYXJ0OiB7IGluZGV4OiBudW1iZXI7IHBhcnQ6IHVua25vd24gfSB9O1xuICBjb250ZXh0PzogVENvbnRleHQ7XG4gIGluaXRpYWxTdGF0ZT86IFRTdGF0ZTtcbiAgYWJvcnRTaWduYWw/OiBBYm9ydFNpZ25hbDtcbiAgc2FuZGJveElkPzogc3RyaW5nO1xufTtcblxuZXhwb3J0IHR5cGUgU2VuZFJlc3VsdCA9IHtcbiAgYXNzaXN0YW50TWVzc2FnZUlkOiBzdHJpbmc7XG4gIGRvbmU6IHRydWUgfCBQcm9taXNlPHRydWU+O1xufTtcblxuZXhwb3J0IHR5cGUgQWN0aXZlUnVuID0ge1xuICBjaHVua3M6IFVJTWVzc2FnZUNodW5rW107XG4gIHdyaXRhYmxlOiBXcml0YWJsZVN0cmVhbTxVSU1lc3NhZ2VDaHVuaz47XG4gIGRvbmU6IFByb21pc2U8dm9pZD47XG4gIC8qKiBSZXNvbHZlcyB3aGVuIGEgbmV3IGNodW5rIGlzIGF2YWlsYWJsZS4gUmVwbGFjZWQgYWZ0ZXIgZWFjaCBub3RpZmljYXRpb24uICovXG4gIG9uQ2h1bms6IFByb21pc2U8dm9pZD47XG59O1xuXG5jb25zdCBBQ1RJVkVfUlVOU19LRVkgPSBTeW1ib2wuZm9yKFwiZXhwZXJpbWVudGFsLWFnZW50OmFjdGl2ZVJ1bnNcIik7XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRBY3RpdmVSdW5zKCk6IE1hcDxzdHJpbmcsIEFjdGl2ZVJ1bj4ge1xuICBjb25zdCBnID0gZ2xvYmFsVGhpcyBhcyBSZWNvcmQ8c3ltYm9sLCBNYXA8c3RyaW5nLCBBY3RpdmVSdW4+IHwgdW5kZWZpbmVkPjtcbiAgaWYgKCFnW0FDVElWRV9SVU5TX0tFWV0pIHtcbiAgICBnW0FDVElWRV9SVU5TX0tFWV0gPSBuZXcgTWFwKCk7XG4gIH1cbiAgcmV0dXJuIGdbQUNUSVZFX1JVTlNfS0VZXTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNlbmQ8XG4gIFRvb2xzIGV4dGVuZHMgVG9vbFNldCxcbiAgVENvbnRleHQsXG4gIFRNZXNzYWdlTWV0YWRhdGEgPSB1bmtub3duLFxuICBUU3RhdGUgPSB1bmtub3duLFxuPihcbiAgc2Vzc2lvbkNvbnRleHQ6IFNlc3Npb25Db250ZXh0LFxuICBpbnB1dDpcbiAgICB8IFNlbmRJbnB1dDxUb29scywgVE1lc3NhZ2VNZXRhZGF0YT5cbiAgICB8IFNlbmRJbnB1dDxUb29scywgVE1lc3NhZ2VNZXRhZGF0YT5bXSxcbiAgb3B0cz86IFNlbmRPcHRpb25zPFRDb250ZXh0LCBUU3RhdGU+XG4pOiBQcm9taXNlPFNlbmRSZXN1bHQ+IHtcbiAgaWYgKG9wdHM/LmludGVycnVwdElmU3RyZWFtaW5nKSB7XG4gICAgY29uc3QgbGFzdFBhcnQgPVxuICAgICAgdHlwZW9mIG9wdHMuaW50ZXJydXB0SWZTdHJlYW1pbmcgPT09IFwib2JqZWN0XCJcbiAgICAgICAgPyBvcHRzLmludGVycnVwdElmU3RyZWFtaW5nLmxhc3RQYXJ0XG4gICAgICAgIDogdW5kZWZpbmVkO1xuICAgIGF3YWl0IGludGVycnVwdChzZXNzaW9uQ29udGV4dCwgeyBsYXN0UGFydCB9KTtcbiAgfVxuXG4gIGNvbnN0IHtcbiAgICB3b3JrZmxvd1J1bklkLFxuICAgIHdvcmtmbG93V3JpdGFibGUsXG4gICAgZXhpc3RpbmdQYXJ0Q291bnQsXG4gICAgYXNzaXN0YW50TWVzc2FnZUlkLFxuICAgIGFzc2lzdGFudE1lc3NhZ2VDcmVhdGVkQXQsXG4gICAgc3RhdGUsXG4gIH0gPSBhd2FpdCBlcnJvcmUudHJ5QXN5bmMoe1xuICAgIHRyeTogKCkgPT5cbiAgICAgIGluaXRTZXNzaW9uU3RlcDxUb29scz4oe1xuICAgICAgICBzZXNzaW9uQ29udGV4dCxcbiAgICAgICAgc2Vzc2lvbklkOiBzZXNzaW9uQ29udGV4dC5zZXNzaW9uSWQsXG4gICAgICAgIHNhbmRib3hJZDogb3B0cz8uc2FuZGJveElkLFxuICAgICAgICBpbml0aWFsU3RhdGU6IG9wdHM/LmluaXRpYWxTdGF0ZSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB8IHVuZGVmaW5lZCxcbiAgICAgICAgaW5wdXQsXG4gICAgICB9KSxcbiAgICBjYXRjaDogKGUpID0+IHtcbiAgICAgIGlmIChlIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICAgIHRocm93IG5ldyBTZW5kRXJyb3Ioe1xuICAgICAgICBpZDogc2Vzc2lvbkNvbnRleHQuc2Vzc2lvbklkLFxuICAgICAgICByZWFzb246IFN0cmluZyhlKSxcbiAgICAgICAgY2F1c2U6IGUsXG4gICAgICB9KTtcbiAgICB9LFxuICB9KTtcblxuICBjb25zdCBsb29wT3B0cyA9IHtcbiAgICBzZXNzaW9uQ29udGV4dCxcbiAgICBhc3Npc3RhbnRNZXNzYWdlSWQsXG4gICAgY3JlYXRlZEF0OiBhc3Npc3RhbnRNZXNzYWdlQ3JlYXRlZEF0LFxuICAgIGNvbnRleHQ6IChvcHRzPy5jb250ZXh0ID8/IHt9KSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgICBzdGF0ZSxcbiAgICBsYXN0UGFydEluZGV4OiBleGlzdGluZ1BhcnRDb3VudCxcbiAgICB3b3JrZmxvd1J1bklkLFxuICB9O1xuXG4gIGlmICh3b3JrZmxvd1dyaXRhYmxlKSB7XG4gICAgYXdhaXQgcnVuTG9vcDxUb29scz4oeyAuLi5sb29wT3B0cywgd3JpdGFibGU6IHdvcmtmbG93V3JpdGFibGUgfSk7XG4gICAgcmV0dXJuIHsgYXNzaXN0YW50TWVzc2FnZUlkLCBkb25lOiB0cnVlIH07XG4gIH1cblxuICBjb25zdCBjaHVua3M6IFVJTWVzc2FnZUNodW5rW10gPSBbXTtcbiAgbGV0IG5vdGlmeUNodW5rOiAoKSA9PiB2b2lkO1xuICBsZXQgb25DaHVuayA9IG5ldyBQcm9taXNlPHZvaWQ+KChyKSA9PiB7XG4gICAgbm90aWZ5Q2h1bmsgPSByO1xuICB9KTtcblxuICBjb25zdCB3cml0YWJsZSA9IG5ldyBXcml0YWJsZVN0cmVhbTxVSU1lc3NhZ2VDaHVuaz4oe1xuICAgIHdyaXRlKGNodW5rKSB7XG4gICAgICBjaHVua3MucHVzaChjaHVuayk7XG4gICAgICBjb25zdCBwcmV2ID0gbm90aWZ5Q2h1bms7XG4gICAgICBvbkNodW5rID0gbmV3IFByb21pc2U8dm9pZD4oKHIpID0+IHtcbiAgICAgICAgbm90aWZ5Q2h1bmsgPSByO1xuICAgICAgfSk7XG4gICAgICBwcmV2KCk7XG4gICAgfSxcbiAgfSk7XG5cbiAgY29uc3QgZG9uZSA9IHJ1bkxvb3A8VG9vbHM+KHsgLi4ubG9vcE9wdHMsIHdyaXRhYmxlIH0pO1xuXG4gIGNvbnN0IGFjdGl2ZVJ1bjogQWN0aXZlUnVuID0ge1xuICAgIGNodW5rcyxcbiAgICB3cml0YWJsZSxcbiAgICBkb25lLFxuICAgIGdldCBvbkNodW5rKCkge1xuICAgICAgcmV0dXJuIG9uQ2h1bms7XG4gICAgfSxcbiAgfTtcbiAgY29uc3QgYWN0aXZlUnVucyA9IGdldEFjdGl2ZVJ1bnMoKTtcbiAgYWN0aXZlUnVucy5zZXQoYXNzaXN0YW50TWVzc2FnZUlkLCBhY3RpdmVSdW4pO1xuICBkb25lLmZpbmFsbHkoKCkgPT4gYWN0aXZlUnVucy5kZWxldGUoYXNzaXN0YW50TWVzc2FnZUlkKSk7XG5cbiAgcmV0dXJuIHsgYXNzaXN0YW50TWVzc2FnZUlkLCBkb25lOiBkb25lLnRoZW4oKCkgPT4gdHJ1ZSkgfTtcbn1cblxuLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogQUkgTG9vcFxuICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG5hc3luYyBmdW5jdGlvbiBydW5Mb29wPFRvb2xzIGV4dGVuZHMgVG9vbFNldD4oe1xuICB3b3JrZmxvd1J1bklkLFxuICBzZXNzaW9uQ29udGV4dCxcbiAgYXNzaXN0YW50TWVzc2FnZUlkLFxuICBjcmVhdGVkQXQsXG4gIGNvbnRleHQ6IGluaXRpYWxDb250ZXh0LFxuICBzdGF0ZSxcbiAgd3JpdGFibGUsXG4gIGxhc3RQYXJ0SW5kZXg6IGluaXRpYWxQYXJ0SW5kZXgsXG59OiB7XG4gIHdvcmtmbG93UnVuSWQ6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgc2Vzc2lvbkNvbnRleHQ6IFNlc3Npb25Db250ZXh0O1xuICBhc3Npc3RhbnRNZXNzYWdlSWQ6IHN0cmluZztcbiAgY3JlYXRlZEF0OiBudW1iZXI7XG4gIGNvbnRleHQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBzdGF0ZTogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIHdyaXRhYmxlOiBXcml0YWJsZVN0cmVhbTtcbiAgbGFzdFBhcnRJbmRleDogbnVtYmVyO1xufSk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBhZ2VudCA9IHNlc3Npb25Db250ZXh0LmFnZW50O1xuXG4gIGNvbnN0IGxvZyA9IGNyZWF0ZUxvZ2dlcih7XG4gICAgY29uZmlnOiB7IC4uLmFnZW50Lm9wdGlvbnMubG9nZ2luZywgbmFtZTogYWdlbnQubmFtZSB9LFxuICAgIHN1YnN5c3RlbTogXCJhaS1sb29wXCIsXG4gIH0pO1xuICBjb25zdCBtc2dMb2cgPSBsb2cud2l0aENvbnRleHQoe1xuICAgIHNlc3Npb25JZDogc2Vzc2lvbkNvbnRleHQuc2Vzc2lvbklkLFxuICAgIG1lc3NhZ2VJZDogYXNzaXN0YW50TWVzc2FnZUlkLFxuICB9KTtcbiAgY29uc3QgZG9uZU1lc3NhZ2UgPSBtc2dMb2cudGltZShcIm9uTWVzc2FnZVwiKTtcblxuICBsZXQgZmluaXNoUmVhc29uOiBGaW5pc2hSZWFzb24gfCB1bmRlZmluZWQ7XG4gIGxldCBsYXN0UGFydEluZGV4ID0gaW5pdGlhbFBhcnRJbmRleDtcbiAgY29uc3QgdXNhZ2VTdGVwczogU3RlcFVzYWdlW10gPSBbXTtcbiAgbGV0IGRpc2NvdmVyZWRTa2lsbHM6IFNraWxsU3VtbWFyeVtdIHwgbnVsbCA9IG51bGw7XG4gIGxldCBjb250ZXh0ID0gaW5pdGlhbENvbnRleHQ7XG5cbiAgdHJ5IHtcbiAgICB3aGlsZSAoZmluaXNoUmVhc29uICE9PSBcInN0b3BcIikge1xuICAgICAgY29uc3Qgc3RyZWFtVGV4dEZuID0gd29ya2Zsb3dSdW5JZFxuICAgICAgICA/IHN0cmVhbVRleHRTdGVwPFRvb2xzPlxuICAgICAgICA6IHN0cmVhbVRleHQ8VG9vbHM+O1xuICAgICAgY29uc3QgdGhyb3VnaHB1dCA9IHdvcmtmbG93UnVuSWQgPyA1IDogREVGQVVMVF9TVEVQX1RIUk9VR0hQVVQ7XG5cbiAgICAgIGNvbnN0IHJlc3VsdDogU3RyZWFtVGV4dFJlc3VsdCA9IGF3YWl0IHN0cmVhbVRleHRGbih7XG4gICAgICAgIHN0ZXBUaHJvdWdocHV0OiB0aHJvdWdocHV0LFxuICAgICAgICBhc3Npc3RhbnRNZXNzYWdlSWQsXG4gICAgICAgIGFnZW50LFxuICAgICAgICBzZXNzaW9uSWQ6IHNlc3Npb25Db250ZXh0LnNlc3Npb25JZCxcbiAgICAgICAgY29udGV4dCxcbiAgICAgICAgc3RhdGUsXG4gICAgICAgIGNyZWF0ZWRBdCxcbiAgICAgICAgd3JpdGFibGUsXG4gICAgICAgIGxhc3RQYXJ0SW5kZXgsXG4gICAgICAgIHN0ZXBJbmRleE9mZnNldDogdXNhZ2VTdGVwcy5sZW5ndGgsXG4gICAgICAgIGRpc2NvdmVyZWRTa2lsbHMsXG4gICAgICB9KTtcblxuICAgICAgZmluaXNoUmVhc29uID0gcmVzdWx0LmZpbmlzaFJlYXNvbjtcbiAgICAgIGxhc3RQYXJ0SW5kZXggPSByZXN1bHQubGFzdFBhcnRJbmRleDtcbiAgICAgIHVzYWdlU3RlcHMucHVzaCguLi5yZXN1bHQudXNhZ2VTdGVwcyk7XG4gICAgICBkaXNjb3ZlcmVkU2tpbGxzID0gcmVzdWx0LmRpc2NvdmVyZWRTa2lsbHM7XG4gICAgICBjb250ZXh0ID0gcmVzdWx0LmNvbnRleHQ7XG5cbiAgICAgIGlmIChyZXN1bHQubWF4U3RlcHMgIT0gbnVsbCAmJiB1c2FnZVN0ZXBzLmxlbmd0aCA+PSByZXN1bHQubWF4U3RlcHMpIHtcbiAgICAgICAgbXNnTG9nLmluZm8oXCJyZWFjaGVkIG1heFN0ZXBzIGxpbWl0XCIsIHsgbWF4U3RlcHM6IHJlc3VsdC5tYXhTdGVwcyB9KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICAgIGlmIChyZXN1bHQucGVuZGluZ0FwcHJvdmFscy5sZW5ndGggPiAwKSB7XG4gICAgICAgIG1zZ0xvZy5pbmZvKFwicGVuZGluZyBhcHByb3ZhbHMsIHN0b3BwaW5nIGxvb3BcIiwge1xuICAgICAgICAgIGNvdW50OiByZXN1bHQucGVuZGluZ0FwcHJvdmFscy5sZW5ndGgsXG4gICAgICAgICAgdG9vbHM6IHJlc3VsdC5wZW5kaW5nQXBwcm92YWxzLm1hcCgocCkgPT4gcC50b29sTmFtZSksXG4gICAgICAgIH0pO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICBkb25lTWVzc2FnZSh7IHRvdGFsU3RlcHM6IHVzYWdlU3RlcHMubGVuZ3RoIH0pO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBtc2dMb2cuZXJyb3IoXCJBSSBsb29wIGZhaWxlZFwiLCB7XG4gICAgICBlcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpLFxuICAgIH0pO1xuICAgIHRocm93IGVycjtcbiAgfSBmaW5hbGx5IHtcbiAgICBhd2FpdCBjb21wbGV0ZU1lc3NhZ2VTdGVwKHtcbiAgICAgIGFzc2lzdGFudE1lc3NhZ2VJZCxcbiAgICAgIHNlc3Npb25Db250ZXh0LFxuICAgICAgd3JpdGFibGUsXG4gICAgICB1c2FnZVN0ZXBzLFxuICAgIH0pO1xuICB9XG59XG5cbi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqIFN0ZXBzXG4gKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbmFzeW5jIGZ1bmN0aW9uIGluaXRTZXNzaW9uU3RlcDxUb29scyBleHRlbmRzIFRvb2xTZXQ+KHtcbiAgc2Vzc2lvbkNvbnRleHQsXG4gIHNlc3Npb25JZCxcbiAgc2FuZGJveElkLFxuICBpbml0aWFsU3RhdGUsXG4gIGlucHV0LFxufToge1xuICBzZXNzaW9uQ29udGV4dDogU2Vzc2lvbkNvbnRleHQ7XG4gIHNlc3Npb25JZDogc3RyaW5nO1xuICBzYW5kYm94SWQ/OiBzdHJpbmc7XG4gIGluaXRpYWxTdGF0ZT86IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBpbnB1dDogU2VuZElucHV0PFRvb2xzPiB8IFNlbmRJbnB1dDxUb29scz5bXTtcbn0pIHtcbiAgXCJ1c2Ugc3RlcFwiO1xuXG4gIGxldCB3b3JrZmxvd1J1bklkOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIGxldCB3b3JrZmxvd1dyaXRhYmxlOiBXcml0YWJsZVN0cmVhbSB8IHVuZGVmaW5lZDtcbiAgdHJ5IHtcbiAgICBjb25zdCB7IGdldFdvcmtmbG93TWV0YWRhdGEsIGdldFdyaXRhYmxlIH0gPSBhd2FpdCBpbXBvcnQoXCJ3b3JrZmxvd1wiKTtcbiAgICB3b3JrZmxvd1J1bklkID0gZ2V0V29ya2Zsb3dNZXRhZGF0YSgpLndvcmtmbG93UnVuSWQ7XG4gICAgd29ya2Zsb3dXcml0YWJsZSA9IGdldFdyaXRhYmxlKCk7XG4gIH0gY2F0Y2gge1xuICAgIC8vIHdvcmtmbG93IG5vdCBpbnN0YWxsZWRcbiAgfVxuXG4gIGNvbnN0IG5ld01lc3NhZ2VzOiBNZXNzYWdlW10gPSBbXTtcbiAgY29uc3QgbmV3UGFydHM6IFBhcnRbXSA9IFtdO1xuICBjb25zdCBuZXdBcHByb3ZhbHM6IEFwcHJvdmFsRGF0YVtdID0gW107XG4gIGlmIChBcnJheS5pc0FycmF5KGlucHV0KSkge1xuICAgIGZvciAoY29uc3QgaSBvZiBpbnB1dCkge1xuICAgICAgY29uc3QgeyBtZXNzYWdlLCBwYXJ0cywgYXBwcm92YWxzIH0gPSB0b01lc3NhZ2VBbmRQYXJ0cyh7XG4gICAgICAgIHNlc3Npb25JZDogc2Vzc2lvbkNvbnRleHQuc2Vzc2lvbklkLFxuICAgICAgICBpbnB1dDogaSxcbiAgICAgICAgZGVmYXVsdFJvbGU6IFwidXNlclwiLFxuICAgICAgfSk7XG4gICAgICBpZiAobWVzc2FnZSkge1xuICAgICAgICBuZXdNZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgICAgfVxuICAgICAgbmV3UGFydHMucHVzaCguLi5wYXJ0cyk7XG4gICAgICBuZXdBcHByb3ZhbHMucHVzaCguLi5hcHByb3ZhbHMpO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBjb25zdCB7IG1lc3NhZ2UsIHBhcnRzLCBhcHByb3ZhbHMgfSA9IHRvTWVzc2FnZUFuZFBhcnRzKHtcbiAgICAgIGlucHV0LFxuICAgICAgc2Vzc2lvbklkOiBzZXNzaW9uQ29udGV4dC5zZXNzaW9uSWQsXG4gICAgICBkZWZhdWx0Um9sZTogXCJ1c2VyXCIsXG4gICAgfSk7XG4gICAgaWYgKG1lc3NhZ2UpIHtcbiAgICAgIG5ld01lc3NhZ2VzLnB1c2gobWVzc2FnZSk7XG4gICAgfVxuICAgIG5ld1BhcnRzLnB1c2goLi4ucGFydHMpO1xuICAgIG5ld0FwcHJvdmFscy5wdXNoKC4uLmFwcHJvdmFscyk7XG4gIH1cblxuICBjb25zdCBsYXN0TmV3TWVzc2FnZSA9IG5ld01lc3NhZ2VzLmF0KC0xKTtcbiAgY29uc3QgcmV1c2VBc3Npc3RhbnQgPSBsYXN0TmV3TWVzc2FnZT8ucm9sZSA9PT0gXCJhc3Npc3RhbnRcIjtcblxuICBjb25zdCBhc3Npc3RhbnRNZXNzYWdlSWQgPSByZXVzZUFzc2lzdGFudFxuICAgID8gbGFzdE5ld01lc3NhZ2UuaWRcbiAgICA6IGBtZXNzYWdlXyR7dWxpZCgpfWA7XG4gIGNvbnN0IGJhc2VUaW1lID0gRGF0ZS5ub3coKTtcbiAgY29uc3QgYXNzaXN0YW50TWVzc2FnZUNyZWF0ZWRBdCA9IGJhc2VUaW1lICsgbmV3TWVzc2FnZXMubGVuZ3RoO1xuXG4gIGlmICghcmV1c2VBc3Npc3RhbnQpIHtcbiAgICBuZXdNZXNzYWdlcy5wdXNoKHtcbiAgICAgIGlkOiBhc3Npc3RhbnRNZXNzYWdlSWQsXG4gICAgICBzZXNzaW9uSWQ6IHNlc3Npb25Db250ZXh0LnNlc3Npb25JZCxcbiAgICAgIHJvbGU6IFwiYXNzaXN0YW50XCIsXG4gICAgICBjcmVhdGVkQXQ6IGFzc2lzdGFudE1lc3NhZ2VDcmVhdGVkQXQsXG4gICAgICBzdGFydGVkQXQ6IG51bGwsXG4gICAgICBjb21wbGV0ZWRBdDogbnVsbCxcbiAgICAgIGludGVycnVwdGVkQXQ6IG51bGwsXG4gICAgICBpbnRlcnJ1cHRlZExhc3RQYXJ0OiBudWxsLFxuICAgICAgdXNhZ2U6IG51bGwsXG4gICAgICB3b3JrZmxvd1J1bklkOiBudWxsLFxuICAgICAgbWV0YWRhdGE6IG51bGwsXG4gICAgfSk7XG4gIH1cblxuICBjb25zdCBleGlzdGluZ1BhcnRDb3VudCA9IHJldXNlQXNzaXN0YW50XG4gICAgPyBuZXdQYXJ0cy5maWx0ZXIoKHApID0+IHAubWVzc2FnZUlkID09PSBhc3Npc3RhbnRNZXNzYWdlSWQpLmxlbmd0aFxuICAgIDogMDtcblxuICBsZXQgc2Vzc2lvbiA9IGF3YWl0IHNlc3Npb25Db250ZXh0LmFnZW50LnN0b3JhZ2Uuc2Vzc2lvbi5nZXQoc2Vzc2lvbklkKTtcbiAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgaWYgKCFzZXNzaW9uKSB7XG4gICAgc2Vzc2lvbiA9IHtcbiAgICAgIGlkOiBzZXNzaW9uSWQsXG4gICAgICBzYW5kYm94SWQ6IHNhbmRib3hJZCA/PyBudWxsLFxuICAgICAgbGFzdE1lc3NhZ2VJZDogbnVsbCxcbiAgICAgIGNyZWF0ZWRBdDogbm93LFxuICAgICAgdXBkYXRlZEF0OiBub3csXG4gICAgfTtcbiAgICBhd2FpdCBzZXNzaW9uQ29udGV4dC5hZ2VudC5zdG9yYWdlLnNlc3Npb24uc2V0KHNlc3Npb24uaWQsIHNlc3Npb24pO1xuICB9IGVsc2UgaWYgKHNhbmRib3hJZCAmJiBzYW5kYm94SWQgIT09IHNlc3Npb24uc2FuZGJveElkKSB7XG4gICAgc2Vzc2lvbiA9IHsgLi4uc2Vzc2lvbiwgc2FuZGJveElkLCB1cGRhdGVkQXQ6IG5vdyB9O1xuICAgIGF3YWl0IHNlc3Npb25Db250ZXh0LmFnZW50LnN0b3JhZ2Uuc2Vzc2lvbi51cGRhdGUoc2Vzc2lvbi5pZCwge1xuICAgICAgc2FuZGJveElkLFxuICAgIH0pO1xuICB9XG5cbiAgYXdhaXQgYWxsKHtcbiAgICBhc3luYyBzYXZlTWVzc2FnZXMoKSB7XG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgbmV3TWVzc2FnZXMubWFwKGFzeW5jIChtLCBpKSA9PiB7XG4gICAgICAgICAgY29uc3QgZXhpc3RpbmcgPSBhd2FpdCBzZXNzaW9uQ29udGV4dC5hZ2VudC5zdG9yYWdlLm1lc3NhZ2UuZ2V0KG0uaWQpO1xuICAgICAgICAgIGlmIChleGlzdGluZykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICBhd2FpdCBzZXNzaW9uQ29udGV4dC5hZ2VudC5zdG9yYWdlLm1lc3NhZ2Uuc2V0KG0uaWQsIHtcbiAgICAgICAgICAgIC4uLm0sXG4gICAgICAgICAgICBjcmVhdGVkQXQ6IGJhc2VUaW1lICsgaSxcbiAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6XG4gICAgICAgICAgICAgIG0uaWQgPT09IGFzc2lzdGFudE1lc3NhZ2VJZFxuICAgICAgICAgICAgICAgID8gKHdvcmtmbG93UnVuSWQgPz8gbnVsbClcbiAgICAgICAgICAgICAgICA6IG0ud29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfSxcbiAgICBhc3luYyBzYXZlUGFydHMoKSB7XG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgbmV3UGFydHMubWFwKGFzeW5jIChwKSA9PlxuICAgICAgICAgIHNlc3Npb25Db250ZXh0LmFnZW50LnN0b3JhZ2UucGFydC5zZXQocC5pZCwgcClcbiAgICAgICAgKVxuICAgICAgKTtcbiAgICB9LFxuICAgIGFzeW5jIHJlc29sdmVBcHByb3ZhbHMoKSB7XG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgbmV3QXBwcm92YWxzLm1hcChhc3luYyAoYSkgPT4ge1xuICAgICAgICAgIGNvbnN0IHBhcnRJZCA9IGFwcHJvdmFsUGFydElkKGEuYXBwcm92YWxJZCk7XG4gICAgICAgICAgY29uc3QgcGFydCA9IGF3YWl0IHNlc3Npb25Db250ZXh0LmFnZW50LnN0b3JhZ2UucGFydC5nZXQocGFydElkKTtcbiAgICAgICAgICBpZiAoIXBhcnQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBBcHByb3ZhbE5vdEZvdW5kRXJyb3Ioe1xuICAgICAgICAgICAgICBpZDogc2Vzc2lvbkNvbnRleHQuc2Vzc2lvbklkLFxuICAgICAgICAgICAgICBhcHByb3ZhbElkOiBhLmFwcHJvdmFsSWQsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgYXdhaXQgc2Vzc2lvbkNvbnRleHQuYWdlbnQuc3RvcmFnZS5wYXJ0LnNldChwYXJ0SWQsIHtcbiAgICAgICAgICAgIC4uLnBhcnQsXG4gICAgICAgICAgICBwYXJ0OiB7XG4gICAgICAgICAgICAgIC4uLnBhcnQucGFydCxcbiAgICAgICAgICAgICAgc3RhdGU6IGEuYXBwcm92ZWQgPyBcImFwcHJvdmFsLXJlc3BvbmRlZFwiIDogXCJvdXRwdXQtZGVuaWVkXCIsXG4gICAgICAgICAgICAgIGFwcHJvdmFsOiB7XG4gICAgICAgICAgICAgICAgaWQ6IGEuYXBwcm92YWxJZCxcbiAgICAgICAgICAgICAgICBhcHByb3ZlZDogYS5hcHByb3ZlZCxcbiAgICAgICAgICAgICAgICByZWFzb246IGEucmVhc29uLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSBhcyB0eXBlb2YgcGFydC5wYXJ0LFxuICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9LFxuICAgIGFzeW5jIHVwZGF0ZVNlc3Npb24oKSB7XG4gICAgICBhd2FpdCBzZXNzaW9uQ29udGV4dC5hZ2VudC5zdG9yYWdlLnNlc3Npb24uc2V0KHNlc3Npb24uaWQsIHtcbiAgICAgICAgLi4uc2Vzc2lvbixcbiAgICAgICAgbGFzdE1lc3NhZ2VJZDogYXNzaXN0YW50TWVzc2FnZUlkLFxuICAgICAgICB1cGRhdGVkQXQ6IERhdGUubm93KCksXG4gICAgICB9KTtcbiAgICB9LFxuICB9KTtcblxuICBjb25zdCBzdGF0ZTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSBzZXNzaW9uLnN0YXRlXG4gICAgPyB7IC4uLnNlc3Npb24uc3RhdGUgfVxuICAgIDogeyAuLi4oaW5pdGlhbFN0YXRlID8/IHt9KSB9O1xuXG4gIHJldHVybiB7XG4gICAgd29ya2Zsb3dSdW5JZCxcbiAgICB3b3JrZmxvd1dyaXRhYmxlLFxuICAgIGV4aXN0aW5nUGFydENvdW50LFxuICAgIGFzc2lzdGFudE1lc3NhZ2VJZCxcbiAgICBhc3Npc3RhbnRNZXNzYWdlQ3JlYXRlZEF0LFxuICAgIHN0YXRlLFxuICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBjb21wbGV0ZU1lc3NhZ2VTdGVwKHtcbiAgYXNzaXN0YW50TWVzc2FnZUlkLFxuICBzZXNzaW9uQ29udGV4dCxcbiAgd3JpdGFibGUsXG4gIHVzYWdlU3RlcHMsXG59OiB7XG4gIGFzc2lzdGFudE1lc3NhZ2VJZDogc3RyaW5nO1xuICBzZXNzaW9uQ29udGV4dDogU2Vzc2lvbkNvbnRleHQ7XG4gIHdyaXRhYmxlOiBXcml0YWJsZVN0cmVhbTtcbiAgdXNhZ2VTdGVwczogU3RlcFVzYWdlW107XG59KSB7XG4gIFwidXNlIHN0ZXBcIjtcblxuICBjb25zdCBsb2cgPSBjcmVhdGVMb2dnZXIoe1xuICAgIGNvbmZpZzoge1xuICAgICAgLi4uc2Vzc2lvbkNvbnRleHQuYWdlbnQub3B0aW9ucy5sb2dnaW5nLFxuICAgICAgbmFtZTogc2Vzc2lvbkNvbnRleHQuYWdlbnQubmFtZSxcbiAgICB9LFxuICAgIHN1YnN5c3RlbTogXCJhaS1sb29wXCIsXG4gIH0pO1xuICBjb25zdCBtc2dMb2cgPSBsb2cud2l0aENvbnRleHQoe1xuICAgIHNlc3Npb25JZDogc2Vzc2lvbkNvbnRleHQuc2Vzc2lvbklkLFxuICAgIG1lc3NhZ2VJZDogYXNzaXN0YW50TWVzc2FnZUlkLFxuICB9KTtcblxuICBjb25zdCB1c2FnZSA9XG4gICAgdXNhZ2VTdGVwcy5sZW5ndGggPiAwXG4gICAgICA/IHtcbiAgICAgICAgICBzdGVwczogdXNhZ2VTdGVwcyxcbiAgICAgICAgICBzdW1tYXJ5OiB7XG4gICAgICAgICAgICBtb2RlbDogdXNhZ2VTdGVwc1swXT8ubW9kZWwgPz8gXCJ1bmtub3duXCIsXG4gICAgICAgICAgICBpbnB1dFRva2VuczogdXNhZ2VTdGVwcy5yZWR1Y2UoKGEsIHMpID0+IGEgKyBzLmlucHV0VG9rZW5zLCAwKSxcbiAgICAgICAgICAgIG91dHB1dFRva2VuczogdXNhZ2VTdGVwcy5yZWR1Y2UoKGEsIHMpID0+IGEgKyBzLm91dHB1dFRva2VucywgMCksXG4gICAgICAgICAgICB0b3RhbFRva2VuczogdXNhZ2VTdGVwcy5yZWR1Y2UoKGEsIHMpID0+IGEgKyBzLnRvdGFsVG9rZW5zLCAwKSxcbiAgICAgICAgICAgIGNhY2hlUmVhZFRva2VuczogdXNhZ2VTdGVwcy5yZWR1Y2UoXG4gICAgICAgICAgICAgIChhLCBzKSA9PiBhICsgcy5jYWNoZVJlYWRUb2tlbnMsXG4gICAgICAgICAgICAgIDBcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBjYWNoZVdyaXRlVG9rZW5zOiB1c2FnZVN0ZXBzLnJlZHVjZShcbiAgICAgICAgICAgICAgKGEsIHMpID0+IGEgKyBzLmNhY2hlV3JpdGVUb2tlbnMsXG4gICAgICAgICAgICAgIDBcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICByZWFzb25pbmdUb2tlbnM6IHVzYWdlU3RlcHMucmVkdWNlKFxuICAgICAgICAgICAgICAoYSwgcykgPT4gYSArIHMucmVhc29uaW5nVG9rZW5zLFxuICAgICAgICAgICAgICAwXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgc3RlcENvdW50OiB1c2FnZVN0ZXBzLmxlbmd0aCxcbiAgICAgICAgICB9LFxuICAgICAgICB9XG4gICAgICA6IG51bGw7XG5cbiAgYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgIHNlc3Npb25Db250ZXh0LmFnZW50LnN0b3JhZ2UubWVzc2FnZS51cGRhdGUoYXNzaXN0YW50TWVzc2FnZUlkLCB7XG4gICAgICBjb21wbGV0ZWRBdDogRGF0ZS5ub3coKSxcbiAgICAgIHVzYWdlLFxuICAgIH0pLFxuICAgIHdyaXRhYmxlLmNsb3NlKCkuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKSxcbiAgXSk7XG5cbiAgbXNnTG9nLmluZm8oXCJtZXNzYWdlIGNvbXBsZXRlZFwiLCB7XG4gICAgc3RlcHM6IHVzYWdlU3RlcHMubGVuZ3RoLFxuICAgIHRvdGFsVG9rZW5zOiB1c2FnZT8uc3VtbWFyeS50b3RhbFRva2VucyxcbiAgfSk7XG59XG5cbi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqIFV0aWxzXG4gKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbmV4cG9ydCBmdW5jdGlvbiBhcHByb3ZhbFBhcnRJZChhcHByb3ZhbElkOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gYHBhcnRfJHthcHByb3ZhbElkfWA7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZXBsYXlBY3RpdmVSdW4oXG4gIGFjdGl2ZTogQWN0aXZlUnVuLFxuICBzdGFydEluZGV4ID0gMFxuKTogUmVhZGFibGVTdHJlYW08VUlNZXNzYWdlQ2h1bms+IHtcbiAgbGV0IGN1cnNvciA9IHN0YXJ0SW5kZXg7XG4gIGxldCBjYW5jZWxsZWQgPSBmYWxzZTtcblxuICByZXR1cm4gbmV3IFJlYWRhYmxlU3RyZWFtPFVJTWVzc2FnZUNodW5rPih7XG4gICAgYXN5bmMgcHVsbChjb250cm9sbGVyKSB7XG4gICAgICAvLyBEcmFpbiBhbnkgYnVmZmVyZWQgY2h1bmtzXG4gICAgICB3aGlsZSAoY3Vyc29yIDwgYWN0aXZlLmNodW5rcy5sZW5ndGgpIHtcbiAgICAgICAgY29udHJvbGxlci5lbnF1ZXVlKGFjdGl2ZS5jaHVua3NbY3Vyc29yKytdKTtcbiAgICAgIH1cblxuICAgICAgLy8gV2FpdCBmb3IgZWl0aGVyIGEgbmV3IGNodW5rIG9yIGNvbXBsZXRpb25cbiAgICAgIHdoaWxlICghY2FuY2VsbGVkICYmIGN1cnNvciA+PSBhY3RpdmUuY2h1bmtzLmxlbmd0aCkge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBQcm9taXNlLnJhY2UoW1xuICAgICAgICAgIGFjdGl2ZS5vbkNodW5rLnRoZW4oKCkgPT4gXCJjaHVua1wiIGFzIGNvbnN0KSxcbiAgICAgICAgICBhY3RpdmUuZG9uZS50aGVuKCgpID0+IFwiZG9uZVwiIGFzIGNvbnN0KSxcbiAgICAgICAgXSk7XG5cbiAgICAgICAgLy8gRHJhaW4gbmV3IGNodW5rc1xuICAgICAgICB3aGlsZSAoY3Vyc29yIDwgYWN0aXZlLmNodW5rcy5sZW5ndGgpIHtcbiAgICAgICAgICBjb250cm9sbGVyLmVucXVldWUoYWN0aXZlLmNodW5rc1tjdXJzb3IrK10pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHJlc3VsdCA9PT0gXCJkb25lXCIpIHtcbiAgICAgICAgICBjb250cm9sbGVyLmNsb3NlKCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcbiAgICBjYW5jZWwoKSB7XG4gICAgICBjYW5jZWxsZWQgPSB0cnVlO1xuICAgIH0sXG4gIH0pO1xufVxuXG5mdW5jdGlvbiB0b01lc3NhZ2VBbmRQYXJ0czxUb29scyBleHRlbmRzIFRvb2xTZXQ+KHtcbiAgc2Vzc2lvbklkLFxuICBpZCxcbiAgaW5wdXQsXG4gIGRlZmF1bHRSb2xlLFxufToge1xuICBzZXNzaW9uSWQ6IHN0cmluZztcbiAgaWQ/OiBzdHJpbmc7XG4gIGlucHV0OiBTZW5kSW5wdXQ8VG9vbHM+O1xuICBkZWZhdWx0Um9sZTogVUlNZXNzYWdlW1wicm9sZVwiXTtcbn0pOiB7XG4gIG1lc3NhZ2U6IE1lc3NhZ2UgfCB1bmRlZmluZWQ7XG4gIHBhcnRzOiBQYXJ0W107XG4gIGFwcHJvdmFsczogQXBwcm92YWxEYXRhW107XG59IHtcbiAgbGV0IG1lc3NhZ2VJZCA9IGlkID8/IGBtZXNzYWdlXyR7dWxpZCgpfWA7XG4gIGlmICh0eXBlb2YgaW5wdXQgPT09IFwic3RyaW5nXCIpIHtcbiAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgIHJldHVybiB7XG4gICAgICBhcHByb3ZhbHM6IFtdLFxuICAgICAgbWVzc2FnZToge1xuICAgICAgICBpZDogbWVzc2FnZUlkLFxuICAgICAgICBzZXNzaW9uSWQsXG4gICAgICAgIHJvbGU6IGRlZmF1bHRSb2xlLFxuICAgICAgICBjcmVhdGVkQXQ6IG5vdyxcbiAgICAgICAgc3RhcnRlZEF0OiBudWxsLFxuICAgICAgICBjb21wbGV0ZWRBdDogbnVsbCxcbiAgICAgICAgaW50ZXJydXB0ZWRBdDogbnVsbCxcbiAgICAgICAgaW50ZXJydXB0ZWRMYXN0UGFydDogbnVsbCxcbiAgICAgICAgdXNhZ2U6IG51bGwsXG4gICAgICAgIHdvcmtmbG93UnVuSWQ6IG51bGwsXG4gICAgICAgIG1ldGFkYXRhOiBudWxsLFxuICAgICAgfSxcbiAgICAgIHBhcnRzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBzZXNzaW9uSWQsXG4gICAgICAgICAgbWVzc2FnZUlkLFxuICAgICAgICAgIGlkOiBgcGFydF8ke21lc3NhZ2VJZH1fMGAsXG4gICAgICAgICAgaW5kZXg6IDAsXG4gICAgICAgICAgcGFydDogeyB0eXBlOiBcInRleHRcIiwgdGV4dDogaW5wdXQgfSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfTtcbiAgfVxuICBpZiAoXCJ0eXBlXCIgaW4gaW5wdXQgJiYgaW5wdXQudHlwZSA9PT0gXCJhcHByb3ZhbFwiKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG1lc3NhZ2U6IHVuZGVmaW5lZCxcbiAgICAgIHBhcnRzOiBbXSxcbiAgICAgIGFwcHJvdmFsczogW2lucHV0LmFwcHJvdmFsXSxcbiAgICB9O1xuICB9XG5cbiAgY29uc3QgbXNnID1cbiAgICBcInR5cGVcIiBpbiBpbnB1dCAmJiBpbnB1dC50eXBlID09PSBcIm1lc3NhZ2VcIiA/IGlucHV0Lm1lc3NhZ2UgOiBpbnB1dDtcbiAgaWYgKFwiaWRcIiBpbiBtc2cgJiYgbXNnLmlkKSB7XG4gICAgbWVzc2FnZUlkID0gbXNnLmlkO1xuICB9XG5cbiAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgY29uc3QgbWV0YWRhdGEgPVxuICAgIFwibWV0YWRhdGFcIiBpbiBtc2cgJiYgbXNnLm1ldGFkYXRhICE9IG51bGxcbiAgICAgID8gKG1zZy5tZXRhZGF0YSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPilcbiAgICAgIDogbnVsbDtcbiAgcmV0dXJuIHtcbiAgICBhcHByb3ZhbHM6IFtdLFxuICAgIG1lc3NhZ2U6IHtcbiAgICAgIHNlc3Npb25JZCxcbiAgICAgIGlkOiBtZXNzYWdlSWQsXG4gICAgICBjcmVhdGVkQXQ6IG5vdyxcbiAgICAgIHN0YXJ0ZWRBdDogbnVsbCxcbiAgICAgIGNvbXBsZXRlZEF0OiBudWxsLFxuICAgICAgaW50ZXJydXB0ZWRBdDogbnVsbCxcbiAgICAgIGludGVycnVwdGVkTGFzdFBhcnQ6IG51bGwsXG4gICAgICB1c2FnZTogbnVsbCxcbiAgICAgIHdvcmtmbG93UnVuSWQ6IG51bGwsXG4gICAgICByb2xlOiBtc2cucm9sZSA/PyBkZWZhdWx0Um9sZSxcbiAgICAgIG1ldGFkYXRhLFxuICAgIH0sXG4gICAgcGFydHM6IG1zZy5wYXJ0cy5tYXAoKHBhcnQsIGluZGV4KSA9PiB7XG4gICAgICBjb25zdCBhcCA9IHBhcnQgYXMgeyBhcHByb3ZhbD86IHsgaWQ6IHN0cmluZyB9IH07XG4gICAgICBjb25zdCBpZCA9IGFwLmFwcHJvdmFsPy5pZFxuICAgICAgICA/IGFwcHJvdmFsUGFydElkKGFwLmFwcHJvdmFsLmlkKVxuICAgICAgICA6IGBwYXJ0XyR7bWVzc2FnZUlkfV8ke2luZGV4fWA7XG4gICAgICByZXR1cm4geyBzZXNzaW9uSWQsIG1lc3NhZ2VJZCwgaWQsIGluZGV4LCBwYXJ0IH07XG4gICAgfSksXG4gIH07XG59XG5cbi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqIEVycm9yc1xuICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG5leHBvcnQgY2xhc3MgU2VuZEVycm9yIGV4dGVuZHMgZXJyb3JlLmNyZWF0ZVRhZ2dlZEVycm9yKHtcbiAgbmFtZTogXCJTZW5kRXJyb3JcIixcbiAgbWVzc2FnZTogXCJTZW5kIGZhaWxlZCBmb3Igc2Vzc2lvbiAkaWQ6ICRyZWFzb25cIixcbn0pIHt9XG5cbmV4cG9ydCBjbGFzcyBBcHByb3ZhbE5vdEZvdW5kRXJyb3IgZXh0ZW5kcyBlcnJvcmUuY3JlYXRlVGFnZ2VkRXJyb3Ioe1xuICBuYW1lOiBcIkFwcHJvdmFsTm90Rm91bmRFcnJvclwiLFxuICBtZXNzYWdlOiBcIkFwcHJvdmFsICRhcHByb3ZhbElkIG5vdCBmb3VuZCBpbiBzZXNzaW9uICRpZFwiLFxufSkge31cbiIsICJpbXBvcnQgdHlwZSB7XG4gIEZpbmlzaFJlYXNvbixcbiAgVG9vbFNldCxcbiAgVUlNZXNzYWdlLFxuICBVSU1lc3NhZ2VTdHJlYW1Xcml0ZXIsXG59IGZyb20gXCJhaVwiO1xuaW1wb3J0IHtcbiAgY29udmVydFRvTW9kZWxNZXNzYWdlcyxcbiAgY3JlYXRlVUlNZXNzYWdlU3RyZWFtLFxuICBzdGVwQ291bnRJcyxcbiAgc3RyZWFtVGV4dCBhcyBzdHJlYW1UZXh0QWksXG59IGZyb20gXCJhaVwiO1xuaW1wb3J0IHR5cGUge1xuICBBZ2VudFN0YXR1cyxcbiAgQW55QWdlbnQsXG4gIFJlc29sdmFibGUsXG4gIFJlc29sdmFibGVBcmdzLFxuICBUeXBlZFVJTWVzc2FnZSxcbn0gZnJvbSBcIi4uLy4uL2FnZW50L2NsaWVudFwiO1xuaW1wb3J0IHsgU2Vzc2lvbk5vdEZvdW5kRXJyb3IgfSBmcm9tIFwiLi4vLi4vZXJyb3JzXCI7XG5pbXBvcnQgeyBkaXNjb3ZlclNraWxsc0luU2FuZGJveCB9IGZyb20gXCIuLi8uLi9za2lsbHMvZGlzY292ZXJcIjtcbmltcG9ydCB7IHJlc29sdmVTa2lsbElucHV0c1RvU2FuZGJveERpcnMgfSBmcm9tIFwiLi4vLi4vc2tpbGxzL3Jlc29sdmVcIjtcbmltcG9ydCB0eXBlIHsgU2tpbGxTdW1tYXJ5IH0gZnJvbSBcIi4uLy4uL3NraWxscy90eXBlc1wiO1xuaW1wb3J0IHR5cGUgeyBQYXJ0IH0gZnJvbSBcIi4uLy4uL3N0b3JhZ2UvdHlwZXNcIjtcbmltcG9ydCB7IHR5cGUgQnVpbHRJblRvb2xOYW1lLCBnZXRUb29scywgdHlwZSBUb29sQ29udGV4dCB9IGZyb20gXCIuLi8uLi90b29sc1wiO1xuaW1wb3J0IHsgY3JlYXRlTG9nZ2VyLCB0eXBlIExvZ2dlciB9IGZyb20gXCIuLi8uLi91dGlscy9sb2dnZXJcIjtcbmltcG9ydCB7XG4gIGFwcGx5UHJvbXB0Q2FjaGluZ1RvTW9kZWxSZXF1ZXN0LFxuICBtZXJnZVByb3ZpZGVyT3B0aW9ucyxcbn0gZnJvbSBcIi4uLy4uL3V0aWxzL3Byb21wdC1jYWNoZVwiO1xuaW1wb3J0IHsgYXNzZW1ibGVVSU1lc3NhZ2VzIH0gZnJvbSBcIi4uLy4uL3V0aWxzL3VpXCI7XG5pbXBvcnQgdHlwZSB7IFN0ZXBVc2FnZSB9IGZyb20gXCIuLi8uLi91dGlscy91c2FnZVwiO1xuaW1wb3J0IHsgYXBwcm92YWxQYXJ0SWQgfSBmcm9tIFwiLi4vc2VuZFwiO1xuXG5jb25zdCBJTlRFUlJVUFRfUE9MTF9JTlRFUlZBTF9NUyA9IDI1MDtcblxuZnVuY3Rpb24gcG9sbEZvckludGVycnVwdCh7XG4gIGFnZW50LFxuICBtZXNzYWdlSWQsXG4gIHNpZ25hbCxcbiAgYWJvcnRDb250cm9sbGVyLFxufToge1xuICBhZ2VudDogQW55QWdlbnQ7XG4gIG1lc3NhZ2VJZDogc3RyaW5nO1xuICBzaWduYWw6IEFib3J0U2lnbmFsO1xuICBhYm9ydENvbnRyb2xsZXI6IEFib3J0Q29udHJvbGxlcjtcbn0pOiB7XG4gIGZpcnN0Q2hlY2s6IFByb21pc2U8dm9pZD47XG4gIGludGVycnVwdGVkTGFzdFBhcnRSZWY6IHsgY3VycmVudDogeyBpbmRleDogbnVtYmVyOyBwYXJ0OiB1bmtub3duIH0gfCBudWxsIH07XG59IHtcbiAgbGV0IHJlc29sdmVGaXJzdENoZWNrOiAoKSA9PiB2b2lkO1xuICBjb25zdCBmaXJzdENoZWNrID0gbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUpID0+IHtcbiAgICByZXNvbHZlRmlyc3RDaGVjayA9IHJlc29sdmU7XG4gIH0pO1xuICBjb25zdCBpbnRlcnJ1cHRlZExhc3RQYXJ0UmVmID0ge1xuICAgIGN1cnJlbnQ6IG51bGwgYXMgeyBpbmRleDogbnVtYmVyOyBwYXJ0OiB1bmtub3duIH0gfCBudWxsLFxuICB9O1xuXG4gIGNvbnN0IGxvZyA9IGNyZWF0ZUxvZ2dlcih7XG4gICAgY29uZmlnOiB7IC4uLmFnZW50Lm9wdGlvbnMubG9nZ2luZywgbmFtZTogYWdlbnQubmFtZSB9LFxuICAgIHN1YnN5c3RlbTogXCJhaS1sb29wXCIsXG4gIH0pO1xuXG4gIGNvbnN0IHBvbGwgPSBhc3luYyAoKSA9PiB7XG4gICAgbGV0IGlzRmlyc3QgPSB0cnVlO1xuICAgIHdoaWxlICghc2lnbmFsLmFib3J0ZWQpIHtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBhd2FpdCBhZ2VudC5zdG9yYWdlLm1lc3NhZ2UuZ2V0KG1lc3NhZ2VJZCk7XG4gICAgICBpZiAoIW1lc3NhZ2UpIHtcbiAgICAgICAgaWYgKGlzRmlyc3QpIHtcbiAgICAgICAgICByZXNvbHZlRmlyc3RDaGVjaygpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE1lc3NhZ2UgJHttZXNzYWdlSWR9IG5vdCBmb3VuZGApO1xuICAgICAgfVxuICAgICAgaWYgKG1lc3NhZ2UuaW50ZXJydXB0ZWRBdCAhPT0gbnVsbCkge1xuICAgICAgICBsb2cuaW5mbyhcImludGVycnVwdCBkZXRlY3RlZFwiLCB7IG1lc3NhZ2VJZCB9KTtcbiAgICAgICAgaW50ZXJydXB0ZWRMYXN0UGFydFJlZi5jdXJyZW50ID0gbWVzc2FnZS5pbnRlcnJ1cHRlZExhc3RQYXJ0O1xuICAgICAgICBhYm9ydENvbnRyb2xsZXIuYWJvcnQoKTtcbiAgICAgICAgaWYgKGlzRmlyc3QpIHtcbiAgICAgICAgICByZXNvbHZlRmlyc3RDaGVjaygpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmIChpc0ZpcnN0KSB7XG4gICAgICAgIGlzRmlyc3QgPSBmYWxzZTtcbiAgICAgICAgcmVzb2x2ZUZpcnN0Q2hlY2soKTtcbiAgICAgIH1cbiAgICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PlxuICAgICAgICBzZXRUaW1lb3V0KHJlc29sdmUsIElOVEVSUlVQVF9QT0xMX0lOVEVSVkFMX01TKVxuICAgICAgKTtcbiAgICB9XG4gIH07XG5cbiAgcG9sbCgpO1xuICByZXR1cm4geyBmaXJzdENoZWNrLCBpbnRlcnJ1cHRlZExhc3RQYXJ0UmVmIH07XG59XG5cbnR5cGUgU3RyZWFtVGV4dE9wdGlvbnMgPSB7XG4gIHN0ZXBUaHJvdWdocHV0OiBudW1iZXI7XG4gIGFzc2lzdGFudE1lc3NhZ2VJZDogc3RyaW5nO1xuICBzZXNzaW9uSWQ6IHN0cmluZztcbiAgYWdlbnQ6IEFueUFnZW50O1xuICBjcmVhdGVkQXQ6IG51bWJlcjtcbiAgY29udGV4dDogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIHN0YXRlOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgd3JpdGFibGU6IFdyaXRhYmxlU3RyZWFtO1xuICBsYXN0UGFydEluZGV4OiBudW1iZXI7XG4gIHN0ZXBJbmRleE9mZnNldDogbnVtYmVyO1xuICBkaXNjb3ZlcmVkU2tpbGxzOiBTa2lsbFN1bW1hcnlbXSB8IG51bGw7XG59O1xuXG5leHBvcnQgdHlwZSBTdHJlYW1UZXh0UmVzdWx0ID0ge1xuICBmaW5pc2hSZWFzb246IEZpbmlzaFJlYXNvbjtcbiAgbGFzdFBhcnRJbmRleDogbnVtYmVyO1xuICB1c2FnZVN0ZXBzOiBTdGVwVXNhZ2VbXTtcbiAgcGVuZGluZ0FwcHJvdmFsczogeyBhcHByb3ZhbElkOiBzdHJpbmc7IHRvb2xOYW1lOiBzdHJpbmcgfVtdO1xuICBtYXhTdGVwczogbnVtYmVyIHwgdW5kZWZpbmVkO1xuICBkaXNjb3ZlcmVkU2tpbGxzOiBTa2lsbFN1bW1hcnlbXSB8IG51bGw7XG4gIGNvbnRleHQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xufTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHN0cmVhbVRleHQ8VG9vbHMgZXh0ZW5kcyBUb29sU2V0Pih7XG4gIHN0ZXBUaHJvdWdocHV0LFxuICBhc3Npc3RhbnRNZXNzYWdlSWQsXG4gIGFnZW50LFxuICBzZXNzaW9uSWQsXG4gIGNvbnRleHQsXG4gIHN0YXRlLFxuICBjcmVhdGVkQXQsXG4gIHdyaXRhYmxlLFxuICBsYXN0UGFydEluZGV4LFxuICBzdGVwSW5kZXhPZmZzZXQsXG4gIGRpc2NvdmVyZWRTa2lsbHMsXG59OiBTdHJlYW1UZXh0T3B0aW9ucyk6IFByb21pc2U8U3RyZWFtVGV4dFJlc3VsdD4ge1xuICBjb25zdCBsb2cgPSBjcmVhdGVMb2dnZXIoe1xuICAgIGNvbmZpZzogeyAuLi5hZ2VudC5vcHRpb25zLmxvZ2dpbmcsIG5hbWU6IGFnZW50Lm5hbWUgfSxcbiAgICBzdWJzeXN0ZW06IFwiYWktbG9vcFwiLFxuICB9KTtcblxuICBjb25zdCBzdGVwTG9nID0gbG9nLndpdGhDb250ZXh0KHtcbiAgICBzZXNzaW9uSWQsXG4gICAgbWVzc2FnZUlkOiBhc3Npc3RhbnRNZXNzYWdlSWQsXG4gIH0pO1xuICBjb25zdCBkb25lU3RlcCA9IHN0ZXBMb2cudGltZShcInN0cmVhbVRleHRcIik7XG5cbiAgY29uc3QgdGhyb3R0bGVkRW1pdFN0YXR1cyA9IGNyZWF0ZVRocm90dGxlZEVtaXRTdGF0dXMoYWdlbnQpO1xuXG4gIGNvbnN0IGFib3J0Q29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgY29uc3QgcG9sbENvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG5cbiAgY29uc3QgeyBmaXJzdENoZWNrLCBpbnRlcnJ1cHRlZExhc3RQYXJ0UmVmIH0gPSBwb2xsRm9ySW50ZXJydXB0KHtcbiAgICBhZ2VudCxcbiAgICBtZXNzYWdlSWQ6IGFzc2lzdGFudE1lc3NhZ2VJZCxcbiAgICBzaWduYWw6IHBvbGxDb250cm9sbGVyLnNpZ25hbCxcbiAgICBhYm9ydENvbnRyb2xsZXIsXG4gIH0pO1xuXG4gIGNvbnN0IGRvbmVMb2FkID0gc3RlcExvZy50aW1lKFwibG9hZCBzZXNzaW9uICsgbWVzc2FnZXMgKyBwYXJ0cyArIHNhbmRib3hcIik7XG4gIGNvbnN0IFssIG1lc3NhZ2VzUmVzdWx0LCBwYXJ0c1Jlc3VsdCwgeyBzYW5kYm94LCBzYW5kYm94UmVjb3JkIH1dID1cbiAgICBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICBmaXJzdENoZWNrLFxuICAgICAgYWdlbnQuc3RvcmFnZS5tZXNzYWdlLmxpc3RCeVNlc3Npb24oc2Vzc2lvbklkKSxcbiAgICAgIGFnZW50LnN0b3JhZ2UucGFydC5saXN0QnlTZXNzaW9uKHNlc3Npb25JZCksXG4gICAgICBhZ2VudC5zdG9yYWdlLnNlc3Npb24uZ2V0KHNlc3Npb25JZCkudGhlbihhc3luYyAoc2Vzc2lvbikgPT4ge1xuICAgICAgICBpZiAoIXNlc3Npb24pIHtcbiAgICAgICAgICB0aHJvdyBuZXcgU2Vzc2lvbk5vdEZvdW5kRXJyb3IoeyBpZDogc2Vzc2lvbklkIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgc2FuZGJveElkID0gc2Vzc2lvbi5zYW5kYm94SWQgPz8gc2Vzc2lvbi5pZDtcbiAgICAgICAgY29uc3Qgc2FuZGJveCA9IGFnZW50LnNhbmRib3goc2FuZGJveElkKTtcbiAgICAgICAgY29uc3Qgc2FuZGJveFJlY29yZCA9IGF3YWl0IGFnZW50LnN0b3JhZ2Uuc2FuZGJveC5nZXQoc2FuZGJveElkKTtcblxuICAgICAgICByZXR1cm4geyBzYW5kYm94LCBzYW5kYm94UmVjb3JkIH07XG4gICAgICB9KSxcbiAgICBdKTtcblxuICBkb25lTG9hZCgpO1xuXG4gIGlmIChhYm9ydENvbnRyb2xsZXIuc2lnbmFsLmFib3J0ZWQpIHtcbiAgICBwb2xsQ29udHJvbGxlci5hYm9ydCgpO1xuICAgIHJldHVybiB7XG4gICAgICBmaW5pc2hSZWFzb246IFwic3RvcFwiIGFzIEZpbmlzaFJlYXNvbixcbiAgICAgIGxhc3RQYXJ0SW5kZXgsXG4gICAgICB1c2FnZVN0ZXBzOiBbXSxcbiAgICAgIHBlbmRpbmdBcHByb3ZhbHM6IFtdLFxuICAgICAgbWF4U3RlcHM6IHVuZGVmaW5lZCxcbiAgICAgIGRpc2NvdmVyZWRTa2lsbHMsXG4gICAgICBjb250ZXh0LFxuICAgIH07XG4gIH1cblxuICBjb25zdCBzZXRTdGFydGVkUHJvbWlzZSA9XG4gICAgbGFzdFBhcnRJbmRleCA9PT0gMFxuICAgICAgPyAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gICAgICAgICAgY29uc3QgcGVuZGluZ01lc3NhZ2VzID0gbWVzc2FnZXNSZXN1bHQuZmlsdGVyKFxuICAgICAgICAgICAgKG0pID0+IG0uY3JlYXRlZEF0IDw9IGNyZWF0ZWRBdCAmJiBtLnN0YXJ0ZWRBdCA9PT0gbnVsbFxuICAgICAgICAgICk7XG4gICAgICAgICAgaWYgKHBlbmRpbmdNZXNzYWdlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgICAgICAgIHBlbmRpbmdNZXNzYWdlcy5tYXAoKG0pID0+XG4gICAgICAgICAgICAgICAgYWdlbnQuc3RvcmFnZS5tZXNzYWdlLnVwZGF0ZShtLmlkLCB7XG4gICAgICAgICAgICAgICAgICBzdGFydGVkQXQ6IG5vdyxcbiAgICAgICAgICAgICAgICAgIGNvbXBsZXRlZEF0OiBtLnJvbGUgPT09IFwiYXNzaXN0YW50XCIgPyBudWxsIDogbm93LFxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9KSgpXG4gICAgICA6IG51bGw7XG5cbiAgY29uc3QgYWxsUGFydHMgPSBbLi4ucGFydHNSZXN1bHRdO1xuICBjb25zdCBuZXh0UGFydEluZGV4UmVmID0ge1xuICAgIGN1cnJlbnQ6IE1hdGgubWF4KFxuICAgICAgbGFzdFBhcnRJbmRleCxcbiAgICAgIC4uLmFsbFBhcnRzXG4gICAgICAgIC5maWx0ZXIoKHApID0+IHAubWVzc2FnZUlkID09PSBhc3Npc3RhbnRNZXNzYWdlSWQpXG4gICAgICAgIC5tYXAoKHApID0+IHAuaW5kZXggKyAxKSxcbiAgICAgIDBcbiAgICApLFxuICB9O1xuXG4gIGNvbnN0IHNraWxsc1JlZjogeyBjdXJyZW50OiBTa2lsbFN1bW1hcnlbXSB9ID0ge1xuICAgIGN1cnJlbnQ6IGRpc2NvdmVyZWRTa2lsbHMgPz8gW10sXG4gIH07XG5cbiAgLy8gQnVpbGQgdWlNZXNzYWdlcyBmcm9tIGN1cnJlbnQgcGFydHMgKHJlYnVpbHQgYmV0d2VlbiBpdGVyYXRpb25zKVxuICBsZXQgdWlNZXNzYWdlcyA9IGFzc2VtYmxlVUlNZXNzYWdlcyh7XG4gICAgbWVzc2FnZXM6IG1lc3NhZ2VzUmVzdWx0LFxuICAgIHBhcnRzOiBhbGxQYXJ0cyxcbiAgICB1bnRpbDogY3JlYXRlZEF0LFxuICAgIGluY2x1ZGVRdWV1ZWQ6IHRydWUsXG4gICAgZXhjbHVkZVN1YlRvb2xQYXJ0czogdHJ1ZSxcbiAgfSk7XG5cbiAgLy8gQnVpbGQgcmVzb2x2YWJsZSBhcmdzIGZvciByZXNvbHZpbmcgYWdlbnQgb3B0aW9uc1xuICBjb25zdCByZXNvbHZhYmxlQXJnczogUmVzb2x2YWJsZUFyZ3MgPSB7XG4gICAgY29udGV4dCxcbiAgICBzdGF0ZSxcbiAgICBzZXNzaW9uSWQsXG4gICAgc2FuZGJveCxcbiAgICBnZXQgbWVzc2FnZXMoKSB7XG4gICAgICByZXR1cm4gdWlNZXNzYWdlcztcbiAgICB9LFxuICB9O1xuXG4gIC8vIHNraWxscyBkaXNjb3ZlcnkgXHUyMDE0IGZpcnN0IGl0ZXJhdGlvbiBvbmx5XG4gIGlmIChsYXN0UGFydEluZGV4ID09PSAwICYmICFkaXNjb3ZlcmVkU2tpbGxzKSB7XG4gICAgY29uc3QgcmVzb2x2ZWRTa2lsbHMgPSBhd2FpdCByZXNvbHZlT3B0aW9uKFxuICAgICAgYWdlbnQub3B0aW9ucy5za2lsbHMsXG4gICAgICByZXNvbHZhYmxlQXJnc1xuICAgICk7XG4gICAgY29uc3Qgc2tpbGxzRGlycyA9IHJlc29sdmVkU2tpbGxzPy5sZW5ndGhcbiAgICAgID8gYXdhaXQgcmVzb2x2ZVNraWxsSW5wdXRzVG9TYW5kYm94RGlycyh7XG4gICAgICAgICAgYWdlbnQsXG4gICAgICAgICAgc2FuZGJveCxcbiAgICAgICAgICBza2lsbHM6IHJlc29sdmVkU2tpbGxzLFxuICAgICAgICAgIHNlc3Npb25JZCxcbiAgICAgICAgfSlcbiAgICAgIDogW107XG4gICAgaWYgKHNraWxsc0RpcnMubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgZG9uZVNraWxscyA9IHN0ZXBMb2cudGltZShcImRpc2NvdmVyIHNraWxsc1wiLCB7IHNraWxsc0RpcnMgfSk7XG4gICAgICBza2lsbHNSZWYuY3VycmVudCA9IGF3YWl0IGRpc2NvdmVyU2tpbGxzSW5TYW5kYm94KHtcbiAgICAgICAgYWdlbnQsXG4gICAgICAgIHNhbmRib3gsXG4gICAgICAgIHNraWxsc0RpcnMsXG4gICAgICAgIHNlc3Npb25JZCxcbiAgICAgIH0pO1xuICAgICAgZG9uZVNraWxscyh7IGNvdW50OiBza2lsbHNSZWYuY3VycmVudC5sZW5ndGggfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIElubmVyIGxvb3A6IHJ1biB1cCB0byBgc3RlcFRocm91Z2hwdXRgIHNlcXVlbnRpYWwgTExNIGNhbGxzLlxuICAgKiBQYXJ0cyBhcmUgcGVyc2lzdGVkIGFmdGVyIGVhY2ggY2FsbCBzbyBwcm9ncmVzcyBpc24ndCBsb3N0LlxuICAgKiBTZXNzaW9uIGlzIHJlLWZldGNoZWQgYmV0d2VlbiBpdGVyYXRpb25zIChjb25maWcgbWF5IGNoYW5nZSksXG4gICAqIHBhcmFsbGVsaXplZCB3aXRoIHBhcnQgcGVyc2lzdGVuY2Ugb24gbm9uLWZpbmFsIGl0ZXJhdGlvbnMuXG4gICAqL1xuICBjb25zdCB1c2FnZVN0ZXBzOiBTdGVwVXNhZ2VbXSA9IFtdO1xuICBsZXQgaW50ZXJuYWxTdGVwSW5kZXggPSAwO1xuICBsZXQgbG9vcEZpbmlzaFJlYXNvbjogRmluaXNoUmVhc29uID0gXCJ1bmtub3duXCIgYXMgRmluaXNoUmVhc29uO1xuICBsZXQgd2FzQWJvcnRlZCA9IGZhbHNlO1xuICBjb25zdCBhbGxQZW5kaW5nQXBwcm92YWxzOiB7IGFwcHJvdmFsSWQ6IHN0cmluZzsgdG9vbE5hbWU6IHN0cmluZyB9W10gPSBbXTtcbiAgbGV0IGN1cnJlbnRNYXhTdGVwczogbnVtYmVyIHwgdW5kZWZpbmVkO1xuXG4gIHRyeSB7XG4gICAgZm9yIChsZXQgaXRlcmF0aW9uID0gMDsgaXRlcmF0aW9uIDwgc3RlcFRocm91Z2hwdXQ7IGl0ZXJhdGlvbisrKSB7XG4gICAgICAvLyBSZXNvbHZlIGFnZW50IG9wdGlvbnMgZnJlc2ggZWFjaCBpdGVyYXRpb25cbiAgICAgIGNvbnN0IHJlc29sdmVkTW9kZWwgPSBhd2FpdCByZXNvbHZlT3B0aW9uKFxuICAgICAgICBhZ2VudC5vcHRpb25zLm1vZGVsLFxuICAgICAgICByZXNvbHZhYmxlQXJnc1xuICAgICAgKTtcbiAgICAgIGNvbnN0IHJlc29sdmVkR2VuZXJhdGlvbiA9IGF3YWl0IHJlc29sdmVPcHRpb24oXG4gICAgICAgIGFnZW50Lm9wdGlvbnMuZ2VuZXJhdGlvbixcbiAgICAgICAgcmVzb2x2YWJsZUFyZ3NcbiAgICAgICk7XG4gICAgICBjb25zdCByZXNvbHZlZEFjdGl2ZVRvb2xzID0gKGF3YWl0IHJlc29sdmVPcHRpb24oXG4gICAgICAgIGFnZW50Lm9wdGlvbnMuYWN0aXZlVG9vbHMsXG4gICAgICAgIHJlc29sdmFibGVBcmdzXG4gICAgICApKSBhcyBzdHJpbmdbXSB8IHVuZGVmaW5lZDtcblxuICAgICAgY3VycmVudE1heFN0ZXBzID0gcmVzb2x2ZWRHZW5lcmF0aW9uPy5tYXhTdGVwcztcblxuICAgICAgaWYgKCFyZXNvbHZlZE1vZGVsKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkFnZW50IG1vZGVsIGlzIG5vdCBzZXRcIik7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHN0ZXBQYXJ0czogVUlNZXNzYWdlW1wicGFydHNcIl0gPSBbXTtcbiAgICAgIGxldCBzdHJlYW1UZXh0RmluaXNoUmVhc29uOiBGaW5pc2hSZWFzb24gfCB1bmRlZmluZWQ7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHN0cmVhbSA9IGNyZWF0ZVVJTWVzc2FnZVN0cmVhbSh7XG4gICAgICAgICAgZXhlY3V0ZTogYXN5bmMgKHsgd3JpdGVyIH0pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHsgcmF3VG9vbHMsIHRvb2xzV2l0aE5lZWRzQXBwcm92YWwsIHRvb2xDb250ZXh0IH0gPSBnZXRUb29scyh7XG4gICAgICAgICAgICAgIGFnZW50LFxuICAgICAgICAgICAgICBzYW5kYm94LFxuICAgICAgICAgICAgICBza2lsbHNSZWYsXG4gICAgICAgICAgICAgIHdyaXRlcixcbiAgICAgICAgICAgICAgYWJvcnRDb250cm9sbGVyLFxuICAgICAgICAgICAgICBuZXh0UGFydEluZGV4UmVmLFxuICAgICAgICAgICAgICBhc3Npc3RhbnRNZXNzYWdlSWQsXG4gICAgICAgICAgICAgIHNlc3Npb25JZCxcbiAgICAgICAgICAgICAgc3RlcExvZyxcbiAgICAgICAgICAgICAgY29udGV4dCxcbiAgICAgICAgICAgICAgc3RhdGUsXG4gICAgICAgICAgICAgIG1lc3NhZ2VzOiB1aU1lc3NhZ2VzLFxuICAgICAgICAgICAgICBhY3RpdmVUb29sczogcmVzb2x2ZWRBY3RpdmVUb29scyxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvLyBwcm9jZXNzIGFwcHJvdmFscyBvbmNlIChmaXJzdCBpdGVyYXRpb24gb25seSlcbiAgICAgICAgICAgIGlmIChpdGVyYXRpb24gPT09IDApIHtcbiAgICAgICAgICAgICAgYXdhaXQgcHJvY2Vzc0FwcHJvdmFscyh7XG4gICAgICAgICAgICAgICAgYWxsUGFydHMsXG4gICAgICAgICAgICAgICAgbWVzc2FnZXNSZXN1bHQsXG4gICAgICAgICAgICAgICAgY3JlYXRlZEF0LFxuICAgICAgICAgICAgICAgIHJhd1Rvb2xzLFxuICAgICAgICAgICAgICAgIGFib3J0Q29udHJvbGxlcixcbiAgICAgICAgICAgICAgICB0b29sQ29udGV4dCxcbiAgICAgICAgICAgICAgICBhZ2VudCxcbiAgICAgICAgICAgICAgICBzdGVwTG9nLFxuICAgICAgICAgICAgICAgIHRocm90dGxlZEVtaXRTdGF0dXMsXG4gICAgICAgICAgICAgICAgd3JpdGVyLFxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhyb3R0bGVkRW1pdFN0YXR1cyh7XG4gICAgICAgICAgICAgIHdyaXRlcixcbiAgICAgICAgICAgICAgc3RhdHVzOiB7IHR5cGU6IFwidGhpbmtpbmdcIiB9LFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGNvbnN0IGl0ZXJSZXN1bHQgPSBzdHJlYW1UZXh0QWkoe1xuICAgICAgICAgICAgICBtZXNzYWdlczogW3sgcm9sZTogXCJ1c2VyXCIgYXMgY29uc3QsIGNvbnRlbnQ6IFwiLlwiIH1dLFxuICAgICAgICAgICAgICB0b29sczogdG9vbHNXaXRoTmVlZHNBcHByb3ZhbCxcbiAgICAgICAgICAgICAgbW9kZWw6IHJlc29sdmVkTW9kZWwsXG4gICAgICAgICAgICAgIGFib3J0U2lnbmFsOiBhYm9ydENvbnRyb2xsZXIuc2lnbmFsLFxuICAgICAgICAgICAgICBzdG9wV2hlbjogc3RlcENvdW50SXMoMSksXG4gICAgICAgICAgICAgIHRlbXBlcmF0dXJlOiByZXNvbHZlZEdlbmVyYXRpb24/LnRlbXBlcmF0dXJlLFxuICAgICAgICAgICAgICB0b3BLOiByZXNvbHZlZEdlbmVyYXRpb24/LnRvcEssXG4gICAgICAgICAgICAgIHRvcFA6IHJlc29sdmVkR2VuZXJhdGlvbj8udG9wUCxcbiAgICAgICAgICAgICAgZnJlcXVlbmN5UGVuYWx0eTogcmVzb2x2ZWRHZW5lcmF0aW9uPy5mcmVxdWVuY3lQZW5hbHR5LFxuICAgICAgICAgICAgICBwcmVzZW5jZVBlbmFsdHk6IHJlc29sdmVkR2VuZXJhdGlvbj8ucHJlc2VuY2VQZW5hbHR5LFxuICAgICAgICAgICAgICBtYXhPdXRwdXRUb2tlbnM6IHJlc29sdmVkR2VuZXJhdGlvbj8ubWF4T3V0cHV0VG9rZW5zLFxuICAgICAgICAgICAgICBoZWFkZXJzOiByZXNvbHZlZEdlbmVyYXRpb24/LmhlYWRlcnMsXG4gICAgICAgICAgICAgIGV4cGVyaW1lbnRhbF9jb250ZXh0OiB7XG4gICAgICAgICAgICAgICAgY29udGV4dCxcbiAgICAgICAgICAgICAgICBzdGF0ZSxcbiAgICAgICAgICAgICAgICBzZXNzaW9uSWQsXG4gICAgICAgICAgICAgICAgc2FuZGJveCxcbiAgICAgICAgICAgICAgICBtZXNzYWdlczogdWlNZXNzYWdlcyxcbiAgICAgICAgICAgICAgfSBzYXRpc2ZpZXMgVG9vbENvbnRleHQsXG4gICAgICAgICAgICAgIHByZXBhcmVTdGVwOiBhc3luYyAoeyBtb2RlbCB9KSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc2tpbGxzQ29udGV4dCA9IGJ1aWxkU2tpbGxzQ29udGV4dChza2lsbHNSZWYuY3VycmVudCk7XG4gICAgICAgICAgICAgICAgY29uc3QgY3dkUHJvbXB0ID0gc2FuZGJveFJlY29yZD8uc2V0dXA/LmN3ZFxuICAgICAgICAgICAgICAgICAgPyBgWW91ciB3b3JraW5nIGRpcmVjdG9yeSBpcyAke3NhbmRib3hSZWNvcmQuc2V0dXAuY3dkfS4gQWxsIGZpbGUgcGF0aHMgc2hvdWxkIGJlIGFic29sdXRlLmBcbiAgICAgICAgICAgICAgICAgIDogXCJBbGwgZmlsZSBwYXRocyBtdXN0IGJlIGFic29sdXRlLlwiO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgcmVzb2x2ZWRTeXN0ZW0gPSBhd2FpdCByZXNvbHZlU3lzdGVtKFxuICAgICAgICAgICAgICAgICAgYWdlbnQub3B0aW9ucy5zeXN0ZW0sXG4gICAgICAgICAgICAgICAgICByZXNvbHZhYmxlQXJnc1xuICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBzeXN0ZW1IZWFkZXIgPSBqb2luUHJvbXB0U2VjdGlvbnMoXG4gICAgICAgICAgICAgICAgICBCQVNFX1NZU1RFTV9QUk9NUFQsXG4gICAgICAgICAgICAgICAgICBjd2RQcm9tcHQsXG4gICAgICAgICAgICAgICAgICByZXNvbHZlZFN5c3RlbVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3lzdGVtQ29udGV4dCA9IGpvaW5Qcm9tcHRTZWN0aW9ucyhcbiAgICAgICAgICAgICAgICAgIHNraWxsc0NvbnRleHQsXG4gICAgICAgICAgICAgICAgICBjd2RQcm9tcHRcbiAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgY29udmVydGVkTWVzc2FnZXMgPSBhd2FpdCBjb252ZXJ0VG9Nb2RlbE1lc3NhZ2VzKFxuICAgICAgICAgICAgICAgICAgdWlNZXNzYWdlcyxcbiAgICAgICAgICAgICAgICAgIHsgaWdub3JlSW5jb21wbGV0ZVRvb2xDYWxsczogdHJ1ZSB9XG4gICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IG1vZGVsTWVzc2FnZXMgPSBbXG4gICAgICAgICAgICAgICAgICAuLi4oc3lzdGVtSGVhZGVyLnRyaW0oKVxuICAgICAgICAgICAgICAgICAgICA/IFt7IHJvbGU6IFwic3lzdGVtXCIgYXMgY29uc3QsIGNvbnRlbnQ6IHN5c3RlbUhlYWRlciB9XVxuICAgICAgICAgICAgICAgICAgICA6IFtdKSxcbiAgICAgICAgICAgICAgICAgIC4uLihzeXN0ZW1Db250ZXh0LnRyaW0oKVxuICAgICAgICAgICAgICAgICAgICA/IFt7IHJvbGU6IFwic3lzdGVtXCIgYXMgY29uc3QsIGNvbnRlbnQ6IHN5c3RlbUNvbnRleHQgfV1cbiAgICAgICAgICAgICAgICAgICAgOiBbXSksXG4gICAgICAgICAgICAgICAgICAuLi5jb252ZXJ0ZWRNZXNzYWdlcyxcbiAgICAgICAgICAgICAgICBdO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgcHJvbXB0Q2FjaGluZyA9IGFwcGx5UHJvbXB0Q2FjaGluZ1RvTW9kZWxSZXF1ZXN0KHtcbiAgICAgICAgICAgICAgICAgIG1vZGVsOiB0eXBlb2YgbW9kZWwgPT09IFwic3RyaW5nXCIgPyBtb2RlbCA6IG1vZGVsLm1vZGVsSWQsXG4gICAgICAgICAgICAgICAgICBzZXNzaW9uSWQsXG4gICAgICAgICAgICAgICAgICBtZXNzYWdlczogbW9kZWxNZXNzYWdlcyxcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGxldCBhY3RpdmVUb29scyA9IHJlc29sdmVkQWN0aXZlVG9vbHMgPz8gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIGlmIChza2lsbHNSZWYuY3VycmVudC5sZW5ndGggPT09IDAgJiYgYWN0aXZlVG9vbHMpIHtcbiAgICAgICAgICAgICAgICAgIGFjdGl2ZVRvb2xzID0gYWN0aXZlVG9vbHMuZmlsdGVyKFxuICAgICAgICAgICAgICAgICAgICAodCkgPT4gdCAhPT0gKFwiU2tpbGxcIiBzYXRpc2ZpZXMgQnVpbHRJblRvb2xOYW1lKVxuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgbWVzc2FnZXM6IHByb21wdENhY2hpbmcubWVzc2FnZXMsXG4gICAgICAgICAgICAgICAgICBwcm92aWRlck9wdGlvbnM6IG1lcmdlUHJvdmlkZXJPcHRpb25zKHtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudDogcmVzb2x2ZWRHZW5lcmF0aW9uPy5wcm92aWRlck9wdGlvbnMsXG4gICAgICAgICAgICAgICAgICAgIHBhdGNoOiBwcm9tcHRDYWNoaW5nLnByb3ZpZGVyT3B0aW9ucyxcbiAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgYWN0aXZlVG9vbHMsXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgb25TdGVwRmluaXNoOiAoeyB1c2FnZSB9KSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHVzYWdlKSB7XG4gICAgICAgICAgICAgICAgICB1c2FnZVN0ZXBzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBzdGVwSW5kZXg6IHN0ZXBJbmRleE9mZnNldCArIGludGVybmFsU3RlcEluZGV4LFxuICAgICAgICAgICAgICAgICAgICBtb2RlbDogcmVzb2x2ZWRNb2RlbCA/PyBcInVua25vd25cIixcbiAgICAgICAgICAgICAgICAgICAgaW5wdXRUb2tlbnM6IHVzYWdlLmlucHV0VG9rZW5zID8/IDAsXG4gICAgICAgICAgICAgICAgICAgIG91dHB1dFRva2VuczogdXNhZ2Uub3V0cHV0VG9rZW5zID8/IDAsXG4gICAgICAgICAgICAgICAgICAgIHRvdGFsVG9rZW5zOiB1c2FnZS50b3RhbFRva2VucyA/PyAwLFxuICAgICAgICAgICAgICAgICAgICBjYWNoZVJlYWRUb2tlbnM6XG4gICAgICAgICAgICAgICAgICAgICAgdXNhZ2UuaW5wdXRUb2tlbkRldGFpbHM/LmNhY2hlUmVhZFRva2VucyA/PyAwLFxuICAgICAgICAgICAgICAgICAgICBjYWNoZVdyaXRlVG9rZW5zOlxuICAgICAgICAgICAgICAgICAgICAgIHVzYWdlLmlucHV0VG9rZW5EZXRhaWxzPy5jYWNoZVdyaXRlVG9rZW5zID8/IDAsXG4gICAgICAgICAgICAgICAgICAgIHJlYXNvbmluZ1Rva2VuczpcbiAgICAgICAgICAgICAgICAgICAgICB1c2FnZS5vdXRwdXRUb2tlbkRldGFpbHM/LnJlYXNvbmluZ1Rva2VucyA/PyAwLFxuICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGludGVybmFsU3RlcEluZGV4Kys7XG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgd3JpdGVyLm1lcmdlKFxuICAgICAgICAgICAgICBpdGVyUmVzdWx0LnRvVUlNZXNzYWdlU3RyZWFtKHtcbiAgICAgICAgICAgICAgICBnZW5lcmF0ZU1lc3NhZ2VJZDogKCkgPT4gYXNzaXN0YW50TWVzc2FnZUlkLFxuICAgICAgICAgICAgICAgIG9uRmluaXNoOiAoeyBtZXNzYWdlcyB9KSA9PiB7XG4gICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IG0gb2YgbWVzc2FnZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG0ucm9sZSA9PT0gXCJhc3Npc3RhbnRcIikge1xuICAgICAgICAgICAgICAgICAgICAgIHN0ZXBQYXJ0cy5wdXNoKC4uLm0ucGFydHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIHN0cmVhbVRleHRGaW5pc2hSZWFzb24gPSBhd2FpdCBpdGVyUmVzdWx0LmZpbmlzaFJlYXNvbjtcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcblxuICAgICAgICBhd2FpdCBzdHJlYW0ucGlwZVRvKHdyaXRhYmxlLCB7XG4gICAgICAgICAgcHJldmVudENsb3NlOiB0cnVlLFxuICAgICAgICAgIHByZXZlbnRBYm9ydDogdHJ1ZSxcbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgaWYgKGFib3J0Q29udHJvbGxlci5zaWduYWwuYWJvcnRlZCkge1xuICAgICAgICAgIHdhc0Fib3J0ZWQgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoYWJvcnRDb250cm9sbGVyLnNpZ25hbC5hYm9ydGVkKSB7XG4gICAgICAgIHdhc0Fib3J0ZWQgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBNYXJrIGludGVycnVwdGVkIHRvb2wgcGFydHNcbiAgICAgIGlmICh3YXNBYm9ydGVkKSB7XG4gICAgICAgIGNvbnN0IHRlcm1pbmFsU3RhdGVzID0gbmV3IFNldChbXG4gICAgICAgICAgXCJvdXRwdXQtYXZhaWxhYmxlXCIsXG4gICAgICAgICAgXCJvdXRwdXQtZXJyb3JcIixcbiAgICAgICAgICBcIm91dHB1dC1kZW5pZWRcIixcbiAgICAgICAgICBcImRvbmVcIixcbiAgICAgICAgXSk7XG4gICAgICAgIGZvciAoY29uc3QgcGFydCBvZiBzdGVwUGFydHMpIHtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBcInR5cGVcIiBpbiBwYXJ0ICYmXG4gICAgICAgICAgICB0eXBlb2YgcGFydC50eXBlID09PSBcInN0cmluZ1wiICYmXG4gICAgICAgICAgICBwYXJ0LnR5cGUuc3RhcnRzV2l0aChcInRvb2wtXCIpICYmXG4gICAgICAgICAgICBcInN0YXRlXCIgaW4gcGFydCAmJlxuICAgICAgICAgICAgIXRlcm1pbmFsU3RhdGVzLmhhcyhwYXJ0LnN0YXRlIGFzIHN0cmluZylcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIChwYXJ0IGFzIHsgc3RhdGU6IHN0cmluZyB9KS5zdGF0ZSA9IFwib3V0cHV0LWVycm9yXCI7XG4gICAgICAgICAgICAocGFydCBhcyB7IGVycm9yVGV4dD86IHN0cmluZyB9KS5lcnJvclRleHQgPSBcImludGVycnVwdGVkXCI7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIEhhbmRsZSBpbnRlcnJ1cHRlZCBsYXN0UGFydCB0cnVuY2F0aW9uXG4gICAgICBjb25zdCBsYXN0UGFydCA9IGludGVycnVwdGVkTGFzdFBhcnRSZWYuY3VycmVudDtcblxuICAgICAgY29uc3QgbmV3UGFydFJlY29yZHMgPSBzdGVwUGFydHNcbiAgICAgICAgLm1hcCgodWlQYXJ0LCBpKSA9PiB7XG4gICAgICAgICAgY29uc3QgaW5kZXggPSBuZXh0UGFydEluZGV4UmVmLmN1cnJlbnQgKyBpO1xuICAgICAgICAgIGlmIChsYXN0UGFydCAhPSBudWxsICYmIGluZGV4ID4gbGFzdFBhcnQuaW5kZXgpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCB1c2VDbGllbnRQYXJ0ID0gbGFzdFBhcnQgIT0gbnVsbCAmJiBpbmRleCA9PT0gbGFzdFBhcnQuaW5kZXg7XG4gICAgICAgICAgY29uc3QgY29udGVudCA9IChcbiAgICAgICAgICAgIHVzZUNsaWVudFBhcnQgPyBsYXN0UGFydC5wYXJ0IDogdWlQYXJ0XG4gICAgICAgICAgKSBhcyBUeXBlZFVJTWVzc2FnZTxUb29scz5bXCJwYXJ0c1wiXVtudW1iZXJdO1xuICAgICAgICAgIGNvbnN0IHBhcnRJZCA9XG4gICAgICAgICAgICBcImFwcHJvdmFsXCIgaW4gY29udGVudCAmJiBjb250ZW50LmFwcHJvdmFsPy5pZFxuICAgICAgICAgICAgICA/IGFwcHJvdmFsUGFydElkKGNvbnRlbnQuYXBwcm92YWwuaWQpXG4gICAgICAgICAgICAgIDogYHBhcnRfJHthc3Npc3RhbnRNZXNzYWdlSWR9XyR7aW5kZXh9YDtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgaWQ6IHBhcnRJZCxcbiAgICAgICAgICAgIGluZGV4LFxuICAgICAgICAgICAgbWVzc2FnZUlkOiBhc3Npc3RhbnRNZXNzYWdlSWQsXG4gICAgICAgICAgICBzZXNzaW9uSWQsXG4gICAgICAgICAgICBwYXJ0OiBjb250ZW50LFxuICAgICAgICAgIH07XG4gICAgICAgIH0pXG4gICAgICAgIC5maWx0ZXIoKHIpOiByIGlzIE5vbk51bGxhYmxlPHR5cGVvZiByPiA9PiByICE9PSBudWxsKTtcblxuICAgICAgY29uc3QgcGVyc2lzdFByb21pc2UgPSBQcm9taXNlLmFsbChbXG4gICAgICAgIC4uLm5ld1BhcnRSZWNvcmRzLm1hcCgocmVjb3JkKSA9PlxuICAgICAgICAgIGFnZW50LnN0b3JhZ2UucGFydC5zZXQocmVjb3JkLmlkLCByZWNvcmQpXG4gICAgICAgICksXG4gICAgICAgIGFnZW50LnN0b3JhZ2Uuc2Vzc2lvbi51cGRhdGUoc2Vzc2lvbklkLCB7IHN0YXRlIH0pLFxuICAgICAgXSk7XG5cbiAgICAgIG5leHRQYXJ0SW5kZXhSZWYuY3VycmVudCA9XG4gICAgICAgIGxhc3RQYXJ0ICE9IG51bGxcbiAgICAgICAgICA/IE1hdGgubWluKFxuICAgICAgICAgICAgICBuZXh0UGFydEluZGV4UmVmLmN1cnJlbnQgKyBzdGVwUGFydHMubGVuZ3RoLFxuICAgICAgICAgICAgICBsYXN0UGFydC5pbmRleCArIDFcbiAgICAgICAgICAgIClcbiAgICAgICAgICA6IG5leHRQYXJ0SW5kZXhSZWYuY3VycmVudCArIHN0ZXBQYXJ0cy5sZW5ndGg7XG5cbiAgICAgIGNvbnN0IGl0ZXJQZW5kaW5nQXBwcm92YWxzID0gc3RlcFBhcnRzXG4gICAgICAgIC5maWx0ZXIoXG4gICAgICAgICAgKHApOiBwIGlzIHR5cGVvZiBwICYgeyBhcHByb3ZhbDogeyBpZDogc3RyaW5nIH0gfSA9PlxuICAgICAgICAgICAgXCJzdGF0ZVwiIGluIHAgJiZcbiAgICAgICAgICAgIHAuc3RhdGUgPT09IFwiYXBwcm92YWwtcmVxdWVzdGVkXCIgJiZcbiAgICAgICAgICAgIFwiYXBwcm92YWxcIiBpbiBwICYmXG4gICAgICAgICAgICAhIShwIGFzIHsgYXBwcm92YWw/OiB7IGlkOiBzdHJpbmcgfSB9KS5hcHByb3ZhbD8uaWRcbiAgICAgICAgKVxuICAgICAgICAubWFwKChwKSA9PiAoe1xuICAgICAgICAgIGFwcHJvdmFsSWQ6IHAuYXBwcm92YWwuaWQsXG4gICAgICAgICAgdG9vbE5hbWU6XG4gICAgICAgICAgICBcInR5cGVcIiBpbiBwID8gU3RyaW5nKHAudHlwZSkucmVwbGFjZShcInRvb2wtXCIsIFwiXCIpIDogXCJ1bmtub3duXCIsXG4gICAgICAgIH0pKTtcblxuICAgICAgbG9vcEZpbmlzaFJlYXNvbiA9IHdhc0Fib3J0ZWRcbiAgICAgICAgPyAoXCJzdG9wXCIgYXMgRmluaXNoUmVhc29uKVxuICAgICAgICA6IChzdHJlYW1UZXh0RmluaXNoUmVhc29uID8/IChcInVua25vd25cIiBhcyBGaW5pc2hSZWFzb24pKTtcblxuICAgICAgLy8gRGVjaWRlIHdoZXRoZXIgdG8gYnJlYWsgb3IgY29udGludWVcbiAgICAgIGNvbnN0IHNob3VsZEJyZWFrID1cbiAgICAgICAgaXRlclBlbmRpbmdBcHByb3ZhbHMubGVuZ3RoID4gMCB8fFxuICAgICAgICBsb29wRmluaXNoUmVhc29uID09PSBcInN0b3BcIiB8fFxuICAgICAgICB3YXNBYm9ydGVkIHx8XG4gICAgICAgIGxhc3RQYXJ0ICE9IG51bGwgfHxcbiAgICAgICAgKGN1cnJlbnRNYXhTdGVwcyAhPSBudWxsICYmXG4gICAgICAgICAgc3RlcEluZGV4T2Zmc2V0ICsgdXNhZ2VTdGVwcy5sZW5ndGggPj0gY3VycmVudE1heFN0ZXBzKSB8fFxuICAgICAgICBpdGVyYXRpb24gPj0gc3RlcFRocm91Z2hwdXQgLSAxO1xuXG4gICAgICBpZiAoc2hvdWxkQnJlYWspIHtcbiAgICAgICAgYXdhaXQgcGVyc2lzdFByb21pc2U7XG4gICAgICAgIGFsbFBhcnRzLnB1c2goLi4ubmV3UGFydFJlY29yZHMpO1xuICAgICAgICBhbGxQZW5kaW5nQXBwcm92YWxzLnB1c2goLi4uaXRlclBlbmRpbmdBcHByb3ZhbHMpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgLy8gTm9uLWZpbmFsIGl0ZXJhdGlvbjogcGVyc2lzdCBwYXJ0cyBhbmQgcmVidWlsZCBtZXNzYWdlc1xuICAgICAgYXdhaXQgcGVyc2lzdFByb21pc2U7XG4gICAgICBhbGxQYXJ0cy5wdXNoKC4uLm5ld1BhcnRSZWNvcmRzKTtcbiAgICAgIHVpTWVzc2FnZXMgPSBhc3NlbWJsZVVJTWVzc2FnZXMoe1xuICAgICAgICBtZXNzYWdlczogbWVzc2FnZXNSZXN1bHQsXG4gICAgICAgIHBhcnRzOiBhbGxQYXJ0cyxcbiAgICAgICAgdW50aWw6IGNyZWF0ZWRBdCxcbiAgICAgICAgaW5jbHVkZVF1ZXVlZDogdHJ1ZSxcbiAgICAgICAgZXhjbHVkZVN1YlRvb2xQYXJ0czogdHJ1ZSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfSBmaW5hbGx5IHtcbiAgICBwb2xsQ29udHJvbGxlci5hYm9ydCgpO1xuICAgIHRocm90dGxlZEVtaXRTdGF0dXMuZGlzcG9zZSgpO1xuICB9XG5cbiAgaWYgKHNldFN0YXJ0ZWRQcm9taXNlKSB7XG4gICAgYXdhaXQgc2V0U3RhcnRlZFByb21pc2U7XG4gIH1cblxuICBkb25lU3RlcCh7XG4gICAgZmluaXNoUmVhc29uOiBsb29wRmluaXNoUmVhc29uLFxuICAgIHdhc0Fib3J0ZWQsXG4gICAgaXRlcmF0aW9uczogaW50ZXJuYWxTdGVwSW5kZXgsXG4gICAgcGVuZGluZ0FwcHJvdmFsczogYWxsUGVuZGluZ0FwcHJvdmFscy5sZW5ndGgsXG4gIH0pO1xuXG4gIHJldHVybiB7XG4gICAgZmluaXNoUmVhc29uOiBsb29wRmluaXNoUmVhc29uLFxuICAgIGxhc3RQYXJ0SW5kZXg6IG5leHRQYXJ0SW5kZXhSZWYuY3VycmVudCxcbiAgICB1c2FnZVN0ZXBzLFxuICAgIHBlbmRpbmdBcHByb3ZhbHM6IGFsbFBlbmRpbmdBcHByb3ZhbHMsXG4gICAgbWF4U3RlcHM6IGN1cnJlbnRNYXhTdGVwcyxcbiAgICBkaXNjb3ZlcmVkU2tpbGxzOiBza2lsbHNSZWYuY3VycmVudCxcbiAgICBjb250ZXh0LFxuICB9O1xufVxuXG4vKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiBTdGVwc1xuICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc3RyZWFtVGV4dFN0ZXA8VG9vbHMgZXh0ZW5kcyBUb29sU2V0PihcbiAgLi4uYXJnczogUGFyYW1ldGVyczx0eXBlb2Ygc3RyZWFtVGV4dDxUb29scz4+XG4pIHtcbiAgXCJ1c2Ugc3RlcFwiO1xuICByZXR1cm4gYXdhaXQgc3RyZWFtVGV4dCguLi5hcmdzKTtcbn1cblxuLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogVXRpbHNcbiAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuYXN5bmMgZnVuY3Rpb24gcHJvY2Vzc0FwcHJvdmFscyh7XG4gIGFsbFBhcnRzLFxuICBtZXNzYWdlc1Jlc3VsdCxcbiAgY3JlYXRlZEF0LFxuICByYXdUb29scyxcbiAgYWJvcnRDb250cm9sbGVyLFxuICB0b29sQ29udGV4dCxcbiAgYWdlbnQsXG4gIHN0ZXBMb2csXG4gIHRocm90dGxlZEVtaXRTdGF0dXMsXG4gIHdyaXRlcixcbn06IHtcbiAgYWxsUGFydHM6IFBhcnRbXTtcbiAgbWVzc2FnZXNSZXN1bHQ6IFBhcmFtZXRlcnM8dHlwZW9mIGFzc2VtYmxlVUlNZXNzYWdlcz5bMF1bXCJtZXNzYWdlc1wiXTtcbiAgY3JlYXRlZEF0OiBudW1iZXI7XG4gIHJhd1Rvb2xzOiBUb29sU2V0O1xuICBhYm9ydENvbnRyb2xsZXI6IEFib3J0Q29udHJvbGxlcjtcbiAgdG9vbENvbnRleHQ6IFRvb2xDb250ZXh0O1xuICBhZ2VudDogQW55QWdlbnQ7XG4gIHN0ZXBMb2c6IExvZ2dlcjtcbiAgdGhyb3R0bGVkRW1pdFN0YXR1czogUmV0dXJuVHlwZTx0eXBlb2YgY3JlYXRlVGhyb3R0bGVkRW1pdFN0YXR1cz47XG4gIHdyaXRlcjogU3RyZWFtV3JpdGVyO1xufSkge1xuICAvLyBFeGVjdXRlIGFwcHJvdmVkIHRvb2xzIHNvIHRoZSBtb2RlbCBzZWVzIGNvbXBsZXRlIHRvb2wgY2FsbCArIHJlc3VsdCBwYWlyc1xuICBjb25zdCBhcHByb3ZlZFBhcnRzID0gYWxsUGFydHMuZmlsdGVyKFxuICAgIChwKSA9PlxuICAgICAgcC5wYXJ0ICYmXG4gICAgICBcInN0YXRlXCIgaW4gcC5wYXJ0ICYmXG4gICAgICAocC5wYXJ0IGFzIHsgc3RhdGU6IHN0cmluZyB9KS5zdGF0ZSA9PT0gXCJhcHByb3ZhbC1yZXNwb25kZWRcIiAmJlxuICAgICAgXCJhcHByb3ZhbFwiIGluIHAucGFydCAmJlxuICAgICAgKHAucGFydCBhcyB7IGFwcHJvdmFsPzogeyBhcHByb3ZlZDogYm9vbGVhbiB9IH0pLmFwcHJvdmFsPy5hcHByb3ZlZCA9PT1cbiAgICAgICAgdHJ1ZVxuICApO1xuXG4gIGlmIChhcHByb3ZlZFBhcnRzLmxlbmd0aCA+IDApIHtcbiAgICBzdGVwTG9nLmluZm8oXCJleGVjdXRpbmcgYXBwcm92ZWQgdG9vbHNcIiwge1xuICAgICAgY291bnQ6IGFwcHJvdmVkUGFydHMubGVuZ3RoLFxuICAgIH0pO1xuICAgIHRocm90dGxlZEVtaXRTdGF0dXMoe1xuICAgICAgd3JpdGVyLFxuICAgICAgc3RhdHVzOiB7IHR5cGU6IFwicHJvY2Vzc2luZy1hcHByb3ZhbHNcIiB9LFxuICAgIH0pO1xuXG4gICAgY29uc3QgcHJlRXhlY01lc3NhZ2VzID0gYXdhaXQgY29udmVydFRvTW9kZWxNZXNzYWdlcyhcbiAgICAgIGFzc2VtYmxlVUlNZXNzYWdlcyh7XG4gICAgICAgIG1lc3NhZ2VzOiBtZXNzYWdlc1Jlc3VsdCxcbiAgICAgICAgcGFydHM6IGFsbFBhcnRzLFxuICAgICAgICB1bnRpbDogY3JlYXRlZEF0LFxuICAgICAgICBpbmNsdWRlUXVldWVkOiB0cnVlLFxuICAgICAgICBleGNsdWRlU3ViVG9vbFBhcnRzOiB0cnVlLFxuICAgICAgfSksXG4gICAgICB7IGlnbm9yZUluY29tcGxldGVUb29sQ2FsbHM6IHRydWUgfVxuICAgICk7XG5cbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIGFwcHJvdmVkUGFydHMubWFwKGFzeW5jIChhcCkgPT4ge1xuICAgICAgICBpZiAoIWFwLnBhcnQudHlwZS5zdGFydHNXaXRoKFwidG9vbC1cIikpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcGFydCA9IGFwLnBhcnQgYXMgRXh0cmFjdDxcbiAgICAgICAgICBVSU1lc3NhZ2VbXCJwYXJ0c1wiXVtudW1iZXJdLFxuICAgICAgICAgIHsgdHlwZTogYHRvb2wtJHtzdHJpbmd9YCB9XG4gICAgICAgID47XG4gICAgICAgIGNvbnN0IHRvb2xOYW1lID0gcGFydC50eXBlLnJlcGxhY2UoXCJ0b29sLVwiLCBcIlwiKTtcbiAgICAgICAgY29uc3QgdG9vbERlZiA9IHJhd1Rvb2xzW3Rvb2xOYW1lXTtcblxuICAgICAgICBpZiAodG9vbERlZj8uZXhlY3V0ZSAmJiBwYXJ0LmlucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgdG9vbE91dHB1dCA9IGF3YWl0IHRvb2xEZWYuZXhlY3V0ZShwYXJ0LmlucHV0LCB7XG4gICAgICAgICAgICAgIHRvb2xDYWxsSWQ6IHBhcnQudG9vbENhbGxJZCxcbiAgICAgICAgICAgICAgbWVzc2FnZXM6IHByZUV4ZWNNZXNzYWdlcyxcbiAgICAgICAgICAgICAgYWJvcnRTaWduYWw6IGFib3J0Q29udHJvbGxlci5zaWduYWwsXG4gICAgICAgICAgICAgIGV4cGVyaW1lbnRhbF9jb250ZXh0OiB0b29sQ29udGV4dCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcGFydC5zdGF0ZSA9IFwib3V0cHV0LWF2YWlsYWJsZVwiO1xuICAgICAgICAgICAgcGFydC5vdXRwdXQgPSB0b29sT3V0cHV0O1xuICAgICAgICAgICAgd3JpdGVyLndyaXRlKHtcbiAgICAgICAgICAgICAgdHlwZTogXCJ0b29sLW91dHB1dC1hdmFpbGFibGVcIixcbiAgICAgICAgICAgICAgdG9vbENhbGxJZDogcGFydC50b29sQ2FsbElkLFxuICAgICAgICAgICAgICBvdXRwdXQ6IHRvb2xPdXRwdXQsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIHBhcnQuc3RhdGUgPSBcIm91dHB1dC1lcnJvclwiO1xuICAgICAgICAgICAgcGFydC5lcnJvclRleHQgPSBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVycik7XG4gICAgICAgICAgICB3cml0ZXIud3JpdGUoe1xuICAgICAgICAgICAgICB0eXBlOiBcInRvb2wtb3V0cHV0LWVycm9yXCIsXG4gICAgICAgICAgICAgIHRvb2xDYWxsSWQ6IHBhcnQudG9vbENhbGxJZCxcbiAgICAgICAgICAgICAgZXJyb3JUZXh0OiBwYXJ0LmVycm9yVGV4dCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICBhd2FpdCBhZ2VudC5zdG9yYWdlLnBhcnQuc2V0KGFwLmlkLCB7IC4uLmFwLCBwYXJ0IH0pO1xuICAgICAgICB9XG4gICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvLyBBdXRvLWRlbnkgYW55IHJlbWFpbmluZyBhcHByb3ZhbC1yZXF1ZXN0ZWQgcGFydHMgc28gdGhlIG1vZGVsXG4gIC8vIHNlZXMgY29tcGxldGUgdG9vbCBjYWxsICsgZGVuaWVkIHJlc3VsdCBwYWlycyAobm90IG1pc3NpbmcgcmVzdWx0cykuXG4gIGNvbnN0IHBlbmRpbmdBcHByb3ZhbFBhcnRzID0gYWxsUGFydHMuZmlsdGVyKFxuICAgIChwKSA9PiAocC5wYXJ0IGFzIHsgc3RhdGU/OiBzdHJpbmcgfSkuc3RhdGUgPT09IFwiYXBwcm92YWwtcmVxdWVzdGVkXCJcbiAgKTtcbiAgaWYgKHBlbmRpbmdBcHByb3ZhbFBhcnRzLmxlbmd0aCA+IDApIHtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIHBlbmRpbmdBcHByb3ZhbFBhcnRzLm1hcChhc3luYyAocCkgPT4ge1xuICAgICAgICBjb25zdCBkZW5pZWQgPSB7XG4gICAgICAgICAgLi4ucCxcbiAgICAgICAgICBwYXJ0OiB7XG4gICAgICAgICAgICAuLi5wLnBhcnQsXG4gICAgICAgICAgICBzdGF0ZTogXCJvdXRwdXQtZGVuaWVkXCIsXG4gICAgICAgICAgICBhcHByb3ZhbDoge1xuICAgICAgICAgICAgICAuLi4oKHAucGFydCBhcyB7IGFwcHJvdmFsPzogb2JqZWN0IH0pLmFwcHJvdmFsID8/IHt9KSxcbiAgICAgICAgICAgICAgYXBwcm92ZWQ6IGZhbHNlLFxuICAgICAgICAgICAgICByZWFzb246IFwiYXV0by1kZW5pZWQ6IG5ldyBtZXNzYWdlIHNlbnRcIixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSBhcyB0eXBlb2YgcC5wYXJ0LFxuICAgICAgICB9O1xuICAgICAgICBPYmplY3QuYXNzaWduKHAsIGRlbmllZCk7XG4gICAgICAgIGF3YWl0IGFnZW50LnN0b3JhZ2UucGFydC5zZXQocC5pZCwgZGVuaWVkKTtcbiAgICAgIH0pXG4gICAgKTtcbiAgfVxufVxuXG50eXBlIFN0cmVhbVdyaXRlciA9IFVJTWVzc2FnZVN0cmVhbVdyaXRlcjtcblxuZnVuY3Rpb24gZW1pdFN0YXR1cyh7XG4gIHdyaXRlcixcbiAgc3RhdHVzLFxuICBhZ2VudCxcbn06IHtcbiAgd3JpdGVyOiBTdHJlYW1Xcml0ZXI7XG4gIHN0YXR1czogQWdlbnRTdGF0dXM7XG4gIGFnZW50OiBBbnlBZ2VudDtcbn0pIHtcbiAgd3JpdGVyLndyaXRlKHsgdHlwZTogXCJkYXRhLXN0YXR1c1wiLCBkYXRhOiBzdGF0dXMsIHRyYW5zaWVudDogdHJ1ZSB9KTtcbiAgYWdlbnQuaG9va3M/LnN0YXR1cz8uKHN0YXR1cyk7XG59XG5cbmNvbnN0IFNUQVRVU19USFJPVFRMRV9NUyA9IDUwMDtcblxuZnVuY3Rpb24gY3JlYXRlVGhyb3R0bGVkRW1pdFN0YXR1cyhhZ2VudDogQW55QWdlbnQpIHtcbiAgbGV0IHRpbWVyOiBSZXR1cm5UeXBlPHR5cGVvZiBzZXRUaW1lb3V0PiB8IG51bGwgPSBudWxsO1xuICBsZXQgcGVuZGluZzoge1xuICAgIHdyaXRlcjogU3RyZWFtV3JpdGVyO1xuICAgIHN0YXR1czogQWdlbnRTdGF0dXM7XG4gIH0gfCBudWxsID0gbnVsbDtcblxuICBmdW5jdGlvbiB0aHJvdHRsZWQoe1xuICAgIHdyaXRlcixcbiAgICBzdGF0dXMsXG4gIH06IHtcbiAgICB3cml0ZXI6IFN0cmVhbVdyaXRlcjtcbiAgICBzdGF0dXM6IEFnZW50U3RhdHVzO1xuICB9KSB7XG4gICAgcGVuZGluZyA9IHsgd3JpdGVyLCBzdGF0dXMgfTtcbiAgICBpZiAodGltZXIgIT09IG51bGwpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZmx1c2goKTtcbiAgICB0aW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGltZXIgPSBudWxsO1xuICAgICAgaWYgKHBlbmRpbmcpIHtcbiAgICAgICAgZmx1c2goKTtcbiAgICAgIH1cbiAgICB9LCBTVEFUVVNfVEhST1RUTEVfTVMpO1xuICB9XG5cbiAgZnVuY3Rpb24gZmx1c2goKSB7XG4gICAgaWYgKCFwZW5kaW5nKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHsgd3JpdGVyLCBzdGF0dXMgfSA9IHBlbmRpbmc7XG4gICAgcGVuZGluZyA9IG51bGw7XG4gICAgZW1pdFN0YXR1cyh7IHdyaXRlciwgc3RhdHVzLCBhZ2VudCB9KTtcbiAgfVxuXG4gIHRocm90dGxlZC5kaXNwb3NlID0gKCkgPT4ge1xuICAgIGlmICh0aW1lciAhPT0gbnVsbCkge1xuICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgIHRpbWVyID0gbnVsbDtcbiAgICB9XG4gICAgZmx1c2goKTtcbiAgfTtcblxuICByZXR1cm4gdGhyb3R0bGVkO1xufVxuXG5hc3luYyBmdW5jdGlvbiByZXNvbHZlT3B0aW9uPFQ+KFxuICB2YWx1ZTogUmVzb2x2YWJsZTxUPiB8IHVuZGVmaW5lZCxcbiAgYXJnczogUmVzb2x2YWJsZUFyZ3Ncbik6IFByb21pc2U8VCB8IHVuZGVmaW5lZD4ge1xuICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgcmV0dXJuIGF3YWl0ICh2YWx1ZSBhcyAoYXJnczogUmVzb2x2YWJsZUFyZ3MpID0+IFQgfCBQcm9taXNlPFQ+KShhcmdzKTtcbiAgfVxuICByZXR1cm4gdmFsdWU7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlc29sdmVTeXN0ZW0oXG4gIGlucHV0OiBSZXNvbHZhYmxlPHN0cmluZyB8IHN0cmluZ1tdIHwgdW5kZWZpbmVkPiB8IHVuZGVmaW5lZCxcbiAgYXJnczogUmVzb2x2YWJsZUFyZ3Ncbik6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xuICBjb25zdCByZXN1bHQgPSBhd2FpdCByZXNvbHZlT3B0aW9uKGlucHV0LCBhcmdzKTtcbiAgaWYgKCFyZXN1bHQpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICByZXR1cm4gQXJyYXkuaXNBcnJheShyZXN1bHQpID8gcmVzdWx0LmZpbHRlcihCb29sZWFuKS5qb2luKFwiXFxuXCIpIDogcmVzdWx0O1xufVxuXG5jb25zdCBCQVNFX1NZU1RFTV9QUk9NUFQgPVxuICBcIllvdSBhcmUgYW4gQUkgYXNzaXN0YW50IHdpdGggYmFzaWMgdG9vbHMgdG8gaW50ZXJhY3Qgd2l0aCB5b3VyIGVudmlyb25tZW50LiBFeHBsb3JlIGFuZCB3b3JrIGZyZWVseS5cIjtcblxuZnVuY3Rpb24gam9pblByb21wdFNlY3Rpb25zKFxuICAuLi5zZWN0aW9uczogKHN0cmluZyB8IHVuZGVmaW5lZCB8IG51bGwpW11cbik6IHN0cmluZyB7XG4gIHJldHVybiBzZWN0aW9ucy5maWx0ZXIoKHMpID0+IHM/LnRyaW0oKSkuam9pbihcIlxcblxcblwiKTtcbn1cblxuY29uc3QgYmFja2dyb3VuZFByb2Nlc3NQcm9tcHQgPSBgIyMgQmFja2dyb3VuZCBQcm9jZXNzZXNcblRoZXNlIGJhY2tncm91bmQgcHJvY2VzcyBpbnN0cnVjdGlvbnMgYXJlIGZvciB5b3UgdG8gbWFuaXB1bGF0ZSB0aGUgcHJvY2Vzc2VzLCBkbyBub3QgYmUgdG8gdmVyYm9zZSB0byB0aGUgdXNlciBhYm91dCB0aGUgcmVzcG9uc2UgZGV0YWlscyBsaWtlIFwiaG93IHRvIGRlYnVnIHRoZSBwcm9jZXNzIG91dHB1dFwiIHRoZSB1c2VyIHdpbGwgaGF2ZSBhbiBVSS5cblxuVXNlIFxcYHdhaXRVbnRpbDogMFxcYCBmb3IgZGV2IHNlcnZlcnMgdGhhdCBzaG91bGQgcnVuIGluZGVmaW5pdGVseS5cbkl0IGlzIGEgZ29vZCBwcmFjdGljZSB0byBjaGVjayB0aGUgb3V0cHV0IGxvZyBhZnRlciBydW5uaW5nIHByb2Nlc3NlcyBsaWtlIGRldiBzZXJ2ZXJzIHRvIG1ha2Ugc3VyZSB0aGV5IHN0YXJ0ZWQgY29ycmVjdGx5LlxuXG5UbyBydW4gYSBiYWNrZ3JvdW5kIHByb2Nlc3M6XG5CYXNoKHsgY29tbWFuZDogXCJucG0gcnVuIGRldlwiLCB3YWl0VW50aWw6IDAgfSlcblJldHVybnMgaW1tZWRpYXRlbHkgd2l0aCBcXGBjb21tYW5kSWRcXGAuIFRoZSBwcm9jZXNzIGtlZXBzIHJ1bm5pbmcgaW4gdGhlIHNhbmRib3guXG5cblRvIGtpbGwgYSBwcm9jZXNzOlxuQmFzaCh7IGNvbW1hbmQ6IFwicHMgYXV4IHwgZ3JlcCBub2RlXCIgfSkgICAvLyBGaW5kIHRoZSBQSURcbkJhc2goeyBjb21tYW5kOiBcImtpbGwge3BpZH1cIiB9KSAgICAgICAgICAgIC8vIEdyYWNlZnVsXG5CYXNoKHsgY29tbWFuZDogXCJraWxsIC05IHtwaWR9XCIgfSkgICAgICAgICAvLyBGb3JjZVxuYDtcblxuZnVuY3Rpb24gYnVpbGRTa2lsbHNDb250ZXh0KHNraWxsczogU2tpbGxTdW1tYXJ5W10pOiBzdHJpbmcge1xuICBpZiAoc2tpbGxzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBcIlwiO1xuICB9XG5cbiAgY29uc3Qgc2tpbGxMaW5lcyA9IHNraWxsc1xuICAgIC5tYXAoKHMpID0+IGAtICR7cy5uYW1lfTogJHtzLmRlc2NyaXB0aW9ufWApXG4gICAgLmpvaW4oXCJcXG5cIik7XG5cbiAgcmV0dXJuIGAjIyBBdmFpbGFibGUgU2tpbGxzXG4ke3NraWxsTGluZXN9XG5cbiR7YmFja2dyb3VuZFByb2Nlc3NQcm9tcHR9XG5cblVzZSB0aGUgU2tpbGwgdG9vbCB0byBsb2FkIGEgc2tpbGwncyBmdWxsIGluc3RydWN0aW9ucyBiZWZvcmUgZm9sbG93aW5nIGl0LmA7XG59XG4iLCAiaW1wb3J0IHR5cGUgeyBTa2lsbEVudHJ5LCBTa2lsbElucHV0IH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuLyoqXG4gKiBQYXJzZWQgZnJvbnRtYXR0ZXIgZnJvbSBhIFNLSUxMLm1kIGZpbGUuXG4gKi9cbmV4cG9ydCB0eXBlIFNraWxsRnJvbnRtYXR0ZXIgPSB7XG4gIG5hbWU6IHN0cmluZztcbiAgZGVzY3JpcHRpb246IHN0cmluZztcbn07XG5cbi8qKlxuICogUGFyc2VzIFlBTUwgZnJvbnRtYXR0ZXIgZnJvbSBhIFNLSUxMLm1kIGZpbGUgY29udGVudC5cbiAqIEZyb250bWF0dGVyIG11c3QgYmUgYXQgdGhlIHN0YXJ0IG9mIHRoZSBmaWxlLCBkZWxpbWl0ZWQgYnkgYC0tLWAgbWFya2Vycy5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgbWFya2Rvd25cbiAqIC0tLVxuICogbmFtZTogY3N2XG4gKiBkZXNjcmlwdGlvbjogQW5hbHl6ZSBDU1YgZGF0YVxuICogLS0tXG4gKiAjIENTViBTa2lsbFxuICogLi4uXG4gKiBgYGBcbiAqXG4gKiBAcmV0dXJucyBQYXJzZWQgbmFtZSBhbmQgZGVzY3JpcHRpb24sIG9yIG51bGwgaWYgZnJvbnRtYXR0ZXIgaXMgbWlzc2luZy9pbnZhbGlkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVNraWxsRnJvbnRtYXR0ZXIoXG4gIGNvbnRlbnQ6IHN0cmluZ1xuKTogU2tpbGxGcm9udG1hdHRlciB8IG51bGwge1xuICBjb25zdCB0cmltbWVkID0gY29udGVudC50cmltKCk7XG5cbiAgaWYgKCF0cmltbWVkLnN0YXJ0c1dpdGgoXCItLS1cIikpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IGVuZE1hcmtlckluZGV4ID0gdHJpbW1lZC5pbmRleE9mKFwiLS0tXCIsIDMpO1xuICBpZiAoZW5kTWFya2VySW5kZXggPT09IC0xKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCBmcm9udG1hdHRlckJsb2NrID0gdHJpbW1lZC5zbGljZSgzLCBlbmRNYXJrZXJJbmRleCkudHJpbSgpO1xuICBjb25zdCBwYXJzZWQgPSBwYXJzZVNpbXBsZVlhbWwoZnJvbnRtYXR0ZXJCbG9jayk7XG5cbiAgaWYgKCEocGFyc2VkLm5hbWUgJiYgcGFyc2VkLmRlc2NyaXB0aW9uKSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiBTdHJpbmcocGFyc2VkLm5hbWUpLFxuICAgIGRlc2NyaXB0aW9uOiBTdHJpbmcocGFyc2VkLmRlc2NyaXB0aW9uKSxcbiAgfTtcbn1cblxuLyoqXG4gKiBQYXJzZXMgc2ltcGxlIFlBTUwga2V5LXZhbHVlIHBhaXJzIChzaW5nbGUtbGluZSB2YWx1ZXMgb25seSkuXG4gKiBUaGlzIGF2b2lkcyBhZGRpbmcgYSBmdWxsIFlBTUwgcGFyc2VyIGRlcGVuZGVuY3kgZm9yIGJhc2ljIGZyb250bWF0dGVyLlxuICovXG5mdW5jdGlvbiBwYXJzZVNpbXBsZVlhbWwoeWFtbDogc3RyaW5nKTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB7XG4gIGNvbnN0IHJlc3VsdDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuXG4gIGZvciAoY29uc3QgbGluZSBvZiB5YW1sLnNwbGl0KFwiXFxuXCIpKSB7XG4gICAgY29uc3QgdHJpbW1lZExpbmUgPSBsaW5lLnRyaW0oKTtcbiAgICBpZiAoIXRyaW1tZWRMaW5lIHx8IHRyaW1tZWRMaW5lLnN0YXJ0c1dpdGgoXCIjXCIpKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBjb25zdCBjb2xvbkluZGV4ID0gdHJpbW1lZExpbmUuaW5kZXhPZihcIjpcIik7XG4gICAgaWYgKGNvbG9uSW5kZXggPT09IC0xKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBjb25zdCBrZXkgPSB0cmltbWVkTGluZS5zbGljZSgwLCBjb2xvbkluZGV4KS50cmltKCk7XG4gICAgbGV0IHZhbHVlID0gdHJpbW1lZExpbmUuc2xpY2UoY29sb25JbmRleCArIDEpLnRyaW0oKTtcblxuICAgIC8vIFJlbW92ZSBzdXJyb3VuZGluZyBxdW90ZXMgaWYgcHJlc2VudFxuICAgIGlmIChcbiAgICAgICh2YWx1ZS5zdGFydHNXaXRoKCdcIicpICYmIHZhbHVlLmVuZHNXaXRoKCdcIicpKSB8fFxuICAgICAgKHZhbHVlLnN0YXJ0c1dpdGgoXCInXCIpICYmIHZhbHVlLmVuZHNXaXRoKFwiJ1wiKSlcbiAgICApIHtcbiAgICAgIHZhbHVlID0gdmFsdWUuc2xpY2UoMSwgLTEpO1xuICAgIH1cblxuICAgIGlmIChrZXkpIHtcbiAgICAgIHJlc3VsdFtrZXldID0gdmFsdWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG5vcm1hbGl6ZVNraWxscyhcbiAgc2tpbGxzOiBTa2lsbElucHV0W10gfCBudWxsIHwgdW5kZWZpbmVkXG4pOiBTa2lsbEVudHJ5W10ge1xuICBpZiAoIXNraWxscyB8fCBza2lsbHMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgcmV0dXJuIHNraWxscy5tYXAoKHNraWxsKSA9PiB7XG4gICAgaWYgKHR5cGVvZiBza2lsbCAhPT0gXCJvYmplY3RcIiB8fCBza2lsbCA9PT0gbnVsbCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIkludmFsaWQgc2tpbGxzIGVudHJ5OiBleHBlY3RlZCBhbiBvYmplY3Qgd2l0aCBhIGB0eXBlYCBmaWVsZC5cIlxuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKFwidHlwZVwiIGluIHNraWxsICYmIHNraWxsLnR5cGUpIHtcbiAgICAgIHJldHVybiBza2lsbCBhcyBTa2lsbEVudHJ5O1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNraWxscyBlbnRyeTogZXhwZWN0ZWQgYHR5cGVgLlwiKTtcbiAgfSk7XG59XG4iLCAiaW1wb3J0IHR5cGUgeyBBbnlBZ2VudCB9IGZyb20gXCIuLi9hZ2VudC9jbGllbnRcIjtcbmltcG9ydCB0eXBlIHsgU2FuZGJveEluc3RhbmNlIH0gZnJvbSBcIi4uL3NhbmRib3gvYWRhcHRlclwiO1xuaW1wb3J0IHsgY3JlYXRlTG9nZ2VyLCB0eXBlIExvZ2dlciB9IGZyb20gXCIuLi91dGlscy9sb2dnZXJcIjtcbmltcG9ydCB7IHBhcnNlU2tpbGxGcm9udG1hdHRlciB9IGZyb20gXCIuL3BhcnNlclwiO1xuaW1wb3J0IHR5cGUgeyBTa2lsbFN1bW1hcnkgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG4vKipcbiAqIERpc2NvdmVycyBza2lsbHMgZnJvbSBkaXJlY3RvcmllcyBpbnNpZGUgdGhlIHNhbmRib3ggYnkgZmluZGluZyBhbmQgcGFyc2luZyBTS0lMTC5tZCBmaWxlcy5cbiAqIFNjYW5zIGVhY2ggZGlyZWN0b3J5IGZvciBzdWJkaXJlY3RvcmllcyBjb250YWluaW5nIFNLSUxMLm1kLCBleHRyYWN0cyBmcm9udG1hdHRlciBtZXRhZGF0YSxcbiAqIGFuZCByZXR1cm5zIHN1bW1hcmllcyBmb3IgdXNlIGluIHRoZSBzeXN0ZW0gcHJvbXB0LlxuICpcbiAqIEByZXR1cm5zIEFycmF5IG9mIHNraWxsIHN1bW1hcmllcyAoZGVkdXBsaWNhdGVkIGJ5IG5hbWUsIGZpcnN0IG9jY3VycmVuY2Ugd2lucylcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRpc2NvdmVyU2tpbGxzSW5TYW5kYm94KG9wdHM6IHtcbiAgYWdlbnQ6IEFueUFnZW50O1xuICBzYW5kYm94OiBTYW5kYm94SW5zdGFuY2U7XG4gIHNraWxsc0RpcnM6IHN0cmluZ1tdO1xuICBzZXNzaW9uSWQ/OiBzdHJpbmc7XG59KTogUHJvbWlzZTxTa2lsbFN1bW1hcnlbXT4ge1xuICBjb25zdCB7IGFnZW50LCBzYW5kYm94LCBza2lsbHNEaXJzLCBzZXNzaW9uSWQgfSA9IG9wdHM7XG4gIGNvbnN0IGJhc2VMb2cgPSBjcmVhdGVMb2dnZXIoe1xuICAgIGNvbmZpZzogeyAuLi5hZ2VudC5vcHRpb25zLmxvZ2dpbmcsIG5hbWU6IGFnZW50Lm5hbWUgfSxcbiAgICBzdWJzeXN0ZW06IFwic2tpbGxzXCIsXG4gIH0pO1xuICBjb25zdCBsb2cgPSBzZXNzaW9uSWQgPyBiYXNlTG9nLndpdGhDb250ZXh0KHsgc2Vzc2lvbklkIH0pIDogYmFzZUxvZztcbiAgY29uc3QgZG9uZSA9IGxvZy50aW1lKFwiZGlzY292ZXJTa2lsbHNJblNhbmRib3hcIik7XG5cbiAgY29uc3Qgc3VtbWFyaWVzOiBTa2lsbFN1bW1hcnlbXSA9IFtdO1xuICBjb25zdCBzZWVuTmFtZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcblxuICBmb3IgKGNvbnN0IHNraWxsc0RpciBvZiBza2lsbHNEaXJzKSB7XG4gICAgY29uc3QgZGlyRG9uZSA9IGxvZy50aW1lKFwic2NhbiBkaXJlY3RvcnlcIiwgeyBkaXI6IHNraWxsc0RpciB9KTtcbiAgICBjb25zdCBkaXJTdW1tYXJpZXMgPSBhd2FpdCBkaXNjb3ZlclNraWxsc0luRGlyZWN0b3J5KHtcbiAgICAgIHNhbmRib3gsXG4gICAgICBza2lsbHNEaXIsXG4gICAgICBsb2csXG4gICAgfSk7XG4gICAgZGlyRG9uZSh7IGNvdW50OiBkaXJTdW1tYXJpZXMubGVuZ3RoIH0pO1xuXG4gICAgZm9yIChjb25zdCBzdW1tYXJ5IG9mIGRpclN1bW1hcmllcykge1xuICAgICAgaWYgKCFzZWVuTmFtZXMuaGFzKHN1bW1hcnkubmFtZSkpIHtcbiAgICAgICAgc2Vlbk5hbWVzLmFkZChzdW1tYXJ5Lm5hbWUpO1xuICAgICAgICBzdW1tYXJpZXMucHVzaChzdW1tYXJ5KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBkb25lKHsgdG90YWxTa2lsbHM6IHN1bW1hcmllcy5sZW5ndGggfSk7XG5cbiAgcmV0dXJuIHN1bW1hcmllcztcbn1cblxuYXN5bmMgZnVuY3Rpb24gZGlzY292ZXJTa2lsbHNJbkRpcmVjdG9yeShvcHRzOiB7XG4gIHNhbmRib3g6IFNhbmRib3hJbnN0YW5jZTtcbiAgc2tpbGxzRGlyOiBzdHJpbmc7XG4gIGxvZzogTG9nZ2VyO1xufSk6IFByb21pc2U8U2tpbGxTdW1tYXJ5W10+IHtcbiAgY29uc3QgeyBzYW5kYm94LCBza2lsbHNEaXIsIGxvZyB9ID0gb3B0cztcbiAgY29uc3Qgc2tpbGxQYXRocyA9IGF3YWl0IGZpbmRTa2lsbEZpbGVzKHsgc2FuZGJveCwgc2tpbGxzRGlyLCBsb2cgfSk7XG5cbiAgaWYgKHNraWxsUGF0aHMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgY29uc3Qgc3VtbWFyaWVzOiBTa2lsbFN1bW1hcnlbXSA9IFtdO1xuXG4gIGZvciAoY29uc3Qgc2tpbGxNZFBhdGggb2Ygc2tpbGxQYXRocykge1xuICAgIGNvbnN0IHN1bW1hcnkgPSBhd2FpdCBwYXJzZVNraWxsRmlsZSh7IHNhbmRib3gsIHNraWxsTWRQYXRoLCBsb2cgfSk7XG4gICAgaWYgKHN1bW1hcnkpIHtcbiAgICAgIHN1bW1hcmllcy5wdXNoKHN1bW1hcnkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBzdW1tYXJpZXM7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGZpbmRTa2lsbEZpbGVzKG9wdHM6IHtcbiAgc2FuZGJveDogU2FuZGJveEluc3RhbmNlO1xuICBza2lsbHNEaXI6IHN0cmluZztcbiAgbG9nOiBMb2dnZXI7XG59KTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICBjb25zdCB7IHNhbmRib3gsIHNraWxsc0RpciwgbG9nIH0gPSBvcHRzO1xuXG4gIGNvbnN0IGV4ZWNSZXN1bHQgPSBhd2FpdCBzYW5kYm94LmV4ZWMoe1xuICAgIGNvbW1hbmQ6IFwiZmluZFwiLFxuICAgIGFyZ3M6IFtza2lsbHNEaXIsIFwiLW5hbWVcIiwgXCJTS0lMTC5tZFwiLCBcIi10eXBlXCIsIFwiZlwiXSxcbiAgfSk7XG5cbiAgaWYgKGV4ZWNSZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgIGxvZy53YXJuKFwiZmFpbGVkIHRvIHNjYW4gc2tpbGxzIGRpcmVjdG9yeVwiLCB7XG4gICAgICBkaXI6IHNraWxsc0RpcixcbiAgICAgIGVycm9yOiBleGVjUmVzdWx0Lm1lc3NhZ2UsXG4gICAgfSk7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgY29uc3QgeyBzdGRvdXQsIGV4aXRDb2RlIH0gPSBhd2FpdCBleGVjUmVzdWx0LnJlc3VsdDtcblxuICBpZiAoZXhpdENvZGUgIT09IDApIHtcbiAgICBsb2cud2FybihcInNraWxscyBkaXJlY3Rvcnkgbm90IGZvdW5kIG9yIGluYWNjZXNzaWJsZVwiLCB7IGRpcjogc2tpbGxzRGlyIH0pO1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIHJldHVybiBzdGRvdXRcbiAgICAudHJpbSgpXG4gICAgLnNwbGl0KFwiXFxuXCIpXG4gICAgLmZpbHRlcigocCkgPT4gcC5sZW5ndGggPiAwKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gcGFyc2VTa2lsbEZpbGUob3B0czoge1xuICBzYW5kYm94OiBTYW5kYm94SW5zdGFuY2U7XG4gIHNraWxsTWRQYXRoOiBzdHJpbmc7XG4gIGxvZzogTG9nZ2VyO1xufSk6IFByb21pc2U8U2tpbGxTdW1tYXJ5IHwgbnVsbD4ge1xuICBjb25zdCB7IHNhbmRib3gsIHNraWxsTWRQYXRoLCBsb2cgfSA9IG9wdHM7XG4gIGNvbnN0IGV4ZWNSZXN1bHQgPSBhd2FpdCBzYW5kYm94LmV4ZWMoe1xuICAgIGNvbW1hbmQ6IFwiY2F0XCIsXG4gICAgYXJnczogW3NraWxsTWRQYXRoXSxcbiAgfSk7XG5cbiAgaWYgKGV4ZWNSZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgIGxvZy53YXJuKFwiZmFpbGVkIHRvIHJlYWQgc2tpbGwgZmlsZVwiLCB7XG4gICAgICBwYXRoOiBza2lsbE1kUGF0aCxcbiAgICAgIGVycm9yOiBleGVjUmVzdWx0Lm1lc3NhZ2UsXG4gICAgfSk7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCB7IHN0ZG91dCwgZXhpdENvZGUgfSA9IGF3YWl0IGV4ZWNSZXN1bHQucmVzdWx0O1xuXG4gIGlmIChleGl0Q29kZSAhPT0gMCkge1xuICAgIGxvZy53YXJuKFwiY291bGQgbm90IHJlYWQgc2tpbGwgZmlsZVwiLCB7IHBhdGg6IHNraWxsTWRQYXRoIH0pO1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgcGFyc2VkID0gcGFyc2VTa2lsbEZyb250bWF0dGVyKHN0ZG91dCk7XG5cbiAgaWYgKCFwYXJzZWQpIHtcbiAgICBsb2cud2FybihcImludmFsaWQgb3IgbWlzc2luZyBmcm9udG1hdHRlclwiLCB7IHBhdGg6IHNraWxsTWRQYXRoIH0pO1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiBwYXJzZWQubmFtZSxcbiAgICBkZXNjcmlwdGlvbjogcGFyc2VkLmRlc2NyaXB0aW9uLFxuICAgIHNraWxsTWRQYXRoLFxuICB9O1xufVxuIiwgImltcG9ydCB0eXBlIHsgU2FuZGJveEluc3RhbmNlIH0gZnJvbSBcIi4uL3NhbmRib3gvYWRhcHRlclwiO1xuaW1wb3J0IHR5cGUgeyBIb3N0U2tpbGxJbnB1dCB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbmFzeW5jIGZ1bmN0aW9uIGNvbGxlY3RGaWxlcyhvcHRzOiB7XG4gIGFic29sdXRlUGF0aDogc3RyaW5nO1xuICByZWxhdGl2ZVByZWZpeD86IHN0cmluZztcbn0pOiBQcm9taXNlPHsgcGF0aDogc3RyaW5nOyBjb250ZW50OiBCdWZmZXIgfVtdPiB7XG4gIGNvbnN0IHsgcmVhZGRpciwgcmVhZEZpbGUsIHN0YXQgfSA9IGF3YWl0IGltcG9ydChcIm5vZGU6ZnMvcHJvbWlzZXNcIik7XG4gIGNvbnN0IHsgcmVzb2x2ZSwgcG9zaXg6IHBhdGhQb3NpeCB9ID0gYXdhaXQgaW1wb3J0KFwibm9kZTpwYXRoXCIpO1xuXG4gIGNvbnN0IGZpbGVTdGF0ID0gYXdhaXQgc3RhdChvcHRzLmFic29sdXRlUGF0aCk7XG4gIGlmIChmaWxlU3RhdC5pc0ZpbGUoKSkge1xuICAgIGNvbnN0IGNvbnRlbnQgPSBhd2FpdCByZWFkRmlsZShvcHRzLmFic29sdXRlUGF0aCk7XG4gICAgcmV0dXJuIFt7IHBhdGg6IG9wdHMucmVsYXRpdmVQcmVmaXggPz8gXCJTS0lMTC5tZFwiLCBjb250ZW50IH1dO1xuICB9XG5cbiAgaWYgKCFmaWxlU3RhdC5pc0RpcmVjdG9yeSgpKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgY29uc3QgZW50cmllcyA9IGF3YWl0IHJlYWRkaXIob3B0cy5hYnNvbHV0ZVBhdGgsIHsgd2l0aEZpbGVUeXBlczogdHJ1ZSB9KTtcbiAgY29uc3QgZmlsZXM6IHsgcGF0aDogc3RyaW5nOyBjb250ZW50OiBCdWZmZXIgfVtdID0gW107XG5cbiAgZm9yIChjb25zdCBlbnRyeSBvZiBlbnRyaWVzKSB7XG4gICAgY29uc3QgbmV4dEFicyA9IHJlc29sdmUob3B0cy5hYnNvbHV0ZVBhdGgsIGVudHJ5Lm5hbWUpO1xuICAgIGNvbnN0IG5leHRSZWwgPSBvcHRzLnJlbGF0aXZlUHJlZml4XG4gICAgICA/IHBhdGhQb3NpeC5qb2luKG9wdHMucmVsYXRpdmVQcmVmaXgsIGVudHJ5Lm5hbWUpXG4gICAgICA6IGVudHJ5Lm5hbWU7XG5cbiAgICBpZiAoZW50cnkuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgZmlsZXMucHVzaChcbiAgICAgICAgLi4uKGF3YWl0IGNvbGxlY3RGaWxlcyh7XG4gICAgICAgICAgYWJzb2x1dGVQYXRoOiBuZXh0QWJzLFxuICAgICAgICAgIHJlbGF0aXZlUHJlZml4OiBuZXh0UmVsLFxuICAgICAgICB9KSlcbiAgICAgICk7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBpZiAoZW50cnkuaXNGaWxlKCkpIHtcbiAgICAgIGZpbGVzLnB1c2goe1xuICAgICAgICBwYXRoOiBuZXh0UmVsLFxuICAgICAgICBjb250ZW50OiBhd2FpdCByZWFkRmlsZShuZXh0QWJzKSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmaWxlcztcbn1cblxuYXN5bmMgZnVuY3Rpb24gc3RhYmxlRGlyTmFtZShpbnB1dFBhdGg6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IHsgY3JlYXRlSGFzaCB9ID0gYXdhaXQgaW1wb3J0KFwibm9kZTpjcnlwdG9cIik7XG4gIGNvbnN0IGhhc2ggPSBjcmVhdGVIYXNoKFwic2hhMVwiKS51cGRhdGUoaW5wdXRQYXRoKS5kaWdlc3QoXCJoZXhcIikuc2xpY2UoMCwgMTApO1xuICByZXR1cm4gYGhvc3QtJHtoYXNofWA7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXNvbHZlSG9zdFNraWxsKG9wdHM6IHtcbiAgc2FuZGJveDogU2FuZGJveEluc3RhbmNlO1xuICBza2lsbDogSG9zdFNraWxsSW5wdXQ7XG59KTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3QgeyByZXNvbHZlLCBwb3NpeDogcGF0aFBvc2l4IH0gPSBhd2FpdCBpbXBvcnQoXCJub2RlOnBhdGhcIik7XG5cbiAgY29uc3QgaG9zdFBhdGggPSByZXNvbHZlKHByb2Nlc3MuY3dkKCksIG9wdHMuc2tpbGwucGF0aCk7XG4gIGNvbnN0IGZpbGVzID0gYXdhaXQgY29sbGVjdEZpbGVzKHsgYWJzb2x1dGVQYXRoOiBob3N0UGF0aCB9KTtcbiAgY29uc3QgZGlyTmFtZSA9IGF3YWl0IHN0YWJsZURpck5hbWUoaG9zdFBhdGgpO1xuICBjb25zdCBkZXN0UGF0aCA9IHBhdGhQb3NpeC5qb2luKFwiLmFnZW50XCIsIFwic2tpbGxzXCIsIFwiLm1hdGVyaWFsaXplZFwiLCBkaXJOYW1lKTtcblxuICBpZiAoZmlsZXMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIGRlc3RQYXRoO1xuICB9XG5cbiAgYXdhaXQgb3B0cy5zYW5kYm94LndyaXRlRmlsZXMoe1xuICAgIGZpbGVzLFxuICAgIGRlc3RQYXRoLFxuICB9KTtcblxuICByZXR1cm4gZGVzdFBhdGg7XG59XG4iLCAiaW1wb3J0IHR5cGUgeyBTYW5kYm94SW5zdGFuY2UgfSBmcm9tIFwiLi4vc2FuZGJveC9hZGFwdGVyXCI7XG5pbXBvcnQgdHlwZSB7IElubGluZVNraWxsSW5wdXQgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG5mdW5jdGlvbiBzbHVnaWZ5KHZhbHVlOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gdmFsdWVcbiAgICAudG9Mb3dlckNhc2UoKVxuICAgIC5yZXBsYWNlKC9bXmEtejAtOV0rL2csIFwiLVwiKVxuICAgIC5yZXBsYWNlKC8oXi18LSQpL2csIFwiXCIpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBzdGFibGVJbmxpbmVEaXJOYW1lKG5hbWU6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IHsgY3JlYXRlSGFzaCB9ID0gYXdhaXQgaW1wb3J0KFwibm9kZTpjcnlwdG9cIik7XG4gIGNvbnN0IHNsdWcgPSBzbHVnaWZ5KG5hbWUpIHx8IFwiaW5saW5lLXNraWxsXCI7XG4gIGNvbnN0IGhhc2ggPSBjcmVhdGVIYXNoKFwic2hhMVwiKS51cGRhdGUobmFtZSkuZGlnZXN0KFwiaGV4XCIpLnNsaWNlKDAsIDgpO1xuICByZXR1cm4gYCR7c2x1Z30tJHtoYXNofWA7XG59XG5cbmZ1bmN0aW9uIGJ1aWxkU2tpbGxNYXJrZG93bihza2lsbDogSW5saW5lU2tpbGxJbnB1dCk6IHN0cmluZyB7XG4gIHJldHVybiBgLS0tXG5uYW1lOiAke3NraWxsLm5hbWV9XG5kZXNjcmlwdGlvbjogJHtza2lsbC5kZXNjcmlwdGlvbn1cbi0tLVxuXG4ke3NraWxsLmluc3RydWN0aW9ucy50cmltKCl9XG5gO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZUlubGluZVNraWxsKG9wdHM6IHtcbiAgc2FuZGJveDogU2FuZGJveEluc3RhbmNlO1xuICBza2lsbDogSW5saW5lU2tpbGxJbnB1dDtcbn0pOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCB7IHBvc2l4OiBwYXRoUG9zaXggfSA9IGF3YWl0IGltcG9ydChcIm5vZGU6cGF0aFwiKTtcblxuICBjb25zdCBkaXJOYW1lID0gYXdhaXQgc3RhYmxlSW5saW5lRGlyTmFtZShvcHRzLnNraWxsLm5hbWUpO1xuICBjb25zdCBkZXN0UGF0aCA9IHBhdGhQb3NpeC5qb2luKFwiLmFnZW50XCIsIFwic2tpbGxzXCIsIFwiLm1hdGVyaWFsaXplZFwiLCBkaXJOYW1lKTtcblxuICBhd2FpdCBvcHRzLnNhbmRib3gud3JpdGVGaWxlcyh7XG4gICAgZGVzdFBhdGgsXG4gICAgZmlsZXM6IFtcbiAgICAgIHtcbiAgICAgICAgcGF0aDogXCJTS0lMTC5tZFwiLFxuICAgICAgICBjb250ZW50OiBidWlsZFNraWxsTWFya2Rvd24ob3B0cy5za2lsbCksXG4gICAgICB9LFxuICAgIF0sXG4gIH0pO1xuXG4gIHJldHVybiBkZXN0UGF0aDtcbn1cbiIsICJpbXBvcnQgdHlwZSB7IFNhbmRib3hJbnN0YW5jZSB9IGZyb20gXCIuLi9zYW5kYm94L2FkYXB0ZXJcIjtcbmltcG9ydCB0eXBlIHsgR2l0U2tpbGxJbnB1dCB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbmZ1bmN0aW9uIHNoZWxsUXVvdGUodmFsdWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgJyR7dmFsdWUucmVwbGFjZSgvJy9nLCBgJ1xcXFwnJ2ApfSdgO1xufVxuXG5hc3luYyBmdW5jdGlvbiBzdGFibGVSZXBvRGlyTmFtZShza2lsbDogR2l0U2tpbGxJbnB1dCk6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IHsgY3JlYXRlSGFzaCB9ID0gYXdhaXQgaW1wb3J0KFwibm9kZTpjcnlwdG9cIik7XG4gIGNvbnN0IGhhc2hJbnB1dCA9IGAke3NraWxsLnJlcG99Ojoke3NraWxsLnJlZiA/PyBcIkhFQURcIn1gO1xuICBjb25zdCBoYXNoID0gY3JlYXRlSGFzaChcInNoYTFcIikudXBkYXRlKGhhc2hJbnB1dCkuZGlnZXN0KFwiaGV4XCIpLnNsaWNlKDAsIDEyKTtcbiAgcmV0dXJuIGBnaXQtJHtoYXNofWA7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXNvbHZlUmVtb3RlU2tpbGwob3B0czoge1xuICBzYW5kYm94OiBTYW5kYm94SW5zdGFuY2U7XG4gIHNraWxsOiBHaXRTa2lsbElucHV0O1xufSk6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IHsgcG9zaXg6IHBhdGhQb3NpeCB9ID0gYXdhaXQgaW1wb3J0KFwibm9kZTpwYXRoXCIpO1xuXG4gIGNvbnN0IGRpck5hbWUgPSBhd2FpdCBzdGFibGVSZXBvRGlyTmFtZShvcHRzLnNraWxsKTtcbiAgY29uc3QgY2xvbmVEaXIgPSBwYXRoUG9zaXguam9pbihcIi5hZ2VudFwiLCBcInNraWxsc1wiLCBcIi5tYXRlcmlhbGl6ZWRcIiwgZGlyTmFtZSk7XG4gIGNvbnN0IHF1b3RlZERpciA9IHNoZWxsUXVvdGUoY2xvbmVEaXIpO1xuICBjb25zdCBxdW90ZWRSZXBvID0gc2hlbGxRdW90ZShvcHRzLnNraWxsLnJlcG8pO1xuICBjb25zdCBxdW90ZWRSZWYgPSBzaGVsbFF1b3RlKG9wdHMuc2tpbGwucmVmID8/IFwiSEVBRFwiKTtcblxuICBjb25zdCBzeW5jQ29tbWFuZCA9IFtcbiAgICBcInNldCAtZXVvIHBpcGVmYWlsXCIsXG4gICAgYGlmIFsgISAtZCAke3F1b3RlZERpcn0vLmdpdCBdOyB0aGVuYCxcbiAgICBgICBybSAtcmYgJHtxdW90ZWREaXJ9YCxcbiAgICBgICBta2RpciAtcCAke3F1b3RlZERpcn1gLFxuICAgIGAgIGdpdCBjbG9uZSAtLWRlcHRoIDEgJHtxdW90ZWRSZXBvfSAke3F1b3RlZERpcn1gLFxuICAgIFwiZmlcIixcbiAgICBgaWYgWyAke3F1b3RlZFJlZn0gIT0gJ0hFQUQnIF07IHRoZW5gLFxuICAgIGAgIGdpdCAtQyAke3F1b3RlZERpcn0gZmV0Y2ggLS1kZXB0aCAxIG9yaWdpbiAke3F1b3RlZFJlZn1gLFxuICAgIGAgIGdpdCAtQyAke3F1b3RlZERpcn0gY2hlY2tvdXQgRkVUQ0hfSEVBRGAsXG4gICAgXCJmaVwiLFxuICBdLmpvaW4oXCJcXG5cIik7XG5cbiAgY29uc3QgZXhlY1Jlc3VsdCA9IGF3YWl0IG9wdHMuc2FuZGJveC5leGVjKHtcbiAgICBjb21tYW5kOiBcImJhc2hcIixcbiAgICBhcmdzOiBbXCItbGNcIiwgc3luY0NvbW1hbmRdLFxuICB9KTtcbiAgY29uc3QgeyBleGl0Q29kZSwgc3RkZXJyIH0gPSBhd2FpdCBleGVjUmVzdWx0LnJlc3VsdDtcbiAgaWYgKGV4aXRDb2RlICE9PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYEZhaWxlZCB0byBtYXRlcmlhbGl6ZSBnaXQgc2tpbGwgZnJvbSAke29wdHMuc2tpbGwucmVwb306ICR7c3RkZXJyIHx8IFwidW5rbm93biBlcnJvclwifWBcbiAgICApO1xuICB9XG5cbiAgbGV0IHJlc29sdmVkRGlyID0gY2xvbmVEaXI7XG4gIGlmIChvcHRzLnNraWxsLnBhdGgpIHtcbiAgICByZXNvbHZlZERpciA9IHBhdGhQb3NpeC5qb2luKHJlc29sdmVkRGlyLCBvcHRzLnNraWxsLnBhdGgpO1xuICB9XG4gIGlmIChvcHRzLnNraWxsLm5hbWUpIHtcbiAgICByZXNvbHZlZERpciA9IHBhdGhQb3NpeC5qb2luKHJlc29sdmVkRGlyLCBvcHRzLnNraWxsLm5hbWUpO1xuICB9XG4gIHJldHVybiByZXNvbHZlZERpcjtcbn1cbiIsICJpbXBvcnQgdHlwZSB7IEFueUFnZW50IH0gZnJvbSBcIi4uL2FnZW50L2NsaWVudFwiO1xuaW1wb3J0IHR5cGUgeyBTYW5kYm94SW5zdGFuY2UgfSBmcm9tIFwiLi4vc2FuZGJveC9hZGFwdGVyXCI7XG5pbXBvcnQgeyBjcmVhdGVMb2dnZXIgfSBmcm9tIFwiLi4vdXRpbHMvbG9nZ2VyXCI7XG5pbXBvcnQgeyBub3JtYWxpemVTa2lsbHMgfSBmcm9tIFwiLi9wYXJzZXJcIjtcbmltcG9ydCB7IHJlc29sdmVIb3N0U2tpbGwgfSBmcm9tIFwiLi9yZXNvbHZlLWhvc3RcIjtcbmltcG9ydCB7IHJlc29sdmVJbmxpbmVTa2lsbCB9IGZyb20gXCIuL3Jlc29sdmUtaW5saW5lXCI7XG5pbXBvcnQgeyByZXNvbHZlUmVtb3RlU2tpbGwgfSBmcm9tIFwiLi9yZXNvbHZlLXJlbW90ZVwiO1xuaW1wb3J0IHR5cGUgeyBTa2lsbElucHV0IH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlc29sdmVTa2lsbElucHV0c1RvU2FuZGJveERpcnMob3B0czoge1xuICBhZ2VudDogQW55QWdlbnQ7XG4gIHNhbmRib3g6IFNhbmRib3hJbnN0YW5jZTtcbiAgc2tpbGxzOiBTa2lsbElucHV0W107XG4gIHNlc3Npb25JZD86IHN0cmluZztcbn0pOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gIGNvbnN0IGJhc2VMb2cgPSBjcmVhdGVMb2dnZXIoe1xuICAgIGNvbmZpZzogeyAuLi5vcHRzLmFnZW50Lm9wdGlvbnMubG9nZ2luZywgbmFtZTogb3B0cy5hZ2VudC5uYW1lIH0sXG4gICAgc3Vic3lzdGVtOiBcInNraWxsc1wiLFxuICB9KTtcbiAgY29uc3QgbG9nID0gb3B0cy5zZXNzaW9uSWRcbiAgICA/IGJhc2VMb2cud2l0aENvbnRleHQoeyBzZXNzaW9uSWQ6IG9wdHMuc2Vzc2lvbklkIH0pXG4gICAgOiBiYXNlTG9nO1xuICBjb25zdCBlbnRyaWVzID0gbm9ybWFsaXplU2tpbGxzKG9wdHMuc2tpbGxzKTtcbiAgY29uc3QgcmVzb2x2ZWQ6IHN0cmluZ1tdID0gW107XG5cbiAgZm9yIChjb25zdCBlbnRyeSBvZiBlbnRyaWVzKSB7XG4gICAgaWYgKGVudHJ5LnR5cGUgPT09IFwic2FuZGJveFwiKSB7XG4gICAgICByZXNvbHZlZC5wdXNoKGVudHJ5LnBhdGgpO1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGlmIChlbnRyeS50eXBlID09PSBcImhvc3RcIikge1xuICAgICAgcmVzb2x2ZWQucHVzaChcbiAgICAgICAgYXdhaXQgcmVzb2x2ZUhvc3RTa2lsbCh7XG4gICAgICAgICAgc2FuZGJveDogb3B0cy5zYW5kYm94LFxuICAgICAgICAgIHNraWxsOiBlbnRyeSxcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgaWYgKGVudHJ5LnR5cGUgPT09IFwiZ2l0XCIpIHtcbiAgICAgIHJlc29sdmVkLnB1c2goXG4gICAgICAgIGF3YWl0IHJlc29sdmVSZW1vdGVTa2lsbCh7XG4gICAgICAgICAgc2FuZGJveDogb3B0cy5zYW5kYm94LFxuICAgICAgICAgIHNraWxsOiBlbnRyeSxcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgaWYgKGVudHJ5LnR5cGUgPT09IFwiaW5saW5lXCIpIHtcbiAgICAgIHJlc29sdmVkLnB1c2goXG4gICAgICAgIGF3YWl0IHJlc29sdmVJbmxpbmVTa2lsbCh7XG4gICAgICAgICAgc2FuZGJveDogb3B0cy5zYW5kYm94LFxuICAgICAgICAgIHNraWxsOiBlbnRyeSxcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgbG9nLndhcm4oXCJ1bmtub3duIHNraWxsIHNvdXJjZSBlbnRyeSBlbmNvdW50ZXJlZFwiLCB7IGVudHJ5IH0pO1xuICB9XG5cbiAgcmV0dXJuIHJlc29sdmVkO1xufVxuIiwgImltcG9ydCB7XG4gIHR5cGUgVG9vbFNldCxcbiAgdG9vbCxcbiAgdHlwZSBVSU1lc3NhZ2UsXG4gIHR5cGUgVUlNZXNzYWdlU3RyZWFtV3JpdGVyLFxufSBmcm9tIFwiYWlcIjtcbmltcG9ydCB7IHVsaWQgfSBmcm9tIFwidWxpZFwiO1xuaW1wb3J0IHsgeiB9IGZyb20gXCJ6b2RcIjtcbmltcG9ydCB0eXBlIHsgQW55QWdlbnQgfSBmcm9tIFwiLi4vYWdlbnQvY2xpZW50XCI7XG5pbXBvcnQgdHlwZSB7IFNhbmRib3hJbnN0YW5jZSB9IGZyb20gXCIuLi9zYW5kYm94L2FkYXB0ZXJcIjtcbmltcG9ydCB7IERFRkFVTFRfV0FJVF9VTlRJTCB9IGZyb20gXCIuLi9zYW5kYm94L3Byb2Nlc3MtbWFuYWdlclwiO1xuaW1wb3J0IHsgYXBwcm92YWxQYXJ0SWQgfSBmcm9tIFwiLi4vc2Vzc2lvbi9zZW5kXCI7XG5pbXBvcnQgdHlwZSB7IFNraWxsU3VtbWFyeSB9IGZyb20gXCIuLi9za2lsbHMvdHlwZXNcIjtcbmltcG9ydCB7IGNyZWF0ZUxvZ2dlciwgdHlwZSBMb2dnZXIgfSBmcm9tIFwiLi4vdXRpbHMvbG9nZ2VyXCI7XG5pbXBvcnQgeyBjcmVhdGVKYXZhU2NyaXB0VG9vbCwgdHlwZSBPblN1YlRvb2xDYWxsIH0gZnJvbSBcIi4vamF2YXNjcmlwdFwiO1xuaW1wb3J0IHsgY2hlY2tOZWVkc0FwcHJvdmFsIH0gZnJvbSBcIi4vbmVlZHMtYXBwcm92YWxcIjtcblxuZXhwb3J0IHsgdG9vbCBhcyBhZ2VudFRvb2wgfSBmcm9tIFwiLi90b29sXCI7XG5cbmNvbnN0IGxvZyA9IGNyZWF0ZUxvZ2dlcih7IGNvbmZpZzogeyBuYW1lOiBcInRvb2xzXCIgfSwgc3Vic3lzdGVtOiBcInRvb2xzXCIgfSk7XG5cbmZ1bmN0aW9uIGZvcm1hdEZpbGVTaXplKGJ5dGVzOiBudW1iZXIpOiBzdHJpbmcge1xuICBpZiAoYnl0ZXMgPCAxMDI0KSB7XG4gICAgcmV0dXJuIGAke2J5dGVzfWA7XG4gIH1cbiAgaWYgKGJ5dGVzIDwgMTAyNCAqIDEwMjQpIHtcbiAgICByZXR1cm4gYCR7KGJ5dGVzIC8gMTAyNCkudG9GaXhlZCgxKX1LYDtcbiAgfVxuICBpZiAoYnl0ZXMgPCAxMDI0ICogMTAyNCAqIDEwMjQpIHtcbiAgICByZXR1cm4gYCR7KGJ5dGVzIC8gKDEwMjQgKiAxMDI0KSkudG9GaXhlZCgxKX1NYDtcbiAgfVxuICByZXR1cm4gYCR7KGJ5dGVzIC8gKDEwMjQgKiAxMDI0ICogMTAyNCkpLnRvRml4ZWQoMSl9R2A7XG59XG5cbnR5cGUgU3RyZWFtV3JpdGVyID0gVUlNZXNzYWdlU3RyZWFtV3JpdGVyO1xuXG5leHBvcnQgdHlwZSBUb29sQ29udGV4dDxcbiAgVENvbnRleHQgPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgVFN0YXRlID0gUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4+ID0ge1xuICBjb250ZXh0OiBUQ29udGV4dDtcbiAgc3RhdGU6IFRTdGF0ZTtcbiAgc2Vzc2lvbklkOiBzdHJpbmc7XG4gIHNhbmRib3g6IFNhbmRib3hJbnN0YW5jZTtcbiAgbWVzc2FnZXM6IFVJTWVzc2FnZVtdO1xufTtcblxuZnVuY3Rpb24gaXNSZ05vdEZvdW5kRXJyb3IoZXJyOiBFcnJvcik6IGJvb2xlYW4ge1xuICBjb25zdCBwYXJ0cyA9IFtlcnIubWVzc2FnZV07XG5cbiAgY29uc3QgYW55RXJyID0gZXJyIGFzIHVua25vd24gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIGlmICh0eXBlb2YgYW55RXJyLnJlYXNvbiA9PT0gXCJzdHJpbmdcIikge1xuICAgIHBhcnRzLnB1c2goYW55RXJyLnJlYXNvbik7XG4gIH1cbiAgaWYgKGFueUVyci5jYXVzZSBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgcGFydHMucHVzaChhbnlFcnIuY2F1c2UubWVzc2FnZSk7XG4gICAgY29uc3QgYW55Q2F1c2UgPSBhbnlFcnIuY2F1c2UgYXMgdW5rbm93biBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICBpZiAodHlwZW9mIGFueUNhdXNlLnRleHQgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgIHBhcnRzLnB1c2goYW55Q2F1c2UudGV4dCk7XG4gICAgfVxuICB9XG5cbiAgY29uc3QgbXNnID0gcGFydHMuam9pbihcIiBcIikudG9Mb3dlckNhc2UoKTtcbiAgcmV0dXJuIChcbiAgICBtc2cuaW5jbHVkZXMoXCJleGVjdXRhYmxlIGZpbGUgbm90IGZvdW5kXCIpIHx8XG4gICAgbXNnLmluY2x1ZGVzKFwiZXhlY3V0YWJsZV9ub3RfZm91bmRcIikgfHxcbiAgICAobXNnLmluY2x1ZGVzKFwiZW5vZW50XCIpICYmIG1zZy5pbmNsdWRlcyhcInJnXCIpKVxuICApO1xufVxuXG5leHBvcnQgY29uc3QgYnVpbHRJblRvb2xzID0ge1xuICBSZWFkOiB0b29sKHtcbiAgICBkZXNjcmlwdGlvbjpcbiAgICAgIFwiUmVhZHMgYSBmaWxlIGFuZCByZXR1cm5zIGl0cyBjb250ZW50cyB3aXRoIG1ldGFkYXRhLiBGb3IgZmlsZXMgb3ZlciAyMDAgbGluZXMsIGF1dG9tYXRpY2FsbHkgc2hvd3MgZmlyc3QgMTAwIGxpbmVzIHVubGVzcyBhIHNwZWNpZmljIGxpbmUgcmFuZ2UgaXMgcHJvdmlkZWQuIFVzZSBzdGFydExpbmUgYW5kIGVuZExpbmUgcGFyYW1ldGVycyB0byByZWFkIHNwZWNpZmljIHBvcnRpb25zIG9mIGxhcmdlIGZpbGVzLlwiLFxuICAgIGlucHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4gICAgICBsYWJlbDogelxuICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgLmRlc2NyaWJlKFwiQSBsYWJlbCB0aGF0IGRlc2NyaWJlcyB0aGUgYWN0aW9uIGJlaW5nIHBlcmZvcm1lZFwiKSxcbiAgICAgIHBhdGg6IHouc3RyaW5nKCkuZGVzY3JpYmUoXCJBYnNvbHV0ZSBwYXRoIHRvIHRoZSBmaWxlXCIpLFxuICAgICAgc3RhcnRMaW5lOiB6XG4gICAgICAgIC5udW1iZXIoKVxuICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgXCJTdGFydGluZyBsaW5lIG51bWJlciAoMS1pbmRleGVkKS4gSWYgcHJvdmlkZWQgd2l0aCBlbmRMaW5lLCByZWFkcyBleGFjdCByYW5nZSByZWdhcmRsZXNzIG9mIGZpbGUgc2l6ZS5cIlxuICAgICAgICApLFxuICAgICAgZW5kTGluZTogelxuICAgICAgICAubnVtYmVyKClcbiAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgLmRlc2NyaWJlKFxuICAgICAgICAgIFwiRW5kaW5nIGxpbmUgbnVtYmVyICgxLWluZGV4ZWQsIGluY2x1c2l2ZSkuIElmIHByb3ZpZGVkIHdpdGggc3RhcnRMaW5lLCByZWFkcyBleGFjdCByYW5nZSByZWdhcmRsZXNzIG9mIGZpbGUgc2l6ZS5cIlxuICAgICAgICApLFxuICAgIH0pLFxuICAgIG91dHB1dFNjaGVtYTogei5vYmplY3Qoe1xuICAgICAgY29udGVudDogei5zdHJpbmcoKS5kZXNjcmliZShcIkZpbGUgY29udGVudFwiKSxcbiAgICAgIG1ldGFkYXRhOiB6Lm9iamVjdCh7XG4gICAgICAgIHRvdGFsTGluZXM6IHoubnVtYmVyKCkuZGVzY3JpYmUoXCJUb3RhbCBudW1iZXIgb2YgbGluZXMgaW4gdGhlIGZpbGVcIiksXG4gICAgICAgIGxpbmVzU2hvd246IHpcbiAgICAgICAgICAubnVtYmVyKClcbiAgICAgICAgICAuZGVzY3JpYmUoXCJOdW1iZXIgb2YgbGluZXMgaW5jbHVkZWQgaW4gdGhpcyByZXNwb25zZVwiKSxcbiAgICAgICAgc3RhcnRMaW5lOiB6Lm51bWJlcigpLmRlc2NyaWJlKFwiRmlyc3QgbGluZSBudW1iZXIgc2hvd24gKDEtaW5kZXhlZClcIiksXG4gICAgICAgIGVuZExpbmU6IHoubnVtYmVyKCkuZGVzY3JpYmUoXCJMYXN0IGxpbmUgbnVtYmVyIHNob3duICgxLWluZGV4ZWQpXCIpLFxuICAgICAgICBpc1BhZ2luYXRlZDogelxuICAgICAgICAgIC5ib29sZWFuKClcbiAgICAgICAgICAuZGVzY3JpYmUoXCJXaGV0aGVyIHRoaXMgaXMgYSBwYXJ0aWFsIHZpZXcgb2YgdGhlIGZpbGVcIiksXG4gICAgICAgIGZpbGVTaXplOiB6XG4gICAgICAgICAgLnN0cmluZygpXG4gICAgICAgICAgLmRlc2NyaWJlKFwiSHVtYW4tcmVhZGFibGUgZmlsZSBzaXplIChlLmcuLCAnMi41SycsICcxLjJNJylcIiksXG4gICAgICAgIHBhdGg6IHouc3RyaW5nKCkuZGVzY3JpYmUoXCJBYnNvbHV0ZSBwYXRoIHRvIHRoZSBmaWxlXCIpLFxuICAgICAgfSksXG4gICAgfSksXG4gIH0pLFxuICBHcmVwOiB0b29sKHtcbiAgICBkZXNjcmlwdGlvbjpcbiAgICAgIFwiU2VhcmNoIGZvciBwYXR0ZXJucyBpbiBmaWxlcyB1c2luZyByaXBncmVwLiBVc2UgdGhpcyB0byBmaW5kIGNvZGUgcGF0dGVybnMsIGZ1bmN0aW9uIGRlZmluaXRpb25zLCBpbXBvcnRzLCBldGMuXCIsXG4gICAgaW5wdXRTY2hlbWE6IHoub2JqZWN0KHtcbiAgICAgIGxhYmVsOiB6XG4gICAgICAgIC5zdHJpbmcoKVxuICAgICAgICAuZGVzY3JpYmUoXCJBIGxhYmVsIHRoYXQgZGVzY3JpYmVzIHRoZSBhY3Rpb24gYmVpbmcgcGVyZm9ybWVkXCIpLFxuICAgICAgcGF0dGVybjogelxuICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgLmRlc2NyaWJlKFwiUmVnZXggcGF0dGVybiB0byBzZWFyY2ggZm9yIChyaXBncmVwIHN5bnRheClcIiksXG4gICAgICBwYXRoOiB6XG4gICAgICAgIC5zdHJpbmcoKVxuICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgXCJBYnNvbHV0ZSBwYXRoIHRvIHNlYXJjaCBpbiAoZGVmYXVsdHMgdG8gd29ya2luZyBkaXJlY3RvcnkpLiBDYW4gYmUgYSBmaWxlIG9yIGRpcmVjdG9yeS5cIlxuICAgICAgICApLFxuICAgICAgZmlsZVR5cGU6IHpcbiAgICAgICAgLnN0cmluZygpXG4gICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgIC5kZXNjcmliZShcbiAgICAgICAgICBcIkZpbGUgdHlwZSB0byBmaWx0ZXIgYnkgKGUuZy4sICd0cycsICdqcycsICdweScsICdtZCcpLiBVc2VzIHJpcGdyZXAncyBidWlsdC1pbiB0eXBlIGZpbHRlcnMuXCJcbiAgICAgICAgKSxcbiAgICAgIGdsb2I6IHpcbiAgICAgICAgLnN0cmluZygpXG4gICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgIC5kZXNjcmliZShcbiAgICAgICAgICBcIkdsb2IgcGF0dGVybiB0byBmaWx0ZXIgZmlsZXMgKGUuZy4sICcqLnRzeCcsICdzcmMvKiovKi50cycpXCJcbiAgICAgICAgKSxcbiAgICAgIGNhc2VTZW5zaXRpdmU6IHpcbiAgICAgICAgLmJvb2xlYW4oKVxuICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAuZGVmYXVsdCh0cnVlKVxuICAgICAgICAuZGVzY3JpYmUoXCJXaGV0aGVyIHNlYXJjaCBpcyBjYXNlLXNlbnNpdGl2ZSAoZGVmYXVsdDogdHJ1ZSlcIiksXG4gICAgICBjb250ZXh0TGluZXM6IHpcbiAgICAgICAgLm51bWJlcigpXG4gICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgIC5kZXNjcmliZShcbiAgICAgICAgICBcIk51bWJlciBvZiBjb250ZXh0IGxpbmVzIHRvIHNob3cgYmVmb3JlIGFuZCBhZnRlciBlYWNoIG1hdGNoXCJcbiAgICAgICAgKSxcbiAgICAgIG1heENvdW50OiB6XG4gICAgICAgIC5udW1iZXIoKVxuICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgXCJNYXhpbXVtIG51bWJlciBvZiBtYXRjaGVzIHBlciBmaWxlICh1c2VmdWwgZm9yIGxpbWl0aW5nIG91dHB1dClcIlxuICAgICAgICApLFxuICAgICAgZmlsZXNXaXRoTWF0Y2hlczogelxuICAgICAgICAuYm9vbGVhbigpXG4gICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgIC5kZWZhdWx0KGZhbHNlKVxuICAgICAgICAuZGVzY3JpYmUoXG4gICAgICAgICAgXCJPbmx5IHNob3cgZmlsZSBwYXRocyB0aGF0IGNvbnRhaW4gbWF0Y2hlcywgbm90IHRoZSBtYXRjaGluZyBsaW5lcyB0aGVtc2VsdmVzXCJcbiAgICAgICAgKSxcbiAgICB9KSxcbiAgICBvdXRwdXRTY2hlbWE6IHoub2JqZWN0KHtcbiAgICAgIG1hdGNoZXM6IHpcbiAgICAgICAgLnN0cmluZygpXG4gICAgICAgIC5kZXNjcmliZShcbiAgICAgICAgICBcIlNlYXJjaCByZXN1bHRzIHdpdGggZmlsZSBwYXRocywgbGluZSBudW1iZXJzLCBhbmQgbWF0Y2hpbmcgY29udGVudFwiXG4gICAgICAgICksXG4gICAgICBzdW1tYXJ5OiB6Lm9iamVjdCh7XG4gICAgICAgIG1hdGNoQ291bnQ6IHoubnVtYmVyKCkuZGVzY3JpYmUoXCJOdW1iZXIgb2YgbWF0Y2hlcyBmb3VuZFwiKSxcbiAgICAgICAgZmlsZUNvdW50OiB6Lm51bWJlcigpLmRlc2NyaWJlKFwiTnVtYmVyIG9mIGZpbGVzIGNvbnRhaW5pbmcgbWF0Y2hlc1wiKSxcbiAgICAgICAgc2VhcmNoUGF0aDogei5zdHJpbmcoKS5kZXNjcmliZShcIlBhdGggdGhhdCB3YXMgc2VhcmNoZWRcIiksXG4gICAgICAgIHBhdHRlcm46IHouc3RyaW5nKCkuZGVzY3JpYmUoXCJQYXR0ZXJuIHRoYXQgd2FzIHNlYXJjaGVkIGZvclwiKSxcbiAgICAgIH0pLFxuICAgIH0pLFxuICB9KSxcbiAgTGlzdDogdG9vbCh7XG4gICAgZGVzY3JpcHRpb246XG4gICAgICBcIlJlY3Vyc2l2ZWx5IGxpc3QgZGlyZWN0b3J5IGNvbnRlbnRzLiBVc2UgdGhpcyB0byB1bmRlcnN0YW5kIHRoZSBjb2RlYmFzZSBzdHJ1Y3R1cmUsIGZpbmQgZmlsZXMsIG9yIGV4cGxvcmUgZGlyZWN0b3JpZXMuIENvbnRyb2wgZGVwdGggdG8gYmFsYW5jZSBkZXRhaWwgdnMuIG92ZXJ2aWV3LiBEZXB0aCAxIHNob3dzIGltbWVkaWF0ZSBjaGlsZHJlbiwgZGVwdGggMiBpbmNsdWRlcyBzdWJkaXJlY3RvcmllcywgZXRjLlwiLFxuICAgIGlucHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4gICAgICBsYWJlbDogelxuICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgLmRlc2NyaWJlKFwiQSBsYWJlbCB0aGF0IGRlc2NyaWJlcyB0aGUgYWN0aW9uIGJlaW5nIHBlcmZvcm1lZFwiKSxcbiAgICAgIHBhdGg6IHpcbiAgICAgICAgLnN0cmluZygpXG4gICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgIC5kZXNjcmliZShcIkFic29sdXRlIHBhdGggdG8gbGlzdCAoZGVmYXVsdHMgdG8gd29ya2luZyBkaXJlY3RvcnkpXCIpLFxuICAgICAgZGVwdGg6IHpcbiAgICAgICAgLm51bWJlcigpXG4gICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgIC5kZXNjcmliZShcbiAgICAgICAgICBcIk1heGltdW0gZGVwdGggdG8gdHJhdmVyc2UuIENob29zZSBiYXNlZCBvbiBjb250ZXh0OiAxLTIgZm9yIHF1aWNrIG92ZXJ2aWV3LCAzLTQgZm9yIGRldGFpbGVkIGV4cGxvcmF0aW9uLCA1KyBmb3IgY29tcHJlaGVuc2l2ZSBtYXBwaW5nXCJcbiAgICAgICAgKSxcbiAgICAgIGluY2x1ZGVIaWRkZW46IHpcbiAgICAgICAgLmJvb2xlYW4oKVxuICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAuZGVmYXVsdChmYWxzZSlcbiAgICAgICAgLmRlc2NyaWJlKFxuICAgICAgICAgIFwiSW5jbHVkZSBoaWRkZW4gZmlsZXMgYW5kIGRpcmVjdG9yaWVzICh0aG9zZSBzdGFydGluZyB3aXRoICcuJylcIlxuICAgICAgICApLFxuICAgICAgZmlsZXNPbmx5OiB6XG4gICAgICAgIC5ib29sZWFuKClcbiAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgLmRlZmF1bHQoZmFsc2UpXG4gICAgICAgIC5kZXNjcmliZShcIk9ubHkgc2hvdyBmaWxlcywgbm90IGRpcmVjdG9yaWVzXCIpLFxuICAgICAgcGF0dGVybjogelxuICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgLmRlc2NyaWJlKFwiR2xvYiBwYXR0ZXJuIHRvIGZpbHRlciByZXN1bHRzIChlLmcuLCAnKi50cycsICcqdGVzdConKVwiKSxcbiAgICB9KSxcbiAgICBvdXRwdXRTY2hlbWE6IHoub2JqZWN0KHtcbiAgICAgIGxpc3Rpbmc6IHpcbiAgICAgICAgLnN0cmluZygpXG4gICAgICAgIC5kZXNjcmliZShcbiAgICAgICAgICBcIkRpcmVjdG9yeSB0cmVlIGxpc3Rpbmcgc2hvd2luZyBwYXRocyByZWxhdGl2ZSB0byBzZWFyY2ggcm9vdFwiXG4gICAgICAgICksXG4gICAgICBzdW1tYXJ5OiB6Lm9iamVjdCh7XG4gICAgICAgIHRvdGFsSXRlbXM6IHoubnVtYmVyKCkuZGVzY3JpYmUoXCJUb3RhbCBudW1iZXIgb2YgaXRlbXMgZm91bmRcIiksXG4gICAgICAgIHRvdGFsRmlsZXM6IHoubnVtYmVyKCkuZGVzY3JpYmUoXCJUb3RhbCBudW1iZXIgb2YgZmlsZXMgZm91bmRcIiksXG4gICAgICAgIHRvdGFsRGlyczogei5udW1iZXIoKS5kZXNjcmliZShcIlRvdGFsIG51bWJlciBvZiBkaXJlY3RvcmllcyBmb3VuZFwiKSxcbiAgICAgICAgc2VhcmNoUGF0aDogei5zdHJpbmcoKS5kZXNjcmliZShcIlBhdGggdGhhdCB3YXMgbGlzdGVkXCIpLFxuICAgICAgICBkZXB0aDogelxuICAgICAgICAgIC5udW1iZXIoKVxuICAgICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgICAgLmRlc2NyaWJlKFwiTWF4aW11bSBkZXB0aCB1c2VkIChpZiBzcGVjaWZpZWQpXCIpLFxuICAgICAgfSksXG4gICAgfSksXG4gIH0pLFxuICBXcml0ZTogdG9vbCh7XG4gICAgZGVzY3JpcHRpb246XG4gICAgICBcIldyaXRlIGNvbnRlbnQgdG8gYSBmaWxlLiBDcmVhdGVzIHBhcmVudCBkaXJlY3RvcmllcyBhdXRvbWF0aWNhbGx5LiBPdmVyd3JpdGVzIGV4aXN0aW5nIGZpbGVzLlwiLFxuICAgIGlucHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4gICAgICBsYWJlbDogelxuICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgLmRlc2NyaWJlKFwiQSBsYWJlbCB0aGF0IGRlc2NyaWJlcyB0aGUgYWN0aW9uIGJlaW5nIHBlcmZvcm1lZFwiKSxcbiAgICAgIHBhdGg6IHouc3RyaW5nKCkuZGVzY3JpYmUoXCJBYnNvbHV0ZSBwYXRoIHRvIHRoZSBmaWxlXCIpLFxuICAgICAgY29udGVudDogei5zdHJpbmcoKS5kZXNjcmliZShcIkNvbnRlbnQgdG8gd3JpdGUgdG8gdGhlIGZpbGVcIiksXG4gICAgfSksXG4gICAgb3V0cHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4gICAgICBzdWNjZXNzOiB6LmJvb2xlYW4oKS5kZXNjcmliZShcIldoZXRoZXIgdGhlIHdyaXRlIHN1Y2NlZWRlZFwiKSxcbiAgICAgIHBhdGg6IHouc3RyaW5nKCkuZGVzY3JpYmUoXCJQYXRoIHRvIHRoZSB3cml0dGVuIGZpbGVcIiksXG4gICAgICBieXRlc1dyaXR0ZW46IHoubnVtYmVyKCkuZGVzY3JpYmUoXCJOdW1iZXIgb2YgYnl0ZXMgd3JpdHRlblwiKSxcbiAgICAgIGVycm9yOiB6LnN0cmluZygpLm9wdGlvbmFsKCkuZGVzY3JpYmUoXCJFcnJvciBtZXNzYWdlIGlmIHdyaXRlIGZhaWxlZFwiKSxcbiAgICB9KSxcbiAgfSksXG4gIEVkaXQ6IHRvb2woe1xuICAgIGRlc2NyaXB0aW9uOlxuICAgICAgXCJFZGl0IGEgZmlsZSBieSByZXBsYWNpbmcgYW4gZXhhY3Qgc3RyaW5nLiBGYWlscyBpZiBvbGRfc3RyaW5nIGlzIG5vdCBmb3VuZCBvciBhcHBlYXJzIG11bHRpcGxlIHRpbWVzIChub3QgdW5pcXVlKS4gRm9yIG11bHRpcGxlIHJlcGxhY2VtZW50cywgY2FsbCB0aGlzIHRvb2wgbXVsdGlwbGUgdGltZXMgd2l0aCB1bmlxdWUgY29udGV4dC5cIixcbiAgICBpbnB1dFNjaGVtYTogei5vYmplY3Qoe1xuICAgICAgbGFiZWw6IHpcbiAgICAgICAgLnN0cmluZygpXG4gICAgICAgIC5kZXNjcmliZShcIkEgbGFiZWwgdGhhdCBkZXNjcmliZXMgdGhlIGFjdGlvbiBiZWluZyBwZXJmb3JtZWRcIiksXG4gICAgICBwYXRoOiB6LnN0cmluZygpLmRlc2NyaWJlKFwiQWJzb2x1dGUgcGF0aCB0byB0aGUgZmlsZVwiKSxcbiAgICAgIG9sZF9zdHJpbmc6IHpcbiAgICAgICAgLnN0cmluZygpXG4gICAgICAgIC5kZXNjcmliZShcIkV4YWN0IHN0cmluZyB0byBmaW5kIGFuZCByZXBsYWNlIChtdXN0IGJlIHVuaXF1ZSBpbiBmaWxlKVwiKSxcbiAgICAgIG5ld19zdHJpbmc6IHouc3RyaW5nKCkuZGVzY3JpYmUoXCJTdHJpbmcgdG8gcmVwbGFjZSBvbGRfc3RyaW5nIHdpdGhcIiksXG4gICAgfSksXG4gICAgb3V0cHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4gICAgICBzdWNjZXNzOiB6LmJvb2xlYW4oKS5kZXNjcmliZShcIldoZXRoZXIgdGhlIGVkaXQgc3VjY2VlZGVkXCIpLFxuICAgICAgcGF0aDogei5zdHJpbmcoKS5kZXNjcmliZShcIlBhdGggdG8gdGhlIGVkaXRlZCBmaWxlXCIpLFxuICAgICAgZXJyb3I6IHouc3RyaW5nKCkub3B0aW9uYWwoKS5kZXNjcmliZShcIkVycm9yIG1lc3NhZ2UgaWYgZWRpdCBmYWlsZWRcIiksXG4gICAgfSksXG4gIH0pLFxuICBCYXNoOiB0b29sKHtcbiAgICBkZXNjcmlwdGlvbjpcbiAgICAgIFwiRXhlY3V0ZXMgYSBiYXNoIGNvbW1hbmQuIFJldHVybnMgc3Rkb3V0IGFuZCBzdGRlcnIgc2VwYXJhdGVseS4gVXNlIHdhaXRVbnRpbCB0byBjb250cm9sIGhvdyBsb25nIHRvIHdhaXQgKDAgPSByZXR1cm4gaW1tZWRpYXRlbHksIHByb2Nlc3Mga2VlcHMgcnVubmluZykuIExhcmdlIG91dHB1dHMgYXJlIHRhaWwtdHJ1bmNhdGVkOyBmdWxsIG91dHB1dCBpbiBvdXRwdXREaXIuXCIsXG4gICAgaW5wdXRTY2hlbWE6IHoub2JqZWN0KHtcbiAgICAgIGxhYmVsOiB6XG4gICAgICAgIC5zdHJpbmcoKVxuICAgICAgICAuZGVzY3JpYmUoXCJBIGxhYmVsIHRoYXQgZGVzY3JpYmVzIHRoZSBhY3Rpb24gYmVpbmcgcGVyZm9ybWVkXCIpLFxuICAgICAgY29tbWFuZDogei5zdHJpbmcoKS5kZXNjcmliZShcIlRoZSBzaGVsbCBjb21tYW5kIHRvIGV4ZWN1dGVcIiksXG4gICAgICB3YWl0VW50aWw6IHpcbiAgICAgICAgLm51bWJlcigpXG4gICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgIC5kZXNjcmliZShcbiAgICAgICAgICBgTWF4IG1zIHRvIHdhaXQgZm9yIGNvbXBsZXRpb24gKGRlZmF1bHQ6ICR7REVGQVVMVF9XQUlUX1VOVElMfSkuIFVzZSAwIHRvIHJldHVybiBpbW1lZGlhdGVseSB3aGlsZSB0aGUgcHJvY2VzcyBrZWVwcyBydW5uaW5nLmBcbiAgICAgICAgKSxcbiAgICB9KSxcbiAgICBvdXRwdXRTY2hlbWE6IHoub2JqZWN0KHtcbiAgICAgIGNvbW1hbmRJZDogelxuICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgLmRlc2NyaWJlKFwiQ29tbWFuZCBJRC4gVXNlIHRvIHJlZmVyZW5jZSBvciBraWxsIHJ1bm5pbmcgcHJvY2Vzc2VzLlwiKSxcbiAgICAgIHN0ZG91dDogelxuICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgLmRlc2NyaWJlKFxuICAgICAgICAgIFwiQ29tbWFuZCBzdGRvdXQuIFRhaWwtdHJ1bmNhdGVkIGlmIGxhcmdlOyBmdWxsIGNvbnRlbnQgaW4gb3V0cHV0RGlyL3N0ZG91dC50eHQuXCJcbiAgICAgICAgKSxcbiAgICAgIHN0ZGVycjogelxuICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgLmRlc2NyaWJlKFxuICAgICAgICAgIFwiQ29tbWFuZCBzdGRlcnIuIFRhaWwtdHJ1bmNhdGVkIGlmIGxhcmdlOyBmdWxsIGNvbnRlbnQgaW4gb3V0cHV0RGlyL3N0ZGVyci50eHQuXCJcbiAgICAgICAgKSxcbiAgICAgIGV4aXRDb2RlOiB6Lm51bWJlcigpLmRlc2NyaWJlKFwiRXhpdCBjb2RlICgtMSBpZiBzdGlsbCBydW5uaW5nKVwiKSxcbiAgICAgIHN0YXR1czogelxuICAgICAgICAuZW51bShbXCJydW5uaW5nXCIsIFwiY29tcGxldGVkXCIsIFwiZmFpbGVkXCJdKVxuICAgICAgICAuZGVzY3JpYmUoXCJQcm9jZXNzIHN0YXR1c1wiKSxcbiAgICAgIG91dHB1dERpcjogelxuICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgLmRlc2NyaWJlKFxuICAgICAgICAgIFwiUGF0aCB0byBvdXRwdXQgZGlyZWN0b3J5IGNvbnRhaW5pbmcgc3Rkb3V0LnR4dCwgc3RkZXJyLnR4dCwgYW5kIG1ldGFkYXRhLmpzb24uIEVtcHR5IGlmIHN0aWxsIHJ1bm5pbmcuXCJcbiAgICAgICAgKSxcbiAgICB9KSxcbiAgfSksXG4gIFNraWxsOiB0b29sKHtcbiAgICBkZXNjcmlwdGlvbjpcbiAgICAgIFwiTG9hZCBhIHNraWxsJ3MgZnVsbCBpbnN0cnVjdGlvbnMgYnkgbmFtZS4gQ2FsbCB0aGlzIGJlZm9yZSBmb2xsb3dpbmcgYSBza2lsbC5cIixcbiAgICBpbnB1dFNjaGVtYTogei5vYmplY3Qoe1xuICAgICAgbGFiZWw6IHpcbiAgICAgICAgLnN0cmluZygpXG4gICAgICAgIC5kZXNjcmliZShcIkEgbGFiZWwgdGhhdCBkZXNjcmliZXMgdGhlIGFjdGlvbiBiZWluZyBwZXJmb3JtZWRcIiksXG4gICAgICBuYW1lOiB6LnN0cmluZygpLmRlc2NyaWJlKFwiU2tpbGwgbmFtZSBmcm9tIHRoZSBBdmFpbGFibGUgU2tpbGxzIGxpc3RcIiksXG4gICAgfSksXG4gICAgb3V0cHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4gICAgICBuYW1lOiB6LnN0cmluZygpLFxuICAgICAgZGVzY3JpcHRpb246IHouc3RyaW5nKCksXG4gICAgICBjb250ZW50OiB6LnN0cmluZygpLmRlc2NyaWJlKFwiRnVsbCBTS0lMTC5tZCBjb250ZW50XCIpLFxuICAgICAgcGF0aDogei5zdHJpbmcoKS5kZXNjcmliZShcIlBhdGggdG8gdGhlIHNraWxsIGRpcmVjdG9yeSBpbiB0aGUgc2FuZGJveFwiKSxcbiAgICB9KSxcbiAgfSksXG4gIEphdmFTY3JpcHQ6IHRvb2woe1xuICAgIGlucHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4gICAgICBsYWJlbDogelxuICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgLmRlc2NyaWJlKFwiQSBsYWJlbCB0aGF0IGRlc2NyaWJlcyB0aGUgYWN0aW9uIGJlaW5nIHBlcmZvcm1lZFwiKSxcbiAgICAgIGNvZGU6IHpcbiAgICAgICAgLnN0cmluZygpXG4gICAgICAgIC5kZXNjcmliZShcbiAgICAgICAgICBcIkphdmFTY3JpcHQgYXN5bmMgZnVuY3Rpb24gYm9keS4gYGN0eGAgaXMgaW4gc2NvcGUuIE11c3QgdXNlIGByZXR1cm5gIHRvIHByb2R1Y2Ugb3V0cHV0LlwiXG4gICAgICAgICksXG4gICAgfSksXG4gIH0pLFxufSBzYXRpc2ZpZXMgVG9vbFNldDtcblxuZXhwb3J0IHR5cGUgQnVpbHRJblRvb2xOYW1lID0ga2V5b2YgdHlwZW9mIGJ1aWx0SW5Ub29scztcbmV4cG9ydCBjb25zdCBidWlsdGluVG9vbE5hbWVzID0gT2JqZWN0LmZyb21FbnRyaWVzKFxuICBPYmplY3QuZW50cmllcyhidWlsdEluVG9vbHMpLm1hcCgoW25hbWVdKSA9PiBbbmFtZSwgbmFtZV0pXG4pIGFzIHsgW0sgaW4gQnVpbHRJblRvb2xOYW1lXTogSyB9O1xuXG5jb25zdCBTS0lMTF9NRF9TVUZGSVggPSAvXFwvP1NLSUxMXFwubWQkLztcblxuZXhwb3J0IGZ1bmN0aW9uIGdldFRvb2xzKHtcbiAgYWdlbnQsXG4gIHNhbmRib3gsXG4gIHNraWxsc1JlZixcbiAgd3JpdGVyLFxuICBhYm9ydENvbnRyb2xsZXIsXG4gIG5leHRQYXJ0SW5kZXhSZWYsXG4gIGFzc2lzdGFudE1lc3NhZ2VJZCxcbiAgc2Vzc2lvbklkLFxuICBzdGVwTG9nLFxuICBjb250ZXh0LFxuICBzdGF0ZSxcbiAgbWVzc2FnZXMsXG4gIGFjdGl2ZVRvb2xzLFxufToge1xuICBhZ2VudDogQW55QWdlbnQ7XG4gIHNhbmRib3g6IFNhbmRib3hJbnN0YW5jZTtcbiAgc2tpbGxzUmVmOiB7IGN1cnJlbnQ6IFNraWxsU3VtbWFyeVtdIH07XG4gIHdyaXRlcjogU3RyZWFtV3JpdGVyO1xuICBhYm9ydENvbnRyb2xsZXI6IEFib3J0Q29udHJvbGxlcjtcbiAgbmV4dFBhcnRJbmRleFJlZjogeyBjdXJyZW50OiBudW1iZXIgfTtcbiAgYXNzaXN0YW50TWVzc2FnZUlkOiBzdHJpbmc7XG4gIHNlc3Npb25JZDogc3RyaW5nO1xuICBzdGVwTG9nOiBMb2dnZXI7XG4gIGNvbnRleHQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBzdGF0ZTogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIG1lc3NhZ2VzOiBVSU1lc3NhZ2VbXTtcbiAgYWN0aXZlVG9vbHM/OiBzdHJpbmdbXTtcbn0pOiB7XG4gIHJhd1Rvb2xzOiBUb29sU2V0O1xuICB0b29sc1dpdGhOZWVkc0FwcHJvdmFsOiBUb29sU2V0O1xuICB0b29sQ29udGV4dDogVG9vbENvbnRleHQ7XG59IHtcbiAgY29uc3QgcmF3VG9vbHM6IFRvb2xTZXQgPSB7XG4gICAgW2J1aWx0aW5Ub29sTmFtZXMuUmVhZF06IHRvb2woe1xuICAgICAgLi4uYnVpbHRJblRvb2xzLlJlYWQsXG4gICAgICBleGVjdXRlOiBhc3luYyAoeyBwYXRoLCBzdGFydExpbmUsIGVuZExpbmUgfSkgPT4ge1xuICAgICAgICBjb25zdCBmaWxlUGF0aCA9IHBhdGg7XG5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc2FuZGJveC5yZWFkRmlsZSh7IHBhdGg6IGZpbGVQYXRoIH0pO1xuXG4gICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgIGxvZy5lcnJvcihcIlJlYWQgZmFpbGVkXCIsIHsgZXJyb3I6IHJlc3VsdC5tZXNzYWdlIH0pO1xuICAgICAgICAgIHRocm93IHJlc3VsdDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChyZXN1bHQgPT09IG51bGwpIHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgY29udGVudDogYEVycm9yOiBGaWxlIG5vdCBmb3VuZCAtICR7ZmlsZVBhdGh9YCxcbiAgICAgICAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgICAgICAgIHRvdGFsTGluZXM6IDAsXG4gICAgICAgICAgICAgIGxpbmVzU2hvd246IDAsXG4gICAgICAgICAgICAgIHN0YXJ0TGluZTogMCxcbiAgICAgICAgICAgICAgZW5kTGluZTogMCxcbiAgICAgICAgICAgICAgaXNQYWdpbmF0ZWQ6IGZhbHNlLFxuICAgICAgICAgICAgICBmaWxlU2l6ZTogXCIwXCIsXG4gICAgICAgICAgICAgIHBhdGg6IGZpbGVQYXRoLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZnVsbENvbnRlbnQgPSByZXN1bHQudG9TdHJpbmcoXCJ1dGYtOFwiKTtcbiAgICAgICAgY29uc3QgbGluZXMgPSBmdWxsQ29udGVudC5zcGxpdChcIlxcblwiKTtcbiAgICAgICAgLy8gQSB0cmFpbGluZyBuZXdsaW5lIHByb2R1Y2VzIGFuIGVtcHR5IGxhc3QgZWxlbWVudCBcdTIwMTQgcmVtb3ZlIGl0XG4gICAgICAgIC8vIHNvIGxpbmUgY291bnQgbWF0Y2hlcyBgd2MgLWxgIC8gYGF3ayAnRU5Ee3ByaW50IE5SfSdgIGJlaGF2aW9yLlxuICAgICAgICBpZiAobGluZXMubGVuZ3RoID4gMCAmJiBsaW5lcy5hdCgtMSkgPT09IFwiXCIpIHtcbiAgICAgICAgICBsaW5lcy5wb3AoKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB0b3RhbExpbmVzID0gbGluZXMubGVuZ3RoO1xuICAgICAgICBjb25zdCBmaWxlQnl0ZXMgPSBCdWZmZXIuYnl0ZUxlbmd0aChmdWxsQ29udGVudCk7XG4gICAgICAgIGNvbnN0IGZpbGVTaXplID0gZm9ybWF0RmlsZVNpemUoZmlsZUJ5dGVzKTtcblxuICAgICAgICAvLyBEZXRlcm1pbmUgcmFuZ2VcbiAgICAgICAgY29uc3QgUEFHRV9TSVpFID0gMTAwO1xuICAgICAgICBsZXQgYWN0dWFsU3RhcnQ6IG51bWJlcjtcbiAgICAgICAgbGV0IGFjdHVhbEVuZDogbnVtYmVyO1xuXG4gICAgICAgIGlmIChzdGFydExpbmUgIT09IHVuZGVmaW5lZCAmJiBlbmRMaW5lICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBhY3R1YWxTdGFydCA9IHN0YXJ0TGluZTtcbiAgICAgICAgICBhY3R1YWxFbmQgPSBlbmRMaW5lO1xuICAgICAgICB9IGVsc2UgaWYgKHN0YXJ0TGluZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgYWN0dWFsU3RhcnQgPSBzdGFydExpbmU7XG4gICAgICAgICAgYWN0dWFsRW5kID0gTWF0aC5taW4oc3RhcnRMaW5lICsgUEFHRV9TSVpFIC0gMSwgdG90YWxMaW5lcyk7XG4gICAgICAgIH0gZWxzZSBpZiAoZW5kTGluZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgYWN0dWFsU3RhcnQgPSAxO1xuICAgICAgICAgIGFjdHVhbEVuZCA9IGVuZExpbmU7XG4gICAgICAgIH0gZWxzZSBpZiAodG90YWxMaW5lcyA+IDIwMCkge1xuICAgICAgICAgIGFjdHVhbFN0YXJ0ID0gMTtcbiAgICAgICAgICBhY3R1YWxFbmQgPSBQQUdFX1NJWkU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYWN0dWFsU3RhcnQgPSAxO1xuICAgICAgICAgIGFjdHVhbEVuZCA9IHRvdGFsTGluZXM7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBFeHRyYWN0IHRoZSBsaW5lIHJhbmdlICgxLWluZGV4ZWQpXG4gICAgICAgIGNvbnN0IHNsaWNlZExpbmVzID0gbGluZXMuc2xpY2UoYWN0dWFsU3RhcnQgLSAxLCBhY3R1YWxFbmQpO1xuICAgICAgICBjb25zdCBjb250ZW50ID0gc2xpY2VkTGluZXMuam9pbihcIlxcblwiKTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgICAgICB0b3RhbExpbmVzLFxuICAgICAgICAgICAgbGluZXNTaG93bjogTWF0aC5tYXgoMCwgYWN0dWFsRW5kIC0gYWN0dWFsU3RhcnQgKyAxKSxcbiAgICAgICAgICAgIHN0YXJ0TGluZTogYWN0dWFsU3RhcnQsXG4gICAgICAgICAgICBlbmRMaW5lOiBhY3R1YWxFbmQsXG4gICAgICAgICAgICBpc1BhZ2luYXRlZDogYWN0dWFsRW5kIDwgdG90YWxMaW5lcyxcbiAgICAgICAgICAgIGZpbGVTaXplLFxuICAgICAgICAgICAgcGF0aDogZmlsZVBhdGgsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBjb250ZW50LFxuICAgICAgICB9O1xuICAgICAgfSxcbiAgICB9KSxcbiAgICBbYnVpbHRpblRvb2xOYW1lcy5HcmVwXTogdG9vbCh7XG4gICAgICAuLi5idWlsdEluVG9vbHMuR3JlcCxcbiAgICAgIGV4ZWN1dGU6IGFzeW5jICh7XG4gICAgICAgIHBhdHRlcm4sXG4gICAgICAgIHBhdGgsXG4gICAgICAgIGZpbGVUeXBlLFxuICAgICAgICBnbG9iLFxuICAgICAgICBjYXNlU2Vuc2l0aXZlLFxuICAgICAgICBjb250ZXh0TGluZXMsXG4gICAgICAgIG1heENvdW50LFxuICAgICAgICBmaWxlc1dpdGhNYXRjaGVzLFxuICAgICAgfSkgPT4ge1xuICAgICAgICBjb25zdCBzZWFyY2hQYXRoID0gcGF0aCA/PyBcIi5cIjtcblxuICAgICAgICBjb25zdCBhcmdzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgICAgIGFyZ3MucHVzaChcIi0tbGluZS1udW1iZXJcIik7XG4gICAgICAgIGFyZ3MucHVzaChcIi0taGVhZGluZ1wiKTtcbiAgICAgICAgYXJncy5wdXNoKFwiLS1jb2xvclwiLCBcIm5ldmVyXCIpO1xuXG4gICAgICAgIGlmICghY2FzZVNlbnNpdGl2ZSkge1xuICAgICAgICAgIGFyZ3MucHVzaChcIi1pXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZpbGVUeXBlKSB7XG4gICAgICAgICAgYXJncy5wdXNoKFwiLS10eXBlXCIsIGZpbGVUeXBlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChnbG9iKSB7XG4gICAgICAgICAgYXJncy5wdXNoKFwiLS1nbG9iXCIsIGdsb2IpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNvbnRleHRMaW5lcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgYXJncy5wdXNoKFwiLUNcIiwgU3RyaW5nKGNvbnRleHRMaW5lcykpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG1heENvdW50ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBhcmdzLnB1c2goXCItLW1heC1jb3VudFwiLCBTdHJpbmcobWF4Q291bnQpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmaWxlc1dpdGhNYXRjaGVzKSB7XG4gICAgICAgICAgYXJncy5wdXNoKFwiLS1maWxlcy13aXRoLW1hdGNoZXNcIik7XG4gICAgICAgIH1cblxuICAgICAgICBhcmdzLnB1c2goXCItLVwiLCBwYXR0ZXJuLCBzZWFyY2hQYXRoKTtcblxuICAgICAgICBsZXQgcmVzdWx0ID0gYXdhaXQgc2FuZGJveC5leGVjKHsgY29tbWFuZDogXCJyZ1wiLCBhcmdzIH0pO1xuXG4gICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvciAmJiBpc1JnTm90Rm91bmRFcnJvcihyZXN1bHQpKSB7XG4gICAgICAgICAgbG9nLndhcm4oXCJyZyBub3QgZm91bmQsIGluc3RhbGxpbmcgcmlwZ3JlcFwiKTtcbiAgICAgICAgICBjb25zdCBpbnN0YWxsUmVzdWx0ID0gYXdhaXQgc2FuZGJveC5leGVjKHtcbiAgICAgICAgICAgIGNvbW1hbmQ6IFwiYmFzaFwiLFxuICAgICAgICAgICAgYXJnczogW1xuICAgICAgICAgICAgICBcIi1jXCIsXG4gICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICBcImNvbW1hbmQgLXYgcmcgPi9kZXYvbnVsbCAyPiYxICYmIGV4aXQgMFwiLFxuICAgICAgICAgICAgICAgIFwiZG5mIGluc3RhbGwgLXkgcmlwZ3JlcCAyPi9kZXYvbnVsbCAmJiBleGl0IDBcIixcbiAgICAgICAgICAgICAgICBcIihhcHQtZ2V0IHVwZGF0ZSAtcXEgJiYgYXB0LWdldCBpbnN0YWxsIC15IC1xcSByaXBncmVwKSAyPi9kZXYvbnVsbCAmJiBleGl0IDBcIixcbiAgICAgICAgICAgICAgICBcImFwayBhZGQgLS1uby1jYWNoZSByaXBncmVwIDI+L2Rldi9udWxsICYmIGV4aXQgMFwiLFxuICAgICAgICAgICAgICAgIFwiY3VybCAtc0wgaHR0cHM6Ly9naXRodWIuY29tL0J1cm50U3VzaGkvcmlwZ3JlcC9yZWxlYXNlcy9kb3dubG9hZC8xNC4xLjEvcmlwZ3JlcC0xNC4xLjEteDg2XzY0LXVua25vd24tbGludXgtbXVzbC50YXIuZ3ogfCB0YXIgeHogLUMgL3RtcCAmJiBpbnN0YWxsIC90bXAvcmlwZ3JlcC0xNC4xLjEteDg2XzY0LXVua25vd24tbGludXgtbXVzbC9yZyAvdXNyL2xvY2FsL2Jpbi9yZyAmJiBybSAtcmYgL3RtcC9yaXBncmVwLTE0LjEuMS14ODZfNjQtdW5rbm93bi1saW51eC1tdXNsXCIsXG4gICAgICAgICAgICAgIF0uam9pbihcIlxcblwiKSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBzdWRvOiB0cnVlLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGlmICghKGluc3RhbGxSZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikpIHtcbiAgICAgICAgICAgIGNvbnN0IGluc3RhbGxPdXRwdXQgPSBhd2FpdCBpbnN0YWxsUmVzdWx0LnJlc3VsdDtcbiAgICAgICAgICAgIGlmIChpbnN0YWxsT3V0cHV0LmV4aXRDb2RlICE9PSAwKSB7XG4gICAgICAgICAgICAgIGxvZy53YXJuKFwicmlwZ3JlcCBpbnN0YWxsIGZhaWxlZFwiLCB7XG4gICAgICAgICAgICAgICAgc3RkZXJyOiBpbnN0YWxsT3V0cHV0LnN0ZGVycixcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc3VsdCA9IGF3YWl0IHNhbmRib3guZXhlYyh7IGNvbW1hbmQ6IFwicmdcIiwgYXJncyB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvciAmJiBpc1JnTm90Rm91bmRFcnJvcihyZXN1bHQpKSB7XG4gICAgICAgICAgbG9nLndhcm4oXCJyZyB1bmF2YWlsYWJsZSwgZmFsbGluZyBiYWNrIHRvIGdyZXBcIik7XG4gICAgICAgICAgY29uc3QgZ3JlcEFyZ3MgPSBbXCItcm5cIiwgXCItLWNvbG9yPW5ldmVyXCJdO1xuICAgICAgICAgIGlmICghY2FzZVNlbnNpdGl2ZSkge1xuICAgICAgICAgICAgZ3JlcEFyZ3MucHVzaChcIi1pXCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoY29udGV4dExpbmVzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGdyZXBBcmdzLnB1c2goXCItQ1wiLCBTdHJpbmcoY29udGV4dExpbmVzKSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChtYXhDb3VudCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBncmVwQXJncy5wdXNoKFwiLW1cIiwgU3RyaW5nKG1heENvdW50KSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChmaWxlc1dpdGhNYXRjaGVzKSB7XG4gICAgICAgICAgICBncmVwQXJncy5wdXNoKFwiLWxcIik7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChnbG9iKSB7XG4gICAgICAgICAgICBncmVwQXJncy5wdXNoKGAtLWluY2x1ZGU9JHtnbG9ifWApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoZmlsZVR5cGUpIHtcbiAgICAgICAgICAgIGNvbnN0IGluY2x1ZGVNYXA6IFJlY29yZDxzdHJpbmcsIHN0cmluZ1tdPiA9IHtcbiAgICAgICAgICAgICAgdHM6IFtcIioudHNcIiwgXCIqLnRzeFwiLCBcIioubXRzXCIsIFwiKi5jdHNcIl0sXG4gICAgICAgICAgICAgIGpzOiBbXCIqLmpzXCIsIFwiKi5qc3hcIiwgXCIqLm1qc1wiLCBcIiouY2pzXCJdLFxuICAgICAgICAgICAgICBweTogW1wiKi5weVwiXSxcbiAgICAgICAgICAgICAgcnVzdDogW1wiKi5yc1wiXSxcbiAgICAgICAgICAgICAgZ286IFtcIiouZ29cIl0sXG4gICAgICAgICAgICAgIGphdmE6IFtcIiouamF2YVwiXSxcbiAgICAgICAgICAgICAgbWQ6IFtcIioubWRcIl0sXG4gICAgICAgICAgICAgIGpzb246IFtcIiouanNvblwiXSxcbiAgICAgICAgICAgICAgY3NzOiBbXCIqLmNzc1wiXSxcbiAgICAgICAgICAgICAgaHRtbDogW1wiKi5odG1sXCJdLFxuICAgICAgICAgICAgICB5YW1sOiBbXCIqLnltbFwiLCBcIioueWFtbFwiXSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGV4dCBvZiBpbmNsdWRlTWFwW2ZpbGVUeXBlXSA/PyBbYCouJHtmaWxlVHlwZX1gXSkge1xuICAgICAgICAgICAgICBncmVwQXJncy5wdXNoKGAtLWluY2x1ZGU9JHtleHR9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGdyZXBBcmdzLnB1c2goXCItLVwiLCBwYXR0ZXJuLCBzZWFyY2hQYXRoKTtcbiAgICAgICAgICByZXN1bHQgPSBhd2FpdCBzYW5kYm94LmV4ZWMoe1xuICAgICAgICAgICAgY29tbWFuZDogXCJncmVwXCIsXG4gICAgICAgICAgICBhcmdzOiBncmVwQXJncyxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgIGxvZy5lcnJvcihcIkdyZXAgZmFpbGVkXCIsIHsgZXJyb3I6IHJlc3VsdC5tZXNzYWdlIH0pO1xuICAgICAgICAgIHRocm93IHJlc3VsdDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHsgc3Rkb3V0LCBzdGRlcnIgfSA9IGF3YWl0IHJlc3VsdC5yZXN1bHQ7XG5cbiAgICAgICAgaWYgKHN0ZGVyciAmJiAhc3RkZXJyLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoXCJubyBtYXRjaGVzXCIpKSB7XG4gICAgICAgICAgbG9nLndhcm4oXCJHcmVwIHN0ZGVyclwiLCB7IHN0ZGVyciB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRydW5jYXRlIG91dHB1dCB0byBwcmV2ZW50IFwiaW5wdXQgdG9vIGxvbmdcIiBlcnJvcnMgKDUwayBjaGFycyBcdTIyNDggMTIuNWsgdG9rZW5zKVxuICAgICAgICBjb25zdCBNQVhfR1JFUF9PVVRQVVRfQ0hBUlMgPSA1MF8wMDA7XG4gICAgICAgIGxldCBmaW5hbE91dHB1dCA9IHN0ZG91dDtcbiAgICAgICAgbGV0IHdhc1RydW5jYXRlZCA9IGZhbHNlO1xuICAgICAgICBpZiAoZmluYWxPdXRwdXQubGVuZ3RoID4gTUFYX0dSRVBfT1VUUFVUX0NIQVJTKSB7XG4gICAgICAgICAgZmluYWxPdXRwdXQgPVxuICAgICAgICAgICAgZmluYWxPdXRwdXQuc2xpY2UoMCwgTUFYX0dSRVBfT1VUUFVUX0NIQVJTKSArXG4gICAgICAgICAgICBcIlxcblxcbltPdXRwdXQgdHJ1bmNhdGVkIC0gdXNlIG1vcmUgc3BlY2lmaWMgcGF0dGVybiBvciBwYXRoXVwiO1xuICAgICAgICAgIHdhc1RydW5jYXRlZCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBsaW5lcyA9IGZpbmFsT3V0cHV0XG4gICAgICAgICAgLnRyaW0oKVxuICAgICAgICAgIC5zcGxpdChcIlxcblwiKVxuICAgICAgICAgIC5maWx0ZXIoKGwpID0+IGwubGVuZ3RoID4gMCk7XG4gICAgICAgIGNvbnN0IGZpbGVDb3VudCA9IGZpbGVzV2l0aE1hdGNoZXNcbiAgICAgICAgICA/IGxpbmVzLmxlbmd0aFxuICAgICAgICAgIDogbmV3IFNldChcbiAgICAgICAgICAgICAgbGluZXNcbiAgICAgICAgICAgICAgICAuZmlsdGVyKChsKSA9PiAhbC5zdGFydHNXaXRoKFwiIFwiKSAmJiBsLmluY2x1ZGVzKFwiOlwiKSlcbiAgICAgICAgICAgICAgICAubWFwKChsKSA9PiBsLnNwbGl0KFwiOlwiKVswXSlcbiAgICAgICAgICAgICkuc2l6ZTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHN1bW1hcnk6IHtcbiAgICAgICAgICAgIG1hdGNoQ291bnQ6IGZpbGVzV2l0aE1hdGNoZXNcbiAgICAgICAgICAgICAgPyAwXG4gICAgICAgICAgICAgIDogbGluZXMuZmlsdGVyKChsKSA9PiBsLmluY2x1ZGVzKFwiOlwiKSkubGVuZ3RoLFxuICAgICAgICAgICAgZmlsZUNvdW50LFxuICAgICAgICAgICAgc2VhcmNoUGF0aCxcbiAgICAgICAgICAgIHBhdHRlcm4sXG4gICAgICAgICAgICB3YXNUcnVuY2F0ZWQsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBtYXRjaGVzOiBmaW5hbE91dHB1dCB8fCBcIihubyBtYXRjaGVzIGZvdW5kKVwiLFxuICAgICAgICB9O1xuICAgICAgfSxcbiAgICB9KSxcbiAgICBbYnVpbHRpblRvb2xOYW1lcy5MaXN0XTogdG9vbCh7XG4gICAgICAuLi5idWlsdEluVG9vbHMuTGlzdCxcbiAgICAgIGV4ZWN1dGU6IGFzeW5jICh7IHBhdGgsIGRlcHRoLCBpbmNsdWRlSGlkZGVuLCBmaWxlc09ubHksIHBhdHRlcm4gfSkgPT4ge1xuICAgICAgICBjb25zdCBzZWFyY2hQYXRoID0gcGF0aCA/PyBcIi5cIjtcblxuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzYW5kYm94LmV4ZWMoe1xuICAgICAgICAgIGNvbW1hbmQ6IFwiYmFzaFwiLFxuICAgICAgICAgIGFyZ3M6IFtcbiAgICAgICAgICAgIFwiLWNcIixcbiAgICAgICAgICAgIGBcbiAgICAgICAgICAgIHNldCAtZVxuICAgICAgICAgICAgU0VBUkNIX1BBVEg9XCIkMVwiXG4gICAgICAgICAgICBERVBUSD1cIiQyXCJcbiAgICAgICAgICAgIElOQ0xVREVfSElEREVOPVwiJDNcIlxuICAgICAgICAgICAgRklMRVNfT05MWT1cIiQ0XCJcbiAgICAgICAgICAgIFBBVFRFUk49XCIkNVwiXG5cbiAgICAgICAgICAgICMgQnVpbGQgZmluZCBjb21tYW5kIGFyZ3VtZW50c1xuICAgICAgICAgICAgRklORF9BUkdTPVwiXCJcbiAgICAgICAgICAgIFsgLW4gXCIkREVQVEhcIiBdICYmIEZJTkRfQVJHUz1cIiRGSU5EX0FSR1MgLW1heGRlcHRoICRERVBUSFwiXG4gICAgICAgICAgICBbIFwiJElOQ0xVREVfSElEREVOXCIgIT0gXCJ0cnVlXCIgXSAmJiBGSU5EX0FSR1M9XCIkRklORF9BUkdTICEgLXBhdGggJyovLionXCJcbiAgICAgICAgICAgIFsgXCIkRklMRVNfT05MWVwiID0gXCJ0cnVlXCIgXSAmJiBGSU5EX0FSR1M9XCIkRklORF9BUkdTIC10eXBlIGZcIlxuICAgICAgICAgICAgWyAtbiBcIiRQQVRURVJOXCIgXSAmJiBGSU5EX0FSR1M9XCIkRklORF9BUkdTIC1uYW1lICckUEFUVEVSTidcIlxuXG4gICAgICAgICAgICAjIEdldCBsaXN0aW5nXG4gICAgICAgICAgICBMSVNUSU5HPSQoZXZhbCBcImZpbmQgJyRTRUFSQ0hfUEFUSCcgJEZJTkRfQVJHU1wiIDI+L2Rldi9udWxsIHwgc29ydClcblxuICAgICAgICAgICAgIyBHZXQgY291bnRzXG4gICAgICAgICAgICBDT1VOVF9BUkdTPVwiXCJcbiAgICAgICAgICAgIFsgLW4gXCIkREVQVEhcIiBdICYmIENPVU5UX0FSR1M9XCIkQ09VTlRfQVJHUyAtbWF4ZGVwdGggJERFUFRIXCJcbiAgICAgICAgICAgIFsgXCIkSU5DTFVERV9ISURERU5cIiAhPSBcInRydWVcIiBdICYmIENPVU5UX0FSR1M9XCIkQ09VTlRfQVJHUyAhIC1wYXRoICcqLy4qJ1wiXG5cbiAgICAgICAgICAgIEZJTEVfQ09VTlQ9JChldmFsIFwiZmluZCAnJFNFQVJDSF9QQVRIJyAkQ09VTlRfQVJHUyAtdHlwZSBmXCIgMj4vZGV2L251bGwgfCB3YyAtbClcbiAgICAgICAgICAgIERJUl9DT1VOVD0kKGV2YWwgXCJmaW5kICckU0VBUkNIX1BBVEgnICRDT1VOVF9BUkdTIC10eXBlIGRcIiAyPi9kZXYvbnVsbCB8IHdjIC1sKVxuXG4gICAgICAgICAgICAjIE91dHB1dDogY291bnRzIGZpcnN0LCB0aGVuIGxpc3RpbmdcbiAgICAgICAgICAgIGVjaG8gXCIkRklMRV9DT1VOVHwkRElSX0NPVU5UXCJcbiAgICAgICAgICAgIGVjaG8gXCJ8fHxMSVNUSU5HfHx8XCJcbiAgICAgICAgICAgIGVjaG8gXCIkTElTVElOR1wiIHwgc2VkIFwic3xeJFNFQVJDSF9QQVRIfC58XCJcbiAgICAgICAgICBgLFxuICAgICAgICAgICAgXCItLVwiLFxuICAgICAgICAgICAgc2VhcmNoUGF0aCxcbiAgICAgICAgICAgIGRlcHRoPy50b1N0cmluZygpIHx8IFwiXCIsXG4gICAgICAgICAgICBpbmNsdWRlSGlkZGVuID8gXCJ0cnVlXCIgOiBcImZhbHNlXCIsXG4gICAgICAgICAgICBmaWxlc09ubHkgPyBcInRydWVcIiA6IFwiZmFsc2VcIixcbiAgICAgICAgICAgIHBhdHRlcm4gfHwgXCJcIixcbiAgICAgICAgICBdLFxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICBsb2cuZXJyb3IoXCJMaXN0IGZhaWxlZFwiLCB7IGVycm9yOiByZXN1bHQubWVzc2FnZSB9KTtcbiAgICAgICAgICB0aHJvdyByZXN1bHQ7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB7IHN0ZG91dCwgc3RkZXJyIH0gPSBhd2FpdCByZXN1bHQucmVzdWx0O1xuXG4gICAgICAgIGlmIChzdGRlcnIpIHtcbiAgICAgICAgICBsb2cud2FybihcIkxpc3Qgc3RkZXJyXCIsIHsgc3RkZXJyIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgW2NvdW50c0xpbmUsIC4uLnJlc3RdID0gc3Rkb3V0LnNwbGl0KFwifHx8TElTVElOR3x8fFwiKTtcbiAgICAgICAgY29uc3QgbGlzdGluZyA9IHJlc3Quam9pbihcInx8fExJU1RJTkd8fHxcIikudHJpbSgpO1xuICAgICAgICBjb25zdCBbZmlsZUNvdW50U3RyLCBkaXJDb3VudFN0cl0gPSBjb3VudHNMaW5lLnRyaW0oKS5zcGxpdChcInxcIik7XG5cbiAgICAgICAgY29uc3QgdG90YWxGaWxlcyA9IE51bWJlci5wYXJzZUludChmaWxlQ291bnRTdHIsIDEwKSB8fCAwO1xuICAgICAgICBjb25zdCB0b3RhbERpcnMgPSBOdW1iZXIucGFyc2VJbnQoZGlyQ291bnRTdHIsIDEwKSB8fCAwO1xuICAgICAgICBjb25zdCBsaW5lcyA9IGxpc3Rpbmcuc3BsaXQoXCJcXG5cIikuZmlsdGVyKChsKSA9PiBsLmxlbmd0aCA+IDApO1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgc3VtbWFyeToge1xuICAgICAgICAgICAgdG90YWxJdGVtczogbGluZXMubGVuZ3RoLFxuICAgICAgICAgICAgdG90YWxGaWxlcyxcbiAgICAgICAgICAgIHRvdGFsRGlycyxcbiAgICAgICAgICAgIHNlYXJjaFBhdGgsXG4gICAgICAgICAgICBkZXB0aCxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGxpc3RpbmcsXG4gICAgICAgIH07XG4gICAgICB9LFxuICAgIH0pLFxuICAgIFtidWlsdGluVG9vbE5hbWVzLldyaXRlXTogdG9vbCh7XG4gICAgICAuLi5idWlsdEluVG9vbHMuV3JpdGUsXG4gICAgICBleGVjdXRlOiBhc3luYyAoeyBwYXRoLCBjb250ZW50IH0pID0+IHtcbiAgICAgICAgY29uc3QgZmlsZVBhdGggPSBwYXRoO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYXdhaXQgc2FuZGJveC53cml0ZUZpbGVzKHtcbiAgICAgICAgICAgIGZpbGVzOiBbeyBwYXRoOiBmaWxlUGF0aCwgY29udGVudCB9XSxcbiAgICAgICAgICAgIGRlc3RQYXRoOiBcIi5cIixcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzdWNjZXNzOiB0cnVlLFxuICAgICAgICAgICAgcGF0aDogZmlsZVBhdGgsXG4gICAgICAgICAgICBieXRlc1dyaXR0ZW46IEJ1ZmZlci5ieXRlTGVuZ3RoKGNvbnRlbnQsIFwidXRmOFwiKSxcbiAgICAgICAgICB9O1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBjb25zdCBlcnJvck1zZyA9IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKTtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICAgICAgICBwYXRoOiBmaWxlUGF0aCxcbiAgICAgICAgICAgIGJ5dGVzV3JpdHRlbjogMCxcbiAgICAgICAgICAgIGVycm9yOiBlcnJvck1zZyxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICB9LFxuICAgIH0pLFxuICAgIFtidWlsdGluVG9vbE5hbWVzLkVkaXRdOiB0b29sKHtcbiAgICAgIC4uLmJ1aWx0SW5Ub29scy5FZGl0LFxuICAgICAgZXhlY3V0ZTogYXN5bmMgKHsgcGF0aCwgb2xkX3N0cmluZywgbmV3X3N0cmluZyB9KSA9PiB7XG4gICAgICAgIGNvbnN0IGZpbGVQYXRoID0gcGF0aDtcblxuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzYW5kYm94LnJlYWRGaWxlKHsgcGF0aDogZmlsZVBhdGggfSk7XG5cbiAgICAgICAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIHsgc3VjY2VzczogZmFsc2UsIHBhdGg6IGZpbGVQYXRoLCBlcnJvcjogcmVzdWx0Lm1lc3NhZ2UgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChyZXN1bHQgPT09IG51bGwpIHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICAgICAgICBwYXRoOiBmaWxlUGF0aCxcbiAgICAgICAgICAgIGVycm9yOiBgRmlsZSBub3QgZm91bmQ6ICR7ZmlsZVBhdGh9YCxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY29udGVudCA9IHJlc3VsdC50b1N0cmluZyhcInV0Zi04XCIpO1xuICAgICAgICBjb25zdCBvY2N1cnJlbmNlcyA9IGNvbnRlbnQuc3BsaXQob2xkX3N0cmluZykubGVuZ3RoIC0gMTtcblxuICAgICAgICBpZiAob2NjdXJyZW5jZXMgPT09IDApIHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICAgICAgICBwYXRoOiBmaWxlUGF0aCxcbiAgICAgICAgICAgIGVycm9yOiBcIm9sZF9zdHJpbmcgbm90IGZvdW5kIGluIGZpbGVcIixcbiAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG9jY3VycmVuY2VzID4gMSkge1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICAgICAgICAgIHBhdGg6IGZpbGVQYXRoLFxuICAgICAgICAgICAgZXJyb3I6IGBvbGRfc3RyaW5nIGFwcGVhcnMgJHtvY2N1cnJlbmNlc30gdGltZXMgaW4gZmlsZSAobXVzdCBiZSB1bmlxdWUpLiBJbmNsdWRlIG1vcmUgc3Vycm91bmRpbmcgY29udGV4dCB0byBtYWtlIHRoZSBtYXRjaCB1bmlxdWUuYCxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbmV3Q29udGVudCA9IGNvbnRlbnQucmVwbGFjZShvbGRfc3RyaW5nLCBuZXdfc3RyaW5nKTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IHNhbmRib3gud3JpdGVGaWxlcyh7XG4gICAgICAgICAgICBmaWxlczogW3sgcGF0aDogZmlsZVBhdGgsIGNvbnRlbnQ6IG5ld0NvbnRlbnQgfV0sXG4gICAgICAgICAgICBkZXN0UGF0aDogXCIuXCIsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICByZXR1cm4geyBzdWNjZXNzOiB0cnVlLCBwYXRoOiBmaWxlUGF0aCB9O1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBjb25zdCBlcnJvck1zZyA9IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKTtcbiAgICAgICAgICByZXR1cm4geyBzdWNjZXNzOiBmYWxzZSwgcGF0aDogZmlsZVBhdGgsIGVycm9yOiBlcnJvck1zZyB9O1xuICAgICAgICB9XG4gICAgICB9LFxuICAgIH0pLFxuICAgIFtidWlsdGluVG9vbE5hbWVzLkJhc2hdOiB0b29sKHtcbiAgICAgIC4uLmJ1aWx0SW5Ub29scy5CYXNoLFxuICAgICAgZXhlY3V0ZTogYXN5bmMgKHsgY29tbWFuZCwgd2FpdFVudGlsIH0pID0+IHtcbiAgICAgICAgY29uc3QgeyBjcmVhdGVQcm9jZXNzTWFuYWdlciB9ID0gYXdhaXQgaW1wb3J0KFxuICAgICAgICAgIFwiLi4vc2FuZGJveC9wcm9jZXNzLW1hbmFnZXJcIlxuICAgICAgICApO1xuXG4gICAgICAgIGNvbnN0IHByb2Nlc3NNYW5hZ2VyID0gY3JlYXRlUHJvY2Vzc01hbmFnZXIoeyBzYW5kYm94IH0pO1xuXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHByb2Nlc3NNYW5hZ2VyLnJ1bih7IGNvbW1hbmQsIHdhaXRVbnRpbCB9KTtcblxuICAgICAgICBjb25zdCBNQVhfU1RET1VUID0gNTBfMDAwO1xuICAgICAgICBjb25zdCBNQVhfU1RERVJSID0gMTBfMDAwO1xuXG4gICAgICAgIGxldCB7IHN0ZG91dCwgc3RkZXJyIH0gPSByZXN1bHQ7XG4gICAgICAgIGlmIChzdGRvdXQubGVuZ3RoID4gTUFYX1NURE9VVCkge1xuICAgICAgICAgIHN0ZG91dCA9XG4gICAgICAgICAgICBgW3RydW5jYXRlZCBcdTIwMTQgc2hvd2luZyBsYXN0ICR7TUFYX1NURE9VVH0gY2hhcnMuIEZ1bGw6ICR7cmVzdWx0Lm91dHB1dERpcn0vc3Rkb3V0LnR4dF1cXG5cXG5gICtcbiAgICAgICAgICAgIHN0ZG91dC5zbGljZSgtTUFYX1NURE9VVCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHN0ZGVyci5sZW5ndGggPiBNQVhfU1RERVJSKSB7XG4gICAgICAgICAgc3RkZXJyID1cbiAgICAgICAgICAgIGBbdHJ1bmNhdGVkIFx1MjAxNCBzaG93aW5nIGxhc3QgJHtNQVhfU1RERVJSfSBjaGFycy4gRnVsbDogJHtyZXN1bHQub3V0cHV0RGlyfS9zdGRlcnIudHh0XVxcblxcbmAgK1xuICAgICAgICAgICAgc3RkZXJyLnNsaWNlKC1NQVhfU1RERVJSKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7IC4uLnJlc3VsdCwgc3Rkb3V0LCBzdGRlcnIgfTtcbiAgICAgIH0sXG4gICAgfSksXG4gIH07XG5cbiAgLy8gQWRkIHVzZXItZGVmaW5lZCB0b29sc1xuICBmb3IgKGNvbnN0IFtuYW1lLCB0XSBvZiBPYmplY3QuZW50cmllcyhhZ2VudC5vcHRpb25zLnRvb2xzID8/IHt9KSkge1xuICAgIHJhd1Rvb2xzW25hbWVdID0gdCBhcyBUb29sU2V0W3N0cmluZ107XG4gIH1cblxuICBpZiAoc2tpbGxzUmVmLmN1cnJlbnQubGVuZ3RoID4gMCkge1xuICAgIHJhd1Rvb2xzW2J1aWx0aW5Ub29sTmFtZXMuU2tpbGxdID0gdG9vbCh7XG4gICAgICAuLi5idWlsdEluVG9vbHMuU2tpbGwsXG4gICAgICBleGVjdXRlOiBhc3luYyAoeyBuYW1lIH0pID0+IHtcbiAgICAgICAgY29uc3Qgc2tpbGxzID0gc2tpbGxzUmVmLmN1cnJlbnQ7XG4gICAgICAgIGNvbnN0IHNraWxsID0gc2tpbGxzLmZpbmQoXG4gICAgICAgICAgKHMpID0+IHMubmFtZS50b0xvd2VyQ2FzZSgpID09PSBuYW1lLnRvTG93ZXJDYXNlKClcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKCFza2lsbCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBTa2lsbCBub3QgZm91bmQ6IFwiJHtuYW1lfVwiLiBBdmFpbGFibGU6ICR7c2tpbGxzLm1hcCgocykgPT4gcy5uYW1lKS5qb2luKFwiLCBcIil9YFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc2FuZGJveC5yZWFkRmlsZSh7XG4gICAgICAgICAgcGF0aDogc2tpbGwuc2tpbGxNZFBhdGgsXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJlc3VsdCA9PT0gbnVsbCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgU2tpbGwgZmlsZSBub3QgZm91bmQ6ICR7c2tpbGwuc2tpbGxNZFBhdGh9YCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcmF3ID1cbiAgICAgICAgICB0eXBlb2YgcmVzdWx0ID09PSBcInN0cmluZ1wiID8gcmVzdWx0IDogcmVzdWx0LnRvU3RyaW5nKFwidXRmLThcIik7XG4gICAgICAgIGNvbnN0IGVuZE1hcmtlciA9IHJhdy5pbmRleE9mKFwiLS0tXCIsIDMpO1xuICAgICAgICBjb25zdCBjb250ZW50ID1cbiAgICAgICAgICBlbmRNYXJrZXIgPT09IC0xID8gcmF3IDogcmF3LnNsaWNlKGVuZE1hcmtlciArIDMpLnRyaW0oKTtcbiAgICAgICAgY29uc3Qgc2tpbGxEaXIgPSBza2lsbC5za2lsbE1kUGF0aC5yZXBsYWNlKFNLSUxMX01EX1NVRkZJWCwgXCJcIik7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgbmFtZTogc2tpbGwubmFtZSxcbiAgICAgICAgICBkZXNjcmlwdGlvbjogc2tpbGwuZGVzY3JpcHRpb24sXG4gICAgICAgICAgY29udGVudCxcbiAgICAgICAgICBwYXRoOiBza2lsbERpcixcbiAgICAgICAgfTtcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICBjb25zdCBvblN1YlRvb2xDYWxsOiBPblN1YlRvb2xDYWxsID0gYXN5bmMgKHRvb2xOYW1lLCB0b29sSW5wdXQsIGV4ZWN1dGUpID0+IHtcbiAgICBjb25zdCBuZWVkc0FwcHJvdmFsID0gYXdhaXQgY2hlY2tOZWVkc0FwcHJvdmFsKHtcbiAgICAgIGFnZW50LFxuICAgICAgdG9vbE5hbWUsXG4gICAgICBpbnB1dDogdG9vbElucHV0LFxuICAgICAgdG9vbENhbGxJZDogYGpzXyR7dG9vbE5hbWV9XyR7RGF0ZS5ub3coKX1gLFxuICAgICAgbWVzc2FnZXM6IFtdLFxuICAgIH0pO1xuXG4gICAgaWYgKCFuZWVkc0FwcHJvdmFsKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBleGVjdXRlKCk7XG4gICAgICAgIHJldHVybiB7IHJlc3VsdCB9O1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgZXJyb3I6IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKSxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBhcHByb3ZhbElkID0gYGpzX2FwcHJvdmFsXyR7dWxpZCgpfWA7XG4gICAgY29uc3QgdG9vbENhbGxJZCA9IGBqc190Y18ke3VsaWQoKX1gO1xuICAgIGNvbnN0IHBhcnRJZCA9IGFwcHJvdmFsUGFydElkKGFwcHJvdmFsSWQpO1xuXG4gICAgYXdhaXQgYWdlbnQuc3RvcmFnZS5wYXJ0LnNldChwYXJ0SWQsIHtcbiAgICAgIGlkOiBwYXJ0SWQsXG4gICAgICBpbmRleDogbmV4dFBhcnRJbmRleFJlZi5jdXJyZW50KyssXG4gICAgICBtZXNzYWdlSWQ6IGFzc2lzdGFudE1lc3NhZ2VJZCxcbiAgICAgIHNlc3Npb25JZCxcbiAgICAgIHBhcnQ6IHtcbiAgICAgICAgdHlwZTogYHRvb2wtJHt0b29sTmFtZX1gLFxuICAgICAgICB0b29sQ2FsbElkLFxuICAgICAgICBzdGF0ZTogXCJhcHByb3ZhbC1yZXF1ZXN0ZWRcIixcbiAgICAgICAgaW5wdXQ6IHRvb2xJbnB1dCxcbiAgICAgICAgYXBwcm92YWw6IHsgaWQ6IGFwcHJvdmFsSWQgfSxcbiAgICAgIH0gYXMgdW5rbm93biBhcyBVSU1lc3NhZ2VbXCJwYXJ0c1wiXVtudW1iZXJdLFxuICAgIH0pO1xuXG4gICAgd3JpdGVyLndyaXRlKHtcbiAgICAgIHR5cGU6IFwidG9vbC1pbnB1dC1zdGFydFwiLFxuICAgICAgdG9vbENhbGxJZCxcbiAgICAgIHRvb2xOYW1lLFxuICAgIH0pO1xuICAgIHdyaXRlci53cml0ZSh7XG4gICAgICB0eXBlOiBcInRvb2wtaW5wdXQtYXZhaWxhYmxlXCIsXG4gICAgICB0b29sQ2FsbElkLFxuICAgICAgdG9vbE5hbWUsXG4gICAgICBpbnB1dDogdG9vbElucHV0LFxuICAgIH0pO1xuICAgIHdyaXRlci53cml0ZSh7XG4gICAgICB0eXBlOiBcInRvb2wtYXBwcm92YWwtcmVxdWVzdFwiLFxuICAgICAgYXBwcm92YWxJZCxcbiAgICAgIHRvb2xDYWxsSWQsXG4gICAgfSk7XG5cbiAgICBjb25zdCBQT0xMX01TID0gNTAwO1xuICAgIGNvbnN0IFRJTUVPVVRfTVMgPSA1ICogNjAgKiAxMDAwO1xuICAgIGNvbnN0IHN0YXJ0ID0gRGF0ZS5ub3coKTtcblxuICAgIHdoaWxlIChEYXRlLm5vdygpIC0gc3RhcnQgPCBUSU1FT1VUX01TICYmICFhYm9ydENvbnRyb2xsZXIuc2lnbmFsLmFib3J0ZWQpIHtcbiAgICAgIGNvbnN0IHVwZGF0ZWQgPSBhd2FpdCBhZ2VudC5zdG9yYWdlLnBhcnQuZ2V0KHBhcnRJZCk7XG4gICAgICBpZiAoXG4gICAgICAgIHVwZGF0ZWQgJiZcbiAgICAgICAgXCJzdGF0ZVwiIGluIHVwZGF0ZWQucGFydCAmJlxuICAgICAgICAoKHVwZGF0ZWQucGFydCBhcyB7IHN0YXRlOiBzdHJpbmcgfSkuc3RhdGUgPT09IFwiYXBwcm92YWwtcmVzcG9uZGVkXCIgfHxcbiAgICAgICAgICAodXBkYXRlZC5wYXJ0IGFzIHsgc3RhdGU6IHN0cmluZyB9KS5zdGF0ZSA9PT0gXCJvdXRwdXQtZGVuaWVkXCIpXG4gICAgICApIHtcbiAgICAgICAgY29uc3Qgc3RhdGUgPSAodXBkYXRlZC5wYXJ0IGFzIHsgc3RhdGU6IHN0cmluZyB9KS5zdGF0ZTtcblxuICAgICAgICBpZiAoc3RhdGUgPT09IFwib3V0cHV0LWRlbmllZFwiKSB7XG4gICAgICAgICAgY29uc3QgcmVhc29uID0gKHVwZGF0ZWQucGFydCBhcyB7IGFwcHJvdmFsPzogeyByZWFzb24/OiBzdHJpbmcgfSB9KVxuICAgICAgICAgICAgLmFwcHJvdmFsPy5yZWFzb247XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGVycm9yOiBgVG9vbCBcIiR7dG9vbE5hbWV9XCIgZGVuaWVkOiAke3JlYXNvbiB8fCBcInVzZXIgZGVuaWVkXCJ9YCxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYXBwcm92YWwgPSAoXG4gICAgICAgICAgdXBkYXRlZC5wYXJ0IGFzIHtcbiAgICAgICAgICAgIGFwcHJvdmFsPzogeyBhcHByb3ZlZDogYm9vbGVhbjsgcmVhc29uPzogc3RyaW5nIH07XG4gICAgICAgICAgfVxuICAgICAgICApLmFwcHJvdmFsO1xuICAgICAgICBpZiAoYXBwcm92YWw/LmFwcHJvdmVkKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGV4ZWN1dGUoKTtcbiAgICAgICAgICAgIHdyaXRlci53cml0ZSh7XG4gICAgICAgICAgICAgIHR5cGU6IFwidG9vbC1vdXRwdXQtYXZhaWxhYmxlXCIsXG4gICAgICAgICAgICAgIHRvb2xDYWxsSWQsXG4gICAgICAgICAgICAgIG91dHB1dDogcmVzdWx0LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4geyByZXN1bHQgfTtcbiAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGNvbnN0IGVycm9yID0gZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpO1xuICAgICAgICAgICAgd3JpdGVyLndyaXRlKHtcbiAgICAgICAgICAgICAgdHlwZTogXCJ0b29sLW91dHB1dC1lcnJvclwiLFxuICAgICAgICAgICAgICB0b29sQ2FsbElkLFxuICAgICAgICAgICAgICBlcnJvclRleHQ6IGVycm9yLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4geyBlcnJvciB9O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB3cml0ZXIud3JpdGUoe1xuICAgICAgICAgIHR5cGU6IFwidG9vbC1vdXRwdXQtZGVuaWVkXCIsXG4gICAgICAgICAgdG9vbENhbGxJZCxcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgZXJyb3I6IGBUb29sIFwiJHt0b29sTmFtZX1cIiBkZW5pZWQ6ICR7YXBwcm92YWw/LnJlYXNvbiB8fCBcInVzZXIgZGVuaWVkXCJ9YCxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIGF3YWl0IG5ldyBQcm9taXNlKChyKSA9PiBzZXRUaW1lb3V0KHIsIFBPTExfTVMpKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgZXJyb3I6IGFib3J0Q29udHJvbGxlci5zaWduYWwuYWJvcnRlZFxuICAgICAgICA/IFwiaW50ZXJydXB0ZWRcIlxuICAgICAgICA6IFwiQXBwcm92YWwgdGltZWQgb3V0XCIsXG4gICAgfTtcbiAgfTtcblxuICBjb25zdCB0b29sQ29udGV4dDogVG9vbENvbnRleHQgPSB7XG4gICAgY29udGV4dCxcbiAgICBzdGF0ZSxcbiAgICBzZXNzaW9uSWQsXG4gICAgc2FuZGJveCxcbiAgICBtZXNzYWdlczogbWVzc2FnZXMgYXMgVG9vbENvbnRleHRbXCJtZXNzYWdlc1wiXSxcbiAgfTtcblxuICByYXdUb29sc1tidWlsdGluVG9vbE5hbWVzLkphdmFTY3JpcHRdID0gY3JlYXRlSmF2YVNjcmlwdFRvb2woe1xuICAgIHRvb2xzOiByYXdUb29scyxcbiAgICBzYW5kYm94LFxuICAgIGFjdGl2ZVRvb2xzLFxuICAgIG9uU3ViVG9vbENhbGwsXG4gICAgdG9vbENvbnRleHQsXG4gIH0pO1xuXG4gIGNvbnN0IHRvb2xzV2l0aE5lZWRzQXBwcm92YWwgPSBPYmplY3QuZnJvbUVudHJpZXMoXG4gICAgT2JqZWN0LmVudHJpZXMocmF3VG9vbHMpLm1hcCgoW25hbWUsIHRdKSA9PiB7XG4gICAgICBjb25zdCBvcmlnaW5hbEV4ZWN1dGUgPSB0LmV4ZWN1dGU7XG4gICAgICBjb25zdCB3cmFwcGVkRXhlY3V0ZSA9IG9yaWdpbmFsRXhlY3V0ZVxuICAgICAgICA/IGFzeW5jICguLi5hcmdzOiBQYXJhbWV0ZXJzPHR5cGVvZiBvcmlnaW5hbEV4ZWN1dGU+KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBkb25lID0gc3RlcExvZy50aW1lKGB0b29sOiR7bmFtZX1gKTtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIGxldCB0b29sSW5wdXQgPSBhcmdzWzBdO1xuICAgICAgICAgICAgICBpZiAoYWdlbnQuaG9va3NbXCJ0b29sLmJlZm9yZVwiXSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGJlZm9yZVJlc3VsdCA9IGF3YWl0IGFnZW50Lmhvb2tzW1widG9vbC5iZWZvcmVcIl0oe1xuICAgICAgICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgICAgICAgIGlucHV0OiB0b29sSW5wdXQsXG4gICAgICAgICAgICAgICAgICBjb250ZXh0OiB0b29sQ29udGV4dCxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBpZiAoYmVmb3JlUmVzdWx0Py5pbnB1dCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICB0b29sSW5wdXQgPSBiZWZvcmVSZXN1bHQuaW5wdXQ7XG4gICAgICAgICAgICAgICAgICBhcmdzWzBdID0gdG9vbElucHV0IGFzICh0eXBlb2YgYXJncylbMF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgbGV0IHJlc3VsdCA9IGF3YWl0IG9yaWdpbmFsRXhlY3V0ZSguLi5hcmdzKTtcblxuICAgICAgICAgICAgICBpZiAoYWdlbnQuaG9va3NbXCJ0b29sLmFmdGVyXCJdKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgYWZ0ZXJSZXN1bHQgPSBhd2FpdCBhZ2VudC5ob29rc1tcInRvb2wuYWZ0ZXJcIl0oe1xuICAgICAgICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgICAgICAgIGlucHV0OiB0b29sSW5wdXQsXG4gICAgICAgICAgICAgICAgICByZXN1bHQsXG4gICAgICAgICAgICAgICAgICBjb250ZXh0OiB0b29sQ29udGV4dCxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBpZiAoYWZ0ZXJSZXN1bHQ/LnJlc3VsdCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICByZXN1bHQgPSBhZnRlclJlc3VsdC5yZXN1bHQgYXMgdHlwZW9mIHJlc3VsdDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBkb25lKCk7XG4gICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgIGRvbmUoe1xuICAgICAgICAgICAgICAgIGVycm9yOiBlIGluc3RhbmNlb2YgRXJyb3IgPyBlLm1lc3NhZ2UgOiBTdHJpbmcoZSksXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgOiB1bmRlZmluZWQ7XG4gICAgICByZXR1cm4gW1xuICAgICAgICBuYW1lLFxuICAgICAgICB7XG4gICAgICAgICAgLi4udCxcbiAgICAgICAgICAuLi4od3JhcHBlZEV4ZWN1dGUgPyB7IGV4ZWN1dGU6IHdyYXBwZWRFeGVjdXRlIH0gOiB7fSksXG4gICAgICAgICAgbmVlZHNBcHByb3ZhbDogYXN5bmMgKFxuICAgICAgICAgICAgdG9vbElucHV0OiB1bmtub3duLFxuICAgICAgICAgICAgb3B0czogeyB0b29sQ2FsbElkOiBzdHJpbmc7IG1lc3NhZ2VzOiB1bmtub3duW10gfVxuICAgICAgICAgICkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IGNoZWNrTmVlZHNBcHByb3ZhbCh7XG4gICAgICAgICAgICAgIGFnZW50LFxuICAgICAgICAgICAgICB0b29sTmFtZTogbmFtZSxcbiAgICAgICAgICAgICAgaW5wdXQ6IHRvb2xJbnB1dCxcbiAgICAgICAgICAgICAgdG9vbENhbGxJZDogb3B0cy50b29sQ2FsbElkLFxuICAgICAgICAgICAgICBtZXNzYWdlczogb3B0cy5tZXNzYWdlcyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICBdO1xuICAgIH0pXG4gICk7XG5cbiAgcmV0dXJuIHsgcmF3VG9vbHMsIHRvb2xzV2l0aE5lZWRzQXBwcm92YWwsIHRvb2xDb250ZXh0IH07XG59XG4iLCAiaW1wb3J0IHsgdHlwZSBUb29sU2V0LCB0b29sIH0gZnJvbSBcImFpXCI7XG5pbXBvcnQgeyB6IH0gZnJvbSBcInpvZFwiO1xuaW1wb3J0IHR5cGUgeyBTYW5kYm94SW5zdGFuY2UgfSBmcm9tIFwiLi4vc2FuZGJveC9hZGFwdGVyXCI7XG5pbXBvcnQgeyBidWlsdEluVG9vbHMgfSBmcm9tIFwiLlwiO1xuXG5leHBvcnQgY29uc3QgSkFWQVNDUklQVF9UT09MX05BTUUgPSBcIkphdmFTY3JpcHRcIjtcblxuZXhwb3J0IHR5cGUgU3ViVG9vbENhbGxSZXN1bHQgPSB7IHJlc3VsdD86IHVua25vd247IGVycm9yPzogc3RyaW5nIH07XG5leHBvcnQgdHlwZSBPblN1YlRvb2xDYWxsID0gKFxuICB0b29sTmFtZTogc3RyaW5nLFxuICBpbnB1dDogdW5rbm93bixcbiAgZXhlY3V0ZTogKCkgPT4gUHJvbWlzZTx1bmtub3duPlxuKSA9PiBQcm9taXNlPFN1YlRvb2xDYWxsUmVzdWx0PjtcblxuY29uc3QgUkVRVUVTVF9NQVJLRVJfU1RBUlQgPSBcIl9fVE9PTF9SRVFVRVNUX19cIjtcbmNvbnN0IFJFUVVFU1RfTUFSS0VSX0VORCA9IFwiX19UT09MX1JFUVVFU1RfRU5EX19cIjtcbmNvbnN0IEVYRUNVVElPTl9USU1FT1VUX01TID0gNSAqIDYwICogMTAwMDtcblxuLyoqXG4gKiBUaGUgcnVubmVyIHNjcmlwdCBpcyB3cml0dGVuIHRvIHRoZSBzYW5kYm94IGFuZCBleGVjdXRlZCB2aWEgTm9kZS5qcy5cbiAqIEl0IHJlYWRzIHRoZSBtb2RlbCdzIGNvZGUgZnJvbSBjb2RlLmpzLCBzZXRzIHVwIGN0eC50b29scyBhcyBSUEMgcHJveGllc1xuICogKHJlcXVlc3RzIHNlbnQgdmlhIHN0ZGVyciBtYXJrZXJzLCByZXNwb25zZXMgcG9sbGVkIGZyb20gZmlsZXMpLCBleGVjdXRlc1xuICogdGhlIGNvZGUsIGFuZCB3cml0ZXMgdGhlIHJlc3VsdCB0byBzdGRvdXQgYXMgSlNPTi5cbiAqL1xuY29uc3QgUlVOTkVSX1NDUklQVCA9IGBcbmltcG9ydCB7IHJlYWRGaWxlU3luYywgZXhpc3RzU3luYywgdW5saW5rU3luYywgbWtkaXJTeW5jIH0gZnJvbSAnbm9kZTpmcyc7XG5pbXBvcnQgeyBqb2luLCBkaXJuYW1lIH0gZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCB7IGZpbGVVUkxUb1BhdGggfSBmcm9tICdub2RlOnVybCc7XG5cbmNvbnN0IFNDUklQVF9ESVIgPSBkaXJuYW1lKGZpbGVVUkxUb1BhdGgoaW1wb3J0Lm1ldGEudXJsKSk7XG5jb25zdCBUT09MX0NBTExfVElNRU9VVF9NUyA9IDMwMF8wMDA7XG5cbmxldCByZXFDb3VudGVyID0gMDtcblxuYXN5bmMgZnVuY3Rpb24gY2FsbFRvb2wobmFtZSwgaW5wdXQpIHtcbiAgY29uc3QgaWQgPSAncmVxXycgKyAoKytyZXFDb3VudGVyKSArICdfJyArIERhdGUubm93KCk7XG4gIGNvbnN0IHJlc3BvbnNlRmlsZSA9IGpvaW4oU0NSSVBUX0RJUiwgaWQgKyAnLnJlc3BvbnNlLmpzb24nKTtcblxuICBjb25zdCByZXF1ZXN0ID0gSlNPTi5zdHJpbmdpZnkoeyBpZCwgdG9vbDogbmFtZSwgaW5wdXQgfSk7XG4gIHByb2Nlc3Muc3RkZXJyLndyaXRlKCcke1JFUVVFU1RfTUFSS0VSX1NUQVJUfScgKyByZXF1ZXN0ICsgJyR7UkVRVUVTVF9NQVJLRVJfRU5EfScgKyAnXFxcXG4nKTtcblxuICBjb25zdCBzdGFydCA9IERhdGUubm93KCk7XG4gIHdoaWxlICghZXhpc3RzU3luYyhyZXNwb25zZUZpbGUpKSB7XG4gICAgaWYgKERhdGUubm93KCkgLSBzdGFydCA+IFRPT0xfQ0FMTF9USU1FT1VUX01TKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Rvb2wgY2FsbCAnICsgbmFtZSArICcgdGltZWQgb3V0IHdhaXRpbmcgZm9yIHJlc3BvbnNlJyk7XG4gICAgfVxuICAgIGF3YWl0IG5ldyBQcm9taXNlKHIgPT4gc2V0VGltZW91dChyLCAzMCkpO1xuICB9XG5cbiAgbGV0IHJhdztcbiAgdHJ5IHtcbiAgICByYXcgPSByZWFkRmlsZVN5bmMocmVzcG9uc2VGaWxlLCAndXRmOCcpO1xuICB9IGNhdGNoIHtcbiAgICBhd2FpdCBuZXcgUHJvbWlzZShyID0+IHNldFRpbWVvdXQociwgNTApKTtcbiAgICByYXcgPSByZWFkRmlsZVN5bmMocmVzcG9uc2VGaWxlLCAndXRmOCcpO1xuICB9XG5cbiAgY29uc3QgcmVzcG9uc2UgPSBKU09OLnBhcnNlKHJhdyk7XG4gIHRyeSB7IHVubGlua1N5bmMocmVzcG9uc2VGaWxlKTsgfSBjYXRjaCB7fVxuXG4gIGlmIChyZXNwb25zZS5lcnJvcikge1xuICAgIHRocm93IG5ldyBFcnJvcihyZXNwb25zZS5lcnJvcik7XG4gIH1cbiAgcmV0dXJuIHJlc3BvbnNlLnJlc3VsdDtcbn1cblxuY29uc3QgY29kZSA9IHJlYWRGaWxlU3luYyhqb2luKFNDUklQVF9ESVIsICdjb2RlLmpzJyksICd1dGY4Jyk7XG5jb25zdCB0b29sTmFtZXMgPSBKU09OLnBhcnNlKHJlYWRGaWxlU3luYyhqb2luKFNDUklQVF9ESVIsICd0b29scy5qc29uJyksICd1dGY4JykpO1xuXG5jb25zdCBjdHggPSB7IHRvb2xzOiB7fSB9O1xuZm9yIChjb25zdCBuYW1lIG9mIHRvb2xOYW1lcykge1xuICBjdHgudG9vbHNbbmFtZV0gPSAoaW5wdXQpID0+IGNhbGxUb29sKG5hbWUsIGlucHV0KTtcbn1cblxuY29uc3QgbG9ncyA9IFtdO1xuY29uc3QgY3VzdG9tQ29uc29sZSA9IHtcbiAgbG9nOiAoLi4uYXJncykgPT4gbG9ncy5wdXNoKGFyZ3MubWFwKGEgPT4gdHlwZW9mIGEgPT09ICdzdHJpbmcnID8gYSA6IEpTT04uc3RyaW5naWZ5KGEpKS5qb2luKCcgJykpLFxuICBlcnJvcjogKC4uLmFyZ3MpID0+IGxvZ3MucHVzaCgnW2Vycm9yXSAnICsgYXJncy5tYXAoYSA9PiB0eXBlb2YgYSA9PT0gJ3N0cmluZycgPyBhIDogSlNPTi5zdHJpbmdpZnkoYSkpLmpvaW4oJyAnKSksXG4gIHdhcm46ICguLi5hcmdzKSA9PiBsb2dzLnB1c2goJ1t3YXJuXSAnICsgYXJncy5tYXAoYSA9PiB0eXBlb2YgYSA9PT0gJ3N0cmluZycgPyBhIDogSlNPTi5zdHJpbmdpZnkoYSkpLmpvaW4oJyAnKSksXG59O1xuXG50cnkge1xuICBjb25zdCBBc3luY0Z1bmN0aW9uID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKGFzeW5jIGZ1bmN0aW9uKCkge30pLmNvbnN0cnVjdG9yO1xuICBjb25zdCBmbiA9IG5ldyBBc3luY0Z1bmN0aW9uKCdjdHgnLCAnY29uc29sZScsIGNvZGUpO1xuICBjb25zdCByZXN1bHQgPSBhd2FpdCBmbihjdHgsIGN1c3RvbUNvbnNvbGUpO1xuXG4gIGNvbnN0IG91dHB1dCA9IHsgc3VjY2VzczogdHJ1ZSwgcmVzdWx0OiByZXN1bHQgIT09IHVuZGVmaW5lZCA/IHJlc3VsdCA6IG51bGwgfTtcbiAgaWYgKGxvZ3MubGVuZ3RoID4gMCkgb3V0cHV0LmxvZ3MgPSBsb2dzO1xuICBwcm9jZXNzLnN0ZG91dC53cml0ZShKU09OLnN0cmluZ2lmeShvdXRwdXQpKTtcbn0gY2F0Y2ggKGVycikge1xuICBjb25zdCBvdXRwdXQgPSB7XG4gICAgc3VjY2VzczogZmFsc2UsXG4gICAgZXJyb3I6IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKSxcbiAgfTtcbiAgaWYgKGxvZ3MubGVuZ3RoID4gMCkgb3V0cHV0LmxvZ3MgPSBsb2dzO1xuICBwcm9jZXNzLnN0ZG91dC53cml0ZShKU09OLnN0cmluZ2lmeShvdXRwdXQpKTtcbn1cbmA7XG5cbi8qKlxuICogRXh0cmFjdHMgYSBwbGFpbiBKU09OIFNjaGVtYSBmcm9tIHdoYXRldmVyIGZvcm1hdCB0aGUgQUkgU0RLIHRvb2wgdXNlc1xuICogKFpvZCBzY2hlbWEsIEFJIFNESyB3cmFwcGVkIHNjaGVtYSwgb3IgcmF3IEpTT04gU2NoZW1hKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4dHJhY3RKc29uU2NoZW1hKFxuICBzY2hlbWE6IHVua25vd25cbik6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgbnVsbCB7XG4gIGlmICghc2NoZW1hIHx8IHR5cGVvZiBzY2hlbWEgIT09IFwib2JqZWN0XCIpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGlmIChcbiAgICBcIl9kZWZcIiBpbiBzY2hlbWEgJiZcbiAgICB0eXBlb2YgKHNjaGVtYSBhcyB7IF9kZWY6IHVua25vd24gfSkuX2RlZiA9PT0gXCJvYmplY3RcIlxuICApIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIHoudG9KU09OU2NoZW1hKHNjaGVtYSBhcyB6LlpvZFR5cGUpIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgY29uc3QgcyA9IHNjaGVtYSBhcyBSZWNvcmQ8c3RyaW5nIHwgc3ltYm9sLCB1bmtub3duPjtcbiAgaWYgKFN5bWJvbC5mb3IoXCJ2ZXJjZWwuYWkuc2NoZW1hXCIpIGluIHMgJiYgXCJqc29uU2NoZW1hXCIgaW4gcykge1xuICAgIHJldHVybiBzLmpzb25TY2hlbWEgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIH1cblxuICBpZiAoXCJ0eXBlXCIgaW4gcyB8fCBcInByb3BlcnRpZXNcIiBpbiBzKSB7XG4gICAgcmV0dXJuIHMgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIH1cblxuICByZXR1cm4gbnVsbDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGpzb25TY2hlbWFUb1RzKFxuICBzY2hlbWE6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICBpbmRlbnQgPSAwXG4pOiBzdHJpbmcge1xuICBpZiAoIXNjaGVtYSkge1xuICAgIHJldHVybiBcInVua25vd25cIjtcbiAgfVxuXG4gIGlmIChzY2hlbWEuZW51bSAmJiBBcnJheS5pc0FycmF5KHNjaGVtYS5lbnVtKSkge1xuICAgIHJldHVybiBzY2hlbWEuZW51bS5tYXAoKHYpID0+IEpTT04uc3RyaW5naWZ5KHYpKS5qb2luKFwiIHwgXCIpO1xuICB9XG5cbiAgaWYgKHNjaGVtYS5hbnlPZiAmJiBBcnJheS5pc0FycmF5KHNjaGVtYS5hbnlPZikpIHtcbiAgICByZXR1cm4gc2NoZW1hLmFueU9mXG4gICAgICAubWFwKChzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikgPT4ganNvblNjaGVtYVRvVHMocywgaW5kZW50KSlcbiAgICAgIC5qb2luKFwiIHwgXCIpO1xuICB9XG4gIGlmIChzY2hlbWEub25lT2YgJiYgQXJyYXkuaXNBcnJheShzY2hlbWEub25lT2YpKSB7XG4gICAgcmV0dXJuIHNjaGVtYS5vbmVPZlxuICAgICAgLm1hcCgoczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pID0+IGpzb25TY2hlbWFUb1RzKHMsIGluZGVudCkpXG4gICAgICAuam9pbihcIiB8IFwiKTtcbiAgfVxuXG4gIGNvbnN0IHR5cGUgPSBzY2hlbWEudHlwZSBhcyBzdHJpbmc7XG5cbiAgc3dpdGNoICh0eXBlKSB7XG4gICAgY2FzZSBcInN0cmluZ1wiOlxuICAgICAgcmV0dXJuIFwic3RyaW5nXCI7XG4gICAgY2FzZSBcIm51bWJlclwiOlxuICAgIGNhc2UgXCJpbnRlZ2VyXCI6XG4gICAgICByZXR1cm4gXCJudW1iZXJcIjtcbiAgICBjYXNlIFwiYm9vbGVhblwiOlxuICAgICAgcmV0dXJuIFwiYm9vbGVhblwiO1xuICAgIGNhc2UgXCJudWxsXCI6XG4gICAgICByZXR1cm4gXCJudWxsXCI7XG4gICAgY2FzZSBcImFycmF5XCI6IHtcbiAgICAgIGNvbnN0IGl0ZW1zID0gc2NoZW1hLml0ZW1zXG4gICAgICAgID8ganNvblNjaGVtYVRvVHMoc2NoZW1hLml0ZW1zIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+LCBpbmRlbnQpXG4gICAgICAgIDogXCJ1bmtub3duXCI7XG4gICAgICByZXR1cm4gYEFycmF5PCR7aXRlbXN9PmA7XG4gICAgfVxuICAgIGNhc2UgXCJvYmplY3RcIjoge1xuICAgICAgY29uc3QgcHJvcGVydGllcyA9IHNjaGVtYS5wcm9wZXJ0aWVzIGFzXG4gICAgICAgIHwgUmVjb3JkPHN0cmluZywgUmVjb3JkPHN0cmluZywgdW5rbm93bj4+XG4gICAgICAgIHwgdW5kZWZpbmVkO1xuICAgICAgaWYgKCFwcm9wZXJ0aWVzKSB7XG4gICAgICAgIHJldHVybiBcIlJlY29yZDxzdHJpbmcsIHVua25vd24+XCI7XG4gICAgICB9XG4gICAgICBjb25zdCByZXF1aXJlZCA9IG5ldyBTZXQoKHNjaGVtYS5yZXF1aXJlZCBhcyBzdHJpbmdbXSkgfHwgW10pO1xuICAgICAgY29uc3QgcGFkID0gXCIgIFwiLnJlcGVhdChpbmRlbnQgKyAxKTtcbiAgICAgIGNvbnN0IGNsb3NlUGFkID0gXCIgIFwiLnJlcGVhdChpbmRlbnQpO1xuICAgICAgY29uc3QgcHJvcHMgPSBPYmplY3QuZW50cmllcyhwcm9wZXJ0aWVzKS5tYXAoKFtrZXksIHZhbHVlXSkgPT4ge1xuICAgICAgICBjb25zdCBvcHQgPSByZXF1aXJlZC5oYXMoa2V5KSA/IFwiXCIgOiBcIj9cIjtcbiAgICAgICAgcmV0dXJuIGAke3BhZH0ke2tleX0ke29wdH06ICR7anNvblNjaGVtYVRvVHModmFsdWUsIGluZGVudCArIDEpfWA7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBge1xcbiR7cHJvcHMuam9pbihcIjtcXG5cIil9O1xcbiR7Y2xvc2VQYWR9fWA7XG4gICAgfVxuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gXCJ1bmtub3duXCI7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdlbmVyYXRlQ29udGV4dFR5cGVTdHJpbmcodG9vbHM6IFRvb2xTZXQpOiBzdHJpbmcge1xuICBjb25zdCBzaWdzOiBzdHJpbmdbXSA9IFtdO1xuXG4gIGZvciAoY29uc3QgW25hbWUsIHRdIG9mIE9iamVjdC5lbnRyaWVzKHRvb2xzKSkge1xuICAgIGNvbnN0IHJhdyA9IHQgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgY29uc3QgaW5wdXRTY2hlbWEgPSBleHRyYWN0SnNvblNjaGVtYShyYXcuaW5wdXRTY2hlbWEgPz8gcmF3LnBhcmFtZXRlcnMpO1xuICAgIGNvbnN0IG91dHB1dFNjaGVtYSA9IGV4dHJhY3RKc29uU2NoZW1hKHJhdy5vdXRwdXRTY2hlbWEpO1xuXG4gICAgY29uc3QgaW5wdXRUeXBlID0gaW5wdXRTY2hlbWEgPyBqc29uU2NoZW1hVG9UcyhpbnB1dFNjaGVtYSwgMikgOiBcInt9XCI7XG4gICAgY29uc3Qgb3V0cHV0VHlwZSA9IG91dHB1dFNjaGVtYVxuICAgICAgPyBqc29uU2NoZW1hVG9UcyhvdXRwdXRTY2hlbWEsIDIpXG4gICAgICA6IFwidW5rbm93blwiO1xuXG4gICAgc2lncy5wdXNoKGAgICAgJHtuYW1lfShpbnB1dDogJHtpbnB1dFR5cGV9KTogUHJvbWlzZTwke291dHB1dFR5cGV9PmApO1xuICB9XG5cbiAgcmV0dXJuIGB0eXBlIENvbnRleHQgPSB7XFxuICB0b29sczoge1xcbiR7c2lncy5qb2luKFwiO1xcblwiKX07XFxuICB9XFxufWA7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGV4ZWN1dGVJblNhbmRib3goe1xuICBjb2RlLFxuICBycGNEaXIsXG4gIGFib3J0Q29udHJvbGxlcixcbiAgc2FuZGJveCxcbiAgYXZhaWxhYmxlVG9vbHMsXG4gIG9uU3ViVG9vbENhbGwsXG4gIHRvb2xDb250ZXh0LFxufToge1xuICBjb2RlOiBzdHJpbmc7XG4gIHJwY0Rpcjogc3RyaW5nO1xuICBhYm9ydENvbnRyb2xsZXI6IEFib3J0Q29udHJvbGxlcjtcbiAgc2FuZGJveDogU2FuZGJveEluc3RhbmNlO1xuICBhdmFpbGFibGVUb29sczogVG9vbFNldDtcbiAgb25TdWJUb29sQ2FsbD86IE9uU3ViVG9vbENhbGw7XG4gIHRvb2xDb250ZXh0PzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG59KTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4ge1xuICBjb25zdCBta2RpclJlc3VsdCA9IGF3YWl0IHNhbmRib3guZXhlYyh7XG4gICAgY29tbWFuZDogXCJta2RpclwiLFxuICAgIGFyZ3M6IFtcIi1wXCIsIHJwY0Rpcl0sXG4gIH0pO1xuICBpZiAobWtkaXJSZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgIHJldHVybiB7IHN1Y2Nlc3M6IGZhbHNlLCBlcnJvcjogbWtkaXJSZXN1bHQubWVzc2FnZSB9O1xuICB9XG4gIGF3YWl0IG1rZGlyUmVzdWx0LnJlc3VsdDtcblxuICBhd2FpdCBzYW5kYm94LndyaXRlRmlsZXMoe1xuICAgIGZpbGVzOiBbXG4gICAgICB7IHBhdGg6IFwicnVubmVyLm1qc1wiLCBjb250ZW50OiBSVU5ORVJfU0NSSVBUIH0sXG4gICAgICB7IHBhdGg6IFwiY29kZS5qc1wiLCBjb250ZW50OiBjb2RlIH0sXG4gICAgICB7XG4gICAgICAgIHBhdGg6IFwidG9vbHMuanNvblwiLFxuICAgICAgICBjb250ZW50OiBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyhhdmFpbGFibGVUb29scykpLFxuICAgICAgfSxcbiAgICBdLFxuICAgIGRlc3RQYXRoOiBycGNEaXIsXG4gIH0pO1xuXG4gIGNvbnN0IG5vZGVNYWpvciA9IE51bWJlci5wYXJzZUludChwcm9jZXNzLnZlcnNpb25zLm5vZGUuc3BsaXQoXCIuXCIpWzBdLCAxMCk7XG4gIGNvbnN0IHBlcm1pc3Npb25GbGFnID1cbiAgICBub2RlTWFqb3IgPj0gMjIgPyBcIi0tcGVybWlzc2lvblwiIDogXCItLWV4cGVyaW1lbnRhbC1wZXJtaXNzaW9uXCI7XG5cbiAgY29uc3QgZXhlY1Jlc3VsdCA9IGF3YWl0IHNhbmRib3guZXhlYyh7XG4gICAgY29tbWFuZDogXCJub2RlXCIsXG4gICAgYXJnczogW1xuICAgICAgcGVybWlzc2lvbkZsYWcsXG4gICAgICBgLS1hbGxvdy1mcy1yZWFkPSR7cnBjRGlyfWAsXG4gICAgICBgLS1hbGxvdy1mcy13cml0ZT0ke3JwY0Rpcn1gLFxuICAgICAgYCR7cnBjRGlyfS9ydW5uZXIubWpzYCxcbiAgICBdLFxuICAgIHNpZ25hbDogYWJvcnRDb250cm9sbGVyLnNpZ25hbCxcbiAgfSk7XG5cbiAgaWYgKGV4ZWNSZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgIHJldHVybiB7IHN1Y2Nlc3M6IGZhbHNlLCBlcnJvcjogZXhlY1Jlc3VsdC5tZXNzYWdlIH07XG4gIH1cblxuICBjb25zdCBmYXRhbDogeyBlcnJvcjogRXJyb3IgfCBudWxsIH0gPSB7IGVycm9yOiBudWxsIH07XG5cbiAgY29uc3QgYWJvcnQgPSAoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgaWYgKCFmYXRhbC5lcnJvcikge1xuICAgICAgZmF0YWwuZXJyb3IgPSBlcnJvcjtcbiAgICAgIGFib3J0Q29udHJvbGxlci5hYm9ydCgpO1xuICAgIH1cbiAgfTtcblxuICBjb25zdCBoYW5kbGVUb29sUmVxdWVzdCA9IGFzeW5jIChyZXF1ZXN0SnNvbjogc3RyaW5nKSA9PiB7XG4gICAgbGV0IHBhcnNlZDogeyBpZDogc3RyaW5nOyB0b29sOiBzdHJpbmc7IGlucHV0OiB1bmtub3duIH07XG4gICAgdHJ5IHtcbiAgICAgIHBhcnNlZCA9IEpTT04ucGFyc2UocmVxdWVzdEpzb24pO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHsgaWQsIHRvb2w6IHRvb2xOYW1lLCBpbnB1dCB9ID0gcGFyc2VkO1xuXG4gICAgbGV0IHJlc3BvbnNlOiB7IHJlc3VsdD86IHVua25vd247IGVycm9yPzogc3RyaW5nIH07XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHQgPSBhdmFpbGFibGVUb29sc1t0b29sTmFtZV07XG4gICAgICBpZiAoIXQ/LmV4ZWN1dGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBUb29sICR7dG9vbE5hbWV9IG5vdCBmb3VuZCBvciBoYXMgbm8gZXhlY3V0ZSBmdW5jdGlvbmBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGV4ZWMgPSB0LmV4ZWN1dGUuYmluZCh0KTtcbiAgICAgIGNvbnN0IGV4ZWNPcHRpb25zID0ge1xuICAgICAgICB0b29sQ2FsbElkOiBganNfJHt0b29sTmFtZX1fJHtEYXRlLm5vdygpfWAsXG4gICAgICAgIG1lc3NhZ2VzOiBbXSxcbiAgICAgICAgZXhwZXJpbWVudGFsX2NvbnRleHQ6IHRvb2xDb250ZXh0LFxuICAgICAgfTtcbiAgICAgIGlmIChvblN1YlRvb2xDYWxsKSB7XG4gICAgICAgIHJlc3BvbnNlID0gYXdhaXQgb25TdWJUb29sQ2FsbCh0b29sTmFtZSwgaW5wdXQsICgpID0+XG4gICAgICAgICAgZXhlYyhpbnB1dCwgZXhlY09wdGlvbnMpXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBleGVjKGlucHV0LCBleGVjT3B0aW9ucyk7XG4gICAgICAgIHJlc3BvbnNlID0geyByZXN1bHQgfTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGNvbnN0IG1zZyA9IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKTtcbiAgICAgIHJlc3BvbnNlID0geyBlcnJvcjogbXNnIH07XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHNhbmRib3gud3JpdGVGaWxlcyh7XG4gICAgICAgIGZpbGVzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgcGF0aDogYCR7aWR9LnJlc3BvbnNlLmpzb25gLFxuICAgICAgICAgICAgY29udGVudDogSlNPTi5zdHJpbmdpZnkocmVzcG9uc2UpLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICAgIGRlc3RQYXRoOiBycGNEaXIsXG4gICAgICB9KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIC8qKlxuICAgICAgICogSWYgd3JpdGluZyB0aGUgcmVzcG9uc2UgZmlsZSBmYWlscywgdGhlIHJ1bm5lciB3aWxsIHBvbGwgZm9yZXZlclxuICAgICAgICogd2FpdGluZyBmb3IgaXQuIEFib3J0IHRoZSBydW5uZXIgcHJvY2VzcyBzbyB3ZSBkb24ndCBkZWFkbG9jay5cbiAgICAgICAqL1xuICAgICAgY29uc3QgbXNnID0gZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpO1xuICAgICAgYWJvcnQobmV3IEVycm9yKGBGYWlsZWQgdG8gd3JpdGUgUlBDIHJlc3BvbnNlIGZvciAke3Rvb2xOYW1lfTogJHttc2d9YCkpO1xuICAgIH1cbiAgfTtcblxuICBjb25zdCB0b29sQ2FsbFByb21pc2VzOiBQcm9taXNlPHZvaWQ+W10gPSBbXTtcbiAgbGV0IHN0ZGVyckJ1ZmZlciA9IFwiXCI7XG4gIGxldCBub25NYXJrZXJTdGRlcnIgPSBcIlwiO1xuXG4gIGNvbnN0IHRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICBhYm9ydChcbiAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgYEphdmFTY3JpcHQgZXhlY3V0aW9uIHRpbWVkIG91dCBhZnRlciAke0VYRUNVVElPTl9USU1FT1VUX01TIC8gMTAwMH1zYFxuICAgICAgKVxuICAgICk7XG4gIH0sIEVYRUNVVElPTl9USU1FT1VUX01TKTtcblxuICB0cnkge1xuICAgIGZvciBhd2FpdCAoY29uc3QgZW50cnkgb2YgZXhlY1Jlc3VsdC5sb2dzKCkpIHtcbiAgICAgIGlmIChmYXRhbC5lcnJvcikge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgaWYgKGVudHJ5LnN0cmVhbSA9PT0gXCJzdGRlcnJcIikge1xuICAgICAgICBzdGRlcnJCdWZmZXIgKz0gZW50cnkuZGF0YTtcblxuICAgICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICAgIGNvbnN0IHN0YXJ0SWR4ID0gc3RkZXJyQnVmZmVyLmluZGV4T2YoUkVRVUVTVF9NQVJLRVJfU1RBUlQpO1xuICAgICAgICAgIGlmIChzdGFydElkeCA9PT0gLTEpIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IGJlZm9yZU1hcmtlciA9IHN0ZGVyckJ1ZmZlci5zbGljZSgwLCBzdGFydElkeCk7XG4gICAgICAgICAgaWYgKGJlZm9yZU1hcmtlci50cmltKCkpIHtcbiAgICAgICAgICAgIG5vbk1hcmtlclN0ZGVyciArPSBiZWZvcmVNYXJrZXI7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgY29udGVudFN0YXJ0ID0gc3RhcnRJZHggKyBSRVFVRVNUX01BUktFUl9TVEFSVC5sZW5ndGg7XG4gICAgICAgICAgY29uc3QgZW5kSWR4ID0gc3RkZXJyQnVmZmVyLmluZGV4T2YoUkVRVUVTVF9NQVJLRVJfRU5ELCBjb250ZW50U3RhcnQpO1xuICAgICAgICAgIGlmIChlbmRJZHggPT09IC0xKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCByZXF1ZXN0SnNvbiA9IHN0ZGVyckJ1ZmZlci5zbGljZShjb250ZW50U3RhcnQsIGVuZElkeCk7XG4gICAgICAgICAgc3RkZXJyQnVmZmVyID0gc3RkZXJyQnVmZmVyLnNsaWNlKGVuZElkeCArIFJFUVVFU1RfTUFSS0VSX0VORC5sZW5ndGgpO1xuXG4gICAgICAgICAgdG9vbENhbGxQcm9taXNlcy5wdXNoKGhhbmRsZVRvb2xSZXF1ZXN0KHJlcXVlc3RKc29uKSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH0gZmluYWxseSB7XG4gICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuICB9XG5cbiAgaWYgKHN0ZGVyckJ1ZmZlci50cmltKCkpIHtcbiAgICBub25NYXJrZXJTdGRlcnIgKz0gc3RkZXJyQnVmZmVyO1xuICB9XG5cbiAgYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKHRvb2xDYWxsUHJvbWlzZXMpO1xuXG4gIGlmIChmYXRhbC5lcnJvcikge1xuICAgIGV4ZWNSZXN1bHQucmVzdWx0LmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgZXJyb3I6IGZhdGFsLmVycm9yLm1lc3NhZ2UsXG4gICAgICAuLi4obm9uTWFya2VyU3RkZXJyID8geyBzdGRlcnI6IG5vbk1hcmtlclN0ZGVyci5zbGljZSgwLCAyMDAwKSB9IDoge30pLFxuICAgIH07XG4gIH1cblxuICBjb25zdCB7IHN0ZG91dCwgc3RkZXJyLCBleGl0Q29kZSB9ID0gYXdhaXQgZXhlY1Jlc3VsdC5yZXN1bHQ7XG5cbiAgdHJ5IHtcbiAgICByZXR1cm4gSlNPTi5wYXJzZShzdGRvdXQpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4ge1xuICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICBlcnJvcjogYFJ1bm5lciBmYWlsZWQgKGV4aXQgJHtleGl0Q29kZX0pLmAsXG4gICAgICBzdGRlcnI6IChub25NYXJrZXJTdGRlcnIgKyBzdGRlcnIpLnNsaWNlKDAsIDIwMDApLFxuICAgICAgc3Rkb3V0OiBzdGRvdXQuc2xpY2UoMCwgMTAwMCksXG4gICAgfTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlSmF2YVNjcmlwdFRvb2wob3B0czoge1xuICB0b29sczogVG9vbFNldDtcbiAgc2FuZGJveDogU2FuZGJveEluc3RhbmNlO1xuICBhY3RpdmVUb29scz86IHN0cmluZ1tdO1xuICBvblN1YlRvb2xDYWxsPzogT25TdWJUb29sQ2FsbDtcbiAgdG9vbENvbnRleHQ/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbn0pIHtcbiAgY29uc3QgeyBzYW5kYm94LCBvblN1YlRvb2xDYWxsIH0gPSBvcHRzO1xuICBjb25zdCBhY3RpdmVTZXQgPSBvcHRzLmFjdGl2ZVRvb2xzID8gbmV3IFNldChvcHRzLmFjdGl2ZVRvb2xzKSA6IG51bGw7XG4gIGNvbnN0IGF2YWlsYWJsZVRvb2xzOiBUb29sU2V0ID0ge307XG4gIGZvciAoY29uc3QgW25hbWUsIHRdIG9mIE9iamVjdC5lbnRyaWVzKG9wdHMudG9vbHMpKSB7XG4gICAgaWYgKCFhY3RpdmVTZXQgfHwgYWN0aXZlU2V0LmhhcyhuYW1lKSkge1xuICAgICAgYXZhaWxhYmxlVG9vbHNbbmFtZV0gPSB0O1xuICAgIH1cbiAgfVxuICBjb25zdCBjb250ZXh0VHlwZSA9IGdlbmVyYXRlQ29udGV4dFR5cGVTdHJpbmcoYXZhaWxhYmxlVG9vbHMpO1xuXG4gIHJldHVybiB0b29sKHtcbiAgICAuLi5idWlsdEluVG9vbHMuSmF2YVNjcmlwdCxcbiAgICBkZXNjcmlwdGlvbjogYEV4ZWN1dGUgSmF2YVNjcmlwdCB0byBvcmNoZXN0cmF0ZSBtdWx0aXBsZSB0b29sIGNhbGxzIGluIGEgc2luZ2xlIHN0ZXAuIFVzZSB0aGlzIHdoZW4geW91IG5lZWQgdG8gcnVuIHNldmVyYWwgdG9vbHMgaW4gc2VxdWVuY2UsIHRyYW5zZm9ybSBpbnRlcm1lZGlhdGUgcmVzdWx0cywgb3IgcGFyYWxsZWxpemUgaW5kZXBlbmRlbnQgb3BlcmF0aW9ucyB3aXRoIFByb21pc2UuYWxsLlxuXG5UaGUgY29kZSBydW5zIGFzIGFuIGFzeW5jIGZ1bmN0aW9uIGJvZHkgd2l0aCBcXGBjdHhcXGAgaW4gc2NvcGU6XG5cblxcYFxcYFxcYHR5cGVzY3JpcHRcbiR7Y29udGV4dFR5cGV9XG5cXGBcXGBcXGBcblxuRXhhbXBsZXM6XG4tIFNlcXVlbnRpYWw6IFxcYGNvbnN0IGZpbGUgPSBhd2FpdCBjdHgudG9vbHMuUmVhZCh7IHBhdGg6IFwicGFja2FnZS5qc29uXCIgfSk7IHJldHVybiBKU09OLnBhcnNlKGZpbGUuY29udGVudCk7XFxgXG4tIFBhcmFsbGVsOiBcXGBjb25zdCBbYSwgYl0gPSBhd2FpdCBQcm9taXNlLmFsbChbY3R4LnRvb2xzLlJlYWQoeyBwYXRoOiBcImEudHNcIiB9KSwgY3R4LnRvb2xzLlJlYWQoeyBwYXRoOiBcImIudHNcIiB9KV0pOyByZXR1cm4geyBhOiBhLmNvbnRlbnQsIGI6IGIuY29udGVudCB9O1xcYFxuLSBUcmFuc2Zvcm06IFxcYGNvbnN0IGdyZXAgPSBhd2FpdCBjdHgudG9vbHMuR3JlcCh7IHBhdHRlcm46IFwiVE9ET1wiIH0pOyByZXR1cm4gZ3JlcC5tYXRjaGVzLnNwbGl0KFwiXFxcXG5cIikubGVuZ3RoO1xcYFxuLSBCYXNoOiBcXGBjb25zdCByID0gYXdhaXQgY3R4LnRvb2xzLkJhc2goeyBjb21tYW5kOiBcIm5vZGUgLWUgXFxcXFwiY29uc29sZS5sb2coSlNPTi5zdHJpbmdpZnkoe3Y6MX0pKVxcXFxcIlwiIH0pOyByZXR1cm4gSlNPTi5wYXJzZShyLnN0ZG91dCk7XFxgXG5cblJldHVybiBhIHZhbHVlIHRvIHBhc3MgcmVzdWx0cyBiYWNrLiBVc2UgY29uc29sZS5sb2coKSBmb3IgZGVidWcgb3V0cHV0LlxuSW1wb3J0YW50OiBFYWNoIHRvb2wgcmV0dXJucyBhIHN0cnVjdHVyZWQgb2JqZWN0IG1hdGNoaW5nIGl0cyBvdXRwdXQgc2NoZW1hIFx1MjAxNCBub3QgYSByYXcgc3RyaW5nLiBBY2Nlc3MgdGhlIHNwZWNpZmljIGZpZWxkIHlvdSBuZWVkIChlLmcuIEJhc2gncyByZXN1bHQuc3Rkb3V0LCBSZWFkJ3MgcmVzdWx0LmNvbnRlbnQpIHJhdGhlciB0aGFuIHRyeWluZyB0byBwYXJzZSB0aGUgZW50aXJlIHJlc3VsdC5gLFxuICAgIGV4ZWN1dGU6ICh7IGNvZGUgfSkgPT4ge1xuICAgICAgY29uc3QgcnVuSWQgPSBgcnVuXyR7RGF0ZS5ub3coKX1fJHtNYXRoLnJhbmRvbSgpXG4gICAgICAgIC50b1N0cmluZygzNilcbiAgICAgICAgLnNsaWNlKDIsIDgpfWA7XG4gICAgICBjb25zdCBycGNEaXIgPSBgLmFnZW50L2pzLXJwYy8ke3J1bklkfWA7XG4gICAgICBjb25zdCBhYm9ydENvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG5cbiAgICAgIHJldHVybiBleGVjdXRlSW5TYW5kYm94KHtcbiAgICAgICAgY29kZSxcbiAgICAgICAgcnBjRGlyLFxuICAgICAgICBhYm9ydENvbnRyb2xsZXIsXG4gICAgICAgIHNhbmRib3gsXG4gICAgICAgIGF2YWlsYWJsZVRvb2xzLFxuICAgICAgICBvblN1YlRvb2xDYWxsLFxuICAgICAgICB0b29sQ29udGV4dDogb3B0cy50b29sQ29udGV4dCxcbiAgICAgIH0pO1xuICAgIH0sXG4gIH0pO1xufVxuIiwgImltcG9ydCB0eXBlIHsgVG9vbCB9IGZyb20gXCJhaVwiO1xuaW1wb3J0IHR5cGUgeyBBbnlBZ2VudCB9IGZyb20gXCIuLi9hZ2VudC9jbGllbnRcIjtcbmltcG9ydCB0eXBlIHsgQnVpbHRJblRvb2xOYW1lIH0gZnJvbSBcIi4vaW5kZXhcIjtcblxuLyoqIEJ1aWx0LWluIGRlZmF1bHRzIGZvciBuZWVkc0FwcHJvdmFsICh1c2VyIGNhbiBvdmVycmlkZSB2aWEgYWdlbnQgY29uZmlnKS4gKi9cbmNvbnN0IGJ1aWx0aW5OZWVkc0FwcHJvdmFsOiBQYXJ0aWFsPFJlY29yZDxCdWlsdEluVG9vbE5hbWUsIGJvb2xlYW4+PiA9IHt9O1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY2hlY2tOZWVkc0FwcHJvdmFsKHtcbiAgYWdlbnQsXG4gIHRvb2xOYW1lLFxuICBpbnB1dCxcbiAgdG9vbENhbGxJZCxcbiAgbWVzc2FnZXMsXG59OiB7XG4gIGFnZW50OiBBbnlBZ2VudDtcbiAgdG9vbE5hbWU6IHN0cmluZztcbiAgaW5wdXQ6IHVua25vd247XG4gIHRvb2xDYWxsSWQ6IHN0cmluZztcbiAgbWVzc2FnZXM6IHVua25vd25bXTtcbn0pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgLy8gMS4gUGVyLXRvb2wgbmVlZHNBcHByb3ZhbCBvbiB0aGUgVG9vbCBkZWZpbml0aW9uIHRha2VzIHByaW9yaXR5XG4gIGNvbnN0IHRvb2xEZWYgPSBhZ2VudC5vcHRpb25zLnRvb2xzPy5bdG9vbE5hbWVdIGFzIFRvb2wgfCB1bmRlZmluZWQ7XG4gIGlmICh0b29sRGVmPy5uZWVkc0FwcHJvdmFsICE9IG51bGwpIHtcbiAgICBpZiAodHlwZW9mIHRvb2xEZWYubmVlZHNBcHByb3ZhbCA9PT0gXCJib29sZWFuXCIpIHtcbiAgICAgIHJldHVybiB0b29sRGVmLm5lZWRzQXBwcm92YWw7XG4gICAgfVxuICAgIHJldHVybiBhd2FpdCB0b29sRGVmLm5lZWRzQXBwcm92YWwoaW5wdXQsIHtcbiAgICAgIHRvb2xDYWxsSWQsXG4gICAgICBtZXNzYWdlczogbWVzc2FnZXMgYXMgbmV2ZXJbXSxcbiAgICAgIGV4cGVyaW1lbnRhbF9jb250ZXh0OiB1bmRlZmluZWQsXG4gICAgfSk7XG4gIH1cblxuICAvLyAyLiBBZ2VudC1sZXZlbCBuZWVkc0FwcHJvdmFsIG1hcFxuICBjb25zdCBhZ2VudEVudHJ5ID0gKFxuICAgIGFnZW50Lm9wdGlvbnMubmVlZHNBcHByb3ZhbCBhc1xuICAgICAgfCBSZWNvcmQ8XG4gICAgICAgICAgc3RyaW5nLFxuICAgICAgICAgIGJvb2xlYW4gfCAoKC4uLmFyZ3M6IHVua25vd25bXSkgPT4gYm9vbGVhbiB8IFByb21pc2U8Ym9vbGVhbj4pXG4gICAgICAgID5cbiAgICAgIHwgdW5kZWZpbmVkXG4gICk/Llt0b29sTmFtZV07XG5cbiAgaWYgKGFnZW50RW50cnkgIT0gbnVsbCkge1xuICAgIGlmICh0eXBlb2YgYWdlbnRFbnRyeSA9PT0gXCJib29sZWFuXCIpIHtcbiAgICAgIHJldHVybiBhZ2VudEVudHJ5O1xuICAgIH1cbiAgICByZXR1cm4gYXdhaXQgYWdlbnRFbnRyeShpbnB1dCwge1xuICAgICAgdG9vbENhbGxJZCxcbiAgICAgIG1lc3NhZ2VzLFxuICAgICAgZXhwZXJpbWVudGFsX2NvbnRleHQ6IHVuZGVmaW5lZCxcbiAgICB9KTtcbiAgfVxuXG4gIC8vIDMuIEJ1aWx0LWluIGRlZmF1bHRzXG4gIHJldHVybiBidWlsdGluTmVlZHNBcHByb3ZhbFt0b29sTmFtZSBhcyBCdWlsdEluVG9vbE5hbWVdID8/IGZhbHNlO1xufVxuIiwgImltcG9ydCB7XG4gIHRvb2wgYXMgYWlUb29sLFxuICB0eXBlIFRvb2wsXG4gIHR5cGUgVG9vbEV4ZWN1dGlvbk9wdGlvbnMsXG4gIHR5cGUgVUlNZXNzYWdlLFxufSBmcm9tIFwiYWlcIjtcbmltcG9ydCB0eXBlIHsgeiB9IGZyb20gXCJ6b2RcIjtcbmltcG9ydCB0eXBlIHsgU2FuZGJveEluc3RhbmNlIH0gZnJvbSBcIi4uL3NhbmRib3gvYWRhcHRlclwiO1xuaW1wb3J0IHR5cGUgeyBUb29sQ29udGV4dCB9IGZyb20gXCIuL2luZGV4XCI7XG5cbi8qKlxuICogRGVmaW5lIGFuIGFnZW50IHRvb2wgd2l0aCB0eXBlZCBjb250ZXh0IGFuZCBzdGF0ZS5cbiAqXG4gKiBQYXNzIHRoZSBzYW1lIGBjb250ZXh0U2NoZW1hYCBhbmQvb3IgYHN0YXRlU2NoZW1hYCAoWm9kIG9iamVjdHMpIHVzZWQgaW5cbiAqIHlvdXIgYWdlbnQgZGVmaW5pdGlvbiB0byBnZXQgdHlwZWQgYGNvbnRleHRgIGFuZCBgc3RhdGVgIGluc2lkZSBgZXhlY3V0ZWAuXG4gKlxuICogYGBgdHNcbiAqIGltcG9ydCB7IHRvb2wgfSBmcm9tIFwiZXhwZXJpbWVudGFsLWFnZW50XCI7XG4gKiBpbXBvcnQgeyBjb250ZXh0U2NoZW1hLCBzdGF0ZVNjaGVtYSB9IGZyb20gXCIuL2NvbnRleHRcIjtcbiAqXG4gKiBleHBvcnQgY29uc3QgTXlUb29sID0gdG9vbCh7XG4gKiAgIGNvbnRleHRTY2hlbWEsXG4gKiAgIHN0YXRlU2NoZW1hLFxuICogICBpbnB1dFNjaGVtYTogei5vYmplY3QoeyBxdWVyeTogei5zdHJpbmcoKSB9KSxcbiAqICAgZXhlY3V0ZTogYXN5bmMgKHsgcXVlcnkgfSwgeyBjb250ZXh0LCBzdGF0ZSwgc2FuZGJveCB9KSA9PiB7XG4gKiAgICAgY29udGV4dC5jaGFubmVsSWQgLy8gXHUyNzEzIHR5cGVkIGZyb20gY29udGV4dFNjaGVtYVxuICogICAgIHN0YXRlLmNvdW50ZXIrKyAgIC8vIFx1MjcxMyB0eXBlZCBmcm9tIHN0YXRlU2NoZW1hLCBtdXRhYmxlXG4gKiAgIH0sXG4gKiB9KTtcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gdG9vbDxcbiAgVElucHV0U2NoZW1hIGV4dGVuZHMgei5ab2RUeXBlLFxuICBUQ29udGV4dFNjaGVtYSBleHRlbmRzIHouWm9kVHlwZSA9IHouWm9kVHlwZTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4sXG4gIFRTdGF0ZVNjaGVtYSBleHRlbmRzIHouWm9kVHlwZSA9IHouWm9kVHlwZTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4sXG4gIC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogZGVmYXVsdCBlcmFzZWRcbiAgVE91dHB1dFNjaGVtYSBleHRlbmRzIHouWm9kVHlwZSA9IHouWm9kVHlwZTxhbnk+LFxuPihkZWY6IHtcbiAgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG4gIGlucHV0U2NoZW1hOiBUSW5wdXRTY2hlbWE7XG4gIG91dHB1dFNjaGVtYT86IFRPdXRwdXRTY2hlbWE7XG4gIGNvbnRleHRTY2hlbWE/OiBUQ29udGV4dFNjaGVtYTtcbiAgc3RhdGVTY2hlbWE/OiBUU3RhdGVTY2hlbWE7XG4gIGV4ZWN1dGU/OiAoXG4gICAgaW5wdXQ6IHouaW5mZXI8VElucHV0U2NoZW1hPixcbiAgICBvcHRpb25zOiBUb29sQ29udGV4dDx6LmluZmVyPFRDb250ZXh0U2NoZW1hPiwgei5pbmZlcjxUU3RhdGVTY2hlbWE+PiAmIHtcbiAgICAgIHRvb2xDYWxsSWQ6IHN0cmluZztcbiAgICAgIGFib3J0U2lnbmFsOiBBYm9ydFNpZ25hbDtcbiAgICB9XG4gICAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiBleGVjdXRlIGNhbiByZXR1cm4gYW55dGhpbmdcbiAgKSA9PiBhbnk7XG4gIC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogZXJhc2VkIHRvb2wgZ2VuZXJpY3Ncbn0pOiBUb29sPGFueSwgYW55PiB7XG4gIGNvbnN0IHsgZXhlY3V0ZSwgY29udGV4dFNjaGVtYSwgc3RhdGVTY2hlbWEsIC4uLnJlc3QgfSA9IGRlZjtcblxuICBjb25zdCB3cmFwcGVkRXhlY3V0ZSA9IGV4ZWN1dGVcbiAgICA/IC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogaW5wdXQgdHlwZSBlcmFzZWQgYXQgcnVudGltZVxuICAgICAgKGlucHV0OiBhbnksIG9wdGlvbnM6IFRvb2xFeGVjdXRpb25PcHRpb25zKSA9PiB7XG4gICAgICAgIGNvbnN0IGN0eCA9IG9wdGlvbnMuZXhwZXJpbWVudGFsX2NvbnRleHQgYXMge1xuICAgICAgICAgIGNvbnRleHQ6IHVua25vd247XG4gICAgICAgICAgc3RhdGU6IHVua25vd247XG4gICAgICAgICAgc2Vzc2lvbklkOiBzdHJpbmc7XG4gICAgICAgICAgbWVzc2FnZXM6IFVJTWVzc2FnZVtdO1xuICAgICAgICAgIHNhbmRib3g6IFNhbmRib3hJbnN0YW5jZTtcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBjb250ZXh0ID0gKFxuICAgICAgICAgIGNvbnRleHRTY2hlbWEgPyBjb250ZXh0U2NoZW1hLnBhcnNlKGN0eC5jb250ZXh0KSA6IGN0eC5jb250ZXh0XG4gICAgICAgICkgYXMgei5pbmZlcjxUQ29udGV4dFNjaGVtYT47XG5cbiAgICAgICAgaWYgKHN0YXRlU2NoZW1hKSB7XG4gICAgICAgICAgc3RhdGVTY2hlbWEucGFyc2UoY3R4LnN0YXRlKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBzdGF0ZSA9IGN0eC5zdGF0ZSBhcyB6LmluZmVyPFRTdGF0ZVNjaGVtYT47XG5cbiAgICAgICAgcmV0dXJuIGV4ZWN1dGUoaW5wdXQsIHtcbiAgICAgICAgICB0b29sQ2FsbElkOiBvcHRpb25zLnRvb2xDYWxsSWQsXG4gICAgICAgICAgYWJvcnRTaWduYWw6IG9wdGlvbnMuYWJvcnRTaWduYWwhLFxuICAgICAgICAgIGNvbnRleHQsXG4gICAgICAgICAgc3RhdGUsXG4gICAgICAgICAgc2Vzc2lvbklkOiBjdHguc2Vzc2lvbklkLFxuICAgICAgICAgIG1lc3NhZ2VzOiBjdHgubWVzc2FnZXMsXG4gICAgICAgICAgc2FuZGJveDogY3R4LnNhbmRib3gsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIDogdW5kZWZpbmVkO1xuXG4gIHJldHVybiB3cmFwcGVkRXhlY3V0ZVxuICAgID8gYWlUb29sKHsgLi4ucmVzdCwgZXhlY3V0ZTogd3JhcHBlZEV4ZWN1dGUgfSlcbiAgICA6IC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogbm8tZXhlY3V0ZSBwYXRoIG5lZWRzIGNhc3RcbiAgICAgIGFpVG9vbChyZXN0IGFzIGFueSk7XG59XG4iLCAiaW1wb3J0IHR5cGUgeyBKU09OVmFsdWUsIE1vZGVsTWVzc2FnZSB9IGZyb20gXCJhaVwiO1xuXG50eXBlIFByb3ZpZGVyT3B0aW9ucyA9IFJlY29yZDxzdHJpbmcsIFJlY29yZDxzdHJpbmcsIEpTT05WYWx1ZT4+O1xuXG5jb25zdCBBTlRIUk9QSUNfTUFYX0NBQ0hFX0JSRUFLUE9JTlRTX1BFUl9SRVFVRVNUID0gNDtcblxuY29uc3QgQ0xBVURFX0xJS0VfTU9ERUxfTUFUQ0hFUlMgPSBbXCJjbGF1ZGVcIiwgXCJhbnRocm9waWNcIl07XG5cbmNvbnN0IENMQVVERV9QUk9NUFRfQ0FDSElOR19QUk9WSURFUl9PUFRJT05TOiBQcm92aWRlck9wdGlvbnMgPSB7XG4gIGFudGhyb3BpYzoge1xuICAgIGNhY2hlQ29udHJvbDogeyB0eXBlOiBcImVwaGVtZXJhbFwiIH0sXG4gIH0sXG4gIG9wZW5yb3V0ZXI6IHtcbiAgICBjYWNoZUNvbnRyb2w6IHsgdHlwZTogXCJlcGhlbWVyYWxcIiB9LFxuICB9LFxuICBiZWRyb2NrOiB7XG4gICAgY2FjaGVQb2ludDogeyB0eXBlOiBcImRlZmF1bHRcIiB9LFxuICB9LFxuICBvcGVuYWlDb21wYXRpYmxlOiB7XG4gICAgY2FjaGVfY29udHJvbDogeyB0eXBlOiBcImVwaGVtZXJhbFwiIH0sXG4gIH0sXG4gIGNvcGlsb3Q6IHtcbiAgICBjb3BpbG90X2NhY2hlX2NvbnRyb2w6IHsgdHlwZTogXCJlcGhlbWVyYWxcIiB9LFxuICB9LFxufTtcblxuZnVuY3Rpb24gZ2V0R2F0ZXdheVByb3ZpZGVyKG1vZGVsOiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsIHtcbiAgY29uc3Qgc2xhc2hJbmRleCA9IG1vZGVsLmluZGV4T2YoXCIvXCIpO1xuICBpZiAoc2xhc2hJbmRleCA9PT0gLTEpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICByZXR1cm4gbW9kZWwuc2xpY2UoMCwgc2xhc2hJbmRleCk7XG59XG5cbmZ1bmN0aW9uIGNvdW50QW50aHJvcGljQ2FjaGVCcmVha3BvaW50cyhtZXNzYWdlczogTW9kZWxNZXNzYWdlW10pOiBudW1iZXIge1xuICBsZXQgY291bnQgPSAwO1xuICBmb3IgKGNvbnN0IG1lc3NhZ2Ugb2YgbWVzc2FnZXMpIHtcbiAgICBjb25zdCBwcm92aWRlck9wdGlvbnMgPSAobWVzc2FnZSBhcyB7IHByb3ZpZGVyT3B0aW9ucz86IFByb3ZpZGVyT3B0aW9ucyB9KVxuICAgICAgLnByb3ZpZGVyT3B0aW9ucztcbiAgICBpZiAocHJvdmlkZXJPcHRpb25zPy5hbnRocm9waWM/LmNhY2hlQ29udHJvbCkge1xuICAgICAgY291bnQgKz0gMTtcbiAgICB9XG4gICAgaWYgKEFycmF5LmlzQXJyYXkobWVzc2FnZS5jb250ZW50KSkge1xuICAgICAgZm9yIChjb25zdCBwYXJ0IG9mIG1lc3NhZ2UuY29udGVudCkge1xuICAgICAgICBjb25zdCBwYXJ0UHJvdmlkZXJPcHRpb25zID0gKFxuICAgICAgICAgIHBhcnQgYXMgeyBwcm92aWRlck9wdGlvbnM/OiBQcm92aWRlck9wdGlvbnMgfVxuICAgICAgICApLnByb3ZpZGVyT3B0aW9ucztcbiAgICAgICAgaWYgKHBhcnRQcm92aWRlck9wdGlvbnM/LmFudGhyb3BpYz8uY2FjaGVDb250cm9sKSB7XG4gICAgICAgICAgY291bnQgKz0gMTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gY291bnQ7XG59XG5cbmZ1bmN0aW9uIGlzQ2xhdWRlTGlrZU1vZGVsKG1vZGVsOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgY29uc3QgbG93ZXIgPSBtb2RlbC50b0xvd2VyQ2FzZSgpO1xuICByZXR1cm4gQ0xBVURFX0xJS0VfTU9ERUxfTUFUQ0hFUlMuc29tZSgobSkgPT4gbG93ZXIuaW5jbHVkZXMobSkpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbWVyZ2VQcm92aWRlck9wdGlvbnMob3B0czoge1xuICBjdXJyZW50OiBQcm92aWRlck9wdGlvbnMgfCB1bmRlZmluZWQ7XG4gIHBhdGNoOiBQcm92aWRlck9wdGlvbnM7XG59KTogUHJvdmlkZXJPcHRpb25zIHtcbiAgY29uc3QgbmV4dDogUHJvdmlkZXJPcHRpb25zID0geyAuLi4ob3B0cy5jdXJyZW50ID8/IHt9KSB9O1xuICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhvcHRzLnBhdGNoKSkge1xuICAgIG5leHRba2V5XSA9IHsgLi4uKG5leHRba2V5XSA/PyB7fSksIC4uLnZhbHVlIH07XG4gIH1cbiAgcmV0dXJuIG5leHQ7XG59XG5cbmZ1bmN0aW9uIGlzQ2FjaGVhYmxlQ2xhdWRlUGFydChwYXJ0OiB1bmtub3duKTogYm9vbGVhbiB7XG4gIGlmICghcGFydCB8fCB0eXBlb2YgcGFydCAhPT0gXCJvYmplY3RcIikge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmIChcInR5cGVcIiBpbiBwYXJ0ICYmIChwYXJ0IGFzIHsgdHlwZT86IHVua25vd24gfSkudHlwZSA9PT0gXCJ0ZXh0XCIpIHtcbiAgICBjb25zdCB0ZXh0ID0gKHBhcnQgYXMgeyB0ZXh0PzogdW5rbm93biB9KS50ZXh0O1xuICAgIGlmICh0eXBlb2YgdGV4dCA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgcmV0dXJuIHRleHQudHJpbSgpLmxlbmd0aCA+IDA7XG4gICAgfVxuICB9XG5cbiAgaWYgKFwidHlwZVwiIGluIHBhcnQpIHtcbiAgICBjb25zdCB0eXBlID0gKHBhcnQgYXMgeyB0eXBlPzogdW5rbm93biB9KS50eXBlO1xuICAgIGlmICh0eXBlID09PSBcInRoaW5raW5nXCIgfHwgdHlwZSA9PT0gXCJyZWFzb25pbmdcIikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBoYXNDYWNoZWFibGVDb250ZW50KG1lc3NhZ2U6IE1vZGVsTWVzc2FnZSk6IGJvb2xlYW4ge1xuICBpZiAodHlwZW9mIG1lc3NhZ2UuY29udGVudCA9PT0gXCJzdHJpbmdcIikge1xuICAgIHJldHVybiBtZXNzYWdlLmNvbnRlbnQudHJpbSgpLmxlbmd0aCA+IDA7XG4gIH1cblxuICBpZiAoQXJyYXkuaXNBcnJheShtZXNzYWdlLmNvbnRlbnQpKSB7XG4gICAgcmV0dXJuIG1lc3NhZ2UuY29udGVudC5zb21lKChwYXJ0KSA9PiBpc0NhY2hlYWJsZUNsYXVkZVBhcnQocGFydCkpO1xuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBmaW5kTGFzdENhY2hlYWJsZVBhcnRJbmRleChjb250ZW50OiB1bmtub3duW10pOiBudW1iZXIgfCBudWxsIHtcbiAgZm9yIChsZXQgaSA9IGNvbnRlbnQubGVuZ3RoIC0gMTsgaSA+PSAwOyBpIC09IDEpIHtcbiAgICBpZiAoaXNDYWNoZWFibGVDbGF1ZGVQYXJ0KGNvbnRlbnRbaV0pKSB7XG4gICAgICByZXR1cm4gaTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG51bGw7XG59XG5cbmZ1bmN0aW9uIHNlbGVjdENsYXVkZUNhY2hpbmdUYXJnZXRzKG1lc3NhZ2VzOiBNb2RlbE1lc3NhZ2VbXSk6IG51bWJlcltdIHtcbiAgY29uc3Qgc3lzdGVtSW5kaWNlczogbnVtYmVyW10gPSBbXTtcbiAgY29uc3QgZmluYWxJbmRpY2VzOiBudW1iZXJbXSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbWVzc2FnZXMubGVuZ3RoICYmIHN5c3RlbUluZGljZXMubGVuZ3RoIDwgMjsgaSArPSAxKSB7XG4gICAgY29uc3QgbWVzc2FnZSA9IG1lc3NhZ2VzW2ldO1xuICAgIGlmIChtZXNzYWdlLnJvbGUgPT09IFwic3lzdGVtXCIgJiYgaGFzQ2FjaGVhYmxlQ29udGVudChtZXNzYWdlKSkge1xuICAgICAgc3lzdGVtSW5kaWNlcy5wdXNoKGkpO1xuICAgIH1cbiAgfVxuXG4gIGZvciAobGV0IGkgPSBtZXNzYWdlcy5sZW5ndGggLSAxOyBpID49IDAgJiYgZmluYWxJbmRpY2VzLmxlbmd0aCA8IDI7IGkgLT0gMSkge1xuICAgIGNvbnN0IG1lc3NhZ2UgPSBtZXNzYWdlc1tpXTtcbiAgICBpZiAobWVzc2FnZS5yb2xlICE9PSBcInN5c3RlbVwiICYmIGhhc0NhY2hlYWJsZUNvbnRlbnQobWVzc2FnZSkpIHtcbiAgICAgIGZpbmFsSW5kaWNlcy5wdXNoKGkpO1xuICAgIH1cbiAgfVxuXG4gIGZpbmFsSW5kaWNlcy5yZXZlcnNlKCk7XG5cbiAgcmV0dXJuIFsuLi5zeXN0ZW1JbmRpY2VzLCAuLi5maW5hbEluZGljZXNdO1xufVxuXG5mdW5jdGlvbiBhcHBseUNsYXVkZVByb21wdENhY2hpbmcob3B0czoge1xuICBtZXNzYWdlczogTW9kZWxNZXNzYWdlW107XG4gIHByb3ZpZGVySWQ6IHN0cmluZyB8IG51bGw7XG4gIG1heEJyZWFrcG9pbnRzUGVyUmVxdWVzdDogbnVtYmVyO1xufSk6IE1vZGVsTWVzc2FnZVtdIHtcbiAgY29uc3QgZXhpc3RpbmdCcmVha3BvaW50cyA9IGNvdW50QW50aHJvcGljQ2FjaGVCcmVha3BvaW50cyhvcHRzLm1lc3NhZ2VzKTtcbiAgY29uc3QgcmVtYWluaW5nQnVkZ2V0ID0gTWF0aC5tYXgoXG4gICAgMCxcbiAgICBvcHRzLm1heEJyZWFrcG9pbnRzUGVyUmVxdWVzdCAtIGV4aXN0aW5nQnJlYWtwb2ludHNcbiAgKTtcblxuICBpZiAocmVtYWluaW5nQnVkZ2V0ID09PSAwKSB7XG4gICAgcmV0dXJuIG9wdHMubWVzc2FnZXM7XG4gIH1cblxuICBjb25zdCB0YXJnZXRJbmRpY2VzID0gc2VsZWN0Q2xhdWRlQ2FjaGluZ1RhcmdldHMob3B0cy5tZXNzYWdlcykuc2xpY2UoXG4gICAgMCxcbiAgICByZW1haW5pbmdCdWRnZXRcbiAgKTtcbiAgaWYgKHRhcmdldEluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIG9wdHMubWVzc2FnZXM7XG4gIH1cblxuICBjb25zdCB1c2VNZXNzYWdlTGV2ZWxPcHRpb25zID1cbiAgICBvcHRzLnByb3ZpZGVySWQgPT09IFwiYW50aHJvcGljXCIgfHxcbiAgICBCb29sZWFuKG9wdHMucHJvdmlkZXJJZD8uaW5jbHVkZXMoXCJiZWRyb2NrXCIpKTtcblxuICBjb25zdCBuZXh0TWVzc2FnZXMgPSBvcHRzLm1lc3NhZ2VzLnNsaWNlKCk7XG5cbiAgZm9yIChjb25zdCBtZXNzYWdlSW5kZXggb2YgdGFyZ2V0SW5kaWNlcykge1xuICAgIGNvbnN0IG1lc3NhZ2UgPSBuZXh0TWVzc2FnZXNbbWVzc2FnZUluZGV4XTtcblxuICAgIGNvbnN0IHNob3VsZFVzZUNvbnRlbnRPcHRpb25zID1cbiAgICAgICF1c2VNZXNzYWdlTGV2ZWxPcHRpb25zICYmXG4gICAgICBBcnJheS5pc0FycmF5KG1lc3NhZ2UuY29udGVudCkgJiZcbiAgICAgIG1lc3NhZ2UuY29udGVudC5sZW5ndGggPiAwO1xuXG4gICAgaWYgKHNob3VsZFVzZUNvbnRlbnRPcHRpb25zICYmIEFycmF5LmlzQXJyYXkobWVzc2FnZS5jb250ZW50KSkge1xuICAgICAgY29uc3QgcGFydEluZGV4ID0gZmluZExhc3RDYWNoZWFibGVQYXJ0SW5kZXgobWVzc2FnZS5jb250ZW50KTtcbiAgICAgIGlmIChwYXJ0SW5kZXggIT09IG51bGwpIHtcbiAgICAgICAgY29uc3QgcGFydCA9IG1lc3NhZ2UuY29udGVudFtwYXJ0SW5kZXhdO1xuICAgICAgICBpZiAocGFydCAmJiB0eXBlb2YgcGFydCA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICAgIGNvbnN0IHBhcnRQcm92aWRlck9wdGlvbnMgPSAoXG4gICAgICAgICAgICBwYXJ0IGFzIHsgcHJvdmlkZXJPcHRpb25zPzogUHJvdmlkZXJPcHRpb25zIH1cbiAgICAgICAgICApLnByb3ZpZGVyT3B0aW9ucztcblxuICAgICAgICAgIGNvbnN0IG5leHRDb250ZW50ID0gbWVzc2FnZS5jb250ZW50LnNsaWNlKCk7XG4gICAgICAgICAgbmV4dENvbnRlbnRbcGFydEluZGV4XSA9IHtcbiAgICAgICAgICAgIC4uLihwYXJ0IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KSxcbiAgICAgICAgICAgIHByb3ZpZGVyT3B0aW9uczogbWVyZ2VQcm92aWRlck9wdGlvbnMoe1xuICAgICAgICAgICAgICBjdXJyZW50OiBwYXJ0UHJvdmlkZXJPcHRpb25zLFxuICAgICAgICAgICAgICBwYXRjaDogQ0xBVURFX1BST01QVF9DQUNISU5HX1BST1ZJREVSX09QVElPTlMsXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICB9IGFzICh0eXBlb2YgbWVzc2FnZS5jb250ZW50KVtudW1iZXJdO1xuXG4gICAgICAgICAgbmV4dE1lc3NhZ2VzW21lc3NhZ2VJbmRleF0gPSB7XG4gICAgICAgICAgICAuLi5tZXNzYWdlLFxuICAgICAgICAgICAgY29udGVudDogbmV4dENvbnRlbnQsXG4gICAgICAgICAgfSBhcyBNb2RlbE1lc3NhZ2U7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBtZXNzYWdlUHJvdmlkZXJPcHRpb25zID0gKFxuICAgICAgbWVzc2FnZSBhcyB7IHByb3ZpZGVyT3B0aW9ucz86IFByb3ZpZGVyT3B0aW9ucyB9XG4gICAgKS5wcm92aWRlck9wdGlvbnM7XG5cbiAgICBuZXh0TWVzc2FnZXNbbWVzc2FnZUluZGV4XSA9IHtcbiAgICAgIC4uLm1lc3NhZ2UsXG4gICAgICBwcm92aWRlck9wdGlvbnM6IG1lcmdlUHJvdmlkZXJPcHRpb25zKHtcbiAgICAgICAgY3VycmVudDogbWVzc2FnZVByb3ZpZGVyT3B0aW9ucyxcbiAgICAgICAgcGF0Y2g6IENMQVVERV9QUk9NUFRfQ0FDSElOR19QUk9WSURFUl9PUFRJT05TLFxuICAgICAgfSksXG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiBuZXh0TWVzc2FnZXM7XG59XG5cbmV4cG9ydCB0eXBlIFByb21wdENhY2hpbmdSZXN1bHQgPSB7XG4gIG1lc3NhZ2VzOiBNb2RlbE1lc3NhZ2VbXTtcbiAgcHJvdmlkZXJPcHRpb25zOiBQcm92aWRlck9wdGlvbnM7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gYXBwbHlQcm9tcHRDYWNoaW5nVG9Nb2RlbFJlcXVlc3Qob3B0czoge1xuICBtb2RlbDogc3RyaW5nO1xuICBzZXNzaW9uSWQ6IHN0cmluZztcbiAgbWVzc2FnZXM6IE1vZGVsTWVzc2FnZVtdO1xuICBhbnRocm9waWM/OiB7IG1heEJyZWFrcG9pbnRzUGVyUmVxdWVzdD86IG51bWJlciB9O1xuICBvcGVuYWk/OiB7IHNldFByb21wdENhY2hlS2V5PzogYm9vbGVhbiB9O1xufSk6IFByb21wdENhY2hpbmdSZXN1bHQge1xuICBjb25zdCBwcm92aWRlciA9IGdldEdhdGV3YXlQcm92aWRlcihvcHRzLm1vZGVsKTtcblxuICBjb25zdCBwcm92aWRlck9wdGlvbnM6IFByb3ZpZGVyT3B0aW9ucyA9IHt9O1xuXG4gIGlmIChcbiAgICAocHJvdmlkZXIgPT09IFwib3BlbmFpXCIgfHwgcHJvdmlkZXIgPT09IFwiYXp1cmVcIikgJiZcbiAgICBvcHRzLm9wZW5haT8uc2V0UHJvbXB0Q2FjaGVLZXkgIT09IGZhbHNlXG4gICkge1xuICAgIHByb3ZpZGVyT3B0aW9ucy5vcGVuYWkgPSB7IHByb21wdENhY2hlS2V5OiBvcHRzLnNlc3Npb25JZCB9O1xuICB9XG5cbiAgY29uc3QgbWF4QnJlYWtwb2ludHNQZXJSZXF1ZXN0ID1cbiAgICBvcHRzLmFudGhyb3BpYz8ubWF4QnJlYWtwb2ludHNQZXJSZXF1ZXN0ID8/XG4gICAgQU5USFJPUElDX01BWF9DQUNIRV9CUkVBS1BPSU5UU19QRVJfUkVRVUVTVDtcblxuICBjb25zdCBjYWNoZWRNZXNzYWdlcyA9IGlzQ2xhdWRlTGlrZU1vZGVsKG9wdHMubW9kZWwpXG4gICAgPyBhcHBseUNsYXVkZVByb21wdENhY2hpbmcoe1xuICAgICAgICBtZXNzYWdlczogb3B0cy5tZXNzYWdlcyxcbiAgICAgICAgcHJvdmlkZXJJZDogcHJvdmlkZXIsXG4gICAgICAgIG1heEJyZWFrcG9pbnRzUGVyUmVxdWVzdCxcbiAgICAgIH0pXG4gICAgOiBvcHRzLm1lc3NhZ2VzO1xuXG4gIHJldHVybiB7XG4gICAgbWVzc2FnZXM6IGNhY2hlZE1lc3NhZ2VzLFxuICAgIHByb3ZpZGVyT3B0aW9ucyxcbiAgfTtcbn1cbiIsICJpbXBvcnQgdHlwZSB7IFVJTWVzc2FnZUNodW5rIH0gZnJvbSBcImFpXCI7XG5pbXBvcnQgKiBhcyBlcnJvcmUgZnJvbSBcImVycm9yZVwiO1xuaW1wb3J0IHsgU2Vzc2lvbk5vdEZvdW5kRXJyb3IgfSBmcm9tIFwiLi4vZXJyb3JzXCI7XG5pbXBvcnQgdHlwZSB7IFNlc3Npb25Db250ZXh0IH0gZnJvbSBcIi4vaGFuZGxlXCI7XG5pbXBvcnQgeyBnZXRBY3RpdmVSdW5zLCByZXBsYXlBY3RpdmVSdW4gfSBmcm9tIFwiLi9zZW5kXCI7XG5cbmV4cG9ydCB0eXBlIFN0cmVhbU9wdGlvbnMgPSB7XG4gIG1lc3NhZ2VJZD86IHN0cmluZztcbiAgc3RhcnRJbmRleD86IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIFdvcmtmbG93UnVuTGlrZSA9IHtcbiAgZ2V0UmVhZGFibGUob3B0aW9ucz86IHsgc3RhcnRJbmRleD86IG51bWJlciB9KTogUmVhZGFibGVTdHJlYW07XG59O1xuXG5mdW5jdGlvbiBpc1dvcmtmbG93UnVuKGFyZzogdW5rbm93bik6IGFyZyBpcyBXb3JrZmxvd1J1bkxpa2Uge1xuICByZXR1cm4gKFxuICAgIHR5cGVvZiBhcmcgPT09IFwib2JqZWN0XCIgJiZcbiAgICBhcmcgIT09IG51bGwgJiZcbiAgICBcImdldFJlYWRhYmxlXCIgaW4gYXJnICYmXG4gICAgdHlwZW9mIChhcmcgYXMgV29ya2Zsb3dSdW5MaWtlKS5nZXRSZWFkYWJsZSA9PT0gXCJmdW5jdGlvblwiXG4gICk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzdHJlYW0oXG4gIHNlc3Npb25Db250ZXh0OiBTZXNzaW9uQ29udGV4dCxcbiAgcnVuT3JPcHRzPzogV29ya2Zsb3dSdW5MaWtlIHwgU3RyZWFtT3B0aW9uc1xuKTogUHJvbWlzZTxSZWFkYWJsZVN0cmVhbTxVSU1lc3NhZ2VDaHVuaz4+IHtcbiAgaWYgKGlzV29ya2Zsb3dSdW4ocnVuT3JPcHRzKSkge1xuICAgIGNvbnN0IHJlYWRlciA9IHJ1bk9yT3B0cy5nZXRSZWFkYWJsZSgpLmdldFJlYWRlcigpO1xuICAgIC8vIGF3YWl0IGZvciB0aGUgZmlyc3QgY2h1bmsgdG8gYmUgcmVhZHkgYmVmb3JlIGZpbmlzaGluZyB0aGUgd29ya2Zsb3cgdG8gYXZvaWQgcmFjZSBjb25kaXRpb25zXG4gICAgYXdhaXQgcmVhZGVyLnJlYWQoKS5jYXRjaCgoKSA9PiB7XG4gICAgICB0aHJvdyBuZXcgU3RyZWFtRXJyb3Ioe1xuICAgICAgICBpZDogc2Vzc2lvbkNvbnRleHQuc2Vzc2lvbklkLFxuICAgICAgICByZWFzb246IFwic3RyZWFtKCkgZmFpbGVkIHRvIHJlYWQgZmlyc3QgY2h1bmsgZnJvbSB3b3JrZmxvdyBydW5cIixcbiAgICAgIH0pO1xuICAgIH0pO1xuICAgIHJlYWRlci5jYW5jZWwoKTtcblxuICAgIHJldHVybiBydW5Pck9wdHMuZ2V0UmVhZGFibGUoKTtcbiAgfVxuXG4gIGNvbnN0IG9wdHMgPSBydW5Pck9wdHM7XG4gIGNvbnN0IHNlc3Npb24gPSBhd2FpdCBzZXNzaW9uQ29udGV4dC5hZ2VudC5zdG9yYWdlLnNlc3Npb24uZ2V0KFxuICAgIHNlc3Npb25Db250ZXh0LnNlc3Npb25JZFxuICApO1xuICBpZiAoIXNlc3Npb24pIHtcbiAgICB0aHJvdyBuZXcgU2Vzc2lvbk5vdEZvdW5kRXJyb3IoeyBpZDogc2Vzc2lvbkNvbnRleHQuc2Vzc2lvbklkIH0pO1xuICB9XG4gIGNvbnN0IG1lc3NhZ2VJZCA9IG9wdHM/Lm1lc3NhZ2VJZCA/PyBzZXNzaW9uLmxhc3RNZXNzYWdlSWQ7XG4gIGlmICghbWVzc2FnZUlkKSB7XG4gICAgdGhyb3cgbmV3IFN0cmVhbUVycm9yKHtcbiAgICAgIGlkOiBzZXNzaW9uQ29udGV4dC5zZXNzaW9uSWQsXG4gICAgICByZWFzb246IFwiTm8gbWVzc2FnZSB0byBzdHJlYW1cIixcbiAgICB9KTtcbiAgfVxuXG4gIGNvbnN0IGFjdGl2ZVJ1bnMgPSBnZXRBY3RpdmVSdW5zKCk7XG4gIGNvbnN0IGFjdGl2ZSA9IGFjdGl2ZVJ1bnMuZ2V0KG1lc3NhZ2VJZCk7XG4gIGlmICghYWN0aXZlKSB7XG4gICAgY29uc3QgbWVzc2FnZSA9IGF3YWl0IHNlc3Npb25Db250ZXh0LmFnZW50LnN0b3JhZ2UubWVzc2FnZS5nZXQobWVzc2FnZUlkKTtcbiAgICBpZiAobWVzc2FnZT8ud29ya2Zsb3dSdW5JZCkge1xuICAgICAgY29uc3QgcmVhZGFibGUgPSBhd2FpdCBpbXBvcnQoXCJ3b3JrZmxvdy9hcGlcIilcbiAgICAgICAgLnRoZW4oKHsgZ2V0UnVuIH0pID0+IGdldFJ1bihtZXNzYWdlLndvcmtmbG93UnVuSWQhKS5nZXRSZWFkYWJsZSgpKVxuICAgICAgICAuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICAgIGlmIChyZWFkYWJsZSkge1xuICAgICAgICByZXR1cm4gcmVhZGFibGU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IFN0cmVhbUVycm9yKHtcbiAgICAgIGlkOiBzZXNzaW9uQ29udGV4dC5zZXNzaW9uSWQsXG4gICAgICByZWFzb246IGBObyBhY3RpdmUgcnVuIGZvciBtZXNzYWdlICR7bWVzc2FnZUlkfWAsXG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gcmVwbGF5QWN0aXZlUnVuKGFjdGl2ZSwgb3B0cz8uc3RhcnRJbmRleCk7XG59XG5cbi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqIEVycm9yc1xuICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG5leHBvcnQgY2xhc3MgU3RyZWFtRXJyb3IgZXh0ZW5kcyBlcnJvcmUuY3JlYXRlVGFnZ2VkRXJyb3Ioe1xuICBuYW1lOiBcIlN0cmVhbUVycm9yXCIsXG4gIG1lc3NhZ2U6IFwiU3RyZWFtIGZhaWxlZCBmb3Igc2Vzc2lvbiAkaWQ6ICRyZWFzb25cIixcbn0pIHt9XG4iLCAiaW1wb3J0IHR5cGUgeyBTZXNzaW9uIH0gZnJvbSBcIi4uL3N0b3JhZ2UvdHlwZXNcIjtcbmltcG9ydCB0eXBlIHsgU2Vzc2lvbkNvbnRleHQgfSBmcm9tIFwiLi9oYW5kbGVcIjtcblxuZXhwb3J0IHR5cGUgVXBkYXRlT3B0aW9uczxcbiAgVFN0YXRlIGV4dGVuZHMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbj4gPSBQYXJ0aWFsPE9taXQ8U2Vzc2lvbiwgXCJpZFwiIHwgXCJjcmVhdGVkQXRcIiB8IFwidXBkYXRlZEF0XCIgfCBcInN0YXRlXCI+PiAmIHtcbiAgc3RhdGU/OiBUU3RhdGU7XG59O1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gdXBkYXRlPFxuICBUU3RhdGUgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuPihcbiAgc2Vzc2lvbkNvbnRleHQ6IFNlc3Npb25Db250ZXh0LFxuICBvcHRzOiBVcGRhdGVPcHRpb25zPFRTdGF0ZT5cbikge1xuICBcInVzZSBzdGVwXCI7XG4gIGNvbnN0IHVwZGF0ZXMgPSBPYmplY3QuZnJvbUVudHJpZXMoXG4gICAgT2JqZWN0LmVudHJpZXMob3B0cykuZmlsdGVyKChbLCB2YWx1ZV0pID0+IHZhbHVlICE9PSB1bmRlZmluZWQpXG4gICk7XG5cbiAgaWYgKE9iamVjdC5rZXlzKHVwZGF0ZXMpLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGF3YWl0IHNlc3Npb25Db250ZXh0LmFnZW50LnN0b3JhZ2Uuc2Vzc2lvbi51cGRhdGUoc2Vzc2lvbkNvbnRleHQuc2Vzc2lvbklkLCB7XG4gICAgLi4udXBkYXRlcyxcbiAgICB1cGRhdGVkQXQ6IERhdGUubm93KCksXG4gIH0pO1xufVxuIiwgImltcG9ydCB7IGNvbXB1dGVTZXNzaW9uVXNhZ2UsIHR5cGUgU2Vzc2lvblVzYWdlIH0gZnJvbSBcIi4uL3V0aWxzL3VzYWdlXCI7XG5pbXBvcnQgdHlwZSB7IFNlc3Npb25Db250ZXh0IH0gZnJvbSBcIi4vaGFuZGxlXCI7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB1c2FnZShcbiAgc2Vzc2lvbkNvbnRleHQ6IFNlc3Npb25Db250ZXh0XG4pOiBQcm9taXNlPFNlc3Npb25Vc2FnZT4ge1xuICBcInVzZSBzdGVwXCI7XG4gIGNvbnN0IG1lc3NhZ2VzID0gYXdhaXQgc2Vzc2lvbkNvbnRleHQuYWdlbnQuc3RvcmFnZS5tZXNzYWdlLmxpc3RCeVNlc3Npb24oXG4gICAgc2Vzc2lvbkNvbnRleHQuc2Vzc2lvbklkXG4gICk7XG4gIHJldHVybiBjb21wdXRlU2Vzc2lvblVzYWdlKG1lc3NhZ2VzKTtcbn1cbiIsICJpbXBvcnQgdHlwZSB7XG4gIEluZmVyVG9vbElucHV0LFxuICBJbmZlclVJVG9vbHMsXG4gIE1vZGVsTWVzc2FnZSxcbiAgVG9vbFNldCxcbiAgVUlNZXNzYWdlLFxufSBmcm9tIFwiYWlcIjtcbmltcG9ydCAqIGFzIGVycm9yZSBmcm9tIFwiZXJyb3JlXCI7XG5pbXBvcnQgeyB6IH0gZnJvbSBcInpvZFwiO1xuaW1wb3J0IHR5cGUgeyBCdWlsdEluVG9vbE5hbWUsIGJ1aWx0SW5Ub29scywgVG9vbENvbnRleHQgfSBmcm9tIFwiLi4vdG9vbHNcIjtcbmltcG9ydCB0eXBlIHsgQW55QWdlbnQgfSBmcm9tIFwiLi9jbGllbnRcIjtcblxuLy8gXHUyNTAwXHUyNTAwXHUyNTAwIEFnZW50IFN0YXR1cyBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcdTI1MDBcblxuLyoqXG4gKiBUcmFuc2llbnQgc3RhdHVzIGluZGljYXRvcnMgZW1pdHRlZCBvdmVyIHRoZSBzdHJlYW0gZHVyaW5nIGxvbmctcnVubmluZyBwaGFzZXMuXG4gKiBEZWxpdmVyZWQgdG8gdGhlIGNsaWVudCBhcyBgZGF0YS1zdGF0dXNgIGNodW5rcyB3aXRoIGB0cmFuc2llbnQ6IHRydWVgIFx1MjAxNCBub3QgcGVyc2lzdGVkLlxuICovXG5leHBvcnQgY29uc3QgQWdlbnRTdGF0dXMgPSB6LmRpc2NyaW1pbmF0ZWRVbmlvbihcInR5cGVcIiwgW1xuICB6Lm9iamVjdCh7IHR5cGU6IHoubGl0ZXJhbChcInNhbmRib3gtc2V0dXBcIikgfSksXG4gIHoub2JqZWN0KHsgdHlwZTogei5saXRlcmFsKFwic2FuZGJveC1zZXR1cC1jb2xkXCIpIH0pLFxuICB6Lm9iamVjdCh7IHR5cGU6IHoubGl0ZXJhbChcImxvYWRpbmctc2tpbGxzXCIpIH0pLFxuICB6Lm9iamVjdCh7IHR5cGU6IHoubGl0ZXJhbChcInByb2Nlc3NpbmctYXBwcm92YWxzXCIpIH0pLFxuICB6Lm9iamVjdCh7IHR5cGU6IHoubGl0ZXJhbChcIm5lZWRzLWFwcHJvdmFsXCIpIH0pLFxuICB6Lm9iamVjdCh7IHR5cGU6IHoubGl0ZXJhbChcInRoaW5raW5nXCIpIH0pLFxuICB6Lm9iamVjdCh7IHR5cGU6IHoubGl0ZXJhbChcImN1c3RvbVwiKSwgc3RhdHVzOiB6LnN0cmluZygpIH0pLFxuXSk7XG5cbmV4cG9ydCB0eXBlIEFnZW50U3RhdHVzID0gei5pbmZlcjx0eXBlb2YgQWdlbnRTdGF0dXM+O1xuXG5leHBvcnQgdHlwZSBBZ2VudERhdGFUeXBlcyA9IHsgc3RhdHVzOiBBZ2VudFN0YXR1cyB9O1xuXG4vLyBcdTI1MDBcdTI1MDBcdTI1MDAgSG9va3MgXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXG5cbmV4cG9ydCB0eXBlIEFnZW50SG9va3MgPSB7XG4gIFwidG9vbC5iZWZvcmVcIj86IChvcHRzOiB7XG4gICAgbmFtZTogc3RyaW5nO1xuICAgIGlucHV0OiB1bmtub3duO1xuICAgIGNvbnRleHQ6IFRvb2xDb250ZXh0O1xuICB9KSA9PiBQcm9taXNlPHVuZGVmaW5lZCB8IHsgaW5wdXQ6IHVua25vd24gfT47XG4gIFwidG9vbC5hZnRlclwiPzogKG9wdHM6IHtcbiAgICBuYW1lOiBzdHJpbmc7XG4gICAgaW5wdXQ6IHVua25vd247XG4gICAgcmVzdWx0OiB1bmtub3duO1xuICAgIGNvbnRleHQ6IFRvb2xDb250ZXh0O1xuICB9KSA9PiBQcm9taXNlPHVuZGVmaW5lZCB8IHsgcmVzdWx0OiB1bmtub3duIH0+O1xuICBzdGF0dXM/OiAoc3RhdHVzOiBBZ2VudFN0YXR1cykgPT4gdm9pZCB8IFByb21pc2U8dm9pZD47XG59O1xuXG4vLyBcdTI1MDBcdTI1MDBcdTI1MDAgTmVlZHMgQXBwcm92YWwgXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXG5cbnR5cGUgVG9vbE5hbWU8VG9vbHM+ID0gRXh0cmFjdDxrZXlvZiBUb29scywgc3RyaW5nPiB8IEJ1aWx0SW5Ub29sTmFtZTtcblxudHlwZSBUb29sSW5wdXQ8VG9vbHMsIEs+ID0gSyBleHRlbmRzIEJ1aWx0SW5Ub29sTmFtZVxuICA/IEluZmVyVG9vbElucHV0PCh0eXBlb2YgYnVpbHRJblRvb2xzKVtLXT5cbiAgOiBLIGV4dGVuZHMga2V5b2YgVG9vbHNcbiAgICA/IFRvb2xzW0tdIGV4dGVuZHMgaW1wb3J0KFwiYWlcIikuVG9vbFxuICAgICAgPyBJbmZlclRvb2xJbnB1dDxUb29sc1tLXT5cbiAgICAgIDogdW5rbm93blxuICAgIDogdW5rbm93bjtcblxuZXhwb3J0IHR5cGUgTmVlZHNBcHByb3ZhbE1hcDxUb29scz4gPSB7XG4gIFtLIGluIFRvb2xOYW1lPFRvb2xzPl0/OlxuICAgIHwgYm9vbGVhblxuICAgIHwgKChcbiAgICAgICAgaW5wdXQ6IFRvb2xJbnB1dDxUb29scywgSz4sXG4gICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICB0b29sQ2FsbElkOiBzdHJpbmc7XG4gICAgICAgICAgbWVzc2FnZXM6IE1vZGVsTWVzc2FnZVtdO1xuICAgICAgICAgIGV4cGVyaW1lbnRhbF9jb250ZXh0OiB1bmtub3duO1xuICAgICAgICB9XG4gICAgICApID0+IGJvb2xlYW4gfCBQcm9taXNlPGJvb2xlYW4+KTtcbn07XG5cbi8vIFx1MjUwMFx1MjUwMFx1MjUwMCBJbmZlciBVSSBNZXNzYWdlIFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFx1MjUwMFxuXG5leHBvcnQgdHlwZSBJbmZlclVJTWVzc2FnZTxBPiA9IEEgZXh0ZW5kcyB7XG4gIHRvb2xzOiBpbmZlciBUIGV4dGVuZHMgVG9vbFNldDtcbiAgJFVJTWVzc2FnZTogVUlNZXNzYWdlPGluZmVyIE0+O1xufVxuICA/IFVJTWVzc2FnZTxNLCBBZ2VudERhdGFUeXBlcywgSW5mZXJVSVRvb2xzPFQ+PlxuICA6IEEgZXh0ZW5kcyB7IHRvb2xzOiBpbmZlciBUIGV4dGVuZHMgVG9vbFNldCB9XG4gICAgPyBVSU1lc3NhZ2U8dW5rbm93biwgQWdlbnREYXRhVHlwZXMsIEluZmVyVUlUb29sczxUPj5cbiAgICA6IFVJTWVzc2FnZTx1bmtub3duLCBBZ2VudERhdGFUeXBlcz47XG5cbmV4cG9ydCB0eXBlIFR5cGVkVUlNZXNzYWdlPFxuICBUTWVzc2FnZU1ldGFkYXRhID0gdW5rbm93bixcbiAgVG9vbHMgZXh0ZW5kcyBUb29sU2V0ID0gVG9vbFNldCxcbj4gPSBVSU1lc3NhZ2U8VE1lc3NhZ2VNZXRhZGF0YSwgQWdlbnREYXRhVHlwZXMsIEluZmVyVUlUb29sczxUb29scz4+O1xuXG4vLyBcdTI1MDBcdTI1MDBcdTI1MDAgUmVnaXN0cnkgXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXHUyNTAwXG5cbmNsYXNzIEFnZW50Tm90Rm91bmRFcnJvciBleHRlbmRzIGVycm9yZS5jcmVhdGVUYWdnZWRFcnJvcih7XG4gIG5hbWU6IFwiQWdlbnROb3RGb3VuZEVycm9yXCIsXG4gIG1lc3NhZ2U6IGBBZ2VudCBcIiRhZ2VudE5hbWVcIiBub3QgZm91bmQgaW4gcmVnaXN0cnkuXG5cbmhpbnQ6IGFnZW50KCkgbXVzdCBiZSBjYWxsZWQgYmVmb3JlIHdvcmtmbG93IHN0ZXBzIGV4ZWN1dGUuXG4gICAgICBWYWxpZCBsb2NhdGlvbnM6IG1vZHVsZSBzY29wZSwgb3IgaW5zaWRlIGEgXCJ1c2Ugd29ya2Zsb3dcIiBib2R5LlxuXG4gIC8vIE1vZHVsZSBzY29wZSAoc3RhdGljIGFnZW50cylcbiAgZXhwb3J0IGNvbnN0IG15QWdlbnQgPSBhZ2VudChcIiRhZ2VudE5hbWVcIiwgeyAuLi4gfSk7XG5cbiAgLy8gV29ya2Zsb3cgYm9keSAoZHluYW1pYyBhZ2VudHMpXG4gIGFzeW5jIGZ1bmN0aW9uIG15V29ya2Zsb3coeyBpbnB1dCB9KSB7XG4gICAgXCJ1c2Ugd29ya2Zsb3dcIjtcbiAgICBjb25zdCBteUFnZW50ID0gYWdlbnQoXCIkYWdlbnROYW1lXCIsIHsgLi4uIH0pO1xuICAgIC4uLlxuICB9YCxcbn0pIHt9XG5cbmNvbnN0IEFHRU5UX1JFR0lTVFJZX0tFWSA9IFN5bWJvbC5mb3IoXCJleHBlcmltZW50YWwtYWdlbnQtcmVnaXN0cnlcIik7XG5cbmZ1bmN0aW9uIGdldEFnZW50UmVnaXN0cnkoKTogTWFwPHN0cmluZywgQW55QWdlbnQ+IHtcbiAgY29uc3QgZyA9IGdsb2JhbFRoaXMgYXMgUmVjb3JkPHN5bWJvbCwgdW5rbm93bj47XG4gIGxldCByZWdpc3RyeSA9IGdbQUdFTlRfUkVHSVNUUllfS0VZXSBhcyBNYXA8c3RyaW5nLCBBbnlBZ2VudD4gfCB1bmRlZmluZWQ7XG4gIGlmICghcmVnaXN0cnkpIHtcbiAgICByZWdpc3RyeSA9IG5ldyBNYXAoKTtcbiAgICBnW0FHRU5UX1JFR0lTVFJZX0tFWV0gPSByZWdpc3RyeTtcbiAgfVxuICByZXR1cm4gcmVnaXN0cnk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZWdpc3RlckFnZW50KG5hbWU6IHN0cmluZywgYWdlbnQ6IEFueUFnZW50KSB7XG4gIGdldEFnZW50UmVnaXN0cnkoKS5zZXQobmFtZSwgYWdlbnQpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGdldEFnZW50PFJlcXVpcmVkIGV4dGVuZHMgYm9vbGVhbj4oXG4gIG5hbWU6IHN0cmluZyxcbiAgcmVxdWlyZWQ/OiBSZXF1aXJlZFxuKTogUmVxdWlyZWQgZXh0ZW5kcyB0cnVlID8gQW55QWdlbnQgOiBBbnlBZ2VudCB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IGFnZW50ID0gZ2V0QWdlbnRSZWdpc3RyeSgpLmdldChuYW1lKTtcbiAgaWYgKHJlcXVpcmVkICYmICFhZ2VudCkge1xuICAgIHRocm93IG5ldyBBZ2VudE5vdEZvdW5kRXJyb3IoeyBhZ2VudE5hbWU6IG5hbWUgfSk7XG4gIH1cbiAgcmV0dXJuIGFnZW50IGFzIFJlcXVpcmVkIGV4dGVuZHMgdHJ1ZSA/IEFueUFnZW50IDogQW55QWdlbnQgfCB1bmRlZmluZWQ7XG59XG4iLCAiaW1wb3J0IHsgY3JlYXRlVUlNZXNzYWdlU3RyZWFtUmVzcG9uc2UgfSBmcm9tIFwiYWlcIjtcbmltcG9ydCBFbHlzaWEgZnJvbSBcImVseXNpYVwiO1xuaW1wb3J0IHR5cGUgeyBBbnlBZ2VudCwgU2Vzc2lvblNlbmRBcmdzIH0gZnJvbSBcIi4uL2FnZW50L2NsaWVudFwiO1xuaW1wb3J0IHR5cGUgeyBTZW5kUmVzdWx0IH0gZnJvbSBcIi4uL3Nlc3Npb24vc2VuZFwiO1xuaW1wb3J0IHtcbiAgdHlwZSBBZ2VudENvbnRyYWN0LFxuICBhZ2VudENvbnRyYWN0LFxuICB0eXBlIEluZmVyQ29udHJhY3QsXG4gIHR5cGUgSW5mZXJSZXNwb25zZSxcbn0gZnJvbSBcIi4vYWdlbnRDb250cmFjdFwiO1xuaW1wb3J0IHsgdHlwZSBCYXNlUGF0aCwgYmFzZVBhdGhGb3JBZ2VudCB9IGZyb20gXCIuL2Jhc2UtcGF0aFwiO1xuXG50eXBlIFdpdGhvdXQ8TywgSyBleHRlbmRzIGtleW9mIE8+ID0gT21pdDxPLCBLPjtcblxuZXhwb3J0IGZ1bmN0aW9uIGhhbmRsZVJlcXVlc3Q8XG4gIEFnZW50IGV4dGVuZHMgQW55QWdlbnQsXG4gIEFnZW50QmFzZVBhdGggZXh0ZW5kcyBzdHJpbmcgPSBCYXNlUGF0aCxcbj4oXG4gIGFnZW50OiBBZ2VudCxcbiAgb3B0aW9uczoge1xuICAgIGJhc2VQYXRoPzogQWdlbnRCYXNlUGF0aDtcbiAgICB3b3JrZmxvdz86IChcbiAgICAgIHNlc3Npb25JZDogc3RyaW5nLFxuICAgICAgLi4uYXJnczogU2Vzc2lvblNlbmRBcmdzPEFueUFnZW50PlxuICAgICkgPT4gUHJvbWlzZTxTZW5kUmVzdWx0PjtcbiAgICBvdmVycmlkZXM/OiB7XG4gICAgICBbSyBpbiBrZXlvZiBBZ2VudENvbnRyYWN0PEFnZW50Pl0/OiAoXG4gICAgICAgIGNvbnRyYWN0OiBXaXRob3V0PEluZmVyQ29udHJhY3Q8QWdlbnQ+W0tdLCBcInJlc3BvbnNlXCI+LFxuICAgICAgICBuZXh0OiAoKSA9PiBQcm9taXNlPEluZmVyUmVzcG9uc2U8QWdlbnQsIEs+IHwgUmVzcG9uc2U+XG4gICAgICApID0+IFByb21pc2U8SW5mZXJSZXNwb25zZTxBZ2VudCwgSz4gfCBSZXNwb25zZT47XG4gICAgfTtcbiAgfSA9IHt9XG4pIHtcbiAgY29uc3QgeyBiYXNlUGF0aCA9IGJhc2VQYXRoRm9yQWdlbnQoYWdlbnQubmFtZSksIHdvcmtmbG93IH0gPSBvcHRpb25zO1xuXG4gIGNvbnN0IGNvbnRyYWN0ID0gYWdlbnRDb250cmFjdChhZ2VudCk7XG5cbiAgY29uc3Qgcm91dGVyID0gbmV3IEVseXNpYSh7IHByZWZpeDogYmFzZVBhdGggfSlcbiAgICAuZ2V0KFxuICAgICAgXCIvOnNlc3Npb25JZFwiLFxuICAgICAgYXN5bmMgKHsgcGFyYW1zIH0pID0+IHtcbiAgICAgICAgY29uc3QgbmV4dCA9IGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCBzZXNzaW9uID0gYWdlbnQuc2Vzc2lvbihwYXJhbXMuc2Vzc2lvbklkISk7XG4gICAgICAgICAgY29uc3QgdWkgPSBhd2FpdCBzZXNzaW9uLmhpc3RvcnkoKTtcbiAgICAgICAgICByZXR1cm4gdWk7XG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3Qgb3ZlcnJpZGUgPSBvcHRpb25zLm92ZXJyaWRlcz8uW1wic2Vzc2lvbi5nZXRcIl07XG4gICAgICAgIGlmIChvdmVycmlkZSkge1xuICAgICAgICAgIHJldHVybiBSZXNwb25zZS5qc29uKFxuICAgICAgICAgICAgYXdhaXQgb3ZlcnJpZGUoXG4gICAgICAgICAgICAgIHsgcGFyYW1zIH0sXG4gICAgICAgICAgICAgIC8vIFRPRE8gbWFrZSB0aGUgbWlzbWF0Y2hlZCB0eXBlcyB3aXRoIEFJIFNESyBsZXNzIHdlaXJkXG4gICAgICAgICAgICAgIG5leHQgYXMgKCkgPT4gUHJvbWlzZTxcbiAgICAgICAgICAgICAgICBJbmZlclJlc3BvbnNlPEFnZW50LCBcInNlc3Npb24uZ2V0XCI+IHwgUmVzcG9uc2VcbiAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgKVxuICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gUmVzcG9uc2UuanNvbihhd2FpdCBuZXh0KCkpO1xuICAgICAgfSxcbiAgICAgIGNvbnRyYWN0W1wic2Vzc2lvbi5nZXRcIl1cbiAgICApXG4gICAgLnBvc3QoXG4gICAgICBcIi86c2Vzc2lvbklkXCIsXG4gICAgICBhc3luYyAoeyBwYXJhbXMsIGJvZHkgfSkgPT4ge1xuICAgICAgICBjb25zdCBuZXh0ID0gYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHNlc3Npb24gPSBhZ2VudC5zZXNzaW9uKHBhcmFtcy5zZXNzaW9uSWQhKTtcblxuICAgICAgICAgIGlmICh3b3JrZmxvdykge1xuICAgICAgICAgICAgY29uc3QgeyBzdGFydCB9ID0gYXdhaXQgaW1wb3J0KFwid29ya2Zsb3cvYXBpXCIpO1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3RhcnQod29ya2Zsb3csIFtwYXJhbXMuc2Vzc2lvbklkISwgYm9keV0pO1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gYXdhaXQgc2Vzc2lvbi5zdHJlYW0ocmVzdWx0KTtcbiAgICAgICAgICAgIHJldHVybiBjcmVhdGVVSU1lc3NhZ2VTdHJlYW1SZXNwb25zZSh7IHN0cmVhbSB9KTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBhd2FpdCBzZXNzaW9uLnNlbmQoYm9keSk7XG4gICAgICAgICAgY29uc3Qgc3RyZWFtID0gYXdhaXQgc2Vzc2lvbi5zdHJlYW0oKTtcbiAgICAgICAgICByZXR1cm4gY3JlYXRlVUlNZXNzYWdlU3RyZWFtUmVzcG9uc2UoeyBzdHJlYW0gfSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3Qgb3ZlcnJpZGUgPSBvcHRpb25zLm92ZXJyaWRlcz8uW1wic2Vzc2lvbi5wb3N0XCJdO1xuICAgICAgICBpZiAob3ZlcnJpZGUpIHtcbiAgICAgICAgICByZXR1cm4gYXdhaXQgb3ZlcnJpZGUoeyBwYXJhbXMsIGJvZHkgfSwgbmV4dCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYXdhaXQgbmV4dCgpO1xuICAgICAgfSxcbiAgICAgIGNvbnRyYWN0W1wic2Vzc2lvbi5wb3N0XCJdXG4gICAgKVxuICAgIC5nZXQoXG4gICAgICBcIi86c2Vzc2lvbklkL3JlY29ubmVjdFwiLFxuICAgICAgYXN5bmMgKHsgcGFyYW1zIH0pID0+IHtcbiAgICAgICAgY29uc3QgbmV4dCA9IGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCBzZXNzaW9uID0gYWdlbnQuc2Vzc2lvbihwYXJhbXMuc2Vzc2lvbklkISk7XG4gICAgICAgICAgY29uc3Qgc3RyZWFtID0gYXdhaXQgc2Vzc2lvbi5zdHJlYW0oKTtcbiAgICAgICAgICByZXR1cm4gY3JlYXRlVUlNZXNzYWdlU3RyZWFtUmVzcG9uc2UoeyBzdHJlYW0gfSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3Qgb3ZlcnJpZGUgPSBvcHRpb25zLm92ZXJyaWRlcz8uW1wicmVjb25uZWN0LmdldFwiXTtcbiAgICAgICAgaWYgKG92ZXJyaWRlKSB7XG4gICAgICAgICAgcmV0dXJuIGF3YWl0IG92ZXJyaWRlKHsgcGFyYW1zIH0sIG5leHQpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGF3YWl0IG5leHQoKTtcbiAgICAgIH0sXG4gICAgICBjb250cmFjdFtcInJlY29ubmVjdC5nZXRcIl1cbiAgICApXG4gICAgLnBvc3QoXG4gICAgICBcIi86c2Vzc2lvbklkL2ludGVycnVwdFwiLFxuXG4gICAgICBhc3luYyAoeyBwYXJhbXMsIGJvZHkgfSkgPT4ge1xuICAgICAgICBjb25zdCBuZXh0ID0gYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHNlc3Npb24gPSBhZ2VudC5zZXNzaW9uKHBhcmFtcy5zZXNzaW9uSWQhKTtcbiAgICAgICAgICBhd2FpdCBzZXNzaW9uLmludGVycnVwdChib2R5KTtcbiAgICAgICAgICByZXR1cm4geyBzdWNjZXNzOiB0cnVlIH07XG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3Qgb3ZlcnJpZGUgPSBvcHRpb25zLm92ZXJyaWRlcz8uW1wiaW50ZXJydXB0LnBvc3RcIl07XG4gICAgICAgIGlmIChvdmVycmlkZSkge1xuICAgICAgICAgIHJldHVybiBSZXNwb25zZS5qc29uKGF3YWl0IG92ZXJyaWRlKHsgcGFyYW1zLCBib2R5IH0sIG5leHQpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBSZXNwb25zZS5qc29uKGF3YWl0IG5leHQoKSk7XG4gICAgICB9LFxuICAgICAgY29udHJhY3RbXCJpbnRlcnJ1cHQucG9zdFwiXVxuICAgICk7XG5cbiAgcmV0dXJuIHJvdXRlcjtcbn1cbiIsICJpbXBvcnQgeiBmcm9tIFwiem9kXCI7XG5pbXBvcnQgdHlwZSB7IEFueUFnZW50IH0gZnJvbSBcIi4uL2FnZW50L2NsaWVudFwiO1xuaW1wb3J0IHtcbiAgYnVpbGRTZXNzaW9uSGlzdG9yeVNjaGVtYSxcbiAgYnVpbGRVSU1lc3NhZ2VQYXJ0U2NoZW1hLFxuICBidWlsZFVJTWVzc2FnZVNjaGVtYSxcbn0gZnJvbSBcIi4vc2NoZW1hc1wiO1xuXG5leHBvcnQgZnVuY3Rpb24gYWdlbnRDb250cmFjdDxBZ2VudCBleHRlbmRzIEFueUFnZW50PihhZ2VudDogQWdlbnQpIHtcbiAgY29uc3QgY29udHJhY3QgPSB7XG4gICAgXCJzZXNzaW9uLmdldFwiOiB7XG4gICAgICBwYXJhbXM6IHoub2JqZWN0KHtcbiAgICAgICAgc2Vzc2lvbklkOiB6LnN0cmluZygpLFxuICAgICAgfSksXG4gICAgICByZXNwb25zZTogYnVpbGRTZXNzaW9uSGlzdG9yeVNjaGVtYShhZ2VudCksXG4gICAgfSxcbiAgICBcInNlc3Npb24ucG9zdFwiOiB7XG4gICAgICBwYXJhbXM6IHoub2JqZWN0KHtcbiAgICAgICAgc2Vzc2lvbklkOiB6LnN0cmluZygpLFxuICAgICAgfSksXG4gICAgICBib2R5OiB6LnVuaW9uKFt6LnN0cmluZygpLCBidWlsZFVJTWVzc2FnZVNjaGVtYShhZ2VudC50b29scyldKSxcbiAgICAgIHJlc3BvbnNlOiB6LmFueSgpLFxuICAgIH0sXG4gICAgXCJyZWNvbm5lY3QuZ2V0XCI6IHtcbiAgICAgIHBhcmFtczogei5vYmplY3Qoe1xuICAgICAgICBzZXNzaW9uSWQ6IHouc3RyaW5nKCksXG4gICAgICB9KSxcbiAgICAgIHJlc3BvbnNlOiB6LmFueSgpLFxuICAgIH0sXG4gICAgXCJpbnRlcnJ1cHQucG9zdFwiOiB7XG4gICAgICBwYXJhbXM6IHoub2JqZWN0KHtcbiAgICAgICAgc2Vzc2lvbklkOiB6LnN0cmluZygpLFxuICAgICAgfSksXG4gICAgICBib2R5OiB6XG4gICAgICAgIC5vYmplY3Qoe1xuICAgICAgICAgIGxhc3RQYXJ0OiB6XG4gICAgICAgICAgICAub2JqZWN0KHtcbiAgICAgICAgICAgICAgaW5kZXg6IHoubnVtYmVyKCksXG4gICAgICAgICAgICAgIHBhcnQ6IGJ1aWxkVUlNZXNzYWdlUGFydFNjaGVtYShhZ2VudC50b29scyksXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLm9wdGlvbmFsKCksXG4gICAgICAgIH0pXG4gICAgICAgIC5vcHRpb25hbCgpLFxuICAgICAgcmVzcG9uc2U6IHoub2JqZWN0KHtcbiAgICAgICAgc3VjY2Vzczogei5ib29sZWFuKCksXG4gICAgICB9KSxcbiAgICB9LFxuICB9IHNhdGlzZmllcyBSZWNvcmQ8XG4gICAgc3RyaW5nLFxuICAgIHtcbiAgICAgIHBhcmFtczogei5ab2RUeXBlO1xuICAgICAgYm9keT86IHouWm9kVHlwZTtcbiAgICAgIHJlc3BvbnNlOiB6LlpvZFR5cGU7XG4gICAgfVxuICA+O1xuXG4gIHJldHVybiBjb250cmFjdDtcbn1cblxuZXhwb3J0IHR5cGUgQWdlbnRDb250cmFjdDxBZ2VudCBleHRlbmRzIEFueUFnZW50PiA9IFJldHVyblR5cGU8XG4gIHR5cGVvZiBhZ2VudENvbnRyYWN0PEFnZW50PlxuPjtcblxuZXhwb3J0IHR5cGUgSW5mZXJDb250cmFjdDxBZ2VudCBleHRlbmRzIEFueUFnZW50PiA9IHtcbiAgW0sgaW4ga2V5b2YgQWdlbnRDb250cmFjdDxBZ2VudD5dOiB7XG4gICAgW0syIGluIGtleW9mIEFnZW50Q29udHJhY3Q8QWdlbnQ+W0tdXTogei5pbmZlcjxBZ2VudENvbnRyYWN0PEFnZW50PltLXVtLMl0+O1xuICB9O1xufTtcblxuZXhwb3J0IHR5cGUgSW5mZXJSZXNwb25zZTxcbiAgQWdlbnQgZXh0ZW5kcyBBbnlBZ2VudCxcbiAgS2V5IGV4dGVuZHMga2V5b2YgQWdlbnRDb250cmFjdDxBZ2VudD4sXG4+ID0gSW5mZXJDb250cmFjdDxBZ2VudD5bS2V5XVtcInJlc3BvbnNlXCJdO1xuIiwgImltcG9ydCB0eXBlIHtcbiAgRmlsZVVJUGFydCxcbiAgSW5mZXJVSVRvb2xzLFxuICBSZWFzb25pbmdVSVBhcnQsXG4gIFNvdXJjZVVybFVJUGFydCxcbiAgU3RlcFN0YXJ0VUlQYXJ0LFxuICBUZXh0VUlQYXJ0LFxuICBUb29sU2V0LFxuICBUb29sVUlQYXJ0LFxufSBmcm9tIFwiYWlcIjtcbmltcG9ydCB7IHogfSBmcm9tIFwiem9kXCI7XG5pbXBvcnQgdHlwZSB7IEFueUFnZW50IH0gZnJvbSBcIi4uL2FnZW50L2NsaWVudFwiO1xuXG50eXBlIFVJTWVzc2FnZVBhcnQ8VCBleHRlbmRzIFRvb2xTZXQ+ID1cbiAgfCBUZXh0VUlQYXJ0XG4gIHwgUmVhc29uaW5nVUlQYXJ0XG4gIHwgRmlsZVVJUGFydFxuICB8IFNvdXJjZVVybFVJUGFydFxuICB8IFN0ZXBTdGFydFVJUGFydFxuICB8IFRvb2xVSVBhcnQ8SW5mZXJVSVRvb2xzPFQ+PjtcblxuY29uc3QgVGV4dFBhcnQgPSB6Lm9iamVjdCh7XG4gIHR5cGU6IHoubGl0ZXJhbChcInRleHRcIiksXG4gIHRleHQ6IHouc3RyaW5nKCksXG59KTtcblxuY29uc3QgUmVhc29uaW5nUGFydCA9IHoub2JqZWN0KHtcbiAgdHlwZTogei5saXRlcmFsKFwicmVhc29uaW5nXCIpLFxuICB0ZXh0OiB6LnN0cmluZygpLFxufSk7XG5cbmNvbnN0IEZpbGVQYXJ0ID0gei5vYmplY3Qoe1xuICB0eXBlOiB6LmxpdGVyYWwoXCJmaWxlXCIpLFxuICBtZWRpYVR5cGU6IHouc3RyaW5nKCksXG4gIHVybDogei5zdHJpbmcoKSxcbiAgZmlsZW5hbWU6IHouc3RyaW5nKCkub3B0aW9uYWwoKSxcbn0pO1xuXG5jb25zdCBTb3VyY2VVcmxQYXJ0ID0gei5vYmplY3Qoe1xuICB0eXBlOiB6LmxpdGVyYWwoXCJzb3VyY2UtdXJsXCIpLFxuICBzb3VyY2VJZDogei5zdHJpbmcoKSxcbiAgdXJsOiB6LnN0cmluZygpLFxuICB0aXRsZTogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxufSk7XG5cbmNvbnN0IFN0ZXBTdGFydFBhcnQgPSB6Lm9iamVjdCh7XG4gIHR5cGU6IHoubGl0ZXJhbChcInN0ZXAtc3RhcnRcIiksXG59KTtcblxuZnVuY3Rpb24gdG9vbFBhcnRTY2hlbWFzKG5hbWU6IHN0cmluZywgdG9vbDogVG9vbFNldFtzdHJpbmddKSB7XG4gIGNvbnN0IGlucHV0ID0gdG9vbC5pbnB1dFNjaGVtYSA/PyB6LnVua25vd24oKTtcbiAgY29uc3Qgb3V0cHV0ID0gdG9vbC5vdXRwdXRTY2hlbWEgPz8gei51bmtub3duKCk7XG4gIGNvbnN0IHR5cGUgPSB6LmxpdGVyYWwoYHRvb2wtJHtuYW1lfWApO1xuXG4gIGNvbnN0IGFwcHJvdmFsSWQgPSB6Lm9iamVjdCh7IGlkOiB6LnN0cmluZygpIH0pO1xuICBjb25zdCBhcHByb3ZhbEFwcHJvdmVkID0gYXBwcm92YWxJZC5leHRlbmQoe1xuICAgIGFwcHJvdmVkOiB6LmxpdGVyYWwodHJ1ZSksXG4gICAgcmVhc29uOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG4gIH0pO1xuICBjb25zdCBhcHByb3ZhbERlbmllZCA9IGFwcHJvdmFsSWQuZXh0ZW5kKHtcbiAgICBhcHByb3ZlZDogei5saXRlcmFsKGZhbHNlKSxcbiAgICByZWFzb246IHouc3RyaW5nKCkub3B0aW9uYWwoKSxcbiAgfSk7XG4gIGNvbnN0IGFwcHJvdmFsUmVzcG9uc2UgPSBhcHByb3ZhbElkLmV4dGVuZCh7XG4gICAgYXBwcm92ZWQ6IHouYm9vbGVhbigpLFxuICAgIHJlYXNvbjogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuICB9KTtcblxuICByZXR1cm4gW1xuICAgIHoub2JqZWN0KHtcbiAgICAgIHR5cGUsXG4gICAgICB0b29sQ2FsbElkOiB6LnN0cmluZygpLFxuICAgICAgc3RhdGU6IHoubGl0ZXJhbChcImlucHV0LXN0cmVhbWluZ1wiKSxcbiAgICAgIGlucHV0OiB6LnVua25vd24oKSxcbiAgICB9KSxcbiAgICB6Lm9iamVjdCh7XG4gICAgICB0eXBlLFxuICAgICAgdG9vbENhbGxJZDogei5zdHJpbmcoKSxcbiAgICAgIHN0YXRlOiB6LmxpdGVyYWwoXCJpbnB1dC1hdmFpbGFibGVcIiksXG4gICAgICBpbnB1dCxcbiAgICB9KSxcbiAgICB6Lm9iamVjdCh7XG4gICAgICB0eXBlLFxuICAgICAgdG9vbENhbGxJZDogei5zdHJpbmcoKSxcbiAgICAgIHN0YXRlOiB6LmxpdGVyYWwoXCJhcHByb3ZhbC1yZXF1ZXN0ZWRcIiksXG4gICAgICBpbnB1dCxcbiAgICAgIGFwcHJvdmFsOiBhcHByb3ZhbElkLFxuICAgIH0pLFxuICAgIHoub2JqZWN0KHtcbiAgICAgIHR5cGUsXG4gICAgICB0b29sQ2FsbElkOiB6LnN0cmluZygpLFxuICAgICAgc3RhdGU6IHoubGl0ZXJhbChcImFwcHJvdmFsLXJlc3BvbmRlZFwiKSxcbiAgICAgIGlucHV0LFxuICAgICAgYXBwcm92YWw6IGFwcHJvdmFsUmVzcG9uc2UsXG4gICAgfSksXG4gICAgei5vYmplY3Qoe1xuICAgICAgdHlwZSxcbiAgICAgIHRvb2xDYWxsSWQ6IHouc3RyaW5nKCksXG4gICAgICBzdGF0ZTogei5saXRlcmFsKFwib3V0cHV0LWF2YWlsYWJsZVwiKSxcbiAgICAgIGlucHV0LFxuICAgICAgb3V0cHV0LFxuICAgICAgYXBwcm92YWw6IGFwcHJvdmFsQXBwcm92ZWQub3B0aW9uYWwoKSxcbiAgICB9KSxcbiAgICB6Lm9iamVjdCh7XG4gICAgICB0eXBlLFxuICAgICAgdG9vbENhbGxJZDogei5zdHJpbmcoKSxcbiAgICAgIHN0YXRlOiB6LmxpdGVyYWwoXCJvdXRwdXQtZXJyb3JcIiksXG4gICAgICBpbnB1dCxcbiAgICAgIGVycm9yVGV4dDogei5zdHJpbmcoKSxcbiAgICAgIGFwcHJvdmFsOiBhcHByb3ZhbEFwcHJvdmVkLm9wdGlvbmFsKCksXG4gICAgfSksXG4gICAgei5vYmplY3Qoe1xuICAgICAgdHlwZSxcbiAgICAgIHRvb2xDYWxsSWQ6IHouc3RyaW5nKCksXG4gICAgICBzdGF0ZTogei5saXRlcmFsKFwib3V0cHV0LWRlbmllZFwiKSxcbiAgICAgIGlucHV0LFxuICAgICAgYXBwcm92YWw6IGFwcHJvdmFsRGVuaWVkLFxuICAgIH0pLFxuICBdO1xufVxuXG5jb25zdCBVc2FnZVN1bW1hcnkgPSB6Lm9iamVjdCh7XG4gIG1vZGVsOiB6LnN0cmluZygpLFxuICBpbnB1dFRva2Vuczogei5udW1iZXIoKSxcbiAgb3V0cHV0VG9rZW5zOiB6Lm51bWJlcigpLFxuICB0b3RhbFRva2Vuczogei5udW1iZXIoKSxcbiAgY2FjaGVSZWFkVG9rZW5zOiB6Lm51bWJlcigpLFxuICBjYWNoZVdyaXRlVG9rZW5zOiB6Lm51bWJlcigpLFxuICByZWFzb25pbmdUb2tlbnM6IHoubnVtYmVyKCksXG4gIHN0ZXBDb3VudDogei5udW1iZXIoKSxcbn0pO1xuXG5jb25zdCBTZXNzaW9uVXNhZ2UgPSB6Lm9iamVjdCh7XG4gIHRvdGFsOiBVc2FnZVN1bW1hcnkuZXh0ZW5kKHsgbWVzc2FnZUNvdW50OiB6Lm51bWJlcigpIH0pLFxuICBieU1lc3NhZ2VJZDogei5yZWNvcmQoei5zdHJpbmcoKSwgVXNhZ2VTdW1tYXJ5Lm51bGxhYmxlKCkpLFxufSk7XG5cbmV4cG9ydCBmdW5jdGlvbiBidWlsZFNlc3Npb25IaXN0b3J5U2NoZW1hPEFnZW50IGV4dGVuZHMgQW55QWdlbnQ+KFxuICBhZ2VudDogQWdlbnRcbikge1xuICByZXR1cm4gei5vYmplY3Qoe1xuICAgIG1lc3NhZ2VzOiB6LmFycmF5KGJ1aWxkVUlNZXNzYWdlU2NoZW1hKGFnZW50LnRvb2xzKSksXG4gICAgc3RyZWFtaW5nTWVzc2FnZUlkOiB6LnN0cmluZygpLm51bGxhYmxlKCksXG4gICAgdXNhZ2U6IFNlc3Npb25Vc2FnZSxcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBidWlsZFVJTWVzc2FnZVBhcnRTY2hlbWE8VCBleHRlbmRzIFRvb2xTZXQ+KFxuICB0b29sczogVFxuKTogei5ab2RUeXBlPFVJTWVzc2FnZVBhcnQ8VD4+IHtcbiAgY29uc3QgdG9vbFBhcnRzID0gT2JqZWN0LmVudHJpZXModG9vbHMpLmZsYXRNYXAoKFtuYW1lLCB0b29sXSkgPT5cbiAgICB0b29sUGFydFNjaGVtYXMobmFtZSwgdG9vbClcbiAgKTtcblxuICBjb25zdCBhbGwgPSBbXG4gICAgVGV4dFBhcnQsXG4gICAgUmVhc29uaW5nUGFydCxcbiAgICBGaWxlUGFydCxcbiAgICBTb3VyY2VVcmxQYXJ0LFxuICAgIFN0ZXBTdGFydFBhcnQsXG4gICAgLi4udG9vbFBhcnRzLFxuICBdO1xuXG4gIHJldHVybiB6LnVuaW9uKGFsbCkgYXMgei5ab2RUeXBlPFVJTWVzc2FnZVBhcnQ8VD4+O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRVSU1lc3NhZ2VTY2hlbWE8VCBleHRlbmRzIFRvb2xTZXQ+KHRvb2xzOiBUKSB7XG4gIHJldHVybiB6Lm9iamVjdCh7XG4gICAgaWQ6IHouc3RyaW5nKCksXG4gICAgcm9sZTogei5lbnVtKFtcInN5c3RlbVwiLCBcInVzZXJcIiwgXCJhc3Npc3RhbnRcIl0pLFxuICAgIHBhcnRzOiB6LmFycmF5KGJ1aWxkVUlNZXNzYWdlUGFydFNjaGVtYSh0b29scykpLFxuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkU2Vzc2lvblVJU2NoZW1hPFQgZXh0ZW5kcyBUb29sU2V0Pih0b29sczogVCkge1xuICBjb25zdCBVSU1lc3NhZ2UgPSBidWlsZFVJTWVzc2FnZVNjaGVtYSh0b29scyk7XG5cbiAgcmV0dXJuIHoub2JqZWN0KHtcbiAgICB0aXRsZTogei5zdHJpbmcoKS5udWxsYWJsZSgpLFxuICAgIG1lc3NhZ2VzOiB6LmFycmF5KFVJTWVzc2FnZSksXG4gICAgc3RyZWFtaW5nTWVzc2FnZUlkOiB6LnN0cmluZygpLm51bGxhYmxlKCksXG4gICAgdXNhZ2U6IFNlc3Npb25Vc2FnZSxcbiAgfSk7XG59XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxTQUFTLHNCQUFzQiwwQkFBMEI7OztBQ0F6RCxTQUFTLFlBQVk7OztBQ0FkLElBQU0sV0FBVyxZQUFZO0FBQ2xDLE1BQUk7QUFDRixVQUFNLEVBQUUsbUJBQW1CLElBQUksTUFBTSxPQUFPLGNBQWM7QUFDMUQsV0FBTyxRQUFRLE1BQU0sbUJBQW1CLENBQUM7QUFBQSxFQUMzQyxRQUFRO0FBQ04s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WTtBQUN2QixjQUFNLFVBQVVGLE9BQU0sUUFBUSxPQUFPLFNBQVU7QUFDL0MsY0FBTSxRQUFRLFVBQVUsSUFBSTtBQUM1QixlQUFPLEVBQUUsU0FBUyxLQUFLO0FBQUEsTUFDekI7QUFFQSxZQUFNLFdBQVcsUUFBUSxZQUFZLGdCQUFnQjtBQUNyRCxVQUFJLFVBQVU7QUFDWixlQUFPLFNBQVMsS0FBSyxNQUFNLFNBQVMsRUFBRSxRQUFRLEtBQUssR0FBRyxJQUFJLENBQUM7QUFBQSxNQUM3RDtBQUVBLGFBQU8sU0FBUyxLQUFLLE1BQU0sS0FBSyxDQUFDO0FBQUEsSUFDbkM7QUFBQSxJQUNBLFNBQVMsZ0JBQWdCO0FBQUEsRUFDM0I7QUFFRixTQUFPO0FBQ1Q7IiwKICAibmFtZXMiOiBbImFnZW50IiwgImxvZyIsICJyZXNvbHZlIiwgImFnZW50IiwgInVsaWQiLCAidXNhZ2UiLCAiZXJyb3JlIiwgInVsaWQiLCAiYWdlbnQiLCAibG9nIiwgInJlYWRGaWxlIiwgInJlc29sdmUiLCAibG9nIiwgInRvb2wiLCAidWxpZCIsICJ6IiwgImV4ZWMiLCAiYWdlbnQiLCAidG9vbCIsICJ0b29sIiwgInoiLCAiYWdlbnQiLCAidWxpZCIsICJzdGFydCIsICJzdGF0ZSIsICJhZ2VudCIsICJyZXNvbHZlIiwgImxvZyIsICJzYW5kYm94IiwgInNhbmRib3hSZWNvcmQiLCAic3RyZWFtIiwgInVzYWdlIiwgImFnZW50IiwgImxvZyIsICJ1bGlkIiwgInVzYWdlIiwgIm5vdyIsICJpZCIsICJlcnJvcmUiLCAiYWdlbnQiLCAidWxpZCIsICJlcnJvcmUiLCAieiIsICJhZ2VudCIsICJhZ2VudCIsICJsb2ciLCAieiIsICJ6IiwgInRvb2wiLCAiYWdlbnQiLCAiYWxsIiwgImFnZW50IiwgInoiLCAiYWdlbnQiLCAic3RhcnQiLCAic3RyZWFtIl0KfQo=
|
|
336
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL3JwYy9ycGMudHMiLCAiLi4vc3JjL3JwYy9hZ2VudENvbnRyYWN0LnRzIiwgIi4uL3NyYy9ycGMvc2NoZW1hcy50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiaW1wb3J0IHsgb3BlbmFwaSB9IGZyb20gXCJAZWx5c2lhanMvb3BlbmFwaVwiO1xuaW1wb3J0IHsgY3JlYXRlVUlNZXNzYWdlU3RyZWFtUmVzcG9uc2UgfSBmcm9tIFwiYWlcIjtcbmltcG9ydCBFbHlzaWEgZnJvbSBcImVseXNpYVwiO1xuaW1wb3J0IHogZnJvbSBcInpvZFwiO1xuaW1wb3J0IHtcbiAgQWdlbnRTdGF0dXMsXG4gIHR5cGUgQW55QWdlbnQsXG4gIHR5cGUgU2Vzc2lvblNlbmRBcmdzLFxufSBmcm9tIFwiLi4vYWdlbnQvY2xpZW50XCI7XG5pbXBvcnQgdHlwZSB7IFNlbmRSZXN1bHQgfSBmcm9tIFwiLi4vc2Vzc2lvbi9zZW5kXCI7XG5pbXBvcnQge1xuICB0eXBlIEFnZW50Q29udHJhY3QsXG4gIGFnZW50Q29udHJhY3QsXG4gIHR5cGUgSW5mZXJDb250cmFjdCxcbiAgdHlwZSBJbmZlclJlc3BvbnNlLFxufSBmcm9tIFwiLi9hZ2VudENvbnRyYWN0XCI7XG5pbXBvcnQgeyB0eXBlIEJhc2VQYXRoLCBiYXNlUGF0aEZvckFnZW50IH0gZnJvbSBcIi4vYmFzZS1wYXRoXCI7XG5cbnR5cGUgV2l0aG91dDxPLCBLIGV4dGVuZHMga2V5b2YgTz4gPSBPbWl0PE8sIEs+O1xuXG5leHBvcnQgZnVuY3Rpb24gaGFuZGxlUmVxdWVzdDxcbiAgQWdlbnQgZXh0ZW5kcyBBbnlBZ2VudCxcbiAgQWdlbnRCYXNlUGF0aCBleHRlbmRzIHN0cmluZyA9IEJhc2VQYXRoLFxuPihcbiAgYWdlbnQ6IEFnZW50LFxuICBvcHRpb25zOiB7XG4gICAgYmFzZVBhdGg/OiBBZ2VudEJhc2VQYXRoO1xuICAgIHdvcmtmbG93PzogKFxuICAgICAgc2Vzc2lvbklkOiBzdHJpbmcsXG4gICAgICAuLi5hcmdzOiBTZXNzaW9uU2VuZEFyZ3M8QWdlbnQ+XG4gICAgKSA9PiBQcm9taXNlPFNlbmRSZXN1bHQ+O1xuICAgIG92ZXJyaWRlcz86IHtcbiAgICAgIFtLIGluIGtleW9mIEFnZW50Q29udHJhY3Q8QWdlbnQ+XT86IChcbiAgICAgICAgY29udHJhY3Q6IFdpdGhvdXQ8SW5mZXJDb250cmFjdDxBZ2VudD5bS10sIFwicmVzcG9uc2VcIj4sXG4gICAgICAgIG5leHQ6ICgpID0+IFByb21pc2U8SW5mZXJSZXNwb25zZTxBZ2VudCwgSz4gfCBSZXNwb25zZT5cbiAgICAgICkgPT4gUHJvbWlzZTxJbmZlclJlc3BvbnNlPEFnZW50LCBLPiB8IFJlc3BvbnNlPjtcbiAgICB9O1xuICB9ID0ge31cbikge1xuICBjb25zdCB7IGJhc2VQYXRoID0gYmFzZVBhdGhGb3JBZ2VudChhZ2VudC5uYW1lKSwgd29ya2Zsb3cgfSA9IG9wdGlvbnM7XG5cbiAgY29uc3QgY29udHJhY3QgPSBhZ2VudENvbnRyYWN0KGFnZW50KTtcblxuICBjb25zdCByb3V0ZXIgPSBuZXcgRWx5c2lhKHsgcHJlZml4OiBiYXNlUGF0aCB9KVxuICAgIC51c2UoXG4gICAgICBvcGVuYXBpKHtcbiAgICAgICAgcHJvdmlkZXI6IG51bGwsXG4gICAgICAgIHNwZWNQYXRoOiBcIi9vcGVuYXBpLmpzb25cIixcbiAgICAgICAgZXhjbHVkZTogeyBzdGF0aWNGaWxlOiBmYWxzZSB9LFxuICAgICAgICBkb2N1bWVudGF0aW9uOiB7XG4gICAgICAgICAgaW5mbzoge1xuICAgICAgICAgICAgdGl0bGU6IGAke2FnZW50Lm5hbWV9IEFQSWAsXG4gICAgICAgICAgICB2ZXJzaW9uOiBcIjEuMC4wXCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBjb21wb25lbnRzOiB7XG4gICAgICAgICAgICBzY2hlbWFzOiB7XG4gICAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgLSBlbHlzaWEgaXMgYW5ub3lpbmdcbiAgICAgICAgICAgICAgQWdlbnRTdGF0dXM6IHoudG9KU09OU2NoZW1hKEFnZW50U3RhdHVzLCB7XG4gICAgICAgICAgICAgICAgdGFyZ2V0OiBcIm9wZW5hcGktMy4wXCIsXG4gICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNlY3VyaXR5U2NoZW1lczoge1xuICAgICAgICAgICAgICBiZWFyZXJBdXRoOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJodHRwXCIsXG4gICAgICAgICAgICAgICAgc2NoZW1lOiBcImJlYXJlclwiLFxuICAgICAgICAgICAgICAgIGJlYXJlckZvcm1hdDogXCJKV1RcIixcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgbWFwSnNvblNjaGVtYToge1xuICAgICAgICAgIHpvZDogKHNjaGVtYTogei5ab2RUeXBlKSA9PlxuICAgICAgICAgICAgei50b0pTT05TY2hlbWEoc2NoZW1hLCB7IHRhcmdldDogXCJvcGVuYXBpLTMuMFwiIH0pLFxuICAgICAgICB9LFxuICAgICAgfSlcbiAgICApXG4gICAgLmdldChcbiAgICAgIFwiLzpzZXNzaW9uSWRcIixcbiAgICAgIGFzeW5jICh7IHBhcmFtcyB9KSA9PiB7XG4gICAgICAgIGNvbnN0IG5leHQgPSBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgY29uc3Qgc2Vzc2lvbiA9IGFnZW50LnNlc3Npb24ocGFyYW1zLnNlc3Npb25JZCEpO1xuICAgICAgICAgIGNvbnN0IHVpID0gYXdhaXQgc2Vzc2lvbi5oaXN0b3J5KCk7XG4gICAgICAgICAgcmV0dXJuIHVpO1xuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IG92ZXJyaWRlID0gb3B0aW9ucy5vdmVycmlkZXM/LltcInNlc3Npb24uZ2V0XCJdO1xuICAgICAgICBpZiAob3ZlcnJpZGUpIHtcbiAgICAgICAgICByZXR1cm4gUmVzcG9uc2UuanNvbihcbiAgICAgICAgICAgIGF3YWl0IG92ZXJyaWRlKFxuICAgICAgICAgICAgICB7IHBhcmFtcyB9LFxuICAgICAgICAgICAgICAvLyBUT0RPIG1ha2UgdGhlIG1pc21hdGNoZWQgdHlwZXMgd2l0aCBBSSBTREsgbGVzcyB3ZWlyZFxuICAgICAgICAgICAgICBuZXh0IGFzICgpID0+IFByb21pc2U8XG4gICAgICAgICAgICAgICAgSW5mZXJSZXNwb25zZTxBZ2VudCwgXCJzZXNzaW9uLmdldFwiPiB8IFJlc3BvbnNlXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgIClcbiAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFJlc3BvbnNlLmpzb24oYXdhaXQgbmV4dCgpKTtcbiAgICAgIH0sXG4gICAgICBjb250cmFjdFtcInNlc3Npb24uZ2V0XCJdXG4gICAgKVxuICAgIC5wb3N0KFxuICAgICAgXCIvOnNlc3Npb25JZFwiLFxuICAgICAgYXN5bmMgKHsgcGFyYW1zLCBib2R5IH0pID0+IHtcbiAgICAgICAgY29uc3QgbmV4dCA9IGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCBzZXNzaW9uID0gYWdlbnQuc2Vzc2lvbihwYXJhbXMuc2Vzc2lvbklkISk7XG5cbiAgICAgICAgICBpZiAod29ya2Zsb3cpIHtcbiAgICAgICAgICAgIGNvbnN0IHsgc3RhcnQgfSA9IGF3YWl0IGltcG9ydChcIndvcmtmbG93L2FwaVwiKTtcblxuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3RhcnQoXG4gICAgICAgICAgICAgIC8vIGZvciBzb21lIHJlYXNvbiwgc3RhcnQoKSByZXF1aXJlcyBTZXNzaW9uU2VuZEFyZ3M8QW55QWdlbnQ+XG4gICAgICAgICAgICAgIC8vIHRvIGF2b2lkIGJsb3dpbmcgdXAgdHlwZXNcbiAgICAgICAgICAgICAgLy8gd2Ugd2FudCB0byBwdXQgdGhlIHR5cGVndWFyZCBoZXJlIHNvIGNvbnN1bWVycyBvZiBoYW5kbGVSZXF1ZXN0IHN0aWxsIHdvcmsgZmluZVxuICAgICAgICAgICAgICB3b3JrZmxvdyBhcyAoXG4gICAgICAgICAgICAgICAgc2Vzc2lvbklkOiBzdHJpbmcsXG4gICAgICAgICAgICAgICAgLi4uYXJnczogU2Vzc2lvblNlbmRBcmdzPEFueUFnZW50PlxuICAgICAgICAgICAgICApID0+IFByb21pc2U8U2VuZFJlc3VsdD4sXG4gICAgICAgICAgICAgIFtwYXJhbXMuc2Vzc2lvbklkISwgYm9keV1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBhd2FpdCBzZXNzaW9uLnN0cmVhbShyZXN1bHQpO1xuICAgICAgICAgICAgcmV0dXJuIGNyZWF0ZVVJTWVzc2FnZVN0cmVhbVJlc3BvbnNlKHsgc3RyZWFtIH0pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGF3YWl0IHNlc3Npb24uc2VuZChib2R5KTtcbiAgICAgICAgICBjb25zdCBzdHJlYW0gPSBhd2FpdCBzZXNzaW9uLnN0cmVhbSgpO1xuICAgICAgICAgIHJldHVybiBjcmVhdGVVSU1lc3NhZ2VTdHJlYW1SZXNwb25zZSh7IHN0cmVhbSB9KTtcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBvdmVycmlkZSA9IG9wdGlvbnMub3ZlcnJpZGVzPy5bXCJzZXNzaW9uLnBvc3RcIl07XG4gICAgICAgIGlmIChvdmVycmlkZSkge1xuICAgICAgICAgIHJldHVybiBhd2FpdCBvdmVycmlkZSh7IHBhcmFtcywgYm9keSB9LCBuZXh0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBhd2FpdCBuZXh0KCk7XG4gICAgICB9LFxuICAgICAgY29udHJhY3RbXCJzZXNzaW9uLnBvc3RcIl1cbiAgICApXG4gICAgLmdldChcbiAgICAgIFwiLzpzZXNzaW9uSWQvcmVjb25uZWN0XCIsXG4gICAgICBhc3luYyAoeyBwYXJhbXMgfSkgPT4ge1xuICAgICAgICBjb25zdCBuZXh0ID0gYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHNlc3Npb24gPSBhZ2VudC5zZXNzaW9uKHBhcmFtcy5zZXNzaW9uSWQhKTtcbiAgICAgICAgICBjb25zdCBzdHJlYW0gPSBhd2FpdCBzZXNzaW9uLnN0cmVhbSgpO1xuICAgICAgICAgIHJldHVybiBjcmVhdGVVSU1lc3NhZ2VTdHJlYW1SZXNwb25zZSh7IHN0cmVhbSB9KTtcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBvdmVycmlkZSA9IG9wdGlvbnMub3ZlcnJpZGVzPy5bXCJyZWNvbm5lY3QuZ2V0XCJdO1xuICAgICAgICBpZiAob3ZlcnJpZGUpIHtcbiAgICAgICAgICByZXR1cm4gYXdhaXQgb3ZlcnJpZGUoeyBwYXJhbXMgfSwgbmV4dCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYXdhaXQgbmV4dCgpO1xuICAgICAgfSxcbiAgICAgIGNvbnRyYWN0W1wicmVjb25uZWN0LmdldFwiXVxuICAgIClcbiAgICAucG9zdChcbiAgICAgIFwiLzpzZXNzaW9uSWQvaW50ZXJydXB0XCIsXG5cbiAgICAgIGFzeW5jICh7IHBhcmFtcywgYm9keSB9KSA9PiB7XG4gICAgICAgIGNvbnN0IG5leHQgPSBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgY29uc3Qgc2Vzc2lvbiA9IGFnZW50LnNlc3Npb24ocGFyYW1zLnNlc3Npb25JZCEpO1xuICAgICAgICAgIGF3YWl0IHNlc3Npb24uaW50ZXJydXB0KGJvZHkpO1xuICAgICAgICAgIHJldHVybiB7IHN1Y2Nlc3M6IHRydWUgfTtcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBvdmVycmlkZSA9IG9wdGlvbnMub3ZlcnJpZGVzPy5bXCJpbnRlcnJ1cHQucG9zdFwiXTtcbiAgICAgICAgaWYgKG92ZXJyaWRlKSB7XG4gICAgICAgICAgcmV0dXJuIFJlc3BvbnNlLmpzb24oYXdhaXQgb3ZlcnJpZGUoeyBwYXJhbXMsIGJvZHkgfSwgbmV4dCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFJlc3BvbnNlLmpzb24oYXdhaXQgbmV4dCgpKTtcbiAgICAgIH0sXG4gICAgICBjb250cmFjdFtcImludGVycnVwdC5wb3N0XCJdXG4gICAgKTtcblxuICByZXR1cm4gcm91dGVyO1xufVxuIiwgImltcG9ydCB6IGZyb20gXCJ6b2RcIjtcbmltcG9ydCB0eXBlIHsgQW55QWdlbnQgfSBmcm9tIFwiLi4vYWdlbnQvY2xpZW50XCI7XG5pbXBvcnQge1xuICBidWlsZFNlc3Npb25IaXN0b3J5U2NoZW1hLFxuICBidWlsZFVJTWVzc2FnZVBhcnRTY2hlbWEsXG4gIGJ1aWxkVUlNZXNzYWdlU2NoZW1hLFxufSBmcm9tIFwiLi9zY2hlbWFzXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBhZ2VudENvbnRyYWN0PEFnZW50IGV4dGVuZHMgQW55QWdlbnQ+KGFnZW50OiBBZ2VudCkge1xuICBjb25zdCBjb250cmFjdCA9IHtcbiAgICBcInNlc3Npb24uZ2V0XCI6IHtcbiAgICAgIHBhcmFtczogei5vYmplY3Qoe1xuICAgICAgICBzZXNzaW9uSWQ6IHouc3RyaW5nKCksXG4gICAgICB9KSxcbiAgICAgIHJlc3BvbnNlOiBidWlsZFNlc3Npb25IaXN0b3J5U2NoZW1hKGFnZW50KSxcbiAgICB9LFxuICAgIFwic2Vzc2lvbi5wb3N0XCI6IHtcbiAgICAgIHBhcmFtczogei5vYmplY3Qoe1xuICAgICAgICBzZXNzaW9uSWQ6IHouc3RyaW5nKCksXG4gICAgICB9KSxcbiAgICAgIGJvZHk6IHoudW5pb24oW3ouc3RyaW5nKCksIGJ1aWxkVUlNZXNzYWdlU2NoZW1hKGFnZW50LnRvb2xzKV0pLFxuICAgICAgcmVzcG9uc2U6IHouYW55KCksXG4gICAgfSxcbiAgICBcInJlY29ubmVjdC5nZXRcIjoge1xuICAgICAgcGFyYW1zOiB6Lm9iamVjdCh7XG4gICAgICAgIHNlc3Npb25JZDogei5zdHJpbmcoKSxcbiAgICAgIH0pLFxuICAgICAgcmVzcG9uc2U6IHouYW55KCksXG4gICAgfSxcbiAgICBcImludGVycnVwdC5wb3N0XCI6IHtcbiAgICAgIHBhcmFtczogei5vYmplY3Qoe1xuICAgICAgICBzZXNzaW9uSWQ6IHouc3RyaW5nKCksXG4gICAgICB9KSxcbiAgICAgIGJvZHk6IHpcbiAgICAgICAgLm9iamVjdCh7XG4gICAgICAgICAgbGFzdFBhcnQ6IHpcbiAgICAgICAgICAgIC5vYmplY3Qoe1xuICAgICAgICAgICAgICBpbmRleDogei5udW1iZXIoKSxcbiAgICAgICAgICAgICAgcGFydDogYnVpbGRVSU1lc3NhZ2VQYXJ0U2NoZW1hKGFnZW50LnRvb2xzKSxcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAub3B0aW9uYWwoKSxcbiAgICAgICAgfSlcbiAgICAgICAgLm9wdGlvbmFsKCksXG4gICAgICByZXNwb25zZTogei5vYmplY3Qoe1xuICAgICAgICBzdWNjZXNzOiB6LmJvb2xlYW4oKSxcbiAgICAgIH0pLFxuICAgIH0sXG4gIH0gc2F0aXNmaWVzIFJlY29yZDxcbiAgICBzdHJpbmcsXG4gICAge1xuICAgICAgcGFyYW1zOiB6LlpvZFR5cGU7XG4gICAgICBib2R5Pzogei5ab2RUeXBlO1xuICAgICAgcmVzcG9uc2U6IHouWm9kVHlwZTtcbiAgICB9XG4gID47XG5cbiAgcmV0dXJuIGNvbnRyYWN0O1xufVxuXG5leHBvcnQgdHlwZSBBZ2VudENvbnRyYWN0PEFnZW50IGV4dGVuZHMgQW55QWdlbnQ+ID0gUmV0dXJuVHlwZTxcbiAgdHlwZW9mIGFnZW50Q29udHJhY3Q8QWdlbnQ+XG4+O1xuXG5leHBvcnQgdHlwZSBJbmZlckNvbnRyYWN0PEFnZW50IGV4dGVuZHMgQW55QWdlbnQ+ID0ge1xuICBbSyBpbiBrZXlvZiBBZ2VudENvbnRyYWN0PEFnZW50Pl06IHtcbiAgICBbSzIgaW4ga2V5b2YgQWdlbnRDb250cmFjdDxBZ2VudD5bS11dOiB6LmluZmVyPEFnZW50Q29udHJhY3Q8QWdlbnQ+W0tdW0syXT47XG4gIH07XG59O1xuXG5leHBvcnQgdHlwZSBJbmZlclJlc3BvbnNlPFxuICBBZ2VudCBleHRlbmRzIEFueUFnZW50LFxuICBLZXkgZXh0ZW5kcyBrZXlvZiBBZ2VudENvbnRyYWN0PEFnZW50Pixcbj4gPSBJbmZlckNvbnRyYWN0PEFnZW50PltLZXldW1wicmVzcG9uc2VcIl07XG4iLCAiaW1wb3J0IHR5cGUge1xuICBGaWxlVUlQYXJ0LFxuICBJbmZlclVJVG9vbHMsXG4gIFJlYXNvbmluZ1VJUGFydCxcbiAgU291cmNlVXJsVUlQYXJ0LFxuICBTdGVwU3RhcnRVSVBhcnQsXG4gIFRleHRVSVBhcnQsXG4gIFRvb2xTZXQsXG4gIFRvb2xVSVBhcnQsXG59IGZyb20gXCJhaVwiO1xuaW1wb3J0IHsgeiB9IGZyb20gXCJ6b2RcIjtcbmltcG9ydCB0eXBlIHsgQW55QWdlbnQgfSBmcm9tIFwiLi4vYWdlbnQvY2xpZW50XCI7XG5cbnR5cGUgVUlNZXNzYWdlUGFydDxUIGV4dGVuZHMgVG9vbFNldD4gPVxuICB8IFRleHRVSVBhcnRcbiAgfCBSZWFzb25pbmdVSVBhcnRcbiAgfCBGaWxlVUlQYXJ0XG4gIHwgU291cmNlVXJsVUlQYXJ0XG4gIHwgU3RlcFN0YXJ0VUlQYXJ0XG4gIHwgVG9vbFVJUGFydDxJbmZlclVJVG9vbHM8VD4+O1xuXG5jb25zdCBUZXh0UGFydCA9IHoub2JqZWN0KHtcbiAgdHlwZTogei5saXRlcmFsKFwidGV4dFwiKSxcbiAgdGV4dDogei5zdHJpbmcoKSxcbn0pO1xuXG5jb25zdCBSZWFzb25pbmdQYXJ0ID0gei5vYmplY3Qoe1xuICB0eXBlOiB6LmxpdGVyYWwoXCJyZWFzb25pbmdcIiksXG4gIHRleHQ6IHouc3RyaW5nKCksXG59KTtcblxuY29uc3QgRmlsZVBhcnQgPSB6Lm9iamVjdCh7XG4gIHR5cGU6IHoubGl0ZXJhbChcImZpbGVcIiksXG4gIG1lZGlhVHlwZTogei5zdHJpbmcoKSxcbiAgdXJsOiB6LnN0cmluZygpLFxuICBmaWxlbmFtZTogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxufSk7XG5cbmNvbnN0IFNvdXJjZVVybFBhcnQgPSB6Lm9iamVjdCh7XG4gIHR5cGU6IHoubGl0ZXJhbChcInNvdXJjZS11cmxcIiksXG4gIHNvdXJjZUlkOiB6LnN0cmluZygpLFxuICB1cmw6IHouc3RyaW5nKCksXG4gIHRpdGxlOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG59KTtcblxuY29uc3QgU3RlcFN0YXJ0UGFydCA9IHoub2JqZWN0KHtcbiAgdHlwZTogei5saXRlcmFsKFwic3RlcC1zdGFydFwiKSxcbn0pO1xuXG5mdW5jdGlvbiB0b29sUGFydFNjaGVtYXMobmFtZTogc3RyaW5nLCB0b29sOiBUb29sU2V0W3N0cmluZ10pIHtcbiAgY29uc3QgaW5wdXQgPSB0b29sLmlucHV0U2NoZW1hID8/IHoudW5rbm93bigpO1xuICBjb25zdCBvdXRwdXQgPSB0b29sLm91dHB1dFNjaGVtYSA/PyB6LnVua25vd24oKTtcbiAgY29uc3QgdHlwZSA9IHoubGl0ZXJhbChgdG9vbC0ke25hbWV9YCk7XG5cbiAgY29uc3QgYXBwcm92YWxJZCA9IHoub2JqZWN0KHsgaWQ6IHouc3RyaW5nKCkgfSk7XG4gIGNvbnN0IGFwcHJvdmFsQXBwcm92ZWQgPSBhcHByb3ZhbElkLmV4dGVuZCh7XG4gICAgYXBwcm92ZWQ6IHoubGl0ZXJhbCh0cnVlKSxcbiAgICByZWFzb246IHouc3RyaW5nKCkub3B0aW9uYWwoKSxcbiAgfSk7XG4gIGNvbnN0IGFwcHJvdmFsRGVuaWVkID0gYXBwcm92YWxJZC5leHRlbmQoe1xuICAgIGFwcHJvdmVkOiB6LmxpdGVyYWwoZmFsc2UpLFxuICAgIHJlYXNvbjogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuICB9KTtcbiAgY29uc3QgYXBwcm92YWxSZXNwb25zZSA9IGFwcHJvdmFsSWQuZXh0ZW5kKHtcbiAgICBhcHByb3ZlZDogei5ib29sZWFuKCksXG4gICAgcmVhc29uOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG4gIH0pO1xuXG4gIHJldHVybiBbXG4gICAgei5vYmplY3Qoe1xuICAgICAgdHlwZSxcbiAgICAgIHRvb2xDYWxsSWQ6IHouc3RyaW5nKCksXG4gICAgICBzdGF0ZTogei5saXRlcmFsKFwiaW5wdXQtc3RyZWFtaW5nXCIpLFxuICAgICAgaW5wdXQ6IHoudW5rbm93bigpLFxuICAgIH0pLFxuICAgIHoub2JqZWN0KHtcbiAgICAgIHR5cGUsXG4gICAgICB0b29sQ2FsbElkOiB6LnN0cmluZygpLFxuICAgICAgc3RhdGU6IHoubGl0ZXJhbChcImlucHV0LWF2YWlsYWJsZVwiKSxcbiAgICAgIGlucHV0LFxuICAgIH0pLFxuICAgIHoub2JqZWN0KHtcbiAgICAgIHR5cGUsXG4gICAgICB0b29sQ2FsbElkOiB6LnN0cmluZygpLFxuICAgICAgc3RhdGU6IHoubGl0ZXJhbChcImFwcHJvdmFsLXJlcXVlc3RlZFwiKSxcbiAgICAgIGlucHV0LFxuICAgICAgYXBwcm92YWw6IGFwcHJvdmFsSWQsXG4gICAgfSksXG4gICAgei5vYmplY3Qoe1xuICAgICAgdHlwZSxcbiAgICAgIHRvb2xDYWxsSWQ6IHouc3RyaW5nKCksXG4gICAgICBzdGF0ZTogei5saXRlcmFsKFwiYXBwcm92YWwtcmVzcG9uZGVkXCIpLFxuICAgICAgaW5wdXQsXG4gICAgICBhcHByb3ZhbDogYXBwcm92YWxSZXNwb25zZSxcbiAgICB9KSxcbiAgICB6Lm9iamVjdCh7XG4gICAgICB0eXBlLFxuICAgICAgdG9vbENhbGxJZDogei5zdHJpbmcoKSxcbiAgICAgIHN0YXRlOiB6LmxpdGVyYWwoXCJvdXRwdXQtYXZhaWxhYmxlXCIpLFxuICAgICAgaW5wdXQsXG4gICAgICBvdXRwdXQsXG4gICAgICBhcHByb3ZhbDogYXBwcm92YWxBcHByb3ZlZC5vcHRpb25hbCgpLFxuICAgIH0pLFxuICAgIHoub2JqZWN0KHtcbiAgICAgIHR5cGUsXG4gICAgICB0b29sQ2FsbElkOiB6LnN0cmluZygpLFxuICAgICAgc3RhdGU6IHoubGl0ZXJhbChcIm91dHB1dC1lcnJvclwiKSxcbiAgICAgIGlucHV0LFxuICAgICAgZXJyb3JUZXh0OiB6LnN0cmluZygpLFxuICAgICAgYXBwcm92YWw6IGFwcHJvdmFsQXBwcm92ZWQub3B0aW9uYWwoKSxcbiAgICB9KSxcbiAgICB6Lm9iamVjdCh7XG4gICAgICB0eXBlLFxuICAgICAgdG9vbENhbGxJZDogei5zdHJpbmcoKSxcbiAgICAgIHN0YXRlOiB6LmxpdGVyYWwoXCJvdXRwdXQtZGVuaWVkXCIpLFxuICAgICAgaW5wdXQsXG4gICAgICBhcHByb3ZhbDogYXBwcm92YWxEZW5pZWQsXG4gICAgfSksXG4gIF07XG59XG5cbmNvbnN0IFVzYWdlU3VtbWFyeSA9IHoub2JqZWN0KHtcbiAgbW9kZWw6IHouc3RyaW5nKCksXG4gIGlucHV0VG9rZW5zOiB6Lm51bWJlcigpLFxuICBvdXRwdXRUb2tlbnM6IHoubnVtYmVyKCksXG4gIHRvdGFsVG9rZW5zOiB6Lm51bWJlcigpLFxuICBjYWNoZVJlYWRUb2tlbnM6IHoubnVtYmVyKCksXG4gIGNhY2hlV3JpdGVUb2tlbnM6IHoubnVtYmVyKCksXG4gIHJlYXNvbmluZ1Rva2Vuczogei5udW1iZXIoKSxcbiAgc3RlcENvdW50OiB6Lm51bWJlcigpLFxufSk7XG5cbmNvbnN0IFNlc3Npb25Vc2FnZSA9IHoub2JqZWN0KHtcbiAgdG90YWw6IFVzYWdlU3VtbWFyeS5leHRlbmQoeyBtZXNzYWdlQ291bnQ6IHoubnVtYmVyKCkgfSksXG4gIGJ5TWVzc2FnZUlkOiB6LnJlY29yZCh6LnN0cmluZygpLCBVc2FnZVN1bW1hcnkubnVsbGFibGUoKSksXG59KTtcblxuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkU2Vzc2lvbkhpc3RvcnlTY2hlbWE8QWdlbnQgZXh0ZW5kcyBBbnlBZ2VudD4oXG4gIGFnZW50OiBBZ2VudFxuKSB7XG4gIHJldHVybiB6Lm9iamVjdCh7XG4gICAgbWVzc2FnZXM6IHouYXJyYXkoYnVpbGRVSU1lc3NhZ2VTY2hlbWEoYWdlbnQudG9vbHMpKSxcbiAgICBzdHJlYW1pbmdNZXNzYWdlSWQ6IHouc3RyaW5nKCkubnVsbGFibGUoKSxcbiAgICB1c2FnZTogU2Vzc2lvblVzYWdlLFxuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkVUlNZXNzYWdlUGFydFNjaGVtYTxUIGV4dGVuZHMgVG9vbFNldD4oXG4gIHRvb2xzOiBUXG4pOiB6LlpvZFR5cGU8VUlNZXNzYWdlUGFydDxUPj4ge1xuICBjb25zdCB0b29sUGFydHMgPSBPYmplY3QuZW50cmllcyh0b29scykuZmxhdE1hcCgoW25hbWUsIHRvb2xdKSA9PlxuICAgIHRvb2xQYXJ0U2NoZW1hcyhuYW1lLCB0b29sKVxuICApO1xuXG4gIGNvbnN0IGFsbCA9IFtcbiAgICBUZXh0UGFydCxcbiAgICBSZWFzb25pbmdQYXJ0LFxuICAgIEZpbGVQYXJ0LFxuICAgIFNvdXJjZVVybFBhcnQsXG4gICAgU3RlcFN0YXJ0UGFydCxcbiAgICAuLi50b29sUGFydHMsXG4gIF07XG5cbiAgcmV0dXJuIHoudW5pb24oYWxsKSBhcyB6LlpvZFR5cGU8VUlNZXNzYWdlUGFydDxUPj47XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBidWlsZFVJTWVzc2FnZVNjaGVtYTxUIGV4dGVuZHMgVG9vbFNldD4odG9vbHM6IFQpIHtcbiAgcmV0dXJuIHoub2JqZWN0KHtcbiAgICBpZDogei5zdHJpbmcoKSxcbiAgICByb2xlOiB6LmVudW0oW1wic3lzdGVtXCIsIFwidXNlclwiLCBcImFzc2lzdGFudFwiXSksXG4gICAgcGFydHM6IHouYXJyYXkoYnVpbGRVSU1lc3NhZ2VQYXJ0U2NoZW1hKHRvb2xzKSksXG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRTZXNzaW9uVUlTY2hlbWE8VCBleHRlbmRzIFRvb2xTZXQ+KHRvb2xzOiBUKSB7XG4gIGNvbnN0IFVJTWVzc2FnZSA9IGJ1aWxkVUlNZXNzYWdlU2NoZW1hKHRvb2xzKTtcblxuICByZXR1cm4gei5vYmplY3Qoe1xuICAgIHRpdGxlOiB6LnN0cmluZygpLm51bGxhYmxlKCksXG4gICAgbWVzc2FnZXM6IHouYXJyYXkoVUlNZXNzYWdlKSxcbiAgICBzdHJlYW1pbmdNZXNzYWdlSWQ6IHouc3RyaW5nKCkubnVsbGFibGUoKSxcbiAgICB1c2FnZTogU2Vzc2lvblVzYWdlLFxuICB9KTtcbn1cbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7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QSxjQUFNLFFBQVEsS0FBSyxJQUFJO0FBQ3ZCLGNBQU0sU0FBUyxNQUFNLFFBQVEsT0FBTztBQUNwQyxlQUFPLDhCQUE4QixFQUFFLE9BQU8sQ0FBQztBQUFBLE1BQ2pEO0FBRUEsWUFBTSxXQUFXLFFBQVEsWUFBWSxjQUFjO0FBQ25ELFVBQUksVUFBVTtBQUNaLGVBQU8sTUFBTSxTQUFTLEVBQUUsUUFBUSxLQUFLLEdBQUcsSUFBSTtBQUFBLE1BQzlDO0FBRUEsYUFBTyxNQUFNLEtBQUs7QUFBQSxJQUNwQjtBQUFBLElBQ0EsU0FBUyxjQUFjO0FBQUEsRUFDekIsRUFDQztBQUFBLElBQ0M7QUFBQSxJQUNBLE9BQU8sRUFBRSxPQUFPLE1BQU07QUFDcEIsWUFBTSxPQUFPLFlBQVk7QUFDdkIsY0FBTSxVQUFVRixPQUFNLFFBQVEsT0FBTyxTQUFVO0FBQy9DLGNBQU0sU0FBUyxNQUFNLFFBQVEsT0FBTztBQUNwQyxlQUFPLDhCQUE4QixFQUFFLE9BQU8sQ0FBQztBQUFBLE1BQ2pEO0FBRUEsWUFBTSxXQUFXLFFBQVEsWUFBWSxlQUFlO0FBQ3BELFVBQUksVUFBVTtBQUNaLGVBQU8sTUFBTSxTQUFTLEVBQUUsT0FBTyxHQUFHLElBQUk7QUFBQSxNQUN4QztBQUVBLGFBQU8sTUFBTSxLQUFLO0FBQUEsSUFDcEI7QUFBQSxJQUNBLFNBQVMsZUFBZTtBQUFBLEVBQzFCLEVBQ0M7QUFBQSxJQUNDO0FBQUEsSUFFQSxPQUFPLEVBQUUsUUFBUSxLQUFLLE1BQU07QUFDMUIsWUFBTSxPQUFPLFlBQVk7QUFDdkIsY0FBTSxVQUFVQSxPQUFNLFFBQVEsT0FBTyxTQUFVO0FBQy9DLGNBQU0sUUFBUSxVQUFVLElBQUk7QUFDNUIsZUFBTyxFQUFFLFNBQVMsS0FBSztBQUFBLE1BQ3pCO0FBRUEsWUFBTSxXQUFXLFFBQVEsWUFBWSxnQkFBZ0I7QUFDckQsVUFBSSxVQUFVO0FBQ1osZUFBTyxTQUFTLEtBQUssTUFBTSxTQUFTLEVBQUUsUUFBUSxLQUFLLEdBQUcsSUFBSSxDQUFDO0FBQUEsTUFDN0Q7QUFFQSxhQUFPLFNBQVMsS0FBSyxNQUFNLEtBQUssQ0FBQztBQUFBLElBQ25DO0FBQUEsSUFDQSxTQUFTLGdCQUFnQjtBQUFBLEVBQzNCO0FBRUYsU0FBTztBQUNUOyIsCiAgIm5hbWVzIjogWyJ6IiwgInoiLCAidG9vbCIsICJhZ2VudCIsICJhZ2VudCIsICJ6IiwgImFnZW50IiwgInoiLCAic3RyZWFtIl0KfQo=
|