@cartanova/qgrid-cli 2.6.9 → 2.6.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/dist/application/qgrid/qgrid-run-lifecycle.js +137 -60
- package/bundle/dist/application/qgrid/qgrid.frame.js +5 -2
- package/bundle/dist/application/setting/setting.model.js +65 -3
- package/bundle/dist/application/setting/setting.types.js +13 -3
- package/bundle/dist/i18n/en.js +3 -1
- package/bundle/dist/i18n/ko.js +3 -1
- package/bundle/dist/utils/process-supervisor.js +22 -0
- package/bundle/dist/utils/server-restart.js +61 -0
- package/bundle/src/application/qgrid/qgrid-oauth-redirect.test.ts +7 -0
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +113 -0
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.ts +172 -75
- package/bundle/src/application/qgrid/qgrid.frame.test.ts +45 -0
- package/bundle/src/application/qgrid/qgrid.frame.ts +4 -0
- package/bundle/src/application/setting/setting.model.test.ts +104 -0
- package/bundle/src/application/setting/setting.model.ts +75 -3
- package/bundle/src/application/setting/setting.types.ts +12 -0
- package/bundle/src/application/sonamu.generated.http +7 -0
- package/bundle/src/i18n/en.ts +3 -0
- package/bundle/src/i18n/ko.ts +3 -0
- package/bundle/src/server-error-handler.test.ts +15 -0
- package/bundle/src/utils/process-supervisor.test.ts +24 -0
- package/bundle/src/utils/process-supervisor.ts +17 -0
- package/bundle/src/utils/server-restart.test.ts +76 -0
- package/bundle/src/utils/server-restart.ts +68 -0
- package/bundle/web-dist/client/assets/index-CFvFRDk_.js +78 -0
- package/bundle/web-dist/client/assets/index-CJ9iTI_V.css +1 -0
- package/bundle/web-dist/client/assets/{logs-5gACO5tJ.js → logs-DeAK5Uyu.js} +1 -1
- package/bundle/web-dist/client/assets/{monit-DRCc50GU.js → monit-Rj94Sz3_.js} +1 -1
- package/bundle/web-dist/client/assets/{routes-DBdI9Ba1.js → routes-DVseTo6T.js} +1 -1
- package/bundle/web-dist/client/assets/{sd.generated-Bwa7rses.js → sd.generated-W6XqgWK6.js} +8 -8
- package/bundle/web-dist/client/assets/services.generated-Dz5pA5Fb.js +1 -0
- package/bundle/web-dist/client/assets/settings-DvuRDFfS.js +1 -0
- package/bundle/web-dist/client/assets/{show-BCRrSc8-.js → show-C7etBj89.js} +1 -1
- package/bundle/web-dist/client/assets/{tokens-CDiXKYGf.js → tokens-BroPe7Tn.js} +1 -1
- package/bundle/web-dist/client/assets/{use-oauth-login-flow-Qqg4koSg.js → use-oauth-login-flow-CuLvs_CW.js} +1 -1
- package/bundle/web-dist/client/index.html +3 -3
- package/bundle/web-dist/server/assets/{lazyRouteComponent-Ws7I6fL-.js → lazyRouteComponent-C-N6sd5N.js} +2 -2
- package/bundle/web-dist/server/assets/{logs-C1rxLh8H.js → logs-CVkeSr1S.js} +3 -3
- package/bundle/web-dist/server/assets/{monit-C8gx9Sar.js → monit-Bb6QfT9V.js} +3 -3
- package/bundle/web-dist/server/assets/{plus-BISXNqRU.js → plus-B8JRuCb9.js} +1 -1
- package/bundle/web-dist/server/assets/{react-dom-D7duWOwf.js → react-dom-ByF9tqTB.js} +1 -1
- package/bundle/web-dist/server/assets/{routes-ZW_Ih5Em.js → routes-Dnm-Eti6.js} +4 -4
- package/bundle/web-dist/server/assets/{sd.generated-LO-h1_16.js → sd.generated-CuyajYtc.js} +126 -116
- package/bundle/web-dist/server/assets/{services.generated-CZIChgHV.js → services.generated-BAGLi2r8.js} +9 -1
- package/bundle/web-dist/server/assets/{settings--aoatERH.js → settings-4T3nBfY8.js} +271 -39
- package/bundle/web-dist/server/assets/{show-BY27w9oi.js → show-CQw03iTP.js} +3 -3
- package/bundle/web-dist/server/assets/{tokens-DIObtTuZ.js → tokens-Di_SGPYj.js} +4 -4
- package/bundle/web-dist/server/assets/{use-oauth-login-flow-V3k8PSqQ.js → use-oauth-login-flow-DiYCMNAQ.js} +2 -2
- package/bundle/web-dist/server/entry-server.generated.js +10 -10
- package/dist/cli.js +93 -38
- package/package.json +1 -1
- package/skills/qgrid/references/cli-env-and-server-boot.md +34 -3
- package/skills/qgrid/references/decision-rationale.md +7 -0
- package/skills/qgrid/references/tool-calling-and-multiturn.md +21 -0
- package/bundle/web-dist/client/assets/index-DnnliAzf.js +0 -78
- package/bundle/web-dist/client/assets/index-rdbxJinT.css +0 -1
- package/bundle/web-dist/client/assets/services.generated-BzwTuZRP.js +0 -1
- package/bundle/web-dist/client/assets/settings-B62_r1i4.js +0 -1
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { SD } from "../../i18n/sd.generated.js";
|
|
2
|
+
import { isRestartPending } from "../../utils/server-restart.js";
|
|
1
3
|
import { estimateImageGenerationCostMicroUsd, imageGenerationCostMethod } from "./qgrid-image-generation.js";
|
|
2
4
|
import { buildImageGenerationToolSteps, formatResponseForLog, getImageParts } from "./qgrid-response-format.js";
|
|
3
5
|
import { RequestLogModel } from "../request-log/request-log.model.js";
|
|
6
|
+
import { ServiceUnavailableException } from "sonamu";
|
|
4
7
|
import { getLogger } from "@logtape/logtape";
|
|
5
8
|
//#region src/application/qgrid/qgrid-run-lifecycle.ts
|
|
6
9
|
const logger = getLogger(["qgrid", "run-lifecycle"]);
|
|
@@ -8,6 +11,35 @@ const STALE_RUN_THRESHOLD_MS = 1800 * 1e3;
|
|
|
8
11
|
const STALE_CLEANUP_INTERVAL_MS = 60 * 1e3;
|
|
9
12
|
let staleCleanupInFlight;
|
|
10
13
|
let lastStaleCleanupStartedAt = 0;
|
|
14
|
+
const activeNativeRunRefs = /* @__PURE__ */ new Map();
|
|
15
|
+
const interruptedNativeRunIds = /* @__PURE__ */ new Set();
|
|
16
|
+
const activeNativeFinalizers = /* @__PURE__ */ new Map();
|
|
17
|
+
function restartUnavailable() {
|
|
18
|
+
return new ServiceUnavailableException(SD("qgrid.restartPending")());
|
|
19
|
+
}
|
|
20
|
+
function registerNativeRun(requestLogId) {
|
|
21
|
+
activeNativeRunRefs.set(requestLogId, (activeNativeRunRefs.get(requestLogId) ?? 0) + 1);
|
|
22
|
+
}
|
|
23
|
+
function releaseNativeRun(requestLogId) {
|
|
24
|
+
const refs = activeNativeRunRefs.get(requestLogId);
|
|
25
|
+
if (refs === void 0 || refs <= 1) activeNativeRunRefs.delete(requestLogId);
|
|
26
|
+
else activeNativeRunRefs.set(requestLogId, refs - 1);
|
|
27
|
+
}
|
|
28
|
+
function trackNativeFinalizer(requestLogId, finalize) {
|
|
29
|
+
const operation = finalize();
|
|
30
|
+
const settled = operation.then(() => void 0, () => void 0);
|
|
31
|
+
const finalizers = activeNativeFinalizers.get(requestLogId) ?? /* @__PURE__ */ new Set();
|
|
32
|
+
finalizers.add(settled);
|
|
33
|
+
activeNativeFinalizers.set(requestLogId, finalizers);
|
|
34
|
+
settled.then(() => {
|
|
35
|
+
finalizers.delete(settled);
|
|
36
|
+
if (finalizers.size === 0) activeNativeFinalizers.delete(requestLogId);
|
|
37
|
+
});
|
|
38
|
+
return operation;
|
|
39
|
+
}
|
|
40
|
+
function assertNativeRunAdmission() {
|
|
41
|
+
if (isRestartPending()) throw restartUnavailable();
|
|
42
|
+
}
|
|
11
43
|
function withProviderPrefix(routeModel, model) {
|
|
12
44
|
if (!model) return void 0;
|
|
13
45
|
if (model.includes("/")) return model;
|
|
@@ -38,6 +70,7 @@ function filterHistoryForStorage(rawHistory) {
|
|
|
38
70
|
* 2) afterQuery: generate step + tool-call step + finish/keep-open
|
|
39
71
|
*/
|
|
40
72
|
async function beforeQuery(args) {
|
|
73
|
+
assertNativeRunAdmission();
|
|
41
74
|
let requestLogId;
|
|
42
75
|
let stepIndex = 0;
|
|
43
76
|
if (args.runContext?.requestLogId !== void 0) {
|
|
@@ -57,79 +90,123 @@ async function beforeQuery(args) {
|
|
|
57
90
|
is_image_generation: args.imageGeneration
|
|
58
91
|
});
|
|
59
92
|
}
|
|
93
|
+
if (isRestartPending()) {
|
|
94
|
+
await finishTerminalRun(requestLogId, "error", "server restarted");
|
|
95
|
+
throw restartUnavailable();
|
|
96
|
+
}
|
|
97
|
+
registerNativeRun(requestLogId);
|
|
60
98
|
return {
|
|
61
99
|
requestLogId,
|
|
62
100
|
stepIndex
|
|
63
101
|
};
|
|
64
102
|
}
|
|
65
103
|
async function afterQuery(requestLogId, stepIndex, args, result) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
model_name: servedModelName,
|
|
72
|
-
requested_model_name: requestedModelName,
|
|
73
|
-
fallback_count: result.modelFallbacks?.length ?? 0,
|
|
74
|
-
input_tokens: result.usage.input_tokens,
|
|
75
|
-
output_tokens: result.usage.output_tokens,
|
|
76
|
-
cache_read_tokens: result.usage.cache_read_input_tokens,
|
|
77
|
-
cache_creation_tokens: result.usage.cache_creation_input_tokens,
|
|
78
|
-
cache_creation_5m_tokens: result.usage.cache_creation_5m_input_tokens,
|
|
79
|
-
cache_creation_1h_tokens: result.usage.cache_creation_1h_input_tokens,
|
|
80
|
-
cost_usd: Math.round(result.costUsd * 1e6),
|
|
81
|
-
cost_source: result.costSource,
|
|
82
|
-
duration_ms: result.durationMs,
|
|
83
|
-
ttft_ms: result.ttftMs,
|
|
84
|
-
finish_reason: result.finishReason
|
|
85
|
-
});
|
|
86
|
-
const imageParts = getImageParts(result);
|
|
87
|
-
const imageCostMicroUsd = estimateImageGenerationCostMicroUsd(result, args.imageGenerationOptions);
|
|
88
|
-
for (const step of buildImageGenerationToolSteps(args, imageParts, stepIndex)) await RequestLogModel.appendStep(requestLogId, step);
|
|
89
|
-
if (result.finishReason === "tool-calls") {
|
|
90
|
-
const toolCalls = result.content.filter((c) => c.type === "tool-call");
|
|
91
|
-
for (let i = 0; i < toolCalls.length; i++) {
|
|
92
|
-
const tc = toolCalls[i];
|
|
93
|
-
if (tc.type !== "tool-call") continue;
|
|
104
|
+
if (interruptedNativeRunIds.has(requestLogId)) return {};
|
|
105
|
+
return trackNativeFinalizer(requestLogId, async () => {
|
|
106
|
+
try {
|
|
107
|
+
const requestedModelName = withProviderPrefix(args.model, args.model ?? result.requestedModel ?? result.model);
|
|
108
|
+
const servedModelName = withProviderPrefix(args.model, result.model);
|
|
94
109
|
await RequestLogModel.appendStep(requestLogId, {
|
|
95
110
|
step_index: stepIndex,
|
|
96
|
-
type: "
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
111
|
+
type: "generate",
|
|
112
|
+
model_name: servedModelName,
|
|
113
|
+
requested_model_name: requestedModelName,
|
|
114
|
+
fallback_count: result.modelFallbacks?.length ?? 0,
|
|
115
|
+
input_tokens: result.usage.input_tokens,
|
|
116
|
+
output_tokens: result.usage.output_tokens,
|
|
117
|
+
cache_read_tokens: result.usage.cache_read_input_tokens,
|
|
118
|
+
cache_creation_tokens: result.usage.cache_creation_input_tokens,
|
|
119
|
+
cache_creation_5m_tokens: result.usage.cache_creation_5m_input_tokens,
|
|
120
|
+
cache_creation_1h_tokens: result.usage.cache_creation_1h_input_tokens,
|
|
121
|
+
cost_usd: Math.round(result.costUsd * 1e6),
|
|
122
|
+
cost_source: result.costSource,
|
|
123
|
+
duration_ms: result.durationMs,
|
|
124
|
+
ttft_ms: result.ttftMs,
|
|
125
|
+
finish_reason: result.finishReason
|
|
126
|
+
});
|
|
127
|
+
const imageParts = getImageParts(result);
|
|
128
|
+
const imageCostMicroUsd = estimateImageGenerationCostMicroUsd(result, args.imageGenerationOptions);
|
|
129
|
+
for (const step of buildImageGenerationToolSteps(args, imageParts, stepIndex)) await RequestLogModel.appendStep(requestLogId, step);
|
|
130
|
+
if (result.finishReason === "tool-calls") {
|
|
131
|
+
const toolCalls = result.content.filter((c) => c.type === "tool-call");
|
|
132
|
+
for (let i = 0; i < toolCalls.length; i++) {
|
|
133
|
+
const tc = toolCalls[i];
|
|
134
|
+
if (tc.type !== "tool-call") continue;
|
|
135
|
+
await RequestLogModel.appendStep(requestLogId, {
|
|
136
|
+
step_index: stepIndex,
|
|
137
|
+
type: "tool_call",
|
|
138
|
+
tool_call_index: imageParts.length + i,
|
|
139
|
+
tool_call_id: tc.toolCallId,
|
|
140
|
+
tool_name: tc.toolName,
|
|
141
|
+
tool_args: tc.input
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
return { runContext: { requestLogId } };
|
|
145
|
+
}
|
|
146
|
+
const agg = await RequestLogModel.aggregateStepUsage(requestLogId);
|
|
147
|
+
await RequestLogModel.finishRun(requestLogId, {
|
|
148
|
+
status: "succeeded",
|
|
149
|
+
response: formatResponseForLog(result),
|
|
150
|
+
token_name: result.tokenName,
|
|
151
|
+
input_tokens: agg.input_tokens,
|
|
152
|
+
output_tokens: agg.output_tokens,
|
|
153
|
+
cache_read_tokens: agg.cache_read_tokens,
|
|
154
|
+
cache_creation_tokens: agg.cache_creation_tokens,
|
|
155
|
+
cache_creation_5m_tokens: agg.cache_creation_5m_tokens,
|
|
156
|
+
cache_creation_1h_tokens: agg.cache_creation_1h_tokens,
|
|
157
|
+
duration_ms: agg.duration_ms,
|
|
158
|
+
requested_model_name: requestedModelName,
|
|
159
|
+
model_name: servedModelName,
|
|
160
|
+
fallback_count: agg.fallback_count,
|
|
161
|
+
cost_usd: agg.cost_usd,
|
|
162
|
+
cost_source: agg.cost_source,
|
|
163
|
+
image_cost_usd: imageCostMicroUsd,
|
|
164
|
+
image_cost_method: imageCostMicroUsd !== null ? imageGenerationCostMethod(args.imageGenerationOptions) : null,
|
|
165
|
+
history: filterHistoryForStorage(args.history)
|
|
101
166
|
});
|
|
167
|
+
return {};
|
|
168
|
+
} finally {
|
|
169
|
+
releaseNativeRun(requestLogId);
|
|
102
170
|
}
|
|
103
|
-
return { runContext: { requestLogId } };
|
|
104
|
-
}
|
|
105
|
-
const agg = await RequestLogModel.aggregateStepUsage(requestLogId);
|
|
106
|
-
await RequestLogModel.finishRun(requestLogId, {
|
|
107
|
-
status: "succeeded",
|
|
108
|
-
response: formatResponseForLog(result),
|
|
109
|
-
token_name: result.tokenName,
|
|
110
|
-
input_tokens: agg.input_tokens,
|
|
111
|
-
output_tokens: agg.output_tokens,
|
|
112
|
-
cache_read_tokens: agg.cache_read_tokens,
|
|
113
|
-
cache_creation_tokens: agg.cache_creation_tokens,
|
|
114
|
-
cache_creation_5m_tokens: agg.cache_creation_5m_tokens,
|
|
115
|
-
cache_creation_1h_tokens: agg.cache_creation_1h_tokens,
|
|
116
|
-
duration_ms: agg.duration_ms,
|
|
117
|
-
requested_model_name: requestedModelName,
|
|
118
|
-
model_name: servedModelName,
|
|
119
|
-
fallback_count: agg.fallback_count,
|
|
120
|
-
cost_usd: agg.cost_usd,
|
|
121
|
-
cost_source: agg.cost_source,
|
|
122
|
-
image_cost_usd: imageCostMicroUsd,
|
|
123
|
-
image_cost_method: imageCostMicroUsd !== null ? imageGenerationCostMethod(args.imageGenerationOptions) : null,
|
|
124
|
-
history: filterHistoryForStorage(args.history)
|
|
125
171
|
});
|
|
126
|
-
return {};
|
|
127
172
|
}
|
|
128
173
|
async function finishRunWithError(requestLogId, errorMessage, args) {
|
|
129
|
-
|
|
174
|
+
if (interruptedNativeRunIds.has(requestLogId)) return;
|
|
175
|
+
return trackNativeFinalizer(requestLogId, async () => {
|
|
176
|
+
try {
|
|
177
|
+
await finishTerminalRun(requestLogId, "error", errorMessage, args);
|
|
178
|
+
} finally {
|
|
179
|
+
releaseNativeRun(requestLogId);
|
|
180
|
+
}
|
|
181
|
+
});
|
|
130
182
|
}
|
|
131
183
|
async function finishRunAborted(requestLogId, args) {
|
|
132
|
-
|
|
184
|
+
if (interruptedNativeRunIds.has(requestLogId)) return;
|
|
185
|
+
return trackNativeFinalizer(requestLogId, async () => {
|
|
186
|
+
try {
|
|
187
|
+
await finishTerminalRun(requestLogId, "aborted", "client disconnected", args);
|
|
188
|
+
} finally {
|
|
189
|
+
releaseNativeRun(requestLogId);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
/** 현재 이 프로세스가 provider를 실행 중인 native run만 재시작 오류로 마감한다. */
|
|
194
|
+
async function finishActiveNativeRunsForRestart() {
|
|
195
|
+
const requestLogIds = [...activeNativeRunRefs.keys()];
|
|
196
|
+
for (const requestLogId of requestLogIds) {
|
|
197
|
+
interruptedNativeRunIds.add(requestLogId);
|
|
198
|
+
activeNativeRunRefs.delete(requestLogId);
|
|
199
|
+
}
|
|
200
|
+
await Promise.all(requestLogIds.map(async (requestLogId) => {
|
|
201
|
+
await Promise.all(activeNativeFinalizers.get(requestLogId) ?? []);
|
|
202
|
+
await finishTerminalRun(requestLogId, "error", "server restarted");
|
|
203
|
+
}));
|
|
204
|
+
}
|
|
205
|
+
/** 프로세스 전역 registry를 격리해야 하는 단위 테스트 전용. */
|
|
206
|
+
function resetNativeRunRegistryForTests() {
|
|
207
|
+
activeNativeRunRefs.clear();
|
|
208
|
+
interruptedNativeRunIds.clear();
|
|
209
|
+
activeNativeFinalizers.clear();
|
|
133
210
|
}
|
|
134
211
|
async function finishTerminalRun(requestLogId, status, errorMessage, args) {
|
|
135
212
|
try {
|
|
@@ -185,6 +262,6 @@ async function performStaleRunCleanup() {
|
|
|
185
262
|
}
|
|
186
263
|
}
|
|
187
264
|
//#endregion
|
|
188
|
-
export { afterQuery, beforeQuery, finishRunAborted, finishRunWithError };
|
|
265
|
+
export { afterQuery, assertNativeRunAdmission, beforeQuery, finishActiveNativeRunsForRestart, finishRunAborted, finishRunWithError, resetNativeRunRegistryForTests };
|
|
189
266
|
|
|
190
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicWdyaWQtcnVuLWxpZmVjeWNsZS5qcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBwbGljYXRpb24vcWdyaWQvcWdyaWQtcnVuLWxpZmVjeWNsZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBnZXRMb2dnZXIgfSBmcm9tIFwiQGxvZ3RhcGUvbG9ndGFwZVwiO1xuXG5pbXBvcnQgeyBSZXF1ZXN0TG9nTW9kZWwgfSBmcm9tIFwiLi4vcmVxdWVzdC1sb2cvcmVxdWVzdC1sb2cubW9kZWxcIjtcbmltcG9ydCB7XG4gIGVzdGltYXRlSW1hZ2VHZW5lcmF0aW9uQ29zdE1pY3JvVXNkLFxuICBpbWFnZUdlbmVyYXRpb25Db3N0TWV0aG9kLFxufSBmcm9tIFwiLi9xZ3JpZC1pbWFnZS1nZW5lcmF0aW9uXCI7XG5pbXBvcnQge1xuICBidWlsZEltYWdlR2VuZXJhdGlvblRvb2xTdGVwcyxcbiAgZm9ybWF0UmVzcG9uc2VGb3JMb2csXG4gIGdldEltYWdlUGFydHMsXG59IGZyb20gXCIuL3FncmlkLXJlc3BvbnNlLWZvcm1hdFwiO1xuaW1wb3J0IHsgdHlwZSBRZ3JpZFJ1bkNvbnRleHQsIHR5cGUgUXVlcnlJbnB1dCwgdHlwZSBRdWVyeU91dHB1dCB9IGZyb20gXCIuL3FncmlkLnR5cGVzXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGdldExvZ2dlcihbXCJxZ3JpZFwiLCBcInJ1bi1saWZlY3ljbGVcIl0pO1xuY29uc3QgU1RBTEVfUlVOX1RIUkVTSE9MRF9NUyA9IDMwICogNjAgKiAxMDAwO1xuY29uc3QgU1RBTEVfQ0xFQU5VUF9JTlRFUlZBTF9NUyA9IDYwICogMTAwMDtcbmxldCBzdGFsZUNsZWFudXBJbkZsaWdodDogUHJvbWlzZTx2b2lkPiB8IHVuZGVmaW5lZDtcbmxldCBsYXN0U3RhbGVDbGVhbnVwU3RhcnRlZEF0ID0gMDtcblxuZnVuY3Rpb24gd2l0aFByb3ZpZGVyUHJlZml4KFxuICByb3V0ZU1vZGVsOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gIG1vZGVsOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBpZiAoIW1vZGVsKSByZXR1cm4gdW5kZWZpbmVkO1xuICBpZiAobW9kZWwuaW5jbHVkZXMoXCIvXCIpKSByZXR1cm4gbW9kZWw7XG4gIGNvbnN0IHNsYXNoID0gcm91dGVNb2RlbD8uaW5kZXhPZihcIi9cIikgPz8gLTE7XG4gIGNvbnN0IHByb3ZpZGVyID0gc2xhc2ggPiAwID8gcm91dGVNb2RlbD8uc2xpY2UoMCwgc2xhc2gpIDogdW5kZWZpbmVkO1xuICByZXR1cm4gcHJvdmlkZXIgPyBgJHtwcm92aWRlcn0vJHttb2RlbH1gIDogbW9kZWw7XG59XG5cbi8qKlxuICogaGlzdG9yeeuKlCDsm5Drs7gg6re464yA66GcIOyggOyepe2VmOq4sOuztOuLpOuKlCwgcnVuIOu2hOyEneyXkCDtlYTsmpTtlZwgdXNlci9hc3Npc3RhbnQg7KCV67O066eMIO2VhO2EsOunge2VtOyEnCDsoIDsnqVcbiAqL1xuZnVuY3Rpb24gZmlsdGVySGlzdG9yeUZvclN0b3JhZ2UocmF3SGlzdG9yeTogc3RyaW5nIHwgdW5kZWZpbmVkKTogdW5rbm93biB7XG4gIGlmICghcmF3SGlzdG9yeSkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgdHJ5IHtcbiAgICBjb25zdCBpdGVtcyA9IEpTT04ucGFyc2UocmF3SGlzdG9yeSkgYXMgdW5rbm93bltdO1xuICAgIGNvbnN0IGZpbHRlcmVkID0gaXRlbXMuZmlsdGVyKChpdGVtKSA9PiB7XG4gICAgICBpZiAoIWl0ZW0gfHwgdHlwZW9mIGl0ZW0gIT09IFwib2JqZWN0XCIpIHJldHVybiBmYWxzZTtcbiAgICAgIGNvbnN0IHJlY29yZCA9IGl0ZW0gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgICByZXR1cm4gcmVjb3JkLnR5cGUgPT09IFwibWVzc2FnZVwiICYmIChyZWNvcmQucm9sZSA9PT0gXCJ1c2VyXCIgfHwgcmVjb3JkLnJvbGUgPT09IFwiYXNzaXN0YW50XCIpO1xuICAgIH0pO1xuICAgIHJldHVybiBmaWx0ZXJlZC5sZW5ndGggPiAwID8gZmlsdGVyZWQgOiB1bmRlZmluZWQ7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn1cblxuZXhwb3J0IHR5cGUgUnVuTGlmZWN5Y2xlUmVzdWx0ID0ge1xuICBydW5Db250ZXh0PzogUWdyaWRSdW5Db250ZXh0O1xufTtcblxuLyoqXG4gKiBsb2dnZXItZW5hYmxlZCBxdWVyeS9zdHJlYW0g7J2R64u1IOyghO2bhOyXkCDtmLjstpwuXG4gKlxuICogMSkgYmVmb3JlUXVlcnk6IHJ1biDsg53shLEv6rOE7IaNICsgdG9vbCByZXN1bHQg7JmE66OMICsgc3RhbGUgdG9vbC13YWl0IGNsZWFudXBcbiAqIDIpIGFmdGVyUXVlcnk6IGdlbmVyYXRlIHN0ZXAgKyB0b29sLWNhbGwgc3RlcCArIGZpbmlzaC9rZWVwLW9wZW5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGJlZm9yZVF1ZXJ5KGFyZ3M6IFF1ZXJ5SW5wdXQpOiBQcm9taXNlPHtcbiAgcmVxdWVzdExvZ0lkOiBudW1iZXI7XG4gIHN0ZXBJbmRleDogbnVtYmVyO1xufT4ge1xuICBsZXQgcmVxdWVzdExvZ0lkOiBudW1iZXI7XG4gIGxldCBzdGVwSW5kZXggPSAwO1xuXG4gIC8vIHJlcXVlc3RMb2dJZCDqsIAg7J6I7J2EIOuVjOunjCDquLDsobQgcnVuIOyXsOyepS4gdGhyZWFkQ29vcmQg66eMIOyeiOuKlCBjb252IOuKlCDsg4ggcnVuIOycvOuhnCDsi5zsnpEuXG4gIC8vIGNvbnRpbnVhdGlvbiDsnYAgY3JlYXRlUnVuIOydhCDqsbTrhIjrm7Drr4DroZwgcnVuIOydmCB0b29scyDripQg7LKrIOyKpO2FnSDsnqXssKnrtoTsnLzroZwg6rOg7KCV65Cc64ukIOKAlFxuICAvLyBBSSBTREsgcHJlcGFyZVN0ZXAvYWN0aXZlVG9vbHMg66GcIOyKpO2FneuniOuLpCDtiLTshYvsnbQg67CU64CM7Ja064+EIOuhnOq3uOyXkOuKlCDrsJjsmIHrkJjsp4Ag7JWK64qU64ukLlxuICBpZiAoYXJncy5ydW5Db250ZXh0Py5yZXF1ZXN0TG9nSWQgIT09IHVuZGVmaW5lZCkge1xuICAgIHJlcXVlc3RMb2dJZCA9IGFyZ3MucnVuQ29udGV4dC5yZXF1ZXN0TG9nSWQ7XG4gICAgLy8gY2xlYW51cOqzvCDqsJnsnYAgREIgYWR2aXNvcnkgbG9ja+ydhCDsnqHqs6AgdG9vbCDqsrDqs7wg67CY7JiBICsg64uk7J2MIHN0ZXAg7JiI7JW97J2EIO2VnFxuICAgIC8vIHRyYW5zYWN0aW9u7JeQ7IScIOyymOumrO2VnOuLpC4g7Jes65+sIHFncmlkIO2UhOuhnOyEuOyKpCDsgqzsnbTsl5DshJzrj4Qgc3RhbGUgZXhwaXJ56rCAXG4gICAgLy8g64+E7LCpIOykkeyduCBmb2xsb3ctdXDsnYQgZXJyb3LroZwg642u7Ja07JOw7KeAIOuqu+2VnOuLpC5cbiAgICBzdGVwSW5kZXggPSBhd2FpdCBSZXF1ZXN0TG9nTW9kZWwuY29udGludWVUb29sUnVuKHJlcXVlc3RMb2dJZCwgYXJncy50b29sUmVzdWx0cyA/PyBbXSk7XG4gICAgYXdhaXQgY2xlYW51cFN0YWxlUnVucygpO1xuICB9IGVsc2Uge1xuICAgIGF3YWl0IGNsZWFudXBTdGFsZVJ1bnMoKTtcbiAgICByZXF1ZXN0TG9nSWQgPSBhd2FpdCBSZXF1ZXN0TG9nTW9kZWwuY3JlYXRlUnVuKHtcbiAgICAgIHVzZXJfcHJvbXB0OiBhcmdzLnByb21wdCxcbiAgICAgIHN5c3RlbV9wcm9tcHQ6IGFyZ3Muc3lzdGVtLFxuICAgICAgcmVxdWVzdGVkX21vZGVsX25hbWU6IGFyZ3MubW9kZWwsXG4gICAgICBlZmZvcnQ6IGFyZ3MuZWZmb3J0LFxuICAgICAgcHJvamVjdF9uYW1lOiBhcmdzLnByb2plY3ROYW1lLFxuICAgICAgaGlzdG9yeTogZmlsdGVySGlzdG9yeUZvclN0b3JhZ2UoYXJncy5oaXN0b3J5KSxcbiAgICAgIHRvb2xzOiBhcmdzLnRvb2xzPy5sZW5ndGggPyBhcmdzLnRvb2xzIDogdW5kZWZpbmVkLFxuICAgICAgaXNfaW1hZ2VfZ2VuZXJhdGlvbjogYXJncy5pbWFnZUdlbmVyYXRpb24sXG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4geyByZXF1ZXN0TG9nSWQsIHN0ZXBJbmRleCB9O1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYWZ0ZXJRdWVyeShcbiAgcmVxdWVzdExvZ0lkOiBudW1iZXIsXG4gIHN0ZXBJbmRleDogbnVtYmVyLFxuICBhcmdzOiBRdWVyeUlucHV0LFxuICByZXN1bHQ6IFF1ZXJ5T3V0cHV0LFxuKTogUHJvbWlzZTxSdW5MaWZlY3ljbGVSZXN1bHQ+IHtcbiAgLy8gcHJvdmlkZXLqsIAgY2Fub25pY2FsIG1vZGVs7J2EIOuPjOugpOykmOuPhCDsmpTssq0gcm91dGUg7J6Q7LK0KFsxbV0g65OxKeuKlCDrs7TsobTtlZzri6QuXG4gIGNvbnN0IHJlcXVlc3RlZE1vZGVsTmFtZSA9IHdpdGhQcm92aWRlclByZWZpeChcbiAgICBhcmdzLm1vZGVsLFxuICAgIGFyZ3MubW9kZWwgPz8gcmVzdWx0LnJlcXVlc3RlZE1vZGVsID8/IHJlc3VsdC5tb2RlbCxcbiAgKTtcbiAgY29uc3Qgc2VydmVkTW9kZWxOYW1lID0gd2l0aFByb3ZpZGVyUHJlZml4KGFyZ3MubW9kZWwsIHJlc3VsdC5tb2RlbCk7XG5cbiAgLy8gZ2VuZXJhdGUgc3RlcCDquLDroZ1cbiAgYXdhaXQgUmVxdWVzdExvZ01vZGVsLmFwcGVuZFN0ZXAocmVxdWVzdExvZ0lkLCB7XG4gICAgc3RlcF9pbmRleDogc3RlcEluZGV4LFxuICAgIHR5cGU6IFwiZ2VuZXJhdGVcIixcbiAgICBtb2RlbF9uYW1lOiBzZXJ2ZWRNb2RlbE5hbWUsXG4gICAgcmVxdWVzdGVkX21vZGVsX25hbWU6IHJlcXVlc3RlZE1vZGVsTmFtZSxcbiAgICBmYWxsYmFja19jb3VudDogcmVzdWx0Lm1vZGVsRmFsbGJhY2tzPy5sZW5ndGggPz8gMCxcbiAgICBpbnB1dF90b2tlbnM6IHJlc3VsdC51c2FnZS5pbnB1dF90b2tlbnMsXG4gICAgb3V0cHV0X3Rva2VuczogcmVzdWx0LnVzYWdlLm91dHB1dF90b2tlbnMsXG4gICAgY2FjaGVfcmVhZF90b2tlbnM6IHJlc3VsdC51c2FnZS5jYWNoZV9yZWFkX2lucHV0X3Rva2VucyxcbiAgICBjYWNoZV9jcmVhdGlvbl90b2tlbnM6IHJlc3VsdC51c2FnZS5jYWNoZV9jcmVhdGlvbl9pbnB1dF90b2tlbnMsXG4gICAgY2FjaGVfY3JlYXRpb25fNW1fdG9rZW5zOiByZXN1bHQudXNhZ2UuY2FjaGVfY3JlYXRpb25fNW1faW5wdXRfdG9rZW5zLFxuICAgIGNhY2hlX2NyZWF0aW9uXzFoX3Rva2VuczogcmVzdWx0LnVzYWdlLmNhY2hlX2NyZWF0aW9uXzFoX2lucHV0X3Rva2VucyxcbiAgICBjb3N0X3VzZDogTWF0aC5yb3VuZChyZXN1bHQuY29zdFVzZCAqIDFfMDAwXzAwMCksXG4gICAgY29zdF9zb3VyY2U6IHJlc3VsdC5jb3N0U291cmNlLFxuICAgIGR1cmF0aW9uX21zOiByZXN1bHQuZHVyYXRpb25NcyxcbiAgICB0dGZ0X21zOiByZXN1bHQudHRmdE1zLFxuICAgIGZpbmlzaF9yZWFzb246IHJlc3VsdC5maW5pc2hSZWFzb24sXG4gIH0pO1xuXG4gIGNvbnN0IGltYWdlUGFydHMgPSBnZXRJbWFnZVBhcnRzKHJlc3VsdCk7XG4gIGNvbnN0IGltYWdlQ29zdE1pY3JvVXNkID0gZXN0aW1hdGVJbWFnZUdlbmVyYXRpb25Db3N0TWljcm9Vc2QoXG4gICAgcmVzdWx0LFxuICAgIGFyZ3MuaW1hZ2VHZW5lcmF0aW9uT3B0aW9ucyxcbiAgKTtcbiAgZm9yIChjb25zdCBzdGVwIG9mIGJ1aWxkSW1hZ2VHZW5lcmF0aW9uVG9vbFN0ZXBzKGFyZ3MsIGltYWdlUGFydHMsIHN0ZXBJbmRleCkpIHtcbiAgICBhd2FpdCBSZXF1ZXN0TG9nTW9kZWwuYXBwZW5kU3RlcChyZXF1ZXN0TG9nSWQsIHN0ZXApO1xuICB9XG5cbiAgaWYgKHJlc3VsdC5maW5pc2hSZWFzb24gPT09IFwidG9vbC1jYWxsc1wiKSB7XG4gICAgLy8gdG9vbC1jYWxsIHN0ZXDsnYQg7KaJ7IucIOq4sOuhne2VmOqzoCwg64uk7J2MIGZvbGxvdy11cOydtCDqsJnsnYAgcm937JeQIOqysOqzvOulvCDssYTsmrTri6QuXG4gICAgY29uc3QgdG9vbENhbGxzID0gcmVzdWx0LmNvbnRlbnQuZmlsdGVyKChjKSA9PiBjLnR5cGUgPT09IFwidG9vbC1jYWxsXCIpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdG9vbENhbGxzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCB0YyA9IHRvb2xDYWxsc1tpXSE7XG4gICAgICBpZiAodGMudHlwZSAhPT0gXCJ0b29sLWNhbGxcIikgY29udGludWU7XG4gICAgICBhd2FpdCBSZXF1ZXN0TG9nTW9kZWwuYXBwZW5kU3RlcChyZXF1ZXN0TG9nSWQsIHtcbiAgICAgICAgc3RlcF9pbmRleDogc3RlcEluZGV4LFxuICAgICAgICB0eXBlOiBcInRvb2xfY2FsbFwiLFxuICAgICAgICB0b29sX2NhbGxfaW5kZXg6IGltYWdlUGFydHMubGVuZ3RoICsgaSxcbiAgICAgICAgdG9vbF9jYWxsX2lkOiB0Yy50b29sQ2FsbElkLFxuICAgICAgICB0b29sX25hbWU6IHRjLnRvb2xOYW1lLFxuICAgICAgICB0b29sX2FyZ3M6IHRjLmlucHV0LFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgcnVuQ29udGV4dDogeyByZXF1ZXN0TG9nSWQgfSB9O1xuICB9XG5cbiAgLy8gZmluaXNoUmVhc29uID09PSBcInN0b3BcIiDihpIgcnVuIOyiheujjCAo7KCE7LK0IHN0ZXAgdXNhZ2Ug7ZWp7IKwKVxuICBjb25zdCBhZ2cgPSBhd2FpdCBSZXF1ZXN0TG9nTW9kZWwuYWdncmVnYXRlU3RlcFVzYWdlKHJlcXVlc3RMb2dJZCk7XG4gIGF3YWl0IFJlcXVlc3RMb2dNb2RlbC5maW5pc2hSdW4ocmVxdWVzdExvZ0lkLCB7XG4gICAgc3RhdHVzOiBcInN1Y2NlZWRlZFwiLFxuICAgIHJlc3BvbnNlOiBmb3JtYXRSZXNwb25zZUZvckxvZyhyZXN1bHQpLFxuICAgIHRva2VuX25hbWU6IHJlc3VsdC50b2tlbk5hbWUsXG4gICAgaW5wdXRfdG9rZW5zOiBhZ2cuaW5wdXRfdG9rZW5zLFxuICAgIG91dHB1dF90b2tlbnM6IGFnZy5vdXRwdXRfdG9rZW5zLFxuICAgIGNhY2hlX3JlYWRfdG9rZW5zOiBhZ2cuY2FjaGVfcmVhZF90b2tlbnMsXG4gICAgY2FjaGVfY3JlYXRpb25fdG9rZW5zOiBhZ2cuY2FjaGVfY3JlYXRpb25fdG9rZW5zLFxuICAgIGNhY2hlX2NyZWF0aW9uXzVtX3Rva2VuczogYWdnLmNhY2hlX2NyZWF0aW9uXzVtX3Rva2VucyxcbiAgICBjYWNoZV9jcmVhdGlvbl8xaF90b2tlbnM6IGFnZy5jYWNoZV9jcmVhdGlvbl8xaF90b2tlbnMsXG4gICAgZHVyYXRpb25fbXM6IGFnZy5kdXJhdGlvbl9tcyxcbiAgICAvLyBtdWx0aS1zdGVwIHJ1biDrtoDrqqjsnZgg66qo64247J2AIOy1nOyihSB0dXJu7J2EIOyEnOu5me2VnCDrqqjrjbjsnbTri6QuXG4gICAgcmVxdWVzdGVkX21vZGVsX25hbWU6IHJlcXVlc3RlZE1vZGVsTmFtZSxcbiAgICBtb2RlbF9uYW1lOiBzZXJ2ZWRNb2RlbE5hbWUsXG4gICAgZmFsbGJhY2tfY291bnQ6IGFnZy5mYWxsYmFja19jb3VudCxcbiAgICBjb3N0X3VzZDogYWdnLmNvc3RfdXNkLFxuICAgIGNvc3Rfc291cmNlOiBhZ2cuY29zdF9zb3VyY2UsXG4gICAgaW1hZ2VfY29zdF91c2Q6IGltYWdlQ29zdE1pY3JvVXNkLFxuICAgIGltYWdlX2Nvc3RfbWV0aG9kOlxuICAgICAgaW1hZ2VDb3N0TWljcm9Vc2QgIT09IG51bGwgPyBpbWFnZUdlbmVyYXRpb25Db3N0TWV0aG9kKGFyZ3MuaW1hZ2VHZW5lcmF0aW9uT3B0aW9ucykgOiBudWxsLFxuICAgIGhpc3Rvcnk6IGZpbHRlckhpc3RvcnlGb3JTdG9yYWdlKGFyZ3MuaGlzdG9yeSksXG4gIH0pO1xuXG4gIHJldHVybiB7fTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGZpbmlzaFJ1bldpdGhFcnJvcihcbiAgcmVxdWVzdExvZ0lkOiBudW1iZXIsXG4gIGVycm9yTWVzc2FnZTogc3RyaW5nLFxuICBhcmdzPzogUXVlcnlJbnB1dCxcbik6IFByb21pc2U8dm9pZD4ge1xuICBhd2FpdCBmaW5pc2hUZXJtaW5hbFJ1bihyZXF1ZXN0TG9nSWQsIFwiZXJyb3JcIiwgZXJyb3JNZXNzYWdlLCBhcmdzKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGZpbmlzaFJ1bkFib3J0ZWQocmVxdWVzdExvZ0lkOiBudW1iZXIsIGFyZ3M/OiBRdWVyeUlucHV0KTogUHJvbWlzZTx2b2lkPiB7XG4gIGF3YWl0IGZpbmlzaFRlcm1pbmFsUnVuKHJlcXVlc3RMb2dJZCwgXCJhYm9ydGVkXCIsIFwiY2xpZW50IGRpc2Nvbm5lY3RlZFwiLCBhcmdzKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZmluaXNoVGVybWluYWxSdW4oXG4gIHJlcXVlc3RMb2dJZDogbnVtYmVyLFxuICBzdGF0dXM6IFwiZXJyb3JcIiB8IFwiYWJvcnRlZFwiLFxuICBlcnJvck1lc3NhZ2U6IHN0cmluZyxcbiAgYXJncz86IFF1ZXJ5SW5wdXQsXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgdHJ5IHtcbiAgICBsZXQgYWdncmVnYXRlOiBBd2FpdGVkPFJldHVyblR5cGU8dHlwZW9mIFJlcXVlc3RMb2dNb2RlbC5hZ2dyZWdhdGVTdGVwVXNhZ2U+PiB8IHVuZGVmaW5lZDtcbiAgICB0cnkge1xuICAgICAgYWdncmVnYXRlID0gYXdhaXQgUmVxdWVzdExvZ01vZGVsLmFnZ3JlZ2F0ZVN0ZXBVc2FnZShyZXF1ZXN0TG9nSWQpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxvZ2dlci5lcnJvcihgYWdncmVnYXRlU3RlcFVzYWdlIGZhaWxlZCB3aGlsZSBmaW5pc2hpbmcgJHtzdGF0dXN9OiAkeyhlIGFzIEVycm9yKS5tZXNzYWdlfWApO1xuICAgIH1cblxuICAgIGF3YWl0IFJlcXVlc3RMb2dNb2RlbC5maW5pc2hSdW4ocmVxdWVzdExvZ0lkLCB7XG4gICAgICBzdGF0dXMsXG4gICAgICBlcnJvcl9tZXNzYWdlOiBlcnJvck1lc3NhZ2UsXG4gICAgICBoaXN0b3J5OiBhcmdzID8gZmlsdGVySGlzdG9yeUZvclN0b3JhZ2UoYXJncy5oaXN0b3J5KSA6IHVuZGVmaW5lZCxcbiAgICAgIC4uLihhZ2dyZWdhdGVcbiAgICAgICAgPyB7XG4gICAgICAgICAgICBpbnB1dF90b2tlbnM6IGFnZ3JlZ2F0ZS5pbnB1dF90b2tlbnMsXG4gICAgICAgICAgICBvdXRwdXRfdG9rZW5zOiBhZ2dyZWdhdGUub3V0cHV0X3Rva2VucyxcbiAgICAgICAgICAgIGNhY2hlX3JlYWRfdG9rZW5zOiBhZ2dyZWdhdGUuY2FjaGVfcmVhZF90b2tlbnMsXG4gICAgICAgICAgICBjYWNoZV9jcmVhdGlvbl90b2tlbnM6IGFnZ3JlZ2F0ZS5jYWNoZV9jcmVhdGlvbl90b2tlbnMsXG4gICAgICAgICAgICBjYWNoZV9jcmVhdGlvbl81bV90b2tlbnM6IGFnZ3JlZ2F0ZS5jYWNoZV9jcmVhdGlvbl81bV90b2tlbnMsXG4gICAgICAgICAgICBjYWNoZV9jcmVhdGlvbl8xaF90b2tlbnM6IGFnZ3JlZ2F0ZS5jYWNoZV9jcmVhdGlvbl8xaF90b2tlbnMsXG4gICAgICAgICAgICBkdXJhdGlvbl9tczogYWdncmVnYXRlLmR1cmF0aW9uX21zLFxuICAgICAgICAgICAgZmFsbGJhY2tfY291bnQ6IGFnZ3JlZ2F0ZS5mYWxsYmFja19jb3VudCxcbiAgICAgICAgICAgIGNvc3RfdXNkOiBhZ2dyZWdhdGUuY29zdF91c2QsXG4gICAgICAgICAgICBjb3N0X3NvdXJjZTogYWdncmVnYXRlLmNvc3Rfc291cmNlLFxuICAgICAgICAgIH1cbiAgICAgICAgOiB7fSksXG4gICAgfSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBsb2dnZXIuZXJyb3IoYGZpbmlzaFRlcm1pbmFsUnVuKCR7c3RhdHVzfSkgZmFpbGVkOiAkeyhlIGFzIEVycm9yKS5tZXNzYWdlfWApO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGNsZWFudXBTdGFsZVJ1bnMoKTogUHJvbWlzZTx2b2lkPiB7XG4gIGlmIChzdGFsZUNsZWFudXBJbkZsaWdodCkge1xuICAgIGF3YWl0IHN0YWxlQ2xlYW51cEluRmxpZ2h0O1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gIGlmIChub3cgLSBsYXN0U3RhbGVDbGVhbnVwU3RhcnRlZEF0IDwgU1RBTEVfQ0xFQU5VUF9JTlRFUlZBTF9NUykgcmV0dXJuO1xuICBsYXN0U3RhbGVDbGVhbnVwU3RhcnRlZEF0ID0gbm93O1xuXG4gIGNvbnN0IGNsZWFudXAgPSBwZXJmb3JtU3RhbGVSdW5DbGVhbnVwKCk7XG4gIHN0YWxlQ2xlYW51cEluRmxpZ2h0ID0gY2xlYW51cDtcbiAgdHJ5IHtcbiAgICBhd2FpdCBjbGVhbnVwO1xuICB9IGZpbmFsbHkge1xuICAgIGlmIChzdGFsZUNsZWFudXBJbkZsaWdodCA9PT0gY2xlYW51cCkgc3RhbGVDbGVhbnVwSW5GbGlnaHQgPSB1bmRlZmluZWQ7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gcGVyZm9ybVN0YWxlUnVuQ2xlYW51cCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBcInRvb2wtY2FsbCBydW46IG5vIGZvbGxvdy11cCB3aXRoaW4gMzAgbWludXRlc1wiO1xuICAgIGNvbnN0IHN0YWxlSWRzID0gYXdhaXQgUmVxdWVzdExvZ01vZGVsLmV4cGlyZVN0YWxlVG9vbFdhaXRpbmdSdW5zKFxuICAgICAgU1RBTEVfUlVOX1RIUkVTSE9MRF9NUyxcbiAgICAgIGVycm9yTWVzc2FnZSxcbiAgICApO1xuICAgIGNvbnN0IGNsZWFuZWRDb3VudCA9IHN0YWxlSWRzLmxlbmd0aDtcbiAgICBpZiAoY2xlYW5lZENvdW50ID4gMCkge1xuICAgICAgbG9nZ2VyLmluZm8oYGNsZWFuZWQgdXAgJHtjbGVhbmVkQ291bnR9IHN0YWxlIHJ1bm5pbmcgcmVxdWVzdCBsb2dzYCk7XG4gICAgfVxuICB9IGNhdGNoIChlKSB7XG4gICAgbG9nZ2VyLmVycm9yKGBzdGFsZSBjbGVhbnVwIGZhaWxlZDogJHsoZSBhcyBFcnJvcikubWVzc2FnZX1gKTtcbiAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7OztBQWNBLE1BQU0sU0FBUyxVQUFVLENBQUMsU0FBUyxlQUFlLENBQUM7QUFDbkQsTUFBTSx5QkFBeUIsT0FBVTtBQUN6QyxNQUFNLDRCQUE0QixLQUFLO0FBQ3ZDLElBQUk7QUFDSixJQUFJLDRCQUE0QjtBQUVoQyxTQUFTLG1CQUNQLFlBQ0EsT0FDb0I7Q0FDcEIsSUFBSSxDQUFDLE9BQU8sT0FBTztDQUNuQixJQUFJLE1BQU0sU0FBUyxHQUFHLEdBQUcsT0FBTztDQUNoQyxNQUFNLFFBQVEsWUFBWSxRQUFRLEdBQUcsS0FBSztDQUMxQyxNQUFNLFdBQVcsUUFBUSxJQUFJLFlBQVksTUFBTSxHQUFHLEtBQUssSUFBSTtDQUMzRCxPQUFPLFdBQVcsR0FBRyxTQUFTLEdBQUcsVUFBVTtBQUM3Qzs7OztBQUtBLFNBQVMsd0JBQXdCLFlBQXlDO0NBQ3hFLElBQUksQ0FBQyxZQUFZLE9BQU87Q0FDeEIsSUFBSTtFQUVGLE1BQU0sV0FEUSxLQUFLLE1BQU0sVUFDUixDQUFBLENBQU0sUUFBUSxTQUFTO0dBQ3RDLElBQUksQ0FBQyxRQUFRLE9BQU8sU0FBUyxVQUFVLE9BQU87R0FDOUMsTUFBTSxTQUFTO0dBQ2YsT0FBTyxPQUFPLFNBQVMsY0FBYyxPQUFPLFNBQVMsVUFBVSxPQUFPLFNBQVM7RUFDakYsQ0FBQztFQUNELE9BQU8sU0FBUyxTQUFTLElBQUksV0FBVztDQUMxQyxRQUFRO0VBQ047Q0FDRjtBQUNGOzs7Ozs7O0FBWUEsZUFBc0IsWUFBWSxNQUcvQjtDQUNELElBQUk7Q0FDSixJQUFJLFlBQVk7Q0FLaEIsSUFBSSxLQUFLLFlBQVksaUJBQWlCLFFBQVc7RUFDL0MsZUFBZSxLQUFLLFdBQVc7RUFJ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
|
|
267
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicWdyaWQtcnVuLWxpZmVjeWNsZS5qcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBwbGljYXRpb24vcWdyaWQvcWdyaWQtcnVuLWxpZmVjeWNsZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBnZXRMb2dnZXIgfSBmcm9tIFwiQGxvZ3RhcGUvbG9ndGFwZVwiO1xuaW1wb3J0IHsgU2VydmljZVVuYXZhaWxhYmxlRXhjZXB0aW9uIH0gZnJvbSBcInNvbmFtdVwiO1xuXG5pbXBvcnQgeyBTRCB9IGZyb20gXCIuLi8uLi9pMThuL3NkLmdlbmVyYXRlZFwiO1xuaW1wb3J0IHsgaXNSZXN0YXJ0UGVuZGluZyB9IGZyb20gXCIuLi8uLi91dGlscy9zZXJ2ZXItcmVzdGFydFwiO1xuaW1wb3J0IHsgUmVxdWVzdExvZ01vZGVsIH0gZnJvbSBcIi4uL3JlcXVlc3QtbG9nL3JlcXVlc3QtbG9nLm1vZGVsXCI7XG5pbXBvcnQge1xuICBlc3RpbWF0ZUltYWdlR2VuZXJhdGlvbkNvc3RNaWNyb1VzZCxcbiAgaW1hZ2VHZW5lcmF0aW9uQ29zdE1ldGhvZCxcbn0gZnJvbSBcIi4vcWdyaWQtaW1hZ2UtZ2VuZXJhdGlvblwiO1xuaW1wb3J0IHtcbiAgYnVpbGRJbWFnZUdlbmVyYXRpb25Ub29sU3RlcHMsXG4gIGZvcm1hdFJlc3BvbnNlRm9yTG9nLFxuICBnZXRJbWFnZVBhcnRzLFxufSBmcm9tIFwiLi9xZ3JpZC1yZXNwb25zZS1mb3JtYXRcIjtcbmltcG9ydCB7IHR5cGUgUWdyaWRSdW5Db250ZXh0LCB0eXBlIFF1ZXJ5SW5wdXQsIHR5cGUgUXVlcnlPdXRwdXQgfSBmcm9tIFwiLi9xZ3JpZC50eXBlc1wiO1xuXG5jb25zdCBsb2dnZXIgPSBnZXRMb2dnZXIoW1wicWdyaWRcIiwgXCJydW4tbGlmZWN5Y2xlXCJdKTtcbmNvbnN0IFNUQUxFX1JVTl9USFJFU0hPTERfTVMgPSAzMCAqIDYwICogMTAwMDtcbmNvbnN0IFNUQUxFX0NMRUFOVVBfSU5URVJWQUxfTVMgPSA2MCAqIDEwMDA7XG5sZXQgc3RhbGVDbGVhbnVwSW5GbGlnaHQ6IFByb21pc2U8dm9pZD4gfCB1bmRlZmluZWQ7XG5sZXQgbGFzdFN0YWxlQ2xlYW51cFN0YXJ0ZWRBdCA9IDA7XG5jb25zdCBhY3RpdmVOYXRpdmVSdW5SZWZzID0gbmV3IE1hcDxudW1iZXIsIG51bWJlcj4oKTtcbmNvbnN0IGludGVycnVwdGVkTmF0aXZlUnVuSWRzID0gbmV3IFNldDxudW1iZXI+KCk7XG5jb25zdCBhY3RpdmVOYXRpdmVGaW5hbGl6ZXJzID0gbmV3IE1hcDxudW1iZXIsIFNldDxQcm9taXNlPHZvaWQ+Pj4oKTtcblxuZnVuY3Rpb24gcmVzdGFydFVuYXZhaWxhYmxlKCk6IFNlcnZpY2VVbmF2YWlsYWJsZUV4Y2VwdGlvbiB7XG4gIHJldHVybiBuZXcgU2VydmljZVVuYXZhaWxhYmxlRXhjZXB0aW9uKFNEKFwicWdyaWQucmVzdGFydFBlbmRpbmdcIikoKSk7XG59XG5cbmZ1bmN0aW9uIHJlZ2lzdGVyTmF0aXZlUnVuKHJlcXVlc3RMb2dJZDogbnVtYmVyKTogdm9pZCB7XG4gIGFjdGl2ZU5hdGl2ZVJ1blJlZnMuc2V0KHJlcXVlc3RMb2dJZCwgKGFjdGl2ZU5hdGl2ZVJ1blJlZnMuZ2V0KHJlcXVlc3RMb2dJZCkgPz8gMCkgKyAxKTtcbn1cblxuZnVuY3Rpb24gcmVsZWFzZU5hdGl2ZVJ1bihyZXF1ZXN0TG9nSWQ6IG51bWJlcik6IHZvaWQge1xuICBjb25zdCByZWZzID0gYWN0aXZlTmF0aXZlUnVuUmVmcy5nZXQocmVxdWVzdExvZ0lkKTtcbiAgaWYgKHJlZnMgPT09IHVuZGVmaW5lZCB8fCByZWZzIDw9IDEpIGFjdGl2ZU5hdGl2ZVJ1blJlZnMuZGVsZXRlKHJlcXVlc3RMb2dJZCk7XG4gIGVsc2UgYWN0aXZlTmF0aXZlUnVuUmVmcy5zZXQocmVxdWVzdExvZ0lkLCByZWZzIC0gMSk7XG59XG5cbmZ1bmN0aW9uIHRyYWNrTmF0aXZlRmluYWxpemVyPFQ+KHJlcXVlc3RMb2dJZDogbnVtYmVyLCBmaW5hbGl6ZTogKCkgPT4gUHJvbWlzZTxUPik6IFByb21pc2U8VD4ge1xuICBjb25zdCBvcGVyYXRpb24gPSBmaW5hbGl6ZSgpO1xuICBjb25zdCBzZXR0bGVkID0gb3BlcmF0aW9uLnRoZW4oXG4gICAgKCkgPT4gdW5kZWZpbmVkLFxuICAgICgpID0+IHVuZGVmaW5lZCxcbiAgKTtcbiAgY29uc3QgZmluYWxpemVycyA9IGFjdGl2ZU5hdGl2ZUZpbmFsaXplcnMuZ2V0KHJlcXVlc3RMb2dJZCkgPz8gbmV3IFNldDxQcm9taXNlPHZvaWQ+PigpO1xuICBmaW5hbGl6ZXJzLmFkZChzZXR0bGVkKTtcbiAgYWN0aXZlTmF0aXZlRmluYWxpemVycy5zZXQocmVxdWVzdExvZ0lkLCBmaW5hbGl6ZXJzKTtcbiAgdm9pZCBzZXR0bGVkLnRoZW4oKCkgPT4ge1xuICAgIGZpbmFsaXplcnMuZGVsZXRlKHNldHRsZWQpO1xuICAgIGlmIChmaW5hbGl6ZXJzLnNpemUgPT09IDApIGFjdGl2ZU5hdGl2ZUZpbmFsaXplcnMuZGVsZXRlKHJlcXVlc3RMb2dJZCk7XG4gIH0pO1xuICByZXR1cm4gb3BlcmF0aW9uO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYXNzZXJ0TmF0aXZlUnVuQWRtaXNzaW9uKCk6IHZvaWQge1xuICBpZiAoaXNSZXN0YXJ0UGVuZGluZygpKSB0aHJvdyByZXN0YXJ0VW5hdmFpbGFibGUoKTtcbn1cblxuZnVuY3Rpb24gd2l0aFByb3ZpZGVyUHJlZml4KFxuICByb3V0ZU1vZGVsOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gIG1vZGVsOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBpZiAoIW1vZGVsKSByZXR1cm4gdW5kZWZpbmVkO1xuICBpZiAobW9kZWwuaW5jbHVkZXMoXCIvXCIpKSByZXR1cm4gbW9kZWw7XG4gIGNvbnN0IHNsYXNoID0gcm91dGVNb2RlbD8uaW5kZXhPZihcIi9cIikgPz8gLTE7XG4gIGNvbnN0IHByb3ZpZGVyID0gc2xhc2ggPiAwID8gcm91dGVNb2RlbD8uc2xpY2UoMCwgc2xhc2gpIDogdW5kZWZpbmVkO1xuICByZXR1cm4gcHJvdmlkZXIgPyBgJHtwcm92aWRlcn0vJHttb2RlbH1gIDogbW9kZWw7XG59XG5cbi8qKlxuICogaGlzdG9yeeuKlCDsm5Drs7gg6re464yA66GcIOyggOyepe2VmOq4sOuztOuLpOuKlCwgcnVuIOu2hOyEneyXkCDtlYTsmpTtlZwgdXNlci9hc3Npc3RhbnQg7KCV67O066eMIO2VhO2EsOunge2VtOyEnCDsoIDsnqVcbiAqL1xuZnVuY3Rpb24gZmlsdGVySGlzdG9yeUZvclN0b3JhZ2UocmF3SGlzdG9yeTogc3RyaW5nIHwgdW5kZWZpbmVkKTogdW5rbm93biB7XG4gIGlmICghcmF3SGlzdG9yeSkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgdHJ5IHtcbiAgICBjb25zdCBpdGVtcyA9IEpTT04ucGFyc2UocmF3SGlzdG9yeSkgYXMgdW5rbm93bltdO1xuICAgIGNvbnN0IGZpbHRlcmVkID0gaXRlbXMuZmlsdGVyKChpdGVtKSA9PiB7XG4gICAgICBpZiAoIWl0ZW0gfHwgdHlwZW9mIGl0ZW0gIT09IFwib2JqZWN0XCIpIHJldHVybiBmYWxzZTtcbiAgICAgIGNvbnN0IHJlY29yZCA9IGl0ZW0gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgICByZXR1cm4gcmVjb3JkLnR5cGUgPT09IFwibWVzc2FnZVwiICYmIChyZWNvcmQucm9sZSA9PT0gXCJ1c2VyXCIgfHwgcmVjb3JkLnJvbGUgPT09IFwiYXNzaXN0YW50XCIpO1xuICAgIH0pO1xuICAgIHJldHVybiBmaWx0ZXJlZC5sZW5ndGggPiAwID8gZmlsdGVyZWQgOiB1bmRlZmluZWQ7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn1cblxuZXhwb3J0IHR5cGUgUnVuTGlmZWN5Y2xlUmVzdWx0ID0ge1xuICBydW5Db250ZXh0PzogUWdyaWRSdW5Db250ZXh0O1xufTtcblxuLyoqXG4gKiBsb2dnZXItZW5hYmxlZCBxdWVyeS9zdHJlYW0g7J2R64u1IOyghO2bhOyXkCDtmLjstpwuXG4gKlxuICogMSkgYmVmb3JlUXVlcnk6IHJ1biDsg53shLEv6rOE7IaNICsgdG9vbCByZXN1bHQg7JmE66OMICsgc3RhbGUgdG9vbC13YWl0IGNsZWFudXBcbiAqIDIpIGFmdGVyUXVlcnk6IGdlbmVyYXRlIHN0ZXAgKyB0b29sLWNhbGwgc3RlcCArIGZpbmlzaC9rZWVwLW9wZW5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGJlZm9yZVF1ZXJ5KGFyZ3M6IFF1ZXJ5SW5wdXQpOiBQcm9taXNlPHtcbiAgcmVxdWVzdExvZ0lkOiBudW1iZXI7XG4gIHN0ZXBJbmRleDogbnVtYmVyO1xufT4ge1xuICBhc3NlcnROYXRpdmVSdW5BZG1pc3Npb24oKTtcblxuICBsZXQgcmVxdWVzdExvZ0lkOiBudW1iZXI7XG4gIGxldCBzdGVwSW5kZXggPSAwO1xuXG4gIC8vIHJlcXVlc3RMb2dJZCDqsIAg7J6I7J2EIOuVjOunjCDquLDsobQgcnVuIOyXsOyepS4gdGhyZWFkQ29vcmQg66eMIOyeiOuKlCBjb252IOuKlCDsg4ggcnVuIOycvOuhnCDsi5zsnpEuXG4gIC8vIGNvbnRpbnVhdGlvbiDsnYAgY3JlYXRlUnVuIOydhCDqsbTrhIjrm7Drr4DroZwgcnVuIOydmCB0b29scyDripQg7LKrIOyKpO2FnSDsnqXssKnrtoTsnLzroZwg6rOg7KCV65Cc64ukIOKAlFxuICAvLyBBSSBTREsgcHJlcGFyZVN0ZXAvYWN0aXZlVG9vbHMg66GcIOyKpO2FneuniOuLpCDtiLTshYvsnbQg67CU64CM7Ja064+EIOuhnOq3uOyXkOuKlCDrsJjsmIHrkJjsp4Ag7JWK64qU64ukLlxuICBpZiAoYXJncy5ydW5Db250ZXh0Py5yZXF1ZXN0TG9nSWQgIT09IHVuZGVmaW5lZCkge1xuICAgIHJlcXVlc3RMb2dJZCA9IGFyZ3MucnVuQ29udGV4dC5yZXF1ZXN0TG9nSWQ7XG4gICAgLy8gY2xlYW51cOqzvCDqsJnsnYAgREIgYWR2aXNvcnkgbG9ja+ydhCDsnqHqs6AgdG9vbCDqsrDqs7wg67CY7JiBICsg64uk7J2MIHN0ZXAg7JiI7JW97J2EIO2VnFxuICAgIC8vIHRyYW5zYWN0aW9u7JeQ7IScIOyymOumrO2VnOuLpC4g7Jes65+sIHFncmlkIO2UhOuhnOyEuOyKpCDsgqzsnbTsl5DshJzrj4Qgc3RhbGUgZXhwaXJ56rCAXG4gICAgLy8g64+E7LCpIOykkeyduCBmb2xsb3ctdXDsnYQgZXJyb3LroZwg642u7Ja07JOw7KeAIOuqu+2VnOuLpC5cbiAgICBzdGVwSW5kZXggPSBhd2FpdCBSZXF1ZXN0TG9nTW9kZWwuY29udGludWVUb29sUnVuKHJlcXVlc3RMb2dJZCwgYXJncy50b29sUmVzdWx0cyA/PyBbXSk7XG4gICAgYXdhaXQgY2xlYW51cFN0YWxlUnVucygpO1xuICB9IGVsc2Uge1xuICAgIGF3YWl0IGNsZWFudXBTdGFsZVJ1bnMoKTtcbiAgICByZXF1ZXN0TG9nSWQgPSBhd2FpdCBSZXF1ZXN0TG9nTW9kZWwuY3JlYXRlUnVuKHtcbiAgICAgIHVzZXJfcHJvbXB0OiBhcmdzLnByb21wdCxcbiAgICAgIHN5c3RlbV9wcm9tcHQ6IGFyZ3Muc3lzdGVtLFxuICAgICAgcmVxdWVzdGVkX21vZGVsX25hbWU6IGFyZ3MubW9kZWwsXG4gICAgICBlZmZvcnQ6IGFyZ3MuZWZmb3J0LFxuICAgICAgcHJvamVjdF9uYW1lOiBhcmdzLnByb2plY3ROYW1lLFxuICAgICAgaGlzdG9yeTogZmlsdGVySGlzdG9yeUZvclN0b3JhZ2UoYXJncy5oaXN0b3J5KSxcbiAgICAgIHRvb2xzOiBhcmdzLnRvb2xzPy5sZW5ndGggPyBhcmdzLnRvb2xzIDogdW5kZWZpbmVkLFxuICAgICAgaXNfaW1hZ2VfZ2VuZXJhdGlvbjogYXJncy5pbWFnZUdlbmVyYXRpb24sXG4gICAgfSk7XG4gIH1cblxuICAvLyBEQiDspIDruYQg7KSR7JeQIOyerOyLnOyekeydtCDsi5zsnpHrkJDri6TrqbQgcHJvdmlkZXIg7Iuk7ZaJ7Jy866GcIOuEmOyWtOqwgOyngCDslYrripTri6QuXG4gIC8vIOydtCDsmpTssq3snYAg7J6s7Iuc7J6RIHNuYXBzaG907JeQIOyXhuyXiOycvOuvgOuhnCDrsKnquIgg7KSA67mE7ZWcIHJ1buydhCDsp4HsoJEg66eI6rCQ7ZWc64ukLlxuICBpZiAoaXNSZXN0YXJ0UGVuZGluZygpKSB7XG4gICAgYXdhaXQgZmluaXNoVGVybWluYWxSdW4ocmVxdWVzdExvZ0lkLCBcImVycm9yXCIsIFwic2VydmVyIHJlc3RhcnRlZFwiKTtcbiAgICB0aHJvdyByZXN0YXJ0VW5hdmFpbGFibGUoKTtcbiAgfVxuXG4gIHJlZ2lzdGVyTmF0aXZlUnVuKHJlcXVlc3RMb2dJZCk7XG4gIHJldHVybiB7IHJlcXVlc3RMb2dJZCwgc3RlcEluZGV4IH07XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhZnRlclF1ZXJ5KFxuICByZXF1ZXN0TG9nSWQ6IG51bWJlcixcbiAgc3RlcEluZGV4OiBudW1iZXIsXG4gIGFyZ3M6IFF1ZXJ5SW5wdXQsXG4gIHJlc3VsdDogUXVlcnlPdXRwdXQsXG4pOiBQcm9taXNlPFJ1bkxpZmVjeWNsZVJlc3VsdD4ge1xuICBpZiAoaW50ZXJydXB0ZWROYXRpdmVSdW5JZHMuaGFzKHJlcXVlc3RMb2dJZCkpIHJldHVybiB7fTtcblxuICByZXR1cm4gdHJhY2tOYXRpdmVGaW5hbGl6ZXIocmVxdWVzdExvZ0lkLCBhc3luYyAoKSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIHByb3ZpZGVy6rCAIGNhbm9uaWNhbCBtb2RlbOydhCDrj4zroKTspJjrj4Qg7JqU7LKtIHJvdXRlIOyekOyytChbMW1dIOuTsSnripQg67O07KG07ZWc64ukLlxuICAgICAgY29uc3QgcmVxdWVzdGVkTW9kZWxOYW1lID0gd2l0aFByb3ZpZGVyUHJlZml4KFxuICAgICAgICBhcmdzLm1vZGVsLFxuICAgICAgICBhcmdzLm1vZGVsID8/IHJlc3VsdC5yZXF1ZXN0ZWRNb2RlbCA/PyByZXN1bHQubW9kZWwsXG4gICAgICApO1xuICAgICAgY29uc3Qgc2VydmVkTW9kZWxOYW1lID0gd2l0aFByb3ZpZGVyUHJlZml4KGFyZ3MubW9kZWwsIHJlc3VsdC5tb2RlbCk7XG5cbiAgICAgIC8vIGdlbmVyYXRlIHN0ZXAg6riw66GdXG4gICAgICBhd2FpdCBSZXF1ZXN0TG9nTW9kZWwuYXBwZW5kU3RlcChyZXF1ZXN0TG9nSWQsIHtcbiAgICAgICAgc3RlcF9pbmRleDogc3RlcEluZGV4LFxuICAgICAgICB0eXBlOiBcImdlbmVyYXRlXCIsXG4gICAgICAgIG1vZGVsX25hbWU6IHNlcnZlZE1vZGVsTmFtZSxcbiAgICAgICAgcmVxdWVzdGVkX21vZGVsX25hbWU6IHJlcXVlc3RlZE1vZGVsTmFtZSxcbiAgICAgICAgZmFsbGJhY2tfY291bnQ6IHJlc3VsdC5tb2RlbEZhbGxiYWNrcz8ubGVuZ3RoID8/IDAsXG4gICAgICAgIGlucHV0X3Rva2VuczogcmVzdWx0LnVzYWdlLmlucHV0X3Rva2VucyxcbiAgICAgICAgb3V0cHV0X3Rva2VuczogcmVzdWx0LnVzYWdlLm91dHB1dF90b2tlbnMsXG4gICAgICAgIGNhY2hlX3JlYWRfdG9rZW5zOiByZXN1bHQudXNhZ2UuY2FjaGVfcmVhZF9pbnB1dF90b2tlbnMsXG4gICAgICAgIGNhY2hlX2NyZWF0aW9uX3Rva2VuczogcmVzdWx0LnVzYWdlLmNhY2hlX2NyZWF0aW9uX2lucHV0X3Rva2VucyxcbiAgICAgICAgY2FjaGVfY3JlYXRpb25fNW1fdG9rZW5zOiByZXN1bHQudXNhZ2UuY2FjaGVfY3JlYXRpb25fNW1faW5wdXRfdG9rZW5zLFxuICAgICAgICBjYWNoZV9jcmVhdGlvbl8xaF90b2tlbnM6IHJlc3VsdC51c2FnZS5jYWNoZV9jcmVhdGlvbl8xaF9pbnB1dF90b2tlbnMsXG4gICAgICAgIGNvc3RfdXNkOiBNYXRoLnJvdW5kKHJlc3VsdC5jb3N0VXNkICogMV8wMDBfMDAwKSxcbiAgICAgICAgY29zdF9zb3VyY2U6IHJlc3VsdC5jb3N0U291cmNlLFxuICAgICAgICBkdXJhdGlvbl9tczogcmVzdWx0LmR1cmF0aW9uTXMsXG4gICAgICAgIHR0ZnRfbXM6IHJlc3VsdC50dGZ0TXMsXG4gICAgICAgIGZpbmlzaF9yZWFzb246IHJlc3VsdC5maW5pc2hSZWFzb24sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgaW1hZ2VQYXJ0cyA9IGdldEltYWdlUGFydHMocmVzdWx0KTtcbiAgICAgIGNvbnN0IGltYWdlQ29zdE1pY3JvVXNkID0gZXN0aW1hdGVJbWFnZUdlbmVyYXRpb25Db3N0TWljcm9Vc2QoXG4gICAgICAgIHJlc3VsdCxcbiAgICAgICAgYXJncy5pbWFnZUdlbmVyYXRpb25PcHRpb25zLFxuICAgICAgKTtcbiAgICAgIGZvciAoY29uc3Qgc3RlcCBvZiBidWlsZEltYWdlR2VuZXJhdGlvblRvb2xTdGVwcyhhcmdzLCBpbWFnZVBhcnRzLCBzdGVwSW5kZXgpKSB7XG4gICAgICAgIGF3YWl0IFJlcXVlc3RMb2dNb2RlbC5hcHBlbmRTdGVwKHJlcXVlc3RMb2dJZCwgc3RlcCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChyZXN1bHQuZmluaXNoUmVhc29uID09PSBcInRvb2wtY2FsbHNcIikge1xuICAgICAgICAvLyB0b29sLWNhbGwgc3RlcOydhCDsponsi5wg6riw66Gd7ZWY6rOgLCDri6TsnYwgZm9sbG93LXVw7J20IOqwmeydgCByb3fsl5Ag6rKw6rO866W8IOyxhOyatOuLpC5cbiAgICAgICAgY29uc3QgdG9vbENhbGxzID0gcmVzdWx0LmNvbnRlbnQuZmlsdGVyKChjKSA9PiBjLnR5cGUgPT09IFwidG9vbC1jYWxsXCIpO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRvb2xDYWxscy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGNvbnN0IHRjID0gdG9vbENhbGxzW2ldITtcbiAgICAgICAgICBpZiAodGMudHlwZSAhPT0gXCJ0b29sLWNhbGxcIikgY29udGludWU7XG4gICAgICAgICAgYXdhaXQgUmVxdWVzdExvZ01vZGVsLmFwcGVuZFN0ZXAocmVxdWVzdExvZ0lkLCB7XG4gICAgICAgICAgICBzdGVwX2luZGV4OiBzdGVwSW5kZXgsXG4gICAgICAgICAgICB0eXBlOiBcInRvb2xfY2FsbFwiLFxuICAgICAgICAgICAgdG9vbF9jYWxsX2luZGV4OiBpbWFnZVBhcnRzLmxlbmd0aCArIGksXG4gICAgICAgICAgICB0b29sX2NhbGxfaWQ6IHRjLnRvb2xDYWxsSWQsXG4gICAgICAgICAgICB0b29sX25hbWU6IHRjLnRvb2xOYW1lLFxuICAgICAgICAgICAgdG9vbF9hcmdzOiB0Yy5pbnB1dCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7IHJ1bkNvbnRleHQ6IHsgcmVxdWVzdExvZ0lkIH0gfTtcbiAgICAgIH1cblxuICAgICAgLy8gZmluaXNoUmVhc29uID09PSBcInN0b3BcIiDihpIgcnVuIOyiheujjCAo7KCE7LK0IHN0ZXAgdXNhZ2Ug7ZWp7IKwKVxuICAgICAgY29uc3QgYWdnID0gYXdhaXQgUmVxdWVzdExvZ01vZGVsLmFnZ3JlZ2F0ZVN0ZXBVc2FnZShyZXF1ZXN0TG9nSWQpO1xuICAgICAgYXdhaXQgUmVxdWVzdExvZ01vZGVsLmZpbmlzaFJ1bihyZXF1ZXN0TG9nSWQsIHtcbiAgICAgICAgc3RhdHVzOiBcInN1Y2NlZWRlZFwiLFxuICAgICAgICByZXNwb25zZTogZm9ybWF0UmVzcG9uc2VGb3JMb2cocmVzdWx0KSxcbiAgICAgICAgdG9rZW5fbmFtZTogcmVzdWx0LnRva2VuTmFtZSxcbiAgICAgICAgaW5wdXRfdG9rZW5zOiBhZ2cuaW5wdXRfdG9rZW5zLFxuICAgICAgICBvdXRwdXRfdG9rZW5zOiBhZ2cub3V0cHV0X3Rva2VucyxcbiAgICAgICAgY2FjaGVfcmVhZF90b2tlbnM6IGFnZy5jYWNoZV9yZWFkX3Rva2VucyxcbiAgICAgICAgY2FjaGVfY3JlYXRpb25fdG9rZW5zOiBhZ2cuY2FjaGVfY3JlYXRpb25fdG9rZW5zLFxuICAgICAgICBjYWNoZV9jcmVhdGlvbl81bV90b2tlbnM6IGFnZy5jYWNoZV9jcmVhdGlvbl81bV90b2tlbnMsXG4gICAgICAgIGNhY2hlX2NyZWF0aW9uXzFoX3Rva2VuczogYWdnLmNhY2hlX2NyZWF0aW9uXzFoX3Rva2VucyxcbiAgICAgICAgZHVyYXRpb25fbXM6IGFnZy5kdXJhdGlvbl9tcyxcbiAgICAgICAgLy8gbXVsdGktc3RlcCBydW4g67aA66qo7J2YIOuqqOuNuOydgCDstZzsooUgdHVybuydhCDshJzruZntlZwg66qo64247J2064ukLlxuICAgICAgICByZXF1ZXN0ZWRfbW9kZWxfbmFtZTogcmVxdWVzdGVkTW9kZWxOYW1lLFxuICAgICAgICBtb2RlbF9uYW1lOiBzZXJ2ZWRNb2RlbE5hbWUsXG4gICAgICAgIGZhbGxiYWNrX2NvdW50OiBhZ2cuZmFsbGJhY2tfY291bnQsXG4gICAgICAgIGNvc3RfdXNkOiBhZ2cuY29zdF91c2QsXG4gICAgICAgIGNvc3Rfc291cmNlOiBhZ2cuY29zdF9zb3VyY2UsXG4gICAgICAgIGltYWdlX2Nvc3RfdXNkOiBpbWFnZUNvc3RNaWNyb1VzZCxcbiAgICAgICAgaW1hZ2VfY29zdF9tZXRob2Q6XG4gICAgICAgICAgaW1hZ2VDb3N0TWljcm9Vc2QgIT09IG51bGxcbiAgICAgICAgICAgID8gaW1hZ2VHZW5lcmF0aW9uQ29zdE1ldGhvZChhcmdzLmltYWdlR2VuZXJhdGlvbk9wdGlvbnMpXG4gICAgICAgICAgICA6IG51bGwsXG4gICAgICAgIGhpc3Rvcnk6IGZpbHRlckhpc3RvcnlGb3JTdG9yYWdlKGFyZ3MuaGlzdG9yeSksXG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIHt9O1xuICAgIH0gZmluYWxseSB7XG4gICAgICByZWxlYXNlTmF0aXZlUnVuKHJlcXVlc3RMb2dJZCk7XG4gICAgfVxuICB9KTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGZpbmlzaFJ1bldpdGhFcnJvcihcbiAgcmVxdWVzdExvZ0lkOiBudW1iZXIsXG4gIGVycm9yTWVzc2FnZTogc3RyaW5nLFxuICBhcmdzPzogUXVlcnlJbnB1dCxcbik6IFByb21pc2U8dm9pZD4ge1xuICBpZiAoaW50ZXJydXB0ZWROYXRpdmVSdW5JZHMuaGFzKHJlcXVlc3RMb2dJZCkpIHJldHVybjtcbiAgcmV0dXJuIHRyYWNrTmF0aXZlRmluYWxpemVyKHJlcXVlc3RMb2dJZCwgYXN5bmMgKCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBmaW5pc2hUZXJtaW5hbFJ1bihyZXF1ZXN0TG9nSWQsIFwiZXJyb3JcIiwgZXJyb3JNZXNzYWdlLCBhcmdzKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgcmVsZWFzZU5hdGl2ZVJ1bihyZXF1ZXN0TG9nSWQpO1xuICAgIH1cbiAgfSk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBmaW5pc2hSdW5BYm9ydGVkKHJlcXVlc3RMb2dJZDogbnVtYmVyLCBhcmdzPzogUXVlcnlJbnB1dCk6IFByb21pc2U8dm9pZD4ge1xuICBpZiAoaW50ZXJydXB0ZWROYXRpdmVSdW5JZHMuaGFzKHJlcXVlc3RMb2dJZCkpIHJldHVybjtcbiAgcmV0dXJuIHRyYWNrTmF0aXZlRmluYWxpemVyKHJlcXVlc3RMb2dJZCwgYXN5bmMgKCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBmaW5pc2hUZXJtaW5hbFJ1bihyZXF1ZXN0TG9nSWQsIFwiYWJvcnRlZFwiLCBcImNsaWVudCBkaXNjb25uZWN0ZWRcIiwgYXJncyk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHJlbGVhc2VOYXRpdmVSdW4ocmVxdWVzdExvZ0lkKTtcbiAgICB9XG4gIH0pO1xufVxuXG4vKiog7ZiE7J6sIOydtCDtlITroZzshLjsiqTqsIAgcHJvdmlkZXLrpbwg7Iuk7ZaJIOykkeyduCBuYXRpdmUgcnVu66eMIOyerOyLnOyekSDsmKTrpZjroZwg66eI6rCQ7ZWc64ukLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGZpbmlzaEFjdGl2ZU5hdGl2ZVJ1bnNGb3JSZXN0YXJ0KCk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCByZXF1ZXN0TG9nSWRzID0gWy4uLmFjdGl2ZU5hdGl2ZVJ1blJlZnMua2V5cygpXTtcbiAgZm9yIChjb25zdCByZXF1ZXN0TG9nSWQgb2YgcmVxdWVzdExvZ0lkcykge1xuICAgIGludGVycnVwdGVkTmF0aXZlUnVuSWRzLmFkZChyZXF1ZXN0TG9nSWQpO1xuICAgIGFjdGl2ZU5hdGl2ZVJ1blJlZnMuZGVsZXRlKHJlcXVlc3RMb2dJZCk7XG4gIH1cblxuICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICByZXF1ZXN0TG9nSWRzLm1hcChhc3luYyAocmVxdWVzdExvZ0lkKSA9PiB7XG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChhY3RpdmVOYXRpdmVGaW5hbGl6ZXJzLmdldChyZXF1ZXN0TG9nSWQpID8/IFtdKTtcbiAgICAgIGF3YWl0IGZpbmlzaFRlcm1pbmFsUnVuKHJlcXVlc3RMb2dJZCwgXCJlcnJvclwiLCBcInNlcnZlciByZXN0YXJ0ZWRcIik7XG4gICAgfSksXG4gICk7XG59XG5cbi8qKiDtlITroZzshLjsiqQg7KCE7JetIHJlZ2lzdHJ566W8IOqyqeumrO2VtOyVvCDtlZjripQg64uo7JyEIO2FjOyKpO2KuCDsoITsmqkuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzZXROYXRpdmVSdW5SZWdpc3RyeUZvclRlc3RzKCk6IHZvaWQge1xuICBhY3RpdmVOYXRpdmVSdW5SZWZzLmNsZWFyKCk7XG4gIGludGVycnVwdGVkTmF0aXZlUnVuSWRzLmNsZWFyKCk7XG4gIGFjdGl2ZU5hdGl2ZUZpbmFsaXplcnMuY2xlYXIoKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZmluaXNoVGVybWluYWxSdW4oXG4gIHJlcXVlc3RMb2dJZDogbnVtYmVyLFxuICBzdGF0dXM6IFwiZXJyb3JcIiB8IFwiYWJvcnRlZFwiLFxuICBlcnJvck1lc3NhZ2U6IHN0cmluZyxcbiAgYXJncz86IFF1ZXJ5SW5wdXQsXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgdHJ5IHtcbiAgICBsZXQgYWdncmVnYXRlOiBBd2FpdGVkPFJldHVyblR5cGU8dHlwZW9mIFJlcXVlc3RMb2dNb2RlbC5hZ2dyZWdhdGVTdGVwVXNhZ2U+PiB8IHVuZGVmaW5lZDtcbiAgICB0cnkge1xuICAgICAgYWdncmVnYXRlID0gYXdhaXQgUmVxdWVzdExvZ01vZGVsLmFnZ3JlZ2F0ZVN0ZXBVc2FnZShyZXF1ZXN0TG9nSWQpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxvZ2dlci5lcnJvcihgYWdncmVnYXRlU3RlcFVzYWdlIGZhaWxlZCB3aGlsZSBmaW5pc2hpbmcgJHtzdGF0dXN9OiAkeyhlIGFzIEVycm9yKS5tZXNzYWdlfWApO1xuICAgIH1cblxuICAgIGF3YWl0IFJlcXVlc3RMb2dNb2RlbC5maW5pc2hSdW4ocmVxdWVzdExvZ0lkLCB7XG4gICAgICBzdGF0dXMsXG4gICAgICBlcnJvcl9tZXNzYWdlOiBlcnJvck1lc3NhZ2UsXG4gICAgICBoaXN0b3J5OiBhcmdzID8gZmlsdGVySGlzdG9yeUZvclN0b3JhZ2UoYXJncy5oaXN0b3J5KSA6IHVuZGVmaW5lZCxcbiAgICAgIC4uLihhZ2dyZWdhdGVcbiAgICAgICAgPyB7XG4gICAgICAgICAgICBpbnB1dF90b2tlbnM6IGFnZ3JlZ2F0ZS5pbnB1dF90b2tlbnMsXG4gICAgICAgICAgICBvdXRwdXRfdG9rZW5zOiBhZ2dyZWdhdGUub3V0cHV0X3Rva2VucyxcbiAgICAgICAgICAgIGNhY2hlX3JlYWRfdG9rZW5zOiBhZ2dyZWdhdGUuY2FjaGVfcmVhZF90b2tlbnMsXG4gICAgICAgICAgICBjYWNoZV9jcmVhdGlvbl90b2tlbnM6IGFnZ3JlZ2F0ZS5jYWNoZV9jcmVhdGlvbl90b2tlbnMsXG4gICAgICAgICAgICBjYWNoZV9jcmVhdGlvbl81bV90b2tlbnM6IGFnZ3JlZ2F0ZS5jYWNoZV9jcmVhdGlvbl81bV90b2tlbnMsXG4gICAgICAgICAgICBjYWNoZV9jcmVhdGlvbl8xaF90b2tlbnM6IGFnZ3JlZ2F0ZS5jYWNoZV9jcmVhdGlvbl8xaF90b2tlbnMsXG4gICAgICAgICAgICBkdXJhdGlvbl9tczogYWdncmVnYXRlLmR1cmF0aW9uX21zLFxuICAgICAgICAgICAgZmFsbGJhY2tfY291bnQ6IGFnZ3JlZ2F0ZS5mYWxsYmFja19jb3VudCxcbiAgICAgICAgICAgIGNvc3RfdXNkOiBhZ2dyZWdhdGUuY29zdF91c2QsXG4gICAgICAgICAgICBjb3N0X3NvdXJjZTogYWdncmVnYXRlLmNvc3Rfc291cmNlLFxuICAgICAgICAgIH1cbiAgICAgICAgOiB7fSksXG4gICAgfSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBsb2dnZXIuZXJyb3IoYGZpbmlzaFRlcm1pbmFsUnVuKCR7c3RhdHVzfSkgZmFpbGVkOiAkeyhlIGFzIEVycm9yKS5tZXNzYWdlfWApO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGNsZWFudXBTdGFsZVJ1bnMoKTogUHJvbWlzZTx2b2lkPiB7XG4gIGlmIChzdGFsZUNsZWFudXBJbkZsaWdodCkge1xuICAgIGF3YWl0IHN0YWxlQ2xlYW51cEluRmxpZ2h0O1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gIGlmIChub3cgLSBsYXN0U3RhbGVDbGVhbnVwU3RhcnRlZEF0IDwgU1RBTEVfQ0xFQU5VUF9JTlRFUlZBTF9NUykgcmV0dXJuO1xuICBsYXN0U3RhbGVDbGVhbnVwU3RhcnRlZEF0ID0gbm93O1xuXG4gIGNvbnN0IGNsZWFudXAgPSBwZXJmb3JtU3RhbGVSdW5DbGVhbnVwKCk7XG4gIHN0YWxlQ2xlYW51cEluRmxpZ2h0ID0gY2xlYW51cDtcbiAgdHJ5IHtcbiAgICBhd2FpdCBjbGVhbnVwO1xuICB9IGZpbmFsbHkge1xuICAgIGlmIChzdGFsZUNsZWFudXBJbkZsaWdodCA9PT0gY2xlYW51cCkgc3RhbGVDbGVhbnVwSW5GbGlnaHQgPSB1bmRlZmluZWQ7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gcGVyZm9ybVN0YWxlUnVuQ2xlYW51cCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBcInRvb2wtY2FsbCBydW46IG5vIGZvbGxvdy11cCB3aXRoaW4gMzAgbWludXRlc1wiO1xuICAgIGNvbnN0IHN0YWxlSWRzID0gYXdhaXQgUmVxdWVzdExvZ01vZGVsLmV4cGlyZVN0YWxlVG9vbFdhaXRpbmdSdW5zKFxuICAgICAgU1RBTEVfUlVOX1RIUkVTSE9MRF9NUyxcbiAgICAgIGVycm9yTWVzc2FnZSxcbiAgICApO1xuICAgIGNvbnN0IGNsZWFuZWRDb3VudCA9IHN0YWxlSWRzLmxlbmd0aDtcbiAgICBpZiAoY2xlYW5lZENvdW50ID4gMCkge1xuICAgICAgbG9nZ2VyLmluZm8oYGNsZWFuZWQgdXAgJHtjbGVhbmVkQ291bnR9IHN0YWxlIHJ1bm5pbmcgcmVxdWVzdCBsb2dzYCk7XG4gICAgfVxuICB9IGNhdGNoIChlKSB7XG4gICAgbG9nZ2VyLmVycm9yKGBzdGFsZSBjbGVhbnVwIGZhaWxlZDogJHsoZSBhcyBFcnJvcikubWVzc2FnZX1gKTtcbiAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7OztBQWlCQSxNQUFNLFNBQVMsVUFBVSxDQUFDLFNBQVMsZUFBZSxDQUFDO0FBQ25ELE1BQU0seUJBQXlCLE9BQVU7QUFDekMsTUFBTSw0QkFBNEIsS0FBSztBQUN2QyxJQUFJO0FBQ0osSUFBSSw0QkFBNEI7QUFDaEMsTUFBTSxzQ0FBc0IsSUFBSSxJQUFvQjtBQUNwRCxNQUFNLDBDQUEwQixJQUFJLElBQVk7QUFDaEQsTUFBTSx5Q0FBeUIsSUFBSSxJQUFnQztBQUVuRSxTQUFTLHFCQUFrRDtDQUN6RCxPQUFPLElBQUksNEJBQTRCLEdBQUcsc0JBQXNCLENBQUMsQ0FBQyxDQUFDO0FBQ3JFO0FBRUEsU0FBUyxrQkFBa0IsY0FBNEI7Q0FDckQsb0JBQW9CLElBQUksZUFBZSxvQkFBb0IsSUFBSSxZQUFZLEtBQUssS0FBSyxDQUFDO0FBQ3hGO0FBRUEsU0FBUyxpQkFBaUIsY0FBNEI7Q0FDcEQsTUFBTSxPQUFPLG9CQUFvQixJQUFJLFlBQVk7Q0FDakQsSUFBSSxTQUFTLFVBQWEsUUFBUSxHQUFHLG9CQUFvQixPQUFPLFlBQVk7TUFDdkUsb0JBQW9CLElBQUksY0FBYyxPQUFPLENBQUM7QUFDckQ7QUFFQSxTQUFT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
|