@cartanova/qgrid-cli 2.3.2 → 2.3.3
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/bundle/dist/application/qgrid/qgrid.dispatcher.js +91 -278
- package/bundle/dist/application/qgrid/qgrid.frame.js +15 -5
- package/bundle/dist/utils/providers/anthropic/anthropic-constants.js +33 -12
- package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +39 -96
- package/bundle/dist/utils/providers/anthropic/claude-session.js +47 -32
- package/bundle/dist/utils/providers/anthropic/stream-json-adapter.js +3 -36
- package/bundle/dist/utils/providers/common/model-cost.js +3 -2
- package/bundle/dist/utils/providers/openai/codex-worker.js +1 -2
- package/bundle/dist/utils/providers/openai/openai-dispatcher.js +19 -12
- package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +193 -6
- package/bundle/src/application/qgrid/qgrid.dispatcher.ts +140 -364
- package/bundle/src/application/qgrid/qgrid.frame.ts +38 -23
- package/bundle/src/utils/providers/anthropic/anthropic-constants.test.ts +60 -0
- package/bundle/src/utils/providers/anthropic/anthropic-constants.ts +57 -16
- package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.test.ts +92 -340
- package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +50 -185
- package/bundle/src/utils/providers/anthropic/claude-session.test.ts +71 -62
- package/bundle/src/utils/providers/anthropic/claude-session.ts +56 -46
- package/bundle/src/utils/providers/anthropic/stream-json-adapter.test.ts +19 -30
- package/bundle/src/utils/providers/anthropic/stream-json-adapter.ts +24 -101
- package/bundle/src/utils/providers/common/model-cost.test.ts +19 -1
- package/bundle/src/utils/providers/common/model-cost.ts +2 -1
- package/bundle/src/utils/providers/common/provider-dispatcher.ts +7 -4
- package/bundle/src/utils/providers/openai/codex-worker.ts +2 -8
- package/bundle/src/utils/providers/openai/openai-dispatcher.ts +18 -11
- package/package.json +1 -1
|
@@ -52,10 +52,14 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
52
52
|
}
|
|
53
53
|
async onTokenRemoved(id) {
|
|
54
54
|
const workers = this.workerPool.get(id) ?? [];
|
|
55
|
+
const tokenName = workers[0]?.tokenName;
|
|
55
56
|
this.workerPool.delete(id);
|
|
56
57
|
await Promise.allSettled(workers.map((w) => w.kill()));
|
|
57
58
|
if (this.getAllReadyActiveWorkers().length === 0) this.rejectAllQueued("NO_OPENAI_WORKERS");
|
|
58
|
-
if (workers.length > 0)
|
|
59
|
+
if (workers.length > 0) {
|
|
60
|
+
const label = tokenName ?? `token ${id}`;
|
|
61
|
+
logger.info(`workers removed: ${label} (${workers.length})`);
|
|
62
|
+
}
|
|
59
63
|
}
|
|
60
64
|
async onTokenUpdated(id, name, credentials) {
|
|
61
65
|
const existing = this.workerPool.get(id) ?? [];
|
|
@@ -65,7 +69,7 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
65
69
|
}
|
|
66
70
|
if (existing.every((w) => w.canReuseForToken(name, credentials))) {
|
|
67
71
|
existing.forEach((w) => w.updateTokenState(name, credentials));
|
|
68
|
-
logger.info(`workers updated in-place
|
|
72
|
+
logger.info(`workers updated in-place: ${name}`);
|
|
69
73
|
this.drainQueue();
|
|
70
74
|
return;
|
|
71
75
|
}
|
|
@@ -74,18 +78,24 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
74
78
|
await this.spawnWorkers(id, name, credentials);
|
|
75
79
|
}
|
|
76
80
|
onTokenDeactivated(id) {
|
|
77
|
-
|
|
81
|
+
const workers = this.workerPool.get(id) ?? [];
|
|
82
|
+
const tokenName = workers[0]?.tokenName;
|
|
83
|
+
workers.forEach((w) => {
|
|
78
84
|
w.active = false;
|
|
79
85
|
});
|
|
80
86
|
if (this.getAllReadyActiveWorkers().length === 0) this.rejectAllQueued("NO_ACTIVE_WORKERS");
|
|
81
|
-
|
|
87
|
+
const label = tokenName ?? `token ${id}`;
|
|
88
|
+
logger.info(`workers deactivated: ${label}`);
|
|
82
89
|
}
|
|
83
90
|
onTokenActivated(id) {
|
|
84
|
-
|
|
91
|
+
const workers = this.workerPool.get(id) ?? [];
|
|
92
|
+
const tokenName = workers[0]?.tokenName;
|
|
93
|
+
workers.forEach((w) => {
|
|
85
94
|
w.active = true;
|
|
86
95
|
});
|
|
87
96
|
this.drainQueue();
|
|
88
|
-
|
|
97
|
+
const label = tokenName ?? `token ${id}`;
|
|
98
|
+
logger.info(`workers activated: ${label}`);
|
|
89
99
|
}
|
|
90
100
|
async generate(req) {
|
|
91
101
|
const reuseWorker = await this.acquireReuseWorker(req);
|
|
@@ -274,10 +284,7 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
274
284
|
const worker = await this.spawnSingleWorker(tokenId, tokenName, credentials, i);
|
|
275
285
|
if (worker) workers.push(worker);
|
|
276
286
|
}
|
|
277
|
-
if (workers.length > 0)
|
|
278
|
-
this.workerPool.set(tokenId, workers);
|
|
279
|
-
logger.info(`${workers.length}/${WORKERS_PER_TOKEN} workers spawned for ${tokenName}`);
|
|
280
|
-
}
|
|
287
|
+
if (workers.length > 0) this.workerPool.set(tokenId, workers);
|
|
281
288
|
}
|
|
282
289
|
async spawnSingleWorker(tokenId, tokenName, credentials, workerIndex) {
|
|
283
290
|
const worker = new CodexAppServerWorker({
|
|
@@ -295,7 +302,7 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
295
302
|
});
|
|
296
303
|
try {
|
|
297
304
|
await worker.initialize();
|
|
298
|
-
logger.info(`worker spawned: ${tokenName}[${workerIndex}]
|
|
305
|
+
logger.info(`worker spawned: ${tokenName}[${workerIndex}]`);
|
|
299
306
|
return worker;
|
|
300
307
|
} catch (e) {
|
|
301
308
|
logger.warn(`worker spawn failed: ${tokenName}[${workerIndex}]: ${e.message}`);
|
|
@@ -376,4 +383,4 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
376
383
|
//#endregion
|
|
377
384
|
export { OpenAIDispatcher };
|
|
378
385
|
|
|
379
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlbmFpLWRpc3BhdGNoZXIuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3Byb3ZpZGVycy9vcGVuYWkvb3BlbmFpLWRpc3BhdGNoZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBPcGVuQUlEaXNwYXRjaGVyIOKAlCBjb2RleCBhcHAtc2VydmVyIHdvcmtlciBwb29sICsg7Yag7YGwIOudvOyasO2MhS5cbiAqXG4gKiAtIO2GoO2BsOuLuSBOIHdvcmtlciAoQ29kZXhBcHBTZXJ2ZXJXb3JrZXIpLCDquLDrs7ggM1xuICogLSBpZGxlIHdvcmtlciByb3VuZC1yb2JpbiDshKDtg50gKyDtgZAg64yA6riwICjsoITrtoAgYnVzeSDsi5wpXG4gKiAtIFRva2VuU3Vic2NyaWJlciDsnbTrsqTtirjroZwgd29ya2VyIHBvb2wg64+Z6riw7ZmUXG4gKiAtIGJhY2twcmVzc3VyZTog7YGQIGZ1bGwg65iQ64qUIHRpbWVvdXQg7IucIFNFUlZFUl9CVVNZXG4gKi9cbmltcG9ydCB7IGdldExvZ2dlciB9IGZyb20gXCJAbG9ndGFwZS9sb2d0YXBlXCI7XG5cbmltcG9ydCB7IFRva2VuTW9kZWwgfSBmcm9tIFwiLi4vLi4vLi4vYXBwbGljYXRpb24vdG9rZW4vdG9rZW4ubW9kZWxcIjtcbmltcG9ydCB7IHR5cGUgT3BlbkFJQ3JlZGVudGlhbHMgfSBmcm9tIFwiLi4vLi4vLi4vYXBwbGljYXRpb24vdG9rZW4vdG9rZW4udHlwZXNcIjtcbmltcG9ydCB7XG4gIHR5cGUgR2VuZXJhdGVSZXF1ZXN0LFxuICB0eXBlIEdlbmVyYXRlUmVzdWx0LFxuICB0eXBlIEdlbmVyYXRlU3RyZWFtQ2FsbGJhY2tzLFxuICB0eXBlIFByb3ZpZGVyRGlzcGF0Y2hlcixcbn0gZnJvbSBcIi4uL2NvbW1vbi9wcm92aWRlci1kaXNwYXRjaGVyXCI7XG5pbXBvcnQgeyBDb2RleEFwcFNlcnZlcldvcmtlciwgdHlwZSBTdHJlYW1DYWxsYmFja3MsIHR5cGUgVHVyblJlcXVlc3QgfSBmcm9tIFwiLi9jb2RleC13b3JrZXJcIjtcbmltcG9ydCB7IGhhbmRsZUNoYXRncHRBdXRoVG9rZW5zUmVmcmVzaCB9IGZyb20gXCIuL29wZW5haS1yZWZyZXNoXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGdldExvZ2dlcihbXCJxZ3JpZFwiLCBcIm9wZW5haS1kaXNwYXRjaGVyXCJdKTtcblxuY29uc3QgREVGQVVMVF9FRkZPUlQgPSBcImxvd1wiO1xuY29uc3QgTUFYX1dPUktFUlNfUEVSX1RPS0VOID0gNTtcbmNvbnN0IFdPUktFUlNfUEVSX1RPS0VOID0gTWF0aC5taW4oXG4gIE51bWJlcihwcm9jZXNzLmVudi5RR1JJRF9XT1JLRVJTX1BFUl9UT0tFTiA/PyAzKSxcbiAgTUFYX1dPUktFUlNfUEVSX1RPS0VOLFxuKTtcbmNvbnN0IFFVRVVFX1RJTUVPVVRfTVMgPSA2MF8wMDA7XG5jb25zdCBNQVhfUVVFVUVfU0laRSA9IDUwO1xuY29uc3QgU1BBV05fSU5URVJWQUxfTVMgPSA1MDA7XG5cbi8vIHRocmVhZCDsnqzsgqzsmqkocHJvbXB0IGNhY2hlIOqzoOyglSkuIOuBhOuptCDquLDsobQgXCLrp6QgdHVybiDsg4ggdGhyZWFkICsgaGlzdG9yeSBpbmplY3RcIiDrj5nsnpEuXG5jb25zdCBUSFJFQURfUkVVU0VfRU5BQkxFRCA9IHByb2Nlc3MuZW52LlFHUklEX09QRU5BSV9USFJFQURfUkVVU0UgIT09IFwiZmFsc2VcIjtcbi8vIOyijO2RnCB3b3JrZXIg6rCAIGJ1c3kg7J28IOuVjCBmcmVlIOulvCDquLDri6TrpqzripQg7LWc64yAIOyLnOqwhC4g7LSI6rO8IOyLnCDsg4ggdGhyZWFkIOuhnCDtj7TrsLEuXG5jb25zdCBSRVVTRV9XT1JLRVJfV0FJVF9NUyA9IDVfMDAwO1xuY29uc3QgUkVVU0VfV09SS0VSX1BPTExfTVMgPSA1MDtcblxuLy8gd29ya2VySWQg7ZWp7ISxOiB0b2tlbklkIOyZgCB3b3JrZXJJbmRleCgwLi40KSDrpbwg7ZWY64KY7J2YIOyViOyglSDsiKvsnpDroZwg7J247L2U65SpLlxuZnVuY3Rpb24gbWFrZVdvcmtlcklkKHRva2VuSWQ6IG51bWJlciwgd29ya2VySW5kZXg6IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiB0b2tlbklkICogMTAgKyB3b3JrZXJJbmRleDtcbn1cblxuZnVuY3Rpb24gc2xlZXAobXM6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgbXMpKTtcbn1cblxudHlwZSBRdWV1ZUl0ZW0gPSB7XG4gIHJlc29sdmU6ICh3b3JrZXI6IENvZGV4QXBwU2VydmVyV29ya2VyKSA9PiB2b2lkO1xuICByZWplY3Q6IChlcnJvcjogRXJyb3IpID0+IHZvaWQ7XG4gIHRpbWVyOiBSZXR1cm5UeXBlPHR5cGVvZiBzZXRUaW1lb3V0PjtcbiAgYWJvcnRDbGVhbnVwPzogKCkgPT4gdm9pZDtcbn07XG5cbmV4cG9ydCBjbGFzcyBPcGVuQUlEaXNwYXRjaGVyIGltcGxlbWVudHMgUHJvdmlkZXJEaXNwYXRjaGVyIHtcbiAgd29ya2VyUG9vbCA9IG5ldyBNYXA8bnVtYmVyLCBDb2RleEFwcFNlcnZlcldvcmtlcltdPigpO1xuICByckN1cnNvciA9IDA7XG4gIHF1ZXVlOiBRdWV1ZUl0ZW1bXSA9IFtdO1xuXG4gIGFzeW5jIHN0YXJ0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHsgcm93cyB9ID0gYXdhaXQgVG9rZW5Nb2RlbC5maW5kTWFueShcIkFcIik7XG4gICAgY29uc3Qgb3BlbmFpVG9rZW5zID0gcm93cy5maWx0ZXIoKHQpID0+IHQucHJvdmlkZXIgPT09IFwib3BlbmFpXCIpO1xuICAgIGxvZ2dlci5pbmZvKFxuICAgICAgYHN0YXJ0aW5nICR7b3BlbmFpVG9rZW5zLmxlbmd0aH0gb3BlbmFpIHRva2VucyAoJHtXT1JLRVJTX1BFUl9UT0tFTn0gd29ya2VycyBlYWNoKWAsXG4gICAgKTtcblxuICAgIGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChcbiAgICAgIG9wZW5haVRva2Vucy5tYXAoYXN5bmMgKHQpID0+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5zcGF3bldvcmtlcnModC5pZCwgdC5uYW1lLCB0LmNyZWRlbnRpYWxzIGFzIE9wZW5BSUNyZWRlbnRpYWxzKTtcbiAgICAgICAgaWYgKCF0LmFjdGl2ZSkgdGhpcy5vblRva2VuRGVhY3RpdmF0ZWQodC5pZCk7XG4gICAgICB9KSxcbiAgICApO1xuICB9XG5cbiAgYXN5bmMgc3RvcCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0aGlzLnJlamVjdEFsbFF1ZXVlZChcIkRJU1BBVENIRVJfU0hVVERPV05cIik7XG4gICAgY29uc3Qga2lsbHMgPSBbLi4udGhpcy53b3JrZXJQb29sLnZhbHVlcygpXS5mbGF0KCkubWFwKCh3KSA9PiB3LmtpbGwoKSk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKGtpbGxzKTtcbiAgICB0aGlzLndvcmtlclBvb2wuY2xlYXIoKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBUb2tlbiBldmVudHMgKGZyb20gVG9rZW5TdWJzY3JpYmVyKSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBhc3luYyBvblRva2VuQWRkZWQoaWQ6IG51bWJlciwgbmFtZTogc3RyaW5nLCBjcmVkZW50aWFsczogT3BlbkFJQ3JlZGVudGlhbHMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy53b3JrZXJQb29sLmhhcyhpZCkpIHJldHVybjtcbiAgICBhd2FpdCB0aGlzLnNwYXduV29ya2VycyhpZCwgbmFtZSwgY3JlZGVudGlhbHMpO1xuICB9XG5cbiAgYXN5bmMgb25Ub2tlblJlbW92ZWQoaWQ6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHdvcmtlcnMgPSB0aGlzLndvcmtlclBvb2wuZ2V0KGlkKSA/PyBbXTtcbiAgICB0aGlzLndvcmtlclBvb2wuZGVsZXRlKGlkKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQod29ya2Vycy5tYXAoKHcpID0+IHcua2lsbCgpKSk7XG4gICAgaWYgKHRoaXMuZ2V0QWxsUmVhZHlBY3RpdmVXb3JrZXJzKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aGlzLnJlamVjdEFsbFF1ZXVlZChcIk5PX09QRU5BSV9XT1JLRVJTXCIpO1xuICAgIH1cbiAgICBpZiAod29ya2Vycy5sZW5ndGggPiAwKSBsb2dnZXIuaW5mbyhgd29ya2VycyByZW1vdmVkIGZvciB0b2tlbiAke2lkfTogJHt3b3JrZXJzLmxlbmd0aH1gKTtcbiAgfVxuXG4gIGFzeW5jIG9uVG9rZW5VcGRhdGVkKGlkOiBudW1iZXIsIG5hbWU6IHN0cmluZywgY3JlZGVudGlhbHM6IE9wZW5BSUNyZWRlbnRpYWxzKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgZXhpc3RpbmcgPSB0aGlzLndvcmtlclBvb2wuZ2V0KGlkKSA/PyBbXTtcbiAgICBpZiAoZXhpc3RpbmcubGVuZ3RoID09PSAwKSB7XG4gICAgICBhd2FpdCB0aGlzLnNwYXduV29ya2VycyhpZCwgbmFtZSwgY3JlZGVudGlhbHMpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChleGlzdGluZy5ldmVyeSgodykgPT4gdy5jYW5SZXVzZUZvclRva2VuKG5hbWUsIGNyZWRlbnRpYWxzKSkpIHtcbiAgICAgIGV4aXN0aW5nLmZvckVhY2goKHcpID0+IHcudXBkYXRlVG9rZW5TdGF0ZShuYW1lLCBjcmVkZW50aWFscykpO1xuICAgICAgbG9nZ2VyLmluZm8oYHdvcmtlcnMgdXBkYXRlZCBpbi1wbGFjZSBmb3IgdG9rZW4gJHtpZH0gKCR7bmFtZX0pYCk7XG4gICAgICB0aGlzLmRyYWluUXVldWUoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLndvcmtlclBvb2wuZGVsZXRlKGlkKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQoZXhpc3RpbmcubWFwKCh3KSA9PiB3LmtpbGwoKSkpO1xuICAgIGF3YWl0IHRoaXMuc3Bhd25Xb3JrZXJzKGlkLCBuYW1lLCBjcmVkZW50aWFscyk7XG4gIH1cblxuICBvblRva2VuRGVhY3RpdmF0ZWQoaWQ6IG51bWJlcik6IHZvaWQge1xuICAgICh0aGlzLndvcmtlclBvb2wuZ2V0KGlkKSA/PyBbXSkuZm9yRWFjaCgodykgPT4ge1xuICAgICAgdy5hY3RpdmUgPSBmYWxzZTtcbiAgICB9KTtcbiAgICBpZiAodGhpcy5nZXRBbGxSZWFkeUFjdGl2ZVdvcmtlcnMoKS5sZW5ndGggPT09IDApIHtcbiAgICAgIHRoaXMucmVqZWN0QWxsUXVldWVkKFwiTk9fQUNUSVZFX1dPUktFUlNcIik7XG4gICAgfVxuICAgIGxvZ2dlci5pbmZvKGB3b3JrZXJzIGRlYWN0aXZhdGVkOiB0b2tlbiAke2lkfWApO1xuICB9XG5cbiAgb25Ub2tlbkFjdGl2YXRlZChpZDogbnVtYmVyKTogdm9pZCB7XG4gICAgKHRoaXMud29ya2VyUG9vbC5nZXQoaWQpID8/IFtdKS5mb3JFYWNoKCh3KSA9PiB7XG4gICAgICB3LmFjdGl2ZSA9IHRydWU7XG4gICAgfSk7XG4gICAgdGhpcy5kcmFpblF1ZXVlKCk7XG4gICAgbG9nZ2VyLmluZm8oYHdvcmtlcnMgYWN0aXZhdGVkOiB0b2tlbiAke2lkfWApO1xuICB9XG5cbiAgLy8g4pSA4pSAIEdlbmVyYXRlIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIGFzeW5jIGdlbmVyYXRlKHJlcTogR2VuZXJhdGVSZXF1ZXN0KTogUHJvbWlzZTxHZW5lcmF0ZVJlc3VsdD4ge1xuICAgIC8vIHRocmVhZCDsnqzsgqzsmqkg6rK966GcOiDsooztkZwgd29ya2VyIOulvCDsoJDsnKDtlbQg6riw7KG0IHRocmVhZCDsl5AgdHVybiDrp4wg7Iuk7ZaJLlxuICAgIGNvbnN0IHJldXNlV29ya2VyID0gYXdhaXQgdGhpcy5hY3F1aXJlUmV1c2VXb3JrZXIocmVxKTtcbiAgICBpZiAocmV1c2VXb3JrZXIpIHtcbiAgICAgIGxvZ2dlci5pbmZvKFxuICAgICAgICBg4oa7ICR7cmV1c2VXb3JrZXIudG9rZW5OYW1lfVske3JldXNlV29ya2VyLnRva2VuSWR9XSAocmV1c2UgdGhyZWFkLCAke3JlcS5tb2RlbH0pYCxcbiAgICAgICk7XG4gICAgICByZXR1cm4gdGhpcy5leGVjdXRlQW5kUmVsZWFzZShyZXVzZVdvcmtlciwgKHcpID0+XG4gICAgICAgIHRoaXMuZXhlY3V0ZVR1cm4odywgcmVxLCByZXEucmV1c2UhLnRocmVhZElkKSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3Qgd29ya2VyID0gdGhpcy5hY3F1aXJlSWRsZVdvcmtlcigpO1xuICAgIGlmICh3b3JrZXIpIHtcbiAgICAgIGxvZ2dlci5pbmZvKGDihpIgJHt3b3JrZXIudG9rZW5OYW1lfVske3dvcmtlci50b2tlbklkfV0gKG1vZGVsOiAke3JlcS5tb2RlbH0pYCk7XG4gICAgICByZXR1cm4gdGhpcy5leGVjdXRlQW5kUmVsZWFzZSh3b3JrZXIsICh3KSA9PiB0aGlzLmV4ZWN1dGVUdXJuKHcsIHJlcSkpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5lbnF1ZXVlKCh3KSA9PiB7XG4gICAgICBsb2dnZXIuaW5mbyhg4oaSICR7dy50b2tlbk5hbWV9WyR7dy50b2tlbklkfV0gKG1vZGVsOiAke3JlcS5tb2RlbH0sIHF1ZXVlZClgKTtcbiAgICAgIHJldHVybiB0aGlzLmV4ZWN1dGVUdXJuKHcsIHJlcSk7XG4gICAgfSk7XG4gIH1cblxuICBhc3luYyBnZW5lcmF0ZVN0cmVhbShyZXE6IEdlbmVyYXRlUmVxdWVzdCwgY2I6IEdlbmVyYXRlU3RyZWFtQ2FsbGJhY2tzKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgcmV1c2VXb3JrZXIgPSBhd2FpdCB0aGlzLmFjcXVpcmVSZXVzZVdvcmtlcihyZXEpO1xuICAgIGlmIChyZXVzZVdvcmtlcikge1xuICAgICAgbG9nZ2VyLmluZm8oYOKGuyAke3JldXNlV29ya2VyLnRva2VuTmFtZX1bJHtyZXVzZVdvcmtlci50b2tlbklkfV0gKHJldXNlIHRocmVhZCwgW3N0cmVhbV0pYCk7XG4gICAgICByZXR1cm4gdGhpcy5leGVjdXRlQW5kUmVsZWFzZShyZXVzZVdvcmtlciwgKHcpID0+XG4gICAgICAgIHRoaXMuZXhlY3V0ZVN0cmVhbVR1cm4odywgcmVxLCBjYiwgcmVxLnJldXNlIS50aHJlYWRJZCksXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHdvcmtlciA9IHRoaXMuYWNxdWlyZUlkbGVXb3JrZXIoKTtcbiAgICBpZiAod29ya2VyKSB7XG4gICAgICBsb2dnZXIuaW5mbyhg4oaSICR7d29ya2VyLnRva2VuTmFtZX1bJHt3b3JrZXIudG9rZW5JZH1dIChtb2RlbDogJHtyZXEubW9kZWx9LCBbc3RyZWFtXSlgKTtcbiAgICAgIHJldHVybiB0aGlzLmV4ZWN1dGVBbmRSZWxlYXNlKHdvcmtlciwgKHcpID0+IHRoaXMuZXhlY3V0ZVN0cmVhbVR1cm4odywgcmVxLCBjYikpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5lbnF1ZXVlKCh3KSA9PiB7XG4gICAgICBsb2dnZXIuaW5mbyhg4oaSICR7dy50b2tlbk5hbWV9WyR7dy50b2tlbklkfV0gKG1vZGVsOiAke3JlcS5tb2RlbH0sIFtzdHJlYW1dLCBxdWV1ZWQpYCk7XG4gICAgICByZXR1cm4gdGhpcy5leGVjdXRlU3RyZWFtVHVybih3LCByZXEsIGNiKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIHJldXNlIOyijO2RnOqwgCDsnKDtmqjtlZjrqbQg6re4IHdvcmtlciDrpbwgYnVzeSDsoJDsnKDtlbQg67CY7ZmYLiDsl4bqsbDrgpgg7Y+067CxIOuMgOyDgeydtOuptCBudWxsLlxuICAvLyDtj7TrsLEg7IKs7JygOiDquLDriqUgb2ZmIC8g7KKM7ZGcIOyXhuydjCAvIHdvcmtlciDrtoDsnqzCt+yjveydjCAvIGVwb2NoIOu2iOydvOy5mChyZXN0YXJ0KSAvIHRocmVhZCDshozrqbggL1xuICAvLyAgICAgICAgICAgIGJ1c3kg64yA6riwIO2DgOyehOyVhOybgy4gbnVsbCDrsJjtmZgg7IucIO2YuOy2nOu2gOuKlCDsg4ggdGhyZWFkIOqyveuhnOuhnCDsp4TtlokuXG4gIGFzeW5jIGFjcXVpcmVSZXVzZVdvcmtlcihyZXE6IEdlbmVyYXRlUmVxdWVzdCk6IFByb21pc2U8Q29kZXhBcHBTZXJ2ZXJXb3JrZXIgfCBudWxsPiB7XG4gICAgaWYgKCFUSFJFQURfUkVVU0VfRU5BQkxFRCB8fCAhcmVxLnJldXNlKSByZXR1cm4gbnVsbDtcbiAgICBjb25zdCB7IHdvcmtlcklkLCB0aHJlYWRJZCwgZXBvY2ggfSA9IHJlcS5yZXVzZTtcblxuICAgIGNvbnN0IHdvcmtlciA9IHRoaXMuZmluZFdvcmtlckJ5SWQod29ya2VySWQpO1xuICAgIGlmICghd29ya2VyIHx8ICF3b3JrZXIuaXNSZWFkeSB8fCAhd29ya2VyLmFjdGl2ZSkgcmV0dXJuIG51bGw7XG4gICAgaWYgKHdvcmtlci5lcG9jaCAhPT0gZXBvY2gpIHJldHVybiBudWxsO1xuICAgIGlmICghd29ya2VyLmhhc1RocmVhZCh0aHJlYWRJZCkpIHJldHVybiBudWxsO1xuXG4gICAgY29uc3QgZGVhZGxpbmUgPSBEYXRlLm5vdygpICsgUkVVU0VfV09SS0VSX1dBSVRfTVM7XG4gICAgZm9yICg7Oykge1xuICAgICAgLy8gcmVzdGFydChlcG9jaCDrs4Dqsr0pIC8gdGhyZWFkIOyGjOupuOydtCDrjIDquLAg7KSR7JeQIOuwnOyDne2VmOuptCDtj7TrsLEuXG4gICAgICBpZiAod29ya2VyLmVwb2NoICE9PSBlcG9jaCB8fCAhd29ya2VyLmhhc1RocmVhZCh0aHJlYWRJZCkpIHJldHVybiBudWxsO1xuICAgICAgaWYgKHdvcmtlci50cnlBY3F1aXJlVHVybigpKSByZXR1cm4gd29ya2VyO1xuICAgICAgaWYgKERhdGUubm93KCkgPj0gZGVhZGxpbmUpIHJldHVybiBudWxsO1xuICAgICAgYXdhaXQgc2xlZXAoUkVVU0VfV09SS0VSX1BPTExfTVMpO1xuICAgIH1cbiAgfVxuXG4gIGZpbmRXb3JrZXJCeUlkKHdvcmtlcklkOiBudW1iZXIpOiBDb2RleEFwcFNlcnZlcldvcmtlciB8IG51bGwge1xuICAgIGZvciAoY29uc3Qgd29ya2VycyBvZiB0aGlzLndvcmtlclBvb2wudmFsdWVzKCkpIHtcbiAgICAgIGZvciAoY29uc3QgdyBvZiB3b3JrZXJzKSB7XG4gICAgICAgIGlmIChtYWtlV29ya2VySWQody50b2tlbklkLCB3LndvcmtlckluZGV4KSA9PT0gd29ya2VySWQpIHJldHVybiB3O1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGFzeW5jIGludGVycnVwdFdvcmtlclR1cm4odGhyZWFkSWQ6IHN0cmluZywgdHVybklkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBhbGxXb3JrZXJzID0gWy4uLnRoaXMud29ya2VyUG9vbC52YWx1ZXMoKV0uZmxhdCgpLmZpbHRlcigodykgPT4gdy5pc1JlYWR5KTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQoYWxsV29ya2Vycy5tYXAoKHcpID0+IHcuaW50ZXJydXB0VHVybih0aHJlYWRJZCwgdHVybklkKSkpO1xuICB9XG5cbiAgLy8g4pSA4pSAIFdvcmtlciBzZWxlY3Rpb24g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4gIC8vICDquLDrs7ggcm91bmQtcm9iaW5cbiAgLy8gVE9ETzog7LaU7ZuEIOuLpOuluCDslYzqs6DrpqzsppjsnLzroZwg67OA6rK9IOqwgOuKpe2VmOqyjCDsp4Dsm5BcbiAgYWNxdWlyZUlkbGVXb3JrZXIoKTogQ29kZXhBcHBTZXJ2ZXJXb3JrZXIgfCBudWxsIHtcbiAgICBjb25zdCBhbGxXb3JrZXJzID0gdGhpcy5nZXRBbGxSZWFkeUFjdGl2ZVdvcmtlcnMoKTtcbiAgICBpZiAoYWxsV29ya2Vycy5sZW5ndGggPT09IDApIHJldHVybiBudWxsO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYWxsV29ya2Vycy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgdyA9IGFsbFdvcmtlcnNbKHRoaXMucnJDdXJzb3IgKyBpKSAlIGFsbFdvcmtlcnMubGVuZ3RoXSE7XG4gICAgICBpZiAody50cnlBY3F1aXJlVHVybigpKSB7XG4gICAgICAgIHRoaXMucnJDdXJzb3IgPSAodGhpcy5yckN1cnNvciArIGkgKyAxKSAlIGFsbFdvcmtlcnMubGVuZ3RoO1xuICAgICAgICByZXR1cm4gdztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBnZXRBbGxSZWFkeUFjdGl2ZVdvcmtlcnMoKTogQ29kZXhBcHBTZXJ2ZXJXb3JrZXJbXSB7XG4gICAgcmV0dXJuIFsuLi50aGlzLndvcmtlclBvb2wudmFsdWVzKCldLmZsYXQoKS5maWx0ZXIoKHcpID0+IHcuaXNSZWFkeSAmJiB3LmFjdGl2ZSk7XG4gIH1cblxuICAvLyDilIDilIAgUXVldWUg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgZW5xdWV1ZTxUPihleGVjdXRlOiAod29ya2VyOiBDb2RleEFwcFNlcnZlcldvcmtlcikgPT4gUHJvbWlzZTxUPik6IFByb21pc2U8VD4ge1xuICAgIGlmICh0aGlzLmdldEFsbFJlYWR5QWN0aXZlV29ya2VycygpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBFcnJvcihcIk5PX09QRU5BSV9XT1JLRVJTXCIpKTtcbiAgICB9XG4gICAgaWYgKHRoaXMucXVldWUubGVuZ3RoID49IE1BWF9RVUVVRV9TSVpFKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKFwiU0VSVkVSX0JVU1lcIikpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgUHJvbWlzZTxUPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBpdGVtOiBRdWV1ZUl0ZW0gPSB7XG4gICAgICAgIHJlc29sdmU6ICh3b3JrZXIpID0+IHtcbiAgICAgICAgICBjbGVhclRpbWVvdXQoaXRlbS50aW1lcik7XG4gICAgICAgICAgaXRlbS5hYm9ydENsZWFudXA/LigpO1xuICAgICAgICAgIFByb21pc2UucmVzb2x2ZSgpXG4gICAgICAgICAgICAudGhlbigoKSA9PiB0aGlzLmV4ZWN1dGVBbmRSZWxlYXNlKHdvcmtlciwgZXhlY3V0ZSkpXG4gICAgICAgICAgICAudGhlbihyZXNvbHZlLCByZWplY3QpO1xuICAgICAgICB9LFxuICAgICAgICByZWplY3Q6IChlcnIpID0+IHtcbiAgICAgICAgICBjbGVhclRpbWVvdXQoaXRlbS50aW1lcik7XG4gICAgICAgICAgaXRlbS5hYm9ydENsZWFudXA/LigpO1xuICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICB9LFxuICAgICAgICB0aW1lcjogc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgdGhpcy5yZW1vdmVGcm9tUXVldWUoaXRlbSk7XG4gICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihcIlNFUlZFUl9CVVNZXCIpKTtcbiAgICAgICAgfSwgUVVFVUVfVElNRU9VVF9NUyksXG4gICAgICB9O1xuXG4gICAgICB0aGlzLnF1ZXVlLnB1c2goaXRlbSk7XG4gICAgfSk7XG4gIH1cblxuICByZW1vdmVGcm9tUXVldWUoaXRlbTogUXVldWVJdGVtKTogdm9pZCB7XG4gICAgY2xlYXJUaW1lb3V0KGl0ZW0udGltZXIpO1xuICAgIGl0ZW0uYWJvcnRDbGVhbnVwPy4oKTtcbiAgICBjb25zdCBpZHggPSB0aGlzLnF1ZXVlLmluZGV4T2YoaXRlbSk7XG4gICAgaWYgKGlkeCAhPT0gLTEpIHRoaXMucXVldWUuc3BsaWNlKGlkeCwgMSk7XG4gIH1cblxuICByZWplY3RBbGxRdWV1ZWQocmVhc29uOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBlcnIgPSBuZXcgRXJyb3IocmVhc29uKTtcbiAgICB0aGlzLnF1ZXVlLmZvckVhY2goKGl0ZW0pID0+IHtcbiAgICAgIGNsZWFyVGltZW91dChpdGVtLnRpbWVyKTtcbiAgICAgIGl0ZW0uYWJvcnRDbGVhbnVwPy4oKTtcbiAgICAgIGl0ZW0ucmVqZWN0KGVycik7XG4gICAgfSk7XG4gICAgdGhpcy5xdWV1ZSA9IFtdO1xuICB9XG5cbiAgZHJhaW5RdWV1ZShyZWxlYXNlZFdvcmtlcj86IENvZGV4QXBwU2VydmVyV29ya2VyKTogdm9pZCB7XG4gICAgaWYgKFxuICAgICAgcmVsZWFzZWRXb3JrZXIgJiZcbiAgICAgIHRoaXMucXVldWUubGVuZ3RoID4gMCAmJlxuICAgICAgcmVsZWFzZWRXb3JrZXIuaXNSZWFkeSAmJlxuICAgICAgcmVsZWFzZWRXb3JrZXIuYWN0aXZlICYmXG4gICAgICByZWxlYXNlZFdvcmtlci50cnlBY3F1aXJlVHVybigpXG4gICAgKSB7XG4gICAgICBjb25zdCBuZXh0ID0gdGhpcy5xdWV1ZS5zaGlmdCgpITtcbiAgICAgIG5leHQucmVzb2x2ZShyZWxlYXNlZFdvcmtlcik7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2hpbGUgKHRoaXMucXVldWUubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3Qgd29ya2VyID0gdGhpcy5hY3F1aXJlSWRsZVdvcmtlcigpO1xuICAgICAgaWYgKCF3b3JrZXIpIGJyZWFrO1xuICAgICAgY29uc3QgbmV4dCA9IHRoaXMucXVldWUuc2hpZnQoKSE7XG4gICAgICBuZXh0LnJlc29sdmUod29ya2VyKTtcbiAgICB9XG4gIH1cblxuICAvLyDilIDilIAgRXhlY3V0aW9uIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIGFzeW5jIGV4ZWN1dGVBbmRSZWxlYXNlPFQ+KFxuICAgIHdvcmtlcjogQ29kZXhBcHBTZXJ2ZXJXb3JrZXIsXG4gICAgZXhlY3V0ZTogKHdvcmtlcjogQ29kZXhBcHBTZXJ2ZXJXb3JrZXIpID0+IFByb21pc2U8VD4sXG4gICk6IFByb21pc2U8VD4ge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgZXhlY3V0ZSh3b3JrZXIpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB3b3JrZXIucmVsZWFzZVR1cm4oKTtcbiAgICAgIHRoaXMuZHJhaW5RdWV1ZSh3b3JrZXIpO1xuICAgIH1cbiAgfVxuXG4gIC8vIHJldXNlVGhyZWFkSWQg6rCAIOyeiOycvOuptCDquLDsobQgdGhyZWFkIOyXkCBkZWx0YShyZXVzZUlucHV0KeunjCwg7JeG7Jy866m0IOyDiCB0aHJlYWQg7JeQIOyghOyytFxuICAvLyBwcm9tcHQoY29sZElucHV0KSArIGhpc3RvcnkgaW5qZWN0LiByZXVzZSDqsIAgZGlzcGF0Y2hlciDri6jsl5DshJwg7Y+067Cx65CY66m0IO2bhOyekOuhnCDrlqjslrTsp4Tri6QuXG4gIHByaXZhdGUgYnVpbGRUdXJuUmVxdWVzdChyZXE6IEdlbmVyYXRlUmVxdWVzdCwgcmV1c2VUaHJlYWRJZD86IHN0cmluZyk6IFR1cm5SZXF1ZXN0IHtcbiAgICBjb25zdCByZXVzaW5nID0gcmV1c2VUaHJlYWRJZCAhPT0gdW5kZWZpbmVkO1xuICAgIHJldHVybiB7XG4gICAgICBpbnB1dDogcmV1c2luZyAmJiByZXEucmV1c2VJbnB1dCA/IHJlcS5yZXVzZUlucHV0IDogcmVxLmNvbGRJbnB1dCxcbiAgICAgIGhpc3Rvcnk6IHJldXNpbmcgPyB1bmRlZmluZWQgOiByZXEuY29sZEhpc3RvcnksXG4gICAgICBkZXZlbG9wZXJJbnN0cnVjdGlvbnM6IHJlcS5zeXN0ZW1Qcm9tcHQsXG4gICAgICBvdXRwdXRTY2hlbWE6IHJlcS5vdXRwdXRTY2hlbWEsXG4gICAgICBlZmZvcnQ6IHJlcS5lZmZvcnQgPz8gREVGQVVMVF9FRkZPUlQsXG4gICAgICBtb2RlbDogcmVxLm1vZGVsLFxuICAgICAgdmVyYm9zaXR5OiByZXEudmVyYm9zaXR5LFxuICAgICAgcmVhc29uaW5nU3VtbWFyeTogcmVxLnJlYXNvbmluZ1N1bW1hcnksXG4gICAgICBzZXJ2aWNlVGllcjogcmVxLnNlcnZpY2VUaWVyLFxuICAgIH07XG4gIH1cblxuICBhc3luYyBleGVjdXRlVHVybihcbiAgICB3b3JrZXI6IENvZGV4QXBwU2VydmVyV29ya2VyLFxuICAgIHJlcTogR2VuZXJhdGVSZXF1ZXN0LFxuICAgIHJldXNlVGhyZWFkSWQ/OiBzdHJpbmcsXG4gICk6IFByb21pc2U8R2VuZXJhdGVSZXN1bHQ+IHtcbiAgICBjb25zdCB0dXJuUmVxID0gdGhpcy5idWlsZFR1cm5SZXF1ZXN0KHJlcSwgcmV1c2VUaHJlYWRJZCk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgd29ya2VyLmV4ZWN1dGVUdXJuKHR1cm5SZXEsIHJldXNlVGhyZWFkSWQpO1xuICAgIHJldHVybiB7XG4gICAgICB0ZXh0OiByZXN1bHQudGV4dCxcbiAgICAgIHRva2VuTmFtZTogd29ya2VyLnRva2VuTmFtZSxcbiAgICAgIHVzYWdlOiByZXN1bHQudXNhZ2UsXG4gICAgICBkdXJhdGlvbk1zOiByZXN1bHQuZHVyYXRpb25NcyxcbiAgICAgIG1vZGVsOiByZXN1bHQubW9kZWwsXG4gICAgICB0aHJlYWRDb29yZDoge1xuICAgICAgICB3b3JrZXJJZDogbWFrZVdvcmtlcklkKHdvcmtlci50b2tlbklkLCB3b3JrZXIud29ya2VySW5kZXgpLFxuICAgICAgICB0aHJlYWRJZDogcmVzdWx0LnRocmVhZElkLFxuICAgICAgICBlcG9jaDogd29ya2VyLmVwb2NoLFxuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgYXN5bmMgZXhlY3V0ZVN0cmVhbVR1cm4oXG4gICAgd29ya2VyOiBDb2RleEFwcFNlcnZlcldvcmtlcixcbiAgICByZXE6IEdlbmVyYXRlUmVxdWVzdCxcbiAgICBjYjogR2VuZXJhdGVTdHJlYW1DYWxsYmFja3MsXG4gICAgcmV1c2VUaHJlYWRJZD86IHN0cmluZyxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgdHVyblJlcSA9IHRoaXMuYnVpbGRUdXJuUmVxdWVzdChyZXEsIHJldXNlVGhyZWFkSWQpO1xuICAgIC8vIHdvcmtlciDsnZggVHVyblJlc3VsdCDsl5AgdG9rZW5OYW1lL3RocmVhZENvb3JkIOulvCDrtpnsl6wg7IOB7JyEKEdlbmVyYXRlUmVzdWx0KeuhnCDsmKzrprDri6QuXG4gICAgLy8gdGhyZWFkSWQg64qUIOyDiCB0aHJlYWQg66m0IG9uVGhyZWFkSWQg66GcIO2ZleygleuQmOuvgOuhnCDrr7jrpqwg67O06rSA7ZW0IOuRkOqzoCBvbkNvbXBsZXRlIOuVjCDsnb3ripTri6QuXG4gICAgbGV0IHJlc29sdmVkVGhyZWFkSWQgPSByZXVzZVRocmVhZElkID8/IFwiXCI7XG4gICAgY29uc3Qgd3JhcHBlZENiOiBTdHJlYW1DYWxsYmFja3MgPSB7XG4gICAgICAuLi5jYixcbiAgICAgIG9uVGhyZWFkSWQ6ICh0aHJlYWRJZCkgPT4ge1xuICAgICAgICByZXNvbHZlZFRocmVhZElkID0gdGhyZWFkSWQ7XG4gICAgICAgIGNiLm9uVGhyZWFkSWQ/Lih0aHJlYWRJZCk7XG4gICAgICB9LFxuICAgICAgb25Db21wbGV0ZTogKHJlc3VsdCkgPT4ge1xuICAgICAgICBjYi5vbkNvbXBsZXRlKHtcbiAgICAgICAgICAuLi5yZXN1bHQsXG4gICAgICAgICAgdG9rZW5OYW1lOiB3b3JrZXIudG9rZW5OYW1lLFxuICAgICAgICAgIHRocmVhZENvb3JkOiB7XG4gICAgICAgICAgICB3b3JrZXJJZDogbWFrZVdvcmtlcklkKHdvcmtlci50b2tlbklkLCB3b3JrZXIud29ya2VySW5kZXgpLFxuICAgICAgICAgICAgdGhyZWFkSWQ6IHJlc29sdmVkVGhyZWFkSWQsXG4gICAgICAgICAgICBlcG9jaDogd29ya2VyLmVwb2NoLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgfSxcbiAgICB9O1xuICAgIGF3YWl0IHdvcmtlci5leGVjdXRlVHVyblN0cmVhbSh0dXJuUmVxLCB3cmFwcGVkQ2IsIHJldXNlVGhyZWFkSWQpO1xuICB9XG5cbiAgLy8g4pSA4pSAIFNwYXduIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIGFzeW5jIHNwYXduV29ya2VycyhcbiAgICB0b2tlbklkOiBudW1iZXIsXG4gICAgdG9rZW5OYW1lOiBzdHJpbmcsXG4gICAgY3JlZGVudGlhbHM6IE9wZW5BSUNyZWRlbnRpYWxzLFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB3b3JrZXJzOiBDb2RleEFwcFNlcnZlcldvcmtlcltdID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBXT1JLRVJTX1BFUl9UT0tFTjsgaSsrKSB7XG4gICAgICBpZiAoaSA+IDApIGF3YWl0IHNsZWVwKFNQQVdOX0lOVEVSVkFMX01TKTtcbiAgICAgIGNvbnN0IHdvcmtlciA9IGF3YWl0IHRoaXMuc3Bhd25TaW5nbGVXb3JrZXIodG9rZW5JZCwgdG9rZW5OYW1lLCBjcmVkZW50aWFscywgaSk7XG4gICAgICBpZiAod29ya2VyKSB3b3JrZXJzLnB1c2god29ya2VyKTtcbiAgICB9XG4gICAgaWYgKHdvcmtlcnMubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy53b3JrZXJQb29sLnNldCh0b2tlbklkLCB3b3JrZXJzKTtcbiAgICAgIGxvZ2dlci5pbmZvKGAke3dvcmtlcnMubGVuZ3RofS8ke1dPUktFUlNfUEVSX1RPS0VOfSB3b3JrZXJzIHNwYXduZWQgZm9yICR7dG9rZW5OYW1lfWApO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHNwYXduU2luZ2xlV29ya2VyKFxuICAgIHRva2VuSWQ6IG51bWJlcixcbiAgICB0b2tlbk5hbWU6IHN0cmluZyxcbiAgICBjcmVkZW50aWFsczogT3BlbkFJQ3JlZGVudGlhbHMsXG4gICAgd29ya2VySW5kZXg6IG51bWJlcixcbiAgKTogUHJvbWlzZTxDb2RleEFwcFNlcnZlcldvcmtlciB8IG51bGw+IHtcbiAgICBjb25zdCB3b3JrZXIgPSBuZXcgQ29kZXhBcHBTZXJ2ZXJXb3JrZXIoe1xuICAgICAgdG9rZW5JZCxcbiAgICAgIHRva2VuTmFtZSxcbiAgICAgIGFjY2Vzc1Rva2VuOiBjcmVkZW50aWFscy5hY2Nlc3NUb2tlbixcbiAgICAgIGFjY291bnRJZDogY3JlZGVudGlhbHMuYWNjb3VudElkLFxuICAgICAgcGxhblR5cGU6IGNyZWRlbnRpYWxzLnBsYW5UeXBlLFxuICAgICAgd29ya2VySW5kZXgsXG4gICAgfSk7XG5cbiAgICB3b3JrZXIub25SZWFkeSA9ICgpID0+IHRoaXMuZHJhaW5RdWV1ZSgpO1xuXG4gICAgd29ya2VyLnNldFNlcnZlclJlcXVlc3RIYW5kbGVyKGFzeW5jIChtZXRob2QpID0+IHtcbiAgICAgIGlmIChtZXRob2QgPT09IFwiYWNjb3VudC9jaGF0Z3B0QXV0aFRva2Vucy9yZWZyZXNoXCIpIHtcbiAgICAgICAgcmV0dXJuIGhhbmRsZUNoYXRncHRBdXRoVG9rZW5zUmVmcmVzaCh0b2tlbklkKTtcbiAgICAgIH1cbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5oYW5kbGVkIHNlcnZlci1yZXF1ZXN0OiAke21ldGhvZH1gKTtcbiAgICB9KTtcblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCB3b3JrZXIuaW5pdGlhbGl6ZSgpO1xuICAgICAgbG9nZ2VyLmluZm8oYHdvcmtlciBzcGF3bmVkOiAke3Rva2VuTmFtZX1bJHt3b3JrZXJJbmRleH1dIChpZD0ke3Rva2VuSWQgKyAxfSlgKTtcbiAgICAgIHJldHVybiB3b3JrZXI7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgbG9nZ2VyLndhcm4oYHdvcmtlciBzcGF3biBmYWlsZWQ6ICR7dG9rZW5OYW1lfVske3dvcmtlckluZGV4fV06ICR7KGUgYXMgRXJyb3IpLm1lc3NhZ2V9YCk7XG4gICAgICBhd2FpdCB3b3JrZXIua2lsbCgpLmNhdGNoKCgpID0+IHt9KTtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gIC8vIOKUgOKUgCBSYXRlIGxpbWl0cyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICByYXRlTGltaXRzQ2FjaGUgPSBuZXcgTWFwPHN0cmluZywgeyBkYXRhOiB1bmtub3duOyBjYWNoZWRBdDogbnVtYmVyIH0+KCk7XG4gIHN0YXRpYyByZWFkb25seSBSQVRFX0xJTUlUU19DQUNIRV9UVEwgPSA2MF8wMDA7XG5cbiAgYXN5bmMgZ2V0UmF0ZUxpbWl0cyh0b2tlbk5hbWU/OiBzdHJpbmcpOiBQcm9taXNlPHVua25vd24+IHtcbiAgICBjb25zdCBjYWNoZUtleSA9IHRva2VuTmFtZSA/PyBcIl9kZWZhdWx0XCI7XG4gICAgY29uc3QgY2FjaGVkID0gdGhpcy5yYXRlTGltaXRzQ2FjaGUuZ2V0KGNhY2hlS2V5KTtcbiAgICBpZiAoY2FjaGVkICYmIERhdGUubm93KCkgLSBjYWNoZWQuY2FjaGVkQXQgPCBPcGVuQUlEaXNwYXRjaGVyLlJBVEVfTElNSVRTX0NBQ0hFX1RUTCkge1xuICAgICAgcmV0dXJuIGNhY2hlZC5kYXRhO1xuICAgIH1cblxuICAgIGNvbnN0IGFsbFdvcmtlcnMgPSBbLi4udGhpcy53b3JrZXJQb29sLnZhbHVlcygpXS5mbGF0KCkuZmlsdGVyKCh3KSA9PiB3LmlzUmVhZHkpO1xuICAgIGNvbnN0IHdvcmtlciA9IHRva2VuTmFtZSA/IGFsbFdvcmtlcnMuZmluZCgodykgPT4gdy50b2tlbk5hbWUgPT09IHRva2VuTmFtZSkgOiBhbGxXb3JrZXJzWzBdO1xuICAgIGlmICghd29ya2VyKSB0aHJvdyBuZXcgRXJyb3IoXCJubyByZWFkeSBvcGVuYWkgd29ya2Vyc1wiKTtcbiAgICBjb25zdCBkYXRhID0gYXdhaXQgd29ya2VyLmdldFJhdGVMaW1pdHMoKTtcbiAgICB0aGlzLnJhdGVMaW1pdHNDYWNoZS5zZXQoY2FjaGVLZXksIHsgZGF0YSwgY2FjaGVkQXQ6IERhdGUubm93KCkgfSk7XG4gICAgcmV0dXJuIGRhdGE7XG4gIH1cblxuICAvLyDilIDilIAgQnJvd3NlciBsb2dpbiBmbG93IOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIHBlbmRpbmdMb2dpbjoge1xuICAgIHdvcmtlcjogQ29kZXhBcHBTZXJ2ZXJXb3JrZXI7XG4gICAgbmFtZTogc3RyaW5nO1xuICAgIHRpbWVyOiBSZXR1cm5UeXBlPHR5cGVvZiBzZXRUaW1lb3V0PjtcbiAgfSB8IG51bGwgPSBudWxsO1xuXG4gIGFzeW5jIHN0YXJ0QnJvd3NlckxvZ2luKG5hbWU6IHN0cmluZyk6IFByb21pc2U8eyBhdXRoVXJsOiBzdHJpbmcgfT4ge1xuICAgIGlmICh0aGlzLnBlbmRpbmdMb2dpbikge1xuICAgICAgdGhpcy5wZW5kaW5nTG9naW4ud29ya2VyLmtpbGwoKS5jYXRjaCgoKSA9PiB7fSk7XG4gICAgICBjbGVhclRpbWVvdXQodGhpcy5wZW5kaW5nTG9naW4udGltZXIpO1xuICAgICAgdGhpcy5wZW5kaW5nTG9naW4gPSBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IHRlbXBJZCA9IERhdGUubm93KCk7XG4gICAgY29uc3Qgd29ya2VyID0gbmV3IENvZGV4QXBwU2VydmVyV29ya2VyKHtcbiAgICAgIHRva2VuSWQ6IHRlbXBJZCxcbiAgICAgIHRva2VuTmFtZTogbmFtZSxcbiAgICAgIGFjY2Vzc1Rva2VuOiBcIlwiLFxuICAgICAgYWNjb3VudElkOiBcIlwiLFxuICAgIH0pO1xuXG4gICAgY29uc3QgYXV0aFVybCA9IGF3YWl0IHdvcmtlci5zdGFydEJyb3dzZXJMb2dpbigpO1xuXG4gICAgY29uc3QgdGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIGlmICh0aGlzLnBlbmRpbmdMb2dpbj8ud29ya2VyID09PSB3b3JrZXIpIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oYGJyb3dzZXIgbG9naW4gdGltZW91dCBmb3IgJHtuYW1lfSwga2lsbGluZyB3b3JrZXJgKTtcbiAgICAgICAgd29ya2VyLmtpbGwoKS5jYXRjaCgoKSA9PiB7fSk7XG4gICAgICAgIHRoaXMucGVuZGluZ0xvZ2luID0gbnVsbDtcbiAgICAgIH1cbiAgICB9LCAzMDBfMDAwKTtcblxuICAgIHRoaXMucGVuZGluZ0xvZ2luID0geyB3b3JrZXIsIG5hbWUsIHRpbWVyIH07XG4gICAgcmV0dXJuIHsgYXV0aFVybCB9O1xuICB9XG5cbiAgZ2V0IHBlbmRpbmdMb2dpbk5hbWUoKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMucGVuZGluZ0xvZ2luPy5uYW1lID8/IG51bGw7XG4gIH1cblxuICBhc3luYyBjb21wbGV0ZUJyb3dzZXJMb2dpbigpOiBQcm9taXNlPHtcbiAgICBhY2Nlc3NUb2tlbjogc3RyaW5nO1xuICAgIHJlZnJlc2hUb2tlbjogc3RyaW5nO1xuICAgIGlkVG9rZW4/OiBzdHJpbmc7XG4gICAgYWNjb3VudElkOiBzdHJpbmc7XG4gIH0+IHtcbiAgICBpZiAoIXRoaXMucGVuZGluZ0xvZ2luKSB0aHJvdyBuZXcgRXJyb3IoXCJubyBwZW5kaW5nIGxvZ2luXCIpO1xuICAgIGNvbnN0IHsgd29ya2VyLCB0aW1lciB9ID0gdGhpcy5wZW5kaW5nTG9naW47XG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgd29ya2VyLndhaXRGb3JCcm93c2VyTG9naW5Db21wbGV0ZSgpO1xuICAgICAgY29uc3QgY3JlZHMgPSBhd2FpdCB3b3JrZXIucmVhZE1hbmFnZWRDcmVkZW50aWFscygpO1xuICAgICAgaWYgKCFjcmVkcykgdGhyb3cgbmV3IEVycm9yKFwiZmFpbGVkIHRvIHJlYWQgY3JlZGVudGlhbHMgYWZ0ZXIgbG9naW5cIik7XG4gICAgICByZXR1cm4gY3JlZHM7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lcik7XG4gICAgICB0aGlzLnBlbmRpbmdMb2dpbiA9IG51bGw7XG4gICAgICBhd2FpdCB3b3JrZXIua2lsbCgpLmNhdGNoKCgpID0+IHt9KTtcbiAgICB9XG4gIH1cblxuICAvLyDilIDilIAgU3RhdHMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgZ2V0IHdvcmtlckNvdW50KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIFsuLi50aGlzLndvcmtlclBvb2wudmFsdWVzKCldLmZsYXQoKS5sZW5ndGg7XG4gIH1cblxuICBnZXQgcmVhZHlXb3JrZXJDb3VudCgpOiBudW1iZXIge1xuICAgIHJldHVybiBbLi4udGhpcy53b3JrZXJQb29sLnZhbHVlcygpXS5mbGF0KCkuZmlsdGVyKCh3KSA9PiB3LmlzUmVhZHkpLmxlbmd0aDtcbiAgfVxuXG4gIGdldCBxdWV1ZUxlbmd0aCgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLnF1ZXVlLmxlbmd0aDtcbiAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7OztBQXFCQSxNQUFNLFNBQVMsVUFBVSxDQUFDLFNBQVMsb0JBQW9CLENBQUM7QUFFeEQsTUFBTSxpQkFBaUI7QUFFdkIsTUFBTSxvQkFBb0IsS0FBSyxJQUM3QixPQUFPLFFBQVEsSUFBSSwyQkFBMkIsRUFBRSxFQUZwQixFQUk3QjtBQUNELE1BQU0sbUJBQW1CO0FBQ3pCLE1BQU0saUJBQWlCO0FBQ3ZCLE1BQU0sb0JBQW9CO0FBRzFCLE1BQU0sdUJBQXVCLFFBQVEsSUFBSSw4QkFBOEI7QUFFdkUsTUFBTSx1QkFBdUI7QUFDN0IsTUFBTSx1QkFBdUI7QUFHN0IsU0FBUyxhQUFhLFNBQWlCLGFBQTZCO0FBQ2xFLFFBQU8sVUFBVSxLQUFLOztBQUd4QixTQUFTLE1BQU0sSUFBMkI7QUFDeEMsUUFBTyxJQUFJLFNBQVMsWUFBWSxXQUFXLFNBQVMsR0FBRyxDQUFDOztBQVUxRCxJQUFhLG1CQUFiLE1BQWEsaUJBQStDO0NBQzFELDZCQUFhLElBQUksS0FBcUM7Q0FDdEQsV0FBVztDQUNYLFFBQXFCLEVBQUU7Q0FFdkIsTUFBTSxRQUF1QjtFQUMzQixNQUFNLEVBQUUsU0FBUyxNQUFNLFdBQVcsU0FBUyxJQUFJO0VBQy9DLE1BQU0sZUFBZSxLQUFLLFFBQVEsTUFBTSxFQUFFLGFBQWEsU0FBUztBQUNoRSxTQUFPLEtBQ0wsWUFBWSxhQUFhLE9BQU8sa0JBQWtCLGtCQUFrQixnQkFDckU7QUFFRCxRQUFNLFFBQVEsV0FDWixhQUFhLElBQUksT0FBTyxNQUFNO0FBQzVCLFNBQU0sS0FBSyxhQUFhLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFB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
|
|
386
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlbmFpLWRpc3BhdGNoZXIuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3Byb3ZpZGVycy9vcGVuYWkvb3BlbmFpLWRpc3BhdGNoZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBPcGVuQUlEaXNwYXRjaGVyIOKAlCBjb2RleCBhcHAtc2VydmVyIHdvcmtlciBwb29sICsg7Yag7YGwIOudvOyasO2MhS5cbiAqXG4gKiAtIO2GoO2BsOuLuSBOIHdvcmtlciAoQ29kZXhBcHBTZXJ2ZXJXb3JrZXIpLCDquLDrs7ggM1xuICogLSBpZGxlIHdvcmtlciByb3VuZC1yb2JpbiDshKDtg50gKyDtgZAg64yA6riwICjsoITrtoAgYnVzeSDsi5wpXG4gKiAtIFRva2VuU3Vic2NyaWJlciDsnbTrsqTtirjroZwgd29ya2VyIHBvb2wg64+Z6riw7ZmUXG4gKiAtIGJhY2twcmVzc3VyZTog7YGQIGZ1bGwg65iQ64qUIHRpbWVvdXQg7IucIFNFUlZFUl9CVVNZXG4gKi9cbmltcG9ydCB7IGdldExvZ2dlciB9IGZyb20gXCJAbG9ndGFwZS9sb2d0YXBlXCI7XG5cbmltcG9ydCB7IFRva2VuTW9kZWwgfSBmcm9tIFwiLi4vLi4vLi4vYXBwbGljYXRpb24vdG9rZW4vdG9rZW4ubW9kZWxcIjtcbmltcG9ydCB7IHR5cGUgT3BlbkFJQ3JlZGVudGlhbHMgfSBmcm9tIFwiLi4vLi4vLi4vYXBwbGljYXRpb24vdG9rZW4vdG9rZW4udHlwZXNcIjtcbmltcG9ydCB7XG4gIHR5cGUgR2VuZXJhdGVSZXF1ZXN0LFxuICB0eXBlIEdlbmVyYXRlUmVzdWx0LFxuICB0eXBlIEdlbmVyYXRlU3RyZWFtQ2FsbGJhY2tzLFxuICB0eXBlIFByb3ZpZGVyRGlzcGF0Y2hlcixcbn0gZnJvbSBcIi4uL2NvbW1vbi9wcm92aWRlci1kaXNwYXRjaGVyXCI7XG5pbXBvcnQgeyBDb2RleEFwcFNlcnZlcldvcmtlciwgdHlwZSBTdHJlYW1DYWxsYmFja3MsIHR5cGUgVHVyblJlcXVlc3QgfSBmcm9tIFwiLi9jb2RleC13b3JrZXJcIjtcbmltcG9ydCB7IGhhbmRsZUNoYXRncHRBdXRoVG9rZW5zUmVmcmVzaCB9IGZyb20gXCIuL29wZW5haS1yZWZyZXNoXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGdldExvZ2dlcihbXCJxZ3JpZFwiLCBcIm9wZW5haS1kaXNwYXRjaGVyXCJdKTtcblxuY29uc3QgREVGQVVMVF9FRkZPUlQgPSBcImxvd1wiO1xuY29uc3QgTUFYX1dPUktFUlNfUEVSX1RPS0VOID0gNTtcbmNvbnN0IFdPUktFUlNfUEVSX1RPS0VOID0gTWF0aC5taW4oXG4gIE51bWJlcihwcm9jZXNzLmVudi5RR1JJRF9XT1JLRVJTX1BFUl9UT0tFTiA/PyAzKSxcbiAgTUFYX1dPUktFUlNfUEVSX1RPS0VOLFxuKTtcbmNvbnN0IFFVRVVFX1RJTUVPVVRfTVMgPSA2MF8wMDA7XG5jb25zdCBNQVhfUVVFVUVfU0laRSA9IDUwO1xuY29uc3QgU1BBV05fSU5URVJWQUxfTVMgPSA1MDA7XG5cbi8vIHRocmVhZCDsnqzsgqzsmqkocHJvbXB0IGNhY2hlIOqzoOyglSkuIOuBhOuptCDquLDsobQgXCLrp6QgdHVybiDsg4ggdGhyZWFkICsgaGlzdG9yeSBpbmplY3RcIiDrj5nsnpEuXG5jb25zdCBUSFJFQURfUkVVU0VfRU5BQkxFRCA9IHByb2Nlc3MuZW52LlFHUklEX09QRU5BSV9USFJFQURfUkVVU0UgIT09IFwiZmFsc2VcIjtcbi8vIOyijO2RnCB3b3JrZXIg6rCAIGJ1c3kg7J28IOuVjCBmcmVlIOulvCDquLDri6TrpqzripQg7LWc64yAIOyLnOqwhC4g7LSI6rO8IOyLnCDsg4ggdGhyZWFkIOuhnCDtj7TrsLEuXG5jb25zdCBSRVVTRV9XT1JLRVJfV0FJVF9NUyA9IDVfMDAwO1xuY29uc3QgUkVVU0VfV09SS0VSX1BPTExfTVMgPSA1MDtcblxuLy8gd29ya2VySWQg7ZWp7ISxOiB0b2tlbklkIOyZgCB3b3JrZXJJbmRleCgwLi40KSDrpbwg7ZWY64KY7J2YIOyViOyglSDsiKvsnpDroZwg7J247L2U65SpLlxuZnVuY3Rpb24gbWFrZVdvcmtlcklkKHRva2VuSWQ6IG51bWJlciwgd29ya2VySW5kZXg6IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiB0b2tlbklkICogMTAgKyB3b3JrZXJJbmRleDtcbn1cblxuZnVuY3Rpb24gc2xlZXAobXM6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgbXMpKTtcbn1cblxudHlwZSBRdWV1ZUl0ZW0gPSB7XG4gIHJlc29sdmU6ICh3b3JrZXI6IENvZGV4QXBwU2VydmVyV29ya2VyKSA9PiB2b2lkO1xuICByZWplY3Q6IChlcnJvcjogRXJyb3IpID0+IHZvaWQ7XG4gIHRpbWVyOiBSZXR1cm5UeXBlPHR5cGVvZiBzZXRUaW1lb3V0PjtcbiAgYWJvcnRDbGVhbnVwPzogKCkgPT4gdm9pZDtcbn07XG5cbmV4cG9ydCBjbGFzcyBPcGVuQUlEaXNwYXRjaGVyIGltcGxlbWVudHMgUHJvdmlkZXJEaXNwYXRjaGVyIHtcbiAgd29ya2VyUG9vbCA9IG5ldyBNYXA8bnVtYmVyLCBDb2RleEFwcFNlcnZlcldvcmtlcltdPigpO1xuICByckN1cnNvciA9IDA7XG4gIHF1ZXVlOiBRdWV1ZUl0ZW1bXSA9IFtdO1xuXG4gIGFzeW5jIHN0YXJ0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHsgcm93cyB9ID0gYXdhaXQgVG9rZW5Nb2RlbC5maW5kTWFueShcIkFcIik7XG4gICAgY29uc3Qgb3BlbmFpVG9rZW5zID0gcm93cy5maWx0ZXIoKHQpID0+IHQucHJvdmlkZXIgPT09IFwib3BlbmFpXCIpO1xuICAgIGxvZ2dlci5pbmZvKFxuICAgICAgYHN0YXJ0aW5nICR7b3BlbmFpVG9rZW5zLmxlbmd0aH0gb3BlbmFpIHRva2VucyAoJHtXT1JLRVJTX1BFUl9UT0tFTn0gd29ya2VycyBlYWNoKWAsXG4gICAgKTtcblxuICAgIGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChcbiAgICAgIG9wZW5haVRva2Vucy5tYXAoYXN5bmMgKHQpID0+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5zcGF3bldvcmtlcnModC5pZCwgdC5uYW1lLCB0LmNyZWRlbnRpYWxzIGFzIE9wZW5BSUNyZWRlbnRpYWxzKTtcbiAgICAgICAgaWYgKCF0LmFjdGl2ZSkgdGhpcy5vblRva2VuRGVhY3RpdmF0ZWQodC5pZCk7XG4gICAgICB9KSxcbiAgICApO1xuICB9XG5cbiAgYXN5bmMgc3RvcCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0aGlzLnJlamVjdEFsbFF1ZXVlZChcIkRJU1BBVENIRVJfU0hVVERPV05cIik7XG4gICAgY29uc3Qga2lsbHMgPSBbLi4udGhpcy53b3JrZXJQb29sLnZhbHVlcygpXS5mbGF0KCkubWFwKCh3KSA9PiB3LmtpbGwoKSk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKGtpbGxzKTtcbiAgICB0aGlzLndvcmtlclBvb2wuY2xlYXIoKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBUb2tlbiBldmVudHMgKGZyb20gVG9rZW5TdWJzY3JpYmVyKSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBhc3luYyBvblRva2VuQWRkZWQoaWQ6IG51bWJlciwgbmFtZTogc3RyaW5nLCBjcmVkZW50aWFsczogT3BlbkFJQ3JlZGVudGlhbHMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy53b3JrZXJQb29sLmhhcyhpZCkpIHJldHVybjtcbiAgICBhd2FpdCB0aGlzLnNwYXduV29ya2VycyhpZCwgbmFtZSwgY3JlZGVudGlhbHMpO1xuICB9XG5cbiAgYXN5bmMgb25Ub2tlblJlbW92ZWQoaWQ6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHdvcmtlcnMgPSB0aGlzLndvcmtlclBvb2wuZ2V0KGlkKSA/PyBbXTtcbiAgICBjb25zdCB0b2tlbk5hbWUgPSB3b3JrZXJzWzBdPy50b2tlbk5hbWU7XG4gICAgdGhpcy53b3JrZXJQb29sLmRlbGV0ZShpZCk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKHdvcmtlcnMubWFwKCh3KSA9PiB3LmtpbGwoKSkpO1xuICAgIGlmICh0aGlzLmdldEFsbFJlYWR5QWN0aXZlV29ya2VycygpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhpcy5yZWplY3RBbGxRdWV1ZWQoXCJOT19PUEVOQUlfV09SS0VSU1wiKTtcbiAgICB9XG4gICAgaWYgKHdvcmtlcnMubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgbGFiZWwgPSB0b2tlbk5hbWUgPz8gYHRva2VuICR7aWR9YDtcbiAgICAgIGxvZ2dlci5pbmZvKGB3b3JrZXJzIHJlbW92ZWQ6ICR7bGFiZWx9ICgke3dvcmtlcnMubGVuZ3RofSlgKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBvblRva2VuVXBkYXRlZChpZDogbnVtYmVyLCBuYW1lOiBzdHJpbmcsIGNyZWRlbnRpYWxzOiBPcGVuQUlDcmVkZW50aWFscyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGV4aXN0aW5nID0gdGhpcy53b3JrZXJQb29sLmdldChpZCkgPz8gW107XG4gICAgaWYgKGV4aXN0aW5nLmxlbmd0aCA9PT0gMCkge1xuICAgICAgYXdhaXQgdGhpcy5zcGF3bldvcmtlcnMoaWQsIG5hbWUsIGNyZWRlbnRpYWxzKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoZXhpc3RpbmcuZXZlcnkoKHcpID0+IHcuY2FuUmV1c2VGb3JUb2tlbihuYW1lLCBjcmVkZW50aWFscykpKSB7XG4gICAgICBleGlzdGluZy5mb3JFYWNoKCh3KSA9PiB3LnVwZGF0ZVRva2VuU3RhdGUobmFtZSwgY3JlZGVudGlhbHMpKTtcbiAgICAgIGxvZ2dlci5pbmZvKGB3b3JrZXJzIHVwZGF0ZWQgaW4tcGxhY2U6ICR7bmFtZX1gKTtcbiAgICAgIHRoaXMuZHJhaW5RdWV1ZSgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMud29ya2VyUG9vbC5kZWxldGUoaWQpO1xuICAgIGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChleGlzdGluZy5tYXAoKHcpID0+IHcua2lsbCgpKSk7XG4gICAgYXdhaXQgdGhpcy5zcGF3bldvcmtlcnMoaWQsIG5hbWUsIGNyZWRlbnRpYWxzKTtcbiAgfVxuXG4gIG9uVG9rZW5EZWFjdGl2YXRlZChpZDogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3Qgd29ya2VycyA9IHRoaXMud29ya2VyUG9vbC5nZXQoaWQpID8/IFtdO1xuICAgIGNvbnN0IHRva2VuTmFtZSA9IHdvcmtlcnNbMF0/LnRva2VuTmFtZTtcbiAgICB3b3JrZXJzLmZvckVhY2goKHcpID0+IHtcbiAgICAgIHcuYWN0aXZlID0gZmFsc2U7XG4gICAgfSk7XG4gICAgaWYgKHRoaXMuZ2V0QWxsUmVhZHlBY3RpdmVXb3JrZXJzKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aGlzLnJlamVjdEFsbFF1ZXVlZChcIk5PX0FDVElWRV9XT1JLRVJTXCIpO1xuICAgIH1cbiAgICBjb25zdCBsYWJlbCA9IHRva2VuTmFtZSA/PyBgdG9rZW4gJHtpZH1gO1xuICAgIGxvZ2dlci5pbmZvKGB3b3JrZXJzIGRlYWN0aXZhdGVkOiAke2xhYmVsfWApO1xuICB9XG5cbiAgb25Ub2tlbkFjdGl2YXRlZChpZDogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3Qgd29ya2VycyA9IHRoaXMud29ya2VyUG9vbC5nZXQoaWQpID8/IFtdO1xuICAgIGNvbnN0IHRva2VuTmFtZSA9IHdvcmtlcnNbMF0/LnRva2VuTmFtZTtcbiAgICB3b3JrZXJzLmZvckVhY2goKHcpID0+IHtcbiAgICAgIHcuYWN0aXZlID0gdHJ1ZTtcbiAgICB9KTtcbiAgICB0aGlzLmRyYWluUXVldWUoKTtcbiAgICBjb25zdCBsYWJlbCA9IHRva2VuTmFtZSA/PyBgdG9rZW4gJHtpZH1gO1xuICAgIGxvZ2dlci5pbmZvKGB3b3JrZXJzIGFjdGl2YXRlZDogJHtsYWJlbH1gKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBHZW5lcmF0ZSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBhc3luYyBnZW5lcmF0ZShyZXE6IEdlbmVyYXRlUmVxdWVzdCk6IFByb21pc2U8R2VuZXJhdGVSZXN1bHQ+IHtcbiAgICAvLyB0aHJlYWQg7J6s7IKs7JqpIOqyveuhnDog7KKM7ZGcIHdvcmtlciDrpbwg7KCQ7Jyg7ZW0IOq4sOyhtCB0aHJlYWQg7JeQIHR1cm4g66eMIOyLpO2WiS5cbiAgICBjb25zdCByZXVzZVdvcmtlciA9IGF3YWl0IHRoaXMuYWNxdWlyZVJldXNlV29ya2VyKHJlcSk7XG4gICAgaWYgKHJldXNlV29ya2VyKSB7XG4gICAgICBsb2dnZXIuaW5mbyhcbiAgICAgICAgYOKGuyAke3JldXNlV29ya2VyLnRva2VuTmFtZX1bJHtyZXVzZVdvcmtlci50b2tlbklkfV0gKHJldXNlIHRocmVhZCwgJHtyZXEubW9kZWx9KWAsXG4gICAgICApO1xuICAgICAgcmV0dXJuIHRoaXMuZXhlY3V0ZUFuZFJlbGVhc2UocmV1c2VXb3JrZXIsICh3KSA9PlxuICAgICAgICB0aGlzLmV4ZWN1dGVUdXJuKHcsIHJlcSwgcmVxLnJldXNlIS50aHJlYWRJZCksXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHdvcmtlciA9IHRoaXMuYWNxdWlyZUlkbGVXb3JrZXIoKTtcbiAgICBpZiAod29ya2VyKSB7XG4gICAgICBsb2dnZXIuaW5mbyhg4oaSICR7d29ya2VyLnRva2VuTmFtZX1bJHt3b3JrZXIudG9rZW5JZH1dIChtb2RlbDogJHtyZXEubW9kZWx9KWApO1xuICAgICAgcmV0dXJuIHRoaXMuZXhlY3V0ZUFuZFJlbGVhc2Uod29ya2VyLCAodykgPT4gdGhpcy5leGVjdXRlVHVybih3LCByZXEpKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZW5xdWV1ZSgodykgPT4ge1xuICAgICAgbG9nZ2VyLmluZm8oYOKGkiAke3cudG9rZW5OYW1lfVske3cudG9rZW5JZH1dIChtb2RlbDogJHtyZXEubW9kZWx9LCBxdWV1ZWQpYCk7XG4gICAgICByZXR1cm4gdGhpcy5leGVjdXRlVHVybih3LCByZXEpO1xuICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgZ2VuZXJhdGVTdHJlYW0ocmVxOiBHZW5lcmF0ZVJlcXVlc3QsIGNiOiBHZW5lcmF0ZVN0cmVhbUNhbGxiYWNrcyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHJldXNlV29ya2VyID0gYXdhaXQgdGhpcy5hY3F1aXJlUmV1c2VXb3JrZXIocmVxKTtcbiAgICBpZiAocmV1c2VXb3JrZXIpIHtcbiAgICAgIGxvZ2dlci5pbmZvKGDihrsgJHtyZXVzZVdvcmtlci50b2tlbk5hbWV9WyR7cmV1c2VXb3JrZXIudG9rZW5JZH1dIChyZXVzZSB0aHJlYWQsIFtzdHJlYW1dKWApO1xuICAgICAgcmV0dXJuIHRoaXMuZXhlY3V0ZUFuZFJlbGVhc2UocmV1c2VXb3JrZXIsICh3KSA9PlxuICAgICAgICB0aGlzLmV4ZWN1dGVTdHJlYW1UdXJuKHcsIHJlcSwgY2IsIHJlcS5yZXVzZSEudGhyZWFkSWQpLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCB3b3JrZXIgPSB0aGlzLmFjcXVpcmVJZGxlV29ya2VyKCk7XG4gICAgaWYgKHdvcmtlcikge1xuICAgICAgbG9nZ2VyLmluZm8oYOKGkiAke3dvcmtlci50b2tlbk5hbWV9WyR7d29ya2VyLnRva2VuSWR9XSAobW9kZWw6ICR7cmVxLm1vZGVsfSwgW3N0cmVhbV0pYCk7XG4gICAgICByZXR1cm4gdGhpcy5leGVjdXRlQW5kUmVsZWFzZSh3b3JrZXIsICh3KSA9PiB0aGlzLmV4ZWN1dGVTdHJlYW1UdXJuKHcsIHJlcSwgY2IpKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZW5xdWV1ZSgodykgPT4ge1xuICAgICAgbG9nZ2VyLmluZm8oYOKGkiAke3cudG9rZW5OYW1lfVske3cudG9rZW5JZH1dIChtb2RlbDogJHtyZXEubW9kZWx9LCBbc3RyZWFtXSwgcXVldWVkKWApO1xuICAgICAgcmV0dXJuIHRoaXMuZXhlY3V0ZVN0cmVhbVR1cm4odywgcmVxLCBjYik7XG4gICAgfSk7XG4gIH1cblxuICAvLyByZXVzZSDsooztkZzqsIAg7Jyg7Zqo7ZWY66m0IOq3uCB3b3JrZXIg66W8IGJ1c3kg7KCQ7Jyg7ZW0IOuwmO2ZmC4g7JeG6rGw64KYIO2PtOuwsSDrjIDsg4HsnbTrqbQgbnVsbC5cbiAgLy8g7Y+067CxIOyCrOycoDog6riw64qlIG9mZiAvIOyijO2RnCDsl4bsnYwgLyB3b3JrZXIg67aA7J6swrfso73snYwgLyBlcG9jaCDrtojsnbzsuZgocmVzdGFydCkgLyB0aHJlYWQg7IaM66m4IC9cbiAgLy8gICAgICAgICAgICBidXN5IOuMgOq4sCDtg4DsnoTslYTsm4MuIG51bGwg67CY7ZmYIOyLnCDtmLjstpzrtoDripQg7IOIIHRocmVhZCDqsr3roZzroZwg7KeE7ZaJLlxuICBhc3luYyBhY3F1aXJlUmV1c2VXb3JrZXIocmVxOiBHZW5lcmF0ZVJlcXVlc3QpOiBQcm9taXNlPENvZGV4QXBwU2VydmVyV29ya2VyIHwgbnVsbD4ge1xuICAgIGlmICghVEhSRUFEX1JFVVNFX0VOQUJMRUQgfHwgIXJlcS5yZXVzZSkgcmV0dXJuIG51bGw7XG4gICAgY29uc3QgeyB3b3JrZXJJZCwgdGhyZWFkSWQsIGVwb2NoIH0gPSByZXEucmV1c2U7XG5cbiAgICBjb25zdCB3b3JrZXIgPSB0aGlzLmZpbmRXb3JrZXJCeUlkKHdvcmtlcklkKTtcbiAgICBpZiAoIXdvcmtlciB8fCAhd29ya2VyLmlzUmVhZHkgfHwgIXdvcmtlci5hY3RpdmUpIHJldHVybiBudWxsO1xuICAgIGlmICh3b3JrZXIuZXBvY2ggIT09IGVwb2NoKSByZXR1cm4gbnVsbDtcbiAgICBpZiAoIXdvcmtlci5oYXNUaHJlYWQodGhyZWFkSWQpKSByZXR1cm4gbnVsbDtcblxuICAgIGNvbnN0IGRlYWRsaW5lID0gRGF0ZS5ub3coKSArIFJFVVNFX1dPUktFUl9XQUlUX01TO1xuICAgIGZvciAoOzspIHtcbiAgICAgIC8vIHJlc3RhcnQoZXBvY2gg67OA6rK9KSAvIHRocmVhZCDshozrqbjsnbQg64yA6riwIOykkeyXkCDrsJzsg53tlZjrqbQg7Y+067CxLlxuICAgICAgaWYgKHdvcmtlci5lcG9jaCAhPT0gZXBvY2ggfHwgIXdvcmtlci5oYXNUaHJlYWQodGhyZWFkSWQpKSByZXR1cm4gbnVsbDtcbiAgICAgIGlmICh3b3JrZXIudHJ5QWNxdWlyZVR1cm4oKSkgcmV0dXJuIHdvcmtlcjtcbiAgICAgIGlmIChEYXRlLm5vdygpID49IGRlYWRsaW5lKSByZXR1cm4gbnVsbDtcbiAgICAgIGF3YWl0IHNsZWVwKFJFVVNFX1dPUktFUl9QT0xMX01TKTtcbiAgICB9XG4gIH1cblxuICBmaW5kV29ya2VyQnlJZCh3b3JrZXJJZDogbnVtYmVyKTogQ29kZXhBcHBTZXJ2ZXJXb3JrZXIgfCBudWxsIHtcbiAgICBmb3IgKGNvbnN0IHdvcmtlcnMgb2YgdGhpcy53b3JrZXJQb29sLnZhbHVlcygpKSB7XG4gICAgICBmb3IgKGNvbnN0IHcgb2Ygd29ya2Vycykge1xuICAgICAgICBpZiAobWFrZVdvcmtlcklkKHcudG9rZW5JZCwgdy53b3JrZXJJbmRleCkgPT09IHdvcmtlcklkKSByZXR1cm4gdztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBhc3luYyBpbnRlcnJ1cHRXb3JrZXJUdXJuKHRocmVhZElkOiBzdHJpbmcsIHR1cm5JZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgYWxsV29ya2VycyA9IFsuLi50aGlzLndvcmtlclBvb2wudmFsdWVzKCldLmZsYXQoKS5maWx0ZXIoKHcpID0+IHcuaXNSZWFkeSk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKGFsbFdvcmtlcnMubWFwKCh3KSA9PiB3LmludGVycnVwdFR1cm4odGhyZWFkSWQsIHR1cm5JZCkpKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBXb3JrZXIgc2VsZWN0aW9uIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuICAvLyAg6riw67O4IHJvdW5kLXJvYmluXG4gIC8vIFRPRE86IOy2lO2bhCDri6Trpbgg7JWM6rOg66as7KaY7Jy866GcIOuzgOqyvSDqsIDriqXtlZjqsowg7KeA7JuQXG4gIGFjcXVpcmVJZGxlV29ya2VyKCk6IENvZGV4QXBwU2VydmVyV29ya2VyIHwgbnVsbCB7XG4gICAgY29uc3QgYWxsV29ya2VycyA9IHRoaXMuZ2V0QWxsUmVhZHlBY3RpdmVXb3JrZXJzKCk7XG4gICAgaWYgKGFsbFdvcmtlcnMubGVuZ3RoID09PSAwKSByZXR1cm4gbnVsbDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFsbFdvcmtlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IHcgPSBhbGxXb3JrZXJzWyh0aGlzLnJyQ3Vyc29yICsgaSkgJSBhbGxXb3JrZXJzLmxlbmd0aF0hO1xuICAgICAgaWYgKHcudHJ5QWNxdWlyZVR1cm4oKSkge1xuICAgICAgICB0aGlzLnJyQ3Vyc29yID0gKHRoaXMucnJDdXJzb3IgKyBpICsgMSkgJSBhbGxXb3JrZXJzLmxlbmd0aDtcbiAgICAgICAgcmV0dXJuIHc7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgZ2V0QWxsUmVhZHlBY3RpdmVXb3JrZXJzKCk6IENvZGV4QXBwU2VydmVyV29ya2VyW10ge1xuICAgIHJldHVybiBbLi4udGhpcy53b3JrZXJQb29sLnZhbHVlcygpXS5mbGF0KCkuZmlsdGVyKCh3KSA9PiB3LmlzUmVhZHkgJiYgdy5hY3RpdmUpO1xuICB9XG5cbiAgLy8g4pSA4pSAIFF1ZXVlIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIGVucXVldWU8VD4oZXhlY3V0ZTogKHdvcmtlcjogQ29kZXhBcHBTZXJ2ZXJXb3JrZXIpID0+IFByb21pc2U8VD4pOiBQcm9taXNlPFQ+IHtcbiAgICBpZiAodGhpcy5nZXRBbGxSZWFkeUFjdGl2ZVdvcmtlcnMoKS5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoXCJOT19PUEVOQUlfV09SS0VSU1wiKSk7XG4gICAgfVxuICAgIGlmICh0aGlzLnF1ZXVlLmxlbmd0aCA+PSBNQVhfUVVFVUVfU0laRSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBFcnJvcihcIlNFUlZFUl9CVVNZXCIpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2U8VD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgaXRlbTogUXVldWVJdGVtID0ge1xuICAgICAgICByZXNvbHZlOiAod29ya2VyKSA9PiB7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KGl0ZW0udGltZXIpO1xuICAgICAgICAgIGl0ZW0uYWJvcnRDbGVhbnVwPy4oKTtcbiAgICAgICAgICBQcm9taXNlLnJlc29sdmUoKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4gdGhpcy5leGVjdXRlQW5kUmVsZWFzZSh3b3JrZXIsIGV4ZWN1dGUpKVxuICAgICAgICAgICAgLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgICAgfSxcbiAgICAgICAgcmVqZWN0OiAoZXJyKSA9PiB7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KGl0ZW0udGltZXIpO1xuICAgICAgICAgIGl0ZW0uYWJvcnRDbGVhbnVwPy4oKTtcbiAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgfSxcbiAgICAgICAgdGltZXI6IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgIHRoaXMucmVtb3ZlRnJvbVF1ZXVlKGl0ZW0pO1xuICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoXCJTRVJWRVJfQlVTWVwiKSk7XG4gICAgICAgIH0sIFFVRVVFX1RJTUVPVVRfTVMpLFxuICAgICAgfTtcblxuICAgICAgdGhpcy5xdWV1ZS5wdXNoKGl0ZW0pO1xuICAgIH0pO1xuICB9XG5cbiAgcmVtb3ZlRnJvbVF1ZXVlKGl0ZW06IFF1ZXVlSXRlbSk6IHZvaWQge1xuICAgIGNsZWFyVGltZW91dChpdGVtLnRpbWVyKTtcbiAgICBpdGVtLmFib3J0Q2xlYW51cD8uKCk7XG4gICAgY29uc3QgaWR4ID0gdGhpcy5xdWV1ZS5pbmRleE9mKGl0ZW0pO1xuICAgIGlmIChpZHggIT09IC0xKSB0aGlzLnF1ZXVlLnNwbGljZShpZHgsIDEpO1xuICB9XG5cbiAgcmVqZWN0QWxsUXVldWVkKHJlYXNvbjogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgZXJyID0gbmV3IEVycm9yKHJlYXNvbik7XG4gICAgdGhpcy5xdWV1ZS5mb3JFYWNoKChpdGVtKSA9PiB7XG4gICAgICBjbGVhclRpbWVvdXQoaXRlbS50aW1lcik7XG4gICAgICBpdGVtLmFib3J0Q2xlYW51cD8uKCk7XG4gICAgICBpdGVtLnJlamVjdChlcnIpO1xuICAgIH0pO1xuICAgIHRoaXMucXVldWUgPSBbXTtcbiAgfVxuXG4gIGRyYWluUXVldWUocmVsZWFzZWRXb3JrZXI/OiBDb2RleEFwcFNlcnZlcldvcmtlcik6IHZvaWQge1xuICAgIGlmIChcbiAgICAgIHJlbGVhc2VkV29ya2VyICYmXG4gICAgICB0aGlzLnF1ZXVlLmxlbmd0aCA+IDAgJiZcbiAgICAgIHJlbGVhc2VkV29ya2VyLmlzUmVhZHkgJiZcbiAgICAgIHJlbGVhc2VkV29ya2VyLmFjdGl2ZSAmJlxuICAgICAgcmVsZWFzZWRXb3JrZXIudHJ5QWNxdWlyZVR1cm4oKVxuICAgICkge1xuICAgICAgY29uc3QgbmV4dCA9IHRoaXMucXVldWUuc2hpZnQoKSE7XG4gICAgICBuZXh0LnJlc29sdmUocmVsZWFzZWRXb3JrZXIpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHdoaWxlICh0aGlzLnF1ZXVlLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IHdvcmtlciA9IHRoaXMuYWNxdWlyZUlkbGVXb3JrZXIoKTtcbiAgICAgIGlmICghd29ya2VyKSBicmVhaztcbiAgICAgIGNvbnN0IG5leHQgPSB0aGlzLnF1ZXVlLnNoaWZ0KCkhO1xuICAgICAgbmV4dC5yZXNvbHZlKHdvcmtlcik7XG4gICAgfVxuICB9XG5cbiAgLy8g4pSA4pSAIEV4ZWN1dGlvbiDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBhc3luYyBleGVjdXRlQW5kUmVsZWFzZTxUPihcbiAgICB3b3JrZXI6IENvZGV4QXBwU2VydmVyV29ya2VyLFxuICAgIGV4ZWN1dGU6ICh3b3JrZXI6IENvZGV4QXBwU2VydmVyV29ya2VyKSA9PiBQcm9taXNlPFQ+LFxuICApOiBQcm9taXNlPFQ+IHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGF3YWl0IGV4ZWN1dGUod29ya2VyKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgd29ya2VyLnJlbGVhc2VUdXJuKCk7XG4gICAgICB0aGlzLmRyYWluUXVldWUod29ya2VyKTtcbiAgICB9XG4gIH1cblxuICAvLyByZXVzZVRocmVhZElkIOqwgCDsnojsnLzrqbQg6riw7KG0IHRocmVhZCDsl5AgZGVsdGEocmV1c2VJbnB1dCnrp4wsIOyXhuycvOuptCDsg4ggdGhyZWFkIOyXkCDsoITssrRcbiAgLy8gcHJvbXB0KGNvbGRJbnB1dCkgKyBoaXN0b3J5IGluamVjdC4gcmV1c2Ug6rCAIGRpc3BhdGNoZXIg64uo7JeQ7IScIO2PtOuwseuQmOuptCDtm4TsnpDroZwg65ao7Ja07KeE64ukLlxuICBwcml2YXRlIGJ1aWxkVHVyblJlcXVlc3QocmVxOiBHZW5lcmF0ZVJlcXVlc3QsIHJldXNlVGhyZWFkSWQ/OiBzdHJpbmcpOiBUdXJuUmVxdWVzdCB7XG4gICAgY29uc3QgcmV1c2luZyA9IHJldXNlVGhyZWFkSWQgIT09IHVuZGVmaW5lZDtcbiAgICByZXR1cm4ge1xuICAgICAgaW5wdXQ6IHJldXNpbmcgJiYgcmVxLnJldXNlSW5wdXQgPyByZXEucmV1c2VJbnB1dCA6IHJlcS5jb2xkSW5wdXQsXG4gICAgICBoaXN0b3J5OiByZXVzaW5nID8gdW5kZWZpbmVkIDogcmVxLmNvbGRIaXN0b3J5LFxuICAgICAgZGV2ZWxvcGVySW5zdHJ1Y3Rpb25zOiByZXEuc3lzdGVtUHJvbXB0LFxuICAgICAgb3V0cHV0U2NoZW1hOiByZXEub3V0cHV0U2NoZW1hLFxuICAgICAgZWZmb3J0OiByZXEuZWZmb3J0ID8/IERFRkFVTFRfRUZGT1JULFxuICAgICAgbW9kZWw6IHJlcS5tb2RlbCxcbiAgICAgIHZlcmJvc2l0eTogcmVxLnZlcmJvc2l0eSxcbiAgICAgIHJlYXNvbmluZ1N1bW1hcnk6IHJlcS5yZWFzb25pbmdTdW1tYXJ5LFxuICAgICAgc2VydmljZVRpZXI6IHJlcS5zZXJ2aWNlVGllcixcbiAgICB9O1xuICB9XG5cbiAgYXN5bmMgZXhlY3V0ZVR1cm4oXG4gICAgd29ya2VyOiBDb2RleEFwcFNlcnZlcldvcmtlcixcbiAgICByZXE6IEdlbmVyYXRlUmVxdWVzdCxcbiAgICByZXVzZVRocmVhZElkPzogc3RyaW5nLFxuICApOiBQcm9taXNlPEdlbmVyYXRlUmVzdWx0PiB7XG4gICAgY29uc3QgdHVyblJlcSA9IHRoaXMuYnVpbGRUdXJuUmVxdWVzdChyZXEsIHJldXNlVGhyZWFkSWQpO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHdvcmtlci5leGVjdXRlVHVybih0dXJuUmVxLCByZXVzZVRocmVhZElkKTtcbiAgICByZXR1cm4ge1xuICAgICAgdGV4dDogcmVzdWx0LnRleHQsXG4gICAgICB0b2tlbk5hbWU6IHdvcmtlci50b2tlbk5hbWUsXG4gICAgICB1c2FnZTogcmVzdWx0LnVzYWdlLFxuICAgICAgZHVyYXRpb25NczogcmVzdWx0LmR1cmF0aW9uTXMsXG4gICAgICBtb2RlbDogcmVzdWx0Lm1vZGVsLFxuICAgICAgdGhyZWFkQ29vcmQ6IHtcbiAgICAgICAgd29ya2VySWQ6IG1ha2VXb3JrZXJJZCh3b3JrZXIudG9rZW5JZCwgd29ya2VyLndvcmtlckluZGV4KSxcbiAgICAgICAgdGhyZWFkSWQ6IHJlc3VsdC50aHJlYWRJZCxcbiAgICAgICAgZXBvY2g6IHdvcmtlci5lcG9jaCxcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxuXG4gIGFzeW5jIGV4ZWN1dGVTdHJlYW1UdXJuKFxuICAgIHdvcmtlcjogQ29kZXhBcHBTZXJ2ZXJXb3JrZXIsXG4gICAgcmVxOiBHZW5lcmF0ZVJlcXVlc3QsXG4gICAgY2I6IEdlbmVyYXRlU3RyZWFtQ2FsbGJhY2tzLFxuICAgIHJldXNlVGhyZWFkSWQ/OiBzdHJpbmcsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHR1cm5SZXEgPSB0aGlzLmJ1aWxkVHVyblJlcXVlc3QocmVxLCByZXVzZVRocmVhZElkKTtcbiAgICAvLyB3b3JrZXIg7J2YIFR1cm5SZXN1bHQg7JeQIHRva2VuTmFtZS90aHJlYWRDb29yZCDrpbwg67aZ7JesIOyDgeychChHZW5lcmF0ZVJlc3VsdCnroZwg7Jis66aw64ukLlxuICAgIC8vIHRocmVhZElkIOuKlCDsg4ggdGhyZWFkIOuptCBvblRocmVhZElkIOuhnCDtmZXsoJXrkJjrr4DroZwg66+466asIOuztOq0gO2VtCDrkZDqs6Agb25Db21wbGV0ZSDrlYwg7J2964qU64ukLlxuICAgIGxldCByZXNvbHZlZFRocmVhZElkID0gcmV1c2VUaHJlYWRJZCA/PyBcIlwiO1xuICAgIGNvbnN0IHdyYXBwZWRDYjogU3RyZWFtQ2FsbGJhY2tzID0ge1xuICAgICAgLi4uY2IsXG4gICAgICBvblRocmVhZElkOiAodGhyZWFkSWQpID0+IHtcbiAgICAgICAgcmVzb2x2ZWRUaHJlYWRJZCA9IHRocmVhZElkO1xuICAgICAgICBjYi5vblRocmVhZElkPy4odGhyZWFkSWQpO1xuICAgICAgfSxcbiAgICAgIG9uQ29tcGxldGU6IChyZXN1bHQpID0+IHtcbiAgICAgICAgY2Iub25Db21wbGV0ZSh7XG4gICAgICAgICAgLi4ucmVzdWx0LFxuICAgICAgICAgIHRva2VuTmFtZTogd29ya2VyLnRva2VuTmFtZSxcbiAgICAgICAgICB0aHJlYWRDb29yZDoge1xuICAgICAgICAgICAgd29ya2VySWQ6IG1ha2VXb3JrZXJJZCh3b3JrZXIudG9rZW5JZCwgd29ya2VyLndvcmtlckluZGV4KSxcbiAgICAgICAgICAgIHRocmVhZElkOiByZXNvbHZlZFRocmVhZElkLFxuICAgICAgICAgICAgZXBvY2g6IHdvcmtlci5lcG9jaCxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH0sXG4gICAgfTtcbiAgICBhd2FpdCB3b3JrZXIuZXhlY3V0ZVR1cm5TdHJlYW0odHVyblJlcSwgd3JhcHBlZENiLCByZXVzZVRocmVhZElkKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBTcGF3biDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBhc3luYyBzcGF3bldvcmtlcnMoXG4gICAgdG9rZW5JZDogbnVtYmVyLFxuICAgIHRva2VuTmFtZTogc3RyaW5nLFxuICAgIGNyZWRlbnRpYWxzOiBPcGVuQUlDcmVkZW50aWFscyxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3Qgd29ya2VyczogQ29kZXhBcHBTZXJ2ZXJXb3JrZXJbXSA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgV09SS0VSU19QRVJfVE9LRU47IGkrKykge1xuICAgICAgaWYgKGkgPiAwKSBhd2FpdCBzbGVlcChTUEFXTl9JTlRFUlZBTF9NUyk7XG4gICAgICBjb25zdCB3b3JrZXIgPSBhd2FpdCB0aGlzLnNwYXduU2luZ2xlV29ya2VyKHRva2VuSWQsIHRva2VuTmFtZSwgY3JlZGVudGlhbHMsIGkpO1xuICAgICAgaWYgKHdvcmtlcikgd29ya2Vycy5wdXNoKHdvcmtlcik7XG4gICAgfVxuICAgIGlmICh3b3JrZXJzLmxlbmd0aCA+IDApIHRoaXMud29ya2VyUG9vbC5zZXQodG9rZW5JZCwgd29ya2Vycyk7XG4gIH1cblxuICBhc3luYyBzcGF3blNpbmdsZVdvcmtlcihcbiAgICB0b2tlbklkOiBudW1iZXIsXG4gICAgdG9rZW5OYW1lOiBzdHJpbmcsXG4gICAgY3JlZGVudGlhbHM6IE9wZW5BSUNyZWRlbnRpYWxzLFxuICAgIHdvcmtlckluZGV4OiBudW1iZXIsXG4gICk6IFByb21pc2U8Q29kZXhBcHBTZXJ2ZXJXb3JrZXIgfCBudWxsPiB7XG4gICAgY29uc3Qgd29ya2VyID0gbmV3IENvZGV4QXBwU2VydmVyV29ya2VyKHtcbiAgICAgIHRva2VuSWQsXG4gICAgICB0b2tlbk5hbWUsXG4gICAgICBhY2Nlc3NUb2tlbjogY3JlZGVudGlhbHMuYWNjZXNzVG9rZW4sXG4gICAgICBhY2NvdW50SWQ6IGNyZWRlbnRpYWxzLmFjY291bnRJZCxcbiAgICAgIHBsYW5UeXBlOiBjcmVkZW50aWFscy5wbGFuVHlwZSxcbiAgICAgIHdvcmtlckluZGV4LFxuICAgIH0pO1xuXG4gICAgd29ya2VyLm9uUmVhZHkgPSAoKSA9PiB0aGlzLmRyYWluUXVldWUoKTtcblxuICAgIHdvcmtlci5zZXRTZXJ2ZXJSZXF1ZXN0SGFuZGxlcihhc3luYyAobWV0aG9kKSA9PiB7XG4gICAgICBpZiAobWV0aG9kID09PSBcImFjY291bnQvY2hhdGdwdEF1dGhUb2tlbnMvcmVmcmVzaFwiKSB7XG4gICAgICAgIHJldHVybiBoYW5kbGVDaGF0Z3B0QXV0aFRva2Vuc1JlZnJlc2godG9rZW5JZCk7XG4gICAgICB9XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuaGFuZGxlZCBzZXJ2ZXItcmVxdWVzdDogJHttZXRob2R9YCk7XG4gICAgfSk7XG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgd29ya2VyLmluaXRpYWxpemUoKTtcbiAgICAgIGxvZ2dlci5pbmZvKGB3b3JrZXIgc3Bhd25lZDogJHt0b2tlbk5hbWV9WyR7d29ya2VySW5kZXh9XWApO1xuICAgICAgcmV0dXJuIHdvcmtlcjtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBsb2dnZXIud2Fybihgd29ya2VyIHNwYXduIGZhaWxlZDogJHt0b2tlbk5hbWV9WyR7d29ya2VySW5kZXh9XTogJHsoZSBhcyBFcnJvcikubWVzc2FnZX1gKTtcbiAgICAgIGF3YWl0IHdvcmtlci5raWxsKCkuY2F0Y2goKCkgPT4ge30pO1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgLy8g4pSA4pSAIFJhdGUgbGltaXRzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIHJhdGVMaW1pdHNDYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCB7IGRhdGE6IHVua25vd247IGNhY2hlZEF0OiBudW1iZXIgfT4oKTtcbiAgc3RhdGljIHJlYWRvbmx5IFJBVEVfTElNSVRTX0NBQ0hFX1RUTCA9IDYwXzAwMDtcblxuICBhc3luYyBnZXRSYXRlTGltaXRzKHRva2VuTmFtZT86IHN0cmluZyk6IFByb21pc2U8dW5rbm93bj4ge1xuICAgIGNvbnN0IGNhY2hlS2V5ID0gdG9rZW5OYW1lID8/IFwiX2RlZmF1bHRcIjtcbiAgICBjb25zdCBjYWNoZWQgPSB0aGlzLnJhdGVMaW1pdHNDYWNoZS5nZXQoY2FjaGVLZXkpO1xuICAgIGlmIChjYWNoZWQgJiYgRGF0ZS5ub3coKSAtIGNhY2hlZC5jYWNoZWRBdCA8IE9wZW5BSURpc3BhdGNoZXIuUkFURV9MSU1JVFNfQ0FDSEVfVFRMKSB7XG4gICAgICByZXR1cm4gY2FjaGVkLmRhdGE7XG4gICAgfVxuXG4gICAgY29uc3QgYWxsV29ya2VycyA9IFsuLi50aGlzLndvcmtlclBvb2wudmFsdWVzKCldLmZsYXQoKS5maWx0ZXIoKHcpID0+IHcuaXNSZWFkeSk7XG4gICAgY29uc3Qgd29ya2VyID0gdG9rZW5OYW1lID8gYWxsV29ya2Vycy5maW5kKCh3KSA9PiB3LnRva2VuTmFtZSA9PT0gdG9rZW5OYW1lKSA6IGFsbFdvcmtlcnNbMF07XG4gICAgaWYgKCF3b3JrZXIpIHRocm93IG5ldyBFcnJvcihcIm5vIHJlYWR5IG9wZW5haSB3b3JrZXJzXCIpO1xuICAgIGNvbnN0IGRhdGEgPSBhd2FpdCB3b3JrZXIuZ2V0UmF0ZUxpbWl0cygpO1xuICAgIHRoaXMucmF0ZUxpbWl0c0NhY2hlLnNldChjYWNoZUtleSwgeyBkYXRhLCBjYWNoZWRBdDogRGF0ZS5ub3coKSB9KTtcbiAgICByZXR1cm4gZGF0YTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBCcm93c2VyIGxvZ2luIGZsb3cg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgcGVuZGluZ0xvZ2luOiB7XG4gICAgd29ya2VyOiBDb2RleEFwcFNlcnZlcldvcmtlcjtcbiAgICBuYW1lOiBzdHJpbmc7XG4gICAgdGltZXI6IFJldHVyblR5cGU8dHlwZW9mIHNldFRpbWVvdXQ+O1xuICB9IHwgbnVsbCA9IG51bGw7XG5cbiAgYXN5bmMgc3RhcnRCcm93c2VyTG9naW4obmFtZTogc3RyaW5nKTogUHJvbWlzZTx7IGF1dGhVcmw6IHN0cmluZyB9PiB7XG4gICAgaWYgKHRoaXMucGVuZGluZ0xvZ2luKSB7XG4gICAgICB0aGlzLnBlbmRpbmdMb2dpbi53b3JrZXIua2lsbCgpLmNhdGNoKCgpID0+IHt9KTtcbiAgICAgIGNsZWFyVGltZW91dCh0aGlzLnBlbmRpbmdMb2dpbi50aW1lcik7XG4gICAgICB0aGlzLnBlbmRpbmdMb2dpbiA9IG51bGw7XG4gICAgfVxuXG4gICAgY29uc3QgdGVtcElkID0gRGF0ZS5ub3coKTtcbiAgICBjb25zdCB3b3JrZXIgPSBuZXcgQ29kZXhBcHBTZXJ2ZXJXb3JrZXIoe1xuICAgICAgdG9rZW5JZDogdGVtcElkLFxuICAgICAgdG9rZW5OYW1lOiBuYW1lLFxuICAgICAgYWNjZXNzVG9rZW46IFwiXCIsXG4gICAgICBhY2NvdW50SWQ6IFwiXCIsXG4gICAgfSk7XG5cbiAgICBjb25zdCBhdXRoVXJsID0gYXdhaXQgd29ya2VyLnN0YXJ0QnJvd3NlckxvZ2luKCk7XG5cbiAgICBjb25zdCB0aW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgaWYgKHRoaXMucGVuZGluZ0xvZ2luPy53b3JrZXIgPT09IHdvcmtlcikge1xuICAgICAgICBsb2dnZXIud2FybihgYnJvd3NlciBsb2dpbiB0aW1lb3V0IGZvciAke25hbWV9LCBraWxsaW5nIHdvcmtlcmApO1xuICAgICAgICB3b3JrZXIua2lsbCgpLmNhdGNoKCgpID0+IHt9KTtcbiAgICAgICAgdGhpcy5wZW5kaW5nTG9naW4gPSBudWxsO1xuICAgICAgfVxuICAgIH0sIDMwMF8wMDApO1xuXG4gICAgdGhpcy5wZW5kaW5nTG9naW4gPSB7IHdvcmtlciwgbmFtZSwgdGltZXIgfTtcbiAgICByZXR1cm4geyBhdXRoVXJsIH07XG4gIH1cblxuICBnZXQgcGVuZGluZ0xvZ2luTmFtZSgpOiBzdHJpbmcgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5wZW5kaW5nTG9naW4/Lm5hbWUgPz8gbnVsbDtcbiAgfVxuXG4gIGFzeW5jIGNvbXBsZXRlQnJvd3NlckxvZ2luKCk6IFByb21pc2U8e1xuICAgIGFjY2Vzc1Rva2VuOiBzdHJpbmc7XG4gICAgcmVmcmVzaFRva2VuOiBzdHJpbmc7XG4gICAgaWRUb2tlbj86IHN0cmluZztcbiAgICBhY2NvdW50SWQ6IHN0cmluZztcbiAgfT4ge1xuICAgIGlmICghdGhpcy5wZW5kaW5nTG9naW4pIHRocm93IG5ldyBFcnJvcihcIm5vIHBlbmRpbmcgbG9naW5cIik7XG4gICAgY29uc3QgeyB3b3JrZXIsIHRpbWVyIH0gPSB0aGlzLnBlbmRpbmdMb2dpbjtcblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCB3b3JrZXIud2FpdEZvckJyb3dzZXJMb2dpbkNvbXBsZXRlKCk7XG4gICAgICBjb25zdCBjcmVkcyA9IGF3YWl0IHdvcmtlci5yZWFkTWFuYWdlZENyZWRlbnRpYWxzKCk7XG4gICAgICBpZiAoIWNyZWRzKSB0aHJvdyBuZXcgRXJyb3IoXCJmYWlsZWQgdG8gcmVhZCBjcmVkZW50aWFscyBhZnRlciBsb2dpblwiKTtcbiAgICAgIHJldHVybiBjcmVkcztcbiAgICB9IGZpbmFsbHkge1xuICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgIHRoaXMucGVuZGluZ0xvZ2luID0gbnVsbDtcbiAgICAgIGF3YWl0IHdvcmtlci5raWxsKCkuY2F0Y2goKCkgPT4ge30pO1xuICAgIH1cbiAgfVxuXG4gIC8vIOKUgOKUgCBTdGF0cyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBnZXQgd29ya2VyQ291bnQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gWy4uLnRoaXMud29ya2VyUG9vbC52YWx1ZXMoKV0uZmxhdCgpLmxlbmd0aDtcbiAgfVxuXG4gIGdldCByZWFkeVdvcmtlckNvdW50KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIFsuLi50aGlzLndvcmtlclBvb2wudmFsdWVzKCldLmZsYXQoKS5maWx0ZXIoKHcpID0+IHcuaXNSZWFkeSkubGVuZ3RoO1xuICB9XG5cbiAgZ2V0IHF1ZXVlTGVuZ3RoKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMucXVldWUubGVuZ3RoO1xuICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7O0FBcUJBLE1BQU0sU0FBUyxVQUFVLENBQUMsU0FBUyxvQkFBb0IsQ0FBQztBQUV4RCxNQUFNLGlCQUFpQjtBQUV2QixNQUFNLG9CQUFvQixLQUFLLElBQzdCLE9BQU8sUUFBUSxJQUFJLDJCQUEyQixFQUFFLEVBRnBCLEVBSTdCO0FBQ0QsTUFBTSxtQkFBbUI7QUFDekIsTUFBTSxpQkFBaUI7QUFDdkIsTUFBTSxvQkFBb0I7QUFHMUIsTUFBTSx1QkFBdUIsUUFBUSxJQUFJLDhCQUE4QjtBQUV2RSxNQUFNLHVCQUF1QjtBQUM3QixNQUFNLHVCQUF1QjtBQUc3QixTQUFTLGFBQWEsU0FBaUIsYUFBNkI7QUFDbEUsUUFBTyxVQUFVLEtBQUs7O0FBR3hCLFNBQVMsTUFBTSxJQUEyQjtBQUN4QyxRQUFPLElBQUksU0FBUyxZQUFZLFdBQVcsU0FBUyxHQUFHLENBQUM7O0FBVTFELElBQWEsbUJBQWIsTUFBYSxpQkFBK0M7Q0FDMUQsNkJBQWEsSUFBSSxLQUFxQztDQUN0RCxXQUFXO0NBQ1gsUUFBcUIsRUFBRTtDQUV2QixNQUFNLFFBQXVCO0VBQzNCLE1BQU0sRUFBRSxTQUFTLE1BQU0sV0FB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
|
|
@@ -3,10 +3,198 @@ import { describe, expect, it, vi } from "vitest";
|
|
|
3
3
|
import {
|
|
4
4
|
type GenerateRequest,
|
|
5
5
|
type GenerateResult,
|
|
6
|
+
type GenerateStreamCallbacks,
|
|
6
7
|
} from "../../utils/providers/common/provider-dispatcher";
|
|
7
8
|
import { buildStrictOutputSchema, QgridDispatcherClass } from "./qgrid.dispatcher";
|
|
8
9
|
|
|
10
|
+
function providerResult(overrides: Partial<GenerateResult> = {}): GenerateResult {
|
|
11
|
+
return {
|
|
12
|
+
text: "ok",
|
|
13
|
+
tokenName: "provider/test",
|
|
14
|
+
usage: {
|
|
15
|
+
totalTokens: 10,
|
|
16
|
+
inputTokens: 5,
|
|
17
|
+
cachedInputTokens: 0,
|
|
18
|
+
outputTokens: 5,
|
|
19
|
+
reasoningOutputTokens: 0,
|
|
20
|
+
},
|
|
21
|
+
durationMs: 12,
|
|
22
|
+
model: "model",
|
|
23
|
+
threadCoord: { workerId: 1, threadId: "sess-1", epoch: 0 },
|
|
24
|
+
...overrides,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
9
28
|
describe("QgridDispatcherClass", () => {
|
|
29
|
+
it("AnthropicDispatcher 미초기화 시 query 는 폴백 없이 실패한다", async () => {
|
|
30
|
+
const dispatcher = new QgridDispatcherClass();
|
|
31
|
+
|
|
32
|
+
await expect(
|
|
33
|
+
dispatcher.query({ prompt: "hi", model: "anthropic/claude-sonnet-4-6" }),
|
|
34
|
+
).rejects.toThrow(/Anthropic dispatcher not initialized/);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("AnthropicDispatcher 미초기화 시 queryStream 은 delta 없는 query 폴백 없이 실패한다", async () => {
|
|
38
|
+
const dispatcher = new QgridDispatcherClass();
|
|
39
|
+
|
|
40
|
+
await expect(
|
|
41
|
+
dispatcher.queryStream(
|
|
42
|
+
{ prompt: "hi", model: "anthropic/claude-sonnet-4-6" },
|
|
43
|
+
{
|
|
44
|
+
onDelta: vi.fn(),
|
|
45
|
+
onComplete: vi.fn(),
|
|
46
|
+
onError: vi.fn(),
|
|
47
|
+
},
|
|
48
|
+
),
|
|
49
|
+
).rejects.toThrow(/Anthropic dispatcher not initialized/);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("provider prefix 없는 모델은 AnthropicDispatcher 로 암묵 라우팅하지 않는다", async () => {
|
|
53
|
+
const dispatcher = new QgridDispatcherClass();
|
|
54
|
+
const generate = vi.fn();
|
|
55
|
+
dispatcher.anthropicDispatcher = { generate } as never;
|
|
56
|
+
|
|
57
|
+
await expect(dispatcher.query({ prompt: "hi", model: "claude-sonnet-4-6" })).rejects.toThrow(
|
|
58
|
+
/Direct LLM API fallback not implemented/,
|
|
59
|
+
);
|
|
60
|
+
expect(generate).not.toHaveBeenCalled();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("Anthropic queryStream 은 abortSignal 을 provider request 로 전달한다", async () => {
|
|
64
|
+
const dispatcher = new QgridDispatcherClass();
|
|
65
|
+
const generateStream = vi.fn(async (_req: GenerateRequest, _cb: GenerateStreamCallbacks) => {});
|
|
66
|
+
dispatcher.anthropicDispatcher = { generateStream } as never;
|
|
67
|
+
const abortSignal = new AbortController().signal;
|
|
68
|
+
|
|
69
|
+
await dispatcher.queryStream(
|
|
70
|
+
{ prompt: "hi", model: "anthropic/claude-sonnet-4-6" },
|
|
71
|
+
{
|
|
72
|
+
onDelta: vi.fn(),
|
|
73
|
+
onComplete: vi.fn(),
|
|
74
|
+
onError: vi.fn(),
|
|
75
|
+
},
|
|
76
|
+
abortSignal,
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
expect(generateStream.mock.calls[0]![0].abortSignal).toBe(abortSignal);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("Anthropic queryStream provider error 는 상위 onError 로 전달한다", async () => {
|
|
83
|
+
const dispatcher = new QgridDispatcherClass();
|
|
84
|
+
const serverError = new Error(
|
|
85
|
+
"claude error (anthropic/yds): API Error: 529 Overloaded. This is a server-side issue",
|
|
86
|
+
);
|
|
87
|
+
const generateStream = vi.fn(async (_req, cb) => {
|
|
88
|
+
cb.onError(serverError);
|
|
89
|
+
});
|
|
90
|
+
dispatcher.anthropicDispatcher = { generateStream } as never;
|
|
91
|
+
|
|
92
|
+
const onDelta = vi.fn();
|
|
93
|
+
const onComplete = vi.fn();
|
|
94
|
+
const onError = vi.fn();
|
|
95
|
+
await dispatcher.queryStream(
|
|
96
|
+
{ prompt: "hi", model: "anthropic/claude-sonnet-4-6" },
|
|
97
|
+
{ onDelta, onComplete, onError },
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
expect(onDelta).not.toHaveBeenCalled();
|
|
101
|
+
expect(onComplete).not.toHaveBeenCalled();
|
|
102
|
+
expect(onError).toHaveBeenCalledWith(serverError);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it("OpenAI query 는 reuse/reuseInput 을 provider 로 계속 전달한다", async () => {
|
|
106
|
+
const dispatcher = new QgridDispatcherClass();
|
|
107
|
+
const generate = vi.fn(async (_req: GenerateRequest) => providerResult({ model: "gpt-5.5" }));
|
|
108
|
+
dispatcher.openaiDispatcher = { generate } as never;
|
|
109
|
+
|
|
110
|
+
await dispatcher.query({
|
|
111
|
+
prompt: "next",
|
|
112
|
+
model: "openai/gpt-5.5",
|
|
113
|
+
system: "same-system",
|
|
114
|
+
runContext: {
|
|
115
|
+
threadCoord: {
|
|
116
|
+
workerId: 1,
|
|
117
|
+
threadId: "thread-1",
|
|
118
|
+
epoch: 0,
|
|
119
|
+
systemHash: "800ddd9ba811b821",
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
const req = generate.mock.calls[0]![0];
|
|
125
|
+
expect(req.reuse).toEqual({ workerId: 1, threadId: "thread-1", epoch: 0 });
|
|
126
|
+
expect(req.reuseInput).toEqual([{ type: "text", text: "next", text_elements: [] }]);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it("Anthropic query 는 reuse/reuseInput 을 provider 로 전달하지 않는다", async () => {
|
|
130
|
+
const dispatcher = new QgridDispatcherClass();
|
|
131
|
+
const generate = vi.fn(async (_req: GenerateRequest) =>
|
|
132
|
+
providerResult({ model: "claude-sonnet-4-6" }),
|
|
133
|
+
);
|
|
134
|
+
dispatcher.anthropicDispatcher = { generate } as never;
|
|
135
|
+
|
|
136
|
+
await dispatcher.query({
|
|
137
|
+
prompt: "next",
|
|
138
|
+
model: "anthropic/claude-sonnet-4-6",
|
|
139
|
+
system: "same-system",
|
|
140
|
+
runContext: {
|
|
141
|
+
threadCoord: {
|
|
142
|
+
workerId: 1,
|
|
143
|
+
threadId: "thread-1",
|
|
144
|
+
epoch: 0,
|
|
145
|
+
systemHash: "800ddd9ba811b821",
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
const req = generate.mock.calls[0]![0];
|
|
151
|
+
expect(req).not.toHaveProperty("reuse");
|
|
152
|
+
expect(req).not.toHaveProperty("reuseInput");
|
|
153
|
+
expect(req.coldInput).toEqual([{ type: "text", text: "next", text_elements: [] }]);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it("Anthropic queryStream 도 reuse/reuseInput 을 provider 로 전달하지 않고 delta/complete 를 보존한다", async () => {
|
|
157
|
+
const dispatcher = new QgridDispatcherClass();
|
|
158
|
+
const generateStream = vi.fn(async (_req, cb) => {
|
|
159
|
+
cb.onDelta("d");
|
|
160
|
+
cb.onComplete(providerResult({ model: "claude-sonnet-4-6" }));
|
|
161
|
+
});
|
|
162
|
+
dispatcher.anthropicDispatcher = { generateStream } as never;
|
|
163
|
+
|
|
164
|
+
const onDelta = vi.fn();
|
|
165
|
+
const onComplete = vi.fn();
|
|
166
|
+
await dispatcher.queryStream(
|
|
167
|
+
{
|
|
168
|
+
prompt: "next",
|
|
169
|
+
model: "anthropic/claude-sonnet-4-6",
|
|
170
|
+
system: "same-system",
|
|
171
|
+
runContext: {
|
|
172
|
+
threadCoord: {
|
|
173
|
+
workerId: 1,
|
|
174
|
+
threadId: "thread-1",
|
|
175
|
+
epoch: 0,
|
|
176
|
+
systemHash: "800ddd9ba811b821",
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
{ onDelta, onComplete, onError: vi.fn() },
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
const req = generateStream.mock.calls[0]![0];
|
|
184
|
+
expect(req).not.toHaveProperty("reuse");
|
|
185
|
+
expect(req).not.toHaveProperty("reuseInput");
|
|
186
|
+
expect(req.coldInput).toEqual([{ type: "text", text: "next", text_elements: [] }]);
|
|
187
|
+
expect(onDelta).toHaveBeenCalledWith("d");
|
|
188
|
+
expect(onComplete).toHaveBeenCalledWith(
|
|
189
|
+
expect.objectContaining({
|
|
190
|
+
text: "ok",
|
|
191
|
+
runContext: expect.objectContaining({
|
|
192
|
+
threadCoord: expect.objectContaining({ threadId: "sess-1" }),
|
|
193
|
+
}),
|
|
194
|
+
}),
|
|
195
|
+
);
|
|
196
|
+
});
|
|
197
|
+
|
|
10
198
|
it("jsonSchema 를 required + additionalProperties:false 로 strictify 한다", () => {
|
|
11
199
|
const schema = buildStrictOutputSchema({
|
|
12
200
|
jsonSchema: JSON.stringify({
|
|
@@ -33,11 +221,10 @@ describe("QgridDispatcherClass", () => {
|
|
|
33
221
|
|
|
34
222
|
expect(schema.required).toEqual(["contents"]);
|
|
35
223
|
expect(schema.additionalProperties).toBe(false);
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
).anyOf?.[0];
|
|
224
|
+
const contents = schema.properties?.contents as
|
|
225
|
+
| { anyOf?: Array<{ items?: { required?: string[]; additionalProperties?: boolean } }> }
|
|
226
|
+
| undefined;
|
|
227
|
+
const contentsArray = contents?.anyOf?.[0];
|
|
41
228
|
expect(contentsArray?.items?.required).toEqual(["text"]);
|
|
42
229
|
expect(contentsArray?.items?.additionalProperties).toBe(false);
|
|
43
230
|
});
|
|
@@ -102,7 +289,7 @@ describe("QgridDispatcherClass", () => {
|
|
|
102
289
|
);
|
|
103
290
|
dispatcher.anthropicDispatcher = { generate } as never;
|
|
104
291
|
|
|
105
|
-
const result = await dispatcher.query({ prompt: "hi", model: "claude-sonnet-4-6" });
|
|
292
|
+
const result = await dispatcher.query({ prompt: "hi", model: "anthropic/claude-sonnet-4-6" });
|
|
106
293
|
|
|
107
294
|
expect(result.costUsd).toBe(0.123456);
|
|
108
295
|
expect(result.usage.cache_creation_input_tokens).toBe(600);
|