@bian-womp/spark-workbench 0.2.94 → 0.3.0
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/lib/cjs/index.cjs +204 -240
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/cjs/src/examples/reactflow/App.d.ts.map +1 -1
- package/lib/cjs/src/index.d.ts +1 -0
- package/lib/cjs/src/index.d.ts.map +1 -1
- package/lib/cjs/src/misc/DefaultNodeHeader.d.ts +1 -2
- package/lib/cjs/src/misc/DefaultNodeHeader.d.ts.map +1 -1
- package/lib/cjs/src/misc/WorkbenchCanvas.d.ts.map +1 -1
- package/lib/cjs/src/misc/WorkbenchStudio.d.ts +1 -3
- package/lib/cjs/src/misc/WorkbenchStudio.d.ts.map +1 -1
- package/lib/cjs/src/misc/context/WorkbenchContext.d.ts +8 -6
- package/lib/cjs/src/misc/context/WorkbenchContext.d.ts.map +1 -1
- package/lib/cjs/src/misc/context/WorkbenchContext.provider.d.ts.map +1 -1
- package/lib/cjs/src/misc/context-menu/ContextMenuHandlers.d.ts +6 -2
- package/lib/cjs/src/misc/context-menu/ContextMenuHandlers.d.ts.map +1 -1
- package/lib/cjs/src/misc/context-menu/ContextMenuHelpers.d.ts +1 -1
- package/lib/cjs/src/misc/context-menu/ContextMenuHelpers.d.ts.map +1 -1
- package/lib/cjs/src/misc/context-menu/NodeContextMenu.d.ts +1 -1
- package/lib/cjs/src/misc/context-menu/NodeContextMenu.d.ts.map +1 -1
- package/lib/cjs/src/runtime/AbstractGraphRunner.d.ts +9 -7
- package/lib/cjs/src/runtime/AbstractGraphRunner.d.ts.map +1 -1
- package/lib/cjs/src/runtime/IGraphRunner.d.ts +18 -7
- package/lib/cjs/src/runtime/IGraphRunner.d.ts.map +1 -1
- package/lib/cjs/src/runtime/LocalGraphRunner.d.ts +7 -4
- package/lib/cjs/src/runtime/LocalGraphRunner.d.ts.map +1 -1
- package/lib/cjs/src/runtime/RemoteGraphRunner.d.ts +11 -9
- package/lib/cjs/src/runtime/RemoteGraphRunner.d.ts.map +1 -1
- package/lib/esm/index.js +207 -243
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/src/examples/reactflow/App.d.ts.map +1 -1
- package/lib/esm/src/index.d.ts +1 -0
- package/lib/esm/src/index.d.ts.map +1 -1
- package/lib/esm/src/misc/DefaultNodeHeader.d.ts +1 -2
- package/lib/esm/src/misc/DefaultNodeHeader.d.ts.map +1 -1
- package/lib/esm/src/misc/WorkbenchCanvas.d.ts.map +1 -1
- package/lib/esm/src/misc/WorkbenchStudio.d.ts +1 -3
- package/lib/esm/src/misc/WorkbenchStudio.d.ts.map +1 -1
- package/lib/esm/src/misc/context/WorkbenchContext.d.ts +8 -6
- package/lib/esm/src/misc/context/WorkbenchContext.d.ts.map +1 -1
- package/lib/esm/src/misc/context/WorkbenchContext.provider.d.ts.map +1 -1
- package/lib/esm/src/misc/context-menu/ContextMenuHandlers.d.ts +6 -2
- package/lib/esm/src/misc/context-menu/ContextMenuHandlers.d.ts.map +1 -1
- package/lib/esm/src/misc/context-menu/ContextMenuHelpers.d.ts +1 -1
- package/lib/esm/src/misc/context-menu/ContextMenuHelpers.d.ts.map +1 -1
- package/lib/esm/src/misc/context-menu/NodeContextMenu.d.ts +1 -1
- package/lib/esm/src/misc/context-menu/NodeContextMenu.d.ts.map +1 -1
- package/lib/esm/src/runtime/AbstractGraphRunner.d.ts +9 -7
- package/lib/esm/src/runtime/AbstractGraphRunner.d.ts.map +1 -1
- package/lib/esm/src/runtime/IGraphRunner.d.ts +18 -7
- package/lib/esm/src/runtime/IGraphRunner.d.ts.map +1 -1
- package/lib/esm/src/runtime/LocalGraphRunner.d.ts +7 -4
- package/lib/esm/src/runtime/LocalGraphRunner.d.ts.map +1 -1
- package/lib/esm/src/runtime/RemoteGraphRunner.d.ts +11 -9
- package/lib/esm/src/runtime/RemoteGraphRunner.d.ts.map +1 -1
- package/package.json +4 -4
package/lib/cjs/index.cjs
CHANGED
|
@@ -927,31 +927,21 @@ class AbstractGraphRunner {
|
|
|
927
927
|
this.engine.dispose();
|
|
928
928
|
this.engine = undefined;
|
|
929
929
|
// Emit status but keep runtime alive
|
|
930
|
-
if (this.
|
|
931
|
-
this.
|
|
932
|
-
this.emit("status", { running: false,
|
|
933
|
-
}
|
|
934
|
-
}
|
|
935
|
-
async switchEngine(opts) {
|
|
936
|
-
if (!this.engine || !this.runtime) {
|
|
937
|
-
throw new Error("No engine running to switch from");
|
|
938
|
-
}
|
|
939
|
-
// Wait for current engine to be idle
|
|
940
|
-
await this.whenIdle();
|
|
941
|
-
// Capture current state
|
|
942
|
-
const currentInputs = { ...this.stagedInputs };
|
|
943
|
-
// Stop current engine
|
|
944
|
-
this.stop();
|
|
945
|
-
// Ensure runtime is in a clean state (resumed)
|
|
946
|
-
this.runtime.resume();
|
|
947
|
-
// Create and launch new engine (to be implemented by subclasses)
|
|
948
|
-
await this.createAndLaunchEngine(opts);
|
|
949
|
-
// Re-apply staged inputs to new engine using runner's setInputs method
|
|
950
|
-
// This ensures consistency and proper handling of staged inputs
|
|
951
|
-
for (const [nodeId, map] of Object.entries(currentInputs)) {
|
|
952
|
-
await this.setInputs(nodeId, map);
|
|
930
|
+
if (this.runMode) {
|
|
931
|
+
this.runMode = undefined;
|
|
932
|
+
this.emit("status", { running: false, runMode: undefined });
|
|
953
933
|
}
|
|
954
934
|
}
|
|
935
|
+
setRunMode(runMode) {
|
|
936
|
+
if (!this.engine) {
|
|
937
|
+
throw new Error("Cannot set run mode: engine not running");
|
|
938
|
+
}
|
|
939
|
+
// Update engine run mode (this will update pause/resume state)
|
|
940
|
+
this.engine.setRunMode(runMode);
|
|
941
|
+
// Update local state and emit status event
|
|
942
|
+
this.runMode = runMode;
|
|
943
|
+
this.emit("status", { running: true, runMode: this.runMode });
|
|
944
|
+
}
|
|
955
945
|
getInputDefaults(def) {
|
|
956
946
|
const out = {};
|
|
957
947
|
for (const n of def.nodes) {
|
|
@@ -980,16 +970,16 @@ class AbstractGraphRunner {
|
|
|
980
970
|
this.engine = undefined;
|
|
981
971
|
this.runtime?.dispose();
|
|
982
972
|
this.runtime = undefined;
|
|
983
|
-
if (this.
|
|
984
|
-
this.
|
|
985
|
-
this.emit("status", { running: false,
|
|
973
|
+
if (this.runMode) {
|
|
974
|
+
this.runMode = undefined;
|
|
975
|
+
this.emit("status", { running: false, runMode: undefined });
|
|
986
976
|
}
|
|
987
977
|
}
|
|
988
978
|
isRunning() {
|
|
989
979
|
return !!this.engine;
|
|
990
980
|
}
|
|
991
|
-
|
|
992
|
-
return this.
|
|
981
|
+
getRunMode() {
|
|
982
|
+
return this.runMode;
|
|
993
983
|
}
|
|
994
984
|
// Optional undo/redo support
|
|
995
985
|
async undo() {
|
|
@@ -1084,7 +1074,7 @@ class LocalGraphRunner extends AbstractGraphRunner {
|
|
|
1084
1074
|
if (!this.runtime)
|
|
1085
1075
|
throw new Error("Runtime not built");
|
|
1086
1076
|
// Use shared engine factory
|
|
1087
|
-
this.engine = sparkGraph.
|
|
1077
|
+
this.engine = new sparkGraph.UnifiedEngine(this.runtime, opts?.runMode);
|
|
1088
1078
|
if (!this.engine)
|
|
1089
1079
|
throw new Error("Failed to create engine");
|
|
1090
1080
|
this.engine.on("value", (e) => this.emit("value", e));
|
|
@@ -1092,36 +1082,34 @@ class LocalGraphRunner extends AbstractGraphRunner {
|
|
|
1092
1082
|
this.engine.on("invalidate", (e) => this.emit("invalidate", e));
|
|
1093
1083
|
this.engine.on("stats", (e) => this.emit("stats", e));
|
|
1094
1084
|
this.engine.launch(opts?.invalidate);
|
|
1095
|
-
this.
|
|
1096
|
-
this.emit("status", { running: true,
|
|
1085
|
+
this.runMode = opts?.runMode ?? "manual";
|
|
1086
|
+
this.emit("status", { running: true, runMode: this.runMode });
|
|
1097
1087
|
for (const [nodeId, map] of Object.entries(this.stagedInputs)) {
|
|
1098
1088
|
this.engine.setInputs(nodeId, map);
|
|
1099
1089
|
}
|
|
1100
1090
|
}
|
|
1101
|
-
async
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
await eng.step();
|
|
1091
|
+
async computeNode(nodeId, options) {
|
|
1092
|
+
if (this.engine)
|
|
1093
|
+
await this.engine.computeNode(nodeId, options);
|
|
1105
1094
|
}
|
|
1106
|
-
async
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
await eng.computeNode(nodeId);
|
|
1095
|
+
async runFromHere(nodeId) {
|
|
1096
|
+
if (this.engine)
|
|
1097
|
+
await this.engine.runFromHere(nodeId);
|
|
1110
1098
|
}
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1099
|
+
cancelNodeRuns(nodeIds) {
|
|
1100
|
+
if (this.engine) {
|
|
1101
|
+
this.engine.cancelNodeRuns(nodeIds);
|
|
1102
|
+
}
|
|
1115
1103
|
}
|
|
1116
1104
|
getOutputs(def) {
|
|
1117
1105
|
const out = {};
|
|
1118
|
-
if (!this.
|
|
1106
|
+
if (!this.engine)
|
|
1119
1107
|
return out;
|
|
1120
1108
|
for (const n of def.nodes) {
|
|
1121
1109
|
const desc = this.registry.nodes.get(n.typeId);
|
|
1122
1110
|
const handles = Object.keys(desc?.outputs ?? {});
|
|
1123
1111
|
for (const h of handles) {
|
|
1124
|
-
const v = this.
|
|
1112
|
+
const v = this.engine.getOutput(n.nodeId, h);
|
|
1125
1113
|
if (v !== undefined) {
|
|
1126
1114
|
if (!out[n.nodeId])
|
|
1127
1115
|
out[n.nodeId] = {};
|
|
@@ -1154,19 +1142,8 @@ class LocalGraphRunner extends AbstractGraphRunner {
|
|
|
1154
1142
|
return out;
|
|
1155
1143
|
}
|
|
1156
1144
|
triggerExternal(nodeId, event, options) {
|
|
1157
|
-
//
|
|
1158
|
-
|
|
1159
|
-
if (options?.dry && !wasPaused && this.runtime) {
|
|
1160
|
-
this.runtime.pause();
|
|
1161
|
-
}
|
|
1162
|
-
try {
|
|
1163
|
-
this.engine?.triggerExternal(nodeId, event);
|
|
1164
|
-
}
|
|
1165
|
-
finally {
|
|
1166
|
-
if (options?.dry && !wasPaused && this.runtime) {
|
|
1167
|
-
this.runtime.resume();
|
|
1168
|
-
}
|
|
1169
|
-
}
|
|
1145
|
+
// Engine handles dry option via AbstractEngine
|
|
1146
|
+
this.engine?.triggerExternal(nodeId, event, options);
|
|
1170
1147
|
}
|
|
1171
1148
|
// Batch update multiple inputs on a node and trigger a single run
|
|
1172
1149
|
setInputs(nodeId, inputs, options) {
|
|
@@ -1182,40 +1159,23 @@ class LocalGraphRunner extends AbstractGraphRunner {
|
|
|
1182
1159
|
this.stagedInputs[nodeId][handle] = value;
|
|
1183
1160
|
}
|
|
1184
1161
|
}
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
this.runtime.pause();
|
|
1189
|
-
}
|
|
1190
|
-
try {
|
|
1191
|
-
if (this.engine) {
|
|
1192
|
-
this.engine.setInputs(nodeId, inputs);
|
|
1193
|
-
}
|
|
1194
|
-
else {
|
|
1195
|
-
// Not running: emit a single synthetic value event per handle; UI will coalesce
|
|
1196
|
-
console.warn("Engine does not exists");
|
|
1197
|
-
for (const [handle, value] of Object.entries(inputs)) {
|
|
1198
|
-
this.emit("value", { nodeId, handle, value, io: "input" });
|
|
1199
|
-
}
|
|
1200
|
-
}
|
|
1162
|
+
if (this.engine) {
|
|
1163
|
+
// Engine handles dry option via AbstractEngine
|
|
1164
|
+
this.engine.setInputs(nodeId, inputs, options);
|
|
1201
1165
|
}
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1166
|
+
else {
|
|
1167
|
+
// Not running: emit a single synthetic value event per handle; UI will coalesce
|
|
1168
|
+
// Note: dry option doesn't apply when engine doesn't exist (no execution to prevent)
|
|
1169
|
+
console.warn("Engine does not exists");
|
|
1170
|
+
for (const [handle, value] of Object.entries(inputs)) {
|
|
1171
|
+
this.emit("value", { nodeId, handle, value, io: "input" });
|
|
1205
1172
|
}
|
|
1206
1173
|
}
|
|
1207
1174
|
}
|
|
1208
1175
|
copyOutputs(fromNodeId, toNodeId, options) {
|
|
1209
|
-
if (
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
const fromNode = this.runtime.getNodeData(fromNodeId);
|
|
1213
|
-
if (!fromNode?.outputs)
|
|
1214
|
-
return;
|
|
1215
|
-
// Copy outputs to target node using hydrate
|
|
1216
|
-
// hydrate already pauses internally, so we don't need to handle dry option here
|
|
1217
|
-
// reemit: !options?.dry means don't propagate downstream if dry mode
|
|
1218
|
-
this.runtime.hydrate({ outputs: { [toNodeId]: { ...fromNode.outputs } } }, { reemit: !options?.dry });
|
|
1176
|
+
if (this.engine) {
|
|
1177
|
+
this.engine.copyOutputs(fromNodeId, toNodeId, options);
|
|
1178
|
+
}
|
|
1219
1179
|
}
|
|
1220
1180
|
async snapshotFull() {
|
|
1221
1181
|
const def = undefined; // UI will supply def/positions on download for local
|
|
@@ -1316,7 +1276,7 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
1316
1276
|
}
|
|
1317
1277
|
this.registryFetching = true;
|
|
1318
1278
|
try {
|
|
1319
|
-
const desc = await client.describeRegistry();
|
|
1279
|
+
const desc = await client.api.describeRegistry();
|
|
1320
1280
|
// Register types
|
|
1321
1281
|
for (const t of desc.types) {
|
|
1322
1282
|
if (t.options) {
|
|
@@ -1418,7 +1378,7 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
1418
1378
|
}
|
|
1419
1379
|
}
|
|
1420
1380
|
/**
|
|
1421
|
-
* Build
|
|
1381
|
+
* Build RemoteRuntimeClient config from RemoteExecutionBackend config.
|
|
1422
1382
|
*/
|
|
1423
1383
|
buildClientConfig(backend) {
|
|
1424
1384
|
if (backend.kind === "remote-http") {
|
|
@@ -1441,7 +1401,7 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
1441
1401
|
*/
|
|
1442
1402
|
setupClientSubscriptions(client) {
|
|
1443
1403
|
// Subscribe to transport status changes
|
|
1444
|
-
// Convert
|
|
1404
|
+
// Convert RemoteRuntimeClient.TransportStatus to IGraphRunner.TransportStatus
|
|
1445
1405
|
// Only emit status if it matches this runner's ID
|
|
1446
1406
|
this.transportStatusUnsubscribe = client.onTransportStatus((status) => {
|
|
1447
1407
|
if (status.runnerId && status.runnerId !== this.runnerId)
|
|
@@ -1491,7 +1451,7 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
1491
1451
|
}
|
|
1492
1452
|
};
|
|
1493
1453
|
// Create client with wrapped custom event handler
|
|
1494
|
-
const client = new sparkRemote.
|
|
1454
|
+
const client = new sparkRemote.RemoteRuntimeClient(clientConfig, {
|
|
1495
1455
|
onCustomEvent: wrappedOnCustomEvent,
|
|
1496
1456
|
runnerId: this.runnerId,
|
|
1497
1457
|
});
|
|
@@ -1541,7 +1501,7 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
1541
1501
|
// Auto-handle registry-changed invalidations from remote
|
|
1542
1502
|
// We listen on invalidate and if reason matches, we rehydrate registry and emit a registry event
|
|
1543
1503
|
this.ensureClient().then(async (client) => {
|
|
1544
|
-
const eng = client.
|
|
1504
|
+
const eng = client.engine;
|
|
1545
1505
|
if (!this.listenersBound) {
|
|
1546
1506
|
eng.on("invalidate", async (e) => {
|
|
1547
1507
|
if (e.reason === "registry-changed") {
|
|
@@ -1605,7 +1565,7 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
1605
1565
|
// Remote: forward update and await completion
|
|
1606
1566
|
const client = await this.ensureClient();
|
|
1607
1567
|
try {
|
|
1608
|
-
await client.update(def, options);
|
|
1568
|
+
await client.api.update(def, options);
|
|
1609
1569
|
this.emit("invalidate", { reason: "graph-updated" });
|
|
1610
1570
|
this.lastDef = def;
|
|
1611
1571
|
}
|
|
@@ -1618,13 +1578,13 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
1618
1578
|
super.launch(def, opts);
|
|
1619
1579
|
// Remote: build remotely then launch
|
|
1620
1580
|
this.ensureClient().then(async (client) => {
|
|
1621
|
-
await client.build(def);
|
|
1581
|
+
await client.api.build(def);
|
|
1622
1582
|
// Signal UI after remote build as well
|
|
1623
1583
|
this.emit("invalidate", { reason: "graph-built" });
|
|
1624
1584
|
this.lastDef = def;
|
|
1625
1585
|
// Hydrate current remote inputs/outputs (including defaults) into cache
|
|
1626
1586
|
try {
|
|
1627
|
-
const snap = await client.snapshot();
|
|
1587
|
+
const snap = await client.api.snapshot();
|
|
1628
1588
|
for (const [nodeId, map] of Object.entries(snap.inputs || {})) {
|
|
1629
1589
|
for (const [handle, value] of Object.entries(map || {})) {
|
|
1630
1590
|
this.valueCache.set(`${nodeId}.${handle}`, {
|
|
@@ -1653,9 +1613,9 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
1653
1613
|
async createAndLaunchEngine(opts) {
|
|
1654
1614
|
const client = await this.ensureClient();
|
|
1655
1615
|
// Configure and launch engine on the backend
|
|
1656
|
-
await client.launch(opts);
|
|
1616
|
+
await client.api.launch(opts);
|
|
1657
1617
|
// Get the remote engine proxy and wire up event listeners
|
|
1658
|
-
const eng = client.
|
|
1618
|
+
const eng = client.engine;
|
|
1659
1619
|
if (!this.listenersBound) {
|
|
1660
1620
|
eng.on("value", (e) => {
|
|
1661
1621
|
this.valueCache.set(`${e.nodeId}.${e.handle}`, {
|
|
@@ -1671,11 +1631,11 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
1671
1631
|
this.listenersBound = true;
|
|
1672
1632
|
}
|
|
1673
1633
|
this.engine = eng;
|
|
1674
|
-
this.
|
|
1675
|
-
this.emit("status", { running: true,
|
|
1634
|
+
this.runMode = opts?.runMode ?? "manual";
|
|
1635
|
+
this.emit("status", { running: true, runMode: this.runMode });
|
|
1676
1636
|
// Re-apply staged inputs using client.setInputs for consistency
|
|
1677
1637
|
for (const [nodeId, map] of Object.entries(this.stagedInputs)) {
|
|
1678
|
-
await eng.setInputs(nodeId, map).catch(() => {
|
|
1638
|
+
await eng.setInputs(nodeId, map, undefined).catch(() => {
|
|
1679
1639
|
// Ignore errors during launch - inputs will be set when user calls setInputs
|
|
1680
1640
|
});
|
|
1681
1641
|
}
|
|
@@ -1698,45 +1658,27 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
1698
1658
|
await this.createAndLaunchEngine(opts);
|
|
1699
1659
|
});
|
|
1700
1660
|
}
|
|
1701
|
-
|
|
1661
|
+
setRunMode(runMode) {
|
|
1702
1662
|
if (!this.engine) {
|
|
1703
|
-
throw new Error("
|
|
1704
|
-
}
|
|
1705
|
-
// Wait for current engine to be idle
|
|
1706
|
-
await this.whenIdle();
|
|
1707
|
-
// Capture current state
|
|
1708
|
-
const currentInputs = { ...this.stagedInputs };
|
|
1709
|
-
// For remote runners, we cannot call this.stop() because it sends a Dispose
|
|
1710
|
-
// command that destroys the graphRuntime on the backend. Instead, we rely on
|
|
1711
|
-
// the backend's launch() method to dispose the old engine and create a new one.
|
|
1712
|
-
// Reconfigure engine on the backend (this will dispose old engine and create new one)
|
|
1713
|
-
const client = await this.ensureClient();
|
|
1714
|
-
await client.launch(opts);
|
|
1715
|
-
// Get the remote engine proxy (should be the same RemoteEngine instance)
|
|
1716
|
-
const eng = client.getEngine();
|
|
1717
|
-
// Update local state to reflect new engine kind
|
|
1718
|
-
// Note: The RemoteEngine instance itself doesn't change, but the backend engine does
|
|
1719
|
-
this.engine = eng;
|
|
1720
|
-
this.runningKind = opts?.engine ?? "push";
|
|
1721
|
-
this.emit("status", { running: true, engine: this.runningKind });
|
|
1722
|
-
// Re-apply staged inputs using client.setInputs for consistency
|
|
1723
|
-
for (const [nodeId, map] of Object.entries(currentInputs)) {
|
|
1724
|
-
await eng.setInputs(nodeId, map).catch(() => {
|
|
1725
|
-
// Ignore errors during engine switch - inputs will be set when user calls setInputs
|
|
1726
|
-
});
|
|
1663
|
+
throw new Error("Cannot set run mode: engine not running");
|
|
1727
1664
|
}
|
|
1665
|
+
// Update engine run mode (sends SetRunMode command to backend)
|
|
1666
|
+
this.engine.setRunMode(runMode);
|
|
1667
|
+
// Update local state and emit status event
|
|
1668
|
+
this.runMode = runMode;
|
|
1669
|
+
this.emit("status", { running: true, runMode: this.runMode });
|
|
1728
1670
|
}
|
|
1729
|
-
async
|
|
1671
|
+
async computeNode(nodeId, options) {
|
|
1730
1672
|
const client = await this.ensureClient();
|
|
1731
|
-
await client.
|
|
1673
|
+
await client.engine.computeNode(nodeId, options);
|
|
1732
1674
|
}
|
|
1733
|
-
async
|
|
1675
|
+
async runFromHere(nodeId) {
|
|
1734
1676
|
const client = await this.ensureClient();
|
|
1735
|
-
await client.
|
|
1677
|
+
await client.engine.runFromHere(nodeId);
|
|
1736
1678
|
}
|
|
1737
|
-
async
|
|
1679
|
+
async cancelNodeRuns(nodeIds) {
|
|
1738
1680
|
const client = await this.ensureClient();
|
|
1739
|
-
await client.
|
|
1681
|
+
await client.engine.cancelNodeRuns(nodeIds);
|
|
1740
1682
|
}
|
|
1741
1683
|
async setInputs(nodeId, inputs, options) {
|
|
1742
1684
|
// Update staged inputs (for getInputs to work correctly)
|
|
@@ -1752,7 +1694,7 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
1752
1694
|
}
|
|
1753
1695
|
try {
|
|
1754
1696
|
const client = await this.ensureClient();
|
|
1755
|
-
await client.
|
|
1697
|
+
await client.engine.setInputs(nodeId, inputs, options);
|
|
1756
1698
|
}
|
|
1757
1699
|
catch (err) {
|
|
1758
1700
|
// Emit synthetic events if connection fails
|
|
@@ -1764,20 +1706,20 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
1764
1706
|
}
|
|
1765
1707
|
async copyOutputs(fromNodeId, toNodeId, options) {
|
|
1766
1708
|
const client = await this.ensureClient();
|
|
1767
|
-
await client.
|
|
1709
|
+
await client.engine.copyOutputs(fromNodeId, toNodeId, options);
|
|
1768
1710
|
}
|
|
1769
1711
|
async triggerExternal(nodeId, event, options) {
|
|
1770
1712
|
const client = await this.ensureClient();
|
|
1771
|
-
await client.
|
|
1713
|
+
await client.engine.triggerExternal(nodeId, event, options);
|
|
1772
1714
|
}
|
|
1773
1715
|
async setViewport(viewport) {
|
|
1774
1716
|
const client = await this.ensureClient();
|
|
1775
|
-
await client.setViewport(viewport);
|
|
1717
|
+
await client.api.setViewport(viewport);
|
|
1776
1718
|
}
|
|
1777
1719
|
async coerce(from, to, value) {
|
|
1778
1720
|
const client = await this.ensureClient();
|
|
1779
1721
|
try {
|
|
1780
|
-
return await client.coerce(from, to, value);
|
|
1722
|
+
return await client.api.coerce(from, to, value);
|
|
1781
1723
|
}
|
|
1782
1724
|
catch {
|
|
1783
1725
|
return value;
|
|
@@ -1785,12 +1727,12 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
1785
1727
|
}
|
|
1786
1728
|
async setExtData(data) {
|
|
1787
1729
|
const client = await this.ensureClient();
|
|
1788
|
-
await client.setExtData(data);
|
|
1730
|
+
await client.api.setExtData(data);
|
|
1789
1731
|
}
|
|
1790
1732
|
async commit(reason) {
|
|
1791
1733
|
const client = await this.ensureClient();
|
|
1792
1734
|
try {
|
|
1793
|
-
const history = await client.commit(reason);
|
|
1735
|
+
const history = await client.api.commit(reason);
|
|
1794
1736
|
return history;
|
|
1795
1737
|
}
|
|
1796
1738
|
catch (err) {
|
|
@@ -1801,7 +1743,7 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
1801
1743
|
async undo() {
|
|
1802
1744
|
const client = await this.ensureClient();
|
|
1803
1745
|
try {
|
|
1804
|
-
return await client.undo();
|
|
1746
|
+
return await client.api.undo();
|
|
1805
1747
|
}
|
|
1806
1748
|
catch {
|
|
1807
1749
|
return false;
|
|
@@ -1810,7 +1752,7 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
1810
1752
|
async redo() {
|
|
1811
1753
|
const client = await this.ensureClient();
|
|
1812
1754
|
try {
|
|
1813
|
-
return await client.redo();
|
|
1755
|
+
return await client.api.redo();
|
|
1814
1756
|
}
|
|
1815
1757
|
catch {
|
|
1816
1758
|
return false;
|
|
@@ -1819,7 +1761,7 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
1819
1761
|
async snapshotFull() {
|
|
1820
1762
|
const client = await this.ensureClient();
|
|
1821
1763
|
try {
|
|
1822
|
-
return await client.snapshotFull();
|
|
1764
|
+
return await client.api.snapshotFull();
|
|
1823
1765
|
}
|
|
1824
1766
|
catch {
|
|
1825
1767
|
return { def: undefined, environment: {}, inputs: {}, outputs: {} };
|
|
@@ -1830,7 +1772,9 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
1830
1772
|
this.hydrateValueCache(payload, { dry: options?.dry });
|
|
1831
1773
|
// Then sync with backend
|
|
1832
1774
|
const client = await this.ensureClient();
|
|
1833
|
-
await client.applySnapshotFull(payload, {
|
|
1775
|
+
await client.api.applySnapshotFull(payload, {
|
|
1776
|
+
skipBuild: options?.skipBuild,
|
|
1777
|
+
});
|
|
1834
1778
|
}
|
|
1835
1779
|
/**
|
|
1836
1780
|
* Hydrates the local valueCache from a snapshot and emits value events.
|
|
@@ -1874,12 +1818,12 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
1874
1818
|
async setEnvironment(env, opts) {
|
|
1875
1819
|
// Use client if available, otherwise ensure client and then set environment
|
|
1876
1820
|
if (this.client) {
|
|
1877
|
-
await this.client.setEnvironment(env, opts);
|
|
1821
|
+
await this.client.api.setEnvironment(env, opts);
|
|
1878
1822
|
}
|
|
1879
1823
|
else {
|
|
1880
1824
|
try {
|
|
1881
1825
|
const client = await this.ensureClient();
|
|
1882
|
-
await client.setEnvironment(env, opts);
|
|
1826
|
+
await client.api.setEnvironment(env, opts);
|
|
1883
1827
|
}
|
|
1884
1828
|
catch {
|
|
1885
1829
|
// Silently fail if connection not available
|
|
@@ -1887,7 +1831,7 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
1887
1831
|
}
|
|
1888
1832
|
}
|
|
1889
1833
|
getEnvironment() {
|
|
1890
|
-
// Interface requires sync return, but
|
|
1834
|
+
// Interface requires sync return, but RemoteRuntimeClient.getEnvironment() is async.
|
|
1891
1835
|
// Returns undefined synchronously; callers needing the actual value should:
|
|
1892
1836
|
// - Use snapshotFull() which includes environment
|
|
1893
1837
|
// - Call client.getEnvironment() directly if they have access to the client
|
|
@@ -3657,6 +3601,7 @@ function computeInvalidatedFromMetadata(metadata) {
|
|
|
3657
3601
|
function WorkbenchProvider({ wb, runner, overrides, uiVersion, children, }) {
|
|
3658
3602
|
const [nodeStatus, setNodeStatus] = React.useState({});
|
|
3659
3603
|
const [edgeStatus, setEdgeStatus] = React.useState({});
|
|
3604
|
+
const [runMode, setRunModeState] = React.useState("manual");
|
|
3660
3605
|
const [events, setEvents] = React.useState([]);
|
|
3661
3606
|
const clearEvents = React.useCallback(() => setEvents([]), []);
|
|
3662
3607
|
const [systemErrors, setSystemErrors] = React.useState([]);
|
|
@@ -3721,6 +3666,24 @@ function WorkbenchProvider({ wb, runner, overrides, uiVersion, children, }) {
|
|
|
3721
3666
|
const graphUiTick = useWorkbenchGraphUiTick(wb);
|
|
3722
3667
|
const versionTick = useWorkbenchVersionTick(runner);
|
|
3723
3668
|
const valuesTick = versionTick + graphTick + graphUiTick;
|
|
3669
|
+
// Keep local runMode state loosely in sync with runner status.
|
|
3670
|
+
// - Seed from runner.getRunMode() on mount if available.
|
|
3671
|
+
// - On status events, update only when a non-undefined runMode is reported,
|
|
3672
|
+
// so the UI preserves the last selected mode after stop().
|
|
3673
|
+
React.useEffect(() => {
|
|
3674
|
+
const initialMode = runner.getRunMode();
|
|
3675
|
+
if (initialMode) {
|
|
3676
|
+
setRunModeState(initialMode);
|
|
3677
|
+
}
|
|
3678
|
+
const offRunnerStatus = runner.on("status", (status) => {
|
|
3679
|
+
if (status.runMode) {
|
|
3680
|
+
setRunModeState(status.runMode);
|
|
3681
|
+
}
|
|
3682
|
+
});
|
|
3683
|
+
return () => {
|
|
3684
|
+
offRunnerStatus();
|
|
3685
|
+
};
|
|
3686
|
+
}, [runner]);
|
|
3724
3687
|
// Def and IO values
|
|
3725
3688
|
const inputsMap = React.useMemo(() => runner.getInputs(wb.def), [runner, wb, wb.def, valuesTick]);
|
|
3726
3689
|
const inputDefaultsMap = React.useMemo(() => runner.getInputDefaults(wb.def), [runner, wb, wb.def, valuesTick]);
|
|
@@ -4414,16 +4377,37 @@ function WorkbenchProvider({ wb, runner, overrides, uiVersion, children, }) {
|
|
|
4414
4377
|
};
|
|
4415
4378
|
}, [runner, wb]);
|
|
4416
4379
|
const isRunning = React.useCallback(() => runner.isRunning(), [runner]);
|
|
4417
|
-
const
|
|
4418
|
-
const start = React.useCallback((engine) => {
|
|
4419
|
-
try {
|
|
4420
|
-
runner.launch(wb.def, { engine });
|
|
4421
|
-
}
|
|
4422
|
-
catch { }
|
|
4423
|
-
}, [runner, wb]);
|
|
4380
|
+
const getRunMode = React.useCallback(() => runner.getRunMode(), [runner]);
|
|
4424
4381
|
const stop = React.useCallback(() => runner.stop(), [runner]);
|
|
4425
|
-
|
|
4426
|
-
const
|
|
4382
|
+
// Run mode actions
|
|
4383
|
+
const setRunMode = React.useCallback((mode) => {
|
|
4384
|
+
if (mode === runMode)
|
|
4385
|
+
return;
|
|
4386
|
+
const wasRunning = runner.isRunning();
|
|
4387
|
+
if (wasRunning) {
|
|
4388
|
+
// Use setRunMode to change run mode without rebuilding
|
|
4389
|
+
try {
|
|
4390
|
+
runner.setRunMode(mode);
|
|
4391
|
+
setRunModeState(mode);
|
|
4392
|
+
}
|
|
4393
|
+
catch (err) {
|
|
4394
|
+
console.error("Failed to set run mode:", err);
|
|
4395
|
+
}
|
|
4396
|
+
}
|
|
4397
|
+
else {
|
|
4398
|
+
// Just update state if not running (will be applied on next launch)
|
|
4399
|
+
setRunModeState(mode);
|
|
4400
|
+
}
|
|
4401
|
+
}, [runMode, runner]);
|
|
4402
|
+
const runNodeAction = React.useCallback(async (nodeId) => {
|
|
4403
|
+
await runner.computeNode(nodeId);
|
|
4404
|
+
}, [runner]);
|
|
4405
|
+
const runFromHereAction = React.useCallback(async (nodeId) => {
|
|
4406
|
+
await runner.runFromHere(nodeId);
|
|
4407
|
+
}, [runner]);
|
|
4408
|
+
const abortNodeAction = React.useCallback((nodeId) => {
|
|
4409
|
+
runner.cancelNodeRuns([nodeId]);
|
|
4410
|
+
}, [runner]);
|
|
4427
4411
|
const validationByNode = React.useMemo(() => {
|
|
4428
4412
|
const inputs = {};
|
|
4429
4413
|
const outputs = {};
|
|
@@ -4515,11 +4499,13 @@ function WorkbenchProvider({ wb, runner, overrides, uiVersion, children, }) {
|
|
|
4515
4499
|
removeRegistryError,
|
|
4516
4500
|
removeInputValidationError,
|
|
4517
4501
|
isRunning,
|
|
4518
|
-
|
|
4519
|
-
start,
|
|
4502
|
+
getRunMode,
|
|
4520
4503
|
stop,
|
|
4521
|
-
|
|
4522
|
-
|
|
4504
|
+
runMode,
|
|
4505
|
+
setRunMode,
|
|
4506
|
+
runNode: runNodeAction,
|
|
4507
|
+
runFromHere: runFromHereAction,
|
|
4508
|
+
abortNode: abortNodeAction,
|
|
4523
4509
|
runAutoLayout,
|
|
4524
4510
|
updateEdgeType,
|
|
4525
4511
|
triggerExternal,
|
|
@@ -4555,11 +4541,13 @@ function WorkbenchProvider({ wb, runner, overrides, uiVersion, children, }) {
|
|
|
4555
4541
|
events,
|
|
4556
4542
|
clearEvents,
|
|
4557
4543
|
isRunning,
|
|
4558
|
-
|
|
4559
|
-
start,
|
|
4544
|
+
getRunMode,
|
|
4560
4545
|
stop,
|
|
4561
|
-
|
|
4562
|
-
|
|
4546
|
+
runMode,
|
|
4547
|
+
setRunMode,
|
|
4548
|
+
runNodeAction,
|
|
4549
|
+
runFromHereAction,
|
|
4550
|
+
abortNodeAction,
|
|
4563
4551
|
runAutoLayout,
|
|
4564
4552
|
wb,
|
|
4565
4553
|
runner,
|
|
@@ -4577,7 +4565,7 @@ function IssueBadge({ level, title, size = 12, className, }) {
|
|
|
4577
4565
|
return (jsxRuntime.jsx("button", { type: "button", className: `inline-flex items-center justify-center shrink-0 ${colorClass} ${className ?? ""}`, title: title, style: { width: size, height: size }, children: level === "error" ? (jsxRuntime.jsx(react$1.XCircleIcon, { size: size, weight: "fill" })) : (jsxRuntime.jsx(react$1.WarningCircleIcon, { size: size, weight: "fill" })) }));
|
|
4578
4566
|
}
|
|
4579
4567
|
|
|
4580
|
-
function DefaultNodeHeader({ id, typeId, validation, right, showId,
|
|
4568
|
+
function DefaultNodeHeader({ id, typeId, validation, right, showId, }) {
|
|
4581
4569
|
const ctx = useWorkbenchContext();
|
|
4582
4570
|
const [isEditing, setIsEditing] = React.useState(false);
|
|
4583
4571
|
const [editValue, setEditValue] = React.useState("");
|
|
@@ -4595,18 +4583,6 @@ function DefaultNodeHeader({ id, typeId, validation, right, showId, onInvalidate
|
|
|
4595
4583
|
const desc = ctx.wb.registry.nodes.get(node.typeId);
|
|
4596
4584
|
return desc?.displayName || node.typeId;
|
|
4597
4585
|
}, [ctx, id, typeId]);
|
|
4598
|
-
const handleInvalidate = React.useCallback(() => {
|
|
4599
|
-
try {
|
|
4600
|
-
if (onInvalidate)
|
|
4601
|
-
return onInvalidate();
|
|
4602
|
-
const kind = ctx.engineKind?.();
|
|
4603
|
-
if (kind === "pull")
|
|
4604
|
-
ctx.runner.computeNode(id);
|
|
4605
|
-
else
|
|
4606
|
-
ctx.triggerExternal?.(id, { type: "invalidate" });
|
|
4607
|
-
}
|
|
4608
|
-
catch { }
|
|
4609
|
-
}, [ctx, id, onInvalidate]);
|
|
4610
4586
|
const handleDoubleClick = React.useCallback((e) => {
|
|
4611
4587
|
// Only allow editing if typeId is provided (enables renaming)
|
|
4612
4588
|
if (!typeId)
|
|
@@ -4651,10 +4627,16 @@ function DefaultNodeHeader({ id, typeId, validation, right, showId, onInvalidate
|
|
|
4651
4627
|
return (jsxRuntime.jsxs("div", { className: "flex items-center justify-center px-2 border-b border-solid border-gray-500 dark:border-gray-400 text-gray-600 dark:text-gray-300", style: {
|
|
4652
4628
|
maxHeight: NODE_HEADER_HEIGHT_PX,
|
|
4653
4629
|
minHeight: NODE_HEADER_HEIGHT_PX,
|
|
4654
|
-
}, children: [isEditing ? (jsxRuntime.jsx("input", { ref: inputRef, type: "text", value: editValue, onChange: (e) => setEditValue(e.target.value), onBlur: handleSave, onKeyDown: handleKeyDown, onClick: (e) => e.stopPropagation(), onMouseDown: (e) => e.stopPropagation(), className: "flex-1 h-full text-sm bg-transparent border border-blue-500 rounded px-1 outline-none wb-nodrag", style: { lineHeight: `${NODE_HEADER_HEIGHT_PX}px` } })) : (jsxRuntime.jsx("strong", { className: `react-flow__node-title flex-1 h-full text-sm select-none truncate ${typeId ? "cursor-text" : ""}`, style: { lineHeight: `${NODE_HEADER_HEIGHT_PX}px` }, onDoubleClick: handleDoubleClick, title: typeId ? "Double-click to rename" : undefined, children: displayName })), jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [jsxRuntime.
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4630
|
+
}, children: [isEditing ? (jsxRuntime.jsx("input", { ref: inputRef, type: "text", value: editValue, onChange: (e) => setEditValue(e.target.value), onBlur: handleSave, onKeyDown: handleKeyDown, onClick: (e) => e.stopPropagation(), onMouseDown: (e) => e.stopPropagation(), className: "flex-1 h-full text-sm bg-transparent border border-blue-500 rounded px-1 outline-none wb-nodrag", style: { lineHeight: `${NODE_HEADER_HEIGHT_PX}px` } })) : (jsxRuntime.jsx("strong", { className: `react-flow__node-title flex-1 h-full text-sm select-none truncate ${typeId ? "cursor-text" : ""}`, style: { lineHeight: `${NODE_HEADER_HEIGHT_PX}px` }, onDoubleClick: handleDoubleClick, title: typeId ? "Double-click to rename" : undefined, children: displayName })), jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [ctx.runMode === "manual" && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("button", { onClick: (e) => {
|
|
4631
|
+
e.stopPropagation();
|
|
4632
|
+
ctx.abortNode(id);
|
|
4633
|
+
}, className: "w-4 h-4 flex items-center justify-center hover:bg-gray-200 dark:hover:bg-gray-700 rounded text-gray-600 dark:text-gray-400 hover:text-red-600 dark:hover:text-red-400 transition-colors", title: "Abort node", children: jsxRuntime.jsx(react$1.StopIcon, { size: 10, weight: "fill" }) }), jsxRuntime.jsx("button", { onClick: (e) => {
|
|
4634
|
+
e.stopPropagation();
|
|
4635
|
+
void ctx.runFromHere(id);
|
|
4636
|
+
}, className: "w-4 h-4 flex items-center justify-center hover:bg-gray-200 dark:hover:bg-gray-700 rounded text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors", title: "Run from here", children: jsxRuntime.jsx(react$1.PlayIcon, { size: 10, weight: "fill" }) }), jsxRuntime.jsx("button", { onClick: (e) => {
|
|
4637
|
+
e.stopPropagation();
|
|
4638
|
+
void ctx.runNode(id);
|
|
4639
|
+
}, className: "w-4 h-4 flex items-center justify-center hover:bg-gray-200 dark:hover:bg-gray-700 rounded text-gray-600 dark:text-gray-400 hover:text-green-600 dark:hover:text-green-400 transition-colors", title: "Run node", children: jsxRuntime.jsx(react$1.Circle, { size: 10, weight: "fill" }) })] })), right, validation.issues && validation.issues.length > 0 && (jsxRuntime.jsx(IssueBadge, { level: validation.issues.some((i) => i.level === "error")
|
|
4658
4640
|
? "error"
|
|
4659
4641
|
: "warning", size: 12, className: "w-3 h-3", title: validation.issues
|
|
4660
4642
|
.map((v) => `${v.code}: ${v.message}`)
|
|
@@ -4808,7 +4790,7 @@ const DefaultEdge = React.memo(function DefaultEdge({ id, sourceX, sourceY, targ
|
|
|
4808
4790
|
return (jsxRuntime.jsx(react.BaseEdge, { id: id, path: edgePath, style: style, markerEnd: markerEnd }));
|
|
4809
4791
|
});
|
|
4810
4792
|
|
|
4811
|
-
function createNodeContextMenuHandlers(nodeId, wb, runner, registry, outputsMap, outputTypesMap, onClose, getDefaultNodeSize, onCopyResult) {
|
|
4793
|
+
function createNodeContextMenuHandlers(nodeId, wb, runner, registry, outputsMap, outputTypesMap, onClose, getDefaultNodeSize, onCopyResult, runNode, runFromHere) {
|
|
4812
4794
|
return {
|
|
4813
4795
|
onDelete: () => {
|
|
4814
4796
|
wb.removeNode(nodeId, { commit: true });
|
|
@@ -4828,13 +4810,24 @@ function createNodeContextMenuHandlers(nodeId, wb, runner, registry, outputsMap,
|
|
|
4828
4810
|
});
|
|
4829
4811
|
onClose();
|
|
4830
4812
|
},
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
|
|
4813
|
+
onRunNode: runNode
|
|
4814
|
+
? async () => {
|
|
4815
|
+
try {
|
|
4816
|
+
await runNode(nodeId);
|
|
4817
|
+
}
|
|
4818
|
+
catch { }
|
|
4819
|
+
onClose();
|
|
4834
4820
|
}
|
|
4835
|
-
|
|
4836
|
-
|
|
4837
|
-
|
|
4821
|
+
: undefined,
|
|
4822
|
+
onRunFromHere: runFromHere
|
|
4823
|
+
? async () => {
|
|
4824
|
+
try {
|
|
4825
|
+
await runFromHere(nodeId);
|
|
4826
|
+
}
|
|
4827
|
+
catch { }
|
|
4828
|
+
onClose();
|
|
4829
|
+
}
|
|
4830
|
+
: undefined,
|
|
4838
4831
|
onBake: async (handleId) => {
|
|
4839
4832
|
const nodePosition = wb.getPositions()[nodeId] || { x: 0, y: 0 };
|
|
4840
4833
|
const typeId = outputTypesMap?.[nodeId]?.[handleId];
|
|
@@ -5416,7 +5409,7 @@ function DefaultContextMenu({ open, clientPos, handlers, registry, nodeIds, enab
|
|
|
5416
5409
|
!handlers.onRedo && jsxRuntime.jsx("div", { className: "h-px bg-gray-200 my-1" }), jsxRuntime.jsxs("div", { className: "px-2 py-1 font-semibold text-gray-700", children: ["Add Node", " ", jsxRuntime.jsxs("span", { className: "text-gray-500 font-normal", children: ["(", totalCount, ")"] })] }), jsxRuntime.jsx("div", { className: "px-2 pb-1", children: jsxRuntime.jsx("input", { ref: inputRef, type: "text", value: query, onChange: (e) => setQuery(e.target.value), placeholder: "Filter nodes...", className: "w-full border border-gray-300 rounded px-2 py-1 text-sm outline-none focus:border-gray-400 select-text", onClick: (e) => e.stopPropagation(), onMouseDown: (e) => e.stopPropagation(), onWheel: (e) => e.stopPropagation() }) }), jsxRuntime.jsx("div", { className: "max-h-60 overflow-auto", children: totalCount > 0 ? (renderTree(root)) : (jsxRuntime.jsx("div", { className: "px-3 py-2 text-gray-400", children: "No matches" })) })] }));
|
|
5417
5410
|
}
|
|
5418
5411
|
|
|
5419
|
-
function NodeContextMenu({ open, clientPos, nodeId, handlers,
|
|
5412
|
+
function NodeContextMenu({ open, clientPos, nodeId, handlers, bakeableOutputs, runMode, enableKeyboardShortcuts = true, keyboardShortcuts = {
|
|
5420
5413
|
copy: "⌘/Ctrl + C",
|
|
5421
5414
|
duplicate: "⌘/Ctrl + E",
|
|
5422
5415
|
duplicateWithEdges: "⌘/Ctrl + Shift + E",
|
|
@@ -5459,7 +5452,7 @@ function NodeContextMenu({ open, clientPos, nodeId, handlers, canRunPull, bakeab
|
|
|
5459
5452
|
return (jsxRuntime.jsxs("div", { ref: ref, tabIndex: -1, className: "fixed z-[1000] bg-white border border-gray-300 rounded-lg shadow-lg p-1 min-w-[180px] text-sm text-gray-700 select-none", style: { left: x, top: y }, onClick: (e) => e.stopPropagation(), onMouseDown: (e) => e.stopPropagation(), onWheel: (e) => e.stopPropagation(), onContextMenu: (e) => {
|
|
5460
5453
|
e.preventDefault();
|
|
5461
5454
|
e.stopPropagation();
|
|
5462
|
-
}, children: [jsxRuntime.jsxs("div", { className: "px-2 py-1 font-semibold text-gray-700", children: ["Node (", nodeId, ")"] }), jsxRuntime.jsx(ContextMenuButton, { label: "Delete", onClick: handlers.onDelete, shortcut: keyboardShortcuts.delete, enableKeyboardShortcuts: enableKeyboardShortcuts }), jsxRuntime.jsx(ContextMenuButton, { label: "Duplicate", onClick: handlers.onDuplicate, shortcut: keyboardShortcuts.duplicate, enableKeyboardShortcuts: enableKeyboardShortcuts }), jsxRuntime.jsx(ContextMenuButton, { label: "Duplicate with edges", onClick: handlers.onDuplicateWithEdges, shortcut: keyboardShortcuts.duplicateWithEdges, enableKeyboardShortcuts: enableKeyboardShortcuts }),
|
|
5455
|
+
}, children: [jsxRuntime.jsxs("div", { className: "px-2 py-1 font-semibold text-gray-700", children: ["Node (", nodeId, ")"] }), jsxRuntime.jsx(ContextMenuButton, { label: "Delete", onClick: handlers.onDelete, shortcut: keyboardShortcuts.delete, enableKeyboardShortcuts: enableKeyboardShortcuts }), jsxRuntime.jsx(ContextMenuButton, { label: "Duplicate", onClick: handlers.onDuplicate, shortcut: keyboardShortcuts.duplicate, enableKeyboardShortcuts: enableKeyboardShortcuts }), jsxRuntime.jsx(ContextMenuButton, { label: "Duplicate with edges", onClick: handlers.onDuplicateWithEdges, shortcut: keyboardShortcuts.duplicateWithEdges, enableKeyboardShortcuts: enableKeyboardShortcuts }), runMode === "manual" && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [handlers.onRunNode && (jsxRuntime.jsx("button", { className: "block w-full text-left px-2 py-1 hover:bg-gray-100", onClick: handlers.onRunNode, children: "Run node" })), handlers.onRunFromHere && (jsxRuntime.jsx("button", { className: "block w-full text-left px-2 py-1 hover:bg-gray-100", onClick: handlers.onRunFromHere, children: "Run from here" }))] })), jsxRuntime.jsx("div", { className: "h-px bg-gray-200 my-1" }), jsxRuntime.jsx(ContextMenuButton, { label: "Copy", onClick: handlers.onCopy, shortcut: keyboardShortcuts.copy, enableKeyboardShortcuts: enableKeyboardShortcuts }), jsxRuntime.jsx("button", { className: "block w-full text-left px-2 py-1 hover:bg-gray-100", onClick: handlers.onCopyId, children: "Copy Node ID" }), bakeableOutputs.length > 0 && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: "h-px bg-gray-200 my-1" }), jsxRuntime.jsx("div", { className: "px-2 py-1 font-semibold text-gray-700", children: "Bake" }), bakeableOutputs.map((h) => (jsxRuntime.jsxs("button", { className: "block w-full text-left px-2 py-1 hover:bg-gray-100", onClick: () => handlers.onBake(h), children: ["Bake: ", h] }, h)))] }))] }));
|
|
5463
5456
|
}
|
|
5464
5457
|
|
|
5465
5458
|
function SelectionContextMenu({ open, clientPos, handlers, enableKeyboardShortcuts = true, keyboardShortcuts = {
|
|
@@ -5546,7 +5539,7 @@ function useKeyboardShortcutToast() {
|
|
|
5546
5539
|
}
|
|
5547
5540
|
|
|
5548
5541
|
const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, getDefaultNodeSize }, ref) => {
|
|
5549
|
-
const { wb, inputsMap, inputDefaultsMap, outputsMap, outputTypesMap, valuesTick, nodeStatus, edgeStatus, validationByNode, validationByEdge, uiVersion, registryVersion, runner,
|
|
5542
|
+
const { wb, inputsMap, inputDefaultsMap, outputsMap, outputTypesMap, valuesTick, nodeStatus, edgeStatus, validationByNode, validationByEdge, uiVersion, registryVersion, runner, overrides, runNode, runFromHere, runMode, } = useWorkbenchContext();
|
|
5550
5543
|
const nodeValidation = validationByNode;
|
|
5551
5544
|
const edgeValidation = validationByEdge.errors;
|
|
5552
5545
|
const [historyState, setHistoryState] = React.useState(wb.getHistory());
|
|
@@ -5986,7 +5979,7 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
5986
5979
|
};
|
|
5987
5980
|
const baseHandlers = createNodeContextMenuHandlers(nodeAtMenu, wb, runner, wb.registry, outputsMap, outputTypesMap, onCloseNodeMenu, overrides?.getDefaultNodeSize, (data) => {
|
|
5988
5981
|
storage.set(data);
|
|
5989
|
-
});
|
|
5982
|
+
}, runNode, runFromHere);
|
|
5990
5983
|
if (overrides?.getNodeContextMenuHandlers) {
|
|
5991
5984
|
return overrides.getNodeContextMenuHandlers(wb, nodeAtMenu, baseHandlers);
|
|
5992
5985
|
}
|
|
@@ -6004,7 +5997,6 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
6004
5997
|
overrides?.getNodeContextMenuHandlers,
|
|
6005
5998
|
overrides?.getCopiedDataStorage,
|
|
6006
5999
|
]);
|
|
6007
|
-
const canRunPull = React.useMemo(() => engineKind()?.toString() === "pull", [engineKind]);
|
|
6008
6000
|
const bakeableOutputs = React.useMemo(() => {
|
|
6009
6001
|
if (!nodeAtMenu)
|
|
6010
6002
|
return [];
|
|
@@ -6209,15 +6201,15 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
6209
6201
|
? { enableKeyboardShortcuts, keyboardShortcuts }
|
|
6210
6202
|
: {}) })) : (jsxRuntime.jsx(DefaultContextMenu, { open: menuOpen, clientPos: menuPos, handlers: defaultContextMenuHandlers, registry: wb.registry, nodeIds: nodeIds, enableKeyboardShortcuts: enableKeyboardShortcuts, keyboardShortcuts: keyboardShortcuts })), !!nodeAtMenu &&
|
|
6211
6203
|
nodeContextMenuHandlers &&
|
|
6212
|
-
(NodeContextMenuRenderer ? (jsxRuntime.jsx(NodeContextMenuRenderer, { open: nodeMenuOpen, clientPos: nodeMenuPos, nodeId: nodeAtMenu, handlers: nodeContextMenuHandlers,
|
|
6204
|
+
(NodeContextMenuRenderer ? (jsxRuntime.jsx(NodeContextMenuRenderer, { open: nodeMenuOpen, clientPos: nodeMenuPos, nodeId: nodeAtMenu, handlers: nodeContextMenuHandlers, bakeableOutputs: bakeableOutputs, runMode: runMode, wb: wb, ...(enableKeyboardShortcuts !== false
|
|
6213
6205
|
? { enableKeyboardShortcuts, keyboardShortcuts }
|
|
6214
|
-
: {}) })) : (jsxRuntime.jsx(NodeContextMenu, { open: nodeMenuOpen, clientPos: nodeMenuPos, nodeId: nodeAtMenu, handlers: nodeContextMenuHandlers,
|
|
6206
|
+
: {}) })) : (jsxRuntime.jsx(NodeContextMenu, { open: nodeMenuOpen, clientPos: nodeMenuPos, nodeId: nodeAtMenu, handlers: nodeContextMenuHandlers, bakeableOutputs: bakeableOutputs, runMode: runMode }))), selectionMenuOpen &&
|
|
6215
6207
|
selectionMenuPos &&
|
|
6216
6208
|
(SelectionContextMenuRenderer ? (jsxRuntime.jsx(SelectionContextMenuRenderer, { open: selectionMenuOpen, clientPos: selectionMenuPos, handlers: selectionContextMenuHandlers, enableKeyboardShortcuts: enableKeyboardShortcuts, keyboardShortcuts: keyboardShortcuts })) : (jsxRuntime.jsx(SelectionContextMenu, { open: selectionMenuOpen, clientPos: selectionMenuPos, handlers: selectionContextMenuHandlers, enableKeyboardShortcuts: enableKeyboardShortcuts, keyboardShortcuts: keyboardShortcuts })))] }) }), toast && (jsxRuntime.jsx(KeyboardShortcutToast, { message: toast.message, onClose: hideToast }, toast.id))] }));
|
|
6217
6209
|
});
|
|
6218
6210
|
|
|
6219
|
-
function WorkbenchStudioCanvas({ autoScroll, onAutoScrollChange, example, onExampleChange,
|
|
6220
|
-
const { wb, runner, selectedNodeId, runAutoLayout } = useWorkbenchContext();
|
|
6211
|
+
function WorkbenchStudioCanvas({ autoScroll, onAutoScrollChange, example, onExampleChange, backendKind, onBackendKindChange, httpBaseUrl, onHttpBaseUrlChange, wsUrl, onWsUrlChange, debug, onDebugChange, showValues, onShowValuesChange, hideWorkbench, onHideWorkbenchChange, overrides, onInit, onChange, }) {
|
|
6212
|
+
const { wb, runner, selectedNodeId, runAutoLayout, runMode, setRunMode, isRunning, } = useWorkbenchContext();
|
|
6221
6213
|
const [transportStatus, setTransportStatus] = React.useState({
|
|
6222
6214
|
state: "local",
|
|
6223
6215
|
});
|
|
@@ -6226,8 +6218,7 @@ function WorkbenchStudioCanvas({ autoScroll, onAutoScrollChange, example, onExam
|
|
|
6226
6218
|
? computeEffectiveHandles(selectedNode, wb.registry)
|
|
6227
6219
|
: { inputs: {}, outputs: {}, inputDefaults: {} };
|
|
6228
6220
|
const [exampleState, setExampleState] = React.useState(example ?? "");
|
|
6229
|
-
const isGraphRunning =
|
|
6230
|
-
const engineKind = runner.getRunningEngine();
|
|
6221
|
+
const isGraphRunning = isRunning();
|
|
6231
6222
|
// Render Start/Stop button based on transport and runner state
|
|
6232
6223
|
const renderStartStopButton = React.useCallback(() => {
|
|
6233
6224
|
// Check if transport is connecting/retrying
|
|
@@ -6243,14 +6234,11 @@ function WorkbenchStudioCanvas({ autoScroll, onAutoScrollChange, example, onExam
|
|
|
6243
6234
|
return (jsxRuntime.jsxs("button", { className: "border rounded px-2 py-1.5 text-red-700 border-red-600 flex items-center gap-1 disabled:opacity-50 disabled:text-gray-400 disabled:border-gray-300", onClick: () => runner.stop(), disabled: !canControl, title: canControl ? "Stop engine" : "Waiting for connection", children: [jsxRuntime.jsx(react$1.StopIcon, { size: 16, weight: "fill" }), jsxRuntime.jsx("span", { className: "font-medium ml-1", children: "Stop" })] }));
|
|
6244
6235
|
}
|
|
6245
6236
|
return (jsxRuntime.jsxs("button", { className: "border rounded px-2 py-1.5 text-green-700 border-green-600 flex items-center gap-1 disabled:text-gray-400 disabled:border-gray-300 disabled:opacity-50", onClick: (evt) => {
|
|
6246
|
-
const kind = engine;
|
|
6247
|
-
if (!kind)
|
|
6248
|
-
return alert("Select an engine first.");
|
|
6249
6237
|
if (evt.shiftKey && !confirm("Invalidate and re-run graph?"))
|
|
6250
6238
|
return;
|
|
6251
6239
|
try {
|
|
6252
6240
|
runner.launch(wb.def, {
|
|
6253
|
-
|
|
6241
|
+
runMode,
|
|
6254
6242
|
invalidate: evt.shiftKey,
|
|
6255
6243
|
});
|
|
6256
6244
|
}
|
|
@@ -6258,12 +6246,10 @@ function WorkbenchStudioCanvas({ autoScroll, onAutoScrollChange, example, onExam
|
|
|
6258
6246
|
const message = err instanceof Error ? err.message : String(err);
|
|
6259
6247
|
alert(message);
|
|
6260
6248
|
}
|
|
6261
|
-
}, disabled: !
|
|
6262
|
-
? "
|
|
6263
|
-
:
|
|
6264
|
-
|
|
6265
|
-
: "Start engine", children: [jsxRuntime.jsx(react$1.PlayIcon, { size: 16, weight: "fill" }), jsxRuntime.jsx("span", { className: "font-medium ml-1", children: "Start" })] }));
|
|
6266
|
-
}, [transportStatus, isGraphRunning, runner, engine, wb]);
|
|
6249
|
+
}, disabled: !canControl, title: !canControl
|
|
6250
|
+
? "Waiting for connection"
|
|
6251
|
+
: `Start ${runMode === "manual" ? "manual" : "auto"} mode`, children: [jsxRuntime.jsx(react$1.PlayIcon, { size: 16, weight: "fill" }), jsxRuntime.jsx("span", { className: "font-medium ml-1", children: "Start" })] }));
|
|
6252
|
+
}, [transportStatus, isGraphRunning, runner, runMode, wb]);
|
|
6267
6253
|
const defaultExamples = React.useMemo(() => [
|
|
6268
6254
|
{
|
|
6269
6255
|
id: "simple",
|
|
@@ -6445,8 +6431,6 @@ function WorkbenchStudioCanvas({ autoScroll, onAutoScrollChange, example, onExam
|
|
|
6445
6431
|
return () => off();
|
|
6446
6432
|
}, [runner, backendKind]);
|
|
6447
6433
|
React.useEffect(() => {
|
|
6448
|
-
if (!engine)
|
|
6449
|
-
return;
|
|
6450
6434
|
if (isGraphRunning)
|
|
6451
6435
|
return;
|
|
6452
6436
|
// Only auto-launch for local backend; require explicit Start for remote
|
|
@@ -6455,12 +6439,12 @@ function WorkbenchStudioCanvas({ autoScroll, onAutoScrollChange, example, onExam
|
|
|
6455
6439
|
if (!wb.def.nodes || wb.def.nodes.length === 0)
|
|
6456
6440
|
return;
|
|
6457
6441
|
try {
|
|
6458
|
-
runner.launch(wb.def, {
|
|
6442
|
+
runner.launch(wb.def, { runMode });
|
|
6459
6443
|
}
|
|
6460
6444
|
catch {
|
|
6461
6445
|
// ignore
|
|
6462
6446
|
}
|
|
6463
|
-
}, [
|
|
6447
|
+
}, [runMode, runner, isGraphRunning, wb, backendKind]);
|
|
6464
6448
|
const baseSetInput = React.useCallback((handle, raw) => {
|
|
6465
6449
|
if (!selectedNodeId)
|
|
6466
6450
|
return;
|
|
@@ -6630,38 +6614,18 @@ function WorkbenchStudioCanvas({ autoScroll, onAutoScrollChange, example, onExam
|
|
|
6630
6614
|
return overrides.toElement(baseToElement, { registry: wb.registry });
|
|
6631
6615
|
return baseToElement;
|
|
6632
6616
|
}, [overrides, baseToElement, wb.registry]);
|
|
6633
|
-
return (jsxRuntime.jsxs("div", { className: "w-full h-screen flex flex-col", children: [jsxRuntime.jsxs("div", { className: "p-2 border-b border-gray-300 flex gap-2 items-center", children: [isGraphRunning ? (jsxRuntime.jsxs("span", { className: "ml-2 text-sm text-green-700", children: ["Running: ",
|
|
6634
|
-
const
|
|
6635
|
-
|
|
6636
|
-
|
|
6637
|
-
if (runner.isRunning() &&
|
|
6638
|
-
currentEngine &&
|
|
6639
|
-
kind &&
|
|
6640
|
-
kind !== currentEngine) {
|
|
6641
|
-
try {
|
|
6642
|
-
await runner.switchEngine({
|
|
6643
|
-
engine: kind,
|
|
6644
|
-
batched: { flushIntervalMs: 0 },
|
|
6645
|
-
hybrid: { windowMs: 250, batchThreshold: 3 },
|
|
6646
|
-
});
|
|
6647
|
-
onEngineChange?.(kind);
|
|
6648
|
-
}
|
|
6649
|
-
catch (err) {
|
|
6650
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
6651
|
-
alert(`Failed to switch engine: ${message}`);
|
|
6652
|
-
// Reset dropdown to current engine
|
|
6653
|
-
e.target.value = currentEngine;
|
|
6654
|
-
}
|
|
6655
|
-
}
|
|
6656
|
-
else {
|
|
6657
|
-
// Normal change when not running
|
|
6658
|
-
onEngineChange?.(kind);
|
|
6617
|
+
return (jsxRuntime.jsxs("div", { className: "w-full h-screen flex flex-col", children: [jsxRuntime.jsxs("div", { className: "p-2 border-b border-gray-300 flex gap-2 items-center", children: [isGraphRunning ? (jsxRuntime.jsxs("span", { className: "ml-2 text-sm text-green-700", children: ["Running: ", runMode === "manual" ? "Manual" : "Auto"] })) : (jsxRuntime.jsx("span", { className: "ml-2 text-sm text-gray-500", children: "Stopped" })), jsxRuntime.jsxs("span", { className: "ml-2 flex items-center gap-1 text-xs", title: transportStatus.kind || undefined, children: [transportStatus.state === "local" && (jsxRuntime.jsx(react$1.PlugsConnectedIcon, { size: 14, className: "text-gray-500" })), transportStatus.state === "connecting" && (jsxRuntime.jsx(react$1.ClockClockwiseIcon, { size: 14, className: "text-amber-600 animate-pulse" })), transportStatus.state === "connected" && (jsxRuntime.jsx(react$1.WifiHighIcon, { size: 14, className: "text-green-600" })), transportStatus.state === "disconnected" && (jsxRuntime.jsx(react$1.WifiSlashIcon, { size: 14, className: "text-red-600" })), transportStatus.state === "retrying" && (jsxRuntime.jsx(react$1.ClockClockwiseIcon, { size: 14, className: "text-amber-700 animate-pulse" }))] }), jsxRuntime.jsxs("select", { className: "border border-gray-300 rounded px-2 py-1", value: exampleState, onChange: (e) => applyExample(e.target.value), disabled: isGraphRunning, title: isGraphRunning ? "Stop engine before switching example" : undefined, children: [jsxRuntime.jsx("option", { value: "", children: "Select Example\u2026" }), examples.map((ex) => (jsxRuntime.jsx("option", { value: ex.id, children: ex.label }, ex.id)))] }), jsxRuntime.jsxs("select", { className: "border border-gray-300 rounded px-2 py-1", value: backendKind, onChange: (e) => onBackendKindChange(e.target.value), disabled: isGraphRunning, title: isGraphRunning ? "Stop engine before switching backend" : undefined, children: [jsxRuntime.jsx("option", { value: "local", children: "Local" }), jsxRuntime.jsx("option", { value: "remote-http", children: "Remote (HTTP)" }), jsxRuntime.jsx("option", { value: "remote-ws", children: "Remote (WebSocket)" })] }), backendKind === "remote-http" && !!onHttpBaseUrlChange && (jsxRuntime.jsx("input", { className: "border border-gray-300 rounded px-2 py-1 w-72", placeholder: "http://127.0.0.1:18080", value: httpBaseUrl, onChange: (e) => onHttpBaseUrlChange(e.target.value) })), backendKind === "remote-ws" && !!onWsUrlChange && (jsxRuntime.jsx("input", { className: "border border-gray-300 rounded px-2 py-1 w-72", placeholder: "ws://127.0.0.1:18081", value: wsUrl, onChange: (e) => onWsUrlChange(e.target.value) })), jsxRuntime.jsxs("select", { className: "border border-gray-300 rounded px-2 py-1", value: runMode, onChange: async (e) => {
|
|
6618
|
+
const mode = e.target.value;
|
|
6619
|
+
if (mode !== runMode) {
|
|
6620
|
+
await setRunMode(mode);
|
|
6659
6621
|
}
|
|
6660
|
-
},
|
|
6622
|
+
}, disabled: isGraphRunning, title: isGraphRunning
|
|
6623
|
+
? "Stop before switching run mode"
|
|
6624
|
+
: "Select run mode", children: [jsxRuntime.jsx("option", { value: "manual", children: "Manual" }), jsxRuntime.jsx("option", { value: "auto", children: "Auto" })] }), renderStartStopButton(), jsxRuntime.jsx("button", { className: "border border-gray-300 rounded p-1", onClick: runAutoLayout, children: jsxRuntime.jsx(react$1.TreeStructureIcon, { size: 24 }) }), jsxRuntime.jsx("button", { className: "border border-gray-300 rounded p-1", onClick: () => canvasRef.current?.fitView?.(), title: "Fit View", children: jsxRuntime.jsx(react$1.CornersOutIcon, { size: 24 }) }), jsxRuntime.jsx("button", { className: "border border-gray-300 rounded p-1", onClick: download$1, children: jsxRuntime.jsx(react$1.DownloadIcon, { size: 24 }) }), jsxRuntime.jsx("input", { ref: uploadInputRef, type: "file", accept: "application/json,.json", className: "hidden", onChange: onUploadPicked }), jsxRuntime.jsx("button", { className: "border border-gray-300 rounded p-1", onClick: triggerUpload, children: jsxRuntime.jsx(react$1.UploadIcon, { size: 24 }) }), jsxRuntime.jsx("button", { className: "border border-gray-300 rounded p-1", onClick: async () => {
|
|
6661
6625
|
await downloadCanvasThumbnail(canvasContainerRef.current);
|
|
6662
6626
|
}, title: "Download Flow Thumbnail (SVG)", children: jsxRuntime.jsx(react$1.ImageIcon, { size: 24 }) }), jsxRuntime.jsxs("label", { className: "flex items-center gap-1", children: [jsxRuntime.jsx("input", { type: "checkbox", checked: debug, onChange: (e) => onDebugChange(e.target.checked) }), jsxRuntime.jsx(react$1.BugBeetleIcon, { size: 24, weight: debug ? "fill" : undefined })] }), jsxRuntime.jsxs("label", { className: "flex items-center gap-1", children: [jsxRuntime.jsx("input", { type: "checkbox", checked: showValues, onChange: (e) => onShowValuesChange(e.target.checked) }), jsxRuntime.jsx(react$1.ListBulletsIcon, { size: 24, weight: showValues ? "fill" : undefined })] })] }), jsxRuntime.jsxs("div", { className: "flex flex-1 min-h-0", children: [jsxRuntime.jsx("div", { className: "flex-1 min-w-0", ref: canvasContainerRef, children: jsxRuntime.jsx(WorkbenchCanvas, { ref: canvasRef, showValues: showValues, toString: toString, toElement: toElement, getDefaultNodeSize: overrides?.getDefaultNodeSize }) }), jsxRuntime.jsx(Inspector, { setInput: setInput, debug: debug, autoScroll: autoScroll, hideWorkbench: hideWorkbench, onAutoScrollChange: onAutoScrollChange, onHideWorkbenchChange: onHideWorkbenchChange, toString: toString, contextPanel: overrides?.contextPanel })] })] }));
|
|
6663
6627
|
}
|
|
6664
|
-
function WorkbenchStudio({
|
|
6628
|
+
function WorkbenchStudio({ example, onExampleChange, backendKind, onBackendKindChange, httpBaseUrl, onHttpBaseUrlChange, wsUrl, onWsUrlChange, debug, onDebugChange, showValues, onShowValuesChange, hideWorkbench, onHideWorkbenchChange, autoScroll, onAutoScrollChange, backendOptions, overrides, onInit, onChange, }) {
|
|
6665
6629
|
const [registry, setRegistry] = React.useState(sparkGraph.createSimpleGraphRegistry());
|
|
6666
6630
|
const [wb] = React.useState(() => new InMemoryWorkbench({ ui: new DefaultUIExtensionRegistry() }));
|
|
6667
6631
|
// Store previous runner for cleanup
|
|
@@ -6731,7 +6695,7 @@ function WorkbenchStudio({ engine, onEngineChange, example, onExampleChange, bac
|
|
|
6731
6695
|
runner.dispose();
|
|
6732
6696
|
onBackendKindChange(v);
|
|
6733
6697
|
}, [isGraphRunning]);
|
|
6734
|
-
return (jsxRuntime.jsx(WorkbenchProvider, { wb: wb, runner: runner, overrides: overrides, uiVersion: uiVersion, children: jsxRuntime.jsx(WorkbenchStudioCanvas, { setRegistry: setRegistry, autoScroll: autoScroll, onAutoScrollChange: onAutoScrollChange, example: example, onExampleChange: onExampleChange,
|
|
6698
|
+
return (jsxRuntime.jsx(WorkbenchProvider, { wb: wb, runner: runner, overrides: overrides, uiVersion: uiVersion, children: jsxRuntime.jsx(WorkbenchStudioCanvas, { setRegistry: setRegistry, autoScroll: autoScroll, onAutoScrollChange: onAutoScrollChange, example: example, onExampleChange: onExampleChange, backendKind: backendKind, onBackendKindChange: onBackendKindChangeWithDispose, httpBaseUrl: httpBaseUrl, onHttpBaseUrlChange: onHttpBaseUrlChange, wsUrl: wsUrl, onWsUrlChange: onWsUrlChange, debug: debug, onDebugChange: onDebugChange, showValues: showValues, onShowValuesChange: onShowValuesChange, hideWorkbench: hideWorkbench, onHideWorkbenchChange: onHideWorkbenchChange, overrides: overrides, onInit: onInit, onChange: onChange }) }));
|
|
6735
6699
|
}
|
|
6736
6700
|
|
|
6737
6701
|
exports.AbstractWorkbench = AbstractWorkbench;
|