blokctl 1.2.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (693) hide show
  1. package/dist/commands/create/project.d.ts +3 -0
  2. package/dist/commands/create/project.js +166 -21
  3. package/dist/commands/create/utils/Examples.d.ts +2 -2
  4. package/dist/commands/create/utils/Examples.js +9 -3
  5. package/dist/commands/dev/index.js +13 -1
  6. package/dist/commands/runtime/add.js +92 -29
  7. package/dist/commands/runtime/index.js +1 -0
  8. package/dist/commands/runtime/shared.js +4 -0
  9. package/dist/scaffold-repo/examples/ts-workflows/mcp-greeter.ts +59 -0
  10. package/dist/scaffold-repo/examples/ts-workflows/runtime-csharp-hello.ts +36 -0
  11. package/dist/scaffold-repo/examples/ts-workflows/runtime-go-hello.ts +36 -0
  12. package/dist/scaffold-repo/examples/ts-workflows/runtime-java-hello.ts +36 -0
  13. package/dist/scaffold-repo/examples/ts-workflows/runtime-php-hello.ts +36 -0
  14. package/dist/scaffold-repo/examples/ts-workflows/runtime-python3-hello.ts +36 -0
  15. package/dist/scaffold-repo/examples/ts-workflows/runtime-ruby-hello.ts +36 -0
  16. package/dist/scaffold-repo/examples/ts-workflows/runtime-rust-hello.ts +36 -0
  17. package/dist/scaffold-repo/infra/development/3055.dat +602 -0
  18. package/dist/scaffold-repo/infra/development/3057.dat +203 -0
  19. package/dist/scaffold-repo/infra/development/3059.dat +19 -0
  20. package/dist/scaffold-repo/infra/development/3061.dat +1003 -0
  21. package/dist/scaffold-repo/infra/development/3062.dat +5465 -0
  22. package/dist/scaffold-repo/infra/development/3063.dat +1003 -0
  23. package/dist/scaffold-repo/infra/development/3065.dat +606 -0
  24. package/dist/scaffold-repo/infra/development/3067.dat +603 -0
  25. package/dist/scaffold-repo/infra/development/3069.dat +112 -0
  26. package/dist/scaffold-repo/infra/development/3071.dat +4584 -0
  27. package/dist/scaffold-repo/infra/development/3073.dat +9 -0
  28. package/dist/scaffold-repo/infra/development/3075.dat +14599 -0
  29. package/dist/scaffold-repo/infra/development/3077.dat +16047 -0
  30. package/dist/scaffold-repo/infra/development/3079.dat +5 -0
  31. package/dist/scaffold-repo/infra/development/3081.dat +5 -0
  32. package/dist/scaffold-repo/infra/development/docker-compose.yml +106 -0
  33. package/dist/scaffold-repo/infra/development/schema.sql +1616 -0
  34. package/dist/scaffold-repo/infra/development/toc.dat +0 -0
  35. package/dist/scaffold-repo/infra/metrics/alertmanager.yml +43 -0
  36. package/dist/scaffold-repo/infra/metrics/alloy-config.alloy +75 -0
  37. package/dist/scaffold-repo/infra/metrics/dashboard.json +1152 -0
  38. package/dist/scaffold-repo/infra/metrics/dashboards/blok-overview.json +314 -0
  39. package/dist/scaffold-repo/infra/metrics/dashboards/blok-system.json +175 -0
  40. package/dist/scaffold-repo/infra/metrics/dashboards/blok-tracing.json +235 -0
  41. package/dist/scaffold-repo/infra/metrics/dashboards/blok-triggers.json +258 -0
  42. package/dist/scaffold-repo/infra/metrics/datasources.yml +43 -0
  43. package/dist/scaffold-repo/infra/metrics/default.yaml +8 -0
  44. package/dist/scaffold-repo/infra/metrics/docker-compose.yml +193 -0
  45. package/dist/scaffold-repo/infra/metrics/loki-config.yaml +50 -0
  46. package/dist/scaffold-repo/infra/metrics/nginx.conf +25 -0
  47. package/dist/scaffold-repo/infra/metrics/prometheus.yml +51 -0
  48. package/dist/scaffold-repo/infra/metrics/rules/blok-alerts.yml +114 -0
  49. package/dist/scaffold-repo/infra/metrics/telegraf.conf +41 -0
  50. package/dist/scaffold-repo/infra/metrics/tempo.yaml +81 -0
  51. package/dist/scaffold-repo/infra/milvus/docker-compose.yml +73 -0
  52. package/dist/scaffold-repo/sdk/javascript/README.md +151 -0
  53. package/dist/scaffold-repo/sdk/javascript/bootstrap.min.css +11660 -0
  54. package/dist/scaffold-repo/sdk/javascript/image-ai.html +316 -0
  55. package/dist/scaffold-repo/sdk/javascript/nanosdk.js +180 -0
  56. package/dist/scaffold-repo/sdk/javascript/nanosdk.min.js +100 -0
  57. package/dist/scaffold-repo/sdk/javascript/pdf.html +63 -0
  58. package/dist/scaffold-repo/sdk/javascript/test.html +68 -0
  59. package/dist/scaffold-repo/sdks/CLAUDE.md +67 -0
  60. package/dist/scaffold-repo/sdks/csharp/.dockerignore +7 -0
  61. package/dist/scaffold-repo/sdks/csharp/Blok.Core.sln +24 -0
  62. package/dist/scaffold-repo/sdks/csharp/Dockerfile +42 -0
  63. package/dist/scaffold-repo/sdks/csharp/README.md +138 -0
  64. package/dist/scaffold-repo/sdks/csharp/proto/blok/runtime/v1/runtime.proto +302 -0
  65. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Blok.Core.csproj +39 -0
  66. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Config/ServerConfig.cs +90 -0
  67. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Errors/BlokError.cs +538 -0
  68. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Errors/BlokErrorCategory.cs +112 -0
  69. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Errors/BlokErrorSeverity.cs +40 -0
  70. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Errors/BuildContextSnapshot.cs +168 -0
  71. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Errors/ErrorCategory.cs +13 -0
  72. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Errors/NodeException.cs +44 -0
  73. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Logging/LogEntry.cs +34 -0
  74. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Logging/LogLevel.cs +12 -0
  75. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Logging/Logger.cs +92 -0
  76. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Middleware/IMiddleware.cs +14 -0
  77. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Middleware/LoggingMiddleware.cs +46 -0
  78. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Middleware/MiddlewareChain.cs +35 -0
  79. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Middleware/RecoveryMiddleware.cs +63 -0
  80. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Node/INodeHandler.cs +17 -0
  81. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Node/NodeRegistry.cs +128 -0
  82. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Node/TypedNode.cs +140 -0
  83. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Nodes/ApiCallNode.cs +129 -0
  84. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Nodes/BlokErrorDemoNode.cs +125 -0
  85. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Nodes/ChainTestNode.cs +79 -0
  86. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Nodes/HelloWorldNode.cs +45 -0
  87. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Nodes/TransformDataNode.cs +119 -0
  88. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Nodes/TypedGreetNode.cs +23 -0
  89. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Program.cs +26 -0
  90. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Server/BlokNodeRuntimeService.cs +536 -0
  91. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Server/RuntimeServer.cs +183 -0
  92. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Testing/MockContextBuilder.cs +117 -0
  93. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Testing/TestNodeRunner.cs +50 -0
  94. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Types/Context.cs +56 -0
  95. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Types/ExecutionMetrics.cs +21 -0
  96. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Types/ExecutionRequest.cs +15 -0
  97. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Types/ExecutionResult.cs +104 -0
  98. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Types/HealthStatus.cs +18 -0
  99. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Types/NodeConfig.cs +59 -0
  100. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Types/Request.cs +57 -0
  101. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Types/Response.cs +24 -0
  102. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/UserNodeRegistry.cs +17 -0
  103. package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Validation/SchemaValidator.cs +198 -0
  104. package/dist/scaffold-repo/sdks/csharp/tests/Blok.Core.Tests/Blok.Core.Tests.csproj +25 -0
  105. package/dist/scaffold-repo/sdks/csharp/tests/Blok.Core.Tests/Errors/BlokErrorTests.cs +458 -0
  106. package/dist/scaffold-repo/sdks/csharp/tests/Blok.Core.Tests/Logging/LoggerTests.cs +129 -0
  107. package/dist/scaffold-repo/sdks/csharp/tests/Blok.Core.Tests/Node/NodeRegistryTests.cs +145 -0
  108. package/dist/scaffold-repo/sdks/csharp/tests/Blok.Core.Tests/Testing/MockContextTests.cs +153 -0
  109. package/dist/scaffold-repo/sdks/csharp/tests/Blok.Core.Tests/TypedNodeTests.cs +69 -0
  110. package/dist/scaffold-repo/sdks/csharp/tests/Blok.Core.Tests/Types/ExecutionResultTests.cs +110 -0
  111. package/dist/scaffold-repo/sdks/csharp/tests/Blok.Core.Tests/Validation/SchemaValidatorTests.cs +233 -0
  112. package/dist/scaffold-repo/sdks/go/Dockerfile +33 -0
  113. package/dist/scaffold-repo/sdks/go/README.md +255 -0
  114. package/dist/scaffold-repo/sdks/go/blok_error.go +803 -0
  115. package/dist/scaffold-repo/sdks/go/blok_error_test.go +433 -0
  116. package/dist/scaffold-repo/sdks/go/cmd/server/main.go +45 -0
  117. package/dist/scaffold-repo/sdks/go/cmd/server/register_user_nodes.go +12 -0
  118. package/dist/scaffold-repo/sdks/go/config.go +157 -0
  119. package/dist/scaffold-repo/sdks/go/config_test.go +129 -0
  120. package/dist/scaffold-repo/sdks/go/define_node.go +87 -0
  121. package/dist/scaffold-repo/sdks/go/define_node_test.go +75 -0
  122. package/dist/scaffold-repo/sdks/go/errors.go +104 -0
  123. package/dist/scaffold-repo/sdks/go/errors_test.go +95 -0
  124. package/dist/scaffold-repo/sdks/go/examples/nodes/apicall.go +117 -0
  125. package/dist/scaffold-repo/sdks/go/examples/nodes/blokerrordemo.go +80 -0
  126. package/dist/scaffold-repo/sdks/go/examples/nodes/chaintest.go +63 -0
  127. package/dist/scaffold-repo/sdks/go/examples/nodes/helloworld.go +41 -0
  128. package/dist/scaffold-repo/sdks/go/examples/nodes/transformdata.go +176 -0
  129. package/dist/scaffold-repo/sdks/go/examples/nodes/typedgreet.go +34 -0
  130. package/dist/scaffold-repo/sdks/go/genpb/blok/runtime/v1/runtime.pb.go +2070 -0
  131. package/dist/scaffold-repo/sdks/go/genpb/blok/runtime/v1/runtime_grpc.pb.go +273 -0
  132. package/dist/scaffold-repo/sdks/go/go.mod +25 -0
  133. package/dist/scaffold-repo/sdks/go/go.sum +66 -0
  134. package/dist/scaffold-repo/sdks/go/grpc_server.go +670 -0
  135. package/dist/scaffold-repo/sdks/go/grpc_server_test.go +474 -0
  136. package/dist/scaffold-repo/sdks/go/logging.go +144 -0
  137. package/dist/scaffold-repo/sdks/go/logging_test.go +139 -0
  138. package/dist/scaffold-repo/sdks/go/middleware.go +152 -0
  139. package/dist/scaffold-repo/sdks/go/middleware_test.go +222 -0
  140. package/dist/scaffold-repo/sdks/go/node.go +50 -0
  141. package/dist/scaffold-repo/sdks/go/proto/blok/runtime/v1/runtime.proto +302 -0
  142. package/dist/scaffold-repo/sdks/go/registry.go +156 -0
  143. package/dist/scaffold-repo/sdks/go/registry_test.go +195 -0
  144. package/dist/scaffold-repo/sdks/go/server.go +207 -0
  145. package/dist/scaffold-repo/sdks/go/server_test.go +186 -0
  146. package/dist/scaffold-repo/sdks/go/shutdown.go +32 -0
  147. package/dist/scaffold-repo/sdks/go/testutil.go +169 -0
  148. package/dist/scaffold-repo/sdks/go/testutil_test.go +124 -0
  149. package/dist/scaffold-repo/sdks/go/types.go +295 -0
  150. package/dist/scaffold-repo/sdks/go/types_test.go +251 -0
  151. package/dist/scaffold-repo/sdks/go/validation.go +210 -0
  152. package/dist/scaffold-repo/sdks/go/validation_test.go +262 -0
  153. package/dist/scaffold-repo/sdks/go/worker.go +577 -0
  154. package/dist/scaffold-repo/sdks/java/Dockerfile +33 -0
  155. package/dist/scaffold-repo/sdks/java/README.md +221 -0
  156. package/dist/scaffold-repo/sdks/java/pom.xml +163 -0
  157. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/Main.java +90 -0
  158. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/UserNodeRegistry.java +19 -0
  159. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/config/ServerConfig.java +244 -0
  160. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/errors/BlokError.java +576 -0
  161. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/errors/BlokErrorCategory.java +68 -0
  162. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/errors/BlokErrorSeverity.java +31 -0
  163. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/errors/BuildContextSnapshot.java +132 -0
  164. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/errors/ErrorCategory.java +22 -0
  165. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/errors/NodeException.java +176 -0
  166. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/logging/LogEntry.java +78 -0
  167. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/logging/LogLevel.java +48 -0
  168. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/logging/Logger.java +160 -0
  169. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/middleware/LoggingMiddleware.java +65 -0
  170. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/middleware/Middleware.java +29 -0
  171. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/middleware/MiddlewareChain.java +59 -0
  172. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/middleware/RecoveryMiddleware.java +53 -0
  173. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/node/NodeHandler.java +40 -0
  174. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/node/NodeReflector.java +18 -0
  175. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/node/NodeRegistry.java +205 -0
  176. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/node/TypedNode.java +143 -0
  177. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/nodes/ApiCallNode.java +145 -0
  178. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/nodes/BlokErrorDemoNode.java +109 -0
  179. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/nodes/ChainTestNode.java +65 -0
  180. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/nodes/HelloWorldNode.java +62 -0
  181. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/nodes/TransformDataNode.java +121 -0
  182. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/nodes/TypedGreetNode.java +41 -0
  183. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/server/BlokGrpcServer.java +103 -0
  184. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/server/BlokNodeRuntimeService.java +501 -0
  185. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/server/RuntimeServer.java +176 -0
  186. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/testing/MockContext.java +120 -0
  187. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/testing/TestRunner.java +59 -0
  188. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/types/Context.java +167 -0
  189. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/types/ExecutionMetrics.java +80 -0
  190. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/types/ExecutionRequest.java +61 -0
  191. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/types/ExecutionResult.java +188 -0
  192. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/types/HealthStatus.java +77 -0
  193. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/types/NodeConfig.java +139 -0
  194. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/types/Request.java +154 -0
  195. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/types/Response.java +77 -0
  196. package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/validation/SchemaValidator.java +178 -0
  197. package/dist/scaffold-repo/sdks/java/src/main/proto/blok/runtime/v1/runtime.proto +302 -0
  198. package/dist/scaffold-repo/sdks/java/src/test/java/com/blok/blok/errors/BlokErrorTest.java +416 -0
  199. package/dist/scaffold-repo/sdks/java/src/test/java/com/blok/blok/logging/LoggerTest.java +176 -0
  200. package/dist/scaffold-repo/sdks/java/src/test/java/com/blok/blok/node/NodeRegistryTest.java +227 -0
  201. package/dist/scaffold-repo/sdks/java/src/test/java/com/blok/blok/node/TypedNodeTest.java +76 -0
  202. package/dist/scaffold-repo/sdks/java/src/test/java/com/blok/blok/server/RuntimeServerTest.java +197 -0
  203. package/dist/scaffold-repo/sdks/java/src/test/java/com/blok/blok/types/ExecutionResultTest.java +194 -0
  204. package/dist/scaffold-repo/sdks/java/src/test/java/com/blok/blok/validation/SchemaValidatorTest.java +246 -0
  205. package/dist/scaffold-repo/sdks/php/.rr.yaml +29 -0
  206. package/dist/scaffold-repo/sdks/php/Dockerfile +61 -0
  207. package/dist/scaffold-repo/sdks/php/README.md +387 -0
  208. package/dist/scaffold-repo/sdks/php/composer.json +41 -0
  209. package/dist/scaffold-repo/sdks/php/examples/ApiCallNode.php +103 -0
  210. package/dist/scaffold-repo/sdks/php/examples/BlokErrorDemoNode.php +90 -0
  211. package/dist/scaffold-repo/sdks/php/examples/ChainTestNode.php +56 -0
  212. package/dist/scaffold-repo/sdks/php/examples/HelloWorldNode.php +39 -0
  213. package/dist/scaffold-repo/sdks/php/examples/TransformDataNode.php +94 -0
  214. package/dist/scaffold-repo/sdks/php/examples/TypedGreetNode.php +57 -0
  215. package/dist/scaffold-repo/sdks/php/phpunit.xml +23 -0
  216. package/dist/scaffold-repo/sdks/php/proto/blok/runtime/v1/runtime.proto +302 -0
  217. package/dist/scaffold-repo/sdks/php/src/Config/ServerConfig.php +83 -0
  218. package/dist/scaffold-repo/sdks/php/src/Errors/BlokError.php +467 -0
  219. package/dist/scaffold-repo/sdks/php/src/Errors/BlokErrorBuilder.php +121 -0
  220. package/dist/scaffold-repo/sdks/php/src/Errors/BlokErrorCategory.php +83 -0
  221. package/dist/scaffold-repo/sdks/php/src/Errors/BlokErrorSeverity.php +30 -0
  222. package/dist/scaffold-repo/sdks/php/src/Errors/BuildContextSnapshot.php +141 -0
  223. package/dist/scaffold-repo/sdks/php/src/Errors/ErrorCategory.php +17 -0
  224. package/dist/scaffold-repo/sdks/php/src/Errors/NodeException.php +107 -0
  225. package/dist/scaffold-repo/sdks/php/src/Errors/Origin.php +35 -0
  226. package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/ErrorCategory.php +118 -0
  227. package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/ErrorSeverity.php +72 -0
  228. package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/ExecuteEvent.php +181 -0
  229. package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/ExecuteOptions.php +159 -0
  230. package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/ExecuteRequest.php +328 -0
  231. package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/ExecuteResponse.php +288 -0
  232. package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/HealthRequest.php +59 -0
  233. package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/HealthResponse/Status.php +54 -0
  234. package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/HealthResponse.php +113 -0
  235. package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/ListNodesRequest.php +32 -0
  236. package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/ListNodesResponse.php +154 -0
  237. package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/LogLine.php +156 -0
  238. package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/Metrics.php +165 -0
  239. package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/NodeDescriptor.php +174 -0
  240. package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/NodeError.php +627 -0
  241. package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/NodeRef.php +134 -0
  242. package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/NodeRuntimeClient.php +101 -0
  243. package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/NodeStarted.php +68 -0
  244. package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/PartialResult.php +59 -0
  245. package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/Progress.php +85 -0
  246. package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/RuntimeState.php +142 -0
  247. package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/StepInfo.php +168 -0
  248. package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/TriggerInfo.php +289 -0
  249. package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/WorkflowInfo.php +176 -0
  250. package/dist/scaffold-repo/sdks/php/src/Genpb/GPBMetadata/Blok/Runtime/V1/Runtime.php +26 -0
  251. package/dist/scaffold-repo/sdks/php/src/Logging/LogEntry.php +47 -0
  252. package/dist/scaffold-repo/sdks/php/src/Logging/LogLevel.php +50 -0
  253. package/dist/scaffold-repo/sdks/php/src/Logging/Logger.php +133 -0
  254. package/dist/scaffold-repo/sdks/php/src/Node/NodeHandler.php +35 -0
  255. package/dist/scaffold-repo/sdks/php/src/Node/NodeReflector.php +21 -0
  256. package/dist/scaffold-repo/sdks/php/src/Node/NodeRegistry.php +172 -0
  257. package/dist/scaffold-repo/sdks/php/src/Node/TypedNode.php +159 -0
  258. package/dist/scaffold-repo/sdks/php/src/Server/BlokNodeRuntimeService.php +504 -0
  259. package/dist/scaffold-repo/sdks/php/src/Server/DecodeException.php +13 -0
  260. package/dist/scaffold-repo/sdks/php/src/Server/Middleware.php +18 -0
  261. package/dist/scaffold-repo/sdks/php/src/Server/MiddlewarePipeline.php +33 -0
  262. package/dist/scaffold-repo/sdks/php/src/Server/NodeRuntimeInterface.php +40 -0
  263. package/dist/scaffold-repo/sdks/php/src/Server/Server.php +157 -0
  264. package/dist/scaffold-repo/sdks/php/src/Testing/MockContext.php +161 -0
  265. package/dist/scaffold-repo/sdks/php/src/Testing/TestRunner.php +78 -0
  266. package/dist/scaffold-repo/sdks/php/src/Types/Context.php +80 -0
  267. package/dist/scaffold-repo/sdks/php/src/Types/ExecutionMetrics.php +48 -0
  268. package/dist/scaffold-repo/sdks/php/src/Types/ExecutionRequest.php +38 -0
  269. package/dist/scaffold-repo/sdks/php/src/Types/ExecutionResult.php +143 -0
  270. package/dist/scaffold-repo/sdks/php/src/Types/HealthStatus.php +42 -0
  271. package/dist/scaffold-repo/sdks/php/src/Types/NodeConfig.php +72 -0
  272. package/dist/scaffold-repo/sdks/php/src/Types/Request.php +82 -0
  273. package/dist/scaffold-repo/sdks/php/src/Types/Response.php +44 -0
  274. package/dist/scaffold-repo/sdks/php/src/Validation/SchemaValidator.php +197 -0
  275. package/dist/scaffold-repo/sdks/php/tests/Errors/BlokErrorTest.php +402 -0
  276. package/dist/scaffold-repo/sdks/php/tests/Logging/LoggerTest.php +165 -0
  277. package/dist/scaffold-repo/sdks/php/tests/Node/NodeRegistryTest.php +139 -0
  278. package/dist/scaffold-repo/sdks/php/tests/Node/TypedNodeTest.php +84 -0
  279. package/dist/scaffold-repo/sdks/php/tests/Server/BlokNodeRuntimeServiceTest.php +288 -0
  280. package/dist/scaffold-repo/sdks/php/tests/Testing/MockContextTest.php +184 -0
  281. package/dist/scaffold-repo/sdks/php/tests/Types/ExecutionResultTest.php +136 -0
  282. package/dist/scaffold-repo/sdks/php/tests/Validation/SchemaValidatorTest.php +191 -0
  283. package/dist/scaffold-repo/sdks/python3/Dockerfile +62 -0
  284. package/dist/scaffold-repo/sdks/python3/blok/__init__.py +61 -0
  285. package/dist/scaffold-repo/sdks/python3/blok/config/__init__.py +3 -0
  286. package/dist/scaffold-repo/sdks/python3/blok/config/server_config.py +116 -0
  287. package/dist/scaffold-repo/sdks/python3/blok/errors/__init__.py +50 -0
  288. package/dist/scaffold-repo/sdks/python3/blok/errors/blok_error.py +555 -0
  289. package/dist/scaffold-repo/sdks/python3/blok/errors/node_error.py +64 -0
  290. package/dist/scaffold-repo/sdks/python3/blok/logging/__init__.py +3 -0
  291. package/dist/scaffold-repo/sdks/python3/blok/logging/logger.py +82 -0
  292. package/dist/scaffold-repo/sdks/python3/blok/middleware/__init__.py +4 -0
  293. package/dist/scaffold-repo/sdks/python3/blok/middleware/logging_middleware.py +35 -0
  294. package/dist/scaffold-repo/sdks/python3/blok/middleware/recovery_middleware.py +36 -0
  295. package/dist/scaffold-repo/sdks/python3/blok/node/__init__.py +4 -0
  296. package/dist/scaffold-repo/sdks/python3/blok/node/define_node.py +239 -0
  297. package/dist/scaffold-repo/sdks/python3/blok/node/node_handler.py +35 -0
  298. package/dist/scaffold-repo/sdks/python3/blok/node/node_registry.py +136 -0
  299. package/dist/scaffold-repo/sdks/python3/blok/runtime/__init__.py +0 -0
  300. package/dist/scaffold-repo/sdks/python3/blok/runtime/v1/__init__.py +0 -0
  301. package/dist/scaffold-repo/sdks/python3/blok/runtime/v1/runtime_pb2.py +112 -0
  302. package/dist/scaffold-repo/sdks/python3/blok/runtime/v1/runtime_pb2_grpc.py +259 -0
  303. package/dist/scaffold-repo/sdks/python3/blok/server/__init__.py +3 -0
  304. package/dist/scaffold-repo/sdks/python3/blok/server/grpc_server.py +757 -0
  305. package/dist/scaffold-repo/sdks/python3/blok/server/runtime_server.py +165 -0
  306. package/dist/scaffold-repo/sdks/python3/blok/types/__init__.py +13 -0
  307. package/dist/scaffold-repo/sdks/python3/blok/types/context.py +162 -0
  308. package/dist/scaffold-repo/sdks/python3/blok/types/execution_request.py +74 -0
  309. package/dist/scaffold-repo/sdks/python3/blok/types/execution_result.py +103 -0
  310. package/dist/scaffold-repo/sdks/python3/blok/worker/__init__.py +10 -0
  311. package/dist/scaffold-repo/sdks/python3/blok/worker/job_message.py +34 -0
  312. package/dist/scaffold-repo/sdks/python3/blok/worker/worker.py +451 -0
  313. package/dist/scaffold-repo/sdks/python3/blok/worker/worker_config.py +129 -0
  314. package/dist/scaffold-repo/sdks/python3/examples/__init__.py +32 -0
  315. package/dist/scaffold-repo/sdks/python3/examples/api_call_node.py +85 -0
  316. package/dist/scaffold-repo/sdks/python3/examples/blok_error_demo_node.py +79 -0
  317. package/dist/scaffold-repo/sdks/python3/examples/chain_test_node.py +51 -0
  318. package/dist/scaffold-repo/sdks/python3/examples/hello_world_node.py +44 -0
  319. package/dist/scaffold-repo/sdks/python3/examples/transform_data_node.py +71 -0
  320. package/dist/scaffold-repo/sdks/python3/examples/typed_greet_node.py +25 -0
  321. package/dist/scaffold-repo/sdks/python3/proto/blok/runtime/v1/runtime.proto +302 -0
  322. package/dist/scaffold-repo/sdks/python3/pyproject.toml +47 -0
  323. package/dist/scaffold-repo/sdks/python3/requirements.txt +17 -0
  324. package/dist/scaffold-repo/sdks/python3/tests/__init__.py +0 -0
  325. package/dist/scaffold-repo/sdks/python3/tests/test_blok_error.py +341 -0
  326. package/dist/scaffold-repo/sdks/python3/tests/test_define_node.py +135 -0
  327. package/dist/scaffold-repo/sdks/python3/tests/test_discovery.py +99 -0
  328. package/dist/scaffold-repo/sdks/python3/tests/test_grpc_codec.py +260 -0
  329. package/dist/scaffold-repo/sdks/python3/tests/test_grpc_server.py +398 -0
  330. package/dist/scaffold-repo/sdks/ruby/Dockerfile +37 -0
  331. package/dist/scaffold-repo/sdks/ruby/Gemfile +5 -0
  332. package/dist/scaffold-repo/sdks/ruby/README.md +210 -0
  333. package/dist/scaffold-repo/sdks/ruby/Rakefile +11 -0
  334. package/dist/scaffold-repo/sdks/ruby/blok.gemspec +43 -0
  335. package/dist/scaffold-repo/sdks/ruby/config.ru +15 -0
  336. package/dist/scaffold-repo/sdks/ruby/examples/api_call_node.rb +99 -0
  337. package/dist/scaffold-repo/sdks/ruby/examples/blok_error_demo_node.rb +79 -0
  338. package/dist/scaffold-repo/sdks/ruby/examples/chain_test_node.rb +51 -0
  339. package/dist/scaffold-repo/sdks/ruby/examples/hello_world_node.rb +40 -0
  340. package/dist/scaffold-repo/sdks/ruby/examples/transform_data_node.rb +82 -0
  341. package/dist/scaffold-repo/sdks/ruby/examples/typed_greet_node.rb +25 -0
  342. package/dist/scaffold-repo/sdks/ruby/lib/blok/config/server_config.rb +76 -0
  343. package/dist/scaffold-repo/sdks/ruby/lib/blok/errors/blok_error.rb +476 -0
  344. package/dist/scaffold-repo/sdks/ruby/lib/blok/errors/build_context_snapshot.rb +99 -0
  345. package/dist/scaffold-repo/sdks/ruby/lib/blok/errors/error_category.rb +16 -0
  346. package/dist/scaffold-repo/sdks/ruby/lib/blok/errors/node_error.rb +84 -0
  347. package/dist/scaffold-repo/sdks/ruby/lib/blok/logging/log_entry.rb +46 -0
  348. package/dist/scaffold-repo/sdks/ruby/lib/blok/logging/log_level.rb +49 -0
  349. package/dist/scaffold-repo/sdks/ruby/lib/blok/logging/logger.rb +71 -0
  350. package/dist/scaffold-repo/sdks/ruby/lib/blok/middleware/logging_middleware.rb +45 -0
  351. package/dist/scaffold-repo/sdks/ruby/lib/blok/middleware/middleware.rb +36 -0
  352. package/dist/scaffold-repo/sdks/ruby/lib/blok/middleware/recovery_middleware.rb +31 -0
  353. package/dist/scaffold-repo/sdks/ruby/lib/blok/node/discovery.rb +59 -0
  354. package/dist/scaffold-repo/sdks/ruby/lib/blok/node/node_handler.rb +43 -0
  355. package/dist/scaffold-repo/sdks/ruby/lib/blok/node/node_registry.rb +107 -0
  356. package/dist/scaffold-repo/sdks/ruby/lib/blok/node/typed_node.rb +180 -0
  357. package/dist/scaffold-repo/sdks/ruby/lib/blok/runtime/v1/runtime_pb.rb +43 -0
  358. package/dist/scaffold-repo/sdks/ruby/lib/blok/runtime/v1/runtime_services_pb.rb +55 -0
  359. package/dist/scaffold-repo/sdks/ruby/lib/blok/server/grpc_server.rb +435 -0
  360. package/dist/scaffold-repo/sdks/ruby/lib/blok/server/runtime_app.rb +86 -0
  361. package/dist/scaffold-repo/sdks/ruby/lib/blok/testing/mock_context.rb +109 -0
  362. package/dist/scaffold-repo/sdks/ruby/lib/blok/testing/test_runner.rb +40 -0
  363. package/dist/scaffold-repo/sdks/ruby/lib/blok/types/context.rb +82 -0
  364. package/dist/scaffold-repo/sdks/ruby/lib/blok/types/execution_metrics.rb +43 -0
  365. package/dist/scaffold-repo/sdks/ruby/lib/blok/types/execution_request.rb +39 -0
  366. package/dist/scaffold-repo/sdks/ruby/lib/blok/types/execution_result.rb +117 -0
  367. package/dist/scaffold-repo/sdks/ruby/lib/blok/types/health_status.rb +42 -0
  368. package/dist/scaffold-repo/sdks/ruby/lib/blok/types/node_config.rb +73 -0
  369. package/dist/scaffold-repo/sdks/ruby/lib/blok/types/request.rb +71 -0
  370. package/dist/scaffold-repo/sdks/ruby/lib/blok/types/response.rb +46 -0
  371. package/dist/scaffold-repo/sdks/ruby/lib/blok/validation/schema_validator.rb +142 -0
  372. package/dist/scaffold-repo/sdks/ruby/lib/blok/version.rb +5 -0
  373. package/dist/scaffold-repo/sdks/ruby/lib/blok.rb +53 -0
  374. package/dist/scaffold-repo/sdks/ruby/proto/blok/runtime/v1/runtime.proto +302 -0
  375. package/dist/scaffold-repo/sdks/ruby/test/errors/blok_error_test.rb +339 -0
  376. package/dist/scaffold-repo/sdks/ruby/test/logging/logger_test.rb +155 -0
  377. package/dist/scaffold-repo/sdks/ruby/test/node/node_registry_test.rb +132 -0
  378. package/dist/scaffold-repo/sdks/ruby/test/node/typed_node_test.rb +67 -0
  379. package/dist/scaffold-repo/sdks/ruby/test/test_helper.rb +6 -0
  380. package/dist/scaffold-repo/sdks/ruby/test/testing/mock_context_test.rb +150 -0
  381. package/dist/scaffold-repo/sdks/ruby/test/types/execution_result_test.rb +129 -0
  382. package/dist/scaffold-repo/sdks/ruby/test/validation/schema_validator_test.rb +270 -0
  383. package/dist/scaffold-repo/sdks/rust/Cargo.lock +3044 -0
  384. package/dist/scaffold-repo/sdks/rust/Cargo.toml +82 -0
  385. package/dist/scaffold-repo/sdks/rust/Dockerfile +40 -0
  386. package/dist/scaffold-repo/sdks/rust/README.md +73 -0
  387. package/dist/scaffold-repo/sdks/rust/build.rs +32 -0
  388. package/dist/scaffold-repo/sdks/rust/proto/blok/runtime/v1/runtime.proto +302 -0
  389. package/dist/scaffold-repo/sdks/rust/src/blok_error.rs +1168 -0
  390. package/dist/scaffold-repo/sdks/rust/src/config.rs +158 -0
  391. package/dist/scaffold-repo/sdks/rust/src/errors.rs +142 -0
  392. package/dist/scaffold-repo/sdks/rust/src/grpc_server.rs +635 -0
  393. package/dist/scaffold-repo/sdks/rust/src/lib.rs +65 -0
  394. package/dist/scaffold-repo/sdks/rust/src/logging.rs +195 -0
  395. package/dist/scaffold-repo/sdks/rust/src/main.rs +79 -0
  396. package/dist/scaffold-repo/sdks/rust/src/middleware.rs +181 -0
  397. package/dist/scaffold-repo/sdks/rust/src/node.rs +172 -0
  398. package/dist/scaffold-repo/sdks/rust/src/nodes/api_call.rs +93 -0
  399. package/dist/scaffold-repo/sdks/rust/src/nodes/blok_error_demo.rs +151 -0
  400. package/dist/scaffold-repo/sdks/rust/src/nodes/chain_test.rs +57 -0
  401. package/dist/scaffold-repo/sdks/rust/src/nodes/hello_world.rs +83 -0
  402. package/dist/scaffold-repo/sdks/rust/src/nodes/mod.rs +18 -0
  403. package/dist/scaffold-repo/sdks/rust/src/nodes/transform_data.rs +142 -0
  404. package/dist/scaffold-repo/sdks/rust/src/nodes/typed_greet.rs +56 -0
  405. package/dist/scaffold-repo/sdks/rust/src/registry.rs +204 -0
  406. package/dist/scaffold-repo/sdks/rust/src/server.rs +63 -0
  407. package/dist/scaffold-repo/sdks/rust/src/testing.rs +175 -0
  408. package/dist/scaffold-repo/sdks/rust/src/types.rs +338 -0
  409. package/dist/scaffold-repo/sdks/rust/src/user_nodes/mod.rs +10 -0
  410. package/dist/scaffold-repo/sdks/rust/src/validation.rs +232 -0
  411. package/dist/scaffold-repo/sdks/rust/src/worker.rs +509 -0
  412. package/dist/scaffold-repo/sdks/rust/tests/grpc_integration.rs +306 -0
  413. package/dist/scaffold-repo/sdks/rust/tests/typed_node.rs +104 -0
  414. package/dist/scaffold-repo/triggers/cron/CHANGELOG.md +22 -0
  415. package/dist/scaffold-repo/triggers/cron/package.json +36 -0
  416. package/dist/scaffold-repo/triggers/cron/src/CronTrigger.ts +552 -0
  417. package/dist/scaffold-repo/triggers/cron/src/index.ts +77 -0
  418. package/dist/scaffold-repo/triggers/cron/tsconfig.json +32 -0
  419. package/dist/scaffold-repo/triggers/grpc/.env.example +8 -0
  420. package/dist/scaffold-repo/triggers/grpc/CHANGELOG.md +143 -0
  421. package/dist/scaffold-repo/triggers/grpc/README.md +25 -0
  422. package/dist/scaffold-repo/triggers/grpc/buf.gen.yaml +11 -0
  423. package/dist/scaffold-repo/triggers/grpc/buf.yaml +9 -0
  424. package/dist/scaffold-repo/triggers/grpc/localhost+2-key.pem +28 -0
  425. package/dist/scaffold-repo/triggers/grpc/localhost+2.pem +27 -0
  426. package/dist/scaffold-repo/triggers/grpc/package.json +61 -0
  427. package/dist/scaffold-repo/triggers/grpc/proto/workflow.proto +33 -0
  428. package/dist/scaffold-repo/triggers/grpc/src/GRpcTrigger.ts +297 -0
  429. package/dist/scaffold-repo/triggers/grpc/src/GrpcClient.ts +87 -0
  430. package/dist/scaffold-repo/triggers/grpc/src/GrpcServer.ts +68 -0
  431. package/dist/scaffold-repo/triggers/grpc/src/MessageDecode.ts +142 -0
  432. package/dist/scaffold-repo/triggers/grpc/src/NanoSDK.ts +146 -0
  433. package/dist/scaffold-repo/triggers/grpc/src/Nodes.ts +10 -0
  434. package/dist/scaffold-repo/triggers/grpc/src/Workflows.ts +5 -0
  435. package/dist/scaffold-repo/triggers/grpc/src/gen/workflow_pb.ts +142 -0
  436. package/dist/scaffold-repo/triggers/grpc/src/index.ts +22 -0
  437. package/dist/scaffold-repo/triggers/grpc/src/server.ts +8 -0
  438. package/dist/scaffold-repo/triggers/grpc/src/types/Message.ts +0 -0
  439. package/dist/scaffold-repo/triggers/grpc/src/types/RuntimeWorkflow.ts +7 -0
  440. package/dist/scaffold-repo/triggers/grpc/src/types/Workflows.ts +7 -0
  441. package/dist/scaffold-repo/triggers/grpc/tsconfig.json +34 -0
  442. package/dist/scaffold-repo/triggers/grpc/vitest.config.ts +29 -0
  443. package/dist/scaffold-repo/triggers/grpc/workflows/countries.json +27 -0
  444. package/dist/scaffold-repo/triggers/http/.blok/trace.db +0 -0
  445. package/dist/scaffold-repo/triggers/http/.blok/trace.db-shm +0 -0
  446. package/dist/scaffold-repo/triggers/http/.blok/trace.db-wal +0 -0
  447. package/dist/scaffold-repo/triggers/http/.dockerignore +23 -0
  448. package/dist/scaffold-repo/triggers/http/.env.example +8 -0
  449. package/dist/scaffold-repo/triggers/http/CHANGELOG.md +326 -0
  450. package/dist/scaffold-repo/triggers/http/Dockerfile +49 -0
  451. package/dist/scaffold-repo/triggers/http/Dockerfile.dev +34 -0
  452. package/dist/scaffold-repo/triggers/http/infra/docker-compose.yml +38 -0
  453. package/dist/scaffold-repo/triggers/http/notes/CLI_Commands/Authentication.md +74 -0
  454. package/dist/scaffold-repo/triggers/http/notes/CLI_Commands/Building.md +52 -0
  455. package/dist/scaffold-repo/triggers/http/notes/CLI_Commands/Create_Node.md +123 -0
  456. package/dist/scaffold-repo/triggers/http/notes/CLI_Commands/Create_Workflow.md +177 -0
  457. package/dist/scaffold-repo/triggers/http/notes/CLI_Commands/Deployment.md +69 -0
  458. package/dist/scaffold-repo/triggers/http/notes/Core_Concepts/Context.md +156 -0
  459. package/dist/scaffold-repo/triggers/http/notes/examples.md +104 -0
  460. package/dist/scaffold-repo/triggers/http/notes/index.md +51 -0
  461. package/dist/scaffold-repo/triggers/http/package.json +62 -0
  462. package/dist/scaffold-repo/triggers/http/public/favicon.ico +0 -0
  463. package/dist/scaffold-repo/triggers/http/public/metric/index.html +2101 -0
  464. package/dist/scaffold-repo/triggers/http/request.http +7 -0
  465. package/dist/scaffold-repo/triggers/http/src/AppRoutes.ts +64 -0
  466. package/dist/scaffold-repo/triggers/http/src/Nodes.ts +38 -0
  467. package/dist/scaffold-repo/triggers/http/src/Workflows.ts +18 -0
  468. package/dist/scaffold-repo/triggers/http/src/index.ts +86 -0
  469. package/dist/scaffold-repo/triggers/http/src/nodes/chain-init/index.ts +48 -0
  470. package/dist/scaffold-repo/triggers/http/src/nodes/chain-verify/index.ts +123 -0
  471. package/dist/scaffold-repo/triggers/http/src/nodes/eval/index.ts +69 -0
  472. package/dist/scaffold-repo/triggers/http/src/nodes/examples/README.md +14 -0
  473. package/dist/scaffold-repo/triggers/http/src/nodes/examples/chat-ui/index.html +228 -0
  474. package/dist/scaffold-repo/triggers/http/src/nodes/examples/chat-ui/index.ts +65 -0
  475. package/dist/scaffold-repo/triggers/http/src/nodes/examples/index.ts +14 -0
  476. package/dist/scaffold-repo/triggers/http/src/nodes/runtime-bridge/index.ts +84 -0
  477. package/dist/scaffold-repo/triggers/http/src/runner/HonoTraceRouterAdapter.ts +199 -0
  478. package/dist/scaffold-repo/triggers/http/src/runner/HttpTrigger.ts +2039 -0
  479. package/dist/scaffold-repo/triggers/http/src/runner/MessageDecode.ts +57 -0
  480. package/dist/scaffold-repo/triggers/http/src/runner/Util.ts +52 -0
  481. package/dist/scaffold-repo/triggers/http/src/runner/WorkflowRouter.ts +411 -0
  482. package/dist/scaffold-repo/triggers/http/src/runner/metrics/opentelemetry_metrics.ts +84 -0
  483. package/dist/scaffold-repo/triggers/http/src/runner/metrics/opentelemetry_traces.ts +30 -0
  484. package/dist/scaffold-repo/triggers/http/src/runner/nodeCatalog.ts +128 -0
  485. package/dist/scaffold-repo/triggers/http/src/runner/responseEmitter.ts +138 -0
  486. package/dist/scaffold-repo/triggers/http/src/runner/scanWorkflows.ts +201 -0
  487. package/dist/scaffold-repo/triggers/http/src/runner/types/ErrorResponse.ts +3 -0
  488. package/dist/scaffold-repo/triggers/http/src/runner/types/NodeTypes.ts +13 -0
  489. package/dist/scaffold-repo/triggers/http/src/runner/types/Nodes.ts +5 -0
  490. package/dist/scaffold-repo/triggers/http/src/runner/types/RuntimeWorkflow.ts +7 -0
  491. package/dist/scaffold-repo/triggers/http/src/runner/types/WorkflowRequest.ts +8 -0
  492. package/dist/scaffold-repo/triggers/http/src/runner/types/WorkflowResponse.ts +7 -0
  493. package/dist/scaffold-repo/triggers/http/src/runner/types/Workflows.ts +14 -0
  494. package/dist/scaffold-repo/triggers/http/src/workflows/countries-cats-helper.ts +30 -0
  495. package/dist/scaffold-repo/triggers/http/src/workflows/countries-handle-dsl.ts +25 -0
  496. package/dist/scaffold-repo/triggers/http/src/workflows/countries-helper.ts +18 -0
  497. package/dist/scaffold-repo/triggers/http/src/workflows/empty.ts +16 -0
  498. package/dist/scaffold-repo/triggers/http/src/workflows/eval/eval-retrieve.ts +23 -0
  499. package/dist/scaffold-repo/triggers/http/src/workflows/eval/eval-run.ts +39 -0
  500. package/dist/scaffold-repo/triggers/http/src/workflows/eval/foreign-auth.ts +24 -0
  501. package/dist/scaffold-repo/triggers/http/tsconfig.json +39 -0
  502. package/dist/scaffold-repo/triggers/http/vitest.config.ts +39 -0
  503. package/dist/scaffold-repo/triggers/http/workflows/json/agent-message.json +87 -0
  504. package/dist/scaffold-repo/triggers/http/workflows/json/agent-page.json +25 -0
  505. package/dist/scaffold-repo/triggers/http/workflows/json/agent-stream.json +30 -0
  506. package/dist/scaffold-repo/triggers/http/workflows/json/agent-tool-calculator.json +22 -0
  507. package/dist/scaffold-repo/triggers/http/workflows/json/agent-tool-weather.json +22 -0
  508. package/dist/scaffold-repo/triggers/http/workflows/json/chat-memory-message.json +54 -0
  509. package/dist/scaffold-repo/triggers/http/workflows/json/chat-memory-page.json +25 -0
  510. package/dist/scaffold-repo/triggers/http/workflows/json/chat-memory-stream.json +30 -0
  511. package/dist/scaffold-repo/triggers/http/workflows/json/chat-message.json +25 -0
  512. package/dist/scaffold-repo/triggers/http/workflows/json/chat-page.json +20 -0
  513. package/dist/scaffold-repo/triggers/http/workflows/json/chat-stream.json +30 -0
  514. package/dist/scaffold-repo/triggers/http/workflows/json/countries-py.json +27 -0
  515. package/dist/scaffold-repo/triggers/http/workflows/json/countries-vs-facts.json +50 -0
  516. package/dist/scaffold-repo/triggers/http/workflows/json/countries.json +27 -0
  517. package/dist/scaffold-repo/triggers/http/workflows/json/cross-runtime-chain.json +89 -0
  518. package/dist/scaffold-repo/triggers/http/workflows/json/dashboard-gen.json +34 -0
  519. package/dist/scaffold-repo/triggers/http/workflows/json/db-manager.json +34 -0
  520. package/dist/scaffold-repo/triggers/http/workflows/json/empty.json +13 -0
  521. package/dist/scaffold-repo/triggers/http/workflows/json/fanout-enqueue.json +48 -0
  522. package/dist/scaffold-repo/triggers/http/workflows/json/fanout-worker.json +41 -0
  523. package/dist/scaffold-repo/triggers/http/workflows/json/feedback.json +34 -0
  524. package/dist/scaffold-repo/triggers/http/workflows/json/films.json +27 -0
  525. package/dist/scaffold-repo/triggers/http/workflows/json/image-capture.json +34 -0
  526. package/dist/scaffold-repo/triggers/http/workflows/json/launches-by-year.json +27 -0
  527. package/dist/scaffold-repo/triggers/http/workflows/json/loadtest.json +24 -0
  528. package/dist/scaffold-repo/triggers/http/workflows/json/middleware/admin-only.json +31 -0
  529. package/dist/scaffold-repo/triggers/http/workflows/json/middleware/auth-check.json +59 -0
  530. package/dist/scaffold-repo/triggers/http/workflows/json/middleware/github-webhook-verify.json +34 -0
  531. package/dist/scaffold-repo/triggers/http/workflows/json/middleware/jwt-auth.json +46 -0
  532. package/dist/scaffold-repo/triggers/http/workflows/json/middleware/rate-limit.json +70 -0
  533. package/dist/scaffold-repo/triggers/http/workflows/json/middleware/redis-rate-limit.json +71 -0
  534. package/dist/scaffold-repo/triggers/http/workflows/json/mongodb.json +24 -0
  535. package/dist/scaffold-repo/triggers/http/workflows/json/rentals-pdf.json +65 -0
  536. package/dist/scaffold-repo/triggers/http/workflows/json/v05-admin-delete-user.json +42 -0
  537. package/dist/scaffold-repo/triggers/http/workflows/json/v05-async-job-poller.json +45 -0
  538. package/dist/scaffold-repo/triggers/http/workflows/json/v05-csv-import.json +122 -0
  539. package/dist/scaffold-repo/triggers/http/workflows/json/v05-data-export.json +105 -0
  540. package/dist/scaffold-repo/triggers/http/workflows/json/v05-event-router.json +97 -0
  541. package/dist/scaffold-repo/triggers/http/workflows/json/v05-github-handler-issues.json +22 -0
  542. package/dist/scaffold-repo/triggers/http/workflows/json/v05-github-handler-pr.json +22 -0
  543. package/dist/scaffold-repo/triggers/http/workflows/json/v05-github-handler-push.json +22 -0
  544. package/dist/scaffold-repo/triggers/http/workflows/json/v05-github-webhook-router.json +88 -0
  545. package/dist/scaffold-repo/triggers/http/workflows/json/v05-hello-global-mw.json +22 -0
  546. package/dist/scaffold-repo/triggers/http/workflows/json/v05-hello-with-mw.json +23 -0
  547. package/dist/scaffold-repo/triggers/http/workflows/json/v05-jwt-protected.json +23 -0
  548. package/dist/scaffold-repo/triggers/http/workflows/json/v05-multi-tenant-router.json +90 -0
  549. package/dist/scaffold-repo/triggers/http/workflows/json/v05-nested-control-flow.json +207 -0
  550. package/dist/scaffold-repo/triggers/http/workflows/json/v05-order-fulfillment.json +211 -0
  551. package/dist/scaffold-repo/triggers/http/workflows/json/v05-parallel-foreach-with-wait.json +47 -0
  552. package/dist/scaffold-repo/triggers/http/workflows/json/v05-polling-with-backoff.json +55 -0
  553. package/dist/scaffold-repo/triggers/http/workflows/json/v05-protected.json +23 -0
  554. package/dist/scaffold-repo/triggers/http/workflows/json/v05-redis-protected.json +23 -0
  555. package/dist/scaffold-repo/triggers/http/workflows/json/v05-saga.json +122 -0
  556. package/dist/scaffold-repo/triggers/http/workflows/json/v05-tenant-acme.json +22 -0
  557. package/dist/scaffold-repo/triggers/http/workflows/json/v05-tenant-beta.json +22 -0
  558. package/dist/scaffold-repo/triggers/http/workflows/json/v05-tenant-gamma.json +22 -0
  559. package/dist/scaffold-repo/triggers/http/workflows/json/v05-travel-booking.json +200 -0
  560. package/dist/scaffold-repo/triggers/http/workflows/json/v05-user-signup-saga.json +186 -0
  561. package/dist/scaffold-repo/triggers/http/workflows/json/v05-webhook-fanout.json +49 -0
  562. package/dist/scaffold-repo/triggers/http/workflows/json/v06-reliability-showcase.json +80 -0
  563. package/dist/scaffold-repo/triggers/http/workflows/json/v07-sse-publish.json +24 -0
  564. package/dist/scaffold-repo/triggers/http/workflows/json/v07-sse-stream.json +26 -0
  565. package/dist/scaffold-repo/triggers/http/workflows/json/v07-ws-echo.json +38 -0
  566. package/dist/scaffold-repo/triggers/http/workflows/json/webhook-github-issues.json +22 -0
  567. package/dist/scaffold-repo/triggers/http/workflows/json/webhook-github-pr.json +22 -0
  568. package/dist/scaffold-repo/triggers/http/workflows/json/webhook-github-push.json +32 -0
  569. package/dist/scaffold-repo/triggers/http/workflows/json/webhook-github.json +87 -0
  570. package/dist/scaffold-repo/triggers/http/workflows/json/webhook-linear-comment.json +22 -0
  571. package/dist/scaffold-repo/triggers/http/workflows/json/webhook-linear-issue.json +22 -0
  572. package/dist/scaffold-repo/triggers/http/workflows/json/webhook-linear.json +74 -0
  573. package/dist/scaffold-repo/triggers/http/workflows/json/webhook-stripe-customer-created.json +22 -0
  574. package/dist/scaffold-repo/triggers/http/workflows/json/webhook-stripe-invoice-paid.json +32 -0
  575. package/dist/scaffold-repo/triggers/http/workflows/json/webhook-stripe.json +24 -0
  576. package/dist/scaffold-repo/triggers/http/workflows/json/workflow-docs.json +34 -0
  577. package/dist/scaffold-repo/triggers/http/workflows/toml/countries.toml +21 -0
  578. package/dist/scaffold-repo/triggers/http/workflows/xml/countries.xml +23 -0
  579. package/dist/scaffold-repo/triggers/http/workflows/yaml/countries.yaml +19 -0
  580. package/dist/scaffold-repo/triggers/mcp/README.md +131 -0
  581. package/dist/scaffold-repo/triggers/mcp/package.json +39 -0
  582. package/dist/scaffold-repo/triggers/mcp/src/McpTrigger.ts +581 -0
  583. package/dist/scaffold-repo/triggers/mcp/src/index.ts +41 -0
  584. package/dist/scaffold-repo/triggers/mcp/tsconfig.json +32 -0
  585. package/dist/scaffold-repo/triggers/pubsub/CHANGELOG.md +22 -0
  586. package/dist/scaffold-repo/triggers/pubsub/package.json +66 -0
  587. package/dist/scaffold-repo/triggers/pubsub/src/PubSubTrigger.ts +424 -0
  588. package/dist/scaffold-repo/triggers/pubsub/src/adapters/AWSSNSAdapter.ts +352 -0
  589. package/dist/scaffold-repo/triggers/pubsub/src/adapters/AzureServiceBusAdapter.ts +303 -0
  590. package/dist/scaffold-repo/triggers/pubsub/src/adapters/GCPPubSubAdapter.ts +327 -0
  591. package/dist/scaffold-repo/triggers/pubsub/src/adapters/KafkaPubSubAdapter.ts +247 -0
  592. package/dist/scaffold-repo/triggers/pubsub/src/adapters/KafkaPubSubAdapter.ts.bak +251 -0
  593. package/dist/scaffold-repo/triggers/pubsub/src/adapters/NATSPubSubAdapter.ts +333 -0
  594. package/dist/scaffold-repo/triggers/pubsub/src/adapters/RedisStreamsPubSubAdapter.ts +256 -0
  595. package/dist/scaffold-repo/triggers/pubsub/src/adapters/factory.ts +88 -0
  596. package/dist/scaffold-repo/triggers/pubsub/src/index.ts +67 -0
  597. package/dist/scaffold-repo/triggers/pubsub/template/.env.example +8 -0
  598. package/dist/scaffold-repo/triggers/pubsub/template/package.json +45 -0
  599. package/dist/scaffold-repo/triggers/pubsub/template/src/Nodes.ts +20 -0
  600. package/dist/scaffold-repo/triggers/pubsub/template/src/Workflows.ts +8 -0
  601. package/dist/scaffold-repo/triggers/pubsub/template/src/index.ts +41 -0
  602. package/dist/scaffold-repo/triggers/pubsub/template/src/runner/PubSubServer.ts +39 -0
  603. package/dist/scaffold-repo/triggers/pubsub/template/src/runner/types/Workflows.ts +7 -0
  604. package/dist/scaffold-repo/triggers/pubsub/template/src/workflows/messages/on-message.ts +42 -0
  605. package/dist/scaffold-repo/triggers/pubsub/template/src/workflows/publish-order.ts +22 -0
  606. package/dist/scaffold-repo/triggers/pubsub/template/tsconfig.json +31 -0
  607. package/dist/scaffold-repo/triggers/pubsub/template/vitest.config.ts +39 -0
  608. package/dist/scaffold-repo/triggers/pubsub/tsconfig.json +32 -0
  609. package/dist/scaffold-repo/triggers/sse/.env.example +8 -0
  610. package/dist/scaffold-repo/triggers/sse/CHANGELOG.md +12 -0
  611. package/dist/scaffold-repo/triggers/sse/Dockerfile +47 -0
  612. package/dist/scaffold-repo/triggers/sse/Dockerfile.dev +33 -0
  613. package/dist/scaffold-repo/triggers/sse/package.json +37 -0
  614. package/dist/scaffold-repo/triggers/sse/src/SSETrigger.ts +489 -0
  615. package/dist/scaffold-repo/triggers/sse/src/bus.ts +208 -0
  616. package/dist/scaffold-repo/triggers/sse/src/index.ts +38 -0
  617. package/dist/scaffold-repo/triggers/sse/src/workflows/events/README.md +129 -0
  618. package/dist/scaffold-repo/triggers/sse/src/workflows/events/publish-demo.ts +40 -0
  619. package/dist/scaffold-repo/triggers/sse/src/workflows/events/stream-demo.ts +43 -0
  620. package/dist/scaffold-repo/triggers/sse/tsconfig.json +22 -0
  621. package/dist/scaffold-repo/triggers/sse/vitest.config.ts +39 -0
  622. package/dist/scaffold-repo/triggers/webhook/CHANGELOG.md +22 -0
  623. package/dist/scaffold-repo/triggers/webhook/package.json +36 -0
  624. package/dist/scaffold-repo/triggers/webhook/src/WebhookTrigger.ts +465 -0
  625. package/dist/scaffold-repo/triggers/webhook/src/index.ts +51 -0
  626. package/dist/scaffold-repo/triggers/webhook/src/verifiers.ts +394 -0
  627. package/dist/scaffold-repo/triggers/webhook/tsconfig.json +32 -0
  628. package/dist/scaffold-repo/triggers/websocket/.env.example +8 -0
  629. package/dist/scaffold-repo/triggers/websocket/CHANGELOG.md +22 -0
  630. package/dist/scaffold-repo/triggers/websocket/package.json +50 -0
  631. package/dist/scaffold-repo/triggers/websocket/src/Backplane.ts +167 -0
  632. package/dist/scaffold-repo/triggers/websocket/src/WebSocketTrigger.ts +910 -0
  633. package/dist/scaffold-repo/triggers/websocket/src/index.ts +50 -0
  634. package/dist/scaffold-repo/triggers/websocket/src/workflows/events/README.md +93 -0
  635. package/dist/scaffold-repo/triggers/websocket/src/workflows/events/echo-demo.ts +56 -0
  636. package/dist/scaffold-repo/triggers/websocket/tsconfig.json +22 -0
  637. package/dist/scaffold-repo/triggers/websocket/vitest.config.ts +39 -0
  638. package/dist/scaffold-repo/triggers/worker/CHANGELOG.md +22 -0
  639. package/dist/scaffold-repo/triggers/worker/package.json +68 -0
  640. package/dist/scaffold-repo/triggers/worker/src/WorkerTrigger.ts +943 -0
  641. package/dist/scaffold-repo/triggers/worker/src/adapters/BullMQAdapter.ts +296 -0
  642. package/dist/scaffold-repo/triggers/worker/src/adapters/InMemoryAdapter.ts +280 -0
  643. package/dist/scaffold-repo/triggers/worker/src/adapters/KafkaAdapter.ts +347 -0
  644. package/dist/scaffold-repo/triggers/worker/src/adapters/NATSAdapter.ts +505 -0
  645. package/dist/scaffold-repo/triggers/worker/src/adapters/PgBossAdapter.ts +319 -0
  646. package/dist/scaffold-repo/triggers/worker/src/adapters/RabbitMQAdapter.ts +318 -0
  647. package/dist/scaffold-repo/triggers/worker/src/adapters/RedisStreamsAdapter.ts +513 -0
  648. package/dist/scaffold-repo/triggers/worker/src/adapters/SQSAdapter.ts +314 -0
  649. package/dist/scaffold-repo/triggers/worker/src/adapters/factory.ts +111 -0
  650. package/dist/scaffold-repo/triggers/worker/src/index.ts +95 -0
  651. package/dist/scaffold-repo/triggers/worker/template/.env.example +18 -0
  652. package/dist/scaffold-repo/triggers/worker/template/package.json +46 -0
  653. package/dist/scaffold-repo/triggers/worker/template/src/Nodes.ts +20 -0
  654. package/dist/scaffold-repo/triggers/worker/template/src/Workflows.ts +8 -0
  655. package/dist/scaffold-repo/triggers/worker/template/src/index.ts +41 -0
  656. package/dist/scaffold-repo/triggers/worker/template/src/runner/WorkerServer.ts +34 -0
  657. package/dist/scaffold-repo/triggers/worker/template/src/runner/types/Workflows.ts +7 -0
  658. package/dist/scaffold-repo/triggers/worker/template/src/workflows/jobs/process-job.ts +40 -0
  659. package/dist/scaffold-repo/triggers/worker/template/tsconfig.json +31 -0
  660. package/dist/scaffold-repo/triggers/worker/template/vitest.config.ts +39 -0
  661. package/dist/scaffold-repo/triggers/worker/tsconfig.json +32 -0
  662. package/dist/scaffold-repo/workflows/json/agent-message.json +87 -0
  663. package/dist/scaffold-repo/workflows/json/agent-page.json +25 -0
  664. package/dist/scaffold-repo/workflows/json/agent-stream.json +30 -0
  665. package/dist/scaffold-repo/workflows/json/agent-tool-calculator.json +22 -0
  666. package/dist/scaffold-repo/workflows/json/agent-tool-weather.json +22 -0
  667. package/dist/scaffold-repo/workflows/json/chat-memory-message.json +54 -0
  668. package/dist/scaffold-repo/workflows/json/chat-memory-page.json +25 -0
  669. package/dist/scaffold-repo/workflows/json/chat-memory-stream.json +30 -0
  670. package/dist/scaffold-repo/workflows/json/chat-message.json +25 -0
  671. package/dist/scaffold-repo/workflows/json/chat-page.json +20 -0
  672. package/dist/scaffold-repo/workflows/json/chat-stream.json +30 -0
  673. package/dist/scaffold-repo/workflows/json/countries-vs-facts.json +50 -0
  674. package/dist/scaffold-repo/workflows/json/countries.json +27 -0
  675. package/dist/scaffold-repo/workflows/json/cron-heartbeat.json +15 -0
  676. package/dist/scaffold-repo/workflows/json/fanout-enqueue.json +48 -0
  677. package/dist/scaffold-repo/workflows/json/fanout-worker.json +41 -0
  678. package/dist/scaffold-repo/workflows/json/pubsub-on-order.json +24 -0
  679. package/dist/scaffold-repo/workflows/json/webhook-github-issues.json +22 -0
  680. package/dist/scaffold-repo/workflows/json/webhook-github-pr.json +22 -0
  681. package/dist/scaffold-repo/workflows/json/webhook-github-push.json +32 -0
  682. package/dist/scaffold-repo/workflows/json/webhook-github.json +87 -0
  683. package/dist/scaffold-repo/workflows/json/webhook-linear-comment.json +22 -0
  684. package/dist/scaffold-repo/workflows/json/webhook-linear-issue.json +22 -0
  685. package/dist/scaffold-repo/workflows/json/webhook-linear.json +74 -0
  686. package/dist/scaffold-repo/workflows/json/webhook-stripe-customer-created.json +22 -0
  687. package/dist/scaffold-repo/workflows/json/webhook-stripe-invoice-paid.json +32 -0
  688. package/dist/scaffold-repo/workflows/json/webhook-stripe.json +24 -0
  689. package/dist/services/runtime-detector.d.ts +2 -0
  690. package/dist/services/runtime-detector.js +35 -11
  691. package/dist/services/runtime-setup.d.ts +1 -0
  692. package/dist/services/runtime-setup.js +17 -7
  693. package/package.json +4 -4
@@ -0,0 +1,943 @@
1
+ /**
2
+ * WorkerTrigger - Background job processing for Blok workflows
3
+ *
4
+ * Extends TriggerBase to support long-running background jobs:
5
+ * - Concurrency controls (max N concurrent jobs)
6
+ * - Retry logic with exponential backoff
7
+ * - Job timeouts
8
+ * - Job priority and delay scheduling
9
+ * - Dead letter queue support
10
+ *
11
+ * Pattern:
12
+ * 1. loadNodes() - Load available nodes into NodeMap
13
+ * 2. loadWorkflows() - Load workflows with worker triggers
14
+ * 3. listen() - Connect to job backend and start processing
15
+ * 4. For each job:
16
+ * - Create context with this.createContext()
17
+ * - Populate ctx.request with job data
18
+ * - Execute workflow via this.run(ctx)
19
+ * - Ack on success, retry or DLQ on failure
20
+ */
21
+
22
+ import { type WorkerTriggerOpts, type WorkflowV2Builder, tryParseDuration } from "@blokjs/helper";
23
+ import {
24
+ type BlokService,
25
+ ConcurrencyLimitError,
26
+ ConcurrencyMetrics,
27
+ Configuration,
28
+ DebounceCoordinator,
29
+ DefaultLogger,
30
+ DeferredDispatchSignal,
31
+ type GlobalOptions,
32
+ Janitor,
33
+ NodeMap,
34
+ QueueExpiredError,
35
+ RunCancelledError,
36
+ RunTracker,
37
+ TriggerBase,
38
+ type TriggerResponse,
39
+ WorkflowRegistry,
40
+ bootstrapTracing,
41
+ } from "@blokjs/runner";
42
+ import type { Context, NodeBase, RequestContext } from "@blokjs/shared";
43
+ import { type Span, SpanStatusCode, metrics, trace } from "@opentelemetry/api";
44
+ import { v4 as uuid } from "uuid";
45
+
46
+ /**
47
+ * F4 / F24 — thrown by `executeWithTimeout` when a worker job exceeds its
48
+ * trigger-level `config.timeout`. A dedicated type (instead of a plain
49
+ * `Error`) lets `handleJob`'s catch discriminate the timeout: it aborts the
50
+ * detached run via `ctx.signal` and flips the run record to `timedOut`
51
+ * (matching the per-step `maxDuration` taxonomy) rather than routing the
52
+ * timeout through the generic retry/DLQ path.
53
+ */
54
+ export class WorkerTimeoutError extends Error {
55
+ public readonly timeoutMs: number;
56
+ /** Run id of the aborted run, when known — used to flip status to `timedOut`. */
57
+ public readonly runId?: string;
58
+
59
+ constructor(timeoutMs: number, runId?: string) {
60
+ super(`Job timed out after ${timeoutMs}ms`);
61
+ this.name = "WorkerTimeoutError";
62
+ this.timeoutMs = timeoutMs;
63
+ this.runId = runId;
64
+ Object.setPrototypeOf(this, WorkerTimeoutError.prototype);
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Job received from worker queue
70
+ */
71
+ export interface WorkerJob {
72
+ /** Unique job ID */
73
+ id: string;
74
+ /** Job data payload */
75
+ data: unknown;
76
+ /** Job metadata headers */
77
+ headers: Record<string, string>;
78
+ /** Queue name this job belongs to */
79
+ queue: string;
80
+ /** Job priority (higher = more important) */
81
+ priority: number;
82
+ /** Number of attempts made so far */
83
+ attempts: number;
84
+ /** Maximum retry attempts */
85
+ maxRetries: number;
86
+ /** Timestamp when job was created */
87
+ createdAt: Date;
88
+ /** Delay before processing (ms) */
89
+ delay?: number;
90
+ /** Job timeout (ms) */
91
+ timeout?: number;
92
+ /** Original raw job from provider */
93
+ raw: unknown;
94
+ /** Mark job as completed */
95
+ complete: () => Promise<void>;
96
+ /** Mark job as failed (optionally requeue) */
97
+ fail: (error: Error, requeue?: boolean) => Promise<void>;
98
+ }
99
+
100
+ /**
101
+ * Worker adapter interface - implemented by each job backend
102
+ */
103
+ export interface WorkerAdapter {
104
+ /** Provider name (e.g., "bullmq", "in-memory") */
105
+ readonly provider: string;
106
+
107
+ /** Connect to the job backend */
108
+ connect(): Promise<void>;
109
+
110
+ /** Disconnect from the job backend */
111
+ disconnect(): Promise<void>;
112
+
113
+ /**
114
+ * Start processing jobs from a queue
115
+ * @param config Worker trigger configuration
116
+ * @param handler Callback for each job
117
+ */
118
+ process(config: WorkerTriggerOpts, handler: (job: WorkerJob) => Promise<void>): Promise<void>;
119
+
120
+ /**
121
+ * Add a job to a queue (for programmatic dispatching)
122
+ * @param queue Queue name
123
+ * @param data Job payload
124
+ * @param opts Job options
125
+ */
126
+ addJob(
127
+ queue: string,
128
+ data: unknown,
129
+ opts?: {
130
+ priority?: number;
131
+ delay?: number;
132
+ retries?: number;
133
+ timeout?: number;
134
+ jobId?: string;
135
+ },
136
+ ): Promise<string>;
137
+
138
+ /** Stop processing a specific queue */
139
+ stopProcessing(queue: string): Promise<void>;
140
+
141
+ /** Check if connected */
142
+ isConnected(): boolean;
143
+
144
+ /** Health check */
145
+ healthCheck(): Promise<boolean>;
146
+
147
+ /** Get queue stats */
148
+ getQueueStats(queue: string): Promise<WorkerQueueStats>;
149
+ }
150
+
151
+ /**
152
+ * Queue statistics
153
+ */
154
+ export interface WorkerQueueStats {
155
+ /** Number of jobs waiting to be processed */
156
+ waiting: number;
157
+ /** Number of jobs currently being processed */
158
+ active: number;
159
+ /** Number of completed jobs */
160
+ completed: number;
161
+ /** Number of failed jobs */
162
+ failed: number;
163
+ /** Number of delayed jobs */
164
+ delayed: number;
165
+ }
166
+
167
+ /**
168
+ * Workflow model with worker trigger configuration
169
+ */
170
+ interface WorkerWorkflowModel {
171
+ path: string;
172
+ config: {
173
+ name: string;
174
+ version: string;
175
+ trigger?: {
176
+ worker?: WorkerTriggerOpts;
177
+ [key: string]: unknown;
178
+ };
179
+ [key: string]: unknown;
180
+ };
181
+ }
182
+
183
+ /**
184
+ * WorkerTrigger - Abstract base class for worker-based triggers
185
+ *
186
+ * Provides background job processing with:
187
+ * - Configurable concurrency per queue
188
+ * - Automatic retries with exponential backoff
189
+ * - Job timeouts with automatic failure
190
+ * - Priority-based job ordering
191
+ * - Delayed job scheduling
192
+ * - Queue statistics and monitoring
193
+ */
194
+ export abstract class WorkerTrigger extends TriggerBase {
195
+ protected nodeMap: GlobalOptions = {} as GlobalOptions;
196
+ protected readonly tracer = trace.getTracer(
197
+ process.env.PROJECT_NAME || "trigger-worker-workflow",
198
+ process.env.PROJECT_VERSION || "0.0.1",
199
+ );
200
+ protected readonly logger = new DefaultLogger();
201
+ /** OBS-02 T4 — graceful shutdown for the OTel tracer provider, if tracing was enabled. */
202
+ private tracingShutdown: (() => Promise<void>) | null = null;
203
+ /**
204
+ * v0.7 PR 5 — the "default" adapter, used when a workflow's
205
+ * `trigger.worker.provider` field is omitted AND the
206
+ * `BLOK_WORKER_ADAPTER` env var is unset. Subclasses MAY set this
207
+ * for back-compat with the pre-v0.7 single-adapter pattern
208
+ * (`class WorkerServer extends WorkerTrigger { protected adapter = new NATSWorkerAdapter() }`).
209
+ *
210
+ * When unset AND no per-workflow provider is specified, the factory
211
+ * falls back to `in-memory`. The factory pool (`adapters/factory.ts`)
212
+ * tracks one connected adapter per provider so multiple workflows
213
+ * with the same provider share a single broker connection.
214
+ */
215
+ protected adapter?: WorkerAdapter;
216
+
217
+ /** Active queues being processed */
218
+ protected activeQueues: Set<string> = new Set();
219
+
220
+ /**
221
+ * v0.7 PR 5 — adapter pool, keyed by provider name. Populated lazily
222
+ * inside `listen()` as workflows are matched to providers. Each
223
+ * adapter is connected once and reused across workflows that share
224
+ * its provider. Drained in `stop()`.
225
+ */
226
+ protected adapterPool: Map<string, WorkerAdapter> = new Map();
227
+
228
+ // Subclasses provide these
229
+ protected abstract nodes: Record<string, BlokService<unknown>>;
230
+ protected abstract workflows: Record<string, WorkflowV2Builder>;
231
+
232
+ // Constructor removed in v0.6.3 — pre-fix it called `loadNodes()` +
233
+ // `loadWorkflows()`, but subclasses use class-field assignments for
234
+ // `nodes` / `workflows` (the canonical TypeScript pattern). Those
235
+ // fields run AFTER super(), so accessing `this.nodes` from the parent
236
+ // constructor read `undefined` and crashed with
237
+ // `TypeError: undefined is not an object (Object.keys(this.nodes))`.
238
+ // The registry init now happens at the start of `listen()`, after
239
+ // the subclass's fields are initialized.
240
+
241
+ /**
242
+ * Load nodes into the node map
243
+ */
244
+ loadNodes(): void {
245
+ this.nodeMap.nodes = new NodeMap();
246
+ // Register each node under its own node.name (the canonical use: ref, ADR
247
+ // 0002) — the Nodes.ts map keys are cosmetic; the collision guard catches dups.
248
+ this.nodeMap.nodes.addNodes(Object.values(this.nodes) as unknown as NodeBase[]);
249
+ }
250
+
251
+ /**
252
+ * Load workflows into the workflow map
253
+ */
254
+ loadWorkflows(): void {
255
+ this.nodeMap.workflows = this.workflows;
256
+ }
257
+
258
+ /**
259
+ * Start the worker processor - main entry point
260
+ */
261
+ async listen(): Promise<number> {
262
+ const startTime = this.startCounter();
263
+
264
+ // OBS-02 T4 — opt-in distributed tracing for worker jobs. When
265
+ // OTEL_EXPORTER_OTLP_ENDPOINT is set, install an OTel SDK so the spans
266
+ // the runner creates per job/step export to Tempo/Jaeger/etc. Mirrors
267
+ // HttpTrigger's B1 wiring; no-op + zero overhead when the env var is unset.
268
+ await this.maybeBootstrapTracing();
269
+
270
+ // Populate the trigger's node + workflow registries from the
271
+ // subclass's `nodes` / `workflows` fields. v0.6.3 fix — pre-fix
272
+ // these calls lived in the constructor and crashed because class
273
+ // fields haven't run yet at super-constructor time. See the comment
274
+ // where the old constructor used to live for the full reason.
275
+ this.loadNodes();
276
+ this.loadWorkflows();
277
+
278
+ // F6 (worker part) — feed the WorkflowRegistry from the worker nodeMap.
279
+ // Worker-only deployments never instantiate an HttpTrigger, so without
280
+ // this the registry is empty and any trigger-level / process-global
281
+ // middleware name or `subworkflow:` step fails at runtime. Workflows
282
+ // flagged `middleware: true` are registered with `isMiddleware`.
283
+ this.registerWorkflowsFromNodeMap(this.logger);
284
+
285
+ // F14 (worker part) — seed BLOK_GLOBAL_MIDDLEWARE from env. Only
286
+ // HttpTrigger did this before, so a pure worker process silently
287
+ // dropped the documented env-var configuration.
288
+ this.seedGlobalMiddlewareFromEnv(this.logger);
289
+
290
+ try {
291
+ // Tier 2 quick-wins follow-up · install crash handlers + recover
292
+ // orphaned runs from a previous (dead) process. Idempotent + opt-out
293
+ // via `BLOK_CRASH_AUTOFLIP_DISABLED=1`.
294
+ try {
295
+ WorkerTrigger.installCrashHandlers(this.logger);
296
+ const orphaned = WorkerTrigger.recoverOrphanedRuns(undefined, this.logger);
297
+ if (orphaned > 0) {
298
+ this.logger.log(`[crash-autoflip] flipped ${orphaned} orphaned run(s) to crashed on boot`);
299
+ }
300
+ } catch (err) {
301
+ this.logger.error(`[crash-autoflip] setup failed: ${err instanceof Error ? err.message : String(err)}`);
302
+ }
303
+
304
+ // Tier 2 follow-up · start the periodic storage janitor.
305
+ // Idempotent (singleton); opt-out via `BLOK_JANITOR_DISABLED=1`.
306
+ try {
307
+ Janitor.getInstance(RunTracker.getInstance().getStore(), this.logger).start();
308
+ } catch (err) {
309
+ this.logger.error(`[janitor] setup failed: ${err instanceof Error ? err.message : String(err)}`);
310
+ }
311
+
312
+ // Tier 2 follow-up · install graceful shutdown handlers
313
+ // (SIGTERM / SIGINT). Idempotent; opt-out via
314
+ // `BLOK_GRACEFUL_SHUTDOWN_DISABLED=1`.
315
+ try {
316
+ WorkerTrigger.installShutdownHandlers(this, this.logger);
317
+ } catch (err) {
318
+ this.logger.error(`[shutdown] setup failed: ${err instanceof Error ? err.message : String(err)}`);
319
+ }
320
+
321
+ // Find all workflows with worker triggers
322
+ const workerWorkflows = this.getWorkerWorkflows();
323
+
324
+ if (workerWorkflows.length === 0) {
325
+ this.logger.log("No workflows with worker triggers found");
326
+ return this.endCounter(startTime);
327
+ }
328
+
329
+ // Start processing each queue, dispatching to the right adapter
330
+ // based on the workflow's `provider` field (with back-compat
331
+ // fallback to `this.adapter` when subclasses still set it).
332
+ for (const workflow of workerWorkflows) {
333
+ const config = workflow.config.trigger?.worker as WorkerTriggerOpts;
334
+ const adapter = await this.resolveAdapterForWorkflow(config);
335
+ this.logger.log(
336
+ `Starting worker for queue: ${config.queue} via ${adapter.provider} (concurrency=${config.concurrency}, retries=${config.retries})`,
337
+ );
338
+
339
+ this.activeQueues.add(config.queue);
340
+
341
+ await adapter.process(config, async (job) => {
342
+ await this.handleJob(job, workflow, config);
343
+ });
344
+ }
345
+
346
+ this.logger.log(`Worker trigger started. Processing ${workerWorkflows.length} queue(s)`);
347
+
348
+ // Enable HMR in development mode
349
+ if (process.env.BLOK_HMR === "true" || process.env.NODE_ENV === "development") {
350
+ await this.enableHotReload();
351
+ }
352
+
353
+ return this.endCounter(startTime);
354
+ } catch (error) {
355
+ this.logger.error(`Failed to start worker trigger: ${(error as Error).message}`);
356
+ throw error;
357
+ }
358
+ }
359
+
360
+ /**
361
+ * Stop all workers and disconnect
362
+ */
363
+ /**
364
+ * OBS-02 T4 — install the OpenTelemetry SDK at boot when an OTLP endpoint is
365
+ * configured, so the spans the runner already creates for worker jobs export
366
+ * to a backend (Tempo/Jaeger/…). No-op when `OTEL_EXPORTER_OTLP_ENDPOINT` is
367
+ * unset or `BLOK_TRACING_DISABLED=1`. Stores the shutdown so `stop()` flushes.
368
+ */
369
+ private async maybeBootstrapTracing(): Promise<void> {
370
+ if (process.env.BLOK_TRACING_DISABLED === "1") return;
371
+ const base = process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT || process.env.OTEL_EXPORTER_OTLP_ENDPOINT;
372
+ if (!base) return;
373
+ const endpoint = process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ? base : `${base.replace(/\/$/, "")}/v1/traces`;
374
+ try {
375
+ const result = await bootstrapTracing({
376
+ serviceName: process.env.APP_NAME || process.env.PROJECT_NAME || "blok-worker",
377
+ serviceVersion: process.env.PROJECT_VERSION,
378
+ exporter: "otlp",
379
+ endpoint,
380
+ });
381
+ if (result) {
382
+ this.tracingShutdown = result.shutdown;
383
+ this.logger.log(`[blok][tracing] OTLP distributed tracing enabled → ${endpoint}`);
384
+ } else {
385
+ this.logger.error(
386
+ "[blok][tracing] OTEL_EXPORTER_OTLP_ENDPOINT is set but the OTel trace SDK isn't installed — tracing is OFF.",
387
+ );
388
+ }
389
+ } catch (err) {
390
+ this.logger.error(`[blok][tracing] failed to initialize: ${(err as Error).message}`);
391
+ }
392
+ }
393
+
394
+ async stop(): Promise<void> {
395
+ // OBS-02 T4 — flush pending spans before draining so the last jobs'
396
+ // spans aren't lost on shutdown.
397
+ if (this.tracingShutdown) {
398
+ await this.tracingShutdown().catch((err) =>
399
+ this.logger.error(`[blok][tracing] shutdown failed: ${(err as Error).message}`),
400
+ );
401
+ this.tracingShutdown = null;
402
+ }
403
+ // Stop each queue on its owning adapter — adapters are tracked
404
+ // in the pool so multi-provider workers all drain cleanly.
405
+ for (const queue of this.activeQueues) {
406
+ for (const adapter of this.adapterPool.values()) {
407
+ try {
408
+ await adapter.stopProcessing(queue);
409
+ } catch {
410
+ /* swallow — adapter may not own this queue */
411
+ }
412
+ }
413
+ this.logger.log(`Stopped processing queue: ${queue}`);
414
+ }
415
+ this.activeQueues.clear();
416
+ // Disconnect every adapter we ever connected.
417
+ for (const adapter of this.adapterPool.values()) {
418
+ try {
419
+ await adapter.disconnect();
420
+ } catch (err) {
421
+ this.logger.error(`[blok][worker] disconnect failed: ${(err as Error).message}`);
422
+ }
423
+ }
424
+ this.adapterPool.clear();
425
+ this.destroyMonitoring();
426
+ this.logger.log("Worker trigger stopped");
427
+ }
428
+
429
+ protected override async onHmrWorkflowChange(): Promise<void> {
430
+ this.logger.log("[HMR] Worker workflow changed, reloading...");
431
+ await this.waitForInFlightRequests();
432
+ await this.stop();
433
+ this.loadWorkflows();
434
+ await this.listen();
435
+ }
436
+
437
+ /**
438
+ * Dispatch a job to a worker queue
439
+ */
440
+ async dispatch(
441
+ queue: string,
442
+ data: unknown,
443
+ opts?: {
444
+ priority?: number;
445
+ delay?: number;
446
+ retries?: number;
447
+ timeout?: number;
448
+ jobId?: string;
449
+ },
450
+ ): Promise<string> {
451
+ // Back-compat: when a subclass set `this.adapter`, use it.
452
+ // Otherwise dispatch via the first pool adapter — typically the
453
+ // only one when a process owns one trigger workflow.
454
+ const adapter =
455
+ this.adapter ??
456
+ (this.adapterPool.size > 0 ? (this.adapterPool.values().next().value as WorkerAdapter) : undefined);
457
+ if (!adapter) {
458
+ throw new Error(
459
+ "[blok][worker] dispatch() called before any adapter is connected. Call listen() first, or set this.adapter on the subclass.",
460
+ );
461
+ }
462
+ return adapter.addJob(queue, data, opts);
463
+ }
464
+
465
+ /**
466
+ * Get statistics for a queue
467
+ */
468
+ async getQueueStats(queue: string): Promise<WorkerQueueStats> {
469
+ const adapter =
470
+ this.adapter ??
471
+ (this.adapterPool.size > 0 ? (this.adapterPool.values().next().value as WorkerAdapter) : undefined);
472
+ if (!adapter) {
473
+ throw new Error(
474
+ "[blok][worker] getQueueStats() called before any adapter is connected. Call listen() first, or set this.adapter on the subclass.",
475
+ );
476
+ }
477
+ return adapter.getQueueStats(queue);
478
+ }
479
+
480
+ /**
481
+ * Get list of active queues
482
+ */
483
+ getActiveQueues(): string[] {
484
+ return Array.from(this.activeQueues);
485
+ }
486
+
487
+ /**
488
+ * v0.7 PR 5 — pick the adapter for a workflow's `provider` field.
489
+ *
490
+ * Resolution order:
491
+ * 1. Subclass-set `this.adapter` (back-compat: pre-v0.7 pattern
492
+ * where one process binds to one adapter at construction time).
493
+ * 2. Per-workflow `provider` field, looked up via the factory.
494
+ * 3. `BLOK_WORKER_ADAPTER` env var.
495
+ * 4. `in-memory` fallback.
496
+ *
497
+ * Adapters are connected on first use and pooled per provider so
498
+ * multiple workflows sharing a provider share one broker
499
+ * connection. Health-dependency registration also happens here so
500
+ * each provider is tracked individually in `/health`.
501
+ */
502
+ protected async resolveAdapterForWorkflow(config: WorkerTriggerOpts): Promise<WorkerAdapter> {
503
+ // Subclass override wins for back-compat.
504
+ if (this.adapter) {
505
+ if (!this.adapter.isConnected()) {
506
+ await this.adapter.connect();
507
+ this.logger.log(`Connected to ${this.adapter.provider} worker system (subclass adapter)`);
508
+ this.registerAdapterHealth(this.adapter);
509
+ }
510
+ // Pool-track so stop() can drain it.
511
+ this.adapterPool.set(this.adapter.provider, this.adapter);
512
+ return this.adapter;
513
+ }
514
+
515
+ // Lazy-import the factory so the worker package doesn't pull in
516
+ // every adapter on import — only the ones actually exercised.
517
+ const { resolveProvider, createWorkerAdapter } = await import("./adapters/factory");
518
+ const provider = resolveProvider(config.provider);
519
+ let adapter = this.adapterPool.get(provider);
520
+ if (!adapter) {
521
+ adapter = createWorkerAdapter(provider);
522
+ await adapter.connect();
523
+ this.logger.log(`Connected to ${adapter.provider} worker system`);
524
+ this.registerAdapterHealth(adapter);
525
+ this.adapterPool.set(provider, adapter);
526
+ }
527
+ return adapter;
528
+ }
529
+
530
+ private registerAdapterHealth(adapter: WorkerAdapter): void {
531
+ this.registerHealthDependency(`worker-${adapter.provider}`, async () => {
532
+ const healthy = await adapter.healthCheck();
533
+ return {
534
+ status: healthy ? ("healthy" as const) : ("unhealthy" as const),
535
+ lastChecked: Date.now(),
536
+ message: healthy ? "Connected" : "Connection lost",
537
+ };
538
+ });
539
+ }
540
+
541
+ /**
542
+ * Get all workflows that have worker triggers
543
+ */
544
+ protected getWorkerWorkflows(): WorkerWorkflowModel[] {
545
+ const workflows: WorkerWorkflowModel[] = [];
546
+
547
+ for (const [path, workflow] of Object.entries(this.nodeMap.workflows || {})) {
548
+ const workflowConfig = (workflow as unknown as { _config: WorkerWorkflowModel["config"] })._config;
549
+
550
+ // F11 — discover the worker trigger by direct key access, NOT by
551
+ // inspecting only the FIRST key. A multi-trigger workflow such as
552
+ // `trigger: { http: {...}, worker: { queue: "jobs" } }` declares
553
+ // `worker` second; the old `Object.keys(trigger)[0] === "worker"`
554
+ // check silently dropped it, making discovery depend on JS object
555
+ // key insertion order. Every sibling trigger (HTTP/SSE/Webhook)
556
+ // already reads its key directly.
557
+ if (workflowConfig?.trigger?.worker) {
558
+ workflows.push({
559
+ path,
560
+ config: workflowConfig,
561
+ });
562
+ }
563
+ }
564
+
565
+ return workflows;
566
+ }
567
+
568
+ /**
569
+ * Handle an incoming job
570
+ */
571
+ protected async handleJob(job: WorkerJob, workflow: WorkerWorkflowModel, config: WorkerTriggerOpts): Promise<void> {
572
+ const jobId = job.id || uuid();
573
+ const defaultMeter = metrics.getMeter("default");
574
+ const workerJobs = defaultMeter.createCounter("worker_jobs_processed", {
575
+ description: "Worker jobs processed",
576
+ });
577
+ const workerErrors = defaultMeter.createCounter("worker_jobs_failed", {
578
+ description: "Worker job failures",
579
+ });
580
+ const workerRetries = defaultMeter.createCounter("worker_jobs_retried", {
581
+ description: "Worker job retries",
582
+ });
583
+
584
+ await this.tracer.startActiveSpan(`worker:${config.queue}`, async (span: Span) => {
585
+ // F2 — give each job its OWN Configuration so concurrent jobs
586
+ // (`concurrency > 1`, or two queues in one process) never read a
587
+ // step list / name / trigger config another job's `init()`
588
+ // overwrote. Declared outside the try so the catch can flip the
589
+ // run's status via the per-job config name.
590
+ const configuration = new Configuration();
591
+ // F4 — captured from createContext so the timeout path can abort
592
+ // the detached run cooperatively.
593
+ let runCtx: Context | undefined;
594
+ try {
595
+ const start = performance.now();
596
+
597
+ // Bug 03 — resolve the already-loaded workflow object from the
598
+ // in-memory nodeMap and pass it as the `preloaded` arg (mirrors
599
+ // HTTP). This routes init through the preloaded branch and skips
600
+ // the disk-based `LocalStorage` resolver whose dot heuristic
601
+ // rejected dotted `domain.action` workflow names ("File type not
602
+ // supported"). Fallback to `workflow.config` so `preloaded` is
603
+ // never undefined (which would re-trigger the disk branch).
604
+ const preloaded =
605
+ (this.nodeMap.workflows && (this.nodeMap.workflows as Record<string, unknown>)[workflow.path]) ??
606
+ workflow.config;
607
+
608
+ // F2 — initialize the per-job Configuration instead of the shared
609
+ // `this.configuration`.
610
+ await configuration.init(workflow.path, this.nodeMap, preloaded);
611
+
612
+ // Create context — bind it to the per-job Configuration (F2).
613
+ const ctx: Context = this.createContext(undefined, workflow.path, jobId, configuration);
614
+ runCtx = ctx;
615
+
616
+ // Populate request with job data
617
+ ctx.request = {
618
+ body: job.data,
619
+ headers: job.headers,
620
+ query: {},
621
+ params: {
622
+ queue: job.queue,
623
+ jobId: job.id,
624
+ attempt: String(job.attempts),
625
+ priority: String(job.priority),
626
+ },
627
+ } as unknown as RequestContext;
628
+
629
+ // Store worker metadata in context
630
+ if (!ctx.vars) ctx.vars = {};
631
+ ctx.vars._worker_job = {
632
+ id: job.id,
633
+ queue: job.queue,
634
+ attempts: String(job.attempts),
635
+ maxRetries: String(job.maxRetries),
636
+ priority: String(job.priority),
637
+ createdAt: job.createdAt.toISOString(),
638
+ delay: String(job.delay ?? 0),
639
+ timeout: String(job.timeout ?? 0),
640
+ };
641
+
642
+ ctx.logger.log(
643
+ `Processing job ${jobId} from ${config.queue} (attempt ${job.attempts + 1}/${job.maxRetries + 1})`,
644
+ );
645
+
646
+ // v0.6 · apply the merged middleware chain (process-global →
647
+ // workflow-level → trigger-level) on the same ctx the main
648
+ // workflow will see. State mutations from middleware
649
+ // (e.g. ctx.state.identity) carry forward. Middleware that
650
+ // throws (via `@blokjs/throw`) propagates to the outer
651
+ // catch and is routed through the worker's retry / DLQ
652
+ // logic exactly like a main-workflow error.
653
+ //
654
+ // F2 — pass the per-job `configuration` so trigger-level
655
+ // (`trigger.worker.middleware`) and workflow-level middleware
656
+ // are read from the object THIS job initialized. Without it the
657
+ // chain would read the never-initialized shared `this.configuration`
658
+ // (the worker no longer calls `this.configuration.init`) and
659
+ // silently drop everything but the process-global chain.
660
+ await this.applyMiddlewareChain(ctx, this.nodeMap, configuration);
661
+
662
+ // Execute workflow with timeout if configured.
663
+ // F2 — pass the per-job `configuration` into `run` so the runner
664
+ // reads the same object this job initialized.
665
+ let response: TriggerResponse;
666
+ if (config.timeout && config.timeout > 0) {
667
+ response = await this.executeWithTimeout(ctx, config.timeout, configuration);
668
+ } else {
669
+ response = await this.run(ctx, configuration);
670
+ }
671
+
672
+ const end = performance.now();
673
+
674
+ // Set span attributes
675
+ span.setAttribute("success", true);
676
+ span.setAttribute("job_id", jobId);
677
+ span.setAttribute("queue", config.queue);
678
+ span.setAttribute("attempts", job.attempts);
679
+ span.setAttribute("elapsed_ms", end - start);
680
+ span.setStatus({ code: SpanStatusCode.OK });
681
+
682
+ // Record metrics
683
+ workerJobs.add(1, {
684
+ env: process.env.NODE_ENV,
685
+ queue: config.queue,
686
+ workflow_name: configuration.name,
687
+ success: "true",
688
+ });
689
+
690
+ ctx.logger.log(`Job completed in ${(end - start).toFixed(2)}ms: ${jobId}`);
691
+
692
+ // Mark job as completed
693
+ await job.complete();
694
+ } catch (error) {
695
+ const errorMessage = (error as Error).message;
696
+
697
+ // Tier 2 #5 + #7 — deferred dispatch (delay/TTL/debounce).
698
+ // The run was deferred to a future timer; ACK without retry.
699
+ // The in-process scheduler owns the eventual dispatch, NOT
700
+ // the broker — re-queueing here would create a duplicate.
701
+ if (error instanceof DeferredDispatchSignal) {
702
+ span.setAttribute("success", false);
703
+ span.setAttribute("deferred", true);
704
+ span.setAttribute("deferred_status", error.info.status);
705
+ span.setStatus({ code: SpanStatusCode.OK, message: `deferred:${error.info.status}` });
706
+
707
+ this.logger.log(
708
+ `[scheduling] job ${jobId} runId=${error.info.runId} status=${error.info.status} ` +
709
+ `scheduledAt=${error.info.scheduledAt} pingCount=${error.info.pingCount} → ACK (no requeue)`,
710
+ );
711
+
712
+ await job.complete();
713
+ return;
714
+ }
715
+
716
+ // PR 1-5 polish — queue-mode TTL elapsed. The run is already
717
+ // flipped to `expired` (see TriggerBase queue branch); ACK
718
+ // without retry so the broker doesn't redeliver — the run
719
+ // will never succeed (timer won't re-fire). Distinct from
720
+ // the throttled NACK below.
721
+ if (error instanceof QueueExpiredError) {
722
+ span.setAttribute("success", false);
723
+ span.setAttribute("queue_expired", true);
724
+ span.setStatus({ code: SpanStatusCode.OK, message: "queue_expired" });
725
+
726
+ this.logger.log(
727
+ `[concurrency] job ${jobId} runId=${error.info.runId} key='${error.info.concurrencyKey}' ` +
728
+ `queueExpiredAt=${error.info.queueExpiredAt} → ACK (no requeue, run expired)`,
729
+ );
730
+
731
+ await job.complete();
732
+ return;
733
+ }
734
+
735
+ // Tier 2 #6 — concurrency gate denial. Distinct from a normal
736
+ // failure: NACK with redelivery so the broker re-queues the
737
+ // job with its existing back-off semantics. Doesn't count
738
+ // against the workflow's retry budget (different invariant).
739
+ // We always pass `willRetry: true` regardless of `job.attempts`
740
+ // because throttling is a transient resource state, not a
741
+ // permanent failure.
742
+ if (error instanceof ConcurrencyLimitError) {
743
+ span.setAttribute("success", false);
744
+ span.setAttribute("will_retry", true);
745
+ span.setAttribute("throttled", true);
746
+ span.setStatus({ code: SpanStatusCode.OK, message: "concurrency_limit_reached" });
747
+
748
+ this.logger.log(
749
+ `[concurrency] job ${jobId} key='${error.info.concurrencyKey}' ` +
750
+ `limit=${error.info.concurrencyLimit} inFlight=${error.info.currentInFlight} → NACK + redelivery`,
751
+ );
752
+
753
+ workerRetries.add(1, {
754
+ env: process.env.NODE_ENV,
755
+ queue: config.queue,
756
+ workflow_name: configuration?.name || "unknown",
757
+ reason: "throttled",
758
+ });
759
+
760
+ await job.fail(error as Error, true);
761
+ return;
762
+ }
763
+
764
+ // F3 — the run was cancelled by an operator
765
+ // (`POST /__blok/runs/:runId/cancel`). `RunnerSteps` throws
766
+ // `RunCancelledError`, which `TriggerBase.run` re-throws
767
+ // untouched (status already flipped to `cancelled`). The run is
768
+ // terminal — ACK the broker WITHOUT requeue so the
769
+ // deliberately-cancelled, often non-idempotent work doesn't run
770
+ // again on redelivery.
771
+ if (error instanceof RunCancelledError) {
772
+ span.setAttribute("success", false);
773
+ span.setAttribute("cancelled", true);
774
+ span.setStatus({ code: SpanStatusCode.OK, message: "run_cancelled" });
775
+
776
+ this.logger.log(`Job ${jobId} cancelled (run already terminal) → ACK (no requeue)`);
777
+
778
+ await job.complete();
779
+ return;
780
+ }
781
+
782
+ // F4 / F24 — trigger-level `config.timeout` elapsed. The detached
783
+ // run was already aborted via `ctx.signal` inside
784
+ // `executeWithTimeout`, so it unwinds with `RunCancelledError`
785
+ // at the next between-step check. Flip the run record to the
786
+ // dedicated `timedOut` status (matching the per-step
787
+ // `maxDuration` taxonomy) instead of routing through the generic
788
+ // retry/DLQ path, and ACK without requeue.
789
+ if (error instanceof WorkerTimeoutError) {
790
+ span.setAttribute("success", false);
791
+ span.setAttribute("timed_out", true);
792
+ span.setStatus({ code: SpanStatusCode.ERROR, message: "job_timed_out" });
793
+
794
+ const timedOutRunId = error.runId ?? (runCtx as { _traceRunId?: string } | undefined)?._traceRunId;
795
+ if (timedOutRunId) {
796
+ try {
797
+ RunTracker.getInstance().markRunTimedOut(timedOutRunId, {
798
+ stepId: "__worker_timeout__",
799
+ maxDurationMs: error.timeoutMs,
800
+ attemptsExhausted: job.attempts + 1,
801
+ });
802
+ } catch (markErr) {
803
+ this.logger.error(
804
+ `[blok][worker] markRunTimedOut failed for run ${timedOutRunId}: ${markErr instanceof Error ? markErr.message : String(markErr)}`,
805
+ );
806
+ }
807
+ }
808
+
809
+ workerErrors.add(1, {
810
+ env: process.env.NODE_ENV,
811
+ queue: config.queue,
812
+ workflow_name: configuration?.name || "unknown",
813
+ reason: "timeout",
814
+ });
815
+
816
+ this.logger.error(
817
+ `Job ${jobId} timed out after ${error.timeoutMs}ms → run flipped to timedOut, ACK (no requeue)`,
818
+ );
819
+
820
+ await job.complete();
821
+ return;
822
+ }
823
+
824
+ const shouldRetry = job.attempts < job.maxRetries;
825
+
826
+ // Set span error
827
+ span.setAttribute("success", false);
828
+ span.setAttribute("will_retry", shouldRetry);
829
+ span.recordException(error as Error);
830
+ span.setStatus({ code: SpanStatusCode.ERROR, message: errorMessage });
831
+
832
+ if (shouldRetry) {
833
+ // Retry with exponential backoff. `config.delay` widened to
834
+ // `string | number | undefined` in Tier 2 #5 (duration strings).
835
+ // `calculateBackoff` only handles numbers; normalize via
836
+ // tryParseDuration. Fail-open to undefined → default backoff.
837
+ const delayMs =
838
+ typeof config.delay === "number"
839
+ ? config.delay
840
+ : typeof config.delay === "string"
841
+ ? (tryParseDuration(config.delay) ?? undefined)
842
+ : undefined;
843
+ const backoffMs = this.calculateBackoff(job.attempts, delayMs);
844
+ workerRetries.add(1, {
845
+ env: process.env.NODE_ENV,
846
+ queue: config.queue,
847
+ workflow_name: configuration?.name || "unknown",
848
+ attempt: String(job.attempts + 1),
849
+ });
850
+
851
+ this.logger.error(
852
+ `Job ${jobId} failed (attempt ${job.attempts + 1}/${job.maxRetries + 1}), retrying in ${backoffMs}ms: ${errorMessage}`,
853
+ );
854
+
855
+ await job.fail(error as Error, true);
856
+ } else {
857
+ // Max retries exhausted - send to DLQ
858
+ workerErrors.add(1, {
859
+ env: process.env.NODE_ENV,
860
+ queue: config.queue,
861
+ workflow_name: configuration?.name || "unknown",
862
+ });
863
+
864
+ this.logger.error(
865
+ `Job ${jobId} permanently failed after ${job.attempts + 1} attempts: ${errorMessage}`,
866
+ (error as Error).stack,
867
+ );
868
+
869
+ await job.fail(error as Error, false);
870
+ }
871
+ } finally {
872
+ span.end();
873
+ }
874
+ });
875
+ }
876
+
877
+ /**
878
+ * Execute workflow with a timeout.
879
+ *
880
+ * F4 — on timeout, fire the ctx AbortController so the detached `run`
881
+ * unwinds cooperatively (it throws `RunCancelledError` at the next
882
+ * between-step check; long uninterruptible nodes should still poll
883
+ * `ctx.signal.aborted`). The promise rejects with a dedicated
884
+ * {@link WorkerTimeoutError} carrying the run id so `handleJob`'s catch can
885
+ * flip the run record to `timedOut` (F24). The second `run` (broker
886
+ * redelivery) is prevented because we ACK without requeue on timeout.
887
+ *
888
+ * F2 — `configuration` is the per-job Configuration; threaded into `run`.
889
+ */
890
+ protected async executeWithTimeout(
891
+ ctx: Context,
892
+ timeoutMs: number,
893
+ configuration?: Configuration,
894
+ ): Promise<TriggerResponse> {
895
+ return new Promise<TriggerResponse>((resolve, reject) => {
896
+ let settled = false;
897
+ const timer = setTimeout(() => {
898
+ if (settled) return;
899
+ settled = true;
900
+
901
+ // F4 — abort the detached run so it stops executing rather than
902
+ // continuing to settle its own run record out of band.
903
+ const privateSlot = ctx._PRIVATE_ as { abortController?: AbortController } | null;
904
+ try {
905
+ privateSlot?.abortController?.abort();
906
+ } catch {
907
+ /* best-effort — abort never throws, but guard anyway */
908
+ }
909
+
910
+ const runId = (ctx as { _traceRunId?: string })._traceRunId;
911
+ reject(new WorkerTimeoutError(timeoutMs, runId));
912
+ }, timeoutMs);
913
+
914
+ this.run(ctx, configuration)
915
+ .then((result) => {
916
+ clearTimeout(timer);
917
+ if (settled) return; // already timed out — ignore the late result
918
+ settled = true;
919
+ resolve(result);
920
+ })
921
+ .catch((error) => {
922
+ clearTimeout(timer);
923
+ if (settled) return; // already rejected with WorkerTimeoutError
924
+ settled = true;
925
+ reject(error);
926
+ });
927
+ });
928
+ }
929
+
930
+ /**
931
+ * Calculate exponential backoff delay
932
+ * Formula: min(baseDelay * 2^attempt, 30000) + jitter
933
+ */
934
+ protected calculateBackoff(attempt: number, baseDelay?: number): number {
935
+ const base = baseDelay ?? 1000;
936
+ const maxDelay = 30000; // 30 seconds max
937
+ const exponential = Math.min(base * 2 ** attempt, maxDelay);
938
+ const jitter = Math.random() * exponential * 0.1; // 10% jitter
939
+ return Math.floor(exponential + jitter);
940
+ }
941
+ }
942
+
943
+ export default WorkerTrigger;