@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.
- package/CHANGELOG.md +160 -0
- package/LICENSE +21 -0
- package/README.md +210 -2
- package/THIRD_PARTY_NOTICES.md +52 -0
- package/dist/cjs/Action/Action.d.ts +250 -0
- package/dist/cjs/Action/Action.d.ts.map +1 -0
- package/dist/cjs/Action/Action.js +42 -0
- package/dist/cjs/Action/Action.js.map +7 -0
- package/dist/cjs/Action/AttemptTimedOut.d.ts +33 -0
- package/dist/cjs/Action/AttemptTimedOut.d.ts.map +1 -0
- package/dist/cjs/Action/AttemptTimedOut.js +51 -0
- package/dist/cjs/Action/AttemptTimedOut.js.map +7 -0
- package/dist/cjs/Action/BoundaryMode.d.ts +29 -0
- package/dist/cjs/Action/BoundaryMode.d.ts.map +1 -0
- package/dist/cjs/Action/BoundaryMode.js +36 -0
- package/dist/cjs/Action/BoundaryMode.js.map +7 -0
- package/dist/cjs/Action/CacheEnvironment.d.ts +158 -0
- package/dist/cjs/Action/CacheEnvironment.d.ts.map +1 -0
- package/dist/cjs/Action/CacheEnvironment.js +57 -0
- package/dist/cjs/Action/CacheEnvironment.js.map +7 -0
- package/dist/cjs/Action/ConcurrentKeylessDispatch.d.ts +34 -0
- package/dist/cjs/Action/ConcurrentKeylessDispatch.d.ts.map +1 -0
- package/dist/cjs/Action/ConcurrentKeylessDispatch.js +46 -0
- package/dist/cjs/Action/ConcurrentKeylessDispatch.js.map +7 -0
- package/dist/cjs/Action/Context.d.ts +131 -0
- package/dist/cjs/Action/Context.d.ts.map +1 -0
- package/dist/cjs/Action/Context.js +68 -0
- package/dist/cjs/Action/Context.js.map +7 -0
- package/dist/cjs/Action/DuplicateImplementation.d.ts +20 -0
- package/dist/cjs/Action/DuplicateImplementation.d.ts.map +1 -0
- package/dist/cjs/Action/DuplicateImplementation.js +46 -0
- package/dist/cjs/Action/DuplicateImplementation.js.map +7 -0
- package/dist/cjs/Action/FileBoundary.d.ts +59 -0
- package/dist/cjs/Action/FileBoundary.d.ts.map +1 -0
- package/dist/cjs/Action/FileBoundary.js +81 -0
- package/dist/cjs/Action/FileBoundary.js.map +7 -0
- package/dist/cjs/Action/FileInput.d.ts +28 -0
- package/dist/cjs/Action/FileInput.d.ts.map +1 -0
- package/dist/cjs/Action/FileInput.js +42 -0
- package/dist/cjs/Action/FileInput.js.map +7 -0
- package/dist/cjs/Action/Filegroup.d.ts +16 -0
- package/dist/cjs/Action/Filegroup.d.ts.map +1 -0
- package/dist/cjs/Action/Filegroup.js +27 -0
- package/dist/cjs/Action/Filegroup.js.map +7 -0
- package/dist/cjs/Action/Glob.d.ts +8 -0
- package/dist/cjs/Action/Glob.d.ts.map +1 -0
- package/dist/cjs/Action/Glob.js +28 -0
- package/dist/cjs/Action/Glob.js.map +7 -0
- package/dist/cjs/Action/ImplementationVersionMismatch.d.ts +26 -0
- package/dist/cjs/Action/ImplementationVersionMismatch.d.ts.map +1 -0
- package/dist/cjs/Action/ImplementationVersionMismatch.js +45 -0
- package/dist/cjs/Action/ImplementationVersionMismatch.js.map +7 -0
- package/dist/cjs/Action/Implementations.d.ts +114 -0
- package/dist/cjs/Action/Implementations.d.ts.map +1 -0
- package/dist/cjs/Action/Implementations.js +65 -0
- package/dist/cjs/Action/Implementations.js.map +7 -0
- package/dist/cjs/Action/InfraInterrupt.d.ts +26 -0
- package/dist/cjs/Action/InfraInterrupt.d.ts.map +1 -0
- package/dist/cjs/Action/InfraInterrupt.js +46 -0
- package/dist/cjs/Action/InfraInterrupt.js.map +7 -0
- package/dist/cjs/Action/InfraInterruptRetriesExhausted.d.ts +33 -0
- package/dist/cjs/Action/InfraInterruptRetriesExhausted.d.ts.map +1 -0
- package/dist/cjs/Action/InfraInterruptRetriesExhausted.js +54 -0
- package/dist/cjs/Action/InfraInterruptRetriesExhausted.js.map +7 -0
- package/dist/cjs/Action/IrreversibleRetryRequiresIdempotencyKey.d.ts +26 -0
- package/dist/cjs/Action/IrreversibleRetryRequiresIdempotencyKey.d.ts.map +1 -0
- package/dist/cjs/Action/IrreversibleRetryRequiresIdempotencyKey.js +47 -0
- package/dist/cjs/Action/IrreversibleRetryRequiresIdempotencyKey.js.map +7 -0
- package/dist/cjs/Action/StepIdentity.d.ts +153 -0
- package/dist/cjs/Action/StepIdentity.d.ts.map +1 -0
- package/dist/cjs/Action/StepIdentity.js +75 -0
- package/dist/cjs/Action/StepIdentity.js.map +7 -0
- package/dist/cjs/Action/TreeArtifact.d.ts +8 -0
- package/dist/cjs/Action/TreeArtifact.d.ts.map +1 -0
- package/dist/cjs/Action/TreeArtifact.js +25 -0
- package/dist/cjs/Action/TreeArtifact.js.map +7 -0
- package/dist/cjs/Action/TypeId.d.ts +8 -0
- package/dist/cjs/Action/TypeId.d.ts.map +1 -0
- package/dist/cjs/Action/TypeId.js +25 -0
- package/dist/cjs/Action/TypeId.js.map +7 -0
- package/dist/cjs/Action/UncanonicalIdempotencyKey.d.ts +32 -0
- package/dist/cjs/Action/UncanonicalIdempotencyKey.d.ts.map +1 -0
- package/dist/cjs/Action/UncanonicalIdempotencyKey.js +51 -0
- package/dist/cjs/Action/UncanonicalIdempotencyKey.js.map +7 -0
- package/dist/cjs/Action/idempotencyKey.d.ts +21 -0
- package/dist/cjs/Action/idempotencyKey.d.ts.map +1 -0
- package/dist/cjs/Action/idempotencyKey.js +59 -0
- package/dist/cjs/Action/idempotencyKey.js.map +7 -0
- package/dist/cjs/Action/index.d.ts +29 -0
- package/dist/cjs/Action/index.d.ts.map +1 -0
- package/dist/cjs/Action/index.js +60 -0
- package/dist/cjs/Action/index.js.map +7 -0
- package/dist/cjs/Action/make.d.ts +128 -0
- package/dist/cjs/Action/make.d.ts.map +1 -0
- package/dist/cjs/Action/make.js +373 -0
- package/dist/cjs/Action/make.js.map +7 -0
- package/dist/cjs/Action/raceAll.d.ts +21 -0
- package/dist/cjs/Action/raceAll.d.ts.map +1 -0
- package/dist/cjs/Action/raceAll.js +46 -0
- package/dist/cjs/Action/raceAll.js.map +7 -0
- package/dist/cjs/Action/retry.d.ts +19 -0
- package/dist/cjs/Action/retry.d.ts.map +1 -0
- package/dist/cjs/Action/retry.js +75 -0
- package/dist/cjs/Action/retry.js.map +7 -0
- package/dist/cjs/Deadline.d.ts +105 -0
- package/dist/cjs/Deadline.d.ts.map +1 -0
- package/dist/cjs/Deadline.js +104 -0
- package/dist/cjs/Deadline.js.map +7 -0
- package/dist/cjs/DurableClock.d.ts +61 -0
- package/dist/cjs/DurableClock.d.ts.map +1 -0
- package/dist/cjs/DurableClock.js +90 -0
- package/dist/cjs/DurableClock.js.map +7 -0
- package/dist/cjs/DurableDeferred.d.ts +311 -0
- package/dist/cjs/DurableDeferred.d.ts.map +1 -0
- package/dist/cjs/DurableDeferred.js +322 -0
- package/dist/cjs/DurableDeferred.js.map +7 -0
- package/dist/cjs/DurableQueue.d.ts +160 -0
- package/dist/cjs/DurableQueue.d.ts.map +1 -0
- package/dist/cjs/DurableQueue.js +229 -0
- package/dist/cjs/DurableQueue.js.map +7 -0
- package/dist/cjs/ExternalJob.d.ts +179 -0
- package/dist/cjs/ExternalJob.d.ts.map +1 -0
- package/dist/cjs/ExternalJob.js +338 -0
- package/dist/cjs/ExternalJob.js.map +7 -0
- package/dist/cjs/Fault.d.ts +131 -0
- package/dist/cjs/Fault.d.ts.map +1 -0
- package/dist/cjs/Fault.js +157 -0
- package/dist/cjs/Fault.js.map +7 -0
- package/dist/cjs/Flow/Annotations.d.ts +245 -0
- package/dist/cjs/Flow/Annotations.d.ts.map +1 -0
- package/dist/cjs/Flow/Annotations.js +72 -0
- package/dist/cjs/Flow/Annotations.js.map +7 -0
- package/dist/cjs/Flow/CapabilityCeiling.d.ts +21 -0
- package/dist/cjs/Flow/CapabilityCeiling.d.ts.map +1 -0
- package/dist/cjs/Flow/CapabilityCeiling.js +49 -0
- package/dist/cjs/Flow/CapabilityCeiling.js.map +7 -0
- package/dist/cjs/Flow/DeadlineExceeded.d.ts +33 -0
- package/dist/cjs/Flow/DeadlineExceeded.d.ts.map +1 -0
- package/dist/cjs/Flow/DeadlineExceeded.js +52 -0
- package/dist/cjs/Flow/DeadlineExceeded.js.map +7 -0
- package/dist/cjs/Flow/ExecutionIdRequired.d.ts +25 -0
- package/dist/cjs/Flow/ExecutionIdRequired.d.ts.map +1 -0
- package/dist/cjs/Flow/ExecutionIdRequired.js +46 -0
- package/dist/cjs/Flow/ExecutionIdRequired.js.map +7 -0
- package/dist/cjs/Flow/ExecutionIds.d.ts +80 -0
- package/dist/cjs/Flow/ExecutionIds.d.ts.map +1 -0
- package/dist/cjs/Flow/ExecutionIds.js +66 -0
- package/dist/cjs/Flow/ExecutionIds.js.map +7 -0
- package/dist/cjs/Flow/Flow.d.ts +422 -0
- package/dist/cjs/Flow/Flow.d.ts.map +1 -0
- package/dist/cjs/Flow/Flow.js +17 -0
- package/dist/cjs/Flow/Flow.js.map +7 -0
- package/dist/cjs/Flow/MaxRoundsExceeded.d.ts +35 -0
- package/dist/cjs/Flow/MaxRoundsExceeded.d.ts.map +1 -0
- package/dist/cjs/Flow/MaxRoundsExceeded.js +50 -0
- package/dist/cjs/Flow/MaxRoundsExceeded.js.map +7 -0
- package/dist/cjs/Flow/Outcome.d.ts +162 -0
- package/dist/cjs/Flow/Outcome.d.ts.map +1 -0
- package/dist/cjs/Flow/Outcome.js +80 -0
- package/dist/cjs/Flow/Outcome.js.map +7 -0
- package/dist/cjs/Flow/Result.d.ts +186 -0
- package/dist/cjs/Flow/Result.d.ts.map +1 -0
- package/dist/cjs/Flow/Result.js +159 -0
- package/dist/cjs/Flow/Result.js.map +7 -0
- package/dist/cjs/Flow/Runtime.d.ts +98 -0
- package/dist/cjs/Flow/Runtime.d.ts.map +1 -0
- package/dist/cjs/Flow/Runtime.js +160 -0
- package/dist/cjs/Flow/Runtime.js.map +7 -0
- package/dist/cjs/Flow/TypeId.d.ts +8 -0
- package/dist/cjs/Flow/TypeId.d.ts.map +1 -0
- package/dist/cjs/Flow/TypeId.js +25 -0
- package/dist/cjs/Flow/TypeId.js.map +7 -0
- package/dist/cjs/Flow/index.d.ts +17 -0
- package/dist/cjs/Flow/index.d.ts.map +1 -0
- package/dist/cjs/Flow/index.js +29 -0
- package/dist/cjs/Flow/index.js.map +7 -0
- package/dist/cjs/Flow/internal.d.ts +34 -0
- package/dist/cjs/Flow/internal.d.ts.map +1 -0
- package/dist/cjs/Flow/internal.js +187 -0
- package/dist/cjs/Flow/internal.js.map +7 -0
- package/dist/cjs/Flow/make.d.ts +134 -0
- package/dist/cjs/Flow/make.d.ts.map +1 -0
- package/dist/cjs/Flow/make.js +104 -0
- package/dist/cjs/Flow/make.js.map +7 -0
- package/dist/cjs/FlowRuntime/CancelRequestFailed.d.ts +55 -0
- package/dist/cjs/FlowRuntime/CancelRequestFailed.d.ts.map +1 -0
- package/dist/cjs/FlowRuntime/CancelRequestFailed.js +51 -0
- package/dist/cjs/FlowRuntime/CancelRequestFailed.js.map +7 -0
- package/dist/cjs/FlowRuntime/ExecutionIdentityConflict.d.ts +23 -0
- package/dist/cjs/FlowRuntime/ExecutionIdentityConflict.d.ts.map +1 -0
- package/dist/cjs/FlowRuntime/ExecutionIdentityConflict.js +55 -0
- package/dist/cjs/FlowRuntime/ExecutionIdentityConflict.js.map +7 -0
- package/dist/cjs/FlowRuntime/FlowCycleDetected.d.ts +28 -0
- package/dist/cjs/FlowRuntime/FlowCycleDetected.d.ts.map +1 -0
- package/dist/cjs/FlowRuntime/FlowCycleDetected.js +49 -0
- package/dist/cjs/FlowRuntime/FlowCycleDetected.js.map +7 -0
- package/dist/cjs/FlowRuntime/FlowExecutionNotFound.d.ts +38 -0
- package/dist/cjs/FlowRuntime/FlowExecutionNotFound.d.ts.map +1 -0
- package/dist/cjs/FlowRuntime/FlowExecutionNotFound.js +53 -0
- package/dist/cjs/FlowRuntime/FlowExecutionNotFound.js.map +7 -0
- package/dist/cjs/FlowRuntime/FlowInstance.d.ts +115 -0
- package/dist/cjs/FlowRuntime/FlowInstance.d.ts.map +1 -0
- package/dist/cjs/FlowRuntime/FlowInstance.js +37 -0
- package/dist/cjs/FlowRuntime/FlowInstance.js.map +7 -0
- package/dist/cjs/FlowRuntime/FlowRuntime.d.ts +198 -0
- package/dist/cjs/FlowRuntime/FlowRuntime.d.ts.map +1 -0
- package/dist/cjs/FlowRuntime/FlowRuntime.js +37 -0
- package/dist/cjs/FlowRuntime/FlowRuntime.js.map +7 -0
- package/dist/cjs/FlowRuntime/NodeRecord.d.ts +175 -0
- package/dist/cjs/FlowRuntime/NodeRecord.d.ts.map +1 -0
- package/dist/cjs/FlowRuntime/NodeRecord.js +17 -0
- package/dist/cjs/FlowRuntime/NodeRecord.js.map +7 -0
- package/dist/cjs/FlowRuntime/WaitingAnnotation.d.ts +69 -0
- package/dist/cjs/FlowRuntime/WaitingAnnotation.d.ts.map +1 -0
- package/dist/cjs/FlowRuntime/WaitingAnnotation.js +53 -0
- package/dist/cjs/FlowRuntime/WaitingAnnotation.js.map +7 -0
- package/dist/cjs/FlowRuntime/index.d.ts +14 -0
- package/dist/cjs/FlowRuntime/index.d.ts.map +1 -0
- package/dist/cjs/FlowRuntime/index.js +26 -0
- package/dist/cjs/FlowRuntime/index.js.map +7 -0
- package/dist/cjs/Graph.d.ts +325 -0
- package/dist/cjs/Graph.d.ts.map +1 -0
- package/dist/cjs/Graph.js +1022 -0
- package/dist/cjs/Graph.js.map +7 -0
- package/dist/cjs/HumanTask.d.ts +440 -0
- package/dist/cjs/HumanTask.d.ts.map +1 -0
- package/dist/cjs/HumanTask.js +413 -0
- package/dist/cjs/HumanTask.js.map +7 -0
- package/dist/cjs/Interpreter.d.ts +222 -0
- package/dist/cjs/Interpreter.d.ts.map +1 -0
- package/dist/cjs/Interpreter.js +888 -0
- package/dist/cjs/Interpreter.js.map +7 -0
- package/dist/cjs/Poll.d.ts +238 -0
- package/dist/cjs/Poll.d.ts.map +1 -0
- package/dist/cjs/Poll.js +150 -0
- package/dist/cjs/Poll.js.map +7 -0
- package/dist/cjs/RetryPolicy.d.ts +273 -0
- package/dist/cjs/RetryPolicy.d.ts.map +1 -0
- package/dist/cjs/RetryPolicy.js +251 -0
- package/dist/cjs/RetryPolicy.js.map +7 -0
- package/dist/cjs/Sleep.d.ts +98 -0
- package/dist/cjs/Sleep.d.ts.map +1 -0
- package/dist/cjs/Sleep.js +133 -0
- package/dist/cjs/Sleep.js.map +7 -0
- package/dist/cjs/Stall.d.ts +173 -0
- package/dist/cjs/Stall.d.ts.map +1 -0
- package/dist/cjs/Stall.js +92 -0
- package/dist/cjs/Stall.js.map +7 -0
- package/dist/cjs/WaitFor.d.ts +109 -0
- package/dist/cjs/WaitFor.d.ts.map +1 -0
- package/dist/cjs/WaitFor.js +117 -0
- package/dist/cjs/WaitFor.js.map +7 -0
- package/dist/cjs/index.d.ts +107 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +69 -0
- package/dist/cjs/index.js.map +7 -0
- package/dist/cjs/internal/BoundedJson.d.ts +48 -0
- package/dist/cjs/internal/BoundedJson.d.ts.map +1 -0
- package/dist/cjs/internal/BoundedJson.js +96 -0
- package/dist/cjs/internal/BoundedJson.js.map +7 -0
- package/dist/cjs/internal/DeclarationSite.d.ts +135 -0
- package/dist/cjs/internal/DeclarationSite.d.ts.map +1 -0
- package/dist/cjs/internal/DeclarationSite.js +89 -0
- package/dist/cjs/internal/DeclarationSite.js.map +7 -0
- package/dist/cjs/internal/Declarations.d.ts +35 -0
- package/dist/cjs/internal/Declarations.d.ts.map +1 -0
- package/dist/cjs/internal/Declarations.js +50 -0
- package/dist/cjs/internal/Declarations.js.map +7 -0
- package/dist/cjs/internal/ExecutionMiddleware.d.ts +21 -0
- package/dist/cjs/internal/ExecutionMiddleware.d.ts.map +1 -0
- package/dist/cjs/internal/ExecutionMiddleware.js +39 -0
- package/dist/cjs/internal/ExecutionMiddleware.js.map +7 -0
- package/dist/cjs/internal/JsonSchemaSubset.d.ts +133 -0
- package/dist/cjs/internal/JsonSchemaSubset.d.ts.map +1 -0
- package/dist/cjs/internal/JsonSchemaSubset.js +229 -0
- package/dist/cjs/internal/JsonSchemaSubset.js.map +7 -0
- package/dist/cjs/internal/OutcomeMarker.d.ts +18 -0
- package/dist/cjs/internal/OutcomeMarker.d.ts.map +1 -0
- package/dist/cjs/internal/OutcomeMarker.js +27 -0
- package/dist/cjs/internal/OutcomeMarker.js.map +7 -0
- package/dist/cjs/package.json +1 -0
- package/dist/esm/Action/Action.d.ts +250 -0
- package/dist/esm/Action/Action.d.ts.map +1 -0
- package/dist/esm/Action/Action.js +30 -0
- package/dist/esm/Action/Action.js.map +1 -0
- package/dist/esm/Action/AttemptTimedOut.d.ts +33 -0
- package/dist/esm/Action/AttemptTimedOut.d.ts.map +1 -0
- package/dist/esm/Action/AttemptTimedOut.js +32 -0
- package/dist/esm/Action/AttemptTimedOut.js.map +1 -0
- package/dist/esm/Action/BoundaryMode.d.ts +29 -0
- package/dist/esm/Action/BoundaryMode.d.ts.map +1 -0
- package/dist/esm/Action/BoundaryMode.js +23 -0
- package/dist/esm/Action/BoundaryMode.js.map +1 -0
- package/dist/esm/Action/CacheEnvironment.d.ts +158 -0
- package/dist/esm/Action/CacheEnvironment.d.ts.map +1 -0
- package/dist/esm/Action/CacheEnvironment.js +130 -0
- package/dist/esm/Action/CacheEnvironment.js.map +1 -0
- package/dist/esm/Action/ConcurrentKeylessDispatch.d.ts +34 -0
- package/dist/esm/Action/ConcurrentKeylessDispatch.d.ts.map +1 -0
- package/dist/esm/Action/ConcurrentKeylessDispatch.js +33 -0
- package/dist/esm/Action/ConcurrentKeylessDispatch.js.map +1 -0
- package/dist/esm/Action/Context.d.ts +131 -0
- package/dist/esm/Action/Context.d.ts.map +1 -0
- package/dist/esm/Action/Context.js +99 -0
- package/dist/esm/Action/Context.js.map +1 -0
- package/dist/esm/Action/DuplicateImplementation.d.ts +20 -0
- package/dist/esm/Action/DuplicateImplementation.d.ts.map +1 -0
- package/dist/esm/Action/DuplicateImplementation.js +20 -0
- package/dist/esm/Action/DuplicateImplementation.js.map +1 -0
- package/dist/esm/Action/FileBoundary.d.ts +59 -0
- package/dist/esm/Action/FileBoundary.d.ts.map +1 -0
- package/dist/esm/Action/FileBoundary.js +60 -0
- package/dist/esm/Action/FileBoundary.js.map +1 -0
- package/dist/esm/Action/FileInput.d.ts +28 -0
- package/dist/esm/Action/FileInput.d.ts.map +1 -0
- package/dist/esm/Action/FileInput.js +32 -0
- package/dist/esm/Action/FileInput.js.map +1 -0
- package/dist/esm/Action/Filegroup.d.ts +16 -0
- package/dist/esm/Action/Filegroup.d.ts.map +1 -0
- package/dist/esm/Action/Filegroup.js +15 -0
- package/dist/esm/Action/Filegroup.js.map +1 -0
- package/dist/esm/Action/Glob.d.ts +8 -0
- package/dist/esm/Action/Glob.d.ts.map +1 -0
- package/dist/esm/Action/Glob.js +7 -0
- package/dist/esm/Action/Glob.js.map +1 -0
- package/dist/esm/Action/ImplementationVersionMismatch.d.ts +26 -0
- package/dist/esm/Action/ImplementationVersionMismatch.d.ts.map +1 -0
- package/dist/esm/Action/ImplementationVersionMismatch.js +24 -0
- package/dist/esm/Action/ImplementationVersionMismatch.js.map +1 -0
- package/dist/esm/Action/Implementations.d.ts +114 -0
- package/dist/esm/Action/Implementations.d.ts.map +1 -0
- package/dist/esm/Action/Implementations.js +94 -0
- package/dist/esm/Action/Implementations.js.map +1 -0
- package/dist/esm/Action/InfraInterrupt.d.ts +26 -0
- package/dist/esm/Action/InfraInterrupt.d.ts.map +1 -0
- package/dist/esm/Action/InfraInterrupt.js +25 -0
- package/dist/esm/Action/InfraInterrupt.js.map +1 -0
- package/dist/esm/Action/InfraInterruptRetriesExhausted.d.ts +33 -0
- package/dist/esm/Action/InfraInterruptRetriesExhausted.d.ts.map +1 -0
- package/dist/esm/Action/InfraInterruptRetriesExhausted.js +32 -0
- package/dist/esm/Action/InfraInterruptRetriesExhausted.js.map +1 -0
- package/dist/esm/Action/IrreversibleRetryRequiresIdempotencyKey.d.ts +26 -0
- package/dist/esm/Action/IrreversibleRetryRequiresIdempotencyKey.d.ts.map +1 -0
- package/dist/esm/Action/IrreversibleRetryRequiresIdempotencyKey.js +25 -0
- package/dist/esm/Action/IrreversibleRetryRequiresIdempotencyKey.js.map +1 -0
- package/dist/esm/Action/StepIdentity.d.ts +153 -0
- package/dist/esm/Action/StepIdentity.d.ts.map +1 -0
- package/dist/esm/Action/StepIdentity.js +139 -0
- package/dist/esm/Action/StepIdentity.js.map +1 -0
- package/dist/esm/Action/TreeArtifact.d.ts +8 -0
- package/dist/esm/Action/TreeArtifact.d.ts.map +1 -0
- package/dist/esm/Action/TreeArtifact.js +7 -0
- package/dist/esm/Action/TreeArtifact.js.map +1 -0
- package/dist/esm/Action/TypeId.d.ts +8 -0
- package/dist/esm/Action/TypeId.d.ts.map +1 -0
- package/dist/esm/Action/TypeId.js +9 -0
- package/dist/esm/Action/TypeId.js.map +1 -0
- package/dist/esm/Action/UncanonicalIdempotencyKey.d.ts +32 -0
- package/dist/esm/Action/UncanonicalIdempotencyKey.d.ts.map +1 -0
- package/dist/esm/Action/UncanonicalIdempotencyKey.js +31 -0
- package/dist/esm/Action/UncanonicalIdempotencyKey.js.map +1 -0
- package/dist/esm/Action/idempotencyKey.d.ts +21 -0
- package/dist/esm/Action/idempotencyKey.d.ts.map +1 -0
- package/dist/esm/Action/idempotencyKey.js +50 -0
- package/dist/esm/Action/idempotencyKey.js.map +1 -0
- package/dist/esm/Action/index.d.ts +29 -0
- package/dist/esm/Action/index.d.ts.map +1 -0
- package/dist/esm/Action/index.js +30 -0
- package/dist/esm/Action/index.js.map +1 -0
- package/dist/esm/Action/make.d.ts +128 -0
- package/dist/esm/Action/make.d.ts.map +1 -0
- package/dist/esm/Action/make.js +405 -0
- package/dist/esm/Action/make.js.map +1 -0
- package/dist/esm/Action/raceAll.d.ts +21 -0
- package/dist/esm/Action/raceAll.d.ts.map +1 -0
- package/dist/esm/Action/raceAll.js +20 -0
- package/dist/esm/Action/raceAll.js.map +1 -0
- package/dist/esm/Action/retry.d.ts +19 -0
- package/dist/esm/Action/retry.d.ts.map +1 -0
- package/dist/esm/Action/retry.js +72 -0
- package/dist/esm/Action/retry.js.map +1 -0
- package/dist/esm/Deadline.d.ts +105 -0
- package/dist/esm/Deadline.d.ts.map +1 -0
- package/dist/esm/Deadline.js +152 -0
- package/dist/esm/Deadline.js.map +1 -0
- package/dist/esm/DurableClock.d.ts +61 -0
- package/dist/esm/DurableClock.d.ts.map +1 -0
- package/dist/esm/DurableClock.js +75 -0
- package/dist/esm/DurableClock.js.map +1 -0
- package/dist/esm/DurableDeferred.d.ts +311 -0
- package/dist/esm/DurableDeferred.d.ts.map +1 -0
- package/dist/esm/DurableDeferred.js +357 -0
- package/dist/esm/DurableDeferred.js.map +1 -0
- package/dist/esm/DurableQueue.d.ts +160 -0
- package/dist/esm/DurableQueue.d.ts.map +1 -0
- package/dist/esm/DurableQueue.js +303 -0
- package/dist/esm/DurableQueue.js.map +1 -0
- package/dist/esm/ExternalJob.d.ts +179 -0
- package/dist/esm/ExternalJob.d.ts.map +1 -0
- package/dist/esm/ExternalJob.js +296 -0
- package/dist/esm/ExternalJob.js.map +1 -0
- package/dist/esm/Fault.d.ts +131 -0
- package/dist/esm/Fault.d.ts.map +1 -0
- package/dist/esm/Fault.js +198 -0
- package/dist/esm/Fault.js.map +1 -0
- package/dist/esm/Flow/Annotations.d.ts +245 -0
- package/dist/esm/Flow/Annotations.d.ts.map +1 -0
- package/dist/esm/Flow/Annotations.js +110 -0
- package/dist/esm/Flow/Annotations.js.map +1 -0
- package/dist/esm/Flow/CapabilityCeiling.d.ts +21 -0
- package/dist/esm/Flow/CapabilityCeiling.d.ts.map +1 -0
- package/dist/esm/Flow/CapabilityCeiling.js +27 -0
- package/dist/esm/Flow/CapabilityCeiling.js.map +1 -0
- package/dist/esm/Flow/DeadlineExceeded.d.ts +33 -0
- package/dist/esm/Flow/DeadlineExceeded.d.ts.map +1 -0
- package/dist/esm/Flow/DeadlineExceeded.js +34 -0
- package/dist/esm/Flow/DeadlineExceeded.js.map +1 -0
- package/dist/esm/Flow/ExecutionIdRequired.d.ts +25 -0
- package/dist/esm/Flow/ExecutionIdRequired.d.ts.map +1 -0
- package/dist/esm/Flow/ExecutionIdRequired.js +30 -0
- package/dist/esm/Flow/ExecutionIdRequired.js.map +1 -0
- package/dist/esm/Flow/ExecutionIds.d.ts +80 -0
- package/dist/esm/Flow/ExecutionIds.d.ts.map +1 -0
- package/dist/esm/Flow/ExecutionIds.js +91 -0
- package/dist/esm/Flow/ExecutionIds.js.map +1 -0
- package/dist/esm/Flow/Flow.d.ts +422 -0
- package/dist/esm/Flow/Flow.d.ts.map +1 -0
- package/dist/esm/Flow/Flow.js +3 -0
- package/dist/esm/Flow/Flow.js.map +1 -0
- package/dist/esm/Flow/MaxRoundsExceeded.d.ts +35 -0
- package/dist/esm/Flow/MaxRoundsExceeded.d.ts.map +1 -0
- package/dist/esm/Flow/MaxRoundsExceeded.js +34 -0
- package/dist/esm/Flow/MaxRoundsExceeded.js.map +1 -0
- package/dist/esm/Flow/Outcome.d.ts +162 -0
- package/dist/esm/Flow/Outcome.d.ts.map +1 -0
- package/dist/esm/Flow/Outcome.js +115 -0
- package/dist/esm/Flow/Outcome.js.map +1 -0
- package/dist/esm/Flow/Result.d.ts +186 -0
- package/dist/esm/Flow/Result.d.ts.map +1 -0
- package/dist/esm/Flow/Result.js +171 -0
- package/dist/esm/Flow/Result.js.map +1 -0
- package/dist/esm/Flow/Runtime.d.ts +98 -0
- package/dist/esm/Flow/Runtime.d.ts.map +1 -0
- package/dist/esm/Flow/Runtime.js +231 -0
- package/dist/esm/Flow/Runtime.js.map +1 -0
- package/dist/esm/Flow/TypeId.d.ts +8 -0
- package/dist/esm/Flow/TypeId.d.ts.map +1 -0
- package/dist/esm/Flow/TypeId.js +9 -0
- package/dist/esm/Flow/TypeId.js.map +1 -0
- package/dist/esm/Flow/index.d.ts +17 -0
- package/dist/esm/Flow/index.d.ts.map +1 -0
- package/dist/esm/Flow/index.js +18 -0
- package/dist/esm/Flow/index.js.map +1 -0
- package/dist/esm/Flow/internal.d.ts +34 -0
- package/dist/esm/Flow/internal.d.ts.map +1 -0
- package/dist/esm/Flow/internal.js +149 -0
- package/dist/esm/Flow/internal.js.map +1 -0
- package/dist/esm/Flow/make.d.ts +134 -0
- package/dist/esm/Flow/make.d.ts.map +1 -0
- package/dist/esm/Flow/make.js +106 -0
- package/dist/esm/Flow/make.js.map +1 -0
- package/dist/esm/FlowRuntime/CancelRequestFailed.d.ts +55 -0
- package/dist/esm/FlowRuntime/CancelRequestFailed.d.ts.map +1 -0
- package/dist/esm/FlowRuntime/CancelRequestFailed.js +53 -0
- package/dist/esm/FlowRuntime/CancelRequestFailed.js.map +1 -0
- package/dist/esm/FlowRuntime/ExecutionIdentityConflict.d.ts +23 -0
- package/dist/esm/FlowRuntime/ExecutionIdentityConflict.d.ts.map +1 -0
- package/dist/esm/FlowRuntime/ExecutionIdentityConflict.js +24 -0
- package/dist/esm/FlowRuntime/ExecutionIdentityConflict.js.map +1 -0
- package/dist/esm/FlowRuntime/FlowCycleDetected.d.ts +28 -0
- package/dist/esm/FlowRuntime/FlowCycleDetected.d.ts.map +1 -0
- package/dist/esm/FlowRuntime/FlowCycleDetected.js +35 -0
- package/dist/esm/FlowRuntime/FlowCycleDetected.js.map +1 -0
- package/dist/esm/FlowRuntime/FlowExecutionNotFound.d.ts +38 -0
- package/dist/esm/FlowRuntime/FlowExecutionNotFound.d.ts.map +1 -0
- package/dist/esm/FlowRuntime/FlowExecutionNotFound.js +40 -0
- package/dist/esm/FlowRuntime/FlowExecutionNotFound.js.map +1 -0
- package/dist/esm/FlowRuntime/FlowInstance.d.ts +115 -0
- package/dist/esm/FlowRuntime/FlowInstance.d.ts.map +1 -0
- package/dist/esm/FlowRuntime/FlowInstance.js +24 -0
- package/dist/esm/FlowRuntime/FlowInstance.js.map +1 -0
- package/dist/esm/FlowRuntime/FlowRuntime.d.ts +198 -0
- package/dist/esm/FlowRuntime/FlowRuntime.d.ts.map +1 -0
- package/dist/esm/FlowRuntime/FlowRuntime.js +34 -0
- package/dist/esm/FlowRuntime/FlowRuntime.js.map +1 -0
- package/dist/esm/FlowRuntime/NodeRecord.d.ts +175 -0
- package/dist/esm/FlowRuntime/NodeRecord.d.ts.map +1 -0
- package/dist/esm/FlowRuntime/NodeRecord.js +21 -0
- package/dist/esm/FlowRuntime/NodeRecord.js.map +1 -0
- package/dist/esm/FlowRuntime/WaitingAnnotation.d.ts +69 -0
- package/dist/esm/FlowRuntime/WaitingAnnotation.d.ts.map +1 -0
- package/dist/esm/FlowRuntime/WaitingAnnotation.js +53 -0
- package/dist/esm/FlowRuntime/WaitingAnnotation.js.map +1 -0
- package/dist/esm/FlowRuntime/index.d.ts +14 -0
- package/dist/esm/FlowRuntime/index.d.ts.map +1 -0
- package/dist/esm/FlowRuntime/index.js +15 -0
- package/dist/esm/FlowRuntime/index.js.map +1 -0
- package/dist/esm/Graph.d.ts +325 -0
- package/dist/esm/Graph.d.ts.map +1 -0
- package/dist/esm/Graph.js +1482 -0
- package/dist/esm/Graph.js.map +1 -0
- package/dist/esm/HumanTask.d.ts +440 -0
- package/dist/esm/HumanTask.d.ts.map +1 -0
- package/dist/esm/HumanTask.js +794 -0
- package/dist/esm/HumanTask.js.map +1 -0
- package/dist/esm/Interpreter.d.ts +222 -0
- package/dist/esm/Interpreter.d.ts.map +1 -0
- package/dist/esm/Interpreter.js +1269 -0
- package/dist/esm/Interpreter.js.map +1 -0
- package/dist/esm/Poll.d.ts +238 -0
- package/dist/esm/Poll.d.ts.map +1 -0
- package/dist/esm/Poll.js +282 -0
- package/dist/esm/Poll.js.map +1 -0
- package/dist/esm/RetryPolicy.d.ts +273 -0
- package/dist/esm/RetryPolicy.d.ts.map +1 -0
- package/dist/esm/RetryPolicy.js +429 -0
- package/dist/esm/RetryPolicy.js.map +1 -0
- package/dist/esm/Sleep.d.ts +98 -0
- package/dist/esm/Sleep.d.ts.map +1 -0
- package/dist/esm/Sleep.js +230 -0
- package/dist/esm/Sleep.js.map +1 -0
- package/dist/esm/Stall.d.ts +173 -0
- package/dist/esm/Stall.d.ts.map +1 -0
- package/dist/esm/Stall.js +138 -0
- package/dist/esm/Stall.js.map +1 -0
- package/dist/esm/WaitFor.d.ts +109 -0
- package/dist/esm/WaitFor.d.ts.map +1 -0
- package/dist/esm/WaitFor.js +184 -0
- package/dist/esm/WaitFor.js.map +1 -0
- package/dist/esm/index.d.ts +107 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +108 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/internal/BoundedJson.d.ts +48 -0
- package/dist/esm/internal/BoundedJson.d.ts.map +1 -0
- package/dist/esm/internal/BoundedJson.js +107 -0
- package/dist/esm/internal/BoundedJson.js.map +1 -0
- package/dist/esm/internal/DeclarationSite.d.ts +135 -0
- package/dist/esm/internal/DeclarationSite.d.ts.map +1 -0
- package/dist/esm/internal/DeclarationSite.js +196 -0
- package/dist/esm/internal/DeclarationSite.js.map +1 -0
- package/dist/esm/internal/Declarations.d.ts +35 -0
- package/dist/esm/internal/Declarations.d.ts.map +1 -0
- package/dist/esm/internal/Declarations.js +43 -0
- package/dist/esm/internal/Declarations.js.map +1 -0
- package/dist/esm/internal/ExecutionMiddleware.d.ts +21 -0
- package/dist/esm/internal/ExecutionMiddleware.d.ts.map +1 -0
- package/dist/esm/internal/ExecutionMiddleware.js +13 -0
- package/dist/esm/internal/ExecutionMiddleware.js.map +1 -0
- package/dist/esm/internal/JsonSchemaSubset.d.ts +133 -0
- package/dist/esm/internal/JsonSchemaSubset.d.ts.map +1 -0
- package/dist/esm/internal/JsonSchemaSubset.js +363 -0
- package/dist/esm/internal/JsonSchemaSubset.js.map +1 -0
- package/dist/esm/internal/OutcomeMarker.d.ts +18 -0
- package/dist/esm/internal/OutcomeMarker.d.ts.map +1 -0
- package/dist/esm/internal/OutcomeMarker.js +18 -0
- package/dist/esm/internal/OutcomeMarker.js.map +1 -0
- package/docs/README.md +150 -0
- package/docs/api.md +436 -0
- package/docs/concepts/bodies-and-plans.md +157 -0
- package/docs/concepts/execution-identity.md +142 -0
- package/docs/concepts/flows-and-actions.md +129 -0
- package/docs/concepts/suspension-and-replay.md +130 -0
- package/docs/concepts/the-runtime-port.md +110 -0
- package/docs/concepts/trampoline-rounds.md +151 -0
- package/docs/guides/ask-a-person.md +184 -0
- package/docs/guides/build-a-body.md +161 -0
- package/docs/guides/cancel-and-roll-back.md +112 -0
- package/docs/guides/implement-an-action.md +147 -0
- package/docs/guides/inspect-the-plan.md +154 -0
- package/docs/guides/poll-until-ready.md +167 -0
- package/docs/guides/queue-work-to-a-worker.md +122 -0
- package/docs/guides/retry-a-failing-action.md +243 -0
- package/docs/guides/reuse-a-recorded-result.md +122 -0
- package/docs/guides/run-a-child-flow.md +108 -0
- package/docs/guides/run-an-external-job.md +86 -0
- package/docs/guides/use-a-prompt.md +38 -0
- package/docs/guides/wait-for-a-deadline.md +141 -0
- package/docs/guides/wait-for-an-external-signal.md +151 -0
- package/docs/installation.md +82 -0
- package/docs/quickstart.md +155 -0
- package/docs/reference/flow.md +1831 -0
- package/docs/testing.md +157 -0
- package/docs/troubleshooting.md +286 -0
- package/package.json +327 -3
- package/src/Action/Action.ts +333 -0
- package/src/Action/AttemptTimedOut.ts +37 -0
- package/src/Action/BoundaryMode.ts +33 -0
- package/src/Action/CacheEnvironment.ts +170 -0
- package/src/Action/ConcurrentKeylessDispatch.ts +38 -0
- package/src/Action/Context.ts +156 -0
- package/src/Action/DuplicateImplementation.ts +24 -0
- package/src/Action/FileBoundary.ts +77 -0
- package/src/Action/FileInput.ts +42 -0
- package/src/Action/Filegroup.ts +16 -0
- package/src/Action/Glob.ts +8 -0
- package/src/Action/ImplementationVersionMismatch.ts +27 -0
- package/src/Action/Implementations.ts +149 -0
- package/src/Action/InfraInterrupt.ts +30 -0
- package/src/Action/InfraInterruptRetriesExhausted.ts +37 -0
- package/src/Action/IrreversibleRetryRequiresIdempotencyKey.ts +32 -0
- package/src/Action/StepIdentity.ts +219 -0
- package/src/Action/TreeArtifact.ts +8 -0
- package/src/Action/TypeId.ts +9 -0
- package/src/Action/UncanonicalIdempotencyKey.ts +36 -0
- package/src/Action/idempotencyKey.ts +67 -0
- package/src/Action/index.ts +31 -0
- package/src/Action/make.ts +657 -0
- package/src/Action/raceAll.ts +48 -0
- package/src/Action/retry.ts +92 -0
- package/src/Deadline.ts +185 -0
- package/src/DurableClock.ts +133 -0
- package/src/DurableDeferred.ts +753 -0
- package/src/DurableQueue.ts +519 -0
- package/src/ExternalJob.ts +432 -0
- package/src/Fault.ts +279 -0
- package/src/Flow/Annotations.ts +151 -0
- package/src/Flow/CapabilityCeiling.ts +37 -0
- package/src/Flow/DeadlineExceeded.ts +40 -0
- package/src/Flow/ExecutionIdRequired.ts +36 -0
- package/src/Flow/ExecutionIds.ts +133 -0
- package/src/Flow/Flow.ts +576 -0
- package/src/Flow/MaxRoundsExceeded.ts +39 -0
- package/src/Flow/Outcome.ts +179 -0
- package/src/Flow/Result.ts +284 -0
- package/src/Flow/Runtime.ts +309 -0
- package/src/Flow/TypeId.ts +9 -0
- package/src/Flow/index.ts +19 -0
- package/src/Flow/internal.ts +237 -0
- package/src/Flow/make.ts +279 -0
- package/src/FlowRuntime/CancelRequestFailed.ts +56 -0
- package/src/FlowRuntime/ExecutionIdentityConflict.ts +32 -0
- package/src/FlowRuntime/FlowCycleDetected.ts +41 -0
- package/src/FlowRuntime/FlowExecutionNotFound.ts +46 -0
- package/src/FlowRuntime/FlowInstance.ts +128 -0
- package/src/FlowRuntime/FlowRuntime.ts +333 -0
- package/src/FlowRuntime/NodeRecord.ts +183 -0
- package/src/FlowRuntime/WaitingAnnotation.ts +85 -0
- package/src/FlowRuntime/index.ts +17 -0
- package/src/Graph.ts +1860 -0
- package/src/HumanTask.ts +1003 -0
- package/src/Interpreter.ts +1593 -0
- package/src/Poll.ts +414 -0
- package/src/RetryPolicy.ts +550 -0
- package/src/Sleep.ts +267 -0
- package/src/Stall.ts +217 -0
- package/src/WaitFor.ts +228 -0
- package/src/index.ts +125 -0
- package/src/internal/BoundedJson.ts +109 -0
- package/src/internal/DeclarationSite.ts +214 -0
- package/src/internal/Declarations.ts +49 -0
- package/src/internal/ExecutionMiddleware.ts +29 -0
- package/src/internal/JsonSchemaSubset.ts +392 -0
- package/src/internal/OutcomeMarker.ts +19 -0
package/docs/README.md
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "@smthrs/flow"
|
|
3
|
+
description: "Declare durable workflows in TypeScript: an action is a named step with schemas, a flow is a pure plan over those steps, and a re-run replays what already finished instead of doing it again."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
`@smthrs/flow` is the authoring model for durable workflows in TypeScript. You
|
|
7
|
+
declare each step as an **action**: a stable name and the schemas on either side
|
|
8
|
+
of it, with no code. You compose those declarations into a **flow** whose body is
|
|
9
|
+
a pure function that builds a plan. The code that does the work attaches
|
|
10
|
+
separately, as an Effect layer.
|
|
11
|
+
|
|
12
|
+
The package carries no engine. It declares the `FlowRuntime` port that an engine
|
|
13
|
+
implements, so the whole authoring surface bundles for a browser and a test can
|
|
14
|
+
swap the runtime for a fixture without touching a declaration.
|
|
15
|
+
|
|
16
|
+
## What it solves
|
|
17
|
+
|
|
18
|
+
A job that calls a model, spawns a build, uploads an artifact, or waits on a
|
|
19
|
+
person cannot afford to start over when the process dies. Recovering by hand
|
|
20
|
+
means writing your own checkpoint table, your own idempotency keys, and your own
|
|
21
|
+
"did this already run" branch around every call.
|
|
22
|
+
|
|
23
|
+
A pure flow body builds the plan before anything runs. With complete callback
|
|
24
|
+
captures and stable admission, unchanged source, captures, declarations, and
|
|
25
|
+
payload reproduce the same plan keys across processes. An engine records each
|
|
26
|
+
step as it settles, so a re-run under the same execution id reads the recorded
|
|
27
|
+
result rather than
|
|
28
|
+
repeating the work, on this process and on the next one. The same property is
|
|
29
|
+
what lets the engine retry a step, cache it, park a run on a timer or a human
|
|
30
|
+
answer for a week, and put one step on another machine, none of which the flow's
|
|
31
|
+
author arranges.
|
|
32
|
+
|
|
33
|
+
Reach for it when a program has steps you cannot afford to run twice, waits
|
|
34
|
+
longer than a process lifetime, or a failure you want resumed rather than
|
|
35
|
+
restarted. Skip it when a plain `Effect` retry loop covers the whole problem.
|
|
36
|
+
|
|
37
|
+
## Install
|
|
38
|
+
|
|
39
|
+
Not on npm yet; see [Installation](./installation.md#use-the-libraries).
|
|
40
|
+
|
|
41
|
+
Node.js 26.4.0 or later. [Installation](./installation.md) covers the import
|
|
42
|
+
forms, and what each companion package supplies.
|
|
43
|
+
|
|
44
|
+
## Declare a flow and run it
|
|
45
|
+
|
|
46
|
+
This program declares one recorded step, attaches its implementation, and runs
|
|
47
|
+
the flow on the in-memory engine:
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
import * as NodeCrypto from "@effect/platform-node/NodeCrypto"
|
|
51
|
+
import { FlowEngine } from "@smthrs/engine"
|
|
52
|
+
import { Action, Flow, Interpreter } from "@smthrs/flow"
|
|
53
|
+
import { Node } from "@smthrs/plan"
|
|
54
|
+
import * as Effect from "effect/Effect"
|
|
55
|
+
import * as Layer from "effect/Layer"
|
|
56
|
+
import * as Schema from "effect/Schema"
|
|
57
|
+
|
|
58
|
+
/** A step declaration is data: a stable tag and the schemas either side of it. */
|
|
59
|
+
const Summarize = Action.make("digest/Summarize", {
|
|
60
|
+
payload: { url: Schema.String },
|
|
61
|
+
success: Schema.String
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
/** A flow body records nodes. `Summarize.call` plans a step and runs nothing. */
|
|
65
|
+
const Digest = Flow.make("digest/Digest", {
|
|
66
|
+
payload: { url: Schema.String },
|
|
67
|
+
success: Schema.String,
|
|
68
|
+
body: Node.capture(
|
|
69
|
+
{ action: Summarize.name, implementationVersion: "digest/v1" },
|
|
70
|
+
(payload) => Summarize.call(payload)
|
|
71
|
+
)
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
/** The code arrives separately, filed against the tag by `toLayer`. */
|
|
75
|
+
const layer = Interpreter.layerWithImplementations(
|
|
76
|
+
Digest,
|
|
77
|
+
Summarize.toLayer(({ url }) => Effect.succeed(`A summary of ${url}.`))
|
|
78
|
+
).pipe(
|
|
79
|
+
Layer.provideMerge(FlowEngine.layerMemory),
|
|
80
|
+
Layer.provideMerge(NodeCrypto.layer)
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
const main = Digest.execute(
|
|
84
|
+
{ url: "https://example.com/post" },
|
|
85
|
+
{ executionId: "digest-example-post" }
|
|
86
|
+
).pipe(Effect.orDie, Effect.provide(layer))
|
|
87
|
+
|
|
88
|
+
console.log(await Effect.runPromise(main))
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
`Node.capture` declares every semantic value outside the callback source,
|
|
92
|
+
including a version for imported behavior. JavaScript cannot verify that the
|
|
93
|
+
record is complete. `Interpreter.layerWithImplementations` defaults to stable
|
|
94
|
+
callback admission and refuses uncaptured callbacks before dispatch. The
|
|
95
|
+
lower-level `Graph.build` and `Interpreter.layer` default to `process-local`,
|
|
96
|
+
which makes no cross-process callback identity guarantee. Changed source,
|
|
97
|
+
captures, or implementation versions require a newly planned run.
|
|
98
|
+
|
|
99
|
+
Run it and the implementation runs once. Run the same execution id again and it
|
|
100
|
+
does not: the engine finds the execution that already settled and answers with
|
|
101
|
+
its recorded result. Swap `FlowEngine.layerMemory` for the SQLite-backed engine
|
|
102
|
+
in [`@smthrs/engine-store`](/api/engine-store) and the same behavior survives a
|
|
103
|
+
restart, with nothing above the swap changing.
|
|
104
|
+
|
|
105
|
+
## How this relates to @smthrs/flows
|
|
106
|
+
|
|
107
|
+
[`@smthrs/flows`](/api/flows) is the whole Smithers durable flow engine in one
|
|
108
|
+
dependency. It re-exports this package alongside the engine, the journal, the
|
|
109
|
+
store, and the rest, and it adds the modules a Node program needs to run flows
|
|
110
|
+
for real: `NodeRuntime`, which stands a durable engine up over local SQLite, and
|
|
111
|
+
`SandboxedFlow`, which runs a child flow on a machine you provision. Install
|
|
112
|
+
`@smthrs/flows` when you want a host that runs flows. Install `@smthrs/flow`
|
|
113
|
+
alone when you only want to declare them, which is the case for a library that
|
|
114
|
+
publishes flows for someone else to run, and for anything that has to bundle for
|
|
115
|
+
a browser.
|
|
116
|
+
|
|
117
|
+
Above both sits [`@smthrs/cli`](/api/cli), the `smthrs` command. It is this
|
|
118
|
+
engine as a program rather than a library: it finds the flows in a project, plans
|
|
119
|
+
them, takes an approval, runs them, and reads their events back. Reach for it
|
|
120
|
+
when the thing running your flows is a shell or a CI job rather than your own
|
|
121
|
+
program.
|
|
122
|
+
|
|
123
|
+
## Where to go next
|
|
124
|
+
|
|
125
|
+
- [Installation](./installation.md): the pinned `effect` version, the subpath
|
|
126
|
+
exports, and the packages a runnable composition adds.
|
|
127
|
+
- [Quickstart](./quickstart.md): the same program end to end, including what
|
|
128
|
+
happens on the second run.
|
|
129
|
+
- [Flows and actions](./concepts/flows-and-actions.md): the two nouns, the two
|
|
130
|
+
forms of action, and why an implementation attaches as a layer.
|
|
131
|
+
- [Bodies are plans](./concepts/bodies-and-plans.md): what a body may not do,
|
|
132
|
+
and why that restriction is what makes replay work.
|
|
133
|
+
- [Execution identity](./concepts/execution-identity.md): how a run gets its id
|
|
134
|
+
and how one dispatch gets its step key.
|
|
135
|
+
- [Suspension and replay](./concepts/suspension-and-replay.md): the three
|
|
136
|
+
results a round settles with, and what parking on a durable wait costs.
|
|
137
|
+
- [Compose a body from branches and fan-out](./guides/build-a-body.md):
|
|
138
|
+
sequencing, parallelism, branches, and recovering from a typed failure.
|
|
139
|
+
- [Retry a failing action](./guides/retry-a-failing-action.md): policy values,
|
|
140
|
+
non-retryable tags, and where the decision is made.
|
|
141
|
+
- [Ask a person for a decision](./guides/ask-a-person.md): a human answer as a
|
|
142
|
+
typed, durable step with a deadline.
|
|
143
|
+
- [Run an external job](./guides/run-an-external-job.md): retained workers, durable probes,
|
|
144
|
+
replacement generations and cancellation.
|
|
145
|
+
- [Testing](./testing.md): topology, interpretation, and execution, and which
|
|
146
|
+
level a given assertion belongs at.
|
|
147
|
+
- [API reference](./api.md): every public export, with the export tables in the
|
|
148
|
+
[export reference](./reference/flow.md).
|
|
149
|
+
- [Troubleshooting](./troubleshooting.md): every refusal this package raises,
|
|
150
|
+
sorted by the symptom you see.
|
package/docs/api.md
ADDED
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "API reference"
|
|
3
|
+
description: "The complete public surface of @smthrs/flow: flows, actions, durable primitives, step identity, retry policy, and the runtime port, and how the pieces fit together."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
The flow authoring model: typed flow and action definitions, durable primitives, step identity, retry policy, and the runtime port they execute against. The whole package bundles for the browser; durability comes from whichever runtime you provide.
|
|
7
|
+
|
|
8
|
+
An `Action` carries an implementation, attached separately as a layer. A `Flow` carries a pure `body`, authored directly or lowered from a typed `prompt`, and `Interpreter.layer` drives it.
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { FlowEngine } from "@smthrs/engine"
|
|
12
|
+
import { Action, Flow, Interpreter } from "@smthrs/flow"
|
|
13
|
+
import * as Effect from "effect/Effect"
|
|
14
|
+
import * as Layer from "effect/Layer"
|
|
15
|
+
import * as Schema from "effect/Schema"
|
|
16
|
+
|
|
17
|
+
const Compile = Action.make("example/Compile", {
|
|
18
|
+
payload: { target: Schema.String },
|
|
19
|
+
success: Schema.String,
|
|
20
|
+
tier: "sealed"
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
const Build = Flow.make("example/Build", {
|
|
24
|
+
payload: { target: Schema.String },
|
|
25
|
+
success: Schema.String,
|
|
26
|
+
body: (payload) => Compile.call(payload)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
const layer = Layer.mergeAll(
|
|
30
|
+
Compile.toLayer(({ target }) => Effect.succeed(`${target}.js`)),
|
|
31
|
+
Interpreter.layer(Build)
|
|
32
|
+
).pipe(Layer.provideMerge(Action.layerImplementations), Layer.provideMerge(FlowEngine.layerMemory))
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Entry point
|
|
36
|
+
|
|
37
|
+
| Import | Source | Platform |
|
|
38
|
+
| -------------- | ---------------------------------------------------------------------------------------------------------- | -------- |
|
|
39
|
+
| `@smthrs/flow` | [src/index.ts](https://github.com/smithersai/smithers/blob/main/packages/smithers/flows/flow/src/index.ts) | any |
|
|
40
|
+
|
|
41
|
+
This page is the public API reference for the flow authoring model: typed flows, recorded actions, durable deferreds, clocks and queues, the system timer and wait point, polling, human tasks, plan-time graph building, the body interpreter, retry policy, step identity, and the runtime port those APIs execute against. It contains no engine implementation: that is [`@smthrs/engine`](/api/engine).
|
|
42
|
+
|
|
43
|
+
The [export reference](./reference/flow.md) lists every exported symbol with its signature, its defaults, and the errors it raises. The sections below say how the pieces fit together. For task-shaped instructions, start from the [guides](./README.md#where-to-go-next).
|
|
44
|
+
|
|
45
|
+
## `Flow`
|
|
46
|
+
|
|
47
|
+
`Flow.make(tag, options)` accepts struct payload fields, success and error schemas, an optional `idempotencyKey`, annotations, a `suspendedRetryPolicy`, a `maxRounds` bound for trampoline lineages, and a `deadline` for one execution. Four literals lower into the annotation bag rather than staying options: `description`, `capabilities`, `effects`, the effect envelope from [`@smthrs/plan`](/api/plan#effects), and `modelInvocable`, which says whether a catalog may offer this flow to a model and defaults to `true`. They are literals so a catalog can project a discovered flow's authority from source text without importing the module, and `Graph.build` refuses a composition beneath the flow that reads or writes outside that envelope, loosens its mode, or raises its tier. Declare exactly one of `body` or `prompt`. A prompt declaration lowers to one ordinary action, exposed as `flow.action`; its host supplies the implementation through `flow.action.toLayer`. The typed `flow.prompt` renderer runs inside that implementation, never during planning. Optional `model`, `effort`, `flows`, `system`, and `chat` fields retain host metadata. See [Prompt-backed flows](./guides/use-a-prompt.md). `maxRounds` must be a positive safe integer and `deadline` a positive finite duration; `Flow.make` throws a `RangeError` when either is not. The deadline counts from the execution's journaled first start, so a resume after a restart honors the original deadline, and expiry settles the execution with the `DeadlineExceeded` defect whether it was running or parked. A trampoline lineage is one run: every round after a handoff expires at the originator's start plus the originator's deadline, whatever the round itself declares.
|
|
48
|
+
|
|
49
|
+
The returned definition exposes:
|
|
50
|
+
|
|
51
|
+
- `execute(payload, { executionId?, discard? })`
|
|
52
|
+
- `poll(executionId)`
|
|
53
|
+
- `interrupt(executionId)` and `resume(executionId)`
|
|
54
|
+
- `executionId(payload)`
|
|
55
|
+
- `call(payload)`, `child(payload)`, and `to(payload)` for use inside a body
|
|
56
|
+
- `annotate` and `annotateMerge`
|
|
57
|
+
- `withRollback`
|
|
58
|
+
|
|
59
|
+
`Flow.make`, declared `Action.make`, and `Action.makeSystem` accept
|
|
60
|
+
`declaredFrom: original` when a wrapper reconstructs a native declaration.
|
|
61
|
+
The new declaration retains the original's diagnostic source location, including
|
|
62
|
+
an absent location. It still owns its new body, options, and call closures.
|
|
63
|
+
The source reference is not stored in key material and changes no digest.
|
|
64
|
+
|
|
65
|
+
There is no `toLayer` on a flow. A flow carries a body and never a handler, so the seam that registers one is internal and `Interpreter.layer(flow)` is the public way to make a flow executable.
|
|
66
|
+
|
|
67
|
+
### Execution identity
|
|
68
|
+
|
|
69
|
+
Identity has three sources, consulted in this order:
|
|
70
|
+
|
|
71
|
+
1. the `executionId` the caller named on `execute`;
|
|
72
|
+
2. the `idempotencyKey` the flow declared, hashed together with the flow tag;
|
|
73
|
+
3. the ambient `CurrentExecutionIds` source, whose default `fresh` mints a new cryptographic UUID.
|
|
74
|
+
|
|
75
|
+
`layerExecutionIds(source)` replaces the third. Install `derived` when equal payloads deliberately name one piece of work; callers that name an `executionId` and flows that declare an `idempotencyKey` are unaffected, because both are decided before the source is consulted.
|
|
76
|
+
|
|
77
|
+
`ExecutionIdRequired` is a defect, not a typed failure. The opt-in derived source raises it when the payload has no canonical form, for example a non-finite number, a lone surrogate, or a cycle. `Flow.executionId(payload)` likewise dies when the payload fails the flow's own payload schema, where `Flow.execute` fails with a typed `Schema.SchemaError` instead. Precompute an id with `executionId` only for a payload you have already validated.
|
|
78
|
+
|
|
79
|
+
### Results
|
|
80
|
+
|
|
81
|
+
A flow settles with one of three results:
|
|
82
|
+
|
|
83
|
+
| Result | Meaning |
|
|
84
|
+
| ----------- | ------------------------------------------------------------------------ |
|
|
85
|
+
| `Complete` | the flow finished, carrying an `Exit` |
|
|
86
|
+
| `Suspended` | the flow parked on a durable wait and will be re-driven |
|
|
87
|
+
| `Handoff` | the round ended by handing off to the next round of a trampoline lineage |
|
|
88
|
+
|
|
89
|
+
`Result` is that union, `ResultEncoded` is its codec, `isResult` is the guard, `intoResult` turns a suspension interrupt into `Suspended`, and `wrapActionResult` holds a flow suspension until the sibling actions already running settle or suspend. `MaxRoundsExceeded` is the defect a lineage dies with when it opens a round past its `maxRounds` budget; read it off the `Complete` result, never off `execute`'s error channel. `DeadlineExceeded` is the defect an execution dies with when its `deadline` elapses, read the same way.
|
|
90
|
+
|
|
91
|
+
`Outcome` is the vocabulary a trampoline body settles a round with: `Done(value)` ends the lineage, `To(payload)` opens the next round, and `Park` suspends it. `isOutcome` is its guard.
|
|
92
|
+
|
|
93
|
+
Scope helpers are `scope`, `provideScope`, `addFinalizer`, `withRollback`, and `suspend`. Policy references are `CaptureDefects` and `SuspendOnFailure`. `Execution` is a type-level marker that ties a service to a flow tag; it carries no runtime value and identifies nothing at run time.
|
|
94
|
+
|
|
95
|
+
## `Action`
|
|
96
|
+
|
|
97
|
+
`Action.make(options)` defines a named effect with success and error schemas, a `tier`, idempotency identity, metadata, annotations, an optional `retryPolicy`, and an optional `interruptRetryPolicy`. `Action.make(tag, options)` is the declared form: pure data whose implementation attaches later through `toLayer`. `Action.makeSystem` is the declared form that mints no requirement, which is how `Sleep`, `WaitFor`, `HumanTask`, and `Poll` ship implementations with the engine instead of pushing a layer obligation onto their callers.
|
|
98
|
+
|
|
99
|
+
The declared form takes the same two literals `Flow.make` does, lowered into the annotation bag by the same code: `capabilities`, the capability ceiling the dispatch runs under, and `effects`, the effect envelope from [`@smthrs/plan`](/api/plan#effects). They are literals so a catalog can project a declaration's authority from source text without importing the module. An action is a leaf, so its envelope encloses nothing: `Graph.build` checks it against the envelope the calling flow granted, and records `capability_outside_grant` for every capability the caller does not hold.
|
|
100
|
+
|
|
101
|
+
Omitting `capabilities` inherits the caller's authority. Declaring `capabilities: []`
|
|
102
|
+
denies every guarded host operation. Each declaration intersects with every
|
|
103
|
+
ancestor and the ambient host ceiling; `*` permits any capability within those
|
|
104
|
+
limits. Use full patterns such as `fs:write:**` or `net:get:https://example.com/**`;
|
|
105
|
+
unrecognized patterns grant nothing. Capability declarations constrain the
|
|
106
|
+
guarded host services an action resolves: `FileSystem`, `ChildProcessSpawner`,
|
|
107
|
+
`HttpClient`, and `Jj`. They do not constrain arbitrary JavaScript, such as a
|
|
108
|
+
direct `node:fs` import.
|
|
109
|
+
|
|
110
|
+
Actions, inline calls, child runs, and handoffs keep these ceilings. Admission
|
|
111
|
+
records authority for replay and recovery; an execution ID retains its first
|
|
112
|
+
admission ceiling, and resuming from a broader host cannot widen it. A caller
|
|
113
|
+
joins, polls, or resumes an existing execution ID only when its ceiling covers
|
|
114
|
+
the recorded one; otherwise `Flow.execute` fails with typed `ExecutionIdentityConflict` on field
|
|
115
|
+
`capabilities`. Existing
|
|
116
|
+
durable runs without recorded authority refuse further dispatch: re-keying an
|
|
117
|
+
old action could repeat a completed effect. Inspect existing effects before
|
|
118
|
+
starting replacement work with a new execution ID.
|
|
119
|
+
Graph diagnostics are advisory conservative checks of glob coverage; execution
|
|
120
|
+
checks the exact intersection with the kernel matcher. Cross-run cache keys include
|
|
121
|
+
this effective authority. Remote execution and resume carry the ceiling to the
|
|
122
|
+
serving engine, which intersects it with its own authority and never widens it.
|
|
123
|
+
|
|
124
|
+
`Flow.capabilityCeilings(annotations)` reads explicitly declared groups, preserving
|
|
125
|
+
omission. `Flow.parseCapabilityCeilings(groups)` parses them, dropping invalid
|
|
126
|
+
patterns. `Flow.attenuateCapabilities(groups)(effect)` applies the parsed patterns
|
|
127
|
+
to the shared kernel authority without widening it.
|
|
128
|
+
|
|
129
|
+
| Export | Purpose |
|
|
130
|
+
| -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
131
|
+
| `Tier` | `sealed`, `compensable`, or `irreversible` |
|
|
132
|
+
| `InfraInterrupt` | marker an action adapter explicitly fails with for an infrastructure event it wants `interruptRetryPolicy` to retry; shipped engines do not synthesize it from fiber interruption |
|
|
133
|
+
| `InfraInterruptRetriesExhausted` | the typed identity an exhausted `interruptRetryPolicy` dies with, carrying the action, the attempts, and the final interrupt |
|
|
134
|
+
| `IrreversibleRetryRequiresIdempotencyKey` | an irreversible action retried without a declared key |
|
|
135
|
+
| `ConcurrentKeylessDispatch` | two live dispatches of one keyless allocation scope |
|
|
136
|
+
| `UncanonicalIdempotencyKey` | a caller-declared object-form `idempotencyKey` carrying material canonical serialization rejects, such as a `Date`, an `undefined`, a class instance, or a `Redacted`. It surfaces as a typed, non-retryable recorded completion naming the offending path, never as an untyped fiber defect |
|
|
137
|
+
| `retry(effect, options)` | Effect retry with durable attempt context |
|
|
138
|
+
| `raceAll(name, actions)` | a durable race for the first success, persisting one winner; fails only when every action fails |
|
|
139
|
+
| `idempotencyKey(name, options?)` | the run-local invocation key |
|
|
140
|
+
| `DispatchSite` | the structural node address the interpreter scopes one dispatch to |
|
|
141
|
+
| `CurrentCacheEnvironment` | the complete `{ layers, capabilities }` a sealed cache key is computed under. It is hashed separately from caller-owned identity, and when it is absent the engine scopes the key to the current execution |
|
|
142
|
+
| `CachePolicy` and `withCache` | a declaration-level annotation bounding the age of a reusable sealed result |
|
|
143
|
+
| `FileInput`, `FileBoundary`, `BoundaryMode`, `Filegroup`, `Glob`, `TreeArtifact` | the file-boundary vocabulary an action declares its reads and writes with |
|
|
144
|
+
|
|
145
|
+
`CurrentAttempt` is the one-based durable attempt. `CurrentOrdinal` carries an `OrdinalSlot` (`{ values, cursors }`) rather than a number: the engine allocates each dispatch's ordinal under its declaration-identity scope and pins it per scope by dispatch position, so every attempt of one `Action.retry` sequence reuses its own action's ordinals even when the block dispatches several distinct actions or one declaration several times. Nested blocks share the pinned `values` with the enclosing block but own a private `cursors` view seeded at block entry and merged back on exit, so a concurrent sibling block's attempt boundary never rewinds another block's mid-flight cursor. Concurrent dispatch of one allocation scope is refused with `ConcurrentKeylessDispatch` for every ordinal-keyed action, keyless or keyed at a non-sealed tier, because arrival order would otherwise assign the ordinals; only a sealed action with an `idempotencyKey`, which is a pure cache key, may overlap on the same declared key, and distinct keys are distinct scopes that overlap freely.
|
|
146
|
+
|
|
147
|
+
An action is itself an `Effect`; `action.execute` bypasses engine recording and should normally be used only by engine implementations.
|
|
148
|
+
|
|
149
|
+
Sealed idempotency identity has two forms. A string is namespaced by the action name and the declared schemas. An object is caller-owned canonical JSON and stays stable across action renames. The engine separately adds the complete cache environment and any typed `fileBoundary` (or historical boundary `metadata`), so caller identity cannot override runtime facts.
|
|
150
|
+
|
|
151
|
+
## Durable primitives
|
|
152
|
+
|
|
153
|
+
| Namespace | Public surface |
|
|
154
|
+
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
155
|
+
| `DurableDeferred` | `make`, `await`, `into`, `raceAll`, branded token parsing and creation, and `done`, `succeed`, `fail`, `failCause` completion |
|
|
156
|
+
| `DurableClock` | `make({ name, duration })` and `sleep({ name, duration, inMemoryThreshold? })` |
|
|
157
|
+
| `DurableQueue` | `make`, `process`, `makeWorker`, and `worker` over Effect's `PersistedQueue` |
|
|
158
|
+
| `Deadline` | `start`, `within`, and `bound`: the run deadline `Flow.make` applies, for a host that bounds a run by an approved deadline |
|
|
159
|
+
|
|
160
|
+
A deferred token encodes the flow name, the execution id, and the deferred name, so another process can complete the correct durable address. `TokenInvalid` is the typed failure every completion surface returns for a token that does not parse or that names a different deferred than the one it was submitted through. Completing a deferred is first-writer-wins: the first recorded exit is the one every later read replays.
|
|
161
|
+
|
|
162
|
+
`DurableQueue.process` offers a payload, attaches a token, and suspends until a worker records the handler's exit against it. Its `retrySchedule` option bounds how a failing offer is retried; the default retries with exponential backoff, capped at one minute, and never gives up before the call dies. `DurableQueue.worker` and `makeWorker` take a `concurrency` that must be a positive safe integer.
|
|
163
|
+
|
|
164
|
+
## `Graph`
|
|
165
|
+
|
|
166
|
+
`Graph.build(flowOrNode, payload, options)` turns a body, or a bare node, into the plan-time graph the interpreter drives and the planner compiles. Building is a pure function of the declarations and the payload, so the whole shape of a round is known before its first action runs.
|
|
167
|
+
|
|
168
|
+
| Export | Purpose |
|
|
169
|
+
| -------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
|
170
|
+
| `build` | builds the graph, flattening inline flow calls and expanding combinators into keyed nodes |
|
|
171
|
+
| `nodes`, `edges`, `drafts`, `diagnostics` | read what the build produced |
|
|
172
|
+
| `Graph`, `GraphNode`, `Edge`, `EdgeReason`, `LayerRequest`, `BuildOptions` | the models |
|
|
173
|
+
| `maximumGraphDepth` | the nesting bound the build refuses past, so an unrolling composition reads the same number |
|
|
174
|
+
| `evaluatedFrom` | states that a file about to be evaluated holds bytes read from another, so the declarations inside it report the entry an author can open |
|
|
175
|
+
|
|
176
|
+
A graph carrying a FATAL diagnostic is inspectable but deliberately not compilable, so a body whose topology is incomplete is reported rather than half-driven. Building refuses a nesting depth past its bound and refuses a duplicate node id, because a node id is durable dispatch identity and two nodes answering to one address would let a later settlement overwrite an earlier one.
|
|
177
|
+
|
|
178
|
+
Building also enforces effect authority. A flow that declared an `effects` envelope grants it to everything spliced beneath it, and every call and every action that declares one of its own is checked against the enclosing grant: a read or write the envelope does not cover is `effect_outside_envelope`, an `expected` declaration inside a `hermetic` envelope is `effect_mode_widening`, and a tier that rose rather than narrowed is `effect_tier_widening`. A refused declaration does not become the envelope for what it encloses, so one over-claim cannot widen its siblings. A called flow requiring a capability the caller does not hold is the one ADVISORY refusal, `capability_outside_grant`: the call runs with the capability dropped, which is the safe direction, so `drafts` still hands the drafts over while `diagnostics` reports it. Every check runs for `.call()`, `.child()`, and `.to()` alike: a boundary gives a callee its own execution, not its own authority.
|
|
179
|
+
|
|
180
|
+
A call node's key material folds in the declared schemas as their JSON Schema documents, so a change to what a callee accepts or produces re-keys the call. That identity is JSON-Schema-shaped, and the limit is worth stating: two schemas whose decoders disagree can serialize to the same document, so changing only a codec's behaviour does NOT re-key the call, and a result recorded under the old codec is replayed under the new one. Effect codecs are not serializable, so nothing can close this automatically. An author who changes a transformation and needs the call re-keyed renames the declaration.
|
|
181
|
+
|
|
182
|
+
## `Interpreter`
|
|
183
|
+
|
|
184
|
+
`Interpreter.layer(flow)` registers a flow with the runtime and installs the handler that drives its body. `Interpreter.interpret(flowOrNode, payload, options)` is that drive on its own, for a body you want to run without registering it.
|
|
185
|
+
|
|
186
|
+
Explicit `Node.andThen(next)` waits for upstream success before starting any
|
|
187
|
+
part of `next`, including actions inside an `all`, `map`, branch, catch, nested
|
|
188
|
+
sequence, or inline flow. Upstream failure or interruption does not activate
|
|
189
|
+
that subtree. `Graph.build` carries the same prerequisite into every descendant
|
|
190
|
+
draft. `Node.bindPlanned` is different: it builds data dependencies, so members
|
|
191
|
+
that do not use the reference may run concurrently with its producer.
|
|
192
|
+
|
|
193
|
+
The subtree-barrier correction changes compiled identities for affected nested
|
|
194
|
+
sequences. Newly plan and approve changed work; this is not an unfinished-run
|
|
195
|
+
migration or undo of effects an older runtime already started too early. It
|
|
196
|
+
also does not make the interpreter consume the compiled scheduler's filesystem
|
|
197
|
+
conflict edges, priorities or admission limits; that execution-path integration
|
|
198
|
+
remains a separate release requirement.
|
|
199
|
+
|
|
200
|
+
| Export | Purpose |
|
|
201
|
+
| ------------------ | ------------------------------------------------------------------------------------------------------------- |
|
|
202
|
+
| `layer` | registers a flow and installs its body handler |
|
|
203
|
+
| `interpret` | builds and walks the graph, returning an `Interpretation` |
|
|
204
|
+
| `Interpretation` | the root value, every node that settled, the typed failures a catch recovered, and the nodes a branch skipped |
|
|
205
|
+
| `childExecutionId` | the deterministic id a `.child()` boundary opens its child execution under |
|
|
206
|
+
| `InterpreterError` | the graph refusals, each with a stable `code` |
|
|
207
|
+
|
|
208
|
+
`InterpreterError` codes name what the run cannot recover from on its own: `incomplete_graph` for topology the build reported, `duplicate_node_id` for two nodes answering to one dispatch address, `unresolved_action` for an action with no implementation wired up, `unresolved_reference` for a payload reading a node this graph does not hold, `unsupported_call` for a call whose declaration did not survive serialization, and `missing_operation` for a deferred function that did not either.
|
|
209
|
+
|
|
210
|
+
The walk is demand-driven from the root rather than a sweep over the node list, because dependency order puts both branch arms before the branch that chooses between them, and executing an arm to discover it was not taken is exactly what static topology exists to avoid.
|
|
211
|
+
|
|
212
|
+
## `Sleep`
|
|
213
|
+
|
|
214
|
+
`Sleep.action` is the declared `system/sleep` step: a wait that is a keyed plan node rather than a second execution mechanism. Call it in a body wherever a round has to wait for time to pass, and provide `Sleep.layer` beside the other implementation layers.
|
|
215
|
+
|
|
216
|
+
```ts
|
|
217
|
+
Sleep.action.call({ millis: 60_000 })
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
A payload names exactly one deadline: a relative `millis`, or an absolute `until` in epoch milliseconds. `SleepRequestInvalid` is the typed refusal, with three codes:
|
|
221
|
+
|
|
222
|
+
| Code | Meaning |
|
|
223
|
+
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
|
224
|
+
| `missing_deadline` | the payload named neither `millis` nor `until` |
|
|
225
|
+
| `ambiguous_deadline` | it named both, which are the same fact stated two ways |
|
|
226
|
+
| `invalid_deadline` | it named a number that is not a length of time: a non-finite or negative `millis`, a non-finite `until`, or an addition that overflows |
|
|
227
|
+
|
|
228
|
+
Two waits of the same length are two waits: each call is its own node with its own identity, so `sleep` followed by `sleep` waits twice. A deadline that has already passed settles the node instead of parking it, because a run that resumes after its own deadline has to make progress.
|
|
229
|
+
|
|
230
|
+
## `WaitFor`
|
|
231
|
+
|
|
232
|
+
`WaitFor.action` is the declared `system/wait-for` step: a rendezvous with something outside the run. A payload names the wait point by `name`, relative to the running execution, or by an absolute `token`. `WaitFor.deferred(name)` is the resolver's half, the value to hand `DurableDeferred.tokenFromExecutionId` and `DurableDeferred.succeed`.
|
|
233
|
+
|
|
234
|
+
```ts
|
|
235
|
+
const gate = WaitFor.deferred("approval")
|
|
236
|
+
const token = DurableDeferred.tokenFromExecutionId(gate, { flow, executionId })
|
|
237
|
+
yield * DurableDeferred.succeed(gate, { token, value: { approved: true } })
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
`WaitForRequestInvalid` carries four codes: `missing_target` and `ambiguous_target` for a payload naming neither or both, `malformed_token` for a token that does not parse, and `foreign_execution` for a token addressed to another flow or another execution. A deferred result is recorded against the flow and execution that own it, so awaiting a foreign token would park forever while the value it names was recorded elsewhere.
|
|
241
|
+
|
|
242
|
+
## `Poll`
|
|
243
|
+
|
|
244
|
+
`Poll.make(tag, options)` declares a durable poller and returns an ordinary flow. Its body is one attempt: run `check`, and either settle the lineage with the check's own output or sleep for this attempt's delay and hand off to the next round with the attempt counter raised. Each attempt is therefore a durable round with its own keyed plan nodes, a check that already ran replays from its recorded outcome, and the wait between attempts is a durable timer that survives a process restart.
|
|
245
|
+
|
|
246
|
+
| Option | Meaning |
|
|
247
|
+
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
248
|
+
| `input` | the author's payload fields. `attempt` is added to them and defaults to one |
|
|
249
|
+
| `result` | the schema the poll settles with |
|
|
250
|
+
| `check` | a body fragment returning `{ satisfied, output }`. It may not fail; state what a failure means with `Node.catch` inside the fragment |
|
|
251
|
+
| `intervalMs`, `backoff` | the wait before the next attempt: `fixed`, `linear` (interval multiplied by attempt), or `exponential` (interval multiplied by 2 raised to attempt minus one) |
|
|
252
|
+
| `maxAttempts` | the attempt bound. It is also the flow's `maxRounds`, so a lineage that opened another round is refused by the engine |
|
|
253
|
+
| `onTimeout` | `fail` fails `PollExhausted` at the bound; `return-last` answers with the last check output |
|
|
254
|
+
|
|
255
|
+
`delayMillis` is the exported schedule function, `CheckResult(result)` is the success schema a check action declares, `Failure` is the union a poll's rounds can fail with, and `Poll.layer` implements the `system/poll-exhausted` step. `PollExhausted` carries the stable code `poll_exhausted`.
|
|
256
|
+
|
|
257
|
+
`Poll.make` refuses a schedule no clock can keep, with a `RangeError` naming the option that is wrong: an `intervalMs` that is not finite or is negative becomes a `system/sleep` node whose timer never fires, and a `maxAttempts` below one whole attempt reaches `Flow.make` as a complaint about `maxRounds`, an option the author never wrote. The check is on the schedule rather than on the interval alone, because `delayMillis` multiplies the interval by the backoff: `{ intervalMs: 1000, maxAttempts: 2000, backoff: "exponential" }` states three finite options and still asks for a wait of `Infinity`. The last wait a poll can arm, the one before the final attempt, has to be a length too, since the attempt at the budget gives up rather than sleeps.
|
|
258
|
+
|
|
259
|
+
### Bounding a check that can hang
|
|
260
|
+
|
|
261
|
+
A per-attempt time limit on the check is deliberately not a `Poll.make` option. A plan node's duration is not something the body around it can bound, so the bound goes in the check's own implementation, where `DurableDeferred.raceAll` races the work against a durable clock:
|
|
262
|
+
|
|
263
|
+
```ts
|
|
264
|
+
const Status = Action.make("deploy/status", {
|
|
265
|
+
payload: { id: Schema.String, attempt: Schema.Number },
|
|
266
|
+
success: Poll.CheckResult(Schema.String)
|
|
267
|
+
})
|
|
268
|
+
|
|
269
|
+
const statusLayer = Status.toLayer(({ attempt, id }) =>
|
|
270
|
+
DurableDeferred.raceAll({
|
|
271
|
+
name: `deploy/status#${attempt}`,
|
|
272
|
+
success: Poll.CheckResult(Schema.String),
|
|
273
|
+
error: Schema.Never,
|
|
274
|
+
effects: [
|
|
275
|
+
readDeployment(id),
|
|
276
|
+
Effect.as(
|
|
277
|
+
DurableClock.sleep({
|
|
278
|
+
name: `deploy/status#${attempt}`,
|
|
279
|
+
duration: Duration.seconds(30),
|
|
280
|
+
inMemoryThreshold: Duration.zero
|
|
281
|
+
}),
|
|
282
|
+
{ satisfied: false, output: "unknown" }
|
|
283
|
+
)
|
|
284
|
+
]
|
|
285
|
+
})
|
|
286
|
+
)
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
Three things make this the durable bound rather than a wall-clock one. The race records its winner under a name that carries the attempt, so a re-driven round reads the recorded outcome instead of racing again. The clock parks the execution rather than holding a fiber, so the bound outlives the process waiting on it. And the clock's branch answers `satisfied: false`, so a check that ran out of time costs the poll one attempt and nothing else: the round takes its declared interval and hands off to the next attempt exactly as an unsatisfied check does.
|
|
290
|
+
|
|
291
|
+
## `ExternalJob`
|
|
292
|
+
|
|
293
|
+
`ExternalJob.make(tag, { payload, handle, success, error?, probe, timeout, restarts? })`
|
|
294
|
+
declares external work using ordinary actions, child boundaries and durable
|
|
295
|
+
handoffs. Its `toLayer` attaches `start`, `status`, `collect` and `cancel`.
|
|
296
|
+
`error` declares the full provider failure union. `call` uses a child boundary
|
|
297
|
+
so every job has its own durable identity.
|
|
298
|
+
|
|
299
|
+
Providers receive `<job execution id>#g<generation>`. Start must create-or-get
|
|
300
|
+
by that key; Status is read-only and keyed per probe; Collect and Cancel are
|
|
301
|
+
idempotent. Probe delays double from `every` up to `max`. The journaled original
|
|
302
|
+
deadline survives handoffs and host restarts. Lost or `Again` completes Cancel
|
|
303
|
+
before replacement; `restarts` defaults to zero. Exhaustion fails
|
|
304
|
+
`ExternalJobLost` (`infra`), while timeout fails `ExternalJobTimedOut`
|
|
305
|
+
(`dependency`). See [Run an external job](./guides/run-an-external-job.md).
|
|
306
|
+
|
|
307
|
+
## `Fault`
|
|
308
|
+
|
|
309
|
+
One typed fault for every failure. The owner of an error union registers each code with a class, so a failure crosses every seam as `{ class, tag }` instead of prose.
|
|
310
|
+
|
|
311
|
+
| Export | Behavior |
|
|
312
|
+
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
313
|
+
| `Class` | `user`, `wait`, `infra`, `dependency`, `bug` (the wire registry), plus `factory` (the factory's own work did not converge; a replan may fix it) and `policy` (a cap stopped it). |
|
|
314
|
+
| `Fault` | `{ class, tag }`. `tag` is `<_tag>/<code>`, or `<_tag>` for an error without a code. |
|
|
315
|
+
| `register(tag, table, field?)` | One class for the whole tag, or one per value of `field` (default `code`). Owners write `satisfies Fault.Rows<Code>`, so a new code without a class does not compile. A value the table does not name is `bug`. The registry is one per process (shared by the ESM and CommonJS builds); registering a tag again with the same rows is a no-op, and with different rows throws. |
|
|
316
|
+
| `of(error)` | Reads the error and up to 15 `cause` links beneath it and answers the innermost registered tag, because a wrapper names where a failure surfaced and its cause names why. Anything unregistered is `{ class: "bug", tag: "unregistered" }`. |
|
|
317
|
+
| `respond(fault, state)` | The one response ladder, exhaustive over the classes: `wait` backs up, then parks while `parksLeft` allows, `dependency` backs up then retries (3 attempts), `infra` retries then parks, `factory` replans twice, continues once as `very_hard`, then asks for `help`, a declined request (`coding/Error/declined`) closes, any other `user` fault asks for `help`, and `policy` and `bug` stop. |
|
|
318
|
+
| `registered()` | Every registered tag; the sweep tests read it. |
|
|
319
|
+
|
|
320
|
+
A failed agent run, and a launch the executor refused, journal the fault on `control.run.failed` beside `cause`; the gateway carries it to the worker as `failureFault` and `failureTag`, and drops it once the run resumes.
|
|
321
|
+
|
|
322
|
+
## `Stall`
|
|
323
|
+
|
|
324
|
+
`Stall` is the stall breaker round loops share. `Stall.policy({ rounds, on })` resolves `rounds` (at least two) and `on` (`stop`, the default, `park`, or `escalate`). `Stall.observe(policy, state, observation)` folds one round into the carried `State` and returns the next state with a `Stalled` verdict once one signal held for `rounds` rounds in a row. An observation reports any of `tree` (a tree fingerprint), `checks` (failing check ids, order ignored, empty not compared), and `output` (compared by the SHA-256 of its canonical JSON; a value with no canonical form is not compared). `Stall.initial` is the state before the first round. `State`, `Policy` and `Stalled` are schemas, so a trampoline carries the state in its payload and replay reads the same verdict. The loop decides what `on` means; `@smthrs/patterns` loops and the coding correction flow use it.
|
|
325
|
+
|
|
326
|
+
## `HumanTask`
|
|
327
|
+
|
|
328
|
+
`HumanTask.action` is the declared `system/human-task` step: a typed question with re-asking and a deadline, built on `WaitFor`'s wait points and `DurableClock`.
|
|
329
|
+
|
|
330
|
+
| Payload field | Meaning |
|
|
331
|
+
| ------------- | ------------------------------------------------------------------------------------------------------------ |
|
|
332
|
+
| `name` | addresses the question. Two calls naming one question in one execution await one answer |
|
|
333
|
+
| `kind` | `ask` (prose), `confirm` (a boolean), `select` (one of `options`), `json` (a value `schema` accepts) |
|
|
334
|
+
| `prompt` | what the person is asked |
|
|
335
|
+
| `options` | the choices a `select` offers |
|
|
336
|
+
| `schema` | a JSON Schema in the bounded subset, valid only with `kind: "json"` |
|
|
337
|
+
| `maxAttempts` | how many answers may be refused before the task fails. Defaults to `defaultMaxAttempts` (10) |
|
|
338
|
+
| `timeoutMs` | how long the question stays open, across every attempt. A finite number of milliseconds that is not negative |
|
|
339
|
+
|
|
340
|
+
The bounded schema subset is `type` (`object`, `array`, `string`, `number`, `integer`, `boolean`, `null`), `enum`, `properties`, `required`, `items`, `nullable`, `description`, and `title`. `enum` members may be any JSON value, including objects and arrays, and membership is compared structurally rather than by reference. A schema supplied with any kind other than `json` is refused as `request_invalid`, because nothing would check it.
|
|
341
|
+
|
|
342
|
+
Each attempt is its own durable wait point, `WaitFor/<name>#<attempt>`, so an answer is recorded through the ordinary durable deferred path and a refused answer stays recorded under the attempt that refused it. The refusal itself is recorded as a sealed step named `HumanTask/<name>#<attempt>/rejected`, carrying the task, the attempt, and the reason, so a reader of the journal sees why an answer was sent back. The run parks under the `approval` waiting reason carrying the current attempt's token, and `HumanTask.answer({ token, value })` records an answer against it. A re-driven round replays every answer it already has and parks on the first attempt that has none, so a restart between the park and the answer resumes on the same token.
|
|
343
|
+
|
|
344
|
+
The park also publishes `WaitingAnnotation.request` as JSON text containing
|
|
345
|
+
`task: "human"`, `name`, `kind`, `prompt`, `attempt`, `maxAttempts`, and any
|
|
346
|
+
declared `options` or `schema`. It describes the question without including an
|
|
347
|
+
answer. Durable readers use it to render pending questions, including waits
|
|
348
|
+
inside child executions; routing still uses the wait token.
|
|
349
|
+
|
|
350
|
+
`HumanTaskFailed` carries `code`, `task`, `attempts`, the `rejections` it collected, and a message. `request_invalid` refuses an unanswerable question before anyone is asked: a `select` with no options, an attempt budget below one or above the documented ceiling, a `timeoutMs` that is not a length of time, a schema outside the subset, a schema past the depth or node bound, or a schema supplied with the wrong kind. `rejected` means the budget was spent on answers the task refused. `timeout` means the deadline passed with the question open.
|
|
351
|
+
|
|
352
|
+
Sizes are bounded so one question cannot grow a durable record without limit. The attempt budget is refused above `maxAttemptBudget`, the schema is refused past `maxSchemaDepth` levels or `maxSchemaNodes` nodes, an answer is refused past `maxAnswerNodes` visited values, a value echoed into a rejection message is truncated at `maxDiagnosticChars` with an explicit marker, and the retained `rejections` array stops at `maxRetainedRejectionChars` and records how many further rejections it omitted. The per-attempt journal step still records its own full reason: only the accumulated array is capped, because a refused answer stays recorded so the record shows what was actually said.
|
|
353
|
+
|
|
354
|
+
`timeoutMs` races the answer against one `DurableClock` per task through `DurableDeferred.raceAll`. The race parks and settles on whichever arrives first, on both hosts: the in-process engine and the SQLite engine store each re-enter a parked race on the next drive, re-registering the raced deferreds against their persisted completions. A parked dispatch keeps its attempt row and its attempt number, so a question that waits out a person costs nothing against the action's retry budget.
|
|
355
|
+
|
|
356
|
+
`validate(value, request)` returns the reason an answer was refused, or `undefined`; run it in the interface so a typo is refused while the person is still looking at it. `validateSchema(schema)` checks that a schema stays inside the subset at every depth. `decode(schema)` gives the `Schema.Json` answer the caller's own type; the two schema descriptions must agree, and a disagreement surfaces as a defect rather than as a failure a body could catch.
|
|
357
|
+
|
|
358
|
+
## `RetryPolicy`
|
|
359
|
+
|
|
360
|
+
A `RetryPolicy` is a plain value, so the next retry delay is derived from a persisted attempt count instead of fiber-local `Schedule` state. `nextDelay` mirrors Temporal's `ComputeNextDelay`, and `decide` is the engine's single retry decision point.
|
|
361
|
+
|
|
362
|
+
`RetryPolicy.make` validates its bounds and throws a `RangeError` naming the field that is wrong: `initialMs` finite and greater than zero, `factor` finite and positive, `maxMs` finite and not below `initialMs`, `maxAttempts` a safe integer of at least one, `expirationMs` finite and positive, and `jitterRatio` finite and within zero and one inclusive. `initialMs: 0` is refused rather than read as an immediate retry, because every computed delay would be zero and the policy would give up on its first failure; use `initialMs: 1` for a near-immediate retry. It also copies and freezes the `nonRetryable` array, so a later mutation of the caller's array cannot change what a parked policy means.
|
|
363
|
+
|
|
364
|
+
`nextDelay` is total even for a policy that never went through `make`, which is what a policy decoded from a persisted row is: a non-finite attempt, elapsed time, bound, or computed delay answers `None` rather than handing the engine a negative or `NaN` duration to sleep for.
|
|
365
|
+
|
|
366
|
+
`decide` classifies non-retryable errors here and nowhere else, by the policy's declared tags and by `defaultNonRetryable`, which lists the integrity verdicts that must reach the driver unretried under every policy. Exhaustion and expiration preserve the final declared failure. The older `RetryPolicyExpired` and `RetryAttemptsExhausted` schemas remain available for interpreting historical outcomes.
|
|
367
|
+
|
|
368
|
+
## `StepIdentity`
|
|
369
|
+
|
|
370
|
+
| Export | Purpose |
|
|
371
|
+
| -------------------- | ------------------------------------------------------ |
|
|
372
|
+
| `AllocationIdentity` | an action name refined by a declared string key |
|
|
373
|
+
| `allocationScope` | the scope an ordinal is allocated from |
|
|
374
|
+
| `invocationKey` | the run-local ordinal step key |
|
|
375
|
+
| `DispatchSite` | the structural graph address one dispatch is scoped to |
|
|
376
|
+
|
|
377
|
+
## `FlowRuntime`
|
|
378
|
+
|
|
379
|
+
`FlowRuntime` is the service tag the authoring APIs are written against: registration, execution, polling, safe and unsafe interruption, resume, action execution, deferred lookup and completion, and clock scheduling. This package declares the port and depends on nothing that implements it, so the dependency direction is `@smthrs/flow` then `@smthrs/engine` then the durable stores, with no cycle and no type-only escape hatch back.
|
|
380
|
+
|
|
381
|
+
| Export | Purpose |
|
|
382
|
+
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
383
|
+
| `FlowRuntime` | the port itself |
|
|
384
|
+
| `FlowInstance` | one execution's mutable frontier state: execution id, flow, scope, suspension and interruption flags, the waiting annotation, and action coordination |
|
|
385
|
+
| `annotateWaiting` | declares how the flow is about to wait, so a durable driver parks the run under that reason and token |
|
|
386
|
+
| `WaitingAnnotation` | `{ reason, wakeAt?, token?, request? }`; `request` is JSON text describing the wait, not a routing key |
|
|
387
|
+
| `FlowCycleDetected` | executing a flow would close a cycle in the persisted parent chain |
|
|
388
|
+
| `FlowExecutionNotFound` | `poll` was given an execution id the runtime does not hold; `resume` has no error channel and ignores an unknown id |
|
|
389
|
+
| `CancelRequestFailed` | a durable runtime could not record a cancellation, with `cancel_request_failed` for a storage failure and `unsafe_interrupt_unsupported` for `interruptUnsafe`, which the durable engine does not implement |
|
|
390
|
+
|
|
391
|
+
`runtime.resume(flow, executionId)` and `MyFlow.resume(executionId)` are
|
|
392
|
+
explicit resumes. `{ poll: true }` drives background polling without recovery
|
|
393
|
+
consent; local and remote dispatch preserve this choice. `{ delegated: true }`
|
|
394
|
+
records a local background wake without recovery consent and retains the
|
|
395
|
+
coordinator wake signal. Remote placement refuses delegated resumes.
|
|
396
|
+
|
|
397
|
+
## See also
|
|
398
|
+
|
|
399
|
+
- [Flows and actions](./concepts/flows-and-actions.md), [bodies are plans](./concepts/bodies-and-plans.md), [execution identity](./concepts/execution-identity.md), [suspension and replay](./concepts/suspension-and-replay.md), [trampoline rounds](./concepts/trampoline-rounds.md), and [the runtime port](./concepts/the-runtime-port.md): the model behind this surface.
|
|
400
|
+
- [Export reference](./reference/flow.md): every symbol, with types and defaults read from source.
|
|
401
|
+
- [Troubleshooting](./troubleshooting.md): the same failures, sorted by symptom.
|
|
402
|
+
- [`@smthrs/engine`](/api/engine) implements the `FlowRuntime` port, and [`@smthrs/engine-store`](/api/engine-store) makes it durable.
|
|
403
|
+
- [`@smthrs/plan`](/api/plan) owns the `Node` and `FileSet` vocabulary a body is written in.
|
|
404
|
+
|
|
405
|
+
## Explicit execution and registration
|
|
406
|
+
|
|
407
|
+
`flow.start(payload)` starts fresh work and returns its execution id, even for
|
|
408
|
+
identical payloads or a declaration with an idempotency key.
|
|
409
|
+
`flow.ensure(payload, { key })` starts or joins explicitly keyed work and returns
|
|
410
|
+
its id. Both return after admission and scheduling, before the child settles,
|
|
411
|
+
including when called inside an action. The child continues after that action
|
|
412
|
+
or parent round finishes. `execute(payload, { discard: true })` has the same
|
|
413
|
+
return timing. Keep the engine scope open while it runs; the memory engine
|
|
414
|
+
retains work only for that scope, and the durable engine records work for
|
|
415
|
+
recovery after a host restart. Use `poll(id)` to observe it, or
|
|
416
|
+
`execute(payload, { executionId: id })` to await it. The default unkeyed `execute` now starts fresh work. To reattach after a crash,
|
|
417
|
+
retain and pass the execution id, declare an idempotency key, or deliberately
|
|
418
|
+
install `Flow.layerExecutionIds(Flow.derived)`. Existing stored key encodings are
|
|
419
|
+
unchanged; the library does not rewrite historical runs.
|
|
420
|
+
|
|
421
|
+
`Interpreter.layerWithImplementations(flow, implementationLayer)` builds the
|
|
422
|
+
interpreter and all action implementations against one isolated registry. Its
|
|
423
|
+
types require every action named by the flow; runtime graph preflight rejects
|
|
424
|
+
missing handlers before dispatch. Conflicting same-tag registrations fail during
|
|
425
|
+
layer construction. Intentional scoped substitution uses
|
|
426
|
+
`action.toLayer(handler, { override: true })`.
|
|
427
|
+
|
|
428
|
+
### Execution identity conflicts
|
|
429
|
+
|
|
430
|
+
`Flow.execute` fails with `FlowRuntime.ExecutionIdentityConflict` when an id
|
|
431
|
+
conflicts with the recorded identity. The value is also exported as
|
|
432
|
+
`FlowEngine.ExecutionIdentityConflict` and carries the existing execution
|
|
433
|
+
`status`. A caller may choose a new id only for `completed`, `failed`, or
|
|
434
|
+
`cancelled` executions. A live or suspended execution must retain its id to
|
|
435
|
+
avoid starting a second worker. Older low-level refusals may report
|
|
436
|
+
`unknown`; that status never authorizes re-keying.
|