@cartanova/qgrid-cli 2.3.6 → 2.3.8

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/bundle/dist/application/qgrid/qgrid-image-generation.js +42 -0
  2. package/bundle/dist/application/qgrid/qgrid-response-format.js +44 -0
  3. package/bundle/dist/application/qgrid/qgrid-run-lifecycle.js +23 -4
  4. package/bundle/dist/application/qgrid/qgrid.dispatcher.js +15 -6
  5. package/bundle/dist/application/qgrid/qgrid.frame.js +52 -17
  6. package/bundle/dist/application/qgrid/qgrid.types.js +36 -12
  7. package/bundle/dist/application/qgrid/tool-emulation.js +16 -8
  8. package/bundle/dist/application/request-log/request-log.model.js +5 -2
  9. package/bundle/dist/application/sonamu.generated.js +13 -4
  10. package/bundle/dist/application/sonamu.generated.sso.js +9 -3
  11. package/bundle/dist/i18n/sd.generated.js +4 -1
  12. package/bundle/dist/migrations/20260705140614_alter_request_logs_add1_alter1.js +16 -0
  13. package/bundle/dist/migrations/20260705140615_alter_request_log_steps_alter1.js +14 -0
  14. package/bundle/dist/migrations/20260706120000_alter_request_logs_add_image_cost.js +17 -0
  15. package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +2 -1
  16. package/bundle/dist/utils/providers/openai/codex-rpc.js +1 -1
  17. package/bundle/dist/utils/providers/openai/codex-worker.js +78 -6
  18. package/bundle/dist/utils/providers/openai/openai-dispatcher.js +21 -4
  19. package/bundle/src/application/qgrid/qgrid-image-generation.ts +62 -0
  20. package/bundle/src/application/qgrid/qgrid-response-format.ts +59 -0
  21. package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +105 -0
  22. package/bundle/src/application/qgrid/qgrid-run-lifecycle.ts +34 -2
  23. package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +33 -0
  24. package/bundle/src/application/qgrid/qgrid.dispatcher.ts +16 -5
  25. package/bundle/src/application/qgrid/qgrid.frame.test.ts +123 -1
  26. package/bundle/src/application/qgrid/qgrid.frame.ts +52 -5
  27. package/bundle/src/application/qgrid/qgrid.types.ts +22 -0
  28. package/bundle/src/application/qgrid/tool-emulation.test.ts +44 -1
  29. package/bundle/src/application/qgrid/tool-emulation.ts +27 -4
  30. package/bundle/src/application/request-log/request-log.entity.json +73 -47
  31. package/bundle/src/application/request-log/request-log.model.ts +7 -0
  32. package/bundle/src/application/sonamu.generated.http +16 -3
  33. package/bundle/src/application/sonamu.generated.sso.ts +6 -0
  34. package/bundle/src/application/sonamu.generated.ts +12 -0
  35. package/bundle/src/i18n/sd.generated.ts +3 -0
  36. package/bundle/src/migrations/20260705140614_alter_request_logs_add1_alter1.ts +15 -0
  37. package/bundle/src/migrations/20260705140615_alter_request_log_steps_alter1.ts +13 -0
  38. package/bundle/src/migrations/20260706120000_alter_request_logs_add_image_cost.ts +14 -0
  39. package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +5 -0
  40. package/bundle/src/utils/providers/common/provider-dispatcher.ts +14 -0
  41. package/bundle/src/utils/providers/openai/codex-rpc.ts +2 -0
  42. package/bundle/src/utils/providers/openai/codex-worker.test.ts +219 -0
  43. package/bundle/src/utils/providers/openai/codex-worker.ts +154 -5
  44. package/bundle/src/utils/providers/openai/openai-dispatcher.test.ts +95 -1
  45. package/bundle/src/utils/providers/openai/openai-dispatcher.ts +42 -0
  46. package/bundle/web-dist/client/assets/index-OQd6CclQ.js +78 -0
  47. package/bundle/web-dist/client/assets/index-VE_24EJf.css +1 -0
  48. package/bundle/web-dist/client/assets/{logs-B0pWpDrg.js → logs-8T91eoLY.js} +1 -1
  49. package/bundle/web-dist/client/assets/{routes-7XhVuG7o.js → routes--GqHRT2A.js} +1 -1
  50. package/bundle/web-dist/client/assets/{sd.generated-DXhjjL2f.js → sd.generated-BrUnRt0B.js} +1 -1
  51. package/bundle/web-dist/client/assets/{services.generated-B7u0U1wC.js → services.generated-AsEvHbJ7.js} +1 -1
  52. package/bundle/web-dist/client/assets/{show-CcjZ9nr7.js → show-cHMucIDC.js} +3 -3
  53. package/bundle/web-dist/client/assets/{tokens-DlwAm0v4.js → tokens-BXAJUeCJ.js} +1 -1
  54. package/bundle/web-dist/client/index.html +3 -3
  55. package/bundle/web-dist/server/assets/{lazyRouteComponent-B0LkbiYf.js → lazyRouteComponent-BswulcOx.js} +1 -1
  56. package/bundle/web-dist/server/assets/{logs-dLx6gMXT.js → logs-B_ZLzpwY.js} +4 -4
  57. package/bundle/web-dist/server/assets/{routes-DD3Hb9xO.js → routes-D9OiKoqa.js} +2 -2
  58. package/bundle/web-dist/server/assets/{sd.generated-DdfpD_iN.js → sd.generated-DRuQSIKo.js} +3 -0
  59. package/bundle/web-dist/server/assets/{services.generated-D3ZCvIkt.js → services.generated-Dp0uKgpV.js} +1 -1
  60. package/bundle/web-dist/server/assets/{show-BQjeyv6A.js → show-CGlX9OYt.js} +104 -13
  61. package/bundle/web-dist/server/assets/{tokens-CSOsBpP7.js → tokens-Cjw6cQxZ.js} +2 -2
  62. package/bundle/web-dist/server/entry-server.generated.js +9 -8
  63. package/package.json +1 -1
  64. package/bundle/web-dist/client/assets/index-5WdFEqZT.css +0 -1
  65. package/bundle/web-dist/client/assets/index-jnUY7nJ-.js +0 -78
@@ -15,6 +15,13 @@ import { getLogger } from "@logtape/logtape";
15
15
  * - backpressure: 큐 full 또는 timeout 시 SERVER_BUSY
16
16
  */
17
17
  const logger = getLogger(["qgrid", "openai-dispatcher"]);
18
+ var ImageGenerationError = class extends Error {
19
+ constructor(kind, message) {
20
+ super(message);
21
+ this.kind = kind;
22
+ this.name = "ImageGenerationError";
23
+ }
24
+ };
18
25
  const DEFAULT_EFFORT = "low";
19
26
  const WORKERS_PER_TOKEN = Math.min(Number(process.env.QGRID_WORKERS_PER_TOKEN ?? 3), 5);
20
27
  const QUEUE_TIMEOUT_MS = 6e4;
@@ -142,6 +149,7 @@ var OpenAIDispatcher = class OpenAIDispatcher {
142
149
  }, excludedTokenIds);
143
150
  }
144
151
  async generateStream(req, cb) {
152
+ if (req.imageGeneration) throw new ImageGenerationError("gate", "image generation is not supported on the streaming path");
145
153
  const excludedTokenIds = /* @__PURE__ */ new Set();
146
154
  const reuseWorker = await this.acquireReuseWorker(req, excludedTokenIds);
147
155
  if (reuseWorker) {
@@ -159,6 +167,7 @@ var OpenAIDispatcher = class OpenAIDispatcher {
159
167
  }, excludedTokenIds);
160
168
  }
161
169
  async acquireReuseWorker(req, excludedTokenIds = /* @__PURE__ */ new Set()) {
170
+ if (req.imageGeneration) return null;
162
171
  if (!THREAD_REUSE_ENABLED || !req.reuse) return null;
163
172
  const { workerId, threadId, epoch } = req.reuse;
164
173
  const worker = this.findWorkerById(workerId);
@@ -302,12 +311,19 @@ var OpenAIDispatcher = class OpenAIDispatcher {
302
311
  model: req.model,
303
312
  verbosity: req.verbosity,
304
313
  reasoningSummary: req.reasoningSummary,
305
- serviceTier: req.serviceTier
314
+ serviceTier: req.serviceTier,
315
+ imageGeneration: req.imageGeneration,
316
+ imageGenerationOptions: req.imageGenerationOptions
306
317
  };
307
318
  }
308
319
  async executeTurn(worker, req, reuseThreadId) {
320
+ if (req.imageGeneration) {
321
+ const reason = await worker.checkImageGenerationSupport(req.model);
322
+ if (reason) throw new ImageGenerationError("gate", reason);
323
+ }
309
324
  const turnReq = this.buildTurnRequest(req, reuseThreadId);
310
325
  const result = await worker.executeTurn(turnReq, reuseThreadId);
326
+ if (req.imageGeneration && (!result.images || result.images.length === 0)) throw result.imageAttempted ? new ImageGenerationError("incomplete", "image tool ran but produced no completed image") : new ImageGenerationError("not_called", "model did not call the image_generation tool");
311
327
  return {
312
328
  text: result.text,
313
329
  tokenName: worker.tokenName,
@@ -319,7 +335,8 @@ var OpenAIDispatcher = class OpenAIDispatcher {
319
335
  workerId: makeWorkerId(worker.tokenId, worker.workerIndex),
320
336
  threadId: result.threadId,
321
337
  epoch: worker.epoch
322
- }
338
+ },
339
+ images: result.images
323
340
  };
324
341
  }
325
342
  async executeStreamTurn(worker, req, cb, reuseThreadId) {
@@ -579,6 +596,6 @@ var OpenAIDispatcher = class OpenAIDispatcher {
579
596
  }
580
597
  };
581
598
  //#endregion
582
- export { OpenAIDispatcher };
599
+ export { ImageGenerationError, OpenAIDispatcher };
583
600
 
584
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlbmFpLWRpc3BhdGNoZXIuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3Byb3ZpZGVycy9vcGVuYWkvb3BlbmFpLWRpc3BhdGNoZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBPcGVuQUlEaXNwYXRjaGVyIOKAlCBjb2RleCBhcHAtc2VydmVyIHdvcmtlciBwb29sICsg7Yag7YGwIOudvOyasO2MhS5cbiAqXG4gKiAtIO2GoO2BsOuLuSBOIHdvcmtlciAoQ29kZXhBcHBTZXJ2ZXJXb3JrZXIpLCDquLDrs7ggM1xuICogLSBpZGxlIHdvcmtlciByb3VuZC1yb2JpbiDshKDtg50gKyDtgZAg64yA6riwICjsoITrtoAgYnVzeSDsi5wpXG4gKiAtIFRva2VuU3Vic2NyaWJlciDsnbTrsqTtirjroZwgd29ya2VyIHBvb2wg64+Z6riw7ZmUXG4gKiAtIGJhY2twcmVzc3VyZTog7YGQIGZ1bGwg65iQ64qUIHRpbWVvdXQg7IucIFNFUlZFUl9CVVNZXG4gKi9cbmltcG9ydCB7IGdldExvZ2dlciB9IGZyb20gXCJAbG9ndGFwZS9sb2d0YXBlXCI7XG5cbmltcG9ydCB7IFF1b3RhVGhyZXNob2xkRXhjZWVkZWRFcnJvciB9IGZyb20gXCIuLi8uLi8uLi9hcHBsaWNhdGlvbi9xZ3JpZC9xZ3JpZC50eXBlc1wiO1xuaW1wb3J0IHsgVG9rZW5Nb2RlbCB9IGZyb20gXCIuLi8uLi8uLi9hcHBsaWNhdGlvbi90b2tlbi90b2tlbi5tb2RlbFwiO1xuaW1wb3J0IHsgdHlwZSBPcGVuQUlDcmVkZW50aWFscyB9IGZyb20gXCIuLi8uLi8uLi9hcHBsaWNhdGlvbi90b2tlbi90b2tlbi50eXBlc1wiO1xuaW1wb3J0IHsgdHlwZSBHZXRBY2NvdW50UmF0ZUxpbWl0c1Jlc3BvbnNlIH0gZnJvbSBcIi4uLy4uLy4uL2NvZGV4LXByb3RvY29sL3YyL0dldEFjY291bnRSYXRlTGltaXRzUmVzcG9uc2VcIjtcbmltcG9ydCB7XG4gIHR5cGUgR2VuZXJhdGVSZXF1ZXN0LFxuICB0eXBlIEdlbmVyYXRlUmVzdWx0LFxuICB0eXBlIEdlbmVyYXRlU3RyZWFtQ2FsbGJhY2tzLFxuICB0eXBlIFByb3ZpZGVyRGlzcGF0Y2hlcixcbn0gZnJvbSBcIi4uL2NvbW1vbi9wcm92aWRlci1kaXNwYXRjaGVyXCI7XG5pbXBvcnQgeyBDb2RleEFwcFNlcnZlcldvcmtlciwgdHlwZSBTdHJlYW1DYWxsYmFja3MsIHR5cGUgVHVyblJlcXVlc3QgfSBmcm9tIFwiLi9jb2RleC13b3JrZXJcIjtcbmltcG9ydCB7XG4gIHJlYWRPcGVuQUlRdW90YVVzYWdlLFxuICB0eXBlIE9wZW5BSVF1b3RhVXNhZ2VSZXN1bHQsXG4gIHR5cGUgT3BlbkFJUmF0ZUxpbWl0c1dpdGhNZXRhLFxufSBmcm9tIFwiLi9vcGVuYWktcXVvdGFcIjtcbmltcG9ydCB7IGhhbmRsZUNoYXRncHRBdXRoVG9rZW5zUmVmcmVzaCB9IGZyb20gXCIuL29wZW5haS1yZWZyZXNoXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGdldExvZ2dlcihbXCJxZ3JpZFwiLCBcIm9wZW5haS1kaXNwYXRjaGVyXCJdKTtcblxuY29uc3QgREVGQVVMVF9FRkZPUlQgPSBcImxvd1wiO1xuY29uc3QgTUFYX1dPUktFUlNfUEVSX1RPS0VOID0gNTtcbmNvbnN0IFdPUktFUlNfUEVSX1RPS0VOID0gTWF0aC5taW4oXG4gIE51bWJlcihwcm9jZXNzLmVudi5RR1JJRF9XT1JLRVJTX1BFUl9UT0tFTiA/PyAzKSxcbiAgTUFYX1dPUktFUlNfUEVSX1RPS0VOLFxuKTtcbmNvbnN0IFFVRVVFX1RJTUVPVVRfTVMgPSA2MF8wMDA7XG5jb25zdCBNQVhfUVVFVUVfU0laRSA9IDUwO1xuY29uc3QgU1BBV05fSU5URVJWQUxfTVMgPSA1MDA7XG5cbi8vIHRocmVhZCDsnqzsgqzsmqkocHJvbXB0IGNhY2hlIOqzoOyglSkuIOuBhOuptCDquLDsobQgXCLrp6QgdHVybiDsg4ggdGhyZWFkICsgaGlzdG9yeSBpbmplY3RcIiDrj5nsnpEuXG5jb25zdCBUSFJFQURfUkVVU0VfRU5BQkxFRCA9IHByb2Nlc3MuZW52LlFHUklEX09QRU5BSV9USFJFQURfUkVVU0UgIT09IFwiZmFsc2VcIjtcbi8vIOyijO2RnCB3b3JrZXIg6rCAIGJ1c3kg7J28IOuVjCBmcmVlIOulvCDquLDri6TrpqzripQg7LWc64yAIOyLnOqwhC4g7LSI6rO8IOyLnCDsg4ggdGhyZWFkIOuhnCDtj7TrsLEuXG5jb25zdCBSRVVTRV9XT1JLRVJfV0FJVF9NUyA9IDVfMDAwO1xuY29uc3QgUkVVU0VfV09SS0VSX1BPTExfTVMgPSA1MDtcblxuLy8gd29ya2VySWQg7ZWp7ISxOiB0b2tlbklkIOyZgCB3b3JrZXJJbmRleCgwLi40KSDrpbwg7ZWY64KY7J2YIOyViOyglSDsiKvsnpDroZwg7J247L2U65SpLlxuZnVuY3Rpb24gbWFrZVdvcmtlcklkKHRva2VuSWQ6IG51bWJlciwgd29ya2VySW5kZXg6IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiB0b2tlbklkICogMTAgKyB3b3JrZXJJbmRleDtcbn1cblxuZnVuY3Rpb24gc2xlZXAobXM6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgbXMpKTtcbn1cblxuZnVuY3Rpb24gcXVvdGFUaHJlc2hvbGRFeGNlZWRlZE1lc3NhZ2UoXG4gIHByb3ZpZGVyOiBzdHJpbmcsXG4gIHRva2VuczogQXJyYXk8eyB0b2tlbk5hbWU6IHN0cmluZzsgdGhyZXNob2xkOiBudW1iZXIgfT4sXG4pOiBzdHJpbmcge1xuICBjb25zdCBkZXRhaWxzID0gdG9rZW5zXG4gICAgLm1hcCgodG9rZW4pID0+IGAke3Rva2VuLnRva2VuTmFtZX0gKHRocmVzaG9sZCAke3Rva2VuLnRocmVzaG9sZH0lKWApXG4gICAgLmpvaW4oXCIsIFwiKTtcbiAgcmV0dXJuIGRldGFpbHMubGVuZ3RoID4gMFxuICAgID8gYEFsbCAke3Byb3ZpZGVyfSB0b2tlbnMgZXhjZWVkZWQgcXVvdGEgdGhyZXNob2xkOiAke2RldGFpbHN9YFxuICAgIDogYEFsbCAke3Byb3ZpZGVyfSB0b2tlbnMgZXhjZWVkZWQgcXVvdGEgdGhyZXNob2xkYDtcbn1cblxudHlwZSBRdWV1ZUl0ZW0gPSB7XG4gIHJlc29sdmU6ICh3b3JrZXI6IENvZGV4QXBwU2VydmVyV29ya2VyKSA9PiB2b2lkO1xuICByZWplY3Q6IChlcnJvcjogRXJyb3IpID0+IHZvaWQ7XG4gIHRpbWVyOiBSZXR1cm5UeXBlPHR5cGVvZiBzZXRUaW1lb3V0PjtcbiAgYWJvcnRDbGVhbnVwPzogKCkgPT4gdm9pZDtcbiAgZXhjbHVkZWRUb2tlbklkczogU2V0PG51bWJlcj47XG59O1xuXG50eXBlIFRva2VuTWV0YWRhdGEgPSB7XG4gIG5hbWU6IHN0cmluZztcbiAgcXVvdGFUaHJlc2hvbGQ/OiBudW1iZXIgfCBudWxsO1xufTtcblxudHlwZSBUb2tlbkVsaWdpYmlsaXR5ID0ge1xuICByZWFkeUFjdGl2ZVRva2VuSWRzOiBTZXQ8bnVtYmVyPjtcbiAgZWxpZ2libGVUb2tlbklkczogU2V0PG51bWJlcj47XG4gIG92ZXJUaHJlc2hvbGRUb2tlbnM6IEFycmF5PHsgdG9rZW5OYW1lOiBzdHJpbmc7IHRocmVzaG9sZDogbnVtYmVyIH0+O1xuICB0aHJlc2hvbGRlZFRva2VuQ291bnQ6IG51bWJlcjtcbn07XG5cbmV4cG9ydCBjbGFzcyBPcGVuQUlEaXNwYXRjaGVyIGltcGxlbWVudHMgUHJvdmlkZXJEaXNwYXRjaGVyIHtcbiAgd29ya2VyUG9vbCA9IG5ldyBNYXA8bnVtYmVyLCBDb2RleEFwcFNlcnZlcldvcmtlcltdPigpO1xuICB0b2tlbk1ldGFkYXRhID0gbmV3IE1hcDxudW1iZXIsIFRva2VuTWV0YWRhdGE+KCk7XG4gIHJyQ3Vyc29yID0gMDtcbiAgcXVldWU6IFF1ZXVlSXRlbVtdID0gW107XG4gIHByaXZhdGUgZHJhaW5pbmcgPSBmYWxzZTtcbiAgcHJpdmF0ZSBkcmFpbkFnYWluID0gZmFsc2U7XG5cbiAgYXN5bmMgc3RhcnQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgeyByb3dzIH0gPSBhd2FpdCBUb2tlbk1vZGVsLmZpbmRNYW55KFwiQVwiKTtcbiAgICBjb25zdCBvcGVuYWlUb2tlbnMgPSByb3dzLmZpbHRlcigodCkgPT4gdC5wcm92aWRlciA9PT0gXCJvcGVuYWlcIik7XG4gICAgbG9nZ2VyLmluZm8oXG4gICAgICBgc3RhcnRpbmcgJHtvcGVuYWlUb2tlbnMubGVuZ3RofSBvcGVuYWkgdG9rZW5zICgke1dPUktFUlNfUEVSX1RPS0VOfSB3b3JrZXJzIGVhY2gpYCxcbiAgICApO1xuXG4gICAgYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKFxuICAgICAgb3BlbmFpVG9rZW5zLm1hcChhc3luYyAodCkgPT4ge1xuICAgICAgICBhd2FpdCB0aGlzLnNwYXduV29ya2VycyhcbiAgICAgICAgICB0LmlkLFxuICAgICAgICAgIHQubmFtZSxcbiAgICAgICAgICB0LmNyZWRlbnRpYWxzIGFzIE9wZW5BSUNyZWRlbnRpYWxzLFxuICAgICAgICAgIHQucXVvdGFfdGhyZXNob2xkLFxuICAgICAgICApO1xuICAgICAgICBpZiAoIXQuYWN0aXZlKSB0aGlzLm9uVG9rZW5EZWFjdGl2YXRlZCh0LmlkKTtcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cblxuICBhc3luYyBzdG9wKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMucmVqZWN0QWxsUXVldWVkKFwiRElTUEFUQ0hFUl9TSFVURE9XTlwiKTtcbiAgICBjb25zdCBraWxscyA9IFsuLi50aGlzLndvcmtlclBvb2wudmFsdWVzKCldLmZsYXQoKS5tYXAoKHcpID0+IHcua2lsbCgpKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQoa2lsbHMpO1xuICAgIHRoaXMud29ya2VyUG9vbC5jbGVhcigpO1xuICAgIHRoaXMudG9rZW5NZXRhZGF0YS5jbGVhcigpO1xuICAgIHRoaXMucmF0ZUxpbWl0c0NhY2hlLmNsZWFyKCk7XG4gIH1cblxuICAvLyDilIDilIAgVG9rZW4gZXZlbnRzIChmcm9tIFRva2VuU3Vic2NyaWJlcikg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgYXN5bmMgb25Ub2tlbkFkZGVkKFxuICAgIGlkOiBudW1iZXIsXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIGNyZWRlbnRpYWxzOiBPcGVuQUlDcmVkZW50aWFscyxcbiAgICBxdW90YVRocmVzaG9sZD86IG51bWJlciB8IG51bGwsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuc2V0VG9rZW5NZXRhZGF0YShpZCwgbmFtZSwgcXVvdGFUaHJlc2hvbGQpO1xuICAgIGlmICh0aGlzLndvcmtlclBvb2wuaGFzKGlkKSkgcmV0dXJuO1xuICAgIGF3YWl0IHRoaXMuc3Bhd25Xb3JrZXJzKGlkLCBuYW1lLCBjcmVkZW50aWFscywgcXVvdGFUaHJlc2hvbGQpO1xuICB9XG5cbiAgYXN5bmMgb25Ub2tlblJlbW92ZWQoaWQ6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHdvcmtlcnMgPSB0aGlzLndvcmtlclBvb2wuZ2V0KGlkKSA/PyBbXTtcbiAgICBjb25zdCB0b2tlbk5hbWUgPSB3b3JrZXJzWzBdPy50b2tlbk5hbWU7XG4gICAgdGhpcy53b3JrZXJQb29sLmRlbGV0ZShpZCk7XG4gICAgdGhpcy50b2tlbk1ldGFkYXRhLmRlbGV0ZShpZCk7XG4gICAgdGhpcy5yYXRlTGltaXRzQ2FjaGUuZGVsZXRlKGlkKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQod29ya2Vycy5tYXAoKHcpID0+IHcua2lsbCgpKSk7XG4gICAgaWYgKHRoaXMuZ2V0QWxsUmVhZHlBY3RpdmVXb3JrZXJzKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aGlzLnJlamVjdEFsbFF1ZXVlZChcIk5PX09QRU5BSV9XT1JLRVJTXCIpO1xuICAgIH1cbiAgICBpZiAod29ya2Vycy5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCBsYWJlbCA9IHRva2VuTmFtZSA/PyBgdG9rZW4gJHtpZH1gO1xuICAgICAgbG9nZ2VyLmluZm8oYHdvcmtlcnMgcmVtb3ZlZDogJHtsYWJlbH0gKCR7d29ya2Vycy5sZW5ndGh9KWApO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIG9uVG9rZW5VcGRhdGVkKFxuICAgIGlkOiBudW1iZXIsXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIGNyZWRlbnRpYWxzOiBPcGVuQUlDcmVkZW50aWFscyxcbiAgICBxdW90YVRocmVzaG9sZD86IG51bWJlciB8IG51bGwsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGV4aXN0aW5nID0gdGhpcy53b3JrZXJQb29sLmdldChpZCkgPz8gW107XG4gICAgY29uc3QgcmVuYW1lZCA9IGV4aXN0aW5nLnNvbWUoKHcpID0+IHcudG9rZW5OYW1lICE9PSBuYW1lKTtcbiAgICB0aGlzLnNldFRva2VuTWV0YWRhdGEoaWQsIG5hbWUsIHF1b3RhVGhyZXNob2xkKTtcbiAgICBpZiAocmVuYW1lZCkgdGhpcy5yYXRlTGltaXRzQ2FjaGUuZGVsZXRlKGlkKTtcblxuICAgIGlmIChleGlzdGluZy5sZW5ndGggPT09IDApIHtcbiAgICAgIGF3YWl0IHRoaXMuc3Bhd25Xb3JrZXJzKGlkLCBuYW1lLCBjcmVkZW50aWFscywgcXVvdGFUaHJlc2hvbGQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChleGlzdGluZy5ldmVyeSgodykgPT4gdy5jYW5SZXVzZUZvclRva2VuKG5hbWUsIGNyZWRlbnRpYWxzKSkpIHtcbiAgICAgIGV4aXN0aW5nLmZvckVhY2goKHcpID0+IHcudXBkYXRlVG9rZW5TdGF0ZShuYW1lLCBjcmVkZW50aWFscykpO1xuICAgICAgbG9nZ2VyLmluZm8oYHdvcmtlcnMgdXBkYXRlZCBpbi1wbGFjZTogJHtuYW1lfWApO1xuICAgICAgdGhpcy5yZXF1ZXN0RHJhaW5RdWV1ZSgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMud29ya2VyUG9vbC5kZWxldGUoaWQpO1xuICAgIHRoaXMucmF0ZUxpbWl0c0NhY2hlLmRlbGV0ZShpZCk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKGV4aXN0aW5nLm1hcCgodykgPT4gdy5raWxsKCkpKTtcbiAgICBhd2FpdCB0aGlzLnNwYXduV29ya2VycyhpZCwgbmFtZSwgY3JlZGVudGlhbHMsIHF1b3RhVGhyZXNob2xkKTtcbiAgfVxuXG4gIG9uVG9rZW5EZWFjdGl2YXRlZChpZDogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3Qgd29ya2VycyA9IHRoaXMud29ya2VyUG9vbC5nZXQoaWQpID8/IFtdO1xuICAgIGNvbnN0IHRva2VuTmFtZSA9IHdvcmtlcnNbMF0/LnRva2VuTmFtZTtcbiAgICB3b3JrZXJzLmZvckVhY2goKHcpID0+IHtcbiAgICAgIHcuYWN0aXZlID0gZmFsc2U7XG4gICAgfSk7XG4gICAgaWYgKHRoaXMuZ2V0QWxsUmVhZHlBY3RpdmVXb3JrZXJzKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aGlzLnJlamVjdEFsbFF1ZXVlZChcIk5PX0FDVElWRV9XT1JLRVJTXCIpO1xuICAgIH1cbiAgICBjb25zdCBsYWJlbCA9IHRva2VuTmFtZSA/PyBgdG9rZW4gJHtpZH1gO1xuICAgIGxvZ2dlci5pbmZvKGB3b3JrZXJzIGRlYWN0aXZhdGVkOiAke2xhYmVsfWApO1xuICB9XG5cbiAgb25Ub2tlbkFjdGl2YXRlZChpZDogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3Qgd29ya2VycyA9IHRoaXMud29ya2VyUG9vbC5nZXQoaWQpID8/IFtdO1xuICAgIGNvbnN0IHRva2VuTmFtZSA9IHdvcmtlcnNbMF0/LnRva2VuTmFtZTtcbiAgICB3b3JrZXJzLmZvckVhY2goKHcpID0+IHtcbiAgICAgIHcuYWN0aXZlID0gdHJ1ZTtcbiAgICB9KTtcbiAgICB0aGlzLnJlcXVlc3REcmFpblF1ZXVlKCk7XG4gICAgY29uc3QgbGFiZWwgPSB0b2tlbk5hbWUgPz8gYHRva2VuICR7aWR9YDtcbiAgICBsb2dnZXIuaW5mbyhgd29ya2VycyBhY3RpdmF0ZWQ6ICR7bGFiZWx9YCk7XG4gIH1cblxuICBhc3luYyByZXBsYWNlVG9rZW5zKFxuICAgIHJvd3M6IEFycmF5PHtcbiAgICAgIGlkOiBudW1iZXI7XG4gICAgICBuYW1lOiBzdHJpbmc7XG4gICAgICBjcmVkZW50aWFsczogT3BlbkFJQ3JlZGVudGlhbHM7XG4gICAgICBxdW90YVRocmVzaG9sZD86IG51bWJlciB8IG51bGw7XG4gICAgfT4sXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IG5leHQgPSBuZXcgU2V0KHJvd3MubWFwKChyKSA9PiByLmlkKSk7XG4gICAgZm9yIChjb25zdCBpZCBvZiBBcnJheS5mcm9tKHRoaXMud29ya2VyUG9vbC5rZXlzKCkpKSB7XG4gICAgICBpZiAoIW5leHQuaGFzKGlkKSkgYXdhaXQgdGhpcy5vblRva2VuUmVtb3ZlZChpZCk7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCByb3cgb2Ygcm93cykge1xuICAgICAgaWYgKHRoaXMud29ya2VyUG9vbC5oYXMocm93LmlkKSkge1xuICAgICAgICBhd2FpdCB0aGlzLm9uVG9rZW5VcGRhdGVkKHJvdy5pZCwgcm93Lm5hbWUsIHJvdy5jcmVkZW50aWFscywgcm93LnF1b3RhVGhyZXNob2xkKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGF3YWl0IHRoaXMub25Ub2tlbkFkZGVkKHJvdy5pZCwgcm93Lm5hbWUsIHJvdy5jcmVkZW50aWFscywgcm93LnF1b3RhVGhyZXNob2xkKTtcbiAgICAgIH1cbiAgICAgIHRoaXMub25Ub2tlbkFjdGl2YXRlZChyb3cuaWQpO1xuICAgIH1cbiAgfVxuXG4gIC8vIOKUgOKUgCBHZW5lcmF0ZSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBhc3luYyBnZW5lcmF0ZShyZXE6IEdlbmVyYXRlUmVxdWVzdCk6IFByb21pc2U8R2VuZXJhdGVSZXN1bHQ+IHtcbiAgICBjb25zdCBleGNsdWRlZFRva2VuSWRzID0gbmV3IFNldDxudW1iZXI+KCk7XG4gICAgLy8gdGhyZWFkIOyerOyCrOyaqSDqsr3roZw6IOyijO2RnCB3b3JrZXIg66W8IOygkOycoO2VtCDquLDsobQgdGhyZWFkIOyXkCB0dXJuIOunjCDsi6TtlokuXG4gICAgY29uc3QgcmV1c2VXb3JrZXIgPSBhd2FpdCB0aGlzLmFjcXVpcmVSZXVzZVdvcmtlcihyZXEsIGV4Y2x1ZGVkVG9rZW5JZHMpO1xuICAgIGlmIChyZXVzZVdvcmtlcikge1xuICAgICAgbG9nZ2VyLmluZm8oXG4gICAgICAgIGDihrsgJHtyZXVzZVdvcmtlci50b2tlbk5hbWV9WyR7cmV1c2VXb3JrZXIudG9rZW5JZH1dIChyZXVzZSB0aHJlYWQsICR7cmVxLm1vZGVsfSlgLFxuICAgICAgKTtcbiAgICAgIHJldHVybiB0aGlzLmV4ZWN1dGVBbmRSZWxlYXNlKHJldXNlV29ya2VyLCAodykgPT5cbiAgICAgICAgdGhpcy5leGVjdXRlVHVybih3LCByZXEsIHJlcS5yZXVzZSEudGhyZWFkSWQpLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCB3b3JrZXIgPSBhd2FpdCB0aGlzLmFjcXVpcmVJZGxlV29ya2VyKGV4Y2x1ZGVkVG9rZW5JZHMpO1xuICAgIGlmICh3b3JrZXIpIHtcbiAgICAgIGxvZ2dlci5pbmZvKGDihpIgJHt3b3JrZXIudG9rZW5OYW1lfVske3dvcmtlci50b2tlbklkfV0gKG1vZGVsOiAke3JlcS5tb2RlbH0pYCk7XG4gICAgICByZXR1cm4gdGhpcy5leGVjdXRlQW5kUmVsZWFzZSh3b3JrZXIsICh3KSA9PiB0aGlzLmV4ZWN1dGVUdXJuKHcsIHJlcSkpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5lbnF1ZXVlKCh3KSA9PiB7XG4gICAgICBsb2dnZXIuaW5mbyhg4oaSICR7dy50b2tlbk5hbWV9WyR7dy50b2tlbklkfV0gKG1vZGVsOiAke3JlcS5tb2RlbH0sIHF1ZXVlZClgKTtcbiAgICAgIHJldHVybiB0aGlzLmV4ZWN1dGVUdXJuKHcsIHJlcSk7XG4gICAgfSwgZXhjbHVkZWRUb2tlbklkcyk7XG4gIH1cblxuICBhc3luYyBnZW5lcmF0ZVN0cmVhbShyZXE6IEdlbmVyYXRlUmVxdWVzdCwgY2I6IEdlbmVyYXRlU3RyZWFtQ2FsbGJhY2tzKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgZXhjbHVkZWRUb2tlbklkcyA9IG5ldyBTZXQ8bnVtYmVyPigpO1xuICAgIGNvbnN0IHJldXNlV29ya2VyID0gYXdhaXQgdGhpcy5hY3F1aXJlUmV1c2VXb3JrZXIocmVxLCBleGNsdWRlZFRva2VuSWRzKTtcbiAgICBpZiAocmV1c2VXb3JrZXIpIHtcbiAgICAgIGxvZ2dlci5pbmZvKGDihrsgJHtyZXVzZVdvcmtlci50b2tlbk5hbWV9WyR7cmV1c2VXb3JrZXIudG9rZW5JZH1dIChyZXVzZSB0aHJlYWQsIFtzdHJlYW1dKWApO1xuICAgICAgcmV0dXJuIHRoaXMuZXhlY3V0ZUFuZFJlbGVhc2UocmV1c2VXb3JrZXIsICh3KSA9PlxuICAgICAgICB0aGlzLmV4ZWN1dGVTdHJlYW1UdXJuKHcsIHJlcSwgY2IsIHJlcS5yZXVzZSEudGhyZWFkSWQpLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCB3b3JrZXIgPSBhd2FpdCB0aGlzLmFjcXVpcmVJZGxlV29ya2VyKGV4Y2x1ZGVkVG9rZW5JZHMpO1xuICAgIGlmICh3b3JrZXIpIHtcbiAgICAgIGxvZ2dlci5pbmZvKGDihpIgJHt3b3JrZXIudG9rZW5OYW1lfVske3dvcmtlci50b2tlbklkfV0gKG1vZGVsOiAke3JlcS5tb2RlbH0sIFtzdHJlYW1dKWApO1xuICAgICAgcmV0dXJuIHRoaXMuZXhlY3V0ZUFuZFJlbGVhc2Uod29ya2VyLCAodykgPT4gdGhpcy5leGVjdXRlU3RyZWFtVHVybih3LCByZXEsIGNiKSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmVucXVldWUoKHcpID0+IHtcbiAgICAgIGxvZ2dlci5pbmZvKGDihpIgJHt3LnRva2VuTmFtZX1bJHt3LnRva2VuSWR9XSAobW9kZWw6ICR7cmVxLm1vZGVsfSwgW3N0cmVhbV0sIHF1ZXVlZClgKTtcbiAgICAgIHJldHVybiB0aGlzLmV4ZWN1dGVTdHJlYW1UdXJuKHcsIHJlcSwgY2IpO1xuICAgIH0sIGV4Y2x1ZGVkVG9rZW5JZHMpO1xuICB9XG5cbiAgLy8gcmV1c2Ug7KKM7ZGc6rCAIOycoO2aqO2VmOuptCDqt7ggd29ya2VyIOulvCBidXN5IOygkOycoO2VtCDrsJjtmZguIOyXhuqxsOuCmCDtj7TrsLEg64yA7IOB7J2066m0IG51bGwuXG4gIC8vIO2PtOuwsSDsgqzsnKA6IOq4sOuKpSBvZmYgLyDsooztkZwg7JeG7J2MIC8gd29ya2VyIOu2gOyerMK37KO97J2MIC8gZXBvY2gg67aI7J287LmYKHJlc3RhcnQpIC8gdGhyZWFkIOyGjOupuCAvXG4gIC8vICAgICAgICAgICAgYnVzeSDrjIDquLAg7YOA7J6E7JWE7JuDLiBudWxsIOuwmO2ZmCDsi5wg7Zi47Lac67aA64qUIOyDiCB0aHJlYWQg6rK966Gc66GcIOynhO2WiS5cbiAgYXN5bmMgYWNxdWlyZVJldXNlV29ya2VyKFxuICAgIHJlcTogR2VuZXJhdGVSZXF1ZXN0LFxuICAgIGV4Y2x1ZGVkVG9rZW5JZHMgPSBuZXcgU2V0PG51bWJlcj4oKSxcbiAgKTogUHJvbWlzZTxDb2RleEFwcFNlcnZlcldvcmtlciB8IG51bGw+IHtcbiAgICBpZiAoIVRIUkVBRF9SRVVTRV9FTkFCTEVEIHx8ICFyZXEucmV1c2UpIHJldHVybiBudWxsO1xuICAgIGNvbnN0IHsgd29ya2VySWQsIHRocmVhZElkLCBlcG9jaCB9ID0gcmVxLnJldXNlO1xuXG4gICAgY29uc3Qgd29ya2VyID0gdGhpcy5maW5kV29ya2VyQnlJZCh3b3JrZXJJZCk7XG4gICAgaWYgKCF3b3JrZXIgfHwgIXdvcmtlci5pc1JlYWR5IHx8ICF3b3JrZXIuYWN0aXZlKSByZXR1cm4gbnVsbDtcbiAgICBpZiAod29ya2VyLmVwb2NoICE9PSBlcG9jaCkgcmV0dXJuIG51bGw7XG4gICAgaWYgKCF3b3JrZXIuaGFzVGhyZWFkKHRocmVhZElkKSkgcmV0dXJuIG51bGw7XG4gICAgaWYgKCEoYXdhaXQgdGhpcy5pc1Rva2VuUXVvdGFFbGlnaWJsZSh3b3JrZXIudG9rZW5JZCwgd29ya2VyLnRva2VuTmFtZSwgZXhjbHVkZWRUb2tlbklkcykpKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCBkZWFkbGluZSA9IERhdGUubm93KCkgKyBSRVVTRV9XT1JLRVJfV0FJVF9NUztcbiAgICBmb3IgKDs7KSB7XG4gICAgICAvLyByZXN0YXJ0KGVwb2NoIOuzgOqyvSkgLyB0aHJlYWQg7IaM66m47J20IOuMgOq4sCDspJHsl5Ag67Cc7IOd7ZWY66m0IO2PtOuwsS5cbiAgICAgIGlmICh3b3JrZXIuZXBvY2ggIT09IGVwb2NoIHx8ICF3b3JrZXIuaGFzVGhyZWFkKHRocmVhZElkKSkgcmV0dXJuIG51bGw7XG4gICAgICBpZiAod29ya2VyLnRyeUFjcXVpcmVUdXJuKCkpIHJldHVybiB3b3JrZXI7XG4gICAgICBpZiAoRGF0ZS5ub3coKSA+PSBkZWFkbGluZSkgcmV0dXJuIG51bGw7XG4gICAgICBhd2FpdCBzbGVlcChSRVVTRV9XT1JLRVJfUE9MTF9NUyk7XG4gICAgfVxuICB9XG5cbiAgZmluZFdvcmtlckJ5SWQod29ya2VySWQ6IG51bWJlcik6IENvZGV4QXBwU2VydmVyV29ya2VyIHwgbnVsbCB7XG4gICAgZm9yIChjb25zdCB3b3JrZXJzIG9mIHRoaXMud29ya2VyUG9vbC52YWx1ZXMoKSkge1xuICAgICAgZm9yIChjb25zdCB3IG9mIHdvcmtlcnMpIHtcbiAgICAgICAgaWYgKG1ha2VXb3JrZXJJZCh3LnRva2VuSWQsIHcud29ya2VySW5kZXgpID09PSB3b3JrZXJJZCkgcmV0dXJuIHc7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgYXN5bmMgaW50ZXJydXB0V29ya2VyVHVybih0aHJlYWRJZDogc3RyaW5nLCB0dXJuSWQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGFsbFdvcmtlcnMgPSBbLi4udGhpcy53b3JrZXJQb29sLnZhbHVlcygpXS5mbGF0KCkuZmlsdGVyKCh3KSA9PiB3LmlzUmVhZHkpO1xuICAgIGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChhbGxXb3JrZXJzLm1hcCgodykgPT4gdy5pbnRlcnJ1cHRUdXJuKHRocmVhZElkLCB0dXJuSWQpKSk7XG4gIH1cblxuICAvLyDilIDilIAgV29ya2VyIHNlbGVjdGlvbiDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbiAgLy8gIOq4sOuzuCByb3VuZC1yb2JpblxuICAvLyBUT0RPOiDstpTtm4Qg64uk66W4IOyVjOqzoOumrOymmOycvOuhnCDrs4Dqsr0g6rCA64ql7ZWY6rKMIOyngOybkFxuICBhc3luYyBhY3F1aXJlSWRsZVdvcmtlcihcbiAgICBleGNsdWRlZFRva2VuSWRzID0gbmV3IFNldDxudW1iZXI+KCksXG4gICk6IFByb21pc2U8Q29kZXhBcHBTZXJ2ZXJXb3JrZXIgfCBudWxsPiB7XG4gICAgY29uc3QgZWxpZ2liaWxpdHkgPSBhd2FpdCB0aGlzLnJlc29sdmVUb2tlbkVsaWdpYmlsaXR5KGV4Y2x1ZGVkVG9rZW5JZHMpO1xuICAgIGlmIChlbGlnaWJpbGl0eS5yZWFkeUFjdGl2ZVRva2VuSWRzLnNpemUgPT09IDApIHJldHVybiBudWxsO1xuICAgIGlmIChlbGlnaWJpbGl0eS5lbGlnaWJsZVRva2VuSWRzLnNpemUgPT09IDApIHRoaXMudGhyb3dRdW90YVRocmVzaG9sZEV4Y2VlZGVkKGVsaWdpYmlsaXR5KTtcblxuICAgIGNvbnN0IGFsbFdvcmtlcnMgPSB0aGlzLmdldEFsbFJlYWR5QWN0aXZlV29ya2VycygpLmZpbHRlcigodykgPT5cbiAgICAgIGVsaWdpYmlsaXR5LmVsaWdpYmxlVG9rZW5JZHMuaGFzKHcudG9rZW5JZCksXG4gICAgKTtcbiAgICBpZiAoYWxsV29ya2Vycy5sZW5ndGggPT09IDApIHJldHVybiBudWxsO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYWxsV29ya2Vycy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgdyA9IGFsbFdvcmtlcnNbKHRoaXMucnJDdXJzb3IgKyBpKSAlIGFsbFdvcmtlcnMubGVuZ3RoXSE7XG4gICAgICBpZiAody50cnlBY3F1aXJlVHVybigpKSB7XG4gICAgICAgIHRoaXMucnJDdXJzb3IgPSAodGhpcy5yckN1cnNvciArIGkgKyAxKSAlIGFsbFdvcmtlcnMubGVuZ3RoO1xuICAgICAgICByZXR1cm4gdztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBnZXRBbGxSZWFkeUFjdGl2ZVdvcmtlcnMoKTogQ29kZXhBcHBTZXJ2ZXJXb3JrZXJbXSB7XG4gICAgcmV0dXJuIFsuLi50aGlzLndvcmtlclBvb2wudmFsdWVzKCldLmZsYXQoKS5maWx0ZXIoKHcpID0+IHcuaXNSZWFkeSAmJiB3LmFjdGl2ZSk7XG4gIH1cblxuICAvLyDilIDilIAgUXVldWUg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgYXN5bmMgZW5xdWV1ZTxUPihcbiAgICBleGVjdXRlOiAod29ya2VyOiBDb2RleEFwcFNlcnZlcldvcmtlcikgPT4gUHJvbWlzZTxUPixcbiAgICBleGNsdWRlZFRva2VuSWRzID0gbmV3IFNldDxudW1iZXI+KCksXG4gICk6IFByb21pc2U8VD4ge1xuICAgIGNvbnN0IGVsaWdpYmlsaXR5ID0gYXdhaXQgdGhpcy5yZXNvbHZlVG9rZW5FbGlnaWJpbGl0eShleGNsdWRlZFRva2VuSWRzKTtcbiAgICBpZiAoZWxpZ2liaWxpdHkucmVhZHlBY3RpdmVUb2tlbklkcy5zaXplID09PSAwKSB0aHJvdyBuZXcgRXJyb3IoXCJOT19PUEVOQUlfV09SS0VSU1wiKTtcbiAgICBpZiAoZWxpZ2liaWxpdHkuZWxpZ2libGVUb2tlbklkcy5zaXplID09PSAwKSB0aGlzLnRocm93UXVvdGFUaHJlc2hvbGRFeGNlZWRlZChlbGlnaWJpbGl0eSk7XG4gICAgaWYgKHRoaXMucXVldWUubGVuZ3RoID49IE1BWF9RVUVVRV9TSVpFKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTRVJWRVJfQlVTWVwiKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2U8VD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgaXRlbTogUXVldWVJdGVtID0ge1xuICAgICAgICByZXNvbHZlOiAod29ya2VyKSA9PiB7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KGl0ZW0udGltZXIpO1xuICAgICAgICAgIGl0ZW0uYWJvcnRDbGVhbnVwPy4oKTtcbiAgICAgICAgICBQcm9taXNlLnJlc29sdmUoKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4gdGhpcy5leGVjdXRlQW5kUmVsZWFzZSh3b3JrZXIsIGV4ZWN1dGUpKVxuICAgICAgICAgICAgLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgICAgfSxcbiAgICAgICAgcmVqZWN0OiAoZXJyKSA9PiB7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KGl0ZW0udGltZXIpO1xuICAgICAgICAgIGl0ZW0uYWJvcnRDbGVhbnVwPy4oKTtcbiAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgfSxcbiAgICAgICAgdGltZXI6IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgIHRoaXMucmVtb3ZlRnJvbVF1ZXVlKGl0ZW0pO1xuICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoXCJTRVJWRVJfQlVTWVwiKSk7XG4gICAgICAgIH0sIFFVRVVFX1RJTUVPVVRfTVMpLFxuICAgICAgICBleGNsdWRlZFRva2VuSWRzOiBuZXcgU2V0KGV4Y2x1ZGVkVG9rZW5JZHMpLFxuICAgICAgfTtcblxuICAgICAgdGhpcy5xdWV1ZS5wdXNoKGl0ZW0pO1xuICAgIH0pO1xuICB9XG5cbiAgcmVtb3ZlRnJvbVF1ZXVlKGl0ZW06IFF1ZXVlSXRlbSk6IHZvaWQge1xuICAgIGNsZWFyVGltZW91dChpdGVtLnRpbWVyKTtcbiAgICBpdGVtLmFib3J0Q2xlYW51cD8uKCk7XG4gICAgY29uc3QgaWR4ID0gdGhpcy5xdWV1ZS5pbmRleE9mKGl0ZW0pO1xuICAgIGlmIChpZHggIT09IC0xKSB0aGlzLnF1ZXVlLnNwbGljZShpZHgsIDEpO1xuICB9XG5cbiAgcmVqZWN0QWxsUXVldWVkKHJlYXNvbjogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgZXJyID0gbmV3IEVycm9yKHJlYXNvbik7XG4gICAgdGhpcy5xdWV1ZS5mb3JFYWNoKChpdGVtKSA9PiB7XG4gICAgICBjbGVhclRpbWVvdXQoaXRlbS50aW1lcik7XG4gICAgICBpdGVtLmFib3J0Q2xlYW51cD8uKCk7XG4gICAgICBpdGVtLnJlamVjdChlcnIpO1xuICAgIH0pO1xuICAgIHRoaXMucXVldWUgPSBbXTtcbiAgfVxuXG4gIGFzeW5jIGRyYWluUXVldWUocmVsZWFzZWRXb3JrZXI/OiBDb2RleEFwcFNlcnZlcldvcmtlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLmRyYWluaW5nKSB7XG4gICAgICB0aGlzLmRyYWluQWdhaW4gPSB0cnVlO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuZHJhaW5pbmcgPSB0cnVlO1xuICAgIGxldCB3b3JrZXIgPSByZWxlYXNlZFdvcmtlcjtcbiAgICB0cnkge1xuICAgICAgZG8ge1xuICAgICAgICB0aGlzLmRyYWluQWdhaW4gPSBmYWxzZTtcbiAgICAgICAgYXdhaXQgdGhpcy5kcmFpblF1ZXVlT25jZSh3b3JrZXIpO1xuICAgICAgICB3b3JrZXIgPSB1bmRlZmluZWQ7XG4gICAgICB9IHdoaWxlICh0aGlzLmRyYWluQWdhaW4pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxvZ2dlci53YXJuKGBkcmFpblF1ZXVlIGZhaWxlZDogJHsoZSBhcyBFcnJvcikubWVzc2FnZX1gKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgdGhpcy5kcmFpbmluZyA9IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZHJhaW5RdWV1ZU9uY2UocmVsZWFzZWRXb3JrZXI/OiBDb2RleEFwcFNlcnZlcldvcmtlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmIChcbiAgICAgIHJlbGVhc2VkV29ya2VyICYmXG4gICAgICB0aGlzLnF1ZXVlLmxlbmd0aCA+IDAgJiZcbiAgICAgIHJlbGVhc2VkV29ya2VyLmlzUmVhZHkgJiZcbiAgICAgIHJlbGVhc2VkV29ya2VyLmFjdGl2ZSAmJlxuICAgICAgKGF3YWl0IHRoaXMuaXNXb3JrZXJFbGlnaWJsZUZvclF1ZXVlSXRlbShyZWxlYXNlZFdvcmtlciwgdGhpcy5xdWV1ZVswXSEpKSAmJlxuICAgICAgcmVsZWFzZWRXb3JrZXIudHJ5QWNxdWlyZVR1cm4oKVxuICAgICkge1xuICAgICAgY29uc3QgbmV4dCA9IHRoaXMucXVldWUuc2hpZnQoKSE7XG4gICAgICBuZXh0LnJlc29sdmUocmVsZWFzZWRXb3JrZXIpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHdoaWxlICh0aGlzLnF1ZXVlLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IG5leHQgPSB0aGlzLnF1ZXVlWzBdITtcbiAgICAgIGxldCB3b3JrZXI6IENvZGV4QXBwU2VydmVyV29ya2VyIHwgbnVsbDtcbiAgICAgIHRyeSB7XG4gICAgICAgIHdvcmtlciA9IGF3YWl0IHRoaXMuYWNxdWlyZUlkbGVXb3JrZXIobmV4dC5leGNsdWRlZFRva2VuSWRzKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiBRdW90YVRocmVzaG9sZEV4Y2VlZGVkRXJyb3IpIHtcbiAgICAgICAgICB0aGlzLnF1ZXVlLnNoaWZ0KCk7XG4gICAgICAgICAgbmV4dC5yZWplY3QoZSk7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICAgIGlmICghd29ya2VyKSBicmVhaztcbiAgICAgIHRoaXMucXVldWUuc2hpZnQoKTtcbiAgICAgIG5leHQucmVzb2x2ZSh3b3JrZXIpO1xuICAgIH1cbiAgfVxuXG4gIC8vIOKUgOKUgCBFeGVjdXRpb24g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgYXN5bmMgZXhlY3V0ZUFuZFJlbGVhc2U8VD4oXG4gICAgd29ya2VyOiBDb2RleEFwcFNlcnZlcldvcmtlcixcbiAgICBleGVjdXRlOiAod29ya2VyOiBDb2RleEFwcFNlcnZlcldvcmtlcikgPT4gUHJvbWlzZTxUPixcbiAgKTogUHJvbWlzZTxUPiB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBhd2FpdCBleGVjdXRlKHdvcmtlcik7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHdvcmtlci5yZWxlYXNlVHVybigpO1xuICAgICAgdGhpcy5yZXF1ZXN0RHJhaW5RdWV1ZSh3b3JrZXIpO1xuICAgIH1cbiAgfVxuXG4gIC8vIHJldXNlVGhyZWFkSWQg6rCAIOyeiOycvOuptCDquLDsobQgdGhyZWFkIOyXkCBkZWx0YShyZXVzZUlucHV0KeunjCwg7JeG7Jy866m0IOyDiCB0aHJlYWQg7JeQIOyghOyytFxuICAvLyBwcm9tcHQoY29sZElucHV0KSArIGhpc3RvcnkgaW5qZWN0LiByZXVzZSDqsIAgZGlzcGF0Y2hlciDri6jsl5DshJwg7Y+067Cx65CY66m0IO2bhOyekOuhnCDrlqjslrTsp4Tri6QuXG4gIHByaXZhdGUgYnVpbGRUdXJuUmVxdWVzdChyZXE6IEdlbmVyYXRlUmVxdWVzdCwgcmV1c2VUaHJlYWRJZD86IHN0cmluZyk6IFR1cm5SZXF1ZXN0IHtcbiAgICBjb25zdCByZXVzaW5nID0gcmV1c2VUaHJlYWRJZCAhPT0gdW5kZWZpbmVkO1xuICAgIHJldHVybiB7XG4gICAgICBpbnB1dDogcmV1c2luZyAmJiByZXEucmV1c2VJbnB1dCA/IHJlcS5yZXVzZUlucHV0IDogcmVxLmNvbGRJbnB1dCxcbiAgICAgIGhpc3Rvcnk6IHJldXNpbmcgPyB1bmRlZmluZWQgOiByZXEuY29sZEhpc3RvcnksXG4gICAgICBkZXZlbG9wZXJJbnN0cnVjdGlvbnM6IHJlcS5zeXN0ZW1Qcm9tcHQsXG4gICAgICBvdXRwdXRTY2hlbWE6IHJlcS5vdXRwdXRTY2hlbWEsXG4gICAgICBlZmZvcnQ6IHJlcS5lZmZvcnQgPz8gREVGQVVMVF9FRkZPUlQsXG4gICAgICBtb2RlbDogcmVxLm1vZGVsLFxuICAgICAgdmVyYm9zaXR5OiByZXEudmVyYm9zaXR5LFxuICAgICAgcmVhc29uaW5nU3VtbWFyeTogcmVxLnJlYXNvbmluZ1N1bW1hcnksXG4gICAgICBzZXJ2aWNlVGllcjogcmVxLnNlcnZpY2VUaWVyLFxuICAgIH07XG4gIH1cblxuICBhc3luYyBleGVjdXRlVHVybihcbiAgICB3b3JrZXI6IENvZGV4QXBwU2VydmVyV29ya2VyLFxuICAgIHJlcTogR2VuZXJhdGVSZXF1ZXN0LFxuICAgIHJldXNlVGhyZWFkSWQ/OiBzdHJpbmcsXG4gICk6IFByb21pc2U8R2VuZXJhdGVSZXN1bHQ+IHtcbiAgICBjb25zdCB0dXJuUmVxID0gdGhpcy5idWlsZFR1cm5SZXF1ZXN0KHJlcSwgcmV1c2VUaHJlYWRJZCk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgd29ya2VyLmV4ZWN1dGVUdXJuKHR1cm5SZXEsIHJldXNlVGhyZWFkSWQpO1xuICAgIHJldHVybiB7XG4gICAgICB0ZXh0OiByZXN1bHQudGV4dCxcbiAgICAgIHRva2VuTmFtZTogd29ya2VyLnRva2VuTmFtZSxcbiAgICAgIHVzYWdlOiByZXN1bHQudXNhZ2UsXG4gICAgICBkdXJhdGlvbk1zOiByZXN1bHQuZHVyYXRpb25NcyxcbiAgICAgIHR0ZnRNczogcmVzdWx0LnR0ZnRNcyxcbiAgICAgIG1vZGVsOiByZXN1bHQubW9kZWwsXG4gICAgICB0aHJlYWRDb29yZDoge1xuICAgICAgICB3b3JrZXJJZDogbWFrZVdvcmtlcklkKHdvcmtlci50b2tlbklkLCB3b3JrZXIud29ya2VySW5kZXgpLFxuICAgICAgICB0aHJlYWRJZDogcmVzdWx0LnRocmVhZElkLFxuICAgICAgICBlcG9jaDogd29ya2VyLmVwb2NoLFxuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgYXN5bmMgZXhlY3V0ZVN0cmVhbVR1cm4oXG4gICAgd29ya2VyOiBDb2RleEFwcFNlcnZlcldvcmtlcixcbiAgICByZXE6IEdlbmVyYXRlUmVxdWVzdCxcbiAgICBjYjogR2VuZXJhdGVTdHJlYW1DYWxsYmFja3MsXG4gICAgcmV1c2VUaHJlYWRJZD86IHN0cmluZyxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgdHVyblJlcSA9IHRoaXMuYnVpbGRUdXJuUmVxdWVzdChyZXEsIHJldXNlVGhyZWFkSWQpO1xuICAgIC8vIHdvcmtlciDsnZggVHVyblJlc3VsdCDsl5AgdG9rZW5OYW1lL3RocmVhZENvb3JkIOulvCDrtpnsl6wg7IOB7JyEKEdlbmVyYXRlUmVzdWx0KeuhnCDsmKzrprDri6QuXG4gICAgLy8gdGhyZWFkSWQg64qUIOyDiCB0aHJlYWQg66m0IG9uVGhyZWFkSWQg66GcIO2ZleygleuQmOuvgOuhnCDrr7jrpqwg67O06rSA7ZW0IOuRkOqzoCBvbkNvbXBsZXRlIOuVjCDsnb3ripTri6QuXG4gICAgbGV0IHJlc29sdmVkVGhyZWFkSWQgPSByZXVzZVRocmVhZElkID8/IFwiXCI7XG4gICAgY29uc3Qgd3JhcHBlZENiOiBTdHJlYW1DYWxsYmFja3MgPSB7XG4gICAgICAuLi5jYixcbiAgICAgIG9uVGhyZWFkSWQ6ICh0aHJlYWRJZCkgPT4ge1xuICAgICAgICByZXNvbHZlZFRocmVhZElkID0gdGhyZWFkSWQ7XG4gICAgICAgIGNiLm9uVGhyZWFkSWQ/Lih0aHJlYWRJZCk7XG4gICAgICB9LFxuICAgICAgb25Db21wbGV0ZTogKHJlc3VsdCkgPT4ge1xuICAgICAgICBjYi5vbkNvbXBsZXRlKHtcbiAgICAgICAgICAuLi5yZXN1bHQsXG4gICAgICAgICAgdG9rZW5OYW1lOiB3b3JrZXIudG9rZW5OYW1lLFxuICAgICAgICAgIHRocmVhZENvb3JkOiB7XG4gICAgICAgICAgICB3b3JrZXJJZDogbWFrZVdvcmtlcklkKHdvcmtlci50b2tlbklkLCB3b3JrZXIud29ya2VySW5kZXgpLFxuICAgICAgICAgICAgdGhyZWFkSWQ6IHJlc29sdmVkVGhyZWFkSWQsXG4gICAgICAgICAgICBlcG9jaDogd29ya2VyLmVwb2NoLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgfSxcbiAgICB9O1xuICAgIGF3YWl0IHdvcmtlci5leGVjdXRlVHVyblN0cmVhbSh0dXJuUmVxLCB3cmFwcGVkQ2IsIHJldXNlVGhyZWFkSWQpO1xuICB9XG5cbiAgLy8g4pSA4pSAIFNwYXduIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIGFzeW5jIHNwYXduV29ya2VycyhcbiAgICB0b2tlbklkOiBudW1iZXIsXG4gICAgdG9rZW5OYW1lOiBzdHJpbmcsXG4gICAgY3JlZGVudGlhbHM6IE9wZW5BSUNyZWRlbnRpYWxzLFxuICAgIHF1b3RhVGhyZXNob2xkPzogbnVtYmVyIHwgbnVsbCxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5zZXRUb2tlbk1ldGFkYXRhKHRva2VuSWQsIHRva2VuTmFtZSwgcXVvdGFUaHJlc2hvbGQpO1xuICAgIGNvbnN0IHdvcmtlcnM6IENvZGV4QXBwU2VydmVyV29ya2VyW10gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IFdPUktFUlNfUEVSX1RPS0VOOyBpKyspIHtcbiAgICAgIGlmIChpID4gMCkgYXdhaXQgc2xlZXAoU1BBV05fSU5URVJWQUxfTVMpO1xuICAgICAgY29uc3Qgd29ya2VyID0gYXdhaXQgdGhpcy5zcGF3blNpbmdsZVdvcmtlcih0b2tlbklkLCB0b2tlbk5hbWUsIGNyZWRlbnRpYWxzLCBpKTtcbiAgICAgIGlmICh3b3JrZXIpIHdvcmtlcnMucHVzaCh3b3JrZXIpO1xuICAgIH1cbiAgICBpZiAod29ya2Vycy5sZW5ndGggPiAwKSB0aGlzLndvcmtlclBvb2wuc2V0KHRva2VuSWQsIHdvcmtlcnMpO1xuICB9XG5cbiAgYXN5bmMgc3Bhd25TaW5nbGVXb3JrZXIoXG4gICAgdG9rZW5JZDogbnVtYmVyLFxuICAgIHRva2VuTmFtZTogc3RyaW5nLFxuICAgIGNyZWRlbnRpYWxzOiBPcGVuQUlDcmVkZW50aWFscyxcbiAgICB3b3JrZXJJbmRleDogbnVtYmVyLFxuICApOiBQcm9taXNlPENvZGV4QXBwU2VydmVyV29ya2VyIHwgbnVsbD4ge1xuICAgIGNvbnN0IHdvcmtlciA9IG5ldyBDb2RleEFwcFNlcnZlcldvcmtlcih7XG4gICAgICB0b2tlbklkLFxuICAgICAgdG9rZW5OYW1lLFxuICAgICAgYWNjZXNzVG9rZW46IGNyZWRlbnRpYWxzLmFjY2Vzc1Rva2VuLFxuICAgICAgYWNjb3VudElkOiBjcmVkZW50aWFscy5hY2NvdW50SWQsXG4gICAgICBwbGFuVHlwZTogY3JlZGVudGlhbHMucGxhblR5cGUsXG4gICAgICB3b3JrZXJJbmRleCxcbiAgICB9KTtcblxuICAgIHdvcmtlci5vblJlYWR5ID0gKCkgPT4gdGhpcy5yZXF1ZXN0RHJhaW5RdWV1ZSgpO1xuXG4gICAgd29ya2VyLnNldFNlcnZlclJlcXVlc3RIYW5kbGVyKGFzeW5jIChtZXRob2QpID0+IHtcbiAgICAgIGlmIChtZXRob2QgPT09IFwiYWNjb3VudC9jaGF0Z3B0QXV0aFRva2Vucy9yZWZyZXNoXCIpIHtcbiAgICAgICAgcmV0dXJuIGhhbmRsZUNoYXRncHRBdXRoVG9rZW5zUmVmcmVzaCh0b2tlbklkKTtcbiAgICAgIH1cbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5oYW5kbGVkIHNlcnZlci1yZXF1ZXN0OiAke21ldGhvZH1gKTtcbiAgICB9KTtcblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCB3b3JrZXIuaW5pdGlhbGl6ZSgpO1xuICAgICAgbG9nZ2VyLmluZm8oYHdvcmtlciBzcGF3bmVkOiAke3Rva2VuTmFtZX1bJHt3b3JrZXJJbmRleH1dYCk7XG4gICAgICByZXR1cm4gd29ya2VyO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxvZ2dlci53YXJuKGB3b3JrZXIgc3Bhd24gZmFpbGVkOiAke3Rva2VuTmFtZX1bJHt3b3JrZXJJbmRleH1dOiAkeyhlIGFzIEVycm9yKS5tZXNzYWdlfWApO1xuICAgICAgYXdhaXQgd29ya2VyLmtpbGwoKS5jYXRjaCgoKSA9PiB7fSk7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cblxuICAvLyDilIDilIAgUmF0ZSBsaW1pdHMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgcmF0ZUxpbWl0c0NhY2hlID0gbmV3IE1hcDxudW1iZXIsIHsgZGF0YTogR2V0QWNjb3VudFJhdGVMaW1pdHNSZXNwb25zZTsgY2FjaGVkQXQ6IG51bWJlciB9PigpO1xuICBzdGF0aWMgcmVhZG9ubHkgUkFURV9MSU1JVFNfQ0FDSEVfVFRMID0gNjBfMDAwO1xuXG4gIGFzeW5jIGdldFJhdGVMaW1pdHNCeVRva2VuSWQodG9rZW5JZDogbnVtYmVyKTogUHJvbWlzZTxPcGVuQUlSYXRlTGltaXRzV2l0aE1ldGE+IHtcbiAgICBjb25zdCBjYWNoZWQgPSB0aGlzLnJhdGVMaW1pdHNDYWNoZS5nZXQodG9rZW5JZCk7XG4gICAgaWYgKGNhY2hlZCAmJiBEYXRlLm5vdygpIC0gY2FjaGVkLmNhY2hlZEF0IDwgT3BlbkFJRGlzcGF0Y2hlci5SQVRFX0xJTUlUU19DQUNIRV9UVEwpIHtcbiAgICAgIHJldHVybiBjYWNoZWQ7XG4gICAgfVxuXG4gICAgY29uc3Qgd29ya2VyID0gKHRoaXMud29ya2VyUG9vbC5nZXQodG9rZW5JZCkgPz8gW10pLmZpbmQoKHcpID0+IHcuaXNSZWFkeSk7XG4gICAgaWYgKCF3b3JrZXIpIHRocm93IG5ldyBFcnJvcihcIm5vIHJlYWR5IG9wZW5haSB3b3JrZXJzXCIpO1xuICAgIGNvbnN0IGRhdGEgPSAoYXdhaXQgd29ya2VyLmdldFJhdGVMaW1pdHMoKSkgYXMgR2V0QWNjb3VudFJhdGVMaW1pdHNSZXNwb25zZTtcbiAgICBjb25zdCBlbnRyeSA9IHsgZGF0YSwgY2FjaGVkQXQ6IERhdGUubm93KCkgfTtcbiAgICB0aGlzLnJhdGVMaW1pdHNDYWNoZS5zZXQodG9rZW5JZCwgZW50cnkpO1xuICAgIHJldHVybiBlbnRyeTtcbiAgfVxuXG4gIHByaXZhdGUgcmVxdWVzdERyYWluUXVldWUocmVsZWFzZWRXb3JrZXI/OiBDb2RleEFwcFNlcnZlcldvcmtlcik6IHZvaWQge1xuICAgIHZvaWQgdGhpcy5kcmFpblF1ZXVlKHJlbGVhc2VkV29ya2VyKS5jYXRjaCgoZSkgPT5cbiAgICAgIGxvZ2dlci53YXJuKGBkcmFpblF1ZXVlIGZhaWxlZDogJHsoZSBhcyBFcnJvcikubWVzc2FnZX1gKSxcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBzZXRUb2tlbk1ldGFkYXRhKGlkOiBudW1iZXIsIG5hbWU6IHN0cmluZywgcXVvdGFUaHJlc2hvbGQ/OiBudW1iZXIgfCBudWxsKTogdm9pZCB7XG4gICAgdGhpcy50b2tlbk1ldGFkYXRhLnNldChpZCwgeyBuYW1lLCBxdW90YVRocmVzaG9sZCB9KTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0UXVvdGFUaHJlc2hvbGQodG9rZW5JZDogbnVtYmVyKTogbnVtYmVyIHwgbnVsbCB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMudG9rZW5NZXRhZGF0YS5nZXQodG9rZW5JZCk/LnF1b3RhVGhyZXNob2xkO1xuICB9XG5cbiAgcHJpdmF0ZSBoYXNRdW90YVRocmVzaG9sZCh0b2tlbklkOiBudW1iZXIpOiBib29sZWFuIHtcbiAgICBjb25zdCB0aHJlc2hvbGQgPSB0aGlzLmdldFF1b3RhVGhyZXNob2xkKHRva2VuSWQpO1xuICAgIHJldHVybiB0aHJlc2hvbGQgIT09IHVuZGVmaW5lZCAmJiB0aHJlc2hvbGQgIT09IG51bGw7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlc29sdmVUb2tlbkVsaWdpYmlsaXR5KGV4Y2x1ZGVkVG9rZW5JZHM6IFNldDxudW1iZXI+KTogUHJvbWlzZTxUb2tlbkVsaWdpYmlsaXR5PiB7XG4gICAgY29uc3Qgd29ya2VycyA9IHRoaXMuZ2V0QWxsUmVhZHlBY3RpdmVXb3JrZXJzKCk7XG4gICAgY29uc3QgYnlUb2tlbiA9IG5ldyBNYXA8bnVtYmVyLCBzdHJpbmc+KCk7XG4gICAgZm9yIChjb25zdCB3b3JrZXIgb2Ygd29ya2Vycykge1xuICAgICAgaWYgKCFieVRva2VuLmhhcyh3b3JrZXIudG9rZW5JZCkpIGJ5VG9rZW4uc2V0KHdvcmtlci50b2tlbklkLCB3b3JrZXIudG9rZW5OYW1lKTtcbiAgICB9XG5cbiAgICBjb25zdCByZWFkeUFjdGl2ZVRva2VuSWRzID0gbmV3IFNldChieVRva2VuLmtleXMoKSk7XG4gICAgY29uc3QgZWxpZ2libGVUb2tlbklkcyA9IG5ldyBTZXQ8bnVtYmVyPigpO1xuICAgIGNvbnN0IG92ZXJUaHJlc2hvbGRUb2tlbnM6IEFycmF5PHsgdG9rZW5OYW1lOiBzdHJpbmc7IHRocmVzaG9sZDogbnVtYmVyIH0+ID0gW107XG4gICAgbGV0IHRocmVzaG9sZGVkVG9rZW5Db3VudCA9IDA7XG5cbiAgICBjb25zdCBlbnRyaWVzID0gQXJyYXkuZnJvbShieVRva2VuLmVudHJpZXMoKSk7XG4gICAgY29uc3QgY2hlY2tzID0gYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKFxuICAgICAgZW50cmllcy5tYXAoYXN5bmMgKFt0b2tlbklkLCB0b2tlbk5hbWVdKSA9PiB7XG4gICAgICAgIGlmIChleGNsdWRlZFRva2VuSWRzLmhhcyh0b2tlbklkKSkge1xuICAgICAgICAgIHRocmVzaG9sZGVkVG9rZW5Db3VudCsrO1xuICAgICAgICAgIHJldHVybiB7IHRva2VuSWQsIHRva2VuTmFtZSwgZWxpZ2libGU6IGZhbHNlIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLmhhc1F1b3RhVGhyZXNob2xkKHRva2VuSWQpKSB7XG4gICAgICAgICAgcmV0dXJuIHsgdG9rZW5JZCwgdG9rZW5OYW1lLCBlbGlnaWJsZTogdHJ1ZSB9O1xuICAgICAgICB9XG4gICAgICAgIHRocmVzaG9sZGVkVG9rZW5Db3VudCsrO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHRva2VuSWQsXG4gICAgICAgICAgdG9rZW5OYW1lLFxuICAgICAgICAgIGVsaWdpYmxlOiBhd2FpdCB0aGlzLmlzVG9rZW5RdW90YUVsaWdpYmxlKHRva2VuSWQsIHRva2VuTmFtZSksXG4gICAgICAgIH07XG4gICAgICB9KSxcbiAgICApO1xuXG4gICAgY2hlY2tzLmZvckVhY2goKGNoZWNrLCBpbmRleCkgPT4ge1xuICAgICAgaWYgKGNoZWNrLnN0YXR1cyA9PT0gXCJmdWxmaWxsZWRcIikge1xuICAgICAgICBpZiAoY2hlY2sudmFsdWUuZWxpZ2libGUpIHtcbiAgICAgICAgICBlbGlnaWJsZVRva2VuSWRzLmFkZChjaGVjay52YWx1ZS50b2tlbklkKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zdCB0aHJlc2hvbGQgPSB0aGlzLmdldFF1b3RhVGhyZXNob2xkKGNoZWNrLnZhbHVlLnRva2VuSWQpO1xuICAgICAgICAgIGlmICh0aHJlc2hvbGQgIT09IHVuZGVmaW5lZCAmJiB0aHJlc2hvbGQgIT09IG51bGwpIHtcbiAgICAgICAgICAgIG92ZXJUaHJlc2hvbGRUb2tlbnMucHVzaCh7IHRva2VuTmFtZTogY2hlY2sudmFsdWUudG9rZW5OYW1lLCB0aHJlc2hvbGQgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZW50cnkgPSBlbnRyaWVzW2luZGV4XTtcbiAgICAgIGlmIChlbnRyeSkge1xuICAgICAgICBjb25zdCBbdG9rZW5JZCwgdG9rZW5OYW1lXSA9IGVudHJ5O1xuICAgICAgICB0aGlzLmxvZ1F1b3RhTG9va3VwRmFpbE9wZW4odG9rZW5JZCwgdG9rZW5OYW1lLCBTdHJpbmcoY2hlY2sucmVhc29uKSk7XG4gICAgICAgIGVsaWdpYmxlVG9rZW5JZHMuYWRkKHRva2VuSWQpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHsgcmVhZHlBY3RpdmVUb2tlbklkcywgZWxpZ2libGVUb2tlbklkcywgb3ZlclRocmVzaG9sZFRva2VucywgdGhyZXNob2xkZWRUb2tlbkNvdW50IH07XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzV29ya2VyRWxpZ2libGVGb3JRdWV1ZUl0ZW0oXG4gICAgd29ya2VyOiBDb2RleEFwcFNlcnZlcldvcmtlcixcbiAgICBpdGVtOiBRdWV1ZUl0ZW0sXG4gICk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGlmIChpdGVtLmV4Y2x1ZGVkVG9rZW5JZHMuaGFzKHdvcmtlci50b2tlbklkKSkgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiB0aGlzLmlzVG9rZW5RdW90YUVsaWdpYmxlKHdvcmtlci50b2tlbklkLCB3b3JrZXIudG9rZW5OYW1lKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNUb2tlblF1b3RhRWxpZ2libGUoXG4gICAgdG9rZW5JZDogbnVtYmVyLFxuICAgIHRva2VuTmFtZTogc3RyaW5nLFxuICAgIGV4Y2x1ZGVkVG9rZW5JZHM/OiBTZXQ8bnVtYmVyPixcbiAgKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgY29uc3QgdGhyZXNob2xkID0gdGhpcy5nZXRRdW90YVRocmVzaG9sZCh0b2tlbklkKTtcbiAgICBpZiAodGhyZXNob2xkID09PSB1bmRlZmluZWQgfHwgdGhyZXNob2xkID09PSBudWxsKSByZXR1cm4gdHJ1ZTtcblxuICAgIGxldCByZXN1bHQ6IE9wZW5BSVF1b3RhVXNhZ2VSZXN1bHQ7XG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IGF3YWl0IHJlYWRPcGVuQUlRdW90YVVzYWdlKCgpID0+IHRoaXMuZ2V0UmF0ZUxpbWl0c0J5VG9rZW5JZCh0b2tlbklkKSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhpcy5sb2dRdW90YUxvb2t1cEZhaWxPcGVuKHRva2VuSWQsIHRva2VuTmFtZSwgKGUgYXMgRXJyb3IpLm1lc3NhZ2UpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgaWYgKHJlc3VsdC5raW5kID09PSBcImxvb2t1cF9mYWlsZWRcIikge1xuICAgICAgdGhpcy5sb2dRdW90YUxvb2t1cEZhaWxPcGVuKHRva2VuSWQsIHRva2VuTmFtZSwgcmVzdWx0LnJlYXNvbik7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAocmVzdWx0LnV0aWxpemF0aW9uUGN0ID49IHRocmVzaG9sZCkge1xuICAgICAgdGhpcy5sb2dRdW90YU92ZXJUaHJlc2hvbGQodG9rZW5JZCwgdG9rZW5OYW1lLCB0aHJlc2hvbGQsIHJlc3VsdCk7XG4gICAgICBleGNsdWRlZFRva2VuSWRzPy5hZGQodG9rZW5JZCk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBwcml2YXRlIGxvZ1F1b3RhT3ZlclRocmVzaG9sZChcbiAgICB0b2tlbklkOiBudW1iZXIsXG4gICAgdG9rZW5OYW1lOiBzdHJpbmcsXG4gICAgdGhyZXNob2xkOiBudW1iZXIsXG4gICAgcmVzdWx0OiBFeHRyYWN0PE9wZW5BSVF1b3RhVXNhZ2VSZXN1bHQsIHsga2luZDogXCJva1wiIH0+LFxuICApOiB2b2lkIHtcbiAgICBsb2dnZXIuaW5mbyhcInF1b3RhX3RocmVzaG9sZCBnYXRlOiBvdmVyX3RocmVzaG9sZFwiLCB7XG4gICAgICB0b2tlbklkLFxuICAgICAgdG9rZW5OYW1lLFxuICAgICAgcHJvdmlkZXI6IFwib3BlbmFpXCIsXG4gICAgICB0aHJlc2hvbGQsXG4gICAgICBjYWNoZWRVdGlsaXphdGlvbjogcmVzdWx0LnV0aWxpemF0aW9uUGN0LFxuICAgICAgY2FjaGVBZ2U6IHJlc3VsdC5jYWNoZUFnZU1zLFxuICAgICAgd2luZG93RHVyYXRpb25NaW5zOiByZXN1bHQud2luZG93RHVyYXRpb25NaW5zLFxuICAgICAgcmVzZXRzQXQ6IHJlc3VsdC5yZXNldHNBdCxcbiAgICAgIGxpbWl0SWQ6IHJlc3VsdC5saW1pdElkLFxuICAgICAgcmVhc29uOiBcIm92ZXJfdGhyZXNob2xkXCIsXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGxvZ1F1b3RhTG9va3VwRmFpbE9wZW4odG9rZW5JZDogbnVtYmVyLCB0b2tlbk5hbWU6IHN0cmluZywgcmVhc29uOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCB0aHJlc2hvbGQgPSB0aGlzLmdldFF1b3RhVGhyZXNob2xkKHRva2VuSWQpO1xuICAgIGxvZ2dlci53YXJuKFwicXVvdGFfdGhyZXNob2xkIGdhdGU6IGxvb2t1cF9mYWlsX29wZW5cIiwge1xuICAgICAgdG9rZW5JZCxcbiAgICAgIHRva2VuTmFtZSxcbiAgICAgIHByb3ZpZGVyOiBcIm9wZW5haVwiLFxuICAgICAgdGhyZXNob2xkLFxuICAgICAgcmVhc29uOiBcImxvb2t1cF9mYWlsX29wZW5cIixcbiAgICAgIGxvb2t1cFJlYXNvbjogcmVhc29uLFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSB0aHJvd1F1b3RhVGhyZXNob2xkRXhjZWVkZWQoZWxpZ2liaWxpdHk6IFRva2VuRWxpZ2liaWxpdHkpOiBuZXZlciB7XG4gICAgbG9nZ2VyLndhcm4oXCJxdW90YV90aHJlc2hvbGQgZ2F0ZTogYWxsX2V4Y2VlZGVkXCIsIHtcbiAgICAgIHByb3ZpZGVyOiBcIm9wZW5haVwiLFxuICAgICAgdG9rZW5Db3VudDogZWxpZ2liaWxpdHkucmVhZHlBY3RpdmVUb2tlbklkcy5zaXplLFxuICAgICAgdGhyZXNob2xkZWRUb2tlbkNvdW50OiBlbGlnaWJpbGl0eS50aHJlc2hvbGRlZFRva2VuQ291bnQsXG4gICAgICBvdmVyVGhyZXNob2xkVG9rZW5zOiBlbGlnaWJpbGl0eS5vdmVyVGhyZXNob2xkVG9rZW5zLFxuICAgICAgcmVhc29uOiBcImFsbF9leGNlZWRlZFwiLFxuICAgIH0pO1xuICAgIHRocm93IG5ldyBRdW90YVRocmVzaG9sZEV4Y2VlZGVkRXJyb3IoXG4gICAgICBxdW90YVRocmVzaG9sZEV4Y2VlZGVkTWVzc2FnZShcIm9wZW5haVwiLCBlbGlnaWJpbGl0eS5vdmVyVGhyZXNob2xkVG9rZW5zKSxcbiAgICApO1xuICB9XG5cbiAgLy8g4pSA4pSAIEJyb3dzZXIgbG9naW4gZmxvdyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBwZW5kaW5nTG9naW46IHtcbiAgICB3b3JrZXI6IENvZGV4QXBwU2VydmVyV29ya2VyO1xuICAgIG5hbWU6IHN0cmluZztcbiAgICB0aW1lcjogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0VGltZW91dD47XG4gIH0gfCBudWxsID0gbnVsbDtcblxuICBhc3luYyBzdGFydEJyb3dzZXJMb2dpbihuYW1lOiBzdHJpbmcpOiBQcm9taXNlPHsgYXV0aFVybDogc3RyaW5nIH0+IHtcbiAgICBpZiAodGhpcy5wZW5kaW5nTG9naW4pIHtcbiAgICAgIHRoaXMucGVuZGluZ0xvZ2luLndvcmtlci5raWxsKCkuY2F0Y2goKCkgPT4ge30pO1xuICAgICAgY2xlYXJUaW1lb3V0KHRoaXMucGVuZGluZ0xvZ2luLnRpbWVyKTtcbiAgICAgIHRoaXMucGVuZGluZ0xvZ2luID0gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCB0ZW1wSWQgPSBEYXRlLm5vdygpO1xuICAgIGNvbnN0IHdvcmtlciA9IG5ldyBDb2RleEFwcFNlcnZlcldvcmtlcih7XG4gICAgICB0b2tlbklkOiB0ZW1wSWQsXG4gICAgICB0b2tlbk5hbWU6IG5hbWUsXG4gICAgICBhY2Nlc3NUb2tlbjogXCJcIixcbiAgICAgIGFjY291bnRJZDogXCJcIixcbiAgICB9KTtcblxuICAgIGNvbnN0IGF1dGhVcmwgPSBhd2FpdCB3b3JrZXIuc3RhcnRCcm93c2VyTG9naW4oKTtcblxuICAgIGNvbnN0IHRpbWVyID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICBpZiAodGhpcy5wZW5kaW5nTG9naW4/LndvcmtlciA9PT0gd29ya2VyKSB7XG4gICAgICAgIGxvZ2dlci53YXJuKGBicm93c2VyIGxvZ2luIHRpbWVvdXQgZm9yICR7bmFtZX0sIGtpbGxpbmcgd29ya2VyYCk7XG4gICAgICAgIHdvcmtlci5raWxsKCkuY2F0Y2goKCkgPT4ge30pO1xuICAgICAgICB0aGlzLnBlbmRpbmdMb2dpbiA9IG51bGw7XG4gICAgICB9XG4gICAgfSwgMzAwXzAwMCk7XG5cbiAgICB0aGlzLnBlbmRpbmdMb2dpbiA9IHsgd29ya2VyLCBuYW1lLCB0aW1lciB9O1xuICAgIHJldHVybiB7IGF1dGhVcmwgfTtcbiAgfVxuXG4gIGdldCBwZW5kaW5nTG9naW5OYW1lKCk6IHN0cmluZyB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLnBlbmRpbmdMb2dpbj8ubmFtZSA/PyBudWxsO1xuICB9XG5cbiAgYXN5bmMgY29tcGxldGVCcm93c2VyTG9naW4oKTogUHJvbWlzZTx7XG4gICAgYWNjZXNzVG9rZW46IHN0cmluZztcbiAgICByZWZyZXNoVG9rZW46IHN0cmluZztcbiAgICBpZFRva2VuPzogc3RyaW5nO1xuICAgIGFjY291bnRJZDogc3RyaW5nO1xuICB9PiB7XG4gICAgaWYgKCF0aGlzLnBlbmRpbmdMb2dpbikgdGhyb3cgbmV3IEVycm9yKFwibm8gcGVuZGluZyBsb2dpblwiKTtcbiAgICBjb25zdCB7IHdvcmtlciwgdGltZXIgfSA9IHRoaXMucGVuZGluZ0xvZ2luO1xuXG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHdvcmtlci53YWl0Rm9yQnJvd3NlckxvZ2luQ29tcGxldGUoKTtcbiAgICAgIGNvbnN0IGNyZWRzID0gYXdhaXQgd29ya2VyLnJlYWRNYW5hZ2VkQ3JlZGVudGlhbHMoKTtcbiAgICAgIGlmICghY3JlZHMpIHRocm93IG5ldyBFcnJvcihcImZhaWxlZCB0byByZWFkIGNyZWRlbnRpYWxzIGFmdGVyIGxvZ2luXCIpO1xuICAgICAgcmV0dXJuIGNyZWRzO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBjbGVhclRpbWVvdXQodGltZXIpO1xuICAgICAgdGhpcy5wZW5kaW5nTG9naW4gPSBudWxsO1xuICAgICAgYXdhaXQgd29ya2VyLmtpbGwoKS5jYXRjaCgoKSA9PiB7fSk7XG4gICAgfVxuICB9XG5cbiAgLy8g4pSA4pSAIFN0YXRzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIGdldCB3b3JrZXJDb3VudCgpOiBudW1iZXIge1xuICAgIHJldHVybiBbLi4udGhpcy53b3JrZXJQb29sLnZhbHVlcygpXS5mbGF0KCkubGVuZ3RoO1xuICB9XG5cbiAgZ2V0IHJlYWR5V29ya2VyQ291bnQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gWy4uLnRoaXMud29ya2VyUG9vbC52YWx1ZXMoKV0uZmxhdCgpLmZpbHRlcigodykgPT4gdy5pc1JlYWR5KS5sZW5ndGg7XG4gIH1cblxuICBnZXQgcXVldWVMZW5ndGgoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5xdWV1ZS5sZW5ndGg7XG4gIH1cbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztBQTRCQSxNQUFNLFNBQVMsVUFBVSxDQUFDLFNBQVMsb0JBQW9CLENBQUM7QUFFeEQsTUFBTSxpQkFBaUI7QUFFdkIsTUFBTSxvQkFBb0IsS0FBSyxJQUM3QixPQUFPLFFBQVEsSUFBSSwyQkFBMkIsRUFBRSxFQUZwQixFQUk3QjtBQUNELE1BQU0sbUJBQW1CO0FBQ3pCLE1BQU0saUJBQWlCO0FBQ3ZCLE1BQU0sb0JBQW9CO0FBRzFCLE1BQU0sdUJBQXVCLFFBQVEsSUFBSSw4QkFBOEI7QUFFdkUsTUFBTSx1QkFBdUI7QUFDN0IsTUFBTSx1QkFBdUI7QUFHN0IsU0FBUyxhQUFhLFNBQWlCLGFBQTZCO0FBQ2xFLFFBQU8sVUFBVSxLQUFLOztBQUd4QixTQUFTLE1BQU0sSUFBMkI7QUFDeEMsUUFBTyxJQUFJLFNBQVMsWUFBWSxXQUFXLFNBQVMsR0FBRyxDQUFDOztBQUcxRCxTQUFTLDhCQUNQLFVBQ0EsUUFDUTtDQUNSLE1BQU0sVUFBVSxPQUNiLEtBQUssVUFBVSxHQUFHLE1BQU0sVUFB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
601
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlbmFpLWRpc3BhdGNoZXIuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3Byb3ZpZGVycy9vcGVuYWkvb3BlbmFpLWRpc3BhdGNoZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBPcGVuQUlEaXNwYXRjaGVyIOKAlCBjb2RleCBhcHAtc2VydmVyIHdvcmtlciBwb29sICsg7Yag7YGwIOudvOyasO2MhS5cbiAqXG4gKiAtIO2GoO2BsOuLuSBOIHdvcmtlciAoQ29kZXhBcHBTZXJ2ZXJXb3JrZXIpLCDquLDrs7ggM1xuICogLSBpZGxlIHdvcmtlciByb3VuZC1yb2JpbiDshKDtg50gKyDtgZAg64yA6riwICjsoITrtoAgYnVzeSDsi5wpXG4gKiAtIFRva2VuU3Vic2NyaWJlciDsnbTrsqTtirjroZwgd29ya2VyIHBvb2wg64+Z6riw7ZmUXG4gKiAtIGJhY2twcmVzc3VyZTog7YGQIGZ1bGwg65iQ64qUIHRpbWVvdXQg7IucIFNFUlZFUl9CVVNZXG4gKi9cbmltcG9ydCB7IGdldExvZ2dlciB9IGZyb20gXCJAbG9ndGFwZS9sb2d0YXBlXCI7XG5cbmltcG9ydCB7IFF1b3RhVGhyZXNob2xkRXhjZWVkZWRFcnJvciB9IGZyb20gXCIuLi8uLi8uLi9hcHBsaWNhdGlvbi9xZ3JpZC9xZ3JpZC50eXBlc1wiO1xuaW1wb3J0IHsgVG9rZW5Nb2RlbCB9IGZyb20gXCIuLi8uLi8uLi9hcHBsaWNhdGlvbi90b2tlbi90b2tlbi5tb2RlbFwiO1xuaW1wb3J0IHsgdHlwZSBPcGVuQUlDcmVkZW50aWFscyB9IGZyb20gXCIuLi8uLi8uLi9hcHBsaWNhdGlvbi90b2tlbi90b2tlbi50eXBlc1wiO1xuaW1wb3J0IHsgdHlwZSBHZXRBY2NvdW50UmF0ZUxpbWl0c1Jlc3BvbnNlIH0gZnJvbSBcIi4uLy4uLy4uL2NvZGV4LXByb3RvY29sL3YyL0dldEFjY291bnRSYXRlTGltaXRzUmVzcG9uc2VcIjtcbmltcG9ydCB7XG4gIHR5cGUgR2VuZXJhdGVSZXF1ZXN0LFxuICB0eXBlIEdlbmVyYXRlUmVzdWx0LFxuICB0eXBlIEdlbmVyYXRlU3RyZWFtQ2FsbGJhY2tzLFxuICB0eXBlIFByb3ZpZGVyRGlzcGF0Y2hlcixcbn0gZnJvbSBcIi4uL2NvbW1vbi9wcm92aWRlci1kaXNwYXRjaGVyXCI7XG5pbXBvcnQgeyBDb2RleEFwcFNlcnZlcldvcmtlciwgdHlwZSBTdHJlYW1DYWxsYmFja3MsIHR5cGUgVHVyblJlcXVlc3QgfSBmcm9tIFwiLi9jb2RleC13b3JrZXJcIjtcbmltcG9ydCB7XG4gIHJlYWRPcGVuQUlRdW90YVVzYWdlLFxuICB0eXBlIE9wZW5BSVF1b3RhVXNhZ2VSZXN1bHQsXG4gIHR5cGUgT3BlbkFJUmF0ZUxpbWl0c1dpdGhNZXRhLFxufSBmcm9tIFwiLi9vcGVuYWktcXVvdGFcIjtcbmltcG9ydCB7IGhhbmRsZUNoYXRncHRBdXRoVG9rZW5zUmVmcmVzaCB9IGZyb20gXCIuL29wZW5haS1yZWZyZXNoXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGdldExvZ2dlcihbXCJxZ3JpZFwiLCBcIm9wZW5haS1kaXNwYXRjaGVyXCJdKTtcblxuLy8g7J2066+47KeAIOyDneyEsSDsmpTssq3snbQg6rKM7J207Yq4L+yDneyEseyXkCDsi6TtjKjtlojsnYQg65WM7J2YIOq1rOu2hOyekC5cbi8vIC0gXCJnYXRlXCI6IOyCrOyghCDqsoDspp0g7Iuk7YyoKGNhcGFiaWxpdHkv66qo6424IOupgO2LsOuqqOuLrCDrtojstqnsobEpIOKAlCB0dXJuIOuvuOyLpO2WiS5cbi8vIC0gXCJub3RfY2FsbGVkXCI6IHR1cm4g7J2AIOyEseqzte2WiOycvOuCmCDrqqjrjbjsnbQgaW1hZ2UgdG9vbCDsnYQg7Zi47LacIOyViCDtlagg4oCUIOyerOyLnOuPhCDrrLTsnbUo7ZSE66Gs7ZSE7Yq4IOusuOygnCkuXG4vLyAtIFwiaW5jb21wbGV0ZVwiOiB0b29sIOyLnOuPhOuQkOycvOuCmCDsmYTshLEg7J2066+47KeAIOuvuOuPhOywqSDigJQg7J6s7Iuc64+EIO2bhOuztCjshJzrsoTsuKEg7Iuk7YyoL+qxsOu2gCkuXG5leHBvcnQgdHlwZSBJbWFnZUZhaWx1cmVLaW5kID0gXCJnYXRlXCIgfCBcIm5vdF9jYWxsZWRcIiB8IFwiaW5jb21wbGV0ZVwiO1xuXG5leHBvcnQgY2xhc3MgSW1hZ2VHZW5lcmF0aW9uRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHJlYWRvbmx5IGtpbmQ6IEltYWdlRmFpbHVyZUtpbmQsXG4gICAgbWVzc2FnZTogc3RyaW5nLFxuICApIHtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgICB0aGlzLm5hbWUgPSBcIkltYWdlR2VuZXJhdGlvbkVycm9yXCI7XG4gIH1cbn1cblxuY29uc3QgREVGQVVMVF9FRkZPUlQgPSBcImxvd1wiO1xuY29uc3QgTUFYX1dPUktFUlNfUEVSX1RPS0VOID0gNTtcbmNvbnN0IFdPUktFUlNfUEVSX1RPS0VOID0gTWF0aC5taW4oXG4gIE51bWJlcihwcm9jZXNzLmVudi5RR1JJRF9XT1JLRVJTX1BFUl9UT0tFTiA/PyAzKSxcbiAgTUFYX1dPUktFUlNfUEVSX1RPS0VOLFxuKTtcbmNvbnN0IFFVRVVFX1RJTUVPVVRfTVMgPSA2MF8wMDA7XG5jb25zdCBNQVhfUVVFVUVfU0laRSA9IDUwO1xuY29uc3QgU1BBV05fSU5URVJWQUxfTVMgPSA1MDA7XG5cbi8vIHRocmVhZCDsnqzsgqzsmqkocHJvbXB0IGNhY2hlIOqzoOyglSkuIOuBhOuptCDquLDsobQgXCLrp6QgdHVybiDsg4ggdGhyZWFkICsgaGlzdG9yeSBpbmplY3RcIiDrj5nsnpEuXG5jb25zdCBUSFJFQURfUkVVU0VfRU5BQkxFRCA9IHByb2Nlc3MuZW52LlFHUklEX09QRU5BSV9USFJFQURfUkVVU0UgIT09IFwiZmFsc2VcIjtcbi8vIOyijO2RnCB3b3JrZXIg6rCAIGJ1c3kg7J28IOuVjCBmcmVlIOulvCDquLDri6TrpqzripQg7LWc64yAIOyLnOqwhC4g7LSI6rO8IOyLnCDsg4ggdGhyZWFkIOuhnCDtj7TrsLEuXG5jb25zdCBSRVVTRV9XT1JLRVJfV0FJVF9NUyA9IDVfMDAwO1xuY29uc3QgUkVVU0VfV09SS0VSX1BPTExfTVMgPSA1MDtcblxuLy8gd29ya2VySWQg7ZWp7ISxOiB0b2tlbklkIOyZgCB3b3JrZXJJbmRleCgwLi40KSDrpbwg7ZWY64KY7J2YIOyViOyglSDsiKvsnpDroZwg7J247L2U65SpLlxuZnVuY3Rpb24gbWFrZVdvcmtlcklkKHRva2VuSWQ6IG51bWJlciwgd29ya2VySW5kZXg6IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiB0b2tlbklkICogMTAgKyB3b3JrZXJJbmRleDtcbn1cblxuZnVuY3Rpb24gc2xlZXAobXM6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgbXMpKTtcbn1cblxuZnVuY3Rpb24gcXVvdGFUaHJlc2hvbGRFeGNlZWRlZE1lc3NhZ2UoXG4gIHByb3ZpZGVyOiBzdHJpbmcsXG4gIHRva2VuczogQXJyYXk8eyB0b2tlbk5hbWU6IHN0cmluZzsgdGhyZXNob2xkOiBudW1iZXIgfT4sXG4pOiBzdHJpbmcge1xuICBjb25zdCBkZXRhaWxzID0gdG9rZW5zXG4gICAgLm1hcCgodG9rZW4pID0+IGAke3Rva2VuLnRva2VuTmFtZX0gKHRocmVzaG9sZCAke3Rva2VuLnRocmVzaG9sZH0lKWApXG4gICAgLmpvaW4oXCIsIFwiKTtcbiAgcmV0dXJuIGRldGFpbHMubGVuZ3RoID4gMFxuICAgID8gYEFsbCAke3Byb3ZpZGVyfSB0b2tlbnMgZXhjZWVkZWQgcXVvdGEgdGhyZXNob2xkOiAke2RldGFpbHN9YFxuICAgIDogYEFsbCAke3Byb3ZpZGVyfSB0b2tlbnMgZXhjZWVkZWQgcXVvdGEgdGhyZXNob2xkYDtcbn1cblxudHlwZSBRdWV1ZUl0ZW0gPSB7XG4gIHJlc29sdmU6ICh3b3JrZXI6IENvZGV4QXBwU2VydmVyV29ya2VyKSA9PiB2b2lkO1xuICByZWplY3Q6IChlcnJvcjogRXJyb3IpID0+IHZvaWQ7XG4gIHRpbWVyOiBSZXR1cm5UeXBlPHR5cGVvZiBzZXRUaW1lb3V0PjtcbiAgYWJvcnRDbGVhbnVwPzogKCkgPT4gdm9pZDtcbiAgZXhjbHVkZWRUb2tlbklkczogU2V0PG51bWJlcj47XG59O1xuXG50eXBlIFRva2VuTWV0YWRhdGEgPSB7XG4gIG5hbWU6IHN0cmluZztcbiAgcXVvdGFUaHJlc2hvbGQ/OiBudW1iZXIgfCBudWxsO1xufTtcblxudHlwZSBUb2tlbkVsaWdpYmlsaXR5ID0ge1xuICByZWFkeUFjdGl2ZVRva2VuSWRzOiBTZXQ8bnVtYmVyPjtcbiAgZWxpZ2libGVUb2tlbklkczogU2V0PG51bWJlcj47XG4gIG92ZXJUaHJlc2hvbGRUb2tlbnM6IEFycmF5PHsgdG9rZW5OYW1lOiBzdHJpbmc7IHRocmVzaG9sZDogbnVtYmVyIH0+O1xuICB0aHJlc2hvbGRlZFRva2VuQ291bnQ6IG51bWJlcjtcbn07XG5cbmV4cG9ydCBjbGFzcyBPcGVuQUlEaXNwYXRjaGVyIGltcGxlbWVudHMgUHJvdmlkZXJEaXNwYXRjaGVyIHtcbiAgd29ya2VyUG9vbCA9IG5ldyBNYXA8bnVtYmVyLCBDb2RleEFwcFNlcnZlcldvcmtlcltdPigpO1xuICB0b2tlbk1ldGFkYXRhID0gbmV3IE1hcDxudW1iZXIsIFRva2VuTWV0YWRhdGE+KCk7XG4gIHJyQ3Vyc29yID0gMDtcbiAgcXVldWU6IFF1ZXVlSXRlbVtdID0gW107XG4gIHByaXZhdGUgZHJhaW5pbmcgPSBmYWxzZTtcbiAgcHJpdmF0ZSBkcmFpbkFnYWluID0gZmFsc2U7XG5cbiAgYXN5bmMgc3RhcnQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgeyByb3dzIH0gPSBhd2FpdCBUb2tlbk1vZGVsLmZpbmRNYW55KFwiQVwiKTtcbiAgICBjb25zdCBvcGVuYWlUb2tlbnMgPSByb3dzLmZpbHRlcigodCkgPT4gdC5wcm92aWRlciA9PT0gXCJvcGVuYWlcIik7XG4gICAgbG9nZ2VyLmluZm8oXG4gICAgICBgc3RhcnRpbmcgJHtvcGVuYWlUb2tlbnMubGVuZ3RofSBvcGVuYWkgdG9rZW5zICgke1dPUktFUlNfUEVSX1RPS0VOfSB3b3JrZXJzIGVhY2gpYCxcbiAgICApO1xuXG4gICAgYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKFxuICAgICAgb3BlbmFpVG9rZW5zLm1hcChhc3luYyAodCkgPT4ge1xuICAgICAgICBhd2FpdCB0aGlzLnNwYXduV29ya2VycyhcbiAgICAgICAgICB0LmlkLFxuICAgICAgICAgIHQubmFtZSxcbiAgICAgICAgICB0LmNyZWRlbnRpYWxzIGFzIE9wZW5BSUNyZWRlbnRpYWxzLFxuICAgICAgICAgIHQucXVvdGFfdGhyZXNob2xkLFxuICAgICAgICApO1xuICAgICAgICBpZiAoIXQuYWN0aXZlKSB0aGlzLm9uVG9rZW5EZWFjdGl2YXRlZCh0LmlkKTtcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cblxuICBhc3luYyBzdG9wKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMucmVqZWN0QWxsUXVldWVkKFwiRElTUEFUQ0hFUl9TSFVURE9XTlwiKTtcbiAgICBjb25zdCBraWxscyA9IFsuLi50aGlzLndvcmtlclBvb2wudmFsdWVzKCldLmZsYXQoKS5tYXAoKHcpID0+IHcua2lsbCgpKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQoa2lsbHMpO1xuICAgIHRoaXMud29ya2VyUG9vbC5jbGVhcigpO1xuICAgIHRoaXMudG9rZW5NZXRhZGF0YS5jbGVhcigpO1xuICAgIHRoaXMucmF0ZUxpbWl0c0NhY2hlLmNsZWFyKCk7XG4gIH1cblxuICAvLyDilIDilIAgVG9rZW4gZXZlbnRzIChmcm9tIFRva2VuU3Vic2NyaWJlcikg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgYXN5bmMgb25Ub2tlbkFkZGVkKFxuICAgIGlkOiBudW1iZXIsXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIGNyZWRlbnRpYWxzOiBPcGVuQUlDcmVkZW50aWFscyxcbiAgICBxdW90YVRocmVzaG9sZD86IG51bWJlciB8IG51bGwsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuc2V0VG9rZW5NZXRhZGF0YShpZCwgbmFtZSwgcXVvdGFUaHJlc2hvbGQpO1xuICAgIGlmICh0aGlzLndvcmtlclBvb2wuaGFzKGlkKSkgcmV0dXJuO1xuICAgIGF3YWl0IHRoaXMuc3Bhd25Xb3JrZXJzKGlkLCBuYW1lLCBjcmVkZW50aWFscywgcXVvdGFUaHJlc2hvbGQpO1xuICB9XG5cbiAgYXN5bmMgb25Ub2tlblJlbW92ZWQoaWQ6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHdvcmtlcnMgPSB0aGlzLndvcmtlclBvb2wuZ2V0KGlkKSA/PyBbXTtcbiAgICBjb25zdCB0b2tlbk5hbWUgPSB3b3JrZXJzWzBdPy50b2tlbk5hbWU7XG4gICAgdGhpcy53b3JrZXJQb29sLmRlbGV0ZShpZCk7XG4gICAgdGhpcy50b2tlbk1ldGFkYXRhLmRlbGV0ZShpZCk7XG4gICAgdGhpcy5yYXRlTGltaXRzQ2FjaGUuZGVsZXRlKGlkKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQod29ya2Vycy5tYXAoKHcpID0+IHcua2lsbCgpKSk7XG4gICAgaWYgKHRoaXMuZ2V0QWxsUmVhZHlBY3RpdmVXb3JrZXJzKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aGlzLnJlamVjdEFsbFF1ZXVlZChcIk5PX09QRU5BSV9XT1JLRVJTXCIpO1xuICAgIH1cbiAgICBpZiAod29ya2Vycy5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCBsYWJlbCA9IHRva2VuTmFtZSA/PyBgdG9rZW4gJHtpZH1gO1xuICAgICAgbG9nZ2VyLmluZm8oYHdvcmtlcnMgcmVtb3ZlZDogJHtsYWJlbH0gKCR7d29ya2Vycy5sZW5ndGh9KWApO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIG9uVG9rZW5VcGRhdGVkKFxuICAgIGlkOiBudW1iZXIsXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIGNyZWRlbnRpYWxzOiBPcGVuQUlDcmVkZW50aWFscyxcbiAgICBxdW90YVRocmVzaG9sZD86IG51bWJlciB8IG51bGwsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGV4aXN0aW5nID0gdGhpcy53b3JrZXJQb29sLmdldChpZCkgPz8gW107XG4gICAgY29uc3QgcmVuYW1lZCA9IGV4aXN0aW5nLnNvbWUoKHcpID0+IHcudG9rZW5OYW1lICE9PSBuYW1lKTtcbiAgICB0aGlzLnNldFRva2VuTWV0YWRhdGEoaWQsIG5hbWUsIHF1b3RhVGhyZXNob2xkKTtcbiAgICBpZiAocmVuYW1lZCkgdGhpcy5yYXRlTGltaXRzQ2FjaGUuZGVsZXRlKGlkKTtcblxuICAgIGlmIChleGlzdGluZy5sZW5ndGggPT09IDApIHtcbiAgICAgIGF3YWl0IHRoaXMuc3Bhd25Xb3JrZXJzKGlkLCBuYW1lLCBjcmVkZW50aWFscywgcXVvdGFUaHJlc2hvbGQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChleGlzdGluZy5ldmVyeSgodykgPT4gdy5jYW5SZXVzZUZvclRva2VuKG5hbWUsIGNyZWRlbnRpYWxzKSkpIHtcbiAgICAgIGV4aXN0aW5nLmZvckVhY2goKHcpID0+IHcudXBkYXRlVG9rZW5TdGF0ZShuYW1lLCBjcmVkZW50aWFscykpO1xuICAgICAgbG9nZ2VyLmluZm8oYHdvcmtlcnMgdXBkYXRlZCBpbi1wbGFjZTogJHtuYW1lfWApO1xuICAgICAgdGhpcy5yZXF1ZXN0RHJhaW5RdWV1ZSgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMud29ya2VyUG9vbC5kZWxldGUoaWQpO1xuICAgIHRoaXMucmF0ZUxpbWl0c0NhY2hlLmRlbGV0ZShpZCk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKGV4aXN0aW5nLm1hcCgodykgPT4gdy5raWxsKCkpKTtcbiAgICBhd2FpdCB0aGlzLnNwYXduV29ya2VycyhpZCwgbmFtZSwgY3JlZGVudGlhbHMsIHF1b3RhVGhyZXNob2xkKTtcbiAgfVxuXG4gIG9uVG9rZW5EZWFjdGl2YXRlZChpZDogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3Qgd29ya2VycyA9IHRoaXMud29ya2VyUG9vbC5nZXQoaWQpID8/IFtdO1xuICAgIGNvbnN0IHRva2VuTmFtZSA9IHdvcmtlcnNbMF0/LnRva2VuTmFtZTtcbiAgICB3b3JrZXJzLmZvckVhY2goKHcpID0+IHtcbiAgICAgIHcuYWN0aXZlID0gZmFsc2U7XG4gICAgfSk7XG4gICAgaWYgKHRoaXMuZ2V0QWxsUmVhZHlBY3RpdmVXb3JrZXJzKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aGlzLnJlamVjdEFsbFF1ZXVlZChcIk5PX0FDVElWRV9XT1JLRVJTXCIpO1xuICAgIH1cbiAgICBjb25zdCBsYWJlbCA9IHRva2VuTmFtZSA/PyBgdG9rZW4gJHtpZH1gO1xuICAgIGxvZ2dlci5pbmZvKGB3b3JrZXJzIGRlYWN0aXZhdGVkOiAke2xhYmVsfWApO1xuICB9XG5cbiAgb25Ub2tlbkFjdGl2YXRlZChpZDogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3Qgd29ya2VycyA9IHRoaXMud29ya2VyUG9vbC5nZXQoaWQpID8/IFtdO1xuICAgIGNvbnN0IHRva2VuTmFtZSA9IHdvcmtlcnNbMF0/LnRva2VuTmFtZTtcbiAgICB3b3JrZXJzLmZvckVhY2goKHcpID0+IHtcbiAgICAgIHcuYWN0aXZlID0gdHJ1ZTtcbiAgICB9KTtcbiAgICB0aGlzLnJlcXVlc3REcmFpblF1ZXVlKCk7XG4gICAgY29uc3QgbGFiZWwgPSB0b2tlbk5hbWUgPz8gYHRva2VuICR7aWR9YDtcbiAgICBsb2dnZXIuaW5mbyhgd29ya2VycyBhY3RpdmF0ZWQ6ICR7bGFiZWx9YCk7XG4gIH1cblxuICBhc3luYyByZXBsYWNlVG9rZW5zKFxuICAgIHJvd3M6IEFycmF5PHtcbiAgICAgIGlkOiBudW1iZXI7XG4gICAgICBuYW1lOiBzdHJpbmc7XG4gICAgICBjcmVkZW50aWFsczogT3BlbkFJQ3JlZGVudGlhbHM7XG4gICAgICBxdW90YVRocmVzaG9sZD86IG51bWJlciB8IG51bGw7XG4gICAgfT4sXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IG5leHQgPSBuZXcgU2V0KHJvd3MubWFwKChyKSA9PiByLmlkKSk7XG4gICAgZm9yIChjb25zdCBpZCBvZiBBcnJheS5mcm9tKHRoaXMud29ya2VyUG9vbC5rZXlzKCkpKSB7XG4gICAgICBpZiAoIW5leHQuaGFzKGlkKSkgYXdhaXQgdGhpcy5vblRva2VuUmVtb3ZlZChpZCk7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCByb3cgb2Ygcm93cykge1xuICAgICAgaWYgKHRoaXMud29ya2VyUG9vbC5oYXMocm93LmlkKSkge1xuICAgICAgICBhd2FpdCB0aGlzLm9uVG9rZW5VcGRhdGVkKHJvdy5pZCwgcm93Lm5hbWUsIHJvdy5jcmVkZW50aWFscywgcm93LnF1b3RhVGhyZXNob2xkKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGF3YWl0IHRoaXMub25Ub2tlbkFkZGVkKHJvdy5pZCwgcm93Lm5hbWUsIHJvdy5jcmVkZW50aWFscywgcm93LnF1b3RhVGhyZXNob2xkKTtcbiAgICAgIH1cbiAgICAgIHRoaXMub25Ub2tlbkFjdGl2YXRlZChyb3cuaWQpO1xuICAgIH1cbiAgfVxuXG4gIC8vIOKUgOKUgCBHZW5lcmF0ZSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBhc3luYyBnZW5lcmF0ZShyZXE6IEdlbmVyYXRlUmVxdWVzdCk6IFByb21pc2U8R2VuZXJhdGVSZXN1bHQ+IHtcbiAgICBjb25zdCBleGNsdWRlZFRva2VuSWRzID0gbmV3IFNldDxudW1iZXI+KCk7XG4gICAgLy8gdGhyZWFkIOyerOyCrOyaqSDqsr3roZw6IOyijO2RnCB3b3JrZXIg66W8IOygkOycoO2VtCDquLDsobQgdGhyZWFkIOyXkCB0dXJuIOunjCDsi6TtlokuXG4gICAgY29uc3QgcmV1c2VXb3JrZXIgPSBhd2FpdCB0aGlzLmFjcXVpcmVSZXVzZVdvcmtlcihyZXEsIGV4Y2x1ZGVkVG9rZW5JZHMpO1xuICAgIGlmIChyZXVzZVdvcmtlcikge1xuICAgICAgbG9nZ2VyLmluZm8oXG4gICAgICAgIGDihrsgJHtyZXVzZVdvcmtlci50b2tlbk5hbWV9WyR7cmV1c2VXb3JrZXIudG9rZW5JZH1dIChyZXVzZSB0aHJlYWQsICR7cmVxLm1vZGVsfSlgLFxuICAgICAgKTtcbiAgICAgIHJldHVybiB0aGlzLmV4ZWN1dGVBbmRSZWxlYXNlKHJldXNlV29ya2VyLCAodykgPT5cbiAgICAgICAgdGhpcy5leGVjdXRlVHVybih3LCByZXEsIHJlcS5yZXVzZSEudGhyZWFkSWQpLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCB3b3JrZXIgPSBhd2FpdCB0aGlzLmFjcXVpcmVJZGxlV29ya2VyKGV4Y2x1ZGVkVG9rZW5JZHMpO1xuICAgIGlmICh3b3JrZXIpIHtcbiAgICAgIGxvZ2dlci5pbmZvKGDihpIgJHt3b3JrZXIudG9rZW5OYW1lfVske3dvcmtlci50b2tlbklkfV0gKG1vZGVsOiAke3JlcS5tb2RlbH0pYCk7XG4gICAgICByZXR1cm4gdGhpcy5leGVjdXRlQW5kUmVsZWFzZSh3b3JrZXIsICh3KSA9PiB0aGlzLmV4ZWN1dGVUdXJuKHcsIHJlcSkpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5lbnF1ZXVlKCh3KSA9PiB7XG4gICAgICBsb2dnZXIuaW5mbyhg4oaSICR7dy50b2tlbk5hbWV9WyR7dy50b2tlbklkfV0gKG1vZGVsOiAke3JlcS5tb2RlbH0sIHF1ZXVlZClgKTtcbiAgICAgIHJldHVybiB0aGlzLmV4ZWN1dGVUdXJuKHcsIHJlcSk7XG4gICAgfSwgZXhjbHVkZWRUb2tlbklkcyk7XG4gIH1cblxuICBhc3luYyBnZW5lcmF0ZVN0cmVhbShyZXE6IEdlbmVyYXRlUmVxdWVzdCwgY2I6IEdlbmVyYXRlU3RyZWFtQ2FsbGJhY2tzKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgLy8g7J2066+47KeAIOyDneyEseydgCBub24tc3RyZWFtIOyghOyaqShSMik6IGNvZGV4IOqwgCDsnbTrr7jsp4Ag64247YOA66W8IOyjvOyngCDslYrqs6Ag7JmE7ISxIGJhc2U2NCDrpbxcbiAgICAvLyDtlZwg67KI7JeQIOykgOuLpC4g7Iqk7Yq466as67CNIOqyveuhnOuhnCDsnbTrr7jsp4Ag7JqU7LKt7J20IOyYpOuptCDrqoXsi5zsoIEg7JeQ65+sLlxuICAgIGlmIChyZXEuaW1hZ2VHZW5lcmF0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgSW1hZ2VHZW5lcmF0aW9uRXJyb3IoXCJnYXRlXCIsIFwiaW1hZ2UgZ2VuZXJhdGlvbiBpcyBub3Qgc3VwcG9ydGVkIG9uIHRoZSBzdHJlYW1pbmcgcGF0aFwiKTtcbiAgICB9XG4gICAgY29uc3QgZXhjbHVkZWRUb2tlbklkcyA9IG5ldyBTZXQ8bnVtYmVyPigpO1xuICAgIGNvbnN0IHJldXNlV29ya2VyID0gYXdhaXQgdGhpcy5hY3F1aXJlUmV1c2VXb3JrZXIocmVxLCBleGNsdWRlZFRva2VuSWRzKTtcbiAgICBpZiAocmV1c2VXb3JrZXIpIHtcbiAgICAgIGxvZ2dlci5pbmZvKGDihrsgJHtyZXVzZVdvcmtlci50b2tlbk5hbWV9WyR7cmV1c2VXb3JrZXIudG9rZW5JZH1dIChyZXVzZSB0aHJlYWQsIFtzdHJlYW1dKWApO1xuICAgICAgcmV0dXJuIHRoaXMuZXhlY3V0ZUFuZFJlbGVhc2UocmV1c2VXb3JrZXIsICh3KSA9PlxuICAgICAgICB0aGlzLmV4ZWN1dGVTdHJlYW1UdXJuKHcsIHJlcSwgY2IsIHJlcS5yZXVzZSEudGhyZWFkSWQpLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCB3b3JrZXIgPSBhd2FpdCB0aGlzLmFjcXVpcmVJZGxlV29ya2VyKGV4Y2x1ZGVkVG9rZW5JZHMpO1xuICAgIGlmICh3b3JrZXIpIHtcbiAgICAgIGxvZ2dlci5pbmZvKGDihpIgJHt3b3JrZXIudG9rZW5OYW1lfVske3dvcmtlci50b2tlbklkfV0gKG1vZGVsOiAke3JlcS5tb2RlbH0sIFtzdHJlYW1dKWApO1xuICAgICAgcmV0dXJuIHRoaXMuZXhlY3V0ZUFuZFJlbGVhc2Uod29ya2VyLCAodykgPT4gdGhpcy5leGVjdXRlU3RyZWFtVHVybih3LCByZXEsIGNiKSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmVucXVldWUoKHcpID0+IHtcbiAgICAgIGxvZ2dlci5pbmZvKGDihpIgJHt3LnRva2VuTmFtZX1bJHt3LnRva2VuSWR9XSAobW9kZWw6ICR7cmVxLm1vZGVsfSwgW3N0cmVhbV0sIHF1ZXVlZClgKTtcbiAgICAgIHJldHVybiB0aGlzLmV4ZWN1dGVTdHJlYW1UdXJuKHcsIHJlcSwgY2IpO1xuICAgIH0sIGV4Y2x1ZGVkVG9rZW5JZHMpO1xuICB9XG5cbiAgLy8gcmV1c2Ug7KKM7ZGc6rCAIOycoO2aqO2VmOuptCDqt7ggd29ya2VyIOulvCBidXN5IOygkOycoO2VtCDrsJjtmZguIOyXhuqxsOuCmCDtj7TrsLEg64yA7IOB7J2066m0IG51bGwuXG4gIC8vIO2PtOuwsSDsgqzsnKA6IOq4sOuKpSBvZmYgLyDsooztkZwg7JeG7J2MIC8gd29ya2VyIOu2gOyerMK37KO97J2MIC8gZXBvY2gg67aI7J287LmYKHJlc3RhcnQpIC8gdGhyZWFkIOyGjOupuCAvXG4gIC8vICAgICAgICAgICAgYnVzeSDrjIDquLAg7YOA7J6E7JWE7JuDLiBudWxsIOuwmO2ZmCDsi5wg7Zi47Lac67aA64qUIOyDiCB0aHJlYWQg6rK966Gc66GcIOynhO2WiS5cbiAgYXN5bmMgYWNxdWlyZVJldXNlV29ya2VyKFxuICAgIHJlcTogR2VuZXJhdGVSZXF1ZXN0LFxuICAgIGV4Y2x1ZGVkVG9rZW5JZHMgPSBuZXcgU2V0PG51bWJlcj4oKSxcbiAgKTogUHJvbWlzZTxDb2RleEFwcFNlcnZlcldvcmtlciB8IG51bGw+IHtcbiAgICAvLyDsnbTrr7jsp4Ag7JqU7LKt7J2AIO2VreyDgSBjb2xkIHRocmVhZChSOCk6IOyerOyCrOyaqSDsooztkZzqsIAg7J6I7Ja064+EIOqxtOuEiOubtOuLpC5cbiAgICAvLyBiYXNlNjQg6rCAIHRocmVhZCDrqZTrqqjrpqzCt+y6kOyLnCBwcmVmaXgg7JeQIOyDgeyjvO2VmOuKlCDqsoPsnYQg66eJ64qU64ukLlxuICAgIGlmIChyZXEuaW1hZ2VHZW5lcmF0aW9uKSByZXR1cm4gbnVsbDtcbiAgICBpZiAoIVRIUkVBRF9SRVVTRV9FTkFCTEVEIHx8ICFyZXEucmV1c2UpIHJldHVybiBudWxsO1xuICAgIGNvbnN0IHsgd29ya2VySWQsIHRocmVhZElkLCBlcG9jaCB9ID0gcmVxLnJldXNlO1xuXG4gICAgY29uc3Qgd29ya2VyID0gdGhpcy5maW5kV29ya2VyQnlJZCh3b3JrZXJJZCk7XG4gICAgaWYgKCF3b3JrZXIgfHwgIXdvcmtlci5pc1JlYWR5IHx8ICF3b3JrZXIuYWN0aXZlKSByZXR1cm4gbnVsbDtcbiAgICBpZiAod29ya2VyLmVwb2NoICE9PSBlcG9jaCkgcmV0dXJuIG51bGw7XG4gICAgaWYgKCF3b3JrZXIuaGFzVGhyZWFkKHRocmVhZElkKSkgcmV0dXJuIG51bGw7XG4gICAgaWYgKCEoYXdhaXQgdGhpcy5pc1Rva2VuUXVvdGFFbGlnaWJsZSh3b3JrZXIudG9rZW5JZCwgd29ya2VyLnRva2VuTmFtZSwgZXhjbHVkZWRUb2tlbklkcykpKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCBkZWFkbGluZSA9IERhdGUubm93KCkgKyBSRVVTRV9XT1JLRVJfV0FJVF9NUztcbiAgICBmb3IgKDs7KSB7XG4gICAgICAvLyByZXN0YXJ0KGVwb2NoIOuzgOqyvSkgLyB0aHJlYWQg7IaM66m47J20IOuMgOq4sCDspJHsl5Ag67Cc7IOd7ZWY66m0IO2PtOuwsS5cbiAgICAgIGlmICh3b3JrZXIuZXBvY2ggIT09IGVwb2NoIHx8ICF3b3JrZXIuaGFzVGhyZWFkKHRocmVhZElkKSkgcmV0dXJuIG51bGw7XG4gICAgICBpZiAod29ya2VyLnRyeUFjcXVpcmVUdXJuKCkpIHJldHVybiB3b3JrZXI7XG4gICAgICBpZiAoRGF0ZS5ub3coKSA+PSBkZWFkbGluZSkgcmV0dXJuIG51bGw7XG4gICAgICBhd2FpdCBzbGVlcChSRVVTRV9XT1JLRVJfUE9MTF9NUyk7XG4gICAgfVxuICB9XG5cbiAgZmluZFdvcmtlckJ5SWQod29ya2VySWQ6IG51bWJlcik6IENvZGV4QXBwU2VydmVyV29ya2VyIHwgbnVsbCB7XG4gICAgZm9yIChjb25zdCB3b3JrZXJzIG9mIHRoaXMud29ya2VyUG9vbC52YWx1ZXMoKSkge1xuICAgICAgZm9yIChjb25zdCB3IG9mIHdvcmtlcnMpIHtcbiAgICAgICAgaWYgKG1ha2VXb3JrZXJJZCh3LnRva2VuSWQsIHcud29ya2VySW5kZXgpID09PSB3b3JrZXJJZCkgcmV0dXJuIHc7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgYXN5bmMgaW50ZXJydXB0V29ya2VyVHVybih0aHJlYWRJZDogc3RyaW5nLCB0dXJuSWQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGFsbFdvcmtlcnMgPSBbLi4udGhpcy53b3JrZXJQb29sLnZhbHVlcygpXS5mbGF0KCkuZmlsdGVyKCh3KSA9PiB3LmlzUmVhZHkpO1xuICAgIGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChhbGxXb3JrZXJzLm1hcCgodykgPT4gdy5pbnRlcnJ1cHRUdXJuKHRocmVhZElkLCB0dXJuSWQpKSk7XG4gIH1cblxuICAvLyDilIDilIAgV29ya2VyIHNlbGVjdGlvbiDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbiAgLy8gIOq4sOuzuCByb3VuZC1yb2JpblxuICAvLyBUT0RPOiDstpTtm4Qg64uk66W4IOyVjOqzoOumrOymmOycvOuhnCDrs4Dqsr0g6rCA64ql7ZWY6rKMIOyngOybkFxuICBhc3luYyBhY3F1aXJlSWRsZVdvcmtlcihcbiAgICBleGNsdWRlZFRva2VuSWRzID0gbmV3IFNldDxudW1iZXI+KCksXG4gICk6IFByb21pc2U8Q29kZXhBcHBTZXJ2ZXJXb3JrZXIgfCBudWxsPiB7XG4gICAgY29uc3QgZWxpZ2liaWxpdHkgPSBhd2FpdCB0aGlzLnJlc29sdmVUb2tlbkVsaWdpYmlsaXR5KGV4Y2x1ZGVkVG9rZW5JZHMpO1xuICAgIGlmIChlbGlnaWJpbGl0eS5yZWFkeUFjdGl2ZVRva2VuSWRzLnNpemUgPT09IDApIHJldHVybiBudWxsO1xuICAgIGlmIChlbGlnaWJpbGl0eS5lbGlnaWJsZVRva2VuSWRzLnNpemUgPT09IDApIHRoaXMudGhyb3dRdW90YVRocmVzaG9sZEV4Y2VlZGVkKGVsaWdpYmlsaXR5KTtcblxuICAgIGNvbnN0IGFsbFdvcmtlcnMgPSB0aGlzLmdldEFsbFJlYWR5QWN0aXZlV29ya2VycygpLmZpbHRlcigodykgPT5cbiAgICAgIGVsaWdpYmlsaXR5LmVsaWdpYmxlVG9rZW5JZHMuaGFzKHcudG9rZW5JZCksXG4gICAgKTtcbiAgICBpZiAoYWxsV29ya2Vycy5sZW5ndGggPT09IDApIHJldHVybiBudWxsO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYWxsV29ya2Vycy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgdyA9IGFsbFdvcmtlcnNbKHRoaXMucnJDdXJzb3IgKyBpKSAlIGFsbFdvcmtlcnMubGVuZ3RoXSE7XG4gICAgICBpZiAody50cnlBY3F1aXJlVHVybigpKSB7XG4gICAgICAgIHRoaXMucnJDdXJzb3IgPSAodGhpcy5yckN1cnNvciArIGkgKyAxKSAlIGFsbFdvcmtlcnMubGVuZ3RoO1xuICAgICAgICByZXR1cm4gdztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBnZXRBbGxSZWFkeUFjdGl2ZVdvcmtlcnMoKTogQ29kZXhBcHBTZXJ2ZXJXb3JrZXJbXSB7XG4gICAgcmV0dXJuIFsuLi50aGlzLndvcmtlclBvb2wudmFsdWVzKCldLmZsYXQoKS5maWx0ZXIoKHcpID0+IHcuaXNSZWFkeSAmJiB3LmFjdGl2ZSk7XG4gIH1cblxuICAvLyDilIDilIAgUXVldWUg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgYXN5bmMgZW5xdWV1ZTxUPihcbiAgICBleGVjdXRlOiAod29ya2VyOiBDb2RleEFwcFNlcnZlcldvcmtlcikgPT4gUHJvbWlzZTxUPixcbiAgICBleGNsdWRlZFRva2VuSWRzID0gbmV3IFNldDxudW1iZXI+KCksXG4gICk6IFByb21pc2U8VD4ge1xuICAgIGNvbnN0IGVsaWdpYmlsaXR5ID0gYXdhaXQgdGhpcy5yZXNvbHZlVG9rZW5FbGlnaWJpbGl0eShleGNsdWRlZFRva2VuSWRzKTtcbiAgICBpZiAoZWxpZ2liaWxpdHkucmVhZHlBY3RpdmVUb2tlbklkcy5zaXplID09PSAwKSB0aHJvdyBuZXcgRXJyb3IoXCJOT19PUEVOQUlfV09SS0VSU1wiKTtcbiAgICBpZiAoZWxpZ2liaWxpdHkuZWxpZ2libGVUb2tlbklkcy5zaXplID09PSAwKSB0aGlzLnRocm93UXVvdGFUaHJlc2hvbGRFeGNlZWRlZChlbGlnaWJpbGl0eSk7XG4gICAgaWYgKHRoaXMucXVldWUubGVuZ3RoID49IE1BWF9RVUVVRV9TSVpFKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTRVJWRVJfQlVTWVwiKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2U8VD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgaXRlbTogUXVldWVJdGVtID0ge1xuICAgICAgICByZXNvbHZlOiAod29ya2VyKSA9PiB7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KGl0ZW0udGltZXIpO1xuICAgICAgICAgIGl0ZW0uYWJvcnRDbGVhbnVwPy4oKTtcbiAgICAgICAgICBQcm9taXNlLnJlc29sdmUoKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4gdGhpcy5leGVjdXRlQW5kUmVsZWFzZSh3b3JrZXIsIGV4ZWN1dGUpKVxuICAgICAgICAgICAgLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgICAgfSxcbiAgICAgICAgcmVqZWN0OiAoZXJyKSA9PiB7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KGl0ZW0udGltZXIpO1xuICAgICAgICAgIGl0ZW0uYWJvcnRDbGVhbnVwPy4oKTtcbiAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgfSxcbiAgICAgICAgdGltZXI6IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgIHRoaXMucmVtb3ZlRnJvbVF1ZXVlKGl0ZW0pO1xuICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoXCJTRVJWRVJfQlVTWVwiKSk7XG4gICAgICAgIH0sIFFVRVVFX1RJTUVPVVRfTVMpLFxuICAgICAgICBleGNsdWRlZFRva2VuSWRzOiBuZXcgU2V0KGV4Y2x1ZGVkVG9rZW5JZHMpLFxuICAgICAgfTtcblxuICAgICAgdGhpcy5xdWV1ZS5wdXNoKGl0ZW0pO1xuICAgIH0pO1xuICB9XG5cbiAgcmVtb3ZlRnJvbVF1ZXVlKGl0ZW06IFF1ZXVlSXRlbSk6IHZvaWQge1xuICAgIGNsZWFyVGltZW91dChpdGVtLnRpbWVyKTtcbiAgICBpdGVtLmFib3J0Q2xlYW51cD8uKCk7XG4gICAgY29uc3QgaWR4ID0gdGhpcy5xdWV1ZS5pbmRleE9mKGl0ZW0pO1xuICAgIGlmIChpZHggIT09IC0xKSB0aGlzLnF1ZXVlLnNwbGljZShpZHgsIDEpO1xuICB9XG5cbiAgcmVqZWN0QWxsUXVldWVkKHJlYXNvbjogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgZXJyID0gbmV3IEVycm9yKHJlYXNvbik7XG4gICAgdGhpcy5xdWV1ZS5mb3JFYWNoKChpdGVtKSA9PiB7XG4gICAgICBjbGVhclRpbWVvdXQoaXRlbS50aW1lcik7XG4gICAgICBpdGVtLmFib3J0Q2xlYW51cD8uKCk7XG4gICAgICBpdGVtLnJlamVjdChlcnIpO1xuICAgIH0pO1xuICAgIHRoaXMucXVldWUgPSBbXTtcbiAgfVxuXG4gIGFzeW5jIGRyYWluUXVldWUocmVsZWFzZWRXb3JrZXI/OiBDb2RleEFwcFNlcnZlcldvcmtlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLmRyYWluaW5nKSB7XG4gICAgICB0aGlzLmRyYWluQWdhaW4gPSB0cnVlO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuZHJhaW5pbmcgPSB0cnVlO1xuICAgIGxldCB3b3JrZXIgPSByZWxlYXNlZFdvcmtlcjtcbiAgICB0cnkge1xuICAgICAgZG8ge1xuICAgICAgICB0aGlzLmRyYWluQWdhaW4gPSBmYWxzZTtcbiAgICAgICAgYXdhaXQgdGhpcy5kcmFpblF1ZXVlT25jZSh3b3JrZXIpO1xuICAgICAgICB3b3JrZXIgPSB1bmRlZmluZWQ7XG4gICAgICB9IHdoaWxlICh0aGlzLmRyYWluQWdhaW4pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxvZ2dlci53YXJuKGBkcmFpblF1ZXVlIGZhaWxlZDogJHsoZSBhcyBFcnJvcikubWVzc2FnZX1gKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgdGhpcy5kcmFpbmluZyA9IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZHJhaW5RdWV1ZU9uY2UocmVsZWFzZWRXb3JrZXI/OiBDb2RleEFwcFNlcnZlcldvcmtlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmIChcbiAgICAgIHJlbGVhc2VkV29ya2VyICYmXG4gICAgICB0aGlzLnF1ZXVlLmxlbmd0aCA+IDAgJiZcbiAgICAgIHJlbGVhc2VkV29ya2VyLmlzUmVhZHkgJiZcbiAgICAgIHJlbGVhc2VkV29ya2VyLmFjdGl2ZSAmJlxuICAgICAgKGF3YWl0IHRoaXMuaXNXb3JrZXJFbGlnaWJsZUZvclF1ZXVlSXRlbShyZWxlYXNlZFdvcmtlciwgdGhpcy5xdWV1ZVswXSEpKSAmJlxuICAgICAgcmVsZWFzZWRXb3JrZXIudHJ5QWNxdWlyZVR1cm4oKVxuICAgICkge1xuICAgICAgY29uc3QgbmV4dCA9IHRoaXMucXVldWUuc2hpZnQoKSE7XG4gICAgICBuZXh0LnJlc29sdmUocmVsZWFzZWRXb3JrZXIpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHdoaWxlICh0aGlzLnF1ZXVlLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IG5leHQgPSB0aGlzLnF1ZXVlWzBdITtcbiAgICAgIGxldCB3b3JrZXI6IENvZGV4QXBwU2VydmVyV29ya2VyIHwgbnVsbDtcbiAgICAgIHRyeSB7XG4gICAgICAgIHdvcmtlciA9IGF3YWl0IHRoaXMuYWNxdWlyZUlkbGVXb3JrZXIobmV4dC5leGNsdWRlZFRva2VuSWRzKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiBRdW90YVRocmVzaG9sZEV4Y2VlZGVkRXJyb3IpIHtcbiAgICAgICAgICB0aGlzLnF1ZXVlLnNoaWZ0KCk7XG4gICAgICAgICAgbmV4dC5yZWplY3QoZSk7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICAgIGlmICghd29ya2VyKSBicmVhaztcbiAgICAgIHRoaXMucXVldWUuc2hpZnQoKTtcbiAgICAgIG5leHQucmVzb2x2ZSh3b3JrZXIpO1xuICAgIH1cbiAgfVxuXG4gIC8vIOKUgOKUgCBFeGVjdXRpb24g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgYXN5bmMgZXhlY3V0ZUFuZFJlbGVhc2U8VD4oXG4gICAgd29ya2VyOiBDb2RleEFwcFNlcnZlcldvcmtlcixcbiAgICBleGVjdXRlOiAod29ya2VyOiBDb2RleEFwcFNlcnZlcldvcmtlcikgPT4gUHJvbWlzZTxUPixcbiAgKTogUHJvbWlzZTxUPiB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBhd2FpdCBleGVjdXRlKHdvcmtlcik7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHdvcmtlci5yZWxlYXNlVHVybigpO1xuICAgICAgdGhpcy5yZXF1ZXN0RHJhaW5RdWV1ZSh3b3JrZXIpO1xuICAgIH1cbiAgfVxuXG4gIC8vIHJldXNlVGhyZWFkSWQg6rCAIOyeiOycvOuptCDquLDsobQgdGhyZWFkIOyXkCBkZWx0YShyZXVzZUlucHV0KeunjCwg7JeG7Jy866m0IOyDiCB0aHJlYWQg7JeQIOyghOyytFxuICAvLyBwcm9tcHQoY29sZElucHV0KSArIGhpc3RvcnkgaW5qZWN0LiByZXVzZSDqsIAgZGlzcGF0Y2hlciDri6jsl5DshJwg7Y+067Cx65CY66m0IO2bhOyekOuhnCDrlqjslrTsp4Tri6QuXG4gIHByaXZhdGUgYnVpbGRUdXJuUmVxdWVzdChyZXE6IEdlbmVyYXRlUmVxdWVzdCwgcmV1c2VUaHJlYWRJZD86IHN0cmluZyk6IFR1cm5SZXF1ZXN0IHtcbiAgICBjb25zdCByZXVzaW5nID0gcmV1c2VUaHJlYWRJZCAhPT0gdW5kZWZpbmVkO1xuICAgIHJldHVybiB7XG4gICAgICBpbnB1dDogcmV1c2luZyAmJiByZXEucmV1c2VJbnB1dCA/IHJlcS5yZXVzZUlucHV0IDogcmVxLmNvbGRJbnB1dCxcbiAgICAgIGhpc3Rvcnk6IHJldXNpbmcgPyB1bmRlZmluZWQgOiByZXEuY29sZEhpc3RvcnksXG4gICAgICBkZXZlbG9wZXJJbnN0cnVjdGlvbnM6IHJlcS5zeXN0ZW1Qcm9tcHQsXG4gICAgICBvdXRwdXRTY2hlbWE6IHJlcS5vdXRwdXRTY2hlbWEsXG4gICAgICBlZmZvcnQ6IHJlcS5lZmZvcnQgPz8gREVGQVVMVF9FRkZPUlQsXG4gICAgICBtb2RlbDogcmVxLm1vZGVsLFxuICAgICAgdmVyYm9zaXR5OiByZXEudmVyYm9zaXR5LFxuICAgICAgcmVhc29uaW5nU3VtbWFyeTogcmVxLnJlYXNvbmluZ1N1bW1hcnksXG4gICAgICBzZXJ2aWNlVGllcjogcmVxLnNlcnZpY2VUaWVyLFxuICAgICAgaW1hZ2VHZW5lcmF0aW9uOiByZXEuaW1hZ2VHZW5lcmF0aW9uLFxuICAgICAgaW1hZ2VHZW5lcmF0aW9uT3B0aW9uczogcmVxLmltYWdlR2VuZXJhdGlvbk9wdGlvbnMsXG4gICAgfTtcbiAgfVxuXG4gIGFzeW5jIGV4ZWN1dGVUdXJuKFxuICAgIHdvcmtlcjogQ29kZXhBcHBTZXJ2ZXJXb3JrZXIsXG4gICAgcmVxOiBHZW5lcmF0ZVJlcXVlc3QsXG4gICAgcmV1c2VUaHJlYWRJZD86IHN0cmluZyxcbiAgKTogUHJvbWlzZTxHZW5lcmF0ZVJlc3VsdD4ge1xuICAgIC8vIOydtOuvuOyngCDsmpTssq0g7IKs7KCEIOqyjOydtO2KuChSNSk6IOuwsOygleuQnCB3b3JrZXIg7J2YIGNhcGFiaWxpdHkgKyDsoIHsmqkg66qo6424IOupgO2LsOuqqOuLrC5cbiAgICAvLyDrtojstqnsobHsnbTrqbQgdHVybiDsnYQg7Iuk7ZaJ7ZWY7KeAIOyViuqzoCDrqoXsi5zsoIEg7JeQ65+sLlxuICAgIGlmIChyZXEuaW1hZ2VHZW5lcmF0aW9uKSB7XG4gICAgICBjb25zdCByZWFzb24gPSBhd2FpdCB3b3JrZXIuY2hlY2tJbWFnZUdlbmVyYXRpb25TdXBwb3J0KHJlcS5tb2RlbCk7XG4gICAgICBpZiAocmVhc29uKSB0aHJvdyBuZXcgSW1hZ2VHZW5lcmF0aW9uRXJyb3IoXCJnYXRlXCIsIHJlYXNvbik7XG4gICAgfVxuXG4gICAgY29uc3QgdHVyblJlcSA9IHRoaXMuYnVpbGRUdXJuUmVxdWVzdChyZXEsIHJldXNlVGhyZWFkSWQpO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHdvcmtlci5leGVjdXRlVHVybih0dXJuUmVxLCByZXVzZVRocmVhZElkKTtcblxuICAgIC8vIOydtOuvuOyngCAw6rCcIOyLpO2MqCDrtoTrpZgoUjYpOiB0b29sIOuvuO2YuOy2nCjsnqzsi5zrj4Qg66y07J21KSB2cyDsi5zrj4Qg7ZuEIOuvuOyZhOyEsSjsnqzsi5zrj4Qg7ZuE67O0KS5cbiAgICBpZiAocmVxLmltYWdlR2VuZXJhdGlvbiAmJiAoIXJlc3VsdC5pbWFnZXMgfHwgcmVzdWx0LmltYWdlcy5sZW5ndGggPT09IDApKSB7XG4gICAgICB0aHJvdyByZXN1bHQuaW1hZ2VBdHRlbXB0ZWRcbiAgICAgICAgPyBuZXcgSW1hZ2VHZW5lcmF0aW9uRXJyb3IoXCJpbmNvbXBsZXRlXCIsIFwiaW1hZ2UgdG9vbCByYW4gYnV0IHByb2R1Y2VkIG5vIGNvbXBsZXRlZCBpbWFnZVwiKVxuICAgICAgICA6IG5ldyBJbWFnZUdlbmVyYXRpb25FcnJvcihcIm5vdF9jYWxsZWRcIiwgXCJtb2RlbCBkaWQgbm90IGNhbGwgdGhlIGltYWdlX2dlbmVyYXRpb24gdG9vbFwiKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgdGV4dDogcmVzdWx0LnRleHQsXG4gICAgICB0b2tlbk5hbWU6IHdvcmtlci50b2tlbk5hbWUsXG4gICAgICB1c2FnZTogcmVzdWx0LnVzYWdlLFxuICAgICAgZHVyYXRpb25NczogcmVzdWx0LmR1cmF0aW9uTXMsXG4gICAgICB0dGZ0TXM6IHJlc3VsdC50dGZ0TXMsXG4gICAgICBtb2RlbDogcmVzdWx0Lm1vZGVsLFxuICAgICAgdGhyZWFkQ29vcmQ6IHtcbiAgICAgICAgd29ya2VySWQ6IG1ha2VXb3JrZXJJZCh3b3JrZXIudG9rZW5JZCwgd29ya2VyLndvcmtlckluZGV4KSxcbiAgICAgICAgdGhyZWFkSWQ6IHJlc3VsdC50aHJlYWRJZCxcbiAgICAgICAgZXBvY2g6IHdvcmtlci5lcG9jaCxcbiAgICAgIH0sXG4gICAgICBpbWFnZXM6IHJlc3VsdC5pbWFnZXMsXG4gICAgfTtcbiAgfVxuXG4gIGFzeW5jIGV4ZWN1dGVTdHJlYW1UdXJuKFxuICAgIHdvcmtlcjogQ29kZXhBcHBTZXJ2ZXJXb3JrZXIsXG4gICAgcmVxOiBHZW5lcmF0ZVJlcXVlc3QsXG4gICAgY2I6IEdlbmVyYXRlU3RyZWFtQ2FsbGJhY2tzLFxuICAgIHJldXNlVGhyZWFkSWQ/OiBzdHJpbmcsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHR1cm5SZXEgPSB0aGlzLmJ1aWxkVHVyblJlcXVlc3QocmVxLCByZXVzZVRocmVhZElkKTtcbiAgICAvLyB3b3JrZXIg7J2YIFR1cm5SZXN1bHQg7JeQIHRva2VuTmFtZS90aHJlYWRDb29yZCDrpbwg67aZ7JesIOyDgeychChHZW5lcmF0ZVJlc3VsdCnroZwg7Jis66aw64ukLlxuICAgIC8vIHRocmVhZElkIOuKlCDsg4ggdGhyZWFkIOuptCBvblRocmVhZElkIOuhnCDtmZXsoJXrkJjrr4DroZwg66+466asIOuztOq0gO2VtCDrkZDqs6Agb25Db21wbGV0ZSDrlYwg7J2964qU64ukLlxuICAgIGxldCByZXNvbHZlZFRocmVhZElkID0gcmV1c2VUaHJlYWRJZCA/PyBcIlwiO1xuICAgIGNvbnN0IHdyYXBwZWRDYjogU3RyZWFtQ2FsbGJhY2tzID0ge1xuICAgICAgLi4uY2IsXG4gICAgICBvblRocmVhZElkOiAodGhyZWFkSWQpID0+IHtcbiAgICAgICAgcmVzb2x2ZWRUaHJlYWRJZCA9IHRocmVhZElkO1xuICAgICAgICBjYi5vblRocmVhZElkPy4odGhyZWFkSWQpO1xuICAgICAgfSxcbiAgICAgIG9uQ29tcGxldGU6IChyZXN1bHQpID0+IHtcbiAgICAgICAgY2Iub25Db21wbGV0ZSh7XG4gICAgICAgICAgLi4ucmVzdWx0LFxuICAgICAgICAgIHRva2VuTmFtZTogd29ya2VyLnRva2VuTmFtZSxcbiAgICAgICAgICB0aHJlYWRDb29yZDoge1xuICAgICAgICAgICAgd29ya2VySWQ6IG1ha2VXb3JrZXJJZCh3b3JrZXIudG9rZW5JZCwgd29ya2VyLndvcmtlckluZGV4KSxcbiAgICAgICAgICAgIHRocmVhZElkOiByZXNvbHZlZFRocmVhZElkLFxuICAgICAgICAgICAgZXBvY2g6IHdvcmtlci5lcG9jaCxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH0sXG4gICAgfTtcbiAgICBhd2FpdCB3b3JrZXIuZXhlY3V0ZVR1cm5TdHJlYW0odHVyblJlcSwgd3JhcHBlZENiLCByZXVzZVRocmVhZElkKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBTcGF3biDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBhc3luYyBzcGF3bldvcmtlcnMoXG4gICAgdG9rZW5JZDogbnVtYmVyLFxuICAgIHRva2VuTmFtZTogc3RyaW5nLFxuICAgIGNyZWRlbnRpYWxzOiBPcGVuQUlDcmVkZW50aWFscyxcbiAgICBxdW90YVRocmVzaG9sZD86IG51bWJlciB8IG51bGwsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuc2V0VG9rZW5NZXRhZGF0YSh0b2tlbklkLCB0b2tlbk5hbWUsIHF1b3RhVGhyZXNob2xkKTtcbiAgICBjb25zdCB3b3JrZXJzOiBDb2RleEFwcFNlcnZlcldvcmtlcltdID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBXT1JLRVJTX1BFUl9UT0tFTjsgaSsrKSB7XG4gICAgICBpZiAoaSA+IDApIGF3YWl0IHNsZWVwKFNQQVdOX0lOVEVSVkFMX01TKTtcbiAgICAgIGNvbnN0IHdvcmtlciA9IGF3YWl0IHRoaXMuc3Bhd25TaW5nbGVXb3JrZXIodG9rZW5JZCwgdG9rZW5OYW1lLCBjcmVkZW50aWFscywgaSk7XG4gICAgICBpZiAod29ya2VyKSB3b3JrZXJzLnB1c2god29ya2VyKTtcbiAgICB9XG4gICAgaWYgKHdvcmtlcnMubGVuZ3RoID4gMCkgdGhpcy53b3JrZXJQb29sLnNldCh0b2tlbklkLCB3b3JrZXJzKTtcbiAgfVxuXG4gIGFzeW5jIHNwYXduU2luZ2xlV29ya2VyKFxuICAgIHRva2VuSWQ6IG51bWJlcixcbiAgICB0b2tlbk5hbWU6IHN0cmluZyxcbiAgICBjcmVkZW50aWFsczogT3BlbkFJQ3JlZGVudGlhbHMsXG4gICAgd29ya2VySW5kZXg6IG51bWJlcixcbiAgKTogUHJvbWlzZTxDb2RleEFwcFNlcnZlcldvcmtlciB8IG51bGw+IHtcbiAgICBjb25zdCB3b3JrZXIgPSBuZXcgQ29kZXhBcHBTZXJ2ZXJXb3JrZXIoe1xuICAgICAgdG9rZW5JZCxcbiAgICAgIHRva2VuTmFtZSxcbiAgICAgIGFjY2Vzc1Rva2VuOiBjcmVkZW50aWFscy5hY2Nlc3NUb2tlbixcbiAgICAgIGFjY291bnRJZDogY3JlZGVudGlhbHMuYWNjb3VudElkLFxuICAgICAgcGxhblR5cGU6IGNyZWRlbnRpYWxzLnBsYW5UeXBlLFxuICAgICAgd29ya2VySW5kZXgsXG4gICAgfSk7XG5cbiAgICB3b3JrZXIub25SZWFkeSA9ICgpID0+IHRoaXMucmVxdWVzdERyYWluUXVldWUoKTtcblxuICAgIHdvcmtlci5zZXRTZXJ2ZXJSZXF1ZXN0SGFuZGxlcihhc3luYyAobWV0aG9kKSA9PiB7XG4gICAgICBpZiAobWV0aG9kID09PSBcImFjY291bnQvY2hhdGdwdEF1dGhUb2tlbnMvcmVmcmVzaFwiKSB7XG4gICAgICAgIHJldHVybiBoYW5kbGVDaGF0Z3B0QXV0aFRva2Vuc1JlZnJlc2godG9rZW5JZCk7XG4gICAgICB9XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuaGFuZGxlZCBzZXJ2ZXItcmVxdWVzdDogJHttZXRob2R9YCk7XG4gICAgfSk7XG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgd29ya2VyLmluaXRpYWxpemUoKTtcbiAgICAgIGxvZ2dlci5pbmZvKGB3b3JrZXIgc3Bhd25lZDogJHt0b2tlbk5hbWV9WyR7d29ya2VySW5kZXh9XWApO1xuICAgICAgcmV0dXJuIHdvcmtlcjtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBsb2dnZXIud2Fybihgd29ya2VyIHNwYXduIGZhaWxlZDogJHt0b2tlbk5hbWV9WyR7d29ya2VySW5kZXh9XTogJHsoZSBhcyBFcnJvcikubWVzc2FnZX1gKTtcbiAgICAgIGF3YWl0IHdvcmtlci5raWxsKCkuY2F0Y2goKCkgPT4ge30pO1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgLy8g4pSA4pSAIFJhdGUgbGltaXRzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIHJhdGVMaW1pdHNDYWNoZSA9IG5ldyBNYXA8bnVtYmVyLCB7IGRhdGE6IEdldEFjY291bnRSYXRlTGltaXRzUmVzcG9uc2U7IGNhY2hlZEF0OiBudW1iZXIgfT4oKTtcbiAgc3RhdGljIHJlYWRvbmx5IFJBVEVfTElNSVRTX0NBQ0hFX1RUTCA9IDYwXzAwMDtcblxuICBhc3luYyBnZXRSYXRlTGltaXRzQnlUb2tlbklkKHRva2VuSWQ6IG51bWJlcik6IFByb21pc2U8T3BlbkFJUmF0ZUxpbWl0c1dpdGhNZXRhPiB7XG4gICAgY29uc3QgY2FjaGVkID0gdGhpcy5yYXRlTGltaXRzQ2FjaGUuZ2V0KHRva2VuSWQpO1xuICAgIGlmIChjYWNoZWQgJiYgRGF0ZS5ub3coKSAtIGNhY2hlZC5jYWNoZWRBdCA8IE9wZW5BSURpc3BhdGNoZXIuUkFURV9MSU1JVFNfQ0FDSEVfVFRMKSB7XG4gICAgICByZXR1cm4gY2FjaGVkO1xuICAgIH1cblxuICAgIGNvbnN0IHdvcmtlciA9ICh0aGlzLndvcmtlclBvb2wuZ2V0KHRva2VuSWQpID8/IFtdKS5maW5kKCh3KSA9PiB3LmlzUmVhZHkpO1xuICAgIGlmICghd29ya2VyKSB0aHJvdyBuZXcgRXJyb3IoXCJubyByZWFkeSBvcGVuYWkgd29ya2Vyc1wiKTtcbiAgICBjb25zdCBkYXRhID0gKGF3YWl0IHdvcmtlci5nZXRSYXRlTGltaXRzKCkpIGFzIEdldEFjY291bnRSYXRlTGltaXRzUmVzcG9uc2U7XG4gICAgY29uc3QgZW50cnkgPSB7IGRhdGEsIGNhY2hlZEF0OiBEYXRlLm5vdygpIH07XG4gICAgdGhpcy5yYXRlTGltaXRzQ2FjaGUuc2V0KHRva2VuSWQsIGVudHJ5KTtcbiAgICByZXR1cm4gZW50cnk7XG4gIH1cblxuICBwcml2YXRlIHJlcXVlc3REcmFpblF1ZXVlKHJlbGVhc2VkV29ya2VyPzogQ29kZXhBcHBTZXJ2ZXJXb3JrZXIpOiB2b2lkIHtcbiAgICB2b2lkIHRoaXMuZHJhaW5RdWV1ZShyZWxlYXNlZFdvcmtlcikuY2F0Y2goKGUpID0+XG4gICAgICBsb2dnZXIud2FybihgZHJhaW5RdWV1ZSBmYWlsZWQ6ICR7KGUgYXMgRXJyb3IpLm1lc3NhZ2V9YCksXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgc2V0VG9rZW5NZXRhZGF0YShpZDogbnVtYmVyLCBuYW1lOiBzdHJpbmcsIHF1b3RhVGhyZXNob2xkPzogbnVtYmVyIHwgbnVsbCk6IHZvaWQge1xuICAgIHRoaXMudG9rZW5NZXRhZGF0YS5zZXQoaWQsIHsgbmFtZSwgcXVvdGFUaHJlc2hvbGQgfSk7XG4gIH1cblxuICBwcml2YXRlIGdldFF1b3RhVGhyZXNob2xkKHRva2VuSWQ6IG51bWJlcik6IG51bWJlciB8IG51bGwgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLnRva2VuTWV0YWRhdGEuZ2V0KHRva2VuSWQpPy5xdW90YVRocmVzaG9sZDtcbiAgfVxuXG4gIHByaXZhdGUgaGFzUXVvdGFUaHJlc2hvbGQodG9rZW5JZDogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgY29uc3QgdGhyZXNob2xkID0gdGhpcy5nZXRRdW90YVRocmVzaG9sZCh0b2tlbklkKTtcbiAgICByZXR1cm4gdGhyZXNob2xkICE9PSB1bmRlZmluZWQgJiYgdGhyZXNob2xkICE9PSBudWxsO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyByZXNvbHZlVG9rZW5FbGlnaWJpbGl0eShleGNsdWRlZFRva2VuSWRzOiBTZXQ8bnVtYmVyPik6IFByb21pc2U8VG9rZW5FbGlnaWJpbGl0eT4ge1xuICAgIGNvbnN0IHdvcmtlcnMgPSB0aGlzLmdldEFsbFJlYWR5QWN0aXZlV29ya2VycygpO1xuICAgIGNvbnN0IGJ5VG9rZW4gPSBuZXcgTWFwPG51bWJlciwgc3RyaW5nPigpO1xuICAgIGZvciAoY29uc3Qgd29ya2VyIG9mIHdvcmtlcnMpIHtcbiAgICAgIGlmICghYnlUb2tlbi5oYXMod29ya2VyLnRva2VuSWQpKSBieVRva2VuLnNldCh3b3JrZXIudG9rZW5JZCwgd29ya2VyLnRva2VuTmFtZSk7XG4gICAgfVxuXG4gICAgY29uc3QgcmVhZHlBY3RpdmVUb2tlbklkcyA9IG5ldyBTZXQoYnlUb2tlbi5rZXlzKCkpO1xuICAgIGNvbnN0IGVsaWdpYmxlVG9rZW5JZHMgPSBuZXcgU2V0PG51bWJlcj4oKTtcbiAgICBjb25zdCBvdmVyVGhyZXNob2xkVG9rZW5zOiBBcnJheTx7IHRva2VuTmFtZTogc3RyaW5nOyB0aHJlc2hvbGQ6IG51bWJlciB9PiA9IFtdO1xuICAgIGxldCB0aHJlc2hvbGRlZFRva2VuQ291bnQgPSAwO1xuXG4gICAgY29uc3QgZW50cmllcyA9IEFycmF5LmZyb20oYnlUb2tlbi5lbnRyaWVzKCkpO1xuICAgIGNvbnN0IGNoZWNrcyA9IGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChcbiAgICAgIGVudHJpZXMubWFwKGFzeW5jIChbdG9rZW5JZCwgdG9rZW5OYW1lXSkgPT4ge1xuICAgICAgICBpZiAoZXhjbHVkZWRUb2tlbklkcy5oYXModG9rZW5JZCkpIHtcbiAgICAgICAgICB0aHJlc2hvbGRlZFRva2VuQ291bnQrKztcbiAgICAgICAgICByZXR1cm4geyB0b2tlbklkLCB0b2tlbk5hbWUsIGVsaWdpYmxlOiBmYWxzZSB9O1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5oYXNRdW90YVRocmVzaG9sZCh0b2tlbklkKSkge1xuICAgICAgICAgIHJldHVybiB7IHRva2VuSWQsIHRva2VuTmFtZSwgZWxpZ2libGU6IHRydWUgfTtcbiAgICAgICAgfVxuICAgICAgICB0aHJlc2hvbGRlZFRva2VuQ291bnQrKztcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0b2tlbklkLFxuICAgICAgICAgIHRva2VuTmFtZSxcbiAgICAgICAgICBlbGlnaWJsZTogYXdhaXQgdGhpcy5pc1Rva2VuUXVvdGFFbGlnaWJsZSh0b2tlbklkLCB0b2tlbk5hbWUpLFxuICAgICAgICB9O1xuICAgICAgfSksXG4gICAgKTtcblxuICAgIGNoZWNrcy5mb3JFYWNoKChjaGVjaywgaW5kZXgpID0+IHtcbiAgICAgIGlmIChjaGVjay5zdGF0dXMgPT09IFwiZnVsZmlsbGVkXCIpIHtcbiAgICAgICAgaWYgKGNoZWNrLnZhbHVlLmVsaWdpYmxlKSB7XG4gICAgICAgICAgZWxpZ2libGVUb2tlbklkcy5hZGQoY2hlY2sudmFsdWUudG9rZW5JZCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3QgdGhyZXNob2xkID0gdGhpcy5nZXRRdW90YVRocmVzaG9sZChjaGVjay52YWx1ZS50b2tlbklkKTtcbiAgICAgICAgICBpZiAodGhyZXNob2xkICE9PSB1bmRlZmluZWQgJiYgdGhyZXNob2xkICE9PSBudWxsKSB7XG4gICAgICAgICAgICBvdmVyVGhyZXNob2xkVG9rZW5zLnB1c2goeyB0b2tlbk5hbWU6IGNoZWNrLnZhbHVlLnRva2VuTmFtZSwgdGhyZXNob2xkIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGVudHJ5ID0gZW50cmllc1tpbmRleF07XG4gICAgICBpZiAoZW50cnkpIHtcbiAgICAgICAgY29uc3QgW3Rva2VuSWQsIHRva2VuTmFtZV0gPSBlbnRyeTtcbiAgICAgICAgdGhpcy5sb2dRdW90YUxvb2t1cEZhaWxPcGVuKHRva2VuSWQsIHRva2VuTmFtZSwgU3RyaW5nKGNoZWNrLnJlYXNvbikpO1xuICAgICAgICBlbGlnaWJsZVRva2VuSWRzLmFkZCh0b2tlbklkKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiB7IHJlYWR5QWN0aXZlVG9rZW5JZHMsIGVsaWdpYmxlVG9rZW5JZHMsIG92ZXJUaHJlc2hvbGRUb2tlbnMsIHRocmVzaG9sZGVkVG9rZW5Db3VudCB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBpc1dvcmtlckVsaWdpYmxlRm9yUXVldWVJdGVtKFxuICAgIHdvcmtlcjogQ29kZXhBcHBTZXJ2ZXJXb3JrZXIsXG4gICAgaXRlbTogUXVldWVJdGVtLFxuICApOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBpZiAoaXRlbS5leGNsdWRlZFRva2VuSWRzLmhhcyh3b3JrZXIudG9rZW5JZCkpIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4gdGhpcy5pc1Rva2VuUXVvdGFFbGlnaWJsZSh3b3JrZXIudG9rZW5JZCwgd29ya2VyLnRva2VuTmFtZSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzVG9rZW5RdW90YUVsaWdpYmxlKFxuICAgIHRva2VuSWQ6IG51bWJlcixcbiAgICB0b2tlbk5hbWU6IHN0cmluZyxcbiAgICBleGNsdWRlZFRva2VuSWRzPzogU2V0PG51bWJlcj4sXG4gICk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IHRocmVzaG9sZCA9IHRoaXMuZ2V0UXVvdGFUaHJlc2hvbGQodG9rZW5JZCk7XG4gICAgaWYgKHRocmVzaG9sZCA9PT0gdW5kZWZpbmVkIHx8IHRocmVzaG9sZCA9PT0gbnVsbCkgcmV0dXJuIHRydWU7XG5cbiAgICBsZXQgcmVzdWx0OiBPcGVuQUlRdW90YVVzYWdlUmVzdWx0O1xuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSBhd2FpdCByZWFkT3BlbkFJUXVvdGFVc2FnZSgoKSA9PiB0aGlzLmdldFJhdGVMaW1pdHNCeVRva2VuSWQodG9rZW5JZCkpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRoaXMubG9nUXVvdGFMb29rdXBGYWlsT3Blbih0b2tlbklkLCB0b2tlbk5hbWUsIChlIGFzIEVycm9yKS5tZXNzYWdlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIGlmIChyZXN1bHQua2luZCA9PT0gXCJsb29rdXBfZmFpbGVkXCIpIHtcbiAgICAgIHRoaXMubG9nUXVvdGFMb29rdXBGYWlsT3Blbih0b2tlbklkLCB0b2tlbk5hbWUsIHJlc3VsdC5yZWFzb24pO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgaWYgKHJlc3VsdC51dGlsaXphdGlvblBjdCA+PSB0aHJlc2hvbGQpIHtcbiAgICAgIHRoaXMubG9nUXVvdGFPdmVyVGhyZXNob2xkKHRva2VuSWQsIHRva2VuTmFtZSwgdGhyZXNob2xkLCByZXN1bHQpO1xuICAgICAgZXhjbHVkZWRUb2tlbklkcz8uYWRkKHRva2VuSWQpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBsb2dRdW90YU92ZXJUaHJlc2hvbGQoXG4gICAgdG9rZW5JZDogbnVtYmVyLFxuICAgIHRva2VuTmFtZTogc3RyaW5nLFxuICAgIHRocmVzaG9sZDogbnVtYmVyLFxuICAgIHJlc3VsdDogRXh0cmFjdDxPcGVuQUlRdW90YVVzYWdlUmVzdWx0LCB7IGtpbmQ6IFwib2tcIiB9PixcbiAgKTogdm9pZCB7XG4gICAgbG9nZ2VyLmluZm8oXCJxdW90YV90aHJlc2hvbGQgZ2F0ZTogb3Zlcl90aHJlc2hvbGRcIiwge1xuICAgICAgdG9rZW5JZCxcbiAgICAgIHRva2VuTmFtZSxcbiAgICAgIHByb3ZpZGVyOiBcIm9wZW5haVwiLFxuICAgICAgdGhyZXNob2xkLFxuICAgICAgY2FjaGVkVXRpbGl6YXRpb246IHJlc3VsdC51dGlsaXphdGlvblBjdCxcbiAgICAgIGNhY2hlQWdlOiByZXN1bHQuY2FjaGVBZ2VNcyxcbiAgICAgIHdpbmRvd0R1cmF0aW9uTWluczogcmVzdWx0LndpbmRvd0R1cmF0aW9uTWlucyxcbiAgICAgIHJlc2V0c0F0OiByZXN1bHQucmVzZXRzQXQsXG4gICAgICBsaW1pdElkOiByZXN1bHQubGltaXRJZCxcbiAgICAgIHJlYXNvbjogXCJvdmVyX3RocmVzaG9sZFwiLFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBsb2dRdW90YUxvb2t1cEZhaWxPcGVuKHRva2VuSWQ6IG51bWJlciwgdG9rZW5OYW1lOiBzdHJpbmcsIHJlYXNvbjogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgdGhyZXNob2xkID0gdGhpcy5nZXRRdW90YVRocmVzaG9sZCh0b2tlbklkKTtcbiAgICBsb2dnZXIud2FybihcInF1b3RhX3RocmVzaG9sZCBnYXRlOiBsb29rdXBfZmFpbF9vcGVuXCIsIHtcbiAgICAgIHRva2VuSWQsXG4gICAgICB0b2tlbk5hbWUsXG4gICAgICBwcm92aWRlcjogXCJvcGVuYWlcIixcbiAgICAgIHRocmVzaG9sZCxcbiAgICAgIHJlYXNvbjogXCJsb29rdXBfZmFpbF9vcGVuXCIsXG4gICAgICBsb29rdXBSZWFzb246IHJlYXNvbixcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgdGhyb3dRdW90YVRocmVzaG9sZEV4Y2VlZGVkKGVsaWdpYmlsaXR5OiBUb2tlbkVsaWdpYmlsaXR5KTogbmV2ZXIge1xuICAgIGxvZ2dlci53YXJuKFwicXVvdGFfdGhyZXNob2xkIGdhdGU6IGFsbF9leGNlZWRlZFwiLCB7XG4gICAgICBwcm92aWRlcjogXCJvcGVuYWlcIixcbiAgICAgIHRva2VuQ291bnQ6IGVsaWdpYmlsaXR5LnJlYWR5QWN0aXZlVG9rZW5JZHMuc2l6ZSxcbiAgICAgIHRocmVzaG9sZGVkVG9rZW5Db3VudDogZWxpZ2liaWxpdHkudGhyZXNob2xkZWRUb2tlbkNvdW50LFxuICAgICAgb3ZlclRocmVzaG9sZFRva2VuczogZWxpZ2liaWxpdHkub3ZlclRocmVzaG9sZFRva2VucyxcbiAgICAgIHJlYXNvbjogXCJhbGxfZXhjZWVkZWRcIixcbiAgICB9KTtcbiAgICB0aHJvdyBuZXcgUXVvdGFUaHJlc2hvbGRFeGNlZWRlZEVycm9yKFxuICAgICAgcXVvdGFUaHJlc2hvbGRFeGNlZWRlZE1lc3NhZ2UoXCJvcGVuYWlcIiwgZWxpZ2liaWxpdHkub3ZlclRocmVzaG9sZFRva2VucyksXG4gICAgKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBCcm93c2VyIGxvZ2luIGZsb3cg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgcGVuZGluZ0xvZ2luOiB7XG4gICAgd29ya2VyOiBDb2RleEFwcFNlcnZlcldvcmtlcjtcbiAgICBuYW1lOiBzdHJpbmc7XG4gICAgdGltZXI6IFJldHVyblR5cGU8dHlwZW9mIHNldFRpbWVvdXQ+O1xuICB9IHwgbnVsbCA9IG51bGw7XG5cbiAgYXN5bmMgc3RhcnRCcm93c2VyTG9naW4obmFtZTogc3RyaW5nKTogUHJvbWlzZTx7IGF1dGhVcmw6IHN0cmluZyB9PiB7XG4gICAgaWYgKHRoaXMucGVuZGluZ0xvZ2luKSB7XG4gICAgICB0aGlzLnBlbmRpbmdMb2dpbi53b3JrZXIua2lsbCgpLmNhdGNoKCgpID0+IHt9KTtcbiAgICAgIGNsZWFyVGltZW91dCh0aGlzLnBlbmRpbmdMb2dpbi50aW1lcik7XG4gICAgICB0aGlzLnBlbmRpbmdMb2dpbiA9IG51bGw7XG4gICAgfVxuXG4gICAgY29uc3QgdGVtcElkID0gRGF0ZS5ub3coKTtcbiAgICBjb25zdCB3b3JrZXIgPSBuZXcgQ29kZXhBcHBTZXJ2ZXJXb3JrZXIoe1xuICAgICAgdG9rZW5JZDogdGVtcElkLFxuICAgICAgdG9rZW5OYW1lOiBuYW1lLFxuICAgICAgYWNjZXNzVG9rZW46IFwiXCIsXG4gICAgICBhY2NvdW50SWQ6IFwiXCIsXG4gICAgfSk7XG5cbiAgICBjb25zdCBhdXRoVXJsID0gYXdhaXQgd29ya2VyLnN0YXJ0QnJvd3NlckxvZ2luKCk7XG5cbiAgICBjb25zdCB0aW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgaWYgKHRoaXMucGVuZGluZ0xvZ2luPy53b3JrZXIgPT09IHdvcmtlcikge1xuICAgICAgICBsb2dnZXIud2FybihgYnJvd3NlciBsb2dpbiB0aW1lb3V0IGZvciAke25hbWV9LCBraWxsaW5nIHdvcmtlcmApO1xuICAgICAgICB3b3JrZXIua2lsbCgpLmNhdGNoKCgpID0+IHt9KTtcbiAgICAgICAgdGhpcy5wZW5kaW5nTG9naW4gPSBudWxsO1xuICAgICAgfVxuICAgIH0sIDMwMF8wMDApO1xuXG4gICAgdGhpcy5wZW5kaW5nTG9naW4gPSB7IHdvcmtlciwgbmFtZSwgdGltZXIgfTtcbiAgICByZXR1cm4geyBhdXRoVXJsIH07XG4gIH1cblxuICBnZXQgcGVuZGluZ0xvZ2luTmFtZSgpOiBzdHJpbmcgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5wZW5kaW5nTG9naW4/Lm5hbWUgPz8gbnVsbDtcbiAgfVxuXG4gIGFzeW5jIGNvbXBsZXRlQnJvd3NlckxvZ2luKCk6IFByb21pc2U8e1xuICAgIGFjY2Vzc1Rva2VuOiBzdHJpbmc7XG4gICAgcmVmcmVzaFRva2VuOiBzdHJpbmc7XG4gICAgaWRUb2tlbj86IHN0cmluZztcbiAgICBhY2NvdW50SWQ6IHN0cmluZztcbiAgfT4ge1xuICAgIGlmICghdGhpcy5wZW5kaW5nTG9naW4pIHRocm93IG5ldyBFcnJvcihcIm5vIHBlbmRpbmcgbG9naW5cIik7XG4gICAgY29uc3QgeyB3b3JrZXIsIHRpbWVyIH0gPSB0aGlzLnBlbmRpbmdMb2dpbjtcblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCB3b3JrZXIud2FpdEZvckJyb3dzZXJMb2dpbkNvbXBsZXRlKCk7XG4gICAgICBjb25zdCBjcmVkcyA9IGF3YWl0IHdvcmtlci5yZWFkTWFuYWdlZENyZWRlbnRpYWxzKCk7XG4gICAgICBpZiAoIWNyZWRzKSB0aHJvdyBuZXcgRXJyb3IoXCJmYWlsZWQgdG8gcmVhZCBjcmVkZW50aWFscyBhZnRlciBsb2dpblwiKTtcbiAgICAgIHJldHVybiBjcmVkcztcbiAgICB9IGZpbmFsbHkge1xuICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgIHRoaXMucGVuZGluZ0xvZ2luID0gbnVsbDtcbiAgICAgIGF3YWl0IHdvcmtlci5raWxsKCkuY2F0Y2goKCkgPT4ge30pO1xuICAgIH1cbiAgfVxuXG4gIC8vIOKUgOKUgCBTdGF0cyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBnZXQgd29ya2VyQ291bnQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gWy4uLnRoaXMud29ya2VyUG9vbC52YWx1ZXMoKV0uZmxhdCgpLmxlbmd0aDtcbiAgfVxuXG4gIGdldCByZWFkeVdvcmtlckNvdW50KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIFsuLi50aGlzLndvcmtlclBvb2wudmFsdWVzKCldLmZsYXQoKS5maWx0ZXIoKHcpID0+IHcuaXNSZWFkeSkubGVuZ3RoO1xuICB9XG5cbiAgZ2V0IHF1ZXVlTGVuZ3RoKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMucXVldWUubGVuZ3RoO1xuICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7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
@@ -0,0 +1,62 @@
1
+ import {
2
+ type ImageGenerationOptions,
3
+ type ImageGenerationQuality,
4
+ type ImageGenerationSize,
5
+ type QueryOutput,
6
+ } from "./qgrid.types";
7
+
8
+ export const CODEX_IMAGE_GENERATION_MODEL = "gpt-image-2";
9
+ export const DEFAULT_IMAGE_GENERATION_QUALITY: ImageGenerationQuality = "medium";
10
+ export const DEFAULT_IMAGE_GENERATION_SIZE: ImageGenerationSize = "1536x1024";
11
+
12
+ export type ResolvedImageGenerationOptions = {
13
+ quality: ImageGenerationQuality;
14
+ size: ImageGenerationSize;
15
+ };
16
+
17
+ // OpenAI gpt-image-2 image output cost estimates by quality/size:
18
+ // https://developers.openai.com/api/docs/guides/image-generation#calculating-costs
19
+ const IMAGE_OUTPUT_COST_MICRO_USD: Record<
20
+ ImageGenerationQuality,
21
+ Record<ImageGenerationSize, number>
22
+ > = {
23
+ low: {
24
+ "1024x1024": 6_000,
25
+ "1024x1536": 5_000,
26
+ "1536x1024": 5_000,
27
+ },
28
+ medium: {
29
+ "1024x1024": 53_000,
30
+ "1024x1536": 41_000,
31
+ "1536x1024": 41_000,
32
+ },
33
+ high: {
34
+ "1024x1024": 211_000,
35
+ "1024x1536": 165_000,
36
+ "1536x1024": 165_000,
37
+ },
38
+ };
39
+
40
+ export function resolveImageGenerationOptions(
41
+ options: ImageGenerationOptions | undefined,
42
+ ): ResolvedImageGenerationOptions {
43
+ return {
44
+ quality: options?.quality ?? DEFAULT_IMAGE_GENERATION_QUALITY,
45
+ size: options?.size ?? DEFAULT_IMAGE_GENERATION_SIZE,
46
+ };
47
+ }
48
+
49
+ export function imageGenerationCostMethod(options: ImageGenerationOptions | undefined): string {
50
+ const resolved = resolveImageGenerationOptions(options);
51
+ return `assumed:${CODEX_IMAGE_GENERATION_MODEL}:${resolved.quality}:${resolved.size}:png`;
52
+ }
53
+
54
+ export function estimateImageGenerationCostMicroUsd(
55
+ result: QueryOutput,
56
+ options: ImageGenerationOptions | undefined,
57
+ ): number | null {
58
+ const imageCount = result.content.filter((item) => item.type === "image").length;
59
+ if (imageCount === 0) return null;
60
+ const resolved = resolveImageGenerationOptions(options);
61
+ return imageCount * IMAGE_OUTPUT_COST_MICRO_USD[resolved.quality][resolved.size];
62
+ }
@@ -0,0 +1,59 @@
1
+ import {
2
+ type QgridContent,
3
+ type QueryInput,
4
+ type QueryOutput,
5
+ } from "./qgrid.types";
6
+ import {
7
+ CODEX_IMAGE_GENERATION_MODEL,
8
+ resolveImageGenerationOptions,
9
+ } from "./qgrid-image-generation";
10
+
11
+ export const CODEX_IMAGE_GENERATION_TOOL_CONFIG = {
12
+ type: "image_generation",
13
+ outputFormat: "png",
14
+ } as const;
15
+
16
+ function escapeHtmlAttribute(value: string): string {
17
+ return value
18
+ .replace(/&/g, "&amp;")
19
+ .replace(/"/g, "&quot;")
20
+ .replace(/</g, "&lt;")
21
+ .replace(/>/g, "&gt;");
22
+ }
23
+
24
+ export function formatResponseForLog(result: QueryOutput): string {
25
+ return result.content
26
+ .flatMap((item) => {
27
+ if (item.type === "text") return [item.text];
28
+ if (item.type === "image") {
29
+ const alt = escapeHtmlAttribute(item.revisedPrompt ?? "generated image");
30
+ return [`<img src="data:image/png;base64,${item.data}" alt="${alt}" />`];
31
+ }
32
+ return [];
33
+ })
34
+ .filter((part) => part.length > 0)
35
+ .join("\n");
36
+ }
37
+
38
+ export function getImageParts(result: QueryOutput): Extract<QgridContent, { type: "image" }>[] {
39
+ return result.content.filter((item) => item.type === "image");
40
+ }
41
+
42
+ export function formatImagePartForLog(image: Extract<QgridContent, { type: "image" }>): string {
43
+ const alt = escapeHtmlAttribute(image.revisedPrompt ?? "generated image");
44
+ return `<img src="data:image/png;base64,${image.data}" alt="${alt}" />`;
45
+ }
46
+
47
+ export function imageGenerationToolArgs(args: QueryInput): string {
48
+ const resolved = resolveImageGenerationOptions(args.imageGenerationOptions);
49
+ return JSON.stringify({
50
+ prompt: args.prompt,
51
+ driverModel: args.model ?? null,
52
+ tool: CODEX_IMAGE_GENERATION_TOOL_CONFIG,
53
+ pricingAssumption: {
54
+ model: CODEX_IMAGE_GENERATION_MODEL,
55
+ quality: resolved.quality,
56
+ size: resolved.size,
57
+ },
58
+ });
59
+ }
@@ -93,4 +93,109 @@ describe("qgrid run lifecycle TTFT", () => {
93
93
  }),
94
94
  );
95
95
  });
96
+
97
+ it("finishes runs with image data-url img tags in response", async () => {
98
+ await afterQuery(
99
+ 10,
100
+ 2,
101
+ { prompt: "draw", imageGeneration: true },
102
+ queryOutput({
103
+ text: "image ready",
104
+ content: [
105
+ { type: "text", text: "image ready" },
106
+ { type: "image", data: "iVBORw0KGgoBAgM", revisedPrompt: "green triangle" },
107
+ ],
108
+ }),
109
+ );
110
+
111
+ expect(finishRunMock).toHaveBeenCalledWith(
112
+ 10,
113
+ expect.objectContaining({
114
+ response:
115
+ 'image ready\n<img src="data:image/png;base64,iVBORw0KGgoBAgM" alt="green triangle" />',
116
+ }),
117
+ );
118
+ });
119
+
120
+ it("records image generation as a completed synthetic tool call step", async () => {
121
+ await afterQuery(
122
+ 10,
123
+ 2,
124
+ { prompt: "draw a green triangle", model: "openai/gpt-5.5", imageGeneration: true },
125
+ queryOutput({
126
+ text: "image ready",
127
+ content: [
128
+ { type: "text", text: "image ready" },
129
+ { type: "image", data: "iVBORw0KGgoBAgM", revisedPrompt: "green triangle" },
130
+ ],
131
+ }),
132
+ );
133
+
134
+ expect(appendStepMock).toHaveBeenCalledWith(
135
+ 10,
136
+ expect.objectContaining({
137
+ step_index: 2,
138
+ type: "tool_call",
139
+ tool_call_index: 0,
140
+ tool_call_id: "image_generation:2:0",
141
+ tool_name: "image_generation",
142
+ tool_args: JSON.stringify({
143
+ prompt: "draw a green triangle",
144
+ driverModel: "openai/gpt-5.5",
145
+ tool: {
146
+ type: "image_generation",
147
+ outputFormat: "png",
148
+ },
149
+ pricingAssumption: {
150
+ model: "gpt-image-2",
151
+ quality: "medium",
152
+ size: "1536x1024",
153
+ },
154
+ }),
155
+ tool_result: '<img src="data:image/png;base64,iVBORw0KGgoBAgM" alt="green triangle" />',
156
+ }),
157
+ );
158
+ });
159
+
160
+ it("passes configured image generation cost estimate into finishRun", async () => {
161
+ await afterQuery(
162
+ 10,
163
+ 2,
164
+ { prompt: "draw", imageGeneration: true },
165
+ queryOutput({
166
+ content: [{ type: "image", data: "iVBORw0KGgoBAgM", revisedPrompt: "green triangle" }],
167
+ }),
168
+ );
169
+
170
+ expect(finishRunMock).toHaveBeenCalledWith(
171
+ 10,
172
+ expect.objectContaining({
173
+ image_cost_usd: 41000,
174
+ image_cost_method: "assumed:gpt-image-2:medium:1536x1024:png",
175
+ }),
176
+ );
177
+ });
178
+
179
+ it("uses requested image quality and size for cost estimate", async () => {
180
+ await afterQuery(
181
+ 10,
182
+ 2,
183
+ {
184
+ prompt: "draw",
185
+ imageGeneration: true,
186
+ imageGenerationOptions: { quality: "high", size: "1024x1024" },
187
+ },
188
+ queryOutput({
189
+ content: [{ type: "image", data: "iVBORw0KGgoBAgM", revisedPrompt: "green triangle" }],
190
+ }),
191
+ );
192
+
193
+ expect(finishRunMock).toHaveBeenCalledWith(
194
+ 10,
195
+ expect.objectContaining({
196
+ image_cost_usd: 211000,
197
+ image_cost_method: "assumed:gpt-image-2:high:1024x1024:png",
198
+ }),
199
+ );
200
+ });
96
201
  });
@@ -7,6 +7,16 @@ import {
7
7
  type QueryInput,
8
8
  type QueryOutput,
9
9
  } from "./qgrid.types";
10
+ import {
11
+ formatImagePartForLog,
12
+ formatResponseForLog,
13
+ getImageParts,
14
+ imageGenerationToolArgs,
15
+ } from "./qgrid-response-format";
16
+ import {
17
+ estimateImageGenerationCostMicroUsd,
18
+ imageGenerationCostMethod,
19
+ } from "./qgrid-image-generation";
10
20
 
11
21
  const logger = getLogger(["qgrid", "run-lifecycle"]);
12
22
  const STALE_RUN_THRESHOLD_MS = 30 * 60 * 1000;
@@ -64,6 +74,7 @@ export async function beforeQuery(args: QueryInput): Promise<{
64
74
  model_name: args.model,
65
75
  effort: args.effort,
66
76
  project_name: args.projectName,
77
+ is_image_generation: args.imageGeneration,
67
78
  });
68
79
  }
69
80
 
@@ -89,6 +100,24 @@ export async function afterQuery(
89
100
  finish_reason: result.finishReason,
90
101
  });
91
102
 
103
+ const imageParts = getImageParts(result);
104
+ const imageCostMicroUsd = estimateImageGenerationCostMicroUsd(
105
+ result,
106
+ args.imageGenerationOptions,
107
+ );
108
+ for (let i = 0; i < imageParts.length; i++) {
109
+ const image = imageParts[i]!;
110
+ await RequestLogModel.appendStep(requestLogId, {
111
+ step_index: stepIndex,
112
+ type: "tool_call",
113
+ tool_call_index: i,
114
+ tool_call_id: `image_generation:${stepIndex}:${i}`,
115
+ tool_name: "image_generation",
116
+ tool_args: imageGenerationToolArgs(args),
117
+ tool_result: formatImagePartForLog(image),
118
+ });
119
+ }
120
+
92
121
  if (result.finishReason === "tool-calls") {
93
122
  // tool-call step 즉시 기록 (result는 나중에 completeToolCall로 채움)
94
123
  const toolCalls = result.content.filter((c) => c.type === "tool-call");
@@ -98,7 +127,7 @@ export async function afterQuery(
98
127
  await RequestLogModel.appendStep(requestLogId, {
99
128
  step_index: stepIndex,
100
129
  type: "tool_call",
101
- tool_call_index: i,
130
+ tool_call_index: imageParts.length + i,
102
131
  tool_call_id: tc.toolCallId,
103
132
  tool_name: tc.toolName,
104
133
  tool_args: tc.input,
@@ -112,13 +141,16 @@ export async function afterQuery(
112
141
  const agg = await RequestLogModel.aggregateStepUsage(requestLogId);
113
142
  await RequestLogModel.finishRun(requestLogId, {
114
143
  status: "succeeded",
115
- response: result.text,
144
+ response: formatResponseForLog(result),
116
145
  token_name: result.tokenName,
117
146
  input_tokens: agg.input_tokens,
118
147
  output_tokens: agg.output_tokens,
119
148
  cache_read_tokens: agg.cache_read_tokens,
120
149
  cache_creation_tokens: agg.cache_creation_tokens,
121
150
  duration_ms: agg.duration_ms,
151
+ image_cost_usd: imageCostMicroUsd,
152
+ image_cost_method:
153
+ imageCostMicroUsd !== null ? imageGenerationCostMethod(args.imageGenerationOptions) : null,
122
154
  history: filterHistoryForStorage(args.history),
123
155
  });
124
156