@cartanova/qgrid-cli 2.10.9 → 2.11.0

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 (318) hide show
  1. package/bundle/dist/_virtual/_rolldown/runtime.js +1 -10
  2. package/bundle/dist/application/monit/log-buffer.js +12 -6
  3. package/bundle/dist/application/monit/monit.frame.js +11 -3
  4. package/bundle/dist/application/monit/monit.types.js +1 -1
  5. package/bundle/dist/application/qgrid/conv-routing.js +9 -6
  6. package/bundle/dist/application/qgrid/expired-token-reminder.js +2 -2
  7. package/bundle/dist/application/qgrid/oauth.js +31 -4
  8. package/bundle/dist/application/qgrid/qgrid-image-generation.js +1 -1
  9. package/bundle/dist/application/qgrid/qgrid-response-format.js +22 -20
  10. package/bundle/dist/application/qgrid/qgrid-run-lifecycle.js +43 -34
  11. package/bundle/dist/application/qgrid/qgrid.dispatcher.js +128 -93
  12. package/bundle/dist/application/qgrid/qgrid.frame.js +930 -49
  13. package/bundle/dist/application/qgrid/qgrid.types.js +212 -5
  14. package/bundle/dist/application/qgrid/schema-prompt.js +75 -48
  15. package/bundle/dist/application/qgrid/slack-user-map.js +1 -1
  16. package/bundle/dist/application/qgrid/token-death.js +1 -1
  17. package/bundle/dist/application/qgrid/token-subscriber.js +83 -30
  18. package/bundle/dist/application/qgrid/token-trigger-setup.js +1 -1
  19. package/bundle/dist/application/qgrid/token-window-keepalive.js +8 -6
  20. package/bundle/dist/application/qgrid/tool-emulation-schema.js +13 -13
  21. package/bundle/dist/application/qgrid/tool-emulation.js +19 -15
  22. package/bundle/dist/application/request-log/json-schema-type-text.js +29 -12
  23. package/bundle/dist/application/request-log/request-log.model.js +83 -69
  24. package/bundle/dist/application/request-log/request-log.types.js +8 -2
  25. package/bundle/dist/application/request-log/zod-code-format.js +1 -1
  26. package/bundle/dist/application/request-log-step/request-log-step.model.js +1 -1
  27. package/bundle/dist/application/request-log-step/request-log-step.types.js +1 -1
  28. package/bundle/dist/application/setting/setting.constant.js +1 -1
  29. package/bundle/dist/application/setting/setting.model.js +2 -2
  30. package/bundle/dist/application/setting/setting.store.js +2 -2
  31. package/bundle/dist/application/setting/setting.types.js +1 -1
  32. package/bundle/dist/application/sonamu.generated.js +40 -16
  33. package/bundle/dist/application/sonamu.generated.sso.js +2 -1
  34. package/bundle/dist/application/token/token.model.js +26 -9
  35. package/bundle/dist/application/token/token.types.js +20 -3
  36. package/bundle/dist/i18n/en.js +15 -1
  37. package/bundle/dist/i18n/ko.js +15 -1
  38. package/bundle/dist/i18n/sd.generated.js +2 -1
  39. package/bundle/dist/migrations/20260807133553_manual__backfill_request_log_cost.js +8 -6
  40. package/bundle/dist/migrations/20261018215031_alter_request_logs_add1_alter1.js +15 -0
  41. package/bundle/dist/server-bootstrap.js +4 -2
  42. package/bundle/dist/server-error-handler.js +1 -1
  43. package/bundle/dist/sonamu.config.js +37 -8
  44. package/bundle/dist/startup-migrations.js +17 -7
  45. package/bundle/dist/testing/global.js +1 -1
  46. package/bundle/dist/testing/schema-bench.js +0 -0
  47. package/bundle/dist/testing/test-database-name.js +1 -1
  48. package/bundle/dist/utils/providers/anthropic/anthropic-constants.js +1 -1
  49. package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +11 -5
  50. package/bundle/dist/utils/providers/anthropic/anthropic-quota.js +4 -4
  51. package/bundle/dist/utils/providers/anthropic/anthropic-thinking.js +1 -1
  52. package/bundle/dist/utils/providers/anthropic/claude-session.js +20 -19
  53. package/bundle/dist/utils/providers/anthropic/fence-strip.js +1 -1
  54. package/bundle/dist/utils/providers/anthropic/stream-json-adapter.js +49 -23
  55. package/bundle/dist/utils/providers/common/credentials.js +5 -1
  56. package/bundle/dist/utils/providers/common/effort.js +3 -3
  57. package/bundle/dist/utils/providers/common/model-cost.js +69 -14
  58. package/bundle/dist/utils/providers/common/provider-types.js +29 -1
  59. package/bundle/dist/utils/providers/common/schema-validation.js +78 -40
  60. package/bundle/dist/utils/providers/common/smooth-weighted-round-robin.js +1 -1
  61. package/bundle/dist/utils/providers/common/strictifier.js +62 -43
  62. package/bundle/dist/utils/providers/common/thinking.js +3 -2
  63. package/bundle/dist/utils/providers/common/ttft.js +1 -1
  64. package/bundle/dist/utils/providers/grok/grok-backend-protocol.js +427 -0
  65. package/bundle/dist/utils/providers/grok/grok-constants.js +55 -0
  66. package/bundle/dist/utils/providers/grok/grok-direct-client.js +196 -0
  67. package/bundle/dist/utils/providers/grok/grok-dispatcher.js +1313 -0
  68. package/bundle/dist/utils/providers/grok/grok-headers.js +118 -0
  69. package/bundle/dist/utils/providers/grok/grok-media-client.js +420 -0
  70. package/bundle/dist/utils/providers/grok/grok-models.js +114 -0
  71. package/bundle/dist/utils/providers/grok/grok-oauth.js +455 -0
  72. package/bundle/dist/utils/providers/grok/grok-quota.js +119 -0
  73. package/bundle/dist/utils/providers/grok/grok-refresh.js +192 -0
  74. package/bundle/dist/utils/providers/grok/grok-types.js +186 -0
  75. package/bundle/dist/utils/providers/grok/grok-voice-client.js +199 -0
  76. package/bundle/dist/utils/providers/grok/index.js +11 -0
  77. package/bundle/dist/utils/providers/openai/openai-backend-protocol.js +111 -83
  78. package/bundle/dist/utils/providers/openai/openai-callback-relay.js +3 -2
  79. package/bundle/dist/utils/providers/openai/openai-constants.js +1 -1
  80. package/bundle/dist/utils/providers/openai/openai-direct-client.js +23 -7
  81. package/bundle/dist/utils/providers/openai/openai-dispatcher.js +143 -106
  82. package/bundle/dist/utils/providers/openai/openai-image-generation.js +48 -33
  83. package/bundle/dist/utils/providers/openai/openai-oauth.js +28 -13
  84. package/bundle/dist/utils/providers/openai/openai-quota.js +38 -27
  85. package/bundle/dist/utils/providers/openai/openai-refresh.js +17 -9
  86. package/bundle/dist/utils/providers/openai/openai-sse.js +1 -1
  87. package/bundle/dist/utils/providers/openai/openai-transport-config.js +1 -1
  88. package/bundle/dist/utils/quiet-hours.js +1 -1
  89. package/bundle/dist/utils/slack-notify.js +14 -8
  90. package/bundle/dist/utils/subset-loaders.js +4 -5
  91. package/bundle/src/application/monit/log-buffer.ts +23 -9
  92. package/bundle/src/application/monit/monit.frame.ts +22 -5
  93. package/bundle/src/application/monit/monit.types.ts +6 -0
  94. package/bundle/src/application/qgrid/conv-routing.test.ts +76 -4
  95. package/bundle/src/application/qgrid/conv-routing.ts +35 -9
  96. package/bundle/src/application/qgrid/expired-token-reminder.ts +9 -1
  97. package/bundle/src/application/qgrid/oauth.ts +51 -15
  98. package/bundle/src/application/qgrid/qgrid-image-generation.ts +9 -0
  99. package/bundle/src/application/qgrid/qgrid-response-format.ts +50 -25
  100. package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +33 -0
  101. package/bundle/src/application/qgrid/qgrid-run-lifecycle.ts +87 -40
  102. package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +97 -0
  103. package/bundle/src/application/qgrid/qgrid.dispatcher.ts +274 -126
  104. package/bundle/src/application/qgrid/qgrid.frame.test.ts +1013 -3
  105. package/bundle/src/application/qgrid/qgrid.frame.ts +1415 -60
  106. package/bundle/src/application/qgrid/qgrid.types.ts +335 -0
  107. package/bundle/src/application/qgrid/schema-prompt.ts +105 -41
  108. package/bundle/src/application/qgrid/slack-user-map.ts +5 -0
  109. package/bundle/src/application/qgrid/token-death.ts +4 -0
  110. package/bundle/src/application/qgrid/token-subscriber.test.ts +21 -19
  111. package/bundle/src/application/qgrid/token-subscriber.ts +186 -53
  112. package/bundle/src/application/qgrid/token-trigger-setup.ts +2 -0
  113. package/bundle/src/application/qgrid/token-window-keepalive.ts +49 -6
  114. package/bundle/src/application/qgrid/tool-emulation-schema.ts +33 -29
  115. package/bundle/src/application/qgrid/tool-emulation.ts +52 -27
  116. package/bundle/src/application/request-log/json-schema-type-text.test.ts +5 -5
  117. package/bundle/src/application/request-log/json-schema-type-text.ts +81 -26
  118. package/bundle/src/application/request-log/request-log.entity.json +8 -0
  119. package/bundle/src/application/request-log/request-log.model.test.ts +111 -4
  120. package/bundle/src/application/request-log/request-log.model.ts +279 -145
  121. package/bundle/src/application/request-log/request-log.types.ts +17 -0
  122. package/bundle/src/application/request-log/zod-code-format.ts +11 -0
  123. package/bundle/src/application/request-log-step/request-log-step.model.ts +1 -0
  124. package/bundle/src/application/request-log-step/request-log-step.types.ts +2 -0
  125. package/bundle/src/application/setting/setting.constant.ts +9 -0
  126. package/bundle/src/application/setting/setting.model.ts +12 -2
  127. package/bundle/src/application/setting/setting.store.ts +5 -1
  128. package/bundle/src/application/setting/setting.types.ts +8 -0
  129. package/bundle/src/application/sonamu.generated.http +135 -0
  130. package/bundle/src/application/sonamu.generated.sso.ts +3 -0
  131. package/bundle/src/application/sonamu.generated.ts +29 -0
  132. package/bundle/src/application/token/token.identity.test.ts +20 -0
  133. package/bundle/src/application/token/token.model.ts +66 -7
  134. package/bundle/src/application/token/token.types.ts +24 -1
  135. package/bundle/src/i18n/en.ts +19 -0
  136. package/bundle/src/i18n/ko.ts +21 -0
  137. package/bundle/src/i18n/sd.generated.ts +24 -2
  138. package/bundle/src/migrations/20260807133553_manual__backfill_request_log_cost.ts +16 -8
  139. package/bundle/src/migrations/20261018215031_alter_request_logs_add1_alter1.ts +15 -0
  140. package/bundle/src/server-bootstrap.ts +4 -2
  141. package/bundle/src/server-error-handler.ts +1 -0
  142. package/bundle/src/sonamu.config.ts +69 -7
  143. package/bundle/src/startup-migrations.ts +27 -9
  144. package/bundle/src/testing/global.ts +20 -0
  145. package/bundle/src/testing/schema-bench.ts +105 -30
  146. package/bundle/src/testing/test-database-name.ts +2 -0
  147. package/bundle/src/utils/providers/anthropic/anthropic-constants.ts +8 -0
  148. package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +41 -6
  149. package/bundle/src/utils/providers/anthropic/anthropic-quota.ts +7 -3
  150. package/bundle/src/utils/providers/anthropic/anthropic-thinking.ts +6 -0
  151. package/bundle/src/utils/providers/anthropic/claude-session.ts +58 -24
  152. package/bundle/src/utils/providers/anthropic/fence-strip.ts +11 -0
  153. package/bundle/src/utils/providers/anthropic/stream-json-adapter.ts +110 -45
  154. package/bundle/src/utils/providers/common/credentials.ts +8 -0
  155. package/bundle/src/utils/providers/common/effort.ts +9 -2
  156. package/bundle/src/utils/providers/common/model-cost.test.ts +48 -1
  157. package/bundle/src/utils/providers/common/model-cost.ts +259 -158
  158. package/bundle/src/utils/providers/common/provider-dispatcher.ts +98 -2
  159. package/bundle/src/utils/providers/common/provider-types.ts +46 -3
  160. package/bundle/src/utils/providers/common/schema-validation.test.ts +5 -1
  161. package/bundle/src/utils/providers/common/schema-validation.ts +124 -56
  162. package/bundle/src/utils/providers/common/smooth-weighted-round-robin.ts +4 -0
  163. package/bundle/src/utils/providers/common/strictifier.ts +185 -59
  164. package/bundle/src/utils/providers/common/thinking.ts +2 -2
  165. package/bundle/src/utils/providers/common/ttft.ts +4 -2
  166. package/bundle/src/utils/providers/grok/__fixtures__/golden-responses-1.0.60.json +164 -0
  167. package/bundle/src/utils/providers/grok/grok-backend-protocol.test.ts +325 -0
  168. package/bundle/src/utils/providers/grok/grok-backend-protocol.ts +721 -0
  169. package/bundle/src/utils/providers/grok/grok-constants.ts +105 -0
  170. package/bundle/src/utils/providers/grok/grok-direct-client.test.ts +179 -0
  171. package/bundle/src/utils/providers/grok/grok-direct-client.ts +313 -0
  172. package/bundle/src/utils/providers/grok/grok-dispatcher.test.ts +1395 -0
  173. package/bundle/src/utils/providers/grok/grok-dispatcher.ts +2105 -0
  174. package/bundle/src/utils/providers/grok/grok-headers.test.ts +149 -0
  175. package/bundle/src/utils/providers/grok/grok-headers.ts +199 -0
  176. package/bundle/src/utils/providers/grok/grok-media-client.test.ts +446 -0
  177. package/bundle/src/utils/providers/grok/grok-media-client.ts +703 -0
  178. package/bundle/src/utils/providers/grok/grok-models.test.ts +96 -0
  179. package/bundle/src/utils/providers/grok/grok-models.ts +161 -0
  180. package/bundle/src/utils/providers/grok/grok-oauth.test.ts +406 -0
  181. package/bundle/src/utils/providers/grok/grok-oauth.ts +771 -0
  182. package/bundle/src/utils/providers/grok/grok-quota.test.ts +142 -0
  183. package/bundle/src/utils/providers/grok/grok-quota.ts +198 -0
  184. package/bundle/src/utils/providers/grok/grok-refresh.test.ts +239 -0
  185. package/bundle/src/utils/providers/grok/grok-refresh.ts +325 -0
  186. package/bundle/src/utils/providers/grok/grok-types.test.ts +252 -0
  187. package/bundle/src/utils/providers/grok/grok-types.ts +374 -0
  188. package/bundle/src/utils/providers/grok/grok-voice-client.test.ts +321 -0
  189. package/bundle/src/utils/providers/grok/grok-voice-client.ts +284 -0
  190. package/bundle/src/utils/providers/grok/index.ts +20 -0
  191. package/bundle/src/utils/providers/openai/openai-backend-protocol.ts +221 -137
  192. package/bundle/src/utils/providers/openai/openai-callback-relay.ts +12 -1
  193. package/bundle/src/utils/providers/openai/openai-constants.ts +2 -0
  194. package/bundle/src/utils/providers/openai/openai-direct-client.ts +111 -21
  195. package/bundle/src/utils/providers/openai/openai-dispatcher.ts +322 -169
  196. package/bundle/src/utils/providers/openai/openai-image-generation.ts +116 -36
  197. package/bundle/src/utils/providers/openai/openai-oauth.ts +48 -20
  198. package/bundle/src/utils/providers/openai/openai-quota.ts +77 -46
  199. package/bundle/src/utils/providers/openai/openai-refresh.ts +42 -18
  200. package/bundle/src/utils/providers/openai/openai-sse.ts +27 -3
  201. package/bundle/src/utils/providers/openai/openai-transport-config.ts +2 -0
  202. package/bundle/src/utils/quiet-hours.ts +12 -1
  203. package/bundle/src/utils/slack-notify.ts +44 -13
  204. package/bundle/src/utils/subset-loaders.ts +7 -7
  205. package/bundle/web-dist/client/assets/clsx-5XM_pHvN.js +1 -0
  206. package/bundle/web-dist/client/assets/index-BA7uQ-6c.js +31 -0
  207. package/bundle/web-dist/client/assets/index-Be2qCZmI.css +1 -0
  208. package/bundle/web-dist/client/assets/logs-C47OJGEI.js +1 -0
  209. package/bundle/web-dist/client/assets/monit-BS9no0dU.js +4 -0
  210. package/bundle/web-dist/client/assets/plus-sdACTfH0.js +1 -0
  211. package/bundle/web-dist/client/assets/refresh-cw-CY8o_1cT.js +1 -0
  212. package/bundle/web-dist/client/assets/request-model-BRtFuZvj.js +1 -0
  213. package/bundle/web-dist/client/assets/routes-kqgkUxE8.js +5 -0
  214. package/bundle/web-dist/client/assets/{services.generated-BsieU37H.js → services.generated-CefiDXEv.js} +5 -5
  215. package/bundle/web-dist/client/assets/settings-DNDvFGSw.js +1 -0
  216. package/bundle/web-dist/client/assets/show-u8Np69q3.js +2 -0
  217. package/bundle/web-dist/client/assets/tokens-QvP410NW.js +1 -0
  218. package/bundle/web-dist/client/assets/total-cost-MnfKU8IN.js +1 -0
  219. package/bundle/web-dist/client/assets/use-oauth-login-flow-Bzdh28Ws.js +1 -0
  220. package/bundle/web-dist/client/assets/use-update-token-mutation-CfJKaxmR.js +1 -0
  221. package/bundle/web-dist/client/assets/vendor-react-CUFFrVN9.js +244 -0
  222. package/bundle/web-dist/client/assets/vendor-tanstack-Bf_jag9G.js +1 -0
  223. package/bundle/web-dist/client/index.html +6 -6
  224. package/bundle/web-dist/server/assets/clsx-D_N5PN_2.js +16 -0
  225. package/bundle/web-dist/server/assets/{lazyRouteComponent-Dtd0NR4r.js → lazyRouteComponent-D8iTIHyn.js} +129 -2
  226. package/bundle/web-dist/server/assets/logs-B3OTd9hy.js +825 -0
  227. package/bundle/web-dist/server/assets/{monit-DvzribSE.js → monit-B2hqorPe.js} +385 -126
  228. package/bundle/web-dist/server/assets/plus-DwG7h9kq.js +28 -0
  229. package/bundle/web-dist/server/assets/{react-dom-B4a6-uuR.js → react-dom-BIYQzBqG.js} +2 -129
  230. package/bundle/web-dist/server/assets/refresh-cw-mMBkwOq0.js +44 -0
  231. package/bundle/web-dist/server/assets/{request-model-CbqfnQOJ.js → request-model-I6OdODSH.js} +15 -6
  232. package/bundle/web-dist/server/assets/{routes-BAPWTizT.js → routes-B95YlUv2.js} +760 -213
  233. package/bundle/web-dist/server/assets/{services.generated-CEbGjsI0.js → services.generated-DQATJ6qf.js} +12821 -12194
  234. package/bundle/web-dist/server/assets/settings-C3gbGk0m.js +830 -0
  235. package/bundle/web-dist/server/assets/{show-CxVZTAdv.js → show-Bxaj3rhH.js} +1355 -419
  236. package/bundle/web-dist/server/assets/tokens-CZjH3cB7.js +1038 -0
  237. package/bundle/web-dist/server/assets/total-cost-fTE9Xy82.js +18 -0
  238. package/bundle/web-dist/server/assets/use-oauth-login-flow-CKDHgc3U.js +2379 -0
  239. package/bundle/web-dist/server/assets/{use-update-token-mutation-CfYmk_4_.js → use-update-token-mutation-BEbgOzaa.js} +1 -1
  240. package/bundle/web-dist/server/entry-server.generated.js +4303 -22810
  241. package/dist/cli.js +9 -9
  242. package/package.json +4 -11
  243. package/postinstall.mjs +12 -0
  244. package/skills/qgrid/SKILL.md +1 -0
  245. package/skills/qgrid/references/cli-env-and-server-boot.md +4 -1
  246. package/skills/qgrid/references/decision-rationale.md +24 -1
  247. package/skills/qgrid/references/grok-runtime.md +89 -0
  248. package/skills/qgrid/references/provider-runtime-differences.md +30 -29
  249. package/skills/qgrid/references/repo-map.md +10 -0
  250. package/skills/qgrid/references/request-log-run-lifecycle.md +1 -1
  251. package/skills/qgrid/references/sonamu-api-web-flow.md +1 -1
  252. package/skills/qgrid/references/token-auth-quota-lifecycle.md +56 -3
  253. package/bundle/dist/node_modules/.pnpm/@jridgewell_sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js +0 -406
  254. package/bundle/dist/node_modules/.pnpm/@vitest_expect@4.1.10/node_modules/@vitest/expect/dist/index.js +0 -1507
  255. package/bundle/dist/node_modules/.pnpm/@vitest_pretty-format@4.1.10/node_modules/@vitest/pretty-format/dist/index.js +0 -887
  256. package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/chunk-artifact.js +0 -2756
  257. package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/index.js +0 -8
  258. package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/utils.js +0 -8
  259. package/bundle/dist/node_modules/.pnpm/@vitest_snapshot@4.1.10/node_modules/@vitest/snapshot/dist/index.js +0 -922
  260. package/bundle/dist/node_modules/.pnpm/@vitest_spy@4.1.10/node_modules/@vitest/spy/dist/index.js +0 -386
  261. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js +0 -121
  262. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/constants.js +0 -51
  263. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/diff.js +0 -1317
  264. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/display.js +0 -561
  265. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/error.js +0 -40
  266. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/helpers.js +0 -272
  267. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/offset.js +0 -27
  268. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/serialize.js +0 -77
  269. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/source-map.js +0 -381
  270. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/timers.js +0 -51
  271. package/bundle/dist/node_modules/.pnpm/chai@6.2.2/node_modules/chai/index.js +0 -2986
  272. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/branding.js +0 -10
  273. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/index.js +0 -109
  274. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/messages.js +0 -10
  275. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/overloads.js +0 -10
  276. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/utils.js +0 -10
  277. package/bundle/dist/node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.js +0 -1126
  278. package/bundle/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/index.js +0 -21
  279. package/bundle/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.js +0 -432
  280. package/bundle/dist/node_modules/.pnpm/tinybench@2.9.0/node_modules/tinybench/dist/index.js +0 -517
  281. package/bundle/dist/node_modules/.pnpm/tinyrainbow@3.1.0/node_modules/tinyrainbow/dist/index.js +0 -101
  282. package/bundle/dist/node_modules/.pnpm/vite@8.0.3_@emnapi_core@1.11.2_@emnapi_runtime@1.11.2_@types_node@25.0.7_esbuild@0.27.4_5b35fc1fb85d2af4d105e0d74f940f50/node_modules/vite/dist/node/module-runner.js +0 -1265
  283. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/_commonjsHelpers.D26ty3Ew.js +0 -9
  284. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/benchmark.CX_oY03V.js +0 -41
  285. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/evaluatedModules.Dg1zASAC.js +0 -19
  286. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/index.Chj8NDwU.js +0 -202
  287. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/index.DdgEv5B1.js +0 -46
  288. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/rpc.MzXet3jl.js +0 -119
  289. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/test.DNmyFkvJ.js +0 -3044
  290. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/utils.BX5Fg8C4.js +0 -59
  291. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/index.js +0 -28
  292. package/bundle/dist/testing/setup-mocks.js +0 -16
  293. package/bundle/src/testing/setup-mocks.ts +0 -44
  294. package/bundle/web-dist/client/assets/index-Bw2s88Ot.css +0 -1
  295. package/bundle/web-dist/client/assets/index-CrXKu_J8.js +0 -106
  296. package/bundle/web-dist/client/assets/logs-B2SmWJXA.js +0 -1
  297. package/bundle/web-dist/client/assets/monit-D-JwXXoA.js +0 -1
  298. package/bundle/web-dist/client/assets/plus-B62CuqT8.js +0 -1
  299. package/bundle/web-dist/client/assets/refresh-cw-NNcU0Cmq.js +0 -1
  300. package/bundle/web-dist/client/assets/request-model-CojtinqK.js +0 -1
  301. package/bundle/web-dist/client/assets/routes-C5r4gTvY.js +0 -5
  302. package/bundle/web-dist/client/assets/settings-D3tDSAck.js +0 -1
  303. package/bundle/web-dist/client/assets/show-Cah_kUKC.js +0 -2
  304. package/bundle/web-dist/client/assets/tokens-DU2Iyxxd.js +0 -1
  305. package/bundle/web-dist/client/assets/use-oauth-login-flow-D0UaR9_e.js +0 -1
  306. package/bundle/web-dist/client/assets/use-update-token-mutation-DAq0F8p-.js +0 -1
  307. package/bundle/web-dist/client/assets/vendor-react-DH4kUfK2.js +0 -9
  308. package/bundle/web-dist/client/assets/vendor-tanstack-DJRQAbrY.js +0 -1
  309. package/bundle/web-dist/server/assets/logs-l91avYif.js +0 -509
  310. package/bundle/web-dist/server/assets/plus-KZrECewT.js +0 -19
  311. package/bundle/web-dist/server/assets/refresh-cw-BND93JrF.js +0 -23
  312. package/bundle/web-dist/server/assets/settings-BZR5HSAL.js +0 -461
  313. package/bundle/web-dist/server/assets/tokens-D1hb4eKk.js +0 -448
  314. package/bundle/web-dist/server/assets/use-oauth-login-flow-Cvdy0zF8.js +0 -178
  315. package/dist/cli.d.ts +0 -10
  316. /package/bundle/web-dist/client/assets/{cost-DH2jZbrw.js → cost-DB3HbU7T.js} +0 -0
  317. /package/bundle/web-dist/client/assets/{preload-helper-ca-nBW7U.js → preload-helper-DWTEM3RW.js} +0 -0
  318. /package/bundle/web-dist/server/assets/{cost-eEHeTRT5.js → cost-BC9yzyA9.js} +0 -0
@@ -1,30 +1,58 @@
1
+ import { SD } from "../../i18n/sd.generated.js";
1
2
  import { getAccessToken, getExpiresAt, getRefreshToken } from "../../utils/providers/common/credentials.js";
3
+ import { GROK_IMAGE_DEFAULT_MODEL, GROK_STT_DEFAULT_MODEL, GROK_VIDEO_DEFAULT_MODEL } from "../../utils/providers/grok/grok-constants.js";
4
+ import { grokImageCost, grokReportedCost } from "../../utils/providers/common/model-cost.js";
5
+ import { isProviderId } from "../../utils/providers/common/provider-types.js";
2
6
  import { CallerSchemaValidationError } from "../../utils/providers/common/schema-validation.js";
3
- import { StreamEvents } from "./qgrid.types.js";
7
+ import { GenerateImagesInput, REQUEST_BODY_LIMIT_BYTES, SpeakInput, StreamEvents, TranscribeInput, VideoStartInput, VideoStatusInput } from "./qgrid.types.js";
4
8
  import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.140.0/helpers/esm/decorateMetadata.js";
5
9
  import __decorate from "../../_virtual/_@oxc-project_runtime@0.140.0/helpers/esm/decorate.js";
6
10
  import { TokenModel } from "../token/token.model.js";
7
11
  import { deactivateAuthDeadToken, notifyTokenAdded } from "./token-death.js";
12
+ import { GrokCredentials, TokenCredentials } from "../token/token.types.js";
8
13
  import { ToolSchemaCompositionError } from "./tool-emulation-schema.js";
9
14
  import { QgridDispatcher, buildAndValidateStrictOutputSchema, completedDriverFromImageFailure } from "./qgrid.dispatcher.js";
10
15
  import { MICRO_USD, RequestLogModel } from "../request-log/request-log.model.js";
11
16
  import { CONSOLE_CALLBACK_URL, RefreshFailedError, buildAuthUrl, exchangeCodeForTokens, fetchUsage, generatePKCE, refreshAccessToken } from "./oauth.js";
12
17
  import { CODEX_IMAGE_GENERATION_MODEL } from "./qgrid-image-generation.js";
13
18
  import { afterQuery, beforeQuery, finishRunAborted, finishRunWithError } from "./qgrid-run-lifecycle.js";
19
+ import { GrokCredentials as GrokCredentials$1 } from "../../utils/providers/grok/grok-types.js";
20
+ import { GrokOAuthError, completeGrokOAuth, pollGrokDeviceCode, startGrokDeviceCode, startGrokOAuth } from "../../utils/providers/grok/grok-oauth.js";
21
+ import { GrokCapabilityUnavailableError, GrokCapacityError, GrokInvalidRequestError, GrokNoWorkersError, GrokOnDemandExcludedError, GrokRateLimitedError, GrokZdrVideoUnavailableError } from "../../utils/providers/grok/grok-dispatcher.js";
22
+ import "../../utils/providers/grok/index.js";
23
+ import { GrokContentPolicyError, decodeGrokImages, summarizeGrokVideoStatus } from "../../utils/providers/grok/grok-media-client.js";
24
+ import "../../utils/providers/grok/grok-voice-client.js";
14
25
  import { OPENAI_CALLBACK_PORTS, openAICallbackRedirectUri, startOpenAICallbackRelay } from "../../utils/providers/openai/openai-callback-relay.js";
15
26
  import { buildOpenAIAuthUrl, exchangeOpenAICode, generateOpenAIPKCE } from "../../utils/providers/openai/openai-oauth.js";
16
- import { TokenCredentials } from "../token/token.types.js";
17
- import { BadRequestException, BaseFrameClass, Sonamu, api, stream } from "sonamu";
27
+ import { z } from "zod";
28
+ import { BadRequestException, BaseFrameClass, InternalServerErrorException, NotFoundException, ServiceUnavailableException, SoException, Sonamu, api, stream } from "sonamu";
18
29
  import { getLogger } from "@logtape/logtape";
19
30
  import crypto from "node:crypto";
20
31
  import { getCacheManagerRef } from "sonamu/cache";
21
32
  //#region src/application/qgrid/qgrid.frame.ts
22
33
  const pendingStreams = /* @__PURE__ */ new Map();
34
+ const PendingOAuth = z.object({
35
+ codeVerifier: z.string(),
36
+ name: z.string(),
37
+ redirectUri: z.string(),
38
+ provider: z.enum([
39
+ "anthropic",
40
+ "openai",
41
+ "grok"
42
+ ])
43
+ });
23
44
  const OAUTH_STATE_PREFIX = "oauth:state:";
24
45
  const OAUTH_STATE_TTL = "5m";
25
46
  const OAUTH_STATE_TTL_MS = 5 * 6e4;
47
+ const GROK_LATEST_STATE_KEY = "oauth:grok:latest";
48
+ const GROK_DEVICE_PREFIX = "oauth:grok:device:";
49
+ const PendingGrokDevice = z.object({
50
+ name: z.string(),
51
+ interval: z.number(),
52
+ expiresAtMs: z.number()
53
+ });
26
54
  function unixSecondsToIso(seconds) {
27
- return typeof seconds === "number" ? (/* @__PURE__ */ new Date(seconds * 1e3)).toISOString() : null;
55
+ return seconds === null || seconds === void 0 ? null : (/* @__PURE__ */ new Date(seconds * 1e3)).toISOString();
28
56
  }
29
57
  async function setOAuthState(state, data) {
30
58
  const cache = getCacheManagerRef();
@@ -40,18 +68,74 @@ async function getOAuthState(state) {
40
68
  if (!cache) throw new Error("CacheManager not initialized");
41
69
  const raw = await cache.get({ key: `${OAUTH_STATE_PREFIX}${state}` });
42
70
  if (!raw) return void 0;
43
- return JSON.parse(raw);
71
+ return PendingOAuth.safeParse(JSON.parse(raw)).data;
44
72
  }
45
73
  async function deleteOAuthState(state) {
46
74
  const cache = getCacheManagerRef();
47
75
  if (!cache) return;
48
76
  await cache.delete({ key: `${OAUTH_STATE_PREFIX}${state}` });
49
77
  }
78
+ async function setGrokLatestState(state) {
79
+ const cache = getCacheManagerRef();
80
+ if (!cache) throw new Error("CacheManager not initialized");
81
+ await cache.set({
82
+ key: GROK_LATEST_STATE_KEY,
83
+ value: state,
84
+ ttl: OAUTH_STATE_TTL
85
+ });
86
+ }
87
+ async function getGrokLatestState() {
88
+ const cache = getCacheManagerRef();
89
+ if (!cache) throw new Error("CacheManager not initialized");
90
+ return await cache.get({ key: GROK_LATEST_STATE_KEY }) ?? void 0;
91
+ }
92
+ async function setGrokDeviceState(deviceCode, data) {
93
+ const cache = getCacheManagerRef();
94
+ if (!cache) throw new Error("CacheManager not initialized");
95
+ const ttlSec = Math.max(1, Math.ceil((data.expiresAtMs - Date.now()) / 1e3));
96
+ await cache.set({
97
+ key: `${GROK_DEVICE_PREFIX}${deviceCode}`,
98
+ value: JSON.stringify(data),
99
+ ttl: `${ttlSec}s`
100
+ });
101
+ }
102
+ async function getGrokDeviceState(deviceCode) {
103
+ const cache = getCacheManagerRef();
104
+ if (!cache) throw new Error("CacheManager not initialized");
105
+ const raw = await cache.get({ key: `${GROK_DEVICE_PREFIX}${deviceCode}` });
106
+ if (!raw) return void 0;
107
+ const data = PendingGrokDevice.safeParse(JSON.parse(raw)).data;
108
+ return data && data.expiresAtMs > Date.now() ? data : void 0;
109
+ }
110
+ async function deleteGrokDeviceState(deviceCode) {
111
+ const cache = getCacheManagerRef();
112
+ if (!cache) return;
113
+ await cache.delete({ key: `${GROK_DEVICE_PREFIX}${deviceCode}` });
114
+ }
115
+ function grokOAuthBadRequest(cause) {
116
+ if (cause instanceof GrokOAuthError) throw new BadRequestException(SD("qgrid.grokLoginFailed")(cause.message));
117
+ throw cause;
118
+ }
119
+ function grokTokenSnapshot(tokenId) {
120
+ return QgridDispatcher.grokDispatcher?.tokenStates?.().find((state) => state.id === tokenId);
121
+ }
122
+ /** Stores refreshed Grok credentials; the token subscriber pushes the row to the dispatcher. */
123
+ async function persistGrokCredentials(tokenId, next) {
124
+ const credentials = GrokCredentials$1.parse(next);
125
+ const row = await TokenModel.findById("A", tokenId);
126
+ await TokenModel.save([{
127
+ id: row.id,
128
+ provider: row.provider,
129
+ credentials,
130
+ name: row.name,
131
+ reauth_required: false
132
+ }]);
133
+ }
50
134
  const trustedLoopbackBase = () => `http://localhost:${process.env.PORT ?? "44900"}`;
51
135
  function isRemoteOAuthRequest() {
52
136
  try {
53
137
  const { headers } = Sonamu.getContext();
54
- const origin = typeof headers.origin === "string" ? headers.origin : void 0;
138
+ const origin = headers.origin;
55
139
  const forwarded = headers["x-forwarded-host"];
56
140
  const rawHost = Array.isArray(forwarded) ? forwarded[0] : forwarded ?? headers.host;
57
141
  const host = origin ? new URL(origin).hostname : new URL(`http://${rawHost ?? "localhost"}`).hostname;
@@ -95,22 +179,22 @@ function parsePastedOAuthResult(input) {
95
179
  }
96
180
  function rejectImageGenerationStream(args) {
97
181
  if (!args.imageGeneration && args.model !== `openai/gpt-image-2`) return;
98
- throw new BadRequestException("qgrid: imageGeneration is not supported with streaming; use query or generateImage with qgrid.image() instead.");
182
+ throw new BadRequestException(SD("error.detail")("qgrid: imageGeneration is not supported with streaming; use query or generateImage with qgrid.image() instead."));
99
183
  }
100
184
  function rejectInvalidImageQuery(args) {
101
185
  const standalone = args.model === `openai/${CODEX_IMAGE_GENERATION_MODEL}`;
102
186
  if (!standalone && args.imageGeneration !== "auto") return;
103
- if (standalone && args.imageGeneration !== true) throw new BadRequestException("qgrid: the image model requires imageGeneration: true; use qgrid.image() with generateImage.");
104
- if (args.tools?.length || args.jsonSchema !== void 0) throw new BadRequestException("qgrid: automatic and standalone image generation do not support caller tools or structured output.");
105
- if (args.imageGenerationOptions?.outputFormat && args.imageGenerationOptions.outputFormat !== "png") throw new BadRequestException("qgrid: automatic and standalone image generation only support PNG output.");
187
+ if (standalone && args.imageGeneration !== true) throw new BadRequestException(SD("error.detail")("qgrid: the image model requires imageGeneration: true; use qgrid.image() with generateImage."));
188
+ if (args.tools?.length || args.jsonSchema !== void 0) throw new BadRequestException(SD("error.detail")("qgrid: automatic and standalone image generation do not support caller tools or structured output."));
189
+ if (args.imageGenerationOptions?.outputFormat && args.imageGenerationOptions.outputFormat !== "png") throw new BadRequestException(SD("error.detail")("qgrid: automatic and standalone image generation only support PNG output."));
106
190
  }
107
191
  function rejectInvalidCallerSchemas(args) {
108
192
  if (args.jsonSchema === void 0 && !args.tools?.length) return;
109
193
  try {
110
194
  buildAndValidateStrictOutputSchema(args);
111
195
  } catch (error) {
112
- if (error instanceof CallerSchemaValidationError || error instanceof ToolSchemaCompositionError) throw new BadRequestException(error.message);
113
- if (error instanceof Error) throw new BadRequestException(`qgrid: caller schema cannot be normalized: ${error.message}`);
196
+ if (error instanceof CallerSchemaValidationError || error instanceof ToolSchemaCompositionError) throw new BadRequestException(SD("error.detail")(error.message));
197
+ if (error instanceof Error) throw new BadRequestException(SD("error.detail")(`qgrid: caller schema cannot be normalized: ${error.message}`));
114
198
  throw error;
115
199
  }
116
200
  }
@@ -118,10 +202,10 @@ async function resolveTokenName(args) {
118
202
  if (!args.tokenName) return args;
119
203
  const tokenProvider = args.tokenName.split("/", 1)[0];
120
204
  const modelProvider = args.model?.split("/", 1)[0];
121
- if (tokenProvider !== "anthropic" && tokenProvider !== "openai") throw new BadRequestException(`Invalid token name: ${args.tokenName}`);
122
- if (modelProvider !== tokenProvider) throw new BadRequestException("Token provider does not match model provider");
205
+ if (!isProviderId(tokenProvider)) throw new BadRequestException(SD("error.detail")(`Invalid token name: ${args.tokenName}`));
206
+ if (modelProvider !== tokenProvider) throw new BadRequestException(SD("error.detail")("Token provider does not match model provider"));
123
207
  const token = await TokenModel.findActiveByProviderAndName("A", tokenProvider, args.tokenName);
124
- if (!token) throw new BadRequestException(`Active token not found: ${args.tokenName}`);
208
+ if (!token) throw new BadRequestException(SD("error.detail")(`Active token not found: ${args.tokenName}`));
125
209
  return {
126
210
  ...args,
127
211
  preferredTokenId: token.id,
@@ -155,6 +239,294 @@ function createHttpDisconnectHandle() {
155
239
  const logger = getLogger(["qgrid"]);
156
240
  const oauthLogger = getLogger(["qgrid", "oauth"]);
157
241
  const inflightAnthropicRefresh = /* @__PURE__ */ new Map();
242
+ const mediaLogger = getLogger(["qgrid", "media"]);
243
+ const MEDIA_TOOL_NAMES = {
244
+ image: "image_generation",
245
+ video: "video_generation",
246
+ stt: "transcription",
247
+ tts: "speech"
248
+ };
249
+ function grokNotReady() {
250
+ return QgridDispatcher.startupState.grok === "failed" ? new InternalServerErrorException(SD("qgrid.dispatcherFailed")("Grok")) : new ServiceUnavailableException(SD("qgrid.dispatcherStarting")("Grok"));
251
+ }
252
+ function grokMedia() {
253
+ const dispatcher = QgridDispatcher.grokDispatcher;
254
+ const generateImages = dispatcher?.generateImages;
255
+ const editImages = dispatcher?.editImages;
256
+ const startVideo = dispatcher?.startVideo;
257
+ const getVideo = dispatcher?.getVideo;
258
+ if (!dispatcher || !generateImages || !editImages || !startVideo || !getVideo) throw grokNotReady();
259
+ return {
260
+ generateImages: generateImages.bind(dispatcher),
261
+ editImages: editImages.bind(dispatcher),
262
+ startVideo: startVideo.bind(dispatcher),
263
+ getVideo: getVideo.bind(dispatcher)
264
+ };
265
+ }
266
+ function grokVoice() {
267
+ const dispatcher = QgridDispatcher.grokDispatcher;
268
+ const transcribe = dispatcher?.transcribe;
269
+ const speak = dispatcher?.speak;
270
+ if (!dispatcher || !transcribe || !speak) throw grokNotReady();
271
+ return {
272
+ transcribe: transcribe.bind(dispatcher),
273
+ speak: speak.bind(dispatcher)
274
+ };
275
+ }
276
+ var TooManyRequestsException = class extends SoException {
277
+ constructor(message) {
278
+ super(429, message);
279
+ }
280
+ };
281
+ /**
282
+ * Every Grok token is cooling down. A 429 rather than a 503: the server error handler pins 503's
283
+ * Retry-After to its startup interval, while this delay comes from the upstream cooldown.
284
+ */
285
+ function grokRateLimited(error) {
286
+ let reply;
287
+ try {
288
+ const ctx = Sonamu.getContext();
289
+ if (ctx.transport === "http") reply = ctx.reply;
290
+ } catch {}
291
+ if (reply && !reply.raw.headersSent) reply.header("Retry-After", String(error.retryAfterSec));
292
+ return new TooManyRequestsException(SD("qgrid.grokRateLimited")(error.retryAfterSec));
293
+ }
294
+ /**
295
+ * Caller-fault Grok errors become 400/429/503 at the chat and media boundaries; upstream and
296
+ * provider failures propagate unchanged (500 by the server error handler). "No eligible token for
297
+ * this request class" (no workers, in-flight cap, on-demand D6, ZDR video) is a 503, not a server
298
+ * fault; every token cooling down is a 429 with the soonest retry delay.
299
+ */
300
+ function throwGrokCallerError(cause) {
301
+ if (cause instanceof GrokInvalidRequestError) throw new BadRequestException(SD("qgrid.grokInvalidRequest")(cause.message));
302
+ if (cause instanceof GrokContentPolicyError) throw new BadRequestException(SD("qgrid.grokContentPolicy")(cause.message));
303
+ if (cause instanceof GrokCapabilityUnavailableError) throw new ServiceUnavailableException(SD("qgrid.grokCapabilityUnavailable")(cause.message));
304
+ if (cause instanceof GrokOnDemandExcludedError) throw new ServiceUnavailableException(SD("qgrid.grokOnDemandExcluded")(cause.tokenNames.join(", ")));
305
+ if (cause instanceof GrokZdrVideoUnavailableError) throw new ServiceUnavailableException(SD("qgrid.grokZdrVideoUnavailable")(cause.tokenNames.join(", ")));
306
+ if (cause instanceof GrokCapacityError) throw new ServiceUnavailableException(SD("qgrid.grokCapacity"));
307
+ if (cause instanceof GrokRateLimitedError) throw grokRateLimited(cause);
308
+ if (cause instanceof GrokNoWorkersError) throw new ServiceUnavailableException(SD("qgrid.grokNoWorkers")(cause.message));
309
+ throw cause;
310
+ }
311
+ var PayloadTooLargeException = class extends SoException {
312
+ constructor(message) {
313
+ super(413, message);
314
+ }
315
+ };
316
+ const MiB = 1024 * 1024;
317
+ /**
318
+ * Fastify rejects a body over `bodyLimit` before routing with FST_ERR_CTP_BODY_TOO_LARGE, which is
319
+ * not a Sonamu exception and would otherwise answer 500. The server error handler applies this
320
+ * first so the caller gets a Sonamu 413.
321
+ */
322
+ function mapRequestBodyTooLarge(error) {
323
+ if ("code" in error && error.code === "FST_ERR_CTP_BODY_TOO_LARGE") return new PayloadTooLargeException(SD("qgrid.requestBodyTooLarge")(REQUEST_BODY_LIMIT_BYTES / MiB));
324
+ return error;
325
+ }
326
+ function parseMediaInput(schema, value) {
327
+ const parsed = schema.safeParse(value);
328
+ if (!parsed.success) {
329
+ const detail = parsed.error.issues.map((issue) => `${issue.path.join(".") || "input"}: ${issue.message}`).join("; ");
330
+ throw new BadRequestException(SD("qgrid.invalidInput")(detail));
331
+ }
332
+ return parsed.data;
333
+ }
334
+ async function resolveGrokTokenSelection(tokenName) {
335
+ if (!tokenName) return {};
336
+ if (!tokenName.startsWith("grok/")) throw new BadRequestException(SD("error.detail")("Token provider does not match model provider"));
337
+ const token = await TokenModel.findActiveByProviderAndName("A", "grok", tokenName);
338
+ if (!token) throw new BadRequestException(SD("error.detail")(`Active token not found: ${tokenName}`));
339
+ return {
340
+ preferredTokenId: token.id,
341
+ requirePreferredToken: true
342
+ };
343
+ }
344
+ function routeModelId(model, fallback) {
345
+ const id = model ? model.slice(5) : fallback;
346
+ return {
347
+ id,
348
+ route: `grok/${id}`
349
+ };
350
+ }
351
+ /** Adds the provider thread coordinate to the lifecycle run context without dropping either. */
352
+ function mergeRunContext(lifecycle, threadCoord) {
353
+ if (!lifecycle && !threadCoord) return void 0;
354
+ const runContext = { ...lifecycle };
355
+ if (threadCoord) runContext.threadCoord = threadCoord;
356
+ return runContext;
357
+ }
358
+ function microUsd(usd) {
359
+ return usd === void 0 ? void 0 : Math.round(usd * MICRO_USD);
360
+ }
361
+ /** Reference-image log metadata. Data URLs keep their bytes only when `withData` (images). */
362
+ function describeImageRefs(refs, withData) {
363
+ return refs.map((ref) => {
364
+ const match = /^data:([^;,]+);base64,(.*)$/.exec(ref);
365
+ if (!match) return { url: ref };
366
+ const [, mediaType = "", data = ""] = match;
367
+ const byteSize = Buffer.byteLength(data, "base64");
368
+ return withData ? {
369
+ mediaType,
370
+ data,
371
+ byteSize
372
+ } : {
373
+ mediaType,
374
+ byteSize
375
+ };
376
+ });
377
+ }
378
+ function imageTagForLog(b64, mimeType, alt) {
379
+ return `<img src="data:${mimeType};base64,${b64}" alt="${(alt ?? "generated image").replace(/[&"<>]/g, (ch) => `&#${ch.charCodeAt(0)};`)}" />`;
380
+ }
381
+ async function startMediaRun(loggerEnabled, start) {
382
+ if (loggerEnabled === false) return void 0;
383
+ return RequestLogModel.createRun({
384
+ user_prompt: start.prompt,
385
+ requested_model_name: start.model,
386
+ project_name: start.projectName,
387
+ is_image_generation: start.kind === "image"
388
+ });
389
+ }
390
+ function mediaToolSteps(kind, steps, durationMs) {
391
+ return steps.map((step, index) => {
392
+ const fields = {
393
+ step_index: 0,
394
+ type: "tool_call",
395
+ tool_call_index: index,
396
+ tool_call_id: step.toolCallId,
397
+ tool_name: MEDIA_TOOL_NAMES[kind],
398
+ tool_args: JSON.stringify(step.args)
399
+ };
400
+ if (step.result !== void 0) fields.tool_result = step.result;
401
+ fields.tool_duration_ms = durationMs;
402
+ return fields;
403
+ });
404
+ }
405
+ function mediaCostFields(kind, model, cost) {
406
+ if (kind === "image") return {
407
+ cost_usd: 0,
408
+ cost_source: cost?.costSource ?? null,
409
+ is_image_generation: true,
410
+ image_cost_usd: microUsd(cost?.costUsd) ?? null,
411
+ image_cost_method: cost ? `${cost.costSource === "provider" ? "reported" : "catalog"}:${model}:ticks=${cost.ticks}` : null
412
+ };
413
+ return {
414
+ cost_usd: microUsd(cost?.costUsd) ?? null,
415
+ cost_source: cost?.costSource ?? null
416
+ };
417
+ }
418
+ function mediaFinishFields(success) {
419
+ return {
420
+ status: "succeeded",
421
+ response: success.response,
422
+ token_name: success.tokenName,
423
+ requested_model_name: success.model,
424
+ model_name: success.model,
425
+ input_tokens: 0,
426
+ output_tokens: 0,
427
+ cache_read_tokens: 0,
428
+ cache_creation_tokens: 0,
429
+ duration_ms: success.durationMs,
430
+ ...mediaCostFields(success.kind, success.model, success.cost)
431
+ };
432
+ }
433
+ async function finishMediaRun(requestLogId, success) {
434
+ if (requestLogId === void 0) return;
435
+ try {
436
+ for (const step of mediaToolSteps(success.kind, success.steps, success.durationMs)) await RequestLogModel.appendStep(requestLogId, step);
437
+ await RequestLogModel.finishRun(requestLogId, mediaFinishFields(success));
438
+ } catch (e) {
439
+ mediaLogger.error(`${success.kind} request log failed: ${e instanceof Error ? e.message : String(e)}`);
440
+ }
441
+ }
442
+ async function failMediaRun(requestLogId, cause, aborted) {
443
+ if (requestLogId === void 0) return;
444
+ try {
445
+ await RequestLogModel.finishRun(requestLogId, {
446
+ status: aborted ? "aborted" : "error",
447
+ error_message: aborted ? "client disconnected" : cause instanceof Error ? cause.message : String(cause)
448
+ });
449
+ } catch (e) {
450
+ mediaLogger.error(`media request log failed: ${e instanceof Error ? e.message : String(e)}`);
451
+ }
452
+ }
453
+ /**
454
+ * One provider call against an open media run. A failure closes the run as error (or aborted on
455
+ * client disconnect) and surfaces as the caller-facing Grok error; success leaves the run open.
456
+ */
457
+ async function dispatchMediaCall(requestLogId, call) {
458
+ const disconnect = createHttpDisconnectHandle();
459
+ let result;
460
+ try {
461
+ result = await call(disconnect.signal);
462
+ } catch (e) {
463
+ await failMediaRun(requestLogId, e, disconnect.signal.aborted);
464
+ throwGrokCallerError(e);
465
+ } finally {
466
+ disconnect.dispose();
467
+ }
468
+ return result;
469
+ }
470
+ /**
471
+ * A one-shot media endpoint: open the run, make the provider call, then log the result. `dispatch`
472
+ * returns the endpoint output and what the run records about it.
473
+ */
474
+ async function runMediaEndpoint(start, dispatch) {
475
+ const requestLogId = await startMediaRun(start.logger, start);
476
+ const startedAt = Date.now();
477
+ const { output, log } = await dispatchMediaCall(requestLogId, (signal) => dispatch(signal, requestLogId));
478
+ await finishMediaRun(requestLogId, {
479
+ ...log,
480
+ kind: start.kind,
481
+ model: start.model,
482
+ durationMs: Date.now() - startedAt
483
+ });
484
+ return output;
485
+ }
486
+ const VIDEO_JOB_TTL_MS = 1440 * 6e4;
487
+ const VIDEO_JOB_MAX = 1e4;
488
+ const videoJobs = /* @__PURE__ */ new Map();
489
+ function pruneVideoJobs(now) {
490
+ for (const [handle, job] of videoJobs) {
491
+ if (now - job.createdAt < VIDEO_JOB_TTL_MS && videoJobs.size <= VIDEO_JOB_MAX) break;
492
+ videoJobs.delete(handle);
493
+ }
494
+ }
495
+ function videoToolCallId(job) {
496
+ return `video_generation:${job.requestId}`;
497
+ }
498
+ async function finishVideoRun(job, final, cost) {
499
+ if (job.requestLogId === void 0) return;
500
+ try {
501
+ await RequestLogModel.continueToolRun(job.requestLogId, [{
502
+ toolCallId: videoToolCallId(job),
503
+ output: JSON.stringify({
504
+ status: final.status,
505
+ url: final.url,
506
+ durationSec: final.durationSec,
507
+ costInUsdTicks: final.costInUsdTicks,
508
+ error: final.error
509
+ }),
510
+ isError: final.status === "failed"
511
+ }]);
512
+ const fields = mediaFinishFields({
513
+ kind: "video",
514
+ model: job.model,
515
+ tokenName: job.tokenName,
516
+ durationMs: Date.now() - job.createdAt,
517
+ response: final.url ?? "",
518
+ cost
519
+ });
520
+ await RequestLogModel.finishRun(job.requestLogId, final.status === "done" ? fields : {
521
+ ...fields,
522
+ status: "error",
523
+ error_message: final.error ?? "video generation failed"
524
+ });
525
+ } catch (e) {
526
+ mediaLogger.error(`video request log failed: ${e instanceof Error ? e.message : String(e)}`);
527
+ }
528
+ }
529
+ const GROK_TTS_LOG_MODEL = "grok/tts";
158
530
  var QgridFrameClass = class extends BaseFrameClass {
159
531
  constructor() {
160
532
  super("Qgrid");
@@ -165,7 +537,11 @@ var QgridFrameClass = class extends BaseFrameClass {
165
537
  const resolvedArgs = await resolveTokenName(args);
166
538
  const disconnect = createHttpDisconnectHandle();
167
539
  try {
168
- if (resolvedArgs.logger === false) return await QgridDispatcher.query(resolvedArgs, disconnect.signal);
540
+ if (resolvedArgs.logger === false) try {
541
+ return await QgridDispatcher.query(resolvedArgs, disconnect.signal);
542
+ } catch (e) {
543
+ throwGrokCallerError(e);
544
+ }
169
545
  const { requestLogId, stepIndex } = await beforeQuery(resolvedArgs);
170
546
  let result;
171
547
  try {
@@ -177,26 +553,23 @@ var QgridFrameClass = class extends BaseFrameClass {
177
553
  result: completedDriver
178
554
  }] : [];
179
555
  if (disconnect.signal.aborted) await finishRunAborted(requestLogId, resolvedArgs, ...completedStep);
180
- else await finishRunWithError(requestLogId, e.message, resolvedArgs, ...completedStep);
181
- throw e;
556
+ else await finishRunWithError(requestLogId, e instanceof Error ? e.message : String(e), resolvedArgs, ...completedStep);
557
+ throwGrokCallerError(e);
182
558
  }
183
559
  try {
184
560
  const lifecycle = await afterQuery(requestLogId, stepIndex, resolvedArgs, result);
185
561
  if (disconnect.signal.aborted) await finishRunAborted(requestLogId, resolvedArgs);
186
562
  const threadCoord = result.runContext?.threadCoord;
187
- const runContext = lifecycle.runContext || threadCoord ? {
188
- ...lifecycle.runContext,
189
- ...threadCoord ? { threadCoord } : {}
190
- } : void 0;
563
+ const runContext = mergeRunContext(lifecycle.runContext, threadCoord);
191
564
  return {
192
565
  ...result,
193
566
  requestLogId,
194
567
  runContext
195
568
  };
196
569
  } catch (e) {
197
- logger.error(`query afterQuery failed: ${e.message}`);
570
+ logger.error(`query afterQuery failed: ${e instanceof Error ? e.message : String(e)}`);
198
571
  if (disconnect.signal.aborted) await finishRunAborted(requestLogId, resolvedArgs);
199
- else await finishRunWithError(requestLogId, e.message, resolvedArgs);
572
+ else await finishRunWithError(requestLogId, e instanceof Error ? e.message : String(e), resolvedArgs);
200
573
  return {
201
574
  ...result,
202
575
  requestLogId
@@ -249,7 +622,7 @@ var QgridFrameClass = class extends BaseFrameClass {
249
622
  }
250
623
  }, abortController.signal);
251
624
  } catch (e) {
252
- streamError = e;
625
+ streamError = e instanceof Error ? e : new Error(String(e));
253
626
  }
254
627
  if (clientClosed && !streamResult) {
255
628
  if (runInfo) await finishRunAborted(runInfo.requestLogId, args);
@@ -258,32 +631,29 @@ var QgridFrameClass = class extends BaseFrameClass {
258
631
  }
259
632
  if (streamResult) {
260
633
  const threadCoord = streamResult.runContext?.threadCoord;
261
- let runContext = threadCoord !== void 0 ? { threadCoord } : void 0;
634
+ let runContext = threadCoord === void 0 ? void 0 : { threadCoord };
262
635
  if (runInfo) try {
263
- const lifecycle = await afterQuery(runInfo.requestLogId, runInfo.stepIndex, args, streamResult);
264
- runContext = lifecycle.runContext || threadCoord ? {
265
- ...lifecycle.runContext,
266
- ...threadCoord ? { threadCoord } : {}
267
- } : void 0;
636
+ runContext = mergeRunContext((await afterQuery(runInfo.requestLogId, runInfo.stepIndex, args, streamResult)).runContext, threadCoord);
268
637
  if (clientClosed) {
269
638
  await finishRunAborted(runInfo.requestLogId, args);
270
639
  await sse.end();
271
640
  return;
272
641
  }
273
642
  } catch (e) {
274
- logger.error(`stream afterQuery failed: ${e.message}`);
275
- await finishRunWithError(runInfo.requestLogId, e.message, args);
643
+ logger.error(`stream afterQuery failed: ${e instanceof Error ? e.message : String(e)}`);
644
+ await finishRunWithError(runInfo.requestLogId, e instanceof Error ? e.message : String(e), args);
276
645
  if (clientClosed) {
277
646
  await finishRunAborted(runInfo.requestLogId, args);
278
647
  await sse.end();
279
648
  return;
280
649
  }
281
650
  }
282
- if (!clientClosed && !sse.closed) sse.publish("done", {
283
- ...streamResult,
284
- ...runInfo ? { requestLogId: runInfo.requestLogId } : {},
285
- runContext
286
- });
651
+ if (!clientClosed && !sse.closed) {
652
+ const done = { ...streamResult };
653
+ if (runInfo) done.requestLogId = runInfo.requestLogId;
654
+ done.runContext = runContext;
655
+ sse.publish("done", done);
656
+ }
287
657
  } else if (streamError) {
288
658
  if (runInfo) await finishRunWithError(runInfo.requestLogId, streamError.message, args);
289
659
  if (!clientClosed && !sse.closed) sse.publish("error", { message: streamError.message });
@@ -375,8 +745,8 @@ var QgridFrameClass = class extends BaseFrameClass {
375
745
  return { added: true };
376
746
  }
377
747
  async updateToken(id, name, quotaThreshold, weight, keepaliveEnabled) {
378
- if (quotaThreshold !== void 0 && quotaThreshold !== null && (!Number.isInteger(quotaThreshold) || quotaThreshold < 1 || quotaThreshold > 100)) throw new BadRequestException("quotaThreshold must be an integer between 1 and 100, or null");
379
- if (weight !== void 0 && (!Number.isInteger(weight) || weight < 1 || weight > 100)) throw new BadRequestException("weight must be an integer between 1 and 100");
748
+ if (quotaThreshold !== void 0 && quotaThreshold !== null && (!Number.isInteger(quotaThreshold) || quotaThreshold < 1 || quotaThreshold > 100)) throw new BadRequestException(SD("error.detail")("quotaThreshold must be an integer between 1 and 100, or null"));
749
+ if (weight !== void 0 && (!Number.isInteger(weight) || weight < 1 || weight > 100)) throw new BadRequestException(SD("error.detail")("weight must be an integer between 1 and 100"));
380
750
  const patch = {};
381
751
  if (name !== void 0) patch.name = name;
382
752
  if (quotaThreshold !== void 0) patch.quota_threshold = quotaThreshold;
@@ -397,7 +767,7 @@ var QgridFrameClass = class extends BaseFrameClass {
397
767
  async toggleToken(id) {
398
768
  const result = await TokenModel.toggleActive(id);
399
769
  if (!result) return { active: false };
400
- if (result.reauthRequired) throw new BadRequestException("Re-login required");
770
+ if (result.reauthRequired) throw new BadRequestException(SD("error.detail")("Re-login required"));
401
771
  return { active: result.active };
402
772
  }
403
773
  async oauthStart(name) {
@@ -417,12 +787,25 @@ var QgridFrameClass = class extends BaseFrameClass {
417
787
  }
418
788
  async oauthComplete(pastedCode) {
419
789
  const result = parsePastedOAuthResult(pastedCode);
420
- if (!result) throw new BadRequestException("expected the callback URL or code shown after login, in code#state form");
790
+ if (!result) {
791
+ const grokState = await getGrokLatestState();
792
+ const grokPending = grokState ? await getOAuthState(grokState) : void 0;
793
+ if (grokState && grokPending?.provider === "grok" && pastedCode.trim()) {
794
+ await deleteOAuthState(grokState);
795
+ await this.completeGrokLogin(pastedCode, grokState, grokPending);
796
+ return {
797
+ added: true,
798
+ name: grokPending.name
799
+ };
800
+ }
801
+ throw new BadRequestException(SD("error.detail")("expected the callback URL or code shown after login, in code#state form"));
802
+ }
421
803
  const { code, state } = result;
422
804
  const pending = await getOAuthState(state);
423
- if (!pending) throw new BadRequestException("login session not found or expired — start the login again");
805
+ if (!pending) throw new BadRequestException(SD("error.detail")("login session not found or expired — start the login again"));
424
806
  await deleteOAuthState(state);
425
807
  if (pending.provider === "openai") await this.completeOpenAILogin(code, pending);
808
+ else if (pending.provider === "grok") await this.completeGrokLogin(pastedCode, state, pending);
426
809
  else await this.completeAnthropicLogin(code, state, pending);
427
810
  return {
428
811
  added: true,
@@ -453,6 +836,31 @@ var QgridFrameClass = class extends BaseFrameClass {
453
836
  logger.info(`OpenAI token saved for ${pending.name}`);
454
837
  notifyTokenAdded(pending.name, "openai");
455
838
  }
839
+ async completeGrokLogin(codeOrUrl, state, pending) {
840
+ let credentials;
841
+ try {
842
+ credentials = await completeGrokOAuth({
843
+ codeOrUrl,
844
+ verifier: pending.codeVerifier,
845
+ redirectUri: pending.redirectUri,
846
+ state
847
+ });
848
+ } catch (error) {
849
+ grokOAuthBadRequest(error);
850
+ }
851
+ await this.saveGrokToken(credentials, pending.name);
852
+ }
853
+ async saveGrokToken(candidate, name) {
854
+ const parsed = GrokCredentials$1.safeParse(candidate);
855
+ if (!parsed.success) throw new BadRequestException(SD("qgrid.grokNotOAuthToken"));
856
+ await TokenModel.replaceByAccount("grok", parsed.data.userId, {
857
+ provider: "grok",
858
+ credentials: parsed.data,
859
+ name
860
+ });
861
+ logger.info(`Grok token saved for ${name}`);
862
+ notifyTokenAdded(name, "grok");
863
+ }
456
864
  async handleOAuthCallback(code, state, reply) {
457
865
  const pending = await getOAuthState(state);
458
866
  if (!pending) {
@@ -462,6 +870,7 @@ var QgridFrameClass = class extends BaseFrameClass {
462
870
  await deleteOAuthState(state);
463
871
  try {
464
872
  if (pending.provider === "openai") await this.completeOpenAILogin(code, pending);
873
+ else if (pending.provider === "grok") await this.completeGrokLogin(code, state, pending);
465
874
  else await this.completeAnthropicLogin(code, state, pending);
466
875
  return reply.redirect(`/?oauth=success&name=${encodeURIComponent(pending.name)}`);
467
876
  } catch {
@@ -480,7 +889,7 @@ var QgridFrameClass = class extends BaseFrameClass {
480
889
  else try {
481
890
  redirectUri = await startOpenAICallbackRelay(trustedLoopbackBase(), OAUTH_STATE_TTL_MS);
482
891
  } catch {
483
- throw new BadRequestException(`OpenAI login needs local port ${OPENAI_CALLBACK_PORTS.join(" or ")} — close any running \`codex login\` and retry`);
892
+ throw new BadRequestException(SD("error.detail")(`OpenAI login needs local port ${OPENAI_CALLBACK_PORTS.join(" or ")} — close any running \`codex login\` and retry`));
484
893
  }
485
894
  const authUrl = buildOpenAIAuthUrl(codeChallenge, state, redirectUri);
486
895
  await setOAuthState(state, {
@@ -494,6 +903,381 @@ var QgridFrameClass = class extends BaseFrameClass {
494
903
  mode
495
904
  };
496
905
  }
906
+ async oauthStartGrok(name) {
907
+ const state = crypto.randomBytes(32).toString("base64url");
908
+ let started;
909
+ try {
910
+ started = await startGrokOAuth({ state });
911
+ } catch (error) {
912
+ grokOAuthBadRequest(error);
913
+ }
914
+ await setOAuthState(state, {
915
+ codeVerifier: started.verifier,
916
+ name,
917
+ redirectUri: started.redirectUri,
918
+ provider: "grok"
919
+ });
920
+ await setGrokLatestState(state);
921
+ return {
922
+ authUrl: started.authorizeUrl,
923
+ mode: "code"
924
+ };
925
+ }
926
+ async oauthStartGrokDevice(name) {
927
+ let device;
928
+ try {
929
+ device = await startGrokDeviceCode();
930
+ } catch (error) {
931
+ grokOAuthBadRequest(error);
932
+ }
933
+ await setGrokDeviceState(device.deviceCode, {
934
+ name,
935
+ interval: device.interval,
936
+ expiresAtMs: Date.now() + device.expiresIn * 1e3
937
+ });
938
+ return device;
939
+ }
940
+ async oauthPollGrokDevice(deviceCode) {
941
+ const pending = await getGrokDeviceState(deviceCode);
942
+ if (!pending) throw new BadRequestException(SD("error.detail")("login session not found or expired — start the login again"));
943
+ let result;
944
+ try {
945
+ result = await pollGrokDeviceCode({
946
+ deviceCode,
947
+ interval: pending.interval
948
+ });
949
+ } catch (error) {
950
+ if (error instanceof GrokOAuthError && !error.options.retryable) await deleteGrokDeviceState(deviceCode);
951
+ grokOAuthBadRequest(error);
952
+ }
953
+ if (result.status === "pending") {
954
+ const slowDown = result.interval > pending.interval;
955
+ if (slowDown) await setGrokDeviceState(deviceCode, {
956
+ ...pending,
957
+ interval: result.interval
958
+ });
959
+ return {
960
+ status: slowDown ? "slow_down" : "pending",
961
+ intervalSec: result.interval
962
+ };
963
+ }
964
+ await deleteGrokDeviceState(deviceCode);
965
+ await this.saveGrokToken(result.credentials, pending.name);
966
+ return {
967
+ status: "added",
968
+ name: pending.name
969
+ };
970
+ }
971
+ async generateImages(params) {
972
+ const input = parseMediaInput(GenerateImagesInput, params);
973
+ const media = grokMedia();
974
+ const selection = await resolveGrokTokenSelection(input.tokenName);
975
+ const { id, route } = routeModelId(input.model, GROK_IMAGE_DEFAULT_MODEL);
976
+ const refs = input.referenceImages ?? [];
977
+ return runMediaEndpoint({
978
+ kind: "image",
979
+ model: route,
980
+ prompt: input.prompt,
981
+ projectName: input.projectName,
982
+ logger: input.logger
983
+ }, async (signal, requestLogId) => {
984
+ const request = {
985
+ model: id,
986
+ prompt: input.prompt,
987
+ n: input.n,
988
+ aspectRatio: input.aspectRatio,
989
+ resolution: input.resolution,
990
+ quality: input.quality,
991
+ outputFormat: input.outputFormat,
992
+ signal,
993
+ ...selection
994
+ };
995
+ const dispatched = refs.length ? await media.editImages({
996
+ ...request,
997
+ images: refs
998
+ }) : await media.generateImages(request);
999
+ const decoded = decodeGrokImages(dispatched.result);
1000
+ const cost = grokImageCost(id, decoded.images.length, decoded.costInUsdTicks);
1001
+ const output = {
1002
+ model: route,
1003
+ tokenName: dispatched.tokenName,
1004
+ images: decoded.images.map((image) => {
1005
+ const generated = {
1006
+ b64: Buffer.from(image.bytes).toString("base64"),
1007
+ mimeType: image.mediaType
1008
+ };
1009
+ if (image.revisedPrompt) generated.revisedPrompt = image.revisedPrompt;
1010
+ return generated;
1011
+ }),
1012
+ usage: { imageCount: decoded.images.length }
1013
+ };
1014
+ if (decoded.costInUsdTicks !== void 0) output.usage.costInUsdTicks = decoded.costInUsdTicks;
1015
+ if (cost) {
1016
+ output.costUsd = cost.costUsd;
1017
+ output.costSource = cost.costSource;
1018
+ }
1019
+ if (requestLogId !== void 0) output.requestLogId = requestLogId;
1020
+ return {
1021
+ output,
1022
+ log: {
1023
+ tokenName: output.tokenName,
1024
+ cost,
1025
+ response: output.images.map((image) => imageTagForLog(image.b64, image.mimeType, image.revisedPrompt)).join("\n"),
1026
+ steps: output.images.map((image, index) => {
1027
+ const args = {
1028
+ kind: "image",
1029
+ prompt: input.prompt,
1030
+ model: route,
1031
+ requestedOptions: {
1032
+ n: input.n,
1033
+ aspectRatio: input.aspectRatio,
1034
+ resolution: input.resolution,
1035
+ quality: input.quality,
1036
+ outputFormat: input.outputFormat
1037
+ },
1038
+ imageCount: output.usage.imageCount
1039
+ };
1040
+ if (cost) {
1041
+ args.costSource = cost.costSource;
1042
+ args.costInUsdTicks = cost.ticks;
1043
+ }
1044
+ if (index === 0 && refs.length) args.inputImages = describeImageRefs(refs, true);
1045
+ return {
1046
+ toolCallId: `image_generation:0:${index}`,
1047
+ args,
1048
+ result: imageTagForLog(image.b64, image.mimeType, image.revisedPrompt)
1049
+ };
1050
+ })
1051
+ }
1052
+ };
1053
+ });
1054
+ }
1055
+ async videoStart(params) {
1056
+ const input = parseMediaInput(VideoStartInput, params);
1057
+ const media = grokMedia();
1058
+ const selection = await resolveGrokTokenSelection(input.tokenName);
1059
+ const { id, route } = routeModelId(input.model, GROK_VIDEO_DEFAULT_MODEL);
1060
+ const requestLogId = await startMediaRun(input.logger, {
1061
+ kind: "video",
1062
+ model: route,
1063
+ prompt: input.prompt,
1064
+ projectName: input.projectName
1065
+ });
1066
+ const startedAt = Date.now();
1067
+ const started = await dispatchMediaCall(requestLogId, (signal) => media.startVideo({
1068
+ model: id,
1069
+ prompt: input.prompt,
1070
+ duration: input.duration,
1071
+ aspectRatio: input.aspectRatio,
1072
+ resolution: input.resolution,
1073
+ image: input.image,
1074
+ lastFrame: input.lastFrame,
1075
+ referenceImages: input.referenceImages,
1076
+ mode: input.mode,
1077
+ signal,
1078
+ ...selection
1079
+ }));
1080
+ const now = Date.now();
1081
+ pruneVideoJobs(now);
1082
+ const jobHandle = crypto.randomBytes(16).toString("base64url");
1083
+ const job = {
1084
+ tokenId: started.tokenId,
1085
+ tokenName: started.tokenName,
1086
+ requestId: started.result.request_id,
1087
+ owner: input.projectName ?? null,
1088
+ model: route,
1089
+ createdAt: now
1090
+ };
1091
+ if (requestLogId !== void 0) job.requestLogId = requestLogId;
1092
+ videoJobs.set(jobHandle, job);
1093
+ if (requestLogId !== void 0) {
1094
+ const refs = [
1095
+ ...input.image ? [input.image] : [],
1096
+ ...input.lastFrame ? [input.lastFrame] : [],
1097
+ ...input.referenceImages ?? []
1098
+ ];
1099
+ const args = {
1100
+ kind: "video",
1101
+ prompt: input.prompt,
1102
+ model: route,
1103
+ requestedOptions: {
1104
+ duration: input.duration,
1105
+ aspectRatio: input.aspectRatio,
1106
+ resolution: input.resolution,
1107
+ mode: input.mode
1108
+ }
1109
+ };
1110
+ if (refs.length) args.inputImages = describeImageRefs(refs, false);
1111
+ const [step] = mediaToolSteps("video", [{
1112
+ toolCallId: videoToolCallId(job),
1113
+ args
1114
+ }], now - startedAt);
1115
+ try {
1116
+ await RequestLogModel.appendStep(requestLogId, step);
1117
+ } catch (e) {
1118
+ mediaLogger.error(`video request log failed: ${e instanceof Error ? e.message : String(e)}`);
1119
+ }
1120
+ }
1121
+ const output = {
1122
+ jobHandle,
1123
+ model: route
1124
+ };
1125
+ if (requestLogId !== void 0) output.requestLogId = requestLogId;
1126
+ return output;
1127
+ }
1128
+ async videoStatus(params) {
1129
+ const input = parseMediaInput(VideoStatusInput, params);
1130
+ pruneVideoJobs(Date.now());
1131
+ const job = videoJobs.get(input.jobHandle);
1132
+ if (!job || job.owner !== (input.projectName ?? null)) throw new NotFoundException(SD("qgrid.videoJobNotFound"));
1133
+ if (job.final) return job.final;
1134
+ const media = grokMedia();
1135
+ const disconnect = createHttpDisconnectHandle();
1136
+ let summary;
1137
+ let durationSec;
1138
+ try {
1139
+ const polled = await media.getVideo(job.tokenId, job.requestId, disconnect.signal);
1140
+ summary = summarizeGrokVideoStatus(polled.result);
1141
+ durationSec = polled.result.video?.duration ?? void 0;
1142
+ } catch (e) {
1143
+ if (!(e instanceof GrokContentPolicyError)) throwGrokCallerError(e);
1144
+ summary = {
1145
+ status: "failed",
1146
+ mimeType: "video/mp4",
1147
+ error: e.message
1148
+ };
1149
+ } finally {
1150
+ disconnect.dispose();
1151
+ }
1152
+ if (job.final) return job.final;
1153
+ const status = {
1154
+ status: summary.status,
1155
+ mimeType: "video/mp4"
1156
+ };
1157
+ if (job.requestLogId !== void 0) status.requestLogId = job.requestLogId;
1158
+ if (summary.status === "pending") return status;
1159
+ const cost = grokReportedCost(summary.usageTicks);
1160
+ const final = status;
1161
+ if (summary.url) final.url = summary.url;
1162
+ if (durationSec !== void 0) final.durationSec = durationSec;
1163
+ if (cost) {
1164
+ final.costInUsdTicks = cost.ticks;
1165
+ final.costUsd = cost.costUsd;
1166
+ }
1167
+ if (summary.error) final.error = summary.error;
1168
+ job.final = final;
1169
+ await finishVideoRun(job, final, cost);
1170
+ return final;
1171
+ }
1172
+ async transcribe(params) {
1173
+ const input = parseMediaInput(TranscribeInput, params);
1174
+ const voice = grokVoice();
1175
+ const selection = await resolveGrokTokenSelection(input.tokenName);
1176
+ const { id, route } = routeModelId(input.model, GROK_STT_DEFAULT_MODEL);
1177
+ const audio = new Uint8Array(Buffer.from(input.audio, "base64"));
1178
+ return runMediaEndpoint({
1179
+ kind: "stt",
1180
+ model: route,
1181
+ prompt: `[audio ${input.mediaType} ${audio.byteLength} bytes]`,
1182
+ projectName: input.projectName,
1183
+ logger: input.logger
1184
+ }, async (signal, requestLogId) => {
1185
+ const dispatched = await voice.transcribe({
1186
+ audio,
1187
+ mediaType: input.mediaType,
1188
+ model: id,
1189
+ language: input.language,
1190
+ signal,
1191
+ ...selection
1192
+ });
1193
+ const { text, language, duration } = dispatched.result;
1194
+ const output = {
1195
+ text,
1196
+ model: route,
1197
+ tokenName: dispatched.tokenName
1198
+ };
1199
+ if (language) output.language = language;
1200
+ if (duration !== void 0) output.durationSec = duration;
1201
+ if (requestLogId !== void 0) output.requestLogId = requestLogId;
1202
+ return {
1203
+ output,
1204
+ log: {
1205
+ tokenName: output.tokenName,
1206
+ response: output.text,
1207
+ steps: [{
1208
+ toolCallId: "transcription:0",
1209
+ args: {
1210
+ kind: "stt",
1211
+ model: route,
1212
+ mediaType: input.mediaType,
1213
+ audioBytes: audio.byteLength,
1214
+ language: input.language,
1215
+ durationSec: output.durationSec
1216
+ },
1217
+ result: JSON.stringify({
1218
+ text: output.text,
1219
+ language: output.language,
1220
+ durationSec: output.durationSec
1221
+ })
1222
+ }]
1223
+ }
1224
+ };
1225
+ });
1226
+ }
1227
+ async speak(params) {
1228
+ const input = parseMediaInput(SpeakInput, params);
1229
+ const voice = grokVoice();
1230
+ const selection = await resolveGrokTokenSelection(input.tokenName);
1231
+ const route = input.model ?? GROK_TTS_LOG_MODEL;
1232
+ const request = {
1233
+ text: input.text,
1234
+ voice: input.voice ?? "ara",
1235
+ language: input.language ?? "en",
1236
+ format: input.format ?? "mp3"
1237
+ };
1238
+ return runMediaEndpoint({
1239
+ kind: "tts",
1240
+ model: route,
1241
+ prompt: input.text,
1242
+ projectName: input.projectName,
1243
+ logger: input.logger
1244
+ }, async (signal, requestLogId) => {
1245
+ const dispatched = await voice.speak({
1246
+ ...request,
1247
+ signal,
1248
+ ...selection
1249
+ });
1250
+ const audioBytes = dispatched.result.audio.byteLength;
1251
+ const output = {
1252
+ audio: Buffer.from(dispatched.result.audio).toString("base64"),
1253
+ mimeType: dispatched.result.mediaType,
1254
+ tokenName: dispatched.tokenName
1255
+ };
1256
+ if (requestLogId !== void 0) output.requestLogId = requestLogId;
1257
+ return {
1258
+ output,
1259
+ log: {
1260
+ tokenName: output.tokenName,
1261
+ response: `[audio ${output.mimeType} ${audioBytes} bytes]`,
1262
+ steps: [{
1263
+ toolCallId: "speech:0",
1264
+ args: {
1265
+ kind: "tts",
1266
+ model: route,
1267
+ voice: request.voice,
1268
+ language: request.language,
1269
+ format: request.format,
1270
+ characters: input.text.length
1271
+ },
1272
+ result: JSON.stringify({
1273
+ mimeType: output.mimeType,
1274
+ audioBytes
1275
+ })
1276
+ }]
1277
+ }
1278
+ };
1279
+ });
1280
+ }
497
1281
  async usage(tokenId) {
498
1282
  const { rows: allTokens } = await TokenModel.findMany("A");
499
1283
  const entry = tokenId ? allTokens.find((e) => e.id === tokenId) : allTokens.findLast((e) => e.active && e.provider === "anthropic");
@@ -521,15 +1305,33 @@ var QgridFrameClass = class extends BaseFrameClass {
521
1305
  } : null
522
1306
  };
523
1307
  } catch (e) {
524
- return { error: `OpenAI usage failed: ${e.message}` };
1308
+ return { error: `OpenAI usage failed: ${e instanceof Error ? e.message : String(e)}` };
525
1309
  }
526
1310
  }
1311
+ if (entry.provider === "grok") {
1312
+ const snapshot = entry.active ? grokTokenSnapshot(entry.id) : void 0;
1313
+ const billing = snapshot?.lastBilling;
1314
+ const storedTier = GrokCredentials.safeParse(entry.credentials).data?.subscriptionTier;
1315
+ return {
1316
+ provider: "grok",
1317
+ fiveHour: null,
1318
+ sevenDay: billing ? {
1319
+ utilization: billing.utilizationPct,
1320
+ resetsAt: billing.periodEnd
1321
+ } : null,
1322
+ periodType: billing?.periodType ?? null,
1323
+ tier: snapshot?.lastTier ?? storedTier ?? null,
1324
+ onDemandExcluded: snapshot?.onDemandExcluded ?? false,
1325
+ zdrVideoExcluded: snapshot?.zdrVideoExcluded ?? false,
1326
+ keepaliveApplicable: false
1327
+ };
1328
+ }
527
1329
  if (entry.provider !== "anthropic") return { error: `usage API not supported for provider: ${entry.provider}` };
528
1330
  let accessToken = getAccessToken(entry.credentials);
529
1331
  if (getExpiresAt(entry.credentials) < Date.now() && getRefreshToken(entry.credentials)) try {
530
1332
  accessToken = await this.refreshToken(entry);
531
1333
  } catch (e) {
532
- oauthLogger.warn(`refresh failed for ${entry.name}: ${e.message}`);
1334
+ oauthLogger.warn(`refresh failed for ${entry.name}: ${e instanceof Error ? e.message : String(e)}`);
533
1335
  return { error: "Token refresh failed; usage is unavailable" };
534
1336
  }
535
1337
  const raw = await fetchUsage(accessToken);
@@ -539,13 +1341,14 @@ var QgridFrameClass = class extends BaseFrameClass {
539
1341
  if (retried.error) return { error: retried.error };
540
1342
  return convertAnthropicUsage(retried);
541
1343
  } catch (e) {
542
- oauthLogger.warn(`refresh failed for ${entry.name}: ${e.message}`);
1344
+ oauthLogger.warn(`refresh failed for ${entry.name}: ${e instanceof Error ? e.message : String(e)}`);
543
1345
  return { error: "Token refresh failed; usage is unavailable" };
544
1346
  }
545
1347
  if (raw.error) return { error: raw.error };
546
1348
  return convertAnthropicUsage(raw);
547
1349
  }
548
1350
  async refreshToken(token) {
1351
+ if (token.provider === "grok") return this.refreshGrokToken(token);
549
1352
  const inflight = inflightAnthropicRefresh.get(token.id);
550
1353
  if (inflight) return inflight;
551
1354
  const promise = this.doRefreshToken(token);
@@ -556,6 +1359,12 @@ var QgridFrameClass = class extends BaseFrameClass {
556
1359
  inflightAnthropicRefresh.delete(token.id);
557
1360
  }
558
1361
  }
1362
+ grokRefresher = null;
1363
+ async refreshGrokToken(token) {
1364
+ if (!this.grokRefresher) throw new Error("Grok refresher not initialized");
1365
+ const current = GrokCredentials$1.parse(token.credentials);
1366
+ return (await this.grokRefresher.refresh(token.id, current, (creds) => persistGrokCredentials(token.id, creds))).accessToken;
1367
+ }
559
1368
  async doRefreshToken(token) {
560
1369
  const creds = token.credentials;
561
1370
  const rt = getRefreshToken(creds);
@@ -756,6 +1565,78 @@ __decorate([
756
1565
  __decorateMetadata("design:paramtypes", [String]),
757
1566
  __decorateMetadata("design:returntype", Promise)
758
1567
  ], QgridFrameClass.prototype, "oauthStartOpenAI", null);
1568
+ __decorate([
1569
+ api({
1570
+ httpMethod: "POST",
1571
+ clients: ["axios", "tanstack-mutation"]
1572
+ }),
1573
+ __decorateMetadata("design:type", Function),
1574
+ __decorateMetadata("design:paramtypes", [String]),
1575
+ __decorateMetadata("design:returntype", Promise)
1576
+ ], QgridFrameClass.prototype, "oauthStartGrok", null);
1577
+ __decorate([
1578
+ api({
1579
+ httpMethod: "POST",
1580
+ clients: ["axios", "tanstack-mutation"]
1581
+ }),
1582
+ __decorateMetadata("design:type", Function),
1583
+ __decorateMetadata("design:paramtypes", [String]),
1584
+ __decorateMetadata("design:returntype", Promise)
1585
+ ], QgridFrameClass.prototype, "oauthStartGrokDevice", null);
1586
+ __decorate([
1587
+ api({
1588
+ httpMethod: "POST",
1589
+ clients: ["axios", "tanstack-mutation"]
1590
+ }),
1591
+ __decorateMetadata("design:type", Function),
1592
+ __decorateMetadata("design:paramtypes", [String]),
1593
+ __decorateMetadata("design:returntype", Promise)
1594
+ ], QgridFrameClass.prototype, "oauthPollGrokDevice", null);
1595
+ __decorate([
1596
+ api({
1597
+ httpMethod: "POST",
1598
+ clients: ["axios", "tanstack-mutation"]
1599
+ }),
1600
+ __decorateMetadata("design:type", Function),
1601
+ __decorateMetadata("design:paramtypes", [typeof GenerateImagesInput === "undefined" ? Object : GenerateImagesInput]),
1602
+ __decorateMetadata("design:returntype", Promise)
1603
+ ], QgridFrameClass.prototype, "generateImages", null);
1604
+ __decorate([
1605
+ api({
1606
+ httpMethod: "POST",
1607
+ clients: ["axios", "tanstack-mutation"]
1608
+ }),
1609
+ __decorateMetadata("design:type", Function),
1610
+ __decorateMetadata("design:paramtypes", [typeof VideoStartInput === "undefined" ? Object : VideoStartInput]),
1611
+ __decorateMetadata("design:returntype", Promise)
1612
+ ], QgridFrameClass.prototype, "videoStart", null);
1613
+ __decorate([
1614
+ api({
1615
+ httpMethod: "POST",
1616
+ clients: ["axios", "tanstack-mutation"]
1617
+ }),
1618
+ __decorateMetadata("design:type", Function),
1619
+ __decorateMetadata("design:paramtypes", [typeof VideoStatusInput === "undefined" ? Object : VideoStatusInput]),
1620
+ __decorateMetadata("design:returntype", Promise)
1621
+ ], QgridFrameClass.prototype, "videoStatus", null);
1622
+ __decorate([
1623
+ api({
1624
+ httpMethod: "POST",
1625
+ clients: ["axios", "tanstack-mutation"]
1626
+ }),
1627
+ __decorateMetadata("design:type", Function),
1628
+ __decorateMetadata("design:paramtypes", [typeof TranscribeInput === "undefined" ? Object : TranscribeInput]),
1629
+ __decorateMetadata("design:returntype", Promise)
1630
+ ], QgridFrameClass.prototype, "transcribe", null);
1631
+ __decorate([
1632
+ api({
1633
+ httpMethod: "POST",
1634
+ clients: ["axios", "tanstack-mutation"]
1635
+ }),
1636
+ __decorateMetadata("design:type", Function),
1637
+ __decorateMetadata("design:paramtypes", [typeof SpeakInput === "undefined" ? Object : SpeakInput]),
1638
+ __decorateMetadata("design:returntype", Promise)
1639
+ ], QgridFrameClass.prototype, "speak", null);
759
1640
  __decorate([
760
1641
  api({
761
1642
  httpMethod: "GET",
@@ -789,6 +1670,6 @@ function convertAnthropicUsage(raw) {
789
1670
  };
790
1671
  }
791
1672
  //#endregion
792
- export { QgridFrame };
1673
+ export { QgridFrame, mapRequestBodyTooLarge, persistGrokCredentials };
793
1674
 
794
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicWdyaWQuZnJhbWUuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2FwcGxpY2F0aW9uL3FncmlkL3FncmlkLmZyYW1lLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBjcnlwdG8gZnJvbSBcIm5vZGU6Y3J5cHRvXCI7XG5cbmltcG9ydCB7IGdldExvZ2dlciB9IGZyb20gXCJAbG9ndGFwZS9sb2d0YXBlXCI7XG5pbXBvcnQgeyB0eXBlIEZhc3RpZnlSZXBseSwgdHlwZSBGYXN0aWZ5UmVxdWVzdCB9IGZyb20gXCJmYXN0aWZ5XCI7XG5pbXBvcnQgeyBhcGksIEJhZFJlcXVlc3RFeGNlcHRpb24sIEJhc2VGcmFtZUNsYXNzLCBTb25hbXUsIHN0cmVhbSB9IGZyb20gXCJzb25hbXVcIjtcbmltcG9ydCB7IGdldENhY2hlTWFuYWdlclJlZiB9IGZyb20gXCJzb25hbXUvY2FjaGVcIjtcblxuaW1wb3J0IHsgdHlwZSBMb2NhbGl6ZWRTdHJpbmcgfSBmcm9tIFwiLi4vLi4vaTE4bi9zZC5nZW5lcmF0ZWRcIjtcbmltcG9ydCB7XG4gIGdldEFjY2Vzc1Rva2VuLFxuICBnZXRFeHBpcmVzQXQsXG4gIGdldFJlZnJlc2hUb2tlbixcbn0gZnJvbSBcIi4uLy4uL3V0aWxzL3Byb3ZpZGVycy9jb21tb24vY3JlZGVudGlhbHNcIjtcbmltcG9ydCB7IENhbGxlclNjaGVtYVZhbGlkYXRpb25FcnJvciB9IGZyb20gXCIuLi8uLi91dGlscy9wcm92aWRlcnMvY29tbW9uL3NjaGVtYS12YWxpZGF0aW9uXCI7XG5pbXBvcnQge1xuICBPUEVOQUlfQ0FMTEJBQ0tfUE9SVFMsXG4gIG9wZW5BSUNhbGxiYWNrUmVkaXJlY3RVcmksXG4gIHN0YXJ0T3BlbkFJQ2FsbGJhY2tSZWxheSxcbn0gZnJvbSBcIi4uLy4uL3V0aWxzL3Byb3ZpZGVycy9vcGVuYWkvb3BlbmFpLWNhbGxiYWNrLXJlbGF5XCI7XG5pbXBvcnQge1xuICBidWlsZE9wZW5BSUF1dGhVcmwsXG4gIGV4Y2hhbmdlT3BlbkFJQ29kZSxcbiAgZ2VuZXJhdGVPcGVuQUlQS0NFLFxufSBmcm9tIFwiLi4vLi4vdXRpbHMvcHJvdmlkZXJzL29wZW5haS9vcGVuYWktb2F1dGhcIjtcbmltcG9ydCB7IE1JQ1JPX1VTRCwgUmVxdWVzdExvZ01vZGVsIH0gZnJvbSBcIi4uL3JlcXVlc3QtbG9nL3JlcXVlc3QtbG9nLm1vZGVsXCI7XG5pbXBvcnQgeyB0eXBlIFJlcXVlc3RMb2dMaXN0UGFyYW1zIH0gZnJvbSBcIi4uL3JlcXVlc3QtbG9nL3JlcXVlc3QtbG9nLnR5cGVzXCI7XG5pbXBvcnQgeyB0eXBlIFRva2VuU3Vic2V0QSB9IGZyb20gXCIuLi9zb25hbXUuZ2VuZXJhdGVkXCI7XG5pbXBvcnQgeyBUb2tlbk1vZGVsLCB0eXBlIFRva2VuVXBkYXRlRmllbGRzIH0gZnJvbSBcIi4uL3Rva2VuL3Rva2VuLm1vZGVsXCI7XG5pbXBvcnQgeyBUb2tlbkNyZWRlbnRpYWxzIH0gZnJvbSBcIi4uL3Rva2VuL3Rva2VuLnR5cGVzXCI7XG5pbXBvcnQge1xuICBDT05TT0xFX0NBTExCQUNLX1VSTCxcbiAgdHlwZSBBbnRocm9waWNVc2FnZVJhdyxcbiAgYnVpbGRBdXRoVXJsLFxuICBleGNoYW5nZUNvZGVGb3JUb2tlbnMsXG4gIGZldGNoVXNhZ2UsXG4gIGdlbmVyYXRlUEtDRSxcbiAgcmVmcmVzaEFjY2Vzc1Rva2VuLFxuICBSZWZyZXNoRmFpbGVkRXJyb3IsXG59IGZyb20gXCIuL29hdXRoXCI7XG5pbXBvcnQgeyBDT0RFWF9JTUFHRV9HRU5FUkFUSU9OX01PREVMIH0gZnJvbSBcIi4vcWdyaWQtaW1hZ2UtZ2VuZXJhdGlvblwiO1xuaW1wb3J0IHtcbiAgYWZ0ZXJRdWVyeSxcbiAgYmVmb3JlUXVlcnksXG4gIGZpbmlzaFJ1bkFib3J0ZWQsXG4gIGZpbmlzaFJ1bldpdGhFcnJvcixcbn0gZnJvbSBcIi4vcWdyaWQtcnVuLWxpZmVjeWNsZVwiO1xuaW1wb3J0IHtcbiAgYnVpbGRBbmRWYWxpZGF0ZVN0cmljdE91dHB1dFNjaGVtYSxcbiAgY29tcGxldGVkRHJpdmVyRnJvbUltYWdlRmFpbHVyZSxcbiAgdHlwZSBJbnRlcm5hbFF1ZXJ5SW5wdXQsXG4gIFFncmlkRGlzcGF0Y2hlcixcbn0gZnJvbSBcIi4vcWdyaWQuZGlzcGF0Y2hlclwiO1xuaW1wb3J0IHtcbiAgdHlwZSBRdWVyeUlucHV0LFxuICB0eXBlIEFwcGVuZFN0ZXBJbnB1dCxcbiAgdHlwZSBDcmVhdGVSdW5JbnB1dCxcbiAgdHlwZSBGaW5pc2hSdW5JbnB1dCxcbiAgdHlwZSBIZWFsdGhSZXNwb25zZSxcbiAgdHlwZSBPQXV0aFN0YXJ0UmVzdWx0LFxuICB0eXBlIFF1ZXJ5T3V0cHV0LFxuICB0eXBlIFFncmlkUnVuQ29udGV4dCxcbiAgU3RyZWFtRXZlbnRzLFxuICB0eXBlIFRva2VuU3RhdHMsXG4gIHR5cGUgVXNhZ2VSZXNwb25zZSxcbn0gZnJvbSBcIi4vcWdyaWQudHlwZXNcIjtcbmltcG9ydCB7IGRlYWN0aXZhdGVBdXRoRGVhZFRva2VuLCBub3RpZnlUb2tlbkFkZGVkIH0gZnJvbSBcIi4vdG9rZW4tZGVhdGhcIjtcbmltcG9ydCB7IFRvb2xTY2hlbWFDb21wb3NpdGlvbkVycm9yIH0gZnJvbSBcIi4vdG9vbC1lbXVsYXRpb24tc2NoZW1hXCI7XG5cbmNvbnN0IHBlbmRpbmdTdHJlYW1zID0gbmV3IE1hcDxzdHJpbmcsIFF1ZXJ5SW5wdXQ+KCk7XG5cbnR5cGUgUGVuZGluZ09BdXRoID0ge1xuICBjb2RlVmVyaWZpZXI6IHN0cmluZztcbiAgbmFtZTogc3RyaW5nO1xuICByZWRpcmVjdFVyaTogc3RyaW5nO1xuICBwcm92aWRlcjogXCJhbnRocm9waWNcIiB8IFwib3BlbmFpXCI7XG59O1xuY29uc3QgT0FVVEhfU1RBVEVfUFJFRklYID0gXCJvYXV0aDpzdGF0ZTpcIjtcbmNvbnN0IE9BVVRIX1NUQVRFX1RUTCA9IFwiNW1cIjtcbmNvbnN0IE9BVVRIX1NUQVRFX1RUTF9NUyA9IDUgKiA2MF8wMDA7XG5cbmZ1bmN0aW9uIHVuaXhTZWNvbmRzVG9Jc28oc2Vjb25kczogbnVtYmVyIHwgbnVsbCB8IHVuZGVmaW5lZCk6IHN0cmluZyB8IG51bGwge1xuICByZXR1cm4gdHlwZW9mIHNlY29uZHMgPT09IFwibnVtYmVyXCIgPyBuZXcgRGF0ZShzZWNvbmRzICogMTAwMCkudG9JU09TdHJpbmcoKSA6IG51bGw7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNldE9BdXRoU3RhdGUoc3RhdGU6IHN0cmluZywgZGF0YTogUGVuZGluZ09BdXRoKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IGNhY2hlID0gZ2V0Q2FjaGVNYW5hZ2VyUmVmKCk7XG4gIGlmICghY2FjaGUpIHRocm93IG5ldyBFcnJvcihcIkNhY2hlTWFuYWdlciBub3QgaW5pdGlhbGl6ZWRcIik7XG4gIGF3YWl0IGNhY2hlLnNldCh7XG4gICAga2V5OiBgJHtPQVVUSF9TVEFURV9QUkVGSVh9JHtzdGF0ZX1gLFxuICAgIHZhbHVlOiBKU09OLnN0cmluZ2lmeShkYXRhKSxcbiAgICB0dGw6IE9BVVRIX1NUQVRFX1RUTCxcbiAgfSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldE9BdXRoU3RhdGUoc3RhdGU6IHN0cmluZyk6IFByb21pc2U8UGVuZGluZ09BdXRoIHwgdW5kZWZpbmVkPiB7XG4gIGNvbnN0IGNhY2hlID0gZ2V0Q2FjaGVNYW5hZ2VyUmVmKCk7XG4gIGlmICghY2FjaGUpIHRocm93IG5ldyBFcnJvcihcIkNhY2hlTWFuYWdlciBub3QgaW5pdGlhbGl6ZWRcIik7XG4gIGNvbnN0IHJhdyA9IGF3YWl0IGNhY2hlLmdldDxzdHJpbmc+KHsga2V5OiBgJHtPQVVUSF9TVEFURV9QUkVGSVh9JHtzdGF0ZX1gIH0pO1xuICBpZiAoIXJhdykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgcmV0dXJuIEpTT04ucGFyc2UocmF3KSBhcyBQZW5kaW5nT0F1dGg7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGRlbGV0ZU9BdXRoU3RhdGUoc3RhdGU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBjYWNoZSA9IGdldENhY2hlTWFuYWdlclJlZigpO1xuICBpZiAoIWNhY2hlKSByZXR1cm47XG4gIGF3YWl0IGNhY2hlLmRlbGV0ZSh7IGtleTogYCR7T0FVVEhfU1RBVEVfUFJFRklYfSR7c3RhdGV9YCB9KTtcbn1cblxuY29uc3QgdHJ1c3RlZExvb3BiYWNrQmFzZSA9ICgpID0+IGBodHRwOi8vbG9jYWxob3N0OiR7cHJvY2Vzcy5lbnYuUE9SVCA/PyBcIjQ0OTAwXCJ9YDtcblxuZnVuY3Rpb24gaXNSZW1vdGVPQXV0aFJlcXVlc3QoKTogYm9vbGVhbiB7XG4gIHRyeSB7XG4gICAgY29uc3QgeyBoZWFkZXJzIH0gPSBTb25hbXUuZ2V0Q29udGV4dCgpO1xuICAgIGNvbnN0IG9yaWdpbiA9IHR5cGVvZiBoZWFkZXJzLm9yaWdpbiA9PT0gXCJzdHJpbmdcIiA/IGhlYWRlcnMub3JpZ2luIDogdW5kZWZpbmVkO1xuICAgIGNvbnN0IGZvcndhcmRlZCA9IGhlYWRlcnNbXCJ4LWZvcndhcmRlZC1ob3N0XCJdO1xuICAgIGNvbnN0IHJhd0hvc3QgPSBBcnJheS5pc0FycmF5KGZvcndhcmRlZCkgPyBmb3J3YXJkZWRbMF0gOiAoZm9yd2FyZGVkID8/IGhlYWRlcnMuaG9zdCk7XG4gICAgY29uc3QgaG9zdCA9IG9yaWdpblxuICAgICAgPyBuZXcgVVJMKG9yaWdpbikuaG9zdG5hbWVcbiAgICAgIDogbmV3IFVSTChgaHR0cDovLyR7cmF3SG9zdCA/PyBcImxvY2FsaG9zdFwifWApLmhvc3RuYW1lO1xuICAgIHJldHVybiAhbmV3IFNldChbXCJsb2NhbGhvc3RcIiwgXCIxMjcuMC4wLjFcIiwgXCI6OjFcIiwgXCJbOjoxXVwiXSkuaGFzKGhvc3QpO1xuICB9IGNhdGNoIHt9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuLy8gQW50aHJvcGljJ3MgcmVtb3RlL21hbnVhbCBmbG93IHVzZXMgaXRzIGZpeGVkIGNvbnNvbGUgY2FsbGJhY2suIEhlYWRlcnMgbWF5IHNlbGVjdCBiZXR3ZWVuIHR3b1xuLy8gYWxsb3dsaXN0ZWQgVVJJcywgYnV0IG5ldmVyIGNvbnRyaWJ1dGUgYXV0aG9yaXR5IG9yIHBhdGggYnl0ZXMgdG8gZWl0aGVyIFVSSS5cbmZ1bmN0aW9uIHJlc29sdmVPQXV0aFJlZGlyZWN0KCk6IHsgcmVkaXJlY3RVcmk6IHN0cmluZzsgbW9kZTogXCJyZWRpcmVjdFwiIHwgXCJjb2RlXCIgfSB7XG4gIGlmIChpc1JlbW90ZU9BdXRoUmVxdWVzdCgpKSB7XG4gICAgcmV0dXJuIHsgcmVkaXJlY3RVcmk6IENPTlNPTEVfQ0FMTEJBQ0tfVVJMLCBtb2RlOiBcImNvZGVcIiB9O1xuICB9XG4gIHJldHVybiB7IHJlZGlyZWN0VXJpOiBgJHt0cnVzdGVkTG9vcGJhY2tCYXNlKCl9L2NhbGxiYWNrYCwgbW9kZTogXCJyZWRpcmVjdFwiIH07XG59XG5cbmZ1bmN0aW9uIHBhcnNlUGFzdGVkT0F1dGhSZXN1bHQoaW5wdXQ6IHN0cmluZyk6IHsgY29kZTogc3RyaW5nOyBzdGF0ZTogc3RyaW5nIH0gfCBudWxsIHtcbiAgY29uc3QgdHJpbW1lZCA9IGlucHV0LnRyaW0oKTtcbiAgdHJ5IHtcbiAgICBjb25zdCBjYWxsYmFjayA9IG5ldyBVUkwodHJpbW1lZCk7XG4gICAgY29uc3QgY29kZSA9IGNhbGxiYWNrLnNlYXJjaFBhcmFtcy5nZXQoXCJjb2RlXCIpPy50cmltKCkgPz8gXCJcIjtcbiAgICBjb25zdCBzdGF0ZSA9IGNhbGxiYWNrLnNlYXJjaFBhcmFtcy5nZXQoXCJzdGF0ZVwiKT8udHJpbSgpID8/IFwiXCI7XG4gICAgaWYgKGNvZGUgJiYgc3RhdGUpIHJldHVybiB7IGNvZGUsIHN0YXRlIH07XG4gIH0gY2F0Y2gge31cblxuICBjb25zdCBzZXBhcmF0b3JBdCA9IHRyaW1tZWQuaW5kZXhPZihcIiNcIik7XG4gIGNvbnN0IGNvZGUgPSBzZXBhcmF0b3JBdCA+IDAgPyB0cmltbWVkLnNsaWNlKDAsIHNlcGFyYXRvckF0KS50cmltKCkgOiBcIlwiO1xuICBjb25zdCBzdGF0ZSA9IHNlcGFyYXRvckF0ID4gMCA/IHRyaW1tZWQuc2xpY2Uoc2VwYXJhdG9yQXQgKyAxKS50cmltKCkgOiBcIlwiO1xuICByZXR1cm4gY29kZSAmJiBzdGF0ZSA/IHsgY29kZSwgc3RhdGUgfSA6IG51bGw7XG59XG5cbmZ1bmN0aW9uIHJlamVjdEltYWdlR2VuZXJhdGlvblN0cmVhbShhcmdzOiBRdWVyeUlucHV0KTogdm9pZCB7XG4gIGlmICghYXJncy5pbWFnZUdlbmVyYXRpb24gJiYgYXJncy5tb2RlbCAhPT0gYG9wZW5haS8ke0NPREVYX0lNQUdFX0dFTkVSQVRJT05fTU9ERUx9YCkgcmV0dXJuO1xuICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihcbiAgICBcInFncmlkOiBpbWFnZUdlbmVyYXRpb24gaXMgbm90IHN1cHBvcnRlZCB3aXRoIHN0cmVhbWluZzsgdXNlIHF1ZXJ5IG9yIGdlbmVyYXRlSW1hZ2Ugd2l0aCBxZ3JpZC5pbWFnZSgpIGluc3RlYWQuXCIgYXMgTG9jYWxpemVkU3RyaW5nLFxuICApO1xufVxuXG5mdW5jdGlvbiByZWplY3RJbnZhbGlkSW1hZ2VRdWVyeShhcmdzOiBRdWVyeUlucHV0KTogdm9pZCB7XG4gIGNvbnN0IHN0YW5kYWxvbmUgPSBhcmdzLm1vZGVsID09PSBgb3BlbmFpLyR7Q09ERVhfSU1BR0VfR0VORVJBVElPTl9NT0RFTH1gO1xuICBpZiAoIXN0YW5kYWxvbmUgJiYgYXJncy5pbWFnZUdlbmVyYXRpb24gIT09IFwiYXV0b1wiKSByZXR1cm47XG4gIGlmIChzdGFuZGFsb25lICYmIGFyZ3MuaW1hZ2VHZW5lcmF0aW9uICE9PSB0cnVlKSB7XG4gICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oXG4gICAgICBcInFncmlkOiB0aGUgaW1hZ2UgbW9kZWwgcmVxdWlyZXMgaW1hZ2VHZW5lcmF0aW9uOiB0cnVlOyB1c2UgcWdyaWQuaW1hZ2UoKSB3aXRoIGdlbmVyYXRlSW1hZ2UuXCIgYXMgTG9jYWxpemVkU3RyaW5nLFxuICAgICk7XG4gIH1cbiAgaWYgKGFyZ3MudG9vbHM/Lmxlbmd0aCB8fCBhcmdzLmpzb25TY2hlbWEgIT09IHVuZGVmaW5lZCkge1xuICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKFxuICAgICAgXCJxZ3JpZDogYXV0b21hdGljIGFuZCBzdGFuZGFsb25lIGltYWdlIGdlbmVyYXRpb24gZG8gbm90IHN1cHBvcnQgY2FsbGVyIHRvb2xzIG9yIHN0cnVjdHVyZWQgb3V0cHV0LlwiIGFzIExvY2FsaXplZFN0cmluZyxcbiAgICApO1xuICB9XG4gIGlmIChcbiAgICBhcmdzLmltYWdlR2VuZXJhdGlvbk9wdGlvbnM/Lm91dHB1dEZvcm1hdCAmJlxuICAgIGFyZ3MuaW1hZ2VHZW5lcmF0aW9uT3B0aW9ucy5vdXRwdXRGb3JtYXQgIT09IFwicG5nXCJcbiAgKSB7XG4gICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oXG4gICAgICBcInFncmlkOiBhdXRvbWF0aWMgYW5kIHN0YW5kYWxvbmUgaW1hZ2UgZ2VuZXJhdGlvbiBvbmx5IHN1cHBvcnQgUE5HIG91dHB1dC5cIiBhcyBMb2NhbGl6ZWRTdHJpbmcsXG4gICAgKTtcbiAgfVxufVxuXG4vLyBhbnRocm9waWMg7J2AIC0tanNvbi1zY2hlbWEg66W8IOyTsOyngCDslYrsnLzrr4DroZwoU09OLTUzMikgc3RyaWN0IOuzgO2ZmMK3YXJndiDsoJztlZwg7JeG7J20IOybkO2YleydmFxuLy8g6rWs66y4wrfrs7XsnqHrj4Trp4wg6rKA7Kad65Cc64ukIOKAlCBwcm92aWRlciDrtoTquLDripQgYnVpbGRBbmRWYWxpZGF0ZVN0cmljdE91dHB1dFNjaGVtYSDqsIAg7IaM7Jyg7ZWc64ukLlxuZnVuY3Rpb24gcmVqZWN0SW52YWxpZENhbGxlclNjaGVtYXMoYXJnczogUXVlcnlJbnB1dCk6IHZvaWQge1xuICBpZiAoYXJncy5qc29uU2NoZW1hID09PSB1bmRlZmluZWQgJiYgIWFyZ3MudG9vbHM/Lmxlbmd0aCkgcmV0dXJuO1xuXG4gIHRyeSB7XG4gICAgYnVpbGRBbmRWYWxpZGF0ZVN0cmljdE91dHB1dFNjaGVtYShhcmdzKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBpZiAoXG4gICAgICBlcnJvciBpbnN0YW5jZW9mIENhbGxlclNjaGVtYVZhbGlkYXRpb25FcnJvciB8fFxuICAgICAgZXJyb3IgaW5zdGFuY2VvZiBUb29sU2NoZW1hQ29tcG9zaXRpb25FcnJvclxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oZXJyb3IubWVzc2FnZSBhcyBMb2NhbGl6ZWRTdHJpbmcpO1xuICAgIH1cbiAgICAvLyDsnpjrqrvrkJwga2V5d29yZCDtmJXtg5woYW55T2Yg66W8IOqwneyytOuhnCDrs7TrgrTripQg65OxKeuKlCDtjIzsnbTtlITrnbzsnbjsl5DshJwgdW50eXBlZCDsmKTrpZjroZwg64KY7Jik66+A66GcLFxuICAgIC8vIO2DgOyehSDsooHtnojquLAg64yA7IugIEVycm9yIOyghOyytOulvCBjYWxsZXItZmF1bHQgNDAwIOycvOuhnCDrp6TtlZHtlZzri6Qo6rOE7JW9IO2FjOyKpO2KuOuhnCDqs6DsoJXrkKgpLlxuICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihcbiAgICAgICAgYHFncmlkOiBjYWxsZXIgc2NoZW1hIGNhbm5vdCBiZSBub3JtYWxpemVkOiAke2Vycm9yLm1lc3NhZ2V9YCBhcyBMb2NhbGl6ZWRTdHJpbmcsXG4gICAgICApO1xuICAgIH1cbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiByZXNvbHZlVG9rZW5OYW1lKGFyZ3M6IFF1ZXJ5SW5wdXQpOiBQcm9taXNlPEludGVybmFsUXVlcnlJbnB1dD4ge1xuICBpZiAoIWFyZ3MudG9rZW5OYW1lKSByZXR1cm4gYXJncztcblxuICBjb25zdCB0b2tlblByb3ZpZGVyID0gYXJncy50b2tlbk5hbWUuc3BsaXQoXCIvXCIsIDEpWzBdO1xuICBjb25zdCBtb2RlbFByb3ZpZGVyID0gYXJncy5tb2RlbD8uc3BsaXQoXCIvXCIsIDEpWzBdO1xuICBpZiAodG9rZW5Qcm92aWRlciAhPT0gXCJhbnRocm9waWNcIiAmJiB0b2tlblByb3ZpZGVyICE9PSBcIm9wZW5haVwiKSB7XG4gICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oYEludmFsaWQgdG9rZW4gbmFtZTogJHthcmdzLnRva2VuTmFtZX1gIGFzIExvY2FsaXplZFN0cmluZyk7XG4gIH1cbiAgaWYgKG1vZGVsUHJvdmlkZXIgIT09IHRva2VuUHJvdmlkZXIpIHtcbiAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihcbiAgICAgIFwiVG9rZW4gcHJvdmlkZXIgZG9lcyBub3QgbWF0Y2ggbW9kZWwgcHJvdmlkZXJcIiBhcyBMb2NhbGl6ZWRTdHJpbmcsXG4gICAgKTtcbiAgfVxuXG4gIGNvbnN0IHRva2VuID0gYXdhaXQgVG9rZW5Nb2RlbC5maW5kQWN0aXZlQnlQcm92aWRlckFuZE5hbWUoXCJBXCIsIHRva2VuUHJvdmlkZXIsIGFyZ3MudG9rZW5OYW1lKTtcbiAgaWYgKCF0b2tlbikge1xuICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKGBBY3RpdmUgdG9rZW4gbm90IGZvdW5kOiAke2FyZ3MudG9rZW5OYW1lfWAgYXMgTG9jYWxpemVkU3RyaW5nKTtcbiAgfVxuICByZXR1cm4geyAuLi5hcmdzLCBwcmVmZXJyZWRUb2tlbklkOiB0b2tlbi5pZCwgcmVxdWlyZVByZWZlcnJlZFRva2VuOiB0cnVlIH07XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUh0dHBEaXNjb25uZWN0SGFuZGxlKCk6IHtcbiAgc2lnbmFsOiBBYm9ydFNpZ25hbDtcbiAgZGlzcG9zZTogKCkgPT4gdm9pZDtcbn0ge1xuICBjb25zdCBhYm9ydENvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gIGxldCByZXF1ZXN0UmF3OiBGYXN0aWZ5UmVxdWVzdFtcInJhd1wiXSB8IHVuZGVmaW5lZDtcbiAgbGV0IHJlc3BvbnNlUmF3OiBGYXN0aWZ5UmVwbHlbXCJyYXdcIl0gfCB1bmRlZmluZWQ7XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBjdHggPSBTb25hbXUuZ2V0Q29udGV4dCgpO1xuICAgIHJlcXVlc3RSYXcgPSBjdHgucmVxdWVzdD8ucmF3O1xuICAgIGlmIChjdHgudHJhbnNwb3J0ID09PSBcImh0dHBcIikgcmVzcG9uc2VSYXcgPSBjdHgucmVwbHkucmF3O1xuICB9IGNhdGNoIHtcbiAgICAvLyBEaXJlY3QgZnJhbWUgY2FsbHMgKGZvciBleGFtcGxlIHVuaXQgdGVzdHMpIGRvIG5vdCBoYXZlIGFuIEhUVFAgY29udGV4dC5cbiAgfVxuXG4gIGNvbnN0IGFib3J0ID0gKCkgPT4gYWJvcnRDb250cm9sbGVyLmFib3J0KCk7XG4gIGNvbnN0IGFib3J0T25JbmNvbXBsZXRlUmVzcG9uc2VDbG9zZSA9ICgpID0+IHtcbiAgICBpZiAoIXJlc3BvbnNlUmF3Py53cml0YWJsZUVuZGVkKSBhYm9ydCgpO1xuICB9O1xuXG4gIHJlcXVlc3RSYXc/Lm9uY2UoXCJhYm9ydGVkXCIsIGFib3J0KTtcbiAgcmVzcG9uc2VSYXc/Lm9uY2UoXCJjbG9zZVwiLCBhYm9ydE9uSW5jb21wbGV0ZVJlc3BvbnNlQ2xvc2UpO1xuXG4gIGlmIChyZXF1ZXN0UmF3Py5hYm9ydGVkIHx8IChyZXNwb25zZVJhdz8uZGVzdHJveWVkICYmICFyZXNwb25zZVJhdy53cml0YWJsZUVuZGVkKSkge1xuICAgIGFib3J0KCk7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIHNpZ25hbDogYWJvcnRDb250cm9sbGVyLnNpZ25hbCxcbiAgICBkaXNwb3NlOiAoKSA9PiB7XG4gICAgICByZXF1ZXN0UmF3Py5yZW1vdmVMaXN0ZW5lcihcImFib3J0ZWRcIiwgYWJvcnQpO1xuICAgICAgcmVzcG9uc2VSYXc/LnJlbW92ZUxpc3RlbmVyKFwiY2xvc2VcIiwgYWJvcnRPbkluY29tcGxldGVSZXNwb25zZUNsb3NlKTtcbiAgICB9LFxuICB9O1xufVxuXG5jb25zdCBsb2dnZXIgPSBnZXRMb2dnZXIoW1wicWdyaWRcIl0pO1xuY29uc3Qgb2F1dGhMb2dnZXIgPSBnZXRMb2dnZXIoW1wicWdyaWRcIiwgXCJvYXV0aFwiXSk7XG5cbi8vIHBlci10b2tlbiByZWZyZXNoIGRlZHVwIOKAlCDtmozsoIQg6rK57Lmo7Jy866GcIOyduO2VnCDsgqzrp50g7Jik7YyQ7J2EIOunieuKlOuLpC5cbmNvbnN0IGluZmxpZ2h0QW50aHJvcGljUmVmcmVzaCA9IG5ldyBNYXA8bnVtYmVyLCBQcm9taXNlPHN0cmluZz4+KCk7XG5cbmNsYXNzIFFncmlkRnJhbWVDbGFzcyBleHRlbmRzIEJhc2VGcmFtZUNsYXNzIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoXCJRZ3JpZFwiKTtcbiAgfVxuXG4gIEBhcGkoeyBodHRwTWV0aG9kOiBcIlBPU1RcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1tdXRhdGlvblwiXSB9KVxuICBhc3luYyBxdWVyeShhcmdzOiBRdWVyeUlucHV0KTogUHJvbWlzZTxRdWVyeU91dHB1dD4ge1xuICAgIHJlamVjdEludmFsaWRJbWFnZVF1ZXJ5KGFyZ3MpO1xuICAgIHJlamVjdEludmFsaWRDYWxsZXJTY2hlbWFzKGFyZ3MpO1xuICAgIGNvbnN0IHJlc29sdmVkQXJncyA9IGF3YWl0IHJlc29sdmVUb2tlbk5hbWUoYXJncyk7XG4gICAgY29uc3QgZGlzY29ubmVjdCA9IGNyZWF0ZUh0dHBEaXNjb25uZWN0SGFuZGxlKCk7XG4gICAgdHJ5IHtcbiAgICAgIGlmIChyZXNvbHZlZEFyZ3MubG9nZ2VyID09PSBmYWxzZSkge1xuICAgICAgICByZXR1cm4gYXdhaXQgUWdyaWREaXNwYXRjaGVyLnF1ZXJ5KHJlc29sdmVkQXJncywgZGlzY29ubmVjdC5zaWduYWwpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB7IHJlcXVlc3RMb2dJZCwgc3RlcEluZGV4IH0gPSBhd2FpdCBiZWZvcmVRdWVyeShyZXNvbHZlZEFyZ3MpO1xuICAgICAgbGV0IHJlc3VsdDogUXVlcnlPdXRwdXQ7XG4gICAgICB0cnkge1xuICAgICAgICByZXN1bHQgPSBhd2FpdCBRZ3JpZERpc3BhdGNoZXIucXVlcnkocmVzb2x2ZWRBcmdzLCBkaXNjb25uZWN0LnNpZ25hbCk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnN0IGNvbXBsZXRlZERyaXZlciA9IGNvbXBsZXRlZERyaXZlckZyb21JbWFnZUZhaWx1cmUoZSwgcmVzb2x2ZWRBcmdzLnNlcnZpY2VUaWVyKTtcbiAgICAgICAgY29uc3QgY29tcGxldGVkU3RlcCA9IGNvbXBsZXRlZERyaXZlclxuICAgICAgICAgID8gKFt7IHN0ZXBJbmRleCwgcmVzdWx0OiBjb21wbGV0ZWREcml2ZXIgfV0gYXMgY29uc3QpXG4gICAgICAgICAgOiAoW10gYXMgY29uc3QpO1xuICAgICAgICBpZiAoZGlzY29ubmVjdC5zaWduYWwuYWJvcnRlZCkge1xuICAgICAgICAgIGF3YWl0IGZpbmlzaFJ1bkFib3J0ZWQocmVxdWVzdExvZ0lkLCByZXNvbHZlZEFyZ3MsIC4uLmNvbXBsZXRlZFN0ZXApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGF3YWl0IGZpbmlzaFJ1bldpdGhFcnJvcihcbiAgICAgICAgICAgIHJlcXVlc3RMb2dJZCxcbiAgICAgICAgICAgIChlIGFzIEVycm9yKS5tZXNzYWdlLFxuICAgICAgICAgICAgcmVzb2x2ZWRBcmdzLFxuICAgICAgICAgICAgLi4uY29tcGxldGVkU3RlcCxcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGxpZmVjeWNsZSA9IGF3YWl0IGFmdGVyUXVlcnkocmVxdWVzdExvZ0lkLCBzdGVwSW5kZXgsIHJlc29sdmVkQXJncywgcmVzdWx0KTtcbiAgICAgICAgaWYgKGRpc2Nvbm5lY3Quc2lnbmFsLmFib3J0ZWQpIHtcbiAgICAgICAgICBhd2FpdCBmaW5pc2hSdW5BYm9ydGVkKHJlcXVlc3RMb2dJZCwgcmVzb2x2ZWRBcmdzKTtcbiAgICAgICAgfVxuICAgICAgICAvLyB0b29sLWNhbGwgcmVxdWVzdExvZ0lk7JmAIHByb3ZpZGVyIHRocmVhZENvb3Jk64qUIOyEnOuhnCDrj4Xrpr3soIHsnLzroZwg7Jyg7KeA7ZWc64ukLlxuICAgICAgICBjb25zdCB0aHJlYWRDb29yZCA9IHJlc3VsdC5ydW5Db250ZXh0Py50aHJlYWRDb29yZDtcbiAgICAgICAgY29uc3QgcnVuQ29udGV4dCA9XG4gICAgICAgICAgbGlmZWN5Y2xlLnJ1bkNvbnRleHQgfHwgdGhyZWFkQ29vcmRcbiAgICAgICAgICAgID8geyAuLi5saWZlY3ljbGUucnVuQ29udGV4dCwgLi4uKHRocmVhZENvb3JkID8geyB0aHJlYWRDb29yZCB9IDoge30pIH1cbiAgICAgICAgICAgIDogdW5kZWZpbmVkO1xuICAgICAgICByZXR1cm4geyAuLi5yZXN1bHQsIHJlcXVlc3RMb2dJZCwgcnVuQ29udGV4dCB9O1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBsb2dnZXIuZXJyb3IoYHF1ZXJ5IGFmdGVyUXVlcnkgZmFpbGVkOiAkeyhlIGFzIEVycm9yKS5tZXNzYWdlfWApO1xuICAgICAgICBpZiAoZGlzY29ubmVjdC5zaWduYWwuYWJvcnRlZCkge1xuICAgICAgICAgIGF3YWl0IGZpbmlzaFJ1bkFib3J0ZWQocmVxdWVzdExvZ0lkLCByZXNvbHZlZEFyZ3MpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGF3YWl0IGZpbmlzaFJ1bldpdGhFcnJvcihyZXF1ZXN0TG9nSWQsIChlIGFzIEVycm9yKS5tZXNzYWdlLCByZXNvbHZlZEFyZ3MpO1xuICAgICAgICB9XG4gICAgICAgIC8vIHByb3ZpZGVyIOydkeuLteydgCDshLHqs7XtlojsnLzrr4DroZwg66Gc6rmFIOyepeyVoOqwgCDsg53shLEg6rKw6rO866W8IOuNruyWtOyTsOyngCDslYrripTri6QuXG4gICAgICAgIHJldHVybiB7IC4uLnJlc3VsdCwgcmVxdWVzdExvZ0lkIH07XG4gICAgICB9XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGRpc2Nvbm5lY3QuZGlzcG9zZSgpO1xuICAgIH1cbiAgfVxuXG4gIEBhcGkoeyBodHRwTWV0aG9kOiBcIlBPU1RcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1tdXRhdGlvblwiXSB9KVxuICBhc3luYyBwcmVwYXJlU3RyZWFtKGFyZ3M6IFF1ZXJ5SW5wdXQpOiBQcm9taXNlPHsgc3RyZWFtSWQ6IHN0cmluZyB9PiB7XG4gICAgcmVqZWN0SW1hZ2VHZW5lcmF0aW9uU3RyZWFtKGFyZ3MpO1xuICAgIHJlamVjdEludmFsaWRDYWxsZXJTY2hlbWFzKGFyZ3MpO1xuICAgIGNvbnN0IHJlc29sdmVkQXJncyA9IGF3YWl0IHJlc29sdmVUb2tlbk5hbWUoYXJncyk7XG4gICAgY29uc3Qgc3RyZWFtSWQgPSBjcnlwdG8ucmFuZG9tVVVJRCgpO1xuICAgIHBlbmRpbmdTdHJlYW1zLnNldChzdHJlYW1JZCwgcmVzb2x2ZWRBcmdzKTtcbiAgICBjb25zdCBleHBpcnkgPSBzZXRUaW1lb3V0KCgpID0+IHBlbmRpbmdTdHJlYW1zLmRlbGV0ZShzdHJlYW1JZCksIDMwXzAwMCk7XG4gICAgZXhwaXJ5LnVucmVmPy4oKTtcbiAgICByZXR1cm4geyBzdHJlYW1JZCB9O1xuICB9XG5cbiAgQHN0cmVhbSh7IHR5cGU6IFwic3NlXCIsIGV2ZW50czogU3RyZWFtRXZlbnRzIH0pXG4gIGFzeW5jIHF1ZXJ5U3RyZWFtKHN0cmVhbUlkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBhcmdzID0gcGVuZGluZ1N0cmVhbXMuZ2V0KHN0cmVhbUlkKTtcbiAgICBwZW5kaW5nU3RyZWFtcy5kZWxldGUoc3RyZWFtSWQpO1xuICAgIGlmICghYXJncykgdGhyb3cgbmV3IEVycm9yKFwiaW52YWxpZCBvciBleHBpcmVkIHN0cmVhbUlkXCIpO1xuICAgIHJlamVjdEltYWdlR2VuZXJhdGlvblN0cmVhbShhcmdzKTtcblxuICAgIGNvbnN0IGN0eCA9IFNvbmFtdS5nZXRDb250ZXh0KCk7XG4gICAgY29uc3Qgc3NlID0gY3R4LmNyZWF0ZVNTRShTdHJlYW1FdmVudHMpO1xuICAgIGxldCBzdHJlYW1SZXN1bHQ6IFF1ZXJ5T3V0cHV0IHwgdW5kZWZpbmVkO1xuICAgIGxldCBzdHJlYW1FcnJvcjogRXJyb3IgfCB1bmRlZmluZWQ7XG4gICAgbGV0IGNsaWVudENsb3NlZCA9IGZhbHNlO1xuICAgIGNvbnN0IGFib3J0Q29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcblxuICAgIHNzZS5vbkNsb3NlKCgpID0+IHtcbiAgICAgIGNsaWVudENsb3NlZCA9IHRydWU7XG4gICAgICBhYm9ydENvbnRyb2xsZXIuYWJvcnQoKTtcbiAgICB9KTtcblxuICAgIGxldCBydW5JbmZvOiB7IHJlcXVlc3RMb2dJZDogbnVtYmVyOyBzdGVwSW5kZXg6IG51bWJlciB9IHwgdW5kZWZpbmVkO1xuICAgIGlmIChhcmdzLmxvZ2dlciAhPT0gZmFsc2UpIHtcbiAgICAgIC8vIHByb3ZpZGVyIOyLpO2WiSDsoIQgcnVubmluZyByb3cg7IOd7ISx7JeQIOyLpO2MqO2VmOuptCBsb2dnZWQg7JqU7LKt7Jy866GcIOynhO2Wie2VmOyngCDslYrripTri6QuXG4gICAgICBydW5JbmZvID0gYXdhaXQgYmVmb3JlUXVlcnkoYXJncyk7XG4gICAgfVxuXG4gICAgLy8gYmVmb3JlUXVlcnkgREIg7J6R7JeFIOykkSBjbG9zZeulvCDrhpPsuZjsp4Ag7JWK6rOgIHByb3ZpZGVyIOyLpO2WiSDsoITsl5Ag66eI6rCQ7ZWc64ukLlxuICAgIGlmIChjbGllbnRDbG9zZWQgfHwgc3NlLmNsb3NlZCkge1xuICAgICAgaWYgKHJ1bkluZm8pIGF3YWl0IGZpbmlzaFJ1bkFib3J0ZWQocnVuSW5mby5yZXF1ZXN0TG9nSWQsIGFyZ3MpO1xuICAgICAgYXdhaXQgc3NlLmVuZCgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCBRZ3JpZERpc3BhdGNoZXIucXVlcnlTdHJlYW0oXG4gICAgICAgIGFyZ3MsXG4gICAgICAgIHtcbiAgICAgICAgICBvbkRlbHRhOiAodGV4dCkgPT4ge1xuICAgICAgICAgICAgaWYgKCFjbGllbnRDbG9zZWQgJiYgIXNzZS5jbG9zZWQpIHNzZS5wdWJsaXNoKFwiZGVsdGFcIiwgeyB0ZXh0IH0pO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgb25Db21wbGV0ZTogKHJlc3VsdCkgPT4ge1xuICAgICAgICAgICAgc3RyZWFtUmVzdWx0ID0gcmVzdWx0O1xuICAgICAgICAgIH0sXG4gICAgICAgICAgb25FcnJvcjogKGVycikgPT4ge1xuICAgICAgICAgICAgc3RyZWFtRXJyb3IgPSBlcnI7XG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgYWJvcnRDb250cm9sbGVyLnNpZ25hbCxcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgc3RyZWFtRXJyb3IgPSBlIGFzIEVycm9yO1xuICAgIH1cblxuICAgIC8vIHByb3ZpZGVyIOqysOqzvOqwgCDsl4bripQgY2xvc2XripQg7KaJ7IucIGFib3J0ZWTroZwg66eI6rCQ7ZWc64ukLlxuICAgIGlmIChjbGllbnRDbG9zZWQgJiYgIXN0cmVhbVJlc3VsdCkge1xuICAgICAgaWYgKHJ1bkluZm8pIGF3YWl0IGZpbmlzaFJ1bkFib3J0ZWQocnVuSW5mby5yZXF1ZXN0TG9nSWQsIGFyZ3MpO1xuICAgICAgYXdhaXQgc3NlLmVuZCgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIGRpc3BhdGNoZXIg7JmE66OMIO2bhCBsaWZlY3ljbGUg7LKY66asIChhd2FpdCDslYjsoIQpXG4gICAgaWYgKHN0cmVhbVJlc3VsdCkge1xuICAgICAgLy8gZGlzcGF0Y2hlciDqsIAg7Iuk7J2AIHRocmVhZCDsnqzsgqzsmqkg7KKM7ZGc64qUIGxvZ2dlciDshKTsoJXqs7wg66y06rSA7ZWY6rKMIO2ajOyGoe2VnOuLpC5cbiAgICAgIGNvbnN0IHRocmVhZENvb3JkID0gc3RyZWFtUmVzdWx0LnJ1bkNvbnRleHQ/LnRocmVhZENvb3JkO1xuICAgICAgbGV0IHJ1bkNvbnRleHQ6IFFncmlkUnVuQ29udGV4dCB8IHVuZGVmaW5lZCA9XG4gICAgICAgIHRocmVhZENvb3JkICE9PSB1bmRlZmluZWQgPyB7IHRocmVhZENvb3JkIH0gOiB1bmRlZmluZWQ7XG4gICAgICBpZiAocnVuSW5mbykge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIC8vIGNsb3NlIO2bhCDrj4TssKntlZwg6rKw6rO864+EIHN0ZXAvdXNhZ2XripQg64Ko6riw65CYLCDslYTrnpjsl5DshJwg7LWc7KKFIHN0YXR1c+ulvCBhYm9ydGVk66GcIOuNruyWtOyTtOuLpC5cbiAgICAgICAgICBjb25zdCBsaWZlY3ljbGUgPSBhd2FpdCBhZnRlclF1ZXJ5KFxuICAgICAgICAgICAgcnVuSW5mby5yZXF1ZXN0TG9nSWQsXG4gICAgICAgICAgICBydW5JbmZvLnN0ZXBJbmRleCxcbiAgICAgICAgICAgIGFyZ3MsXG4gICAgICAgICAgICBzdHJlYW1SZXN1bHQsXG4gICAgICAgICAgKTtcbiAgICAgICAgICBydW5Db250ZXh0ID1cbiAgICAgICAgICAgIGxpZmVjeWNsZS5ydW5Db250ZXh0IHx8IHRocmVhZENvb3JkXG4gICAgICAgICAgICAgID8geyAuLi5saWZlY3ljbGUucnVuQ29udGV4dCwgLi4uKHRocmVhZENvb3JkID8geyB0aHJlYWRDb29yZCB9IDoge30pIH1cbiAgICAgICAgICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAvLyBhZnRlclF1ZXJ56rCAIOynhO2WieuQmOuKlCDsgqzsnbQgY2xpZW506rCAIOuLq+2ejCDqsr3smrAg7JmE66OMIOyDge2DnOulvCBhYm9ydGVk66GcIOuQmOuPjOumsOuLpC5cbiAgICAgICAgICBpZiAoY2xpZW50Q2xvc2VkKSB7XG4gICAgICAgICAgICBhd2FpdCBmaW5pc2hSdW5BYm9ydGVkKHJ1bkluZm8ucmVxdWVzdExvZ0lkLCBhcmdzKTtcbiAgICAgICAgICAgIGF3YWl0IHNzZS5lbmQoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBsb2dnZXIuZXJyb3IoYHN0cmVhbSBhZnRlclF1ZXJ5IGZhaWxlZDogJHsoZSBhcyBFcnJvcikubWVzc2FnZX1gKTtcbiAgICAgICAgICBhd2FpdCBmaW5pc2hSdW5XaXRoRXJyb3IocnVuSW5mby5yZXF1ZXN0TG9nSWQsIChlIGFzIEVycm9yKS5tZXNzYWdlLCBhcmdzKTtcblxuICAgICAgICAgIGlmIChjbGllbnRDbG9zZWQpIHtcbiAgICAgICAgICAgIGF3YWl0IGZpbmlzaFJ1bkFib3J0ZWQocnVuSW5mby5yZXF1ZXN0TG9nSWQsIGFyZ3MpO1xuICAgICAgICAgICAgYXdhaXQgc3NlLmVuZCgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKCFjbGllbnRDbG9zZWQgJiYgIXNzZS5jbG9zZWQpIHtcbiAgICAgICAgc3NlLnB1Ymxpc2goXCJkb25lXCIsIHtcbiAgICAgICAgICAuLi5zdHJlYW1SZXN1bHQsXG4gICAgICAgICAgLi4uKHJ1bkluZm8gPyB7IHJlcXVlc3RMb2dJZDogcnVuSW5mby5yZXF1ZXN0TG9nSWQgfSA6IHt9KSxcbiAgICAgICAgICBydW5Db250ZXh0LFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHN0cmVhbUVycm9yKSB7XG4gICAgICBpZiAocnVuSW5mbykgYXdhaXQgZmluaXNoUnVuV2l0aEVycm9yKHJ1bkluZm8ucmVxdWVzdExvZ0lkLCBzdHJlYW1FcnJvci5tZXNzYWdlLCBhcmdzKTtcbiAgICAgIGlmICghY2xpZW50Q2xvc2VkICYmICFzc2UuY2xvc2VkKSBzc2UucHVibGlzaChcImVycm9yXCIsIHsgbWVzc2FnZTogc3RyZWFtRXJyb3IubWVzc2FnZSB9KTtcbiAgICB9IGVsc2UgaWYgKChjbGllbnRDbG9zZWQgfHwgc3NlLmNsb3NlZCkgJiYgcnVuSW5mbykge1xuICAgICAgYXdhaXQgZmluaXNoUnVuQWJvcnRlZChydW5JbmZvLnJlcXVlc3RMb2dJZCwgYXJncyk7XG4gICAgfVxuXG4gICAgYXdhaXQgc3NlLmVuZCgpO1xuICB9XG5cbiAgQGFwaSh7IGh0dHBNZXRob2Q6IFwiUE9TVFwiLCBjbGllbnRzOiBbXCJheGlvc1wiLCBcInRhbnN0YWNrLW11dGF0aW9uXCJdIH0pXG4gIGFzeW5jIGNyZWF0ZVJ1bihpbnB1dDogQ3JlYXRlUnVuSW5wdXQpOiBQcm9taXNlPHsgcmVxdWVzdExvZ0lkOiBudW1iZXIgfT4ge1xuICAgIGNvbnN0IHJlcXVlc3RMb2dJZCA9IGF3YWl0IFJlcXVlc3RMb2dNb2RlbC5jcmVhdGVSdW4oe1xuICAgICAgdXNlcl9wcm9tcHQ6IGlucHV0LnVzZXJQcm9tcHQsXG4gICAgICByZXF1ZXN0ZWRfbW9kZWxfbmFtZTogaW5wdXQubW9kZWxOYW1lLFxuICAgICAgZWZmb3J0OiBpbnB1dC5lZmZvcnQsXG4gICAgICBwcm9qZWN0X25hbWU6IGlucHV0LnByb2plY3ROYW1lLFxuICAgICAgc3lzdGVtX3Byb21wdDogaW5wdXQuc3lzdGVtUHJvbXB0LFxuICAgICAgaGlzdG9yeTogaW5wdXQuaGlzdG9yeSA/IEpTT04ucGFyc2UoaW5wdXQuaGlzdG9yeSkgOiB1bmRlZmluZWQsXG4gICAgICBpc19zdHJ1Y3R1cmVkOiBpbnB1dC5pc1N0cnVjdHVyZWQsXG4gICAgICBqc29uX3NjaGVtYTogaW5wdXQuanNvblNjaGVtYSxcbiAgICB9KTtcbiAgICByZXR1cm4geyByZXF1ZXN0TG9nSWQgfTtcbiAgfVxuXG4gIEBhcGkoeyBodHRwTWV0aG9kOiBcIlBPU1RcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1tdXRhdGlvblwiXSB9KVxuICBhc3luYyBhcHBlbmRTdGVwKGlucHV0OiBBcHBlbmRTdGVwSW5wdXQpOiBQcm9taXNlPHsgc3RlcElkOiBudW1iZXIgfT4ge1xuICAgIGNvbnN0IHN0ZXBJZCA9IGF3YWl0IFJlcXVlc3RMb2dNb2RlbC5hcHBlbmRTdGVwKGlucHV0LnJlcXVlc3RMb2dJZCwge1xuICAgICAgc3RlcF9pbmRleDogaW5wdXQuc3RlcEluZGV4LFxuICAgICAgdHlwZTogaW5wdXQudHlwZSxcbiAgICAgIG1vZGVsX25hbWU6IGlucHV0Lm1vZGVsTmFtZSxcbiAgICAgIHJlcXVlc3RlZF9tb2RlbF9uYW1lOiBpbnB1dC5yZXF1ZXN0ZWRNb2RlbE5hbWUsXG4gICAgICBmYWxsYmFja19jb3VudDogaW5wdXQuZmFsbGJhY2tDb3VudCxcbiAgICAgIGlucHV0X3Rva2VuczogaW5wdXQuaW5wdXRUb2tlbnMsXG4gICAgICBvdXRwdXRfdG9rZW5zOiBpbnB1dC5vdXRwdXRUb2tlbnMsXG4gICAgICBjYWNoZV9yZWFkX3Rva2VuczogaW5wdXQuY2FjaGVSZWFkVG9rZW5zLFxuICAgICAgY2FjaGVfY3JlYXRpb25fdG9rZW5zOiBpbnB1dC5jYWNoZUNyZWF0aW9uVG9rZW5zLFxuICAgICAgY2FjaGVfY3JlYXRpb25fNW1fdG9rZW5zOiBpbnB1dC5jYWNoZUNyZWF0aW9uNW1Ub2tlbnMsXG4gICAgICBjYWNoZV9jcmVhdGlvbl8xaF90b2tlbnM6IGlucHV0LmNhY2hlQ3JlYXRpb24xaFRva2VucyxcbiAgICAgIGNvc3RfdXNkOiBpbnB1dC5jb3N0VXNkID09PSB1bmRlZmluZWQgPyB1bmRlZmluZWQgOiBNYXRoLnJvdW5kKGlucHV0LmNvc3RVc2QgKiBNSUNST19VU0QpLFxuICAgICAgY29zdF9zb3VyY2U6IGlucHV0LmNvc3RTb3VyY2UsXG4gICAgICBkdXJhdGlvbl9tczogaW5wdXQuZHVyYXRpb25NcyxcbiAgICAgIHR0ZnRfbXM6IGlucHV0LnR0ZnRNcyA/PyBudWxsLFxuICAgICAgZmluaXNoX3JlYXNvbjogaW5wdXQuZmluaXNoUmVhc29uLFxuICAgICAgcmVhc29uaW5nX3RleHQ6IGlucHV0LnJlYXNvbmluZ1RleHQsXG4gICAgICByZWFzb25pbmdfdG9rZW5zOiBpbnB1dC5yZWFzb25pbmdUb2tlbnMsXG4gICAgICB0b29sX2NhbGxfaW5kZXg6IGlucHV0LnRvb2xDYWxsSW5kZXgsXG4gICAgICB0b29sX2NhbGxfaWQ6IGlucHV0LnRvb2xDYWxsSWQsXG4gICAgICB0b29sX25hbWU6IGlucHV0LnRvb2xOYW1lLFxuICAgICAgdG9vbF9hcmdzOiBpbnB1dC50b29sQXJncyxcbiAgICAgIHRvb2xfcmVzdWx0OiBpbnB1dC50b29sUmVzdWx0LFxuICAgICAgdG9vbF9kdXJhdGlvbl9tczogaW5wdXQudG9vbER1cmF0aW9uTXMsXG4gICAgICBlcnJvcjogaW5wdXQuZXJyb3IsXG4gICAgfSk7XG4gICAgcmV0dXJuIHsgc3RlcElkIH07XG4gIH1cblxuICBAYXBpKHsgaHR0cE1ldGhvZDogXCJQT1NUXCIsIGNsaWVudHM6IFtcImF4aW9zXCIsIFwidGFuc3RhY2stbXV0YXRpb25cIl0gfSlcbiAgYXN5bmMgZmluaXNoUnVuKGlucHV0OiBGaW5pc2hSdW5JbnB1dCk6IFByb21pc2U8eyBvazogYm9vbGVhbiB9PiB7XG4gICAgYXdhaXQgUmVxdWVzdExvZ01vZGVsLmZpbmlzaFJ1bihpbnB1dC5yZXF1ZXN0TG9nSWQsIHtcbiAgICAgIHN0YXR1czogaW5wdXQuc3RhdHVzLFxuICAgICAgcmVzcG9uc2U6IGlucHV0LnJlc3BvbnNlLFxuICAgICAgdG9rZW5fbmFtZTogaW5wdXQudG9rZW5OYW1lLFxuICAgICAgbW9kZWxfbmFtZTogaW5wdXQubW9kZWxOYW1lLFxuICAgICAgcmVxdWVzdGVkX21vZGVsX25hbWU6IGlucHV0LnJlcXVlc3RlZE1vZGVsTmFtZSxcbiAgICAgIGZhbGxiYWNrX2NvdW50OiBpbnB1dC5mYWxsYmFja0NvdW50LFxuICAgICAgaW5wdXRfdG9rZW5zOiBpbnB1dC50b3RhbElucHV0VG9rZW5zLFxuICAgICAgb3V0cHV0X3Rva2VuczogaW5wdXQudG90YWxPdXRwdXRUb2tlbnMsXG4gICAgICBjYWNoZV9yZWFkX3Rva2VuczogaW5wdXQudG90YWxDYWNoZVJlYWRUb2tlbnMsXG4gICAgICBjYWNoZV9jcmVhdGlvbl90b2tlbnM6IGlucHV0LnRvdGFsQ2FjaGVDcmVhdGlvblRva2VucyxcbiAgICAgIGNhY2hlX2NyZWF0aW9uXzVtX3Rva2VuczogaW5wdXQudG90YWxDYWNoZUNyZWF0aW9uNW1Ub2tlbnMsXG4gICAgICBjYWNoZV9jcmVhdGlvbl8xaF90b2tlbnM6IGlucHV0LnRvdGFsQ2FjaGVDcmVhdGlvbjFoVG9rZW5zLFxuICAgICAgY29zdF91c2Q6IGlucHV0LmNvc3RVc2QgPT09IHVuZGVmaW5lZCA/IHVuZGVmaW5lZCA6IE1hdGgucm91bmQoaW5wdXQuY29zdFVzZCAqIE1JQ1JPX1VTRCksXG4gICAgICBjb3N0X3NvdXJjZTogaW5wdXQuY29zdFNvdXJjZSxcbiAgICAgIGR1cmF0aW9uX21zOiBpbnB1dC50b3RhbER1cmF0aW9uTXMsXG4gICAgICBoaXN0b3J5OiBpbnB1dC5oaXN0b3J5ID8gSlNPTi5wYXJzZShpbnB1dC5oaXN0b3J5KSA6IHVuZGVmaW5lZCxcbiAgICAgIGVycm9yX21lc3NhZ2U6IGlucHV0LmVycm9yTWVzc2FnZSxcbiAgICAgIHJlc3BvbnNlX2pzb25fb2s6IGlucHV0LnJlc3BvbnNlSnNvbk9rLFxuICAgIH0pO1xuICAgIHJldHVybiB7IG9rOiB0cnVlIH07XG4gIH1cblxuICBAYXBpKHsgaHR0cE1ldGhvZDogXCJHRVRcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1xdWVyeVwiXSB9KVxuICBhc3luYyBzdGF0cygpOiBQcm9taXNlPFRva2VuU3RhdHNbXT4ge1xuICAgIHJldHVybiBRZ3JpZERpc3BhdGNoZXIuZ2V0U3RhdHMoKTtcbiAgfVxuXG4gIC8vIO2ZlOuptOydmCDrqqnroZ0g7ZWE7YSw66W8IOq3uOuMgOuhnCDrsJvslYQg6rCZ7J2AIOyhsOqxtOydmCDtlanqs4Trpbwg64+M66Ck7KSA64ukIOKAlCDrqqnroZ3qs7wg67mE7Jqp7J20XG4gIC8vIOyEnOuhnCDri6Trpbgg66qo7IiY66W8IOuztOuptCDsgqzsmqnsnpDsl5DqsozripQg7Iir7J6Q6rCAIOyWtOq4i+uCnCDqsoPsnLzroZwg7J297Z6M64ukLlxuICBAYXBpKHsgaHR0cE1ldGhvZDogXCJHRVRcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1xdWVyeVwiXSB9KVxuICBhc3luYyB0b3RhbENvc3QoXG4gICAgcGFyYW1zPzogUmVxdWVzdExvZ0xpc3RQYXJhbXMsXG4gICk6IFByb21pc2U8eyB1c2Q6IG51bWJlcjsgdW5rbm93bkltYWdlQ29zdENvdW50OiBudW1iZXIgfT4ge1xuICAgIHJldHVybiBSZXF1ZXN0TG9nTW9kZWwudG90YWxDb3N0KHBhcmFtcyk7XG4gIH1cblxuICBAYXBpKHsgaHR0cE1ldGhvZDogXCJHRVRcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1xdWVyeVwiXSB9KVxuICBhc3luYyBwcm9qZWN0TmFtZXMoKTogUHJvbWlzZTx7IG5hbWVzOiBzdHJpbmdbXSB9PiB7XG4gICAgcmV0dXJuIHsgbmFtZXM6IGF3YWl0IFJlcXVlc3RMb2dNb2RlbC5kaXN0aW5jdFByb2plY3ROYW1lcygpIH07XG4gIH1cblxuICBAYXBpKHsgaHR0cE1ldGhvZDogXCJHRVRcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1xdWVyeVwiXSB9KVxuICBhc3luYyBtb2RlbE5hbWVzKCk6IFByb21pc2U8eyBuYW1lczogc3RyaW5nW10gfT4ge1xuICAgIHJldHVybiB7IG5hbWVzOiBhd2FpdCBSZXF1ZXN0TG9nTW9kZWwuZGlzdGluY3RNb2RlbE5hbWVzKCkgfTtcbiAgfVxuXG4gIEBhcGkoeyBodHRwTWV0aG9kOiBcIlBPU1RcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1tdXRhdGlvblwiXSB9KVxuICBhc3luYyBhZGRUb2tlbihcbiAgICBwcm92aWRlcjogc3RyaW5nLFxuICAgIGNyZWRlbnRpYWxzOiBUb2tlbkNyZWRlbnRpYWxzLFxuICAgIG5hbWU6IHN0cmluZyxcbiAgKTogUHJvbWlzZTx7IGFkZGVkOiBib29sZWFuIH0+IHtcbiAgICBhd2FpdCBUb2tlbk1vZGVsLnNhdmUoW1xuICAgICAge1xuICAgICAgICBwcm92aWRlcixcbiAgICAgICAgY3JlZGVudGlhbHMsXG4gICAgICAgIG5hbWUsXG4gICAgICB9LFxuICAgIF0pO1xuICAgIHJldHVybiB7IGFkZGVkOiB0cnVlIH07XG4gIH1cblxuICBAYXBpKHsgaHR0cE1ldGhvZDogXCJQT1NUXCIsIGNsaWVudHM6IFtcImF4aW9zXCJdIH0pXG4gIGFzeW5jIHVwZGF0ZVRva2VuKFxuICAgIGlkOiBudW1iZXIsXG4gICAgbmFtZT86IHN0cmluZyxcbiAgICBxdW90YVRocmVzaG9sZD86IG51bWJlciB8IG51bGwsXG4gICAgd2VpZ2h0PzogbnVtYmVyLFxuICAgIGtlZXBhbGl2ZUVuYWJsZWQ/OiBib29sZWFuLFxuICApOiBQcm9taXNlPHsgdXBkYXRlZDogYm9vbGVhbiB9PiB7XG4gICAgaWYgKFxuICAgICAgcXVvdGFUaHJlc2hvbGQgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgcXVvdGFUaHJlc2hvbGQgIT09IG51bGwgJiZcbiAgICAgICghTnVtYmVyLmlzSW50ZWdlcihxdW90YVRocmVzaG9sZCkgfHwgcXVvdGFUaHJlc2hvbGQgPCAxIHx8IHF1b3RhVGhyZXNob2xkID4gMTAwKVxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oXG4gICAgICAgIFwicXVvdGFUaHJlc2hvbGQgbXVzdCBiZSBhbiBpbnRlZ2VyIGJldHdlZW4gMSBhbmQgMTAwLCBvciBudWxsXCIgYXMgTG9jYWxpemVkU3RyaW5nLFxuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKHdlaWdodCAhPT0gdW5kZWZpbmVkICYmICghTnVtYmVyLmlzSW50ZWdlcih3ZWlnaHQpIHx8IHdlaWdodCA8IDEgfHwgd2VpZ2h0ID4gMTAwKSkge1xuICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oXG4gICAgICAgIFwid2VpZ2h0IG11c3QgYmUgYW4gaW50ZWdlciBiZXR3ZWVuIDEgYW5kIDEwMFwiIGFzIExvY2FsaXplZFN0cmluZyxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgcGF0Y2g6IFRva2VuVXBkYXRlRmllbGRzID0ge307XG4gICAgaWYgKG5hbWUgIT09IHVuZGVmaW5lZCkgcGF0Y2gubmFtZSA9IG5hbWU7XG4gICAgaWYgKHF1b3RhVGhyZXNob2xkICE9PSB1bmRlZmluZWQpIHBhdGNoLnF1b3RhX3RocmVzaG9sZCA9IHF1b3RhVGhyZXNob2xkO1xuICAgIGlmICh3ZWlnaHQgIT09IHVuZGVmaW5lZCkgcGF0Y2gud2VpZ2h0ID0gd2VpZ2h0O1xuICAgIGlmIChrZWVwYWxpdmVFbmFibGVkICE9PSB1bmRlZmluZWQpIHBhdGNoLmtlZXBhbGl2ZV9lbmFibGVkID0ga2VlcGFsaXZlRW5hYmxlZDtcbiAgICBpZiAoT2JqZWN0LmtleXMocGF0Y2gpLmxlbmd0aCA9PT0gMCkgcmV0dXJuIHsgdXBkYXRlZDogZmFsc2UgfTtcblxuICAgIGNvbnN0IHVwZGF0ZWQgPSBhd2FpdCBUb2tlbk1vZGVsLnVwZGF0ZUZpZWxkcyhpZCwgcGF0Y2gpO1xuICAgIHJldHVybiB7IHVwZGF0ZWQ6IHVwZGF0ZWQgPiAwIH07XG4gIH1cblxuICBAYXBpKHsgaHR0cE1ldGhvZDogXCJQT1NUXCIsIGNsaWVudHM6IFtcImF4aW9zXCIsIFwidGFuc3RhY2stbXV0YXRpb25cIl0gfSlcbiAgYXN5bmMgcmVtb3ZlVG9rZW4oaWQ6IG51bWJlcik6IFByb21pc2U8eyByZW1vdmVkOiBib29sZWFuIH0+IHtcbiAgICBjb25zdCBlbnRyeSA9IGF3YWl0IFRva2VuTW9kZWwuZmluZE9uZShcIkFcIiwgeyBpZCB9KTtcbiAgICBpZiAoIWVudHJ5KSByZXR1cm4geyByZW1vdmVkOiBmYWxzZSB9O1xuICAgIGF3YWl0IFRva2VuTW9kZWwuZGVsKFtlbnRyeS5pZF0pO1xuICAgIHJldHVybiB7IHJlbW92ZWQ6IHRydWUgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiDthqDtgbAg7Zmc7ISx7ZmUL+u5hO2ZnOyEse2ZlCDthqDquIAgRELsnZggYWN0aXZlIO2VhOuTnCDsl4XrjbDsnbTtirhcbiAgICovXG4gIEBhcGkoeyBodHRwTWV0aG9kOiBcIlBPU1RcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1tdXRhdGlvblwiXSB9KVxuICBhc3luYyB0b2dnbGVUb2tlbihpZDogbnVtYmVyKTogUHJvbWlzZTx7IGFjdGl2ZTogYm9vbGVhbiB9PiB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgVG9rZW5Nb2RlbC50b2dnbGVBY3RpdmUoaWQpO1xuICAgIGlmICghcmVzdWx0KSByZXR1cm4geyBhY3RpdmU6IGZhbHNlIH07XG4gICAgaWYgKHJlc3VsdC5yZWF1dGhSZXF1aXJlZCkge1xuICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oXCJSZS1sb2dpbiByZXF1aXJlZFwiIGFzIExvY2FsaXplZFN0cmluZyk7XG4gICAgfVxuICAgIHJldHVybiB7IGFjdGl2ZTogcmVzdWx0LmFjdGl2ZSB9O1xuICB9XG5cbiAgQGFwaSh7IGh0dHBNZXRob2Q6IFwiUE9TVFwiLCBjbGllbnRzOiBbXCJheGlvc1wiLCBcInRhbnN0YWNrLW11dGF0aW9uXCJdIH0pXG4gIGFzeW5jIG9hdXRoU3RhcnQobmFtZTogc3RyaW5nKTogUHJvbWlzZTxPQXV0aFN0YXJ0UmVzdWx0PiB7XG4gICAgY29uc3QgeyBjb2RlVmVyaWZpZXIsIGNvZGVDaGFsbGVuZ2UsIHN0YXRlIH0gPSBnZW5lcmF0ZVBLQ0UoKTtcblxuICAgIGNvbnN0IHsgcmVkaXJlY3RVcmksIG1vZGUgfSA9IHJlc29sdmVPQXV0aFJlZGlyZWN0KCk7XG4gICAgY29uc3QgYXV0aFVybCA9IGJ1aWxkQXV0aFVybChjb2RlQ2hhbGxlbmdlLCBzdGF0ZSwgcmVkaXJlY3RVcmkpO1xuXG4gICAgYXdhaXQgc2V0T0F1dGhTdGF0ZShzdGF0ZSwgeyBjb2RlVmVyaWZpZXIsIG5hbWUsIHJlZGlyZWN0VXJpLCBwcm92aWRlcjogXCJhbnRocm9waWNcIiB9KTtcblxuICAgIHJldHVybiB7IGF1dGhVcmwsIG1vZGUgfTtcbiAgfVxuXG4gIC8vIOybkOqyqSDsoJHsho3snZgg7IiY64+ZIOyZhOujjDogQW50aHJvcGljIGBjb2RlI3N0YXRlYCDrmJDripQgT3BlbkFJIGNhbGxiYWNrIFVSTOydhCDrsJvslYQg6rWQ7ZmY7ZWc64ukLlxuICBAYXBpKHsgaHR0cE1ldGhvZDogXCJQT1NUXCIsIGNsaWVudHM6IFtcImF4aW9zXCIsIFwidGFuc3RhY2stbXV0YXRpb25cIl0gfSlcbiAgYXN5bmMgb2F1dGhDb21wbGV0ZShwYXN0ZWRDb2RlOiBzdHJpbmcpOiBQcm9taXNlPHsgYWRkZWQ6IGJvb2xlYW47IG5hbWU6IHN0cmluZyB9PiB7XG4gICAgY29uc3QgcmVzdWx0ID0gcGFyc2VQYXN0ZWRPQXV0aFJlc3VsdChwYXN0ZWRDb2RlKTtcbiAgICBpZiAoIXJlc3VsdCkge1xuICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oXG4gICAgICAgIFwiZXhwZWN0ZWQgdGhlIGNhbGxiYWNrIFVSTCBvciBjb2RlIHNob3duIGFmdGVyIGxvZ2luLCBpbiBjb2RlI3N0YXRlIGZvcm1cIiBhcyBMb2NhbGl6ZWRTdHJpbmcsXG4gICAgICApO1xuICAgIH1cbiAgICBjb25zdCB7IGNvZGUsIHN0YXRlIH0gPSByZXN1bHQ7XG5cbiAgICBjb25zdCBwZW5kaW5nID0gYXdhaXQgZ2V0T0F1dGhTdGF0ZShzdGF0ZSk7XG4gICAgaWYgKCFwZW5kaW5nKSB7XG4gICAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihcbiAgICAgICAgXCJsb2dpbiBzZXNzaW9uIG5vdCBmb3VuZCBvciBleHBpcmVkIOKAlCBzdGFydCB0aGUgbG9naW4gYWdhaW5cIiBhcyBMb2NhbGl6ZWRTdHJpbmcsXG4gICAgICApO1xuICAgIH1cbiAgICBhd2FpdCBkZWxldGVPQXV0aFN0YXRlKHN0YXRlKTtcblxuICAgIGlmIChwZW5kaW5nLnByb3ZpZGVyID09PSBcIm9wZW5haVwiKSB7XG4gICAgICBhd2FpdCB0aGlzLmNvbXBsZXRlT3BlbkFJTG9naW4oY29kZSwgcGVuZGluZyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGF3YWl0IHRoaXMuY29tcGxldGVBbnRocm9waWNMb2dpbihjb2RlLCBzdGF0ZSwgcGVuZGluZyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgYWRkZWQ6IHRydWUsIG5hbWU6IHBlbmRpbmcubmFtZSB9O1xuICB9XG5cbiAgLy8g6rWQ7ZmYICsg6rOE7KCVIOykkeuztSDsoJzqsbAgKyDsoIDsnqUg4oCUIHJlZGlyZWN0IOy9nOuwseqzvCDsvZTrk5wg67aZ7Jes64Sj6riwIO2UjOuhnOyasOqwgCDqs7XsnKDtlZzri6QuXG4gIGFzeW5jIGNvbXBsZXRlQW50aHJvcGljTG9naW4oY29kZTogc3RyaW5nLCBzdGF0ZTogc3RyaW5nLCBwZW5kaW5nOiBQZW5kaW5nT0F1dGgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB0b2tlbnMgPSBhd2FpdCBleGNoYW5nZUNvZGVGb3JUb2tlbnMoXG4gICAgICBjb2RlLFxuICAgICAgcGVuZGluZy5jb2RlVmVyaWZpZXIsXG4gICAgICBzdGF0ZSxcbiAgICAgIHBlbmRpbmcucmVkaXJlY3RVcmksXG4gICAgKTtcblxuICAgIGF3YWl0IFRva2VuTW9kZWwucmVwbGFjZUJ5QWNjb3VudChcImFudGhyb3BpY1wiLCB0b2tlbnMuYWNjb3VudFV1aWQsIHtcbiAgICAgIHByb3ZpZGVyOiBcImFudGhyb3BpY1wiLFxuICAgICAgY3JlZGVudGlhbHM6IHtcbiAgICAgICAgYWNjZXNzVG9rZW46IHRva2Vucy5hY2Nlc3NUb2tlbixcbiAgICAgICAgcmVmcmVzaFRva2VuOiB0b2tlbnMucmVmcmVzaFRva2VuLFxuICAgICAgICBleHBpcmVzQXQ6IHRva2Vucy5leHBpcmVzQXQgPz8gMCxcbiAgICAgICAgYWNjb3VudFV1aWQ6IHRva2Vucy5hY2NvdW50VXVpZCA/PyBcIlwiLFxuICAgICAgfSxcbiAgICAgIG5hbWU6IHBlbmRpbmcubmFtZSxcbiAgICB9KTtcblxuICAgIG5vdGlmeVRva2VuQWRkZWQocGVuZGluZy5uYW1lLCBcImFudGhyb3BpY1wiKTtcbiAgfVxuXG4gIGFzeW5jIGNvbXBsZXRlT3BlbkFJTG9naW4oY29kZTogc3RyaW5nLCBwZW5kaW5nOiBQZW5kaW5nT0F1dGgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBjcmVkcyA9IGF3YWl0IGV4Y2hhbmdlT3BlbkFJQ29kZShjb2RlLCBwZW5kaW5nLmNvZGVWZXJpZmllciwgcGVuZGluZy5yZWRpcmVjdFVyaSk7XG4gICAgYXdhaXQgVG9rZW5Nb2RlbC5yZXBsYWNlQnlBY2NvdW50KFwib3BlbmFpXCIsIGNyZWRzLmFjY291bnRJZCwge1xuICAgICAgcHJvdmlkZXI6IFwib3BlbmFpXCIsXG4gICAgICBjcmVkZW50aWFsczogY3JlZHMsXG4gICAgICBuYW1lOiBwZW5kaW5nLm5hbWUsXG4gICAgfSk7XG4gICAgbG9nZ2VyLmluZm8oYE9wZW5BSSB0b2tlbiBzYXZlZCBmb3IgJHtwZW5kaW5nLm5hbWV9YCk7XG4gICAgbm90aWZ5VG9rZW5BZGRlZChwZW5kaW5nLm5hbWUsIFwib3BlbmFpXCIpO1xuICB9XG5cbiAgYXN5bmMgaGFuZGxlT0F1dGhDYWxsYmFjayhjb2RlOiBzdHJpbmcsIHN0YXRlOiBzdHJpbmcsIHJlcGx5OiBGYXN0aWZ5UmVwbHkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBwZW5kaW5nID0gYXdhaXQgZ2V0T0F1dGhTdGF0ZShzdGF0ZSk7XG4gICAgaWYgKCFwZW5kaW5nKSB7XG4gICAgICBsb2dnZXIud2FybihcIm9hdXRoIGNhbGxiYWNrOiBpbnZhbGlkX3N0YXRlXCIpO1xuICAgICAgcmV0dXJuIHJlcGx5LnJlZGlyZWN0KFwiLz9vYXV0aD1lcnJvciZyZWFzb249aW52YWxpZF9zdGF0ZVwiKTtcbiAgICB9XG4gICAgYXdhaXQgZGVsZXRlT0F1dGhTdGF0ZShzdGF0ZSk7XG5cbiAgICB0cnkge1xuICAgICAgaWYgKHBlbmRpbmcucHJvdmlkZXIgPT09IFwib3BlbmFpXCIpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5jb21wbGV0ZU9wZW5BSUxvZ2luKGNvZGUsIHBlbmRpbmcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXdhaXQgdGhpcy5jb21wbGV0ZUFudGhyb3BpY0xvZ2luKGNvZGUsIHN0YXRlLCBwZW5kaW5nKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXBseS5yZWRpcmVjdChgLz9vYXV0aD1zdWNjZXNzJm5hbWU9JHtlbmNvZGVVUklDb21wb25lbnQocGVuZGluZy5uYW1lKX1gKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIGxvZ2dlci53YXJuKFwib2F1dGggY2FsbGJhY2sgZmFpbGVkXCIsIHtcbiAgICAgICAgcHJvdmlkZXI6IHBlbmRpbmcucHJvdmlkZXIsXG4gICAgICAgIHJlYXNvbjogXCJleGNoYW5nZV9mYWlsZWRcIixcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlcGx5LnJlZGlyZWN0KFwiLz9vYXV0aD1lcnJvciZyZWFzb249ZXhjaGFuZ2VfZmFpbGVkXCIpO1xuICAgIH1cbiAgfVxuXG4gIEBhcGkoeyBodHRwTWV0aG9kOiBcIlBPU1RcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1tdXRhdGlvblwiXSB9KVxuICBhc3luYyBvYXV0aFN0YXJ0T3BlbkFJKG5hbWU6IHN0cmluZyk6IFByb21pc2U8T0F1dGhTdGFydFJlc3VsdD4ge1xuICAgIGNvbnN0IHsgY29kZVZlcmlmaWVyLCBjb2RlQ2hhbGxlbmdlLCBzdGF0ZSB9ID0gZ2VuZXJhdGVPcGVuQUlQS0NFKCk7XG4gICAgY29uc3QgbW9kZSA9IGlzUmVtb3RlT0F1dGhSZXF1ZXN0KCkgPyBcImNvZGVcIiA6IFwicmVkaXJlY3RcIjtcbiAgICBsZXQgcmVkaXJlY3RVcmk6IHN0cmluZztcbiAgICBpZiAobW9kZSA9PT0gXCJjb2RlXCIpIHtcbiAgICAgIC8vIE9wZW5BSSBhY2NlcHRzIG9ubHkgdGhlIENvZGV4IENMSSdzIHJlZ2lzdGVyZWQgbG9vcGJhY2sgVVJJLiBPbiBhIHJlbW90ZSBkYXNoYm9hcmQgdGhlXG4gICAgICAvLyBicm93c2VyIGNhbm5vdCByZWFjaCB0aGUgc2VydmVyJ3MgbG9vcGJhY2ssIHNvIHRoZSB1c2VyIHBhc3RlcyB0aGUgcmVzdWx0aW5nIGNhbGxiYWNrIFVSTC5cbiAgICAgIHJlZGlyZWN0VXJpID0gb3BlbkFJQ2FsbGJhY2tSZWRpcmVjdFVyaShPUEVOQUlfQ0FMTEJBQ0tfUE9SVFNbMF0pO1xuICAgIH0gZWxzZSB7XG4gICAgICB0cnkge1xuICAgICAgICByZWRpcmVjdFVyaSA9IGF3YWl0IHN0YXJ0T3BlbkFJQ2FsbGJhY2tSZWxheSh0cnVzdGVkTG9vcGJhY2tCYXNlKCksIE9BVVRIX1NUQVRFX1RUTF9NUyk7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oXG4gICAgICAgICAgYE9wZW5BSSBsb2dpbiBuZWVkcyBsb2NhbCBwb3J0ICR7T1BFTkFJX0NBTExCQUNLX1BPUlRTLmpvaW4oXCIgb3IgXCIpfSDigJQgY2xvc2UgYW55IHJ1bm5pbmcgXFxgY29kZXggbG9naW5cXGAgYW5kIHJldHJ5YCBhcyBMb2NhbGl6ZWRTdHJpbmcsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICAgIGNvbnN0IGF1dGhVcmwgPSBidWlsZE9wZW5BSUF1dGhVcmwoY29kZUNoYWxsZW5nZSwgc3RhdGUsIHJlZGlyZWN0VXJpKTtcbiAgICBhd2FpdCBzZXRPQXV0aFN0YXRlKHN0YXRlLCB7IGNvZGVWZXJpZmllciwgbmFtZSwgcmVkaXJlY3RVcmksIHByb3ZpZGVyOiBcIm9wZW5haVwiIH0pO1xuICAgIHJldHVybiB7IGF1dGhVcmwsIG1vZGUgfTtcbiAgfVxuXG4gIEBhcGkoeyBodHRwTWV0aG9kOiBcIkdFVFwiLCBjbGllbnRzOiBbXCJheGlvc1wiLCBcInRhbnN0YWNrLXF1ZXJ5XCJdIH0pXG4gIGFzeW5jIHVzYWdlKHRva2VuSWQ/OiBudW1iZXIpOiBQcm9taXNlPFVzYWdlUmVzcG9uc2U+IHtcbiAgICBjb25zdCB7IHJvd3M6IGFsbFRva2VucyB9ID0gYXdhaXQgVG9rZW5Nb2RlbC5maW5kTWFueShcIkFcIik7XG4gICAgY29uc3QgZW50cnkgPSB0b2tlbklkXG4gICAgICA/IGFsbFRva2Vucy5maW5kKChlKSA9PiBlLmlkID09PSB0b2tlbklkKVxuICAgICAgOiBhbGxUb2tlbnMuZmluZExhc3QoKGUpID0+IGUuYWN0aXZlICYmIGUucHJvdmlkZXIgPT09IFwiYW50aHJvcGljXCIpO1xuXG4gICAgaWYgKCFlbnRyeSkgcmV0dXJuIHsgZXJyb3I6IFwiTk9UX0ZPVU5EXCIgfTtcbiAgICBpZiAoZW50cnkucmVhdXRoX3JlcXVpcmVkKSByZXR1cm4geyBlcnJvcjogXCJyZS1sb2dpbiByZXF1aXJlZFwiIH07XG5cbiAgICBpZiAoZW50cnkucHJvdmlkZXIgPT09IFwib3BlbmFpXCIpIHtcbiAgICAgIGlmICghZW50cnkuYWN0aXZlKSB7XG4gICAgICAgIHJldHVybiB7IHByb3ZpZGVyOiBcIm9wZW5haVwiLCBmaXZlSG91cjogbnVsbCwgc2V2ZW5EYXk6IG51bGwgfTtcbiAgICAgIH1cblxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmF3ID0gYXdhaXQgUWdyaWREaXNwYXRjaGVyLm9wZW5haURpc3BhdGNoZXI/LmdldFJhdGVMaW1pdHNCeVRva2VuSWQoZW50cnkuaWQpO1xuICAgICAgICBjb25zdCBybCA9IHJhdz8uZGF0YS5yYXRlTGltaXRzO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHByb3ZpZGVyOiBcIm9wZW5haVwiLFxuICAgICAgICAgIGZpdmVIb3VyOiBybD8ucHJpbWFyeVxuICAgICAgICAgICAgPyB7XG4gICAgICAgICAgICAgICAgdXRpbGl6YXRpb246IHJsLnByaW1hcnkudXNlZFBlcmNlbnQsXG4gICAgICAgICAgICAgICAgcmVzZXRzQXQ6IHVuaXhTZWNvbmRzVG9Jc28ocmwucHJpbWFyeS5yZXNldHNBdCksXG4gICAgICAgICAgICAgICAgd2luZG93RHVyYXRpb25NaW5zOiBybC5wcmltYXJ5LndpbmRvd0R1cmF0aW9uTWlucyxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgOiBudWxsLFxuICAgICAgICAgIHNldmVuRGF5OiBybD8uc2Vjb25kYXJ5XG4gICAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgICB1dGlsaXphdGlvbjogcmwuc2Vjb25kYXJ5LnVzZWRQZXJjZW50LFxuICAgICAgICAgICAgICAgIHJlc2V0c0F0OiB1bml4U2Vjb25kc1RvSXNvKHJsLnNlY29uZGFyeS5yZXNldHNBdCksXG4gICAgICAgICAgICAgICAgd2luZG93RHVyYXRpb25NaW5zOiBybC5zZWNvbmRhcnkud2luZG93RHVyYXRpb25NaW5zLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICA6IG51bGwsXG4gICAgICAgIH07XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHJldHVybiB7IGVycm9yOiBgT3BlbkFJIHVzYWdlIGZhaWxlZDogJHsoZSBhcyBFcnJvcikubWVzc2FnZX1gIH07XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGVudHJ5LnByb3ZpZGVyICE9PSBcImFudGhyb3BpY1wiKSB7XG4gICAgICByZXR1cm4geyBlcnJvcjogYHVzYWdlIEFQSSBub3Qgc3VwcG9ydGVkIGZvciBwcm92aWRlcjogJHtlbnRyeS5wcm92aWRlcn1gIH07XG4gICAgfVxuXG4gICAgbGV0IGFjY2Vzc1Rva2VuID0gZ2V0QWNjZXNzVG9rZW4oZW50cnkuY3JlZGVudGlhbHMpO1xuICAgIGNvbnN0IGlzRXhwaXJlZCA9IGdldEV4cGlyZXNBdChlbnRyeS5jcmVkZW50aWFscykgPCBEYXRlLm5vdygpO1xuXG4gICAgaWYgKGlzRXhwaXJlZCAmJiBnZXRSZWZyZXNoVG9rZW4oZW50cnkuY3JlZGVudGlhbHMpKSB7XG4gICAgICB0cnkge1xuICAgICAgICBhY2Nlc3NUb2tlbiA9IGF3YWl0IHRoaXMucmVmcmVzaFRva2VuKGVudHJ5KTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgb2F1dGhMb2dnZXIud2FybihgcmVmcmVzaCBmYWlsZWQgZm9yICR7ZW50cnkubmFtZX06ICR7KGUgYXMgRXJyb3IpLm1lc3NhZ2V9YCk7XG4gICAgICAgIHJldHVybiB7IGVycm9yOiBcIlRva2VuIHJlZnJlc2ggZmFpbGVkOyB1c2FnZSBpcyB1bmF2YWlsYWJsZVwiIH07XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgcmF3ID0gYXdhaXQgZmV0Y2hVc2FnZShhY2Nlc3NUb2tlbik7XG4gICAgaWYgKHJhdy5lcnJvciAmJiBnZXRSZWZyZXNoVG9rZW4oZW50cnkuY3JlZGVudGlhbHMpKSB7XG4gICAgICB0cnkge1xuICAgICAgICBhY2Nlc3NUb2tlbiA9IGF3YWl0IHRoaXMucmVmcmVzaFRva2VuKGVudHJ5KTtcbiAgICAgICAgY29uc3QgcmV0cmllZCA9IGF3YWl0IGZldGNoVXNhZ2UoYWNjZXNzVG9rZW4pO1xuICAgICAgICBpZiAocmV0cmllZC5lcnJvcikgcmV0dXJuIHsgZXJyb3I6IHJldHJpZWQuZXJyb3IgfTtcbiAgICAgICAgcmV0dXJuIGNvbnZlcnRBbnRocm9waWNVc2FnZShyZXRyaWVkKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgb2F1dGhMb2dnZXIud2FybihgcmVmcmVzaCBmYWlsZWQgZm9yICR7ZW50cnkubmFtZX06ICR7KGUgYXMgRXJyb3IpLm1lc3NhZ2V9YCk7XG4gICAgICAgIHJldHVybiB7IGVycm9yOiBcIlRva2VuIHJlZnJlc2ggZmFpbGVkOyB1c2FnZSBpcyB1bmF2YWlsYWJsZVwiIH07XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChyYXcuZXJyb3IpIHJldHVybiB7IGVycm9yOiByYXcuZXJyb3IgfTtcbiAgICByZXR1cm4gY29udmVydEFudGhyb3BpY1VzYWdlKHJhdyk7XG4gIH1cblxuICAvLyDrj5nsi5wgcmVmcmVzaCDqsIAg7ZqM7KCE7J2EIOqyuey5mOuptCDrkqTriqbsnYAg7Zi47Lac7J20IOydtOuvuCDtj5DquLDrkJwgcmVmcmVzaCB0b2tlbiDsnYQg7JOw6rKMIOuQmOyWtFxuICAvLyDrqYDsqaHtlZwg7Yag7YGw7J20IOyCrOunneycvOuhnCDsmKTtjJDrkJzri6QuIG9wZW5haS1yZWZyZXNoLnRzIOyZgCDqsJnsnYAgcGVyLXRva2VuIGRlZHVwIOydhCDrkZTri6QuXG4gIGFzeW5jIHJlZnJlc2hUb2tlbih0b2tlbjogVG9rZW5TdWJzZXRBKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBpbmZsaWdodCA9IGluZmxpZ2h0QW50aHJvcGljUmVmcmVzaC5nZXQodG9rZW4uaWQpO1xuICAgIGlmIChpbmZsaWdodCkgcmV0dXJuIGluZmxpZ2h0O1xuXG4gICAgY29uc3QgcHJvbWlzZSA9IHRoaXMuZG9SZWZyZXNoVG9rZW4odG9rZW4pO1xuICAgIGluZmxpZ2h0QW50aHJvcGljUmVmcmVzaC5zZXQodG9rZW4uaWQsIHByb21pc2UpO1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgcHJvbWlzZTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgaW5mbGlnaHRBbnRocm9waWNSZWZyZXNoLmRlbGV0ZSh0b2tlbi5pZCk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgZG9SZWZyZXNoVG9rZW4odG9rZW46IFRva2VuU3Vic2V0QSk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgY3JlZHMgPSB0b2tlbi5jcmVkZW50aWFscztcbiAgICBjb25zdCBydCA9IGdldFJlZnJlc2hUb2tlbihjcmVkcyk7XG4gICAgaWYgKCFydCkgdGhyb3cgbmV3IEVycm9yKFwiTm8gcmVmcmVzaCB0b2tlblwiKTtcblxuICAgIGxldCByZWZyZXNoZWQ7XG4gICAgdHJ5IHtcbiAgICAgIHJlZnJlc2hlZCA9IGF3YWl0IHJlZnJlc2hBY2Nlc3NUb2tlbihydCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKGUgaW5zdGFuY2VvZiBSZWZyZXNoRmFpbGVkRXJyb3IgJiYgZS5pc0F1dGhEZWFkKCkpIHtcbiAgICAgICAgYXdhaXQgZGVhY3RpdmF0ZUF1dGhEZWFkVG9rZW4odG9rZW4sIGBhbnRocm9waWM6JHtlLnN0YXR1c31gKTtcbiAgICAgIH1cbiAgICAgIHRocm93IGU7XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlZCA9IFRva2VuQ3JlZGVudGlhbHMucGFyc2Uoe1xuICAgICAgLi4uY3JlZHMsXG4gICAgICBhY2Nlc3NUb2tlbjogcmVmcmVzaGVkLmFjY2Vzc1Rva2VuLFxuICAgICAgcmVmcmVzaFRva2VuOiByZWZyZXNoZWQucmVmcmVzaFRva2VuLFxuICAgICAgZXhwaXJlc0F0OiByZWZyZXNoZWQuZXhwaXJlc0F0LFxuICAgIH0pO1xuICAgIGF3YWl0IFRva2VuTW9kZWwuc2F2ZShbXG4gICAgICB7XG4gICAgICAgIGlkOiB0b2tlbi5pZCxcbiAgICAgICAgcHJvdmlkZXI6IHRva2VuLnByb3ZpZGVyLFxuICAgICAgICBjcmVkZW50aWFsczogdXBkYXRlZCxcbiAgICAgICAgbmFtZTogdG9rZW4ubmFtZSxcbiAgICAgICAgcmVhdXRoX3JlcXVpcmVkOiBmYWxzZSxcbiAgICAgIH0sXG4gICAgXSk7XG4gICAgcmV0dXJuIHJlZnJlc2hlZC5hY2Nlc3NUb2tlbjtcbiAgfVxuXG4gIEBhcGkoeyBodHRwTWV0aG9kOiBcIkdFVFwiLCBjbGllbnRzOiBbXCJheGlvc1wiLCBcInRhbnN0YWNrLXF1ZXJ5XCJdIH0pXG4gIGFzeW5jIGhlYWx0aCgpOiBQcm9taXNlPEhlYWx0aFJlc3BvbnNlPiB7XG4gICAgY29uc3QgcHJvdmlkZXJzID0geyAuLi5RZ3JpZERpc3BhdGNoZXIuc3RhcnR1cFN0YXRlIH07XG4gICAgcmV0dXJuIHtcbiAgICAgIHN0YXR1czogXCJva1wiLFxuICAgICAgYWN0aXZlVG9rZW5zOiBRZ3JpZERpc3BhdGNoZXIudG9rZW5zLnNpemUsXG4gICAgICBzdWJzY3JpYmVyOiBRZ3JpZERpc3BhdGNoZXIuc3Vic2NyaWJlcj8uc3RhdHVzKCkgPz8gbnVsbCxcbiAgICAgIC8vIHByb3ZpZGVyIOuzhCDrnbzsmrDtjIXsnbTrnbwg7ZWY64KY66eMIOykgOu5hOuPvOuPhCDqt7ggcHJvdmlkZXIg7JqU7LKt7J2AIOyymOumrOuQnOuLpC5cbiAgICAgIHJlYWR5OiBPYmplY3QudmFsdWVzKHByb3ZpZGVycykuaW5jbHVkZXMoXCJyZWFkeVwiKSxcbiAgICAgIHByb3ZpZGVycyxcbiAgICB9O1xuICB9XG59XG5cbmV4cG9ydCBjb25zdCBRZ3JpZEZyYW1lID0gbmV3IFFncmlkRnJhbWVDbGFzcygpO1xuXG5mdW5jdGlvbiBjb252ZXJ0QW50aHJvcGljVXNhZ2UocmF3OiBBbnRocm9waWNVc2FnZVJhdyk6IFVzYWdlUmVzcG9uc2Uge1xuICByZXR1cm4ge1xuICAgIHByb3ZpZGVyOiBcImFudGhyb3BpY1wiLFxuICAgIGZpdmVIb3VyOiByYXcuZml2ZV9ob3VyXG4gICAgICA/IHsgdXRpbGl6YXRpb246IHJhdy5maXZlX2hvdXIudXRpbGl6YXRpb24sIHJlc2V0c0F0OiByYXcuZml2ZV9ob3VyLnJlc2V0c19hdCB9XG4gICAgICA6IG51bGwsXG4gICAgc2V2ZW5EYXk6IHJhdy5zZXZlbl9kYXlcbiAgICAgID8geyB1dGlsaXphdGlvbjogcmF3LnNldmVuX2RheS51dGlsaXphdGlvbiwgcmVzZXRzQXQ6IHJhdy5zZXZlbl9kYXkucmVzZXRzX2F0IH1cbiAgICAgIDogbnVsbCxcbiAgfTtcbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBb0VBLE1BQU0saUNBQWlCLElBQUksSUFBd0I7QUFRbkQsTUFBTSxxQkFBcUI7QUFDM0IsTUFBTSxrQkFBa0I7QUFDeEIsTUFBTSxxQkFBcUIsSUFBSTtBQUUvQixTQUFTLGlCQUFpQixTQUFtRDtDQUMzRSxPQUFPLE9BQU8sWUFBWSw0QkFBVyxJQUFJLEtBQUssVUFBVSxHQUFJLEVBQUMsQ0FBQyxZQUFZLElBQUk7QUFDaEY7QUFFQSxlQUFlLGNBQWMs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
1675
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicWdyaWQuZnJhbWUuanMiLCJuYW1lcyI6WyJTdHJpY3RHcm9rQ3JlZGVudGlhbHMiLCJTdG9yZWRHcm9rQ3JlZGVudGlhbHMiXSwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBwbGljYXRpb24vcWdyaWQvcWdyaWQuZnJhbWUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGNyeXB0byBmcm9tIFwibm9kZTpjcnlwdG9cIjtcblxuaW1wb3J0IHsgZ2V0TG9nZ2VyIH0gZnJvbSBcIkBsb2d0YXBlL2xvZ3RhcGVcIjtcbmltcG9ydCB7IHR5cGUgRmFzdGlmeVJlcGx5LCB0eXBlIEZhc3RpZnlSZXF1ZXN0IH0gZnJvbSBcImZhc3RpZnlcIjtcbmltcG9ydCB7XG4gIGFwaSxcbiAgQmFkUmVxdWVzdEV4Y2VwdGlvbixcbiAgQmFzZUZyYW1lQ2xhc3MsXG4gIEludGVybmFsU2VydmVyRXJyb3JFeGNlcHRpb24sXG4gIE5vdEZvdW5kRXhjZXB0aW9uLFxuICBTZXJ2aWNlVW5hdmFpbGFibGVFeGNlcHRpb24sXG4gIFNvRXhjZXB0aW9uLFxuICBTb25hbXUsXG4gIHN0cmVhbSxcbn0gZnJvbSBcInNvbmFtdVwiO1xuaW1wb3J0IHsgZ2V0Q2FjaGVNYW5hZ2VyUmVmIH0gZnJvbSBcInNvbmFtdS9jYWNoZVwiO1xuaW1wb3J0IHsgeiB9IGZyb20gXCJ6b2RcIjtcblxuaW1wb3J0IHsgdHlwZSBMb2NhbGl6ZWRTdHJpbmcsIFNEIH0gZnJvbSBcIi4uLy4uL2kxOG4vc2QuZ2VuZXJhdGVkXCI7XG5pbXBvcnQge1xuICBnZXRBY2Nlc3NUb2tlbixcbiAgZ2V0RXhwaXJlc0F0LFxuICBnZXRSZWZyZXNoVG9rZW4sXG59IGZyb20gXCIuLi8uLi91dGlscy9wcm92aWRlcnMvY29tbW9uL2NyZWRlbnRpYWxzXCI7XG5pbXBvcnQge1xuICB0eXBlIEdyb2tNZWRpYUNvc3QsXG4gIGdyb2tJbWFnZUNvc3QsXG4gIGdyb2tSZXBvcnRlZENvc3QsXG59IGZyb20gXCIuLi8uLi91dGlscy9wcm92aWRlcnMvY29tbW9uL21vZGVsLWNvc3RcIjtcbmltcG9ydCB7XG4gIHR5cGUgTWVkaWFEaXNwYXRjaGVyLFxuICB0eXBlIE1lZGlhVG9rZW5TZWxlY3Rpb24sXG4gIHR5cGUgVm9pY2VEaXNwYXRjaGVyLFxufSBmcm9tIFwiLi4vLi4vdXRpbHMvcHJvdmlkZXJzL2NvbW1vbi9wcm92aWRlci1kaXNwYXRjaGVyXCI7XG5pbXBvcnQgeyBpc1Byb3ZpZGVySWQgfSBmcm9tIFwiLi4vLi4vdXRpbHMvcHJvdmlkZXJzL2NvbW1vbi9wcm92aWRlci10eXBlc1wiO1xuaW1wb3J0IHsgQ2FsbGVyU2NoZW1hVmFsaWRhdGlvbkVycm9yIH0gZnJvbSBcIi4uLy4uL3V0aWxzL3Byb3ZpZGVycy9jb21tb24vc2NoZW1hLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7XG4gIEdST0tfSU1BR0VfREVGQVVMVF9NT0RFTCxcbiAgR1JPS19TVFRfREVGQVVMVF9NT0RFTCxcbiAgR1JPS19WSURFT19ERUZBVUxUX01PREVMLFxuICBHcm9rQ2FwYWJpbGl0eVVuYXZhaWxhYmxlRXJyb3IsXG4gIEdyb2tDYXBhY2l0eUVycm9yLFxuICBHcm9rSW52YWxpZFJlcXVlc3RFcnJvcixcbiAgR3Jva05vV29ya2Vyc0Vycm9yLFxuICBHcm9rT25EZW1hbmRFeGNsdWRlZEVycm9yLFxuICBHcm9rUmF0ZUxpbWl0ZWRFcnJvcixcbiAgR3Jva1pkclZpZGVvVW5hdmFpbGFibGVFcnJvcixcbiAgY29tcGxldGVHcm9rT0F1dGgsXG4gIEdyb2tDcmVkZW50aWFscyBhcyBTdHJpY3RHcm9rQ3JlZGVudGlhbHMsXG4gIEdyb2tPQXV0aEVycm9yLFxuICB0eXBlIEdyb2tSZWZyZXNoQ29vcmRpbmF0b3IsXG4gIHR5cGUgR3Jva1Rva2VuU3RhdGVTbmFwc2hvdCxcbiAgcG9sbEdyb2tEZXZpY2VDb2RlLFxuICBzdGFydEdyb2tEZXZpY2VDb2RlLFxuICBzdGFydEdyb2tPQXV0aCxcbn0gZnJvbSBcIi4uLy4uL3V0aWxzL3Byb3ZpZGVycy9ncm9rXCI7XG5pbXBvcnQge1xuICBkZWNvZGVHcm9rSW1hZ2VzLFxuICBHcm9rQ29udGVudFBvbGljeUVycm9yLFxuICBzdW1tYXJpemVHcm9rVmlkZW9TdGF0dXMsXG59IGZyb20gXCIuLi8uLi91dGlscy9wcm92aWRlcnMvZ3Jvay9ncm9rLW1lZGlhLWNsaWVudFwiO1xuaW1wb3J0IHtcbiAgR1JPS19UVFNfREVGQVVMVF9GT1JNQVQsXG4gIEdST0tfVFRTX0RFRkFVTFRfTEFOR1VBR0UsXG4gIEdST0tfVFRTX0RFRkFVTFRfVk9JQ0UsXG59IGZyb20gXCIuLi8uLi91dGlscy9wcm92aWRlcnMvZ3Jvay9ncm9rLXZvaWNlLWNsaWVudFwiO1xuaW1wb3J0IHtcbiAgT1BFTkFJX0NBTExCQUNLX1BPUlRTLFxuICBvcGVuQUlDYWxsYmFja1JlZGlyZWN0VXJpLFxuICBzdGFydE9wZW5BSUNhbGxiYWNrUmVsYXksXG59IGZyb20gXCIuLi8uLi91dGlscy9wcm92aWRlcnMvb3BlbmFpL29wZW5haS1jYWxsYmFjay1yZWxheVwiO1xuaW1wb3J0IHtcbiAgYnVpbGRPcGVuQUlBdXRoVXJsLFxuICBleGNoYW5nZU9wZW5BSUNvZGUsXG4gIGdlbmVyYXRlT3BlbkFJUEtDRSxcbn0gZnJvbSBcIi4uLy4uL3V0aWxzL3Byb3ZpZGVycy9vcGVuYWkvb3BlbmFpLW9hdXRoXCI7XG5pbXBvcnQge1xuICB0eXBlIEZpbmlzaFJ1blBhcmFtcyxcbiAgTUlDUk9fVVNELFxuICBSZXF1ZXN0TG9nTW9kZWwsXG4gIHR5cGUgUmVxdWVzdExvZ1N0ZXBGaWVsZHMsXG59IGZyb20gXCIuLi9yZXF1ZXN0LWxvZy9yZXF1ZXN0LWxvZy5tb2RlbFwiO1xuaW1wb3J0IHsgdHlwZSBSZXF1ZXN0TG9nTGlzdFBhcmFtcyB9IGZyb20gXCIuLi9yZXF1ZXN0LWxvZy9yZXF1ZXN0LWxvZy50eXBlc1wiO1xuaW1wb3J0IHsgdHlwZSBUb2tlblN1YnNldEEgfSBmcm9tIFwiLi4vc29uYW11LmdlbmVyYXRlZFwiO1xuXG4vKiogRmllbGRzIHRva2VuIHJlZnJlc2ggcmVhZHM7IGRpc3BhdGNoZXJzIHBhc3MgdGhlaXIgcG9vbGVkIHZpZXcgb2YgYSB0b2tlbi4gKi9cbnR5cGUgUmVmcmVzaGFibGVUb2tlbiA9IFBpY2s8VG9rZW5TdWJzZXRBLCBcImlkXCIgfCBcIm5hbWVcIiB8IFwicHJvdmlkZXJcIiB8IFwiY3JlZGVudGlhbHNcIj47XG5cbmltcG9ydCB7IFRva2VuTW9kZWwsIHR5cGUgVG9rZW5VcGRhdGVGaWVsZHMgfSBmcm9tIFwiLi4vdG9rZW4vdG9rZW4ubW9kZWxcIjtcbmltcG9ydCB7IEdyb2tDcmVkZW50aWFscyBhcyBTdG9yZWRHcm9rQ3JlZGVudGlhbHMsIFRva2VuQ3JlZGVudGlhbHMgfSBmcm9tIFwiLi4vdG9rZW4vdG9rZW4udHlwZXNcIjtcbmltcG9ydCB7XG4gIENPTlNPTEVfQ0FMTEJBQ0tfVVJMLFxuICB0eXBlIEFudGhyb3BpY1VzYWdlUmF3LFxuICBidWlsZEF1dGhVcmwsXG4gIGV4Y2hhbmdlQ29kZUZvclRva2VucyxcbiAgZmV0Y2hVc2FnZSxcbiAgZ2VuZXJhdGVQS0NFLFxuICByZWZyZXNoQWNjZXNzVG9rZW4sXG4gIFJlZnJlc2hGYWlsZWRFcnJvcixcbn0gZnJvbSBcIi4vb2F1dGhcIjtcbmltcG9ydCB7IENPREVYX0lNQUdFX0dFTkVSQVRJT05fTU9ERUwgfSBmcm9tIFwiLi9xZ3JpZC1pbWFnZS1nZW5lcmF0aW9uXCI7XG5pbXBvcnQge1xuICBhZnRlclF1ZXJ5LFxuICBiZWZvcmVRdWVyeSxcbiAgZmluaXNoUnVuQWJvcnRlZCxcbiAgZmluaXNoUnVuV2l0aEVycm9yLFxufSBmcm9tIFwiLi9xZ3JpZC1ydW4tbGlmZWN5Y2xlXCI7XG5pbXBvcnQge1xuICBidWlsZEFuZFZhbGlkYXRlU3RyaWN0T3V0cHV0U2NoZW1hLFxuICBjb21wbGV0ZWREcml2ZXJGcm9tSW1hZ2VGYWlsdXJlLFxuICB0eXBlIEludGVybmFsUXVlcnlJbnB1dCxcbiAgUWdyaWREaXNwYXRjaGVyLFxufSBmcm9tIFwiLi9xZ3JpZC5kaXNwYXRjaGVyXCI7XG5pbXBvcnQge1xuICB0eXBlIFF1ZXJ5SW5wdXQsXG4gIHR5cGUgQXBwZW5kU3RlcElucHV0LFxuICB0eXBlIENyZWF0ZVJ1bklucHV0LFxuICB0eXBlIEZpbmlzaFJ1bklucHV0LFxuICBHZW5lcmF0ZUltYWdlc0lucHV0LFxuICB0eXBlIEdlbmVyYXRlSW1hZ2VzT3V0cHV0LFxuICBTcGVha0lucHV0LFxuICB0eXBlIFNwZWFrT3V0cHV0LFxuICBUcmFuc2NyaWJlSW5wdXQsXG4gIHR5cGUgVHJhbnNjcmliZU91dHB1dCxcbiAgVmlkZW9TdGFydElucHV0LFxuICB0eXBlIFZpZGVvU3RhcnRPdXRwdXQsXG4gIFZpZGVvU3RhdHVzSW5wdXQsXG4gIHR5cGUgVmlkZW9TdGF0dXNPdXRwdXQsXG4gIHR5cGUgR3Jva0RldmljZUNvZGVTdGFydCxcbiAgdHlwZSBHcm9rRGV2aWNlUG9sbFJlc3VsdCxcbiAgdHlwZSBIZWFsdGhSZXNwb25zZSxcbiAgdHlwZSBPQXV0aFN0YXJ0UmVzdWx0LFxuICB0eXBlIFF1ZXJ5T3V0cHV0LFxuICB0eXBlIFFncmlkUnVuQ29udGV4dCxcbiAgdHlwZSBRZ3JpZFRocmVhZENvb3JkLFxuICBSRVFVRVNUX0JPRFlfTElNSVRfQllURVMsXG4gIFN0cmVhbUV2ZW50cyxcbiAgdHlwZSBUb2tlblN0YXRzLFxuICB0eXBlIFVzYWdlUmVzcG9uc2UsXG59IGZyb20gXCIuL3FncmlkLnR5cGVzXCI7XG5pbXBvcnQgeyBkZWFjdGl2YXRlQXV0aERlYWRUb2tlbiwgbm90aWZ5VG9rZW5BZGRlZCB9IGZyb20gXCIuL3Rva2VuLWRlYXRoXCI7XG5pbXBvcnQgeyBUb29sU2NoZW1hQ29tcG9zaXRpb25FcnJvciB9IGZyb20gXCIuL3Rvb2wtZW11bGF0aW9uLXNjaGVtYVwiO1xuXG5jb25zdCBwZW5kaW5nU3RyZWFtcyA9IG5ldyBNYXA8c3RyaW5nLCBRdWVyeUlucHV0PigpO1xuXG5jb25zdCBQZW5kaW5nT0F1dGggPSB6Lm9iamVjdCh7XG4gIGNvZGVWZXJpZmllcjogei5zdHJpbmcoKSxcbiAgbmFtZTogei5zdHJpbmcoKSxcbiAgcmVkaXJlY3RVcmk6IHouc3RyaW5nKCksXG4gIHByb3ZpZGVyOiB6LmVudW0oW1wiYW50aHJvcGljXCIsIFwib3BlbmFpXCIsIFwiZ3Jva1wiXSksXG59KTtcblxudHlwZSBQZW5kaW5nT0F1dGggPSB6LmluZmVyPHR5cGVvZiBQZW5kaW5nT0F1dGg+O1xuXG5jb25zdCBPQVVUSF9TVEFURV9QUkVGSVggPSBcIm9hdXRoOnN0YXRlOlwiO1xuY29uc3QgT0FVVEhfU1RBVEVfVFRMID0gXCI1bVwiO1xuY29uc3QgT0FVVEhfU1RBVEVfVFRMX01TID0gNSAqIDYwXzAwMDtcblxuLy8gQSBiYXJlIHBhc3RlZCBHcm9rIGNvZGUgY2FycmllcyBubyBzdGF0ZSwgc28gaXQgYmluZHMgdG8gdGhlIG5ld2VzdCBwZW5kaW5nIEdyb2sgbG9naW4uXG5jb25zdCBHUk9LX0xBVEVTVF9TVEFURV9LRVkgPSBcIm9hdXRoOmdyb2s6bGF0ZXN0XCI7XG5jb25zdCBHUk9LX0RFVklDRV9QUkVGSVggPSBcIm9hdXRoOmdyb2s6ZGV2aWNlOlwiO1xuXG5jb25zdCBQZW5kaW5nR3Jva0RldmljZSA9IHoub2JqZWN0KHtcbiAgbmFtZTogei5zdHJpbmcoKSxcbiAgaW50ZXJ2YWw6IHoubnVtYmVyKCksXG4gIGV4cGlyZXNBdE1zOiB6Lm51bWJlcigpLFxufSk7XG5cbnR5cGUgUGVuZGluZ0dyb2tEZXZpY2UgPSB6LmluZmVyPHR5cGVvZiBQZW5kaW5nR3Jva0RldmljZT47XG5cbmZ1bmN0aW9uIHVuaXhTZWNvbmRzVG9Jc28oc2Vjb25kczogbnVtYmVyIHwgbnVsbCB8IHVuZGVmaW5lZCk6IHN0cmluZyB8IG51bGwge1xuICByZXR1cm4gc2Vjb25kcyA9PT0gbnVsbCB8fCBzZWNvbmRzID09PSB1bmRlZmluZWQgPyBudWxsIDogbmV3IERhdGUoc2Vjb25kcyAqIDEwMDApLnRvSVNPU3RyaW5nKCk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNldE9BdXRoU3RhdGUoc3RhdGU6IHN0cmluZywgZGF0YTogUGVuZGluZ09BdXRoKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IGNhY2hlID0gZ2V0Q2FjaGVNYW5hZ2VyUmVmKCk7XG5cbiAgaWYgKCFjYWNoZSkgdGhyb3cgbmV3IEVycm9yKFwiQ2FjaGVNYW5hZ2VyIG5vdCBpbml0aWFsaXplZFwiKTtcbiAgYXdhaXQgY2FjaGUuc2V0KHtcbiAgICBrZXk6IGAke09BVVRIX1NUQVRFX1BSRUZJWH0ke3N0YXRlfWAsXG4gICAgdmFsdWU6IEpTT04uc3RyaW5naWZ5KGRhdGEpLFxuICAgIHR0bDogT0FVVEhfU1RBVEVfVFRMLFxuICB9KTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0T0F1dGhTdGF0ZShzdGF0ZTogc3RyaW5nKTogUHJvbWlzZTxQZW5kaW5nT0F1dGggfCB1bmRlZmluZWQ+IHtcbiAgY29uc3QgY2FjaGUgPSBnZXRDYWNoZU1hbmFnZXJSZWYoKTtcblxuICBpZiAoIWNhY2hlKSB0aHJvdyBuZXcgRXJyb3IoXCJDYWNoZU1hbmFnZXIgbm90IGluaXRpYWxpemVkXCIpO1xuICBjb25zdCByYXcgPSBhd2FpdCBjYWNoZS5nZXQ8c3RyaW5nPih7IGtleTogYCR7T0FVVEhfU1RBVEVfUFJFRklYfSR7c3RhdGV9YCB9KTtcblxuICBpZiAoIXJhdykgcmV0dXJuIHVuZGVmaW5lZDtcblxuICByZXR1cm4gUGVuZGluZ09BdXRoLnNhZmVQYXJzZShKU09OLnBhcnNlKHJhdykpLmRhdGE7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGRlbGV0ZU9BdXRoU3RhdGUoc3RhdGU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBjYWNoZSA9IGdldENhY2hlTWFuYWdlclJlZigpO1xuXG4gIGlmICghY2FjaGUpIHJldHVybjtcbiAgYXdhaXQgY2FjaGUuZGVsZXRlKHsga2V5OiBgJHtPQVVUSF9TVEFURV9QUkVGSVh9JHtzdGF0ZX1gIH0pO1xufVxuXG5hc3luYyBmdW5jdGlvbiBzZXRHcm9rTGF0ZXN0U3RhdGUoc3RhdGU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBjYWNoZSA9IGdldENhY2hlTWFuYWdlclJlZigpO1xuXG4gIGlmICghY2FjaGUpIHRocm93IG5ldyBFcnJvcihcIkNhY2hlTWFuYWdlciBub3QgaW5pdGlhbGl6ZWRcIik7XG4gIGF3YWl0IGNhY2hlLnNldCh7IGtleTogR1JPS19MQVRFU1RfU1RBVEVfS0VZLCB2YWx1ZTogc3RhdGUsIHR0bDogT0FVVEhfU1RBVEVfVFRMIH0pO1xufVxuXG5hc3luYyBmdW5jdGlvbiBnZXRHcm9rTGF0ZXN0U3RhdGUoKTogUHJvbWlzZTxzdHJpbmcgfCB1bmRlZmluZWQ+IHtcbiAgY29uc3QgY2FjaGUgPSBnZXRDYWNoZU1hbmFnZXJSZWYoKTtcblxuICBpZiAoIWNhY2hlKSB0aHJvdyBuZXcgRXJyb3IoXCJDYWNoZU1hbmFnZXIgbm90IGluaXRpYWxpemVkXCIpO1xuXG4gIHJldHVybiAoYXdhaXQgY2FjaGUuZ2V0PHN0cmluZz4oeyBrZXk6IEdST0tfTEFURVNUX1NUQVRFX0tFWSB9KSkgPz8gdW5kZWZpbmVkO1xufVxuXG5hc3luYyBmdW5jdGlvbiBzZXRHcm9rRGV2aWNlU3RhdGUoZGV2aWNlQ29kZTogc3RyaW5nLCBkYXRhOiBQZW5kaW5nR3Jva0RldmljZSk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBjYWNoZSA9IGdldENhY2hlTWFuYWdlclJlZigpO1xuXG4gIGlmICghY2FjaGUpIHRocm93IG5ldyBFcnJvcihcIkNhY2hlTWFuYWdlciBub3QgaW5pdGlhbGl6ZWRcIik7XG4gIGNvbnN0IHR0bFNlYyA9IE1hdGgubWF4KDEsIE1hdGguY2VpbCgoZGF0YS5leHBpcmVzQXRNcyAtIERhdGUubm93KCkpIC8gMTAwMCkpO1xuICBhd2FpdCBjYWNoZS5zZXQoe1xuICAgIGtleTogYCR7R1JPS19ERVZJQ0VfUFJFRklYfSR7ZGV2aWNlQ29kZX1gLFxuICAgIHZhbHVlOiBKU09OLnN0cmluZ2lmeShkYXRhKSxcbiAgICB0dGw6IGAke3R0bFNlY31zYCxcbiAgfSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldEdyb2tEZXZpY2VTdGF0ZShkZXZpY2VDb2RlOiBzdHJpbmcpOiBQcm9taXNlPFBlbmRpbmdHcm9rRGV2aWNlIHwgdW5kZWZpbmVkPiB7XG4gIGNvbnN0IGNhY2hlID0gZ2V0Q2FjaGVNYW5hZ2VyUmVmKCk7XG5cbiAgaWYgKCFjYWNoZSkgdGhyb3cgbmV3IEVycm9yKFwiQ2FjaGVNYW5hZ2VyIG5vdCBpbml0aWFsaXplZFwiKTtcbiAgY29uc3QgcmF3ID0gYXdhaXQgY2FjaGUuZ2V0PHN0cmluZz4oeyBrZXk6IGAke0dST0tfREVWSUNFX1BSRUZJWH0ke2RldmljZUNvZGV9YCB9KTtcblxuICBpZiAoIXJhdykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgY29uc3QgZGF0YSA9IFBlbmRpbmdHcm9rRGV2aWNlLnNhZmVQYXJzZShKU09OLnBhcnNlKHJhdykpLmRhdGE7XG5cbiAgcmV0dXJuIGRhdGEgJiYgZGF0YS5leHBpcmVzQXRNcyA+IERhdGUubm93KCkgPyBkYXRhIDogdW5kZWZpbmVkO1xufVxuXG5hc3luYyBmdW5jdGlvbiBkZWxldGVHcm9rRGV2aWNlU3RhdGUoZGV2aWNlQ29kZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IGNhY2hlID0gZ2V0Q2FjaGVNYW5hZ2VyUmVmKCk7XG5cbiAgaWYgKCFjYWNoZSkgcmV0dXJuO1xuICBhd2FpdCBjYWNoZS5kZWxldGUoeyBrZXk6IGAke0dST0tfREVWSUNFX1BSRUZJWH0ke2RldmljZUNvZGV9YCB9KTtcbn1cblxuZnVuY3Rpb24gZ3Jva09BdXRoQmFkUmVxdWVzdChjYXVzZTogdW5rbm93bik6IG5ldmVyIHtcbiAgaWYgKGNhdXNlIGluc3RhbmNlb2YgR3Jva09BdXRoRXJyb3IpIHtcbiAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihTRChcInFncmlkLmdyb2tMb2dpbkZhaWxlZFwiKShjYXVzZS5tZXNzYWdlKSk7XG4gIH1cblxuICB0aHJvdyBjYXVzZTtcbn1cblxuZnVuY3Rpb24gZ3Jva1Rva2VuU25hcHNob3QodG9rZW5JZDogbnVtYmVyKTogR3Jva1Rva2VuU3RhdGVTbmFwc2hvdCB8IHVuZGVmaW5lZCB7XG4gIC8vIFRva2VuLXN0YXRlIHJlcG9ydGluZyBpcyBvcHRpb25hbCBvbiB0aGUgcm91dGluZyBwb3J0OyB0aGUgY29uY3JldGUgR3Jva0Rpc3BhdGNoZXIgaGFzIGl0LlxuICByZXR1cm4gUWdyaWREaXNwYXRjaGVyLmdyb2tEaXNwYXRjaGVyPy50b2tlblN0YXRlcz8uKCkuZmluZCgoc3RhdGUpID0+IHN0YXRlLmlkID09PSB0b2tlbklkKTtcbn1cblxuLyoqIFN0b3JlcyByZWZyZXNoZWQgR3JvayBjcmVkZW50aWFsczsgdGhlIHRva2VuIHN1YnNjcmliZXIgcHVzaGVzIHRoZSByb3cgdG8gdGhlIGRpc3BhdGNoZXIuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcGVyc2lzdEdyb2tDcmVkZW50aWFscyhcbiAgdG9rZW5JZDogbnVtYmVyLFxuICBuZXh0OiBTdHJpY3RHcm9rQ3JlZGVudGlhbHMsXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgY3JlZGVudGlhbHMgPSBTdHJpY3RHcm9rQ3JlZGVudGlhbHMucGFyc2UobmV4dCk7XG4gIGNvbnN0IHJvdyA9IGF3YWl0IFRva2VuTW9kZWwuZmluZEJ5SWQoXCJBXCIsIHRva2VuSWQpO1xuICBhd2FpdCBUb2tlbk1vZGVsLnNhdmUoW1xuICAgIHtcbiAgICAgIGlkOiByb3cuaWQsXG4gICAgICBwcm92aWRlcjogcm93LnByb3ZpZGVyLFxuICAgICAgY3JlZGVudGlhbHMsXG4gICAgICBuYW1lOiByb3cubmFtZSxcbiAgICAgIHJlYXV0aF9yZXF1aXJlZDogZmFsc2UsXG4gICAgfSxcbiAgXSk7XG59XG5cbmNvbnN0IHRydXN0ZWRMb29wYmFja0Jhc2UgPSAoKSA9PiBgaHR0cDovL2xvY2FsaG9zdDoke3Byb2Nlc3MuZW52LlBPUlQgPz8gXCI0NDkwMFwifWA7XG5cbmZ1bmN0aW9uIGlzUmVtb3RlT0F1dGhSZXF1ZXN0KCk6IGJvb2xlYW4ge1xuICB0cnkge1xuICAgIGNvbnN0IHsgaGVhZGVycyB9ID0gU29uYW11LmdldENvbnRleHQoKTtcbiAgICBjb25zdCBvcmlnaW4gPSBoZWFkZXJzLm9yaWdpbjtcbiAgICBjb25zdCBmb3J3YXJkZWQgPSBoZWFkZXJzW1wieC1mb3J3YXJkZWQtaG9zdFwiXTtcbiAgICBjb25zdCByYXdIb3N0ID0gQXJyYXkuaXNBcnJheShmb3J3YXJkZWQpID8gZm9yd2FyZGVkWzBdIDogKGZvcndhcmRlZCA/PyBoZWFkZXJzLmhvc3QpO1xuXG4gICAgY29uc3QgaG9zdCA9IG9yaWdpblxuICAgICAgPyBuZXcgVVJMKG9yaWdpbikuaG9zdG5hbWVcbiAgICAgIDogbmV3IFVSTChgaHR0cDovLyR7cmF3SG9zdCA/PyBcImxvY2FsaG9zdFwifWApLmhvc3RuYW1lO1xuXG4gICAgcmV0dXJuICFuZXcgU2V0KFtcImxvY2FsaG9zdFwiLCBcIjEyNy4wLjAuMVwiLCBcIjo6MVwiLCBcIls6OjFdXCJdKS5oYXMoaG9zdCk7XG4gIH0gY2F0Y2gge31cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbi8vIEFudGhyb3BpYydzIHJlbW90ZS9tYW51YWwgZmxvdyB1c2VzIGl0cyBmaXhlZCBjb25zb2xlIGNhbGxiYWNrLiBIZWFkZXJzIG1heSBzZWxlY3QgYmV0d2VlbiB0d29cbi8vIGFsbG93bGlzdGVkIFVSSXMsIGJ1dCBuZXZlciBjb250cmlidXRlIGF1dGhvcml0eSBvciBwYXRoIGJ5dGVzIHRvIGVpdGhlciBVUkkuXG5pbnRlcmZhY2UgT0F1dGhSZWRpcmVjdCB7XG4gIHJlZGlyZWN0VXJpOiBzdHJpbmc7XG4gIG1vZGU6IFwicmVkaXJlY3RcIiB8IFwiY29kZVwiO1xufVxuXG5mdW5jdGlvbiByZXNvbHZlT0F1dGhSZWRpcmVjdCgpOiBPQXV0aFJlZGlyZWN0IHtcbiAgaWYgKGlzUmVtb3RlT0F1dGhSZXF1ZXN0KCkpIHtcbiAgICByZXR1cm4geyByZWRpcmVjdFVyaTogQ09OU09MRV9DQUxMQkFDS19VUkwsIG1vZGU6IFwiY29kZVwiIH07XG4gIH1cblxuICByZXR1cm4geyByZWRpcmVjdFVyaTogYCR7dHJ1c3RlZExvb3BiYWNrQmFzZSgpfS9jYWxsYmFja2AsIG1vZGU6IFwicmVkaXJlY3RcIiB9O1xufVxuXG5mdW5jdGlvbiBwYXJzZVBhc3RlZE9BdXRoUmVzdWx0KGlucHV0OiBzdHJpbmcpOiB7IGNvZGU6IHN0cmluZzsgc3RhdGU6IHN0cmluZyB9IHwgbnVsbCB7XG4gIGNvbnN0IHRyaW1tZWQgPSBpbnB1dC50cmltKCk7XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBjYWxsYmFjayA9IG5ldyBVUkwodHJpbW1lZCk7XG4gICAgY29uc3QgY29kZSA9IGNhbGxiYWNrLnNlYXJjaFBhcmFtcy5nZXQoXCJjb2RlXCIpPy50cmltKCkgPz8gXCJcIjtcbiAgICBjb25zdCBzdGF0ZSA9IGNhbGxiYWNrLnNlYXJjaFBhcmFtcy5nZXQoXCJzdGF0ZVwiKT8udHJpbSgpID8/IFwiXCI7XG5cbiAgICBpZiAoY29kZSAmJiBzdGF0ZSkgcmV0dXJuIHsgY29kZSwgc3RhdGUgfTtcbiAgfSBjYXRjaCB7fVxuXG4gIGNvbnN0IHNlcGFyYXRvckF0ID0gdHJpbW1lZC5pbmRleE9mKFwiI1wiKTtcbiAgY29uc3QgY29kZSA9IHNlcGFyYXRvckF0ID4gMCA/IHRyaW1tZWQuc2xpY2UoMCwgc2VwYXJhdG9yQXQpLnRyaW0oKSA6IFwiXCI7XG4gIGNvbnN0IHN0YXRlID0gc2VwYXJhdG9yQXQgPiAwID8gdHJpbW1lZC5zbGljZShzZXBhcmF0b3JBdCArIDEpLnRyaW0oKSA6IFwiXCI7XG5cbiAgcmV0dXJuIGNvZGUgJiYgc3RhdGUgPyB7IGNvZGUsIHN0YXRlIH0gOiBudWxsO1xufVxuXG5mdW5jdGlvbiByZWplY3RJbWFnZUdlbmVyYXRpb25TdHJlYW0oYXJnczogUXVlcnlJbnB1dCk6IHZvaWQge1xuICBpZiAoIWFyZ3MuaW1hZ2VHZW5lcmF0aW9uICYmIGFyZ3MubW9kZWwgIT09IGBvcGVuYWkvJHtDT0RFWF9JTUFHRV9HRU5FUkFUSU9OX01PREVMfWApIHJldHVybjtcbiAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oXG4gICAgU0QoXCJlcnJvci5kZXRhaWxcIikoXG4gICAgICBcInFncmlkOiBpbWFnZUdlbmVyYXRpb24gaXMgbm90IHN1cHBvcnRlZCB3aXRoIHN0cmVhbWluZzsgdXNlIHF1ZXJ5IG9yIGdlbmVyYXRlSW1hZ2Ugd2l0aCBxZ3JpZC5pbWFnZSgpIGluc3RlYWQuXCIsXG4gICAgKSxcbiAgKTtcbn1cblxuZnVuY3Rpb24gcmVqZWN0SW52YWxpZEltYWdlUXVlcnkoYXJnczogUXVlcnlJbnB1dCk6IHZvaWQge1xuICBjb25zdCBzdGFuZGFsb25lID0gYXJncy5tb2RlbCA9PT0gYG9wZW5haS8ke0NPREVYX0lNQUdFX0dFTkVSQVRJT05fTU9ERUx9YDtcblxuICBpZiAoIXN0YW5kYWxvbmUgJiYgYXJncy5pbWFnZUdlbmVyYXRpb24gIT09IFwiYXV0b1wiKSByZXR1cm47XG5cbiAgaWYgKHN0YW5kYWxvbmUgJiYgYXJncy5pbWFnZUdlbmVyYXRpb24gIT09IHRydWUpIHtcbiAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihcbiAgICAgIFNEKFwiZXJyb3IuZGV0YWlsXCIpKFxuICAgICAgICBcInFncmlkOiB0aGUgaW1hZ2UgbW9kZWwgcmVxdWlyZXMgaW1hZ2VHZW5lcmF0aW9uOiB0cnVlOyB1c2UgcWdyaWQuaW1hZ2UoKSB3aXRoIGdlbmVyYXRlSW1hZ2UuXCIsXG4gICAgICApLFxuICAgICk7XG4gIH1cblxuICBpZiAoYXJncy50b29scz8ubGVuZ3RoIHx8IGFyZ3MuanNvblNjaGVtYSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oXG4gICAgICBTRChcImVycm9yLmRldGFpbFwiKShcbiAgICAgICAgXCJxZ3JpZDogYXV0b21hdGljIGFuZCBzdGFuZGFsb25lIGltYWdlIGdlbmVyYXRpb24gZG8gbm90IHN1cHBvcnQgY2FsbGVyIHRvb2xzIG9yIHN0cnVjdHVyZWQgb3V0cHV0LlwiLFxuICAgICAgKSxcbiAgICApO1xuICB9XG5cbiAgaWYgKFxuICAgIGFyZ3MuaW1hZ2VHZW5lcmF0aW9uT3B0aW9ucz8ub3V0cHV0Rm9ybWF0ICYmXG4gICAgYXJncy5pbWFnZUdlbmVyYXRpb25PcHRpb25zLm91dHB1dEZvcm1hdCAhPT0gXCJwbmdcIlxuICApIHtcbiAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihcbiAgICAgIFNEKFwiZXJyb3IuZGV0YWlsXCIpKFxuICAgICAgICBcInFncmlkOiBhdXRvbWF0aWMgYW5kIHN0YW5kYWxvbmUgaW1hZ2UgZ2VuZXJhdGlvbiBvbmx5IHN1cHBvcnQgUE5HIG91dHB1dC5cIixcbiAgICAgICksXG4gICAgKTtcbiAgfVxufVxuXG4vLyBhbnRocm9waWMg7J2AIC0tanNvbi1zY2hlbWEg66W8IOyTsOyngCDslYrsnLzrr4DroZwoU09OLTUzMikgc3RyaWN0IOuzgO2ZmMK3YXJndiDsoJztlZwg7JeG7J20IOybkO2YleydmFxuLy8g6rWs66y4wrfrs7XsnqHrj4Trp4wg6rKA7Kad65Cc64ukIOKAlCBwcm92aWRlciDrtoTquLDripQgYnVpbGRBbmRWYWxpZGF0ZVN0cmljdE91dHB1dFNjaGVtYSDqsIAg7IaM7Jyg7ZWc64ukLlxuZnVuY3Rpb24gcmVqZWN0SW52YWxpZENhbGxlclNjaGVtYXMoYXJnczogUXVlcnlJbnB1dCk6IHZvaWQge1xuICBpZiAoYXJncy5qc29uU2NoZW1hID09PSB1bmRlZmluZWQgJiYgIWFyZ3MudG9vbHM/Lmxlbmd0aCkgcmV0dXJuO1xuXG4gIHRyeSB7XG4gICAgYnVpbGRBbmRWYWxpZGF0ZVN0cmljdE91dHB1dFNjaGVtYShhcmdzKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBpZiAoXG4gICAgICBlcnJvciBpbnN0YW5jZW9mIENhbGxlclNjaGVtYVZhbGlkYXRpb25FcnJvciB8fFxuICAgICAgZXJyb3IgaW5zdGFuY2VvZiBUb29sU2NoZW1hQ29tcG9zaXRpb25FcnJvclxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oU0QoXCJlcnJvci5kZXRhaWxcIikoZXJyb3IubWVzc2FnZSkpO1xuICAgIH1cblxuICAgIC8vIOyemOuqu+uQnCBrZXl3b3JkIO2Yle2DnChhbnlPZiDrpbwg6rCd7LK066GcIOuztOuCtOuKlCDrk7Ep64qUIO2MjOydtO2UhOudvOyduOyXkOyEnCB1bnR5cGVkIOyYpOulmOuhnCDrgpjsmKTrr4DroZwsXG4gICAgLy8g7YOA7J6FIOyige2eiOq4sCDrjIDsi6AgRXJyb3Ig7KCE7LK066W8IGNhbGxlci1mYXVsdCA0MDAg7Jy866GcIOunpO2Vke2VnOuLpCjqs4Tslb0g7YWM7Iqk7Yq466GcIOqzoOygleuQqCkuXG4gICAgaWYgKGVycm9yIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKFxuICAgICAgICBTRChcImVycm9yLmRldGFpbFwiKShgcWdyaWQ6IGNhbGxlciBzY2hlbWEgY2Fubm90IGJlIG5vcm1hbGl6ZWQ6ICR7ZXJyb3IubWVzc2FnZX1gKSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZVRva2VuTmFtZShhcmdzOiBRdWVyeUlucHV0KTogUHJvbWlzZTxJbnRlcm5hbFF1ZXJ5SW5wdXQ+IHtcbiAgaWYgKCFhcmdzLnRva2VuTmFtZSkgcmV0dXJuIGFyZ3M7XG5cbiAgY29uc3QgdG9rZW5Qcm92aWRlciA9IGFyZ3MudG9rZW5OYW1lLnNwbGl0KFwiL1wiLCAxKVswXTtcbiAgY29uc3QgbW9kZWxQcm92aWRlciA9IGFyZ3MubW9kZWw/LnNwbGl0KFwiL1wiLCAxKVswXTtcblxuICBpZiAoIWlzUHJvdmlkZXJJZCh0b2tlblByb3ZpZGVyKSkge1xuICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKFNEKFwiZXJyb3IuZGV0YWlsXCIpKGBJbnZhbGlkIHRva2VuIG5hbWU6ICR7YXJncy50b2tlbk5hbWV9YCkpO1xuICB9XG5cbiAgaWYgKG1vZGVsUHJvdmlkZXIgIT09IHRva2VuUHJvdmlkZXIpIHtcbiAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihcbiAgICAgIFNEKFwiZXJyb3IuZGV0YWlsXCIpKFwiVG9rZW4gcHJvdmlkZXIgZG9lcyBub3QgbWF0Y2ggbW9kZWwgcHJvdmlkZXJcIiksXG4gICAgKTtcbiAgfVxuXG4gIGNvbnN0IHRva2VuID0gYXdhaXQgVG9rZW5Nb2RlbC5maW5kQWN0aXZlQnlQcm92aWRlckFuZE5hbWUoXCJBXCIsIHRva2VuUHJvdmlkZXIsIGFyZ3MudG9rZW5OYW1lKTtcblxuICBpZiAoIXRva2VuKSB7XG4gICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oU0QoXCJlcnJvci5kZXRhaWxcIikoYEFjdGl2ZSB0b2tlbiBub3QgZm91bmQ6ICR7YXJncy50b2tlbk5hbWV9YCkpO1xuICB9XG5cbiAgcmV0dXJuIHsgLi4uYXJncywgcHJlZmVycmVkVG9rZW5JZDogdG9rZW4uaWQsIHJlcXVpcmVQcmVmZXJyZWRUb2tlbjogdHJ1ZSB9O1xufVxuXG5pbnRlcmZhY2UgSHR0cERpc2Nvbm5lY3RIYW5kbGUge1xuICBzaWduYWw6IEFib3J0U2lnbmFsO1xuICBkaXNwb3NlOiAoKSA9PiB2b2lkO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVIdHRwRGlzY29ubmVjdEhhbmRsZSgpOiBIdHRwRGlzY29ubmVjdEhhbmRsZSB7XG4gIGNvbnN0IGFib3J0Q29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgbGV0IHJlcXVlc3RSYXc6IEZhc3RpZnlSZXF1ZXN0W1wicmF3XCJdIHwgdW5kZWZpbmVkO1xuICBsZXQgcmVzcG9uc2VSYXc6IEZhc3RpZnlSZXBseVtcInJhd1wiXSB8IHVuZGVmaW5lZDtcblxuICB0cnkge1xuICAgIGNvbnN0IGN0eCA9IFNvbmFtdS5nZXRDb250ZXh0KCk7XG4gICAgcmVxdWVzdFJhdyA9IGN0eC5yZXF1ZXN0Py5yYXc7XG5cbiAgICBpZiAoY3R4LnRyYW5zcG9ydCA9PT0gXCJodHRwXCIpIHJlc3BvbnNlUmF3ID0gY3R4LnJlcGx5LnJhdztcbiAgfSBjYXRjaCB7XG4gICAgLy8gRGlyZWN0IGZyYW1lIGNhbGxzIChmb3IgZXhhbXBsZSB1bml0IHRlc3RzKSBkbyBub3QgaGF2ZSBhbiBIVFRQIGNvbnRleHQuXG4gIH1cblxuICBjb25zdCBhYm9ydCA9ICgpID0+IGFib3J0Q29udHJvbGxlci5hYm9ydCgpO1xuXG4gIGNvbnN0IGFib3J0T25JbmNvbXBsZXRlUmVzcG9uc2VDbG9zZSA9ICgpID0+IHtcbiAgICBpZiAoIXJlc3BvbnNlUmF3Py53cml0YWJsZUVuZGVkKSBhYm9ydCgpO1xuICB9O1xuXG4gIHJlcXVlc3RSYXc/Lm9uY2UoXCJhYm9ydGVkXCIsIGFib3J0KTtcbiAgcmVzcG9uc2VSYXc/Lm9uY2UoXCJjbG9zZVwiLCBhYm9ydE9uSW5jb21wbGV0ZVJlc3BvbnNlQ2xvc2UpO1xuXG4gIGlmIChyZXF1ZXN0UmF3Py5hYm9ydGVkIHx8IChyZXNwb25zZVJhdz8uZGVzdHJveWVkICYmICFyZXNwb25zZVJhdy53cml0YWJsZUVuZGVkKSkge1xuICAgIGFib3J0KCk7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIHNpZ25hbDogYWJvcnRDb250cm9sbGVyLnNpZ25hbCxcbiAgICBkaXNwb3NlOiAoKSA9PiB7XG4gICAgICByZXF1ZXN0UmF3Py5yZW1vdmVMaXN0ZW5lcihcImFib3J0ZWRcIiwgYWJvcnQpO1xuICAgICAgcmVzcG9uc2VSYXc/LnJlbW92ZUxpc3RlbmVyKFwiY2xvc2VcIiwgYWJvcnRPbkluY29tcGxldGVSZXNwb25zZUNsb3NlKTtcbiAgICB9LFxuICB9O1xufVxuXG5jb25zdCBsb2dnZXIgPSBnZXRMb2dnZXIoW1wicWdyaWRcIl0pO1xuY29uc3Qgb2F1dGhMb2dnZXIgPSBnZXRMb2dnZXIoW1wicWdyaWRcIiwgXCJvYXV0aFwiXSk7XG5cbi8vIHBlci10b2tlbiByZWZyZXNoIGRlZHVwIOKAlCDtmozsoIQg6rK57Lmo7Jy866GcIOyduO2VnCDsgqzrp50g7Jik7YyQ7J2EIOunieuKlOuLpC5cbmNvbnN0IGluZmxpZ2h0QW50aHJvcGljUmVmcmVzaCA9IG5ldyBNYXA8bnVtYmVyLCBQcm9taXNlPHN0cmluZz4+KCk7XG5cbi8vIC0tLSBHcm9rIG1lZGlhIGFuZCB2b2ljZSAtLS1cblxuY29uc3QgbWVkaWFMb2dnZXIgPSBnZXRMb2dnZXIoW1wicWdyaWRcIiwgXCJtZWRpYVwiXSk7XG5cbnR5cGUgTWVkaWFLaW5kID0gXCJpbWFnZVwiIHwgXCJ2aWRlb1wiIHwgXCJzdHRcIiB8IFwidHRzXCI7XG5cbmNvbnN0IE1FRElBX1RPT0xfTkFNRVM6IFJlY29yZDxNZWRpYUtpbmQsIHN0cmluZz4gPSB7XG4gIGltYWdlOiBcImltYWdlX2dlbmVyYXRpb25cIixcbiAgdmlkZW86IFwidmlkZW9fZ2VuZXJhdGlvblwiLFxuICBzdHQ6IFwidHJhbnNjcmlwdGlvblwiLFxuICB0dHM6IFwic3BlZWNoXCIsXG59O1xuXG5mdW5jdGlvbiBncm9rTm90UmVhZHkoKTogRXJyb3Ige1xuICByZXR1cm4gUWdyaWREaXNwYXRjaGVyLnN0YXJ0dXBTdGF0ZS5ncm9rID09PSBcImZhaWxlZFwiXG4gICAgPyBuZXcgSW50ZXJuYWxTZXJ2ZXJFcnJvckV4Y2VwdGlvbihTRChcInFncmlkLmRpc3BhdGNoZXJGYWlsZWRcIikoXCJHcm9rXCIpKVxuICAgIDogbmV3IFNlcnZpY2VVbmF2YWlsYWJsZUV4Y2VwdGlvbihTRChcInFncmlkLmRpc3BhdGNoZXJTdGFydGluZ1wiKShcIkdyb2tcIikpO1xufVxuXG5mdW5jdGlvbiBncm9rTWVkaWEoKTogTWVkaWFEaXNwYXRjaGVyIHtcbiAgY29uc3QgZGlzcGF0Y2hlciA9IFFncmlkRGlzcGF0Y2hlci5ncm9rRGlzcGF0Y2hlcjtcbiAgY29uc3QgZ2VuZXJhdGVJbWFnZXMgPSBkaXNwYXRjaGVyPy5nZW5lcmF0ZUltYWdlcztcbiAgY29uc3QgZWRpdEltYWdlcyA9IGRpc3BhdGNoZXI/LmVkaXRJbWFnZXM7XG4gIGNvbnN0IHN0YXJ0VmlkZW8gPSBkaXNwYXRjaGVyPy5zdGFydFZpZGVvO1xuICBjb25zdCBnZXRWaWRlbyA9IGRpc3BhdGNoZXI/LmdldFZpZGVvO1xuXG4gIGlmICghZGlzcGF0Y2hlciB8fCAhZ2VuZXJhdGVJbWFnZXMgfHwgIWVkaXRJbWFnZXMgfHwgIXN0YXJ0VmlkZW8gfHwgIWdldFZpZGVvKSB7XG4gICAgdGhyb3cgZ3Jva05vdFJlYWR5KCk7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGdlbmVyYXRlSW1hZ2VzOiBnZW5lcmF0ZUltYWdlcy5iaW5kKGRpc3BhdGNoZXIpLFxuICAgIGVkaXRJbWFnZXM6IGVkaXRJbWFnZXMuYmluZChkaXNwYXRjaGVyKSxcbiAgICBzdGFydFZpZGVvOiBzdGFydFZpZGVvLmJpbmQoZGlzcGF0Y2hlciksXG4gICAgZ2V0VmlkZW86IGdldFZpZGVvLmJpbmQoZGlzcGF0Y2hlciksXG4gIH07XG59XG5cbmZ1bmN0aW9uIGdyb2tWb2ljZSgpOiBWb2ljZURpc3BhdGNoZXIge1xuICBjb25zdCBkaXNwYXRjaGVyID0gUWdyaWREaXNwYXRjaGVyLmdyb2tEaXNwYXRjaGVyO1xuICBjb25zdCB0cmFuc2NyaWJlID0gZGlzcGF0Y2hlcj8udHJhbnNjcmliZTtcbiAgY29uc3Qgc3BlYWsgPSBkaXNwYXRjaGVyPy5zcGVhaztcblxuICBpZiAoIWRpc3BhdGNoZXIgfHwgIXRyYW5zY3JpYmUgfHwgIXNwZWFrKSB0aHJvdyBncm9rTm90UmVhZHkoKTtcblxuICByZXR1cm4geyB0cmFuc2NyaWJlOiB0cmFuc2NyaWJlLmJpbmQoZGlzcGF0Y2hlciksIHNwZWFrOiBzcGVhay5iaW5kKGRpc3BhdGNoZXIpIH07XG59XG5cbmNsYXNzIFRvb01hbnlSZXF1ZXN0c0V4Y2VwdGlvbiBleHRlbmRzIFNvRXhjZXB0aW9uIHtcbiAgY29uc3RydWN0b3IobWVzc2FnZTogTG9jYWxpemVkU3RyaW5nKSB7XG4gICAgc3VwZXIoNDI5LCBtZXNzYWdlKTtcbiAgfVxufVxuXG4vKipcbiAqIEV2ZXJ5IEdyb2sgdG9rZW4gaXMgY29vbGluZyBkb3duLiBBIDQyOSByYXRoZXIgdGhhbiBhIDUwMzogdGhlIHNlcnZlciBlcnJvciBoYW5kbGVyIHBpbnMgNTAzJ3NcbiAqIFJldHJ5LUFmdGVyIHRvIGl0cyBzdGFydHVwIGludGVydmFsLCB3aGlsZSB0aGlzIGRlbGF5IGNvbWVzIGZyb20gdGhlIHVwc3RyZWFtIGNvb2xkb3duLlxuICovXG5mdW5jdGlvbiBncm9rUmF0ZUxpbWl0ZWQoZXJyb3I6IEdyb2tSYXRlTGltaXRlZEVycm9yKTogVG9vTWFueVJlcXVlc3RzRXhjZXB0aW9uIHtcbiAgbGV0IHJlcGx5OiBGYXN0aWZ5UmVwbHkgfCB1bmRlZmluZWQ7XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBjdHggPSBTb25hbXUuZ2V0Q29udGV4dCgpO1xuXG4gICAgaWYgKGN0eC50cmFuc3BvcnQgPT09IFwiaHR0cFwiKSByZXBseSA9IGN0eC5yZXBseTtcbiAgfSBjYXRjaCB7XG4gICAgLy8gRGlyZWN0IGZyYW1lIGNhbGxzIChmb3IgZXhhbXBsZSB1bml0IHRlc3RzKSBoYXZlIG5vIEhUVFAgY29udGV4dCBhbmQgbm8gaGVhZGVyIHRvIHNldC5cbiAgfVxuXG4gIC8vIEFuIFNTRSBzdHJlYW0gaGFzIGFscmVhZHkgc2VudCBpdHMgaGVhZGVyczsgdGhlIGVycm9yIGV2ZW50IHRoZW4gY2FycmllcyB0aGUgZGVsYXkgYWxvbmUuXG4gIGlmIChyZXBseSAmJiAhcmVwbHkucmF3LmhlYWRlcnNTZW50KSByZXBseS5oZWFkZXIoXCJSZXRyeS1BZnRlclwiLCBTdHJpbmcoZXJyb3IucmV0cnlBZnRlclNlYykpO1xuXG4gIHJldHVybiBuZXcgVG9vTWFueVJlcXVlc3RzRXhjZXB0aW9uKFNEKFwicWdyaWQuZ3Jva1JhdGVMaW1pdGVkXCIpKGVycm9yLnJldHJ5QWZ0ZXJTZWMpKTtcbn1cblxuLyoqXG4gKiBDYWxsZXItZmF1bHQgR3JvayBlcnJvcnMgYmVjb21lIDQwMC80MjkvNTAzIGF0IHRoZSBjaGF0IGFuZCBtZWRpYSBib3VuZGFyaWVzOyB1cHN0cmVhbSBhbmRcbiAqIHByb3ZpZGVyIGZhaWx1cmVzIHByb3BhZ2F0ZSB1bmNoYW5nZWQgKDUwMCBieSB0aGUgc2VydmVyIGVycm9yIGhhbmRsZXIpLiBcIk5vIGVsaWdpYmxlIHRva2VuIGZvclxuICogdGhpcyByZXF1ZXN0IGNsYXNzXCIgKG5vIHdvcmtlcnMsIGluLWZsaWdodCBjYXAsIG9uLWRlbWFuZCBENiwgWkRSIHZpZGVvKSBpcyBhIDUwMywgbm90IGEgc2VydmVyXG4gKiBmYXVsdDsgZXZlcnkgdG9rZW4gY29vbGluZyBkb3duIGlzIGEgNDI5IHdpdGggdGhlIHNvb25lc3QgcmV0cnkgZGVsYXkuXG4gKi9cbmZ1bmN0aW9uIHRocm93R3Jva0NhbGxlckVycm9yKGNhdXNlOiB1bmtub3duKTogbmV2ZXIge1xuICBpZiAoY2F1c2UgaW5zdGFuY2VvZiBHcm9rSW52YWxpZFJlcXVlc3RFcnJvcikge1xuICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKFNEKFwicWdyaWQuZ3Jva0ludmFsaWRSZXF1ZXN0XCIpKGNhdXNlLm1lc3NhZ2UpKTtcbiAgfVxuXG4gIGlmIChjYXVzZSBpbnN0YW5jZW9mIEdyb2tDb250ZW50UG9saWN5RXJyb3IpIHtcbiAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihTRChcInFncmlkLmdyb2tDb250ZW50UG9saWN5XCIpKGNhdXNlLm1lc3NhZ2UpKTtcbiAgfVxuXG4gIGlmIChjYXVzZSBpbnN0YW5jZW9mIEdyb2tDYXBhYmlsaXR5VW5hdmFpbGFibGVFcnJvcikge1xuICAgIHRocm93IG5ldyBTZXJ2aWNlVW5hdmFpbGFibGVFeGNlcHRpb24oU0QoXCJxZ3JpZC5ncm9rQ2FwYWJpbGl0eVVuYXZhaWxhYmxlXCIpKGNhdXNlLm1lc3NhZ2UpKTtcbiAgfVxuXG4gIGlmIChjYXVzZSBpbnN0YW5jZW9mIEdyb2tPbkRlbWFuZEV4Y2x1ZGVkRXJyb3IpIHtcbiAgICB0aHJvdyBuZXcgU2VydmljZVVuYXZhaWxhYmxlRXhjZXB0aW9uKFxuICAgICAgU0QoXCJxZ3JpZC5ncm9rT25EZW1hbmRFeGNsdWRlZFwiKShjYXVzZS50b2tlbk5hbWVzLmpvaW4oXCIsIFwiKSksXG4gICAgKTtcbiAgfVxuXG4gIGlmIChjYXVzZSBpbnN0YW5jZW9mIEdyb2taZHJWaWRlb1VuYXZhaWxhYmxlRXJyb3IpIHtcbiAgICB0aHJvdyBuZXcgU2VydmljZVVuYXZhaWxhYmxlRXhjZXB0aW9uKFxuICAgICAgU0QoXCJxZ3JpZC5ncm9rWmRyVmlkZW9VbmF2YWlsYWJsZVwiKShjYXVzZS50b2tlbk5hbWVzLmpvaW4oXCIsIFwiKSksXG4gICAgKTtcbiAgfVxuXG4gIGlmIChjYXVzZSBpbnN0YW5jZW9mIEdyb2tDYXBhY2l0eUVycm9yKSB7XG4gICAgdGhyb3cgbmV3IFNlcnZpY2VVbmF2YWlsYWJsZUV4Y2VwdGlvbihTRChcInFncmlkLmdyb2tDYXBhY2l0eVwiKSk7XG4gIH1cblxuICBpZiAoY2F1c2UgaW5zdGFuY2VvZiBHcm9rUmF0ZUxpbWl0ZWRFcnJvcikgdGhyb3cgZ3Jva1JhdGVMaW1pdGVkKGNhdXNlKTtcblxuICBpZiAoY2F1c2UgaW5zdGFuY2VvZiBHcm9rTm9Xb3JrZXJzRXJyb3IpIHtcbiAgICB0aHJvdyBuZXcgU2VydmljZVVuYXZhaWxhYmxlRXhjZXB0aW9uKFNEKFwicWdyaWQuZ3Jva05vV29ya2Vyc1wiKShjYXVzZS5tZXNzYWdlKSk7XG4gIH1cblxuICB0aHJvdyBjYXVzZTtcbn1cblxuY2xhc3MgUGF5bG9hZFRvb0xhcmdlRXhjZXB0aW9uIGV4dGVuZHMgU29FeGNlcHRpb24ge1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlOiBMb2NhbGl6ZWRTdHJpbmcpIHtcbiAgICBzdXBlcig0MTMsIG1lc3NhZ2UpO1xuICB9XG59XG5cbmNvbnN0IE1pQiA9IDEwMjQgKiAxMDI0O1xuXG4vKipcbiAqIEZhc3RpZnkgcmVqZWN0cyBhIGJvZHkgb3ZlciBgYm9keUxpbWl0YCBiZWZvcmUgcm91dGluZyB3aXRoIEZTVF9FUlJfQ1RQX0JPRFlfVE9PX0xBUkdFLCB3aGljaCBpc1xuICogbm90IGEgU29uYW11IGV4Y2VwdGlvbiBhbmQgd291bGQgb3RoZXJ3aXNlIGFuc3dlciA1MDAuIFRoZSBzZXJ2ZXIgZXJyb3IgaGFuZGxlciBhcHBsaWVzIHRoaXNcbiAqIGZpcnN0IHNvIHRoZSBjYWxsZXIgZ2V0cyBhIFNvbmFtdSA0MTMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtYXBSZXF1ZXN0Qm9keVRvb0xhcmdlKGVycm9yOiBFcnJvcik6IEVycm9yIHtcbiAgaWYgKFwiY29kZVwiIGluIGVycm9yICYmIGVycm9yLmNvZGUgPT09IFwiRlNUX0VSUl9DVFBfQk9EWV9UT09fTEFSR0VcIikge1xuICAgIHJldHVybiBuZXcgUGF5bG9hZFRvb0xhcmdlRXhjZXB0aW9uKFxuICAgICAgU0QoXCJxZ3JpZC5yZXF1ZXN0Qm9keVRvb0xhcmdlXCIpKFJFUVVFU1RfQk9EWV9MSU1JVF9CWVRFUyAvIE1pQiksXG4gICAgKTtcbiAgfVxuXG4gIHJldHVybiBlcnJvcjtcbn1cblxuLy8gU29uYW11J3MgZ2VuZXJhdGVkIHZhbGlkYXRvciBkb2VzIG5vdCBjYXJyeSB6b2QgcmVmaW5lbWVudHMgKHNpemUsIGh0dHBzLCBiYXNlNjQpLCBzbyBtZWRpYVxuLy8gZW5kcG9pbnRzIHJlLXZhbGlkYXRlIHdpdGggdGhlIGZ1bGwgc2NoZW1hLlxuZnVuY3Rpb24gcGFyc2VNZWRpYUlucHV0PFMgZXh0ZW5kcyB6LlpvZFR5cGU+KHNjaGVtYTogUywgdmFsdWU6IHouaW5wdXQ8Uz4pOiB6LmluZmVyPFM+IHtcbiAgY29uc3QgcGFyc2VkID0gc2NoZW1hLnNhZmVQYXJzZSh2YWx1ZSk7XG5cbiAgaWYgKCFwYXJzZWQuc3VjY2Vzcykge1xuICAgIGNvbnN0IGRldGFpbCA9IHBhcnNlZC5lcnJvci5pc3N1ZXNcbiAgICAgIC5tYXAoKGlzc3VlKSA9PiBgJHtpc3N1ZS5wYXRoLmpvaW4oXCIuXCIpIHx8IFwiaW5wdXRcIn06ICR7aXNzdWUubWVzc2FnZX1gKVxuICAgICAgLmpvaW4oXCI7IFwiKTtcblxuICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKFNEKFwicWdyaWQuaW52YWxpZElucHV0XCIpKGRldGFpbCkpO1xuICB9XG5cbiAgcmV0dXJuIHBhcnNlZC5kYXRhO1xufVxuXG5hc3luYyBmdW5jdGlvbiByZXNvbHZlR3Jva1Rva2VuU2VsZWN0aW9uKFxuICB0b2tlbk5hbWU6IHN0cmluZyB8IHVuZGVmaW5lZCxcbik6IFByb21pc2U8TWVkaWFUb2tlblNlbGVjdGlvbj4ge1xuICBpZiAoIXRva2VuTmFtZSkgcmV0dXJuIHt9O1xuXG4gIGlmICghdG9rZW5OYW1lLnN0YXJ0c1dpdGgoXCJncm9rL1wiKSkge1xuICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKFxuICAgICAgU0QoXCJlcnJvci5kZXRhaWxcIikoXCJUb2tlbiBwcm92aWRlciBkb2VzIG5vdCBtYXRjaCBtb2RlbCBwcm92aWRlclwiKSxcbiAgICApO1xuICB9XG5cbiAgY29uc3QgdG9rZW4gPSBhd2FpdCBUb2tlbk1vZGVsLmZpbmRBY3RpdmVCeVByb3ZpZGVyQW5kTmFtZShcIkFcIiwgXCJncm9rXCIsIHRva2VuTmFtZSk7XG5cbiAgaWYgKCF0b2tlbikge1xuICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKFNEKFwiZXJyb3IuZGV0YWlsXCIpKGBBY3RpdmUgdG9rZW4gbm90IGZvdW5kOiAke3Rva2VuTmFtZX1gKSk7XG4gIH1cblxuICByZXR1cm4geyBwcmVmZXJyZWRUb2tlbklkOiB0b2tlbi5pZCwgcmVxdWlyZVByZWZlcnJlZFRva2VuOiB0cnVlIH07XG59XG5cbmludGVyZmFjZSBSb3V0ZWRNb2RlbElkIHtcbiAgaWQ6IHN0cmluZztcbiAgcm91dGU6IHN0cmluZztcbn1cblxuZnVuY3Rpb24gcm91dGVNb2RlbElkKG1vZGVsOiBzdHJpbmcgfCB1bmRlZmluZWQsIGZhbGxiYWNrOiBzdHJpbmcpOiBSb3V0ZWRNb2RlbElkIHtcbiAgY29uc3QgaWQgPSBtb2RlbCA/IG1vZGVsLnNsaWNlKFwiZ3Jvay9cIi5sZW5ndGgpIDogZmFsbGJhY2s7XG5cbiAgcmV0dXJuIHsgaWQsIHJvdXRlOiBgZ3Jvay8ke2lkfWAgfTtcbn1cblxudHlwZSBHZW5lcmF0ZWRJbWFnZSA9IEdlbmVyYXRlSW1hZ2VzT3V0cHV0W1wiaW1hZ2VzXCJdW251bWJlcl07XG5cbi8qKiBBZGRzIHRoZSBwcm92aWRlciB0aHJlYWQgY29vcmRpbmF0ZSB0byB0aGUgbGlmZWN5Y2xlIHJ1biBjb250ZXh0IHdpdGhvdXQgZHJvcHBpbmcgZWl0aGVyLiAqL1xuZnVuY3Rpb24gbWVyZ2VSdW5Db250ZXh0KFxuICBsaWZlY3ljbGU6IFFncmlkUnVuQ29udGV4dCB8IHVuZGVmaW5lZCxcbiAgdGhyZWFkQ29vcmQ6IFFncmlkVGhyZWFkQ29vcmQgfCB1bmRlZmluZWQsXG4pOiBRZ3JpZFJ1bkNvbnRleHQgfCB1bmRlZmluZWQge1xuICBpZiAoIWxpZmVjeWNsZSAmJiAhdGhyZWFkQ29vcmQpIHJldHVybiB1bmRlZmluZWQ7XG4gIGNvbnN0IHJ1bkNvbnRleHQ6IFFncmlkUnVuQ29udGV4dCA9IHsgLi4ubGlmZWN5Y2xlIH07XG5cbiAgaWYgKHRocmVhZENvb3JkKSBydW5Db250ZXh0LnRocmVhZENvb3JkID0gdGhyZWFkQ29vcmQ7XG5cbiAgcmV0dXJuIHJ1bkNvbnRleHQ7XG59XG5cbmZ1bmN0aW9uIG1pY3JvVXNkKHVzZDogbnVtYmVyIHwgdW5kZWZpbmVkKTogbnVtYmVyIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIHVzZCA9PT0gdW5kZWZpbmVkID8gdW5kZWZpbmVkIDogTWF0aC5yb3VuZCh1c2QgKiBNSUNST19VU0QpO1xufVxuXG4vKiogUmVmZXJlbmNlLWltYWdlIGxvZyBtZXRhZGF0YTogYSBVUkwsIG9yIGEgZGF0YSBVUkwncyBtZWRpYSB0eXBlIGFuZCBzaXplIChwbHVzIGJ5dGVzKS4gKi9cbnR5cGUgSW1hZ2VSZWZMb2cgPSB7IHVybDogc3RyaW5nIH0gfCB7IG1lZGlhVHlwZTogc3RyaW5nOyBkYXRhPzogc3RyaW5nOyBieXRlU2l6ZTogbnVtYmVyIH07XG5cbi8qKiBSZWZlcmVuY2UtaW1hZ2UgbG9nIG1ldGFkYXRhLiBEYXRhIFVSTHMga2VlcCB0aGVpciBieXRlcyBvbmx5IHdoZW4gYHdpdGhEYXRhYCAoaW1hZ2VzKS4gKi9cbmZ1bmN0aW9uIGRlc2NyaWJlSW1hZ2VSZWZzKHJlZnM6IHN0cmluZ1tdLCB3aXRoRGF0YTogYm9vbGVhbik6IEltYWdlUmVmTG9nW10ge1xuICByZXR1cm4gcmVmcy5tYXAoKHJlZikgPT4ge1xuICAgIGNvbnN0IG1hdGNoID0gL15kYXRhOihbXjssXSspO2Jhc2U2NCwoLiopJC8uZXhlYyhyZWYpO1xuXG4gICAgaWYgKCFtYXRjaCkgcmV0dXJuIHsgdXJsOiByZWYgfTtcbiAgICBjb25zdCBbLCBtZWRpYVR5cGUgPSBcIlwiLCBkYXRhID0gXCJcIl0gPSBtYXRjaDtcbiAgICBjb25zdCBieXRlU2l6ZSA9IEJ1ZmZlci5ieXRlTGVuZ3RoKGRhdGEsIFwiYmFzZTY0XCIpO1xuXG4gICAgcmV0dXJuIHdpdGhEYXRhID8geyBtZWRpYVR5cGUsIGRhdGEsIGJ5dGVTaXplIH0gOiB7IG1lZGlhVHlwZSwgYnl0ZVNpemUgfTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGltYWdlVGFnRm9yTG9nKGI2NDogc3RyaW5nLCBtaW1lVHlwZTogc3RyaW5nLCBhbHQ6IHN0cmluZyB8IHVuZGVmaW5lZCk6IHN0cmluZyB7XG4gIGNvbnN0IHNhZmVBbHQgPSAoYWx0ID8/IFwiZ2VuZXJhdGVkIGltYWdlXCIpLnJlcGxhY2UoL1smXCI8Pl0vZywgKGNoKSA9PiBgJiMke2NoLmNoYXJDb2RlQXQoMCl9O2ApO1xuXG4gIHJldHVybiBgPGltZyBzcmM9XCJkYXRhOiR7bWltZVR5cGV9O2Jhc2U2NCwke2I2NH1cIiBhbHQ9XCIke3NhZmVBbHR9XCIgLz5gO1xufVxuXG50eXBlIE1lZGlhTG9nU3RhcnQgPSB7IGtpbmQ6IE1lZGlhS2luZDsgbW9kZWw6IHN0cmluZzsgcHJvbXB0OiBzdHJpbmc7IHByb2plY3ROYW1lPzogc3RyaW5nIH07XG5cbi8vIENyZWF0aW5nIHRoZSBydW5uaW5nIHJvdyBpcyBhIHByZWNvbmRpdGlvbiBvZiBhIGxvZ2dlZCBwcm92aWRlciBjYWxsLCBhcyBmb3IgcXVlcnkuXG5hc3luYyBmdW5jdGlvbiBzdGFydE1lZGlhUnVuKFxuICBsb2dnZXJFbmFibGVkOiBib29sZWFuIHwgdW5kZWZpbmVkLFxuICBzdGFydDogTWVkaWFMb2dTdGFydCxcbik6IFByb21pc2U8bnVtYmVyIHwgdW5kZWZpbmVkPiB7XG4gIGlmIChsb2dnZXJFbmFibGVkID09PSBmYWxzZSkgcmV0dXJuIHVuZGVmaW5lZDtcblxuICByZXR1cm4gUmVxdWVzdExvZ01vZGVsLmNyZWF0ZVJ1bih7XG4gICAgdXNlcl9wcm9tcHQ6IHN0YXJ0LnByb21wdCxcbiAgICByZXF1ZXN0ZWRfbW9kZWxfbmFtZTogc3RhcnQubW9kZWwsXG4gICAgcHJvamVjdF9uYW1lOiBzdGFydC5wcm9qZWN0TmFtZSxcbiAgICBpc19pbWFnZV9nZW5lcmF0aW9uOiBzdGFydC5raW5kID09PSBcImltYWdlXCIsXG4gIH0pO1xufVxuXG4vKiogSlNPTi1zZXJpYWxpemFibGUgbG9nIGFyZ3VtZW50czsgYHVuZGVmaW5lZGAgbWVtYmVycyBhcmUgZHJvcHBlZCBieSBKU09OLnN0cmluZ2lmeS4gKi9cbnR5cGUgTWVkaWFMb2dBcmcgPSBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgbnVsbCB8IHVuZGVmaW5lZCB8IE1lZGlhTG9nQXJnW10gfCBNZWRpYUxvZ0FyZ3M7XG5cbnR5cGUgTWVkaWFMb2dBcmdzID0geyBba2V5OiBzdHJpbmddOiBNZWRpYUxvZ0FyZyB9O1xuXG4vKiogSW1hZ2Ugc3RlcCBhcmd1bWVudHM7IGNvc3QgYW5kIHJlZmVyZW5jZSBpbWFnZXMgYXJlIHJlY29yZGVkIG9ubHkgd2hlbiBrbm93bi4gKi9cbnR5cGUgSW1hZ2VTdGVwQXJncyA9IHtcbiAga2luZDogXCJpbWFnZVwiO1xuICBwcm9tcHQ6IHN0cmluZztcbiAgbW9kZWw6IHN0cmluZztcbiAgcmVxdWVzdGVkT3B0aW9uczogTWVkaWFMb2dBcmdzO1xuICBpbWFnZUNvdW50OiBudW1iZXI7XG4gIGNvc3RTb3VyY2U/OiBzdHJpbmc7XG4gIGNvc3RJblVzZFRpY2tzPzogbnVtYmVyO1xuICBpbnB1dEltYWdlcz86IEltYWdlUmVmTG9nW107XG59O1xuXG4vKiogVmlkZW8gc3RlcCBhcmd1bWVudHM7IHJlZmVyZW5jZSBpbWFnZXMgYXJlIHJlY29yZGVkIG9ubHkgd2hlbiBzdXBwbGllZC4gKi9cbnR5cGUgVmlkZW9TdGVwQXJncyA9IHtcbiAga2luZDogXCJ2aWRlb1wiO1xuICBwcm9tcHQ6IHN0cmluZztcbiAgbW9kZWw6IHN0cmluZztcbiAgcmVxdWVzdGVkT3B0aW9uczogTWVkaWFMb2dBcmdzO1xuICBpbnB1dEltYWdlcz86IEltYWdlUmVmTG9nW107XG59O1xuXG50eXBlIE1lZGlhTG9nU3RlcHMgPSBBcnJheTx7IHRvb2xDYWxsSWQ6IHN0cmluZzsgYXJnczogTWVkaWFMb2dBcmdzOyByZXN1bHQ/OiBzdHJpbmcgfT47XG5cbnR5cGUgTWVkaWFMb2dTdWNjZXNzID0ge1xuICBraW5kOiBNZWRpYUtpbmQ7XG4gIG1vZGVsOiBzdHJpbmc7XG4gIHRva2VuTmFtZTogc3RyaW5nO1xuICBkdXJhdGlvbk1zOiBudW1iZXI7XG4gIHJlc3BvbnNlOiBzdHJpbmc7XG4gIHN0ZXBzOiBNZWRpYUxvZ1N0ZXBzO1xuICBjb3N0PzogR3Jva01lZGlhQ29zdDtcbn07XG5cbmZ1bmN0aW9uIG1lZGlhVG9vbFN0ZXBzKFxuICBraW5kOiBNZWRpYUtpbmQsXG4gIHN0ZXBzOiBNZWRpYUxvZ1N0ZXBzLFxuICBkdXJhdGlvbk1zOiBudW1iZXIsXG4pOiBSZXF1ZXN0TG9nU3RlcEZpZWxkc1tdIHtcbiAgcmV0dXJuIHN0ZXBzLm1hcCgoc3RlcCwgaW5kZXgpID0+IHtcbiAgICBjb25zdCBmaWVsZHM6IFJlcXVlc3RMb2dTdGVwRmllbGRzID0ge1xuICAgICAgc3RlcF9pbmRleDogMCxcbiAgICAgIHR5cGU6IFwidG9vbF9jYWxsXCIsXG4gICAgICB0b29sX2NhbGxfaW5kZXg6IGluZGV4LFxuICAgICAgdG9vbF9jYWxsX2lkOiBzdGVwLnRvb2xDYWxsSWQsXG4gICAgICB0b29sX25hbWU6IE1FRElBX1RPT0xfTkFNRVNba2luZF0sXG4gICAgICB0b29sX2FyZ3M6IEpTT04uc3RyaW5naWZ5KHN0ZXAuYXJncyksXG4gICAgfTtcblxuICAgIGlmIChzdGVwLnJlc3VsdCAhPT0gdW5kZWZpbmVkKSBmaWVsZHMudG9vbF9yZXN1bHQgPSBzdGVwLnJlc3VsdDtcbiAgICBmaWVsZHMudG9vbF9kdXJhdGlvbl9tcyA9IGR1cmF0aW9uTXM7XG5cbiAgICByZXR1cm4gZmllbGRzO1xuICB9KTtcbn1cblxuLy8gSW1hZ2UgY29zdCBmb2xsb3dzIHRoZSBpbWFnZS1nZW5lcmF0aW9uIGNvbHVtbnMgKGRyaXZlciBjb3N0IDApOyB2aWRlbyBhbmQgdm9pY2UgY29zdCBpcyB0aGVcbi8vIHJvdydzIG93biBjb3N0LiBBbiB1bmtub3duIGNvc3Qgc3RheXMgTlVMTCByYXRoZXIgdGhhbiBhIGd1ZXNzZWQgMC5cbnR5cGUgTWVkaWFDb3N0RmllbGRzID0gUGljazxGaW5pc2hSdW5QYXJhbXMsIFwiY29zdF91c2RcIiB8IFwiY29zdF9zb3VyY2VcIj4gJlxuICBQYXJ0aWFsPFBpY2s8RmluaXNoUnVuUGFyYW1zLCBcImlzX2ltYWdlX2dlbmVyYXRpb25cIiB8IFwiaW1hZ2VfY29zdF91c2RcIiB8IFwiaW1hZ2VfY29zdF9tZXRob2RcIj4+O1xuXG5mdW5jdGlvbiBtZWRpYUNvc3RGaWVsZHMoXG4gIGtpbmQ6IE1lZGlhS2luZCxcbiAgbW9kZWw6IHN0cmluZyxcbiAgY29zdDogR3Jva01lZGlhQ29zdCB8IHVuZGVmaW5lZCxcbik6IE1lZGlhQ29zdEZpZWxkcyB7XG4gIGlmIChraW5kID09PSBcImltYWdlXCIpIHtcbiAgICByZXR1cm4ge1xuICAgICAgY29zdF91c2Q6IDAsXG4gICAgICBjb3N0X3NvdXJjZTogY29zdD8uY29zdFNvdXJjZSA/PyBudWxsLFxuICAgICAgaXNfaW1hZ2VfZ2VuZXJhdGlvbjogdHJ1ZSxcbiAgICAgIGltYWdlX2Nvc3RfdXNkOiBtaWNyb1VzZChjb3N0Py5jb3N0VXNkKSA/PyBudWxsLFxuICAgICAgaW1hZ2VfY29zdF9tZXRob2Q6IGNvc3RcbiAgICAgICAgPyBgJHtjb3N0LmNvc3RTb3VyY2UgPT09IFwicHJvdmlkZXJcIiA/IFwicmVwb3J0ZWRcIiA6IFwiY2F0YWxvZ1wifToke21vZGVsfTp0aWNrcz0ke2Nvc3QudGlja3N9YFxuICAgICAgICA6IG51bGwsXG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiB7IGNvc3RfdXNkOiBtaWNyb1VzZChjb3N0Py5jb3N0VXNkKSA/PyBudWxsLCBjb3N0X3NvdXJjZTogY29zdD8uY29zdFNvdXJjZSA/PyBudWxsIH07XG59XG5cbmZ1bmN0aW9uIG1lZGlhRmluaXNoRmllbGRzKHN1Y2Nlc3M6IE9taXQ8TWVkaWFMb2dTdWNjZXNzLCBcInN0ZXBzXCI+KTogRmluaXNoUnVuUGFyYW1zIHtcbiAgcmV0dXJuIHtcbiAgICBzdGF0dXM6IFwic3VjY2VlZGVkXCIsXG4gICAgcmVzcG9uc2U6IHN1Y2Nlc3MucmVzcG9uc2UsXG4gICAgdG9rZW5fbmFtZTogc3VjY2Vzcy50b2tlbk5hbWUsXG4gICAgcmVxdWVzdGVkX21vZGVsX25hbWU6IHN1Y2Nlc3MubW9kZWwsXG4gICAgbW9kZWxfbmFtZTogc3VjY2Vzcy5tb2RlbCxcbiAgICBpbnB1dF90b2tlbnM6IDAsXG4gICAgb3V0cHV0X3Rva2VuczogMCxcbiAgICBjYWNoZV9yZWFkX3Rva2VuczogMCxcbiAgICBjYWNoZV9jcmVhdGlvbl90b2tlbnM6IDAsXG4gICAgZHVyYXRpb25fbXM6IHN1Y2Nlc3MuZHVyYXRpb25NcyxcbiAgICAuLi5tZWRpYUNvc3RGaWVsZHMoc3VjY2Vzcy5raW5kLCBzdWNjZXNzLm1vZGVsLCBzdWNjZXNzLmNvc3QpLFxuICB9O1xufVxuXG4vLyBMb2dnaW5nIGFmdGVyIGEgc3VjY2Vzc2Z1bCBwcm92aWRlciBjYWxsIGlzIGJlc3QtZWZmb3J0IGFuZCBuZXZlciByZXBsYWNlcyB0aGUgcmVzdWx0LlxuYXN5bmMgZnVuY3Rpb24gZmluaXNoTWVkaWFSdW4oXG4gIHJlcXVlc3RMb2dJZDogbnVtYmVyIHwgdW5kZWZpbmVkLFxuICBzdWNjZXNzOiBNZWRpYUxvZ1N1Y2Nlc3MsXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgaWYgKHJlcXVlc3RMb2dJZCA9PT0gdW5kZWZpbmVkKSByZXR1cm47XG5cbiAgdHJ5IHtcbiAgICBmb3IgKGNvbnN0IHN0ZXAgb2YgbWVkaWFUb29sU3RlcHMoc3VjY2Vzcy5raW5kLCBzdWNjZXNzLnN0ZXBzLCBzdWNjZXNzLmR1cmF0aW9uTXMpKSB7XG4gICAgICBhd2FpdCBSZXF1ZXN0TG9nTW9kZWwuYXBwZW5kU3RlcChyZXF1ZXN0TG9nSWQsIHN0ZXApO1xuICAgIH1cblxuICAgIGF3YWl0IFJlcXVlc3RMb2dNb2RlbC5maW5pc2hSdW4ocmVxdWVzdExvZ0lkLCBtZWRpYUZpbmlzaEZpZWxkcyhzdWNjZXNzKSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBtZWRpYUxvZ2dlci5lcnJvcihcbiAgICAgIGAke3N1Y2Nlc3Mua2luZH0gcmVxdWVzdCBsb2cgZmFpbGVkOiAke2UgaW5zdGFuY2VvZiBFcnJvciA/IGUubWVzc2FnZSA6IFN0cmluZyhlKX1gLFxuICAgICk7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gZmFpbE1lZGlhUnVuKFxuICByZXF1ZXN0TG9nSWQ6IG51bWJlciB8IHVuZGVmaW5lZCxcbiAgY2F1c2U6IHVua25vd24sXG4gIGFib3J0ZWQ6IGJvb2xlYW4sXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgaWYgKHJlcXVlc3RMb2dJZCA9PT0gdW5kZWZpbmVkKSByZXR1cm47XG5cbiAgdHJ5IHtcbiAgICBhd2FpdCBSZXF1ZXN0TG9nTW9kZWwuZmluaXNoUnVuKHJlcXVlc3RMb2dJZCwge1xuICAgICAgc3RhdHVzOiBhYm9ydGVkID8gXCJhYm9ydGVkXCIgOiBcImVycm9yXCIsXG4gICAgICBlcnJvcl9tZXNzYWdlOiBhYm9ydGVkXG4gICAgICAgID8gXCJjbGllbnQgZGlzY29ubmVjdGVkXCJcbiAgICAgICAgOiBjYXVzZSBpbnN0YW5jZW9mIEVycm9yXG4gICAgICAgICAgPyBjYXVzZS5tZXNzYWdlXG4gICAgICAgICAgOiBTdHJpbmcoY2F1c2UpLFxuICAgIH0pO1xuICB9IGNhdGNoIChlKSB7XG4gICAgbWVkaWFMb2dnZXIuZXJyb3IoYG1lZGlhIHJlcXVlc3QgbG9nIGZhaWxlZDogJHtlIGluc3RhbmNlb2YgRXJyb3IgPyBlLm1lc3NhZ2UgOiBTdHJpbmcoZSl9YCk7XG4gIH1cbn1cblxuLyoqXG4gKiBPbmUgcHJvdmlkZXIgY2FsbCBhZ2FpbnN0IGFuIG9wZW4gbWVkaWEgcnVuLiBBIGZhaWx1cmUgY2xvc2VzIHRoZSBydW4gYXMgZXJyb3IgKG9yIGFib3J0ZWQgb25cbiAqIGNsaWVudCBkaXNjb25uZWN0KSBhbmQgc3VyZmFjZXMgYXMgdGhlIGNhbGxlci1mYWNpbmcgR3JvayBlcnJvcjsgc3VjY2VzcyBsZWF2ZXMgdGhlIHJ1biBvcGVuLlxuICovXG5hc3luYyBmdW5jdGlvbiBkaXNwYXRjaE1lZGlhQ2FsbDxUPihcbiAgcmVxdWVzdExvZ0lkOiBudW1iZXIgfCB1bmRlZmluZWQsXG4gIGNhbGw6IChzaWduYWw6IEFib3J0U2lnbmFsKSA9PiBQcm9taXNlPFQ+LFxuKTogUHJvbWlzZTxUPiB7XG4gIGNvbnN0IGRpc2Nvbm5lY3QgPSBjcmVhdGVIdHRwRGlzY29ubmVjdEhhbmRsZSgpO1xuICBsZXQgcmVzdWx0OiBUO1xuXG4gIHRyeSB7XG4gICAgcmVzdWx0ID0gYXdhaXQgY2FsbChkaXNjb25uZWN0LnNpZ25hbCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBhd2FpdCBmYWlsTWVkaWFSdW4ocmVxdWVzdExvZ0lkLCBlLCBkaXNjb25uZWN0LnNpZ25hbC5hYm9ydGVkKTtcbiAgICB0aHJvd0dyb2tDYWxsZXJFcnJvcihlKTtcbiAgfSBmaW5hbGx5IHtcbiAgICBkaXNjb25uZWN0LmRpc3Bvc2UoKTtcbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59XG5cbnR5cGUgTWVkaWFSdW5Mb2cgPSBPbWl0PE1lZGlhTG9nU3VjY2VzcywgXCJraW5kXCIgfCBcIm1vZGVsXCIgfCBcImR1cmF0aW9uTXNcIj47XG5cbi8qKlxuICogQSBvbmUtc2hvdCBtZWRpYSBlbmRwb2ludDogb3BlbiB0aGUgcnVuLCBtYWtlIHRoZSBwcm92aWRlciBjYWxsLCB0aGVuIGxvZyB0aGUgcmVzdWx0LiBgZGlzcGF0Y2hgXG4gKiByZXR1cm5zIHRoZSBlbmRwb2ludCBvdXRwdXQgYW5kIHdoYXQgdGhlIHJ1biByZWNvcmRzIGFib3V0IGl0LlxuICovXG5hc3luYyBmdW5jdGlvbiBydW5NZWRpYUVuZHBvaW50PFQ+KFxuICBzdGFydDogTWVkaWFMb2dTdGFydCAmIHsgbG9nZ2VyOiBib29sZWFuIHwgdW5kZWZpbmVkIH0sXG4gIGRpc3BhdGNoOiAoXG4gICAgc2lnbmFsOiBBYm9ydFNpZ25hbCxcbiAgICByZXF1ZXN0TG9nSWQ6IG51bWJlciB8IHVuZGVmaW5lZCxcbiAgKSA9PiBQcm9taXNlPHsgb3V0cHV0OiBUOyBsb2c6IE1lZGlhUnVuTG9nIH0+LFxuKTogUHJvbWlzZTxUPiB7XG4gIGNvbnN0IHJlcXVlc3RMb2dJZCA9IGF3YWl0IHN0YXJ0TWVkaWFSdW4oc3RhcnQubG9nZ2VyLCBzdGFydCk7XG4gIGNvbnN0IHN0YXJ0ZWRBdCA9IERhdGUubm93KCk7XG5cbiAgY29uc3QgeyBvdXRwdXQsIGxvZyB9ID0gYXdhaXQgZGlzcGF0Y2hNZWRpYUNhbGwocmVxdWVzdExvZ0lkLCAoc2lnbmFsKSA9PlxuICAgIGRpc3BhdGNoKHNpZ25hbCwgcmVxdWVzdExvZ0lkKSxcbiAgKTtcblxuICBhd2FpdCBmaW5pc2hNZWRpYVJ1bihyZXF1ZXN0TG9nSWQsIHtcbiAgICAuLi5sb2csXG4gICAga2luZDogc3RhcnQua2luZCxcbiAgICBtb2RlbDogc3RhcnQubW9kZWwsXG4gICAgZHVyYXRpb25NczogRGF0ZS5ub3coKSAtIHN0YXJ0ZWRBdCxcbiAgfSk7XG5cbiAgcmV0dXJuIG91dHB1dDtcbn1cblxuLy8gVmlkZW8gam9icyAocGxhbiA1LjcpOiBhbiB1bmd1ZXNzYWJsZSBoYW5kbGUgbWFwcyB0byB0aGUgdG9rZW4gdGhhdCBzdGFydGVkIHRoZSBqb2IuIFBvbGxzIGdvXG4vLyBvbmx5IHRvIHRoYXQgdG9rZW4uIFRoZSBvd25lciBpcyB0aGUgY2FsbGVyIGlkZW50aXR5IHJlcXVlc3QgbG9ncyBhbHJlYWR5IGNhcnJ5IChwcm9qZWN0TmFtZSk7XG4vLyBxZ3JpZCBoYXMgbm8gYXV0aGVudGljYXRlZCBjYWxsZXIgaWQsIHNvIHRoZSAxMjgtYml0IGhhbmRsZSBpcyB0aGUgYWN0dWFsIGNhcGFiaWxpdHkuXG5jb25zdCBWSURFT19KT0JfVFRMX01TID0gMjQgKiA2MCAqIDYwXzAwMDtcbmNvbnN0IFZJREVPX0pPQl9NQVggPSAxMF8wMDA7XG5cbnR5cGUgVmlkZW9Kb2IgPSB7XG4gIHRva2VuSWQ6IG51bWJlcjtcbiAgdG9rZW5OYW1lOiBzdHJpbmc7XG4gIHJlcXVlc3RJZDogc3RyaW5nO1xuICBvd25lcjogc3RyaW5nIHwgbnVsbDtcbiAgbW9kZWw6IHN0cmluZztcbiAgY3JlYXRlZEF0OiBudW1iZXI7XG4gIHJlcXVlc3RMb2dJZD86IG51bWJlcjtcbiAgZmluYWw/OiBWaWRlb1N0YXR1c091dHB1dDtcbn07XG5cbmNvbnN0IHZpZGVvSm9icyA9IG5ldyBNYXA8c3RyaW5nLCBWaWRlb0pvYj4oKTtcblxuZnVuY3Rpb24gcHJ1bmVWaWRlb0pvYnMobm93OiBudW1iZXIpOiB2b2lkIHtcbiAgZm9yIChjb25zdCBbaGFuZGxlLCBqb2JdIG9mIHZpZGVvSm9icykge1xuICAgIGlmIChub3cgLSBqb2IuY3JlYXRlZEF0IDwgVklERU9fSk9CX1RUTF9NUyAmJiB2aWRlb0pvYnMuc2l6ZSA8PSBWSURFT19KT0JfTUFYKSBicmVhaztcbiAgICB2aWRlb0pvYnMuZGVsZXRlKGhhbmRsZSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gdmlkZW9Ub29sQ2FsbElkKGpvYjogUGljazxWaWRlb0pvYiwgXCJyZXF1ZXN0SWRcIj4pOiBzdHJpbmcge1xuICByZXR1cm4gYHZpZGVvX2dlbmVyYXRpb246JHtqb2IucmVxdWVzdElkfWA7XG59XG5cbi8vIFJlc29sdmVzIHRoZSBwZW5kaW5nIHZpZGVvIHN0ZXAgYW5kIGZpbmlzaGVzIHRoZSBydW4uIEJlc3QtZWZmb3J0OiBhIHJ1biBhbHJlYWR5IGV4cGlyZWQgYnlcbi8vIHN0YWxlIGNsZWFudXAgb25seSBsb3NlcyBpdHMgbGF0ZSByZXN1bHQuXG5hc3luYyBmdW5jdGlvbiBmaW5pc2hWaWRlb1J1bihcbiAgam9iOiBWaWRlb0pvYixcbiAgZmluYWw6IFZpZGVvU3RhdHVzT3V0cHV0LFxuICBjb3N0OiBHcm9rTWVkaWFDb3N0IHwgdW5kZWZpbmVkLFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGlmIChqb2IucmVxdWVzdExvZ0lkID09PSB1bmRlZmluZWQpIHJldHVybjtcblxuICB0cnkge1xuICAgIGF3YWl0IFJlcXVlc3RMb2dNb2RlbC5jb250aW51ZVRvb2xSdW4oam9iLnJlcXVlc3RMb2dJZCwgW1xuICAgICAge1xuICAgICAgICB0b29sQ2FsbElkOiB2aWRlb1Rvb2xDYWxsSWQoam9iKSxcbiAgICAgICAgb3V0cHV0OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgc3RhdHVzOiBmaW5hbC5zdGF0dXMsXG4gICAgICAgICAgdXJsOiBmaW5hbC51cmwsXG4gICAgICAgICAgZHVyYXRpb25TZWM6IGZpbmFsLmR1cmF0aW9uU2VjLFxuICAgICAgICAgIGNvc3RJblVzZFRpY2tzOiBmaW5hbC5jb3N0SW5Vc2RUaWNrcyxcbiAgICAgICAgICBlcnJvcjogZmluYWwuZXJyb3IsXG4gICAgICAgIH0pLFxuICAgICAgICBpc0Vycm9yOiBmaW5hbC5zdGF0dXMgPT09IFwiZmFpbGVkXCIsXG4gICAgICB9LFxuICAgIF0pO1xuXG4gICAgY29uc3QgZmllbGRzID0gbWVkaWFGaW5pc2hGaWVsZHMoe1xuICAgICAga2luZDogXCJ2aWRlb1wiLFxuICAgICAgbW9kZWw6IGpvYi5tb2RlbCxcbiAgICAgIHRva2VuTmFtZTogam9iLnRva2VuTmFtZSxcbiAgICAgIGR1cmF0aW9uTXM6IERhdGUubm93KCkgLSBqb2IuY3JlYXRlZEF0LFxuICAgICAgcmVzcG9uc2U6IGZpbmFsLnVybCA/PyBcIlwiLFxuICAgICAgY29zdCxcbiAgICB9KTtcblxuICAgIGF3YWl0IFJlcXVlc3RMb2dNb2RlbC5maW5pc2hSdW4oXG4gICAgICBqb2IucmVxdWVzdExvZ0lkLFxuICAgICAgZmluYWwuc3RhdHVzID09PSBcImRvbmVcIlxuICAgICAgICA/IGZpZWxkc1xuICAgICAgICA6IHsgLi4uZmllbGRzLCBzdGF0dXM6IFwiZXJyb3JcIiwgZXJyb3JfbWVzc2FnZTogZmluYWwuZXJyb3IgPz8gXCJ2aWRlbyBnZW5lcmF0aW9uIGZhaWxlZFwiIH0sXG4gICAgKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIG1lZGlhTG9nZ2VyLmVycm9yKGB2aWRlbyByZXF1ZXN0IGxvZyBmYWlsZWQ6ICR7ZSBpbnN0YW5jZW9mIEVycm9yID8gZS5tZXNzYWdlIDogU3RyaW5nKGUpfWApO1xuICB9XG59XG5cbmNvbnN0IEdST0tfVFRTX0xPR19NT0RFTCA9IFwiZ3Jvay90dHNcIjtcblxuY2xhc3MgUWdyaWRGcmFtZUNsYXNzIGV4dGVuZHMgQmFzZUZyYW1lQ2xhc3Mge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcihcIlFncmlkXCIpO1xuICB9XG5cbiAgQGFwaSh7IGh0dHBNZXRob2Q6IFwiUE9TVFwiLCBjbGllbnRzOiBbXCJheGlvc1wiLCBcInRhbnN0YWNrLW11dGF0aW9uXCJdIH0pXG4gIGFzeW5jIHF1ZXJ5KGFyZ3M6IFF1ZXJ5SW5wdXQpOiBQcm9taXNlPFF1ZXJ5T3V0cHV0PiB7XG4gICAgcmVqZWN0SW52YWxpZEltYWdlUXVlcnkoYXJncyk7XG4gICAgcmVqZWN0SW52YWxpZENhbGxlclNjaGVtYXMoYXJncyk7XG4gICAgY29uc3QgcmVzb2x2ZWRBcmdzID0gYXdhaXQgcmVzb2x2ZVRva2VuTmFtZShhcmdzKTtcbiAgICBjb25zdCBkaXNjb25uZWN0ID0gY3JlYXRlSHR0cERpc2Nvbm5lY3RIYW5kbGUoKTtcblxuICAgIHRyeSB7XG4gICAgICBpZiAocmVzb2x2ZWRBcmdzLmxvZ2dlciA9PT0gZmFsc2UpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXR1cm4gYXdhaXQgUWdyaWREaXNwYXRjaGVyLnF1ZXJ5KHJlc29sdmVkQXJncywgZGlzY29ubmVjdC5zaWduYWwpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgdGhyb3dHcm9rQ2FsbGVyRXJyb3IoZSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3QgeyByZXF1ZXN0TG9nSWQsIHN0ZXBJbmRleCB9ID0gYXdhaXQgYmVmb3JlUXVlcnkocmVzb2x2ZWRBcmdzKTtcbiAgICAgIGxldCByZXN1bHQ6IFF1ZXJ5T3V0cHV0O1xuXG4gICAgICB0cnkge1xuICAgICAgICByZXN1bHQgPSBhd2FpdCBRZ3JpZERpc3BhdGNoZXIucXVlcnkocmVzb2x2ZWRBcmdzLCBkaXNjb25uZWN0LnNpZ25hbCk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnN0IGNvbXBsZXRlZERyaXZlciA9IGNvbXBsZXRlZERyaXZlckZyb21JbWFnZUZhaWx1cmUoZSwgcmVzb2x2ZWRBcmdzLnNlcnZpY2VUaWVyKTtcblxuICAgICAgICBjb25zdCBjb21wbGV0ZWRTdGVwID0gY29tcGxldGVkRHJpdmVyXG4gICAgICAgICAgPyAoW3sgc3RlcEluZGV4LCByZXN1bHQ6IGNvbXBsZXRlZERyaXZlciB9XSBhcyBjb25zdClcbiAgICAgICAgICA6IChbXSBhcyBjb25zdCk7XG5cbiAgICAgICAgaWYgKGRpc2Nvbm5lY3Quc2lnbmFsLmFib3J0ZWQpIHtcbiAgICAgICAgICBhd2FpdCBmaW5pc2hSdW5BYm9ydGVkKHJlcXVlc3RMb2dJZCwgcmVzb2x2ZWRBcmdzLCAuLi5jb21wbGV0ZWRTdGVwKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBhd2FpdCBmaW5pc2hSdW5XaXRoRXJyb3IoXG4gICAgICAgICAgICByZXF1ZXN0TG9nSWQsXG4gICAgICAgICAgICBlIGluc3RhbmNlb2YgRXJyb3IgPyBlLm1lc3NhZ2UgOiBTdHJpbmcoZSksXG4gICAgICAgICAgICByZXNvbHZlZEFyZ3MsXG4gICAgICAgICAgICAuLi5jb21wbGV0ZWRTdGVwLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvd0dyb2tDYWxsZXJFcnJvcihlKTtcbiAgICAgIH1cblxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgbGlmZWN5Y2xlID0gYXdhaXQgYWZ0ZXJRdWVyeShyZXF1ZXN0TG9nSWQsIHN0ZXBJbmRleCwgcmVzb2x2ZWRBcmdzLCByZXN1bHQpO1xuXG4gICAgICAgIGlmIChkaXNjb25uZWN0LnNpZ25hbC5hYm9ydGVkKSB7XG4gICAgICAgICAgYXdhaXQgZmluaXNoUnVuQWJvcnRlZChyZXF1ZXN0TG9nSWQsIHJlc29sdmVkQXJncyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0b29sLWNhbGwgcmVxdWVzdExvZ0lk7JmAIHByb3ZpZGVyIHRocmVhZENvb3Jk64qUIOyEnOuhnCDrj4Xrpr3soIHsnLzroZwg7Jyg7KeA7ZWc64ukLlxuICAgICAgICBjb25zdCB0aHJlYWRDb29yZCA9IHJlc3VsdC5ydW5Db250ZXh0Py50aHJlYWRDb29yZDtcblxuICAgICAgICBjb25zdCBydW5Db250ZXh0ID0gbWVyZ2VSdW5Db250ZXh0KGxpZmVjeWNsZS5ydW5Db250ZXh0LCB0aHJlYWRDb29yZCk7XG5cbiAgICAgICAgcmV0dXJuIHsgLi4ucmVzdWx0LCByZXF1ZXN0TG9nSWQsIHJ1bkNvbnRleHQgfTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgbG9nZ2VyLmVycm9yKGBxdWVyeSBhZnRlclF1ZXJ5IGZhaWxlZDogJHtlIGluc3RhbmNlb2YgRXJyb3IgPyBlLm1lc3NhZ2UgOiBTdHJpbmcoZSl9YCk7XG5cbiAgICAgICAgaWYgKGRpc2Nvbm5lY3Quc2lnbmFsLmFib3J0ZWQpIHtcbiAgICAgICAgICBhd2FpdCBmaW5pc2hSdW5BYm9ydGVkKHJlcXVlc3RMb2dJZCwgcmVzb2x2ZWRBcmdzKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBhd2FpdCBmaW5pc2hSdW5XaXRoRXJyb3IoXG4gICAgICAgICAgICByZXF1ZXN0TG9nSWQsXG4gICAgICAgICAgICBlIGluc3RhbmNlb2YgRXJyb3IgPyBlLm1lc3NhZ2UgOiBTdHJpbmcoZSksXG4gICAgICAgICAgICByZXNvbHZlZEFyZ3MsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHByb3ZpZGVyIOydkeuLteydgCDshLHqs7XtlojsnLzrr4DroZwg66Gc6rmFIOyepeyVoOqwgCDsg53shLEg6rKw6rO866W8IOuNruyWtOyTsOyngCDslYrripTri6QuXG4gICAgICAgIHJldHVybiB7IC4uLnJlc3VsdCwgcmVxdWVzdExvZ0lkIH07XG4gICAgICB9XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGRpc2Nvbm5lY3QuZGlzcG9zZSgpO1xuICAgIH1cbiAgfVxuXG4gIEBhcGkoeyBodHRwTWV0aG9kOiBcIlBPU1RcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1tdXRhdGlvblwiXSB9KVxuICBhc3luYyBwcmVwYXJlU3RyZWFtKGFyZ3M6IFF1ZXJ5SW5wdXQpOiBQcm9taXNlPHsgc3RyZWFtSWQ6IHN0cmluZyB9PiB7XG4gICAgcmVqZWN0SW1hZ2VHZW5lcmF0aW9uU3RyZWFtKGFyZ3MpO1xuICAgIHJlamVjdEludmFsaWRDYWxsZXJTY2hlbWFzKGFyZ3MpO1xuICAgIGNvbnN0IHJlc29sdmVkQXJncyA9IGF3YWl0IHJlc29sdmVUb2tlbk5hbWUoYXJncyk7XG4gICAgY29uc3Qgc3RyZWFtSWQgPSBjcnlwdG8ucmFuZG9tVVVJRCgpO1xuICAgIHBlbmRpbmdTdHJlYW1zLnNldChzdHJlYW1JZCwgcmVzb2x2ZWRBcmdzKTtcbiAgICBjb25zdCBleHBpcnkgPSBzZXRUaW1lb3V0KCgpID0+IHBlbmRpbmdTdHJlYW1zLmRlbGV0ZShzdHJlYW1JZCksIDMwXzAwMCk7XG4gICAgZXhwaXJ5LnVucmVmPy4oKTtcblxuICAgIHJldHVybiB7IHN0cmVhbUlkIH07XG4gIH1cblxuICBAc3RyZWFtKHsgdHlwZTogXCJzc2VcIiwgZXZlbnRzOiBTdHJlYW1FdmVudHMgfSlcbiAgYXN5bmMgcXVlcnlTdHJlYW0oc3RyZWFtSWQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGFyZ3MgPSBwZW5kaW5nU3RyZWFtcy5nZXQoc3RyZWFtSWQpO1xuICAgIHBlbmRpbmdTdHJlYW1zLmRlbGV0ZShzdHJlYW1JZCk7XG5cbiAgICBpZiAoIWFyZ3MpIHRocm93IG5ldyBFcnJvcihcImludmFsaWQgb3IgZXhwaXJlZCBzdHJlYW1JZFwiKTtcbiAgICByZWplY3RJbWFnZUdlbmVyYXRpb25TdHJlYW0oYXJncyk7XG5cbiAgICBjb25zdCBjdHggPSBTb25hbXUuZ2V0Q29udGV4dCgpO1xuICAgIGNvbnN0IHNzZSA9IGN0eC5jcmVhdGVTU0UoU3RyZWFtRXZlbnRzKTtcbiAgICBsZXQgc3RyZWFtUmVzdWx0OiBRdWVyeU91dHB1dCB8IHVuZGVmaW5lZDtcbiAgICBsZXQgc3RyZWFtRXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkO1xuICAgIGxldCBjbGllbnRDbG9zZWQgPSBmYWxzZTtcbiAgICBjb25zdCBhYm9ydENvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG5cbiAgICBzc2Uub25DbG9zZSgoKSA9PiB7XG4gICAgICBjbGllbnRDbG9zZWQgPSB0cnVlO1xuICAgICAgYWJvcnRDb250cm9sbGVyLmFib3J0KCk7XG4gICAgfSk7XG5cbiAgICBsZXQgcnVuSW5mbzogeyByZXF1ZXN0TG9nSWQ6IG51bWJlcjsgc3RlcEluZGV4OiBudW1iZXIgfSB8IHVuZGVmaW5lZDtcblxuICAgIGlmIChhcmdzLmxvZ2dlciAhPT0gZmFsc2UpIHtcbiAgICAgIC8vIHByb3ZpZGVyIOyLpO2WiSDsoIQgcnVubmluZyByb3cg7IOd7ISx7JeQIOyLpO2MqO2VmOuptCBsb2dnZWQg7JqU7LKt7Jy866GcIOynhO2Wie2VmOyngCDslYrripTri6QuXG4gICAgICBydW5JbmZvID0gYXdhaXQgYmVmb3JlUXVlcnkoYXJncyk7XG4gICAgfVxuXG4gICAgLy8gYmVmb3JlUXVlcnkgREIg7J6R7JeFIOykkSBjbG9zZeulvCDrhpPsuZjsp4Ag7JWK6rOgIHByb3ZpZGVyIOyLpO2WiSDsoITsl5Ag66eI6rCQ7ZWc64ukLlxuICAgIGlmIChjbGllbnRDbG9zZWQgfHwgc3NlLmNsb3NlZCkge1xuICAgICAgaWYgKHJ1bkluZm8pIGF3YWl0IGZpbmlzaFJ1bkFib3J0ZWQocnVuSW5mby5yZXF1ZXN0TG9nSWQsIGFyZ3MpO1xuICAgICAgYXdhaXQgc3NlLmVuZCgpO1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IFFncmlkRGlzcGF0Y2hlci5xdWVyeVN0cmVhbShcbiAgICAgICAgYXJncyxcbiAgICAgICAge1xuICAgICAgICAgIG9uRGVsdGE6ICh0ZXh0KSA9PiB7XG4gICAgICAgICAgICBpZiAoIWNsaWVudENsb3NlZCAmJiAhc3NlLmNsb3NlZCkgc3NlLnB1Ymxpc2goXCJkZWx0YVwiLCB7IHRleHQgfSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBvbkNvbXBsZXRlOiAocmVzdWx0KSA9PiB7XG4gICAgICAgICAgICBzdHJlYW1SZXN1bHQgPSByZXN1bHQ7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBvbkVycm9yOiAoZXJyKSA9PiB7XG4gICAgICAgICAgICBzdHJlYW1FcnJvciA9IGVycjtcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICBhYm9ydENvbnRyb2xsZXIuc2lnbmFsLFxuICAgICAgKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBzdHJlYW1FcnJvciA9IGUgaW5zdGFuY2VvZiBFcnJvciA/IGUgOiBuZXcgRXJyb3IoU3RyaW5nKGUpKTtcbiAgICB9XG5cbiAgICAvLyBwcm92aWRlciDqsrDqs7zqsIAg7JeG64qUIGNsb3Nl64qUIOymieyLnCBhYm9ydGVk66GcIOuniOqwkO2VnOuLpC5cbiAgICBpZiAoY2xpZW50Q2xvc2VkICYmICFzdHJlYW1SZXN1bHQpIHtcbiAgICAgIGlmIChydW5JbmZvKSBhd2FpdCBmaW5pc2hSdW5BYm9ydGVkKHJ1bkluZm8ucmVxdWVzdExvZ0lkLCBhcmdzKTtcbiAgICAgIGF3YWl0IHNzZS5lbmQoKTtcblxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIGRpc3BhdGNoZXIg7JmE66OMIO2bhCBsaWZlY3ljbGUg7LKY66asIChhd2FpdCDslYjsoIQpXG4gICAgaWYgKHN0cmVhbVJlc3VsdCkge1xuICAgICAgLy8gZGlzcGF0Y2hlciDqsIAg7Iuk7J2AIHRocmVhZCDsnqzsgqzsmqkg7KKM7ZGc64qUIGxvZ2dlciDshKTsoJXqs7wg66y06rSA7ZWY6rKMIO2ajOyGoe2VnOuLpC5cbiAgICAgIGNvbnN0IHRocmVhZENvb3JkID0gc3RyZWFtUmVzdWx0LnJ1bkNvbnRleHQ/LnRocmVhZENvb3JkO1xuXG4gICAgICBsZXQgcnVuQ29udGV4dDogUWdyaWRSdW5Db250ZXh0IHwgdW5kZWZpbmVkID1cbiAgICAgICAgdGhyZWFkQ29vcmQgPT09IHVuZGVmaW5lZCA/IHVuZGVmaW5lZCA6IHsgdGhyZWFkQ29vcmQgfTtcblxuICAgICAgaWYgKHJ1bkluZm8pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAvLyBjbG9zZSDtm4Qg64+E7LCp7ZWcIOqysOqzvOuPhCBzdGVwL3VzYWdl64qUIOuCqOq4sOuQmCwg7JWE656Y7JeQ7IScIOy1nOyihSBzdGF0dXPrpbwgYWJvcnRlZOuhnCDrja7slrTsk7Tri6QuXG4gICAgICAgICAgY29uc3QgbGlmZWN5Y2xlID0gYXdhaXQgYWZ0ZXJRdWVyeShcbiAgICAgICAgICAgIHJ1bkluZm8ucmVxdWVzdExvZ0lkLFxuICAgICAgICAgICAgcnVuSW5mby5zdGVwSW5kZXgsXG4gICAgICAgICAgICBhcmdzLFxuICAgICAgICAgICAgc3RyZWFtUmVzdWx0LFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBydW5Db250ZXh0ID0gbWVyZ2VSdW5Db250ZXh0KGxpZmVjeWNsZS5ydW5Db250ZXh0LCB0aHJlYWRDb29yZCk7XG5cbiAgICAgICAgICAvLyBhZnRlclF1ZXJ56rCAIOynhO2WieuQmOuKlCDsgqzsnbQgY2xpZW506rCAIOuLq+2ejCDqsr3smrAg7JmE66OMIOyDge2DnOulvCBhYm9ydGVk66GcIOuQmOuPjOumsOuLpC5cbiAgICAgICAgICBpZiAoY2xpZW50Q2xvc2VkKSB7XG4gICAgICAgICAgICBhd2FpdCBmaW5pc2hSdW5BYm9ydGVkKHJ1bkluZm8ucmVxdWVzdExvZ0lkLCBhcmdzKTtcbiAgICAgICAgICAgIGF3YWl0IHNzZS5lbmQoKTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGxvZ2dlci5lcnJvcihgc3RyZWFtIGFmdGVyUXVlcnkgZmFpbGVkOiAke2UgaW5zdGFuY2VvZiBFcnJvciA/IGUubWVzc2FnZSA6IFN0cmluZyhlKX1gKTtcbiAgICAgICAgICBhd2FpdCBmaW5pc2hSdW5XaXRoRXJyb3IoXG4gICAgICAgICAgICBydW5JbmZvLnJlcXVlc3RMb2dJZCxcbiAgICAgICAgICAgIGUgaW5zdGFuY2VvZiBFcnJvciA/IGUubWVzc2FnZSA6IFN0cmluZyhlKSxcbiAgICAgICAgICAgIGFyZ3MsXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIGlmIChjbGllbnRDbG9zZWQpIHtcbiAgICAgICAgICAgIGF3YWl0IGZpbmlzaFJ1bkFib3J0ZWQocnVuSW5mby5yZXF1ZXN0TG9nSWQsIGFyZ3MpO1xuICAgICAgICAgICAgYXdhaXQgc3NlLmVuZCgpO1xuXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmICghY2xpZW50Q2xvc2VkICYmICFzc2UuY2xvc2VkKSB7XG4gICAgICAgIGNvbnN0IGRvbmU6IFF1ZXJ5T3V0cHV0ID0geyAuLi5zdHJlYW1SZXN1bHQgfTtcblxuICAgICAgICBpZiAocnVuSW5mbykgZG9uZS5yZXF1ZXN0TG9nSWQgPSBydW5JbmZvLnJlcXVlc3RMb2dJZDtcbiAgICAgICAgZG9uZS5ydW5Db250ZXh0ID0gcnVuQ29udGV4dDtcbiAgICAgICAgc3NlLnB1Ymxpc2goXCJkb25lXCIsIGRvbmUpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoc3RyZWFtRXJyb3IpIHtcbiAgICAgIGlmIChydW5JbmZvKSBhd2FpdCBmaW5pc2hSdW5XaXRoRXJyb3IocnVuSW5mby5yZXF1ZXN0TG9nSWQsIHN0cmVhbUVycm9yLm1lc3NhZ2UsIGFyZ3MpO1xuXG4gICAgICBpZiAoIWNsaWVudENsb3NlZCAmJiAhc3NlLmNsb3NlZCkgc3NlLnB1Ymxpc2goXCJlcnJvclwiLCB7IG1lc3NhZ2U6IHN0cmVhbUVycm9yLm1lc3NhZ2UgfSk7XG4gICAgfSBlbHNlIGlmICgoY2xpZW50Q2xvc2VkIHx8IHNzZS5jbG9zZWQpICYmIHJ1bkluZm8pIHtcbiAgICAgIGF3YWl0IGZpbmlzaFJ1bkFib3J0ZWQocnVuSW5mby5yZXF1ZXN0TG9nSWQsIGFyZ3MpO1xuICAgIH1cblxuICAgIGF3YWl0IHNzZS5lbmQoKTtcbiAgfVxuXG4gIEBhcGkoeyBodHRwTWV0aG9kOiBcIlBPU1RcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1tdXRhdGlvblwiXSB9KVxuICBhc3luYyBjcmVhdGVSdW4oaW5wdXQ6IENyZWF0ZVJ1bklucHV0KTogUHJvbWlzZTx7IHJlcXVlc3RMb2dJZDogbnVtYmVyIH0+IHtcbiAgICBjb25zdCByZXF1ZXN0TG9nSWQgPSBhd2FpdCBSZXF1ZXN0TG9nTW9kZWwuY3JlYXRlUnVuKHtcbiAgICAgIHVzZXJfcHJvbXB0OiBpbnB1dC51c2VyUHJvbXB0LFxuICAgICAgcmVxdWVzdGVkX21vZGVsX25hbWU6IGlucHV0Lm1vZGVsTmFtZSxcbiAgICAgIGVmZm9ydDogaW5wdXQuZWZmb3J0LFxuICAgICAgcHJvamVjdF9uYW1lOiBpbnB1dC5wcm9qZWN0TmFtZSxcbiAgICAgIHN5c3RlbV9wcm9tcHQ6IGlucHV0LnN5c3RlbVByb21wdCxcbiAgICAgIGhpc3Rvcnk6IGlucHV0Lmhpc3RvcnkgPyBKU09OLnBhcnNlKGlucHV0Lmhpc3RvcnkpIDogdW5kZWZpbmVkLFxuICAgICAgaXNfc3RydWN0dXJlZDogaW5wdXQuaXNTdHJ1Y3R1cmVkLFxuICAgICAganNvbl9zY2hlbWE6IGlucHV0Lmpzb25TY2hlbWEsXG4gICAgfSk7XG5cbiAgICByZXR1cm4geyByZXF1ZXN0TG9nSWQgfTtcbiAgfVxuXG4gIEBhcGkoeyBodHRwTWV0aG9kOiBcIlBPU1RcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1tdXRhdGlvblwiXSB9KVxuICBhc3luYyBhcHBlbmRTdGVwKGlucHV0OiBBcHBlbmRTdGVwSW5wdXQpOiBQcm9taXNlPHsgc3RlcElkOiBudW1iZXIgfT4ge1xuICAgIGNvbnN0IHN0ZXBJZCA9IGF3YWl0IFJlcXVlc3RMb2dNb2RlbC5hcHBlbmRTdGVwKGlucHV0LnJlcXVlc3RMb2dJZCwge1xuICAgICAgc3RlcF9pbmRleDogaW5wdXQuc3RlcEluZGV4LFxuICAgICAgdHlwZTogaW5wdXQudHlwZSxcbiAgICAgIG1vZGVsX25hbWU6IGlucHV0Lm1vZGVsTmFtZSxcbiAgICAgIHJlcXVlc3RlZF9tb2RlbF9uYW1lOiBpbnB1dC5yZXF1ZXN0ZWRNb2RlbE5hbWUsXG4gICAgICBmYWxsYmFja19jb3VudDogaW5wdXQuZmFsbGJhY2tDb3VudCxcbiAgICAgIGlucHV0X3Rva2VuczogaW5wdXQuaW5wdXRUb2tlbnMsXG4gICAgICBvdXRwdXRfdG9rZW5zOiBpbnB1dC5vdXRwdXRUb2tlbnMsXG4gICAgICBjYWNoZV9yZWFkX3Rva2VuczogaW5wdXQuY2FjaGVSZWFkVG9rZW5zLFxuICAgICAgY2FjaGVfY3JlYXRpb25fdG9rZW5zOiBpbnB1dC5jYWNoZUNyZWF0aW9uVG9rZW5zLFxuICAgICAgY2FjaGVfY3JlYXRpb25fNW1fdG9rZW5zOiBpbnB1dC5jYWNoZUNyZWF0aW9uNW1Ub2tlbnMsXG4gICAgICBjYWNoZV9jcmVhdGlvbl8xaF90b2tlbnM6IGlucHV0LmNhY2hlQ3JlYXRpb24xaFRva2VucyxcbiAgICAgIGNvc3RfdXNkOiBpbnB1dC5jb3N0VXNkID09PSB1bmRlZmluZWQgPyB1bmRlZmluZWQgOiBNYXRoLnJvdW5kKGlucHV0LmNvc3RVc2QgKiBNSUNST19VU0QpLFxuICAgICAgY29zdF9zb3VyY2U6IGlucHV0LmNvc3RTb3VyY2UsXG4gICAgICBkdXJhdGlvbl9tczogaW5wdXQuZHVyYXRpb25NcyxcbiAgICAgIHR0ZnRfbXM6IGlucHV0LnR0ZnRNcyA/PyBudWxsLFxuICAgICAgZmluaXNoX3JlYXNvbjogaW5wdXQuZmluaXNoUmVhc29uLFxuICAgICAgcmVhc29uaW5nX3RleHQ6IGlucHV0LnJlYXNvbmluZ1RleHQsXG4gICAgICByZWFzb25pbmdfdG9rZW5zOiBpbnB1dC5yZWFzb25pbmdUb2tlbnMsXG4gICAgICB0b29sX2NhbGxfaW5kZXg6IGlucHV0LnRvb2xDYWxsSW5kZXgsXG4gICAgICB0b29sX2NhbGxfaWQ6IGlucHV0LnRvb2xDYWxsSWQsXG4gICAgICB0b29sX25hbWU6IGlucHV0LnRvb2xOYW1lLFxuICAgICAgdG9vbF9hcmdzOiBpbnB1dC50b29sQXJncyxcbiAgICAgIHRvb2xfcmVzdWx0OiBpbnB1dC50b29sUmVzdWx0LFxuICAgICAgdG9vbF9kdXJhdGlvbl9tczogaW5wdXQudG9vbER1cmF0aW9uTXMsXG4gICAgICBlcnJvcjogaW5wdXQuZXJyb3IsXG4gICAgfSk7XG5cbiAgICByZXR1cm4geyBzdGVwSWQgfTtcbiAgfVxuXG4gIEBhcGkoeyBodHRwTWV0aG9kOiBcIlBPU1RcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1tdXRhdGlvblwiXSB9KVxuICBhc3luYyBmaW5pc2hSdW4oaW5wdXQ6IEZpbmlzaFJ1bklucHV0KTogUHJvbWlzZTx7IG9rOiBib29sZWFuIH0+IHtcbiAgICBhd2FpdCBSZXF1ZXN0TG9nTW9kZWwuZmluaXNoUnVuKGlucHV0LnJlcXVlc3RMb2dJZCwge1xuICAgICAgc3RhdHVzOiBpbnB1dC5zdGF0dXMsXG4gICAgICByZXNwb25zZTogaW5wdXQucmVzcG9uc2UsXG4gICAgICB0b2tlbl9uYW1lOiBpbnB1dC50b2tlbk5hbWUsXG4gICAgICBtb2RlbF9uYW1lOiBpbnB1dC5tb2RlbE5hbWUsXG4gICAgICByZXF1ZXN0ZWRfbW9kZWxfbmFtZTogaW5wdXQucmVxdWVzdGVkTW9kZWxOYW1lLFxuICAgICAgZmFsbGJhY2tfY291bnQ6IGlucHV0LmZhbGxiYWNrQ291bnQsXG4gICAgICBpbnB1dF90b2tlbnM6IGlucHV0LnRvdGFsSW5wdXRUb2tlbnMsXG4gICAgICBvdXRwdXRfdG9rZW5zOiBpbnB1dC50b3RhbE91dHB1dFRva2VucyxcbiAgICAgIGNhY2hlX3JlYWRfdG9rZW5zOiBpbnB1dC50b3RhbENhY2hlUmVhZFRva2VucyxcbiAgICAgIGNhY2hlX2NyZWF0aW9uX3Rva2VuczogaW5wdXQudG90YWxDYWNoZUNyZWF0aW9uVG9rZW5zLFxuICAgICAgY2FjaGVfY3JlYXRpb25fNW1fdG9rZW5zOiBpbnB1dC50b3RhbENhY2hlQ3JlYXRpb241bVRva2VucyxcbiAgICAgIGNhY2hlX2NyZWF0aW9uXzFoX3Rva2VuczogaW5wdXQudG90YWxDYWNoZUNyZWF0aW9uMWhUb2tlbnMsXG4gICAgICBjb3N0X3VzZDogaW5wdXQuY29zdFVzZCA9PT0gdW5kZWZpbmVkID8gdW5kZWZpbmVkIDogTWF0aC5yb3VuZChpbnB1dC5jb3N0VXNkICogTUlDUk9fVVNEKSxcbiAgICAgIGNvc3Rfc291cmNlOiBpbnB1dC5jb3N0U291cmNlLFxuICAgICAgZHVyYXRpb25fbXM6IGlucHV0LnRvdGFsRHVyYXRpb25NcyxcbiAgICAgIGhpc3Rvcnk6IGlucHV0Lmhpc3RvcnkgPyBKU09OLnBhcnNlKGlucHV0Lmhpc3RvcnkpIDogdW5kZWZpbmVkLFxuICAgICAgZXJyb3JfbWVzc2FnZTogaW5wdXQuZXJyb3JNZXNzYWdlLFxuICAgICAgcmVzcG9uc2VfanNvbl9vazogaW5wdXQucmVzcG9uc2VKc29uT2ssXG4gICAgfSk7XG5cbiAgICByZXR1cm4geyBvazogdHJ1ZSB9O1xuICB9XG5cbiAgQGFwaSh7IGh0dHBNZXRob2Q6IFwiR0VUXCIsIGNsaWVudHM6IFtcImF4aW9zXCIsIFwidGFuc3RhY2stcXVlcnlcIl0gfSlcbiAgYXN5bmMgc3RhdHMoKTogUHJvbWlzZTxUb2tlblN0YXRzW10+IHtcbiAgICByZXR1cm4gUWdyaWREaXNwYXRjaGVyLmdldFN0YXRzKCk7XG4gIH1cblxuICAvLyDtmZTrqbTsnZgg66qp66GdIO2VhO2EsOulvCDqt7jrjIDroZwg67Cb7JWEIOqwmeydgCDsobDqsbTsnZgg7ZWp6rOE66W8IOuPjOugpOykgOuLpCDigJQg66qp66Gd6rO8IOu5hOyaqeydtFxuICAvLyDshJzroZwg64uk66W4IOuqqOyImOulvCDrs7TrqbQg7IKs7Jqp7J6Q7JeQ6rKM64qUIOyIq+yekOqwgCDslrTquIvrgpwg6rKD7Jy866GcIOydve2ejOuLpC5cbiAgQGFwaSh7IGh0dHBNZXRob2Q6IFwiR0VUXCIsIGNsaWVudHM6IFtcImF4aW9zXCIsIFwidGFuc3RhY2stcXVlcnlcIl0gfSlcbiAgYXN5bmMgdG90YWxDb3N0KFxuICAgIHBhcmFtcz86IFJlcXVlc3RMb2dMaXN0UGFyYW1zLFxuICApOiBQcm9taXNlPHsgdXNkOiBudW1iZXI7IHVua25vd25JbWFnZUNvc3RDb3VudDogbnVtYmVyOyB1bmtub3duQ29zdENvdW50OiBudW1iZXIgfT4ge1xuICAgIHJldHVybiBSZXF1ZXN0TG9nTW9kZWwudG90YWxDb3N0KHBhcmFtcyk7XG4gIH1cblxuICBAYXBpKHsgaHR0cE1ldGhvZDogXCJHRVRcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1xdWVyeVwiXSB9KVxuICBhc3luYyBwcm9qZWN0TmFtZXMoKTogUHJvbWlzZTx7IG5hbWVzOiBzdHJpbmdbXSB9PiB7XG4gICAgcmV0dXJuIHsgbmFtZXM6IGF3YWl0IFJlcXVlc3RMb2dNb2RlbC5kaXN0aW5jdFByb2plY3ROYW1lcygpIH07XG4gIH1cblxuICBAYXBpKHsgaHR0cE1ldGhvZDogXCJHRVRcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1xdWVyeVwiXSB9KVxuICBhc3luYyBtb2RlbE5hbWVzKCk6IFByb21pc2U8eyBuYW1lczogc3RyaW5nW10gfT4ge1xuICAgIHJldHVybiB7IG5hbWVzOiBhd2FpdCBSZXF1ZXN0TG9nTW9kZWwuZGlzdGluY3RNb2RlbE5hbWVzKCkgfTtcbiAgfVxuXG4gIEBhcGkoeyBodHRwTWV0aG9kOiBcIlBPU1RcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1tdXRhdGlvblwiXSB9KVxuICBhc3luYyBhZGRUb2tlbihcbiAgICBwcm92aWRlcjogc3RyaW5nLFxuICAgIGNyZWRlbnRpYWxzOiBUb2tlbkNyZWRlbnRpYWxzLFxuICAgIG5hbWU6IHN0cmluZyxcbiAgKTogUHJvbWlzZTx7IGFkZGVkOiBib29sZWFuIH0+IHtcbiAgICBhd2FpdCBUb2tlbk1vZGVsLnNhdmUoW1xuICAgICAge1xuICAgICAgICBwcm92aWRlcixcbiAgICAgICAgY3JlZGVudGlhbHMsXG4gICAgICAgIG5hbWUsXG4gICAgICB9LFxuICAgIF0pO1xuXG4gICAgcmV0dXJuIHsgYWRkZWQ6IHRydWUgfTtcbiAgfVxuXG4gIEBhcGkoeyBodHRwTWV0aG9kOiBcIlBPU1RcIiwgY2xpZW50czogW1wiYXhpb3NcIl0gfSlcbiAgYXN5bmMgdXBkYXRlVG9rZW4oXG4gICAgaWQ6IG51bWJlcixcbiAgICBuYW1lPzogc3RyaW5nLFxuICAgIHF1b3RhVGhyZXNob2xkPzogbnVtYmVyIHwgbnVsbCxcbiAgICB3ZWlnaHQ/OiBudW1iZXIsXG4gICAga2VlcGFsaXZlRW5hYmxlZD86IGJvb2xlYW4sXG4gICk6IFByb21pc2U8eyB1cGRhdGVkOiBib29sZWFuIH0+IHtcbiAgICBpZiAoXG4gICAgICBxdW90YVRocmVzaG9sZCAhPT0gdW5kZWZpbmVkICYmXG4gICAgICBxdW90YVRocmVzaG9sZCAhPT0gbnVsbCAmJlxuICAgICAgKCFOdW1iZXIuaXNJbnRlZ2VyKHF1b3RhVGhyZXNob2xkKSB8fCBxdW90YVRocmVzaG9sZCA8IDEgfHwgcXVvdGFUaHJlc2hvbGQgPiAxMDApXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihcbiAgICAgICAgU0QoXCJlcnJvci5kZXRhaWxcIikoXCJxdW90YVRocmVzaG9sZCBtdXN0IGJlIGFuIGludGVnZXIgYmV0d2VlbiAxIGFuZCAxMDAsIG9yIG51bGxcIiksXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmICh3ZWlnaHQgIT09IHVuZGVmaW5lZCAmJiAoIU51bWJlci5pc0ludGVnZXIod2VpZ2h0KSB8fCB3ZWlnaHQgPCAxIHx8IHdlaWdodCA+IDEwMCkpIHtcbiAgICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKFxuICAgICAgICBTRChcImVycm9yLmRldGFpbFwiKShcIndlaWdodCBtdXN0IGJlIGFuIGludGVnZXIgYmV0d2VlbiAxIGFuZCAxMDBcIiksXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHBhdGNoOiBUb2tlblVwZGF0ZUZpZWxkcyA9IHt9O1xuXG4gICAgaWYgKG5hbWUgIT09IHVuZGVmaW5lZCkgcGF0Y2gubmFtZSA9IG5hbWU7XG5cbiAgICBpZiAocXVvdGFUaHJlc2hvbGQgIT09IHVuZGVmaW5lZCkgcGF0Y2gucXVvdGFfdGhyZXNob2xkID0gcXVvdGFUaHJlc2hvbGQ7XG5cbiAgICBpZiAod2VpZ2h0ICE9PSB1bmRlZmluZWQpIHBhdGNoLndlaWdodCA9IHdlaWdodDtcblxuICAgIGlmIChrZWVwYWxpdmVFbmFibGVkICE9PSB1bmRlZmluZWQpIHBhdGNoLmtlZXBhbGl2ZV9lbmFibGVkID0ga2VlcGFsaXZlRW5hYmxlZDtcblxuICAgIGlmIChPYmplY3Qua2V5cyhwYXRjaCkubGVuZ3RoID09PSAwKSByZXR1cm4geyB1cGRhdGVkOiBmYWxzZSB9O1xuXG4gICAgY29uc3QgdXBkYXRlZCA9IGF3YWl0IFRva2VuTW9kZWwudXBkYXRlRmllbGRzKGlkLCBwYXRjaCk7XG5cbiAgICByZXR1cm4geyB1cGRhdGVkOiB1cGRhdGVkID4gMCB9O1xuICB9XG5cbiAgQGFwaSh7IGh0dHBNZXRob2Q6IFwiUE9TVFwiLCBjbGllbnRzOiBbXCJheGlvc1wiLCBcInRhbnN0YWNrLW11dGF0aW9uXCJdIH0pXG4gIGFzeW5jIHJlbW92ZVRva2VuKGlkOiBudW1iZXIpOiBQcm9taXNlPHsgcmVtb3ZlZDogYm9vbGVhbiB9PiB7XG4gICAgY29uc3QgZW50cnkgPSBhd2FpdCBUb2tlbk1vZGVsLmZpbmRPbmUoXCJBXCIsIHsgaWQgfSk7XG5cbiAgICBpZiAoIWVudHJ5KSByZXR1cm4geyByZW1vdmVkOiBmYWxzZSB9O1xuICAgIGF3YWl0IFRva2VuTW9kZWwuZGVsKFtlbnRyeS5pZF0pO1xuXG4gICAgcmV0dXJuIHsgcmVtb3ZlZDogdHJ1ZSB9O1xuICB9XG5cbiAgLyoqXG4gICAqIO2GoO2BsCDtmZzshLHtmZQv67mE7Zmc7ISx7ZmUIO2GoOq4gCBEQuydmCBhY3RpdmUg7ZWE65OcIOyXheuNsOydtO2KuFxuICAgKi9cbiAgQGFwaSh7IGh0dHBNZXRob2Q6IFwiUE9TVFwiLCBjbGllbnRzOiBbXCJheGlvc1wiLCBcInRhbnN0YWNrLW11dGF0aW9uXCJdIH0pXG4gIGFzeW5jIHRvZ2dsZVRva2VuKGlkOiBudW1iZXIpOiBQcm9taXNlPHsgYWN0aXZlOiBib29sZWFuIH0+IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBUb2tlbk1vZGVsLnRvZ2dsZUFjdGl2ZShpZCk7XG5cbiAgICBpZiAoIXJlc3VsdCkgcmV0dXJuIHsgYWN0aXZlOiBmYWxzZSB9O1xuXG4gICAgaWYgKHJlc3VsdC5yZWF1dGhSZXF1aXJlZCkge1xuICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oU0QoXCJlcnJvci5kZXRhaWxcIikoXCJSZS1sb2dpbiByZXF1aXJlZFwiKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgYWN0aXZlOiByZXN1bHQuYWN0aXZlIH07XG4gIH1cblxuICBAYXBpKHsgaHR0cE1ldGhvZDogXCJQT1NUXCIsIGNsaWVudHM6IFtcImF4aW9zXCIsIFwidGFuc3RhY2stbXV0YXRpb25cIl0gfSlcbiAgYXN5bmMgb2F1dGhTdGFydChuYW1lOiBzdHJpbmcpOiBQcm9taXNlPE9BdXRoU3RhcnRSZXN1bHQ+IHtcbiAgICBjb25zdCB7IGNvZGVWZXJpZmllciwgY29kZUNoYWxsZW5nZSwgc3RhdGUgfSA9IGdlbmVyYXRlUEtDRSgpO1xuXG4gICAgY29uc3QgeyByZWRpcmVjdFVyaSwgbW9kZSB9ID0gcmVzb2x2ZU9BdXRoUmVkaXJlY3QoKTtcbiAgICBjb25zdCBhdXRoVXJsID0gYnVpbGRBdXRoVXJsKGNvZGVDaGFsbGVuZ2UsIHN0YXRlLCByZWRpcmVjdFVyaSk7XG5cbiAgICBhd2FpdCBzZXRPQXV0aFN0YXRlKHN0YXRlLCB7IGNvZGVWZXJpZmllciwgbmFtZSwgcmVkaXJlY3RVcmksIHByb3ZpZGVyOiBcImFudGhyb3BpY1wiIH0pO1xuXG4gICAgcmV0dXJuIHsgYXV0aFVybCwgbW9kZSB9O1xuICB9XG5cbiAgLy8g7JuQ6rKpIOygkeyGjeydmCDsiJjrj5kg7JmE66OMOiBBbnRocm9waWMgYGNvZGUjc3RhdGVgIOuYkOuKlCBPcGVuQUkgY2FsbGJhY2sgVVJM7J2EIOuwm+yVhCDqtZDtmZjtlZzri6QuXG4gIEBhcGkoeyBodHRwTWV0aG9kOiBcIlBPU1RcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1tdXRhdGlvblwiXSB9KVxuICBhc3luYyBvYXV0aENvbXBsZXRlKHBhc3RlZENvZGU6IHN0cmluZyk6IFByb21pc2U8eyBhZGRlZDogYm9vbGVhbjsgbmFtZTogc3RyaW5nIH0+IHtcbiAgICBjb25zdCByZXN1bHQgPSBwYXJzZVBhc3RlZE9BdXRoUmVzdWx0KHBhc3RlZENvZGUpO1xuXG4gICAgaWYgKCFyZXN1bHQpIHtcbiAgICAgIC8vIEdyb2sgYWNjZXB0cyBhIGJhcmUgYXV0aG9yaXphdGlvbiBjb2RlLCB3aGljaCBjYXJyaWVzIG5vIHN0YXRlIChncm9rLWJ1aWxkIGxvZ2luLnJzKS5cbiAgICAgIGNvbnN0IGdyb2tTdGF0ZSA9IGF3YWl0IGdldEdyb2tMYXRlc3RTdGF0ZSgpO1xuICAgICAgY29uc3QgZ3Jva1BlbmRpbmcgPSBncm9rU3RhdGUgPyBhd2FpdCBnZXRPQXV0aFN0YXRlKGdyb2tTdGF0ZSkgOiB1bmRlZmluZWQ7XG5cbiAgICAgIGlmIChncm9rU3RhdGUgJiYgZ3Jva1BlbmRpbmc/LnByb3ZpZGVyID09PSBcImdyb2tcIiAmJiBwYXN0ZWRDb2RlLnRyaW0oKSkge1xuICAgICAgICBhd2FpdCBkZWxldGVPQXV0aFN0YXRlKGdyb2tTdGF0ZSk7XG4gICAgICAgIGF3YWl0IHRoaXMuY29tcGxldGVHcm9rTG9naW4ocGFzdGVkQ29kZSwgZ3Jva1N0YXRlLCBncm9rUGVuZGluZyk7XG5cbiAgICAgICAgcmV0dXJuIHsgYWRkZWQ6IHRydWUsIG5hbWU6IGdyb2tQZW5kaW5nLm5hbWUgfTtcbiAgICAgIH1cblxuICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oXG4gICAgICAgIFNEKFwiZXJyb3IuZGV0YWlsXCIpKFxuICAgICAgICAgIFwiZXhwZWN0ZWQgdGhlIGNhbGxiYWNrIFVSTCBvciBjb2RlIHNob3duIGFmdGVyIGxvZ2luLCBpbiBjb2RlI3N0YXRlIGZvcm1cIixcbiAgICAgICAgKSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgeyBjb2RlLCBzdGF0ZSB9ID0gcmVzdWx0O1xuXG4gICAgY29uc3QgcGVuZGluZyA9IGF3YWl0IGdldE9BdXRoU3RhdGUoc3RhdGUpO1xuXG4gICAgaWYgKCFwZW5kaW5nKSB7XG4gICAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihcbiAgICAgICAgU0QoXCJlcnJvci5kZXRhaWxcIikoXCJsb2dpbiBzZXNzaW9uIG5vdCBmb3VuZCBvciBleHBpcmVkIOKAlCBzdGFydCB0aGUgbG9naW4gYWdhaW5cIiksXG4gICAgICApO1xuICAgIH1cblxuICAgIGF3YWl0IGRlbGV0ZU9BdXRoU3RhdGUoc3RhdGUpO1xuXG4gICAgaWYgKHBlbmRpbmcucHJvdmlkZXIgPT09IFwib3BlbmFpXCIpIHtcbiAgICAgIGF3YWl0IHRoaXMuY29tcGxldGVPcGVuQUlMb2dpbihjb2RlLCBwZW5kaW5nKTtcbiAgICB9IGVsc2UgaWYgKHBlbmRpbmcucHJvdmlkZXIgPT09IFwiZ3Jva1wiKSB7XG4gICAgICAvLyBjb21wbGV0ZUdyb2tPQXV0aCByZS1jaGVja3MgdGhlIHBhc3RlZCBVUkwncyBzdGF0ZSBhZ2FpbnN0IHRoZSBzdG9yZWQgb25lLlxuICAgICAgYXdhaXQgdGhpcy5jb21wbGV0ZUdyb2tMb2dpbihwYXN0ZWRDb2RlLCBzdGF0ZSwgcGVuZGluZyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGF3YWl0IHRoaXMuY29tcGxldGVBbnRocm9waWNMb2dpbihjb2RlLCBzdGF0ZSwgcGVuZGluZyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgYWRkZWQ6IHRydWUsIG5hbWU6IHBlbmRpbmcubmFtZSB9O1xuICB9XG5cbiAgLy8g6rWQ7ZmYICsg6rOE7KCVIOykkeuztSDsoJzqsbAgKyDsoIDsnqUg4oCUIHJlZGlyZWN0IOy9nOuwseqzvCDsvZTrk5wg67aZ7Jes64Sj6riwIO2UjOuhnOyasOqwgCDqs7XsnKDtlZzri6QuXG4gIGFzeW5jIGNvbXBsZXRlQW50aHJvcGljTG9naW4oY29kZTogc3RyaW5nLCBzdGF0ZTogc3RyaW5nLCBwZW5kaW5nOiBQZW5kaW5nT0F1dGgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB0b2tlbnMgPSBhd2FpdCBleGNoYW5nZUNvZGVGb3JUb2tlbnMoXG4gICAgICBjb2RlLFxuICAgICAgcGVuZGluZy5jb2RlVmVyaWZpZXIsXG4gICAgICBzdGF0ZSxcbiAgICAgIHBlbmRpbmcucmVkaXJlY3RVcmksXG4gICAgKTtcblxuICAgIGF3YWl0IFRva2VuTW9kZWwucmVwbGFjZUJ5QWNjb3VudChcImFudGhyb3BpY1wiLCB0b2tlbnMuYWNjb3VudFV1aWQsIHtcbiAgICAgIHByb3ZpZGVyOiBcImFudGhyb3BpY1wiLFxuICAgICAgY3JlZGVudGlhbHM6IHtcbiAgICAgICAgYWNjZXNzVG9rZW46IHRva2Vucy5hY2Nlc3NUb2tlbixcbiAgICAgICAgcmVmcmVzaFRva2VuOiB0b2tlbnMucmVmcmVzaFRva2VuLFxuICAgICAgICBleHBpcmVzQXQ6IHRva2Vucy5leHBpcmVzQXQgPz8gMCxcbiAgICAgICAgYWNjb3VudFV1aWQ6IHRva2Vucy5hY2NvdW50VXVpZCA/PyBcIlwiLFxuICAgICAgfSxcbiAgICAgIG5hbWU6IHBlbmRpbmcubmFtZSxcbiAgICB9KTtcblxuICAgIG5vdGlmeVRva2VuQWRkZWQocGVuZGluZy5uYW1lLCBcImFudGhyb3BpY1wiKTtcbiAgfVxuXG4gIGFzeW5jIGNvbXBsZXRlT3BlbkFJTG9naW4oY29kZTogc3RyaW5nLCBwZW5kaW5nOiBQZW5kaW5nT0F1dGgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBjcmVkcyA9IGF3YWl0IGV4Y2hhbmdlT3BlbkFJQ29kZShjb2RlLCBwZW5kaW5nLmNvZGVWZXJpZmllciwgcGVuZGluZy5yZWRpcmVjdFVyaSk7XG4gICAgYXdhaXQgVG9rZW5Nb2RlbC5yZXBsYWNlQnlBY2NvdW50KFwib3BlbmFpXCIsIGNyZWRzLmFjY291bnRJZCwge1xuICAgICAgcHJvdmlkZXI6IFwib3BlbmFpXCIsXG4gICAgICBjcmVkZW50aWFsczogY3JlZHMsXG4gICAgICBuYW1lOiBwZW5kaW5nLm5hbWUsXG4gICAgfSk7XG4gICAgbG9nZ2VyLmluZm8oYE9wZW5BSSB0b2tlbiBzYXZlZCBmb3IgJHtwZW5kaW5nLm5hbWV9YCk7XG4gICAgbm90aWZ5VG9rZW5BZGRlZChwZW5kaW5nLm5hbWUsIFwib3BlbmFpXCIpO1xuICB9XG5cbiAgYXN5bmMgY29tcGxldGVHcm9rTG9naW4oY29kZU9yVXJsOiBzdHJpbmcsIHN0YXRlOiBzdHJpbmcsIHBlbmRpbmc6IFBlbmRpbmdPQXV0aCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGxldCBjcmVkZW50aWFsczogU3RyaWN0R3Jva0NyZWRlbnRpYWxzO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNyZWRlbnRpYWxzID0gYXdhaXQgY29tcGxldGVHcm9rT0F1dGgoe1xuICAgICAgICBjb2RlT3JVcmwsXG4gICAgICAgIHZlcmlmaWVyOiBwZW5kaW5nLmNvZGVWZXJpZmllcixcbiAgICAgICAgcmVkaXJlY3RVcmk6IHBlbmRpbmcucmVkaXJlY3RVcmksXG4gICAgICAgIHN0YXRlLFxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGdyb2tPQXV0aEJhZFJlcXVlc3QoZXJyb3IpO1xuICAgIH1cblxuICAgIGF3YWl0IHRoaXMuc2F2ZUdyb2tUb2tlbihjcmVkZW50aWFscywgcGVuZGluZy5uYW1lKTtcbiAgfVxuXG4gIC8vIFJlZ2lzdHJhdGlvbiByZWplY3RzIGFueXRoaW5nIHRoYXQgaXMgbm90IGFuIHhBSSBPQXV0aCBhdCtqd3QgKEFQSSBrZXlzLCBvcGFxdWUgdG9rZW5zKS5cbiAgYXN5bmMgc2F2ZUdyb2tUb2tlbihjYW5kaWRhdGU6IFN0cmljdEdyb2tDcmVkZW50aWFscywgbmFtZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgcGFyc2VkID0gU3RyaWN0R3Jva0NyZWRlbnRpYWxzLnNhZmVQYXJzZShjYW5kaWRhdGUpO1xuXG4gICAgaWYgKCFwYXJzZWQuc3VjY2Vzcykge1xuICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oU0QoXCJxZ3JpZC5ncm9rTm90T0F1dGhUb2tlblwiKSk7XG4gICAgfVxuXG4gICAgYXdhaXQgVG9rZW5Nb2RlbC5yZXBsYWNlQnlBY2NvdW50KFwiZ3Jva1wiLCBwYXJzZWQuZGF0YS51c2VySWQsIHtcbiAgICAgIHByb3ZpZGVyOiBcImdyb2tcIixcbiAgICAgIGNyZWRlbnRpYWxzOiBwYXJzZWQuZGF0YSxcbiAgICAgIG5hbWUsXG4gICAgfSk7XG4gICAgbG9nZ2VyLmluZm8oYEdyb2sgdG9rZW4gc2F2ZWQgZm9yICR7bmFtZX1gKTtcbiAgICBub3RpZnlUb2tlbkFkZGVkKG5hbWUsIFwiZ3Jva1wiKTtcbiAgfVxuXG4gIGFzeW5jIGhhbmRsZU9BdXRoQ2FsbGJhY2soY29kZTogc3RyaW5nLCBzdGF0ZTogc3RyaW5nLCByZXBseTogRmFzdGlmeVJlcGx5KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgcGVuZGluZyA9IGF3YWl0IGdldE9BdXRoU3RhdGUoc3RhdGUpO1xuXG4gICAgaWYgKCFwZW5kaW5nKSB7XG4gICAgICBsb2dnZXIud2FybihcIm9hdXRoIGNhbGxiYWNrOiBpbnZhbGlkX3N0YXRlXCIpO1xuXG4gICAgICByZXR1cm4gcmVwbHkucmVkaXJlY3QoXCIvP29hdXRoPWVycm9yJnJlYXNvbj1pbnZhbGlkX3N0YXRlXCIpO1xuICAgIH1cblxuICAgIGF3YWl0IGRlbGV0ZU9BdXRoU3RhdGUoc3RhdGUpO1xuXG4gICAgdHJ5IHtcbiAgICAgIGlmIChwZW5kaW5nLnByb3ZpZGVyID09PSBcIm9wZW5haVwiKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuY29tcGxldGVPcGVuQUlMb2dpbihjb2RlLCBwZW5kaW5nKTtcbiAgICAgIH0gZWxzZSBpZiAocGVuZGluZy5wcm92aWRlciA9PT0gXCJncm9rXCIpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5jb21wbGV0ZUdyb2tMb2dpbihjb2RlLCBzdGF0ZSwgcGVuZGluZyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhd2FpdCB0aGlzLmNvbXBsZXRlQW50aHJvcGljTG9naW4oY29kZSwgc3RhdGUsIHBlbmRpbmcpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmVwbHkucmVkaXJlY3QoYC8/b2F1dGg9c3VjY2VzcyZuYW1lPSR7ZW5jb2RlVVJJQ29tcG9uZW50KHBlbmRpbmcubmFtZSl9YCk7XG4gICAgfSBjYXRjaCB7XG4gICAgICBsb2dnZXIud2FybihcIm9hdXRoIGNhbGxiYWNrIGZhaWxlZFwiLCB7XG4gICAgICAgIHByb3ZpZGVyOiBwZW5kaW5nLnByb3ZpZGVyLFxuICAgICAgICByZWFzb246IFwiZXhjaGFuZ2VfZmFpbGVkXCIsXG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIHJlcGx5LnJlZGlyZWN0KFwiLz9vYXV0aD1lcnJvciZyZWFzb249ZXhjaGFuZ2VfZmFpbGVkXCIpO1xuICAgIH1cbiAgfVxuXG4gIEBhcGkoeyBodHRwTWV0aG9kOiBcIlBPU1RcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1tdXRhdGlvblwiXSB9KVxuICBhc3luYyBvYXV0aFN0YXJ0T3BlbkFJKG5hbWU6IHN0cmluZyk6IFByb21pc2U8T0F1dGhTdGFydFJlc3VsdD4ge1xuICAgIGNvbnN0IHsgY29kZVZlcmlmaWVyLCBjb2RlQ2hhbGxlbmdlLCBzdGF0ZSB9ID0gZ2VuZXJhdGVPcGVuQUlQS0NFKCk7XG4gICAgY29uc3QgbW9kZSA9IGlzUmVtb3RlT0F1dGhSZXF1ZXN0KCkgPyBcImNvZGVcIiA6IFwicmVkaXJlY3RcIjtcbiAgICBsZXQgcmVkaXJlY3RVcmk6IHN0cmluZztcblxuICAgIGlmIChtb2RlID09PSBcImNvZGVcIikge1xuICAgICAgLy8gT3BlbkFJIGFjY2VwdHMgb25seSB0aGUgQ29kZXggQ0xJJ3MgcmVnaXN0ZXJlZCBsb29wYmFjayBVUkkuIE9uIGEgcmVtb3RlIGRhc2hib2FyZCB0aGVcbiAgICAgIC8vIGJyb3dzZXIgY2Fubm90IHJlYWNoIHRoZSBzZXJ2ZXIncyBsb29wYmFjaywgc28gdGhlIHVzZXIgcGFzdGVzIHRoZSByZXN1bHRpbmcgY2FsbGJhY2sgVVJMLlxuICAgICAgcmVkaXJlY3RVcmkgPSBvcGVuQUlDYWxsYmFja1JlZGlyZWN0VXJpKE9QRU5BSV9DQUxMQkFDS19QT1JUU1swXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJlZGlyZWN0VXJpID0gYXdhaXQgc3RhcnRPcGVuQUlDYWxsYmFja1JlbGF5KHRydXN0ZWRMb29wYmFja0Jhc2UoKSwgT0FVVEhfU1RBVEVfVFRMX01TKTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihcbiAgICAgICAgICBTRChcImVycm9yLmRldGFpbFwiKShcbiAgICAgICAgICAgIGBPcGVuQUkgbG9naW4gbmVlZHMgbG9jYWwgcG9ydCAke09QRU5BSV9DQUxMQkFDS19QT1JUUy5qb2luKFwiIG9yIFwiKX0g4oCUIGNsb3NlIGFueSBydW5uaW5nIFxcYGNvZGV4IGxvZ2luXFxgIGFuZCByZXRyeWAsXG4gICAgICAgICAgKSxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBhdXRoVXJsID0gYnVpbGRPcGVuQUlBdXRoVXJsKGNvZGVDaGFsbGVuZ2UsIHN0YXRlLCByZWRpcmVjdFVyaSk7XG4gICAgYXdhaXQgc2V0T0F1dGhTdGF0ZShzdGF0ZSwgeyBjb2RlVmVyaWZpZXIsIG5hbWUsIHJlZGlyZWN0VXJpLCBwcm92aWRlcjogXCJvcGVuYWlcIiB9KTtcblxuICAgIHJldHVybiB7IGF1dGhVcmwsIG1vZGUgfTtcbiAgfVxuXG4gIC8vIEdyb2sncyByZWdpc3RlcmVkIHJlZGlyZWN0IGlzIGEgcmFuZG9tIDEyNy4wLjAuMSBsb29wYmFjayBwb3J0IHRoYXQgcWdyaWQgZG9lcyBub3Qgc2VydmUsIHNvXG4gIC8vIHRoZSB1c2VyIGFsd2F5cyBwYXN0ZXMgdGhlIHJlc3VsdGluZyBjYWxsYmFjayBVUkwgKG9yIHRoZSBiYXJlIGNvZGUpIGludG8gb2F1dGhDb21wbGV0ZS5cbiAgQGFwaSh7IGh0dHBNZXRob2Q6IFwiUE9TVFwiLCBjbGllbnRzOiBbXCJheGlvc1wiLCBcInRhbnN0YWNrLW11dGF0aW9uXCJdIH0pXG4gIGFzeW5jIG9hdXRoU3RhcnRHcm9rKG5hbWU6IHN0cmluZyk6IFByb21pc2U8T0F1dGhTdGFydFJlc3VsdD4ge1xuICAgIGNvbnN0IHN0YXRlID0gY3J5cHRvLnJhbmRvbUJ5dGVzKDMyKS50b1N0cmluZyhcImJhc2U2NHVybFwiKTtcbiAgICBsZXQgc3RhcnRlZDtcblxuICAgIHRyeSB7XG4gICAgICBzdGFydGVkID0gYXdhaXQgc3RhcnRHcm9rT0F1dGgoeyBzdGF0ZSB9KTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgZ3Jva09BdXRoQmFkUmVxdWVzdChlcnJvcik7XG4gICAgfVxuXG4gICAgYXdhaXQgc2V0T0F1dGhTdGF0ZShzdGF0ZSwge1xuICAgICAgY29kZVZlcmlmaWVyOiBzdGFydGVkLnZlcmlmaWVyLFxuICAgICAgbmFtZSxcbiAgICAgIHJlZGlyZWN0VXJpOiBzdGFydGVkLnJlZGlyZWN0VXJpLFxuICAgICAgcHJvdmlkZXI6IFwiZ3Jva1wiLFxuICAgIH0pO1xuICAgIGF3YWl0IHNldEdyb2tMYXRlc3RTdGF0ZShzdGF0ZSk7XG5cbiAgICByZXR1cm4geyBhdXRoVXJsOiBzdGFydGVkLmF1dGhvcml6ZVVybCwgbW9kZTogXCJjb2RlXCIgfTtcbiAgfVxuXG4gIEBhcGkoeyBodHRwTWV0aG9kOiBcIlBPU1RcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1tdXRhdGlvblwiXSB9KVxuICBhc3luYyBvYXV0aFN0YXJ0R3Jva0RldmljZShuYW1lOiBzdHJpbmcpOiBQcm9taXNlPEdyb2tEZXZpY2VDb2RlU3RhcnQ+IHtcbiAgICBsZXQgZGV2aWNlO1xuXG4gICAgdHJ5IHtcbiAgICAgIGRldmljZSA9IGF3YWl0IHN0YXJ0R3Jva0RldmljZUNvZGUoKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgZ3Jva09BdXRoQmFkUmVxdWVzdChlcnJvcik7XG4gICAgfVxuXG4gICAgYXdhaXQgc2V0R3Jva0RldmljZVN0YXRlKGRldmljZS5kZXZpY2VDb2RlLCB7XG4gICAgICBuYW1lLFxuICAgICAgaW50ZXJ2YWw6IGRldmljZS5pbnRlcnZhbCxcbiAgICAgIGV4cGlyZXNBdE1zOiBEYXRlLm5vdygpICsgZGV2aWNlLmV4cGlyZXNJbiAqIDEwMDAsXG4gICAgfSk7XG5cbiAgICByZXR1cm4gZGV2aWNlO1xuICB9XG5cbiAgLy8gT25lIHBvbGwgcGVyIGNhbGw7IHRoZSB3ZWIgd2FpdHMgaW50ZXJ2YWxTZWMgYmV0d2VlbiBjYWxscy5cbiAgQGFwaSh7IGh0dHBNZXRob2Q6IFwiUE9TVFwiLCBjbGllbnRzOiBbXCJheGlvc1wiLCBcInRhbnN0YWNrLW11dGF0aW9uXCJdIH0pXG4gIGFzeW5jIG9hdXRoUG9sbEdyb2tEZXZpY2UoZGV2aWNlQ29kZTogc3RyaW5nKTogUHJvbWlzZTxHcm9rRGV2aWNlUG9sbFJlc3VsdD4ge1xuICAgIGNvbnN0IHBlbmRpbmcgPSBhd2FpdCBnZXRHcm9rRGV2aWNlU3RhdGUoZGV2aWNlQ29kZSk7XG5cbiAgICBpZiAoIXBlbmRpbmcpIHtcbiAgICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKFxuICAgICAgICBTRChcImVycm9yLmRldGFpbFwiKShcImxvZ2luIHNlc3Npb24gbm90IGZvdW5kIG9yIGV4cGlyZWQg4oCUIHN0YXJ0IHRoZSBsb2dpbiBhZ2FpblwiKSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgbGV0IHJlc3VsdDtcblxuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSBhd2FpdCBwb2xsR3Jva0RldmljZUNvZGUoeyBkZXZpY2VDb2RlLCBpbnRlcnZhbDogcGVuZGluZy5pbnRlcnZhbCB9KTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgaWYgKGVycm9yIGluc3RhbmNlb2YgR3Jva09BdXRoRXJyb3IgJiYgIWVycm9yLm9wdGlvbnMucmV0cnlhYmxlKSB7XG4gICAgICAgIGF3YWl0IGRlbGV0ZUdyb2tEZXZpY2VTdGF0ZShkZXZpY2VDb2RlKTtcbiAgICAgIH1cblxuICAgICAgZ3Jva09BdXRoQmFkUmVxdWVzdChlcnJvcik7XG4gICAgfVxuXG4gICAgaWYgKHJlc3VsdC5zdGF0dXMgPT09IFwicGVuZGluZ1wiKSB7XG4gICAgICBjb25zdCBzbG93RG93biA9IHJlc3VsdC5pbnRlcnZhbCA+IHBlbmRpbmcuaW50ZXJ2YWw7XG5cbiAgICAgIGlmIChzbG93RG93bikgYXdhaXQgc2V0R3Jva0RldmljZVN0YXRlKGRldmljZUNvZGUsIHsgLi4ucGVuZGluZywgaW50ZXJ2YWw6IHJlc3VsdC5pbnRlcnZhbCB9KTtcblxuICAgICAgcmV0dXJuIHsgc3RhdHVzOiBzbG93RG93biA/IFwic2xvd19kb3duXCIgOiBcInBlbmRpbmdcIiwgaW50ZXJ2YWxTZWM6IHJlc3VsdC5pbnRlcnZhbCB9O1xuICAgIH1cblxuICAgIGF3YWl0IGRlbGV0ZUdyb2tEZXZpY2VTdGF0ZShkZXZpY2VDb2RlKTtcbiAgICBhd2FpdCB0aGlzLnNhdmVHcm9rVG9rZW4ocmVzdWx0LmNyZWRlbnRpYWxzLCBwZW5kaW5nLm5hbWUpO1xuXG4gICAgcmV0dXJuIHsgc3RhdHVzOiBcImFkZGVkXCIsIG5hbWU6IHBlbmRpbmcubmFtZSB9O1xuICB9XG5cbiAgLy8gR3JvayBpbWFnZSBnZW5lcmF0aW9uIChncm9rLyogb25seTsgT3BlbkFJIGltYWdlcyBzdGF5IG9uIHF1ZXJ5L3FncmlkLmltYWdlKCkpLiBXaXRoXG4gIC8vIHJlZmVyZW5jZUltYWdlcyB0aGUgcmVxdWVzdCBnb2VzIHRvIC9pbWFnZXMvZWRpdHMuXG4gIEBhcGkoeyBodHRwTWV0aG9kOiBcIlBPU1RcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1tdXRhdGlvblwiXSB9KVxuICBhc3luYyBnZW5lcmF0ZUltYWdlcyhwYXJhbXM6IEdlbmVyYXRlSW1hZ2VzSW5wdXQpOiBQcm9taXNlPEdlbmVyYXRlSW1hZ2VzT3V0cHV0PiB7XG4gICAgY29uc3QgaW5wdXQgPSBwYXJzZU1lZGlhSW5wdXQoR2VuZXJhdGVJbWFnZXNJbnB1dCwgcGFyYW1zKTtcbiAgICBjb25zdCBtZWRpYSA9IGdyb2tNZWRpYSgpO1xuICAgIGNvbnN0IHNlbGVjdGlvbiA9IGF3YWl0IHJlc29sdmVHcm9rVG9rZW5TZWxlY3Rpb24oaW5wdXQudG9rZW5OYW1lKTtcbiAgICBjb25zdCB7IGlkLCByb3V0ZSB9ID0gcm91dGVNb2RlbElkKGlucHV0Lm1vZGVsLCBHUk9LX0lNQUdFX0RFRkFVTFRfTU9ERUwpO1xuICAgIGNvbnN0IHJlZnMgPSBpbnB1dC5yZWZlcmVuY2VJbWFnZXMgPz8gW107XG5cbiAgICBjb25zdCBzdGFydCA9IHtcbiAgICAgIGtpbmQ6IFwiaW1hZ2VcIixcbiAgICAgIG1vZGVsOiByb3V0ZSxcbiAgICAgIHByb21wdDogaW5wdXQucHJvbXB0LFxuICAgICAgcHJvamVjdE5hbWU6IGlucHV0LnByb2plY3ROYW1lLFxuICAgICAgbG9nZ2VyOiBpbnB1dC5sb2dnZXIsXG4gICAgfSBhcyBjb25zdDtcblxuICAgIHJldHVybiBydW5NZWRpYUVuZHBvaW50KHN0YXJ0LCBhc3luYyAoc2lnbmFsLCByZXF1ZXN0TG9nSWQpID0+IHtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSB7XG4gICAgICAgIG1vZGVsOiBpZCxcbiAgICAgICAgcHJvbXB0OiBpbnB1dC5wcm9tcHQsXG4gICAgICAgIG46IGlucHV0Lm4sXG4gICAgICAgIGFzcGVjdFJhdGlvOiBpbnB1dC5hc3BlY3RSYXRpbyxcbiAgICAgICAgcmVzb2x1dGlvbjogaW5wdXQucmVzb2x1dGlvbixcbiAgICAgICAgcXVhbGl0eTogaW5wdXQucXVhbGl0eSxcbiAgICAgICAgb3V0cHV0Rm9ybWF0OiBpbnB1dC5vdXRwdXRGb3JtYXQsXG4gICAgICAgIHNpZ25hbCxcbiAgICAgICAgLi4uc2VsZWN0aW9uLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgZGlzcGF0Y2hlZCA9IHJlZnMubGVuZ3RoXG4gICAgICAgID8gYXdhaXQgbWVkaWEuZWRpdEltYWdlcyh7IC4uLnJlcXVlc3QsIGltYWdlczogcmVmcyB9KVxuICAgICAgICA6IGF3YWl0IG1lZGlhLmdlbmVyYXRlSW1hZ2VzKHJlcXVlc3QpO1xuXG4gICAgICBjb25zdCBkZWNvZGVkID0gZGVjb2RlR3Jva0ltYWdlcyhkaXNwYXRjaGVkLnJlc3VsdCk7XG4gICAgICBjb25zdCBjb3N0ID0gZ3Jva0ltYWdlQ29zdChpZCwgZGVjb2RlZC5pbWFnZXMubGVuZ3RoLCBkZWNvZGVkLmNvc3RJblVzZFRpY2tzKTtcblxuICAgICAgY29uc3Qgb3V0cHV0OiBHZW5lcmF0ZUltYWdlc091dHB1dCA9IHtcbiAgICAgICAgbW9kZWw6IHJvdXRlLFxuICAgICAgICB0b2tlbk5hbWU6IGRpc3BhdGNoZWQudG9rZW5OYW1lLFxuICAgICAgICBpbWFnZXM6IGRlY29kZWQuaW1hZ2VzLm1hcCgoaW1hZ2UpID0+IHtcbiAgICAgICAgICBjb25zdCBnZW5lcmF0ZWQ6IEdlbmVyYXRlZEltYWdlID0ge1xuICAgICAgICAgICAgYjY0OiBCdWZmZXIuZnJvbShpbWFnZS5ieXRlcykudG9TdHJpbmcoXCJiYXNlNjRcIiksXG4gICAgICAgICAgICBtaW1lVHlwZTogaW1hZ2UubWVkaWFUeXBlLFxuICAgICAgICAgIH07XG5cbiAgICAgICAgICBpZiAoaW1hZ2UucmV2aXNlZFByb21wdCkgZ2VuZXJhdGVkLnJldmlzZWRQcm9tcHQgPSBpbWFnZS5yZXZpc2VkUHJvbXB0O1xuXG4gICAgICAgICAgcmV0dXJuIGdlbmVyYXRlZDtcbiAgICAgICAgfSksXG4gICAgICAgIHVzYWdlOiB7IGltYWdlQ291bnQ6IGRlY29kZWQuaW1hZ2VzLmxlbmd0aCB9LFxuICAgICAgfTtcblxuICAgICAgaWYgKGRlY29kZWQuY29zdEluVXNkVGlja3MgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBvdXRwdXQudXNhZ2UuY29zdEluVXNkVGlja3MgPSBkZWNvZGVkLmNvc3RJblVzZFRpY2tzO1xuICAgICAgfVxuXG4gICAgICBpZiAoY29zdCkge1xuICAgICAgICBvdXRwdXQuY29zdFVzZCA9IGNvc3QuY29zdFVzZDtcbiAgICAgICAgb3V0cHV0LmNvc3RTb3VyY2UgPSBjb3N0LmNvc3RTb3VyY2U7XG4gICAgICB9XG5cbiAgICAgIGlmIChyZXF1ZXN0TG9nSWQgIT09IHVuZGVmaW5lZCkgb3V0cHV0LnJlcXVlc3RMb2dJZCA9IHJlcXVlc3RMb2dJZDtcblxuICAgICAgY29uc3QgbG9nOiBNZWRpYVJ1bkxvZyA9IHtcbiAgICAgICAgdG9rZW5OYW1lOiBvdXRwdXQudG9rZW5OYW1lLFxuICAgICAgICBjb3N0LFxuICAgICAgICByZXNwb25zZTogb3V0cHV0LmltYWdlc1xuICAgICAgICAgIC5tYXAoKGltYWdlKSA9PiBpbWFnZVRhZ0ZvckxvZyhpbWFnZS5iNjQsIGltYWdlLm1pbWVUeXBlLCBpbWFnZS5yZXZpc2VkUHJvbXB0KSlcbiAgICAgICAgICAuam9pbihcIlxcblwiKSxcbiAgICAgICAgc3RlcHM6IG91dHB1dC5pbWFnZXMubWFwKChpbWFnZSwgaW5kZXgpID0+IHtcbiAgICAgICAgICBjb25zdCBhcmdzOiBJbWFnZVN0ZXBBcmdzID0ge1xuICAgICAgICAgICAga2luZDogXCJpbWFnZVwiLFxuICAgICAgICAgICAgcHJvbXB0OiBpbnB1dC5wcm9tcHQsXG4gICAgICAgICAgICBtb2RlbDogcm91dGUsXG4gICAgICAgICAgICByZXF1ZXN0ZWRPcHRpb25zOiB7XG4gICAgICAgICAgICAgIG46IGlucHV0Lm4sXG4gICAgICAgICAgICAgIGFzcGVjdFJhdGlvOiBpbnB1dC5hc3BlY3RSYXRpbyxcbiAgICAgICAgICAgICAgcmVzb2x1dGlvbjogaW5wdXQucmVzb2x1dGlvbixcbiAgICAgICAgICAgICAgcXVhbGl0eTogaW5wdXQucXVhbGl0eSxcbiAgICAgICAgICAgICAgb3V0cHV0Rm9ybWF0OiBpbnB1dC5vdXRwdXRGb3JtYXQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaW1hZ2VDb3VudDogb3V0cHV0LnVzYWdlLmltYWdlQ291bnQsXG4gICAgICAgICAgfTtcblxuICAgICAgICAgIGlmIChjb3N0KSB7XG4gICAgICAgICAgICBhcmdzLmNvc3RTb3VyY2UgPSBjb3N0LmNvc3RTb3VyY2U7XG4gICAgICAgICAgICBhcmdzLmNvc3RJblVzZFRpY2tzID0gY29zdC50aWNrcztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBSZWZlcmVuY2UgaW1hZ2VzIGFyZSBzdG9yZWQgb25jZSwgb24gdGhlIGZpcnN0IG91dHB1dCBzdGVwLlxuICAgICAgICAgIGlmIChpbmRleCA9PT0gMCAmJiByZWZzLmxlbmd0aCkgYXJncy5pbnB1dEltYWdlcyA9IGRlc2NyaWJlSW1hZ2VSZWZzKHJlZnMsIHRydWUpO1xuXG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHRvb2xDYWxsSWQ6IGBpbWFnZV9nZW5lcmF0aW9uOjA6JHtpbmRleH1gLFxuICAgICAgICAgICAgYXJncyxcbiAgICAgICAgICAgIHJlc3VsdDogaW1hZ2VUYWdGb3JMb2coaW1hZ2UuYjY0LCBpbWFnZS5taW1lVHlwZSwgaW1hZ2UucmV2aXNlZFByb21wdCksXG4gICAgICAgICAgfTtcbiAgICAgICAgfSksXG4gICAgICB9O1xuXG4gICAgICByZXR1cm4geyBvdXRwdXQsIGxvZyB9O1xuICAgIH0pO1xuICB9XG5cbiAgLy8gU3RhcnRzIGEgR3JvayB2aWRlbyBqb2IuIFBvbGwgdmlkZW9TdGF0dXMgd2l0aCB0aGUgcmV0dXJuZWQgaGFuZGxlIGFuZCB0aGUgc2FtZSBwcm9qZWN0TmFtZS5cbiAgLy8gVGhlIHJ1biBzdGF5cyBvcGVuIGFmdGVyIGEgc3VjY2Vzc2Z1bCBzdGFydCAoYSBwZW5kaW5nIHRvb2wgc3RlcCksIHNvIG9ubHkgdGhlIHByb3ZpZGVyIGNhbGxcbiAgLy8gZ29lcyB0aHJvdWdoIGRpc3BhdGNoTWVkaWFDYWxsOyB2aWRlb1N0YXR1cyBmaW5pc2hlcyB0aGUgcnVuIG9uIGEgdGVybWluYWwgc3RhdHVzLlxuICBAYXBpKHsgaHR0cE1ldGhvZDogXCJQT1NUXCIsIGNsaWVudHM6IFtcImF4aW9zXCIsIFwidGFuc3RhY2stbXV0YXRpb25cIl0gfSlcbiAgYXN5bmMgdmlkZW9TdGFydChwYXJhbXM6IFZpZGVvU3RhcnRJbnB1dCk6IFByb21pc2U8VmlkZW9TdGFydE91dHB1dD4ge1xuICAgIGNvbnN0IGlucHV0ID0gcGFyc2VNZWRpYUlucHV0KFZpZGVvU3RhcnRJbnB1dCwgcGFyYW1zKTtcbiAgICBjb25zdCBtZWRpYSA9IGdyb2tNZWRpYSgpO1xuICAgIGNvbnN0IHNlbGVjdGlvbiA9IGF3YWl0IHJlc29sdmVHcm9rVG9rZW5TZWxlY3Rpb24oaW5wdXQudG9rZW5OYW1lKTtcbiAgICBjb25zdCB7IGlkLCByb3V0ZSB9ID0gcm91dGVNb2RlbElkKGlucHV0Lm1vZGVsLCBHUk9LX1ZJREVPX0RFRkFVTFRfTU9ERUwpO1xuXG4gICAgY29uc3QgcmVxdWVzdExvZ0lkID0gYXdhaXQgc3RhcnRNZWRpYVJ1bihpbnB1dC5sb2dnZXIsIHtcbiAgICAgIGtpbmQ6IFwidmlkZW9cIixcbiAgICAgIG1vZGVsOiByb3V0ZSxcbiAgICAgIHByb21wdDogaW5wdXQucHJvbXB0LFxuICAgICAgcHJvamVjdE5hbWU6IGlucHV0LnByb2plY3ROYW1lLFxuICAgIH0pO1xuXG4gICAgY29uc3Qgc3RhcnRlZEF0ID0gRGF0ZS5ub3coKTtcblxuICAgIGNvbnN0IHN0YXJ0ZWQgPSBhd2FpdCBkaXNwYXRjaE1lZGlhQ2FsbChyZXF1ZXN0TG9nSWQsIChzaWduYWwpID0+XG4gICAgICBtZWRpYS5zdGFydFZpZGVvKHtcbiAgICAgICAgbW9kZWw6IGlkLFxuICAgICAgICBwcm9tcHQ6IGlucHV0LnByb21wdCxcbiAgICAgICAgZHVyYXRpb246IGlucHV0LmR1cmF0aW9uLFxuICAgICAgICBhc3BlY3RSYXRpbzogaW5wdXQuYXNwZWN0UmF0aW8sXG4gICAgICAgIHJlc29sdXRpb246IGlucHV0LnJlc29sdXRpb24sXG4gICAgICAgIGltYWdlOiBpbnB1dC5pbWFnZSxcbiAgICAgICAgbGFzdEZyYW1lOiBpbnB1dC5sYXN0RnJhbWUsXG4gICAgICAgIHJlZmVyZW5jZUltYWdlczogaW5wdXQucmVmZXJlbmNlSW1hZ2VzLFxuICAgICAgICBtb2RlOiBpbnB1dC5tb2RlLFxuICAgICAgICBzaWduYWwsXG4gICAgICAgIC4uLnNlbGVjdGlvbixcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgIHBydW5lVmlkZW9Kb2JzKG5vdyk7XG4gICAgY29uc3Qgam9iSGFuZGxlID0gY3J5cHRvLnJhbmRvbUJ5dGVzKDE2KS50b1N0cmluZyhcImJhc2U2NHVybFwiKTtcblxuICAgIGNvbnN0IGpvYjogVmlkZW9Kb2IgPSB7XG4gICAgICB0b2tlbklkOiBzdGFydGVkLnRva2VuSWQsXG4gICAgICB0b2tlbk5hbWU6IHN0YXJ0ZWQudG9rZW5OYW1lLFxuICAgICAgcmVxdWVzdElkOiBzdGFydGVkLnJlc3VsdC5yZXF1ZXN0X2lkLFxuICAgICAgb3duZXI6IGlucHV0LnByb2plY3ROYW1lID8/IG51bGwsXG4gICAgICBtb2RlbDogcm91dGUsXG4gICAgICBjcmVhdGVkQXQ6IG5vdyxcbiAgICB9O1xuXG4gICAgaWYgKHJlcXVlc3RMb2dJZCAhPT0gdW5kZWZpbmVkKSBqb2IucmVxdWVzdExvZ0lkID0gcmVxdWVzdExvZ0lkO1xuXG4gICAgdmlkZW9Kb2JzLnNldChqb2JIYW5kbGUsIGpvYik7XG5cbiAgICBpZiAocmVxdWVzdExvZ0lkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIC8vIFRoZSBwZW5kaW5nIHRvb2wgc3RlcCBrZWVwcyB0aGUgcnVuIG9wZW47IGFuIGFiYW5kb25lZCBqb2IgaXMgZXhwaXJlZCBieSBzdGFsZSBjbGVhbnVwLlxuICAgICAgY29uc3QgcmVmcyA9IFtcbiAgICAgICAgLi4uKGlucHV0LmltYWdlID8gW2lucHV0LmltYWdlXSA6IFtdKSxcbiAgICAgICAgLi4uKGlucHV0Lmxhc3RGcmFtZSA/IFtpbnB1dC5sYXN0RnJhbWVdIDogW10pLFxuICAgICAgICAuLi4oaW5wdXQucmVmZXJlbmNlSW1hZ2VzID8/IFtdKSxcbiAgICAgIF07XG5cbiAgICAgIGNvbnN0IGFyZ3M6IFZpZGVvU3RlcEFyZ3MgPSB7XG4gICAgICAgIGtpbmQ6IFwidmlkZW9cIixcbiAgICAgICAgcHJvbXB0OiBpbnB1dC5wcm9tcHQsXG4gICAgICAgIG1vZGVsOiByb3V0ZSxcbiAgICAgICAgcmVxdWVzdGVkT3B0aW9uczoge1xuICAgICAgICAgIGR1cmF0aW9uOiBpbnB1dC5kdXJhdGlvbixcbiAgICAgICAgICBhc3BlY3RSYXRpbzogaW5wdXQuYXNwZWN0UmF0aW8sXG4gICAgICAgICAgcmVzb2x1dGlvbjogaW5wdXQucmVzb2x1dGlvbixcbiAgICAgICAgICBtb2RlOiBpbnB1dC5tb2RlLFxuICAgICAgICB9LFxuICAgICAgfTtcblxuICAgICAgaWYgKHJlZnMubGVuZ3RoKSBhcmdzLmlucHV0SW1hZ2VzID0gZGVzY3JpYmVJbWFnZVJlZnMocmVmcywgZmFsc2UpO1xuXG4gICAgICBjb25zdCBbc3RlcF0gPSBtZWRpYVRvb2xTdGVwcyhcbiAgICAgICAgXCJ2aWRlb1wiLFxuICAgICAgICBbeyB0b29sQ2FsbElkOiB2aWRlb1Rvb2xDYWxsSWQoam9iKSwgYXJncyB9XSxcbiAgICAgICAgbm93IC0gc3RhcnRlZEF0LFxuICAgICAgKTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgUmVxdWVzdExvZ01vZGVsLmFwcGVuZFN0ZXAocmVxdWVzdExvZ0lkLCBzdGVwISk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIG1lZGlhTG9nZ2VyLmVycm9yKFxuICAgICAgICAgIGB2aWRlbyByZXF1ZXN0IGxvZyBmYWlsZWQ6ICR7ZSBpbnN0YW5jZW9mIEVycm9yID8gZS5tZXNzYWdlIDogU3RyaW5nKGUpfWAsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3Qgb3V0cHV0OiBWaWRlb1N0YXJ0T3V0cHV0ID0geyBqb2JIYW5kbGUsIG1vZGVsOiByb3V0ZSB9O1xuXG4gICAgaWYgKHJlcXVlc3RMb2dJZCAhPT0gdW5kZWZpbmVkKSBvdXRwdXQucmVxdWVzdExvZ0lkID0gcmVxdWVzdExvZ0lkO1xuXG4gICAgcmV0dXJuIG91dHB1dDtcbiAgfVxuXG4gIC8vIFBvbGxzIHRoZSB0b2tlbiB0aGF0IHN0YXJ0ZWQgdGhlIGpvYi4gQSB0ZXJtaW5hbCBzdGF0dXMgaXMgY2FjaGVkIHNvIHRoZSBydW4gaXMgbG9nZ2VkIG9uY2UuXG4gIEBhcGkoeyBodHRwTWV0aG9kOiBcIlBPU1RcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1tdXRhdGlvblwiXSB9KVxuICBhc3luYyB2aWRlb1N0YXR1cyhwYXJhbXM6IFZpZGVvU3RhdHVzSW5wdXQpOiBQcm9taXNlPFZpZGVvU3RhdHVzT3V0cHV0PiB7XG4gICAgY29uc3QgaW5wdXQgPSBwYXJzZU1lZGlhSW5wdXQoVmlkZW9TdGF0dXNJbnB1dCwgcGFyYW1zKTtcbiAgICBwcnVuZVZpZGVvSm9icyhEYXRlLm5vdygpKTtcbiAgICBjb25zdCBqb2IgPSB2aWRlb0pvYnMuZ2V0KGlucHV0LmpvYkhhbmRsZSk7XG5cbiAgICAvLyBBIGZvcmVpZ24gb3duZXIgZ2V0cyB0aGUgc2FtZSA0MDQgYXMgYW4gdW5rbm93biBoYW5kbGUsIHNvIGhhbmRsZXMgY2Fubm90IGJlIHByb2JlZC5cbiAgICBpZiAoIWpvYiB8fCBqb2Iub3duZXIgIT09IChpbnB1dC5wcm9qZWN0TmFtZSA/PyBudWxsKSkge1xuICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKFNEKFwicWdyaWQudmlkZW9Kb2JOb3RGb3VuZFwiKSk7XG4gICAgfVxuXG4gICAgaWYgKGpvYi5maW5hbCkgcmV0dXJuIGpvYi5maW5hbDtcblxuICAgIGNvbnN0IG1lZGlhID0gZ3Jva01lZGlhKCk7XG4gICAgY29uc3QgZGlzY29ubmVjdCA9IGNyZWF0ZUh0dHBEaXNjb25uZWN0SGFuZGxlKCk7XG4gICAgbGV0IHN1bW1hcnk6IFJldHVyblR5cGU8dHlwZW9mIHN1bW1hcml6ZUdyb2tWaWRlb1N0YXR1cz47XG4gICAgbGV0IGR1cmF0aW9uU2VjOiBudW1iZXIgfCB1bmRlZmluZWQ7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcG9sbGVkID0gYXdhaXQgbWVkaWEuZ2V0VmlkZW8oam9iLnRva2VuSWQsIGpvYi5yZXF1ZXN0SWQsIGRpc2Nvbm5lY3Quc2lnbmFsKTtcbiAgICAgIHN1bW1hcnkgPSBzdW1tYXJpemVHcm9rVmlkZW9TdGF0dXMocG9sbGVkLnJlc3VsdCk7XG4gICAgICBkdXJhdGlvblNlYyA9IHBvbGxlZC5yZXN1bHQudmlkZW8/LmR1cmF0aW9uID8/IHVuZGVmaW5lZDtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgR3Jva0NvbnRlbnRQb2xpY3lFcnJvcikpIHRocm93R3Jva0NhbGxlckVycm9yKGUpO1xuICAgICAgc3VtbWFyeSA9IHsgc3RhdHVzOiBcImZhaWxlZFwiLCBtaW1lVHlwZTogXCJ2aWRlby9tcDRcIiwgZXJyb3I6IGUubWVzc2FnZSB9O1xuICAgIH0gZmluYWxseSB7XG4gICAgICBkaXNjb25uZWN0LmRpc3Bvc2UoKTtcbiAgICB9XG5cbiAgICAvLyBBbiBvdmVybGFwcGluZyBwb2xsIG1heSBoYXZlIGZpbmlzaGVkIHRoZSBqb2Igd2hpbGUgdGhpcyBvbmUgYXdhaXRlZCB1cHN0cmVhbS5cbiAgICBpZiAoam9iLmZpbmFsKSByZXR1cm4gam9iLmZpbmFsO1xuXG4gICAgY29uc3Qgc3RhdHVzOiBWaWRlb1N0YXR1c091dHB1dCA9IHsgc3RhdHVzOiBzdW1tYXJ5LnN0YXR1cywgbWltZVR5cGU6IFwidmlkZW8vbXA0XCIgfTtcblxuICAgIGlmIChqb2IucmVxdWVzdExvZ0lkICE9PSB1bmRlZmluZWQpIHN0YXR1cy5yZXF1ZXN0TG9nSWQgPSBqb2IucmVxdWVzdExvZ0lkO1xuXG4gICAgaWYgKHN1bW1hcnkuc3RhdHVzID09PSBcInBlbmRpbmdcIikgcmV0dXJuIHN0YXR1cztcblxuICAgIGNvbnN0IGNvc3QgPSBncm9rUmVwb3J0ZWRDb3N0KHN1bW1hcnkudXNhZ2VUaWNrcyk7XG4gICAgY29uc3QgZmluYWwgPSBzdGF0dXM7XG5cbiAgICBpZiAoc3VtbWFyeS51cmwpIGZpbmFsLnVybCA9IHN1bW1hcnkudXJsO1xuXG4gICAgaWYgKGR1cmF0aW9uU2VjICE9PSB1bmRlZmluZWQpIGZpbmFsLmR1cmF0aW9uU2VjID0gZHVyYXRpb25TZWM7XG5cbiAgICBpZiAoY29zdCkge1xuICAgICAgZmluYWwuY29zdEluVXNkVGlja3MgPSBjb3N0LnRpY2tzO1xuICAgICAgZmluYWwuY29zdFVzZCA9IGNvc3QuY29zdFVzZDtcbiAgICB9XG5cbiAgICBpZiAoc3VtbWFyeS5lcnJvcikgZmluYWwuZXJyb3IgPSBzdW1tYXJ5LmVycm9yO1xuXG4gICAgLy8gU2V0IGJlZm9yZSBmaW5pc2hWaWRlb1J1bidzIGF3YWl0OiBvdmVybGFwcGluZyBwb2xscyByZXR1cm4gdGhpcyByZXN1bHQgaW5zdGVhZCBvZiBsb2dnaW5nIGFnYWluLlxuICAgIGpvYi5maW5hbCA9IGZpbmFsO1xuICAgIGF3YWl0IGZpbmlzaFZpZGVvUnVuKGpvYiwgZmluYWwsIGNvc3QpO1xuXG4gICAgcmV0dXJuIGZpbmFsO1xuICB9XG5cbiAgQGFwaSh7IGh0dHBNZXRob2Q6IFwiUE9TVFwiLCBjbGllbnRzOiBbXCJheGlvc1wiLCBcInRhbnN0YWNrLW11dGF0aW9uXCJdIH0pXG4gIGFzeW5jIHRyYW5zY3JpYmUocGFyYW1zOiBUcmFuc2NyaWJlSW5wdXQpOiBQcm9taXNlPFRyYW5zY3JpYmVPdXRwdXQ+IHtcbiAgICBjb25zdCBpbnB1dCA9IHBhcnNlTWVkaWFJbnB1dChUcmFuc2NyaWJlSW5wdXQsIHBhcmFtcyk7XG4gICAgY29uc3Qgdm9pY2UgPSBncm9rVm9pY2UoKTtcbiAgICBjb25zdCBzZWxlY3Rpb24gPSBhd2FpdCByZXNvbHZlR3Jva1Rva2VuU2VsZWN0aW9uKGlucHV0LnRva2VuTmFtZSk7XG4gICAgY29uc3QgeyBpZCwgcm91dGUgfSA9IHJvdXRlTW9kZWxJZChpbnB1dC5tb2RlbCwgR1JPS19TVFRfREVGQVVMVF9NT0RFTCk7XG4gICAgY29uc3QgYXVkaW8gPSBuZXcgVWludDhBcnJheShCdWZmZXIuZnJvbShpbnB1dC5hdWRpbywgXCJiYXNlNjRcIikpO1xuXG4gICAgY29uc3Qgc3RhcnQgPSB7XG4gICAgICBraW5kOiBcInN0dFwiLFxuICAgICAgbW9kZWw6IHJvdXRlLFxuICAgICAgcHJvbXB0OiBgW2F1ZGlvICR7aW5wdXQubWVkaWFUeXBlfSAke2F1ZGlvLmJ5dGVMZW5ndGh9IGJ5dGVzXWAsXG4gICAgICBwcm9qZWN0TmFtZTogaW5wdXQucHJvamVjdE5hbWUsXG4gICAgICBsb2dnZXI6IGlucHV0LmxvZ2dlcixcbiAgICB9IGFzIGNvbnN0O1xuXG4gICAgcmV0dXJuIHJ1bk1lZGlhRW5kcG9pbnQoc3RhcnQsIGFzeW5jIChzaWduYWwsIHJlcXVlc3RMb2dJZCkgPT4ge1xuICAgICAgY29uc3QgZGlzcGF0Y2hlZCA9IGF3YWl0IHZvaWNlLnRyYW5zY3JpYmUoe1xuICAgICAgICBhdWRpbyxcbiAgICAgICAgbWVkaWFUeXBlOiBpbnB1dC5tZWRpYVR5cGUsXG4gICAgICAgIG1vZGVsOiBpZCxcbiAgICAgICAgbGFuZ3VhZ2U6IGlucHV0Lmxhbmd1YWdlLFxuICAgICAgICBzaWduYWwsXG4gICAgICAgIC4uLnNlbGVjdGlvbixcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB7IHRleHQsIGxhbmd1YWdlLCBkdXJhdGlvbiB9ID0gZGlzcGF0Y2hlZC5yZXN1bHQ7XG5cbiAgICAgIGNvbnN0IG91dHB1dDogVHJhbnNjcmliZU91dHB1dCA9IHsgdGV4dCwgbW9kZWw6IHJvdXRlLCB0b2tlbk5hbWU6IGRpc3BhdGNoZWQudG9rZW5OYW1lIH07XG5cbiAgICAgIGlmIChsYW5ndWFnZSkgb3V0cHV0Lmxhbmd1YWdlID0gbGFuZ3VhZ2U7XG5cbiAgICAgIGlmIChkdXJhdGlvbiAhPT0gdW5kZWZpbmVkKSBvdXRwdXQuZHVyYXRpb25TZWMgPSBkdXJhdGlvbjtcblxuICAgICAgaWYgKHJlcXVlc3RMb2dJZCAhPT0gdW5kZWZpbmVkKSBvdXRwdXQucmVxdWVzdExvZ0lkID0gcmVxdWVzdExvZ0lkO1xuXG4gICAgICBjb25zdCBsb2c6IE1lZGlhUnVuTG9nID0ge1xuICAgICAgICB0b2tlbk5hbWU6IG91dHB1dC50b2tlbk5hbWUsXG4gICAgICAgIHJlc3BvbnNlOiBvdXRwdXQudGV4dCxcbiAgICAgICAgc3RlcHM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICB0b29sQ2FsbElkOiBcInRyYW5zY3JpcHRpb246MFwiLFxuICAgICAgICAgICAgYXJnczoge1xuICAgICAgICAgICAgICBraW5kOiBcInN0dFwiLFxuICAgICAgICAgICAgICBtb2RlbDogcm91dGUsXG4gICAgICAgICAgICAgIG1lZGlhVHlwZTogaW5wdXQubWVkaWFUeXBlLFxuICAgICAgICAgICAgICBhdWRpb0J5dGVzOiBhdWRpby5ieXRlTGVuZ3RoLFxuICAgICAgICAgICAgICBsYW5ndWFnZTogaW5wdXQubGFuZ3VhZ2UsXG4gICAgICAgICAgICAgIGR1cmF0aW9uU2VjOiBvdXRwdXQuZHVyYXRpb25TZWMsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcmVzdWx0OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgIHRleHQ6IG91dHB1dC50ZXh0LFxuICAgICAgICAgICAgICBsYW5ndWFnZTogb3V0cHV0Lmxhbmd1YWdlLFxuICAgICAgICAgICAgICBkdXJhdGlvblNlYzogb3V0cHV0LmR1cmF0aW9uU2VjLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG5cbiAgICAgIHJldHVybiB7IG91dHB1dCwgbG9nIH07XG4gICAgfSk7XG4gIH1cblxuICAvLyAvdHRzIHRha2VzIG5vIG1vZGVsOyBgbW9kZWxgIG9ubHkgbGFiZWxzIHRoZSByZXF1ZXN0IGxvZy5cbiAgQGFwaSh7IGh0dHBNZXRob2Q6IFwiUE9TVFwiLCBjbGllbnRzOiBbXCJheGlvc1wiLCBcInRhbnN0YWNrLW11dGF0aW9uXCJdIH0pXG4gIGFzeW5jIHNwZWFrKHBhcmFtczogU3BlYWtJbnB1dCk6IFByb21pc2U8U3BlYWtPdXRwdXQ+IHtcbiAgICBjb25zdCBpbnB1dCA9IHBhcnNlTWVkaWFJbnB1dChTcGVha0lucHV0LCBwYXJhbXMpO1xuICAgIGNvbnN0IHZvaWNlID0gZ3Jva1ZvaWNlKCk7XG4gICAgY29uc3Qgc2VsZWN0aW9uID0gYXdhaXQgcmVzb2x2ZUdyb2tUb2tlblNlbGVjdGlvbihpbnB1dC50b2tlbk5hbWUpO1xuICAgIGNvbnN0IHJvdXRlID0gaW5wdXQubW9kZWwgPz8gR1JPS19UVFNfTE9HX01PREVMO1xuXG4gICAgY29uc3QgcmVxdWVzdCA9IHtcbiAgICAgIHRleHQ6IGlucHV0LnRleHQsXG4gICAgICB2b2ljZTogaW5wdXQudm9pY2UgPz8gR1JPS19UVFNfREVGQVVMVF9WT0lDRSxcbiAgICAgIGxhbmd1YWdlOiBpbnB1dC5sYW5ndWFnZSA/PyBHUk9LX1RUU19ERUZBVUxUX0xBTkdVQUdFLFxuICAgICAgZm9ybWF0OiBpbnB1dC5mb3JtYXQgPz8gR1JPS19UVFNfREVGQVVMVF9GT1JNQVQsXG4gICAgfTtcblxuICAgIGNvbnN0IHN0YXJ0ID0ge1xuICAgICAga2luZDogXCJ0dHNcIixcbiAgICAgIG1vZGVsOiByb3V0ZSxcbiAgICAgIHByb21wdDogaW5wdXQudGV4dCxcbiAgICAgIHByb2plY3ROYW1lOiBpbnB1dC5wcm9qZWN0TmFtZSxcbiAgICAgIGxvZ2dlcjogaW5wdXQubG9nZ2VyLFxuICAgIH0gYXMgY29uc3Q7XG5cbiAgICByZXR1cm4gcnVuTWVkaWFFbmRwb2ludChzdGFydCwgYXN5bmMgKHNpZ25hbCwgcmVxdWVzdExvZ0lkKSA9PiB7XG4gICAgICBjb25zdCBkaXNwYXRjaGVkID0gYXdhaXQgdm9pY2Uuc3BlYWsoeyAuLi5yZXF1ZXN0LCBzaWduYWwsIC4uLnNlbGVjdGlvbiB9KTtcbiAgICAgIGNvbnN0IGF1ZGlvQnl0ZXMgPSBkaXNwYXRjaGVkLnJlc3VsdC5hdWRpby5ieXRlTGVuZ3RoO1xuXG4gICAgICBjb25zdCBvdXRwdXQ6IFNwZWFrT3V0cHV0ID0ge1xuICAgICAgICBhdWRpbzogQnVmZmVyLmZyb20oZGlzcGF0Y2hlZC5yZXN1bHQuYXVkaW8pLnRvU3RyaW5nKFwiYmFzZTY0XCIpLFxuICAgICAgICBtaW1lVHlwZTogZGlzcGF0Y2hlZC5yZXN1bHQubWVkaWFUeXBlLFxuICAgICAgICB0b2tlbk5hbWU6IGRpc3BhdGNoZWQudG9rZW5OYW1lLFxuICAgICAgfTtcblxuICAgICAgaWYgKHJlcXVlc3RMb2dJZCAhPT0gdW5kZWZpbmVkKSBvdXRwdXQucmVxdWVzdExvZ0lkID0gcmVxdWVzdExvZ0lkO1xuXG4gICAgICBjb25zdCBsb2c6IE1lZGlhUnVuTG9nID0ge1xuICAgICAgICB0b2tlbk5hbWU6IG91dHB1dC50b2tlbk5hbWUsXG4gICAgICAgIHJlc3BvbnNlOiBgW2F1ZGlvICR7b3V0cHV0Lm1pbWVUeXBlfSAke2F1ZGlvQnl0ZXN9IGJ5dGVzXWAsXG4gICAgICAgIHN0ZXBzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgdG9vbENhbGxJZDogXCJzcGVlY2g6MFwiLFxuICAgICAgICAgICAgYXJnczoge1xuICAgICAgICAgICAgICBraW5kOiBcInR0c1wiLFxuICAgICAgICAgICAgICBtb2RlbDogcm91dGUsXG4gICAgICAgICAgICAgIHZvaWNlOiByZXF1ZXN0LnZvaWNlLFxuICAgICAgICAgICAgICBsYW5ndWFnZTogcmVxdWVzdC5sYW5ndWFnZSxcbiAgICAgICAgICAgICAgZm9ybWF0OiByZXF1ZXN0LmZvcm1hdCxcbiAgICAgICAgICAgICAgY2hhcmFjdGVyczogaW5wdXQudGV4dC5sZW5ndGgsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcmVzdWx0OiBKU09OLnN0cmluZ2lmeSh7IG1pbWVUeXBlOiBvdXRwdXQubWltZVR5cGUsIGF1ZGlvQnl0ZXMgfSksXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG5cbiAgICAgIHJldHVybiB7IG91dHB1dCwgbG9nIH07XG4gICAgfSk7XG4gIH1cblxuICBAYXBpKHsgaHR0cE1ldGhvZDogXCJHRVRcIiwgY2xpZW50czogW1wiYXhpb3NcIiwgXCJ0YW5zdGFjay1xdWVyeVwiXSB9KVxuICBhc3luYyB1c2FnZSh0b2tlbklkPzogbnVtYmVyKTogUHJvbWlzZTxVc2FnZVJlc3BvbnNlPiB7XG4gICAgY29uc3QgeyByb3dzOiBhbGxUb2tlbnMgfSA9IGF3YWl0IFRva2VuTW9kZWwuZmluZE1hbnkoXCJBXCIpO1xuXG4gICAgY29uc3QgZW50cnkgPSB0b2tlbklkXG4gICAgICA/IGFsbFRva2Vucy5maW5kKChlKSA9PiBlLmlkID09PSB0b2tlbklkKVxuICAgICAgOiBhbGxUb2tlbnMuZmluZExhc3QoKGUpID0+IGUuYWN0aXZlICYmIGUucHJvdmlkZXIgPT09IFwiYW50aHJvcGljXCIpO1xuXG4gICAgaWYgKCFlbnRyeSkgcmV0dXJuIHsgZXJyb3I6IFwiTk9UX0ZPVU5EXCIgfTtcblxuICAgIGlmIChlbnRyeS5yZWF1dGhfcmVxdWlyZWQpIHJldHVybiB7IGVycm9yOiBcInJlLWxvZ2luIHJlcXVpcmVkXCIgfTtcblxuICAgIGlmIChlbnRyeS5wcm92aWRlciA9PT0gXCJvcGVuYWlcIikge1xuICAgICAgaWYgKCFlbnRyeS5hY3RpdmUpIHtcbiAgICAgICAgcmV0dXJuIHsgcHJvdmlkZXI6IFwib3BlbmFpXCIsIGZpdmVIb3VyOiBudWxsLCBzZXZlbkRheTogbnVsbCB9O1xuICAgICAgfVxuXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByYXcgPSBhd2FpdCBRZ3JpZERpc3BhdGNoZXIub3BlbmFpRGlzcGF0Y2hlcj8uZ2V0UmF0ZUxpbWl0c0J5VG9rZW5JZChlbnRyeS5pZCk7XG4gICAgICAgIGNvbnN0IHJsID0gcmF3Py5kYXRhLnJhdGVMaW1pdHM7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBwcm92aWRlcjogXCJvcGVuYWlcIixcbiAgICAgICAgICBmaXZlSG91cjogcmw/LnByaW1hcnlcbiAgICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAgIHV0aWxpemF0aW9uOiBybC5wcmltYXJ5LnVzZWRQZXJjZW50LFxuICAgICAgICAgICAgICAgIHJlc2V0c0F0OiB1bml4U2Vjb25kc1RvSXNvKHJsLnByaW1hcnkucmVzZXRzQXQpLFxuICAgICAgICAgICAgICAgIHdpbmRvd0R1cmF0aW9uTWluczogcmwucHJpbWFyeS53aW5kb3dEdXJhdGlvbk1pbnMsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDogbnVsbCxcbiAgICAgICAgICBzZXZlbkRheTogcmw/LnNlY29uZGFyeVxuICAgICAgICAgICAgPyB7XG4gICAgICAgICAgICAgICAgdXRpbGl6YXRpb246IHJsLnNlY29uZGFyeS51c2VkUGVyY2VudCxcbiAgICAgICAgICAgICAgICByZXNldHNBdDogdW5peFNlY29uZHNUb0lzbyhybC5zZWNvbmRhcnkucmVzZXRzQXQpLFxuICAgICAgICAgICAgICAgIHdpbmRvd0R1cmF0aW9uTWluczogcmwuc2Vjb25kYXJ5LndpbmRvd0R1cmF0aW9uTWlucyxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgOiBudWxsLFxuICAgICAgICB9O1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZXR1cm4geyBlcnJvcjogYE9wZW5BSSB1c2FnZSBmYWlsZWQ6ICR7ZSBpbnN0YW5jZW9mIEVycm9yID8gZS5tZXNzYWdlIDogU3RyaW5nKGUpfWAgfTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZW50cnkucHJvdmlkZXIgPT09IFwiZ3Jva1wiKSB7XG4gICAgICAvLyBDYWNoZWQgYmlsbGluZyBmcm9tIHRoZSBkaXNwYXRjaGVyJ3MgcHJlZmV0Y2g7IHVzYWdlIG5ldmVyIGNhbGxzIHhBSSBpdHNlbGYuXG4gICAgICBjb25zdCBzbmFwc2hvdCA9IGVudHJ5LmFjdGl2ZSA/IGdyb2tUb2tlblNuYXBzaG90KGVudHJ5LmlkKSA6IHVuZGVmaW5lZDtcbiAgICAgIGNvbnN0IGJpbGxpbmcgPSBzbmFwc2hvdD8ubGFzdEJpbGxpbmc7XG4gICAgICBjb25zdCBzdG9yZWRUaWVyID0gU3RvcmVkR3Jva0NyZWRlbnRpYWxzLnNhZmVQYXJzZShlbnRyeS5jcmVkZW50aWFscykuZGF0YT8uc3Vic2NyaXB0aW9uVGllcjtcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgcHJvdmlkZXI6IFwiZ3Jva1wiLFxuICAgICAgICBmaXZlSG91cjogbnVsbCxcbiAgICAgICAgc2V2ZW5EYXk6IGJpbGxpbmdcbiAgICAgICAgICA/IHsgdXRpbGl6YXRpb246IGJpbGxpbmcudXRpbGl6YXRpb25QY3QsIHJlc2V0c0F0OiBiaWxsaW5nLnBlcmlvZEVuZCB9XG4gICAgICAgICAgOiBudWxsLFxuICAgICAgICBwZXJpb2RUeXBlOiBiaWxsaW5nPy5wZXJpb2RUeXBlID8/IG51bGwsXG4gICAgICAgIHRpZXI6IHNuYXBzaG90Py5sYXN0VGllciA/PyBzdG9yZWRUaWVyID8/IG51bGwsXG4gICAgICAgIG9uRGVtYW5kRXhjbHVkZWQ6IHNuYXBzaG90Py5vbkRlbWFuZEV4Y2x1ZGVkID8/IGZhbHNlLFxuICAgICAgICB6ZHJWaWRlb0V4Y2x1ZGVkOiBzbmFwc2hvdD8uemRyVmlkZW9FeGNsdWRlZCA/PyBmYWxzZSxcbiAgICAgICAga2VlcGFsaXZlQXBwbGljYWJsZTogZmFsc2UsXG4gICAgICB9O1xuICAgIH1cblxuICAgIGlmIChlbnRyeS5wcm92aWRlciAhPT0gXCJhbnRocm9waWNcIikge1xuICAgICAgcmV0dXJuIHsgZXJyb3I6IGB1c2FnZSBBUEkgbm90IHN1cHBvcnRlZCBmb3IgcHJvdmlkZXI6ICR7ZW50cnkucHJvdmlkZXJ9YCB9O1xuICAgIH1cblxuICAgIGxldCBhY2Nlc3NUb2tlbiA9IGdldEFjY2Vzc1Rva2VuKGVudHJ5LmNyZWRlbnRpYWxzKTtcbiAgICBjb25zdCBpc0V4cGlyZWQgPSBnZXRFeHBpcmVzQXQoZW50cnkuY3JlZGVudGlhbHMpIDwgRGF0ZS5ub3coKTtcblxuICAgIGlmIChpc0V4cGlyZWQgJiYgZ2V0UmVmcmVzaFRva2VuKGVudHJ5LmNyZWRlbnRpYWxzKSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYWNjZXNzVG9rZW4gPSBhd2FpdCB0aGlzLnJlZnJlc2hUb2tlbihlbnRyeSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIG9hdXRoTG9nZ2VyLndhcm4oXG4gICAgICAgICAgYHJlZnJlc2ggZmFpbGVkIGZvciAke2VudHJ5Lm5hbWV9OiAke2UgaW5zdGFuY2VvZiBFcnJvciA/IGUubWVzc2FnZSA6IFN0cmluZyhlKX1gLFxuICAgICAgICApO1xuXG4gICAgICAgIHJldHVybiB7IGVycm9yOiBcIlRva2VuIHJlZnJlc2ggZmFpbGVkOyB1c2FnZSBpcyB1bmF2YWlsYWJsZVwiIH07XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgcmF3ID0gYXdhaXQgZmV0Y2hVc2FnZShhY2Nlc3NUb2tlbik7XG5cbiAgICBpZiAocmF3LmVycm9yICYmIGdldFJlZnJlc2hUb2tlbihlbnRyeS5jcmVkZW50aWFscykpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGFjY2Vzc1Rva2VuID0gYXdhaXQgdGhpcy5yZWZyZXNoVG9rZW4oZW50cnkpO1xuICAgICAgICBjb25zdCByZXRyaWVkID0gYXdhaXQgZmV0Y2hVc2FnZShhY2Nlc3NUb2tlbik7XG5cbiAgICAgICAgaWYgKHJldHJpZWQuZXJyb3IpIHJldHVybiB7IGVycm9yOiByZXRyaWVkLmVycm9yIH07XG5cbiAgICAgICAgcmV0dXJuIGNvbnZlcnRBbnRocm9waWNVc2FnZShyZXRyaWVkKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgb2F1dGhMb2dnZXIud2FybihcbiAgICAgICAgICBgcmVmcmVzaCBmYWlsZWQgZm9yICR7ZW50cnkubmFtZX06ICR7ZSBpbnN0YW5jZW9mIEVycm9yID8gZS5tZXNzYWdlIDogU3RyaW5nKGUpfWAsXG4gICAgICAgICk7XG5cbiAgICAgICAgcmV0dXJuIHsgZXJyb3I6IFwiVG9rZW4gcmVmcmVzaCBmYWlsZWQ7IHVzYWdlIGlzIHVuYXZhaWxhYmxlXCIgfTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAocmF3LmVycm9yKSByZXR1cm4geyBlcnJvcjogcmF3LmVycm9yIH07XG5cbiAgICByZXR1cm4gY29udmVydEFudGhyb3BpY1VzYWdlKHJhdyk7XG4gIH1cblxuICAvLyDrj5nsi5wgcmVmcmVzaCDqsIAg7ZqM7KCE7J2EIOqyuey5mOuptCDrkqTriqbsnYAg7Zi47Lac7J20IOydtOuvuCDtj5DquLDrkJwgcmVmcmVzaCB0b2tlbiDsnYQg7JOw6rKMIOuQmOyWtFxuICAvLyDrqYDsqaHtlZwg7Yag7YGw7J20IOyCrOunneycvOuhnCDsmKTtjJDrkJzri6QuIG9wZW5haS1yZWZyZXNoLnRzIOyZgCDqsJnsnYAgcGVyLXRva2VuIGRlZHVwIOydhCDrkZTri6QuXG4gIGFzeW5jIHJlZnJlc2hUb2tlbih0b2tlbjogUmVmcmVzaGFibGVUb2tlbik6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgaWYgKHRva2VuLnByb3ZpZGVyID09PSBcImdyb2tcIikgcmV0dXJuIHRoaXMucmVmcmVzaEdyb2tUb2tlbih0b2tlbik7XG4gICAgY29uc3QgaW5mbGlnaHQgPSBpbmZsaWdodEFudGhyb3BpY1JlZnJlc2guZ2V0KHRva2VuLmlkKTtcblxuICAgIGlmIChpbmZsaWdodCkgcmV0dXJuIGluZmxpZ2h0O1xuXG4gICAgY29uc3QgcHJvbWlzZSA9IHRoaXMuZG9SZWZyZXNoVG9rZW4odG9rZW4pO1xuICAgIGluZmxpZ2h0QW50aHJvcGljUmVmcmVzaC5zZXQodG9rZW4uaWQsIHByb21pc2UpO1xuXG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBhd2FpdCBwcm9taXNlO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBpbmZsaWdodEFudGhyb3BpY1JlZnJlc2guZGVsZXRlKHRva2VuLmlkKTtcbiAgICB9XG4gIH1cblxuICAvLyBTZXQgYnkgYm9vdHN0cmFwOyB0aGUgc2FtZSBjb29yZGluYXRvciB0aGUgR3Jva0Rpc3BhdGNoZXIgdXNlcywgc28gcmVmcmVzaGVzIGFyZSBzaW5nbGUtZmxpZ2h0LlxuICBncm9rUmVmcmVzaGVyOiBHcm9rUmVmcmVzaENvb3JkaW5hdG9yIHwgbnVsbCA9IG51bGw7XG5cbiAgYXN5bmMgcmVmcmVzaEdyb2tUb2tlbih0b2tlbjogUmVmcmVzaGFibGVUb2tlbik6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgaWYgKCF0aGlzLmdyb2tSZWZyZXNoZXIpIHRocm93IG5ldyBFcnJvcihcIkdyb2sgcmVmcmVzaGVyIG5vdCBpbml0aWFsaXplZFwiKTtcbiAgICBjb25zdCBjdXJyZW50ID0gU3RyaWN0R3Jva0NyZWRlbnRpYWxzLnBhcnNlKHRva2VuLmNyZWRlbnRpYWxzKTtcblxuICAgIGNvbnN0IG5leHQgPSBhd2FpdCB0aGlzLmdyb2tSZWZyZXNoZXIucmVmcmVzaCh0b2tlbi5pZCwgY3VycmVudCwgKGNyZWRzKSA9PlxuICAgICAgcGVyc2lzdEdyb2tDcmVkZW50aWFscyh0b2tlbi5pZCwgY3JlZHMpLFxuICAgICk7XG5cbiAgICByZXR1cm4gbmV4dC5hY2Nlc3NUb2tlbjtcbiAgfVxuXG4gIGFzeW5jIGRvUmVmcmVzaFRva2VuKHRva2VuOiBSZWZyZXNoYWJsZVRva2VuKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBjcmVkcyA9IHRva2VuLmNyZWRlbnRpYWxzO1xuICAgIGNvbnN0IHJ0ID0gZ2V0UmVmcmVzaFRva2VuKGNyZWRzKTtcblxuICAgIGlmICghcnQpIHRocm93IG5ldyBFcnJvcihcIk5vIHJlZnJlc2ggdG9rZW5cIik7XG5cbiAgICBsZXQgcmVmcmVzaGVkO1xuXG4gICAgdHJ5IHtcbiAgICAgIHJlZnJlc2hlZCA9IGF3YWl0IHJlZnJlc2hBY2Nlc3NUb2tlbihydCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKGUgaW5zdGFuY2VvZiBSZWZyZXNoRmFpbGVkRXJyb3IgJiYgZS5pc0F1dGhEZWFkKCkpIHtcbiAgICAgICAgYXdhaXQgZGVhY3RpdmF0ZUF1dGhEZWFkVG9rZW4odG9rZW4sIGBhbnRocm9waWM6JHtlLnN0YXR1c31gKTtcbiAgICAgIH1cblxuICAgICAgdGhyb3cgZTtcbiAgICB9XG5cbiAgICBjb25zdCB1cGRhdGVkID0gVG9rZW5DcmVkZW50aWFscy5wYXJzZSh7XG4gICAgICAuLi5jcmVkcyxcbiAgICAgIGFjY2Vzc1Rva2VuOiByZWZyZXNoZWQuYWNjZXNzVG9rZW4sXG4gICAgICByZWZyZXNoVG9rZW46IHJlZnJlc2hlZC5yZWZyZXNoVG9rZW4sXG4gICAgICBleHBpcmVzQXQ6IHJlZnJlc2hlZC5leHBpcmVzQXQsXG4gICAgfSk7XG5cbiAgICBhd2FpdCBUb2tlbk1vZGVsLnNhdmUoW1xuICAgICAge1xuICAgICAgICBpZDogdG9rZW4uaWQsXG4gICAgICAgIHByb3ZpZGVyOiB0b2tlbi5wcm92aWRlcixcbiAgICAgICAgY3JlZGVudGlhbHM6IHVwZGF0ZWQsXG4gICAgICAgIG5hbWU6IHRva2VuLm5hbWUsXG4gICAgICAgIHJlYXV0aF9yZXF1aXJlZDogZmFsc2UsXG4gICAgICB9LFxuICAgIF0pO1xuXG4gICAgcmV0dXJuIHJlZnJlc2hlZC5hY2Nlc3NUb2tlbjtcbiAgfVxuXG4gIEBhcGkoeyBodHRwTWV0aG9kOiBcIkdFVFwiLCBjbGllbnRzOiBbXCJheGlvc1wiLCBcInRhbnN0YWNrLXF1ZXJ5XCJdIH0pXG4gIGFzeW5jIGhlYWx0aCgpOiBQcm9taXNlPEhlYWx0aFJlc3BvbnNlPiB7XG4gICAgY29uc3QgcHJvdmlkZXJzID0geyAuLi5RZ3JpZERpc3BhdGNoZXIuc3RhcnR1cFN0YXRlIH07XG5cbiAgICByZXR1cm4ge1xuICAgICAgc3RhdHVzOiBcIm9rXCIsXG4gICAgICBhY3RpdmVUb2tlbnM6IFFncmlkRGlzcGF0Y2hlci50b2tlbnMuc2l6ZSxcbiAgICAgIHN1YnNjcmliZXI6IFFncmlkRGlzcGF0Y2hlci5zdWJzY3JpYmVyPy5zdGF0dXMoKSA/PyBudWxsLFxuICAgICAgLy8gcHJvdmlkZXIg67OEIOudvOyasO2MheydtOudvCDtlZjrgpjrp4wg7KSA67mE64+864+EIOq3uCBwcm92aWRlciDsmpTssq3snYAg7LKY66as65Cc64ukLlxuICAgICAgcmVhZHk6IE9iamVjdC52YWx1ZXMocHJvdmlkZXJzKS5pbmNsdWRlcyhcInJlYWR5XCIpLFxuICAgICAgcHJvdmlkZXJzLFxuICAgIH07XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IFFncmlkRnJhbWUgPSBuZXcgUWdyaWRGcmFtZUNsYXNzKCk7XG5cbmZ1bmN0aW9uIGNvbnZlcnRBbnRocm9waWNVc2FnZShyYXc6IEFudGhyb3BpY1VzYWdlUmF3KTogVXNhZ2VSZXNwb25zZSB7XG4gIHJldHVybiB7XG4gICAgcHJvdmlkZXI6IFwiYW50aHJvcGljXCIsXG4gICAgZml2ZUhvdXI6IHJhdy5maXZlX2hvdXJcbiAgICAgID8geyB1dGlsaXphdGlvbjogcmF3LmZpdmVfaG91ci51dGlsaXphdGlvbiwgcmVzZXRzQXQ6IHJhdy5maXZlX2hvdXIucmVzZXRzX2F0IH1cbiAgICAgIDogbnVsbCxcbiAgICBzZXZlbkRheTogcmF3LnNldmVuX2RheVxuICAgICAgPyB7IHV0aWxpemF0aW9uOiByYXcuc2V2ZW5fZGF5LnV0aWxpemF0aW9uLCByZXNldHNBdDogcmF3LnNldmVuX2RheS5yZXNldHNfYXQgfVxuICAgICAgOiBudWxsLFxuICB9O1xufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQStJQSxNQUFNLGlDQUFpQixJ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