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