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.
- package/dist/commands/create/project.d.ts +3 -0
- package/dist/commands/create/project.js +166 -21
- package/dist/commands/create/utils/Examples.d.ts +2 -2
- package/dist/commands/create/utils/Examples.js +9 -3
- package/dist/commands/dev/index.js +13 -1
- package/dist/commands/runtime/add.js +92 -29
- package/dist/commands/runtime/index.js +1 -0
- package/dist/commands/runtime/shared.js +4 -0
- package/dist/scaffold-repo/examples/ts-workflows/mcp-greeter.ts +59 -0
- package/dist/scaffold-repo/examples/ts-workflows/runtime-csharp-hello.ts +36 -0
- package/dist/scaffold-repo/examples/ts-workflows/runtime-go-hello.ts +36 -0
- package/dist/scaffold-repo/examples/ts-workflows/runtime-java-hello.ts +36 -0
- package/dist/scaffold-repo/examples/ts-workflows/runtime-php-hello.ts +36 -0
- package/dist/scaffold-repo/examples/ts-workflows/runtime-python3-hello.ts +36 -0
- package/dist/scaffold-repo/examples/ts-workflows/runtime-ruby-hello.ts +36 -0
- package/dist/scaffold-repo/examples/ts-workflows/runtime-rust-hello.ts +36 -0
- package/dist/scaffold-repo/infra/development/3055.dat +602 -0
- package/dist/scaffold-repo/infra/development/3057.dat +203 -0
- package/dist/scaffold-repo/infra/development/3059.dat +19 -0
- package/dist/scaffold-repo/infra/development/3061.dat +1003 -0
- package/dist/scaffold-repo/infra/development/3062.dat +5465 -0
- package/dist/scaffold-repo/infra/development/3063.dat +1003 -0
- package/dist/scaffold-repo/infra/development/3065.dat +606 -0
- package/dist/scaffold-repo/infra/development/3067.dat +603 -0
- package/dist/scaffold-repo/infra/development/3069.dat +112 -0
- package/dist/scaffold-repo/infra/development/3071.dat +4584 -0
- package/dist/scaffold-repo/infra/development/3073.dat +9 -0
- package/dist/scaffold-repo/infra/development/3075.dat +14599 -0
- package/dist/scaffold-repo/infra/development/3077.dat +16047 -0
- package/dist/scaffold-repo/infra/development/3079.dat +5 -0
- package/dist/scaffold-repo/infra/development/3081.dat +5 -0
- package/dist/scaffold-repo/infra/development/docker-compose.yml +106 -0
- package/dist/scaffold-repo/infra/development/schema.sql +1616 -0
- package/dist/scaffold-repo/infra/development/toc.dat +0 -0
- package/dist/scaffold-repo/infra/metrics/alertmanager.yml +43 -0
- package/dist/scaffold-repo/infra/metrics/alloy-config.alloy +75 -0
- package/dist/scaffold-repo/infra/metrics/dashboard.json +1152 -0
- package/dist/scaffold-repo/infra/metrics/dashboards/blok-overview.json +314 -0
- package/dist/scaffold-repo/infra/metrics/dashboards/blok-system.json +175 -0
- package/dist/scaffold-repo/infra/metrics/dashboards/blok-tracing.json +235 -0
- package/dist/scaffold-repo/infra/metrics/dashboards/blok-triggers.json +258 -0
- package/dist/scaffold-repo/infra/metrics/datasources.yml +43 -0
- package/dist/scaffold-repo/infra/metrics/default.yaml +8 -0
- package/dist/scaffold-repo/infra/metrics/docker-compose.yml +193 -0
- package/dist/scaffold-repo/infra/metrics/loki-config.yaml +50 -0
- package/dist/scaffold-repo/infra/metrics/nginx.conf +25 -0
- package/dist/scaffold-repo/infra/metrics/prometheus.yml +51 -0
- package/dist/scaffold-repo/infra/metrics/rules/blok-alerts.yml +114 -0
- package/dist/scaffold-repo/infra/metrics/telegraf.conf +41 -0
- package/dist/scaffold-repo/infra/metrics/tempo.yaml +81 -0
- package/dist/scaffold-repo/infra/milvus/docker-compose.yml +73 -0
- package/dist/scaffold-repo/sdk/javascript/README.md +151 -0
- package/dist/scaffold-repo/sdk/javascript/bootstrap.min.css +11660 -0
- package/dist/scaffold-repo/sdk/javascript/image-ai.html +316 -0
- package/dist/scaffold-repo/sdk/javascript/nanosdk.js +180 -0
- package/dist/scaffold-repo/sdk/javascript/nanosdk.min.js +100 -0
- package/dist/scaffold-repo/sdk/javascript/pdf.html +63 -0
- package/dist/scaffold-repo/sdk/javascript/test.html +68 -0
- package/dist/scaffold-repo/sdks/CLAUDE.md +67 -0
- package/dist/scaffold-repo/sdks/csharp/.dockerignore +7 -0
- package/dist/scaffold-repo/sdks/csharp/Blok.Core.sln +24 -0
- package/dist/scaffold-repo/sdks/csharp/Dockerfile +42 -0
- package/dist/scaffold-repo/sdks/csharp/README.md +138 -0
- package/dist/scaffold-repo/sdks/csharp/proto/blok/runtime/v1/runtime.proto +302 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Blok.Core.csproj +39 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Config/ServerConfig.cs +90 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Errors/BlokError.cs +538 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Errors/BlokErrorCategory.cs +112 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Errors/BlokErrorSeverity.cs +40 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Errors/BuildContextSnapshot.cs +168 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Errors/ErrorCategory.cs +13 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Errors/NodeException.cs +44 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Logging/LogEntry.cs +34 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Logging/LogLevel.cs +12 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Logging/Logger.cs +92 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Middleware/IMiddleware.cs +14 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Middleware/LoggingMiddleware.cs +46 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Middleware/MiddlewareChain.cs +35 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Middleware/RecoveryMiddleware.cs +63 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Node/INodeHandler.cs +17 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Node/NodeRegistry.cs +128 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Node/TypedNode.cs +140 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Nodes/ApiCallNode.cs +129 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Nodes/BlokErrorDemoNode.cs +125 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Nodes/ChainTestNode.cs +79 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Nodes/HelloWorldNode.cs +45 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Nodes/TransformDataNode.cs +119 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Nodes/TypedGreetNode.cs +23 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Program.cs +26 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Server/BlokNodeRuntimeService.cs +536 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Server/RuntimeServer.cs +183 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Testing/MockContextBuilder.cs +117 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Testing/TestNodeRunner.cs +50 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Types/Context.cs +56 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Types/ExecutionMetrics.cs +21 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Types/ExecutionRequest.cs +15 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Types/ExecutionResult.cs +104 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Types/HealthStatus.cs +18 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Types/NodeConfig.cs +59 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Types/Request.cs +57 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Types/Response.cs +24 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/UserNodeRegistry.cs +17 -0
- package/dist/scaffold-repo/sdks/csharp/src/Blok.Core/Validation/SchemaValidator.cs +198 -0
- package/dist/scaffold-repo/sdks/csharp/tests/Blok.Core.Tests/Blok.Core.Tests.csproj +25 -0
- package/dist/scaffold-repo/sdks/csharp/tests/Blok.Core.Tests/Errors/BlokErrorTests.cs +458 -0
- package/dist/scaffold-repo/sdks/csharp/tests/Blok.Core.Tests/Logging/LoggerTests.cs +129 -0
- package/dist/scaffold-repo/sdks/csharp/tests/Blok.Core.Tests/Node/NodeRegistryTests.cs +145 -0
- package/dist/scaffold-repo/sdks/csharp/tests/Blok.Core.Tests/Testing/MockContextTests.cs +153 -0
- package/dist/scaffold-repo/sdks/csharp/tests/Blok.Core.Tests/TypedNodeTests.cs +69 -0
- package/dist/scaffold-repo/sdks/csharp/tests/Blok.Core.Tests/Types/ExecutionResultTests.cs +110 -0
- package/dist/scaffold-repo/sdks/csharp/tests/Blok.Core.Tests/Validation/SchemaValidatorTests.cs +233 -0
- package/dist/scaffold-repo/sdks/go/Dockerfile +33 -0
- package/dist/scaffold-repo/sdks/go/README.md +255 -0
- package/dist/scaffold-repo/sdks/go/blok_error.go +803 -0
- package/dist/scaffold-repo/sdks/go/blok_error_test.go +433 -0
- package/dist/scaffold-repo/sdks/go/cmd/server/main.go +45 -0
- package/dist/scaffold-repo/sdks/go/cmd/server/register_user_nodes.go +12 -0
- package/dist/scaffold-repo/sdks/go/config.go +157 -0
- package/dist/scaffold-repo/sdks/go/config_test.go +129 -0
- package/dist/scaffold-repo/sdks/go/define_node.go +87 -0
- package/dist/scaffold-repo/sdks/go/define_node_test.go +75 -0
- package/dist/scaffold-repo/sdks/go/errors.go +104 -0
- package/dist/scaffold-repo/sdks/go/errors_test.go +95 -0
- package/dist/scaffold-repo/sdks/go/examples/nodes/apicall.go +117 -0
- package/dist/scaffold-repo/sdks/go/examples/nodes/blokerrordemo.go +80 -0
- package/dist/scaffold-repo/sdks/go/examples/nodes/chaintest.go +63 -0
- package/dist/scaffold-repo/sdks/go/examples/nodes/helloworld.go +41 -0
- package/dist/scaffold-repo/sdks/go/examples/nodes/transformdata.go +176 -0
- package/dist/scaffold-repo/sdks/go/examples/nodes/typedgreet.go +34 -0
- package/dist/scaffold-repo/sdks/go/genpb/blok/runtime/v1/runtime.pb.go +2070 -0
- package/dist/scaffold-repo/sdks/go/genpb/blok/runtime/v1/runtime_grpc.pb.go +273 -0
- package/dist/scaffold-repo/sdks/go/go.mod +25 -0
- package/dist/scaffold-repo/sdks/go/go.sum +66 -0
- package/dist/scaffold-repo/sdks/go/grpc_server.go +670 -0
- package/dist/scaffold-repo/sdks/go/grpc_server_test.go +474 -0
- package/dist/scaffold-repo/sdks/go/logging.go +144 -0
- package/dist/scaffold-repo/sdks/go/logging_test.go +139 -0
- package/dist/scaffold-repo/sdks/go/middleware.go +152 -0
- package/dist/scaffold-repo/sdks/go/middleware_test.go +222 -0
- package/dist/scaffold-repo/sdks/go/node.go +50 -0
- package/dist/scaffold-repo/sdks/go/proto/blok/runtime/v1/runtime.proto +302 -0
- package/dist/scaffold-repo/sdks/go/registry.go +156 -0
- package/dist/scaffold-repo/sdks/go/registry_test.go +195 -0
- package/dist/scaffold-repo/sdks/go/server.go +207 -0
- package/dist/scaffold-repo/sdks/go/server_test.go +186 -0
- package/dist/scaffold-repo/sdks/go/shutdown.go +32 -0
- package/dist/scaffold-repo/sdks/go/testutil.go +169 -0
- package/dist/scaffold-repo/sdks/go/testutil_test.go +124 -0
- package/dist/scaffold-repo/sdks/go/types.go +295 -0
- package/dist/scaffold-repo/sdks/go/types_test.go +251 -0
- package/dist/scaffold-repo/sdks/go/validation.go +210 -0
- package/dist/scaffold-repo/sdks/go/validation_test.go +262 -0
- package/dist/scaffold-repo/sdks/go/worker.go +577 -0
- package/dist/scaffold-repo/sdks/java/Dockerfile +33 -0
- package/dist/scaffold-repo/sdks/java/README.md +221 -0
- package/dist/scaffold-repo/sdks/java/pom.xml +163 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/Main.java +90 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/UserNodeRegistry.java +19 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/config/ServerConfig.java +244 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/errors/BlokError.java +576 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/errors/BlokErrorCategory.java +68 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/errors/BlokErrorSeverity.java +31 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/errors/BuildContextSnapshot.java +132 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/errors/ErrorCategory.java +22 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/errors/NodeException.java +176 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/logging/LogEntry.java +78 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/logging/LogLevel.java +48 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/logging/Logger.java +160 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/middleware/LoggingMiddleware.java +65 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/middleware/Middleware.java +29 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/middleware/MiddlewareChain.java +59 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/middleware/RecoveryMiddleware.java +53 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/node/NodeHandler.java +40 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/node/NodeReflector.java +18 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/node/NodeRegistry.java +205 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/node/TypedNode.java +143 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/nodes/ApiCallNode.java +145 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/nodes/BlokErrorDemoNode.java +109 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/nodes/ChainTestNode.java +65 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/nodes/HelloWorldNode.java +62 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/nodes/TransformDataNode.java +121 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/nodes/TypedGreetNode.java +41 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/server/BlokGrpcServer.java +103 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/server/BlokNodeRuntimeService.java +501 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/server/RuntimeServer.java +176 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/testing/MockContext.java +120 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/testing/TestRunner.java +59 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/types/Context.java +167 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/types/ExecutionMetrics.java +80 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/types/ExecutionRequest.java +61 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/types/ExecutionResult.java +188 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/types/HealthStatus.java +77 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/types/NodeConfig.java +139 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/types/Request.java +154 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/types/Response.java +77 -0
- package/dist/scaffold-repo/sdks/java/src/main/java/com/blok/blok/validation/SchemaValidator.java +178 -0
- package/dist/scaffold-repo/sdks/java/src/main/proto/blok/runtime/v1/runtime.proto +302 -0
- package/dist/scaffold-repo/sdks/java/src/test/java/com/blok/blok/errors/BlokErrorTest.java +416 -0
- package/dist/scaffold-repo/sdks/java/src/test/java/com/blok/blok/logging/LoggerTest.java +176 -0
- package/dist/scaffold-repo/sdks/java/src/test/java/com/blok/blok/node/NodeRegistryTest.java +227 -0
- package/dist/scaffold-repo/sdks/java/src/test/java/com/blok/blok/node/TypedNodeTest.java +76 -0
- package/dist/scaffold-repo/sdks/java/src/test/java/com/blok/blok/server/RuntimeServerTest.java +197 -0
- package/dist/scaffold-repo/sdks/java/src/test/java/com/blok/blok/types/ExecutionResultTest.java +194 -0
- package/dist/scaffold-repo/sdks/java/src/test/java/com/blok/blok/validation/SchemaValidatorTest.java +246 -0
- package/dist/scaffold-repo/sdks/php/.rr.yaml +29 -0
- package/dist/scaffold-repo/sdks/php/Dockerfile +61 -0
- package/dist/scaffold-repo/sdks/php/README.md +387 -0
- package/dist/scaffold-repo/sdks/php/composer.json +41 -0
- package/dist/scaffold-repo/sdks/php/examples/ApiCallNode.php +103 -0
- package/dist/scaffold-repo/sdks/php/examples/BlokErrorDemoNode.php +90 -0
- package/dist/scaffold-repo/sdks/php/examples/ChainTestNode.php +56 -0
- package/dist/scaffold-repo/sdks/php/examples/HelloWorldNode.php +39 -0
- package/dist/scaffold-repo/sdks/php/examples/TransformDataNode.php +94 -0
- package/dist/scaffold-repo/sdks/php/examples/TypedGreetNode.php +57 -0
- package/dist/scaffold-repo/sdks/php/phpunit.xml +23 -0
- package/dist/scaffold-repo/sdks/php/proto/blok/runtime/v1/runtime.proto +302 -0
- package/dist/scaffold-repo/sdks/php/src/Config/ServerConfig.php +83 -0
- package/dist/scaffold-repo/sdks/php/src/Errors/BlokError.php +467 -0
- package/dist/scaffold-repo/sdks/php/src/Errors/BlokErrorBuilder.php +121 -0
- package/dist/scaffold-repo/sdks/php/src/Errors/BlokErrorCategory.php +83 -0
- package/dist/scaffold-repo/sdks/php/src/Errors/BlokErrorSeverity.php +30 -0
- package/dist/scaffold-repo/sdks/php/src/Errors/BuildContextSnapshot.php +141 -0
- package/dist/scaffold-repo/sdks/php/src/Errors/ErrorCategory.php +17 -0
- package/dist/scaffold-repo/sdks/php/src/Errors/NodeException.php +107 -0
- package/dist/scaffold-repo/sdks/php/src/Errors/Origin.php +35 -0
- package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/ErrorCategory.php +118 -0
- package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/ErrorSeverity.php +72 -0
- package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/ExecuteEvent.php +181 -0
- package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/ExecuteOptions.php +159 -0
- package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/ExecuteRequest.php +328 -0
- package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/ExecuteResponse.php +288 -0
- package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/HealthRequest.php +59 -0
- package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/HealthResponse/Status.php +54 -0
- package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/HealthResponse.php +113 -0
- package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/ListNodesRequest.php +32 -0
- package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/ListNodesResponse.php +154 -0
- package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/LogLine.php +156 -0
- package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/Metrics.php +165 -0
- package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/NodeDescriptor.php +174 -0
- package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/NodeError.php +627 -0
- package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/NodeRef.php +134 -0
- package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/NodeRuntimeClient.php +101 -0
- package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/NodeStarted.php +68 -0
- package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/PartialResult.php +59 -0
- package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/Progress.php +85 -0
- package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/RuntimeState.php +142 -0
- package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/StepInfo.php +168 -0
- package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/TriggerInfo.php +289 -0
- package/dist/scaffold-repo/sdks/php/src/Genpb/Blok/Runtime/V1/WorkflowInfo.php +176 -0
- package/dist/scaffold-repo/sdks/php/src/Genpb/GPBMetadata/Blok/Runtime/V1/Runtime.php +26 -0
- package/dist/scaffold-repo/sdks/php/src/Logging/LogEntry.php +47 -0
- package/dist/scaffold-repo/sdks/php/src/Logging/LogLevel.php +50 -0
- package/dist/scaffold-repo/sdks/php/src/Logging/Logger.php +133 -0
- package/dist/scaffold-repo/sdks/php/src/Node/NodeHandler.php +35 -0
- package/dist/scaffold-repo/sdks/php/src/Node/NodeReflector.php +21 -0
- package/dist/scaffold-repo/sdks/php/src/Node/NodeRegistry.php +172 -0
- package/dist/scaffold-repo/sdks/php/src/Node/TypedNode.php +159 -0
- package/dist/scaffold-repo/sdks/php/src/Server/BlokNodeRuntimeService.php +504 -0
- package/dist/scaffold-repo/sdks/php/src/Server/DecodeException.php +13 -0
- package/dist/scaffold-repo/sdks/php/src/Server/Middleware.php +18 -0
- package/dist/scaffold-repo/sdks/php/src/Server/MiddlewarePipeline.php +33 -0
- package/dist/scaffold-repo/sdks/php/src/Server/NodeRuntimeInterface.php +40 -0
- package/dist/scaffold-repo/sdks/php/src/Server/Server.php +157 -0
- package/dist/scaffold-repo/sdks/php/src/Testing/MockContext.php +161 -0
- package/dist/scaffold-repo/sdks/php/src/Testing/TestRunner.php +78 -0
- package/dist/scaffold-repo/sdks/php/src/Types/Context.php +80 -0
- package/dist/scaffold-repo/sdks/php/src/Types/ExecutionMetrics.php +48 -0
- package/dist/scaffold-repo/sdks/php/src/Types/ExecutionRequest.php +38 -0
- package/dist/scaffold-repo/sdks/php/src/Types/ExecutionResult.php +143 -0
- package/dist/scaffold-repo/sdks/php/src/Types/HealthStatus.php +42 -0
- package/dist/scaffold-repo/sdks/php/src/Types/NodeConfig.php +72 -0
- package/dist/scaffold-repo/sdks/php/src/Types/Request.php +82 -0
- package/dist/scaffold-repo/sdks/php/src/Types/Response.php +44 -0
- package/dist/scaffold-repo/sdks/php/src/Validation/SchemaValidator.php +197 -0
- package/dist/scaffold-repo/sdks/php/tests/Errors/BlokErrorTest.php +402 -0
- package/dist/scaffold-repo/sdks/php/tests/Logging/LoggerTest.php +165 -0
- package/dist/scaffold-repo/sdks/php/tests/Node/NodeRegistryTest.php +139 -0
- package/dist/scaffold-repo/sdks/php/tests/Node/TypedNodeTest.php +84 -0
- package/dist/scaffold-repo/sdks/php/tests/Server/BlokNodeRuntimeServiceTest.php +288 -0
- package/dist/scaffold-repo/sdks/php/tests/Testing/MockContextTest.php +184 -0
- package/dist/scaffold-repo/sdks/php/tests/Types/ExecutionResultTest.php +136 -0
- package/dist/scaffold-repo/sdks/php/tests/Validation/SchemaValidatorTest.php +191 -0
- package/dist/scaffold-repo/sdks/python3/Dockerfile +62 -0
- package/dist/scaffold-repo/sdks/python3/blok/__init__.py +61 -0
- package/dist/scaffold-repo/sdks/python3/blok/config/__init__.py +3 -0
- package/dist/scaffold-repo/sdks/python3/blok/config/server_config.py +116 -0
- package/dist/scaffold-repo/sdks/python3/blok/errors/__init__.py +50 -0
- package/dist/scaffold-repo/sdks/python3/blok/errors/blok_error.py +555 -0
- package/dist/scaffold-repo/sdks/python3/blok/errors/node_error.py +64 -0
- package/dist/scaffold-repo/sdks/python3/blok/logging/__init__.py +3 -0
- package/dist/scaffold-repo/sdks/python3/blok/logging/logger.py +82 -0
- package/dist/scaffold-repo/sdks/python3/blok/middleware/__init__.py +4 -0
- package/dist/scaffold-repo/sdks/python3/blok/middleware/logging_middleware.py +35 -0
- package/dist/scaffold-repo/sdks/python3/blok/middleware/recovery_middleware.py +36 -0
- package/dist/scaffold-repo/sdks/python3/blok/node/__init__.py +4 -0
- package/dist/scaffold-repo/sdks/python3/blok/node/define_node.py +239 -0
- package/dist/scaffold-repo/sdks/python3/blok/node/node_handler.py +35 -0
- package/dist/scaffold-repo/sdks/python3/blok/node/node_registry.py +136 -0
- package/dist/scaffold-repo/sdks/python3/blok/runtime/__init__.py +0 -0
- package/dist/scaffold-repo/sdks/python3/blok/runtime/v1/__init__.py +0 -0
- package/dist/scaffold-repo/sdks/python3/blok/runtime/v1/runtime_pb2.py +112 -0
- package/dist/scaffold-repo/sdks/python3/blok/runtime/v1/runtime_pb2_grpc.py +259 -0
- package/dist/scaffold-repo/sdks/python3/blok/server/__init__.py +3 -0
- package/dist/scaffold-repo/sdks/python3/blok/server/grpc_server.py +757 -0
- package/dist/scaffold-repo/sdks/python3/blok/server/runtime_server.py +165 -0
- package/dist/scaffold-repo/sdks/python3/blok/types/__init__.py +13 -0
- package/dist/scaffold-repo/sdks/python3/blok/types/context.py +162 -0
- package/dist/scaffold-repo/sdks/python3/blok/types/execution_request.py +74 -0
- package/dist/scaffold-repo/sdks/python3/blok/types/execution_result.py +103 -0
- package/dist/scaffold-repo/sdks/python3/blok/worker/__init__.py +10 -0
- package/dist/scaffold-repo/sdks/python3/blok/worker/job_message.py +34 -0
- package/dist/scaffold-repo/sdks/python3/blok/worker/worker.py +451 -0
- package/dist/scaffold-repo/sdks/python3/blok/worker/worker_config.py +129 -0
- package/dist/scaffold-repo/sdks/python3/examples/__init__.py +32 -0
- package/dist/scaffold-repo/sdks/python3/examples/api_call_node.py +85 -0
- package/dist/scaffold-repo/sdks/python3/examples/blok_error_demo_node.py +79 -0
- package/dist/scaffold-repo/sdks/python3/examples/chain_test_node.py +51 -0
- package/dist/scaffold-repo/sdks/python3/examples/hello_world_node.py +44 -0
- package/dist/scaffold-repo/sdks/python3/examples/transform_data_node.py +71 -0
- package/dist/scaffold-repo/sdks/python3/examples/typed_greet_node.py +25 -0
- package/dist/scaffold-repo/sdks/python3/proto/blok/runtime/v1/runtime.proto +302 -0
- package/dist/scaffold-repo/sdks/python3/pyproject.toml +47 -0
- package/dist/scaffold-repo/sdks/python3/requirements.txt +17 -0
- package/dist/scaffold-repo/sdks/python3/tests/__init__.py +0 -0
- package/dist/scaffold-repo/sdks/python3/tests/test_blok_error.py +341 -0
- package/dist/scaffold-repo/sdks/python3/tests/test_define_node.py +135 -0
- package/dist/scaffold-repo/sdks/python3/tests/test_discovery.py +99 -0
- package/dist/scaffold-repo/sdks/python3/tests/test_grpc_codec.py +260 -0
- package/dist/scaffold-repo/sdks/python3/tests/test_grpc_server.py +398 -0
- package/dist/scaffold-repo/sdks/ruby/Dockerfile +37 -0
- package/dist/scaffold-repo/sdks/ruby/Gemfile +5 -0
- package/dist/scaffold-repo/sdks/ruby/README.md +210 -0
- package/dist/scaffold-repo/sdks/ruby/Rakefile +11 -0
- package/dist/scaffold-repo/sdks/ruby/blok.gemspec +43 -0
- package/dist/scaffold-repo/sdks/ruby/config.ru +15 -0
- package/dist/scaffold-repo/sdks/ruby/examples/api_call_node.rb +99 -0
- package/dist/scaffold-repo/sdks/ruby/examples/blok_error_demo_node.rb +79 -0
- package/dist/scaffold-repo/sdks/ruby/examples/chain_test_node.rb +51 -0
- package/dist/scaffold-repo/sdks/ruby/examples/hello_world_node.rb +40 -0
- package/dist/scaffold-repo/sdks/ruby/examples/transform_data_node.rb +82 -0
- package/dist/scaffold-repo/sdks/ruby/examples/typed_greet_node.rb +25 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/config/server_config.rb +76 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/errors/blok_error.rb +476 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/errors/build_context_snapshot.rb +99 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/errors/error_category.rb +16 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/errors/node_error.rb +84 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/logging/log_entry.rb +46 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/logging/log_level.rb +49 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/logging/logger.rb +71 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/middleware/logging_middleware.rb +45 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/middleware/middleware.rb +36 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/middleware/recovery_middleware.rb +31 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/node/discovery.rb +59 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/node/node_handler.rb +43 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/node/node_registry.rb +107 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/node/typed_node.rb +180 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/runtime/v1/runtime_pb.rb +43 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/runtime/v1/runtime_services_pb.rb +55 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/server/grpc_server.rb +435 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/server/runtime_app.rb +86 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/testing/mock_context.rb +109 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/testing/test_runner.rb +40 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/types/context.rb +82 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/types/execution_metrics.rb +43 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/types/execution_request.rb +39 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/types/execution_result.rb +117 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/types/health_status.rb +42 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/types/node_config.rb +73 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/types/request.rb +71 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/types/response.rb +46 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/validation/schema_validator.rb +142 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok/version.rb +5 -0
- package/dist/scaffold-repo/sdks/ruby/lib/blok.rb +53 -0
- package/dist/scaffold-repo/sdks/ruby/proto/blok/runtime/v1/runtime.proto +302 -0
- package/dist/scaffold-repo/sdks/ruby/test/errors/blok_error_test.rb +339 -0
- package/dist/scaffold-repo/sdks/ruby/test/logging/logger_test.rb +155 -0
- package/dist/scaffold-repo/sdks/ruby/test/node/node_registry_test.rb +132 -0
- package/dist/scaffold-repo/sdks/ruby/test/node/typed_node_test.rb +67 -0
- package/dist/scaffold-repo/sdks/ruby/test/test_helper.rb +6 -0
- package/dist/scaffold-repo/sdks/ruby/test/testing/mock_context_test.rb +150 -0
- package/dist/scaffold-repo/sdks/ruby/test/types/execution_result_test.rb +129 -0
- package/dist/scaffold-repo/sdks/ruby/test/validation/schema_validator_test.rb +270 -0
- package/dist/scaffold-repo/sdks/rust/Cargo.lock +3044 -0
- package/dist/scaffold-repo/sdks/rust/Cargo.toml +82 -0
- package/dist/scaffold-repo/sdks/rust/Dockerfile +40 -0
- package/dist/scaffold-repo/sdks/rust/README.md +73 -0
- package/dist/scaffold-repo/sdks/rust/build.rs +32 -0
- package/dist/scaffold-repo/sdks/rust/proto/blok/runtime/v1/runtime.proto +302 -0
- package/dist/scaffold-repo/sdks/rust/src/blok_error.rs +1168 -0
- package/dist/scaffold-repo/sdks/rust/src/config.rs +158 -0
- package/dist/scaffold-repo/sdks/rust/src/errors.rs +142 -0
- package/dist/scaffold-repo/sdks/rust/src/grpc_server.rs +635 -0
- package/dist/scaffold-repo/sdks/rust/src/lib.rs +65 -0
- package/dist/scaffold-repo/sdks/rust/src/logging.rs +195 -0
- package/dist/scaffold-repo/sdks/rust/src/main.rs +79 -0
- package/dist/scaffold-repo/sdks/rust/src/middleware.rs +181 -0
- package/dist/scaffold-repo/sdks/rust/src/node.rs +172 -0
- package/dist/scaffold-repo/sdks/rust/src/nodes/api_call.rs +93 -0
- package/dist/scaffold-repo/sdks/rust/src/nodes/blok_error_demo.rs +151 -0
- package/dist/scaffold-repo/sdks/rust/src/nodes/chain_test.rs +57 -0
- package/dist/scaffold-repo/sdks/rust/src/nodes/hello_world.rs +83 -0
- package/dist/scaffold-repo/sdks/rust/src/nodes/mod.rs +18 -0
- package/dist/scaffold-repo/sdks/rust/src/nodes/transform_data.rs +142 -0
- package/dist/scaffold-repo/sdks/rust/src/nodes/typed_greet.rs +56 -0
- package/dist/scaffold-repo/sdks/rust/src/registry.rs +204 -0
- package/dist/scaffold-repo/sdks/rust/src/server.rs +63 -0
- package/dist/scaffold-repo/sdks/rust/src/testing.rs +175 -0
- package/dist/scaffold-repo/sdks/rust/src/types.rs +338 -0
- package/dist/scaffold-repo/sdks/rust/src/user_nodes/mod.rs +10 -0
- package/dist/scaffold-repo/sdks/rust/src/validation.rs +232 -0
- package/dist/scaffold-repo/sdks/rust/src/worker.rs +509 -0
- package/dist/scaffold-repo/sdks/rust/tests/grpc_integration.rs +306 -0
- package/dist/scaffold-repo/sdks/rust/tests/typed_node.rs +104 -0
- package/dist/scaffold-repo/triggers/cron/CHANGELOG.md +22 -0
- package/dist/scaffold-repo/triggers/cron/package.json +36 -0
- package/dist/scaffold-repo/triggers/cron/src/CronTrigger.ts +552 -0
- package/dist/scaffold-repo/triggers/cron/src/index.ts +77 -0
- package/dist/scaffold-repo/triggers/cron/tsconfig.json +32 -0
- package/dist/scaffold-repo/triggers/grpc/.env.example +8 -0
- package/dist/scaffold-repo/triggers/grpc/CHANGELOG.md +143 -0
- package/dist/scaffold-repo/triggers/grpc/README.md +25 -0
- package/dist/scaffold-repo/triggers/grpc/buf.gen.yaml +11 -0
- package/dist/scaffold-repo/triggers/grpc/buf.yaml +9 -0
- package/dist/scaffold-repo/triggers/grpc/localhost+2-key.pem +28 -0
- package/dist/scaffold-repo/triggers/grpc/localhost+2.pem +27 -0
- package/dist/scaffold-repo/triggers/grpc/package.json +61 -0
- package/dist/scaffold-repo/triggers/grpc/proto/workflow.proto +33 -0
- package/dist/scaffold-repo/triggers/grpc/src/GRpcTrigger.ts +297 -0
- package/dist/scaffold-repo/triggers/grpc/src/GrpcClient.ts +87 -0
- package/dist/scaffold-repo/triggers/grpc/src/GrpcServer.ts +68 -0
- package/dist/scaffold-repo/triggers/grpc/src/MessageDecode.ts +142 -0
- package/dist/scaffold-repo/triggers/grpc/src/NanoSDK.ts +146 -0
- package/dist/scaffold-repo/triggers/grpc/src/Nodes.ts +10 -0
- package/dist/scaffold-repo/triggers/grpc/src/Workflows.ts +5 -0
- package/dist/scaffold-repo/triggers/grpc/src/gen/workflow_pb.ts +142 -0
- package/dist/scaffold-repo/triggers/grpc/src/index.ts +22 -0
- package/dist/scaffold-repo/triggers/grpc/src/server.ts +8 -0
- package/dist/scaffold-repo/triggers/grpc/src/types/Message.ts +0 -0
- package/dist/scaffold-repo/triggers/grpc/src/types/RuntimeWorkflow.ts +7 -0
- package/dist/scaffold-repo/triggers/grpc/src/types/Workflows.ts +7 -0
- package/dist/scaffold-repo/triggers/grpc/tsconfig.json +34 -0
- package/dist/scaffold-repo/triggers/grpc/vitest.config.ts +29 -0
- package/dist/scaffold-repo/triggers/grpc/workflows/countries.json +27 -0
- package/dist/scaffold-repo/triggers/http/.blok/trace.db +0 -0
- package/dist/scaffold-repo/triggers/http/.blok/trace.db-shm +0 -0
- package/dist/scaffold-repo/triggers/http/.blok/trace.db-wal +0 -0
- package/dist/scaffold-repo/triggers/http/.dockerignore +23 -0
- package/dist/scaffold-repo/triggers/http/.env.example +8 -0
- package/dist/scaffold-repo/triggers/http/CHANGELOG.md +326 -0
- package/dist/scaffold-repo/triggers/http/Dockerfile +49 -0
- package/dist/scaffold-repo/triggers/http/Dockerfile.dev +34 -0
- package/dist/scaffold-repo/triggers/http/infra/docker-compose.yml +38 -0
- package/dist/scaffold-repo/triggers/http/notes/CLI_Commands/Authentication.md +74 -0
- package/dist/scaffold-repo/triggers/http/notes/CLI_Commands/Building.md +52 -0
- package/dist/scaffold-repo/triggers/http/notes/CLI_Commands/Create_Node.md +123 -0
- package/dist/scaffold-repo/triggers/http/notes/CLI_Commands/Create_Workflow.md +177 -0
- package/dist/scaffold-repo/triggers/http/notes/CLI_Commands/Deployment.md +69 -0
- package/dist/scaffold-repo/triggers/http/notes/Core_Concepts/Context.md +156 -0
- package/dist/scaffold-repo/triggers/http/notes/examples.md +104 -0
- package/dist/scaffold-repo/triggers/http/notes/index.md +51 -0
- package/dist/scaffold-repo/triggers/http/package.json +62 -0
- package/dist/scaffold-repo/triggers/http/public/favicon.ico +0 -0
- package/dist/scaffold-repo/triggers/http/public/metric/index.html +2101 -0
- package/dist/scaffold-repo/triggers/http/request.http +7 -0
- package/dist/scaffold-repo/triggers/http/src/AppRoutes.ts +64 -0
- package/dist/scaffold-repo/triggers/http/src/Nodes.ts +38 -0
- package/dist/scaffold-repo/triggers/http/src/Workflows.ts +18 -0
- package/dist/scaffold-repo/triggers/http/src/index.ts +86 -0
- package/dist/scaffold-repo/triggers/http/src/nodes/chain-init/index.ts +48 -0
- package/dist/scaffold-repo/triggers/http/src/nodes/chain-verify/index.ts +123 -0
- package/dist/scaffold-repo/triggers/http/src/nodes/eval/index.ts +69 -0
- package/dist/scaffold-repo/triggers/http/src/nodes/examples/README.md +14 -0
- package/dist/scaffold-repo/triggers/http/src/nodes/examples/chat-ui/index.html +228 -0
- package/dist/scaffold-repo/triggers/http/src/nodes/examples/chat-ui/index.ts +65 -0
- package/dist/scaffold-repo/triggers/http/src/nodes/examples/index.ts +14 -0
- package/dist/scaffold-repo/triggers/http/src/nodes/runtime-bridge/index.ts +84 -0
- package/dist/scaffold-repo/triggers/http/src/runner/HonoTraceRouterAdapter.ts +199 -0
- package/dist/scaffold-repo/triggers/http/src/runner/HttpTrigger.ts +2039 -0
- package/dist/scaffold-repo/triggers/http/src/runner/MessageDecode.ts +57 -0
- package/dist/scaffold-repo/triggers/http/src/runner/Util.ts +52 -0
- package/dist/scaffold-repo/triggers/http/src/runner/WorkflowRouter.ts +411 -0
- package/dist/scaffold-repo/triggers/http/src/runner/metrics/opentelemetry_metrics.ts +84 -0
- package/dist/scaffold-repo/triggers/http/src/runner/metrics/opentelemetry_traces.ts +30 -0
- package/dist/scaffold-repo/triggers/http/src/runner/nodeCatalog.ts +128 -0
- package/dist/scaffold-repo/triggers/http/src/runner/responseEmitter.ts +138 -0
- package/dist/scaffold-repo/triggers/http/src/runner/scanWorkflows.ts +201 -0
- package/dist/scaffold-repo/triggers/http/src/runner/types/ErrorResponse.ts +3 -0
- package/dist/scaffold-repo/triggers/http/src/runner/types/NodeTypes.ts +13 -0
- package/dist/scaffold-repo/triggers/http/src/runner/types/Nodes.ts +5 -0
- package/dist/scaffold-repo/triggers/http/src/runner/types/RuntimeWorkflow.ts +7 -0
- package/dist/scaffold-repo/triggers/http/src/runner/types/WorkflowRequest.ts +8 -0
- package/dist/scaffold-repo/triggers/http/src/runner/types/WorkflowResponse.ts +7 -0
- package/dist/scaffold-repo/triggers/http/src/runner/types/Workflows.ts +14 -0
- package/dist/scaffold-repo/triggers/http/src/workflows/countries-cats-helper.ts +30 -0
- package/dist/scaffold-repo/triggers/http/src/workflows/countries-handle-dsl.ts +25 -0
- package/dist/scaffold-repo/triggers/http/src/workflows/countries-helper.ts +18 -0
- package/dist/scaffold-repo/triggers/http/src/workflows/empty.ts +16 -0
- package/dist/scaffold-repo/triggers/http/src/workflows/eval/eval-retrieve.ts +23 -0
- package/dist/scaffold-repo/triggers/http/src/workflows/eval/eval-run.ts +39 -0
- package/dist/scaffold-repo/triggers/http/src/workflows/eval/foreign-auth.ts +24 -0
- package/dist/scaffold-repo/triggers/http/tsconfig.json +39 -0
- package/dist/scaffold-repo/triggers/http/vitest.config.ts +39 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/agent-message.json +87 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/agent-page.json +25 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/agent-stream.json +30 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/agent-tool-calculator.json +22 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/agent-tool-weather.json +22 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/chat-memory-message.json +54 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/chat-memory-page.json +25 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/chat-memory-stream.json +30 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/chat-message.json +25 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/chat-page.json +20 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/chat-stream.json +30 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/countries-py.json +27 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/countries-vs-facts.json +50 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/countries.json +27 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/cross-runtime-chain.json +89 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/dashboard-gen.json +34 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/db-manager.json +34 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/empty.json +13 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/fanout-enqueue.json +48 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/fanout-worker.json +41 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/feedback.json +34 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/films.json +27 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/image-capture.json +34 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/launches-by-year.json +27 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/loadtest.json +24 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/middleware/admin-only.json +31 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/middleware/auth-check.json +59 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/middleware/github-webhook-verify.json +34 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/middleware/jwt-auth.json +46 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/middleware/rate-limit.json +70 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/middleware/redis-rate-limit.json +71 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/mongodb.json +24 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/rentals-pdf.json +65 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v05-admin-delete-user.json +42 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v05-async-job-poller.json +45 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v05-csv-import.json +122 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v05-data-export.json +105 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v05-event-router.json +97 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v05-github-handler-issues.json +22 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v05-github-handler-pr.json +22 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v05-github-handler-push.json +22 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v05-github-webhook-router.json +88 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v05-hello-global-mw.json +22 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v05-hello-with-mw.json +23 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v05-jwt-protected.json +23 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v05-multi-tenant-router.json +90 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v05-nested-control-flow.json +207 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v05-order-fulfillment.json +211 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v05-parallel-foreach-with-wait.json +47 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v05-polling-with-backoff.json +55 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v05-protected.json +23 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v05-redis-protected.json +23 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v05-saga.json +122 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v05-tenant-acme.json +22 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v05-tenant-beta.json +22 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v05-tenant-gamma.json +22 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v05-travel-booking.json +200 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v05-user-signup-saga.json +186 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v05-webhook-fanout.json +49 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v06-reliability-showcase.json +80 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v07-sse-publish.json +24 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v07-sse-stream.json +26 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/v07-ws-echo.json +38 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/webhook-github-issues.json +22 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/webhook-github-pr.json +22 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/webhook-github-push.json +32 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/webhook-github.json +87 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/webhook-linear-comment.json +22 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/webhook-linear-issue.json +22 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/webhook-linear.json +74 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/webhook-stripe-customer-created.json +22 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/webhook-stripe-invoice-paid.json +32 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/webhook-stripe.json +24 -0
- package/dist/scaffold-repo/triggers/http/workflows/json/workflow-docs.json +34 -0
- package/dist/scaffold-repo/triggers/http/workflows/toml/countries.toml +21 -0
- package/dist/scaffold-repo/triggers/http/workflows/xml/countries.xml +23 -0
- package/dist/scaffold-repo/triggers/http/workflows/yaml/countries.yaml +19 -0
- package/dist/scaffold-repo/triggers/mcp/README.md +131 -0
- package/dist/scaffold-repo/triggers/mcp/package.json +39 -0
- package/dist/scaffold-repo/triggers/mcp/src/McpTrigger.ts +581 -0
- package/dist/scaffold-repo/triggers/mcp/src/index.ts +41 -0
- package/dist/scaffold-repo/triggers/mcp/tsconfig.json +32 -0
- package/dist/scaffold-repo/triggers/pubsub/CHANGELOG.md +22 -0
- package/dist/scaffold-repo/triggers/pubsub/package.json +66 -0
- package/dist/scaffold-repo/triggers/pubsub/src/PubSubTrigger.ts +424 -0
- package/dist/scaffold-repo/triggers/pubsub/src/adapters/AWSSNSAdapter.ts +352 -0
- package/dist/scaffold-repo/triggers/pubsub/src/adapters/AzureServiceBusAdapter.ts +303 -0
- package/dist/scaffold-repo/triggers/pubsub/src/adapters/GCPPubSubAdapter.ts +327 -0
- package/dist/scaffold-repo/triggers/pubsub/src/adapters/KafkaPubSubAdapter.ts +247 -0
- package/dist/scaffold-repo/triggers/pubsub/src/adapters/KafkaPubSubAdapter.ts.bak +251 -0
- package/dist/scaffold-repo/triggers/pubsub/src/adapters/NATSPubSubAdapter.ts +333 -0
- package/dist/scaffold-repo/triggers/pubsub/src/adapters/RedisStreamsPubSubAdapter.ts +256 -0
- package/dist/scaffold-repo/triggers/pubsub/src/adapters/factory.ts +88 -0
- package/dist/scaffold-repo/triggers/pubsub/src/index.ts +67 -0
- package/dist/scaffold-repo/triggers/pubsub/template/.env.example +8 -0
- package/dist/scaffold-repo/triggers/pubsub/template/package.json +45 -0
- package/dist/scaffold-repo/triggers/pubsub/template/src/Nodes.ts +20 -0
- package/dist/scaffold-repo/triggers/pubsub/template/src/Workflows.ts +8 -0
- package/dist/scaffold-repo/triggers/pubsub/template/src/index.ts +41 -0
- package/dist/scaffold-repo/triggers/pubsub/template/src/runner/PubSubServer.ts +39 -0
- package/dist/scaffold-repo/triggers/pubsub/template/src/runner/types/Workflows.ts +7 -0
- package/dist/scaffold-repo/triggers/pubsub/template/src/workflows/messages/on-message.ts +42 -0
- package/dist/scaffold-repo/triggers/pubsub/template/src/workflows/publish-order.ts +22 -0
- package/dist/scaffold-repo/triggers/pubsub/template/tsconfig.json +31 -0
- package/dist/scaffold-repo/triggers/pubsub/template/vitest.config.ts +39 -0
- package/dist/scaffold-repo/triggers/pubsub/tsconfig.json +32 -0
- package/dist/scaffold-repo/triggers/sse/.env.example +8 -0
- package/dist/scaffold-repo/triggers/sse/CHANGELOG.md +12 -0
- package/dist/scaffold-repo/triggers/sse/Dockerfile +47 -0
- package/dist/scaffold-repo/triggers/sse/Dockerfile.dev +33 -0
- package/dist/scaffold-repo/triggers/sse/package.json +37 -0
- package/dist/scaffold-repo/triggers/sse/src/SSETrigger.ts +489 -0
- package/dist/scaffold-repo/triggers/sse/src/bus.ts +208 -0
- package/dist/scaffold-repo/triggers/sse/src/index.ts +38 -0
- package/dist/scaffold-repo/triggers/sse/src/workflows/events/README.md +129 -0
- package/dist/scaffold-repo/triggers/sse/src/workflows/events/publish-demo.ts +40 -0
- package/dist/scaffold-repo/triggers/sse/src/workflows/events/stream-demo.ts +43 -0
- package/dist/scaffold-repo/triggers/sse/tsconfig.json +22 -0
- package/dist/scaffold-repo/triggers/sse/vitest.config.ts +39 -0
- package/dist/scaffold-repo/triggers/webhook/CHANGELOG.md +22 -0
- package/dist/scaffold-repo/triggers/webhook/package.json +36 -0
- package/dist/scaffold-repo/triggers/webhook/src/WebhookTrigger.ts +465 -0
- package/dist/scaffold-repo/triggers/webhook/src/index.ts +51 -0
- package/dist/scaffold-repo/triggers/webhook/src/verifiers.ts +394 -0
- package/dist/scaffold-repo/triggers/webhook/tsconfig.json +32 -0
- package/dist/scaffold-repo/triggers/websocket/.env.example +8 -0
- package/dist/scaffold-repo/triggers/websocket/CHANGELOG.md +22 -0
- package/dist/scaffold-repo/triggers/websocket/package.json +50 -0
- package/dist/scaffold-repo/triggers/websocket/src/Backplane.ts +167 -0
- package/dist/scaffold-repo/triggers/websocket/src/WebSocketTrigger.ts +910 -0
- package/dist/scaffold-repo/triggers/websocket/src/index.ts +50 -0
- package/dist/scaffold-repo/triggers/websocket/src/workflows/events/README.md +93 -0
- package/dist/scaffold-repo/triggers/websocket/src/workflows/events/echo-demo.ts +56 -0
- package/dist/scaffold-repo/triggers/websocket/tsconfig.json +22 -0
- package/dist/scaffold-repo/triggers/websocket/vitest.config.ts +39 -0
- package/dist/scaffold-repo/triggers/worker/CHANGELOG.md +22 -0
- package/dist/scaffold-repo/triggers/worker/package.json +68 -0
- package/dist/scaffold-repo/triggers/worker/src/WorkerTrigger.ts +943 -0
- package/dist/scaffold-repo/triggers/worker/src/adapters/BullMQAdapter.ts +296 -0
- package/dist/scaffold-repo/triggers/worker/src/adapters/InMemoryAdapter.ts +280 -0
- package/dist/scaffold-repo/triggers/worker/src/adapters/KafkaAdapter.ts +347 -0
- package/dist/scaffold-repo/triggers/worker/src/adapters/NATSAdapter.ts +505 -0
- package/dist/scaffold-repo/triggers/worker/src/adapters/PgBossAdapter.ts +319 -0
- package/dist/scaffold-repo/triggers/worker/src/adapters/RabbitMQAdapter.ts +318 -0
- package/dist/scaffold-repo/triggers/worker/src/adapters/RedisStreamsAdapter.ts +513 -0
- package/dist/scaffold-repo/triggers/worker/src/adapters/SQSAdapter.ts +314 -0
- package/dist/scaffold-repo/triggers/worker/src/adapters/factory.ts +111 -0
- package/dist/scaffold-repo/triggers/worker/src/index.ts +95 -0
- package/dist/scaffold-repo/triggers/worker/template/.env.example +18 -0
- package/dist/scaffold-repo/triggers/worker/template/package.json +46 -0
- package/dist/scaffold-repo/triggers/worker/template/src/Nodes.ts +20 -0
- package/dist/scaffold-repo/triggers/worker/template/src/Workflows.ts +8 -0
- package/dist/scaffold-repo/triggers/worker/template/src/index.ts +41 -0
- package/dist/scaffold-repo/triggers/worker/template/src/runner/WorkerServer.ts +34 -0
- package/dist/scaffold-repo/triggers/worker/template/src/runner/types/Workflows.ts +7 -0
- package/dist/scaffold-repo/triggers/worker/template/src/workflows/jobs/process-job.ts +40 -0
- package/dist/scaffold-repo/triggers/worker/template/tsconfig.json +31 -0
- package/dist/scaffold-repo/triggers/worker/template/vitest.config.ts +39 -0
- package/dist/scaffold-repo/triggers/worker/tsconfig.json +32 -0
- package/dist/scaffold-repo/workflows/json/agent-message.json +87 -0
- package/dist/scaffold-repo/workflows/json/agent-page.json +25 -0
- package/dist/scaffold-repo/workflows/json/agent-stream.json +30 -0
- package/dist/scaffold-repo/workflows/json/agent-tool-calculator.json +22 -0
- package/dist/scaffold-repo/workflows/json/agent-tool-weather.json +22 -0
- package/dist/scaffold-repo/workflows/json/chat-memory-message.json +54 -0
- package/dist/scaffold-repo/workflows/json/chat-memory-page.json +25 -0
- package/dist/scaffold-repo/workflows/json/chat-memory-stream.json +30 -0
- package/dist/scaffold-repo/workflows/json/chat-message.json +25 -0
- package/dist/scaffold-repo/workflows/json/chat-page.json +20 -0
- package/dist/scaffold-repo/workflows/json/chat-stream.json +30 -0
- package/dist/scaffold-repo/workflows/json/countries-vs-facts.json +50 -0
- package/dist/scaffold-repo/workflows/json/countries.json +27 -0
- package/dist/scaffold-repo/workflows/json/cron-heartbeat.json +15 -0
- package/dist/scaffold-repo/workflows/json/fanout-enqueue.json +48 -0
- package/dist/scaffold-repo/workflows/json/fanout-worker.json +41 -0
- package/dist/scaffold-repo/workflows/json/pubsub-on-order.json +24 -0
- package/dist/scaffold-repo/workflows/json/webhook-github-issues.json +22 -0
- package/dist/scaffold-repo/workflows/json/webhook-github-pr.json +22 -0
- package/dist/scaffold-repo/workflows/json/webhook-github-push.json +32 -0
- package/dist/scaffold-repo/workflows/json/webhook-github.json +87 -0
- package/dist/scaffold-repo/workflows/json/webhook-linear-comment.json +22 -0
- package/dist/scaffold-repo/workflows/json/webhook-linear-issue.json +22 -0
- package/dist/scaffold-repo/workflows/json/webhook-linear.json +74 -0
- package/dist/scaffold-repo/workflows/json/webhook-stripe-customer-created.json +22 -0
- package/dist/scaffold-repo/workflows/json/webhook-stripe-invoice-paid.json +32 -0
- package/dist/scaffold-repo/workflows/json/webhook-stripe.json +24 -0
- package/dist/services/runtime-detector.d.ts +2 -0
- package/dist/services/runtime-detector.js +35 -11
- package/dist/services/runtime-setup.d.ts +1 -0
- package/dist/services/runtime-setup.js +17 -7
- 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
|
+
)
|