@workglow/task-graph 0.0.87 → 0.0.89

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 CHANGED
@@ -1,54 +1,19 @@
1
- var __defProp = Object.defineProperty;
2
- var __getOwnPropNames = Object.getOwnPropertyNames;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __hasOwnProp = Object.prototype.hasOwnProperty;
5
- var __moduleCache = /* @__PURE__ */ new WeakMap;
6
- var __toCommonJS = (from) => {
7
- var entry = __moduleCache.get(from), desc;
8
- if (entry)
9
- return entry;
10
- entry = __defProp({}, "__esModule", { value: true });
11
- if (from && typeof from === "object" || typeof from === "function")
12
- __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
13
- get: () => from[key],
14
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
- }));
16
- __moduleCache.set(from, entry);
17
- return entry;
18
- };
19
- var __export = (target, all) => {
20
- for (var name in all)
21
- __defProp(target, name, {
22
- get: all[name],
23
- enumerable: true,
24
- configurable: true,
25
- set: (newValue) => all[name] = () => newValue
26
- });
27
- };
28
- var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
1
+ // src/task-graph/Dataflow.ts
2
+ import { areSemanticallyCompatible, EventEmitter } from "@workglow/util";
29
3
 
30
4
  // src/task/TaskTypes.ts
31
- var TaskStatus;
32
- var init_TaskTypes = __esm(() => {
33
- TaskStatus = {
34
- PENDING: "PENDING",
35
- DISABLED: "DISABLED",
36
- PROCESSING: "PROCESSING",
37
- COMPLETED: "COMPLETED",
38
- ABORTING: "ABORTING",
39
- FAILED: "FAILED"
40
- };
41
- });
5
+ var TaskStatus = {
6
+ PENDING: "PENDING",
7
+ DISABLED: "DISABLED",
8
+ PROCESSING: "PROCESSING",
9
+ COMPLETED: "COMPLETED",
10
+ ABORTING: "ABORTING",
11
+ FAILED: "FAILED"
12
+ };
42
13
 
43
14
  // src/task-graph/Dataflow.ts
44
- var exports_Dataflow = {};
45
- __export(exports_Dataflow, {
46
- DataflowArrow: () => DataflowArrow,
47
- Dataflow: () => Dataflow,
48
- DATAFLOW_ERROR_PORT: () => DATAFLOW_ERROR_PORT,
49
- DATAFLOW_ALL_PORTS: () => DATAFLOW_ALL_PORTS
50
- });
51
- import { areSemanticallyCompatible, EventEmitter } from "@workglow/util";
15
+ var DATAFLOW_ALL_PORTS = "*";
16
+ var DATAFLOW_ERROR_PORT = "[error]";
52
17
 
53
18
  class Dataflow {
54
19
  sourceTaskId;
@@ -183,30 +148,22 @@ class Dataflow {
183
148
  this._events?.emit(name, ...args);
184
149
  }
185
150
  }
186
- var DATAFLOW_ALL_PORTS = "*", DATAFLOW_ERROR_PORT = "[error]", DataflowArrow;
187
- var init_Dataflow = __esm(() => {
188
- init_TaskTypes();
189
- DataflowArrow = class DataflowArrow extends Dataflow {
190
- constructor(dataflow) {
191
- const pattern = /^([a-zA-Z0-9-]+?)\[([a-zA-Z0-9-]+?)\] ==> ([a-zA-Z0-9-]+?)\[([a-zA-Z0-9-]+?)\]$/;
192
- const match = dataflow.match(pattern);
193
- if (!match) {
194
- throw new Error(`Invalid dataflow format: ${dataflow}`);
195
- }
196
- const [, sourceTaskId, sourceTaskPortId, targetTaskId, targetTaskPortId] = match;
197
- super(sourceTaskId, sourceTaskPortId, targetTaskId, targetTaskPortId);
198
- }
199
- };
200
- });
201
-
202
- // src/common.ts
203
- init_Dataflow();
204
151
 
152
+ class DataflowArrow extends Dataflow {
153
+ constructor(dataflow) {
154
+ const pattern = /^([a-zA-Z0-9-]+?)\[([a-zA-Z0-9-]+?)\] ==> ([a-zA-Z0-9-]+?)\[([a-zA-Z0-9-]+?)\]$/;
155
+ const match = dataflow.match(pattern);
156
+ if (!match) {
157
+ throw new Error(`Invalid dataflow format: ${dataflow}`);
158
+ }
159
+ const [, sourceTaskId, sourceTaskPortId, targetTaskId, targetTaskPortId] = match;
160
+ super(sourceTaskId, sourceTaskPortId, targetTaskId, targetTaskPortId);
161
+ }
162
+ }
205
163
  // src/task-graph/TaskGraph.ts
206
- import { DirectedAcyclicGraph, EventEmitter as EventEmitter5, uuid4 as uuid44 } from "@workglow/util";
164
+ import { DirectedAcyclicGraph, EventEmitter as EventEmitter5, uuid4 as uuid43 } from "@workglow/util";
207
165
 
208
166
  // src/task/GraphAsTask.ts
209
- init_Dataflow();
210
167
  import { compileSchema as compileSchema2 } from "@workglow/util";
211
168
 
212
169
  // src/task-graph/TaskGraphRunner.ts
@@ -248,7 +205,6 @@ class TaskOutputRepository {
248
205
  }
249
206
 
250
207
  // src/task/Task.ts
251
- init_Dataflow();
252
208
  import {
253
209
  compileSchema,
254
210
  deepEqual,
@@ -375,8 +331,6 @@ async function resolveSchemaInputs(input, schema, config) {
375
331
  }
376
332
 
377
333
  // src/task/TaskRunner.ts
378
- init_TaskTypes();
379
-
380
334
  class TaskRunner {
381
335
  running = false;
382
336
  reactiveRunning = false;
@@ -569,8 +523,6 @@ class TaskRunner {
569
523
  }
570
524
 
571
525
  // src/task/Task.ts
572
- init_TaskTypes();
573
-
574
526
  class Task {
575
527
  static type = "Task";
576
528
  static category = "Hidden";
@@ -1069,13 +1021,7 @@ class ConditionalTask extends Task {
1069
1021
  }
1070
1022
  }
1071
1023
 
1072
- // src/task-graph/TaskGraphRunner.ts
1073
- init_TaskTypes();
1074
- init_Dataflow();
1075
-
1076
1024
  // src/task-graph/TaskGraphScheduler.ts
1077
- init_TaskTypes();
1078
-
1079
1025
  class TopologicalScheduler {
1080
1026
  dag;
1081
1027
  sortedNodes;
@@ -1255,16 +1201,18 @@ class TaskGraphRunner {
1255
1201
  await this.handleComplete();
1256
1202
  return results;
1257
1203
  }
1258
- async runGraphReactive() {
1204
+ async runGraphReactive(input = {}) {
1259
1205
  await this.handleStartReactive();
1260
1206
  const results = [];
1261
1207
  try {
1262
1208
  for await (const task of this.reactiveScheduler.tasks()) {
1209
+ const isRootTask = this.graph.getSourceDataflows(task.config.id).length === 0;
1263
1210
  if (task.status === TaskStatus.PENDING) {
1264
1211
  task.resetInputData();
1265
1212
  this.copyInputFromEdgesToNode(task);
1266
1213
  }
1267
- const taskResult = await task.runReactive();
1214
+ const taskInput = isRootTask ? input : {};
1215
+ const taskResult = await task.runReactive(taskInput);
1268
1216
  await this.pushOutputFromNodeToEdges(task, taskResult);
1269
1217
  if (this.graph.getTargetDataflows(task.config.id).length === 0) {
1270
1218
  results.push({
@@ -1565,7 +1513,7 @@ class GraphAsTaskRunner extends TaskRunner {
1565
1513
  return results;
1566
1514
  }
1567
1515
  async executeTaskChildrenReactive() {
1568
- return this.task.subGraph.runReactive();
1516
+ return this.task.subGraph.runReactive(this.task.runInputData);
1569
1517
  }
1570
1518
  async handleDisable() {
1571
1519
  if (this.task.hasChildren()) {
@@ -1779,70 +1727,35 @@ class GraphAsTask extends Task {
1779
1727
  }
1780
1728
  }
1781
1729
 
1782
- // src/task-graph/Conversions.ts
1783
- init_Dataflow();
1784
-
1785
1730
  // src/task-graph/Workflow.ts
1786
- import { EventEmitter as EventEmitter4, uuid4 as uuid43 } from "@workglow/util";
1787
- init_Dataflow();
1788
- function CreateWorkflow(taskClass) {
1789
- return Workflow.createWorkflow(taskClass);
1790
- }
1791
- function CreateLoopWorkflow(taskClass) {
1792
- return function(config = {}) {
1793
- const task = new taskClass({}, config);
1794
- this.graph.addTask(task);
1795
- const previousTask = getLastTask(this);
1796
- if (previousTask && previousTask !== task) {
1797
- this.graph.addDataflow(new Dataflow(previousTask.config.id, "*", task.config.id, "*"));
1798
- }
1799
- return new Workflow(this.outputCache(), this, task);
1800
- };
1801
- }
1802
- function CreateEndLoopWorkflow(methodName) {
1803
- return function() {
1804
- if (!this.isLoopBuilder) {
1805
- throw new Error(`${methodName}() can only be called on loop workflows`);
1806
- }
1807
- return this.finalizeAndReturn();
1808
- };
1809
- }
1810
-
1731
+ import { EventEmitter as EventEmitter4 } from "@workglow/util";
1811
1732
  class WorkflowTask extends GraphAsTask {
1812
1733
  static type = "Workflow";
1813
1734
  static compoundMerge = PROPERTY_ARRAY;
1814
1735
  }
1736
+ var taskIdCounter = 0;
1815
1737
 
1816
1738
  class Workflow {
1817
- constructor(cache, parent, iteratorTask) {
1818
- this._outputCache = cache;
1819
- this._parentWorkflow = parent;
1820
- this._iteratorTask = iteratorTask;
1821
- this._graph = new TaskGraph({ outputCache: this._outputCache });
1822
- if (!parent) {
1823
- this._onChanged = this._onChanged.bind(this);
1824
- this.setupEvents();
1825
- }
1739
+ constructor(repository) {
1740
+ this._repository = repository;
1741
+ this._graph = new TaskGraph({
1742
+ outputCache: this._repository
1743
+ });
1744
+ this._onChanged = this._onChanged.bind(this);
1745
+ this.setupEvents();
1826
1746
  }
1827
1747
  _graph;
1828
1748
  _dataFlows = [];
1829
1749
  _error = "";
1830
- _outputCache;
1750
+ _repository;
1831
1751
  _abortController;
1832
- _parentWorkflow;
1833
- _iteratorTask;
1834
- outputCache() {
1835
- return this._outputCache;
1836
- }
1837
- get isLoopBuilder() {
1838
- return this._parentWorkflow !== undefined;
1839
- }
1840
1752
  events = new EventEmitter4;
1841
1753
  static createWorkflow(taskClass) {
1842
1754
  const helper = function(input = {}, config = {}) {
1843
1755
  this._error = "";
1844
1756
  const parent = getLastTask(this);
1845
- const task = this.addTaskToGraph(taskClass, input, { id: uuid43(), ...config });
1757
+ taskIdCounter++;
1758
+ const task = this.addTask(taskClass, input, { id: String(taskIdCounter), ...config });
1846
1759
  if (this._dataFlows.length > 0) {
1847
1760
  this._dataFlows.forEach((dataflow) => {
1848
1761
  const taskSchema = task.inputSchema();
@@ -1857,23 +1770,158 @@ class Workflow {
1857
1770
  this._dataFlows = [];
1858
1771
  }
1859
1772
  if (parent && this.graph.getTargetDataflows(parent.config.id).length === 0) {
1860
- const nodes = this._graph.getTasks();
1861
- const parentIndex = nodes.findIndex((n) => n.config.id === parent.config.id);
1862
- const earlierTasks = [];
1863
- for (let i = parentIndex - 1;i >= 0; i--) {
1864
- earlierTasks.push(nodes[i]);
1865
- }
1866
- const providedInputKeys = new Set(Object.keys(input || {}));
1867
- const result = Workflow.autoConnect(this.graph, parent, task, {
1868
- providedInputKeys,
1869
- earlierTasks
1773
+ const matches = new Map;
1774
+ const sourceSchema = parent.outputSchema();
1775
+ const targetSchema = task.inputSchema();
1776
+ const makeMatch = (comparator) => {
1777
+ if (typeof sourceSchema === "object") {
1778
+ if (targetSchema === true || typeof targetSchema === "object" && targetSchema.additionalProperties === true) {
1779
+ for (const fromOutputPortId of Object.keys(sourceSchema.properties || {})) {
1780
+ matches.set(fromOutputPortId, fromOutputPortId);
1781
+ this.connect(parent.config.id, fromOutputPortId, task.config.id, fromOutputPortId);
1782
+ }
1783
+ return matches;
1784
+ }
1785
+ }
1786
+ if (typeof sourceSchema === "boolean" || typeof targetSchema === "boolean") {
1787
+ return matches;
1788
+ }
1789
+ for (const [fromOutputPortId, fromPortOutputSchema] of Object.entries(sourceSchema.properties || {})) {
1790
+ for (const [toInputPortId, toPortInputSchema] of Object.entries(targetSchema.properties || {})) {
1791
+ if (!matches.has(toInputPortId) && comparator([fromOutputPortId, fromPortOutputSchema], [toInputPortId, toPortInputSchema])) {
1792
+ matches.set(toInputPortId, fromOutputPortId);
1793
+ this.connect(parent.config.id, fromOutputPortId, task.config.id, toInputPortId);
1794
+ }
1795
+ }
1796
+ }
1797
+ return matches;
1798
+ };
1799
+ const getSpecificTypeIdentifiers = (schema) => {
1800
+ const formats = new Set;
1801
+ const ids = new Set;
1802
+ if (typeof schema === "boolean") {
1803
+ return { formats, ids };
1804
+ }
1805
+ const extractFromSchema = (s) => {
1806
+ if (!s || typeof s !== "object" || Array.isArray(s))
1807
+ return;
1808
+ if (s.format)
1809
+ formats.add(s.format);
1810
+ if (s.$id)
1811
+ ids.add(s.$id);
1812
+ };
1813
+ extractFromSchema(schema);
1814
+ const checkUnion = (schemas) => {
1815
+ if (!schemas)
1816
+ return;
1817
+ for (const s of schemas) {
1818
+ if (typeof s === "boolean")
1819
+ continue;
1820
+ extractFromSchema(s);
1821
+ if (s.items && typeof s.items === "object" && !Array.isArray(s.items)) {
1822
+ extractFromSchema(s.items);
1823
+ }
1824
+ }
1825
+ };
1826
+ checkUnion(schema.oneOf);
1827
+ checkUnion(schema.anyOf);
1828
+ if (schema.items && typeof schema.items === "object" && !Array.isArray(schema.items)) {
1829
+ extractFromSchema(schema.items);
1830
+ }
1831
+ return { formats, ids };
1832
+ };
1833
+ const isTypeCompatible = (fromPortOutputSchema, toPortInputSchema, requireSpecificType = false) => {
1834
+ if (typeof fromPortOutputSchema === "boolean" || typeof toPortInputSchema === "boolean") {
1835
+ return fromPortOutputSchema === true && toPortInputSchema === true;
1836
+ }
1837
+ const outputIds = getSpecificTypeIdentifiers(fromPortOutputSchema);
1838
+ const inputIds = getSpecificTypeIdentifiers(toPortInputSchema);
1839
+ for (const format of outputIds.formats) {
1840
+ if (inputIds.formats.has(format)) {
1841
+ return true;
1842
+ }
1843
+ }
1844
+ for (const id of outputIds.ids) {
1845
+ if (inputIds.ids.has(id)) {
1846
+ return true;
1847
+ }
1848
+ }
1849
+ if (requireSpecificType) {
1850
+ return false;
1851
+ }
1852
+ const idTypeBlank = fromPortOutputSchema.$id === undefined && toPortInputSchema.$id === undefined;
1853
+ if (!idTypeBlank)
1854
+ return false;
1855
+ if (fromPortOutputSchema.type === toPortInputSchema.type)
1856
+ return true;
1857
+ const matchesOneOf = toPortInputSchema.oneOf?.some((schema) => {
1858
+ if (typeof schema === "boolean")
1859
+ return schema;
1860
+ return schema.type === fromPortOutputSchema.type;
1861
+ }) ?? false;
1862
+ const matchesAnyOf = toPortInputSchema.anyOf?.some((schema) => {
1863
+ if (typeof schema === "boolean")
1864
+ return schema;
1865
+ return schema.type === fromPortOutputSchema.type;
1866
+ }) ?? false;
1867
+ return matchesOneOf || matchesAnyOf;
1868
+ };
1869
+ makeMatch(([fromOutputPortId, fromPortOutputSchema], [toInputPortId, toPortInputSchema]) => {
1870
+ const outputPortIdMatch = fromOutputPortId === toInputPortId;
1871
+ const outputPortIdOutputInput = fromOutputPortId === "output" && toInputPortId === "input";
1872
+ const portIdsCompatible = outputPortIdMatch || outputPortIdOutputInput;
1873
+ return portIdsCompatible && isTypeCompatible(fromPortOutputSchema, toPortInputSchema, false);
1870
1874
  });
1871
- if (result.error) {
1872
- if (this.isLoopBuilder) {
1873
- this._error = result.error;
1874
- console.warn(this._error);
1875
- } else {
1876
- this._error = result.error + " Task not added.";
1875
+ makeMatch(([_fromOutputPortId, fromPortOutputSchema], [_toInputPortId, toPortInputSchema]) => {
1876
+ return isTypeCompatible(fromPortOutputSchema, toPortInputSchema, true);
1877
+ });
1878
+ const requiredInputs = new Set(typeof targetSchema === "object" ? targetSchema.required || [] : []);
1879
+ const providedInputKeys = new Set(Object.keys(input || {}));
1880
+ const requiredInputsNeedingConnection = [...requiredInputs].filter((r) => !providedInputKeys.has(r));
1881
+ let unmatchedRequired = requiredInputsNeedingConnection.filter((r) => !matches.has(r));
1882
+ if (unmatchedRequired.length > 0) {
1883
+ const nodes = this._graph.getTasks();
1884
+ const parentIndex = nodes.findIndex((n) => n.config.id === parent.config.id);
1885
+ for (let i = parentIndex - 1;i >= 0 && unmatchedRequired.length > 0; i--) {
1886
+ const earlierTask = nodes[i];
1887
+ const earlierOutputSchema = earlierTask.outputSchema();
1888
+ const makeMatchFromEarlier = (comparator) => {
1889
+ if (typeof earlierOutputSchema === "boolean" || typeof targetSchema === "boolean") {
1890
+ return;
1891
+ }
1892
+ for (const [fromOutputPortId, fromPortOutputSchema] of Object.entries(earlierOutputSchema.properties || {})) {
1893
+ for (const requiredInputId of unmatchedRequired) {
1894
+ const toPortInputSchema = targetSchema.properties?.[requiredInputId];
1895
+ if (!matches.has(requiredInputId) && toPortInputSchema && comparator([fromOutputPortId, fromPortOutputSchema], [requiredInputId, toPortInputSchema])) {
1896
+ matches.set(requiredInputId, fromOutputPortId);
1897
+ this.connect(earlierTask.config.id, fromOutputPortId, task.config.id, requiredInputId);
1898
+ }
1899
+ }
1900
+ }
1901
+ };
1902
+ makeMatchFromEarlier(([fromOutputPortId, fromPortOutputSchema], [toInputPortId, toPortInputSchema]) => {
1903
+ const outputPortIdMatch = fromOutputPortId === toInputPortId;
1904
+ const outputPortIdOutputInput = fromOutputPortId === "output" && toInputPortId === "input";
1905
+ const portIdsCompatible = outputPortIdMatch || outputPortIdOutputInput;
1906
+ return portIdsCompatible && isTypeCompatible(fromPortOutputSchema, toPortInputSchema, false);
1907
+ });
1908
+ makeMatchFromEarlier(([_fromOutputPortId, fromPortOutputSchema], [_toInputPortId, toPortInputSchema]) => {
1909
+ return isTypeCompatible(fromPortOutputSchema, toPortInputSchema, true);
1910
+ });
1911
+ unmatchedRequired = unmatchedRequired.filter((r) => !matches.has(r));
1912
+ }
1913
+ }
1914
+ const stillUnmatchedRequired = requiredInputsNeedingConnection.filter((r) => !matches.has(r));
1915
+ if (stillUnmatchedRequired.length > 0) {
1916
+ this._error = `Could not find matches for required inputs [${stillUnmatchedRequired.join(", ")}] of ${task.type}. ` + `Attempted to match from ${parent.type} and earlier tasks. Task not added.`;
1917
+ console.error(this._error);
1918
+ this.graph.removeTask(task.config.id);
1919
+ } else if (matches.size === 0 && requiredInputsNeedingConnection.length === 0) {
1920
+ const hasRequiredInputs = requiredInputs.size > 0;
1921
+ const allRequiredInputsProvided = hasRequiredInputs && [...requiredInputs].every((r) => providedInputKeys.has(r));
1922
+ const hasInputsWithDefaults = typeof targetSchema === "object" && targetSchema.properties && Object.values(targetSchema.properties).some((prop) => prop && typeof prop === "object" && ("default" in prop));
1923
+ if (!allRequiredInputsProvided && !hasInputsWithDefaults) {
1924
+ this._error = `Could not find a match between the outputs of ${parent.type} and the inputs of ${task.type}. ` + `You now need to connect the outputs to the inputs via connect() manually before adding this task. Task not added.`;
1877
1925
  console.error(this._error);
1878
1926
  this.graph.removeTask(task.config.id);
1879
1927
  }
@@ -1916,16 +1964,12 @@ class Workflow {
1916
1964
  return this.events.waitOn(name);
1917
1965
  }
1918
1966
  async run(input = {}) {
1919
- if (this.isLoopBuilder) {
1920
- this.finalizeTemplate();
1921
- return this._parentWorkflow.run(input);
1922
- }
1923
1967
  this.events.emit("start");
1924
1968
  this._abortController = new AbortController;
1925
1969
  try {
1926
1970
  const output = await this.graph.run(input, {
1927
1971
  parentSignal: this._abortController.signal,
1928
- outputCache: this._outputCache
1972
+ outputCache: this._repository
1929
1973
  });
1930
1974
  const results = this.graph.mergeExecuteOutputsToRunOutput(output, PROPERTY_ARRAY);
1931
1975
  this.events.emit("complete");
@@ -1938,9 +1982,6 @@ class Workflow {
1938
1982
  }
1939
1983
  }
1940
1984
  async abort() {
1941
- if (this._parentWorkflow) {
1942
- return this._parentWorkflow.abort();
1943
- }
1944
1985
  this._abortController?.abort();
1945
1986
  }
1946
1987
  pop() {
@@ -2009,12 +2050,10 @@ class Workflow {
2009
2050
  return task;
2010
2051
  }
2011
2052
  reset() {
2012
- if (this._parentWorkflow) {
2013
- throw new WorkflowError("Cannot reset a loop workflow. Call reset() on the parent workflow.");
2014
- }
2053
+ taskIdCounter = 0;
2015
2054
  this.clearEvents();
2016
2055
  this._graph = new TaskGraph({
2017
- outputCache: this._outputCache
2056
+ outputCache: this._repository
2018
2057
  });
2019
2058
  this._dataFlows = [];
2020
2059
  this._error = "";
@@ -2069,194 +2108,15 @@ class Workflow {
2069
2108
  this.graph.addDataflow(dataflow);
2070
2109
  return this;
2071
2110
  }
2072
- addTaskToGraph(taskClass, input, config) {
2111
+ addTask(taskClass, input, config) {
2073
2112
  const task = new taskClass(input, config);
2074
2113
  const id = this.graph.addTask(task);
2075
2114
  this.events.emit("changed", id);
2076
2115
  return task;
2077
2116
  }
2078
- addTask(taskClass, input, config) {
2079
- const helper = Workflow.createWorkflow(taskClass);
2080
- return helper.call(this, input, config);
2081
- }
2082
- static AutoConnectOptions = Symbol("AutoConnectOptions");
2083
- static autoConnect(graph, sourceTask, targetTask, options) {
2084
- const matches = new Map;
2085
- const sourceSchema = sourceTask.outputSchema();
2086
- const targetSchema = targetTask.inputSchema();
2087
- const providedInputKeys = options?.providedInputKeys ?? new Set;
2088
- const earlierTasks = options?.earlierTasks ?? [];
2089
- const getSpecificTypeIdentifiers = (schema) => {
2090
- const formats = new Set;
2091
- const ids = new Set;
2092
- if (typeof schema === "boolean") {
2093
- return { formats, ids };
2094
- }
2095
- const extractFromSchema = (s) => {
2096
- if (!s || typeof s !== "object" || Array.isArray(s))
2097
- return;
2098
- if (s.format)
2099
- formats.add(s.format);
2100
- if (s.$id)
2101
- ids.add(s.$id);
2102
- };
2103
- extractFromSchema(schema);
2104
- const checkUnion = (schemas) => {
2105
- if (!schemas)
2106
- return;
2107
- for (const s of schemas) {
2108
- if (typeof s === "boolean")
2109
- continue;
2110
- extractFromSchema(s);
2111
- if (s.items && typeof s.items === "object" && !Array.isArray(s.items)) {
2112
- extractFromSchema(s.items);
2113
- }
2114
- }
2115
- };
2116
- checkUnion(schema.oneOf);
2117
- checkUnion(schema.anyOf);
2118
- if (schema.items && typeof schema.items === "object" && !Array.isArray(schema.items)) {
2119
- extractFromSchema(schema.items);
2120
- }
2121
- return { formats, ids };
2122
- };
2123
- const isTypeCompatible = (fromPortOutputSchema, toPortInputSchema, requireSpecificType = false) => {
2124
- if (typeof fromPortOutputSchema === "boolean" || typeof toPortInputSchema === "boolean") {
2125
- return fromPortOutputSchema === true && toPortInputSchema === true;
2126
- }
2127
- const outputIds = getSpecificTypeIdentifiers(fromPortOutputSchema);
2128
- const inputIds = getSpecificTypeIdentifiers(toPortInputSchema);
2129
- for (const format of outputIds.formats) {
2130
- if (inputIds.formats.has(format)) {
2131
- return true;
2132
- }
2133
- }
2134
- for (const id of outputIds.ids) {
2135
- if (inputIds.ids.has(id)) {
2136
- return true;
2137
- }
2138
- }
2139
- if (requireSpecificType) {
2140
- return false;
2141
- }
2142
- const idTypeBlank = fromPortOutputSchema.$id === undefined && toPortInputSchema.$id === undefined;
2143
- if (!idTypeBlank)
2144
- return false;
2145
- if (fromPortOutputSchema.type === toPortInputSchema.type)
2146
- return true;
2147
- const matchesOneOf = toPortInputSchema.oneOf?.some((schema) => {
2148
- if (typeof schema === "boolean")
2149
- return schema;
2150
- return schema.type === fromPortOutputSchema.type;
2151
- }) ?? false;
2152
- const matchesAnyOf = toPortInputSchema.anyOf?.some((schema) => {
2153
- if (typeof schema === "boolean")
2154
- return schema;
2155
- return schema.type === fromPortOutputSchema.type;
2156
- }) ?? false;
2157
- return matchesOneOf || matchesAnyOf;
2158
- };
2159
- const makeMatch = (fromSchema, toSchema, fromTaskId, toTaskId, comparator) => {
2160
- if (typeof fromSchema === "object") {
2161
- if (toSchema === true || typeof toSchema === "object" && toSchema.additionalProperties === true) {
2162
- for (const fromOutputPortId of Object.keys(fromSchema.properties || {})) {
2163
- matches.set(fromOutputPortId, fromOutputPortId);
2164
- graph.addDataflow(new Dataflow(fromTaskId, fromOutputPortId, toTaskId, fromOutputPortId));
2165
- }
2166
- return;
2167
- }
2168
- }
2169
- if (typeof fromSchema === "boolean" || typeof toSchema === "boolean") {
2170
- return;
2171
- }
2172
- for (const [fromOutputPortId, fromPortOutputSchema] of Object.entries(fromSchema.properties || {})) {
2173
- for (const [toInputPortId, toPortInputSchema] of Object.entries(toSchema.properties || {})) {
2174
- if (!matches.has(toInputPortId) && comparator([fromOutputPortId, fromPortOutputSchema], [toInputPortId, toPortInputSchema])) {
2175
- matches.set(toInputPortId, fromOutputPortId);
2176
- graph.addDataflow(new Dataflow(fromTaskId, fromOutputPortId, toTaskId, toInputPortId));
2177
- }
2178
- }
2179
- }
2180
- };
2181
- makeMatch(sourceSchema, targetSchema, sourceTask.config.id, targetTask.config.id, ([fromOutputPortId, fromPortOutputSchema], [toInputPortId, toPortInputSchema]) => {
2182
- const outputPortIdMatch = fromOutputPortId === toInputPortId;
2183
- const outputPortIdOutputInput = fromOutputPortId === "output" && toInputPortId === "input";
2184
- const portIdsCompatible = outputPortIdMatch || outputPortIdOutputInput;
2185
- return portIdsCompatible && isTypeCompatible(fromPortOutputSchema, toPortInputSchema, false);
2186
- });
2187
- makeMatch(sourceSchema, targetSchema, sourceTask.config.id, targetTask.config.id, ([_fromOutputPortId, fromPortOutputSchema], [_toInputPortId, toPortInputSchema]) => {
2188
- return isTypeCompatible(fromPortOutputSchema, toPortInputSchema, true);
2189
- });
2190
- const requiredInputs = new Set(typeof targetSchema === "object" ? targetSchema.required || [] : []);
2191
- const requiredInputsNeedingConnection = [...requiredInputs].filter((r) => !providedInputKeys.has(r));
2192
- let unmatchedRequired = requiredInputsNeedingConnection.filter((r) => !matches.has(r));
2193
- if (unmatchedRequired.length > 0 && earlierTasks.length > 0) {
2194
- for (let i = 0;i < earlierTasks.length && unmatchedRequired.length > 0; i++) {
2195
- const earlierTask = earlierTasks[i];
2196
- const earlierOutputSchema = earlierTask.outputSchema();
2197
- const makeMatchFromEarlier = (comparator) => {
2198
- if (typeof earlierOutputSchema === "boolean" || typeof targetSchema === "boolean") {
2199
- return;
2200
- }
2201
- for (const [fromOutputPortId, fromPortOutputSchema] of Object.entries(earlierOutputSchema.properties || {})) {
2202
- for (const requiredInputId of unmatchedRequired) {
2203
- const toPortInputSchema = targetSchema.properties?.[requiredInputId];
2204
- if (!matches.has(requiredInputId) && toPortInputSchema && comparator([fromOutputPortId, fromPortOutputSchema], [requiredInputId, toPortInputSchema])) {
2205
- matches.set(requiredInputId, fromOutputPortId);
2206
- graph.addDataflow(new Dataflow(earlierTask.config.id, fromOutputPortId, targetTask.config.id, requiredInputId));
2207
- }
2208
- }
2209
- }
2210
- };
2211
- makeMatchFromEarlier(([fromOutputPortId, fromPortOutputSchema], [toInputPortId, toPortInputSchema]) => {
2212
- const outputPortIdMatch = fromOutputPortId === toInputPortId;
2213
- const outputPortIdOutputInput = fromOutputPortId === "output" && toInputPortId === "input";
2214
- const portIdsCompatible = outputPortIdMatch || outputPortIdOutputInput;
2215
- return portIdsCompatible && isTypeCompatible(fromPortOutputSchema, toPortInputSchema, false);
2216
- });
2217
- makeMatchFromEarlier(([_fromOutputPortId, fromPortOutputSchema], [_toInputPortId, toPortInputSchema]) => {
2218
- return isTypeCompatible(fromPortOutputSchema, toPortInputSchema, true);
2219
- });
2220
- unmatchedRequired = unmatchedRequired.filter((r) => !matches.has(r));
2221
- }
2222
- }
2223
- const stillUnmatchedRequired = requiredInputsNeedingConnection.filter((r) => !matches.has(r));
2224
- if (stillUnmatchedRequired.length > 0) {
2225
- return {
2226
- matches,
2227
- error: `Could not find matches for required inputs [${stillUnmatchedRequired.join(", ")}] of ${targetTask.type}. ` + `Attempted to match from ${sourceTask.type} and earlier tasks.`,
2228
- unmatchedRequired: stillUnmatchedRequired
2229
- };
2230
- }
2231
- if (matches.size === 0 && requiredInputsNeedingConnection.length === 0) {
2232
- const hasRequiredInputs = requiredInputs.size > 0;
2233
- const allRequiredInputsProvided = hasRequiredInputs && [...requiredInputs].every((r) => providedInputKeys.has(r));
2234
- const hasInputsWithDefaults = typeof targetSchema === "object" && targetSchema.properties && Object.values(targetSchema.properties).some((prop) => prop && typeof prop === "object" && ("default" in prop));
2235
- if (!allRequiredInputsProvided && !hasInputsWithDefaults) {
2236
- return {
2237
- matches,
2238
- error: `Could not find a match between the outputs of ${sourceTask.type} and the inputs of ${targetTask.type}. ` + `You may need to connect the outputs to the inputs via connect() manually.`,
2239
- unmatchedRequired: []
2240
- };
2241
- }
2242
- }
2243
- return {
2244
- matches,
2245
- unmatchedRequired: []
2246
- };
2247
- }
2248
- finalizeTemplate() {
2249
- if (this._iteratorTask && this.graph.getTasks().length > 0) {
2250
- this._iteratorTask.setTemplateGraph(this.graph);
2251
- }
2252
- }
2253
- finalizeAndReturn() {
2254
- if (!this._parentWorkflow) {
2255
- throw new WorkflowError("finalizeAndReturn() can only be called on loop workflows");
2256
- }
2257
- this.finalizeTemplate();
2258
- return this._parentWorkflow;
2259
- }
2117
+ }
2118
+ function CreateWorkflow(taskClass) {
2119
+ return Workflow.createWorkflow(taskClass);
2260
2120
  }
2261
2121
 
2262
2122
  // src/task-graph/Conversions.ts
@@ -2379,9 +2239,6 @@ function parallel(args, mergeFn = PROPERTY_ARRAY, workflow = new Workflow) {
2379
2239
  return workflow;
2380
2240
  }
2381
2241
 
2382
- // src/task-graph/TaskGraph.ts
2383
- init_Dataflow();
2384
-
2385
2242
  // src/task-graph/TaskGraphEvents.ts
2386
2243
  var EventDagToTaskGraphMapping = {
2387
2244
  "node-added": "task_added",
@@ -2427,8 +2284,8 @@ class TaskGraph {
2427
2284
  parentSignal: config?.parentSignal || undefined
2428
2285
  });
2429
2286
  }
2430
- runReactive() {
2431
- return this.runner.runGraphReactive();
2287
+ runReactive(input = {}) {
2288
+ return this.runner.runGraphReactive(input);
2432
2289
  }
2433
2290
  mergeExecuteOutputsToRunOutput(results, compoundMerge) {
2434
2291
  return this.runner.mergeExecuteOutputsToRunOutput(results, compoundMerge);
@@ -2499,7 +2356,7 @@ class TaskGraph {
2499
2356
  return this._dag.removeNode(taskId);
2500
2357
  }
2501
2358
  resetGraph() {
2502
- this.runner.resetGraph(this, uuid44());
2359
+ this.runner.resetGraph(this, uuid43());
2503
2360
  }
2504
2361
  toJSON() {
2505
2362
  const tasks = this.getTasks().map((node) => node.toJSON());
@@ -2664,10 +2521,84 @@ function serialGraph(tasks, inputHandle, outputHandle) {
2664
2521
  graph.addDataflows(serialGraphEdges(tasks, inputHandle, outputHandle));
2665
2522
  return graph;
2666
2523
  }
2667
- // src/task/IteratorTaskRunner.ts
2668
- import { Job, JobQueueClient, JobQueueServer } from "@workglow/job-queue";
2524
+ // src/task/JobQueueFactory.ts
2525
+ import {
2526
+ JobQueueClient,
2527
+ JobQueueServer
2528
+ } from "@workglow/job-queue";
2669
2529
  import { InMemoryQueueStorage } from "@workglow/storage";
2670
- import { uuid4 as uuid45 } from "@workglow/util";
2530
+ import { createServiceToken as createServiceToken2, globalServiceRegistry as globalServiceRegistry3 } from "@workglow/util";
2531
+ var JOB_QUEUE_FACTORY = createServiceToken2("taskgraph.jobQueueFactory");
2532
+ var defaultJobQueueFactory = async ({
2533
+ queueName,
2534
+ jobClass,
2535
+ options
2536
+ }) => {
2537
+ const storage = options?.storage ?? new InMemoryQueueStorage(queueName);
2538
+ await storage.setupDatabase();
2539
+ const server = new JobQueueServer(jobClass, {
2540
+ storage,
2541
+ queueName,
2542
+ limiter: options?.limiter,
2543
+ workerCount: options?.workerCount,
2544
+ pollIntervalMs: options?.pollIntervalMs,
2545
+ deleteAfterCompletionMs: options?.deleteAfterCompletionMs,
2546
+ deleteAfterFailureMs: options?.deleteAfterFailureMs,
2547
+ deleteAfterDisabledMs: options?.deleteAfterDisabledMs,
2548
+ cleanupIntervalMs: options?.cleanupIntervalMs
2549
+ });
2550
+ const client = new JobQueueClient({
2551
+ storage,
2552
+ queueName
2553
+ });
2554
+ client.attach(server);
2555
+ return { server, client, storage };
2556
+ };
2557
+ function registerJobQueueFactory(factory) {
2558
+ globalServiceRegistry3.registerInstance(JOB_QUEUE_FACTORY, factory);
2559
+ }
2560
+ function createJobQueueFactoryWithOptions(defaultOptions = {}) {
2561
+ return async ({
2562
+ queueName,
2563
+ jobClass,
2564
+ options
2565
+ }) => {
2566
+ const mergedOptions = {
2567
+ ...defaultOptions,
2568
+ ...options ?? {}
2569
+ };
2570
+ const storage = mergedOptions.storage ?? new InMemoryQueueStorage(queueName);
2571
+ await storage.setupDatabase();
2572
+ const server = new JobQueueServer(jobClass, {
2573
+ storage,
2574
+ queueName,
2575
+ limiter: mergedOptions.limiter,
2576
+ workerCount: mergedOptions.workerCount,
2577
+ pollIntervalMs: mergedOptions.pollIntervalMs,
2578
+ deleteAfterCompletionMs: mergedOptions.deleteAfterCompletionMs,
2579
+ deleteAfterFailureMs: mergedOptions.deleteAfterFailureMs,
2580
+ deleteAfterDisabledMs: mergedOptions.deleteAfterDisabledMs,
2581
+ cleanupIntervalMs: mergedOptions.cleanupIntervalMs
2582
+ });
2583
+ const client = new JobQueueClient({
2584
+ storage,
2585
+ queueName
2586
+ });
2587
+ client.attach(server);
2588
+ return { server, client, storage };
2589
+ };
2590
+ }
2591
+ function getJobQueueFactory() {
2592
+ if (!globalServiceRegistry3.has(JOB_QUEUE_FACTORY)) {
2593
+ registerJobQueueFactory(defaultJobQueueFactory);
2594
+ }
2595
+ return globalServiceRegistry3.get(JOB_QUEUE_FACTORY);
2596
+ }
2597
+ if (!globalServiceRegistry3.has(JOB_QUEUE_FACTORY)) {
2598
+ registerJobQueueFactory(defaultJobQueueFactory);
2599
+ }
2600
+ // src/task/JobQueueTask.ts
2601
+ import { Job as Job2 } from "@workglow/job-queue";
2671
2602
 
2672
2603
  // src/task/TaskQueueRegistry.ts
2673
2604
  var taskQueueRegistry = null;
@@ -2717,659 +2648,24 @@ function setTaskQueueRegistry(registry) {
2717
2648
  taskQueueRegistry = registry;
2718
2649
  }
2719
2650
 
2720
- // src/task/IteratorTaskRunner.ts
2721
- class IteratorTaskRunner extends GraphAsTaskRunner {
2722
- iteratorQueue;
2723
- iteratorQueueName;
2724
- async getOrCreateIteratorQueue() {
2725
- const executionMode = this.task.executionMode;
2726
- if (executionMode === "parallel") {
2727
- return;
2728
- }
2729
- if (this.iteratorQueue) {
2730
- return this.iteratorQueue;
2731
- }
2732
- const queueName = this.task.config.queueName ?? `iterator-${this.task.config.id}-${uuid45().slice(0, 8)}`;
2733
- this.iteratorQueueName = queueName;
2734
- const existingQueue = getTaskQueueRegistry().getQueue(queueName);
2735
- if (existingQueue) {
2736
- this.iteratorQueue = existingQueue;
2737
- return existingQueue;
2738
- }
2739
- const concurrency = this.getConcurrencyForMode(executionMode);
2740
- this.iteratorQueue = await this.createIteratorQueue(queueName, concurrency);
2741
- return this.iteratorQueue;
2742
- }
2743
- getConcurrencyForMode(mode) {
2744
- switch (mode) {
2745
- case "sequential":
2746
- return 1;
2747
- case "parallel-limited":
2748
- return this.task.concurrencyLimit;
2749
- case "batched":
2750
- return this.task.batchSize;
2751
- case "parallel":
2752
- default:
2753
- return Infinity;
2754
- }
2755
- }
2756
- async createIteratorQueue(queueName, concurrency) {
2757
- const storage = new InMemoryQueueStorage(queueName);
2758
- await storage.setupDatabase();
2759
- const JobClass = class extends Job {
2760
- async execute(input) {
2761
- return input;
2762
- }
2763
- };
2764
- const server = new JobQueueServer(JobClass, {
2765
- storage,
2766
- queueName,
2767
- workerCount: Math.min(concurrency, 10)
2768
- });
2769
- const client = new JobQueueClient({
2770
- storage,
2771
- queueName
2772
- });
2773
- client.attach(server);
2774
- const queue = {
2775
- server,
2776
- client,
2777
- storage
2778
- };
2779
- try {
2780
- getTaskQueueRegistry().registerQueue(queue);
2781
- } catch (err) {
2782
- const existing = getTaskQueueRegistry().getQueue(queueName);
2783
- if (existing) {
2784
- return existing;
2785
- }
2786
- throw err;
2787
- }
2788
- await server.start();
2789
- return queue;
2651
+ // src/task/JobQueueTask.ts
2652
+ class JobQueueTask extends GraphAsTask {
2653
+ static type = "JobQueueTask";
2654
+ static canRunDirectly = true;
2655
+ currentQueueName;
2656
+ currentJobId;
2657
+ currentRunnerId;
2658
+ jobClass;
2659
+ constructor(input = {}, config = {}) {
2660
+ config.queue ??= true;
2661
+ super(input, config);
2662
+ this.jobClass = Job2;
2790
2663
  }
2791
- async executeTaskChildren(input) {
2792
- const executionMode = this.task.executionMode;
2793
- switch (executionMode) {
2794
- case "sequential":
2795
- return this.executeSequential(input);
2796
- case "parallel-limited":
2797
- return this.executeParallelLimited(input);
2798
- case "batched":
2799
- return this.executeBatched(input);
2800
- case "parallel":
2801
- default:
2802
- return super.executeTaskChildren(input);
2803
- }
2804
- }
2805
- async executeSequential(input) {
2806
- const tasks = this.task.subGraph.getTasks();
2807
- const results = [];
2808
- for (const task of tasks) {
2809
- if (this.abortController?.signal.aborted) {
2810
- break;
2811
- }
2812
- const taskResult = await task.run(input);
2813
- results.push({
2814
- id: task.config.id,
2815
- type: task.type,
2816
- data: taskResult
2817
- });
2818
- }
2819
- return results;
2820
- }
2821
- async executeParallelLimited(input) {
2822
- const tasks = this.task.subGraph.getTasks();
2823
- const results = [];
2824
- const limit = this.task.concurrencyLimit;
2825
- for (let i = 0;i < tasks.length; i += limit) {
2826
- if (this.abortController?.signal.aborted) {
2827
- break;
2828
- }
2829
- const chunk = tasks.slice(i, i + limit);
2830
- const chunkPromises = chunk.map(async (task) => {
2831
- const taskResult = await task.run(input);
2832
- return {
2833
- id: task.config.id,
2834
- type: task.type,
2835
- data: taskResult
2836
- };
2837
- });
2838
- const chunkResults = await Promise.all(chunkPromises);
2839
- results.push(...chunkResults);
2840
- }
2841
- return results;
2842
- }
2843
- async executeBatched(input) {
2844
- const tasks = this.task.subGraph.getTasks();
2845
- const results = [];
2846
- const batchSize = this.task.batchSize;
2847
- for (let i = 0;i < tasks.length; i += batchSize) {
2848
- if (this.abortController?.signal.aborted) {
2849
- break;
2850
- }
2851
- const batch = tasks.slice(i, i + batchSize);
2852
- const batchPromises = batch.map(async (task) => {
2853
- const taskResult = await task.run(input);
2854
- return {
2855
- id: task.config.id,
2856
- type: task.type,
2857
- data: taskResult
2858
- };
2859
- });
2860
- const batchResults = await Promise.all(batchPromises);
2861
- results.push(...batchResults);
2862
- const progress = Math.round((i + batch.length) / tasks.length * 100);
2863
- this.task.emit("progress", progress, `Completed batch ${Math.ceil((i + 1) / batchSize)}`);
2864
- }
2865
- return results;
2866
- }
2867
- async cleanup() {
2868
- if (this.iteratorQueue && this.iteratorQueueName) {
2869
- try {
2870
- this.iteratorQueue.server.stop();
2871
- } catch (err) {}
2872
- }
2873
- }
2874
- }
2875
-
2876
- // src/task/IteratorTask.ts
2877
- class IteratorTask extends GraphAsTask {
2878
- static type = "IteratorTask";
2879
- static category = "Flow Control";
2880
- static title = "Iterator";
2881
- static description = "Base class for loop-type tasks";
2882
- static hasDynamicSchemas = true;
2883
- _templateGraph;
2884
- _iteratorPortInfo;
2885
- constructor(input = {}, config = {}) {
2886
- super(input, config);
2887
- }
2888
- get runner() {
2889
- if (!this._runner) {
2890
- this._runner = new IteratorTaskRunner(this);
2891
- }
2892
- return this._runner;
2893
- }
2894
- get executionMode() {
2895
- return this.config.executionMode ?? "parallel";
2896
- }
2897
- get concurrencyLimit() {
2898
- return this.config.concurrencyLimit ?? 5;
2899
- }
2900
- get batchSize() {
2901
- return this.config.batchSize ?? 10;
2902
- }
2903
- detectIteratorPort() {
2904
- if (this._iteratorPortInfo) {
2905
- return this._iteratorPortInfo;
2906
- }
2907
- if (this.config.iteratorPort) {
2908
- const schema2 = this.inputSchema();
2909
- if (typeof schema2 === "boolean")
2910
- return;
2911
- const portSchema = schema2.properties?.[this.config.iteratorPort];
2912
- if (portSchema && typeof portSchema === "object") {
2913
- const itemSchema = portSchema.items ?? { type: "object" };
2914
- this._iteratorPortInfo = {
2915
- portName: this.config.iteratorPort,
2916
- itemSchema
2917
- };
2918
- return this._iteratorPortInfo;
2919
- }
2920
- }
2921
- const schema = this.inputSchema();
2922
- if (typeof schema === "boolean")
2923
- return;
2924
- const properties = schema.properties || {};
2925
- for (const [portName, portSchema] of Object.entries(properties)) {
2926
- if (typeof portSchema !== "object" || portSchema === null)
2927
- continue;
2928
- const ps = portSchema;
2929
- if (ps.type === "array" || ps.items !== undefined) {
2930
- const itemSchema = ps.items ?? {
2931
- type: "object",
2932
- properties: {},
2933
- additionalProperties: true
2934
- };
2935
- this._iteratorPortInfo = { portName, itemSchema };
2936
- return this._iteratorPortInfo;
2937
- }
2938
- const variants = ps.oneOf ?? ps.anyOf;
2939
- if (Array.isArray(variants)) {
2940
- for (const variant of variants) {
2941
- if (typeof variant === "object" && variant !== null) {
2942
- const v = variant;
2943
- if (v.type === "array" || v.items !== undefined) {
2944
- const itemSchema = v.items ?? {
2945
- type: "object",
2946
- properties: {},
2947
- additionalProperties: true
2948
- };
2949
- this._iteratorPortInfo = { portName, itemSchema };
2950
- return this._iteratorPortInfo;
2951
- }
2952
- }
2953
- }
2954
- }
2955
- }
2956
- return;
2957
- }
2958
- getIteratorPortName() {
2959
- return this.detectIteratorPort()?.portName;
2960
- }
2961
- getItemSchema() {
2962
- return this.detectIteratorPort()?.itemSchema ?? {
2963
- type: "object",
2964
- properties: {},
2965
- additionalProperties: true
2966
- };
2967
- }
2968
- getIterableItems(input) {
2969
- const portName = this.getIteratorPortName();
2970
- if (!portName) {
2971
- throw new TaskConfigurationError(`${this.type}: No array port found in input schema. ` + `Specify 'iteratorPort' in config or ensure input has an array-typed property.`);
2972
- }
2973
- const items = input[portName];
2974
- if (items === undefined || items === null) {
2975
- return [];
2976
- }
2977
- if (Array.isArray(items)) {
2978
- return items;
2979
- }
2980
- return [items];
2981
- }
2982
- setTemplateGraph(graph) {
2983
- this._templateGraph = graph;
2984
- this.events.emit("regenerate");
2985
- }
2986
- getTemplateGraph() {
2987
- return this._templateGraph;
2988
- }
2989
- regenerateGraph() {
2990
- this.subGraph = new TaskGraph;
2991
- if (!this._templateGraph || !this._templateGraph.getTasks().length) {
2992
- super.regenerateGraph();
2993
- return;
2994
- }
2995
- const items = this.getIterableItems(this.runInputData);
2996
- if (items.length === 0) {
2997
- super.regenerateGraph();
2998
- return;
2999
- }
3000
- this.createIterationTasks(items);
3001
- super.regenerateGraph();
3002
- }
3003
- createIterationTasks(items) {
3004
- const portName = this.getIteratorPortName();
3005
- if (!portName)
3006
- return;
3007
- const baseInput = {};
3008
- for (const [key, value] of Object.entries(this.runInputData)) {
3009
- if (key !== portName) {
3010
- baseInput[key] = value;
3011
- }
3012
- }
3013
- for (let i = 0;i < items.length; i++) {
3014
- const item = items[i];
3015
- const iterationInput = {
3016
- ...baseInput,
3017
- [portName]: item,
3018
- _iterationIndex: i,
3019
- _iterationItem: item
3020
- };
3021
- this.cloneTemplateForIteration(iterationInput, i);
3022
- }
3023
- }
3024
- cloneTemplateForIteration(iterationInput, index) {
3025
- if (!this._templateGraph)
3026
- return;
3027
- const templateTasks = this._templateGraph.getTasks();
3028
- const templateDataflows = this._templateGraph.getDataflows();
3029
- const idMap = new Map;
3030
- for (const templateTask of templateTasks) {
3031
- const TaskClass = templateTask.constructor;
3032
- const clonedTask = new TaskClass({ ...templateTask.defaults, ...iterationInput }, {
3033
- ...templateTask.config,
3034
- id: `${templateTask.config.id}_iter${index}`,
3035
- name: `${templateTask.config.name || templateTask.type} [${index}]`
3036
- });
3037
- this.subGraph.addTask(clonedTask);
3038
- idMap.set(templateTask.config.id, clonedTask.config.id);
3039
- }
3040
- for (const templateDataflow of templateDataflows) {
3041
- const sourceId = idMap.get(templateDataflow.sourceTaskId);
3042
- const targetId = idMap.get(templateDataflow.targetTaskId);
3043
- if (sourceId !== undefined && targetId !== undefined) {
3044
- const { Dataflow: Dataflow2 } = (init_Dataflow(), __toCommonJS(exports_Dataflow));
3045
- const clonedDataflow = new Dataflow2(sourceId, templateDataflow.sourceTaskPortId, targetId, templateDataflow.targetTaskPortId);
3046
- this.subGraph.addDataflow(clonedDataflow);
3047
- }
3048
- }
3049
- }
3050
- async execute(input, context) {
3051
- const items = this.getIterableItems(input);
3052
- if (items.length === 0) {
3053
- return this.getEmptyResult();
3054
- }
3055
- this.runInputData = { ...this.defaults, ...input };
3056
- this.regenerateGraph();
3057
- return super.execute(input, context);
3058
- }
3059
- getEmptyResult() {
3060
- return {};
3061
- }
3062
- collectResults(results) {
3063
- return results;
3064
- }
3065
- inputSchema() {
3066
- if (this.hasChildren() || this._templateGraph) {
3067
- return super.inputSchema();
3068
- }
3069
- return this.constructor.inputSchema();
3070
- }
3071
- outputSchema() {
3072
- if (!this.hasChildren() && !this._templateGraph) {
3073
- return this.constructor.outputSchema();
3074
- }
3075
- return this.getWrappedOutputSchema();
3076
- }
3077
- getWrappedOutputSchema() {
3078
- const templateGraph = this._templateGraph ?? this.subGraph;
3079
- if (!templateGraph) {
3080
- return { type: "object", properties: {}, additionalProperties: false };
3081
- }
3082
- const tasks = templateGraph.getTasks();
3083
- const endingNodes = tasks.filter((task) => templateGraph.getTargetDataflows(task.config.id).length === 0);
3084
- if (endingNodes.length === 0) {
3085
- return { type: "object", properties: {}, additionalProperties: false };
3086
- }
3087
- const properties = {};
3088
- for (const task of endingNodes) {
3089
- const taskOutputSchema = task.outputSchema();
3090
- if (typeof taskOutputSchema === "boolean")
3091
- continue;
3092
- const taskProperties = taskOutputSchema.properties || {};
3093
- for (const [key, schema] of Object.entries(taskProperties)) {
3094
- properties[key] = {
3095
- type: "array",
3096
- items: schema
3097
- };
3098
- }
3099
- }
3100
- return {
3101
- type: "object",
3102
- properties,
3103
- additionalProperties: false
3104
- };
3105
- }
3106
- }
3107
-
3108
- // src/task/BatchTask.ts
3109
- class BatchTask extends IteratorTask {
3110
- static type = "BatchTask";
3111
- static category = "Flow Control";
3112
- static title = "Batch";
3113
- static description = "Processes an array in configurable batches";
3114
- static compoundMerge = PROPERTY_ARRAY;
3115
- static inputSchema() {
3116
- return {
3117
- type: "object",
3118
- properties: {},
3119
- additionalProperties: true
3120
- };
3121
- }
3122
- static outputSchema() {
3123
- return {
3124
- type: "object",
3125
- properties: {},
3126
- additionalProperties: true
3127
- };
3128
- }
3129
- get batchSize() {
3130
- return this.config.batchSize ?? 10;
3131
- }
3132
- get flattenResults() {
3133
- return this.config.flattenResults ?? true;
3134
- }
3135
- get batchExecutionMode() {
3136
- return this.config.batchExecutionMode ?? "sequential";
3137
- }
3138
- getIterableItems(input) {
3139
- const items = super.getIterableItems(input);
3140
- return this.groupIntoBatches(items);
3141
- }
3142
- groupIntoBatches(items) {
3143
- const batches = [];
3144
- const size = this.batchSize;
3145
- for (let i = 0;i < items.length; i += size) {
3146
- batches.push(items.slice(i, i + size));
3147
- }
3148
- return batches;
3149
- }
3150
- createIterationTasks(batches) {
3151
- const portName = this.getIteratorPortName();
3152
- if (!portName)
3153
- return;
3154
- const baseInput = {};
3155
- for (const [key, value] of Object.entries(this.runInputData)) {
3156
- if (key !== portName) {
3157
- baseInput[key] = value;
3158
- }
3159
- }
3160
- for (let i = 0;i < batches.length; i++) {
3161
- const batch = batches[i];
3162
- const batchInput = {
3163
- ...baseInput,
3164
- [portName]: batch,
3165
- _batchIndex: i,
3166
- _batchItems: batch
3167
- };
3168
- this.cloneTemplateForIteration(batchInput, i);
3169
- }
3170
- }
3171
- getEmptyResult() {
3172
- const schema = this.outputSchema();
3173
- if (typeof schema === "boolean") {
3174
- return {};
3175
- }
3176
- const result = {};
3177
- for (const key of Object.keys(schema.properties || {})) {
3178
- result[key] = [];
3179
- }
3180
- return result;
3181
- }
3182
- outputSchema() {
3183
- if (!this.hasChildren() && !this._templateGraph) {
3184
- return this.constructor.outputSchema();
3185
- }
3186
- return this.getWrappedOutputSchema();
3187
- }
3188
- collectResults(results) {
3189
- const collected = super.collectResults(results);
3190
- if (!this.flattenResults || typeof collected !== "object" || collected === null) {
3191
- return collected;
3192
- }
3193
- const flattened = {};
3194
- for (const [key, value] of Object.entries(collected)) {
3195
- if (Array.isArray(value)) {
3196
- flattened[key] = value.flat(2);
3197
- } else {
3198
- flattened[key] = value;
3199
- }
3200
- }
3201
- return flattened;
3202
- }
3203
- regenerateGraph() {
3204
- this.subGraph = new TaskGraph;
3205
- if (!this._templateGraph || !this._templateGraph.getTasks().length) {
3206
- super.regenerateGraph();
3207
- return;
3208
- }
3209
- const batches = this.getIterableItems(this.runInputData);
3210
- if (batches.length === 0) {
3211
- super.regenerateGraph();
3212
- return;
3213
- }
3214
- this.createIterationTasks(batches);
3215
- this.events.emit("regenerate");
3216
- }
3217
- }
3218
- Workflow.prototype.batch = CreateLoopWorkflow(BatchTask);
3219
- Workflow.prototype.endBatch = CreateEndLoopWorkflow("endBatch");
3220
- // src/task/ForEachTask.ts
3221
- class ForEachTask extends IteratorTask {
3222
- static type = "ForEachTask";
3223
- static category = "Flow Control";
3224
- static title = "For Each";
3225
- static description = "Iterates over an array and runs a workflow for each element";
3226
- static inputSchema() {
3227
- return {
3228
- type: "object",
3229
- properties: {},
3230
- additionalProperties: true
3231
- };
3232
- }
3233
- static outputSchema() {
3234
- return {
3235
- type: "object",
3236
- properties: {
3237
- completed: {
3238
- type: "boolean",
3239
- title: "Completed",
3240
- description: "Whether all iterations completed successfully"
3241
- },
3242
- count: {
3243
- type: "number",
3244
- title: "Count",
3245
- description: "Number of items processed"
3246
- }
3247
- },
3248
- additionalProperties: false
3249
- };
3250
- }
3251
- get shouldCollectResults() {
3252
- return this.config.shouldCollectResults ?? false;
3253
- }
3254
- getEmptyResult() {
3255
- return {
3256
- completed: true,
3257
- count: 0
3258
- };
3259
- }
3260
- outputSchema() {
3261
- if (this.shouldCollectResults && (this.hasChildren() || this._templateGraph)) {
3262
- return this.getWrappedOutputSchema();
3263
- }
3264
- return this.constructor.outputSchema();
3265
- }
3266
- collectResults(results) {
3267
- if (this.config.shouldCollectResults) {
3268
- return super.collectResults(results);
3269
- }
3270
- return {
3271
- completed: true,
3272
- count: results.length
3273
- };
3274
- }
3275
- }
3276
- Workflow.prototype.forEach = CreateLoopWorkflow(ForEachTask);
3277
- Workflow.prototype.endForEach = CreateEndLoopWorkflow("endForEach");
3278
- // src/task/JobQueueFactory.ts
3279
- import {
3280
- JobQueueClient as JobQueueClient2,
3281
- JobQueueServer as JobQueueServer2
3282
- } from "@workglow/job-queue";
3283
- import { InMemoryQueueStorage as InMemoryQueueStorage2 } from "@workglow/storage";
3284
- import { createServiceToken as createServiceToken2, globalServiceRegistry as globalServiceRegistry3 } from "@workglow/util";
3285
- var JOB_QUEUE_FACTORY = createServiceToken2("taskgraph.jobQueueFactory");
3286
- var defaultJobQueueFactory = async ({
3287
- queueName,
3288
- jobClass,
3289
- options
3290
- }) => {
3291
- const storage = options?.storage ?? new InMemoryQueueStorage2(queueName);
3292
- await storage.setupDatabase();
3293
- const server = new JobQueueServer2(jobClass, {
3294
- storage,
3295
- queueName,
3296
- limiter: options?.limiter,
3297
- workerCount: options?.workerCount,
3298
- pollIntervalMs: options?.pollIntervalMs,
3299
- deleteAfterCompletionMs: options?.deleteAfterCompletionMs,
3300
- deleteAfterFailureMs: options?.deleteAfterFailureMs,
3301
- deleteAfterDisabledMs: options?.deleteAfterDisabledMs,
3302
- cleanupIntervalMs: options?.cleanupIntervalMs
3303
- });
3304
- const client = new JobQueueClient2({
3305
- storage,
3306
- queueName
3307
- });
3308
- client.attach(server);
3309
- return { server, client, storage };
3310
- };
3311
- function registerJobQueueFactory(factory) {
3312
- globalServiceRegistry3.registerInstance(JOB_QUEUE_FACTORY, factory);
3313
- }
3314
- function createJobQueueFactoryWithOptions(defaultOptions = {}) {
3315
- return async ({
3316
- queueName,
3317
- jobClass,
3318
- options
3319
- }) => {
3320
- const mergedOptions = {
3321
- ...defaultOptions,
3322
- ...options ?? {}
3323
- };
3324
- const storage = mergedOptions.storage ?? new InMemoryQueueStorage2(queueName);
3325
- await storage.setupDatabase();
3326
- const server = new JobQueueServer2(jobClass, {
3327
- storage,
3328
- queueName,
3329
- limiter: mergedOptions.limiter,
3330
- workerCount: mergedOptions.workerCount,
3331
- pollIntervalMs: mergedOptions.pollIntervalMs,
3332
- deleteAfterCompletionMs: mergedOptions.deleteAfterCompletionMs,
3333
- deleteAfterFailureMs: mergedOptions.deleteAfterFailureMs,
3334
- deleteAfterDisabledMs: mergedOptions.deleteAfterDisabledMs,
3335
- cleanupIntervalMs: mergedOptions.cleanupIntervalMs
3336
- });
3337
- const client = new JobQueueClient2({
3338
- storage,
3339
- queueName
3340
- });
3341
- client.attach(server);
3342
- return { server, client, storage };
3343
- };
3344
- }
3345
- function getJobQueueFactory() {
3346
- if (!globalServiceRegistry3.has(JOB_QUEUE_FACTORY)) {
3347
- registerJobQueueFactory(defaultJobQueueFactory);
3348
- }
3349
- return globalServiceRegistry3.get(JOB_QUEUE_FACTORY);
3350
- }
3351
- if (!globalServiceRegistry3.has(JOB_QUEUE_FACTORY)) {
3352
- registerJobQueueFactory(defaultJobQueueFactory);
3353
- }
3354
- // src/task/JobQueueTask.ts
3355
- import { Job as Job3 } from "@workglow/job-queue";
3356
- class JobQueueTask extends GraphAsTask {
3357
- static type = "JobQueueTask";
3358
- static canRunDirectly = true;
3359
- currentQueueName;
3360
- currentJobId;
3361
- currentRunnerId;
3362
- jobClass;
3363
- constructor(input = {}, config = {}) {
3364
- config.queue ??= true;
3365
- super(input, config);
3366
- this.jobClass = Job3;
3367
- }
3368
- async execute(input, executeContext) {
3369
- let cleanup = () => {};
3370
- try {
3371
- if (this.config.queue === false && !this.constructor.canRunDirectly) {
3372
- throw new TaskConfigurationError(`${this.type} cannot run directly without a queue`);
2664
+ async execute(input, executeContext) {
2665
+ let cleanup = () => {};
2666
+ try {
2667
+ if (this.config.queue === false && !this.constructor.canRunDirectly) {
2668
+ throw new TaskConfigurationError(`${this.type} cannot run directly without a queue`);
3373
2669
  }
3374
2670
  const registeredQueue = await this.resolveQueue(input);
3375
2671
  if (!registeredQueue) {
@@ -3485,219 +2781,6 @@ class JobQueueTask extends GraphAsTask {
3485
2781
  super.abort();
3486
2782
  }
3487
2783
  }
3488
- // src/task/MapTask.ts
3489
- class MapTask extends IteratorTask {
3490
- static type = "MapTask";
3491
- static category = "Flow Control";
3492
- static title = "Map";
3493
- static description = "Transforms an array by running a workflow for each element";
3494
- static compoundMerge = PROPERTY_ARRAY;
3495
- static inputSchema() {
3496
- return {
3497
- type: "object",
3498
- properties: {},
3499
- additionalProperties: true
3500
- };
3501
- }
3502
- static outputSchema() {
3503
- return {
3504
- type: "object",
3505
- properties: {},
3506
- additionalProperties: true
3507
- };
3508
- }
3509
- get preserveOrder() {
3510
- return this.config.preserveOrder ?? true;
3511
- }
3512
- get flatten() {
3513
- return this.config.flatten ?? false;
3514
- }
3515
- getEmptyResult() {
3516
- const schema = this.outputSchema();
3517
- if (typeof schema === "boolean") {
3518
- return {};
3519
- }
3520
- const result = {};
3521
- for (const key of Object.keys(schema.properties || {})) {
3522
- result[key] = [];
3523
- }
3524
- return result;
3525
- }
3526
- outputSchema() {
3527
- if (!this.hasChildren() && !this._templateGraph) {
3528
- return this.constructor.outputSchema();
3529
- }
3530
- return this.getWrappedOutputSchema();
3531
- }
3532
- collectResults(results) {
3533
- const collected = super.collectResults(results);
3534
- if (!this.flatten || typeof collected !== "object" || collected === null) {
3535
- return collected;
3536
- }
3537
- const flattened = {};
3538
- for (const [key, value] of Object.entries(collected)) {
3539
- if (Array.isArray(value)) {
3540
- flattened[key] = value.flat();
3541
- } else {
3542
- flattened[key] = value;
3543
- }
3544
- }
3545
- return flattened;
3546
- }
3547
- }
3548
- Workflow.prototype.map = CreateLoopWorkflow(MapTask);
3549
- Workflow.prototype.endMap = CreateEndLoopWorkflow("endMap");
3550
- // src/task/ReduceTask.ts
3551
- class ReduceTask extends IteratorTask {
3552
- static type = "ReduceTask";
3553
- static category = "Flow Control";
3554
- static title = "Reduce";
3555
- static description = "Processes array elements sequentially with an accumulator (fold)";
3556
- constructor(input = {}, config = {}) {
3557
- const reduceConfig = {
3558
- ...config,
3559
- executionMode: "sequential"
3560
- };
3561
- super(input, reduceConfig);
3562
- }
3563
- get initialValue() {
3564
- return this.config.initialValue ?? {};
3565
- }
3566
- get accumulatorPort() {
3567
- return this.config.accumulatorPort ?? "accumulator";
3568
- }
3569
- get currentItemPort() {
3570
- return this.config.currentItemPort ?? "currentItem";
3571
- }
3572
- get indexPort() {
3573
- return this.config.indexPort ?? "index";
3574
- }
3575
- async execute(input, context) {
3576
- if (!this._templateGraph || this._templateGraph.getTasks().length === 0) {
3577
- return this.initialValue;
3578
- }
3579
- const items = this.getIterableItems(input);
3580
- if (items.length === 0) {
3581
- return this.initialValue;
3582
- }
3583
- let accumulator = { ...this.initialValue };
3584
- for (let index = 0;index < items.length; index++) {
3585
- if (context.signal?.aborted) {
3586
- break;
3587
- }
3588
- const currentItem = items[index];
3589
- const stepInput = {
3590
- ...input,
3591
- [this.accumulatorPort]: accumulator,
3592
- [this.currentItemPort]: currentItem,
3593
- [this.indexPort]: index
3594
- };
3595
- this.subGraph = this.cloneTemplateForStep(index);
3596
- const results = await this.subGraph.run(stepInput, {
3597
- parentSignal: context.signal
3598
- });
3599
- accumulator = this.subGraph.mergeExecuteOutputsToRunOutput(results, this.compoundMerge);
3600
- const progress = Math.round((index + 1) / items.length * 100);
3601
- await context.updateProgress(progress, `Processing item ${index + 1}/${items.length}`);
3602
- }
3603
- return accumulator;
3604
- }
3605
- getEmptyResult() {
3606
- return this.initialValue;
3607
- }
3608
- cloneTemplateForStep(stepIndex) {
3609
- const clonedGraph = new TaskGraph;
3610
- if (!this._templateGraph) {
3611
- return clonedGraph;
3612
- }
3613
- const templateTasks = this._templateGraph.getTasks();
3614
- const templateDataflows = this._templateGraph.getDataflows();
3615
- const idMap = new Map;
3616
- for (const templateTask of templateTasks) {
3617
- const TaskClass = templateTask.constructor;
3618
- const clonedTask = new TaskClass({ ...templateTask.defaults }, {
3619
- ...templateTask.config,
3620
- id: `${templateTask.config.id}_step${stepIndex}`,
3621
- name: `${templateTask.config.name || templateTask.type} [${stepIndex}]`
3622
- });
3623
- clonedGraph.addTask(clonedTask);
3624
- idMap.set(templateTask.config.id, clonedTask.config.id);
3625
- }
3626
- for (const templateDataflow of templateDataflows) {
3627
- const sourceId = idMap.get(templateDataflow.sourceTaskId);
3628
- const targetId = idMap.get(templateDataflow.targetTaskId);
3629
- if (sourceId !== undefined && targetId !== undefined) {
3630
- const { Dataflow: Dataflow2 } = (init_Dataflow(), __toCommonJS(exports_Dataflow));
3631
- const clonedDataflow = new Dataflow2(sourceId, templateDataflow.sourceTaskPortId, targetId, templateDataflow.targetTaskPortId);
3632
- clonedGraph.addDataflow(clonedDataflow);
3633
- }
3634
- }
3635
- return clonedGraph;
3636
- }
3637
- static inputSchema() {
3638
- return {
3639
- type: "object",
3640
- properties: {
3641
- accumulator: {
3642
- title: "Accumulator",
3643
- description: "The current accumulator value"
3644
- },
3645
- currentItem: {
3646
- title: "Current Item",
3647
- description: "The current item being processed"
3648
- },
3649
- index: {
3650
- type: "number",
3651
- title: "Index",
3652
- description: "The current item index"
3653
- }
3654
- },
3655
- additionalProperties: true
3656
- };
3657
- }
3658
- static outputSchema() {
3659
- return {
3660
- type: "object",
3661
- properties: {},
3662
- additionalProperties: true
3663
- };
3664
- }
3665
- outputSchema() {
3666
- if (!this._templateGraph) {
3667
- return this.constructor.outputSchema();
3668
- }
3669
- const tasks = this._templateGraph.getTasks();
3670
- const endingNodes = tasks.filter((task) => this._templateGraph.getTargetDataflows(task.config.id).length === 0);
3671
- if (endingNodes.length === 0) {
3672
- return this.constructor.outputSchema();
3673
- }
3674
- const properties = {};
3675
- for (const task of endingNodes) {
3676
- const taskOutputSchema = task.outputSchema();
3677
- if (typeof taskOutputSchema === "boolean")
3678
- continue;
3679
- const taskProperties = taskOutputSchema.properties || {};
3680
- for (const [key, schema] of Object.entries(taskProperties)) {
3681
- if (!properties[key]) {
3682
- properties[key] = schema;
3683
- }
3684
- }
3685
- }
3686
- return {
3687
- type: "object",
3688
- properties,
3689
- additionalProperties: false
3690
- };
3691
- }
3692
- regenerateGraph() {
3693
- this.events.emit("regenerate");
3694
- }
3695
- }
3696
- Workflow.prototype.reduce = CreateLoopWorkflow(ReduceTask);
3697
- Workflow.prototype.endReduce = CreateEndLoopWorkflow("endReduce");
3698
- // src/task/TaskJSON.ts
3699
- init_Dataflow();
3700
-
3701
2784
  // src/task/TaskRegistry.ts
3702
2785
  var taskConstructors = new Map;
3703
2786
  function registerTask(baseClass) {
@@ -3765,167 +2848,9 @@ var createGraphFromGraphJSON = (graphJsonObj) => {
3765
2848
  }
3766
2849
  return subGraph;
3767
2850
  };
3768
-
3769
- // src/task/index.ts
3770
- init_TaskTypes();
3771
-
3772
- // src/task/WhileTask.ts
3773
- class WhileTask extends GraphAsTask {
3774
- static type = "WhileTask";
3775
- static category = "Flow Control";
3776
- static title = "While Loop";
3777
- static description = "Loops until a condition function returns false";
3778
- static hasDynamicSchemas = true;
3779
- _templateGraph;
3780
- _currentIteration = 0;
3781
- constructor(input = {}, config = {}) {
3782
- super(input, config);
3783
- }
3784
- get condition() {
3785
- return this.config.condition;
3786
- }
3787
- get maxIterations() {
3788
- return this.config.maxIterations ?? 100;
3789
- }
3790
- get chainIterations() {
3791
- return this.config.chainIterations ?? true;
3792
- }
3793
- get currentIteration() {
3794
- return this._currentIteration;
3795
- }
3796
- setTemplateGraph(graph) {
3797
- this._templateGraph = graph;
3798
- }
3799
- getTemplateGraph() {
3800
- return this._templateGraph;
3801
- }
3802
- async execute(input, context) {
3803
- if (!this._templateGraph || this._templateGraph.getTasks().length === 0) {
3804
- throw new TaskConfigurationError(`${this.type}: No template graph set for while loop`);
3805
- }
3806
- if (!this.condition) {
3807
- throw new TaskConfigurationError(`${this.type}: No condition function provided`);
3808
- }
3809
- this._currentIteration = 0;
3810
- let currentInput = { ...input };
3811
- let currentOutput = {};
3812
- while (this._currentIteration < this.maxIterations) {
3813
- if (context.signal?.aborted) {
3814
- break;
3815
- }
3816
- this.subGraph = this.cloneTemplateGraph(this._currentIteration);
3817
- const results = await this.subGraph.run(currentInput, {
3818
- parentSignal: context.signal
3819
- });
3820
- currentOutput = this.subGraph.mergeExecuteOutputsToRunOutput(results, this.compoundMerge);
3821
- if (!this.condition(currentOutput, this._currentIteration)) {
3822
- break;
3823
- }
3824
- if (this.chainIterations) {
3825
- currentInput = { ...currentInput, ...currentOutput };
3826
- }
3827
- this._currentIteration++;
3828
- const progress = Math.min(this._currentIteration / this.maxIterations * 100, 99);
3829
- await context.updateProgress(progress, `Iteration ${this._currentIteration}`);
3830
- }
3831
- return currentOutput;
3832
- }
3833
- cloneTemplateGraph(iteration) {
3834
- const clonedGraph = new TaskGraph;
3835
- if (!this._templateGraph) {
3836
- return clonedGraph;
3837
- }
3838
- const templateTasks = this._templateGraph.getTasks();
3839
- const templateDataflows = this._templateGraph.getDataflows();
3840
- const idMap = new Map;
3841
- for (const templateTask of templateTasks) {
3842
- const TaskClass = templateTask.constructor;
3843
- const clonedTask = new TaskClass({ ...templateTask.defaults }, {
3844
- ...templateTask.config,
3845
- id: `${templateTask.config.id}_iter${iteration}`,
3846
- name: `${templateTask.config.name || templateTask.type} [${iteration}]`
3847
- });
3848
- clonedGraph.addTask(clonedTask);
3849
- idMap.set(templateTask.config.id, clonedTask.config.id);
3850
- }
3851
- for (const templateDataflow of templateDataflows) {
3852
- const sourceId = idMap.get(templateDataflow.sourceTaskId);
3853
- const targetId = idMap.get(templateDataflow.targetTaskId);
3854
- if (sourceId !== undefined && targetId !== undefined) {
3855
- const { Dataflow: Dataflow2 } = (init_Dataflow(), __toCommonJS(exports_Dataflow));
3856
- const clonedDataflow = new Dataflow2(sourceId, templateDataflow.sourceTaskPortId, targetId, templateDataflow.targetTaskPortId);
3857
- clonedGraph.addDataflow(clonedDataflow);
3858
- }
3859
- }
3860
- return clonedGraph;
3861
- }
3862
- static inputSchema() {
3863
- return {
3864
- type: "object",
3865
- properties: {},
3866
- additionalProperties: true
3867
- };
3868
- }
3869
- static outputSchema() {
3870
- return {
3871
- type: "object",
3872
- properties: {
3873
- _iterations: {
3874
- type: "number",
3875
- title: "Iterations",
3876
- description: "Number of iterations executed"
3877
- }
3878
- },
3879
- additionalProperties: true
3880
- };
3881
- }
3882
- outputSchema() {
3883
- if (!this._templateGraph) {
3884
- return this.constructor.outputSchema();
3885
- }
3886
- const tasks = this._templateGraph.getTasks();
3887
- const endingNodes = tasks.filter((task) => this._templateGraph.getTargetDataflows(task.config.id).length === 0);
3888
- if (endingNodes.length === 0) {
3889
- return this.constructor.outputSchema();
3890
- }
3891
- const properties = {
3892
- _iterations: {
3893
- type: "number",
3894
- title: "Iterations",
3895
- description: "Number of iterations executed"
3896
- }
3897
- };
3898
- for (const task of endingNodes) {
3899
- const taskOutputSchema = task.outputSchema();
3900
- if (typeof taskOutputSchema === "boolean")
3901
- continue;
3902
- const taskProperties = taskOutputSchema.properties || {};
3903
- for (const [key, schema] of Object.entries(taskProperties)) {
3904
- if (!properties[key]) {
3905
- properties[key] = schema;
3906
- }
3907
- }
3908
- }
3909
- return {
3910
- type: "object",
3911
- properties,
3912
- additionalProperties: false
3913
- };
3914
- }
3915
- }
3916
- Workflow.prototype.while = CreateLoopWorkflow(WhileTask);
3917
- Workflow.prototype.endWhile = CreateEndLoopWorkflow("endWhile");
3918
2851
  // src/task/index.ts
3919
2852
  var registerBaseTasks = () => {
3920
- const tasks = [
3921
- ConditionalTask,
3922
- GraphAsTask,
3923
- ForEachTask,
3924
- MapTask,
3925
- BatchTask,
3926
- WhileTask,
3927
- ReduceTask
3928
- ];
2853
+ const tasks = [ConditionalTask, GraphAsTask];
3929
2854
  tasks.map(TaskRegistry.registerTask);
3930
2855
  return tasks;
3931
2856
  };
@@ -4105,7 +3030,6 @@ export {
4105
3030
  connect,
4106
3031
  WorkflowError,
4107
3032
  Workflow,
4108
- WhileTask,
4109
3033
  TaskStatus,
4110
3034
  TaskRegistry,
4111
3035
  TaskQueueRegistry,
@@ -4128,18 +3052,13 @@ export {
4128
3052
  Task,
4129
3053
  TASK_OUTPUT_REPOSITORY,
4130
3054
  TASK_GRAPH_REPOSITORY,
4131
- ReduceTask,
4132
3055
  PROPERTY_ARRAY,
4133
- MapTask,
4134
3056
  JobTaskFailedError,
4135
3057
  JobQueueTask,
4136
3058
  JOB_QUEUE_FACTORY,
4137
- IteratorTaskRunner,
4138
- IteratorTask,
4139
3059
  GraphAsTaskRunner,
4140
3060
  GraphAsTask,
4141
3061
  GRAPH_RESULT_ARRAY,
4142
- ForEachTask,
4143
3062
  EventTaskGraphToDagMapping,
4144
3063
  EventDagToTaskGraphMapping,
4145
3064
  DataflowArrow,
@@ -4147,10 +3066,7 @@ export {
4147
3066
  DATAFLOW_ERROR_PORT,
4148
3067
  DATAFLOW_ALL_PORTS,
4149
3068
  CreateWorkflow,
4150
- CreateLoopWorkflow,
4151
- CreateEndLoopWorkflow,
4152
- ConditionalTask,
4153
- BatchTask
3069
+ ConditionalTask
4154
3070
  };
4155
3071
 
4156
- //# debugId=BB6441A3D3B3FDA564756E2164756E21
3072
+ //# debugId=262FD218D0D53F5964756E2164756E21