@cartanova/qgrid-cli 2.5.3 → 2.5.5

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 (65) hide show
  1. package/README.ko.md +7 -2
  2. package/README.md +7 -2
  3. package/bundle/dist/application/monit/monit.frame.js +3 -3
  4. package/bundle/dist/application/qgrid/oauth.js +1 -1
  5. package/bundle/dist/application/qgrid/qgrid.dispatcher.js +36 -14
  6. package/bundle/dist/application/qgrid/qgrid.frame.js +19 -5
  7. package/bundle/dist/application/qgrid/tool-emulation-schema.js +93 -0
  8. package/bundle/dist/application/qgrid/tool-emulation.js +116 -96
  9. package/bundle/dist/application/request-log/request-log.model.js +3 -3
  10. package/bundle/dist/application/request-log-step/request-log-step.model.js +2 -2
  11. package/bundle/dist/application/token/token.model.js +2 -2
  12. package/bundle/dist/server-error-handler.js +15 -0
  13. package/bundle/dist/sonamu.config.js +4 -7
  14. package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +4 -3
  15. package/bundle/dist/utils/providers/anthropic/claude-session.js +7 -5
  16. package/bundle/dist/utils/providers/common/json-schema-keywords.js +77 -0
  17. package/bundle/dist/utils/providers/common/schema-validation.js +178 -0
  18. package/bundle/dist/utils/providers/common/strictifier.js +332 -42
  19. package/bundle/dist/utils/providers/openai/codex-worker.js +16 -8
  20. package/bundle/dist/utils/providers/openai/openai-dispatcher.js +5 -37
  21. package/bundle/dist/utils/providers/openai/openai-worker-pool-config.js +37 -0
  22. package/bundle/src/application/monit/monit.frame.ts +1 -1
  23. package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +103 -0
  24. package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +337 -0
  25. package/bundle/src/application/qgrid/qgrid.dispatcher.ts +45 -25
  26. package/bundle/src/application/qgrid/qgrid.frame.test.ts +580 -8
  27. package/bundle/src/application/qgrid/qgrid.frame.ts +28 -1
  28. package/bundle/src/application/qgrid/tool-emulation-schema.test.ts +188 -0
  29. package/bundle/src/application/qgrid/tool-emulation-schema.ts +177 -0
  30. package/bundle/src/application/qgrid/tool-emulation.test.ts +285 -67
  31. package/bundle/src/application/qgrid/tool-emulation.ts +199 -102
  32. package/bundle/src/server-error-handler.ts +22 -0
  33. package/bundle/src/sonamu.config.test.ts +37 -0
  34. package/bundle/src/sonamu.config.ts +2 -5
  35. package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.test.ts +44 -0
  36. package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +2 -2
  37. package/bundle/src/utils/providers/anthropic/claude-session.test.ts +10 -0
  38. package/bundle/src/utils/providers/anthropic/claude-session.ts +6 -1
  39. package/bundle/src/utils/providers/common/json-schema-keywords.ts +72 -0
  40. package/bundle/src/utils/providers/common/schema-validation.test.ts +284 -0
  41. package/bundle/src/utils/providers/common/schema-validation.ts +308 -0
  42. package/bundle/src/utils/providers/common/strictifier.test.ts +746 -0
  43. package/bundle/src/utils/providers/common/strictifier.ts +520 -52
  44. package/bundle/src/utils/providers/openai/codex-worker.test.ts +31 -0
  45. package/bundle/src/utils/providers/openai/codex-worker.ts +12 -4
  46. package/bundle/src/utils/providers/openai/openai-dispatcher.test.ts +6 -4
  47. package/bundle/src/utils/providers/openai/openai-dispatcher.ts +6 -79
  48. package/bundle/src/utils/providers/openai/openai-worker-pool-config.ts +80 -0
  49. package/bundle/web-dist/client/assets/{index-DXdGBfB8.js → index-CN_kMswh.js} +3 -3
  50. package/bundle/web-dist/client/assets/{logs-D_j1yxC4.js → logs-6nYj9OKL.js} +1 -1
  51. package/bundle/web-dist/client/assets/{monit-CIToyoxW.js → monit-CaPH9Uwc.js} +1 -1
  52. package/bundle/web-dist/client/assets/{routes-Dd21A-wi.js → routes-Dh5HPi-b.js} +1 -1
  53. package/bundle/web-dist/client/assets/{show-DfePWRbc.js → show-Be_LVd9d.js} +1 -1
  54. package/bundle/web-dist/client/assets/{tokens-B4MV2fdk.js → tokens-CAi3zu_0.js} +1 -1
  55. package/bundle/web-dist/client/index.html +1 -1
  56. package/bundle/web-dist/server/entry-server.generated.js +1 -1
  57. package/package.json +1 -1
  58. package/skills/qgrid/references/ai-sdk-provider-contract.md +34 -2
  59. package/skills/qgrid/references/anthropic-claude-code-runtime.md +3 -0
  60. package/skills/qgrid/references/cli-env-and-server-boot.md +1 -1
  61. package/skills/qgrid/references/decision-rationale.md +10 -1
  62. package/skills/qgrid/references/docs-workflow.md +9 -0
  63. package/skills/qgrid/references/repo-map.md +2 -1
  64. package/skills/qgrid/references/tool-calling-and-multiturn.md +145 -6
  65. package/skills/qgrid/references/verification-and-debugging.md +16 -1
@@ -1,4 +1,14 @@
1
+ import { SCHEMA_ARRAY_KEYWORDS, SCHEMA_MAP_KEYWORDS, SCHEMA_SINGLE_KEYWORDS, UNSUPPORTED_REFERENCE_KEYWORDS } from "./json-schema-keywords.js";
1
2
  //#region src/utils/providers/common/strictifier.ts
3
+ /**
4
+ * JSON Schema → OpenAI strict JSON Schema 변환.
5
+ *
6
+ * OpenAI Responses API strict 모드 요구사항:
7
+ * - 모든 object 에 additionalProperties: false
8
+ * - 모든 object properties 를 required 에 포함
9
+ * - optional 필드 → anyOf [original, { type: 'null' }] 로 required 유지
10
+ * - recursive 처리 (nested objects, arrays, allOf/anyOf/oneOf)
11
+ */
2
12
  var StrictifierError = class extends Error {
3
13
  path;
4
14
  constructor(message, path) {
@@ -7,44 +17,245 @@ var StrictifierError = class extends Error {
7
17
  this.name = "StrictifierError";
8
18
  }
9
19
  };
10
- function strictify(schema) {
11
- return strictifyNode(schema, "$");
20
+ function strictify(schema, options = {}) {
21
+ if (options.provider === "openai" || options.provider === "anthropic") assertNormalizationCompatibility(schema, options.provider);
22
+ const result = strictifyNode(schema, "$", options.provider);
23
+ if (options.provider === "openai" || options.provider === "anthropic") assertNormalizationCompatibility(result, options.provider);
24
+ return result;
12
25
  }
13
- function strictifyNode(node, path) {
26
+ /**
27
+ * 위치 목록은 json-schema-keywords 가 소유하고, 여기서는 각 위치의 `normalizable` 여부만 얹는다.
28
+ * normalizable=true 는 strictifyNode 가 그 위치를 실제로 재작성한다는 뜻이다. `not`/`if` 처럼
29
+ * 재작성하면 caller 의미가 바뀌는 위치는 false 이고, 그 아래 tuple/`$ref` 는 정규화 대신 거부된다.
30
+ *
31
+ * `items`/`additionalItems` 는 tuple 판정과 함께 다뤄야 해서 아래 순회에서 개별 처리한다.
32
+ */
33
+ const NON_NORMALIZABLE_POSITIONS = /* @__PURE__ */ new Set([
34
+ "dependentSchemas",
35
+ "patternProperties",
36
+ "additionalProperties",
37
+ "contains",
38
+ "contentSchema",
39
+ "else",
40
+ "if",
41
+ "not",
42
+ "propertyNames",
43
+ "then",
44
+ "unevaluatedItems",
45
+ "unevaluatedProperties"
46
+ ]);
47
+ function positionEntries(keywords) {
48
+ return keywords.map((keyword) => [keyword, !NON_NORMALIZABLE_POSITIONS.has(keyword)]);
49
+ }
50
+ const SCHEMA_SCAN_MAP_KEYWORDS = positionEntries(SCHEMA_MAP_KEYWORDS);
51
+ const SCHEMA_SCAN_ARRAY_KEYWORDS = positionEntries(SCHEMA_ARRAY_KEYWORDS);
52
+ const SCHEMA_SCAN_SINGLE_KEYWORDS = positionEntries(SCHEMA_SINGLE_KEYWORDS.filter((keyword) => keyword !== "items" && keyword !== "additionalItems"));
53
+ /**
54
+ * Inspect every JSON Schema-bearing position without rewriting it.
55
+ *
56
+ * Positive positions already traversed by strictifyNode may normalize OpenAI tuples. Positions
57
+ * such as `not` and `if` cannot be tightened without changing caller semantics, so positional
58
+ * tuples there fail explicitly instead of leaking an unsupported provider schema. References
59
+ * from those positions also fail because their definitions are normalized globally.
60
+ */
61
+ function assertNormalizationCompatibility(schema, provider) {
62
+ const references = [];
63
+ const stack = [{
64
+ node: schema,
65
+ path: "$",
66
+ normalizable: true
67
+ }];
68
+ while (stack.length > 0) {
69
+ const current = stack.pop();
70
+ const itemsValue = ownValue(current.node, "items");
71
+ const prefixItemsValue = ownValue(current.node, "prefixItems");
72
+ const legacyTuple = Array.isArray(itemsValue);
73
+ const prefixTuple = Array.isArray(prefixItemsValue);
74
+ assertUnsupportedReferenceKeywords(current.node, current.path);
75
+ collectSchemaReference(current, references);
76
+ if (legacyTuple || prefixTuple) {
77
+ if (provider === "anthropic" && (legacyTuple ? itemsValue : prefixItemsValue).length > 0) throw new StrictifierError("positional tuple schemas are not supported on Anthropic because Claude Code cannot preserve item positions", current.path);
78
+ if (!current.normalizable) throw new StrictifierError("positional tuple schemas are not supported in this schema position", current.path);
79
+ if (ownValue(current.node, "type") !== "array") throw new StrictifierError("positional tuple schemas must declare type \"array\"; express nullable tuples with anyOf", `${current.path}.type`);
80
+ }
81
+ for (const [keyword, keywordNormalizable] of SCHEMA_SCAN_MAP_KEYWORDS) {
82
+ const schemas = ownValue(current.node, keyword);
83
+ if (!isSchemaObject(schemas)) continue;
84
+ for (const [name, child] of Object.entries(schemas)) {
85
+ if (!isSchemaObject(child)) continue;
86
+ stack.push({
87
+ node: child,
88
+ path: `${current.path}.${keyword}.${name}`,
89
+ normalizable: current.normalizable && keywordNormalizable
90
+ });
91
+ }
92
+ }
93
+ const dependencies = ownValue(current.node, "dependencies");
94
+ if (isSchemaObject(dependencies)) for (const [name, child] of Object.entries(dependencies)) {
95
+ if (!isSchemaObject(child)) continue;
96
+ stack.push({
97
+ node: child,
98
+ path: `${current.path}.dependencies.${name}`,
99
+ normalizable: false
100
+ });
101
+ }
102
+ for (const [keyword, keywordNormalizable] of SCHEMA_SCAN_ARRAY_KEYWORDS) {
103
+ const schemas = ownValue(current.node, keyword);
104
+ if (!Array.isArray(schemas)) continue;
105
+ for (let index = 0; index < schemas.length; index += 1) {
106
+ const child = schemas[index];
107
+ if (!isSchemaObject(child)) continue;
108
+ stack.push({
109
+ node: child,
110
+ path: `${current.path}.${keyword}[${index}]`,
111
+ normalizable: current.normalizable && keywordNormalizable
112
+ });
113
+ }
114
+ }
115
+ const items = ownValue(current.node, "items");
116
+ if (isSchemaObject(items)) stack.push({
117
+ node: items,
118
+ path: `${current.path}.items`,
119
+ normalizable: current.normalizable
120
+ });
121
+ else if (Array.isArray(items)) for (let index = 0; index < items.length; index += 1) {
122
+ const child = items[index];
123
+ if (!isSchemaObject(child)) continue;
124
+ stack.push({
125
+ node: child,
126
+ path: `${current.path}.items[${index}]`,
127
+ normalizable: current.normalizable
128
+ });
129
+ }
130
+ const additionalItems = ownValue(current.node, "additionalItems");
131
+ if (isSchemaObject(additionalItems)) stack.push({
132
+ node: additionalItems,
133
+ path: `${current.path}.additionalItems`,
134
+ normalizable: current.normalizable && legacyTuple
135
+ });
136
+ for (const [keyword, keywordNormalizable] of SCHEMA_SCAN_SINGLE_KEYWORDS) {
137
+ const child = ownValue(current.node, keyword);
138
+ if (!isSchemaObject(child)) continue;
139
+ stack.push({
140
+ node: child,
141
+ path: `${current.path}.${keyword}`,
142
+ normalizable: current.normalizable && keywordNormalizable
143
+ });
144
+ }
145
+ }
146
+ assertReferenceTargets(schema, references);
147
+ }
148
+ function assertUnsupportedReferenceKeywords(schema, path) {
149
+ for (const keyword of UNSUPPORTED_REFERENCE_KEYWORDS) if (Object.hasOwn(schema, keyword)) throw new StrictifierError(`${keyword} is not supported`, `${path}.${keyword}`);
150
+ }
151
+ function collectSchemaReference(current, references) {
152
+ if (!Object.hasOwn(current.node, "$ref")) return;
153
+ const reference = current.node.$ref;
154
+ if (typeof reference !== "string") throw new StrictifierError("$ref must be a string", `${current.path}.$ref`);
155
+ if (!current.normalizable) throw new StrictifierError("schema references are not supported in this schema position", current.path);
156
+ references.push({
157
+ value: reference,
158
+ path: `${current.path}.$ref`
159
+ });
160
+ }
161
+ function assertReferenceTargets(root, references) {
162
+ for (const reference of references) {
163
+ const tokens = parseLocalJsonPointer(reference.value, reference.path);
164
+ if (!isDefinitionRootPointer(tokens)) throw new StrictifierError("$ref target must be the document root or a definition root", reference.path);
165
+ resolveDefinitionRoot(root, tokens, reference.path);
166
+ }
167
+ }
168
+ function isDefinitionRootPointer(tokens) {
169
+ if (tokens.length === 0) return true;
170
+ if (tokens.length % 2 !== 0) return false;
171
+ for (let index = 0; index < tokens.length; index += 2) if (tokens[index] !== "$defs" && tokens[index] !== "definitions") return false;
172
+ return true;
173
+ }
174
+ function parseLocalJsonPointer(reference, path) {
175
+ if (reference === "#") return [];
176
+ if (!reference.startsWith("#/")) throw new StrictifierError("only local root-relative JSON Pointer $ref values are supported", path);
177
+ let fragment;
178
+ try {
179
+ fragment = decodeURIComponent(reference.slice(1));
180
+ } catch {
181
+ throw new StrictifierError("$ref contains invalid percent encoding", path);
182
+ }
183
+ if (!fragment.startsWith("/")) throw new StrictifierError("only local root-relative JSON Pointer $ref values are supported", path);
184
+ return fragment.slice(1).split("/").map((token) => decodeJsonPointerToken(token, path));
185
+ }
186
+ function resolveDefinitionRoot(root, tokens, path) {
187
+ let current = root;
188
+ for (let index = 0; index < tokens.length; index += 2) {
189
+ const keyword = tokens[index];
190
+ const name = tokens[index + 1];
191
+ const definitions = ownValue(current, keyword);
192
+ if (!isSchemaObject(definitions) || !Object.hasOwn(definitions, name)) throw new StrictifierError("$ref does not resolve inside the caller schema", path);
193
+ const target = definitions[name];
194
+ if (!isSchemaObject(target)) throw new StrictifierError("$ref target must be an object schema", path);
195
+ current = target;
196
+ }
197
+ }
198
+ function decodeJsonPointerToken(rawToken, path) {
199
+ let token = "";
200
+ for (let index = 0; index < rawToken.length; index += 1) {
201
+ const character = rawToken[index];
202
+ if (character !== "~") {
203
+ token += character;
204
+ continue;
205
+ }
206
+ const escaped = rawToken[index + 1];
207
+ if (escaped === "0") token += "~";
208
+ else if (escaped === "1") token += "/";
209
+ else throw new StrictifierError("$ref contains an invalid JSON Pointer escape", path);
210
+ index += 1;
211
+ }
212
+ return token;
213
+ }
214
+ function strictifyNode(node, path, provider) {
14
215
  if (typeof node !== "object" || node === null) return node;
15
- const type = node.type;
16
- if (type === "object" || node.properties) return strictifyObject(node, path);
17
- if (type === "array") return strictifyArray(node, path);
18
- if (node.anyOf) return {
19
- ...node,
20
- anyOf: node.anyOf.map((s, i) => strictifyNode(s, `${path}.anyOf[${i}]`))
21
- };
22
- if (node.oneOf) return {
23
- ...node,
24
- oneOf: node.oneOf.map((s, i) => strictifyNode(s, `${path}.oneOf[${i}]`))
25
- };
26
- if (node.allOf) return {
27
- ...node,
28
- allOf: node.allOf.map((s, i) => strictifyNode(s, `${path}.allOf[${i}]`))
29
- };
30
- if (node.$ref) return { ...node };
31
- return { ...node };
216
+ let result = strictifySchemaMaps(provider === "openai" ? omitKeys(node, ["$schema"]) : node, path, provider);
217
+ const type = ownValue(result, "type");
218
+ if (type === "object" || Object.hasOwn(result, "properties")) result = strictifyObject(result, path, provider);
219
+ if (type === "array" || Object.hasOwn(result, "items") || Object.hasOwn(result, "prefixItems")) result = strictifyArray(result, path, provider);
220
+ return strictifySchemaArrays(result, path, provider);
32
221
  }
33
- function strictifyObject(node, path) {
34
- const properties = node.properties;
222
+ const DEFINITION_MAP_KEYWORDS = ["$defs", "definitions"];
223
+ function strictifySchemaMaps(node, path, provider) {
224
+ const result = { ...node };
225
+ for (const keyword of DEFINITION_MAP_KEYWORDS) {
226
+ const schemas = ownValue(node, keyword);
227
+ if (!isSchemaObject(schemas)) continue;
228
+ result[keyword] = Object.fromEntries(Object.entries(schemas).map(([name, schema]) => [name, isSchemaObject(schema) ? strictifyNode(schema, `${path}.${keyword}.${name}`, provider) : schema]));
229
+ }
230
+ return result;
231
+ }
232
+ const COMBINATOR_KEYWORDS = [
233
+ "anyOf",
234
+ "oneOf",
235
+ "allOf"
236
+ ];
237
+ function strictifySchemaArrays(node, path, provider) {
238
+ const result = { ...node };
239
+ for (const keyword of COMBINATOR_KEYWORDS) {
240
+ const schemas = ownValue(node, keyword);
241
+ if (!schemas) continue;
242
+ result[keyword] = schemas.map((schema, index) => strictifyNode(schema, `${path}.${keyword}[${index}]`, provider));
243
+ }
244
+ return result;
245
+ }
246
+ function strictifyObject(node, path, provider) {
247
+ const properties = ownValue(node, "properties");
35
248
  if (!properties) return {
36
249
  ...node,
37
250
  additionalProperties: false
38
251
  };
39
- const existingRequired = new Set(node.required ?? []);
252
+ const existingRequired = new Set(ownValue(node, "required") ?? []);
40
253
  const allKeys = Object.keys(properties);
41
- const strictProps = {};
42
- for (const key of allKeys) {
254
+ const strictProps = Object.fromEntries(allKeys.map((key) => {
43
255
  const prop = properties[key];
44
- const strictProp = strictifyNode(prop, `${path}.${key}`);
45
- if (!existingRequired.has(key)) strictProps[key] = makeNullable(strictProp);
46
- else strictProps[key] = strictProp;
47
- }
256
+ const strictProp = strictifyNode(prop, `${path}.${key}`, provider);
257
+ return [key, existingRequired.has(key) ? strictProp : makeNullable(strictProp)];
258
+ }));
48
259
  return {
49
260
  ...node,
50
261
  type: "object",
@@ -53,24 +264,103 @@ function strictifyObject(node, path) {
53
264
  additionalProperties: false
54
265
  };
55
266
  }
56
- function strictifyArray(node, path) {
57
- const items = node.items;
58
- if (!items) return { ...node };
267
+ const UNREACHABLE_TUPLE_TAIL_SCHEMA = { type: "string" };
268
+ function strictifyArray(node, path, provider) {
269
+ if ((provider === "openai" || provider === "anthropic") && (Array.isArray(ownValue(node, "items")) || Array.isArray(ownValue(node, "prefixItems")))) return normalizeTuple(node, path, provider);
270
+ const result = { ...node };
271
+ const items = ownValue(node, "items");
272
+ if (Array.isArray(items)) result.items = items.map((schema, index) => strictifyNode(schema, `${path}.items[${index}]`, provider));
273
+ else if (items !== void 0) result.items = strictifyNode(items, `${path}.items`, provider);
274
+ const prefixItems = ownValue(node, "prefixItems");
275
+ if (Array.isArray(prefixItems)) result.prefixItems = prefixItems.map((schema, index) => strictifyNode(schema, `${path}.prefixItems[${index}]`, provider));
276
+ return result;
277
+ }
278
+ function normalizeTuple(node, path, provider) {
279
+ const items = ownValue(node, "items");
280
+ const prefixItems = ownValue(node, "prefixItems");
281
+ const legacyTuple = Array.isArray(items);
282
+ const prefixTuple = Array.isArray(prefixItems);
283
+ if (legacyTuple && prefixTuple) throw new StrictifierError("items and prefixItems tuple forms cannot be combined", path);
284
+ if (prefixTuple && Object.hasOwn(node, "additionalItems")) throw new StrictifierError("additionalItems cannot be combined with prefixItems", path);
285
+ const rawTuple = legacyTuple ? items : prefixItems;
286
+ const tuplePath = legacyTuple ? `${path}.items` : `${path}.prefixItems`;
287
+ const tuple = rawTuple.map((schema, index) => {
288
+ if (!isSchemaObject(schema)) throw new StrictifierError("boolean and non-object tuple member schemas are not supported", `${tuplePath}[${index}]`);
289
+ const memberPath = `${tuplePath}[${index}]`;
290
+ const member = strictifyNode(schema, memberPath, provider);
291
+ if (!hasProviderSchemaEntryPoint(member)) throw new StrictifierError("tuple member must define a provider-representable schema", memberPath);
292
+ return member;
293
+ });
294
+ const rawTail = legacyTuple ? ownValue(node, "additionalItems") : items;
295
+ if (rawTail === true) throw new StrictifierError("an unrestricted tuple rest is not supported", path);
296
+ if (rawTail !== void 0 && rawTail !== false && !isSchemaObject(rawTail)) throw new StrictifierError("tuple rest must be an object schema or false", path);
297
+ const tail = isSchemaObject(rawTail) ? strictifyNode(rawTail, legacyTuple ? `${path}.additionalItems` : `${path}.items`, provider) : void 0;
298
+ if (tail !== void 0 && !hasProviderSchemaEntryPoint(tail)) throw new StrictifierError("an unrestricted tuple rest is not supported", path);
299
+ const tailMode = tail !== void 0 ? "typed" : rawTail === false ? "closed" : "implicit";
300
+ const bounds = normalizeTupleBounds(node, tuple.length, tailMode, path);
59
301
  return {
60
- ...node,
61
- items: strictifyNode(items, `${path}.items`)
302
+ ...omitKeys(node, [
303
+ "items",
304
+ "prefixItems",
305
+ "additionalItems",
306
+ "minItems",
307
+ "maxItems"
308
+ ]),
309
+ ...tuple.length > 0 ? { prefixItems: tuple } : {},
310
+ items: tail ?? UNREACHABLE_TUPLE_TAIL_SCHEMA,
311
+ ...bounds
62
312
  };
63
313
  }
314
+ function normalizeTupleBounds(node, tupleLength, tailMode, path) {
315
+ const callerMinItems = integerBound(ownValue(node, "minItems"), "minItems", path);
316
+ const callerMaxItems = integerBound(ownValue(node, "maxItems"), "maxItems", path);
317
+ if (tailMode === "implicit" && callerMaxItems !== void 0 && callerMaxItems > tupleLength) throw new StrictifierError("implicit tuple rest cannot be represented when maxItems exceeds the tuple length", path);
318
+ const minItems = callerMinItems ?? (callerMaxItems === void 0 ? tupleLength : 0);
319
+ const maxItems = tailMode === "typed" ? callerMaxItems : Math.min(callerMaxItems ?? tupleLength, tupleLength);
320
+ if (maxItems !== void 0 && minItems > maxItems) throw new StrictifierError("tuple minItems cannot exceed maxItems", path);
321
+ return {
322
+ minItems,
323
+ ...maxItems !== void 0 ? { maxItems } : {}
324
+ };
325
+ }
326
+ function integerBound(value, keyword, path) {
327
+ if (value === void 0) return void 0;
328
+ if (!Number.isSafeInteger(value) || value < 0) throw new StrictifierError(`${keyword} must be a non-negative safe integer`, path);
329
+ return value;
330
+ }
331
+ function isSchemaObject(value) {
332
+ return typeof value === "object" && value !== null && !Array.isArray(value);
333
+ }
334
+ function ownValue(schema, keyword) {
335
+ return Object.hasOwn(schema, keyword) ? schema[keyword] : void 0;
336
+ }
337
+ const PROVIDER_SCHEMA_ENTRY_POINT_KEYWORDS = /* @__PURE__ */ new Set([
338
+ "type",
339
+ "$ref",
340
+ "properties",
341
+ "anyOf",
342
+ "oneOf",
343
+ "allOf"
344
+ ]);
345
+ function hasProviderSchemaEntryPoint(schema) {
346
+ return Object.keys(schema).some((key) => PROVIDER_SCHEMA_ENTRY_POINT_KEYWORDS.has(key));
347
+ }
348
+ function omitKeys(node, keys) {
349
+ const omitted = new Set(keys);
350
+ return Object.fromEntries(Object.entries(node).filter(([key]) => !omitted.has(key)));
351
+ }
64
352
  function makeNullable(schema) {
65
- if (schema.type === "null") return schema;
66
- if (schema.anyOf) {
67
- const variants = schema.anyOf;
68
- if (variants.some((v) => v.type === "null")) return schema;
353
+ if (ownValue(schema, "type") === "null") return schema;
354
+ const anyOf = ownValue(schema, "anyOf");
355
+ if (anyOf) {
356
+ const variants = anyOf;
357
+ if (variants.some((v) => ownValue(v, "type") === "null")) return schema;
69
358
  return { anyOf: [...variants, { type: "null" }] };
70
359
  }
71
- if (schema.oneOf) {
72
- const variants = schema.oneOf;
73
- if (variants.some((v) => v.type === "null")) return schema;
360
+ const oneOf = ownValue(schema, "oneOf");
361
+ if (oneOf) {
362
+ const variants = oneOf;
363
+ if (variants.some((v) => ownValue(v, "type") === "null")) return schema;
74
364
  return { oneOf: [...variants, { type: "null" }] };
75
365
  }
76
366
  return { anyOf: [schema, { type: "null" }] };
@@ -78,4 +368,4 @@ function makeNullable(schema) {
78
368
  //#endregion
79
369
  export { StrictifierError, strictify };
80
370
 
81
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RyaWN0aWZpZXIuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3Byb3ZpZGVycy9jb21tb24vc3RyaWN0aWZpZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBKU09OIFNjaGVtYSDihpIgT3BlbkFJIHN0cmljdCBKU09OIFNjaGVtYSDrs4DtmZguXG4gKlxuICogT3BlbkFJIFJlc3BvbnNlcyBBUEkgc3RyaWN0IOuqqOuTnCDsmpTqtazsgqztla06XG4gKiAgLSDrqqjrk6Agb2JqZWN0IOyXkCBhZGRpdGlvbmFsUHJvcGVydGllczogZmFsc2VcbiAqICAtIOuqqOuToCBvYmplY3QgcHJvcGVydGllcyDrpbwgcmVxdWlyZWQg7JeQIO2PrO2VqFxuICogIC0gb3B0aW9uYWwg7ZWE65OcIOKGkiBhbnlPZiBbb3JpZ2luYWwsIHsgdHlwZTogJ251bGwnIH1dIOuhnCByZXF1aXJlZCDsnKDsp4BcbiAqICAtIHJlY3Vyc2l2ZSDsspjrpqwgKG5lc3RlZCBvYmplY3RzLCBhcnJheXMsIGFsbE9mL2FueU9mL29uZU9mKVxuICovXG5cbmV4cG9ydCB0eXBlIEpzb25TY2hlbWEgPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcblxuZXhwb3J0IGNsYXNzIFN0cmljdGlmaWVyRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIG1lc3NhZ2U6IHN0cmluZyxcbiAgICBwdWJsaWMgcGF0aDogc3RyaW5nLFxuICApIHtcbiAgICBzdXBlcihgc3RyaWN0aWZpZXI6ICR7bWVzc2FnZX0gKGF0ICR7cGF0aH0pYCk7XG4gICAgdGhpcy5uYW1lID0gXCJTdHJpY3RpZmllckVycm9yXCI7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHN0cmljdGlmeShzY2hlbWE6IEpzb25TY2hlbWEpOiBKc29uU2NoZW1hIHtcbiAgcmV0dXJuIHN0cmljdGlmeU5vZGUoc2NoZW1hLCBcIiRcIik7XG59XG5cbmZ1bmN0aW9uIHN0cmljdGlmeU5vZGUobm9kZTogSnNvblNjaGVtYSwgcGF0aDogc3RyaW5nKTogSnNvblNjaGVtYSB7XG4gIGlmICh0eXBlb2Ygbm9kZSAhPT0gXCJvYmplY3RcIiB8fCBub2RlID09PSBudWxsKSByZXR1cm4gbm9kZTtcblxuICBjb25zdCB0eXBlID0gbm9kZS50eXBlIGFzIHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICBpZiAodHlwZSA9PT0gXCJvYmplY3RcIiB8fCBub2RlLnByb3BlcnRpZXMpIHtcbiAgICByZXR1cm4gc3RyaWN0aWZ5T2JqZWN0KG5vZGUsIHBhdGgpO1xuICB9XG5cbiAgaWYgKHR5cGUgPT09IFwiYXJyYXlcIikge1xuICAgIHJldHVybiBzdHJpY3RpZnlBcnJheShub2RlLCBwYXRoKTtcbiAgfVxuXG4gIGlmIChub2RlLmFueU9mKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLm5vZGUsXG4gICAgICBhbnlPZjogKG5vZGUuYW55T2YgYXMgSnNvblNjaGVtYVtdKS5tYXAoKHMsIGkpID0+IHN0cmljdGlmeU5vZGUocywgYCR7cGF0aH0uYW55T2ZbJHtpfV1gKSksXG4gICAgfTtcbiAgfVxuXG4gIGlmIChub2RlLm9uZU9mKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLm5vZGUsXG4gICAgICBvbmVPZjogKG5vZGUub25lT2YgYXMgSnNvblNjaGVtYVtdKS5tYXAoKHMsIGkpID0+IHN0cmljdGlmeU5vZGUocywgYCR7cGF0aH0ub25lT2ZbJHtpfV1gKSksXG4gICAgfTtcbiAgfVxuXG4gIGlmIChub2RlLmFsbE9mKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLm5vZGUsXG4gICAgICBhbGxPZjogKG5vZGUuYWxsT2YgYXMgSnNvblNjaGVtYVtdKS5tYXAoKHMsIGkpID0+IHN0cmljdGlmeU5vZGUocywgYCR7cGF0aH0uYWxsT2ZbJHtpfV1gKSksXG4gICAgfTtcbiAgfVxuXG4gIGlmIChub2RlLiRyZWYpIHtcbiAgICByZXR1cm4geyAuLi5ub2RlIH07XG4gIH1cblxuICByZXR1cm4geyAuLi5ub2RlIH07XG59XG5cbmZ1bmN0aW9uIHN0cmljdGlmeU9iamVjdChub2RlOiBKc29uU2NoZW1hLCBwYXRoOiBzdHJpbmcpOiBKc29uU2NoZW1hIHtcbiAgY29uc3QgcHJvcGVydGllcyA9IG5vZGUucHJvcGVydGllcyBhcyBSZWNvcmQ8c3RyaW5nLCBKc29uU2NoZW1hPiB8IHVuZGVmaW5lZDtcbiAgaWYgKCFwcm9wZXJ0aWVzKSB7XG4gICAgcmV0dXJuIHsgLi4ubm9kZSwgYWRkaXRpb25hbFByb3BlcnRpZXM6IGZhbHNlIH07XG4gIH1cblxuICBjb25zdCBleGlzdGluZ1JlcXVpcmVkID0gbmV3IFNldCgobm9kZS5yZXF1aXJlZCBhcyBzdHJpbmdbXSB8IHVuZGVmaW5lZCkgPz8gW10pO1xuICBjb25zdCBhbGxLZXlzID0gT2JqZWN0LmtleXMocHJvcGVydGllcyk7XG5cbiAgY29uc3Qgc3RyaWN0UHJvcHM6IFJlY29yZDxzdHJpbmcsIEpzb25TY2hlbWE+ID0ge307XG4gIGZvciAoY29uc3Qga2V5IG9mIGFsbEtleXMpIHtcbiAgICBjb25zdCBwcm9wID0gcHJvcGVydGllc1trZXldITtcbiAgICBjb25zdCBzdHJpY3RQcm9wID0gc3RyaWN0aWZ5Tm9kZShwcm9wLCBgJHtwYXRofS4ke2tleX1gKTtcblxuICAgIGlmICghZXhpc3RpbmdSZXF1aXJlZC5oYXMoa2V5KSkge1xuICAgICAgc3RyaWN0UHJvcHNba2V5XSA9IG1ha2VOdWxsYWJsZShzdHJpY3RQcm9wKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3RyaWN0UHJvcHNba2V5XSA9IHN0cmljdFByb3A7XG4gICAgfVxuICB9XG5cbiAgY29uc3QgcmVzdWx0OiBKc29uU2NoZW1hID0ge1xuICAgIC4uLm5vZGUsXG4gICAgdHlwZTogXCJvYmplY3RcIixcbiAgICBwcm9wZXJ0aWVzOiBzdHJpY3RQcm9wcyxcbiAgICByZXF1aXJlZDogYWxsS2V5cyxcbiAgICBhZGRpdGlvbmFsUHJvcGVydGllczogZmFsc2UsXG4gIH07XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZnVuY3Rpb24gc3RyaWN0aWZ5QXJyYXkobm9kZTogSnNvblNjaGVtYSwgcGF0aDogc3RyaW5nKTogSnNvblNjaGVtYSB7XG4gIGNvbnN0IGl0ZW1zID0gbm9kZS5pdGVtcyBhcyBKc29uU2NoZW1hIHwgdW5kZWZpbmVkO1xuICBpZiAoIWl0ZW1zKSByZXR1cm4geyAuLi5ub2RlIH07XG5cbiAgcmV0dXJuIHtcbiAgICAuLi5ub2RlLFxuICAgIGl0ZW1zOiBzdHJpY3RpZnlOb2RlKGl0ZW1zLCBgJHtwYXRofS5pdGVtc2ApLFxuICB9O1xufVxuXG5mdW5jdGlvbiBtYWtlTnVsbGFibGUoc2NoZW1hOiBKc29uU2NoZW1hKTogSnNvblNjaGVtYSB7XG4gIGlmIChzY2hlbWEudHlwZSA9PT0gXCJudWxsXCIpIHJldHVybiBzY2hlbWE7XG5cbiAgaWYgKHNjaGVtYS5hbnlPZikge1xuICAgIGNvbnN0IHZhcmlhbnRzID0gc2NoZW1hLmFueU9mIGFzIEpzb25TY2hlbWFbXTtcbiAgICBjb25zdCBoYXNOdWxsID0gdmFyaWFudHMuc29tZSgodikgPT4gdi50eXBlID09PSBcIm51bGxcIik7XG4gICAgaWYgKGhhc051bGwpIHJldHVybiBzY2hlbWE7XG4gICAgcmV0dXJuIHsgYW55T2Y6IFsuLi52YXJpYW50cywgeyB0eXBlOiBcIm51bGxcIiB9XSB9O1xuICB9XG5cbiAgaWYgKHNjaGVtYS5vbmVPZikge1xuICAgIGNvbnN0IHZhcmlhbnRzID0gc2NoZW1hLm9uZU9mIGFzIEpzb25TY2hlbWFbXTtcbiAgICBjb25zdCBoYXNOdWxsID0gdmFyaWFudHMuc29tZSgodikgPT4gdi50eXBlID09PSBcIm51bGxcIik7XG4gICAgaWYgKGhhc051bGwpIHJldHVybiBzY2hlbWE7XG4gICAgcmV0dXJuIHsgb25lT2Y6IFsuLi52YXJpYW50cywgeyB0eXBlOiBcIm51bGxcIiB9XSB9O1xuICB9XG5cbiAgcmV0dXJuIHsgYW55T2Y6IFtzY2hlbWEsIHsgdHlwZTogXCJudWxsXCIgfV0gfTtcbn1cbiJdLCJtYXBwaW5ncyI6IjtBQVlBLElBQWEsbUJBQWIsY0FBc0MsTUFBTTtDQUdqQztDQUZULFlBQ0UsU0FDQSxNQUNBO0VBQ0EsTUFBTSxnQkFBZ0IsUUFBUSxPQUFPLEtBQUssRUFBRTtFQUZyQyxLQUFBLE9BQUE7RUFHUCxLQUFLLE9BQU87Q0FDZDtBQUNGO0FBRUEsU0FBZ0IsVUFBVSxRQUFnQztDQUN4RCxPQUFPLGNBQWMsUUFBUSxHQUFHO0FBQ2xDO0FBRUEsU0FBUyxjQUFjLE1BQWtCLE1BQTBCO0NBQ2pFLElBQUksT0FBTyxTQUFTLFlBQVksU0FBUyxNQUFNLE9BQU87Q0FFdEQsTUFBTSxPQUFPLEtBQUs7Q0FFbEIsSUFBSSxTQUFTLFlBQVksS0FBSyxZQUM1QixPQUFPLGdCQUFnQixNQUFNLElBQUk7Q0FHbkMsSUFBSSxTQUFTLFNBQ1gsT0FBTyxlQUFlLE1BQU0sSUFBSTtDQUdsQyxJQUFJLEtBQUssT0FDUCxPQUFPO0VBQ0wsR0FBRztFQUNILE9BQVEsS0FBSyxNQUF1QixLQUFLLEdBQUcsTUFBTSxjQUFjLEdBQUcsR0FBRyxLQUFLLFNBQVMsRUFBRSxFQUFFLENBQUM7Q0FDM0Y7Q0FHRixJQUFJLEtBQUssT0FDUCxPQUFPO0VBQ0wsR0FBRztFQUNILE9BQVEsS0FBSyxNQUF1QixLQUFLLEdBQUcsTUFBTSxjQUFjLEdBQUcsR0FBRyxLQUFLLFNBQVMsRUFBRSxFQUFFLENBQUM7Q0FDM0Y7Q0FHRixJQUFJLEtBQUssT0FDUCxPQUFPO0VBQ0wsR0FBRztFQUNILE9BQVEsS0FBSyxNQUF1QixLQUFLLEdBQUcsTUFBTSxjQUFjLEdBQUcsR0FBRyxLQUFLLFNBQVMsRUFBRSxFQUFFLENBQUM7Q0FDM0Y7Q0FHRixJQUFJLEtBQUssTUFDUCxPQUFPLEVBQUUsR0FBRyxLQUFLO0NBR25CLE9BQU8sRUFBRSxHQUFHLEtBQUs7QUFDbkI7QUFFQSxTQUFTLGdCQUFnQixNQUFrQixNQUEwQjtDQUNuRSxNQUFNLGFBQWEsS0FBSztDQUN4QixJQUFJLENBQUMsWUFDSCxPQUFPO0VBQUUsR0FBRztFQUFNLHNCQUFzQjtDQUFNO0NBR2hELE1BQU0sbUJBQW1CLElBQUksSUFBSyxLQUFLLFlBQXFDLENBQUMsQ0FBQztDQUM5RSxNQUFNLFVBQVUsT0FBTyxLQUFLLFVBQVU7Q0FFdEMsTUFBTSxjQUEwQyxDQUFDO0NBQ2pELEtBQUssTUFBTSxPQUFPLFNBQVM7RUFDekIsTUFBTSxPQUFPLFdBQVc7RUFDeEIsTUFBTSxhQUFhLGNBQWMsTUFBTSxHQUFHLEtBQUssR0FBRyxLQUFLO0VBRXZELElBQUksQ0FBQyxpQkFBaUIsSUFBSSxHQUFHLEdBQzNCLFlBQVksT0FBTyxhQUFhLFVBQVU7T0FFMUMsWUFBWSxPQUFPO0NBRXZCO0NBVUEsT0FBTztFQVBMLEdBQUc7RUFDSCxNQUFNO0VBQ04sWUFBWTtFQUNaLFVBQVU7RUFDVixzQkFBc0I7Q0FHakI7QUFDVDtBQUVBLFNBQVMsZUFBZSxNQUFrQixNQUEwQjtDQUNsRSxNQUFNLFFBQVEsS0FBSztDQUNuQixJQUFJLENBQUMsT0FBTyxPQUFPLEVBQUUsR0FBRyxLQUFLO0NBRTdCLE9BQU87RUFDTCxHQUFHO0VBQ0gsT0FBTyxjQUFjLE9BQU8sR0FBRyxLQUFLLE9BQU87Q0FDN0M7QUFDRjtBQUVBLFNBQVMsYUFBYSxRQUFnQztDQUNwRCxJQUFJLE9BQU8sU0FBUyxRQUFRLE9BQU87Q0FFbkMsSUFBSSxPQUFPLE9BQU87RUFDaEIsTUFBTSxXQUFXLE9BQU87RUFFeEIsSUFEZ0IsU0FBUyxNQUFNLE1BQU0sRUFBRSxTQUFTLE1BQzVDLEdBQVMsT0FBTztFQUNwQixPQUFPLEVBQUUsT0FBTyxDQUFDLEdBQUcsVUFBVSxFQUFFLE1BQU0sT0FBTyxDQUFDLEVBQUU7Q0FDbEQ7Q0FFQSxJQUFJLE9BQU8sT0FBTztFQUNoQixNQUFNLFdBQVcsT0FBTztFQUV4QixJQURnQixTQUFTLE1BQU0sTUFBTSxFQUFFLFNBQVMsTUFDNUMsR0FBUyxPQUFPO0VBQ3BCLE9BQU8sRUFBRSxPQUFPLENBQUMsR0FBRyxVQUFVLEVBQUUsTUFBTSxPQUFPLENBQUMsRUFBRTtDQUNsRDtDQUVBLE9BQU8sRUFBRSxPQUFPLENBQUMsUUFBUSxFQUFFLE1BQU0sT0FBTyxDQUFDLEVBQUU7QUFDN0MifQ==
371
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RyaWN0aWZpZXIuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3Byb3ZpZGVycy9jb21tb24vc3RyaWN0aWZpZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBKU09OIFNjaGVtYSDihpIgT3BlbkFJIHN0cmljdCBKU09OIFNjaGVtYSDrs4DtmZguXG4gKlxuICogT3BlbkFJIFJlc3BvbnNlcyBBUEkgc3RyaWN0IOuqqOuTnCDsmpTqtazsgqztla06XG4gKiAgLSDrqqjrk6Agb2JqZWN0IOyXkCBhZGRpdGlvbmFsUHJvcGVydGllczogZmFsc2VcbiAqICAtIOuqqOuToCBvYmplY3QgcHJvcGVydGllcyDrpbwgcmVxdWlyZWQg7JeQIO2PrO2VqFxuICogIC0gb3B0aW9uYWwg7ZWE65OcIOKGkiBhbnlPZiBbb3JpZ2luYWwsIHsgdHlwZTogJ251bGwnIH1dIOuhnCByZXF1aXJlZCDsnKDsp4BcbiAqICAtIHJlY3Vyc2l2ZSDsspjrpqwgKG5lc3RlZCBvYmplY3RzLCBhcnJheXMsIGFsbE9mL2FueU9mL29uZU9mKVxuICovXG5cbmltcG9ydCB7XG4gIFNDSEVNQV9BUlJBWV9LRVlXT1JEUyxcbiAgU0NIRU1BX01BUF9LRVlXT1JEUyxcbiAgU0NIRU1BX1NJTkdMRV9LRVlXT1JEUyxcbiAgVU5TVVBQT1JURURfUkVGRVJFTkNFX0tFWVdPUkRTLFxufSBmcm9tIFwiLi9qc29uLXNjaGVtYS1rZXl3b3Jkc1wiO1xuXG5leHBvcnQgdHlwZSBKc29uU2NoZW1hID0gUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RyaWN0aWZpZXJPcHRpb25zIHtcbiAgcHJvdmlkZXI/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBjbGFzcyBTdHJpY3RpZmllckVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihcbiAgICBtZXNzYWdlOiBzdHJpbmcsXG4gICAgcHVibGljIHBhdGg6IHN0cmluZyxcbiAgKSB7XG4gICAgc3VwZXIoYHN0cmljdGlmaWVyOiAke21lc3NhZ2V9IChhdCAke3BhdGh9KWApO1xuICAgIHRoaXMubmFtZSA9IFwiU3RyaWN0aWZpZXJFcnJvclwiO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzdHJpY3RpZnkoc2NoZW1hOiBKc29uU2NoZW1hLCBvcHRpb25zOiBTdHJpY3RpZmllck9wdGlvbnMgPSB7fSk6IEpzb25TY2hlbWEge1xuICBpZiAob3B0aW9ucy5wcm92aWRlciA9PT0gXCJvcGVuYWlcIiB8fCBvcHRpb25zLnByb3ZpZGVyID09PSBcImFudGhyb3BpY1wiKSB7XG4gICAgYXNzZXJ0Tm9ybWFsaXphdGlvbkNvbXBhdGliaWxpdHkoc2NoZW1hLCBvcHRpb25zLnByb3ZpZGVyKTtcbiAgfVxuICBjb25zdCByZXN1bHQgPSBzdHJpY3RpZnlOb2RlKHNjaGVtYSwgXCIkXCIsIG9wdGlvbnMucHJvdmlkZXIpO1xuICBpZiAob3B0aW9ucy5wcm92aWRlciA9PT0gXCJvcGVuYWlcIiB8fCBvcHRpb25zLnByb3ZpZGVyID09PSBcImFudGhyb3BpY1wiKSB7XG4gICAgYXNzZXJ0Tm9ybWFsaXphdGlvbkNvbXBhdGliaWxpdHkocmVzdWx0LCBvcHRpb25zLnByb3ZpZGVyKTtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKipcbiAqIOychOy5mCDrqqnroZ3snYAganNvbi1zY2hlbWEta2V5d29yZHMg6rCAIOyGjOycoO2VmOqzoCwg7Jes6riw7ISc64qUIOqwgSDsnITsuZjsnZggYG5vcm1hbGl6YWJsZWAg7Jes67aA66eMIOyWueuKlOuLpC5cbiAqIG5vcm1hbGl6YWJsZT10cnVlIOuKlCBzdHJpY3RpZnlOb2RlIOqwgCDqt7gg7JyE7LmY66W8IOyLpOygnOuhnCDsnqzsnpHshLHtlZzri6TripQg65y77J2064ukLiBgbm90YC9gaWZgIOyymOufvFxuICog7J6s7J6R7ISx7ZWY66m0IGNhbGxlciDsnZjrr7jqsIAg67CU64CM64qUIOychOy5mOuKlCBmYWxzZSDsnbTqs6AsIOq3uCDslYTrnpggdHVwbGUvYCRyZWZgIOuKlCDsoJXqt5ztmZQg64yA7IugIOqxsOu2gOuQnOuLpC5cbiAqXG4gKiBgaXRlbXNgL2BhZGRpdGlvbmFsSXRlbXNgIOuKlCB0dXBsZSDtjJDsoJXqs7wg7ZWo6ruYIOuLpOukhOyVvCDtlbTshJwg7JWE656YIOyInO2ajOyXkOyEnCDqsJzrs4Qg7LKY66as7ZWc64ukLlxuICovXG5jb25zdCBOT05fTk9STUFMSVpBQkxFX1BPU0lUSU9OUyA9IG5ldyBTZXQ8c3RyaW5nPihbXG4gIFwiZGVwZW5kZW50U2NoZW1hc1wiLFxuICBcInBhdHRlcm5Qcm9wZXJ0aWVzXCIsXG4gIFwiYWRkaXRpb25hbFByb3BlcnRpZXNcIixcbiAgXCJjb250YWluc1wiLFxuICBcImNvbnRlbnRTY2hlbWFcIixcbiAgXCJlbHNlXCIsXG4gIFwiaWZcIixcbiAgXCJub3RcIixcbiAgXCJwcm9wZXJ0eU5hbWVzXCIsXG4gIFwidGhlblwiLFxuICBcInVuZXZhbHVhdGVkSXRlbXNcIixcbiAgXCJ1bmV2YWx1YXRlZFByb3BlcnRpZXNcIixcbl0pO1xuXG5mdW5jdGlvbiBwb3NpdGlvbkVudHJpZXMoa2V5d29yZHM6IHJlYWRvbmx5IHN0cmluZ1tdKTogUmVhZG9ubHlBcnJheTxyZWFkb25seSBbc3RyaW5nLCBib29sZWFuXT4ge1xuICByZXR1cm4ga2V5d29yZHMubWFwKChrZXl3b3JkKSA9PiBba2V5d29yZCwgIU5PTl9OT1JNQUxJWkFCTEVfUE9TSVRJT05TLmhhcyhrZXl3b3JkKV0gYXMgY29uc3QpO1xufVxuXG5jb25zdCBTQ0hFTUFfU0NBTl9NQVBfS0VZV09SRFMgPSBwb3NpdGlvbkVudHJpZXMoU0NIRU1BX01BUF9LRVlXT1JEUyk7XG5jb25zdCBTQ0hFTUFfU0NBTl9BUlJBWV9LRVlXT1JEUyA9IHBvc2l0aW9uRW50cmllcyhTQ0hFTUFfQVJSQVlfS0VZV09SRFMpO1xuLy8gaXRlbXMvYWRkaXRpb25hbEl0ZW1zIOuKlCB0dXBsZSDrtoTquLDsl5DshJwg7KeB7KCRIOuLpOujqOuvgOuhnCDri6jsnbwg7JyE7LmYIOyKpOy6lOyXkOyEnCDsoJzsmbjtlZzri6QuXG5jb25zdCBTQ0hFTUFfU0NBTl9TSU5HTEVfS0VZV09SRFMgPSBwb3NpdGlvbkVudHJpZXMoXG4gIFNDSEVNQV9TSU5HTEVfS0VZV09SRFMuZmlsdGVyKChrZXl3b3JkKSA9PiBrZXl3b3JkICE9PSBcIml0ZW1zXCIgJiYga2V5d29yZCAhPT0gXCJhZGRpdGlvbmFsSXRlbXNcIiksXG4pO1xuXG4vKipcbiAqIEluc3BlY3QgZXZlcnkgSlNPTiBTY2hlbWEtYmVhcmluZyBwb3NpdGlvbiB3aXRob3V0IHJld3JpdGluZyBpdC5cbiAqXG4gKiBQb3NpdGl2ZSBwb3NpdGlvbnMgYWxyZWFkeSB0cmF2ZXJzZWQgYnkgc3RyaWN0aWZ5Tm9kZSBtYXkgbm9ybWFsaXplIE9wZW5BSSB0dXBsZXMuIFBvc2l0aW9uc1xuICogc3VjaCBhcyBgbm90YCBhbmQgYGlmYCBjYW5ub3QgYmUgdGlnaHRlbmVkIHdpdGhvdXQgY2hhbmdpbmcgY2FsbGVyIHNlbWFudGljcywgc28gcG9zaXRpb25hbFxuICogdHVwbGVzIHRoZXJlIGZhaWwgZXhwbGljaXRseSBpbnN0ZWFkIG9mIGxlYWtpbmcgYW4gdW5zdXBwb3J0ZWQgcHJvdmlkZXIgc2NoZW1hLiBSZWZlcmVuY2VzXG4gKiBmcm9tIHRob3NlIHBvc2l0aW9ucyBhbHNvIGZhaWwgYmVjYXVzZSB0aGVpciBkZWZpbml0aW9ucyBhcmUgbm9ybWFsaXplZCBnbG9iYWxseS5cbiAqL1xuZnVuY3Rpb24gYXNzZXJ0Tm9ybWFsaXphdGlvbkNvbXBhdGliaWxpdHkoXG4gIHNjaGVtYTogSnNvblNjaGVtYSxcbiAgcHJvdmlkZXI6IFwib3BlbmFpXCIgfCBcImFudGhyb3BpY1wiLFxuKTogdm9pZCB7XG4gIGNvbnN0IHJlZmVyZW5jZXM6IEFycmF5PHsgdmFsdWU6IHN0cmluZzsgcGF0aDogc3RyaW5nIH0+ID0gW107XG4gIGNvbnN0IHN0YWNrOiBBcnJheTx7IG5vZGU6IEpzb25TY2hlbWE7IHBhdGg6IHN0cmluZzsgbm9ybWFsaXphYmxlOiBib29sZWFuIH0+ID0gW1xuICAgIHsgbm9kZTogc2NoZW1hLCBwYXRoOiBcIiRcIiwgbm9ybWFsaXphYmxlOiB0cnVlIH0sXG4gIF07XG5cbiAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDApIHtcbiAgICBjb25zdCBjdXJyZW50ID0gc3RhY2sucG9wKCkhO1xuICAgIGNvbnN0IGl0ZW1zVmFsdWUgPSBvd25WYWx1ZShjdXJyZW50Lm5vZGUsIFwiaXRlbXNcIik7XG4gICAgY29uc3QgcHJlZml4SXRlbXNWYWx1ZSA9IG93blZhbHVlKGN1cnJlbnQubm9kZSwgXCJwcmVmaXhJdGVtc1wiKTtcbiAgICBjb25zdCBsZWdhY3lUdXBsZSA9IEFycmF5LmlzQXJyYXkoaXRlbXNWYWx1ZSk7XG4gICAgY29uc3QgcHJlZml4VHVwbGUgPSBBcnJheS5pc0FycmF5KHByZWZpeEl0ZW1zVmFsdWUpO1xuXG4gICAgYXNzZXJ0VW5zdXBwb3J0ZWRSZWZlcmVuY2VLZXl3b3JkcyhjdXJyZW50Lm5vZGUsIGN1cnJlbnQucGF0aCk7XG4gICAgY29sbGVjdFNjaGVtYVJlZmVyZW5jZShjdXJyZW50LCByZWZlcmVuY2VzKTtcblxuICAgIGlmIChsZWdhY3lUdXBsZSB8fCBwcmVmaXhUdXBsZSkge1xuICAgICAgY29uc3QgdHVwbGUgPSAobGVnYWN5VHVwbGUgPyBpdGVtc1ZhbHVlIDogcHJlZml4SXRlbXNWYWx1ZSkgYXMgdW5rbm93bltdO1xuICAgICAgaWYgKHByb3ZpZGVyID09PSBcImFudGhyb3BpY1wiICYmIHR1cGxlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IFN0cmljdGlmaWVyRXJyb3IoXG4gICAgICAgICAgXCJwb3NpdGlvbmFsIHR1cGxlIHNjaGVtYXMgYXJlIG5vdCBzdXBwb3J0ZWQgb24gQW50aHJvcGljIGJlY2F1c2UgQ2xhdWRlIENvZGUgY2Fubm90IHByZXNlcnZlIGl0ZW0gcG9zaXRpb25zXCIsXG4gICAgICAgICAgY3VycmVudC5wYXRoLFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgaWYgKCFjdXJyZW50Lm5vcm1hbGl6YWJsZSkge1xuICAgICAgICB0aHJvdyBuZXcgU3RyaWN0aWZpZXJFcnJvcihcbiAgICAgICAgICBcInBvc2l0aW9uYWwgdHVwbGUgc2NoZW1hcyBhcmUgbm90IHN1cHBvcnRlZCBpbiB0aGlzIHNjaGVtYSBwb3NpdGlvblwiLFxuICAgICAgICAgIGN1cnJlbnQucGF0aCxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIGlmIChvd25WYWx1ZShjdXJyZW50Lm5vZGUsIFwidHlwZVwiKSAhPT0gXCJhcnJheVwiKSB7XG4gICAgICAgIHRocm93IG5ldyBTdHJpY3RpZmllckVycm9yKFxuICAgICAgICAgICdwb3NpdGlvbmFsIHR1cGxlIHNjaGVtYXMgbXVzdCBkZWNsYXJlIHR5cGUgXCJhcnJheVwiOyBleHByZXNzIG51bGxhYmxlIHR1cGxlcyB3aXRoIGFueU9mJyxcbiAgICAgICAgICBgJHtjdXJyZW50LnBhdGh9LnR5cGVgLFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZvciAoY29uc3QgW2tleXdvcmQsIGtleXdvcmROb3JtYWxpemFibGVdIG9mIFNDSEVNQV9TQ0FOX01BUF9LRVlXT1JEUykge1xuICAgICAgY29uc3Qgc2NoZW1hcyA9IG93blZhbHVlKGN1cnJlbnQubm9kZSwga2V5d29yZCk7XG4gICAgICBpZiAoIWlzU2NoZW1hT2JqZWN0KHNjaGVtYXMpKSBjb250aW51ZTtcbiAgICAgIGZvciAoY29uc3QgW25hbWUsIGNoaWxkXSBvZiBPYmplY3QuZW50cmllcyhzY2hlbWFzKSkge1xuICAgICAgICBpZiAoIWlzU2NoZW1hT2JqZWN0KGNoaWxkKSkgY29udGludWU7XG4gICAgICAgIHN0YWNrLnB1c2goe1xuICAgICAgICAgIG5vZGU6IGNoaWxkLFxuICAgICAgICAgIHBhdGg6IGAke2N1cnJlbnQucGF0aH0uJHtrZXl3b3JkfS4ke25hbWV9YCxcbiAgICAgICAgICBub3JtYWxpemFibGU6IGN1cnJlbnQubm9ybWFsaXphYmxlICYmIGtleXdvcmROb3JtYWxpemFibGUsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGRlcGVuZGVuY2llcyA9IG93blZhbHVlKGN1cnJlbnQubm9kZSwgXCJkZXBlbmRlbmNpZXNcIik7XG4gICAgaWYgKGlzU2NoZW1hT2JqZWN0KGRlcGVuZGVuY2llcykpIHtcbiAgICAgIGZvciAoY29uc3QgW25hbWUsIGNoaWxkXSBvZiBPYmplY3QuZW50cmllcyhkZXBlbmRlbmNpZXMpKSB7XG4gICAgICAgIGlmICghaXNTY2hlbWFPYmplY3QoY2hpbGQpKSBjb250aW51ZTtcbiAgICAgICAgc3RhY2sucHVzaCh7XG4gICAgICAgICAgbm9kZTogY2hpbGQsXG4gICAgICAgICAgcGF0aDogYCR7Y3VycmVudC5wYXRofS5kZXBlbmRlbmNpZXMuJHtuYW1lfWAsXG4gICAgICAgICAgbm9ybWFsaXphYmxlOiBmYWxzZSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBba2V5d29yZCwga2V5d29yZE5vcm1hbGl6YWJsZV0gb2YgU0NIRU1BX1NDQU5fQVJSQVlfS0VZV09SRFMpIHtcbiAgICAgIGNvbnN0IHNjaGVtYXMgPSBvd25WYWx1ZShjdXJyZW50Lm5vZGUsIGtleXdvcmQpO1xuICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHNjaGVtYXMpKSBjb250aW51ZTtcbiAgICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBzY2hlbWFzLmxlbmd0aDsgaW5kZXggKz0gMSkge1xuICAgICAgICBjb25zdCBjaGlsZCA9IHNjaGVtYXNbaW5kZXhdO1xuICAgICAgICBpZiAoIWlzU2NoZW1hT2JqZWN0KGNoaWxkKSkgY29udGludWU7XG4gICAgICAgIHN0YWNrLnB1c2goe1xuICAgICAgICAgIG5vZGU6IGNoaWxkLFxuICAgICAgICAgIHBhdGg6IGAke2N1cnJlbnQucGF0aH0uJHtrZXl3b3JkfVske2luZGV4fV1gLFxuICAgICAgICAgIG5vcm1hbGl6YWJsZTogY3VycmVudC5ub3JtYWxpemFibGUgJiYga2V5d29yZE5vcm1hbGl6YWJsZSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgaXRlbXMgPSBvd25WYWx1ZShjdXJyZW50Lm5vZGUsIFwiaXRlbXNcIik7XG4gICAgaWYgKGlzU2NoZW1hT2JqZWN0KGl0ZW1zKSkge1xuICAgICAgc3RhY2sucHVzaCh7XG4gICAgICAgIG5vZGU6IGl0ZW1zLFxuICAgICAgICBwYXRoOiBgJHtjdXJyZW50LnBhdGh9Lml0ZW1zYCxcbiAgICAgICAgbm9ybWFsaXphYmxlOiBjdXJyZW50Lm5vcm1hbGl6YWJsZSxcbiAgICAgIH0pO1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShpdGVtcykpIHtcbiAgICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBpdGVtcy5sZW5ndGg7IGluZGV4ICs9IDEpIHtcbiAgICAgICAgY29uc3QgY2hpbGQgPSBpdGVtc1tpbmRleF07XG4gICAgICAgIGlmICghaXNTY2hlbWFPYmplY3QoY2hpbGQpKSBjb250aW51ZTtcbiAgICAgICAgc3RhY2sucHVzaCh7XG4gICAgICAgICAgbm9kZTogY2hpbGQsXG4gICAgICAgICAgcGF0aDogYCR7Y3VycmVudC5wYXRofS5pdGVtc1ske2luZGV4fV1gLFxuICAgICAgICAgIG5vcm1hbGl6YWJsZTogY3VycmVudC5ub3JtYWxpemFibGUsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGFkZGl0aW9uYWxJdGVtcyA9IG93blZhbHVlKGN1cnJlbnQubm9kZSwgXCJhZGRpdGlvbmFsSXRlbXNcIik7XG4gICAgaWYgKGlzU2NoZW1hT2JqZWN0KGFkZGl0aW9uYWxJdGVtcykpIHtcbiAgICAgIHN0YWNrLnB1c2goe1xuICAgICAgICBub2RlOiBhZGRpdGlvbmFsSXRlbXMsXG4gICAgICAgIHBhdGg6IGAke2N1cnJlbnQucGF0aH0uYWRkaXRpb25hbEl0ZW1zYCxcbiAgICAgICAgbm9ybWFsaXphYmxlOiBjdXJyZW50Lm5vcm1hbGl6YWJsZSAmJiBsZWdhY3lUdXBsZSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgW2tleXdvcmQsIGtleXdvcmROb3JtYWxpemFibGVdIG9mIFNDSEVNQV9TQ0FOX1NJTkdMRV9LRVlXT1JEUykge1xuICAgICAgY29uc3QgY2hpbGQgPSBvd25WYWx1ZShjdXJyZW50Lm5vZGUsIGtleXdvcmQpO1xuICAgICAgaWYgKCFpc1NjaGVtYU9iamVjdChjaGlsZCkpIGNvbnRpbnVlO1xuICAgICAgc3RhY2sucHVzaCh7XG4gICAgICAgIG5vZGU6IGNoaWxkLFxuICAgICAgICBwYXRoOiBgJHtjdXJyZW50LnBhdGh9LiR7a2V5d29yZH1gLFxuICAgICAgICBub3JtYWxpemFibGU6IGN1cnJlbnQubm9ybWFsaXphYmxlICYmIGtleXdvcmROb3JtYWxpemFibGUsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBhc3NlcnRSZWZlcmVuY2VUYXJnZXRzKHNjaGVtYSwgcmVmZXJlbmNlcyk7XG59XG5cbmZ1bmN0aW9uIGFzc2VydFVuc3VwcG9ydGVkUmVmZXJlbmNlS2V5d29yZHMoc2NoZW1hOiBKc29uU2NoZW1hLCBwYXRoOiBzdHJpbmcpOiB2b2lkIHtcbiAgZm9yIChjb25zdCBrZXl3b3JkIG9mIFVOU1VQUE9SVEVEX1JFRkVSRU5DRV9LRVlXT1JEUykge1xuICAgIGlmIChPYmplY3QuaGFzT3duKHNjaGVtYSwga2V5d29yZCkpIHtcbiAgICAgIHRocm93IG5ldyBTdHJpY3RpZmllckVycm9yKGAke2tleXdvcmR9IGlzIG5vdCBzdXBwb3J0ZWRgLCBgJHtwYXRofS4ke2tleXdvcmR9YCk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGNvbGxlY3RTY2hlbWFSZWZlcmVuY2UoXG4gIGN1cnJlbnQ6IHsgbm9kZTogSnNvblNjaGVtYTsgcGF0aDogc3RyaW5nOyBub3JtYWxpemFibGU6IGJvb2xlYW4gfSxcbiAgcmVmZXJlbmNlczogQXJyYXk8eyB2YWx1ZTogc3RyaW5nOyBwYXRoOiBzdHJpbmcgfT4sXG4pOiB2b2lkIHtcbiAgaWYgKCFPYmplY3QuaGFzT3duKGN1cnJlbnQubm9kZSwgXCIkcmVmXCIpKSByZXR1cm47XG5cbiAgY29uc3QgcmVmZXJlbmNlID0gY3VycmVudC5ub2RlLiRyZWY7XG4gIGlmICh0eXBlb2YgcmVmZXJlbmNlICE9PSBcInN0cmluZ1wiKSB7XG4gICAgdGhyb3cgbmV3IFN0cmljdGlmaWVyRXJyb3IoXCIkcmVmIG11c3QgYmUgYSBzdHJpbmdcIiwgYCR7Y3VycmVudC5wYXRofS4kcmVmYCk7XG4gIH1cbiAgaWYgKCFjdXJyZW50Lm5vcm1hbGl6YWJsZSkge1xuICAgIHRocm93IG5ldyBTdHJpY3RpZmllckVycm9yKFxuICAgICAgXCJzY2hlbWEgcmVmZXJlbmNlcyBhcmUgbm90IHN1cHBvcnRlZCBpbiB0aGlzIHNjaGVtYSBwb3NpdGlvblwiLFxuICAgICAgY3VycmVudC5wYXRoLFxuICAgICk7XG4gIH1cblxuICByZWZlcmVuY2VzLnB1c2goeyB2YWx1ZTogcmVmZXJlbmNlLCBwYXRoOiBgJHtjdXJyZW50LnBhdGh9LiRyZWZgIH0pO1xufVxuXG5mdW5jdGlvbiBhc3NlcnRSZWZlcmVuY2VUYXJnZXRzKFxuICByb290OiBKc29uU2NoZW1hLFxuICByZWZlcmVuY2VzOiBBcnJheTx7IHZhbHVlOiBzdHJpbmc7IHBhdGg6IHN0cmluZyB9Pixcbik6IHZvaWQge1xuICBmb3IgKGNvbnN0IHJlZmVyZW5jZSBvZiByZWZlcmVuY2VzKSB7XG4gICAgY29uc3QgdG9rZW5zID0gcGFyc2VMb2NhbEpzb25Qb2ludGVyKHJlZmVyZW5jZS52YWx1ZSwgcmVmZXJlbmNlLnBhdGgpO1xuICAgIGlmICghaXNEZWZpbml0aW9uUm9vdFBvaW50ZXIodG9rZW5zKSkge1xuICAgICAgdGhyb3cgbmV3IFN0cmljdGlmaWVyRXJyb3IoXG4gICAgICAgIFwiJHJlZiB0YXJnZXQgbXVzdCBiZSB0aGUgZG9jdW1lbnQgcm9vdCBvciBhIGRlZmluaXRpb24gcm9vdFwiLFxuICAgICAgICByZWZlcmVuY2UucGF0aCxcbiAgICAgICk7XG4gICAgfVxuICAgIHJlc29sdmVEZWZpbml0aW9uUm9vdChyb290LCB0b2tlbnMsIHJlZmVyZW5jZS5wYXRoKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBpc0RlZmluaXRpb25Sb290UG9pbnRlcih0b2tlbnM6IHN0cmluZ1tdKTogYm9vbGVhbiB7XG4gIGlmICh0b2tlbnMubGVuZ3RoID09PSAwKSByZXR1cm4gdHJ1ZTtcbiAgaWYgKHRva2Vucy5sZW5ndGggJSAyICE9PSAwKSByZXR1cm4gZmFsc2U7XG5cbiAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IHRva2Vucy5sZW5ndGg7IGluZGV4ICs9IDIpIHtcbiAgICBpZiAodG9rZW5zW2luZGV4XSAhPT0gXCIkZGVmc1wiICYmIHRva2Vuc1tpbmRleF0gIT09IFwiZGVmaW5pdGlvbnNcIikgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBwYXJzZUxvY2FsSnNvblBvaW50ZXIocmVmZXJlbmNlOiBzdHJpbmcsIHBhdGg6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgaWYgKHJlZmVyZW5jZSA9PT0gXCIjXCIpIHJldHVybiBbXTtcbiAgaWYgKCFyZWZlcmVuY2Uuc3RhcnRzV2l0aChcIiMvXCIpKSB7XG4gICAgdGhyb3cgbmV3IFN0cmljdGlmaWVyRXJyb3IoXG4gICAgICBcIm9ubHkgbG9jYWwgcm9vdC1yZWxhdGl2ZSBKU09OIFBvaW50ZXIgJHJlZiB2YWx1ZXMgYXJlIHN1cHBvcnRlZFwiLFxuICAgICAgcGF0aCxcbiAgICApO1xuICB9XG5cbiAgbGV0IGZyYWdtZW50OiBzdHJpbmc7XG4gIHRyeSB7XG4gICAgZnJhZ21lbnQgPSBkZWNvZGVVUklDb21wb25lbnQocmVmZXJlbmNlLnNsaWNlKDEpKTtcbiAgfSBjYXRjaCB7XG4gICAgdGhyb3cgbmV3IFN0cmljdGlmaWVyRXJyb3IoXCIkcmVmIGNvbnRhaW5zIGludmFsaWQgcGVyY2VudCBlbmNvZGluZ1wiLCBwYXRoKTtcbiAgfVxuICBpZiAoIWZyYWdtZW50LnN0YXJ0c1dpdGgoXCIvXCIpKSB7XG4gICAgdGhyb3cgbmV3IFN0cmljdGlmaWVyRXJyb3IoXG4gICAgICBcIm9ubHkgbG9jYWwgcm9vdC1yZWxhdGl2ZSBKU09OIFBvaW50ZXIgJHJlZiB2YWx1ZXMgYXJlIHN1cHBvcnRlZFwiLFxuICAgICAgcGF0aCxcbiAgICApO1xuICB9XG5cbiAgcmV0dXJuIGZyYWdtZW50XG4gICAgLnNsaWNlKDEpXG4gICAgLnNwbGl0KFwiL1wiKVxuICAgIC5tYXAoKHRva2VuKSA9PiBkZWNvZGVKc29uUG9pbnRlclRva2VuKHRva2VuLCBwYXRoKSk7XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVEZWZpbml0aW9uUm9vdChyb290OiBKc29uU2NoZW1hLCB0b2tlbnM6IHN0cmluZ1tdLCBwYXRoOiBzdHJpbmcpOiB2b2lkIHtcbiAgbGV0IGN1cnJlbnQgPSByb290O1xuICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgdG9rZW5zLmxlbmd0aDsgaW5kZXggKz0gMikge1xuICAgIGNvbnN0IGtleXdvcmQgPSB0b2tlbnNbaW5kZXhdITtcbiAgICBjb25zdCBuYW1lID0gdG9rZW5zW2luZGV4ICsgMV0hO1xuICAgIGNvbnN0IGRlZmluaXRpb25zID0gb3duVmFsdWUoY3VycmVudCwga2V5d29yZCk7XG4gICAgaWYgKCFpc1NjaGVtYU9iamVjdChkZWZpbml0aW9ucykgfHwgIU9iamVjdC5oYXNPd24oZGVmaW5pdGlvbnMsIG5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgU3RyaWN0aWZpZXJFcnJvcihcIiRyZWYgZG9lcyBub3QgcmVzb2x2ZSBpbnNpZGUgdGhlIGNhbGxlciBzY2hlbWFcIiwgcGF0aCk7XG4gICAgfVxuICAgIGNvbnN0IHRhcmdldCA9IGRlZmluaXRpb25zW25hbWVdO1xuICAgIGlmICghaXNTY2hlbWFPYmplY3QodGFyZ2V0KSkge1xuICAgICAgdGhyb3cgbmV3IFN0cmljdGlmaWVyRXJyb3IoXCIkcmVmIHRhcmdldCBtdXN0IGJlIGFuIG9iamVjdCBzY2hlbWFcIiwgcGF0aCk7XG4gICAgfVxuICAgIGN1cnJlbnQgPSB0YXJnZXQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gZGVjb2RlSnNvblBvaW50ZXJUb2tlbihyYXdUb2tlbjogc3RyaW5nLCBwYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuICBsZXQgdG9rZW4gPSBcIlwiO1xuICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgcmF3VG9rZW4ubGVuZ3RoOyBpbmRleCArPSAxKSB7XG4gICAgY29uc3QgY2hhcmFjdGVyID0gcmF3VG9rZW5baW5kZXhdITtcbiAgICBpZiAoY2hhcmFjdGVyICE9PSBcIn5cIikge1xuICAgICAgdG9rZW4gKz0gY2hhcmFjdGVyO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgY29uc3QgZXNjYXBlZCA9IHJhd1Rva2VuW2luZGV4ICsgMV07XG4gICAgaWYgKGVzY2FwZWQgPT09IFwiMFwiKSB7XG4gICAgICB0b2tlbiArPSBcIn5cIjtcbiAgICB9IGVsc2UgaWYgKGVzY2FwZWQgPT09IFwiMVwiKSB7XG4gICAgICB0b2tlbiArPSBcIi9cIjtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFN0cmljdGlmaWVyRXJyb3IoXCIkcmVmIGNvbnRhaW5zIGFuIGludmFsaWQgSlNPTiBQb2ludGVyIGVzY2FwZVwiLCBwYXRoKTtcbiAgICB9XG4gICAgaW5kZXggKz0gMTtcbiAgfVxuICByZXR1cm4gdG9rZW47XG59XG5cbmZ1bmN0aW9uIHN0cmljdGlmeU5vZGUobm9kZTogSnNvblNjaGVtYSwgcGF0aDogc3RyaW5nLCBwcm92aWRlcj86IHN0cmluZyk6IEpzb25TY2hlbWEge1xuICBpZiAodHlwZW9mIG5vZGUgIT09IFwib2JqZWN0XCIgfHwgbm9kZSA9PT0gbnVsbCkgcmV0dXJuIG5vZGU7XG5cbiAgY29uc3QgZGlhbGVjdE5ldXRyYWxOb2RlID0gcHJvdmlkZXIgPT09IFwib3BlbmFpXCIgPyBvbWl0S2V5cyhub2RlLCBbXCIkc2NoZW1hXCJdKSA6IG5vZGU7XG4gIGxldCByZXN1bHQgPSBzdHJpY3RpZnlTY2hlbWFNYXBzKGRpYWxlY3ROZXV0cmFsTm9kZSwgcGF0aCwgcHJvdmlkZXIpO1xuICBjb25zdCB0eXBlID0gb3duVmFsdWUocmVzdWx0LCBcInR5cGVcIikgYXMgc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gIGlmICh0eXBlID09PSBcIm9iamVjdFwiIHx8IE9iamVjdC5oYXNPd24ocmVzdWx0LCBcInByb3BlcnRpZXNcIikpIHtcbiAgICByZXN1bHQgPSBzdHJpY3RpZnlPYmplY3QocmVzdWx0LCBwYXRoLCBwcm92aWRlcik7XG4gIH1cblxuICBpZiAodHlwZSA9PT0gXCJhcnJheVwiIHx8IE9iamVjdC5oYXNPd24ocmVzdWx0LCBcIml0ZW1zXCIpIHx8IE9iamVjdC5oYXNPd24ocmVzdWx0LCBcInByZWZpeEl0ZW1zXCIpKSB7XG4gICAgcmVzdWx0ID0gc3RyaWN0aWZ5QXJyYXkocmVzdWx0LCBwYXRoLCBwcm92aWRlcik7XG4gIH1cblxuICByZXR1cm4gc3RyaWN0aWZ5U2NoZW1hQXJyYXlzKHJlc3VsdCwgcGF0aCwgcHJvdmlkZXIpO1xufVxuXG4vLyDsnqzsnpHshLEg7Yyo7Iqk64qUIOygleydmCDrp7Xrp4wg7J6s6reA7ZWc64ukLiBwcm9wZXJ0aWVzIOuKlCBzdHJpY3RpZnlPYmplY3Qg6rCAIOuzhOuPhOuhnCDsspjrpqztlZjrr4DroZxcbi8vIOqzteycoCDsnITsuZgg66qp66GdKFNDSEVNQV9NQVBfS0VZV09SRFMp6rO8IOydmOuPhOyggeycvOuhnCDrspTsnITqsIAg64uk66W064ukLlxuY29uc3QgREVGSU5JVElPTl9NQVBfS0VZV09SRFMgPSBbXCIkZGVmc1wiLCBcImRlZmluaXRpb25zXCJdIGFzIGNvbnN0O1xuXG5mdW5jdGlvbiBzdHJpY3RpZnlTY2hlbWFNYXBzKG5vZGU6IEpzb25TY2hlbWEsIHBhdGg6IHN0cmluZywgcHJvdmlkZXI/OiBzdHJpbmcpOiBKc29uU2NoZW1hIHtcbiAgY29uc3QgcmVzdWx0ID0geyAuLi5ub2RlIH07XG5cbiAgZm9yIChjb25zdCBrZXl3b3JkIG9mIERFRklOSVRJT05fTUFQX0tFWVdPUkRTKSB7XG4gICAgY29uc3Qgc2NoZW1hcyA9IG93blZhbHVlKG5vZGUsIGtleXdvcmQpO1xuICAgIGlmICghaXNTY2hlbWFPYmplY3Qoc2NoZW1hcykpIGNvbnRpbnVlO1xuXG4gICAgcmVzdWx0W2tleXdvcmRdID0gT2JqZWN0LmZyb21FbnRyaWVzKFxuICAgICAgT2JqZWN0LmVudHJpZXMoc2NoZW1hcykubWFwKChbbmFtZSwgc2NoZW1hXSkgPT4gW1xuICAgICAgICBuYW1lLFxuICAgICAgICBpc1NjaGVtYU9iamVjdChzY2hlbWEpXG4gICAgICAgICAgPyBzdHJpY3RpZnlOb2RlKHNjaGVtYSwgYCR7cGF0aH0uJHtrZXl3b3JkfS4ke25hbWV9YCwgcHJvdmlkZXIpXG4gICAgICAgICAgOiBzY2hlbWEsXG4gICAgICBdKSxcbiAgICApO1xuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLy8gcHJlZml4SXRlbXMg64qUIHN0cmljdGlmeUFycmF5IOydmCB0dXBsZSDqsr3roZzqsIAg64uk66Oo66+A66GcIOyXrOq4sOyEnOuKlCDsobDtlakga2V5d29yZCDrp4wg7J6s6reA7ZWc64ukLlxuY29uc3QgQ09NQklOQVRPUl9LRVlXT1JEUyA9IFtcImFueU9mXCIsIFwib25lT2ZcIiwgXCJhbGxPZlwiXSBhcyBjb25zdDtcblxuZnVuY3Rpb24gc3RyaWN0aWZ5U2NoZW1hQXJyYXlzKG5vZGU6IEpzb25TY2hlbWEsIHBhdGg6IHN0cmluZywgcHJvdmlkZXI/OiBzdHJpbmcpOiBKc29uU2NoZW1hIHtcbiAgY29uc3QgcmVzdWx0ID0geyAuLi5ub2RlIH07XG5cbiAgZm9yIChjb25zdCBrZXl3b3JkIG9mIENPTUJJTkFUT1JfS0VZV09SRFMpIHtcbiAgICBjb25zdCBzY2hlbWFzID0gb3duVmFsdWUobm9kZSwga2V5d29yZCk7XG4gICAgaWYgKCFzY2hlbWFzKSBjb250aW51ZTtcbiAgICByZXN1bHRba2V5d29yZF0gPSAoc2NoZW1hcyBhcyBKc29uU2NoZW1hW10pLm1hcCgoc2NoZW1hLCBpbmRleCkgPT5cbiAgICAgIHN0cmljdGlmeU5vZGUoc2NoZW1hLCBgJHtwYXRofS4ke2tleXdvcmR9WyR7aW5kZXh9XWAsIHByb3ZpZGVyKSxcbiAgICApO1xuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZnVuY3Rpb24gc3RyaWN0aWZ5T2JqZWN0KG5vZGU6IEpzb25TY2hlbWEsIHBhdGg6IHN0cmluZywgcHJvdmlkZXI/OiBzdHJpbmcpOiBKc29uU2NoZW1hIHtcbiAgY29uc3QgcHJvcGVydGllcyA9IG93blZhbHVlKG5vZGUsIFwicHJvcGVydGllc1wiKSBhcyBSZWNvcmQ8c3RyaW5nLCBKc29uU2NoZW1hPiB8IHVuZGVmaW5lZDtcbiAgaWYgKCFwcm9wZXJ0aWVzKSB7XG4gICAgcmV0dXJuIHsgLi4ubm9kZSwgYWRkaXRpb25hbFByb3BlcnRpZXM6IGZhbHNlIH07XG4gIH1cblxuICBjb25zdCBleGlzdGluZ1JlcXVpcmVkID0gbmV3IFNldCgob3duVmFsdWUobm9kZSwgXCJyZXF1aXJlZFwiKSBhcyBzdHJpbmdbXSB8IHVuZGVmaW5lZCkgPz8gW10pO1xuICBjb25zdCBhbGxLZXlzID0gT2JqZWN0LmtleXMocHJvcGVydGllcyk7XG5cbiAgY29uc3Qgc3RyaWN0UHJvcHMgPSBPYmplY3QuZnJvbUVudHJpZXMoXG4gICAgYWxsS2V5cy5tYXAoKGtleSkgPT4ge1xuICAgICAgY29uc3QgcHJvcCA9IHByb3BlcnRpZXNba2V5XSE7XG4gICAgICBjb25zdCBzdHJpY3RQcm9wID0gc3RyaWN0aWZ5Tm9kZShwcm9wLCBgJHtwYXRofS4ke2tleX1gLCBwcm92aWRlcik7XG5cbiAgICAgIHJldHVybiBba2V5LCBleGlzdGluZ1JlcXVpcmVkLmhhcyhrZXkpID8gc3RyaWN0UHJvcCA6IG1ha2VOdWxsYWJsZShzdHJpY3RQcm9wKV07XG4gICAgfSksXG4gICkgYXMgUmVjb3JkPHN0cmluZywgSnNvblNjaGVtYT47XG5cbiAgY29uc3QgcmVzdWx0OiBKc29uU2NoZW1hID0ge1xuICAgIC4uLm5vZGUsXG4gICAgdHlwZTogXCJvYmplY3RcIixcbiAgICBwcm9wZXJ0aWVzOiBzdHJpY3RQcm9wcyxcbiAgICByZXF1aXJlZDogYWxsS2V5cyxcbiAgICBhZGRpdGlvbmFsUHJvcGVydGllczogZmFsc2UsXG4gIH07XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuY29uc3QgVU5SRUFDSEFCTEVfVFVQTEVfVEFJTF9TQ0hFTUE6IEpzb25TY2hlbWEgPSB7IHR5cGU6IFwic3RyaW5nXCIgfTtcblxuZnVuY3Rpb24gc3RyaWN0aWZ5QXJyYXkobm9kZTogSnNvblNjaGVtYSwgcGF0aDogc3RyaW5nLCBwcm92aWRlcj86IHN0cmluZyk6IEpzb25TY2hlbWEge1xuICBpZiAoXG4gICAgKHByb3ZpZGVyID09PSBcIm9wZW5haVwiIHx8IHByb3ZpZGVyID09PSBcImFudGhyb3BpY1wiKSAmJlxuICAgIChBcnJheS5pc0FycmF5KG93blZhbHVlKG5vZGUsIFwiaXRlbXNcIikpIHx8IEFycmF5LmlzQXJyYXkob3duVmFsdWUobm9kZSwgXCJwcmVmaXhJdGVtc1wiKSkpXG4gICkge1xuICAgIHJldHVybiBub3JtYWxpemVUdXBsZShub2RlLCBwYXRoLCBwcm92aWRlcik7XG4gIH1cblxuICBjb25zdCByZXN1bHQgPSB7IC4uLm5vZGUgfTtcbiAgY29uc3QgaXRlbXMgPSBvd25WYWx1ZShub2RlLCBcIml0ZW1zXCIpIGFzIEpzb25TY2hlbWEgfCBKc29uU2NoZW1hW10gfCB1bmRlZmluZWQ7XG5cbiAgaWYgKEFycmF5LmlzQXJyYXkoaXRlbXMpKSB7XG4gICAgcmVzdWx0Lml0ZW1zID0gaXRlbXMubWFwKChzY2hlbWEsIGluZGV4KSA9PlxuICAgICAgc3RyaWN0aWZ5Tm9kZShzY2hlbWEsIGAke3BhdGh9Lml0ZW1zWyR7aW5kZXh9XWAsIHByb3ZpZGVyKSxcbiAgICApO1xuICB9IGVsc2UgaWYgKGl0ZW1zICE9PSB1bmRlZmluZWQpIHtcbiAgICByZXN1bHQuaXRlbXMgPSBzdHJpY3RpZnlOb2RlKGl0ZW1zLCBgJHtwYXRofS5pdGVtc2AsIHByb3ZpZGVyKTtcbiAgfVxuXG4gIGNvbnN0IHByZWZpeEl0ZW1zID0gb3duVmFsdWUobm9kZSwgXCJwcmVmaXhJdGVtc1wiKSBhcyBKc29uU2NoZW1hW10gfCB1bmRlZmluZWQ7XG4gIGlmIChBcnJheS5pc0FycmF5KHByZWZpeEl0ZW1zKSkge1xuICAgIHJlc3VsdC5wcmVmaXhJdGVtcyA9IHByZWZpeEl0ZW1zLm1hcCgoc2NoZW1hLCBpbmRleCkgPT5cbiAgICAgIHN0cmljdGlmeU5vZGUoc2NoZW1hLCBgJHtwYXRofS5wcmVmaXhJdGVtc1ske2luZGV4fV1gLCBwcm92aWRlciksXG4gICAgKTtcbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZVR1cGxlKFxuICBub2RlOiBKc29uU2NoZW1hLFxuICBwYXRoOiBzdHJpbmcsXG4gIHByb3ZpZGVyOiBcIm9wZW5haVwiIHwgXCJhbnRocm9waWNcIixcbik6IEpzb25TY2hlbWEge1xuICBjb25zdCBpdGVtcyA9IG93blZhbHVlKG5vZGUsIFwiaXRlbXNcIik7XG4gIGNvbnN0IHByZWZpeEl0ZW1zID0gb3duVmFsdWUobm9kZSwgXCJwcmVmaXhJdGVtc1wiKTtcbiAgY29uc3QgbGVnYWN5VHVwbGUgPSBBcnJheS5pc0FycmF5KGl0ZW1zKTtcbiAgY29uc3QgcHJlZml4VHVwbGUgPSBBcnJheS5pc0FycmF5KHByZWZpeEl0ZW1zKTtcbiAgaWYgKGxlZ2FjeVR1cGxlICYmIHByZWZpeFR1cGxlKSB7XG4gICAgdGhyb3cgbmV3IFN0cmljdGlmaWVyRXJyb3IoXCJpdGVtcyBhbmQgcHJlZml4SXRlbXMgdHVwbGUgZm9ybXMgY2Fubm90IGJlIGNvbWJpbmVkXCIsIHBhdGgpO1xuICB9XG4gIGlmIChwcmVmaXhUdXBsZSAmJiBPYmplY3QuaGFzT3duKG5vZGUsIFwiYWRkaXRpb25hbEl0ZW1zXCIpKSB7XG4gICAgdGhyb3cgbmV3IFN0cmljdGlmaWVyRXJyb3IoXCJhZGRpdGlvbmFsSXRlbXMgY2Fubm90IGJlIGNvbWJpbmVkIHdpdGggcHJlZml4SXRlbXNcIiwgcGF0aCk7XG4gIH1cblxuICBjb25zdCByYXdUdXBsZSA9IChsZWdhY3lUdXBsZSA/IGl0ZW1zIDogcHJlZml4SXRlbXMpIGFzIHVua25vd25bXTtcbiAgY29uc3QgdHVwbGVQYXRoID0gbGVnYWN5VHVwbGUgPyBgJHtwYXRofS5pdGVtc2AgOiBgJHtwYXRofS5wcmVmaXhJdGVtc2A7XG4gIGNvbnN0IHR1cGxlID0gcmF3VHVwbGUubWFwKChzY2hlbWEsIGluZGV4KSA9PiB7XG4gICAgaWYgKCFpc1NjaGVtYU9iamVjdChzY2hlbWEpKSB7XG4gICAgICB0aHJvdyBuZXcgU3RyaWN0aWZpZXJFcnJvcihcbiAgICAgICAgXCJib29sZWFuIGFuZCBub24tb2JqZWN0IHR1cGxlIG1lbWJlciBzY2hlbWFzIGFyZSBub3Qgc3VwcG9ydGVkXCIsXG4gICAgICAgIGAke3R1cGxlUGF0aH1bJHtpbmRleH1dYCxcbiAgICAgICk7XG4gICAgfVxuICAgIGNvbnN0IG1lbWJlclBhdGggPSBgJHt0dXBsZVBhdGh9WyR7aW5kZXh9XWA7XG4gICAgY29uc3QgbWVtYmVyID0gc3RyaWN0aWZ5Tm9kZShzY2hlbWEsIG1lbWJlclBhdGgsIHByb3ZpZGVyKTtcbiAgICBpZiAoIWhhc1Byb3ZpZGVyU2NoZW1hRW50cnlQb2ludChtZW1iZXIpKSB7XG4gICAgICB0aHJvdyBuZXcgU3RyaWN0aWZpZXJFcnJvcihcbiAgICAgICAgXCJ0dXBsZSBtZW1iZXIgbXVzdCBkZWZpbmUgYSBwcm92aWRlci1yZXByZXNlbnRhYmxlIHNjaGVtYVwiLFxuICAgICAgICBtZW1iZXJQYXRoLFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIG1lbWJlcjtcbiAgfSk7XG5cbiAgY29uc3QgcmF3VGFpbCA9IGxlZ2FjeVR1cGxlID8gb3duVmFsdWUobm9kZSwgXCJhZGRpdGlvbmFsSXRlbXNcIikgOiBpdGVtcztcbiAgaWYgKHJhd1RhaWwgPT09IHRydWUpIHtcbiAgICB0aHJvdyBuZXcgU3RyaWN0aWZpZXJFcnJvcihcImFuIHVucmVzdHJpY3RlZCB0dXBsZSByZXN0IGlzIG5vdCBzdXBwb3J0ZWRcIiwgcGF0aCk7XG4gIH1cbiAgaWYgKHJhd1RhaWwgIT09IHVuZGVmaW5lZCAmJiByYXdUYWlsICE9PSBmYWxzZSAmJiAhaXNTY2hlbWFPYmplY3QocmF3VGFpbCkpIHtcbiAgICB0aHJvdyBuZXcgU3RyaWN0aWZpZXJFcnJvcihcInR1cGxlIHJlc3QgbXVzdCBiZSBhbiBvYmplY3Qgc2NoZW1hIG9yIGZhbHNlXCIsIHBhdGgpO1xuICB9XG5cbiAgY29uc3QgdGFpbCA9IGlzU2NoZW1hT2JqZWN0KHJhd1RhaWwpXG4gICAgPyBzdHJpY3RpZnlOb2RlKHJhd1RhaWwsIGxlZ2FjeVR1cGxlID8gYCR7cGF0aH0uYWRkaXRpb25hbEl0ZW1zYCA6IGAke3BhdGh9Lml0ZW1zYCwgcHJvdmlkZXIpXG4gICAgOiB1bmRlZmluZWQ7XG4gIGlmICh0YWlsICE9PSB1bmRlZmluZWQgJiYgIWhhc1Byb3ZpZGVyU2NoZW1hRW50cnlQb2ludCh0YWlsKSkge1xuICAgIHRocm93IG5ldyBTdHJpY3RpZmllckVycm9yKFwiYW4gdW5yZXN0cmljdGVkIHR1cGxlIHJlc3QgaXMgbm90IHN1cHBvcnRlZFwiLCBwYXRoKTtcbiAgfVxuICBjb25zdCB0YWlsTW9kZSA9IHRhaWwgIT09IHVuZGVmaW5lZCA/IFwidHlwZWRcIiA6IHJhd1RhaWwgPT09IGZhbHNlID8gXCJjbG9zZWRcIiA6IFwiaW1wbGljaXRcIjtcbiAgY29uc3QgYm91bmRzID0gbm9ybWFsaXplVHVwbGVCb3VuZHMobm9kZSwgdHVwbGUubGVuZ3RoLCB0YWlsTW9kZSwgcGF0aCk7XG4gIGNvbnN0IGJhc2UgPSBvbWl0S2V5cyhub2RlLCBbXCJpdGVtc1wiLCBcInByZWZpeEl0ZW1zXCIsIFwiYWRkaXRpb25hbEl0ZW1zXCIsIFwibWluSXRlbXNcIiwgXCJtYXhJdGVtc1wiXSk7XG5cbiAgLy8gQW50aHJvcGljIOydgCBhc3NlcnROb3JtYWxpemF0aW9uQ29tcGF0aWJpbGl0eSDqsIAg67mE7Ja0IOyeiOyngCDslYrsnYAgdHVwbGUg7J2EIOydtOuvuCDqsbDrtoDtlojsnLzrr4DroZxcbiAgLy8g7Jes6riwIOuPhOuLrO2VmOuKlCB0dXBsZSDsnYAg67mIIHR1cGxlIOu/kOydtOqzoCwg6re4IOqyveyasCBwcmVmaXhJdGVtcyBzcHJlYWQg64qUIOyekOyXsO2eiCDsg53rnrXrkJzri6Qg4oCUXG4gIC8vIHByb3ZpZGVyIOu2hOq4sCDsl4bsnbQg7ZWcIO2Yle2DnOuhnCDrkZAgcHJvdmlkZXIg66qo65GQ66W8IO2RnO2YhO2VnOuLpC5cbiAgcmV0dXJuIHtcbiAgICAuLi5iYXNlLFxuICAgIC4uLih0dXBsZS5sZW5ndGggPiAwID8geyBwcmVmaXhJdGVtczogdHVwbGUgfSA6IHt9KSxcbiAgICBpdGVtczogdGFpbCA/PyBVTlJFQUNIQUJMRV9UVVBMRV9UQUlMX1NDSEVNQSxcbiAgICAuLi5ib3VuZHMsXG4gIH07XG59XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZVR1cGxlQm91bmRzKFxuICBub2RlOiBKc29uU2NoZW1hLFxuICB0dXBsZUxlbmd0aDogbnVtYmVyLFxuICB0YWlsTW9kZTogXCJ0eXBlZFwiIHwgXCJjbG9zZWRcIiB8IFwiaW1wbGljaXRcIixcbiAgcGF0aDogc3RyaW5nLFxuKTogeyBtaW5JdGVtczogbnVtYmVyOyBtYXhJdGVtcz86IG51bWJlciB9IHtcbiAgY29uc3QgY2FsbGVyTWluSXRlbXMgPSBpbnRlZ2VyQm91bmQob3duVmFsdWUobm9kZSwgXCJtaW5JdGVtc1wiKSwgXCJtaW5JdGVtc1wiLCBwYXRoKTtcbiAgY29uc3QgY2FsbGVyTWF4SXRlbXMgPSBpbnRlZ2VyQm91bmQob3duVmFsdWUobm9kZSwgXCJtYXhJdGVtc1wiKSwgXCJtYXhJdGVtc1wiLCBwYXRoKTtcbiAgaWYgKHRhaWxNb2RlID09PSBcImltcGxpY2l0XCIgJiYgY2FsbGVyTWF4SXRlbXMgIT09IHVuZGVmaW5lZCAmJiBjYWxsZXJNYXhJdGVtcyA+IHR1cGxlTGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IFN0cmljdGlmaWVyRXJyb3IoXG4gICAgICBcImltcGxpY2l0IHR1cGxlIHJlc3QgY2Fubm90IGJlIHJlcHJlc2VudGVkIHdoZW4gbWF4SXRlbXMgZXhjZWVkcyB0aGUgdHVwbGUgbGVuZ3RoXCIsXG4gICAgICBwYXRoLFxuICAgICk7XG4gIH1cblxuICBjb25zdCBtaW5JdGVtcyA9IGNhbGxlck1pbkl0ZW1zID8/IChjYWxsZXJNYXhJdGVtcyA9PT0gdW5kZWZpbmVkID8gdHVwbGVMZW5ndGggOiAwKTtcbiAgY29uc3QgbWF4SXRlbXMgPVxuICAgIHRhaWxNb2RlID09PSBcInR5cGVkXCIgPyBjYWxsZXJNYXhJdGVtcyA6IE1hdGgubWluKGNhbGxlck1heEl0ZW1zID8/IHR1cGxlTGVuZ3RoLCB0dXBsZUxlbmd0aCk7XG5cbiAgaWYgKG1heEl0ZW1zICE9PSB1bmRlZmluZWQgJiYgbWluSXRlbXMgPiBtYXhJdGVtcykge1xuICAgIHRocm93IG5ldyBTdHJpY3RpZmllckVycm9yKFwidHVwbGUgbWluSXRlbXMgY2Fubm90IGV4Y2VlZCBtYXhJdGVtc1wiLCBwYXRoKTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgbWluSXRlbXMsXG4gICAgLi4uKG1heEl0ZW1zICE9PSB1bmRlZmluZWQgPyB7IG1heEl0ZW1zIH0gOiB7fSksXG4gIH07XG59XG5cbmZ1bmN0aW9uIGludGVnZXJCb3VuZCh2YWx1ZTogdW5rbm93biwga2V5d29yZDogc3RyaW5nLCBwYXRoOiBzdHJpbmcpOiBudW1iZXIgfCB1bmRlZmluZWQge1xuICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgaWYgKCFOdW1iZXIuaXNTYWZlSW50ZWdlcih2YWx1ZSkgfHwgKHZhbHVlIGFzIG51bWJlcikgPCAwKSB7XG4gICAgdGhyb3cgbmV3IFN0cmljdGlmaWVyRXJyb3IoYCR7a2V5d29yZH0gbXVzdCBiZSBhIG5vbi1uZWdhdGl2ZSBzYWZlIGludGVnZXJgLCBwYXRoKTtcbiAgfVxuICByZXR1cm4gdmFsdWUgYXMgbnVtYmVyO1xufVxuXG5mdW5jdGlvbiBpc1NjaGVtYU9iamVjdCh2YWx1ZTogdW5rbm93bik6IHZhbHVlIGlzIEpzb25TY2hlbWEge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSBcIm9iamVjdFwiICYmIHZhbHVlICE9PSBudWxsICYmICFBcnJheS5pc0FycmF5KHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gb3duVmFsdWUoc2NoZW1hOiBKc29uU2NoZW1hLCBrZXl3b3JkOiBzdHJpbmcpOiB1bmtub3duIHtcbiAgcmV0dXJuIE9iamVjdC5oYXNPd24oc2NoZW1hLCBrZXl3b3JkKSA/IHNjaGVtYVtrZXl3b3JkXSA6IHVuZGVmaW5lZDtcbn1cblxuY29uc3QgUFJPVklERVJfU0NIRU1BX0VOVFJZX1BPSU5UX0tFWVdPUkRTID0gbmV3IFNldChbXG4gIFwidHlwZVwiLFxuICBcIiRyZWZcIixcbiAgXCJwcm9wZXJ0aWVzXCIsXG4gIFwiYW55T2ZcIixcbiAgXCJvbmVPZlwiLFxuICBcImFsbE9mXCIsXG5dKTtcblxuZnVuY3Rpb24gaGFzUHJvdmlkZXJTY2hlbWFFbnRyeVBvaW50KHNjaGVtYTogSnNvblNjaGVtYSk6IGJvb2xlYW4ge1xuICByZXR1cm4gT2JqZWN0LmtleXMoc2NoZW1hKS5zb21lKChrZXkpID0+IFBST1ZJREVSX1NDSEVNQV9FTlRSWV9QT0lOVF9LRVlXT1JEUy5oYXMoa2V5KSk7XG59XG5cbmZ1bmN0aW9uIG9taXRLZXlzKG5vZGU6IEpzb25TY2hlbWEsIGtleXM6IHJlYWRvbmx5IHN0cmluZ1tdKTogSnNvblNjaGVtYSB7XG4gIGNvbnN0IG9taXR0ZWQgPSBuZXcgU2V0KGtleXMpO1xuICByZXR1cm4gT2JqZWN0LmZyb21FbnRyaWVzKE9iamVjdC5lbnRyaWVzKG5vZGUpLmZpbHRlcigoW2tleV0pID0+ICFvbWl0dGVkLmhhcyhrZXkpKSk7XG59XG5cbmZ1bmN0aW9uIG1ha2VOdWxsYWJsZShzY2hlbWE6IEpzb25TY2hlbWEpOiBKc29uU2NoZW1hIHtcbiAgaWYgKG93blZhbHVlKHNjaGVtYSwgXCJ0eXBlXCIpID09PSBcIm51bGxcIikgcmV0dXJuIHNjaGVtYTtcblxuICBjb25zdCBhbnlPZiA9IG93blZhbHVlKHNjaGVtYSwgXCJhbnlPZlwiKTtcbiAgaWYgKGFueU9mKSB7XG4gICAgY29uc3QgdmFyaWFudHMgPSBhbnlPZiBhcyBKc29uU2NoZW1hW107XG4gICAgY29uc3QgaGFzTnVsbCA9IHZhcmlhbnRzLnNvbWUoKHYpID0+IG93blZhbHVlKHYsIFwidHlwZVwiKSA9PT0gXCJudWxsXCIpO1xuICAgIGlmIChoYXNOdWxsKSByZXR1cm4gc2NoZW1hO1xuICAgIHJldHVybiB7IGFueU9mOiBbLi4udmFyaWFudHMsIHsgdHlwZTogXCJudWxsXCIgfV0gfTtcbiAgfVxuXG4gIGNvbnN0IG9uZU9mID0gb3duVmFsdWUoc2NoZW1hLCBcIm9uZU9mXCIpO1xuICBpZiAob25lT2YpIHtcbiAgICBjb25zdCB2YXJpYW50cyA9IG9uZU9mIGFzIEpzb25TY2hlbWFbXTtcbiAgICBjb25zdCBoYXNOdWxsID0gdmFyaWFudHMuc29tZSgodikgPT4gb3duVmFsdWUodiwgXCJ0eXBlXCIpID09PSBcIm51bGxcIik7XG4gICAgaWYgKGhhc051bGwpIHJldHVybiBzY2hlbWE7XG4gICAgcmV0dXJuIHsgb25lT2Y6IFsuLi52YXJpYW50cywgeyB0eXBlOiBcIm51bGxcIiB9XSB9O1xuICB9XG5cbiAgcmV0dXJuIHsgYW55T2Y6IFtzY2hlbWEsIHsgdHlwZTogXCJudWxsXCIgfV0gfTtcbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7QUF1QkEsSUFBYSxtQkFBYixjQUFzQyxNQUFNO0NBR2pDO0NBRlQs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