@workflow/core 5.0.0-beta.5 → 5.0.0-beta.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (310) hide show
  1. package/dist/attribute-changes.d.ts +5 -0
  2. package/dist/attribute-changes.d.ts.map +1 -0
  3. package/dist/attribute-changes.js +25 -0
  4. package/dist/capabilities.d.ts +35 -2
  5. package/dist/capabilities.d.ts.map +1 -1
  6. package/dist/capabilities.js +74 -5
  7. package/dist/capture-stack.d.ts +1 -1
  8. package/dist/capture-stack.js +2 -2
  9. package/dist/class-serialization.d.ts +32 -0
  10. package/dist/class-serialization.d.ts.map +1 -1
  11. package/dist/class-serialization.js +37 -1
  12. package/dist/classify-error.d.ts +19 -3
  13. package/dist/classify-error.d.ts.map +1 -1
  14. package/dist/classify-error.js +98 -6
  15. package/dist/context-violation-error.d.ts +5 -5
  16. package/dist/context-violation-error.d.ts.map +1 -1
  17. package/dist/context-violation-error.js +8 -6
  18. package/dist/create-hook.d.ts +72 -7
  19. package/dist/create-hook.d.ts.map +1 -1
  20. package/dist/create-hook.js +1 -1
  21. package/dist/define-hook.js +2 -2
  22. package/dist/describe-error.d.ts +7 -7
  23. package/dist/describe-error.d.ts.map +1 -1
  24. package/dist/describe-error.js +97 -12
  25. package/dist/encryption.d.ts +38 -4
  26. package/dist/encryption.d.ts.map +1 -1
  27. package/dist/encryption.js +96 -14
  28. package/dist/events-consumer.d.ts +271 -0
  29. package/dist/events-consumer.d.ts.map +1 -1
  30. package/dist/events-consumer.js +646 -42
  31. package/dist/flushable-stream.d.ts +56 -1
  32. package/dist/flushable-stream.d.ts.map +1 -1
  33. package/dist/flushable-stream.js +123 -11
  34. package/dist/global.d.ts +36 -2
  35. package/dist/global.d.ts.map +1 -1
  36. package/dist/global.js +21 -6
  37. package/dist/index.d.ts +2 -1
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +3 -2
  40. package/dist/log-format.d.ts +2 -2
  41. package/dist/log-format.js +7 -7
  42. package/dist/logger.d.ts +1 -0
  43. package/dist/logger.d.ts.map +1 -1
  44. package/dist/logger.js +10 -6
  45. package/dist/private.d.ts +226 -9
  46. package/dist/private.d.ts.map +1 -1
  47. package/dist/private.js +626 -7
  48. package/dist/replay-payload-cache.d.ts +64 -0
  49. package/dist/replay-payload-cache.d.ts.map +1 -0
  50. package/dist/replay-payload-cache.js +158 -0
  51. package/dist/runtime/compute-instance.d.ts +13 -0
  52. package/dist/runtime/compute-instance.d.ts.map +1 -0
  53. package/dist/runtime/compute-instance.js +14 -0
  54. package/dist/runtime/constants.d.ts +315 -0
  55. package/dist/runtime/constants.d.ts.map +1 -1
  56. package/dist/runtime/constants.js +502 -16
  57. package/dist/runtime/count-step-started-events.d.ts +52 -0
  58. package/dist/runtime/count-step-started-events.d.ts.map +1 -0
  59. package/dist/runtime/count-step-started-events.js +72 -0
  60. package/dist/runtime/deployment-guard.d.ts +99 -0
  61. package/dist/runtime/deployment-guard.d.ts.map +1 -0
  62. package/dist/runtime/deployment-guard.js +154 -0
  63. package/dist/runtime/get-port-lazy.d.ts +15 -0
  64. package/dist/runtime/get-port-lazy.d.ts.map +1 -1
  65. package/dist/runtime/get-port-lazy.js +75 -6
  66. package/dist/runtime/get-world-lazy.d.ts +5 -14
  67. package/dist/runtime/get-world-lazy.d.ts.map +1 -1
  68. package/dist/runtime/get-world-lazy.js +19 -29
  69. package/dist/runtime/helpers.d.ts +341 -29
  70. package/dist/runtime/helpers.d.ts.map +1 -1
  71. package/dist/runtime/helpers.js +559 -57
  72. package/dist/runtime/quickjs-assets.generated.d.ts +14 -0
  73. package/dist/runtime/quickjs-assets.generated.d.ts.map +1 -0
  74. package/dist/runtime/quickjs-assets.generated.js +30 -0
  75. package/dist/runtime/quickjs-entrypoint.d.ts +136 -0
  76. package/dist/runtime/quickjs-entrypoint.d.ts.map +1 -0
  77. package/dist/runtime/quickjs-entrypoint.js +1686 -0
  78. package/dist/runtime/quickjs-runtime.d.ts +244 -0
  79. package/dist/runtime/quickjs-runtime.d.ts.map +1 -0
  80. package/dist/runtime/quickjs-runtime.js +2427 -0
  81. package/dist/runtime/quickjs-serde.d.ts +107 -0
  82. package/dist/runtime/quickjs-serde.d.ts.map +1 -0
  83. package/dist/runtime/quickjs-serde.js +2159 -0
  84. package/dist/runtime/replay-budget.d.ts +97 -0
  85. package/dist/runtime/replay-budget.d.ts.map +1 -0
  86. package/dist/runtime/replay-budget.js +139 -0
  87. package/dist/runtime/replay-recovery-reporter.d.ts +36 -0
  88. package/dist/runtime/replay-recovery-reporter.d.ts.map +1 -0
  89. package/dist/runtime/replay-recovery-reporter.js +64 -0
  90. package/dist/runtime/resume-hook.d.ts +91 -8
  91. package/dist/runtime/resume-hook.d.ts.map +1 -1
  92. package/dist/runtime/resume-hook.js +512 -89
  93. package/dist/runtime/resume-latency.d.ts +150 -0
  94. package/dist/runtime/resume-latency.d.ts.map +1 -0
  95. package/dist/runtime/resume-latency.js +155 -0
  96. package/dist/runtime/run-id-time.d.ts +19 -0
  97. package/dist/runtime/run-id-time.d.ts.map +1 -0
  98. package/dist/runtime/run-id-time.js +42 -0
  99. package/dist/runtime/run.d.ts +72 -7
  100. package/dist/runtime/run.d.ts.map +1 -1
  101. package/dist/runtime/run.js +280 -53
  102. package/dist/runtime/runs.d.ts +54 -3
  103. package/dist/runtime/runs.d.ts.map +1 -1
  104. package/dist/runtime/runs.js +126 -16
  105. package/dist/runtime/start.d.ts +101 -2
  106. package/dist/runtime/start.d.ts.map +1 -1
  107. package/dist/runtime/start.js +352 -61
  108. package/dist/runtime/step-executor.d.ts +205 -5
  109. package/dist/runtime/step-executor.d.ts.map +1 -1
  110. package/dist/runtime/step-executor.js +760 -127
  111. package/dist/runtime/step-latency.d.ts +220 -0
  112. package/dist/runtime/step-latency.d.ts.map +1 -0
  113. package/dist/runtime/step-latency.js +215 -0
  114. package/dist/runtime/step-ownership.d.ts +72 -0
  115. package/dist/runtime/step-ownership.d.ts.map +1 -0
  116. package/dist/runtime/step-ownership.js +114 -0
  117. package/dist/runtime/step-single-flight.d.ts +12 -0
  118. package/dist/runtime/step-single-flight.d.ts.map +1 -0
  119. package/dist/runtime/step-single-flight.js +75 -0
  120. package/dist/runtime/suspension-handler.d.ts +269 -7
  121. package/dist/runtime/suspension-handler.d.ts.map +1 -1
  122. package/dist/runtime/suspension-handler.js +1253 -125
  123. package/dist/runtime/unserializable-step.d.ts +34 -0
  124. package/dist/runtime/unserializable-step.d.ts.map +1 -0
  125. package/dist/runtime/unserializable-step.js +52 -0
  126. package/dist/runtime/vm-mode.d.ts +44 -0
  127. package/dist/runtime/vm-mode.d.ts.map +1 -0
  128. package/dist/runtime/vm-mode.js +62 -0
  129. package/dist/runtime/vm-serde-bundle.generated.d.ts +14 -0
  130. package/dist/runtime/vm-serde-bundle.generated.d.ts.map +1 -0
  131. package/dist/runtime/vm-serde-bundle.generated.js +16 -0
  132. package/dist/runtime/wait-continuation.d.ts +106 -0
  133. package/dist/runtime/wait-continuation.d.ts.map +1 -0
  134. package/dist/runtime/wait-continuation.js +136 -0
  135. package/dist/runtime/wait-until.d.ts +18 -0
  136. package/dist/runtime/wait-until.d.ts.map +1 -0
  137. package/dist/runtime/wait-until.js +42 -0
  138. package/dist/runtime/world-compatibility.d.ts +32 -0
  139. package/dist/runtime/world-compatibility.d.ts.map +1 -0
  140. package/dist/runtime/world-compatibility.js +44 -0
  141. package/dist/runtime/world-init.d.ts +17 -42
  142. package/dist/runtime/world-init.d.ts.map +1 -1
  143. package/dist/runtime/world-init.js +18 -43
  144. package/dist/runtime/world.d.ts +14 -2
  145. package/dist/runtime/world.d.ts.map +1 -1
  146. package/dist/runtime/world.js +75 -19
  147. package/dist/runtime.d.ts +10 -6
  148. package/dist/runtime.d.ts.map +1 -1
  149. package/dist/runtime.js +3741 -490
  150. package/dist/sealed-box.d.ts +167 -0
  151. package/dist/sealed-box.d.ts.map +1 -0
  152. package/dist/sealed-box.js +571 -0
  153. package/dist/serialization/client.d.ts +3 -3
  154. package/dist/serialization/client.d.ts.map +1 -1
  155. package/dist/serialization/client.js +8 -4
  156. package/dist/serialization/codec-devalue-vm.d.ts +16 -0
  157. package/dist/serialization/codec-devalue-vm.d.ts.map +1 -0
  158. package/dist/serialization/codec-devalue-vm.js +148 -0
  159. package/dist/serialization/codec-devalue.d.ts +1 -1
  160. package/dist/serialization/codec-devalue.d.ts.map +1 -1
  161. package/dist/serialization/codec-devalue.js +24 -6
  162. package/dist/serialization/codec.d.ts +37 -2
  163. package/dist/serialization/codec.d.ts.map +1 -1
  164. package/dist/serialization/codec.js +2 -2
  165. package/dist/serialization/compression.d.ts +105 -0
  166. package/dist/serialization/compression.d.ts.map +1 -0
  167. package/dist/serialization/compression.js +261 -0
  168. package/dist/serialization/encryption.d.ts +119 -17
  169. package/dist/serialization/encryption.d.ts.map +1 -1
  170. package/dist/serialization/encryption.js +152 -17
  171. package/dist/serialization/errors.d.ts +13 -0
  172. package/dist/serialization/errors.d.ts.map +1 -1
  173. package/dist/serialization/errors.js +20 -2
  174. package/dist/serialization/format.d.ts +6 -6
  175. package/dist/serialization/format.js +7 -7
  176. package/dist/serialization/hardened.d.ts +156 -0
  177. package/dist/serialization/hardened.d.ts.map +1 -0
  178. package/dist/serialization/hardened.js +538 -0
  179. package/dist/serialization/index.d.ts +10 -8
  180. package/dist/serialization/index.d.ts.map +1 -1
  181. package/dist/serialization/index.js +10 -8
  182. package/dist/serialization/reducers/class-vm.d.ts +20 -0
  183. package/dist/serialization/reducers/class-vm.d.ts.map +1 -0
  184. package/dist/serialization/reducers/class-vm.js +77 -0
  185. package/dist/serialization/reducers/class.d.ts.map +1 -1
  186. package/dist/serialization/reducers/class.js +11 -6
  187. package/dist/serialization/reducers/common-vm.d.ts +15 -0
  188. package/dist/serialization/reducers/common-vm.d.ts.map +1 -0
  189. package/dist/serialization/reducers/common-vm.js +616 -0
  190. package/dist/serialization/reducers/common.d.ts +1 -1
  191. package/dist/serialization/reducers/common.d.ts.map +1 -1
  192. package/dist/serialization/reducers/common.js +202 -62
  193. package/dist/serialization/reducers/step-function-vm.d.ts +44 -0
  194. package/dist/serialization/reducers/step-function-vm.d.ts.map +1 -0
  195. package/dist/serialization/reducers/step-function-vm.js +97 -0
  196. package/dist/serialization/reducers/step-function.d.ts.map +1 -1
  197. package/dist/serialization/reducers/step-function.js +25 -9
  198. package/dist/serialization/step.d.ts +4 -4
  199. package/dist/serialization/step.d.ts.map +1 -1
  200. package/dist/serialization/step.js +9 -5
  201. package/dist/serialization/types.d.ts +80 -1
  202. package/dist/serialization/types.d.ts.map +1 -1
  203. package/dist/serialization/types.js +15 -1
  204. package/dist/serialization/workflow-vm.d.ts +29 -0
  205. package/dist/serialization/workflow-vm.d.ts.map +1 -0
  206. package/dist/serialization/workflow-vm.js +74 -0
  207. package/dist/serialization-format.d.ts +64 -8
  208. package/dist/serialization-format.d.ts.map +1 -1
  209. package/dist/serialization-format.js +225 -73
  210. package/dist/serialization.d.ts +262 -34
  211. package/dist/serialization.d.ts.map +1 -1
  212. package/dist/serialization.js +1879 -274
  213. package/dist/set-attributes.d.ts +13 -0
  214. package/dist/set-attributes.d.ts.map +1 -0
  215. package/dist/set-attributes.js +60 -0
  216. package/dist/source-map.d.ts +25 -0
  217. package/dist/source-map.d.ts.map +1 -1
  218. package/dist/source-map.js +154 -10
  219. package/dist/step/context-storage.d.ts +61 -2
  220. package/dist/step/context-storage.d.ts.map +1 -1
  221. package/dist/step/context-storage.js +7 -5
  222. package/dist/step/writable-stream.d.ts +3 -3
  223. package/dist/step/writable-stream.d.ts.map +1 -1
  224. package/dist/step/writable-stream.js +72 -9
  225. package/dist/step.d.ts.map +1 -1
  226. package/dist/step.js +148 -27
  227. package/dist/symbols.d.ts +50 -0
  228. package/dist/symbols.d.ts.map +1 -1
  229. package/dist/symbols.js +51 -1
  230. package/dist/telemetry/semantic-conventions.d.ts +397 -2
  231. package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
  232. package/dist/telemetry/semantic-conventions.js +297 -3
  233. package/dist/telemetry.d.ts +91 -0
  234. package/dist/telemetry.d.ts.map +1 -1
  235. package/dist/telemetry.js +244 -17
  236. package/dist/test-support/orchestrator-context.d.ts +25 -0
  237. package/dist/test-support/orchestrator-context.d.ts.map +1 -0
  238. package/dist/test-support/orchestrator-context.js +101 -0
  239. package/dist/types.d.ts +6 -0
  240. package/dist/types.d.ts.map +1 -1
  241. package/dist/types.js +23 -1
  242. package/dist/util.d.ts +0 -5
  243. package/dist/util.d.ts.map +1 -1
  244. package/dist/util.js +1 -15
  245. package/dist/version.d.ts +1 -1
  246. package/dist/version.d.ts.map +1 -1
  247. package/dist/version.js +2 -2
  248. package/dist/vm/index.d.ts.map +1 -1
  249. package/dist/vm/index.js +84 -14
  250. package/dist/vm/script-cache.d.ts +26 -0
  251. package/dist/vm/script-cache.d.ts.map +1 -0
  252. package/dist/vm/script-cache.js +131 -0
  253. package/dist/vm/uint8array-base64.js +1 -1
  254. package/dist/workflow/abort-controller.d.ts +2 -2
  255. package/dist/workflow/abort-controller.d.ts.map +1 -1
  256. package/dist/workflow/abort-controller.js +88 -21
  257. package/dist/workflow/attribute-dispatcher.d.ts +6 -0
  258. package/dist/workflow/attribute-dispatcher.d.ts.map +1 -0
  259. package/dist/workflow/attribute-dispatcher.js +45 -0
  260. package/dist/workflow/create-hook.d.ts.map +1 -1
  261. package/dist/workflow/create-hook.js +24 -3
  262. package/dist/workflow/get-workflow-metadata.js +2 -2
  263. package/dist/workflow/hook.d.ts.map +1 -1
  264. package/dist/workflow/hook.js +304 -47
  265. package/dist/workflow/index.d.ts +1 -0
  266. package/dist/workflow/index.d.ts.map +1 -1
  267. package/dist/workflow/index.js +2 -1
  268. package/dist/workflow/set-attributes.d.ts +68 -0
  269. package/dist/workflow/set-attributes.d.ts.map +1 -0
  270. package/dist/workflow/set-attributes.js +60 -0
  271. package/dist/workflow/sleep.d.ts.map +1 -1
  272. package/dist/workflow/sleep.js +58 -12
  273. package/dist/workflow/world-init-stub.d.ts +3 -3
  274. package/dist/workflow/world-init-stub.js +4 -4
  275. package/dist/workflow.d.ts +95 -3
  276. package/dist/workflow.d.ts.map +1 -1
  277. package/dist/workflow.js +895 -561
  278. package/docs/api-reference/create-hook.mdx +89 -10
  279. package/docs/api-reference/create-webhook.mdx +16 -15
  280. package/docs/api-reference/define-hook.mdx +35 -33
  281. package/docs/api-reference/fatal-error.mdx +30 -8
  282. package/docs/api-reference/fetch.mdx +14 -10
  283. package/docs/api-reference/get-step-metadata.mdx +2 -2
  284. package/docs/api-reference/get-workflow-metadata.mdx +3 -3
  285. package/docs/api-reference/get-writable.mdx +7 -7
  286. package/docs/api-reference/index.mdx +4 -1
  287. package/docs/api-reference/retryable-error.mdx +1 -1
  288. package/docs/api-reference/set-attributes.mdx +61 -0
  289. package/docs/api-reference/sleep.mdx +4 -4
  290. package/docs/foundations/cancellation.mdx +31 -32
  291. package/docs/foundations/errors-and-retries.mdx +42 -11
  292. package/docs/foundations/hooks.mdx +64 -35
  293. package/docs/foundations/idempotency.mdx +244 -12
  294. package/docs/foundations/index.mdx +1 -23
  295. package/docs/foundations/meta.json +2 -1
  296. package/docs/foundations/serialization.mdx +21 -22
  297. package/docs/foundations/starting-workflows.mdx +106 -30
  298. package/docs/foundations/streaming.mdx +107 -59
  299. package/docs/foundations/versioning.mdx +263 -0
  300. package/docs/foundations/workflows-and-steps.mdx +9 -9
  301. package/docs/how-it-works/cancellation.mdx +63 -63
  302. package/docs/how-it-works/code-transform.mdx +83 -67
  303. package/docs/how-it-works/encryption.mdx +30 -26
  304. package/docs/how-it-works/event-sourcing.mdx +98 -34
  305. package/docs/how-it-works/framework-integrations.mdx +96 -337
  306. package/docs/how-it-works/understanding-directives.mdx +22 -22
  307. package/package.json +24 -15
  308. package/dist/runtime/step-handler.d.ts +0 -2
  309. package/dist/runtime/step-handler.d.ts.map +0 -1
  310. package/dist/runtime/step-handler.js +0 -776
@@ -1,135 +1,386 @@
1
- import { waitUntil } from '@vercel/functions';
2
- import { EntityConflictError, HookNotFoundError, RunExpiredError, } from '@workflow/errors';
3
- import { SPEC_VERSION_CURRENT, } from '@workflow/world';
1
+ import { EntityConflictError, FatalError, HookNotFoundError, PreconditionFailedError, RunExpiredError, SerializationError, WorkflowWorldError, } from '@workflow/errors';
2
+ import { AttributeValidationError, SPEC_VERSION_CURRENT, SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT, SPEC_VERSION_SUPPORTS_COMPRESSION, SPEC_VERSION_SUPPORTS_SLOT_IDENTITY, } from '@workflow/world';
3
+ import { isRetryableWorldError } from '../classify-error.js';
4
4
  import { importKey } from '../encryption.js';
5
5
  import { runtimeLogger } from '../logger.js';
6
- import { dehydrateStepArguments } from '../serialization.js';
7
- import { getAbortStreamIdFromToken } from '../util.js';
6
+ import { GUEST_CODE_EXECUTION_SAMPLE_LIMIT, } from '../serialization/hardened.js';
7
+ import { dehydrateStepArguments, dehydrateStepError, } from '../serialization.js';
8
8
  import * as Attribute from '../telemetry/semantic-conventions.js';
9
+ import { getAbortStreamIdFromToken } from '../util.js';
10
+ import { COMPUTE_INSTANCE_ID } from './compute-instance.js';
11
+ import { getMaxInlineSteps, isBatchTransitionsEnabled, isResilientStepDispatchEnabled, MAX_BATCH_FANOUT_EVENTS, MAX_RESILIENT_STEP_INPUT_BYTES, } from './constants.js';
12
+ import { absorbSkippedSlotReport, appendEventLog, maxEventSlot, queueMessage, slotSnapshotParams, stepDispatchIdempotencyKey, } from './helpers.js';
13
+ import { ReplayRecoveryReporter } from './replay-recovery-reporter.js';
14
+ import { unserializableStepInputPlaceholder } from './unserializable-step.js';
15
+ async function createHookEvent({ runId, hookEvent, queueItem, requestId, sinceCursor, createEvent, }) {
16
+ try {
17
+ const result = await createEvent(hookEvent, {
18
+ requestId,
19
+ ...(sinceCursor === undefined ? {} : { sinceCursor }),
20
+ });
21
+ // Check if the world returned a hook_conflict event instead of hook_created.
22
+ // The hook_conflict event is stored in the event log and is what the next
23
+ // pass consumes to settle the hook's awaiters — rejecting a payload await,
24
+ // resolving a `hook.getConflict()` with the conflicting run. An inline
25
+ // delta asked for above carries it just as it would have carried the
26
+ // hook_created, so the caller can advance over it without a re-invocation.
27
+ if (result.event?.eventType === 'hook_conflict') {
28
+ return {
29
+ hasHookConflict: true,
30
+ hasAwaitedHookCreation: false,
31
+ };
32
+ }
33
+ return {
34
+ hasHookConflict: false,
35
+ hasAwaitedHookCreation: queueItem.hasConflictAwaiter === true,
36
+ };
37
+ }
38
+ catch (err) {
39
+ if (EntityConflictError.is(err)) {
40
+ runtimeLogger.info('Hook already exists, continuing', {
41
+ workflowRunId: runId,
42
+ message: err.message,
43
+ });
44
+ return {
45
+ hasHookConflict: false,
46
+ hasAwaitedHookCreation: queueItem.hasConflictAwaiter === true,
47
+ };
48
+ }
49
+ if (RunExpiredError.is(err)) {
50
+ runtimeLogger.info('Workflow run already completed, skipping hook', {
51
+ workflowRunId: runId,
52
+ message: err.message,
53
+ });
54
+ return {
55
+ hasHookConflict: false,
56
+ hasAwaitedHookCreation: false,
57
+ };
58
+ }
59
+ if (isWorldValidationFailure(err)) {
60
+ const fatal = new FatalError(`createHook failed World validation: ${err instanceof Error ? err.message : String(err)}`);
61
+ fatal.cause = err;
62
+ throw fatal;
63
+ }
64
+ throw err;
65
+ }
66
+ }
9
67
  /**
10
68
  * Handles a workflow suspension by processing all pending operations (hooks, steps, waits).
11
- * Creates events for all operations but does NOT queue step messages returns the pending
69
+ * Creates events for all operations but does NOT queue step messages; returns the pending
12
70
  * steps so the caller can decide which to execute inline vs queue to background.
13
71
  *
14
72
  * Processing order:
15
73
  * 1. Hooks are processed first to prevent race conditions with webhook receivers
16
74
  * 2. Step events and wait events are created in parallel
17
75
  */
18
- export async function handleSuspension({ suspension, world, run, span, requestId, }) {
76
+ export async function handleSuspension({ suspension, world, run, span, requestId, eventLog, runReadyBarrier, replayRecoveryReporter, stepDispatch, ownerMessageId, allowDeferredBatchWork, }) {
19
77
  const runId = run.runId;
78
+ // Turbo mode: hold every world write below until the backgrounded
79
+ // `run_started` has *settled*, so we never write a step/hook/wait event for a
80
+ // run that does not exist yet. A no-op outside turbo (barrier undefined) and
81
+ // on the pure inline hot path, which defers all steps and writes nothing.
82
+ // Awaiting the same (usually already-settled) promise more than once is cheap.
83
+ // A barrier rejection is swallowed for ordering only: if `run_started` truly
84
+ // failed the run does not exist, so the subsequent write surfaces the real
85
+ // error (run not found / gone) and the message redelivers.
86
+ const ensureRunReady = async () => {
87
+ if (runReadyBarrier) {
88
+ try {
89
+ await runReadyBarrier;
90
+ }
91
+ catch {
92
+ // intentional: ordering barrier only, see above.
93
+ }
94
+ }
95
+ };
96
+ /**
97
+ * Await every operation in a suspension phase before letting a failure
98
+ * escape, preferring a stale-snapshot (412) rejection when one occurred.
99
+ *
100
+ * `Promise.all` rejects as soon as one operation does and leaves its siblings
101
+ * in flight. That matters for a 412: the caller reacts by reloading the event
102
+ * log and restarting the replay, so a sibling create that lands after the
103
+ * rejection escaped commits an event whose correlation id came from the
104
+ * abandoned replay's seeded sequence (an event the fresh replay never
105
+ * produces), and it races the restart's reload while doing so. Settling first
106
+ * makes this phase's write set final before the caller acts on the failure.
107
+ * It mirrors the runtime's inline step claim, which settles the in-flight
108
+ * step executions before escalating a 412.
109
+ *
110
+ * A 412 is preferred over any other rejection in the same phase because it
111
+ * has a defined, cheap recovery (replay from a corrected log) while the
112
+ * others do not. A deterministic failure such as an attribute-validation
113
+ * `FatalError` recurs on the restart and fails the run then, at the cost of
114
+ * one extra replay.
115
+ */
116
+ const settlePhase = async (ops) => {
117
+ const reasons = (await Promise.allSettled(ops))
118
+ .filter((r) => r.status === 'rejected')
119
+ .map((r) => r.reason);
120
+ if (reasons.length === 0)
121
+ return;
122
+ throw reasons.find((r) => PreconditionFailedError.is(r)) ?? reasons[0];
123
+ };
124
+ // Every suspension write carries replay-recovery telemetry on the first one
125
+ // that commits after replay recovered. All suspension events are
126
+ // non-run_created events on this run's `runId`.
127
+ const reporter = replayRecoveryReporter ?? ReplayRecoveryReporter.inert();
128
+ const createEvent = (data, params) => reporter.withEventCreate(params, (p) => world.events.create(runId, data, p));
129
+ // Adds the optimistic-concurrency guard when the caller supplied a loaded
130
+ // event log; without one it creates directly (callers with no replay
131
+ // snapshot, e.g. tests). A stale (412) rejection propagates to the caller,
132
+ // which restarts the replay from a corrected log. It is not retried here,
133
+ // because the event's correlation id was minted by *this* replay's seeded
134
+ // sequence, so re-committing it against a corrected log would persist an
135
+ // event no correct replay produces.
136
+ let reportedEvents = 0;
137
+ // Writes this suspension issued, and whether one of them handed back a
138
+ // complete inline delta that was folded into the caller's log. Together they
139
+ // answer `eventLogCarriedForward`: the delta covers the log up to the write
140
+ // that returned it, so it accounts for every event this suspension committed
141
+ // only if that write was the only one.
142
+ let guardedWrites = 0;
143
+ let deltaAbsorbed = false;
144
+ const createGuarded = async (data, params) => {
145
+ guardedWrites++;
146
+ if (!eventLog) {
147
+ return createEvent(data, params);
148
+ }
149
+ const log = eventLog;
150
+ const result = await createEvent(data, {
151
+ ...params,
152
+ ...slotSnapshotParams(log.events),
153
+ });
154
+ // An inline delta this call asked for (`sinceCursor`) is everything the
155
+ // log gained since that cursor, this write included, so it is folded onto
156
+ // the tail and carries the cursor with it — unlike a skipped-slot report,
157
+ // which is a window strictly below the write and has to be sorted back
158
+ // into place. A World returns one or the other, never both (the delta is a
159
+ // strict superset), so the two are handled apart rather than merged.
160
+ //
161
+ // Declining is always safe — an unabsorbed delta is one the next read
162
+ // returns — so the guards match the replay loop's `absorbCreateDelta`: a
163
+ // truncated page (`hasMore`) is dropped whole rather than advancing the
164
+ // cursor past events it did not carry, and the log must still be where the
165
+ // request was computed from, since appending does not re-sort.
166
+ if (typeof params?.sinceCursor === 'string') {
167
+ if (log.cursor === params.sinceCursor &&
168
+ result.events !== undefined &&
169
+ result.hasMore !== true) {
170
+ appendEventLog(log, { events: result.events, cursor: result.cursor });
171
+ deltaAbsorbed = true;
172
+ }
173
+ return result;
174
+ }
175
+ // Bump-and-report: the write landed above the slot it asked for, so the
176
+ // report holds the events it was decided without. Absorbing here rather
177
+ // than at each call site means the rest of this phase's writes (which read
178
+ // the same array to build their own snapshot) ask for a slot above them,
179
+ // and the replay that resumes from this log sees them without a reload.
180
+ const report = absorbSkippedSlotReport(log.events, result);
181
+ reportedEvents += report.added;
182
+ if (report.truncated) {
183
+ runtimeLogger.debug('Dropped a truncated skipped-slot report', {
184
+ workflowRunId: runId,
185
+ eventType: data.eventType,
186
+ eventId: result.event?.eventId,
187
+ offered: report.offered,
188
+ });
189
+ }
190
+ else if (report.added > 0) {
191
+ runtimeLogger.debug('Suspension write skipped occupied slots', {
192
+ workflowRunId: runId,
193
+ eventType: data.eventType,
194
+ eventId: result.event?.eventId,
195
+ reported: report.added,
196
+ });
197
+ }
198
+ return result;
199
+ };
20
200
  // Separate queue items by type
21
- const stepItems = suspension.steps.filter((item) => item.type === 'step');
22
- const allHookItems = suspension.steps.filter((item) => item.type === 'hook');
23
- const waitItems = suspension.steps.filter((item) => item.type === 'wait');
24
- // Split hooks by what actions they need
201
+ const stepItems = suspension.items.filter((item) => item.type === 'step');
202
+ const allHookItems = suspension.items.filter((item) => item.type === 'hook');
203
+ const waitItems = suspension.items.filter((item) => item.type === 'wait');
204
+ const attributeItems = suspension.items.filter((item) => item.type === 'attribute');
25
205
  const hooksNeedingCreation = allHookItems.filter((item) => !item.hasCreatedEvent);
26
- const hooksNeedingDisposal = allHookItems.filter((item) => item.disposed);
206
+ // Group hook items that need work by token, preserving queue-insertion
207
+ // (workflow code) order within each token. Operations on one token must
208
+ // apply in code order: a dispose() of an earlier hook releases the token
209
+ // before a later same-token hook's creation is validated (otherwise the
210
+ // new hook records a spurious hook_conflict against the run's own
211
+ // disposed hook), while a hook created and disposed within the same
212
+ // suspension is still created before it is disposed. Different tokens
213
+ // have no claim interaction, so token groups are processed in parallel.
214
+ const hookItemsByToken = new Map();
215
+ for (const item of allHookItems) {
216
+ if (item.hasCreatedEvent && !item.disposed) {
217
+ continue; // already committed and still live: nothing to do
218
+ }
219
+ const group = hookItemsByToken.get(item.token);
220
+ if (group) {
221
+ group.push(item);
222
+ }
223
+ else {
224
+ hookItemsByToken.set(item.token, [item]);
225
+ }
226
+ }
27
227
  // Resolve encryption key for this run
28
228
  const rawKey = await world.getEncryptionKeyForRun?.(run);
29
229
  const encryptionKey = rawKey ? await importKey(rawKey) : undefined;
30
- // Build and process hook_created events (same as V1)
31
- const hookEvents = await Promise.all(hooksNeedingCreation.map(async (queueItem) => {
32
- const hookMetadata = typeof queueItem.metadata === 'undefined'
33
- ? undefined
34
- : (await dehydrateStepArguments(queueItem.metadata, runId, encryptionKey, suspension.globalThis));
35
- return {
36
- eventType: 'hook_created',
230
+ // Gate payload compression on the run's specVersion.
231
+ const compression = (run.specVersion ?? 0) >= SPEC_VERSION_SUPPORTS_COMPRESSION;
232
+ let serializationBlockerCount = 0;
233
+ const serializationBlockers = [];
234
+ async function dehydrateInput(value, context) {
235
+ const stats = { executions: [] };
236
+ try {
237
+ return (await dehydrateStepArguments(value, runId, encryptionKey, suspension.globalThis, false, compression, stats));
238
+ }
239
+ finally {
240
+ serializationBlockerCount +=
241
+ stats.totalExecutions ?? stats.executions.length;
242
+ serializationBlockers.push(...stats.executions
243
+ .slice(0, GUEST_CODE_EXECUTION_SAMPLE_LIMIT - serializationBlockers.length)
244
+ .map((execution) => ({ ...context, ...execution })));
245
+ }
246
+ }
247
+ async function disposeHook(queueItem) {
248
+ const hookDisposedEvent = {
249
+ eventType: 'hook_disposed',
37
250
  specVersion: SPEC_VERSION_CURRENT,
38
251
  correlationId: queueItem.correlationId,
39
252
  eventData: {
40
253
  token: queueItem.token,
41
- metadata: hookMetadata,
42
- isWebhook: queueItem.isWebhook ?? false,
43
- ...(queueItem.isSystem && { isSystem: true }),
44
254
  },
45
255
  };
46
- }));
47
- // Process hooks first to prevent race conditions with webhook receivers.
48
- // All hook creations run in parallel.
49
- // Track any hook conflicts that occur — these are returned to the caller
50
- // so the V2 handler can re-invoke immediately.
51
- let hasHookConflict = false;
52
- if (hookEvents.length > 0) {
53
- await Promise.all(hookEvents.map(async (hookEvent) => {
54
- try {
55
- const result = await world.events.create(runId, hookEvent, {
56
- requestId,
256
+ try {
257
+ await createGuarded(hookDisposedEvent, { requestId });
258
+ }
259
+ catch (err) {
260
+ if (EntityConflictError.is(err)) {
261
+ // Hook was already disposed by a concurrent invocation, safe to skip
262
+ runtimeLogger.info('Hook already disposed, skipping duplicate disposal', {
263
+ workflowRunId: runId,
264
+ correlationId: queueItem.correlationId,
265
+ message: err.message,
57
266
  });
58
- // Check if the world returned a hook_conflict event instead of hook_created.
59
- // The hook_conflict event is stored in the event log and will be replayed
60
- // on the next workflow invocation, causing the hook's promise to reject.
61
- // Note: hook events always create an event (legacy runs throw, not return undefined)
62
- if (result.event.eventType === 'hook_conflict') {
63
- hasHookConflict = true;
64
- }
65
267
  }
66
- catch (err) {
67
- if (EntityConflictError.is(err) || RunExpiredError.is(err)) {
68
- runtimeLogger.info('Workflow run already completed, skipping hook', {
69
- workflowRunId: runId,
70
- message: err.message,
71
- });
72
- }
73
- else {
74
- throw err;
75
- }
268
+ else if (RunExpiredError.is(err)) {
269
+ runtimeLogger.info('Workflow run already completed, skipping hook disposal', {
270
+ workflowRunId: runId,
271
+ correlationId: queueItem.correlationId,
272
+ message: err.message,
273
+ });
76
274
  }
77
- }));
78
- }
79
- // Process hook disposals — these release hook tokens for reuse by other workflows.
80
- if (hooksNeedingDisposal.length > 0) {
81
- await Promise.all(hooksNeedingDisposal.map(async (queueItem) => {
82
- const hookDisposedEvent = {
83
- eventType: 'hook_disposed',
84
- specVersion: SPEC_VERSION_CURRENT,
85
- correlationId: queueItem.correlationId,
86
- };
87
- try {
88
- await world.events.create(runId, hookDisposedEvent, { requestId });
275
+ else if (HookNotFoundError.is(err)) {
276
+ // Hook may have already been disposed or never created
277
+ runtimeLogger.info('Hook not found for disposal, continuing', {
278
+ workflowRunId: runId,
279
+ correlationId: queueItem.correlationId,
280
+ message: err.message,
281
+ });
89
282
  }
90
- catch (err) {
91
- if (EntityConflictError.is(err)) {
92
- // Hook was already disposed by a concurrent invocation — safe to skip
93
- runtimeLogger.info('Hook already disposed, skipping duplicate disposal', {
94
- workflowRunId: runId,
95
- correlationId: queueItem.correlationId,
96
- message: err.message,
97
- });
98
- }
99
- else if (RunExpiredError.is(err)) {
100
- runtimeLogger.info('Workflow run already completed, skipping hook disposal', {
101
- workflowRunId: runId,
102
- correlationId: queueItem.correlationId,
103
- message: err.message,
104
- });
105
- }
106
- else if (HookNotFoundError.is(err)) {
107
- // Hook may have already been disposed or never created
108
- runtimeLogger.info('Hook not found for disposal, continuing', {
109
- workflowRunId: runId,
283
+ else {
284
+ throw err;
285
+ }
286
+ }
287
+ }
288
+ // Process hooks first to prevent race conditions with webhook receivers.
289
+ // Track any hook conflicts that occur — these are returned to the caller so
290
+ // it can advance the workflow over the committed `hook_conflict` before
291
+ // anything else this suspension scheduled runs.
292
+ const hookConflictCorrelationIds = [];
293
+ const awaitedHookCorrelationIds = [];
294
+ let hookCreationMs = 0;
295
+ // Ask the hook create for the event-log delta since the cursor the caller's
296
+ // log was read at. The hook's awaiters are settled by the event this write
297
+ // commits and by nothing else — a `hook_created` for a clean registration,
298
+ // a `hook_conflict` when the token was already claimed — so the caller can
299
+ // continue the workflow in its own process on either outcome, but only over
300
+ // a log that holds that event, and this write is the one request that can
301
+ // hand it back together with anything another writer landed in the meantime.
302
+ // Optional by contract: a World that ignores `sinceCursor` returns no delta
303
+ // and the caller reads instead.
304
+ //
305
+ // Asked for on the single-hook suspension only. Two creates issued from one
306
+ // snapshot each diff against the same cursor, and only the first delta back
307
+ // can be folded in (the cursor moves with it), so the log would end up short
308
+ // of the other's event with nothing to say so.
309
+ const hookDeltaCursor = hooksNeedingCreation.length === 1 && typeof eventLog?.cursor === 'string'
310
+ ? eventLog.cursor
311
+ : undefined;
312
+ if (hookItemsByToken.size > 0) {
313
+ const hookPhaseStart = Date.now();
314
+ await ensureRunReady();
315
+ await settlePhase([...hookItemsByToken.values()].map(async (items) => {
316
+ for (const queueItem of items) {
317
+ let creationConflicted = false;
318
+ if (!queueItem.hasCreatedEvent) {
319
+ const hookMetadata = typeof queueItem.metadata === 'undefined'
320
+ ? undefined
321
+ : await dehydrateInput(queueItem.metadata, {
322
+ source: 'hook_metadata',
323
+ correlationId: queueItem.correlationId,
324
+ });
325
+ const hookEvent = {
326
+ eventType: 'hook_created',
327
+ specVersion: SPEC_VERSION_CURRENT,
110
328
  correlationId: queueItem.correlationId,
111
- message: err.message,
329
+ eventData: {
330
+ token: queueItem.token,
331
+ tokenRetentionUntil: queueItem.tokenRetentionUntil,
332
+ metadata: hookMetadata,
333
+ isWebhook: queueItem.isWebhook ?? false,
334
+ ...(queueItem.isSystem && { isSystem: true }),
335
+ },
336
+ };
337
+ const result = await createHookEvent({
338
+ runId,
339
+ hookEvent,
340
+ queueItem,
341
+ requestId,
342
+ sinceCursor: hookDeltaCursor,
343
+ createEvent: createGuarded,
112
344
  });
345
+ if (result.hasHookConflict) {
346
+ hookConflictCorrelationIds.push(queueItem.correlationId);
347
+ }
348
+ if (result.hasAwaitedHookCreation) {
349
+ awaitedHookCorrelationIds.push(queueItem.correlationId);
350
+ }
351
+ creationConflicted = result.hasHookConflict;
113
352
  }
114
- else {
115
- throw err;
353
+ // Dispose after creation for hooks born and disposed within this
354
+ // batch. A hook whose creation conflicted was never created, so
355
+ // there is nothing to dispose.
356
+ if (queueItem.disposed && !creationConflicted) {
357
+ await disposeHook(queueItem);
116
358
  }
117
359
  }
118
360
  }));
361
+ hookCreationMs = Date.now() - hookPhaseStart;
119
362
  }
120
- // Process abort requests resume the hook with abort payload and write stream packet
363
+ // Process abort requests: resume the hook with abort payload and write stream packet
121
364
  const hooksNeedingAbort = allHookItems.filter((item) => item.abortRequested && !item.disposed);
122
365
  if (hooksNeedingAbort.length > 0) {
123
- await Promise.all(hooksNeedingAbort.map(async (queueItem) => {
366
+ await ensureRunReady();
367
+ await settlePhase(hooksNeedingAbort.map(async (queueItem) => {
124
368
  try {
125
369
  // Dehydrate the abort payload for storage
126
- const abortPayload = await dehydrateStepArguments({ aborted: true, reason: queueItem.abortReason }, runId, encryptionKey, suspension.globalThis);
370
+ const abortPayload = await dehydrateInput({
371
+ aborted: true,
372
+ reason: queueItem.abortReason,
373
+ }, {
374
+ source: 'hook_abort',
375
+ correlationId: queueItem.correlationId,
376
+ });
127
377
  // Create hook_received event with abort payload
128
- await world.events.create(runId, {
378
+ await createGuarded({
129
379
  eventType: 'hook_received',
130
380
  specVersion: SPEC_VERSION_CURRENT,
131
381
  correlationId: queueItem.correlationId,
132
382
  eventData: {
383
+ token: queueItem.token,
133
384
  payload: abortPayload,
134
385
  },
135
386
  });
@@ -146,7 +397,7 @@ export async function handleSuspension({ suspension, world, run, span, requestId
146
397
  await world.streams.close(runId, streamName);
147
398
  }
148
399
  catch {
149
- // Best-effort stream write hook event provides the durable fallback
400
+ // Best-effort stream write: hook event provides the durable fallback
150
401
  runtimeLogger.debug('Failed to write abort stream packet, hook event will provide fallback', {
151
402
  workflowRunId: runId,
152
403
  correlationId: queueItem.correlationId,
@@ -168,7 +419,7 @@ export async function handleSuspension({ suspension, world, run, span, requestId
168
419
  }));
169
420
  }
170
421
  // Create step events for steps that don't have them yet.
171
- // Unlike V1, we do NOT queue step messages from here the caller
422
+ // Unlike V1, we do NOT queue step messages from here: the caller
172
423
  // decides which steps to execute inline vs. queue to background.
173
424
  // Wait events are also created in parallel below.
174
425
  const stepsNeedingCreation = new Set(stepItems
@@ -176,30 +427,420 @@ export async function handleSuspension({ suspension, world, run, span, requestId
176
427
  .map((queueItem) => queueItem.correlationId));
177
428
  // Correlation IDs for which THIS suspension call actually wrote the
178
429
  // step_created event. Populated by the ops below after a successful
179
- // events.create used by the caller to claim ownership and avoid
430
+ // events.create, used by the caller to claim ownership and avoid
180
431
  // racing with concurrent handlers on step execution.
181
432
  const createdStepCorrelationIds = new Set();
433
+ // Correlation IDs of steps finalized as failed because their arguments
434
+ // refused to serialize: see finalizeUnserializableStep below.
435
+ const failedStepCorrelationIds = new Set();
436
+ /**
437
+ * A step whose arguments fail to serialize is deterministic: every replay
438
+ * re-derives the same unserializable value, so redelivering the
439
+ * orchestrator message can never succeed. Instead of rejecting the whole
440
+ * suspension (which fails the run from the outside, where no user code can
441
+ * observe it), treat it exactly like a step-body failure: write
442
+ * `step_created` with a placeholder input (every World requires the step
443
+ * entity to exist before a terminal step event, and the real input is
444
+ * precisely what refused to serialize) followed by `step_failed` carrying
445
+ * the SerializationError. The next replay rejects the step's promise with
446
+ * it, so a try/catch around the step call observes the error; uncaught, it
447
+ * propagates out of the workflow body and fails the run as a USER_ERROR,
448
+ * without burning queue redeliveries either way.
449
+ */
450
+ const finalizeUnserializableStep = async (queueItem, error) => {
451
+ runtimeLogger.warn('Step arguments failed to serialize; failing the step so the ' +
452
+ 'workflow can observe the error', {
453
+ workflowRunId: runId,
454
+ correlationId: queueItem.correlationId,
455
+ stepName: queueItem.stepName,
456
+ error: error.message,
457
+ });
458
+ await ensureRunReady();
459
+ // Marker placeholder (not empty args): byte-identical-to-zero-args would
460
+ // make `workflow inspect steps` show "no arguments" for the one step
461
+ // whose entire problem was its arguments.
462
+ const placeholderInput = (await dehydrateStepArguments(unserializableStepInputPlaceholder(), runId, encryptionKey, suspension.globalThis, false, compression));
463
+ try {
464
+ await createGuarded({
465
+ eventType: 'step_created',
466
+ specVersion: SPEC_VERSION_CURRENT,
467
+ correlationId: queueItem.correlationId,
468
+ eventData: {
469
+ stepName: queueItem.stepName,
470
+ workflowName: run.workflowName,
471
+ input: placeholderInput,
472
+ },
473
+ }, { requestId });
474
+ }
475
+ catch (createErr) {
476
+ if (EntityConflictError.is(createErr)) {
477
+ // A concurrent handler already created the step: the failure is
478
+ // deterministic, so it is racing toward the same step_failed below.
479
+ runtimeLogger.info('Step already exists, continuing', {
480
+ workflowRunId: runId,
481
+ correlationId: queueItem.correlationId,
482
+ message: createErr.message,
483
+ });
484
+ }
485
+ else if (RunExpiredError.is(createErr)) {
486
+ // Run already finished: nothing to observe the failure.
487
+ return;
488
+ }
489
+ else {
490
+ throw createErr;
491
+ }
492
+ }
493
+ try {
494
+ await createGuarded({
495
+ eventType: 'step_failed',
496
+ specVersion: SPEC_VERSION_CURRENT,
497
+ correlationId: queueItem.correlationId,
498
+ eventData: {
499
+ stepName: queueItem.stepName,
500
+ // The error itself is a plain WorkflowError (name, message with
501
+ // framed hint, cause chain), serializable even though the step
502
+ // input was not. Error detection is realm-independent
503
+ // (types.isNativeError), so the host-created error serializes
504
+ // the same under either global; the VM global is passed for
505
+ // consistency with every other dehydration in this file and so
506
+ // any VM-realm values guest code threw into the cause chain
507
+ // (getters/proxies executed during the failed dehydration) are
508
+ // detected by the realm-sensitive reducers.
509
+ error: await dehydrateStepError(error, runId, encryptionKey, [], suspension.globalThis, compression),
510
+ },
511
+ }, { requestId });
512
+ }
513
+ catch (failErr) {
514
+ if (EntityConflictError.is(failErr) || RunExpiredError.is(failErr)) {
515
+ // Step already terminal (a concurrent handler wrote the same
516
+ // deterministic failure) or the run already finished.
517
+ runtimeLogger.info('Tried failing step, but step or run has already finished.', {
518
+ workflowRunId: runId,
519
+ correlationId: queueItem.correlationId,
520
+ message: failErr.message,
521
+ });
522
+ }
523
+ else {
524
+ throw failErr;
525
+ }
526
+ }
527
+ failedStepCorrelationIds.add(queueItem.correlationId);
528
+ // Release the inline slot bookkeeping: the step never runs, so it must
529
+ // not appear in the rebuilt `lazyInlineSteps`. (Its slot in the first-N
530
+ // selection and in `inlinePairFoldEligible`'s arithmetic was consumed
531
+ // before dehydration could reveal the failure, inherent to selecting
532
+ // before serializing, and bounded to one wasted slot on a pass that
533
+ // ends in a forced replay anyway.)
534
+ lazyInlineCorrelationIds.delete(queueItem.correlationId);
535
+ };
536
+ // Lazy inline start: defer the step_created write for up to
537
+ // `getMaxInlineSteps()` steps the caller will run inline (in parallel). Each
538
+ // step is created on the fly by the lazy `step_started` executeStep sends
539
+ // (saving a round-trip per step). We never defer when a `hook.getConflict()`
540
+ // awaiter is present, because in that case the caller executes nothing inline
541
+ // (it continues the workflow to resolve the awaiter instead), so deferring
542
+ // would leave the steps uncreated and unqueued. We pick the first N uncreated
543
+ // steps — matching the caller's inline-candidate selection — and dehydrate
544
+ // their input here so executeStep can ship it as the step_started payload.
545
+ const lazyInlineCorrelationIds = new Set(awaitedHookCorrelationIds.length === 0
546
+ ? stepItems
547
+ .filter((item) => stepsNeedingCreation.has(item.correlationId))
548
+ .slice(0, getMaxInlineSteps())
549
+ .map((item) => item.correlationId)
550
+ : []);
551
+ // Collected by correlationId because the per-step ops below run concurrently
552
+ // and settle out of order. We rebuild the array in deterministic
553
+ // `lazyInlineCorrelationIds` order (the ordered slice above) after the ops
554
+ // settle, so the inline batch order is stable regardless of dehydration timing.
555
+ const lazyInlineByCorrelationId = new Map();
182
556
  const ops = [];
183
- // Steps: create step_created events (no queuing V2 returns pending steps to caller)
557
+ // Correlation IDs of steps whose step-execution queue message was already
558
+ // published by the resilient-dispatch ops below (alongside the step_created
559
+ // write). Reported to the caller so its dispatch pass skips them.
560
+ const queuedStepCorrelationIds = new Set();
561
+ // Resilient step dispatch eligibility, shared by every step op below (the
562
+ // per-step input-size check is applied inside the op). All must hold:
563
+ //
564
+ // - The caller provided a dispatch target (`stepDispatch`): terminal
565
+ // drains and other create-only callers never queue.
566
+ // - The feature is enabled (`WORKFLOW_RESILIENT_STEP_DISPATCH` opt-in).
567
+ // It is off by default because the publish races the create's verdict,
568
+ // and a create can come back refused: as a duplicate the replay should
569
+ // stop pursuing, or (on a World that would rather refuse a stale write
570
+ // than report what it missed) as a 412. Either way the queue message
571
+ // carrying the payload is already out, and the consumer can materialize a
572
+ // step whose create was refused. Nothing orders that verdict before the
573
+ // consumer's redelivery re-ensure, so no backend-side revocation
574
+ // bookkeeping can close the window: a best-effort marker that fails open
575
+ // cannot carry a correctness property. The sequential path is the only
576
+ // thing that gives the message a happens-after edge over the verdict.
577
+ // - The run's queue transport preserves binary payloads (CBOR,
578
+ // specVersion >= 3): `stepInput.input` is the serialized (possibly
579
+ // encrypted) input bytes, which the JSON transport would mangle.
580
+ const resilientDispatchEligible = stepDispatch !== undefined &&
581
+ isResilientStepDispatchEnabled() &&
582
+ (run.specVersion ?? 0) >= SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT;
583
+ // Batched fan-out: fold this suspension's step_created + wait_created
584
+ // writes into one `events.createBatch` call (one durable write, per-event
585
+ // outcomes) instead of one write per event. Engages only for a CLEAN
586
+ // fan-out (no attribute writes, no hook writes, no resilient dispatch
587
+ // whose creates are each paired with a queue publish) on a World that
588
+ // implements the optional method and a run whose events are slot-numbered.
589
+ // Everything outside the gate keeps the single-event path byte-for-byte.
590
+ const batchFanoutEligible = isBatchTransitionsEnabled() &&
591
+ typeof world.events.createBatch === 'function' &&
592
+ (run.specVersion ?? 0) >= SPEC_VERSION_SUPPORTS_SLOT_IDENTITY &&
593
+ !resilientDispatchEligible &&
594
+ allHookItems.length === 0 &&
595
+ attributeItems.length === 0;
596
+ /**
597
+ * The fold's collection, in scheduling order (steps in stepItems order,
598
+ * then waits). Step entries are enqueued by their prep promises (input
599
+ * dehydration runs concurrently, so entries are ordered by `order`, not by
600
+ * completion); the single flush op below awaits every prep, sorts, and
601
+ * commits the whole set through `createBatch`.
602
+ */
603
+ const batchQueue = [];
604
+ const batchPreps = [];
605
+ // Pre-claimed inline pairs: fold each lazy-inline step's deferred
606
+ // `step_created` (carrying its input) AND its `step_started` claim (bare,
607
+ // ownership-stamped) into the batch, so the whole fan-out (the inline
608
+ // steps' claims included) commits in the one durable write and the caller
609
+ // starts the bodies straight off that commit instead of posting one claim
610
+ // per inline step. The lone-inline case (nothing else to batch with) is
611
+ // excluded: a pair-only batch costs the same round trip as the single lazy
612
+ // claim while giving up the optimistic claim/body overlap and the
613
+ // bump-and-report that `createGuarded` provides, so it stays on the lazy
614
+ // path. Requires the caller's `ownerMessageId`: the started row must
615
+ // stamp ownership exactly like the lazy claim it replaces (and a caller
616
+ // that does not inline-execute never provides one).
617
+ const uncreatedWaitCount = waitItems.filter((item) => !item.hasCreatedEvent).length;
618
+ const inlinePairFoldEligible = batchFanoutEligible &&
619
+ ownerMessageId !== undefined &&
620
+ lazyInlineCorrelationIds.size > 0 &&
621
+ (lazyInlineCorrelationIds.size >= 2 ||
622
+ stepsNeedingCreation.size -
623
+ lazyInlineCorrelationIds.size +
624
+ uncreatedWaitCount >=
625
+ 1);
626
+ const inlineClaims = new Map();
627
+ let batchCommittedSlotCeiling;
628
+ // The trace carrier for resilient step dispatches, resolved at most once per
629
+ // suspension (the per-step ops run concurrently and share it).
630
+ let stepDispatchTraceCarrier;
631
+ const getStepDispatchTraceCarrier = () => {
632
+ stepDispatchTraceCarrier ??=
633
+ stepDispatch?.getTraceCarrier() ?? Promise.resolve({});
634
+ return stepDispatchTraceCarrier;
635
+ };
636
+ // Producer-side resilient recovery count for the suspension span attribute.
637
+ let resilientDispatchRecovered = 0;
638
+ // Steps: create step_created events (no queuing, V2 returns pending steps
639
+ // to caller, EXCEPT on the resilient dispatch path, which parallelizes the
640
+ // create with the step's queue publish and reports it in
641
+ // `queuedStepCorrelationIds`).
642
+ let batchOrderCounter = 0;
184
643
  for (const queueItem of stepItems) {
185
644
  if (stepsNeedingCreation.has(queueItem.correlationId)) {
186
- ops.push((async () => {
187
- const dehydratedInput = await dehydrateStepArguments({
188
- args: queueItem.args,
189
- closureVars: queueItem.closureVars,
190
- thisVal: queueItem.thisVal,
191
- }, runId, encryptionKey, suspension.globalThis);
645
+ // Deterministic position in the batched fold (assigned in stepItems
646
+ // order, before the concurrent dehydration runs). A pair-folded inline
647
+ // step occupies two consecutive positions (created row then started
648
+ // row), which the flush keeps adjacent and never splits across chunks,
649
+ // so a World can fold them into one born-running create.
650
+ const pairFolded = inlinePairFoldEligible &&
651
+ lazyInlineCorrelationIds.has(queueItem.correlationId);
652
+ const stepOrder = batchOrderCounter;
653
+ batchOrderCounter += pairFolded ? 2 : 1;
654
+ const stepOp = (async () => {
655
+ let dehydratedInput;
656
+ try {
657
+ dehydratedInput = await dehydrateInput({
658
+ args: queueItem.args,
659
+ closureVars: queueItem.closureVars,
660
+ thisVal: queueItem.thisVal,
661
+ }, {
662
+ source: 'step_input',
663
+ correlationId: queueItem.correlationId,
664
+ });
665
+ }
666
+ catch (err) {
667
+ if (!SerializationError.is(err)) {
668
+ // e.g. RuntimeDecryptionError: an SDK fault, not a user value
669
+ // problem. Keep its identity (RUNTIME_ERROR) and current
670
+ // fail-the-suspension behavior.
671
+ throw err;
672
+ }
673
+ if (!stepDispatch) {
674
+ // No dispatch target means no replay will observe a
675
+ // finalization: this is the terminal drain (or a create-only
676
+ // test caller). The run is already completing/failing, so
677
+ // writing step_created + step_failed here would leave e.g. a
678
+ // COMPLETED run carrying a failed step nothing can ever
679
+ // observe, reading as a bug from the dashboard. Rethrow
680
+ // instead; the drain's own catch swallows it, preserving its
681
+ // pre-existing behavior (no rows for the unawaited step).
682
+ throw err;
683
+ }
684
+ await finalizeUnserializableStep(queueItem, err);
685
+ return;
686
+ }
687
+ // Deferred (lazy) inline step: skip the step_created write — the
688
+ // caller's inline executeStep will send a lazy step_started carrying
689
+ // this input, and the world creates the step (entity + synthetic
690
+ // step_created event) atomically. We do NOT add it to
691
+ // createdStepCorrelationIds; ownership is decided by that lazy
692
+ // step_started's atomic create-claim instead.
693
+ if (lazyInlineCorrelationIds.has(queueItem.correlationId)) {
694
+ lazyInlineByCorrelationId.set(queueItem.correlationId, {
695
+ correlationId: queueItem.correlationId,
696
+ stepName: queueItem.stepName,
697
+ dehydratedInput,
698
+ });
699
+ if (pairFolded) {
700
+ // Enqueue the pair the deferral would otherwise leave to the
701
+ // caller's lazy `step_started`: the created row carries the
702
+ // input (payloads ride creates in a batch), the started row is
703
+ // bare and stamps this invocation's ownership, the same claim
704
+ // shape the lazy start would have sent, settled by the batch.
705
+ batchQueue.push({
706
+ order: stepOrder,
707
+ kind: 'inline-created',
708
+ correlationId: queueItem.correlationId,
709
+ event: {
710
+ eventType: 'step_created',
711
+ specVersion: SPEC_VERSION_CURRENT,
712
+ correlationId: queueItem.correlationId,
713
+ eventData: {
714
+ stepName: queueItem.stepName,
715
+ workflowName: run.workflowName,
716
+ input: dehydratedInput,
717
+ },
718
+ },
719
+ });
720
+ batchQueue.push({
721
+ order: stepOrder + 1,
722
+ kind: 'inline-started',
723
+ correlationId: queueItem.correlationId,
724
+ event: {
725
+ eventType: 'step_started',
726
+ specVersion: SPEC_VERSION_CURRENT,
727
+ correlationId: queueItem.correlationId,
728
+ eventData: {
729
+ stepName: queueItem.stepName,
730
+ // Checked by inlinePairFoldEligible; spread keeps the
731
+ // narrow-through-closure problem away from the type.
732
+ ...(ownerMessageId !== undefined ? { ownerMessageId } : {}),
733
+ },
734
+ },
735
+ });
736
+ }
737
+ return;
738
+ }
192
739
  const stepEvent = {
193
740
  eventType: 'step_created',
194
741
  specVersion: SPEC_VERSION_CURRENT,
195
742
  correlationId: queueItem.correlationId,
196
743
  eventData: {
197
744
  stepName: queueItem.stepName,
745
+ workflowName: run.workflowName,
198
746
  input: dehydratedInput,
199
747
  },
200
748
  };
749
+ // Resilient step dispatch: fire the step_created write and the
750
+ // step-execution queue publish in parallel: the message carries the
751
+ // same serialized input (`stepInput`) so the consumer can
752
+ // idempotently re-ensure the event if the direct write failed
753
+ // transiently. Mirrors the resilient start (`runInput`) and
754
+ // resilient hook resume (`hookInput`) patterns. Only for inputs the
755
+ // queue message can safely carry (binary, under the VQS size cap).
756
+ if (resilientDispatchEligible &&
757
+ dehydratedInput instanceof Uint8Array &&
758
+ dehydratedInput.byteLength <= MAX_RESILIENT_STEP_INPUT_BYTES) {
759
+ await ensureRunReady();
760
+ const traceCarrier = await getStepDispatchTraceCarrier();
761
+ const [createResult, queueResult] = await Promise.allSettled([
762
+ createGuarded(stepEvent, { requestId }),
763
+ queueMessage(world,
764
+ // biome-ignore lint/style/noNonNullAssertion: implied by resilientDispatchEligible
765
+ stepDispatch.queueName, {
766
+ runId,
767
+ stepId: queueItem.correlationId,
768
+ stepName: queueItem.stepName,
769
+ traceCarrier,
770
+ requestedAt: new Date(),
771
+ stepInput: { input: dehydratedInput },
772
+ },
773
+ // Same key as the caller's dispatch pass and any concurrent
774
+ // handler's, so redundant publishes for this step dedupe. The
775
+ // key is step-identity-scoped so a revoked message for a
776
+ // reassigned correlation id cannot absorb the corrected
777
+ // schedule's dispatch: see stepDispatchIdempotencyKey.
778
+ {
779
+ idempotencyKey: stepDispatchIdempotencyKey(queueItem.correlationId, queueItem.stepName),
780
+ }),
781
+ ]);
782
+ // Queue failure is always fatal for this suspension pass: without
783
+ // the message the step would rely on the create alone, and if the
784
+ // create ALSO failed there would be no durable record at all.
785
+ // Propagating redelivers the orchestrator message, which
786
+ // re-creates the (idempotent) step_created and re-dispatches,
787
+ // the same recovery as the sequential path.
788
+ if (queueResult.status === 'rejected') {
789
+ throw queueResult.reason;
790
+ }
791
+ queuedStepCorrelationIds.add(queueItem.correlationId);
792
+ if (createResult.status === 'rejected') {
793
+ const err = createResult.reason;
794
+ if (EntityConflictError.is(err)) {
795
+ // Concurrent handler wrote it first, same as the sequential
796
+ // path. The step message is already out; a duplicate publish
797
+ // by that handler dedupes on the shared idempotency key.
798
+ runtimeLogger.info('Step already exists, continuing', {
799
+ workflowRunId: runId,
800
+ correlationId: queueItem.correlationId,
801
+ message: err.message,
802
+ });
803
+ }
804
+ else if (isRetryableWorldError(err)) {
805
+ // Resilient: the write failed transiently (429 / 5xx /
806
+ // transport) but the step message (carrying the same
807
+ // serialized input) was published, so the consumer
808
+ // idempotently re-ensures the step_created before executing.
809
+ resilientDispatchRecovered++;
810
+ runtimeLogger.warn('Step creation event write failed, but the step was ' +
811
+ 'dispatched via the queue. The step_created event will ' +
812
+ 'be ensured by the queue consumer.', {
813
+ workflowRunId: runId,
814
+ correlationId: queueItem.correlationId,
815
+ stepName: queueItem.stepName,
816
+ error: err instanceof Error ? err.message : String(err),
817
+ });
818
+ }
819
+ else {
820
+ throw err;
821
+ }
822
+ }
823
+ else {
824
+ createdStepCorrelationIds.add(queueItem.correlationId);
825
+ }
826
+ return;
827
+ }
828
+ if (batchFanoutEligible) {
829
+ // Fold into the batch instead of writing here. The enclosing
830
+ // promise joins `batchPreps` (see the loop below), so the flush
831
+ // op cannot run before this step's input finished dehydrating.
832
+ batchQueue.push({
833
+ order: stepOrder,
834
+ kind: 'step',
835
+ correlationId: queueItem.correlationId,
836
+ stepName: queueItem.stepName,
837
+ event: stepEvent,
838
+ });
839
+ return;
840
+ }
201
841
  try {
202
- await world.events.create(runId, stepEvent, { requestId });
842
+ await ensureRunReady();
843
+ await createGuarded(stepEvent, { requestId });
203
844
  createdStepCorrelationIds.add(queueItem.correlationId);
204
845
  }
205
846
  catch (err) {
@@ -214,23 +855,44 @@ export async function handleSuspension({ suspension, world, run, span, requestId
214
855
  throw err;
215
856
  }
216
857
  }
217
- })());
858
+ })();
859
+ ops.push(stepOp);
860
+ if (batchFanoutEligible) {
861
+ // The flush op waits for every prep before committing; a prep that
862
+ // rejected already surfaces through `ops`, so the flush's own wait
863
+ // swallows it and commits whatever was successfully enqueued,
864
+ // preserving today's per-op independence.
865
+ batchPreps.push(stepOp.catch(() => { }));
866
+ }
218
867
  }
219
868
  }
220
869
  // Create wait events (same as V1)
221
870
  for (const queueItem of waitItems) {
222
871
  if (!queueItem.hasCreatedEvent) {
223
- ops.push((async () => {
224
- const waitEvent = {
225
- eventType: 'wait_created',
226
- specVersion: SPEC_VERSION_CURRENT,
872
+ const waitEvent = {
873
+ eventType: 'wait_created',
874
+ specVersion: SPEC_VERSION_CURRENT,
875
+ correlationId: queueItem.correlationId,
876
+ eventData: {
877
+ resumeAt: queueItem.resumeAt,
878
+ },
879
+ };
880
+ if (batchFanoutEligible) {
881
+ // Waits need no dehydration, so they enqueue synchronously, after
882
+ // every step's order slot, preserving steps-then-waits scheduling
883
+ // order in the log.
884
+ batchQueue.push({
885
+ order: batchOrderCounter++,
886
+ kind: 'wait',
227
887
  correlationId: queueItem.correlationId,
228
- eventData: {
229
- resumeAt: queueItem.resumeAt,
230
- },
231
- };
888
+ event: waitEvent,
889
+ });
890
+ continue;
891
+ }
892
+ ops.push((async () => {
232
893
  try {
233
- await world.events.create(runId, waitEvent, { requestId });
894
+ await ensureRunReady();
895
+ await createGuarded(waitEvent, { requestId });
234
896
  }
235
897
  catch (err) {
236
898
  if (EntityConflictError.is(err)) {
@@ -247,33 +909,499 @@ export async function handleSuspension({ suspension, world, run, span, requestId
247
909
  })());
248
910
  }
249
911
  }
250
- waitUntil(Promise.all(ops).catch((opErr) => {
251
- const isAbortError = opErr?.name === 'AbortError' || opErr?.name === 'ResponseAborted';
252
- if (!isAbortError)
253
- throw opErr;
254
- }));
255
- await Promise.all(ops);
256
- // Calculate minimum timeout from waits
912
+ // The batched fold's flush: the clean fan-out commits through
913
+ // `createBatch` in chunks of MAX_BATCH_FANOUT_EVENTS, all chunks IN
914
+ // FLIGHT CONCURRENTLY. Slot assignment is the server's, so parallel
915
+ // chunks race for slot ranges exactly like the pre-fold path's parallel
916
+ // single writes did; entity conditions, not commit order, carry
917
+ // correctness (sibling fan-out events have no cross-order the replay
918
+ // depends on; it matches by correlation id). Each event reports the
919
+ // outcome its own single create would have had: a 409 is the same
920
+ // already-exists tolerance as the single path, anything else fails the
921
+ // delivery the way a single-path rejection would.
922
+ //
923
+ // Latency shape: only the chunk carrying the pre-claimed inline pairs
924
+ // gates the handler's return (the caller starts bodies off its claims).
925
+ // Every other chunk's commit (and every chunk's step-message publishes,
926
+ // which fire the moment ITS creates are durable) rides
927
+ // `deferredBatchWork` when the caller opted in, joined before ack. A slow
928
+ // sibling chunk therefore delays neither the inline bodies nor another
929
+ // chunk's queue messages, while publish-after-create still holds per
930
+ // step: a step's message is only ever sent after the chunk carrying its
931
+ // create has committed.
932
+ let deferredBatchWork;
933
+ if (batchFanoutEligible) {
934
+ ops.push((async () => {
935
+ // Preps that rejected already surface through their own `ops`
936
+ // entries; the fold commits whatever was successfully enqueued,
937
+ // preserving today's per-op independence.
938
+ await Promise.all(batchPreps);
939
+ if (batchQueue.length === 0) {
940
+ return;
941
+ }
942
+ const entries = [...batchQueue].sort((a, b) => a.order - b.order);
943
+ await ensureRunReady();
944
+ // A batch of ONE gains nothing over the single write (same round
945
+ // trip) and loses the slot-snapshot params + bump-and-report that
946
+ // createGuarded provides, so a lone eager event takes the ordinary
947
+ // single path, with the same conflict tolerance and ownership
948
+ // bookkeeping it would have had without the fold.
949
+ if (entries.length === 1) {
950
+ const [entry] = entries;
951
+ try {
952
+ await createGuarded(entry.event, { requestId });
953
+ if (entry.kind === 'step') {
954
+ createdStepCorrelationIds.add(entry.correlationId);
955
+ }
956
+ }
957
+ catch (err) {
958
+ if (EntityConflictError.is(err)) {
959
+ runtimeLogger.info(entry.kind === 'step'
960
+ ? 'Step already exists, continuing'
961
+ : 'Wait already exists, continuing', {
962
+ workflowRunId: runId,
963
+ correlationId: entry.correlationId,
964
+ message: err.message,
965
+ });
966
+ }
967
+ else {
968
+ throw err;
969
+ }
970
+ }
971
+ return;
972
+ }
973
+ // Seed for the foreign-interleaving diagnostic below. With chunks
974
+ // committing in parallel there is no per-chunk "expected next slot";
975
+ // the whole fold's committed span is compared against the seed
976
+ // once every chunk has settled: committed slots are dense per the
977
+ // World's invariant, so any excess of (max committed slot − seed +
978
+ // 1) over the fold's own committed count is events OTHER writers
979
+ // landed in between.
980
+ const expectedFirstSlot = eventLog
981
+ ? (maxEventSlot(eventLog.events) ?? 0) + 1
982
+ : undefined;
983
+ // Pair-aware chunking: a pre-claimed pair's two rows must land in
984
+ // the same createBatch call (adjacent, so a World can fold them
985
+ // into one born-running create) and never straddle a chunk
986
+ // boundary, which would turn the started row into a standalone
987
+ // claim racing its own create's commit.
988
+ const chunks = [];
989
+ {
990
+ let current = [];
991
+ for (let index = 0; index < entries.length; index++) {
992
+ const entry = entries[index];
993
+ const next = entries[index + 1];
994
+ const pairLead = entry.kind === 'inline-created' &&
995
+ next?.kind === 'inline-started' &&
996
+ next.correlationId === entry.correlationId;
997
+ const take = pairLead ? 2 : 1;
998
+ if (current.length > 0 &&
999
+ current.length + take > MAX_BATCH_FANOUT_EVENTS) {
1000
+ chunks.push(current);
1001
+ current = [];
1002
+ }
1003
+ current.push(entry);
1004
+ if (pairLead) {
1005
+ current.push(next);
1006
+ index++;
1007
+ }
1008
+ }
1009
+ if (current.length > 0)
1010
+ chunks.push(current);
1011
+ }
1012
+ // Steps whose queue messages THIS FLUSH will publish (the eager
1013
+ // creates), recorded before any chunk settles so the caller's
1014
+ // dispatch pass (which runs off the handler's return) skips them.
1015
+ // The sends are guaranteed-or-failed by the trailing work the
1016
+ // caller joins before acking, so "will be published by this flush"
1017
+ // and "already published" are equivalent from the caller's side.
1018
+ const publishEagerSteps = stepDispatch !== undefined;
1019
+ if (publishEagerSteps) {
1020
+ for (const entry of entries) {
1021
+ if (entry.kind === 'step') {
1022
+ queuedStepCorrelationIds.add(entry.correlationId);
1023
+ }
1024
+ }
1025
+ }
1026
+ // Tallies for the foreign-interleaving diagnostic, folded across
1027
+ // the concurrent chunks and read once all of them settled.
1028
+ let committedCount = 0;
1029
+ let maxCommittedSlot;
1030
+ const commitChunk = async (chunk) => {
1031
+ // Anchors for the pre-claimed steps' telemetry: the POST instant
1032
+ // is the claim's "start POST sent" (RSFS's end), the return is the
1033
+ // claim's completion (TTR's T6), the same two instants the lazy
1034
+ // claim's own POST would have produced.
1035
+ const batchPostSentAtMs = Date.now();
1036
+ // biome-ignore lint/style/noNonNullAssertion: batchFanoutEligible implies presence
1037
+ const { results } = await world.events.createBatch(runId, chunk.map((entry) => ({
1038
+ event: entry.event,
1039
+ // The started row is the step's executing claim, so it carries
1040
+ // the compute-instance attribution the single claim sends via
1041
+ // CreateEventParams.
1042
+ ...(entry.kind === 'inline-started'
1043
+ ? { computeInstanceId: COMPUTE_INSTANCE_ID }
1044
+ : {}),
1045
+ })),
1046
+ // Per-write request attribution, same as the single path's
1047
+ // createGuarded(…, { requestId }).
1048
+ { requestId });
1049
+ const claimCompletedAtMs = Date.now();
1050
+ for (const [index, item] of results.entries()) {
1051
+ const entry = chunk[index];
1052
+ if (item.error === undefined) {
1053
+ if (entry.kind === 'step') {
1054
+ createdStepCorrelationIds.add(entry.correlationId);
1055
+ }
1056
+ else if (entry.kind === 'inline-started') {
1057
+ // The pair committed: this invocation owns the step and the
1058
+ // caller runs the body with no claim of its own. The
1059
+ // readback entity is authoritative where present; a World
1060
+ // that omitted it gets the same locally synthesized running
1061
+ // attempt-1 the optimistic path executes against. Either
1062
+ // way the input is re-attached locally: batch responses
1063
+ // return refs lazily, and the body's hydration wants the
1064
+ // exact bytes the pair's created row carried. (The created
1065
+ // row's success is deliberately NOT membership in
1066
+ // createdStepCorrelationIds: for inline steps ownership is
1067
+ // the started row's verdict, and the caller's dispatch pass
1068
+ // skips inline correlation ids regardless.)
1069
+ const dehydrated = lazyInlineByCorrelationId.get(entry.correlationId);
1070
+ if (dehydrated === undefined) {
1071
+ // Unreachable: the same prep op that enqueued the pair set
1072
+ // this entry, and the flush awaited every prep above.
1073
+ //
1074
+ // Not free if it ever fires, though: the pair is already
1075
+ // durable here, so this throws with the step claimed and
1076
+ // its body never run. The delivery fails, and redelivery
1077
+ // recovers it through owned-recovery (the step carries this
1078
+ // message's ownership stamp) rather than the request just
1079
+ // failing cleanly.
1080
+ throw new WorkflowWorldError(`no dehydrated input for pre-claimed step ${entry.correlationId}`, { status: 500 });
1081
+ }
1082
+ const now = new Date();
1083
+ const startedStep = item.step?.startedAt
1084
+ ? { ...item.step, startedAt: item.step.startedAt }
1085
+ : {
1086
+ runId,
1087
+ stepId: entry.correlationId,
1088
+ stepName: dehydrated.stepName,
1089
+ status: 'running',
1090
+ attempt: 1,
1091
+ createdAt: now,
1092
+ updatedAt: now,
1093
+ startedAt: now,
1094
+ };
1095
+ inlineClaims.set(entry.correlationId, {
1096
+ owned: true,
1097
+ step: {
1098
+ ...startedStep,
1099
+ input: dehydrated.dehydratedInput,
1100
+ },
1101
+ batchPostSentAtMs,
1102
+ claimCompletedAtMs,
1103
+ });
1104
+ }
1105
+ continue;
1106
+ }
1107
+ if (item.status === 409) {
1108
+ if (entry.kind === 'inline-created' ||
1109
+ entry.kind === 'inline-started') {
1110
+ // The pair lost its atomic create-claim: a concurrent writer
1111
+ // already owns this step (an earlier delivery's create, or a
1112
+ // racing handler's claim). Recorded as a lost claim: the
1113
+ // caller's executeStep returns `skipped` without running the
1114
+ // body, the same outcome as losing the lazy claim. A World
1115
+ // that folds the pair reports the 409 on both rows (set
1116
+ // twice, harmless); one that evaluates rows independently
1117
+ // has the started row (processed second) decide, which is
1118
+ // exactly the single path's semantics (create lost + claim
1119
+ // won still runs the body; create won + claim lost skips).
1120
+ inlineClaims.set(entry.correlationId, { owned: false });
1121
+ runtimeLogger.info('Inline step pre-claim lost, continuing', {
1122
+ workflowRunId: runId,
1123
+ correlationId: entry.correlationId,
1124
+ message: item.message,
1125
+ });
1126
+ continue;
1127
+ }
1128
+ // Same tolerance as the single path's EntityConflictError: a
1129
+ // concurrent or earlier delivery already created it.
1130
+ runtimeLogger.info(entry.kind === 'step'
1131
+ ? 'Step already exists, continuing'
1132
+ : 'Wait already exists, continuing', {
1133
+ workflowRunId: runId,
1134
+ correlationId: entry.correlationId,
1135
+ message: item.message,
1136
+ });
1137
+ continue;
1138
+ }
1139
+ throw new WorkflowWorldError(`batched ${entry.event.eventType} for ${entry.correlationId} ` +
1140
+ `failed: ${item.error}: ${item.message}`, { status: item.status });
1141
+ }
1142
+ // Highest slot this chunk committed: the ceiling the caller folds
1143
+ // into the inline executions' slot snapshot (see
1144
+ // SuspensionHandlerResult.batchCommittedSlotCeiling) and one input
1145
+ // of the interleaving diagnostic.
1146
+ const chunkMaxSlot = maxEventSlot(results.flatMap((item) => item.error === undefined && item.event ? [item.event] : []));
1147
+ if (chunkMaxSlot !== undefined &&
1148
+ (batchCommittedSlotCeiling === undefined ||
1149
+ chunkMaxSlot > batchCommittedSlotCeiling)) {
1150
+ batchCommittedSlotCeiling = chunkMaxSlot;
1151
+ }
1152
+ committedCount += results.filter((item) => item.error === undefined).length;
1153
+ if (chunkMaxSlot !== undefined &&
1154
+ (maxCommittedSlot === undefined || chunkMaxSlot > maxCommittedSlot)) {
1155
+ maxCommittedSlot = chunkMaxSlot;
1156
+ }
1157
+ };
1158
+ // Publish the chunk's eager steps' queue messages the moment ITS
1159
+ // creates are durable, the per-chunk half of publish-after-create.
1160
+ // Same message shape and step-identity-scoped idempotency key as the
1161
+ // caller's dispatch pass, so anything double-published dedupes.
1162
+ const publishChunkSteps = async (chunk) => {
1163
+ if (!publishEagerSteps)
1164
+ return;
1165
+ const stepEntries = chunk.filter((entry) => entry.kind === 'step');
1166
+ if (stepEntries.length === 0)
1167
+ return;
1168
+ const traceCarrier = await getStepDispatchTraceCarrier();
1169
+ await Promise.all(stepEntries.map((entry) => queueMessage(world,
1170
+ // biome-ignore lint/style/noNonNullAssertion: publishEagerSteps implies presence
1171
+ stepDispatch.queueName, {
1172
+ runId,
1173
+ stepId: entry.correlationId,
1174
+ // biome-ignore lint/style/noNonNullAssertion: set on every 'step' entry at enqueue
1175
+ stepName: entry.stepName,
1176
+ traceCarrier,
1177
+ requestedAt: new Date(),
1178
+ }, {
1179
+ idempotencyKey: stepDispatchIdempotencyKey(entry.correlationId,
1180
+ // biome-ignore lint/style/noNonNullAssertion: set on every 'step' entry at enqueue
1181
+ entry.stepName),
1182
+ })));
1183
+ };
1184
+ // Launch every chunk's POST now; chain each chunk's publishes on its
1185
+ // OWN commit. A chunk whose commit rejected keeps its messages
1186
+ // unsent (the rejection fails the delivery; redelivery re-creates
1187
+ // and re-dispatches, deduped by the idempotency keys).
1188
+ const commits = chunks.map((chunk) => commitChunk(chunk));
1189
+ const publishes = chunks.map(async (chunk, index) => {
1190
+ await commits[index];
1191
+ await publishChunkSteps(chunk);
1192
+ });
1193
+ const trailing = (async () => {
1194
+ // Let every sibling settle before surfacing the first failure: a
1195
+ // chunk that committed must still get its publishes out even when
1196
+ // another chunk failed, and the caller acks only after this
1197
+ // resolves.
1198
+ const settled = await Promise.allSettled([...commits, ...publishes]);
1199
+ // Foreign-interleaving visibility: the batch endpoint has no
1200
+ // bump-and-report, so events other writers landed between the
1201
+ // snapshot and these commits pushed the fold to higher slots
1202
+ // WITHOUT handing us the skipped events. Same accepted exposure
1203
+ // as a dropped truncated report on the single path: the local
1204
+ // log stays a strict prefix and the next reload observes them.
1205
+ // Logged so a bump is diagnosable rather than silent.
1206
+ if (expectedFirstSlot !== undefined &&
1207
+ maxCommittedSlot !== undefined) {
1208
+ const interleaved = maxCommittedSlot - expectedFirstSlot + 1 - committedCount;
1209
+ if (interleaved > 0) {
1210
+ runtimeLogger.debug('Batched fan-out committed above snapshot', {
1211
+ workflowRunId: runId,
1212
+ expectedFirstSlot,
1213
+ maxCommittedSlot,
1214
+ committedCount,
1215
+ interleaved,
1216
+ });
1217
+ }
1218
+ }
1219
+ const failure = settled.find((outcome) => outcome.status === 'rejected');
1220
+ if (failure)
1221
+ throw failure.reason;
1222
+ })();
1223
+ // EVERY chunk carrying pairs gates the return, not just the first:
1224
+ // a pair whose commit the caller has not seen yields no
1225
+ // `inlineClaims` entry, so the caller falls back to a lazy
1226
+ // `step_started` that would race this same fold's still-in-flight
1227
+ // pair for the same step. Today pairs always land in one chunk
1228
+ // (they sort first, and two rows per inline step fit inside one
1229
+ // chunk, pinned by constants.test.ts), so this is at most one
1230
+ // commit; the filter is what keeps the property true if either cap
1231
+ // moves.
1232
+ const pairCommits = chunks.flatMap((chunk, index) => chunk.some((entry) => entry.kind === 'inline-started')
1233
+ ? [commits[index]]
1234
+ : []);
1235
+ if (allowDeferredBatchWork) {
1236
+ // The trailing work is the caller's to join before ack. Attach a
1237
+ // handler now so a rejection that races that join (or a foreground
1238
+ // failure that prevents the caller from ever reaching it) is never
1239
+ // an unhandledRejection; awaiting the promise still observes it.
1240
+ trailing.catch(() => { });
1241
+ deferredBatchWork = trailing;
1242
+ // Only the pair chunks gate the return: their claims are what the
1243
+ // caller starts the inline bodies from. With no pairs there is
1244
+ // nothing the caller's post-return work reads from the commits,
1245
+ // so nothing gates.
1246
+ if (pairCommits.length > 0) {
1247
+ try {
1248
+ await Promise.all(pairCommits);
1249
+ }
1250
+ catch (err) {
1251
+ // A pair chunk failed, so this phase's write set is NOT the
1252
+ // caller's to join any more: `deferredBatchWork` never
1253
+ // reaches it once handleSuspension throws. Settle the rest
1254
+ // before the rejection escapes, for the reason `settlePhase`
1255
+ // gives: a sibling create landing after the throw commits an
1256
+ // event from the abandoned replay's seeded sequence and races
1257
+ // the caller's restart reload while doing so.
1258
+ await trailing.catch(() => { });
1259
+ throw err;
1260
+ }
1261
+ }
1262
+ }
1263
+ else {
1264
+ await trailing;
1265
+ }
1266
+ })());
1267
+ }
1268
+ for (const queueItem of attributeItems) {
1269
+ ops.push((async () => {
1270
+ try {
1271
+ await ensureRunReady();
1272
+ // Guarded like every other suspension write: an attr_set is a
1273
+ // replay-derived event with a correlation id from this replay's
1274
+ // seeded sequence, so it must not land on a log the replay never
1275
+ // saw. Rejecting it is cheap: a run with attribute events already
1276
+ // forces an in-process replay, so the restart costs the replay it
1277
+ // was going to do anyway.
1278
+ await createGuarded({
1279
+ eventType: 'attr_set',
1280
+ specVersion: SPEC_VERSION_CURRENT,
1281
+ correlationId: queueItem.correlationId,
1282
+ eventData: {
1283
+ changes: queueItem.changes,
1284
+ writer: { type: 'workflow' },
1285
+ ...(queueItem.allowReservedAttributes
1286
+ ? { allowReservedAttributes: true }
1287
+ : {}),
1288
+ },
1289
+ }, { requestId });
1290
+ }
1291
+ catch (err) {
1292
+ if (EntityConflictError.is(err)) {
1293
+ runtimeLogger.info('Workflow attribute event already exists, continuing', {
1294
+ workflowRunId: runId,
1295
+ correlationId: queueItem.correlationId,
1296
+ message: err.message,
1297
+ });
1298
+ }
1299
+ else if (isWorldValidationFailure(err)) {
1300
+ // Deterministic validation rejection from the World, e.g. the
1301
+ // cumulative per-run attribute cap, which only the World can
1302
+ // check against the run's existing attributes. Redelivering the
1303
+ // orchestrator message replays the workflow into the exact same
1304
+ // write and the exact same rejection, so retrying can never
1305
+ // succeed. Surface it as a FatalError so the caller fails the
1306
+ // run with a clear error instead of wedging it in redelivery.
1307
+ const fatal = new FatalError(`setAttributes failed World validation: ${err instanceof Error ? err.message : String(err)}`);
1308
+ fatal.cause = err;
1309
+ throw fatal;
1310
+ }
1311
+ else {
1312
+ throw err;
1313
+ }
1314
+ }
1315
+ })());
1316
+ }
1317
+ // Await the step_created / wait_created event creates before returning.
1318
+ // The caller (workflowEntrypoint) only enqueues the step-dispatch queue
1319
+ // messages AFTER handleSuspension resolves, and the queue handler acks
1320
+ // the orchestrator message only after the caller resolves. So the step_created
1321
+ // events must be durable here, and the dispatch sends must complete in the caller,
1322
+ // all before ack. If the process crashes before this resolves, the orchestrator
1323
+ // message is not acked and VQS redelivers, re-creates the (idempotent)
1324
+ // step_created and re-dispatches, and recovers the run instead of orphaning it.
1325
+ await settlePhase(ops);
1326
+ // Rebuild the inline batch in deterministic order. `lazyInlineCorrelationIds`
1327
+ // is a Set seeded from the ordered first-N slice, so iterating it preserves
1328
+ // stepItems order; every id in it was set by the lazy branch above.
1329
+ const lazyInlineSteps = [];
1330
+ for (const correlationId of lazyInlineCorrelationIds) {
1331
+ const lazyStep = lazyInlineByCorrelationId.get(correlationId);
1332
+ if (lazyStep)
1333
+ lazyInlineSteps.push(lazyStep);
1334
+ }
1335
+ // Find the soonest pending wait (minimum timeout)
257
1336
  const now = Date.now();
258
- const minTimeoutSeconds = waitItems.reduce((min, queueItem) => {
1337
+ let soonestWait;
1338
+ for (const queueItem of waitItems) {
259
1339
  const resumeAtMs = queueItem.resumeAt.getTime();
260
1340
  const delayMs = Math.max(1000, resumeAtMs - now);
261
1341
  const timeoutSeconds = Math.ceil(delayMs / 1000);
262
- if (min === null)
263
- return timeoutSeconds;
264
- return Math.min(min, timeoutSeconds);
265
- }, null);
1342
+ if (!soonestWait || timeoutSeconds < soonestWait.seconds) {
1343
+ soonestWait = {
1344
+ seconds: timeoutSeconds,
1345
+ correlationId: queueItem.correlationId,
1346
+ };
1347
+ }
1348
+ }
266
1349
  span?.setAttributes({
267
1350
  ...Attribute.WorkflowRunStatus('workflow_suspended'),
268
1351
  ...Attribute.WorkflowStepsCreated(stepItems.length),
269
1352
  ...Attribute.WorkflowHooksCreated(hooksNeedingCreation.length),
270
1353
  ...Attribute.WorkflowWaitsCreated(waitItems.length),
1354
+ ...(failedStepCorrelationIds.size > 0
1355
+ ? Attribute.WorkflowStepsFailedSerialization(failedStepCorrelationIds.size)
1356
+ : {}),
1357
+ ...(resilientDispatchRecovered > 0
1358
+ ? Attribute.StepResilientDispatchRecovered(resilientDispatchRecovered)
1359
+ : {}),
271
1360
  });
272
1361
  return {
273
1362
  pendingSteps: stepItems,
274
1363
  createdStepCorrelationIds,
275
- timeoutSeconds: hasHookConflict ? 0 : (minTimeoutSeconds ?? undefined),
276
- hasHookConflict,
1364
+ failedStepCorrelationIds,
1365
+ queuedStepCorrelationIds,
1366
+ lazyInlineSteps,
1367
+ inlineClaims,
1368
+ batchCommittedSlotCeiling,
1369
+ deferredBatchWork,
1370
+ // On hook conflict the caller advances the workflow over the conflict
1371
+ // before scheduling anything and never reads the wait timeout, so don't
1372
+ // report one. The next pass, which sees the conflict settled, reports it.
1373
+ waitTimeout: hookConflictCorrelationIds.length > 0 ? undefined : soonestWait,
1374
+ hasHookConflict: hookConflictCorrelationIds.length > 0,
1375
+ hookConflictCorrelationIds,
1376
+ hasAwaitedHookCreation: awaitedHookCorrelationIds.length > 0,
1377
+ awaitedHookCorrelationIds,
1378
+ // The delta accounts for the whole log only if the write that returned it
1379
+ // was this suspension's only one — anything written after it landed above
1380
+ // the delta and is missing from the caller's log.
1381
+ eventLogCarriedForward: deltaAbsorbed && guardedWrites === 1,
1382
+ hasAttributeEvents: attributeItems.length > 0,
1383
+ hasHookEvents: hooksNeedingCreation.length > 0,
1384
+ hookCreationMs,
1385
+ serializationBlockerCount,
1386
+ serializationBlockers,
1387
+ reportedEventCount: reportedEvents,
277
1388
  };
278
1389
  }
279
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3VzcGVuc2lvbi1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bnRpbWUvc3VzcGVuc2lvbi1oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUM5QyxPQUFPLEVBQ0wsbUJBQW1CLEVBQ25CLGlCQUFpQixFQUNqQixlQUFlLEdBQ2hCLE1BQU0sa0JBQWtCLENBQUM7QUFDMUIsT0FBTyxFQUdMLG9CQUFvQixHQUdyQixNQUFNLGlCQUFpQixDQUFDO0FBQ3pCLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQU83QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzdDLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzdELE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUN2RCxPQUFPLEtBQUssU0FBUyxNQUFNLHNDQUFzQyxDQUFDO0FBZ0NsRTs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsZ0JBQWdCLENBQUMsRUFDckMsVUFBVSxFQUNWLEtBQUssRUFDTCxHQUFHLEVBQ0gsSUFBSSxFQUNKLFNBQVMsR0FDZTtJQUN4QixNQUFNLEtBQUssR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDO0lBQ3hCLCtCQUErQjtJQUMvQixNQUFNLFNBQVMsR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FDdkMsQ0FBQyxJQUFJLEVBQW1DLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxLQUFLLE1BQU0sQ0FDaEUsQ0FBQztJQUNGLE1BQU0sWUFBWSxHQUFHLFVBQVUsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUMxQyxDQUFDLElBQUksRUFBbUMsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUNoRSxDQUFDO0lB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LENBQUM7UUFDakQsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLENBQUM7UUFDakQsSUFBSSxHQUFHLEtBQUssSUFBSTtZQUFFLE9BQU8sY0FBYyxDQUFDO1FBQ3hDLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsY0FBYyxDQUFDLENBQUM7SUFDdkMsQ0FBQyxFQUNELElBQUksQ0FDTCxDQUFDO0lBRUYsSUFBSSxFQUFFLGFBQWEsQ0FBQztRQUNsQixHQUFHLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxvQkFBb0IsQ0FBQztRQUNwRCxHQUFHLFNBQVMsQ0FBQyxvQkFBb0IsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDO1FBQ25ELEdBQUcsU0FBUyxDQUFDLG9CQUFvQixDQUFDLG9CQUFvQixDQUFDLE1BQU0sQ0FBQztRQUM5RCxHQUFHLFNBQVMsQ0FBQyxvQkFBb0IsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDO0tBQ3BELENBQUMsQ0FBQztJQUVILE9BQU87UUFDTCxZQUFZLEVBQUUsU0FBUztRQUN2Qix5QkFBeUI7UUFDekIsY0FBYyxFQUFFLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLGlCQUFpQixJQUFJLFNBQVMsQ0FBQztRQUN0RSxlQUFlO0tBQ2hCLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBTcGFuIH0gZnJvbSAnQG9wZW50ZWxlbWV0cnkvYXBpJztcbmltcG9ydCB7IHdhaXRVbnRpbCB9IGZyb20gJ0B2ZXJjZWwvZnVuY3Rpb25zJztcbmltcG9ydCB7XG4gIEVudGl0eUNvbmZsaWN0RXJyb3IsXG4gIEhvb2tOb3RGb3VuZEVycm9yLFxuICBSdW5FeHBpcmVkRXJyb3IsXG59IGZyb20gJ0B3b3JrZmxvdy9lcnJvcnMnO1xuaW1wb3J0IHtcbiAgdHlwZSBDcmVhdGVFdmVudFJlcXVlc3QsXG4gIHR5cGUgU2VyaWFsaXplZERhdGEsXG4gIFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICB0eXBlIFdvcmtmbG93UnVuLFxuICB0eXBlIFdvcmxkLFxufSBmcm9tICdAd29ya2Zsb3cvd29ybGQnO1xuaW1wb3J0IHsgaW1wb3J0S2V5IH0gZnJvbSAnLi4vZW5jcnlwdGlvbi5qcyc7XG5pbXBvcnQgdHlwZSB7XG4gIEhvb2tJbnZvY2F0aW9uUXVldWVJdGVtLFxuICBTdGVwSW52b2NhdGlvblF1ZXVlSXRlbSxcbiAgV2FpdEludm9jYXRpb25RdWV1ZUl0ZW0sXG4gIFdvcmtmbG93U3VzcGVuc2lvbixcbn0gZnJvbSAnLi4vZ2xvYmFsLmpzJztcbmltcG9ydCB7IHJ1bnRpbWVMb2dnZXIgfSBmcm9tICcuLi9sb2dnZXIuanMnO1xuaW1wb3J0IHsgZGVoeWRyYXRlU3RlcEFyZ3VtZW50cyB9IGZyb20gJy4uL3NlcmlhbGl6YXRpb24uanMnO1xuaW1wb3J0IHsgZ2V0QWJvcnRTdHJlYW1JZEZyb21Ub2tlbiB9IGZyb20gJy4uL3V0aWwuanMnO1xuaW1wb3J0ICogYXMgQXR0cmlidXRlIGZyb20gJy4uL3RlbGVtZXRyeS9zZW1hbnRpYy1jb252ZW50aW9ucy5qcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3VzcGVuc2lvbkhhbmRsZXJQYXJhbXMge1xuICBzdXNwZW5zaW9uOiBXb3JrZmxvd1N1c3BlbnNpb247XG4gIHdvcmxkOiBXb3JsZDtcbiAgcnVuOiBXb3JrZmxvd1J1bjtcbiAgc3Bhbj86IFNwYW47XG4gIHJlcXVlc3RJZD86IHN0cmluZztcbn1cblxuLyoqXG4gKiBSZXN1bHQgb2YgaGFuZGxpbmcgYSBzdXNwZW5zaW9uLiBSZXR1cm5zIHBlbmRpbmcgc3RlcCBpdGVtcyBzbyB0aGUgY2FsbGVyXG4gKiBjYW4gZGVjaWRlIHdoaWNoIHRvIGV4ZWN1dGUgaW5saW5lIHZzIHF1ZXVlIHRvIGJhY2tncm91bmQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3VzcGVuc2lvbkhhbmRsZXJSZXN1bHQge1xuICAvKiogUGVuZGluZyBzdGVwIGl0ZW1zIHdpdGggZXZlbnRzIGNyZWF0ZWQgYnV0IE5PVCBxdWV1ZWQgKi9cbiAgcGVuZGluZ1N0ZXBzOiBTdGVwSW52b2NhdGlvblF1ZXVlSXRlbVtdO1xuICAvKipcbiAgICogQ29ycmVsYXRpb24gSURzIGZvciB3aGljaCB0aGlzIHN1c3BlbnNpb24gY2FsbCBhY3R1YWxseSB3cm90ZSB0aGVcbiAgICogc3RlcF9jcmVhdGVkIGV2ZW50IChhcyBvcHBvc2VkIHRvIGNhdGNoaW5nIEVudGl0eUNvbmZsaWN0RXJyb3IgYmVjYXVzZVxuICAgKiBhIGNvbmN1cnJlbnQgaGFuZGxlciB3cm90ZSBpdCBmaXJzdCkuIE9ubHkgdGhlIGhhbmRsZXIgdGhhdCB3cm90ZSB0aGVcbiAgICogc3RlcF9jcmVhdGVkIGV2ZW50IHNob3VsZCBxdWV1ZSAvIGlubGluZS1leGVjdXRlIHRoZSBzdGVwIOKAlCB0aGlzXG4gICAqIGd1YXJhbnRlZXMgYSBzaW5nbGUgb3duZXIgcGVyIHN0ZXAsIGV2ZW4gd2hlbiBtdWx0aXBsZSBoYW5kbGVycyByYWNlXG4gICAqIGludG8gdGhlIHNhbWUgYmF0Y2ggYm91bmRhcnkuXG4gICAqL1xuICBjcmVhdGVkU3RlcENvcnJlbGF0aW9uSWRzOiBTZXQ8c3RyaW5nPjtcbiAgLyoqIFRpbWVvdXQgZnJvbSB3YWl0cywgaWYgYW55ICovXG4gIHRpbWVvdXRTZWNvbmRzPzogbnVtYmVyO1xuICAvKiogV2hldGhlciBhIGhvb2sgY29uZmxpY3Qgd2FzIGRldGVjdGVkIChzaG91bGQgcmUtaW52b2tlIGltbWVkaWF0ZWx5KSAqL1xuICBoYXNIb29rQ29uZmxpY3Q6IGJvb2xlYW47XG59XG5cbi8qKlxuICogSGFuZGxlcyBhIHdvcmtmbG93IHN1c3BlbnNpb24gYnkgcHJvY2Vzc2luZyBhbGwgcGVuZGluZyBvcGVyYXRpb25zIChob29rcywgc3RlcHMsIHdhaXRzKS5cbiAqIENyZWF0ZXMgZXZlbnRzIGZvciBhbGwgb3BlcmF0aW9ucyBidXQgZG9lcyBOT1QgcXVldWUgc3RlcCBtZXNzYWdlcyDigJQgcmV0dXJucyB0aGUgcGVuZGluZ1xuICogc3RlcHMgc28gdGhlIGNhbGxlciBjYW4gZGVjaWRlIHdoaWNoIHRvIGV4ZWN1dGUgaW5saW5lIHZzIHF1ZXVlIHRvIGJhY2tncm91bmQuXG4gKlxuICogUHJvY2Vzc2luZyBvcmRlcjpcbiAqIDEuIEhvb2tzIGFyZSBwcm9jZXNzZWQgZmlyc3QgdG8gcHJldmVudCByYWNlIGNvbmRpdGlvbnMgd2l0aCB3ZWJob29rIHJlY2VpdmVyc1xuICogMi4gU3RlcCBldmVudHMgYW5kIHdhaXQgZXZlbnRzIGFyZSBjcmVhdGVkIGluIHBhcmFsbGVsXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYW5kbGVTdXNwZW5zaW9uKHtcbiAgc3VzcGVuc2lvbixcbiAgd29ybGQsXG4gIHJ1bixcbiAgc3BhbixcbiAgcmVxdWVzdElkLFxufTogU3VzcGVuc2lvbkhhbmRsZXJQYXJhbXMpOiBQcm9taXNlPFN1c3BlbnNpb25IYW5kbGVyUmVzdWx0PiB7XG4gIGNvbnN0IHJ1bklkID0gcnVuLnJ1bklkO1xuICAvLyBTZXBhcmF0ZSBxdWV1ZSBpdGVtcyBieSB0eXBlXG4gIGNvbnN0IHN0ZXBJdGVtcyA9IHN1c3BlbnNpb24uc3RlcHMuZmlsdGVyKFxuICAgIChpdGVtKTogaXRlbSBpcyBTdGVwSW52b2NhdGlvblF1ZXVlSXRlbSA9PiBpdGVtLnR5cGUgPT09ICdzdGVwJ1xuICApO1xuICBjb25zdCBhbGxIb29rSXRlbXMgPSBzdXNwZW5zaW9uLnN0ZXBzLmZpbHRlcihcbiAgICAoaXRlbSk6IGl0ZW0gaXMgSG9va0ludm9jYXRpb25RdWV1ZUl0ZW0gPT4gaXRlbS50eXBlID09PSAnaG9vaydcbiAgKTtcbiAgY29uc3Qgd2FpdEl0ZW1zID0gc3VzcGVuc2lvbi5zdGVwcy5maWx0ZXIoXG4gICAgKGl0ZW0pOiBpdGVtIGlzIFdhaXRJbnZvY2F0aW9uUXVldWVJdGVtID0+IGl0ZW0udHlwZSA9PT0gJ3dhaXQnXG4gICk7XG5cbiAgLy8gU3BsaXQgaG9va3MgYnkgd2hhdCBhY3Rpb25zIHRoZXkgbmVlZFxuICBjb25zdCBob29rc05lZWRpbmdDcmVhdGlvbiA9IGFsbEhvb2tJdGVtcy5maWx0ZXIoXG4gICAgKGl0ZW0pID0+ICFpdGVtLmhhc0NyZWF0ZWRFdmVudFxuICApO1xuICBjb25zdCBob29rc05lZWRpbmdEaXNwb3NhbCA9IGFsbEhvb2tJdGVtcy5maWx0ZXIoKGl0ZW0pID0+IGl0ZW0uZGlzcG9zZWQpO1xuXG4gIC8vIFJlc29sdmUgZW5jcnlwdGlvbiBrZXkgZm9yIHRoaXMgcnVuXG4gIGNvbnN0IHJhd0tleSA9IGF3YWl0IHdvcmxkLmdldEVuY3J5cHRpb25LZXlGb3JSdW4/LihydW4pO1xuICBjb25zdCBlbmNyeXB0aW9uS2V5ID0gcmF3S2V5ID8gYXdhaXQgaW1wb3J0S2V5KHJhd0tleSkgOiB1bmRlZmluZWQ7XG5cbiAgLy8gQnVpbGQgYW5kIHByb2Nlc3MgaG9va19jcmVhdGVkIGV2ZW50cyAoc2FtZSBhcyBWMSlcbiAgY29uc3QgaG9va0V2ZW50czogQ3JlYXRlRXZlbnRSZXF1ZXN0W10gPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICBob29rc05lZWRpbmdDcmVhdGlvbi5tYXAoYXN5bmMgKHF1ZXVlSXRlbSkgPT4ge1xuICAgICAgY29uc3QgaG9va01ldGFkYXRhOiBTZXJpYWxpemVkRGF0YSB8IHVuZGVmaW5lZCA9XG4gICAgICAgIHR5cGVvZiBxdWV1ZUl0ZW0ubWV0YWRhdGEgPT09ICd1bmRlZmluZWQnXG4gICAgICAgICAgPyB1bmRlZmluZWRcbiAgICAgICAgICA6ICgoYXdhaXQgZGVoeWRyYXRlU3RlcEFyZ3VtZW50cyhcbiAgICAgICAgICAgICAgcXVldWVJdGVtLm1ldGFkYXRhLFxuICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgICAgICAgICAgc3VzcGVuc2lvbi5nbG9iYWxUaGlzXG4gICAgICAgICAgICApKSBhcyBTZXJpYWxpemVkRGF0YSk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBldmVudFR5cGU6ICdob29rX2NyZWF0ZWQnIGFzIGNvbnN0LFxuICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICB0b2tlbjogcXVldWVJdGVtLnRva2VuLFxuICAgICAgICAgIG1ldGFkYXRhOiBob29rTWV0YWRhdGEsXG4gICAgICAgICAgaXNXZWJob29rOiBxdWV1ZUl0ZW0uaXNXZWJob29rID8/IGZhbHNlLFxuICAgICAgICAgIC4uLihxdWV1ZUl0ZW0uaXNTeXN0ZW0gJiYgeyBpc1N5c3RlbTogdHJ1ZSB9KSxcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgfSlcbiAgKTtcblxuICAvLyBQcm9jZXNzIGhvb2tzIGZpcnN0IHRvIHByZXZlbnQgcmFjZSBjb25kaXRpb25zIHdpdGggd2ViaG9vayByZWNlaXZlcnMuXG4gIC8vIEFsbCBob29rIGNyZWF0aW9ucyBydW4gaW4gcGFyYWxsZWwuXG4gIC8vIFRyYWNrIGFueSBob29rIGNvbmZsaWN0cyB0aGF0IG9jY3VyIOKAlCB0aGVzZSBhcmUgcmV0dXJuZWQgdG8gdGhlIGNhbGxlclxuICAvLyBzbyB0aGUgVjIgaGFuZGxlciBjYW4gcmUtaW52b2tlIGltbWVkaWF0ZWx5LlxuICBsZXQgaGFzSG9va0NvbmZsaWN0ID0gZmFsc2U7XG5cbiAgaWYgKGhvb2tFdmVudHMubGVuZ3RoID4gMCkge1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgaG9va0V2ZW50cy5tYXAoYXN5bmMgKGhvb2tFdmVudCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUocnVuSWQsIGhvb2tFdmVudCwge1xuICAgICAgICAgICAgcmVxdWVzdElkLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIC8vIENoZWNrIGlmIHRoZSB3b3JsZCByZXR1cm5lZCBhIGhvb2tfY29uZmxpY3QgZXZlbnQgaW5zdGVhZCBvZiBob29rX2NyZWF0ZWQuXG4gICAgICAgICAgLy8gVGhlIGhvb2tfY29uZmxpY3QgZXZlbnQgaXMgc3RvcmVkIGluIHRoZSBldmVudCBsb2cgYW5kIHdpbGwgYmUgcmVwbGF5ZWRcbiAgICAgICAgICAvLyBvbiB0aGUgbmV4dCB3b3JrZmxvdyBpbnZvY2F0aW9uLCBjYXVzaW5nIHRoZSBob29rJ3MgcHJvbWlzZSB0byByZWplY3QuXG4gICAgICAgICAgLy8gTm90ZTogaG9vayBldmVudHMgYWx3YXlzIGNyZWF0ZSBhbiBldmVudCAobGVnYWN5IHJ1bnMgdGhyb3csIG5vdCByZXR1cm4gdW5kZWZpbmVkKVxuICAgICAgICAgIGlmIChyZXN1bHQuZXZlbnQhLmV2ZW50VHlwZSA9PT0gJ2hvb2tfY29uZmxpY3QnKSB7XG4gICAgICAgICAgICBoYXNIb29rQ29uZmxpY3QgPSB0cnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSB8fCBSdW5FeHBpcmVkRXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAnV29ya2Zsb3cgcnVuIGFscmVhZHkgY29tcGxldGVkLCBza2lwcGluZyBob29rJyxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvLyBQcm9jZXNzIGhvb2sgZGlzcG9zYWxzIOKAlCB0aGVzZSByZWxlYXNlIGhvb2sgdG9rZW5zIGZvciByZXVzZSBieSBvdGhlciB3b3JrZmxvd3MuXG4gIGlmIChob29rc05lZWRpbmdEaXNwb3NhbC5sZW5ndGggPiAwKSB7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBob29rc05lZWRpbmdEaXNwb3NhbC5tYXAoYXN5bmMgKHF1ZXVlSXRlbSkgPT4ge1xuICAgICAgICBjb25zdCBob29rRGlzcG9zZWRFdmVudDogQ3JlYXRlRXZlbnRSZXF1ZXN0ID0ge1xuICAgICAgICAgIGV2ZW50VHlwZTogJ2hvb2tfZGlzcG9zZWQnIGFzIGNvbnN0LFxuICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgfTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKHJ1bklkLCBob29rRGlzcG9zZWRFdmVudCwgeyByZXF1ZXN0SWQgfSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgIC8vIEhvb2sgd2FzIGFscmVhZHkgZGlzcG9zZWQgYnkgYSBjb25jdXJyZW50IGludm9jYXRpb24g4oCUIHNhZmUgdG8gc2tpcFxuICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAnSG9vayBhbHJlYWR5IGRpc3Bvc2VkLCBza2lwcGluZyBkdXBsaWNhdGUgZGlzcG9zYWwnLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIGlmIChSdW5FeHBpcmVkRXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAnV29ya2Zsb3cgcnVuIGFscmVhZHkgY29tcGxldGVkLCBza2lwcGluZyBob29rIGRpc3Bvc2FsJyxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0gZWxzZSBpZiAoSG9va05vdEZvdW5kRXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgLy8gSG9vayBtYXkgaGF2ZSBhbHJlYWR5IGJlZW4gZGlzcG9zZWQgb3IgbmV2ZXIgY3JlYXRlZFxuICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKCdIb29rIG5vdCBmb3VuZCBmb3IgZGlzcG9zYWwsIGNvbnRpbnVpbmcnLCB7XG4gICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgLy8gUHJvY2VzcyBhYm9ydCByZXF1ZXN0cyDigJQgcmVzdW1lIHRoZSBob29rIHdpdGggYWJvcnQgcGF5bG9hZCBhbmQgd3JpdGUgc3RyZWFtIHBhY2tldFxuICBjb25zdCBob29rc05lZWRpbmdBYm9ydCA9IGFsbEhvb2tJdGVtcy5maWx0ZXIoXG4gICAgKGl0ZW0pID0+IGl0ZW0uYWJvcnRSZXF1ZXN0ZWQgJiYgIWl0ZW0uZGlzcG9zZWRcbiAgKTtcblxuICBpZiAoaG9va3NOZWVkaW5nQWJvcnQubGVuZ3RoID4gMCkge1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgaG9va3NOZWVkaW5nQWJvcnQubWFwKGFzeW5jIChxdWV1ZUl0ZW0pID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAvLyBEZWh5ZHJhdGUgdGhlIGFib3J0IHBheWxvYWQgZm9yIHN0b3JhZ2VcbiAgICAgICAgICBjb25zdCBhYm9ydFBheWxvYWQgPSBhd2FpdCBkZWh5ZHJhdGVTdGVwQXJndW1lbnRzKFxuICAgICAgICAgICAgeyBhYm9ydGVkOiB0cnVlLCByZWFzb246IHF1ZXVlSXRlbS5hYm9ydFJlYXNvbiB9LFxuICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICBlbmNyeXB0aW9uS2V5LFxuICAgICAgICAgICAgc3VzcGVuc2lvbi5nbG9iYWxUaGlzXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIC8vIENyZWF0ZSBob29rX3JlY2VpdmVkIGV2ZW50IHdpdGggYWJvcnQgcGF5bG9hZFxuICAgICAgICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUocnVuSWQsIHtcbiAgICAgICAgICAgIGV2ZW50VHlwZTogJ2hvb2tfcmVjZWl2ZWQnIGFzIGNvbnN0LFxuICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgcGF5bG9hZDogYWJvcnRQYXlsb2FkLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIC8vIFdyaXRlIHN0cmVhbSBjYW5jZWxsYXRpb24gcGFja2V0IGZvciByZWFsLXRpbWUgc3RlcCBwcm9wYWdhdGlvbi5cbiAgICAgICAgICAvLyBSZXVzZSB0aGUgc2FtZSBkZWh5ZHJhdGVkIHBheWxvYWQgYXMgdGhlIGhvb2sgZXZlbnQgc28gdGhlIHJlYXNvblxuICAgICAgICAgIC8vIHJvdW5kLXRyaXBzIHRocm91Z2ggYGRlaHlkcmF0ZVN0ZXBBcmd1bWVudHNgIC8gYGh5ZHJhdGVTdGVwQXJndW1lbnRzYFxuICAgICAgICAgIC8vIChoYW5kbGVzIERPTUV4Y2VwdGlvbiwgY3VzdG9tIGVycm9ycywgZW5jcnlwdGlvbiwgZXRjLikgaW5zdGVhZCBvZlxuICAgICAgICAgIC8vIGJhcmUgSlNPTi5zdHJpbmdpZnkgd2hpY2ggbG9zZXMgdHlwZSBpbmZvcm1hdGlvbiBhbmQgZHJvcHMgdW5kZWZpbmVkLlxuICAgICAgICAgIC8vIHN0cmVhbU5hbWUgaXMgc2V0IG9uIHRoZSBxdWV1ZSBpdGVtIGF0IGNvbnRyb2xsZXIgY29uc3RydWN0aW9uIHRpbWVcbiAgICAgICAgICAvLyAoc2VlIHdvcmtmbG93L2Fib3J0LWNvbnRyb2xsZXIudHMpLlxuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBzdHJlYW1OYW1lID0gZ2V0QWJvcnRTdHJlYW1JZEZyb21Ub2tlbihxdWV1ZUl0ZW0udG9rZW4pO1xuICAgICAgICAgICAgYXdhaXQgd29ybGQuc3RyZWFtcy53cml0ZShcbiAgICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICAgIHN0cmVhbU5hbWUsXG4gICAgICAgICAgICAgIGFib3J0UGF5bG9hZCBhcyBVaW50OEFycmF5XG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgYXdhaXQgd29ybGQuc3RyZWFtcy5jbG9zZShydW5JZCwgc3RyZWFtTmFtZSk7XG4gICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICAvLyBCZXN0LWVmZm9ydCBzdHJlYW0gd3JpdGUg4oCUIGhvb2sgZXZlbnQgcHJvdmlkZXMgdGhlIGR1cmFibGUgZmFsbGJhY2tcbiAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuZGVidWcoXG4gICAgICAgICAgICAgICdGYWlsZWQgdG8gd3JpdGUgYWJvcnQgc3RyZWFtIHBhY2tldCwgaG9vayBldmVudCB3aWxsIHByb3ZpZGUgZmFsbGJhY2snLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpIHx8IFJ1bkV4cGlyZWRFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICdXb3JrZmxvdyBydW4gYWxyZWFkeSBjb21wbGV0ZWQsIHNraXBwaW5nIGFib3J0JyxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvLyBDcmVhdGUgc3RlcCBldmVudHMgZm9yIHN0ZXBzIHRoYXQgZG9uJ3QgaGF2ZSB0aGVtIHlldC5cbiAgLy8gVW5saWtlIFYxLCB3ZSBkbyBOT1QgcXVldWUgc3RlcCBtZXNzYWdlcyBmcm9tIGhlcmUg4oCUIHRoZSBjYWxsZXJcbiAgLy8gZGVjaWRlcyB3aGljaCBzdGVwcyB0byBleGVjdXRlIGlubGluZSB2cy4gcXVldWUgdG8gYmFja2dyb3VuZC5cbiAgLy8gV2FpdCBldmVudHMgYXJlIGFsc28gY3JlYXRlZCBpbiBwYXJhbGxlbCBiZWxvdy5cbiAgY29uc3Qgc3RlcHNOZWVkaW5nQ3JlYXRpb24gPSBuZXcgU2V0KFxuICAgIHN0ZXBJdGVtc1xuICAgICAgLmZpbHRlcigocXVldWVJdGVtKSA9PiAhcXVldWVJdGVtLmhhc0NyZWF0ZWRFdmVudClcbiAgICAgIC5tYXAoKHF1ZXVlSXRlbSkgPT4gcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQpXG4gICk7XG5cbiAgLy8gQ29ycmVsYXRpb24gSURzIGZvciB3aGljaCBUSElTIHN1c3BlbnNpb24gY2FsbCBhY3R1YWxseSB3cm90ZSB0aGVcbiAgLy8gc3RlcF9jcmVhdGVkIGV2ZW50LiBQb3B1bGF0ZWQgYnkgdGhlIG9wcyBiZWxvdyBhZnRlciBhIHN1Y2Nlc3NmdWxcbiAgLy8gZXZlbnRzLmNyZWF0ZSDigJQgdXNlZCBieSB0aGUgY2FsbGVyIHRvIGNsYWltIG93bmVyc2hpcCBhbmQgYXZvaWRcbiAgLy8gcmFjaW5nIHdpdGggY29uY3VycmVudCBoYW5kbGVycyBvbiBzdGVwIGV4ZWN1dGlvbi5cbiAgY29uc3QgY3JlYXRlZFN0ZXBDb3JyZWxhdGlvbklkcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4gIGNvbnN0IG9wczogUHJvbWlzZTx2b2lkPltdID0gW107XG5cbiAgLy8gU3RlcHM6IGNyZWF0ZSBzdGVwX2NyZWF0ZWQgZXZlbnRzIChubyBxdWV1aW5nIOKAlCBWMiByZXR1cm5zIHBlbmRpbmcgc3RlcHMgdG8gY2FsbGVyKVxuICBmb3IgKGNvbnN0IHF1ZXVlSXRlbSBvZiBzdGVwSXRlbXMpIHtcbiAgICBpZiAoc3RlcHNOZWVkaW5nQ3JlYXRpb24uaGFzKHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKSkge1xuICAgICAgb3BzLnB1c2goXG4gICAgICAgIChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgZGVoeWRyYXRlZElucHV0ID0gYXdhaXQgZGVoeWRyYXRlU3RlcEFyZ3VtZW50cyhcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgYXJnczogcXVldWVJdGVtLmFyZ3MsXG4gICAgICAgICAgICAgIGNsb3N1cmVWYXJzOiBxdWV1ZUl0ZW0uY2xvc3VyZVZhcnMsXG4gICAgICAgICAgICAgIHRoaXNWYWw6IHF1ZXVlSXRlbS50aGlzVmFsLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgICAgICAgIHN1c3BlbnNpb24uZ2xvYmFsVGhpc1xuICAgICAgICAgICk7XG4gICAgICAgICAgY29uc3Qgc3RlcEV2ZW50OiBDcmVhdGVFdmVudFJlcXVlc3QgPSB7XG4gICAgICAgICAgICBldmVudFR5cGU6ICdzdGVwX2NyZWF0ZWQnIGFzIGNvbnN0LFxuICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgc3RlcE5hbWU6IHF1ZXVlSXRlbS5zdGVwTmFtZSxcbiAgICAgICAgICAgICAgaW5wdXQ6IGRlaHlkcmF0ZWRJbnB1dCBhcyBTZXJpYWxpemVkRGF0YSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfTtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgd29ybGQuZXZlbnRzLmNyZWF0ZShydW5JZCwgc3RlcEV2ZW50LCB7IHJlcXVlc3RJZCB9KTtcbiAgICAgICAgICAgIGNyZWF0ZWRTdGVwQ29ycmVsYXRpb25JZHMuYWRkKHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKTtcbiAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKCdTdGVwIGFscmVhZHkgZXhpc3RzLCBjb250aW51aW5nJywge1xuICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pKClcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLy8gQ3JlYXRlIHdhaXQgZXZlbnRzIChzYW1lIGFzIFYxKVxuICBmb3IgKGNvbnN0IHF1ZXVlSXRlbSBvZiB3YWl0SXRlbXMpIHtcbiAgICBpZiAoIXF1ZXVlSXRlbS5oYXNDcmVhdGVkRXZlbnQpIHtcbiAgICAgIG9wcy5wdXNoKFxuICAgICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHdhaXRFdmVudDogQ3JlYXRlRXZlbnRSZXF1ZXN0ID0ge1xuICAgICAgICAgICAgZXZlbnRUeXBlOiAnd2FpdF9jcmVhdGVkJyBhcyBjb25zdCxcbiAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgIHJlc3VtZUF0OiBxdWV1ZUl0ZW0ucmVzdW1lQXQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH07XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUocnVuSWQsIHdhaXRFdmVudCwgeyByZXF1ZXN0SWQgfSk7XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbygnV2FpdCBhbHJlYWR5IGV4aXN0cywgY29udGludWluZycsIHtcbiAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9KSgpXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHdhaXRVbnRpbChcbiAgICBQcm9taXNlLmFsbChvcHMpLmNhdGNoKChvcEVycikgPT4ge1xuICAgICAgY29uc3QgaXNBYm9ydEVycm9yID1cbiAgICAgICAgb3BFcnI/Lm5hbWUgPT09ICdBYm9ydEVycm9yJyB8fCBvcEVycj8ubmFtZSA9PT0gJ1Jlc3BvbnNlQWJvcnRlZCc7XG4gICAgICBpZiAoIWlzQWJvcnRFcnJvcikgdGhyb3cgb3BFcnI7XG4gICAgfSlcbiAgKTtcbiAgYXdhaXQgUHJvbWlzZS5hbGwob3BzKTtcblxuICAvLyBDYWxjdWxhdGUgbWluaW11bSB0aW1lb3V0IGZyb20gd2FpdHNcbiAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgY29uc3QgbWluVGltZW91dFNlY29uZHMgPSB3YWl0SXRlbXMucmVkdWNlPG51bWJlciB8IG51bGw+KFxuICAgIChtaW4sIHF1ZXVlSXRlbSkgPT4ge1xuICAgICAgY29uc3QgcmVzdW1lQXRNcyA9IHF1ZXVlSXRlbS5yZXN1bWVBdC5nZXRUaW1lKCk7XG4gICAgICBjb25zdCBkZWxheU1zID0gTWF0aC5tYXgoMTAwMCwgcmVzdW1lQXRNcyAtIG5vdyk7XG4gICAgICBjb25zdCB0aW1lb3V0U2Vjb25kcyA9IE1hdGguY2VpbChkZWxheU1zIC8gMTAwMCk7XG4gICAgICBpZiAobWluID09PSBudWxsKSByZXR1cm4gdGltZW91dFNlY29uZHM7XG4gICAgICByZXR1cm4gTWF0aC5taW4obWluLCB0aW1lb3V0U2Vjb25kcyk7XG4gICAgfSxcbiAgICBudWxsXG4gICk7XG5cbiAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93UnVuU3RhdHVzKCd3b3JrZmxvd19zdXNwZW5kZWQnKSxcbiAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dTdGVwc0NyZWF0ZWQoc3RlcEl0ZW1zLmxlbmd0aCksXG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93SG9va3NDcmVhdGVkKGhvb2tzTmVlZGluZ0NyZWF0aW9uLmxlbmd0aCksXG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93V2FpdHNDcmVhdGVkKHdhaXRJdGVtcy5sZW5ndGgpLFxuICB9KTtcblxuICByZXR1cm4ge1xuICAgIHBlbmRpbmdTdGVwczogc3RlcEl0ZW1zLFxuICAgIGNyZWF0ZWRTdGVwQ29ycmVsYXRpb25JZHMsXG4gICAgdGltZW91dFNlY29uZHM6IGhhc0hvb2tDb25mbGljdCA/IDAgOiAobWluVGltZW91dFNlY29uZHMgPz8gdW5kZWZpbmVkKSxcbiAgICBoYXNIb29rQ29uZmxpY3QsXG4gIH07XG59XG4iXX0=
1390
+ /**
1391
+ * Whether an `events.create` rejection is deterministic World validation
1392
+ * rather than a transient/storage error. Local Worlds
1393
+ * (world-local, world-postgres) throw `AttributeValidationError` directly;
1394
+ * remote Worlds surface the equivalent server-side rejection as a
1395
+ * `WorkflowWorldError` with HTTP status 400. The name check covers
1396
+ * `AttributeValidationError` instances from a different copy of
1397
+ * `@workflow/world` than the one this package resolved.
1398
+ */
1399
+ function isWorldValidationFailure(err) {
1400
+ if (err instanceof AttributeValidationError)
1401
+ return true;
1402
+ if (err instanceof Error && err.name === 'AttributeValidationError') {
1403
+ return true;
1404
+ }
1405
+ return WorkflowWorldError.is(err) && err.status === 400;
1406
+ }
1407
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3VzcGVuc2lvbi1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bnRpbWUvc3VzcGVuc2lvbi1oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFDTCxtQkFBbUIsRUFDbkIsVUFBVSxFQUNWLGlCQUFpQixFQUNqQix1QkFBdUIsRUFDdkIsZUFBZSxFQUNmLGtCQUFrQixFQUNsQixrQkFBa0IsR0FDbkIsTUFBTSxrQkFBa0IsQ0FBQztBQUMxQixPQUFPLEVBQ0wsd0JBQXdCLEVBS3hCLG9CQUFvQixFQUNwQiwwQ0FBMEMsRUFDMUMsaUNBQWlDLEVBQ2pDLG1DQUFtQyxHQU1wQyxNQUFNLGlCQUFpQixDQUFDO0FBQ3pCLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQzdELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQVE3QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzdDLE9BQU8sRUFDTCxpQ0FBaUMsR0FHbEMsTUFBTSw4QkFBOEIsQ0FBQztBQUN0QyxPQUFPLEVBQ0wsc0JBQXNCLEVBQ3RCLGtCQUFrQixHQUNuQixNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sS0FBSyxTQUFTLE1BQU0sc0NBQXNDLENBQUM7QUFDbEUsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ3ZELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzVELE9BQU8sRUFDTCxpQkFBaUIsRUFDakIseUJBQXlCLEVBQ3pCLDhCQUE4QixFQUM5Qix1QkFBdUIsRUFDdkIsOEJBQThCLEdBQy9CLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEIsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixjQUFjLEVBR2QsWUFBWSxFQUNaLFlBQVksRUFDWixrQkFBa0IsRUFDbEIsMEJBQTBCLEdBQzNCLE1BQU0s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RUFDVCwwQkFBMEIsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLFdBQVc7UUFDakUsZUFBZSxFQUFFLDBCQUEwQixDQUFDLE1BQU0sR0FBRyxDQUFDO1FBQ3RELDBCQUEwQjtRQUMxQixzQkFBc0IsRUFBRSx5QkFBeUIsQ0FBQyxNQUFNLEdBQUcsQ0FBQztRQUM1RCx5QkFBeUI7UUFDekIsMEVBQTBFO1FBQzFFLDBFQUEwRTtRQUMxRSxrREFBa0Q7UUFDbEQsc0JBQXNCLEVBQUUsYUFBYSxJQUFJLGFBQWEsS0FBSyxDQUFDO1FBQzVELGtCQUFrQixFQUFFLGNBQWMsQ0FBQyxNQUFNLEdBQUcsQ0FBQztRQUM3QyxhQUFhLEVBQUUsb0JBQW9CLENBQUMsTUFBTSxHQUFHLENBQUM7UUFDOUMsY0FBYztRQUNkLHlCQUF5QjtRQUN6QixxQkFBcUI7UUFDckIsa0JBQWtCLEVBQUUsY0FBYztLQUNuQyxDQUFDO0FBQ0osQ0FBQztBQUVEOzs7Ozs7OztHQVFHO0FBQ0gsU0FBUyx3QkFBd0IsQ0FBQyxHQUFZO0lBQzVDLElBQUksR0FBRyxZQUFZLHdCQUF3QjtRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ3pELElBQUksR0FBRyxZQUFZLEtBQUssSUFBSSxHQUFHLENBQUMsSUFBSSxLQUFLLDBCQUEwQixFQUFFLENBQUM7UUFDcEUsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBQ0QsT0FBTyxrQkFBa0IsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksR0FBRyxDQUFDLE1BQU0sS0FBSyxHQUFHLENBQUM7QUFDMUQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgU3BhbiB9IGZyb20gJ0BvcGVudGVsZW1ldHJ5L2FwaSc7XG5pbXBvcnQge1xuICBFbnRpdHlDb25mbGljdEVycm9yLFxuICBGYXRhbEVycm9yLFxuICBIb29rTm90Rm91bmRFcnJvcixcbiAgUHJlY29uZGl0aW9uRmFpbGVkRXJyb3IsXG4gIFJ1bkV4cGlyZWRFcnJvcixcbiAgU2VyaWFsaXphdGlvbkVycm9yLFxuICBXb3JrZmxvd1dvcmxkRXJyb3IsXG59IGZyb20gJ0B3b3JrZmxvdy9lcnJvcnMnO1xuaW1wb3J0IHtcbiAgQXR0cmlidXRlVmFsaWRhdGlvbkVycm9yLFxuICB0eXBlIENyZWF0ZUV2ZW50UGFyYW1zLFxuICB0eXBlIENyZWF0ZUV2ZW50UmVxdWVzdCxcbiAgdHlwZSBFdmVudFJlc3VsdCxcbiAgdHlwZSBTZXJpYWxpemVkRGF0YSxcbiAgU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gIFNQRUNfVkVSU0lPTl9TVVBQT1JUU19DQk9SX1FVRVVFX1RSQU5TUE9SVCxcbiAgU1BFQ19WRVJTSU9OX1NVUFBPUlRTX0NPTVBSRVNTSU9OLFxuICBTUEVDX1ZFUlNJT05fU1VQUE9SVFNfU0xPVF9JREVOVElUWSxcbiAgdHlwZSBTdGFydGVkU3RlcCxcbiAgdHlwZSBUcmFjZUNhcnJpZXIsXG4gIHR5cGUgVmFsaWRRdWV1ZU5hbWUsXG4gIHR5cGUgV29ya2Zsb3dSdW4sXG4gIHR5cGUgV29ybGQsXG59IGZyb20gJ0B3b3JrZmxvdy93b3JsZCc7XG5pbXBvcnQgeyBpc1JldHJ5YWJsZVdvcmxkRXJyb3IgfSBmcm9tICcuLi9jbGFzc2lmeS1lcnJvci5qcyc7XG5pbXBvcnQgeyBpbXBvcnRLZXkgfSBmcm9tICcuLi9lbmNyeXB0aW9uLmpzJztcbmltcG9ydCB0eXBlIHtcbiAgQXR0cmlidXRlSW52b2NhdGlvblF1ZXVlSXRlbSxcbiAgSG9va0ludm9jYXRpb25RdWV1ZUl0ZW0sXG4gIFN0ZXBJbnZvY2F0aW9uUXVldWVJdGVtLFxuICBXYWl0SW52b2NhdGlvblF1ZXVlSXRlbSxcbiAgV29ya2Zsb3dTdXNwZW5zaW9uLFxufSBmcm9tICcuLi9nbG9iYWwuanMnO1xuaW1wb3J0IHsgcnVudGltZUxvZ2dlciB9IGZyb20gJy4uL2xvZ2dlci5qcyc7XG5pbXBvcnQge1xuICBHVUVTVF9DT0RFX0VYRUNVVElPTl9TQU1QTEVfTElNSVQsXG4gIHR5cGUgR3Vlc3RDb2RlRXhlY3V0aW9uLFxuICB0eXBlIEd1ZXN0Q29kZVN0YXRzLFxufSBmcm9tICcuLi9zZXJpYWxpemF0aW9uL2hhcmRlbmVkLmpzJztcbmltcG9ydCB7XG4gIGRlaHlkcmF0ZVN0ZXBBcmd1bWVudHMsXG4gIGRlaHlkcmF0ZVN0ZXBFcnJvcixcbn0gZnJvbSAnLi4vc2VyaWFsaXphdGlvbi5qcyc7XG5pbXBvcnQgKiBhcyBBdHRyaWJ1dGUgZnJvbSAnLi4vdGVsZW1ldHJ5L3NlbWFudGljLWNvbnZlbnRpb25zLmpzJztcbmltcG9ydCB7IGdldEFib3J0U3RyZWFtSWRGcm9tVG9rZW4gfSBmcm9tICcuLi91dGlsLmpzJztcbmltcG9ydCB7IENPTVBVVEVfSU5TVEFOQ0VfSUQgfSBmcm9tICcuL2NvbXB1dGUtaW5zdGFuY2UuanMnO1xuaW1wb3J0IHtcbiAgZ2V0TWF4SW5saW5lU3RlcHMsXG4gIGlzQmF0Y2hUcmFuc2l0aW9uc0VuYWJsZWQsXG4gIGlzUmVzaWxpZW50U3RlcERpc3BhdGNoRW5hYmxlZCxcbiAgTUFYX0JBVENIX0ZBTk9VVF9FVkVOVFMsXG4gIE1BWF9SRVNJTElFTlRfU1RFUF9JTlBVVF9CWVRFUyxcbn0gZnJvbSAnLi9jb25zdGFudHMuanMnO1xuaW1wb3J0IHtcbiAgYWJzb3JiU2tpcHBlZFNsb3RSZXBvcnQsXG4gIGFwcGVuZEV2ZW50TG9nLFxuICB0eXBlIEV2ZW50Q3JlYXRvcixcbiAgdHlwZSBMb2FkZWRFdmVudExvZyxcbiAgbWF4RXZlbnRTbG90LFxuICBxdWV1ZU1lc3NhZ2UsXG4gIHNsb3RTbmFwc2hvdFBhcmFtcyxcbiAgc3RlcERpc3BhdGNoSWRlbXBvdGVuY3lLZXksXG59IGZyb20gJy4vaGVscGVycy5qcyc7XG5pbXBvcnQgeyBSZXBsYXlSZWNvdmVyeVJlcG9ydGVyIH0gZnJvbSAnLi9yZXBsYXktcmVjb3ZlcnktcmVwb3J0ZXIuanMnO1xuaW1wb3J0IHR5cGUgeyBQcmVjbGFpbWVkSW5saW5lU3RhcnQgfSBmcm9tICcuL3N0ZXAtZXhlY3V0b3IuanMnO1xuaW1wb3J0IHsgdW5zZXJpYWxpemFibGVTdGVwSW5wdXRQbGFjZWhvbGRlciB9IGZyb20gJy4vdW5zZXJpYWxpemFibGUtc3RlcC5qcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3VzcGVuc2lvbkhhbmRsZXJQYXJhbXMge1xuICBzdXNwZW5zaW9uOiBXb3JrZmxvd1N1c3BlbnNpb247XG4gIHdvcmxkOiBXb3JsZDtcbiAgcnVuOiBXb3JrZmxvd1J1bjtcbiAgc3Bhbj86IFNwYW47XG4gIHJlcXVlc3RJZD86IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBydW50aW1lJ3MgbG9hZGVkIGV2ZW50IGxvZy4gRXZlcnkgZXZlbnQgY3JlYXRpb24gdGhpcyBzdXNwZW5zaW9uIG1ha2VzXG4gICAqIG5hbWVzIHRoZSBwb3NpdGlvbiBpdCB3YXMgZGVyaXZlZCBmcm9tLCBzbyBhIGJhY2tlbmQgdGhhdCBoYXMgcmVjb3JkZWRcbiAgICogZXZlbnRzIHRoZSByZXBsYXkgZGlkIG5vdCBzZWUgY2FuIHJlcG9ydCB0aGVtIGJhY2sgb24gdGhlIHdyaXRlLCBvciwgaWZcbiAgICogaXQgd291bGQgcmF0aGVyIHJlZnVzZSB0aGFuIHJlcG9ydCwgcmVqZWN0IGl0IHdpdGggYSA0MTIuIEEgcmVqZWN0aW9uIGlzXG4gICAqIG5vdCByZXRyaWVkIGhlcmU6IHRoZSBldmVudCdzIGNvcnJlbGF0aW9uIGlkIHdhcyBtaW50ZWQgYnkgKnRoaXMqIHJlcGxheSdzXG4gICAqIHNlZWRlZCBzZXF1ZW5jZSwgc28gcmUtY29tbWl0dGluZyBpdCBhZ2FpbnN0IGEgY29ycmVjdGVkIGxvZyB3b3VsZCBwZXJzaXN0XG4gICAqIGFuIGV2ZW50IG5vIGNvcnJlY3QgcmVwbGF5IHByb2R1Y2VzLiBUaGUgY2FsbGVyIHJlc3RhcnRzIHRoZSByZXBsYXlcbiAgICogaW5zdGVhZC5cbiAgICpcbiAgICogRXh0ZW5kZWQgaW4gcGxhY2UgYnkgd2hhdCB0aG9zZSB3cml0ZXMgcmVwb3J0IGJhY2sg4oCUIHRoZSBldmVudHMgb24gc2xvdHNcbiAgICogdGhleSBza2lwcGVkIG92ZXIsIGFuZCAob24gdGhlIGhvb2sgY3JlYXRlKSB0aGUgaW5saW5lIGRlbHRhIHNpbmNlIGl0c1xuICAgKiBjdXJzb3IuIFdoZXRoZXIgdGhlIGxvZyBpcyBjb21wbGV0ZSBhZnRlcndhcmRzIGlzIGFuc3dlcmVkIGJ5XG4gICAqIHtAbGluayBTdXNwZW5zaW9uSGFuZGxlclJlc3VsdC5ldmVudExvZ0NhcnJpZWRGb3J3YXJkfS5cbiAgICovXG4gIGV2ZW50TG9nPzogTG9hZGVkRXZlbnRMb2c7XG4gIC8qKlxuICAgKiBUdXJibyBtb2RlIG9ubHk6IGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIG9uY2UgdGhlIGJhY2tncm91bmRlZFxuICAgKiBgcnVuX3N0YXJ0ZWRgIGhhcyBsYW5kZWQgKHRoZSBydW4gZXhpc3RzKS4gV2hlbiBwcmVzZW50LCBldmVyeSB3b3JsZCB3cml0ZVxuICAgKiB0aGlzIHN1c3BlbnNpb24gcGVyZm9ybXMgKGBob29rX2NyZWF0ZWRgLCBgd2FpdF9jcmVhdGVkYCwgZWFnZXIgb3ZlcmZsb3dcbiAgICogYHN0ZXBfY3JlYXRlZGAsIOKApikgaXMgZ2F0ZWQgb24gaXQgc28gdGhlIHdyaXRlIG5ldmVyIHJhY2VzIGFoZWFkIG9mIHRoZVxuICAgKiBydW4ncyBjcmVhdGlvbi4gVGhlIHB1cmUgaW5saW5lIGhvdCBwYXRoIGRlZmVycyBhbGwgb2YgaXRzIHN0ZXBzIGFuZCB3cml0ZXNcbiAgICogbm90aGluZyBoZXJlLCBzbyBpdCBuZXZlciBhd2FpdHMgdGhpcyBiYXJyaWVyLiBgdW5kZWZpbmVkYCBvdXRzaWRlIHR1cmJvLFxuICAgKiB3aGVyZSBgcnVuX3N0YXJ0ZWRgIHdhcyBhbHJlYWR5IGF3YWl0ZWQgdXAgZnJvbnQuXG4gICAqL1xuICBydW5SZWFkeUJhcnJpZXI/OiBQcm9taXNlPHVua25vd24+O1xuICAvKiogT25lLXNob3QgdGVsZW1ldHJ5IHJlcG9ydGVyLCBhY3RpdmF0ZWQgb25seSBhZnRlciByZXBsYXkgaGFzIHJlY292ZXJlZC4gKi9cbiAgcmVwbGF5UmVjb3ZlcnlSZXBvcnRlcj86IFJlcGxheVJlY292ZXJ5UmVwb3J0ZXI7XG4gIC8qKlxuICAgKiBSZXNpbGllbnQgc3RlcCBkaXNwYXRjaDogd2hlbiBwcm92aWRlZCAoYW5kIHRoZSBwZXItc3RlcCBlbGlnaWJpbGl0eSBnYXRlc1xuICAgKiBwYXNzLCBzZWUgdGhlIHN0ZXAgb3BzIGJlbG93KSwgZWFjaCBuZXdseSBjcmVhdGVkIG5vbi1pbmxpbmUgc3RlcCdzXG4gICAqIGBzdGVwX2NyZWF0ZWRgIHdyaXRlIGlzIHBhcmFsbGVsaXplZCB3aXRoIGl0cyBzdGVwLWV4ZWN1dGlvbiBxdWV1ZVxuICAgKiBwdWJsaXNoLCBhbmQgdGhlIHF1ZXVlIG1lc3NhZ2UgY2FycmllcyB0aGUgc2VyaWFsaXplZCBzdGVwIGlucHV0XG4gICAqIChgc3RlcElucHV0YCkgc28gdGhlIGNvbnN1bWVyIGNhbiBpZGVtcG90ZW50bHkgcmUtZW5zdXJlIHRoZSBldmVudCBpZiB0aGVcbiAgICogZGlyZWN0IHdyaXRlIGZhaWxlZCB0cmFuc2llbnRseS4gU3RlcHMgcXVldWVkIHRoaXMgd2F5IGFyZSByZXBvcnRlZCBpblxuICAgKiB7QGxpbmsgU3VzcGVuc2lvbkhhbmRsZXJSZXN1bHQucXVldWVkU3RlcENvcnJlbGF0aW9uSWRzfSBzbyB0aGUgY2FsbGVyXG4gICAqIHNraXBzIHRoZW0gaW4gaXRzIG93biBkaXNwYXRjaCBwYXNzLiBPbWl0dGVkIGJ5IGNhbGxlcnMgdGhhdCBtdXN0IG5vdFxuICAgKiBxdWV1ZSAodGVybWluYWwgZHJhaW4sIHRlc3RzKTsgY3JlYXRlcyB0aGVuIGJlaGF2ZSBleGFjdGx5IGFzIGJlZm9yZS5cbiAgICovXG4gIHN0ZXBEaXNwYXRjaD86IHtcbiAgICAvKiogVGhlIHVuaWZpZWQgd29ya2Zsb3cgcXVldWUgdGhpcyBydW4ncyBzdGVwIG1lc3NhZ2VzIGFyZSBwdWJsaXNoZWQgdG8uICovXG4gICAgcXVldWVOYW1lOiBWYWxpZFF1ZXVlTmFtZTtcbiAgICAvKipcbiAgICAgKiBMYXppbHkgcmVzb2x2ZXMgdGhlIHRyYWNlIGNhcnJpZXIgdG8gc3RhbXAgb24gdGhlIHN0ZXAgbWVzc2FnZXMuXG4gICAgICogQ2FsbGVkIGF0IG1vc3Qgb25jZSBwZXIgc3VzcGVuc2lvbiAobWVtb2l6ZWQgaGVyZSkuXG4gICAgICovXG4gICAgZ2V0VHJhY2VDYXJyaWVyOiAoKSA9PiBQcm9taXNlPFRyYWNlQ2Fycmllcj47XG4gIH07XG4gIC8qKlxuICAgKiBJbmxpbmUgc3RlcCBvd25lcnNoaXA6IHRoZSBxdWV1ZSBtZXNzYWdlIElEIG9mIHRoZSBpbnZvY2F0aW9uIHRoaXNcbiAgICogc3VzcGVuc2lvbiBydW5zIGluICh0aGUgcXVldWUgaGFuZGxlcidzIG1ldGEpLiBXaGVuIHByZXNlbnQgQU5EIHRoZVxuICAgKiBiYXRjaGVkIGZhbi1vdXQgZW5nYWdlcywgdGhlIGxhenktaW5saW5lIHN0ZXBzJyBkZWZlcnJlZCB3cml0ZXMgYXJlXG4gICAqIGZvbGRlZCBpbnRvIHRoZSBiYXRjaCBhcyBgc3RlcF9jcmVhdGVkYCArIGBzdGVwX3N0YXJ0ZWRgIHBhaXJzICh0aGVcbiAgICogc3RhcnRlZCByb3cgc3RhbXBlZCB3aXRoIHRoaXMgSUQsIGV4YWN0bHkgbGlrZSB0aGUgbGF6eSBjbGFpbSBpdFxuICAgKiByZXBsYWNlcyksIHByZS1jbGFpbWluZyB0aGUgc3RlcHMgdGhlIGNhbGxlciBpcyBhYm91dCB0byBydW4gaW5saW5lLiBTZWVcbiAgICoge0BsaW5rIFN1c3BlbnNpb25IYW5kbGVyUmVzdWx0LmlubGluZUNsYWltc30uIENhbGxlcnMgdGhhdCBuZXZlclxuICAgKiBpbmxpbmUtZXhlY3V0ZSAodGVybWluYWwgZHJhaW4pIG9taXQgaXQsIGtlZXBpbmcgdGhlaXIgbGF6eSBzdGVwcyBvbiB0aGVcbiAgICogcGxhaW4gZGVmZXJyZWQgcGF0aC5cbiAgICovXG4gIG93bmVyTWVzc2FnZUlkPzogc3RyaW5nO1xuICAvKipcbiAgICogTGV0cyB0aGUgYmF0Y2hlZCBmYW4tb3V0IHJldHVybiBiZWZvcmUgZXZlcnkgY2h1bmsgaGFzIGNvbW1pdHRlZDogb25seVxuICAgKiB0aGUgY2h1bmsgY2FycnlpbmcgdGhlIHByZS1jbGFpbWVkIGlubGluZSBwYWlycyBnYXRlcyB0aGUgaGFuZGxlcidzXG4gICAqIHJldHVybiAoaXRzIGNsYWltcyBhcmUgd2hhdCB0aGUgY2FsbGVyIHN0YXJ0cyBib2RpZXMgZnJvbSksIHdoaWxlIHRoZVxuICAgKiB0cmFpbGluZyBjaHVua3MnIGNvbW1pdHMgKGFuZCBldmVyeSBjaHVuaydzIGluLWZsdXNoIHN0ZXAtbWVzc2FnZVxuICAgKiBwdWJsaXNoZXMpIHJpZGUge0BsaW5rIFN1c3BlbnNpb25IYW5kbGVyUmVzdWx0LmRlZmVycmVkQmF0Y2hXb3JrfS4gQVxuICAgKiBjYWxsZXIgdGhhdCBvcHRzIGluIE1VU1QgYXdhaXQgdGhhdCBwcm9taXNlIGJlZm9yZSBhY2tpbmcgaXRzIGRlbGl2ZXJ5OlxuICAgKiB0aGUgZHVyYWJpbGl0eSBjb250cmFjdCAoXCJldmVyeSBjcmVhdGUgZHVyYWJsZSBiZWZvcmUgYWNrXCIpIG1vdmVzIGZyb21cbiAgICogdGhlIGhhbmRsZXIncyByZXR1cm4gdG8gdGhhdCBqb2luLCBhbmQgbm90aGluZyBlbHNlIHJlLWRyaXZlcyBhIGxvc3RcbiAgICogdHJhaWxpbmcgY2h1bmsuIENhbGxlcnMgdGhhdCBkb24ndCBvcHQgaW4gKHRlcm1pbmFsIGRyYWluLCBkZWZhdWx0KVxuICAgKiBrZWVwIHRoZSBldmVyeXRoaW5nLWR1cmFibGUtYXQtcmV0dXJuIGJlaGF2aW9yLlxuICAgKi9cbiAgYWxsb3dEZWZlcnJlZEJhdGNoV29yaz86IGJvb2xlYW47XG59XG5cbi8qKlxuICogUmVzdWx0IG9mIGhhbmRsaW5nIGEgc3VzcGVuc2lvbi4gUmV0dXJucyBwZW5kaW5nIHN0ZXAgaXRlbXMgc28gdGhlIGNhbGxlclxuICogY2FuIGRlY2lkZSB3aGljaCB0byBleGVjdXRlIGlubGluZSB2cyBxdWV1ZSB0byBiYWNrZ3JvdW5kLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFN1c3BlbnNpb25IYW5kbGVyUmVzdWx0IHtcbiAgLyoqIFBlbmRpbmcgc3RlcCBpdGVtcyB3aXRoIGV2ZW50cyBjcmVhdGVkIGJ1dCBOT1QgcXVldWVkICovXG4gIHBlbmRpbmdTdGVwczogU3RlcEludm9jYXRpb25RdWV1ZUl0ZW1bXTtcbiAgLyoqXG4gICAqIENvcnJlbGF0aW9uIElEcyBmb3Igd2hpY2ggdGhpcyBzdXNwZW5zaW9uIGNhbGwgYWN0dWFsbHkgd3JvdGUgdGhlXG4gICAqIHN0ZXBfY3JlYXRlZCBldmVudCAoYXMgb3Bwb3NlZCB0byBjYXRjaGluZyBFbnRpdHlDb25mbGljdEVycm9yIGJlY2F1c2VcbiAgICogYSBjb25jdXJyZW50IGhhbmRsZXIgd3JvdGUgaXQgZmlyc3QpLiBPbmx5IHRoZSBoYW5kbGVyIHRoYXQgd3JvdGUgdGhlXG4gICAqIHN0ZXBfY3JlYXRlZCBldmVudCBzaG91bGQgcXVldWUgLyBpbmxpbmUtZXhlY3V0ZSB0aGUgc3RlcDsgdGhpc1xuICAgKiBndWFyYW50ZWVzIGEgc2luZ2xlIG93bmVyIHBlciBzdGVwLCBldmVuIHdoZW4gbXVsdGlwbGUgaGFuZGxlcnMgcmFjZVxuICAgKiBpbnRvIHRoZSBzYW1lIGJhdGNoIGJvdW5kYXJ5LlxuICAgKi9cbiAgY3JlYXRlZFN0ZXBDb3JyZWxhdGlvbklkczogU2V0PHN0cmluZz47XG4gIC8qKlxuICAgKiBDb3JyZWxhdGlvbiBJRHMgb2Ygc3RlcHMgd2hvc2UgYXJndW1lbnRzIGZhaWxlZCB0byBzZXJpYWxpemUuIEVhY2ggd2FzXG4gICAqIGZpbmFsaXplZCBoZXJlIGFzIGBzdGVwX2NyZWF0ZWRgICh3aXRoIGEgcGxhY2Vob2xkZXIgaW5wdXQ7IHRoZSByZWFsXG4gICAqIGlucHV0IGlzIHByZWNpc2VseSB3aGF0IHJlZnVzZWQgdG8gc2VyaWFsaXplKSBmb2xsb3dlZCBieSBgc3RlcF9mYWlsZWRgXG4gICAqIGNhcnJ5aW5nIHRoZSBTZXJpYWxpemF0aW9uRXJyb3IsIHNvIHRoZSBuZXh0IHJlcGxheSByZWplY3RzIHRoZSBzdGVwJ3NcbiAgICogcHJvbWlzZSBhbmQgYSB0cnkvY2F0Y2ggYXJvdW5kIHRoZSBzdGVwIGNhbGwgb2JzZXJ2ZXMgdGhlIGVycm9yLFxuICAgKiBleGFjdGx5IGxpa2UgYSBzdGVwLWJvZHkgZmFpbHVyZS4gTm8gc3RlcC1leGVjdXRpb24gbWVzc2FnZSBpc1xuICAgKiBkaXNwYXRjaGVkIGZvciB0aGVzZSwgc28gdGhlIGNhbGxlciBNVVNUIGZvcmNlIGFuIGluLXByb2Nlc3MgcmVwbGF5OlxuICAgKiB3aGVuIHRoZSBmYWlsZWQgc3RlcCB3YXMgdGhlIG9ubHkgcGVuZGluZyB3b3JrLCBub3RoaW5nIGVsc2Ugd2lsbCBldmVyXG4gICAqIHJlLWludm9rZSB0aGUgcnVuIHRvIG9ic2VydmUgdGhlIHRlcm1pbmFsIGV2ZW50LlxuICAgKi9cbiAgZmFpbGVkU3RlcENvcnJlbGF0aW9uSWRzOiBTZXQ8c3RyaW5nPjtcbiAgLyoqXG4gICAqIENvcnJlbGF0aW9uIElEcyBvZiBzdGVwcyB0aGlzIHN1c3BlbnNpb24gY2FsbCBhbHJlYWR5IHB1Ymxpc2hlZFxuICAgKiBzdGVwLWV4ZWN1dGlvbiBxdWV1ZSBtZXNzYWdlcyBmb3IsIHZpYSByZXNpbGllbnQgc3RlcCBkaXNwYXRjaCAodGhlXG4gICAqIGBzdGVwX2NyZWF0ZWRgIHdyaXRlIHBhcmFsbGVsaXplZCB3aXRoIGEgYHN0ZXBJbnB1dGAtY2FycnlpbmcgcXVldWVcbiAgICogcHVibGlzaCkuIFRoZSBjYWxsZXIgTVVTVCBOT1QgZGlzcGF0Y2ggdGhlc2UgYWdhaW46IHRoZSBtZXNzYWdlIGlzXG4gICAqIGFscmVhZHkgb3V0IChhIGR1cGxpY2F0ZSB3b3VsZCBiZSBkZWR1cGVkIGJ5IGl0cyBpZGVtcG90ZW5jeSBrZXksIGJ1dFxuICAgKiBjb3N0cyBhIHdhc3RlZCByb3VuZC10cmlwKS4gRW1wdHkgd2hlbiB7QGxpbmsgU3VzcGVuc2lvbkhhbmRsZXJQYXJhbXMuc3RlcERpc3BhdGNofVxuICAgKiB3YXMgbm90IHByb3ZpZGVkIG9yIG5vIHN0ZXAgd2FzIGVsaWdpYmxlLlxuICAgKi9cbiAgcXVldWVkU3RlcENvcnJlbGF0aW9uSWRzOiBTZXQ8c3RyaW5nPjtcbiAgLyoqXG4gICAqIEhvdyBtYW55IGV2ZW50cyB0aGlzIHBoYXNlJ3Mgd3JpdGVzIHJlcG9ydGVkIGJhY2sgYXMgb2NjdXB5aW5nIHNsb3RzIHRoZXlcbiAgICogc2tpcHBlZCBvdmVyLCBhbHJlYWR5IG1lcmdlZCBpbnRvIHRoZSBjYWxsZXIncyBgZXZlbnRMb2cuZXZlbnRzYC4gTm9uemVyb1xuICAgKiBtZWFucyB0aGUgYXJyYXkgd2FzIHJlb3JkZXJlZCB0byByZXN0b3JlIHNsb3Qgb3JkZXIsIHNvIGFueSBpbmRleCB0aGVcbiAgICogY2FsbGVyIGNhY2hlZCBpbnRvIGl0IChwYXlsb2FkIHByZXdhcm0gc2NhbiBwb3NpdGlvbikgaXMgc3RhbGUuXG4gICAqL1xuICByZXBvcnRlZEV2ZW50Q291bnQ6IG51bWJlcjtcbiAgLyoqXG4gICAqIFRoZSBzdGVwcyB3aG9zZSBgc3RlcF9jcmVhdGVkYCB3cml0ZXMgd2VyZSBpbnRlbnRpb25hbGx5IGRlZmVycmVkIHNvIHRoZVxuICAgKiBjYWxsZXIgY2FuIHJ1biB0aGVtIGlubGluZSB2aWEgbGF6eSBgc3RlcF9zdGFydGVkYCBldmVudHMgKHdoaWNoIGNyZWF0ZVxuICAgKiB0aGUgc3RlcCBvbiB0aGUgZmx5KSwgc2F2aW5nIG9uZSB3b3JsZCByb3VuZC10cmlwIHBlciBpbmxpbmUgc3RlcC4gVXAgdG9cbiAgICogYGdldE1heElubGluZVN0ZXBzKClgIHN0ZXBzIGFyZSBkZWZlcnJlZDsgdGhlIGNhbGxlciBydW5zIHRoZW0gaW5saW5lIGluXG4gICAqIHBhcmFsbGVsIGFuZCBxdWV1ZXMgdGhlIHJlc3QuIEVtcHR5IHdoZW4gbm8gc3RlcCB3YXMgZGVmZXJyZWQgKG5vdGhpbmdcbiAgICogcGVuZGluZywgb3IgYSBgaG9vay5nZXRDb25mbGljdCgpYCBhd2FpdGVyIGlzIHByZXNlbnQgc28gbm90aGluZyBpc1xuICAgKiBleGVjdXRlZCBpbmxpbmUpLiBUaGUgY2FsbGVyIHBhc3NlcyBlYWNoIGBkZWh5ZHJhdGVkSW5wdXRgIHN0cmFpZ2h0IHRvXG4gICAqIGBleGVjdXRlU3RlcGAsIHdoaWNoIHNlbmRzIGl0IGFzIHRoZSBgc3RlcF9zdGFydGVkYCBwYXlsb2FkLiBUaGUgYXRvbWljXG4gICAqIGNyZWF0ZS1jbGFpbSBpbnNpZGUgZWFjaCBgc3RlcF9zdGFydGVkYCBpcyB0aGUgZXhhY3RseS1vbmUtb3duZXIgZ2F0ZSB0aGF0XG4gICAqIHRoZSBzdGFuZGFsb25lIGBzdGVwX2NyZWF0ZWRgIHByb3ZpZGVkIGJlZm9yZTogdGhlIGxvc2VyIG9mIHRoZSByYWNlIGdldHNcbiAgICogYEVudGl0eUNvbmZsaWN0RXJyb3JgIOKGkiBgc2tpcHBlZGAgYW5kIGRvZXMgbm90IHJ1biB0aGUgYm9keS5cbiAgICovXG4gIGxhenlJbmxpbmVTdGVwczogQXJyYXk8e1xuICAgIGNvcnJlbGF0aW9uSWQ6IHN0cmluZztcbiAgICBzdGVwTmFtZTogc3RyaW5nO1xuICAgIGRlaHlkcmF0ZWRJbnB1dDogU2VyaWFsaXplZERhdGE7XG4gIH0+O1xuICAvKipcbiAgICogUHJlLWNsYWltZWQgaW5saW5lIHN0YXJ0cywgYnkgY29ycmVsYXRpb24gaWQ6IHRoZSBwZXItc3RlcCB2ZXJkaWN0cyBvZlxuICAgKiB0aGUgYHN0ZXBfY3JlYXRlZGAgKyBgc3RlcF9zdGFydGVkYCBwYWlycyB0aGUgYmF0Y2hlZCBmYW4tb3V0IGNvbW1pdHRlZFxuICAgKiBmb3IgdGhlIGxhenktaW5saW5lIHN0ZXBzLiBBIHN0ZXAgd2l0aCBhbiBlbnRyeSBoZXJlIGlzIHBhc3NlZCB0b1xuICAgKiBgZXhlY3V0ZVN0ZXBgIGFzIGBwcmVjbGFpbWVkU3RhcnRgIElOU1RFQUQgb2YgYGxhenlTdGVwSW5wdXRgOiBpdHNcbiAgICogaW5wdXQgYWxyZWFkeSByb2RlIHRoZSBwYWlyLCBhbmQgdGhlIGNsYWltIGlzIHNldHRsZWQ6IGBvd25lZDogdHJ1ZWBcbiAgICogY2FycmllcyB0aGUgc3RhcnRlZCBhdHRlbXB0LTEgZW50aXR5IChpbnB1dCByZS1hdHRhY2hlZCkgc28gdGhlIGJvZHlcbiAgICogcnVucyBzdHJhaWdodCBvZmYgdGhlIGJhdGNoIGNvbW1pdCB3aXRoIG5vIHN0YXJ0IHdyaXRlIG9mIGl0cyBvd247XG4gICAqIGBvd25lZDogZmFsc2VgIGxvc3QgdGhlIHBhaXIncyBhdG9taWMgY3JlYXRlLWNsYWltIHRvIGEgY29uY3VycmVudFxuICAgKiB3cml0ZXIsIGFuZCBleGVjdXRlU3RlcCByZXR1cm5zIGBza2lwcGVkYCB3aXRob3V0IHJ1bm5pbmcgdGhlIGJvZHksXG4gICAqIHRoZSBzYW1lIG91dGNvbWUgYXMgbG9zaW5nIHRoZSBsYXp5IGNsYWltLiBFbXB0eSB3aGVuZXZlciB0aGUgZm9sZCBkaWRcbiAgICogbm90IGVuZ2FnZSAoYmF0Y2hpbmcgb2ZmLCBubyBgb3duZXJNZXNzYWdlSWRgLCBvciB0aGUgbG9uZS1pbmxpbmUgY2FzZSxcbiAgICogd2hpY2gga2VlcHMgdGhlIG9wdGltaXN0aWMgbGF6eSBwYXRoIGFuZCBpdHMgY2xhaW0vYm9keSBvdmVybGFwKS5cbiAgICpcbiAgICogQ3Jhc2ggd2luZG93OiB0aGUgcGFpciBjb21taXRzIGJlZm9yZSB0aGUgY2FsbGVyIHJ1bnMgdGhlIGJvZHksIHNvIGFcbiAgICogY3Jhc2ggYmV0d2VlbiB0aGVtIGxlYXZlcyBhIHN0YXJ0ZWQgc3RlcCBzdGFtcGVkIHdpdGggdGhpcyBtZXNzYWdlJ3NcbiAgICogSUQuIFJlZGVsaXZlcnkgb2YgdGhlIHNhbWUgbWVzc2FnZSByZS1leGVjdXRlcyBpdCB2aWEgdGhlIG93bmVkLXJlY292ZXJ5XG4gICAqIHBhdGgsIHRoZSBleGFjdCBtYWNoaW5lcnkgdGhlIGxhenkgY2xhaW0ncyBjcmFzaCB3aW5kb3cgYWxyZWFkeSB1c2VzLlxuICAgKi9cbiAgaW5saW5lQ2xhaW1zOiBNYXA8c3RyaW5nLCBQcmVjbGFpbWVkSW5saW5lU3RhcnQ+O1xuICAvKipcbiAgICogVGhlIGhpZ2hlc3Qgc2xvdCB0aGUgYmF0Y2hlZCBmYW4tb3V0IGNvbW1pdHRlZCwgd2hlbiBpdCByYW4uIFRoZSBiYXRjaCdzXG4gICAqIG93biBldmVudHMgYXJlIG5vdCBpbiB0aGUgY2FsbGVyJ3MgbG9hZGVkIGxvZyAodGhlIG5leHQgcmVsb2FkIHBpY2tzXG4gICAqIHRoZW0gdXApLCBzbyB0aGUgY2FsbGVyIGZvbGRzIHRoaXMgY2VpbGluZyBpbnRvIHRoZSBzbG90IHNuYXBzaG90IGl0XG4gICAqIGhhbmRzIHRoZSBpbmxpbmUgZXhlY3V0aW9uczsgb3RoZXJ3aXNlIGV2ZXJ5IGlubGluZSB0ZXJtaW5hbCB3cml0ZVxuICAgKiB3b3VsZCBuYW1lIGEgcHJlLWJhdGNoIHBvc2l0aW9uIGFuZCBiZSBhbnN3ZXJlZCB3aXRoIGEgc2tpcHBlZC1zbG90XG4gICAqIHJlcG9ydCBlY2hvaW5nIHRoZSBldmVudHMgdGhpcyBzdXNwZW5zaW9uIGp1c3Qgd3JvdGUuIFVuZGVyXG4gICAqIHtAbGluayBTdXNwZW5zaW9uSGFuZGxlclBhcmFtcy5hbGxvd0RlZmVycmVkQmF0Y2hXb3JrfSB0aGlzIGNvdmVycyB0aGVcbiAgICogY2h1bmtzIHRoYXQgaGFkIGNvbW1pdHRlZCBieSB0aGUgaGFuZGxlcidzIHJldHVybiAoYWx3YXlzIHRoZSBwYWlyXG4gICAqIGNodW5rKTsgYSB0cmFpbGluZyBjaHVuayB0aGF0IGNvbW1pdHMgbGF0ZXIgaXMgZWNob2VkIGJhY2sgb24gdGhlXG4gICAqIHRlcm1pbmFsIHdyaXRlcyBsaWtlIGFueSBmb3JlaWduIGV2ZW50OiByZXBvcnRzIHRoZSBleGVjdXRvciByZWFkcyBmb3JcbiAgICogcG9zaXRpb24gYW5kIGRpc2NhcmRzLlxuICAgKlxuICAgKiBTbyB0aGUgZWNobyBpcyBvbmx5IGZ1bGx5IHN1cHByZXNzZWQgZm9yIGEgU0lOR0xFLWNodW5rIGZvbGQuIE9uIGFcbiAgICogbXVsdGktY2h1bmsgZmFuLW91dCB0aGUgYm9kaWVzIHN0YXJ0IG9mZiB0aGUgcGFpciBjaHVuayB3aGlsZSB0cmFpbGluZ1xuICAgKiBjaHVua3MgYXJlIHN0aWxsIGluIGZsaWdodCwgYW5kIGFuIGlubGluZSB0ZXJtaW5hbCB3cml0ZSBpc3N1ZWQgaW4gdGhhdFxuICAgKiB3aW5kb3cgc3RpbGwgbmFtZXMgYSBwb3NpdGlvbiBiZWxvdyB0aGVtIGFuZCBzdGlsbCBkcmF3cyBhIHJlcG9ydCBmb3JcbiAgICogdGhlaXIgZXZlbnRzLiBCb3VuZGVkICh0cmFpbGluZyBjaHVua3Mgb25seSwgbGFyZ2UgZmFuLW91dHMgb25seSkgYW5kXG4gICAqIHNlbGYtY29ycmVjdGluZyBvbiB0aGUgbmV4dCByZWxvYWQsIGFuZCByZWNvcmRlZCBzbyBhIHJlcG9ydCBzZWVuIHRoZXJlXG4gICAqIHJlYWRzIGFzIGV4cGVjdGVkIHJhdGhlciB0aGFuIGFzIGEgYnVnLlxuICAgKi9cbiAgYmF0Y2hDb21taXR0ZWRTbG90Q2VpbGluZz86IG51bWJlcjtcbiAgLyoqXG4gICAqIFRoZSBiYXRjaGVkIGZhbi1vdXQncyBkZWZlcnJlZCB3b3JrLCBwcmVzZW50IG9ubHkgd2hlbiB0aGUgY2FsbGVyIG9wdGVkXG4gICAqIGluIHZpYSB7QGxpbmsgU3VzcGVuc2lvbkhhbmRsZXJQYXJhbXMuYWxsb3dEZWZlcnJlZEJhdGNoV29ya30gYW5kXG4gICAqIHRyYWlsaW5nIHdvcmsgZXhpc3RzOiB0aGUgY29tbWl0cyBvZiBldmVyeSBjaHVuayBleGNlcHQgdGhlIHBhaXIgY2h1bmssXG4gICAqIHBsdXMgZXZlcnkgY2h1bmsncyBzdGVwLW1lc3NhZ2UgcHVibGlzaGVzIChlYWNoIGNoYWluZWQgb24gSVRTIE9XTlxuICAgKiBjaHVuaydzIGNvbW1pdCwgc28gcHVibGlzaC1hZnRlci1jcmVhdGUgaG9sZHMgcGVyIHN0ZXApLiBUaGUgY2FsbGVyXG4gICAqIE1VU1QgYXdhaXQgaXQgYmVmb3JlIGFja2luZzogYSByZWplY3Rpb24gaGVyZSBpcyBhIGZhaWxlZCBzdXNwZW5zaW9uXG4gICAqIHdyaXRlIGFuZCBmYWlscyB0aGUgZGVsaXZlcnkgZXhhY3RseSBhcyBpdCB3b3VsZCBoYXZlIGF0IHRoZSBoYW5kbGVyJ3NcbiAgICogcmV0dXJuLiBTdGVwcyB3aG9zZSBtZXNzYWdlcyB0aGlzIHdvcmsgcHVibGlzaGVzIGFyZSBhbHJlYWR5IGluXG4gICAqIHtAbGluayBxdWV1ZWRTdGVwQ29ycmVsYXRpb25JZHN9IGF0IHJldHVybiB0aW1lLlxuICAgKi9cbiAgZGVmZXJyZWRCYXRjaFdvcms/OiBQcm9taXNlPHZvaWQ+O1xuICAvKipcbiAgICogVGhlIHNvb25lc3QgcGVuZGluZyB3YWl0LCBpZiBhbnk6IHNlY29uZHMgdW50aWwgaXQgZWxhcHNlcyBhbmQgdGhlXG4gICAqIGNvcnJlbGF0aW9uSWQgb2YgdGhlIHdhaXQgdGhhdCBwcm9kdWNlZCB0aGF0IHRpbWVvdXQuIFRoZVxuICAgKiBjb3JyZWxhdGlvbklkIHNlZWRzIHRoZSBpZGVtcG90ZW5jeSBrZXkgZm9yIHRoZSB3YWl0LWNvbnRpbnVhdGlvblxuICAgKiBxdWV1ZSBtZXNzYWdlIHNvIHRoYXQgcmVwZWF0ZWQgc3VzcGVuc2lvbiBwYXNzZXMgb3ZlciB0aGUgc2FtZVxuICAgKiBwZW5kaW5nIHdhaXQgY29sbGFwc2UgaW50byBhIHNpbmdsZSBkZWxheWVkIGNvbnRpbnVhdGlvbi5cbiAgICovXG4gIHdhaXRUaW1lb3V0PzogeyBzZWNvbmRzOiBudW1iZXI7IGNvcnJlbGF0aW9uSWQ6IHN0cmluZyB9O1xuICAvKipcbiAgICogV2hldGhlciBhIGhvb2sgY3JlYXRlIGNvbW1pdHRlZCBhIGBob29rX2NvbmZsaWN0YCDigJQgdGhlIHRva2VuIHdhcyBhbHJlYWR5XG4gICAqIGNsYWltZWQsIHNvIHRoaXMgcnVuJ3MgaG9vayB3YXMgbmV2ZXIgY3JlYXRlZCBhbmQgdGhlIHdvcmtmbG93IG11c3RcbiAgICogb2JzZXJ2ZSB0aGUgY29uZmxpY3QgYmVmb3JlIGFueXRoaW5nIGVsc2UgdGhpcyBzdXNwZW5zaW9uIHNjaGVkdWxlZCBydW5zLlxuICAgKiBUaGUgY2FsbGVyIGFuc3dlcnMgaXQgYnkgYWR2YW5jaW5nIHRoZSB3b3JrZmxvdyBvdmVyIHRoZSBjb21taXR0ZWQgZXZlbnQuXG4gICAqL1xuICBoYXNIb29rQ29uZmxpY3Q6IGJvb2xlYW47XG4gIC8qKiBXaGV0aGVyIGEgYGhvb2suZ2V0Q29uZmxpY3QoKWAgYXdhaXRlciBuZWVkcyB0aGUgd29ya2Zsb3cgdG8gY29udGludWUgaW1tZWRpYXRlbHkgKi9cbiAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbjogYm9vbGVhbjtcbiAgLyoqXG4gICAqIENvcnJlbGF0aW9uIGlkcyBvZiB0aGUgaG9va3MgdGhpcyBzdXNwZW5zaW9uIGNvbW1pdHRlZCBhIGBob29rX2NyZWF0ZWRgXG4gICAqIGZvciB3aGlsZSBhIGBob29rLmdldENvbmZsaWN0KClgIGF3YWl0ZXIgd2FzIHdhaXRpbmcgb24gaXQg4oCUIHRoZSBldmVudHNcbiAgICogdGhhdCByZXNvbHZlIHRob3NlIGF3YWl0ZXJzIG9uIHRoZSBuZXh0IHBhc3MuIEVtcHR5IGV4YWN0bHkgd2hlblxuICAgKiB7QGxpbmsgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbn0gaXMgZmFsc2UuXG4gICAqXG4gICAqIFJlcG9ydGVkIGJ5IGlkLCBub3QganVzdCBjb3VudGVkLCBzbyBhIGNhbGxlciB0aGF0IGNvbnRpbnVlcyBpbiB0aGlzXG4gICAqIHByb2Nlc3MgY2FuIHRlbGwgYSBjb250aW51YXRpb24gdGhhdCBnb3Qgc29tZXdoZXJlIGZyb20gb25lIHRoYXQgaXNcbiAgICogcmVwZWF0aW5nOiBhIHdvcmtmbG93IG1heSBjcmVhdGUgb25lIGF3YWl0ZWQgaG9vayBhZnRlciBhbm90aGVyLCBhbmQgZWFjaFxuICAgKiBuZXcgaWQgaXMgYSBwYXNzIHRoYXQgbWFkZSBwcm9ncmVzcywgd2hpbGUgdGhlIHNhbWUgaWQgY29taW5nIGJhY2sgbWVhbnNcbiAgICogdGhlIHBhc3MgcmFuIG92ZXIgYSBsb2cgdGhhdCBzdGlsbCBkaWQgbm90IGhvbGQgaXRzIGV2ZW50IGFuZCBjb250aW51aW5nXG4gICAqIGFnYWluIGNhbm5vdCBjaGFuZ2UgdGhhdC5cbiAgICovXG4gIGF3YWl0ZWRIb29rQ29ycmVsYXRpb25JZHM6IHN0cmluZ1tdO1xuICAvKipcbiAgICogQ29ycmVsYXRpb24gaWRzIG9mIHRoZSBob29rcyB3aG9zZSBjcmVhdGUgY29tbWl0dGVkIGEgYGhvb2tfY29uZmxpY3RgLlxuICAgKiBFbXB0eSBleGFjdGx5IHdoZW4ge0BsaW5rIGhhc0hvb2tDb25mbGljdH0gaXMgZmFsc2UuXG4gICAqXG4gICAqIEJ5IGlkIGZvciB0aGUgc2FtZSByZWFzb24gYXMge0BsaW5rIGF3YWl0ZWRIb29rQ29ycmVsYXRpb25JZHN9LCBhbmRcbiAgICogYWdhaW5zdCB0aGUgc2FtZSBoYXphcmQ6IGEgY29uZmxpY3QgaXMgcmVzb2x2ZWQgYnkgdGhlIGBob29rX2NvbmZsaWN0YFxuICAgKiB0aGlzIHN1c3BlbnNpb24gY29tbWl0dGVkLCBhbmQgdW50aWwgdGhlIHdvcmtmbG93IG9ic2VydmVzIGl0IHRoZSBob29rXG4gICAqIHN0YXlzIGluIHRoZSBpbnZvY2F0aW9ucyBxdWV1ZSBhbmQgdGhlIG5leHQgcGFzcyB3cml0ZXMgdGhlIGNyZWF0ZSBhZ2Fpbi5cbiAgICogQSBmcmVzaCBpZCBpcyBwcm9ncmVzczsgdGhlIHNhbWUgaWQgY29taW5nIGJhY2sgaXMgYSBwYXNzIHRoYXQgcmFuIG92ZXIgYVxuICAgKiBsb2cgd2hpY2ggc3RpbGwgZGlkIG5vdCBob2xkIHRoZSBldmVudCwgc28gY29udGludWluZyBhZ2FpbiBjYW5ub3QgY2hhbmdlXG4gICAqIHRoYXQuXG4gICAqL1xuICBob29rQ29uZmxpY3RDb3JyZWxhdGlvbklkczogc3RyaW5nW107XG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSBjYWxsZXIncyBgZXZlbnRMb2dgIG5vdyBob2xkcyBldmVyeSBldmVudCB0aGlzIHN1c3BlbnNpb25cbiAgICogY29tbWl0dGVkLCBzbyBhIGNhbGxlciB0aGF0IGNvbnRpbnVlcyBpbiB0aGlzIHByb2Nlc3MgY2FuIHJlcGxheSDigJQgb3JcbiAgICogcmVzdW1lIGEgcmV0YWluZWQgVk0g4oCUIHN0cmFpZ2h0IG9mZiBpdCB3aXRoIG5vIHJlYWQuXG4gICAqXG4gICAqIFRydWUgb25seSB3aGVuIHRoZSBob29rIGNyZWF0ZSdzIGlubGluZSBkZWx0YSBjYW1lIGJhY2sgY29tcGxldGUgYW5kIHdhc1xuICAgKiBmb2xkZWQgaW4gKHNlZSBgaG9va0RlbHRhQ3Vyc29yYCBiZWxvdyksIGFuZCBub3RoaW5nIGVsc2UgaW4gdGhpc1xuICAgKiBzdXNwZW5zaW9uIHdyb3RlIGFuIGV2ZW50LiBGYWxzZSB3aGVuZXZlciBhIHJlYWQgaXMgbmVlZGVkIGZpcnN0OiBub1xuICAgKiBkZWx0YSB3YXMgYXNrZWQgZm9yIG9yIHJldHVybmVkLCBpdCB3YXMgdHJ1bmNhdGVkLCBvciBhIHN0ZXAgLyB3YWl0IC9cbiAgICogYXR0cmlidXRlIC8gYWJvcnQgd3JpdGUgbGFuZGVkIGFib3ZlIGl0IGFuZCBpcyB0aGVyZWZvcmUgbm90IGluIGl0LlxuICAgKlxuICAgKiBJbmRpZmZlcmVudCB0byB3aGljaCBldmVudCB0aGUgY3JlYXRlIGNvbW1pdHRlZDogdGhlIGRlbHRhIGlzIHRoZSBzbGljZVxuICAgKiBvZiB0aGUgbG9nIGFmdGVyIHRoZSBjYWxsZXIncyBjdXJzb3IgZWl0aGVyIHdheSwgc28gaXQgY2FycmllcyBhXG4gICAqIGBob29rX2NvbmZsaWN0YCBleGFjdGx5IGFzIGl0IGNhcnJpZXMgYSBgaG9va19jcmVhdGVkYC5cbiAgICovXG4gIGV2ZW50TG9nQ2FycmllZEZvcndhcmQ6IGJvb2xlYW47XG4gIC8qKiBXaGV0aGVyIG5hdGl2ZSB3b3JrZmxvdyBhdHRyaWJ1dGUgZXZlbnRzIHdlcmUgd3JpdHRlbiBmb3IgcmVwbGF5LiAqL1xuICBoYXNBdHRyaWJ1dGVFdmVudHM6IGJvb2xlYW47XG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoaXMgc3VzcGVuc2lvbiBjcmVhdGVkIGFueSBob29rIChgaG9va19jcmVhdGVkYCkgZXZlbnRzLiBVbmxpa2VcbiAgICogYGhhc0hvb2tDb25mbGljdGAgLyBgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbmAsIHRoaXMgaXMgdHJ1ZSBldmVuIGZvciBhIHBsYWluXG4gICAqIGZpcmUtYW5kLWZvcmdldCBob29rIHdpdGggbm8gY29uZmxpY3QgYW5kIG5vIGF3YWl0ZXIuIFR1cmJvIG1vZGUgdXNlcyBpdCB0b1xuICAgKiBkZXRlY3QgXCJhIGhvb2sgd2FzIGNyZWF0ZWQgdGhpcyBzdXNwZW5zaW9uXCIgYW5kIHN0b3AgZm9yY2luZyBvcHRpbWlzdGljXG4gICAqIGlubGluZSBzdGFydCAoYSBob29rIGludHJvZHVjZXMgbGF0ZXIgcmVzdW1lIGludm9jYXRpb25zIHRoYXQgY291bGQgcmFjZSkuXG4gICAqL1xuICBoYXNIb29rRXZlbnRzOiBib29sZWFuO1xuICAvKipcbiAgICogV2FsbC1jbG9jayBtcyBzcGVudCBjb21taXR0aW5nIHRoaXMgc3VzcGVuc2lvbidzIGBob29rX2NyZWF0ZWRgIGV2ZW50c1xuICAgKiAoMCB3aGVuIGl0IGNyZWF0ZWQgbm9uZSkuIFRoZSBjYWxsZXIgYWNjdW11bGF0ZXMgdGhpcyBhY3Jvc3MgaXRlcmF0aW9uc1xuICAgKiBhbmQgc3VidHJhY3RzIGl0IGZyb20gdGhlIFRURlMgbGF0ZW5jeSBtZWFzdXJlbWVudCwgc28gdGltZSBzcGVudFxuICAgKiBkdXJhYmx5IGNyZWF0aW5nIHRoZSB1c2VyJ3MgaG9va3MgZG9lc24ndCBjb3VudCBhcyBydW50aW1lIG92ZXJoZWFkLlxuICAgKi9cbiAgaG9va0NyZWF0aW9uTXM6IG51bWJlcjtcbiAgLyoqIEV4YWN0IG51bWJlciBvZiB3b3JrZmxvdy1jb2RlIGV4ZWN1dGlvbnMgb2JzZXJ2ZWQgZHVyaW5nIHNlcmlhbGl6YXRpb24uICovXG4gIHNlcmlhbGl6YXRpb25CbG9ja2VyQ291bnQ6IG51bWJlcjtcbiAgLyoqIEJvdW5kZWQgc2FtcGxlIHVzZWQgb25seSBmb3IgcmV0ZW50aW9uIGRpYWdub3N0aWNzLiAqL1xuICBzZXJpYWxpemF0aW9uQmxvY2tlcnM6IFN1c3BlbnNpb25TZXJpYWxpemF0aW9uQmxvY2tlcltdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFN1c3BlbnNpb25TZXJpYWxpemF0aW9uQmxvY2tlciBleHRlbmRzIEd1ZXN0Q29kZUV4ZWN1dGlvbiB7XG4gIHNvdXJjZTogJ3N0ZXBfaW5wdXQnIHwgJ2hvb2tfbWV0YWRhdGEnIHwgJ2hvb2tfYWJvcnQnO1xuICBjb3JyZWxhdGlvbklkOiBzdHJpbmc7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGNyZWF0ZUhvb2tFdmVudCh7XG4gIHJ1bklkLFxuICBob29rRXZlbnQsXG4gIHF1ZXVlSXRlbSxcbiAgcmVxdWVzdElkLFxuICBzaW5jZUN1cnNvcixcbiAgY3JlYXRlRXZlbnQsXG59OiB7XG4gIHJ1bklkOiBzdHJpbmc7XG4gIGhvb2tFdmVudDogQ3JlYXRlRXZlbnRSZXF1ZXN0O1xuICBxdWV1ZUl0ZW06IEhvb2tJbnZvY2F0aW9uUXVldWVJdGVtO1xuICByZXF1ZXN0SWQ/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBDdXJzb3IgdG8gYXNrIHRoZSBXb3JsZCBmb3IgdGhlIGV2ZW50LWxvZyBkZWx0YSBhZ2FpbnN0LCBvciB1bmRlZmluZWQgdG9cbiAgICogbm90IGFzay4gU2VlIGBob29rRGVsdGFDdXJzb3JgIGluIHtAbGluayBoYW5kbGVTdXNwZW5zaW9ufSBmb3Igd2hlbiBpdCBpc1xuICAgKiBzZXQgYW5kIHdoeSBpdCBpcyBhdCBtb3N0IG9uZSB3cml0ZSBwZXIgc3VzcGVuc2lvbi5cbiAgICovXG4gIHNpbmNlQ3Vyc29yPzogc3RyaW5nO1xuICBjcmVhdGVFdmVudDogKFxuICAgIGRhdGE6IENyZWF0ZUV2ZW50UmVxdWVzdCxcbiAgICBwYXJhbXM/OiBDcmVhdGVFdmVudFBhcmFtc1xuICApID0+IFByb21pc2U8RXZlbnRSZXN1bHQ+O1xufSk6IFByb21pc2U8e1xuICBoYXNIb29rQ29uZmxpY3Q6IGJvb2xlYW47XG4gIGhhc0F3YWl0ZWRIb29rQ3JlYXRpb246IGJvb2xlYW47XG59PiB7XG4gIHRyeSB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY3JlYXRlRXZlbnQoaG9va0V2ZW50LCB7XG4gICAgICByZXF1ZXN0SWQsXG4gICAgICAuLi4oc2luY2VDdXJzb3IgPT09IHVuZGVmaW5lZCA/IHt9IDogeyBzaW5jZUN1cnNvciB9KSxcbiAgICB9KTtcblxuICAgIC8vIENoZWNrIGlmIHRoZSB3b3JsZCByZXR1cm5lZCBhIGhvb2tfY29uZmxpY3QgZXZlbnQgaW5zdGVhZCBvZiBob29rX2NyZWF0ZWQuXG4gICAgLy8gVGhlIGhvb2tfY29uZmxpY3QgZXZlbnQgaXMgc3RvcmVkIGluIHRoZSBldmVudCBsb2cgYW5kIGlzIHdoYXQgdGhlIG5leHRcbiAgICAvLyBwYXNzIGNvbnN1bWVzIHRvIHNldHRsZSB0aGUgaG9vaydzIGF3YWl0ZXJzIOKAlCByZWplY3RpbmcgYSBwYXlsb2FkIGF3YWl0LFxuICAgIC8vIHJlc29sdmluZyBhIGBob29rLmdldENvbmZsaWN0KClgIHdpdGggdGhlIGNvbmZsaWN0aW5nIHJ1bi4gQW4gaW5saW5lXG4gICAgLy8gZGVsdGEgYXNrZWQgZm9yIGFib3ZlIGNhcnJpZXMgaXQganVzdCBhcyBpdCB3b3VsZCBoYXZlIGNhcnJpZWQgdGhlXG4gICAgLy8gaG9va19jcmVhdGVkLCBzbyB0aGUgY2FsbGVyIGNhbiBhZHZhbmNlIG92ZXIgaXQgd2l0aG91dCBhIHJlLWludm9jYXRpb24uXG4gICAgaWYgKHJlc3VsdC5ldmVudD8uZXZlbnRUeXBlID09PSAnaG9va19jb25mbGljdCcpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGhhc0hvb2tDb25mbGljdDogdHJ1ZSxcbiAgICAgICAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbjogZmFsc2UsXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBoYXNIb29rQ29uZmxpY3Q6IGZhbHNlLFxuICAgICAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbjogcXVldWVJdGVtLmhhc0NvbmZsaWN0QXdhaXRlciA9PT0gdHJ1ZSxcbiAgICB9O1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ0hvb2sgYWxyZWFkeSBleGlzdHMsIGNvbnRpbnVpbmcnLCB7XG4gICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaGFzSG9va0NvbmZsaWN0OiBmYWxzZSxcbiAgICAgICAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbjogcXVldWVJdGVtLmhhc0NvbmZsaWN0QXdhaXRlciA9PT0gdHJ1ZSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKFJ1bkV4cGlyZWRFcnJvci5pcyhlcnIpKSB7XG4gICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ1dvcmtmbG93IHJ1biBhbHJlYWR5IGNvbXBsZXRlZCwgc2tpcHBpbmcgaG9vaycsIHtcbiAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgfSk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBoYXNIb29rQ29uZmxpY3Q6IGZhbHNlLFxuICAgICAgICBoYXNBd2FpdGVkSG9va0NyZWF0aW9uOiBmYWxzZSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKGlzV29ybGRWYWxpZGF0aW9uRmFpbHVyZShlcnIpKSB7XG4gICAgICBjb25zdCBmYXRhbCA9IG5ldyBGYXRhbEVycm9yKFxuICAgICAgICBgY3JlYXRlSG9vayBmYWlsZWQgV29ybGQgdmFsaWRhdGlvbjogJHtcbiAgICAgICAgICBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVycilcbiAgICAgICAgfWBcbiAgICAgICk7XG4gICAgICBmYXRhbC5jYXVzZSA9IGVycjtcbiAgICAgIHRocm93IGZhdGFsO1xuICAgIH1cblxuICAgIHRocm93IGVycjtcbiAgfVxufVxuXG4vKipcbiAqIEhhbmRsZXMgYSB3b3JrZmxvdyBzdXNwZW5zaW9uIGJ5IHByb2Nlc3NpbmcgYWxsIHBlbmRpbmcgb3BlcmF0aW9ucyAoaG9va3MsIHN0ZXBzLCB3YWl0cykuXG4gKiBDcmVhdGVzIGV2ZW50cyBmb3IgYWxsIG9wZXJhdGlvbnMgYnV0IGRvZXMgTk9UIHF1ZXVlIHN0ZXAgbWVzc2FnZXM7IHJldHVybnMgdGhlIHBlbmRpbmdcbiAqIHN0ZXBzIHNvIHRoZSBjYWxsZXIgY2FuIGRlY2lkZSB3aGljaCB0byBleGVjdXRlIGlubGluZSB2cyBxdWV1ZSB0byBiYWNrZ3JvdW5kLlxuICpcbiAqIFByb2Nlc3Npbmcgb3JkZXI6XG4gKiAxLiBIb29rcyBhcmUgcHJvY2Vzc2VkIGZpcnN0IHRvIHByZXZlbnQgcmFjZSBjb25kaXRpb25zIHdpdGggd2ViaG9vayByZWNlaXZlcnNcbiAqIDIuIFN0ZXAgZXZlbnRzIGFuZCB3YWl0IGV2ZW50cyBhcmUgY3JlYXRlZCBpbiBwYXJhbGxlbFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlU3VzcGVuc2lvbih7XG4gIHN1c3BlbnNpb24sXG4gIHdvcmxkLFxuICBydW4sXG4gIHNwYW4sXG4gIHJlcXVlc3RJZCxcbiAgZXZlbnRMb2csXG4gIHJ1blJlYWR5QmFycmllcixcbiAgcmVwbGF5UmVjb3ZlcnlSZXBvcnRlcixcbiAgc3RlcERpc3BhdGNoLFxuICBvd25lck1lc3NhZ2VJZCxcbiAgYWxsb3dEZWZlcnJlZEJhdGNoV29yayxcbn06IFN1c3BlbnNpb25IYW5kbGVyUGFyYW1zKTogUHJvbWlzZTxTdXNwZW5zaW9uSGFuZGxlclJlc3VsdD4ge1xuICBjb25zdCBydW5JZCA9IHJ1bi5ydW5JZDtcblxuICAvLyBUdXJibyBtb2RlOiBob2xkIGV2ZXJ5IHdvcmxkIHdyaXRlIGJlbG93IHVudGlsIHRoZSBiYWNrZ3JvdW5kZWRcbiAgLy8gYHJ1bl9zdGFydGVkYCBoYXMgKnNldHRsZWQqLCBzbyB3ZSBuZXZlciB3cml0ZSBhIHN0ZXAvaG9vay93YWl0IGV2ZW50IGZvciBhXG4gIC8vIHJ1biB0aGF0IGRvZXMgbm90IGV4aXN0IHlldC4gQSBuby1vcCBvdXRzaWRlIHR1cmJvIChiYXJyaWVyIHVuZGVmaW5lZCkgYW5kXG4gIC8vIG9uIHRoZSBwdXJlIGlubGluZSBob3QgcGF0aCwgd2hpY2ggZGVmZXJzIGFsbCBzdGVwcyBhbmQgd3JpdGVzIG5vdGhpbmcuXG4gIC8vIEF3YWl0aW5nIHRoZSBzYW1lICh1c3VhbGx5IGFscmVhZHktc2V0dGxlZCkgcHJvbWlzZSBtb3JlIHRoYW4gb25jZSBpcyBjaGVhcC5cbiAgLy8gQSBiYXJyaWVyIHJlamVjdGlvbiBpcyBzd2FsbG93ZWQgZm9yIG9yZGVyaW5nIG9ubHk6IGlmIGBydW5fc3RhcnRlZGAgdHJ1bHlcbiAgLy8gZmFpbGVkIHRoZSBydW4gZG9lcyBub3QgZXhpc3QsIHNvIHRoZSBzdWJzZXF1ZW50IHdyaXRlIHN1cmZhY2VzIHRoZSByZWFsXG4gIC8vIGVycm9yIChydW4gbm90IGZvdW5kIC8gZ29uZSkgYW5kIHRoZSBtZXNzYWdlIHJlZGVsaXZlcnMuXG4gIGNvbnN0IGVuc3VyZVJ1blJlYWR5ID0gYXN5bmMgKCk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgIGlmIChydW5SZWFkeUJhcnJpZXIpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHJ1blJlYWR5QmFycmllcjtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBpbnRlbnRpb25hbDogb3JkZXJpbmcgYmFycmllciBvbmx5LCBzZWUgYWJvdmUuXG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiBBd2FpdCBldmVyeSBvcGVyYXRpb24gaW4gYSBzdXNwZW5zaW9uIHBoYXNlIGJlZm9yZSBsZXR0aW5nIGEgZmFpbHVyZVxuICAgKiBlc2NhcGUsIHByZWZlcnJpbmcgYSBzdGFsZS1zbmFwc2hvdCAoNDEyKSByZWplY3Rpb24gd2hlbiBvbmUgb2NjdXJyZWQuXG4gICAqXG4gICAqIGBQcm9taXNlLmFsbGAgcmVqZWN0cyBhcyBzb29uIGFzIG9uZSBvcGVyYXRpb24gZG9lcyBhbmQgbGVhdmVzIGl0cyBzaWJsaW5nc1xuICAgKiBpbiBmbGlnaHQuIFRoYXQgbWF0dGVycyBmb3IgYSA0MTI6IHRoZSBjYWxsZXIgcmVhY3RzIGJ5IHJlbG9hZGluZyB0aGUgZXZlbnRcbiAgICogbG9nIGFuZCByZXN0YXJ0aW5nIHRoZSByZXBsYXksIHNvIGEgc2libGluZyBjcmVhdGUgdGhhdCBsYW5kcyBhZnRlciB0aGVcbiAgICogcmVqZWN0aW9uIGVzY2FwZWQgY29tbWl0cyBhbiBldmVudCB3aG9zZSBjb3JyZWxhdGlvbiBpZCBjYW1lIGZyb20gdGhlXG4gICAqIGFiYW5kb25lZCByZXBsYXkncyBzZWVkZWQgc2VxdWVuY2UgKGFuIGV2ZW50IHRoZSBmcmVzaCByZXBsYXkgbmV2ZXJcbiAgICogcHJvZHVjZXMpLCBhbmQgaXQgcmFjZXMgdGhlIHJlc3RhcnQncyByZWxvYWQgd2hpbGUgZG9pbmcgc28uIFNldHRsaW5nIGZpcnN0XG4gICAqIG1ha2VzIHRoaXMgcGhhc2UncyB3cml0ZSBzZXQgZmluYWwgYmVmb3JlIHRoZSBjYWxsZXIgYWN0cyBvbiB0aGUgZmFpbHVyZS5cbiAgICogSXQgbWlycm9ycyB0aGUgcnVudGltZSdzIGlubGluZSBzdGVwIGNsYWltLCB3aGljaCBzZXR0bGVzIHRoZSBpbi1mbGlnaHRcbiAgICogc3RlcCBleGVjdXRpb25zIGJlZm9yZSBlc2NhbGF0aW5nIGEgNDEyLlxuICAgKlxuICAgKiBBIDQxMiBpcyBwcmVmZXJyZWQgb3ZlciBhbnkgb3RoZXIgcmVqZWN0aW9uIGluIHRoZSBzYW1lIHBoYXNlIGJlY2F1c2UgaXRcbiAgICogaGFzIGEgZGVmaW5lZCwgY2hlYXAgcmVjb3ZlcnkgKHJlcGxheSBmcm9tIGEgY29ycmVjdGVkIGxvZykgd2hpbGUgdGhlXG4gICAqIG90aGVycyBkbyBub3QuIEEgZGV0ZXJtaW5pc3RpYyBmYWlsdXJlIHN1Y2ggYXMgYW4gYXR0cmlidXRlLXZhbGlkYXRpb25cbiAgICogYEZhdGFsRXJyb3JgIHJlY3VycyBvbiB0aGUgcmVzdGFydCBhbmQgZmFpbHMgdGhlIHJ1biB0aGVuLCBhdCB0aGUgY29zdCBvZlxuICAgKiBvbmUgZXh0cmEgcmVwbGF5LlxuICAgKi9cbiAgY29uc3Qgc2V0dGxlUGhhc2UgPSBhc3luYyAob3BzOiBQcm9taXNlPHVua25vd24+W10pOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICBjb25zdCByZWFzb25zID0gKGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChvcHMpKVxuICAgICAgLmZpbHRlcigocik6IHIgaXMgUHJvbWlzZVJlamVjdGVkUmVzdWx0ID0+IHIuc3RhdHVzID09PSAncmVqZWN0ZWQnKVxuICAgICAgLm1hcCgocikgPT4gci5yZWFzb24pO1xuICAgIGlmIChyZWFzb25zLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xuICAgIHRocm93IHJlYXNvbnMuZmluZCgocikgPT4gUHJlY29uZGl0aW9uRmFpbGVkRXJyb3IuaXMocikpID8/IHJlYXNvbnNbMF07XG4gIH07XG5cbiAgLy8gRXZlcnkgc3VzcGVuc2lvbiB3cml0ZSBjYXJyaWVzIHJlcGxheS1yZWNvdmVyeSB0ZWxlbWV0cnkgb24gdGhlIGZpcnN0IG9uZVxuICAvLyB0aGF0IGNvbW1pdHMgYWZ0ZXIgcmVwbGF5IHJlY292ZXJlZC4gQWxsIHN1c3BlbnNpb24gZXZlbnRzIGFyZVxuICAvLyBub24tcnVuX2NyZWF0ZWQgZXZlbnRzIG9uIHRoaXMgcnVuJ3MgYHJ1bklkYC5cbiAgY29uc3QgcmVwb3J0ZXIgPSByZXBsYXlSZWNvdmVyeVJlcG9ydGVyID8/IFJlcGxheVJlY292ZXJ5UmVwb3J0ZXIuaW5lcnQoKTtcbiAgY29uc3QgY3JlYXRlRXZlbnQgPSAoZGF0YTogQ3JlYXRlRXZlbnRSZXF1ZXN0LCBwYXJhbXM/OiBDcmVhdGVFdmVudFBhcmFtcykgPT5cbiAgICByZXBvcnRlci53aXRoRXZlbnRDcmVhdGUocGFyYW1zLCAocCkgPT5cbiAgICAgIHdvcmxkLmV2ZW50cy5jcmVhdGUocnVuSWQsIGRhdGEsIHApXG4gICAgKTtcbiAgLy8gQWRkcyB0aGUgb3B0aW1pc3RpYy1jb25jdXJyZW5jeSBndWFyZCB3aGVuIHRoZSBjYWxsZXIgc3VwcGxpZWQgYSBsb2FkZWRcbiAgLy8gZXZlbnQgbG9nOyB3aXRob3V0IG9uZSBpdCBjcmVhdGVzIGRpcmVjdGx5IChjYWxsZXJzIHdpdGggbm8gcmVwbGF5XG4gIC8vIHNuYXBzaG90LCBlLmcuIHRlc3RzKS4gQSBzdGFsZSAoNDEyKSByZWplY3Rpb24gcHJvcGFnYXRlcyB0byB0aGUgY2FsbGVyLFxuICAvLyB3aGljaCByZXN0YXJ0cyB0aGUgcmVwbGF5IGZyb20gYSBjb3JyZWN0ZWQgbG9nLiBJdCBpcyBub3QgcmV0cmllZCBoZXJlLFxuICAvLyBiZWNhdXNlIHRoZSBldmVudCdzIGNvcnJlbGF0aW9uIGlkIHdhcyBtaW50ZWQgYnkgKnRoaXMqIHJlcGxheSdzIHNlZWRlZFxuICAvLyBzZXF1ZW5jZSwgc28gcmUtY29tbWl0dGluZyBpdCBhZ2FpbnN0IGEgY29ycmVjdGVkIGxvZyB3b3VsZCBwZXJzaXN0IGFuXG4gIC8vIGV2ZW50IG5vIGNvcnJlY3QgcmVwbGF5IHByb2R1Y2VzLlxuICBsZXQgcmVwb3J0ZWRFdmVudHMgPSAwO1xuICAvLyBXcml0ZXMgdGhpcyBzdXNwZW5zaW9uIGlzc3VlZCwgYW5kIHdoZXRoZXIgb25lIG9mIHRoZW0gaGFuZGVkIGJhY2sgYVxuICAvLyBjb21wbGV0ZSBpbmxpbmUgZGVsdGEgdGhhdCB3YXMgZm9sZGVkIGludG8gdGhlIGNhbGxlcidzIGxvZy4gVG9nZXRoZXIgdGhleVxuICAvLyBhbnN3ZXIgYGV2ZW50TG9nQ2FycmllZEZvcndhcmRgOiB0aGUgZGVsdGEgY292ZXJzIHRoZSBsb2cgdXAgdG8gdGhlIHdyaXRlXG4gIC8vIHRoYXQgcmV0dXJuZWQgaXQsIHNvIGl0IGFjY291bnRzIGZvciBldmVyeSBldmVudCB0aGlzIHN1c3BlbnNpb24gY29tbWl0dGVkXG4gIC8vIG9ubHkgaWYgdGhhdCB3cml0ZSB3YXMgdGhlIG9ubHkgb25lLlxuICBsZXQgZ3VhcmRlZFdyaXRlcyA9IDA7XG4gIGxldCBkZWx0YUFic29yYmVkID0gZmFsc2U7XG4gIGNvbnN0IGNyZWF0ZUd1YXJkZWQ6IEV2ZW50Q3JlYXRvciA9IGFzeW5jIChkYXRhLCBwYXJhbXMpID0+IHtcbiAgICBndWFyZGVkV3JpdGVzKys7XG4gICAgaWYgKCFldmVudExvZykge1xuICAgICAgcmV0dXJuIGNyZWF0ZUV2ZW50KGRhdGEsIHBhcmFtcyk7XG4gICAgfVxuICAgIGNvbnN0IGxvZyA9IGV2ZW50TG9nO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNyZWF0ZUV2ZW50KGRhdGEsIHtcbiAgICAgIC4uLnBhcmFtcyxcbiAgICAgIC4uLnNsb3RTbmFwc2hvdFBhcmFtcyhsb2cuZXZlbnRzKSxcbiAgICB9KTtcbiAgICAvLyBBbiBpbmxpbmUgZGVsdGEgdGhpcyBjYWxsIGFza2VkIGZvciAoYHNpbmNlQ3Vyc29yYCkgaXMgZXZlcnl0aGluZyB0aGVcbiAgICAvLyBsb2cgZ2FpbmVkIHNpbmNlIHRoYXQgY3Vyc29yLCB0aGlzIHdyaXRlIGluY2x1ZGVkLCBzbyBpdCBpcyBmb2xkZWQgb250b1xuICAgIC8vIHRoZSB0YWlsIGFuZCBjYXJyaWVzIHRoZSBjdXJzb3Igd2l0aCBpdCDigJQgdW5saWtlIGEgc2tpcHBlZC1zbG90IHJlcG9ydCxcbiAgICAvLyB3aGljaCBpcyBhIHdpbmRvdyBzdHJpY3RseSBiZWxvdyB0aGUgd3JpdGUgYW5kIGhhcyB0byBiZSBzb3J0ZWQgYmFja1xuICAgIC8vIGludG8gcGxhY2UuIEEgV29ybGQgcmV0dXJucyBvbmUgb3IgdGhlIG90aGVyLCBuZXZlciBib3RoICh0aGUgZGVsdGEgaXMgYVxuICAgIC8vIHN0cmljdCBzdXBlcnNldCksIHNvIHRoZSB0d28gYXJlIGhhbmRsZWQgYXBhcnQgcmF0aGVyIHRoYW4gbWVyZ2VkLlxuICAgIC8vXG4gICAgLy8gRGVjbGluaW5nIGlzIGFsd2F5cyBzYWZlIOKAlCBhbiB1bmFic29yYmVkIGRlbHRhIGlzIG9uZSB0aGUgbmV4dCByZWFkXG4gICAgLy8gcmV0dXJucyDigJQgc28gdGhlIGd1YXJkcyBtYXRjaCB0aGUgcmVwbGF5IGxvb3AncyBgYWJzb3JiQ3JlYXRlRGVsdGFgOiBhXG4gICAgLy8gdHJ1bmNhdGVkIHBhZ2UgKGBoYXNNb3JlYCkgaXMgZHJvcHBlZCB3aG9sZSByYXRoZXIgdGhhbiBhZHZhbmNpbmcgdGhlXG4gICAgLy8gY3Vyc29yIHBhc3QgZXZlbnRzIGl0IGRpZCBub3QgY2FycnksIGFuZCB0aGUgbG9nIG11c3Qgc3RpbGwgYmUgd2hlcmUgdGhlXG4gICAgLy8gcmVxdWVzdCB3YXMgY29tcHV0ZWQgZnJvbSwgc2luY2UgYXBwZW5kaW5nIGRvZXMgbm90IHJlLXNvcnQuXG4gICAgaWYgKHR5cGVvZiBwYXJhbXM/LnNpbmNlQ3Vyc29yID09PSAnc3RyaW5nJykge1xuICAgICAgaWYgKFxuICAgICAgICBsb2cuY3Vyc29yID09PSBwYXJhbXMuc2luY2VDdXJzb3IgJiZcbiAgICAgICAgcmVzdWx0LmV2ZW50cyAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgIHJlc3VsdC5oYXNNb3JlICE9PSB0cnVlXG4gICAgICApIHtcbiAgICAgICAgYXBwZW5kRXZlbnRMb2cobG9nLCB7IGV2ZW50czogcmVzdWx0LmV2ZW50cywgY3Vyc29yOiByZXN1bHQuY3Vyc29yIH0pO1xuICAgICAgICBkZWx0YUFic29yYmVkID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICAgIC8vIEJ1bXAtYW5kLXJlcG9ydDogdGhlIHdyaXRlIGxhbmRlZCBhYm92ZSB0aGUgc2xvdCBpdCBhc2tlZCBmb3IsIHNvIHRoZVxuICAgIC8vIHJlcG9ydCBob2xkcyB0aGUgZXZlbnRzIGl0IHdhcyBkZWNpZGVkIHdpdGhvdXQuIEFic29yYmluZyBoZXJlIHJhdGhlclxuICAgIC8vIHRoYW4gYXQgZWFjaCBjYWxsIHNpdGUgbWVhbnMgdGhlIHJlc3Qgb2YgdGhpcyBwaGFzZSdzIHdyaXRlcyAod2hpY2ggcmVhZFxuICAgIC8vIHRoZSBzYW1lIGFycmF5IHRvIGJ1aWxkIHRoZWlyIG93biBzbmFwc2hvdCkgYXNrIGZvciBhIHNsb3QgYWJvdmUgdGhlbSxcbiAgICAvLyBhbmQgdGhlIHJlcGxheSB0aGF0IHJlc3VtZXMgZnJvbSB0aGlzIGxvZyBzZWVzIHRoZW0gd2l0aG91dCBhIHJlbG9hZC5cbiAgICBjb25zdCByZXBvcnQgPSBhYnNvcmJTa2lwcGVkU2xvdFJlcG9ydChsb2cuZXZlbnRzLCByZXN1bHQpO1xuICAgIHJlcG9ydGVkRXZlbnRzICs9IHJlcG9ydC5hZGRlZDtcbiAgICBpZiAocmVwb3J0LnRydW5jYXRlZCkge1xuICAgICAgcnVudGltZUxvZ2dlci5kZWJ1ZygnRHJvcHBlZCBhIHRydW5jYXRlZCBza2lwcGVkLXNsb3QgcmVwb3J0Jywge1xuICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgZXZlbnRUeXBlOiBkYXRhLmV2ZW50VHlwZSxcbiAgICAgICAgZXZlbnRJZDogcmVzdWx0LmV2ZW50Py5ldmVudElkLFxuICAgICAgICBvZmZlcmVkOiByZXBvcnQub2ZmZXJlZCxcbiAgICAgIH0pO1xuICAgIH0gZWxzZSBpZiAocmVwb3J0LmFkZGVkID4gMCkge1xuICAgICAgcnVudGltZUxvZ2dlci5kZWJ1ZygnU3VzcGVuc2lvbiB3cml0ZSBza2lwcGVkIG9jY3VwaWVkIHNsb3RzJywge1xuICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgZXZlbnRUeXBlOiBkYXRhLmV2ZW50VHlwZSxcbiAgICAgICAgZXZlbnRJZDogcmVzdWx0LmV2ZW50Py5ldmVudElkLFxuICAgICAgICByZXBvcnRlZDogcmVwb3J0LmFkZGVkLFxuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG4gIC8vIFNlcGFyYXRlIHF1ZXVlIGl0ZW1zIGJ5IHR5cGVcbiAgY29uc3Qgc3RlcEl0ZW1zID0gc3VzcGVuc2lvbi5pdGVtcy5maWx0ZXIoXG4gICAgKGl0ZW0pOiBpdGVtIGlzIFN0ZXBJbnZvY2F0aW9uUXVldWVJdGVtID0+IGl0ZW0udHlwZSA9PT0gJ3N0ZXAnXG4gICk7XG4gIGNvbnN0IGFsbEhvb2tJdGVtcyA9IHN1c3BlbnNpb24uaXRlbXMuZmlsdGVyKFxuICAgIChpdGVtKTogaXRlbSBpcyBIb29rSW52b2NhdGlvblF1ZXVlSXRlbSA9PiBpdGVtLnR5cGUgPT09ICdob29rJ1xuICApO1xuICBjb25zdCB3YWl0SXRlbXMgPSBzdXNwZW5zaW9uLml0ZW1zLmZpbHRlcihcbiAgICAoaXRlbSk6IGl0ZW0gaXMgV2FpdEludm9jYXRpb25RdWV1ZUl0ZW0gPT4gaXRlbS50eXBlID09PSAnd2FpdCdcbiAgKTtcbiAgY29uc3QgYXR0cmlidXRlSXRlbXMgPSBzdXNwZW5zaW9uLml0ZW1zLmZpbHRlcihcbiAgICAoaXRlbSk6IGl0ZW0gaXMgQXR0cmlidXRlSW52b2NhdGlvblF1ZXVlSXRlbSA9PiBpdGVtLnR5cGUgPT09ICdhdHRyaWJ1dGUnXG4gICk7XG5cbiAgY29uc3QgaG9va3NOZWVkaW5nQ3JlYXRpb24gPSBhbGxIb29rSXRlbXMuZmlsdGVyKFxuICAgIChpdGVtKSA9PiAhaXRlbS5oYXNDcmVhdGVkRXZlbnRcbiAgKTtcblxuICAvLyBHcm91cCBob29rIGl0ZW1zIHRoYXQgbmVlZCB3b3JrIGJ5IHRva2VuLCBwcmVzZXJ2aW5nIHF1ZXVlLWluc2VydGlvblxuICAvLyAod29ya2Zsb3cgY29kZSkgb3JkZXIgd2l0aGluIGVhY2ggdG9rZW4uIE9wZXJhdGlvbnMgb24gb25lIHRva2VuIG11c3RcbiAgLy8gYXBwbHkgaW4gY29kZSBvcmRlcjogYSBkaXNwb3NlKCkgb2YgYW4gZWFybGllciBob29rIHJlbGVhc2VzIHRoZSB0b2tlblxuICAvLyBiZWZvcmUgYSBsYXRlciBzYW1lLXRva2VuIGhvb2sncyBjcmVhdGlvbiBpcyB2YWxpZGF0ZWQgKG90aGVyd2lzZSB0aGVcbiAgLy8gbmV3IGhvb2sgcmVjb3JkcyBhIHNwdXJpb3VzIGhvb2tfY29uZmxpY3QgYWdhaW5zdCB0aGUgcnVuJ3Mgb3duXG4gIC8vIGRpc3Bvc2VkIGhvb2spLCB3aGlsZSBhIGhvb2sgY3JlYXRlZCBhbmQgZGlzcG9zZWQgd2l0aGluIHRoZSBzYW1lXG4gIC8vIHN1c3BlbnNpb24gaXMgc3RpbGwgY3JlYXRlZCBiZWZvcmUgaXQgaXMgZGlzcG9zZWQuIERpZmZlcmVudCB0b2tlbnNcbiAgLy8gaGF2ZSBubyBjbGFpbSBpbnRlcmFjdGlvbiwgc28gdG9rZW4gZ3JvdXBzIGFyZSBwcm9jZXNzZWQgaW4gcGFyYWxsZWwuXG4gIGNvbnN0IGhvb2tJdGVtc0J5VG9rZW4gPSBuZXcgTWFwPHN0cmluZywgSG9va0ludm9jYXRpb25RdWV1ZUl0ZW1bXT4oKTtcbiAgZm9yIChjb25zdCBpdGVtIG9mIGFsbEhvb2tJdGVtcykge1xuICAgIGlmIChpdGVtLmhhc0NyZWF0ZWRFdmVudCAmJiAhaXRlbS5kaXNwb3NlZCkge1xuICAgICAgY29udGludWU7IC8vIGFscmVhZHkgY29tbWl0dGVkIGFuZCBzdGlsbCBsaXZlOiBub3RoaW5nIHRvIGRvXG4gICAgfVxuICAgIGNvbnN0IGdyb3VwID0gaG9va0l0ZW1zQnlUb2tlbi5nZXQoaXRlbS50b2tlbik7XG4gICAgaWYgKGdyb3VwKSB7XG4gICAgICBncm91cC5wdXNoKGl0ZW0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBob29rSXRlbXNCeVRva2VuLnNldChpdGVtLnRva2VuLCBbaXRlbV0pO1xuICAgIH1cbiAgfVxuXG4gIC8vIFJlc29sdmUgZW5jcnlwdGlvbiBrZXkgZm9yIHRoaXMgcnVuXG4gIGNvbnN0IHJhd0tleSA9IGF3YWl0IHdvcmxkLmdldEVuY3J5cHRpb25LZXlGb3JSdW4/LihydW4pO1xuICBjb25zdCBlbmNyeXB0aW9uS2V5ID0gcmF3S2V5ID8gYXdhaXQgaW1wb3J0S2V5KHJhd0tleSkgOiB1bmRlZmluZWQ7XG5cbiAgLy8gR2F0ZSBwYXlsb2FkIGNvbXByZXNzaW9uIG9uIHRoZSBydW4ncyBzcGVjVmVyc2lvbi5cbiAgY29uc3QgY29tcHJlc3Npb24gPVxuICAgIChydW4uc3BlY1ZlcnNpb24gPz8gMCkgPj0gU1BFQ19WRVJTSU9OX1NVUFBPUlRTX0NPTVBSRVNTSU9OO1xuXG4gIGxldCBzZXJpYWxpemF0aW9uQmxvY2tlckNvdW50ID0gMDtcbiAgY29uc3Qgc2VyaWFsaXphdGlvbkJsb2NrZXJzOiBTdXNwZW5zaW9uU2VyaWFsaXphdGlvbkJsb2NrZXJbXSA9IFtdO1xuICBhc3luYyBmdW5jdGlvbiBkZWh5ZHJhdGVJbnB1dChcbiAgICB2YWx1ZTogdW5rbm93bixcbiAgICBjb250ZXh0OiBQaWNrPFN1c3BlbnNpb25TZXJpYWxpemF0aW9uQmxvY2tlciwgJ3NvdXJjZScgfCAnY29ycmVsYXRpb25JZCc+XG4gICk6IFByb21pc2U8U2VyaWFsaXplZERhdGE+IHtcbiAgICBjb25zdCBzdGF0czogR3Vlc3RDb2RlU3RhdHMgPSB7IGV4ZWN1dGlvbnM6IFtdIH07XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiAoYXdhaXQgZGVoeWRyYXRlU3RlcEFyZ3VtZW50cyhcbiAgICAgICAgdmFsdWUsXG4gICAgICAgIHJ1bklkLFxuICAgICAgICBlbmNyeXB0aW9uS2V5LFxuICAgICAgICBzdXNwZW5zaW9uLmdsb2JhbFRoaXMsXG4gICAgICAgIGZhbHNlLFxuICAgICAgICBjb21wcmVzc2lvbixcbiAgICAgICAgc3RhdHNcbiAgICAgICkpIGFzIFNlcmlhbGl6ZWREYXRhO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBzZXJpYWxpemF0aW9uQmxvY2tlckNvdW50ICs9XG4gICAgICAgIHN0YXRzLnRvdGFsRXhlY3V0aW9ucyA/PyBzdGF0cy5leGVjdXRpb25zLmxlbmd0aDtcbiAgICAgIHNlcmlhbGl6YXRpb25CbG9ja2Vycy5wdXNoKFxuICAgICAgICAuLi5zdGF0cy5leGVjdXRpb25zXG4gICAgICAgICAgLnNsaWNlKFxuICAgICAgICAgICAgMCxcbiAgICAgICAgICAgIEdVRVNUX0NPREVfRVhFQ1VUSU9OX1NBTVBMRV9MSU1JVCAtIHNlcmlhbGl6YXRpb25CbG9ja2Vycy5sZW5ndGhcbiAgICAgICAgICApXG4gICAgICAgICAgLm1hcCgoZXhlY3V0aW9uKSA9PiAoeyAuLi5jb250ZXh0LCAuLi5leGVjdXRpb24gfSkpXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIGRpc3Bvc2VIb29rKFxuICAgIHF1ZXVlSXRlbTogSG9va0ludm9jYXRpb25RdWV1ZUl0ZW1cbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgaG9va0Rpc3Bvc2VkRXZlbnQ6IENyZWF0ZUV2ZW50UmVxdWVzdCA9IHtcbiAgICAgIGV2ZW50VHlwZTogJ2hvb2tfZGlzcG9zZWQnIGFzIGNvbnN0LFxuICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICBldmVudERhdGE6IHtcbiAgICAgICAgdG9rZW46IHF1ZXVlSXRlbS50b2tlbixcbiAgICAgIH0sXG4gICAgfTtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgY3JlYXRlR3VhcmRlZChob29rRGlzcG9zZWRFdmVudCwgeyByZXF1ZXN0SWQgfSk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgIC8vIEhvb2sgd2FzIGFscmVhZHkgZGlzcG9zZWQgYnkgYSBjb25jdXJyZW50IGludm9jYXRpb24sIHNhZmUgdG8gc2tpcFxuICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgJ0hvb2sgYWxyZWFkeSBkaXNwb3NlZCwgc2tpcHBpbmcgZHVwbGljYXRlIGRpc3Bvc2FsJyxcbiAgICAgICAgICB7XG4gICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgfSBlbHNlIGlmIChSdW5FeHBpcmVkRXJyb3IuaXMoZXJyKSkge1xuICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgJ1dvcmtmbG93IHJ1biBhbHJlYWR5IGNvbXBsZXRlZCwgc2tpcHBpbmcgaG9vayBkaXNwb3NhbCcsXG4gICAgICAgICAge1xuICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSBpZiAoSG9va05vdEZvdW5kRXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAvLyBIb29rIG1heSBoYXZlIGFscmVhZHkgYmVlbiBkaXNwb3NlZCBvciBuZXZlciBjcmVhdGVkXG4gICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbygnSG9vayBub3QgZm91bmQgZm9yIGRpc3Bvc2FsLCBjb250aW51aW5nJywge1xuICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBQcm9jZXNzIGhvb2tzIGZpcnN0IHRvIHByZXZlbnQgcmFjZSBjb25kaXRpb25zIHdpdGggd2ViaG9vayByZWNlaXZlcnMuXG4gIC8vIFRyYWNrIGFueSBob29rIGNvbmZsaWN0cyB0aGF0IG9jY3VyIOKAlCB0aGVzZSBhcmUgcmV0dXJuZWQgdG8gdGhlIGNhbGxlciBzb1xuICAvLyBpdCBjYW4gYWR2YW5jZSB0aGUgd29ya2Zsb3cgb3ZlciB0aGUgY29tbWl0dGVkIGBob29rX2NvbmZsaWN0YCBiZWZvcmVcbiAgLy8gYW55dGhpbmcgZWxzZSB0aGlzIHN1c3BlbnNpb24gc2NoZWR1bGVkIHJ1bnMuXG4gIGNvbnN0IGhvb2tDb25mbGljdENvcnJlbGF0aW9uSWRzOiBzdHJpbmdbXSA9IFtdO1xuICBjb25zdCBhd2FpdGVkSG9va0NvcnJlbGF0aW9uSWRzOiBzdHJpbmdbXSA9IFtdO1xuICBsZXQgaG9va0NyZWF0aW9uTXMgPSAwO1xuXG4gIC8vIEFzayB0aGUgaG9vayBjcmVhdGUgZm9yIHRoZSBldmVudC1sb2cgZGVsdGEgc2luY2UgdGhlIGN1cnNvciB0aGUgY2FsbGVyJ3NcbiAgLy8gbG9nIHdhcyByZWFkIGF0LiBUaGUgaG9vaydzIGF3YWl0ZXJzIGFyZSBzZXR0bGVkIGJ5IHRoZSBldmVudCB0aGlzIHdyaXRlXG4gIC8vIGNvbW1pdHMgYW5kIGJ5IG5vdGhpbmcgZWxzZSDigJQgYSBgaG9va19jcmVhdGVkYCBmb3IgYSBjbGVhbiByZWdpc3RyYXRpb24sXG4gIC8vIGEgYGhvb2tfY29uZmxpY3RgIHdoZW4gdGhlIHRva2VuIHdhcyBhbHJlYWR5IGNsYWltZWQg4oCUIHNvIHRoZSBjYWxsZXIgY2FuXG4gIC8vIGNvbnRpbnVlIHRoZSB3b3JrZmxvdyBpbiBpdHMgb3duIHByb2Nlc3Mgb24gZWl0aGVyIG91dGNvbWUsIGJ1dCBvbmx5IG92ZXJcbiAgLy8gYSBsb2cgdGhhdCBob2xkcyB0aGF0IGV2ZW50LCBhbmQgdGhpcyB3cml0ZSBpcyB0aGUgb25lIHJlcXVlc3QgdGhhdCBjYW5cbiAgLy8gaGFuZCBpdCBiYWNrIHRvZ2V0aGVyIHdpdGggYW55dGhpbmcgYW5vdGhlciB3cml0ZXIgbGFuZGVkIGluIHRoZSBtZWFudGltZS5cbiAgLy8gT3B0aW9uYWwgYnkgY29udHJhY3Q6IGEgV29ybGQgdGhhdCBpZ25vcmVzIGBzaW5jZUN1cnNvcmAgcmV0dXJucyBubyBkZWx0YVxuICAvLyBhbmQgdGhlIGNhbGxlciByZWFkcyBpbnN0ZWFkLlxuICAvL1xuICAvLyBBc2tlZCBmb3Igb24gdGhlIHNpbmdsZS1ob29rIHN1c3BlbnNpb24gb25seS4gVHdvIGNyZWF0ZXMgaXNzdWVkIGZyb20gb25lXG4gIC8vIHNuYXBzaG90IGVhY2ggZGlmZiBhZ2FpbnN0IHRoZSBzYW1lIGN1cnNvciwgYW5kIG9ubHkgdGhlIGZpcnN0IGRlbHRhIGJhY2tcbiAgLy8gY2FuIGJlIGZvbGRlZCBpbiAodGhlIGN1cnNvciBtb3ZlcyB3aXRoIGl0KSwgc28gdGhlIGxvZyB3b3VsZCBlbmQgdXAgc2hvcnRcbiAgLy8gb2YgdGhlIG90aGVyJ3MgZXZlbnQgd2l0aCBub3RoaW5nIHRvIHNheSBzby5cbiAgY29uc3QgaG9va0RlbHRhQ3Vyc29yID1cbiAgICBob29rc05lZWRpbmdDcmVhdGlvbi5sZW5ndGggPT09IDEgJiYgdHlwZW9mIGV2ZW50TG9nPy5jdXJzb3IgPT09ICdzdHJpbmcnXG4gICAgICA/IGV2ZW50TG9nLmN1cnNvclxuICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgaWYgKGhvb2tJdGVtc0J5VG9rZW4uc2l6ZSA+IDApIHtcbiAgICBjb25zdCBob29rUGhhc2VTdGFydCA9IERhdGUubm93KCk7XG4gICAgYXdhaXQgZW5zdXJlUnVuUmVhZHkoKTtcbiAgICBhd2FpdCBzZXR0bGVQaGFzZShcbiAgICAgIFsuLi5ob29rSXRlbXNCeVRva2VuLnZhbHVlcygpXS5tYXAoYXN5bmMgKGl0ZW1zKSA9PiB7XG4gICAgICAgIGZvciAoY29uc3QgcXVldWVJdGVtIG9mIGl0ZW1zKSB7XG4gICAgICAgICAgbGV0IGNyZWF0aW9uQ29uZmxpY3RlZCA9IGZhbHNlO1xuXG4gICAgICAgICAgaWYgKCFxdWV1ZUl0ZW0uaGFzQ3JlYXRlZEV2ZW50KSB7XG4gICAgICAgICAgICBjb25zdCBob29rTWV0YWRhdGEgPVxuICAgICAgICAgICAgICB0eXBlb2YgcXVldWVJdGVtLm1ldGFkYXRhID09PSAndW5kZWZpbmVkJ1xuICAgICAgICAgICAgICAgID8gdW5kZWZpbmVkXG4gICAgICAgICAgICAgICAgOiBhd2FpdCBkZWh5ZHJhdGVJbnB1dChxdWV1ZUl0ZW0ubWV0YWRhdGEsIHtcbiAgICAgICAgICAgICAgICAgICAgc291cmNlOiAnaG9va19tZXRhZGF0YScsXG4gICAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBjb25zdCBob29rRXZlbnQ6IENyZWF0ZUV2ZW50UmVxdWVzdCA9IHtcbiAgICAgICAgICAgICAgZXZlbnRUeXBlOiAnaG9va19jcmVhdGVkJyBhcyBjb25zdCxcbiAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgICAgdG9rZW46IHF1ZXVlSXRlbS50b2tlbixcbiAgICAgICAgICAgICAgICB0b2tlblJldGVudGlvblVudGlsOiBxdWV1ZUl0ZW0udG9rZW5SZXRlbnRpb25VbnRpbCxcbiAgICAgICAgICAgICAgICBtZXRhZGF0YTogaG9va01ldGFkYXRhLFxuICAgICAgICAgICAgICAgIGlzV2ViaG9vazogcXVldWVJdGVtLmlzV2ViaG9vayA/PyBmYWxzZSxcbiAgICAgICAgICAgICAgICAuLi4ocXVldWVJdGVtLmlzU3lzdGVtICYmIHsgaXNTeXN0ZW06IHRydWUgfSksXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY3JlYXRlSG9va0V2ZW50KHtcbiAgICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICAgIGhvb2tFdmVudCxcbiAgICAgICAgICAgICAgcXVldWVJdGVtLFxuICAgICAgICAgICAgICByZXF1ZXN0SWQsXG4gICAgICAgICAgICAgIHNpbmNlQ3Vyc29yOiBob29rRGVsdGFDdXJzb3IsXG4gICAgICAgICAgICAgIGNyZWF0ZUV2ZW50OiBjcmVhdGVHdWFyZGVkLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAocmVzdWx0Lmhhc0hvb2tDb25mbGljdCkge1xuICAgICAgICAgICAgICBob29rQ29uZmxpY3RDb3JyZWxhdGlvbklkcy5wdXNoKHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyZXN1bHQuaGFzQXdhaXRlZEhvb2tDcmVhdGlvbikge1xuICAgICAgICAgICAgICBhd2FpdGVkSG9va0NvcnJlbGF0aW9uSWRzLnB1c2gocXVldWVJdGVtLmNvcnJlbGF0aW9uSWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3JlYXRpb25Db25mbGljdGVkID0gcmVzdWx0Lmhhc0hvb2tDb25mbGljdDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBEaXNwb3NlIGFmdGVyIGNyZWF0aW9uIGZvciBob29rcyBib3JuIGFuZCBkaXNwb3NlZCB3aXRoaW4gdGhpc1xuICAgICAgICAgIC8vIGJhdGNoLiBBIGhvb2sgd2hvc2UgY3JlYXRpb24gY29uZmxpY3RlZCB3YXMgbmV2ZXIgY3JlYXRlZCwgc29cbiAgICAgICAgICAvLyB0aGVyZSBpcyBub3RoaW5nIHRvIGRpc3Bvc2UuXG4gICAgICAgICAgaWYgKHF1ZXVlSXRlbS5kaXNwb3NlZCAmJiAhY3JlYXRpb25Db25mbGljdGVkKSB7XG4gICAgICAgICAgICBhd2FpdCBkaXNwb3NlSG9vayhxdWV1ZUl0ZW0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApO1xuICAgIGhvb2tDcmVhdGlvbk1zID0gRGF0ZS5ub3coKSAtIGhvb2tQaGFzZVN0YXJ0O1xuICB9XG5cbiAgLy8gUHJvY2VzcyBhYm9ydCByZXF1ZXN0czogcmVzdW1lIHRoZSBob29rIHdpdGggYWJvcnQgcGF5bG9hZCBhbmQgd3JpdGUgc3RyZWFtIHBhY2tldFxuICBjb25zdCBob29rc05lZWRpbmdBYm9ydCA9IGFsbEhvb2tJdGVtcy5maWx0ZXIoXG4gICAgKGl0ZW0pID0+IGl0ZW0uYWJvcnRSZXF1ZXN0ZWQgJiYgIWl0ZW0uZGlzcG9zZWRcbiAgKTtcblxuICBpZiAoaG9va3NOZWVkaW5nQWJvcnQubGVuZ3RoID4gMCkge1xuICAgIGF3YWl0IGVuc3VyZVJ1blJlYWR5KCk7XG4gICAgYXdhaXQgc2V0dGxlUGhhc2UoXG4gICAgICBob29rc05lZWRpbmdBYm9ydC5tYXAoYXN5bmMgKHF1ZXVlSXRlbSkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIC8vIERlaHlkcmF0ZSB0aGUgYWJvcnQgcGF5bG9hZCBmb3Igc3RvcmFnZVxuICAgICAgICAgIGNvbnN0IGFib3J0UGF5bG9hZCA9IGF3YWl0IGRlaHlkcmF0ZUlucHV0KFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBhYm9ydGVkOiB0cnVlLFxuICAgICAgICAgICAgICByZWFzb246IHF1ZXVlSXRlbS5hYm9ydFJlYXNvbixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHNvdXJjZTogJ2hvb2tfYWJvcnQnLFxuICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICApO1xuXG4gICAgICAgICAgLy8gQ3JlYXRlIGhvb2tfcmVjZWl2ZWQgZXZlbnQgd2l0aCBhYm9ydCBwYXlsb2FkXG4gICAgICAgICAgYXdhaXQgY3JlYXRlR3VhcmRlZCh7XG4gICAgICAgICAgICBldmVudFR5cGU6ICdob29rX3JlY2VpdmVkJyBhcyBjb25zdCxcbiAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgIHRva2VuOiBxdWV1ZUl0ZW0udG9rZW4sXG4gICAgICAgICAgICAgIHBheWxvYWQ6IGFib3J0UGF5bG9hZCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICAvLyBXcml0ZSBzdHJlYW0gY2FuY2VsbGF0aW9uIHBhY2tldCBmb3IgcmVhbC10aW1lIHN0ZXAgcHJvcGFnYXRpb24uXG4gICAgICAgICAgLy8gUmV1c2UgdGhlIHNhbWUgZGVoeWRyYXRlZCBwYXlsb2FkIGFzIHRoZSBob29rIGV2ZW50IHNvIHRoZSByZWFzb25cbiAgICAgICAgICAvLyByb3VuZC10cmlwcyB0aHJvdWdoIGBkZWh5ZHJhdGVTdGVwQXJndW1lbnRzYCAvIGBoeWRyYXRlU3RlcEFyZ3VtZW50c2BcbiAgICAgICAgICAvLyAoaGFuZGxlcyBET01FeGNlcHRpb24sIGN1c3RvbSBlcnJvcnMsIGVuY3J5cHRpb24sIGV0Yy4pIGluc3RlYWQgb2ZcbiAgICAgICAgICAvLyBiYXJlIEpTT04uc3RyaW5naWZ5IHdoaWNoIGxvc2VzIHR5cGUgaW5mb3JtYXRpb24gYW5kIGRyb3BzIHVuZGVmaW5lZC5cbiAgICAgICAgICAvLyBzdHJlYW1OYW1lIGlzIHNldCBvbiB0aGUgcXVldWUgaXRlbSBhdCBjb250cm9sbGVyIGNvbnN0cnVjdGlvbiB0aW1lXG4gICAgICAgICAgLy8gKHNlZSB3b3JrZmxvdy9hYm9ydC1jb250cm9sbGVyLnRzKS5cbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtTmFtZSA9IGdldEFib3J0U3RyZWFtSWRGcm9tVG9rZW4ocXVldWVJdGVtLnRva2VuKTtcbiAgICAgICAgICAgIGF3YWl0IHdvcmxkLnN0cmVhbXMud3JpdGUoXG4gICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICBzdHJlYW1OYW1lLFxuICAgICAgICAgICAgICBhYm9ydFBheWxvYWQgYXMgVWludDhBcnJheVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGF3YWl0IHdvcmxkLnN0cmVhbXMuY2xvc2UocnVuSWQsIHN0cmVhbU5hbWUpO1xuICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgLy8gQmVzdC1lZmZvcnQgc3RyZWFtIHdyaXRlOiBob29rIGV2ZW50IHByb3ZpZGVzIHRoZSBkdXJhYmxlIGZhbGxiYWNrXG4gICAgICAgICAgICBydW50aW1lTG9nZ2VyLmRlYnVnKFxuICAgICAgICAgICAgICAnRmFpbGVkIHRvIHdyaXRlIGFib3J0IHN0cmVhbSBwYWNrZXQsIGhvb2sgZXZlbnQgd2lsbCBwcm92aWRlIGZhbGxiYWNrJyxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSB8fCBSdW5FeHBpcmVkRXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAnV29ya2Zsb3cgcnVuIGFscmVhZHkgY29tcGxldGVkLCBza2lwcGluZyBhYm9ydCcsXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgLy8gQ3JlYXRlIHN0ZXAgZXZlbnRzIGZvciBzdGVwcyB0aGF0IGRvbid0IGhhdmUgdGhlbSB5ZXQuXG4gIC8vIFVubGlrZSBWMSwgd2UgZG8gTk9UIHF1ZXVlIHN0ZXAgbWVzc2FnZXMgZnJvbSBoZXJlOiB0aGUgY2FsbGVyXG4gIC8vIGRlY2lkZXMgd2hpY2ggc3RlcHMgdG8gZXhlY3V0ZSBpbmxpbmUgdnMuIHF1ZXVlIHRvIGJhY2tncm91bmQuXG4gIC8vIFdhaXQgZXZlbnRzIGFyZSBhbHNvIGNyZWF0ZWQgaW4gcGFyYWxsZWwgYmVsb3cuXG4gIGNvbnN0IHN0ZXBzTmVlZGluZ0NyZWF0aW9uID0gbmV3IFNldChcbiAgICBzdGVwSXRlbXNcbiAgICAgIC5maWx0ZXIoKHF1ZXVlSXRlbSkgPT4gIXF1ZXVlSXRlbS5oYXNDcmVhdGVkRXZlbnQpXG4gICAgICAubWFwKChxdWV1ZUl0ZW0pID0+IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKVxuICApO1xuXG4gIC8vIENvcnJlbGF0aW9uIElEcyBmb3Igd2hpY2ggVEhJUyBzdXNwZW5zaW9uIGNhbGwgYWN0dWFsbHkgd3JvdGUgdGhlXG4gIC8vIHN0ZXBfY3JlYXRlZCBldmVudC4gUG9wdWxhdGVkIGJ5IHRoZSBvcHMgYmVsb3cgYWZ0ZXIgYSBzdWNjZXNzZnVsXG4gIC8vIGV2ZW50cy5jcmVhdGUsIHVzZWQgYnkgdGhlIGNhbGxlciB0byBjbGFpbSBvd25lcnNoaXAgYW5kIGF2b2lkXG4gIC8vIHJhY2luZyB3aXRoIGNvbmN1cnJlbnQgaGFuZGxlcnMgb24gc3RlcCBleGVjdXRpb24uXG4gIGNvbnN0IGNyZWF0ZWRTdGVwQ29ycmVsYXRpb25JZHMgPSBuZXcgU2V0PHN0cmluZz4oKTtcblxuICAvLyBDb3JyZWxhdGlvbiBJRHMgb2Ygc3RlcHMgZmluYWxpemVkIGFzIGZhaWxlZCBiZWNhdXNlIHRoZWlyIGFyZ3VtZW50c1xuICAvLyByZWZ1c2VkIHRvIHNlcmlhbGl6ZTogc2VlIGZpbmFsaXplVW5zZXJpYWxpemFibGVTdGVwIGJlbG93LlxuICBjb25zdCBmYWlsZWRTdGVwQ29ycmVsYXRpb25JZHMgPSBuZXcgU2V0PHN0cmluZz4oKTtcblxuICAvKipcbiAgICogQSBzdGVwIHdob3NlIGFyZ3VtZW50cyBmYWlsIHRvIHNlcmlhbGl6ZSBpcyBkZXRlcm1pbmlzdGljOiBldmVyeSByZXBsYXlcbiAgICogcmUtZGVyaXZlcyB0aGUgc2FtZSB1bnNlcmlhbGl6YWJsZSB2YWx1ZSwgc28gcmVkZWxpdmVyaW5nIHRoZVxuICAgKiBvcmNoZXN0cmF0b3IgbWVzc2FnZSBjYW4gbmV2ZXIgc3VjY2VlZC4gSW5zdGVhZCBvZiByZWplY3RpbmcgdGhlIHdob2xlXG4gICAqIHN1c3BlbnNpb24gKHdoaWNoIGZhaWxzIHRoZSBydW4gZnJvbSB0aGUgb3V0c2lkZSwgd2hlcmUgbm8gdXNlciBjb2RlIGNhblxuICAgKiBvYnNlcnZlIGl0KSwgdHJlYXQgaXQgZXhhY3RseSBsaWtlIGEgc3RlcC1ib2R5IGZhaWx1cmU6IHdyaXRlXG4gICAqIGBzdGVwX2NyZWF0ZWRgIHdpdGggYSBwbGFjZWhvbGRlciBpbnB1dCAoZXZlcnkgV29ybGQgcmVxdWlyZXMgdGhlIHN0ZXBcbiAgICogZW50aXR5IHRvIGV4aXN0IGJlZm9yZSBhIHRlcm1pbmFsIHN0ZXAgZXZlbnQsIGFuZCB0aGUgcmVhbCBpbnB1dCBpc1xuICAgKiBwcmVjaXNlbHkgd2hhdCByZWZ1c2VkIHRvIHNlcmlhbGl6ZSkgZm9sbG93ZWQgYnkgYHN0ZXBfZmFpbGVkYCBjYXJyeWluZ1xuICAgKiB0aGUgU2VyaWFsaXphdGlvbkVycm9yLiBUaGUgbmV4dCByZXBsYXkgcmVqZWN0cyB0aGUgc3RlcCdzIHByb21pc2Ugd2l0aFxuICAgKiBpdCwgc28gYSB0cnkvY2F0Y2ggYXJvdW5kIHRoZSBzdGVwIGNhbGwgb2JzZXJ2ZXMgdGhlIGVycm9yOyB1bmNhdWdodCwgaXRcbiAgICogcHJvcGFnYXRlcyBvdXQgb2YgdGhlIHdvcmtmbG93IGJvZHkgYW5kIGZhaWxzIHRoZSBydW4gYXMgYSBVU0VSX0VSUk9SLFxuICAgKiB3aXRob3V0IGJ1cm5pbmcgcXVldWUgcmVkZWxpdmVyaWVzIGVpdGhlciB3YXkuXG4gICAqL1xuICBjb25zdCBmaW5hbGl6ZVVuc2VyaWFsaXphYmxlU3RlcCA9IGFzeW5jIChcbiAgICBxdWV1ZUl0ZW06IFN0ZXBJbnZvY2F0aW9uUXVldWVJdGVtLFxuICAgIGVycm9yOiBTZXJpYWxpemF0aW9uRXJyb3JcbiAgKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgcnVudGltZUxvZ2dlci53YXJuKFxuICAgICAgJ1N0ZXAgYXJndW1lbnRzIGZhaWxlZCB0byBzZXJpYWxpemU7IGZhaWxpbmcgdGhlIHN0ZXAgc28gdGhlICcgK1xuICAgICAgICAnd29ya2Zsb3cgY2FuIG9ic2VydmUgdGhlIGVycm9yJyxcbiAgICAgIHtcbiAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICBzdGVwTmFtZTogcXVldWVJdGVtLnN0ZXBOYW1lLFxuICAgICAgICBlcnJvcjogZXJyb3IubWVzc2FnZSxcbiAgICAgIH1cbiAgICApO1xuICAgIGF3YWl0IGVuc3VyZVJ1blJlYWR5KCk7XG4gICAgLy8gTWFya2VyIHBsYWNlaG9sZGVyIChub3QgZW1wdHkgYXJncyk6IGJ5dGUtaWRlbnRpY2FsLXRvLXplcm8tYXJncyB3b3VsZFxuICAgIC8vIG1ha2UgYHdvcmtmbG93IGluc3BlY3Qgc3RlcHNgIHNob3cgXCJubyBhcmd1bWVudHNcIiBmb3IgdGhlIG9uZSBzdGVwXG4gICAgLy8gd2hvc2UgZW50aXJlIHByb2JsZW0gd2FzIGl0cyBhcmd1bWVudHMuXG4gICAgY29uc3QgcGxhY2Vob2xkZXJJbnB1dCA9IChhd2FpdCBkZWh5ZHJhdGVTdGVwQXJndW1lbnRzKFxuICAgICAgdW5zZXJpYWxpemFibGVTdGVwSW5wdXRQbGFjZWhvbGRlcigpLFxuICAgICAgcnVuSWQsXG4gICAgICBlbmNyeXB0aW9uS2V5LFxuICAgICAgc3VzcGVuc2lvbi5nbG9iYWxUaGlzLFxuICAgICAgZmFsc2UsXG4gICAgICBjb21wcmVzc2lvblxuICAgICkpIGFzIFNlcmlhbGl6ZWREYXRhO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBjcmVhdGVHdWFyZGVkKFxuICAgICAgICB7XG4gICAgICAgICAgZXZlbnRUeXBlOiAnc3RlcF9jcmVhdGVkJyBhcyBjb25zdCxcbiAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICBzdGVwTmFtZTogcXVldWVJdGVtLnN0ZXBOYW1lLFxuICAgICAgICAgICAgd29ya2Zsb3dOYW1lOiBydW4ud29ya2Zsb3dOYW1lLFxuICAgICAgICAgICAgaW5wdXQ6IHBsYWNlaG9sZGVySW5wdXQsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgeyByZXF1ZXN0SWQgfVxuICAgICAgKTtcbiAgICB9IGNhdGNoIChjcmVhdGVFcnIpIHtcbiAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGNyZWF0ZUVycikpIHtcbiAgICAgICAgLy8gQSBjb25jdXJyZW50IGhhbmRsZXIgYWxyZWFkeSBjcmVhdGVkIHRoZSBzdGVwOiB0aGUgZmFpbHVyZSBpc1xuICAgICAgICAvLyBkZXRlcm1pbmlzdGljLCBzbyBpdCBpcyByYWNpbmcgdG93YXJkIHRoZSBzYW1lIHN0ZXBfZmFpbGVkIGJlbG93LlxuICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ1N0ZXAgYWxyZWFkeSBleGlzdHMsIGNvbnRpbnVpbmcnLCB7XG4gICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgbWVzc2FnZTogY3JlYXRlRXJyLm1lc3NhZ2UsXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIGlmIChSdW5FeHBpcmVkRXJyb3IuaXMoY3JlYXRlRXJyKSkge1xuICAgICAgICAvLyBSdW4gYWxyZWFkeSBmaW5pc2hlZDogbm90aGluZyB0byBvYnNlcnZlIHRoZSBmYWlsdXJlLlxuICAgICAgICByZXR1cm47XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBjcmVhdGVFcnI7XG4gICAgICB9XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBhd2FpdCBjcmVhdGVHdWFyZGVkKFxuICAgICAgICB7XG4gICAgICAgICAgZXZlbnRUeXBlOiAnc3RlcF9mYWlsZWQnIGFzIGNvbnN0LFxuICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgIHN0ZXBOYW1lOiBxdWV1ZUl0ZW0uc3RlcE5hbWUsXG4gICAgICAgICAgICAvLyBUaGUgZXJyb3IgaXRzZWxmIGlzIGEgcGxhaW4gV29ya2Zsb3dFcnJvciAobmFtZSwgbWVzc2FnZSB3aXRoXG4gICAgICAgICAgICAvLyBmcmFtZWQgaGludCwgY2F1c2UgY2hhaW4pLCBzZXJpYWxpemFibGUgZXZlbiB0aG91Z2ggdGhlIHN0ZXBcbiAgICAgICAgICAgIC8vIGlucHV0IHdhcyBub3QuIEVycm9yIGRldGVjdGlvbiBpcyByZWFsbS1pbmRlcGVuZGVudFxuICAgICAgICAgICAgLy8gKHR5cGVzLmlzTmF0aXZlRXJyb3IpLCBzbyB0aGUgaG9zdC1jcmVhdGVkIGVycm9yIHNlcmlhbGl6ZXNcbiAgICAgICAgICAgIC8vIHRoZSBzYW1lIHVuZGVyIGVpdGhlciBnbG9iYWw7IHRoZSBWTSBnbG9iYWwgaXMgcGFzc2VkIGZvclxuICAgICAgICAgICAgLy8gY29uc2lzdGVuY3kgd2l0aCBldmVyeSBvdGhlciBkZWh5ZHJhdGlvbiBpbiB0aGlzIGZpbGUgYW5kIHNvXG4gICAgICAgICAgICAvLyBhbnkgVk0tcmVhbG0gdmFsdWVzIGd1ZXN0IGNvZGUgdGhyZXcgaW50byB0aGUgY2F1c2UgY2hhaW5cbiAgICAgICAgICAgIC8vIChnZXR0ZXJzL3Byb3hpZXMgZXhlY3V0ZWQgZHVyaW5nIHRoZSBmYWlsZWQgZGVoeWRyYXRpb24pIGFyZVxuICAgICAgICAgICAgLy8gZGV0ZWN0ZWQgYnkgdGhlIHJlYWxtLXNlbnNpdGl2ZSByZWR1Y2Vycy5cbiAgICAgICAgICAgIGVycm9yOiBhd2FpdCBkZWh5ZHJhdGVTdGVwRXJyb3IoXG4gICAgICAgICAgICAgIGVycm9yLFxuICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgICAgICAgICAgW10sXG4gICAgICAgICAgICAgIHN1c3BlbnNpb24uZ2xvYmFsVGhpcyxcbiAgICAgICAgICAgICAgY29tcHJlc3Npb25cbiAgICAgICAgICAgICksXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgeyByZXF1ZXN0SWQgfVxuICAgICAgKTtcbiAgICB9IGNhdGNoIChmYWlsRXJyKSB7XG4gICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhmYWlsRXJyKSB8fCBSdW5FeHBpcmVkRXJyb3IuaXMoZmFpbEVycikpIHtcbiAgICAgICAgLy8gU3RlcCBhbHJlYWR5IHRlcm1pbmFsIChhIGNvbmN1cnJlbnQgaGFuZGxlciB3cm90ZSB0aGUgc2FtZVxuICAgICAgICAvLyBkZXRlcm1pbmlzdGljIGZhaWx1cmUpIG9yIHRoZSBydW4gYWxyZWFkeSBmaW5pc2hlZC5cbiAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICdUcmllZCBmYWlsaW5nIHN0ZXAsIGJ1dCBzdGVwIG9yIHJ1biBoYXMgYWxyZWFkeSBmaW5pc2hlZC4nLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICBtZXNzYWdlOiBmYWlsRXJyLm1lc3NhZ2UsXG4gICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgZmFpbEVycjtcbiAgICAgIH1cbiAgICB9XG4gICAgZmFpbGVkU3RlcENvcnJlbGF0aW9uSWRzLmFkZChxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCk7XG4gICAgLy8gUmVsZWFzZSB0aGUgaW5saW5lIHNsb3QgYm9va2tlZXBpbmc6IHRoZSBzdGVwIG5ldmVyIHJ1bnMsIHNvIGl0IG11c3RcbiAgICAvLyBub3QgYXBwZWFyIGluIHRoZSByZWJ1aWx0IGBsYXp5SW5saW5lU3RlcHNgLiAoSXRzIHNsb3QgaW4gdGhlIGZpcnN0LU5cbiAgICAvLyBzZWxlY3Rpb24gYW5kIGluIGBpbmxpbmVQYWlyRm9sZEVsaWdpYmxlYCdzIGFyaXRobWV0aWMgd2FzIGNvbnN1bWVkXG4gICAgLy8gYmVmb3JlIGRlaHlkcmF0aW9uIGNvdWxkIHJldmVhbCB0aGUgZmFpbHVyZSwgaW5oZXJlbnQgdG8gc2VsZWN0aW5nXG4gICAgLy8gYmVmb3JlIHNlcmlhbGl6aW5nLCBhbmQgYm91bmRlZCB0byBvbmUgd2FzdGVkIHNsb3Qgb24gYSBwYXNzIHRoYXRcbiAgICAvLyBlbmRzIGluIGEgZm9yY2VkIHJlcGxheSBhbnl3YXkuKVxuICAgIGxhenlJbmxpbmVDb3JyZWxhdGlvbklkcy5kZWxldGUocXVldWVJdGVtLmNvcnJlbGF0aW9uSWQpO1xuICB9O1xuXG4gIC8vIExhenkgaW5saW5lIHN0YXJ0OiBkZWZlciB0aGUgc3RlcF9jcmVhdGVkIHdyaXRlIGZvciB1cCB0b1xuICAvLyBgZ2V0TWF4SW5saW5lU3RlcHMoKWAgc3RlcHMgdGhlIGNhbGxlciB3aWxsIHJ1biBpbmxpbmUgKGluIHBhcmFsbGVsKS4gRWFjaFxuICAvLyBzdGVwIGlzIGNyZWF0ZWQgb24gdGhlIGZseSBieSB0aGUgbGF6eSBgc3RlcF9zdGFydGVkYCBleGVjdXRlU3RlcCBzZW5kc1xuICAvLyAoc2F2aW5nIGEgcm91bmQtdHJpcCBwZXIgc3RlcCkuIFdlIG5ldmVyIGRlZmVyIHdoZW4gYSBgaG9vay5nZXRDb25mbGljdCgpYFxuICAvLyBhd2FpdGVyIGlzIHByZXNlbnQsIGJlY2F1c2UgaW4gdGhhdCBjYXNlIHRoZSBjYWxsZXIgZXhlY3V0ZXMgbm90aGluZyBpbmxpbmVcbiAgLy8gKGl0IGNvbnRpbnVlcyB0aGUgd29ya2Zsb3cgdG8gcmVzb2x2ZSB0aGUgYXdhaXRlciBpbnN0ZWFkKSwgc28gZGVmZXJyaW5nXG4gIC8vIHdvdWxkIGxlYXZlIHRoZSBzdGVwcyB1bmNyZWF0ZWQgYW5kIHVucXVldWVkLiBXZSBwaWNrIHRoZSBmaXJzdCBOIHVuY3JlYXRlZFxuICAvLyBzdGVwcyDigJQgbWF0Y2hpbmcgdGhlIGNhbGxlcidzIGlubGluZS1jYW5kaWRhdGUgc2VsZWN0aW9uIOKAlCBhbmQgZGVoeWRyYXRlXG4gIC8vIHRoZWlyIGlucHV0IGhlcmUgc28gZXhlY3V0ZVN0ZXAgY2FuIHNoaXAgaXQgYXMgdGhlIHN0ZXBfc3RhcnRlZCBwYXlsb2FkLlxuICBjb25zdCBsYXp5SW5saW5lQ29ycmVsYXRpb25JZHMgPSBuZXcgU2V0PHN0cmluZz4oXG4gICAgYXdhaXRlZEhvb2tDb3JyZWxhdGlvbklkcy5sZW5ndGggPT09IDBcbiAgICAgID8gc3RlcEl0ZW1zXG4gICAgICAgICAgLmZpbHRlcigoaXRlbSkgPT4gc3RlcHNOZWVkaW5nQ3JlYXRpb24uaGFzKGl0ZW0uY29ycmVsYXRpb25JZCkpXG4gICAgICAgICAgLnNsaWNlKDAsIGdldE1heElubGluZVN0ZXBzKCkpXG4gICAgICAgICAgLm1hcCgoaXRlbSkgPT4gaXRlbS5jb3JyZWxhdGlvbklkKVxuICAgICAgOiBbXVxuICApO1xuICAvLyBDb2xsZWN0ZWQgYnkgY29ycmVsYXRpb25JZCBiZWNhdXNlIHRoZSBwZXItc3RlcCBvcHMgYmVsb3cgcnVuIGNvbmN1cnJlbnRseVxuICAvLyBhbmQgc2V0dGxlIG91dCBvZiBvcmRlci4gV2UgcmVidWlsZCB0aGUgYXJyYXkgaW4gZGV0ZXJtaW5pc3RpY1xuICAvLyBgbGF6eUlubGluZUNvcnJlbGF0aW9uSWRzYCBvcmRlciAodGhlIG9yZGVyZWQgc2xpY2UgYWJvdmUpIGFmdGVyIHRoZSBvcHNcbiAgLy8gc2V0dGxlLCBzbyB0aGUgaW5saW5lIGJhdGNoIG9yZGVyIGlzIHN0YWJsZSByZWdhcmRsZXNzIG9mIGRlaHlkcmF0aW9uIHRpbWluZy5cbiAgY29uc3QgbGF6eUlubGluZUJ5Q29ycmVsYXRpb25JZCA9IG5ldyBNYXA8XG4gICAgc3RyaW5nLFxuICAgIFN1c3BlbnNpb25IYW5kbGVyUmVzdWx0WydsYXp5SW5saW5lU3RlcHMnXVtudW1iZXJdXG4gID4oKTtcblxuICBjb25zdCBvcHM6IFByb21pc2U8dm9pZD5bXSA9IFtdO1xuXG4gIC8vIENvcnJlbGF0aW9uIElEcyBvZiBzdGVwcyB3aG9zZSBzdGVwLWV4ZWN1dGlvbiBxdWV1ZSBtZXNzYWdlIHdhcyBhbHJlYWR5XG4gIC8vIHB1Ymxpc2hlZCBieSB0aGUgcmVzaWxpZW50LWRpc3BhdGNoIG9wcyBiZWxvdyAoYWxvbmdzaWRlIHRoZSBzdGVwX2NyZWF0ZWRcbiAgLy8gd3JpdGUpLiBSZXBvcnRlZCB0byB0aGUgY2FsbGVyIHNvIGl0cyBkaXNwYXRjaCBwYXNzIHNraXBzIHRoZW0uXG4gIGNvbnN0IHF1ZXVlZFN0ZXBDb3JyZWxhdGlvbklkcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4gIC8vIFJlc2lsaWVudCBzdGVwIGRpc3BhdGNoIGVsaWdpYmlsaXR5LCBzaGFyZWQgYnkgZXZlcnkgc3RlcCBvcCBiZWxvdyAodGhlXG4gIC8vIHBlci1zdGVwIGlucHV0LXNpemUgY2hlY2sgaXMgYXBwbGllZCBpbnNpZGUgdGhlIG9wKS4gQWxsIG11c3QgaG9sZDpcbiAgLy9cbiAgLy8gIC0gVGhlIGNhbGxlciBwcm92aWRlZCBhIGRpc3BhdGNoIHRhcmdldCAoYHN0ZXBEaXNwYXRjaGApOiB0ZXJtaW5hbFxuICAvLyAgICBkcmFpbnMgYW5kIG90aGVyIGNyZWF0ZS1vbmx5IGNhbGxlcnMgbmV2ZXIgcXVldWUuXG4gIC8vICAtIFRoZSBmZWF0dXJlIGlzIGVuYWJsZWQgKGBXT1JLRkxPV19SRVNJTElFTlRfU1RFUF9ESVNQQVRDSGAgb3B0LWluKS5cbiAgLy8gICAgSXQgaXMgb2ZmIGJ5IGRlZmF1bHQgYmVjYXVzZSB0aGUgcHVibGlzaCByYWNlcyB0aGUgY3JlYXRlJ3MgdmVyZGljdCxcbiAgLy8gICAgYW5kIGEgY3JlYXRlIGNhbiBjb21lIGJhY2sgcmVmdXNlZDogYXMgYSBkdXBsaWNhdGUgdGhlIHJlcGxheSBzaG91bGRcbiAgLy8gICAgc3RvcCBwdXJzdWluZywgb3IgKG9uIGEgV29ybGQgdGhhdCB3b3VsZCByYXRoZXIgcmVmdXNlIGEgc3RhbGUgd3JpdGVcbiAgLy8gICAgdGhhbiByZXBvcnQgd2hhdCBpdCBtaXNzZWQpIGFzIGEgNDEyLiBFaXRoZXIgd2F5IHRoZSBxdWV1ZSBtZXNzYWdlXG4gIC8vICAgIGNhcnJ5aW5nIHRoZSBwYXlsb2FkIGlzIGFscmVhZHkgb3V0LCBhbmQgdGhlIGNvbnN1bWVyIGNhbiBtYXRlcmlhbGl6ZSBhXG4gIC8vICAgIHN0ZXAgd2hvc2UgY3JlYXRlIHdhcyByZWZ1c2VkLiBOb3RoaW5nIG9yZGVycyB0aGF0IHZlcmRpY3QgYmVmb3JlIHRoZVxuICAvLyAgICBjb25zdW1lcidzIHJlZGVsaXZlcnkgcmUtZW5zdXJlLCBzbyBubyBiYWNrZW5kLXNpZGUgcmV2b2NhdGlvblxuICAvLyAgICBib29ra2VlcGluZyBjYW4gY2xvc2UgdGhlIHdpbmRvdzogYSBiZXN0LWVmZm9ydCBtYXJrZXIgdGhhdCBmYWlscyBvcGVuXG4gIC8vICAgIGNhbm5vdCBjYXJyeSBhIGNvcnJlY3RuZXNzIHByb3BlcnR5LiBUaGUgc2VxdWVudGlhbCBwYXRoIGlzIHRoZSBvbmx5XG4gIC8vICAgIHRoaW5nIHRoYXQgZ2l2ZXMgdGhlIG1lc3NhZ2UgYSBoYXBwZW5zLWFmdGVyIGVkZ2Ugb3ZlciB0aGUgdmVyZGljdC5cbiAgLy8gIC0gVGhlIHJ1bidzIHF1ZXVlIHRyYW5zcG9ydCBwcmVzZXJ2ZXMgYmluYXJ5IHBheWxvYWRzIChDQk9SLFxuICAvLyAgICBzcGVjVmVyc2lvbiA+PSAzKTogYHN0ZXBJbnB1dC5pbnB1dGAgaXMgdGhlIHNlcmlhbGl6ZWQgKHBvc3NpYmx5XG4gIC8vICAgIGVuY3J5cHRlZCkgaW5wdXQgYnl0ZXMsIHdoaWNoIHRoZSBKU09OIHRyYW5zcG9ydCB3b3VsZCBtYW5nbGUuXG4gIGNvbnN0IHJlc2lsaWVudERpc3BhdGNoRWxpZ2libGUgPVxuICAgIHN0ZXBEaXNwYXRjaCAhPT0gdW5kZWZpbmVkICYmXG4gICAgaXNSZXNpbGllbnRTdGVwRGlzcGF0Y2hFbmFibGVkKCkgJiZcbiAgICAocnVuLnNwZWNWZXJzaW9uID8/IDApID49IFNQRUNfVkVSU0lPTl9TVVBQT1JUU19DQk9SX1FVRVVFX1RSQU5TUE9SVDtcblxuICAvLyBCYXRjaGVkIGZhbi1vdXQ6IGZvbGQgdGhpcyBzdXNwZW5zaW9uJ3Mgc3RlcF9jcmVhdGVkICsgd2FpdF9jcmVhdGVkXG4gIC8vIHdyaXRlcyBpbnRvIG9uZSBgZXZlbnRzLmNyZWF0ZUJhdGNoYCBjYWxsIChvbmUgZHVyYWJsZSB3cml0ZSwgcGVyLWV2ZW50XG4gIC8vIG91dGNvbWVzKSBpbnN0ZWFkIG9mIG9uZSB3cml0ZSBwZXIgZXZlbnQuIEVuZ2FnZXMgb25seSBmb3IgYSBDTEVBTlxuICAvLyBmYW4tb3V0IChubyBhdHRyaWJ1dGUgd3JpdGVzLCBubyBob29rIHdyaXRlcywgbm8gcmVzaWxpZW50IGRpc3BhdGNoXG4gIC8vIHdob3NlIGNyZWF0ZXMgYXJlIGVhY2ggcGFpcmVkIHdpdGggYSBxdWV1ZSBwdWJsaXNoKSBvbiBhIFdvcmxkIHRoYXRcbiAgLy8gaW1wbGVtZW50cyB0aGUgb3B0aW9uYWwgbWV0aG9kIGFuZCBhIHJ1biB3aG9zZSBldmVudHMgYXJlIHNsb3QtbnVtYmVyZWQuXG4gIC8vIEV2ZXJ5dGhpbmcgb3V0c2lkZSB0aGUgZ2F0ZSBrZWVwcyB0aGUgc2luZ2xlLWV2ZW50IHBhdGggYnl0ZS1mb3ItYnl0ZS5cbiAgY29uc3QgYmF0Y2hGYW5vdXRFbGlnaWJsZSA9XG4gICAgaXNCYXRjaFRyYW5zaXRpb25zRW5hYmxlZCgpICYmXG4gICAgdHlwZW9mIHdvcmxkLmV2ZW50cy5jcmVhdGVCYXRjaCA9PT0gJ2Z1bmN0aW9uJyAmJlxuICAgIChydW4uc3BlY1ZlcnNpb24gPz8gMCkgPj0gU1BFQ19WRVJTSU9OX1NVUFBPUlRTX1NMT1RfSURFTlRJVFkgJiZcbiAgICAhcmVzaWxpZW50RGlzcGF0Y2hFbGlnaWJsZSAmJlxuICAgIGFsbEhvb2tJdGVtcy5sZW5ndGggPT09IDAgJiZcbiAgICBhdHRyaWJ1dGVJdGVtcy5sZW5ndGggPT09IDA7XG4gIC8qKlxuICAgKiBUaGUgZm9sZCdzIGNvbGxlY3Rpb24sIGluIHNjaGVkdWxpbmcgb3JkZXIgKHN0ZXBzIGluIHN0ZXBJdGVtcyBvcmRlcixcbiAgICogdGhlbiB3YWl0cykuIFN0ZXAgZW50cmllcyBhcmUgZW5xdWV1ZWQgYnkgdGhlaXIgcHJlcCBwcm9taXNlcyAoaW5wdXRcbiAgICogZGVoeWRyYXRpb24gcnVucyBjb25jdXJyZW50bHksIHNvIGVudHJpZXMgYXJlIG9yZGVyZWQgYnkgYG9yZGVyYCwgbm90IGJ5XG4gICAqIGNvbXBsZXRpb24pOyB0aGUgc2luZ2xlIGZsdXNoIG9wIGJlbG93IGF3YWl0cyBldmVyeSBwcmVwLCBzb3J0cywgYW5kXG4gICAqIGNvbW1pdHMgdGhlIHdob2xlIHNldCB0aHJvdWdoIGBjcmVhdGVCYXRjaGAuXG4gICAqL1xuICBjb25zdCBiYXRjaFF1ZXVlOiB7XG4gICAgb3JkZXI6IG51bWJlcjtcbiAgICBraW5kOiAnc3RlcCcgfCAnd2FpdCcgfCAnaW5saW5lLWNyZWF0ZWQnIHwgJ2lubGluZS1zdGFydGVkJztcbiAgICBjb3JyZWxhdGlvbklkOiBzdHJpbmc7XG4gICAgLyoqIFRoZSBzdGVwJ3MgbmFtZSwgc2V0IG9uIHN0ZXAtY2Fycnlpbmcga2luZHMgKHRoZSBpbi1mbHVzaCBwdWJsaXNoZXNcbiAgICAgKiAgYW5kIHRoZSBkaXNwYXRjaCBpZGVtcG90ZW5jeSBrZXkgbmVlZCBpdCkuICovXG4gICAgc3RlcE5hbWU/OiBzdHJpbmc7XG4gICAgZXZlbnQ6IENyZWF0ZUV2ZW50UmVxdWVzdDtcbiAgfVtdID0gW107XG4gIGNvbnN0IGJhdGNoUHJlcHM6IFByb21pc2U8dm9pZD5bXSA9IFtdO1xuXG4gIC8vIFByZS1jbGFpbWVkIGlubGluZSBwYWlyczogZm9sZCBlYWNoIGxhenktaW5saW5lIHN0ZXAncyBkZWZlcnJlZFxuICAvLyBgc3RlcF9jcmVhdGVkYCAoY2FycnlpbmcgaXRzIGlucHV0KSBBTkQgaXRzIGBzdGVwX3N0YXJ0ZWRgIGNsYWltIChiYXJlLFxuICAvLyBvd25lcnNoaXAtc3RhbXBlZCkgaW50byB0aGUgYmF0Y2gsIHNvIHRoZSB3aG9sZSBmYW4tb3V0ICh0aGUgaW5saW5lXG4gIC8vIHN0ZXBzJyBjbGFpbXMgaW5jbHVkZWQpIGNvbW1pdHMgaW4gdGhlIG9uZSBkdXJhYmxlIHdyaXRlIGFuZCB0aGUgY2FsbGVyXG4gIC8vIHN0YXJ0cyB0aGUgYm9kaWVzIHN0cmFpZ2h0IG9mZiB0aGF0IGNvbW1pdCBpbnN0ZWFkIG9mIHBvc3Rpbmcgb25lIGNsYWltXG4gIC8vIHBlciBpbmxpbmUgc3RlcC4gVGhlIGxvbmUtaW5saW5lIGNhc2UgKG5vdGhpbmcgZWxzZSB0byBiYXRjaCB3aXRoKSBpc1xuICAvLyBleGNsdWRlZDogYSBwYWlyLW9ubHkgYmF0Y2ggY29zdHMgdGhlIHNhbWUgcm91bmQgdHJpcCBhcyB0aGUgc2luZ2xlIGxhenlcbiAgLy8gY2xhaW0gd2hpbGUgZ2l2aW5nIHVwIHRoZSBvcHRpbWlzdGljIGNsYWltL2JvZHkgb3ZlcmxhcCBhbmQgdGhlXG4gIC8vIGJ1bXAtYW5kLXJlcG9ydCB0aGF0IGBjcmVhdGVHdWFyZGVkYCBwcm92aWRlcywgc28gaXQgc3RheXMgb24gdGhlIGxhenlcbiAgLy8gcGF0aC4gUmVxdWlyZXMgdGhlIGNhbGxlcidzIGBvd25lck1lc3NhZ2VJZGA6IHRoZSBzdGFydGVkIHJvdyBtdXN0XG4gIC8vIHN0YW1wIG93bmVyc2hpcCBleGFjdGx5IGxpa2UgdGhlIGxhenkgY2xhaW0gaXQgcmVwbGFjZXMgKGFuZCBhIGNhbGxlclxuICAvLyB0aGF0IGRvZXMgbm90IGlubGluZS1leGVjdXRlIG5ldmVyIHByb3ZpZGVzIG9uZSkuXG4gIGNvbnN0IHVuY3JlYXRlZFdhaXRDb3VudCA9IHdhaXRJdGVtcy5maWx0ZXIoXG4gICAgKGl0ZW0pID0+ICFpdGVtLmhhc0NyZWF0ZWRFdmVudFxuICApLmxlbmd0aDtcbiAgY29uc3QgaW5saW5lUGFpckZvbGRFbGlnaWJsZSA9XG4gICAgYmF0Y2hGYW5vdXRFbGlnaWJsZSAmJlxuICAgIG93bmVyTWVzc2FnZUlkICE9PSB1bmRlZmluZWQgJiZcbiAgICBsYXp5SW5saW5lQ29ycmVsYXRpb25JZHMuc2l6ZSA+IDAgJiZcbiAgICAobGF6eUlubGluZUNvcnJlbGF0aW9uSWRzLnNpemUgPj0gMiB8fFxuICAgICAgc3RlcHNOZWVkaW5nQ3JlYXRpb24uc2l6ZSAtXG4gICAgICAgIGxhenlJbmxpbmVDb3JyZWxhdGlvbklkcy5zaXplICtcbiAgICAgICAgdW5jcmVhdGVkV2FpdENvdW50ID49XG4gICAgICAgIDEpO1xuICBjb25zdCBpbmxpbmVDbGFpbXM6IFN1c3BlbnNpb25IYW5kbGVyUmVzdWx0WydpbmxpbmVDbGFpbXMnXSA9IG5ldyBNYXAoKTtcbiAgbGV0IGJhdGNoQ29tbWl0dGVkU2xvdENlaWxpbmc6IG51bWJlciB8IHVuZGVmaW5lZDtcblxuICAvLyBUaGUgdHJhY2UgY2FycmllciBmb3IgcmVzaWxpZW50IHN0ZXAgZGlzcGF0Y2hlcywgcmVzb2x2ZWQgYXQgbW9zdCBvbmNlIHBlclxuICAvLyBzdXNwZW5zaW9uICh0aGUgcGVyLXN0ZXAgb3BzIHJ1biBjb25jdXJyZW50bHkgYW5kIHNoYXJlIGl0KS5cbiAgbGV0IHN0ZXBEaXNwYXRjaFRyYWNlQ2FycmllcjogUHJvbWlzZTxUcmFjZUNhcnJpZXI+IHwgdW5kZWZpbmVkO1xuICBjb25zdCBnZXRTdGVwRGlzcGF0Y2hUcmFjZUNhcnJpZXIgPSAoKTogUHJvbWlzZTxUcmFjZUNhcnJpZXI+ID0+IHtcbiAgICBzdGVwRGlzcGF0Y2hUcmFjZUNhcnJpZXIgPz89XG4gICAgICBzdGVwRGlzcGF0Y2g/LmdldFRyYWNlQ2FycmllcigpID8/IFByb21pc2UucmVzb2x2ZSh7fSk7XG4gICAgcmV0dXJuIHN0ZXBEaXNwYXRjaFRyYWNlQ2FycmllcjtcbiAgfTtcblxuICAvLyBQcm9kdWNlci1zaWRlIHJlc2lsaWVudCByZWNvdmVyeSBjb3VudCBmb3IgdGhlIHN1c3BlbnNpb24gc3BhbiBhdHRyaWJ1dGUuXG4gIGxldCByZXNpbGllbnREaXNwYXRjaFJlY292ZXJlZCA9IDA7XG5cbiAgLy8gU3RlcHM6IGNyZWF0ZSBzdGVwX2NyZWF0ZWQgZXZlbnRzIChubyBxdWV1aW5nLCBWMiByZXR1cm5zIHBlbmRpbmcgc3RlcHNcbiAgLy8gdG8gY2FsbGVyLCBFWENFUFQgb24gdGhlIHJlc2lsaWVudCBkaXNwYXRjaCBwYXRoLCB3aGljaCBwYXJhbGxlbGl6ZXMgdGhlXG4gIC8vIGNyZWF0ZSB3aXRoIHRoZSBzdGVwJ3MgcXVldWUgcHVibGlzaCBhbmQgcmVwb3J0cyBpdCBpblxuICAvLyBgcXVldWVkU3RlcENvcnJlbGF0aW9uSWRzYCkuXG4gIGxldCBiYXRjaE9yZGVyQ291bnRlciA9IDA7XG4gIGZvciAoY29uc3QgcXVldWVJdGVtIG9mIHN0ZXBJdGVtcykge1xuICAgIGlmIChzdGVwc05lZWRpbmdDcmVhdGlvbi5oYXMocXVldWVJdGVtLmNvcnJlbGF0aW9uSWQpKSB7XG4gICAgICAvLyBEZXRlcm1pbmlzdGljIHBvc2l0aW9uIGluIHRoZSBiYXRjaGVkIGZvbGQgKGFzc2lnbmVkIGluIHN0ZXBJdGVtc1xuICAgICAgLy8gb3JkZXIsIGJlZm9yZSB0aGUgY29uY3VycmVudCBkZWh5ZHJhdGlvbiBydW5zKS4gQSBwYWlyLWZvbGRlZCBpbmxpbmVcbiAgICAgIC8vIHN0ZXAgb2NjdXBpZXMgdHdvIGNvbnNlY3V0aXZlIHBvc2l0aW9ucyAoY3JlYXRlZCByb3cgdGhlbiBzdGFydGVkXG4gICAgICAvLyByb3cpLCB3aGljaCB0aGUgZmx1c2gga2VlcHMgYWRqYWNlbnQgYW5kIG5ldmVyIHNwbGl0cyBhY3Jvc3MgY2h1bmtzLFxuICAgICAgLy8gc28gYSBXb3JsZCBjYW4gZm9sZCB0aGVtIGludG8gb25lIGJvcm4tcnVubmluZyBjcmVhdGUuXG4gICAgICBjb25zdCBwYWlyRm9sZGVkID1cbiAgICAgICAgaW5saW5lUGFpckZvbGRFbGlnaWJsZSAmJlxuICAgICAgICBsYXp5SW5saW5lQ29ycmVsYXRpb25JZHMuaGFzKHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKTtcbiAgICAgIGNvbnN0IHN0ZXBPcmRlciA9IGJhdGNoT3JkZXJDb3VudGVyO1xuICAgICAgYmF0Y2hPcmRlckNvdW50ZXIgKz0gcGFpckZvbGRlZCA/IDIgOiAxO1xuICAgICAgY29uc3Qgc3RlcE9wID0gKGFzeW5jICgpID0+IHtcbiAgICAgICAgbGV0IGRlaHlkcmF0ZWRJbnB1dDogU2VyaWFsaXplZERhdGE7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZGVoeWRyYXRlZElucHV0ID0gYXdhaXQgZGVoeWRyYXRlSW5wdXQoXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGFyZ3M6IHF1ZXVlSXRlbS5hcmdzLFxuICAgICAgICAgICAgICBjbG9zdXJlVmFyczogcXVldWVJdGVtLmNsb3N1cmVWYXJzLFxuICAgICAgICAgICAgICB0aGlzVmFsOiBxdWV1ZUl0ZW0udGhpc1ZhbCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHNvdXJjZTogJ3N0ZXBfaW5wdXQnLFxuICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICApO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBpZiAoIVNlcmlhbGl6YXRpb25FcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAvLyBlLmcuIFJ1bnRpbWVEZWNyeXB0aW9uRXJyb3I6IGFuIFNESyBmYXVsdCwgbm90IGEgdXNlciB2YWx1ZVxuICAgICAgICAgICAgLy8gcHJvYmxlbS4gS2VlcCBpdHMgaWRlbnRpdHkgKFJVTlRJTUVfRVJST1IpIGFuZCBjdXJyZW50XG4gICAgICAgICAgICAvLyBmYWlsLXRoZS1zdXNwZW5zaW9uIGJlaGF2aW9yLlxuICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIXN0ZXBEaXNwYXRjaCkge1xuICAgICAgICAgICAgLy8gTm8gZGlzcGF0Y2ggdGFyZ2V0IG1lYW5zIG5vIHJlcGxheSB3aWxsIG9ic2VydmUgYVxuICAgICAgICAgICAgLy8gZmluYWxpemF0aW9uOiB0aGlzIGlzIHRoZSB0ZXJtaW5hbCBkcmFpbiAob3IgYSBjcmVhdGUtb25seVxuICAgICAgICAgICAgLy8gdGVzdCBjYWxsZXIpLiBUaGUgcnVuIGlzIGFscmVhZHkgY29tcGxldGluZy9mYWlsaW5nLCBzb1xuICAgICAgICAgICAgLy8gd3JpdGluZyBzdGVwX2NyZWF0ZWQgKyBzdGVwX2ZhaWxlZCBoZXJlIHdvdWxkIGxlYXZlIGUuZy4gYVxuICAgICAgICAgICAgLy8gQ09NUExFVEVEIHJ1biBjYXJyeWluZyBhIGZhaWxlZCBzdGVwIG5vdGhpbmcgY2FuIGV2ZXJcbiAgICAgICAgICAgIC8vIG9ic2VydmUsIHJlYWRpbmcgYXMgYSBidWcgZnJvbSB0aGUgZGFzaGJvYXJkLiBSZXRocm93XG4gICAgICAgICAgICAvLyBpbnN0ZWFkOyB0aGUgZHJhaW4ncyBvd24gY2F0Y2ggc3dhbGxvd3MgaXQsIHByZXNlcnZpbmcgaXRzXG4gICAgICAgICAgICAvLyBwcmUtZXhpc3RpbmcgYmVoYXZpb3IgKG5vIHJvd3MgZm9yIHRoZSB1bmF3YWl0ZWQgc3RlcCkuXG4gICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgfVxuICAgICAgICAgIGF3YWl0IGZpbmFsaXplVW5zZXJpYWxpemFibGVTdGVwKHF1ZXVlSXRlbSwgZXJyKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gRGVmZXJyZWQgKGxhenkpIGlubGluZSBzdGVwOiBza2lwIHRoZSBzdGVwX2NyZWF0ZWQgd3JpdGUg4oCUIHRoZVxuICAgICAgICAvLyBjYWxsZXIncyBpbmxpbmUgZXhlY3V0ZVN0ZXAgd2lsbCBzZW5kIGEgbGF6eSBzdGVwX3N0YXJ0ZWQgY2FycnlpbmdcbiAgICAgICAgLy8gdGhpcyBpbnB1dCwgYW5kIHRoZSB3b3JsZCBjcmVhdGVzIHRoZSBzdGVwIChlbnRpdHkgKyBzeW50aGV0aWNcbiAgICAgICAgLy8gc3RlcF9jcmVhdGVkIGV2ZW50KSBhdG9taWNhbGx5LiBXZSBkbyBOT1QgYWRkIGl0IHRvXG4gICAgICAgIC8vIGNyZWF0ZWRTdGVwQ29ycmVsYXRpb25JZHM7IG93bmVyc2hpcCBpcyBkZWNpZGVkIGJ5IHRoYXQgbGF6eVxuICAgICAgICAvLyBzdGVwX3N0YXJ0ZWQncyBhdG9taWMgY3JlYXRlLWNsYWltIGluc3RlYWQuXG4gICAgICAgIGlmIChsYXp5SW5saW5lQ29ycmVsYXRpb25JZHMuaGFzKHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKSkge1xuICAgICAgICAgIGxhenlJbmxpbmVCeUNvcnJlbGF0aW9uSWQuc2V0KHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLCB7XG4gICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgIHN0ZXBOYW1lOiBxdWV1ZUl0ZW0uc3RlcE5hbWUsXG4gICAgICAgICAgICBkZWh5ZHJhdGVkSW5wdXQsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgaWYgKHBhaXJGb2xkZWQpIHtcbiAgICAgICAgICAgIC8vIEVucXVldWUgdGhlIHBhaXIgdGhlIGRlZmVycmFsIHdvdWxkIG90aGVyd2lzZSBsZWF2ZSB0byB0aGVcbiAgICAgICAgICAgIC8vIGNhbGxlcidzIGxhenkgYHN0ZXBfc3RhcnRlZGA6IHRoZSBjcmVhdGVkIHJvdyBjYXJyaWVzIHRoZVxuICAgICAgICAgICAgLy8gaW5wdXQgKHBheWxvYWRzIHJpZGUgY3JlYXRlcyBpbiBhIGJhdGNoKSwgdGhlIHN0YXJ0ZWQgcm93IGlzXG4gICAgICAgICAgICAvLyBiYXJlIGFuZCBzdGFtcHMgdGhpcyBpbnZvY2F0aW9uJ3Mgb3duZXJzaGlwLCB0aGUgc2FtZSBjbGFpbVxuICAgICAgICAgICAgLy8gc2hhcGUgdGhlIGxhenkgc3RhcnQgd291bGQgaGF2ZSBzZW50LCBzZXR0bGVkIGJ5IHRoZSBiYXRjaC5cbiAgICAgICAgICAgIGJhdGNoUXVldWUucHVzaCh7XG4gICAgICAgICAgICAgIG9yZGVyOiBzdGVwT3JkZXIsXG4gICAgICAgICAgICAgIGtpbmQ6ICdpbmxpbmUtY3JlYXRlZCcsXG4gICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICBldmVudDoge1xuICAgICAgICAgICAgICAgIGV2ZW50VHlwZTogJ3N0ZXBfY3JlYXRlZCcsXG4gICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgICAgc3RlcE5hbWU6IHF1ZXVlSXRlbS5zdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgIHdvcmtmbG93TmFtZTogcnVuLndvcmtmbG93TmFtZSxcbiAgICAgICAgICAgICAgICAgIGlucHV0OiBkZWh5ZHJhdGVkSW5wdXQgYXMgU2VyaWFsaXplZERhdGEsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgYmF0Y2hRdWV1ZS5wdXNoKHtcbiAgICAgICAgICAgICAgb3JkZXI6IHN0ZXBPcmRlciArIDEsXG4gICAgICAgICAgICAgIGtpbmQ6ICdpbmxpbmUtc3RhcnRlZCcsXG4gICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICBldmVudDoge1xuICAgICAgICAgICAgICAgIGV2ZW50VHlwZTogJ3N0ZXBfc3RhcnRlZCcsXG4gICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgICAgc3RlcE5hbWU6IHF1ZXVlSXRlbS5zdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgIC8vIENoZWNrZWQgYnkgaW5saW5lUGFpckZvbGRFbGlnaWJsZTsgc3ByZWFkIGtlZXBzIHRoZVxuICAgICAgICAgICAgICAgICAgLy8gbmFycm93LXRocm91Z2gtY2xvc3VyZSBwcm9ibGVtIGF3YXkgZnJvbSB0aGUgdHlwZS5cbiAgICAgICAgICAgICAgICAgIC4uLihvd25lck1lc3NhZ2VJZCAhPT0gdW5kZWZpbmVkID8geyBvd25lck1lc3NhZ2VJZCB9IDoge30pLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHN0ZXBFdmVudDogQ3JlYXRlRXZlbnRSZXF1ZXN0ID0ge1xuICAgICAgICAgIGV2ZW50VHlwZTogJ3N0ZXBfY3JlYXRlZCcgYXMgY29uc3QsXG4gICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgc3RlcE5hbWU6IHF1ZXVlSXRlbS5zdGVwTmFtZSxcbiAgICAgICAgICAgIHdvcmtmbG93TmFtZTogcnVuLndvcmtmbG93TmFtZSxcbiAgICAgICAgICAgIGlucHV0OiBkZWh5ZHJhdGVkSW5wdXQgYXMgU2VyaWFsaXplZERhdGEsXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBSZXNpbGllbnQgc3RlcCBkaXNwYXRjaDogZmlyZSB0aGUgc3RlcF9jcmVhdGVkIHdyaXRlIGFuZCB0aGVcbiAgICAgICAgLy8gc3RlcC1leGVjdXRpb24gcXVldWUgcHVibGlzaCBpbiBwYXJhbGxlbDogdGhlIG1lc3NhZ2UgY2FycmllcyB0aGVcbiAgICAgICAgLy8gc2FtZSBzZXJpYWxpemVkIGlucHV0IChgc3RlcElucHV0YCkgc28gdGhlIGNvbnN1bWVyIGNhblxuICAgICAgICAvLyBpZGVtcG90ZW50bHkgcmUtZW5zdXJlIHRoZSBldmVudCBpZiB0aGUgZGlyZWN0IHdyaXRlIGZhaWxlZFxuICAgICAgICAvLyB0cmFuc2llbnRseS4gTWlycm9ycyB0aGUgcmVzaWxpZW50IHN0YXJ0IChgcnVuSW5wdXRgKSBhbmRcbiAgICAgICAgLy8gcmVzaWxpZW50IGhvb2sgcmVzdW1lIChgaG9va0lucHV0YCkgcGF0dGVybnMuIE9ubHkgZm9yIGlucHV0cyB0aGVcbiAgICAgICAgLy8gcXVldWUgbWVzc2FnZSBjYW4gc2FmZWx5IGNhcnJ5IChiaW5hcnksIHVuZGVyIHRoZSBWUVMgc2l6ZSBjYXApLlxuICAgICAgICBpZiAoXG4gICAgICAgICAgcmVzaWxpZW50RGlzcGF0Y2hFbGlnaWJsZSAmJlxuICAgICAgICAgIGRlaHlkcmF0ZWRJbnB1dCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkgJiZcbiAgICAgICAgICBkZWh5ZHJhdGVkSW5wdXQuYnl0ZUxlbmd0aCA8PSBNQVhfUkVTSUxJRU5UX1NURVBfSU5QVVRfQllURVNcbiAgICAgICAgKSB7XG4gICAgICAgICAgYXdhaXQgZW5zdXJlUnVuUmVhZHkoKTtcbiAgICAgICAgICBjb25zdCB0cmFjZUNhcnJpZXIgPSBhd2FpdCBnZXRTdGVwRGlzcGF0Y2hUcmFjZUNhcnJpZXIoKTtcbiAgICAgICAgICBjb25zdCBbY3JlYXRlUmVzdWx0LCBxdWV1ZVJlc3VsdF0gPSBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQoW1xuICAgICAgICAgICAgY3JlYXRlR3VhcmRlZChzdGVwRXZlbnQsIHsgcmVxdWVzdElkIH0pLFxuICAgICAgICAgICAgcXVldWVNZXNzYWdlKFxuICAgICAgICAgICAgICB3b3JsZCxcbiAgICAgICAgICAgICAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3R5bGUvbm9Ob25OdWxsQXNzZXJ0aW9uOiBpbXBsaWVkIGJ5IHJlc2lsaWVudERpc3BhdGNoRWxpZ2libGVcbiAgICAgICAgICAgICAgc3RlcERpc3BhdGNoIS5xdWV1ZU5hbWUsXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgICBzdGVwSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgIHN0ZXBOYW1lOiBxdWV1ZUl0ZW0uc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgdHJhY2VDYXJyaWVyLFxuICAgICAgICAgICAgICAgIHJlcXVlc3RlZEF0OiBuZXcgRGF0ZSgpLFxuICAgICAgICAgICAgICAgIHN0ZXBJbnB1dDogeyBpbnB1dDogZGVoeWRyYXRlZElucHV0IH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIC8vIFNhbWUga2V5IGFzIHRoZSBjYWxsZXIncyBkaXNwYXRjaCBwYXNzIGFuZCBhbnkgY29uY3VycmVudFxuICAgICAgICAgICAgICAvLyBoYW5kbGVyJ3MsIHNvIHJlZHVuZGFudCBwdWJsaXNoZXMgZm9yIHRoaXMgc3RlcCBkZWR1cGUuIFRoZVxuICAgICAgICAgICAgICAvLyBrZXkgaXMgc3RlcC1pZGVudGl0eS1zY29wZWQgc28gYSByZXZva2VkIG1lc3NhZ2UgZm9yIGFcbiAgICAgICAgICAgICAgLy8gcmVhc3NpZ25lZCBjb3JyZWxhdGlvbiBpZCBjYW5ub3QgYWJzb3JiIHRoZSBjb3JyZWN0ZWRcbiAgICAgICAgICAgICAgLy8gc2NoZWR1bGUncyBkaXNwYXRjaDogc2VlIHN0ZXBEaXNwYXRjaElkZW1wb3RlbmN5S2V5LlxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgaWRlbXBvdGVuY3lLZXk6IHN0ZXBEaXNwYXRjaElkZW1wb3RlbmN5S2V5KFxuICAgICAgICAgICAgICAgICAgcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgICBxdWV1ZUl0ZW0uc3RlcE5hbWVcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApLFxuICAgICAgICAgIF0pO1xuICAgICAgICAgIC8vIFF1ZXVlIGZhaWx1cmUgaXMgYWx3YXlzIGZhdGFsIGZvciB0aGlzIHN1c3BlbnNpb24gcGFzczogd2l0aG91dFxuICAgICAgICAgIC8vIHRoZSBtZXNzYWdlIHRoZSBzdGVwIHdvdWxkIHJlbHkgb24gdGhlIGNyZWF0ZSBhbG9uZSwgYW5kIGlmIHRoZVxuICAgICAgICAgIC8vIGNyZWF0ZSBBTFNPIGZhaWxlZCB0aGVyZSB3b3VsZCBiZSBubyBkdXJhYmxlIHJlY29yZCBhdCBhbGwuXG4gICAgICAgICAgLy8gUHJvcGFnYXRpbmcgcmVkZWxpdmVycyB0aGUgb3JjaGVzdHJhdG9yIG1lc3NhZ2UsIHdoaWNoXG4gICAgICAgICAgLy8gcmUtY3JlYXRlcyB0aGUgKGlkZW1wb3RlbnQpIHN0ZXBfY3JlYXRlZCBhbmQgcmUtZGlzcGF0Y2hlcyxcbiAgICAgICAgICAvLyB0aGUgc2FtZSByZWNvdmVyeSBhcyB0aGUgc2VxdWVudGlhbCBwYXRoLlxuICAgICAgICAgIGlmIChxdWV1ZVJlc3VsdC5zdGF0dXMgPT09ICdyZWplY3RlZCcpIHtcbiAgICAgICAgICAgIHRocm93IHF1ZXVlUmVzdWx0LnJlYXNvbjtcbiAgICAgICAgICB9XG4gICAgICAgICAgcXVldWVkU3RlcENvcnJlbGF0aW9uSWRzLmFkZChxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCk7XG4gICAgICAgICAgaWYgKGNyZWF0ZVJlc3VsdC5zdGF0dXMgPT09ICdyZWplY3RlZCcpIHtcbiAgICAgICAgICAgIGNvbnN0IGVyciA9IGNyZWF0ZVJlc3VsdC5yZWFzb247XG4gICAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgIC8vIENvbmN1cnJlbnQgaGFuZGxlciB3cm90ZSBpdCBmaXJzdCwgc2FtZSBhcyB0aGUgc2VxdWVudGlhbFxuICAgICAgICAgICAgICAvLyBwYXRoLiBUaGUgc3RlcCBtZXNzYWdlIGlzIGFscmVhZHkgb3V0OyBhIGR1cGxpY2F0ZSBwdWJsaXNoXG4gICAgICAgICAgICAgIC8vIGJ5IHRoYXQgaGFuZGxlciBkZWR1cGVzIG9uIHRoZSBzaGFyZWQgaWRlbXBvdGVuY3kga2V5LlxuICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ1N0ZXAgYWxyZWFkeSBleGlzdHMsIGNvbnRpbnVpbmcnLCB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChpc1JldHJ5YWJsZVdvcmxkRXJyb3IoZXJyKSkge1xuICAgICAgICAgICAgICAvLyBSZXNpbGllbnQ6IHRoZSB3cml0ZSBmYWlsZWQgdHJhbnNpZW50bHkgKDQyOSAvIDV4eCAvXG4gICAgICAgICAgICAgIC8vIHRyYW5zcG9ydCkgYnV0IHRoZSBzdGVwIG1lc3NhZ2UgKGNhcnJ5aW5nIHRoZSBzYW1lXG4gICAgICAgICAgICAgIC8vIHNlcmlhbGl6ZWQgaW5wdXQpIHdhcyBwdWJsaXNoZWQsIHNvIHRoZSBjb25zdW1lclxuICAgICAgICAgICAgICAvLyBpZGVtcG90ZW50bHkgcmUtZW5zdXJlcyB0aGUgc3RlcF9jcmVhdGVkIGJlZm9yZSBleGVjdXRpbmcuXG4gICAgICAgICAgICAgIHJlc2lsaWVudERpc3BhdGNoUmVjb3ZlcmVkKys7XG4gICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIud2FybihcbiAgICAgICAgICAgICAgICAnU3RlcCBjcmVhdGlvbiBldmVudCB3cml0ZSBmYWlsZWQsIGJ1dCB0aGUgc3RlcCB3YXMgJyArXG4gICAgICAgICAgICAgICAgICAnZGlzcGF0Y2hlZCB2aWEgdGhlIHF1ZXVlLiBUaGUgc3RlcF9jcmVhdGVkIGV2ZW50IHdpbGwgJyArXG4gICAgICAgICAgICAgICAgICAnYmUgZW5zdXJlZCBieSB0aGUgcXVldWUgY29uc3VtZXIuJyxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgICAgc3RlcE5hbWU6IHF1ZXVlSXRlbS5zdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgIGVycm9yOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVyciksXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjcmVhdGVkU3RlcENvcnJlbGF0aW9uSWRzLmFkZChxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChiYXRjaEZhbm91dEVsaWdpYmxlKSB7XG4gICAgICAgICAgLy8gRm9sZCBpbnRvIHRoZSBiYXRjaCBpbnN0ZWFkIG9mIHdyaXRpbmcgaGVyZS4gVGhlIGVuY2xvc2luZ1xuICAgICAgICAgIC8vIHByb21pc2Ugam9pbnMgYGJhdGNoUHJlcHNgIChzZWUgdGhlIGxvb3AgYmVsb3cpLCBzbyB0aGUgZmx1c2hcbiAgICAgICAgICAvLyBvcCBjYW5ub3QgcnVuIGJlZm9yZSB0aGlzIHN0ZXAncyBpbnB1dCBmaW5pc2hlZCBkZWh5ZHJhdGluZy5cbiAgICAgICAgICBiYXRjaFF1ZXVlLnB1c2goe1xuICAgICAgICAgICAgb3JkZXI6IHN0ZXBPcmRlcixcbiAgICAgICAgICAgIGtpbmQ6ICdzdGVwJyxcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgc3RlcE5hbWU6IHF1ZXVlSXRlbS5zdGVwTmFtZSxcbiAgICAgICAgICAgIGV2ZW50OiBzdGVwRXZlbnQsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCBlbnN1cmVSdW5SZWFkeSgpO1xuICAgICAgICAgIGF3YWl0IGNyZWF0ZUd1YXJkZWQoc3RlcEV2ZW50LCB7IHJlcXVlc3RJZCB9KTtcbiAgICAgICAgICBjcmVhdGVkU3RlcENvcnJlbGF0aW9uSWRzLmFkZChxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbygnU3RlcCBhbHJlYWR5IGV4aXN0cywgY29udGludWluZycsIHtcbiAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KSgpO1xuICAgICAgb3BzLnB1c2goc3RlcE9wKTtcbiAgICAgIGlmIChiYXRjaEZhbm91dEVsaWdpYmxlKSB7XG4gICAgICAgIC8vIFRoZSBmbHVzaCBvcCB3YWl0cyBmb3IgZXZlcnkgcHJlcCBiZWZvcmUgY29tbWl0dGluZzsgYSBwcmVwIHRoYXRcbiAgICAgICAgLy8gcmVqZWN0ZWQgYWxyZWFkeSBzdXJmYWNlcyB0aHJvdWdoIGBvcHNgLCBzbyB0aGUgZmx1c2gncyBvd24gd2FpdFxuICAgICAgICAvLyBzd2FsbG93cyBpdCBhbmQgY29tbWl0cyB3aGF0ZXZlciB3YXMgc3VjY2Vzc2Z1bGx5IGVucXVldWVkLFxuICAgICAgICAvLyBwcmVzZXJ2aW5nIHRvZGF5J3MgcGVyLW9wIGluZGVwZW5kZW5jZS5cbiAgICAgICAgYmF0Y2hQcmVwcy5wdXNoKHN0ZXBPcC5jYXRjaCgoKSA9PiB7fSkpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIENyZWF0ZSB3YWl0IGV2ZW50cyAoc2FtZSBhcyBWMSlcbiAgZm9yIChjb25zdCBxdWV1ZUl0ZW0gb2Ygd2FpdEl0ZW1zKSB7XG4gICAgaWYgKCFxdWV1ZUl0ZW0uaGFzQ3JlYXRlZEV2ZW50KSB7XG4gICAgICBjb25zdCB3YWl0RXZlbnQ6IENyZWF0ZUV2ZW50UmVxdWVzdCA9IHtcbiAgICAgICAgZXZlbnRUeXBlOiAnd2FpdF9jcmVhdGVkJyBhcyBjb25zdCxcbiAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgcmVzdW1lQXQ6IHF1ZXVlSXRlbS5yZXN1bWVBdCxcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgICBpZiAoYmF0Y2hGYW5vdXRFbGlnaWJsZSkge1xuICAgICAgICAvLyBXYWl0cyBuZWVkIG5vIGRlaHlkcmF0aW9uLCBzbyB0aGV5IGVucXVldWUgc3luY2hyb25vdXNseSwgYWZ0ZXJcbiAgICAgICAgLy8gZXZlcnkgc3RlcCdzIG9yZGVyIHNsb3QsIHByZXNlcnZpbmcgc3RlcHMtdGhlbi13YWl0cyBzY2hlZHVsaW5nXG4gICAgICAgIC8vIG9yZGVyIGluIHRoZSBsb2cuXG4gICAgICAgIGJhdGNoUXVldWUucHVzaCh7XG4gICAgICAgICAgb3JkZXI6IGJhdGNoT3JkZXJDb3VudGVyKyssXG4gICAgICAgICAga2luZDogJ3dhaXQnLFxuICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgIGV2ZW50OiB3YWl0RXZlbnQsXG4gICAgICAgIH0pO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIG9wcy5wdXNoKFxuICAgICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBlbnN1cmVSdW5SZWFkeSgpO1xuICAgICAgICAgICAgYXdhaXQgY3JlYXRlR3VhcmRlZCh3YWl0RXZlbnQsIHsgcmVxdWVzdElkIH0pO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ1dhaXQgYWxyZWFkeSBleGlzdHMsIGNvbnRpbnVpbmcnLCB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSkoKVxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvLyBUaGUgYmF0Y2hlZCBmb2xkJ3MgZmx1c2g6IHRoZSBjbGVhbiBmYW4tb3V0IGNvbW1pdHMgdGhyb3VnaFxuICAvLyBgY3JlYXRlQmF0Y2hgIGluIGNodW5rcyBvZiBNQVhfQkFUQ0hfRkFOT1VUX0VWRU5UUywgYWxsIGNodW5rcyBJTlxuICAvLyBGTElHSFQgQ09OQ1VSUkVOVExZLiBTbG90IGFzc2lnbm1lbnQgaXMgdGhlIHNlcnZlcidzLCBzbyBwYXJhbGxlbFxuICAvLyBjaHVua3MgcmFjZSBmb3Igc2xvdCByYW5nZXMgZXhhY3RseSBsaWtlIHRoZSBwcmUtZm9sZCBwYXRoJ3MgcGFyYWxsZWxcbiAgLy8gc2luZ2xlIHdyaXRlcyBkaWQ7IGVudGl0eSBjb25kaXRpb25zLCBub3QgY29tbWl0IG9yZGVyLCBjYXJyeVxuICAvLyBjb3JyZWN0bmVzcyAoc2libGluZyBmYW4tb3V0IGV2ZW50cyBoYXZlIG5vIGNyb3NzLW9yZGVyIHRoZSByZXBsYXlcbiAgLy8gZGVwZW5kcyBvbjsgaXQgbWF0Y2hlcyBieSBjb3JyZWxhdGlvbiBpZCkuIEVhY2ggZXZlbnQgcmVwb3J0cyB0aGVcbiAgLy8gb3V0Y29tZSBpdHMgb3duIHNpbmdsZSBjcmVhdGUgd291bGQgaGF2ZSBoYWQ6IGEgNDA5IGlzIHRoZSBzYW1lXG4gIC8vIGFscmVhZHktZXhpc3RzIHRvbGVyYW5jZSBhcyB0aGUgc2luZ2xlIHBhdGgsIGFueXRoaW5nIGVsc2UgZmFpbHMgdGhlXG4gIC8vIGRlbGl2ZXJ5IHRoZSB3YXkgYSBzaW5nbGUtcGF0aCByZWplY3Rpb24gd291bGQuXG4gIC8vXG4gIC8vIExhdGVuY3kgc2hhcGU6IG9ubHkgdGhlIGNodW5rIGNhcnJ5aW5nIHRoZSBwcmUtY2xhaW1lZCBpbmxpbmUgcGFpcnNcbiAgLy8gZ2F0ZXMgdGhlIGhhbmRsZXIncyByZXR1cm4gKHRoZSBjYWxsZXIgc3RhcnRzIGJvZGllcyBvZmYgaXRzIGNsYWltcykuXG4gIC8vIEV2ZXJ5IG90aGVyIGNodW5rJ3MgY29tbWl0IChhbmQgZXZlcnkgY2h1bmsncyBzdGVwLW1lc3NhZ2UgcHVibGlzaGVzLFxuICAvLyB3aGljaCBmaXJlIHRoZSBtb21lbnQgSVRTIGNyZWF0ZXMgYXJlIGR1cmFibGUpIHJpZGVzXG4gIC8vIGBkZWZlcnJlZEJhdGNoV29ya2Agd2hlbiB0aGUgY2FsbGVyIG9wdGVkIGluLCBqb2luZWQgYmVmb3JlIGFjay4gQSBzbG93XG4gIC8vIHNpYmxpbmcgY2h1bmsgdGhlcmVmb3JlIGRlbGF5cyBuZWl0aGVyIHRoZSBpbmxpbmUgYm9kaWVzIG5vciBhbm90aGVyXG4gIC8vIGNodW5rJ3MgcXVldWUgbWVzc2FnZXMsIHdoaWxlIHB1Ymxpc2gtYWZ0ZXItY3JlYXRlIHN0aWxsIGhvbGRzIHBlclxuICAvLyBzdGVwOiBhIHN0ZXAncyBtZXNzYWdlIGlzIG9ubHkgZXZlciBzZW50IGFmdGVyIHRoZSBjaHVuayBjYXJyeWluZyBpdHNcbiAgLy8gY3JlYXRlIGhhcyBjb21taXR0ZWQuXG4gIGxldCBkZWZlcnJlZEJhdGNoV29yazogUHJvbWlzZTx2b2lkPiB8IHVuZGVmaW5lZDtcbiAgaWYgKGJhdGNoRmFub3V0RWxpZ2libGUpIHtcbiAgICBvcHMucHVzaChcbiAgICAgIChhc3luYyAoKSA9PiB7XG4gICAgICAgIC8vIFByZXBzIHRoYXQgcmVqZWN0ZWQgYWxyZWFkeSBzdXJmYWNlIHRocm91Z2ggdGhlaXIgb3duIGBvcHNgXG4gICAgICAgIC8vIGVudHJpZXM7IHRoZSBmb2xkIGNvbW1pdHMgd2hhdGV2ZXIgd2FzIHN1Y2Nlc3NmdWxseSBlbnF1ZXVlZCxcbiAgICAgICAgLy8gcHJlc2VydmluZyB0b2RheSdzIHBlci1vcCBpbmRlcGVuZGVuY2UuXG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKGJhdGNoUHJlcHMpO1xuICAgICAgICBpZiAoYmF0Y2hRdWV1ZS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZW50cmllcyA9IFsuLi5iYXRjaFF1ZXVlXS5zb3J0KChhLCBiKSA9PiBhLm9yZGVyIC0gYi5vcmRlcik7XG4gICAgICAgIGF3YWl0IGVuc3VyZVJ1blJlYWR5KCk7XG4gICAgICAgIC8vIEEgYmF0Y2ggb2YgT05FIGdhaW5zIG5vdGhpbmcgb3ZlciB0aGUgc2luZ2xlIHdyaXRlIChzYW1lIHJvdW5kXG4gICAgICAgIC8vIHRyaXApIGFuZCBsb3NlcyB0aGUgc2xvdC1zbmFwc2hvdCBwYXJhbXMgKyBidW1wLWFuZC1yZXBvcnQgdGhhdFxuICAgICAgICAvLyBjcmVhdGVHdWFyZGVkIHByb3ZpZGVzLCBzbyBhIGxvbmUgZWFnZXIgZXZlbnQgdGFrZXMgdGhlIG9yZGluYXJ5XG4gICAgICAgIC8vIHNpbmdsZSBwYXRoLCB3aXRoIHRoZSBzYW1lIGNvbmZsaWN0IHRvbGVyYW5jZSBhbmQgb3duZXJzaGlwXG4gICAgICAgIC8vIGJvb2trZWVwaW5nIGl0IHdvdWxkIGhhdmUgaGFkIHdpdGhvdXQgdGhlIGZvbGQuXG4gICAgICAgIGlmIChlbnRyaWVzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgIGNvbnN0IFtlbnRyeV0gPSBlbnRyaWVzO1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBjcmVhdGVHdWFyZGVkKGVudHJ5LmV2ZW50LCB7IHJlcXVlc3RJZCB9KTtcbiAgICAgICAgICAgIGlmIChlbnRyeS5raW5kID09PSAnc3RlcCcpIHtcbiAgICAgICAgICAgICAgY3JlYXRlZFN0ZXBDb3JyZWxhdGlvbklkcy5hZGQoZW50cnkuY29ycmVsYXRpb25JZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgICBlbnRyeS5raW5kID09PSAnc3RlcCdcbiAgICAgICAgICAgICAgICAgID8gJ1N0ZXAgYWxyZWFkeSBleGlzdHMsIGNvbnRpbnVpbmcnXG4gICAgICAgICAgICAgICAgICA6ICdXYWl0IGFscmVhZHkgZXhpc3RzLCBjb250aW51aW5nJyxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IGVudHJ5LmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBTZWVkIGZvciB0aGUgZm9yZWlnbi1pbnRlcmxlYXZpbmcgZGlhZ25vc3RpYyBiZWxvdy4gV2l0aCBjaHVua3NcbiAgICAgICAgLy8gY29tbWl0dGluZyBpbiBwYXJhbGxlbCB0aGVyZSBpcyBubyBwZXItY2h1bmsgXCJleHBlY3RlZCBuZXh0IHNsb3RcIjtcbiAgICAgICAgLy8gdGhlIHdob2xlIGZvbGQncyBjb21taXR0ZWQgc3BhbiBpcyBjb21wYXJlZCBhZ2FpbnN0IHRoZSBzZWVkXG4gICAgICAgIC8vIG9uY2UgZXZlcnkgY2h1bmsgaGFzIHNldHRsZWQ6IGNvbW1pdHRlZCBzbG90cyBhcmUgZGVuc2UgcGVyIHRoZVxuICAgICAgICAvLyBXb3JsZCdzIGludmFyaWFudCwgc28gYW55IGV4Y2VzcyBvZiAobWF4IGNvbW1pdHRlZCBzbG90IOKIkiBzZWVkICtcbiAgICAgICAgLy8gMSkgb3ZlciB0aGUgZm9sZCdzIG93biBjb21taXR0ZWQgY291bnQgaXMgZXZlbnRzIE9USEVSIHdyaXRlcnNcbiAgICAgICAgLy8gbGFuZGVkIGluIGJldHdlZW4uXG4gICAgICAgIGNvbnN0IGV4cGVjdGVkRmlyc3RTbG90ID0gZXZlbnRMb2dcbiAgICAgICAgICA/IChtYXhFdmVudFNsb3QoZXZlbnRMb2cuZXZlbnRzKSA/PyAwKSArIDFcbiAgICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICAgICAgLy8gUGFpci1hd2FyZSBjaHVua2luZzogYSBwcmUtY2xhaW1lZCBwYWlyJ3MgdHdvIHJvd3MgbXVzdCBsYW5kIGluXG4gICAgICAgIC8vIHRoZSBzYW1lIGNyZWF0ZUJhdGNoIGNhbGwgKGFkamFjZW50LCBzbyBhIFdvcmxkIGNhbiBmb2xkIHRoZW1cbiAgICAgICAgLy8gaW50byBvbmUgYm9ybi1ydW5uaW5nIGNyZWF0ZSkgYW5kIG5ldmVyIHN0cmFkZGxlIGEgY2h1bmtcbiAgICAgICAgLy8gYm91bmRhcnksIHdoaWNoIHdvdWxkIHR1cm4gdGhlIHN0YXJ0ZWQgcm93IGludG8gYSBzdGFuZGFsb25lXG4gICAgICAgIC8vIGNsYWltIHJhY2luZyBpdHMgb3duIGNyZWF0ZSdzIGNvbW1pdC5cbiAgICAgICAgY29uc3QgY2h1bmtzOiAodHlwZW9mIGVudHJpZXMpW10gPSBbXTtcbiAgICAgICAge1xuICAgICAgICAgIGxldCBjdXJyZW50OiB0eXBlb2YgZW50cmllcyA9IFtdO1xuICAgICAgICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBlbnRyaWVzLmxlbmd0aDsgaW5kZXgrKykge1xuICAgICAgICAgICAgY29uc3QgZW50cnkgPSBlbnRyaWVzW2luZGV4XTtcbiAgICAgICAgICAgIGNvbnN0IG5leHQgPSBlbnRyaWVzW2luZGV4ICsgMV07XG4gICAgICAgICAgICBjb25zdCBwYWlyTGVhZCA9XG4gICAgICAgICAgICAgIGVudHJ5LmtpbmQgPT09ICdpbmxpbmUtY3JlYXRlZCcgJiZcbiAgICAgICAgICAgICAgbmV4dD8ua2luZCA9PT0gJ2lubGluZS1zdGFydGVkJyAmJlxuICAgICAgICAgICAgICBuZXh0LmNvcnJlbGF0aW9uSWQgPT09IGVudHJ5LmNvcnJlbGF0aW9uSWQ7XG4gICAgICAgICAgICBjb25zdCB0YWtlID0gcGFpckxlYWQgPyAyIDogMTtcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgY3VycmVudC5sZW5ndGggPiAwICYmXG4gICAgICAgICAgICAgIGN1cnJlbnQubGVuZ3RoICsgdGFrZSA+IE1BWF9CQVRDSF9GQU5PVVRfRVZFTlRTXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgY2h1bmtzLnB1c2goY3VycmVudCk7XG4gICAgICAgICAgICAgIGN1cnJlbnQgPSBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnQucHVzaChlbnRyeSk7XG4gICAgICAgICAgICBpZiAocGFpckxlYWQpIHtcbiAgICAgICAgICAgICAgY3VycmVudC5wdXNoKG5leHQpO1xuICAgICAgICAgICAgICBpbmRleCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoY3VycmVudC5sZW5ndGggPiAwKSBjaHVua3MucHVzaChjdXJyZW50KTtcbiAgICAgICAgfVxuICAgICAgICAvLyBTdGVwcyB3aG9zZSBxdWV1ZSBtZXNzYWdlcyBUSElTIEZMVVNIIHdpbGwgcHVibGlzaCAodGhlIGVhZ2VyXG4gICAgICAgIC8vIGNyZWF0ZXMpLCByZWNvcmRlZCBiZWZvcmUgYW55IGNodW5rIHNldHRsZXMgc28gdGhlIGNhbGxlcidzXG4gICAgICAgIC8vIGRpc3BhdGNoIHBhc3MgKHdoaWNoIHJ1bnMgb2ZmIHRoZSBoYW5kbGVyJ3MgcmV0dXJuKSBza2lwcyB0aGVtLlxuICAgICAgICAvLyBUaGUgc2VuZHMgYXJlIGd1YXJhbnRlZWQtb3ItZmFpbGVkIGJ5IHRoZSB0cmFpbGluZyB3b3JrIHRoZVxuICAgICAgICAvLyBjYWxsZXIgam9pbnMgYmVmb3JlIGFja2luZywgc28gXCJ3aWxsIGJlIHB1Ymxpc2hlZCBieSB0aGlzIGZsdXNoXCJcbiAgICAgICAgLy8gYW5kIFwiYWxyZWFkeSBwdWJsaXNoZWRcIiBhcmUgZXF1aXZhbGVudCBmcm9tIHRoZSBjYWxsZXIncyBzaWRlLlxuICAgICAgICBjb25zdCBwdWJsaXNoRWFnZXJTdGVwcyA9IHN0ZXBEaXNwYXRjaCAhPT0gdW5kZWZpbmVkO1xuICAgICAgICBpZiAocHVibGlzaEVhZ2VyU3RlcHMpIHtcbiAgICAgICAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGVudHJpZXMpIHtcbiAgICAgICAgICAgIGlmIChlbnRyeS5raW5kID09PSAnc3RlcCcpIHtcbiAgICAgICAgICAgICAgcXVldWVkU3RlcENvcnJlbGF0aW9uSWRzLmFkZChlbnRyeS5jb3JyZWxhdGlvbklkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUYWxsaWVzIGZvciB0aGUgZm9yZWlnbi1pbnRlcmxlYXZpbmcgZGlhZ25vc3RpYywgZm9sZGVkIGFjcm9zc1xuICAgICAgICAvLyB0aGUgY29uY3VycmVudCBjaHVua3MgYW5kIHJlYWQgb25jZSBhbGwgb2YgdGhlbSBzZXR0bGVkLlxuICAgICAgICBsZXQgY29tbWl0dGVkQ291bnQgPSAwO1xuICAgICAgICBsZXQgbWF4Q29tbWl0dGVkU2xvdDogbnVtYmVyIHwgdW5kZWZpbmVkO1xuXG4gICAgICAgIGNvbnN0IGNvbW1pdENodW5rID0gYXN5bmMgKGNodW5rOiB0eXBlb2YgZW50cmllcyk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICAgIC8vIEFuY2hvcnMgZm9yIHRoZSBwcmUtY2xhaW1lZCBzdGVwcycgdGVsZW1ldHJ5OiB0aGUgUE9TVCBpbnN0YW50XG4gICAgICAgICAgLy8gaXMgdGhlIGNsYWltJ3MgXCJzdGFydCBQT1NUIHNlbnRcIiAoUlNGUydzIGVuZCksIHRoZSByZXR1cm4gaXMgdGhlXG4gICAgICAgICAgLy8gY2xhaW0ncyBjb21wbGV0aW9uIChUVFIncyBUNiksIHRoZSBzYW1lIHR3byBpbnN0YW50cyB0aGUgbGF6eVxuICAgICAgICAgIC8vIGNsYWltJ3Mgb3duIFBPU1Qgd291bGQgaGF2ZSBwcm9kdWNlZC5cbiAgICAgICAgICBjb25zdCBiYXRjaFBvc3RTZW50QXRNcyA9IERhdGUubm93KCk7XG4gICAgICAgICAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3R5bGUvbm9Ob25OdWxsQXNzZXJ0aW9uOiBiYXRjaEZhbm91dEVsaWdpYmxlIGltcGxpZXMgcHJlc2VuY2VcbiAgICAgICAgICBjb25zdCB7IHJlc3VsdHMgfSA9IGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGVCYXRjaCEoXG4gICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgIGNodW5rLm1hcCgoZW50cnkpID0+ICh7XG4gICAgICAgICAgICAgIGV2ZW50OiBlbnRyeS5ldmVudCxcbiAgICAgICAgICAgICAgLy8gVGhlIHN0YXJ0ZWQgcm93IGlzIHRoZSBzdGVwJ3MgZXhlY3V0aW5nIGNsYWltLCBzbyBpdCBjYXJyaWVzXG4gICAgICAgICAgICAgIC8vIHRoZSBjb21wdXRlLWluc3RhbmNlIGF0dHJpYnV0aW9uIHRoZSBzaW5nbGUgY2xhaW0gc2VuZHMgdmlhXG4gICAgICAgICAgICAgIC8vIENyZWF0ZUV2ZW50UGFyYW1zLlxuICAgICAgICAgICAgICAuLi4oZW50cnkua2luZCA9PT0gJ2lubGluZS1zdGFydGVkJ1xuICAgICAgICAgICAgICAgID8geyBjb21wdXRlSW5zdGFuY2VJZDogQ09NUFVURV9JTlNUQU5DRV9JRCB9XG4gICAgICAgICAgICAgICAgOiB7fSksXG4gICAgICAgICAgICB9KSksXG4gICAgICAgICAgICAvLyBQZXItd3JpdGUgcmVxdWVzdCBhdHRyaWJ1dGlvbiwgc2FtZSBhcyB0aGUgc2luZ2xlIHBhdGgnc1xuICAgICAgICAgICAgLy8gY3JlYXRlR3VhcmRlZCjigKYsIHsgcmVxdWVzdElkIH0pLlxuICAgICAgICAgICAgeyByZXF1ZXN0SWQgfVxuICAgICAgICAgICk7XG4gICAgICAgICAgY29uc3QgY2xhaW1Db21wbGV0ZWRBdE1zID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICBmb3IgKGNvbnN0IFtpbmRleCwgaXRlbV0gb2YgcmVzdWx0cy5lbnRyaWVzKCkpIHtcbiAgICAgICAgICAgIGNvbnN0IGVudHJ5ID0gY2h1bmtbaW5kZXhdO1xuICAgICAgICAgICAgaWYgKGl0ZW0uZXJyb3IgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICBpZiAoZW50cnkua2luZCA9PT0gJ3N0ZXAnKSB7XG4gICAgICAgICAgICAgICAgY3JlYXRlZFN0ZXBDb3JyZWxhdGlvbklkcy5hZGQoZW50cnkuY29ycmVsYXRpb25JZCk7XG4gICAgICAgICAgICAgIH0gZWxzZSBpZiAoZW50cnkua2luZCA9PT0gJ2lubGluZS1zdGFydGVkJykge1xuICAgICAgICAgICAgICAgIC8vIFRoZSBwYWlyIGNvbW1pdHRlZDogdGhpcyBpbnZvY2F0aW9uIG93bnMgdGhlIHN0ZXAgYW5kIHRoZVxuICAgICAgICAgICAgICAgIC8vIGNhbGxlciBydW5zIHRoZSBib2R5IHdpdGggbm8gY2xhaW0gb2YgaXRzIG93bi4gVGhlXG4gICAgICAgICAgICAgICAgLy8gcmVhZGJhY2sgZW50aXR5IGlzIGF1dGhvcml0YXRpdmUgd2hlcmUgcHJlc2VudDsgYSBXb3JsZFxuICAgICAgICAgICAgICAgIC8vIHRoYXQgb21pdHRlZCBpdCBnZXRzIHRoZSBzYW1lIGxvY2FsbHkgc3ludGhlc2l6ZWQgcnVubmluZ1xuICAgICAgICAgICAgICAgIC8vIGF0dGVtcHQtMSB0aGUgb3B0aW1pc3RpYyBwYXRoIGV4ZWN1dGVzIGFnYWluc3QuIEVpdGhlclxuICAgICAgICAgICAgICAgIC8vIHdheSB0aGUgaW5wdXQgaXMgcmUtYXR0YWNoZWQgbG9jYWxseTogYmF0Y2ggcmVzcG9uc2VzXG4gICAgICAgICAgICAgICAgLy8gcmV0dXJuIHJlZnMgbGF6aWx5LCBhbmQgdGhlIGJvZHkncyBoeWRyYXRpb24gd2FudHMgdGhlXG4gICAgICAgICAgICAgICAgLy8gZXhhY3QgYnl0ZXMgdGhlIHBhaXIncyBjcmVhdGVkIHJvdyBjYXJyaWVkLiAoVGhlIGNyZWF0ZWRcbiAgICAgICAgICAgICAgICAvLyByb3cncyBzdWNjZXNzIGlzIGRlbGliZXJhdGVseSBOT1QgbWVtYmVyc2hpcCBpblxuICAgICAgICAgICAgICAgIC8vIGNyZWF0ZWRTdGVwQ29ycmVsYXRpb25JZHM6IGZvciBpbmxpbmUgc3RlcHMgb3duZXJzaGlwIGlzXG4gICAgICAgICAgICAgICAgLy8gdGhlIHN0YXJ0ZWQgcm93J3MgdmVyZGljdCwgYW5kIHRoZSBjYWxsZXIncyBkaXNwYXRjaCBwYXNzXG4gICAgICAgICAgICAgICAgLy8gc2tpcHMgaW5saW5lIGNvcnJlbGF0aW9uIGlkcyByZWdhcmRsZXNzLilcbiAgICAgICAgICAgICAgICBjb25zdCBkZWh5ZHJhdGVkID0gbGF6eUlubGluZUJ5Q29ycmVsYXRpb25JZC5nZXQoXG4gICAgICAgICAgICAgICAgICBlbnRyeS5jb3JyZWxhdGlvbklkXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBpZiAoZGVoeWRyYXRlZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAvLyBVbnJlYWNoYWJsZTogdGhlIHNhbWUgcHJlcCBvcCB0aGF0IGVucXVldWVkIHRoZSBwYWlyIHNldFxuICAgICAgICAgICAgICAgICAgLy8gdGhpcyBlbnRyeSwgYW5kIHRoZSBmbHVzaCBhd2FpdGVkIGV2ZXJ5IHByZXAgYWJvdmUuXG4gICAgICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAgICAgLy8gTm90IGZyZWUgaWYgaXQgZXZlciBmaXJlcywgdGhvdWdoOiB0aGUgcGFpciBpcyBhbHJlYWR5XG4gICAgICAgICAgICAgICAgICAvLyBkdXJhYmxlIGhlcmUsIHNvIHRoaXMgdGhyb3dzIHdpdGggdGhlIHN0ZXAgY2xhaW1lZCBhbmRcbiAgICAgICAgICAgICAgICAgIC8vIGl0cyBib2R5IG5ldmVyIHJ1bi4gVGhlIGRlbGl2ZXJ5IGZhaWxzLCBhbmQgcmVkZWxpdmVyeVxuICAgICAgICAgICAgICAgICAgLy8gcmVjb3ZlcnMgaXQgdGhyb3VnaCBvd25lZC1yZWNvdmVyeSAodGhlIHN0ZXAgY2FycmllcyB0aGlzXG4gICAgICAgICAgICAgICAgICAvLyBtZXNzYWdlJ3Mgb3duZXJzaGlwIHN0YW1wKSByYXRoZXIgdGhhbiB0aGUgcmVxdWVzdCBqdXN0XG4gICAgICAgICAgICAgICAgICAvLyBmYWlsaW5nIGNsZWFubHkuXG4gICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgV29ya2Zsb3dXb3JsZEVycm9yKFxuICAgICAgICAgICAgICAgICAgICBgbm8gZGVoeWRyYXRlZCBpbnB1dCBmb3IgcHJlLWNsYWltZWQgc3RlcCAke2VudHJ5LmNvcnJlbGF0aW9uSWR9YCxcbiAgICAgICAgICAgICAgICAgICAgeyBzdGF0dXM6IDUwMCB9XG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCBub3cgPSBuZXcgRGF0ZSgpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0YXJ0ZWRTdGVwOiBTdGFydGVkU3RlcCA9IGl0ZW0uc3RlcD8uc3RhcnRlZEF0XG4gICAgICAgICAgICAgICAgICA/IHsgLi4uaXRlbS5zdGVwLCBzdGFydGVkQXQ6IGl0ZW0uc3RlcC5zdGFydGVkQXQgfVxuICAgICAgICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgc3RlcElkOiBlbnRyeS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgICAgICAgIHN0ZXBOYW1lOiBkZWh5ZHJhdGVkLnN0ZXBOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgIHN0YXR1czogJ3J1bm5pbmcnLFxuICAgICAgICAgICAgICAgICAgICAgIGF0dGVtcHQ6IDEsXG4gICAgICAgICAgICAgICAgICAgICAgY3JlYXRlZEF0OiBub3csXG4gICAgICAgICAgICAgICAgICAgICAgdXBkYXRlZEF0OiBub3csXG4gICAgICAgICAgICAgICAgICAgICAgc3RhcnRlZEF0OiBub3csXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgaW5saW5lQ2xhaW1zLnNldChlbnRyeS5jb3JyZWxhdGlvbklkLCB7XG4gICAgICAgICAgICAgICAgICBvd25lZDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgIHN0ZXA6IHtcbiAgICAgICAgICAgICAgICAgICAgLi4uc3RhcnRlZFN0ZXAsXG4gICAgICAgICAgICAgICAgICAgIGlucHV0OiBkZWh5ZHJhdGVkLmRlaHlkcmF0ZWRJbnB1dCxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICBiYXRjaFBvc3RTZW50QXRNcyxcbiAgICAgICAgICAgICAgICAgIGNsYWltQ29tcGxldGVkQXRNcyxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpdGVtLnN0YXR1cyA9PT0gNDA5KSB7XG4gICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICBlbnRyeS5raW5kID09PSAnaW5saW5lLWNyZWF0ZWQnIHx8XG4gICAgICAgICAgICAgICAgZW50cnkua2luZCA9PT0gJ2lubGluZS1zdGFydGVkJ1xuICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAvLyBUaGUgcGFpciBsb3N0IGl0cyBhdG9taWMgY3JlYXRlLWNsYWltOiBhIGNvbmN1cnJlbnQgd3JpdGVyXG4gICAgICAgICAgICAgICAgLy8gYWxyZWFkeSBvd25zIHRoaXMgc3RlcCAoYW4gZWFybGllciBkZWxpdmVyeSdzIGNyZWF0ZSwgb3IgYVxuICAgICAgICAgICAgICAgIC8vIHJhY2luZyBoYW5kbGVyJ3MgY2xhaW0pLiBSZWNvcmRlZCBhcyBhIGxvc3QgY2xhaW06IHRoZVxuICAgICAgICAgICAgICAgIC8vIGNhbGxlcidzIGV4ZWN1dGVTdGVwIHJldHVybnMgYHNraXBwZWRgIHdpdGhvdXQgcnVubmluZyB0aGVcbiAgICAgICAgICAgICAgICAvLyBib2R5LCB0aGUgc2FtZSBvdXRjb21lIGFzIGxvc2luZyB0aGUgbGF6eSBjbGFpbS4gQSBXb3JsZFxuICAgICAgICAgICAgICAgIC8vIHRoYXQgZm9sZHMgdGhlIHBhaXIgcmVwb3J0cyB0aGUgNDA5IG9uIGJvdGggcm93cyAoc2V0XG4gICAgICAgICAgICAgICAgLy8gdHdpY2UsIGhhcm1sZXNzKTsgb25lIHRoYXQgZXZhbHVhdGVzIHJvd3MgaW5kZXBlbmRlbnRseVxuICAgICAgICAgICAgICAgIC8vIGhhcyB0aGUgc3RhcnRlZCByb3cgKHByb2Nlc3NlZCBzZWNvbmQpIGRlY2lkZSwgd2hpY2ggaXNcbiAgICAgICAgICAgICAgICAvLyBleGFjdGx5IHRoZSBzaW5nbGUgcGF0aCdzIHNlbWFudGljcyAoY3JlYXRlIGxvc3QgKyBjbGFpbVxuICAgICAgICAgICAgICAgIC8vIHdvbiBzdGlsbCBydW5zIHRoZSBib2R5OyBjcmVhdGUgd29uICsgY2xhaW0gbG9zdCBza2lwcykuXG4gICAgICAgICAgICAgICAgaW5saW5lQ2xhaW1zLnNldChlbnRyeS5jb3JyZWxhdGlvbklkLCB7IG93bmVkOiBmYWxzZSB9KTtcbiAgICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ0lubGluZSBzdGVwIHByZS1jbGFpbSBsb3N0LCBjb250aW51aW5nJywge1xuICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBlbnRyeS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgICAgbWVzc2FnZTogaXRlbS5tZXNzYWdlLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIC8vIFNhbWUgdG9sZXJhbmNlIGFzIHRoZSBzaW5nbGUgcGF0aCdzIEVudGl0eUNvbmZsaWN0RXJyb3I6IGFcbiAgICAgICAgICAgICAgLy8gY29uY3VycmVudCBvciBlYXJsaWVyIGRlbGl2ZXJ5IGFscmVhZHkgY3JlYXRlZCBpdC5cbiAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAgIGVudHJ5LmtpbmQgPT09ICdzdGVwJ1xuICAgICAgICAgICAgICAgICAgPyAnU3RlcCBhbHJlYWR5IGV4aXN0cywgY29udGludWluZydcbiAgICAgICAgICAgICAgICAgIDogJ1dhaXQgYWxyZWFkeSBleGlzdHMsIGNvbnRpbnVpbmcnLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogZW50cnkuY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGl0ZW0ubWVzc2FnZSxcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IFdvcmtmbG93V29ybGRFcnJvcihcbiAgICAgICAgICAgICAgYGJhdGNoZWQgJHtlbnRyeS5ldmVudC5ldmVudFR5cGV9IGZvciAke2VudHJ5LmNvcnJlbGF0aW9uSWR9IGAgK1xuICAgICAgICAgICAgICAgIGBmYWlsZWQ6ICR7aXRlbS5lcnJvcn06ICR7aXRlbS5tZXNzYWdlfWAsXG4gICAgICAgICAgICAgIHsgc3RhdHVzOiBpdGVtLnN0YXR1cyB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBIaWdoZXN0IHNsb3QgdGhpcyBjaHVuayBjb21taXR0ZWQ6IHRoZSBjZWlsaW5nIHRoZSBjYWxsZXIgZm9sZHNcbiAgICAgICAgICAvLyBpbnRvIHRoZSBpbmxpbmUgZXhlY3V0aW9ucycgc2xvdCBzbmFwc2hvdCAoc2VlXG4gICAgICAgICAgLy8gU3VzcGVuc2lvbkhhbmRsZXJSZXN1bHQuYmF0Y2hDb21taXR0ZWRTbG90Q2VpbGluZykgYW5kIG9uZSBpbnB1dFxuICAgICAgICAgIC8vIG9mIHRoZSBpbnRlcmxlYXZpbmcgZGlhZ25vc3RpYy5cbiAgICAgICAgICBjb25zdCBjaHVua01heFNsb3QgPSBtYXhFdmVudFNsb3QoXG4gICAgICAgICAgICByZXN1bHRzLmZsYXRNYXAoKGl0ZW0pID0+XG4gICAgICAgICAgICAgIGl0ZW0uZXJyb3IgPT09IHVuZGVmaW5lZCAmJiBpdGVtLmV2ZW50ID8gW2l0ZW0uZXZlbnRdIDogW11cbiAgICAgICAgICAgIClcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIGNodW5rTWF4U2xvdCAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgICAgICAoYmF0Y2hDb21taXR0ZWRTbG90Q2VpbGluZyA9PT0gdW5kZWZpbmVkIHx8XG4gICAgICAgICAgICAgIGNodW5rTWF4U2xvdCA+IGJhdGNoQ29tbWl0dGVkU2xvdENlaWxpbmcpXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBiYXRjaENvbW1pdHRlZFNsb3RDZWlsaW5nID0gY2h1bmtNYXhTbG90O1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb21taXR0ZWRDb3VudCArPSByZXN1bHRzLmZpbHRlcihcbiAgICAgICAgICAgIChpdGVtKSA9PiBpdGVtLmVycm9yID09PSB1bmRlZmluZWRcbiAgICAgICAgICApLmxlbmd0aDtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBjaHVua01heFNsb3QgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAgICAgKG1heENvbW1pdHRlZFNsb3QgPT09IHVuZGVmaW5lZCB8fCBjaHVua01heFNsb3QgPiBtYXhDb21taXR0ZWRTbG90KVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgbWF4Q29tbWl0dGVkU2xvdCA9IGNodW5rTWF4U2xvdDtcbiAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gUHVibGlzaCB0aGUgY2h1bmsncyBlYWdlciBzdGVwcycgcXVldWUgbWVzc2FnZXMgdGhlIG1vbWVudCBJVFNcbiAgICAgICAgLy8gY3JlYXRlcyBhcmUgZHVyYWJsZSwgdGhlIHBlci1jaHVuayBoYWxmIG9mIHB1Ymxpc2gtYWZ0ZXItY3JlYXRlLlxuICAgICAgICAvLyBTYW1lIG1lc3NhZ2Ugc2hhcGUgYW5kIHN0ZXAtaWRlbnRpdHktc2NvcGVkIGlkZW1wb3RlbmN5IGtleSBhcyB0aGVcbiAgICAgICAgLy8gY2FsbGVyJ3MgZGlzcGF0Y2ggcGFzcywgc28gYW55dGhpbmcgZG91YmxlLXB1Ymxpc2hlZCBkZWR1cGVzLlxuICAgICAgICBjb25zdCBwdWJsaXNoQ2h1bmtTdGVwcyA9IGFzeW5jIChcbiAgICAgICAgICBjaHVuazogdHlwZW9mIGVudHJpZXNcbiAgICAgICAgKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgICAgaWYgKCFwdWJsaXNoRWFnZXJTdGVwcykgcmV0dXJuO1xuICAgICAgICAgIGNvbnN0IHN0ZXBFbnRyaWVzID0gY2h1bmsuZmlsdGVyKChlbnRyeSkgPT4gZW50cnkua2luZCA9PT0gJ3N0ZXAnKTtcbiAgICAgICAgICBpZiAoc3RlcEVudHJpZXMubGVuZ3RoID09PSAwKSByZXR1cm47XG4gICAgICAgICAgY29uc3QgdHJhY2VDYXJyaWVyID0gYXdhaXQgZ2V0U3RlcERpc3BhdGNoVHJhY2VDYXJyaWVyKCk7XG4gICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgICAgICBzdGVwRW50cmllcy5tYXAoKGVudHJ5KSA9PlxuICAgICAgICAgICAgICBxdWV1ZU1lc3NhZ2UoXG4gICAgICAgICAgICAgICAgd29ybGQsXG4gICAgICAgICAgICAgICAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3R5bGUvbm9Ob25OdWxsQXNzZXJ0aW9uOiBwdWJsaXNoRWFnZXJTdGVwcyBpbXBsaWVzIHByZXNlbmNlXG4gICAgICAgICAgICAgICAgc3RlcERpc3BhdGNoIS5xdWV1ZU5hbWUsXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICAgICAgICBzdGVwSWQ6IGVudHJ5LmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgICAvLyBiaW9tZS1pZ25vcmUgbGludC9zdHlsZS9ub05vbk51bGxBc3NlcnRpb246IHNldCBvbiBldmVyeSAnc3RlcCcgZW50cnkgYXQgZW5xdWV1ZVxuICAgICAgICAgICAgICAgICAgc3RlcE5hbWU6IGVudHJ5LnN0ZXBOYW1lISxcbiAgICAgICAgICAgICAgICAgIHRyYWNlQ2FycmllcixcbiAgICAgICAgICAgICAgICAgIHJlcXVlc3RlZEF0OiBuZXcgRGF0ZSgpLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgaWRlbXBvdGVuY3lLZXk6IHN0ZXBEaXNwYXRjaElkZW1wb3RlbmN5S2V5KFxuICAgICAgICAgICAgICAgICAgICBlbnRyeS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgICAgICAvLyBiaW9tZS1pZ25vcmUgbGludC9zdHlsZS9ub05vbk51bGxBc3NlcnRpb246IHNldCBvbiBldmVyeSAnc3RlcCcgZW50cnkgYXQgZW5xdWV1ZVxuICAgICAgICAgICAgICAgICAgICBlbnRyeS5zdGVwTmFtZSFcbiAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICApXG4gICAgICAgICAgKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBMYXVuY2ggZXZlcnkgY2h1bmsncyBQT1NUIG5vdzsgY2hhaW4gZWFjaCBjaHVuaydzIHB1Ymxpc2hlcyBvbiBpdHNcbiAgICAgICAgLy8gT1dOIGNvbW1pdC4gQSBjaHVuayB3aG9zZSBjb21taXQgcmVqZWN0ZWQga2VlcHMgaXRzIG1lc3NhZ2VzXG4gICAgICAgIC8vIHVuc2VudCAodGhlIHJlamVjdGlvbiBmYWlscyB0aGUgZGVsaXZlcnk7IHJlZGVsaXZlcnkgcmUtY3JlYXRlc1xuICAgICAgICAvLyBhbmQgcmUtZGlzcGF0Y2hlcywgZGVkdXBlZCBieSB0aGUgaWRlbXBvdGVuY3kga2V5cykuXG4gICAgICAgIGNvbnN0IGNvbW1pdHMgPSBjaHVua3MubWFwKChjaHVuaykgPT4gY29tbWl0Q2h1bmsoY2h1bmspKTtcbiAgICAgICAgY29uc3QgcHVibGlzaGVzID0gY2h1bmtzLm1hcChhc3luYyAoY2h1bmssIGluZGV4KSA9PiB7XG4gICAgICAgICAgYXdhaXQgY29tbWl0c1tpbmRleF07XG4gICAgICAgICAgYXdhaXQgcHVibGlzaENodW5rU3RlcHMoY2h1bmspO1xuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCB0cmFpbGluZyA9IChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgLy8gTGV0IGV2ZXJ5IHNpYmxpbmcgc2V0dGxlIGJlZm9yZSBzdXJmYWNpbmcgdGhlIGZpcnN0IGZhaWx1cmU6IGFcbiAgICAgICAgICAvLyBjaHVuayB0aGF0IGNvbW1pdHRlZCBtdXN0IHN0aWxsIGdldCBpdHMgcHVibGlzaGVzIG91dCBldmVuIHdoZW5cbiAgICAgICAgICAvLyBhbm90aGVyIGNodW5rIGZhaWxlZCwgYW5kIHRoZSBjYWxsZXIgYWNrcyBvbmx5IGFmdGVyIHRoaXNcbiAgICAgICAgICAvLyByZXNvbHZlcy5cbiAgICAgICAgICBjb25zdCBzZXR0bGVkID0gYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKFsuLi5jb21taXRzLCAuLi5wdWJsaXNoZXNdKTtcbiAgICAgICAgICAvLyBGb3JlaWduLWludGVybGVhdmluZyB2aXNpYmlsaXR5OiB0aGUgYmF0Y2ggZW5kcG9pbnQgaGFzIG5vXG4gICAgICAgICAgLy8gYnVtcC1hbmQtcmVwb3J0LCBzbyBldmVudHMgb3RoZXIgd3JpdGVycyBsYW5kZWQgYmV0d2VlbiB0aGVcbiAgICAgICAgICAvLyBzbmFwc2hvdCBhbmQgdGhlc2UgY29tbWl0cyBwdXNoZWQgdGhlIGZvbGQgdG8gaGlnaGVyIHNsb3RzXG4gICAgICAgICAgLy8gV0lUSE9VVCBoYW5kaW5nIHVzIHRoZSBza2lwcGVkIGV2ZW50cy4gU2FtZSBhY2NlcHRlZCBleHBvc3VyZVxuICAgICAgICAgIC8vIGFzIGEgZHJvcHBlZCB0cnVuY2F0ZWQgcmVwb3J0IG9uIHRoZSBzaW5nbGUgcGF0aDogdGhlIGxvY2FsXG4gICAgICAgICAgLy8gbG9nIHN0YXlzIGEgc3RyaWN0IHByZWZpeCBhbmQgdGhlIG5leHQgcmVsb2FkIG9ic2VydmVzIHRoZW0uXG4gICAgICAgICAgLy8gTG9nZ2VkIHNvIGEgYnVtcCBpcyBkaWFnbm9zYWJsZSByYXRoZXIgdGhhbiBzaWxlbnQuXG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgZXhwZWN0ZWRGaXJzdFNsb3QgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAgICAgbWF4Q29tbWl0dGVkU2xvdCAhPT0gdW5kZWZpbmVkXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBjb25zdCBpbnRlcmxlYXZlZCA9XG4gICAgICAgICAgICAgIG1heENvbW1pdHRlZFNsb3QgLSBleHBlY3RlZEZpcnN0U2xvdCArIDEgLSBjb21taXR0ZWRDb3VudDtcbiAgICAgICAgICAgIGlmIChpbnRlcmxlYXZlZCA+IDApIHtcbiAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5kZWJ1ZygnQmF0Y2hlZCBmYW4tb3V0IGNvbW1pdHRlZCBhYm92ZSBzbmFwc2hvdCcsIHtcbiAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICBleHBlY3RlZEZpcnN0U2xvdCxcbiAgICAgICAgICAgICAgICBtYXhDb21taXR0ZWRTbG90LFxuICAgICAgICAgICAgICAgIGNvbW1pdHRlZENvdW50LFxuICAgICAgICAgICAgICAgIGludGVybGVhdmVkLFxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3QgZmFpbHVyZSA9IHNldHRsZWQuZmluZChcbiAgICAgICAgICAgIChvdXRjb21lKTogb3V0Y29tZSBpcyBQcm9taXNlUmVqZWN0ZWRSZXN1bHQgPT5cbiAgICAgICAgICAgICAgb3V0Y29tZS5zdGF0dXMgPT09ICdyZWplY3RlZCdcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmIChmYWlsdXJlKSB0aHJvdyBmYWlsdXJlLnJlYXNvbjtcbiAgICAgICAgfSkoKTtcblxuICAgICAgICAvLyBFVkVSWSBjaHVuayBjYXJyeWluZyBwYWlycyBnYXRlcyB0aGUgcmV0dXJuLCBub3QganVzdCB0aGUgZmlyc3Q6XG4gICAgICAgIC8vIGEgcGFpciB3aG9zZSBjb21taXQgdGhlIGNhbGxlciBoYXMgbm90IHNlZW4geWllbGRzIG5vXG4gICAgICAgIC8vIGBpbmxpbmVDbGFpbXNgIGVudHJ5LCBzbyB0aGUgY2FsbGVyIGZhbGxzIGJhY2sgdG8gYSBsYXp5XG4gICAgICAgIC8vIGBzdGVwX3N0YXJ0ZWRgIHRoYXQgd291bGQgcmFjZSB0aGlzIHNhbWUgZm9sZCdzIHN0aWxsLWluLWZsaWdodFxuICAgICAgICAvLyBwYWlyIGZvciB0aGUgc2FtZSBzdGVwLiBUb2RheSBwYWlycyBhbHdheXMgbGFuZCBpbiBvbmUgY2h1bmtcbiAgICAgICAgLy8gKHRoZXkgc29ydCBmaXJzdCwgYW5kIHR3byByb3dzIHBlciBpbmxpbmUgc3RlcCBmaXQgaW5zaWRlIG9uZVxuICAgICAgICAvLyBjaHVuaywgcGlubmVkIGJ5IGNvbnN0YW50cy50ZXN0LnRzKSwgc28gdGhpcyBpcyBhdCBtb3N0IG9uZVxuICAgICAgICAvLyBjb21taXQ7IHRoZSBmaWx0ZXIgaXMgd2hhdCBrZWVwcyB0aGUgcHJvcGVydHkgdHJ1ZSBpZiBlaXRoZXIgY2FwXG4gICAgICAgIC8vIG1vdmVzLlxuICAgICAgICBjb25zdCBwYWlyQ29tbWl0cyA9IGNodW5rcy5mbGF0TWFwKChjaHVuaywgaW5kZXgpID0+XG4gICAgICAgICAgY2h1bmsuc29tZSgoZW50cnkpID0+IGVudHJ5LmtpbmQgPT09ICdpbmxpbmUtc3RhcnRlZCcpXG4gICAgICAgICAgICA/IFtjb21taXRzW2luZGV4XV1cbiAgICAgICAgICAgIDogW11cbiAgICAgICAgKTtcbiAgICAgICAgaWYgKGFsbG93RGVmZXJyZWRCYXRjaFdvcmspIHtcbiAgICAgICAgICAvLyBUaGUgdHJhaWxpbmcgd29yayBpcyB0aGUgY2FsbGVyJ3MgdG8gam9pbiBiZWZvcmUgYWNrLiBBdHRhY2ggYVxuICAgICAgICAgIC8vIGhhbmRsZXIgbm93IHNvIGEgcmVqZWN0aW9uIHRoYXQgcmFjZXMgdGhhdCBqb2luIChvciBhIGZvcmVncm91bmRcbiAgICAgICAgICAvLyBmYWlsdXJlIHRoYXQgcHJldmVudHMgdGhlIGNhbGxlciBmcm9tIGV2ZXIgcmVhY2hpbmcgaXQpIGlzIG5ldmVyXG4gICAgICAgICAgLy8gYW4gdW5oYW5kbGVkUmVqZWN0aW9uOyBhd2FpdGluZyB0aGUgcHJvbWlzZSBzdGlsbCBvYnNlcnZlcyBpdC5cbiAgICAgICAgICB0cmFpbGluZy5jYXRjaCgoKSA9PiB7fSk7XG4gICAgICAgICAgZGVmZXJyZWRCYXRjaFdvcmsgPSB0cmFpbGluZztcbiAgICAgICAgICAvLyBPbmx5IHRoZSBwYWlyIGNodW5rcyBnYXRlIHRoZSByZXR1cm46IHRoZWlyIGNsYWltcyBhcmUgd2hhdCB0aGVcbiAgICAgICAgICAvLyBjYWxsZXIgc3RhcnRzIHRoZSBpbmxpbmUgYm9kaWVzIGZyb20uIFdpdGggbm8gcGFpcnMgdGhlcmUgaXNcbiAgICAgICAgICAvLyBub3RoaW5nIHRoZSBjYWxsZXIncyBwb3N0LXJldHVybiB3b3JrIHJlYWRzIGZyb20gdGhlIGNvbW1pdHMsXG4gICAgICAgICAgLy8gc28gbm90aGluZyBnYXRlcy5cbiAgICAgICAgICBpZiAocGFpckNvbW1pdHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwocGFpckNvbW1pdHMpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgIC8vIEEgcGFpciBjaHVuayBmYWlsZWQsIHNvIHRoaXMgcGhhc2UncyB3cml0ZSBzZXQgaXMgTk9UIHRoZVxuICAgICAgICAgICAgICAvLyBjYWxsZXIncyB0byBqb2luIGFueSBtb3JlOiBgZGVmZXJyZWRCYXRjaFdvcmtgIG5ldmVyXG4gICAgICAgICAgICAgIC8vIHJlYWNoZXMgaXQgb25jZSBoYW5kbGVTdXNwZW5zaW9uIHRocm93cy4gU2V0dGxlIHRoZSByZXN0XG4gICAgICAgICAgICAgIC8vIGJlZm9yZSB0aGUgcmVqZWN0aW9uIGVzY2FwZXMsIGZvciB0aGUgcmVhc29uIGBzZXR0bGVQaGFzZWBcbiAgICAgICAgICAgICAgLy8gZ2l2ZXM6IGEgc2libGluZyBjcmVhdGUgbGFuZGluZyBhZnRlciB0aGUgdGhyb3cgY29tbWl0cyBhblxuICAgICAgICAgICAgICAvLyBldmVudCBmcm9tIHRoZSBhYmFuZG9uZWQgcmVwbGF5J3Mgc2VlZGVkIHNlcXVlbmNlIGFuZCByYWNlc1xuICAgICAgICAgICAgICAvLyB0aGUgY2FsbGVyJ3MgcmVzdGFydCByZWxvYWQgd2hpbGUgZG9pbmcgc28uXG4gICAgICAgICAgICAgIGF3YWl0IHRyYWlsaW5nLmNhdGNoKCgpID0+IHt9KTtcbiAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBhd2FpdCB0cmFpbGluZztcbiAgICAgICAgfVxuICAgICAgfSkoKVxuICAgICk7XG4gIH1cblxuICBmb3IgKGNvbnN0IHF1ZXVlSXRlbSBvZiBhdHRyaWJ1dGVJdGVtcykge1xuICAgIG9wcy5wdXNoKFxuICAgICAgKGFzeW5jICgpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCBlbnN1cmVSdW5SZWFkeSgpO1xuICAgICAgICAgIC8vIEd1YXJkZWQgbGlrZSBldmVyeSBvdGhlciBzdXNwZW5zaW9uIHdyaXRlOiBhbiBhdHRyX3NldCBpcyBhXG4gICAgICAgICAgLy8gcmVwbGF5LWRlcml2ZWQgZXZlbnQgd2l0aCBhIGNvcnJlbGF0aW9uIGlkIGZyb20gdGhpcyByZXBsYXknc1xuICAgICAgICAgIC8vIHNlZWRlZCBzZXF1ZW5jZSwgc28gaXQgbXVzdCBub3QgbGFuZCBvbiBhIGxvZyB0aGUgcmVwbGF5IG5ldmVyXG4gICAgICAgICAgLy8gc2F3LiBSZWplY3RpbmcgaXQgaXMgY2hlYXA6IGEgcnVuIHdpdGggYXR0cmlidXRlIGV2ZW50cyBhbHJlYWR5XG4gICAgICAgICAgLy8gZm9yY2VzIGFuIGluLXByb2Nlc3MgcmVwbGF5LCBzbyB0aGUgcmVzdGFydCBjb3N0cyB0aGUgcmVwbGF5IGl0XG4gICAgICAgICAgLy8gd2FzIGdvaW5nIHRvIGRvIGFueXdheS5cbiAgICAgICAgICBhd2FpdCBjcmVhdGVHdWFyZGVkKFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBldmVudFR5cGU6ICdhdHRyX3NldCcsXG4gICAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgIGNoYW5nZXM6IHF1ZXVlSXRlbS5jaGFuZ2VzLFxuICAgICAgICAgICAgICAgIHdyaXRlcjogeyB0eXBlOiAnd29ya2Zsb3cnIH0sXG4gICAgICAgICAgICAgICAgLi4uKHF1ZXVlSXRlbS5hbGxvd1Jlc2VydmVkQXR0cmlidXRlc1xuICAgICAgICAgICAgICAgICAgPyB7IGFsbG93UmVzZXJ2ZWRBdHRyaWJ1dGVzOiB0cnVlIH1cbiAgICAgICAgICAgICAgICAgIDoge30pLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHsgcmVxdWVzdElkIH1cbiAgICAgICAgICApO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICdXb3JrZmxvdyBhdHRyaWJ1dGUgZXZlbnQgYWxyZWFkeSBleGlzdHMsIGNvbnRpbnVpbmcnLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIGlmIChpc1dvcmxkVmFsaWRhdGlvbkZhaWx1cmUoZXJyKSkge1xuICAgICAgICAgICAgLy8gRGV0ZXJtaW5pc3RpYyB2YWxpZGF0aW9uIHJlamVjdGlvbiBmcm9tIHRoZSBXb3JsZCwgZS5nLiB0aGVcbiAgICAgICAgICAgIC8vIGN1bXVsYXRpdmUgcGVyLXJ1biBhdHRyaWJ1dGUgY2FwLCB3aGljaCBvbmx5IHRoZSBXb3JsZCBjYW5cbiAgICAgICAgICAgIC8vIGNoZWNrIGFnYWluc3QgdGhlIHJ1bidzIGV4aXN0aW5nIGF0dHJpYnV0ZXMuIFJlZGVsaXZlcmluZyB0aGVcbiAgICAgICAgICAgIC8vIG9yY2hlc3RyYXRvciBtZXNzYWdlIHJlcGxheXMgdGhlIHdvcmtmbG93IGludG8gdGhlIGV4YWN0IHNhbWVcbiAgICAgICAgICAgIC8vIHdyaXRlIGFuZCB0aGUgZXhhY3Qgc2FtZSByZWplY3Rpb24sIHNvIHJldHJ5aW5nIGNhbiBuZXZlclxuICAgICAgICAgICAgLy8gc3VjY2VlZC4gU3VyZmFjZSBpdCBhcyBhIEZhdGFsRXJyb3Igc28gdGhlIGNhbGxlciBmYWlscyB0aGVcbiAgICAgICAgICAgIC8vIHJ1biB3aXRoIGEgY2xlYXIgZXJyb3IgaW5zdGVhZCBvZiB3ZWRnaW5nIGl0IGluIHJlZGVsaXZlcnkuXG4gICAgICAgICAgICBjb25zdCBmYXRhbCA9IG5ldyBGYXRhbEVycm9yKFxuICAgICAgICAgICAgICBgc2V0QXR0cmlidXRlcyBmYWlsZWQgV29ybGQgdmFsaWRhdGlvbjogJHtcbiAgICAgICAgICAgICAgICBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVycilcbiAgICAgICAgICAgICAgfWBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBmYXRhbC5jYXVzZSA9IGVycjtcbiAgICAgICAgICAgIHRocm93IGZhdGFsO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KSgpXG4gICAgKTtcbiAgfVxuXG4gIC8vIEF3YWl0IHRoZSBzdGVwX2NyZWF0ZWQgLyB3YWl0X2NyZWF0ZWQgZXZlbnQgY3JlYXRlcyBiZWZvcmUgcmV0dXJuaW5nLlxuICAvLyBUaGUgY2FsbGVyICh3b3JrZmxvd0VudHJ5cG9pbnQpIG9ubHkgZW5xdWV1ZXMgdGhlIHN0ZXAtZGlzcGF0Y2ggcXVldWVcbiAgLy8gbWVzc2FnZXMgQUZURVIgaGFuZGxlU3VzcGVuc2lvbiByZXNvbHZlcywgYW5kIHRoZSBxdWV1ZSBoYW5kbGVyIGFja3NcbiAgLy8gdGhlIG9yY2hlc3RyYXRvciBtZXNzYWdlIG9ubHkgYWZ0ZXIgdGhlIGNhbGxlciByZXNvbHZlcy4gU28gdGhlIHN0ZXBfY3JlYXRlZFxuICAvLyBldmVudHMgbXVzdCBiZSBkdXJhYmxlIGhlcmUsIGFuZCB0aGUgZGlzcGF0Y2ggc2VuZHMgbXVzdCBjb21wbGV0ZSBpbiB0aGUgY2FsbGVyLFxuICAvLyBhbGwgYmVmb3JlIGFjay4gSWYgdGhlIHByb2Nlc3MgY3Jhc2hlcyBiZWZvcmUgdGhpcyByZXNvbHZlcywgdGhlIG9yY2hlc3RyYXRvclxuICAvLyBtZXNzYWdlIGlzIG5vdCBhY2tlZCBhbmQgVlFTIHJlZGVsaXZlcnMsIHJlLWNyZWF0ZXMgdGhlIChpZGVtcG90ZW50KVxuICAvLyBzdGVwX2NyZWF0ZWQgYW5kIHJlLWRpc3BhdGNoZXMsIGFuZCByZWNvdmVycyB0aGUgcnVuIGluc3RlYWQgb2Ygb3JwaGFuaW5nIGl0LlxuICBhd2FpdCBzZXR0bGVQaGFzZShvcHMpO1xuXG4gIC8vIFJlYnVpbGQgdGhlIGlubGluZSBiYXRjaCBpbiBkZXRlcm1pbmlzdGljIG9yZGVyLiBgbGF6eUlubGluZUNvcnJlbGF0aW9uSWRzYFxuICAvLyBpcyBhIFNldCBzZWVkZWQgZnJvbSB0aGUgb3JkZXJlZCBmaXJzdC1OIHNsaWNlLCBzbyBpdGVyYXRpbmcgaXQgcHJlc2VydmVzXG4gIC8vIHN0ZXBJdGVtcyBvcmRlcjsgZXZlcnkgaWQgaW4gaXQgd2FzIHNldCBieSB0aGUgbGF6eSBicmFuY2ggYWJvdmUuXG4gIGNvbnN0IGxhenlJbmxpbmVTdGVwczogU3VzcGVuc2lvbkhhbmRsZXJSZXN1bHRbJ2xhenlJbmxpbmVTdGVwcyddID0gW107XG4gIGZvciAoY29uc3QgY29ycmVsYXRpb25JZCBvZiBsYXp5SW5saW5lQ29ycmVsYXRpb25JZHMpIHtcbiAgICBjb25zdCBsYXp5U3RlcCA9IGxhenlJbmxpbmVCeUNvcnJlbGF0aW9uSWQuZ2V0KGNvcnJlbGF0aW9uSWQpO1xuICAgIGlmIChsYXp5U3RlcCkgbGF6eUlubGluZVN0ZXBzLnB1c2gobGF6eVN0ZXApO1xuICB9XG5cbiAgLy8gRmluZCB0aGUgc29vbmVzdCBwZW5kaW5nIHdhaXQgKG1pbmltdW0gdGltZW91dClcbiAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgbGV0IHNvb25lc3RXYWl0OiB7IHNlY29uZHM6IG51bWJlcjsgY29ycmVsYXRpb25JZDogc3RyaW5nIH0gfCB1bmRlZmluZWQ7XG4gIGZvciAoY29uc3QgcXVldWVJdGVtIG9mIHdhaXRJdGVtcykge1xuICAgIGNvbnN0IHJlc3VtZUF0TXMgPSBxdWV1ZUl0ZW0ucmVzdW1lQXQuZ2V0VGltZSgpO1xuICAgIGNvbnN0IGRlbGF5TXMgPSBNYXRoLm1heCgxMDAwLCByZXN1bWVBdE1zIC0gbm93KTtcbiAgICBjb25zdCB0aW1lb3V0U2Vjb25kcyA9IE1hdGguY2VpbChkZWxheU1zIC8gMTAwMCk7XG4gICAgaWYgKCFzb29uZXN0V2FpdCB8fCB0aW1lb3V0U2Vjb25kcyA8IHNvb25lc3RXYWl0LnNlY29uZHMpIHtcbiAgICAgIHNvb25lc3RXYWl0ID0ge1xuICAgICAgICBzZWNvbmRzOiB0aW1lb3V0U2Vjb25kcyxcbiAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1J1blN0YXR1cygnd29ya2Zsb3dfc3VzcGVuZGVkJyksXG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93U3RlcHNDcmVhdGVkKHN0ZXBJdGVtcy5sZW5ndGgpLFxuICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd0hvb2tzQ3JlYXRlZChob29rc05lZWRpbmdDcmVhdGlvbi5sZW5ndGgpLFxuICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1dhaXRzQ3JlYXRlZCh3YWl0SXRlbXMubGVuZ3RoKSxcbiAgICAuLi4oZmFpbGVkU3RlcENvcnJlbGF0aW9uSWRzLnNpemUgPiAwXG4gICAgICA/IEF0dHJpYnV0ZS5Xb3JrZmxvd1N0ZXBzRmFpbGVkU2VyaWFsaXphdGlvbihcbiAgICAgICAgICBmYWlsZWRTdGVwQ29ycmVsYXRpb25JZHMuc2l6ZVxuICAgICAgICApXG4gICAgICA6IHt9KSxcbiAgICAuLi4ocmVzaWxpZW50RGlzcGF0Y2hSZWNvdmVyZWQgPiAwXG4gICAgICA/IEF0dHJpYnV0ZS5TdGVwUmVzaWxpZW50RGlzcGF0Y2hSZWNvdmVyZWQocmVzaWxpZW50RGlzcGF0Y2hSZWNvdmVyZWQpXG4gICAgICA6IHt9KSxcbiAgfSk7XG5cbiAgcmV0dXJuIHtcbiAgICBwZW5kaW5nU3RlcHM6IHN0ZXBJdGVtcyxcbiAgICBjcmVhdGVkU3RlcENvcnJlbGF0aW9uSWRzLFxuICAgIGZhaWxlZFN0ZXBDb3JyZWxhdGlvbklkcyxcbiAgICBxdWV1ZWRTdGVwQ29ycmVsYXRpb25JZHMsXG4gICAgbGF6eUlubGluZVN0ZXBzLFxuICAgIGlubGluZUNsYWltcyxcbiAgICBiYXRjaENvbW1pdHRlZFNsb3RDZWlsaW5nLFxuICAgIGRlZmVycmVkQmF0Y2hXb3JrLFxuICAgIC8vIE9uIGhvb2sgY29uZmxpY3QgdGhlIGNhbGxlciBhZHZhbmNlcyB0aGUgd29ya2Zsb3cgb3ZlciB0aGUgY29uZmxpY3RcbiAgICAvLyBiZWZvcmUgc2NoZWR1bGluZyBhbnl0aGluZyBhbmQgbmV2ZXIgcmVhZHMgdGhlIHdhaXQgdGltZW91dCwgc28gZG9uJ3RcbiAgICAvLyByZXBvcnQgb25lLiBUaGUgbmV4dCBwYXNzLCB3aGljaCBzZWVzIHRoZSBjb25mbGljdCBzZXR0bGVkLCByZXBvcnRzIGl0LlxuICAgIHdhaXRUaW1lb3V0OlxuICAgICAgaG9va0NvbmZsaWN0Q29ycmVsYXRpb25JZHMubGVuZ3RoID4gMCA/IHVuZGVmaW5lZCA6IHNvb25lc3RXYWl0LFxuICAgIGhhc0hvb2tDb25mbGljdDogaG9va0NvbmZsaWN0Q29ycmVsYXRpb25JZHMubGVuZ3RoID4gMCxcbiAgICBob29rQ29uZmxpY3RDb3JyZWxhdGlvbklkcyxcbiAgICBoYXNBd2FpdGVkSG9va0NyZWF0aW9uOiBhd2FpdGVkSG9va0NvcnJlbGF0aW9uSWRzLmxlbmd0aCA+IDAsXG4gICAgYXdhaXRlZEhvb2tDb3JyZWxhdGlvbklkcyxcbiAgICAvLyBUaGUgZGVsdGEgYWNjb3VudHMgZm9yIHRoZSB3aG9sZSBsb2cgb25seSBpZiB0aGUgd3JpdGUgdGhhdCByZXR1cm5lZCBpdFxuICAgIC8vIHdhcyB0aGlzIHN1c3BlbnNpb24ncyBvbmx5IG9uZSDigJQgYW55dGhpbmcgd3JpdHRlbiBhZnRlciBpdCBsYW5kZWQgYWJvdmVcbiAgICAvLyB0aGUgZGVsdGEgYW5kIGlzIG1pc3NpbmcgZnJvbSB0aGUgY2FsbGVyJ3MgbG9nLlxuICAgIGV2ZW50TG9nQ2FycmllZEZvcndhcmQ6IGRlbHRhQWJzb3JiZWQgJiYgZ3VhcmRlZFdyaXRlcyA9PT0gMSxcbiAgICBoYXNBdHRyaWJ1dGVFdmVudHM6IGF0dHJpYnV0ZUl0ZW1zLmxlbmd0aCA+IDAsXG4gICAgaGFzSG9va0V2ZW50czogaG9va3NOZWVkaW5nQ3JlYXRpb24ubGVuZ3RoID4gMCxcbiAgICBob29rQ3JlYXRpb25NcyxcbiAgICBzZXJpYWxpemF0aW9uQmxvY2tlckNvdW50LFxuICAgIHNlcmlhbGl6YXRpb25CbG9ja2VycyxcbiAgICByZXBvcnRlZEV2ZW50Q291bnQ6IHJlcG9ydGVkRXZlbnRzLFxuICB9O1xufVxuXG4vKipcbiAqIFdoZXRoZXIgYW4gYGV2ZW50cy5jcmVhdGVgIHJlamVjdGlvbiBpcyBkZXRlcm1pbmlzdGljIFdvcmxkIHZhbGlkYXRpb25cbiAqIHJhdGhlciB0aGFuIGEgdHJhbnNpZW50L3N0b3JhZ2UgZXJyb3IuIExvY2FsIFdvcmxkc1xuICogKHdvcmxkLWxvY2FsLCB3b3JsZC1wb3N0Z3JlcykgdGhyb3cgYEF0dHJpYnV0ZVZhbGlkYXRpb25FcnJvcmAgZGlyZWN0bHk7XG4gKiByZW1vdGUgV29ybGRzIHN1cmZhY2UgdGhlIGVxdWl2YWxlbnQgc2VydmVyLXNpZGUgcmVqZWN0aW9uIGFzIGFcbiAqIGBXb3JrZmxvd1dvcmxkRXJyb3JgIHdpdGggSFRUUCBzdGF0dXMgNDAwLiBUaGUgbmFtZSBjaGVjayBjb3ZlcnNcbiAqIGBBdHRyaWJ1dGVWYWxpZGF0aW9uRXJyb3JgIGluc3RhbmNlcyBmcm9tIGEgZGlmZmVyZW50IGNvcHkgb2ZcbiAqIGBAd29ya2Zsb3cvd29ybGRgIHRoYW4gdGhlIG9uZSB0aGlzIHBhY2thZ2UgcmVzb2x2ZWQuXG4gKi9cbmZ1bmN0aW9uIGlzV29ybGRWYWxpZGF0aW9uRmFpbHVyZShlcnI6IHVua25vd24pOiBib29sZWFuIHtcbiAgaWYgKGVyciBpbnN0YW5jZW9mIEF0dHJpYnV0ZVZhbGlkYXRpb25FcnJvcikgcmV0dXJuIHRydWU7XG4gIGlmIChlcnIgaW5zdGFuY2VvZiBFcnJvciAmJiBlcnIubmFtZSA9PT0gJ0F0dHJpYnV0ZVZhbGlkYXRpb25FcnJvcicpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICByZXR1cm4gV29ya2Zsb3dXb3JsZEVycm9yLmlzKGVycikgJiYgZXJyLnN0YXR1cyA9PT0gNDAwO1xufVxuIl19