@workflow/core 5.0.0-beta.4 → 5.0.0-beta.41

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 (322) hide show
  1. package/dist/attribute-changes.d.ts +7 -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 +33 -1
  5. package/dist/capabilities.d.ts.map +1 -1
  6. package/dist/capabilities.js +71 -4
  7. package/dist/capture-stack.d.ts +16 -0
  8. package/dist/capture-stack.d.ts.map +1 -0
  9. package/dist/capture-stack.js +21 -0
  10. package/dist/class-serialization.d.ts +32 -0
  11. package/dist/class-serialization.d.ts.map +1 -1
  12. package/dist/class-serialization.js +37 -1
  13. package/dist/classify-error.d.ts +26 -3
  14. package/dist/classify-error.d.ts.map +1 -1
  15. package/dist/classify-error.js +109 -6
  16. package/dist/context-errors.d.ts +27 -0
  17. package/dist/context-errors.d.ts.map +1 -0
  18. package/dist/context-errors.js +101 -0
  19. package/dist/context-violation-error.d.ts +97 -0
  20. package/dist/context-violation-error.d.ts.map +1 -0
  21. package/dist/context-violation-error.js +149 -0
  22. package/dist/create-hook.d.ts +62 -4
  23. package/dist/create-hook.d.ts.map +1 -1
  24. package/dist/create-hook.js +4 -3
  25. package/dist/define-hook.d.ts.map +1 -1
  26. package/dist/define-hook.js +20 -5
  27. package/dist/describe-error.d.ts +70 -0
  28. package/dist/describe-error.d.ts.map +1 -0
  29. package/dist/describe-error.js +189 -0
  30. package/dist/encryption.d.ts +37 -3
  31. package/dist/encryption.d.ts.map +1 -1
  32. package/dist/encryption.js +97 -31
  33. package/dist/events-consumer.d.ts +147 -1
  34. package/dist/events-consumer.d.ts.map +1 -1
  35. package/dist/events-consumer.js +444 -43
  36. package/dist/flushable-stream.d.ts +65 -10
  37. package/dist/flushable-stream.d.ts.map +1 -1
  38. package/dist/flushable-stream.js +131 -18
  39. package/dist/global.d.ts +37 -1
  40. package/dist/global.d.ts.map +1 -1
  41. package/dist/global.js +21 -3
  42. package/dist/index.d.ts +1 -0
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +2 -1
  45. package/dist/log-format.d.ts +25 -0
  46. package/dist/log-format.d.ts.map +1 -0
  47. package/dist/log-format.js +250 -0
  48. package/dist/logger.d.ts +29 -30
  49. package/dist/logger.d.ts.map +1 -1
  50. package/dist/logger.js +82 -32
  51. package/dist/private.d.ts +246 -8
  52. package/dist/private.d.ts.map +1 -1
  53. package/dist/private.js +345 -9
  54. package/dist/replay-payload-cache.d.ts +68 -0
  55. package/dist/replay-payload-cache.d.ts.map +1 -0
  56. package/dist/replay-payload-cache.js +160 -0
  57. package/dist/runtime/compute-instance.d.ts +12 -0
  58. package/dist/runtime/compute-instance.d.ts.map +1 -0
  59. package/dist/runtime/compute-instance.js +13 -0
  60. package/dist/runtime/constants.d.ts +251 -0
  61. package/dist/runtime/constants.d.ts.map +1 -1
  62. package/dist/runtime/constants.js +425 -16
  63. package/dist/runtime/count-step-started-events.d.ts +52 -0
  64. package/dist/runtime/count-step-started-events.d.ts.map +1 -0
  65. package/dist/runtime/count-step-started-events.js +72 -0
  66. package/dist/runtime/deployment-guard.d.ts +99 -0
  67. package/dist/runtime/deployment-guard.d.ts.map +1 -0
  68. package/dist/runtime/deployment-guard.js +154 -0
  69. package/dist/runtime/get-port-lazy.d.ts +25 -0
  70. package/dist/runtime/get-port-lazy.d.ts.map +1 -0
  71. package/dist/runtime/get-port-lazy.js +92 -0
  72. package/dist/runtime/get-world-lazy.d.ts +23 -0
  73. package/dist/runtime/get-world-lazy.d.ts.map +1 -0
  74. package/dist/runtime/get-world-lazy.js +46 -0
  75. package/dist/runtime/helpers.d.ts +327 -10
  76. package/dist/runtime/helpers.d.ts.map +1 -1
  77. package/dist/runtime/helpers.js +586 -40
  78. package/dist/runtime/quickjs-assets.generated.d.ts +14 -0
  79. package/dist/runtime/quickjs-assets.generated.d.ts.map +1 -0
  80. package/dist/runtime/quickjs-assets.generated.js +30 -0
  81. package/dist/runtime/quickjs-entrypoint.d.ts +124 -0
  82. package/dist/runtime/quickjs-entrypoint.d.ts.map +1 -0
  83. package/dist/runtime/quickjs-entrypoint.js +1437 -0
  84. package/dist/runtime/quickjs-runtime.d.ts +228 -0
  85. package/dist/runtime/quickjs-runtime.d.ts.map +1 -0
  86. package/dist/runtime/quickjs-runtime.js +2372 -0
  87. package/dist/runtime/quickjs-serde.d.ts +107 -0
  88. package/dist/runtime/quickjs-serde.d.ts.map +1 -0
  89. package/dist/runtime/quickjs-serde.js +2098 -0
  90. package/dist/runtime/replay-budget.d.ts +89 -0
  91. package/dist/runtime/replay-budget.d.ts.map +1 -0
  92. package/dist/runtime/replay-budget.js +139 -0
  93. package/dist/runtime/replay-recovery-reporter.d.ts +36 -0
  94. package/dist/runtime/replay-recovery-reporter.d.ts.map +1 -0
  95. package/dist/runtime/replay-recovery-reporter.js +64 -0
  96. package/dist/runtime/resume-hook.d.ts +27 -4
  97. package/dist/runtime/resume-hook.d.ts.map +1 -1
  98. package/dist/runtime/resume-hook.js +452 -76
  99. package/dist/runtime/run-id-time.d.ts +19 -0
  100. package/dist/runtime/run-id-time.d.ts.map +1 -0
  101. package/dist/runtime/run-id-time.js +42 -0
  102. package/dist/runtime/run.d.ts +8 -2
  103. package/dist/runtime/run.d.ts.map +1 -1
  104. package/dist/runtime/run.js +62 -15
  105. package/dist/runtime/runs.d.ts +54 -3
  106. package/dist/runtime/runs.d.ts.map +1 -1
  107. package/dist/runtime/runs.js +119 -13
  108. package/dist/runtime/start.d.ts +70 -1
  109. package/dist/runtime/start.d.ts.map +1 -1
  110. package/dist/runtime/start.js +313 -60
  111. package/dist/runtime/step-executor.d.ts +177 -0
  112. package/dist/runtime/step-executor.d.ts.map +1 -0
  113. package/dist/runtime/step-executor.js +946 -0
  114. package/dist/runtime/step-latency.d.ts +197 -0
  115. package/dist/runtime/step-latency.d.ts.map +1 -0
  116. package/dist/runtime/step-latency.js +207 -0
  117. package/dist/runtime/step-ownership.d.ts +72 -0
  118. package/dist/runtime/step-ownership.d.ts.map +1 -0
  119. package/dist/runtime/step-ownership.js +114 -0
  120. package/dist/runtime/step-single-flight.d.ts +12 -0
  121. package/dist/runtime/step-single-flight.d.ts.map +1 -0
  122. package/dist/runtime/step-single-flight.js +69 -0
  123. package/dist/runtime/suspension-handler.d.ts +109 -7
  124. package/dist/runtime/suspension-handler.d.ts.map +1 -1
  125. package/dist/runtime/suspension-handler.js +486 -140
  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 +84 -0
  133. package/dist/runtime/wait-continuation.d.ts.map +1 -0
  134. package/dist/runtime/wait-continuation.js +105 -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 +20 -0
  139. package/dist/runtime/world-compatibility.d.ts.map +1 -0
  140. package/dist/runtime/world-compatibility.js +32 -0
  141. package/dist/runtime/world-init.d.ts +50 -0
  142. package/dist/runtime/world-init.d.ts.map +1 -0
  143. package/dist/runtime/world-init.js +50 -0
  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 +101 -26
  147. package/dist/runtime.d.ts +17 -12
  148. package/dist/runtime.d.ts.map +1 -1
  149. package/dist/runtime.js +3135 -328
  150. package/dist/schemas.d.ts +1 -1
  151. package/dist/schemas.d.ts.map +1 -1
  152. package/dist/schemas.js +1 -1
  153. package/dist/sealed-box.d.ts +167 -0
  154. package/dist/sealed-box.d.ts.map +1 -0
  155. package/dist/sealed-box.js +571 -0
  156. package/dist/serialization/client.d.ts +17 -0
  157. package/dist/serialization/client.d.ts.map +1 -0
  158. package/dist/serialization/client.js +48 -0
  159. package/dist/serialization/codec-devalue-vm.d.ts +16 -0
  160. package/dist/serialization/codec-devalue-vm.d.ts.map +1 -0
  161. package/dist/serialization/codec-devalue-vm.js +148 -0
  162. package/dist/serialization/codec-devalue.d.ts +14 -0
  163. package/dist/serialization/codec-devalue.d.ts.map +1 -0
  164. package/dist/serialization/codec-devalue.js +105 -0
  165. package/dist/serialization/codec.d.ts +125 -0
  166. package/dist/serialization/codec.d.ts.map +1 -0
  167. package/dist/serialization/codec.js +17 -0
  168. package/dist/serialization/compression.d.ts +104 -0
  169. package/dist/serialization/compression.d.ts.map +1 -0
  170. package/dist/serialization/compression.js +260 -0
  171. package/dist/serialization/encryption.d.ts +134 -0
  172. package/dist/serialization/encryption.d.ts.map +1 -0
  173. package/dist/serialization/encryption.js +186 -0
  174. package/dist/serialization/errors.d.ts +34 -0
  175. package/dist/serialization/errors.d.ts.map +1 -0
  176. package/dist/serialization/errors.js +59 -0
  177. package/dist/serialization/format.d.ts +60 -0
  178. package/dist/serialization/format.d.ts.map +1 -0
  179. package/dist/serialization/format.js +97 -0
  180. package/dist/serialization/hardened.d.ts +155 -0
  181. package/dist/serialization/hardened.d.ts.map +1 -0
  182. package/dist/serialization/hardened.js +523 -0
  183. package/dist/serialization/index.d.ts +20 -0
  184. package/dist/serialization/index.d.ts.map +1 -0
  185. package/dist/serialization/index.js +22 -0
  186. package/dist/serialization/reducers/class-vm.d.ts +20 -0
  187. package/dist/serialization/reducers/class-vm.d.ts.map +1 -0
  188. package/dist/serialization/reducers/class-vm.js +77 -0
  189. package/dist/serialization/reducers/class.d.ts +11 -0
  190. package/dist/serialization/reducers/class.d.ts.map +1 -0
  191. package/dist/serialization/reducers/class.js +73 -0
  192. package/dist/serialization/reducers/common-vm.d.ts +15 -0
  193. package/dist/serialization/reducers/common-vm.d.ts.map +1 -0
  194. package/dist/serialization/reducers/common-vm.js +579 -0
  195. package/dist/serialization/reducers/common.d.ts +16 -0
  196. package/dist/serialization/reducers/common.d.ts.map +1 -0
  197. package/dist/serialization/reducers/common.js +478 -0
  198. package/dist/serialization/reducers/step-function-vm.d.ts +44 -0
  199. package/dist/serialization/reducers/step-function-vm.d.ts.map +1 -0
  200. package/dist/serialization/reducers/step-function-vm.js +97 -0
  201. package/dist/serialization/reducers/step-function.d.ts +35 -0
  202. package/dist/serialization/reducers/step-function.d.ts.map +1 -0
  203. package/dist/serialization/reducers/step-function.js +104 -0
  204. package/dist/serialization/step.d.ts +17 -0
  205. package/dist/serialization/step.d.ts.map +1 -0
  206. package/dist/serialization/step.js +48 -0
  207. package/dist/serialization/types.d.ts +273 -0
  208. package/dist/serialization/types.d.ts.map +1 -0
  209. package/dist/serialization/types.js +35 -0
  210. package/dist/serialization/workflow-vm.d.ts +29 -0
  211. package/dist/serialization/workflow-vm.d.ts.map +1 -0
  212. package/dist/serialization/workflow-vm.js +71 -0
  213. package/dist/serialization/workflow.d.ts +29 -0
  214. package/dist/serialization/workflow.d.ts.map +1 -0
  215. package/dist/serialization/workflow.js +54 -0
  216. package/dist/serialization-format.d.ts +60 -4
  217. package/dist/serialization-format.d.ts.map +1 -1
  218. package/dist/serialization-format.js +276 -56
  219. package/dist/serialization.d.ts +374 -221
  220. package/dist/serialization.d.ts.map +1 -1
  221. package/dist/serialization.js +2300 -783
  222. package/dist/set-attributes.d.ts +13 -0
  223. package/dist/set-attributes.d.ts.map +1 -0
  224. package/dist/set-attributes.js +60 -0
  225. package/dist/sleep.d.ts.map +1 -1
  226. package/dist/sleep.js +3 -2
  227. package/dist/source-map.d.ts +25 -0
  228. package/dist/source-map.d.ts.map +1 -1
  229. package/dist/source-map.js +148 -10
  230. package/dist/step/context-storage.d.ts +61 -2
  231. package/dist/step/context-storage.d.ts.map +1 -1
  232. package/dist/step/context-storage.js +7 -5
  233. package/dist/step/get-closure-vars.d.ts.map +1 -1
  234. package/dist/step/get-closure-vars.js +3 -2
  235. package/dist/step/get-step-metadata.d.ts.map +1 -1
  236. package/dist/step/get-step-metadata.js +3 -2
  237. package/dist/step/get-workflow-metadata.d.ts.map +1 -1
  238. package/dist/step/get-workflow-metadata.js +3 -2
  239. package/dist/step/writable-stream.d.ts.map +1 -1
  240. package/dist/step/writable-stream.js +71 -7
  241. package/dist/step.d.ts.map +1 -1
  242. package/dist/step.js +225 -29
  243. package/dist/symbols.d.ts +54 -0
  244. package/dist/symbols.d.ts.map +1 -1
  245. package/dist/symbols.js +55 -1
  246. package/dist/telemetry/semantic-conventions.d.ts +265 -2
  247. package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
  248. package/dist/telemetry/semantic-conventions.js +190 -1
  249. package/dist/telemetry.d.ts +73 -0
  250. package/dist/telemetry.d.ts.map +1 -1
  251. package/dist/telemetry.js +153 -16
  252. package/dist/types.d.ts +6 -0
  253. package/dist/types.d.ts.map +1 -1
  254. package/dist/types.js +23 -1
  255. package/dist/util.d.ts +16 -6
  256. package/dist/util.d.ts.map +1 -1
  257. package/dist/util.js +25 -16
  258. package/dist/version.d.ts +1 -1
  259. package/dist/version.d.ts.map +1 -1
  260. package/dist/version.js +2 -2
  261. package/dist/vm/index.d.ts.map +1 -1
  262. package/dist/vm/index.js +85 -14
  263. package/dist/vm/script-cache.d.ts +28 -0
  264. package/dist/vm/script-cache.d.ts.map +1 -0
  265. package/dist/vm/script-cache.js +140 -0
  266. package/dist/workflow/abort-controller.d.ts +65 -0
  267. package/dist/workflow/abort-controller.d.ts.map +1 -0
  268. package/dist/workflow/abort-controller.js +312 -0
  269. package/dist/workflow/attribute-dispatcher.d.ts +6 -0
  270. package/dist/workflow/attribute-dispatcher.d.ts.map +1 -0
  271. package/dist/workflow/attribute-dispatcher.js +48 -0
  272. package/dist/workflow/create-hook.d.ts.map +1 -1
  273. package/dist/workflow/create-hook.js +25 -3
  274. package/dist/workflow/define-hook.d.ts +1 -1
  275. package/dist/workflow/define-hook.d.ts.map +1 -1
  276. package/dist/workflow/define-hook.js +8 -4
  277. package/dist/workflow/get-workflow-metadata.d.ts.map +1 -1
  278. package/dist/workflow/get-workflow-metadata.js +14 -3
  279. package/dist/workflow/hook.d.ts.map +1 -1
  280. package/dist/workflow/hook.js +302 -36
  281. package/dist/workflow/index.d.ts +1 -0
  282. package/dist/workflow/index.d.ts.map +1 -1
  283. package/dist/workflow/index.js +5 -3
  284. package/dist/workflow/set-attributes.d.ts +68 -0
  285. package/dist/workflow/set-attributes.d.ts.map +1 -0
  286. package/dist/workflow/set-attributes.js +60 -0
  287. package/dist/workflow/sleep.d.ts.map +1 -1
  288. package/dist/workflow/sleep.js +57 -8
  289. package/dist/workflow/world-init-stub.d.ts +15 -0
  290. package/dist/workflow/world-init-stub.d.ts.map +1 -0
  291. package/dist/workflow/world-init-stub.js +15 -0
  292. package/dist/workflow.d.ts +79 -3
  293. package/dist/workflow.d.ts.map +1 -1
  294. package/dist/workflow.js +831 -553
  295. package/docs/api-reference/create-hook.mdx +79 -0
  296. package/docs/api-reference/create-webhook.mdx +1 -0
  297. package/docs/api-reference/define-hook.mdx +26 -24
  298. package/docs/api-reference/fatal-error.mdx +29 -7
  299. package/docs/api-reference/fetch.mdx +8 -4
  300. package/docs/api-reference/index.mdx +3 -0
  301. package/docs/api-reference/set-attributes.mdx +61 -0
  302. package/docs/api-reference/sleep.mdx +1 -1
  303. package/docs/foundations/cancellation.mdx +459 -0
  304. package/docs/foundations/errors-and-retries.mdx +7 -3
  305. package/docs/foundations/hooks.mdx +29 -0
  306. package/docs/foundations/idempotency.mdx +243 -11
  307. package/docs/foundations/index.mdx +1 -23
  308. package/docs/foundations/meta.json +3 -1
  309. package/docs/foundations/serialization.mdx +77 -41
  310. package/docs/foundations/starting-workflows.mdx +79 -2
  311. package/docs/foundations/streaming.mdx +14 -23
  312. package/docs/foundations/versioning.mdx +263 -0
  313. package/docs/how-it-works/cancellation.mdx +287 -0
  314. package/docs/how-it-works/code-transform.mdx +21 -17
  315. package/docs/how-it-works/encryption.mdx +5 -5
  316. package/docs/how-it-works/event-sourcing.mdx +17 -9
  317. package/docs/how-it-works/framework-integrations.mdx +96 -337
  318. package/docs/how-it-works/meta.json +2 -1
  319. package/package.json +31 -13
  320. package/dist/runtime/step-handler.d.ts +0 -2
  321. package/dist/runtime/step-handler.d.ts.map +0 -1
  322. package/dist/runtime/step-handler.js +0 -678
@@ -1,128 +1,340 @@
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, WorkflowWorldError, } from '@workflow/errors';
2
+ import { AttributeValidationError, SPEC_VERSION_CURRENT, SPEC_VERSION_SUPPORTS_COMPRESSION, } from '@workflow/world';
4
3
  import { importKey } from '../encryption.js';
5
4
  import { runtimeLogger } from '../logger.js';
6
5
  import { dehydrateStepArguments } from '../serialization.js';
7
6
  import * as Attribute from '../telemetry/semantic-conventions.js';
8
- import { serializeTraceCarrier } from '../telemetry.js';
9
- import { queueMessage } from './helpers.js';
10
- /**
11
- * Extracts W3C trace context headers from a trace carrier for HTTP propagation.
12
- * Returns an object with `traceparent` and optionally `tracestate` headers.
13
- */
14
- function extractTraceHeaders(traceCarrier) {
15
- const headers = {};
16
- if (traceCarrier.traceparent) {
17
- headers.traceparent = traceCarrier.traceparent;
7
+ import { getAbortStreamIdFromToken } from '../util.js';
8
+ import { getMaxInlineSteps } from './constants.js';
9
+ import { mergeReportedEvents, preconditionSnapshotParams, } from './helpers.js';
10
+ import { ReplayRecoveryReporter } from './replay-recovery-reporter.js';
11
+ async function createHookEvent({ runId, hookEvent, queueItem, requestId, createEvent, }) {
12
+ try {
13
+ const result = await createEvent(hookEvent, {
14
+ requestId,
15
+ });
16
+ // Check if the world returned a hook_conflict event instead of hook_created.
17
+ // The hook_conflict event is stored in the event log and will be replayed
18
+ // on the next workflow invocation, causing the hook's promise to reject.
19
+ if (result.event?.eventType === 'hook_conflict') {
20
+ return {
21
+ hasHookConflict: true,
22
+ hasAwaitedHookCreation: false,
23
+ };
24
+ }
25
+ return {
26
+ hasHookConflict: false,
27
+ hasAwaitedHookCreation: queueItem.hasConflictAwaiter === true,
28
+ };
18
29
  }
19
- if (traceCarrier.tracestate) {
20
- headers.tracestate = traceCarrier.tracestate;
30
+ catch (err) {
31
+ if (EntityConflictError.is(err)) {
32
+ runtimeLogger.info('Hook already exists, continuing', {
33
+ workflowRunId: runId,
34
+ message: err.message,
35
+ });
36
+ return {
37
+ hasHookConflict: false,
38
+ hasAwaitedHookCreation: queueItem.hasConflictAwaiter === true,
39
+ };
40
+ }
41
+ if (RunExpiredError.is(err)) {
42
+ runtimeLogger.info('Workflow run already completed, skipping hook', {
43
+ workflowRunId: runId,
44
+ message: err.message,
45
+ });
46
+ return {
47
+ hasHookConflict: false,
48
+ hasAwaitedHookCreation: false,
49
+ };
50
+ }
51
+ if (isWorldValidationFailure(err)) {
52
+ const fatal = new FatalError(`createHook failed World validation: ${err instanceof Error ? err.message : String(err)}`);
53
+ fatal.cause = err;
54
+ throw fatal;
55
+ }
56
+ throw err;
21
57
  }
22
- return headers;
23
58
  }
24
59
  /**
25
60
  * Handles a workflow suspension by processing all pending operations (hooks, steps, waits).
26
- * Uses an event-sourced architecture where entities (steps, hooks) are created atomically
27
- * with their corresponding events via events.create().
61
+ * Creates events for all operations but does NOT queue step messages — returns the pending
62
+ * steps so the caller can decide which to execute inline vs queue to background.
28
63
  *
29
64
  * Processing order:
30
65
  * 1. Hooks are processed first to prevent race conditions with webhook receivers
31
- * 2. Steps and waits are processed in parallel after hooks complete
66
+ * 2. Step events and wait events are created in parallel
32
67
  */
33
- export async function handleSuspension({ suspension, world, run, span, requestId, }) {
68
+ export async function handleSuspension({ suspension, world, run, span, requestId, eventLog, runReadyBarrier, replayRecoveryReporter, }) {
34
69
  const runId = run.runId;
35
- const workflowName = run.workflowName;
36
- const workflowStartedAt = run.startedAt ? +run.startedAt : Date.now();
70
+ // Turbo mode: hold every world write below until the backgrounded
71
+ // `run_started` has *settled*, so we never write a step/hook/wait event for a
72
+ // run that does not exist yet. A no-op outside turbo (barrier undefined) and
73
+ // on the pure inline hot path, which defers all steps and writes nothing.
74
+ // Awaiting the same (usually already-settled) promise more than once is cheap.
75
+ // A barrier rejection is swallowed for ordering only: if `run_started` truly
76
+ // failed the run does not exist, so the subsequent write surfaces the real
77
+ // error (run not found / gone) and the message redelivers.
78
+ const ensureRunReady = async () => {
79
+ if (runReadyBarrier) {
80
+ try {
81
+ await runReadyBarrier;
82
+ }
83
+ catch {
84
+ // intentional: ordering barrier only — see above.
85
+ }
86
+ }
87
+ };
88
+ /**
89
+ * Await every operation in a suspension phase before letting a failure
90
+ * escape, preferring a stale-snapshot (412) rejection when one occurred.
91
+ *
92
+ * `Promise.all` rejects as soon as one operation does and leaves its siblings
93
+ * in flight. That matters for a 412: the caller reacts by reloading the event
94
+ * log and restarting the replay, so a sibling create that lands after the
95
+ * rejection escaped commits an event whose correlation id came from the
96
+ * abandoned replay's seeded sequence — an event the fresh replay never
97
+ * produces — and it races the restart's reload while doing so. Settling first
98
+ * makes this phase's write set final before the caller acts on the failure.
99
+ * It mirrors the runtime's inline step claim, which settles the in-flight
100
+ * step executions before escalating a 412.
101
+ *
102
+ * A 412 is preferred over any other rejection in the same phase because it
103
+ * has a defined, cheap recovery (replay from a corrected log) while the
104
+ * others do not. A deterministic failure such as an attribute-validation
105
+ * `FatalError` recurs on the restart and fails the run then, at the cost of
106
+ * one extra replay.
107
+ */
108
+ const settlePhase = async (ops) => {
109
+ const reasons = (await Promise.allSettled(ops))
110
+ .filter((r) => r.status === 'rejected')
111
+ .map((r) => r.reason);
112
+ if (reasons.length === 0)
113
+ return;
114
+ throw reasons.find((r) => PreconditionFailedError.is(r)) ?? reasons[0];
115
+ };
116
+ // Every suspension write carries replay-recovery telemetry on the first one
117
+ // that commits after replay recovered. All suspension events are
118
+ // non-run_created events on this run's `runId`.
119
+ const reporter = replayRecoveryReporter ?? ReplayRecoveryReporter.inert();
120
+ const createEvent = (data, params) => reporter.withEventCreate(params, (p) => world.events.create(runId, data, p));
121
+ // Adds the optimistic-concurrency guard when the caller supplied a loaded
122
+ // event log; without one it creates directly (callers with no replay
123
+ // snapshot, e.g. tests). A stale (412) rejection propagates to the caller,
124
+ // which restarts the replay from a corrected log — it is not retried here,
125
+ // because the event's correlation id was minted by *this* replay's seeded
126
+ // sequence, so re-committing it against a corrected log would persist an
127
+ // event no correct replay produces.
128
+ let reportedEvents = 0;
129
+ const createGuarded = async (data, params) => {
130
+ if (!eventLog) {
131
+ return createEvent(data, params);
132
+ }
133
+ const log = eventLog;
134
+ const result = await createEvent(data, {
135
+ ...params,
136
+ ...preconditionSnapshotParams(log.events, log.cursor),
137
+ });
138
+ // Bump-and-report: the write landed above the slot it asked for, so these
139
+ // are the events it was decided without. Merging them here rather than at
140
+ // each call site means the rest of this phase's writes — which read the
141
+ // same array to build their own snapshot — ask for a slot above them, and
142
+ // the replay that resumes from this log sees them without a reload.
143
+ //
144
+ // A truncated report (`hasMore`) is dropped whole rather than merged, the
145
+ // same way the wait loop treats one. It covers a span of positions but
146
+ // carries only some of the events on them, so merging it would raise the
147
+ // log's highest position past a position whose event is missing. Every
148
+ // later write of this phase reads that maximum to say what it has seen, so
149
+ // each would claim a position it never saw and the World, which only
150
+ // reports the span a write skips, would never send it. Dropping the report
151
+ // costs one more round of the same events on the next write and keeps the
152
+ // log a prefix of the truth.
153
+ if (result.events?.length && result.hasMore !== true) {
154
+ const added = mergeReportedEvents(log.events, result.events);
155
+ reportedEvents += added;
156
+ if (added > 0) {
157
+ runtimeLogger.debug('Suspension write skipped occupied slots', {
158
+ workflowRunId: runId,
159
+ eventType: data.eventType,
160
+ eventId: result.event?.eventId,
161
+ reported: added,
162
+ });
163
+ }
164
+ }
165
+ else if (result.events?.length) {
166
+ runtimeLogger.debug('Dropped a truncated skipped-slot report', {
167
+ workflowRunId: runId,
168
+ eventType: data.eventType,
169
+ eventId: result.event?.eventId,
170
+ offered: result.events.length,
171
+ });
172
+ }
173
+ return result;
174
+ };
37
175
  // Separate queue items by type
38
176
  const stepItems = suspension.steps.filter((item) => item.type === 'step');
39
177
  const allHookItems = suspension.steps.filter((item) => item.type === 'hook');
40
178
  const waitItems = suspension.steps.filter((item) => item.type === 'wait');
41
- // Split hooks by what actions they need
179
+ const attributeItems = suspension.steps.filter((item) => item.type === 'attribute');
42
180
  const hooksNeedingCreation = allHookItems.filter((item) => !item.hasCreatedEvent);
43
- // Hooks needing disposal: any disposed hook (including those needing creation first)
44
- // Hooks are created before disposal in the processing order below
45
- const hooksNeedingDisposal = allHookItems.filter((item) => item.disposed);
181
+ // Group hook items that need work by token, preserving queue-insertion
182
+ // (workflow code) order within each token. Operations on one token must
183
+ // apply in code order: a dispose() of an earlier hook releases the token
184
+ // before a later same-token hook's creation is validated — otherwise the
185
+ // new hook records a spurious hook_conflict against the run's own
186
+ // disposed hook — while a hook created and disposed within the same
187
+ // suspension is still created before it is disposed. Different tokens
188
+ // have no claim interaction, so token groups are processed in parallel.
189
+ const hookItemsByToken = new Map();
190
+ for (const item of allHookItems) {
191
+ if (item.hasCreatedEvent && !item.disposed) {
192
+ continue; // already committed and still live — nothing to do
193
+ }
194
+ const group = hookItemsByToken.get(item.token);
195
+ if (group) {
196
+ group.push(item);
197
+ }
198
+ else {
199
+ hookItemsByToken.set(item.token, [item]);
200
+ }
201
+ }
46
202
  // Resolve encryption key for this run
47
203
  const rawKey = await world.getEncryptionKeyForRun?.(run);
48
204
  const encryptionKey = rawKey ? await importKey(rawKey) : undefined;
49
- // Build hook_created events (World will atomically create hook entities)
50
- const hookEvents = await Promise.all(hooksNeedingCreation.map(async (queueItem) => {
51
- const hookMetadata = typeof queueItem.metadata === 'undefined'
52
- ? undefined
53
- : (await dehydrateStepArguments(queueItem.metadata, runId, encryptionKey, suspension.globalThis));
54
- return {
55
- eventType: 'hook_created',
205
+ // Gate payload compression on the run's specVersion.
206
+ const compression = (run.specVersion ?? 0) >= SPEC_VERSION_SUPPORTS_COMPRESSION;
207
+ async function disposeHook(queueItem) {
208
+ const hookDisposedEvent = {
209
+ eventType: 'hook_disposed',
56
210
  specVersion: SPEC_VERSION_CURRENT,
57
211
  correlationId: queueItem.correlationId,
58
212
  eventData: {
59
213
  token: queueItem.token,
60
- metadata: hookMetadata,
61
- isWebhook: queueItem.isWebhook ?? false,
62
214
  },
63
215
  };
64
- }));
65
- // Process hooks first to prevent race conditions with webhook receivers
66
- // All hook creations run in parallel
67
- // Track any hook conflicts that occur - these will be handled by re-enqueueing the workflow
68
- let hasHookConflict = false;
69
- if (hookEvents.length > 0) {
70
- await Promise.all(hookEvents.map(async (hookEvent) => {
71
- try {
72
- const result = await world.events.create(runId, hookEvent, {
73
- requestId,
216
+ try {
217
+ await createGuarded(hookDisposedEvent, { requestId });
218
+ }
219
+ catch (err) {
220
+ if (EntityConflictError.is(err)) {
221
+ // Hook was already disposed by a concurrent invocation — safe to skip
222
+ runtimeLogger.info('Hook already disposed, skipping duplicate disposal', {
223
+ workflowRunId: runId,
224
+ correlationId: queueItem.correlationId,
225
+ message: err.message,
74
226
  });
75
- // Check if the world returned a hook_conflict event instead of hook_created
76
- // The hook_conflict event is stored in the event log and will be replayed
77
- // on the next workflow invocation, causing the hook's promise to reject
78
- // Note: hook events always create an event (legacy runs throw, not return undefined)
79
- if (result.event.eventType === 'hook_conflict') {
80
- hasHookConflict = true;
81
- }
82
227
  }
83
- catch (err) {
84
- if (EntityConflictError.is(err) || RunExpiredError.is(err)) {
85
- runtimeLogger.info('Workflow run already completed, skipping hook', {
86
- workflowRunId: runId,
87
- message: err.message,
228
+ else if (RunExpiredError.is(err)) {
229
+ runtimeLogger.info('Workflow run already completed, skipping hook disposal', {
230
+ workflowRunId: runId,
231
+ correlationId: queueItem.correlationId,
232
+ message: err.message,
233
+ });
234
+ }
235
+ else if (HookNotFoundError.is(err)) {
236
+ // Hook may have already been disposed or never created
237
+ runtimeLogger.info('Hook not found for disposal, continuing', {
238
+ workflowRunId: runId,
239
+ correlationId: queueItem.correlationId,
240
+ message: err.message,
241
+ });
242
+ }
243
+ else {
244
+ throw err;
245
+ }
246
+ }
247
+ }
248
+ // Process hooks first to prevent race conditions with webhook receivers.
249
+ // Track any hook conflicts that occur — these are returned to the caller
250
+ // so the V2 handler can re-invoke immediately.
251
+ let hasHookConflict = false;
252
+ let hasAwaitedHookCreation = false;
253
+ let hookCreationMs = 0;
254
+ if (hookItemsByToken.size > 0) {
255
+ const hookPhaseStart = Date.now();
256
+ await ensureRunReady();
257
+ await settlePhase([...hookItemsByToken.values()].map(async (items) => {
258
+ for (const queueItem of items) {
259
+ let creationConflicted = false;
260
+ if (!queueItem.hasCreatedEvent) {
261
+ const hookMetadata = typeof queueItem.metadata === 'undefined'
262
+ ? undefined
263
+ : (await dehydrateStepArguments(queueItem.metadata, runId, encryptionKey, suspension.globalThis, false, compression));
264
+ const hookEvent = {
265
+ eventType: 'hook_created',
266
+ specVersion: SPEC_VERSION_CURRENT,
267
+ correlationId: queueItem.correlationId,
268
+ eventData: {
269
+ token: queueItem.token,
270
+ tokenRetentionUntil: queueItem.tokenRetentionUntil,
271
+ metadata: hookMetadata,
272
+ isWebhook: queueItem.isWebhook ?? false,
273
+ ...(queueItem.isSystem && { isSystem: true }),
274
+ },
275
+ };
276
+ const result = await createHookEvent({
277
+ runId,
278
+ hookEvent,
279
+ queueItem,
280
+ requestId,
281
+ createEvent: createGuarded,
88
282
  });
283
+ hasHookConflict ||= result.hasHookConflict;
284
+ hasAwaitedHookCreation ||= result.hasAwaitedHookCreation;
285
+ creationConflicted = result.hasHookConflict;
89
286
  }
90
- else {
91
- throw err;
287
+ // Dispose after creation for hooks born and disposed within this
288
+ // batch. A hook whose creation conflicted was never created, so
289
+ // there is nothing to dispose.
290
+ if (queueItem.disposed && !creationConflicted) {
291
+ await disposeHook(queueItem);
92
292
  }
93
293
  }
94
294
  }));
295
+ hookCreationMs = Date.now() - hookPhaseStart;
95
296
  }
96
- // Process hook disposals - these release hook tokens for reuse by other workflows
97
- if (hooksNeedingDisposal.length > 0) {
98
- await Promise.all(hooksNeedingDisposal.map(async (queueItem) => {
99
- const hookDisposedEvent = {
100
- eventType: 'hook_disposed',
101
- specVersion: SPEC_VERSION_CURRENT,
102
- correlationId: queueItem.correlationId,
103
- };
297
+ // Process abort requests resume the hook with abort payload and write stream packet
298
+ const hooksNeedingAbort = allHookItems.filter((item) => item.abortRequested && !item.disposed);
299
+ if (hooksNeedingAbort.length > 0) {
300
+ await ensureRunReady();
301
+ await settlePhase(hooksNeedingAbort.map(async (queueItem) => {
104
302
  try {
105
- await world.events.create(runId, hookDisposedEvent, { requestId });
106
- }
107
- catch (err) {
108
- if (EntityConflictError.is(err)) {
109
- // Hook was already disposed by a concurrent invocation — safe to skip
110
- runtimeLogger.info('Hook already disposed, skipping duplicate disposal', {
111
- workflowRunId: runId,
112
- correlationId: queueItem.correlationId,
113
- message: err.message,
114
- });
303
+ // Dehydrate the abort payload for storage
304
+ const abortPayload = await dehydrateStepArguments({ aborted: true, reason: queueItem.abortReason }, runId, encryptionKey, suspension.globalThis, false, compression);
305
+ // Create hook_received event with abort payload
306
+ await createGuarded({
307
+ eventType: 'hook_received',
308
+ specVersion: SPEC_VERSION_CURRENT,
309
+ correlationId: queueItem.correlationId,
310
+ eventData: {
311
+ token: queueItem.token,
312
+ payload: abortPayload,
313
+ },
314
+ });
315
+ // Write stream cancellation packet for real-time step propagation.
316
+ // Reuse the same dehydrated payload as the hook event so the reason
317
+ // round-trips through `dehydrateStepArguments` / `hydrateStepArguments`
318
+ // (handles DOMException, custom errors, encryption, etc.) instead of
319
+ // bare JSON.stringify which loses type information and drops undefined.
320
+ // streamName is set on the queue item at controller construction time
321
+ // (see workflow/abort-controller.ts).
322
+ try {
323
+ const streamName = getAbortStreamIdFromToken(queueItem.token);
324
+ await world.streams.write(runId, streamName, abortPayload);
325
+ await world.streams.close(runId, streamName);
115
326
  }
116
- else if (RunExpiredError.is(err)) {
117
- runtimeLogger.info('Workflow run already completed, skipping hook disposal', {
327
+ catch {
328
+ // Best-effort stream write hook event provides the durable fallback
329
+ runtimeLogger.debug('Failed to write abort stream packet, hook event will provide fallback', {
118
330
  workflowRunId: runId,
119
331
  correlationId: queueItem.correlationId,
120
- message: err.message,
121
332
  });
122
333
  }
123
- else if (HookNotFoundError.is(err)) {
124
- // Hook may have already been disposed or never created
125
- runtimeLogger.info('Hook not found for disposal, continuing', {
334
+ }
335
+ catch (err) {
336
+ if (EntityConflictError.is(err) || RunExpiredError.is(err)) {
337
+ runtimeLogger.info('Workflow run already completed, skipping abort', {
126
338
  workflowRunId: runId,
127
339
  correlationId: queueItem.correlationId,
128
340
  message: err.message,
@@ -134,35 +346,92 @@ export async function handleSuspension({ suspension, world, run, span, requestId
134
346
  }
135
347
  }));
136
348
  }
137
- // Build a map of stepId -> step event for steps that need creation
349
+ // Create step events for steps that don't have them yet.
350
+ // Unlike V1, we do NOT queue step messages from here — the caller
351
+ // decides which steps to execute inline vs. queue to background.
352
+ // Wait events are also created in parallel below.
138
353
  const stepsNeedingCreation = new Set(stepItems
139
354
  .filter((queueItem) => !queueItem.hasCreatedEvent)
140
355
  .map((queueItem) => queueItem.correlationId));
141
- // Process steps and waits in parallel
142
- // Each step: create event (if needed) -> queue message
143
- // Each wait: create event (if needed)
356
+ // Correlation IDs for which THIS suspension call actually wrote the
357
+ // step_created event. Populated by the ops below after a successful
358
+ // events.create used by the caller to claim ownership and avoid
359
+ // racing with concurrent handlers on step execution.
360
+ const createdStepCorrelationIds = new Set();
361
+ // Serialization always runs through the one ordinary path below, so the
362
+ // durable bytes cannot depend on retention. What retention needs to know is
363
+ // whether that serialization *executed* workflow code (getters, proxy
364
+ // traps, custom serializers) — side effects a cold replay would not
365
+ // repeat, since a replay skips dehydration for already-recorded steps.
366
+ // The hardened serializer records exactly that into this sink (see
367
+ // ../serialization/hardened.ts); when any input in the batch records an
368
+ // execution, the caller demotes the session so the side effects land in a
369
+ // VM that is about to be discarded, exactly like the pre-retention
370
+ // runtime.
371
+ const guestCodeStats = { executions: [] };
372
+ // Lazy inline start: defer the step_created write for up to
373
+ // `getMaxInlineSteps()` steps the caller will run inline (in parallel). Each
374
+ // step is created on the fly by the lazy `step_started` executeStep sends
375
+ // (saving a round-trip per step). We never defer when a `hook.getConflict()`
376
+ // awaiter is present, because in that case the caller executes nothing inline
377
+ // (it re-invokes immediately to resolve the awaiter), so deferring would
378
+ // leave the steps uncreated and unqueued. We pick the first N uncreated steps
379
+ // — matching the caller's inline-candidate selection — and dehydrate their
380
+ // input here so executeStep can ship it as the step_started payload.
381
+ const lazyInlineCorrelationIds = new Set(hasAwaitedHookCreation === false
382
+ ? stepItems
383
+ .filter((item) => stepsNeedingCreation.has(item.correlationId))
384
+ .slice(0, getMaxInlineSteps())
385
+ .map((item) => item.correlationId)
386
+ : []);
387
+ // Collected by correlationId because the per-step ops below run concurrently
388
+ // and settle out of order. We rebuild the array in deterministic
389
+ // `lazyInlineCorrelationIds` order (the ordered slice above) after the ops
390
+ // settle, so the inline batch order is stable regardless of dehydration timing.
391
+ const lazyInlineByCorrelationId = new Map();
144
392
  const ops = [];
145
- // Steps: create event then queue message, all in parallel
393
+ // Steps: create step_created events (no queuing V2 returns pending steps to caller)
146
394
  for (const queueItem of stepItems) {
147
- ops.push((async () => {
148
- // Create step event if not already created
149
- if (stepsNeedingCreation.has(queueItem.correlationId)) {
395
+ if (stepsNeedingCreation.has(queueItem.correlationId)) {
396
+ ops.push((async () => {
397
+ // Per-step sink, merged below: the dehydrate wrapper emits span
398
+ // attributes from the sink it is handed, so sharing one across
399
+ // steps would re-emit (and misattribute) earlier steps' entries.
400
+ const stepGuestCode = { executions: [] };
150
401
  const dehydratedInput = await dehydrateStepArguments({
151
402
  args: queueItem.args,
152
403
  closureVars: queueItem.closureVars,
153
404
  thisVal: queueItem.thisVal,
154
- }, runId, encryptionKey, suspension.globalThis);
405
+ }, runId, encryptionKey, suspension.globalThis, false, compression, stepGuestCode);
406
+ guestCodeStats.executions.push(...stepGuestCode.executions);
407
+ // Deferred (lazy) inline step: skip the step_created write — the
408
+ // caller's inline executeStep will send a lazy step_started carrying
409
+ // this input, and the world creates the step (entity + synthetic
410
+ // step_created event) atomically. We do NOT add it to
411
+ // createdStepCorrelationIds; ownership is decided by that lazy
412
+ // step_started's atomic create-claim instead.
413
+ if (lazyInlineCorrelationIds.has(queueItem.correlationId)) {
414
+ lazyInlineByCorrelationId.set(queueItem.correlationId, {
415
+ correlationId: queueItem.correlationId,
416
+ stepName: queueItem.stepName,
417
+ dehydratedInput: dehydratedInput,
418
+ });
419
+ return;
420
+ }
155
421
  const stepEvent = {
156
422
  eventType: 'step_created',
157
423
  specVersion: SPEC_VERSION_CURRENT,
158
424
  correlationId: queueItem.correlationId,
159
425
  eventData: {
160
426
  stepName: queueItem.stepName,
427
+ workflowName: run.workflowName,
161
428
  input: dehydratedInput,
162
429
  },
163
430
  };
164
431
  try {
165
- await world.events.create(runId, stepEvent, { requestId });
432
+ await ensureRunReady();
433
+ await createGuarded(stepEvent, { requestId });
434
+ createdStepCorrelationIds.add(queueItem.correlationId);
166
435
  }
167
436
  catch (err) {
168
437
  if (EntityConflictError.is(err)) {
@@ -176,28 +445,10 @@ export async function handleSuspension({ suspension, world, run, span, requestId
176
445
  throw err;
177
446
  }
178
447
  }
179
- }
180
- // Queue step execution message
181
- // Serialize trace context once and include in both payload and headers
182
- // Payload: for manual context restoration in step handler
183
- // Headers: for automatic trace propagation by Vercel's infrastructure
184
- const traceCarrier = await serializeTraceCarrier();
185
- await queueMessage(world, `__wkf_step_${queueItem.stepName}`, {
186
- workflowName,
187
- workflowRunId: runId,
188
- workflowStartedAt,
189
- stepId: queueItem.correlationId,
190
- traceCarrier,
191
- requestedAt: new Date(),
192
- }, {
193
- idempotencyKey: queueItem.correlationId,
194
- headers: {
195
- ...extractTraceHeaders(traceCarrier),
196
- },
197
- });
198
- })());
448
+ })());
449
+ }
199
450
  }
200
- // Waits: create events in parallel (no queueing needed for waits)
451
+ // Create wait events (same as V1)
201
452
  for (const queueItem of waitItems) {
202
453
  if (!queueItem.hasCreatedEvent) {
203
454
  ops.push((async () => {
@@ -210,7 +461,8 @@ export async function handleSuspension({ suspension, world, run, span, requestId
210
461
  },
211
462
  };
212
463
  try {
213
- await world.events.create(runId, waitEvent, { requestId });
464
+ await ensureRunReady();
465
+ await createGuarded(waitEvent, { requestId });
214
466
  }
215
467
  catch (err) {
216
468
  if (EntityConflictError.is(err)) {
@@ -227,40 +479,134 @@ export async function handleSuspension({ suspension, world, run, span, requestId
227
479
  })());
228
480
  }
229
481
  }
230
- // Wait for all step and wait operations to complete
231
- waitUntil(Promise.all(ops).catch((opErr) => {
232
- const isAbortError = opErr?.name === 'AbortError' || opErr?.name === 'ResponseAborted';
233
- if (!isAbortError)
234
- throw opErr;
235
- }));
236
- await Promise.all(ops);
237
- // Calculate minimum timeout from waits
482
+ for (const queueItem of attributeItems) {
483
+ ops.push((async () => {
484
+ try {
485
+ await ensureRunReady();
486
+ // Guarded like every other suspension write: an attr_set is a
487
+ // replay-derived event with a correlation id from this replay's
488
+ // seeded sequence, so it must not land on a log the replay never
489
+ // saw. Rejecting it is cheap — a run with attribute events already
490
+ // forces an in-process replay, so the restart costs the replay it
491
+ // was going to do anyway.
492
+ await createGuarded({
493
+ eventType: 'attr_set',
494
+ specVersion: SPEC_VERSION_CURRENT,
495
+ correlationId: queueItem.correlationId,
496
+ eventData: {
497
+ changes: queueItem.changes,
498
+ writer: { type: 'workflow' },
499
+ ...(queueItem.allowReservedAttributes
500
+ ? { allowReservedAttributes: true }
501
+ : {}),
502
+ },
503
+ }, { requestId });
504
+ }
505
+ catch (err) {
506
+ if (EntityConflictError.is(err)) {
507
+ runtimeLogger.info('Workflow attribute event already exists, continuing', {
508
+ workflowRunId: runId,
509
+ correlationId: queueItem.correlationId,
510
+ message: err.message,
511
+ });
512
+ }
513
+ else if (isWorldValidationFailure(err)) {
514
+ // Deterministic validation rejection from the World — e.g. the
515
+ // cumulative per-run attribute cap, which only the World can
516
+ // check against the run's existing attributes. Redelivering the
517
+ // orchestrator message replays the workflow into the exact same
518
+ // write and the exact same rejection, so retrying can never
519
+ // succeed. Surface it as a FatalError so the caller fails the
520
+ // run with a clear error instead of wedging it in redelivery.
521
+ const fatal = new FatalError(`setAttributes failed World validation: ${err instanceof Error ? err.message : String(err)}`);
522
+ fatal.cause = err;
523
+ throw fatal;
524
+ }
525
+ else {
526
+ throw err;
527
+ }
528
+ }
529
+ })());
530
+ }
531
+ // Await the step_created / wait_created event creates before returning.
532
+ // The caller (workflowEntrypoint) only enqueues the step-dispatch queue
533
+ // messages AFTER handleSuspension resolves, and the queue handler acks
534
+ // the orchestrator message only after the caller resolves. So the step_created
535
+ // events must be durable here, and the dispatch sends must complete in the caller,
536
+ // all before ack. If the process crashes before this resolves, the orchestrator
537
+ // message is not acked and VQS redelivers, re-creates the (idempotent)
538
+ // step_created and re-dispatches, and recovers the run instead of orphaning it.
539
+ await settlePhase(ops);
540
+ // The step-input dehydrations above have settled, so the sink is final.
541
+ const retainedStepInputsSafe = guestCodeStats.executions.length === 0;
542
+ if (!retainedStepInputsSafe) {
543
+ runtimeLogger.debug('Serializing step inputs executed workflow code; falling back to replay instead of retaining the VM', {
544
+ workflowRunId: runId,
545
+ executions: guestCodeStats.executions
546
+ .slice(0, 5)
547
+ .map((e) => (e.detail ? `${e.kind}(${e.detail})` : e.kind)),
548
+ });
549
+ }
550
+ // Rebuild the inline batch in deterministic order. `lazyInlineCorrelationIds`
551
+ // is a Set seeded from the ordered first-N slice, so iterating it preserves
552
+ // stepItems order; every id in it was set by the lazy branch above.
553
+ const lazyInlineSteps = [];
554
+ for (const correlationId of lazyInlineCorrelationIds) {
555
+ const lazyStep = lazyInlineByCorrelationId.get(correlationId);
556
+ if (lazyStep)
557
+ lazyInlineSteps.push(lazyStep);
558
+ }
559
+ // Find the soonest pending wait (minimum timeout)
238
560
  const now = Date.now();
239
- const minTimeoutSeconds = waitItems.reduce((min, queueItem) => {
561
+ let soonestWait;
562
+ for (const queueItem of waitItems) {
240
563
  const resumeAtMs = queueItem.resumeAt.getTime();
241
564
  const delayMs = Math.max(1000, resumeAtMs - now);
242
565
  const timeoutSeconds = Math.ceil(delayMs / 1000);
243
- if (min === null)
244
- return timeoutSeconds;
245
- return Math.min(min, timeoutSeconds);
246
- }, null);
566
+ if (!soonestWait || timeoutSeconds < soonestWait.seconds) {
567
+ soonestWait = {
568
+ seconds: timeoutSeconds,
569
+ correlationId: queueItem.correlationId,
570
+ };
571
+ }
572
+ }
247
573
  span?.setAttributes({
248
574
  ...Attribute.WorkflowRunStatus('workflow_suspended'),
249
575
  ...Attribute.WorkflowStepsCreated(stepItems.length),
250
576
  ...Attribute.WorkflowHooksCreated(hooksNeedingCreation.length),
251
577
  ...Attribute.WorkflowWaitsCreated(waitItems.length),
252
578
  });
253
- // If any hook conflicts occurred, re-enqueue the workflow immediately
254
- // On the next iteration, the hook consumer will see the hook_conflict event
255
- // and reject the promise with a WorkflowRuntimeError
256
- // We do this after processing all other operations (steps, waits) to ensure
257
- // they are recorded in the event log before the re-execution
258
- if (hasHookConflict) {
259
- return { timeoutSeconds: 0 };
260
- }
261
- if (minTimeoutSeconds !== null) {
262
- return { timeoutSeconds: minTimeoutSeconds };
579
+ return {
580
+ pendingSteps: stepItems,
581
+ createdStepCorrelationIds,
582
+ lazyInlineSteps,
583
+ // On hook conflict the caller re-invokes immediately and never reads
584
+ // the wait timeout, so don't report one.
585
+ waitTimeout: hasHookConflict ? undefined : soonestWait,
586
+ hasHookConflict,
587
+ hasAwaitedHookCreation,
588
+ hasAttributeEvents: attributeItems.length > 0,
589
+ hasHookEvents: hooksNeedingCreation.length > 0,
590
+ hookCreationMs,
591
+ retainedStepInputsSafe,
592
+ reportedEventCount: reportedEvents,
593
+ };
594
+ }
595
+ /**
596
+ * Whether an `events.create` rejection is deterministic World validation
597
+ * rather than a transient/storage error. Local Worlds
598
+ * (world-local, world-postgres) throw `AttributeValidationError` directly;
599
+ * remote Worlds surface the equivalent server-side rejection as a
600
+ * `WorkflowWorldError` with HTTP status 400. The name check covers
601
+ * `AttributeValidationError` instances from a different copy of
602
+ * `@workflow/world` than the one this package resolved.
603
+ */
604
+ function isWorldValidationFailure(err) {
605
+ if (err instanceof AttributeValidationError)
606
+ return true;
607
+ if (err instanceof Error && err.name === 'AttributeValidationError') {
608
+ return true;
263
609
  }
264
- return {};
610
+ return WorkflowWorldError.is(err) && err.status === 400;
265
611
  }
266
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3VzcGVuc2lvbi1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bnRpbWUvc3VzcGVuc2lvbi1oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUM5QyxPQUFPLEVBQ0wsbUJBQW1CLEVBQ25CLGlCQUFpQixFQUNqQixlQUFlLEdBQ2hCLE1BQU0sa0JBQWtCLENBQUM7QUFDMUIsT0FBTyxFQUdMLG9CQUFvQixHQUdyQixNQUFNLGlCQUFpQixDQUFDO0FBQ3pCLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQU83QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzdDLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzdELE9BQU8sS0FBSyxTQUFTLE1BQU0sc0NBQXNDLENBQUM7QUFDbEUsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDeEQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUU1Qzs7O0dBR0c7QUFDSCxTQUFTLG1CQUFtQixDQUMxQixZQUFvQztJQUVwQyxNQUFNLE9BQU8sR0FBMkIsRUFBRSxDQUFDO0lBQzNDLElBQUksWUFBWSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQzdCLE9BQU8sQ0FBQyxXQUFXLEdBQUcsWUFBWSxDQUFDLFdBQVcsQ0FBQztJQUNqRCxDQUFDO0lBQ0QsSUFBSSxZQUFZLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDNUIsT0FBTyxDQUFDLFVBQVUsR0FBRyxZQUFZLENBQUMsVUFBVSxDQUFDO0lBQy9DLENBQUM7SUFDRCxPQUFPLE9BQU8sQ0FBQztBQUNqQixDQUFDO0FBY0Q7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLGdCQUFnQixDQUFDLEVBQ3JDLFVB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aW1wb3J0IHsgd2FpdFVudGlsIH0gZnJvbSAnQHZlcmNlbC9mdW5jdGlvbnMnO1xuaW1wb3J0IHtcbiAgRW50aXR5Q29uZmxpY3RFcnJvcixcbiAgSG9va05vdEZvdW5kRXJyb3IsXG4gIFJ1bkV4cGlyZWRFcnJvcixcbn0gZnJvbSAnQHdvcmtmbG93L2Vycm9ycyc7XG5pbXBvcnQge1xuICB0eXBlIENyZWF0ZUV2ZW50UmVxdWVzdCxcbiAgdHlwZSBTZXJpYWxpemVkRGF0YSxcbiAgU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gIHR5cGUgV29ya2Zsb3dSdW4sXG4gIHR5cGUgV29ybGQsXG59IGZyb20gJ0B3b3JrZmxvdy93b3JsZCc7XG5pbXBvcnQgeyBpbXBvcnRLZXkgfSBmcm9tICcuLi9lbmNyeXB0aW9uLmpzJztcbmltcG9ydCB0eXBlIHtcbiAgSG9va0ludm9jYXRpb25RdWV1ZUl0ZW0sXG4gIFN0ZXBJbnZvY2F0aW9uUXVldWVJdGVtLFxuICBXYWl0SW52b2NhdGlvblF1ZXVlSXRlbSxcbiAgV29ya2Zsb3dTdXNwZW5zaW9uLFxufSBmcm9tICcuLi9nbG9iYWwuanMnO1xuaW1wb3J0IHsgcnVudGltZUxvZ2dlciB9IGZyb20gJy4uL2xvZ2dlci5qcyc7XG5pbXBvcnQgeyBkZWh5ZHJhdGVTdGVwQXJndW1lbnRzIH0gZnJvbSAnLi4vc2VyaWFsaXphdGlvbi5qcyc7XG5pbXBvcnQgKiBhcyBBdHRyaWJ1dGUgZnJvbSAnLi4vdGVsZW1ldHJ5L3NlbWFudGljLWNvbnZlbnRpb25zLmpzJztcbmltcG9ydCB7IHNlcmlhbGl6ZVRyYWNlQ2FycmllciB9IGZyb20gJy4uL3RlbGVtZXRyeS5qcyc7XG5pbXBvcnQgeyBxdWV1ZU1lc3NhZ2UgfSBmcm9tICcuL2hlbHBlcnMuanMnO1xuXG4vKipcbiAqIEV4dHJhY3RzIFczQyB0cmFjZSBjb250ZXh0IGhlYWRlcnMgZnJvbSBhIHRyYWNlIGNhcnJpZXIgZm9yIEhUVFAgcHJvcGFnYXRpb24uXG4gKiBSZXR1cm5zIGFuIG9iamVjdCB3aXRoIGB0cmFjZXBhcmVudGAgYW5kIG9wdGlvbmFsbHkgYHRyYWNlc3RhdGVgIGhlYWRlcnMuXG4gKi9cbmZ1bmN0aW9uIGV4dHJhY3RUcmFjZUhlYWRlcnMoXG4gIHRyYWNlQ2FycmllcjogUmVjb3JkPHN0cmluZywgc3RyaW5nPlxuKTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB7XG4gIGNvbnN0IGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgaWYgKHRyYWNlQ2Fycmllci50cmFjZXBhcmVudCkge1xuICAgIGhlYWRlcnMudHJhY2VwYXJlbnQgPSB0cmFjZUNhcnJpZXIudHJhY2VwYXJlbnQ7XG4gIH1cbiAgaWYgKHRyYWNlQ2Fycmllci50cmFjZXN0YXRlKSB7XG4gICAgaGVhZGVycy50cmFjZXN0YXRlID0gdHJhY2VDYXJyaWVyLnRyYWNlc3RhdGU7XG4gIH1cbiAgcmV0dXJuIGhlYWRlcnM7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3VzcGVuc2lvbkhhbmRsZXJQYXJhbXMge1xuICBzdXNwZW5zaW9uOiBXb3JrZmxvd1N1c3BlbnNpb247XG4gIHdvcmxkOiBXb3JsZDtcbiAgcnVuOiBXb3JrZmxvd1J1bjtcbiAgc3Bhbj86IFNwYW47XG4gIHJlcXVlc3RJZD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTdXNwZW5zaW9uSGFuZGxlclJlc3VsdCB7XG4gIHRpbWVvdXRTZWNvbmRzPzogbnVtYmVyO1xufVxuXG4vKipcbiAqIEhhbmRsZXMgYSB3b3JrZmxvdyBzdXNwZW5zaW9uIGJ5IHByb2Nlc3NpbmcgYWxsIHBlbmRpbmcgb3BlcmF0aW9ucyAoaG9va3MsIHN0ZXBzLCB3YWl0cykuXG4gKiBVc2VzIGFuIGV2ZW50LXNvdXJjZWQgYXJjaGl0ZWN0dXJlIHdoZXJlIGVudGl0aWVzIChzdGVwcywgaG9va3MpIGFyZSBjcmVhdGVkIGF0b21pY2FsbHlcbiAqIHdpdGggdGhlaXIgY29ycmVzcG9uZGluZyBldmVudHMgdmlhIGV2ZW50cy5jcmVhdGUoKS5cbiAqXG4gKiBQcm9jZXNzaW5nIG9yZGVyOlxuICogMS4gSG9va3MgYXJlIHByb2Nlc3NlZCBmaXJzdCB0byBwcmV2ZW50IHJhY2UgY29uZGl0aW9ucyB3aXRoIHdlYmhvb2sgcmVjZWl2ZXJzXG4gKiAyLiBTdGVwcyBhbmQgd2FpdHMgYXJlIHByb2Nlc3NlZCBpbiBwYXJhbGxlbCBhZnRlciBob29rcyBjb21wbGV0ZVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlU3VzcGVuc2lvbih7XG4gIHN1c3BlbnNpb24sXG4gIHdvcmxkLFxuICBydW4sXG4gIHNwYW4sXG4gIHJlcXVlc3RJZCxcbn06IFN1c3BlbnNpb25IYW5kbGVyUGFyYW1zKTogUHJvbWlzZTxTdXNwZW5zaW9uSGFuZGxlclJlc3VsdD4ge1xuICBjb25zdCBydW5JZCA9IHJ1bi5ydW5JZDtcbiAgY29uc3Qgd29ya2Zsb3dOYW1lID0gcnVuLndvcmtmbG93TmFtZTtcbiAgY29uc3Qgd29ya2Zsb3dTdGFydGVkQXQgPSBydW4uc3RhcnRlZEF0ID8gK3J1bi5zdGFydGVkQXQgOiBEYXRlLm5vdygpO1xuICAvLyBTZXBhcmF0ZSBxdWV1ZSBpdGVtcyBieSB0eXBlXG4gIGNvbnN0IHN0ZXBJdGVtcyA9IHN1c3BlbnNpb24uc3RlcHMuZmlsdGVyKFxuICAgIChpdGVtKTogaXRlbSBpcyBTdGVwSW52b2NhdGlvblF1ZXVlSXRlbSA9PiBpdGVtLnR5cGUgPT09ICdzdGVwJ1xuICApO1xuICBjb25zdCBhbGxIb29rSXRlbXMgPSBzdXNwZW5zaW9uLnN0ZXBzLmZpbHRlcihcbiAgICAoaXRlbSk6IGl0ZW0gaXMgSG9va0ludm9jYXRpb25RdWV1ZUl0ZW0gPT4gaXRlbS50eXBlID09PSAnaG9vaydcbiAgKTtcbiAgY29uc3Qgd2FpdEl0ZW1zID0gc3VzcGVuc2lvbi5zdGVwcy5maWx0ZXIoXG4gICAgKGl0ZW0pOiBpdGVtIGlzIFdhaXRJbnZvY2F0aW9uUXVldWVJdGVtID0+IGl0ZW0udHlwZSA9PT0gJ3dhaXQnXG4gICk7XG5cbiAgLy8gU3BsaXQgaG9va3MgYnkgd2hhdCBhY3Rpb25zIHRoZXkgbmVlZFxuICBjb25zdCBob29rc05lZWRpbmdDcmVhdGlvbiA9IGFsbEhvb2tJdGVtcy5maWx0ZXIoXG4gICAgKGl0ZW0pID0+ICFpdGVtLmhhc0NyZWF0ZWRFdmVudFxuICApO1xuICAvLyBIb29rcyBuZWVkaW5nIGRpc3Bvc2FsOiBhbnkgZGlzcG9zZWQgaG9vayAoaW5jbHVkaW5nIHRob3NlIG5lZWRpbmcgY3JlYXRpb24gZmlyc3QpXG4gIC8vIEhvb2tzIGFyZSBjcmVhdGVkIGJlZm9yZSBkaXNwb3NhbCBpbiB0aGUgcHJvY2Vzc2luZyBvcmRlciBiZWxvd1xuICBjb25zdCBob29rc05lZWRpbmdEaXNwb3NhbCA9IGFsbEhvb2tJdGVtcy5maWx0ZXIoKGl0ZW0pID0+IGl0ZW0uZGlzcG9zZWQpO1xuXG4gIC8vIFJlc29sdmUgZW5jcnlwdGlvbiBrZXkgZm9yIHRoaXMgcnVuXG4gIGNvbnN0IHJhd0tleSA9IGF3YWl0IHdvcmxkLmdldEVuY3J5cHRpb25LZXlGb3JSdW4/LihydW4pO1xuICBjb25zdCBlbmNyeXB0aW9uS2V5ID0gcmF3S2V5ID8gYXdhaXQgaW1wb3J0S2V5KHJhd0tleSkgOiB1bmRlZmluZWQ7XG5cbiAgLy8gQnVpbGQgaG9va19jcmVhdGVkIGV2ZW50cyAoV29ybGQgd2lsbCBhdG9taWNhbGx5IGNyZWF0ZSBob29rIGVudGl0aWVzKVxuICBjb25zdCBob29rRXZlbnRzOiBDcmVhdGVFdmVudFJlcXVlc3RbXSA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgIGhvb2tzTmVlZGluZ0NyZWF0aW9uLm1hcChhc3luYyAocXVldWVJdGVtKSA9PiB7XG4gICAgICBjb25zdCBob29rTWV0YWRhdGE6IFNlcmlhbGl6ZWREYXRhIHwgdW5kZWZpbmVkID1cbiAgICAgICAgdHlwZW9mIHF1ZXVlSXRlbS5tZXRhZGF0YSA9PT0gJ3VuZGVmaW5lZCdcbiAgICAgICAgICA/IHVuZGVmaW5lZFxuICAgICAgICAgIDogKChhd2FpdCBkZWh5ZHJhdGVTdGVwQXJndW1lbnRzKFxuICAgICAgICAgICAgICBxdWV1ZUl0ZW0ubWV0YWRhdGEsXG4gICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICBlbmNyeXB0aW9uS2V5LFxuICAgICAgICAgICAgICBzdXNwZW5zaW9uLmdsb2JhbFRoaXNcbiAgICAgICAgICAgICkpIGFzIFNlcmlhbGl6ZWREYXRhKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGV2ZW50VHlwZTogJ2hvb2tfY3JlYXRlZCcgYXMgY29uc3QsXG4gICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgIHRva2VuOiBxdWV1ZUl0ZW0udG9rZW4sXG4gICAgICAgICAgbWV0YWRhdGE6IGhvb2tNZXRhZGF0YSxcbiAgICAgICAgICBpc1dlYmhvb2s6IHF1ZXVlSXRlbS5pc1dlYmhvb2sgPz8gZmFsc2UsXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH0pXG4gICk7XG5cbiAgLy8gUHJvY2VzcyBob29rcyBmaXJzdCB0byBwcmV2ZW50IHJhY2UgY29uZGl0aW9ucyB3aXRoIHdlYmhvb2sgcmVjZWl2ZXJzXG4gIC8vIEFsbCBob29rIGNyZWF0aW9ucyBydW4gaW4gcGFyYWxsZWxcbiAgLy8gVHJhY2sgYW55IGhvb2sgY29uZmxpY3RzIHRoYXQgb2NjdXIgLSB0aGVzZSB3aWxsIGJlIGhhbmRsZWQgYnkgcmUtZW5xdWV1ZWluZyB0aGUgd29ya2Zsb3dcbiAgbGV0IGhhc0hvb2tDb25mbGljdCA9IGZhbHNlO1xuXG4gIGlmIChob29rRXZlbnRzLmxlbmd0aCA+IDApIHtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIGhvb2tFdmVudHMubWFwKGFzeW5jIChob29rRXZlbnQpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKHJ1bklkLCBob29rRXZlbnQsIHtcbiAgICAgICAgICAgIHJlcXVlc3RJZCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICAvLyBDaGVjayBpZiB0aGUgd29ybGQgcmV0dXJuZWQgYSBob29rX2NvbmZsaWN0IGV2ZW50IGluc3RlYWQgb2YgaG9va19jcmVhdGVkXG4gICAgICAgICAgLy8gVGhlIGhvb2tfY29uZmxpY3QgZXZlbnQgaXMgc3RvcmVkIGluIHRoZSBldmVudCBsb2cgYW5kIHdpbGwgYmUgcmVwbGF5ZWRcbiAgICAgICAgICAvLyBvbiB0aGUgbmV4dCB3b3JrZmxvdyBpbnZvY2F0aW9uLCBjYXVzaW5nIHRoZSBob29rJ3MgcHJvbWlzZSB0byByZWplY3RcbiAgICAgICAgICAvLyBOb3RlOiBob29rIGV2ZW50cyBhbHdheXMgY3JlYXRlIGFuIGV2ZW50IChsZWdhY3kgcnVucyB0aHJvdywgbm90IHJldHVybiB1bmRlZmluZWQpXG4gICAgICAgICAgaWYgKHJlc3VsdC5ldmVudCEuZXZlbnRUeXBlID09PSAnaG9va19jb25mbGljdCcpIHtcbiAgICAgICAgICAgIGhhc0hvb2tDb25mbGljdCA9IHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpIHx8IFJ1bkV4cGlyZWRFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICdXb3JrZmxvdyBydW4gYWxyZWFkeSBjb21wbGV0ZWQsIHNraXBwaW5nIGhvb2snLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIC8vIFByb2Nlc3MgaG9vayBkaXNwb3NhbHMgLSB0aGVzZSByZWxlYXNlIGhvb2sgdG9rZW5zIGZvciByZXVzZSBieSBvdGhlciB3b3JrZmxvd3NcbiAgaWYgKGhvb2tzTmVlZGluZ0Rpc3Bvc2FsLmxlbmd0aCA+IDApIHtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIGhvb2tzTmVlZGluZ0Rpc3Bvc2FsLm1hcChhc3luYyAocXVldWVJdGVtKSA9PiB7XG4gICAgICAgIGNvbnN0IGhvb2tEaXNwb3NlZEV2ZW50OiBDcmVhdGVFdmVudFJlcXVlc3QgPSB7XG4gICAgICAgICAgZXZlbnRUeXBlOiAnaG9va19kaXNwb3NlZCcgYXMgY29uc3QsXG4gICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICB9O1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUocnVuSWQsIGhvb2tEaXNwb3NlZEV2ZW50LCB7IHJlcXVlc3RJZCB9KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgLy8gSG9vayB3YXMgYWxyZWFkeSBkaXNwb3NlZCBieSBhIGNvbmN1cnJlbnQgaW52b2NhdGlvbiDigJQgc2FmZSB0byBza2lwXG4gICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICdIb29rIGFscmVhZHkgZGlzcG9zZWQsIHNraXBwaW5nIGR1cGxpY2F0ZSBkaXNwb3NhbCcsXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKFJ1bkV4cGlyZWRFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICdXb3JrZmxvdyBydW4gYWxyZWFkeSBjb21wbGV0ZWQsIHNraXBwaW5nIGhvb2sgZGlzcG9zYWwnLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIGlmIChIb29rTm90Rm91bmRFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAvLyBIb29rIG1heSBoYXZlIGFscmVhZHkgYmVlbiBkaXNwb3NlZCBvciBuZXZlciBjcmVhdGVkXG4gICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ0hvb2sgbm90IGZvdW5kIGZvciBkaXNwb3NhbCwgY29udGludWluZycsIHtcbiAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvLyBCdWlsZCBhIG1hcCBvZiBzdGVwSWQgLT4gc3RlcCBldmVudCBmb3Igc3RlcHMgdGhhdCBuZWVkIGNyZWF0aW9uXG4gIGNvbnN0IHN0ZXBzTmVlZGluZ0NyZWF0aW9uID0gbmV3IFNldChcbiAgICBzdGVwSXRlbXNcbiAgICAgIC5maWx0ZXIoKHF1ZXVlSXRlbSkgPT4gIXF1ZXVlSXRlbS5oYXNDcmVhdGVkRXZlbnQpXG4gICAgICAubWFwKChxdWV1ZUl0ZW0pID0+IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKVxuICApO1xuXG4gIC8vIFByb2Nlc3Mgc3RlcHMgYW5kIHdhaXRzIGluIHBhcmFsbGVsXG4gIC8vIEVhY2ggc3RlcDogY3JlYXRlIGV2ZW50IChpZiBuZWVkZWQpIC0+IHF1ZXVlIG1lc3NhZ2VcbiAgLy8gRWFjaCB3YWl0OiBjcmVhdGUgZXZlbnQgKGlmIG5lZWRlZClcbiAgY29uc3Qgb3BzOiBQcm9taXNlPHZvaWQ+W10gPSBbXTtcblxuICAvLyBTdGVwczogY3JlYXRlIGV2ZW50IHRoZW4gcXVldWUgbWVzc2FnZSwgYWxsIGluIHBhcmFsbGVsXG4gIGZvciAoY29uc3QgcXVldWVJdGVtIG9mIHN0ZXBJdGVtcykge1xuICAgIG9wcy5wdXNoKFxuICAgICAgKGFzeW5jICgpID0+IHtcbiAgICAgICAgLy8gQ3JlYXRlIHN0ZXAgZXZlbnQgaWYgbm90IGFscmVhZHkgY3JlYXRlZFxuICAgICAgICBpZiAoc3RlcHNOZWVkaW5nQ3JlYXRpb24uaGFzKHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKSkge1xuICAgICAgICAgIGNvbnN0IGRlaHlkcmF0ZWRJbnB1dCA9IGF3YWl0IGRlaHlkcmF0ZVN0ZXBBcmd1bWVudHMoXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGFyZ3M6IHF1ZXVlSXRlbS5hcmdzLFxuICAgICAgICAgICAgICBjbG9zdXJlVmFyczogcXVldWVJdGVtLmNsb3N1cmVWYXJzLFxuICAgICAgICAgICAgICB0aGlzVmFsOiBxdWV1ZUl0ZW0udGhpc1ZhbCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgIGVuY3J5cHRpb25LZXksXG4gICAgICAgICAgICBzdXNwZW5zaW9uLmdsb2JhbFRoaXNcbiAgICAgICAgICApO1xuICAgICAgICAgIGNvbnN0IHN0ZXBFdmVudDogQ3JlYXRlRXZlbnRSZXF1ZXN0ID0ge1xuICAgICAgICAgICAgZXZlbnRUeXBlOiAnc3RlcF9jcmVhdGVkJyBhcyBjb25zdCxcbiAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgIHN0ZXBOYW1lOiBxdWV1ZUl0ZW0uc3RlcE5hbWUsXG4gICAgICAgICAgICAgIGlucHV0OiBkZWh5ZHJhdGVkSW5wdXQgYXMgU2VyaWFsaXplZERhdGEsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH07XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUocnVuSWQsIHN0ZXBFdmVudCwgeyByZXF1ZXN0SWQgfSk7XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbygnU3RlcCBhbHJlYWR5IGV4aXN0cywgY29udGludWluZycsIHtcbiAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gUXVldWUgc3RlcCBleGVjdXRpb24gbWVzc2FnZVxuICAgICAgICAvLyBTZXJpYWxpemUgdHJhY2UgY29udGV4dCBvbmNlIGFuZCBpbmNsdWRlIGluIGJvdGggcGF5bG9hZCBhbmQgaGVhZGVyc1xuICAgICAgICAvLyBQYXlsb2FkOiBmb3IgbWFudWFsIGNvbnRleHQgcmVzdG9yYXRpb24gaW4gc3RlcCBoYW5kbGVyXG4gICAgICAgIC8vIEhlYWRlcnM6IGZvciBhdXRvbWF0aWMgdHJhY2UgcHJvcGFnYXRpb24gYnkgVmVyY2VsJ3MgaW5mcmFzdHJ1Y3R1cmVcbiAgICAgICAgY29uc3QgdHJhY2VDYXJyaWVyID0gYXdhaXQgc2VyaWFsaXplVHJhY2VDYXJyaWVyKCk7XG4gICAgICAgIGF3YWl0IHF1ZXVlTWVzc2FnZShcbiAgICAgICAgICB3b3JsZCxcbiAgICAgICAgICBgX193a2Zfc3RlcF8ke3F1ZXVlSXRlbS5zdGVwTmFtZX1gLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHdvcmtmbG93TmFtZSxcbiAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgd29ya2Zsb3dTdGFydGVkQXQsXG4gICAgICAgICAgICBzdGVwSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgdHJhY2VDYXJyaWVyLFxuICAgICAgICAgICAgcmVxdWVzdGVkQXQ6IG5ldyBEYXRlKCksXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBpZGVtcG90ZW5jeUtleTogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgICAgIC4uLmV4dHJhY3RUcmFjZUhlYWRlcnModHJhY2VDYXJyaWVyKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgfSkoKVxuICAgICk7XG4gIH1cblxuICAvLyBXYWl0czogY3JlYXRlIGV2ZW50cyBpbiBwYXJhbGxlbCAobm8gcXVldWVpbmcgbmVlZGVkIGZvciB3YWl0cylcbiAgZm9yIChjb25zdCBxdWV1ZUl0ZW0gb2Ygd2FpdEl0ZW1zKSB7XG4gICAgaWYgKCFxdWV1ZUl0ZW0uaGFzQ3JlYXRlZEV2ZW50KSB7XG4gICAgICBvcHMucHVzaChcbiAgICAgICAgKGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCB3YWl0RXZlbnQ6IENyZWF0ZUV2ZW50UmVxdWVzdCA9IHtcbiAgICAgICAgICAgIGV2ZW50VHlwZTogJ3dhaXRfY3JlYXRlZCcgYXMgY29uc3QsXG4gICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICByZXN1bWVBdDogcXVldWVJdGVtLnJlc3VtZUF0LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9O1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKHJ1bklkLCB3YWl0RXZlbnQsIHsgcmVxdWVzdElkIH0pO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ1dhaXQgYWxyZWFkeSBleGlzdHMsIGNvbnRpbnVpbmcnLCB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSkoKVxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvLyBXYWl0IGZvciBhbGwgc3RlcCBhbmQgd2FpdCBvcGVyYXRpb25zIHRvIGNvbXBsZXRlXG4gIHdhaXRVbnRpbChcbiAgICBQcm9taXNlLmFsbChvcHMpLmNhdGNoKChvcEVycikgPT4ge1xuICAgICAgY29uc3QgaXNBYm9ydEVycm9yID1cbiAgICAgICAgb3BFcnI/Lm5hbWUgPT09ICdBYm9ydEVycm9yJyB8fCBvcEVycj8ubmFtZSA9PT0gJ1Jlc3BvbnNlQWJvcnRlZCc7XG4gICAgICBpZiAoIWlzQWJvcnRFcnJvcikgdGhyb3cgb3BFcnI7XG4gICAgfSlcbiAgKTtcbiAgYXdhaXQgUHJvbWlzZS5hbGwob3BzKTtcblxuICAvLyBDYWxjdWxhdGUgbWluaW11bSB0aW1lb3V0IGZyb20gd2FpdHNcbiAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgY29uc3QgbWluVGltZW91dFNlY29uZHMgPSB3YWl0SXRlbXMucmVkdWNlPG51bWJlciB8IG51bGw+KFxuICAgIChtaW4sIHF1ZXVlSXRlbSkgPT4ge1xuICAgICAgY29uc3QgcmVzdW1lQXRNcyA9IHF1ZXVlSXRlbS5yZXN1bWVBdC5nZXRUaW1lKCk7XG4gICAgICBjb25zdCBkZWxheU1zID0gTWF0aC5tYXgoMTAwMCwgcmVzdW1lQXRNcyAtIG5vdyk7XG4gICAgICBjb25zdCB0aW1lb3V0U2Vjb25kcyA9IE1hdGguY2VpbChkZWxheU1zIC8gMTAwMCk7XG4gICAgICBpZiAobWluID09PSBudWxsKSByZXR1cm4gdGltZW91dFNlY29uZHM7XG4gICAgICByZXR1cm4gTWF0aC5taW4obWluLCB0aW1lb3V0U2Vjb25kcyk7XG4gICAgfSxcbiAgICBudWxsXG4gICk7XG5cbiAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93UnVuU3RhdHVzKCd3b3JrZmxvd19zdXNwZW5kZWQnKSxcbiAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dTdGVwc0NyZWF0ZWQoc3RlcEl0ZW1zLmxlbmd0aCksXG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93SG9va3NDcmVhdGVkKGhvb2tzTmVlZGluZ0NyZWF0aW9uLmxlbmd0aCksXG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93V2FpdHNDcmVhdGVkKHdhaXRJdGVtcy5sZW5ndGgpLFxuICB9KTtcblxuICAvLyBJZiBhbnkgaG9vayBjb25mbGljdHMgb2NjdXJyZWQsIHJlLWVucXVldWUgdGhlIHdvcmtmbG93IGltbWVkaWF0ZWx5XG4gIC8vIE9uIHRoZSBuZXh0IGl0ZXJhdGlvbiwgdGhlIGhvb2sgY29uc3VtZXIgd2lsbCBzZWUgdGhlIGhvb2tfY29uZmxpY3QgZXZlbnRcbiAgLy8gYW5kIHJlamVjdCB0aGUgcHJvbWlzZSB3aXRoIGEgV29ya2Zsb3dSdW50aW1lRXJyb3JcbiAgLy8gV2UgZG8gdGhpcyBhZnRlciBwcm9jZXNzaW5nIGFsbCBvdGhlciBvcGVyYXRpb25zIChzdGVwcywgd2FpdHMpIHRvIGVuc3VyZVxuICAvLyB0aGV5IGFyZSByZWNvcmRlZCBpbiB0aGUgZXZlbnQgbG9nIGJlZm9yZSB0aGUgcmUtZXhlY3V0aW9uXG4gIGlmIChoYXNIb29rQ29uZmxpY3QpIHtcbiAgICByZXR1cm4geyB0aW1lb3V0U2Vjb25kczogMCB9O1xuICB9XG5cbiAgaWYgKG1pblRpbWVvdXRTZWNvbmRzICE9PSBudWxsKSB7XG4gICAgcmV0dXJuIHsgdGltZW91dFNlY29uZHM6IG1pblRpbWVvdXRTZWNvbmRzIH07XG4gIH1cblxuICByZXR1cm4ge307XG59XG4iXX0=
612
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3VzcGVuc2lvbi1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bnRpbWUvc3VzcGVuc2lvbi1oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFDTCxtQkFBbUIsRUFDbkIsVUFBVSxFQUNWLGlCQUFpQixFQUNqQix1QkFBdUIsRUFDdkIsZUFBZSxFQUNmLGtCQUFrQixHQUNuQixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFDTCx3QkFBd0IsRUFLeEIsb0JBQW9CLEVBQ3BCLGlDQUFpQyxHQUdsQyxNQUFNLGlCQUFpQixDQUFDO0FBQ3pCLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQVE3QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBRTdDLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzdELE9BQU8sS0FBSyxTQUFTLE1BQU0sc0NBQXNDLENBQUM7QUFDbEUsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ3ZELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ25ELE9BQU8sRUFHTCxtQkFBbUIsRUFDbkIsMEJBQTBCLEdBQzNCLE1BQU0sY0FBYyxDQUFDO0FBQ3RCLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBK0d2RSxLQUFLLFVBQVUsZUFBZSxDQUFDLEVBQzdCLEtBQUssRUFDTCxTQUFTLEVBQ1QsU0FBUyxFQUNULFNBQVMsRUFDVCxXQUFXLEdBVVo7SUFJQyxJQUFJLENBQUM7UUFDSCxNQUFNLE1BQU0sR0FBRyxNQUFNLFdBQVcsQ0FBQyxTQUFTLEVBQUU7WUFDMUMsU0FBUztTQUNWLENBQUMsQ0FBQztRQUVILDZFQUE2RTtRQUM3RSwwRUFBMEU7UUFDMUUseUVBQXlFO1FBQ3pFLElBQUksTUFBTSxDQUFDLEtB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Q0FBQyxNQUFNLEdBQUcsQ0FBQztRQUM5QyxjQUFjO1FBQ2Qsc0JBQXNCO1FBQ3RCLGtCQUFrQixFQUFFLGNBQWM7S0FDbkMsQ0FBQztBQUNKLENBQUM7QUFFRDs7Ozs7Ozs7R0FRRztBQUNILFNBQVMsd0JBQXdCLENBQUMsR0FBWTtJQUM1QyxJQUFJLEdBQUcsWUFBWSx3QkFBd0I7UUFBRSxPQUFPLElBQUksQ0FBQztJQUN6RCxJQUFJLEdBQUcsWUFBWSxLQUFLLElBQUksR0FBRyxDQUFDLElBQUksS0FBSywwQkFBMEIsRUFBRSxDQUFDO1FBQ3BFLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUNELE9BQU8sa0JBQWtCLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxNQUFNLEtBQUssR0FBRyxDQUFDO0FBQzFELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IFNwYW4gfSBmcm9tICdAb3BlbnRlbGVtZXRyeS9hcGknO1xuaW1wb3J0IHtcbiAgRW50aXR5Q29uZmxpY3RFcnJvcixcbiAgRmF0YWxFcnJvcixcbiAgSG9va05vdEZvdW5kRXJyb3IsXG4gIFByZWNvbmRpdGlvbkZhaWxlZEVycm9yLFxuICBSdW5FeHBpcmVkRXJyb3IsXG4gIFdvcmtmbG93V29ybGRFcnJvcixcbn0gZnJvbSAnQHdvcmtmbG93L2Vycm9ycyc7XG5pbXBvcnQge1xuICBBdHRyaWJ1dGVWYWxpZGF0aW9uRXJyb3IsXG4gIHR5cGUgQ3JlYXRlRXZlbnRQYXJhbXMsXG4gIHR5cGUgQ3JlYXRlRXZlbnRSZXF1ZXN0LFxuICB0eXBlIEV2ZW50UmVzdWx0LFxuICB0eXBlIFNlcmlhbGl6ZWREYXRhLFxuICBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgU1BFQ19WRVJTSU9OX1NVUFBPUlRTX0NPTVBSRVNTSU9OLFxuICB0eXBlIFdvcmtmbG93UnVuLFxuICB0eXBlIFdvcmxkLFxufSBmcm9tICdAd29ya2Zsb3cvd29ybGQnO1xuaW1wb3J0IHsgaW1wb3J0S2V5IH0gZnJvbSAnLi4vZW5jcnlwdGlvbi5qcyc7XG5pbXBvcnQgdHlwZSB7XG4gIEF0dHJpYnV0ZUludm9jYXRpb25RdWV1ZUl0ZW0sXG4gIEhvb2tJbnZvY2F0aW9uUXVldWVJdGVtLFxuICBTdGVwSW52b2NhdGlvblF1ZXVlSXRlbSxcbiAgV2FpdEludm9jYXRpb25RdWV1ZUl0ZW0sXG4gIFdvcmtmbG93U3VzcGVuc2lvbixcbn0gZnJvbSAnLi4vZ2xvYmFsLmpzJztcbmltcG9ydCB7IHJ1bnRpbWVMb2dnZXIgfSBmcm9tICcuLi9sb2dnZXIuanMnO1xuaW1wb3J0IHR5cGUgeyBHdWVzdENvZGVTdGF0cyB9IGZyb20gJy4uL3NlcmlhbGl6YXRpb24vaGFyZGVuZWQuanMnO1xuaW1wb3J0IHsgZGVoeWRyYXRlU3RlcEFyZ3VtZW50cyB9IGZyb20gJy4uL3NlcmlhbGl6YXRpb24uanMnO1xuaW1wb3J0ICogYXMgQXR0cmlidXRlIGZyb20gJy4uL3RlbGVtZXRyeS9zZW1hbnRpYy1jb252ZW50aW9ucy5qcyc7XG5pbXBvcnQgeyBnZXRBYm9ydFN0cmVhbUlkRnJvbVRva2VuIH0gZnJvbSAnLi4vdXRpbC5qcyc7XG5pbXBvcnQgeyBnZXRNYXhJbmxpbmVTdGVwcyB9IGZyb20gJy4vY29uc3RhbnRzLmpzJztcbmltcG9ydCB7XG4gIHR5cGUgRXZlbnRDcmVhdG9yLFxuICB0eXBlIExvYWRlZEV2ZW50TG9nLFxuICBtZXJnZVJlcG9ydGVkRXZlbnRzLFxuICBwcmVjb25kaXRpb25TbmFwc2hvdFBhcmFtcyxcbn0gZnJvbSAnLi9oZWxwZXJzLmpzJztcbmltcG9ydCB7IFJlcGxheVJlY292ZXJ5UmVwb3J0ZXIgfSBmcm9tICcuL3JlcGxheS1yZWNvdmVyeS1yZXBvcnRlci5qcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3VzcGVuc2lvbkhhbmRsZXJQYXJhbXMge1xuICBzdXNwZW5zaW9uOiBXb3JrZmxvd1N1c3BlbnNpb247XG4gIHdvcmxkOiBXb3JsZDtcbiAgcnVuOiBXb3JrZmxvd1J1bjtcbiAgc3Bhbj86IFNwYW47XG4gIHJlcXVlc3RJZD86IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBydW50aW1lJ3MgbG9hZGVkIGV2ZW50IGxvZy4gRXZlcnkgZXZlbnQgY3JlYXRpb24gdGhpcyBzdXNwZW5zaW9uIG1ha2VzXG4gICAqIGlzIHNlbnQgd2l0aCB0aGUgcHJlY29uZGl0aW9uIHNuYXBzaG90IGRlcml2ZWQgZnJvbSBpdCwgc28gYSBiYWNrZW5kIHRoYXRcbiAgICogaGFzIHJlY29yZGVkIGFuIGV2ZW50IHRoZSByZXBsYXkgZGlkIG5vdCBzZWUgcmVqZWN0cyB0aGUgd3JpdGUgd2l0aCBhIDQxMlxuICAgKiBpbnN0ZWFkIG9mIGFjY2VwdGluZyBhIGRpdmVyZ2VudCBldmVudC4gVGhlIHJlamVjdGlvbiBpcyBub3QgcmV0cmllZCBoZXJlOlxuICAgKiB0aGUgZXZlbnQncyBjb3JyZWxhdGlvbiBpZCB3YXMgbWludGVkIGJ5ICp0aGlzKiByZXBsYXkncyBzZWVkZWQgc2VxdWVuY2UsXG4gICAqIHNvIHJlLWNvbW1pdHRpbmcgaXQgYWdhaW5zdCBhIGNvcnJlY3RlZCBsb2cgd291bGQgcGVyc2lzdCBhbiBldmVudCBub1xuICAgKiBjb3JyZWN0IHJlcGxheSBwcm9kdWNlcy4gVGhlIGNhbGxlciByZXN0YXJ0cyB0aGUgcmVwbGF5IGluc3RlYWQuXG4gICAqL1xuICBldmVudExvZz86IExvYWRlZEV2ZW50TG9nO1xuICAvKipcbiAgICogVHVyYm8gbW9kZSBvbmx5OiBhIHByb21pc2UgdGhhdCByZXNvbHZlcyBvbmNlIHRoZSBiYWNrZ3JvdW5kZWRcbiAgICogYHJ1bl9zdGFydGVkYCBoYXMgbGFuZGVkICh0aGUgcnVuIGV4aXN0cykuIFdoZW4gcHJlc2VudCwgZXZlcnkgd29ybGQgd3JpdGVcbiAgICogdGhpcyBzdXNwZW5zaW9uIHBlcmZvcm1zIChgaG9va19jcmVhdGVkYCwgYHdhaXRfY3JlYXRlZGAsIGVhZ2VyIG92ZXJmbG93XG4gICAqIGBzdGVwX2NyZWF0ZWRgLCDigKYpIGlzIGdhdGVkIG9uIGl0IHNvIHRoZSB3cml0ZSBuZXZlciByYWNlcyBhaGVhZCBvZiB0aGVcbiAgICogcnVuJ3MgY3JlYXRpb24uIFRoZSBwdXJlIGlubGluZSBob3QgcGF0aCBkZWZlcnMgYWxsIG9mIGl0cyBzdGVwcyBhbmQgd3JpdGVzXG4gICAqIG5vdGhpbmcgaGVyZSwgc28gaXQgbmV2ZXIgYXdhaXRzIHRoaXMgYmFycmllci4gYHVuZGVmaW5lZGAgb3V0c2lkZSB0dXJibyxcbiAgICogd2hlcmUgYHJ1bl9zdGFydGVkYCB3YXMgYWxyZWFkeSBhd2FpdGVkIHVwIGZyb250LlxuICAgKi9cbiAgcnVuUmVhZHlCYXJyaWVyPzogUHJvbWlzZTx1bmtub3duPjtcbiAgLyoqIE9uZS1zaG90IHRlbGVtZXRyeSByZXBvcnRlciwgYWN0aXZhdGVkIG9ubHkgYWZ0ZXIgcmVwbGF5IGhhcyByZWNvdmVyZWQuICovXG4gIHJlcGxheVJlY292ZXJ5UmVwb3J0ZXI/OiBSZXBsYXlSZWNvdmVyeVJlcG9ydGVyO1xufVxuXG4vKipcbiAqIFJlc3VsdCBvZiBoYW5kbGluZyBhIHN1c3BlbnNpb24uIFJldHVybnMgcGVuZGluZyBzdGVwIGl0ZW1zIHNvIHRoZSBjYWxsZXJcbiAqIGNhbiBkZWNpZGUgd2hpY2ggdG8gZXhlY3V0ZSBpbmxpbmUgdnMgcXVldWUgdG8gYmFja2dyb3VuZC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTdXNwZW5zaW9uSGFuZGxlclJlc3VsdCB7XG4gIC8qKiBQZW5kaW5nIHN0ZXAgaXRlbXMgd2l0aCBldmVudHMgY3JlYXRlZCBidXQgTk9UIHF1ZXVlZCAqL1xuICBwZW5kaW5nU3RlcHM6IFN0ZXBJbnZvY2F0aW9uUXVldWVJdGVtW107XG4gIC8qKlxuICAgKiBDb3JyZWxhdGlvbiBJRHMgZm9yIHdoaWNoIHRoaXMgc3VzcGVuc2lvbiBjYWxsIGFjdHVhbGx5IHdyb3RlIHRoZVxuICAgKiBzdGVwX2NyZWF0ZWQgZXZlbnQgKGFzIG9wcG9zZWQgdG8gY2F0Y2hpbmcgRW50aXR5Q29uZmxpY3RFcnJvciBiZWNhdXNlXG4gICAqIGEgY29uY3VycmVudCBoYW5kbGVyIHdyb3RlIGl0IGZpcnN0KS4gT25seSB0aGUgaGFuZGxlciB0aGF0IHdyb3RlIHRoZVxuICAgKiBzdGVwX2NyZWF0ZWQgZXZlbnQgc2hvdWxkIHF1ZXVlIC8gaW5saW5lLWV4ZWN1dGUgdGhlIHN0ZXAg4oCUIHRoaXNcbiAgICogZ3VhcmFudGVlcyBhIHNpbmdsZSBvd25lciBwZXIgc3RlcCwgZXZlbiB3aGVuIG11bHRpcGxlIGhhbmRsZXJzIHJhY2VcbiAgICogaW50byB0aGUgc2FtZSBiYXRjaCBib3VuZGFyeS5cbiAgICovXG4gIGNyZWF0ZWRTdGVwQ29ycmVsYXRpb25JZHM6IFNldDxzdHJpbmc+O1xuICAvKipcbiAgICogSG93IG1hbnkgZXZlbnRzIHRoaXMgcGhhc2UncyB3cml0ZXMgcmVwb3J0ZWQgYmFjayBhcyBvY2N1cHlpbmcgc2xvdHMgdGhleVxuICAgKiBza2lwcGVkIG92ZXIsIGFscmVhZHkgbWVyZ2VkIGludG8gdGhlIGNhbGxlcidzIGBldmVudExvZy5ldmVudHNgLiBOb256ZXJvXG4gICAqIG1lYW5zIHRoZSBhcnJheSB3YXMgcmVvcmRlcmVkIHRvIHJlc3RvcmUgc2xvdCBvcmRlciwgc28gYW55IGluZGV4IHRoZVxuICAgKiBjYWxsZXIgY2FjaGVkIGludG8gaXQgKHBheWxvYWQgcHJld2FybSBzY2FuIHBvc2l0aW9uKSBpcyBzdGFsZS5cbiAgICovXG4gIHJlcG9ydGVkRXZlbnRDb3VudDogbnVtYmVyO1xuICAvKipcbiAgICogVGhlIHN0ZXBzIHdob3NlIGBzdGVwX2NyZWF0ZWRgIHdyaXRlcyB3ZXJlIGludGVudGlvbmFsbHkgZGVmZXJyZWQgc28gdGhlXG4gICAqIGNhbGxlciBjYW4gcnVuIHRoZW0gaW5saW5lIHZpYSBsYXp5IGBzdGVwX3N0YXJ0ZWRgIGV2ZW50cyAod2hpY2ggY3JlYXRlXG4gICAqIHRoZSBzdGVwIG9uIHRoZSBmbHkpLCBzYXZpbmcgb25lIHdvcmxkIHJvdW5kLXRyaXAgcGVyIGlubGluZSBzdGVwLiBVcCB0b1xuICAgKiBgZ2V0TWF4SW5saW5lU3RlcHMoKWAgc3RlcHMgYXJlIGRlZmVycmVkOyB0aGUgY2FsbGVyIHJ1bnMgdGhlbSBpbmxpbmUgaW5cbiAgICogcGFyYWxsZWwgYW5kIHF1ZXVlcyB0aGUgcmVzdC4gRW1wdHkgd2hlbiBubyBzdGVwIHdhcyBkZWZlcnJlZCAobm90aGluZ1xuICAgKiBwZW5kaW5nLCBvciBhIGBob29rLmdldENvbmZsaWN0KClgIGF3YWl0ZXIgaXMgcHJlc2VudCBzbyBub3RoaW5nIGlzXG4gICAqIGV4ZWN1dGVkIGlubGluZSkuIFRoZSBjYWxsZXIgcGFzc2VzIGVhY2ggYGRlaHlkcmF0ZWRJbnB1dGAgc3RyYWlnaHQgdG9cbiAgICogYGV4ZWN1dGVTdGVwYCwgd2hpY2ggc2VuZHMgaXQgYXMgdGhlIGBzdGVwX3N0YXJ0ZWRgIHBheWxvYWQuIFRoZSBhdG9taWNcbiAgICogY3JlYXRlLWNsYWltIGluc2lkZSBlYWNoIGBzdGVwX3N0YXJ0ZWRgIGlzIHRoZSBleGFjdGx5LW9uZS1vd25lciBnYXRlIHRoYXRcbiAgICogdGhlIHN0YW5kYWxvbmUgYHN0ZXBfY3JlYXRlZGAgcHJvdmlkZWQgYmVmb3JlOiB0aGUgbG9zZXIgb2YgdGhlIHJhY2UgZ2V0c1xuICAgKiBgRW50aXR5Q29uZmxpY3RFcnJvcmAg4oaSIGBza2lwcGVkYCBhbmQgZG9lcyBub3QgcnVuIHRoZSBib2R5LlxuICAgKi9cbiAgbGF6eUlubGluZVN0ZXBzOiBBcnJheTx7XG4gICAgY29ycmVsYXRpb25JZDogc3RyaW5nO1xuICAgIHN0ZXBOYW1lOiBzdHJpbmc7XG4gICAgZGVoeWRyYXRlZElucHV0OiBTZXJpYWxpemVkRGF0YTtcbiAgfT47XG4gIC8qKlxuICAgKiBUaGUgc29vbmVzdCBwZW5kaW5nIHdhaXQsIGlmIGFueTogc2Vjb25kcyB1bnRpbCBpdCBlbGFwc2VzIGFuZCB0aGVcbiAgICogY29ycmVsYXRpb25JZCBvZiB0aGUgd2FpdCB0aGF0IHByb2R1Y2VkIHRoYXQgdGltZW91dC4gVGhlXG4gICAqIGNvcnJlbGF0aW9uSWQgc2VlZHMgdGhlIGlkZW1wb3RlbmN5IGtleSBmb3IgdGhlIHdhaXQtY29udGludWF0aW9uXG4gICAqIHF1ZXVlIG1lc3NhZ2Ugc28gdGhhdCByZXBlYXRlZCBzdXNwZW5zaW9uIHBhc3NlcyBvdmVyIHRoZSBzYW1lXG4gICAqIHBlbmRpbmcgd2FpdCBjb2xsYXBzZSBpbnRvIGEgc2luZ2xlIGRlbGF5ZWQgY29udGludWF0aW9uLlxuICAgKi9cbiAgd2FpdFRpbWVvdXQ/OiB7IHNlY29uZHM6IG51bWJlcjsgY29ycmVsYXRpb25JZDogc3RyaW5nIH07XG4gIC8qKiBXaGV0aGVyIGEgaG9vayBjb25mbGljdCB3YXMgZGV0ZWN0ZWQgKHNob3VsZCByZS1pbnZva2UgaW1tZWRpYXRlbHkpICovXG4gIGhhc0hvb2tDb25mbGljdDogYm9vbGVhbjtcbiAgLyoqIFdoZXRoZXIgYSBgaG9vay5nZXRDb25mbGljdCgpYCBhd2FpdGVyIG5lZWRzIHRoZSB3b3JrZmxvdyB0byBjb250aW51ZSBpbW1lZGlhdGVseSAqL1xuICBoYXNBd2FpdGVkSG9va0NyZWF0aW9uOiBib29sZWFuO1xuICAvKiogV2hldGhlciBuYXRpdmUgd29ya2Zsb3cgYXR0cmlidXRlIGV2ZW50cyB3ZXJlIHdyaXR0ZW4gZm9yIHJlcGxheS4gKi9cbiAgaGFzQXR0cmlidXRlRXZlbnRzOiBib29sZWFuO1xuICAvKipcbiAgICogV2hldGhlciB0aGlzIHN1c3BlbnNpb24gY3JlYXRlZCBhbnkgaG9vayAoYGhvb2tfY3JlYXRlZGApIGV2ZW50cy4gVW5saWtlXG4gICAqIGBoYXNIb29rQ29uZmxpY3RgIC8gYGhhc0F3YWl0ZWRIb29rQ3JlYXRpb25gLCB0aGlzIGlzIHRydWUgZXZlbiBmb3IgYSBwbGFpblxuICAgKiBmaXJlLWFuZC1mb3JnZXQgaG9vayB3aXRoIG5vIGNvbmZsaWN0IGFuZCBubyBhd2FpdGVyLiBUdXJibyBtb2RlIHVzZXMgaXQgdG9cbiAgICogZGV0ZWN0IFwiYSBob29rIHdhcyBjcmVhdGVkIHRoaXMgc3VzcGVuc2lvblwiIGFuZCBzdG9wIGZvcmNpbmcgb3B0aW1pc3RpY1xuICAgKiBpbmxpbmUgc3RhcnQgKGEgaG9vayBpbnRyb2R1Y2VzIGxhdGVyIHJlc3VtZSBpbnZvY2F0aW9ucyB0aGF0IGNvdWxkIHJhY2UpLlxuICAgKi9cbiAgaGFzSG9va0V2ZW50czogYm9vbGVhbjtcbiAgLyoqXG4gICAqIFdhbGwtY2xvY2sgbXMgc3BlbnQgY29tbWl0dGluZyB0aGlzIHN1c3BlbnNpb24ncyBgaG9va19jcmVhdGVkYCBldmVudHNcbiAgICogKDAgd2hlbiBpdCBjcmVhdGVkIG5vbmUpLiBUaGUgY2FsbGVyIGFjY3VtdWxhdGVzIHRoaXMgYWNyb3NzIGl0ZXJhdGlvbnNcbiAgICogYW5kIHN1YnRyYWN0cyBpdCBmcm9tIHRoZSBUVEZTIGxhdGVuY3kgbWVhc3VyZW1lbnQsIHNvIHRpbWUgc3BlbnRcbiAgICogZHVyYWJseSBjcmVhdGluZyB0aGUgdXNlcidzIGhvb2tzIGRvZXNuJ3QgY291bnQgYXMgcnVudGltZSBvdmVyaGVhZC5cbiAgICovXG4gIGhvb2tDcmVhdGlvbk1zOiBudW1iZXI7XG4gIC8qKlxuICAgKiBXaGV0aGVyIHNlcmlhbGl6aW5nIHRoaXMgc3VzcGVuc2lvbidzIG5ldyBzdGVwIGlucHV0cyB3YXMgcGFzc2l2ZSAoZGlkXG4gICAqIG5vdCBleGVjdXRlIHdvcmtmbG93LW93bmVkIGNvZGUgc3VjaCBhcyBnZXR0ZXJzLCBwcm94eSB0cmFwcywgb3IgY3VzdG9tXG4gICAqIHNlcmlhbGl6ZXJzKS4gYGZhbHNlYCBtZWFucyB0aGUgcmV0YWluZWQgVk0gbWF5IGhhdmUgZGl2ZXJnZWQgZnJvbSB3aGF0XG4gICAqIGEgY29sZCByZXBsYXkgd291bGQgY29tcHV0ZSwgc28gdGhlIGNhbGxlciBtdXN0IGRlbW90ZSB0byByZXBsYXkuXG4gICAqL1xuICByZXRhaW5lZFN0ZXBJbnB1dHNTYWZlOiBib29sZWFuO1xufVxuXG5hc3luYyBmdW5jdGlvbiBjcmVhdGVIb29rRXZlbnQoe1xuICBydW5JZCxcbiAgaG9va0V2ZW50LFxuICBxdWV1ZUl0ZW0sXG4gIHJlcXVlc3RJZCxcbiAgY3JlYXRlRXZlbnQsXG59OiB7XG4gIHJ1bklkOiBzdHJpbmc7XG4gIGhvb2tFdmVudDogQ3JlYXRlRXZlbnRSZXF1ZXN0O1xuICBxdWV1ZUl0ZW06IEhvb2tJbnZvY2F0aW9uUXVldWVJdGVtO1xuICByZXF1ZXN0SWQ/OiBzdHJpbmc7XG4gIGNyZWF0ZUV2ZW50OiAoXG4gICAgZGF0YTogQ3JlYXRlRXZlbnRSZXF1ZXN0LFxuICAgIHBhcmFtcz86IENyZWF0ZUV2ZW50UGFyYW1zXG4gICkgPT4gUHJvbWlzZTxFdmVudFJlc3VsdD47XG59KTogUHJvbWlzZTx7XG4gIGhhc0hvb2tDb25mbGljdDogYm9vbGVhbjtcbiAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbjogYm9vbGVhbjtcbn0+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjcmVhdGVFdmVudChob29rRXZlbnQsIHtcbiAgICAgIHJlcXVlc3RJZCxcbiAgICB9KTtcblxuICAgIC8vIENoZWNrIGlmIHRoZSB3b3JsZCByZXR1cm5lZCBhIGhvb2tfY29uZmxpY3QgZXZlbnQgaW5zdGVhZCBvZiBob29rX2NyZWF0ZWQuXG4gICAgLy8gVGhlIGhvb2tfY29uZmxpY3QgZXZlbnQgaXMgc3RvcmVkIGluIHRoZSBldmVudCBsb2cgYW5kIHdpbGwgYmUgcmVwbGF5ZWRcbiAgICAvLyBvbiB0aGUgbmV4dCB3b3JrZmxvdyBpbnZvY2F0aW9uLCBjYXVzaW5nIHRoZSBob29rJ3MgcHJvbWlzZSB0byByZWplY3QuXG4gICAgaWYgKHJlc3VsdC5ldmVudD8uZXZlbnRUeXBlID09PSAnaG9va19jb25mbGljdCcpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGhhc0hvb2tDb25mbGljdDogdHJ1ZSxcbiAgICAgICAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbjogZmFsc2UsXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBoYXNIb29rQ29uZmxpY3Q6IGZhbHNlLFxuICAgICAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbjogcXVldWVJdGVtLmhhc0NvbmZsaWN0QXdhaXRlciA9PT0gdHJ1ZSxcbiAgICB9O1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ0hvb2sgYWxyZWFkeSBleGlzdHMsIGNvbnRpbnVpbmcnLCB7XG4gICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaGFzSG9va0NvbmZsaWN0OiBmYWxzZSxcbiAgICAgICAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbjogcXVldWVJdGVtLmhhc0NvbmZsaWN0QXdhaXRlciA9PT0gdHJ1ZSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKFJ1bkV4cGlyZWRFcnJvci5pcyhlcnIpKSB7XG4gICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ1dvcmtmbG93IHJ1biBhbHJlYWR5IGNvbXBsZXRlZCwgc2tpcHBpbmcgaG9vaycsIHtcbiAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgfSk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBoYXNIb29rQ29uZmxpY3Q6IGZhbHNlLFxuICAgICAgICBoYXNBd2FpdGVkSG9va0NyZWF0aW9uOiBmYWxzZSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKGlzV29ybGRWYWxpZGF0aW9uRmFpbHVyZShlcnIpKSB7XG4gICAgICBjb25zdCBmYXRhbCA9IG5ldyBGYXRhbEVycm9yKFxuICAgICAgICBgY3JlYXRlSG9vayBmYWlsZWQgV29ybGQgdmFsaWRhdGlvbjogJHtcbiAgICAgICAgICBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVycilcbiAgICAgICAgfWBcbiAgICAgICk7XG4gICAgICBmYXRhbC5jYXVzZSA9IGVycjtcbiAgICAgIHRocm93IGZhdGFsO1xuICAgIH1cblxuICAgIHRocm93IGVycjtcbiAgfVxufVxuXG4vKipcbiAqIEhhbmRsZXMgYSB3b3JrZmxvdyBzdXNwZW5zaW9uIGJ5IHByb2Nlc3NpbmcgYWxsIHBlbmRpbmcgb3BlcmF0aW9ucyAoaG9va3MsIHN0ZXBzLCB3YWl0cykuXG4gKiBDcmVhdGVzIGV2ZW50cyBmb3IgYWxsIG9wZXJhdGlvbnMgYnV0IGRvZXMgTk9UIHF1ZXVlIHN0ZXAgbWVzc2FnZXMg4oCUIHJldHVybnMgdGhlIHBlbmRpbmdcbiAqIHN0ZXBzIHNvIHRoZSBjYWxsZXIgY2FuIGRlY2lkZSB3aGljaCB0byBleGVjdXRlIGlubGluZSB2cyBxdWV1ZSB0byBiYWNrZ3JvdW5kLlxuICpcbiAqIFByb2Nlc3Npbmcgb3JkZXI6XG4gKiAxLiBIb29rcyBhcmUgcHJvY2Vzc2VkIGZpcnN0IHRvIHByZXZlbnQgcmFjZSBjb25kaXRpb25zIHdpdGggd2ViaG9vayByZWNlaXZlcnNcbiAqIDIuIFN0ZXAgZXZlbnRzIGFuZCB3YWl0IGV2ZW50cyBhcmUgY3JlYXRlZCBpbiBwYXJhbGxlbFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlU3VzcGVuc2lvbih7XG4gIHN1c3BlbnNpb24sXG4gIHdvcmxkLFxuICBydW4sXG4gIHNwYW4sXG4gIHJlcXVlc3RJZCxcbiAgZXZlbnRMb2csXG4gIHJ1blJlYWR5QmFycmllcixcbiAgcmVwbGF5UmVjb3ZlcnlSZXBvcnRlcixcbn06IFN1c3BlbnNpb25IYW5kbGVyUGFyYW1zKTogUHJvbWlzZTxTdXNwZW5zaW9uSGFuZGxlclJlc3VsdD4ge1xuICBjb25zdCBydW5JZCA9IHJ1bi5ydW5JZDtcblxuICAvLyBUdXJibyBtb2RlOiBob2xkIGV2ZXJ5IHdvcmxkIHdyaXRlIGJlbG93IHVudGlsIHRoZSBiYWNrZ3JvdW5kZWRcbiAgLy8gYHJ1bl9zdGFydGVkYCBoYXMgKnNldHRsZWQqLCBzbyB3ZSBuZXZlciB3cml0ZSBhIHN0ZXAvaG9vay93YWl0IGV2ZW50IGZvciBhXG4gIC8vIHJ1biB0aGF0IGRvZXMgbm90IGV4aXN0IHlldC4gQSBuby1vcCBvdXRzaWRlIHR1cmJvIChiYXJyaWVyIHVuZGVmaW5lZCkgYW5kXG4gIC8vIG9uIHRoZSBwdXJlIGlubGluZSBob3QgcGF0aCwgd2hpY2ggZGVmZXJzIGFsbCBzdGVwcyBhbmQgd3JpdGVzIG5vdGhpbmcuXG4gIC8vIEF3YWl0aW5nIHRoZSBzYW1lICh1c3VhbGx5IGFscmVhZHktc2V0dGxlZCkgcHJvbWlzZSBtb3JlIHRoYW4gb25jZSBpcyBjaGVhcC5cbiAgLy8gQSBiYXJyaWVyIHJlamVjdGlvbiBpcyBzd2FsbG93ZWQgZm9yIG9yZGVyaW5nIG9ubHk6IGlmIGBydW5fc3RhcnRlZGAgdHJ1bHlcbiAgLy8gZmFpbGVkIHRoZSBydW4gZG9lcyBub3QgZXhpc3QsIHNvIHRoZSBzdWJzZXF1ZW50IHdyaXRlIHN1cmZhY2VzIHRoZSByZWFsXG4gIC8vIGVycm9yIChydW4gbm90IGZvdW5kIC8gZ29uZSkgYW5kIHRoZSBtZXNzYWdlIHJlZGVsaXZlcnMuXG4gIGNvbnN0IGVuc3VyZVJ1blJlYWR5ID0gYXN5bmMgKCk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgIGlmIChydW5SZWFkeUJhcnJpZXIpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHJ1blJlYWR5QmFycmllcjtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBpbnRlbnRpb25hbDogb3JkZXJpbmcgYmFycmllciBvbmx5IOKAlCBzZWUgYWJvdmUuXG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiBBd2FpdCBldmVyeSBvcGVyYXRpb24gaW4gYSBzdXNwZW5zaW9uIHBoYXNlIGJlZm9yZSBsZXR0aW5nIGEgZmFpbHVyZVxuICAgKiBlc2NhcGUsIHByZWZlcnJpbmcgYSBzdGFsZS1zbmFwc2hvdCAoNDEyKSByZWplY3Rpb24gd2hlbiBvbmUgb2NjdXJyZWQuXG4gICAqXG4gICAqIGBQcm9taXNlLmFsbGAgcmVqZWN0cyBhcyBzb29uIGFzIG9uZSBvcGVyYXRpb24gZG9lcyBhbmQgbGVhdmVzIGl0cyBzaWJsaW5nc1xuICAgKiBpbiBmbGlnaHQuIFRoYXQgbWF0dGVycyBmb3IgYSA0MTI6IHRoZSBjYWxsZXIgcmVhY3RzIGJ5IHJlbG9hZGluZyB0aGUgZXZlbnRcbiAgICogbG9nIGFuZCByZXN0YXJ0aW5nIHRoZSByZXBsYXksIHNvIGEgc2libGluZyBjcmVhdGUgdGhhdCBsYW5kcyBhZnRlciB0aGVcbiAgICogcmVqZWN0aW9uIGVzY2FwZWQgY29tbWl0cyBhbiBldmVudCB3aG9zZSBjb3JyZWxhdGlvbiBpZCBjYW1lIGZyb20gdGhlXG4gICAqIGFiYW5kb25lZCByZXBsYXkncyBzZWVkZWQgc2VxdWVuY2Ug4oCUIGFuIGV2ZW50IHRoZSBmcmVzaCByZXBsYXkgbmV2ZXJcbiAgICogcHJvZHVjZXMg4oCUIGFuZCBpdCByYWNlcyB0aGUgcmVzdGFydCdzIHJlbG9hZCB3aGlsZSBkb2luZyBzby4gU2V0dGxpbmcgZmlyc3RcbiAgICogbWFrZXMgdGhpcyBwaGFzZSdzIHdyaXRlIHNldCBmaW5hbCBiZWZvcmUgdGhlIGNhbGxlciBhY3RzIG9uIHRoZSBmYWlsdXJlLlxuICAgKiBJdCBtaXJyb3JzIHRoZSBydW50aW1lJ3MgaW5saW5lIHN0ZXAgY2xhaW0sIHdoaWNoIHNldHRsZXMgdGhlIGluLWZsaWdodFxuICAgKiBzdGVwIGV4ZWN1dGlvbnMgYmVmb3JlIGVzY2FsYXRpbmcgYSA0MTIuXG4gICAqXG4gICAqIEEgNDEyIGlzIHByZWZlcnJlZCBvdmVyIGFueSBvdGhlciByZWplY3Rpb24gaW4gdGhlIHNhbWUgcGhhc2UgYmVjYXVzZSBpdFxuICAgKiBoYXMgYSBkZWZpbmVkLCBjaGVhcCByZWNvdmVyeSAocmVwbGF5IGZyb20gYSBjb3JyZWN0ZWQgbG9nKSB3aGlsZSB0aGVcbiAgICogb3RoZXJzIGRvIG5vdC4gQSBkZXRlcm1pbmlzdGljIGZhaWx1cmUgc3VjaCBhcyBhbiBhdHRyaWJ1dGUtdmFsaWRhdGlvblxuICAgKiBgRmF0YWxFcnJvcmAgcmVjdXJzIG9uIHRoZSByZXN0YXJ0IGFuZCBmYWlscyB0aGUgcnVuIHRoZW4sIGF0IHRoZSBjb3N0IG9mXG4gICAqIG9uZSBleHRyYSByZXBsYXkuXG4gICAqL1xuICBjb25zdCBzZXR0bGVQaGFzZSA9IGFzeW5jIChvcHM6IFByb21pc2U8dW5rbm93bj5bXSk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgIGNvbnN0IHJlYXNvbnMgPSAoYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKG9wcykpXG4gICAgICAuZmlsdGVyKChyKTogciBpcyBQcm9taXNlUmVqZWN0ZWRSZXN1bHQgPT4gci5zdGF0dXMgPT09ICdyZWplY3RlZCcpXG4gICAgICAubWFwKChyKSA9PiByLnJlYXNvbik7XG4gICAgaWYgKHJlYXNvbnMubGVuZ3RoID09PSAwKSByZXR1cm47XG4gICAgdGhyb3cgcmVhc29ucy5maW5kKChyKSA9PiBQcmVjb25kaXRpb25GYWlsZWRFcnJvci5pcyhyKSkgPz8gcmVhc29uc1swXTtcbiAgfTtcblxuICAvLyBFdmVyeSBzdXNwZW5zaW9uIHdyaXRlIGNhcnJpZXMgcmVwbGF5LXJlY292ZXJ5IHRlbGVtZXRyeSBvbiB0aGUgZmlyc3Qgb25lXG4gIC8vIHRoYXQgY29tbWl0cyBhZnRlciByZXBsYXkgcmVjb3ZlcmVkLiBBbGwgc3VzcGVuc2lvbiBldmVudHMgYXJlXG4gIC8vIG5vbi1ydW5fY3JlYXRlZCBldmVudHMgb24gdGhpcyBydW4ncyBgcnVuSWRgLlxuICBjb25zdCByZXBvcnRlciA9IHJlcGxheVJlY292ZXJ5UmVwb3J0ZXIgPz8gUmVwbGF5UmVjb3ZlcnlSZXBvcnRlci5pbmVydCgpO1xuICBjb25zdCBjcmVhdGVFdmVudCA9IChkYXRhOiBDcmVhdGVFdmVudFJlcXVlc3QsIHBhcmFtcz86IENyZWF0ZUV2ZW50UGFyYW1zKSA9PlxuICAgIHJlcG9ydGVyLndpdGhFdmVudENyZWF0ZShwYXJhbXMsIChwKSA9PlxuICAgICAgd29ybGQuZXZlbnRzLmNyZWF0ZShydW5JZCwgZGF0YSwgcClcbiAgICApO1xuICAvLyBBZGRzIHRoZSBvcHRpbWlzdGljLWNvbmN1cnJlbmN5IGd1YXJkIHdoZW4gdGhlIGNhbGxlciBzdXBwbGllZCBhIGxvYWRlZFxuICAvLyBldmVudCBsb2c7IHdpdGhvdXQgb25lIGl0IGNyZWF0ZXMgZGlyZWN0bHkgKGNhbGxlcnMgd2l0aCBubyByZXBsYXlcbiAgLy8gc25hcHNob3QsIGUuZy4gdGVzdHMpLiBBIHN0YWxlICg0MTIpIHJlamVjdGlvbiBwcm9wYWdhdGVzIHRvIHRoZSBjYWxsZXIsXG4gIC8vIHdoaWNoIHJlc3RhcnRzIHRoZSByZXBsYXkgZnJvbSBhIGNvcnJlY3RlZCBsb2cg4oCUIGl0IGlzIG5vdCByZXRyaWVkIGhlcmUsXG4gIC8vIGJlY2F1c2UgdGhlIGV2ZW50J3MgY29ycmVsYXRpb24gaWQgd2FzIG1pbnRlZCBieSAqdGhpcyogcmVwbGF5J3Mgc2VlZGVkXG4gIC8vIHNlcXVlbmNlLCBzbyByZS1jb21taXR0aW5nIGl0IGFnYWluc3QgYSBjb3JyZWN0ZWQgbG9nIHdvdWxkIHBlcnNpc3QgYW5cbiAgLy8gZXZlbnQgbm8gY29ycmVjdCByZXBsYXkgcHJvZHVjZXMuXG4gIGxldCByZXBvcnRlZEV2ZW50cyA9IDA7XG4gIGNvbnN0IGNyZWF0ZUd1YXJkZWQ6IEV2ZW50Q3JlYXRvciA9IGFzeW5jIChkYXRhLCBwYXJhbXMpID0+IHtcbiAgICBpZiAoIWV2ZW50TG9nKSB7XG4gICAgICByZXR1cm4gY3JlYXRlRXZlbnQoZGF0YSwgcGFyYW1zKTtcbiAgICB9XG4gICAgY29uc3QgbG9nID0gZXZlbnRMb2c7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY3JlYXRlRXZlbnQoZGF0YSwge1xuICAgICAgLi4ucGFyYW1zLFxuICAgICAgLi4ucHJlY29uZGl0aW9uU25hcHNob3RQYXJhbXMobG9nLmV2ZW50cywgbG9nLmN1cnNvciksXG4gICAgfSk7XG4gICAgLy8gQnVtcC1hbmQtcmVwb3J0OiB0aGUgd3JpdGUgbGFuZGVkIGFib3ZlIHRoZSBzbG90IGl0IGFza2VkIGZvciwgc28gdGhlc2VcbiAgICAvLyBhcmUgdGhlIGV2ZW50cyBpdCB3YXMgZGVjaWRlZCB3aXRob3V0LiBNZXJnaW5nIHRoZW0gaGVyZSByYXRoZXIgdGhhbiBhdFxuICAgIC8vIGVhY2ggY2FsbCBzaXRlIG1lYW5zIHRoZSByZXN0IG9mIHRoaXMgcGhhc2UncyB3cml0ZXMg4oCUIHdoaWNoIHJlYWQgdGhlXG4gICAgLy8gc2FtZSBhcnJheSB0byBidWlsZCB0aGVpciBvd24gc25hcHNob3Qg4oCUIGFzayBmb3IgYSBzbG90IGFib3ZlIHRoZW0sIGFuZFxuICAgIC8vIHRoZSByZXBsYXkgdGhhdCByZXN1bWVzIGZyb20gdGhpcyBsb2cgc2VlcyB0aGVtIHdpdGhvdXQgYSByZWxvYWQuXG4gICAgLy9cbiAgICAvLyBBIHRydW5jYXRlZCByZXBvcnQgKGBoYXNNb3JlYCkgaXMgZHJvcHBlZCB3aG9sZSByYXRoZXIgdGhhbiBtZXJnZWQsIHRoZVxuICAgIC8vIHNhbWUgd2F5IHRoZSB3YWl0IGxvb3AgdHJlYXRzIG9uZS4gSXQgY292ZXJzIGEgc3BhbiBvZiBwb3NpdGlvbnMgYnV0XG4gICAgLy8gY2FycmllcyBvbmx5IHNvbWUgb2YgdGhlIGV2ZW50cyBvbiB0aGVtLCBzbyBtZXJnaW5nIGl0IHdvdWxkIHJhaXNlIHRoZVxuICAgIC8vIGxvZydzIGhpZ2hlc3QgcG9zaXRpb24gcGFzdCBhIHBvc2l0aW9uIHdob3NlIGV2ZW50IGlzIG1pc3NpbmcuIEV2ZXJ5XG4gICAgLy8gbGF0ZXIgd3JpdGUgb2YgdGhpcyBwaGFzZSByZWFkcyB0aGF0IG1heGltdW0gdG8gc2F5IHdoYXQgaXQgaGFzIHNlZW4sIHNvXG4gICAgLy8gZWFjaCB3b3VsZCBjbGFpbSBhIHBvc2l0aW9uIGl0IG5ldmVyIHNhdyBhbmQgdGhlIFdvcmxkLCB3aGljaCBvbmx5XG4gICAgLy8gcmVwb3J0cyB0aGUgc3BhbiBhIHdyaXRlIHNraXBzLCB3b3VsZCBuZXZlciBzZW5kIGl0LiBEcm9wcGluZyB0aGUgcmVwb3J0XG4gICAgLy8gY29zdHMgb25lIG1vcmUgcm91bmQgb2YgdGhlIHNhbWUgZXZlbnRzIG9uIHRoZSBuZXh0IHdyaXRlIGFuZCBrZWVwcyB0aGVcbiAgICAvLyBsb2cgYSBwcmVmaXggb2YgdGhlIHRydXRoLlxuICAgIGlmIChyZXN1bHQuZXZlbnRzPy5sZW5ndGggJiYgcmVzdWx0Lmhhc01vcmUgIT09IHRydWUpIHtcbiAgICAgIGNvbnN0IGFkZGVkID0gbWVyZ2VSZXBvcnRlZEV2ZW50cyhsb2cuZXZlbnRzLCByZXN1bHQuZXZlbnRzKTtcbiAgICAgIHJlcG9ydGVkRXZlbnRzICs9IGFkZGVkO1xuICAgICAgaWYgKGFkZGVkID4gMCkge1xuICAgICAgICBydW50aW1lTG9nZ2VyLmRlYnVnKCdTdXNwZW5zaW9uIHdyaXRlIHNraXBwZWQgb2NjdXBpZWQgc2xvdHMnLCB7XG4gICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgZXZlbnRUeXBlOiBkYXRhLmV2ZW50VHlwZSxcbiAgICAgICAgICBldmVudElkOiByZXN1bHQuZXZlbnQ/LmV2ZW50SWQsXG4gICAgICAgICAgcmVwb3J0ZWQ6IGFkZGVkLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHJlc3VsdC5ldmVudHM/Lmxlbmd0aCkge1xuICAgICAgcnVudGltZUxvZ2dlci5kZWJ1ZygnRHJvcHBlZCBhIHRydW5jYXRlZCBza2lwcGVkLXNsb3QgcmVwb3J0Jywge1xuICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgZXZlbnRUeXBlOiBkYXRhLmV2ZW50VHlwZSxcbiAgICAgICAgZXZlbnRJZDogcmVzdWx0LmV2ZW50Py5ldmVudElkLFxuICAgICAgICBvZmZlcmVkOiByZXN1bHQuZXZlbnRzLmxlbmd0aCxcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuICAvLyBTZXBhcmF0ZSBxdWV1ZSBpdGVtcyBieSB0eXBlXG4gIGNvbnN0IHN0ZXBJdGVtcyA9IHN1c3BlbnNpb24uc3RlcHMuZmlsdGVyKFxuICAgIChpdGVtKTogaXRlbSBpcyBTdGVwSW52b2NhdGlvblF1ZXVlSXRlbSA9PiBpdGVtLnR5cGUgPT09ICdzdGVwJ1xuICApO1xuICBjb25zdCBhbGxIb29rSXRlbXMgPSBzdXNwZW5zaW9uLnN0ZXBzLmZpbHRlcihcbiAgICAoaXRlbSk6IGl0ZW0gaXMgSG9va0ludm9jYXRpb25RdWV1ZUl0ZW0gPT4gaXRlbS50eXBlID09PSAnaG9vaydcbiAgKTtcbiAgY29uc3Qgd2FpdEl0ZW1zID0gc3VzcGVuc2lvbi5zdGVwcy5maWx0ZXIoXG4gICAgKGl0ZW0pOiBpdGVtIGlzIFdhaXRJbnZvY2F0aW9uUXVldWVJdGVtID0+IGl0ZW0udHlwZSA9PT0gJ3dhaXQnXG4gICk7XG4gIGNvbnN0IGF0dHJpYnV0ZUl0ZW1zID0gc3VzcGVuc2lvbi5zdGVwcy5maWx0ZXIoXG4gICAgKGl0ZW0pOiBpdGVtIGlzIEF0dHJpYnV0ZUludm9jYXRpb25RdWV1ZUl0ZW0gPT4gaXRlbS50eXBlID09PSAnYXR0cmlidXRlJ1xuICApO1xuXG4gIGNvbnN0IGhvb2tzTmVlZGluZ0NyZWF0aW9uID0gYWxsSG9va0l0ZW1zLmZpbHRlcihcbiAgICAoaXRlbSkgPT4gIWl0ZW0uaGFzQ3JlYXRlZEV2ZW50XG4gICk7XG5cbiAgLy8gR3JvdXAgaG9vayBpdGVtcyB0aGF0IG5lZWQgd29yayBieSB0b2tlbiwgcHJlc2VydmluZyBxdWV1ZS1pbnNlcnRpb25cbiAgLy8gKHdvcmtmbG93IGNvZGUpIG9yZGVyIHdpdGhpbiBlYWNoIHRva2VuLiBPcGVyYXRpb25zIG9uIG9uZSB0b2tlbiBtdXN0XG4gIC8vIGFwcGx5IGluIGNvZGUgb3JkZXI6IGEgZGlzcG9zZSgpIG9mIGFuIGVhcmxpZXIgaG9vayByZWxlYXNlcyB0aGUgdG9rZW5cbiAgLy8gYmVmb3JlIGEgbGF0ZXIgc2FtZS10b2tlbiBob29rJ3MgY3JlYXRpb24gaXMgdmFsaWRhdGVkIOKAlCBvdGhlcndpc2UgdGhlXG4gIC8vIG5ldyBob29rIHJlY29yZHMgYSBzcHVyaW91cyBob29rX2NvbmZsaWN0IGFnYWluc3QgdGhlIHJ1bidzIG93blxuICAvLyBkaXNwb3NlZCBob29rIOKAlCB3aGlsZSBhIGhvb2sgY3JlYXRlZCBhbmQgZGlzcG9zZWQgd2l0aGluIHRoZSBzYW1lXG4gIC8vIHN1c3BlbnNpb24gaXMgc3RpbGwgY3JlYXRlZCBiZWZvcmUgaXQgaXMgZGlzcG9zZWQuIERpZmZlcmVudCB0b2tlbnNcbiAgLy8gaGF2ZSBubyBjbGFpbSBpbnRlcmFjdGlvbiwgc28gdG9rZW4gZ3JvdXBzIGFyZSBwcm9jZXNzZWQgaW4gcGFyYWxsZWwuXG4gIGNvbnN0IGhvb2tJdGVtc0J5VG9rZW4gPSBuZXcgTWFwPHN0cmluZywgSG9va0ludm9jYXRpb25RdWV1ZUl0ZW1bXT4oKTtcbiAgZm9yIChjb25zdCBpdGVtIG9mIGFsbEhvb2tJdGVtcykge1xuICAgIGlmIChpdGVtLmhhc0NyZWF0ZWRFdmVudCAmJiAhaXRlbS5kaXNwb3NlZCkge1xuICAgICAgY29udGludWU7IC8vIGFscmVhZHkgY29tbWl0dGVkIGFuZCBzdGlsbCBsaXZlIOKAlCBub3RoaW5nIHRvIGRvXG4gICAgfVxuICAgIGNvbnN0IGdyb3VwID0gaG9va0l0ZW1zQnlUb2tlbi5nZXQoaXRlbS50b2tlbik7XG4gICAgaWYgKGdyb3VwKSB7XG4gICAgICBncm91cC5wdXNoKGl0ZW0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBob29rSXRlbXNCeVRva2VuLnNldChpdGVtLnRva2VuLCBbaXRlbV0pO1xuICAgIH1cbiAgfVxuXG4gIC8vIFJlc29sdmUgZW5jcnlwdGlvbiBrZXkgZm9yIHRoaXMgcnVuXG4gIGNvbnN0IHJhd0tleSA9IGF3YWl0IHdvcmxkLmdldEVuY3J5cHRpb25LZXlGb3JSdW4/LihydW4pO1xuICBjb25zdCBlbmNyeXB0aW9uS2V5ID0gcmF3S2V5ID8gYXdhaXQgaW1wb3J0S2V5KHJhd0tleSkgOiB1bmRlZmluZWQ7XG5cbiAgLy8gR2F0ZSBwYXlsb2FkIGNvbXByZXNzaW9uIG9uIHRoZSBydW4ncyBzcGVjVmVyc2lvbi5cbiAgY29uc3QgY29tcHJlc3Npb24gPVxuICAgIChydW4uc3BlY1ZlcnNpb24gPz8gMCkgPj0gU1BFQ19WRVJTSU9OX1NVUFBPUlRTX0NPTVBSRVNTSU9OO1xuXG4gIGFzeW5jIGZ1bmN0aW9uIGRpc3Bvc2VIb29rKFxuICAgIHF1ZXVlSXRlbTogSG9va0ludm9jYXRpb25RdWV1ZUl0ZW1cbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgaG9va0Rpc3Bvc2VkRXZlbnQ6IENyZWF0ZUV2ZW50UmVxdWVzdCA9IHtcbiAgICAgIGV2ZW50VHlwZTogJ2hvb2tfZGlzcG9zZWQnIGFzIGNvbnN0LFxuICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICBldmVudERhdGE6IHtcbiAgICAgICAgdG9rZW46IHF1ZXVlSXRlbS50b2tlbixcbiAgICAgIH0sXG4gICAgfTtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgY3JlYXRlR3VhcmRlZChob29rRGlzcG9zZWRFdmVudCwgeyByZXF1ZXN0SWQgfSk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgIC8vIEhvb2sgd2FzIGFscmVhZHkgZGlzcG9zZWQgYnkgYSBjb25jdXJyZW50IGludm9jYXRpb24g4oCUIHNhZmUgdG8gc2tpcFxuICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgJ0hvb2sgYWxyZWFkeSBkaXNwb3NlZCwgc2tpcHBpbmcgZHVwbGljYXRlIGRpc3Bvc2FsJyxcbiAgICAgICAgICB7XG4gICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgfSBlbHNlIGlmIChSdW5FeHBpcmVkRXJyb3IuaXMoZXJyKSkge1xuICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgJ1dvcmtmbG93IHJ1biBhbHJlYWR5IGNvbXBsZXRlZCwgc2tpcHBpbmcgaG9vayBkaXNwb3NhbCcsXG4gICAgICAgICAge1xuICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSBpZiAoSG9va05vdEZvdW5kRXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAvLyBIb29rIG1heSBoYXZlIGFscmVhZHkgYmVlbiBkaXNwb3NlZCBvciBuZXZlciBjcmVhdGVkXG4gICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbygnSG9vayBub3QgZm91bmQgZm9yIGRpc3Bvc2FsLCBjb250aW51aW5nJywge1xuICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBQcm9jZXNzIGhvb2tzIGZpcnN0IHRvIHByZXZlbnQgcmFjZSBjb25kaXRpb25zIHdpdGggd2ViaG9vayByZWNlaXZlcnMuXG4gIC8vIFRyYWNrIGFueSBob29rIGNvbmZsaWN0cyB0aGF0IG9jY3VyIOKAlCB0aGVzZSBhcmUgcmV0dXJuZWQgdG8gdGhlIGNhbGxlclxuICAvLyBzbyB0aGUgVjIgaGFuZGxlciBjYW4gcmUtaW52b2tlIGltbWVkaWF0ZWx5LlxuICBsZXQgaGFzSG9va0NvbmZsaWN0ID0gZmFsc2U7XG4gIGxldCBoYXNBd2FpdGVkSG9va0NyZWF0aW9uID0gZmFsc2U7XG4gIGxldCBob29rQ3JlYXRpb25NcyA9IDA7XG5cbiAgaWYgKGhvb2tJdGVtc0J5VG9rZW4uc2l6ZSA+IDApIHtcbiAgICBjb25zdCBob29rUGhhc2VTdGFydCA9IERhdGUubm93KCk7XG4gICAgYXdhaXQgZW5zdXJlUnVuUmVhZHkoKTtcbiAgICBhd2FpdCBzZXR0bGVQaGFzZShcbiAgICAgIFsuLi5ob29rSXRlbXNCeVRva2VuLnZhbHVlcygpXS5tYXAoYXN5bmMgKGl0ZW1zKSA9PiB7XG4gICAgICAgIGZvciAoY29uc3QgcXVldWVJdGVtIG9mIGl0ZW1zKSB7XG4gICAgICAgICAgbGV0IGNyZWF0aW9uQ29uZmxpY3RlZCA9IGZhbHNlO1xuXG4gICAgICAgICAgaWYgKCFxdWV1ZUl0ZW0uaGFzQ3JlYXRlZEV2ZW50KSB7XG4gICAgICAgICAgICBjb25zdCBob29rTWV0YWRhdGE6IFNlcmlhbGl6ZWREYXRhIHwgdW5kZWZpbmVkID1cbiAgICAgICAgICAgICAgdHlwZW9mIHF1ZXVlSXRlbS5tZXRhZGF0YSA9PT0gJ3VuZGVmaW5lZCdcbiAgICAgICAgICAgICAgICA/IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgIDogKChhd2FpdCBkZWh5ZHJhdGVTdGVwQXJndW1lbnRzKFxuICAgICAgICAgICAgICAgICAgICBxdWV1ZUl0ZW0ubWV0YWRhdGEsXG4gICAgICAgICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICBlbmNyeXB0aW9uS2V5LFxuICAgICAgICAgICAgICAgICAgICBzdXNwZW5zaW9uLmdsb2JhbFRoaXMsXG4gICAgICAgICAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBjb21wcmVzc2lvblxuICAgICAgICAgICAgICAgICAgKSkgYXMgU2VyaWFsaXplZERhdGEpO1xuICAgICAgICAgICAgY29uc3QgaG9va0V2ZW50OiBDcmVhdGVFdmVudFJlcXVlc3QgPSB7XG4gICAgICAgICAgICAgIGV2ZW50VHlwZTogJ2hvb2tfY3JlYXRlZCcgYXMgY29uc3QsXG4gICAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgIHRva2VuOiBxdWV1ZUl0ZW0udG9rZW4sXG4gICAgICAgICAgICAgICAgdG9rZW5SZXRlbnRpb25VbnRpbDogcXVldWVJdGVtLnRva2VuUmV0ZW50aW9uVW50aWwsXG4gICAgICAgICAgICAgICAgbWV0YWRhdGE6IGhvb2tNZXRhZGF0YSxcbiAgICAgICAgICAgICAgICBpc1dlYmhvb2s6IHF1ZXVlSXRlbS5pc1dlYmhvb2sgPz8gZmFsc2UsXG4gICAgICAgICAgICAgICAgLi4uKHF1ZXVlSXRlbS5pc1N5c3RlbSAmJiB7IGlzU3lzdGVtOiB0cnVlIH0pLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNyZWF0ZUhvb2tFdmVudCh7XG4gICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICBob29rRXZlbnQsXG4gICAgICAgICAgICAgIHF1ZXVlSXRlbSxcbiAgICAgICAgICAgICAgcmVxdWVzdElkLFxuICAgICAgICAgICAgICBjcmVhdGVFdmVudDogY3JlYXRlR3VhcmRlZCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaGFzSG9va0NvbmZsaWN0IHx8PSByZXN1bHQuaGFzSG9va0NvbmZsaWN0O1xuICAgICAgICAgICAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbiB8fD0gcmVzdWx0Lmhhc0F3YWl0ZWRIb29rQ3JlYXRpb247XG4gICAgICAgICAgICBjcmVhdGlvbkNvbmZsaWN0ZWQgPSByZXN1bHQuaGFzSG9va0NvbmZsaWN0O1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIERpc3Bvc2UgYWZ0ZXIgY3JlYXRpb24gZm9yIGhvb2tzIGJvcm4gYW5kIGRpc3Bvc2VkIHdpdGhpbiB0aGlzXG4gICAgICAgICAgLy8gYmF0Y2guIEEgaG9vayB3aG9zZSBjcmVhdGlvbiBjb25mbGljdGVkIHdhcyBuZXZlciBjcmVhdGVkLCBzb1xuICAgICAgICAgIC8vIHRoZXJlIGlzIG5vdGhpbmcgdG8gZGlzcG9zZS5cbiAgICAgICAgICBpZiAocXVldWVJdGVtLmRpc3Bvc2VkICYmICFjcmVhdGlvbkNvbmZsaWN0ZWQpIHtcbiAgICAgICAgICAgIGF3YWl0IGRpc3Bvc2VIb29rKHF1ZXVlSXRlbSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KVxuICAgICk7XG4gICAgaG9va0NyZWF0aW9uTXMgPSBEYXRlLm5vdygpIC0gaG9va1BoYXNlU3RhcnQ7XG4gIH1cblxuICAvLyBQcm9jZXNzIGFib3J0IHJlcXVlc3RzIOKAlCByZXN1bWUgdGhlIGhvb2sgd2l0aCBhYm9ydCBwYXlsb2FkIGFuZCB3cml0ZSBzdHJlYW0gcGFja2V0XG4gIGNvbnN0IGhvb2tzTmVlZGluZ0Fib3J0ID0gYWxsSG9va0l0ZW1zLmZpbHRlcihcbiAgICAoaXRlbSkgPT4gaXRlbS5hYm9ydFJlcXVlc3RlZCAmJiAhaXRlbS5kaXNwb3NlZFxuICApO1xuXG4gIGlmIChob29rc05lZWRpbmdBYm9ydC5sZW5ndGggPiAwKSB7XG4gICAgYXdhaXQgZW5zdXJlUnVuUmVhZHkoKTtcbiAgICBhd2FpdCBzZXR0bGVQaGFzZShcbiAgICAgIGhvb2tzTmVlZGluZ0Fib3J0Lm1hcChhc3luYyAocXVldWVJdGVtKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgLy8gRGVoeWRyYXRlIHRoZSBhYm9ydCBwYXlsb2FkIGZvciBzdG9yYWdlXG4gICAgICAgICAgY29uc3QgYWJvcnRQYXlsb2FkID0gYXdhaXQgZGVoeWRyYXRlU3RlcEFyZ3VtZW50cyhcbiAgICAgICAgICAgIHsgYWJvcnRlZDogdHJ1ZSwgcmVhc29uOiBxdWV1ZUl0ZW0uYWJvcnRSZWFzb24gfSxcbiAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgICAgICAgIHN1c3BlbnNpb24uZ2xvYmFsVGhpcyxcbiAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgY29tcHJlc3Npb25cbiAgICAgICAgICApO1xuXG4gICAgICAgICAgLy8gQ3JlYXRlIGhvb2tfcmVjZWl2ZWQgZXZlbnQgd2l0aCBhYm9ydCBwYXlsb2FkXG4gICAgICAgICAgYXdhaXQgY3JlYXRlR3VhcmRlZCh7XG4gICAgICAgICAgICBldmVudFR5cGU6ICdob29rX3JlY2VpdmVkJyBhcyBjb25zdCxcbiAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgIHRva2VuOiBxdWV1ZUl0ZW0udG9rZW4sXG4gICAgICAgICAgICAgIHBheWxvYWQ6IGFib3J0UGF5bG9hZCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICAvLyBXcml0ZSBzdHJlYW0gY2FuY2VsbGF0aW9uIHBhY2tldCBmb3IgcmVhbC10aW1lIHN0ZXAgcHJvcGFnYXRpb24uXG4gICAgICAgICAgLy8gUmV1c2UgdGhlIHNhbWUgZGVoeWRyYXRlZCBwYXlsb2FkIGFzIHRoZSBob29rIGV2ZW50IHNvIHRoZSByZWFzb25cbiAgICAgICAgICAvLyByb3VuZC10cmlwcyB0aHJvdWdoIGBkZWh5ZHJhdGVTdGVwQXJndW1lbnRzYCAvIGBoeWRyYXRlU3RlcEFyZ3VtZW50c2BcbiAgICAgICAgICAvLyAoaGFuZGxlcyBET01FeGNlcHRpb24sIGN1c3RvbSBlcnJvcnMsIGVuY3J5cHRpb24sIGV0Yy4pIGluc3RlYWQgb2ZcbiAgICAgICAgICAvLyBiYXJlIEpTT04uc3RyaW5naWZ5IHdoaWNoIGxvc2VzIHR5cGUgaW5mb3JtYXRpb24gYW5kIGRyb3BzIHVuZGVmaW5lZC5cbiAgICAgICAgICAvLyBzdHJlYW1OYW1lIGlzIHNldCBvbiB0aGUgcXVldWUgaXRlbSBhdCBjb250cm9sbGVyIGNvbnN0cnVjdGlvbiB0aW1lXG4gICAgICAgICAgLy8gKHNlZSB3b3JrZmxvdy9hYm9ydC1jb250cm9sbGVyLnRzKS5cbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtTmFtZSA9IGdldEFib3J0U3RyZWFtSWRGcm9tVG9rZW4ocXVldWVJdGVtLnRva2VuKTtcbiAgICAgICAgICAgIGF3YWl0IHdvcmxkLnN0cmVhbXMud3JpdGUoXG4gICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICBzdHJlYW1OYW1lLFxuICAgICAgICAgICAgICBhYm9ydFBheWxvYWQgYXMgVWludDhBcnJheVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGF3YWl0IHdvcmxkLnN0cmVhbXMuY2xvc2UocnVuSWQsIHN0cmVhbU5hbWUpO1xuICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgLy8gQmVzdC1lZmZvcnQgc3RyZWFtIHdyaXRlIOKAlCBob29rIGV2ZW50IHByb3ZpZGVzIHRoZSBkdXJhYmxlIGZhbGxiYWNrXG4gICAgICAgICAgICBydW50aW1lTG9nZ2VyLmRlYnVnKFxuICAgICAgICAgICAgICAnRmFpbGVkIHRvIHdyaXRlIGFib3J0IHN0cmVhbSBwYWNrZXQsIGhvb2sgZXZlbnQgd2lsbCBwcm92aWRlIGZhbGxiYWNrJyxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSB8fCBSdW5FeHBpcmVkRXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAnV29ya2Zsb3cgcnVuIGFscmVhZHkgY29tcGxldGVkLCBza2lwcGluZyBhYm9ydCcsXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgLy8gQ3JlYXRlIHN0ZXAgZXZlbnRzIGZvciBzdGVwcyB0aGF0IGRvbid0IGhhdmUgdGhlbSB5ZXQuXG4gIC8vIFVubGlrZSBWMSwgd2UgZG8gTk9UIHF1ZXVlIHN0ZXAgbWVzc2FnZXMgZnJvbSBoZXJlIOKAlCB0aGUgY2FsbGVyXG4gIC8vIGRlY2lkZXMgd2hpY2ggc3RlcHMgdG8gZXhlY3V0ZSBpbmxpbmUgdnMuIHF1ZXVlIHRvIGJhY2tncm91bmQuXG4gIC8vIFdhaXQgZXZlbnRzIGFyZSBhbHNvIGNyZWF0ZWQgaW4gcGFyYWxsZWwgYmVsb3cuXG4gIGNvbnN0IHN0ZXBzTmVlZGluZ0NyZWF0aW9uID0gbmV3IFNldChcbiAgICBzdGVwSXRlbXNcbiAgICAgIC5maWx0ZXIoKHF1ZXVlSXRlbSkgPT4gIXF1ZXVlSXRlbS5oYXNDcmVhdGVkRXZlbnQpXG4gICAgICAubWFwKChxdWV1ZUl0ZW0pID0+IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKVxuICApO1xuXG4gIC8vIENvcnJlbGF0aW9uIElEcyBmb3Igd2hpY2ggVEhJUyBzdXNwZW5zaW9uIGNhbGwgYWN0dWFsbHkgd3JvdGUgdGhlXG4gIC8vIHN0ZXBfY3JlYXRlZCBldmVudC4gUG9wdWxhdGVkIGJ5IHRoZSBvcHMgYmVsb3cgYWZ0ZXIgYSBzdWNjZXNzZnVsXG4gIC8vIGV2ZW50cy5jcmVhdGUg4oCUIHVzZWQgYnkgdGhlIGNhbGxlciB0byBjbGFpbSBvd25lcnNoaXAgYW5kIGF2b2lkXG4gIC8vIHJhY2luZyB3aXRoIGNvbmN1cnJlbnQgaGFuZGxlcnMgb24gc3RlcCBleGVjdXRpb24uXG4gIGNvbnN0IGNyZWF0ZWRTdGVwQ29ycmVsYXRpb25JZHMgPSBuZXcgU2V0PHN0cmluZz4oKTtcblxuICAvLyBTZXJpYWxpemF0aW9uIGFsd2F5cyBydW5zIHRocm91Z2ggdGhlIG9uZSBvcmRpbmFyeSBwYXRoIGJlbG93LCBzbyB0aGVcbiAgLy8gZHVyYWJsZSBieXRlcyBjYW5ub3QgZGVwZW5kIG9uIHJldGVudGlvbi4gV2hhdCByZXRlbnRpb24gbmVlZHMgdG8ga25vdyBpc1xuICAvLyB3aGV0aGVyIHRoYXQgc2VyaWFsaXphdGlvbiAqZXhlY3V0ZWQqIHdvcmtmbG93IGNvZGUgKGdldHRlcnMsIHByb3h5XG4gIC8vIHRyYXBzLCBjdXN0b20gc2VyaWFsaXplcnMpIOKAlCBzaWRlIGVmZmVjdHMgYSBjb2xkIHJlcGxheSB3b3VsZCBub3RcbiAgLy8gcmVwZWF0LCBzaW5jZSBhIHJlcGxheSBza2lwcyBkZWh5ZHJhdGlvbiBmb3IgYWxyZWFkeS1yZWNvcmRlZCBzdGVwcy5cbiAgLy8gVGhlIGhhcmRlbmVkIHNlcmlhbGl6ZXIgcmVjb3JkcyBleGFjdGx5IHRoYXQgaW50byB0aGlzIHNpbmsgKHNlZVxuICAvLyAuLi9zZXJpYWxpemF0aW9uL2hhcmRlbmVkLnRzKTsgd2hlbiBhbnkgaW5wdXQgaW4gdGhlIGJhdGNoIHJlY29yZHMgYW5cbiAgLy8gZXhlY3V0aW9uLCB0aGUgY2FsbGVyIGRlbW90ZXMgdGhlIHNlc3Npb24gc28gdGhlIHNpZGUgZWZmZWN0cyBsYW5kIGluIGFcbiAgLy8gVk0gdGhhdCBpcyBhYm91dCB0byBiZSBkaXNjYXJkZWQsIGV4YWN0bHkgbGlrZSB0aGUgcHJlLXJldGVudGlvblxuICAvLyBydW50aW1lLlxuICBjb25zdCBndWVzdENvZGVTdGF0czogR3Vlc3RDb2RlU3RhdHMgPSB7IGV4ZWN1dGlvbnM6IFtdIH07XG5cbiAgLy8gTGF6eSBpbmxpbmUgc3RhcnQ6IGRlZmVyIHRoZSBzdGVwX2NyZWF0ZWQgd3JpdGUgZm9yIHVwIHRvXG4gIC8vIGBnZXRNYXhJbmxpbmVTdGVwcygpYCBzdGVwcyB0aGUgY2FsbGVyIHdpbGwgcnVuIGlubGluZSAoaW4gcGFyYWxsZWwpLiBFYWNoXG4gIC8vIHN0ZXAgaXMgY3JlYXRlZCBvbiB0aGUgZmx5IGJ5IHRoZSBsYXp5IGBzdGVwX3N0YXJ0ZWRgIGV4ZWN1dGVTdGVwIHNlbmRzXG4gIC8vIChzYXZpbmcgYSByb3VuZC10cmlwIHBlciBzdGVwKS4gV2UgbmV2ZXIgZGVmZXIgd2hlbiBhIGBob29rLmdldENvbmZsaWN0KClgXG4gIC8vIGF3YWl0ZXIgaXMgcHJlc2VudCwgYmVjYXVzZSBpbiB0aGF0IGNhc2UgdGhlIGNhbGxlciBleGVjdXRlcyBub3RoaW5nIGlubGluZVxuICAvLyAoaXQgcmUtaW52b2tlcyBpbW1lZGlhdGVseSB0byByZXNvbHZlIHRoZSBhd2FpdGVyKSwgc28gZGVmZXJyaW5nIHdvdWxkXG4gIC8vIGxlYXZlIHRoZSBzdGVwcyB1bmNyZWF0ZWQgYW5kIHVucXVldWVkLiBXZSBwaWNrIHRoZSBmaXJzdCBOIHVuY3JlYXRlZCBzdGVwc1xuICAvLyDigJQgbWF0Y2hpbmcgdGhlIGNhbGxlcidzIGlubGluZS1jYW5kaWRhdGUgc2VsZWN0aW9uIOKAlCBhbmQgZGVoeWRyYXRlIHRoZWlyXG4gIC8vIGlucHV0IGhlcmUgc28gZXhlY3V0ZVN0ZXAgY2FuIHNoaXAgaXQgYXMgdGhlIHN0ZXBfc3RhcnRlZCBwYXlsb2FkLlxuICBjb25zdCBsYXp5SW5saW5lQ29ycmVsYXRpb25JZHMgPSBuZXcgU2V0PHN0cmluZz4oXG4gICAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbiA9PT0gZmFsc2VcbiAgICAgID8gc3RlcEl0ZW1zXG4gICAgICAgICAgLmZpbHRlcigoaXRlbSkgPT4gc3RlcHNOZWVkaW5nQ3JlYXRpb24uaGFzKGl0ZW0uY29ycmVsYXRpb25JZCkpXG4gICAgICAgICAgLnNsaWNlKDAsIGdldE1heElubGluZVN0ZXBzKCkpXG4gICAgICAgICAgLm1hcCgoaXRlbSkgPT4gaXRlbS5jb3JyZWxhdGlvbklkKVxuICAgICAgOiBbXVxuICApO1xuICAvLyBDb2xsZWN0ZWQgYnkgY29ycmVsYXRpb25JZCBiZWNhdXNlIHRoZSBwZXItc3RlcCBvcHMgYmVsb3cgcnVuIGNvbmN1cnJlbnRseVxuICAvLyBhbmQgc2V0dGxlIG91dCBvZiBvcmRlci4gV2UgcmVidWlsZCB0aGUgYXJyYXkgaW4gZGV0ZXJtaW5pc3RpY1xuICAvLyBgbGF6eUlubGluZUNvcnJlbGF0aW9uSWRzYCBvcmRlciAodGhlIG9yZGVyZWQgc2xpY2UgYWJvdmUpIGFmdGVyIHRoZSBvcHNcbiAgLy8gc2V0dGxlLCBzbyB0aGUgaW5saW5lIGJhdGNoIG9yZGVyIGlzIHN0YWJsZSByZWdhcmRsZXNzIG9mIGRlaHlkcmF0aW9uIHRpbWluZy5cbiAgY29uc3QgbGF6eUlubGluZUJ5Q29ycmVsYXRpb25JZCA9IG5ldyBNYXA8XG4gICAgc3RyaW5nLFxuICAgIFN1c3BlbnNpb25IYW5kbGVyUmVzdWx0WydsYXp5SW5saW5lU3RlcHMnXVtudW1iZXJdXG4gID4oKTtcblxuICBjb25zdCBvcHM6IFByb21pc2U8dm9pZD5bXSA9IFtdO1xuXG4gIC8vIFN0ZXBzOiBjcmVhdGUgc3RlcF9jcmVhdGVkIGV2ZW50cyAobm8gcXVldWluZyDigJQgVjIgcmV0dXJucyBwZW5kaW5nIHN0ZXBzIHRvIGNhbGxlcilcbiAgZm9yIChjb25zdCBxdWV1ZUl0ZW0gb2Ygc3RlcEl0ZW1zKSB7XG4gICAgaWYgKHN0ZXBzTmVlZGluZ0NyZWF0aW9uLmhhcyhxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCkpIHtcbiAgICAgIG9wcy5wdXNoKFxuICAgICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIC8vIFBlci1zdGVwIHNpbmssIG1lcmdlZCBiZWxvdzogdGhlIGRlaHlkcmF0ZSB3cmFwcGVyIGVtaXRzIHNwYW5cbiAgICAgICAgICAvLyBhdHRyaWJ1dGVzIGZyb20gdGhlIHNpbmsgaXQgaXMgaGFuZGVkLCBzbyBzaGFyaW5nIG9uZSBhY3Jvc3NcbiAgICAgICAgICAvLyBzdGVwcyB3b3VsZCByZS1lbWl0IChhbmQgbWlzYXR0cmlidXRlKSBlYXJsaWVyIHN0ZXBzJyBlbnRyaWVzLlxuICAgICAgICAgIGNvbnN0IHN0ZXBHdWVzdENvZGU6IEd1ZXN0Q29kZVN0YXRzID0geyBleGVjdXRpb25zOiBbXSB9O1xuICAgICAgICAgIGNvbnN0IGRlaHlkcmF0ZWRJbnB1dCA9IGF3YWl0IGRlaHlkcmF0ZVN0ZXBBcmd1bWVudHMoXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGFyZ3M6IHF1ZXVlSXRlbS5hcmdzLFxuICAgICAgICAgICAgICBjbG9zdXJlVmFyczogcXVldWVJdGVtLmNsb3N1cmVWYXJzLFxuICAgICAgICAgICAgICB0aGlzVmFsOiBxdWV1ZUl0ZW0udGhpc1ZhbCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgIGVuY3J5cHRpb25LZXksXG4gICAgICAgICAgICBzdXNwZW5zaW9uLmdsb2JhbFRoaXMsXG4gICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgIGNvbXByZXNzaW9uLFxuICAgICAgICAgICAgc3RlcEd1ZXN0Q29kZVxuICAgICAgICAgICk7XG4gICAgICAgICAgZ3Vlc3RDb2RlU3RhdHMuZXhlY3V0aW9ucy5wdXNoKC4uLnN0ZXBHdWVzdENvZGUuZXhlY3V0aW9ucyk7XG4gICAgICAgICAgLy8gRGVmZXJyZWQgKGxhenkpIGlubGluZSBzdGVwOiBza2lwIHRoZSBzdGVwX2NyZWF0ZWQgd3JpdGUg4oCUIHRoZVxuICAgICAgICAgIC8vIGNhbGxlcidzIGlubGluZSBleGVjdXRlU3RlcCB3aWxsIHNlbmQgYSBsYXp5IHN0ZXBfc3RhcnRlZCBjYXJyeWluZ1xuICAgICAgICAgIC8vIHRoaXMgaW5wdXQsIGFuZCB0aGUgd29ybGQgY3JlYXRlcyB0aGUgc3RlcCAoZW50aXR5ICsgc3ludGhldGljXG4gICAgICAgICAgLy8gc3RlcF9jcmVhdGVkIGV2ZW50KSBhdG9taWNhbGx5LiBXZSBkbyBOT1QgYWRkIGl0IHRvXG4gICAgICAgICAgLy8gY3JlYXRlZFN0ZXBDb3JyZWxhdGlvbklkczsgb3duZXJzaGlwIGlzIGRlY2lkZWQgYnkgdGhhdCBsYXp5XG4gICAgICAgICAgLy8gc3RlcF9zdGFydGVkJ3MgYXRvbWljIGNyZWF0ZS1jbGFpbSBpbnN0ZWFkLlxuICAgICAgICAgIGlmIChsYXp5SW5saW5lQ29ycmVsYXRpb25JZHMuaGFzKHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKSkge1xuICAgICAgICAgICAgbGF6eUlubGluZUJ5Q29ycmVsYXRpb25JZC5zZXQocXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsIHtcbiAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgIHN0ZXBOYW1lOiBxdWV1ZUl0ZW0uc3RlcE5hbWUsXG4gICAgICAgICAgICAgIGRlaHlkcmF0ZWRJbnB1dDogZGVoeWRyYXRlZElucHV0IGFzIFNlcmlhbGl6ZWREYXRhLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IHN0ZXBFdmVudDogQ3JlYXRlRXZlbnRSZXF1ZXN0ID0ge1xuICAgICAgICAgICAgZXZlbnRUeXBlOiAnc3RlcF9jcmVhdGVkJyBhcyBjb25zdCxcbiAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgIHN0ZXBOYW1lOiBxdWV1ZUl0ZW0uc3RlcE5hbWUsXG4gICAgICAgICAgICAgIHdvcmtmbG93TmFtZTogcnVuLndvcmtmbG93TmFtZSxcbiAgICAgICAgICAgICAgaW5wdXQ6IGRlaHlkcmF0ZWRJbnB1dCBhcyBTZXJpYWxpemVkRGF0YSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfTtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgZW5zdXJlUnVuUmVhZHkoKTtcbiAgICAgICAgICAgIGF3YWl0IGNyZWF0ZUd1YXJkZWQoc3RlcEV2ZW50LCB7IHJlcXVlc3RJZCB9KTtcbiAgICAgICAgICAgIGNyZWF0ZWRTdGVwQ29ycmVsYXRpb25JZHMuYWRkKHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKTtcbiAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKCdTdGVwIGFscmVhZHkgZXhpc3RzLCBjb250aW51aW5nJywge1xuICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pKClcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLy8gQ3JlYXRlIHdhaXQgZXZlbnRzIChzYW1lIGFzIFYxKVxuICBmb3IgKGNvbnN0IHF1ZXVlSXRlbSBvZiB3YWl0SXRlbXMpIHtcbiAgICBpZiAoIXF1ZXVlSXRlbS5oYXNDcmVhdGVkRXZlbnQpIHtcbiAgICAgIG9wcy5wdXNoKFxuICAgICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHdhaXRFdmVudDogQ3JlYXRlRXZlbnRSZXF1ZXN0ID0ge1xuICAgICAgICAgICAgZXZlbnRUeXBlOiAnd2FpdF9jcmVhdGVkJyBhcyBjb25zdCxcbiAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgIHJlc3VtZUF0OiBxdWV1ZUl0ZW0ucmVzdW1lQXQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH07XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IGVuc3VyZVJ1blJlYWR5KCk7XG4gICAgICAgICAgICBhd2FpdCBjcmVhdGVHdWFyZGVkKHdhaXRFdmVudCwgeyByZXF1ZXN0SWQgfSk7XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbygnV2FpdCBhbHJlYWR5IGV4aXN0cywgY29udGludWluZycsIHtcbiAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9KSgpXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIGZvciAoY29uc3QgcXVldWVJdGVtIG9mIGF0dHJpYnV0ZUl0ZW1zKSB7XG4gICAgb3BzLnB1c2goXG4gICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IGVuc3VyZVJ1blJlYWR5KCk7XG4gICAgICAgICAgLy8gR3VhcmRlZCBsaWtlIGV2ZXJ5IG90aGVyIHN1c3BlbnNpb24gd3JpdGU6IGFuIGF0dHJfc2V0IGlzIGFcbiAgICAgICAgICAvLyByZXBsYXktZGVyaXZlZCBldmVudCB3aXRoIGEgY29ycmVsYXRpb24gaWQgZnJvbSB0aGlzIHJlcGxheSdzXG4gICAgICAgICAgLy8gc2VlZGVkIHNlcXVlbmNlLCBzbyBpdCBtdXN0IG5vdCBsYW5kIG9uIGEgbG9nIHRoZSByZXBsYXkgbmV2ZXJcbiAgICAgICAgICAvLyBzYXcuIFJlamVjdGluZyBpdCBpcyBjaGVhcCDigJQgYSBydW4gd2l0aCBhdHRyaWJ1dGUgZXZlbnRzIGFscmVhZHlcbiAgICAgICAgICAvLyBmb3JjZXMgYW4gaW4tcHJvY2VzcyByZXBsYXksIHNvIHRoZSByZXN0YXJ0IGNvc3RzIHRoZSByZXBsYXkgaXRcbiAgICAgICAgICAvLyB3YXMgZ29pbmcgdG8gZG8gYW55d2F5LlxuICAgICAgICAgIGF3YWl0IGNyZWF0ZUd1YXJkZWQoXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGV2ZW50VHlwZTogJ2F0dHJfc2V0JyxcbiAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgICAgY2hhbmdlczogcXVldWVJdGVtLmNoYW5nZXMsXG4gICAgICAgICAgICAgICAgd3JpdGVyOiB7IHR5cGU6ICd3b3JrZmxvdycgfSxcbiAgICAgICAgICAgICAgICAuLi4ocXVldWVJdGVtLmFsbG93UmVzZXJ2ZWRBdHRyaWJ1dGVzXG4gICAgICAgICAgICAgICAgICA/IHsgYWxsb3dSZXNlcnZlZEF0dHJpYnV0ZXM6IHRydWUgfVxuICAgICAgICAgICAgICAgICAgOiB7fSksXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgeyByZXF1ZXN0SWQgfVxuICAgICAgICAgICk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgJ1dvcmtmbG93IGF0dHJpYnV0ZSBldmVudCBhbHJlYWR5IGV4aXN0cywgY29udGludWluZycsXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGlzV29ybGRWYWxpZGF0aW9uRmFpbHVyZShlcnIpKSB7XG4gICAgICAgICAgICAvLyBEZXRlcm1pbmlzdGljIHZhbGlkYXRpb24gcmVqZWN0aW9uIGZyb20gdGhlIFdvcmxkIOKAlCBlLmcuIHRoZVxuICAgICAgICAgICAgLy8gY3VtdWxhdGl2ZSBwZXItcnVuIGF0dHJpYnV0ZSBjYXAsIHdoaWNoIG9ubHkgdGhlIFdvcmxkIGNhblxuICAgICAgICAgICAgLy8gY2hlY2sgYWdhaW5zdCB0aGUgcnVuJ3MgZXhpc3RpbmcgYXR0cmlidXRlcy4gUmVkZWxpdmVyaW5nIHRoZVxuICAgICAgICAgICAgLy8gb3JjaGVzdHJhdG9yIG1lc3NhZ2UgcmVwbGF5cyB0aGUgd29ya2Zsb3cgaW50byB0aGUgZXhhY3Qgc2FtZVxuICAgICAgICAgICAgLy8gd3JpdGUgYW5kIHRoZSBleGFjdCBzYW1lIHJlamVjdGlvbiwgc28gcmV0cnlpbmcgY2FuIG5ldmVyXG4gICAgICAgICAgICAvLyBzdWNjZWVkLiBTdXJmYWNlIGl0IGFzIGEgRmF0YWxFcnJvciBzbyB0aGUgY2FsbGVyIGZhaWxzIHRoZVxuICAgICAgICAgICAgLy8gcnVuIHdpdGggYSBjbGVhciBlcnJvciBpbnN0ZWFkIG9mIHdlZGdpbmcgaXQgaW4gcmVkZWxpdmVyeS5cbiAgICAgICAgICAgIGNvbnN0IGZhdGFsID0gbmV3IEZhdGFsRXJyb3IoXG4gICAgICAgICAgICAgIGBzZXRBdHRyaWJ1dGVzIGZhaWxlZCBXb3JsZCB2YWxpZGF0aW9uOiAke1xuICAgICAgICAgICAgICAgIGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKVxuICAgICAgICAgICAgICB9YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGZhdGFsLmNhdXNlID0gZXJyO1xuICAgICAgICAgICAgdGhyb3cgZmF0YWw7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pKClcbiAgICApO1xuICB9XG5cbiAgLy8gQXdhaXQgdGhlIHN0ZXBfY3JlYXRlZCAvIHdhaXRfY3JlYXRlZCBldmVudCBjcmVhdGVzIGJlZm9yZSByZXR1cm5pbmcuXG4gIC8vIFRoZSBjYWxsZXIgKHdvcmtmbG93RW50cnlwb2ludCkgb25seSBlbnF1ZXVlcyB0aGUgc3RlcC1kaXNwYXRjaCBxdWV1ZVxuICAvLyBtZXNzYWdlcyBBRlRFUiBoYW5kbGVTdXNwZW5zaW9uIHJlc29sdmVzLCBhbmQgdGhlIHF1ZXVlIGhhbmRsZXIgYWNrc1xuICAvLyB0aGUgb3JjaGVzdHJhdG9yIG1lc3NhZ2Ugb25seSBhZnRlciB0aGUgY2FsbGVyIHJlc29sdmVzLiBTbyB0aGUgc3RlcF9jcmVhdGVkXG4gIC8vIGV2ZW50cyBtdXN0IGJlIGR1cmFibGUgaGVyZSwgYW5kIHRoZSBkaXNwYXRjaCBzZW5kcyBtdXN0IGNvbXBsZXRlIGluIHRoZSBjYWxsZXIsXG4gIC8vIGFsbCBiZWZvcmUgYWNrLiBJZiB0aGUgcHJvY2VzcyBjcmFzaGVzIGJlZm9yZSB0aGlzIHJlc29sdmVzLCB0aGUgb3JjaGVzdHJhdG9yXG4gIC8vIG1lc3NhZ2UgaXMgbm90IGFja2VkIGFuZCBWUVMgcmVkZWxpdmVycywgcmUtY3JlYXRlcyB0aGUgKGlkZW1wb3RlbnQpXG4gIC8vIHN0ZXBfY3JlYXRlZCBhbmQgcmUtZGlzcGF0Y2hlcywgYW5kIHJlY292ZXJzIHRoZSBydW4gaW5zdGVhZCBvZiBvcnBoYW5pbmcgaXQuXG4gIGF3YWl0IHNldHRsZVBoYXNlKG9wcyk7XG5cbiAgLy8gVGhlIHN0ZXAtaW5wdXQgZGVoeWRyYXRpb25zIGFib3ZlIGhhdmUgc2V0dGxlZCwgc28gdGhlIHNpbmsgaXMgZmluYWwuXG4gIGNvbnN0IHJldGFpbmVkU3RlcElucHV0c1NhZmUgPSBndWVzdENvZGVTdGF0cy5leGVjdXRpb25zLmxlbmd0aCA9PT0gMDtcbiAgaWYgKCFyZXRhaW5lZFN0ZXBJbnB1dHNTYWZlKSB7XG4gICAgcnVudGltZUxvZ2dlci5kZWJ1ZyhcbiAgICAgICdTZXJpYWxpemluZyBzdGVwIGlucHV0cyBleGVjdXRlZCB3b3JrZmxvdyBjb2RlOyBmYWxsaW5nIGJhY2sgdG8gcmVwbGF5IGluc3RlYWQgb2YgcmV0YWluaW5nIHRoZSBWTScsXG4gICAgICB7XG4gICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICBleGVjdXRpb25zOiBndWVzdENvZGVTdGF0cy5leGVjdXRpb25zXG4gICAgICAgICAgLnNsaWNlKDAsIDUpXG4gICAgICAgICAgLm1hcCgoZSkgPT4gKGUuZGV0YWlsID8gYCR7ZS5raW5kfSgke2UuZGV0YWlsfSlgIDogZS5raW5kKSksXG4gICAgICB9XG4gICAgKTtcbiAgfVxuXG4gIC8vIFJlYnVpbGQgdGhlIGlubGluZSBiYXRjaCBpbiBkZXRlcm1pbmlzdGljIG9yZGVyLiBgbGF6eUlubGluZUNvcnJlbGF0aW9uSWRzYFxuICAvLyBpcyBhIFNldCBzZWVkZWQgZnJvbSB0aGUgb3JkZXJlZCBmaXJzdC1OIHNsaWNlLCBzbyBpdGVyYXRpbmcgaXQgcHJlc2VydmVzXG4gIC8vIHN0ZXBJdGVtcyBvcmRlcjsgZXZlcnkgaWQgaW4gaXQgd2FzIHNldCBieSB0aGUgbGF6eSBicmFuY2ggYWJvdmUuXG4gIGNvbnN0IGxhenlJbmxpbmVTdGVwczogU3VzcGVuc2lvbkhhbmRsZXJSZXN1bHRbJ2xhenlJbmxpbmVTdGVwcyddID0gW107XG4gIGZvciAoY29uc3QgY29ycmVsYXRpb25JZCBvZiBsYXp5SW5saW5lQ29ycmVsYXRpb25JZHMpIHtcbiAgICBjb25zdCBsYXp5U3RlcCA9IGxhenlJbmxpbmVCeUNvcnJlbGF0aW9uSWQuZ2V0KGNvcnJlbGF0aW9uSWQpO1xuICAgIGlmIChsYXp5U3RlcCkgbGF6eUlubGluZVN0ZXBzLnB1c2gobGF6eVN0ZXApO1xuICB9XG5cbiAgLy8gRmluZCB0aGUgc29vbmVzdCBwZW5kaW5nIHdhaXQgKG1pbmltdW0gdGltZW91dClcbiAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgbGV0IHNvb25lc3RXYWl0OiB7IHNlY29uZHM6IG51bWJlcjsgY29ycmVsYXRpb25JZDogc3RyaW5nIH0gfCB1bmRlZmluZWQ7XG4gIGZvciAoY29uc3QgcXVldWVJdGVtIG9mIHdhaXRJdGVtcykge1xuICAgIGNvbnN0IHJlc3VtZUF0TXMgPSBxdWV1ZUl0ZW0ucmVzdW1lQXQuZ2V0VGltZSgpO1xuICAgIGNvbnN0IGRlbGF5TXMgPSBNYXRoLm1heCgxMDAwLCByZXN1bWVBdE1zIC0gbm93KTtcbiAgICBjb25zdCB0aW1lb3V0U2Vjb25kcyA9IE1hdGguY2VpbChkZWxheU1zIC8gMTAwMCk7XG4gICAgaWYgKCFzb29uZXN0V2FpdCB8fCB0aW1lb3V0U2Vjb25kcyA8IHNvb25lc3RXYWl0LnNlY29uZHMpIHtcbiAgICAgIHNvb25lc3RXYWl0ID0ge1xuICAgICAgICBzZWNvbmRzOiB0aW1lb3V0U2Vjb25kcyxcbiAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1J1blN0YXR1cygnd29ya2Zsb3dfc3VzcGVuZGVkJyksXG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93U3RlcHNDcmVhdGVkKHN0ZXBJdGVtcy5sZW5ndGgpLFxuICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd0hvb2tzQ3JlYXRlZChob29rc05lZWRpbmdDcmVhdGlvbi5sZW5ndGgpLFxuICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1dhaXRzQ3JlYXRlZCh3YWl0SXRlbXMubGVuZ3RoKSxcbiAgfSk7XG5cbiAgcmV0dXJuIHtcbiAgICBwZW5kaW5nU3RlcHM6IHN0ZXBJdGVtcyxcbiAgICBjcmVhdGVkU3RlcENvcnJlbGF0aW9uSWRzLFxuICAgIGxhenlJbmxpbmVTdGVwcyxcbiAgICAvLyBPbiBob29rIGNvbmZsaWN0IHRoZSBjYWxsZXIgcmUtaW52b2tlcyBpbW1lZGlhdGVseSBhbmQgbmV2ZXIgcmVhZHNcbiAgICAvLyB0aGUgd2FpdCB0aW1lb3V0LCBzbyBkb24ndCByZXBvcnQgb25lLlxuICAgIHdhaXRUaW1lb3V0OiBoYXNIb29rQ29uZmxpY3QgPyB1bmRlZmluZWQgOiBzb29uZXN0V2FpdCxcbiAgICBoYXNIb29rQ29uZmxpY3QsXG4gICAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbixcbiAgICBoYXNBdHRyaWJ1dGVFdmVudHM6IGF0dHJpYnV0ZUl0ZW1zLmxlbmd0aCA+IDAsXG4gICAgaGFzSG9va0V2ZW50czogaG9va3NOZWVkaW5nQ3JlYXRpb24ubGVuZ3RoID4gMCxcbiAgICBob29rQ3JlYXRpb25NcyxcbiAgICByZXRhaW5lZFN0ZXBJbnB1dHNTYWZlLFxuICAgIHJlcG9ydGVkRXZlbnRDb3VudDogcmVwb3J0ZWRFdmVudHMsXG4gIH07XG59XG5cbi8qKlxuICogV2hldGhlciBhbiBgZXZlbnRzLmNyZWF0ZWAgcmVqZWN0aW9uIGlzIGRldGVybWluaXN0aWMgV29ybGQgdmFsaWRhdGlvblxuICogcmF0aGVyIHRoYW4gYSB0cmFuc2llbnQvc3RvcmFnZSBlcnJvci4gTG9jYWwgV29ybGRzXG4gKiAod29ybGQtbG9jYWwsIHdvcmxkLXBvc3RncmVzKSB0aHJvdyBgQXR0cmlidXRlVmFsaWRhdGlvbkVycm9yYCBkaXJlY3RseTtcbiAqIHJlbW90ZSBXb3JsZHMgc3VyZmFjZSB0aGUgZXF1aXZhbGVudCBzZXJ2ZXItc2lkZSByZWplY3Rpb24gYXMgYVxuICogYFdvcmtmbG93V29ybGRFcnJvcmAgd2l0aCBIVFRQIHN0YXR1cyA0MDAuIFRoZSBuYW1lIGNoZWNrIGNvdmVyc1xuICogYEF0dHJpYnV0ZVZhbGlkYXRpb25FcnJvcmAgaW5zdGFuY2VzIGZyb20gYSBkaWZmZXJlbnQgY29weSBvZlxuICogYEB3b3JrZmxvdy93b3JsZGAgdGhhbiB0aGUgb25lIHRoaXMgcGFja2FnZSByZXNvbHZlZC5cbiAqL1xuZnVuY3Rpb24gaXNXb3JsZFZhbGlkYXRpb25GYWlsdXJlKGVycjogdW5rbm93bik6IGJvb2xlYW4ge1xuICBpZiAoZXJyIGluc3RhbmNlb2YgQXR0cmlidXRlVmFsaWRhdGlvbkVycm9yKSByZXR1cm4gdHJ1ZTtcbiAgaWYgKGVyciBpbnN0YW5jZW9mIEVycm9yICYmIGVyci5uYW1lID09PSAnQXR0cmlidXRlVmFsaWRhdGlvbkVycm9yJykge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIHJldHVybiBXb3JrZmxvd1dvcmxkRXJyb3IuaXMoZXJyKSAmJiBlcnIuc3RhdHVzID09PSA0MDA7XG59XG4iXX0=