@bian-womp/spark-workbench 0.2.34 → 0.2.36
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 +175 -53
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/cjs/src/misc/DefaultNode.d.ts.map +1 -1
- package/lib/cjs/src/misc/Inspector.d.ts.map +1 -1
- package/lib/cjs/src/misc/WorkbenchCanvas.d.ts.map +1 -1
- package/lib/cjs/src/misc/context/WorkbenchContext.d.ts +1 -0
- 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/mapping.d.ts +2 -0
- package/lib/cjs/src/misc/mapping.d.ts.map +1 -1
- package/lib/cjs/src/runtime/AbstractGraphRunner.d.ts +2 -1
- package/lib/cjs/src/runtime/AbstractGraphRunner.d.ts.map +1 -1
- package/lib/cjs/src/runtime/IGraphRunner.d.ts +1 -0
- package/lib/cjs/src/runtime/IGraphRunner.d.ts.map +1 -1
- package/lib/cjs/src/runtime/LocalGraphRunner.d.ts +1 -0
- package/lib/cjs/src/runtime/LocalGraphRunner.d.ts.map +1 -1
- package/lib/cjs/src/runtime/RemoteGraphRunner.d.ts +1 -0
- package/lib/cjs/src/runtime/RemoteGraphRunner.d.ts.map +1 -1
- package/lib/esm/index.js +175 -53
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/src/misc/DefaultNode.d.ts.map +1 -1
- package/lib/esm/src/misc/Inspector.d.ts.map +1 -1
- package/lib/esm/src/misc/WorkbenchCanvas.d.ts.map +1 -1
- package/lib/esm/src/misc/context/WorkbenchContext.d.ts +1 -0
- 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/mapping.d.ts +2 -0
- package/lib/esm/src/misc/mapping.d.ts.map +1 -1
- package/lib/esm/src/runtime/AbstractGraphRunner.d.ts +2 -1
- package/lib/esm/src/runtime/AbstractGraphRunner.d.ts.map +1 -1
- package/lib/esm/src/runtime/IGraphRunner.d.ts +1 -0
- package/lib/esm/src/runtime/IGraphRunner.d.ts.map +1 -1
- package/lib/esm/src/runtime/LocalGraphRunner.d.ts +1 -0
- package/lib/esm/src/runtime/LocalGraphRunner.d.ts.map +1 -1
- package/lib/esm/src/runtime/RemoteGraphRunner.d.ts +1 -0
- package/lib/esm/src/runtime/RemoteGraphRunner.d.ts.map +1 -1
- package/package.json +4 -4
package/lib/cjs/index.cjs
CHANGED
|
@@ -539,6 +539,16 @@ class LocalGraphRunner extends AbstractGraphRunner {
|
|
|
539
539
|
}
|
|
540
540
|
return out;
|
|
541
541
|
}
|
|
542
|
+
getInputDefaults(def) {
|
|
543
|
+
const out = {};
|
|
544
|
+
for (const n of def.nodes) {
|
|
545
|
+
const dynDefaults = n.resolvedHandles?.inputDefaults ?? {};
|
|
546
|
+
if (Object.keys(dynDefaults).length > 0) {
|
|
547
|
+
out[n.nodeId] = dynDefaults;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
return out;
|
|
551
|
+
}
|
|
542
552
|
async snapshotFull() {
|
|
543
553
|
const def = undefined; // UI will supply def/positions on download for local
|
|
544
554
|
const inputs = this.getInputs(this.runtime
|
|
@@ -857,6 +867,16 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
857
867
|
}
|
|
858
868
|
return out;
|
|
859
869
|
}
|
|
870
|
+
getInputDefaults(def) {
|
|
871
|
+
const out = {};
|
|
872
|
+
for (const n of def.nodes) {
|
|
873
|
+
const dynDefaults = n.resolvedHandles?.inputDefaults ?? {};
|
|
874
|
+
if (Object.keys(dynDefaults).length > 0) {
|
|
875
|
+
out[n.nodeId] = dynDefaults;
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
return out;
|
|
879
|
+
}
|
|
860
880
|
dispose() {
|
|
861
881
|
super.dispose();
|
|
862
882
|
this.runner = undefined;
|
|
@@ -1608,6 +1628,7 @@ function toReactFlow(def, positions, registry, opts) {
|
|
|
1608
1628
|
renderWidth: initialWidth,
|
|
1609
1629
|
renderHeight: initialHeight,
|
|
1610
1630
|
inputValues: opts.inputs?.[n.nodeId],
|
|
1631
|
+
inputDefaults: opts.inputDefaults?.[n.nodeId],
|
|
1611
1632
|
outputValues: opts.outputs?.[n.nodeId],
|
|
1612
1633
|
status: opts.nodeStatus?.[n.nodeId],
|
|
1613
1634
|
validation: {
|
|
@@ -1774,6 +1795,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
1774
1795
|
// Def and IO values
|
|
1775
1796
|
const def = wb.export();
|
|
1776
1797
|
const inputsMap = React.useMemo(() => runner.getInputs(def), [runner, def, valuesTick]);
|
|
1798
|
+
const inputDefaultsMap = React.useMemo(() => runner.getInputDefaults(def), [runner, def, valuesTick]);
|
|
1777
1799
|
const outputsMap = React.useMemo(() => runner.getOutputs(def), [runner, def, valuesTick]);
|
|
1778
1800
|
const outputTypesMap = React.useMemo(() => {
|
|
1779
1801
|
const out = {};
|
|
@@ -1937,7 +1959,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
1937
1959
|
}
|
|
1938
1960
|
catch { }
|
|
1939
1961
|
};
|
|
1940
|
-
const
|
|
1962
|
+
const offRunnerValue = runner.on("value", (e) => {
|
|
1941
1963
|
if (e?.io === "input") {
|
|
1942
1964
|
const nodeId = e?.nodeId;
|
|
1943
1965
|
setNodeStatus((s) => ({
|
|
@@ -1947,7 +1969,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
1947
1969
|
}
|
|
1948
1970
|
return add("runner", "value")(e);
|
|
1949
1971
|
});
|
|
1950
|
-
const
|
|
1972
|
+
const offRunnerError = runner.on("error", (e) => {
|
|
1951
1973
|
const edgeError = e;
|
|
1952
1974
|
const nodeError = e;
|
|
1953
1975
|
const registryError = e;
|
|
@@ -2000,14 +2022,14 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
2000
2022
|
}
|
|
2001
2023
|
return add("runner", "error")(e);
|
|
2002
2024
|
});
|
|
2003
|
-
const
|
|
2025
|
+
const offRunnerInvalidate = runner.on("invalidate", (e) => {
|
|
2004
2026
|
// After build/update, pull resolved handles and merge in-place (no graphChanged)
|
|
2005
2027
|
if (e?.reason === "graph-updated" || e?.reason === "graph-built") {
|
|
2006
2028
|
refreshResolvedHandles();
|
|
2007
2029
|
}
|
|
2008
2030
|
return add("runner", "invalidate")(e);
|
|
2009
2031
|
});
|
|
2010
|
-
const
|
|
2032
|
+
const offRunnerStats = runner.on("stats", (s) => {
|
|
2011
2033
|
if (!s)
|
|
2012
2034
|
return;
|
|
2013
2035
|
if (s.kind === "node-start") {
|
|
@@ -2110,9 +2132,11 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
2110
2132
|
}
|
|
2111
2133
|
return add("runner", "stats")(s);
|
|
2112
2134
|
});
|
|
2113
|
-
const
|
|
2135
|
+
const offWbGraphChanged = wb.on("graphChanged", add("workbench", "graphChanged"));
|
|
2136
|
+
const offWbGraphUiChanged = wb.on("graphUiChanged", add("workbench", "graphUiChanged"));
|
|
2137
|
+
const offWbValidationChanged = wb.on("validationChanged", add("workbench", "validationChanged"));
|
|
2114
2138
|
// Ensure newly added nodes start as invalidated until first evaluation
|
|
2115
|
-
const
|
|
2139
|
+
const offWbAddNode = wb.on("graphChanged", (e) => {
|
|
2116
2140
|
const change = e.change;
|
|
2117
2141
|
if (change?.type === "addNode" && typeof change.nodeId === "string") {
|
|
2118
2142
|
const id = change.nodeId;
|
|
@@ -2122,17 +2146,14 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
2122
2146
|
}));
|
|
2123
2147
|
}
|
|
2124
2148
|
});
|
|
2125
|
-
const
|
|
2126
|
-
const
|
|
2127
|
-
const off5b = wb.on("validationChanged", (r) => setValidation(r));
|
|
2128
|
-
const off6 = wb.on("selectionChanged", (sel) => {
|
|
2149
|
+
const offWbdSetValidation = wb.on("validationChanged", (r) => setValidation(r));
|
|
2150
|
+
const offWbSelectionChanged = wb.on("selectionChanged", (sel) => {
|
|
2129
2151
|
setSelectedNodeId(sel.nodes?.[0]);
|
|
2130
2152
|
setSelectedEdgeId(sel.edges?.[0]);
|
|
2131
2153
|
});
|
|
2132
|
-
const
|
|
2133
|
-
wb.refreshValidation();
|
|
2154
|
+
const offWbError = wb.on("error", add("workbench", "error"));
|
|
2134
2155
|
// Registry updates: swap registry and refresh graph validation/UI
|
|
2135
|
-
const
|
|
2156
|
+
const offRunnerRegistry = runner.on("registry", (newReg) => {
|
|
2136
2157
|
try {
|
|
2137
2158
|
setRegistry(newReg);
|
|
2138
2159
|
wb.setRegistry(newReg);
|
|
@@ -2148,19 +2169,31 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
2148
2169
|
console.error("Failed to handle registry changed event");
|
|
2149
2170
|
}
|
|
2150
2171
|
});
|
|
2172
|
+
// Handle transport disconnect: reset runtime status when connection is lost
|
|
2173
|
+
const offRunnerTransport = runner.on("transport", (t) => {
|
|
2174
|
+
if (t.state === "disconnected") {
|
|
2175
|
+
console.info("[WorkbenchContext] Transport disconnected, resetting node status");
|
|
2176
|
+
setNodeStatus({});
|
|
2177
|
+
setEdgeStatus({});
|
|
2178
|
+
setFallbackStarts({});
|
|
2179
|
+
errorRunsRef.current = {};
|
|
2180
|
+
}
|
|
2181
|
+
});
|
|
2182
|
+
wb.refreshValidation();
|
|
2151
2183
|
return () => {
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2184
|
+
offRunnerValue();
|
|
2185
|
+
offRunnerError();
|
|
2186
|
+
offRunnerInvalidate();
|
|
2187
|
+
offRunnerStats();
|
|
2188
|
+
offWbGraphChanged();
|
|
2189
|
+
offWbGraphUiChanged();
|
|
2190
|
+
offWbValidationChanged();
|
|
2191
|
+
offWbError();
|
|
2192
|
+
offWbAddNode();
|
|
2193
|
+
offWbdSetValidation();
|
|
2194
|
+
offWbSelectionChanged();
|
|
2195
|
+
offRunnerRegistry();
|
|
2196
|
+
offRunnerTransport();
|
|
2164
2197
|
};
|
|
2165
2198
|
}, [runner, wb]);
|
|
2166
2199
|
// Push incremental updates into running engine without full reload
|
|
@@ -2259,6 +2292,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
2259
2292
|
edgeStatus,
|
|
2260
2293
|
valuesTick,
|
|
2261
2294
|
inputsMap,
|
|
2295
|
+
inputDefaultsMap,
|
|
2262
2296
|
outputsMap,
|
|
2263
2297
|
outputTypesMap,
|
|
2264
2298
|
validationByNode,
|
|
@@ -2301,6 +2335,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
2301
2335
|
removeSystemError,
|
|
2302
2336
|
removeRegistryError,
|
|
2303
2337
|
inputsMap,
|
|
2338
|
+
inputDefaultsMap,
|
|
2304
2339
|
outputsMap,
|
|
2305
2340
|
validationByNode,
|
|
2306
2341
|
validationByEdge,
|
|
@@ -2386,7 +2421,7 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
|
|
|
2386
2421
|
return String(value ?? "");
|
|
2387
2422
|
}
|
|
2388
2423
|
};
|
|
2389
|
-
const { registry, def, selectedNodeId, selectedEdgeId, inputsMap, outputsMap, outputTypesMap, nodeStatus, edgeStatus, validationByNode, validationByEdge, validationGlobal, valuesTick, updateEdgeType, systemErrors, registryErrors, clearSystemErrors, clearRegistryErrors, removeSystemError, removeRegistryError, } = useWorkbenchContext();
|
|
2424
|
+
const { registry, def, selectedNodeId, selectedEdgeId, inputsMap, inputDefaultsMap, outputsMap, outputTypesMap, nodeStatus, edgeStatus, validationByNode, validationByEdge, validationGlobal, valuesTick, updateEdgeType, systemErrors, registryErrors, clearSystemErrors, clearRegistryErrors, removeSystemError, removeRegistryError, } = useWorkbenchContext();
|
|
2390
2425
|
const nodeValidationIssues = validationByNode.issues;
|
|
2391
2426
|
const edgeValidationIssues = validationByEdge.issues;
|
|
2392
2427
|
const nodeValidationHandles = validationByNode;
|
|
@@ -2401,8 +2436,33 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
|
|
|
2401
2436
|
.filter(([k]) => !sparkGraph.isInputPrivate(effectiveHandles.inputs, k))
|
|
2402
2437
|
.map(([k]) => k);
|
|
2403
2438
|
const outputHandles = Object.keys(effectiveHandles.outputs);
|
|
2404
|
-
const
|
|
2439
|
+
const nodeInputsRaw = selectedNodeId ? inputsMap[selectedNodeId] ?? {} : {};
|
|
2440
|
+
const nodeInputsDefaults = selectedNodeId
|
|
2441
|
+
? inputDefaultsMap[selectedNodeId] ?? {}
|
|
2442
|
+
: {};
|
|
2443
|
+
// Keep defaults separate for placeholder use (don't merge into nodeInputs)
|
|
2444
|
+
const nodeInputs = nodeInputsRaw;
|
|
2405
2445
|
const nodeOutputs = selectedNodeId ? outputsMap[selectedNodeId] ?? {} : {};
|
|
2446
|
+
// Helper to truncate long values
|
|
2447
|
+
const truncateValue = (str, maxLen = 50) => {
|
|
2448
|
+
if (str.length <= maxLen)
|
|
2449
|
+
return str;
|
|
2450
|
+
const start = Math.floor(maxLen / 2) - 5;
|
|
2451
|
+
const end = str.length - Math.floor(maxLen / 2) + 5;
|
|
2452
|
+
return `${str.slice(0, start)}...${str.slice(end)}`;
|
|
2453
|
+
};
|
|
2454
|
+
// Helper to copy to clipboard
|
|
2455
|
+
const copyToClipboard = (text) => {
|
|
2456
|
+
navigator.clipboard.writeText(text).catch(() => {
|
|
2457
|
+
// Fallback for older browsers
|
|
2458
|
+
const textarea = document.createElement("textarea");
|
|
2459
|
+
textarea.value = text;
|
|
2460
|
+
document.body.appendChild(textarea);
|
|
2461
|
+
textarea.select();
|
|
2462
|
+
document.execCommand("copy");
|
|
2463
|
+
document.body.removeChild(textarea);
|
|
2464
|
+
});
|
|
2465
|
+
};
|
|
2406
2466
|
const selectedNodeStatus = selectedNodeId
|
|
2407
2467
|
? nodeStatus?.[selectedNodeId]
|
|
2408
2468
|
: undefined;
|
|
@@ -2488,19 +2548,30 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
|
|
|
2488
2548
|
}, children: [jsxRuntime.jsx("option", { value: "", children: "(infer from source)" }), Array.from(registry.types.keys()).map((tid) => (jsxRuntime.jsx("option", { value: tid, children: tid }, tid)))] })] })] }), selectedEdgeValidation.length > 0 && (jsxRuntime.jsxs("div", { className: "mt-2 text-xs bg-red-50 border border-red-200 rounded px-2 py-1", children: [jsxRuntime.jsx("div", { className: "font-semibold mb-1", children: "Validation" }), jsxRuntime.jsx("ul", { className: "list-disc ml-4", children: selectedEdgeValidation.map((m, i) => (jsxRuntime.jsxs("li", { className: "flex items-center gap-1", children: [jsxRuntime.jsx(IssueBadge, { level: m.level, size: 24, className: "w-6 h-6" }), jsxRuntime.jsx("span", { children: `${m.code}: ${m.message}` }), jsxRuntime.jsx("button", { className: "ml-2 text-[10px] px-1 py-[2px] border border-red-300 rounded text-red-700 hover:bg-red-50", onClick: (e) => {
|
|
2489
2549
|
e.stopPropagation();
|
|
2490
2550
|
deleteEdgeById(selectedEdge.id);
|
|
2491
|
-
}, title: "Delete this edge", children: "Delete edge" })] }, i))) })] }))] })) : (jsxRuntime.jsxs("div", { children: [selectedNode && (jsxRuntime.jsxs("div", { className: "mb-2", children: [jsxRuntime.jsxs("div", { children: ["Node: ", selectedNode.nodeId] }), jsxRuntime.jsxs("div", { children: ["Type: ", selectedNode.typeId] }), selectedNodeStatus?.activeRuns &&
|
|
2551
|
+
}, title: "Delete this edge", children: "Delete edge" })] }, i))) })] }))] })) : (jsxRuntime.jsxs("div", { children: [selectedNode && (jsxRuntime.jsxs("div", { className: "mb-2", children: [jsxRuntime.jsxs("div", { children: ["Node: ", selectedNode.nodeId] }), jsxRuntime.jsxs("div", { children: ["Type: ", selectedNode.typeId] }), !!selectedNodeStatus?.activeRuns &&
|
|
2492
2552
|
selectedNodeStatus.activeRuns > 0 && (jsxRuntime.jsxs("div", { className: "mt-1 text-xs text-blue-700 bg-blue-50 border border-blue-200 rounded px-2 py-1", children: [jsxRuntime.jsxs("div", { className: "font-semibold", children: ["Running (", selectedNodeStatus.activeRuns, ")"] }), selectedNodeStatus.activeRunIds &&
|
|
2493
2553
|
selectedNodeStatus.activeRunIds.length > 0 ? (jsxRuntime.jsxs("div", { className: "mt-1", children: [jsxRuntime.jsx("div", { className: "text-[10px] text-blue-600", children: "RunIds:" }), jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1 mt-1", children: selectedNodeStatus.activeRunIds.map((runId, idx) => (jsxRuntime.jsx("span", { className: "text-[10px] px-1.5 py-0.5 bg-blue-100 border border-blue-300 rounded font-mono", children: runId }, idx))) })] })) : (jsxRuntime.jsx("div", { className: "text-[10px] text-blue-600 mt-1", children: "RunIds not available (some runs may have started without runId)" }))] })), !!selectedNodeStatus?.lastError && (jsxRuntime.jsx("div", { className: "mt-2 text-sm text-red-700 bg-red-50 border border-red-200 rounded px-2 py-1 break-words", children: String(selectedNodeStatus.lastError?.message ??
|
|
2494
2554
|
selectedNodeStatus.lastError) }))] })), jsxRuntime.jsxs("div", { className: "mb-2", children: [jsxRuntime.jsx("div", { className: "font-semibold mb-1", children: "Inputs" }), inputHandles.length === 0 ? (jsxRuntime.jsx("div", { className: "text-gray-500", children: "No inputs" })) : (inputHandles.map((h) => {
|
|
2495
2555
|
const typeId = sparkGraph.getInputTypeId(effectiveHandles.inputs, h);
|
|
2496
2556
|
const isLinked = def.edges.some((e) => e.target.nodeId === selectedNodeId &&
|
|
2497
2557
|
e.target.handle === h);
|
|
2558
|
+
const inbound = new Set(def.edges
|
|
2559
|
+
.filter((e) => e.target.nodeId === selectedNodeId &&
|
|
2560
|
+
e.target.handle === h)
|
|
2561
|
+
.map((e) => e.target.handle));
|
|
2562
|
+
const hasDefault = !inbound.has(h) && nodeInputsDefaults[h] !== undefined;
|
|
2563
|
+
const defaultStr = hasDefault
|
|
2564
|
+
? safeToString(typeId, nodeInputsDefaults[h])
|
|
2565
|
+
: undefined;
|
|
2498
2566
|
const commonProps = {
|
|
2499
2567
|
style: { flex: 1 },
|
|
2500
2568
|
disabled: isLinked,
|
|
2501
2569
|
};
|
|
2502
2570
|
const current = nodeInputs[h];
|
|
2571
|
+
const hasValue = current !== undefined && current !== null;
|
|
2503
2572
|
const value = drafts[h] ?? safeToString(typeId, current);
|
|
2573
|
+
const displayValue = hasValue ? value : "";
|
|
2574
|
+
const placeholder = hasDefault ? defaultStr : undefined;
|
|
2504
2575
|
const onChangeText = (text) => setDrafts((d) => ({ ...d, [h]: text }));
|
|
2505
2576
|
const commit = () => {
|
|
2506
2577
|
const draft = drafts[h];
|
|
@@ -2513,6 +2584,11 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
|
|
|
2513
2584
|
const orig = originals[h] ?? safeToString(typeId, current);
|
|
2514
2585
|
setDrafts((d) => ({ ...d, [h]: orig }));
|
|
2515
2586
|
};
|
|
2587
|
+
const clearInput = () => {
|
|
2588
|
+
setInput(h, undefined);
|
|
2589
|
+
setDrafts((d) => ({ ...d, [h]: "" }));
|
|
2590
|
+
setOriginals((o) => ({ ...o, [h]: "" }));
|
|
2591
|
+
};
|
|
2516
2592
|
const isEnum = typeId?.startsWith("enum:");
|
|
2517
2593
|
const inIssues = selectedNodeHandleValidation.inputs.filter((m) => m.handle === h);
|
|
2518
2594
|
const hasValidation = inIssues.length > 0;
|
|
@@ -2520,25 +2596,43 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
|
|
|
2520
2596
|
const title = inIssues
|
|
2521
2597
|
.map((v) => `${v.code}: ${v.message}`)
|
|
2522
2598
|
.join("; ");
|
|
2523
|
-
return (jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-1", children: [jsxRuntime.jsxs("label", { className: "w-32 flex flex-col", children: [jsxRuntime.jsx("span", { children: prettyHandle(h) }), jsxRuntime.jsx("span", { className: "text-gray-500 text-[11px]", children: typeId })] }), hasValidation && (jsxRuntime.jsx(IssueBadge, { level: hasErr ? "error" : "warning", size: 24, className: "ml-1 w-6 h-6", title: title })), isEnum ? (jsxRuntime.jsxs("select", { className: "border border-gray-300 rounded px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2599
|
+
return (jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-1", children: [jsxRuntime.jsxs("label", { className: "w-32 flex flex-col", children: [jsxRuntime.jsx("span", { children: prettyHandle(h) }), jsxRuntime.jsx("span", { className: "text-gray-500 text-[11px]", children: typeId })] }), hasValidation && (jsxRuntime.jsx(IssueBadge, { level: hasErr ? "error" : "warning", size: 24, className: "ml-1 w-6 h-6", title: title })), isEnum ? (jsxRuntime.jsxs("div", { className: "flex items-center gap-1 flex-1", children: [jsxRuntime.jsxs("select", { className: "border border-gray-300 rounded px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500 flex-1", value: current !== undefined && current !== null
|
|
2600
|
+
? String(current)
|
|
2601
|
+
: "", onChange: (e) => {
|
|
2602
|
+
const val = e.target.value;
|
|
2603
|
+
const raw = val === "" ? undefined : Number(val);
|
|
2604
|
+
setInput(h, raw);
|
|
2605
|
+
// keep drafts/originals in sync with label for display elsewhere
|
|
2606
|
+
const display = safeToString(typeId, raw);
|
|
2607
|
+
setDrafts((d) => ({ ...d, [h]: display }));
|
|
2608
|
+
setOriginals((o) => ({ ...o, [h]: display }));
|
|
2609
|
+
}, ...commonProps, children: [jsxRuntime.jsx("option", { value: "", children: placeholder
|
|
2610
|
+
? `Default: ${placeholder}`
|
|
2611
|
+
: "(select)" }), registry.enums
|
|
2612
|
+
.get(typeId)
|
|
2613
|
+
?.options.map((opt) => (jsxRuntime.jsx("option", { value: String(opt.value), children: opt.label }, opt.value)))] }), hasValue && !isLinked && (jsxRuntime.jsx("button", { className: "flex-shrink-0 p-1 hover:bg-gray-100 rounded text-gray-500 hover:text-gray-700", onClick: clearInput, title: "Clear input value", children: jsxRuntime.jsx(react$1.XCircleIcon, { size: 16 }) }))] })) : isLinked ? (jsxRuntime.jsx("div", { className: "flex items-center gap-1 flex-1", children: jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: (() => {
|
|
2614
|
+
const displayStr = safeToString(typeId, current);
|
|
2615
|
+
const isLong = displayStr.length > 50;
|
|
2616
|
+
const truncated = isLong
|
|
2617
|
+
? truncateValue(displayStr)
|
|
2618
|
+
: displayStr;
|
|
2619
|
+
return (jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [jsxRuntime.jsx("span", { className: "truncate", children: truncated }), isLong && (jsxRuntime.jsx("button", { className: "flex-shrink-0 p-1 hover:bg-gray-100 rounded", onClick: () => copyToClipboard(displayStr), title: "Copy full value", children: jsxRuntime.jsx(react$1.CopyIcon, { size: 14 }) }))] }));
|
|
2620
|
+
})() }) })) : (jsxRuntime.jsxs("div", { className: "flex items-center gap-1 flex-1", children: [jsxRuntime.jsx("input", { className: "border border-gray-300 rounded px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500 flex-1", placeholder: placeholder
|
|
2621
|
+
? `Default: ${placeholder}`
|
|
2622
|
+
: undefined, value: displayValue, onChange: (e) => onChangeText(e.target.value), onBlur: commit, onKeyDown: (e) => {
|
|
2623
|
+
if (e.key === "Enter")
|
|
2624
|
+
commit();
|
|
2625
|
+
if (e.key === "Escape")
|
|
2626
|
+
revert();
|
|
2627
|
+
}, ...commonProps }), hasValue && !isLinked && (jsxRuntime.jsx("button", { className: "flex-shrink-0 p-1 hover:bg-gray-100 rounded text-gray-500 hover:text-gray-700", onClick: clearInput, title: "Clear input value", children: jsxRuntime.jsx(react$1.XCircleIcon, { size: 16 }) }))] }))] }, h));
|
|
2628
|
+
}))] }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("div", { className: "font-semibold mb-1", children: "Outputs" }), outputHandles.length === 0 ? (jsxRuntime.jsx("div", { className: "text-gray-500", children: "No outputs" })) : (outputHandles.map((h) => (jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-1", children: [jsxRuntime.jsxs("label", { className: "w-20 flex flex-col", children: [jsxRuntime.jsx("span", { children: prettyHandle(h) }), jsxRuntime.jsx("span", { className: "text-gray-500 text-[11px]", children: outputTypesMap[selectedNodeId]?.[h] ?? "" })] }), jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: (() => {
|
|
2540
2629
|
const { typeId, value } = resolveOutputDisplay(nodeOutputs[h], effectiveHandles.outputs[h]);
|
|
2541
|
-
|
|
2630
|
+
const displayStr = safeToString(typeId, value);
|
|
2631
|
+
const isLong = displayStr.length > 50;
|
|
2632
|
+
const truncated = isLong
|
|
2633
|
+
? truncateValue(displayStr)
|
|
2634
|
+
: displayStr;
|
|
2635
|
+
return (jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [jsxRuntime.jsx("span", { className: "truncate", children: truncated }), isLong && (jsxRuntime.jsx("button", { className: "flex-shrink-0 p-1 hover:bg-gray-100 rounded", onClick: () => copyToClipboard(displayStr), title: "Copy full value", children: jsxRuntime.jsx(react$1.CopyIcon, { size: 14 }) }))] }));
|
|
2542
2636
|
})() }), (() => {
|
|
2543
2637
|
const outIssues = selectedNodeHandleValidation.outputs.filter((m) => m.handle === h);
|
|
2544
2638
|
if (outIssues.length === 0)
|
|
@@ -2680,7 +2774,7 @@ function DefaultNodeHeader({ id, title, validation, right, showId, onInvalidate,
|
|
|
2680
2774
|
.join("; ") })), showId && jsxRuntime.jsxs("span", { className: "text-[10px] opacity-70", children: ["(", id, ")"] })] })] }));
|
|
2681
2775
|
}
|
|
2682
2776
|
function DefaultNodeContent({ data, isConnectable, }) {
|
|
2683
|
-
const { showValues, inputValues, outputValues, toString } = data;
|
|
2777
|
+
const { showValues, inputValues, inputDefaults, outputValues, toString } = data;
|
|
2684
2778
|
const inputEntries = data.inputHandles ?? [];
|
|
2685
2779
|
const outputEntries = data.outputHandles ?? [];
|
|
2686
2780
|
const status = data.status ?? { activeRuns: 0 };
|
|
@@ -2709,14 +2803,23 @@ function DefaultNodeContent({ data, isConnectable, }) {
|
|
|
2709
2803
|
if (!showValues)
|
|
2710
2804
|
return undefined;
|
|
2711
2805
|
if (kind === "input") {
|
|
2712
|
-
const
|
|
2713
|
-
|
|
2806
|
+
const value = inputValues?.[entry.id];
|
|
2807
|
+
const isDefault = value !== undefined &&
|
|
2808
|
+
inputDefaults?.[entry.id] !== undefined &&
|
|
2809
|
+
JSON.stringify(value) ===
|
|
2810
|
+
JSON.stringify(inputDefaults[entry.id]);
|
|
2811
|
+
const txt = toString(entry.typeId, value);
|
|
2812
|
+
const str = typeof txt === "string" ? txt : String(txt);
|
|
2813
|
+
return { text: str, isDefault };
|
|
2714
2814
|
}
|
|
2715
2815
|
const resolved = resolveOutputDisplay(outputValues?.[entry.id], entry.typeId);
|
|
2716
2816
|
const txt = toString(resolved.typeId, resolved.value);
|
|
2717
|
-
return
|
|
2817
|
+
return {
|
|
2818
|
+
text: typeof txt === "string" ? txt : String(txt),
|
|
2819
|
+
isDefault: false,
|
|
2820
|
+
};
|
|
2718
2821
|
})();
|
|
2719
|
-
return (jsxRuntime.jsxs("span", { className:
|
|
2822
|
+
return (jsxRuntime.jsxs("span", { className: `flex items-center gap-1 w-full ${valueText?.isDefault ? "text-gray-400" : ""}`, children: [kind === "output" ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [valueText !== undefined ? (jsxRuntime.jsx("span", { className: "opacity-60 truncate pl-1", style: { flex: 1, minWidth: 0, maxWidth: "100%" }, children: valueText.text })) : (jsxRuntime.jsx("span", { style: { flex: 1, minWidth: 0, maxWidth: "100%" } })), jsxRuntime.jsx("span", { className: "truncate shrink-0", style: valueText !== undefined ? { maxWidth: "40%" } : {}, children: prettyHandle(handleId) })] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("span", { className: "truncate shrink-0", style: valueText !== undefined ? { maxWidth: "40%" } : {}, children: prettyHandle(handleId) }), valueText !== undefined && (jsxRuntime.jsx("span", { className: `truncate pr-1 ${valueText.isDefault ? "text-gray-400" : "opacity-60"}`, style: { flex: 1, minWidth: 0, maxWidth: "100%" }, children: valueText.text }))] })), hasAny && (jsxRuntime.jsx(IssueBadge, { level: hasErr ? "error" : "warning", size: 12, className: "shrink-0", title: title }))] }));
|
|
2720
2823
|
} })] }));
|
|
2721
2824
|
}
|
|
2722
2825
|
|
|
@@ -3013,7 +3116,7 @@ function NodeContextMenu({ open, clientPos, nodeId, onClose, }) {
|
|
|
3013
3116
|
}
|
|
3014
3117
|
|
|
3015
3118
|
const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, getDefaultNodeSize }, ref) => {
|
|
3016
|
-
const { wb, registry, inputsMap, outputsMap, valuesTick, nodeStatus, edgeStatus, validationByNode, validationByEdge, uiVersion, } = useWorkbenchContext();
|
|
3119
|
+
const { wb, registry, inputsMap, inputDefaultsMap, outputsMap, valuesTick, nodeStatus, edgeStatus, validationByNode, validationByEdge, uiVersion, } = useWorkbenchContext();
|
|
3017
3120
|
const nodeValidation = validationByNode;
|
|
3018
3121
|
const edgeValidation = validationByEdge.errors;
|
|
3019
3122
|
// Keep stable references for nodes/edges to avoid unnecessary updates
|
|
@@ -3108,9 +3211,28 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
3108
3211
|
const { nodes, edges } = React.useMemo(() => {
|
|
3109
3212
|
const def = wb.export();
|
|
3110
3213
|
const sel = wb.getSelection();
|
|
3214
|
+
// Merge defaults with inputs for node display (defaults shown in lighter gray)
|
|
3215
|
+
const inputsWithDefaults = {};
|
|
3216
|
+
for (const n of def.nodes) {
|
|
3217
|
+
const nodeInputs = inputsMap[n.nodeId] ?? {};
|
|
3218
|
+
const nodeDefaults = inputDefaultsMap[n.nodeId] ?? {};
|
|
3219
|
+
const inbound = new Set(def.edges
|
|
3220
|
+
.filter((e) => e.target.nodeId === n.nodeId)
|
|
3221
|
+
.map((e) => e.target.handle));
|
|
3222
|
+
const merged = { ...nodeInputs };
|
|
3223
|
+
for (const [h, v] of Object.entries(nodeDefaults)) {
|
|
3224
|
+
if (!inbound.has(h) && merged[h] === undefined) {
|
|
3225
|
+
merged[h] = v;
|
|
3226
|
+
}
|
|
3227
|
+
}
|
|
3228
|
+
if (Object.keys(merged).length > 0) {
|
|
3229
|
+
inputsWithDefaults[n.nodeId] = merged;
|
|
3230
|
+
}
|
|
3231
|
+
}
|
|
3111
3232
|
const out = toReactFlow(def, wb.getPositions(), registry, {
|
|
3112
3233
|
showValues,
|
|
3113
|
-
inputs:
|
|
3234
|
+
inputs: inputsWithDefaults,
|
|
3235
|
+
inputDefaults: inputDefaultsMap,
|
|
3114
3236
|
outputs: outputsMap,
|
|
3115
3237
|
resolveNodeType,
|
|
3116
3238
|
toString,
|