blokctl 0.2.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/build/index.d.ts +2 -0
- package/dist/commands/build/index.js +210 -0
- package/dist/commands/config/index.d.ts +1 -0
- package/dist/commands/config/index.js +46 -0
- package/dist/commands/cost/index.d.ts +1 -0
- package/dist/commands/cost/index.js +74 -0
- package/dist/commands/create/node.d.ts +2 -0
- package/dist/commands/create/node.js +541 -0
- package/dist/commands/create/project.d.ts +2 -0
- package/dist/commands/create/project.js +941 -0
- package/dist/commands/create/utils/Examples.d.ts +39 -0
- package/dist/commands/create/utils/Examples.js +983 -0
- package/dist/commands/create/workflow.d.ts +2 -0
- package/dist/commands/create/workflow.js +109 -0
- package/dist/commands/deploy/index.d.ts +2 -0
- package/dist/commands/deploy/index.js +176 -0
- package/dist/commands/dev/index.d.ts +2 -0
- package/dist/commands/dev/index.js +190 -0
- package/dist/commands/generate/GenerationAnalytics.d.ts +61 -0
- package/dist/commands/generate/GenerationAnalytics.js +162 -0
- package/dist/commands/generate/GenerationAnalytics.test.d.ts +1 -0
- package/dist/commands/generate/GenerationAnalytics.test.js +407 -0
- package/dist/commands/generate/NodeFileWriter.d.ts +5 -0
- package/dist/commands/generate/NodeFileWriter.js +240 -0
- package/dist/commands/generate/NodeGenerator.d.ts +20 -0
- package/dist/commands/generate/NodeGenerator.js +181 -0
- package/dist/commands/generate/NodeGenerator.test.d.ts +1 -0
- package/dist/commands/generate/NodeGenerator.test.js +101 -0
- package/dist/commands/generate/PromptVersioning.d.ts +25 -0
- package/dist/commands/generate/PromptVersioning.js +71 -0
- package/dist/commands/generate/PromptVersioning.test.d.ts +1 -0
- package/dist/commands/generate/PromptVersioning.test.js +120 -0
- package/dist/commands/generate/RegisterNode.d.ts +3 -0
- package/dist/commands/generate/RegisterNode.js +37 -0
- package/dist/commands/generate/RuntimeGenerator.d.ts +40 -0
- package/dist/commands/generate/RuntimeGenerator.js +369 -0
- package/dist/commands/generate/RuntimeGenerator.test.d.ts +1 -0
- package/dist/commands/generate/RuntimeGenerator.test.js +553 -0
- package/dist/commands/generate/TriggerGenerator.d.ts +22 -0
- package/dist/commands/generate/TriggerGenerator.js +220 -0
- package/dist/commands/generate/TriggerGenerator.test.d.ts +1 -0
- package/dist/commands/generate/TriggerGenerator.test.js +209 -0
- package/dist/commands/generate/WorkflowGenerator.d.ts +20 -0
- package/dist/commands/generate/WorkflowGenerator.js +131 -0
- package/dist/commands/generate/WorkflowGenerator.test.d.ts +1 -0
- package/dist/commands/generate/WorkflowGenerator.test.js +77 -0
- package/dist/commands/generate/e2e/NodeGenerator.e2e.test.d.ts +1 -0
- package/dist/commands/generate/e2e/NodeGenerator.e2e.test.js +216 -0
- package/dist/commands/generate/e2e/RuntimeGenerator.e2e.test.d.ts +1 -0
- package/dist/commands/generate/e2e/RuntimeGenerator.e2e.test.js +759 -0
- package/dist/commands/generate/e2e/TriggerGenerator.e2e.test.d.ts +1 -0
- package/dist/commands/generate/e2e/TriggerGenerator.e2e.test.js +295 -0
- package/dist/commands/generate/e2e/WorkflowGenerator.e2e.test.d.ts +1 -0
- package/dist/commands/generate/e2e/WorkflowGenerator.e2e.test.js +353 -0
- package/dist/commands/generate/index.d.ts +1 -0
- package/dist/commands/generate/index.js +418 -0
- package/dist/commands/generate/prompts/create-fn-node.system.d.ts +5 -0
- package/dist/commands/generate/prompts/create-fn-node.system.js +256 -0
- package/dist/commands/generate/prompts/create-node-manifest.system.d.ts +4 -0
- package/dist/commands/generate/prompts/create-node-manifest.system.js +41 -0
- package/dist/commands/generate/prompts/create-node.system.d.ts +5 -0
- package/dist/commands/generate/prompts/create-node.system.js +114 -0
- package/dist/commands/generate/prompts/create-readme.system.d.ts +4 -0
- package/dist/commands/generate/prompts/create-readme.system.js +83 -0
- package/dist/commands/generate/prompts/create-runtime.system.d.ts +5 -0
- package/dist/commands/generate/prompts/create-runtime.system.js +284 -0
- package/dist/commands/generate/prompts/create-trigger.system.d.ts +5 -0
- package/dist/commands/generate/prompts/create-trigger.system.js +293 -0
- package/dist/commands/generate/prompts/create-workflow.system.d.ts +5 -0
- package/dist/commands/generate/prompts/create-workflow.system.js +476 -0
- package/dist/commands/generate/prompts/register-node.system.d.ts +4 -0
- package/dist/commands/generate/prompts/register-node.system.js +26 -0
- package/dist/commands/generate/validators/CompilationValidator.d.ts +9 -0
- package/dist/commands/generate/validators/CompilationValidator.js +86 -0
- package/dist/commands/generate/validators/CompilationValidator.test.d.ts +1 -0
- package/dist/commands/generate/validators/CompilationValidator.test.js +161 -0
- package/dist/commands/generate/validators/NodeValidator.d.ts +18 -0
- package/dist/commands/generate/validators/NodeValidator.js +217 -0
- package/dist/commands/generate/validators/NodeValidator.test.d.ts +1 -0
- package/dist/commands/generate/validators/NodeValidator.test.js +281 -0
- package/dist/commands/generate/validators/WorkflowValidator.d.ts +6 -0
- package/dist/commands/generate/validators/WorkflowValidator.js +301 -0
- package/dist/commands/generate/validators/WorkflowValidator.test.d.ts +1 -0
- package/dist/commands/generate/validators/WorkflowValidator.test.js +647 -0
- package/dist/commands/generate/validators/index.d.ts +4 -0
- package/dist/commands/generate/validators/index.js +2 -0
- package/dist/commands/graph/index.d.ts +1 -0
- package/dist/commands/graph/index.js +69 -0
- package/dist/commands/install/index.d.ts +1 -0
- package/dist/commands/install/index.js +4 -0
- package/dist/commands/install/node.d.ts +4 -0
- package/dist/commands/install/node.js +136 -0
- package/dist/commands/install/workflow.d.ts +4 -0
- package/dist/commands/install/workflow.js +62 -0
- package/dist/commands/login/index.d.ts +2 -0
- package/dist/commands/login/index.js +77 -0
- package/dist/commands/logout/index.d.ts +2 -0
- package/dist/commands/logout/index.js +20 -0
- package/dist/commands/marketplace/runtime.d.ts +54 -0
- package/dist/commands/marketplace/runtime.js +350 -0
- package/dist/commands/migrate/index.d.ts +1 -0
- package/dist/commands/migrate/index.js +14 -0
- package/dist/commands/migrate/node.d.ts +2 -0
- package/dist/commands/migrate/node.js +110 -0
- package/dist/commands/monitor/index.d.ts +1 -0
- package/dist/commands/monitor/index.js +28 -0
- package/dist/commands/monitor/monitor-component.d.ts +1 -0
- package/dist/commands/monitor/monitor-component.js +271 -0
- package/dist/commands/monitor/static/index.html +2124 -0
- package/dist/commands/monitor/static-web-server.d.ts +1 -0
- package/dist/commands/monitor/static-web-server.js +89 -0
- package/dist/commands/profile/index.d.ts +1 -0
- package/dist/commands/profile/index.js +112 -0
- package/dist/commands/publish/index.d.ts +1 -0
- package/dist/commands/publish/index.js +4 -0
- package/dist/commands/publish/node.d.ts +4 -0
- package/dist/commands/publish/node.js +231 -0
- package/dist/commands/publish/workflow.d.ts +4 -0
- package/dist/commands/publish/workflow.js +165 -0
- package/dist/commands/search/docs.d.ts +17 -0
- package/dist/commands/search/docs.js +179 -0
- package/dist/commands/search/index.d.ts +1 -0
- package/dist/commands/search/index.js +5 -0
- package/dist/commands/search/indexer.d.ts +10 -0
- package/dist/commands/search/indexer.js +265 -0
- package/dist/commands/search/nodes.d.ts +4 -0
- package/dist/commands/search/nodes.js +101 -0
- package/dist/commands/search/workflow.d.ts +4 -0
- package/dist/commands/search/workflow.js +100 -0
- package/dist/commands/trace/index.d.ts +1 -0
- package/dist/commands/trace/index.js +26 -0
- package/dist/commands/trace/startStudio.d.ts +8 -0
- package/dist/commands/trace/startStudio.js +116 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +186 -0
- package/dist/services/commander.d.ts +9 -0
- package/dist/services/commander.js +20 -0
- package/dist/services/constants.d.ts +1 -0
- package/dist/services/constants.js +3 -0
- package/dist/services/local-token-manager.d.ts +14 -0
- package/dist/services/local-token-manager.js +99 -0
- package/dist/services/non-interactive.d.ts +5 -0
- package/dist/services/non-interactive.js +30 -0
- package/dist/services/package-manager.d.ts +35 -0
- package/dist/services/package-manager.js +111 -0
- package/dist/services/posthog.d.ts +31 -0
- package/dist/services/posthog.js +159 -0
- package/dist/services/registry-manager.d.ts +9 -0
- package/dist/services/registry-manager.js +26 -0
- package/dist/services/runtime-detector.d.ts +23 -0
- package/dist/services/runtime-detector.js +181 -0
- package/dist/services/runtime-setup.d.ts +36 -0
- package/dist/services/runtime-setup.js +250 -0
- package/dist/services/utils.d.ts +2 -0
- package/dist/services/utils.js +29 -0
- package/dist/services/workflow-loader.d.ts +30 -0
- package/dist/services/workflow-loader.js +46 -0
- package/dist/studio-dist/assets/charts-Dso0hPUR.js +68 -0
- package/dist/studio-dist/assets/graph-CsV2nWGn.js +23 -0
- package/dist/studio-dist/assets/icons-zP8LLgPh.js +311 -0
- package/dist/studio-dist/assets/index-CLyEkXMx.css +1 -0
- package/dist/studio-dist/assets/index-CNXFX_ar.js +27 -0
- package/dist/studio-dist/assets/react-vendor--Eh9ivFN.js +17 -0
- package/dist/studio-dist/assets/tanstack-query-CiM1U6F5.js +1 -0
- package/dist/studio-dist/assets/tanstack-router-Btjy0MKq.js +25 -0
- package/dist/studio-dist/assets/tanstack-table-DhwRvuH2.js +22 -0
- package/dist/studio-dist/favicon.svg +5 -0
- package/dist/studio-dist/index.html +21 -0
- package/package.json +75 -0
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
const createWorkflowSystemPrompt = {
|
|
2
|
+
prompt: `You are a senior backend engineer specializing in the Blok (blok) workflow framework. Your task is to generate a fully working **Workflow JSON configuration file** that implements the described logic.
|
|
3
|
+
|
|
4
|
+
What to return:
|
|
5
|
+
|
|
6
|
+
* Return only a complete JSON object representing a workflow configuration, ready to be saved directly into \`workflows/json/<workflow-name>.json\`.
|
|
7
|
+
* The JSON object MUST include:
|
|
8
|
+
|
|
9
|
+
1. \`name\`: A descriptive name for the workflow
|
|
10
|
+
2. \`description\`: A short human-readable description of what the workflow does
|
|
11
|
+
3. \`version\`: Semantic version string (e.g., "1.0.0")
|
|
12
|
+
4. \`trigger\`: An object with exactly ONE trigger type and its configuration
|
|
13
|
+
5. \`steps\`: An ordered array of entry step objects (the workflow execution plan)
|
|
14
|
+
6. \`nodes\`: A map of node configurations keyed by step names
|
|
15
|
+
|
|
16
|
+
## Trigger Types
|
|
17
|
+
|
|
18
|
+
The workflow can be triggered by one of these types:
|
|
19
|
+
|
|
20
|
+
### HTTP Trigger
|
|
21
|
+
\`\`\`json
|
|
22
|
+
"trigger": {
|
|
23
|
+
"http": {
|
|
24
|
+
"method": "GET",
|
|
25
|
+
"path": "/api/resource",
|
|
26
|
+
"accept": "application/json"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
\`\`\`
|
|
30
|
+
- \`method\`: "GET", "POST", "PUT", "DELETE", "PATCH", or "*" (any method)
|
|
31
|
+
- \`path\`: Express-style route with optional params (e.g., "/:id", "/:function?/:id?")
|
|
32
|
+
- \`accept\`: Content type accepted
|
|
33
|
+
|
|
34
|
+
### Queue Trigger
|
|
35
|
+
\`\`\`json
|
|
36
|
+
"trigger": {
|
|
37
|
+
"queue": {
|
|
38
|
+
"provider": "kafka",
|
|
39
|
+
"topic": "user-events",
|
|
40
|
+
"consumerGroup": "my-consumer-group",
|
|
41
|
+
"ack": true,
|
|
42
|
+
"batchSize": 1,
|
|
43
|
+
"concurrency": 1
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
\`\`\`
|
|
47
|
+
- \`provider\`: "kafka", "rabbitmq", "sqs", or "redis"
|
|
48
|
+
- \`topic\`: Queue/topic name to consume from
|
|
49
|
+
- \`consumerGroup\`: Consumer group ID (for Kafka)
|
|
50
|
+
- \`ack\`: Whether to acknowledge after processing (default: true)
|
|
51
|
+
|
|
52
|
+
### Pub/Sub Trigger
|
|
53
|
+
\`\`\`json
|
|
54
|
+
"trigger": {
|
|
55
|
+
"pubsub": {
|
|
56
|
+
"provider": "gcp",
|
|
57
|
+
"topic": "user-notifications",
|
|
58
|
+
"subscription": "notification-worker",
|
|
59
|
+
"ack": true,
|
|
60
|
+
"maxMessages": 10
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
\`\`\`
|
|
64
|
+
- \`provider\`: "gcp", "aws", or "azure"
|
|
65
|
+
- \`topic\`: Topic name
|
|
66
|
+
- \`subscription\`: Subscription name
|
|
67
|
+
|
|
68
|
+
### Cron Trigger
|
|
69
|
+
\`\`\`json
|
|
70
|
+
"trigger": {
|
|
71
|
+
"cron": {
|
|
72
|
+
"schedule": "0 * * * *",
|
|
73
|
+
"timezone": "America/New_York",
|
|
74
|
+
"overlap": false
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
\`\`\`
|
|
78
|
+
- \`schedule\`: Standard cron expression
|
|
79
|
+
- \`timezone\`: IANA timezone name (default: "UTC")
|
|
80
|
+
- \`overlap\`: Allow overlapping executions (default: false)
|
|
81
|
+
|
|
82
|
+
### Webhook Trigger
|
|
83
|
+
\`\`\`json
|
|
84
|
+
"trigger": {
|
|
85
|
+
"webhook": {
|
|
86
|
+
"source": "github",
|
|
87
|
+
"events": ["push", "pull_request.*"],
|
|
88
|
+
"secret": "\${process.env.GITHUB_WEBHOOK_SECRET}",
|
|
89
|
+
"path": "/webhooks/github"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
\`\`\`
|
|
93
|
+
- \`source\`: "github", "stripe", "shopify", or "custom"
|
|
94
|
+
- \`events\`: Array of event types to listen for (supports wildcards)
|
|
95
|
+
- \`secret\`: Webhook secret for signature verification
|
|
96
|
+
|
|
97
|
+
### WebSocket Trigger
|
|
98
|
+
\`\`\`json
|
|
99
|
+
"trigger": {
|
|
100
|
+
"websocket": {
|
|
101
|
+
"events": ["message", "join", "leave"],
|
|
102
|
+
"path": "/ws",
|
|
103
|
+
"maxConnections": 10000,
|
|
104
|
+
"heartbeatInterval": 30000
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
\`\`\`
|
|
108
|
+
|
|
109
|
+
### SSE Trigger
|
|
110
|
+
\`\`\`json
|
|
111
|
+
"trigger": {
|
|
112
|
+
"sse": {
|
|
113
|
+
"events": ["update", "notification"],
|
|
114
|
+
"channels": ["feed", "alerts"],
|
|
115
|
+
"path": "/events",
|
|
116
|
+
"heartbeatInterval": 30000
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
\`\`\`
|
|
120
|
+
|
|
121
|
+
## Steps Structure
|
|
122
|
+
|
|
123
|
+
Steps are an ordered array of step objects:
|
|
124
|
+
|
|
125
|
+
\`\`\`json
|
|
126
|
+
"steps": [
|
|
127
|
+
{
|
|
128
|
+
"name": "step-key-name",
|
|
129
|
+
"node": "@blok/api-call",
|
|
130
|
+
"type": "module"
|
|
131
|
+
}
|
|
132
|
+
]
|
|
133
|
+
\`\`\`
|
|
134
|
+
|
|
135
|
+
- \`name\`: Unique identifier for this step (used as key in \`nodes\` map)
|
|
136
|
+
- \`node\`: Node package/module name (e.g., "@blok/api-call" for module types, or custom node names for local types)
|
|
137
|
+
- \`type\`: "module" (from node_modules), "local" (from src/nodes/), or "runtime.python3" (Python runtime)
|
|
138
|
+
|
|
139
|
+
## Nodes Configuration
|
|
140
|
+
|
|
141
|
+
Each step MUST have a corresponding entry in the \`nodes\` map.
|
|
142
|
+
|
|
143
|
+
### Simple Node (with inputs)
|
|
144
|
+
\`\`\`json
|
|
145
|
+
"nodes": {
|
|
146
|
+
"step-name": {
|
|
147
|
+
"inputs": {
|
|
148
|
+
"url": "https://api.example.com/data",
|
|
149
|
+
"method": "GET",
|
|
150
|
+
"headers": { "Authorization": "Bearer \${ctx.env.API_KEY}" }
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
\`\`\`
|
|
155
|
+
|
|
156
|
+
### Conditional Node (if-else routing)
|
|
157
|
+
\`\`\`json
|
|
158
|
+
"nodes": {
|
|
159
|
+
"filter-request": {
|
|
160
|
+
"conditions": [
|
|
161
|
+
{
|
|
162
|
+
"type": "if",
|
|
163
|
+
"condition": "ctx.request.method.toLowerCase() === \\"get\\" && ctx.request.params.function === undefined",
|
|
164
|
+
"steps": [
|
|
165
|
+
{ "name": "get-data", "node": "fetch-data", "type": "module" }
|
|
166
|
+
]
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
"type": "if",
|
|
170
|
+
"condition": "ctx.request.method.toLowerCase() === \\"post\\"",
|
|
171
|
+
"steps": [
|
|
172
|
+
{ "name": "create-data", "node": "save-data", "type": "module" }
|
|
173
|
+
]
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"type": "else",
|
|
177
|
+
"steps": [
|
|
178
|
+
{ "name": "not-allowed", "node": "error", "type": "module" }
|
|
179
|
+
]
|
|
180
|
+
}
|
|
181
|
+
]
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
\`\`\`
|
|
185
|
+
|
|
186
|
+
## Input Value Patterns
|
|
187
|
+
|
|
188
|
+
Node inputs support these patterns:
|
|
189
|
+
|
|
190
|
+
1. **Static values**: Direct strings, numbers, objects, arrays
|
|
191
|
+
\`\`\`json
|
|
192
|
+
"message": "Hello World"
|
|
193
|
+
\`\`\`
|
|
194
|
+
|
|
195
|
+
2. **Context interpolation**: Use \${ctx.*} to read from the workflow context
|
|
196
|
+
\`\`\`json
|
|
197
|
+
"userId": "\${ctx.request.params.id}"
|
|
198
|
+
"query": "\${ctx.request.query.search}"
|
|
199
|
+
"body": "\${ctx.request.body}"
|
|
200
|
+
\`\`\`
|
|
201
|
+
|
|
202
|
+
3. **JavaScript expressions**: Prefix with "js/" for dynamic evaluation
|
|
203
|
+
\`\`\`json
|
|
204
|
+
"path": "js/process.env.DATA_PATH + '/files'"
|
|
205
|
+
"data": "js/ctx.response.data"
|
|
206
|
+
"value": "js/JSON.stringify(ctx.request.body)"
|
|
207
|
+
\`\`\`
|
|
208
|
+
|
|
209
|
+
4. **Previous node output**: Use ctx.vars to access outputs from previous steps
|
|
210
|
+
\`\`\`json
|
|
211
|
+
"input": "js/ctx.vars['previous-step-name']"
|
|
212
|
+
\`\`\`
|
|
213
|
+
|
|
214
|
+
## Context Properties Available in Conditions and Inputs
|
|
215
|
+
|
|
216
|
+
- \`ctx.request.method\`: HTTP method (GET, POST, etc.)
|
|
217
|
+
- \`ctx.request.params\`: URL path parameters (e.g., :id, :function)
|
|
218
|
+
- \`ctx.request.query\`: URL query parameters
|
|
219
|
+
- \`ctx.request.body\`: Request body
|
|
220
|
+
- \`ctx.request.headers\`: Request headers
|
|
221
|
+
- \`ctx.response.data\`: Current response data (set by previous nodes)
|
|
222
|
+
- \`ctx.vars['node-name']\`: Output from a specific previous node
|
|
223
|
+
- \`ctx.env.VARIABLE_NAME\`: Environment variables (via process.env)
|
|
224
|
+
- \`ctx.id\`: Unique request ID
|
|
225
|
+
- \`ctx.workflow_name\`: Workflow name
|
|
226
|
+
|
|
227
|
+
## Available Built-in Nodes
|
|
228
|
+
|
|
229
|
+
- \`@blok/api-call\`: Makes HTTP API calls (inputs: url, method, headers, body, responseType)
|
|
230
|
+
- \`@blok/if-else\`: Conditional routing (uses conditions array instead of inputs)
|
|
231
|
+
- \`@blok/react\`: Server-side React rendering (inputs: template, props)
|
|
232
|
+
- \`error\`: Returns error response (inputs: message, code)
|
|
233
|
+
|
|
234
|
+
## Constraints
|
|
235
|
+
|
|
236
|
+
* The JSON MUST be valid and well-formed
|
|
237
|
+
* Every step name in \`steps\` MUST have a matching key in \`nodes\`
|
|
238
|
+
* Every step referenced in conditional branches MUST also have a matching key in \`nodes\`
|
|
239
|
+
* Condition expressions MUST be valid JavaScript using only ctx.* properties
|
|
240
|
+
* The workflow MUST have exactly ONE trigger type
|
|
241
|
+
* Always include a fallback "else" branch in conditional routing for error handling
|
|
242
|
+
* Use descriptive step names in kebab-case (e.g., "fetch-user", "validate-input")
|
|
243
|
+
* Use descriptive workflow names
|
|
244
|
+
* Reference environment variables with ctx.env.VARIABLE_NAME (not process.env directly in inputs)
|
|
245
|
+
|
|
246
|
+
## Real-World Examples
|
|
247
|
+
|
|
248
|
+
### Example 1: Simple API Proxy
|
|
249
|
+
\`\`\`json
|
|
250
|
+
{
|
|
251
|
+
"name": "Country Data API",
|
|
252
|
+
"description": "Fetches country data from external API",
|
|
253
|
+
"version": "1.0.0",
|
|
254
|
+
"trigger": {
|
|
255
|
+
"http": {
|
|
256
|
+
"method": "GET",
|
|
257
|
+
"path": "/",
|
|
258
|
+
"accept": "application/json"
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
"steps": [
|
|
262
|
+
{
|
|
263
|
+
"name": "get-countries",
|
|
264
|
+
"node": "@blok/api-call",
|
|
265
|
+
"type": "module"
|
|
266
|
+
}
|
|
267
|
+
],
|
|
268
|
+
"nodes": {
|
|
269
|
+
"get-countries": {
|
|
270
|
+
"inputs": {
|
|
271
|
+
"url": "https://countriesnow.space/api/v0.1/countries/capital",
|
|
272
|
+
"method": "GET",
|
|
273
|
+
"headers": { "Content-Type": "application/json" },
|
|
274
|
+
"responseType": "application/json"
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
\`\`\`
|
|
280
|
+
|
|
281
|
+
### Example 2: CRUD with Conditional Routing
|
|
282
|
+
\`\`\`json
|
|
283
|
+
{
|
|
284
|
+
"name": "Feedback Manager",
|
|
285
|
+
"description": "Manages user feedback with CRUD operations",
|
|
286
|
+
"version": "1.0.0",
|
|
287
|
+
"trigger": {
|
|
288
|
+
"http": {
|
|
289
|
+
"method": "*",
|
|
290
|
+
"path": "/:function?/:id?",
|
|
291
|
+
"accept": "application/json"
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
"steps": [
|
|
295
|
+
{
|
|
296
|
+
"name": "filter-request",
|
|
297
|
+
"node": "@blok/if-else",
|
|
298
|
+
"type": "module"
|
|
299
|
+
}
|
|
300
|
+
],
|
|
301
|
+
"nodes": {
|
|
302
|
+
"filter-request": {
|
|
303
|
+
"conditions": [
|
|
304
|
+
{
|
|
305
|
+
"type": "if",
|
|
306
|
+
"condition": "ctx.request.method.toLowerCase() === \\"get\\" && ctx.request.params.function === ''",
|
|
307
|
+
"steps": [
|
|
308
|
+
{ "name": "list-view", "node": "feedback-ui", "type": "module" }
|
|
309
|
+
]
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
"type": "if",
|
|
313
|
+
"condition": "ctx.request.method.toLowerCase() === \\"post\\" && ctx.request.params.function === \\"create\\"",
|
|
314
|
+
"steps": [
|
|
315
|
+
{ "name": "process-data", "node": "data-processor", "type": "module" },
|
|
316
|
+
{ "name": "save-data", "node": "storage", "type": "module" }
|
|
317
|
+
]
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
"type": "if",
|
|
321
|
+
"condition": "ctx.request.method.toLowerCase() === \\"get\\" && ctx.request.params.function === \\"all\\"",
|
|
322
|
+
"steps": [
|
|
323
|
+
{ "name": "get-all", "node": "storage", "type": "module" }
|
|
324
|
+
]
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
"type": "else",
|
|
328
|
+
"steps": [
|
|
329
|
+
{ "name": "not-allowed", "node": "error", "type": "module" }
|
|
330
|
+
]
|
|
331
|
+
}
|
|
332
|
+
]
|
|
333
|
+
},
|
|
334
|
+
"list-view": { "inputs": {} },
|
|
335
|
+
"process-data": {
|
|
336
|
+
"inputs": {
|
|
337
|
+
"id": "\${ctx.request.body.id}",
|
|
338
|
+
"data": "\${ctx.request.body}"
|
|
339
|
+
}
|
|
340
|
+
},
|
|
341
|
+
"save-data": {
|
|
342
|
+
"inputs": {
|
|
343
|
+
"action": "set",
|
|
344
|
+
"key": "\${ctx.request.body.id}",
|
|
345
|
+
"value": "js/ctx.response.data"
|
|
346
|
+
}
|
|
347
|
+
},
|
|
348
|
+
"get-all": {
|
|
349
|
+
"inputs": { "action": "get-all" }
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
\`\`\`
|
|
354
|
+
|
|
355
|
+
### Example 3: Queue-Triggered Workflow
|
|
356
|
+
\`\`\`json
|
|
357
|
+
{
|
|
358
|
+
"name": "User Event Processor",
|
|
359
|
+
"description": "Processes user events from Kafka queue",
|
|
360
|
+
"version": "1.0.0",
|
|
361
|
+
"trigger": {
|
|
362
|
+
"queue": {
|
|
363
|
+
"provider": "kafka",
|
|
364
|
+
"topic": "user-events",
|
|
365
|
+
"consumerGroup": "event-processor",
|
|
366
|
+
"ack": true
|
|
367
|
+
}
|
|
368
|
+
},
|
|
369
|
+
"steps": [
|
|
370
|
+
{
|
|
371
|
+
"name": "process-event",
|
|
372
|
+
"node": "event-handler",
|
|
373
|
+
"type": "module"
|
|
374
|
+
},
|
|
375
|
+
{
|
|
376
|
+
"name": "notify-user",
|
|
377
|
+
"node": "@blok/api-call",
|
|
378
|
+
"type": "module"
|
|
379
|
+
}
|
|
380
|
+
],
|
|
381
|
+
"nodes": {
|
|
382
|
+
"process-event": {
|
|
383
|
+
"inputs": {
|
|
384
|
+
"eventType": "\${ctx.request.body.type}",
|
|
385
|
+
"payload": "\${ctx.request.body.data}"
|
|
386
|
+
}
|
|
387
|
+
},
|
|
388
|
+
"notify-user": {
|
|
389
|
+
"inputs": {
|
|
390
|
+
"url": "https://api.notifications.com/send",
|
|
391
|
+
"method": "POST",
|
|
392
|
+
"headers": { "Authorization": "Bearer \${ctx.env.NOTIFICATION_API_KEY}" },
|
|
393
|
+
"body": "js/ctx.vars['process-event']"
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
\`\`\`
|
|
399
|
+
|
|
400
|
+
### Example 4: Cron-Triggered Workflow
|
|
401
|
+
\`\`\`json
|
|
402
|
+
{
|
|
403
|
+
"name": "Daily Report Generator",
|
|
404
|
+
"description": "Generates and emails daily reports every morning",
|
|
405
|
+
"version": "1.0.0",
|
|
406
|
+
"trigger": {
|
|
407
|
+
"cron": {
|
|
408
|
+
"schedule": "0 8 * * *",
|
|
409
|
+
"timezone": "America/New_York",
|
|
410
|
+
"overlap": false
|
|
411
|
+
}
|
|
412
|
+
},
|
|
413
|
+
"steps": [
|
|
414
|
+
{
|
|
415
|
+
"name": "fetch-metrics",
|
|
416
|
+
"node": "@blok/api-call",
|
|
417
|
+
"type": "module"
|
|
418
|
+
},
|
|
419
|
+
{
|
|
420
|
+
"name": "generate-report",
|
|
421
|
+
"node": "report-generator",
|
|
422
|
+
"type": "module"
|
|
423
|
+
}
|
|
424
|
+
],
|
|
425
|
+
"nodes": {
|
|
426
|
+
"fetch-metrics": {
|
|
427
|
+
"inputs": {
|
|
428
|
+
"url": "\${ctx.env.METRICS_API_URL}",
|
|
429
|
+
"method": "GET",
|
|
430
|
+
"headers": { "Authorization": "Bearer \${ctx.env.METRICS_API_KEY}" }
|
|
431
|
+
}
|
|
432
|
+
},
|
|
433
|
+
"generate-report": {
|
|
434
|
+
"inputs": {
|
|
435
|
+
"data": "js/ctx.vars['fetch-metrics']",
|
|
436
|
+
"format": "html",
|
|
437
|
+
"recipients": ["admin@example.com"]
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
\`\`\`
|
|
443
|
+
|
|
444
|
+
## Formatting
|
|
445
|
+
|
|
446
|
+
* No explanations, comments, or markdown fences outside the JSON
|
|
447
|
+
* The output must be a single valid JSON object
|
|
448
|
+
* Use 2-space indentation
|
|
449
|
+
* All string values must be properly escaped
|
|
450
|
+
* No trailing commas`,
|
|
451
|
+
updatePrompt: `You are a senior backend engineer specializing in the Blok (blok) workflow framework. Your task is to update an existing workflow JSON configuration with new functionality while preserving its core structure.
|
|
452
|
+
|
|
453
|
+
Given the existing workflow JSON below, enhance or modify it according to the user's requirements while maintaining:
|
|
454
|
+
|
|
455
|
+
1. Valid JSON structure with name, description, version, trigger, steps, nodes
|
|
456
|
+
2. Consistent trigger configuration
|
|
457
|
+
3. All step names matching their nodes entries
|
|
458
|
+
4. Valid condition expressions using only ctx.* properties
|
|
459
|
+
5. Proper input value patterns (\${ctx.*}, js/*, static values)
|
|
460
|
+
|
|
461
|
+
What to return:
|
|
462
|
+
* Return only the full updated workflow JSON
|
|
463
|
+
* Preserve existing functionality unless explicitly asked to change it
|
|
464
|
+
* Add new functionality as requested
|
|
465
|
+
* Ensure all step references remain consistent
|
|
466
|
+
* Keep input patterns comprehensive and accurate
|
|
467
|
+
|
|
468
|
+
Format:
|
|
469
|
+
* No explanations or comments outside the JSON
|
|
470
|
+
* Return the complete JSON as it would appear in the .json file
|
|
471
|
+
* Use 2-space indentation
|
|
472
|
+
|
|
473
|
+
Current Workflow to be improved:
|
|
474
|
+
`,
|
|
475
|
+
};
|
|
476
|
+
export default createWorkflowSystemPrompt;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const registerNodeSystemPrompt = {
|
|
2
|
+
prompt: `You are a senior TypeScript developer and code editor assistant. Your task is to update a TypeScript file that exports a \`nodes\` registry object. This object contains imported blok node classes (e.g., \`ApiCall\`, \`IfElse\`) as values, and their corresponding keys (string identifiers used in the system) as keys.
|
|
3
|
+
|
|
4
|
+
You will receive:
|
|
5
|
+
- The current full content of the TypeScript file.
|
|
6
|
+
- The import path of the new node (e.g., "@blok/my-new-node" or "./nodes/remove-properties").
|
|
7
|
+
- The class name of the new node (e.g., "RemovePropertiesFromArray").
|
|
8
|
+
- The string **registry key** to register it under (e.g., "remove-properties").
|
|
9
|
+
|
|
10
|
+
Your task:
|
|
11
|
+
|
|
12
|
+
1. Add an \`import\` statement for the new node in the correct location, maintaining **alphabetical order** among existing regular imports.
|
|
13
|
+
2. The line \`import type { NodeBase } from "@blok/shared";\` must remain in place and not be reordered.
|
|
14
|
+
3. Add a new entry to the \`nodes\` object using the provided registry key only. Example:
|
|
15
|
+
"remove-properties": new RemovePropertiesFromArray(),
|
|
16
|
+
4. **Do not modify any existing imports or registry entries.** Their keys must remain exactly as they appear.
|
|
17
|
+
5. **Do not change** the type of the \`nodes\` object or its declaration structure. Leave it as-is.
|
|
18
|
+
6. Keep the format, indentation, spacing, and structure exactly like the input.
|
|
19
|
+
7. If the registry key already exists in the object, do not add it again.
|
|
20
|
+
8. Your response must be a single full TypeScript file containing the updated code. No explanations or markdown formatting.
|
|
21
|
+
9. If the node is already registered, simply update the import statement if necessary, but do not add a duplicate entry.
|
|
22
|
+
|
|
23
|
+
Here is the current content of the TypeScript file:
|
|
24
|
+
`,
|
|
25
|
+
};
|
|
26
|
+
export default registerNodeSystemPrompt;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface CompilationResult {
|
|
2
|
+
success: boolean;
|
|
3
|
+
errors: string[];
|
|
4
|
+
warnings: string[];
|
|
5
|
+
}
|
|
6
|
+
export declare function validateFile(filePath: string): CompilationResult;
|
|
7
|
+
export declare function validateCode(code: string, fileName?: string): CompilationResult;
|
|
8
|
+
export declare function check(code: string): boolean;
|
|
9
|
+
export declare function getErrorMessage(result: CompilationResult): string;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as ts from "typescript";
|
|
3
|
+
export function validateFile(filePath) {
|
|
4
|
+
const result = {
|
|
5
|
+
success: true,
|
|
6
|
+
errors: [],
|
|
7
|
+
warnings: [],
|
|
8
|
+
};
|
|
9
|
+
if (!fs.existsSync(filePath)) {
|
|
10
|
+
result.success = false;
|
|
11
|
+
result.errors.push(`File not found: ${filePath}`);
|
|
12
|
+
return result;
|
|
13
|
+
}
|
|
14
|
+
return validateCode(fs.readFileSync(filePath, "utf-8"), filePath);
|
|
15
|
+
}
|
|
16
|
+
export function validateCode(code, fileName = "temp.ts") {
|
|
17
|
+
const result = {
|
|
18
|
+
success: true,
|
|
19
|
+
errors: [],
|
|
20
|
+
warnings: [],
|
|
21
|
+
};
|
|
22
|
+
try {
|
|
23
|
+
const sourceFile = ts.createSourceFile(fileName, code, ts.ScriptTarget.ES2020, true, ts.ScriptKind.TS);
|
|
24
|
+
const compilerOptions = {
|
|
25
|
+
target: ts.ScriptTarget.ES2020,
|
|
26
|
+
module: ts.ModuleKind.CommonJS,
|
|
27
|
+
strict: true,
|
|
28
|
+
esModuleInterop: true,
|
|
29
|
+
skipLibCheck: true,
|
|
30
|
+
noEmit: true,
|
|
31
|
+
};
|
|
32
|
+
const compilerHost = ts.createCompilerHost(compilerOptions);
|
|
33
|
+
const originalGetSourceFile = compilerHost.getSourceFile;
|
|
34
|
+
compilerHost.getSourceFile = (name, languageVersion) => {
|
|
35
|
+
if (name === fileName) {
|
|
36
|
+
return sourceFile;
|
|
37
|
+
}
|
|
38
|
+
return originalGetSourceFile.call(compilerHost, name, languageVersion);
|
|
39
|
+
};
|
|
40
|
+
const program = ts.createProgram([fileName], compilerOptions, compilerHost);
|
|
41
|
+
const diagnostics = [...program.getSyntacticDiagnostics(), ...program.getSemanticDiagnostics()];
|
|
42
|
+
for (const diagnostic of diagnostics) {
|
|
43
|
+
const errorCode = diagnostic.code;
|
|
44
|
+
const skipCodes = [
|
|
45
|
+
2307,
|
|
46
|
+
2304,
|
|
47
|
+
];
|
|
48
|
+
if (skipCodes.includes(errorCode)) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
|
|
52
|
+
if (diagnostic.category === ts.DiagnosticCategory.Error) {
|
|
53
|
+
result.success = false;
|
|
54
|
+
result.errors.push(message);
|
|
55
|
+
}
|
|
56
|
+
else if (diagnostic.category === ts.DiagnosticCategory.Warning) {
|
|
57
|
+
result.warnings.push(message);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
result.success = false;
|
|
63
|
+
result.errors.push(`Compilation failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
export function check(code) {
|
|
68
|
+
return validateCode(code).success;
|
|
69
|
+
}
|
|
70
|
+
export function getErrorMessage(result) {
|
|
71
|
+
if (result.success) {
|
|
72
|
+
return "✅ Code compiles successfully";
|
|
73
|
+
}
|
|
74
|
+
const lines = ["❌ Compilation errors:"];
|
|
75
|
+
for (let i = 0; i < result.errors.length; i++) {
|
|
76
|
+
lines.push(`${i + 1}. ${result.errors[i]}`);
|
|
77
|
+
}
|
|
78
|
+
if (result.warnings.length > 0) {
|
|
79
|
+
lines.push("");
|
|
80
|
+
lines.push("⚠️ Warnings:");
|
|
81
|
+
for (let i = 0; i < result.warnings.length; i++) {
|
|
82
|
+
lines.push(`${i + 1}. ${result.warnings[i]}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return lines.join("\n");
|
|
86
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|