@bian-womp/spark-workbench 0.2.38 → 0.2.39
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 +201 -209
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/cjs/src/index.d.ts +2 -2
- package/lib/cjs/src/index.d.ts.map +1 -1
- package/lib/cjs/src/runtime/RemoteGraphRunner.d.ts.map +1 -1
- package/lib/esm/index.js +201 -209
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/src/index.d.ts +2 -2
- package/lib/esm/src/index.d.ts.map +1 -1
- package/lib/esm/src/runtime/RemoteGraphRunner.d.ts.map +1 -1
- package/package.json +4 -4
package/lib/cjs/src/index.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export * from "./adapters/cli";
|
|
|
6
6
|
export * from "./runtime/IGraphRunner";
|
|
7
7
|
export * from "./runtime/LocalGraphRunner";
|
|
8
8
|
export * from "./runtime/RemoteGraphRunner";
|
|
9
|
+
export * from "./misc/value";
|
|
10
|
+
export * from "./misc/layout";
|
|
9
11
|
export * from "./misc/hooks";
|
|
10
12
|
export * from "./misc/mapping";
|
|
11
13
|
export * from "./misc/context/WorkbenchContext";
|
|
@@ -14,7 +16,5 @@ export * from "./misc/Inspector";
|
|
|
14
16
|
export * from "./misc/DefaultNode";
|
|
15
17
|
export * from "./misc/WorkbenchCanvas";
|
|
16
18
|
export * from "./misc/WorkbenchStudio";
|
|
17
|
-
export * from "./misc/value";
|
|
18
19
|
export * from "./misc/NodeHandles";
|
|
19
|
-
export * from "./misc/layout";
|
|
20
20
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AAEzC,cAAc,gBAAgB,CAAC;AAE/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAE5C,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAE/B,cAAc,iCAAiC,CAAC;AAChD,cAAc,0CAA0C,CAAC;AAEzD,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AAEvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RemoteGraphRunner.d.ts","sourceRoot":"","sources":["../../../../src/runtime/RemoteGraphRunner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,eAAe,EAChB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAU,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EACL,gBAAgB,EAGjB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,sBAAsB,EAEtB,aAAa,EACd,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,qBAAa,iBAAkB,SAAQ,mBAAmB;IACxD,SAAS,CAAC,OAAO,CAAC,EAAE,eAAe,CAAC;IACpC,SAAS,CAAC,MAAM,CAAC,EAAE,gBAAgB,CAAC;IACpC,OAAO,CAAC,aAAa,CAAC,CAA4B;IAClD,OAAO,CAAC,sBAAsB,CAAC,CAAa;IAC5C,OAAO,CAAC,0BAA0B,CAAC,CAAa;IAChD,OAAO,CAAC,QAAQ,CAAS;IAEzB,OAAO,CAAC,UAAU,CAGd;IACJ,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,2BAA2B,CAAK;IACjD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAQ;IAE/C;;;OAGG;YACW,aAAa;IA4H3B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAkBzB;;OAEG;IACH,OAAO,CAAC,wBAAwB;cA2BhB,YAAY,IAAI,OAAO,CAAC,gBAAgB,CAAC;gBAkD7C,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,sBAAsB;IA8D/D,KAAK,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"RemoteGraphRunner.d.ts","sourceRoot":"","sources":["../../../../src/runtime/RemoteGraphRunner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,eAAe,EAChB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAU,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EACL,gBAAgB,EAGjB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,sBAAsB,EAEtB,aAAa,EACd,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,qBAAa,iBAAkB,SAAQ,mBAAmB;IACxD,SAAS,CAAC,OAAO,CAAC,EAAE,eAAe,CAAC;IACpC,SAAS,CAAC,MAAM,CAAC,EAAE,gBAAgB,CAAC;IACpC,OAAO,CAAC,aAAa,CAAC,CAA4B;IAClD,OAAO,CAAC,sBAAsB,CAAC,CAAa;IAC5C,OAAO,CAAC,0BAA0B,CAAC,CAAa;IAChD,OAAO,CAAC,QAAQ,CAAS;IAEzB,OAAO,CAAC,UAAU,CAGd;IACJ,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,2BAA2B,CAAK;IACjD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAQ;IAE/C;;;OAGG;YACW,aAAa;IA4H3B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAkBzB;;OAEG;IACH,OAAO,CAAC,wBAAwB;cA2BhB,YAAY,IAAI,OAAO,CAAC,gBAAgB,CAAC;gBAkD7C,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,sBAAsB;IA8D/D,KAAK,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI;IAEjC,MAAM,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI;IAWlC,MAAM,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,aAAa,GAAG,IAAI;IAyDvD;;;;;;OAMG;IACH,cAAc,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,aAAa,GAAG,IAAI;IAoCzD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAErB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAEhD,KAAK,IAAI,IAAI;IAEb,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAQ/C,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IASlE,YAAY;IASZ,iBAAiB,CAAC,OAAO,EAAE,mBAAmB;IASpD;;;;OAIG;IACH,mBAAmB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,IAAI;IAuBxD,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;IAcvE,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;IASrD,UAAU,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAoBzE,SAAS,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IA6BxE,gBAAgB,CACd,GAAG,EAAE,eAAe,GACnB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAW1C,OAAO,IAAI,IAAI;CAqChB"}
|
package/lib/esm/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { GraphBuilder, StepEngine, HybridEngine, PullEngine, BatchedEngine, PushEngine, isTypedOutput, getTypedOutputValue, getTypedOutputTypeId, isInputPrivate, getInputTypeId, createSimpleGraphRegistry, createSimpleGraphDef, createAsyncGraphDef, createAsyncGraphRegistry, createProgressGraphDef, createProgressGraphRegistry, createValidationGraphDef, createValidationGraphRegistry } from '@bian-womp/spark-graph';
|
|
2
2
|
import { RuntimeApiClient } from '@bian-womp/spark-remote';
|
|
3
|
-
import React, { useCallback, useState, useRef, useEffect, useMemo, createContext, useContext, useImperativeHandle } from 'react';
|
|
4
3
|
import { Position, Handle, useUpdateNodeInternals, useReactFlow, ReactFlowProvider, ReactFlow, Background, BackgroundVariant, MiniMap, Controls } from '@xyflow/react';
|
|
4
|
+
import React, { useCallback, useState, useRef, useEffect, useMemo, createContext, useContext, useImperativeHandle } from 'react';
|
|
5
5
|
import cx from 'classnames';
|
|
6
6
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
7
7
|
import { XCircleIcon, WarningCircleIcon, CopyIcon, TrashIcon, XIcon, ArrowClockwiseIcon, PlugsConnectedIcon, ClockClockwiseIcon, WifiHighIcon, WifiSlashIcon, PlayPauseIcon, LightningIcon, StopIcon, PlayIcon, TreeStructureIcon, CornersOutIcon, DownloadSimpleIcon, DownloadIcon, UploadIcon, BugBeetleIcon, ListBulletsIcon } from '@phosphor-icons/react';
|
|
@@ -862,9 +862,7 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
862
862
|
}
|
|
863
863
|
});
|
|
864
864
|
}
|
|
865
|
-
build(def) {
|
|
866
|
-
console.warn("Unsupported operation for remote runner");
|
|
867
|
-
}
|
|
865
|
+
build(def) { }
|
|
868
866
|
update(def) {
|
|
869
867
|
// Remote: forward update; ignore errors (fire-and-forget)
|
|
870
868
|
this.ensureClient().then(async (client) => {
|
|
@@ -973,15 +971,9 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
973
971
|
}
|
|
974
972
|
});
|
|
975
973
|
}
|
|
976
|
-
async step() {
|
|
977
|
-
|
|
978
|
-
}
|
|
979
|
-
async computeNode(nodeId) {
|
|
980
|
-
console.warn("Unsupported operation for remote runner");
|
|
981
|
-
}
|
|
982
|
-
flush() {
|
|
983
|
-
console.warn("Unsupported operation for remote runner");
|
|
984
|
-
}
|
|
974
|
+
async step() { }
|
|
975
|
+
async computeNode(nodeId) { }
|
|
976
|
+
flush() { }
|
|
985
977
|
triggerExternal(nodeId, event) {
|
|
986
978
|
this.ensureClient().then(async (client) => {
|
|
987
979
|
try {
|
|
@@ -1158,6 +1150,202 @@ class RemoteGraphRunner extends AbstractGraphRunner {
|
|
|
1158
1150
|
}
|
|
1159
1151
|
}
|
|
1160
1152
|
|
|
1153
|
+
function formatDataUrlAsLabel(dataUrl) {
|
|
1154
|
+
try {
|
|
1155
|
+
const semi = dataUrl.indexOf(";");
|
|
1156
|
+
const comma = dataUrl.indexOf(",");
|
|
1157
|
+
const mime = dataUrl.slice(5, semi > 0 ? semi : undefined).toUpperCase();
|
|
1158
|
+
const b64 = comma >= 0 ? dataUrl.slice(comma + 1) : "";
|
|
1159
|
+
const bytes = Math.floor((b64.length * 3) / 4);
|
|
1160
|
+
return `${mime} Data (${bytes} bytes)`;
|
|
1161
|
+
}
|
|
1162
|
+
catch {
|
|
1163
|
+
return dataUrl.length > 64 ? dataUrl.slice(0, 64) + "…" : dataUrl;
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
function resolveOutputDisplay(raw, declared) {
|
|
1167
|
+
if (isTypedOutput(raw)) {
|
|
1168
|
+
return {
|
|
1169
|
+
typeId: getTypedOutputTypeId(raw),
|
|
1170
|
+
value: getTypedOutputValue(raw),
|
|
1171
|
+
};
|
|
1172
|
+
}
|
|
1173
|
+
let typeId = undefined;
|
|
1174
|
+
if (Array.isArray(declared)) {
|
|
1175
|
+
typeId = declared.length === 1 ? declared[0] : undefined;
|
|
1176
|
+
}
|
|
1177
|
+
else if (typeof declared === "string") {
|
|
1178
|
+
typeId = declared.includes("|") ? undefined : declared;
|
|
1179
|
+
}
|
|
1180
|
+
return { typeId, value: raw };
|
|
1181
|
+
}
|
|
1182
|
+
function formatDeclaredTypeSignature(declared) {
|
|
1183
|
+
if (Array.isArray(declared))
|
|
1184
|
+
return declared.join(" | ");
|
|
1185
|
+
return declared ?? "";
|
|
1186
|
+
}
|
|
1187
|
+
/**
|
|
1188
|
+
* Formats a handle ID for display in the UI.
|
|
1189
|
+
* For handles with format "prefix:middle:suffix:extra" (4 parts), displays only the middle part.
|
|
1190
|
+
* Otherwise returns the handle ID as-is.
|
|
1191
|
+
*/
|
|
1192
|
+
function prettyHandle(id) {
|
|
1193
|
+
try {
|
|
1194
|
+
const parts = String(id).split(":");
|
|
1195
|
+
// If there are exactly 3 colons (4 parts), display only the second part
|
|
1196
|
+
if (parts.length === 4)
|
|
1197
|
+
return parts[1] || id;
|
|
1198
|
+
return id;
|
|
1199
|
+
}
|
|
1200
|
+
catch {
|
|
1201
|
+
return id;
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
// Pre-format common structures for display; return undefined to defer to caller
|
|
1205
|
+
function preformatValueForDisplay(typeId, value, registry) {
|
|
1206
|
+
if (value === undefined || value === null)
|
|
1207
|
+
return "";
|
|
1208
|
+
// Unwrap typed outputs
|
|
1209
|
+
if (isTypedOutput(value)) {
|
|
1210
|
+
return preformatValueForDisplay(getTypedOutputTypeId(value), getTypedOutputValue(value), registry);
|
|
1211
|
+
}
|
|
1212
|
+
// Enums
|
|
1213
|
+
if (typeId && typeId.startsWith("enum:") && registry) {
|
|
1214
|
+
const n = Number(value);
|
|
1215
|
+
const label = registry.enums.get(typeId)?.valueToLabel.get(n);
|
|
1216
|
+
if (label)
|
|
1217
|
+
return label;
|
|
1218
|
+
}
|
|
1219
|
+
// Use deep summarization for strings, arrays and nested objects to avoid huge HTML payloads
|
|
1220
|
+
const summarized = summarizeDeep(value);
|
|
1221
|
+
if (typeof summarized === "string")
|
|
1222
|
+
return summarized;
|
|
1223
|
+
// Resource-like objects with url/title (after summarization)
|
|
1224
|
+
if (summarized && typeof summarized === "object") {
|
|
1225
|
+
const urlMaybe = summarized.url;
|
|
1226
|
+
if (typeof urlMaybe === "string") {
|
|
1227
|
+
const title = summarized.title || "";
|
|
1228
|
+
const shortUrl = urlMaybe.length > 32 ? urlMaybe.slice(0, 32) + "…" : urlMaybe;
|
|
1229
|
+
return title ? `${title} (${shortUrl})` : shortUrl;
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
return undefined;
|
|
1233
|
+
}
|
|
1234
|
+
function summarizeDeep(value) {
|
|
1235
|
+
// Strings: summarize data URLs and trim extremely long strings
|
|
1236
|
+
if (typeof value === "string") {
|
|
1237
|
+
if (value.startsWith("data:"))
|
|
1238
|
+
return formatDataUrlAsLabel(value);
|
|
1239
|
+
return value.length > 512 ? value.slice(0, 512) + "…" : value;
|
|
1240
|
+
}
|
|
1241
|
+
// Typed output wrapper
|
|
1242
|
+
if (isTypedOutput(value)) {
|
|
1243
|
+
return summarizeDeep(getTypedOutputValue(value));
|
|
1244
|
+
}
|
|
1245
|
+
// Arrays
|
|
1246
|
+
if (Array.isArray(value)) {
|
|
1247
|
+
return value.map((v) => summarizeDeep(v));
|
|
1248
|
+
}
|
|
1249
|
+
// Objects
|
|
1250
|
+
if (value && typeof value === "object") {
|
|
1251
|
+
const obj = value;
|
|
1252
|
+
const out = {};
|
|
1253
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
1254
|
+
// Special-case any 'url' field
|
|
1255
|
+
if (typeof v === "string" &&
|
|
1256
|
+
k.toLowerCase() === "url" &&
|
|
1257
|
+
v.startsWith("data:")) {
|
|
1258
|
+
out[k] = formatDataUrlAsLabel(v);
|
|
1259
|
+
continue;
|
|
1260
|
+
}
|
|
1261
|
+
out[k] = summarizeDeep(v);
|
|
1262
|
+
}
|
|
1263
|
+
return out;
|
|
1264
|
+
}
|
|
1265
|
+
return value;
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
// Shared UI constants for node layout to keep mapping and rendering in sync
|
|
1269
|
+
const NODE_HEADER_HEIGHT_PX = 24;
|
|
1270
|
+
const NODE_ROW_HEIGHT_PX = 22;
|
|
1271
|
+
|
|
1272
|
+
function computeEffectiveHandles(node, registry) {
|
|
1273
|
+
const desc = registry.nodes.get(node.typeId);
|
|
1274
|
+
const resolved = node.resolvedHandles || {};
|
|
1275
|
+
const inputs = { ...desc?.inputs, ...resolved.inputs };
|
|
1276
|
+
const outputs = { ...desc?.outputs, ...resolved.outputs };
|
|
1277
|
+
const inputDefaults = { ...desc?.inputDefaults, ...resolved.inputDefaults };
|
|
1278
|
+
return { inputs, outputs, inputDefaults };
|
|
1279
|
+
}
|
|
1280
|
+
function countVisibleHandles(handles) {
|
|
1281
|
+
const inputIds = Object.keys(handles.inputs).filter((k) => !isInputPrivate(handles.inputs, k));
|
|
1282
|
+
const outputIds = Object.keys(handles.outputs);
|
|
1283
|
+
return { inputsCount: inputIds.length, outputsCount: outputIds.length };
|
|
1284
|
+
}
|
|
1285
|
+
function estimateNodeSize(args) {
|
|
1286
|
+
const { node, registry, showValues, overrides } = args;
|
|
1287
|
+
const { inputs, outputs } = computeEffectiveHandles(node, registry);
|
|
1288
|
+
// Count only non-private inputs for rows on left
|
|
1289
|
+
const { inputsCount, outputsCount } = countVisibleHandles({
|
|
1290
|
+
inputs,
|
|
1291
|
+
outputs,
|
|
1292
|
+
});
|
|
1293
|
+
const rows = Math.max(inputsCount, outputsCount);
|
|
1294
|
+
const baseWidth = showValues ? 320 : 240;
|
|
1295
|
+
const width = overrides?.width ?? baseWidth;
|
|
1296
|
+
const height = overrides?.height ?? NODE_HEADER_HEIGHT_PX + rows * NODE_ROW_HEIGHT_PX;
|
|
1297
|
+
return { width, height, inputsCount, outputsCount, rowCount: rows };
|
|
1298
|
+
}
|
|
1299
|
+
function layoutNode(args) {
|
|
1300
|
+
const { node, registry, showValues, overrides } = args;
|
|
1301
|
+
const { inputs, outputs } = computeEffectiveHandles(node, registry);
|
|
1302
|
+
const inputOrder = Object.keys(inputs).filter((k) => !isInputPrivate(inputs, k));
|
|
1303
|
+
const outputOrder = Object.keys(outputs);
|
|
1304
|
+
const { width, height } = estimateNodeSize({
|
|
1305
|
+
node,
|
|
1306
|
+
registry,
|
|
1307
|
+
showValues,
|
|
1308
|
+
overrides,
|
|
1309
|
+
});
|
|
1310
|
+
const HEADER = NODE_HEADER_HEIGHT_PX;
|
|
1311
|
+
const ROW = NODE_ROW_HEIGHT_PX;
|
|
1312
|
+
const handles = [
|
|
1313
|
+
...inputOrder.map((id, i) => ({
|
|
1314
|
+
id,
|
|
1315
|
+
type: "target",
|
|
1316
|
+
position: Position.Left,
|
|
1317
|
+
x: 0,
|
|
1318
|
+
y: HEADER + i * ROW,
|
|
1319
|
+
width: 1,
|
|
1320
|
+
height: ROW + 2,
|
|
1321
|
+
})),
|
|
1322
|
+
...outputOrder.map((id, i) => ({
|
|
1323
|
+
id,
|
|
1324
|
+
type: "source",
|
|
1325
|
+
position: Position.Right,
|
|
1326
|
+
x: width - 1,
|
|
1327
|
+
y: HEADER + i * ROW,
|
|
1328
|
+
width: 1,
|
|
1329
|
+
height: ROW + 2,
|
|
1330
|
+
})),
|
|
1331
|
+
];
|
|
1332
|
+
const handleLayout = [
|
|
1333
|
+
...inputOrder.map((id, i) => ({
|
|
1334
|
+
id,
|
|
1335
|
+
type: "target",
|
|
1336
|
+
position: Position.Left,
|
|
1337
|
+
y: HEADER + i * ROW + ROW / 2,
|
|
1338
|
+
})),
|
|
1339
|
+
...outputOrder.map((id, i) => ({
|
|
1340
|
+
id,
|
|
1341
|
+
type: "source",
|
|
1342
|
+
position: Position.Right,
|
|
1343
|
+
y: HEADER + i * ROW + ROW / 2,
|
|
1344
|
+
})),
|
|
1345
|
+
];
|
|
1346
|
+
return { width, height, inputOrder, outputOrder, handles, handleLayout };
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1161
1349
|
function useWorkbenchBridge(wb) {
|
|
1162
1350
|
const onConnect = useCallback((params) => {
|
|
1163
1351
|
if (!params.source || !params.target)
|
|
@@ -1402,202 +1590,6 @@ function useQueryParamString(key, defaultValue) {
|
|
|
1402
1590
|
return [val, set];
|
|
1403
1591
|
}
|
|
1404
1592
|
|
|
1405
|
-
function formatDataUrlAsLabel(dataUrl) {
|
|
1406
|
-
try {
|
|
1407
|
-
const semi = dataUrl.indexOf(";");
|
|
1408
|
-
const comma = dataUrl.indexOf(",");
|
|
1409
|
-
const mime = dataUrl.slice(5, semi > 0 ? semi : undefined).toUpperCase();
|
|
1410
|
-
const b64 = comma >= 0 ? dataUrl.slice(comma + 1) : "";
|
|
1411
|
-
const bytes = Math.floor((b64.length * 3) / 4);
|
|
1412
|
-
return `${mime} Data (${bytes} bytes)`;
|
|
1413
|
-
}
|
|
1414
|
-
catch {
|
|
1415
|
-
return dataUrl.length > 64 ? dataUrl.slice(0, 64) + "…" : dataUrl;
|
|
1416
|
-
}
|
|
1417
|
-
}
|
|
1418
|
-
function resolveOutputDisplay(raw, declared) {
|
|
1419
|
-
if (isTypedOutput(raw)) {
|
|
1420
|
-
return {
|
|
1421
|
-
typeId: getTypedOutputTypeId(raw),
|
|
1422
|
-
value: getTypedOutputValue(raw),
|
|
1423
|
-
};
|
|
1424
|
-
}
|
|
1425
|
-
let typeId = undefined;
|
|
1426
|
-
if (Array.isArray(declared)) {
|
|
1427
|
-
typeId = declared.length === 1 ? declared[0] : undefined;
|
|
1428
|
-
}
|
|
1429
|
-
else if (typeof declared === "string") {
|
|
1430
|
-
typeId = declared.includes("|") ? undefined : declared;
|
|
1431
|
-
}
|
|
1432
|
-
return { typeId, value: raw };
|
|
1433
|
-
}
|
|
1434
|
-
function formatDeclaredTypeSignature(declared) {
|
|
1435
|
-
if (Array.isArray(declared))
|
|
1436
|
-
return declared.join(" | ");
|
|
1437
|
-
return declared ?? "";
|
|
1438
|
-
}
|
|
1439
|
-
/**
|
|
1440
|
-
* Formats a handle ID for display in the UI.
|
|
1441
|
-
* For handles with format "prefix:middle:suffix:extra" (4 parts), displays only the middle part.
|
|
1442
|
-
* Otherwise returns the handle ID as-is.
|
|
1443
|
-
*/
|
|
1444
|
-
function prettyHandle(id) {
|
|
1445
|
-
try {
|
|
1446
|
-
const parts = String(id).split(":");
|
|
1447
|
-
// If there are exactly 3 colons (4 parts), display only the second part
|
|
1448
|
-
if (parts.length === 4)
|
|
1449
|
-
return parts[1] || id;
|
|
1450
|
-
return id;
|
|
1451
|
-
}
|
|
1452
|
-
catch {
|
|
1453
|
-
return id;
|
|
1454
|
-
}
|
|
1455
|
-
}
|
|
1456
|
-
// Pre-format common structures for display; return undefined to defer to caller
|
|
1457
|
-
function preformatValueForDisplay(typeId, value, registry) {
|
|
1458
|
-
if (value === undefined || value === null)
|
|
1459
|
-
return "";
|
|
1460
|
-
// Unwrap typed outputs
|
|
1461
|
-
if (isTypedOutput(value)) {
|
|
1462
|
-
return preformatValueForDisplay(getTypedOutputTypeId(value), getTypedOutputValue(value), registry);
|
|
1463
|
-
}
|
|
1464
|
-
// Enums
|
|
1465
|
-
if (typeId && typeId.startsWith("enum:") && registry) {
|
|
1466
|
-
const n = Number(value);
|
|
1467
|
-
const label = registry.enums.get(typeId)?.valueToLabel.get(n);
|
|
1468
|
-
if (label)
|
|
1469
|
-
return label;
|
|
1470
|
-
}
|
|
1471
|
-
// Use deep summarization for strings, arrays and nested objects to avoid huge HTML payloads
|
|
1472
|
-
const summarized = summarizeDeep(value);
|
|
1473
|
-
if (typeof summarized === "string")
|
|
1474
|
-
return summarized;
|
|
1475
|
-
// Resource-like objects with url/title (after summarization)
|
|
1476
|
-
if (summarized && typeof summarized === "object") {
|
|
1477
|
-
const urlMaybe = summarized.url;
|
|
1478
|
-
if (typeof urlMaybe === "string") {
|
|
1479
|
-
const title = summarized.title || "";
|
|
1480
|
-
const shortUrl = urlMaybe.length > 32 ? urlMaybe.slice(0, 32) + "…" : urlMaybe;
|
|
1481
|
-
return title ? `${title} (${shortUrl})` : shortUrl;
|
|
1482
|
-
}
|
|
1483
|
-
}
|
|
1484
|
-
return undefined;
|
|
1485
|
-
}
|
|
1486
|
-
function summarizeDeep(value) {
|
|
1487
|
-
// Strings: summarize data URLs and trim extremely long strings
|
|
1488
|
-
if (typeof value === "string") {
|
|
1489
|
-
if (value.startsWith("data:"))
|
|
1490
|
-
return formatDataUrlAsLabel(value);
|
|
1491
|
-
return value.length > 512 ? value.slice(0, 512) + "…" : value;
|
|
1492
|
-
}
|
|
1493
|
-
// Typed output wrapper
|
|
1494
|
-
if (isTypedOutput(value)) {
|
|
1495
|
-
return summarizeDeep(getTypedOutputValue(value));
|
|
1496
|
-
}
|
|
1497
|
-
// Arrays
|
|
1498
|
-
if (Array.isArray(value)) {
|
|
1499
|
-
return value.map((v) => summarizeDeep(v));
|
|
1500
|
-
}
|
|
1501
|
-
// Objects
|
|
1502
|
-
if (value && typeof value === "object") {
|
|
1503
|
-
const obj = value;
|
|
1504
|
-
const out = {};
|
|
1505
|
-
for (const [k, v] of Object.entries(obj)) {
|
|
1506
|
-
// Special-case any 'url' field
|
|
1507
|
-
if (typeof v === "string" &&
|
|
1508
|
-
k.toLowerCase() === "url" &&
|
|
1509
|
-
v.startsWith("data:")) {
|
|
1510
|
-
out[k] = formatDataUrlAsLabel(v);
|
|
1511
|
-
continue;
|
|
1512
|
-
}
|
|
1513
|
-
out[k] = summarizeDeep(v);
|
|
1514
|
-
}
|
|
1515
|
-
return out;
|
|
1516
|
-
}
|
|
1517
|
-
return value;
|
|
1518
|
-
}
|
|
1519
|
-
|
|
1520
|
-
// Shared UI constants for node layout to keep mapping and rendering in sync
|
|
1521
|
-
const NODE_HEADER_HEIGHT_PX = 24;
|
|
1522
|
-
const NODE_ROW_HEIGHT_PX = 22;
|
|
1523
|
-
|
|
1524
|
-
function computeEffectiveHandles(node, registry) {
|
|
1525
|
-
const desc = registry.nodes.get(node.typeId);
|
|
1526
|
-
const resolved = node.resolvedHandles || {};
|
|
1527
|
-
const inputs = { ...desc?.inputs, ...resolved.inputs };
|
|
1528
|
-
const outputs = { ...desc?.outputs, ...resolved.outputs };
|
|
1529
|
-
const inputDefaults = { ...desc?.inputDefaults, ...resolved.inputDefaults };
|
|
1530
|
-
return { inputs, outputs, inputDefaults };
|
|
1531
|
-
}
|
|
1532
|
-
function countVisibleHandles(handles) {
|
|
1533
|
-
const inputIds = Object.keys(handles.inputs).filter((k) => !isInputPrivate(handles.inputs, k));
|
|
1534
|
-
const outputIds = Object.keys(handles.outputs);
|
|
1535
|
-
return { inputsCount: inputIds.length, outputsCount: outputIds.length };
|
|
1536
|
-
}
|
|
1537
|
-
function estimateNodeSize(args) {
|
|
1538
|
-
const { node, registry, showValues, overrides } = args;
|
|
1539
|
-
const { inputs, outputs } = computeEffectiveHandles(node, registry);
|
|
1540
|
-
// Count only non-private inputs for rows on left
|
|
1541
|
-
const { inputsCount, outputsCount } = countVisibleHandles({
|
|
1542
|
-
inputs,
|
|
1543
|
-
outputs,
|
|
1544
|
-
});
|
|
1545
|
-
const rows = Math.max(inputsCount, outputsCount);
|
|
1546
|
-
const baseWidth = showValues ? 320 : 240;
|
|
1547
|
-
const width = overrides?.width ?? baseWidth;
|
|
1548
|
-
const height = overrides?.height ?? NODE_HEADER_HEIGHT_PX + rows * NODE_ROW_HEIGHT_PX;
|
|
1549
|
-
return { width, height, inputsCount, outputsCount, rowCount: rows };
|
|
1550
|
-
}
|
|
1551
|
-
function layoutNode(args) {
|
|
1552
|
-
const { node, registry, showValues, overrides } = args;
|
|
1553
|
-
const { inputs, outputs } = computeEffectiveHandles(node, registry);
|
|
1554
|
-
const inputOrder = Object.keys(inputs).filter((k) => !isInputPrivate(inputs, k));
|
|
1555
|
-
const outputOrder = Object.keys(outputs);
|
|
1556
|
-
const { width, height } = estimateNodeSize({
|
|
1557
|
-
node,
|
|
1558
|
-
registry,
|
|
1559
|
-
showValues,
|
|
1560
|
-
overrides,
|
|
1561
|
-
});
|
|
1562
|
-
const HEADER = NODE_HEADER_HEIGHT_PX;
|
|
1563
|
-
const ROW = NODE_ROW_HEIGHT_PX;
|
|
1564
|
-
const handles = [
|
|
1565
|
-
...inputOrder.map((id, i) => ({
|
|
1566
|
-
id,
|
|
1567
|
-
type: "target",
|
|
1568
|
-
position: Position.Left,
|
|
1569
|
-
x: 0,
|
|
1570
|
-
y: HEADER + i * ROW,
|
|
1571
|
-
width: 1,
|
|
1572
|
-
height: ROW + 2,
|
|
1573
|
-
})),
|
|
1574
|
-
...outputOrder.map((id, i) => ({
|
|
1575
|
-
id,
|
|
1576
|
-
type: "source",
|
|
1577
|
-
position: Position.Right,
|
|
1578
|
-
x: width - 1,
|
|
1579
|
-
y: HEADER + i * ROW,
|
|
1580
|
-
width: 1,
|
|
1581
|
-
height: ROW + 2,
|
|
1582
|
-
})),
|
|
1583
|
-
];
|
|
1584
|
-
const handleLayout = [
|
|
1585
|
-
...inputOrder.map((id, i) => ({
|
|
1586
|
-
id,
|
|
1587
|
-
type: "target",
|
|
1588
|
-
position: Position.Left,
|
|
1589
|
-
y: HEADER + i * ROW + ROW / 2,
|
|
1590
|
-
})),
|
|
1591
|
-
...outputOrder.map((id, i) => ({
|
|
1592
|
-
id,
|
|
1593
|
-
type: "source",
|
|
1594
|
-
position: Position.Right,
|
|
1595
|
-
y: HEADER + i * ROW + ROW / 2,
|
|
1596
|
-
})),
|
|
1597
|
-
];
|
|
1598
|
-
return { width, height, inputOrder, outputOrder, handles, handleLayout };
|
|
1599
|
-
}
|
|
1600
|
-
|
|
1601
1593
|
function toReactFlow(def, positions, registry, opts) {
|
|
1602
1594
|
const EDGE_STYLE_MISSING = { stroke: "#f59e0b", strokeWidth: 2 }; // amber-500
|
|
1603
1595
|
const EDGE_STYLE_ERROR = { stroke: "#ef4444", strokeWidth: 2 };
|