@marktoflow/core 2.0.0-alpha.12 → 2.0.0-alpha.13
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/README.md +147 -4
- package/dist/built-in-operations.d.ts +140 -0
- package/dist/built-in-operations.d.ts.map +1 -0
- package/dist/built-in-operations.js +414 -0
- package/dist/built-in-operations.js.map +1 -0
- package/dist/engine.d.ts +11 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +76 -42
- package/dist/engine.js.map +1 -1
- package/dist/file-operations.d.ts +86 -0
- package/dist/file-operations.d.ts.map +1 -0
- package/dist/file-operations.js +363 -0
- package/dist/file-operations.js.map +1 -0
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +29 -1
- package/dist/index.js.map +1 -1
- package/dist/logging.d.ts +40 -2
- package/dist/logging.d.ts.map +1 -1
- package/dist/logging.js +166 -13
- package/dist/logging.js.map +1 -1
- package/dist/models.d.ts +144 -8
- package/dist/models.d.ts.map +1 -1
- package/dist/models.js +15 -1
- package/dist/models.js.map +1 -1
- package/dist/nunjucks-filters.d.ts +271 -0
- package/dist/nunjucks-filters.d.ts.map +1 -0
- package/dist/nunjucks-filters.js +648 -0
- package/dist/nunjucks-filters.js.map +1 -0
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +16 -2
- package/dist/parser.js.map +1 -1
- package/dist/prompt-loader.d.ts +8 -2
- package/dist/prompt-loader.d.ts.map +1 -1
- package/dist/prompt-loader.js +26 -89
- package/dist/prompt-loader.js.map +1 -1
- package/dist/scheduler.d.ts +22 -3
- package/dist/scheduler.d.ts.map +1 -1
- package/dist/scheduler.js +72 -73
- package/dist/scheduler.js.map +1 -1
- package/dist/script-executor.d.ts +65 -0
- package/dist/script-executor.d.ts.map +1 -0
- package/dist/script-executor.js +261 -0
- package/dist/script-executor.js.map +1 -0
- package/dist/template-engine.d.ts +51 -0
- package/dist/template-engine.d.ts.map +1 -0
- package/dist/template-engine.js +227 -0
- package/dist/template-engine.js.map +1 -0
- package/dist/templates.d.ts +10 -0
- package/dist/templates.d.ts.map +1 -1
- package/dist/templates.js +21 -17
- package/dist/templates.js.map +1 -1
- package/package.json +16 -2
package/README.md
CHANGED
|
@@ -128,7 +128,9 @@ await registry.register({
|
|
|
128
128
|
|
|
129
129
|
## Workflow Format
|
|
130
130
|
|
|
131
|
-
Workflows are written in markdown with YAML frontmatter
|
|
131
|
+
Workflows are written in markdown with YAML frontmatter. See the [examples/](https://github.com/marktoflow/marktoflow/tree/main/examples) directory for production-ready workflow templates.
|
|
132
|
+
|
|
133
|
+
### Basic Example
|
|
132
134
|
|
|
133
135
|
```markdown
|
|
134
136
|
---
|
|
@@ -165,12 +167,88 @@ This workflow posts a message to Slack.
|
|
|
165
167
|
\`\`\`yaml
|
|
166
168
|
action: slack.chat.postMessage
|
|
167
169
|
inputs:
|
|
168
|
-
channel: '#general'
|
|
169
|
-
text: '{{ inputs.message }}'
|
|
170
|
+
channel: '#general'
|
|
171
|
+
text: '{{ inputs.message }}'
|
|
170
172
|
output_variable: result
|
|
171
173
|
\`\`\`
|
|
172
174
|
```
|
|
173
175
|
|
|
176
|
+
### Real-World Examples
|
|
177
|
+
|
|
178
|
+
See these production workflows in the `examples/` directory:
|
|
179
|
+
|
|
180
|
+
- **[daily-standup](https://github.com/marktoflow/marktoflow/tree/main/examples/daily-standup)** - Jira + Slack integration with AI-generated summaries
|
|
181
|
+
- **[code-review](https://github.com/marktoflow/marktoflow/tree/main/examples/code-review)** - Automated GitHub PR reviews with security analysis
|
|
182
|
+
- **[incident-response](https://github.com/marktoflow/marktoflow/tree/main/examples/incident-response)** - PagerDuty + Slack + Jira coordination
|
|
183
|
+
- **[gmail-notification](https://github.com/marktoflow/marktoflow/tree/main/examples/gmail-notification)** - Email automation with Gmail API
|
|
184
|
+
- **[web-automation](https://github.com/marktoflow/marktoflow/tree/main/examples/web-automation)** - Browser automation with Playwright
|
|
185
|
+
|
|
186
|
+
### Advanced Features
|
|
187
|
+
|
|
188
|
+
The core engine supports sophisticated workflow patterns:
|
|
189
|
+
|
|
190
|
+
#### Control Flow
|
|
191
|
+
|
|
192
|
+
```yaml
|
|
193
|
+
# Conditional execution
|
|
194
|
+
- action: jira.issues.getIssue
|
|
195
|
+
inputs:
|
|
196
|
+
issueKey: 'PROJ-123'
|
|
197
|
+
output_variable: issue
|
|
198
|
+
|
|
199
|
+
- action: slack.chat.postMessage
|
|
200
|
+
condition: '{{ issue.fields.priority.name == "Critical" }}'
|
|
201
|
+
inputs:
|
|
202
|
+
channel: '#urgent'
|
|
203
|
+
text: 'Critical issue found!'
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
#### Loops and Iteration
|
|
207
|
+
|
|
208
|
+
```yaml
|
|
209
|
+
# Process multiple items
|
|
210
|
+
- action: github.pulls.list
|
|
211
|
+
inputs:
|
|
212
|
+
owner: marktoflow
|
|
213
|
+
repo: marktoflow
|
|
214
|
+
output_variable: prs
|
|
215
|
+
|
|
216
|
+
- action: code_review
|
|
217
|
+
for_each: '{{ prs.data }}'
|
|
218
|
+
inputs:
|
|
219
|
+
pr: '{{ item }}'
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
#### Error Handling and Retry
|
|
223
|
+
|
|
224
|
+
```yaml
|
|
225
|
+
- action: external_api.call
|
|
226
|
+
retry:
|
|
227
|
+
max_attempts: 3
|
|
228
|
+
backoff: exponential
|
|
229
|
+
initial_delay: 1000
|
|
230
|
+
on_error: continue
|
|
231
|
+
fallback:
|
|
232
|
+
- action: slack.chat.postMessage
|
|
233
|
+
inputs:
|
|
234
|
+
channel: '#alerts'
|
|
235
|
+
text: 'API call failed after retries'
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
#### Circuit Breaker Pattern
|
|
239
|
+
|
|
240
|
+
```yaml
|
|
241
|
+
tools:
|
|
242
|
+
external_api:
|
|
243
|
+
sdk: 'custom-api-client'
|
|
244
|
+
circuit_breaker:
|
|
245
|
+
failure_threshold: 5
|
|
246
|
+
timeout: 30000
|
|
247
|
+
reset_timeout: 60000
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
See [examples/tests/control-flow/](https://github.com/marktoflow/marktoflow/tree/main/examples/tests/control-flow) for more advanced patterns.
|
|
251
|
+
|
|
174
252
|
## Architecture
|
|
175
253
|
|
|
176
254
|
### Core Components
|
|
@@ -291,8 +369,73 @@ class Scheduler {
|
|
|
291
369
|
|
|
292
370
|
## Testing
|
|
293
371
|
|
|
372
|
+
The core package includes comprehensive unit and integration tests.
|
|
373
|
+
|
|
374
|
+
### Running Tests
|
|
375
|
+
|
|
294
376
|
```bash
|
|
295
|
-
|
|
377
|
+
# Run all tests (unit + integration)
|
|
378
|
+
pnpm test
|
|
379
|
+
|
|
380
|
+
# Run only unit tests
|
|
381
|
+
pnpm test:unit
|
|
382
|
+
|
|
383
|
+
# Run only integration tests
|
|
384
|
+
pnpm test:integration
|
|
385
|
+
|
|
386
|
+
# Run specific test file
|
|
387
|
+
pnpm test path/to/test.ts
|
|
388
|
+
|
|
389
|
+
# Run tests matching a pattern
|
|
390
|
+
pnpm test:integration -t "transform"
|
|
391
|
+
|
|
392
|
+
# Watch mode
|
|
393
|
+
pnpm test --watch
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### Test Structure
|
|
397
|
+
|
|
398
|
+
- **Unit Tests** (`tests/`) - Fast, isolated tests for individual functions and classes
|
|
399
|
+
- **Integration Tests** (`integration-tests/`) - End-to-end workflow execution tests organized by feature:
|
|
400
|
+
- `suites/built-in-operations.integration.test.ts` - Transform, filter, reduce, etc.
|
|
401
|
+
- `suites/control-flow.integration.test.ts` - If/else, loops, parallel execution
|
|
402
|
+
- `suites/error-handling.integration.test.ts` - Retry, circuit breaker, error recovery
|
|
403
|
+
- `suites/nunjucks-filters.integration.test.ts` - Template engine filters
|
|
404
|
+
- `suites/script-execution.integration.test.ts` - JavaScript script execution
|
|
405
|
+
- `suites/variable-resolution.integration.test.ts` - Template variables and context
|
|
406
|
+
|
|
407
|
+
### Writing Integration Tests
|
|
408
|
+
|
|
409
|
+
Integration tests use real workflow definitions and the full execution engine:
|
|
410
|
+
|
|
411
|
+
```typescript
|
|
412
|
+
import { loadInline, createSmartExecutor } from '../helpers/test-utils.js';
|
|
413
|
+
import { WorkflowEngine } from '../../src/engine.js';
|
|
414
|
+
|
|
415
|
+
const engine = new WorkflowEngine();
|
|
416
|
+
|
|
417
|
+
it('should execute workflow', async () => {
|
|
418
|
+
const { workflow } = loadInline(`
|
|
419
|
+
---
|
|
420
|
+
workflow:
|
|
421
|
+
id: test-workflow
|
|
422
|
+
name: Test Workflow
|
|
423
|
+
steps:
|
|
424
|
+
- id: step1
|
|
425
|
+
type: action
|
|
426
|
+
action: core.set
|
|
427
|
+
inputs:
|
|
428
|
+
value: "Hello"
|
|
429
|
+
output_variable: result
|
|
430
|
+
---
|
|
431
|
+
`);
|
|
432
|
+
|
|
433
|
+
const { executor, registry } = createSmartExecutor();
|
|
434
|
+
const result = await engine.execute(workflow, {}, registry, executor);
|
|
435
|
+
|
|
436
|
+
expect(result.status).toBe(WorkflowStatus.COMPLETED);
|
|
437
|
+
expect(result.output.result).toBe('Hello');
|
|
438
|
+
});
|
|
296
439
|
```
|
|
297
440
|
|
|
298
441
|
## Links
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in Operations for marktoflow
|
|
3
|
+
*
|
|
4
|
+
* Provides common operations that eliminate the need for verbose script blocks:
|
|
5
|
+
* - core.set: Simple variable assignment
|
|
6
|
+
* - core.transform: Map/filter/reduce transformations
|
|
7
|
+
* - core.extract: Nested path access
|
|
8
|
+
* - core.format: Date/number/string formatting
|
|
9
|
+
* - file.read: Read files with format conversion (docx, pdf, xlsx)
|
|
10
|
+
* - file.write: Write files (text or binary)
|
|
11
|
+
*/
|
|
12
|
+
import { ExecutionContext } from './models.js';
|
|
13
|
+
export interface SetOperationInputs {
|
|
14
|
+
[key: string]: unknown;
|
|
15
|
+
}
|
|
16
|
+
export interface TransformOperationInputs {
|
|
17
|
+
input: unknown[];
|
|
18
|
+
operation: 'map' | 'filter' | 'reduce' | 'find' | 'group_by' | 'unique' | 'sort';
|
|
19
|
+
expression?: string;
|
|
20
|
+
condition?: string;
|
|
21
|
+
initialValue?: unknown;
|
|
22
|
+
key?: string;
|
|
23
|
+
reverse?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface ExtractOperationInputs {
|
|
26
|
+
input: unknown;
|
|
27
|
+
path: string;
|
|
28
|
+
default?: unknown;
|
|
29
|
+
}
|
|
30
|
+
export interface FormatOperationInputs {
|
|
31
|
+
value: unknown;
|
|
32
|
+
type: 'date' | 'number' | 'string' | 'currency' | 'json';
|
|
33
|
+
format?: string;
|
|
34
|
+
locale?: string;
|
|
35
|
+
currency?: string;
|
|
36
|
+
precision?: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Set multiple variables at once with expression resolution.
|
|
40
|
+
*
|
|
41
|
+
* Example:
|
|
42
|
+
* ```yaml
|
|
43
|
+
* action: core.set
|
|
44
|
+
* inputs:
|
|
45
|
+
* owner: "{{ inputs.repo =~ /^([^\/]+)\// }}"
|
|
46
|
+
* repo_name: "{{ inputs.repo =~ /\/(.+)$/ }}"
|
|
47
|
+
* timestamp: "{{ now() }}"
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare function executeSet(inputs: SetOperationInputs, context: ExecutionContext): Record<string, unknown>;
|
|
51
|
+
/**
|
|
52
|
+
* Transform arrays using common operations like map, filter, reduce.
|
|
53
|
+
*
|
|
54
|
+
* Examples:
|
|
55
|
+
*
|
|
56
|
+
* Map:
|
|
57
|
+
* ```yaml
|
|
58
|
+
* action: core.transform
|
|
59
|
+
* inputs:
|
|
60
|
+
* input: "{{ oncall_response.data.oncalls }}"
|
|
61
|
+
* operation: map
|
|
62
|
+
* expression: "@{{ item.user.name }}"
|
|
63
|
+
* ```
|
|
64
|
+
*
|
|
65
|
+
* Filter:
|
|
66
|
+
* ```yaml
|
|
67
|
+
* action: core.transform
|
|
68
|
+
* inputs:
|
|
69
|
+
* input: "{{ issues }}"
|
|
70
|
+
* operation: filter
|
|
71
|
+
* condition: "item.priority == 'high'"
|
|
72
|
+
* ```
|
|
73
|
+
*
|
|
74
|
+
* Reduce:
|
|
75
|
+
* ```yaml
|
|
76
|
+
* action: core.transform
|
|
77
|
+
* inputs:
|
|
78
|
+
* input: "{{ numbers }}"
|
|
79
|
+
* operation: reduce
|
|
80
|
+
* expression: "{{ accumulator + item }}"
|
|
81
|
+
* initialValue: 0
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export declare function executeTransform(rawInputs: TransformOperationInputs, resolvedInputs: Record<string, unknown>, context: ExecutionContext): unknown;
|
|
85
|
+
/**
|
|
86
|
+
* Extract values from nested objects safely.
|
|
87
|
+
*
|
|
88
|
+
* Example:
|
|
89
|
+
* ```yaml
|
|
90
|
+
* action: core.extract
|
|
91
|
+
* inputs:
|
|
92
|
+
* input: "{{ api_response }}"
|
|
93
|
+
* path: "data.users[0].email"
|
|
94
|
+
* default: "unknown@example.com"
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
export declare function executeExtract(inputs: ExtractOperationInputs, context: ExecutionContext): unknown;
|
|
98
|
+
/**
|
|
99
|
+
* Format values for display (dates, numbers, strings, currency).
|
|
100
|
+
*
|
|
101
|
+
* Examples:
|
|
102
|
+
*
|
|
103
|
+
* Date:
|
|
104
|
+
* ```yaml
|
|
105
|
+
* action: core.format
|
|
106
|
+
* inputs:
|
|
107
|
+
* value: "{{ now() }}"
|
|
108
|
+
* type: date
|
|
109
|
+
* format: "YYYY-MM-DD HH:mm:ss"
|
|
110
|
+
* ```
|
|
111
|
+
*
|
|
112
|
+
* Number:
|
|
113
|
+
* ```yaml
|
|
114
|
+
* action: core.format
|
|
115
|
+
* inputs:
|
|
116
|
+
* value: 1234.56
|
|
117
|
+
* type: number
|
|
118
|
+
* precision: 2
|
|
119
|
+
* ```
|
|
120
|
+
*
|
|
121
|
+
* Currency:
|
|
122
|
+
* ```yaml
|
|
123
|
+
* action: core.format
|
|
124
|
+
* inputs:
|
|
125
|
+
* value: 1234.56
|
|
126
|
+
* type: currency
|
|
127
|
+
* currency: USD
|
|
128
|
+
* locale: en-US
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
export declare function executeFormat(inputs: FormatOperationInputs, context: ExecutionContext): string;
|
|
132
|
+
/**
|
|
133
|
+
* Execute a built-in operation based on action name
|
|
134
|
+
*/
|
|
135
|
+
export declare function executeBuiltInOperation(action: string, rawInputs: Record<string, unknown>, resolvedInputs: Record<string, unknown>, context: ExecutionContext): unknown | Promise<unknown>;
|
|
136
|
+
/**
|
|
137
|
+
* Check if an action is a built-in operation
|
|
138
|
+
*/
|
|
139
|
+
export declare function isBuiltInOperation(action: string): boolean;
|
|
140
|
+
//# sourceMappingURL=built-in-operations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"built-in-operations.d.ts","sourceRoot":"","sources":["../src/built-in-operations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAQ/C,MAAM,WAAW,kBAAkB;IACjC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,SAAS,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAC;IACjF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAC;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,kBAAkB,EAC1B,OAAO,EAAE,gBAAgB,GACxB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASzB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,wBAAwB,EACnC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACvC,OAAO,EAAE,gBAAgB,GACxB,OAAO,CA4CT;AAsKD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,sBAAsB,EAC9B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAkBT;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,qBAAqB,EAC7B,OAAO,EAAE,gBAAgB,GACxB,MAAM,CAsBR;AAiHD;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACvC,OAAO,EAAE,gBAAgB,GACxB,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAsB5B;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAG1D"}
|