@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.
- package/bundle/dist/_virtual/_rolldown/runtime.js +1 -10
- package/bundle/dist/application/monit/log-buffer.js +12 -6
- package/bundle/dist/application/monit/monit.frame.js +11 -3
- package/bundle/dist/application/monit/monit.types.js +1 -1
- package/bundle/dist/application/qgrid/conv-routing.js +9 -6
- package/bundle/dist/application/qgrid/expired-token-reminder.js +2 -2
- package/bundle/dist/application/qgrid/oauth.js +31 -4
- package/bundle/dist/application/qgrid/qgrid-image-generation.js +1 -1
- package/bundle/dist/application/qgrid/qgrid-response-format.js +22 -20
- package/bundle/dist/application/qgrid/qgrid-run-lifecycle.js +43 -34
- package/bundle/dist/application/qgrid/qgrid.dispatcher.js +128 -93
- package/bundle/dist/application/qgrid/qgrid.frame.js +930 -49
- package/bundle/dist/application/qgrid/qgrid.types.js +212 -5
- package/bundle/dist/application/qgrid/schema-prompt.js +75 -48
- package/bundle/dist/application/qgrid/slack-user-map.js +1 -1
- package/bundle/dist/application/qgrid/token-death.js +1 -1
- package/bundle/dist/application/qgrid/token-subscriber.js +83 -30
- package/bundle/dist/application/qgrid/token-trigger-setup.js +1 -1
- package/bundle/dist/application/qgrid/token-window-keepalive.js +8 -6
- package/bundle/dist/application/qgrid/tool-emulation-schema.js +13 -13
- package/bundle/dist/application/qgrid/tool-emulation.js +19 -15
- package/bundle/dist/application/request-log/json-schema-type-text.js +29 -12
- package/bundle/dist/application/request-log/request-log.model.js +83 -69
- package/bundle/dist/application/request-log/request-log.types.js +8 -2
- package/bundle/dist/application/request-log/zod-code-format.js +1 -1
- package/bundle/dist/application/request-log-step/request-log-step.model.js +1 -1
- package/bundle/dist/application/request-log-step/request-log-step.types.js +1 -1
- package/bundle/dist/application/setting/setting.constant.js +1 -1
- package/bundle/dist/application/setting/setting.model.js +2 -2
- package/bundle/dist/application/setting/setting.store.js +2 -2
- package/bundle/dist/application/setting/setting.types.js +1 -1
- package/bundle/dist/application/sonamu.generated.js +40 -16
- package/bundle/dist/application/sonamu.generated.sso.js +2 -1
- package/bundle/dist/application/token/token.model.js +26 -9
- package/bundle/dist/application/token/token.types.js +20 -3
- package/bundle/dist/i18n/en.js +15 -1
- package/bundle/dist/i18n/ko.js +15 -1
- package/bundle/dist/i18n/sd.generated.js +2 -1
- package/bundle/dist/migrations/20260807133553_manual__backfill_request_log_cost.js +8 -6
- package/bundle/dist/migrations/20261018215031_alter_request_logs_add1_alter1.js +15 -0
- package/bundle/dist/server-bootstrap.js +4 -2
- package/bundle/dist/server-error-handler.js +1 -1
- package/bundle/dist/sonamu.config.js +37 -8
- package/bundle/dist/startup-migrations.js +17 -7
- package/bundle/dist/testing/global.js +1 -1
- package/bundle/dist/testing/schema-bench.js +0 -0
- package/bundle/dist/testing/test-database-name.js +1 -1
- package/bundle/dist/utils/providers/anthropic/anthropic-constants.js +1 -1
- package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +11 -5
- package/bundle/dist/utils/providers/anthropic/anthropic-quota.js +4 -4
- package/bundle/dist/utils/providers/anthropic/anthropic-thinking.js +1 -1
- package/bundle/dist/utils/providers/anthropic/claude-session.js +20 -19
- package/bundle/dist/utils/providers/anthropic/fence-strip.js +1 -1
- package/bundle/dist/utils/providers/anthropic/stream-json-adapter.js +49 -23
- package/bundle/dist/utils/providers/common/credentials.js +5 -1
- package/bundle/dist/utils/providers/common/effort.js +3 -3
- package/bundle/dist/utils/providers/common/model-cost.js +69 -14
- package/bundle/dist/utils/providers/common/provider-types.js +29 -1
- package/bundle/dist/utils/providers/common/schema-validation.js +78 -40
- package/bundle/dist/utils/providers/common/smooth-weighted-round-robin.js +1 -1
- package/bundle/dist/utils/providers/common/strictifier.js +62 -43
- package/bundle/dist/utils/providers/common/thinking.js +3 -2
- package/bundle/dist/utils/providers/common/ttft.js +1 -1
- package/bundle/dist/utils/providers/grok/grok-backend-protocol.js +427 -0
- package/bundle/dist/utils/providers/grok/grok-constants.js +55 -0
- package/bundle/dist/utils/providers/grok/grok-direct-client.js +196 -0
- package/bundle/dist/utils/providers/grok/grok-dispatcher.js +1313 -0
- package/bundle/dist/utils/providers/grok/grok-headers.js +118 -0
- package/bundle/dist/utils/providers/grok/grok-media-client.js +420 -0
- package/bundle/dist/utils/providers/grok/grok-models.js +114 -0
- package/bundle/dist/utils/providers/grok/grok-oauth.js +455 -0
- package/bundle/dist/utils/providers/grok/grok-quota.js +119 -0
- package/bundle/dist/utils/providers/grok/grok-refresh.js +192 -0
- package/bundle/dist/utils/providers/grok/grok-types.js +186 -0
- package/bundle/dist/utils/providers/grok/grok-voice-client.js +199 -0
- package/bundle/dist/utils/providers/grok/index.js +11 -0
- package/bundle/dist/utils/providers/openai/openai-backend-protocol.js +111 -83
- package/bundle/dist/utils/providers/openai/openai-callback-relay.js +3 -2
- package/bundle/dist/utils/providers/openai/openai-constants.js +1 -1
- package/bundle/dist/utils/providers/openai/openai-direct-client.js +23 -7
- package/bundle/dist/utils/providers/openai/openai-dispatcher.js +143 -106
- package/bundle/dist/utils/providers/openai/openai-image-generation.js +48 -33
- package/bundle/dist/utils/providers/openai/openai-oauth.js +28 -13
- package/bundle/dist/utils/providers/openai/openai-quota.js +38 -27
- package/bundle/dist/utils/providers/openai/openai-refresh.js +17 -9
- package/bundle/dist/utils/providers/openai/openai-sse.js +1 -1
- package/bundle/dist/utils/providers/openai/openai-transport-config.js +1 -1
- package/bundle/dist/utils/quiet-hours.js +1 -1
- package/bundle/dist/utils/slack-notify.js +14 -8
- package/bundle/dist/utils/subset-loaders.js +4 -5
- package/bundle/src/application/monit/log-buffer.ts +23 -9
- package/bundle/src/application/monit/monit.frame.ts +22 -5
- package/bundle/src/application/monit/monit.types.ts +6 -0
- package/bundle/src/application/qgrid/conv-routing.test.ts +76 -4
- package/bundle/src/application/qgrid/conv-routing.ts +35 -9
- package/bundle/src/application/qgrid/expired-token-reminder.ts +9 -1
- package/bundle/src/application/qgrid/oauth.ts +51 -15
- package/bundle/src/application/qgrid/qgrid-image-generation.ts +9 -0
- package/bundle/src/application/qgrid/qgrid-response-format.ts +50 -25
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +33 -0
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.ts +87 -40
- package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +97 -0
- package/bundle/src/application/qgrid/qgrid.dispatcher.ts +274 -126
- package/bundle/src/application/qgrid/qgrid.frame.test.ts +1013 -3
- package/bundle/src/application/qgrid/qgrid.frame.ts +1415 -60
- package/bundle/src/application/qgrid/qgrid.types.ts +335 -0
- package/bundle/src/application/qgrid/schema-prompt.ts +105 -41
- package/bundle/src/application/qgrid/slack-user-map.ts +5 -0
- package/bundle/src/application/qgrid/token-death.ts +4 -0
- package/bundle/src/application/qgrid/token-subscriber.test.ts +21 -19
- package/bundle/src/application/qgrid/token-subscriber.ts +186 -53
- package/bundle/src/application/qgrid/token-trigger-setup.ts +2 -0
- package/bundle/src/application/qgrid/token-window-keepalive.ts +49 -6
- package/bundle/src/application/qgrid/tool-emulation-schema.ts +33 -29
- package/bundle/src/application/qgrid/tool-emulation.ts +52 -27
- package/bundle/src/application/request-log/json-schema-type-text.test.ts +5 -5
- package/bundle/src/application/request-log/json-schema-type-text.ts +81 -26
- package/bundle/src/application/request-log/request-log.entity.json +8 -0
- package/bundle/src/application/request-log/request-log.model.test.ts +111 -4
- package/bundle/src/application/request-log/request-log.model.ts +279 -145
- package/bundle/src/application/request-log/request-log.types.ts +17 -0
- package/bundle/src/application/request-log/zod-code-format.ts +11 -0
- package/bundle/src/application/request-log-step/request-log-step.model.ts +1 -0
- package/bundle/src/application/request-log-step/request-log-step.types.ts +2 -0
- package/bundle/src/application/setting/setting.constant.ts +9 -0
- package/bundle/src/application/setting/setting.model.ts +12 -2
- package/bundle/src/application/setting/setting.store.ts +5 -1
- package/bundle/src/application/setting/setting.types.ts +8 -0
- package/bundle/src/application/sonamu.generated.http +135 -0
- package/bundle/src/application/sonamu.generated.sso.ts +3 -0
- package/bundle/src/application/sonamu.generated.ts +29 -0
- package/bundle/src/application/token/token.identity.test.ts +20 -0
- package/bundle/src/application/token/token.model.ts +66 -7
- package/bundle/src/application/token/token.types.ts +24 -1
- package/bundle/src/i18n/en.ts +19 -0
- package/bundle/src/i18n/ko.ts +21 -0
- package/bundle/src/i18n/sd.generated.ts +24 -2
- package/bundle/src/migrations/20260807133553_manual__backfill_request_log_cost.ts +16 -8
- package/bundle/src/migrations/20261018215031_alter_request_logs_add1_alter1.ts +15 -0
- package/bundle/src/server-bootstrap.ts +4 -2
- package/bundle/src/server-error-handler.ts +1 -0
- package/bundle/src/sonamu.config.ts +69 -7
- package/bundle/src/startup-migrations.ts +27 -9
- package/bundle/src/testing/global.ts +20 -0
- package/bundle/src/testing/schema-bench.ts +105 -30
- package/bundle/src/testing/test-database-name.ts +2 -0
- package/bundle/src/utils/providers/anthropic/anthropic-constants.ts +8 -0
- package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +41 -6
- package/bundle/src/utils/providers/anthropic/anthropic-quota.ts +7 -3
- package/bundle/src/utils/providers/anthropic/anthropic-thinking.ts +6 -0
- package/bundle/src/utils/providers/anthropic/claude-session.ts +58 -24
- package/bundle/src/utils/providers/anthropic/fence-strip.ts +11 -0
- package/bundle/src/utils/providers/anthropic/stream-json-adapter.ts +110 -45
- package/bundle/src/utils/providers/common/credentials.ts +8 -0
- package/bundle/src/utils/providers/common/effort.ts +9 -2
- package/bundle/src/utils/providers/common/model-cost.test.ts +48 -1
- package/bundle/src/utils/providers/common/model-cost.ts +259 -158
- package/bundle/src/utils/providers/common/provider-dispatcher.ts +98 -2
- package/bundle/src/utils/providers/common/provider-types.ts +46 -3
- package/bundle/src/utils/providers/common/schema-validation.test.ts +5 -1
- package/bundle/src/utils/providers/common/schema-validation.ts +124 -56
- package/bundle/src/utils/providers/common/smooth-weighted-round-robin.ts +4 -0
- package/bundle/src/utils/providers/common/strictifier.ts +185 -59
- package/bundle/src/utils/providers/common/thinking.ts +2 -2
- package/bundle/src/utils/providers/common/ttft.ts +4 -2
- package/bundle/src/utils/providers/grok/__fixtures__/golden-responses-1.0.60.json +164 -0
- package/bundle/src/utils/providers/grok/grok-backend-protocol.test.ts +325 -0
- package/bundle/src/utils/providers/grok/grok-backend-protocol.ts +721 -0
- package/bundle/src/utils/providers/grok/grok-constants.ts +105 -0
- package/bundle/src/utils/providers/grok/grok-direct-client.test.ts +179 -0
- package/bundle/src/utils/providers/grok/grok-direct-client.ts +313 -0
- package/bundle/src/utils/providers/grok/grok-dispatcher.test.ts +1395 -0
- package/bundle/src/utils/providers/grok/grok-dispatcher.ts +2105 -0
- package/bundle/src/utils/providers/grok/grok-headers.test.ts +149 -0
- package/bundle/src/utils/providers/grok/grok-headers.ts +199 -0
- package/bundle/src/utils/providers/grok/grok-media-client.test.ts +446 -0
- package/bundle/src/utils/providers/grok/grok-media-client.ts +703 -0
- package/bundle/src/utils/providers/grok/grok-models.test.ts +96 -0
- package/bundle/src/utils/providers/grok/grok-models.ts +161 -0
- package/bundle/src/utils/providers/grok/grok-oauth.test.ts +406 -0
- package/bundle/src/utils/providers/grok/grok-oauth.ts +771 -0
- package/bundle/src/utils/providers/grok/grok-quota.test.ts +142 -0
- package/bundle/src/utils/providers/grok/grok-quota.ts +198 -0
- package/bundle/src/utils/providers/grok/grok-refresh.test.ts +239 -0
- package/bundle/src/utils/providers/grok/grok-refresh.ts +325 -0
- package/bundle/src/utils/providers/grok/grok-types.test.ts +252 -0
- package/bundle/src/utils/providers/grok/grok-types.ts +374 -0
- package/bundle/src/utils/providers/grok/grok-voice-client.test.ts +321 -0
- package/bundle/src/utils/providers/grok/grok-voice-client.ts +284 -0
- package/bundle/src/utils/providers/grok/index.ts +20 -0
- package/bundle/src/utils/providers/openai/openai-backend-protocol.ts +221 -137
- package/bundle/src/utils/providers/openai/openai-callback-relay.ts +12 -1
- package/bundle/src/utils/providers/openai/openai-constants.ts +2 -0
- package/bundle/src/utils/providers/openai/openai-direct-client.ts +111 -21
- package/bundle/src/utils/providers/openai/openai-dispatcher.ts +322 -169
- package/bundle/src/utils/providers/openai/openai-image-generation.ts +116 -36
- package/bundle/src/utils/providers/openai/openai-oauth.ts +48 -20
- package/bundle/src/utils/providers/openai/openai-quota.ts +77 -46
- package/bundle/src/utils/providers/openai/openai-refresh.ts +42 -18
- package/bundle/src/utils/providers/openai/openai-sse.ts +27 -3
- package/bundle/src/utils/providers/openai/openai-transport-config.ts +2 -0
- package/bundle/src/utils/quiet-hours.ts +12 -1
- package/bundle/src/utils/slack-notify.ts +44 -13
- package/bundle/src/utils/subset-loaders.ts +7 -7
- package/bundle/web-dist/client/assets/clsx-5XM_pHvN.js +1 -0
- package/bundle/web-dist/client/assets/index-BA7uQ-6c.js +31 -0
- package/bundle/web-dist/client/assets/index-Be2qCZmI.css +1 -0
- package/bundle/web-dist/client/assets/logs-C47OJGEI.js +1 -0
- package/bundle/web-dist/client/assets/monit-BS9no0dU.js +4 -0
- package/bundle/web-dist/client/assets/plus-sdACTfH0.js +1 -0
- package/bundle/web-dist/client/assets/refresh-cw-CY8o_1cT.js +1 -0
- package/bundle/web-dist/client/assets/request-model-BRtFuZvj.js +1 -0
- package/bundle/web-dist/client/assets/routes-kqgkUxE8.js +5 -0
- package/bundle/web-dist/client/assets/{services.generated-BsieU37H.js → services.generated-CefiDXEv.js} +5 -5
- package/bundle/web-dist/client/assets/settings-DNDvFGSw.js +1 -0
- package/bundle/web-dist/client/assets/show-u8Np69q3.js +2 -0
- package/bundle/web-dist/client/assets/tokens-QvP410NW.js +1 -0
- package/bundle/web-dist/client/assets/total-cost-MnfKU8IN.js +1 -0
- package/bundle/web-dist/client/assets/use-oauth-login-flow-Bzdh28Ws.js +1 -0
- package/bundle/web-dist/client/assets/use-update-token-mutation-CfJKaxmR.js +1 -0
- package/bundle/web-dist/client/assets/vendor-react-CUFFrVN9.js +244 -0
- package/bundle/web-dist/client/assets/vendor-tanstack-Bf_jag9G.js +1 -0
- package/bundle/web-dist/client/index.html +6 -6
- package/bundle/web-dist/server/assets/clsx-D_N5PN_2.js +16 -0
- package/bundle/web-dist/server/assets/{lazyRouteComponent-Dtd0NR4r.js → lazyRouteComponent-D8iTIHyn.js} +129 -2
- package/bundle/web-dist/server/assets/logs-B3OTd9hy.js +825 -0
- package/bundle/web-dist/server/assets/{monit-DvzribSE.js → monit-B2hqorPe.js} +385 -126
- package/bundle/web-dist/server/assets/plus-DwG7h9kq.js +28 -0
- package/bundle/web-dist/server/assets/{react-dom-B4a6-uuR.js → react-dom-BIYQzBqG.js} +2 -129
- package/bundle/web-dist/server/assets/refresh-cw-mMBkwOq0.js +44 -0
- package/bundle/web-dist/server/assets/{request-model-CbqfnQOJ.js → request-model-I6OdODSH.js} +15 -6
- package/bundle/web-dist/server/assets/{routes-BAPWTizT.js → routes-B95YlUv2.js} +760 -213
- package/bundle/web-dist/server/assets/{services.generated-CEbGjsI0.js → services.generated-DQATJ6qf.js} +12821 -12194
- package/bundle/web-dist/server/assets/settings-C3gbGk0m.js +830 -0
- package/bundle/web-dist/server/assets/{show-CxVZTAdv.js → show-Bxaj3rhH.js} +1355 -419
- package/bundle/web-dist/server/assets/tokens-CZjH3cB7.js +1038 -0
- package/bundle/web-dist/server/assets/total-cost-fTE9Xy82.js +18 -0
- package/bundle/web-dist/server/assets/use-oauth-login-flow-CKDHgc3U.js +2379 -0
- package/bundle/web-dist/server/assets/{use-update-token-mutation-CfYmk_4_.js → use-update-token-mutation-BEbgOzaa.js} +1 -1
- package/bundle/web-dist/server/entry-server.generated.js +4303 -22810
- package/dist/cli.js +9 -9
- package/package.json +4 -11
- package/postinstall.mjs +12 -0
- package/skills/qgrid/SKILL.md +1 -0
- package/skills/qgrid/references/cli-env-and-server-boot.md +4 -1
- package/skills/qgrid/references/decision-rationale.md +24 -1
- package/skills/qgrid/references/grok-runtime.md +89 -0
- package/skills/qgrid/references/provider-runtime-differences.md +30 -29
- package/skills/qgrid/references/repo-map.md +10 -0
- package/skills/qgrid/references/request-log-run-lifecycle.md +1 -1
- package/skills/qgrid/references/sonamu-api-web-flow.md +1 -1
- package/skills/qgrid/references/token-auth-quota-lifecycle.md +56 -3
- package/bundle/dist/node_modules/.pnpm/@jridgewell_sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js +0 -406
- package/bundle/dist/node_modules/.pnpm/@vitest_expect@4.1.10/node_modules/@vitest/expect/dist/index.js +0 -1507
- package/bundle/dist/node_modules/.pnpm/@vitest_pretty-format@4.1.10/node_modules/@vitest/pretty-format/dist/index.js +0 -887
- package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/chunk-artifact.js +0 -2756
- package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/index.js +0 -8
- package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/utils.js +0 -8
- package/bundle/dist/node_modules/.pnpm/@vitest_snapshot@4.1.10/node_modules/@vitest/snapshot/dist/index.js +0 -922
- package/bundle/dist/node_modules/.pnpm/@vitest_spy@4.1.10/node_modules/@vitest/spy/dist/index.js +0 -386
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js +0 -121
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/constants.js +0 -51
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/diff.js +0 -1317
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/display.js +0 -561
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/error.js +0 -40
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/helpers.js +0 -272
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/offset.js +0 -27
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/serialize.js +0 -77
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/source-map.js +0 -381
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/timers.js +0 -51
- package/bundle/dist/node_modules/.pnpm/chai@6.2.2/node_modules/chai/index.js +0 -2986
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/branding.js +0 -10
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/index.js +0 -109
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/messages.js +0 -10
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/overloads.js +0 -10
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/utils.js +0 -10
- package/bundle/dist/node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.js +0 -1126
- package/bundle/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/index.js +0 -21
- package/bundle/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.js +0 -432
- package/bundle/dist/node_modules/.pnpm/tinybench@2.9.0/node_modules/tinybench/dist/index.js +0 -517
- package/bundle/dist/node_modules/.pnpm/tinyrainbow@3.1.0/node_modules/tinyrainbow/dist/index.js +0 -101
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- package/bundle/dist/testing/setup-mocks.js +0 -16
- package/bundle/src/testing/setup-mocks.ts +0 -44
- package/bundle/web-dist/client/assets/index-Bw2s88Ot.css +0 -1
- package/bundle/web-dist/client/assets/index-CrXKu_J8.js +0 -106
- package/bundle/web-dist/client/assets/logs-B2SmWJXA.js +0 -1
- package/bundle/web-dist/client/assets/monit-D-JwXXoA.js +0 -1
- package/bundle/web-dist/client/assets/plus-B62CuqT8.js +0 -1
- package/bundle/web-dist/client/assets/refresh-cw-NNcU0Cmq.js +0 -1
- package/bundle/web-dist/client/assets/request-model-CojtinqK.js +0 -1
- package/bundle/web-dist/client/assets/routes-C5r4gTvY.js +0 -5
- package/bundle/web-dist/client/assets/settings-D3tDSAck.js +0 -1
- package/bundle/web-dist/client/assets/show-Cah_kUKC.js +0 -2
- package/bundle/web-dist/client/assets/tokens-DU2Iyxxd.js +0 -1
- package/bundle/web-dist/client/assets/use-oauth-login-flow-D0UaR9_e.js +0 -1
- package/bundle/web-dist/client/assets/use-update-token-mutation-DAq0F8p-.js +0 -1
- package/bundle/web-dist/client/assets/vendor-react-DH4kUfK2.js +0 -9
- package/bundle/web-dist/client/assets/vendor-tanstack-DJRQAbrY.js +0 -1
- package/bundle/web-dist/server/assets/logs-l91avYif.js +0 -509
- package/bundle/web-dist/server/assets/plus-KZrECewT.js +0 -19
- package/bundle/web-dist/server/assets/refresh-cw-BND93JrF.js +0 -23
- package/bundle/web-dist/server/assets/settings-BZR5HSAL.js +0 -461
- package/bundle/web-dist/server/assets/tokens-D1hb4eKk.js +0 -448
- package/bundle/web-dist/server/assets/use-oauth-login-flow-Cvdy0zF8.js +0 -178
- package/dist/cli.d.ts +0 -10
- /package/bundle/web-dist/client/assets/{cost-DH2jZbrw.js → cost-DB3HbU7T.js} +0 -0
- /package/bundle/web-dist/client/assets/{preload-helper-ca-nBW7U.js → preload-helper-DWTEM3RW.js} +0 -0
- /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 {
|
|
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
|
|
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 =
|
|
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
|
|
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)
|
|
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
|
-
|
|
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
|
|
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
|
|
634
|
+
let runContext = threadCoord === void 0 ? void 0 : { threadCoord };
|
|
262
635
|
if (runInfo) try {
|
|
263
|
-
|
|
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)
|
|
283
|
-
...streamResult
|
|
284
|
-
|
|
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)
|
|
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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
|