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,757 @@
1
+ """gRPC server implementing the canonical Blok ``NodeRuntime`` v1 service.
2
+
3
+ Wire contract: ``proto/blok/runtime/v1/runtime.proto``. Generated stubs live
4
+ in :mod:`blok.runtime.v1`.
5
+
6
+ Architecture
7
+ ------------
8
+ * :class:`BlokNodeRuntimeServicer` is the grpc-python service implementation.
9
+ It owns a reference to a shared :class:`blok.node.node_registry.NodeRegistry`
10
+ so a single registry can serve both HTTP and gRPC.
11
+ * :func:`serve_grpc` builds the grpc server, binds the port, and blocks until
12
+ shutdown.
13
+ * The codec helpers (``_decode_*`` / ``_encode_*``) sit at the boundary between
14
+ proto and the SDK's internal :class:`ExecutionRequest` / :class:`ExecutionResult`
15
+ types so :class:`NodeRegistry` runs unchanged regardless of which transport
16
+ delivered the request.
17
+
18
+ The proto sends ``inputs``, ``previous_output``, ``vars``, and the request
19
+ ``body`` as raw JSON-encoded ``bytes``. The SDK JSON-decodes them lazily.
20
+
21
+ This module imports ``grpcio`` lazily — callers should import it only when the
22
+ ``grpc`` optional extra is installed. ``__init__.py`` does NOT import this
23
+ module to keep the base SDK installable without grpcio.
24
+ """
25
+ from __future__ import annotations
26
+
27
+ import json
28
+ import logging
29
+ import queue
30
+ import threading
31
+ import time
32
+ from concurrent import futures
33
+ from typing import Any, Dict, Iterator, List, Optional, Tuple
34
+
35
+ import grpc
36
+ from google.protobuf import timestamp_pb2
37
+
38
+ from blok.errors.blok_error import (
39
+ BlokError,
40
+ DEFAULT_RUNTIME_KIND,
41
+ DEFAULT_SDK_NAME,
42
+ ErrorCategory,
43
+ ErrorSeverity,
44
+ )
45
+ from blok.node.node_registry import NodeRegistry
46
+ from blok.types.context import Context, Request, Response
47
+ from blok.types.execution_request import ExecutionRequest, NodeConfig
48
+ from blok.types.execution_result import ExecutionResult
49
+
50
+ from blok.runtime.v1 import runtime_pb2 as pb
51
+ from blok.runtime.v1 import runtime_pb2_grpc as pb_grpc
52
+
53
+ logger = logging.getLogger("blok.grpc")
54
+
55
+ # Logger that node handlers should emit to in order to have their messages
56
+ # streamed back to the runner via ``ExecuteStream``. This is a deliberate
57
+ # convention: only events on this named logger are captured, so the handler
58
+ # doesn't have to filter out unrelated noise from third-party libraries.
59
+ NODE_LOGGER_NAME = "blok.node"
60
+
61
+ # =============================================================================
62
+ # Servicer
63
+ # =============================================================================
64
+
65
+
66
+ class BlokNodeRuntimeServicer(pb_grpc.NodeRuntimeServicer):
67
+ """gRPC implementation of the Blok ``NodeRuntime`` v1 service.
68
+
69
+ Single Responsibility: translate proto messages into the SDK's internal
70
+ :class:`ExecutionRequest` / :class:`ExecutionResult` and dispatch to
71
+ :class:`NodeRegistry`. All node-level error handling lives in
72
+ ``NodeRegistry.execute``.
73
+ """
74
+
75
+ def __init__(self, registry: NodeRegistry, sdk_version: str = "1.0.0") -> None:
76
+ self._registry = registry
77
+ self._sdk_version = sdk_version
78
+
79
+ # -- Execute ----------------------------------------------------------
80
+
81
+ def Execute(self, request: pb.ExecuteRequest, context: grpc.ServicerContext) -> pb.ExecuteResponse:
82
+ try:
83
+ execution_request = _decode_execute_request(request)
84
+ except _DecodeError as exc:
85
+ context.abort(grpc.StatusCode.INVALID_ARGUMENT, str(exc))
86
+ return pb.ExecuteResponse() # unreachable
87
+
88
+ result = self._registry.execute(execution_request)
89
+
90
+ return _encode_execute_response(
91
+ result,
92
+ node_name=execution_request.node.name,
93
+ sdk_version=self._sdk_version,
94
+ )
95
+
96
+ # -- ExecuteStream ----------------------------------------------------
97
+
98
+ def ExecuteStream(
99
+ self,
100
+ request: pb.ExecuteRequest,
101
+ context: grpc.ServicerContext,
102
+ ) -> Iterator[pb.ExecuteEvent]:
103
+ """Server-streaming variant of :meth:`Execute`.
104
+
105
+ Emits, in order:
106
+ 1. one :class:`pb.NodeStarted` event marking call acceptance
107
+ 2. zero or more :class:`pb.LogLine` events captured from the
108
+ :data:`NODE_LOGGER_NAME` logger **as they happen** while the
109
+ node executes (real-time, not buffered — Phase 5 follow-up)
110
+ 2b. zero or more :class:`pb.PartialResult` events the node emits
111
+ via ``ctx.emit(...)`` **as they happen** — the live data
112
+ channel a ``streamTo: "sse"`` step forwards to the client
113
+ 3. one terminal :class:`pb.ExecuteResponse` carrying the same payload
114
+ as a unary :meth:`Execute` would return
115
+
116
+ # Real-time streaming model
117
+
118
+ The handler runs on a worker thread (via
119
+ :class:`threading.Thread`) so the generator's main loop can
120
+ block on the log queue with a short timeout. Every time a log
121
+ record is enqueued the loop wakes, yields a ``LogLine`` proto,
122
+ and goes back to polling. When the worker thread completes the
123
+ loop drains any remaining records (preserving causal order
124
+ with respect to the final response) and yields the
125
+ ``ExecuteResponse``.
126
+
127
+ # Why a thread (not asyncio)
128
+
129
+ The :class:`NodeRegistry` interface is sync (
130
+ ``execute(request) -> result``) and node handlers may call
131
+ blocking I/O (``requests.post``, DB drivers, etc.) without
132
+ wrapping each call in ``run_in_executor``. A thread keeps the
133
+ contract simple and matches the gRPC server's existing
134
+ thread-pool model — the gRPC ThreadPoolExecutor already
135
+ dispatches concurrent calls onto threads, and our worker
136
+ thread is just one more worker for the duration of one call.
137
+
138
+ # Log capture isolation
139
+
140
+ Logs are captured via a per-call handler attached to the
141
+ :data:`NODE_LOGGER_NAME` logger. Concurrent ``ExecuteStream``
142
+ calls running on the gRPC pool each install their own
143
+ handler; ``logging`` itself serializes ``emit()`` so
144
+ ``queue.SimpleQueue`` is the right primitive (no extra lock
145
+ needed). The handler is removed in ``finally`` so a crashed
146
+ worker thread doesn't leave dangling handlers on the
147
+ process-wide root logger.
148
+ """
149
+ try:
150
+ execution_request = _decode_execute_request(request)
151
+ except _DecodeError as exc:
152
+ context.abort(grpc.StatusCode.INVALID_ARGUMENT, str(exc))
153
+ return # pragma: no cover — abort raises
154
+
155
+ # NodeStarted goes out immediately so the runner can record start time
156
+ # before the (potentially long) execute call.
157
+ yield pb.ExecuteEvent(started=pb.NodeStarted(at=_now_timestamp()))
158
+
159
+ log_queue: "queue.SimpleQueue[logging.LogRecord]" = queue.SimpleQueue()
160
+ handler = _QueueLogHandler(log_queue)
161
+ handler.setLevel(logging.DEBUG)
162
+ node_logger = logging.getLogger(NODE_LOGGER_NAME)
163
+ node_logger.addHandler(handler)
164
+ previous_propagate = node_logger.propagate
165
+ previous_level = node_logger.level
166
+ node_logger.propagate = False
167
+ # Lower the logger threshold to DEBUG so INFO/DEBUG messages from
168
+ # the node aren't filtered out before the handler sees them. Restored
169
+ # in the `finally` block so we don't leave the logger globally chatty.
170
+ node_logger.setLevel(logging.DEBUG)
171
+
172
+ # Live data-event channel. The node pushes onto this queue every time
173
+ # it calls ``ctx.emit(...)``; the streaming loop drains it and yields
174
+ # ``PartialResult`` frames. ``SimpleQueue.put`` is thread-safe, so the
175
+ # worker thread can emit freely while this generator (on the gRPC
176
+ # thread) drains. Cleared in ``finally`` so a handler reference can't
177
+ # outlive the call.
178
+ partial_queue: "queue.SimpleQueue[Any]" = queue.SimpleQueue()
179
+ execution_request.context._set_emit_sink(partial_queue.put)
180
+
181
+ # Run the handler on a worker thread so we can stream logs as
182
+ # they happen. ``result_box`` carries the success result (one
183
+ # entry on success, none on exception); ``error_box`` carries a
184
+ # surfaced exception so we can re-raise on the main thread for
185
+ # gRPC to translate into a status. The worker is daemon=True
186
+ # so a stuck handler can't block process shutdown.
187
+ result_box: list = []
188
+ error_box: list = []
189
+
190
+ def run_handler() -> None:
191
+ try:
192
+ result_box.append(self._registry.execute(execution_request))
193
+ except BaseException as exc: # noqa: BLE001 — surface to main thread
194
+ error_box.append(exc)
195
+
196
+ worker = threading.Thread(target=run_handler, daemon=True, name="blok-execute-stream-worker")
197
+
198
+ try:
199
+ worker.start()
200
+ # Real-time streaming loop: wake every 50 ms to either yield
201
+ # a buffered log frame or to check whether the worker has
202
+ # finished. A 50 ms tick is short enough that human
203
+ # observers see logs land "instantly" in Studio's SSE
204
+ # stream while keeping wakeup overhead negligible (~20
205
+ # checks/second).
206
+ while worker.is_alive():
207
+ # Drain all buffered partials immediately — this is the live
208
+ # data stream the SSE client consumes; we don't want it gated
209
+ # behind the 50 ms log-poll tick.
210
+ while True:
211
+ try:
212
+ snapshot = partial_queue.get_nowait()
213
+ except queue.Empty:
214
+ break
215
+ yield pb.ExecuteEvent(partial=_partial_to_proto(snapshot))
216
+ try:
217
+ record = log_queue.get(timeout=0.05)
218
+ except queue.Empty:
219
+ continue
220
+ yield pb.ExecuteEvent(log=_log_record_to_proto(record))
221
+
222
+ # Worker is done. Drain any partials, then any logs, the worker
223
+ # emitted between our last poll and its final return so they all
224
+ # arrive before the terminal frame (partials first — they belong
225
+ # to the live data stream).
226
+ while True:
227
+ try:
228
+ snapshot = partial_queue.get_nowait()
229
+ except queue.Empty:
230
+ break
231
+ yield pb.ExecuteEvent(partial=_partial_to_proto(snapshot))
232
+ while True:
233
+ try:
234
+ record = log_queue.get_nowait()
235
+ except queue.Empty:
236
+ break
237
+ yield pb.ExecuteEvent(log=_log_record_to_proto(record))
238
+ finally:
239
+ node_logger.removeHandler(handler)
240
+ node_logger.propagate = previous_propagate
241
+ node_logger.setLevel(previous_level)
242
+ # Drop the sink so the (possibly daemon) worker thread can't keep
243
+ # pushing into a queue we're no longer draining.
244
+ execution_request.context._set_emit_sink(None)
245
+
246
+ # Surface any exception the worker thread caught.
247
+ if error_box:
248
+ raise error_box[0]
249
+
250
+ # ``result_box`` always has exactly one element when the
251
+ # worker completed without exception (registry.execute()
252
+ # never raises — it converts handler errors into a failed
253
+ # ExecutionResult).
254
+ result = result_box[0]
255
+
256
+ yield pb.ExecuteEvent(
257
+ final=_encode_execute_response(
258
+ result,
259
+ node_name=execution_request.node.name,
260
+ sdk_version=self._sdk_version,
261
+ )
262
+ )
263
+
264
+ # -- Health -----------------------------------------------------------
265
+
266
+ def Health(self, request: pb.HealthRequest, context: grpc.ServicerContext) -> pb.HealthResponse:
267
+ return pb.HealthResponse(
268
+ status=pb.HealthResponse.Status.SERVING,
269
+ sdk_version=self._sdk_version,
270
+ registered_nodes=self._registry.node_names(),
271
+ )
272
+
273
+ # -- ListNodes --------------------------------------------------------
274
+
275
+ def ListNodes(self, request: pb.ListNodesRequest, context: grpc.ServicerContext) -> pb.ListNodesResponse:
276
+ descriptors = []
277
+ for name in self._registry.node_names():
278
+ handler = self._registry.get(name)
279
+ descriptors.append(
280
+ pb.NodeDescriptor(
281
+ name=name,
282
+ description=str(getattr(handler, "description", "") or ""),
283
+ # @node handlers expose JSON Schema via input/output_json_schema()
284
+ # (SPEC-B P2). Legacy Dict handlers don't → empty bytes.
285
+ input_schema_json=_node_schema_bytes(handler, "input_json_schema"),
286
+ output_schema_json=_node_schema_bytes(handler, "output_json_schema"),
287
+ tags=[],
288
+ )
289
+ )
290
+ return pb.ListNodesResponse(
291
+ nodes=descriptors,
292
+ sdk_name="blok-python3",
293
+ sdk_version=self._sdk_version,
294
+ proto_version="1.0.0",
295
+ )
296
+
297
+
298
+ # =============================================================================
299
+ # Server lifecycle
300
+ # =============================================================================
301
+
302
+
303
+ def serve_grpc(
304
+ registry: NodeRegistry,
305
+ port: int,
306
+ *,
307
+ host: str = "0.0.0.0",
308
+ sdk_version: str = "1.0.0",
309
+ max_workers: int = 10,
310
+ max_message_bytes: int = 16 * 1024 * 1024,
311
+ ) -> grpc.Server:
312
+ """Build, bind, and start the gRPC server.
313
+
314
+ Returns the started :class:`grpc.Server` so callers can stop it cleanly.
315
+ Does NOT block — call ``server.wait_for_termination()`` for blocking
316
+ behavior, or ``server.stop(grace)`` to shut down.
317
+ """
318
+ options: List[Tuple[str, Any]] = [
319
+ ("grpc.max_send_message_length", max_message_bytes),
320
+ ("grpc.max_receive_message_length", max_message_bytes),
321
+ ]
322
+
323
+ server = grpc.server(
324
+ futures.ThreadPoolExecutor(max_workers=max_workers),
325
+ options=options,
326
+ )
327
+ pb_grpc.add_NodeRuntimeServicer_to_server(
328
+ BlokNodeRuntimeServicer(registry, sdk_version),
329
+ server,
330
+ )
331
+ bind_address = f"{host}:{port}"
332
+ server.add_insecure_port(bind_address)
333
+ server.start()
334
+ logger.info(
335
+ "Blok gRPC server (NodeRuntime v1) listening on %s with %d nodes registered",
336
+ bind_address,
337
+ len(registry.node_names()),
338
+ )
339
+ return server
340
+
341
+
342
+ # =============================================================================
343
+ # Codec — proto ↔ internal types
344
+ # =============================================================================
345
+
346
+
347
+ def _node_schema_bytes(handler: Any, method_name: str) -> bytes:
348
+ """JSON-encode a node's reflected JSON Schema for the proto NodeDescriptor.
349
+
350
+ `@node` (FunctionNode) handlers expose `input_json_schema()` /
351
+ `output_json_schema()` (SPEC-B P2); legacy Dict handlers don't. Returns
352
+ empty bytes when absent, None, or unserializable — reflection must never
353
+ break ListNodes.
354
+ """
355
+ fn = getattr(handler, method_name, None)
356
+ if not callable(fn):
357
+ return b""
358
+ try:
359
+ schema = fn()
360
+ if schema is None:
361
+ return b""
362
+ return json.dumps(schema).encode("utf-8")
363
+ except Exception:
364
+ return b""
365
+
366
+
367
+ class _DecodeError(Exception):
368
+ """Raised when an incoming proto message can't be decoded into internal types."""
369
+
370
+
371
+ def _decode_execute_request(req: pb.ExecuteRequest) -> ExecutionRequest:
372
+ """Decode a proto ``ExecuteRequest`` into the SDK's ``ExecutionRequest``.
373
+
374
+ The opaque JSON-shaped fields (``inputs``, ``previous_output``, ``vars``,
375
+ request ``body``) arrive as raw ``bytes`` and are JSON-decoded here. This
376
+ keeps :class:`NodeRegistry.execute` transport-agnostic.
377
+ """
378
+ if req.node is None or not req.node.name:
379
+ raise _DecodeError("ExecuteRequest.node is required")
380
+
381
+ inputs_map = _decode_json_object(req.inputs, "inputs")
382
+ previous_output = _decode_json_value(req.state.previous_output, "previous_output")
383
+ vars_map = _decode_json_object(req.state.vars, "vars")
384
+ body = _decode_request_body(req.trigger.body, dict(req.trigger.headers))
385
+
386
+ request = Request(
387
+ body=body,
388
+ headers=dict(req.trigger.headers),
389
+ params=dict(req.trigger.params),
390
+ query=dict(req.trigger.query),
391
+ method=req.trigger.method,
392
+ url=req.trigger.url,
393
+ cookies=dict(req.trigger.cookies),
394
+ base_url=req.trigger.base_url,
395
+ )
396
+ response = Response(
397
+ data=previous_output,
398
+ content_type="application/json",
399
+ success=True,
400
+ error=None,
401
+ )
402
+
403
+ context = Context(
404
+ id=req.workflow.run_id,
405
+ workflow_name=req.workflow.name,
406
+ workflow_path=req.workflow.path,
407
+ request=request,
408
+ response=response,
409
+ vars=vars_map,
410
+ env=dict(req.state.env),
411
+ )
412
+
413
+ return ExecutionRequest(
414
+ node=NodeConfig(
415
+ name=req.node.name,
416
+ type=req.node.type,
417
+ config=inputs_map,
418
+ ),
419
+ context=context,
420
+ )
421
+
422
+
423
+ def _encode_execute_response(
424
+ result: ExecutionResult,
425
+ *,
426
+ node_name: str,
427
+ sdk_version: str,
428
+ ) -> pb.ExecuteResponse:
429
+ """Encode the SDK's ``ExecutionResult`` into a proto ``ExecuteResponse``."""
430
+ data_bytes = b""
431
+ if result.success and result.data is not None:
432
+ data_bytes = _encode_json_bytes(result.data)
433
+
434
+ vars_delta_bytes = b""
435
+ if result.vars:
436
+ vars_delta_bytes = _encode_json_bytes(result.vars)
437
+
438
+ # Phase 0 follow-up: populate `response_bytes` so Studio's run-detail
439
+ # Inspector shows the gRPC wire size next to the runner-measured
440
+ # request_bytes. We approximate via `len(data) + len(vars_delta)` —
441
+ # matches the runner's request_bytes approximation, so the two
442
+ # numbers in the Inspector are comparable.
443
+ response_bytes = len(data_bytes) + len(vars_delta_bytes)
444
+
445
+ metrics = None
446
+ if result.metrics is not None or response_bytes > 0:
447
+ metrics = pb.Metrics(
448
+ duration_ms=(result.metrics.duration_ms if result.metrics else 0) or 0.0,
449
+ cpu_ms=(result.metrics.cpu_ms if result.metrics else 0) or 0.0,
450
+ memory_bytes=int((result.metrics.memory_bytes if result.metrics else 0) or 0),
451
+ request_bytes=0,
452
+ response_bytes=response_bytes,
453
+ )
454
+
455
+ error_proto: Optional[pb.NodeError] = None
456
+ if not result.success:
457
+ error_proto = _internal_error_to_proto(
458
+ result.errors,
459
+ node_name=node_name,
460
+ sdk_version=sdk_version,
461
+ )
462
+
463
+ return pb.ExecuteResponse(
464
+ success=result.success,
465
+ data=data_bytes,
466
+ content_type="application/json",
467
+ error=error_proto,
468
+ vars_delta=vars_delta_bytes,
469
+ logs=[],
470
+ metrics=metrics,
471
+ )
472
+
473
+
474
+ def _internal_error_to_proto(
475
+ err: Any,
476
+ *,
477
+ node_name: str,
478
+ sdk_version: str,
479
+ ) -> pb.NodeError:
480
+ """Build a proto ``NodeError`` from whatever ``ExecutionResult.errors`` carries.
481
+
482
+ Two paths:
483
+
484
+ * **Structured (preferred)** — ``err`` is a :class:`BlokError`. All 19
485
+ fields serialize losslessly via :func:`_blok_error_to_proto`. Auto-fills
486
+ ``node``/``sdk``/``sdk_version``/``runtime_kind`` if the BlokError didn't
487
+ set them itself.
488
+ * **Loose** — ``err`` is a dict / string / None / Exception. Wrapped via
489
+ :meth:`BlokError.from_unknown` (always produces ``category=INTERNAL``
490
+ with the original payload preserved in ``details_json``) and then
491
+ serialized via the structured path.
492
+
493
+ Both paths produce the same proto shape, so the runner's gRPC codec
494
+ consumes them identically.
495
+ """
496
+ if isinstance(err, BlokError):
497
+ return _blok_error_to_proto(
498
+ _enrich(err, node_name=node_name, sdk_version=sdk_version),
499
+ )
500
+
501
+ wrapped = BlokError.from_unknown(
502
+ err,
503
+ node=node_name,
504
+ sdk=DEFAULT_SDK_NAME,
505
+ sdk_version=sdk_version,
506
+ runtime_kind=DEFAULT_RUNTIME_KIND,
507
+ )
508
+ return _blok_error_to_proto(wrapped)
509
+
510
+
511
+ def _enrich(err: BlokError, *, node_name: str, sdk_version: str) -> BlokError:
512
+ """Fill in any missing auto-enrichment fields on a handler-thrown BlokError."""
513
+ if not err.node:
514
+ err.node = node_name
515
+ if not err.sdk:
516
+ err.sdk = DEFAULT_SDK_NAME
517
+ if not err.sdk_version:
518
+ err.sdk_version = sdk_version
519
+ if not err.runtime_kind:
520
+ err.runtime_kind = DEFAULT_RUNTIME_KIND
521
+ return err
522
+
523
+
524
+ def _blok_error_to_proto(err: BlokError) -> pb.NodeError:
525
+ """Serialize a fully-populated :class:`BlokError` into the proto wire format.
526
+
527
+ The cause chain is serialized as a list of ``pb.NodeError`` messages; each
528
+ element is the chain link's payload with its own ``causes`` list emptied
529
+ (the cause chain has already been flattened by ``BlokError`` at construction
530
+ time, so nesting at the wire layer would double-count).
531
+ """
532
+ at_ts = timestamp_pb2.Timestamp()
533
+ at_ts.FromDatetime(err.at)
534
+
535
+ return pb.NodeError(
536
+ code=err.code,
537
+ category=_PROTO_CATEGORY[err.category],
538
+ severity=_PROTO_SEVERITY[err.severity],
539
+ node=err.node,
540
+ sdk=err.sdk,
541
+ sdk_version=err.sdk_version,
542
+ runtime_kind=err.runtime_kind,
543
+ at=at_ts,
544
+ message=err.message,
545
+ description=err.description,
546
+ remediation=err.remediation,
547
+ doc_url=err.doc_url,
548
+ causes=[_cause_dict_to_proto(c) for c in err.causes],
549
+ stack=err.stack,
550
+ context_snapshot_json=_encode_json_bytes(err.context_snapshot) if err.context_snapshot is not None else b"",
551
+ http_status=err.http_status,
552
+ retryable=err.retryable,
553
+ retry_after_ms=err.retry_after_ms,
554
+ details_json=_encode_json_bytes(err.details) if err.details is not None else b"",
555
+ )
556
+
557
+
558
+ def _cause_dict_to_proto(cause: Dict[str, Any]) -> pb.NodeError:
559
+ """Convert a flattened cause-chain dict (from ``BlokError.causes``) into proto.
560
+
561
+ Each element is one link from a `BlokError` cause chain — already a flat
562
+ list, so we don't recurse into the link's own causes.
563
+ """
564
+ at_str = cause.get("at")
565
+ at_ts = timestamp_pb2.Timestamp()
566
+ if isinstance(at_str, str):
567
+ try:
568
+ at_ts.FromJsonString(at_str)
569
+ except Exception: # pragma: no cover — defensive
570
+ at_ts.GetCurrentTime()
571
+ else:
572
+ at_ts.GetCurrentTime()
573
+
574
+ category = _parse_category_name(cause.get("category"))
575
+ severity = _parse_severity_name(cause.get("severity"))
576
+ return pb.NodeError(
577
+ code=str(cause.get("code", "")),
578
+ category=_PROTO_CATEGORY[category],
579
+ severity=_PROTO_SEVERITY[severity],
580
+ node=str(cause.get("node", "")),
581
+ sdk=str(cause.get("sdk", "")),
582
+ sdk_version=str(cause.get("sdk_version", "")),
583
+ runtime_kind=str(cause.get("runtime_kind", "")),
584
+ at=at_ts,
585
+ message=str(cause.get("message", "")),
586
+ description=str(cause.get("description", "")),
587
+ remediation=str(cause.get("remediation", "")),
588
+ doc_url=str(cause.get("doc_url", "")),
589
+ causes=[],
590
+ stack=str(cause.get("stack", "")),
591
+ context_snapshot_json=_encode_json_bytes(cause.get("context_snapshot"))
592
+ if cause.get("context_snapshot") is not None
593
+ else b"",
594
+ http_status=int(cause.get("http_status", 500)),
595
+ retryable=bool(cause.get("retryable", False)),
596
+ retry_after_ms=int(cause.get("retry_after_ms", 0)),
597
+ details_json=_encode_json_bytes(cause.get("details")) if cause.get("details") is not None else b"",
598
+ )
599
+
600
+
601
+ def _parse_category_name(value: Any) -> ErrorCategory:
602
+ if isinstance(value, ErrorCategory):
603
+ return value
604
+ if isinstance(value, str):
605
+ try:
606
+ return ErrorCategory(value)
607
+ except ValueError:
608
+ pass
609
+ return ErrorCategory.INTERNAL
610
+
611
+
612
+ def _parse_severity_name(value: Any) -> ErrorSeverity:
613
+ if isinstance(value, ErrorSeverity):
614
+ return value
615
+ if isinstance(value, str):
616
+ try:
617
+ return ErrorSeverity(value)
618
+ except ValueError:
619
+ pass
620
+ return ErrorSeverity.ERROR
621
+
622
+
623
+ # Map the SDK-side ErrorCategory enum (string values) to the proto-generated
624
+ # integer enum. Single source of truth; failures fall back to INTERNAL.
625
+ _PROTO_CATEGORY: Dict[ErrorCategory, int] = {
626
+ ErrorCategory.VALIDATION: pb.ErrorCategory.VALIDATION,
627
+ ErrorCategory.CONFIGURATION: pb.ErrorCategory.CONFIGURATION,
628
+ ErrorCategory.DEPENDENCY: pb.ErrorCategory.DEPENDENCY,
629
+ ErrorCategory.TIMEOUT: pb.ErrorCategory.TIMEOUT,
630
+ ErrorCategory.PERMISSION: pb.ErrorCategory.PERMISSION,
631
+ ErrorCategory.RATE_LIMIT: pb.ErrorCategory.RATE_LIMIT,
632
+ ErrorCategory.NOT_FOUND: pb.ErrorCategory.NOT_FOUND,
633
+ ErrorCategory.CONFLICT: pb.ErrorCategory.CONFLICT,
634
+ ErrorCategory.CANCELLED: pb.ErrorCategory.CANCELLED,
635
+ ErrorCategory.INTERNAL: pb.ErrorCategory.INTERNAL,
636
+ ErrorCategory.PROTOCOL: pb.ErrorCategory.PROTOCOL,
637
+ ErrorCategory.DATA: pb.ErrorCategory.DATA,
638
+ }
639
+
640
+ _PROTO_SEVERITY: Dict[ErrorSeverity, int] = {
641
+ ErrorSeverity.INFO: pb.ErrorSeverity.INFO,
642
+ ErrorSeverity.WARN: pb.ErrorSeverity.WARN,
643
+ ErrorSeverity.ERROR: pb.ErrorSeverity.ERROR,
644
+ ErrorSeverity.FATAL: pb.ErrorSeverity.FATAL,
645
+ }
646
+
647
+
648
+ def _decode_json_object(blob: bytes, field: str) -> Dict[str, Any]:
649
+ """Decode a JSON-bytes field as a typed dict. Empty bytes → empty dict."""
650
+ if not blob:
651
+ return {}
652
+ try:
653
+ value = json.loads(blob)
654
+ except json.JSONDecodeError as exc:
655
+ raise _DecodeError(f"invalid `{field}` JSON: {exc}") from exc
656
+ if isinstance(value, dict):
657
+ return value
658
+ # For non-object payloads we wrap into a single-key dict so SDK code
659
+ # accustomed to a dict doesn't crash. Rare in practice.
660
+ return {"_value": value}
661
+
662
+
663
+ def _decode_json_value(blob: bytes, field: str) -> Any:
664
+ """Decode a JSON-bytes field as an arbitrary value. Empty bytes → ``None``."""
665
+ if not blob:
666
+ return None
667
+ try:
668
+ return json.loads(blob)
669
+ except json.JSONDecodeError as exc:
670
+ raise _DecodeError(f"invalid `{field}` JSON: {exc}") from exc
671
+
672
+
673
+ def _decode_request_body(blob: bytes, headers: Dict[str, str]) -> Any:
674
+ """Decode the trigger body. JSON content-types parse as JSON; everything
675
+ else arrives as a raw string for the node to interpret.
676
+ """
677
+ if not blob:
678
+ return None
679
+
680
+ content_type = headers.get("content-type") or headers.get("Content-Type") or ""
681
+ if "application/json" in content_type:
682
+ try:
683
+ return json.loads(blob)
684
+ except json.JSONDecodeError:
685
+ pass # fall through to raw-string handling
686
+
687
+ try:
688
+ return blob.decode("utf-8")
689
+ except UnicodeDecodeError:
690
+ return ""
691
+
692
+
693
+ def _encode_json_bytes(value: Any) -> bytes:
694
+ """Encode a Python value as UTF-8 JSON bytes. Errors fall back to empty buffer."""
695
+ try:
696
+ return json.dumps(value).encode("utf-8")
697
+ except (TypeError, ValueError):
698
+ return b""
699
+
700
+
701
+ # =============================================================================
702
+ # Streaming helpers — used by ExecuteStream
703
+ # =============================================================================
704
+
705
+
706
+ class _QueueLogHandler(logging.Handler):
707
+ """Logging handler that pushes records onto a :class:`queue.SimpleQueue`.
708
+
709
+ Used by :meth:`BlokNodeRuntimeServicer.ExecuteStream` to capture log
710
+ records emitted on the ``blok.node`` logger during a single ``execute``
711
+ call. The queue is drained after execute completes; for fully real-time
712
+ streaming the handler would need to coordinate with the generator (Phase 5
713
+ follow-up).
714
+ """
715
+
716
+ def __init__(self, sink: "queue.SimpleQueue[logging.LogRecord]") -> None:
717
+ super().__init__()
718
+ self._sink = sink
719
+
720
+ def emit(self, record: logging.LogRecord) -> None:
721
+ self._sink.put(record)
722
+
723
+
724
+ def _partial_to_proto(snapshot: Any) -> pb.PartialResult:
725
+ """Encode a ``ctx.emit(...)`` snapshot into a proto ``PartialResult``.
726
+
727
+ The snapshot is any JSON-serializable value; it travels as opaque JSON
728
+ bytes (``snapshot_json``) exactly like the unary response ``data`` field,
729
+ so the runner decodes it the same way.
730
+ """
731
+ return pb.PartialResult(snapshot_json=_encode_json_bytes(snapshot))
732
+
733
+
734
+ def _now_timestamp() -> timestamp_pb2.Timestamp:
735
+ """Build a proto Timestamp from the current wall clock."""
736
+ ts = timestamp_pb2.Timestamp()
737
+ ts.GetCurrentTime()
738
+ return ts
739
+
740
+
741
+ def _log_record_to_proto(record: logging.LogRecord) -> pb.LogLine:
742
+ """Convert a Python ``logging.LogRecord`` into a proto ``LogLine``."""
743
+ ts = timestamp_pb2.Timestamp()
744
+ ts.FromMilliseconds(int(record.created * 1000))
745
+
746
+ attributes: Dict[str, str] = {}
747
+ if record.name and record.name != NODE_LOGGER_NAME:
748
+ attributes["logger"] = record.name
749
+ if record.funcName:
750
+ attributes["func"] = record.funcName
751
+
752
+ return pb.LogLine(
753
+ timestamp=ts,
754
+ level=record.levelname.lower(),
755
+ message=record.getMessage(),
756
+ attributes=attributes,
757
+ )