@workglow/task-graph 0.0.123 → 0.0.125
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/browser.d.ts +1 -0
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +652 -11
- package/dist/browser.js.map +8 -7
- package/dist/bun.js +11 -11
- package/dist/bun.js.map +5 -5
- package/dist/debug/console/ConsoleFormatters.d.ts +45 -0
- package/dist/debug/console/ConsoleFormatters.d.ts.map +1 -0
- package/dist/node.js +11 -11
- package/dist/node.js.map +5 -5
- package/dist/task/ITask.d.ts +5 -5
- package/dist/task/ITask.d.ts.map +1 -1
- package/dist/task/Task.d.ts +4 -4
- package/dist/task/Task.d.ts.map +1 -1
- package/dist/task/TaskRunner.d.ts.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +7 -7
- package/src/debug/README.md +115 -0
package/dist/browser.js
CHANGED
|
@@ -948,7 +948,8 @@ class TaskRunner {
|
|
|
948
948
|
this.task.setInput(overrides);
|
|
949
949
|
const schema = this.task.constructor.inputSchema();
|
|
950
950
|
this.task.runInputData = await resolveSchemaInputs(this.task.runInputData, schema, { registry: this.registry });
|
|
951
|
-
const
|
|
951
|
+
const inputs = this.task.runInputData;
|
|
952
|
+
const isValid = await this.task.validateInput(inputs);
|
|
952
953
|
if (!isValid) {
|
|
953
954
|
throw new TaskInvalidInputError("Invalid input data");
|
|
954
955
|
}
|
|
@@ -956,7 +957,6 @@ class TaskRunner {
|
|
|
956
957
|
await this.handleAbort();
|
|
957
958
|
throw new TaskAbortedError("Promise for task created and aborted before run");
|
|
958
959
|
}
|
|
959
|
-
const inputs = this.task.runInputData;
|
|
960
960
|
let outputs;
|
|
961
961
|
const isStreamable = isTaskStreamable(this.task);
|
|
962
962
|
if (this.task.cacheable) {
|
|
@@ -1001,11 +1001,12 @@ class TaskRunner {
|
|
|
1001
1001
|
this.task.runInputData = await resolveSchemaInputs(this.task.runInputData, schema, { registry: this.registry });
|
|
1002
1002
|
await this.handleStartReactive();
|
|
1003
1003
|
try {
|
|
1004
|
-
const
|
|
1004
|
+
const inputs = this.task.runInputData;
|
|
1005
|
+
const isValid = await this.task.validateInput(inputs);
|
|
1005
1006
|
if (!isValid) {
|
|
1006
1007
|
throw new TaskInvalidInputError("Invalid input data");
|
|
1007
1008
|
}
|
|
1008
|
-
const resultReactive = await this.executeTaskReactive(
|
|
1009
|
+
const resultReactive = await this.executeTaskReactive(inputs, this.task.runOutputData);
|
|
1009
1010
|
this.task.runOutputData = resultReactive;
|
|
1010
1011
|
await this.handleCompleteReactive();
|
|
1011
1012
|
} catch (err) {
|
|
@@ -1198,7 +1199,7 @@ class TaskRunner {
|
|
|
1198
1199
|
this.task.emit("start");
|
|
1199
1200
|
this.task.emit("status", this.task.status);
|
|
1200
1201
|
}
|
|
1201
|
-
updateProgress = async (
|
|
1202
|
+
updateProgress = async (_task, _progress, _message, ..._args) => {};
|
|
1202
1203
|
async handleStartReactive() {
|
|
1203
1204
|
this.reactiveRunning = true;
|
|
1204
1205
|
}
|
|
@@ -1306,11 +1307,7 @@ var init_TaskRunner = __esm(() => {
|
|
|
1306
1307
|
|
|
1307
1308
|
// src/task/Task.ts
|
|
1308
1309
|
import { compileSchema } from "@workglow/util/schema";
|
|
1309
|
-
import {
|
|
1310
|
-
deepEqual,
|
|
1311
|
-
EventEmitter as EventEmitter3,
|
|
1312
|
-
uuid4 as uuid42
|
|
1313
|
-
} from "@workglow/util";
|
|
1310
|
+
import { deepEqual, EventEmitter as EventEmitter3, uuid4 as uuid42 } from "@workglow/util";
|
|
1314
1311
|
|
|
1315
1312
|
class Task {
|
|
1316
1313
|
static type = "Task";
|
|
@@ -1677,6 +1674,9 @@ class Task {
|
|
|
1677
1674
|
return this.constructor.getInputSchemaNode();
|
|
1678
1675
|
}
|
|
1679
1676
|
async validateInput(input) {
|
|
1677
|
+
if (typeof input !== "object" || input === null) {
|
|
1678
|
+
throw new TaskInvalidInputError("Input must be an object");
|
|
1679
|
+
}
|
|
1680
1680
|
const ctor = this.constructor;
|
|
1681
1681
|
let schemaNode;
|
|
1682
1682
|
if (ctor.hasDynamicSchemas) {
|
|
@@ -6791,6 +6791,645 @@ class TaskOutputTabularRepository extends TaskOutputRepository {
|
|
|
6791
6791
|
this.emit("output_pruned");
|
|
6792
6792
|
}
|
|
6793
6793
|
}
|
|
6794
|
+
// src/debug/console/ConsoleFormatters.ts
|
|
6795
|
+
init_Dataflow();
|
|
6796
|
+
init_TaskGraph();
|
|
6797
|
+
import { DirectedAcyclicGraph as DirectedAcyclicGraph2 } from "@workglow/util/graph";
|
|
6798
|
+
init_Task();
|
|
6799
|
+
init_TaskTypes();
|
|
6800
|
+
function formatDuration(ms) {
|
|
6801
|
+
if (ms < 1)
|
|
6802
|
+
return `${(ms * 1000).toFixed(0)}µs`;
|
|
6803
|
+
if (ms < 1000)
|
|
6804
|
+
return `${ms.toFixed(1)}ms`;
|
|
6805
|
+
return `${(ms / 1000).toFixed(2)}s`;
|
|
6806
|
+
}
|
|
6807
|
+
function getSchemaProperties(schema) {
|
|
6808
|
+
if (typeof schema === "boolean") {
|
|
6809
|
+
return null;
|
|
6810
|
+
}
|
|
6811
|
+
return schema.properties;
|
|
6812
|
+
}
|
|
6813
|
+
|
|
6814
|
+
class ConsoleFormatter {
|
|
6815
|
+
}
|
|
6816
|
+
function isDarkMode() {
|
|
6817
|
+
return window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
6818
|
+
}
|
|
6819
|
+
|
|
6820
|
+
class WorkflowConsoleFormatter extends ConsoleFormatter {
|
|
6821
|
+
header(workflow, config) {
|
|
6822
|
+
if (workflow instanceof Workflow || workflow instanceof TaskGraph) {
|
|
6823
|
+
const graph = workflow instanceof TaskGraph ? workflow : workflow.graph;
|
|
6824
|
+
const error = workflow instanceof Workflow ? workflow.error : "";
|
|
6825
|
+
const title = workflow instanceof Workflow ? "Workflow" : "TaskGraph";
|
|
6826
|
+
const header = new JsonMLElement("div");
|
|
6827
|
+
header.sectionHeader(title);
|
|
6828
|
+
header.styledText(`(${graph.getTasks().length} tasks)`, "color: green; margin-left: 10px;");
|
|
6829
|
+
if (error) {
|
|
6830
|
+
header.styledText(error, "color: red; margin-left: 10px;");
|
|
6831
|
+
}
|
|
6832
|
+
return header.toJsonML();
|
|
6833
|
+
}
|
|
6834
|
+
return null;
|
|
6835
|
+
}
|
|
6836
|
+
hasBody(value, config) {
|
|
6837
|
+
return true;
|
|
6838
|
+
}
|
|
6839
|
+
body(obj, config) {
|
|
6840
|
+
const body = new JsonMLElement("div");
|
|
6841
|
+
const graph = obj instanceof TaskGraph ? obj : obj.graph;
|
|
6842
|
+
const nodes = body.createStyledList();
|
|
6843
|
+
const tasks = graph.getTasks();
|
|
6844
|
+
if (tasks.length) {
|
|
6845
|
+
nodes.createTextChild("Tasks:");
|
|
6846
|
+
for (const node of tasks) {
|
|
6847
|
+
const nodeTag = nodes.createListItem("", "list-style-type: none;");
|
|
6848
|
+
if (obj instanceof Workflow) {
|
|
6849
|
+
for (const df of graph.getSourceDataflows(node.config.id)) {
|
|
6850
|
+
const edgeTag = nodeTag.createChild("li").setStyle("padding-left: 20px;");
|
|
6851
|
+
if (df.sourceTaskPortId === df.targetTaskPortId)
|
|
6852
|
+
continue;
|
|
6853
|
+
const num = tasks.findIndex((t) => t.config.id === df.sourceTaskId) - tasks.findIndex((t) => t.config.id === node.config.id);
|
|
6854
|
+
edgeTag.highlightText("rename");
|
|
6855
|
+
edgeTag.functionCall((el) => {
|
|
6856
|
+
el.greyText('"');
|
|
6857
|
+
el.outputText(`${df.sourceTaskPortId}`);
|
|
6858
|
+
el.greyText('", "');
|
|
6859
|
+
el.inputText(`${df.targetTaskPortId}`);
|
|
6860
|
+
el.greyText('"');
|
|
6861
|
+
if (num !== -1)
|
|
6862
|
+
el.greyText(`, ${num}`);
|
|
6863
|
+
});
|
|
6864
|
+
}
|
|
6865
|
+
}
|
|
6866
|
+
nodeTag.createObjectTag(node, { graph, workflow: obj });
|
|
6867
|
+
}
|
|
6868
|
+
}
|
|
6869
|
+
if (obj instanceof TaskGraph) {
|
|
6870
|
+
const dfList = nodes.createTextChild("Dataflows:");
|
|
6871
|
+
for (const df of obj.getDataflows()) {
|
|
6872
|
+
const dfTag = dfList.createListItem("", "list-style-type: none;");
|
|
6873
|
+
dfTag.createObjectTag(df);
|
|
6874
|
+
}
|
|
6875
|
+
}
|
|
6876
|
+
let earliestStart;
|
|
6877
|
+
let latestEnd;
|
|
6878
|
+
for (const t of tasks) {
|
|
6879
|
+
if (t.startedAt && (!earliestStart || t.startedAt < earliestStart)) {
|
|
6880
|
+
earliestStart = t.startedAt;
|
|
6881
|
+
}
|
|
6882
|
+
if (t.completedAt && (!latestEnd || t.completedAt > latestEnd)) {
|
|
6883
|
+
latestEnd = t.completedAt;
|
|
6884
|
+
}
|
|
6885
|
+
}
|
|
6886
|
+
if (earliestStart && latestEnd) {
|
|
6887
|
+
const durationMs = latestEnd.getTime() - earliestStart.getTime();
|
|
6888
|
+
const timing = nodes.createListItem("", "list-style-type: none;");
|
|
6889
|
+
timing.highlightText("Total duration: ");
|
|
6890
|
+
timing.createTextChild(formatDuration(durationMs));
|
|
6891
|
+
}
|
|
6892
|
+
const dag = obj._dag ?? obj.graph._dag;
|
|
6893
|
+
if (dag && dag.getNodes().length > 0)
|
|
6894
|
+
body.createObjectTag(dag);
|
|
6895
|
+
return body.toJsonML();
|
|
6896
|
+
}
|
|
6897
|
+
}
|
|
6898
|
+
|
|
6899
|
+
class WorkflowAPIConsoleFormatter extends ConsoleFormatter {
|
|
6900
|
+
header(obj, config) {
|
|
6901
|
+
if (obj === Workflow.prototype || obj === Workflow) {
|
|
6902
|
+
const header = new JsonMLElement("div");
|
|
6903
|
+
header.sectionHeader("Workflow API");
|
|
6904
|
+
return header.toJsonML();
|
|
6905
|
+
}
|
|
6906
|
+
return null;
|
|
6907
|
+
}
|
|
6908
|
+
hasBody(value, config) {
|
|
6909
|
+
return true;
|
|
6910
|
+
}
|
|
6911
|
+
body() {
|
|
6912
|
+
const body = new JsonMLElement("div");
|
|
6913
|
+
const apiSection = body.createChild("div");
|
|
6914
|
+
const apiList = apiSection.createStyledList();
|
|
6915
|
+
const apiTag = apiList.createListItem("", "list-style-type: none;");
|
|
6916
|
+
apiTag.createHighlightedListItem(".reset()");
|
|
6917
|
+
apiTag.createHighlightedListItem(".rename(outputName, inputName)");
|
|
6918
|
+
apiTag.createHighlightedListItem(".run()");
|
|
6919
|
+
apiTag.createHighlightedListItem(".abort()");
|
|
6920
|
+
apiTag.createHighlightedListItem(".toJSON()");
|
|
6921
|
+
apiTag.createHighlightedListItem(".toDependencyJSON()");
|
|
6922
|
+
for (const [key, value] of Object.entries(Workflow.prototype)) {
|
|
6923
|
+
if (typeof value === "function" && key !== "constructor") {
|
|
6924
|
+
const item = apiTag.createListItem("");
|
|
6925
|
+
item.createChild("span").createObjectTag(value);
|
|
6926
|
+
}
|
|
6927
|
+
}
|
|
6928
|
+
return body.toJsonML();
|
|
6929
|
+
}
|
|
6930
|
+
}
|
|
6931
|
+
|
|
6932
|
+
class CreateWorkflowConsoleFormatter extends ConsoleFormatter {
|
|
6933
|
+
header(obj, config) {
|
|
6934
|
+
const workflowObj = obj;
|
|
6935
|
+
if (workflowObj.workflowCreate) {
|
|
6936
|
+
const header = new JsonMLElement("div");
|
|
6937
|
+
const name = workflowObj.constructor.runtype ?? workflowObj.constructor.type ?? workflowObj.type.replace(/Task$/, "");
|
|
6938
|
+
const inputSchema = workflowObj.inputSchema();
|
|
6939
|
+
const outputSchema = workflowObj.outputSchema();
|
|
6940
|
+
const inputProperties = getSchemaProperties(inputSchema);
|
|
6941
|
+
const outputProperties = getSchemaProperties(outputSchema);
|
|
6942
|
+
const inputs = inputProperties ? Object.keys(inputProperties).map((key) => `${key}: …`) : typeof inputSchema === "boolean" ? inputSchema ? ["…"] : ["never"] : [];
|
|
6943
|
+
const outputs = outputProperties ? Object.keys(outputProperties).map((key) => `${key}: …`) : typeof outputSchema === "boolean" ? outputSchema ? ["…"] : ["never"] : [];
|
|
6944
|
+
header.methodSignature(name);
|
|
6945
|
+
header.functionCall((el) => {
|
|
6946
|
+
el.objectBraces((innerObj) => {
|
|
6947
|
+
innerObj.inputText(`${inputs.join(", ")}`);
|
|
6948
|
+
});
|
|
6949
|
+
});
|
|
6950
|
+
header.greyText("): ");
|
|
6951
|
+
header.objectBraces((el) => {
|
|
6952
|
+
el.outputText(`${outputs.join(", ")}`);
|
|
6953
|
+
});
|
|
6954
|
+
return header.toJsonML();
|
|
6955
|
+
}
|
|
6956
|
+
return null;
|
|
6957
|
+
}
|
|
6958
|
+
hasBody(value, config) {
|
|
6959
|
+
return false;
|
|
6960
|
+
}
|
|
6961
|
+
body(obj, config) {
|
|
6962
|
+
return null;
|
|
6963
|
+
}
|
|
6964
|
+
}
|
|
6965
|
+
|
|
6966
|
+
class TaskConsoleFormatter extends ConsoleFormatter {
|
|
6967
|
+
header(task2, config) {
|
|
6968
|
+
if (!task2)
|
|
6969
|
+
return null;
|
|
6970
|
+
if (task2 instanceof Task && task2.inputSchema && task2.outputSchema && task2.runInputData && task2.runOutputData) {
|
|
6971
|
+
const header = new JsonMLElement("div");
|
|
6972
|
+
let name = task2.type ?? task2.constructor.name;
|
|
6973
|
+
if (config?.workflow)
|
|
6974
|
+
name = name.replace(/Task$/, "");
|
|
6975
|
+
const inputSchema = task2.inputSchema();
|
|
6976
|
+
const outputSchema = task2.outputSchema();
|
|
6977
|
+
const inputProperties = getSchemaProperties(inputSchema);
|
|
6978
|
+
const outputProperties = getSchemaProperties(outputSchema);
|
|
6979
|
+
const inputs = inputProperties ? Object.keys(inputProperties).filter((key) => task2.runInputData[key] !== undefined).map((key) => {
|
|
6980
|
+
const value = task2.runInputData[key];
|
|
6981
|
+
return { name: key, value };
|
|
6982
|
+
}) : typeof inputSchema === "boolean" && inputSchema ? Object.keys(task2.runInputData || {}).filter((key) => task2.runInputData[key] !== undefined).map((key) => {
|
|
6983
|
+
const value = task2.runInputData[key];
|
|
6984
|
+
return { name: key, value };
|
|
6985
|
+
}) : [];
|
|
6986
|
+
const outputs = outputProperties ? Object.keys(outputProperties).filter((key) => task2.runOutputData[key] !== undefined && task2.runOutputData[key] !== "").filter((key) => !(Array.isArray(task2.runOutputData[key]) && task2.runOutputData[key].length === 0)).map((key) => {
|
|
6987
|
+
return { name: key, value: task2.runOutputData[key] };
|
|
6988
|
+
}) : typeof outputSchema === "boolean" && outputSchema ? Object.keys(task2.runOutputData || {}).filter((key) => task2.runOutputData[key] !== undefined && task2.runOutputData[key] !== "").filter((key) => !(Array.isArray(task2.runOutputData[key]) && task2.runOutputData[key].length === 0)).map((key) => {
|
|
6989
|
+
return { name: key, value: task2.runOutputData[key] };
|
|
6990
|
+
}) : [];
|
|
6991
|
+
header.highlightText(name);
|
|
6992
|
+
header.functionCall((el) => {
|
|
6993
|
+
el.objectBraces((innerObj) => {
|
|
6994
|
+
innerObj.parameterList(inputs);
|
|
6995
|
+
});
|
|
6996
|
+
el.greyText(", ");
|
|
6997
|
+
el.objectBraces((innerObj) => {
|
|
6998
|
+
innerObj.parameterList([{ name: "id", value: task2.config.id }]);
|
|
6999
|
+
});
|
|
7000
|
+
});
|
|
7001
|
+
if (task2.status === TaskStatus.COMPLETED) {
|
|
7002
|
+
header.greyText(": ");
|
|
7003
|
+
header.objectBraces((el) => {
|
|
7004
|
+
el.parameterList(outputs, true);
|
|
7005
|
+
});
|
|
7006
|
+
}
|
|
7007
|
+
return header.toJsonML();
|
|
7008
|
+
}
|
|
7009
|
+
return null;
|
|
7010
|
+
}
|
|
7011
|
+
hasBody(task2, config) {
|
|
7012
|
+
return task2 instanceof Task;
|
|
7013
|
+
}
|
|
7014
|
+
body(task2, config) {
|
|
7015
|
+
if (!task2)
|
|
7016
|
+
return null;
|
|
7017
|
+
if (!(task2 instanceof Task))
|
|
7018
|
+
return null;
|
|
7019
|
+
const body = new JsonMLElement("div").setStyle("padding-left: 10px;");
|
|
7020
|
+
const inputs = body.createStyledList("Inputs:");
|
|
7021
|
+
const allInboundDataflows = config?.graph?.getSourceDataflows(task2.config.id);
|
|
7022
|
+
const inputSchema = task2.inputSchema();
|
|
7023
|
+
const inputProperties = getSchemaProperties(inputSchema);
|
|
7024
|
+
const schemaKeys = inputProperties !== null ? Object.keys(inputProperties) : inputSchema === true ? Object.keys(task2.runInputData || {}) : [];
|
|
7025
|
+
for (const key of schemaKeys) {
|
|
7026
|
+
const value = task2.runInputData[key];
|
|
7027
|
+
const li = inputs.createListItem("", "padding-left: 20px;");
|
|
7028
|
+
li.inputText(`${key}: `);
|
|
7029
|
+
const inputInboundDataflows = allInboundDataflows?.filter((e) => e.targetTaskPortId === key);
|
|
7030
|
+
if (inputInboundDataflows) {
|
|
7031
|
+
const sources = [];
|
|
7032
|
+
const sourceValues = [];
|
|
7033
|
+
inputInboundDataflows.forEach((df) => {
|
|
7034
|
+
const sourceTask = config?.graph?.getTask(df.sourceTaskId);
|
|
7035
|
+
sources.push(`${sourceTask?.type}->Output{${df.sourceTaskPortId}}`);
|
|
7036
|
+
if (df.status === TaskStatus.COMPLETED) {
|
|
7037
|
+
sourceValues.push(df.value);
|
|
7038
|
+
}
|
|
7039
|
+
});
|
|
7040
|
+
if (sources.length > 1) {
|
|
7041
|
+
if (sourceValues.length > 0) {
|
|
7042
|
+
li.createValueObject(sourceValues);
|
|
7043
|
+
li.createTextChild(" ");
|
|
7044
|
+
}
|
|
7045
|
+
li.createTextChild(`from [${sources.join(", ")}]`);
|
|
7046
|
+
} else if (sources.length === 1) {
|
|
7047
|
+
if (sourceValues.length > 0) {
|
|
7048
|
+
li.createValueObject(sourceValues[0]);
|
|
7049
|
+
li.createTextChild(" ");
|
|
7050
|
+
}
|
|
7051
|
+
li.createTextChild("from " + sources[0]);
|
|
7052
|
+
} else {
|
|
7053
|
+
li.createValueObject(value);
|
|
7054
|
+
}
|
|
7055
|
+
} else {
|
|
7056
|
+
li.createValueObject(value);
|
|
7057
|
+
}
|
|
7058
|
+
}
|
|
7059
|
+
const outputsList = body.createStyledList("Outputs:");
|
|
7060
|
+
const outputSchema = task2.outputSchema();
|
|
7061
|
+
const outputProperties = getSchemaProperties(outputSchema);
|
|
7062
|
+
const outputKeys = outputProperties !== null ? Object.keys(outputProperties) : outputSchema === true ? Object.keys(task2.runOutputData || {}) : [];
|
|
7063
|
+
for (const key of outputKeys) {
|
|
7064
|
+
const value = task2.runOutputData[key];
|
|
7065
|
+
const li = outputsList.createListItem("", "padding-left: 20px;");
|
|
7066
|
+
li.outputText(`${key}: `);
|
|
7067
|
+
li.createValueObject(value);
|
|
7068
|
+
}
|
|
7069
|
+
const taskConfig = body.createStyledList("Config:");
|
|
7070
|
+
for (const [key, value] of Object.entries(task2.config)) {
|
|
7071
|
+
if (value === undefined)
|
|
7072
|
+
continue;
|
|
7073
|
+
const li = taskConfig.createListItem("", "padding-left: 20px;");
|
|
7074
|
+
li.inputText(`${key}: `);
|
|
7075
|
+
li.createValueObject(value);
|
|
7076
|
+
}
|
|
7077
|
+
body.createStatusListItem(task2.status);
|
|
7078
|
+
if (task2.startedAt || task2.completedAt) {
|
|
7079
|
+
const timing = body.createStyledList("Timing:");
|
|
7080
|
+
if (task2.startedAt) {
|
|
7081
|
+
const li = timing.createListItem("", "padding-left: 20px;");
|
|
7082
|
+
li.inputText("startedAt: ");
|
|
7083
|
+
li.createTextChild(task2.startedAt.toISOString());
|
|
7084
|
+
}
|
|
7085
|
+
if (task2.completedAt) {
|
|
7086
|
+
const li = timing.createListItem("", "padding-left: 20px;");
|
|
7087
|
+
li.inputText("completedAt: ");
|
|
7088
|
+
li.createTextChild(task2.completedAt.toISOString());
|
|
7089
|
+
}
|
|
7090
|
+
if (task2.startedAt && task2.completedAt) {
|
|
7091
|
+
const durationMs = task2.completedAt.getTime() - task2.startedAt.getTime();
|
|
7092
|
+
const li = timing.createListItem("", "padding-left: 20px;");
|
|
7093
|
+
li.highlightText("duration: ");
|
|
7094
|
+
li.createTextChild(formatDuration(durationMs));
|
|
7095
|
+
}
|
|
7096
|
+
}
|
|
7097
|
+
const dag = task2.subGraph?._dag;
|
|
7098
|
+
if (dag && dag.getNodes().length > 0)
|
|
7099
|
+
body.createObjectTag(dag);
|
|
7100
|
+
return body.toJsonML();
|
|
7101
|
+
}
|
|
7102
|
+
}
|
|
7103
|
+
|
|
7104
|
+
class DAGConsoleFormatter extends ConsoleFormatter {
|
|
7105
|
+
header(obj, config) {
|
|
7106
|
+
if (obj instanceof DirectedAcyclicGraph2) {
|
|
7107
|
+
const header = new JsonMLElement("div");
|
|
7108
|
+
header.createTextChild("DAG");
|
|
7109
|
+
return header.toJsonML();
|
|
7110
|
+
}
|
|
7111
|
+
return null;
|
|
7112
|
+
}
|
|
7113
|
+
hasBody(value, config) {
|
|
7114
|
+
return true;
|
|
7115
|
+
}
|
|
7116
|
+
body(obj, config) {
|
|
7117
|
+
const body = new JsonMLElement("div");
|
|
7118
|
+
body.createStyledList();
|
|
7119
|
+
const dag = obj;
|
|
7120
|
+
if (dag.getNodes().length > 0) {
|
|
7121
|
+
const { dataURL, height } = generateGraphImage(dag);
|
|
7122
|
+
if (dataURL) {
|
|
7123
|
+
const imageTag = body.createChild("div");
|
|
7124
|
+
imageTag.addAttribute("style", `background-image: url(${dataURL}); background-size: cover; background-position: center; width: 800px; height: ${height}px;`);
|
|
7125
|
+
}
|
|
7126
|
+
}
|
|
7127
|
+
return body.toJsonML();
|
|
7128
|
+
}
|
|
7129
|
+
}
|
|
7130
|
+
|
|
7131
|
+
class DataflowConsoleFormatter extends ConsoleFormatter {
|
|
7132
|
+
header(obj, config) {
|
|
7133
|
+
if (obj instanceof Dataflow) {
|
|
7134
|
+
const header = new JsonMLElement("div");
|
|
7135
|
+
header.highlightText("Dataflow ");
|
|
7136
|
+
header.inputText(`${obj.sourceTaskId}.${obj.sourceTaskPortId}`);
|
|
7137
|
+
header.createTextChild(" -> ");
|
|
7138
|
+
header.outputText(`${obj.targetTaskId}.${obj.targetTaskPortId}`);
|
|
7139
|
+
if (obj.status === TaskStatus.COMPLETED) {
|
|
7140
|
+
header.greyText(" = ");
|
|
7141
|
+
header.createValueObject(obj.value);
|
|
7142
|
+
}
|
|
7143
|
+
return header.toJsonML();
|
|
7144
|
+
}
|
|
7145
|
+
return null;
|
|
7146
|
+
}
|
|
7147
|
+
hasBody(value, config) {
|
|
7148
|
+
return true;
|
|
7149
|
+
}
|
|
7150
|
+
body(obj, config) {
|
|
7151
|
+
return null;
|
|
7152
|
+
}
|
|
7153
|
+
}
|
|
7154
|
+
|
|
7155
|
+
class ReactElementConsoleFormatter extends ConsoleFormatter {
|
|
7156
|
+
header(obj, config) {
|
|
7157
|
+
const reactEl = obj;
|
|
7158
|
+
if (reactEl?.$$typeof?.toString() === "Symbol(react.transitional.element)" && !config?.parent) {
|
|
7159
|
+
const header = new JsonMLElement("div");
|
|
7160
|
+
const isMemo = reactEl.type?.$$typeof?.toString() === "Symbol(react.memo)";
|
|
7161
|
+
const name = !isMemo ? reactEl.displayName || reactEl.type?.displayName || reactEl.type?.name : reactEl.type?.type?.displayName || reactEl.type?.type?.name;
|
|
7162
|
+
header.greyText(`<`);
|
|
7163
|
+
header.sectionHeader(`${name}`);
|
|
7164
|
+
header.greyText(`/>`);
|
|
7165
|
+
if (reactEl.key) {
|
|
7166
|
+
header.createTextChild(" ");
|
|
7167
|
+
header.inputText(`key={${reactEl.key}}`);
|
|
7168
|
+
}
|
|
7169
|
+
if (isMemo) {
|
|
7170
|
+
header.createTextChild(" ");
|
|
7171
|
+
header.pill(`Memo`);
|
|
7172
|
+
}
|
|
7173
|
+
return header.toJsonML();
|
|
7174
|
+
}
|
|
7175
|
+
return null;
|
|
7176
|
+
}
|
|
7177
|
+
hasBody(value, config) {
|
|
7178
|
+
return true;
|
|
7179
|
+
}
|
|
7180
|
+
body(obj, config) {
|
|
7181
|
+
const body = new JsonMLElement("div");
|
|
7182
|
+
const props = body.createStyledList("Props:");
|
|
7183
|
+
const reactEl = obj;
|
|
7184
|
+
props.propertyBlock(reactEl.props ?? {});
|
|
7185
|
+
return body.toJsonML();
|
|
7186
|
+
}
|
|
7187
|
+
}
|
|
7188
|
+
|
|
7189
|
+
class JsonMLElement {
|
|
7190
|
+
_attributes;
|
|
7191
|
+
_jsonML;
|
|
7192
|
+
static getColors() {
|
|
7193
|
+
const dark = isDarkMode();
|
|
7194
|
+
return {
|
|
7195
|
+
grey: dark ? "#aaa" : "#333",
|
|
7196
|
+
inputColor: dark ? "#ada" : "#363",
|
|
7197
|
+
outputColor: dark ? "#caa" : "#633",
|
|
7198
|
+
yellow: dark ? "#f3ce49" : "#a68307",
|
|
7199
|
+
undefined: "#888"
|
|
7200
|
+
};
|
|
7201
|
+
}
|
|
7202
|
+
constructor(tagName) {
|
|
7203
|
+
this._attributes = {};
|
|
7204
|
+
this._jsonML = [tagName, this._attributes];
|
|
7205
|
+
}
|
|
7206
|
+
coloredText(text, color) {
|
|
7207
|
+
this.createChild("span").setStyle(`color:${color};`).createTextChild(text);
|
|
7208
|
+
return this;
|
|
7209
|
+
}
|
|
7210
|
+
styledText(text, style) {
|
|
7211
|
+
this.createChild("span").setStyle(style).createTextChild(text);
|
|
7212
|
+
return this;
|
|
7213
|
+
}
|
|
7214
|
+
inputText(text) {
|
|
7215
|
+
const colors = JsonMLElement.getColors();
|
|
7216
|
+
return this.coloredText(text, colors.inputColor);
|
|
7217
|
+
}
|
|
7218
|
+
outputText(text) {
|
|
7219
|
+
const colors = JsonMLElement.getColors();
|
|
7220
|
+
return this.coloredText(text, colors.outputColor);
|
|
7221
|
+
}
|
|
7222
|
+
greyText(text) {
|
|
7223
|
+
const colors = JsonMLElement.getColors();
|
|
7224
|
+
return this.coloredText(text, colors.grey);
|
|
7225
|
+
}
|
|
7226
|
+
highlightText(text) {
|
|
7227
|
+
const colors = JsonMLElement.getColors();
|
|
7228
|
+
return this.coloredText(text, colors.yellow);
|
|
7229
|
+
}
|
|
7230
|
+
sectionHeader(text) {
|
|
7231
|
+
return this.styledText(text, "font-weight: bold;");
|
|
7232
|
+
}
|
|
7233
|
+
pill(text) {
|
|
7234
|
+
return this.styledText(text, "color: #009; background-color: #ccf; padding: 2px 4px; border-radius: 4px; font-size: 0.7em;");
|
|
7235
|
+
}
|
|
7236
|
+
methodSignature(name, params = "") {
|
|
7237
|
+
const colors = JsonMLElement.getColors();
|
|
7238
|
+
this.styledText("." + name, `font-weight: bold;color:${colors.yellow}`);
|
|
7239
|
+
if (params)
|
|
7240
|
+
this.greyText(`(${params})`);
|
|
7241
|
+
return this;
|
|
7242
|
+
}
|
|
7243
|
+
parameterList(params, isOutput = false) {
|
|
7244
|
+
params.forEach((param, i) => {
|
|
7245
|
+
if (i > 0)
|
|
7246
|
+
this.greyText(`, `);
|
|
7247
|
+
if (isOutput) {
|
|
7248
|
+
this.outputText(param.name);
|
|
7249
|
+
} else {
|
|
7250
|
+
this.inputText(param.name);
|
|
7251
|
+
}
|
|
7252
|
+
this.greyText(`: `);
|
|
7253
|
+
this.createValueObject(param.value);
|
|
7254
|
+
});
|
|
7255
|
+
return this;
|
|
7256
|
+
}
|
|
7257
|
+
propertyBlock(params) {
|
|
7258
|
+
for (const [key, value] of Object.entries(params)) {
|
|
7259
|
+
const item = this.createListItem("");
|
|
7260
|
+
item.inputText(key);
|
|
7261
|
+
item.greyText(`: `);
|
|
7262
|
+
item.createValueObject(value);
|
|
7263
|
+
}
|
|
7264
|
+
return this;
|
|
7265
|
+
}
|
|
7266
|
+
createListItem(text, style) {
|
|
7267
|
+
const li = this.createChild("li").setStyle(`padding-left: 10px;${style ? " " + style : ""}`);
|
|
7268
|
+
if (text)
|
|
7269
|
+
li.createTextChild(text);
|
|
7270
|
+
return li;
|
|
7271
|
+
}
|
|
7272
|
+
createHighlightedListItem(text) {
|
|
7273
|
+
const colors = JsonMLElement.getColors();
|
|
7274
|
+
this.createChild("li").setStyle(`color:${colors.yellow}; padding-left: 10px;`).createTextChild(text);
|
|
7275
|
+
return this;
|
|
7276
|
+
}
|
|
7277
|
+
createStatusListItem(text) {
|
|
7278
|
+
this.createStyledList("Status: ");
|
|
7279
|
+
let color = "grey";
|
|
7280
|
+
switch (text) {
|
|
7281
|
+
case TaskStatus.COMPLETED:
|
|
7282
|
+
color = "green";
|
|
7283
|
+
break;
|
|
7284
|
+
case TaskStatus.ABORTING:
|
|
7285
|
+
case TaskStatus.FAILED:
|
|
7286
|
+
color = "red";
|
|
7287
|
+
break;
|
|
7288
|
+
default:
|
|
7289
|
+
color = "grey";
|
|
7290
|
+
}
|
|
7291
|
+
return this.createListItem(text, `padding-left: 30px;color: ${color};`);
|
|
7292
|
+
}
|
|
7293
|
+
createStyledList(title) {
|
|
7294
|
+
const list = this.createChild("ol").setStyle("list-style-type: none; padding-left: 10px;");
|
|
7295
|
+
if (title)
|
|
7296
|
+
list.createTextChild(title);
|
|
7297
|
+
return list;
|
|
7298
|
+
}
|
|
7299
|
+
objectBraces(content) {
|
|
7300
|
+
this.greyText("{ ");
|
|
7301
|
+
content(this);
|
|
7302
|
+
this.greyText(" }");
|
|
7303
|
+
return this;
|
|
7304
|
+
}
|
|
7305
|
+
functionCall(content) {
|
|
7306
|
+
this.greyText("(");
|
|
7307
|
+
content(this);
|
|
7308
|
+
this.greyText(")");
|
|
7309
|
+
return this;
|
|
7310
|
+
}
|
|
7311
|
+
createChild(tagName) {
|
|
7312
|
+
const c = new JsonMLElement(tagName);
|
|
7313
|
+
this._jsonML.push(c.toJsonML());
|
|
7314
|
+
return c;
|
|
7315
|
+
}
|
|
7316
|
+
createObjectTag(object, config) {
|
|
7317
|
+
const tag = this.createChild("object");
|
|
7318
|
+
tag.addAttribute("object", object);
|
|
7319
|
+
if (config) {
|
|
7320
|
+
tag.addAttribute("config", config);
|
|
7321
|
+
}
|
|
7322
|
+
return tag;
|
|
7323
|
+
}
|
|
7324
|
+
createValueObject(value, config) {
|
|
7325
|
+
if (Array.isArray(value))
|
|
7326
|
+
return this.createArrayChild(value, config);
|
|
7327
|
+
if (typeof value === "undefined") {
|
|
7328
|
+
const colors = JsonMLElement.getColors();
|
|
7329
|
+
return this.createChild("span").setStyle(`color:${colors.undefined};`).createTextChild("undefined");
|
|
7330
|
+
}
|
|
7331
|
+
return this.createObjectTag(value, config);
|
|
7332
|
+
}
|
|
7333
|
+
setStyle(style) {
|
|
7334
|
+
this._attributes["style"] = style;
|
|
7335
|
+
return this;
|
|
7336
|
+
}
|
|
7337
|
+
addAttribute(key, value) {
|
|
7338
|
+
this._attributes[key] = value;
|
|
7339
|
+
return this;
|
|
7340
|
+
}
|
|
7341
|
+
createTextChild(text) {
|
|
7342
|
+
this._jsonML.push(text + "");
|
|
7343
|
+
return this;
|
|
7344
|
+
}
|
|
7345
|
+
createArrayChild(array, config) {
|
|
7346
|
+
const j = new JsonMLElement("span");
|
|
7347
|
+
j.createTextChild("[");
|
|
7348
|
+
for (let i = 0;i < array.length; ++i) {
|
|
7349
|
+
if (i != 0)
|
|
7350
|
+
j.createTextChild(", ");
|
|
7351
|
+
j.createValueObject(array[i], config);
|
|
7352
|
+
}
|
|
7353
|
+
j.createTextChild("]");
|
|
7354
|
+
this._jsonML.push(j.toJsonML());
|
|
7355
|
+
return j;
|
|
7356
|
+
}
|
|
7357
|
+
toJsonML() {
|
|
7358
|
+
return this._jsonML;
|
|
7359
|
+
}
|
|
7360
|
+
}
|
|
7361
|
+
function computeLayout(graph, canvasWidth) {
|
|
7362
|
+
const positions = {};
|
|
7363
|
+
const layers = new Map;
|
|
7364
|
+
const depths = {};
|
|
7365
|
+
for (const node of graph.topologicallySortedNodes()) {
|
|
7366
|
+
const incomingEdges = graph.inEdges(node.config.id).map(([from]) => from);
|
|
7367
|
+
const depth = incomingEdges.length > 0 ? Math.max(...incomingEdges.map((from) => depths[from])) + 1 : 0;
|
|
7368
|
+
depths[node.config.id] = depth;
|
|
7369
|
+
if (!layers.has(depth))
|
|
7370
|
+
layers.set(depth, []);
|
|
7371
|
+
layers.get(depth).push(node.config.id);
|
|
7372
|
+
}
|
|
7373
|
+
const totalLayers = layers.size;
|
|
7374
|
+
const layerSpacing = totalLayers > 1 ? Math.max(canvasWidth / totalLayers, 150) : 150;
|
|
7375
|
+
const maxNodesInLayer = Math.max(...Array.from(layers.values()).map((layer) => layer.length));
|
|
7376
|
+
const nodeSpacing = 100;
|
|
7377
|
+
const requiredHeight = maxNodesInLayer * nodeSpacing + 100;
|
|
7378
|
+
layers.forEach((layerNodes, layerIndex) => {
|
|
7379
|
+
const yStart = (requiredHeight - layerNodes.length * nodeSpacing) / 2;
|
|
7380
|
+
layerNodes.forEach((nodeId, index) => {
|
|
7381
|
+
positions[nodeId] = {
|
|
7382
|
+
x: layerIndex * layerSpacing + layerSpacing / 2,
|
|
7383
|
+
y: yStart + index * nodeSpacing
|
|
7384
|
+
};
|
|
7385
|
+
});
|
|
7386
|
+
});
|
|
7387
|
+
return { positions, requiredHeight };
|
|
7388
|
+
}
|
|
7389
|
+
function generateGraphImage(graph, width = 800) {
|
|
7390
|
+
const ratio = window.devicePixelRatio || 1;
|
|
7391
|
+
const { positions, requiredHeight } = computeLayout(graph, width);
|
|
7392
|
+
const canvas = document.createElement("canvas");
|
|
7393
|
+
canvas.width = width * ratio;
|
|
7394
|
+
canvas.height = requiredHeight * ratio;
|
|
7395
|
+
const ctx = canvas.getContext("2d");
|
|
7396
|
+
if (!ctx) {
|
|
7397
|
+
console.error("Canvas context is not available.");
|
|
7398
|
+
return { dataURL: "", height: requiredHeight };
|
|
7399
|
+
}
|
|
7400
|
+
ctx.scale(ratio, ratio);
|
|
7401
|
+
ctx.clearRect(0, 0, width, requiredHeight);
|
|
7402
|
+
ctx.strokeStyle = "#aaa";
|
|
7403
|
+
ctx.lineWidth = 2;
|
|
7404
|
+
for (const [source, target] of graph.getEdges()) {
|
|
7405
|
+
const fromNode = positions[source];
|
|
7406
|
+
const toNode = positions[target];
|
|
7407
|
+
if (fromNode && toNode) {
|
|
7408
|
+
ctx.beginPath();
|
|
7409
|
+
ctx.moveTo(fromNode.x, fromNode.y);
|
|
7410
|
+
ctx.lineTo(toNode.x, toNode.y);
|
|
7411
|
+
ctx.stroke();
|
|
7412
|
+
}
|
|
7413
|
+
}
|
|
7414
|
+
ctx.fillStyle = "#3498db";
|
|
7415
|
+
for (const node of graph.getNodes()) {
|
|
7416
|
+
const pos = positions[node.config.id];
|
|
7417
|
+
ctx.beginPath();
|
|
7418
|
+
ctx.arc(pos.x, pos.y, 10, 0, Math.PI * 2);
|
|
7419
|
+
ctx.fill();
|
|
7420
|
+
ctx.fillStyle = "black";
|
|
7421
|
+
ctx.font = `12px Arial`;
|
|
7422
|
+
ctx.textAlign = "center";
|
|
7423
|
+
ctx.fillText(node.type ?? "", pos.x, pos.y - 15);
|
|
7424
|
+
ctx.fillStyle = "#3498db";
|
|
7425
|
+
}
|
|
7426
|
+
const dataURL = canvas.toDataURL("image/png");
|
|
7427
|
+
return { dataURL, height: requiredHeight };
|
|
7428
|
+
}
|
|
7429
|
+
function installDevToolsFormatters() {
|
|
7430
|
+
window.devtoolsFormatters = window.devtoolsFormatters || [];
|
|
7431
|
+
window.devtoolsFormatters.push(new WorkflowAPIConsoleFormatter, new CreateWorkflowConsoleFormatter, new WorkflowConsoleFormatter, new TaskConsoleFormatter, new ReactElementConsoleFormatter, new DataflowConsoleFormatter, new DAGConsoleFormatter);
|
|
7432
|
+
}
|
|
6794
7433
|
export {
|
|
6795
7434
|
wrapSchemaInArray,
|
|
6796
7435
|
whileTaskConfigSchema,
|
|
@@ -6815,6 +7454,8 @@ export {
|
|
|
6815
7454
|
isStrictArraySchema,
|
|
6816
7455
|
isIterationProperty,
|
|
6817
7456
|
isFlexibleSchema,
|
|
7457
|
+
isDarkMode,
|
|
7458
|
+
installDevToolsFormatters,
|
|
6818
7459
|
hasVectorOutput,
|
|
6819
7460
|
hasVectorLikeInput,
|
|
6820
7461
|
hasStructuredOutput,
|
|
@@ -6916,4 +7557,4 @@ export {
|
|
|
6916
7557
|
ConditionalTask
|
|
6917
7558
|
};
|
|
6918
7559
|
|
|
6919
|
-
//# debugId=
|
|
7560
|
+
//# debugId=794A622164E9E85664756E2164756E21
|