@workglow/task-graph 0.0.99 → 0.0.101
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.js +253 -82
- package/dist/browser.js.map +17 -17
- package/dist/bun.js +253 -82
- package/dist/bun.js.map +17 -17
- package/dist/node.js +253 -82
- package/dist/node.js.map +17 -17
- package/dist/task/ConditionalTask.d.ts +53 -21
- package/dist/task/ConditionalTask.d.ts.map +1 -1
- package/dist/task/GraphAsTask.d.ts +37 -2
- package/dist/task/GraphAsTask.d.ts.map +1 -1
- package/dist/task/ITask.d.ts +37 -2
- package/dist/task/ITask.d.ts.map +1 -1
- package/dist/task/IteratorTask.d.ts +49 -3
- package/dist/task/IteratorTask.d.ts.map +1 -1
- package/dist/task/JobQueueTask.d.ts +39 -3
- package/dist/task/JobQueueTask.d.ts.map +1 -1
- package/dist/task/MapTask.d.ts +54 -2
- package/dist/task/MapTask.d.ts.map +1 -1
- package/dist/task/ReduceTask.d.ts +49 -2
- package/dist/task/ReduceTask.d.ts.map +1 -1
- package/dist/task/Task.d.ts +43 -3
- package/dist/task/Task.d.ts.map +1 -1
- package/dist/task/TaskJSON.d.ts +10 -8
- package/dist/task/TaskJSON.d.ts.map +1 -1
- package/dist/task/TaskRunner.d.ts +20 -3
- package/dist/task/TaskRunner.d.ts.map +1 -1
- package/dist/task/TaskTypes.d.ts +60 -18
- package/dist/task/TaskTypes.d.ts.map +1 -1
- package/dist/task/WhileTask.d.ts +70 -7
- package/dist/task/WhileTask.d.ts.map +1 -1
- package/dist/task-graph/Conversions.d.ts.map +1 -1
- package/dist/task-graph/Dataflow.d.ts +11 -10
- package/dist/task-graph/Dataflow.d.ts.map +1 -1
- package/dist/task-graph/TaskGraph.d.ts +7 -0
- package/dist/task-graph/TaskGraph.d.ts.map +1 -1
- package/dist/task-graph/TaskGraphRunner.d.ts +22 -1
- package/dist/task-graph/TaskGraphRunner.d.ts.map +1 -1
- package/package.json +7 -7
package/dist/browser.js
CHANGED
|
@@ -11,6 +11,22 @@ var TaskStatus = {
|
|
|
11
11
|
ABORTING: "ABORTING",
|
|
12
12
|
FAILED: "FAILED"
|
|
13
13
|
};
|
|
14
|
+
var TaskConfigSchema = {
|
|
15
|
+
type: "object",
|
|
16
|
+
properties: {
|
|
17
|
+
id: {},
|
|
18
|
+
title: { type: "string" },
|
|
19
|
+
description: { type: "string" },
|
|
20
|
+
cacheable: { type: "boolean" },
|
|
21
|
+
inputSchema: { type: "object", properties: {}, additionalProperties: true },
|
|
22
|
+
outputSchema: { type: "object", properties: {}, additionalProperties: true },
|
|
23
|
+
extras: {
|
|
24
|
+
type: "object",
|
|
25
|
+
additionalProperties: true
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
additionalProperties: false
|
|
29
|
+
};
|
|
14
30
|
|
|
15
31
|
// src/task-graph/Dataflow.ts
|
|
16
32
|
var DATAFLOW_ALL_PORTS = "*";
|
|
@@ -47,10 +63,8 @@ class Dataflow {
|
|
|
47
63
|
if (!this.stream)
|
|
48
64
|
return;
|
|
49
65
|
const reader = this.stream.getReader();
|
|
50
|
-
const accumulatedPorts = new Map;
|
|
51
66
|
let lastSnapshotData = undefined;
|
|
52
67
|
let finishData = undefined;
|
|
53
|
-
let hasTextDelta = false;
|
|
54
68
|
let streamError;
|
|
55
69
|
try {
|
|
56
70
|
while (true) {
|
|
@@ -58,16 +72,6 @@ class Dataflow {
|
|
|
58
72
|
if (done)
|
|
59
73
|
break;
|
|
60
74
|
switch (event.type) {
|
|
61
|
-
case "text-delta": {
|
|
62
|
-
if (this.sourceTaskPortId !== DATAFLOW_ALL_PORTS && event.port !== this.sourceTaskPortId) {
|
|
63
|
-
break;
|
|
64
|
-
}
|
|
65
|
-
hasTextDelta = true;
|
|
66
|
-
accumulatedPorts.set(event.port, (accumulatedPorts.get(event.port) ?? "") + event.textDelta);
|
|
67
|
-
break;
|
|
68
|
-
}
|
|
69
|
-
case "object-delta":
|
|
70
|
-
break;
|
|
71
75
|
case "snapshot":
|
|
72
76
|
lastSnapshotData = event.data;
|
|
73
77
|
break;
|
|
@@ -90,19 +94,8 @@ class Dataflow {
|
|
|
90
94
|
}
|
|
91
95
|
if (lastSnapshotData !== undefined) {
|
|
92
96
|
this.setPortData(lastSnapshotData);
|
|
93
|
-
} else if (finishData
|
|
97
|
+
} else if (finishData !== undefined) {
|
|
94
98
|
this.setPortData(finishData);
|
|
95
|
-
} else if (hasTextDelta) {
|
|
96
|
-
if (this.sourceTaskPortId === DATAFLOW_ALL_PORTS) {
|
|
97
|
-
const obj = {};
|
|
98
|
-
for (const [port, text] of accumulatedPorts) {
|
|
99
|
-
obj[port] = text;
|
|
100
|
-
}
|
|
101
|
-
this.value = obj;
|
|
102
|
-
} else {
|
|
103
|
-
const text = accumulatedPorts.values().next().value ?? "";
|
|
104
|
-
this.value = text;
|
|
105
|
-
}
|
|
106
99
|
}
|
|
107
100
|
}
|
|
108
101
|
reset() {
|
|
@@ -548,6 +541,7 @@ class TaskRunner {
|
|
|
548
541
|
outputCache;
|
|
549
542
|
registry = globalServiceRegistry;
|
|
550
543
|
inputStreams;
|
|
544
|
+
shouldAccumulate = true;
|
|
551
545
|
constructor(task) {
|
|
552
546
|
this.task = task;
|
|
553
547
|
this.own = this.own.bind(this);
|
|
@@ -656,7 +650,7 @@ class TaskRunner {
|
|
|
656
650
|
throw new TaskError(`Task ${this.task.type} declares append streaming but no output port has x-stream: "append"`);
|
|
657
651
|
}
|
|
658
652
|
}
|
|
659
|
-
const accumulated = new Map;
|
|
653
|
+
const accumulated = this.shouldAccumulate ? new Map : undefined;
|
|
660
654
|
let chunkCount = 0;
|
|
661
655
|
let finalOutput;
|
|
662
656
|
this.task.emit("stream_start");
|
|
@@ -676,33 +670,40 @@ class TaskRunner {
|
|
|
676
670
|
if (event.type === "snapshot") {
|
|
677
671
|
this.task.runOutputData = event.data;
|
|
678
672
|
}
|
|
679
|
-
this.task.emit("stream_chunk", event);
|
|
680
673
|
switch (event.type) {
|
|
681
674
|
case "text-delta": {
|
|
682
|
-
|
|
675
|
+
if (accumulated) {
|
|
676
|
+
accumulated.set(event.port, (accumulated.get(event.port) ?? "") + event.textDelta);
|
|
677
|
+
}
|
|
678
|
+
this.task.emit("stream_chunk", event);
|
|
683
679
|
const progress = Math.min(99, Math.round(100 * (1 - Math.exp(-0.05 * chunkCount))));
|
|
684
680
|
await this.handleProgress(progress);
|
|
685
681
|
break;
|
|
686
682
|
}
|
|
687
683
|
case "object-delta": {
|
|
684
|
+
this.task.emit("stream_chunk", event);
|
|
688
685
|
const progress = Math.min(99, Math.round(100 * (1 - Math.exp(-0.05 * chunkCount))));
|
|
689
686
|
await this.handleProgress(progress);
|
|
690
687
|
break;
|
|
691
688
|
}
|
|
692
689
|
case "snapshot": {
|
|
690
|
+
this.task.emit("stream_chunk", event);
|
|
693
691
|
const progress = Math.min(99, Math.round(100 * (1 - Math.exp(-0.05 * chunkCount))));
|
|
694
692
|
await this.handleProgress(progress);
|
|
695
693
|
break;
|
|
696
694
|
}
|
|
697
695
|
case "finish": {
|
|
698
|
-
if (
|
|
696
|
+
if (accumulated) {
|
|
699
697
|
const merged = { ...event.data || {} };
|
|
700
698
|
for (const [port, text] of accumulated) {
|
|
701
|
-
|
|
699
|
+
if (text.length > 0)
|
|
700
|
+
merged[port] = text;
|
|
702
701
|
}
|
|
703
702
|
finalOutput = merged;
|
|
704
|
-
|
|
703
|
+
this.task.emit("stream_chunk", { type: "finish", data: merged });
|
|
704
|
+
} else {
|
|
705
705
|
finalOutput = event.data;
|
|
706
|
+
this.task.emit("stream_chunk", event);
|
|
706
707
|
}
|
|
707
708
|
break;
|
|
708
709
|
}
|
|
@@ -732,7 +733,7 @@ class TaskRunner {
|
|
|
732
733
|
this.abortController.signal.addEventListener("abort", () => {
|
|
733
734
|
this.handleAbort();
|
|
734
735
|
});
|
|
735
|
-
const cache =
|
|
736
|
+
const cache = config.outputCache ?? this.task.runConfig?.outputCache;
|
|
736
737
|
if (cache === true) {
|
|
737
738
|
let instance = globalServiceRegistry.get(TASK_OUTPUT_REPOSITORY);
|
|
738
739
|
this.outputCache = instance;
|
|
@@ -741,6 +742,7 @@ class TaskRunner {
|
|
|
741
742
|
} else if (cache instanceof TaskOutputRepository) {
|
|
742
743
|
this.outputCache = cache;
|
|
743
744
|
}
|
|
745
|
+
this.shouldAccumulate = config.shouldAccumulate !== false;
|
|
744
746
|
if (config.updateProgress) {
|
|
745
747
|
this.updateProgress = config.updateProgress;
|
|
746
748
|
}
|
|
@@ -823,8 +825,10 @@ class Task {
|
|
|
823
825
|
static type = "Task";
|
|
824
826
|
static category = "Hidden";
|
|
825
827
|
static title = "";
|
|
828
|
+
static description = "";
|
|
826
829
|
static cacheable = true;
|
|
827
830
|
static hasDynamicSchemas = false;
|
|
831
|
+
static passthroughInputsToOutputs = false;
|
|
828
832
|
static inputSchema() {
|
|
829
833
|
return {
|
|
830
834
|
type: "object",
|
|
@@ -839,6 +843,9 @@ class Task {
|
|
|
839
843
|
additionalProperties: false
|
|
840
844
|
};
|
|
841
845
|
}
|
|
846
|
+
static configSchema() {
|
|
847
|
+
return TaskConfigSchema;
|
|
848
|
+
}
|
|
842
849
|
async execute(_input, context) {
|
|
843
850
|
if (context.signal?.aborted) {
|
|
844
851
|
throw new TaskAbortedError("Task aborted");
|
|
@@ -855,8 +862,8 @@ class Task {
|
|
|
855
862
|
}
|
|
856
863
|
return this._runner;
|
|
857
864
|
}
|
|
858
|
-
async run(overrides = {}) {
|
|
859
|
-
return this.runner.run(overrides);
|
|
865
|
+
async run(overrides = {}, runConfig = {}) {
|
|
866
|
+
return this.runner.run(overrides, { ...this.runConfig, ...runConfig });
|
|
860
867
|
}
|
|
861
868
|
async runReactive(overrides = {}) {
|
|
862
869
|
return this.runner.runReactive(overrides);
|
|
@@ -873,6 +880,9 @@ class Task {
|
|
|
873
880
|
outputSchema() {
|
|
874
881
|
return this.constructor.outputSchema();
|
|
875
882
|
}
|
|
883
|
+
configSchema() {
|
|
884
|
+
return this.constructor.configSchema();
|
|
885
|
+
}
|
|
876
886
|
get type() {
|
|
877
887
|
return this.constructor.type;
|
|
878
888
|
}
|
|
@@ -880,15 +890,19 @@ class Task {
|
|
|
880
890
|
return this.constructor.category;
|
|
881
891
|
}
|
|
882
892
|
get title() {
|
|
883
|
-
return this.constructor.title;
|
|
893
|
+
return this.config?.title ?? this.constructor.title;
|
|
894
|
+
}
|
|
895
|
+
get description() {
|
|
896
|
+
return this.config?.description ?? this.constructor.description;
|
|
884
897
|
}
|
|
885
898
|
get cacheable() {
|
|
886
|
-
return this.config?.cacheable ?? this.constructor.cacheable;
|
|
899
|
+
return this.runConfig?.cacheable ?? this.config?.cacheable ?? this.constructor.cacheable;
|
|
887
900
|
}
|
|
888
901
|
defaults;
|
|
889
902
|
runInputData = {};
|
|
890
903
|
runOutputData = {};
|
|
891
904
|
config;
|
|
905
|
+
runConfig = {};
|
|
892
906
|
status = TaskStatus.PENDING;
|
|
893
907
|
progress = 0;
|
|
894
908
|
createdAt = new Date;
|
|
@@ -902,16 +916,18 @@ class Task {
|
|
|
902
916
|
return this._events;
|
|
903
917
|
}
|
|
904
918
|
_events;
|
|
905
|
-
constructor(callerDefaultInputs = {}, config = {}) {
|
|
919
|
+
constructor(callerDefaultInputs = {}, config = {}, runConfig = {}) {
|
|
906
920
|
const inputDefaults = this.getDefaultInputsFromStaticInputDefinitions();
|
|
907
921
|
const mergedDefaults = Object.assign(inputDefaults, callerDefaultInputs);
|
|
908
922
|
this.defaults = this.stripSymbols(mergedDefaults);
|
|
909
923
|
this.resetInputData();
|
|
910
|
-
const
|
|
911
|
-
|
|
924
|
+
const title = this.constructor.title || undefined;
|
|
925
|
+
const baseConfig = Object.assign({
|
|
912
926
|
id: uuid4(),
|
|
913
|
-
|
|
927
|
+
...title ? { title } : {}
|
|
914
928
|
}, config);
|
|
929
|
+
this.config = this.validateAndApplyConfigDefaults(baseConfig);
|
|
930
|
+
this.runConfig = runConfig;
|
|
915
931
|
}
|
|
916
932
|
getDefaultInputsFromStaticInputDefinitions() {
|
|
917
933
|
const schema = this.inputSchema();
|
|
@@ -948,7 +964,7 @@ class Task {
|
|
|
948
964
|
return obj;
|
|
949
965
|
}
|
|
950
966
|
if (visited.has(obj)) {
|
|
951
|
-
throw new
|
|
967
|
+
throw new TaskConfigurationError("Circular reference detected in input data. " + "Cannot clone objects with circular references.");
|
|
952
968
|
}
|
|
953
969
|
if (ArrayBuffer.isView(obj)) {
|
|
954
970
|
if (typeof DataView !== "undefined" && obj instanceof DataView) {
|
|
@@ -1093,6 +1109,37 @@ class Task {
|
|
|
1093
1109
|
const finalOutputSchema = outputSchema ?? this.outputSchema();
|
|
1094
1110
|
this.emit("schemaChange", finalInputSchema, finalOutputSchema);
|
|
1095
1111
|
}
|
|
1112
|
+
static _configSchemaNode = new Map;
|
|
1113
|
+
static getConfigSchemaNode(type) {
|
|
1114
|
+
const schema = this.configSchema();
|
|
1115
|
+
if (!schema)
|
|
1116
|
+
return;
|
|
1117
|
+
if (!this._configSchemaNode.has(type)) {
|
|
1118
|
+
try {
|
|
1119
|
+
const schemaNode = typeof schema === "boolean" ? compileSchema(schema ? {} : { not: {} }) : compileSchema(schema);
|
|
1120
|
+
this._configSchemaNode.set(type, schemaNode);
|
|
1121
|
+
} catch (error) {
|
|
1122
|
+
console.warn(`Failed to compile config schema for ${this.type}:`, error);
|
|
1123
|
+
return;
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
return this._configSchemaNode.get(type);
|
|
1127
|
+
}
|
|
1128
|
+
validateAndApplyConfigDefaults(config) {
|
|
1129
|
+
const ctor = this.constructor;
|
|
1130
|
+
const schemaNode = ctor.getConfigSchemaNode(this.type);
|
|
1131
|
+
if (!schemaNode)
|
|
1132
|
+
return config;
|
|
1133
|
+
const result = schemaNode.validate(config);
|
|
1134
|
+
if (!result.valid) {
|
|
1135
|
+
const errorMessages = result.errors.map((e) => {
|
|
1136
|
+
const path = e.data?.pointer || "";
|
|
1137
|
+
return `${e.message}${path ? ` (${path})` : ""}`;
|
|
1138
|
+
});
|
|
1139
|
+
throw new TaskConfigurationError(`[${ctor.name}] Configuration Error: ${errorMessages.join(", ")}`);
|
|
1140
|
+
}
|
|
1141
|
+
return config;
|
|
1142
|
+
}
|
|
1096
1143
|
static _inputSchemaNode = new Map;
|
|
1097
1144
|
static generateInputSchemaNode(schema) {
|
|
1098
1145
|
if (typeof schema === "boolean") {
|
|
@@ -1157,12 +1204,16 @@ class Task {
|
|
|
1157
1204
|
}
|
|
1158
1205
|
toJSON() {
|
|
1159
1206
|
const extras = this.config.extras;
|
|
1160
|
-
|
|
1207
|
+
const json = this.stripSymbols({
|
|
1161
1208
|
id: this.config.id,
|
|
1162
1209
|
type: this.type,
|
|
1163
|
-
...this.config.name ? { name: this.config.name } : {},
|
|
1164
1210
|
defaults: this.defaults,
|
|
1165
|
-
|
|
1211
|
+
config: {
|
|
1212
|
+
...this.config.title ? { title: this.config.title } : {},
|
|
1213
|
+
...this.config.inputSchema ? { inputSchema: this.config.inputSchema } : {},
|
|
1214
|
+
...this.config.outputSchema ? { outputSchema: this.config.outputSchema } : {},
|
|
1215
|
+
...extras && Object.keys(extras).length ? { extras } : {}
|
|
1216
|
+
}
|
|
1166
1217
|
});
|
|
1167
1218
|
return json;
|
|
1168
1219
|
}
|
|
@@ -1205,12 +1256,27 @@ class Task {
|
|
|
1205
1256
|
}
|
|
1206
1257
|
|
|
1207
1258
|
// src/task/ConditionalTask.ts
|
|
1259
|
+
var conditionalTaskConfigSchema = {
|
|
1260
|
+
type: "object",
|
|
1261
|
+
properties: {
|
|
1262
|
+
...TaskConfigSchema["properties"],
|
|
1263
|
+
branches: { type: "array", items: {} },
|
|
1264
|
+
defaultBranch: { type: "string" },
|
|
1265
|
+
exclusive: { type: "boolean" },
|
|
1266
|
+
conditionConfig: { type: "object", additionalProperties: true }
|
|
1267
|
+
},
|
|
1268
|
+
additionalProperties: false
|
|
1269
|
+
};
|
|
1270
|
+
|
|
1208
1271
|
class ConditionalTask extends Task {
|
|
1209
1272
|
static type = "ConditionalTask";
|
|
1210
1273
|
static category = "Flow Control";
|
|
1211
1274
|
static title = "Condition";
|
|
1212
1275
|
static description = "Route data based on conditions";
|
|
1213
1276
|
static hasDynamicSchemas = true;
|
|
1277
|
+
static configSchema() {
|
|
1278
|
+
return conditionalTaskConfigSchema;
|
|
1279
|
+
}
|
|
1214
1280
|
activeBranches = new Set;
|
|
1215
1281
|
buildBranchesFromConditionConfig(conditionConfig) {
|
|
1216
1282
|
if (!conditionConfig?.branches || conditionConfig.branches.length === 0) {
|
|
@@ -1241,7 +1307,7 @@ class ConditionalTask extends Task {
|
|
|
1241
1307
|
fromConditionConfig: false
|
|
1242
1308
|
};
|
|
1243
1309
|
}
|
|
1244
|
-
const conditionConfig = input.conditionConfig ?? this.config.
|
|
1310
|
+
const conditionConfig = input.conditionConfig ?? this.config.conditionConfig;
|
|
1245
1311
|
if (conditionConfig) {
|
|
1246
1312
|
return {
|
|
1247
1313
|
branches: this.buildBranchesFromConditionConfig(conditionConfig),
|
|
@@ -1552,6 +1618,7 @@ class TaskGraphRunner {
|
|
|
1552
1618
|
reactiveRunning = false;
|
|
1553
1619
|
graph;
|
|
1554
1620
|
outputCache;
|
|
1621
|
+
accumulateLeafOutputs = true;
|
|
1555
1622
|
registry = globalServiceRegistry2;
|
|
1556
1623
|
abortController;
|
|
1557
1624
|
inProgressTasks = new Map;
|
|
@@ -1771,6 +1838,29 @@ class TaskGraphRunner {
|
|
|
1771
1838
|
}
|
|
1772
1839
|
}
|
|
1773
1840
|
}
|
|
1841
|
+
taskNeedsAccumulation(task) {
|
|
1842
|
+
if (this.outputCache)
|
|
1843
|
+
return true;
|
|
1844
|
+
const outEdges = this.graph.getTargetDataflows(task.config.id);
|
|
1845
|
+
if (outEdges.length === 0)
|
|
1846
|
+
return this.accumulateLeafOutputs;
|
|
1847
|
+
const outSchema = task.outputSchema();
|
|
1848
|
+
for (const df of outEdges) {
|
|
1849
|
+
if (df.sourceTaskPortId === DATAFLOW_ALL_PORTS) {
|
|
1850
|
+
if (getStreamingPorts(outSchema).length > 0)
|
|
1851
|
+
return true;
|
|
1852
|
+
continue;
|
|
1853
|
+
}
|
|
1854
|
+
const targetTask = this.graph.getTask(df.targetTaskId);
|
|
1855
|
+
if (!targetTask)
|
|
1856
|
+
continue;
|
|
1857
|
+
const inSchema = targetTask.inputSchema();
|
|
1858
|
+
if (edgeNeedsAccumulation(outSchema, df.sourceTaskPortId, inSchema, df.targetTaskPortId)) {
|
|
1859
|
+
return true;
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
return false;
|
|
1863
|
+
}
|
|
1774
1864
|
async runTask(task, input) {
|
|
1775
1865
|
const isStreamable = isTaskStreamable(task);
|
|
1776
1866
|
if (isStreamable) {
|
|
@@ -1793,7 +1883,7 @@ class TaskGraphRunner {
|
|
|
1793
1883
|
return this.runStreamingTask(task, input);
|
|
1794
1884
|
}
|
|
1795
1885
|
const results = await task.runner.run(input, {
|
|
1796
|
-
outputCache: this.outputCache,
|
|
1886
|
+
outputCache: this.outputCache ?? false,
|
|
1797
1887
|
updateProgress: async (task2, progress, message, ...args) => await this.handleProgress(task2, progress, message, ...args),
|
|
1798
1888
|
registry: this.registry
|
|
1799
1889
|
});
|
|
@@ -1813,6 +1903,7 @@ class TaskGraphRunner {
|
|
|
1813
1903
|
}
|
|
1814
1904
|
async runStreamingTask(task, input) {
|
|
1815
1905
|
const streamMode = getOutputStreamMode(task.outputSchema());
|
|
1906
|
+
const shouldAccumulate = this.taskNeedsAccumulation(task);
|
|
1816
1907
|
let streamingNotified = false;
|
|
1817
1908
|
const onStatus = (status) => {
|
|
1818
1909
|
if (status === TaskStatus.STREAMING && !streamingNotified) {
|
|
@@ -1837,7 +1928,8 @@ class TaskGraphRunner {
|
|
|
1837
1928
|
task.on("stream_end", onStreamEnd);
|
|
1838
1929
|
try {
|
|
1839
1930
|
const results = await task.runner.run(input, {
|
|
1840
|
-
outputCache: this.outputCache,
|
|
1931
|
+
outputCache: this.outputCache ?? false,
|
|
1932
|
+
shouldAccumulate,
|
|
1841
1933
|
updateProgress: async (task2, progress, message, ...args) => await this.handleProgress(task2, progress, message, ...args),
|
|
1842
1934
|
registry: this.registry
|
|
1843
1935
|
});
|
|
@@ -1919,9 +2011,7 @@ class TaskGraphRunner {
|
|
|
1919
2011
|
task.runOutputData = {};
|
|
1920
2012
|
task.error = undefined;
|
|
1921
2013
|
task.progress = 0;
|
|
1922
|
-
|
|
1923
|
-
task.config.runnerId = runId;
|
|
1924
|
-
}
|
|
2014
|
+
task.runConfig = { ...task.runConfig, runnerId: runId };
|
|
1925
2015
|
this.pushStatusFromNodeToEdges(graph, task);
|
|
1926
2016
|
this.pushErrorFromNodeToEdges(graph, task);
|
|
1927
2017
|
task.emit("reset");
|
|
@@ -1945,6 +2035,7 @@ class TaskGraphRunner {
|
|
|
1945
2035
|
} else {
|
|
1946
2036
|
this.registry = new ServiceRegistry2(globalServiceRegistry2.container.createChildContainer());
|
|
1947
2037
|
}
|
|
2038
|
+
this.accumulateLeafOutputs = config?.accumulateLeafOutputs !== false;
|
|
1948
2039
|
if (config?.outputCache !== undefined) {
|
|
1949
2040
|
if (typeof config.outputCache === "boolean") {
|
|
1950
2041
|
if (config.outputCache === true) {
|
|
@@ -2084,6 +2175,15 @@ class GraphAsTaskRunner extends TaskRunner {
|
|
|
2084
2175
|
}
|
|
2085
2176
|
|
|
2086
2177
|
// src/task/GraphAsTask.ts
|
|
2178
|
+
var graphAsTaskConfigSchema = {
|
|
2179
|
+
type: "object",
|
|
2180
|
+
properties: {
|
|
2181
|
+
...TaskConfigSchema["properties"],
|
|
2182
|
+
compoundMerge: { type: "string" }
|
|
2183
|
+
},
|
|
2184
|
+
additionalProperties: false
|
|
2185
|
+
};
|
|
2186
|
+
|
|
2087
2187
|
class GraphAsTask extends Task {
|
|
2088
2188
|
static type = "GraphAsTask";
|
|
2089
2189
|
static title = "Group";
|
|
@@ -2105,11 +2205,14 @@ class GraphAsTask extends Task {
|
|
|
2105
2205
|
}
|
|
2106
2206
|
return this._runner;
|
|
2107
2207
|
}
|
|
2208
|
+
static configSchema() {
|
|
2209
|
+
return graphAsTaskConfigSchema;
|
|
2210
|
+
}
|
|
2108
2211
|
get compoundMerge() {
|
|
2109
2212
|
return this.config?.compoundMerge || this.constructor.compoundMerge;
|
|
2110
2213
|
}
|
|
2111
2214
|
get cacheable() {
|
|
2112
|
-
return this.config?.cacheable ?? (this.constructor.cacheable && !this.hasChildren());
|
|
2215
|
+
return this.runConfig?.cacheable ?? this.config?.cacheable ?? (this.constructor.cacheable && !this.hasChildren());
|
|
2113
2216
|
}
|
|
2114
2217
|
inputSchema() {
|
|
2115
2218
|
if (!this.hasChildren()) {
|
|
@@ -2276,7 +2379,7 @@ class GraphAsTask extends Task {
|
|
|
2276
2379
|
}
|
|
2277
2380
|
}
|
|
2278
2381
|
});
|
|
2279
|
-
const runPromise = this.subGraph.run(input, { parentSignal: context.signal }).then((results2) => {
|
|
2382
|
+
const runPromise = this.subGraph.run(input, { parentSignal: context.signal, accumulateLeafOutputs: false }).then((results2) => {
|
|
2280
2383
|
subgraphDone = true;
|
|
2281
2384
|
resolveWaiting?.();
|
|
2282
2385
|
return results2;
|
|
@@ -2986,17 +3089,19 @@ function ensureTask(arg, config = {}) {
|
|
|
2986
3089
|
return arg;
|
|
2987
3090
|
}
|
|
2988
3091
|
if (arg instanceof TaskGraph) {
|
|
2989
|
-
|
|
2990
|
-
|
|
3092
|
+
const { isOwned, ...cleanConfig } = config;
|
|
3093
|
+
if (isOwned) {
|
|
3094
|
+
return new OwnGraphTask({}, { ...cleanConfig, subGraph: arg });
|
|
2991
3095
|
} else {
|
|
2992
|
-
return new GraphTask({}, { ...
|
|
3096
|
+
return new GraphTask({}, { ...cleanConfig, subGraph: arg });
|
|
2993
3097
|
}
|
|
2994
3098
|
}
|
|
2995
3099
|
if (arg instanceof Workflow) {
|
|
2996
|
-
|
|
2997
|
-
|
|
3100
|
+
const { isOwned, ...cleanConfig } = config;
|
|
3101
|
+
if (isOwned) {
|
|
3102
|
+
return new OwnWorkflowTask({}, { ...cleanConfig, subGraph: arg.graph });
|
|
2998
3103
|
} else {
|
|
2999
|
-
return new WorkflowTask2({}, { ...
|
|
3104
|
+
return new WorkflowTask2({}, { ...cleanConfig, subGraph: arg.graph });
|
|
3000
3105
|
}
|
|
3001
3106
|
}
|
|
3002
3107
|
return convertPipeFunctionToTask(arg, config);
|
|
@@ -3083,7 +3188,8 @@ class TaskGraph {
|
|
|
3083
3188
|
run(input = {}, config = {}) {
|
|
3084
3189
|
return this.runner.runGraph(input, {
|
|
3085
3190
|
outputCache: config?.outputCache || this.outputCache,
|
|
3086
|
-
parentSignal: config?.parentSignal || undefined
|
|
3191
|
+
parentSignal: config?.parentSignal || undefined,
|
|
3192
|
+
accumulateLeafOutputs: config?.accumulateLeafOutputs
|
|
3087
3193
|
});
|
|
3088
3194
|
}
|
|
3089
3195
|
runReactive(input = {}) {
|
|
@@ -3472,6 +3578,16 @@ var ITERATOR_CONTEXT_SCHEMA = {
|
|
|
3472
3578
|
}
|
|
3473
3579
|
}
|
|
3474
3580
|
};
|
|
3581
|
+
var iteratorTaskConfigSchema = {
|
|
3582
|
+
type: "object",
|
|
3583
|
+
properties: {
|
|
3584
|
+
...graphAsTaskConfigSchema["properties"],
|
|
3585
|
+
concurrencyLimit: { type: "integer", minimum: 1 },
|
|
3586
|
+
batchSize: { type: "integer", minimum: 1 },
|
|
3587
|
+
iterationInputConfig: { type: "object", additionalProperties: true }
|
|
3588
|
+
},
|
|
3589
|
+
additionalProperties: false
|
|
3590
|
+
};
|
|
3475
3591
|
function isArrayVariant(schema) {
|
|
3476
3592
|
if (!schema || typeof schema !== "object")
|
|
3477
3593
|
return false;
|
|
@@ -3580,6 +3696,9 @@ class IteratorTask extends GraphAsTask {
|
|
|
3580
3696
|
static title = "Iterator";
|
|
3581
3697
|
static description = "Base class for loop-type tasks";
|
|
3582
3698
|
static hasDynamicSchemas = true;
|
|
3699
|
+
static configSchema() {
|
|
3700
|
+
return iteratorTaskConfigSchema;
|
|
3701
|
+
}
|
|
3583
3702
|
static getIterationContextSchema() {
|
|
3584
3703
|
return ITERATOR_CONTEXT_SCHEMA;
|
|
3585
3704
|
}
|
|
@@ -3940,6 +4059,20 @@ var WHILE_CONTEXT_SCHEMA = {
|
|
|
3940
4059
|
}
|
|
3941
4060
|
}
|
|
3942
4061
|
};
|
|
4062
|
+
var whileTaskConfigSchema = {
|
|
4063
|
+
type: "object",
|
|
4064
|
+
properties: {
|
|
4065
|
+
...graphAsTaskConfigSchema["properties"],
|
|
4066
|
+
condition: {},
|
|
4067
|
+
maxIterations: { type: "integer", minimum: 1 },
|
|
4068
|
+
chainIterations: { type: "boolean" },
|
|
4069
|
+
conditionField: { type: "string" },
|
|
4070
|
+
conditionOperator: { type: "string" },
|
|
4071
|
+
conditionValue: { type: "string" },
|
|
4072
|
+
iterationInputConfig: { type: "object", additionalProperties: true }
|
|
4073
|
+
},
|
|
4074
|
+
additionalProperties: false
|
|
4075
|
+
};
|
|
3943
4076
|
|
|
3944
4077
|
class WhileTask extends GraphAsTask {
|
|
3945
4078
|
static type = "WhileTask";
|
|
@@ -3947,6 +4080,9 @@ class WhileTask extends GraphAsTask {
|
|
|
3947
4080
|
static title = "While Loop";
|
|
3948
4081
|
static description = "Loops until a condition function returns false";
|
|
3949
4082
|
static hasDynamicSchemas = true;
|
|
4083
|
+
static configSchema() {
|
|
4084
|
+
return whileTaskConfigSchema;
|
|
4085
|
+
}
|
|
3950
4086
|
static getIterationContextSchema() {
|
|
3951
4087
|
return WHILE_CONTEXT_SCHEMA;
|
|
3952
4088
|
}
|
|
@@ -3964,38 +4100,30 @@ class WhileTask extends GraphAsTask {
|
|
|
3964
4100
|
return this.config.condition;
|
|
3965
4101
|
}
|
|
3966
4102
|
get maxIterations() {
|
|
3967
|
-
|
|
3968
|
-
return this.config.maxIterations;
|
|
3969
|
-
const wc = this.config.extras?.whileConfig;
|
|
3970
|
-
return wc?.maxIterations ?? 100;
|
|
4103
|
+
return this.config.maxIterations ?? 100;
|
|
3971
4104
|
}
|
|
3972
4105
|
get chainIterations() {
|
|
3973
|
-
|
|
3974
|
-
return this.config.chainIterations;
|
|
3975
|
-
const wc = this.config.extras?.whileConfig;
|
|
3976
|
-
return wc?.chainIterations ?? true;
|
|
4106
|
+
return this.config.chainIterations ?? true;
|
|
3977
4107
|
}
|
|
3978
4108
|
get currentIteration() {
|
|
3979
4109
|
return this._currentIteration;
|
|
3980
4110
|
}
|
|
3981
|
-
|
|
3982
|
-
const
|
|
3983
|
-
if (!
|
|
4111
|
+
buildConditionFromConfig() {
|
|
4112
|
+
const { conditionOperator, conditionField, conditionValue } = this.config;
|
|
4113
|
+
if (!conditionOperator) {
|
|
3984
4114
|
return;
|
|
3985
4115
|
}
|
|
3986
|
-
const { conditionField, conditionOperator, conditionValue } = wc;
|
|
3987
4116
|
return (output) => {
|
|
3988
4117
|
const fieldValue = conditionField ? getNestedValue(output, conditionField) : output;
|
|
3989
4118
|
return evaluateCondition(fieldValue, conditionOperator, conditionValue ?? "");
|
|
3990
4119
|
};
|
|
3991
4120
|
}
|
|
3992
4121
|
analyzeArrayInputs(input) {
|
|
3993
|
-
|
|
3994
|
-
if (!wc?.iterationInputConfig) {
|
|
4122
|
+
if (!this.config.iterationInputConfig) {
|
|
3995
4123
|
return null;
|
|
3996
4124
|
}
|
|
3997
4125
|
const inputData = input;
|
|
3998
|
-
const config =
|
|
4126
|
+
const config = this.config.iterationInputConfig;
|
|
3999
4127
|
const arrayPorts = [];
|
|
4000
4128
|
const scalarPorts = [];
|
|
4001
4129
|
const iteratedValues = {};
|
|
@@ -4051,7 +4179,7 @@ class WhileTask extends GraphAsTask {
|
|
|
4051
4179
|
if (!this.hasChildren()) {
|
|
4052
4180
|
throw new TaskConfigurationError(`${this.type}: No subgraph set for while loop`);
|
|
4053
4181
|
}
|
|
4054
|
-
const condition = this.condition ?? this.
|
|
4182
|
+
const condition = this.condition ?? this.buildConditionFromConfig();
|
|
4055
4183
|
if (!condition) {
|
|
4056
4184
|
throw new TaskConfigurationError(`${this.type}: No condition function provided`);
|
|
4057
4185
|
}
|
|
@@ -4096,7 +4224,7 @@ class WhileTask extends GraphAsTask {
|
|
|
4096
4224
|
if (!this.hasChildren()) {
|
|
4097
4225
|
throw new TaskConfigurationError(`${this.type}: No subgraph set for while loop`);
|
|
4098
4226
|
}
|
|
4099
|
-
const condition = this.condition ?? this.
|
|
4227
|
+
const condition = this.condition ?? this.buildConditionFromConfig();
|
|
4100
4228
|
if (!condition) {
|
|
4101
4229
|
throw new TaskConfigurationError(`${this.type}: No condition function provided`);
|
|
4102
4230
|
}
|
|
@@ -4166,12 +4294,11 @@ class WhileTask extends GraphAsTask {
|
|
|
4166
4294
|
const baseSchema = super.inputSchema();
|
|
4167
4295
|
if (typeof baseSchema === "boolean")
|
|
4168
4296
|
return baseSchema;
|
|
4169
|
-
|
|
4170
|
-
if (!wc?.iterationInputConfig) {
|
|
4297
|
+
if (!this.config.iterationInputConfig) {
|
|
4171
4298
|
return baseSchema;
|
|
4172
4299
|
}
|
|
4173
4300
|
const properties = { ...baseSchema.properties || {} };
|
|
4174
|
-
for (const [key, propConfig] of Object.entries(
|
|
4301
|
+
for (const [key, propConfig] of Object.entries(this.config.iterationInputConfig)) {
|
|
4175
4302
|
if (propConfig.mode === "array" && properties[key]) {
|
|
4176
4303
|
const scalarSchema = properties[key];
|
|
4177
4304
|
properties[key] = {
|
|
@@ -4580,9 +4707,21 @@ function setTaskQueueRegistry(registry) {
|
|
|
4580
4707
|
}
|
|
4581
4708
|
|
|
4582
4709
|
// src/task/JobQueueTask.ts
|
|
4710
|
+
var jobQueueTaskConfigSchema = {
|
|
4711
|
+
type: "object",
|
|
4712
|
+
properties: {
|
|
4713
|
+
...graphAsTaskConfigSchema["properties"],
|
|
4714
|
+
queue: {}
|
|
4715
|
+
},
|
|
4716
|
+
additionalProperties: false
|
|
4717
|
+
};
|
|
4718
|
+
|
|
4583
4719
|
class JobQueueTask extends GraphAsTask {
|
|
4584
4720
|
static type = "JobQueueTask";
|
|
4585
4721
|
static canRunDirectly = true;
|
|
4722
|
+
static configSchema() {
|
|
4723
|
+
return jobQueueTaskConfigSchema;
|
|
4724
|
+
}
|
|
4586
4725
|
currentQueueName;
|
|
4587
4726
|
currentJobId;
|
|
4588
4727
|
currentRunnerId;
|
|
@@ -4713,11 +4852,24 @@ class JobQueueTask extends GraphAsTask {
|
|
|
4713
4852
|
}
|
|
4714
4853
|
}
|
|
4715
4854
|
// src/task/MapTask.ts
|
|
4855
|
+
var mapTaskConfigSchema = {
|
|
4856
|
+
type: "object",
|
|
4857
|
+
properties: {
|
|
4858
|
+
...iteratorTaskConfigSchema["properties"],
|
|
4859
|
+
preserveOrder: { type: "boolean" },
|
|
4860
|
+
flatten: { type: "boolean" }
|
|
4861
|
+
},
|
|
4862
|
+
additionalProperties: false
|
|
4863
|
+
};
|
|
4864
|
+
|
|
4716
4865
|
class MapTask extends IteratorTask {
|
|
4717
4866
|
static type = "MapTask";
|
|
4718
4867
|
static category = "Flow Control";
|
|
4719
4868
|
static title = "Map";
|
|
4720
4869
|
static description = "Transforms array inputs by running a workflow per item";
|
|
4870
|
+
static configSchema() {
|
|
4871
|
+
return mapTaskConfigSchema;
|
|
4872
|
+
}
|
|
4721
4873
|
static compoundMerge = PROPERTY_ARRAY;
|
|
4722
4874
|
static inputSchema() {
|
|
4723
4875
|
return {
|
|
@@ -4780,11 +4932,23 @@ queueMicrotask(() => {
|
|
|
4780
4932
|
Workflow.prototype.endMap = CreateEndLoopWorkflow("endMap");
|
|
4781
4933
|
});
|
|
4782
4934
|
// src/task/ReduceTask.ts
|
|
4935
|
+
var reduceTaskConfigSchema = {
|
|
4936
|
+
type: "object",
|
|
4937
|
+
properties: {
|
|
4938
|
+
...iteratorTaskConfigSchema["properties"],
|
|
4939
|
+
initialValue: {}
|
|
4940
|
+
},
|
|
4941
|
+
additionalProperties: false
|
|
4942
|
+
};
|
|
4943
|
+
|
|
4783
4944
|
class ReduceTask extends IteratorTask {
|
|
4784
4945
|
static type = "ReduceTask";
|
|
4785
4946
|
static category = "Flow Control";
|
|
4786
4947
|
static title = "Reduce";
|
|
4787
4948
|
static description = "Processes iterated inputs sequentially with an accumulator (fold)";
|
|
4949
|
+
static configSchema() {
|
|
4950
|
+
return reduceTaskConfigSchema;
|
|
4951
|
+
}
|
|
4788
4952
|
constructor(input = {}, config = {}) {
|
|
4789
4953
|
const reduceConfig = {
|
|
4790
4954
|
...config,
|
|
@@ -4884,9 +5048,8 @@ var createSingleTaskFromJSON = (item) => {
|
|
|
4884
5048
|
if (!taskClass)
|
|
4885
5049
|
throw new TaskJSONError(`Task type ${item.type} not found, perhaps not registered?`);
|
|
4886
5050
|
const taskConfig = {
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
extras: item.extras
|
|
5051
|
+
...item.config,
|
|
5052
|
+
id: item.id
|
|
4890
5053
|
};
|
|
4891
5054
|
const task = new taskClass(item.defaults ?? {}, taskConfig);
|
|
4892
5055
|
return task;
|
|
@@ -5092,6 +5255,7 @@ class TaskOutputTabularRepository extends TaskOutputRepository {
|
|
|
5092
5255
|
}
|
|
5093
5256
|
export {
|
|
5094
5257
|
wrapSchemaInArray,
|
|
5258
|
+
whileTaskConfigSchema,
|
|
5095
5259
|
setTaskQueueRegistry,
|
|
5096
5260
|
serialGraph,
|
|
5097
5261
|
schemaAcceptsArray,
|
|
@@ -5099,15 +5263,20 @@ export {
|
|
|
5099
5263
|
removeIterationProperties,
|
|
5100
5264
|
registerJobQueueFactory,
|
|
5101
5265
|
registerBaseTasks,
|
|
5266
|
+
reduceTaskConfigSchema,
|
|
5102
5267
|
pipe,
|
|
5103
5268
|
parallel,
|
|
5104
5269
|
mergeChainedOutputToInput,
|
|
5270
|
+
mapTaskConfigSchema,
|
|
5271
|
+
jobQueueTaskConfigSchema,
|
|
5272
|
+
iteratorTaskConfigSchema,
|
|
5105
5273
|
isTaskStreamable,
|
|
5106
5274
|
isStrictArraySchema,
|
|
5107
5275
|
isIterationProperty,
|
|
5108
5276
|
isFlexibleSchema,
|
|
5109
5277
|
hasVectorOutput,
|
|
5110
5278
|
hasVectorLikeInput,
|
|
5279
|
+
graphAsTaskConfigSchema,
|
|
5111
5280
|
getTaskQueueRegistry,
|
|
5112
5281
|
getStreamingPorts,
|
|
5113
5282
|
getPortStreamMode,
|
|
@@ -5133,6 +5302,7 @@ export {
|
|
|
5133
5302
|
createFlexibleSchema,
|
|
5134
5303
|
createArraySchema,
|
|
5135
5304
|
connect,
|
|
5305
|
+
conditionalTaskConfigSchema,
|
|
5136
5306
|
buildIterationInputSchema,
|
|
5137
5307
|
addIterationContextToSchema,
|
|
5138
5308
|
WorkflowError,
|
|
@@ -5158,6 +5328,7 @@ export {
|
|
|
5158
5328
|
TaskFailedError,
|
|
5159
5329
|
TaskError,
|
|
5160
5330
|
TaskConfigurationError,
|
|
5331
|
+
TaskConfigSchema,
|
|
5161
5332
|
TaskAbortedError,
|
|
5162
5333
|
Task,
|
|
5163
5334
|
TASK_OUTPUT_REPOSITORY,
|
|
@@ -5187,4 +5358,4 @@ export {
|
|
|
5187
5358
|
ConditionalTask
|
|
5188
5359
|
};
|
|
5189
5360
|
|
|
5190
|
-
//# debugId=
|
|
5361
|
+
//# debugId=365A916C098B8CB464756E2164756E21
|