@cartanova/qgrid-cli 2.3.5 → 2.3.6
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/oauth.js +15 -12
- package/bundle/dist/application/qgrid/qgrid-run-lifecycle.js +2 -1
- package/bundle/dist/application/qgrid/qgrid.dispatcher.js +2 -1
- package/bundle/dist/application/qgrid/qgrid.frame.js +23 -10
- package/bundle/dist/application/qgrid/qgrid.types.js +8 -2
- package/bundle/dist/application/qgrid/token-subscriber.js +16 -8
- package/bundle/dist/application/qgrid/token-trigger-setup.js +3 -2
- package/bundle/dist/application/request-log/request-log.model.js +12 -7
- package/bundle/dist/application/sonamu.generated.js +11 -3
- package/bundle/dist/application/sonamu.generated.sso.js +7 -2
- package/bundle/dist/application/token/token.model.js +10 -2
- package/bundle/dist/application/token/token.types.js +5 -3
- package/bundle/dist/i18n/sd.generated.js +4 -1
- package/bundle/dist/migrations/20260630223950_alter_tokens_add1_alter1.js +16 -0
- package/bundle/dist/migrations/20260701105327_alter_request_logs_add1_alter1.js +16 -0
- package/bundle/dist/migrations/20260701105328_alter_request_log_steps_add1_alter1.js +16 -0
- package/bundle/dist/sonamu.config.js +13 -6
- package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +99 -12
- package/bundle/dist/utils/providers/anthropic/anthropic-quota.js +31 -0
- package/bundle/dist/utils/providers/anthropic/claude-session.js +8 -3
- package/bundle/dist/utils/providers/common/ttft.js +25 -0
- package/bundle/dist/utils/providers/openai/codex-worker.js +35 -7
- package/bundle/dist/utils/providers/openai/openai-dispatcher.js +237 -39
- package/bundle/dist/utils/providers/openai/openai-quota.js +30 -0
- package/bundle/src/application/qgrid/oauth.ts +17 -7
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +96 -0
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.ts +1 -0
- package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +16 -0
- package/bundle/src/application/qgrid/qgrid.dispatcher.ts +1 -0
- package/bundle/src/application/qgrid/qgrid.frame.test.ts +128 -0
- package/bundle/src/application/qgrid/qgrid.frame.ts +41 -20
- package/bundle/src/application/qgrid/qgrid.types.ts +6 -0
- package/bundle/src/application/qgrid/token-subscriber.test.ts +89 -0
- package/bundle/src/application/qgrid/token-subscriber.ts +40 -11
- package/bundle/src/application/qgrid/token-trigger-setup.ts +2 -1
- package/bundle/src/application/qgrid/tool-emulation.test.ts +7 -3
- package/bundle/src/application/request-log/request-log.entity.json +3 -0
- package/bundle/src/application/request-log/request-log.model.test.ts +92 -0
- package/bundle/src/application/request-log/request-log.model.ts +20 -6
- package/bundle/src/application/request-log-step/request-log-step.entity.json +3 -0
- package/bundle/src/application/sonamu.generated.http +7 -2
- package/bundle/src/application/sonamu.generated.sso.ts +5 -0
- package/bundle/src/application/sonamu.generated.ts +11 -1
- package/bundle/src/application/token/token.entity.json +8 -2
- package/bundle/src/application/token/token.model.test.ts +69 -0
- package/bundle/src/application/token/token.model.ts +8 -1
- package/bundle/src/application/token/token.types.test.ts +34 -0
- package/bundle/src/application/token/token.types.ts +5 -0
- package/bundle/src/i18n/sd.generated.ts +3 -0
- package/bundle/src/migrations/20260630223950_alter_tokens_add1_alter1.ts +15 -0
- package/bundle/src/migrations/20260701105327_alter_request_logs_add1_alter1.ts +15 -0
- package/bundle/src/migrations/20260701105328_alter_request_log_steps_add1_alter1.ts +15 -0
- package/bundle/src/sonamu.config.ts +8 -1
- package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.test.ts +183 -15
- package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +142 -12
- package/bundle/src/utils/providers/anthropic/anthropic-quota.test.ts +89 -0
- package/bundle/src/utils/providers/anthropic/anthropic-quota.ts +27 -0
- package/bundle/src/utils/providers/anthropic/claude-session.ts +7 -2
- package/bundle/src/utils/providers/common/provider-dispatcher.ts +1 -0
- package/bundle/src/utils/providers/common/ttft.test.ts +37 -0
- package/bundle/src/utils/providers/common/ttft.ts +26 -0
- package/bundle/src/utils/providers/openai/codex-worker.test.ts +148 -0
- package/bundle/src/utils/providers/openai/codex-worker.ts +50 -8
- package/bundle/src/utils/providers/openai/openai-dispatcher.test.ts +378 -6
- package/bundle/src/utils/providers/openai/openai-dispatcher.ts +332 -37
- package/bundle/src/utils/providers/openai/openai-quota.test.ts +85 -0
- package/bundle/src/utils/providers/openai/openai-quota.ts +46 -0
- package/bundle/web-dist/client/assets/index-5WdFEqZT.css +1 -0
- package/bundle/web-dist/client/assets/{index-DeThumA3.js → index-jnUY7nJ-.js} +3 -3
- package/bundle/web-dist/client/assets/logs-B0pWpDrg.js +1 -0
- package/bundle/web-dist/client/assets/routes-7XhVuG7o.js +5 -0
- package/bundle/web-dist/client/assets/{sd.generated-7jzAQL2_.js → sd.generated-DXhjjL2f.js} +1 -1
- package/bundle/web-dist/client/assets/{services.generated-Bx1Eh7ot.js → services.generated-B7u0U1wC.js} +1 -1
- package/bundle/web-dist/client/assets/{show-C6OofoAL.js → show-CcjZ9nr7.js} +3 -3
- package/bundle/web-dist/client/assets/tokens-DlwAm0v4.js +1 -0
- package/bundle/web-dist/client/index.html +3 -3
- package/bundle/web-dist/server/assets/{lazyRouteComponent-BEaI4mOq.js → lazyRouteComponent-B0LkbiYf.js} +1 -2
- package/bundle/web-dist/server/assets/{logs-CHM0fhfO.js → logs-dLx6gMXT.js} +17 -5
- package/bundle/web-dist/server/assets/{routes-C9xFMJ_r.js → routes-DD3Hb9xO.js} +201 -13
- package/bundle/web-dist/server/assets/{sd.generated-BeUHLWKH.js → sd.generated-DdfpD_iN.js} +131 -1
- package/bundle/web-dist/server/assets/{services.generated-C39hdSv0.js → services.generated-D3ZCvIkt.js} +5 -4
- package/bundle/web-dist/server/assets/{show-BZWqH09U.js → show-BQjeyv6A.js} +76 -25
- package/bundle/web-dist/server/assets/{tokens-IPwv3pNB.js → tokens-CSOsBpP7.js} +4 -3
- package/bundle/web-dist/server/entry-server.generated.js +6 -7
- package/dist/cli.js +67 -15
- package/package.json +1 -1
- package/bundle/web-dist/client/assets/index-B5DSo5uH.css +0 -1
- package/bundle/web-dist/client/assets/logs-CtmOVH58.js +0 -1
- package/bundle/web-dist/client/assets/routes-Cfoe9J0I.js +0 -5
- package/bundle/web-dist/client/assets/tokens-BAZq8sTo.js +0 -1
- package/bundle/web-dist/server/assets/shim-B9ZrFt3Z.js +0 -129
- /package/bundle/web-dist/server/assets/{cost-DzjfVtUr.js → cost-CSH_t17I.js} +0 -0
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import "../../../_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { QuotaThresholdExceededError } from "../../../application/qgrid/qgrid.types.js";
|
|
2
3
|
import { TokenModel } from "../../../application/token/token.model.js";
|
|
3
4
|
import { CodexAppServerWorker } from "./codex-worker.js";
|
|
5
|
+
import { readOpenAIQuotaUsage } from "./openai-quota.js";
|
|
4
6
|
import { handleChatgptAuthTokensRefresh } from "./openai-refresh.js";
|
|
5
7
|
import { getLogger } from "@logtape/logtape";
|
|
6
8
|
//#region src/utils/providers/openai/openai-dispatcher.ts
|
|
@@ -27,16 +29,23 @@ function makeWorkerId(tokenId, workerIndex) {
|
|
|
27
29
|
function sleep(ms) {
|
|
28
30
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
29
31
|
}
|
|
32
|
+
function quotaThresholdExceededMessage(provider, tokens) {
|
|
33
|
+
const details = tokens.map((token) => `${token.tokenName} (threshold ${token.threshold}%)`).join(", ");
|
|
34
|
+
return details.length > 0 ? `All ${provider} tokens exceeded quota threshold: ${details}` : `All ${provider} tokens exceeded quota threshold`;
|
|
35
|
+
}
|
|
30
36
|
var OpenAIDispatcher = class OpenAIDispatcher {
|
|
31
37
|
workerPool = /* @__PURE__ */ new Map();
|
|
38
|
+
tokenMetadata = /* @__PURE__ */ new Map();
|
|
32
39
|
rrCursor = 0;
|
|
33
40
|
queue = [];
|
|
41
|
+
draining = false;
|
|
42
|
+
drainAgain = false;
|
|
34
43
|
async start() {
|
|
35
44
|
const { rows } = await TokenModel.findMany("A");
|
|
36
45
|
const openaiTokens = rows.filter((t) => t.provider === "openai");
|
|
37
46
|
logger.info(`starting ${openaiTokens.length} openai tokens (${WORKERS_PER_TOKEN} workers each)`);
|
|
38
47
|
await Promise.allSettled(openaiTokens.map(async (t) => {
|
|
39
|
-
await this.spawnWorkers(t.id, t.name, t.credentials);
|
|
48
|
+
await this.spawnWorkers(t.id, t.name, t.credentials, t.quota_threshold);
|
|
40
49
|
if (!t.active) this.onTokenDeactivated(t.id);
|
|
41
50
|
}));
|
|
42
51
|
}
|
|
@@ -45,15 +54,20 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
45
54
|
const kills = [...this.workerPool.values()].flat().map((w) => w.kill());
|
|
46
55
|
await Promise.allSettled(kills);
|
|
47
56
|
this.workerPool.clear();
|
|
57
|
+
this.tokenMetadata.clear();
|
|
58
|
+
this.rateLimitsCache.clear();
|
|
48
59
|
}
|
|
49
|
-
async onTokenAdded(id, name, credentials) {
|
|
60
|
+
async onTokenAdded(id, name, credentials, quotaThreshold) {
|
|
61
|
+
this.setTokenMetadata(id, name, quotaThreshold);
|
|
50
62
|
if (this.workerPool.has(id)) return;
|
|
51
|
-
await this.spawnWorkers(id, name, credentials);
|
|
63
|
+
await this.spawnWorkers(id, name, credentials, quotaThreshold);
|
|
52
64
|
}
|
|
53
65
|
async onTokenRemoved(id) {
|
|
54
66
|
const workers = this.workerPool.get(id) ?? [];
|
|
55
67
|
const tokenName = workers[0]?.tokenName;
|
|
56
68
|
this.workerPool.delete(id);
|
|
69
|
+
this.tokenMetadata.delete(id);
|
|
70
|
+
this.rateLimitsCache.delete(id);
|
|
57
71
|
await Promise.allSettled(workers.map((w) => w.kill()));
|
|
58
72
|
if (this.getAllReadyActiveWorkers().length === 0) this.rejectAllQueued("NO_OPENAI_WORKERS");
|
|
59
73
|
if (workers.length > 0) {
|
|
@@ -61,21 +75,25 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
61
75
|
logger.info(`workers removed: ${label} (${workers.length})`);
|
|
62
76
|
}
|
|
63
77
|
}
|
|
64
|
-
async onTokenUpdated(id, name, credentials) {
|
|
78
|
+
async onTokenUpdated(id, name, credentials, quotaThreshold) {
|
|
65
79
|
const existing = this.workerPool.get(id) ?? [];
|
|
80
|
+
const renamed = existing.some((w) => w.tokenName !== name);
|
|
81
|
+
this.setTokenMetadata(id, name, quotaThreshold);
|
|
82
|
+
if (renamed) this.rateLimitsCache.delete(id);
|
|
66
83
|
if (existing.length === 0) {
|
|
67
|
-
await this.spawnWorkers(id, name, credentials);
|
|
84
|
+
await this.spawnWorkers(id, name, credentials, quotaThreshold);
|
|
68
85
|
return;
|
|
69
86
|
}
|
|
70
87
|
if (existing.every((w) => w.canReuseForToken(name, credentials))) {
|
|
71
88
|
existing.forEach((w) => w.updateTokenState(name, credentials));
|
|
72
89
|
logger.info(`workers updated in-place: ${name}`);
|
|
73
|
-
this.
|
|
90
|
+
this.requestDrainQueue();
|
|
74
91
|
return;
|
|
75
92
|
}
|
|
76
93
|
this.workerPool.delete(id);
|
|
94
|
+
this.rateLimitsCache.delete(id);
|
|
77
95
|
await Promise.allSettled(existing.map((w) => w.kill()));
|
|
78
|
-
await this.spawnWorkers(id, name, credentials);
|
|
96
|
+
await this.spawnWorkers(id, name, credentials, quotaThreshold);
|
|
79
97
|
}
|
|
80
98
|
onTokenDeactivated(id) {
|
|
81
99
|
const workers = this.workerPool.get(id) ?? [];
|
|
@@ -93,17 +111,27 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
93
111
|
workers.forEach((w) => {
|
|
94
112
|
w.active = true;
|
|
95
113
|
});
|
|
96
|
-
this.
|
|
114
|
+
this.requestDrainQueue();
|
|
97
115
|
const label = tokenName ?? `token ${id}`;
|
|
98
116
|
logger.info(`workers activated: ${label}`);
|
|
99
117
|
}
|
|
118
|
+
async replaceTokens(rows) {
|
|
119
|
+
const next = new Set(rows.map((r) => r.id));
|
|
120
|
+
for (const id of Array.from(this.workerPool.keys())) if (!next.has(id)) await this.onTokenRemoved(id);
|
|
121
|
+
for (const row of rows) {
|
|
122
|
+
if (this.workerPool.has(row.id)) await this.onTokenUpdated(row.id, row.name, row.credentials, row.quotaThreshold);
|
|
123
|
+
else await this.onTokenAdded(row.id, row.name, row.credentials, row.quotaThreshold);
|
|
124
|
+
this.onTokenActivated(row.id);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
100
127
|
async generate(req) {
|
|
101
|
-
const
|
|
128
|
+
const excludedTokenIds = /* @__PURE__ */ new Set();
|
|
129
|
+
const reuseWorker = await this.acquireReuseWorker(req, excludedTokenIds);
|
|
102
130
|
if (reuseWorker) {
|
|
103
131
|
logger.info(`↻ ${reuseWorker.tokenName}[${reuseWorker.tokenId}] (reuse thread, ${req.model})`);
|
|
104
132
|
return this.executeAndRelease(reuseWorker, (w) => this.executeTurn(w, req, req.reuse.threadId));
|
|
105
133
|
}
|
|
106
|
-
const worker = this.acquireIdleWorker();
|
|
134
|
+
const worker = await this.acquireIdleWorker(excludedTokenIds);
|
|
107
135
|
if (worker) {
|
|
108
136
|
logger.info(`→ ${worker.tokenName}[${worker.tokenId}] (model: ${req.model})`);
|
|
109
137
|
return this.executeAndRelease(worker, (w) => this.executeTurn(w, req));
|
|
@@ -111,15 +139,16 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
111
139
|
return this.enqueue((w) => {
|
|
112
140
|
logger.info(`→ ${w.tokenName}[${w.tokenId}] (model: ${req.model}, queued)`);
|
|
113
141
|
return this.executeTurn(w, req);
|
|
114
|
-
});
|
|
142
|
+
}, excludedTokenIds);
|
|
115
143
|
}
|
|
116
144
|
async generateStream(req, cb) {
|
|
117
|
-
const
|
|
145
|
+
const excludedTokenIds = /* @__PURE__ */ new Set();
|
|
146
|
+
const reuseWorker = await this.acquireReuseWorker(req, excludedTokenIds);
|
|
118
147
|
if (reuseWorker) {
|
|
119
148
|
logger.info(`↻ ${reuseWorker.tokenName}[${reuseWorker.tokenId}] (reuse thread, [stream])`);
|
|
120
149
|
return this.executeAndRelease(reuseWorker, (w) => this.executeStreamTurn(w, req, cb, req.reuse.threadId));
|
|
121
150
|
}
|
|
122
|
-
const worker = this.acquireIdleWorker();
|
|
151
|
+
const worker = await this.acquireIdleWorker(excludedTokenIds);
|
|
123
152
|
if (worker) {
|
|
124
153
|
logger.info(`→ ${worker.tokenName}[${worker.tokenId}] (model: ${req.model}, [stream])`);
|
|
125
154
|
return this.executeAndRelease(worker, (w) => this.executeStreamTurn(w, req, cb));
|
|
@@ -127,15 +156,16 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
127
156
|
return this.enqueue((w) => {
|
|
128
157
|
logger.info(`→ ${w.tokenName}[${w.tokenId}] (model: ${req.model}, [stream], queued)`);
|
|
129
158
|
return this.executeStreamTurn(w, req, cb);
|
|
130
|
-
});
|
|
159
|
+
}, excludedTokenIds);
|
|
131
160
|
}
|
|
132
|
-
async acquireReuseWorker(req) {
|
|
161
|
+
async acquireReuseWorker(req, excludedTokenIds = /* @__PURE__ */ new Set()) {
|
|
133
162
|
if (!THREAD_REUSE_ENABLED || !req.reuse) return null;
|
|
134
163
|
const { workerId, threadId, epoch } = req.reuse;
|
|
135
164
|
const worker = this.findWorkerById(workerId);
|
|
136
165
|
if (!worker || !worker.isReady || !worker.active) return null;
|
|
137
166
|
if (worker.epoch !== epoch) return null;
|
|
138
167
|
if (!worker.hasThread(threadId)) return null;
|
|
168
|
+
if (!await this.isTokenQuotaEligible(worker.tokenId, worker.tokenName, excludedTokenIds)) return null;
|
|
139
169
|
const deadline = Date.now() + REUSE_WORKER_WAIT_MS;
|
|
140
170
|
for (;;) {
|
|
141
171
|
if (worker.epoch !== epoch || !worker.hasThread(threadId)) return null;
|
|
@@ -152,8 +182,11 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
152
182
|
const allWorkers = [...this.workerPool.values()].flat().filter((w) => w.isReady);
|
|
153
183
|
await Promise.allSettled(allWorkers.map((w) => w.interruptTurn(threadId, turnId)));
|
|
154
184
|
}
|
|
155
|
-
acquireIdleWorker() {
|
|
156
|
-
const
|
|
185
|
+
async acquireIdleWorker(excludedTokenIds = /* @__PURE__ */ new Set()) {
|
|
186
|
+
const eligibility = await this.resolveTokenEligibility(excludedTokenIds);
|
|
187
|
+
if (eligibility.readyActiveTokenIds.size === 0) return null;
|
|
188
|
+
if (eligibility.eligibleTokenIds.size === 0) this.throwQuotaThresholdExceeded(eligibility);
|
|
189
|
+
const allWorkers = this.getAllReadyActiveWorkers().filter((w) => eligibility.eligibleTokenIds.has(w.tokenId));
|
|
157
190
|
if (allWorkers.length === 0) return null;
|
|
158
191
|
for (let i = 0; i < allWorkers.length; i++) {
|
|
159
192
|
const w = allWorkers[(this.rrCursor + i) % allWorkers.length];
|
|
@@ -167,9 +200,11 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
167
200
|
getAllReadyActiveWorkers() {
|
|
168
201
|
return [...this.workerPool.values()].flat().filter((w) => w.isReady && w.active);
|
|
169
202
|
}
|
|
170
|
-
enqueue(execute) {
|
|
171
|
-
|
|
172
|
-
if (
|
|
203
|
+
async enqueue(execute, excludedTokenIds = /* @__PURE__ */ new Set()) {
|
|
204
|
+
const eligibility = await this.resolveTokenEligibility(excludedTokenIds);
|
|
205
|
+
if (eligibility.readyActiveTokenIds.size === 0) throw new Error("NO_OPENAI_WORKERS");
|
|
206
|
+
if (eligibility.eligibleTokenIds.size === 0) this.throwQuotaThresholdExceeded(eligibility);
|
|
207
|
+
if (this.queue.length >= MAX_QUEUE_SIZE) throw new Error("SERVER_BUSY");
|
|
173
208
|
return new Promise((resolve, reject) => {
|
|
174
209
|
const item = {
|
|
175
210
|
resolve: (worker) => {
|
|
@@ -185,7 +220,8 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
185
220
|
timer: setTimeout(() => {
|
|
186
221
|
this.removeFromQueue(item);
|
|
187
222
|
reject(/* @__PURE__ */ new Error("SERVER_BUSY"));
|
|
188
|
-
}, QUEUE_TIMEOUT_MS)
|
|
223
|
+
}, QUEUE_TIMEOUT_MS),
|
|
224
|
+
excludedTokenIds: new Set(excludedTokenIds)
|
|
189
225
|
};
|
|
190
226
|
this.queue.push(item);
|
|
191
227
|
});
|
|
@@ -205,15 +241,46 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
205
241
|
});
|
|
206
242
|
this.queue = [];
|
|
207
243
|
}
|
|
208
|
-
drainQueue(releasedWorker) {
|
|
209
|
-
if (
|
|
244
|
+
async drainQueue(releasedWorker) {
|
|
245
|
+
if (this.draining) {
|
|
246
|
+
this.drainAgain = true;
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
this.draining = true;
|
|
250
|
+
let worker = releasedWorker;
|
|
251
|
+
try {
|
|
252
|
+
do {
|
|
253
|
+
this.drainAgain = false;
|
|
254
|
+
await this.drainQueueOnce(worker);
|
|
255
|
+
worker = void 0;
|
|
256
|
+
} while (this.drainAgain);
|
|
257
|
+
} catch (e) {
|
|
258
|
+
logger.warn(`drainQueue failed: ${e.message}`);
|
|
259
|
+
} finally {
|
|
260
|
+
this.draining = false;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
async drainQueueOnce(releasedWorker) {
|
|
264
|
+
if (releasedWorker && this.queue.length > 0 && releasedWorker.isReady && releasedWorker.active && await this.isWorkerEligibleForQueueItem(releasedWorker, this.queue[0]) && releasedWorker.tryAcquireTurn()) {
|
|
210
265
|
this.queue.shift().resolve(releasedWorker);
|
|
211
266
|
return;
|
|
212
267
|
}
|
|
213
268
|
while (this.queue.length > 0) {
|
|
214
|
-
const
|
|
269
|
+
const next = this.queue[0];
|
|
270
|
+
let worker;
|
|
271
|
+
try {
|
|
272
|
+
worker = await this.acquireIdleWorker(next.excludedTokenIds);
|
|
273
|
+
} catch (e) {
|
|
274
|
+
if (e instanceof QuotaThresholdExceededError) {
|
|
275
|
+
this.queue.shift();
|
|
276
|
+
next.reject(e);
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
throw e;
|
|
280
|
+
}
|
|
215
281
|
if (!worker) break;
|
|
216
|
-
this.queue.shift()
|
|
282
|
+
this.queue.shift();
|
|
283
|
+
next.resolve(worker);
|
|
217
284
|
}
|
|
218
285
|
}
|
|
219
286
|
async executeAndRelease(worker, execute) {
|
|
@@ -221,7 +288,7 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
221
288
|
return await execute(worker);
|
|
222
289
|
} finally {
|
|
223
290
|
worker.releaseTurn();
|
|
224
|
-
this.
|
|
291
|
+
this.requestDrainQueue(worker);
|
|
225
292
|
}
|
|
226
293
|
}
|
|
227
294
|
buildTurnRequest(req, reuseThreadId) {
|
|
@@ -246,6 +313,7 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
246
313
|
tokenName: worker.tokenName,
|
|
247
314
|
usage: result.usage,
|
|
248
315
|
durationMs: result.durationMs,
|
|
316
|
+
ttftMs: result.ttftMs,
|
|
249
317
|
model: result.model,
|
|
250
318
|
threadCoord: {
|
|
251
319
|
workerId: makeWorkerId(worker.tokenId, worker.workerIndex),
|
|
@@ -277,7 +345,8 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
277
345
|
};
|
|
278
346
|
await worker.executeTurnStream(turnReq, wrappedCb, reuseThreadId);
|
|
279
347
|
}
|
|
280
|
-
async spawnWorkers(tokenId, tokenName, credentials) {
|
|
348
|
+
async spawnWorkers(tokenId, tokenName, credentials, quotaThreshold) {
|
|
349
|
+
this.setTokenMetadata(tokenId, tokenName, quotaThreshold);
|
|
281
350
|
const workers = [];
|
|
282
351
|
for (let i = 0; i < WORKERS_PER_TOKEN; i++) {
|
|
283
352
|
if (i > 0) await sleep(SPAWN_INTERVAL_MS);
|
|
@@ -295,7 +364,7 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
295
364
|
planType: credentials.planType,
|
|
296
365
|
workerIndex
|
|
297
366
|
});
|
|
298
|
-
worker.onReady = () => this.
|
|
367
|
+
worker.onReady = () => this.requestDrainQueue();
|
|
299
368
|
worker.setServerRequestHandler(async (method) => {
|
|
300
369
|
if (method === "account/chatgptAuthTokens/refresh") return handleChatgptAuthTokensRefresh(tokenId);
|
|
301
370
|
throw new Error(`unhandled server-request: ${method}`);
|
|
@@ -312,19 +381,148 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
312
381
|
}
|
|
313
382
|
rateLimitsCache = /* @__PURE__ */ new Map();
|
|
314
383
|
static RATE_LIMITS_CACHE_TTL = 6e4;
|
|
315
|
-
async
|
|
316
|
-
const
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
const allWorkers = [...this.workerPool.values()].flat().filter((w) => w.isReady);
|
|
320
|
-
const worker = tokenName ? allWorkers.find((w) => w.tokenName === tokenName) : allWorkers[0];
|
|
384
|
+
async getRateLimitsByTokenId(tokenId) {
|
|
385
|
+
const cached = this.rateLimitsCache.get(tokenId);
|
|
386
|
+
if (cached && Date.now() - cached.cachedAt < OpenAIDispatcher.RATE_LIMITS_CACHE_TTL) return cached;
|
|
387
|
+
const worker = (this.workerPool.get(tokenId) ?? []).find((w) => w.isReady);
|
|
321
388
|
if (!worker) throw new Error("no ready openai workers");
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
data,
|
|
389
|
+
const entry = {
|
|
390
|
+
data: await worker.getRateLimits(),
|
|
325
391
|
cachedAt: Date.now()
|
|
392
|
+
};
|
|
393
|
+
this.rateLimitsCache.set(tokenId, entry);
|
|
394
|
+
return entry;
|
|
395
|
+
}
|
|
396
|
+
requestDrainQueue(releasedWorker) {
|
|
397
|
+
this.drainQueue(releasedWorker).catch((e) => logger.warn(`drainQueue failed: ${e.message}`));
|
|
398
|
+
}
|
|
399
|
+
setTokenMetadata(id, name, quotaThreshold) {
|
|
400
|
+
this.tokenMetadata.set(id, {
|
|
401
|
+
name,
|
|
402
|
+
quotaThreshold
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
getQuotaThreshold(tokenId) {
|
|
406
|
+
return this.tokenMetadata.get(tokenId)?.quotaThreshold;
|
|
407
|
+
}
|
|
408
|
+
hasQuotaThreshold(tokenId) {
|
|
409
|
+
const threshold = this.getQuotaThreshold(tokenId);
|
|
410
|
+
return threshold !== void 0 && threshold !== null;
|
|
411
|
+
}
|
|
412
|
+
async resolveTokenEligibility(excludedTokenIds) {
|
|
413
|
+
const workers = this.getAllReadyActiveWorkers();
|
|
414
|
+
const byToken = /* @__PURE__ */ new Map();
|
|
415
|
+
for (const worker of workers) if (!byToken.has(worker.tokenId)) byToken.set(worker.tokenId, worker.tokenName);
|
|
416
|
+
const readyActiveTokenIds = new Set(byToken.keys());
|
|
417
|
+
const eligibleTokenIds = /* @__PURE__ */ new Set();
|
|
418
|
+
const overThresholdTokens = [];
|
|
419
|
+
let thresholdedTokenCount = 0;
|
|
420
|
+
const entries = Array.from(byToken.entries());
|
|
421
|
+
(await Promise.allSettled(entries.map(async ([tokenId, tokenName]) => {
|
|
422
|
+
if (excludedTokenIds.has(tokenId)) {
|
|
423
|
+
thresholdedTokenCount++;
|
|
424
|
+
return {
|
|
425
|
+
tokenId,
|
|
426
|
+
tokenName,
|
|
427
|
+
eligible: false
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
if (!this.hasQuotaThreshold(tokenId)) return {
|
|
431
|
+
tokenId,
|
|
432
|
+
tokenName,
|
|
433
|
+
eligible: true
|
|
434
|
+
};
|
|
435
|
+
thresholdedTokenCount++;
|
|
436
|
+
return {
|
|
437
|
+
tokenId,
|
|
438
|
+
tokenName,
|
|
439
|
+
eligible: await this.isTokenQuotaEligible(tokenId, tokenName)
|
|
440
|
+
};
|
|
441
|
+
}))).forEach((check, index) => {
|
|
442
|
+
if (check.status === "fulfilled") {
|
|
443
|
+
if (check.value.eligible) eligibleTokenIds.add(check.value.tokenId);
|
|
444
|
+
else {
|
|
445
|
+
const threshold = this.getQuotaThreshold(check.value.tokenId);
|
|
446
|
+
if (threshold !== void 0 && threshold !== null) overThresholdTokens.push({
|
|
447
|
+
tokenName: check.value.tokenName,
|
|
448
|
+
threshold
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
const entry = entries[index];
|
|
454
|
+
if (entry) {
|
|
455
|
+
const [tokenId, tokenName] = entry;
|
|
456
|
+
this.logQuotaLookupFailOpen(tokenId, tokenName, String(check.reason));
|
|
457
|
+
eligibleTokenIds.add(tokenId);
|
|
458
|
+
}
|
|
459
|
+
});
|
|
460
|
+
return {
|
|
461
|
+
readyActiveTokenIds,
|
|
462
|
+
eligibleTokenIds,
|
|
463
|
+
overThresholdTokens,
|
|
464
|
+
thresholdedTokenCount
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
async isWorkerEligibleForQueueItem(worker, item) {
|
|
468
|
+
if (item.excludedTokenIds.has(worker.tokenId)) return false;
|
|
469
|
+
return this.isTokenQuotaEligible(worker.tokenId, worker.tokenName);
|
|
470
|
+
}
|
|
471
|
+
async isTokenQuotaEligible(tokenId, tokenName, excludedTokenIds) {
|
|
472
|
+
const threshold = this.getQuotaThreshold(tokenId);
|
|
473
|
+
if (threshold === void 0 || threshold === null) return true;
|
|
474
|
+
let result;
|
|
475
|
+
try {
|
|
476
|
+
result = await readOpenAIQuotaUsage(() => this.getRateLimitsByTokenId(tokenId));
|
|
477
|
+
} catch (e) {
|
|
478
|
+
this.logQuotaLookupFailOpen(tokenId, tokenName, e.message);
|
|
479
|
+
return true;
|
|
480
|
+
}
|
|
481
|
+
if (result.kind === "lookup_failed") {
|
|
482
|
+
this.logQuotaLookupFailOpen(tokenId, tokenName, result.reason);
|
|
483
|
+
return true;
|
|
484
|
+
}
|
|
485
|
+
if (result.utilizationPct >= threshold) {
|
|
486
|
+
this.logQuotaOverThreshold(tokenId, tokenName, threshold, result);
|
|
487
|
+
excludedTokenIds?.add(tokenId);
|
|
488
|
+
return false;
|
|
489
|
+
}
|
|
490
|
+
return true;
|
|
491
|
+
}
|
|
492
|
+
logQuotaOverThreshold(tokenId, tokenName, threshold, result) {
|
|
493
|
+
logger.info("quota_threshold gate: over_threshold", {
|
|
494
|
+
tokenId,
|
|
495
|
+
tokenName,
|
|
496
|
+
provider: "openai",
|
|
497
|
+
threshold,
|
|
498
|
+
cachedUtilization: result.utilizationPct,
|
|
499
|
+
cacheAge: result.cacheAgeMs,
|
|
500
|
+
windowDurationMins: result.windowDurationMins,
|
|
501
|
+
resetsAt: result.resetsAt,
|
|
502
|
+
limitId: result.limitId,
|
|
503
|
+
reason: "over_threshold"
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
logQuotaLookupFailOpen(tokenId, tokenName, reason) {
|
|
507
|
+
const threshold = this.getQuotaThreshold(tokenId);
|
|
508
|
+
logger.warn("quota_threshold gate: lookup_fail_open", {
|
|
509
|
+
tokenId,
|
|
510
|
+
tokenName,
|
|
511
|
+
provider: "openai",
|
|
512
|
+
threshold,
|
|
513
|
+
reason: "lookup_fail_open",
|
|
514
|
+
lookupReason: reason
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
throwQuotaThresholdExceeded(eligibility) {
|
|
518
|
+
logger.warn("quota_threshold gate: all_exceeded", {
|
|
519
|
+
provider: "openai",
|
|
520
|
+
tokenCount: eligibility.readyActiveTokenIds.size,
|
|
521
|
+
thresholdedTokenCount: eligibility.thresholdedTokenCount,
|
|
522
|
+
overThresholdTokens: eligibility.overThresholdTokens,
|
|
523
|
+
reason: "all_exceeded"
|
|
326
524
|
});
|
|
327
|
-
|
|
525
|
+
throw new QuotaThresholdExceededError(quotaThresholdExceededMessage("openai", eligibility.overThresholdTokens));
|
|
328
526
|
}
|
|
329
527
|
pendingLogin = null;
|
|
330
528
|
async startBrowserLogin(name) {
|
|
@@ -383,4 +581,4 @@ var OpenAIDispatcher = class OpenAIDispatcher {
|
|
|
383
581
|
//#endregion
|
|
384
582
|
export { OpenAIDispatcher };
|
|
385
583
|
|
|
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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
|
|
584
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlbmFpLWRpc3BhdGNoZXIuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3Byb3ZpZGVycy9vcGVuYWkvb3BlbmFpLWRpc3BhdGNoZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBPcGVuQUlEaXNwYXRjaGVyIOKAlCBjb2RleCBhcHAtc2VydmVyIHdvcmtlciBwb29sICsg7Yag7YGwIOudvOyasO2MhS5cbiAqXG4gKiAtIO2GoO2BsOuLuSBOIHdvcmtlciAoQ29kZXhBcHBTZXJ2ZXJXb3JrZXIpLCDquLDrs7ggM1xuICogLSBpZGxlIHdvcmtlciByb3VuZC1yb2JpbiDshKDtg50gKyDtgZAg64yA6riwICjsoITrtoAgYnVzeSDsi5wpXG4gKiAtIFRva2VuU3Vic2NyaWJlciDsnbTrsqTtirjroZwgd29ya2VyIHBvb2wg64+Z6riw7ZmUXG4gKiAtIGJhY2twcmVzc3VyZTog7YGQIGZ1bGwg65iQ64qUIHRpbWVvdXQg7IucIFNFUlZFUl9CVVNZXG4gKi9cbmltcG9ydCB7IGdldExvZ2dlciB9IGZyb20gXCJAbG9ndGFwZS9sb2d0YXBlXCI7XG5cbmltcG9ydCB7IFF1b3RhVGhyZXNob2xkRXhjZWVkZWRFcnJvciB9IGZyb20gXCIuLi8uLi8uLi9hcHBsaWNhdGlvbi9xZ3JpZC9xZ3JpZC50eXBlc1wiO1xuaW1wb3J0IHsgVG9rZW5Nb2RlbCB9IGZyb20gXCIuLi8uLi8uLi9hcHBsaWNhdGlvbi90b2tlbi90b2tlbi5tb2RlbFwiO1xuaW1wb3J0IHsgdHlwZSBPcGVuQUlDcmVkZW50aWFscyB9IGZyb20gXCIuLi8uLi8uLi9hcHBsaWNhdGlvbi90b2tlbi90b2tlbi50eXBlc1wiO1xuaW1wb3J0IHsgdHlwZSBHZXRBY2NvdW50UmF0ZUxpbWl0c1Jlc3BvbnNlIH0gZnJvbSBcIi4uLy4uLy4uL2NvZGV4LXByb3RvY29sL3YyL0dldEFjY291bnRSYXRlTGltaXRzUmVzcG9uc2VcIjtcbmltcG9ydCB7XG4gIHR5cGUgR2VuZXJhdGVSZXF1ZXN0LFxuICB0eXBlIEdlbmVyYXRlUmVzdWx0LFxuICB0eXBlIEdlbmVyYXRlU3RyZWFtQ2FsbGJhY2tzLFxuICB0eXBlIFByb3ZpZGVyRGlzcGF0Y2hlcixcbn0gZnJvbSBcIi4uL2NvbW1vbi9wcm92aWRlci1kaXNwYXRjaGVyXCI7XG5pbXBvcnQgeyBDb2RleEFwcFNlcnZlcldvcmtlciwgdHlwZSBTdHJlYW1DYWxsYmFja3MsIHR5cGUgVHVyblJlcXVlc3QgfSBmcm9tIFwiLi9jb2RleC13b3JrZXJcIjtcbmltcG9ydCB7XG4gIHJlYWRPcGVuQUlRdW90YVVzYWdlLFxuICB0eXBlIE9wZW5BSVF1b3RhVXNhZ2VSZXN1bHQsXG4gIHR5cGUgT3BlbkFJUmF0ZUxpbWl0c1dpdGhNZXRhLFxufSBmcm9tIFwiLi9vcGVuYWktcXVvdGFcIjtcbmltcG9ydCB7IGhhbmRsZUNoYXRncHRBdXRoVG9rZW5zUmVmcmVzaCB9IGZyb20gXCIuL29wZW5haS1yZWZyZXNoXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGdldExvZ2dlcihbXCJxZ3JpZFwiLCBcIm9wZW5haS1kaXNwYXRjaGVyXCJdKTtcblxuY29uc3QgREVGQVVMVF9FRkZPUlQgPSBcImxvd1wiO1xuY29uc3QgTUFYX1dPUktFUlNfUEVSX1RPS0VOID0gNTtcbmNvbnN0IFdPUktFUlNfUEVSX1RPS0VOID0gTWF0aC5taW4oXG4gIE51bWJlcihwcm9jZXNzLmVudi5RR1JJRF9XT1JLRVJTX1BFUl9UT0tFTiA/PyAzKSxcbiAgTUFYX1dPUktFUlNfUEVSX1RPS0VOLFxuKTtcbmNvbnN0IFFVRVVFX1RJTUVPVVRfTVMgPSA2MF8wMDA7XG5jb25zdCBNQVhfUVVFVUVfU0laRSA9IDUwO1xuY29uc3QgU1BBV05fSU5URVJWQUxfTVMgPSA1MDA7XG5cbi8vIHRocmVhZCDsnqzsgqzsmqkocHJvbXB0IGNhY2hlIOqzoOyglSkuIOuBhOuptCDquLDsobQgXCLrp6QgdHVybiDsg4ggdGhyZWFkICsgaGlzdG9yeSBpbmplY3RcIiDrj5nsnpEuXG5jb25zdCBUSFJFQURfUkVVU0VfRU5BQkxFRCA9IHByb2Nlc3MuZW52LlFHUklEX09QRU5BSV9USFJFQURfUkVVU0UgIT09IFwiZmFsc2VcIjtcbi8vIOyijO2RnCB3b3JrZXIg6rCAIGJ1c3kg7J28IOuVjCBmcmVlIOulvCDquLDri6TrpqzripQg7LWc64yAIOyLnOqwhC4g7LSI6rO8IOyLnCDsg4ggdGhyZWFkIOuhnCDtj7TrsLEuXG5jb25zdCBSRVVTRV9XT1JLRVJfV0FJVF9NUyA9IDVfMDAwO1xuY29uc3QgUkVVU0VfV09SS0VSX1BPTExfTVMgPSA1MDtcblxuLy8gd29ya2VySWQg7ZWp7ISxOiB0b2tlbklkIOyZgCB3b3JrZXJJbmRleCgwLi40KSDrpbwg7ZWY64KY7J2YIOyViOyglSDsiKvsnpDroZwg7J247L2U65SpLlxuZnVuY3Rpb24gbWFrZVdvcmtlcklkKHRva2VuSWQ6IG51bWJlciwgd29ya2VySW5kZXg6IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiB0b2tlbklkICogMTAgKyB3b3JrZXJJbmRleDtcbn1cblxuZnVuY3Rpb24gc2xlZXAobXM6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgbXMpKTtcbn1cblxuZnVuY3Rpb24gcXVvdGFUaHJlc2hvbGRFeGNlZWRlZE1lc3NhZ2UoXG4gIHByb3ZpZGVyOiBzdHJpbmcsXG4gIHRva2VuczogQXJyYXk8eyB0b2tlbk5hbWU6IHN0cmluZzsgdGhyZXNob2xkOiBudW1iZXIgfT4sXG4pOiBzdHJpbmcge1xuICBjb25zdCBkZXRhaWxzID0gdG9rZW5zXG4gICAgLm1hcCgodG9rZW4pID0+IGAke3Rva2VuLnRva2VuTmFtZX0gKHRocmVzaG9sZCAke3Rva2VuLnRocmVzaG9sZH0lKWApXG4gICAgLmpvaW4oXCIsIFwiKTtcbiAgcmV0dXJuIGRldGFpbHMubGVuZ3RoID4gMFxuICAgID8gYEFsbCAke3Byb3ZpZGVyfSB0b2tlbnMgZXhjZWVkZWQgcXVvdGEgdGhyZXNob2xkOiAke2RldGFpbHN9YFxuICAgIDogYEFsbCAke3Byb3ZpZGVyfSB0b2tlbnMgZXhjZWVkZWQgcXVvdGEgdGhyZXNob2xkYDtcbn1cblxudHlwZSBRdWV1ZUl0ZW0gPSB7XG4gIHJlc29sdmU6ICh3b3JrZXI6IENvZGV4QXBwU2VydmVyV29ya2VyKSA9PiB2b2lkO1xuICByZWplY3Q6IChlcnJvcjogRXJyb3IpID0+IHZvaWQ7XG4gIHRpbWVyOiBSZXR1cm5UeXBlPHR5cGVvZiBzZXRUaW1lb3V0PjtcbiAgYWJvcnRDbGVhbnVwPzogKCkgPT4gdm9pZDtcbiAgZXhjbHVkZWRUb2tlbklkczogU2V0PG51bWJlcj47XG59O1xuXG50eXBlIFRva2VuTWV0YWRhdGEgPSB7XG4gIG5hbWU6IHN0cmluZztcbiAgcXVvdGFUaHJlc2hvbGQ/OiBudW1iZXIgfCBudWxsO1xufTtcblxudHlwZSBUb2tlbkVsaWdpYmlsaXR5ID0ge1xuICByZWFkeUFjdGl2ZVRva2VuSWRzOiBTZXQ8bnVtYmVyPjtcbiAgZWxpZ2libGVUb2tlbklkczogU2V0PG51bWJlcj47XG4gIG92ZXJUaHJlc2hvbGRUb2tlbnM6IEFycmF5PHsgdG9rZW5OYW1lOiBzdHJpbmc7IHRocmVzaG9sZDogbnVtYmVyIH0+O1xuICB0aHJlc2hvbGRlZFRva2VuQ291bnQ6IG51bWJlcjtcbn07XG5cbmV4cG9ydCBjbGFzcyBPcGVuQUlEaXNwYXRjaGVyIGltcGxlbWVudHMgUHJvdmlkZXJEaXNwYXRjaGVyIHtcbiAgd29ya2VyUG9vbCA9IG5ldyBNYXA8bnVtYmVyLCBDb2RleEFwcFNlcnZlcldvcmtlcltdPigpO1xuICB0b2tlbk1ldGFkYXRhID0gbmV3IE1hcDxudW1iZXIsIFRva2VuTWV0YWRhdGE+KCk7XG4gIHJyQ3Vyc29yID0gMDtcbiAgcXVldWU6IFF1ZXVlSXRlbVtdID0gW107XG4gIHByaXZhdGUgZHJhaW5pbmcgPSBmYWxzZTtcbiAgcHJpdmF0ZSBkcmFpbkFnYWluID0gZmFsc2U7XG5cbiAgYXN5bmMgc3RhcnQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgeyByb3dzIH0gPSBhd2FpdCBUb2tlbk1vZGVsLmZpbmRNYW55KFwiQVwiKTtcbiAgICBjb25zdCBvcGVuYWlUb2tlbnMgPSByb3dzLmZpbHRlcigodCkgPT4gdC5wcm92aWRlciA9PT0gXCJvcGVuYWlcIik7XG4gICAgbG9nZ2VyLmluZm8oXG4gICAgICBgc3RhcnRpbmcgJHtvcGVuYWlUb2tlbnMubGVuZ3RofSBvcGVuYWkgdG9rZW5zICgke1dPUktFUlNfUEVSX1RPS0VOfSB3b3JrZXJzIGVhY2gpYCxcbiAgICApO1xuXG4gICAgYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKFxuICAgICAgb3BlbmFpVG9rZW5zLm1hcChhc3luYyAodCkgPT4ge1xuICAgICAgICBhd2FpdCB0aGlzLnNwYXduV29ya2VycyhcbiAgICAgICAgICB0LmlkLFxuICAgICAgICAgIHQubmFtZSxcbiAgICAgICAgICB0LmNyZWRlbnRpYWxzIGFzIE9wZW5BSUNyZWRlbnRpYWxzLFxuICAgICAgICAgIHQucXVvdGFfdGhyZXNob2xkLFxuICAgICAgICApO1xuICAgICAgICBpZiAoIXQuYWN0aXZlKSB0aGlzLm9uVG9rZW5EZWFjdGl2YXRlZCh0LmlkKTtcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cblxuICBhc3luYyBzdG9wKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMucmVqZWN0QWxsUXVldWVkKFwiRElTUEFUQ0hFUl9TSFVURE9XTlwiKTtcbiAgICBjb25zdCBraWxscyA9IFsuLi50aGlzLndvcmtlclBvb2wudmFsdWVzKCldLmZsYXQoKS5tYXAoKHcpID0+IHcua2lsbCgpKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQoa2lsbHMpO1xuICAgIHRoaXMud29ya2VyUG9vbC5jbGVhcigpO1xuICAgIHRoaXMudG9rZW5NZXRhZGF0YS5jbGVhcigpO1xuICAgIHRoaXMucmF0ZUxpbWl0c0NhY2hlLmNsZWFyKCk7XG4gIH1cblxuICAvLyDilIDilIAgVG9rZW4gZXZlbnRzIChmcm9tIFRva2VuU3Vic2NyaWJlcikg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgYXN5bmMgb25Ub2tlbkFkZGVkKFxuICAgIGlkOiBudW1iZXIsXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIGNyZWRlbnRpYWxzOiBPcGVuQUlDcmVkZW50aWFscyxcbiAgICBxdW90YVRocmVzaG9sZD86IG51bWJlciB8IG51bGwsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuc2V0VG9rZW5NZXRhZGF0YShpZCwgbmFtZSwgcXVvdGFUaHJlc2hvbGQpO1xuICAgIGlmICh0aGlzLndvcmtlclBvb2wuaGFzKGlkKSkgcmV0dXJuO1xuICAgIGF3YWl0IHRoaXMuc3Bhd25Xb3JrZXJzKGlkLCBuYW1lLCBjcmVkZW50aWFscywgcXVvdGFUaHJlc2hvbGQpO1xuICB9XG5cbiAgYXN5bmMgb25Ub2tlblJlbW92ZWQoaWQ6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHdvcmtlcnMgPSB0aGlzLndvcmtlclBvb2wuZ2V0KGlkKSA/PyBbXTtcbiAgICBjb25zdCB0b2tlbk5hbWUgPSB3b3JrZXJzWzBdPy50b2tlbk5hbWU7XG4gICAgdGhpcy53b3JrZXJQb29sLmRlbGV0ZShpZCk7XG4gICAgdGhpcy50b2tlbk1ldGFkYXRhLmRlbGV0ZShpZCk7XG4gICAgdGhpcy5yYXRlTGltaXRzQ2FjaGUuZGVsZXRlKGlkKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQod29ya2Vycy5tYXAoKHcpID0+IHcua2lsbCgpKSk7XG4gICAgaWYgKHRoaXMuZ2V0QWxsUmVhZHlBY3RpdmVXb3JrZXJzKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aGlzLnJlamVjdEFsbFF1ZXVlZChcIk5PX09QRU5BSV9XT1JLRVJTXCIpO1xuICAgIH1cbiAgICBpZiAod29ya2Vycy5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCBsYWJlbCA9IHRva2VuTmFtZSA/PyBgdG9rZW4gJHtpZH1gO1xuICAgICAgbG9nZ2VyLmluZm8oYHdvcmtlcnMgcmVtb3ZlZDogJHtsYWJlbH0gKCR7d29ya2Vycy5sZW5ndGh9KWApO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIG9uVG9rZW5VcGRhdGVkKFxuICAgIGlkOiBudW1iZXIsXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIGNyZWRlbnRpYWxzOiBPcGVuQUlDcmVkZW50aWFscyxcbiAgICBxdW90YVRocmVzaG9sZD86IG51bWJlciB8IG51bGwsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGV4aXN0aW5nID0gdGhpcy53b3JrZXJQb29sLmdldChpZCkgPz8gW107XG4gICAgY29uc3QgcmVuYW1lZCA9IGV4aXN0aW5nLnNvbWUoKHcpID0+IHcudG9rZW5OYW1lICE9PSBuYW1lKTtcbiAgICB0aGlzLnNldFRva2VuTWV0YWRhdGEoaWQsIG5hbWUsIHF1b3RhVGhyZXNob2xkKTtcbiAgICBpZiAocmVuYW1lZCkgdGhpcy5yYXRlTGltaXRzQ2FjaGUuZGVsZXRlKGlkKTtcblxuICAgIGlmIChleGlzdGluZy5sZW5ndGggPT09IDApIHtcbiAgICAgIGF3YWl0IHRoaXMuc3Bhd25Xb3JrZXJzKGlkLCBuYW1lLCBjcmVkZW50aWFscywgcXVvdGFUaHJlc2hvbGQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChleGlzdGluZy5ldmVyeSgodykgPT4gdy5jYW5SZXVzZUZvclRva2VuKG5hbWUsIGNyZWRlbnRpYWxzKSkpIHtcbiAgICAgIGV4aXN0aW5nLmZvckVhY2goKHcpID0+IHcudXBkYXRlVG9rZW5TdGF0ZShuYW1lLCBjcmVkZW50aWFscykpO1xuICAgICAgbG9nZ2VyLmluZm8oYHdvcmtlcnMgdXBkYXRlZCBpbi1wbGFjZTogJHtuYW1lfWApO1xuICAgICAgdGhpcy5yZXF1ZXN0RHJhaW5RdWV1ZSgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMud29ya2VyUG9vbC5kZWxldGUoaWQpO1xuICAgIHRoaXMucmF0ZUxpbWl0c0NhY2hlLmRlbGV0ZShpZCk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKGV4aXN0aW5nLm1hcCgodykgPT4gdy5raWxsKCkpKTtcbiAgICBhd2FpdCB0aGlzLnNwYXduV29ya2VycyhpZCwgbmFtZSwgY3JlZGVudGlhbHMsIHF1b3RhVGhyZXNob2xkKTtcbiAgfVxuXG4gIG9uVG9rZW5EZWFjdGl2YXRlZChpZDogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3Qgd29ya2VycyA9IHRoaXMud29ya2VyUG9vbC5nZXQoaWQpID8/IFtdO1xuICAgIGNvbnN0IHRva2VuTmFtZSA9IHdvcmtlcnNbMF0/LnRva2VuTmFtZTtcbiAgICB3b3JrZXJzLmZvckVhY2goKHcpID0+IHtcbiAgICAgIHcuYWN0aXZlID0gZmFsc2U7XG4gICAgfSk7XG4gICAgaWYgKHRoaXMuZ2V0QWxsUmVhZHlBY3RpdmVXb3JrZXJzKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aGlzLnJlamVjdEFsbFF1ZXVlZChcIk5PX0FDVElWRV9XT1JLRVJTXCIpO1xuICAgIH1cbiAgICBjb25zdCBsYWJlbCA9IHRva2VuTmFtZSA/PyBgdG9rZW4gJHtpZH1gO1xuICAgIGxvZ2dlci5pbmZvKGB3b3JrZXJzIGRlYWN0aXZhdGVkOiAke2xhYmVsfWApO1xuICB9XG5cbiAgb25Ub2tlbkFjdGl2YXRlZChpZDogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3Qgd29ya2VycyA9IHRoaXMud29ya2VyUG9vbC5nZXQoaWQpID8/IFtdO1xuICAgIGNvbnN0IHRva2VuTmFtZSA9IHdvcmtlcnNbMF0/LnRva2VuTmFtZTtcbiAgICB3b3JrZXJzLmZvckVhY2goKHcpID0+IHtcbiAgICAgIHcuYWN0aXZlID0gdHJ1ZTtcbiAgICB9KTtcbiAgICB0aGlzLnJlcXVlc3REcmFpblF1ZXVlKCk7XG4gICAgY29uc3QgbGFiZWwgPSB0b2tlbk5hbWUgPz8gYHRva2VuICR7aWR9YDtcbiAgICBsb2dnZXIuaW5mbyhgd29ya2VycyBhY3RpdmF0ZWQ6ICR7bGFiZWx9YCk7XG4gIH1cblxuICBhc3luYyByZXBsYWNlVG9rZW5zKFxuICAgIHJvd3M6IEFycmF5PHtcbiAgICAgIGlkOiBudW1iZXI7XG4gICAgICBuYW1lOiBzdHJpbmc7XG4gICAgICBjcmVkZW50aWFsczogT3BlbkFJQ3JlZGVudGlhbHM7XG4gICAgICBxdW90YVRocmVzaG9sZD86IG51bWJlciB8IG51bGw7XG4gICAgfT4sXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IG5leHQgPSBuZXcgU2V0KHJvd3MubWFwKChyKSA9PiByLmlkKSk7XG4gICAgZm9yIChjb25zdCBpZCBvZiBBcnJheS5mcm9tKHRoaXMud29ya2VyUG9vbC5rZXlzKCkpKSB7XG4gICAgICBpZiAoIW5leHQuaGFzKGlkKSkgYXdhaXQgdGhpcy5vblRva2VuUmVtb3ZlZChpZCk7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCByb3cgb2Ygcm93cykge1xuICAgICAgaWYgKHRoaXMud29ya2VyUG9vbC5oYXMocm93LmlkKSkge1xuICAgICAgICBhd2FpdCB0aGlzLm9uVG9rZW5VcGRhdGVkKHJvdy5pZCwgcm93Lm5hbWUsIHJvdy5jcmVkZW50aWFscywgcm93LnF1b3RhVGhyZXNob2xkKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGF3YWl0IHRoaXMub25Ub2tlbkFkZGVkKHJvdy5pZCwgcm93Lm5hbWUsIHJvdy5jcmVkZW50aWFscywgcm93LnF1b3RhVGhyZXNob2xkKTtcbiAgICAgIH1cbiAgICAgIHRoaXMub25Ub2tlbkFjdGl2YXRlZChyb3cuaWQpO1xuICAgIH1cbiAgfVxuXG4gIC8vIOKUgOKUgCBHZW5lcmF0ZSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBhc3luYyBnZW5lcmF0ZShyZXE6IEdlbmVyYXRlUmVxdWVzdCk6IFByb21pc2U8R2VuZXJhdGVSZXN1bHQ+IHtcbiAgICBjb25zdCBleGNsdWRlZFRva2VuSWRzID0gbmV3IFNldDxudW1iZXI+KCk7XG4gICAgLy8gdGhyZWFkIOyerOyCrOyaqSDqsr3roZw6IOyijO2RnCB3b3JrZXIg66W8IOygkOycoO2VtCDquLDsobQgdGhyZWFkIOyXkCB0dXJuIOunjCDsi6TtlokuXG4gICAgY29uc3QgcmV1c2VXb3JrZXIgPSBhd2FpdCB0aGlzLmFjcXVpcmVSZXVzZVdvcmtlcihyZXEsIGV4Y2x1ZGVkVG9rZW5JZHMpO1xuICAgIGlmIChyZXVzZVdvcmtlcikge1xuICAgICAgbG9nZ2VyLmluZm8oXG4gICAgICAgIGDihrsgJHtyZXVzZVdvcmtlci50b2tlbk5hbWV9WyR7cmV1c2VXb3JrZXIudG9rZW5JZH1dIChyZXVzZSB0aHJlYWQsICR7cmVxLm1vZGVsfSlgLFxuICAgICAgKTtcbiAgICAgIHJldHVybiB0aGlzLmV4ZWN1dGVBbmRSZWxlYXNlKHJldXNlV29ya2VyLCAodykgPT5cbiAgICAgICAgdGhpcy5leGVjdXRlVHVybih3LCByZXEsIHJlcS5yZXVzZSEudGhyZWFkSWQpLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCB3b3JrZXIgPSBhd2FpdCB0aGlzLmFjcXVpcmVJZGxlV29ya2VyKGV4Y2x1ZGVkVG9rZW5JZHMpO1xuICAgIGlmICh3b3JrZXIpIHtcbiAgICAgIGxvZ2dlci5pbmZvKGDihpIgJHt3b3JrZXIudG9rZW5OYW1lfVske3dvcmtlci50b2tlbklkfV0gKG1vZGVsOiAke3JlcS5tb2RlbH0pYCk7XG4gICAgICByZXR1cm4gdGhpcy5leGVjdXRlQW5kUmVsZWFzZSh3b3JrZXIsICh3KSA9PiB0aGlzLmV4ZWN1dGVUdXJuKHcsIHJlcSkpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5lbnF1ZXVlKCh3KSA9PiB7XG4gICAgICBsb2dnZXIuaW5mbyhg4oaSICR7dy50b2tlbk5hbWV9WyR7dy50b2tlbklkfV0gKG1vZGVsOiAke3JlcS5tb2RlbH0sIHF1ZXVlZClgKTtcbiAgICAgIHJldHVybiB0aGlzLmV4ZWN1dGVUdXJuKHcsIHJlcSk7XG4gICAgfSwgZXhjbHVkZWRUb2tlbklkcyk7XG4gIH1cblxuICBhc3luYyBnZW5lcmF0ZVN0cmVhbShyZXE6IEdlbmVyYXRlUmVxdWVzdCwgY2I6IEdlbmVyYXRlU3RyZWFtQ2FsbGJhY2tzKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgZXhjbHVkZWRUb2tlbklkcyA9IG5ldyBTZXQ8bnVtYmVyPigpO1xuICAgIGNvbnN0IHJldXNlV29ya2VyID0gYXdhaXQgdGhpcy5hY3F1aXJlUmV1c2VXb3JrZXIocmVxLCBleGNsdWRlZFRva2VuSWRzKTtcbiAgICBpZiAocmV1c2VXb3JrZXIpIHtcbiAgICAgIGxvZ2dlci5pbmZvKGDihrsgJHtyZXVzZVdvcmtlci50b2tlbk5hbWV9WyR7cmV1c2VXb3JrZXIudG9rZW5JZH1dIChyZXVzZSB0aHJlYWQsIFtzdHJlYW1dKWApO1xuICAgICAgcmV0dXJuIHRoaXMuZXhlY3V0ZUFuZFJlbGVhc2UocmV1c2VXb3JrZXIsICh3KSA9PlxuICAgICAgICB0aGlzLmV4ZWN1dGVTdHJlYW1UdXJuKHcsIHJlcSwgY2IsIHJlcS5yZXVzZSEudGhyZWFkSWQpLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCB3b3JrZXIgPSBhd2FpdCB0aGlzLmFjcXVpcmVJZGxlV29ya2VyKGV4Y2x1ZGVkVG9rZW5JZHMpO1xuICAgIGlmICh3b3JrZXIpIHtcbiAgICAgIGxvZ2dlci5pbmZvKGDihpIgJHt3b3JrZXIudG9rZW5OYW1lfVske3dvcmtlci50b2tlbklkfV0gKG1vZGVsOiAke3JlcS5tb2RlbH0sIFtzdHJlYW1dKWApO1xuICAgICAgcmV0dXJuIHRoaXMuZXhlY3V0ZUFuZFJlbGVhc2Uod29ya2VyLCAodykgPT4gdGhpcy5leGVjdXRlU3RyZWFtVHVybih3LCByZXEsIGNiKSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmVucXVldWUoKHcpID0+IHtcbiAgICAgIGxvZ2dlci5pbmZvKGDihpIgJHt3LnRva2VuTmFtZX1bJHt3LnRva2VuSWR9XSAobW9kZWw6ICR7cmVxLm1vZGVsfSwgW3N0cmVhbV0sIHF1ZXVlZClgKTtcbiAgICAgIHJldHVybiB0aGlzLmV4ZWN1dGVTdHJlYW1UdXJuKHcsIHJlcSwgY2IpO1xuICAgIH0sIGV4Y2x1ZGVkVG9rZW5JZHMpO1xuICB9XG5cbiAgLy8gcmV1c2Ug7KKM7ZGc6rCAIOycoO2aqO2VmOuptCDqt7ggd29ya2VyIOulvCBidXN5IOygkOycoO2VtCDrsJjtmZguIOyXhuqxsOuCmCDtj7TrsLEg64yA7IOB7J2066m0IG51bGwuXG4gIC8vIO2PtOuwsSDsgqzsnKA6IOq4sOuKpSBvZmYgLyDsooztkZwg7JeG7J2MIC8gd29ya2VyIOu2gOyerMK37KO97J2MIC8gZXBvY2gg67aI7J287LmYKHJlc3RhcnQpIC8gdGhyZWFkIOyGjOupuCAvXG4gIC8vICAgICAgICAgICAgYnVzeSDrjIDquLAg7YOA7J6E7JWE7JuDLiBudWxsIOuwmO2ZmCDsi5wg7Zi47Lac67aA64qUIOyDiCB0aHJlYWQg6rK966Gc66GcIOynhO2WiS5cbiAgYXN5bmMgYWNxdWlyZVJldXNlV29ya2VyKFxuICAgIHJlcTogR2VuZXJhdGVSZXF1ZXN0LFxuICAgIGV4Y2x1ZGVkVG9rZW5JZHMgPSBuZXcgU2V0PG51bWJlcj4oKSxcbiAgKTogUHJvbWlzZTxDb2RleEFwcFNlcnZlcldvcmtlciB8IG51bGw+IHtcbiAgICBpZiAoIVRIUkVBRF9SRVVTRV9FTkFCTEVEIHx8ICFyZXEucmV1c2UpIHJldHVybiBudWxsO1xuICAgIGNvbnN0IHsgd29ya2VySWQsIHRocmVhZElkLCBlcG9jaCB9ID0gcmVxLnJldXNlO1xuXG4gICAgY29uc3Qgd29ya2VyID0gdGhpcy5maW5kV29ya2VyQnlJZCh3b3JrZXJJZCk7XG4gICAgaWYgKCF3b3JrZXIgfHwgIXdvcmtlci5pc1JlYWR5IHx8ICF3b3JrZXIuYWN0aXZlKSByZXR1cm4gbnVsbDtcbiAgICBpZiAod29ya2VyLmVwb2NoICE9PSBlcG9jaCkgcmV0dXJuIG51bGw7XG4gICAgaWYgKCF3b3JrZXIuaGFzVGhyZWFkKHRocmVhZElkKSkgcmV0dXJuIG51bGw7XG4gICAgaWYgKCEoYXdhaXQgdGhpcy5pc1Rva2VuUXVvdGFFbGlnaWJsZSh3b3JrZXIudG9rZW5JZCwgd29ya2VyLnRva2VuTmFtZSwgZXhjbHVkZWRUb2tlbklkcykpKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCBkZWFkbGluZSA9IERhdGUubm93KCkgKyBSRVVTRV9XT1JLRVJfV0FJVF9NUztcbiAgICBmb3IgKDs7KSB7XG4gICAgICAvLyByZXN0YXJ0KGVwb2NoIOuzgOqyvSkgLyB0aHJlYWQg7IaM66m47J20IOuMgOq4sCDspJHsl5Ag67Cc7IOd7ZWY66m0IO2PtOuwsS5cbiAgICAgIGlmICh3b3JrZXIuZXBvY2ggIT09IGVwb2NoIHx8ICF3b3JrZXIuaGFzVGhyZWFkKHRocmVhZElkKSkgcmV0dXJuIG51bGw7XG4gICAgICBpZiAod29ya2VyLnRyeUFjcXVpcmVUdXJuKCkpIHJldHVybiB3b3JrZXI7XG4gICAgICBpZiAoRGF0ZS5ub3coKSA+PSBkZWFkbGluZSkgcmV0dXJuIG51bGw7XG4gICAgICBhd2FpdCBzbGVlcChSRVVTRV9XT1JLRVJfUE9MTF9NUyk7XG4gICAgfVxuICB9XG5cbiAgZmluZFdvcmtlckJ5SWQod29ya2VySWQ6IG51bWJlcik6IENvZGV4QXBwU2VydmVyV29ya2VyIHwgbnVsbCB7XG4gICAgZm9yIChjb25zdCB3b3JrZXJzIG9mIHRoaXMud29ya2VyUG9vbC52YWx1ZXMoKSkge1xuICAgICAgZm9yIChjb25zdCB3IG9mIHdvcmtlcnMpIHtcbiAgICAgICAgaWYgKG1ha2VXb3JrZXJJZCh3LnRva2VuSWQsIHcud29ya2VySW5kZXgpID09PSB3b3JrZXJJZCkgcmV0dXJuIHc7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgYXN5bmMgaW50ZXJydXB0V29ya2VyVHVybih0aHJlYWRJZDogc3RyaW5nLCB0dXJuSWQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGFsbFdvcmtlcnMgPSBbLi4udGhpcy53b3JrZXJQb29sLnZhbHVlcygpXS5mbGF0KCkuZmlsdGVyKCh3KSA9PiB3LmlzUmVhZHkpO1xuICAgIGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChhbGxXb3JrZXJzLm1hcCgodykgPT4gdy5pbnRlcnJ1cHRUdXJuKHRocmVhZElkLCB0dXJuSWQpKSk7XG4gIH1cblxuICAvLyDilIDilIAgV29ya2VyIHNlbGVjdGlvbiDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbiAgLy8gIOq4sOuzuCByb3VuZC1yb2JpblxuICAvLyBUT0RPOiDstpTtm4Qg64uk66W4IOyVjOqzoOumrOymmOycvOuhnCDrs4Dqsr0g6rCA64ql7ZWY6rKMIOyngOybkFxuICBhc3luYyBhY3F1aXJlSWRsZVdvcmtlcihcbiAgICBleGNsdWRlZFRva2VuSWRzID0gbmV3IFNldDxudW1iZXI+KCksXG4gICk6IFByb21pc2U8Q29kZXhBcHBTZXJ2ZXJXb3JrZXIgfCBudWxsPiB7XG4gICAgY29uc3QgZWxpZ2liaWxpdHkgPSBhd2FpdCB0aGlzLnJlc29sdmVUb2tlbkVsaWdpYmlsaXR5KGV4Y2x1ZGVkVG9rZW5JZHMpO1xuICAgIGlmIChlbGlnaWJpbGl0eS5yZWFkeUFjdGl2ZVRva2VuSWRzLnNpemUgPT09IDApIHJldHVybiBudWxsO1xuICAgIGlmIChlbGlnaWJpbGl0eS5lbGlnaWJsZVRva2VuSWRzLnNpemUgPT09IDApIHRoaXMudGhyb3dRdW90YVRocmVzaG9sZEV4Y2VlZGVkKGVsaWdpYmlsaXR5KTtcblxuICAgIGNvbnN0IGFsbFdvcmtlcnMgPSB0aGlzLmdldEFsbFJlYWR5QWN0aXZlV29ya2VycygpLmZpbHRlcigodykgPT5cbiAgICAgIGVsaWdpYmlsaXR5LmVsaWdpYmxlVG9rZW5JZHMuaGFzKHcudG9rZW5JZCksXG4gICAgKTtcbiAgICBpZiAoYWxsV29ya2Vycy5sZW5ndGggPT09IDApIHJldHVybiBudWxsO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYWxsV29ya2Vycy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgdyA9IGFsbFdvcmtlcnNbKHRoaXMucnJDdXJzb3IgKyBpKSAlIGFsbFdvcmtlcnMubGVuZ3RoXSE7XG4gICAgICBpZiAody50cnlBY3F1aXJlVHVybigpKSB7XG4gICAgICAgIHRoaXMucnJDdXJzb3IgPSAodGhpcy5yckN1cnNvciArIGkgKyAxKSAlIGFsbFdvcmtlcnMubGVuZ3RoO1xuICAgICAgICByZXR1cm4gdztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBnZXRBbGxSZWFkeUFjdGl2ZVdvcmtlcnMoKTogQ29kZXhBcHBTZXJ2ZXJXb3JrZXJbXSB7XG4gICAgcmV0dXJuIFsuLi50aGlzLndvcmtlclBvb2wudmFsdWVzKCldLmZsYXQoKS5maWx0ZXIoKHcpID0+IHcuaXNSZWFkeSAmJiB3LmFjdGl2ZSk7XG4gIH1cblxuICAvLyDilIDilIAgUXVldWUg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgYXN5bmMgZW5xdWV1ZTxUPihcbiAgICBleGVjdXRlOiAod29ya2VyOiBDb2RleEFwcFNlcnZlcldvcmtlcikgPT4gUHJvbWlzZTxUPixcbiAgICBleGNsdWRlZFRva2VuSWRzID0gbmV3IFNldDxudW1iZXI+KCksXG4gICk6IFByb21pc2U8VD4ge1xuICAgIGNvbnN0IGVsaWdpYmlsaXR5ID0gYXdhaXQgdGhpcy5yZXNvbHZlVG9rZW5FbGlnaWJpbGl0eShleGNsdWRlZFRva2VuSWRzKTtcbiAgICBpZiAoZWxpZ2liaWxpdHkucmVhZHlBY3RpdmVUb2tlbklkcy5zaXplID09PSAwKSB0aHJvdyBuZXcgRXJyb3IoXCJOT19PUEVOQUlfV09SS0VSU1wiKTtcbiAgICBpZiAoZWxpZ2liaWxpdHkuZWxpZ2libGVUb2tlbklkcy5zaXplID09PSAwKSB0aGlzLnRocm93UXVvdGFUaHJlc2hvbGRFeGNlZWRlZChlbGlnaWJpbGl0eSk7XG4gICAgaWYgKHRoaXMucXVldWUubGVuZ3RoID49IE1BWF9RVUVVRV9TSVpFKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTRVJWRVJfQlVTWVwiKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2U8VD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgaXRlbTogUXVldWVJdGVtID0ge1xuICAgICAgICByZXNvbHZlOiAod29ya2VyKSA9PiB7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KGl0ZW0udGltZXIpO1xuICAgICAgICAgIGl0ZW0uYWJvcnRDbGVhbnVwPy4oKTtcbiAgICAgICAgICBQcm9taXNlLnJlc29sdmUoKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4gdGhpcy5leGVjdXRlQW5kUmVsZWFzZSh3b3JrZXIsIGV4ZWN1dGUpKVxuICAgICAgICAgICAgLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgICAgfSxcbiAgICAgICAgcmVqZWN0OiAoZXJyKSA9PiB7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KGl0ZW0udGltZXIpO1xuICAgICAgICAgIGl0ZW0uYWJvcnRDbGVhbnVwPy4oKTtcbiAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgfSxcbiAgICAgICAgdGltZXI6IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgIHRoaXMucmVtb3ZlRnJvbVF1ZXVlKGl0ZW0pO1xuICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoXCJTRVJWRVJfQlVTWVwiKSk7XG4gICAgICAgIH0sIFFVRVVFX1RJTUVPVVRfTVMpLFxuICAgICAgICBleGNsdWRlZFRva2VuSWRzOiBuZXcgU2V0KGV4Y2x1ZGVkVG9rZW5JZHMpLFxuICAgICAgfTtcblxuICAgICAgdGhpcy5xdWV1ZS5wdXNoKGl0ZW0pO1xuICAgIH0pO1xuICB9XG5cbiAgcmVtb3ZlRnJvbVF1ZXVlKGl0ZW06IFF1ZXVlSXRlbSk6IHZvaWQge1xuICAgIGNsZWFyVGltZW91dChpdGVtLnRpbWVyKTtcbiAgICBpdGVtLmFib3J0Q2xlYW51cD8uKCk7XG4gICAgY29uc3QgaWR4ID0gdGhpcy5xdWV1ZS5pbmRleE9mKGl0ZW0pO1xuICAgIGlmIChpZHggIT09IC0xKSB0aGlzLnF1ZXVlLnNwbGljZShpZHgsIDEpO1xuICB9XG5cbiAgcmVqZWN0QWxsUXVldWVkKHJlYXNvbjogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgZXJyID0gbmV3IEVycm9yKHJlYXNvbik7XG4gICAgdGhpcy5xdWV1ZS5mb3JFYWNoKChpdGVtKSA9PiB7XG4gICAgICBjbGVhclRpbWVvdXQoaXRlbS50aW1lcik7XG4gICAgICBpdGVtLmFib3J0Q2xlYW51cD8uKCk7XG4gICAgICBpdGVtLnJlamVjdChlcnIpO1xuICAgIH0pO1xuICAgIHRoaXMucXVldWUgPSBbXTtcbiAgfVxuXG4gIGFzeW5jIGRyYWluUXVldWUocmVsZWFzZWRXb3JrZXI/OiBDb2RleEFwcFNlcnZlcldvcmtlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLmRyYWluaW5nKSB7XG4gICAgICB0aGlzLmRyYWluQWdhaW4gPSB0cnVlO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuZHJhaW5pbmcgPSB0cnVlO1xuICAgIGxldCB3b3JrZXIgPSByZWxlYXNlZFdvcmtlcjtcbiAgICB0cnkge1xuICAgICAgZG8ge1xuICAgICAgICB0aGlzLmRyYWluQWdhaW4gPSBmYWxzZTtcbiAgICAgICAgYXdhaXQgdGhpcy5kcmFpblF1ZXVlT25jZSh3b3JrZXIpO1xuICAgICAgICB3b3JrZXIgPSB1bmRlZmluZWQ7XG4gICAgICB9IHdoaWxlICh0aGlzLmRyYWluQWdhaW4pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxvZ2dlci53YXJuKGBkcmFpblF1ZXVlIGZhaWxlZDogJHsoZSBhcyBFcnJvcikubWVzc2FnZX1gKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgdGhpcy5kcmFpbmluZyA9IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZHJhaW5RdWV1ZU9uY2UocmVsZWFzZWRXb3JrZXI/OiBDb2RleEFwcFNlcnZlcldvcmtlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmIChcbiAgICAgIHJlbGVhc2VkV29ya2VyICYmXG4gICAgICB0aGlzLnF1ZXVlLmxlbmd0aCA+IDAgJiZcbiAgICAgIHJlbGVhc2VkV29ya2VyLmlzUmVhZHkgJiZcbiAgICAgIHJlbGVhc2VkV29ya2VyLmFjdGl2ZSAmJlxuICAgICAgKGF3YWl0IHRoaXMuaXNXb3JrZXJFbGlnaWJsZUZvclF1ZXVlSXRlbShyZWxlYXNlZFdvcmtlciwgdGhpcy5xdWV1ZVswXSEpKSAmJlxuICAgICAgcmVsZWFzZWRXb3JrZXIudHJ5QWNxdWlyZVR1cm4oKVxuICAgICkge1xuICAgICAgY29uc3QgbmV4dCA9IHRoaXMucXVldWUuc2hpZnQoKSE7XG4gICAgICBuZXh0LnJlc29sdmUocmVsZWFzZWRXb3JrZXIpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHdoaWxlICh0aGlzLnF1ZXVlLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IG5leHQgPSB0aGlzLnF1ZXVlWzBdITtcbiAgICAgIGxldCB3b3JrZXI6IENvZGV4QXBwU2VydmVyV29ya2VyIHwgbnVsbDtcbiAgICAgIHRyeSB7XG4gICAgICAgIHdvcmtlciA9IGF3YWl0IHRoaXMuYWNxdWlyZUlkbGVXb3JrZXIobmV4dC5leGNsdWRlZFRva2VuSWRzKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiBRdW90YVRocmVzaG9sZEV4Y2VlZGVkRXJyb3IpIHtcbiAgICAgICAgICB0aGlzLnF1ZXVlLnNoaWZ0KCk7XG4gICAgICAgICAgbmV4dC5yZWplY3QoZSk7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICAgIGlmICghd29ya2VyKSBicmVhaztcbiAgICAgIHRoaXMucXVldWUuc2hpZnQoKTtcbiAgICAgIG5leHQucmVzb2x2ZSh3b3JrZXIpO1xuICAgIH1cbiAgfVxuXG4gIC8vIOKUgOKUgCBFeGVjdXRpb24g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgYXN5bmMgZXhlY3V0ZUFuZFJlbGVhc2U8VD4oXG4gICAgd29ya2VyOiBDb2RleEFwcFNlcnZlcldvcmtlcixcbiAgICBleGVjdXRlOiAod29ya2VyOiBDb2RleEFwcFNlcnZlcldvcmtlcikgPT4gUHJvbWlzZTxUPixcbiAgKTogUHJvbWlzZTxUPiB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBhd2FpdCBleGVjdXRlKHdvcmtlcik7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHdvcmtlci5yZWxlYXNlVHVybigpO1xuICAgICAgdGhpcy5yZXF1ZXN0RHJhaW5RdWV1ZSh3b3JrZXIpO1xuICAgIH1cbiAgfVxuXG4gIC8vIHJldXNlVGhyZWFkSWQg6rCAIOyeiOycvOuptCDquLDsobQgdGhyZWFkIOyXkCBkZWx0YShyZXVzZUlucHV0KeunjCwg7JeG7Jy866m0IOyDiCB0aHJlYWQg7JeQIOyghOyytFxuICAvLyBwcm9tcHQoY29sZElucHV0KSArIGhpc3RvcnkgaW5qZWN0LiByZXVzZSDqsIAgZGlzcGF0Y2hlciDri6jsl5DshJwg7Y+067Cx65CY66m0IO2bhOyekOuhnCDrlqjslrTsp4Tri6QuXG4gIHByaXZhdGUgYnVpbGRUdXJuUmVxdWVzdChyZXE6IEdlbmVyYXRlUmVxdWVzdCwgcmV1c2VUaHJlYWRJZD86IHN0cmluZyk6IFR1cm5SZXF1ZXN0IHtcbiAgICBjb25zdCByZXVzaW5nID0gcmV1c2VUaHJlYWRJZCAhPT0gdW5kZWZpbmVkO1xuICAgIHJldHVybiB7XG4gICAgICBpbnB1dDogcmV1c2luZyAmJiByZXEucmV1c2VJbnB1dCA/IHJlcS5yZXVzZUlucHV0IDogcmVxLmNvbGRJbnB1dCxcbiAgICAgIGhpc3Rvcnk6IHJldXNpbmcgPyB1bmRlZmluZWQgOiByZXEuY29sZEhpc3RvcnksXG4gICAgICBkZXZlbG9wZXJJbnN0cnVjdGlvbnM6IHJlcS5zeXN0ZW1Qcm9tcHQsXG4gICAgICBvdXRwdXRTY2hlbWE6IHJlcS5vdXRwdXRTY2hlbWEsXG4gICAgICBlZmZvcnQ6IHJlcS5lZmZvcnQgPz8gREVGQVVMVF9FRkZPUlQsXG4gICAgICBtb2RlbDogcmVxLm1vZGVsLFxuICAgICAgdmVyYm9zaXR5OiByZXEudmVyYm9zaXR5LFxuICAgICAgcmVhc29uaW5nU3VtbWFyeTogcmVxLnJlYXNvbmluZ1N1bW1hcnksXG4gICAgICBzZXJ2aWNlVGllcjogcmVxLnNlcnZpY2VUaWVyLFxuICAgIH07XG4gIH1cblxuICBhc3luYyBleGVjdXRlVHVybihcbiAgICB3b3JrZXI6IENvZGV4QXBwU2VydmVyV29ya2VyLFxuICAgIHJlcTogR2VuZXJhdGVSZXF1ZXN0LFxuICAgIHJldXNlVGhyZWFkSWQ/OiBzdHJpbmcsXG4gICk6IFByb21pc2U8R2VuZXJhdGVSZXN1bHQ+IHtcbiAgICBjb25zdCB0dXJuUmVxID0gdGhpcy5idWlsZFR1cm5SZXF1ZXN0KHJlcSwgcmV1c2VUaHJlYWRJZCk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgd29ya2VyLmV4ZWN1dGVUdXJuKHR1cm5SZXEsIHJldXNlVGhyZWFkSWQpO1xuICAgIHJldHVybiB7XG4gICAgICB0ZXh0OiByZXN1bHQudGV4dCxcbiAgICAgIHRva2VuTmFtZTogd29ya2VyLnRva2VuTmFtZSxcbiAgICAgIHVzYWdlOiByZXN1bHQudXNhZ2UsXG4gICAgICBkdXJhdGlvbk1zOiByZXN1bHQuZHVyYXRpb25NcyxcbiAgICAgIHR0ZnRNczogcmVzdWx0LnR0ZnRNcyxcbiAgICAgIG1vZGVsOiByZXN1bHQubW9kZWwsXG4gICAgICB0aHJlYWRDb29yZDoge1xuICAgICAgICB3b3JrZXJJZDogbWFrZVdvcmtlcklkKHdvcmtlci50b2tlbklkLCB3b3JrZXIud29ya2VySW5kZXgpLFxuICAgICAgICB0aHJlYWRJZDogcmVzdWx0LnRocmVhZElkLFxuICAgICAgICBlcG9jaDogd29ya2VyLmVwb2NoLFxuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgYXN5bmMgZXhlY3V0ZVN0cmVhbVR1cm4oXG4gICAgd29ya2VyOiBDb2RleEFwcFNlcnZlcldvcmtlcixcbiAgICByZXE6IEdlbmVyYXRlUmVxdWVzdCxcbiAgICBjYjogR2VuZXJhdGVTdHJlYW1DYWxsYmFja3MsXG4gICAgcmV1c2VUaHJlYWRJZD86IHN0cmluZyxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgdHVyblJlcSA9IHRoaXMuYnVpbGRUdXJuUmVxdWVzdChyZXEsIHJldXNlVGhyZWFkSWQpO1xuICAgIC8vIHdvcmtlciDsnZggVHVyblJlc3VsdCDsl5AgdG9rZW5OYW1lL3RocmVhZENvb3JkIOulvCDrtpnsl6wg7IOB7JyEKEdlbmVyYXRlUmVzdWx0KeuhnCDsmKzrprDri6QuXG4gICAgLy8gdGhyZWFkSWQg64qUIOyDiCB0aHJlYWQg66m0IG9uVGhyZWFkSWQg66GcIO2ZleygleuQmOuvgOuhnCDrr7jrpqwg67O06rSA7ZW0IOuRkOqzoCBvbkNvbXBsZXRlIOuVjCDsnb3ripTri6QuXG4gICAgbGV0IHJlc29sdmVkVGhyZWFkSWQgPSByZXVzZVRocmVhZElkID8/IFwiXCI7XG4gICAgY29uc3Qgd3JhcHBlZENiOiBTdHJlYW1DYWxsYmFja3MgPSB7XG4gICAgICAuLi5jYixcbiAgICAgIG9uVGhyZWFkSWQ6ICh0aHJlYWRJZCkgPT4ge1xuICAgICAgICByZXNvbHZlZFRocmVhZElkID0gdGhyZWFkSWQ7XG4gICAgICAgIGNiLm9uVGhyZWFkSWQ/Lih0aHJlYWRJZCk7XG4gICAgICB9LFxuICAgICAgb25Db21wbGV0ZTogKHJlc3VsdCkgPT4ge1xuICAgICAgICBjYi5vbkNvbXBsZXRlKHtcbiAgICAgICAgICAuLi5yZXN1bHQsXG4gICAgICAgICAgdG9rZW5OYW1lOiB3b3JrZXIudG9rZW5OYW1lLFxuICAgICAgICAgIHRocmVhZENvb3JkOiB7XG4gICAgICAgICAgICB3b3JrZXJJZDogbWFrZVdvcmtlcklkKHdvcmtlci50b2tlbklkLCB3b3JrZXIud29ya2VySW5kZXgpLFxuICAgICAgICAgICAgdGhyZWFkSWQ6IHJlc29sdmVkVGhyZWFkSWQsXG4gICAgICAgICAgICBlcG9jaDogd29ya2VyLmVwb2NoLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgfSxcbiAgICB9O1xuICAgIGF3YWl0IHdvcmtlci5leGVjdXRlVHVyblN0cmVhbSh0dXJuUmVxLCB3cmFwcGVkQ2IsIHJldXNlVGhyZWFkSWQpO1xuICB9XG5cbiAgLy8g4pSA4pSAIFNwYXduIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIGFzeW5jIHNwYXduV29ya2VycyhcbiAgICB0b2tlbklkOiBudW1iZXIsXG4gICAgdG9rZW5OYW1lOiBzdHJpbmcsXG4gICAgY3JlZGVudGlhbHM6IE9wZW5BSUNyZWRlbnRpYWxzLFxuICAgIHF1b3RhVGhyZXNob2xkPzogbnVtYmVyIHwgbnVsbCxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5zZXRUb2tlbk1ldGFkYXRhKHRva2VuSWQsIHRva2VuTmFtZSwgcXVvdGFUaHJlc2hvbGQpO1xuICAgIGNvbnN0IHdvcmtlcnM6IENvZGV4QXBwU2VydmVyV29ya2VyW10gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IFdPUktFUlNfUEVSX1RPS0VOOyBpKyspIHtcbiAgICAgIGlmIChpID4gMCkgYXdhaXQgc2xlZXAoU1BBV05fSU5URVJWQUxfTVMpO1xuICAgICAgY29uc3Qgd29ya2VyID0gYXdhaXQgdGhpcy5zcGF3blNpbmdsZVdvcmtlcih0b2tlbklkLCB0b2tlbk5hbWUsIGNyZWRlbnRpYWxzLCBpKTtcbiAgICAgIGlmICh3b3JrZXIpIHdvcmtlcnMucHVzaCh3b3JrZXIpO1xuICAgIH1cbiAgICBpZiAod29ya2Vycy5sZW5ndGggPiAwKSB0aGlzLndvcmtlclBvb2wuc2V0KHRva2VuSWQsIHdvcmtlcnMpO1xuICB9XG5cbiAgYXN5bmMgc3Bhd25TaW5nbGVXb3JrZXIoXG4gICAgdG9rZW5JZDogbnVtYmVyLFxuICAgIHRva2VuTmFtZTogc3RyaW5nLFxuICAgIGNyZWRlbnRpYWxzOiBPcGVuQUlDcmVkZW50aWFscyxcbiAgICB3b3JrZXJJbmRleDogbnVtYmVyLFxuICApOiBQcm9taXNlPENvZGV4QXBwU2VydmVyV29ya2VyIHwgbnVsbD4ge1xuICAgIGNvbnN0IHdvcmtlciA9IG5ldyBDb2RleEFwcFNlcnZlcldvcmtlcih7XG4gICAgICB0b2tlbklkLFxuICAgICAgdG9rZW5OYW1lLFxuICAgICAgYWNjZXNzVG9rZW46IGNyZWRlbnRpYWxzLmFjY2Vzc1Rva2VuLFxuICAgICAgYWNjb3VudElkOiBjcmVkZW50aWFscy5hY2NvdW50SWQsXG4gICAgICBwbGFuVHlwZTogY3JlZGVudGlhbHMucGxhblR5cGUsXG4gICAgICB3b3JrZXJJbmRleCxcbiAgICB9KTtcblxuICAgIHdvcmtlci5vblJlYWR5ID0gKCkgPT4gdGhpcy5yZXF1ZXN0RHJhaW5RdWV1ZSgpO1xuXG4gICAgd29ya2VyLnNldFNlcnZlclJlcXVlc3RIYW5kbGVyKGFzeW5jIChtZXRob2QpID0+IHtcbiAgICAgIGlmIChtZXRob2QgPT09IFwiYWNjb3VudC9jaGF0Z3B0QXV0aFRva2Vucy9yZWZyZXNoXCIpIHtcbiAgICAgICAgcmV0dXJuIGhhbmRsZUNoYXRncHRBdXRoVG9rZW5zUmVmcmVzaCh0b2tlbklkKTtcbiAgICAgIH1cbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5oYW5kbGVkIHNlcnZlci1yZXF1ZXN0OiAke21ldGhvZH1gKTtcbiAgICB9KTtcblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCB3b3JrZXIuaW5pdGlhbGl6ZSgpO1xuICAgICAgbG9nZ2VyLmluZm8oYHdvcmtlciBzcGF3bmVkOiAke3Rva2VuTmFtZX1bJHt3b3JrZXJJbmRleH1dYCk7XG4gICAgICByZXR1cm4gd29ya2VyO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxvZ2dlci53YXJuKGB3b3JrZXIgc3Bhd24gZmFpbGVkOiAke3Rva2VuTmFtZX1bJHt3b3JrZXJJbmRleH1dOiAkeyhlIGFzIEVycm9yKS5tZXNzYWdlfWApO1xuICAgICAgYXdhaXQgd29ya2VyLmtpbGwoKS5jYXRjaCgoKSA9PiB7fSk7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cblxuICAvLyDilIDilIAgUmF0ZSBsaW1pdHMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgcmF0ZUxpbWl0c0NhY2hlID0gbmV3IE1hcDxudW1iZXIsIHsgZGF0YTogR2V0QWNjb3VudFJhdGVMaW1pdHNSZXNwb25zZTsgY2FjaGVkQXQ6IG51bWJlciB9PigpO1xuICBzdGF0aWMgcmVhZG9ubHkgUkFURV9MSU1JVFNfQ0FDSEVfVFRMID0gNjBfMDAwO1xuXG4gIGFzeW5jIGdldFJhdGVMaW1pdHNCeVRva2VuSWQodG9rZW5JZDogbnVtYmVyKTogUHJvbWlzZTxPcGVuQUlSYXRlTGltaXRzV2l0aE1ldGE+IHtcbiAgICBjb25zdCBjYWNoZWQgPSB0aGlzLnJhdGVMaW1pdHNDYWNoZS5nZXQodG9rZW5JZCk7XG4gICAgaWYgKGNhY2hlZCAmJiBEYXRlLm5vdygpIC0gY2FjaGVkLmNhY2hlZEF0IDwgT3BlbkFJRGlzcGF0Y2hlci5SQVRFX0xJTUlUU19DQUNIRV9UVEwpIHtcbiAgICAgIHJldHVybiBjYWNoZWQ7XG4gICAgfVxuXG4gICAgY29uc3Qgd29ya2VyID0gKHRoaXMud29ya2VyUG9vbC5nZXQodG9rZW5JZCkgPz8gW10pLmZpbmQoKHcpID0+IHcuaXNSZWFkeSk7XG4gICAgaWYgKCF3b3JrZXIpIHRocm93IG5ldyBFcnJvcihcIm5vIHJlYWR5IG9wZW5haSB3b3JrZXJzXCIpO1xuICAgIGNvbnN0IGRhdGEgPSAoYXdhaXQgd29ya2VyLmdldFJhdGVMaW1pdHMoKSkgYXMgR2V0QWNjb3VudFJhdGVMaW1pdHNSZXNwb25zZTtcbiAgICBjb25zdCBlbnRyeSA9IHsgZGF0YSwgY2FjaGVkQXQ6IERhdGUubm93KCkgfTtcbiAgICB0aGlzLnJhdGVMaW1pdHNDYWNoZS5zZXQodG9rZW5JZCwgZW50cnkpO1xuICAgIHJldHVybiBlbnRyeTtcbiAgfVxuXG4gIHByaXZhdGUgcmVxdWVzdERyYWluUXVldWUocmVsZWFzZWRXb3JrZXI/OiBDb2RleEFwcFNlcnZlcldvcmtlcik6IHZvaWQge1xuICAgIHZvaWQgdGhpcy5kcmFpblF1ZXVlKHJlbGVhc2VkV29ya2VyKS5jYXRjaCgoZSkgPT5cbiAgICAgIGxvZ2dlci53YXJuKGBkcmFpblF1ZXVlIGZhaWxlZDogJHsoZSBhcyBFcnJvcikubWVzc2FnZX1gKSxcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBzZXRUb2tlbk1ldGFkYXRhKGlkOiBudW1iZXIsIG5hbWU6IHN0cmluZywgcXVvdGFUaHJlc2hvbGQ/OiBudW1iZXIgfCBudWxsKTogdm9pZCB7XG4gICAgdGhpcy50b2tlbk1ldGFkYXRhLnNldChpZCwgeyBuYW1lLCBxdW90YVRocmVzaG9sZCB9KTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0UXVvdGFUaHJlc2hvbGQodG9rZW5JZDogbnVtYmVyKTogbnVtYmVyIHwgbnVsbCB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMudG9rZW5NZXRhZGF0YS5nZXQodG9rZW5JZCk/LnF1b3RhVGhyZXNob2xkO1xuICB9XG5cbiAgcHJpdmF0ZSBoYXNRdW90YVRocmVzaG9sZCh0b2tlbklkOiBudW1iZXIpOiBib29sZWFuIHtcbiAgICBjb25zdCB0aHJlc2hvbGQgPSB0aGlzLmdldFF1b3RhVGhyZXNob2xkKHRva2VuSWQpO1xuICAgIHJldHVybiB0aHJlc2hvbGQgIT09IHVuZGVmaW5lZCAmJiB0aHJlc2hvbGQgIT09IG51bGw7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlc29sdmVUb2tlbkVsaWdpYmlsaXR5KGV4Y2x1ZGVkVG9rZW5JZHM6IFNldDxudW1iZXI+KTogUHJvbWlzZTxUb2tlbkVsaWdpYmlsaXR5PiB7XG4gICAgY29uc3Qgd29ya2VycyA9IHRoaXMuZ2V0QWxsUmVhZHlBY3RpdmVXb3JrZXJzKCk7XG4gICAgY29uc3QgYnlUb2tlbiA9IG5ldyBNYXA8bnVtYmVyLCBzdHJpbmc+KCk7XG4gICAgZm9yIChjb25zdCB3b3JrZXIgb2Ygd29ya2Vycykge1xuICAgICAgaWYgKCFieVRva2VuLmhhcyh3b3JrZXIudG9rZW5JZCkpIGJ5VG9rZW4uc2V0KHdvcmtlci50b2tlbklkLCB3b3JrZXIudG9rZW5OYW1lKTtcbiAgICB9XG5cbiAgICBjb25zdCByZWFkeUFjdGl2ZVRva2VuSWRzID0gbmV3IFNldChieVRva2VuLmtleXMoKSk7XG4gICAgY29uc3QgZWxpZ2libGVUb2tlbklkcyA9IG5ldyBTZXQ8bnVtYmVyPigpO1xuICAgIGNvbnN0IG92ZXJUaHJlc2hvbGRUb2tlbnM6IEFycmF5PHsgdG9rZW5OYW1lOiBzdHJpbmc7IHRocmVzaG9sZDogbnVtYmVyIH0+ID0gW107XG4gICAgbGV0IHRocmVzaG9sZGVkVG9rZW5Db3VudCA9IDA7XG5cbiAgICBjb25zdCBlbnRyaWVzID0gQXJyYXkuZnJvbShieVRva2VuLmVudHJpZXMoKSk7XG4gICAgY29uc3QgY2hlY2tzID0gYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKFxuICAgICAgZW50cmllcy5tYXAoYXN5bmMgKFt0b2tlbklkLCB0b2tlbk5hbWVdKSA9PiB7XG4gICAgICAgIGlmIChleGNsdWRlZFRva2VuSWRzLmhhcyh0b2tlbklkKSkge1xuICAgICAgICAgIHRocmVzaG9sZGVkVG9rZW5Db3VudCsrO1xuICAgICAgICAgIHJldHVybiB7IHRva2VuSWQsIHRva2VuTmFtZSwgZWxpZ2libGU6IGZhbHNlIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLmhhc1F1b3RhVGhyZXNob2xkKHRva2VuSWQpKSB7XG4gICAgICAgICAgcmV0dXJuIHsgdG9rZW5JZCwgdG9rZW5OYW1lLCBlbGlnaWJsZTogdHJ1ZSB9O1xuICAgICAgICB9XG4gICAgICAgIHRocmVzaG9sZGVkVG9rZW5Db3VudCsrO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHRva2VuSWQsXG4gICAgICAgICAgdG9rZW5OYW1lLFxuICAgICAgICAgIGVsaWdpYmxlOiBhd2FpdCB0aGlzLmlzVG9rZW5RdW90YUVsaWdpYmxlKHRva2VuSWQsIHRva2VuTmFtZSksXG4gICAgICAgIH07XG4gICAgICB9KSxcbiAgICApO1xuXG4gICAgY2hlY2tzLmZvckVhY2goKGNoZWNrLCBpbmRleCkgPT4ge1xuICAgICAgaWYgKGNoZWNrLnN0YXR1cyA9PT0gXCJmdWxmaWxsZWRcIikge1xuICAgICAgICBpZiAoY2hlY2sudmFsdWUuZWxpZ2libGUpIHtcbiAgICAgICAgICBlbGlnaWJsZVRva2VuSWRzLmFkZChjaGVjay52YWx1ZS50b2tlbklkKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zdCB0aHJlc2hvbGQgPSB0aGlzLmdldFF1b3RhVGhyZXNob2xkKGNoZWNrLnZhbHVlLnRva2VuSWQpO1xuICAgICAgICAgIGlmICh0aHJlc2hvbGQgIT09IHVuZGVmaW5lZCAmJiB0aHJlc2hvbGQgIT09IG51bGwpIHtcbiAgICAgICAgICAgIG92ZXJUaHJlc2hvbGRUb2tlbnMucHVzaCh7IHRva2VuTmFtZTogY2hlY2sudmFsdWUudG9rZW5OYW1lLCB0aHJlc2hvbGQgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZW50cnkgPSBlbnRyaWVzW2luZGV4XTtcbiAgICAgIGlmIChlbnRyeSkge1xuICAgICAgICBjb25zdCBbdG9rZW5JZCwgdG9rZW5OYW1lXSA9IGVudHJ5O1xuICAgICAgICB0aGlzLmxvZ1F1b3RhTG9va3VwRmFpbE9wZW4odG9rZW5JZCwgdG9rZW5OYW1lLCBTdHJpbmcoY2hlY2sucmVhc29uKSk7XG4gICAgICAgIGVsaWdpYmxlVG9rZW5JZHMuYWRkKHRva2VuSWQpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHsgcmVhZHlBY3RpdmVUb2tlbklkcywgZWxpZ2libGVUb2tlbklkcywgb3ZlclRocmVzaG9sZFRva2VucywgdGhyZXNob2xkZWRUb2tlbkNvdW50IH07XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzV29ya2VyRWxpZ2libGVGb3JRdWV1ZUl0ZW0oXG4gICAgd29ya2VyOiBDb2RleEFwcFNlcnZlcldvcmtlcixcbiAgICBpdGVtOiBRdWV1ZUl0ZW0sXG4gICk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGlmIChpdGVtLmV4Y2x1ZGVkVG9rZW5JZHMuaGFzKHdvcmtlci50b2tlbklkKSkgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiB0aGlzLmlzVG9rZW5RdW90YUVsaWdpYmxlKHdvcmtlci50b2tlbklkLCB3b3JrZXIudG9rZW5OYW1lKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNUb2tlblF1b3RhRWxpZ2libGUoXG4gICAgdG9rZW5JZDogbnVtYmVyLFxuICAgIHRva2VuTmFtZTogc3RyaW5nLFxuICAgIGV4Y2x1ZGVkVG9rZW5JZHM/OiBTZXQ8bnVtYmVyPixcbiAgKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgY29uc3QgdGhyZXNob2xkID0gdGhpcy5nZXRRdW90YVRocmVzaG9sZCh0b2tlbklkKTtcbiAgICBpZiAodGhyZXNob2xkID09PSB1bmRlZmluZWQgfHwgdGhyZXNob2xkID09PSBudWxsKSByZXR1cm4gdHJ1ZTtcblxuICAgIGxldCByZXN1bHQ6IE9wZW5BSVF1b3RhVXNhZ2VSZXN1bHQ7XG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IGF3YWl0IHJlYWRPcGVuQUlRdW90YVVzYWdlKCgpID0+IHRoaXMuZ2V0UmF0ZUxpbWl0c0J5VG9rZW5JZCh0b2tlbklkKSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhpcy5sb2dRdW90YUxvb2t1cEZhaWxPcGVuKHRva2VuSWQsIHRva2VuTmFtZSwgKGUgYXMgRXJyb3IpLm1lc3NhZ2UpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgaWYgKHJlc3VsdC5raW5kID09PSBcImxvb2t1cF9mYWlsZWRcIikge1xuICAgICAgdGhpcy5sb2dRdW90YUxvb2t1cEZhaWxPcGVuKHRva2VuSWQsIHRva2VuTmFtZSwgcmVzdWx0LnJlYXNvbik7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAocmVzdWx0LnV0aWxpemF0aW9uUGN0ID49IHRocmVzaG9sZCkge1xuICAgICAgdGhpcy5sb2dRdW90YU92ZXJUaHJlc2hvbGQodG9rZW5JZCwgdG9rZW5OYW1lLCB0aHJlc2hvbGQsIHJlc3VsdCk7XG4gICAgICBleGNsdWRlZFRva2VuSWRzPy5hZGQodG9rZW5JZCk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBwcml2YXRlIGxvZ1F1b3RhT3ZlclRocmVzaG9sZChcbiAgICB0b2tlbklkOiBudW1iZXIsXG4gICAgdG9rZW5OYW1lOiBzdHJpbmcsXG4gICAgdGhyZXNob2xkOiBudW1iZXIsXG4gICAgcmVzdWx0OiBFeHRyYWN0PE9wZW5BSVF1b3RhVXNhZ2VSZXN1bHQsIHsga2luZDogXCJva1wiIH0+LFxuICApOiB2b2lkIHtcbiAgICBsb2dnZXIuaW5mbyhcInF1b3RhX3RocmVzaG9sZCBnYXRlOiBvdmVyX3RocmVzaG9sZFwiLCB7XG4gICAgICB0b2tlbklkLFxuICAgICAgdG9rZW5OYW1lLFxuICAgICAgcHJvdmlkZXI6IFwib3BlbmFpXCIsXG4gICAgICB0aHJlc2hvbGQsXG4gICAgICBjYWNoZWRVdGlsaXphdGlvbjogcmVzdWx0LnV0aWxpemF0aW9uUGN0LFxuICAgICAgY2FjaGVBZ2U6IHJlc3VsdC5jYWNoZUFnZU1zLFxuICAgICAgd2luZG93RHVyYXRpb25NaW5zOiByZXN1bHQud2luZG93RHVyYXRpb25NaW5zLFxuICAgICAgcmVzZXRzQXQ6IHJlc3VsdC5yZXNldHNBdCxcbiAgICAgIGxpbWl0SWQ6IHJlc3VsdC5saW1pdElkLFxuICAgICAgcmVhc29uOiBcIm92ZXJfdGhyZXNob2xkXCIsXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGxvZ1F1b3RhTG9va3VwRmFpbE9wZW4odG9rZW5JZDogbnVtYmVyLCB0b2tlbk5hbWU6IHN0cmluZywgcmVhc29uOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCB0aHJlc2hvbGQgPSB0aGlzLmdldFF1b3RhVGhyZXNob2xkKHRva2VuSWQpO1xuICAgIGxvZ2dlci53YXJuKFwicXVvdGFfdGhyZXNob2xkIGdhdGU6IGxvb2t1cF9mYWlsX29wZW5cIiwge1xuICAgICAgdG9rZW5JZCxcbiAgICAgIHRva2VuTmFtZSxcbiAgICAgIHByb3ZpZGVyOiBcIm9wZW5haVwiLFxuICAgICAgdGhyZXNob2xkLFxuICAgICAgcmVhc29uOiBcImxvb2t1cF9mYWlsX29wZW5cIixcbiAgICAgIGxvb2t1cFJlYXNvbjogcmVhc29uLFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSB0aHJvd1F1b3RhVGhyZXNob2xkRXhjZWVkZWQoZWxpZ2liaWxpdHk6IFRva2VuRWxpZ2liaWxpdHkpOiBuZXZlciB7XG4gICAgbG9nZ2VyLndhcm4oXCJxdW90YV90aHJlc2hvbGQgZ2F0ZTogYWxsX2V4Y2VlZGVkXCIsIHtcbiAgICAgIHByb3ZpZGVyOiBcIm9wZW5haVwiLFxuICAgICAgdG9rZW5Db3VudDogZWxpZ2liaWxpdHkucmVhZHlBY3RpdmVUb2tlbklkcy5zaXplLFxuICAgICAgdGhyZXNob2xkZWRUb2tlbkNvdW50OiBlbGlnaWJpbGl0eS50aHJlc2hvbGRlZFRva2VuQ291bnQsXG4gICAgICBvdmVyVGhyZXNob2xkVG9rZW5zOiBlbGlnaWJpbGl0eS5vdmVyVGhyZXNob2xkVG9rZW5zLFxuICAgICAgcmVhc29uOiBcImFsbF9leGNlZWRlZFwiLFxuICAgIH0pO1xuICAgIHRocm93IG5ldyBRdW90YVRocmVzaG9sZEV4Y2VlZGVkRXJyb3IoXG4gICAgICBxdW90YVRocmVzaG9sZEV4Y2VlZGVkTWVzc2FnZShcIm9wZW5haVwiLCBlbGlnaWJpbGl0eS5vdmVyVGhyZXNob2xkVG9rZW5zKSxcbiAgICApO1xuICB9XG5cbiAgLy8g4pSA4pSAIEJyb3dzZXIgbG9naW4gZmxvdyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBwZW5kaW5nTG9naW46IHtcbiAgICB3b3JrZXI6IENvZGV4QXBwU2VydmVyV29ya2VyO1xuICAgIG5hbWU6IHN0cmluZztcbiAgICB0aW1lcjogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0VGltZW91dD47XG4gIH0gfCBudWxsID0gbnVsbDtcblxuICBhc3luYyBzdGFydEJyb3dzZXJMb2dpbihuYW1lOiBzdHJpbmcpOiBQcm9taXNlPHsgYXV0aFVybDogc3RyaW5nIH0+IHtcbiAgICBpZiAodGhpcy5wZW5kaW5nTG9naW4pIHtcbiAgICAgIHRoaXMucGVuZGluZ0xvZ2luLndvcmtlci5raWxsKCkuY2F0Y2goKCkgPT4ge30pO1xuICAgICAgY2xlYXJUaW1lb3V0KHRoaXMucGVuZGluZ0xvZ2luLnRpbWVyKTtcbiAgICAgIHRoaXMucGVuZGluZ0xvZ2luID0gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCB0ZW1wSWQgPSBEYXRlLm5vdygpO1xuICAgIGNvbnN0IHdvcmtlciA9IG5ldyBDb2RleEFwcFNlcnZlcldvcmtlcih7XG4gICAgICB0b2tlbklkOiB0ZW1wSWQsXG4gICAgICB0b2tlbk5hbWU6IG5hbWUsXG4gICAgICBhY2Nlc3NUb2tlbjogXCJcIixcbiAgICAgIGFjY291bnRJZDogXCJcIixcbiAgICB9KTtcblxuICAgIGNvbnN0IGF1dGhVcmwgPSBhd2FpdCB3b3JrZXIuc3RhcnRCcm93c2VyTG9naW4oKTtcblxuICAgIGNvbnN0IHRpbWVyID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICBpZiAodGhpcy5wZW5kaW5nTG9naW4/LndvcmtlciA9PT0gd29ya2VyKSB7XG4gICAgICAgIGxvZ2dlci53YXJuKGBicm93c2VyIGxvZ2luIHRpbWVvdXQgZm9yICR7bmFtZX0sIGtpbGxpbmcgd29ya2VyYCk7XG4gICAgICAgIHdvcmtlci5raWxsKCkuY2F0Y2goKCkgPT4ge30pO1xuICAgICAgICB0aGlzLnBlbmRpbmdMb2dpbiA9IG51bGw7XG4gICAgICB9XG4gICAgfSwgMzAwXzAwMCk7XG5cbiAgICB0aGlzLnBlbmRpbmdMb2dpbiA9IHsgd29ya2VyLCBuYW1lLCB0aW1lciB9O1xuICAgIHJldHVybiB7IGF1dGhVcmwgfTtcbiAgfVxuXG4gIGdldCBwZW5kaW5nTG9naW5OYW1lKCk6IHN0cmluZyB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLnBlbmRpbmdMb2dpbj8ubmFtZSA/PyBudWxsO1xuICB9XG5cbiAgYXN5bmMgY29tcGxldGVCcm93c2VyTG9naW4oKTogUHJvbWlzZTx7XG4gICAgYWNjZXNzVG9rZW46IHN0cmluZztcbiAgICByZWZyZXNoVG9rZW46IHN0cmluZztcbiAgICBpZFRva2VuPzogc3RyaW5nO1xuICAgIGFjY291bnRJZDogc3RyaW5nO1xuICB9PiB7XG4gICAgaWYgKCF0aGlzLnBlbmRpbmdMb2dpbikgdGhyb3cgbmV3IEVycm9yKFwibm8gcGVuZGluZyBsb2dpblwiKTtcbiAgICBjb25zdCB7IHdvcmtlciwgdGltZXIgfSA9IHRoaXMucGVuZGluZ0xvZ2luO1xuXG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHdvcmtlci53YWl0Rm9yQnJvd3NlckxvZ2luQ29tcGxldGUoKTtcbiAgICAgIGNvbnN0IGNyZWRzID0gYXdhaXQgd29ya2VyLnJlYWRNYW5hZ2VkQ3JlZGVudGlhbHMoKTtcbiAgICAgIGlmICghY3JlZHMpIHRocm93IG5ldyBFcnJvcihcImZhaWxlZCB0byByZWFkIGNyZWRlbnRpYWxzIGFmdGVyIGxvZ2luXCIpO1xuICAgICAgcmV0dXJuIGNyZWRzO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBjbGVhclRpbWVvdXQodGltZXIpO1xuICAgICAgdGhpcy5wZW5kaW5nTG9naW4gPSBudWxsO1xuICAgICAgYXdhaXQgd29ya2VyLmtpbGwoKS5jYXRjaCgoKSA9PiB7fSk7XG4gICAgfVxuICB9XG5cbiAgLy8g4pSA4pSAIFN0YXRzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIGdldCB3b3JrZXJDb3VudCgpOiBudW1iZXIge1xuICAgIHJldHVybiBbLi4udGhpcy53b3JrZXJQb29sLnZhbHVlcygpXS5mbGF0KCkubGVuZ3RoO1xuICB9XG5cbiAgZ2V0IHJlYWR5V29ya2VyQ291bnQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gWy4uLnRoaXMud29ya2VyUG9vbC52YWx1ZXMoKV0uZmxhdCgpLmZpbHRlcigodykgPT4gdy5pc1JlYWR5KS5sZW5ndGg7XG4gIH1cblxuICBnZXQgcXVldWVMZW5ndGgoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5xdWV1ZS5sZW5ndGg7XG4gIH1cbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztBQTRCQSxNQUFNLFNBQVMsVUFBVSxDQUFDLFNBQVMsb0JBQW9CLENBQUM7QUFFeEQsTUFBTSxpQkFBaUI7QUFFdkIsTUFBTSxvQkFBb0IsS0FBSyxJQUM3QixPQUFPLFFBQVEsSUFBSSwyQkFBMkIsRUFBRSxFQUZwQixFQUk3QjtBQUNELE1BQU0sbUJBQW1CO0FBQ3pCLE1BQU0saUJBQWlCO0FBQ3ZCLE1BQU0sb0JBQW9CO0FBRzFCLE1BQU0sdUJBQXVCLFFBQVEsSUFBSSw4QkFBOEI7QUFFdkUsTUFBTSx1QkFBdUI7QUFDN0IsTUFBTSx1QkFBdUI7QUFHN0IsU0FBUyxhQUFhLFNBQWlCLGFBQTZCO0FBQ2xFLFFBQU8sVUFBVSxLQUFLOztBQUd4QixTQUFTLE1BQU0sSUFBMkI7QUFDeEMsUUFBTyxJQUFJLFNBQVMsWUFBWSxXQUFXLFNBQVMsR0FBRyxDQUFDOztBQUcxRCxTQUFTLDhCQUNQLFVBQ0EsUUFDUTtDQUNSLE1BQU0sVUFBVSxPQUNiLEtBQUssVUFBVSxHQUFHLE1BQU0sVUFB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
|