blokctl 0.6.20 → 0.7.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/__tests__/modular-observability.capstone.e2e.test.js +72 -0
- package/dist/commands/create/node.js +46 -66
- package/dist/commands/create/project.js +55 -9
- package/dist/commands/create/utils/Examples.d.ts +8 -20
- package/dist/commands/create/utils/Examples.js +138 -412
- package/dist/commands/dev/index.js +40 -1
- package/dist/commands/gen/appTypes.js +40 -1
- package/dist/commands/generate/NodeGenerator.d.ts +0 -2
- package/dist/commands/generate/NodeGenerator.js +0 -20
- package/dist/commands/generate/RuntimeGenerator.d.ts +0 -2
- package/dist/commands/generate/RuntimeGenerator.js +0 -19
- package/dist/commands/generate/RuntimeGenerator.test.js +0 -29
- package/dist/commands/generate/TriggerGenerator.d.ts +0 -2
- package/dist/commands/generate/TriggerGenerator.js +0 -19
- package/dist/commands/generate/WorkflowGenerator.d.ts +0 -2
- package/dist/commands/generate/WorkflowGenerator.js +0 -19
- package/dist/commands/generate/e2e/NodeGenerator.e2e.test.js +0 -12
- package/dist/commands/generate/e2e/RuntimeGenerator.e2e.test.js +0 -12
- package/dist/commands/generate/e2e/TriggerGenerator.e2e.test.js +0 -14
- package/dist/commands/monitor/monitor-component.js +5 -5
- package/dist/commands/observability/add.d.ts +2 -0
- package/dist/commands/observability/add.js +113 -0
- package/dist/commands/observability/alerting-module.test.js +43 -0
- package/dist/commands/observability/apply.d.ts +10 -0
- package/dist/commands/observability/apply.js +11 -0
- package/dist/commands/observability/descriptor.d.ts +37 -0
- package/dist/commands/observability/descriptor.js +203 -0
- package/dist/commands/observability/descriptor.test.d.ts +1 -0
- package/dist/commands/observability/descriptor.test.js +40 -0
- package/dist/commands/observability/index.d.ts +1 -0
- package/dist/commands/observability/index.js +53 -0
- package/dist/commands/observability/list.d.ts +2 -0
- package/dist/commands/observability/list.js +45 -0
- package/dist/commands/observability/logging-module.test.d.ts +1 -0
- package/dist/commands/observability/logging-module.test.js +43 -0
- package/dist/commands/observability/obs-stack-module.test.d.ts +1 -0
- package/dist/commands/observability/obs-stack-module.test.js +33 -0
- package/dist/commands/observability/remove.d.ts +2 -0
- package/dist/commands/observability/remove.js +62 -0
- package/dist/commands/observability/shared.d.ts +6 -0
- package/dist/commands/observability/shared.js +23 -0
- package/dist/commands/observability/status.d.ts +2 -0
- package/dist/commands/observability/status.js +36 -0
- package/dist/commands/observability/tracing-module.test.d.ts +1 -0
- package/dist/commands/observability/tracing-module.test.js +42 -0
- package/dist/commands/profile/index.js +7 -10
- package/dist/commands/watch/format.d.ts +23 -0
- package/dist/commands/watch/format.js +60 -0
- package/dist/commands/watch/index.d.ts +1 -0
- package/dist/commands/watch/index.js +53 -0
- package/dist/commands/watch/sse.d.ts +16 -0
- package/dist/commands/watch/sse.js +82 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4 -0
- package/dist/services/obs-setup.d.ts +5 -0
- package/dist/services/obs-setup.js +68 -0
- package/dist/services/obs-setup.test.d.ts +1 -0
- package/dist/services/obs-setup.test.js +71 -0
- package/dist/services/obs-tiers.d.ts +9 -0
- package/dist/services/obs-tiers.js +16 -0
- package/dist/services/observability-mutations.d.ts +4 -0
- package/dist/services/observability-mutations.js +46 -0
- package/dist/services/observability-mutations.test.d.ts +1 -0
- package/dist/services/observability-mutations.test.js +57 -0
- package/dist/services/runtime-setup.d.ts +12 -1
- package/dist/services/runtime-setup.js +274 -14
- package/dist/studio-dist/assets/{index-BD8_9YPN.js → index-CnFqCRQe.js} +17 -17
- package/dist/studio-dist/index.html +1 -1
- package/package.json +3 -3
- package/dist/commands/generate/GenerationAnalytics.d.ts +0 -61
- package/dist/commands/generate/GenerationAnalytics.js +0 -163
- package/dist/commands/generate/GenerationAnalytics.test.js +0 -407
- package/dist/commands/generate/PromptVersioning.d.ts +0 -25
- package/dist/commands/generate/PromptVersioning.js +0 -71
- package/dist/commands/generate/PromptVersioning.test.js +0 -120
- /package/dist/{commands/generate/GenerationAnalytics.test.d.ts → __tests__/modular-observability.capstone.e2e.test.d.ts} +0 -0
- /package/dist/commands/{generate/PromptVersioning.test.d.ts → observability/alerting-module.test.d.ts} +0 -0
|
@@ -32,36 +32,27 @@ const package_dev_dependencies = {
|
|
|
32
32
|
"@types/ejs": "^3.1.5",
|
|
33
33
|
"@types/pg": "^8.11.11",
|
|
34
34
|
};
|
|
35
|
-
const python3_file = `
|
|
36
|
-
|
|
37
|
-
from
|
|
38
|
-
from
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
err.setCode(500)
|
|
57
|
-
err.setName(self.name)
|
|
58
|
-
|
|
59
|
-
stack_trace = traceback.format_exc()
|
|
60
|
-
err.setStack(stack_trace)
|
|
61
|
-
response.success = False
|
|
62
|
-
response.setError(err)
|
|
63
|
-
|
|
64
|
-
return response
|
|
35
|
+
const python3_file = `from pydantic import BaseModel
|
|
36
|
+
|
|
37
|
+
from blok import node
|
|
38
|
+
from blok.types.context import Context
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class Input(BaseModel):
|
|
42
|
+
"""Validated inputs for the {{NODE_NAME}} node."""
|
|
43
|
+
|
|
44
|
+
name: str = "world"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class Output(BaseModel):
|
|
48
|
+
message: str
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@node("{{NODE_NAME}}", "Describe what {{NODE_NAME}} does")
|
|
52
|
+
def run(ctx: Context, input: Input) -> Output:
|
|
53
|
+
# \`input\` is already validated against Input; the return is validated
|
|
54
|
+
# against Output and serialized for you.
|
|
55
|
+
return Output(message=f"Hello, {input.name}!")
|
|
65
56
|
`;
|
|
66
57
|
const examples_url = `
|
|
67
58
|
Examples:
|
|
@@ -121,316 +112,151 @@ autorestart=true
|
|
|
121
112
|
stderr_logfile=/var/log/python.err.log
|
|
122
113
|
stdout_logfile=/var/log/python.out.log
|
|
123
114
|
`;
|
|
124
|
-
const go_node_file =
|
|
115
|
+
const go_node_file = `// {{NODE_NAME}} — a Blok node for the Go runtime.
|
|
116
|
+
package {{NODE_PKG}}
|
|
125
117
|
|
|
126
118
|
import (
|
|
127
|
-
"github.com/blok
|
|
119
|
+
blok "github.com/nickincloud/blok-go"
|
|
128
120
|
)
|
|
129
121
|
|
|
130
|
-
|
|
122
|
+
// {{NODE_NAME_PASCAL}}Node implements blok.NodeHandler.
|
|
123
|
+
type {{NODE_NAME_PASCAL}}Node struct{}
|
|
131
124
|
|
|
132
|
-
|
|
133
|
-
|
|
125
|
+
// Execute runs the node. Input arrives on ctx.Request; config holds the step's
|
|
126
|
+
// inputs from the workflow. Return any JSON-serialisable value (or an error).
|
|
127
|
+
func (n *{{NODE_NAME_PASCAL}}Node) Execute(ctx *blok.Context, config map[string]interface{}) (interface{}, error) {
|
|
134
128
|
name := "World"
|
|
135
|
-
if body
|
|
136
|
-
if
|
|
137
|
-
name =
|
|
129
|
+
if body := ctx.Request.BodyMap(); body != nil {
|
|
130
|
+
if v, ok := body["name"].(string); ok {
|
|
131
|
+
name = v
|
|
138
132
|
}
|
|
139
133
|
}
|
|
140
134
|
|
|
141
|
-
// Access configuration
|
|
142
135
|
prefix := "Hello"
|
|
143
|
-
if
|
|
144
|
-
prefix =
|
|
136
|
+
if v, ok := config["prefix"].(string); ok {
|
|
137
|
+
prefix = v
|
|
145
138
|
}
|
|
146
139
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
// Return successful result
|
|
151
|
-
return &sdk.ExecutionResult{
|
|
152
|
-
Success: true,
|
|
153
|
-
Data: map[string]interface{}{
|
|
154
|
-
"message": prefix + ", " + name + "!",
|
|
155
|
-
"timestamp": sdk.GetCurrentTimestamp(),
|
|
156
|
-
"language": "Go",
|
|
157
|
-
},
|
|
158
|
-
Errors: nil,
|
|
140
|
+
return map[string]interface{}{
|
|
141
|
+
"message": prefix + ", " + name + "!",
|
|
142
|
+
"language": "Go",
|
|
159
143
|
}, nil
|
|
160
144
|
}
|
|
161
145
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
registry.Register("{{NODE_NAME}}", &
|
|
166
|
-
|
|
167
|
-
// Start HTTP server
|
|
168
|
-
server := sdk.NewHTTPServer(registry, ":8080")
|
|
169
|
-
if err := server.Start(); err != nil {
|
|
170
|
-
panic(err)
|
|
171
|
-
}
|
|
146
|
+
// Register wires this node into the runtime registry. The generated
|
|
147
|
+
// register_user_nodes.go calls it for every node under runtimes/go/nodes.
|
|
148
|
+
func Register(registry *blok.NodeRegistry) {
|
|
149
|
+
registry.Register("{{NODE_NAME}}", &{{NODE_NAME_PASCAL}}Node{})
|
|
172
150
|
}
|
|
173
151
|
`;
|
|
174
|
-
const
|
|
152
|
+
const java_node_file = `package com.blok.blok.nodes;
|
|
175
153
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
require github.com/blok/sdk v1.0.0
|
|
179
|
-
`;
|
|
180
|
-
const go_dockerfile = `FROM golang:1.21-alpine AS builder
|
|
181
|
-
|
|
182
|
-
WORKDIR /app
|
|
183
|
-
COPY go.mod go.sum ./
|
|
184
|
-
RUN go mod download
|
|
185
|
-
|
|
186
|
-
COPY . .
|
|
187
|
-
RUN CGO_ENABLED=0 GOOS=linux go build -o /node main.go
|
|
188
|
-
|
|
189
|
-
FROM alpine:latest
|
|
190
|
-
RUN apk --no-cache add ca-certificates
|
|
191
|
-
WORKDIR /root/
|
|
192
|
-
COPY --from=builder /node .
|
|
193
|
-
|
|
194
|
-
EXPOSE 8080
|
|
195
|
-
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\
|
|
196
|
-
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1
|
|
197
|
-
|
|
198
|
-
CMD ["./node"]
|
|
199
|
-
`;
|
|
200
|
-
const java_node_file = `package com.blok.nodes;
|
|
154
|
+
import com.blok.blok.node.NodeHandler;
|
|
155
|
+
import com.blok.blok.types.Context;
|
|
201
156
|
|
|
202
|
-
import
|
|
203
|
-
import com.blok.runtime.NodeRegistry;
|
|
204
|
-
import com.blok.server.RuntimeServer;
|
|
157
|
+
import java.time.Instant;
|
|
205
158
|
import java.util.HashMap;
|
|
206
159
|
import java.util.Map;
|
|
207
160
|
|
|
208
|
-
|
|
161
|
+
/**
|
|
162
|
+
* {{NODE_NAME}} — a Blok node for the Java runtime.
|
|
163
|
+
*
|
|
164
|
+
* <p>Input arrives on {@code ctx.getRequest().bodyMap()} (a Map, or null when
|
|
165
|
+
* the body isn't an object); {@code config} holds the step's inputs from the
|
|
166
|
+
* workflow. Return any JSON-serialisable value (a Map here), or throw to fail
|
|
167
|
+
* the step. {@code blokctl dev} discovers this class under
|
|
168
|
+
* {@code runtimes/java/nodes/} and registers it into the Java runtime.
|
|
169
|
+
*/
|
|
170
|
+
public class {{NODE_NAME_PASCAL}}Node implements NodeHandler {
|
|
171
|
+
|
|
209
172
|
@Override
|
|
210
|
-
public
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
name = (String) ctx.request.body.get("name");
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// Access configuration
|
|
219
|
-
String prefix = "Hello";
|
|
220
|
-
if (config != null && config.containsKey("prefix")) {
|
|
221
|
-
prefix = (String) config.get("prefix");
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// Store result in context for downstream nodes
|
|
225
|
-
String greeting = prefix + ", " + name + "!";
|
|
226
|
-
ctx.vars.put("greeting", greeting);
|
|
227
|
-
|
|
228
|
-
// Build response data
|
|
229
|
-
Map<String, Object> data = new HashMap<>();
|
|
230
|
-
data.put("message", greeting);
|
|
231
|
-
data.put("timestamp", System.currentTimeMillis());
|
|
232
|
-
data.put("language", "Java");
|
|
233
|
-
|
|
234
|
-
// Return successful result
|
|
235
|
-
return new Blok.ExecutionResult(true, data, null, null, null);
|
|
236
|
-
} catch (Exception e) {
|
|
237
|
-
return new Blok.ExecutionResult(false, null, e.getMessage(), null, null);
|
|
173
|
+
public Object execute(Context ctx, Map<String, Object> config) throws Exception {
|
|
174
|
+
String name = "World";
|
|
175
|
+
Map<String, Object> body = ctx.getRequest().bodyMap();
|
|
176
|
+
if (body != null && body.get("name") instanceof String s && !s.isEmpty()) {
|
|
177
|
+
name = s;
|
|
238
178
|
}
|
|
239
|
-
}
|
|
240
179
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
NodeRegistry registry = new NodeRegistry();
|
|
245
|
-
registry.register("{{NODE_NAME}}", new HelloWorldNode());
|
|
246
|
-
|
|
247
|
-
// Start HTTP server
|
|
248
|
-
RuntimeServer server = new RuntimeServer(registry, 8080);
|
|
249
|
-
server.start();
|
|
250
|
-
} catch (Exception e) {
|
|
251
|
-
e.printStackTrace();
|
|
252
|
-
System.exit(1);
|
|
180
|
+
String prefix = "Hello";
|
|
181
|
+
if (config != null && config.get("prefix") instanceof String s && !s.isEmpty()) {
|
|
182
|
+
prefix = s;
|
|
253
183
|
}
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
`;
|
|
257
|
-
const java_pom_file = `<?xml version="1.0" encoding="UTF-8"?>
|
|
258
|
-
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
|
259
|
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
260
|
-
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
|
261
|
-
http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
262
|
-
<modelVersion>4.0.0</modelVersion>
|
|
263
|
-
|
|
264
|
-
<groupId>com.blok</groupId>
|
|
265
|
-
<artifactId>{{NODE_NAME}}</artifactId>
|
|
266
|
-
<version>1.0.0</version>
|
|
267
|
-
|
|
268
|
-
<properties>
|
|
269
|
-
<maven.compiler.source>17</maven.compiler.source>
|
|
270
|
-
<maven.compiler.target>17</maven.compiler.target>
|
|
271
|
-
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
|
272
|
-
</properties>
|
|
273
|
-
|
|
274
|
-
<dependencies>
|
|
275
|
-
<dependency>
|
|
276
|
-
<groupId>com.google.code.gson</groupId>
|
|
277
|
-
<artifactId>gson</artifactId>
|
|
278
|
-
<version>2.10.1</version>
|
|
279
|
-
</dependency>
|
|
280
|
-
</dependencies>
|
|
281
|
-
|
|
282
|
-
<build>
|
|
283
|
-
<plugins>
|
|
284
|
-
<plugin>
|
|
285
|
-
<groupId>org.apache.maven.plugins</groupId>
|
|
286
|
-
<artifactId>maven-shade-plugin</artifactId>
|
|
287
|
-
<version>3.5.0</version>
|
|
288
|
-
<executions>
|
|
289
|
-
<execution>
|
|
290
|
-
<phase>package</phase>
|
|
291
|
-
<goals>
|
|
292
|
-
<goal>shade</goal>
|
|
293
|
-
</goals>
|
|
294
|
-
<configuration>
|
|
295
|
-
<transformers>
|
|
296
|
-
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
|
297
|
-
<mainClass>com.blok.nodes.HelloWorldNode</mainClass>
|
|
298
|
-
</transformer>
|
|
299
|
-
</transformers>
|
|
300
|
-
</configuration>
|
|
301
|
-
</execution>
|
|
302
|
-
</executions>
|
|
303
|
-
</plugin>
|
|
304
|
-
</plugins>
|
|
305
|
-
</build>
|
|
306
|
-
</project>
|
|
307
|
-
`;
|
|
308
|
-
const java_dockerfile = `FROM maven:3.9-eclipse-temurin-17 AS builder
|
|
309
|
-
|
|
310
|
-
WORKDIR /app
|
|
311
|
-
COPY pom.xml .
|
|
312
|
-
RUN mvn dependency:go-offline
|
|
313
|
-
|
|
314
|
-
COPY src ./src
|
|
315
|
-
RUN mvn clean package -DskipTests
|
|
316
|
-
|
|
317
|
-
FROM eclipse-temurin:17-jre-alpine
|
|
318
184
|
|
|
319
|
-
|
|
320
|
-
COPY --from=builder /app/target/{{NODE_NAME}}-1.0.0.jar ./app.jar
|
|
185
|
+
String message = prefix + ", " + name + "!";
|
|
321
186
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1
|
|
187
|
+
// Publish a value for downstream nodes via context vars.
|
|
188
|
+
ctx.setVar("greeting", message);
|
|
325
189
|
|
|
326
|
-
|
|
190
|
+
Map<String, Object> result = new HashMap<>();
|
|
191
|
+
result.put("message", message);
|
|
192
|
+
result.put("timestamp", Instant.now().toString());
|
|
193
|
+
result.put("language", "Java");
|
|
194
|
+
return result;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
327
197
|
`;
|
|
328
198
|
const rust_node_file = `use async_trait::async_trait;
|
|
329
|
-
use blok::
|
|
199
|
+
use blok::registry::NodeRegistry;
|
|
200
|
+
use blok::{Context, NodeHandler};
|
|
330
201
|
use std::collections::HashMap;
|
|
331
202
|
|
|
332
|
-
/// {{
|
|
333
|
-
struct {{NODE_NAME_PASCAL}};
|
|
203
|
+
/// {{NODE_NAME_PASCAL}}Node implements blok::NodeHandler.
|
|
204
|
+
struct {{NODE_NAME_PASCAL}}Node;
|
|
334
205
|
|
|
335
206
|
#[async_trait]
|
|
336
|
-
impl NodeHandler for {{NODE_NAME_PASCAL}} {
|
|
207
|
+
impl NodeHandler for {{NODE_NAME_PASCAL}}Node {
|
|
208
|
+
/// Execute runs the node. Input arrives on ctx.request; config holds the
|
|
209
|
+
/// step's inputs from the workflow. Return any JSON value (or an error).
|
|
337
210
|
async fn execute(
|
|
338
211
|
&self,
|
|
339
212
|
ctx: &mut Context,
|
|
340
213
|
config: &HashMap<String, serde_json::Value>,
|
|
341
214
|
) -> Result<serde_json::Value, Box<dyn std::error::Error + Send + Sync>> {
|
|
342
|
-
|
|
343
|
-
|
|
215
|
+
let name = ctx
|
|
216
|
+
.request
|
|
217
|
+
.body
|
|
344
218
|
.get("name")
|
|
345
219
|
.and_then(|v| v.as_str())
|
|
346
220
|
.unwrap_or("World");
|
|
347
221
|
|
|
348
|
-
// Access configuration
|
|
349
222
|
let prefix = config
|
|
350
223
|
.get("prefix")
|
|
351
224
|
.and_then(|v| v.as_str())
|
|
352
225
|
.unwrap_or("Hello");
|
|
353
226
|
|
|
354
|
-
let message = format!("{}, {}!", prefix, name);
|
|
355
|
-
|
|
356
|
-
// Store in context vars for downstream nodes
|
|
357
|
-
ctx.vars.insert(
|
|
358
|
-
"greeting".to_string(),
|
|
359
|
-
serde_json::Value::String(message.clone()),
|
|
360
|
-
);
|
|
361
|
-
|
|
362
|
-
// Return response
|
|
363
227
|
Ok(serde_json::json!({
|
|
364
|
-
"message":
|
|
228
|
+
"message": format!("{}, {}!", prefix, name),
|
|
365
229
|
"language": "Rust"
|
|
366
230
|
}))
|
|
367
231
|
}
|
|
368
232
|
}
|
|
369
233
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
// Register nodes
|
|
376
|
-
let mut registry = NodeRegistry::new("1.0.0");
|
|
377
|
-
registry.register("{{NODE_NAME}}", {{NODE_NAME_PASCAL}});
|
|
378
|
-
|
|
379
|
-
// Start HTTP server
|
|
380
|
-
blok::server::serve(registry, 8080).await.unwrap();
|
|
234
|
+
/// register wires this node into the runtime registry. The generated
|
|
235
|
+
/// user_nodes/mod.rs calls it for every node under runtimes/rust/nodes.
|
|
236
|
+
pub fn register(registry: &mut NodeRegistry) {
|
|
237
|
+
registry.register("{{NODE_NAME}}", {{NODE_NAME_PASCAL}}Node);
|
|
381
238
|
}
|
|
382
239
|
`;
|
|
383
|
-
const rust_cargo_file = `[package]
|
|
384
|
-
name = "{{NODE_NAME}}"
|
|
385
|
-
version = "1.0.0"
|
|
386
|
-
edition = "2021"
|
|
387
|
-
|
|
388
|
-
[[bin]]
|
|
389
|
-
name = "{{NODE_NAME}}"
|
|
390
|
-
path = "src/main.rs"
|
|
391
|
-
|
|
392
|
-
[dependencies]
|
|
393
|
-
blok = { path = "../../sdk" }
|
|
394
|
-
tokio = { version = "1", features = ["full"] }
|
|
395
|
-
serde = { version = "1", features = ["derive"] }
|
|
396
|
-
serde_json = "1"
|
|
397
|
-
async-trait = "0.1"
|
|
398
|
-
tracing = "0.1"
|
|
399
|
-
tracing-subscriber = "0.3"
|
|
400
|
-
`;
|
|
401
|
-
const rust_dockerfile = `FROM rust:1.77-alpine AS builder
|
|
402
|
-
|
|
403
|
-
RUN apk add --no-cache musl-dev
|
|
404
|
-
|
|
405
|
-
WORKDIR /app
|
|
406
|
-
COPY Cargo.toml Cargo.lock ./
|
|
407
|
-
RUN mkdir -p src && echo 'fn main() {}' > src/main.rs && \\
|
|
408
|
-
cargo build --release 2>/dev/null || true && rm -rf src
|
|
409
|
-
|
|
410
|
-
COPY . .
|
|
411
|
-
RUN cargo build --release
|
|
412
|
-
|
|
413
|
-
FROM alpine:latest
|
|
414
|
-
RUN apk --no-cache add ca-certificates
|
|
415
|
-
WORKDIR /root/
|
|
416
|
-
COPY --from=builder /app/target/release/{{NODE_NAME}} .
|
|
417
|
-
|
|
418
|
-
EXPOSE 8080
|
|
419
|
-
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\
|
|
420
|
-
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1
|
|
421
|
-
|
|
422
|
-
CMD ["./{{NODE_NAME}}"]
|
|
423
|
-
`;
|
|
424
240
|
const csharp_node_file = `using System.Text.Json;
|
|
425
|
-
using Blok.
|
|
241
|
+
using Blok.Core.Node;
|
|
242
|
+
using Blok.Core.Types;
|
|
426
243
|
|
|
427
|
-
namespace Blok.
|
|
244
|
+
namespace Blok.Core.Nodes;
|
|
428
245
|
|
|
246
|
+
/// <summary>
|
|
247
|
+
/// {{NODE_NAME_PASCAL}}Node — a Blok node for the C# runtime. Discovered under
|
|
248
|
+
/// runtimes/csharp/nodes/ and registered into the shared gRPC server alongside
|
|
249
|
+
/// the built-in nodes (same model as the other SDKs). Run \`blokctl dev\`; no
|
|
250
|
+
/// per-node csproj/Dockerfile — it isn't a standalone service.
|
|
251
|
+
/// </summary>
|
|
429
252
|
public class {{NODE_NAME_PASCAL}}Node : INodeHandler
|
|
430
253
|
{
|
|
254
|
+
/// <summary>
|
|
255
|
+
/// Execute the node. Input arrives on ctx.Request; config holds the step's
|
|
256
|
+
/// inputs from the workflow. Return any JSON-serialisable value.
|
|
257
|
+
/// </summary>
|
|
431
258
|
public Task<JsonElement> ExecuteAsync(Context ctx, Dictionary<string, JsonElement> config)
|
|
432
259
|
{
|
|
433
|
-
// Access request body
|
|
434
260
|
var name = "World";
|
|
435
261
|
if (ctx.Request.Body.ValueKind == JsonValueKind.Object &&
|
|
436
262
|
ctx.Request.Body.TryGetProperty("name", out var nameEl) &&
|
|
@@ -439,7 +265,6 @@ public class {{NODE_NAME_PASCAL}}Node : INodeHandler
|
|
|
439
265
|
name = nameEl.GetString() ?? "World";
|
|
440
266
|
}
|
|
441
267
|
|
|
442
|
-
// Access configuration
|
|
443
268
|
var prefix = "Hello";
|
|
444
269
|
if (config.TryGetValue("prefix", out var prefixEl) &&
|
|
445
270
|
prefixEl.ValueKind == JsonValueKind.String)
|
|
@@ -448,11 +273,8 @@ public class {{NODE_NAME_PASCAL}}Node : INodeHandler
|
|
|
448
273
|
}
|
|
449
274
|
|
|
450
275
|
var message = $"{prefix}, {name}!";
|
|
276
|
+
ctx.SetVar("greeting", message);
|
|
451
277
|
|
|
452
|
-
// Store in context for downstream nodes
|
|
453
|
-
ctx.Vars["greeting"] = JsonSerializer.SerializeToElement(message);
|
|
454
|
-
|
|
455
|
-
// Return response
|
|
456
278
|
var result = JsonSerializer.SerializeToElement(new
|
|
457
279
|
{
|
|
458
280
|
message,
|
|
@@ -464,154 +286,58 @@ public class {{NODE_NAME_PASCAL}}Node : INodeHandler
|
|
|
464
286
|
}
|
|
465
287
|
}
|
|
466
288
|
`;
|
|
467
|
-
const csharp_csproj_file = `<Project Sdk="Microsoft.NET.Sdk.Web">
|
|
468
|
-
<PropertyGroup>
|
|
469
|
-
<TargetFramework>net8.0</TargetFramework>
|
|
470
|
-
<RootNamespace>Blok.Runtime</RootNamespace>
|
|
471
|
-
<ImplicitUsings>enable</ImplicitUsings>
|
|
472
|
-
<Nullable>enable</Nullable>
|
|
473
|
-
</PropertyGroup>
|
|
474
|
-
</Project>
|
|
475
|
-
`;
|
|
476
|
-
const csharp_dockerfile = `FROM mcr.microsoft.com/dotnet/sdk:8.0 AS builder
|
|
477
|
-
WORKDIR /app
|
|
478
|
-
COPY *.csproj .
|
|
479
|
-
RUN dotnet restore
|
|
480
|
-
COPY . .
|
|
481
|
-
RUN dotnet publish -c Release -o /out
|
|
482
|
-
|
|
483
|
-
FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine
|
|
484
|
-
WORKDIR /app
|
|
485
|
-
COPY --from=builder /out .
|
|
486
|
-
|
|
487
|
-
EXPOSE 8080
|
|
488
|
-
ENV PORT=8080
|
|
489
|
-
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\
|
|
490
|
-
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1
|
|
491
|
-
|
|
492
|
-
CMD ["dotnet", "BlokRuntime.dll"]
|
|
493
|
-
`;
|
|
494
289
|
const php_node_file = `<?php
|
|
495
290
|
|
|
496
|
-
|
|
291
|
+
declare(strict_types=1);
|
|
497
292
|
|
|
498
|
-
|
|
499
|
-
use Blok\\Context;
|
|
293
|
+
namespace Blok\\Blok\\Nodes\\{{NODE_NAME_PASCAL}};
|
|
500
294
|
|
|
501
|
-
|
|
295
|
+
use Blok\\Blok\\Node\\NodeHandler;
|
|
296
|
+
use Blok\\Blok\\Types\\Context;
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* {{NODE_NAME}} — a Blok node for the PHP runtime.
|
|
300
|
+
*
|
|
301
|
+
* Input arrives on \$ctx->request; \$config holds the step's inputs from the
|
|
302
|
+
* workflow. Return any JSON-serialisable value (array, scalar, etc.).
|
|
303
|
+
*/
|
|
304
|
+
final class {{NODE_NAME_PASCAL}}Node implements NodeHandler
|
|
502
305
|
{
|
|
503
306
|
public function execute(Context $ctx, array $config): mixed
|
|
504
307
|
{
|
|
505
|
-
|
|
506
|
-
$
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
$prefix = $config['prefix'] ?? 'Hello';
|
|
308
|
+
$name = $ctx->request->bodyStr('name') ?? 'World';
|
|
309
|
+
$prefix = isset($config['prefix']) && is_string($config['prefix'])
|
|
310
|
+
? $config['prefix']
|
|
311
|
+
: 'Hello';
|
|
510
312
|
|
|
511
|
-
$message = "$prefix, $name!";
|
|
512
|
-
|
|
513
|
-
// Store in context for downstream nodes
|
|
514
|
-
$ctx->vars['greeting'] = $message;
|
|
515
|
-
|
|
516
|
-
// Return response
|
|
517
313
|
return [
|
|
518
|
-
'message' => $
|
|
519
|
-
'timestamp' => date('c'),
|
|
314
|
+
'message' => sprintf('%s, %s!', $prefix, $name),
|
|
520
315
|
'language' => 'PHP',
|
|
521
316
|
];
|
|
522
317
|
}
|
|
523
318
|
}
|
|
524
319
|
`;
|
|
525
|
-
const
|
|
526
|
-
"name": "blok/{{NODE_NAME}}",
|
|
527
|
-
"type": "project",
|
|
528
|
-
"require": {
|
|
529
|
-
"php": ">=8.2",
|
|
530
|
-
"react/http": "^1.9",
|
|
531
|
-
"react/socket": "^1.15"
|
|
532
|
-
},
|
|
533
|
-
"autoload": {
|
|
534
|
-
"psr-4": {
|
|
535
|
-
"Blok\\\\": "src/"
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
`;
|
|
540
|
-
const php_dockerfile = `FROM php:8.2-cli-alpine AS builder
|
|
541
|
-
WORKDIR /app
|
|
542
|
-
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
|
|
543
|
-
COPY composer.json .
|
|
544
|
-
RUN composer install --no-dev --optimize-autoloader
|
|
545
|
-
COPY . .
|
|
546
|
-
|
|
547
|
-
FROM php:8.2-cli-alpine
|
|
548
|
-
WORKDIR /app
|
|
549
|
-
COPY --from=builder /app .
|
|
550
|
-
|
|
551
|
-
EXPOSE 8080
|
|
552
|
-
ENV PORT=8080
|
|
553
|
-
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\
|
|
554
|
-
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1
|
|
555
|
-
|
|
556
|
-
CMD ["php", "index.php"]
|
|
557
|
-
`;
|
|
558
|
-
const ruby_node_file = `require_relative '../../lib/blok'
|
|
559
|
-
|
|
560
|
-
module Blok
|
|
561
|
-
module Nodes
|
|
562
|
-
class {{NODE_NAME_PASCAL}}Node < Blok::NodeHandler
|
|
563
|
-
def execute(ctx, config)
|
|
564
|
-
# Access request body
|
|
565
|
-
name = ctx.request.body.is_a?(Hash) ? ctx.request.body['name'] : nil
|
|
566
|
-
name ||= 'World'
|
|
320
|
+
const ruby_node_file = `# frozen_string_literal: true
|
|
567
321
|
|
|
568
|
-
|
|
569
|
-
|
|
322
|
+
# {{NODE_NAME_PASCAL}}Node — registered as "{{NODE_NAME}}" by the Ruby runtime.
|
|
323
|
+
#
|
|
324
|
+
# Request body arrives on ctx.request (use body_str(key) for a String|nil);
|
|
325
|
+
# config holds the step's inputs from the workflow. Return any
|
|
326
|
+
# JSON-serialisable Hash. Publish to downstream steps with ctx.set_var(k, v).
|
|
327
|
+
class {{NODE_NAME_PASCAL}}Node < Blok::Node::NodeHandler
|
|
328
|
+
def execute(ctx, config)
|
|
329
|
+
name = ctx.request.body_str("name") || "World"
|
|
330
|
+
prefix = config["prefix"] || "Hello"
|
|
570
331
|
|
|
571
|
-
|
|
332
|
+
message = "#{prefix}, #{name}!"
|
|
333
|
+
ctx.set_var("greeting", message)
|
|
572
334
|
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
{
|
|
578
|
-
'message' => message,
|
|
579
|
-
'timestamp' => Time.now.utc.iso8601,
|
|
580
|
-
'language' => 'Ruby'
|
|
581
|
-
}
|
|
582
|
-
end
|
|
583
|
-
end
|
|
335
|
+
{
|
|
336
|
+
"message" => message,
|
|
337
|
+
"language" => "Ruby"
|
|
338
|
+
}
|
|
584
339
|
end
|
|
585
|
-
end
|
|
586
|
-
`;
|
|
587
|
-
const ruby_gemfile = `source 'https://rubygems.org'
|
|
588
|
-
|
|
589
|
-
ruby '>= 3.1'
|
|
590
|
-
|
|
591
|
-
gem 'sinatra', '~> 4.0'
|
|
592
|
-
gem 'puma', '~> 6.4'
|
|
593
|
-
gem 'rackup', '~> 2.1'
|
|
594
|
-
`;
|
|
595
|
-
const ruby_dockerfile = `FROM ruby:3.2-alpine AS builder
|
|
596
|
-
RUN apk add --no-cache build-base
|
|
597
|
-
WORKDIR /app
|
|
598
|
-
COPY Gemfile Gemfile.lock ./
|
|
599
|
-
RUN bundle install --without development test
|
|
600
|
-
|
|
601
|
-
FROM ruby:3.2-alpine
|
|
602
|
-
RUN apk --no-cache add ca-certificates wget
|
|
603
|
-
WORKDIR /app
|
|
604
|
-
COPY --from=builder /usr/local/bundle /usr/local/bundle
|
|
605
|
-
COPY . .
|
|
606
|
-
|
|
607
|
-
EXPOSE 8080
|
|
608
|
-
ENV PORT=8080
|
|
609
|
-
ENV RACK_ENV=production
|
|
610
|
-
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\
|
|
611
|
-
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1
|
|
612
|
-
|
|
613
|
-
CMD ["bundle", "exec", "puma", "-b", "tcp://0.0.0.0:8080"]
|
|
614
|
-
`;
|
|
340
|
+
end`;
|
|
615
341
|
const agents_md = `
|
|
616
342
|
# AGENTS.md — Blok Framework AI Context
|
|
617
343
|
|
|
@@ -1776,4 +1502,4 @@ export default defineNode({
|
|
|
1776
1502
|
},
|
|
1777
1503
|
});
|
|
1778
1504
|
`;
|
|
1779
|
-
export { node_file, package_dependencies, package_dev_dependencies, python3_file, examples_url, workflow_template, supervisord_nodejs, supervisord_python, go_node_file,
|
|
1505
|
+
export { node_file, package_dependencies, package_dev_dependencies, python3_file, examples_url, workflow_template, supervisord_nodejs, supervisord_python, go_node_file, java_node_file, rust_node_file, csharp_node_file, php_node_file, ruby_node_file, function_first_node_file, agents_md, claude_md, };
|