@workglow/task-graph 0.0.125 → 0.1.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/README.md +104 -36
- package/dist/browser.js +888 -1031
- package/dist/browser.js.map +26 -28
- package/dist/bun.js +888 -1027
- package/dist/bun.js.map +25 -27
- package/dist/debug/console/ConsoleFormatters.d.ts.map +1 -1
- package/dist/node.js +888 -1027
- package/dist/node.js.map +25 -27
- package/dist/task/ConditionalTask.d.ts +1 -0
- package/dist/task/ConditionalTask.d.ts.map +1 -1
- package/dist/task/FallbackTask.d.ts +0 -1
- package/dist/task/FallbackTask.d.ts.map +1 -1
- package/dist/task/GraphAsTask.d.ts.map +1 -1
- package/dist/task/ITask.d.ts +6 -0
- package/dist/task/ITask.d.ts.map +1 -1
- package/dist/task/InputResolver.d.ts +6 -0
- package/dist/task/InputResolver.d.ts.map +1 -1
- package/dist/task/IteratorTask.d.ts +11 -0
- package/dist/task/IteratorTask.d.ts.map +1 -1
- package/dist/task/IteratorTaskRunner.d.ts.map +1 -1
- package/dist/task/JobQueueFactory.d.ts +3 -4
- package/dist/task/JobQueueFactory.d.ts.map +1 -1
- package/dist/task/MapTask.d.ts +4 -0
- package/dist/task/MapTask.d.ts.map +1 -1
- package/dist/task/ReduceTask.d.ts +4 -0
- package/dist/task/ReduceTask.d.ts.map +1 -1
- package/dist/task/Task.d.ts +13 -1
- package/dist/task/Task.d.ts.map +1 -1
- package/dist/task/TaskError.d.ts +23 -0
- package/dist/task/TaskError.d.ts.map +1 -1
- package/dist/task/TaskEvents.d.ts +1 -1
- package/dist/task/TaskEvents.d.ts.map +1 -1
- package/dist/task/TaskJSON.d.ts +17 -7
- package/dist/task/TaskJSON.d.ts.map +1 -1
- package/dist/task/TaskQueueRegistry.d.ts +8 -0
- package/dist/task/TaskQueueRegistry.d.ts.map +1 -1
- package/dist/task/TaskRunner.d.ts.map +1 -1
- package/dist/task/WhileTask.d.ts +1 -0
- package/dist/task/WhileTask.d.ts.map +1 -1
- package/dist/task/index.d.ts +0 -1
- package/dist/task/index.d.ts.map +1 -1
- package/dist/task-graph/Conversions.d.ts.map +1 -1
- package/dist/task-graph/Dataflow.d.ts +11 -0
- package/dist/task-graph/Dataflow.d.ts.map +1 -1
- package/dist/task-graph/GraphSchemaUtils.d.ts.map +1 -1
- package/dist/task-graph/TaskGraph.d.ts +10 -0
- package/dist/task-graph/TaskGraph.d.ts.map +1 -1
- package/dist/task-graph/TaskGraphRunner.d.ts +15 -2
- package/dist/task-graph/TaskGraphRunner.d.ts.map +1 -1
- package/dist/task-graph/Workflow.d.ts.map +1 -1
- package/package.json +20 -11
- package/src/storage/README.md +51 -5
- package/src/task/README.md +0 -17
- package/dist/task/JobQueueTask.d.ts +0 -130
- package/dist/task/JobQueueTask.d.ts.map +0 -1
- package/dist/types.d.ts +0 -8
- package/dist/types.d.ts.map +0 -1
package/dist/bun.js
CHANGED
|
@@ -1,90 +1,52 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
function __accessProp(key) {
|
|
7
|
-
return this[key];
|
|
8
|
-
}
|
|
9
|
-
var __toCommonJS = (from) => {
|
|
10
|
-
var entry = (__moduleCache ??= new WeakMap).get(from), desc;
|
|
11
|
-
if (entry)
|
|
12
|
-
return entry;
|
|
13
|
-
entry = __defProp({}, "__esModule", { value: true });
|
|
14
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
-
for (var key of __getOwnPropNames(from))
|
|
16
|
-
if (!__hasOwnProp.call(entry, key))
|
|
17
|
-
__defProp(entry, key, {
|
|
18
|
-
get: __accessProp.bind(from, key),
|
|
19
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
__moduleCache.set(from, entry);
|
|
23
|
-
return entry;
|
|
24
|
-
};
|
|
25
|
-
var __moduleCache;
|
|
26
|
-
var __returnValue = (v) => v;
|
|
27
|
-
function __exportSetter(name, newValue) {
|
|
28
|
-
this[name] = __returnValue.bind(null, newValue);
|
|
29
|
-
}
|
|
30
|
-
var __export = (target, all) => {
|
|
31
|
-
for (var name in all)
|
|
32
|
-
__defProp(target, name, {
|
|
33
|
-
get: all[name],
|
|
34
|
-
enumerable: true,
|
|
35
|
-
configurable: true,
|
|
36
|
-
set: __exportSetter.bind(all, name)
|
|
37
|
-
});
|
|
38
|
-
};
|
|
39
|
-
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
2
|
+
// src/task-graph/Dataflow.ts
|
|
3
|
+
import { areSemanticallyCompatible } from "@workglow/util/schema";
|
|
4
|
+
import { EventEmitter } from "@workglow/util";
|
|
40
5
|
|
|
41
6
|
// src/task/TaskTypes.ts
|
|
42
|
-
var TaskStatus
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
id: {
|
|
57
|
-
"x-ui-hidden": true
|
|
58
|
-
},
|
|
59
|
-
title: { type: "string" },
|
|
60
|
-
description: { type: "string" },
|
|
61
|
-
cacheable: { type: "boolean" },
|
|
62
|
-
timeout: { type: "number", description: "Max execution time in milliseconds" },
|
|
63
|
-
inputSchema: {
|
|
64
|
-
type: "object",
|
|
65
|
-
properties: {},
|
|
66
|
-
additionalProperties: true,
|
|
67
|
-
"x-ui-hidden": true
|
|
68
|
-
},
|
|
69
|
-
outputSchema: {
|
|
70
|
-
type: "object",
|
|
71
|
-
properties: {},
|
|
72
|
-
additionalProperties: true,
|
|
73
|
-
"x-ui-hidden": true
|
|
74
|
-
},
|
|
75
|
-
extras: {
|
|
76
|
-
type: "object",
|
|
77
|
-
additionalProperties: true,
|
|
78
|
-
"x-ui-hidden": true
|
|
79
|
-
}
|
|
7
|
+
var TaskStatus = {
|
|
8
|
+
PENDING: "PENDING",
|
|
9
|
+
DISABLED: "DISABLED",
|
|
10
|
+
PROCESSING: "PROCESSING",
|
|
11
|
+
STREAMING: "STREAMING",
|
|
12
|
+
COMPLETED: "COMPLETED",
|
|
13
|
+
ABORTING: "ABORTING",
|
|
14
|
+
FAILED: "FAILED"
|
|
15
|
+
};
|
|
16
|
+
var TaskConfigSchema = {
|
|
17
|
+
type: "object",
|
|
18
|
+
properties: {
|
|
19
|
+
id: {
|
|
20
|
+
"x-ui-hidden": true
|
|
80
21
|
},
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
22
|
+
title: { type: "string" },
|
|
23
|
+
description: { type: "string" },
|
|
24
|
+
cacheable: { type: "boolean" },
|
|
25
|
+
timeout: { type: "number", description: "Max execution time in milliseconds" },
|
|
26
|
+
inputSchema: {
|
|
27
|
+
type: "object",
|
|
28
|
+
properties: {},
|
|
29
|
+
additionalProperties: true,
|
|
30
|
+
"x-ui-hidden": true
|
|
31
|
+
},
|
|
32
|
+
outputSchema: {
|
|
33
|
+
type: "object",
|
|
34
|
+
properties: {},
|
|
35
|
+
additionalProperties: true,
|
|
36
|
+
"x-ui-hidden": true
|
|
37
|
+
},
|
|
38
|
+
extras: {
|
|
39
|
+
type: "object",
|
|
40
|
+
additionalProperties: true,
|
|
41
|
+
"x-ui-hidden": true
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
additionalProperties: false
|
|
45
|
+
};
|
|
84
46
|
|
|
85
47
|
// src/task-graph/Dataflow.ts
|
|
86
|
-
|
|
87
|
-
|
|
48
|
+
var DATAFLOW_ALL_PORTS = "*";
|
|
49
|
+
var DATAFLOW_ERROR_PORT = "[error]";
|
|
88
50
|
|
|
89
51
|
class Dataflow {
|
|
90
52
|
sourceTaskId;
|
|
@@ -157,6 +119,7 @@ class Dataflow {
|
|
|
157
119
|
this.error = undefined;
|
|
158
120
|
this.value = undefined;
|
|
159
121
|
this.stream = undefined;
|
|
122
|
+
this._compatibilityCache = undefined;
|
|
160
123
|
this.emit("reset");
|
|
161
124
|
this.emit("status", this.status);
|
|
162
125
|
}
|
|
@@ -217,9 +180,19 @@ class Dataflow {
|
|
|
217
180
|
targetTaskPortId: this.targetTaskPortId
|
|
218
181
|
};
|
|
219
182
|
}
|
|
183
|
+
_compatibilityCache;
|
|
184
|
+
invalidateCompatibilityCache() {
|
|
185
|
+
this._compatibilityCache = undefined;
|
|
186
|
+
}
|
|
220
187
|
semanticallyCompatible(graph, dataflow) {
|
|
221
|
-
const
|
|
222
|
-
const
|
|
188
|
+
const sourceTask = graph.getTask(dataflow.sourceTaskId);
|
|
189
|
+
const targetTask = graph.getTask(dataflow.targetTaskId);
|
|
190
|
+
const shouldCache = !(sourceTask.constructor.hasDynamicSchemas ?? true) && !(targetTask.constructor.hasDynamicSchemas ?? true);
|
|
191
|
+
if (shouldCache && this._compatibilityCache !== undefined) {
|
|
192
|
+
return this._compatibilityCache;
|
|
193
|
+
}
|
|
194
|
+
const targetSchema = targetTask.inputSchema();
|
|
195
|
+
const sourceSchema = sourceTask.outputSchema();
|
|
223
196
|
if (typeof targetSchema === "boolean") {
|
|
224
197
|
if (targetSchema === false) {
|
|
225
198
|
return "incompatible";
|
|
@@ -240,8 +213,11 @@ class Dataflow {
|
|
|
240
213
|
if (sourceSchemaProperty === undefined && sourceSchema.additionalProperties === true) {
|
|
241
214
|
sourceSchemaProperty = true;
|
|
242
215
|
}
|
|
243
|
-
const
|
|
244
|
-
|
|
216
|
+
const result = areSemanticallyCompatible(sourceSchemaProperty, targetSchemaProperty);
|
|
217
|
+
if (shouldCache) {
|
|
218
|
+
this._compatibilityCache = result;
|
|
219
|
+
}
|
|
220
|
+
return result;
|
|
245
221
|
}
|
|
246
222
|
get events() {
|
|
247
223
|
if (!this._events) {
|
|
@@ -269,22 +245,18 @@ class Dataflow {
|
|
|
269
245
|
this._events?.emit(name, ...args);
|
|
270
246
|
}
|
|
271
247
|
}
|
|
272
|
-
var DATAFLOW_ALL_PORTS = "*", DATAFLOW_ERROR_PORT = "[error]", DataflowArrow;
|
|
273
|
-
var init_Dataflow = __esm(() => {
|
|
274
|
-
init_TaskTypes();
|
|
275
|
-
DataflowArrow = class DataflowArrow extends Dataflow {
|
|
276
|
-
constructor(dataflow) {
|
|
277
|
-
const pattern = /^([a-zA-Z0-9-]+?)\[([a-zA-Z0-9-]+?)\] ==> ([a-zA-Z0-9-]+?)\[([a-zA-Z0-9-]+?)\]$/;
|
|
278
|
-
const match = dataflow.match(pattern);
|
|
279
|
-
if (!match) {
|
|
280
|
-
throw new Error(`Invalid dataflow format: ${dataflow}`);
|
|
281
|
-
}
|
|
282
|
-
const [, sourceTaskId, sourceTaskPortId, targetTaskId, targetTaskPortId] = match;
|
|
283
|
-
super(sourceTaskId, sourceTaskPortId, targetTaskId, targetTaskPortId);
|
|
284
|
-
}
|
|
285
|
-
};
|
|
286
|
-
});
|
|
287
248
|
|
|
249
|
+
class DataflowArrow extends Dataflow {
|
|
250
|
+
constructor(dataflow) {
|
|
251
|
+
const pattern = /^([a-zA-Z0-9-]+?)\[([a-zA-Z0-9-]+?)\] ==> ([a-zA-Z0-9-]+?)\[([a-zA-Z0-9-]+?)\]$/;
|
|
252
|
+
const match = dataflow.match(pattern);
|
|
253
|
+
if (!match) {
|
|
254
|
+
throw new Error(`Invalid dataflow format: ${dataflow}`);
|
|
255
|
+
}
|
|
256
|
+
const [, sourceTaskId, sourceTaskPortId, targetTaskId, targetTaskPortId] = match;
|
|
257
|
+
super(sourceTaskId, sourceTaskPortId, targetTaskId, targetTaskPortId);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
288
260
|
// src/task-graph/GraphSchemaUtils.ts
|
|
289
261
|
import { uuid4 } from "@workglow/util";
|
|
290
262
|
function calculateNodeDepths(graph) {
|
|
@@ -633,74 +605,28 @@ function addBoundaryNodesToDependencyJson(items, graph) {
|
|
|
633
605
|
}
|
|
634
606
|
return [...prependItems, ...items, ...appendItems];
|
|
635
607
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
}
|
|
608
|
+
// src/task-graph/TaskGraph.ts
|
|
609
|
+
import { DirectedAcyclicGraph } from "@workglow/util/graph";
|
|
610
|
+
import { EventEmitter as EventEmitter4, uuid4 as uuid44 } from "@workglow/util";
|
|
639
611
|
|
|
640
|
-
// src/task/
|
|
641
|
-
import {
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
}
|
|
655
|
-
};
|
|
656
|
-
WorkflowError = class WorkflowError extends TaskError {
|
|
657
|
-
static type = "WorkflowError";
|
|
658
|
-
constructor(message) {
|
|
659
|
-
super(message);
|
|
660
|
-
}
|
|
661
|
-
};
|
|
662
|
-
TaskAbortedError = class TaskAbortedError extends TaskError {
|
|
663
|
-
static type = "TaskAbortedError";
|
|
664
|
-
constructor(message = "Task aborted") {
|
|
665
|
-
super(message);
|
|
666
|
-
}
|
|
667
|
-
};
|
|
668
|
-
TaskTimeoutError = class TaskTimeoutError extends TaskAbortedError {
|
|
669
|
-
static type = "TaskTimeoutError";
|
|
670
|
-
constructor(timeoutMs) {
|
|
671
|
-
super(timeoutMs ? `Task timed out after ${timeoutMs}ms` : "Task timed out");
|
|
672
|
-
}
|
|
673
|
-
};
|
|
674
|
-
TaskFailedError = class TaskFailedError extends TaskError {
|
|
675
|
-
static type = "TaskFailedError";
|
|
676
|
-
constructor(message = "Task failed") {
|
|
677
|
-
super(message);
|
|
678
|
-
}
|
|
679
|
-
};
|
|
680
|
-
JobTaskFailedError = class JobTaskFailedError extends TaskFailedError {
|
|
681
|
-
static type = "JobTaskFailedError";
|
|
682
|
-
jobError;
|
|
683
|
-
constructor(err) {
|
|
684
|
-
super(String(err));
|
|
685
|
-
this.jobError = err;
|
|
686
|
-
}
|
|
687
|
-
};
|
|
688
|
-
TaskJSONError = class TaskJSONError extends TaskError {
|
|
689
|
-
static type = "TaskJSONError";
|
|
690
|
-
constructor(message = "Error converting JSON to a Task") {
|
|
691
|
-
super(message);
|
|
692
|
-
}
|
|
693
|
-
};
|
|
694
|
-
TaskInvalidInputError = class TaskInvalidInputError extends TaskError {
|
|
695
|
-
static type = "TaskInvalidInputError";
|
|
696
|
-
constructor(message = "Invalid input data") {
|
|
697
|
-
super(message);
|
|
698
|
-
}
|
|
699
|
-
};
|
|
700
|
-
});
|
|
612
|
+
// src/task/GraphAsTask.ts
|
|
613
|
+
import { getLogger as getLogger4 } from "@workglow/util";
|
|
614
|
+
import { compileSchema as compileSchema2 } from "@workglow/util/schema";
|
|
615
|
+
|
|
616
|
+
// src/task-graph/TaskGraphRunner.ts
|
|
617
|
+
import {
|
|
618
|
+
collectPropertyValues,
|
|
619
|
+
getLogger as getLogger3,
|
|
620
|
+
getTelemetryProvider as getTelemetryProvider2,
|
|
621
|
+
globalServiceRegistry as globalServiceRegistry2,
|
|
622
|
+
ServiceRegistry as ServiceRegistry2,
|
|
623
|
+
SpanStatusCode as SpanStatusCode2,
|
|
624
|
+
uuid4 as uuid43
|
|
625
|
+
} from "@workglow/util";
|
|
701
626
|
|
|
702
627
|
// src/storage/TaskOutputRepository.ts
|
|
703
628
|
import { createServiceToken, EventEmitter as EventEmitter2 } from "@workglow/util";
|
|
629
|
+
var TASK_OUTPUT_REPOSITORY = createServiceToken("taskgraph.taskOutputRepository");
|
|
704
630
|
|
|
705
631
|
class TaskOutputRepository {
|
|
706
632
|
outputCompression;
|
|
@@ -727,10 +653,173 @@ class TaskOutputRepository {
|
|
|
727
653
|
this._events?.emit(name, ...args);
|
|
728
654
|
}
|
|
729
655
|
}
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
656
|
+
|
|
657
|
+
// src/task/ConditionalTask.ts
|
|
658
|
+
import { getLogger as getLogger2 } from "@workglow/util";
|
|
659
|
+
|
|
660
|
+
// src/task/ConditionUtils.ts
|
|
661
|
+
function evaluateCondition(fieldValue, operator, compareValue) {
|
|
662
|
+
if (fieldValue === null || fieldValue === undefined) {
|
|
663
|
+
switch (operator) {
|
|
664
|
+
case "is_empty":
|
|
665
|
+
return true;
|
|
666
|
+
case "is_not_empty":
|
|
667
|
+
return false;
|
|
668
|
+
case "is_true":
|
|
669
|
+
return false;
|
|
670
|
+
case "is_false":
|
|
671
|
+
return true;
|
|
672
|
+
default:
|
|
673
|
+
return false;
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
const strValue = String(fieldValue);
|
|
677
|
+
const numValue = Number(fieldValue);
|
|
678
|
+
switch (operator) {
|
|
679
|
+
case "equals":
|
|
680
|
+
if (!isNaN(numValue) && !isNaN(Number(compareValue))) {
|
|
681
|
+
return numValue === Number(compareValue);
|
|
682
|
+
}
|
|
683
|
+
return strValue === compareValue;
|
|
684
|
+
case "not_equals":
|
|
685
|
+
if (!isNaN(numValue) && !isNaN(Number(compareValue))) {
|
|
686
|
+
return numValue !== Number(compareValue);
|
|
687
|
+
}
|
|
688
|
+
return strValue !== compareValue;
|
|
689
|
+
case "greater_than":
|
|
690
|
+
return numValue > Number(compareValue);
|
|
691
|
+
case "greater_or_equal":
|
|
692
|
+
return numValue >= Number(compareValue);
|
|
693
|
+
case "less_than":
|
|
694
|
+
return numValue < Number(compareValue);
|
|
695
|
+
case "less_or_equal":
|
|
696
|
+
return numValue <= Number(compareValue);
|
|
697
|
+
case "contains":
|
|
698
|
+
return strValue.toLowerCase().includes(compareValue.toLowerCase());
|
|
699
|
+
case "starts_with":
|
|
700
|
+
return strValue.toLowerCase().startsWith(compareValue.toLowerCase());
|
|
701
|
+
case "ends_with":
|
|
702
|
+
return strValue.toLowerCase().endsWith(compareValue.toLowerCase());
|
|
703
|
+
case "is_empty":
|
|
704
|
+
return strValue === "" || Array.isArray(fieldValue) && fieldValue.length === 0;
|
|
705
|
+
case "is_not_empty":
|
|
706
|
+
return strValue !== "" && !(Array.isArray(fieldValue) && fieldValue.length === 0);
|
|
707
|
+
case "is_true":
|
|
708
|
+
return Boolean(fieldValue) === true;
|
|
709
|
+
case "is_false":
|
|
710
|
+
return Boolean(fieldValue) === false;
|
|
711
|
+
default:
|
|
712
|
+
return false;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
function getNestedValue(obj, path) {
|
|
716
|
+
const parts = path.split(".");
|
|
717
|
+
let current = obj;
|
|
718
|
+
for (const part of parts) {
|
|
719
|
+
if (current === null || current === undefined || typeof current !== "object") {
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
722
|
+
current = current[part];
|
|
723
|
+
}
|
|
724
|
+
return current;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
// src/task/Task.ts
|
|
728
|
+
import { compileSchema } from "@workglow/util/schema";
|
|
729
|
+
import { deepEqual, EventEmitter as EventEmitter3, uuid4 as uuid42 } from "@workglow/util";
|
|
730
|
+
|
|
731
|
+
// src/task/TaskError.ts
|
|
732
|
+
import { BaseError } from "@workglow/util";
|
|
733
|
+
|
|
734
|
+
class TaskError extends BaseError {
|
|
735
|
+
static type = "TaskError";
|
|
736
|
+
taskType;
|
|
737
|
+
taskId;
|
|
738
|
+
constructor(message) {
|
|
739
|
+
super(message);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
class TaskConfigurationError extends TaskError {
|
|
744
|
+
static type = "TaskConfigurationError";
|
|
745
|
+
constructor(message) {
|
|
746
|
+
super(message);
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
class WorkflowError extends TaskError {
|
|
751
|
+
static type = "WorkflowError";
|
|
752
|
+
constructor(message) {
|
|
753
|
+
super(message);
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
class TaskAbortedError extends TaskError {
|
|
758
|
+
static type = "TaskAbortedError";
|
|
759
|
+
constructor(message = "Task aborted") {
|
|
760
|
+
super(message);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
class TaskTimeoutError extends TaskAbortedError {
|
|
765
|
+
static type = "TaskTimeoutError";
|
|
766
|
+
constructor(timeoutMs) {
|
|
767
|
+
super(timeoutMs ? `Task timed out after ${timeoutMs}ms` : "Task timed out");
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
class TaskGraphTimeoutError extends TaskTimeoutError {
|
|
772
|
+
static type = "TaskGraphTimeoutError";
|
|
773
|
+
constructor(timeoutMs) {
|
|
774
|
+
super(timeoutMs);
|
|
775
|
+
this.message = timeoutMs ? `Graph execution timed out after ${timeoutMs}ms` : "Graph execution timed out";
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
class TaskFailedError extends TaskError {
|
|
780
|
+
static type = "TaskFailedError";
|
|
781
|
+
constructor(message = "Task failed") {
|
|
782
|
+
super(message);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
class JobTaskFailedError extends TaskFailedError {
|
|
787
|
+
static type = "JobTaskFailedError";
|
|
788
|
+
jobError;
|
|
789
|
+
constructor(err) {
|
|
790
|
+
super(String(err));
|
|
791
|
+
this.jobError = err;
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
class TaskJSONError extends TaskError {
|
|
796
|
+
static type = "TaskJSONError";
|
|
797
|
+
constructor(message = "Error converting JSON to a Task") {
|
|
798
|
+
super(message);
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
class TaskInvalidInputError extends TaskError {
|
|
803
|
+
static type = "TaskInvalidInputError";
|
|
804
|
+
constructor(message = "Invalid input data") {
|
|
805
|
+
super(message);
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
class TaskSerializationError extends TaskError {
|
|
810
|
+
static type = "TaskSerializationError";
|
|
811
|
+
constructor(taskType) {
|
|
812
|
+
super(`Task "${taskType}" cannot be serialized: config contains non-serializable values. ` + `Use a declarative config alternative or remove function-valued config properties.`);
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
// src/task/TaskRunner.ts
|
|
817
|
+
import {
|
|
818
|
+
getLogger,
|
|
819
|
+
getTelemetryProvider,
|
|
820
|
+
globalServiceRegistry,
|
|
821
|
+
SpanStatusCode
|
|
822
|
+
} from "@workglow/util";
|
|
734
823
|
|
|
735
824
|
// src/task/InputResolver.ts
|
|
736
825
|
import { getInputResolvers } from "@workglow/util";
|
|
@@ -776,6 +865,18 @@ function getFormatPrefix(format) {
|
|
|
776
865
|
const colonIndex = format.indexOf(":");
|
|
777
866
|
return colonIndex >= 0 ? format.substring(0, colonIndex) : format;
|
|
778
867
|
}
|
|
868
|
+
function schemaHasFormatAnnotations(schema) {
|
|
869
|
+
if (typeof schema === "boolean")
|
|
870
|
+
return false;
|
|
871
|
+
const properties = schema.properties;
|
|
872
|
+
if (!properties || typeof properties !== "object")
|
|
873
|
+
return false;
|
|
874
|
+
for (const propSchema of Object.values(properties)) {
|
|
875
|
+
if (getSchemaFormat(propSchema) !== undefined)
|
|
876
|
+
return true;
|
|
877
|
+
}
|
|
878
|
+
return false;
|
|
879
|
+
}
|
|
779
880
|
async function resolveSchemaInputs(input, schema, config) {
|
|
780
881
|
if (typeof schema === "boolean")
|
|
781
882
|
return input;
|
|
@@ -813,7 +914,6 @@ async function resolveSchemaInputs(input, schema, config) {
|
|
|
813
914
|
}
|
|
814
915
|
return resolved;
|
|
815
916
|
}
|
|
816
|
-
var init_InputResolver = () => {};
|
|
817
917
|
|
|
818
918
|
// src/task/StreamTypes.ts
|
|
819
919
|
function getPortStreamMode(schema, portId) {
|
|
@@ -917,11 +1017,6 @@ function hasStructuredOutput(schema) {
|
|
|
917
1017
|
}
|
|
918
1018
|
|
|
919
1019
|
// src/task/TaskRunner.ts
|
|
920
|
-
import {
|
|
921
|
-
getTelemetryProvider,
|
|
922
|
-
globalServiceRegistry,
|
|
923
|
-
SpanStatusCode
|
|
924
|
-
} from "@workglow/util";
|
|
925
1020
|
function hasRunConfig(i) {
|
|
926
1021
|
return i !== null && typeof i === "object" && "runConfig" in i;
|
|
927
1022
|
}
|
|
@@ -947,6 +1042,12 @@ class TaskRunner {
|
|
|
947
1042
|
await this.handleStart(config);
|
|
948
1043
|
try {
|
|
949
1044
|
this.task.setInput(overrides);
|
|
1045
|
+
const configSchema = this.task.constructor.configSchema();
|
|
1046
|
+
if (schemaHasFormatAnnotations(configSchema)) {
|
|
1047
|
+
const source = this.task.originalConfig ?? this.task.config;
|
|
1048
|
+
const resolved = await resolveSchemaInputs({ ...source }, configSchema, { registry: this.registry });
|
|
1049
|
+
Object.assign(this.task.config, resolved);
|
|
1050
|
+
}
|
|
950
1051
|
const schema = this.task.constructor.inputSchema();
|
|
951
1052
|
this.task.runInputData = await resolveSchemaInputs(this.task.runInputData, schema, { registry: this.registry });
|
|
952
1053
|
const inputs = this.task.runInputData;
|
|
@@ -960,6 +1061,12 @@ class TaskRunner {
|
|
|
960
1061
|
}
|
|
961
1062
|
let outputs;
|
|
962
1063
|
const isStreamable = isTaskStreamable(this.task);
|
|
1064
|
+
if (!isStreamable && typeof this.task.executeStream !== "function") {
|
|
1065
|
+
const streamMode = getOutputStreamMode(this.task.outputSchema());
|
|
1066
|
+
if (streamMode !== "none") {
|
|
1067
|
+
getLogger().warn(`Task "${this.task.type}" declares streaming output (x-stream: "${streamMode}") ` + `but does not implement executeStream(). Falling back to non-streaming execute().`);
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
963
1070
|
if (this.task.cacheable) {
|
|
964
1071
|
outputs = await this.outputCache?.getOutput(this.task.type, inputs);
|
|
965
1072
|
if (outputs) {
|
|
@@ -998,6 +1105,12 @@ class TaskRunner {
|
|
|
998
1105
|
return this.task.runOutputData;
|
|
999
1106
|
}
|
|
1000
1107
|
this.task.setInput(overrides);
|
|
1108
|
+
const configSchema = this.task.constructor.configSchema();
|
|
1109
|
+
if (schemaHasFormatAnnotations(configSchema)) {
|
|
1110
|
+
const source = this.task.originalConfig ?? this.task.config;
|
|
1111
|
+
const resolved = await resolveSchemaInputs({ ...source }, configSchema, { registry: this.registry });
|
|
1112
|
+
Object.assign(this.task.config, resolved);
|
|
1113
|
+
}
|
|
1001
1114
|
const schema = this.task.constructor.inputSchema();
|
|
1002
1115
|
this.task.runInputData = await resolveSchemaInputs(this.task.runInputData, schema, { registry: this.registry });
|
|
1003
1116
|
await this.handleStartReactive();
|
|
@@ -1226,6 +1339,11 @@ class TaskRunner {
|
|
|
1226
1339
|
this.telemetrySpan.end();
|
|
1227
1340
|
this.telemetrySpan = undefined;
|
|
1228
1341
|
}
|
|
1342
|
+
if (typeof this.task.cleanup === "function") {
|
|
1343
|
+
try {
|
|
1344
|
+
await this.task.cleanup();
|
|
1345
|
+
} catch {}
|
|
1346
|
+
}
|
|
1229
1347
|
this.task.emit("abort", this.task.error);
|
|
1230
1348
|
this.task.emit("status", this.task.status);
|
|
1231
1349
|
}
|
|
@@ -1278,7 +1396,15 @@ class TaskRunner {
|
|
|
1278
1396
|
this.task.completedAt = new Date;
|
|
1279
1397
|
this.task.progress = 100;
|
|
1280
1398
|
this.task.status = TaskStatus.FAILED;
|
|
1281
|
-
|
|
1399
|
+
if (err instanceof TaskError) {
|
|
1400
|
+
this.task.error = err;
|
|
1401
|
+
} else {
|
|
1402
|
+
this.task.error = new TaskFailedError(`Task "${this.task.type}" (${this.task.id}): ${err?.message || "Task failed"}`);
|
|
1403
|
+
}
|
|
1404
|
+
if (this.task.error instanceof TaskError) {
|
|
1405
|
+
this.task.error.taskType ??= this.task.type;
|
|
1406
|
+
this.task.error.taskId ??= this.task.id;
|
|
1407
|
+
}
|
|
1282
1408
|
this.abortController = undefined;
|
|
1283
1409
|
if (this.telemetrySpan) {
|
|
1284
1410
|
this.telemetrySpan.setStatus(SpanStatusCode.ERROR, this.task.error.message);
|
|
@@ -1298,18 +1424,8 @@ class TaskRunner {
|
|
|
1298
1424
|
await this.updateProgress(this.task, progress, message, ...args);
|
|
1299
1425
|
}
|
|
1300
1426
|
}
|
|
1301
|
-
var init_TaskRunner = __esm(() => {
|
|
1302
|
-
init_TaskOutputRepository();
|
|
1303
|
-
init_Conversions();
|
|
1304
|
-
init_InputResolver();
|
|
1305
|
-
init_TaskError();
|
|
1306
|
-
init_TaskTypes();
|
|
1307
|
-
});
|
|
1308
1427
|
|
|
1309
1428
|
// src/task/Task.ts
|
|
1310
|
-
import { compileSchema } from "@workglow/util/schema";
|
|
1311
|
-
import { deepEqual, EventEmitter as EventEmitter3, uuid4 as uuid42 } from "@workglow/util";
|
|
1312
|
-
|
|
1313
1429
|
class Task {
|
|
1314
1430
|
static type = "Task";
|
|
1315
1431
|
static category = "Hidden";
|
|
@@ -1392,6 +1508,7 @@ class Task {
|
|
|
1392
1508
|
runInputData = {};
|
|
1393
1509
|
runOutputData = {};
|
|
1394
1510
|
config;
|
|
1511
|
+
originalConfig;
|
|
1395
1512
|
get id() {
|
|
1396
1513
|
return this.config.id;
|
|
1397
1514
|
}
|
|
@@ -1422,6 +1539,11 @@ class Task {
|
|
|
1422
1539
|
baseConfig.id = uuid42();
|
|
1423
1540
|
}
|
|
1424
1541
|
this.config = this.validateAndApplyConfigDefaults(baseConfig);
|
|
1542
|
+
try {
|
|
1543
|
+
this.originalConfig = Object.freeze(structuredClone(this.config));
|
|
1544
|
+
} catch {
|
|
1545
|
+
this.originalConfig = undefined;
|
|
1546
|
+
}
|
|
1425
1547
|
this.runConfig = runConfig;
|
|
1426
1548
|
}
|
|
1427
1549
|
getDefaultInputsFromStaticInputDefinitions() {
|
|
@@ -1692,7 +1814,10 @@ class Task {
|
|
|
1692
1814
|
const path = e.data.pointer || "";
|
|
1693
1815
|
return `${e.message}${path ? ` (${path})` : ""}`;
|
|
1694
1816
|
});
|
|
1695
|
-
|
|
1817
|
+
const err = new TaskInvalidInputError(`Task "${this.type}" (${this.id}): Input ${JSON.stringify(Object.keys(input))} does not match schema: ${errorMessages.join(", ")}`);
|
|
1818
|
+
err.taskType = this.type;
|
|
1819
|
+
err.taskId = this.id;
|
|
1820
|
+
throw err;
|
|
1696
1821
|
}
|
|
1697
1822
|
return true;
|
|
1698
1823
|
}
|
|
@@ -1717,8 +1842,14 @@ class Task {
|
|
|
1717
1842
|
}
|
|
1718
1843
|
return obj;
|
|
1719
1844
|
}
|
|
1845
|
+
canSerializeConfig() {
|
|
1846
|
+
return true;
|
|
1847
|
+
}
|
|
1720
1848
|
toJSON(_options) {
|
|
1721
1849
|
const ctor = this.constructor;
|
|
1850
|
+
if (!this.canSerializeConfig() || !this.originalConfig) {
|
|
1851
|
+
throw new TaskSerializationError(this.type);
|
|
1852
|
+
}
|
|
1722
1853
|
const schema = ctor.configSchema();
|
|
1723
1854
|
const schemaProperties = typeof schema !== "boolean" && schema?.properties ? schema.properties : {};
|
|
1724
1855
|
const config = {};
|
|
@@ -1728,7 +1859,7 @@ class Task {
|
|
|
1728
1859
|
if (propSchema?.["x-ui-hidden"] === true && key !== "inputSchema" && key !== "outputSchema" && key !== "extras") {
|
|
1729
1860
|
continue;
|
|
1730
1861
|
}
|
|
1731
|
-
const value = this.
|
|
1862
|
+
const value = this.originalConfig[key];
|
|
1732
1863
|
if (value === undefined)
|
|
1733
1864
|
continue;
|
|
1734
1865
|
if (typeof value === "function" || typeof value === "symbol")
|
|
@@ -1789,146 +1920,57 @@ class Task {
|
|
|
1789
1920
|
this.events.emit("regenerate");
|
|
1790
1921
|
}
|
|
1791
1922
|
}
|
|
1792
|
-
var init_Task = __esm(() => {
|
|
1793
|
-
init_Dataflow();
|
|
1794
|
-
init_TaskGraph();
|
|
1795
|
-
init_TaskError();
|
|
1796
|
-
init_TaskRunner();
|
|
1797
|
-
init_TaskTypes();
|
|
1798
|
-
});
|
|
1799
|
-
|
|
1800
|
-
// src/task/ConditionUtils.ts
|
|
1801
|
-
function evaluateCondition(fieldValue, operator, compareValue) {
|
|
1802
|
-
if (fieldValue === null || fieldValue === undefined) {
|
|
1803
|
-
switch (operator) {
|
|
1804
|
-
case "is_empty":
|
|
1805
|
-
return true;
|
|
1806
|
-
case "is_not_empty":
|
|
1807
|
-
return false;
|
|
1808
|
-
case "is_true":
|
|
1809
|
-
return false;
|
|
1810
|
-
case "is_false":
|
|
1811
|
-
return true;
|
|
1812
|
-
default:
|
|
1813
|
-
return false;
|
|
1814
|
-
}
|
|
1815
|
-
}
|
|
1816
|
-
const strValue = String(fieldValue);
|
|
1817
|
-
const numValue = Number(fieldValue);
|
|
1818
|
-
switch (operator) {
|
|
1819
|
-
case "equals":
|
|
1820
|
-
if (!isNaN(numValue) && !isNaN(Number(compareValue))) {
|
|
1821
|
-
return numValue === Number(compareValue);
|
|
1822
|
-
}
|
|
1823
|
-
return strValue === compareValue;
|
|
1824
|
-
case "not_equals":
|
|
1825
|
-
if (!isNaN(numValue) && !isNaN(Number(compareValue))) {
|
|
1826
|
-
return numValue !== Number(compareValue);
|
|
1827
|
-
}
|
|
1828
|
-
return strValue !== compareValue;
|
|
1829
|
-
case "greater_than":
|
|
1830
|
-
return numValue > Number(compareValue);
|
|
1831
|
-
case "greater_or_equal":
|
|
1832
|
-
return numValue >= Number(compareValue);
|
|
1833
|
-
case "less_than":
|
|
1834
|
-
return numValue < Number(compareValue);
|
|
1835
|
-
case "less_or_equal":
|
|
1836
|
-
return numValue <= Number(compareValue);
|
|
1837
|
-
case "contains":
|
|
1838
|
-
return strValue.toLowerCase().includes(compareValue.toLowerCase());
|
|
1839
|
-
case "starts_with":
|
|
1840
|
-
return strValue.toLowerCase().startsWith(compareValue.toLowerCase());
|
|
1841
|
-
case "ends_with":
|
|
1842
|
-
return strValue.toLowerCase().endsWith(compareValue.toLowerCase());
|
|
1843
|
-
case "is_empty":
|
|
1844
|
-
return strValue === "" || Array.isArray(fieldValue) && fieldValue.length === 0;
|
|
1845
|
-
case "is_not_empty":
|
|
1846
|
-
return strValue !== "" && !(Array.isArray(fieldValue) && fieldValue.length === 0);
|
|
1847
|
-
case "is_true":
|
|
1848
|
-
return Boolean(fieldValue) === true;
|
|
1849
|
-
case "is_false":
|
|
1850
|
-
return Boolean(fieldValue) === false;
|
|
1851
|
-
default:
|
|
1852
|
-
return false;
|
|
1853
|
-
}
|
|
1854
|
-
}
|
|
1855
|
-
function getNestedValue(obj, path) {
|
|
1856
|
-
const parts = path.split(".");
|
|
1857
|
-
let current = obj;
|
|
1858
|
-
for (const part of parts) {
|
|
1859
|
-
if (current === null || current === undefined || typeof current !== "object") {
|
|
1860
|
-
return;
|
|
1861
|
-
}
|
|
1862
|
-
current = current[part];
|
|
1863
|
-
}
|
|
1864
|
-
return current;
|
|
1865
|
-
}
|
|
1866
1923
|
|
|
1867
1924
|
// src/task/ConditionalTask.ts
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
type: "
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
return
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
];
|
|
1903
|
-
}
|
|
1904
|
-
return conditionConfig.branches.map((branch, index) => ({
|
|
1905
|
-
id: branch.id,
|
|
1906
|
-
outputPort: String(index + 1),
|
|
1907
|
-
condition: (inputData) => {
|
|
1908
|
-
const fieldValue = getNestedValue(inputData, branch.field);
|
|
1909
|
-
return evaluateCondition(fieldValue, branch.operator, branch.value);
|
|
1925
|
+
var conditionalTaskConfigSchema = {
|
|
1926
|
+
type: "object",
|
|
1927
|
+
properties: {
|
|
1928
|
+
...TaskConfigSchema["properties"],
|
|
1929
|
+
branches: { type: "array", items: {} },
|
|
1930
|
+
defaultBranch: { type: "string" },
|
|
1931
|
+
exclusive: { type: "boolean" },
|
|
1932
|
+
conditionConfig: { type: "object", additionalProperties: true }
|
|
1933
|
+
},
|
|
1934
|
+
additionalProperties: false
|
|
1935
|
+
};
|
|
1936
|
+
|
|
1937
|
+
class ConditionalTask extends Task {
|
|
1938
|
+
static type = "ConditionalTask";
|
|
1939
|
+
static category = "Flow Control";
|
|
1940
|
+
static title = "Condition";
|
|
1941
|
+
static description = "Route data based on conditions";
|
|
1942
|
+
static hasDynamicSchemas = true;
|
|
1943
|
+
static configSchema() {
|
|
1944
|
+
return conditionalTaskConfigSchema;
|
|
1945
|
+
}
|
|
1946
|
+
canSerializeConfig() {
|
|
1947
|
+
if (!this.config.branches)
|
|
1948
|
+
return true;
|
|
1949
|
+
return !this.config.branches.some((b) => typeof b.condition === "function");
|
|
1950
|
+
}
|
|
1951
|
+
activeBranches = new Set;
|
|
1952
|
+
buildBranchesFromConditionConfig(conditionConfig) {
|
|
1953
|
+
if (!conditionConfig?.branches || conditionConfig.branches.length === 0) {
|
|
1954
|
+
return [
|
|
1955
|
+
{
|
|
1956
|
+
id: "default",
|
|
1957
|
+
condition: () => true,
|
|
1958
|
+
outputPort: "1"
|
|
1910
1959
|
}
|
|
1911
|
-
|
|
1960
|
+
];
|
|
1912
1961
|
}
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
defaultBranch: this.config.defaultBranch,
|
|
1920
|
-
fromConditionConfig: false
|
|
1921
|
-
};
|
|
1922
|
-
}
|
|
1923
|
-
const conditionConfig = input.conditionConfig ?? this.config.conditionConfig;
|
|
1924
|
-
if (conditionConfig) {
|
|
1925
|
-
return {
|
|
1926
|
-
branches: this.buildBranchesFromConditionConfig(conditionConfig),
|
|
1927
|
-
isExclusive: conditionConfig.exclusive ?? true,
|
|
1928
|
-
defaultBranch: conditionConfig.defaultBranch,
|
|
1929
|
-
fromConditionConfig: true
|
|
1930
|
-
};
|
|
1962
|
+
return conditionConfig.branches.map((branch, index) => ({
|
|
1963
|
+
id: branch.id,
|
|
1964
|
+
outputPort: String(index + 1),
|
|
1965
|
+
condition: (inputData) => {
|
|
1966
|
+
const fieldValue = getNestedValue(inputData, branch.field);
|
|
1967
|
+
return evaluateCondition(fieldValue, branch.operator, branch.value);
|
|
1931
1968
|
}
|
|
1969
|
+
}));
|
|
1970
|
+
}
|
|
1971
|
+
resolveBranches(input) {
|
|
1972
|
+
const configBranches = this.config.branches ?? [];
|
|
1973
|
+
if (configBranches.length > 0 && typeof configBranches[0].condition === "function") {
|
|
1932
1974
|
return {
|
|
1933
1975
|
branches: configBranches,
|
|
1934
1976
|
isExclusive: this.config.exclusive ?? true,
|
|
@@ -1936,146 +1978,161 @@ var init_ConditionalTask = __esm(() => {
|
|
|
1936
1978
|
fromConditionConfig: false
|
|
1937
1979
|
};
|
|
1938
1980
|
}
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1981
|
+
const conditionConfig = input.conditionConfig ?? this.config.conditionConfig;
|
|
1982
|
+
if (conditionConfig) {
|
|
1983
|
+
return {
|
|
1984
|
+
branches: this.buildBranchesFromConditionConfig(conditionConfig),
|
|
1985
|
+
isExclusive: conditionConfig.exclusive ?? true,
|
|
1986
|
+
defaultBranch: conditionConfig.defaultBranch,
|
|
1987
|
+
fromConditionConfig: true
|
|
1988
|
+
};
|
|
1989
|
+
}
|
|
1990
|
+
return {
|
|
1991
|
+
branches: configBranches,
|
|
1992
|
+
isExclusive: this.config.exclusive ?? true,
|
|
1993
|
+
defaultBranch: this.config.defaultBranch,
|
|
1994
|
+
fromConditionConfig: false
|
|
1995
|
+
};
|
|
1996
|
+
}
|
|
1997
|
+
async execute(input, context) {
|
|
1998
|
+
if (context.signal?.aborted) {
|
|
1999
|
+
return;
|
|
2000
|
+
}
|
|
2001
|
+
this.activeBranches.clear();
|
|
2002
|
+
const { branches, isExclusive, defaultBranch, fromConditionConfig } = this.resolveBranches(input);
|
|
2003
|
+
for (const branch of branches) {
|
|
2004
|
+
try {
|
|
2005
|
+
const isActive = branch.condition(input);
|
|
2006
|
+
if (isActive) {
|
|
2007
|
+
this.activeBranches.add(branch.id);
|
|
2008
|
+
if (isExclusive) {
|
|
2009
|
+
break;
|
|
1953
2010
|
}
|
|
1954
|
-
} catch (error) {
|
|
1955
|
-
getLogger().warn(`Condition evaluation failed for branch "${branch.id}":`, { error });
|
|
1956
|
-
}
|
|
1957
|
-
}
|
|
1958
|
-
if (this.activeBranches.size === 0 && defaultBranch) {
|
|
1959
|
-
const defaultBranchExists = branches.some((b) => b.id === defaultBranch);
|
|
1960
|
-
if (defaultBranchExists) {
|
|
1961
|
-
this.activeBranches.add(defaultBranch);
|
|
1962
2011
|
}
|
|
2012
|
+
} catch (error) {
|
|
2013
|
+
getLogger2().warn(`Condition evaluation failed for branch "${branch.id}":`, { error });
|
|
1963
2014
|
}
|
|
1964
|
-
|
|
1965
|
-
|
|
2015
|
+
}
|
|
2016
|
+
if (this.activeBranches.size === 0 && defaultBranch) {
|
|
2017
|
+
const defaultBranchExists = branches.some((b) => b.id === defaultBranch);
|
|
2018
|
+
if (defaultBranchExists) {
|
|
2019
|
+
this.activeBranches.add(defaultBranch);
|
|
1966
2020
|
}
|
|
1967
|
-
return this.buildOutput(input);
|
|
1968
2021
|
}
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
2022
|
+
if (fromConditionConfig) {
|
|
2023
|
+
return this.buildConditionConfigOutput(input, branches, isExclusive);
|
|
2024
|
+
}
|
|
2025
|
+
return this.buildOutput(input);
|
|
2026
|
+
}
|
|
2027
|
+
buildConditionConfigOutput(input, branches, isExclusive) {
|
|
2028
|
+
const output = {};
|
|
2029
|
+
const { conditionConfig, ...passThrough } = input;
|
|
2030
|
+
const inputKeys = Object.keys(passThrough);
|
|
2031
|
+
let matchedBranchNumber = null;
|
|
2032
|
+
for (let i = 0;i < branches.length; i++) {
|
|
2033
|
+
if (this.activeBranches.has(branches[i].id)) {
|
|
2034
|
+
if (matchedBranchNumber === null) {
|
|
2035
|
+
matchedBranchNumber = i + 1;
|
|
1979
2036
|
}
|
|
1980
2037
|
}
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
}
|
|
1986
|
-
} else {
|
|
1987
|
-
for (const key of inputKeys) {
|
|
1988
|
-
output[`${key}_else`] = passThrough[key];
|
|
1989
|
-
}
|
|
2038
|
+
}
|
|
2039
|
+
if (isExclusive) {
|
|
2040
|
+
if (matchedBranchNumber !== null) {
|
|
2041
|
+
for (const key of inputKeys) {
|
|
2042
|
+
output[`${key}_${matchedBranchNumber}`] = passThrough[key];
|
|
1990
2043
|
}
|
|
1991
2044
|
} else {
|
|
1992
|
-
for (
|
|
1993
|
-
|
|
1994
|
-
for (const key of inputKeys) {
|
|
1995
|
-
output[`${key}_${i + 1}`] = passThrough[key];
|
|
1996
|
-
}
|
|
1997
|
-
}
|
|
2045
|
+
for (const key of inputKeys) {
|
|
2046
|
+
output[`${key}_else`] = passThrough[key];
|
|
1998
2047
|
}
|
|
1999
2048
|
}
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
const branches = this.config.branches ?? [];
|
|
2007
|
-
for (const branch of branches) {
|
|
2008
|
-
if (this.activeBranches.has(branch.id)) {
|
|
2009
|
-
output[branch.outputPort] = { ...input };
|
|
2049
|
+
} else {
|
|
2050
|
+
for (let i = 0;i < branches.length; i++) {
|
|
2051
|
+
if (this.activeBranches.has(branches[i].id)) {
|
|
2052
|
+
for (const key of inputKeys) {
|
|
2053
|
+
output[`${key}_${i + 1}`] = passThrough[key];
|
|
2054
|
+
}
|
|
2010
2055
|
}
|
|
2011
2056
|
}
|
|
2012
|
-
return output;
|
|
2013
|
-
}
|
|
2014
|
-
isBranchActive(branchId) {
|
|
2015
|
-
return this.activeBranches.has(branchId);
|
|
2016
|
-
}
|
|
2017
|
-
getActiveBranches() {
|
|
2018
|
-
return new Set(this.activeBranches);
|
|
2019
2057
|
}
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2058
|
+
return output;
|
|
2059
|
+
}
|
|
2060
|
+
buildOutput(input) {
|
|
2061
|
+
const output = {
|
|
2062
|
+
_activeBranches: Array.from(this.activeBranches)
|
|
2063
|
+
};
|
|
2064
|
+
const branches = this.config.branches ?? [];
|
|
2065
|
+
for (const branch of branches) {
|
|
2066
|
+
if (this.activeBranches.has(branch.id)) {
|
|
2067
|
+
output[branch.outputPort] = { ...input };
|
|
2025
2068
|
}
|
|
2026
|
-
return status;
|
|
2027
2069
|
}
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2070
|
+
return output;
|
|
2071
|
+
}
|
|
2072
|
+
isBranchActive(branchId) {
|
|
2073
|
+
return this.activeBranches.has(branchId);
|
|
2074
|
+
}
|
|
2075
|
+
getActiveBranches() {
|
|
2076
|
+
return new Set(this.activeBranches);
|
|
2077
|
+
}
|
|
2078
|
+
getPortActiveStatus() {
|
|
2079
|
+
const status = new Map;
|
|
2080
|
+
const branches = this.config.branches ?? [];
|
|
2081
|
+
for (const branch of branches) {
|
|
2082
|
+
status.set(branch.outputPort, this.activeBranches.has(branch.id));
|
|
2040
2083
|
}
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2084
|
+
return status;
|
|
2085
|
+
}
|
|
2086
|
+
static outputSchema() {
|
|
2087
|
+
return {
|
|
2088
|
+
type: "object",
|
|
2089
|
+
properties: {
|
|
2044
2090
|
_activeBranches: {
|
|
2045
2091
|
type: "array",
|
|
2046
2092
|
items: { type: "string" },
|
|
2047
2093
|
description: "List of active branch IDs after condition evaluation"
|
|
2048
2094
|
}
|
|
2049
|
-
}
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2095
|
+
},
|
|
2096
|
+
additionalProperties: true
|
|
2097
|
+
};
|
|
2098
|
+
}
|
|
2099
|
+
outputSchema() {
|
|
2100
|
+
const branches = this.config?.branches ?? [];
|
|
2101
|
+
const properties = {
|
|
2102
|
+
_activeBranches: {
|
|
2103
|
+
type: "array",
|
|
2104
|
+
items: { type: "string" },
|
|
2105
|
+
description: "List of active branch IDs after condition evaluation"
|
|
2056
2106
|
}
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
additionalProperties: false
|
|
2061
|
-
};
|
|
2062
|
-
}
|
|
2063
|
-
static inputSchema() {
|
|
2064
|
-
return {
|
|
2065
|
-
type: "object",
|
|
2066
|
-
properties: {},
|
|
2067
|
-
additionalProperties: true
|
|
2068
|
-
};
|
|
2069
|
-
}
|
|
2070
|
-
inputSchema() {
|
|
2071
|
-
return {
|
|
2107
|
+
};
|
|
2108
|
+
for (const branch of branches) {
|
|
2109
|
+
properties[branch.outputPort] = {
|
|
2072
2110
|
type: "object",
|
|
2073
|
-
|
|
2111
|
+
description: `Output for branch "${branch.id}" when active`,
|
|
2074
2112
|
additionalProperties: true
|
|
2075
2113
|
};
|
|
2076
2114
|
}
|
|
2077
|
-
|
|
2078
|
-
|
|
2115
|
+
return {
|
|
2116
|
+
type: "object",
|
|
2117
|
+
properties,
|
|
2118
|
+
additionalProperties: false
|
|
2119
|
+
};
|
|
2120
|
+
}
|
|
2121
|
+
static inputSchema() {
|
|
2122
|
+
return {
|
|
2123
|
+
type: "object",
|
|
2124
|
+
properties: {},
|
|
2125
|
+
additionalProperties: true
|
|
2126
|
+
};
|
|
2127
|
+
}
|
|
2128
|
+
inputSchema() {
|
|
2129
|
+
return {
|
|
2130
|
+
type: "object",
|
|
2131
|
+
properties: {},
|
|
2132
|
+
additionalProperties: true
|
|
2133
|
+
};
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2079
2136
|
|
|
2080
2137
|
// src/task-graph/TaskGraphScheduler.ts
|
|
2081
2138
|
class TopologicalScheduler {
|
|
@@ -2220,24 +2277,14 @@ class DependencyBasedScheduler {
|
|
|
2220
2277
|
this.nextResolver = null;
|
|
2221
2278
|
}
|
|
2222
2279
|
}
|
|
2223
|
-
var init_TaskGraphScheduler = __esm(() => {
|
|
2224
|
-
init_TaskTypes();
|
|
2225
|
-
});
|
|
2226
2280
|
|
|
2227
2281
|
// src/task-graph/TaskGraphRunner.ts
|
|
2228
|
-
import {
|
|
2229
|
-
collectPropertyValues,
|
|
2230
|
-
getLogger as getLogger2,
|
|
2231
|
-
getTelemetryProvider as getTelemetryProvider2,
|
|
2232
|
-
globalServiceRegistry as globalServiceRegistry2,
|
|
2233
|
-
ServiceRegistry as ServiceRegistry2,
|
|
2234
|
-
SpanStatusCode as SpanStatusCode2,
|
|
2235
|
-
uuid4 as uuid43
|
|
2236
|
-
} from "@workglow/util";
|
|
2237
2282
|
function taskPrototypeHasOwnExecute(task) {
|
|
2238
2283
|
const Ctor = task.constructor;
|
|
2239
2284
|
return Object.hasOwn(Ctor.prototype, "execute");
|
|
2240
2285
|
}
|
|
2286
|
+
var PROPERTY_ARRAY = "PROPERTY_ARRAY";
|
|
2287
|
+
var GRAPH_RESULT_ARRAY = "GRAPH_RESULT_ARRAY";
|
|
2241
2288
|
|
|
2242
2289
|
class TaskGraphRunner {
|
|
2243
2290
|
processScheduler;
|
|
@@ -2253,6 +2300,8 @@ class TaskGraphRunner {
|
|
|
2253
2300
|
inProgressFunctions = new Map;
|
|
2254
2301
|
failedTaskErrors = new Map;
|
|
2255
2302
|
telemetrySpan;
|
|
2303
|
+
graphTimeoutTimer;
|
|
2304
|
+
pendingGraphTimeoutError;
|
|
2256
2305
|
constructor(graph, outputCache, processScheduler = new DependencyBasedScheduler(graph), reactiveScheduler = new TopologicalScheduler(graph)) {
|
|
2257
2306
|
this.processScheduler = processScheduler;
|
|
2258
2307
|
this.reactiveScheduler = reactiveScheduler;
|
|
@@ -2303,10 +2352,14 @@ class TaskGraphRunner {
|
|
|
2303
2352
|
}
|
|
2304
2353
|
} catch (err) {
|
|
2305
2354
|
error = err;
|
|
2306
|
-
|
|
2355
|
+
getLogger3().error("Error running graph", { error });
|
|
2307
2356
|
}
|
|
2308
2357
|
await Promise.allSettled(Array.from(this.inProgressTasks.values()));
|
|
2309
2358
|
await Promise.allSettled(Array.from(this.inProgressFunctions.values()));
|
|
2359
|
+
if (this.pendingGraphTimeoutError) {
|
|
2360
|
+
await this.handleAbort();
|
|
2361
|
+
throw this.pendingGraphTimeoutError;
|
|
2362
|
+
}
|
|
2310
2363
|
if (this.failedTaskErrors.size > 0) {
|
|
2311
2364
|
const latestError = this.failedTaskErrors.values().next().value;
|
|
2312
2365
|
this.handleError(latestError);
|
|
@@ -2394,6 +2447,7 @@ class TaskGraphRunner {
|
|
|
2394
2447
|
}
|
|
2395
2448
|
copyInputFromEdgesToNode(task) {
|
|
2396
2449
|
const dataflows = this.graph.getSourceDataflows(task.id);
|
|
2450
|
+
dataflows.sort((a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0);
|
|
2397
2451
|
for (const dataflow of dataflows) {
|
|
2398
2452
|
this.addInputData(task, dataflow.getPortData());
|
|
2399
2453
|
}
|
|
@@ -2402,7 +2456,7 @@ class TaskGraphRunner {
|
|
|
2402
2456
|
const dataflows = this.graph.getTargetDataflows(node.id);
|
|
2403
2457
|
for (const dataflow of dataflows) {
|
|
2404
2458
|
const compatibility = dataflow.semanticallyCompatible(this.graph, dataflow);
|
|
2405
|
-
|
|
2459
|
+
getLogger3().debug("pushOutputFromNodeToEdges", {
|
|
2406
2460
|
dataflowId: dataflow.id,
|
|
2407
2461
|
compatibility,
|
|
2408
2462
|
resultsKeys: Object.keys(results)
|
|
@@ -2416,7 +2470,7 @@ class TaskGraphRunner {
|
|
|
2416
2470
|
} else {
|
|
2417
2471
|
const resultsKeys = Object.keys(results);
|
|
2418
2472
|
if (resultsKeys.length > 0) {
|
|
2419
|
-
|
|
2473
|
+
getLogger3().warn("pushOutputFromNodeToEdge not compatible, not setting port data", {
|
|
2420
2474
|
dataflowId: dataflow.id,
|
|
2421
2475
|
compatibility,
|
|
2422
2476
|
resultsKeys
|
|
@@ -2722,6 +2776,12 @@ class TaskGraphRunner {
|
|
|
2722
2776
|
}
|
|
2723
2777
|
this.graph.outputCache = this.outputCache;
|
|
2724
2778
|
}
|
|
2779
|
+
if (config?.maxTasks !== undefined && config.maxTasks > 0) {
|
|
2780
|
+
const taskCount = this.graph.getTasks().length;
|
|
2781
|
+
if (taskCount > config.maxTasks) {
|
|
2782
|
+
throw new TaskConfigurationError(`Graph has ${taskCount} tasks, exceeding the limit of ${config.maxTasks}`);
|
|
2783
|
+
}
|
|
2784
|
+
}
|
|
2725
2785
|
if (this.running || this.reactiveRunning) {
|
|
2726
2786
|
throw new TaskConfigurationError("Graph is already running");
|
|
2727
2787
|
}
|
|
@@ -2730,6 +2790,13 @@ class TaskGraphRunner {
|
|
|
2730
2790
|
this.abortController.signal.addEventListener("abort", () => {
|
|
2731
2791
|
this.handleAbort();
|
|
2732
2792
|
});
|
|
2793
|
+
if (config?.timeout !== undefined && config.timeout > 0) {
|
|
2794
|
+
this.pendingGraphTimeoutError = undefined;
|
|
2795
|
+
this.graphTimeoutTimer = setTimeout(() => {
|
|
2796
|
+
this.pendingGraphTimeoutError = new TaskGraphTimeoutError(config.timeout);
|
|
2797
|
+
this.abortController?.abort();
|
|
2798
|
+
}, config.timeout);
|
|
2799
|
+
}
|
|
2733
2800
|
if (config?.parentSignal?.aborted) {
|
|
2734
2801
|
this.abortController.abort();
|
|
2735
2802
|
return;
|
|
@@ -2763,10 +2830,23 @@ class TaskGraphRunner {
|
|
|
2763
2830
|
if (config?.registry !== undefined) {
|
|
2764
2831
|
this.registry = config.registry;
|
|
2765
2832
|
}
|
|
2833
|
+
if (config?.maxTasks !== undefined && config.maxTasks > 0) {
|
|
2834
|
+
const taskCount = this.graph.getTasks().length;
|
|
2835
|
+
if (taskCount > config.maxTasks) {
|
|
2836
|
+
throw new TaskConfigurationError(`Graph has ${taskCount} tasks, exceeding the limit of ${config.maxTasks}`);
|
|
2837
|
+
}
|
|
2838
|
+
}
|
|
2766
2839
|
this.reactiveScheduler.reset();
|
|
2767
2840
|
this.reactiveRunning = true;
|
|
2768
2841
|
}
|
|
2842
|
+
clearGraphTimeout() {
|
|
2843
|
+
if (this.graphTimeoutTimer !== undefined) {
|
|
2844
|
+
clearTimeout(this.graphTimeoutTimer);
|
|
2845
|
+
this.graphTimeoutTimer = undefined;
|
|
2846
|
+
}
|
|
2847
|
+
}
|
|
2769
2848
|
async handleComplete() {
|
|
2849
|
+
this.clearGraphTimeout();
|
|
2770
2850
|
this.running = false;
|
|
2771
2851
|
if (this.telemetrySpan) {
|
|
2772
2852
|
this.telemetrySpan.setStatus(SpanStatusCode2.OK);
|
|
@@ -2779,6 +2859,7 @@ class TaskGraphRunner {
|
|
|
2779
2859
|
this.reactiveRunning = false;
|
|
2780
2860
|
}
|
|
2781
2861
|
async handleError(error) {
|
|
2862
|
+
this.clearGraphTimeout();
|
|
2782
2863
|
await Promise.allSettled(this.graph.getTasks().map(async (task) => {
|
|
2783
2864
|
if (task.status === TaskStatus.PROCESSING || task.status === TaskStatus.STREAMING) {
|
|
2784
2865
|
return task.abort();
|
|
@@ -2797,6 +2878,7 @@ class TaskGraphRunner {
|
|
|
2797
2878
|
this.reactiveRunning = false;
|
|
2798
2879
|
}
|
|
2799
2880
|
async handleAbort() {
|
|
2881
|
+
this.clearGraphTimeout();
|
|
2800
2882
|
await Promise.allSettled(this.graph.getTasks().map(async (task) => {
|
|
2801
2883
|
if (task.status === TaskStatus.PROCESSING || task.status === TaskStatus.STREAMING) {
|
|
2802
2884
|
return task.abort();
|
|
@@ -2839,254 +2921,231 @@ class TaskGraphRunner {
|
|
|
2839
2921
|
}
|
|
2840
2922
|
}
|
|
2841
2923
|
}
|
|
2842
|
-
var PROPERTY_ARRAY = "PROPERTY_ARRAY", GRAPH_RESULT_ARRAY = "GRAPH_RESULT_ARRAY";
|
|
2843
|
-
var init_TaskGraphRunner = __esm(() => {
|
|
2844
|
-
init_TaskOutputRepository();
|
|
2845
|
-
init_ConditionalTask();
|
|
2846
|
-
init_TaskError();
|
|
2847
|
-
init_TaskTypes();
|
|
2848
|
-
init_Dataflow();
|
|
2849
|
-
init_TaskGraphScheduler();
|
|
2850
|
-
});
|
|
2851
2924
|
|
|
2852
2925
|
// src/task/GraphAsTaskRunner.ts
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
async handleDisable() {
|
|
2875
|
-
if (this.task.hasChildren()) {
|
|
2876
|
-
await this.task.subGraph.disable();
|
|
2877
|
-
}
|
|
2878
|
-
super.handleDisable();
|
|
2926
|
+
class GraphAsTaskRunner extends TaskRunner {
|
|
2927
|
+
async executeTaskChildren(input) {
|
|
2928
|
+
const unsubscribe = this.task.subGraph.subscribe("graph_progress", (progress, message, ...args) => {
|
|
2929
|
+
this.task.emit("progress", progress, message, ...args);
|
|
2930
|
+
});
|
|
2931
|
+
const results = await this.task.subGraph.run(input, {
|
|
2932
|
+
parentSignal: this.abortController?.signal,
|
|
2933
|
+
outputCache: this.outputCache,
|
|
2934
|
+
registry: this.registry
|
|
2935
|
+
});
|
|
2936
|
+
unsubscribe();
|
|
2937
|
+
return results;
|
|
2938
|
+
}
|
|
2939
|
+
async executeTaskChildrenReactive() {
|
|
2940
|
+
return this.task.subGraph.runReactive(this.task.runInputData, {
|
|
2941
|
+
registry: this.registry
|
|
2942
|
+
});
|
|
2943
|
+
}
|
|
2944
|
+
async handleDisable() {
|
|
2945
|
+
if (this.task.hasChildren()) {
|
|
2946
|
+
await this.task.subGraph.disable();
|
|
2879
2947
|
}
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2948
|
+
super.handleDisable();
|
|
2949
|
+
}
|
|
2950
|
+
async executeTask(input) {
|
|
2951
|
+
if (this.task.hasChildren()) {
|
|
2952
|
+
const runExecuteOutputData = await this.executeTaskChildren(input);
|
|
2953
|
+
this.task.runOutputData = this.task.subGraph.mergeExecuteOutputsToRunOutput(runExecuteOutputData, this.task.compoundMerge);
|
|
2954
|
+
} else {
|
|
2955
|
+
const result = await super.executeTask(input);
|
|
2956
|
+
this.task.runOutputData = result ?? {};
|
|
2889
2957
|
}
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2958
|
+
return this.task.runOutputData;
|
|
2959
|
+
}
|
|
2960
|
+
async executeTaskReactive(input, output) {
|
|
2961
|
+
if (this.task.hasChildren()) {
|
|
2962
|
+
const reactiveResults = await this.executeTaskChildrenReactive();
|
|
2963
|
+
this.task.runOutputData = this.task.subGraph.mergeExecuteOutputsToRunOutput(reactiveResults, this.task.compoundMerge);
|
|
2964
|
+
} else {
|
|
2965
|
+
const reactiveResults = await super.executeTaskReactive(input, output);
|
|
2966
|
+
this.task.runOutputData = Object.assign({}, output, reactiveResults ?? {});
|
|
2899
2967
|
}
|
|
2900
|
-
|
|
2901
|
-
}
|
|
2968
|
+
return this.task.runOutputData;
|
|
2969
|
+
}
|
|
2970
|
+
}
|
|
2902
2971
|
|
|
2903
2972
|
// src/task/GraphAsTask.ts
|
|
2904
|
-
var
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
}
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
GraphAsTask = class GraphAsTask extends Task {
|
|
2926
|
-
static type = "GraphAsTask";
|
|
2927
|
-
static title = "Group";
|
|
2928
|
-
static description = "A group of tasks that are executed together";
|
|
2929
|
-
static category = "Flow Control";
|
|
2930
|
-
static compoundMerge = PROPERTY_ARRAY;
|
|
2931
|
-
static hasDynamicSchemas = true;
|
|
2932
|
-
constructor(input = {}, config = {}) {
|
|
2933
|
-
const { subGraph, ...rest } = config;
|
|
2934
|
-
super(input, rest);
|
|
2935
|
-
if (subGraph) {
|
|
2936
|
-
this.subGraph = subGraph;
|
|
2937
|
-
}
|
|
2938
|
-
this.regenerateGraph();
|
|
2973
|
+
var graphAsTaskConfigSchema = {
|
|
2974
|
+
type: "object",
|
|
2975
|
+
properties: {
|
|
2976
|
+
...TaskConfigSchema["properties"],
|
|
2977
|
+
compoundMerge: { type: "string", "x-ui-hidden": true }
|
|
2978
|
+
},
|
|
2979
|
+
additionalProperties: false
|
|
2980
|
+
};
|
|
2981
|
+
|
|
2982
|
+
class GraphAsTask extends Task {
|
|
2983
|
+
static type = "GraphAsTask";
|
|
2984
|
+
static title = "Group";
|
|
2985
|
+
static description = "A group of tasks that are executed together";
|
|
2986
|
+
static category = "Flow Control";
|
|
2987
|
+
static compoundMerge = PROPERTY_ARRAY;
|
|
2988
|
+
static hasDynamicSchemas = true;
|
|
2989
|
+
constructor(input = {}, config = {}) {
|
|
2990
|
+
const { subGraph, ...rest } = config;
|
|
2991
|
+
super(input, rest);
|
|
2992
|
+
if (subGraph) {
|
|
2993
|
+
this.subGraph = subGraph;
|
|
2939
2994
|
}
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2995
|
+
this.regenerateGraph();
|
|
2996
|
+
}
|
|
2997
|
+
get runner() {
|
|
2998
|
+
if (!this._runner) {
|
|
2999
|
+
this._runner = new GraphAsTaskRunner(this);
|
|
2945
3000
|
}
|
|
2946
|
-
|
|
2947
|
-
|
|
3001
|
+
return this._runner;
|
|
3002
|
+
}
|
|
3003
|
+
static configSchema() {
|
|
3004
|
+
return graphAsTaskConfigSchema;
|
|
3005
|
+
}
|
|
3006
|
+
get compoundMerge() {
|
|
3007
|
+
return this.config?.compoundMerge || this.constructor.compoundMerge;
|
|
3008
|
+
}
|
|
3009
|
+
get cacheable() {
|
|
3010
|
+
return this.runConfig?.cacheable ?? this.config?.cacheable ?? (this.constructor.cacheable && !this.hasChildren());
|
|
3011
|
+
}
|
|
3012
|
+
inputSchema() {
|
|
3013
|
+
if (!this.hasChildren()) {
|
|
3014
|
+
return this.constructor.inputSchema();
|
|
2948
3015
|
}
|
|
2949
|
-
|
|
2950
|
-
|
|
3016
|
+
return computeGraphInputSchema(this.subGraph);
|
|
3017
|
+
}
|
|
3018
|
+
_inputSchemaNode;
|
|
3019
|
+
getInputSchemaNode() {
|
|
3020
|
+
if (!this._inputSchemaNode) {
|
|
3021
|
+
try {
|
|
3022
|
+
const dataPortSchema = this.inputSchema();
|
|
3023
|
+
const schemaNode = Task.generateInputSchemaNode(dataPortSchema);
|
|
3024
|
+
this._inputSchemaNode = schemaNode;
|
|
3025
|
+
} catch (error) {
|
|
3026
|
+
getLogger4().warn(`GraphAsTask "${this.type}" (${this.id}): Failed to compile input schema, ` + `falling back to permissive validation. Inputs will NOT be validated.`, { error, taskType: this.type, taskId: this.id });
|
|
3027
|
+
this._inputSchemaNode = compileSchema2({});
|
|
3028
|
+
}
|
|
2951
3029
|
}
|
|
2952
|
-
|
|
2953
|
-
|
|
3030
|
+
return this._inputSchemaNode;
|
|
3031
|
+
}
|
|
3032
|
+
outputSchema() {
|
|
3033
|
+
if (!this.hasChildren()) {
|
|
3034
|
+
return this.constructor.outputSchema();
|
|
2954
3035
|
}
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
3036
|
+
return computeGraphOutputSchema(this.subGraph);
|
|
3037
|
+
}
|
|
3038
|
+
resetInputData() {
|
|
3039
|
+
super.resetInputData();
|
|
3040
|
+
if (this.hasChildren()) {
|
|
3041
|
+
this.subGraph.getTasks().forEach((node) => {
|
|
3042
|
+
node.resetInputData();
|
|
3043
|
+
});
|
|
3044
|
+
this.subGraph.getDataflows().forEach((dataflow) => {
|
|
3045
|
+
dataflow.reset();
|
|
3046
|
+
});
|
|
2960
3047
|
}
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
3048
|
+
}
|
|
3049
|
+
async* executeStream(input, context) {
|
|
3050
|
+
if (context.inputStreams) {
|
|
3051
|
+
for (const [, stream] of context.inputStreams) {
|
|
3052
|
+
const reader = stream.getReader();
|
|
2964
3053
|
try {
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
3054
|
+
while (true) {
|
|
3055
|
+
const { done, value } = await reader.read();
|
|
3056
|
+
if (done)
|
|
3057
|
+
break;
|
|
3058
|
+
if (value.type === "finish")
|
|
3059
|
+
continue;
|
|
3060
|
+
yield value;
|
|
3061
|
+
}
|
|
3062
|
+
} finally {
|
|
3063
|
+
reader.releaseLock();
|
|
2971
3064
|
}
|
|
2972
3065
|
}
|
|
2973
|
-
return this._inputSchemaNode;
|
|
2974
|
-
}
|
|
2975
|
-
outputSchema() {
|
|
2976
|
-
if (!this.hasChildren()) {
|
|
2977
|
-
return this.constructor.outputSchema();
|
|
2978
|
-
}
|
|
2979
|
-
return computeGraphOutputSchema(this.subGraph);
|
|
2980
|
-
}
|
|
2981
|
-
resetInputData() {
|
|
2982
|
-
super.resetInputData();
|
|
2983
|
-
if (this.hasChildren()) {
|
|
2984
|
-
this.subGraph.getTasks().forEach((node) => {
|
|
2985
|
-
node.resetInputData();
|
|
2986
|
-
});
|
|
2987
|
-
this.subGraph.getDataflows().forEach((dataflow) => {
|
|
2988
|
-
dataflow.reset();
|
|
2989
|
-
});
|
|
2990
|
-
}
|
|
2991
3066
|
}
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
const { done, value } = await reader.read();
|
|
2999
|
-
if (done)
|
|
3000
|
-
break;
|
|
3001
|
-
if (value.type === "finish")
|
|
3002
|
-
continue;
|
|
3003
|
-
yield value;
|
|
3004
|
-
}
|
|
3005
|
-
} finally {
|
|
3006
|
-
reader.releaseLock();
|
|
3007
|
-
}
|
|
3067
|
+
if (this.hasChildren()) {
|
|
3068
|
+
const endingNodeIds = new Set;
|
|
3069
|
+
const tasks = this.subGraph.getTasks();
|
|
3070
|
+
for (const task of tasks) {
|
|
3071
|
+
if (this.subGraph.getTargetDataflows(task.id).length === 0) {
|
|
3072
|
+
endingNodeIds.add(task.id);
|
|
3008
3073
|
}
|
|
3009
3074
|
}
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3075
|
+
const eventQueue = [];
|
|
3076
|
+
let resolveWaiting;
|
|
3077
|
+
let subgraphDone = false;
|
|
3078
|
+
const unsub = this.subGraph.subscribeToTaskStreaming({
|
|
3079
|
+
onStreamChunk: (taskId, event) => {
|
|
3080
|
+
if (endingNodeIds.has(taskId) && event.type !== "finish") {
|
|
3081
|
+
eventQueue.push(event);
|
|
3082
|
+
resolveWaiting?.();
|
|
3016
3083
|
}
|
|
3017
3084
|
}
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
const runPromise = this.subGraph.run(input, { parentSignal: context.signal, accumulateLeafOutputs: false }).then((results2) => {
|
|
3030
|
-
subgraphDone = true;
|
|
3031
|
-
resolveWaiting?.();
|
|
3032
|
-
return results2;
|
|
3033
|
-
});
|
|
3034
|
-
while (!subgraphDone) {
|
|
3035
|
-
if (eventQueue.length === 0) {
|
|
3036
|
-
await new Promise((resolve) => {
|
|
3037
|
-
resolveWaiting = resolve;
|
|
3038
|
-
});
|
|
3039
|
-
}
|
|
3040
|
-
while (eventQueue.length > 0) {
|
|
3041
|
-
yield eventQueue.shift();
|
|
3042
|
-
}
|
|
3085
|
+
});
|
|
3086
|
+
const runPromise = this.subGraph.run(input, { parentSignal: context.signal, accumulateLeafOutputs: false }).then((results2) => {
|
|
3087
|
+
subgraphDone = true;
|
|
3088
|
+
resolveWaiting?.();
|
|
3089
|
+
return results2;
|
|
3090
|
+
});
|
|
3091
|
+
while (!subgraphDone) {
|
|
3092
|
+
if (eventQueue.length === 0) {
|
|
3093
|
+
await new Promise((resolve) => {
|
|
3094
|
+
resolveWaiting = resolve;
|
|
3095
|
+
});
|
|
3043
3096
|
}
|
|
3044
3097
|
while (eventQueue.length > 0) {
|
|
3045
3098
|
yield eventQueue.shift();
|
|
3046
3099
|
}
|
|
3047
|
-
unsub();
|
|
3048
|
-
const results = await runPromise;
|
|
3049
|
-
const mergedOutput = this.subGraph.mergeExecuteOutputsToRunOutput(results, this.compoundMerge);
|
|
3050
|
-
yield { type: "finish", data: mergedOutput };
|
|
3051
|
-
} else {
|
|
3052
|
-
yield { type: "finish", data: input };
|
|
3053
3100
|
}
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
this._inputSchemaNode = undefined;
|
|
3057
|
-
this.events.emit("regenerate");
|
|
3058
|
-
}
|
|
3059
|
-
toJSON(options) {
|
|
3060
|
-
let json = super.toJSON(options);
|
|
3061
|
-
const hasChildren = this.hasChildren();
|
|
3062
|
-
if (hasChildren) {
|
|
3063
|
-
json = {
|
|
3064
|
-
...json,
|
|
3065
|
-
merge: this.compoundMerge,
|
|
3066
|
-
subgraph: this.subGraph.toJSON(options)
|
|
3067
|
-
};
|
|
3101
|
+
while (eventQueue.length > 0) {
|
|
3102
|
+
yield eventQueue.shift();
|
|
3068
3103
|
}
|
|
3069
|
-
|
|
3104
|
+
unsub();
|
|
3105
|
+
const results = await runPromise;
|
|
3106
|
+
const mergedOutput = this.subGraph.mergeExecuteOutputsToRunOutput(results, this.compoundMerge);
|
|
3107
|
+
yield { type: "finish", data: mergedOutput };
|
|
3108
|
+
} else {
|
|
3109
|
+
yield { type: "finish", data: input };
|
|
3070
3110
|
}
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3111
|
+
}
|
|
3112
|
+
regenerateGraph() {
|
|
3113
|
+
this._inputSchemaNode = undefined;
|
|
3114
|
+
this.events.emit("regenerate");
|
|
3115
|
+
}
|
|
3116
|
+
toJSON(options) {
|
|
3117
|
+
let json = super.toJSON(options);
|
|
3118
|
+
const hasChildren = this.hasChildren();
|
|
3119
|
+
if (hasChildren) {
|
|
3120
|
+
json = {
|
|
3121
|
+
...json,
|
|
3122
|
+
merge: this.compoundMerge,
|
|
3123
|
+
subgraph: this.subGraph.toJSON(options)
|
|
3124
|
+
};
|
|
3125
|
+
}
|
|
3126
|
+
return json;
|
|
3127
|
+
}
|
|
3128
|
+
toDependencyJSON(options) {
|
|
3129
|
+
const json = this.toJSON(options);
|
|
3130
|
+
if (this.hasChildren()) {
|
|
3131
|
+
if ("subgraph" in json) {
|
|
3132
|
+
delete json.subgraph;
|
|
3078
3133
|
}
|
|
3079
|
-
return json;
|
|
3134
|
+
return { ...json, subtasks: this.subGraph.toDependencyJSON(options) };
|
|
3080
3135
|
}
|
|
3081
|
-
|
|
3082
|
-
}
|
|
3136
|
+
return json;
|
|
3137
|
+
}
|
|
3138
|
+
}
|
|
3083
3139
|
|
|
3084
3140
|
// src/task-graph/Conversions.ts
|
|
3141
|
+
var _OwnGraphTask;
|
|
3142
|
+
var _OwnWorkflowTask;
|
|
3143
|
+
var _GraphTask;
|
|
3144
|
+
var _ConvWorkflowTask;
|
|
3085
3145
|
function getWrapperClasses() {
|
|
3086
3146
|
if (!_OwnGraphTask) {
|
|
3087
|
-
const GaT = (init_GraphAsTask(), __toCommonJS(exports_GraphAsTask)).GraphAsTask;
|
|
3088
3147
|
|
|
3089
|
-
class ListeningGraphAsTask extends
|
|
3148
|
+
class ListeningGraphAsTask extends GraphAsTask {
|
|
3090
3149
|
constructor(input, config) {
|
|
3091
3150
|
super(input, config);
|
|
3092
3151
|
this.subGraph.on("start", () => {
|
|
@@ -3109,11 +3168,11 @@ function getWrapperClasses() {
|
|
|
3109
3168
|
static type = "Own[Workflow]";
|
|
3110
3169
|
}
|
|
3111
3170
|
|
|
3112
|
-
class GraphTask extends
|
|
3171
|
+
class GraphTask extends GraphAsTask {
|
|
3113
3172
|
static type = "Graph";
|
|
3114
3173
|
}
|
|
3115
3174
|
|
|
3116
|
-
class ConvWorkflowTask extends
|
|
3175
|
+
class ConvWorkflowTask extends GraphAsTask {
|
|
3117
3176
|
static type = "Workflow";
|
|
3118
3177
|
}
|
|
3119
3178
|
_OwnGraphTask = OwnGraphTask;
|
|
@@ -3178,37 +3237,31 @@ function ensureTask(arg, config = {}) {
|
|
|
3178
3237
|
}
|
|
3179
3238
|
return convertPipeFunctionToTask(arg, config);
|
|
3180
3239
|
}
|
|
3181
|
-
var _OwnGraphTask, _OwnWorkflowTask, _GraphTask, _ConvWorkflowTask;
|
|
3182
|
-
var init_Conversions = __esm(() => {
|
|
3183
|
-
init_Task();
|
|
3184
|
-
init_Dataflow();
|
|
3185
|
-
init_TaskGraph();
|
|
3186
|
-
});
|
|
3187
3240
|
|
|
3188
3241
|
// src/task-graph/TaskGraphEvents.ts
|
|
3189
|
-
var EventDagToTaskGraphMapping
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
dataflow_replaced: "edge-replaced"
|
|
3206
|
-
};
|
|
3207
|
-
});
|
|
3242
|
+
var EventDagToTaskGraphMapping = {
|
|
3243
|
+
"node-added": "task_added",
|
|
3244
|
+
"node-removed": "task_removed",
|
|
3245
|
+
"node-replaced": "task_replaced",
|
|
3246
|
+
"edge-added": "dataflow_added",
|
|
3247
|
+
"edge-removed": "dataflow_removed",
|
|
3248
|
+
"edge-replaced": "dataflow_replaced"
|
|
3249
|
+
};
|
|
3250
|
+
var EventTaskGraphToDagMapping = {
|
|
3251
|
+
task_added: "node-added",
|
|
3252
|
+
task_removed: "node-removed",
|
|
3253
|
+
task_replaced: "node-replaced",
|
|
3254
|
+
dataflow_added: "edge-added",
|
|
3255
|
+
dataflow_removed: "edge-removed",
|
|
3256
|
+
dataflow_replaced: "edge-replaced"
|
|
3257
|
+
};
|
|
3208
3258
|
|
|
3209
3259
|
// src/task-graph/TaskGraph.ts
|
|
3210
|
-
|
|
3211
|
-
|
|
3260
|
+
class TaskGraphDAG extends DirectedAcyclicGraph {
|
|
3261
|
+
constructor() {
|
|
3262
|
+
super((task) => task.id, (dataflow) => dataflow.id);
|
|
3263
|
+
}
|
|
3264
|
+
}
|
|
3212
3265
|
|
|
3213
3266
|
class TaskGraph {
|
|
3214
3267
|
outputCache;
|
|
@@ -3229,7 +3282,9 @@ class TaskGraph {
|
|
|
3229
3282
|
outputCache: config?.outputCache || this.outputCache,
|
|
3230
3283
|
parentSignal: config?.parentSignal || undefined,
|
|
3231
3284
|
accumulateLeafOutputs: config?.accumulateLeafOutputs,
|
|
3232
|
-
registry: config?.registry
|
|
3285
|
+
registry: config?.registry,
|
|
3286
|
+
timeout: config?.timeout,
|
|
3287
|
+
maxTasks: config?.maxTasks
|
|
3233
3288
|
});
|
|
3234
3289
|
}
|
|
3235
3290
|
runReactive(input = {}, config = {}) {
|
|
@@ -3269,18 +3324,12 @@ class TaskGraph {
|
|
|
3269
3324
|
return this._dag.addEdges(addedEdges);
|
|
3270
3325
|
}
|
|
3271
3326
|
getDataflow(id) {
|
|
3272
|
-
for (const
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
if (maybeEdges !== null) {
|
|
3276
|
-
for (const edge of maybeEdges) {
|
|
3277
|
-
if (this._dag.edgeIdentity(edge, "", "") == id) {
|
|
3278
|
-
return edge;
|
|
3279
|
-
}
|
|
3280
|
-
}
|
|
3281
|
-
}
|
|
3327
|
+
for (const [, , edge] of this._dag.getEdges()) {
|
|
3328
|
+
if (edge.id === id) {
|
|
3329
|
+
return edge;
|
|
3282
3330
|
}
|
|
3283
3331
|
}
|
|
3332
|
+
return;
|
|
3284
3333
|
}
|
|
3285
3334
|
getDataflows() {
|
|
3286
3335
|
return this._dag.getEdges().map((edge) => edge[2]);
|
|
@@ -3468,9 +3517,9 @@ class TaskGraph {
|
|
|
3468
3517
|
emit(name, ...args) {
|
|
3469
3518
|
const dagEvent = EventTaskGraphToDagMapping[name];
|
|
3470
3519
|
if (dagEvent) {
|
|
3471
|
-
return this.emit_dag(name, ...args);
|
|
3520
|
+
return this.emit_dag.call(this, name, ...args);
|
|
3472
3521
|
} else {
|
|
3473
|
-
return this.emit_local(name, ...args);
|
|
3522
|
+
return this.emit_local.call(this, name, ...args);
|
|
3474
3523
|
}
|
|
3475
3524
|
}
|
|
3476
3525
|
emit_local(name, ...args) {
|
|
@@ -3494,41 +3543,10 @@ function serialGraph(tasks, inputHandle, outputHandle) {
|
|
|
3494
3543
|
graph.addDataflows(serialGraphEdges(tasks, inputHandle, outputHandle));
|
|
3495
3544
|
return graph;
|
|
3496
3545
|
}
|
|
3497
|
-
var TaskGraphDAG;
|
|
3498
|
-
var init_TaskGraph = __esm(() => {
|
|
3499
|
-
init_Conversions();
|
|
3500
|
-
init_Dataflow();
|
|
3501
|
-
init_GraphSchemaUtils();
|
|
3502
|
-
init_TaskGraphEvents();
|
|
3503
|
-
init_TaskGraphRunner();
|
|
3504
|
-
TaskGraphDAG = class TaskGraphDAG extends DirectedAcyclicGraph {
|
|
3505
|
-
constructor() {
|
|
3506
|
-
super((task) => task.id, (dataflow) => dataflow.id);
|
|
3507
|
-
}
|
|
3508
|
-
};
|
|
3509
|
-
});
|
|
3510
|
-
|
|
3511
|
-
// src/common.ts
|
|
3512
|
-
init_Dataflow();
|
|
3513
|
-
init_GraphSchemaUtils();
|
|
3514
|
-
init_TaskGraph();
|
|
3515
|
-
init_TaskGraphEvents();
|
|
3516
|
-
init_TaskGraphRunner();
|
|
3517
|
-
init_Conversions();
|
|
3518
|
-
|
|
3519
|
-
// src/task-graph/GraphToWorkflowCode.ts
|
|
3520
|
-
init_Dataflow();
|
|
3521
|
-
|
|
3522
3546
|
// src/task-graph/Workflow.ts
|
|
3523
|
-
init_GraphAsTask();
|
|
3524
|
-
init_TaskError();
|
|
3525
|
-
init_Conversions();
|
|
3526
|
-
init_Dataflow();
|
|
3527
|
-
init_TaskGraph();
|
|
3528
|
-
init_TaskGraphRunner();
|
|
3529
3547
|
import {
|
|
3530
3548
|
EventEmitter as EventEmitter5,
|
|
3531
|
-
getLogger as
|
|
3549
|
+
getLogger as getLogger5,
|
|
3532
3550
|
uuid4 as uuid45
|
|
3533
3551
|
} from "@workglow/util";
|
|
3534
3552
|
function getLastTask(workflow) {
|
|
@@ -3676,7 +3694,7 @@ class Workflow {
|
|
|
3676
3694
|
const taskSchema = task.inputSchema();
|
|
3677
3695
|
if (typeof taskSchema !== "boolean" && taskSchema.properties?.[dataflow.targetTaskPortId] === undefined && taskSchema.additionalProperties !== true || taskSchema === true && dataflow.targetTaskPortId !== DATAFLOW_ALL_PORTS) {
|
|
3678
3696
|
this._error = `Input ${dataflow.targetTaskPortId} not found on task ${task.id}`;
|
|
3679
|
-
|
|
3697
|
+
getLogger5().error(this._error);
|
|
3680
3698
|
return;
|
|
3681
3699
|
}
|
|
3682
3700
|
dataflow.targetTaskId = task.id;
|
|
@@ -3701,10 +3719,10 @@ class Workflow {
|
|
|
3701
3719
|
if (result.error) {
|
|
3702
3720
|
if (this.isLoopBuilder) {
|
|
3703
3721
|
this._error = result.error;
|
|
3704
|
-
|
|
3722
|
+
getLogger5().warn(this._error);
|
|
3705
3723
|
} else {
|
|
3706
3724
|
this._error = result.error + " Task not added.";
|
|
3707
|
-
|
|
3725
|
+
getLogger5().error(this._error);
|
|
3708
3726
|
this.graph.removeTask(task.id);
|
|
3709
3727
|
}
|
|
3710
3728
|
}
|
|
@@ -3792,7 +3810,7 @@ class Workflow {
|
|
|
3792
3810
|
const nodes = this._graph.getTasks();
|
|
3793
3811
|
if (nodes.length === 0) {
|
|
3794
3812
|
this._error = "No tasks to remove";
|
|
3795
|
-
|
|
3813
|
+
getLogger5().error(this._error);
|
|
3796
3814
|
return this;
|
|
3797
3815
|
}
|
|
3798
3816
|
const lastNode = nodes[nodes.length - 1];
|
|
@@ -3823,7 +3841,7 @@ class Workflow {
|
|
|
3823
3841
|
if (-index > nodes.length) {
|
|
3824
3842
|
const errorMsg = `Back index greater than number of tasks`;
|
|
3825
3843
|
this._error = errorMsg;
|
|
3826
|
-
|
|
3844
|
+
getLogger5().error(this._error);
|
|
3827
3845
|
throw new WorkflowError(errorMsg);
|
|
3828
3846
|
}
|
|
3829
3847
|
const lastNode = nodes[nodes.length + index];
|
|
@@ -3832,13 +3850,13 @@ class Workflow {
|
|
|
3832
3850
|
if (outputSchema === false && source !== DATAFLOW_ALL_PORTS) {
|
|
3833
3851
|
const errorMsg = `Task ${lastNode.id} has schema 'false' and outputs nothing`;
|
|
3834
3852
|
this._error = errorMsg;
|
|
3835
|
-
|
|
3853
|
+
getLogger5().error(this._error);
|
|
3836
3854
|
throw new WorkflowError(errorMsg);
|
|
3837
3855
|
}
|
|
3838
3856
|
} else if (!outputSchema.properties?.[source] && source !== DATAFLOW_ALL_PORTS) {
|
|
3839
3857
|
const errorMsg = `Output ${source} not found on task ${lastNode.id}`;
|
|
3840
3858
|
this._error = errorMsg;
|
|
3841
|
-
|
|
3859
|
+
getLogger5().error(this._error);
|
|
3842
3860
|
throw new WorkflowError(errorMsg);
|
|
3843
3861
|
}
|
|
3844
3862
|
this._dataFlows.push(new Dataflow(lastNode.id, source, undefined, target));
|
|
@@ -3849,7 +3867,7 @@ class Workflow {
|
|
|
3849
3867
|
const parent = getLastTask(this);
|
|
3850
3868
|
if (!parent) {
|
|
3851
3869
|
this._error = "onError() requires a preceding task in the workflow";
|
|
3852
|
-
|
|
3870
|
+
getLogger5().error(this._error);
|
|
3853
3871
|
throw new WorkflowError(this._error);
|
|
3854
3872
|
}
|
|
3855
3873
|
const handlerTask = ensureTask(handler);
|
|
@@ -3947,7 +3965,7 @@ class Workflow {
|
|
|
3947
3965
|
const taskSchema = task.inputSchema();
|
|
3948
3966
|
if (typeof taskSchema !== "boolean" && taskSchema.properties?.[dataflow.targetTaskPortId] === undefined && taskSchema.additionalProperties !== true || taskSchema === true && dataflow.targetTaskPortId !== DATAFLOW_ALL_PORTS) {
|
|
3949
3967
|
this._error = `Input ${dataflow.targetTaskPortId} not found on task ${task.id}`;
|
|
3950
|
-
|
|
3968
|
+
getLogger5().error(this._error);
|
|
3951
3969
|
return;
|
|
3952
3970
|
}
|
|
3953
3971
|
dataflow.targetTaskId = task.id;
|
|
@@ -3977,7 +3995,7 @@ class Workflow {
|
|
|
3977
3995
|
});
|
|
3978
3996
|
if (result.error) {
|
|
3979
3997
|
this._error = result.error + " Task not added.";
|
|
3980
|
-
|
|
3998
|
+
getLogger5().error(this._error);
|
|
3981
3999
|
this.graph.removeTask(iteratorTask.id);
|
|
3982
4000
|
}
|
|
3983
4001
|
}
|
|
@@ -4617,17 +4635,7 @@ ${baseIndent}}`;
|
|
|
4617
4635
|
function resetMethodNameCache() {
|
|
4618
4636
|
methodNameCache = undefined;
|
|
4619
4637
|
}
|
|
4620
|
-
// src/task/index.ts
|
|
4621
|
-
init_ConditionalTask();
|
|
4622
|
-
|
|
4623
|
-
// src/task/FallbackTask.ts
|
|
4624
|
-
init_GraphAsTask();
|
|
4625
|
-
|
|
4626
4638
|
// src/task/FallbackTaskRunner.ts
|
|
4627
|
-
init_GraphAsTaskRunner();
|
|
4628
|
-
init_TaskError();
|
|
4629
|
-
init_TaskTypes();
|
|
4630
|
-
|
|
4631
4639
|
class FallbackTaskRunner extends GraphAsTaskRunner {
|
|
4632
4640
|
async executeTask(input) {
|
|
4633
4641
|
if (this.task.fallbackMode === "data") {
|
|
@@ -4826,27 +4834,18 @@ queueMicrotask(() => {
|
|
|
4826
4834
|
};
|
|
4827
4835
|
Workflow.prototype.endFallbackWith = CreateEndLoopWorkflow("endFallbackWith");
|
|
4828
4836
|
});
|
|
4829
|
-
|
|
4830
|
-
// src/task/index.ts
|
|
4831
|
-
init_GraphAsTask();
|
|
4832
|
-
init_GraphAsTaskRunner();
|
|
4833
|
-
init_InputResolver();
|
|
4834
|
-
|
|
4835
|
-
// src/task/IteratorTask.ts
|
|
4836
|
-
init_GraphAsTask();
|
|
4837
|
-
|
|
4838
4837
|
// src/task/IteratorTaskRunner.ts
|
|
4839
|
-
init_Dataflow();
|
|
4840
|
-
init_TaskGraph();
|
|
4841
|
-
init_GraphAsTaskRunner();
|
|
4842
4838
|
import { uuid4 as uuid46 } from "@workglow/util";
|
|
4843
|
-
|
|
4844
4839
|
class IteratorTaskRunner extends GraphAsTaskRunner {
|
|
4845
4840
|
aggregatingParentMapProgress = false;
|
|
4846
4841
|
mapPartialProgress = [];
|
|
4847
4842
|
mapPartialIterationCount = 0;
|
|
4848
4843
|
async executeTask(input) {
|
|
4849
|
-
|
|
4844
|
+
let analysis = this.task.analyzeIterationInput(input);
|
|
4845
|
+
const maxIterations = this.task.config.maxIterations;
|
|
4846
|
+
if (maxIterations !== undefined && maxIterations > 0 && analysis.iterationCount > maxIterations) {
|
|
4847
|
+
analysis = { ...analysis, iterationCount: maxIterations };
|
|
4848
|
+
}
|
|
4850
4849
|
if (analysis.iterationCount === 0) {
|
|
4851
4850
|
const emptyResult = this.task.getEmptyResult();
|
|
4852
4851
|
return this.executeTaskReactive(input, emptyResult);
|
|
@@ -5006,7 +5005,6 @@ class IteratorTaskRunner extends GraphAsTaskRunner {
|
|
|
5006
5005
|
}
|
|
5007
5006
|
|
|
5008
5007
|
// src/task/IteratorTask.ts
|
|
5009
|
-
init_TaskError();
|
|
5010
5008
|
var ITERATOR_CONTEXT_SCHEMA = {
|
|
5011
5009
|
type: "object",
|
|
5012
5010
|
properties: {
|
|
@@ -5032,6 +5030,7 @@ var iteratorTaskConfigSchema = {
|
|
|
5032
5030
|
...graphAsTaskConfigSchema["properties"],
|
|
5033
5031
|
concurrencyLimit: { type: "integer", minimum: 1 },
|
|
5034
5032
|
batchSize: { type: "integer", minimum: 1 },
|
|
5033
|
+
maxIterations: { type: "integer", minimum: 1 },
|
|
5035
5034
|
iterationInputConfig: { type: "object", additionalProperties: true }
|
|
5036
5035
|
},
|
|
5037
5036
|
additionalProperties: false
|
|
@@ -5100,22 +5099,29 @@ function extractBaseSchema(schema) {
|
|
|
5100
5099
|
}
|
|
5101
5100
|
const variants = schema.oneOf ?? schema.anyOf;
|
|
5102
5101
|
if (Array.isArray(variants)) {
|
|
5102
|
+
let hasScalar = false;
|
|
5103
|
+
let hasArray = false;
|
|
5104
|
+
let scalarVariant;
|
|
5105
|
+
let arrayVariant;
|
|
5103
5106
|
for (const variant of variants) {
|
|
5104
5107
|
if (typeof variant === "object") {
|
|
5105
|
-
const
|
|
5106
|
-
if (
|
|
5107
|
-
|
|
5108
|
+
const v = variant;
|
|
5109
|
+
if (v.type === "array" || "items" in v) {
|
|
5110
|
+
hasArray = true;
|
|
5111
|
+
arrayVariant = variant;
|
|
5112
|
+
} else {
|
|
5113
|
+
hasScalar = true;
|
|
5114
|
+
scalarVariant = variant;
|
|
5108
5115
|
}
|
|
5109
5116
|
}
|
|
5110
5117
|
}
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
}
|
|
5117
|
-
}
|
|
5118
|
+
if (hasScalar && hasArray && variants.length === 2) {
|
|
5119
|
+
return scalarVariant;
|
|
5120
|
+
}
|
|
5121
|
+
if (!hasScalar && hasArray && arrayVariant) {
|
|
5122
|
+
return arrayVariant.items;
|
|
5118
5123
|
}
|
|
5124
|
+
return schema;
|
|
5119
5125
|
}
|
|
5120
5126
|
return schema;
|
|
5121
5127
|
}
|
|
@@ -5498,13 +5504,7 @@ class IteratorTask extends GraphAsTask {
|
|
|
5498
5504
|
}
|
|
5499
5505
|
}
|
|
5500
5506
|
|
|
5501
|
-
// src/task/WhileTask.ts
|
|
5502
|
-
init_GraphAsTask();
|
|
5503
|
-
init_TaskError();
|
|
5504
|
-
|
|
5505
5507
|
// src/task/WhileTaskRunner.ts
|
|
5506
|
-
init_GraphAsTaskRunner();
|
|
5507
|
-
|
|
5508
5508
|
class WhileTaskRunner extends GraphAsTaskRunner {
|
|
5509
5509
|
async executeTask(input) {
|
|
5510
5510
|
const result = await this.task.execute(input, {
|
|
@@ -5562,6 +5562,9 @@ class WhileTask extends GraphAsTask {
|
|
|
5562
5562
|
return WHILE_CONTEXT_SCHEMA;
|
|
5563
5563
|
}
|
|
5564
5564
|
_currentIteration = 0;
|
|
5565
|
+
canSerializeConfig() {
|
|
5566
|
+
return typeof this.config.condition !== "function";
|
|
5567
|
+
}
|
|
5565
5568
|
constructor(input = {}, config = {}) {
|
|
5566
5569
|
super(input, config);
|
|
5567
5570
|
}
|
|
@@ -5683,7 +5686,27 @@ class WhileTask extends GraphAsTask {
|
|
|
5683
5686
|
parentSignal: context.signal
|
|
5684
5687
|
});
|
|
5685
5688
|
currentOutput = this.subGraph.mergeExecuteOutputsToRunOutput(results, this.compoundMerge);
|
|
5686
|
-
|
|
5689
|
+
let shouldContinue;
|
|
5690
|
+
try {
|
|
5691
|
+
shouldContinue = condition(currentOutput, this._currentIteration);
|
|
5692
|
+
} catch (err) {
|
|
5693
|
+
if (err instanceof TaskFailedError) {
|
|
5694
|
+
throw err;
|
|
5695
|
+
}
|
|
5696
|
+
const message = `${this.type}: Condition function threw at iteration ${this._currentIteration}: ${err instanceof Error ? err.message : String(err)}`;
|
|
5697
|
+
const wrappedError = new TaskFailedError(message);
|
|
5698
|
+
if (err instanceof Error && err.stack) {
|
|
5699
|
+
if (wrappedError.stack) {
|
|
5700
|
+
wrappedError.stack += `
|
|
5701
|
+
Caused by original error:
|
|
5702
|
+
${err.stack}`;
|
|
5703
|
+
} else {
|
|
5704
|
+
wrappedError.stack = err.stack;
|
|
5705
|
+
}
|
|
5706
|
+
}
|
|
5707
|
+
throw wrappedError;
|
|
5708
|
+
}
|
|
5709
|
+
if (!shouldContinue) {
|
|
5687
5710
|
break;
|
|
5688
5711
|
}
|
|
5689
5712
|
if (this.chainIterations) {
|
|
@@ -5727,7 +5750,13 @@ class WhileTask extends GraphAsTask {
|
|
|
5727
5750
|
parentSignal: context.signal
|
|
5728
5751
|
});
|
|
5729
5752
|
currentOutput = this.subGraph.mergeExecuteOutputsToRunOutput(results, this.compoundMerge);
|
|
5730
|
-
|
|
5753
|
+
let shouldContinue;
|
|
5754
|
+
try {
|
|
5755
|
+
shouldContinue = condition(currentOutput, this._currentIteration);
|
|
5756
|
+
} catch (err) {
|
|
5757
|
+
throw new TaskFailedError(`${this.type}: Condition function threw at iteration ${this._currentIteration}: ${err instanceof Error ? err.message : String(err)}`);
|
|
5758
|
+
}
|
|
5759
|
+
if (!shouldContinue) {
|
|
5731
5760
|
break;
|
|
5732
5761
|
}
|
|
5733
5762
|
if (this.chainIterations) {
|
|
@@ -6130,209 +6159,7 @@ function getJobQueueFactory() {
|
|
|
6130
6159
|
if (!globalServiceRegistry3.has(JOB_QUEUE_FACTORY)) {
|
|
6131
6160
|
registerJobQueueFactory(defaultJobQueueFactory);
|
|
6132
6161
|
}
|
|
6133
|
-
// src/task/JobQueueTask.ts
|
|
6134
|
-
init_GraphAsTask();
|
|
6135
|
-
import { Job as Job2 } from "@workglow/job-queue";
|
|
6136
|
-
init_TaskError();
|
|
6137
|
-
|
|
6138
|
-
// src/task/TaskQueueRegistry.ts
|
|
6139
|
-
var taskQueueRegistry = null;
|
|
6140
|
-
|
|
6141
|
-
class TaskQueueRegistry {
|
|
6142
|
-
queues = new Map;
|
|
6143
|
-
registerQueue(queue) {
|
|
6144
|
-
const queueName = queue.server.queueName;
|
|
6145
|
-
if (this.queues.has(queueName)) {
|
|
6146
|
-
throw new Error(`Queue with name ${queueName} already exists`);
|
|
6147
|
-
}
|
|
6148
|
-
this.queues.set(queueName, queue);
|
|
6149
|
-
}
|
|
6150
|
-
getQueue(queueName) {
|
|
6151
|
-
return this.queues.get(queueName);
|
|
6152
|
-
}
|
|
6153
|
-
async startQueues() {
|
|
6154
|
-
for (const queue of this.queues.values()) {
|
|
6155
|
-
await queue.server.start();
|
|
6156
|
-
}
|
|
6157
|
-
}
|
|
6158
|
-
async stopQueues() {
|
|
6159
|
-
for (const queue of this.queues.values()) {
|
|
6160
|
-
await queue.server.stop();
|
|
6161
|
-
}
|
|
6162
|
-
}
|
|
6163
|
-
async clearQueues() {
|
|
6164
|
-
for (const queue of this.queues.values()) {
|
|
6165
|
-
await queue.storage.deleteAll();
|
|
6166
|
-
}
|
|
6167
|
-
}
|
|
6168
|
-
}
|
|
6169
|
-
function getTaskQueueRegistry() {
|
|
6170
|
-
if (!taskQueueRegistry) {
|
|
6171
|
-
taskQueueRegistry = new TaskQueueRegistry;
|
|
6172
|
-
}
|
|
6173
|
-
return taskQueueRegistry;
|
|
6174
|
-
}
|
|
6175
|
-
async function setTaskQueueRegistry(registry) {
|
|
6176
|
-
if (taskQueueRegistry) {
|
|
6177
|
-
await taskQueueRegistry.stopQueues();
|
|
6178
|
-
await taskQueueRegistry.clearQueues();
|
|
6179
|
-
}
|
|
6180
|
-
taskQueueRegistry = registry;
|
|
6181
|
-
}
|
|
6182
|
-
|
|
6183
|
-
// src/task/JobQueueTask.ts
|
|
6184
|
-
var jobQueueTaskConfigSchema = {
|
|
6185
|
-
type: "object",
|
|
6186
|
-
properties: {
|
|
6187
|
-
...graphAsTaskConfigSchema["properties"],
|
|
6188
|
-
queue: {
|
|
6189
|
-
oneOf: [{ type: "boolean" }, { type: "string" }],
|
|
6190
|
-
description: "Queue handling: false=run inline, true=use default, string=explicit queue name",
|
|
6191
|
-
"x-ui-hidden": true
|
|
6192
|
-
}
|
|
6193
|
-
},
|
|
6194
|
-
additionalProperties: false
|
|
6195
|
-
};
|
|
6196
|
-
|
|
6197
|
-
class JobQueueTask extends GraphAsTask {
|
|
6198
|
-
static type = "JobQueueTask";
|
|
6199
|
-
static canRunDirectly = true;
|
|
6200
|
-
static configSchema() {
|
|
6201
|
-
return jobQueueTaskConfigSchema;
|
|
6202
|
-
}
|
|
6203
|
-
currentQueueName;
|
|
6204
|
-
currentJobId;
|
|
6205
|
-
currentRunnerId;
|
|
6206
|
-
jobClass;
|
|
6207
|
-
constructor(input = {}, config = {}) {
|
|
6208
|
-
config.queue ??= true;
|
|
6209
|
-
super(input, config);
|
|
6210
|
-
this.jobClass = Job2;
|
|
6211
|
-
}
|
|
6212
|
-
async execute(input, executeContext) {
|
|
6213
|
-
let cleanup = () => {};
|
|
6214
|
-
try {
|
|
6215
|
-
if (this.config.queue === false && !this.constructor.canRunDirectly) {
|
|
6216
|
-
throw new TaskConfigurationError(`${this.type} cannot run directly without a queue`);
|
|
6217
|
-
}
|
|
6218
|
-
const registeredQueue = await this.resolveQueue(input);
|
|
6219
|
-
if (!registeredQueue) {
|
|
6220
|
-
if (!this.constructor.canRunDirectly) {
|
|
6221
|
-
const queueLabel = typeof this.config.queue === "string" ? this.config.queue : this.currentQueueName ?? this.type;
|
|
6222
|
-
throw new TaskConfigurationError(`Queue ${queueLabel} not found, and ${this.type} cannot run directly`);
|
|
6223
|
-
}
|
|
6224
|
-
this.currentJobId = undefined;
|
|
6225
|
-
const job = await this.createJob(input, this.currentQueueName);
|
|
6226
|
-
cleanup = job.onJobProgress((progress, message, details) => {
|
|
6227
|
-
executeContext.updateProgress(progress, message, details);
|
|
6228
|
-
});
|
|
6229
|
-
const output2 = await job.execute(job.input, {
|
|
6230
|
-
signal: executeContext.signal,
|
|
6231
|
-
updateProgress: executeContext.updateProgress.bind(this)
|
|
6232
|
-
});
|
|
6233
|
-
return output2;
|
|
6234
|
-
}
|
|
6235
|
-
const { client } = registeredQueue;
|
|
6236
|
-
const jobInput = await this.getJobInput(input);
|
|
6237
|
-
const handle = await client.submit(jobInput, {
|
|
6238
|
-
jobRunId: this.currentRunnerId,
|
|
6239
|
-
maxRetries: 10
|
|
6240
|
-
});
|
|
6241
|
-
this.currentJobId = handle.id;
|
|
6242
|
-
this.currentQueueName = client.queueName;
|
|
6243
|
-
cleanup = handle.onProgress((progress, message, details) => {
|
|
6244
|
-
executeContext.updateProgress(progress, message, details);
|
|
6245
|
-
});
|
|
6246
|
-
const output = await handle.waitFor();
|
|
6247
|
-
if (output === undefined) {
|
|
6248
|
-
throw new TaskConfigurationError("Job disabled, should not happen");
|
|
6249
|
-
}
|
|
6250
|
-
return output;
|
|
6251
|
-
} catch (err) {
|
|
6252
|
-
throw new JobTaskFailedError(err);
|
|
6253
|
-
} finally {
|
|
6254
|
-
cleanup();
|
|
6255
|
-
}
|
|
6256
|
-
}
|
|
6257
|
-
async getJobInput(input) {
|
|
6258
|
-
return input;
|
|
6259
|
-
}
|
|
6260
|
-
async createJob(input, queueName) {
|
|
6261
|
-
return new this.jobClass({
|
|
6262
|
-
queueName: queueName ?? this.currentQueueName,
|
|
6263
|
-
jobRunId: this.currentRunnerId,
|
|
6264
|
-
input
|
|
6265
|
-
});
|
|
6266
|
-
}
|
|
6267
|
-
async resolveQueue(input) {
|
|
6268
|
-
const preference = this.config.queue ?? true;
|
|
6269
|
-
if (preference === false) {
|
|
6270
|
-
this.currentQueueName = undefined;
|
|
6271
|
-
return;
|
|
6272
|
-
}
|
|
6273
|
-
if (typeof preference === "string") {
|
|
6274
|
-
const registeredQueue2 = getTaskQueueRegistry().getQueue(preference);
|
|
6275
|
-
if (registeredQueue2) {
|
|
6276
|
-
this.currentQueueName = registeredQueue2.server.queueName;
|
|
6277
|
-
return registeredQueue2;
|
|
6278
|
-
}
|
|
6279
|
-
this.currentQueueName = preference;
|
|
6280
|
-
return;
|
|
6281
|
-
}
|
|
6282
|
-
const queueName = await this.getDefaultQueueName(input);
|
|
6283
|
-
if (!queueName) {
|
|
6284
|
-
this.currentQueueName = undefined;
|
|
6285
|
-
return;
|
|
6286
|
-
}
|
|
6287
|
-
this.currentQueueName = queueName;
|
|
6288
|
-
let registeredQueue = getTaskQueueRegistry().getQueue(queueName);
|
|
6289
|
-
if (!registeredQueue) {
|
|
6290
|
-
registeredQueue = await this.createAndRegisterQueue(queueName, input);
|
|
6291
|
-
await registeredQueue.server.start();
|
|
6292
|
-
}
|
|
6293
|
-
return registeredQueue;
|
|
6294
|
-
}
|
|
6295
|
-
async getDefaultQueueName(_input) {
|
|
6296
|
-
return this.type;
|
|
6297
|
-
}
|
|
6298
|
-
async createAndRegisterQueue(queueName, input) {
|
|
6299
|
-
const factory = getJobQueueFactory();
|
|
6300
|
-
let registeredQueue = await factory({
|
|
6301
|
-
queueName,
|
|
6302
|
-
jobClass: this.jobClass,
|
|
6303
|
-
input,
|
|
6304
|
-
config: this.config,
|
|
6305
|
-
task: this
|
|
6306
|
-
});
|
|
6307
|
-
const registry = getTaskQueueRegistry();
|
|
6308
|
-
try {
|
|
6309
|
-
registry.registerQueue(registeredQueue);
|
|
6310
|
-
} catch (err) {
|
|
6311
|
-
if (err instanceof Error && err.message.includes("already exists")) {
|
|
6312
|
-
const existing = registry.getQueue(queueName);
|
|
6313
|
-
if (existing) {
|
|
6314
|
-
registeredQueue = existing;
|
|
6315
|
-
}
|
|
6316
|
-
} else {
|
|
6317
|
-
throw err;
|
|
6318
|
-
}
|
|
6319
|
-
}
|
|
6320
|
-
return registeredQueue;
|
|
6321
|
-
}
|
|
6322
|
-
abort() {
|
|
6323
|
-
if (this.currentQueueName && this.currentJobId) {
|
|
6324
|
-
const registeredQueue = getTaskQueueRegistry().getQueue(this.currentQueueName);
|
|
6325
|
-
if (registeredQueue) {
|
|
6326
|
-
registeredQueue.client.abort(this.currentJobId).catch((err) => {
|
|
6327
|
-
console.warn(`Failed to abort remote job ${this.currentJobId}`, err);
|
|
6328
|
-
});
|
|
6329
|
-
}
|
|
6330
|
-
}
|
|
6331
|
-
super.abort();
|
|
6332
|
-
}
|
|
6333
|
-
}
|
|
6334
6162
|
// src/task/MapTask.ts
|
|
6335
|
-
init_TaskGraphRunner();
|
|
6336
6163
|
var mapTaskConfigSchema = {
|
|
6337
6164
|
type: "object",
|
|
6338
6165
|
properties: {
|
|
@@ -6504,16 +6331,6 @@ queueMicrotask(() => {
|
|
|
6504
6331
|
Workflow.prototype.reduce = CreateLoopWorkflow(ReduceTask);
|
|
6505
6332
|
Workflow.prototype.endReduce = CreateEndLoopWorkflow("endReduce");
|
|
6506
6333
|
});
|
|
6507
|
-
|
|
6508
|
-
// src/task/index.ts
|
|
6509
|
-
init_Task();
|
|
6510
|
-
init_TaskError();
|
|
6511
|
-
|
|
6512
|
-
// src/task/TaskJSON.ts
|
|
6513
|
-
init_Dataflow();
|
|
6514
|
-
init_TaskGraph();
|
|
6515
|
-
init_TaskError();
|
|
6516
|
-
|
|
6517
6334
|
// src/task/TaskRegistry.ts
|
|
6518
6335
|
import {
|
|
6519
6336
|
createServiceToken as createServiceToken3,
|
|
@@ -6562,14 +6379,19 @@ function resolveTaskFromRegistry(id, _format, registry) {
|
|
|
6562
6379
|
registerInputResolver("tasks", resolveTaskFromRegistry);
|
|
6563
6380
|
|
|
6564
6381
|
// src/task/TaskJSON.ts
|
|
6565
|
-
|
|
6566
|
-
var createSingleTaskFromJSON = (item, registry) => {
|
|
6382
|
+
var createSingleTaskFromJSON = (item, registry, options) => {
|
|
6567
6383
|
if (!item.id)
|
|
6568
6384
|
throw new TaskJSONError("Task id required");
|
|
6569
6385
|
if (!item.type)
|
|
6570
6386
|
throw new TaskJSONError("Task type required");
|
|
6571
6387
|
if (item.defaults && Array.isArray(item.defaults))
|
|
6572
6388
|
throw new TaskJSONError("Task defaults must be an object");
|
|
6389
|
+
if (options?.allowedTypes) {
|
|
6390
|
+
const allowed = options.allowedTypes instanceof Set ? options.allowedTypes : new Set(options.allowedTypes);
|
|
6391
|
+
if (!allowed.has(item.type)) {
|
|
6392
|
+
throw new TaskJSONError(`Task type "${item.type}" is not in the allowed types list`);
|
|
6393
|
+
}
|
|
6394
|
+
}
|
|
6573
6395
|
const constructors = getTaskConstructors(registry);
|
|
6574
6396
|
const taskClass = constructors.get(item.type);
|
|
6575
6397
|
if (!taskClass)
|
|
@@ -6581,62 +6403,105 @@ var createSingleTaskFromJSON = (item, registry) => {
|
|
|
6581
6403
|
const task = new taskClass(item.defaults ?? {}, taskConfig, registry ? { registry } : {});
|
|
6582
6404
|
return task;
|
|
6583
6405
|
};
|
|
6584
|
-
var createTaskFromDependencyJSON = (item, registry) => {
|
|
6585
|
-
const task = createSingleTaskFromJSON(item, registry);
|
|
6406
|
+
var createTaskFromDependencyJSON = (item, registry, options) => {
|
|
6407
|
+
const task = createSingleTaskFromJSON(item, registry, options);
|
|
6586
6408
|
if (item.subtasks && item.subtasks.length > 0) {
|
|
6587
6409
|
if (!(task instanceof GraphAsTask)) {
|
|
6588
6410
|
throw new TaskConfigurationError("Subgraph is only supported for CompoundTasks");
|
|
6589
6411
|
}
|
|
6590
|
-
task.subGraph = createGraphFromDependencyJSON(item.subtasks, registry);
|
|
6412
|
+
task.subGraph = createGraphFromDependencyJSON(item.subtasks, registry, options);
|
|
6591
6413
|
}
|
|
6592
6414
|
return task;
|
|
6593
6415
|
};
|
|
6594
|
-
var createGraphFromDependencyJSON = (jsonItems, registry) => {
|
|
6416
|
+
var createGraphFromDependencyJSON = (jsonItems, registry, options) => {
|
|
6595
6417
|
const subGraph = new TaskGraph;
|
|
6596
6418
|
for (const subitem of jsonItems) {
|
|
6597
|
-
subGraph.addTask(createTaskFromDependencyJSON(subitem, registry));
|
|
6419
|
+
subGraph.addTask(createTaskFromDependencyJSON(subitem, registry, options));
|
|
6598
6420
|
}
|
|
6599
6421
|
return subGraph;
|
|
6600
6422
|
};
|
|
6601
|
-
var createTaskFromGraphJSON = (item, registry) => {
|
|
6602
|
-
const task = createSingleTaskFromJSON(item, registry);
|
|
6423
|
+
var createTaskFromGraphJSON = (item, registry, options) => {
|
|
6424
|
+
const task = createSingleTaskFromJSON(item, registry, options);
|
|
6603
6425
|
if (item.subgraph) {
|
|
6604
6426
|
if (!(task instanceof GraphAsTask)) {
|
|
6605
6427
|
throw new TaskConfigurationError("Subgraph is only supported for GraphAsTask");
|
|
6606
6428
|
}
|
|
6607
|
-
task.subGraph = createGraphFromGraphJSON(item.subgraph, registry);
|
|
6429
|
+
task.subGraph = createGraphFromGraphJSON(item.subgraph, registry, options);
|
|
6608
6430
|
}
|
|
6609
6431
|
return task;
|
|
6610
6432
|
};
|
|
6611
|
-
var createGraphFromGraphJSON = (graphJsonObj, registry) => {
|
|
6433
|
+
var createGraphFromGraphJSON = (graphJsonObj, registry, options) => {
|
|
6612
6434
|
const subGraph = new TaskGraph;
|
|
6613
6435
|
for (const subitem of graphJsonObj.tasks) {
|
|
6614
|
-
subGraph.addTask(createTaskFromGraphJSON(subitem, registry));
|
|
6436
|
+
subGraph.addTask(createTaskFromGraphJSON(subitem, registry, options));
|
|
6615
6437
|
}
|
|
6616
6438
|
for (const subitem of graphJsonObj.dataflows) {
|
|
6617
6439
|
subGraph.addDataflow(new Dataflow(subitem.sourceTaskId, subitem.sourceTaskPortId, subitem.targetTaskId, subitem.targetTaskPortId));
|
|
6618
6440
|
}
|
|
6619
6441
|
return subGraph;
|
|
6620
6442
|
};
|
|
6443
|
+
// src/task/TaskQueueRegistry.ts
|
|
6444
|
+
import { EventEmitter as EventEmitter6 } from "@workglow/util";
|
|
6445
|
+
var taskQueueRegistry = null;
|
|
6621
6446
|
|
|
6447
|
+
class TaskQueueRegistry {
|
|
6448
|
+
emitter = new EventEmitter6;
|
|
6449
|
+
queues = new Map;
|
|
6450
|
+
registerQueue(queue) {
|
|
6451
|
+
const queueName = queue.server.queueName;
|
|
6452
|
+
if (this.queues.has(queueName)) {
|
|
6453
|
+
throw new Error(`Queue with name ${queueName} already exists`);
|
|
6454
|
+
}
|
|
6455
|
+
this.queues.set(queueName, queue);
|
|
6456
|
+
this.emitter.emit("queue_registered", queueName);
|
|
6457
|
+
}
|
|
6458
|
+
getQueue(queueName) {
|
|
6459
|
+
return this.queues.get(queueName);
|
|
6460
|
+
}
|
|
6461
|
+
async startQueues() {
|
|
6462
|
+
for (const queue of this.queues.values()) {
|
|
6463
|
+
await queue.server.start();
|
|
6464
|
+
}
|
|
6465
|
+
}
|
|
6466
|
+
async stopQueues() {
|
|
6467
|
+
for (const queue of this.queues.values()) {
|
|
6468
|
+
await queue.server.stop();
|
|
6469
|
+
}
|
|
6470
|
+
}
|
|
6471
|
+
async clearQueues() {
|
|
6472
|
+
for (const queue of this.queues.values()) {
|
|
6473
|
+
await queue.storage.deleteAll();
|
|
6474
|
+
}
|
|
6475
|
+
}
|
|
6476
|
+
}
|
|
6477
|
+
function getTaskQueueRegistry() {
|
|
6478
|
+
if (!taskQueueRegistry) {
|
|
6479
|
+
taskQueueRegistry = new TaskQueueRegistry;
|
|
6480
|
+
}
|
|
6481
|
+
return taskQueueRegistry;
|
|
6482
|
+
}
|
|
6483
|
+
async function setTaskQueueRegistry(registry) {
|
|
6484
|
+
if (taskQueueRegistry) {
|
|
6485
|
+
await taskQueueRegistry.stopQueues();
|
|
6486
|
+
await taskQueueRegistry.clearQueues();
|
|
6487
|
+
}
|
|
6488
|
+
taskQueueRegistry = registry;
|
|
6489
|
+
}
|
|
6622
6490
|
// src/task/index.ts
|
|
6623
|
-
init_ConditionalTask();
|
|
6624
|
-
init_TaskTypes();
|
|
6625
|
-
init_GraphAsTask();
|
|
6626
6491
|
var registerBaseTasks = () => {
|
|
6627
6492
|
const tasks = [GraphAsTask, ConditionalTask, FallbackTask, MapTask, WhileTask, ReduceTask];
|
|
6628
6493
|
tasks.map(TaskRegistry.registerTask);
|
|
6629
6494
|
return tasks;
|
|
6630
6495
|
};
|
|
6631
6496
|
// src/storage/TaskGraphRepository.ts
|
|
6632
|
-
import { createServiceToken as createServiceToken4, EventEmitter as
|
|
6497
|
+
import { createServiceToken as createServiceToken4, EventEmitter as EventEmitter7 } from "@workglow/util";
|
|
6633
6498
|
var TASK_GRAPH_REPOSITORY = createServiceToken4("taskgraph.taskGraphRepository");
|
|
6634
6499
|
|
|
6635
6500
|
class TaskGraphRepository {
|
|
6636
6501
|
type = "TaskGraphRepository";
|
|
6637
6502
|
get events() {
|
|
6638
6503
|
if (!this._events) {
|
|
6639
|
-
this._events = new
|
|
6504
|
+
this._events = new EventEmitter7;
|
|
6640
6505
|
}
|
|
6641
6506
|
return this._events;
|
|
6642
6507
|
}
|
|
@@ -6704,12 +6569,7 @@ class TaskGraphTabularRepository extends TaskGraphRepository {
|
|
|
6704
6569
|
return await this.tabularRepository.size();
|
|
6705
6570
|
}
|
|
6706
6571
|
}
|
|
6707
|
-
|
|
6708
|
-
// src/common.ts
|
|
6709
|
-
init_TaskOutputRepository();
|
|
6710
|
-
|
|
6711
6572
|
// src/storage/TaskOutputTabularRepository.ts
|
|
6712
|
-
init_TaskOutputRepository();
|
|
6713
6573
|
import { compress, decompress } from "@workglow/util/compress";
|
|
6714
6574
|
import { makeFingerprint } from "@workglow/util";
|
|
6715
6575
|
var TaskOutputSchema = {
|
|
@@ -6799,6 +6659,7 @@ export {
|
|
|
6799
6659
|
setTaskQueueRegistry,
|
|
6800
6660
|
setGlobalTaskConstructors,
|
|
6801
6661
|
serialGraph,
|
|
6662
|
+
schemaHasFormatAnnotations,
|
|
6802
6663
|
schemaAcceptsArray,
|
|
6803
6664
|
resolveSchemaInputs,
|
|
6804
6665
|
resetMethodNameCache,
|
|
@@ -6810,7 +6671,6 @@ export {
|
|
|
6810
6671
|
parallel,
|
|
6811
6672
|
mergeChainedOutputToInput,
|
|
6812
6673
|
mapTaskConfigSchema,
|
|
6813
|
-
jobQueueTaskConfigSchema,
|
|
6814
6674
|
iteratorTaskConfigSchema,
|
|
6815
6675
|
isTaskStreamable,
|
|
6816
6676
|
isStrictArraySchema,
|
|
@@ -6867,6 +6727,7 @@ export {
|
|
|
6867
6727
|
WHILE_CONTEXT_SCHEMA,
|
|
6868
6728
|
TaskTimeoutError,
|
|
6869
6729
|
TaskStatus,
|
|
6730
|
+
TaskSerializationError,
|
|
6870
6731
|
TaskRegistry,
|
|
6871
6732
|
TaskQueueRegistry,
|
|
6872
6733
|
TaskOutputTabularRepository,
|
|
@@ -6875,6 +6736,7 @@ export {
|
|
|
6875
6736
|
TaskOutputPrimaryKeyNames,
|
|
6876
6737
|
TaskJSONError,
|
|
6877
6738
|
TaskInvalidInputError,
|
|
6739
|
+
TaskGraphTimeoutError,
|
|
6878
6740
|
TaskGraphTabularRepository,
|
|
6879
6741
|
TaskGraphSchema,
|
|
6880
6742
|
TaskGraphRunner,
|
|
@@ -6894,7 +6756,6 @@ export {
|
|
|
6894
6756
|
PROPERTY_ARRAY,
|
|
6895
6757
|
MapTask,
|
|
6896
6758
|
JobTaskFailedError,
|
|
6897
|
-
JobQueueTask,
|
|
6898
6759
|
JOB_QUEUE_FACTORY,
|
|
6899
6760
|
IteratorTaskRunner,
|
|
6900
6761
|
IteratorTask,
|
|
@@ -6917,4 +6778,4 @@ export {
|
|
|
6917
6778
|
ConditionalTask
|
|
6918
6779
|
};
|
|
6919
6780
|
|
|
6920
|
-
//# debugId=
|
|
6781
|
+
//# debugId=8BC5BADB1209138664756E2164756E21
|