@cartanova/qgrid-cli 2.10.10 → 2.11.1

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 (302) 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 +21 -19
  10. package/bundle/dist/application/qgrid/qgrid-run-lifecycle.js +40 -33
  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 -70
  24. package/bundle/dist/application/request-log/request-log.types.js +1 -1
  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 +32 -16
  33. package/bundle/dist/application/sonamu.generated.sso.js +1 -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 +1 -1
  39. package/bundle/dist/migrations/20260807133553_manual__backfill_request_log_cost.js +8 -6
  40. package/bundle/dist/server-bootstrap.js +4 -2
  41. package/bundle/dist/server-error-handler.js +1 -1
  42. package/bundle/dist/sonamu.config.js +37 -8
  43. package/bundle/dist/startup-migrations.js +17 -7
  44. package/bundle/dist/testing/global.js +1 -1
  45. package/bundle/dist/testing/schema-bench.js +0 -0
  46. package/bundle/dist/testing/test-database-name.js +1 -1
  47. package/bundle/dist/utils/providers/anthropic/anthropic-constants.js +1 -1
  48. package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +11 -5
  49. package/bundle/dist/utils/providers/anthropic/anthropic-quota.js +4 -4
  50. package/bundle/dist/utils/providers/anthropic/anthropic-thinking.js +1 -1
  51. package/bundle/dist/utils/providers/anthropic/claude-session.js +20 -19
  52. package/bundle/dist/utils/providers/anthropic/fence-strip.js +1 -1
  53. package/bundle/dist/utils/providers/anthropic/stream-json-adapter.js +49 -23
  54. package/bundle/dist/utils/providers/common/credentials.js +5 -1
  55. package/bundle/dist/utils/providers/common/effort.js +3 -3
  56. package/bundle/dist/utils/providers/common/model-cost.js +69 -14
  57. package/bundle/dist/utils/providers/common/provider-types.js +29 -1
  58. package/bundle/dist/utils/providers/common/schema-validation.js +78 -40
  59. package/bundle/dist/utils/providers/common/smooth-weighted-round-robin.js +1 -1
  60. package/bundle/dist/utils/providers/common/strictifier.js +62 -43
  61. package/bundle/dist/utils/providers/common/thinking.js +3 -2
  62. package/bundle/dist/utils/providers/common/ttft.js +1 -1
  63. package/bundle/dist/utils/providers/grok/grok-backend-protocol.js +427 -0
  64. package/bundle/dist/utils/providers/grok/grok-constants.js +55 -0
  65. package/bundle/dist/utils/providers/grok/grok-direct-client.js +196 -0
  66. package/bundle/dist/utils/providers/grok/grok-dispatcher.js +1313 -0
  67. package/bundle/dist/utils/providers/grok/grok-headers.js +118 -0
  68. package/bundle/dist/utils/providers/grok/grok-media-client.js +420 -0
  69. package/bundle/dist/utils/providers/grok/grok-models.js +114 -0
  70. package/bundle/dist/utils/providers/grok/grok-oauth.js +455 -0
  71. package/bundle/dist/utils/providers/grok/grok-quota.js +119 -0
  72. package/bundle/dist/utils/providers/grok/grok-refresh.js +192 -0
  73. package/bundle/dist/utils/providers/grok/grok-types.js +186 -0
  74. package/bundle/dist/utils/providers/grok/grok-voice-client.js +199 -0
  75. package/bundle/dist/utils/providers/grok/index.js +11 -0
  76. package/bundle/dist/utils/providers/openai/openai-backend-protocol.js +111 -83
  77. package/bundle/dist/utils/providers/openai/openai-callback-relay.js +3 -2
  78. package/bundle/dist/utils/providers/openai/openai-constants.js +1 -1
  79. package/bundle/dist/utils/providers/openai/openai-direct-client.js +23 -7
  80. package/bundle/dist/utils/providers/openai/openai-dispatcher.js +143 -106
  81. package/bundle/dist/utils/providers/openai/openai-image-generation.js +48 -33
  82. package/bundle/dist/utils/providers/openai/openai-oauth.js +28 -13
  83. package/bundle/dist/utils/providers/openai/openai-quota.js +38 -27
  84. package/bundle/dist/utils/providers/openai/openai-refresh.js +17 -9
  85. package/bundle/dist/utils/providers/openai/openai-sse.js +1 -1
  86. package/bundle/dist/utils/providers/openai/openai-transport-config.js +1 -1
  87. package/bundle/dist/utils/quiet-hours.js +1 -1
  88. package/bundle/dist/utils/slack-notify.js +14 -8
  89. package/bundle/dist/utils/subset-loaders.js +4 -5
  90. package/bundle/src/application/monit/log-buffer.ts +23 -9
  91. package/bundle/src/application/monit/monit.frame.ts +22 -5
  92. package/bundle/src/application/monit/monit.types.ts +6 -0
  93. package/bundle/src/application/qgrid/conv-routing.test.ts +76 -4
  94. package/bundle/src/application/qgrid/conv-routing.ts +35 -9
  95. package/bundle/src/application/qgrid/expired-token-reminder.ts +9 -1
  96. package/bundle/src/application/qgrid/oauth.ts +51 -15
  97. package/bundle/src/application/qgrid/qgrid-image-generation.ts +9 -0
  98. package/bundle/src/application/qgrid/qgrid-response-format.ts +50 -25
  99. package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +19 -0
  100. package/bundle/src/application/qgrid/qgrid-run-lifecycle.ts +84 -40
  101. package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +97 -0
  102. package/bundle/src/application/qgrid/qgrid.dispatcher.ts +274 -126
  103. package/bundle/src/application/qgrid/qgrid.frame.test.ts +1013 -3
  104. package/bundle/src/application/qgrid/qgrid.frame.ts +1415 -60
  105. package/bundle/src/application/qgrid/qgrid.types.ts +335 -0
  106. package/bundle/src/application/qgrid/schema-prompt.ts +105 -41
  107. package/bundle/src/application/qgrid/slack-user-map.ts +5 -0
  108. package/bundle/src/application/qgrid/token-death.ts +4 -0
  109. package/bundle/src/application/qgrid/token-subscriber.test.ts +21 -19
  110. package/bundle/src/application/qgrid/token-subscriber.ts +186 -53
  111. package/bundle/src/application/qgrid/token-trigger-setup.ts +2 -0
  112. package/bundle/src/application/qgrid/token-window-keepalive.ts +49 -6
  113. package/bundle/src/application/qgrid/tool-emulation-schema.ts +33 -29
  114. package/bundle/src/application/qgrid/tool-emulation.ts +52 -27
  115. package/bundle/src/application/request-log/json-schema-type-text.test.ts +5 -5
  116. package/bundle/src/application/request-log/json-schema-type-text.ts +81 -26
  117. package/bundle/src/application/request-log/request-log.model.test.ts +111 -4
  118. package/bundle/src/application/request-log/request-log.model.ts +277 -146
  119. package/bundle/src/application/request-log/request-log.types.ts +6 -0
  120. package/bundle/src/application/request-log/zod-code-format.ts +11 -0
  121. package/bundle/src/application/request-log-step/request-log-step.model.ts +1 -0
  122. package/bundle/src/application/request-log-step/request-log-step.types.ts +2 -0
  123. package/bundle/src/application/setting/setting.constant.ts +9 -0
  124. package/bundle/src/application/setting/setting.model.ts +12 -2
  125. package/bundle/src/application/setting/setting.store.ts +5 -1
  126. package/bundle/src/application/setting/setting.types.ts +8 -0
  127. package/bundle/src/application/sonamu.generated.http +133 -0
  128. package/bundle/src/application/sonamu.generated.sso.ts +2 -0
  129. package/bundle/src/application/sonamu.generated.ts +15 -0
  130. package/bundle/src/application/token/token.identity.test.ts +20 -0
  131. package/bundle/src/application/token/token.model.ts +66 -7
  132. package/bundle/src/application/token/token.types.ts +24 -1
  133. package/bundle/src/i18n/en.ts +19 -0
  134. package/bundle/src/i18n/ko.ts +21 -0
  135. package/bundle/src/i18n/sd.generated.ts +23 -2
  136. package/bundle/src/migrations/20260807133553_manual__backfill_request_log_cost.ts +16 -8
  137. package/bundle/src/server-bootstrap.ts +4 -2
  138. package/bundle/src/server-error-handler.ts +1 -0
  139. package/bundle/src/sonamu.config.ts +69 -7
  140. package/bundle/src/startup-migrations.ts +27 -9
  141. package/bundle/src/testing/global.ts +20 -0
  142. package/bundle/src/testing/schema-bench.ts +105 -30
  143. package/bundle/src/testing/test-database-name.ts +2 -0
  144. package/bundle/src/utils/providers/anthropic/anthropic-constants.ts +8 -0
  145. package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +41 -6
  146. package/bundle/src/utils/providers/anthropic/anthropic-quota.ts +7 -3
  147. package/bundle/src/utils/providers/anthropic/anthropic-thinking.ts +6 -0
  148. package/bundle/src/utils/providers/anthropic/claude-session.ts +58 -24
  149. package/bundle/src/utils/providers/anthropic/fence-strip.ts +11 -0
  150. package/bundle/src/utils/providers/anthropic/stream-json-adapter.ts +110 -45
  151. package/bundle/src/utils/providers/common/credentials.ts +8 -0
  152. package/bundle/src/utils/providers/common/effort.ts +9 -2
  153. package/bundle/src/utils/providers/common/model-cost.test.ts +48 -1
  154. package/bundle/src/utils/providers/common/model-cost.ts +259 -158
  155. package/bundle/src/utils/providers/common/provider-dispatcher.ts +98 -2
  156. package/bundle/src/utils/providers/common/provider-types.ts +46 -3
  157. package/bundle/src/utils/providers/common/schema-validation.test.ts +5 -1
  158. package/bundle/src/utils/providers/common/schema-validation.ts +124 -56
  159. package/bundle/src/utils/providers/common/smooth-weighted-round-robin.ts +4 -0
  160. package/bundle/src/utils/providers/common/strictifier.ts +185 -59
  161. package/bundle/src/utils/providers/common/thinking.ts +2 -2
  162. package/bundle/src/utils/providers/common/ttft.ts +4 -2
  163. package/bundle/src/utils/providers/grok/__fixtures__/golden-responses-1.0.60.json +164 -0
  164. package/bundle/src/utils/providers/grok/grok-backend-protocol.test.ts +325 -0
  165. package/bundle/src/utils/providers/grok/grok-backend-protocol.ts +721 -0
  166. package/bundle/src/utils/providers/grok/grok-constants.ts +105 -0
  167. package/bundle/src/utils/providers/grok/grok-direct-client.test.ts +179 -0
  168. package/bundle/src/utils/providers/grok/grok-direct-client.ts +313 -0
  169. package/bundle/src/utils/providers/grok/grok-dispatcher.test.ts +1395 -0
  170. package/bundle/src/utils/providers/grok/grok-dispatcher.ts +2105 -0
  171. package/bundle/src/utils/providers/grok/grok-headers.test.ts +149 -0
  172. package/bundle/src/utils/providers/grok/grok-headers.ts +199 -0
  173. package/bundle/src/utils/providers/grok/grok-media-client.test.ts +446 -0
  174. package/bundle/src/utils/providers/grok/grok-media-client.ts +703 -0
  175. package/bundle/src/utils/providers/grok/grok-models.test.ts +96 -0
  176. package/bundle/src/utils/providers/grok/grok-models.ts +161 -0
  177. package/bundle/src/utils/providers/grok/grok-oauth.test.ts +406 -0
  178. package/bundle/src/utils/providers/grok/grok-oauth.ts +771 -0
  179. package/bundle/src/utils/providers/grok/grok-quota.test.ts +142 -0
  180. package/bundle/src/utils/providers/grok/grok-quota.ts +198 -0
  181. package/bundle/src/utils/providers/grok/grok-refresh.test.ts +239 -0
  182. package/bundle/src/utils/providers/grok/grok-refresh.ts +325 -0
  183. package/bundle/src/utils/providers/grok/grok-types.test.ts +252 -0
  184. package/bundle/src/utils/providers/grok/grok-types.ts +374 -0
  185. package/bundle/src/utils/providers/grok/grok-voice-client.test.ts +321 -0
  186. package/bundle/src/utils/providers/grok/grok-voice-client.ts +284 -0
  187. package/bundle/src/utils/providers/grok/index.ts +20 -0
  188. package/bundle/src/utils/providers/openai/openai-backend-protocol.ts +221 -137
  189. package/bundle/src/utils/providers/openai/openai-callback-relay.ts +12 -1
  190. package/bundle/src/utils/providers/openai/openai-constants.ts +2 -0
  191. package/bundle/src/utils/providers/openai/openai-direct-client.ts +111 -21
  192. package/bundle/src/utils/providers/openai/openai-dispatcher.ts +322 -169
  193. package/bundle/src/utils/providers/openai/openai-image-generation.ts +116 -36
  194. package/bundle/src/utils/providers/openai/openai-oauth.ts +48 -20
  195. package/bundle/src/utils/providers/openai/openai-quota.ts +77 -46
  196. package/bundle/src/utils/providers/openai/openai-refresh.ts +42 -18
  197. package/bundle/src/utils/providers/openai/openai-sse.ts +27 -3
  198. package/bundle/src/utils/providers/openai/openai-transport-config.ts +2 -0
  199. package/bundle/src/utils/quiet-hours.ts +12 -1
  200. package/bundle/src/utils/slack-notify.ts +44 -13
  201. package/bundle/src/utils/subset-loaders.ts +7 -7
  202. package/bundle/web-dist/client/assets/clsx-5XM_pHvN.js +1 -0
  203. package/bundle/web-dist/client/assets/index-Be2qCZmI.css +1 -0
  204. package/bundle/web-dist/client/assets/index-C96h3feE.js +32 -0
  205. package/bundle/web-dist/client/assets/logs-DBM6U0QD.js +1 -0
  206. package/bundle/web-dist/client/assets/monit-BBjXa7vB.js +1 -0
  207. package/bundle/web-dist/client/assets/routes-Crz_PQzi.js +5 -0
  208. package/bundle/web-dist/client/assets/{services.generated-NP-ValHd.js → services.generated-B5lc3aIC.js} +5 -5
  209. package/bundle/web-dist/client/assets/settings-Cdwm3OBB.js +1 -0
  210. package/bundle/web-dist/client/assets/show-DBUhALT1.js +2 -0
  211. package/bundle/web-dist/client/assets/tokens-CVQAVJTo.js +1 -0
  212. package/bundle/web-dist/client/assets/total-cost-MnfKU8IN.js +1 -0
  213. package/bundle/web-dist/client/assets/use-oauth-login-flow-BfxYI4Oh.js +1 -0
  214. package/bundle/web-dist/client/assets/use-update-token-mutation-qKBC2sn7.js +1 -0
  215. package/bundle/web-dist/client/assets/{vendor-tanstack-DJRQAbrY.js → vendor-tanstack-DRPs09ai.js} +1 -1
  216. package/bundle/web-dist/client/index.html +5 -5
  217. package/bundle/web-dist/server/assets/clsx-D_N5PN_2.js +16 -0
  218. package/bundle/web-dist/server/assets/{lazyRouteComponent-CgBdabgd.js → lazyRouteComponent-AKiHfZWp.js} +129 -2
  219. package/bundle/web-dist/server/assets/{logs-BMyR98rU.js → logs-B7QmGJq3.js} +18 -14
  220. package/bundle/web-dist/server/assets/{monit-ZPt66W5M.js → monit-DFt7x3bh.js} +13 -12
  221. package/bundle/web-dist/server/assets/{plus-BZ9I0VgC.js → plus-DaYQRpBt.js} +1 -1
  222. package/bundle/web-dist/server/assets/{react-dom-Ds75e4Jl.js → react-dom-Cv23mm1K.js} +2 -129
  223. package/bundle/web-dist/server/assets/{refresh-cw-CztCFis-.js → refresh-cw-BpXNsAy-.js} +1 -1
  224. package/bundle/web-dist/server/assets/{request-model-DjGldb-h.js → request-model-eHE6YbaF.js} +1 -1
  225. package/bundle/web-dist/server/assets/{routes-Ct-k7nBA.js → routes-_Y-PJfgO.js} +110 -39
  226. package/bundle/web-dist/server/assets/{services.generated-BA4AcAf5.js → services.generated-CMJ8AHbO.js} +582 -172
  227. package/bundle/web-dist/server/assets/{settings-CBUZ47Xx.js → settings-JwJKxn2e.js} +14 -14
  228. package/bundle/web-dist/server/assets/{show-LSFIzvO2.js → show-BEv6z1v_.js} +90 -60
  229. package/bundle/web-dist/server/assets/{tokens-DxrBW512.js → tokens-CNT4mI-f.js} +162 -50
  230. package/bundle/web-dist/server/assets/total-cost-fTE9Xy82.js +18 -0
  231. package/bundle/web-dist/server/assets/use-oauth-login-flow-jkAkT3X6.js +2345 -0
  232. package/bundle/web-dist/server/assets/{use-update-token-mutation-pkArIzCP.js → use-update-token-mutation-Sm6kh02m.js} +1 -1
  233. package/bundle/web-dist/server/entry-server.generated.js +1644 -21655
  234. package/dist/cli.js +9 -9
  235. package/package.json +4 -11
  236. package/postinstall.mjs +12 -0
  237. package/skills/qgrid/SKILL.md +1 -0
  238. package/skills/qgrid/references/cli-env-and-server-boot.md +4 -1
  239. package/skills/qgrid/references/decision-rationale.md +23 -0
  240. package/skills/qgrid/references/grok-runtime.md +89 -0
  241. package/skills/qgrid/references/provider-runtime-differences.md +30 -29
  242. package/skills/qgrid/references/repo-map.md +10 -0
  243. package/skills/qgrid/references/token-auth-quota-lifecycle.md +56 -3
  244. package/bundle/dist/node_modules/.pnpm/@jridgewell_sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js +0 -406
  245. package/bundle/dist/node_modules/.pnpm/@vitest_expect@4.1.10/node_modules/@vitest/expect/dist/index.js +0 -1507
  246. package/bundle/dist/node_modules/.pnpm/@vitest_pretty-format@4.1.10/node_modules/@vitest/pretty-format/dist/index.js +0 -887
  247. package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/chunk-artifact.js +0 -2756
  248. package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/index.js +0 -8
  249. package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/utils.js +0 -8
  250. package/bundle/dist/node_modules/.pnpm/@vitest_snapshot@4.1.10/node_modules/@vitest/snapshot/dist/index.js +0 -922
  251. package/bundle/dist/node_modules/.pnpm/@vitest_spy@4.1.10/node_modules/@vitest/spy/dist/index.js +0 -386
  252. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js +0 -121
  253. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/constants.js +0 -51
  254. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/diff.js +0 -1317
  255. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/display.js +0 -561
  256. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/error.js +0 -40
  257. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/helpers.js +0 -272
  258. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/offset.js +0 -27
  259. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/serialize.js +0 -77
  260. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/source-map.js +0 -381
  261. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/timers.js +0 -51
  262. package/bundle/dist/node_modules/.pnpm/chai@6.2.2/node_modules/chai/index.js +0 -2986
  263. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/branding.js +0 -10
  264. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/index.js +0 -109
  265. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/messages.js +0 -10
  266. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/overloads.js +0 -10
  267. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/utils.js +0 -10
  268. package/bundle/dist/node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.js +0 -1126
  269. package/bundle/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/index.js +0 -21
  270. package/bundle/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.js +0 -432
  271. package/bundle/dist/node_modules/.pnpm/tinybench@2.9.0/node_modules/tinybench/dist/index.js +0 -517
  272. package/bundle/dist/node_modules/.pnpm/tinyrainbow@3.1.0/node_modules/tinyrainbow/dist/index.js +0 -101
  273. 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
  274. 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
  275. 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
  276. 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
  277. 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
  278. 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
  279. 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
  280. 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
  281. 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
  282. 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
  283. package/bundle/dist/testing/setup-mocks.js +0 -16
  284. package/bundle/src/testing/setup-mocks.ts +0 -44
  285. package/bundle/web-dist/client/assets/index-Bw2s88Ot.css +0 -1
  286. package/bundle/web-dist/client/assets/index-DZwzUfI-.js +0 -106
  287. package/bundle/web-dist/client/assets/logs-Cog79DU5.js +0 -1
  288. package/bundle/web-dist/client/assets/monit-2auznBys.js +0 -1
  289. package/bundle/web-dist/client/assets/routes-B0lTeLK-.js +0 -5
  290. package/bundle/web-dist/client/assets/settings-D8ZxZGSJ.js +0 -1
  291. package/bundle/web-dist/client/assets/show-CFSERlnM.js +0 -2
  292. package/bundle/web-dist/client/assets/tokens-CZXUyI7O.js +0 -1
  293. package/bundle/web-dist/client/assets/use-oauth-login-flow-hboOs3wG.js +0 -1
  294. package/bundle/web-dist/client/assets/use-update-token-mutation-BQHS0byG.js +0 -1
  295. package/bundle/web-dist/server/assets/use-oauth-login-flow-Gn8flMK5.js +0 -178
  296. package/dist/cli.d.ts +0 -10
  297. /package/bundle/web-dist/client/assets/{cost-DH2jZbrw.js → cost-DB3HbU7T.js} +0 -0
  298. /package/bundle/web-dist/client/assets/{plus-B62CuqT8.js → plus-BsQdY7PS.js} +0 -0
  299. /package/bundle/web-dist/client/assets/{preload-helper-ca-nBW7U.js → preload-helper-DWTEM3RW.js} +0 -0
  300. /package/bundle/web-dist/client/assets/{refresh-cw-NNcU0Cmq.js → refresh-cw-D9IUmT23.js} +0 -0
  301. /package/bundle/web-dist/client/assets/{request-model-CojtinqK.js → request-model-Bpp_rkK8.js} +0 -0
  302. /package/bundle/web-dist/server/assets/{cost-eEHeTRT5.js → cost-BC9yzyA9.js} +0 -0
@@ -0,0 +1,455 @@
1
+ import { GROK_AUTH_ISSUER, GROK_BUILD_VERSION, GROK_CHAT_PROXY_URL, GROK_DEVICE_CODE_URL, GROK_DEVICE_TOKEN_URL, GROK_OAUTH_CLIENT_ID, GROK_OAUTH_REFERRER, GROK_OAUTH_SCOPES } from "./grok-constants.js";
2
+ import { buildGrokProxyGetHeaders, grokShellUserAgent } from "./grok-headers.js";
3
+ import { GrokCredentials, GrokUserSubscription, decodeGrokJwt, isGrokAccessToken } from "./grok-types.js";
4
+ import { z } from "zod";
5
+ import { createHash, randomBytes, randomInt, randomUUID, timingSafeEqual } from "node:crypto";
6
+ //#region src/utils/providers/grok/grok-oauth.ts
7
+ /** Login failure. `retryable` marks network/5xx failures where the same step may be retried. */
8
+ var GrokOAuthError = class extends Error {
9
+ code;
10
+ options;
11
+ name = "GrokOAuthError";
12
+ constructor(code, message, options = {}) {
13
+ super(message);
14
+ this.code = code;
15
+ this.options = options;
16
+ }
17
+ get status() {
18
+ return this.options.status;
19
+ }
20
+ get retryable() {
21
+ return this.options.retryable ?? false;
22
+ }
23
+ /** OAuth `error` code, only when it is a plain lowercase identifier. */
24
+ get oauthError() {
25
+ return this.options.oauthError;
26
+ }
27
+ };
28
+ const GROK_DISCOVERY_TTL_MS = 1440 * 60 * 1e3;
29
+ const GROK_FALLBACK_AUTHORIZATION_ENDPOINT = `${GROK_AUTH_ISSUER}/oauth2/authorize`;
30
+ const GROK_FALLBACK_TOKEN_ENDPOINT = `${GROK_AUTH_ISSUER}/oauth2/token`;
31
+ const DISCOVERY_TIMEOUT_MS = 1e4;
32
+ const TOKEN_TIMEOUT_MS = 15e3;
33
+ const USER_LOOKUP_TIMEOUT_MS = 15e3;
34
+ const DiscoveryDocument = z.looseObject({
35
+ authorization_endpoint: z.string(),
36
+ token_endpoint: z.string()
37
+ });
38
+ let discoveryCache;
39
+ /** Clears the module-level discovery cache (tests and operator resets). */
40
+ function resetGrokDiscoveryCache() {
41
+ discoveryCache = void 0;
42
+ }
43
+ function isTrustedEndpoint(value) {
44
+ let url;
45
+ try {
46
+ url = new URL(value);
47
+ } catch {
48
+ return false;
49
+ }
50
+ return url.protocol === "https:" && !url.username && !url.password && (url.hostname === "x.ai" || url.hostname.endsWith(".x.ai"));
51
+ }
52
+ /**
53
+ * `GET {issuer}/.well-known/openid-configuration`, cached 24 h. Any failure uses the fallback
54
+ * endpoints without caching them, so the next call retries discovery.
55
+ */
56
+ async function getGrokOAuthEndpoints(io = {}) {
57
+ const fetchImpl = io.fetch ?? globalThis.fetch;
58
+ const now = io.now ?? Date.now;
59
+ const cached = discoveryCache;
60
+ if (cached && now() - cached.fetchedAt < 864e5) return cached.endpoints;
61
+ try {
62
+ const response = await fetchImpl(`${GROK_AUTH_ISSUER}/.well-known/openid-configuration`, {
63
+ method: "GET",
64
+ headers: {
65
+ accept: "application/json",
66
+ "user-agent": grokShellUserAgent()
67
+ },
68
+ signal: AbortSignal.timeout(DISCOVERY_TIMEOUT_MS)
69
+ });
70
+ if (response.ok) {
71
+ const document = DiscoveryDocument.safeParse(await response.json());
72
+ if (document.success && isTrustedEndpoint(document.data.authorization_endpoint) && isTrustedEndpoint(document.data.token_endpoint)) {
73
+ const endpoints = {
74
+ authorizationEndpoint: document.data.authorization_endpoint,
75
+ tokenEndpoint: document.data.token_endpoint,
76
+ source: "discovery"
77
+ };
78
+ discoveryCache = {
79
+ endpoints,
80
+ fetchedAt: now()
81
+ };
82
+ return endpoints;
83
+ }
84
+ } else await response.body?.cancel().catch(() => void 0);
85
+ } catch {}
86
+ return {
87
+ authorizationEndpoint: GROK_FALLBACK_AUTHORIZATION_ENDPOINT,
88
+ tokenEndpoint: GROK_FALLBACK_TOKEN_ENDPOINT,
89
+ source: "fallback"
90
+ };
91
+ }
92
+ /** S256 over a base64url verifier of 32 random bytes (oidc/protocol.rs:314-320). */
93
+ function generateGrokPkce() {
94
+ const codeVerifier = randomBytes(32).toString("base64url");
95
+ return {
96
+ codeVerifier,
97
+ codeChallenge: createHash("sha256").update(codeVerifier).digest("base64url")
98
+ };
99
+ }
100
+ /** RFC 3986 unreserved-only encoding, matching Rust `urlencoding::encode` (space → %20). */
101
+ function encodeQueryValue(value) {
102
+ return encodeURIComponent(value).replace(/[!'()*]/g, (char) => `%${char.charCodeAt(0).toString(16).toUpperCase()}`);
103
+ }
104
+ const GROK_OAUTH_SCOPE = GROK_OAUTH_SCOPES.join(" ");
105
+ /** Authorize URL with grok-build's query order (oidc/protocol.rs:321-366). */
106
+ function buildGrokAuthorizeUrl(input) {
107
+ const search = [
108
+ ["response_type", "code"],
109
+ ["client_id", GROK_OAUTH_CLIENT_ID],
110
+ ["redirect_uri", input.redirectUri],
111
+ ["scope", GROK_OAUTH_SCOPE],
112
+ ["code_challenge", input.codeChallenge],
113
+ ["code_challenge_method", "S256"],
114
+ ["state", input.state],
115
+ ["nonce", input.nonce],
116
+ ["referrer", GROK_OAUTH_REFERRER]
117
+ ].map(([key, value]) => `${key}=${encodeQueryValue(value)}`).join("&");
118
+ return `${input.authorizationEndpoint}?${search}`;
119
+ }
120
+ function grokLoopbackRedirectUri(port) {
121
+ if (!Number.isInteger(port) || port < 1 || port > 65535) throw new RangeError("redirect port must be an integer in 1..65535");
122
+ return `http://127.0.0.1:${port}/callback`;
123
+ }
124
+ async function startGrokOAuth(input) {
125
+ if (!input.state) throw new TypeError("state must be non-empty");
126
+ const endpoints = await getGrokOAuthEndpoints(input);
127
+ const pkce = generateGrokPkce();
128
+ const redirectUri = grokLoopbackRedirectUri(input.redirectPort ?? randomInt(49152, 65536));
129
+ return {
130
+ authorizeUrl: buildGrokAuthorizeUrl({
131
+ authorizationEndpoint: endpoints.authorizationEndpoint,
132
+ redirectUri,
133
+ codeChallenge: pkce.codeChallenge,
134
+ state: input.state,
135
+ nonce: randomUUID()
136
+ }),
137
+ verifier: pkce.codeVerifier,
138
+ redirectUri
139
+ };
140
+ }
141
+ const OAUTH_ERROR_CODE = /^[a-z_]{1,80}$/;
142
+ function safeOAuthErrorCode(value) {
143
+ return OAUTH_ERROR_CODE.test(value) ? value : void 0;
144
+ }
145
+ /** Accepts the full callback URL or a bare authorization code (oidc/login.rs:30-60). */
146
+ function parseGrokCallbackInput(input) {
147
+ const trimmed = input.trim();
148
+ if (!trimmed) throw new GrokOAuthError("invalid_callback_input", "empty callback input");
149
+ let url;
150
+ try {
151
+ url = new URL(trimmed);
152
+ } catch {
153
+ url = void 0;
154
+ }
155
+ if (url) {
156
+ const code = url.searchParams.get("code");
157
+ if (code) return {
158
+ code,
159
+ state: url.searchParams.get("state") ?? ""
160
+ };
161
+ const error = url.searchParams.get("error");
162
+ if (error) {
163
+ const oauthError = safeOAuthErrorCode(error);
164
+ throw new GrokOAuthError("authorization_failed", `authorization failed: ${oauthError ?? "unknown_error"}`, oauthError === void 0 ? {} : { oauthError });
165
+ }
166
+ throw new GrokOAuthError("invalid_callback_input", "callback URL has no code parameter");
167
+ }
168
+ if (/\s/.test(trimmed)) throw new GrokOAuthError("invalid_callback_input", "authorization code contains whitespace");
169
+ return {
170
+ code: trimmed,
171
+ state: ""
172
+ };
173
+ }
174
+ function statesEqual(expected, received) {
175
+ const a = Buffer.from(expected);
176
+ const b = Buffer.from(received);
177
+ return a.length === b.length && timingSafeEqual(a, b);
178
+ }
179
+ const GrokTokenResponse = z.looseObject({
180
+ access_token: z.string().min(1),
181
+ refresh_token: z.string().min(1).nullish(),
182
+ id_token: z.string().nullish(),
183
+ expires_in: z.number().nonnegative().nullish(),
184
+ scope: z.string().nullish(),
185
+ token_type: z.string().nullish()
186
+ });
187
+ const OAuthErrorBody = z.looseObject({ error: z.string() });
188
+ /** Reads the OAuth `error` code from a failed response without retaining the body. */
189
+ async function readGrokOAuthErrorCode(response) {
190
+ const text = await response.text().catch(() => "");
191
+ try {
192
+ const parsed = OAuthErrorBody.safeParse(JSON.parse(text));
193
+ return parsed.success ? safeOAuthErrorCode(parsed.data.error) : void 0;
194
+ } catch {
195
+ return;
196
+ }
197
+ }
198
+ function formHeaders(extra = {}) {
199
+ return {
200
+ "user-agent": grokShellUserAgent(),
201
+ ...extra,
202
+ "content-type": "application/x-www-form-urlencoded",
203
+ accept: "application/json"
204
+ };
205
+ }
206
+ async function parseTokenResponse(response) {
207
+ let body;
208
+ try {
209
+ body = await response.json();
210
+ } catch {
211
+ throw new GrokOAuthError("invalid_token_response", "token response is not JSON");
212
+ }
213
+ const parsed = GrokTokenResponse.safeParse(body);
214
+ if (!parsed.success) throw new GrokOAuthError("invalid_token_response", "token response failed validation");
215
+ return parsed.data;
216
+ }
217
+ function networkError(code, what, cause) {
218
+ return new GrokOAuthError(code, `${what} request failed (${cause instanceof Error ? cause.name : "unknown"})`, { retryable: true });
219
+ }
220
+ /**
221
+ * Validates the token response, resolves the account id (JWT `sub`, confirmed by
222
+ * `GET /user?include=subscription`), and builds stored credentials.
223
+ */
224
+ async function finishGrokLogin(input) {
225
+ const fetchImpl = input.fetch ?? globalThis.fetch;
226
+ const now = input.now ?? Date.now;
227
+ const { tokens } = input;
228
+ if (!isGrokAccessToken(tokens.access_token)) throw new GrokOAuthError("invalid_access_token", `access token is not an at+jwt issued by ${GROK_AUTH_ISSUER}`);
229
+ if (!tokens.refresh_token) throw new GrokOAuthError("missing_refresh_token", "token response has no refresh token");
230
+ const decoded = decodeGrokJwt(tokens.access_token);
231
+ const subject = decoded?.payload.sub;
232
+ if (!subject) throw new GrokOAuthError("user_id_unresolved", "access token has no subject (sub) claim");
233
+ let response;
234
+ try {
235
+ response = await fetchImpl(`${GROK_CHAT_PROXY_URL}/user?include=subscription`, {
236
+ method: "GET",
237
+ headers: buildGrokProxyGetHeaders({
238
+ bearer: tokens.access_token,
239
+ userId: subject
240
+ }),
241
+ signal: AbortSignal.timeout(USER_LOOKUP_TIMEOUT_MS)
242
+ });
243
+ } catch (error) {
244
+ throw networkError("user_lookup_failed", "user lookup", error);
245
+ }
246
+ if (!response.ok) {
247
+ await response.body?.cancel().catch(() => void 0);
248
+ throw new GrokOAuthError("user_lookup_failed", `user lookup failed: HTTP ${response.status}`, {
249
+ status: response.status,
250
+ retryable: response.status >= 500 || response.status === 429
251
+ });
252
+ }
253
+ let userBody;
254
+ try {
255
+ userBody = await response.json();
256
+ } catch {
257
+ throw new GrokOAuthError("user_id_unresolved", "user lookup returned non-JSON");
258
+ }
259
+ const user = GrokUserSubscription.safeParse(userBody);
260
+ if (!user.success) throw new GrokOAuthError("user_id_unresolved", "user lookup did not return a valid userId");
261
+ const issuedAt = now();
262
+ const expiresIn = tokens.expires_in;
263
+ const jwtExpiry = decoded?.payload.exp;
264
+ const expiresAtMs = expiresIn !== void 0 && expiresIn !== null ? issuedAt + expiresIn * 1e3 : jwtExpiry !== void 0 ? jwtExpiry * 1e3 : void 0;
265
+ if (expiresAtMs === void 0 || !Number.isFinite(expiresAtMs)) throw new GrokOAuthError("missing_expiry", "token response has no expiry");
266
+ const grantedScopes = tokens.scope?.split(" ").filter(Boolean);
267
+ const candidate = {
268
+ authMode: "oauth",
269
+ accessToken: tokens.access_token,
270
+ refreshToken: tokens.refresh_token,
271
+ expiresAt: new Date(expiresAtMs).toISOString(),
272
+ issuer: GROK_AUTH_ISSUER,
273
+ clientId: GROK_OAUTH_CLIENT_ID,
274
+ scopes: grantedScopes && grantedScopes.length > 0 ? grantedScopes : [...input.requestedScopes ?? GROK_OAUTH_SCOPES],
275
+ userId: user.data.userId,
276
+ sessionId: randomUUID(),
277
+ agentId: randomUUID()
278
+ };
279
+ if (user.data.subscriptionTier) candidate.subscriptionTier = user.data.subscriptionTier;
280
+ const credentials = GrokCredentials.safeParse(candidate);
281
+ if (!credentials.success) throw new GrokOAuthError("invalid_credentials", "credentials failed validation");
282
+ return credentials.data;
283
+ }
284
+ async function completeGrokOAuth(input) {
285
+ const fetchImpl = input.fetch ?? globalThis.fetch;
286
+ const callback = parseGrokCallbackInput(input.codeOrUrl);
287
+ if (callback.state && !statesEqual(input.state, callback.state)) throw new GrokOAuthError("state_mismatch", "OAuth state mismatch");
288
+ const endpoints = await getGrokOAuthEndpoints(input);
289
+ let response;
290
+ try {
291
+ response = await fetchImpl(endpoints.tokenEndpoint, {
292
+ method: "POST",
293
+ headers: formHeaders({ "x-grok-client-version": GROK_BUILD_VERSION }),
294
+ body: new URLSearchParams([
295
+ ["grant_type", "authorization_code"],
296
+ ["code", callback.code],
297
+ ["redirect_uri", input.redirectUri],
298
+ ["client_id", GROK_OAUTH_CLIENT_ID],
299
+ ["code_verifier", input.verifier]
300
+ ]),
301
+ signal: AbortSignal.timeout(TOKEN_TIMEOUT_MS)
302
+ });
303
+ } catch (error) {
304
+ throw networkError("token_exchange_failed", "token exchange", error);
305
+ }
306
+ if (!response.ok) {
307
+ const oauthError = await readGrokOAuthErrorCode(response);
308
+ const errorOptions = { status: response.status };
309
+ if (oauthError !== void 0) errorOptions.oauthError = oauthError;
310
+ errorOptions.retryable = response.status >= 500;
311
+ throw new GrokOAuthError("token_exchange_failed", `token exchange failed: HTTP ${response.status} ${oauthError ?? "unknown"}`, errorOptions);
312
+ }
313
+ return finishGrokLogin({
314
+ ...input,
315
+ fetch: fetchImpl,
316
+ tokens: await parseTokenResponse(response)
317
+ });
318
+ }
319
+ const GROK_DEVICE_DEFAULT_INTERVAL_S = 5;
320
+ const GROK_DEVICE_SLOW_DOWN_INCREMENT_S = 5;
321
+ const DEVICE_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code";
322
+ const DEVICE_CLIENT_SURFACE = "ui";
323
+ function isAllowedVerificationUri(value) {
324
+ for (let index = 0; index < value.length; index++) {
325
+ const code = value.charCodeAt(index);
326
+ if (code < 32 || code === 127) return false;
327
+ }
328
+ let url;
329
+ try {
330
+ url = new URL(value);
331
+ } catch {
332
+ return false;
333
+ }
334
+ if (url.protocol === "https:") return true;
335
+ return url.protocol === "http:" && (url.hostname === "localhost" || url.hostname === "127.0.0.1");
336
+ }
337
+ const DeviceCodeResponse = z.looseObject({
338
+ device_code: z.string().min(1),
339
+ user_code: z.string().regex(/^[A-Za-z0-9-]+$/),
340
+ verification_uri: z.string().refine(isAllowedVerificationUri),
341
+ verification_uri_complete: z.string().refine(isAllowedVerificationUri).nullish(),
342
+ expires_in: z.number().positive(),
343
+ interval: z.number().int().positive().nullish()
344
+ });
345
+ function deviceHeaders() {
346
+ return formHeaders({
347
+ "x-grok-client-version": GROK_BUILD_VERSION,
348
+ "x-grok-client-surface": DEVICE_CLIENT_SURFACE
349
+ });
350
+ }
351
+ async function startGrokDeviceCode(io = {}) {
352
+ const fetchImpl = io.fetch ?? globalThis.fetch;
353
+ let response;
354
+ try {
355
+ response = await fetchImpl(GROK_DEVICE_CODE_URL, {
356
+ method: "POST",
357
+ headers: deviceHeaders(),
358
+ body: new URLSearchParams([
359
+ ["client_id", GROK_OAUTH_CLIENT_ID],
360
+ ["scope", GROK_OAUTH_SCOPE],
361
+ ["referrer", GROK_OAUTH_REFERRER]
362
+ ]),
363
+ signal: AbortSignal.timeout(TOKEN_TIMEOUT_MS)
364
+ });
365
+ } catch (error) {
366
+ throw networkError("device_code_failed", "device code", error);
367
+ }
368
+ if (!response.ok) {
369
+ await response.body?.cancel().catch(() => void 0);
370
+ if (response.status === 404) throw new GrokOAuthError("device_flow_not_enabled", "device-code login is not available", { status: 404 });
371
+ throw new GrokOAuthError("device_code_failed", `device code request failed: HTTP ${response.status}`, {
372
+ status: response.status,
373
+ retryable: response.status >= 500 || response.status === 429
374
+ });
375
+ }
376
+ let body;
377
+ try {
378
+ body = await response.json();
379
+ } catch {
380
+ throw new GrokOAuthError("invalid_device_code_response", "device code response is not JSON");
381
+ }
382
+ const parsed = DeviceCodeResponse.safeParse(body);
383
+ if (!parsed.success) throw new GrokOAuthError("invalid_device_code_response", "device code response failed validation");
384
+ const data = parsed.data;
385
+ const deviceCode = {
386
+ deviceCode: data.device_code,
387
+ userCode: data.user_code,
388
+ verificationUri: data.verification_uri,
389
+ expiresIn: data.expires_in,
390
+ interval: data.interval ?? 5
391
+ };
392
+ if (data.verification_uri_complete) deviceCode.verificationUriComplete = data.verification_uri_complete;
393
+ return deviceCode;
394
+ }
395
+ /**
396
+ * One poll of the device token endpoint. The caller sleeps `interval` seconds between polls and
397
+ * enforces the device-code expiry; this function never loops.
398
+ */
399
+ async function pollGrokDeviceCode(input) {
400
+ const fetchImpl = input.fetch ?? globalThis.fetch;
401
+ const interval = Math.max(1, Math.ceil(input.interval));
402
+ let response;
403
+ try {
404
+ response = await fetchImpl(GROK_DEVICE_TOKEN_URL, {
405
+ method: "POST",
406
+ headers: deviceHeaders(),
407
+ body: new URLSearchParams([
408
+ ["grant_type", DEVICE_GRANT_TYPE],
409
+ ["device_code", input.deviceCode],
410
+ ["client_id", GROK_OAUTH_CLIENT_ID]
411
+ ]),
412
+ signal: AbortSignal.timeout(TOKEN_TIMEOUT_MS)
413
+ });
414
+ } catch (error) {
415
+ throw networkError("device_token_failed", "device token", error);
416
+ }
417
+ if (response.ok) return {
418
+ status: "complete",
419
+ credentials: await finishGrokLogin({
420
+ ...input,
421
+ fetch: fetchImpl,
422
+ tokens: await parseTokenResponse(response)
423
+ })
424
+ };
425
+ const oauthError = await readGrokOAuthErrorCode(response);
426
+ switch (oauthError) {
427
+ case "authorization_pending": return {
428
+ status: "pending",
429
+ interval
430
+ };
431
+ case "slow_down": return {
432
+ status: "pending",
433
+ interval: interval + 5
434
+ };
435
+ case "access_denied": throw new GrokOAuthError("access_denied", "authorization denied by the user", {
436
+ status: response.status,
437
+ oauthError
438
+ });
439
+ case "expired_token": throw new GrokOAuthError("expired_token", "device code expired", {
440
+ status: response.status,
441
+ oauthError
442
+ });
443
+ default: throw new GrokOAuthError("device_token_failed", `device token request failed: HTTP ${response.status} ${oauthError ?? "unknown"}`, deviceTokenErrorOptions(response.status, oauthError));
444
+ }
445
+ }
446
+ function deviceTokenErrorOptions(status, oauthError) {
447
+ const errorOptions = { status };
448
+ if (oauthError !== void 0) errorOptions.oauthError = oauthError;
449
+ errorOptions.retryable = oauthError === void 0 && status >= 500;
450
+ return errorOptions;
451
+ }
452
+ //#endregion
453
+ export { GROK_DEVICE_DEFAULT_INTERVAL_S, GROK_DEVICE_SLOW_DOWN_INCREMENT_S, GROK_DISCOVERY_TTL_MS, GROK_FALLBACK_AUTHORIZATION_ENDPOINT, GROK_FALLBACK_TOKEN_ENDPOINT, GROK_OAUTH_SCOPE, GrokOAuthError, GrokTokenResponse, buildGrokAuthorizeUrl, completeGrokOAuth, finishGrokLogin, generateGrokPkce, getGrokOAuthEndpoints, grokLoopbackRedirectUri, parseGrokCallbackInput, pollGrokDeviceCode, readGrokOAuthErrorCode, resetGrokDiscoveryCache, startGrokDeviceCode, startGrokOAuth };
454
+
455
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3Jvay1vYXV0aC5qcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvdXRpbHMvcHJvdmlkZXJzL2dyb2svZ3Jvay1vYXV0aC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBHcm9rICh4QUkpIGxvZ2luOiBPSURDIGRpc2NvdmVyeSwgUEtDRSBhdXRob3JpemUgVVJMLCBsb29wYmFjay9wYXN0ZSBjb2RlIGV4Y2hhbmdlLCBSRkMgODYyOFxuLy8gZGV2aWNlIGNvZGUsIGFuZCB0aGUgcG9zdC1sb2dpbiBpZGVudGl0eSBsb29rdXAuIE1lY2hhbmlzbSBmb2xsb3dzIGdyb2stYnVpbGQgMS4wLjQ1XG4vLyBjcmF0ZXMvY29kZWdlbi94YWktZ3Jvay1sb2dpbi9zcmMgKG9pZGMvcHJvdG9jb2wucnMsIG9pZGMvbG9naW4ucnMsIGRldmljZV9jb2RlLnJzKS5cbi8vIEVycm9yIG1lc3NhZ2VzIG5ldmVyIGNhcnJ5IHJlc3BvbnNlIGJvZGllczogdG9rZW4gZW5kcG9pbnRzIGNhbiBlY2hvIGNyZWRlbnRpYWxzLlxuaW1wb3J0IHsgY3JlYXRlSGFzaCwgcmFuZG9tQnl0ZXMsIHJhbmRvbUludCwgcmFuZG9tVVVJRCwgdGltaW5nU2FmZUVxdWFsIH0gZnJvbSBcIm5vZGU6Y3J5cHRvXCI7XG5cbmltcG9ydCB7IHogfSBmcm9tIFwiem9kXCI7XG5cbmltcG9ydCB7XG4gIEdST0tfQVVUSF9JU1NVRVIsXG4gIEdST0tfQlVJTERfVkVSU0lPTixcbiAgR1JPS19DSEFUX1BST1hZX1VSTCxcbiAgR1JPS19ERVZJQ0VfQ09ERV9VUkwsXG4gIEdST0tfREVWSUNFX1RPS0VOX1VSTCxcbiAgR1JPS19PQVVUSF9DTElFTlRfSUQsXG4gIEdST0tfT0FVVEhfUkVGRVJSRVIsXG4gIEdST0tfT0FVVEhfU0NPUEVTLFxufSBmcm9tIFwiLi9ncm9rLWNvbnN0YW50c1wiO1xuaW1wb3J0IHsgYnVpbGRHcm9rUHJveHlHZXRIZWFkZXJzLCBncm9rU2hlbGxVc2VyQWdlbnQgfSBmcm9tIFwiLi9ncm9rLWhlYWRlcnNcIjtcbmltcG9ydCB7XG4gIEdyb2tDcmVkZW50aWFscyxcbiAgR3Jva1VzZXJTdWJzY3JpcHRpb24sXG4gIGRlY29kZUdyb2tKd3QsXG4gIGlzR3Jva0FjY2Vzc1Rva2VuLFxufSBmcm9tIFwiLi9ncm9rLXR5cGVzXCI7XG5cbmV4cG9ydCB0eXBlIEdyb2tGZXRjaCA9IHR5cGVvZiBnbG9iYWxUaGlzLmZldGNoO1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIEVycm9yc1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbmV4cG9ydCB0eXBlIEdyb2tPQXV0aEVycm9yQ29kZSA9XG4gIHwgXCJpbnZhbGlkX2NhbGxiYWNrX2lucHV0XCJcbiAgfCBcImF1dGhvcml6YXRpb25fZmFpbGVkXCJcbiAgfCBcInN0YXRlX21pc21hdGNoXCJcbiAgfCBcInRva2VuX2V4Y2hhbmdlX2ZhaWxlZFwiXG4gIHwgXCJpbnZhbGlkX3Rva2VuX3Jlc3BvbnNlXCJcbiAgfCBcImludmFsaWRfYWNjZXNzX3Rva2VuXCJcbiAgfCBcIm1pc3NpbmdfcmVmcmVzaF90b2tlblwiXG4gIHwgXCJtaXNzaW5nX2V4cGlyeVwiXG4gIHwgXCJ1c2VyX2lkX3VucmVzb2x2ZWRcIlxuICB8IFwidXNlcl9sb29rdXBfZmFpbGVkXCJcbiAgfCBcImludmFsaWRfY3JlZGVudGlhbHNcIlxuICB8IFwiZGV2aWNlX2Zsb3dfbm90X2VuYWJsZWRcIlxuICB8IFwiZGV2aWNlX2NvZGVfZmFpbGVkXCJcbiAgfCBcImludmFsaWRfZGV2aWNlX2NvZGVfcmVzcG9uc2VcIlxuICB8IFwiZGV2aWNlX3Rva2VuX2ZhaWxlZFwiXG4gIHwgXCJhY2Nlc3NfZGVuaWVkXCJcbiAgfCBcImV4cGlyZWRfdG9rZW5cIjtcblxuLyoqIExvZ2luIGZhaWx1cmUuIGByZXRyeWFibGVgIG1hcmtzIG5ldHdvcmsvNXh4IGZhaWx1cmVzIHdoZXJlIHRoZSBzYW1lIHN0ZXAgbWF5IGJlIHJldHJpZWQuICovXG5leHBvcnQgY2xhc3MgR3Jva09BdXRoRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIG92ZXJyaWRlIHJlYWRvbmx5IG5hbWUgPSBcIkdyb2tPQXV0aEVycm9yXCI7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHJlYWRvbmx5IGNvZGU6IEdyb2tPQXV0aEVycm9yQ29kZSxcbiAgICBtZXNzYWdlOiBzdHJpbmcsXG4gICAgcmVhZG9ubHkgb3B0aW9uczogeyBzdGF0dXM/OiBudW1iZXI7IG9hdXRoRXJyb3I/OiBzdHJpbmc7IHJldHJ5YWJsZT86IGJvb2xlYW4gfSA9IHt9LFxuICApIHtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgfVxuXG4gIGdldCBzdGF0dXMoKTogbnVtYmVyIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5vcHRpb25zLnN0YXR1cztcbiAgfVxuXG4gIGdldCByZXRyeWFibGUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucy5yZXRyeWFibGUgPz8gZmFsc2U7XG4gIH1cblxuICAvKiogT0F1dGggYGVycm9yYCBjb2RlLCBvbmx5IHdoZW4gaXQgaXMgYSBwbGFpbiBsb3dlcmNhc2UgaWRlbnRpZmllci4gKi9cbiAgZ2V0IG9hdXRoRXJyb3IoKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5vcHRpb25zLm9hdXRoRXJyb3I7XG4gIH1cbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBEaXNjb3Zlcnlcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5leHBvcnQgaW50ZXJmYWNlIEdyb2tPQXV0aEVuZHBvaW50cyB7XG4gIGF1dGhvcml6YXRpb25FbmRwb2ludDogc3RyaW5nO1xuICB0b2tlbkVuZHBvaW50OiBzdHJpbmc7XG4gIHNvdXJjZTogXCJkaXNjb3ZlcnlcIiB8IFwiZmFsbGJhY2tcIjtcbn1cblxuLy8gZ3Jvay1idWlsZCBjYWNoZXMgMSBoIChvaWRjL3Byb3RvY29sLnJzOjI2OSkgYW5kIGhhcyBubyBmYWxsYmFjayAoZGlzY292ZXJ5IGVycm9ycyBhYm9ydCB0aGVcbi8vIGxvZ2luLCBwcm90b2NvbC5yczoyNzktMzAyKS4gcWdyaWQgY2FjaGVzIDI0IGggYW5kIGZhbGxzIGJhY2sgdG8gZml4ZWQgcGF0aHM6IHRoZSB0b2tlbiBwYXRoXG4vLyBpcyB0aGUgb25lIGdyb2stYnVpbGQgaXRzZWxmIGhhcmQtY29kZXMgZm9yIHRoZSBkZXZpY2UgZ3JhbnQgKGRldmljZV9jb2RlLnJzOjE4Nyk7IHRoZVxuLy8gYXV0aG9yaXplIHBhdGggaXMgbm90IHByZXNlbnQgaW4gdGhlIHNvdXJjZSBhbmQgaXMgdW52ZXJpZmllZC5cbmV4cG9ydCBjb25zdCBHUk9LX0RJU0NPVkVSWV9UVExfTVMgPSAyNCAqIDYwICogNjAgKiAxMDAwO1xuZXhwb3J0IGNvbnN0IEdST0tfRkFMTEJBQ0tfQVVUSE9SSVpBVElPTl9FTkRQT0lOVCA9IGAke0dST0tfQVVUSF9JU1NVRVJ9L29hdXRoMi9hdXRob3JpemVgO1xuZXhwb3J0IGNvbnN0IEdST0tfRkFMTEJBQ0tfVE9LRU5fRU5EUE9JTlQgPSBgJHtHUk9LX0FVVEhfSVNTVUVSfS9vYXV0aDIvdG9rZW5gO1xuXG5jb25zdCBESVNDT1ZFUllfVElNRU9VVF9NUyA9IDEwXzAwMDtcbmNvbnN0IFRPS0VOX1RJTUVPVVRfTVMgPSAxNV8wMDA7XG5jb25zdCBVU0VSX0xPT0tVUF9USU1FT1VUX01TID0gMTVfMDAwO1xuXG5jb25zdCBEaXNjb3ZlcnlEb2N1bWVudCA9IHoubG9vc2VPYmplY3Qoe1xuICBhdXRob3JpemF0aW9uX2VuZHBvaW50OiB6LnN0cmluZygpLFxuICB0b2tlbl9lbmRwb2ludDogei5zdHJpbmcoKSxcbn0pO1xuXG5sZXQgZGlzY292ZXJ5Q2FjaGU6IHsgZW5kcG9pbnRzOiBHcm9rT0F1dGhFbmRwb2ludHM7IGZldGNoZWRBdDogbnVtYmVyIH0gfCB1bmRlZmluZWQ7XG5cbi8qKiBDbGVhcnMgdGhlIG1vZHVsZS1sZXZlbCBkaXNjb3ZlcnkgY2FjaGUgKHRlc3RzIGFuZCBvcGVyYXRvciByZXNldHMpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc2V0R3Jva0Rpc2NvdmVyeUNhY2hlKCk6IHZvaWQge1xuICBkaXNjb3ZlcnlDYWNoZSA9IHVuZGVmaW5lZDtcbn1cblxuLy8gQSBkaXNjb3ZlcnkgZG9jdW1lbnQgdGhhdCByZWRpcmVjdGVkIHRoZSB0b2tlbiBlbmRwb2ludCBvZmYgeEFJIHdvdWxkIHNoaXAgcmVmcmVzaCB0b2tlbnMgdG8gYVxuLy8gdGhpcmQgcGFydHksIHNvIG9ubHkgaHR0cHMgZW5kcG9pbnRzIG9uIHguYWkgaG9zdHMgYXJlIGFjY2VwdGVkOyBhbnl0aGluZyBlbHNlIGZhbGxzIGJhY2suXG5mdW5jdGlvbiBpc1RydXN0ZWRFbmRwb2ludCh2YWx1ZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGxldCB1cmw6IFVSTDtcblxuICB0cnkge1xuICAgIHVybCA9IG5ldyBVUkwodmFsdWUpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gKFxuICAgIHVybC5wcm90b2NvbCA9PT0gXCJodHRwczpcIiAmJlxuICAgICF1cmwudXNlcm5hbWUgJiZcbiAgICAhdXJsLnBhc3N3b3JkICYmXG4gICAgKHVybC5ob3N0bmFtZSA9PT0gXCJ4LmFpXCIgfHwgdXJsLmhvc3RuYW1lLmVuZHNXaXRoKFwiLnguYWlcIikpXG4gICk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgR3Jva09BdXRoSW8ge1xuICBmZXRjaD86IEdyb2tGZXRjaDtcbiAgbm93PzogKCkgPT4gbnVtYmVyO1xufVxuXG4vKipcbiAqIGBHRVQge2lzc3Vlcn0vLndlbGwta25vd24vb3BlbmlkLWNvbmZpZ3VyYXRpb25gLCBjYWNoZWQgMjQgaC4gQW55IGZhaWx1cmUgdXNlcyB0aGUgZmFsbGJhY2tcbiAqIGVuZHBvaW50cyB3aXRob3V0IGNhY2hpbmcgdGhlbSwgc28gdGhlIG5leHQgY2FsbCByZXRyaWVzIGRpc2NvdmVyeS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldEdyb2tPQXV0aEVuZHBvaW50cyhpbzogR3Jva09BdXRoSW8gPSB7fSk6IFByb21pc2U8R3Jva09BdXRoRW5kcG9pbnRzPiB7XG4gIGNvbnN0IGZldGNoSW1wbCA9IGlvLmZldGNoID8/IGdsb2JhbFRoaXMuZmV0Y2g7XG4gIGNvbnN0IG5vdyA9IGlvLm5vdyA/PyBEYXRlLm5vdztcbiAgY29uc3QgY2FjaGVkID0gZGlzY292ZXJ5Q2FjaGU7XG5cbiAgaWYgKGNhY2hlZCAmJiBub3coKSAtIGNhY2hlZC5mZXRjaGVkQXQgPCBHUk9LX0RJU0NPVkVSWV9UVExfTVMpIHJldHVybiBjYWNoZWQuZW5kcG9pbnRzO1xuXG4gIHRyeSB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaEltcGwoYCR7R1JPS19BVVRIX0lTU1VFUn0vLndlbGwta25vd24vb3BlbmlkLWNvbmZpZ3VyYXRpb25gLCB7XG4gICAgICBtZXRob2Q6IFwiR0VUXCIsXG4gICAgICBoZWFkZXJzOiB7IGFjY2VwdDogXCJhcHBsaWNhdGlvbi9qc29uXCIsIFwidXNlci1hZ2VudFwiOiBncm9rU2hlbGxVc2VyQWdlbnQoKSB9LFxuICAgICAgc2lnbmFsOiBBYm9ydFNpZ25hbC50aW1lb3V0KERJU0NPVkVSWV9USU1FT1VUX01TKSxcbiAgICB9KTtcblxuICAgIGlmIChyZXNwb25zZS5vaykge1xuICAgICAgY29uc3QgZG9jdW1lbnQgPSBEaXNjb3ZlcnlEb2N1bWVudC5zYWZlUGFyc2UoYXdhaXQgcmVzcG9uc2UuanNvbigpKTtcblxuICAgICAgaWYgKFxuICAgICAgICBkb2N1bWVudC5zdWNjZXNzICYmXG4gICAgICAgIGlzVHJ1c3RlZEVuZHBvaW50KGRvY3VtZW50LmRhdGEuYXV0aG9yaXphdGlvbl9lbmRwb2ludCkgJiZcbiAgICAgICAgaXNUcnVzdGVkRW5kcG9pbnQoZG9jdW1lbnQuZGF0YS50b2tlbl9lbmRwb2ludClcbiAgICAgICkge1xuICAgICAgICBjb25zdCBlbmRwb2ludHM6IEdyb2tPQXV0aEVuZHBvaW50cyA9IHtcbiAgICAgICAgICBhdXRob3JpemF0aW9uRW5kcG9pbnQ6IGRvY3VtZW50LmRhdGEuYXV0aG9yaXphdGlvbl9lbmRwb2ludCxcbiAgICAgICAgICB0b2tlbkVuZHBvaW50OiBkb2N1bWVudC5kYXRhLnRva2VuX2VuZHBvaW50LFxuICAgICAgICAgIHNvdXJjZTogXCJkaXNjb3ZlcnlcIixcbiAgICAgICAgfTtcblxuICAgICAgICBkaXNjb3ZlcnlDYWNoZSA9IHsgZW5kcG9pbnRzLCBmZXRjaGVkQXQ6IG5vdygpIH07XG5cbiAgICAgICAgcmV0dXJuIGVuZHBvaW50cztcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgYXdhaXQgcmVzcG9uc2UuYm9keT8uY2FuY2VsKCkuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB9XG4gIH0gY2F0Y2gge1xuICAgIC8vIE5ldHdvcmsgZmFpbHVyZSwgdGltZW91dCwgb3IgYSBub24tSlNPTiBib2R5OiBmYWxsIHRocm91Z2ggdG8gdGhlIGZpeGVkIGVuZHBvaW50cy5cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgYXV0aG9yaXphdGlvbkVuZHBvaW50OiBHUk9LX0ZBTExCQUNLX0FVVEhPUklaQVRJT05fRU5EUE9JTlQsXG4gICAgdG9rZW5FbmRwb2ludDogR1JPS19GQUxMQkFDS19UT0tFTl9FTkRQT0lOVCxcbiAgICBzb3VyY2U6IFwiZmFsbGJhY2tcIixcbiAgfTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBQS0NFIGFuZCBhdXRob3JpemUgVVJMXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuZXhwb3J0IGludGVyZmFjZSBHcm9rUGtjZSB7XG4gIGNvZGVWZXJpZmllcjogc3RyaW5nO1xuICBjb2RlQ2hhbGxlbmdlOiBzdHJpbmc7XG59XG5cbi8qKiBTMjU2IG92ZXIgYSBiYXNlNjR1cmwgdmVyaWZpZXIgb2YgMzIgcmFuZG9tIGJ5dGVzIChvaWRjL3Byb3RvY29sLnJzOjMxNC0zMjApLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdlbmVyYXRlR3Jva1BrY2UoKTogR3Jva1BrY2Uge1xuICBjb25zdCBjb2RlVmVyaWZpZXIgPSByYW5kb21CeXRlcygzMikudG9TdHJpbmcoXCJiYXNlNjR1cmxcIik7XG5cbiAgcmV0dXJuIHtcbiAgICBjb2RlVmVyaWZpZXIsXG4gICAgY29kZUNoYWxsZW5nZTogY3JlYXRlSGFzaChcInNoYTI1NlwiKS51cGRhdGUoY29kZVZlcmlmaWVyKS5kaWdlc3QoXCJiYXNlNjR1cmxcIiksXG4gIH07XG59XG5cbi8qKiBSRkMgMzk4NiB1bnJlc2VydmVkLW9ubHkgZW5jb2RpbmcsIG1hdGNoaW5nIFJ1c3QgYHVybGVuY29kaW5nOjplbmNvZGVgIChzcGFjZSDihpIgJTIwKS4gKi9cbmZ1bmN0aW9uIGVuY29kZVF1ZXJ5VmFsdWUodmFsdWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBlbmNvZGVVUklDb21wb25lbnQodmFsdWUpLnJlcGxhY2UoXG4gICAgL1shJygpKl0vZyxcbiAgICAoY2hhcikgPT4gYCUke2NoYXIuY2hhckNvZGVBdCgwKS50b1N0cmluZygxNikudG9VcHBlckNhc2UoKX1gLFxuICApO1xufVxuXG5leHBvcnQgY29uc3QgR1JPS19PQVVUSF9TQ09QRSA9IEdST0tfT0FVVEhfU0NPUEVTLmpvaW4oXCIgXCIpO1xuXG5leHBvcnQgaW50ZXJmYWNlIEdyb2tBdXRob3JpemVVcmxJbnB1dCB7XG4gIGF1dGhvcml6YXRpb25FbmRwb2ludDogc3RyaW5nO1xuICByZWRpcmVjdFVyaTogc3RyaW5nO1xuICBjb2RlQ2hhbGxlbmdlOiBzdHJpbmc7XG4gIHN0YXRlOiBzdHJpbmc7XG4gIG5vbmNlOiBzdHJpbmc7XG59XG5cbi8qKiBBdXRob3JpemUgVVJMIHdpdGggZ3Jvay1idWlsZCdzIHF1ZXJ5IG9yZGVyIChvaWRjL3Byb3RvY29sLnJzOjMyMS0zNjYpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkR3Jva0F1dGhvcml6ZVVybChpbnB1dDogR3Jva0F1dGhvcml6ZVVybElucHV0KTogc3RyaW5nIHtcbiAgY29uc3QgcXVlcnk6IFtzdHJpbmcsIHN0cmluZ11bXSA9IFtcbiAgICBbXCJyZXNwb25zZV90eXBlXCIsIFwiY29kZVwiXSxcbiAgICBbXCJjbGllbnRfaWRcIiwgR1JPS19PQVVUSF9DTElFTlRfSURdLFxuICAgIFtcInJlZGlyZWN0X3VyaVwiLCBpbnB1dC5yZWRpcmVjdFVyaV0sXG4gICAgW1wic2NvcGVcIiwgR1JPS19PQVVUSF9TQ09QRV0sXG4gICAgW1wiY29kZV9jaGFsbGVuZ2VcIiwgaW5wdXQuY29kZUNoYWxsZW5nZV0sXG4gICAgW1wiY29kZV9jaGFsbGVuZ2VfbWV0aG9kXCIsIFwiUzI1NlwiXSxcbiAgICBbXCJzdGF0ZVwiLCBpbnB1dC5zdGF0ZV0sXG4gICAgW1wibm9uY2VcIiwgaW5wdXQubm9uY2VdLFxuICAgIFtcInJlZmVycmVyXCIsIEdST0tfT0FVVEhfUkVGRVJSRVJdLFxuICBdO1xuXG4gIGNvbnN0IHNlYXJjaCA9IHF1ZXJ5Lm1hcCgoW2tleSwgdmFsdWVdKSA9PiBgJHtrZXl9PSR7ZW5jb2RlUXVlcnlWYWx1ZSh2YWx1ZSl9YCkuam9pbihcIiZcIik7XG5cbiAgcmV0dXJuIGAke2lucHV0LmF1dGhvcml6YXRpb25FbmRwb2ludH0/JHtzZWFyY2h9YDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdyb2tMb29wYmFja1JlZGlyZWN0VXJpKHBvcnQ6IG51bWJlcik6IHN0cmluZyB7XG4gIGlmICghTnVtYmVyLmlzSW50ZWdlcihwb3J0KSB8fCBwb3J0IDwgMSB8fCBwb3J0ID4gNjVfNTM1KVxuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKFwicmVkaXJlY3QgcG9ydCBtdXN0IGJlIGFuIGludGVnZXIgaW4gMS4uNjU1MzVcIik7XG5cbiAgcmV0dXJuIGBodHRwOi8vMTI3LjAuMC4xOiR7cG9ydH0vY2FsbGJhY2tgO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFN0YXJ0R3Jva09BdXRoSW5wdXQgZXh0ZW5kcyBHcm9rT0F1dGhJbyB7XG4gIHN0YXRlOiBzdHJpbmc7XG4gIC8qKiBMb29wYmFjayBwb3J0OyBkZWZhdWx0cyB0byBhIHJhbmRvbSBwb3J0IGluIHRoZSBlcGhlbWVyYWwgcmFuZ2UuICovXG4gIHJlZGlyZWN0UG9ydD86IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTdGFydEdyb2tPQXV0aFJlc3VsdCB7XG4gIGF1dGhvcml6ZVVybDogc3RyaW5nO1xuICB2ZXJpZmllcjogc3RyaW5nO1xuICByZWRpcmVjdFVyaTogc3RyaW5nO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc3RhcnRHcm9rT0F1dGgoaW5wdXQ6IFN0YXJ0R3Jva09BdXRoSW5wdXQpOiBQcm9taXNlPFN0YXJ0R3Jva09BdXRoUmVzdWx0PiB7XG4gIGlmICghaW5wdXQuc3RhdGUpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJzdGF0ZSBtdXN0IGJlIG5vbi1lbXB0eVwiKTtcbiAgY29uc3QgZW5kcG9pbnRzID0gYXdhaXQgZ2V0R3Jva09BdXRoRW5kcG9pbnRzKGlucHV0KTtcbiAgY29uc3QgcGtjZSA9IGdlbmVyYXRlR3Jva1BrY2UoKTtcbiAgY29uc3QgcmVkaXJlY3RVcmkgPSBncm9rTG9vcGJhY2tSZWRpcmVjdFVyaShpbnB1dC5yZWRpcmVjdFBvcnQgPz8gcmFuZG9tSW50KDQ5XzE1MiwgNjVfNTM2KSk7XG5cbiAgcmV0dXJuIHtcbiAgICBhdXRob3JpemVVcmw6IGJ1aWxkR3Jva0F1dGhvcml6ZVVybCh7XG4gICAgICBhdXRob3JpemF0aW9uRW5kcG9pbnQ6IGVuZHBvaW50cy5hdXRob3JpemF0aW9uRW5kcG9pbnQsXG4gICAgICByZWRpcmVjdFVyaSxcbiAgICAgIGNvZGVDaGFsbGVuZ2U6IHBrY2UuY29kZUNoYWxsZW5nZSxcbiAgICAgIHN0YXRlOiBpbnB1dC5zdGF0ZSxcbiAgICAgIG5vbmNlOiByYW5kb21VVUlEKCksXG4gICAgfSksXG4gICAgdmVyaWZpZXI6IHBrY2UuY29kZVZlcmlmaWVyLFxuICAgIHJlZGlyZWN0VXJpLFxuICB9O1xufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIENhbGxiYWNrIC8gcGFzdGUgcGFyc2luZ1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbmV4cG9ydCBpbnRlcmZhY2UgR3Jva0NhbGxiYWNrSW5wdXQge1xuICBjb2RlOiBzdHJpbmc7XG4gIC8qKiBFbXB0eSBmb3IgYSBiYXJlIHBhc3RlZCBjb2RlLCB3aGljaCBjYXJyaWVzIG5vIHN0YXRlIChvaWRjL2xvZ2luLnJzOjMzLTYwKS4gKi9cbiAgc3RhdGU6IHN0cmluZztcbn1cblxuY29uc3QgT0FVVEhfRVJST1JfQ09ERSA9IC9eW2Etel9dezEsODB9JC87XG5cbmZ1bmN0aW9uIHNhZmVPQXV0aEVycm9yQ29kZSh2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIE9BVVRIX0VSUk9SX0NPREUudGVzdCh2YWx1ZSkgPyB2YWx1ZSA6IHVuZGVmaW5lZDtcbn1cblxuLyoqIEFjY2VwdHMgdGhlIGZ1bGwgY2FsbGJhY2sgVVJMIG9yIGEgYmFyZSBhdXRob3JpemF0aW9uIGNvZGUgKG9pZGMvbG9naW4ucnM6MzAtNjApLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlR3Jva0NhbGxiYWNrSW5wdXQoaW5wdXQ6IHN0cmluZyk6IEdyb2tDYWxsYmFja0lucHV0IHtcbiAgY29uc3QgdHJpbW1lZCA9IGlucHV0LnRyaW0oKTtcblxuICBpZiAoIXRyaW1tZWQpIHRocm93IG5ldyBHcm9rT0F1dGhFcnJvcihcImludmFsaWRfY2FsbGJhY2tfaW5wdXRcIiwgXCJlbXB0eSBjYWxsYmFjayBpbnB1dFwiKTtcblxuICBsZXQgdXJsOiBVUkwgfCB1bmRlZmluZWQ7XG5cbiAgdHJ5IHtcbiAgICB1cmwgPSBuZXcgVVJMKHRyaW1tZWQpO1xuICB9IGNhdGNoIHtcbiAgICB1cmwgPSB1bmRlZmluZWQ7XG4gIH1cblxuICBpZiAodXJsKSB7XG4gICAgY29uc3QgY29kZSA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KFwiY29kZVwiKTtcblxuICAgIGlmIChjb2RlKSByZXR1cm4geyBjb2RlLCBzdGF0ZTogdXJsLnNlYXJjaFBhcmFtcy5nZXQoXCJzdGF0ZVwiKSA/PyBcIlwiIH07XG4gICAgY29uc3QgZXJyb3IgPSB1cmwuc2VhcmNoUGFyYW1zLmdldChcImVycm9yXCIpO1xuXG4gICAgaWYgKGVycm9yKSB7XG4gICAgICBjb25zdCBvYXV0aEVycm9yID0gc2FmZU9BdXRoRXJyb3JDb2RlKGVycm9yKTtcbiAgICAgIHRocm93IG5ldyBHcm9rT0F1dGhFcnJvcihcbiAgICAgICAgXCJhdXRob3JpemF0aW9uX2ZhaWxlZFwiLFxuICAgICAgICBgYXV0aG9yaXphdGlvbiBmYWlsZWQ6ICR7b2F1dGhFcnJvciA/PyBcInVua25vd25fZXJyb3JcIn1gLFxuICAgICAgICBvYXV0aEVycm9yID09PSB1bmRlZmluZWQgPyB7fSA6IHsgb2F1dGhFcnJvciB9LFxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgR3Jva09BdXRoRXJyb3IoXCJpbnZhbGlkX2NhbGxiYWNrX2lucHV0XCIsIFwiY2FsbGJhY2sgVVJMIGhhcyBubyBjb2RlIHBhcmFtZXRlclwiKTtcbiAgfVxuXG4gIGlmICgvXFxzLy50ZXN0KHRyaW1tZWQpKVxuICAgIHRocm93IG5ldyBHcm9rT0F1dGhFcnJvcihcImludmFsaWRfY2FsbGJhY2tfaW5wdXRcIiwgXCJhdXRob3JpemF0aW9uIGNvZGUgY29udGFpbnMgd2hpdGVzcGFjZVwiKTtcblxuICByZXR1cm4geyBjb2RlOiB0cmltbWVkLCBzdGF0ZTogXCJcIiB9O1xufVxuXG5mdW5jdGlvbiBzdGF0ZXNFcXVhbChleHBlY3RlZDogc3RyaW5nLCByZWNlaXZlZDogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGNvbnN0IGEgPSBCdWZmZXIuZnJvbShleHBlY3RlZCk7XG4gIGNvbnN0IGIgPSBCdWZmZXIuZnJvbShyZWNlaXZlZCk7XG5cbiAgcmV0dXJuIGEubGVuZ3RoID09PSBiLmxlbmd0aCAmJiB0aW1pbmdTYWZlRXF1YWwoYSwgYik7XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gVG9rZW4gZXhjaGFuZ2UgYW5kIGZpbmlzaGluZ1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbmV4cG9ydCBjb25zdCBHcm9rVG9rZW5SZXNwb25zZSA9IHoubG9vc2VPYmplY3Qoe1xuICBhY2Nlc3NfdG9rZW46IHouc3RyaW5nKCkubWluKDEpLFxuICByZWZyZXNoX3Rva2VuOiB6LnN0cmluZygpLm1pbigxKS5udWxsaXNoKCksXG4gIGlkX3Rva2VuOiB6LnN0cmluZygpLm51bGxpc2goKSxcbiAgZXhwaXJlc19pbjogei5udW1iZXIoKS5ub25uZWdhdGl2ZSgpLm51bGxpc2goKSxcbiAgc2NvcGU6IHouc3RyaW5nKCkubnVsbGlzaCgpLFxuICB0b2tlbl90eXBlOiB6LnN0cmluZygpLm51bGxpc2goKSxcbn0pO1xuXG5leHBvcnQgdHlwZSBHcm9rVG9rZW5SZXNwb25zZSA9IHouaW5mZXI8dHlwZW9mIEdyb2tUb2tlblJlc3BvbnNlPjtcblxuY29uc3QgT0F1dGhFcnJvckJvZHkgPSB6Lmxvb3NlT2JqZWN0KHsgZXJyb3I6IHouc3RyaW5nKCkgfSk7XG5cbi8qKiBSZWFkcyB0aGUgT0F1dGggYGVycm9yYCBjb2RlIGZyb20gYSBmYWlsZWQgcmVzcG9uc2Ugd2l0aG91dCByZXRhaW5pbmcgdGhlIGJvZHkuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZEdyb2tPQXV0aEVycm9yQ29kZShyZXNwb25zZTogUmVzcG9uc2UpOiBQcm9taXNlPHN0cmluZyB8IHVuZGVmaW5lZD4ge1xuICBjb25zdCB0ZXh0ID0gYXdhaXQgcmVzcG9uc2UudGV4dCgpLmNhdGNoKCgpID0+IFwiXCIpO1xuXG4gIHRyeSB7XG4gICAgY29uc3QgcGFyc2VkID0gT0F1dGhFcnJvckJvZHkuc2FmZVBhcnNlKEpTT04ucGFyc2UodGV4dCkpO1xuXG4gICAgcmV0dXJuIHBhcnNlZC5zdWNjZXNzID8gc2FmZU9BdXRoRXJyb3JDb2RlKHBhcnNlZC5kYXRhLmVycm9yKSA6IHVuZGVmaW5lZDtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuXG5mdW5jdGlvbiBmb3JtSGVhZGVycyhleHRyYTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9KSB7XG4gIHJldHVybiB7XG4gICAgXCJ1c2VyLWFnZW50XCI6IGdyb2tTaGVsbFVzZXJBZ2VudCgpLFxuICAgIC4uLmV4dHJhLFxuICAgIFwiY29udGVudC10eXBlXCI6IFwiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkXCIsXG4gICAgYWNjZXB0OiBcImFwcGxpY2F0aW9uL2pzb25cIixcbiAgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gcGFyc2VUb2tlblJlc3BvbnNlKHJlc3BvbnNlOiBSZXNwb25zZSk6IFByb21pc2U8R3Jva1Rva2VuUmVzcG9uc2U+IHtcbiAgbGV0IGJvZHk6IHVua25vd247XG5cbiAgdHJ5IHtcbiAgICBib2R5ID0gYXdhaXQgcmVzcG9uc2UuanNvbigpO1xuICB9IGNhdGNoIHtcbiAgICB0aHJvdyBuZXcgR3Jva09BdXRoRXJyb3IoXCJpbnZhbGlkX3Rva2VuX3Jlc3BvbnNlXCIsIFwidG9rZW4gcmVzcG9uc2UgaXMgbm90IEpTT05cIik7XG4gIH1cblxuICBjb25zdCBwYXJzZWQgPSBHcm9rVG9rZW5SZXNwb25zZS5zYWZlUGFyc2UoYm9keSk7XG5cbiAgaWYgKCFwYXJzZWQuc3VjY2VzcylcbiAgICB0aHJvdyBuZXcgR3Jva09BdXRoRXJyb3IoXCJpbnZhbGlkX3Rva2VuX3Jlc3BvbnNlXCIsIFwidG9rZW4gcmVzcG9uc2UgZmFpbGVkIHZhbGlkYXRpb25cIik7XG5cbiAgcmV0dXJuIHBhcnNlZC5kYXRhO1xufVxuXG5mdW5jdGlvbiBuZXR3b3JrRXJyb3IoY29kZTogR3Jva09BdXRoRXJyb3JDb2RlLCB3aGF0OiBzdHJpbmcsIGNhdXNlOiB1bmtub3duKTogR3Jva09BdXRoRXJyb3Ige1xuICBjb25zdCByZWFzb24gPSBjYXVzZSBpbnN0YW5jZW9mIEVycm9yID8gY2F1c2UubmFtZSA6IFwidW5rbm93blwiO1xuXG4gIHJldHVybiBuZXcgR3Jva09BdXRoRXJyb3IoY29kZSwgYCR7d2hhdH0gcmVxdWVzdCBmYWlsZWQgKCR7cmVhc29ufSlgLCB7IHJldHJ5YWJsZTogdHJ1ZSB9KTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBGaW5pc2hHcm9rTG9naW5JbnB1dCBleHRlbmRzIEdyb2tPQXV0aElvIHtcbiAgdG9rZW5zOiBHcm9rVG9rZW5SZXNwb25zZTtcbiAgcmVxdWVzdGVkU2NvcGVzPzogcmVhZG9ubHkgc3RyaW5nW107XG59XG5cbi8qKlxuICogVmFsaWRhdGVzIHRoZSB0b2tlbiByZXNwb25zZSwgcmVzb2x2ZXMgdGhlIGFjY291bnQgaWQgKEpXVCBgc3ViYCwgY29uZmlybWVkIGJ5XG4gKiBgR0VUIC91c2VyP2luY2x1ZGU9c3Vic2NyaXB0aW9uYCksIGFuZCBidWlsZHMgc3RvcmVkIGNyZWRlbnRpYWxzLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZmluaXNoR3Jva0xvZ2luKGlucHV0OiBGaW5pc2hHcm9rTG9naW5JbnB1dCk6IFByb21pc2U8R3Jva0NyZWRlbnRpYWxzPiB7XG4gIGNvbnN0IGZldGNoSW1wbCA9IGlucHV0LmZldGNoID8/IGdsb2JhbFRoaXMuZmV0Y2g7XG4gIGNvbnN0IG5vdyA9IGlucHV0Lm5vdyA/PyBEYXRlLm5vdztcbiAgY29uc3QgeyB0b2tlbnMgfSA9IGlucHV0O1xuXG4gIGlmICghaXNHcm9rQWNjZXNzVG9rZW4odG9rZW5zLmFjY2Vzc190b2tlbikpXG4gICAgdGhyb3cgbmV3IEdyb2tPQXV0aEVycm9yKFxuICAgICAgXCJpbnZhbGlkX2FjY2Vzc190b2tlblwiLFxuICAgICAgYGFjY2VzcyB0b2tlbiBpcyBub3QgYW4gYXQrand0IGlzc3VlZCBieSAke0dST0tfQVVUSF9JU1NVRVJ9YCxcbiAgICApO1xuXG4gIGlmICghdG9rZW5zLnJlZnJlc2hfdG9rZW4pXG4gICAgdGhyb3cgbmV3IEdyb2tPQXV0aEVycm9yKFwibWlzc2luZ19yZWZyZXNoX3Rva2VuXCIsIFwidG9rZW4gcmVzcG9uc2UgaGFzIG5vIHJlZnJlc2ggdG9rZW5cIik7XG5cbiAgY29uc3QgZGVjb2RlZCA9IGRlY29kZUdyb2tKd3QodG9rZW5zLmFjY2Vzc190b2tlbik7XG4gIGNvbnN0IHN1YmplY3QgPSBkZWNvZGVkPy5wYXlsb2FkLnN1YjtcblxuICBpZiAoIXN1YmplY3QpXG4gICAgdGhyb3cgbmV3IEdyb2tPQXV0aEVycm9yKFwidXNlcl9pZF91bnJlc29sdmVkXCIsIFwiYWNjZXNzIHRva2VuIGhhcyBubyBzdWJqZWN0IChzdWIpIGNsYWltXCIpO1xuXG4gIGxldCByZXNwb25zZTogUmVzcG9uc2U7XG5cbiAgdHJ5IHtcbiAgICByZXNwb25zZSA9IGF3YWl0IGZldGNoSW1wbChgJHtHUk9LX0NIQVRfUFJPWFlfVVJMfS91c2VyP2luY2x1ZGU9c3Vic2NyaXB0aW9uYCwge1xuICAgICAgbWV0aG9kOiBcIkdFVFwiLFxuICAgICAgaGVhZGVyczogYnVpbGRHcm9rUHJveHlHZXRIZWFkZXJzKHsgYmVhcmVyOiB0b2tlbnMuYWNjZXNzX3Rva2VuLCB1c2VySWQ6IHN1YmplY3QgfSksXG4gICAgICBzaWduYWw6IEFib3J0U2lnbmFsLnRpbWVvdXQoVVNFUl9MT09LVVBfVElNRU9VVF9NUyksXG4gICAgfSk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgdGhyb3cgbmV0d29ya0Vycm9yKFwidXNlcl9sb29rdXBfZmFpbGVkXCIsIFwidXNlciBsb29rdXBcIiwgZXJyb3IpO1xuICB9XG5cbiAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgIGF3YWl0IHJlc3BvbnNlLmJvZHk/LmNhbmNlbCgpLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgdGhyb3cgbmV3IEdyb2tPQXV0aEVycm9yKFwidXNlcl9sb29rdXBfZmFpbGVkXCIsIGB1c2VyIGxvb2t1cCBmYWlsZWQ6IEhUVFAgJHtyZXNwb25zZS5zdGF0dXN9YCwge1xuICAgICAgc3RhdHVzOiByZXNwb25zZS5zdGF0dXMsXG4gICAgICByZXRyeWFibGU6IHJlc3BvbnNlLnN0YXR1cyA+PSA1MDAgfHwgcmVzcG9uc2Uuc3RhdHVzID09PSA0MjksXG4gICAgfSk7XG4gIH1cblxuICBsZXQgdXNlckJvZHk6IHVua25vd247XG5cbiAgdHJ5IHtcbiAgICB1c2VyQm9keSA9IGF3YWl0IHJlc3BvbnNlLmpzb24oKTtcbiAgfSBjYXRjaCB7XG4gICAgdGhyb3cgbmV3IEdyb2tPQXV0aEVycm9yKFwidXNlcl9pZF91bnJlc29sdmVkXCIsIFwidXNlciBsb29rdXAgcmV0dXJuZWQgbm9uLUpTT05cIik7XG4gIH1cblxuICBjb25zdCB1c2VyID0gR3Jva1VzZXJTdWJzY3JpcHRpb24uc2FmZVBhcnNlKHVzZXJCb2R5KTtcblxuICBpZiAoIXVzZXIuc3VjY2VzcylcbiAgICB0aHJvdyBuZXcgR3Jva09BdXRoRXJyb3IoXCJ1c2VyX2lkX3VucmVzb2x2ZWRcIiwgXCJ1c2VyIGxvb2t1cCBkaWQgbm90IHJldHVybiBhIHZhbGlkIHVzZXJJZFwiKTtcblxuICBjb25zdCBpc3N1ZWRBdCA9IG5vdygpO1xuICBjb25zdCBleHBpcmVzSW4gPSB0b2tlbnMuZXhwaXJlc19pbjtcbiAgY29uc3Qgand0RXhwaXJ5ID0gZGVjb2RlZD8ucGF5bG9hZC5leHA7XG5cbiAgY29uc3QgZXhwaXJlc0F0TXMgPVxuICAgIGV4cGlyZXNJbiAhPT0gdW5kZWZpbmVkICYmIGV4cGlyZXNJbiAhPT0gbnVsbFxuICAgICAgPyBpc3N1ZWRBdCArIGV4cGlyZXNJbiAqIDEwMDBcbiAgICAgIDogand0RXhwaXJ5ICE9PSB1bmRlZmluZWRcbiAgICAgICAgPyBqd3RFeHBpcnkgKiAxMDAwXG4gICAgICAgIDogdW5kZWZpbmVkO1xuXG4gIGlmIChleHBpcmVzQXRNcyA9PT0gdW5kZWZpbmVkIHx8ICFOdW1iZXIuaXNGaW5pdGUoZXhwaXJlc0F0TXMpKVxuICAgIHRocm93IG5ldyBHcm9rT0F1dGhFcnJvcihcIm1pc3NpbmdfZXhwaXJ5XCIsIFwidG9rZW4gcmVzcG9uc2UgaGFzIG5vIGV4cGlyeVwiKTtcblxuICBjb25zdCBncmFudGVkU2NvcGVzID0gdG9rZW5zLnNjb3BlPy5zcGxpdChcIiBcIikuZmlsdGVyKEJvb2xlYW4pO1xuXG4gIGNvbnN0IGNhbmRpZGF0ZTogR3Jva0NyZWRlbnRpYWxzID0ge1xuICAgIGF1dGhNb2RlOiBcIm9hdXRoXCIgYXMgY29uc3QsXG4gICAgYWNjZXNzVG9rZW46IHRva2Vucy5hY2Nlc3NfdG9rZW4sXG4gICAgcmVmcmVzaFRva2VuOiB0b2tlbnMucmVmcmVzaF90b2tlbixcbiAgICBleHBpcmVzQXQ6IG5ldyBEYXRlKGV4cGlyZXNBdE1zKS50b0lTT1N0cmluZygpLFxuICAgIGlzc3VlcjogR1JPS19BVVRIX0lTU1VFUixcbiAgICBjbGllbnRJZDogR1JPS19PQVVUSF9DTElFTlRfSUQsXG4gICAgc2NvcGVzOlxuICAgICAgZ3JhbnRlZFNjb3BlcyAmJiBncmFudGVkU2NvcGVzLmxlbmd0aCA+IDBcbiAgICAgICAgPyBncmFudGVkU2NvcGVzXG4gICAgICAgIDogWy4uLihpbnB1dC5yZXF1ZXN0ZWRTY29wZXMgPz8gR1JPS19PQVVUSF9TQ09QRVMpXSxcbiAgICB1c2VySWQ6IHVzZXIuZGF0YS51c2VySWQsXG4gICAgc2Vzc2lvbklkOiByYW5kb21VVUlEKCksXG4gICAgYWdlbnRJZDogcmFuZG9tVVVJRCgpLFxuICB9O1xuXG4gIGlmICh1c2VyLmRhdGEuc3Vic2NyaXB0aW9uVGllcikgY2FuZGlkYXRlLnN1YnNjcmlwdGlvblRpZXIgPSB1c2VyLmRhdGEuc3Vic2NyaXB0aW9uVGllcjtcblxuICBjb25zdCBjcmVkZW50aWFscyA9IEdyb2tDcmVkZW50aWFscy5zYWZlUGFyc2UoY2FuZGlkYXRlKTtcblxuICBpZiAoIWNyZWRlbnRpYWxzLnN1Y2Nlc3MpXG4gICAgdGhyb3cgbmV3IEdyb2tPQXV0aEVycm9yKFwiaW52YWxpZF9jcmVkZW50aWFsc1wiLCBcImNyZWRlbnRpYWxzIGZhaWxlZCB2YWxpZGF0aW9uXCIpO1xuXG4gIHJldHVybiBjcmVkZW50aWFscy5kYXRhO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIENvbXBsZXRlR3Jva09BdXRoSW5wdXQgZXh0ZW5kcyBHcm9rT0F1dGhJbyB7XG4gIGNvZGVPclVybDogc3RyaW5nO1xuICB2ZXJpZmllcjogc3RyaW5nO1xuICByZWRpcmVjdFVyaTogc3RyaW5nO1xuICAvKiogVGhlIHN0YXRlIGlzc3VlZCB3aXRoIHRoZSBhdXRob3JpemUgVVJMOyBhIHBhc3RlZCBVUkwgbXVzdCBlY2hvIGl0LiAqL1xuICBzdGF0ZTogc3RyaW5nO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY29tcGxldGVHcm9rT0F1dGgoaW5wdXQ6IENvbXBsZXRlR3Jva09BdXRoSW5wdXQpOiBQcm9taXNlPEdyb2tDcmVkZW50aWFscz4ge1xuICBjb25zdCBmZXRjaEltcGwgPSBpbnB1dC5mZXRjaCA/PyBnbG9iYWxUaGlzLmZldGNoO1xuICBjb25zdCBjYWxsYmFjayA9IHBhcnNlR3Jva0NhbGxiYWNrSW5wdXQoaW5wdXQuY29kZU9yVXJsKTtcblxuICAvLyBBIGJhcmUgY29kZSBjYXJyaWVzIG5vIHN0YXRlOyB0aGUgY2FsbGVyIGJpbmRzIGl0IHRvIHRoZSBwZW5kaW5nIGxvZ2luIChvaWRjL2xvZ2luLnJzOjQ1Mi00NTUpLlxuICBpZiAoY2FsbGJhY2suc3RhdGUgJiYgIXN0YXRlc0VxdWFsKGlucHV0LnN0YXRlLCBjYWxsYmFjay5zdGF0ZSkpXG4gICAgdGhyb3cgbmV3IEdyb2tPQXV0aEVycm9yKFwic3RhdGVfbWlzbWF0Y2hcIiwgXCJPQXV0aCBzdGF0ZSBtaXNtYXRjaFwiKTtcblxuICBjb25zdCBlbmRwb2ludHMgPSBhd2FpdCBnZXRHcm9rT0F1dGhFbmRwb2ludHMoaW5wdXQpO1xuICBsZXQgcmVzcG9uc2U6IFJlc3BvbnNlO1xuXG4gIHRyeSB7XG4gICAgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaEltcGwoZW5kcG9pbnRzLnRva2VuRW5kcG9pbnQsIHtcbiAgICAgIG1ldGhvZDogXCJQT1NUXCIsXG4gICAgICAvLyBvaWRjL3Byb3RvY29sLnJzOjM4NS0zOTk6IGZvcm0gYm9keSwgeC1ncm9rLWNsaWVudC12ZXJzaW9uLCBzaGFyZWQtY2xpZW50IFVBLlxuICAgICAgaGVhZGVyczogZm9ybUhlYWRlcnMoeyBcIngtZ3Jvay1jbGllbnQtdmVyc2lvblwiOiBHUk9LX0JVSUxEX1ZFUlNJT04gfSksXG4gICAgICBib2R5OiBuZXcgVVJMU2VhcmNoUGFyYW1zKFtcbiAgICAgICAgW1wiZ3JhbnRfdHlwZVwiLCBcImF1dGhvcml6YXRpb25fY29kZVwiXSxcbiAgICAgICAgW1wiY29kZVwiLCBjYWxsYmFjay5jb2RlXSxcbiAgICAgICAgW1wicmVkaXJlY3RfdXJpXCIsIGlucHV0LnJlZGlyZWN0VXJpXSxcbiAgICAgICAgW1wiY2xpZW50X2lkXCIsIEdST0tfT0FVVEhfQ0xJRU5UX0lEXSxcbiAgICAgICAgW1wiY29kZV92ZXJpZmllclwiLCBpbnB1dC52ZXJpZmllcl0sXG4gICAgICBdKSxcbiAgICAgIHNpZ25hbDogQWJvcnRTaWduYWwudGltZW91dChUT0tFTl9USU1FT1VUX01TKSxcbiAgICB9KTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICB0aHJvdyBuZXR3b3JrRXJyb3IoXCJ0b2tlbl9leGNoYW5nZV9mYWlsZWRcIiwgXCJ0b2tlbiBleGNoYW5nZVwiLCBlcnJvcik7XG4gIH1cblxuICBpZiAoIXJlc3BvbnNlLm9rKSB7XG4gICAgY29uc3Qgb2F1dGhFcnJvciA9IGF3YWl0IHJlYWRHcm9rT0F1dGhFcnJvckNvZGUocmVzcG9uc2UpO1xuICAgIGNvbnN0IGVycm9yT3B0aW9uczogR3Jva09BdXRoRXJyb3JbXCJvcHRpb25zXCJdID0geyBzdGF0dXM6IHJlc3BvbnNlLnN0YXR1cyB9O1xuXG4gICAgaWYgKG9hdXRoRXJyb3IgIT09IHVuZGVmaW5lZCkgZXJyb3JPcHRpb25zLm9hdXRoRXJyb3IgPSBvYXV0aEVycm9yO1xuICAgIGVycm9yT3B0aW9ucy5yZXRyeWFibGUgPSByZXNwb25zZS5zdGF0dXMgPj0gNTAwO1xuICAgIHRocm93IG5ldyBHcm9rT0F1dGhFcnJvcihcbiAgICAgIFwidG9rZW5fZXhjaGFuZ2VfZmFpbGVkXCIsXG4gICAgICBgdG9rZW4gZXhjaGFuZ2UgZmFpbGVkOiBIVFRQICR7cmVzcG9uc2Uuc3RhdHVzfSAke29hdXRoRXJyb3IgPz8gXCJ1bmtub3duXCJ9YCxcbiAgICAgIGVycm9yT3B0aW9ucyxcbiAgICApO1xuICB9XG5cbiAgcmV0dXJuIGZpbmlzaEdyb2tMb2dpbih7XG4gICAgLi4uaW5wdXQsXG4gICAgZmV0Y2g6IGZldGNoSW1wbCxcbiAgICB0b2tlbnM6IGF3YWl0IHBhcnNlVG9rZW5SZXNwb25zZShyZXNwb25zZSksXG4gIH0pO1xufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIERldmljZSBjb2RlIChSRkMgODYyOClcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vLyBkZXZpY2VfY29kZS5yczoxOS0yMFxuZXhwb3J0IGNvbnN0IEdST0tfREVWSUNFX0RFRkFVTFRfSU5URVJWQUxfUyA9IDU7XG5leHBvcnQgY29uc3QgR1JPS19ERVZJQ0VfU0xPV19ET1dOX0lOQ1JFTUVOVF9TID0gNTtcbmNvbnN0IERFVklDRV9HUkFOVF9UWVBFID0gXCJ1cm46aWV0ZjpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTpkZXZpY2VfY29kZVwiO1xuXG4vLyBUaGUgZGFzaGJvYXJkIHJlbmRlcnMgdGhlIFVSTCBhbmQgY29kZSB0byBhIGh1bWFuIChkZXZpY2VfY29kZS5yczoyNjYtMjcxIOKGkiBgdWlgKS5cbmNvbnN0IERFVklDRV9DTElFTlRfU1VSRkFDRSA9IFwidWlcIjtcblxuZnVuY3Rpb24gaXNBbGxvd2VkVmVyaWZpY2F0aW9uVXJpKHZhbHVlOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgLy8gZGV2aWNlX2NvZGUucnM6NDc1LTQ4ODogcmVqZWN0IGNvbnRyb2wgY2hhcmFjdGVycywgcmVxdWlyZSBodHRwcyAoaHR0cCBvbmx5IG9uIGxvb3BiYWNrKS5cbiAgLy8gQ29udHJvbCBjaGFyYWN0ZXJzIGFyZSBzaW5nbGUgVVRGLTE2IGNvZGUgdW5pdHMsIHNvIHNjYW5uaW5nIGNvZGUgdW5pdHMgaXMgZXhhY3QuXG4gIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCB2YWx1ZS5sZW5ndGg7IGluZGV4KyspIHtcbiAgICBjb25zdCBjb2RlID0gdmFsdWUuY2hhckNvZGVBdChpbmRleCk7XG5cbiAgICBpZiAoY29kZSA8IDB4MjAgfHwgY29kZSA9PT0gMHg3ZikgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgbGV0IHVybDogVVJMO1xuXG4gIHRyeSB7XG4gICAgdXJsID0gbmV3IFVSTCh2YWx1ZSk7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmICh1cmwucHJvdG9jb2wgPT09IFwiaHR0cHM6XCIpIHJldHVybiB0cnVlO1xuXG4gIHJldHVybiB1cmwucHJvdG9jb2wgPT09IFwiaHR0cDpcIiAmJiAodXJsLmhvc3RuYW1lID09PSBcImxvY2FsaG9zdFwiIHx8IHVybC5ob3N0bmFtZSA9PT0gXCIxMjcuMC4wLjFcIik7XG59XG5cbmNvbnN0IERldmljZUNvZGVSZXNwb25zZSA9IHoubG9vc2VPYmplY3Qoe1xuICBkZXZpY2VfY29kZTogei5zdHJpbmcoKS5taW4oMSksXG4gIHVzZXJfY29kZTogei5zdHJpbmcoKS5yZWdleCgvXltBLVphLXowLTktXSskLyksXG4gIHZlcmlmaWNhdGlvbl91cmk6IHouc3RyaW5nKCkucmVmaW5lKGlzQWxsb3dlZFZlcmlmaWNhdGlvblVyaSksXG4gIHZlcmlmaWNhdGlvbl91cmlfY29tcGxldGU6IHouc3RyaW5nKCkucmVmaW5lKGlzQWxsb3dlZFZlcmlmaWNhdGlvblVyaSkubnVsbGlzaCgpLFxuICBleHBpcmVzX2luOiB6Lm51bWJlcigpLnBvc2l0aXZlKCksXG4gIGludGVydmFsOiB6Lm51bWJlcigpLmludCgpLnBvc2l0aXZlKCkubnVsbGlzaCgpLFxufSk7XG5cbmV4cG9ydCBpbnRlcmZhY2UgR3Jva0RldmljZUNvZGUge1xuICBkZXZpY2VDb2RlOiBzdHJpbmc7XG4gIHVzZXJDb2RlOiBzdHJpbmc7XG4gIHZlcmlmaWNhdGlvblVyaTogc3RyaW5nO1xuICB2ZXJpZmljYXRpb25VcmlDb21wbGV0ZT86IHN0cmluZztcbiAgLyoqIFNlY29uZHMgdW50aWwgdGhlIGRldmljZSBjb2RlIGV4cGlyZXMuICovXG4gIGV4cGlyZXNJbjogbnVtYmVyO1xuICAvKiogU2Vjb25kcyB0byB3YWl0IGJlZm9yZSB0aGUgbmV4dCBwb2xsLiAqL1xuICBpbnRlcnZhbDogbnVtYmVyO1xufVxuXG5mdW5jdGlvbiBkZXZpY2VIZWFkZXJzKCk6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4ge1xuICByZXR1cm4gZm9ybUhlYWRlcnMoe1xuICAgIFwieC1ncm9rLWNsaWVudC12ZXJzaW9uXCI6IEdST0tfQlVJTERfVkVSU0lPTixcbiAgICBcIngtZ3Jvay1jbGllbnQtc3VyZmFjZVwiOiBERVZJQ0VfQ0xJRU5UX1NVUkZBQ0UsXG4gIH0pO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc3RhcnRHcm9rRGV2aWNlQ29kZShpbzogR3Jva09BdXRoSW8gPSB7fSk6IFByb21pc2U8R3Jva0RldmljZUNvZGU+IHtcbiAgY29uc3QgZmV0Y2hJbXBsID0gaW8uZmV0Y2ggPz8gZ2xvYmFsVGhpcy5mZXRjaDtcbiAgbGV0IHJlc3BvbnNlOiBSZXNwb25zZTtcblxuICB0cnkge1xuICAgIHJlc3BvbnNlID0gYXdhaXQgZmV0Y2hJbXBsKEdST0tfREVWSUNFX0NPREVfVVJMLCB7XG4gICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgaGVhZGVyczogZGV2aWNlSGVhZGVycygpLFxuICAgICAgYm9keTogbmV3IFVSTFNlYXJjaFBhcmFtcyhbXG4gICAgICAgIFtcImNsaWVudF9pZFwiLCBHUk9LX09BVVRIX0NMSUVOVF9JRF0sXG4gICAgICAgIFtcInNjb3BlXCIsIEdST0tfT0FVVEhfU0NPUEVdLFxuICAgICAgICBbXCJyZWZlcnJlclwiLCBHUk9LX09BVVRIX1JFRkVSUkVSXSxcbiAgICAgIF0pLFxuICAgICAgc2lnbmFsOiBBYm9ydFNpZ25hbC50aW1lb3V0KFRPS0VOX1RJTUVPVVRfTVMpLFxuICAgIH0pO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIHRocm93IG5ldHdvcmtFcnJvcihcImRldmljZV9jb2RlX2ZhaWxlZFwiLCBcImRldmljZSBjb2RlXCIsIGVycm9yKTtcbiAgfVxuXG4gIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICBhd2FpdCByZXNwb25zZS5ib2R5Py5jYW5jZWwoKS5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuXG4gICAgaWYgKHJlc3BvbnNlLnN0YXR1cyA9PT0gNDA0KVxuICAgICAgdGhyb3cgbmV3IEdyb2tPQXV0aEVycm9yKFwiZGV2aWNlX2Zsb3dfbm90X2VuYWJsZWRcIiwgXCJkZXZpY2UtY29kZSBsb2dpbiBpcyBub3QgYXZhaWxhYmxlXCIsIHtcbiAgICAgICAgc3RhdHVzOiA0MDQsXG4gICAgICB9KTtcbiAgICB0aHJvdyBuZXcgR3Jva09BdXRoRXJyb3IoXG4gICAgICBcImRldmljZV9jb2RlX2ZhaWxlZFwiLFxuICAgICAgYGRldmljZSBjb2RlIHJlcXVlc3QgZmFpbGVkOiBIVFRQICR7cmVzcG9uc2Uuc3RhdHVzfWAsXG4gICAgICB7IHN0YXR1czogcmVzcG9uc2Uuc3RhdHVzLCByZXRyeWFibGU6IHJlc3BvbnNlLnN0YXR1cyA+PSA1MDAgfHwgcmVzcG9uc2Uuc3RhdHVzID09PSA0MjkgfSxcbiAgICApO1xuICB9XG5cbiAgbGV0IGJvZHk6IHVua25vd247XG5cbiAgdHJ5IHtcbiAgICBib2R5ID0gYXdhaXQgcmVzcG9uc2UuanNvbigpO1xuICB9IGNhdGNoIHtcbiAgICB0aHJvdyBuZXcgR3Jva09BdXRoRXJyb3IoXCJpbnZhbGlkX2RldmljZV9jb2RlX3Jlc3BvbnNlXCIsIFwiZGV2aWNlIGNvZGUgcmVzcG9uc2UgaXMgbm90IEpTT05cIik7XG4gIH1cblxuICBjb25zdCBwYXJzZWQgPSBEZXZpY2VDb2RlUmVzcG9uc2Uuc2FmZVBhcnNlKGJvZHkpO1xuXG4gIGlmICghcGFyc2VkLnN1Y2Nlc3MpXG4gICAgdGhyb3cgbmV3IEdyb2tPQXV0aEVycm9yKFxuICAgICAgXCJpbnZhbGlkX2RldmljZV9jb2RlX3Jlc3BvbnNlXCIsXG4gICAgICBcImRldmljZSBjb2RlIHJlc3BvbnNlIGZhaWxlZCB2YWxpZGF0aW9uXCIsXG4gICAgKTtcbiAgY29uc3QgZGF0YSA9IHBhcnNlZC5kYXRhO1xuXG4gIGNvbnN0IGRldmljZUNvZGU6IEdyb2tEZXZpY2VDb2RlID0ge1xuICAgIGRldmljZUNvZGU6IGRhdGEuZGV2aWNlX2NvZGUsXG4gICAgdXNlckNvZGU6IGRhdGEudXNlcl9jb2RlLFxuICAgIHZlcmlmaWNhdGlvblVyaTogZGF0YS52ZXJpZmljYXRpb25fdXJpLFxuICAgIGV4cGlyZXNJbjogZGF0YS5leHBpcmVzX2luLFxuICAgIGludGVydmFsOiBkYXRhLmludGVydmFsID8/IEdST0tfREVWSUNFX0RFRkFVTFRfSU5URVJWQUxfUyxcbiAgfTtcblxuICBpZiAoZGF0YS52ZXJpZmljYXRpb25fdXJpX2NvbXBsZXRlKSB7XG4gICAgZGV2aWNlQ29kZS52ZXJpZmljYXRpb25VcmlDb21wbGV0ZSA9IGRhdGEudmVyaWZpY2F0aW9uX3VyaV9jb21wbGV0ZTtcbiAgfVxuXG4gIHJldHVybiBkZXZpY2VDb2RlO1xufVxuXG5leHBvcnQgdHlwZSBHcm9rRGV2aWNlUG9sbFJlc3VsdCA9XG4gIHwgeyBzdGF0dXM6IFwicGVuZGluZ1wiOyBpbnRlcnZhbDogbnVtYmVyIH1cbiAgfCB7IHN0YXR1czogXCJjb21wbGV0ZVwiOyBjcmVkZW50aWFsczogR3Jva0NyZWRlbnRpYWxzIH07XG5cbmV4cG9ydCBpbnRlcmZhY2UgUG9sbEdyb2tEZXZpY2VDb2RlSW5wdXQgZXh0ZW5kcyBHcm9rT0F1dGhJbyB7XG4gIGRldmljZUNvZGU6IHN0cmluZztcbiAgLyoqIEN1cnJlbnQgcG9sbCBpbnRlcnZhbCBpbiBzZWNvbmRzOyB0aGUgcmVzdWx0IGNhcnJpZXMgdGhlIGludGVydmFsIGZvciB0aGUgbmV4dCBwb2xsLiAqL1xuICBpbnRlcnZhbDogbnVtYmVyO1xufVxuXG4vKipcbiAqIE9uZSBwb2xsIG9mIHRoZSBkZXZpY2UgdG9rZW4gZW5kcG9pbnQuIFRoZSBjYWxsZXIgc2xlZXBzIGBpbnRlcnZhbGAgc2Vjb25kcyBiZXR3ZWVuIHBvbGxzIGFuZFxuICogZW5mb3JjZXMgdGhlIGRldmljZS1jb2RlIGV4cGlyeTsgdGhpcyBmdW5jdGlvbiBuZXZlciBsb29wcy5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHBvbGxHcm9rRGV2aWNlQ29kZShcbiAgaW5wdXQ6IFBvbGxHcm9rRGV2aWNlQ29kZUlucHV0LFxuKTogUHJvbWlzZTxHcm9rRGV2aWNlUG9sbFJlc3VsdD4ge1xuICBjb25zdCBmZXRjaEltcGwgPSBpbnB1dC5mZXRjaCA/PyBnbG9iYWxUaGlzLmZldGNoO1xuICBjb25zdCBpbnRlcnZhbCA9IE1hdGgubWF4KDEsIE1hdGguY2VpbChpbnB1dC5pbnRlcnZhbCkpO1xuICBsZXQgcmVzcG9uc2U6IFJlc3BvbnNlO1xuXG4gIHRyeSB7XG4gICAgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaEltcGwoR1JPS19ERVZJQ0VfVE9LRU5fVVJMLCB7XG4gICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgaGVhZGVyczogZGV2aWNlSGVhZGVycygpLFxuICAgICAgYm9keTogbmV3IFVSTFNlYXJjaFBhcmFtcyhbXG4gICAgICAgIFtcImdyYW50X3R5cGVcIiwgREVWSUNFX0dSQU5UX1RZUEVdLFxuICAgICAgICBbXCJkZXZpY2VfY29kZVwiLCBpbnB1dC5kZXZpY2VDb2RlXSxcbiAgICAgICAgW1wiY2xpZW50X2lkXCIsIEdST0tfT0FVVEhfQ0xJRU5UX0lEXSxcbiAgICAgIF0pLFxuICAgICAgc2lnbmFsOiBBYm9ydFNpZ25hbC50aW1lb3V0KFRPS0VOX1RJTUVPVVRfTVMpLFxuICAgIH0pO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIHRocm93IG5ldHdvcmtFcnJvcihcImRldmljZV90b2tlbl9mYWlsZWRcIiwgXCJkZXZpY2UgdG9rZW5cIiwgZXJyb3IpO1xuICB9XG5cbiAgaWYgKHJlc3BvbnNlLm9rKVxuICAgIHJldHVybiB7XG4gICAgICBzdGF0dXM6IFwiY29tcGxldGVcIixcbiAgICAgIGNyZWRlbnRpYWxzOiBhd2FpdCBmaW5pc2hHcm9rTG9naW4oe1xuICAgICAgICAuLi5pbnB1dCxcbiAgICAgICAgZmV0Y2g6IGZldGNoSW1wbCxcbiAgICAgICAgdG9rZW5zOiBhd2FpdCBwYXJzZVRva2VuUmVzcG9uc2UocmVzcG9uc2UpLFxuICAgICAgfSksXG4gICAgfTtcblxuICBjb25zdCBvYXV0aEVycm9yID0gYXdhaXQgcmVhZEdyb2tPQXV0aEVycm9yQ29kZShyZXNwb25zZSk7XG5cbiAgc3dpdGNoIChvYXV0aEVycm9yKSB7XG4gICAgY2FzZSBcImF1dGhvcml6YXRpb25fcGVuZGluZ1wiOlxuICAgICAgcmV0dXJuIHsgc3RhdHVzOiBcInBlbmRpbmdcIiwgaW50ZXJ2YWwgfTtcbiAgICBjYXNlIFwic2xvd19kb3duXCI6XG4gICAgICByZXR1cm4geyBzdGF0dXM6IFwicGVuZGluZ1wiLCBpbnRlcnZhbDogaW50ZXJ2YWwgKyBHUk9LX0RFVklDRV9TTE9XX0RPV05fSU5DUkVNRU5UX1MgfTtcbiAgICBjYXNlIFwiYWNjZXNzX2RlbmllZFwiOlxuICAgICAgdGhyb3cgbmV3IEdyb2tPQXV0aEVycm9yKFwiYWNjZXNzX2RlbmllZFwiLCBcImF1dGhvcml6YXRpb24gZGVuaWVkIGJ5IHRoZSB1c2VyXCIsIHtcbiAgICAgICAgc3RhdHVzOiByZXNwb25zZS5zdGF0dXMsXG4gICAgICAgIG9hdXRoRXJyb3IsXG4gICAgICB9KTtcbiAgICBjYXNlIFwiZXhwaXJlZF90b2tlblwiOlxuICAgICAgdGhyb3cgbmV3IEdyb2tPQXV0aEVycm9yKFwiZXhwaXJlZF90b2tlblwiLCBcImRldmljZSBjb2RlIGV4cGlyZWRcIiwge1xuICAgICAgICBzdGF0dXM6IHJlc3BvbnNlLnN0YXR1cyxcbiAgICAgICAgb2F1dGhFcnJvcixcbiAgICAgIH0pO1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgR3Jva09BdXRoRXJyb3IoXG4gICAgICAgIFwiZGV2aWNlX3Rva2VuX2ZhaWxlZFwiLFxuICAgICAgICBgZGV2aWNlIHRva2VuIHJlcXVlc3QgZmFpbGVkOiBIVFRQICR7cmVzcG9uc2Uuc3RhdHVzfSAke29hdXRoRXJyb3IgPz8gXCJ1bmtub3duXCJ9YCxcbiAgICAgICAgZGV2aWNlVG9rZW5FcnJvck9wdGlvbnMocmVzcG9uc2Uuc3RhdHVzLCBvYXV0aEVycm9yKSxcbiAgICAgICk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZGV2aWNlVG9rZW5FcnJvck9wdGlvbnMoXG4gIHN0YXR1czogbnVtYmVyLFxuICBvYXV0aEVycm9yOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4pOiBHcm9rT0F1dGhFcnJvcltcIm9wdGlvbnNcIl0ge1xuICBjb25zdCBlcnJvck9wdGlvbnM6IEdyb2tPQXV0aEVycm9yW1wib3B0aW9uc1wiXSA9IHsgc3RhdHVzIH07XG5cbiAgaWYgKG9hdXRoRXJyb3IgIT09IHVuZGVmaW5lZCkgZXJyb3JPcHRpb25zLm9hdXRoRXJyb3IgPSBvYXV0aEVycm9yO1xuICBlcnJvck9wdGlvbnMucmV0cnlhYmxlID0gb2F1dGhFcnJvciA9PT0gdW5kZWZpbmVkICYmIHN0YXR1cyA+PSA1MDA7XG5cbiAgcmV0dXJuIGVycm9yT3B0aW9ucztcbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQW9EQSxJQUFhLGlCQUFiLGNBQW9DLE1BQU07Q0FHN0I7Q0FFQTtDQUpYLE9BQXlCO0NBQ3pCLFlBQ0UsTUFDQSxTQUNBLFVBQWtGLENBQUMsR0FDbkY7RUFDQSxNQUFNLE9BQU87RUFKSixLQUFBLE9BQUE7RUFFQSxLQUFBLFVBQUE7Q0FHWDtDQUVBLElBQUksU0FBNkI7RUFDL0IsT0FBTyxLQUFLLFFBQVE7Q0FDdEI7Q0FFQSxJQUFJLFlBQXFCO0VBQ3ZCLE9BQU8sS0FBSyxRQUFRLGFBQWE7Q0FDbkM7O0NBR0EsSUFBSSxhQUFpQztFQUNuQyxPQUFPLEtBQUssUUFBUTtDQUN0QjtBQUNGO0FBZ0JBLE1BQWEsd0JBQXdCLE9BQVUsS0FBSztBQUNwRCxNQUFhLHVDQUF1QyxHQUFHLGlCQUFpQjtBQUN4RSxNQUFhLCtCQUErQixHQUFHLGlCQUFpQjtBQUVoRSxNQUFNLHVCQUF1QjtBQUM3QixN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