@cartanova/qgrid-cli 2.3.1 → 2.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/bundle/dist/application/qgrid/qgrid.dispatcher.js +94 -277
  2. package/bundle/dist/application/qgrid/qgrid.frame.js +15 -5
  3. package/bundle/dist/utils/providers/anthropic/anthropic-constants.js +33 -12
  4. package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +39 -96
  5. package/bundle/dist/utils/providers/anthropic/claude-session.js +47 -32
  6. package/bundle/dist/utils/providers/anthropic/stream-json-adapter.js +3 -36
  7. package/bundle/dist/utils/providers/common/model-cost.js +3 -2
  8. package/bundle/dist/utils/providers/openai/codex-worker.js +1 -2
  9. package/bundle/dist/utils/providers/openai/openai-dispatcher.js +19 -12
  10. package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +262 -2
  11. package/bundle/src/application/qgrid/qgrid.dispatcher.ts +142 -373
  12. package/bundle/src/application/qgrid/qgrid.frame.ts +38 -23
  13. package/bundle/src/utils/providers/anthropic/anthropic-constants.test.ts +60 -0
  14. package/bundle/src/utils/providers/anthropic/anthropic-constants.ts +57 -16
  15. package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.test.ts +92 -340
  16. package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +50 -185
  17. package/bundle/src/utils/providers/anthropic/claude-session.test.ts +71 -62
  18. package/bundle/src/utils/providers/anthropic/claude-session.ts +56 -46
  19. package/bundle/src/utils/providers/anthropic/stream-json-adapter.test.ts +19 -30
  20. package/bundle/src/utils/providers/anthropic/stream-json-adapter.ts +24 -101
  21. package/bundle/src/utils/providers/common/model-cost.test.ts +19 -1
  22. package/bundle/src/utils/providers/common/model-cost.ts +2 -1
  23. package/bundle/src/utils/providers/common/provider-dispatcher.ts +7 -4
  24. package/bundle/src/utils/providers/openai/codex-worker.ts +2 -8
  25. package/bundle/src/utils/providers/openai/openai-dispatcher.ts +18 -11
  26. package/package.json +1 -1
@@ -1,55 +1,17 @@
1
1
  import "../../_virtual/_rolldown/runtime.js";
2
2
  import { decideConvRouting, issueConvContext } from "./conv-routing.js";
3
3
  import { calculateCostUsd } from "../../utils/providers/common/model-cost.js";
4
- import { canonicalAnthropicModel } from "../../utils/providers/anthropic/anthropic-constants.js";
5
- import { getAccessToken, getExpiresAt, getRefreshToken } from "../../utils/providers/common/credentials.js";
4
+ import { getAccessToken } from "../../utils/providers/common/credentials.js";
6
5
  import { strictify } from "../../utils/providers/common/strictifier.js";
7
- import { ProcessError, QuotaError, TimeoutError, maskToken } from "./qgrid.types.js";
6
+ import { ProcessError, QuotaError, maskToken } from "./qgrid.types.js";
8
7
  import { applyToolCallEmulation, buildToolCallSchema } from "./tool-emulation.js";
9
- import { getLogger } from "@logtape/logtape";
10
- import assert from "node:assert";
11
- import { spawn } from "node:child_process";
12
- import { mkdirSync, writeFileSync } from "node:fs";
13
8
  //#region src/application/qgrid/qgrid.dispatcher.ts
14
- /**
15
- * QgridDispatcher — OAuth 토큰 선택 + claude CLI fresh spawn 디스패처 싱글턴.
16
- *
17
- * - 매 요청마다 새 claude CLI 프로세스 spawn → 응답 후 종료
18
- * - least-used round-robin 으로 토큰 선택
19
- * - 메모리 캐시 (Map<id, TokenSubsetA>) 는 TokenSubscriber 가 pg LISTEN/NOTIFY 로 갱신
20
- * - query 시 expires_at 비교 → 임박 시 preemptive refresh
21
- * - QuotaError 는 그대로 상위 전파 (자동 failover 없음, UI 에서 수동 토글)
22
- *
23
- * env allowlist: PATH, TMPDIR, CLAUDE_CODE_OAUTH_TOKEN, CLAUDE_CONFIG_DIR
24
- * + CLAUDE_CODE_DISABLE_* + CLAUDE_CODE_ATTRIBUTION_HEADER
25
- */
26
- const logger = getLogger(["qgrid"]);
27
- const DEFAULT_MODEL = "sonnet";
28
- const DEFAULT_TIMEOUT_MS = 6e5;
29
- const DEFAULT_EFFORT = "high";
30
- const CLAUDE_CWD = "/tmp/qgrid";
31
- const CLAUDE_CONFIG_DIR = "/tmp/qgrid-config";
32
- const QGRID_CLAUDE_SETTINGS = {
33
- alwaysThinkingEnabled: false,
34
- includeGitInstructions: false,
35
- cleanupPeriodDays: 1
36
- };
37
- const REFRESH_SAFETY_MS = 6e4;
38
9
  var QgridDispatcherClass = class {
39
10
  tokens = /* @__PURE__ */ new Map();
40
11
  requestCounts = /* @__PURE__ */ new Map();
41
- rrIndex = 0;
42
12
  subscriber = null;
43
13
  openaiDispatcher = null;
44
14
  anthropicDispatcher = null;
45
- constructor() {
46
- const settingsJson = JSON.stringify(QGRID_CLAUDE_SETTINGS, null, 2);
47
- mkdirSync(`${CLAUDE_CWD}/.claude`, { recursive: true });
48
- writeFileSync(`${CLAUDE_CWD}/.claude/settings.json`, settingsJson);
49
- mkdirSync(CLAUDE_CONFIG_DIR, { recursive: true });
50
- writeFileSync(`${CLAUDE_CONFIG_DIR}/.claude.json`, "{}");
51
- writeFileSync(`${CLAUDE_CONFIG_DIR}/settings.json`, settingsJson);
52
- }
53
15
  countOf(name) {
54
16
  return this.requestCounts.get(name) ?? 0;
55
17
  }
@@ -70,136 +32,112 @@ var QgridDispatcherClass = class {
70
32
  requests: this.countOf(r.name)
71
33
  }));
72
34
  }
73
- selectToken(provider = "anthropic") {
74
- const rows = [...this.tokens.values()].filter((r) => r.provider === provider);
75
- if (rows.length === 0) return null;
76
- const minCount = Math.min(...rows.map((r) => this.countOf(r.name)));
77
- const idle = rows.filter((r) => this.countOf(r.name) === minCount);
78
- const picked = idle[this.rrIndex % idle.length];
79
- this.rrIndex++;
80
- return picked;
81
- }
82
35
  async query(input, timeoutMs) {
83
36
  if (input.tools?.length && input.jsonSchema) throw new ProcessError("tools and jsonSchema cannot be used together");
84
- const outputSchema = input.tools?.length ? buildToolCallSchema(input.tools) : input.jsonSchema ? JSON.parse(input.jsonSchema) : void 0;
85
- if (input.model?.includes("/")) {
86
- const [provider, model] = input.model.split("/", 2);
87
- assert(model, "unknown model");
88
- if (provider === "openai") {
89
- if (!this.openaiDispatcher) throw new QuotaError("OpenAI dispatcher not initialized");
90
- const decision = decideConvRouting(input);
91
- const result = await this.openaiDispatcher.generate({
92
- model,
93
- systemPrompt: input.system,
94
- outputSchema: outputSchema ? strictify(outputSchema) : void 0,
95
- effort: input.effort,
96
- verbosity: input.verbosity,
97
- reasoningSummary: input.reasoningSummary,
98
- serviceTier: input.serviceTier,
99
- coldInput: decision.coldInput,
100
- coldHistory: decision.coldHistory,
101
- reuse: decision.reuse,
102
- reuseInput: decision.reuseInput
103
- });
104
- const issuedCoord = issueConvContext(result.threadCoord, decision);
105
- return applyToolCallEmulation(toEmulationResult(result), input.tools, issuedCoord);
106
- }
107
- }
108
- if (this.anthropicDispatcher) {
37
+ const outputSchema = buildStrictOutputSchema(input);
38
+ const route = parseProviderRoute(input.model);
39
+ if (route.provider === "openai") {
40
+ if (!this.openaiDispatcher) throw new QuotaError("OpenAI dispatcher not initialized");
109
41
  const decision = decideConvRouting(input);
110
- const result = await this.anthropicDispatcher.generate({
111
- model: input.model,
42
+ const result = await this.openaiDispatcher.generate({
43
+ model: route.model,
112
44
  systemPrompt: input.system,
113
- outputSchema: outputSchema ? strictify(outputSchema) : void 0,
45
+ outputSchema,
114
46
  effort: input.effort,
47
+ verbosity: input.verbosity,
48
+ reasoningSummary: input.reasoningSummary,
49
+ serviceTier: input.serviceTier,
115
50
  coldInput: decision.coldInput,
116
51
  coldHistory: decision.coldHistory,
117
52
  reuse: decision.reuse,
118
53
  reuseInput: decision.reuseInput
119
54
  });
120
- const issuedCoord = issueConvContext(result.threadCoord, decision);
121
- return applyToolCallEmulation(toEmulationResult(result), input.tools, issuedCoord);
122
- }
123
- const executionInput = outputSchema && input.tools?.length ? {
124
- ...input,
125
- jsonSchema: JSON.stringify(outputSchema)
126
- } : input;
127
- const electedToken = this.selectToken();
128
- if (!electedToken) throw new QuotaError("No tokens available");
129
- this.requestCounts.set(electedToken.name, this.countOf(electedToken.name) + 1);
130
- let token = getAccessToken(electedToken.credentials);
131
- const expiresAt = getExpiresAt(electedToken.credentials);
132
- if (expiresAt && expiresAt - Date.now() < REFRESH_SAFETY_MS && getRefreshToken(electedToken.credentials)) try {
133
- const { QgridFrame } = await import("./qgrid.frame.js");
134
- token = await QgridFrame.refreshToken(electedToken);
135
- } catch (e) {
136
- logger.warn(`refresh failed for ${electedToken.name}: ${e.message}`);
55
+ return applyToolCallEmulation(toEmulationResult(result), input.tools, issueConvContext(result.threadCoord, decision));
56
+ } else if (route.provider === "anthropic") {
57
+ if (!this.anthropicDispatcher) throw new QuotaError("Anthropic dispatcher not initialized");
58
+ const decision = decideConvRouting(input);
59
+ const result = await this.anthropicDispatcher.generate({
60
+ model: input.model,
61
+ systemPrompt: input.system,
62
+ outputSchema,
63
+ effort: input.effort,
64
+ coldInput: decision.coldInput,
65
+ coldHistory: decision.coldHistory
66
+ });
67
+ return applyToolCallEmulation(toEmulationResult(result), input.tools, issueConvContext(result.threadCoord, decision));
137
68
  }
138
- logger.info(`→ ${electedToken.name} (model: ${input.model ?? DEFAULT_MODEL})`);
139
- return applyToolCallEmulation({
140
- ...await executeClaude(executionInput, token, timeoutMs ?? DEFAULT_TIMEOUT_MS),
141
- tokenName: electedToken.name,
142
- model: canonicalAnthropicModel(input.model)
143
- }, input.tools);
69
+ throw directLlmApiFallbackNotImplemented(input);
144
70
  }
145
- async queryStream(input, cb) {
146
- if (!input.model?.startsWith("openai/")) {
147
- if (this.anthropicDispatcher) {
148
- const outputSchema = input.tools?.length ? buildToolCallSchema(input.tools) : input.jsonSchema ? JSON.parse(input.jsonSchema) : void 0;
149
- const decision = decideConvRouting(input);
150
- await this.anthropicDispatcher.generateStream({
151
- model: input.model,
152
- systemPrompt: input.system,
153
- outputSchema: outputSchema ? strictify(outputSchema) : void 0,
154
- effort: input.effort,
155
- coldInput: decision.coldInput,
156
- coldHistory: decision.coldHistory,
157
- reuse: decision.reuse,
158
- reuseInput: decision.reuseInput
159
- }, {
160
- onDelta: cb.onDelta,
161
- onThreadId: cb.onThreadId,
162
- onComplete: (turnResult) => {
163
- const issuedCoord = issueConvContext(turnResult.threadCoord, decision);
164
- cb.onComplete(applyToolCallEmulation(toEmulationResult(turnResult), input.tools, issuedCoord));
165
- },
166
- onError: cb.onError
167
- });
168
- return;
169
- }
170
- const result = await this.query(input);
171
- cb.onComplete(result);
71
+ async queryStream(input, cb, abortSignal) {
72
+ const outputSchema = buildStrictOutputSchema(input);
73
+ const route = parseProviderRoute(input.model);
74
+ if (route.provider === "openai") {
75
+ if (!this.openaiDispatcher) throw new QuotaError("OpenAI dispatcher not initialized");
76
+ const decision = decideConvRouting(input);
77
+ await this.openaiDispatcher.generateStream({
78
+ model: route.model,
79
+ systemPrompt: input.system,
80
+ outputSchema,
81
+ effort: input.effort,
82
+ verbosity: input.verbosity,
83
+ reasoningSummary: input.reasoningSummary,
84
+ serviceTier: input.serviceTier,
85
+ coldInput: decision.coldInput,
86
+ coldHistory: decision.coldHistory,
87
+ reuse: decision.reuse,
88
+ reuseInput: decision.reuseInput,
89
+ abortSignal
90
+ }, {
91
+ onDelta: cb.onDelta,
92
+ onThreadId: cb.onThreadId,
93
+ onTurnId: cb.onTurnId,
94
+ onComplete: (turnResult) => {
95
+ cb.onComplete(applyToolCallEmulation(toEmulationResult(turnResult), input.tools, issueConvContext(turnResult.threadCoord, decision)));
96
+ },
97
+ onError: cb.onError
98
+ });
99
+ return;
100
+ } else if (route.provider === "anthropic") {
101
+ if (!this.anthropicDispatcher) throw new QuotaError("Anthropic dispatcher not initialized");
102
+ const decision = decideConvRouting(input);
103
+ await this.anthropicDispatcher.generateStream({
104
+ model: input.model,
105
+ systemPrompt: input.system,
106
+ outputSchema,
107
+ effort: input.effort,
108
+ coldInput: decision.coldInput,
109
+ coldHistory: decision.coldHistory,
110
+ abortSignal
111
+ }, {
112
+ onDelta: cb.onDelta,
113
+ onThreadId: cb.onThreadId,
114
+ onComplete: (turnResult) => {
115
+ const issuedCoord = issueConvContext(turnResult.threadCoord, decision);
116
+ cb.onComplete(applyToolCallEmulation(toEmulationResult(turnResult), input.tools, issuedCoord));
117
+ },
118
+ onError: cb.onError
119
+ });
172
120
  return;
173
121
  }
174
- const [, model] = input.model.split("/", 2);
175
- if (!model) throw new ProcessError("unknown model");
176
- if (!this.openaiDispatcher) throw new QuotaError("OpenAI dispatcher not initialized");
177
- const outputSchema = input.tools?.length ? buildToolCallSchema(input.tools) : input.jsonSchema ? JSON.parse(input.jsonSchema) : void 0;
178
- const decision = decideConvRouting(input);
179
- await this.openaiDispatcher.generateStream({
180
- model,
181
- systemPrompt: input.system,
182
- outputSchema: outputSchema ? strictify(outputSchema) : void 0,
183
- effort: input.effort,
184
- verbosity: input.verbosity,
185
- reasoningSummary: input.reasoningSummary,
186
- serviceTier: input.serviceTier,
187
- coldInput: decision.coldInput,
188
- coldHistory: decision.coldHistory,
189
- reuse: decision.reuse,
190
- reuseInput: decision.reuseInput
191
- }, {
192
- onDelta: cb.onDelta,
193
- onThreadId: cb.onThreadId,
194
- onTurnId: cb.onTurnId,
195
- onComplete: (turnResult) => {
196
- const issuedCoord = issueConvContext(turnResult.threadCoord, decision);
197
- cb.onComplete(applyToolCallEmulation(toEmulationResult(turnResult), input.tools, issuedCoord));
198
- },
199
- onError: cb.onError
200
- });
122
+ throw directLlmApiFallbackNotImplemented(input);
201
123
  }
202
124
  };
125
+ function parseProviderRoute(model) {
126
+ if (!model?.includes("/")) return { model: model ?? "" };
127
+ const [provider, routedModel] = model.split("/", 2);
128
+ if (!provider || !routedModel) throw new ProcessError("unknown model");
129
+ return {
130
+ provider,
131
+ model: routedModel
132
+ };
133
+ }
134
+ function directLlmApiFallbackNotImplemented(input) {
135
+ return new ProcessError(`Direct LLM API fallback not implemented for model: ${input.model ?? "<default>"}`);
136
+ }
137
+ function buildStrictOutputSchema(input) {
138
+ const outputSchema = input.tools?.length ? buildToolCallSchema(input.tools) : input.jsonSchema ? JSON.parse(input.jsonSchema) : void 0;
139
+ return outputSchema ? strictify(outputSchema) : void 0;
140
+ }
203
141
  function toEmulationResult(result) {
204
142
  return {
205
143
  text: result.text,
@@ -220,129 +158,8 @@ function toEmulationResult(result) {
220
158
  })
221
159
  };
222
160
  }
223
- async function executeClaude(input, token, timeoutMs) {
224
- const rawModel = input.model ?? DEFAULT_MODEL;
225
- const model = rawModel.includes("/") ? rawModel.split("/").pop() : rawModel;
226
- const timeout = input.timeout ?? timeoutMs;
227
- const useStructuredOutput = input.jsonSchema && input.jsonSchema.length > 0;
228
- const args = [
229
- "-p",
230
- ...useStructuredOutput ? [
231
- "--tools",
232
- "",
233
- "--allowed-tools",
234
- "StructuredOutput"
235
- ] : ["--tools", ""],
236
- "--disallowedTools",
237
- ...[
238
- "Monitor",
239
- "PushNotification",
240
- "RemoteTrigger"
241
- ],
242
- "--output-format",
243
- "stream-json",
244
- "--verbose",
245
- "--max-turns",
246
- useStructuredOutput ? "2" : "1",
247
- "--permission-mode",
248
- "bypassPermissions",
249
- "--setting-sources",
250
- "project",
251
- "--model",
252
- model,
253
- "--system-prompt",
254
- input.system ?? "",
255
- "--thinking",
256
- "disabled",
257
- "--effort",
258
- input.effort ?? DEFAULT_EFFORT,
259
- "--no-session-persistence",
260
- "--disable-slash-commands"
261
- ];
262
- if (useStructuredOutput) args.push("--json-schema", input.jsonSchema);
263
- args.push(input.prompt);
264
- const env = {
265
- PATH: process.env.PATH,
266
- TMPDIR: process.env.TMPDIR,
267
- CLAUDE_CODE_OAUTH_TOKEN: token,
268
- CLAUDE_CONFIG_DIR,
269
- CLAUDE_CODE_DISABLE_AUTO_MEMORY: "1",
270
- CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING: "1",
271
- CLAUDE_CODE_DISABLE_1M_CONTEXT: "1",
272
- CLAUDE_CODE_DISABLE_CLAUDE_MDS: "1",
273
- CLAUDE_CODE_ATTRIBUTION_HEADER: "0"
274
- };
275
- return new Promise((resolve, reject) => {
276
- const child = spawn("claude", args, {
277
- stdio: [
278
- "ignore",
279
- "pipe",
280
- "ignore"
281
- ],
282
- env,
283
- cwd: CLAUDE_CWD
284
- });
285
- let buffer = "";
286
- let settled = false;
287
- const timer = setTimeout(() => {
288
- if (settled) return;
289
- settled = true;
290
- child.kill();
291
- reject(new TimeoutError(`Timeout after ${timeout / 1e3}s (token: ${maskToken(token)})`));
292
- }, timeout);
293
- child.stdout?.on("data", (d) => {
294
- if (settled) return;
295
- buffer += d.toString();
296
- const lines = buffer.split("\n");
297
- buffer = lines.pop() ?? "";
298
- for (const line of lines) {
299
- if (!line.trim()) continue;
300
- try {
301
- const j = JSON.parse(line);
302
- if (j.type === "result" && !settled) {
303
- let text;
304
- if (j.structured_output !== void 0) text = JSON.stringify(j.structured_output);
305
- else text = (j.result ?? "").replace(/^```(?:json)?\s*\n?/i, "").replace(/\n?```\s*$/i, "");
306
- if (text.startsWith("You've hit")) {
307
- settled = true;
308
- clearTimeout(timer);
309
- reject(new QuotaError(`Quota exhausted (token: ${maskToken(token)})`));
310
- return;
311
- }
312
- const u = j.usage ?? {};
313
- settled = true;
314
- clearTimeout(timer);
315
- resolve({
316
- text,
317
- usage: {
318
- input_tokens: u.input_tokens ?? 0,
319
- output_tokens: u.output_tokens ?? 0,
320
- cache_creation_input_tokens: u.cache_creation_input_tokens ?? 0,
321
- cache_read_input_tokens: u.cache_read_input_tokens ?? 0
322
- },
323
- durationMs: j.duration_ms ?? 0,
324
- costUsd: j.total_cost_usd ?? 0
325
- });
326
- }
327
- } catch {}
328
- }
329
- });
330
- child.on("close", () => {
331
- if (settled) return;
332
- settled = true;
333
- clearTimeout(timer);
334
- reject(new ProcessError(`CLI process closed without result (token: ${maskToken(token)})`));
335
- });
336
- child.on("error", (err) => {
337
- if (settled) return;
338
- settled = true;
339
- clearTimeout(timer);
340
- reject(new ProcessError(`CLI process error: ${err.message} (token: ${maskToken(token)})`));
341
- });
342
- });
343
- }
344
161
  const QgridDispatcher = new QgridDispatcherClass();
345
162
  //#endregion
346
- export { QgridDispatcher, QgridDispatcherClass };
163
+ export { QgridDispatcher, QgridDispatcherClass, buildStrictOutputSchema };
347
164
 
348
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicWdyaWQuZGlzcGF0Y2hlci5qcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBwbGljYXRpb24vcWdyaWQvcWdyaWQuZGlzcGF0Y2hlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgYXNzZXJ0IGZyb20gXCJub2RlOmFzc2VydFwiO1xuLyoqXG4gKiBRZ3JpZERpc3BhdGNoZXIg4oCUIE9BdXRoIO2GoO2BsCDshKDtg50gKyBjbGF1ZGUgQ0xJIGZyZXNoIHNwYXduIOuUlOyKpO2MqOyymCDsi7HquIDthLQuXG4gKlxuICogLSDrp6Qg7JqU7LKt66eI64ukIOyDiCBjbGF1ZGUgQ0xJIO2UhOuhnOyEuOyKpCBzcGF3biDihpIg7J2R64u1IO2bhCDsooXro4xcbiAqIC0gbGVhc3QtdXNlZCByb3VuZC1yb2JpbiDsnLzroZwg7Yag7YGwIOyEoO2DnVxuICogLSDrqZTrqqjrpqwg7LqQ7IucIChNYXA8aWQsIFRva2VuU3Vic2V0QT4pIOuKlCBUb2tlblN1YnNjcmliZXIg6rCAIHBnIExJU1RFTi9OT1RJRlkg66GcIOqwseyLoFxuICogLSBxdWVyeSDsi5wgZXhwaXJlc19hdCDruYTqtZAg4oaSIOyehOuwlSDsi5wgcHJlZW1wdGl2ZSByZWZyZXNoXG4gKiAtIFF1b3RhRXJyb3Ig64qUIOq3uOuMgOuhnCDsg4HsnIQg7KCE7YyMICjsnpDrj5kgZmFpbG92ZXIg7JeG7J2MLCBVSSDsl5DshJwg7IiY64+ZIO2GoOq4gClcbiAqXG4gKiBlbnYgYWxsb3dsaXN0OiBQQVRILCBUTVBESVIsIENMQVVERV9DT0RFX09BVVRIX1RPS0VOLCBDTEFVREVfQ09ORklHX0RJUlxuICogICArIENMQVVERV9DT0RFX0RJU0FCTEVfKiArIENMQVVERV9DT0RFX0FUVFJJQlVUSU9OX0hFQURFUlxuICovXG5pbXBvcnQgeyBzcGF3biB9IGZyb20gXCJub2RlOmNoaWxkX3Byb2Nlc3NcIjtcbmltcG9ydCB7IG1rZGlyU3luYywgd3JpdGVGaWxlU3luYyB9IGZyb20gXCJub2RlOmZzXCI7XG5cbmltcG9ydCB7IGdldExvZ2dlciB9IGZyb20gXCJAbG9ndGFwZS9sb2d0YXBlXCI7XG5cbmltcG9ydCB7IHR5cGUgSnNvblZhbHVlIH0gZnJvbSBcIi4uLy4uL2NvZGV4LXByb3RvY29sL3NlcmRlX2pzb24vSnNvblZhbHVlXCI7XG5pbXBvcnQgeyBjYW5vbmljYWxBbnRocm9waWNNb2RlbCB9IGZyb20gXCIuLi8uLi91dGlscy9wcm92aWRlcnMvYW50aHJvcGljL2FudGhyb3BpYy1jb25zdGFudHNcIjtcbmltcG9ydCB7IHR5cGUgQW50aHJvcGljRGlzcGF0Y2hlciB9IGZyb20gXCIuLi8uLi91dGlscy9wcm92aWRlcnMvYW50aHJvcGljL2FudGhyb3BpYy1kaXNwYXRjaGVyXCI7XG5pbXBvcnQge1xuICBnZXRBY2Nlc3NUb2tlbixcbiAgZ2V0RXhwaXJlc0F0LFxuICBnZXRSZWZyZXNoVG9rZW4sXG59IGZyb20gXCIuLi8uLi91dGlscy9wcm92aWRlcnMvY29tbW9uL2NyZWRlbnRpYWxzXCI7XG5pbXBvcnQgeyBjYWxjdWxhdGVDb3N0VXNkIH0gZnJvbSBcIi4uLy4uL3V0aWxzL3Byb3ZpZGVycy9jb21tb24vbW9kZWwtY29zdFwiO1xuaW1wb3J0IHsgdHlwZSBHZW5lcmF0ZVJlc3VsdCB9IGZyb20gXCIuLi8uLi91dGlscy9wcm92aWRlcnMvY29tbW9uL3Byb3ZpZGVyLWRpc3BhdGNoZXJcIjtcbmltcG9ydCB7IHN0cmljdGlmeSB9IGZyb20gXCIuLi8uLi91dGlscy9wcm92aWRlcnMvY29tbW9uL3N0cmljdGlmaWVyXCI7XG5pbXBvcnQgeyB0eXBlIE9wZW5BSURpc3BhdGNoZXIgfSBmcm9tIFwiLi4vLi4vdXRpbHMvcHJvdmlkZXJzL29wZW5haS9vcGVuYWktZGlzcGF0Y2hlclwiO1xuaW1wb3J0IHsgdHlwZSBUb2tlblN1YnNldEEgfSBmcm9tIFwiLi4vc29uYW11LmdlbmVyYXRlZFwiO1xuaW1wb3J0IHsgZGVjaWRlQ29udlJvdXRpbmcsIGlzc3VlQ29udkNvbnRleHQgfSBmcm9tIFwiLi9jb252LXJvdXRpbmdcIjtcbmltcG9ydCB7IHR5cGUgUXVlcnlJbnB1dCwgdHlwZSBRdWVyeU91dHB1dCwgdHlwZSBUb2tlblN0YXRzIH0gZnJvbSBcIi4vcWdyaWQudHlwZXNcIjtcbmltcG9ydCB7IG1hc2tUb2tlbiwgUHJvY2Vzc0Vycm9yLCBRdW90YUVycm9yLCBUaW1lb3V0RXJyb3IgfSBmcm9tIFwiLi9xZ3JpZC50eXBlc1wiO1xuaW1wb3J0IHsgdHlwZSBUb2tlblN1YnNjcmliZXIgfSBmcm9tIFwiLi90b2tlbi1zdWJzY3JpYmVyXCI7XG5pbXBvcnQgeyBhcHBseVRvb2xDYWxsRW11bGF0aW9uLCBidWlsZFRvb2xDYWxsU2NoZW1hIH0gZnJvbSBcIi4vdG9vbC1lbXVsYXRpb25cIjtcblxuY29uc3QgbG9nZ2VyID0gZ2V0TG9nZ2VyKFtcInFncmlkXCJdKTtcblxuY29uc3QgREVGQVVMVF9NT0RFTCA9IFwic29ubmV0XCI7XG5jb25zdCBERUZBVUxUX1RJTUVPVVRfTVMgPSA2MDBfMDAwO1xuY29uc3QgREVGQVVMVF9FRkZPUlQgPSBcImhpZ2hcIjtcblxuLy8gY2xhdWRlIENMSSDsnZggY3dkLiDsnbQg6rK966Gc7J2YIC5jbGF1ZGUvc2V0dGluZ3MuanNvbiDsnbQgcHJvamVjdCBzY29wZSDroZwg66Gc65Oc65CY7Ja0XG4vLyDtmLnsi5zrnbzrj4Qg7J6I7J2EIHVzZXIgc2NvcGUgKH4vLmNsYXVkZS9zZXR0aW5ncy5qc29uKeulvCDrja7slrTslIAgKC0tc2V0dGluZy1zb3VyY2VzIHByb2plY3Qg7JmAIO2VqOq7mCkuXG5jb25zdCBDTEFVREVfQ1dEID0gXCIvdG1wL3FncmlkXCI7XG5cbi8vIOq4gOuhnOuyjCB1c2VyIGNvbmZpZyDqsqnrpqwg6rK966GcLiAoQ0Psl5DshJwg7ZmY6rK967OA7IiY66GcIOydveuKlOuzgOyImClcbmNvbnN0IENMQVVERV9DT05GSUdfRElSID0gXCIvdG1wL3FncmlkLWNvbmZpZ1wiO1xuXG4vLyBxZ3JpZCDsoITsmqkgcHJvamVjdC9nbG9iYWwgc2V0dGluZ3Mg4oCUIHVzZXIgc2NvcGUg6rKp66as7JqpXG5jb25zdCBRR1JJRF9DTEFVREVfU0VUVElOR1MgPSB7XG4gIGFsd2F5c1RoaW5raW5nRW5hYmxlZDogZmFsc2UsIC8vIHRoaW5raW5nIGJsb2NrIOywqOuLqFxuICBpbmNsdWRlR2l0SW5zdHJ1Y3Rpb25zOiBmYWxzZSwgLy8gc3lzdGVtIHByb21wdCDsnZggZ2l0IOqwgOydtOuTnCDsoJzqsbBcbiAgY2xlYW51cFBlcmlvZERheXM6IDEsXG59O1xuXG4vLyDthqDtgbAg66eM66OMIOyehOuwlSDsnoTqs4TqsJIg4oCUIHRva2VuLmV4cGlyZWRBdOydtCAx67aEIOyViOyXkCDrp4zro4zrkJzri6TrqbQgcXVlcnkg7IucIOyytO2BrO2VmOqzoCByZWZyZXNoLlxuY29uc3QgUkVGUkVTSF9TQUZFVFlfTVMgPSA2MF8wMDA7XG5cbmV4cG9ydCBjbGFzcyBRZ3JpZERpc3BhdGNoZXJDbGFzcyB7XG4gIHRva2VucyA9IG5ldyBNYXA8bnVtYmVyLCBUb2tlblN1YnNldEE+KCk7XG5cbiAgLy8ga2V56riw67CYKHRva2VuTmFtZSkg64iE7KCBIOy5tOyatO2EsC4gdG9rZW4g7J20IE9BdXRoIHJlZnJlc2gg66GcIOuhnO2FjOydtO2KuOuQmOuPhCB0b2tlbk5hbWUg7J2AIOu2iOuzgOydtOudvCDsubTsmrTthLAg7Jyg7KeA65CoXG4gIHJlcXVlc3RDb3VudHMgPSBuZXcgTWFwPHN0cmluZywgbnVtYmVyPigpO1xuICByckluZGV4ID0gMDtcblxuICAvLyBzb25hbXUuY29uZmlnIG9uU3RhcnQg7JeQ7IScIOyymOumrO2VmOuKlCDrs4DsiJhcbiAgc3Vic2NyaWJlcjogVG9rZW5TdWJzY3JpYmVyIHwgbnVsbCA9IG51bGw7XG4gIG9wZW5haURpc3BhdGNoZXI6IE9wZW5BSURpc3BhdGNoZXIgfCBudWxsID0gbnVsbDtcbiAgYW50aHJvcGljRGlzcGF0Y2hlcjogQW50aHJvcGljRGlzcGF0Y2hlciB8IG51bGwgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIGNvbnN0IHNldHRpbmdzSnNvbiA9IEpTT04uc3RyaW5naWZ5KFFHUklEX0NMQVVERV9TRVRUSU5HUywgbnVsbCwgMik7XG5cbiAgICBta2RpclN5bmMoYCR7Q0xBVURFX0NXRH0vLmNsYXVkZWAsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgIHdyaXRlRmlsZVN5bmMoYCR7Q0xBVURFX0NXRH0vLmNsYXVkZS9zZXR0aW5ncy5qc29uYCwgc2V0dGluZ3NKc29uKTtcblxuICAgIG1rZGlyU3luYyhDTEFVREVfQ09ORklHX0RJUiwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgd3JpdGVGaWxlU3luYyhgJHtDTEFVREVfQ09ORklHX0RJUn0vLmNsYXVkZS5qc29uYCwgXCJ7fVwiKTtcbiAgICB3cml0ZUZpbGVTeW5jKGAke0NMQVVERV9DT05GSUdfRElSfS9zZXR0aW5ncy5qc29uYCwgc2V0dGluZ3NKc29uKTtcbiAgfVxuXG4gIGNvdW50T2YobmFtZTogc3RyaW5nKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5yZXF1ZXN0Q291bnRzLmdldChuYW1lKSA/PyAwO1xuICB9XG5cbiAgLy8gVG9rZW5TdWJzY3JpYmVyIOy9nOuwsSDigJQg7LqQ7IucIG11dGF0aW9uXG4gIHVwc2VydENhY2hlKGlkOiBudW1iZXIsIHJvdzogVG9rZW5TdWJzZXRBKTogdm9pZCB7XG4gICAgdGhpcy50b2tlbnMuc2V0KGlkLCByb3cpO1xuICB9XG5cbiAgcmVtb3ZlQ2FjaGUoaWQ6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMudG9rZW5zLmRlbGV0ZShpZCk7XG4gIH1cblxuICByZXBsYWNlQ2FjaGUocm93czogVG9rZW5TdWJzZXRBW10pOiB2b2lkIHtcbiAgICB0aGlzLnRva2VucyA9IG5ldyBNYXAocm93cy5tYXAoKHIpID0+IFtyLmlkLCByXSkpO1xuICB9XG5cbiAgZ2V0U3RhdHMoKTogVG9rZW5TdGF0c1tdIHtcbiAgICByZXR1cm4gWy4uLnRoaXMudG9rZW5zLnZhbHVlcygpXS5tYXAoKHIpID0+ICh7XG4gICAgICB0b2tlbjogbWFza1Rva2VuKGdldEFjY2Vzc1Rva2VuKHIuY3JlZGVudGlhbHMpKSxcbiAgICAgIG5hbWU6IHIubmFtZSxcbiAgICAgIHByb3ZpZGVyOiByLnByb3ZpZGVyLFxuICAgICAgcmVxdWVzdHM6IHRoaXMuY291bnRPZihyLm5hbWUpLFxuICAgIH0pKTtcbiAgfVxuXG4gIHNlbGVjdFRva2VuKHByb3ZpZGVyID0gXCJhbnRocm9waWNcIik6IFRva2VuU3Vic2V0QSB8IG51bGwge1xuICAgIGNvbnN0IHJvd3MgPSBbLi4udGhpcy50b2tlbnMudmFsdWVzKCldLmZpbHRlcigocikgPT4gci5wcm92aWRlciA9PT0gcHJvdmlkZXIpO1xuICAgIGlmIChyb3dzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIG51bGw7XG5cbiAgICBjb25zdCBtaW5Db3VudCA9IE1hdGgubWluKC4uLnJvd3MubWFwKChyKSA9PiB0aGlzLmNvdW50T2Yoci5uYW1lKSkpO1xuICAgIGNvbnN0IGlkbGUgPSByb3dzLmZpbHRlcigocikgPT4gdGhpcy5jb3VudE9mKHIubmFtZSkgPT09IG1pbkNvdW50KTtcbiAgICBjb25zdCBwaWNrZWQgPSBpZGxlW3RoaXMucnJJbmRleCAlIGlkbGUubGVuZ3RoXSE7XG4gICAgdGhpcy5yckluZGV4Kys7XG4gICAgcmV0dXJuIHBpY2tlZDtcbiAgfVxuXG4gIGFzeW5jIHF1ZXJ5KGlucHV0OiBRdWVyeUlucHV0LCB0aW1lb3V0TXM/OiBudW1iZXIpOiBQcm9taXNlPFF1ZXJ5T3V0cHV0PiB7XG4gICAgaWYgKGlucHV0LnRvb2xzPy5sZW5ndGggJiYgaW5wdXQuanNvblNjaGVtYSkge1xuICAgICAgdGhyb3cgbmV3IFByb2Nlc3NFcnJvcihcInRvb2xzIGFuZCBqc29uU2NoZW1hIGNhbm5vdCBiZSB1c2VkIHRvZ2V0aGVyXCIpO1xuICAgIH1cblxuICAgIGNvbnN0IG91dHB1dFNjaGVtYSA9IGlucHV0LnRvb2xzPy5sZW5ndGhcbiAgICAgID8gYnVpbGRUb29sQ2FsbFNjaGVtYShpbnB1dC50b29scylcbiAgICAgIDogaW5wdXQuanNvblNjaGVtYVxuICAgICAgICA/IChKU09OLnBhcnNlKGlucHV0Lmpzb25TY2hlbWEpIGFzIEpzb25WYWx1ZSlcbiAgICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICAvLyBwcm92aWRlciBwcmVmaXggcm91dGluZzogJ29wZW5haS9ncHQtNS40JyDihpIgT3BlbkFJRGlzcGF0Y2hlclxuICAgIGlmIChpbnB1dC5tb2RlbD8uaW5jbHVkZXMoXCIvXCIpKSB7XG4gICAgICBjb25zdCBbcHJvdmlkZXIsIG1vZGVsXSA9IGlucHV0Lm1vZGVsLnNwbGl0KFwiL1wiLCAyKTtcbiAgICAgIGFzc2VydChtb2RlbCwgXCJ1bmtub3duIG1vZGVsXCIpO1xuICAgICAgaWYgKHByb3ZpZGVyID09PSBcIm9wZW5haVwiKSB7XG4gICAgICAgIGlmICghdGhpcy5vcGVuYWlEaXNwYXRjaGVyKSB0aHJvdyBuZXcgUXVvdGFFcnJvcihcIk9wZW5BSSBkaXNwYXRjaGVyIG5vdCBpbml0aWFsaXplZFwiKTtcbiAgICAgICAgY29uc3QgZGVjaXNpb24gPSBkZWNpZGVDb252Um91dGluZyhpbnB1dCk7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMub3BlbmFpRGlzcGF0Y2hlci5nZW5lcmF0ZSh7XG4gICAgICAgICAgbW9kZWw6IG1vZGVsLFxuICAgICAgICAgIHN5c3RlbVByb21wdDogaW5wdXQuc3lzdGVtLFxuICAgICAgICAgIG91dHB1dFNjaGVtYTogb3V0cHV0U2NoZW1hXG4gICAgICAgICAgICA/IChzdHJpY3RpZnkob3V0cHV0U2NoZW1hIGFzIFBhcmFtZXRlcnM8dHlwZW9mIHN0cmljdGlmeT5bMF0pIGFzIEpzb25WYWx1ZSlcbiAgICAgICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgICAgIGVmZm9ydDogaW5wdXQuZWZmb3J0LFxuICAgICAgICAgIHZlcmJvc2l0eTogaW5wdXQudmVyYm9zaXR5LFxuICAgICAgICAgIHJlYXNvbmluZ1N1bW1hcnk6IGlucHV0LnJlYXNvbmluZ1N1bW1hcnksXG4gICAgICAgICAgc2VydmljZVRpZXI6IGlucHV0LnNlcnZpY2VUaWVyLFxuICAgICAgICAgIGNvbGRJbnB1dDogZGVjaXNpb24uY29sZElucHV0LFxuICAgICAgICAgIGNvbGRIaXN0b3J5OiBkZWNpc2lvbi5jb2xkSGlzdG9yeSxcbiAgICAgICAgICByZXVzZTogZGVjaXNpb24ucmV1c2UsXG4gICAgICAgICAgcmV1c2VJbnB1dDogZGVjaXNpb24ucmV1c2VJbnB1dCxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgaXNzdWVkQ29vcmQgPSBpc3N1ZUNvbnZDb250ZXh0KHJlc3VsdC50aHJlYWRDb29yZCwgZGVjaXNpb24pO1xuICAgICAgICByZXR1cm4gYXBwbHlUb29sQ2FsbEVtdWxhdGlvbih0b0VtdWxhdGlvblJlc3VsdChyZXN1bHQpLCBpbnB1dC50b29scywgaXNzdWVkQ29vcmQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEFudGhyb3BpYyDigJQgQW50aHJvcGljRGlzcGF0Y2hlcijrqYDti7DthLQgc2Vzc2lvbiByZXN1bWUpIOqyveuhnC4gT3BlbkFJIOqyveuhnOyZgCDrj5ntmJUuXG4gICAgaWYgKHRoaXMuYW50aHJvcGljRGlzcGF0Y2hlcikge1xuICAgICAgY29uc3QgZGVjaXNpb24gPSBkZWNpZGVDb252Um91dGluZyhpbnB1dCk7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmFudGhyb3BpY0Rpc3BhdGNoZXIuZ2VuZXJhdGUoe1xuICAgICAgICAvLyBtb2RlbCDrr7jsp4DsoJXsnbTrqbQgQW50aHJvcGljRGlzcGF0Y2hlciDqsIAgQU5USFJPUElDX0RFRkFVTFRfTU9ERUwg7KCB7JqpIOKAlCBcInNvbm5ldFwiIOuzhOy5reydhFxuICAgICAgICAvLyDqsJXsoJzroZwg64G87JuMIGRpc3BhdGNoZXIgZGVmYXVsdCDrpbwg7KO97J207KeAIOyViuuKlOuLpC4gcHJlZml4IOygleq3nO2ZlOuPhCBkaXNwYXRjaGVyIOuCtOu2gOyXkOyEnC5cbiAgICAgICAgbW9kZWw6IGlucHV0Lm1vZGVsLFxuICAgICAgICBzeXN0ZW1Qcm9tcHQ6IGlucHV0LnN5c3RlbSxcbiAgICAgICAgb3V0cHV0U2NoZW1hOiBvdXRwdXRTY2hlbWFcbiAgICAgICAgICA/IChzdHJpY3RpZnkob3V0cHV0U2NoZW1hIGFzIFBhcmFtZXRlcnM8dHlwZW9mIHN0cmljdGlmeT5bMF0pIGFzIEpzb25WYWx1ZSlcbiAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgICAgZWZmb3J0OiBpbnB1dC5lZmZvcnQsXG4gICAgICAgIGNvbGRJbnB1dDogZGVjaXNpb24uY29sZElucHV0LFxuICAgICAgICBjb2xkSGlzdG9yeTogZGVjaXNpb24uY29sZEhpc3RvcnksXG4gICAgICAgIHJldXNlOiBkZWNpc2lvbi5yZXVzZSxcbiAgICAgICAgcmV1c2VJbnB1dDogZGVjaXNpb24ucmV1c2VJbnB1dCxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBpc3N1ZWRDb29yZCA9IGlzc3VlQ29udkNvbnRleHQocmVzdWx0LnRocmVhZENvb3JkLCBkZWNpc2lvbik7XG4gICAgICByZXR1cm4gYXBwbHlUb29sQ2FsbEVtdWxhdGlvbih0b0VtdWxhdGlvblJlc3VsdChyZXN1bHQpLCBpbnB1dC50b29scywgaXNzdWVkQ29vcmQpO1xuICAgIH1cblxuICAgIC8vIO2PtOuwsTogQW50aHJvcGljRGlzcGF0Y2hlciDrr7jstIjquLDtmZQg7IucIOq4sOyhtCBzdGF0ZWxlc3MgY2xhdWRlIC1wIOqyveuhnCjrqYDti7DthLQg7JeG7J2MKS5cbiAgICBjb25zdCBleGVjdXRpb25JbnB1dCA9XG4gICAgICBvdXRwdXRTY2hlbWEgJiYgaW5wdXQudG9vbHM/Lmxlbmd0aFxuICAgICAgICA/IHsgLi4uaW5wdXQsIGpzb25TY2hlbWE6IEpTT04uc3RyaW5naWZ5KG91dHB1dFNjaGVtYSkgfVxuICAgICAgICA6IGlucHV0O1xuXG4gICAgY29uc3QgZWxlY3RlZFRva2VuID0gdGhpcy5zZWxlY3RUb2tlbigpO1xuICAgIGlmICghZWxlY3RlZFRva2VuKSB0aHJvdyBuZXcgUXVvdGFFcnJvcihcIk5vIHRva2VucyBhdmFpbGFibGVcIik7XG5cbiAgICAvLyBhd2FpdCDsoITsl5AgY291bnQg7ISg67CY7JiBLiDrs5HroKwg7JqU7LKt7J20IOuPmeyLnOyXkCDrj4TssKntlbTrj4Qg6rCB7J6QIOuLpOuluCDthqDtgbDsnYQg6rOg66W064+E66GdLlxuICAgIHRoaXMucmVxdWVzdENvdW50cy5zZXQoZWxlY3RlZFRva2VuLm5hbWUsIHRoaXMuY291bnRPZihlbGVjdGVkVG9rZW4ubmFtZSkgKyAxKTtcblxuICAgIGxldCB0b2tlbiA9IGdldEFjY2Vzc1Rva2VuKGVsZWN0ZWRUb2tlbi5jcmVkZW50aWFscyk7XG4gICAgLy8gZXhwaXJlc19hdCDsnoTrsJXsnbTrqbQgcHJlZW1wdGl2ZSByZWZyZXNoXG4gICAgY29uc3QgZXhwaXJlc0F0ID0gZ2V0RXhwaXJlc0F0KGVsZWN0ZWRUb2tlbi5jcmVkZW50aWFscyk7XG4gICAgaWYgKFxuICAgICAgZXhwaXJlc0F0ICYmXG4gICAgICBleHBpcmVzQXQgLSBEYXRlLm5vdygpIDwgUkVGUkVTSF9TQUZFVFlfTVMgJiZcbiAgICAgIGdldFJlZnJlc2hUb2tlbihlbGVjdGVkVG9rZW4uY3JlZGVudGlhbHMpXG4gICAgKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCB7IFFncmlkRnJhbWUgfSA9IGF3YWl0IGltcG9ydChcIi4vcWdyaWQuZnJhbWVcIik7XG4gICAgICAgIHRva2VuID0gYXdhaXQgUWdyaWRGcmFtZS5yZWZyZXNoVG9rZW4oZWxlY3RlZFRva2VuKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oYHJlZnJlc2ggZmFpbGVkIGZvciAke2VsZWN0ZWRUb2tlbi5uYW1lfTogJHsoZSBhcyBFcnJvcikubWVzc2FnZX1gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBsb2dnZXIuaW5mbyhg4oaSICR7ZWxlY3RlZFRva2VuLm5hbWV9IChtb2RlbDogJHtpbnB1dC5tb2RlbCA/PyBERUZBVUxUX01PREVMfSlgKTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGV4ZWN1dGVDbGF1ZGUoZXhlY3V0aW9uSW5wdXQsIHRva2VuLCB0aW1lb3V0TXMgPz8gREVGQVVMVF9USU1FT1VUX01TKTtcbiAgICByZXR1cm4gYXBwbHlUb29sQ2FsbEVtdWxhdGlvbihcbiAgICAgIC8vIG1vZGVsIOuPhCBjYW5vbmljYWwg66GcIOKAlCBmYWxsYmFjayDrj4QgY29zdC/tkZzquLDqsIAgbWFpbiDqsr3roZzsmYAg7J287LmY7ZWY6rKMLlxuICAgICAgeyAuLi5yZXN1bHQsIHRva2VuTmFtZTogZWxlY3RlZFRva2VuLm5hbWUsIG1vZGVsOiBjYW5vbmljYWxBbnRocm9waWNNb2RlbChpbnB1dC5tb2RlbCkgfSxcbiAgICAgIGlucHV0LnRvb2xzLFxuICAgICk7XG4gIH1cblxuICBhc3luYyBxdWVyeVN0cmVhbShcbiAgICBpbnB1dDogUXVlcnlJbnB1dCxcbiAgICBjYjoge1xuICAgICAgb25EZWx0YTogKHRleHQ6IHN0cmluZykgPT4gdm9pZDtcbiAgICAgIG9uQ29tcGxldGU6IChyZXN1bHQ6IFF1ZXJ5T3V0cHV0KSA9PiB2b2lkO1xuICAgICAgb25FcnJvcjogKGVycm9yOiBFcnJvcikgPT4gdm9pZDtcbiAgICAgIG9uVGhyZWFkSWQ/OiAodGhyZWFkSWQ6IHN0cmluZykgPT4gdm9pZDtcbiAgICAgIG9uVHVybklkPzogKHR1cm5JZDogc3RyaW5nKSA9PiB2b2lkO1xuICAgIH0sXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIEFudGhyb3BpYyDsiqTtirjrpqzrsI06IG9wZW5haS8gcHJlZml4IOqwgCDslYTri4jrqbQgYW50aHJvcGljIOqyveuhnC5cbiAgICBpZiAoIWlucHV0Lm1vZGVsPy5zdGFydHNXaXRoKFwib3BlbmFpL1wiKSkge1xuICAgICAgLy8gQW50aHJvcGljRGlzcGF0Y2hlciDqsIAg7J6I7Jy866m0IOyLpOygnCBkZWx0YSDsiqTtirjrpqzrsI0uIOyXhuycvOuptCDquLDsobQgcXVlcnkoKSDtj7TrsLEoZGVsdGEg7JeG7J2MKS5cbiAgICAgIGlmICh0aGlzLmFudGhyb3BpY0Rpc3BhdGNoZXIpIHtcbiAgICAgICAgY29uc3Qgb3V0cHV0U2NoZW1hID0gaW5wdXQudG9vbHM/Lmxlbmd0aFxuICAgICAgICAgID8gYnVpbGRUb29sQ2FsbFNjaGVtYShpbnB1dC50b29scylcbiAgICAgICAgICA6IGlucHV0Lmpzb25TY2hlbWFcbiAgICAgICAgICAgID8gKEpTT04ucGFyc2UoaW5wdXQuanNvblNjaGVtYSkgYXMgSnNvblZhbHVlKVxuICAgICAgICAgICAgOiB1bmRlZmluZWQ7XG4gICAgICAgIGNvbnN0IGRlY2lzaW9uID0gZGVjaWRlQ29udlJvdXRpbmcoaW5wdXQpO1xuICAgICAgICBhd2FpdCB0aGlzLmFudGhyb3BpY0Rpc3BhdGNoZXIuZ2VuZXJhdGVTdHJlYW0oXG4gICAgICAgICAge1xuICAgICAgICAgICAgLy8gbW9kZWwg66+47KeA7KCVIOyLnCBkaXNwYXRjaGVyIOqwgCBBTlRIUk9QSUNfREVGQVVMVF9NT0RFTCDsoIHsmqkuIHByZWZpeCDsoJXqt5ztmZTrj4Qg64K067aA7JeQ7IScLlxuICAgICAgICAgICAgbW9kZWw6IGlucHV0Lm1vZGVsLFxuICAgICAgICAgICAgc3lzdGVtUHJvbXB0OiBpbnB1dC5zeXN0ZW0sXG4gICAgICAgICAgICBvdXRwdXRTY2hlbWE6IG91dHB1dFNjaGVtYVxuICAgICAgICAgICAgICA/IChzdHJpY3RpZnkob3V0cHV0U2NoZW1hIGFzIFBhcmFtZXRlcnM8dHlwZW9mIHN0cmljdGlmeT5bMF0pIGFzIEpzb25WYWx1ZSlcbiAgICAgICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICBlZmZvcnQ6IGlucHV0LmVmZm9ydCxcbiAgICAgICAgICAgIGNvbGRJbnB1dDogZGVjaXNpb24uY29sZElucHV0LFxuICAgICAgICAgICAgY29sZEhpc3Rvcnk6IGRlY2lzaW9uLmNvbGRIaXN0b3J5LFxuICAgICAgICAgICAgcmV1c2U6IGRlY2lzaW9uLnJldXNlLFxuICAgICAgICAgICAgcmV1c2VJbnB1dDogZGVjaXNpb24ucmV1c2VJbnB1dCxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIG9uRGVsdGE6IGNiLm9uRGVsdGEsXG4gICAgICAgICAgICBvblRocmVhZElkOiBjYi5vblRocmVhZElkLFxuICAgICAgICAgICAgb25Db21wbGV0ZTogKHR1cm5SZXN1bHQpID0+IHtcbiAgICAgICAgICAgICAgY29uc3QgaXNzdWVkQ29vcmQgPSBpc3N1ZUNvbnZDb250ZXh0KHR1cm5SZXN1bHQudGhyZWFkQ29vcmQsIGRlY2lzaW9uKTtcbiAgICAgICAgICAgICAgY2Iub25Db21wbGV0ZShcbiAgICAgICAgICAgICAgICBhcHBseVRvb2xDYWxsRW11bGF0aW9uKHRvRW11bGF0aW9uUmVzdWx0KHR1cm5SZXN1bHQpLCBpbnB1dC50b29scywgaXNzdWVkQ29vcmQpLFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9uRXJyb3I6IGNiLm9uRXJyb3IsXG4gICAgICAgICAgfSxcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5xdWVyeShpbnB1dCk7XG4gICAgICBjYi5vbkNvbXBsZXRlKHJlc3VsdCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgWywgbW9kZWxdID0gaW5wdXQubW9kZWwuc3BsaXQoXCIvXCIsIDIpO1xuICAgIGlmICghbW9kZWwpIHRocm93IG5ldyBQcm9jZXNzRXJyb3IoXCJ1bmtub3duIG1vZGVsXCIpO1xuICAgIGlmICghdGhpcy5vcGVuYWlEaXNwYXRjaGVyKSB0aHJvdyBuZXcgUXVvdGFFcnJvcihcIk9wZW5BSSBkaXNwYXRjaGVyIG5vdCBpbml0aWFsaXplZFwiKTtcblxuICAgIGNvbnN0IG91dHB1dFNjaGVtYSA9IGlucHV0LnRvb2xzPy5sZW5ndGhcbiAgICAgID8gYnVpbGRUb29sQ2FsbFNjaGVtYShpbnB1dC50b29scylcbiAgICAgIDogaW5wdXQuanNvblNjaGVtYVxuICAgICAgICA/IChKU09OLnBhcnNlKGlucHV0Lmpzb25TY2hlbWEpIGFzIEpzb25WYWx1ZSlcbiAgICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICBjb25zdCBkZWNpc2lvbiA9IGRlY2lkZUNvbnZSb3V0aW5nKGlucHV0KTtcbiAgICBhd2FpdCB0aGlzLm9wZW5haURpc3BhdGNoZXIuZ2VuZXJhdGVTdHJlYW0oXG4gICAgICB7XG4gICAgICAgIG1vZGVsLFxuICAgICAgICBzeXN0ZW1Qcm9tcHQ6IGlucHV0LnN5c3RlbSxcbiAgICAgICAgb3V0cHV0U2NoZW1hOiBvdXRwdXRTY2hlbWFcbiAgICAgICAgICA/IChzdHJpY3RpZnkob3V0cHV0U2NoZW1hIGFzIFBhcmFtZXRlcnM8dHlwZW9mIHN0cmljdGlmeT5bMF0pIGFzIEpzb25WYWx1ZSlcbiAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgICAgZWZmb3J0OiBpbnB1dC5lZmZvcnQsXG4gICAgICAgIHZlcmJvc2l0eTogaW5wdXQudmVyYm9zaXR5LFxuICAgICAgICByZWFzb25pbmdTdW1tYXJ5OiBpbnB1dC5yZWFzb25pbmdTdW1tYXJ5LFxuICAgICAgICBzZXJ2aWNlVGllcjogaW5wdXQuc2VydmljZVRpZXIsXG4gICAgICAgIGNvbGRJbnB1dDogZGVjaXNpb24uY29sZElucHV0LFxuICAgICAgICBjb2xkSGlzdG9yeTogZGVjaXNpb24uY29sZEhpc3RvcnksXG4gICAgICAgIHJldXNlOiBkZWNpc2lvbi5yZXVzZSxcbiAgICAgICAgcmV1c2VJbnB1dDogZGVjaXNpb24ucmV1c2VJbnB1dCxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIG9uRGVsdGE6IGNiLm9uRGVsdGEsXG4gICAgICAgIG9uVGhyZWFkSWQ6IGNiLm9uVGhyZWFkSWQsXG4gICAgICAgIG9uVHVybklkOiBjYi5vblR1cm5JZCxcbiAgICAgICAgb25Db21wbGV0ZTogKHR1cm5SZXN1bHQpID0+IHtcbiAgICAgICAgICBjb25zdCBpc3N1ZWRDb29yZCA9IGlzc3VlQ29udkNvbnRleHQodHVyblJlc3VsdC50aHJlYWRDb29yZCwgZGVjaXNpb24pO1xuICAgICAgICAgIGNiLm9uQ29tcGxldGUoXG4gICAgICAgICAgICBhcHBseVRvb2xDYWxsRW11bGF0aW9uKHRvRW11bGF0aW9uUmVzdWx0KHR1cm5SZXN1bHQpLCBpbnB1dC50b29scywgaXNzdWVkQ29vcmQpLFxuICAgICAgICAgICk7XG4gICAgICAgIH0sXG4gICAgICAgIG9uRXJyb3I6IGNiLm9uRXJyb3IsXG4gICAgICB9LFxuICAgICk7XG4gIH1cbn1cblxuLy8gR2VuZXJhdGVSZXN1bHQocHJvdmlkZXIgZGlzcGF0Y2hlciDsnZHri7Up66W8IGFwcGx5VG9vbENhbGxFbXVsYXRpb24g7J6F66ClIHNoYXBlIOuhnCDrp6TtlZHtlZzri6QuXG4vLyBPcGVuQUkvQW50aHJvcGljLCBxdWVyeS9xdWVyeVN0cmVhbSA0IOqyveuhnOqwgCDrj5nsnbztlZjqsowg7JO064ukLlxuLy8gQW50aHJvcGljIGFkYXB0ZXIg64qUIGNhY2hlIGNyZWF0aW9uIOydhCBpbnB1dFRva2VucyDsl5Ag7Y+s7ZWo7ZW0IO2RnOykgO2ZlO2VmOqzoCwg67OE64+EIO2VhOuTnOyXkOuPhCDrs7TsobTtlZzri6QuXG4vLyBwZXItcmVxdWVzdCBjb3N0IOuKlCBDbGF1ZGUgQ29kZSDqsIAg7KSAIHRvdGFsX2Nvc3RfdXNkIOulvCDsmrDshKAg7IKs7Jqp7ZWY6rOgIGZhbGxiYWNrIOqzhOyCsOunjCDqs7XthrUgY29zdCDtlajsiJjrpbwg7JO064ukLlxuZnVuY3Rpb24gdG9FbXVsYXRpb25SZXN1bHQoXG4gIHJlc3VsdDogR2VuZXJhdGVSZXN1bHQsXG4pOiBPbWl0PFF1ZXJ5T3V0cHV0LCBcImNvbnRlbnRcIiB8IFwiZmluaXNoUmVhc29uXCIgfCBcInJ1bkNvbnRleHRcIj4ge1xuICByZXR1cm4ge1xuICAgIHRleHQ6IHJlc3VsdC50ZXh0LFxuICAgIHRva2VuTmFtZTogcmVzdWx0LnRva2VuTmFtZSxcbiAgICBtb2RlbDogcmVzdWx0Lm1vZGVsLFxuICAgIHVzYWdlOiB7XG4gICAgICBpbnB1dF90b2tlbnM6IHJlc3VsdC51c2FnZS5pbnB1dFRva2VucyxcbiAgICAgIG91dHB1dF90b2tlbnM6IHJlc3VsdC51c2FnZS5vdXRwdXRUb2tlbnMsXG4gICAgICBjYWNoZV9jcmVhdGlvbl9pbnB1dF90b2tlbnM6IHJlc3VsdC51c2FnZS5jYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnMgPz8gMCxcbiAgICAgIGNhY2hlX3JlYWRfaW5wdXRfdG9rZW5zOiByZXN1bHQudXNhZ2UuY2FjaGVkSW5wdXRUb2tlbnMsXG4gICAgfSxcbiAgICBkdXJhdGlvbk1zOiByZXN1bHQuZHVyYXRpb25NcyxcbiAgICBjb3N0VXNkOlxuICAgICAgcmVzdWx0LmNvc3RVc2QgIT09IHVuZGVmaW5lZCAmJiByZXN1bHQuY29zdFVzZCA+IDBcbiAgICAgICAgPyByZXN1bHQuY29zdFVzZFxuICAgICAgICA6IGNhbGN1bGF0ZUNvc3RVc2QocmVzdWx0Lm1vZGVsLCB7XG4gICAgICAgICAgICBpbnB1dFRva2VuczogcmVzdWx0LnVzYWdlLmlucHV0VG9rZW5zLFxuICAgICAgICAgICAgb3V0cHV0VG9rZW5zOiByZXN1bHQudXNhZ2Uub3V0cHV0VG9rZW5zLFxuICAgICAgICAgICAgY2FjaGVkSW5wdXRUb2tlbnM6IHJlc3VsdC51c2FnZS5jYWNoZWRJbnB1dFRva2VucyxcbiAgICAgICAgICAgIGNhY2hlQ3JlYXRpb25JbnB1dFRva2VuczogcmVzdWx0LnVzYWdlLmNhY2hlQ3JlYXRpb25JbnB1dFRva2VucyA/PyAwLFxuICAgICAgICAgIH0pLFxuICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBleGVjdXRlQ2xhdWRlKFxuICBpbnB1dDogUXVlcnlJbnB1dCxcbiAgdG9rZW46IHN0cmluZyxcbiAgdGltZW91dE1zOiBudW1iZXIsXG4pOiBQcm9taXNlPE9taXQ8UXVlcnlPdXRwdXQsIFwiY29udGVudFwiIHwgXCJmaW5pc2hSZWFzb25cIj4+IHtcbiAgY29uc3QgcmF3TW9kZWwgPSBpbnB1dC5tb2RlbCA/PyBERUZBVUxUX01PREVMO1xuICBjb25zdCBtb2RlbCA9IHJhd01vZGVsLmluY2x1ZGVzKFwiL1wiKSA/IHJhd01vZGVsLnNwbGl0KFwiL1wiKS5wb3AoKSEgOiByYXdNb2RlbDtcbiAgY29uc3QgdGltZW91dCA9IGlucHV0LnRpbWVvdXQgPz8gdGltZW91dE1zO1xuICBjb25zdCB1c2VTdHJ1Y3R1cmVkT3V0cHV0ID0gaW5wdXQuanNvblNjaGVtYSAmJiBpbnB1dC5qc29uU2NoZW1hLmxlbmd0aCA+IDA7XG5cbiAgLy8gLS10b29scyBcIlwiIOuhnCDrqqjrk6AgdG9vbCDsnYQg6riw67O4IOywqOuLqC4gc3RydWN0dXJlZCBvdXRwdXQg7JOw66m0IFN0cnVjdHVyZWRPdXRwdXQg66eMIO2ZlOydtO2KuOumrOyKpO2KuC5cbiAgLy8gLS10b29scyBcIlwiIOuKlCDrsJjrk5zsi5wg65Kk7JeQIOuLpOuluCDtlIzrnpjqt7jqsIAg7JmA7JW8IENMSSDtjIzsi7HsnbQg67mIIOusuOyekOyXtOuhnCDsnbjsi51cbiAgY29uc3QgdG9vbEFyZ3MgPSB1c2VTdHJ1Y3R1cmVkT3V0cHV0XG4gICAgPyBbXCItLXRvb2xzXCIsIFwiXCIsIFwiLS1hbGxvd2VkLXRvb2xzXCIsIFwiU3RydWN0dXJlZE91dHB1dFwiXVxuICAgIDogW1wiLS10b29sc1wiLCBcIlwiXTtcblxuICBjb25zdCBhcmdzOiBzdHJpbmdbXSA9IFtcbiAgICBcIi1wXCIsXG4gICAgLi4udG9vbEFyZ3MsXG4gICAgXCItLWRpc2FsbG93ZWRUb29sc1wiLFxuICAgIC8vIEND7JeQ7IScIOyekOuPmSDtmZzshLHtmZTrkJjripQgZGVmZXJyZWQg64+E6rWsLiDthqDtgbAg7LWc7KCB7ZmU66W87JyE7ZW0IOywqOuLqFxuICAgIC4uLihbXCJNb25pdG9yXCIsIFwiUHVzaE5vdGlmaWNhdGlvblwiLCBcIlJlbW90ZVRyaWdnZXJcIl0gYXMgY29uc3QpLFxuICAgIFwiLS1vdXRwdXQtZm9ybWF0XCIsXG4gICAgXCJzdHJlYW0tanNvblwiLFxuICAgIFwiLS12ZXJib3NlXCIsXG4gICAgLy8gLS1tYXgtdHVybnM6IHN0cnVjdHVyZWQgb3V0cHV0IOydgCB0b29sX3VzZSArIHRvb2xfcmVzdWx0IOuhnCAy7YS0IOyGjOu5hFxuICAgIFwiLS1tYXgtdHVybnNcIixcbiAgICB1c2VTdHJ1Y3R1cmVkT3V0cHV0ID8gXCIyXCIgOiBcIjFcIixcbiAgICBcIi0tcGVybWlzc2lvbi1tb2RlXCIsXG4gICAgXCJieXBhc3NQZXJtaXNzaW9uc1wiLFxuICAgIFwiLS1zZXR0aW5nLXNvdXJjZXNcIixcbiAgICBcInByb2plY3RcIixcbiAgICBcIi0tbW9kZWxcIixcbiAgICBtb2RlbCxcbiAgICAvLyAtLXN5c3RlbS1wcm9tcHTripQg67CY65Oc7IucIOuqheyLnO2VtOyVvO2VqC4g7Ji17IWYIOyDneuetSDsi5wgQ0PqsIAgZGVmYXVsdCBzeXN0ZW0gcHJvbXB066W8IOyekOuPmeycvOuhnCDso7zsnoXtlagoMjNrKVxuICAgIFwiLS1zeXN0ZW0tcHJvbXB0XCIsXG4gICAgaW5wdXQuc3lzdGVtID8/IFwiXCIsXG4gICAgXCItLXRoaW5raW5nXCIsXG4gICAgXCJkaXNhYmxlZFwiLFxuICAgIFwiLS1lZmZvcnRcIixcbiAgICBpbnB1dC5lZmZvcnQgPz8gREVGQVVMVF9FRkZPUlQsXG4gICAgXCItLW5vLXNlc3Npb24tcGVyc2lzdGVuY2VcIixcbiAgICAvLyDrqqjrk6Agc2tpbGxzIOu5hO2ZnOyEse2ZlFxuICAgIFwiLS1kaXNhYmxlLXNsYXNoLWNvbW1hbmRzXCIsXG4gIF07XG4gIGlmICh1c2VTdHJ1Y3R1cmVkT3V0cHV0KSB7XG4gICAgYXJncy5wdXNoKFwiLS1qc29uLXNjaGVtYVwiLCBpbnB1dC5qc29uU2NoZW1hISk7XG4gIH1cbiAgYXJncy5wdXNoKGlucHV0LnByb21wdCk7XG5cbiAgY29uc3QgZW52OiBOb2RlSlMuUHJvY2Vzc0VudiA9IHtcbiAgICBQQVRIOiBwcm9jZXNzLmVudi5QQVRILFxuICAgIFRNUERJUjogcHJvY2Vzcy5lbnYuVE1QRElSLFxuICAgIENMQVVERV9DT0RFX09BVVRIX1RPS0VOOiB0b2tlbixcbiAgICAvLyBDTEFVREVfQ09ORklHX0RJUiDtmZjqsr3rs4DsiJjroZwg7KO87J6FXG4gICAgQ0xBVURFX0NPTkZJR19ESVIsXG4gICAgQ0xBVURFX0NPREVfRElTQUJMRV9BVVRPX01FTU9SWTogXCIxXCIsXG4gICAgQ0xBVURFX0NPREVfRElTQUJMRV9BREFQVElWRV9USElOS0lORzogXCIxXCIsXG4gICAgQ0xBVURFX0NPREVfRElTQUJMRV8xTV9DT05URVhUOiBcIjFcIixcbiAgICBDTEFVREVfQ09ERV9ESVNBQkxFX0NMQVVERV9NRFM6IFwiMVwiLFxuICAgIENMQVVERV9DT0RFX0FUVFJJQlVUSU9OX0hFQURFUjogXCIwXCIsXG4gIH07XG5cbiAgcmV0dXJuIG5ldyBQcm9taXNlPE9taXQ8UXVlcnlPdXRwdXQsIFwiY29udGVudFwiIHwgXCJmaW5pc2hSZWFzb25cIj4+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBjb25zdCBjaGlsZCA9IHNwYXduKFwiY2xhdWRlXCIsIGFyZ3MsIHtcbiAgICAgIHN0ZGlvOiBbXCJpZ25vcmVcIiwgXCJwaXBlXCIsIFwiaWdub3JlXCJdLFxuICAgICAgZW52LFxuICAgICAgLy8g6rKp66asICjrkZAg64uo6rOEKTpcbiAgICAgIC8vIDEuIENMQVVERV9DV0Qg4oCUIHByb2plY3Qgc2NvcGUg6rKp66asIChjd2Qg7J2YIC5jbGF1ZGUvc2V0dGluZ3MuanNvbilcbiAgICAgIC8vIDIuIENMQVVERV9DT05GSUdfRElSIOKAlCB1c2VyIHNjb3BlIOqyqeumrCBjd2Qg6rKp66as66eM7Jy866GgIOu2gOyhsS5cbiAgICAgIGN3ZDogQ0xBVURFX0NXRCxcbiAgICB9KTtcblxuICAgIGxldCBidWZmZXIgPSBcIlwiO1xuICAgIGxldCBzZXR0bGVkID0gZmFsc2U7XG4gICAgY29uc3QgdGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIGlmIChzZXR0bGVkKSByZXR1cm47XG4gICAgICBzZXR0bGVkID0gdHJ1ZTtcbiAgICAgIGNoaWxkLmtpbGwoKTtcbiAgICAgIHJlamVjdChuZXcgVGltZW91dEVycm9yKGBUaW1lb3V0IGFmdGVyICR7dGltZW91dCAvIDEwMDB9cyAodG9rZW46ICR7bWFza1Rva2VuKHRva2VuKX0pYCkpO1xuICAgIH0sIHRpbWVvdXQpO1xuXG4gICAgY2hpbGQuc3Rkb3V0Py5vbihcImRhdGFcIiwgKGQ6IEJ1ZmZlcikgPT4ge1xuICAgICAgaWYgKHNldHRsZWQpIHJldHVybjtcbiAgICAgIGJ1ZmZlciArPSBkLnRvU3RyaW5nKCk7XG4gICAgICBjb25zdCBsaW5lcyA9IGJ1ZmZlci5zcGxpdChcIlxcblwiKTtcbiAgICAgIGJ1ZmZlciA9IGxpbmVzLnBvcCgpID8/IFwiXCI7XG4gICAgICBmb3IgKGNvbnN0IGxpbmUgb2YgbGluZXMpIHtcbiAgICAgICAgaWYgKCFsaW5lLnRyaW0oKSkgY29udGludWU7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgaiA9IEpTT04ucGFyc2UobGluZSk7XG4gICAgICAgICAgaWYgKGoudHlwZSA9PT0gXCJyZXN1bHRcIiAmJiAhc2V0dGxlZCkge1xuICAgICAgICAgICAgLy8gLS1qc29uLXNjaGVtYSDsgqzsmqkg7IucIHN0cnVjdHVyZWRfb3V0cHV0IOyXkCDtjIzsi7HrkJwg6rCd7LK06rCAIOyYqOuLpCDihpIg7Jqw7ISgIOyCrOyaqVxuICAgICAgICAgICAgbGV0IHRleHQ6IHN0cmluZztcbiAgICAgICAgICAgIGlmIChqLnN0cnVjdHVyZWRfb3V0cHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgdGV4dCA9IEpTT04uc3RyaW5naWZ5KGouc3RydWN0dXJlZF9vdXRwdXQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGV4dCA9IChqLnJlc3VsdCA/PyBcIlwiKVxuICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9eYGBgKD86anNvbik/XFxzKlxcbj8vaSwgXCJcIilcbiAgICAgICAgICAgICAgICAucmVwbGFjZSgvXFxuP2BgYFxccyokL2ksIFwiXCIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGV4dC5zdGFydHNXaXRoKFwiWW91J3ZlIGhpdFwiKSkge1xuICAgICAgICAgICAgICBzZXR0bGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgICAgICAgICAgcmVqZWN0KG5ldyBRdW90YUVycm9yKGBRdW90YSBleGhhdXN0ZWQgKHRva2VuOiAke21hc2tUb2tlbih0b2tlbil9KWApKTtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCB1ID0gai51c2FnZSA/PyB7fTtcbiAgICAgICAgICAgIHNldHRsZWQgPSB0cnVlO1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgICAgICAgIHJlc29sdmUoe1xuICAgICAgICAgICAgICB0ZXh0LFxuICAgICAgICAgICAgICB1c2FnZToge1xuICAgICAgICAgICAgICAgIGlucHV0X3Rva2VuczogdS5pbnB1dF90b2tlbnMgPz8gMCxcbiAgICAgICAgICAgICAgICBvdXRwdXRfdG9rZW5zOiB1Lm91dHB1dF90b2tlbnMgPz8gMCxcbiAgICAgICAgICAgICAgICBjYWNoZV9jcmVhdGlvbl9pbnB1dF90b2tlbnM6IHUuY2FjaGVfY3JlYXRpb25faW5wdXRfdG9rZW5zID8/IDAsXG4gICAgICAgICAgICAgICAgY2FjaGVfcmVhZF9pbnB1dF90b2tlbnM6IHUuY2FjaGVfcmVhZF9pbnB1dF90b2tlbnMgPz8gMCxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgZHVyYXRpb25Nczogai5kdXJhdGlvbl9tcyA/PyAwLFxuICAgICAgICAgICAgICBjb3N0VXNkOiBqLnRvdGFsX2Nvc3RfdXNkID8/IDAsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2gge31cbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGNoaWxkLm9uKFwiY2xvc2VcIiwgKCkgPT4ge1xuICAgICAgaWYgKHNldHRsZWQpIHJldHVybjtcbiAgICAgIHNldHRsZWQgPSB0cnVlO1xuICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgIHJlamVjdChuZXcgUHJvY2Vzc0Vycm9yKGBDTEkgcHJvY2VzcyBjbG9zZWQgd2l0aG91dCByZXN1bHQgKHRva2VuOiAke21hc2tUb2tlbih0b2tlbil9KWApKTtcbiAgICB9KTtcblxuICAgIGNoaWxkLm9uKFwiZXJyb3JcIiwgKGVycikgPT4ge1xuICAgICAgaWYgKHNldHRsZWQpIHJldHVybjtcbiAgICAgIHNldHRsZWQgPSB0cnVlO1xuICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgIHJlamVjdChuZXcgUHJvY2Vzc0Vycm9yKGBDTEkgcHJvY2VzcyBlcnJvcjogJHtlcnIubWVzc2FnZX0gKHRva2VuOiAke21hc2tUb2tlbih0b2tlbil9KWApKTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbmV4cG9ydCBjb25zdCBRZ3JpZERpc3BhdGNoZXIgPSBuZXcgUWdyaWREaXNwYXRjaGVyQ2xhc3MoKTtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQXFDQSxNQUFNLFNBQVMsVUFBVSxDQUFDLFFBQVEsQ0FBQztBQUVuQyxNQUFNLGdCQUFnQjtBQUN0QixNQUFNLHFCQUFxQjtBQUMzQixNQUFNLGlCQUFpQjtBQUl2QixNQUFNLGFBQWE7QUFHbkIsTUFBTSxvQkFBb0I7QUFHMUIsTUFBTSx3QkFBd0I7Q0FDNUIsdUJBQXVCO0NBQ3ZCLHdC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
165
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicWdyaWQuZGlzcGF0Y2hlci5qcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBwbGljYXRpb24vcWdyaWQvcWdyaWQuZGlzcGF0Y2hlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFFncmlkRGlzcGF0Y2hlciDigJQgcHJvdmlkZXIgZGlzcGF0Y2hlciDrnbzsmrDtjIUgKyDthqDtgbAg7LqQ7IucL+2GteqzhCDsi7HquIDthLQuXG4gKlxuICogLSDrqZTrqqjrpqwg7LqQ7IucIChNYXA8aWQsIFRva2VuU3Vic2V0QT4pIOuKlCBUb2tlblN1YnNjcmliZXIg6rCAIHBnIExJU1RFTi9OT1RJRlkg66GcIOqwseyLoFxuICogLSBPcGVuQUkvQW50aHJvcGljIOyalOyyreydgCDqsIEgcHJvdmlkZXIgZGlzcGF0Y2hlciDroZzrp4wg7Iuk7ZaJXG4gKiAtIFF1b3RhRXJyb3Ig64qUIOq3uOuMgOuhnCDsg4HsnIQg7KCE7YyMXG4gKi9cblxuaW1wb3J0IHsgdHlwZSBKc29uVmFsdWUgfSBmcm9tIFwiLi4vLi4vY29kZXgtcHJvdG9jb2wvc2VyZGVfanNvbi9Kc29uVmFsdWVcIjtcbmltcG9ydCB7IHR5cGUgQW50aHJvcGljRGlzcGF0Y2hlciB9IGZyb20gXCIuLi8uLi91dGlscy9wcm92aWRlcnMvYW50aHJvcGljL2FudGhyb3BpYy1kaXNwYXRjaGVyXCI7XG5pbXBvcnQgeyBnZXRBY2Nlc3NUb2tlbiB9IGZyb20gXCIuLi8uLi91dGlscy9wcm92aWRlcnMvY29tbW9uL2NyZWRlbnRpYWxzXCI7XG5pbXBvcnQgeyBjYWxjdWxhdGVDb3N0VXNkIH0gZnJvbSBcIi4uLy4uL3V0aWxzL3Byb3ZpZGVycy9jb21tb24vbW9kZWwtY29zdFwiO1xuaW1wb3J0IHtcbiAgdHlwZSBHZW5lcmF0ZVJlc3VsdCxcbiAgdHlwZSBTdHJlYW1DYWxsYmFja3MsXG59IGZyb20gXCIuLi8uLi91dGlscy9wcm92aWRlcnMvY29tbW9uL3Byb3ZpZGVyLWRpc3BhdGNoZXJcIjtcbmltcG9ydCB7IHN0cmljdGlmeSB9IGZyb20gXCIuLi8uLi91dGlscy9wcm92aWRlcnMvY29tbW9uL3N0cmljdGlmaWVyXCI7XG5pbXBvcnQgeyB0eXBlIE9wZW5BSURpc3BhdGNoZXIgfSBmcm9tIFwiLi4vLi4vdXRpbHMvcHJvdmlkZXJzL29wZW5haS9vcGVuYWktZGlzcGF0Y2hlclwiO1xuaW1wb3J0IHsgdHlwZSBUb2tlblN1YnNldEEgfSBmcm9tIFwiLi4vc29uYW11LmdlbmVyYXRlZFwiO1xuaW1wb3J0IHsgZGVjaWRlQ29udlJvdXRpbmcsIGlzc3VlQ29udkNvbnRleHQgfSBmcm9tIFwiLi9jb252LXJvdXRpbmdcIjtcbmltcG9ydCB7IHR5cGUgUXVlcnlJbnB1dCwgdHlwZSBRdWVyeU91dHB1dCwgdHlwZSBUb2tlblN0YXRzIH0gZnJvbSBcIi4vcWdyaWQudHlwZXNcIjtcbmltcG9ydCB7IG1hc2tUb2tlbiwgUHJvY2Vzc0Vycm9yLCBRdW90YUVycm9yIH0gZnJvbSBcIi4vcWdyaWQudHlwZXNcIjtcbmltcG9ydCB7IHR5cGUgVG9rZW5TdWJzY3JpYmVyIH0gZnJvbSBcIi4vdG9rZW4tc3Vic2NyaWJlclwiO1xuaW1wb3J0IHsgYXBwbHlUb29sQ2FsbEVtdWxhdGlvbiwgYnVpbGRUb29sQ2FsbFNjaGVtYSB9IGZyb20gXCIuL3Rvb2wtZW11bGF0aW9uXCI7XG5cbmV4cG9ydCBjbGFzcyBRZ3JpZERpc3BhdGNoZXJDbGFzcyB7XG4gIHRva2VucyA9IG5ldyBNYXA8bnVtYmVyLCBUb2tlblN1YnNldEE+KCk7XG5cbiAgLy8gVG9rZW5TdGF0cyBzaGFwZSDrs7TsobTsmqkuIOyLpOygnCBwcm92aWRlciDsmpTssq0g7Lm07Jq07YyF7J2AIOqwgSBkaXNwYXRjaGVyIOuhnCDsnbTrj5ntlojri6QuXG4gIHJlcXVlc3RDb3VudHMgPSBuZXcgTWFwPHN0cmluZywgbnVtYmVyPigpO1xuXG4gIC8vIHNvbmFtdS5jb25maWcgb25TdGFydCDsl5DshJwg7LKY66as7ZWY64qUIOuzgOyImFxuICBzdWJzY3JpYmVyOiBUb2tlblN1YnNjcmliZXIgfCBudWxsID0gbnVsbDtcbiAgb3BlbmFpRGlzcGF0Y2hlcjogT3BlbkFJRGlzcGF0Y2hlciB8IG51bGwgPSBudWxsO1xuICBhbnRocm9waWNEaXNwYXRjaGVyOiBBbnRocm9waWNEaXNwYXRjaGVyIHwgbnVsbCA9IG51bGw7XG5cbiAgY291bnRPZihuYW1lOiBzdHJpbmcpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLnJlcXVlc3RDb3VudHMuZ2V0KG5hbWUpID8/IDA7XG4gIH1cblxuICAvLyBUb2tlblN1YnNjcmliZXIg7L2c67CxIOKAlCDsupDsi5wgbXV0YXRpb25cbiAgdXBzZXJ0Q2FjaGUoaWQ6IG51bWJlciwgcm93OiBUb2tlblN1YnNldEEpOiB2b2lkIHtcbiAgICB0aGlzLnRva2Vucy5zZXQoaWQsIHJvdyk7XG4gIH1cblxuICByZW1vdmVDYWNoZShpZDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy50b2tlbnMuZGVsZXRlKGlkKTtcbiAgfVxuXG4gIHJlcGxhY2VDYWNoZShyb3dzOiBUb2tlblN1YnNldEFbXSk6IHZvaWQge1xuICAgIHRoaXMudG9rZW5zID0gbmV3IE1hcChyb3dzLm1hcCgocikgPT4gW3IuaWQsIHJdKSk7XG4gIH1cblxuICBnZXRTdGF0cygpOiBUb2tlblN0YXRzW10ge1xuICAgIHJldHVybiBbLi4udGhpcy50b2tlbnMudmFsdWVzKCldLm1hcCgocikgPT4gKHtcbiAgICAgIHRva2VuOiBtYXNrVG9rZW4oZ2V0QWNjZXNzVG9rZW4oci5jcmVkZW50aWFscykpLFxuICAgICAgbmFtZTogci5uYW1lLFxuICAgICAgcHJvdmlkZXI6IHIucHJvdmlkZXIsXG4gICAgICByZXF1ZXN0czogdGhpcy5jb3VudE9mKHIubmFtZSksXG4gICAgfSkpO1xuICB9XG5cbiAgYXN5bmMgcXVlcnkoaW5wdXQ6IFF1ZXJ5SW5wdXQsIHRpbWVvdXRNcz86IG51bWJlcik6IFByb21pc2U8UXVlcnlPdXRwdXQ+IHtcbiAgICB2b2lkIHRpbWVvdXRNcztcblxuICAgIGlmIChpbnB1dC50b29scz8ubGVuZ3RoICYmIGlucHV0Lmpzb25TY2hlbWEpIHtcbiAgICAgIHRocm93IG5ldyBQcm9jZXNzRXJyb3IoXCJ0b29scyBhbmQganNvblNjaGVtYSBjYW5ub3QgYmUgdXNlZCB0b2dldGhlclwiKTtcbiAgICB9XG5cbiAgICBjb25zdCBvdXRwdXRTY2hlbWEgPSBidWlsZFN0cmljdE91dHB1dFNjaGVtYShpbnB1dCk7XG4gICAgY29uc3Qgcm91dGUgPSBwYXJzZVByb3ZpZGVyUm91dGUoaW5wdXQubW9kZWwpO1xuXG4gICAgLy8gcHJvdmlkZXIgcHJlZml4IHJvdXRpbmc6ICdvcGVuYWkvZ3B0LTUuNCcg4oaSIE9wZW5BSURpc3BhdGNoZXJcbiAgICBpZiAocm91dGUucHJvdmlkZXIgPT09IFwib3BlbmFpXCIpIHtcbiAgICAgIGlmICghdGhpcy5vcGVuYWlEaXNwYXRjaGVyKSB0aHJvdyBuZXcgUXVvdGFFcnJvcihcIk9wZW5BSSBkaXNwYXRjaGVyIG5vdCBpbml0aWFsaXplZFwiKTtcblxuICAgICAgY29uc3QgZGVjaXNpb24gPSBkZWNpZGVDb252Um91dGluZyhpbnB1dCk7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLm9wZW5haURpc3BhdGNoZXIuZ2VuZXJhdGUoe1xuICAgICAgICBtb2RlbDogcm91dGUubW9kZWwsXG4gICAgICAgIHN5c3RlbVByb21wdDogaW5wdXQuc3lzdGVtLFxuICAgICAgICBvdXRwdXRTY2hlbWEsXG4gICAgICAgIGVmZm9ydDogaW5wdXQuZWZmb3J0LFxuICAgICAgICB2ZXJib3NpdHk6IGlucHV0LnZlcmJvc2l0eSxcbiAgICAgICAgcmVhc29uaW5nU3VtbWFyeTogaW5wdXQucmVhc29uaW5nU3VtbWFyeSxcbiAgICAgICAgc2VydmljZVRpZXI6IGlucHV0LnNlcnZpY2VUaWVyLFxuICAgICAgICBjb2xkSW5wdXQ6IGRlY2lzaW9uLmNvbGRJbnB1dCxcbiAgICAgICAgY29sZEhpc3Rvcnk6IGRlY2lzaW9uLmNvbGRIaXN0b3J5LFxuICAgICAgICByZXVzZTogZGVjaXNpb24ucmV1c2UsXG4gICAgICAgIHJldXNlSW5wdXQ6IGRlY2lzaW9uLnJldXNlSW5wdXQsXG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIGFwcGx5VG9vbENhbGxFbXVsYXRpb24oXG4gICAgICAgIHRvRW11bGF0aW9uUmVzdWx0KHJlc3VsdCksXG4gICAgICAgIGlucHV0LnRvb2xzLFxuICAgICAgICBpc3N1ZUNvbnZDb250ZXh0KHJlc3VsdC50aHJlYWRDb29yZCwgZGVjaXNpb24pLFxuICAgICAgKTtcbiAgICB9IGVsc2UgaWYgKHJvdXRlLnByb3ZpZGVyID09PSBcImFudGhyb3BpY1wiKSB7XG4gICAgICBpZiAoIXRoaXMuYW50aHJvcGljRGlzcGF0Y2hlcikgdGhyb3cgbmV3IFF1b3RhRXJyb3IoXCJBbnRocm9waWMgZGlzcGF0Y2hlciBub3QgaW5pdGlhbGl6ZWRcIik7XG5cbiAgICAgIGNvbnN0IGRlY2lzaW9uID0gZGVjaWRlQ29udlJvdXRpbmcoaW5wdXQpO1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5hbnRocm9waWNEaXNwYXRjaGVyLmdlbmVyYXRlKHtcbiAgICAgICAgLy8gQW50aHJvcGljRGlzcGF0Y2hlciDrgrTrtoDsl5DshJwg7JWM7JWE7IScIHByb3ZpZGVyIHByZWZpeCDrpbwgY2Fub25pY2FsIG1vZGVsIOuhnCDsoJXqt5ztmZTtlahcbiAgICAgICAgbW9kZWw6IGlucHV0Lm1vZGVsLFxuICAgICAgICBzeXN0ZW1Qcm9tcHQ6IGlucHV0LnN5c3RlbSxcbiAgICAgICAgb3V0cHV0U2NoZW1hLFxuICAgICAgICBlZmZvcnQ6IGlucHV0LmVmZm9ydCxcbiAgICAgICAgY29sZElucHV0OiBkZWNpc2lvbi5jb2xkSW5wdXQsXG4gICAgICAgIGNvbGRIaXN0b3J5OiBkZWNpc2lvbi5jb2xkSGlzdG9yeSxcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gYXBwbHlUb29sQ2FsbEVtdWxhdGlvbihcbiAgICAgICAgdG9FbXVsYXRpb25SZXN1bHQocmVzdWx0KSxcbiAgICAgICAgaW5wdXQudG9vbHMsXG4gICAgICAgIGlzc3VlQ29udkNvbnRleHQocmVzdWx0LnRocmVhZENvb3JkLCBkZWNpc2lvbiksXG4gICAgICApO1xuICAgIH1cblxuICAgIHRocm93IGRpcmVjdExsbUFwaUZhbGxiYWNrTm90SW1wbGVtZW50ZWQoaW5wdXQpO1xuICB9XG5cbiAgYXN5bmMgcXVlcnlTdHJlYW0oXG4gICAgaW5wdXQ6IFF1ZXJ5SW5wdXQsXG4gICAgY2I6IFN0cmVhbUNhbGxiYWNrczxRdWVyeU91dHB1dD4sXG4gICAgYWJvcnRTaWduYWw/OiBBYm9ydFNpZ25hbCxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3Qgb3V0cHV0U2NoZW1hID0gYnVpbGRTdHJpY3RPdXRwdXRTY2hlbWEoaW5wdXQpO1xuICAgIGNvbnN0IHJvdXRlID0gcGFyc2VQcm92aWRlclJvdXRlKGlucHV0Lm1vZGVsKTtcblxuICAgIGlmIChyb3V0ZS5wcm92aWRlciA9PT0gXCJvcGVuYWlcIikge1xuICAgICAgaWYgKCF0aGlzLm9wZW5haURpc3BhdGNoZXIpIHRocm93IG5ldyBRdW90YUVycm9yKFwiT3BlbkFJIGRpc3BhdGNoZXIgbm90IGluaXRpYWxpemVkXCIpO1xuXG4gICAgICBjb25zdCBkZWNpc2lvbiA9IGRlY2lkZUNvbnZSb3V0aW5nKGlucHV0KTtcbiAgICAgIGF3YWl0IHRoaXMub3BlbmFpRGlzcGF0Y2hlci5nZW5lcmF0ZVN0cmVhbShcbiAgICAgICAge1xuICAgICAgICAgIG1vZGVsOiByb3V0ZS5tb2RlbCxcbiAgICAgICAgICBzeXN0ZW1Qcm9tcHQ6IGlucHV0LnN5c3RlbSxcbiAgICAgICAgICBvdXRwdXRTY2hlbWEsXG4gICAgICAgICAgZWZmb3J0OiBpbnB1dC5lZmZvcnQsXG4gICAgICAgICAgdmVyYm9zaXR5OiBpbnB1dC52ZXJib3NpdHksXG4gICAgICAgICAgcmVhc29uaW5nU3VtbWFyeTogaW5wdXQucmVhc29uaW5nU3VtbWFyeSxcbiAgICAgICAgICBzZXJ2aWNlVGllcjogaW5wdXQuc2VydmljZVRpZXIsXG4gICAgICAgICAgY29sZElucHV0OiBkZWNpc2lvbi5jb2xkSW5wdXQsXG4gICAgICAgICAgY29sZEhpc3Rvcnk6IGRlY2lzaW9uLmNvbGRIaXN0b3J5LFxuICAgICAgICAgIHJldXNlOiBkZWNpc2lvbi5yZXVzZSxcbiAgICAgICAgICByZXVzZUlucHV0OiBkZWNpc2lvbi5yZXVzZUlucHV0LFxuICAgICAgICAgIGFib3J0U2lnbmFsLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgb25EZWx0YTogY2Iub25EZWx0YSxcbiAgICAgICAgICBvblRocmVhZElkOiBjYi5vblRocmVhZElkLFxuICAgICAgICAgIG9uVHVybklkOiBjYi5vblR1cm5JZCxcbiAgICAgICAgICBvbkNvbXBsZXRlOiAodHVyblJlc3VsdCkgPT4ge1xuICAgICAgICAgICAgY2Iub25Db21wbGV0ZShcbiAgICAgICAgICAgICAgYXBwbHlUb29sQ2FsbEVtdWxhdGlvbihcbiAgICAgICAgICAgICAgICB0b0VtdWxhdGlvblJlc3VsdCh0dXJuUmVzdWx0KSxcbiAgICAgICAgICAgICAgICBpbnB1dC50b29scyxcbiAgICAgICAgICAgICAgICBpc3N1ZUNvbnZDb250ZXh0KHR1cm5SZXN1bHQudGhyZWFkQ29vcmQsIGRlY2lzaW9uKSxcbiAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBvbkVycm9yOiBjYi5vbkVycm9yLFxuICAgICAgICB9LFxuICAgICAgKTtcbiAgICAgIHJldHVybjtcbiAgICB9IGVsc2UgaWYgKHJvdXRlLnByb3ZpZGVyID09PSBcImFudGhyb3BpY1wiKSB7XG4gICAgICBpZiAoIXRoaXMuYW50aHJvcGljRGlzcGF0Y2hlcikgdGhyb3cgbmV3IFF1b3RhRXJyb3IoXCJBbnRocm9waWMgZGlzcGF0Y2hlciBub3QgaW5pdGlhbGl6ZWRcIik7XG5cbiAgICAgIGNvbnN0IGRlY2lzaW9uID0gZGVjaWRlQ29udlJvdXRpbmcoaW5wdXQpO1xuICAgICAgYXdhaXQgdGhpcy5hbnRocm9waWNEaXNwYXRjaGVyLmdlbmVyYXRlU3RyZWFtKFxuICAgICAgICB7XG4gICAgICAgICAgbW9kZWw6IGlucHV0Lm1vZGVsLFxuICAgICAgICAgIHN5c3RlbVByb21wdDogaW5wdXQuc3lzdGVtLFxuICAgICAgICAgIG91dHB1dFNjaGVtYSxcbiAgICAgICAgICBlZmZvcnQ6IGlucHV0LmVmZm9ydCxcbiAgICAgICAgICBjb2xkSW5wdXQ6IGRlY2lzaW9uLmNvbGRJbnB1dCxcbiAgICAgICAgICBjb2xkSGlzdG9yeTogZGVjaXNpb24uY29sZEhpc3RvcnksXG4gICAgICAgICAgYWJvcnRTaWduYWwsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBvbkRlbHRhOiBjYi5vbkRlbHRhLFxuICAgICAgICAgIG9uVGhyZWFkSWQ6IGNiLm9uVGhyZWFkSWQsXG4gICAgICAgICAgb25Db21wbGV0ZTogKHR1cm5SZXN1bHQpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGlzc3VlZENvb3JkID0gaXNzdWVDb252Q29udGV4dCh0dXJuUmVzdWx0LnRocmVhZENvb3JkLCBkZWNpc2lvbik7XG4gICAgICAgICAgICBjYi5vbkNvbXBsZXRlKFxuICAgICAgICAgICAgICBhcHBseVRvb2xDYWxsRW11bGF0aW9uKHRvRW11bGF0aW9uUmVzdWx0KHR1cm5SZXN1bHQpLCBpbnB1dC50b29scywgaXNzdWVkQ29vcmQpLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIG9uRXJyb3I6IGNiLm9uRXJyb3IsXG4gICAgICAgIH0sXG4gICAgICApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRocm93IGRpcmVjdExsbUFwaUZhbGxiYWNrTm90SW1wbGVtZW50ZWQoaW5wdXQpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHBhcnNlUHJvdmlkZXJSb3V0ZShtb2RlbDogc3RyaW5nIHwgdW5kZWZpbmVkKTogeyBwcm92aWRlcj86IHN0cmluZzsgbW9kZWw6IHN0cmluZyB9IHtcbiAgaWYgKCFtb2RlbD8uaW5jbHVkZXMoXCIvXCIpKSB7XG4gICAgcmV0dXJuIHsgbW9kZWw6IG1vZGVsID8/IFwiXCIgfTtcbiAgfVxuXG4gIGNvbnN0IFtwcm92aWRlciwgcm91dGVkTW9kZWxdID0gbW9kZWwuc3BsaXQoXCIvXCIsIDIpO1xuICBpZiAoIXByb3ZpZGVyIHx8ICFyb3V0ZWRNb2RlbCkgdGhyb3cgbmV3IFByb2Nlc3NFcnJvcihcInVua25vd24gbW9kZWxcIik7XG4gIHJldHVybiB7IHByb3ZpZGVyLCBtb2RlbDogcm91dGVkTW9kZWwgfTtcbn1cblxuLy8gcWdyaWQgcHJvdmlkZXIgZGlzcGF0Y2hlciDsl5DshJwg7LKY66as7ZWY7KeAIOyViuuKlCDrqqjrjbjsnYAg7Zal7ZuEIOyngeygkSBMTE0gQVBJIO2YuOy2nCDsp4DsoJDsnLzroZwg67O064K464ukLlxuZnVuY3Rpb24gZGlyZWN0TGxtQXBpRmFsbGJhY2tOb3RJbXBsZW1lbnRlZChpbnB1dDogUXVlcnlJbnB1dCk6IFByb2Nlc3NFcnJvciB7XG4gIHJldHVybiBuZXcgUHJvY2Vzc0Vycm9yKFxuICAgIGBEaXJlY3QgTExNIEFQSSBmYWxsYmFjayBub3QgaW1wbGVtZW50ZWQgZm9yIG1vZGVsOiAke2lucHV0Lm1vZGVsID8/IFwiPGRlZmF1bHQ+XCJ9YCxcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkU3RyaWN0T3V0cHV0U2NoZW1hKFxuICBpbnB1dDogUGljazxRdWVyeUlucHV0LCBcInRvb2xzXCIgfCBcImpzb25TY2hlbWFcIj4sXG4pOiBKc29uVmFsdWUgfCB1bmRlZmluZWQge1xuICBjb25zdCBvdXRwdXRTY2hlbWEgPSBpbnB1dC50b29scz8ubGVuZ3RoXG4gICAgPyBidWlsZFRvb2xDYWxsU2NoZW1hKGlucHV0LnRvb2xzKVxuICAgIDogaW5wdXQuanNvblNjaGVtYVxuICAgICAgPyAoSlNPTi5wYXJzZShpbnB1dC5qc29uU2NoZW1hKSBhcyBKc29uVmFsdWUpXG4gICAgICA6IHVuZGVmaW5lZDtcblxuICByZXR1cm4gb3V0cHV0U2NoZW1hXG4gICAgPyAoc3RyaWN0aWZ5KG91dHB1dFNjaGVtYSBhcyBQYXJhbWV0ZXJzPHR5cGVvZiBzdHJpY3RpZnk+WzBdKSBhcyBKc29uVmFsdWUpXG4gICAgOiB1bmRlZmluZWQ7XG59XG5cbi8vIEdlbmVyYXRlUmVzdWx0KHByb3ZpZGVyIGRpc3BhdGNoZXIg7J2R64u1KeulvCBhcHBseVRvb2xDYWxsRW11bGF0aW9uIOyeheugpSBzaGFwZSDroZwg66ek7ZWR7ZWc64ukLlxuLy8gT3BlbkFJL0FudGhyb3BpYywgcXVlcnkvcXVlcnlTdHJlYW0gNCDqsr3roZzqsIAg64+Z7J287ZWY6rKMIOyTtOuLpC5cbi8vIEFudGhyb3BpYyBhZGFwdGVyIOuKlCBjYWNoZSBjcmVhdGlvbiDsnYQgaW5wdXRUb2tlbnMg7JeQIO2PrO2VqO2VtCDtkZzspIDtmZTtlZjqs6AsIOuzhOuPhCDtlYTrk5zsl5Drj4Qg67O07KG07ZWc64ukLlxuLy8gcGVyLXJlcXVlc3QgY29zdCDripQgcHJvdmlkZXIg6rCAIOykgCDqsJLsnYQg7Jqw7ISgIOyCrOyaqe2VmOqzoCwg7JeG7Jy866m0IOqzte2GtSBjb3N0IO2VqOyImOulvCDsk7Tri6QuXG5mdW5jdGlvbiB0b0VtdWxhdGlvblJlc3VsdChcbiAgcmVzdWx0OiBHZW5lcmF0ZVJlc3VsdCxcbik6IE9taXQ8UXVlcnlPdXRwdXQsIFwiY29udGVudFwiIHwgXCJmaW5pc2hSZWFzb25cIiB8IFwicnVuQ29udGV4dFwiPiB7XG4gIHJldHVybiB7XG4gICAgdGV4dDogcmVzdWx0LnRleHQsXG4gICAgdG9rZW5OYW1lOiByZXN1bHQudG9rZW5OYW1lLFxuICAgIG1vZGVsOiByZXN1bHQubW9kZWwsXG4gICAgdXNhZ2U6IHtcbiAgICAgIGlucHV0X3Rva2VuczogcmVzdWx0LnVzYWdlLmlucHV0VG9rZW5zLFxuICAgICAgb3V0cHV0X3Rva2VuczogcmVzdWx0LnVzYWdlLm91dHB1dFRva2VucyxcbiAgICAgIGNhY2hlX2NyZWF0aW9uX2lucHV0X3Rva2VuczogcmVzdWx0LnVzYWdlLmNhY2hlQ3JlYXRpb25JbnB1dFRva2VucyA/PyAwLFxuICAgICAgY2FjaGVfcmVhZF9pbnB1dF90b2tlbnM6IHJlc3VsdC51c2FnZS5jYWNoZWRJbnB1dFRva2VucyxcbiAgICB9LFxuICAgIGR1cmF0aW9uTXM6IHJlc3VsdC5kdXJhdGlvbk1zLFxuICAgIGNvc3RVc2Q6XG4gICAgICByZXN1bHQuY29zdFVzZCAhPT0gdW5kZWZpbmVkICYmIHJlc3VsdC5jb3N0VXNkID4gMFxuICAgICAgICA/IHJlc3VsdC5jb3N0VXNkXG4gICAgICAgIDogY2FsY3VsYXRlQ29zdFVzZChyZXN1bHQubW9kZWwsIHtcbiAgICAgICAgICAgIGlucHV0VG9rZW5zOiByZXN1bHQudXNhZ2UuaW5wdXRUb2tlbnMsXG4gICAgICAgICAgICBvdXRwdXRUb2tlbnM6IHJlc3VsdC51c2FnZS5vdXRwdXRUb2tlbnMsXG4gICAgICAgICAgICBjYWNoZWRJbnB1dFRva2VuczogcmVzdWx0LnVzYWdlLmNhY2hlZElucHV0VG9rZW5zLFxuICAgICAgICAgICAgY2FjaGVDcmVhdGlvbklucHV0VG9rZW5zOiByZXN1bHQudXNhZ2UuY2FjaGVDcmVhdGlvbklucHV0VG9rZW5zID8/IDAsXG4gICAgICAgICAgfSksXG4gIH07XG59XG5cbmV4cG9ydCBjb25zdCBRZ3JpZERpc3BhdGNoZXIgPSBuZXcgUWdyaWREaXNwYXRjaGVyQ2xhc3MoKTtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUF5QkEsSUFBYSx1QkFBYixNQUFrQztDQUNoQyx5QkFBUyxJQUFJLEtBQTJCO0NBR3hDLGdDQUFnQixJQUFJLEtBQXFCO0NBR3pDLGFBQXFDO0NBQ3JDLG1CQUE0QztDQUM1QyxzQkFBa0Q7Q0FFbEQsUUFBUSxNQUFzQjtBQUM1QixTQUFPLEtBQUssY0FBYyxJQUFJ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