@smthrs/flow 0.0.0-stage → 1.0.0-rc.3

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 (654) hide show
  1. package/CHANGELOG.md +160 -0
  2. package/LICENSE +21 -0
  3. package/README.md +210 -2
  4. package/THIRD_PARTY_NOTICES.md +52 -0
  5. package/dist/cjs/Action/Action.d.ts +250 -0
  6. package/dist/cjs/Action/Action.d.ts.map +1 -0
  7. package/dist/cjs/Action/Action.js +42 -0
  8. package/dist/cjs/Action/Action.js.map +7 -0
  9. package/dist/cjs/Action/AttemptTimedOut.d.ts +33 -0
  10. package/dist/cjs/Action/AttemptTimedOut.d.ts.map +1 -0
  11. package/dist/cjs/Action/AttemptTimedOut.js +51 -0
  12. package/dist/cjs/Action/AttemptTimedOut.js.map +7 -0
  13. package/dist/cjs/Action/BoundaryMode.d.ts +29 -0
  14. package/dist/cjs/Action/BoundaryMode.d.ts.map +1 -0
  15. package/dist/cjs/Action/BoundaryMode.js +36 -0
  16. package/dist/cjs/Action/BoundaryMode.js.map +7 -0
  17. package/dist/cjs/Action/CacheEnvironment.d.ts +158 -0
  18. package/dist/cjs/Action/CacheEnvironment.d.ts.map +1 -0
  19. package/dist/cjs/Action/CacheEnvironment.js +57 -0
  20. package/dist/cjs/Action/CacheEnvironment.js.map +7 -0
  21. package/dist/cjs/Action/ConcurrentKeylessDispatch.d.ts +34 -0
  22. package/dist/cjs/Action/ConcurrentKeylessDispatch.d.ts.map +1 -0
  23. package/dist/cjs/Action/ConcurrentKeylessDispatch.js +46 -0
  24. package/dist/cjs/Action/ConcurrentKeylessDispatch.js.map +7 -0
  25. package/dist/cjs/Action/Context.d.ts +131 -0
  26. package/dist/cjs/Action/Context.d.ts.map +1 -0
  27. package/dist/cjs/Action/Context.js +68 -0
  28. package/dist/cjs/Action/Context.js.map +7 -0
  29. package/dist/cjs/Action/DuplicateImplementation.d.ts +20 -0
  30. package/dist/cjs/Action/DuplicateImplementation.d.ts.map +1 -0
  31. package/dist/cjs/Action/DuplicateImplementation.js +46 -0
  32. package/dist/cjs/Action/DuplicateImplementation.js.map +7 -0
  33. package/dist/cjs/Action/FileBoundary.d.ts +59 -0
  34. package/dist/cjs/Action/FileBoundary.d.ts.map +1 -0
  35. package/dist/cjs/Action/FileBoundary.js +81 -0
  36. package/dist/cjs/Action/FileBoundary.js.map +7 -0
  37. package/dist/cjs/Action/FileInput.d.ts +28 -0
  38. package/dist/cjs/Action/FileInput.d.ts.map +1 -0
  39. package/dist/cjs/Action/FileInput.js +42 -0
  40. package/dist/cjs/Action/FileInput.js.map +7 -0
  41. package/dist/cjs/Action/Filegroup.d.ts +16 -0
  42. package/dist/cjs/Action/Filegroup.d.ts.map +1 -0
  43. package/dist/cjs/Action/Filegroup.js +27 -0
  44. package/dist/cjs/Action/Filegroup.js.map +7 -0
  45. package/dist/cjs/Action/Glob.d.ts +8 -0
  46. package/dist/cjs/Action/Glob.d.ts.map +1 -0
  47. package/dist/cjs/Action/Glob.js +28 -0
  48. package/dist/cjs/Action/Glob.js.map +7 -0
  49. package/dist/cjs/Action/ImplementationVersionMismatch.d.ts +26 -0
  50. package/dist/cjs/Action/ImplementationVersionMismatch.d.ts.map +1 -0
  51. package/dist/cjs/Action/ImplementationVersionMismatch.js +45 -0
  52. package/dist/cjs/Action/ImplementationVersionMismatch.js.map +7 -0
  53. package/dist/cjs/Action/Implementations.d.ts +114 -0
  54. package/dist/cjs/Action/Implementations.d.ts.map +1 -0
  55. package/dist/cjs/Action/Implementations.js +65 -0
  56. package/dist/cjs/Action/Implementations.js.map +7 -0
  57. package/dist/cjs/Action/InfraInterrupt.d.ts +26 -0
  58. package/dist/cjs/Action/InfraInterrupt.d.ts.map +1 -0
  59. package/dist/cjs/Action/InfraInterrupt.js +46 -0
  60. package/dist/cjs/Action/InfraInterrupt.js.map +7 -0
  61. package/dist/cjs/Action/InfraInterruptRetriesExhausted.d.ts +33 -0
  62. package/dist/cjs/Action/InfraInterruptRetriesExhausted.d.ts.map +1 -0
  63. package/dist/cjs/Action/InfraInterruptRetriesExhausted.js +54 -0
  64. package/dist/cjs/Action/InfraInterruptRetriesExhausted.js.map +7 -0
  65. package/dist/cjs/Action/IrreversibleRetryRequiresIdempotencyKey.d.ts +26 -0
  66. package/dist/cjs/Action/IrreversibleRetryRequiresIdempotencyKey.d.ts.map +1 -0
  67. package/dist/cjs/Action/IrreversibleRetryRequiresIdempotencyKey.js +47 -0
  68. package/dist/cjs/Action/IrreversibleRetryRequiresIdempotencyKey.js.map +7 -0
  69. package/dist/cjs/Action/StepIdentity.d.ts +153 -0
  70. package/dist/cjs/Action/StepIdentity.d.ts.map +1 -0
  71. package/dist/cjs/Action/StepIdentity.js +75 -0
  72. package/dist/cjs/Action/StepIdentity.js.map +7 -0
  73. package/dist/cjs/Action/TreeArtifact.d.ts +8 -0
  74. package/dist/cjs/Action/TreeArtifact.d.ts.map +1 -0
  75. package/dist/cjs/Action/TreeArtifact.js +25 -0
  76. package/dist/cjs/Action/TreeArtifact.js.map +7 -0
  77. package/dist/cjs/Action/TypeId.d.ts +8 -0
  78. package/dist/cjs/Action/TypeId.d.ts.map +1 -0
  79. package/dist/cjs/Action/TypeId.js +25 -0
  80. package/dist/cjs/Action/TypeId.js.map +7 -0
  81. package/dist/cjs/Action/UncanonicalIdempotencyKey.d.ts +32 -0
  82. package/dist/cjs/Action/UncanonicalIdempotencyKey.d.ts.map +1 -0
  83. package/dist/cjs/Action/UncanonicalIdempotencyKey.js +51 -0
  84. package/dist/cjs/Action/UncanonicalIdempotencyKey.js.map +7 -0
  85. package/dist/cjs/Action/idempotencyKey.d.ts +21 -0
  86. package/dist/cjs/Action/idempotencyKey.d.ts.map +1 -0
  87. package/dist/cjs/Action/idempotencyKey.js +59 -0
  88. package/dist/cjs/Action/idempotencyKey.js.map +7 -0
  89. package/dist/cjs/Action/index.d.ts +29 -0
  90. package/dist/cjs/Action/index.d.ts.map +1 -0
  91. package/dist/cjs/Action/index.js +60 -0
  92. package/dist/cjs/Action/index.js.map +7 -0
  93. package/dist/cjs/Action/make.d.ts +128 -0
  94. package/dist/cjs/Action/make.d.ts.map +1 -0
  95. package/dist/cjs/Action/make.js +373 -0
  96. package/dist/cjs/Action/make.js.map +7 -0
  97. package/dist/cjs/Action/raceAll.d.ts +21 -0
  98. package/dist/cjs/Action/raceAll.d.ts.map +1 -0
  99. package/dist/cjs/Action/raceAll.js +46 -0
  100. package/dist/cjs/Action/raceAll.js.map +7 -0
  101. package/dist/cjs/Action/retry.d.ts +19 -0
  102. package/dist/cjs/Action/retry.d.ts.map +1 -0
  103. package/dist/cjs/Action/retry.js +75 -0
  104. package/dist/cjs/Action/retry.js.map +7 -0
  105. package/dist/cjs/Deadline.d.ts +105 -0
  106. package/dist/cjs/Deadline.d.ts.map +1 -0
  107. package/dist/cjs/Deadline.js +104 -0
  108. package/dist/cjs/Deadline.js.map +7 -0
  109. package/dist/cjs/DurableClock.d.ts +61 -0
  110. package/dist/cjs/DurableClock.d.ts.map +1 -0
  111. package/dist/cjs/DurableClock.js +90 -0
  112. package/dist/cjs/DurableClock.js.map +7 -0
  113. package/dist/cjs/DurableDeferred.d.ts +311 -0
  114. package/dist/cjs/DurableDeferred.d.ts.map +1 -0
  115. package/dist/cjs/DurableDeferred.js +322 -0
  116. package/dist/cjs/DurableDeferred.js.map +7 -0
  117. package/dist/cjs/DurableQueue.d.ts +160 -0
  118. package/dist/cjs/DurableQueue.d.ts.map +1 -0
  119. package/dist/cjs/DurableQueue.js +229 -0
  120. package/dist/cjs/DurableQueue.js.map +7 -0
  121. package/dist/cjs/ExternalJob.d.ts +179 -0
  122. package/dist/cjs/ExternalJob.d.ts.map +1 -0
  123. package/dist/cjs/ExternalJob.js +338 -0
  124. package/dist/cjs/ExternalJob.js.map +7 -0
  125. package/dist/cjs/Fault.d.ts +131 -0
  126. package/dist/cjs/Fault.d.ts.map +1 -0
  127. package/dist/cjs/Fault.js +157 -0
  128. package/dist/cjs/Fault.js.map +7 -0
  129. package/dist/cjs/Flow/Annotations.d.ts +245 -0
  130. package/dist/cjs/Flow/Annotations.d.ts.map +1 -0
  131. package/dist/cjs/Flow/Annotations.js +72 -0
  132. package/dist/cjs/Flow/Annotations.js.map +7 -0
  133. package/dist/cjs/Flow/CapabilityCeiling.d.ts +21 -0
  134. package/dist/cjs/Flow/CapabilityCeiling.d.ts.map +1 -0
  135. package/dist/cjs/Flow/CapabilityCeiling.js +49 -0
  136. package/dist/cjs/Flow/CapabilityCeiling.js.map +7 -0
  137. package/dist/cjs/Flow/DeadlineExceeded.d.ts +33 -0
  138. package/dist/cjs/Flow/DeadlineExceeded.d.ts.map +1 -0
  139. package/dist/cjs/Flow/DeadlineExceeded.js +52 -0
  140. package/dist/cjs/Flow/DeadlineExceeded.js.map +7 -0
  141. package/dist/cjs/Flow/ExecutionIdRequired.d.ts +25 -0
  142. package/dist/cjs/Flow/ExecutionIdRequired.d.ts.map +1 -0
  143. package/dist/cjs/Flow/ExecutionIdRequired.js +46 -0
  144. package/dist/cjs/Flow/ExecutionIdRequired.js.map +7 -0
  145. package/dist/cjs/Flow/ExecutionIds.d.ts +80 -0
  146. package/dist/cjs/Flow/ExecutionIds.d.ts.map +1 -0
  147. package/dist/cjs/Flow/ExecutionIds.js +66 -0
  148. package/dist/cjs/Flow/ExecutionIds.js.map +7 -0
  149. package/dist/cjs/Flow/Flow.d.ts +422 -0
  150. package/dist/cjs/Flow/Flow.d.ts.map +1 -0
  151. package/dist/cjs/Flow/Flow.js +17 -0
  152. package/dist/cjs/Flow/Flow.js.map +7 -0
  153. package/dist/cjs/Flow/MaxRoundsExceeded.d.ts +35 -0
  154. package/dist/cjs/Flow/MaxRoundsExceeded.d.ts.map +1 -0
  155. package/dist/cjs/Flow/MaxRoundsExceeded.js +50 -0
  156. package/dist/cjs/Flow/MaxRoundsExceeded.js.map +7 -0
  157. package/dist/cjs/Flow/Outcome.d.ts +162 -0
  158. package/dist/cjs/Flow/Outcome.d.ts.map +1 -0
  159. package/dist/cjs/Flow/Outcome.js +80 -0
  160. package/dist/cjs/Flow/Outcome.js.map +7 -0
  161. package/dist/cjs/Flow/Result.d.ts +186 -0
  162. package/dist/cjs/Flow/Result.d.ts.map +1 -0
  163. package/dist/cjs/Flow/Result.js +159 -0
  164. package/dist/cjs/Flow/Result.js.map +7 -0
  165. package/dist/cjs/Flow/Runtime.d.ts +98 -0
  166. package/dist/cjs/Flow/Runtime.d.ts.map +1 -0
  167. package/dist/cjs/Flow/Runtime.js +160 -0
  168. package/dist/cjs/Flow/Runtime.js.map +7 -0
  169. package/dist/cjs/Flow/TypeId.d.ts +8 -0
  170. package/dist/cjs/Flow/TypeId.d.ts.map +1 -0
  171. package/dist/cjs/Flow/TypeId.js +25 -0
  172. package/dist/cjs/Flow/TypeId.js.map +7 -0
  173. package/dist/cjs/Flow/index.d.ts +17 -0
  174. package/dist/cjs/Flow/index.d.ts.map +1 -0
  175. package/dist/cjs/Flow/index.js +29 -0
  176. package/dist/cjs/Flow/index.js.map +7 -0
  177. package/dist/cjs/Flow/internal.d.ts +34 -0
  178. package/dist/cjs/Flow/internal.d.ts.map +1 -0
  179. package/dist/cjs/Flow/internal.js +187 -0
  180. package/dist/cjs/Flow/internal.js.map +7 -0
  181. package/dist/cjs/Flow/make.d.ts +134 -0
  182. package/dist/cjs/Flow/make.d.ts.map +1 -0
  183. package/dist/cjs/Flow/make.js +104 -0
  184. package/dist/cjs/Flow/make.js.map +7 -0
  185. package/dist/cjs/FlowRuntime/CancelRequestFailed.d.ts +55 -0
  186. package/dist/cjs/FlowRuntime/CancelRequestFailed.d.ts.map +1 -0
  187. package/dist/cjs/FlowRuntime/CancelRequestFailed.js +51 -0
  188. package/dist/cjs/FlowRuntime/CancelRequestFailed.js.map +7 -0
  189. package/dist/cjs/FlowRuntime/ExecutionIdentityConflict.d.ts +23 -0
  190. package/dist/cjs/FlowRuntime/ExecutionIdentityConflict.d.ts.map +1 -0
  191. package/dist/cjs/FlowRuntime/ExecutionIdentityConflict.js +55 -0
  192. package/dist/cjs/FlowRuntime/ExecutionIdentityConflict.js.map +7 -0
  193. package/dist/cjs/FlowRuntime/FlowCycleDetected.d.ts +28 -0
  194. package/dist/cjs/FlowRuntime/FlowCycleDetected.d.ts.map +1 -0
  195. package/dist/cjs/FlowRuntime/FlowCycleDetected.js +49 -0
  196. package/dist/cjs/FlowRuntime/FlowCycleDetected.js.map +7 -0
  197. package/dist/cjs/FlowRuntime/FlowExecutionNotFound.d.ts +38 -0
  198. package/dist/cjs/FlowRuntime/FlowExecutionNotFound.d.ts.map +1 -0
  199. package/dist/cjs/FlowRuntime/FlowExecutionNotFound.js +53 -0
  200. package/dist/cjs/FlowRuntime/FlowExecutionNotFound.js.map +7 -0
  201. package/dist/cjs/FlowRuntime/FlowInstance.d.ts +115 -0
  202. package/dist/cjs/FlowRuntime/FlowInstance.d.ts.map +1 -0
  203. package/dist/cjs/FlowRuntime/FlowInstance.js +37 -0
  204. package/dist/cjs/FlowRuntime/FlowInstance.js.map +7 -0
  205. package/dist/cjs/FlowRuntime/FlowRuntime.d.ts +198 -0
  206. package/dist/cjs/FlowRuntime/FlowRuntime.d.ts.map +1 -0
  207. package/dist/cjs/FlowRuntime/FlowRuntime.js +37 -0
  208. package/dist/cjs/FlowRuntime/FlowRuntime.js.map +7 -0
  209. package/dist/cjs/FlowRuntime/NodeRecord.d.ts +175 -0
  210. package/dist/cjs/FlowRuntime/NodeRecord.d.ts.map +1 -0
  211. package/dist/cjs/FlowRuntime/NodeRecord.js +17 -0
  212. package/dist/cjs/FlowRuntime/NodeRecord.js.map +7 -0
  213. package/dist/cjs/FlowRuntime/WaitingAnnotation.d.ts +69 -0
  214. package/dist/cjs/FlowRuntime/WaitingAnnotation.d.ts.map +1 -0
  215. package/dist/cjs/FlowRuntime/WaitingAnnotation.js +53 -0
  216. package/dist/cjs/FlowRuntime/WaitingAnnotation.js.map +7 -0
  217. package/dist/cjs/FlowRuntime/index.d.ts +14 -0
  218. package/dist/cjs/FlowRuntime/index.d.ts.map +1 -0
  219. package/dist/cjs/FlowRuntime/index.js +26 -0
  220. package/dist/cjs/FlowRuntime/index.js.map +7 -0
  221. package/dist/cjs/Graph.d.ts +325 -0
  222. package/dist/cjs/Graph.d.ts.map +1 -0
  223. package/dist/cjs/Graph.js +1022 -0
  224. package/dist/cjs/Graph.js.map +7 -0
  225. package/dist/cjs/HumanTask.d.ts +440 -0
  226. package/dist/cjs/HumanTask.d.ts.map +1 -0
  227. package/dist/cjs/HumanTask.js +413 -0
  228. package/dist/cjs/HumanTask.js.map +7 -0
  229. package/dist/cjs/Interpreter.d.ts +222 -0
  230. package/dist/cjs/Interpreter.d.ts.map +1 -0
  231. package/dist/cjs/Interpreter.js +888 -0
  232. package/dist/cjs/Interpreter.js.map +7 -0
  233. package/dist/cjs/Poll.d.ts +238 -0
  234. package/dist/cjs/Poll.d.ts.map +1 -0
  235. package/dist/cjs/Poll.js +150 -0
  236. package/dist/cjs/Poll.js.map +7 -0
  237. package/dist/cjs/RetryPolicy.d.ts +273 -0
  238. package/dist/cjs/RetryPolicy.d.ts.map +1 -0
  239. package/dist/cjs/RetryPolicy.js +251 -0
  240. package/dist/cjs/RetryPolicy.js.map +7 -0
  241. package/dist/cjs/Sleep.d.ts +98 -0
  242. package/dist/cjs/Sleep.d.ts.map +1 -0
  243. package/dist/cjs/Sleep.js +133 -0
  244. package/dist/cjs/Sleep.js.map +7 -0
  245. package/dist/cjs/Stall.d.ts +173 -0
  246. package/dist/cjs/Stall.d.ts.map +1 -0
  247. package/dist/cjs/Stall.js +92 -0
  248. package/dist/cjs/Stall.js.map +7 -0
  249. package/dist/cjs/WaitFor.d.ts +109 -0
  250. package/dist/cjs/WaitFor.d.ts.map +1 -0
  251. package/dist/cjs/WaitFor.js +117 -0
  252. package/dist/cjs/WaitFor.js.map +7 -0
  253. package/dist/cjs/index.d.ts +107 -0
  254. package/dist/cjs/index.d.ts.map +1 -0
  255. package/dist/cjs/index.js +69 -0
  256. package/dist/cjs/index.js.map +7 -0
  257. package/dist/cjs/internal/BoundedJson.d.ts +48 -0
  258. package/dist/cjs/internal/BoundedJson.d.ts.map +1 -0
  259. package/dist/cjs/internal/BoundedJson.js +96 -0
  260. package/dist/cjs/internal/BoundedJson.js.map +7 -0
  261. package/dist/cjs/internal/DeclarationSite.d.ts +135 -0
  262. package/dist/cjs/internal/DeclarationSite.d.ts.map +1 -0
  263. package/dist/cjs/internal/DeclarationSite.js +89 -0
  264. package/dist/cjs/internal/DeclarationSite.js.map +7 -0
  265. package/dist/cjs/internal/Declarations.d.ts +35 -0
  266. package/dist/cjs/internal/Declarations.d.ts.map +1 -0
  267. package/dist/cjs/internal/Declarations.js +50 -0
  268. package/dist/cjs/internal/Declarations.js.map +7 -0
  269. package/dist/cjs/internal/ExecutionMiddleware.d.ts +21 -0
  270. package/dist/cjs/internal/ExecutionMiddleware.d.ts.map +1 -0
  271. package/dist/cjs/internal/ExecutionMiddleware.js +39 -0
  272. package/dist/cjs/internal/ExecutionMiddleware.js.map +7 -0
  273. package/dist/cjs/internal/JsonSchemaSubset.d.ts +133 -0
  274. package/dist/cjs/internal/JsonSchemaSubset.d.ts.map +1 -0
  275. package/dist/cjs/internal/JsonSchemaSubset.js +229 -0
  276. package/dist/cjs/internal/JsonSchemaSubset.js.map +7 -0
  277. package/dist/cjs/internal/OutcomeMarker.d.ts +18 -0
  278. package/dist/cjs/internal/OutcomeMarker.d.ts.map +1 -0
  279. package/dist/cjs/internal/OutcomeMarker.js +27 -0
  280. package/dist/cjs/internal/OutcomeMarker.js.map +7 -0
  281. package/dist/cjs/package.json +1 -0
  282. package/dist/esm/Action/Action.d.ts +250 -0
  283. package/dist/esm/Action/Action.d.ts.map +1 -0
  284. package/dist/esm/Action/Action.js +30 -0
  285. package/dist/esm/Action/Action.js.map +1 -0
  286. package/dist/esm/Action/AttemptTimedOut.d.ts +33 -0
  287. package/dist/esm/Action/AttemptTimedOut.d.ts.map +1 -0
  288. package/dist/esm/Action/AttemptTimedOut.js +32 -0
  289. package/dist/esm/Action/AttemptTimedOut.js.map +1 -0
  290. package/dist/esm/Action/BoundaryMode.d.ts +29 -0
  291. package/dist/esm/Action/BoundaryMode.d.ts.map +1 -0
  292. package/dist/esm/Action/BoundaryMode.js +23 -0
  293. package/dist/esm/Action/BoundaryMode.js.map +1 -0
  294. package/dist/esm/Action/CacheEnvironment.d.ts +158 -0
  295. package/dist/esm/Action/CacheEnvironment.d.ts.map +1 -0
  296. package/dist/esm/Action/CacheEnvironment.js +130 -0
  297. package/dist/esm/Action/CacheEnvironment.js.map +1 -0
  298. package/dist/esm/Action/ConcurrentKeylessDispatch.d.ts +34 -0
  299. package/dist/esm/Action/ConcurrentKeylessDispatch.d.ts.map +1 -0
  300. package/dist/esm/Action/ConcurrentKeylessDispatch.js +33 -0
  301. package/dist/esm/Action/ConcurrentKeylessDispatch.js.map +1 -0
  302. package/dist/esm/Action/Context.d.ts +131 -0
  303. package/dist/esm/Action/Context.d.ts.map +1 -0
  304. package/dist/esm/Action/Context.js +99 -0
  305. package/dist/esm/Action/Context.js.map +1 -0
  306. package/dist/esm/Action/DuplicateImplementation.d.ts +20 -0
  307. package/dist/esm/Action/DuplicateImplementation.d.ts.map +1 -0
  308. package/dist/esm/Action/DuplicateImplementation.js +20 -0
  309. package/dist/esm/Action/DuplicateImplementation.js.map +1 -0
  310. package/dist/esm/Action/FileBoundary.d.ts +59 -0
  311. package/dist/esm/Action/FileBoundary.d.ts.map +1 -0
  312. package/dist/esm/Action/FileBoundary.js +60 -0
  313. package/dist/esm/Action/FileBoundary.js.map +1 -0
  314. package/dist/esm/Action/FileInput.d.ts +28 -0
  315. package/dist/esm/Action/FileInput.d.ts.map +1 -0
  316. package/dist/esm/Action/FileInput.js +32 -0
  317. package/dist/esm/Action/FileInput.js.map +1 -0
  318. package/dist/esm/Action/Filegroup.d.ts +16 -0
  319. package/dist/esm/Action/Filegroup.d.ts.map +1 -0
  320. package/dist/esm/Action/Filegroup.js +15 -0
  321. package/dist/esm/Action/Filegroup.js.map +1 -0
  322. package/dist/esm/Action/Glob.d.ts +8 -0
  323. package/dist/esm/Action/Glob.d.ts.map +1 -0
  324. package/dist/esm/Action/Glob.js +7 -0
  325. package/dist/esm/Action/Glob.js.map +1 -0
  326. package/dist/esm/Action/ImplementationVersionMismatch.d.ts +26 -0
  327. package/dist/esm/Action/ImplementationVersionMismatch.d.ts.map +1 -0
  328. package/dist/esm/Action/ImplementationVersionMismatch.js +24 -0
  329. package/dist/esm/Action/ImplementationVersionMismatch.js.map +1 -0
  330. package/dist/esm/Action/Implementations.d.ts +114 -0
  331. package/dist/esm/Action/Implementations.d.ts.map +1 -0
  332. package/dist/esm/Action/Implementations.js +94 -0
  333. package/dist/esm/Action/Implementations.js.map +1 -0
  334. package/dist/esm/Action/InfraInterrupt.d.ts +26 -0
  335. package/dist/esm/Action/InfraInterrupt.d.ts.map +1 -0
  336. package/dist/esm/Action/InfraInterrupt.js +25 -0
  337. package/dist/esm/Action/InfraInterrupt.js.map +1 -0
  338. package/dist/esm/Action/InfraInterruptRetriesExhausted.d.ts +33 -0
  339. package/dist/esm/Action/InfraInterruptRetriesExhausted.d.ts.map +1 -0
  340. package/dist/esm/Action/InfraInterruptRetriesExhausted.js +32 -0
  341. package/dist/esm/Action/InfraInterruptRetriesExhausted.js.map +1 -0
  342. package/dist/esm/Action/IrreversibleRetryRequiresIdempotencyKey.d.ts +26 -0
  343. package/dist/esm/Action/IrreversibleRetryRequiresIdempotencyKey.d.ts.map +1 -0
  344. package/dist/esm/Action/IrreversibleRetryRequiresIdempotencyKey.js +25 -0
  345. package/dist/esm/Action/IrreversibleRetryRequiresIdempotencyKey.js.map +1 -0
  346. package/dist/esm/Action/StepIdentity.d.ts +153 -0
  347. package/dist/esm/Action/StepIdentity.d.ts.map +1 -0
  348. package/dist/esm/Action/StepIdentity.js +139 -0
  349. package/dist/esm/Action/StepIdentity.js.map +1 -0
  350. package/dist/esm/Action/TreeArtifact.d.ts +8 -0
  351. package/dist/esm/Action/TreeArtifact.d.ts.map +1 -0
  352. package/dist/esm/Action/TreeArtifact.js +7 -0
  353. package/dist/esm/Action/TreeArtifact.js.map +1 -0
  354. package/dist/esm/Action/TypeId.d.ts +8 -0
  355. package/dist/esm/Action/TypeId.d.ts.map +1 -0
  356. package/dist/esm/Action/TypeId.js +9 -0
  357. package/dist/esm/Action/TypeId.js.map +1 -0
  358. package/dist/esm/Action/UncanonicalIdempotencyKey.d.ts +32 -0
  359. package/dist/esm/Action/UncanonicalIdempotencyKey.d.ts.map +1 -0
  360. package/dist/esm/Action/UncanonicalIdempotencyKey.js +31 -0
  361. package/dist/esm/Action/UncanonicalIdempotencyKey.js.map +1 -0
  362. package/dist/esm/Action/idempotencyKey.d.ts +21 -0
  363. package/dist/esm/Action/idempotencyKey.d.ts.map +1 -0
  364. package/dist/esm/Action/idempotencyKey.js +50 -0
  365. package/dist/esm/Action/idempotencyKey.js.map +1 -0
  366. package/dist/esm/Action/index.d.ts +29 -0
  367. package/dist/esm/Action/index.d.ts.map +1 -0
  368. package/dist/esm/Action/index.js +30 -0
  369. package/dist/esm/Action/index.js.map +1 -0
  370. package/dist/esm/Action/make.d.ts +128 -0
  371. package/dist/esm/Action/make.d.ts.map +1 -0
  372. package/dist/esm/Action/make.js +405 -0
  373. package/dist/esm/Action/make.js.map +1 -0
  374. package/dist/esm/Action/raceAll.d.ts +21 -0
  375. package/dist/esm/Action/raceAll.d.ts.map +1 -0
  376. package/dist/esm/Action/raceAll.js +20 -0
  377. package/dist/esm/Action/raceAll.js.map +1 -0
  378. package/dist/esm/Action/retry.d.ts +19 -0
  379. package/dist/esm/Action/retry.d.ts.map +1 -0
  380. package/dist/esm/Action/retry.js +72 -0
  381. package/dist/esm/Action/retry.js.map +1 -0
  382. package/dist/esm/Deadline.d.ts +105 -0
  383. package/dist/esm/Deadline.d.ts.map +1 -0
  384. package/dist/esm/Deadline.js +152 -0
  385. package/dist/esm/Deadline.js.map +1 -0
  386. package/dist/esm/DurableClock.d.ts +61 -0
  387. package/dist/esm/DurableClock.d.ts.map +1 -0
  388. package/dist/esm/DurableClock.js +75 -0
  389. package/dist/esm/DurableClock.js.map +1 -0
  390. package/dist/esm/DurableDeferred.d.ts +311 -0
  391. package/dist/esm/DurableDeferred.d.ts.map +1 -0
  392. package/dist/esm/DurableDeferred.js +357 -0
  393. package/dist/esm/DurableDeferred.js.map +1 -0
  394. package/dist/esm/DurableQueue.d.ts +160 -0
  395. package/dist/esm/DurableQueue.d.ts.map +1 -0
  396. package/dist/esm/DurableQueue.js +303 -0
  397. package/dist/esm/DurableQueue.js.map +1 -0
  398. package/dist/esm/ExternalJob.d.ts +179 -0
  399. package/dist/esm/ExternalJob.d.ts.map +1 -0
  400. package/dist/esm/ExternalJob.js +296 -0
  401. package/dist/esm/ExternalJob.js.map +1 -0
  402. package/dist/esm/Fault.d.ts +131 -0
  403. package/dist/esm/Fault.d.ts.map +1 -0
  404. package/dist/esm/Fault.js +198 -0
  405. package/dist/esm/Fault.js.map +1 -0
  406. package/dist/esm/Flow/Annotations.d.ts +245 -0
  407. package/dist/esm/Flow/Annotations.d.ts.map +1 -0
  408. package/dist/esm/Flow/Annotations.js +110 -0
  409. package/dist/esm/Flow/Annotations.js.map +1 -0
  410. package/dist/esm/Flow/CapabilityCeiling.d.ts +21 -0
  411. package/dist/esm/Flow/CapabilityCeiling.d.ts.map +1 -0
  412. package/dist/esm/Flow/CapabilityCeiling.js +27 -0
  413. package/dist/esm/Flow/CapabilityCeiling.js.map +1 -0
  414. package/dist/esm/Flow/DeadlineExceeded.d.ts +33 -0
  415. package/dist/esm/Flow/DeadlineExceeded.d.ts.map +1 -0
  416. package/dist/esm/Flow/DeadlineExceeded.js +34 -0
  417. package/dist/esm/Flow/DeadlineExceeded.js.map +1 -0
  418. package/dist/esm/Flow/ExecutionIdRequired.d.ts +25 -0
  419. package/dist/esm/Flow/ExecutionIdRequired.d.ts.map +1 -0
  420. package/dist/esm/Flow/ExecutionIdRequired.js +30 -0
  421. package/dist/esm/Flow/ExecutionIdRequired.js.map +1 -0
  422. package/dist/esm/Flow/ExecutionIds.d.ts +80 -0
  423. package/dist/esm/Flow/ExecutionIds.d.ts.map +1 -0
  424. package/dist/esm/Flow/ExecutionIds.js +91 -0
  425. package/dist/esm/Flow/ExecutionIds.js.map +1 -0
  426. package/dist/esm/Flow/Flow.d.ts +422 -0
  427. package/dist/esm/Flow/Flow.d.ts.map +1 -0
  428. package/dist/esm/Flow/Flow.js +3 -0
  429. package/dist/esm/Flow/Flow.js.map +1 -0
  430. package/dist/esm/Flow/MaxRoundsExceeded.d.ts +35 -0
  431. package/dist/esm/Flow/MaxRoundsExceeded.d.ts.map +1 -0
  432. package/dist/esm/Flow/MaxRoundsExceeded.js +34 -0
  433. package/dist/esm/Flow/MaxRoundsExceeded.js.map +1 -0
  434. package/dist/esm/Flow/Outcome.d.ts +162 -0
  435. package/dist/esm/Flow/Outcome.d.ts.map +1 -0
  436. package/dist/esm/Flow/Outcome.js +115 -0
  437. package/dist/esm/Flow/Outcome.js.map +1 -0
  438. package/dist/esm/Flow/Result.d.ts +186 -0
  439. package/dist/esm/Flow/Result.d.ts.map +1 -0
  440. package/dist/esm/Flow/Result.js +171 -0
  441. package/dist/esm/Flow/Result.js.map +1 -0
  442. package/dist/esm/Flow/Runtime.d.ts +98 -0
  443. package/dist/esm/Flow/Runtime.d.ts.map +1 -0
  444. package/dist/esm/Flow/Runtime.js +231 -0
  445. package/dist/esm/Flow/Runtime.js.map +1 -0
  446. package/dist/esm/Flow/TypeId.d.ts +8 -0
  447. package/dist/esm/Flow/TypeId.d.ts.map +1 -0
  448. package/dist/esm/Flow/TypeId.js +9 -0
  449. package/dist/esm/Flow/TypeId.js.map +1 -0
  450. package/dist/esm/Flow/index.d.ts +17 -0
  451. package/dist/esm/Flow/index.d.ts.map +1 -0
  452. package/dist/esm/Flow/index.js +18 -0
  453. package/dist/esm/Flow/index.js.map +1 -0
  454. package/dist/esm/Flow/internal.d.ts +34 -0
  455. package/dist/esm/Flow/internal.d.ts.map +1 -0
  456. package/dist/esm/Flow/internal.js +149 -0
  457. package/dist/esm/Flow/internal.js.map +1 -0
  458. package/dist/esm/Flow/make.d.ts +134 -0
  459. package/dist/esm/Flow/make.d.ts.map +1 -0
  460. package/dist/esm/Flow/make.js +106 -0
  461. package/dist/esm/Flow/make.js.map +1 -0
  462. package/dist/esm/FlowRuntime/CancelRequestFailed.d.ts +55 -0
  463. package/dist/esm/FlowRuntime/CancelRequestFailed.d.ts.map +1 -0
  464. package/dist/esm/FlowRuntime/CancelRequestFailed.js +53 -0
  465. package/dist/esm/FlowRuntime/CancelRequestFailed.js.map +1 -0
  466. package/dist/esm/FlowRuntime/ExecutionIdentityConflict.d.ts +23 -0
  467. package/dist/esm/FlowRuntime/ExecutionIdentityConflict.d.ts.map +1 -0
  468. package/dist/esm/FlowRuntime/ExecutionIdentityConflict.js +24 -0
  469. package/dist/esm/FlowRuntime/ExecutionIdentityConflict.js.map +1 -0
  470. package/dist/esm/FlowRuntime/FlowCycleDetected.d.ts +28 -0
  471. package/dist/esm/FlowRuntime/FlowCycleDetected.d.ts.map +1 -0
  472. package/dist/esm/FlowRuntime/FlowCycleDetected.js +35 -0
  473. package/dist/esm/FlowRuntime/FlowCycleDetected.js.map +1 -0
  474. package/dist/esm/FlowRuntime/FlowExecutionNotFound.d.ts +38 -0
  475. package/dist/esm/FlowRuntime/FlowExecutionNotFound.d.ts.map +1 -0
  476. package/dist/esm/FlowRuntime/FlowExecutionNotFound.js +40 -0
  477. package/dist/esm/FlowRuntime/FlowExecutionNotFound.js.map +1 -0
  478. package/dist/esm/FlowRuntime/FlowInstance.d.ts +115 -0
  479. package/dist/esm/FlowRuntime/FlowInstance.d.ts.map +1 -0
  480. package/dist/esm/FlowRuntime/FlowInstance.js +24 -0
  481. package/dist/esm/FlowRuntime/FlowInstance.js.map +1 -0
  482. package/dist/esm/FlowRuntime/FlowRuntime.d.ts +198 -0
  483. package/dist/esm/FlowRuntime/FlowRuntime.d.ts.map +1 -0
  484. package/dist/esm/FlowRuntime/FlowRuntime.js +34 -0
  485. package/dist/esm/FlowRuntime/FlowRuntime.js.map +1 -0
  486. package/dist/esm/FlowRuntime/NodeRecord.d.ts +175 -0
  487. package/dist/esm/FlowRuntime/NodeRecord.d.ts.map +1 -0
  488. package/dist/esm/FlowRuntime/NodeRecord.js +21 -0
  489. package/dist/esm/FlowRuntime/NodeRecord.js.map +1 -0
  490. package/dist/esm/FlowRuntime/WaitingAnnotation.d.ts +69 -0
  491. package/dist/esm/FlowRuntime/WaitingAnnotation.d.ts.map +1 -0
  492. package/dist/esm/FlowRuntime/WaitingAnnotation.js +53 -0
  493. package/dist/esm/FlowRuntime/WaitingAnnotation.js.map +1 -0
  494. package/dist/esm/FlowRuntime/index.d.ts +14 -0
  495. package/dist/esm/FlowRuntime/index.d.ts.map +1 -0
  496. package/dist/esm/FlowRuntime/index.js +15 -0
  497. package/dist/esm/FlowRuntime/index.js.map +1 -0
  498. package/dist/esm/Graph.d.ts +325 -0
  499. package/dist/esm/Graph.d.ts.map +1 -0
  500. package/dist/esm/Graph.js +1482 -0
  501. package/dist/esm/Graph.js.map +1 -0
  502. package/dist/esm/HumanTask.d.ts +440 -0
  503. package/dist/esm/HumanTask.d.ts.map +1 -0
  504. package/dist/esm/HumanTask.js +794 -0
  505. package/dist/esm/HumanTask.js.map +1 -0
  506. package/dist/esm/Interpreter.d.ts +222 -0
  507. package/dist/esm/Interpreter.d.ts.map +1 -0
  508. package/dist/esm/Interpreter.js +1269 -0
  509. package/dist/esm/Interpreter.js.map +1 -0
  510. package/dist/esm/Poll.d.ts +238 -0
  511. package/dist/esm/Poll.d.ts.map +1 -0
  512. package/dist/esm/Poll.js +282 -0
  513. package/dist/esm/Poll.js.map +1 -0
  514. package/dist/esm/RetryPolicy.d.ts +273 -0
  515. package/dist/esm/RetryPolicy.d.ts.map +1 -0
  516. package/dist/esm/RetryPolicy.js +429 -0
  517. package/dist/esm/RetryPolicy.js.map +1 -0
  518. package/dist/esm/Sleep.d.ts +98 -0
  519. package/dist/esm/Sleep.d.ts.map +1 -0
  520. package/dist/esm/Sleep.js +230 -0
  521. package/dist/esm/Sleep.js.map +1 -0
  522. package/dist/esm/Stall.d.ts +173 -0
  523. package/dist/esm/Stall.d.ts.map +1 -0
  524. package/dist/esm/Stall.js +138 -0
  525. package/dist/esm/Stall.js.map +1 -0
  526. package/dist/esm/WaitFor.d.ts +109 -0
  527. package/dist/esm/WaitFor.d.ts.map +1 -0
  528. package/dist/esm/WaitFor.js +184 -0
  529. package/dist/esm/WaitFor.js.map +1 -0
  530. package/dist/esm/index.d.ts +107 -0
  531. package/dist/esm/index.d.ts.map +1 -0
  532. package/dist/esm/index.js +108 -0
  533. package/dist/esm/index.js.map +1 -0
  534. package/dist/esm/internal/BoundedJson.d.ts +48 -0
  535. package/dist/esm/internal/BoundedJson.d.ts.map +1 -0
  536. package/dist/esm/internal/BoundedJson.js +107 -0
  537. package/dist/esm/internal/BoundedJson.js.map +1 -0
  538. package/dist/esm/internal/DeclarationSite.d.ts +135 -0
  539. package/dist/esm/internal/DeclarationSite.d.ts.map +1 -0
  540. package/dist/esm/internal/DeclarationSite.js +196 -0
  541. package/dist/esm/internal/DeclarationSite.js.map +1 -0
  542. package/dist/esm/internal/Declarations.d.ts +35 -0
  543. package/dist/esm/internal/Declarations.d.ts.map +1 -0
  544. package/dist/esm/internal/Declarations.js +43 -0
  545. package/dist/esm/internal/Declarations.js.map +1 -0
  546. package/dist/esm/internal/ExecutionMiddleware.d.ts +21 -0
  547. package/dist/esm/internal/ExecutionMiddleware.d.ts.map +1 -0
  548. package/dist/esm/internal/ExecutionMiddleware.js +13 -0
  549. package/dist/esm/internal/ExecutionMiddleware.js.map +1 -0
  550. package/dist/esm/internal/JsonSchemaSubset.d.ts +133 -0
  551. package/dist/esm/internal/JsonSchemaSubset.d.ts.map +1 -0
  552. package/dist/esm/internal/JsonSchemaSubset.js +363 -0
  553. package/dist/esm/internal/JsonSchemaSubset.js.map +1 -0
  554. package/dist/esm/internal/OutcomeMarker.d.ts +18 -0
  555. package/dist/esm/internal/OutcomeMarker.d.ts.map +1 -0
  556. package/dist/esm/internal/OutcomeMarker.js +18 -0
  557. package/dist/esm/internal/OutcomeMarker.js.map +1 -0
  558. package/docs/README.md +150 -0
  559. package/docs/api.md +436 -0
  560. package/docs/concepts/bodies-and-plans.md +157 -0
  561. package/docs/concepts/execution-identity.md +142 -0
  562. package/docs/concepts/flows-and-actions.md +129 -0
  563. package/docs/concepts/suspension-and-replay.md +130 -0
  564. package/docs/concepts/the-runtime-port.md +110 -0
  565. package/docs/concepts/trampoline-rounds.md +151 -0
  566. package/docs/guides/ask-a-person.md +184 -0
  567. package/docs/guides/build-a-body.md +161 -0
  568. package/docs/guides/cancel-and-roll-back.md +112 -0
  569. package/docs/guides/implement-an-action.md +147 -0
  570. package/docs/guides/inspect-the-plan.md +154 -0
  571. package/docs/guides/poll-until-ready.md +167 -0
  572. package/docs/guides/queue-work-to-a-worker.md +122 -0
  573. package/docs/guides/retry-a-failing-action.md +243 -0
  574. package/docs/guides/reuse-a-recorded-result.md +122 -0
  575. package/docs/guides/run-a-child-flow.md +108 -0
  576. package/docs/guides/run-an-external-job.md +86 -0
  577. package/docs/guides/use-a-prompt.md +38 -0
  578. package/docs/guides/wait-for-a-deadline.md +141 -0
  579. package/docs/guides/wait-for-an-external-signal.md +151 -0
  580. package/docs/installation.md +82 -0
  581. package/docs/quickstart.md +155 -0
  582. package/docs/reference/flow.md +1831 -0
  583. package/docs/testing.md +157 -0
  584. package/docs/troubleshooting.md +286 -0
  585. package/package.json +327 -3
  586. package/src/Action/Action.ts +333 -0
  587. package/src/Action/AttemptTimedOut.ts +37 -0
  588. package/src/Action/BoundaryMode.ts +33 -0
  589. package/src/Action/CacheEnvironment.ts +170 -0
  590. package/src/Action/ConcurrentKeylessDispatch.ts +38 -0
  591. package/src/Action/Context.ts +156 -0
  592. package/src/Action/DuplicateImplementation.ts +24 -0
  593. package/src/Action/FileBoundary.ts +77 -0
  594. package/src/Action/FileInput.ts +42 -0
  595. package/src/Action/Filegroup.ts +16 -0
  596. package/src/Action/Glob.ts +8 -0
  597. package/src/Action/ImplementationVersionMismatch.ts +27 -0
  598. package/src/Action/Implementations.ts +149 -0
  599. package/src/Action/InfraInterrupt.ts +30 -0
  600. package/src/Action/InfraInterruptRetriesExhausted.ts +37 -0
  601. package/src/Action/IrreversibleRetryRequiresIdempotencyKey.ts +32 -0
  602. package/src/Action/StepIdentity.ts +219 -0
  603. package/src/Action/TreeArtifact.ts +8 -0
  604. package/src/Action/TypeId.ts +9 -0
  605. package/src/Action/UncanonicalIdempotencyKey.ts +36 -0
  606. package/src/Action/idempotencyKey.ts +67 -0
  607. package/src/Action/index.ts +31 -0
  608. package/src/Action/make.ts +657 -0
  609. package/src/Action/raceAll.ts +48 -0
  610. package/src/Action/retry.ts +92 -0
  611. package/src/Deadline.ts +185 -0
  612. package/src/DurableClock.ts +133 -0
  613. package/src/DurableDeferred.ts +753 -0
  614. package/src/DurableQueue.ts +519 -0
  615. package/src/ExternalJob.ts +432 -0
  616. package/src/Fault.ts +279 -0
  617. package/src/Flow/Annotations.ts +151 -0
  618. package/src/Flow/CapabilityCeiling.ts +37 -0
  619. package/src/Flow/DeadlineExceeded.ts +40 -0
  620. package/src/Flow/ExecutionIdRequired.ts +36 -0
  621. package/src/Flow/ExecutionIds.ts +133 -0
  622. package/src/Flow/Flow.ts +576 -0
  623. package/src/Flow/MaxRoundsExceeded.ts +39 -0
  624. package/src/Flow/Outcome.ts +179 -0
  625. package/src/Flow/Result.ts +284 -0
  626. package/src/Flow/Runtime.ts +309 -0
  627. package/src/Flow/TypeId.ts +9 -0
  628. package/src/Flow/index.ts +19 -0
  629. package/src/Flow/internal.ts +237 -0
  630. package/src/Flow/make.ts +279 -0
  631. package/src/FlowRuntime/CancelRequestFailed.ts +56 -0
  632. package/src/FlowRuntime/ExecutionIdentityConflict.ts +32 -0
  633. package/src/FlowRuntime/FlowCycleDetected.ts +41 -0
  634. package/src/FlowRuntime/FlowExecutionNotFound.ts +46 -0
  635. package/src/FlowRuntime/FlowInstance.ts +128 -0
  636. package/src/FlowRuntime/FlowRuntime.ts +333 -0
  637. package/src/FlowRuntime/NodeRecord.ts +183 -0
  638. package/src/FlowRuntime/WaitingAnnotation.ts +85 -0
  639. package/src/FlowRuntime/index.ts +17 -0
  640. package/src/Graph.ts +1860 -0
  641. package/src/HumanTask.ts +1003 -0
  642. package/src/Interpreter.ts +1593 -0
  643. package/src/Poll.ts +414 -0
  644. package/src/RetryPolicy.ts +550 -0
  645. package/src/Sleep.ts +267 -0
  646. package/src/Stall.ts +217 -0
  647. package/src/WaitFor.ts +228 -0
  648. package/src/index.ts +125 -0
  649. package/src/internal/BoundedJson.ts +109 -0
  650. package/src/internal/DeclarationSite.ts +214 -0
  651. package/src/internal/Declarations.ts +49 -0
  652. package/src/internal/ExecutionMiddleware.ts +29 -0
  653. package/src/internal/JsonSchemaSubset.ts +392 -0
  654. package/src/internal/OutcomeMarker.ts +19 -0
@@ -0,0 +1,1003 @@
1
+ /**
2
+ * Asking a person something, as an ordinary declared action.
3
+ *
4
+ * {@link module:WaitFor.action} is the general rendezvous: it parks until
5
+ * something outside the run resolves it, and settles with whatever arrived.
6
+ * That is the right primitive and the wrong affordance for a human, because a
7
+ * human answers in prose, in a hurry, and sometimes wrongly. Smithers 0.x had
8
+ * the affordance — a `HumanTask` with a kind, a prompt, an output schema, an
9
+ * attempt budget, and a deadline — and this module is that affordance rebuilt
10
+ * on the primitives this package already has.
11
+ *
12
+ * Four things are added to a bare wait:
13
+ *
14
+ * - a **kind**, so the four shapes a person is asked for (`ask`, `confirm`,
15
+ * `select`, `json`) are stated rather than reconstructed from a schema;
16
+ * - **validation**, so an answer that does not fit is refused where it arrives
17
+ * instead of failing three steps later as a decode error;
18
+ * - **re-asking**, so a refused answer parks again on a NEW wait point rather
19
+ * than ending the run, until the attempt budget is spent;
20
+ * - a **deadline**, so a question nobody answers settles instead of parking
21
+ * forever.
22
+ *
23
+ * All four are built from what is already durable. Each attempt is its own wait
24
+ * point in {@link module:WaitFor}'s namespace — `WaitFor/<name>#<attempt>` — so
25
+ * an answer is recorded exactly as any other durable deferred completion is, a
26
+ * refused answer stays recorded under the attempt that refused it, and a
27
+ * re-driven round replays every answer it already has before parking on the
28
+ * first attempt that has none. The reason an answer was refused is recorded
29
+ * too, as a sealed step named `HumanTask/<name>#<attempt>/rejected`, so the
30
+ * judgment the run made sits in the journal beside the answer it judged rather
31
+ * than in a log stream nobody replays. The park is declared through the ordinary
32
+ * waiting vocabulary under `approval`, carrying the current attempt's token, so
33
+ * whoever collects answers always sees the one wait point that is open. The
34
+ * deadline is a {@link module:DurableClock} armed once per task and raced
35
+ * against every attempt, which makes it a deadline for the QUESTION rather than
36
+ * for one attempt at answering it.
37
+ *
38
+ * @since 0.1.0
39
+ */
40
+
41
+ import * as Node from "@smthrs/plan/Node"
42
+ import type * as Crypto from "effect/Crypto"
43
+ import * as Duration from "effect/Duration"
44
+ import * as Effect from "effect/Effect"
45
+ import * as Exit from "effect/Exit"
46
+ import type * as Layer from "effect/Layer"
47
+ import * as Schema from "effect/Schema"
48
+ import * as Action from "./Action/index.ts"
49
+ import * as DurableClock from "./DurableClock.ts"
50
+ import * as DurableDeferred from "./DurableDeferred.ts"
51
+ import { FlowInstance } from "./FlowRuntime/FlowInstance.ts"
52
+ import { FlowRuntime } from "./FlowRuntime/FlowRuntime.ts"
53
+ import { annotateWaiting } from "./FlowRuntime/WaitingAnnotation.ts"
54
+ import * as BoundedJson from "./internal/BoundedJson.ts"
55
+ import * as JsonSchemaSubset from "./internal/JsonSchemaSubset.ts"
56
+ import * as WaitFor from "./WaitFor.ts"
57
+
58
+ /**
59
+ * The shape a person is asked for.
60
+ *
61
+ * `ask` wants prose, `confirm` wants yes or no, `select` wants one of the
62
+ * options the task names, and `json` wants a value the task's JSON Schema
63
+ * accepts. The kind is what an interface renders and what {@link validate}
64
+ * checks; it is stated rather than inferred, because a text box and a two-
65
+ * button confirmation are different questions even when both answers happen to
66
+ * be strings.
67
+ *
68
+ * @category models
69
+ * @since 0.1.0
70
+ */
71
+ export type Kind = "ask" | "confirm" | "select" | "json"
72
+
73
+ /**
74
+ * The schema the `kind` payload field is declared with.
75
+ *
76
+ * @category schemas
77
+ * @since 0.1.0
78
+ */
79
+ export const Kind: Schema.Literals<readonly ["ask", "confirm", "select", "json"]> = Schema.Literals([
80
+ "ask",
81
+ "confirm",
82
+ "select",
83
+ "json"
84
+ ])
85
+
86
+ /**
87
+ * A question that ended without an answer the task could accept.
88
+ *
89
+ * `request_invalid` is the author's mistake — a `select` with no options, an
90
+ * attempt budget below one, a deadline that is not a length of time, a JSON
91
+ * Schema outside the supported subset — and is refused before anyone is asked
92
+ * anything. `rejected` means every attempt was
93
+ * spent on answers the task refused, and `timeout` means the deadline passed
94
+ * with the question still open. All three are typed failures rather than
95
+ * defects, so a body recovers from them with `Node.catch` like any other
96
+ * declared failure — which is the point, because "the reviewer never answered"
97
+ * is an ordinary outcome of asking a reviewer.
98
+ *
99
+ * @category errors
100
+ * @since 0.1.0
101
+ */
102
+ export class HumanTaskFailed extends Schema.TaggedError<HumanTaskFailed>()(
103
+ "@smthrs/flow/HumanTaskFailed",
104
+ {
105
+ code: Schema.Literals(["request_invalid", "rejected", "timeout"]),
106
+ task: Schema.String,
107
+ attempts: Schema.Number,
108
+ rejections: Schema.Array(Schema.String),
109
+ message: Schema.String
110
+ }
111
+ ) {}
112
+
113
+ /**
114
+ * An answer refused before it could consume durable storage.
115
+ *
116
+ * @category errors
117
+ * @since 1.0.0
118
+ */
119
+ export class HumanAnswerInvalid extends Schema.TaggedError<HumanAnswerInvalid>()(
120
+ "@smthrs/flow/HumanAnswerInvalid",
121
+ {
122
+ code: Schema.Literals(["answer_invalid", "answer_not_open"]).pipe(
123
+ Schema.withConstructorDefault(Effect.succeed("answer_invalid"))
124
+ ),
125
+ message: Schema.String
126
+ }
127
+ ) {}
128
+
129
+ /**
130
+ * The tag the human-task declaration is catalogued and resolved under.
131
+ *
132
+ * @category constructors
133
+ * @since 0.1.0
134
+ */
135
+ export const tag = "system/human-task"
136
+
137
+ /**
138
+ * The attempt budget a task that names none is asked under.
139
+ *
140
+ * @category constructors
141
+ * @since 0.1.0
142
+ */
143
+ export const defaultMaxAttempts = 10
144
+
145
+ /**
146
+ * The deepest supported JSON Schema path, counting the root as depth zero.
147
+ *
148
+ * @category constructors
149
+ * @since 0.1.0
150
+ */
151
+ export const maxSchemaDepth = JsonSchemaSubset.maxSchemaDepth
152
+
153
+ /**
154
+ * The most schema objects one human-task request may contain.
155
+ *
156
+ * @category constructors
157
+ * @since 0.1.0
158
+ */
159
+ export const maxSchemaNodes = JsonSchemaSubset.maxSchemaNodes
160
+
161
+ /**
162
+ * The most JSON values embedded across schema keywords such as `enum`.
163
+ *
164
+ * @category constructors
165
+ * @since 1.0.0
166
+ */
167
+ export const maxSchemaValueNodes = JsonSchemaSubset.maxSchemaValueNodes
168
+
169
+ /**
170
+ * The deepest JSON value embedded in a schema, including enum members.
171
+ *
172
+ * @category constructors
173
+ * @since 1.0.0
174
+ */
175
+ export const maxSchemaValueDepth = JsonSchemaSubset.maxSchemaValueDepth
176
+
177
+ /**
178
+ * The most JSON values one answer validation may visit.
179
+ *
180
+ * @category constructors
181
+ * @since 0.1.0
182
+ */
183
+ export const maxAnswerNodes = JsonSchemaSubset.maxAnswerNodes
184
+
185
+ /**
186
+ * The largest encoded JSON answer that can enter the durable store.
187
+ *
188
+ * @category constructors
189
+ * @since 1.0.0
190
+ */
191
+ export const maxAnswerBytes = JsonSchemaSubset.maxAnswerBytes
192
+
193
+ /**
194
+ * The largest encoded JSON Schema carried by one question.
195
+ *
196
+ * @category constructors
197
+ * @since 1.0.0
198
+ */
199
+ export const maxSchemaBytes = JsonSchemaSubset.maxSchemaBytes
200
+
201
+ /**
202
+ * The deepest admitted answer tree.
203
+ *
204
+ * @category constructors
205
+ * @since 1.0.0
206
+ */
207
+ export const maxAnswerDepth = JsonSchemaSubset.maxAnswerDepth
208
+
209
+ /**
210
+ * The largest encoded string value admitted in a request or answer.
211
+ *
212
+ * @category constructors
213
+ * @since 1.0.0
214
+ */
215
+ export const maxJsonStringBytes = JsonSchemaSubset.maxJsonStringBytes
216
+
217
+ /**
218
+ * The largest encoded object key admitted in a request or answer.
219
+ *
220
+ * @category constructors
221
+ * @since 1.0.0
222
+ */
223
+ export const maxJsonKeyBytes = JsonSchemaSubset.maxJsonKeyBytes
224
+
225
+ /**
226
+ * The most members admitted in one JSON array or object.
227
+ *
228
+ * @category constructors
229
+ * @since 1.0.0
230
+ */
231
+ export const maxJsonMembers = JsonSchemaSubset.maxJsonMembers
232
+
233
+ /**
234
+ * The largest encoded task name.
235
+ *
236
+ * @category constructors
237
+ * @since 1.0.0
238
+ */
239
+ export const maxTaskNameBytes = 1_024
240
+
241
+ /**
242
+ * The largest encoded prompt.
243
+ *
244
+ * @category constructors
245
+ * @since 1.0.0
246
+ */
247
+ export const maxPromptBytes = 64 * 1024
248
+
249
+ /**
250
+ * The largest option list on one select question.
251
+ *
252
+ * @category constructors
253
+ * @since 1.0.0
254
+ */
255
+ export const maxOptions = 256
256
+
257
+ /**
258
+ * The largest encoded select option.
259
+ *
260
+ * @category constructors
261
+ * @since 1.0.0
262
+ */
263
+ export const maxOptionBytes = 4 * 1024
264
+
265
+ /**
266
+ * The largest attempt budget one human task may declare.
267
+ *
268
+ * @category constructors
269
+ * @since 0.1.0
270
+ */
271
+ export const maxAttemptBudget = 1_000
272
+
273
+ /**
274
+ * The most caller-supplied characters retained in one rendered diagnostic.
275
+ *
276
+ * @category constructors
277
+ * @since 0.1.0
278
+ */
279
+ export const maxDiagnosticChars = JsonSchemaSubset.maxDiagnosticChars
280
+
281
+ /**
282
+ * The most characters retained across a terminal failure's rejection list.
283
+ *
284
+ * @category constructors
285
+ * @since 0.1.0
286
+ */
287
+ export const maxRetainedRejectionChars = 8_192
288
+
289
+ /**
290
+ * The durable deferred one attempt at answering resolves through.
291
+ *
292
+ * Attempts are separate wait points on purpose. A durable deferred records the
293
+ * FIRST completion and replays it forever, so re-asking on the same wait point
294
+ * would read the refused answer again on every round; a new point per attempt
295
+ * makes "answer again" expressible without a second completion mechanism, and
296
+ * leaves the refused answers in place as the record of what was asked and what
297
+ * came back.
298
+ *
299
+ * The name lives in {@link module:WaitFor}'s namespace because an answer is
300
+ * completed through exactly the {@link module:WaitFor} path: a token, and
301
+ * `DurableDeferred.succeed`. {@link answer} is that call with the token parsed
302
+ * for you.
303
+ *
304
+ * @category constructors
305
+ * @since 0.1.0
306
+ */
307
+ export const deferred = (
308
+ name: string,
309
+ attempt: number
310
+ ): DurableDeferred.DurableDeferred<typeof Schema.Json> => WaitFor.deferred(`${name}#${attempt}`)
311
+
312
+ /** The namespace {@link module:WaitFor.deferred} prepends to every wait point. */
313
+ const waitForNamespace = /^WaitFor\//
314
+
315
+ /**
316
+ * The only spelling of an attempt {@link deferred} writes: a canonical decimal
317
+ * with no sign, no leading zero, no exponent, and no fraction.
318
+ *
319
+ * `Number()` alone is not this check. `NaN`, `Infinity`, `-Infinity`, and
320
+ * `1e+21` all survive a `Number()`/`String()` round trip character for
321
+ * character, so a gate that rebuilt the name through `Number()` would accept
322
+ * them as attempts the action never parks on.
323
+ */
324
+ const attemptSuffix = /^(0|[1-9][0-9]*)$/
325
+
326
+ /**
327
+ * The deferred a token addresses, when {@link deferred} could have named it.
328
+ *
329
+ * {@link answer} builds its deferred FROM the caller's token, so
330
+ * `DurableDeferred.done`'s own name check compares a name against itself and
331
+ * can never refuse. This is the check that is not vacuous: the name is taken
332
+ * apart at its attempt separator, the suffix is required to be a canonical
333
+ * decimal naming an attempt the action can park on (a safe integer of one or
334
+ * more), the name is rebuilt through {@link deferred}, and it is accepted only
335
+ * when the rebuilt name is character-for-character the one the token carried.
336
+ * A name {@link deferred} cannot produce -- a `DurableQueue` item address, a
337
+ * plain {@link module:WaitFor} gate, another flow's deferred, a suffix spelled
338
+ * any way other than the decimal {@link deferred} writes -- fails, so a
339
+ * foreign token cannot be completed under `Schema.Json` through the
340
+ * human-answer path.
341
+ *
342
+ * This bounds the confusion to human-task wait points. It does NOT distinguish
343
+ * two human tasks from each other, nor a wait point an author deliberately
344
+ * named to collide with one; separating those needs the deferred's schema and
345
+ * purpose carried in the address itself, which is a wire-format change.
346
+ *
347
+ * @private
348
+ */
349
+ const answerableDeferred = (
350
+ deferredName: string
351
+ ): DurableDeferred.DurableDeferred<typeof Schema.Json> | undefined => {
352
+ const separator = deferredName.lastIndexOf("#")
353
+ if (separator === -1) return undefined
354
+ const suffix = deferredName.slice(separator + 1)
355
+ if (!attemptSuffix.test(suffix)) return undefined
356
+ const attempt = Number(suffix)
357
+ if (!Number.isSafeInteger(attempt) || attempt < 1) return undefined
358
+ const rebuilt = deferred(deferredName.slice(0, separator).replace(waitForNamespace, ""), attempt)
359
+ return rebuilt.name === deferredName ? rebuilt : undefined
360
+ }
361
+
362
+ /**
363
+ * The clock a task's deadline is armed on.
364
+ *
365
+ * One clock per task, not one per attempt: the deadline bounds how long the
366
+ * QUESTION stays open, so re-asking does not extend it. The name is the task's,
367
+ * so every attempt's race arms and awaits the same durable timer — a clock row
368
+ * keeps the deadline it was first armed with, which is what makes the bound
369
+ * survive a restart.
370
+ *
371
+ * The deadline settles on both hosts. `@smthrs/engine`'s in-process engine and
372
+ * the SQLite engine store each re-drive a run parked on
373
+ * {@link module:DurableDeferred.raceAll}, so the durable timer wakes the
374
+ * question wherever it was asked
375
+ * (`packages/smithers/flows/engine-store/test/RacedParkResume.test.ts`).
376
+ *
377
+ * @private
378
+ */
379
+ const timeoutClockName = (name: string): string => `HumanTask/${name}/timeout`
380
+
381
+ /**
382
+ * What one attempt settled with: the answer that arrived, or the deadline.
383
+ *
384
+ * @private
385
+ */
386
+ const Settled = Schema.Union([
387
+ Schema.Struct({ _tag: Schema.Literal("answered"), value: Schema.Json }),
388
+ Schema.Struct({ _tag: Schema.Literal("timeout") })
389
+ ])
390
+
391
+ type Settled = typeof Settled.Type
392
+
393
+ /**
394
+ * What {@link validate} checks an answer against.
395
+ *
396
+ * @category models
397
+ * @since 0.1.0
398
+ */
399
+ export interface Request {
400
+ readonly kind: Kind
401
+ /** Ignored for `json`: an option list alone constrains no JSON value. */
402
+ readonly options?: ReadonlyArray<string> | undefined
403
+ readonly schema?: unknown
404
+ }
405
+
406
+ /**
407
+ * Checks that a JSON Schema stays inside the bounded subset, at every depth.
408
+ *
409
+ * This is a different question from {@link validate}, which asks whether an
410
+ * ANSWER fits a schema. A question is worth refusing before anyone is asked it:
411
+ * a constraint the subset cannot enforce would otherwise be silently dropped,
412
+ * and the person would be told their answer was fine when half of what was
413
+ * asked for went unchecked.
414
+ *
415
+ * The subset is `type` (`object`, `array`, `string`, `number`, `integer`,
416
+ * `boolean`, `null`), `enum`, `properties`, `required`, `items`, and
417
+ * `nullable`; it lives in `internal/JsonSchemaSubset`.
418
+ *
419
+ * Returns the first reason the schema is out of bounds, or `undefined` when the
420
+ * whole tree is inside it.
421
+ *
422
+ * @category combinators
423
+ * @since 0.1.0
424
+ */
425
+ export const validateSchema = (
426
+ schema: unknown,
427
+ path: ReadonlyArray<string> = []
428
+ ): string | undefined => JsonSchemaSubset.validateSchema(schema, path)
429
+
430
+ /**
431
+ * Checks one answer against the question that was asked.
432
+ *
433
+ * Returns the reason the answer was refused, or `undefined` when it fits. It is
434
+ * exported because it is the same check an interface should run BEFORE it
435
+ * records an answer: refusing a typo in the text box the person is looking at
436
+ * is worth more than refusing it one durable round later.
437
+ *
438
+ * ```ts
439
+ * const rejection = HumanTask.validate(value, { kind: "select", options })
440
+ * if (rejection !== undefined) return showTheReviewer(rejection)
441
+ * ```
442
+ *
443
+ * @category combinators
444
+ * @since 0.1.0
445
+ */
446
+ export const validate = (value: unknown, request: Request): string | undefined => {
447
+ switch (request.kind) {
448
+ case "ask":
449
+ if (typeof value !== "string") return "The answer must be a string."
450
+ return BoundedJson.textFits(value, maxJsonStringBytes)
451
+ ? undefined
452
+ : `The answer must fit within ${maxJsonStringBytes} encoded bytes of well-formed text.`
453
+ case "confirm":
454
+ return typeof value === "boolean" ? undefined : "The answer must be a boolean."
455
+ case "select": {
456
+ if (request.options === undefined || request.options.length === 0) {
457
+ return "The question declares no options to choose from."
458
+ }
459
+ if (
460
+ request.options.length > maxOptions ||
461
+ request.options.some((option) => typeof option !== "string" || !BoundedJson.textFits(option, maxOptionBytes))
462
+ ) {
463
+ return `The question's options exceed the ${maxOptions}-member or ${maxOptionBytes}-byte limits.`
464
+ }
465
+ return request.options.some((option) => option === value)
466
+ ? undefined
467
+ : `The answer ${JsonSchemaSubset.renderDiagnostic(value)} is not one of ${
468
+ JsonSchemaSubset.truncateDiagnostic(request.options.join(", "))
469
+ }.`
470
+ }
471
+ default: {
472
+ if (request.schema !== undefined) return JsonSchemaSubset.check(value, request.schema)
473
+ const admitted = BoundedJson.admit(value, JsonSchemaSubset.answerLimits)
474
+ return admitted.ok ? undefined : admitted.complaint
475
+ }
476
+ }
477
+ }
478
+
479
+ /**
480
+ * The fields a question is asked with.
481
+ *
482
+ * @private
483
+ */
484
+ const boundedText = (label: string, maximumBytes: number) =>
485
+ Schema.String.check(
486
+ Schema.makeFilter(
487
+ (value) =>
488
+ BoundedJson.textFits(value, maximumBytes) ||
489
+ `${label} must be well-formed text within ${maximumBytes} encoded bytes`,
490
+ { title: `bounded${label.replaceAll(" ", "")}` }
491
+ )
492
+ )
493
+
494
+ const boundedSchema = Schema.Json.check(
495
+ Schema.makeFilter(
496
+ (value) => {
497
+ const admitted = BoundedJson.admit(value, JsonSchemaSubset.schemaLimits)
498
+ return admitted.ok || admitted.complaint
499
+ },
500
+ { title: "boundedHumanTaskSchema" }
501
+ )
502
+ )
503
+
504
+ const option = boundedText("option", maxOptionBytes)
505
+
506
+ const payloadFields = {
507
+ name: boundedText("task name", maxTaskNameBytes),
508
+ kind: Kind,
509
+ prompt: boundedText("prompt", maxPromptBytes),
510
+ options: Schema.optional(
511
+ Schema.Array(option).check(Schema.isMaxLength(maxOptions))
512
+ ),
513
+ schema: Schema.optional(boundedSchema),
514
+ timeoutMs: Schema.optional(Schema.Number),
515
+ maxAttempts: Schema.optional(Schema.Number)
516
+ }
517
+
518
+ /**
519
+ * The declared human-task action.
520
+ *
521
+ * **When to use**
522
+ *
523
+ * Use it in a body wherever the next step depends on a person: a release that
524
+ * needs sign-off, a plan that needs a choice, a field the run cannot compute.
525
+ * The node settles with the answer, so downstream steps read it the way they
526
+ * read any other step result, and {@link decode} gives that answer the caller's
527
+ * own type.
528
+ *
529
+ * ```ts
530
+ * HumanTask.action.call({
531
+ * name: "release",
532
+ * kind: "select",
533
+ * prompt: "Which build should ship?",
534
+ * options: ["canary", "stable"],
535
+ * timeoutMs: 6 * 60 * 60 * 1000
536
+ * })
537
+ * ```
538
+ *
539
+ * `name` addresses the question, so two calls naming one question in one
540
+ * execution await one answer — the same reading {@link module:WaitFor} takes,
541
+ * for the same reason: a person has to be able to name what they are answering.
542
+ *
543
+ * @category constructors
544
+ * @since 0.1.0
545
+ */
546
+ export const action: Action.Declared<
547
+ typeof tag,
548
+ Schema.Struct<typeof payloadFields>,
549
+ typeof Schema.Json,
550
+ typeof HumanTaskFailed,
551
+ never
552
+ > = Action.makeSystem(tag, {
553
+ payload: payloadFields,
554
+ success: Schema.Json,
555
+ error: HumanTaskFailed,
556
+ tier: "sealed"
557
+ })
558
+
559
+ /** The payload the action is called with, as its implementation reads it. */
560
+ type Payload = typeof action.payloadSchema.Type
561
+
562
+ /**
563
+ * The question a park publishes about itself, as the JSON text the durable
564
+ * waiting row stores.
565
+ *
566
+ * It is the payload's own fields, narrowed to what an interface needs to
567
+ * render an answer box and refuse a bad answer before a person sends it: the
568
+ * kind picks the control, the prompt is the question, `options` fills a
569
+ * select, `schema` validates a JSON answer, and the two attempt numbers say
570
+ * how much of the budget is left. The answer VALUE never appears here — this
571
+ * describes the question, not what anybody said.
572
+ *
573
+ * @private
574
+ */
575
+ const declaredQuestion = (
576
+ payload: Payload,
577
+ attempt: number,
578
+ maxAttempts: number
579
+ ): string =>
580
+ JSON.stringify({
581
+ task: "human",
582
+ name: payload.name,
583
+ kind: payload.kind,
584
+ prompt: payload.prompt,
585
+ attempt,
586
+ maxAttempts,
587
+ ...(payload.options === undefined ? {} : { options: [...payload.options] }),
588
+ ...(payload.schema === undefined ? {} : { schema: payload.schema })
589
+ })
590
+
591
+ /** Builds the failure a task settles with, with the reasons it refused. */
592
+ const failed = (
593
+ payload: Payload,
594
+ code: typeof HumanTaskFailed.Type["code"],
595
+ attempts: number,
596
+ rejections: ReadonlyArray<string>,
597
+ message: string
598
+ ): HumanTaskFailed => new HumanTaskFailed({ code, task: payload.name, attempts, rejections, message })
599
+
600
+ interface RetainedRejections {
601
+ readonly entries: Array<string>
602
+ chars: number
603
+ omitted: number
604
+ }
605
+
606
+ /** Describes the tail of a rejection history that could not be retained. */
607
+ const omissionMarker = (count: number): string => `${count} further rejections were omitted.`
608
+
609
+ /** Adds one rejection while keeping the terminal rejection history bounded. */
610
+ const retainRejection = (state: RetainedRejections, rejection: string): void => {
611
+ const alreadyOmitting = state.omitted > 0
612
+ if (alreadyOmitting) {
613
+ const previousMarker = state.entries.pop()!
614
+ state.chars -= previousMarker.length
615
+ }
616
+ if (!alreadyOmitting && state.chars + rejection.length <= maxRetainedRejectionChars) {
617
+ state.entries.push(rejection)
618
+ state.chars += rejection.length
619
+ return
620
+ }
621
+ state.omitted++
622
+ let marker = omissionMarker(state.omitted)
623
+ while (state.chars + marker.length > maxRetainedRejectionChars) {
624
+ const removed = state.entries.pop()!
625
+ state.chars -= removed.length
626
+ state.omitted++
627
+ marker = omissionMarker(state.omitted)
628
+ }
629
+ state.entries.push(marker)
630
+ state.chars += marker.length
631
+ }
632
+
633
+ /**
634
+ * The attempt budget a payload asks for, refused when it is not a whole number
635
+ * of attempts.
636
+ *
637
+ * @private
638
+ */
639
+ const budgetOf = (payload: Payload): Effect.Effect<number, HumanTaskFailed> => {
640
+ const maxAttempts = payload.maxAttempts ?? defaultMaxAttempts
641
+ if (!Number.isInteger(maxAttempts) || maxAttempts < 1) {
642
+ return Effect.fail(
643
+ failed(
644
+ payload,
645
+ "request_invalid",
646
+ 0,
647
+ [],
648
+ `${tag} was called with maxAttempts ${maxAttempts}. A question is asked at least once.`
649
+ )
650
+ )
651
+ }
652
+ return maxAttempts <= maxAttemptBudget
653
+ ? Effect.succeed(maxAttempts)
654
+ : Effect.fail(
655
+ failed(
656
+ payload,
657
+ "request_invalid",
658
+ 0,
659
+ [],
660
+ `${tag} was called with maxAttempts ${maxAttempts}. A question asked more than ` +
661
+ `${maxAttemptBudget} times is a stuck question.`
662
+ )
663
+ )
664
+ }
665
+
666
+ /**
667
+ * The deadline a payload asks for, refused when it is not a length of time.
668
+ *
669
+ * `Duration.millis` takes any number, so an unchecked deadline does not fail —
670
+ * it changes what the question means. `NaN` becomes zero and a negative stays
671
+ * negative, so both are deadlines that have ALREADY passed: the task times out
672
+ * on its first park and nobody is ever really asked. `Infinity` becomes the
673
+ * infinite duration, so the race has a branch that can never win and a question
674
+ * asked with a deadline has none. All three are the same authoring mistake as a
675
+ * `select` with no options, and they are refused in the same place, before the
676
+ * first park, rather than surfacing as a `timeout` nobody waited for.
677
+ *
678
+ * @private
679
+ */
680
+ const deadlineOf = (payload: Payload): Effect.Effect<Duration.Duration | undefined, HumanTaskFailed> => {
681
+ const timeoutMs = payload.timeoutMs
682
+ if (timeoutMs === undefined) return Effect.succeed(undefined)
683
+ return Number.isFinite(timeoutMs) && timeoutMs >= 0
684
+ ? Effect.succeed(Duration.millis(timeoutMs))
685
+ : Effect.fail(
686
+ failed(
687
+ payload,
688
+ "request_invalid",
689
+ 0,
690
+ [],
691
+ `${tag} was called with timeoutMs ${timeoutMs}. A deadline is a finite number of ` +
692
+ "milliseconds that is not negative; the question would be over before it was asked, or " +
693
+ "never over at all."
694
+ )
695
+ )
696
+ }
697
+
698
+ /**
699
+ * Refuses a question nobody could answer correctly, before anyone is asked.
700
+ *
701
+ * A `select` with no options and a schema outside the supported subset are
702
+ * authoring mistakes whose only symptom at answer time would be a person being
703
+ * refused for something they did not do, so {@link validateSchema} walks the
704
+ * whole schema tree before the first park rather than waiting for an answer to
705
+ * reach the keyword nobody can enforce.
706
+ *
707
+ * An `options` list on a `json` question is ignored because it constrains
708
+ * nothing; JSON constraints come only from `schema`.
709
+ *
710
+ * @private
711
+ */
712
+ const requestOf = (payload: Payload): Effect.Effect<Request, HumanTaskFailed> => {
713
+ const request: Request = {
714
+ kind: payload.kind,
715
+ options: payload.options,
716
+ ...(payload.schema === undefined ? {} : { schema: payload.schema })
717
+ }
718
+ if (payload.schema !== undefined && payload.kind !== "json") {
719
+ return Effect.fail(
720
+ failed(
721
+ payload,
722
+ "request_invalid",
723
+ 0,
724
+ [],
725
+ `A schema describes a "json" answer, and this question is an "${payload.kind}".`
726
+ )
727
+ )
728
+ }
729
+ if (payload.kind === "select" && (payload.options === undefined || payload.options.length === 0)) {
730
+ return Effect.fail(
731
+ failed(payload, "request_invalid", 0, [], `${tag} was called as a select with no options to choose from.`)
732
+ )
733
+ }
734
+ if (payload.kind === "json" && payload.schema !== undefined) {
735
+ const complaint = validateSchema(payload.schema)
736
+ if (complaint !== undefined) return Effect.fail(failed(payload, "request_invalid", 0, [], complaint))
737
+ }
738
+ return Effect.succeed(request)
739
+ }
740
+
741
+ /**
742
+ * Awaits one attempt, racing the answer against the task's deadline.
743
+ *
744
+ * The race is named per attempt because a durable race records its winner: one
745
+ * name across attempts would replay the first attempt's answer forever. The
746
+ * clock is NOT named per attempt, for the mirrored reason — the deadline is one
747
+ * fact about the question.
748
+ *
749
+ * @private
750
+ */
751
+ const attemptOnce = (
752
+ payload: Payload,
753
+ attempt: number,
754
+ deadline: Duration.Duration | undefined
755
+ ): Effect.Effect<Settled, never, Crypto.Crypto | FlowRuntime | FlowInstance> => {
756
+ const answered: Effect.Effect<Settled, never, FlowRuntime | FlowInstance> = Effect.map(
757
+ DurableDeferred.await(deferred(payload.name, attempt)),
758
+ (value): Settled => ({ _tag: "answered", value })
759
+ )
760
+ if (deadline === undefined) return answered
761
+ return DurableDeferred.raceAll({
762
+ name: `HumanTask/${payload.name}#${attempt}`,
763
+ success: Settled,
764
+ error: Schema.Never,
765
+ effects: [
766
+ answered,
767
+ Effect.as(
768
+ DurableClock.sleep({
769
+ name: timeoutClockName(payload.name),
770
+ duration: deadline,
771
+ // The wait is the point: the question parks the execution rather than
772
+ // holding a fiber open for however long a person takes.
773
+ inMemoryThreshold: Duration.zero
774
+ }),
775
+ { _tag: "timeout" } as const
776
+ )
777
+ ]
778
+ })
779
+ }
780
+
781
+ /**
782
+ * What a refusal records: which question, which attempt, and why the answer
783
+ * could not be accepted.
784
+ *
785
+ * @private
786
+ */
787
+ const RejectionRecord = Schema.Struct({
788
+ task: Schema.String,
789
+ attempt: Schema.Number,
790
+ reason: Schema.String
791
+ })
792
+
793
+ /**
794
+ * Records that an answer was refused, as a step rather than as a log line.
795
+ *
796
+ * A refusal is a decision the run made about something a person did, and it is
797
+ * the only part of the exchange that is not already durable: the answer is
798
+ * recorded under its own wait point and the re-ask is recorded as the next
799
+ * one, but WHY the answer was refused would otherwise live in a log stream
800
+ * nobody replays. `Action.make` is the recorded boundary the rest of this
801
+ * package already writes through — {@link module:DurableClock.sleep} takes it
802
+ * for an in-memory wait — so the refusal is dispatched, journaled, and
803
+ * replayed like any other sealed step, under a name that carries the task and
804
+ * the attempt it refused.
805
+ *
806
+ * The payload names no time. A record whose contents depend on the wall clock
807
+ * would differ between the first run and its replay, which is the one thing a
808
+ * journaled decision may never do.
809
+ *
810
+ * @private
811
+ */
812
+ const recordRejection = (task: string, attempt: number, reason: string) =>
813
+ Action.make({
814
+ name: `HumanTask/${task}#${attempt}/rejected`,
815
+ tier: "sealed",
816
+ success: RejectionRecord,
817
+ execute: Effect.succeed({ task, attempt, reason })
818
+ })
819
+
820
+ /**
821
+ * The human-task implementation: park, validate, re-ask, settle.
822
+ *
823
+ * Provide it beside the other action implementation layers a body calls, over
824
+ * the {@link module:Implementations.layerImplementations} table they file
825
+ * themselves in:
826
+ *
827
+ * ```ts
828
+ * Layer.mergeAll(HumanTask.layer, Interpreter.layer(Release)).pipe(
829
+ * Layer.provideMerge(Action.layerImplementations)
830
+ * )
831
+ * ```
832
+ *
833
+ * @category layers
834
+ * @since 0.1.0
835
+ */
836
+ export const layer: Layer.Layer<never, never, Crypto.Crypto | FlowRuntime> = action.toLayer((payload) =>
837
+ Effect.gen(function*() {
838
+ const instance = yield* FlowInstance
839
+ const maxAttempts = yield* budgetOf(payload)
840
+ const deadline = yield* deadlineOf(payload)
841
+ const request = yield* requestOf(payload)
842
+ const retained: RetainedRejections = { entries: [], chars: 0, omitted: 0 }
843
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
844
+ const token = DurableDeferred.tokenFromExecutionId(deferred(payload.name, attempt), {
845
+ flow: instance.flow,
846
+ executionId: instance.executionId
847
+ })
848
+ // Declared rather than left to a driver's derivation, so the run parks
849
+ // under `approval` carrying the ONE wait point that is currently open.
850
+ // The question travels with the park for a different reason than the
851
+ // token does: the token addresses the wait, and the question is what an
852
+ // inbox has to render for a person to answer it at all. Without it a
853
+ // parked run carried nothing but a wait name, so run-3's
854
+ // `coding-clarification` could be listed and never asked.
855
+ yield* annotateWaiting({ reason: "approval", token, request: declaredQuestion(payload, attempt, maxAttempts) })
856
+ const settled = yield* attemptOnce(payload, attempt, deadline)
857
+ // The attempt is over either way, so the declared park is over too. A
858
+ // raced attempt awaits on a copied instance, so the branch that resolved
859
+ // could not clear the annotation itself.
860
+ yield* annotateWaiting(undefined)
861
+ if (settled._tag === "timeout") {
862
+ return yield* Effect.fail(
863
+ failed(
864
+ payload,
865
+ "timeout",
866
+ attempt,
867
+ retained.entries,
868
+ `Nobody answered "${payload.name}" within ${payload.timeoutMs} ms.`
869
+ )
870
+ )
871
+ }
872
+ const rejection = validate(settled.value, request)
873
+ if (rejection === undefined) return settled.value
874
+ retainRejection(retained, `attempt ${attempt}: ${rejection}`)
875
+ yield* recordRejection(payload.name, attempt, rejection)
876
+ }
877
+ return yield* Effect.fail(
878
+ failed(
879
+ payload,
880
+ "rejected",
881
+ maxAttempts,
882
+ retained.entries,
883
+ `"${payload.name}" was asked ${maxAttempts} times without an answer it could accept.`
884
+ )
885
+ )
886
+ })
887
+ )
888
+
889
+ /**
890
+ * Records one answer to a human task.
891
+ *
892
+ * `token` is the value the run parked with — the `token` of the waiting
893
+ * annotation, which is the wait point the current attempt is open on. The
894
+ * runtime checks that exact approval wait and records the completion as one
895
+ * mutation, so guessed, unopened, or stale attempt tokens cannot pre-answer a
896
+ * run. An admitted answer then resumes the run through the ordinary durable
897
+ * deferred path.
898
+ *
899
+ * The token is not a credential: anyone who knows or derives the address of
900
+ * the open attempt can answer it. The host decides who may answer, and must
901
+ * authorize the caller before calling `answer`.
902
+ *
903
+ * ```ts
904
+ * yield* HumanTask.answer({ token: waiting.token, value: { decision: "ship" } })
905
+ * ```
906
+ *
907
+ * The durable JSON boundary is validated here: the value must be inert,
908
+ * detached, and within the exported depth, node, member, string, key, and byte
909
+ * limits. Whether that JSON fits the question is the task's own judgment, made
910
+ * where its kind and schema are known; a semantically refused answer stays
911
+ * recorded so the record shows what was actually said. Call {@link validate}
912
+ * first when the interface can refuse it while the person is still looking at
913
+ * it.
914
+ *
915
+ * The TOKEN is checked. This entry point completes an arbitrary caller-supplied
916
+ * address under `Schema.Json`, so it accepts only a token whose deferred name
917
+ * {@link deferred} could have written. A token for a `DurableQueue` item, a
918
+ * plain {@link module:WaitFor} gate, or an unrelated flow's deferred fails with
919
+ * `TokenInvalid` carrying `deferred_mismatch` rather than writing a JSON exit
920
+ * into a row another schema will decode.
921
+ *
922
+ * A syntactically valid HumanTask token can still fail with
923
+ * `HumanAnswerInvalid` carrying `answer_not_open` when the addressed run is not
924
+ * currently parked on that exact approval token.
925
+ *
926
+ * @category combinators
927
+ * @since 0.1.0
928
+ */
929
+ export const answer = (options: {
930
+ readonly token: DurableDeferred.Token
931
+ readonly value: typeof Schema.Json.Type
932
+ }): Effect.Effect<void, DurableDeferred.TokenInvalid | HumanAnswerInvalid, FlowRuntime> =>
933
+ Effect.gen(function*() {
934
+ const admitted = BoundedJson.admit(options.value, JsonSchemaSubset.answerLimits)
935
+ if (!admitted.ok) {
936
+ return yield* Effect.fail(
937
+ new HumanAnswerInvalid({
938
+ message: `The human-task answer was not recorded: ${JsonSchemaSubset.truncateDiagnostic(admitted.complaint)}`
939
+ })
940
+ )
941
+ }
942
+ const parsed = yield* DurableDeferred.TokenParsed.parse(options.token)
943
+ const target = answerableDeferred(parsed.deferredName)
944
+ if (target === undefined) {
945
+ return yield* Effect.fail(
946
+ new DurableDeferred.TokenInvalid({
947
+ code: "deferred_mismatch",
948
+ message:
949
+ `The token addresses deferred "${
950
+ JsonSchemaSubset.truncateDiagnostic(parsed.deferredName)
951
+ }", which is not a ` +
952
+ "human task wait point. Answer it through the surface that owns it."
953
+ })
954
+ )
955
+ }
956
+ const runtime = yield* FlowRuntime
957
+ const outcome = yield* runtime.deferredDoneIfWaiting(target, {
958
+ flowName: parsed.flowName,
959
+ executionId: parsed.executionId,
960
+ deferredName: parsed.deferredName,
961
+ reason: "approval",
962
+ token: options.token,
963
+ exit: Exit.succeed(admitted.value)
964
+ })
965
+ if (outcome === "NotWaiting") {
966
+ return yield* Effect.fail(
967
+ new HumanAnswerInvalid({
968
+ code: "answer_not_open",
969
+ message: "The human-task answer was not recorded because the run is not parked on this approval token."
970
+ })
971
+ )
972
+ }
973
+ })
974
+
975
+ /**
976
+ * Gives an answer the caller's own type.
977
+ *
978
+ * The action's success schema is `Schema.Json`, because what a person may
979
+ * answer is described by the task's payload rather than by a TypeScript type.
980
+ * `decode` is the other half: the author states the schema they were really
981
+ * asking for, and the node downstream of the question carries that type.
982
+ *
983
+ * ```ts
984
+ * const Decision = Schema.Struct({ decision: Schema.Literals(["ship", "hold"]) })
985
+ *
986
+ * HumanTask.action.call({ name: "release", kind: "json", prompt, schema }).pipe(
987
+ * HumanTask.decode(Decision)
988
+ * )
989
+ * ```
990
+ *
991
+ * The two descriptions must agree. The answer already passed the task's own
992
+ * JSON Schema before it reached here, so a value this schema rejects means the
993
+ * payload's schema and the author's schema describe different answers — an
994
+ * authoring mistake, not a human one — and it surfaces as a defect naming the
995
+ * offending path rather than as a failure a body could sensibly catch.
996
+ *
997
+ * @category combinators
998
+ * @since 0.1.0
999
+ */
1000
+ export const decode =
1001
+ <S extends Schema.ConstraintDecoder<unknown>>(schema: S) =>
1002
+ <E, R>(self: Node.Node<typeof Schema.Json.Type, E, R>): Node.Node<S["Type"], E, R> =>
1003
+ Node.map(self, Schema.decodeUnknownSync(schema))