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