blokctl 1.4.0 → 1.5.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.
@@ -23,7 +23,7 @@ const exec = util.promisify(child_process.exec);
23
23
  const HOME_DIR = `${os.homedir()}/.blok`;
24
24
  const GITHUB_REPO_LOCAL = `${HOME_DIR}/blok`;
25
25
  const GITHUB_REPO_REMOTE = "https://github.com/well-prado/blok.git";
26
- const GITHUB_REPO_RELEASE_TAG = "v1.4.0";
26
+ const GITHUB_REPO_RELEASE_TAG = "v1.5.0";
27
27
  const BUNDLED_SCAFFOLD_REPO = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../scaffold-repo");
28
28
  const RUNTIME_HELLO_EXAMPLES = {
29
29
  go: "runtime-go-hello.ts",
@@ -564,7 +564,7 @@ export async function createProject(opts, version, currentPath = false, localRep
564
564
  "@blokjs/trigger-worker": "triggers/worker",
565
565
  "@blokjs/core": "core/core",
566
566
  };
567
- const BLOKJS_DEP_RANGE = "^1.4.0";
567
+ const BLOKJS_DEP_RANGE = "^1.5.0";
568
568
  for (const depGroup of ["dependencies", "devDependencies", "peerDependencies"]) {
569
569
  const deps = packageJsonContent[depGroup];
570
570
  if (!deps)
@@ -0,0 +1,95 @@
1
+ <?php
2
+
3
+ declare(strict_types=1);
4
+
5
+ require_once __DIR__ . '/../vendor/autoload.php';
6
+
7
+ use Blok\Blok\Config\ServerConfig;
8
+ use Blok\Blok\Config\Transport;
9
+ use Blok\Blok\Examples\ApiCallNode;
10
+ use Blok\Blok\Examples\BlokErrorDemoNode;
11
+ use Blok\Blok\Examples\ChainTestNode;
12
+ use Blok\Blok\Examples\HelloWorldNode;
13
+ use Blok\Blok\Examples\TransformDataNode;
14
+ use Blok\Blok\Examples\TypedGreetNode;
15
+ use Blok\Blok\Node\NodeHandler;
16
+ use Blok\Blok\Node\NodeRegistry;
17
+ use Blok\Blok\Server\BlokNodeRuntimeService;
18
+ use Blok\Blok\Server\NodeRuntimeInterface;
19
+ use Blok\Blok\Server\Server;
20
+ use Spiral\RoadRunner\GRPC\Server as GrpcServer;
21
+
22
+ $config = ServerConfig::fromEnv();
23
+
24
+ $registry = new NodeRegistry($config->version);
25
+ $registry->register('hello-world', new HelloWorldNode());
26
+ $registry->register('api-call', new ApiCallNode());
27
+ $registry->register('transform-data', new TransformDataNode());
28
+ $registry->register('chain-test', new ChainTestNode());
29
+ $registry->register('blok-error-demo', new BlokErrorDemoNode());
30
+ $registry->register('typed-greet', new TypedGreetNode());
31
+
32
+ // Discover user nodes scaffolded under runtimes/php/nodes/ (mirrors Python's
33
+ // BLOK_NODES_DIR scan). The CLI sets BLOK_NODES_DIR; each node lives at
34
+ // <dir>/<name>/src/Nodes/<Pascal>Node.php with class
35
+ // Blok\Blok\Nodes\<Pascal>\<Pascal>Node implementing NodeHandler, registered
36
+ // under its directory name. require_once is enough — nodes use the SDK's
37
+ // already-autoloaded classes, so no composer-autoloader merge is needed.
38
+ $nodesDir = getenv('BLOK_NODES_DIR') ?: '';
39
+ if ($nodesDir !== '' && is_dir($nodesDir)) {
40
+ $discovered = 0;
41
+ foreach (glob($nodesDir . '/*/src/Nodes/*Node.php') ?: [] as $file) {
42
+ // ponytail: name = the node's top dir; convention class lives under it.
43
+ $name = basename(dirname($file, 3));
44
+ $pascal = str_replace(' ', '', ucwords(str_replace(['-', '_'], ' ', $name)));
45
+ $class = "Blok\\Blok\\Nodes\\{$pascal}\\{$pascal}Node";
46
+
47
+ require_once $file;
48
+ if (!class_exists($class)) {
49
+ fwrite(STDERR, sprintf("[blok] skipping user node '%s': class %s not found\n", $name, $class));
50
+ continue;
51
+ }
52
+ $handler = new $class();
53
+ if (!$handler instanceof NodeHandler) {
54
+ fwrite(STDERR, sprintf("[blok] skipping user node '%s': %s does not implement NodeHandler\n", $name, $class));
55
+ continue;
56
+ }
57
+ $registry->register($name, $handler);
58
+ $discovered++;
59
+ }
60
+ if ($discovered > 0) {
61
+ fwrite(STDERR, sprintf("Discovered %d user node(s) from %s\n", $discovered, $nodesDir));
62
+ }
63
+ }
64
+
65
+ fwrite(
66
+ STDERR,
67
+ sprintf("Registered %d nodes: %s\n", $registry->count(), implode(', ', $registry->nodeNames())),
68
+ );
69
+
70
+ switch ($config->transport) {
71
+ case Transport::Grpc:
72
+ // Worker mode: the RoadRunner daemon (started via `rr serve -c .rr.yaml`)
73
+ // handles HTTP/2 + gRPC framing in Go and dispatches each call to this
74
+ // PHP worker over goridge pipes. Server::serve() blocks reading payloads
75
+ // from stdin until rr signals shutdown.
76
+ $service = new BlokNodeRuntimeService($registry, sdkVersion: $config->version);
77
+ $server = new GrpcServer();
78
+ $server->registerService(NodeRuntimeInterface::class, $service);
79
+ fwrite(STDERR, "Blok PHP gRPC worker entering spiral/roadrunner-grpc loop\n");
80
+ $server->serve();
81
+ break;
82
+
83
+ case Transport::Both:
84
+ // PHP cannot run two transports in one process without OS threads.
85
+ // Operators run `rr serve` (gRPC) and `php bin/serve.php` (HTTP) side
86
+ // by side; here we fall through to HTTP so this command still serves
87
+ // half the matrix on its own.
88
+ fwrite(STDERR, "BLOK_TRANSPORT=both: this process serves HTTP only; run `rr serve -c .rr.yaml` separately for gRPC\n");
89
+ // intentional fallthrough
90
+ case Transport::Http:
91
+ default:
92
+ $server = new Server($registry, $config);
93
+ $server->start();
94
+ break;
95
+ }
@@ -0,0 +1,174 @@
1
+ #!/usr/bin/env python3
2
+ """Entry point for the Blok blok Python3 runtime server.
3
+
4
+ Usage:
5
+ python bin/serve.py
6
+
7
+ Environment variables:
8
+ PORT HTTP port (default: 9007)
9
+ HOST Bind address (default: 0.0.0.0)
10
+ VERSION Runtime version (default: 1.0.0)
11
+ GRPC_PORT gRPC port (default: 10007)
12
+ BLOK_TRANSPORT "http" | "grpc" | "both" (default: "http")
13
+ LOG_LEVEL DEBUG | INFO | WARN | ERROR (default: INFO)
14
+ ENABLE_CORS true / false (default: false)
15
+ BLOK_GRPC_MAX_MESSAGE_BYTES Max gRPC message size, send+recv (default: 16777216).
16
+ Must match the runner client + other sidecars.
17
+ BLOK_NODES_DIR Directory of user-authored nodes to discover (each node in
18
+ a `<name>/node.py` using the `@node` decorator). Set by
19
+ blokctl to the project's `runtimes/python3/nodes`. When
20
+ unset, only the SDK's built-in example nodes load.
21
+ """
22
+
23
+ import logging
24
+ import os
25
+ import signal
26
+ import sys
27
+ import threading
28
+
29
+ # Add the SDK root to the path so imports work
30
+ sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
31
+
32
+ from blok.config.server_config import ServerConfig
33
+ from blok.middleware.logging_middleware import logging_middleware
34
+ from blok.middleware.recovery_middleware import recovery_middleware
35
+ from blok.node.node_registry import NodeRegistry
36
+ from blok.server.runtime_server import RuntimeServer
37
+ from examples import register_all
38
+
39
+
40
+ def _start_http(registry: NodeRegistry, config: ServerConfig) -> RuntimeServer:
41
+ """Start the HTTP runtime server in the calling thread.
42
+
43
+ Returns the started server so the caller can stop it cleanly.
44
+ """
45
+ server = RuntimeServer(registry, config)
46
+ server.start()
47
+ return server
48
+
49
+
50
+ def _start_grpc(registry: NodeRegistry, config: ServerConfig):
51
+ """Start the gRPC runtime server. Lazy-imports grpcio so the base SDK
52
+ install doesn't pull it in unless `BLOK_TRANSPORT` selects gRPC.
53
+
54
+ Returns the started ``grpc.Server`` instance.
55
+ """
56
+ try:
57
+ from blok.server.grpc_server import serve_grpc
58
+ except ImportError as exc: # pragma: no cover — depends on optional install
59
+ logging.error(
60
+ "BLOK_TRANSPORT=%s requires grpcio. Install with: pip install 'blok-blok-python3[grpc]'",
61
+ config.transport,
62
+ )
63
+ raise SystemExit(1) from exc
64
+
65
+ # Max gRPC message size (decode + encode), default 16 MiB. MUST match the
66
+ # runner client's BLOK_GRPC_MAX_MESSAGE_BYTES and the other sidecars — a
67
+ # client-only raise leaves this server rejecting oversized messages with
68
+ # RESOURCE_EXHAUSTED. Invalid / non-positive falls back to the default.
69
+ default_max = 16 * 1024 * 1024
70
+ try:
71
+ max_message_bytes = int(os.environ.get("BLOK_GRPC_MAX_MESSAGE_BYTES", default_max))
72
+ if max_message_bytes <= 0:
73
+ max_message_bytes = default_max
74
+ except (TypeError, ValueError):
75
+ max_message_bytes = default_max
76
+
77
+ return serve_grpc(
78
+ registry,
79
+ port=config.grpc_port,
80
+ host=config.host,
81
+ sdk_version=config.version,
82
+ max_message_bytes=max_message_bytes,
83
+ )
84
+
85
+
86
+ def _load_user_nodes(registry: NodeRegistry) -> int:
87
+ """Discover user nodes from ``BLOK_NODES_DIR`` (delegates to the SDK).
88
+
89
+ `@node` authoring requires pydantic; if it isn't installed there are no
90
+ user nodes to load, so a missing import is a no-op.
91
+ """
92
+ try:
93
+ from blok.node.define_node import load_user_nodes
94
+ except ImportError:
95
+ return 0
96
+ return load_user_nodes(registry, os.environ.get("BLOK_NODES_DIR"))
97
+
98
+
99
+ def main():
100
+ config = ServerConfig.from_env()
101
+
102
+ log_level = getattr(logging, config.log_level, logging.INFO)
103
+ logging.basicConfig(
104
+ level=log_level,
105
+ format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
106
+ stream=sys.stdout,
107
+ )
108
+
109
+ registry = NodeRegistry(version=config.version)
110
+ register_all(registry)
111
+ user_node_count = _load_user_nodes(registry)
112
+ registry.use(recovery_middleware)
113
+ registry.use(logging_middleware)
114
+
115
+ transport = config.transport
116
+ log = logging.getLogger("blok.serve")
117
+ log.info(
118
+ "Blok Python3 SDK starting (transport=%s, http_port=%d, grpc_port=%d, %d nodes, %d user)",
119
+ transport,
120
+ config.port,
121
+ config.grpc_port,
122
+ len(registry.node_names()),
123
+ user_node_count,
124
+ )
125
+
126
+ if transport == "http":
127
+ _start_http(registry, config)
128
+ return
129
+
130
+ if transport == "grpc":
131
+ grpc_server = _start_grpc(registry, config)
132
+ _block_until_signal_then_stop(grpc=grpc_server, http=None)
133
+ return
134
+
135
+ if transport == "both":
136
+ # Start gRPC in background, HTTP in foreground (HTTP server's
137
+ # ``start()`` blocks until shutdown). On signal we stop gRPC, then
138
+ # the HTTP server unwinds.
139
+ grpc_server = _start_grpc(registry, config)
140
+ http_thread = threading.Thread(
141
+ target=_start_http,
142
+ args=(registry, config),
143
+ daemon=True,
144
+ name="blok-http",
145
+ )
146
+ http_thread.start()
147
+ _block_until_signal_then_stop(grpc=grpc_server, http=None)
148
+ return
149
+
150
+ log.error("Unknown BLOK_TRANSPORT=%r — expected http | grpc | both", transport)
151
+ sys.exit(1)
152
+
153
+
154
+ def _block_until_signal_then_stop(*, grpc, http) -> None:
155
+ """Block on SIGINT/SIGTERM, then stop the gRPC server (and HTTP if owned)."""
156
+ stop_event = threading.Event()
157
+
158
+ def _handler(signum, _frame):
159
+ logging.getLogger("blok.serve").info("Received signal %d, shutting down…", signum)
160
+ stop_event.set()
161
+
162
+ signal.signal(signal.SIGINT, _handler)
163
+ signal.signal(signal.SIGTERM, _handler)
164
+ stop_event.wait()
165
+
166
+ if grpc is not None:
167
+ grpc.stop(grace=3.0)
168
+ # The HTTP server in dual-listen runs in a daemon thread; it tears down
169
+ # automatically on process exit. ``http`` is reserved for future shapes
170
+ # (e.g. promoting HTTP into a stoppable abstraction).
171
+
172
+
173
+ if __name__ == "__main__":
174
+ main()
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env python3
2
+ """Entry point for the Blok NATS JetStream worker.
3
+
4
+ Usage:
5
+ python bin/worker.py
6
+
7
+ Environment variables:
8
+ NATS_SERVERS - Comma-separated NATS server URLs (default: localhost:4222)
9
+ NATS_TOKEN - Authentication token (optional)
10
+ NATS_USER - Username (optional)
11
+ NATS_PASS - Password (optional)
12
+ NATS_STREAM_NAME - JetStream stream name (default: blok-worker)
13
+ WORKER_CONCURRENCY - Max concurrent jobs (default: 1)
14
+ WORKER_MAX_RETRIES - Max delivery attempts (default: 3)
15
+ WORKER_ACK_WAIT_SECS - Job timeout in seconds (default: 30)
16
+ WORKER_QUEUES - Comma-separated queue names
17
+ PORT - HTTP health server port (default: 8080)
18
+ VERSION - Runtime version (default: 1.0.0)
19
+ LOG_LEVEL - Log level: DEBUG, INFO, WARN, ERROR (default: INFO)
20
+ """
21
+
22
+ import logging
23
+ import os
24
+ import sys
25
+
26
+ # Add the SDK root to the path so imports work
27
+ sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
28
+
29
+ from blok.config.server_config import ServerConfig
30
+ from blok.middleware.logging_middleware import logging_middleware
31
+ from blok.middleware.recovery_middleware import recovery_middleware
32
+ from blok.node.node_registry import NodeRegistry
33
+ from blok.worker import listen_and_serve_worker
34
+ from examples import register_all
35
+
36
+
37
+ def main():
38
+ # Configure logging
39
+ config = ServerConfig.from_env()
40
+ log_level = getattr(logging, config.log_level, logging.INFO)
41
+ logging.basicConfig(
42
+ level=log_level,
43
+ format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
44
+ stream=sys.stdout,
45
+ )
46
+
47
+ # Create registry and register nodes
48
+ registry = NodeRegistry(version=config.version)
49
+ register_all(registry)
50
+
51
+ # Add middleware
52
+ registry.use(recovery_middleware)
53
+ registry.use(logging_middleware)
54
+
55
+ # Start worker (blocks until shutdown)
56
+ listen_and_serve_worker(registry)
57
+
58
+
59
+ if __name__ == "__main__":
60
+ main()
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Entry point for the Blok Ruby runtime.
5
+ #
6
+ # Boots the configured server(s) based on +BLOK_TRANSPORT+:
7
+ # - "http" (default): Sinatra HTTP server only.
8
+ # - "grpc": gRPC server only on +GRPC_PORT+.
9
+ # - "both": HTTP in foreground + gRPC in a background thread (dual-listen).
10
+ #
11
+ # Usage:
12
+ # ruby bin/serve.rb
13
+ #
14
+ # Environment:
15
+ # PORT HTTP port (default: 9006)
16
+ # GRPC_PORT gRPC port (default: 10006)
17
+ # BLOK_TRANSPORT "http" | "grpc" | "both" (default: "http")
18
+ # HOST Bind address (default: 0.0.0.0)
19
+ # LOG_LEVEL DEBUG | INFO | WARN | ERROR (default: INFO)
20
+ # BLOK_NODES_DIR Directory of user-authored nodes to discover (each in a
21
+ # `<name>/node.rb` subclassing Blok::Node::NodeHandler). Set by
22
+ # blokctl to the project's `runtimes/ruby/nodes`. When unset,
23
+ # only the SDK's built-in example nodes load.
24
+
25
+ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
26
+
27
+ require "blok"
28
+ require_relative "../examples/hello_world_node"
29
+ require_relative "../examples/api_call_node"
30
+ require_relative "../examples/transform_data_node"
31
+ require_relative "../examples/chain_test_node"
32
+ require_relative "../examples/blok_error_demo_node"
33
+ require_relative "../examples/typed_greet_node"
34
+
35
+ config = Blok::Config::ServerConfig.from_env
36
+
37
+ registry = Blok::Node::NodeRegistry.new(config.version)
38
+ registry.register("hello-world", HelloWorldNode.new)
39
+ registry.register("api-call", ApiCallNode.new)
40
+ registry.register("transform-data", TransformDataNode.new)
41
+ registry.register("chain-test", ChainTestNode.new)
42
+ registry.register("blok-error-demo", BlokErrorDemoNode.new)
43
+ registry.register("typed-greet", TypedGreetNode.new)
44
+
45
+ # Discover user-authored nodes from BLOK_NODES_DIR (set by blokctl to the
46
+ # project's runtimes/ruby/nodes). Each lives in <name>/node.rb subclassing
47
+ # Blok::Node::NodeHandler; no manual registration. Unset => built-ins only.
48
+ user_node_count = Blok::Node.load_user_nodes(registry, ENV["BLOK_NODES_DIR"])
49
+
50
+ logger = Blok::Logging::Logger.new(config.log_level)
51
+ registry.use(Blok::Middleware::RecoveryMiddleware.new)
52
+ registry.use(Blok::Middleware::LoggingMiddleware.new(logger))
53
+
54
+ warn "Blok Ruby SDK starting (transport=#{config.transport}, http_port=#{config.port}, " \
55
+ "grpc_port=#{config.grpc_port}, #{registry.node_names.length} nodes, #{user_node_count} user)"
56
+
57
+ # Lazy-load the gRPC server only when we actually need it. This keeps the
58
+ # HTTP-only path free of grpc dependency load time.
59
+ def start_grpc(registry, config, blocking:)
60
+ require_relative "../lib/blok/server/grpc_server"
61
+ Blok::Server::GrpcServer.new(
62
+ registry,
63
+ port: config.grpc_port,
64
+ host: config.host,
65
+ sdk_version: config.version
66
+ ).tap { |s| s.start(blocking: blocking) }
67
+ end
68
+
69
+ def start_http(registry, config)
70
+ Blok::Server::RuntimeApp.registry = registry
71
+ # Sinatra/Puma: bind on host:port and run in the foreground.
72
+ require "rackup"
73
+ app = Rack::Builder.new { run Blok::Server::RuntimeApp }.to_app
74
+ Rackup::Server.start(
75
+ app: app,
76
+ server: "puma",
77
+ Host: config.host,
78
+ Port: config.port,
79
+ quiet: false
80
+ )
81
+ end
82
+
83
+ case config.transport
84
+ when Blok::Config::ServerConfig::Transport::HTTP
85
+ start_http(registry, config)
86
+ when Blok::Config::ServerConfig::Transport::GRPC
87
+ grpc_server = start_grpc(registry, config, blocking: false)
88
+ # Hand the stop signal off the trap context to the main thread.
89
+ # `GrpcServer#stop` calls `RpcServer#stop` which acquires a Mutex,
90
+ # and `Mutex#synchronize` raises `ThreadError: can't be called from
91
+ # trap context` under Ruby 3.x. `Queue#<<` is signal-safe in MRI.
92
+ stop_queue = Queue.new
93
+ trap("INT") { stop_queue << "INT" }
94
+ trap("TERM") { stop_queue << "TERM" }
95
+ stop_queue.pop
96
+ grpc_server.stop
97
+ exit 0
98
+ when Blok::Config::ServerConfig::Transport::BOTH
99
+ grpc_server = start_grpc(registry, config, blocking: false)
100
+ at_exit { grpc_server.stop }
101
+ start_http(registry, config)
102
+ else
103
+ warn "Unknown transport: #{config.transport}"
104
+ exit 1
105
+ end
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blokjs/trigger-cron",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "files": ["dist"],
5
5
  "description": "Cron/scheduled trigger for Blok workflows - supports cron expressions and interval-based scheduling",
6
6
  "type": "module",
@@ -15,9 +15,9 @@
15
15
  "author": "Deskree Technologies Inc.",
16
16
  "license": "Apache-2.0",
17
17
  "dependencies": {
18
- "@blokjs/helper": "^1.4.0",
19
- "@blokjs/runner": "^1.4.0",
20
- "@blokjs/shared": "^1.4.0",
18
+ "@blokjs/helper": "^1.5.0",
19
+ "@blokjs/runner": "^1.5.0",
20
+ "@blokjs/shared": "^1.5.0",
21
21
  "@opentelemetry/api": "^1.9.0",
22
22
  "cron": "^4.4.0",
23
23
  "uuid": "^11.1.0"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blokjs/trigger-grpc",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "files": ["dist"],
5
5
  "description": "",
6
6
  "type": "module",
@@ -36,11 +36,11 @@
36
36
  "@connectrpc/connect": "^2.1.1",
37
37
  "@connectrpc/connect-fastify": "^2.1.1",
38
38
  "@connectrpc/connect-node": "^2.1.1",
39
- "@blokjs/api-call": "^1.4.0",
40
- "@blokjs/helper": "^1.4.0",
41
- "@blokjs/if-else": "^1.4.0",
42
- "@blokjs/runner": "^1.4.0",
43
- "@blokjs/shared": "^1.4.0",
39
+ "@blokjs/api-call": "^1.5.0",
40
+ "@blokjs/helper": "^1.5.0",
41
+ "@blokjs/if-else": "^1.5.0",
42
+ "@blokjs/runner": "^1.5.0",
43
+ "@blokjs/shared": "^1.5.0",
44
44
  "@opentelemetry/api": "^1.9.0",
45
45
  "@opentelemetry/exporter-prometheus": "^0.57.2",
46
46
  "@opentelemetry/resources": "^1.30.1",
@@ -36,8 +36,8 @@ export default class GRpcTrigger extends TriggerBase {
36
36
  private server = fastify({
37
37
  http2: true,
38
38
  // https: {
39
- // key: readFileSync("localhost+2-key.pem", "utf8"),
40
- // cert: readFileSync("localhost+2.pem", "utf8"),
39
+ // key: readFileSync("server-key.pem", "utf8"), // e.g. generated with mkcert
40
+ // cert: readFileSync("server-cert.pem", "utf8"),
41
41
  // }
42
42
  });
43
43
  private nodeMap: GlobalOptions = <GlobalOptions>{};
@@ -31,17 +31,17 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@ai-sdk/openai": "^1.3.22",
34
- "@blokjs/api-call": "^1.4.0",
35
- "@blokjs/core": "^1.4.0",
36
- "@blokjs/helper": "^1.4.0",
37
- "@blokjs/helpers": "^1.4.0",
38
- "@blokjs/if-else": "^1.4.0",
39
- "@blokjs/runner": "^1.4.0",
40
- "@blokjs/shared": "^1.4.0",
41
- "@blokjs/trigger-mcp": "^1.4.0",
42
- "@blokjs/trigger-sse": "^1.4.0",
43
- "@blokjs/trigger-webhook": "^1.4.0",
44
- "@blokjs/trigger-websocket": "^1.4.0",
34
+ "@blokjs/api-call": "^1.5.0",
35
+ "@blokjs/core": "^1.5.0",
36
+ "@blokjs/helper": "^1.5.0",
37
+ "@blokjs/helpers": "^1.5.0",
38
+ "@blokjs/if-else": "^1.5.0",
39
+ "@blokjs/runner": "^1.5.0",
40
+ "@blokjs/shared": "^1.5.0",
41
+ "@blokjs/trigger-mcp": "^1.5.0",
42
+ "@blokjs/trigger-sse": "^1.5.0",
43
+ "@blokjs/trigger-webhook": "^1.5.0",
44
+ "@blokjs/trigger-websocket": "^1.5.0",
45
45
  "@hono/node-server": "^1.19.9",
46
46
  "@opentelemetry/api": "^1.9.0",
47
47
  "@opentelemetry/exporter-prometheus": "^0.57.2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blokjs/trigger-mcp",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "files": ["dist"],
5
5
  "description": "Model Context Protocol (MCP) trigger for Blok workflows — expose workflows as MCP tools over SSE + Streamable-HTTP on the shared Hono port.",
6
6
  "type": "module",
@@ -15,9 +15,9 @@
15
15
  "author": "Deskree Technologies Inc.",
16
16
  "license": "Apache-2.0",
17
17
  "dependencies": {
18
- "@blokjs/helper": "^1.4.0",
19
- "@blokjs/runner": "^1.4.0",
20
- "@blokjs/shared": "^1.4.0",
18
+ "@blokjs/helper": "^1.5.0",
19
+ "@blokjs/runner": "^1.5.0",
20
+ "@blokjs/shared": "^1.5.0",
21
21
  "@modelcontextprotocol/sdk": "^1.29.0",
22
22
  "@opentelemetry/api": "^1.9.0",
23
23
  "hono": "^4.11.7",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blokjs/trigger-pubsub",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "files": ["dist"],
5
5
  "description": "Pub/Sub trigger for Blok workflows — supports NATS (Core + JetStream), Redis Streams, Kafka, GCP Pub/Sub, AWS SNS+SQS, and Azure Service Bus.",
6
6
  "type": "module",
@@ -15,9 +15,9 @@
15
15
  "author": "Deskree Technologies Inc.",
16
16
  "license": "Apache-2.0",
17
17
  "dependencies": {
18
- "@blokjs/helper": "^1.4.0",
19
- "@blokjs/runner": "^1.4.0",
20
- "@blokjs/shared": "^1.4.0",
18
+ "@blokjs/helper": "^1.5.0",
19
+ "@blokjs/runner": "^1.5.0",
20
+ "@blokjs/shared": "^1.5.0",
21
21
  "@opentelemetry/api": "^1.9.0",
22
22
  "uuid": "^11.1.0"
23
23
  },
@@ -25,13 +25,13 @@
25
25
  "vitest": "^4.0.18"
26
26
  },
27
27
  "dependencies": {
28
- "@blokjs/api-call": "^1.4.0",
29
- "@blokjs/core": "^1.4.0",
30
- "@blokjs/helper": "^1.4.0",
31
- "@blokjs/if-else": "^1.4.0",
32
- "@blokjs/runner": "^1.4.0",
33
- "@blokjs/shared": "^1.4.0",
34
- "@blokjs/trigger-pubsub": "^1.4.0",
28
+ "@blokjs/api-call": "^1.5.0",
29
+ "@blokjs/core": "^1.5.0",
30
+ "@blokjs/helper": "^1.5.0",
31
+ "@blokjs/if-else": "^1.5.0",
32
+ "@blokjs/runner": "^1.5.0",
33
+ "@blokjs/shared": "^1.5.0",
34
+ "@blokjs/trigger-pubsub": "^1.5.0",
35
35
  "@opentelemetry/api": "^1.9.0",
36
36
  "@opentelemetry/exporter-prometheus": "^0.57.2",
37
37
  "@opentelemetry/resources": "^1.30.1",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blokjs/trigger-sse",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "files": ["dist"],
5
5
  "description": "Server-Sent Events (SSE) trigger for Blok workflows — real-time server push on the shared Hono port.",
6
6
  "type": "module",
@@ -15,15 +15,15 @@
15
15
  "author": "Deskree Technologies Inc.",
16
16
  "license": "Apache-2.0",
17
17
  "dependencies": {
18
- "@blokjs/helper": "^1.4.0",
19
- "@blokjs/runner": "^1.4.0",
20
- "@blokjs/shared": "^1.4.0",
18
+ "@blokjs/helper": "^1.5.0",
19
+ "@blokjs/runner": "^1.5.0",
20
+ "@blokjs/shared": "^1.5.0",
21
21
  "@opentelemetry/api": "^1.9.0",
22
22
  "hono": "^4.11.7",
23
23
  "uuid": "^11.1.0"
24
24
  },
25
25
  "devDependencies": {
26
- "@blokjs/core": "^1.4.0",
26
+ "@blokjs/core": "^1.5.0",
27
27
  "@hono/node-server": "^1.19.9",
28
28
  "@types/node": "^22.15.21",
29
29
  "@types/uuid": "^11.0.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blokjs/trigger-webhook",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "files": ["dist"],
5
5
  "description": "Webhook trigger for Blok workflows - supports GitHub, Stripe, Shopify, and custom webhooks",
6
6
  "type": "module",
@@ -15,9 +15,9 @@
15
15
  "author": "Deskree Technologies Inc.",
16
16
  "license": "Apache-2.0",
17
17
  "dependencies": {
18
- "@blokjs/helper": "^1.4.0",
19
- "@blokjs/runner": "^1.4.0",
20
- "@blokjs/shared": "^1.4.0",
18
+ "@blokjs/helper": "^1.5.0",
19
+ "@blokjs/runner": "^1.5.0",
20
+ "@blokjs/shared": "^1.5.0",
21
21
  "@opentelemetry/api": "^1.9.0",
22
22
  "hono": "^4.11.7",
23
23
  "uuid": "^11.1.0"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blokjs/trigger-websocket",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "files": ["dist"],
5
5
  "description": "WebSocket trigger for Blok workflows - real-time bidirectional communication",
6
6
  "type": "module",
@@ -15,15 +15,15 @@
15
15
  "author": "Deskree Technologies Inc.",
16
16
  "license": "Apache-2.0",
17
17
  "dependencies": {
18
- "@blokjs/helper": "^1.4.0",
19
- "@blokjs/runner": "^1.4.0",
20
- "@blokjs/shared": "^1.4.0",
18
+ "@blokjs/helper": "^1.5.0",
19
+ "@blokjs/runner": "^1.5.0",
20
+ "@blokjs/shared": "^1.5.0",
21
21
  "@hono/node-ws": "^1.3.1",
22
22
  "@opentelemetry/api": "^1.9.0",
23
23
  "uuid": "^11.1.0"
24
24
  },
25
25
  "peerDependencies": {
26
- "@blokjs/trigger-pubsub": "^1.4.0",
26
+ "@blokjs/trigger-pubsub": "^1.5.0",
27
27
  "ws": "^8.19.0"
28
28
  },
29
29
  "peerDependenciesMeta": {
@@ -35,7 +35,7 @@
35
35
  }
36
36
  },
37
37
  "devDependencies": {
38
- "@blokjs/core": "^1.4.0",
38
+ "@blokjs/core": "^1.5.0",
39
39
  "@types/node": "^22.15.21",
40
40
  "@types/uuid": "^11.0.0",
41
41
  "@types/ws": "^8.18.1",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blokjs/trigger-worker",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "files": ["dist"],
5
5
  "description": "Worker-based trigger for Blok workflows - supports background job processing with concurrency, retries, and scheduling",
6
6
  "type": "module",
@@ -15,9 +15,9 @@
15
15
  "author": "Deskree Technologies Inc.",
16
16
  "license": "Apache-2.0",
17
17
  "dependencies": {
18
- "@blokjs/helper": "^1.4.0",
19
- "@blokjs/runner": "^1.4.0",
20
- "@blokjs/shared": "^1.4.0",
18
+ "@blokjs/helper": "^1.5.0",
19
+ "@blokjs/runner": "^1.5.0",
20
+ "@blokjs/shared": "^1.5.0",
21
21
  "@opentelemetry/api": "^1.9.0",
22
22
  "uuid": "^11.1.0"
23
23
  },
@@ -25,13 +25,13 @@
25
25
  "vitest": "^4.0.18"
26
26
  },
27
27
  "dependencies": {
28
- "@blokjs/api-call": "^1.4.0",
29
- "@blokjs/core": "^1.4.0",
30
- "@blokjs/helper": "^1.4.0",
31
- "@blokjs/if-else": "^1.4.0",
32
- "@blokjs/runner": "^1.4.0",
33
- "@blokjs/shared": "^1.4.0",
34
- "@blokjs/trigger-worker": "^1.4.0",
28
+ "@blokjs/api-call": "^1.5.0",
29
+ "@blokjs/core": "^1.5.0",
30
+ "@blokjs/helper": "^1.5.0",
31
+ "@blokjs/if-else": "^1.5.0",
32
+ "@blokjs/runner": "^1.5.0",
33
+ "@blokjs/shared": "^1.5.0",
34
+ "@blokjs/trigger-worker": "^1.5.0",
35
35
  "@opentelemetry/api": "^1.9.0",
36
36
  "@opentelemetry/exporter-prometheus": "^0.57.2",
37
37
  "@opentelemetry/resources": "^1.30.1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blokctl",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "author": "Deskree Technologies Inc.",
5
5
  "license": "Apache-2.0",
6
6
  "description": "cli for blok",
@@ -30,8 +30,8 @@
30
30
  "keywords": ["blokctl", "cli", "blok", "blok"],
31
31
  "dependencies": {
32
32
  "@ai-sdk/openai": "^1.3.22",
33
- "@blokjs/helper": "^1.4.0",
34
- "@blokjs/runner": "^1.4.0",
33
+ "@blokjs/helper": "^1.5.0",
34
+ "@blokjs/runner": "^1.5.0",
35
35
  "@clack/prompts": "^1.0.0",
36
36
  "ai": "^4.3.16",
37
37
  "better-sqlite3": "^12.6.2",
@@ -1,28 +0,0 @@
1
- -----BEGIN PRIVATE KEY-----
2
- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDNjfXRKBwXU0IH
3
- ftJJGiR5w6Ccf2JfPZJgDdarhVgJjL2cy9d4AwIq4ydiuU+H8MnguzdGrFaCgYOB
4
- GfgEI4dOAGr1AInRVVHRWKvwGdLYm59dBRi5PQuU2EKVonQNsZy/qcOJSBzBSSAx
5
- PFCpTwrxj0j/Dug6LxIa1wB7UenYn5NjkFSF8F5HufE7l4goIVh0/fVgRripCsnk
6
- iMQFVhMr+2glX+19zTVkBl9EtAPbkXsegUUdnkOH2sd1TBN4HUibnktX+P1aIlhd
7
- p741Eni42jU92u33iZasvvnkA94Q2MhBhzx3lgqAAcHcePzBI9yOEQbTqik4Nkpv
8
- moqqDFBbAgMBAAECggEACDu0aeFCZsjF70jsIVNzvJDSYRJVHV14/HHxdENOCGvj
9
- uGENy1fLgW5ByJmFjvtdCqxVBXanrGiFnOkuXvQRWlV380JHQuQ497qmgGJ4aIar
10
- Nm2a1OiWCysyV43/OgEwNxkUpO4HgNJuAKrazD1HQe+sS9MMCDCUeBC+izH3vN5s
11
- 9LWOrhde+ZwCkHJgRxp6V5HBJXU/27T02ZjgvPXupzXQ2ozRgx2gn5lLvJJfqG/h
12
- jEMi9qyuwoRUL4QXDg3TNHHSllnENdRrVJr7VsvYpRpQogVsr4V7zIZiFkAcbuC4
13
- kMuHeahkjqmlSYVuz9DxPHcmFRW/B5MI5MLQwCvI6QKBgQD61emfMrA323QIWF5l
14
- hbNQBS3hje9pwN27EU3QmCq0z/2Ja0TTaSeNSdlQAfMEGHsO5tL0ldqS267uqs5r
15
- clrukrOFmcARZiHne5U1uMcWgYvRmPTTdwng1lQSBuLo7XR9f6sW3u1csOJ8PY4w
16
- oKtsAIKm0r53iVRCPpd7D9Lr3QKBgQDRyWIccS93kI2rmRxkg4nhniCP8uAacYHy
17
- ZEZUFpm0p23rLKF7zlGd1xZmwKV5lnd1278qBt9YMvDGw6Mlt3WTQUh9XQ3b5q1V
18
- xOHfyn2QvWfFbX/tWousq2RP3CJakGiKMefSx8aZB/Vwat3kSdgz825Vcr9oN2j1
19
- lZZemRlllwKBgD+K1QXpN07PHxPGHxOkzQnmZfsPk6i8nO74sTe4dIkdb2LSc7sC
20
- lmxqWsyz0bYl5Xae7q3bEGXHlQcM6gG6FGL/cs7TZh6COvCDFAdp6bU/2AWes9al
21
- /zCf2ug+KllLXgk0wEio7IRgot9KUKzs5sATWQWduXZaqaemZ4VbOtlZAoGAK457
22
- b1pUt6dssq8khP4Gl7CEJD8SJotgppoJPBZBLZABs21dzd3FdlcdEJJ5COijvvW0
23
- GB67Ko3RDgO6kO8pWzyXt2elo/2eCYvKNfPN5EpfDE+y2u4Mx/oB5s7W1yTaf67i
24
- 6hGOe2F6pS+bCHYIjKjDRLyBXzr58NtxEA0Lh9sCgYEA6dI03OhJpruHxyOE3HYE
25
- oSDah3wr8WUw5BsGDsrW2tMVV7Y3YRO02mL/DB17bmM1FzS5s0n8DKU0c2wViFm4
26
- ZI4wZdm1hA1MBQBEFVQlVkmwtfyhmsnr98Huckd58PfMUZf6KJE9L4h7SXtPa/VL
27
- 492ASgwAEWWqFlfK6wSrHiM=
28
- -----END PRIVATE KEY-----
@@ -1,27 +0,0 @@
1
- -----BEGIN CERTIFICATE-----
2
- MIIEoTCCAwmgAwIBAgIRAKSu5ey0gTHNC82jEhdfdpYwDQYJKoZIhvcNAQELBQAw
3
- gbExHjAcBgNVBAoTFW1rY2VydCBkZXZlbG9wbWVudCBDQTFDMEEGA1UECww6bWFy
4
- Y29ATWFyY29zLU1hY0Jvb2stUHJvLmxvY2FsIChNYXJjbyBDYXN0aWxsbyBEZWxs
5
- YSBTZXJhKTFKMEgGA1UEAwxBbWtjZXJ0IG1hcmNvQE1hcmNvcy1NYWNCb29rLVBy
6
- by5sb2NhbCAoTWFyY28gQ2FzdGlsbG8gRGVsbGEgU2VyYSkwHhcNMjUwMjAzMDE1
7
- MjM5WhcNMjcwNTAzMDE1MjM5WjBuMScwJQYDVQQKEx5ta2NlcnQgZGV2ZWxvcG1l
8
- bnQgY2VydGlmaWNhdGUxQzBBBgNVBAsMOm1hcmNvQE1hcmNvcy1NYWNCb29rLVBy
9
- by5sb2NhbCAoTWFyY28gQ2FzdGlsbG8gRGVsbGEgU2VyYSkwggEiMA0GCSqGSIb3
10
- DQEBAQUAA4IBDwAwggEKAoIBAQDNjfXRKBwXU0IHftJJGiR5w6Ccf2JfPZJgDdar
11
- hVgJjL2cy9d4AwIq4ydiuU+H8MnguzdGrFaCgYOBGfgEI4dOAGr1AInRVVHRWKvw
12
- GdLYm59dBRi5PQuU2EKVonQNsZy/qcOJSBzBSSAxPFCpTwrxj0j/Dug6LxIa1wB7
13
- UenYn5NjkFSF8F5HufE7l4goIVh0/fVgRripCsnkiMQFVhMr+2glX+19zTVkBl9E
14
- tAPbkXsegUUdnkOH2sd1TBN4HUibnktX+P1aIlhdp741Eni42jU92u33iZasvvnk
15
- A94Q2MhBhzx3lgqAAcHcePzBI9yOEQbTqik4NkpvmoqqDFBbAgMBAAGjdjB0MA4G
16
- A1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAfBgNVHSMEGDAWgBTN
17
- imcw8dRZ+LdM83iq2xnhRgHVMjAsBgNVHREEJTAjgglsb2NhbGhvc3SHBH8AAAGH
18
- EAAAAAAAAAAAAAAAAAAAAAEwDQYJKoZIhvcNAQELBQADggGBAIA2HiGT0dtdkNfB
19
- LFAIUvlatqHkH4Pds3jd0TnT4muoebPoHc3HSoqnSdt4g2vN+75S47G7E5b/qQbH
20
- ZfkL9kgZoCar79DuVpC/kCPI/NACRsqdgIcnd09FqN2Dmg1UP2F/nulLucWfOiSL
21
- T3q3nVEAm3UL4R5VopFW94bp8jJ/cWseDohIGZBza4yUiMnbd6mK+g+DoExfGbwc
22
- A3601xeDWcDxKv+KaBWQeyoUWO66FKYOJcdwaiPCPrvXVz3tdbxBpHB/beNeulaU
23
- 6EzDRCmtIwEZNwq9MNn0wViOjta1TtkeERtbvnmgPmFhhSbHDtGbbxuwWnV91aZg
24
- 0JFymKsmmBIv4Qu50zVPo7Jz0n6CucIPVUW8ZoamVBr6ljHOfZIg9N0hkRoX7DUT
25
- pPV22KliCRZCHYnyVcIzwtW2lxlzydUnldhxZga6vlfoKR5WzCceTtsX2+p8dbJe
26
- p5jVRsLyT/sfECb8n5N7BYRLSh36FekFGErFCr9Svqd9pRVsWg==
27
- -----END CERTIFICATE-----