@workglow/task-graph 0.0.124 → 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 +642 -1
- package/dist/browser.js.map +5 -4
- package/dist/debug/console/ConsoleFormatters.d.ts +45 -0
- package/dist/debug/console/ConsoleFormatters.d.ts.map +1 -0
- 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/README.md
CHANGED
|
@@ -32,6 +32,10 @@ bun add @workglow/task-graph
|
|
|
32
32
|
yarn add @workglow/task-graph
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
+
### Browser debugging
|
|
36
|
+
|
|
37
|
+
For Chrome DevTools custom formatters (`Workflow`, `TaskGraph`, `Task`, etc.), import `installDevToolsFormatters` from **`@workglow/task-graph`** (browser build only). See [`src/debug/README.md`](./src/debug/README.md).
|
|
38
|
+
|
|
35
39
|
## Quick Start
|
|
36
40
|
|
|
37
41
|
Here's a simple example that demonstrates the core concepts:
|
package/dist/browser.d.ts
CHANGED
package/dist/browser.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,UAAU,CAAC"}
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,UAAU,CAAC;AACzB,cAAc,mCAAmC,CAAC"}
|
package/dist/browser.js
CHANGED
|
@@ -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
|