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